Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Initial implementation of tabs bar #1468

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 58 additions & 8 deletions app/src/common/shared/com/igalia/wolvic/VRBrowserActivity.java
Original file line number Diff line number Diff line change
Expand Up @@ -69,13 +69,16 @@
import com.igalia.wolvic.telemetry.TelemetryService;
import com.igalia.wolvic.ui.OffscreenDisplay;
import com.igalia.wolvic.ui.adapters.Language;
import com.igalia.wolvic.ui.widgets.AbstractTabsBar;
import com.igalia.wolvic.ui.widgets.AppServicesProvider;
import com.igalia.wolvic.ui.widgets.HorizontalTabsBar;
import com.igalia.wolvic.ui.widgets.KeyboardWidget;
import com.igalia.wolvic.ui.widgets.NavigationBarWidget;
import com.igalia.wolvic.ui.widgets.RootWidget;
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;
Expand Down Expand Up @@ -105,6 +108,7 @@
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ScheduledFuture;
Expand Down Expand Up @@ -213,6 +217,7 @@ public void run() {
RootWidget mRootWidget;
KeyboardWidget mKeyboard;
NavigationBarWidget mNavigationBar;
AbstractTabsBar mTabsBar;
CrashDialogWidget mCrashDialog;
TrayWidget mTray;
WhatsNewWidget mWhatsNewWidget = null;
Expand Down Expand Up @@ -465,9 +470,19 @@ public void onWindowVideoAvailabilityChanged(@NonNull WindowWidget aWindow) {
mTray = new TrayWidget(this);
mTray.addListeners(mWindows);
mTray.setAddWindowVisible(mWindows.canOpenNewWindow());

// Create Tabs bar widget
if (mSettings.getTabsLocation() == SettingsStore.TABS_LOCATION_HORIZONTAL) {
mTabsBar = new HorizontalTabsBar(this, mWindows);
} else if (mSettings.getTabsLocation() == SettingsStore.TABS_LOCATION_VERTICAL) {
mTabsBar = new VerticalTabsBar(this, mWindows);
} else {
mTabsBar = null;
}

attachToWindow(mWindows.getFocusedWindow(), null);

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

// Create the platform plugin after widgets are created to be extra safe.
mPlatformPlugin = createPlatformPlugin(this);
Expand All @@ -483,10 +498,18 @@ private void attachToWindow(@NonNull WindowWidget aWindow, @Nullable WindowWidge
mKeyboard.attachToWindow(aWindow);
mTray.attachToWindow(aWindow);

if (mTabsBar != null) {
mTabsBar.attachToWindow(aWindow);
}

if (aPrevWindow != null) {
updateWidget(mNavigationBar);
updateWidget(mTabsBar);
updateWidget(mKeyboard);
updateWidget(mTray);
if (mTabsBar != null) {
updateWidget(mTabsBar);
}
}
}

Expand Down Expand Up @@ -772,14 +795,41 @@ public void onConfigurationChanged(Configuration newConfig) {

@Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
if (key.equals(getString(R.string.settings_key_voice_search_service))) {
initializeSpeechRecognizer();
} else if (key.equals(getString(R.string.settings_key_head_lock))) {
boolean isHeadLockEnabled = SettingsStore.getInstance(this).isHeadLockEnabled();
setHeadLockEnabled(isHeadLockEnabled);
if (!isHeadLockEnabled)
recenterUIYaw(WidgetManagerDelegate.YAW_TARGET_ALL);
if (Objects.equals(key, getString(R.string.settings_key_voice_search_service))) {
initializeSpeechRecognizer();
} else if (Objects.equals(key, getString(R.string.settings_key_head_lock))) {
boolean isHeadLockEnabled = mSettings.isHeadLockEnabled();
setHeadLockEnabled(isHeadLockEnabled);
if (!isHeadLockEnabled)
recenterUIYaw(WidgetManagerDelegate.YAW_TARGET_ALL);
} else if (Objects.equals(key, getString(R.string.settings_key_tabs_location))) {

Log.e(LOGTAG, "update tabs location");

// remove the previous widget
if (mTabsBar != null) {
Log.e(LOGTAG, "remove previous widget");
removeWidget(mTabsBar);
mTabsBar.releaseWidget();
}

if (mSettings.getTabsLocation() == SettingsStore.TABS_LOCATION_TRAY) {
mTabsBar = null;
} else {
if (mSettings.getTabsLocation() == SettingsStore.TABS_LOCATION_HORIZONTAL) {
mTabsBar = new HorizontalTabsBar(this, mWindows);
} else if (mSettings.getTabsLocation() == SettingsStore.TABS_LOCATION_VERTICAL) {
mTabsBar = new VerticalTabsBar(this, mWindows);
} else {
Log.e(LOGTAG, "Invalid value for tabs location");
mTabsBar = null;
return;
}
addWidget(mTabsBar);
mTabsBar.attachToWindow(mWindows.getFocusedWindow());
updateWidget(mTabsBar);
}
}
}

void loadFromIntent(final Intent intent) {
Expand Down
19 changes: 19 additions & 0 deletions app/src/common/shared/com/igalia/wolvic/browser/SettingsStore.java
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,12 @@ SettingsStore getInstance(final @NonNull Context aContext) {
public static final int INTERNAL = 0;
public static final int EXTERNAL = 1;

@IntDef(value = { TABS_LOCATION_TRAY, TABS_LOCATION_HORIZONTAL, TABS_LOCATION_VERTICAL})
public @interface TabsLocation {}
public static final int TABS_LOCATION_TRAY = 0;
public static final int TABS_LOCATION_HORIZONTAL = 1;
public static final int TABS_LOCATION_VERTICAL = 2;

private Context mContext;
private SharedPreferences mPrefs;
private SettingsViewModel mSettingsViewModel;
Expand Down Expand Up @@ -113,6 +119,7 @@ SettingsStore getInstance(final @NonNull Context aContext) {
public final static boolean AUDIO_ENABLED = BuildConfig.FLAVOR_backend == "chromium";
public final static boolean LATIN_AUTO_COMPLETE_ENABLED = false;
public final static boolean WINDOW_MOVEMENT_DEFAULT = false;
public final static @TabsLocation int TABS_LOCATION_DEFAULT = TABS_LOCATION_TRAY;
public final static float CYLINDER_DENSITY_ENABLED_DEFAULT = 4680.0f;
public final static float HAPTIC_PULSE_DURATION_DEFAULT = 10.0f;
public final static float HAPTIC_PULSE_INTENSITY_DEFAULT = 1.0f;
Expand Down Expand Up @@ -374,6 +381,18 @@ public void setWindowMovementEnabled(boolean isEnabled) {
mSettingsViewModel.setWindowMovementEnabled(isEnabled);
}

@TabsLocation
public int getTabsLocation() {
return mPrefs.getInt(
mContext.getString(R.string.settings_key_tabs_location), TABS_LOCATION_DEFAULT);
}

public void setTabsLocation(@TabsLocation int tabsLocation) {
SharedPreferences.Editor editor = mPrefs.edit();
editor.putInt(mContext.getString(R.string.settings_key_tabs_location), tabsLocation);
editor.commit();
}

public boolean isEnvironmentOverrideEnabled() {
return mPrefs.getBoolean(
mContext.getString(R.string.settings_key_environment_override), ENV_OVERRIDE_DEFAULT);
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,94 @@
package com.igalia.wolvic.ui.adapters;

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.ui.views.TabsBarItem;
import com.igalia.wolvic.ui.widgets.TabDelegate;

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

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

public enum Orientation {HORIZONTAL, VERTICAL}

private final TabDelegate mTabDelegate;
private final Orientation mOrientation;
private final 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.clear();
mTabs.addAll(aTabs);

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) {
holder.mTabBarItem.setDelegate(mItemDelegate);

Session session = mTabs.get(position);
holder.mTabBarItem.attachToSession(session);
}

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

private final TabsBarItem.Delegate mItemDelegate = new TabsBarItem.Delegate() {
@Override
public void onClick(TabsBarItem item) {
mTabDelegate.onTabSelect(item.getSession());
}

@Override
public void onClose(TabsBarItem item) {
mTabDelegate.onTabsClose(Collections.singletonList(item.getSession()));
}
};
}
Loading