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 c44a285ed4a..125f1296c0b 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; @@ -53,7 +54,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; @@ -64,6 +67,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; @@ -92,6 +96,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); @@ -134,11 +139,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)); @@ -150,6 +159,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)); @@ -239,9 +249,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())) { @@ -336,6 +349,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()); @@ -352,6 +366,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()); @@ -374,10 +389,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)); } @@ -421,9 +444,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); + } } } } @@ -434,9 +465,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); } @@ -571,6 +605,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); } @@ -583,6 +622,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; @@ -673,6 +721,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 00000000000..3bedd8eca0b --- /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 7140d88953f..ab2d3ff5df3 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 @@ -177,6 +177,7 @@ public void onDestroy() { mSystemNotificationsView.onDestroy(); } + @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 9c972344935..337ae31b94f 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 8c600061750..bef517a2f07 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 @@ -605,7 +605,7 @@ public void attachToWindow(@NonNull WindowWidget aWindow) { } private Observer mCurrentContentTypeObserver = contentType -> { - 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 821e68f7313..46e99cfea22 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,6 +219,7 @@ private void initialize(Context aContext) { setupListeners(mSession); mLibrary = new LibraryPanel(aContext); + mNewTab = new NewTabView(aContext); SessionStore.get().getBookmarkStore().addListener(mBookmarksListener); @@ -501,31 +504,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); @@ -533,12 +535,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); } @@ -549,6 +553,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); } @@ -557,12 +587,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() { @@ -2003,24 +2054,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 7c65403cc57..65bbef865a6 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; } @@ -636,7 +656,7 @@ public void exitImmersiveMode() { } private void closeLibraryPanelInFocusedWindowIfNeeded() { - if (!mFocusedWindow.isNativeContentVisible()) + if (!mFocusedWindow.getCurrentContentType().isLibraryContent()) return; mFocusedWindow.hidePanel(); } @@ -1205,7 +1225,7 @@ public void onBookmarksClicked() { if (mFocusedWindow.getCurrentContentType() == ContentType.BOOKMARKS) { mFocusedWindow.hidePanel(); } else { - mFocusedWindow.showPanel(ContentType.BOOKMARKS); + mFocusedWindow.showLibraryPanel(ContentType.BOOKMARKS); } } @@ -1214,7 +1234,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 abf9348e248..e6b7f08312f 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 @@ -21,6 +21,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; @@ -86,6 +89,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); }; @@ -263,6 +274,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); @@ -365,11 +381,39 @@ private void setSoundEffect(boolean value, 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/utils/UrlUtils.java b/app/src/common/shared/com/igalia/wolvic/utils/UrlUtils.java index 9b496b2ab62..6ceedac1ad9 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 ae12d97b38d..f9b15014dd9 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 @@ + @@ -34,7 +35,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 137ea71ce24..d71fa5282f9 100644 --- a/app/src/main/res/layout/options_display.xml +++ b/app/src/main/res/layout/options_display.xml @@ -96,15 +96,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 9619e594885..26abe7b9048 100644 --- a/app/src/main/res/values/options_values.xml +++ b/app/src/main/res/values/options_values.xml @@ -85,6 +85,13 @@ 2 + + + @string/developer_options_homepage_new_tab + @string/developer_options_homepage_wolvic + @string/developer_options_homepage_other + + @string/privacy_options_tracking_etp diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 9d5afa6d0ce..50df2489fd7 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -609,6 +609,15 @@ %1$d×%2$d + + wolvic.com + + + New Tab + + + Other + User-Agent Mode @@ -1828,10 +1837,6 @@ tray and the Downloads view is closed. The button it labels, when pressed, closes the Downloads view. --> Close Downloads - - Open Library - Close Library @@ -1963,6 +1968,9 @@ Library + + New Tab + Clear