diff --git a/Clover/app/src/main/java/org/floens/chan/core/presenter/ThreadPresenter.java b/Clover/app/src/main/java/org/floens/chan/core/presenter/ThreadPresenter.java index 9130cb30..19ad16b3 100644 --- a/Clover/app/src/main/java/org/floens/chan/core/presenter/ThreadPresenter.java +++ b/Clover/app/src/main/java/org/floens/chan/core/presenter/ThreadPresenter.java @@ -68,6 +68,7 @@ public class ThreadPresenter implements ChanLoader.ChanLoaderCallback, PostAdapt private static final int POST_OPTION_SHARE = 10; private static final int POST_OPTION_HIGHLIGHT_TRIPCODE = 11; private static final int POST_OPTION_HIDE = 12; + private static final int POST_OPTION_OPEN_BROWSER = 13; private WatchManager watchManager; private DatabaseManager databaseManager; @@ -362,6 +363,7 @@ public class ThreadPresenter implements ChanLoader.ChanLoaderCallback, PostAdapt menu.add(new FloatingMenuItem(POST_OPTION_INFO, R.string.post_info)); menu.add(new FloatingMenuItem(POST_OPTION_LINKS, R.string.post_show_links)); + menu.add(new FloatingMenuItem(POST_OPTION_OPEN_BROWSER, R.string.action_open_browser)); menu.add(new FloatingMenuItem(POST_OPTION_SHARE, R.string.post_share)); menu.add(new FloatingMenuItem(POST_OPTION_COPY_TEXT, R.string.post_copy_text)); menu.add(new FloatingMenuItem(POST_OPTION_REPORT, R.string.post_report)); @@ -426,6 +428,13 @@ public class ThreadPresenter implements ChanLoader.ChanLoaderCallback, PostAdapt case POST_OPTION_PIN: watchManager.addPin(post); break; + case POST_OPTION_OPEN_BROWSER: + AndroidUtils.openLink( + post.isOP ? + ChanUrls.getThreadUrlDesktop(post.board, post.no) : + ChanUrls.getThreadUrlDesktop(post.board, loadable.no, post.no) + ); + break; case POST_OPTION_SHARE: AndroidUtils.shareLink( post.isOP ? diff --git a/Clover/app/src/main/java/org/floens/chan/ui/controller/BrowseController.java b/Clover/app/src/main/java/org/floens/chan/ui/controller/BrowseController.java index 65cedc97..34466d5c 100644 --- a/Clover/app/src/main/java/org/floens/chan/ui/controller/BrowseController.java +++ b/Clover/app/src/main/java/org/floens/chan/ui/controller/BrowseController.java @@ -52,6 +52,7 @@ public class BrowseController extends ThreadController implements ToolbarMenuIte private static final int SHARE_ID = 102; private static final int VIEW_MODE_ID = 103; private static final int ORDER_ID = 104; + private static final int OPEN_BROWSER_ID = 105; private PostCellInterface.PostViewMode postViewMode; private PostsFilter.Order order; @@ -94,6 +95,7 @@ public class BrowseController extends ThreadController implements ToolbarMenuIte postViewMode == PostCellInterface.PostViewMode.LIST ? R.string.action_switch_catalog : R.string.action_switch_board)); items.add(viewModeMenuItem); items.add(new FloatingMenuItem(ORDER_ID, context.getString(R.string.action_order))); + items.add(new FloatingMenuItem(OPEN_BROWSER_ID, context.getString(R.string.action_open_browser))); overflow.setSubMenu(new FloatingMenu(context, overflow.getView(), items)); } @@ -111,13 +113,21 @@ public class BrowseController extends ThreadController implements ToolbarMenuIte @Override public void onSubMenuItemClicked(ToolbarMenuItem parent, FloatingMenuItem item) { - switch ((Integer) item.getId()) { + Integer id = (Integer) item.getId(); + switch (id) { case SEARCH_ID: navigationController.showSearch(); break; case SHARE_ID: + case OPEN_BROWSER_ID: String link = ChanUrls.getCatalogUrlDesktop(threadLayout.getPresenter().getLoadable().board); - AndroidUtils.shareLink(link); + + if (id == SHARE_ID) { + AndroidUtils.shareLink(link); + } else { + AndroidUtils.openLink(link); + } + break; case VIEW_MODE_ID: if (postViewMode == PostCellInterface.PostViewMode.LIST) { diff --git a/Clover/app/src/main/java/org/floens/chan/ui/controller/ViewThreadController.java b/Clover/app/src/main/java/org/floens/chan/ui/controller/ViewThreadController.java index 6c8ea6e0..6f5725a5 100644 --- a/Clover/app/src/main/java/org/floens/chan/ui/controller/ViewThreadController.java +++ b/Clover/app/src/main/java/org/floens/chan/ui/controller/ViewThreadController.java @@ -45,6 +45,7 @@ public class ViewThreadController extends ThreadController implements ThreadLayo private static final int SHARE_ID = 103; private static final int UP_ID = 104; private static final int DOWN_ID = 105; + private static final int OPEN_BROWSER_ID = 106; private ToolbarMenuItem pinItem; private Loadable loadable; @@ -72,6 +73,7 @@ public class ViewThreadController extends ThreadController implements ThreadLayo navigationItem.createOverflow(context, this, Arrays.asList( new FloatingMenuItem(REFRESH_ID, context.getString(R.string.action_reload)), new FloatingMenuItem(SEARCH_ID, context.getString(R.string.action_search)), + new FloatingMenuItem(OPEN_BROWSER_ID, context.getString(R.string.action_open_browser)), new FloatingMenuItem(SHARE_ID, context.getString(R.string.action_share)), new FloatingMenuItem(UP_ID, context.getString(R.string.action_up)), new FloatingMenuItem(DOWN_ID, context.getString(R.string.action_down)) @@ -163,7 +165,9 @@ public class ViewThreadController extends ThreadController implements ThreadLayo @Override public void onSubMenuItemClicked(ToolbarMenuItem parent, FloatingMenuItem item) { - switch ((Integer) item.getId()) { + Integer id = (Integer) item.getId(); + + switch (id) { case REFRESH_ID: threadLayout.getPresenter().requestData(); break; @@ -171,13 +175,20 @@ public class ViewThreadController extends ThreadController implements ThreadLayo navigationController.showSearch(); break; case SHARE_ID: + case OPEN_BROWSER_ID: Loadable loadable = threadLayout.getPresenter().getLoadable(); String link = ChanUrls.getThreadUrlDesktop(loadable.board, loadable.no); - AndroidUtils.shareLink(link); + + if (id == SHARE_ID) { + AndroidUtils.shareLink(link); + } else { + AndroidUtils.openLink(link); + } + break; case UP_ID: case DOWN_ID: - boolean up = ((Integer) item.getId()) == UP_ID; + boolean up = id == UP_ID; threadLayout.getPresenter().scrollTo(up ? 0 : -1, false); break; } diff --git a/Clover/app/src/main/java/org/floens/chan/utils/AndroidUtils.java b/Clover/app/src/main/java/org/floens/chan/utils/AndroidUtils.java index bb9ed5f4..432334f4 100644 --- a/Clover/app/src/main/java/org/floens/chan/utils/AndroidUtils.java +++ b/Clover/app/src/main/java/org/floens/chan/utils/AndroidUtils.java @@ -21,10 +21,13 @@ import android.annotation.SuppressLint; import android.annotation.TargetApi; import android.app.Activity; import android.app.Dialog; +import android.content.ComponentName; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.content.SharedPreferences; +import android.content.pm.PackageManager; +import android.content.pm.ResolveInfo; import android.content.res.Resources; import android.content.res.TypedArray; import android.graphics.Typeface; @@ -97,14 +100,41 @@ public class AndroidUtils { dialog.show(); } + /** + * Tries to open an app that can open the specified URL.
+ * If this app will open the link then show a chooser to the user without this app.
+ * Else allow the default logic to run with startActivity. + * @param link url to open + */ public static void openLink(String link) { + PackageManager pm = getAppRes().getPackageManager(); + Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(link)); - intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - if (intent.resolveActivity(getAppRes().getPackageManager()) != null) { - getAppRes().startActivity(intent); + ComponentName resolvedActivity = intent.resolveActivity(pm); + boolean thisAppIsDefault = resolvedActivity.getPackageName().equals(getAppRes().getPackageName()); + if (!thisAppIsDefault) { + openIntent(intent); } else { - Toast.makeText(getAppRes(), R.string.open_link_failed, Toast.LENGTH_LONG).show(); + // Get all intents that match, and filter out this app + List resolveInfos = pm.queryIntentActivities(intent, 0); + List filteredIntents = new ArrayList<>(resolveInfos.size()); + for (ResolveInfo info : resolveInfos) { + if (!info.activityInfo.packageName.equals(getAppRes().getPackageName())) { + Intent i = new Intent(Intent.ACTION_VIEW, Uri.parse(link)); + i.setPackage(info.activityInfo.packageName); + filteredIntents.add(i); + } + } + + if (filteredIntents.size() > 0) { + // Create a chooser for the last app in the list, and add the rest with EXTRA_INITIAL_INTENTS that get placed above + Intent chooser = Intent.createChooser(filteredIntents.remove(filteredIntents.size() - 1), null); + chooser.putExtra(Intent.EXTRA_INITIAL_INTENTS, filteredIntents.toArray(new Intent[filteredIntents.size()])); + openIntent(chooser); + } else { + openIntentFailed(); + } } } @@ -113,13 +143,7 @@ public class AndroidUtils { intent.setType("text/plain"); intent.putExtra(Intent.EXTRA_TEXT, link); Intent chooser = Intent.createChooser(intent, getRes().getString(R.string.action_share)); - chooser.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - - if (chooser.resolveActivity(getAppRes().getPackageManager()) != null) { - getAppRes().startActivity(chooser); - } else { - Toast.makeText(getAppRes(), R.string.open_link_failed, Toast.LENGTH_LONG).show(); - } + openIntent(chooser); } public static void openIntent(Intent intent) { @@ -127,10 +151,14 @@ public class AndroidUtils { if (intent.resolveActivity(getAppRes().getPackageManager()) != null) { getAppRes().startActivity(intent); } else { - Toast.makeText(getAppRes(), R.string.open_link_failed, Toast.LENGTH_LONG).show(); + openIntentFailed(); } } + private static void openIntentFailed() { + Toast.makeText(getAppRes(), R.string.open_link_failed, Toast.LENGTH_LONG).show(); + } + public static int getAttrColor(Context context, int attr) { TypedArray typedArray = context.getTheme().obtainStyledAttributes(new int[]{attr}); int color = typedArray.getColor(0, 0);