From 76976a9e921867186a7f9d0b318d1fa2844f7c9e Mon Sep 17 00:00:00 2001 From: Mono <81423605+monofunc@users.noreply.github.com> Date: Sat, 6 Jun 2026 12:42:50 +0400 Subject: [PATCH] Add a "Close duplicates" button to the tabs panel * The button sits in the selection bar next to "Close all" * Two tabs are duplicates when they share the same URL * The most recently used tab of each URL is kept * Tabs shown in a window, tabs without a URL and WebExtension sessions are never closed --- .../wolvic/browser/engine/SessionStore.java | 27 +++++++++++++++++++ .../igalia/wolvic/ui/widgets/TabsWidget.java | 14 ++++++++++ app/src/main/res/layout/tabs.xml | 5 ++++ app/src/main/res/values/strings.xml | 5 ++++ 4 files changed, 51 insertions(+) diff --git a/app/src/common/shared/com/igalia/wolvic/browser/engine/SessionStore.java b/app/src/common/shared/com/igalia/wolvic/browser/engine/SessionStore.java index 7f393f1150..5ae123de95 100644 --- a/app/src/common/shared/com/igalia/wolvic/browser/engine/SessionStore.java +++ b/app/src/common/shared/com/igalia/wolvic/browser/engine/SessionStore.java @@ -34,6 +34,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; +import java.util.HashSet; import java.util.LinkedHashSet; import java.util.LinkedList; import java.util.List; @@ -388,6 +389,32 @@ public ArrayList getSortedSessions(boolean aPrivateMode) { return result; } + public ArrayList getDuplicateSessions(boolean aPrivateMode) { + ArrayList duplicates = new ArrayList<>(); + HashSet uris = new HashSet<>(); + ArrayList sessions = getSortedSessions(aPrivateMode); + + for (Session session : sessions) { + if (session.isActive() && !session.getCurrentUri().isEmpty()) { + uris.add(session.getCurrentUri()); + } + } + + for (Session session : sessions) { + String uri = session.getCurrentUri(); + + if (session.isActive() || session.isWebExtensionSession() || uri.isEmpty()) { + continue; + } + + if (!uris.add(uri)) { + duplicates.add(session); + } + } + + return duplicates; + } + public void setPermissionDelegate(PermissionDelegate delegate) { mPermissionDelegate = delegate; } diff --git a/app/src/common/shared/com/igalia/wolvic/ui/widgets/TabsWidget.java b/app/src/common/shared/com/igalia/wolvic/ui/widgets/TabsWidget.java index c145ed21a0..08f373823f 100644 --- a/app/src/common/shared/com/igalia/wolvic/ui/widgets/TabsWidget.java +++ b/app/src/common/shared/com/igalia/wolvic/ui/widgets/TabsWidget.java @@ -40,6 +40,7 @@ public class TabsWidget extends UIDialog { protected UITextButton mCloseTabsButton; protected UITextButton mBookmarkTabsButton; protected UITextButton mCloseTabsAllButton; + protected UITextButton mCloseDuplicateTabsButton; protected UITextButton mSelectAllButton; protected UITextButton mUnselectTabs; protected LinearLayout mTabsSelectModeView; @@ -133,6 +134,16 @@ public void updateUI() { onDismiss(); }); + mCloseDuplicateTabsButton = findViewById(R.id.tabsCloseDuplicatesButton); + mCloseDuplicateTabsButton.setOnClickListener(v -> { + if (mTabDelegate != null) { + mTabDelegate.onTabsClose(SessionStore.get().getDuplicateSessions(mPrivateMode)); + } + + refreshTabs(); + updateSelectionMode(); + }); + mSelectAllButton = findViewById(R.id.tabsSelectAllButton); mSelectAllButton.setOnClickListener(v -> { mSelectedTabs = new ArrayList<>(mAdapter.mTabs); @@ -356,12 +367,15 @@ private void updateSelectionMode() { mBookmarkTabsButton.setVisibility(View.VISIBLE); mUnselectTabs.setVisibility(View.VISIBLE); mCloseTabsAllButton.setVisibility(View.GONE); + mCloseDuplicateTabsButton.setVisibility(View.GONE); mSelectAllButton.setVisibility(View.GONE); } else { mCloseTabsButton.setVisibility(View.GONE); mBookmarkTabsButton.setVisibility(View.GONE); mUnselectTabs.setVisibility(View.GONE); mCloseTabsAllButton.setVisibility(View.VISIBLE); + mCloseDuplicateTabsButton.setVisibility(View.VISIBLE); + mCloseDuplicateTabsButton.setEnabled(!SessionStore.get().getDuplicateSessions(mPrivateMode).isEmpty()); mSelectAllButton.setVisibility(View.VISIBLE); } diff --git a/app/src/main/res/layout/tabs.xml b/app/src/main/res/layout/tabs.xml index 2e39934694..b99350ae91 100644 --- a/app/src/main/res/layout/tabs.xml +++ b/app/src/main/res/layout/tabs.xml @@ -92,6 +92,11 @@ android:visibility="gone" android:text="@string/tabs_bookmark_selected" /> + + the Select` button. When clicked it bookmarks all the previously selected tabs --> Bookmark tabs + + Close duplicates + Close all