diff --git a/app/src/main/java/com/trianguloy/urlchecker/modules/list/OpenModule.java b/app/src/main/java/com/trianguloy/urlchecker/modules/list/OpenModule.java index 1fcafec..600d1d0 100644 --- a/app/src/main/java/com/trianguloy/urlchecker/modules/list/OpenModule.java +++ b/app/src/main/java/com/trianguloy/urlchecker/modules/list/OpenModule.java @@ -24,6 +24,7 @@ import com.trianguloy.urlchecker.utilities.generics.GenericPref; import com.trianguloy.urlchecker.utilities.methods.AndroidUtils; import com.trianguloy.urlchecker.utilities.methods.PackageUtils; import com.trianguloy.urlchecker.utilities.methods.UrlUtils; +import com.trianguloy.urlchecker.utilities.wrappers.RejectionDetector; import java.util.List; @@ -75,15 +76,16 @@ public class OpenModule extends AModuleData { class OpenDialog extends AModuleDialog { - private LastOpened lastOpened; - private final GenericPref.Bool closeOpenPref; private final GenericPref.Bool closeSharePref; private final GenericPref.Bool closeCopyPref; private final GenericPref.Bool noReferrerPref; private final GenericPref.Bool mergeCopyPref; + + private final LastOpened lastOpened; private final CTabs cTabs; private final Incognito incognito; + private final RejectionDetector rejectionDetector; private List packages; private Button btn_open; @@ -94,8 +96,10 @@ class OpenDialog extends AModuleDialog { public OpenDialog(MainDialog dialog) { super(dialog); + lastOpened = new LastOpened(dialog); cTabs = new CTabs(dialog); incognito = new Incognito(dialog); + rejectionDetector = new RejectionDetector(dialog); closeOpenPref = OpenModule.CLOSEOPEN_PREF(dialog); closeSharePref = OpenModule.CLOSESHARE_PREF(dialog); closeCopyPref = OpenModule.CLOSECOPY_PREF(dialog); @@ -152,9 +156,6 @@ class OpenDialog extends AModuleDialog { return false; }); menu = popup.getMenu(); - - // init lastOpened utility - lastOpened = new LastOpened(getActivity()); } @Override @@ -175,6 +176,10 @@ class OpenDialog extends AModuleDialog { packages.remove(AndroidUtils.getReferrer(getActivity())); } + // remove rejected + // note: this will be called each time, so a rejected package will not be rejected again if the user changes the url and goes back. This is expected + packages.remove(rejectionDetector.getPrevious(url)); + // check no apps if (packages.isEmpty()) { btn_open.setText(R.string.mOpen_noapps); @@ -213,13 +218,13 @@ class OpenDialog extends AModuleDialog { private void openUrl(int index) { // get if (index < 0 || index >= packages.size()) return; - String chosen = packages.get(index); + var chosen = packages.get(index); // update as preferred over the rest lastOpened.prefer(chosen, packages, getUrl()); // open - Intent intent = new Intent(getActivity().getIntent()); + var intent = new Intent(getActivity().getIntent()); if (Intent.ACTION_VIEW.equals(intent.getAction())) { // preserve original VIEW intent intent.setData(Uri.parse(getUrl())); @@ -237,13 +242,18 @@ class OpenDialog extends AModuleDialog { incognito.apply(intent); // Get flags from global data (probably set by flags module, if active) - Integer flags = Flags.getGlobalFlagsNullable(this); + var flags = Flags.getGlobalFlagsNullable(this); if (flags != null) { intent.setFlags(flags); } + // rejection detector: mark as open + rejectionDetector.markAsOpen(getUrl(), chosen); + + // open PackageUtils.startActivity(intent, R.string.toast_noApp, getActivity()); + // finish activity if (closeOpenPref.get()) { this.getActivity().finish(); } diff --git a/app/src/main/java/com/trianguloy/urlchecker/utilities/generics/GenericPref.java b/app/src/main/java/com/trianguloy/urlchecker/utilities/generics/GenericPref.java index 13f075e..151cf94 100644 --- a/app/src/main/java/com/trianguloy/urlchecker/utilities/generics/GenericPref.java +++ b/app/src/main/java/com/trianguloy/urlchecker/utilities/generics/GenericPref.java @@ -238,15 +238,23 @@ public abstract class GenericPref { /** - * A list of strings preference + * A list of strings preference. + * Saved as string concatenated with separator + * Optionally limit the number of entries */ static public class LstStr extends GenericPref> { final String separator; + final int limit; public LstStr(String prefName, String separator, List defaultValue, Context cntx) { + this(prefName, separator, 0, defaultValue, cntx); + } + + public LstStr(String prefName, String separator, int limit, List defaultValue, Context cntx) { super(prefName, defaultValue, cntx); this.separator = separator; + this.limit = limit; } @Override @@ -270,7 +278,7 @@ public abstract class GenericPref { private List split(String value) { ArrayList list = new ArrayList<>(); - if (value != null) list.addAll(Arrays.asList(value.split(separator))); + if (value != null) list.addAll(Arrays.asList(value.split(separator, limit))); return list; } } diff --git a/app/src/main/java/com/trianguloy/urlchecker/utilities/wrappers/RejectionDetector.java b/app/src/main/java/com/trianguloy/urlchecker/utilities/wrappers/RejectionDetector.java new file mode 100644 index 0000000..affc9dc --- /dev/null +++ b/app/src/main/java/com/trianguloy/urlchecker/utilities/wrappers/RejectionDetector.java @@ -0,0 +1,49 @@ +package com.trianguloy.urlchecker.utilities.wrappers; + +import android.content.Context; + +import com.trianguloy.urlchecker.utilities.generics.GenericPref; + +import java.util.Collections; +import java.util.List; +import java.util.Objects; + +/** + * Saves the package and time of the last opened url. + * If it is requested again in a short amount of time, that package is considered to 'reject' the url and is hidden. + */ +public class RejectionDetector { + + private static final int TIMEFRAME = 5000; + private final GenericPref.LstStr rejectLast; // [openedTimeMillis, package, url] + + public RejectionDetector(Context cntx) { + rejectLast = new GenericPref.LstStr("reject_last", "\n", 3, Collections.emptyList(), cntx); + } + + /** + * Marks a url as opened to a package (at this moment) + */ + public void markAsOpen(String url, String packageName) { + rejectLast.set(List.of(Long.toString(System.currentTimeMillis()), packageName, url)); + } + + /** + * returns the last package that opened the url if it happened in a short amount of time, null otherwise + */ + public String getPrevious(String url) { + try { + var data = rejectLast.get(); + + // return the saved package if the time is less than the timeframe and the url is the same + return !data.isEmpty() + && System.currentTimeMillis() - Long.parseLong(data.get(0)) < TIMEFRAME + && Objects.equals(data.get(2), url) + ? data.get(1) + : null; + } catch (Exception ignore) { + // just ignore errors while retrieving the data + return null; + } + } +}