Skip to content

Commit

Permalink
Sync button to receive tabs from FxA
Browse files Browse the repository at this point in the history
Since we do not support push notifications from the FxA service,
we need to request an update manually whenever we want to
receive shared tabs.

This change adds a "refresh" button to the tabs bars.

Based on #1718
  • Loading branch information
felipeerias committed Jan 28, 2025
1 parent dc3da54 commit cd045e7
Show file tree
Hide file tree
Showing 7 changed files with 197 additions and 83 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,30 +3,43 @@
import android.content.Context;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.databinding.ObservableBoolean;
import androidx.lifecycle.MutableLiveData;
import androidx.lifecycle.Observer;
import androidx.lifecycle.ViewModelProvider;

import com.igalia.wolvic.VRBrowserActivity;
import com.igalia.wolvic.browser.Accounts;
import com.igalia.wolvic.browser.SessionChangeListener;
import com.igalia.wolvic.browser.api.WSession;
import com.igalia.wolvic.browser.engine.Session;
import com.igalia.wolvic.browser.engine.SessionStore;
import com.igalia.wolvic.ui.viewmodel.WindowViewModel;
import com.igalia.wolvic.utils.SystemUtils;

public abstract class AbstractTabsBar extends UIWidget implements SessionChangeListener, WidgetManagerDelegate.UpdateListener {
import mozilla.components.concept.sync.AccountObserver;
import mozilla.components.concept.sync.AuthFlowError;
import mozilla.components.concept.sync.AuthType;
import mozilla.components.concept.sync.OAuthAccount;
import mozilla.components.concept.sync.Profile;

public abstract class AbstractTabsBar extends UIWidget implements SessionChangeListener, WidgetManagerDelegate.UpdateListener, AccountObserver {

protected final String LOGTAG = SystemUtils.createLogtag(this.getClass());

protected boolean mPrivateMode;
protected WindowWidget mAttachedWindow;
protected WindowViewModel mWindowViewModel;
protected MutableLiveData<Boolean> mSyncAccountEnabled = new MutableLiveData<>(false);

private Accounts mAccounts;

public AbstractTabsBar(Context aContext) {
super(aContext);

SessionStore.get().addSessionChangeListener(this);
mAccounts = mWidgetManager.getServicesProvider().getAccounts();
}

public abstract void updateWidgetPlacement();
Expand All @@ -47,6 +60,9 @@ public void attachToWindow(@NonNull WindowWidget window) {
.get(String.valueOf(mAttachedWindow.hashCode()), WindowViewModel.class);
mWindowViewModel.getIsTabsBarVisible().observe((VRBrowserActivity) getContext(), mIsTabsBarVisibleObserver);

mAccounts.addAccountListener(this);
mSyncAccountEnabled.postValue(mAccounts.isSignedIn());

updateWidgetPlacement();
refreshTabs();
}
Expand All @@ -57,6 +73,7 @@ public void detachFromWindow() {
mWindowViewModel.getIsTabsBarVisible().removeObserver(mIsTabsBarVisibleObserver);
mWindowViewModel = null;
}
mAccounts.removeAccountListener(this);
mAttachedWindow = null;
}

Expand Down Expand Up @@ -143,4 +160,33 @@ public void onStackSession(Session aSession) {
public void onUnstackSession(Session aSession, Session aParent) {
refreshTabs();
}

// AccountObserver

@Override
public void onLoggedOut() {
mSyncAccountEnabled.postValue(mAccounts.isSignedIn());
}

@Override
public void onAuthenticated(@NonNull OAuthAccount oAuthAccount, @NonNull AuthType authType) {
mSyncAccountEnabled.postValue(mAccounts.isSignedIn());
}


@Override
public void onAuthenticationProblems() {
}

@Override
public void onReady(@Nullable OAuthAccount oAuthAccount) {
}

@Override
public void onProfileUpdated(@NonNull Profile profile) {
}

@Override
public void onFlowError(@NonNull AuthFlowError authFlowError) {
}
}
Original file line number Diff line number Diff line change
@@ -1,20 +1,22 @@
package com.igalia.wolvic.ui.widgets;

import android.content.Context;
import android.widget.Button;
import android.view.LayoutInflater;

import androidx.databinding.DataBindingUtil;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

import com.igalia.wolvic.R;
import com.igalia.wolvic.VRBrowserActivity;
import com.igalia.wolvic.browser.SettingsStore;
import com.igalia.wolvic.browser.engine.SessionStore;
import com.igalia.wolvic.databinding.TabsBarHorizontalBinding;
import com.igalia.wolvic.ui.adapters.TabsBarAdapter;

public class HorizontalTabsBar extends AbstractTabsBar {

protected Button mAddTabButton;
protected RecyclerView mTabsList;
private TabsBarHorizontalBinding mBinding;
protected LinearLayoutManager mLayoutManager;
protected TabsBarAdapter mAdapter;
protected final TabDelegate mTabDelegate;
Expand All @@ -28,17 +30,20 @@ public HorizontalTabsBar(Context aContext, TabDelegate aDelegate) {
private void updateUI() {
removeAllViews();

inflate(getContext(), R.layout.tabs_bar_horizontal, this);
LayoutInflater inflater = LayoutInflater.from(getContext());
mBinding = DataBindingUtil.inflate(inflater, R.layout.tabs_bar_horizontal, this, true);
mBinding.setLifecycleOwner((VRBrowserActivity) getContext());
mBinding.setSyncAccountEnabled(mSyncAccountEnabled);

mAddTabButton = findViewById(R.id.add_tab);
mAddTabButton.setOnClickListener(v -> mTabDelegate.onTabAdd());
mBinding.addTab.setOnClickListener(v -> mTabDelegate.onTabAdd());

mBinding.syncTabs.setOnClickListener(v -> mTabDelegate.onTabSync());

mTabsList = findViewById(R.id.tabsRecyclerView);
mLayoutManager = new LinearLayoutManager(getContext());
mLayoutManager.setOrientation(RecyclerView.HORIZONTAL);
mTabsList.setLayoutManager(mLayoutManager);
mBinding.tabsRecyclerView.setLayoutManager(mLayoutManager);
mAdapter = new TabsBarAdapter(mTabDelegate, TabsBarAdapter.Orientation.HORIZONTAL);
mTabsList.setAdapter(mAdapter);
mBinding.tabsRecyclerView.setAdapter(mAdapter);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,5 @@ public interface TabDelegate {
void onTabSelect(Session aTab);
void onTabsClose(List<Session> aTabs);
void onTabsBookmark(List<Session> aTabs);
void onTabSync();
}
Original file line number Diff line number Diff line change
@@ -1,21 +1,22 @@
package com.igalia.wolvic.ui.widgets;

import android.content.Context;
import android.widget.Button;
import android.view.LayoutInflater;

import androidx.annotation.NonNull;
import androidx.databinding.DataBindingUtil;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

import com.igalia.wolvic.R;
import com.igalia.wolvic.VRBrowserActivity;
import com.igalia.wolvic.browser.SettingsStore;
import com.igalia.wolvic.browser.engine.SessionStore;
import com.igalia.wolvic.databinding.TabsBarVerticalBinding;
import com.igalia.wolvic.ui.adapters.TabsBarAdapter;

public class VerticalTabsBar extends AbstractTabsBar {

protected Button mAddTabButton;
protected RecyclerView mTabsList;
private TabsBarVerticalBinding mBinding;
protected LinearLayoutManager mLayoutManager;
protected TabsBarAdapter mAdapter;
protected final TabDelegate mTabDelegate;
Expand All @@ -29,17 +30,20 @@ public VerticalTabsBar(Context aContext, TabDelegate aDelegate) {
private void updateUI() {
removeAllViews();

inflate(getContext(), R.layout.tabs_bar_vertical, this);
LayoutInflater inflater = LayoutInflater.from(getContext());
mBinding = DataBindingUtil.inflate(inflater, R.layout.tabs_bar_vertical, this, true);
mBinding.setLifecycleOwner((VRBrowserActivity) getContext());
mBinding.setSyncAccountEnabled(mSyncAccountEnabled);

mAddTabButton = findViewById(R.id.add_tab);
mAddTabButton.setOnClickListener(v -> mTabDelegate.onTabAdd());
mBinding.addTab.setOnClickListener(v -> mTabDelegate.onTabAdd());

mBinding.syncTabs.setOnClickListener(v -> mTabDelegate.onTabSync());

mTabsList = findViewById(R.id.tabsRecyclerView);
mLayoutManager = new LinearLayoutManager(getContext());
mLayoutManager.setOrientation(RecyclerView.VERTICAL);
mTabsList.setLayoutManager(mLayoutManager);
mBinding.tabsRecyclerView.setLayoutManager(mLayoutManager);
mAdapter = new TabsBarAdapter(mTabDelegate, TabsBarAdapter.Orientation.VERTICAL);
mTabsList.setAdapter(mAdapter);
mBinding.tabsRecyclerView.setAdapter(mAdapter);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1617,6 +1617,14 @@ public void onTabsBookmark(List<Session> aTabs) {
}
}

@Override
public void onTabSync() {
// If we're signed-in, poll for any new device events (e.g. received tabs)
// There's no push support right now, so this helps with the perception of speedy tab delivery.
mAccounts.refreshDevicesAsync();
mAccounts.pollForEventsAsync();
}

public void closeTab(@NonNull Session aTab) {
if (isSessionFocused(aTab)) {
closeTabs(Collections.singletonList(aTab), mPrivateMode, true);
Expand Down
87 changes: 56 additions & 31 deletions app/src/main/res/layout/tabs_bar_horizontal.xml
Original file line number Diff line number Diff line change
@@ -1,38 +1,63 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
tools:layout_height="@dimen/horizontal_tabs_bar_height"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/tabs_bar_bg"
android:orientation="horizontal">
xmlns:tools="http://schemas.android.com/tools">

<com.google.android.material.button.MaterialButton
android:id="@+id/add_tab"
android:layout_width="64dp"
android:layout_height="match_parent"
android:layout_margin="4dp"
android:background="@drawable/tab_add_background"
android:scaleType="fitCenter"
app:backgroundTint="@null"
app:icon="@drawable/ic_icon_newtab"
app:iconGravity="textStart"
app:iconPadding="0dp"
app:iconSize="24dp"
app:iconTint="@color/fog" />
<data>

<variable
name="syncAccountEnabled"
type="androidx.lifecycle.LiveData&lt;Boolean&gt;" />
</data>

<com.igalia.wolvic.ui.views.CustomRecyclerView
android:id="@+id/tabsRecyclerView"
style="@style/customRecyclerViewStyle"
android:layout_width="0dp"
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="2dp"
android:layout_weight="1"
android:background="@drawable/tabs_bar_bg"
android:orientation="horizontal"
android:overScrollMode="never"
android:scrollbars="horizontal"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
tools:listitem="@layout/tabs_bar_item_horizontal" />
tools:layout_height="@dimen/horizontal_tabs_bar_height">

<com.google.android.material.button.MaterialButton
android:id="@+id/sync_tabs"
android:layout_width="64dp"
android:layout_height="match_parent"
android:layout_margin="4dp"
android:background="@drawable/tab_add_background"
android:scaleType="fitCenter"
app:backgroundTint="@null"
app:icon="@drawable/ic_icon_settings_sign_in"
app:iconGravity="textStart"
app:iconPadding="0dp"
app:iconSize="24dp"
app:iconTint="@color/rhino"
app:visibleGone="@{syncAccountEnabled}" />

<com.google.android.material.button.MaterialButton
android:id="@+id/add_tab"
android:layout_width="64dp"
android:layout_height="match_parent"
android:layout_margin="4dp"
android:background="@drawable/tab_add_background"
android:scaleType="fitCenter"
app:backgroundTint="@null"
app:icon="@drawable/ic_icon_newtab"
app:iconGravity="textStart"
app:iconPadding="0dp"
app:iconSize="24dp"
app:iconTint="@color/rhino" />

<com.igalia.wolvic.ui.views.CustomRecyclerView
android:id="@+id/tabsRecyclerView"
style="@style/customRecyclerViewStyle"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_margin="2dp"
android:layout_weight="1"
android:orientation="horizontal"
android:overScrollMode="never"
android:scrollbars="horizontal"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
tools:listitem="@layout/tabs_bar_item_horizontal" />

</LinearLayout>
</LinearLayout>
</layout>
Loading

0 comments on commit cd045e7

Please sign in to comment.