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);