From 808b6515f5d0c77ed232f2e77a89c55012c18eda Mon Sep 17 00:00:00 2001 From: haanhvu Date: Tue, 21 Jan 2025 21:19:41 +0700 Subject: [PATCH] First step for #1318: Create initial New Tab page that has Wolvic logo and add an option in Display Settings to set New Tab page as homepage This should be released when all the steps have been done and #1318 is closed. --- .../wolvic/ui/viewmodel/WindowViewModel.java | 63 +++++++++++- .../igalia/wolvic/ui/views/NewTabView.java | 42 ++++++++ .../wolvic/ui/views/library/LibraryPanel.java | 1 + .../ui/widgets/NavigationBarWidget.java | 22 ++++- .../igalia/wolvic/ui/widgets/TrayWidget.java | 2 +- .../wolvic/ui/widgets/WindowWidget.java | 99 +++++++++++++++---- .../com/igalia/wolvic/ui/widgets/Windows.java | 30 +++++- .../widgets/settings/DisplayOptionsView.java | 52 +++++++++- .../ui/widgets/settings/SettingsWidget.java | 2 +- .../com/igalia/wolvic/utils/UrlUtils.java | 8 +- .../res/layout/navigation_bar_navigation.xml | 6 +- app/src/main/res/layout/new_tab.xml | 18 ++++ app/src/main/res/layout/options_display.xml | 11 ++- app/src/main/res/layout/tray.xml | 2 +- app/src/main/res/values/options_values.xml | 6 ++ app/src/main/res/values/strings.xml | 12 +++ 16 files changed, 333 insertions(+), 43 deletions(-) create mode 100644 app/src/common/shared/com/igalia/wolvic/ui/views/NewTabView.java create mode 100644 app/src/main/res/layout/new_tab.xml diff --git a/app/src/common/shared/com/igalia/wolvic/ui/viewmodel/WindowViewModel.java b/app/src/common/shared/com/igalia/wolvic/ui/viewmodel/WindowViewModel.java index 19523a5041..5423afe6d3 100644 --- a/app/src/common/shared/com/igalia/wolvic/ui/viewmodel/WindowViewModel.java +++ b/app/src/common/shared/com/igalia/wolvic/ui/viewmodel/WindowViewModel.java @@ -37,6 +37,7 @@ public class WindowViewModel extends AndroidViewModel { private int mURLWebsiteColor; private MutableLiveData url; + private MutableLiveData urlForwardFromNewTab; private MutableLiveData hint; private MutableLiveData isWindowVisible; private MutableLiveData placement; @@ -54,7 +55,9 @@ public class WindowViewModel extends AndroidViewModel { private MutableLiveData isActiveWindow; private MediatorLiveData isTitleBarVisible; private MutableLiveData currentContentType; + public MutableLiveData lastContentType; private MediatorLiveData isNativeContentVisible; + private MutableLiveData backToNewTabEnabled; private MutableLiveData isLoading; private MutableLiveData isMicrophoneEnabled; private MutableLiveData isBookmarked; @@ -65,6 +68,7 @@ public class WindowViewModel extends AndroidViewModel { private MutableLiveData isPopUpAvailable; private MutableLiveData isPopUpBlocked; private MutableLiveData canGoForward; + private MutableLiveData canGoForwardFromNewTab; private MutableLiveData canGoBack; private MutableLiveData isInVRVideo; private MutableLiveData autoEnteredVRVideo; @@ -93,6 +97,7 @@ public WindowViewModel(Application application) { mURLWebsiteColor = typedValue.data; url = new MutableLiveData<>(new SpannableString("")); + urlForwardFromNewTab = new MutableLiveData<>(new SpannableString("")); hint = new MutableLiveData<>(""); isWindowVisible = new MutableLiveData<>(new ObservableBoolean(true)); placement = new MutableLiveData<>(Windows.WindowPlacement.FRONT); @@ -135,11 +140,15 @@ public WindowViewModel(Application application) { isTitleBarVisible.setValue(new ObservableBoolean(true)); currentContentType = new MutableLiveData<>(Windows.ContentType.WEB_CONTENT); + lastContentType = new MutableLiveData<>(Windows.ContentType.WEB_CONTENT); + isNativeContentVisible = new MediatorLiveData<>(); isNativeContentVisible.addSource(currentContentType, contentType -> isNativeContentVisible.setValue(new ObservableBoolean(contentType != Windows.ContentType.WEB_CONTENT)) ); - isNativeContentVisible.setValue(new ObservableBoolean(currentContentType.getValue() != Windows.ContentType.WEB_CONTENT)); + isNativeContentVisible.setValue(new ObservableBoolean(currentContentType.getValue() != Windows.ContentType.WEB_CONTENT && currentContentType.getValue() != Windows.ContentType.NEW_TAB)); + + backToNewTabEnabled = new MutableLiveData<>(new ObservableBoolean(false)); isLoading = new MutableLiveData<>(new ObservableBoolean(false)); isMicrophoneEnabled = new MutableLiveData<>(new ObservableBoolean(true)); @@ -151,6 +160,7 @@ public WindowViewModel(Application application) { isPopUpAvailable = new MutableLiveData<>(new ObservableBoolean(false)); isPopUpBlocked = new MutableLiveData<>(new ObservableBoolean(false)); canGoForward = new MutableLiveData<>(new ObservableBoolean(false)); + canGoForwardFromNewTab = new MutableLiveData<>(new ObservableBoolean(false)); canGoBack = new MutableLiveData<>(new ObservableBoolean(false)); isInVRVideo = new MutableLiveData<>(new ObservableBoolean(false)); autoEnteredVRVideo = new MutableLiveData<>(new ObservableBoolean(false)); @@ -260,9 +270,12 @@ public void onChanged(ObservableBoolean o) { @Override public void onChanged(Spannable aUrl) { String url = aUrl.toString(); - if (isNativeContentVisible.getValue().get()) { + if (isNativeContentVisible.getValue().get() && currentContentType.getValue() != Windows.ContentType.NEW_TAB) { url = getApplication().getString(R.string.url_library_title); + } else if (currentContentType.getValue() == Windows.ContentType.NEW_TAB) { + url = getApplication().getString(R.string.url_new_tab_title); + } else { if (UrlUtils.isPrivateAboutPage(getApplication(), url) || (UrlUtils.isDataUri(url) && isPrivateSession.getValue().get())) { @@ -357,6 +370,7 @@ public void onChanged(ObservableBoolean o) { public void refresh() { url.postValue(url.getValue()); + urlForwardFromNewTab.postValue(urlForwardFromNewTab.getValue()); hint.postValue(getHintValue()); isWindowVisible.postValue(isWindowVisible.getValue()); placement.postValue(placement.getValue()); @@ -373,6 +387,7 @@ public void refresh() { isPopUpAvailable.postValue(isPopUpAvailable.getValue()); isPopUpBlocked.postValue(isPopUpBlocked.getValue()); canGoForward.postValue(canGoForward.getValue()); + canGoForwardFromNewTab.postValue(canGoForwardFromNewTab.getValue()); canGoBack.postValue(canGoBack.getValue()); isInVRVideo.postValue(isInVRVideo.getValue()); autoEnteredVRVideo.postValue(autoEnteredVRVideo.getValue()); @@ -395,10 +410,18 @@ public MutableLiveData getUrl() { return url; } + public MutableLiveData getUrlForwardFromNewTab() { + if (urlForwardFromNewTab == null) { + urlForwardFromNewTab = new MutableLiveData<>(new SpannableString("")); + } + return urlForwardFromNewTab; + } + public void setUrl(@Nullable String url) { if (url == null) { return; } + setUrl(new SpannableString(url)); } @@ -442,9 +465,17 @@ private void setUrl(@Nullable Spannable url) { spannable.setSpan(color1, 0, index + 3, 0); spannable.setSpan(color2, index + 3, aURL.length(), 0); this.url.postValue(spannable); + //TODO: Allow other about links outside of library + if (currentContentType.getValue() == Windows.ContentType.WEB_CONTENT && lastContentType.getValue() == Windows.ContentType.NEW_TAB && !aURL.startsWith("about")) { + urlForwardFromNewTab.postValue(spannable); + } } else { this.url.postValue(url); + //TODO: Allow other about links outside of library + if (currentContentType.getValue() == Windows.ContentType.WEB_CONTENT && lastContentType.getValue() == Windows.ContentType.NEW_TAB && !aURL.startsWith("about")) { + urlForwardFromNewTab.postValue(url); + } } } } @@ -455,9 +486,12 @@ public MutableLiveData getHint() { } private String getHintValue() { - if (isNativeContentVisible.getValue().get()) { + if (isNativeContentVisible.getValue().get() && currentContentType.getValue() != Windows.ContentType.NEW_TAB) { return getApplication().getString(R.string.url_library_title); + } else if (currentContentType.getValue() == Windows.ContentType.NEW_TAB) { + return getApplication().getString(R.string.url_new_tab_title); + } else { return getApplication().getString(R.string.search_placeholder); } @@ -597,6 +631,11 @@ public void setIsActiveWindow(boolean isActiveWindow) { } public void setCurrentContentType(Windows.ContentType contentType) { + // No need to store lastContentType when we switch content types in library + if (!currentContentType.getValue().isLibraryContent() || !contentType.isLibraryContent()) { + lastContentType.postValue(currentContentType.getValue()); + } + currentContentType.postValue(contentType); } @@ -609,6 +648,15 @@ public MutableLiveData getIsNativeContentVisible() { return isNativeContentVisible; } + public void enableBackToNewTab(boolean backToNewTabEnabled) { + this.backToNewTabEnabled.postValue(new ObservableBoolean(backToNewTabEnabled)); + } + + @NonNull + public MutableLiveData getBackToNewTabEnabled() { + return backToNewTabEnabled; + } + @NonNull public MutableLiveData getIsLoading() { return isLoading; @@ -699,6 +747,15 @@ public void setCanGoForward(boolean canGoForward) { this.canGoForward.postValue(new ObservableBoolean(canGoForward)); } + @NonNull + public MutableLiveData getCanGoForwardFromNewTab() { + return canGoForwardFromNewTab; + } + + public void setCanGoForwardFromNewTab(boolean canGoForwardFromNewTab) { + this.canGoForwardFromNewTab.postValue(new ObservableBoolean(canGoForwardFromNewTab)); + } + @NonNull public MutableLiveData getCanGoBack() { return canGoBack; diff --git a/app/src/common/shared/com/igalia/wolvic/ui/views/NewTabView.java b/app/src/common/shared/com/igalia/wolvic/ui/views/NewTabView.java new file mode 100644 index 0000000000..3bedd8eca0 --- /dev/null +++ b/app/src/common/shared/com/igalia/wolvic/ui/views/NewTabView.java @@ -0,0 +1,42 @@ +package com.igalia.wolvic.ui.views; + +import android.annotation.SuppressLint; +import android.content.Context; +import android.view.LayoutInflater; +import android.widget.FrameLayout; + +import androidx.databinding.DataBindingUtil; + +import com.igalia.wolvic.R; +import com.igalia.wolvic.VRBrowserActivity; +import com.igalia.wolvic.databinding.NewTabBinding; +import com.igalia.wolvic.ui.widgets.WidgetManagerDelegate; + +public class NewTabView extends FrameLayout { + + private WidgetManagerDelegate mWidgetManager; + + private NewTabBinding mBinding; + + public NewTabView(Context context) { + super(context); + initialize(); + } + + protected void initialize() { + mWidgetManager = ((VRBrowserActivity) getContext()); + updateUI(); + } + + @SuppressLint("ClickableViewAccessibility") + public void updateUI() { + removeAllViews(); + + LayoutInflater inflater = LayoutInflater.from(getContext()); + + mBinding = DataBindingUtil.inflate(inflater, R.layout.new_tab, this, true); + mBinding.setLifecycleOwner((VRBrowserActivity)getContext()); + + mBinding.executePendingBindings(); + } +} \ No newline at end of file diff --git a/app/src/common/shared/com/igalia/wolvic/ui/views/library/LibraryPanel.java b/app/src/common/shared/com/igalia/wolvic/ui/views/library/LibraryPanel.java index 86c293a32d..c0e62b15d0 100644 --- a/app/src/common/shared/com/igalia/wolvic/ui/views/library/LibraryPanel.java +++ b/app/src/common/shared/com/igalia/wolvic/ui/views/library/LibraryPanel.java @@ -189,6 +189,7 @@ public void setController(Controller controller) { mController = controller; } + @NonNull public Windows.ContentType getSelectedPanelType() { if (mCurrentView == mBookmarksView) { return Windows.ContentType.BOOKMARKS; diff --git a/app/src/common/shared/com/igalia/wolvic/ui/widgets/NavigationBarWidget.java b/app/src/common/shared/com/igalia/wolvic/ui/widgets/NavigationBarWidget.java index 9c97234493..337ae31b94 100644 --- a/app/src/common/shared/com/igalia/wolvic/ui/widgets/NavigationBarWidget.java +++ b/app/src/common/shared/com/igalia/wolvic/ui/widgets/NavigationBarWidget.java @@ -247,6 +247,8 @@ private void updateUI() { if (getSession().canGoBack()) { getSession().goBack(); + } else if (mViewModel.getBackToNewTabEnabled().getValue().get()) { + getSession().loadUri(UrlUtils.ABOUT_NEWTAB); } if (mAudio != null) { @@ -257,7 +259,18 @@ private void updateUI() { mBinding.navigationBarNavigation.forwardButton.setOnClickListener(v -> { v.requestFocusFromTouch(); - getSession().goForward(); + if (mViewModel.getCanGoForwardFromNewTab().getValue().get()) { + String forwardUrl = mViewModel.getUrlForwardFromNewTab().getValue().toString(); + getSession().loadUri(forwardUrl); + + mAttachedWindow.hideNewTab(true); + + mViewModel.setCurrentContentType(Windows.ContentType.WEB_CONTENT); + mViewModel.setUrl(forwardUrl); + mViewModel.setCanGoForwardFromNewTab(false); + } else { + getSession().goForward(); + } if (mAudio != null) { mAudio.playSound(AudioEngine.Sound.CLICK); } @@ -1024,7 +1037,10 @@ public void onLocationChange(@NonNull WSession session, @Nullable String url) { updateTrackingProtection(); } - mBinding.navigationBarNavigation.reloadButton.setEnabled(!UrlUtils.isPrivateAboutPage(getContext(), url)); + mBinding.navigationBarNavigation.reloadButton.setEnabled( + mViewModel.getCurrentContentType().getValue() != Windows.ContentType.NEW_TAB + && !mViewModel.getIsNativeContentVisible().getValue().get() + && !UrlUtils.isPrivateAboutPage(getContext(), url)); } // Content delegate @@ -1390,7 +1406,7 @@ public void onSwitchMode() { public void onAddons() { hideMenu(); - mAttachedWindow.showPanel(Windows.ContentType.ADDONS); + mAttachedWindow.showLibraryPanel(Windows.ContentType.ADDONS); } @Override diff --git a/app/src/common/shared/com/igalia/wolvic/ui/widgets/TrayWidget.java b/app/src/common/shared/com/igalia/wolvic/ui/widgets/TrayWidget.java index 4b9c718c5a..becdde98e9 100644 --- a/app/src/common/shared/com/igalia/wolvic/ui/widgets/TrayWidget.java +++ b/app/src/common/shared/com/igalia/wolvic/ui/widgets/TrayWidget.java @@ -623,7 +623,7 @@ public void attachToWindow(@NonNull WindowWidget aWindow) { mBinding.bookmarksButton.setActiveMode(contentType != Windows.ContentType.WEB_CONTENT && contentType != Windows.ContentType.DOWNLOADS); mBinding.downloadsButton.setActiveMode(contentType == Windows.ContentType.DOWNLOADS); - if (contentType == Windows.ContentType.WEB_CONTENT) { + if (contentType == Windows.ContentType.WEB_CONTENT || contentType == Windows.ContentType.NEW_TAB) { animateButtonPadding(mBinding.bookmarksButton, mMaxPadding, ICON_ANIMATION_DURATION); animateButtonPadding(mBinding.downloadsButton, mMaxPadding, ICON_ANIMATION_DURATION); } else if (contentType == Windows.ContentType.DOWNLOADS) { diff --git a/app/src/common/shared/com/igalia/wolvic/ui/widgets/WindowWidget.java b/app/src/common/shared/com/igalia/wolvic/ui/widgets/WindowWidget.java index 33d45dbddf..0aa231fc11 100644 --- a/app/src/common/shared/com/igalia/wolvic/ui/widgets/WindowWidget.java +++ b/app/src/common/shared/com/igalia/wolvic/ui/widgets/WindowWidget.java @@ -62,6 +62,7 @@ import com.igalia.wolvic.telemetry.TelemetryService; import com.igalia.wolvic.ui.adapters.WebApp; import com.igalia.wolvic.ui.viewmodel.WindowViewModel; +import com.igalia.wolvic.ui.views.NewTabView; import com.igalia.wolvic.ui.views.library.LibraryPanel; import com.igalia.wolvic.ui.widgets.dialogs.PromptDialogWidget; import com.igalia.wolvic.ui.widgets.dialogs.SelectionActionWidget; @@ -134,6 +135,7 @@ public class WindowWidget extends UIWidget implements SessionChangeListener, private Session mSession; private int mWindowId; private LibraryPanel mLibrary; + private NewTabView mNewTab; private Windows.WindowPlacement mWindowPlacement = Windows.WindowPlacement.FRONT; private Windows.WindowPlacement mWindowPlacementBeforeFullscreen = Windows.WindowPlacement.FRONT; private float mMaxWindowScale = 3; @@ -217,7 +219,9 @@ private void initialize(Context aContext) { setupListeners(mSession); mLibrary = new LibraryPanel(aContext); - mLibrary.setController(this::showPanel); + mLibrary.setController(this::showLibraryPanel); + + mNewTab = new NewTabView(aContext); SessionStore.get().getBookmarkStore().addListener(mBookmarksListener); @@ -502,31 +506,30 @@ public int getWindowHeight() { return mWidgetPlacement.height; } + @NonNull public Windows.ContentType getSelectedPanel() { return mLibrary.getSelectedPanelType(); } private void hideLibraryPanel() { - if (mViewModel.getIsNativeContentVisible().getValue().get()) { + if (getCurrentContentType().isLibraryContent()) { hidePanel(true); } } Runnable mRestoreFirstPaint; - public void showPanel(Windows.ContentType panelType) { - if (panelType == Windows.ContentType.WEB_CONTENT) { - hidePanel(); - } else { - showPanel(panelType, true); - } + public void showLibraryPanel(Windows.ContentType panelType) { + assert panelType != Windows.ContentType.NEW_TAB && panelType != Windows.ContentType.WEB_CONTENT && panelType != Windows.ContentType.NOTIFICATIONS; + showLibraryPanel(panelType, true); } - private void showPanel(Windows.ContentType contentType, boolean switchSurface) { + private void showLibraryPanel(Windows.ContentType contentType, boolean switchSurface) { if (mLibrary == null) { return; } + hideNewTab(false); mViewModel.setIsFindInPage(false); mViewModel.setCurrentContentType(contentType); mViewModel.setUrl(contentType.URL); @@ -534,12 +537,14 @@ private void showPanel(Windows.ContentType contentType, boolean switchSurface) { setView(mLibrary, switchSurface); mLibrary.selectPanel(contentType); mLibrary.onShow(); - if (mRestoreFirstPaint == null && !isFirstPaintReady() && (mFirstDrawCallback != null) && (mSurface != null)) { - final Runnable firstDrawCallback = mFirstDrawCallback; + if (mRestoreFirstPaint == null) { onFirstContentfulPaint(mSession.getWSession()); mRestoreFirstPaint = () -> { setFirstPaintReady(false); - setFirstDrawCallback(firstDrawCallback); + if (mFirstDrawCallback != null) { + final Runnable firstDrawCallback = mFirstDrawCallback; + setFirstDrawCallback(firstDrawCallback); + } if (mWidgetManager != null) { mWidgetManager.updateWidget(WindowWidget.this); } @@ -550,6 +555,32 @@ private void showPanel(Windows.ContentType contentType, boolean switchSurface) { } } + public void showNewTab() { + if (mNewTab != null) { + mViewModel.setIsFindInPage(false); + mViewModel.setCurrentContentType(Windows.ContentType.NEW_TAB); + mViewModel.setUrl(Windows.ContentType.NEW_TAB.URL); + setView(mNewTab, true); + if (mRestoreFirstPaint == null) { + onFirstContentfulPaint(mSession.getWSession()); + mRestoreFirstPaint = () -> { + setFirstPaintReady(false); + if (mFirstDrawCallback != null) { + final Runnable firstDrawCallback = mFirstDrawCallback; + setFirstDrawCallback(firstDrawCallback); + } + if (mWidgetManager != null) { + mWidgetManager.updateWidget(WindowWidget.this); + } + }; + } + } + if (mViewModel.getBackToNewTabEnabled().getValue().get()) { + mViewModel.enableBackToNewTab(false); + mViewModel.setCanGoForwardFromNewTab(true); + } + } + public void hidePanel() { hidePanel(true); } @@ -558,12 +589,33 @@ private void hidePanel(boolean switchSurface) { if (mView != null && mLibrary != null) { unsetView(mLibrary, switchSurface); mLibrary.onHide(); - mViewModel.setCurrentContentType(Windows.ContentType.WEB_CONTENT); } if (switchSurface && mRestoreFirstPaint != null) { mRestoreFirstPaint.run(); mRestoreFirstPaint = null; } + if (mViewModel.lastContentType.getValue() == Windows.ContentType.NEW_TAB) { + showNewTab(); + } else { + mViewModel.setCurrentContentType(Windows.ContentType.WEB_CONTENT); + } + } + + public void hideNewTab(boolean enableBackToNewTab) { + if (mViewModel.getCurrentContentType().getValue() == Windows.ContentType.NEW_TAB) { + mViewModel.enableBackToNewTab(enableBackToNewTab); + hideNewTab(); + } + } + + private void hideNewTab() { + if (mView != null && mNewTab != null) { + unsetView(mNewTab, true); + } + if (mRestoreFirstPaint != null) { + mRestoreFirstPaint.run(); + mRestoreFirstPaint = null; + } } public void pauseCompositor() { @@ -2010,24 +2062,31 @@ WResult onLoadRequest(WSession aSession, @NonNull LoadRequest aReq Uri uri = Uri.parse(aRequest.uri); if (UrlUtils.isAboutPage(uri.toString())) { - if(UrlUtils.isBookmarksUrl(uri.toString())) { - showPanel(Windows.ContentType.BOOKMARKS); + if(UrlUtils.isBookmarksUrl(uri.toString())) { + showLibraryPanel(Windows.ContentType.BOOKMARKS); } else if (UrlUtils.isHistoryUrl(uri.toString())) { - showPanel(Windows.ContentType.HISTORY); + showLibraryPanel(Windows.ContentType.HISTORY); } else if (UrlUtils.isDownloadsUrl(uri.toString())) { - showPanel(Windows.ContentType.DOWNLOADS); + showLibraryPanel(Windows.ContentType.DOWNLOADS); } else if (UrlUtils.isAddonsUrl(uri.toString())) { - showPanel(Windows.ContentType.ADDONS); + showLibraryPanel(Windows.ContentType.ADDONS); + + } else if (UrlUtils.isNewTabUrl(uri.toString())) { + showNewTab(); } else { - hideLibraryPanel(); - } + hideLibraryPanel(); + hideNewTab(true); + } } else { hideLibraryPanel(); + hideNewTab(true); + mViewModel.setCurrentContentType(Windows.ContentType.WEB_CONTENT); + mViewModel.setUrl(uri.toString()); } if ("file".equalsIgnoreCase(uri.getScheme())) { diff --git a/app/src/common/shared/com/igalia/wolvic/ui/widgets/Windows.java b/app/src/common/shared/com/igalia/wolvic/ui/widgets/Windows.java index e144edf937..2d20ad9d9b 100644 --- a/app/src/common/shared/com/igalia/wolvic/ui/widgets/Windows.java +++ b/app/src/common/shared/com/igalia/wolvic/ui/widgets/Windows.java @@ -98,6 +98,7 @@ class WindowState { int textureHeight; float worldWidth; int tabIndex = -1; + // NOTE: Enum values may be null when deserialized by GSON. ContentType contentType = ContentType.WEB_CONTENT; @@ -120,7 +121,8 @@ public void load(@NonNull WindowWidget aWindow, WindowsState aState, int aTabInd tabIndex = aTabIndex; if (aWindow.isNativeContentVisible()) { contentType = aWindow.getSelectedPanel(); - + } else if (aWindow.getCurrentContentType() == ContentType.NEW_TAB) { + contentType = ContentType.NEW_TAB; } else { contentType = ContentType.WEB_CONTENT; } @@ -171,13 +173,28 @@ public enum ContentType { HISTORY(UrlUtils.ABOUT_HISTORY), DOWNLOADS(UrlUtils.ABOUT_DOWNLOADS), ADDONS(UrlUtils.ABOUT_ADDONS), - NOTIFICATIONS(UrlUtils.ABOUT_NOTIFICATIONS); + NOTIFICATIONS(UrlUtils.ABOUT_NOTIFICATIONS), + NEW_TAB(UrlUtils.ABOUT_NEWTAB); @NonNull public final String URL; + ContentType(@NonNull String url) { this.URL = url; } + + public boolean isLibraryContent() { + switch (this) { + case BOOKMARKS: + case WEB_APPS: + case HISTORY: + case DOWNLOADS: + case ADDONS: + return true; + default: + return false; + } + }; } public enum WindowPlacement{ @@ -389,6 +406,9 @@ private WindowWidget addRestoredWindow(@NonNull WindowState aState, @Nullable Se case ADDONS: newWindow.getSession().loadUri(UrlUtils.ABOUT_ADDONS); break; + case NEW_TAB: + newWindow.getSession().loadUri(UrlUtils.ABOUT_NEWTAB); + break; case WEB_CONTENT: break; } @@ -637,7 +657,7 @@ public void exitImmersiveMode() { } private void closeLibraryPanelInFocusedWindowIfNeeded() { - if (!mFocusedWindow.isNativeContentVisible()) + if (!mFocusedWindow.getCurrentContentType().isLibraryContent()) return; mFocusedWindow.hidePanel(); } @@ -1229,7 +1249,7 @@ public void onBookmarksClicked() { if (mFocusedWindow.getCurrentContentType() == ContentType.BOOKMARKS) { mFocusedWindow.hidePanel(); } else { - mFocusedWindow.showPanel(ContentType.BOOKMARKS); + mFocusedWindow.showLibraryPanel(ContentType.BOOKMARKS); } } @@ -1238,7 +1258,7 @@ public void onDownloadsClicked() { if (mFocusedWindow.getCurrentContentType() == ContentType.DOWNLOADS) { mFocusedWindow.hidePanel(); } else { - mFocusedWindow.showPanel(ContentType.DOWNLOADS); + mFocusedWindow.showLibraryPanel(ContentType.DOWNLOADS); } } diff --git a/app/src/common/shared/com/igalia/wolvic/ui/widgets/settings/DisplayOptionsView.java b/app/src/common/shared/com/igalia/wolvic/ui/widgets/settings/DisplayOptionsView.java index fd80c0f400..89a15bd5de 100644 --- a/app/src/common/shared/com/igalia/wolvic/ui/widgets/settings/DisplayOptionsView.java +++ b/app/src/common/shared/com/igalia/wolvic/ui/widgets/settings/DisplayOptionsView.java @@ -20,6 +20,9 @@ import com.igalia.wolvic.ui.views.settings.SwitchSetting; import com.igalia.wolvic.ui.widgets.WidgetManagerDelegate; import com.igalia.wolvic.ui.widgets.WidgetPlacement; +import com.igalia.wolvic.utils.UrlUtils; + +import java.util.Objects; import java.util.ArrayList; import java.util.List; @@ -85,6 +88,10 @@ protected void updateUI() { SettingsStore.WindowSizePreset windowSizePreset = SettingsStore.WindowSizePreset.fromValues(windowWidth, windowHeight); setWindowsSizePreset(windowSizePreset.ordinal(), false); + int homepageId = getHomepageId(SettingsStore.getInstance(getContext()).getHomepage()); + mBinding.homepage.setOnCheckedChangeListener(mHomepageChangeListener); + setHomepage(homepageId, false); + mBinding.autoplaySwitch.setOnCheckedChangeListener(mAutoplayListener); setAutoplay(SettingsStore.getInstance(getContext()).isAutoplayEnabled(), false); @@ -180,6 +187,10 @@ public boolean isEditing() { setWindowsSizePreset(checkedId, true); }; + private RadioGroupSetting.OnCheckedChangeListener mHomepageChangeListener = (radioGroup, checkedId, doApply) -> { + setHomepage(checkedId, true); + }; + private SwitchSetting.OnCheckedChangeListener mAutoplayListener = (compoundButton, enabled, apply) -> { setAutoplay(enabled, true); }; @@ -266,6 +277,11 @@ public boolean isEditing() { if (mBinding.windowsSize.getCheckedRadioButtonId() != SettingsStore.WINDOW_SIZE_PRESET_DEFAULT.ordinal()) { setWindowsSizePreset(SettingsStore.WINDOW_SIZE_PRESET_DEFAULT.ordinal(), true); } + + int defaultHomepageId = getHomepageId(mDefaultHomepageUrl); + if (mBinding.homepage.getCheckedRadioButtonId() != defaultHomepageId) { + setHomepage(defaultHomepageId, true); + } float prevDensity = SettingsStore.getInstance(getContext()).getDisplayDensity(); restart = restart | setDisplayDensity(SettingsStore.DISPLAY_DENSITY_DEFAULT); @@ -367,11 +383,39 @@ private void setTabsLocation(int checkedId, boolean doApply) { } } + private void setHomepage(int checkedId, boolean doApply) { + mBinding.homepage.setOnCheckedChangeListener(null); + mBinding.homepage.setChecked(checkedId, doApply); + mBinding.homepage.setOnCheckedChangeListener(mHomepageChangeListener); + + if (checkedId == 0) { + mBinding.homepageEdit.setVisibility(View.GONE); + SettingsStore.getInstance(getContext()).setHomepage(UrlUtils.ABOUT_NEWTAB); + } else if (checkedId == 1) { + mBinding.homepageEdit.setVisibility(View.GONE); + SettingsStore.getInstance(getContext()).setHomepage(mDefaultHomepageUrl); + } else if (checkedId == 2) { + mBinding.homepageEdit.setVisibility(View.VISIBLE); + } + } + + private int getHomepageId(String homepage) { + if (Objects.equals(homepage, UrlUtils.ABOUT_NEWTAB)) { + return 0; + } else if (Objects.equals(homepage, getContext().getString(R.string.HOMEPAGE_URL))) { + return 1; + } else { + return 2; + } + } + private void setHomepage(String newHomepage) { - mBinding.homepageEdit.setOnClickListener(null); - mBinding.homepageEdit.setFirstText(newHomepage); - SettingsStore.getInstance(getContext()).setHomepage(newHomepage); - mBinding.homepageEdit.setOnClickListener(mHomepageListener); + if (mBinding.homepageEdit.getVisibility() == VISIBLE) { + mBinding.homepageEdit.setOnClickListener(null); + mBinding.homepageEdit.setFirstText(newHomepage); + SettingsStore.getInstance(getContext()).setHomepage(newHomepage); + mBinding.homepageEdit.setOnClickListener(mHomepageListener); + } } private void setWindowDistance(float value, boolean doApply) { diff --git a/app/src/common/shared/com/igalia/wolvic/ui/widgets/settings/SettingsWidget.java b/app/src/common/shared/com/igalia/wolvic/ui/widgets/settings/SettingsWidget.java index 612dfa214c..830d042776 100644 --- a/app/src/common/shared/com/igalia/wolvic/ui/widgets/settings/SettingsWidget.java +++ b/app/src/common/shared/com/igalia/wolvic/ui/widgets/settings/SettingsWidget.java @@ -219,7 +219,7 @@ public void updateUI() { if (mAudio != null) { mAudio.playSound(AudioEngine.Sound.CLICK); } - mWidgetManager.getFocusedWindow().showPanel(Windows.ContentType.ADDONS); + mWidgetManager.getFocusedWindow().showLibraryPanel(Windows.ContentType.ADDONS); onDismiss(); }); diff --git a/app/src/common/shared/com/igalia/wolvic/utils/UrlUtils.java b/app/src/common/shared/com/igalia/wolvic/utils/UrlUtils.java index 9b496b2ab6..6ceedac1ad 100644 --- a/app/src/common/shared/com/igalia/wolvic/utils/UrlUtils.java +++ b/app/src/common/shared/com/igalia/wolvic/utils/UrlUtils.java @@ -188,6 +188,12 @@ public static boolean isBookmarksUrl(@Nullable String url) { return url != null && url.equalsIgnoreCase(ABOUT_BOOKMARKS); } + public static final String ABOUT_NEWTAB = "about://newtab"; + + public static boolean isNewTabUrl(@Nullable String url) { + return url != null && url.equalsIgnoreCase(ABOUT_NEWTAB); + } + public static final String ABOUT_DOWNLOADS = "about://downloads"; public static boolean isDownloadsUrl(@Nullable String url) { @@ -246,7 +252,7 @@ public static boolean isPrivateUrl(@Nullable String url) { public static boolean isAboutPage(@Nullable String url) { return isHistoryUrl(url) || isBookmarksUrl(url) || isDownloadsUrl(url) || isAddonsUrl(url) || - isWebAppsUrl(url) || isNotificationsUrl(url) || isPrivateUrl(url); + isWebAppsUrl(url) || isNotificationsUrl(url) || isPrivateUrl(url) || isNewTabUrl(url); } public static boolean isContentFeed(Context aContext, @Nullable String url) { diff --git a/app/src/main/res/layout/navigation_bar_navigation.xml b/app/src/main/res/layout/navigation_bar_navigation.xml index 79497e28b6..500b3c6ad4 100644 --- a/app/src/main/res/layout/navigation_bar_navigation.xml +++ b/app/src/main/res/layout/navigation_bar_navigation.xml @@ -4,6 +4,7 @@ + @@ -35,7 +36,7 @@ android:src="@drawable/ic_icon_back" android:tint="@color/midnight" android:tooltipText="@string/back_tooltip" - android:enabled="@{viewmodel.canGoBack}" + android:enabled="@{viewmodel.canGoBack || viewmodel.backToNewTabEnabled}" app:privateMode="@{viewmodel.isPrivateSession}" /> + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/options_display.xml b/app/src/main/res/layout/options_display.xml index 96306557da..2237302033 100644 --- a/app/src/main/res/layout/options_display.xml +++ b/app/src/main/res/layout/options_display.xml @@ -84,15 +84,22 @@ android:layout_height="wrap_content" app:description="@string/settings_window_size" /> + + + app:highlightedTextColor="@color/fog" + android:visibility="gone" /> - + \ No newline at end of file diff --git a/app/src/main/res/values/options_values.xml b/app/src/main/res/values/options_values.xml index 6f7d89cbe2..fe41ce1994 100644 --- a/app/src/main/res/values/options_values.xml +++ b/app/src/main/res/values/options_values.xml @@ -101,6 +101,12 @@ 2 + + + @string/developer_options_homepage_new_tab + @string/developer_options_homepage_wolvic + @string/developer_options_homepage_other + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 88a641f52b..cc062e7197 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -617,6 +617,15 @@ %1$d×%2$d + + wolvic.com + + + New Tab + + + Other + User-Agent Mode @@ -1963,6 +1972,9 @@ Library + + New Tab + Clear