Skip to content

Commit

Permalink
Initial implementation of tabs bar
Browse files Browse the repository at this point in the history
    The Tabs Bar is a small window that sits adyacent to the current window
    and which lists the open tabs.

    This is a very simple implementation for now, as we test and iterate.

    Other minor changes:
     - TabsBar is managed by VRBrowserActivity
     - Add session change listeners to SessionStore
     - Move TabDelegate to a separate interface
  • Loading branch information
felipeerias committed Sep 13, 2024
1 parent 22da6fa commit eb31be6
Show file tree
Hide file tree
Showing 16 changed files with 887 additions and 8 deletions.
11 changes: 10 additions & 1 deletion app/src/common/shared/com/igalia/wolvic/VRBrowserActivity.java
Original file line number Diff line number Diff line change
Expand Up @@ -76,10 +76,12 @@
import com.igalia.wolvic.ui.widgets.TrayWidget;
import com.igalia.wolvic.ui.widgets.UISurfaceTextureRenderer;
import com.igalia.wolvic.ui.widgets.UIWidget;
import com.igalia.wolvic.ui.widgets.VerticalTabsBar;
import com.igalia.wolvic.ui.widgets.WebXRInterstitialWidget;
import com.igalia.wolvic.ui.widgets.Widget;
import com.igalia.wolvic.ui.widgets.WidgetManagerDelegate;
import com.igalia.wolvic.ui.widgets.WidgetPlacement;
import com.igalia.wolvic.ui.widgets.AbstractTabsBar;
import com.igalia.wolvic.ui.widgets.WindowWidget;
import com.igalia.wolvic.ui.widgets.Windows;
import com.igalia.wolvic.ui.widgets.dialogs.CrashDialogWidget;
Expand Down Expand Up @@ -213,6 +215,7 @@ public void run() {
RootWidget mRootWidget;
KeyboardWidget mKeyboard;
NavigationBarWidget mNavigationBar;
AbstractTabsBar mTabsBar;
CrashDialogWidget mCrashDialog;
TrayWidget mTray;
WhatsNewWidget mWhatsNewWidget = null;
Expand Down Expand Up @@ -461,13 +464,17 @@ public void onWindowVideoAvailabilityChanged(@NonNull WindowWidget aWindow) {
}
});

// Create Tabs bar widget
// TODO support horizontal tabs bar depending on setting
mTabsBar = new VerticalTabsBar(this, mWindows);

// Create the tray
mTray = new TrayWidget(this);
mTray.addListeners(mWindows);
mTray.setAddWindowVisible(mWindows.canOpenNewWindow());
attachToWindow(mWindows.getFocusedWindow(), null);

addWidgets(Arrays.asList(mRootWidget, mNavigationBar, mKeyboard, mTray, mWebXRInterstitial));
addWidgets(Arrays.asList(mRootWidget, mNavigationBar, mTabsBar, mKeyboard, mTray, mWebXRInterstitial));

// Create the platform plugin after widgets are created to be extra safe.
mPlatformPlugin = createPlatformPlugin(this);
Expand All @@ -480,11 +487,13 @@ public void onWindowVideoAvailabilityChanged(@NonNull WindowWidget aWindow) {
private void attachToWindow(@NonNull WindowWidget aWindow, @Nullable WindowWidget aPrevWindow) {
mPermissionDelegate.setParentWidgetHandle(aWindow.getHandle());
mNavigationBar.attachToWindow(aWindow);
mTabsBar.attachToWindow(aWindow);
mKeyboard.attachToWindow(aWindow);
mTray.attachToWindow(aWindow);

if (aPrevWindow != null) {
updateWidget(mNavigationBar);
updateWidget(mTabsBar);
updateWidget(mKeyboard);
updateWidget(mTray);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.Executor;
Expand Down Expand Up @@ -84,9 +85,11 @@ public static SessionStore get() {
private FxaWebChannelFeature mWebChannelsFeature;
private Store.Subscription mStoreSubscription;
private BrowserIconsHelper mBrowserIconsHelper;
private final LinkedHashSet<SessionChangeListener> mSessionChangeListeners;

private SessionStore() {
mSessions = new ArrayList<>();
mSessionChangeListeners = new LinkedHashSet<>();
}

public void initialize(Context context) {
Expand Down Expand Up @@ -358,6 +361,10 @@ public Session getActiveSession() {
return mActiveSession;
}

public List<Session> getSessions(boolean aPrivateMode) {
return mSessions.stream().filter(session -> session.isPrivateMode() == aPrivateMode).collect(Collectors.toList());
}

public ArrayList<Session> getSortedSessions(boolean aPrivateMode) {
ArrayList<Session> result = new ArrayList<>(mSessions);
result.removeIf(session -> session.isPrivateMode() != aPrivateMode);
Expand All @@ -374,6 +381,14 @@ public void setPermissionDelegate(PermissionDelegate delegate) {
mPermissionDelegate = delegate;
}

public void addSessionChangeListener(SessionChangeListener listener) {
mSessionChangeListeners.add(listener);
}

public void removeSessionChangeListener(SessionChangeListener listener) {
mSessionChangeListeners.remove(listener);
}

public BookmarksStore getBookmarkStore() {
return mBookmarksStore;
}
Expand Down Expand Up @@ -514,28 +529,43 @@ public void removePermissionException(@NonNull String uri, @SitePermission.Categ
@Override
public void onSessionAdded(Session aSession) {
ComponentsAdapter.get().addSession(aSession);
for (SessionChangeListener listener : mSessionChangeListeners) {
listener.onSessionAdded(aSession);
}
}

@Override
public void onSessionOpened(Session aSession) {
ComponentsAdapter.get().link(aSession);
for (SessionChangeListener listener : mSessionChangeListeners) {
listener.onSessionOpened(aSession);
}
}

@Override
public void onSessionClosed(Session aSession) {
ComponentsAdapter.get().unlink(aSession);
for (SessionChangeListener listener : mSessionChangeListeners) {
listener.onSessionClosed(aSession);
}
}

@Override
public void onSessionRemoved(String aId) {
ComponentsAdapter.get().removeSession(aId);
for (SessionChangeListener listener : mSessionChangeListeners) {
listener.onSessionRemoved(aId);
}
}

@Override
public void onSessionStateChanged(Session aSession, boolean aActive) {
if (aActive) {
ComponentsAdapter.get().selectSession(aSession);
}
for (SessionChangeListener listener : mSessionChangeListeners) {
listener.onSessionStateChanged(aSession, aActive);
}
}

@Override
Expand All @@ -549,6 +579,9 @@ public void onCurrentSessionChange(WSession aOldSession, WSession aSession) {
ComponentsAdapter.get().link(newSession);
}

for (SessionChangeListener listener : mSessionChangeListeners) {
listener.onCurrentSessionChange(aOldSession, aSession);
}
}

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
package com.igalia.wolvic.ui.adapters;

import android.util.Log;
import android.view.LayoutInflater;
import android.view.ViewGroup;

import androidx.annotation.LayoutRes;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;

import com.igalia.wolvic.R;
import com.igalia.wolvic.browser.engine.Session;
import com.igalia.wolvic.browser.engine.SessionStore;
import com.igalia.wolvic.ui.views.TabsBarItem;
import com.igalia.wolvic.ui.widgets.TabDelegate;
import com.igalia.wolvic.utils.SystemUtils;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class TabsBarAdapter extends RecyclerView.Adapter<TabsBarAdapter.ViewHolder> {

private static final String LOGTAG = SystemUtils.createLogtag(TabsBarAdapter.class);

public enum Orientation {HORIZONTAL, VERTICAL}

private final TabDelegate mTabDelegate;
private final Orientation mOrientation;
private List<Session> mTabs = new ArrayList<>();

static class ViewHolder extends RecyclerView.ViewHolder {
TabsBarItem mTabBarItem;

ViewHolder(TabsBarItem v) {
super(v);
mTabBarItem = v;
}
}

public TabsBarAdapter(@NonNull TabDelegate tabDelegate, Orientation orientation) {
mTabDelegate = tabDelegate;
mOrientation = orientation;
}

@Override
public long getItemId(int position) {
if (position == 0) {
return 0;
} else {
return mTabs.get(position - 1).getId().hashCode();
}
}

public void updateTabs(List<Session> aTabs) {
mTabs = aTabs;

Log.e(LOGTAG, "updateTabs: " + aTabs.size());
for (Session session : aTabs) {
Log.e(LOGTAG, " " + session.getCurrentUri() + " " + session.getLastUse());
}

notifyDataSetChanged();
}

@NonNull
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
@LayoutRes int layout;
if (mOrientation == Orientation.HORIZONTAL) {
layout = R.layout.tabs_bar_item_horizontal;
} else {
layout = R.layout.tabs_bar_item_vertical;
}
TabsBarItem view = (TabsBarItem) LayoutInflater.from(parent.getContext()).inflate(layout, parent, false);
return new ViewHolder(view);
}

@Override
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
if (position > 0) {
Session session = mTabs.get(position - 1);
holder.mTabBarItem.attachToSession(session);
holder.mTabBarItem.setMode(TabsBarItem.Mode.TAB_DETAILS);
holder.mTabBarItem.setDelegate(mItemDelegate);
} else {
holder.mTabBarItem.attachToSession(null);
holder.mTabBarItem.setMode(TabsBarItem.Mode.ADD_TAB);
}
}

@Override
public int getItemCount() {
return mTabs.size() + 1;
}

private final TabsBarItem.Delegate mItemDelegate = new TabsBarItem.Delegate() {
@Override
public void onAdd(TabsBarItem item) {

Log.e(LOGTAG, "TabsBarItem.Delegate onAdd");

mTabDelegate.onTabAdd();
}

@Override
public void onClick(TabsBarItem item) {
mTabDelegate.onTabSelect(item.getSession());
}

@Override
public void onClose(TabsBarItem item) {
mTabDelegate.onTabsClose(Collections.singletonList(item.getSession()));
// this should eventually trigger a refresh of the tabs
}
};
}
Loading

0 comments on commit eb31be6

Please sign in to comment.