Bug 1246239 - Show "saved offline" snackbar when readermode page is bookmarked r?sebastian draft
authorAndrzej Hunt <ahunt@mozilla.com>
Tue, 12 Apr 2016 16:18:50 -0700
changeset 350159 0fd480526ad32b3be13d51976a5961fe715342b1
parent 350158 a2de4083a303b3bcc9bc3745b196e6cf0db5cc94
child 350237 f66b8a5ddcd9f0842c1012f17613a1bdf9a2a2ce
push id15264
push userahunt@mozilla.com
push dateTue, 12 Apr 2016 23:20:10 +0000
reviewerssebastian
bugs1246239
milestone48.0a1
Bug 1246239 - Show "saved offline" snackbar when readermode page is bookmarked r?sebastian MozReview-Commit-ID: IC33HwSClcI
mobile/android/base/java/org/mozilla/gecko/BrowserApp.java
mobile/android/base/java/org/mozilla/gecko/SnackbarHelper.java
mobile/android/base/locales/en-US/android_strings.dtd
mobile/android/base/resources/values/colors.xml
mobile/android/base/strings.xml.in
--- a/mobile/android/base/java/org/mozilla/gecko/BrowserApp.java
+++ b/mobile/android/base/java/org/mozilla/gecko/BrowserApp.java
@@ -2,16 +2,18 @@
  * 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;
 
 import android.Manifest;
 import android.app.DownloadManager;
+import android.graphics.Color;
+import android.graphics.drawable.Drawable;
 import android.os.Environment;
 import android.support.annotation.NonNull;
 import android.support.annotation.Nullable;
 import android.support.annotation.WorkerThread;
 import org.json.JSONArray;
 import org.mozilla.gecko.adjust.AdjustHelperInterface;
 import org.mozilla.gecko.annotation.RobocopTarget;
 import org.mozilla.gecko.AppConstants.Versions;
@@ -78,16 +80,17 @@ import org.mozilla.gecko.telemetry.Telem
 import org.mozilla.gecko.toolbar.AutocompleteHandler;
 import org.mozilla.gecko.toolbar.BrowserToolbar;
 import org.mozilla.gecko.toolbar.BrowserToolbar.TabEditingState;
 import org.mozilla.gecko.toolbar.ToolbarProgressView;
 import org.mozilla.gecko.trackingprotection.TrackingProtectionPrompt;
 import org.mozilla.gecko.updater.UpdateServiceHelper;
 import org.mozilla.gecko.util.ActivityUtils;
 import org.mozilla.gecko.util.Clipboard;
+import org.mozilla.gecko.util.DrawableUtil;
 import org.mozilla.gecko.util.EventCallback;
 import org.mozilla.gecko.util.Experiments;
 import org.mozilla.gecko.util.FloatUtils;
 import org.mozilla.gecko.util.GamepadUtils;
 import org.mozilla.gecko.util.GeckoEventListener;
 import org.mozilla.gecko.util.HardwareUtils;
 import org.mozilla.gecko.util.MenuUtils;
 import org.mozilla.gecko.util.NativeEventListener;
@@ -122,16 +125,17 @@ import android.nfc.NfcAdapter;
 import android.nfc.NfcEvent;
 import android.os.Build;
 import android.os.Bundle;
 import android.os.StrictMode;
 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.ContextCompat;
 import android.support.v4.view.MenuItemCompat;
 import android.text.TextUtils;
 import android.util.AttributeSet;
 import android.util.Base64;
 import android.util.Base64OutputStream;
 import android.util.Log;
 import android.view.InputDevice;
 import android.view.KeyEvent;
@@ -355,17 +359,25 @@ public class BrowserApp extends GeckoApp
                 if (Tabs.getInstance().isSelectedTab(tab)) {
                     invalidateOptionsMenu();
                 }
                 break;
             case PAGE_SHOW:
                 tab.loadFavicon();
                 break;
             case BOOKMARK_ADDED:
-                showBookmarkAddedSnackbar();
+                // We always show the special offline snackbar whenever we bookmark a reader page.
+                // It's possible that the page is already stored offline, however this is highly
+                // unlikely, and even so it is probably nicer to show the same offline notification
+                // every time we bookmark an about:reader page.
+                if (!AboutPages.isAboutReader(tab.getURL())) {
+                    showBookmarkAddedSnackbar();
+                } else {
+                    showReaderModeBookmarkAddedSnackbar();
+                }
                 break;
             case BOOKMARK_REMOVED:
                 showBookmarkRemovedSnackbar();
                 break;
 
             case UNSELECTED:
                 // We receive UNSELECTED immediately after the SELECTED listeners run
                 // so we are ensured that the unselectedTabEditingText has not changed.
@@ -434,16 +446,36 @@ public class BrowserApp extends GeckoApp
 
         SnackbarHelper.showSnackbarWithAction(this,
                 getResources().getString(R.string.bookmark_added),
                 Snackbar.LENGTH_LONG,
                 getResources().getString(R.string.bookmark_options),
                 callback);
     }
 
+    private void showReaderModeBookmarkAddedSnackbar() {
+        final Drawable iconDownloaded = DrawableUtil.tintDrawable(getContext(), R.drawable.status_icon_readercache, R.color.saved_offline_icon_color);
+
+        final SnackbarHelper.SnackbarCallback callback = new SnackbarHelper.SnackbarCallback() {
+            @Override
+            public void onClick(View v) {
+                openUrlAndStopEditing("about:home?panel=" + HomeConfig.getIdForBuiltinPanelType(PanelType.BOOKMARKS));
+            }
+        };
+
+        SnackbarHelper.showSnackbarWithActionAndColors(this,
+                getResources().getString(R.string.reader_saved_offline),
+                Snackbar.LENGTH_LONG,
+                getResources().getString(R.string.reader_switch_to_bookmarks),
+                callback,
+                iconDownloaded,
+                ContextCompat.getColor(this, R.color.link_blue),
+                Color.WHITE);
+    }
+
     private void showBookmarkRemovedSnackbar() {
         SnackbarHelper.showSnackbar(this, getResources().getString(R.string.bookmark_removed), Snackbar.LENGTH_LONG);
     }
 
     @Override
     public boolean onKey(View v, int keyCode, KeyEvent event) {
         if (AndroidGamepadManager.handleKeyEvent(event)) {
             return true;
--- a/mobile/android/base/java/org/mozilla/gecko/SnackbarHelper.java
+++ b/mobile/android/base/java/org/mozilla/gecko/SnackbarHelper.java
@@ -4,20 +4,23 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 package org.mozilla.gecko;
 
 import org.mozilla.gecko.util.EventCallback;
 import org.mozilla.gecko.util.NativeJSObject;
 
 import android.app.Activity;
+import android.graphics.drawable.Drawable;
+import android.graphics.drawable.InsetDrawable;
 import android.support.design.widget.Snackbar;
 import android.support.v4.content.ContextCompat;
 import android.text.TextUtils;
 import android.view.View;
+import android.widget.TextView;
 
 import java.lang.ref.WeakReference;
 
 /**
  * Helper class for creating and dismissing snackbars. Use this class to guarantee a consistent style and behavior
  * across the app.
  */
 public class SnackbarHelper {
@@ -93,25 +96,54 @@ public class SnackbarHelper {
      *
      * @param activity Activity to show the snackbar in.
      * @param message The text to show. Can be formatted text.
      * @param duration How long to display the message.
      * @param action Action text to display.
      * @param callback Callback to be invoked when the action is clicked or the snackbar is dismissed.
      */
     public static void showSnackbarWithAction(Activity activity, String message, int duration, String action, SnackbarCallback callback) {
+        showSnackbarWithActionAndColors(activity, message, duration, action, callback, null, null, null);
+    }
+
+
+    public static void showSnackbarWithActionAndColors(Activity activity,
+                                                       String message,
+                                                       int duration,
+                                                       String action,
+                                                       SnackbarCallback callback,
+                                                       Drawable icon,
+                                                       Integer backgroundColor,
+                                                       Integer actionColor) {
         final View parentView = findBestParentView(activity);
         final Snackbar snackbar = Snackbar.make(parentView, message, duration);
 
         if (callback != null && !TextUtils.isEmpty(action)) {
             snackbar.setAction(action, callback);
-            snackbar.setActionTextColor(ContextCompat.getColor(activity, R.color.fennec_ui_orange));
+            if (actionColor == null) {
+                ContextCompat.getColor(activity, R.color.fennec_ui_orange);
+            } else {
+                snackbar.setActionTextColor(actionColor);
+            }
             snackbar.setCallback(callback);
         }
 
+        if (icon != null) {
+            final InsetDrawable paddedIcon = new InsetDrawable(icon, 0, 0, (int) activity.getResources().getDisplayMetrics().density *  10, 0);
+
+            paddedIcon.setBounds(0, 0, ((int) activity.getResources().getDisplayMetrics().density * 10) + icon.getIntrinsicWidth(), icon.getIntrinsicHeight());
+
+            TextView textView = (TextView) snackbar.getView().findViewById(android.support.design.R.id.snackbar_text);
+            textView.setCompoundDrawables(paddedIcon, null, null, null);
+        }
+
+        if (backgroundColor != null) {
+            snackbar.getView().setBackgroundColor(backgroundColor);
+        }
+
         snackbar.show();
 
         synchronized (currentSnackbarLock) {
             currentSnackbar = new WeakReference<>(snackbar);
         }
     }
 
     /**
--- a/mobile/android/base/locales/en-US/android_strings.dtd
+++ b/mobile/android/base/locales/en-US/android_strings.dtd
@@ -65,16 +65,22 @@
 <!ENTITY bookmark_options "Options">
 <!ENTITY screenshot_added_to_bookmarks "Screenshot added to bookmarks">
 <!-- Localization note (screenshot_folder_label_in_bookmarks): We save links to screenshots
      the user takes. The folder we store these links in is located in the bookmarks list
      and is labeled by this String. -->
 <!ENTITY screenshot_folder_label_in_bookmarks "Screenshots">
 <!ENTITY readinglist_smartfolder_label_in_bookmarks "Reading List">
 
+<!ENTITY reader_saved_offline "Saved offline">
+<!-- Localization note (reader_switch_to_bookmarks) : This
+     string is used as an action in a toast - it lets you
+     "switch" to the bookmarks (saved items) panel. -->
+<!ENTITY reader_switch_to_bookmarks "Switch">
+
 <!ENTITY history_today_section "Today">
 <!ENTITY history_yesterday_section "Yesterday">
 <!ENTITY history_week_section3 "Last 7 days">
 <!ENTITY history_older_section3 "Older than 6 months">
 
 <!ENTITY search "Search">
 <!ENTITY reload "Reload">
 <!ENTITY forward "Forward">
--- a/mobile/android/base/resources/values/colors.xml
+++ b/mobile/android/base/resources/values/colors.xml
@@ -138,9 +138,11 @@
   <color name="canvas_delegate_paint">#FFFF0000</color>
 
   <!-- Top sites thumbnail colors -->
   <color name="top_site_default">#FFECF0F3</color>
   <color name="top_site_border">#FFCFD9E1</color>
 
   <color name="private_active_text">#FFFFFF</color>
 
+  <color name="saved_offline_icon_color">#FFFFFF</color>
+
 </resources>
--- a/mobile/android/base/strings.xml.in
+++ b/mobile/android/base/strings.xml.in
@@ -94,16 +94,19 @@
   <string name="bookmark_already_added">&bookmark_already_added;</string>
   <string name="bookmark_removed">&bookmark_removed;</string>
   <string name="bookmark_updated">&bookmark_updated;</string>
   <string name="bookmark_options">&bookmark_options;</string>
   <string name="screenshot_added_to_bookmarks">&screenshot_added_to_bookmarks;</string>
   <string name="screenshot_folder_label_in_bookmarks">&screenshot_folder_label_in_bookmarks;</string>
   <string name="readinglist_smartfolder_label_in_bookmarks">&readinglist_smartfolder_label_in_bookmarks;</string>
 
+  <string name="reader_saved_offline">&reader_saved_offline;</string>
+  <string name="reader_switch_to_bookmarks">&reader_switch_to_bookmarks;</string>
+
   <string name="history_today_section">&history_today_section;</string>
   <string name="history_yesterday_section">&history_yesterday_section;</string>
   <string name="history_week_section">&history_week_section3;</string>
   <string name="history_older_section">&history_older_section3;</string>
 
   <string name="share">&share;</string>
   <string name="share_title">&share_title;</string>
   <string name="share_image_failed">&share_image_failed;</string>