diff --git a/app/src/common/shared/org/mozilla/vrbrowser/VRBrowserActivity.java b/app/src/common/shared/org/mozilla/vrbrowser/VRBrowserActivity.java index 938acf566..ac5b3ffe8 100644 --- a/app/src/common/shared/org/mozilla/vrbrowser/VRBrowserActivity.java +++ b/app/src/common/shared/org/mozilla/vrbrowser/VRBrowserActivity.java @@ -66,6 +66,7 @@ import org.mozilla.vrbrowser.ui.widgets.WindowWidget; import org.mozilla.vrbrowser.ui.widgets.Windows; import org.mozilla.vrbrowser.ui.widgets.dialogs.CrashDialogWidget; +import org.mozilla.vrbrowser.ui.widgets.dialogs.WhatsNewWidget; import org.mozilla.vrbrowser.ui.widgets.prompts.ConfirmPromptWidget; import org.mozilla.vrbrowser.utils.BitmapCache; import org.mozilla.vrbrowser.utils.ConnectivityReceiver; @@ -322,6 +323,15 @@ public void onWindowClosed() { attachToWindow(mWindows.getFocusedWindow(), null); addWidgets(Arrays.asList(mRootWidget, mNavigationBar, mKeyboard, mTray)); + + // Show the what's upp dialog if we haven't showed it yet and this is v6. + if (!SettingsStore.getInstance(this).isWhatsNewDisplayed() && BuildConfig.VERSION_NAME.equals("6")) { + WhatsNewWidget whatsNew = new WhatsNewWidget(this); + whatsNew.getPlacement().parentHandle = mWindows.getFocusedWindow().getHandle(); + whatsNew.setStartBrowsingCallback(() -> whatsNew.hide(UIWidget.REMOVE_WIDGET)); + whatsNew.setSignInCallback(() -> whatsNew.hide(UIWidget.REMOVE_WIDGET)); + whatsNew.show(UIWidget.REQUEST_FOCUS); + } } private void attachToWindow(@NonNull WindowWidget aWindow, @Nullable WindowWidget aPrevWindow) { diff --git a/app/src/common/shared/org/mozilla/vrbrowser/browser/Accounts.kt b/app/src/common/shared/org/mozilla/vrbrowser/browser/Accounts.kt index dff31c3c7..666f37092 100644 --- a/app/src/common/shared/org/mozilla/vrbrowser/browser/Accounts.kt +++ b/app/src/common/shared/org/mozilla/vrbrowser/browser/Accounts.kt @@ -40,6 +40,7 @@ class Accounts constructor(val context: Context) { BOOKMARKS, HISTORY, SETTINGS, + SEND_TABS, UNDEFINED } diff --git a/app/src/common/shared/org/mozilla/vrbrowser/browser/SettingsStore.java b/app/src/common/shared/org/mozilla/vrbrowser/browser/SettingsStore.java index a6a43269f..960ecc5b3 100644 --- a/app/src/common/shared/org/mozilla/vrbrowser/browser/SettingsStore.java +++ b/app/src/common/shared/org/mozilla/vrbrowser/browser/SettingsStore.java @@ -78,6 +78,7 @@ SettingsStore getInstance(final @NonNull Context aContext) { public final static boolean TELEMETRY_STATUS_UPDATE_SENT_DEFAULT = false; public final static boolean BOOKMARKS_SYNC_DEFAULT = true; public final static boolean HISTORY_SYNC_DEFAULT = true; + public final static boolean WHATS_NEW_DISPLAYED = false; // Enable telemetry by default (opt-out). public final static boolean CRASH_REPORTING_DEFAULT = false; @@ -623,5 +624,15 @@ public boolean isHistorySyncEnabled() { return mPrefs.getBoolean(mContext.getString(R.string.settings_key_history_sync), HISTORY_SYNC_DEFAULT); } + public void setWhatsNewDisplayed(boolean isEnabled) { + SharedPreferences.Editor editor = mPrefs.edit(); + editor.putBoolean(mContext.getString(R.string.settings_key_whats_new_displayed), isEnabled); + editor.commit(); + } + + public boolean isWhatsNewDisplayed() { + return mPrefs.getBoolean(mContext.getString(R.string.settings_key_whats_new_displayed), WHATS_NEW_DISPLAYED); + } + } diff --git a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/NavigationBarWidget.java b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/NavigationBarWidget.java index 1fed734f8..35ccd406a 100644 --- a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/NavigationBarWidget.java +++ b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/NavigationBarWidget.java @@ -20,12 +20,15 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import org.jetbrains.annotations.NotNull; import org.mozilla.geckoview.AllowOrDeny; import org.mozilla.geckoview.GeckoResult; import org.mozilla.geckoview.GeckoSession; import org.mozilla.geckoview.GeckoSessionSettings; import org.mozilla.vrbrowser.R; +import org.mozilla.vrbrowser.VRBrowserApplication; import org.mozilla.vrbrowser.audio.AudioEngine; +import org.mozilla.vrbrowser.browser.Accounts; import org.mozilla.vrbrowser.browser.Media; import org.mozilla.vrbrowser.browser.PromptDelegate; import org.mozilla.vrbrowser.browser.SessionChangeListener; @@ -40,6 +43,7 @@ import org.mozilla.vrbrowser.ui.widgets.dialogs.SelectionActionWidget; import org.mozilla.vrbrowser.ui.widgets.dialogs.SendTabDialogWidget; import org.mozilla.vrbrowser.ui.widgets.dialogs.VoiceSearchWidget; +import org.mozilla.vrbrowser.ui.widgets.dialogs.WhatsNewWidget; import org.mozilla.vrbrowser.ui.widgets.menus.BrightnessMenuWidget; import org.mozilla.vrbrowser.ui.widgets.menus.HamburgerMenuWidget; import org.mozilla.vrbrowser.ui.widgets.menus.VideoProjectionMenuWidget; @@ -51,6 +55,11 @@ import java.util.Arrays; import java.util.concurrent.atomic.AtomicBoolean; +import mozilla.components.concept.sync.AccountObserver; +import mozilla.components.concept.sync.AuthType; +import mozilla.components.concept.sync.OAuthAccount; +import mozilla.components.concept.sync.Profile; + public class NavigationBarWidget extends UIWidget implements GeckoSession.NavigationDelegate, GeckoSession.ProgressDelegate, GeckoSession.ContentDelegate, WidgetManagerDelegate.WorldClickListener, WidgetManagerDelegate.UpdateListener, SessionChangeListener, @@ -103,6 +112,7 @@ public class NavigationBarWidget extends UIWidget implements GeckoSession.Naviga private HamburgerMenuWidget mHamburgerMenu; private SendTabDialogWidget mSendTabDialog; private TooltipWidget mPopUpNotification; + protected Accounts mAccounts; public NavigationBarWidget(Context aContext) { super(aContext); @@ -123,6 +133,8 @@ private void initialize(@NonNull Context aContext) { mAppContext = aContext.getApplicationContext(); inflate(aContext, R.layout.navigation_bar, this); + mAccounts = ((VRBrowserApplication)getContext().getApplicationContext()).getAccounts(); + mAccounts.addAccountListener(mAccountObserver); mAudio = AudioEngine.fromContext(aContext); mBackButton = findViewById(R.id.backButton); mForwardButton = findViewById(R.id.forwardButton); @@ -351,6 +363,7 @@ public void onResume() { @Override public void releaseWidget() { + mAccounts.removeAccountListener(mAccountObserver); mWidgetManager.removeUpdateListener(this); mWidgetManager.removeWorldClickListener(this); mPrefs.unregisterOnSharedPreferenceChangeListener(this); @@ -1169,13 +1182,23 @@ private void hideMenu() { } public void showSendTabDialog() { - mSendTabDialog = new SendTabDialogWidget(getContext()); - mSendTabDialog.mWidgetPlacement.parentHandle = mAttachedWindow.getHandle(); - mSendTabDialog.setDelegate(() -> { - mSendTabDialog.releaseWidget(); - mSendTabDialog = null; - }); - mSendTabDialog.show(REQUEST_FOCUS); + if (mAccounts.isSignedIn()) { + mSendTabDialog = new SendTabDialogWidget(getContext()); + mSendTabDialog.mWidgetPlacement.parentHandle = mWidgetManager.getFocusedWindow().getHandle(); + mSendTabDialog.setDelegate(() -> { + mSendTabDialog.releaseWidget(); + mSendTabDialog = null; + show(REQUEST_FOCUS); + }); + mSendTabDialog.show(UIWidget.REQUEST_FOCUS); + + } else { + final WhatsNewWidget whatsNew = new WhatsNewWidget(getContext()); + whatsNew.getPlacement().parentHandle = mWidgetManager.getFocusedWindow().getHandle(); + whatsNew.setStartBrowsingCallback(() -> whatsNew.hide(UIWidget.REMOVE_WIDGET)); + whatsNew.setSignInCallback(() -> whatsNew.hide(UIWidget.REMOVE_WIDGET)); + whatsNew.show(UIWidget.REQUEST_FOCUS); + } } private PromptDelegate.PopUpDelegate mPopUpDelegate = new PromptDelegate.PopUpDelegate() { @@ -1227,4 +1250,28 @@ private void hideNotification(UIButton button) { } button.setNotificationMode(false); } + + private AccountObserver mAccountObserver = new AccountObserver() { + @Override + public void onLoggedOut() { + + } + + @Override + public void onAuthenticated(@NotNull OAuthAccount oAuthAccount, @NotNull AuthType authType) { + if (mAccounts.getLoginOrigin() == Accounts.LoginOrigin.SEND_TABS) { + showSendTabDialog(); + } + } + + @Override + public void onProfileUpdated(@NotNull Profile profile) { + + } + + @Override + public void onAuthenticationProblems() { + + } + }; } diff --git a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/TabsWidget.java b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/TabsWidget.java index 3b2961391..65e90aa2f 100644 --- a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/TabsWidget.java +++ b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/TabsWidget.java @@ -12,6 +12,8 @@ import androidx.recyclerview.widget.RecyclerView; import org.mozilla.vrbrowser.R; +import org.mozilla.vrbrowser.VRBrowserApplication; +import org.mozilla.vrbrowser.browser.Accounts; import org.mozilla.vrbrowser.browser.engine.Session; import org.mozilla.vrbrowser.browser.engine.SessionStore; import org.mozilla.vrbrowser.ui.views.TabView; @@ -19,6 +21,7 @@ import org.mozilla.vrbrowser.ui.views.UITextButton; import org.mozilla.vrbrowser.ui.widgets.dialogs.SendTabDialogWidget; import org.mozilla.vrbrowser.ui.widgets.dialogs.UIDialog; +import org.mozilla.vrbrowser.ui.widgets.dialogs.WhatsNewWidget; import org.mozilla.vrbrowser.utils.BitmapCache; import org.mozilla.vrbrowser.utils.ViewUtils; @@ -41,6 +44,7 @@ public class TabsWidget extends UIDialog implements WidgetManagerDelegate.WorldC protected UITextButton mUnselectTabs; protected LinearLayout mTabsSelectModeView; protected SendTabDialogWidget mSendTabDialog; + protected Accounts mAccounts; protected boolean mSelecting; protected ArrayList mSelectedTabs = new ArrayList<>(); @@ -74,6 +78,7 @@ protected void initializeWidgetPlacement(WidgetPlacement aPlacement) { private void initialize() { inflate(getContext(), R.layout.tabs, this); + mAccounts = ((VRBrowserApplication)getContext().getApplicationContext()).getAccounts(); mTabsList = findViewById(R.id.tabsRecyclerView); mTabsList.setHasFixedSize(true); final int columns = 4; @@ -276,14 +281,30 @@ public void onAdd(TabView aSender) { @Override public void onSend(TabView aSender) { hide(KEEP_WIDGET); - mSendTabDialog = new SendTabDialogWidget(getContext()); - mSendTabDialog.mWidgetPlacement.parentHandle = mWidgetManager.getFocusedWindow().getHandle(); - mSendTabDialog.setDelegate(() -> { - mSendTabDialog.releaseWidget(); - mSendTabDialog = null; - show(REQUEST_FOCUS); - }); - mSendTabDialog.show(UIWidget.REQUEST_FOCUS); + if (mAccounts.isSignedIn()) { + mSendTabDialog = new SendTabDialogWidget(getContext()); + mSendTabDialog.mWidgetPlacement.parentHandle = mWidgetManager.getFocusedWindow().getHandle(); + mSendTabDialog.setDelegate(() -> { + mSendTabDialog.releaseWidget(); + mSendTabDialog = null; + show(REQUEST_FOCUS); + }); + mSendTabDialog.show(UIWidget.REQUEST_FOCUS); + + } else { + final WhatsNewWidget whatsNew = new WhatsNewWidget(getContext()); + whatsNew.getPlacement().parentHandle = mWidgetManager.getFocusedWindow().getHandle(); + whatsNew.setStartBrowsingCallback(() -> { + whatsNew.hide(REMOVE_WIDGET); + show(REQUEST_FOCUS); + }); + whatsNew.setSignInCallback(() -> { + whatsNew.hide(REMOVE_WIDGET); + onDismiss(); + }); + whatsNew.setDelegate(() -> show(REQUEST_FOCUS)); + whatsNew.show(UIWidget.REQUEST_FOCUS); + } } }); } diff --git a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/dialogs/WhatsNewWidget.java b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/dialogs/WhatsNewWidget.java new file mode 100644 index 000000000..cfd2a0fee --- /dev/null +++ b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/dialogs/WhatsNewWidget.java @@ -0,0 +1,129 @@ +/* -*- Mode: Java; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: nil; -*- + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +package org.mozilla.vrbrowser.ui.widgets.dialogs; + +import android.annotation.SuppressLint; +import android.content.Context; +import android.util.AttributeSet; +import android.view.LayoutInflater; + +import androidx.annotation.NonNull; +import androidx.databinding.DataBindingUtil; + +import org.mozilla.geckoview.GeckoSessionSettings; +import org.mozilla.vrbrowser.R; +import org.mozilla.vrbrowser.VRBrowserApplication; +import org.mozilla.vrbrowser.browser.Accounts; +import org.mozilla.vrbrowser.browser.SettingsStore; +import org.mozilla.vrbrowser.databinding.WhatsNewBinding; +import org.mozilla.vrbrowser.ui.widgets.WidgetManagerDelegate; +import org.mozilla.vrbrowser.ui.widgets.WidgetPlacement; +import org.mozilla.vrbrowser.utils.UIThreadExecutor; + +public class WhatsNewWidget extends UIDialog implements WidgetManagerDelegate.WorldClickListener { + + private WhatsNewBinding mBinding; + private Accounts mAccounts; + private Runnable mSignInCallback; + private Runnable mStartBrowsingCallback; + + public WhatsNewWidget(Context aContext) { + super(aContext); + initialize(); + } + + public WhatsNewWidget(Context aContext, AttributeSet aAttrs) { + super(aContext, aAttrs); + initialize(); + } + + public WhatsNewWidget(Context aContext, AttributeSet aAttrs, int aDefStyle) { + super(aContext, aAttrs, aDefStyle); + initialize(); + } + + public void setSignInCallback(@NonNull Runnable callback) { + mSignInCallback = callback; + } + + public void setStartBrowsingCallback(@NonNull Runnable callback) { + mStartBrowsingCallback = callback; + } + + @SuppressLint("ClickableViewAccessibility") + private void initialize() { + LayoutInflater inflater = LayoutInflater.from(getContext()); + + mAccounts = ((VRBrowserApplication)getContext().getApplicationContext()).getAccounts(); + + // Inflate this data binding layout + mBinding = DataBindingUtil.inflate(inflater, R.layout.whats_new, this, true); + + mBinding.signInButton.setOnClickListener(v -> signIn()); + mBinding.startBrowsingButton.setOnClickListener((v) -> { + if (mStartBrowsingCallback != null) { + mStartBrowsingCallback.run(); + } + }); + } + + @Override + protected void initializeWidgetPlacement(WidgetPlacement aPlacement) { + aPlacement.visible = false; + aPlacement.width = WidgetPlacement.dpDimension(getContext(), R.dimen.whats_new_width); + aPlacement.height = WidgetPlacement.dpDimension(getContext(), R.dimen.whats_new_height); + aPlacement.parentAnchorX = 0.5f; + aPlacement.parentAnchorY = 0.0f; + aPlacement.anchorX = 0.5f; + aPlacement.anchorY = 0.5f; + aPlacement.translationY = WidgetPlacement.unitFromMeters(getContext(), R.dimen.settings_world_y) - + WidgetPlacement.unitFromMeters(getContext(), R.dimen.window_world_y); + aPlacement.translationZ = WidgetPlacement.unitFromMeters(getContext(), R.dimen.settings_world_z) - + WidgetPlacement.unitFromMeters(getContext(), R.dimen.window_world_z); + } + + @Override + public void show(@ShowFlags int aShowFlags) { + super.show(aShowFlags); + + mWidgetManager.addWorldClickListener(this); + mWidgetManager.pushWorldBrightness(this, WidgetManagerDelegate.DEFAULT_DIM_BRIGHTNESS); + } + + @Override + public void hide(@HideFlags int aHideFlags) { + super.hide(aHideFlags); + + SettingsStore.getInstance(getContext()).setWhatsNewDisplayed(true); + + mWidgetManager.popWorldBrightness(this); + mWidgetManager.removeWorldClickListener(this); + } + + private void signIn() { + mAccounts.getAuthenticationUrlAsync().thenAcceptAsync((url) -> { + if (url != null) { + mAccounts.setLoginOrigin(Accounts.LoginOrigin.SEND_TABS); + mWidgetManager.openNewTabForeground(url); + mWidgetManager.getFocusedWindow().getSession().setUaMode(GeckoSessionSettings.USER_AGENT_MODE_VR); + mWidgetManager.getFocusedWindow().getSession().loadUri(url); + } + + if (mSignInCallback != null) { + mSignInCallback.run(); + } + + }, new UIThreadExecutor()); + } + + // WidgetManagerDelegate.WorldClickListener + + @Override + public void onWorldClick() { + onDismiss(); + } + +} diff --git a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/settings/ContentLanguageOptionsView.java b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/settings/ContentLanguageOptionsView.java index e68c56e7c..ceec75edb 100644 --- a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/settings/ContentLanguageOptionsView.java +++ b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/settings/ContentLanguageOptionsView.java @@ -26,7 +26,7 @@ import java.util.Arrays; -class ContentLanguageOptionsView extends SettingsView { +public class ContentLanguageOptionsView extends SettingsView { private OptionsLanguageContentBinding mBinding; private LanguagesAdapter mPreferredAdapter; diff --git a/app/src/main/res/drawable/ic_asset_image_accounts.xml b/app/src/main/res/drawable/ic_asset_image_accounts.xml new file mode 100644 index 000000000..f723fbfa7 --- /dev/null +++ b/app/src/main/res/drawable/ic_asset_image_accounts.xml @@ -0,0 +1,292 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/whats_new.xml b/app/src/main/res/layout/whats_new.xml new file mode 100644 index 000000000..08bc20a96 --- /dev/null +++ b/app/src/main/res/layout/whats_new.xml @@ -0,0 +1,104 @@ + + + + + + + + + + + + + + + + + + +