From 285d2e60bbe692958165b72a0b54ac0d27575620 Mon Sep 17 00:00:00 2001 From: Grigory Kruglov Date: Wed, 12 Jul 2017 17:58:45 -0400 Subject: [PATCH] Bug 1377286 - Allow pinning items to Activity Stream from other home panels r=sebastian Menu item to pin/unpin items from Bookmarks and History panels is only displayed when Activity Stream is enabled. MozReview-Commit-ID: Ko3xmpF2R53 --HG-- extra : rebase_source : 4eefb81224c1cc00ba2eb6147e26119af647d317 --- .../src/main/res/menu/home_contextmenu.xml | 3 + .../gecko/home/HomeContextMenuInfo.java | 7 ++ .../org/mozilla/gecko/home/HomeFragment.java | 96 ++++++++++++++++++- .../base/locales/en-US/android_strings.dtd | 5 + mobile/android/base/strings.xml.in | 3 + 5 files changed, 113 insertions(+), 1 deletion(-) diff --git a/mobile/android/app/src/main/res/menu/home_contextmenu.xml b/mobile/android/app/src/main/res/menu/home_contextmenu.xml index ed03f46b47e2..ab3a6bb1124c 100644 --- a/mobile/android/app/src/main/res/menu/home_contextmenu.xml +++ b/mobile/android/app/src/main/res/menu/home_contextmenu.xml @@ -32,6 +32,9 @@ + + diff --git a/mobile/android/base/java/org/mozilla/gecko/home/HomeContextMenuInfo.java b/mobile/android/base/java/org/mozilla/gecko/home/HomeContextMenuInfo.java index d47033e89f71..0a43365c68f9 100644 --- a/mobile/android/base/java/org/mozilla/gecko/home/HomeContextMenuInfo.java +++ b/mobile/android/base/java/org/mozilla/gecko/home/HomeContextMenuInfo.java @@ -9,6 +9,7 @@ import org.mozilla.gecko.db.BrowserContract; import org.mozilla.gecko.util.StringUtils; import android.database.Cursor; +import android.support.annotation.Nullable; import android.text.TextUtils; import android.view.View; import android.widget.AdapterView.AdapterContextMenuInfo; @@ -27,6 +28,8 @@ public class HomeContextMenuInfo extends AdapterContextMenuInfo { public int bookmarkId = -1; public RemoveItemType itemType = null; + /* package-private */ @Nullable Boolean isAsPinned; + // Item type to be handled with "Remove" selection. /* package-private */ enum RemoveItemType { BOOKMARKS, COMBINED, HISTORY @@ -55,6 +58,10 @@ public class HomeContextMenuInfo extends AdapterContextMenuInfo { return hasBookmarkId() || hasHistoryId() || hasPartnerBookmarkId(); } + /* package-private */ void updateAsPinned(boolean pinnedState) { + isAsPinned = pinnedState; + } + private boolean hasHistoryId() { return historyId > -1; } diff --git a/mobile/android/base/java/org/mozilla/gecko/home/HomeFragment.java b/mobile/android/base/java/org/mozilla/gecko/home/HomeFragment.java index 651baa9c1622..728eccfe525f 100644 --- a/mobile/android/base/java/org/mozilla/gecko/home/HomeFragment.java +++ b/mobile/android/base/java/org/mozilla/gecko/home/HomeFragment.java @@ -16,6 +16,7 @@ import org.mozilla.gecko.R; import org.mozilla.gecko.SnackbarBuilder; import org.mozilla.gecko.Telemetry; import org.mozilla.gecko.TelemetryContract; +import org.mozilla.gecko.activitystream.ActivityStream; import org.mozilla.gecko.bookmarks.BookmarkUtils; import org.mozilla.gecko.db.BrowserDB; import org.mozilla.gecko.db.BrowserContract.SuggestedSites; @@ -162,7 +163,7 @@ public abstract class HomeFragment extends Fragment { return; } - HomeContextMenuInfo info = (HomeContextMenuInfo) menuInfo; + final HomeContextMenuInfo info = (HomeContextMenuInfo) menuInfo; // Don't show the context menu for folders if full bookmark management isn't enabled. final boolean enableFullBookmarkManagement = BookmarkUtils.isEnabled(getContext()); @@ -209,7 +210,41 @@ public abstract class HomeFragment extends Fragment { menu.findItem(R.id.home_share).setVisible(false); menu.findItem(R.id.home_add_to_launcher).setVisible(false); menu.findItem(R.id.home_set_as_homepage).setVisible(false); + + menu.findItem(R.id.home_as_pin).setVisible(false); + return; } + + // If Activity Stream is disabled, simply hide "AS Pin" menu item as classic Top Sites do not + // support pinning from outside of the Top Site tiles. + if (!ActivityStream.isEnabled(getContext())) { + menu.findItem(R.id.home_as_pin).setVisible(false); + return; + } + + // Asynchronously update pin state for this item. + // This code should be superseded by context menu unification work in Bug 1377292. + final MenuItem asPinItem = menu.findItem(R.id.home_as_pin); + // Do not let user interact with this menu item before we figure out pinned state. + asPinItem.setEnabled(false); + + (new UIAsyncTask.WithoutParams(ThreadUtils.getBackgroundHandler()) { + @Override + protected Boolean doInBackground() { + return BrowserDB.from(getContext()).isPinnedForAS( + getContext().getContentResolver(), info.url); + } + + @Override + protected void onPostExecute(Boolean hasPin) { + if (hasPin) { + asPinItem.setTitle(R.string.contextmenu_top_sites_unpin); + } + + info.updateAsPinned(hasPin); + asPinItem.setEnabled(true); + } + }).execute(); } @Override @@ -327,6 +362,12 @@ public abstract class HomeFragment extends Fragment { getResources().getResourceEntryName(itemId)); return true; } + + if (itemId == R.id.home_as_pin) { + new ToggleASPinTask(getActivity(), info).execute(); + return true; + } + return false; } @@ -399,6 +440,59 @@ public abstract class HomeFragment extends Fragment { mIsLoaded = true; } + private static class ToggleASPinTask extends UIAsyncTask.WithoutParams { + private final WeakReference activityWeakReference; + private final Context context; + private final HomeContextMenuInfo info; + private final BrowserDB db; + private final ContentResolver cr; + private final boolean toggleWillPin; + + ToggleASPinTask(Activity activity, HomeContextMenuInfo info) { + super(ThreadUtils.getBackgroundHandler()); + + this.activityWeakReference = new WeakReference(activity); + this.context = activity.getApplicationContext(); + this.db = BrowserDB.from(context); + this.info = info; + this.cr = context.getContentResolver(); + + if (info.isAsPinned == null) { + throw new IllegalStateException("Tried changing pinned state before it's determined."); + } + + this.toggleWillPin = !info.isAsPinned; + } + + @Override + protected Void doInBackground() { + if (toggleWillPin) { + db.pinSiteForAS(cr, info.url, info.title); + } else { + db.unpinSiteForAS(cr, info.url); + } + return null; + } + + @Override + protected void onPostExecute(Void aVoid) { + final Activity activity = activityWeakReference.get(); + if (activity == null || activity.isFinishing()) { + return; + } + + int messageId = R.string.home_pinned_site; + if (!toggleWillPin) { + messageId = R.string.home_unpinned_site; + } + + SnackbarBuilder.builder(activity) + .message(messageId) + .duration(Snackbar.LENGTH_LONG) + .buildAndShow(); + } + } + static class RemoveItemTask extends UIAsyncTask.WithoutParams { private final WeakReference activityWeakReference; private final Context context; diff --git a/mobile/android/base/locales/en-US/android_strings.dtd b/mobile/android/base/locales/en-US/android_strings.dtd index f611835e0607..bb4b85c62fe3 100644 --- a/mobile/android/base/locales/en-US/android_strings.dtd +++ b/mobile/android/base/locales/en-US/android_strings.dtd @@ -625,6 +625,11 @@ the text of a button; we expect more than one device. --> + + + + diff --git a/mobile/android/base/strings.xml.in b/mobile/android/base/strings.xml.in index 5158b0126387..3a21963dee03 100644 --- a/mobile/android/base/strings.xml.in +++ b/mobile/android/base/strings.xml.in @@ -481,6 +481,9 @@ &home_remote_tabs_unhide_selected_devices; &pin_site_dialog_hint; + &home_pinned_site; + &home_unpinned_site; + &remote_tabs_never_synced; &filepicker_title;