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
--- 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;
+ }
}