Bug 1393672 - Add a badge (at the same position of Page Actio) for PWA. r?jwu draft
authorNevin Chen(:nechen) <cnevinchen@gmail.com>
Tue, 26 Sep 2017 13:48:09 +0800
changeset 679175 cb40c7c037114a7a2a10d09b0e57e7adbfd5ac29
parent 678457 a72bd6160609be2fa471be5f87955bdd47fafe22
child 679176 f0b0000a095904662fefdf779846b7890c75b790
child 679406 bdf79dee093c793c15ff9cdd9d3eda4e69d8efb5
child 680413 f474cb4e9f8be2515ae83bdfbdfa172f1ea3c096
push id84142
push userbmo:cnevinchen@gmail.com
push dateThu, 12 Oct 2017 11:15:06 +0000
reviewersjwu
bugs1393672
milestone58.0a1
Bug 1393672 - Add a badge (at the same position of Page Actio) for PWA. r?jwu This bug is for the front end work to make users more engaged with PWA. Requirements 1. When the user goes to a web page that has manifest.json, we show a badge(in the same position of page action). 2. If the user switch to another normal page or other Java UI, the page action should be gone. 3. When the user see the PWA website for the first time, we will display a onboarding prompt to teach him how to add PWA to home screen. This prompt only shows once. MozReview-Commit-ID: AcyjHPVKg2b
mobile/android/base/java/org/mozilla/gecko/GeckoApplication.java
mobile/android/base/java/org/mozilla/gecko/Tab.java
mobile/android/base/java/org/mozilla/gecko/Tabs.java
mobile/android/base/java/org/mozilla/gecko/toolbar/PageActionLayout.java
--- a/mobile/android/base/java/org/mozilla/gecko/GeckoApplication.java
+++ b/mobile/android/base/java/org/mozilla/gecko/GeckoApplication.java
@@ -491,16 +491,23 @@ public class GeckoApplication extends Ap
     public LightweightTheme getLightweightTheme() {
         return mLightweightTheme;
     }
 
     public void prepareLightweightTheme() {
         mLightweightTheme = new LightweightTheme(this);
     }
 
+    public static void createShortcut() {
+        final Tab selectedTab = Tabs.getInstance().getSelectedTab();
+        if (selectedTab != null) {
+            createShortcut(selectedTab.getTitle(), selectedTab.getURL());
+        }
+    }
+
     // Creates a homescreen shortcut for a web page.
     // This is the entry point from nsIShellService.
     @WrapForJNI(calledFrom = "gecko")
     public static void createShortcut(final String title, final String url) {
         final Tab selectedTab = Tabs.getInstance().getSelectedTab();
         final String manifestUrl = selectedTab.getManifestUrl();
 
         if (manifestUrl != null) {
--- a/mobile/android/base/java/org/mozilla/gecko/Tab.java
+++ b/mobile/android/base/java/org/mozilla/gecko/Tab.java
@@ -18,16 +18,17 @@ import org.mozilla.gecko.gfx.BitmapUtils
 import org.mozilla.gecko.icons.IconCallback;
 import org.mozilla.gecko.icons.IconDescriptor;
 import org.mozilla.gecko.icons.IconRequestBuilder;
 import org.mozilla.gecko.icons.IconResponse;
 import org.mozilla.gecko.icons.Icons;
 import org.mozilla.gecko.reader.ReaderModeUtils;
 import org.mozilla.gecko.reader.ReadingListHelper;
 import org.mozilla.gecko.toolbar.BrowserToolbar.TabEditingState;
+import org.mozilla.gecko.toolbar.PageActionLayout;
 import org.mozilla.gecko.util.GeckoBundle;
 import org.mozilla.gecko.util.ThreadUtils;
 import org.mozilla.gecko.widget.SiteLogins;
 
 import android.content.ContentResolver;
 import android.content.Context;
 import android.graphics.Bitmap;
 import android.graphics.drawable.BitmapDrawable;
@@ -458,16 +459,26 @@ public class Tab {
     }
 
     public void setHasFeeds(boolean hasFeeds) {
         mHasFeeds = hasFeeds;
     }
 
     public void setManifestUrl(String manifestUrl) {
         mManifestUrl = manifestUrl;
+        updatePageAction();
+    }
+
+    public void updatePageAction() {
+        if (mManifestUrl != null) {
+            PageActionLayout.PageAction.showPwaPageAction();
+
+        } else {
+            PageActionLayout.PageAction.clearPwaPageAction();
+        }
     }
 
     public void setHasOpenSearch(boolean hasOpenSearch) {
         mHasOpenSearch = hasOpenSearch;
     }
 
     public void setLoadedFromCache(boolean loadedFromCache) {
         mLoadedFromCache = loadedFromCache;
--- a/mobile/android/base/java/org/mozilla/gecko/Tabs.java
+++ b/mobile/android/base/java/org/mozilla/gecko/Tabs.java
@@ -305,16 +305,18 @@ public class Tabs implements BundleEvent
 
         // This avoids a NPE below, but callers need to be careful to
         // handle this case.
         if (tab == null || oldTab == tab) {
             return tab;
         }
 
         mSelectedTab = tab;
+        mSelectedTab.updatePageAction();
+
         notifyListeners(tab, TabEvents.SELECTED);
 
         if (mLayerView != null) {
             mLayerView.setClearColor(getTabColor(tab));
         }
 
         if (oldTab != null) {
             notifyListeners(oldTab, TabEvents.UNSELECTED);
--- a/mobile/android/base/java/org/mozilla/gecko/toolbar/PageActionLayout.java
+++ b/mobile/android/base/java/org/mozilla/gecko/toolbar/PageActionLayout.java
@@ -1,16 +1,17 @@
 /* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 package org.mozilla.gecko.toolbar;
 
 import org.mozilla.gecko.EventDispatcher;
+import org.mozilla.gecko.GeckoApplication;
 import org.mozilla.gecko.R;
 import org.mozilla.gecko.util.DrawableUtil;
 import org.mozilla.gecko.util.ResourceDrawableUtils;
 import org.mozilla.gecko.util.BundleEventListener;
 import org.mozilla.gecko.util.EventCallback;
 import org.mozilla.gecko.util.GeckoBundle;
 import org.mozilla.gecko.util.ThreadUtils;
 import org.mozilla.gecko.widget.GeckoPopupMenu;
@@ -103,24 +104,33 @@ public class PageActionLayout extends Th
 
     @Override // BundleEventListener
     public void handleMessage(final String event, final GeckoBundle message,
                               final EventCallback callback) {
         ThreadUtils.assertOnUiThread();
 
         if ("PageActions:Add".equals(event)) {
             final String id = message.getString("id");
+
+            boolean alreadyAdded = isPwaAdded(id);
+            if (alreadyAdded) {
+                return;
+            }
             final String title = message.getString("title");
             final String imageURL = message.getString("icon");
             final boolean important = message.getBoolean("important");
             final boolean useTint = message.getBoolean("useTint");
 
             addPageAction(id, title, imageURL, useTint, new OnPageActionClickListeners() {
                 @Override
                 public void onClick(final String id) {
+                    if (id != null && id.equals(PageAction.UUID_PAGE_ACTION_PWA)) {
+                        GeckoApplication.createShortcut();
+                        return;
+                    }
                     final GeckoBundle data = new GeckoBundle(1);
                     data.putString("id", id);
                     EventDispatcher.getInstance().dispatch("PageActions:Clicked", data);
                 }
 
                 @Override
                 public boolean onLongClick(String id) {
                     final GeckoBundle data = new GeckoBundle(1);
@@ -130,16 +140,25 @@ public class PageActionLayout extends Th
                 }
             }, important);
 
         } else if ("PageActions:Remove".equals(event)) {
             removePageAction(message.getString("id"));
         }
     }
 
+    private boolean isPwaAdded(String id) {
+        for (PageAction pageAction : mPageActionList) {
+            if (pageAction.getID() != null && pageAction.getID().equals(id)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
     private void addPageAction(final String id, final String title, final String imageData, final boolean useTint,
             final OnPageActionClickListeners onPageActionClickListeners, boolean important) {
         ThreadUtils.assertOnUiThread();
 
         final PageAction pageAction = new PageAction(id, title, null, onPageActionClickListeners, important);
 
         int insertAt = mPageActionList.size();
         while (insertAt > 0 && mPageActionList.get(insertAt - 1).isImportant()) {
@@ -323,17 +342,19 @@ public class PageActionLayout extends Th
         mPageActionsMenu.show();
     }
 
     private static interface OnPageActionClickListeners {
         public void onClick(String id);
         public boolean onLongClick(String id);
     }
 
-    private static class PageAction {
+    public static class PageAction {
+        public static final String UUID_PAGE_ACTION_PWA = "279c269d-6397-4f86-a6d2-452e26456d4a";
+
         private final OnPageActionClickListeners mOnPageActionClickListeners;
         private Drawable mDrawable;
         private final String mTitle;
         private final String mId;
         private final int key;
         private final boolean mImportant;
 
         public PageAction(String id,
@@ -345,16 +366,25 @@ public class PageActionLayout extends Th
             mTitle = title;
             mDrawable = image;
             mOnPageActionClickListeners = onPageActionClickListeners;
             mImportant = important;
 
             key = UUID.fromString(mId.subSequence(1, mId.length() - 2).toString()).hashCode();
         }
 
+        public static void showPwaPageAction() {
+            GeckoBundle bundle = new GeckoBundle();
+            bundle.putString("id", UUID_PAGE_ACTION_PWA);
+            bundle.putString("title", "Add PWA Shortcut");
+            bundle.putString("icon", "drawable://icon_openinapp");
+            bundle.putBoolean("important", true);
+            EventDispatcher.getInstance().dispatch("PageActions:Add", bundle);
+        }
+
         public Drawable getDrawable() {
             return mDrawable;
         }
 
         public void setDrawable(Drawable d) {
             mDrawable = d;
         }
 
@@ -381,10 +411,16 @@ public class PageActionLayout extends Th
         }
 
         public boolean onLongClick() {
             if (mOnPageActionClickListeners != null) {
                 return mOnPageActionClickListeners.onLongClick(mId);
             }
             return false;
         }
+
+        public static void clearPwaPageAction() {
+            GeckoBundle bundle = new GeckoBundle();
+            bundle.putString("id", UUID_PAGE_ACTION_PWA);
+            EventDispatcher.getInstance().dispatch("PageActions:Remove", bundle);
+        }
     }
 }