Bug 1331154 - 7. Update the tab strip after tabs are moved in the tabs tray. r?sebastian draft
authorTom Klein <twointofive@gmail.com>
Sat, 25 Feb 2017 19:22:01 -0600
changeset 493023 8cbe40175f84bc1ac033248ec72e65c5bfa1b1fb
parent 490351 dcadd4262b2b9e49343601f99ddb176c17c75018
child 493024 0d77484768d23d34d65e89202c4eb10ab11d521b
push id47629
push userbmo:twointofive@gmail.com
push dateFri, 03 Mar 2017 05:50:49 +0000
reviewerssebastian
bugs1331154
milestone54.0a1
Bug 1331154 - 7. Update the tab strip after tabs are moved in the tabs tray. r?sebastian The tabs tray is drawn on top of the tab strip, not instead of it, so the tab strip needs to be updated after tabs are moved in the tabs tray before the tab strip becomes user-visible again. This introduces a slight change in behavior: *if* a move (of a tab matching the privacy state of the tab strip) occurs while the tabs panel is open, the tab strip will be scrolled to the currently selected tab when the tabs panel is closed - previously the tab strip maintained its old scroll position if a tab wasn't closed or added while the tabs panel was open. MozReview-Commit-ID: Ipy5huthNYB
mobile/android/base/java/org/mozilla/gecko/BrowserApp.java
mobile/android/base/java/org/mozilla/gecko/Tabs.java
mobile/android/base/java/org/mozilla/gecko/tabs/TabStrip.java
mobile/android/base/java/org/mozilla/gecko/tabs/TabStripView.java
--- a/mobile/android/base/java/org/mozilla/gecko/BrowserApp.java
+++ b/mobile/android/base/java/org/mozilla/gecko/BrowserApp.java
@@ -2208,30 +2208,36 @@ public class BrowserApp extends GeckoApp
                         showTabs(panel);
                     }
                 });
             }
         } else {
             if (mDoorHangerPopup != null) {
                 mDoorHangerPopup.disable();
             }
+            if (mTabStrip != null) {
+                mTabStrip.tabStripIsCovered(true);
+            }
             mTabsPanel.show(panel);
 
             // Hide potentially visible "find in page" bar (Bug 1177338)
             mFindInPageBar.hide();
 
             for (final BrowserAppDelegate delegate : delegates) {
                 delegate.onTabsTrayShown(this, mTabsPanel);
             }
         }
     }
 
     @Override
     public void hideTabs() {
         mTabsPanel.hide();
+        if (mTabStrip != null) {
+            mTabStrip.tabStripIsCovered(false);
+        }
         if (mDoorHangerPopup != null) {
             mDoorHangerPopup.enable();
         }
 
         for (final BrowserAppDelegate delegate : delegates) {
             delegate.onTabsTrayHidden(this, mTabsPanel);
         }
     }
@@ -4170,16 +4176,20 @@ public class BrowserApp extends GeckoApp
 
         // Only slide the urlbar out if it was hidden when the action mode started
         // Don't animate hiding it so that there's no flash as we switch back to url mode
         mDynamicToolbar.setTemporarilyVisible(false, VisibilityTransition.IMMEDIATE);
     }
 
     public static interface TabStripInterface {
         public void refresh();
+        /** Called to let the tab strip know it is now, or is now no longer, being hidden by
+         *  something being drawn over it.
+         */
+        void tabStripIsCovered(boolean covered);
         void setOnTabChangedListener(OnTabAddedOrRemovedListener listener);
         interface OnTabAddedOrRemovedListener {
             void onTabChanged();
         }
     }
 
     @Override
     protected void recordStartupActionTelemetry(final String passedURL, final String action) {
--- a/mobile/android/base/java/org/mozilla/gecko/Tabs.java
+++ b/mobile/android/base/java/org/mozilla/gecko/Tabs.java
@@ -672,16 +672,17 @@ public class Tabs implements BundleEvent
         STOP,
         FAVICON,
         THUMBNAIL,
         TITLE,
         SELECTED,
         UNSELECTED,
         ADDED,
         RESTORED,
+        MOVED,
         LOCATION_CHANGE,
         MENU_UPDATED,
         PAGE_SHOW,
         LINK_FEED,
         SECURITY_CHANGE,
         DESKTOP_MODE_CHANGE,
         RECORDING_CHANGE,
         BOOKMARK_ADDED,
@@ -1152,16 +1153,18 @@ public class Tabs implements BundleEvent
             // other threads from possibly choosing to start iterating mOrder in between when we
             // might mOrder.clear() and then mOrder.addAll(newTabsArray) if we were to repopulate
             // mOrder in place.)
             mOrder = new CopyOnWriteArrayList<>(newTabsList);
         }
 
         queuePersistAllTabs();
 
+        notifyListeners(mOrder.get(toPosition), TabEvents.MOVED);
+
         final GeckoBundle data = new GeckoBundle();
         data.putInt("fromTabId", fromTabId);
         data.putInt("fromPosition", fromPosition);
         data.putInt("toTabId", toTabId);
         data.putInt("toPosition", toPosition);
         EventDispatcher.getInstance().dispatch("Tab:Move", data);
     }
 }
--- a/mobile/android/base/java/org/mozilla/gecko/tabs/TabStrip.java
+++ b/mobile/android/base/java/org/mozilla/gecko/tabs/TabStrip.java
@@ -4,16 +4,17 @@
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 package org.mozilla.gecko.tabs;
 
 import android.content.Context;
 import android.graphics.drawable.Drawable;
 import android.graphics.drawable.StateListDrawable;
 import android.graphics.Rect;
+import android.support.annotation.UiThread;
 import android.support.v4.content.ContextCompat;
 import android.util.AttributeSet;
 import android.view.LayoutInflater;
 import android.view.TouchDelegate;
 import android.view.View;
 import android.view.ViewTreeObserver;
 
 import org.mozilla.gecko.BrowserApp.TabStripInterface;
@@ -28,16 +29,20 @@ public class TabStrip extends ThemedLine
     private static final String LOGTAG = "GeckoTabStrip";
 
     private final TabStripView tabStripView;
     private final ThemedImageButton addTabButton;
 
     private final TabsListener tabsListener;
     private OnTabAddedOrRemovedListener tabChangedListener;
 
+    // True when the tab strip isn't visible to the user due to something being drawn over it.
+    private boolean tabStripIsCovered;
+    private boolean tabsNeedUpdating;
+
     public TabStrip(Context context) {
         this(context, null);
     }
 
     public TabStrip(Context context, AttributeSet attrs) {
         super(context, attrs);
         setOrientation(HORIZONTAL);
 
@@ -135,25 +140,43 @@ public class TabStrip extends ThemedLine
                 case UNSELECTED:
                     // We just need to update the style for the unselected tab...
                 case TITLE:
                 case FAVICON:
                 case RECORDING_CHANGE:
                 case AUDIO_PLAYING_CHANGE:
                     tabStripView.updateTab(tab);
                     break;
+
+                case MOVED:
+                    if (tabStripIsCovered && tab.isPrivate() == tabStripView.isPrivate()) {
+                        // One of our tabs got moved while we're visible but covered; be sure to
+                        // update the tabs list before the user can see us again.
+                        tabsNeedUpdating = true;
+                    }
+                    break;
             }
         }
     }
 
     @Override
     public void refresh() {
         tabStripView.refresh();
     }
 
+    @UiThread
+    @Override
+    public void tabStripIsCovered(boolean covered) {
+        tabStripIsCovered = covered;
+        if (!tabStripIsCovered && tabsNeedUpdating) {
+            tabStripView.refreshTabs();
+            tabsNeedUpdating = false;
+        }
+    }
+
     @Override
     public void onLightweightThemeChanged() {
         final Drawable drawable = getTheme().getDrawable(this);
         if (drawable == null) {
             return;
         }
 
         final StateListDrawable stateList = new StateListDrawable();
--- a/mobile/android/base/java/org/mozilla/gecko/tabs/TabStripView.java
+++ b/mobile/android/base/java/org/mozilla/gecko/tabs/TabStripView.java
@@ -133,16 +133,20 @@ public class TabStripView extends Recycl
         }
 
     }
 
     /* package */ void updateTab(Tab tab) {
         adapter.notifyTabChanged(tab);
     }
 
+    /* package */ boolean isPrivate() {
+        return isPrivate;
+    }
+
     @Override
     public boolean onItemMove(int fromPosition, int toPosition) {
         return adapter.moveTab(fromPosition, toPosition);
     }
 
     public int getPositionForSelectedTab() {
         return adapter.getPositionForTab(Tabs.getInstance().getSelectedTab());
     }