Bug 1116415 - 5. Send the index of an added tab as data. r?sebastian draft
authorTom Klein <twointofive@gmail.com>
Thu, 13 Oct 2016 10:26:53 -0500
changeset 425503 20ded81372507f3356c2922a47c299650cdba884
parent 425502 601fc8169aa2b9d93907ebab5669a1653df5bc31
child 425504 9302e89df0fed6be96d88059976a8ad994e2e080
push id32434
push userbmo:twointofive@gmail.com
push dateFri, 14 Oct 2016 20:21:22 +0000
reviewerssebastian
bugs1116415
milestone52.0a1
Bug 1116415 - 5. Send the index of an added tab as data. r?sebastian Use the index in TabsLayout to specify where a tab was inserted instead of just replacing the entire tabs list on a tab add. MozReview-Commit-ID: Feft0RlN97r
mobile/android/base/java/org/mozilla/gecko/Tabs.java
mobile/android/base/java/org/mozilla/gecko/tabs/TabsLayout.java
mobile/android/base/java/org/mozilla/gecko/tabs/TabsLayoutRecyclerAdapter.java
mobile/android/base/java/org/mozilla/gecko/tabs/TabsListLayout.java
--- a/mobile/android/base/java/org/mozilla/gecko/Tabs.java
+++ b/mobile/android/base/java/org/mozilla/gecko/Tabs.java
@@ -222,22 +222,36 @@ public class Tabs implements GeckoEventL
                 mOrder.add(tabIndex, tab);
             } else {
                 mOrder.add(tab);
             }
         }
 
         // Suppress the ADDED event to prevent animation of tabs created via session restore.
         if (mInitialTabsAdded) {
-            notifyListeners(tab, TabEvents.ADDED);
+            notifyListeners(tab, TabEvents.ADDED,
+                    Integer.toString(getPrivacySpecificTabIndex(tabIndex, isPrivate)));
         }
 
         return tab;
     }
 
+    // Return the index, among those tabs whose privacy setting matches isPrivate, of the tab at
+    // position index in mOrder.  Returns -1, for "new last tab", when index is -1.
+    private int getPrivacySpecificTabIndex(int index, boolean isPrivate) {
+        int privacySpecificIndex = -1;
+        for (int i = 0; i <= index; i++) {
+            final Tab tab = mOrder.get(i);
+            if (tab.isPrivate() == isPrivate) {
+                privacySpecificIndex++;
+            }
+        }
+        return privacySpecificIndex;
+    }
+
     public synchronized void removeTab(int id) {
         if (mTabs.containsKey(id)) {
             Tab tab = getTab(id);
             mOrder.remove(tab);
             mTabs.remove(id);
         }
     }
 
--- a/mobile/android/base/java/org/mozilla/gecko/tabs/TabsLayout.java
+++ b/mobile/android/base/java/org/mozilla/gecko/tabs/TabsLayout.java
@@ -93,18 +93,23 @@ public abstract class TabsLayout extends
     protected void autoHidePanel() {
         tabsPanel.autoHidePanel();
     }
 
     @Override
     public void onTabChanged(Tab tab, Tabs.TabEvents msg, String data) {
         switch (msg) {
             case ADDED:
-                // Refresh the list to make sure the new tab is added in the right position.
-                refreshTabsData();
+                final int tabIndex = Integer.parseInt(data);
+                tabsAdapter.notifyTabInserted(tab, tabIndex);
+                if (addAtIndexRequiresScroll(tabIndex)) {
+                    // (The current Tabs implementation updates the SELECTED tab *after* this
+                    // call to ADDED, so don't just call updateSelectedPosition().)
+                    scrollToPosition(tabIndex);
+                }
                 break;
 
             case CLOSED:
                 if (tab.isPrivate() == isPrivate && tabsAdapter.getItemCount() > 0) {
                     tabsAdapter.removeTab(tab);
                 }
                 break;
 
@@ -114,16 +119,20 @@ public abstract class TabsLayout extends
             case TITLE:
             case RECORDING_CHANGE:
             case AUDIO_PLAYING_CHANGE:
                 tabsAdapter.notifyTabChanged(tab);
                 break;
         }
     }
 
+    // Addition of a tab at selected positions (dependent on LayoutManager) will result in a tab
+    // being added out of view - return true if index is such a position.
+    abstract protected boolean addAtIndexRequiresScroll(int index);
+
     @Override
     public void onItemClicked(RecyclerView recyclerView, int position, View v) {
         final TabsLayoutItemView item = (TabsLayoutItemView) v;
         final int tabId = item.getTabId();
         final Tabs tabs = Tabs.getInstance();
         tabs.selectTab(tabId);
         autoHidePanel();
         tabs.notifyListeners(tabs.getTab(tabId), Tabs.TabEvents.OPENED_FROM_TABS_TRAY);
--- a/mobile/android/base/java/org/mozilla/gecko/tabs/TabsLayoutRecyclerAdapter.java
+++ b/mobile/android/base/java/org/mozilla/gecko/tabs/TabsLayoutRecyclerAdapter.java
@@ -5,26 +5,29 @@
 
 package org.mozilla.gecko.tabs;
 
 import org.mozilla.gecko.Tab;
 
 import android.content.Context;
 import android.support.annotation.NonNull;
 import android.support.v7.widget.RecyclerView;
+import android.util.Log;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.Button;
 
 import java.util.ArrayList;
 
 public class TabsLayoutRecyclerAdapter
         extends RecyclerView.Adapter<TabsLayoutRecyclerAdapter.TabsListViewHolder> {
 
+    private static final String LOGTAG = "Gecko" + TabsLayoutRecyclerAdapter.class.getSimpleName();
+
     private final int tabLayoutId;
     private @NonNull ArrayList<Tab> tabs;
     private final LayoutInflater inflater;
     private final boolean isPrivate;
     // Click listener for the close button on itemViews.
     private final Button.OnClickListener closeOnClickListener;
 
     // The TabsLayoutItemView takes care of caching its own Views, so we don't need to do anything
@@ -71,16 +74,31 @@ public class TabsLayoutRecyclerAdapter
 
         return tabs.indexOf(tab);
     }
 
     /* package */ void notifyTabChanged(Tab tab) {
         notifyItemChanged(getPositionForTab(tab));
     }
 
+    /* package */ void notifyTabInserted(Tab tab, int index) {
+        if (index >= 0 && index <= tabs.size()) {
+            tabs.add(index, tab);
+            notifyItemInserted(index);
+        } else {
+            // Add to the end.
+            tabs.add(tab);
+            notifyItemInserted(tabs.size() - 1);
+            // index == -1 is a valid way to add to the end, the other cases are errors.
+            if (index != -1) {
+                Log.e(LOGTAG, "Tab was inserted at an invalid position: " + Integer.toString(index));
+            }
+        }
+    }
+
     @Override
     public int getItemCount() {
         return tabs.size();
     }
 
     private Tab getItem(int position) {
         return tabs.get(position);
     }
--- a/mobile/android/base/java/org/mozilla/gecko/tabs/TabsListLayout.java
+++ b/mobile/android/base/java/org/mozilla/gecko/tabs/TabsListLayout.java
@@ -101,9 +101,14 @@ public class TabsListLayout extends Tabs
                 public void run() {
                     animator.start();
                 }
             }, cascadeDelay);
 
             cascadeDelay += ANIMATION_CASCADE_DELAY;
         }
     }
+
+    @Override
+    protected boolean addAtIndexRequiresScroll(int index) {
+        return index == 0 || index == getAdapter().getItemCount() - 1;
+    }
 }