From d44ab67d5813dd63349a98a2100a252d6f5a7fe1 Mon Sep 17 00:00:00 2001 From: Alexey Martemyanov Date: Wed, 18 Dec 2024 19:55:12 +0600 Subject: [PATCH] Deduplicate open tab suggestions and internal pages --- .../View/AddressBarTextField.swift | 15 +++++++++++---- .../Model/SuggestionContainer.swift | 19 ++++++++++++++----- .../ViewModel/SuggestionViewModel.swift | 6 ++++-- .../View/WindowControllersManager.swift | 9 ++++++++- 4 files changed, 37 insertions(+), 12 deletions(-) diff --git a/DuckDuckGo/NavigationBar/View/AddressBarTextField.swift b/DuckDuckGo/NavigationBar/View/AddressBarTextField.swift index 56b7d1cdd9..57ae483378 100644 --- a/DuckDuckGo/NavigationBar/View/AddressBarTextField.swift +++ b/DuckDuckGo/NavigationBar/View/AddressBarTextField.swift @@ -370,7 +370,11 @@ final class AddressBarTextField: NSTextField { PixelKit.fire(autocompletePixel) } - if case .openTab(let title, url: let url) = suggestion { + if case .internalPage(title: let title, url: let url) = suggestion, + url == .bookmarks || url.isSettingsURL { + // when choosing an internal page suggestion preffer already open matching tab + switchTo(OpenTab(title: title, url: url)) + } else if case .openTab(let title, url: let url) = suggestion { switchTo(OpenTab(title: title, url: url)) } else if NSApp.isCommandPressed { openNew(NSApp.isOptionPressed ? .window : .tab, selected: NSApp.isShiftPressed, suggestion: suggestion) @@ -489,8 +493,12 @@ final class AddressBarTextField: NSTextField { } private func switchTo(_ tab: OpenTab) { - if let selectedTabViewModel = tabCollectionViewModel.selectedTabViewModel, - let selectionIndex = tabCollectionViewModel.selectionIndex, + let selectedTabViewModel = tabCollectionViewModel.selectedTabViewModel + let selectionIndex = tabCollectionViewModel.selectionIndex + + WindowControllersManager.shared.show(url: tab.url, source: .switchToOpenTab, newTab: true /* in case not found */) + + if let selectedTabViewModel, let selectionIndex, case .newtab = selectedTabViewModel.tab.content { // close tab with "new tab" page open tabCollectionViewModel.remove(at: selectionIndex) @@ -500,7 +508,6 @@ final class AddressBarTextField: NSTextField { window.performClose(self) } } - WindowControllersManager.shared.show(url: tab.url, source: .switchToOpenTab, newTab: false) } private func makeUrl(suggestion: Suggestion?, stringValueWithoutSuffix: String, completion: @escaping (URL?, String, Bool) -> Void) { diff --git a/DuckDuckGo/Suggestions/Model/SuggestionContainer.swift b/DuckDuckGo/Suggestions/Model/SuggestionContainer.swift index 802a36b66a..581498286b 100644 --- a/DuckDuckGo/Suggestions/Model/SuggestionContainer.swift +++ b/DuckDuckGo/Suggestions/Model/SuggestionContainer.swift @@ -16,6 +16,7 @@ // limitations under the License. // +import BrowserServicesKit import Combine import Common import Foundation @@ -35,6 +36,7 @@ final class SuggestionContainer { private let historyCoordinating: HistoryCoordinating private let bookmarkManager: BookmarkManager private let startupPreferences: StartupPreferences + private let featureFlagger: FeatureFlagger private let loading: SuggestionLoading // Used for presenting the same suggestions after the removal of the local suggestion @@ -44,11 +46,12 @@ final class SuggestionContainer { fileprivate let suggestionsURLSession = URLSession(configuration: .ephemeral) - init(openTabsProvider: @escaping OpenTabsProvider, suggestionLoading: SuggestionLoading, historyCoordinating: HistoryCoordinating, bookmarkManager: BookmarkManager, startupPreferences: StartupPreferences = .shared) { + init(openTabsProvider: @escaping OpenTabsProvider, suggestionLoading: SuggestionLoading, historyCoordinating: HistoryCoordinating, bookmarkManager: BookmarkManager, startupPreferences: StartupPreferences = .shared, featureFlagger: FeatureFlagger = NSApp.delegateTyped.featureFlagger) { self.openTabsProvider = openTabsProvider self.bookmarkManager = bookmarkManager self.historyCoordinating = historyCoordinating self.startupPreferences = startupPreferences + self.featureFlagger = featureFlagger self.loading = suggestionLoading } @@ -98,11 +101,17 @@ final class SuggestionContainer { { @MainActor in let selectedTab = WindowControllersManager.shared.selectedTab let openTabViewModels = WindowControllersManager.shared.allTabViewModels(for: burnerMode) + var usedUrls = Set() // deduplicate return openTabViewModels.compactMap { model in - guard model.tab !== selectedTab, model.tab.content.isUrl else { return nil } - return model.tab.content.userEditableUrl.map { url in - OpenTab(title: model.title, url: url) - } + guard model.tab !== selectedTab, + model.tab.content.isUrl + || model.tab.content.urlForWebView?.isSettingsURL == true + || model.tab.content.urlForWebView == .bookmarks, + let url = model.tab.content.userEditableUrl, + url != selectedTab?.content.userEditableUrl, // doesn‘t match currently selected + usedUrls.insert(url.absoluteString).inserted == true /* if did not contain */ else { return nil } + + return OpenTab(title: model.title, url: url) } } } diff --git a/DuckDuckGo/Suggestions/ViewModel/SuggestionViewModel.swift b/DuckDuckGo/Suggestions/ViewModel/SuggestionViewModel.swift index 882fe1b36d..a6f4d14776 100644 --- a/DuckDuckGo/Suggestions/ViewModel/SuggestionViewModel.swift +++ b/DuckDuckGo/Suggestions/ViewModel/SuggestionViewModel.swift @@ -181,9 +181,11 @@ struct SuggestionViewModel: Equatable { return .favoritedBookmarkSuggestion case .unknown: return .web - case .internalPage(title: _, url: let url) where url == .bookmarks: + case .internalPage(title: _, url: let url) where url == .bookmarks, + .openTab(title: _, url: let url) where url == .bookmarks: return .bookmarksFolder - case .internalPage(title: _, url: let url) where url.isSettingsURL: + case .internalPage(title: _, url: let url) where url.isSettingsURL, + .openTab(title: _, url: let url) where url.isSettingsURL: return .settingsMulticolor16 case .internalPage(title: _, url: let url): guard url == URL(string: StartupPreferences.shared.formattedCustomHomePageURL) else { return nil } diff --git a/DuckDuckGo/Windows/View/WindowControllersManager.swift b/DuckDuckGo/Windows/View/WindowControllersManager.swift index b6eb66d113..53170a2820 100644 --- a/DuckDuckGo/Windows/View/WindowControllersManager.swift +++ b/DuckDuckGo/Windows/View/WindowControllersManager.swift @@ -215,10 +215,17 @@ extension WindowControllersManager { // prefer current main window guard windowIdx == 0 || windowController !== mainWindowController else { continue } let tabCollectionViewModel = windowController.mainViewController.tabCollectionViewModel - guard let index = tabCollectionViewModel.indexInAllTabs(where: { $0.content.urlForWebView == url }) else { continue } + guard let index = tabCollectionViewModel.indexInAllTabs(where: { + $0.content.urlForWebView == url || (url.isSettingsURL && $0.content.urlForWebView?.isSettingsURL == true) + }) else { continue } windowController.window?.makeKeyAndOrderFront(self) tabCollectionViewModel.select(at: index) + if let tab = tabCollectionViewModel.tabViewModel(at: index)?.tab, + tab.content.urlForWebView != url { + // navigate to another settings pane + tab.setContent(.contentFromURL(url, source: .switchToOpenTab)) + } return true }