Bug 1398834: Add Pin to Top Sites page menu item. r=liuche draft
authorMichael Comella <michael.l.comella@gmail.com>
Tue, 12 Sep 2017 15:31:15 -0700
changeset 663419 44c9cd398c60e9fed9b2d25a8e761872e748fc92
parent 663418 bfe0ee95d6731bf920566fde093160f5d122d6dc
child 663420 7095891695d70bae4d20d7f1d37742e3bf518113
push id79432
push usermichael.l.comella@gmail.com
push dateWed, 13 Sep 2017 00:03:43 +0000
reviewersliuche
bugs1398834
milestone57.0a1
Bug 1398834: Add Pin to Top Sites page menu item. r=liuche MozReview-Commit-ID: 3YK2V7zrUDC
mobile/android/app/src/main/res/menu/browser_app_menu.xml
mobile/android/base/java/org/mozilla/gecko/BrowserApp.java
--- a/mobile/android/app/src/main/res/menu/browser_app_menu.xml
+++ b/mobile/android/app/src/main/res/menu/browser_app_menu.xml
@@ -69,16 +69,20 @@
                   android:title="@string/save_as_pdf"/>
 
             <item android:id="@+id/print"
                   android:title="@string/print"/>
 
             <item android:id="@+id/add_search_engine"
                   android:title="@string/contextmenu_add_search_engine"/>
 
+            <!-- Title is overridden dynamically (it can also be for unpinning). -->
+            <item android:id="@+id/pin_to_top_sites"
+                  android:title="@string/contextmenu_pin_to_top_sites"/>
+
             <item android:id="@+id/add_to_launcher"
                   android:title="@string/contextmenu_add_to_launcher"/>
 
             <item android:id="@+id/set_as_homepage"
                   android:title="@string/contextmenu_set_as_homepage"/>
 
         </menu>
 
--- a/mobile/android/base/java/org/mozilla/gecko/BrowserApp.java
+++ b/mobile/android/base/java/org/mozilla/gecko/BrowserApp.java
@@ -33,16 +33,17 @@ import android.nfc.NdefRecord;
 import android.nfc.NfcAdapter;
 import android.nfc.NfcEvent;
 import android.os.Build;
 import android.os.Bundle;
 import android.os.Environment;
 import android.os.StrictMode;
 import android.support.annotation.NonNull;
 import android.support.annotation.Nullable;
+import android.support.annotation.StringRes;
 import android.support.annotation.UiThread;
 import android.support.design.widget.Snackbar;
 import android.support.v4.app.Fragment;
 import android.support.v4.app.FragmentManager;
 import android.support.v4.app.NotificationCompat;
 import android.support.v4.content.res.ResourcesCompat;
 import android.support.v4.view.MenuItemCompat;
 import android.text.TextUtils;
@@ -1447,16 +1448,44 @@ public class BrowserApp extends GeckoApp
                 if (url != null) {
                     Clipboard.setText(url);
                     Telemetry.sendUIEvent(TelemetryContract.Event.ACTION, TelemetryContract.Method.CONTEXT_MENU, "copyurl");
                 }
             }
             return true;
         }
 
+        if (itemId == R.id.pin_to_top_sites) {
+            final Tab selectedTab = Tabs.getInstance().getSelectedTab();
+            if (selectedTab != null) {
+                ThreadUtils.postToBackgroundThread(new Runnable() {
+                    @Override
+                    public void run() {
+                        final BrowserDB db = BrowserDB.from(BrowserApp.this);
+                        final ContentResolver cr = getContentResolver();
+                        final String url = selectedTab.getURL();
+
+                        final @StringRes int snackbarText;
+                        if (!db.isPinnedForAS(cr, url)) {
+                            db.pinSiteForAS(getContentResolver(), url, selectedTab.getTitle());
+                            snackbarText = R.string.pinned_page_to_top_sites;
+                        } else {
+                            db.unpinSiteForAS(getContentResolver(), url);
+                            snackbarText = R.string.unpinned_page_from_top_sites;
+                        }
+
+                        SnackbarBuilder.builder(BrowserApp.this)
+                                .message(snackbarText)
+                                .buildAndShow();
+                    }
+                });
+            }
+            return true;
+        }
+
         if (itemId == R.id.add_to_launcher) {
             final Tab tab = Tabs.getInstance().getSelectedTab();
             if (tab == null) {
                 return true;
             }
 
             final String url = tab.getURL();
             final String title = tab.getDisplayTitle();
@@ -3525,19 +3554,26 @@ public class BrowserApp extends GeckoApp
             print.setEnabled(false);
             findInPage.setEnabled(false);
 
             // NOTE: Use MenuUtils.safeSetEnabled because some actions might
             // be on the BrowserToolbar context menu.
             MenuUtils.safeSetEnabled(aMenu, R.id.page, false);
             MenuUtils.safeSetEnabled(aMenu, R.id.subscribe, false);
             MenuUtils.safeSetEnabled(aMenu, R.id.add_search_engine, false);
+            MenuUtils.safeSetEnabled(aMenu, R.id.pin_to_top_sites, false);
             MenuUtils.safeSetEnabled(aMenu, R.id.add_to_launcher, false);
             MenuUtils.safeSetEnabled(aMenu, R.id.set_as_homepage, false);
 
+            final MenuItem pinToTopSitesItem = aMenu.findItem(R.id.pin_to_top_sites);
+            if (pinToTopSitesItem != null) {
+                // This title is set dynamically so we reset it for this edge case.
+                pinToTopSitesItem.setTitle(R.string.contextmenu_pin_to_top_sites);
+            }
+
             return true;
         }
 
         // If tab data IS available we need to manually enable items as necessary. They may have
         // been disabled if returning early above, hence every item must be toggled, even if it's
         // always expected to be enabled (e.g. the bookmark star is always enabled, except when
         // we don't have tab data).
 
@@ -3608,16 +3644,17 @@ public class BrowserApp extends GeckoApp
 
         // NOTE: Use MenuUtils.safeSetEnabled because some actions might
         // be on the BrowserToolbar context menu.
         MenuUtils.safeSetEnabled(aMenu, R.id.page, !isAboutHome(tab));
         MenuUtils.safeSetEnabled(aMenu, R.id.subscribe, tab.hasFeeds());
         MenuUtils.safeSetEnabled(aMenu, R.id.add_search_engine, tab.hasOpenSearch());
         MenuUtils.safeSetEnabled(aMenu, R.id.add_to_launcher, !isAboutHome(tab));
         MenuUtils.safeSetEnabled(aMenu, R.id.set_as_homepage, !isAboutHome(tab));
+        onPrepareOptionsMenuPinToTopSites(aMenu, tab);
 
         // This provider also applies to the quick share menu item.
         final GeckoActionProvider provider = ((GeckoMenuItem) share).getGeckoActionProvider();
         if (provider != null) {
             Intent shareIntent = provider.getIntent();
 
             // For efficiency, the provider's intent is only set once
             if (shareIntent == null) {
@@ -3708,16 +3745,42 @@ public class BrowserApp extends GeckoApp
         // Hide panel menu items if the panels themselves are hidden.
         // If we don't know whether the panels are hidden, just show the menu items.
         bookmarksList.setVisible(prefs.getBoolean(HomeConfig.PREF_KEY_BOOKMARKS_PANEL_ENABLED, true));
         historyList.setVisible(prefs.getBoolean(HomeConfig.PREF_KEY_HISTORY_PANEL_ENABLED, true));
 
         return true;
     }
 
+    private void onPrepareOptionsMenuPinToTopSites(final Menu aMenu, final Tab tab) {
+        final MenuItem item = aMenu.findItem(R.id.pin_to_top_sites);
+        if (item == null) {
+            return;
+        }
+
+        // Set initial state before async query completes.
+        item.setEnabled(false); // Disable interaction.
+        item.setTitle(R.string.contextmenu_pin_to_top_sites);
+
+        ThreadUtils.postToBackgroundThread(new Runnable() {
+            @Override
+            public void run() {
+                final boolean isPinned = BrowserDB.from(BrowserApp.this).isPinnedForAS(getContentResolver(), tab.getURL());
+                ThreadUtils.postToUiThread(new Runnable() {
+                    @Override
+                    public void run() {
+                        item.setTitle(isPinned ?
+                                R.string.contextmenu_unpin_from_top_sites : R.string.contextmenu_pin_to_top_sites);
+                        item.setEnabled(true);
+                    }
+                });
+            }
+        });
+    }
+
     private Drawable resolveBookmarkIconDrawable(final boolean isBookmark, final int tint) {
         if (isBookmark) {
             return ResourcesCompat.getDrawable(getResources(), R.drawable.star_blue, null);
         } else {
             return DrawableUtil.tintDrawable(this, R.drawable.ic_menu_bookmark_add, tint);
         }
     }