Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixed address bar cleared/losing focus on Navigation #2157

Merged
merged 17 commits into from
Feb 27, 2024
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
03f9bb3
Fixed address bar cleared/losing focus on Navigation
mallexxx Feb 5, 2024
375cbb1
Merge remote-tracking branch 'origin/main' into alex/fix-address-bar-…
mallexxx Feb 7, 2024
c5cdd45
Merge remote-tracking branch 'origin/main' into alex/fix-address-bar-…
mallexxx Feb 7, 2024
7b699bf
fixed suggestion window not disappearing on tab switch
mallexxx Feb 7, 2024
3aa45ff
Merge remote-tracking branch 'origin/main' into alex/fix-address-bar-…
mallexxx Feb 19, 2024
8f37cd8
refactor first responder setting and fix address bar blinking issues
mallexxx Feb 19, 2024
7ebe607
fix tests
mallexxx Feb 19, 2024
543f5ba
Merge remote-tracking branch 'origin/main' into alex/fix-address-bar-…
mallexxx Feb 19, 2024
535f92e
Merge remote-tracking branch 'origin/main' into alex/fix-address-bar-…
mallexxx Feb 21, 2024
41ae4cf
fix issues, add tests
mallexxx Feb 22, 2024
eeb4e1c
Merge remote-tracking branch 'origin/main' into alex/fix-address-bar-…
mallexxx Feb 22, 2024
d0c5643
Merge remote-tracking branch 'origin/main' into alex/fix-address-bar-…
mallexxx Feb 22, 2024
808c5bd
fix comment; fixing tests
mallexxx Feb 22, 2024
3b634cb
Merge remote-tracking branch 'origin/main' into alex/fix-address-bar-…
mallexxx Feb 26, 2024
5684bb5
fix divider shown on the Home Page
mallexxx Feb 26, 2024
52d6f16
Merge remote-tracking branch 'origin/main' into alex/fix-address-bar-…
mallexxx Feb 27, 2024
a968834
Merge remote-tracking branch 'origin/main' into alex/fix-address-bar-…
mallexxx Feb 27, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions DuckDuckGo/Common/Extensions/NSViewExtension.swift
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,8 @@ extension NSView {
os_log("%s: Window not available", type: .error, className)
return
}
// prevent all text selection on repeated Address Bar activation
guard window.firstResponder !== (self as? NSControl)?.currentEditor() ?? self else { return }

window.makeFirstResponder(self)
}
Expand Down
3 changes: 3 additions & 0 deletions DuckDuckGo/Common/Localizables/UserText.swift
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,9 @@ struct UserText {
static let addressBarVisitSuffix = NSLocalizedString("address.bar.visit.suffix",
value: "Visit",
comment: "Address bar suffix of possibly visited website. Example: spreadprivacy.com . Visit spreadprivacy.com")
static let addressBarPlaceholder = NSLocalizedString("address.bar.placeholder",
value: "Search or enter address",
comment: "Empty Address Bar placeholder text displayed on the new tab page.")

static let navigateBack = NSLocalizedString("navigate.back", value: "Back", comment: "Context menu item")
static let closeAndReturnToParentFormat = NSLocalizedString("close.tab.on.back.format",
Expand Down
14 changes: 13 additions & 1 deletion DuckDuckGo/Localizable.xcstrings
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,18 @@
"Address:" : {
"comment" : "Add Bookmark dialog bookmark url field heading"
},
"address.bar.placeholder" : {
"comment" : "Empty Address Bar placeholder text displayed on the new tab page.",
"extractionState" : "extracted_with_value",
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "new",
"value" : "Search or enter address"
}
}
}
},
"address.bar.search.suffix" : {
"comment" : "Suffix of searched terms in address bar. Example: best watching machine . Search DuckDuckGo",
"extractionState" : "extracted_with_value",
Expand Down Expand Up @@ -9185,4 +9197,4 @@
}
},
"version" : "1.0"
}
}
113 changes: 51 additions & 62 deletions DuckDuckGo/MainWindow/MainViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,8 @@ final class MainViewController: NSViewController {

private var addressBarBookmarkIconVisibilityCancellable: AnyCancellable?
private var selectedTabViewModelCancellable: AnyCancellable?
private var tabViewModelCancellables = Set<AnyCancellable>()
private var bookmarksBarVisibilityChangedCancellable: AnyCancellable?
private var navigationalCancellables = Set<AnyCancellable>()
private var windowTitleCancellable: AnyCancellable?
private var eventMonitorCancellables = Set<AnyCancellable>()

private var bookmarksBarIsVisible: Bool {
Expand Down Expand Up @@ -141,6 +140,7 @@ final class MainViewController: NSViewController {
}

updateDividerColor()
adjustFirstResponder()
}

override func viewDidLayout() {
Expand Down Expand Up @@ -253,28 +253,26 @@ final class MainViewController: NSViewController {
}

private func subscribeToSelectedTabViewModel() {
selectedTabViewModelCancellable = tabCollectionViewModel.$selectedTabViewModel.receive(on: DispatchQueue.main).sink { [weak self] _ in
self?.navigationalCancellables = []
self?.subscribeToCanGoBackForward()
self?.subscribeToFindInPage()
self?.subscribeToTabContent()
self?.adjustFirstResponder()
self?.subscribeToTitleChange()
selectedTabViewModelCancellable = tabCollectionViewModel.$selectedTabViewModel.sink { [weak self] tabViewModel in
guard let self, let tabViewModel else { return }

tabViewModelCancellables.removeAll(keepingCapacity: true)
subscribeToCanGoBackForward(of: tabViewModel)
subscribeToFindInPage(of: tabViewModel)
subscribeToTitleChange(of: tabViewModel)
subscribeToTabContent(of: tabViewModel)
}
}

private func subscribeToTitleChange() {
private func subscribeToTitleChange(of selectedTabViewModel: TabViewModel?) {
guard let window = self.view.window else { return }
windowTitleCancellable = tabCollectionViewModel.$selectedTabViewModel
.compactMap { tabViewModel in
tabViewModel?.$title
}
.switchToLatest()
selectedTabViewModel?.$title
.map {
$0.truncated(length: MainMenu.Constants.maxTitleLength)
}
.receive(on: DispatchQueue.main)
.assign(to: \.title, onWeaklyHeld: window)
.store(in: &tabViewModelCancellables)
}

private func subscribeToAppSettingsNotifications() {
Expand All @@ -299,15 +297,21 @@ final class MainViewController: NSViewController {
}
}

var lastTabContent: Tab.TabContent?
private func subscribeToTabContent() {
tabCollectionViewModel.selectedTabViewModel?.tab.$content.receive(on: DispatchQueue.main).sink(receiveValue: { [weak self] content in
guard let self = self else { return }
self.resizeNavigationBarForHomePage(content == .newtab, animated: content == .newtab && self.lastTabContent != .newtab)
self.updateBookmarksBar(content)
self.lastTabContent = content
self.adjustFirstResponderOnContentChange(content: content)
}).store(in: &self.navigationalCancellables)
private var lastTabContent = Tab.TabContent.none
private func subscribeToTabContent(of selectedTabViewModel: TabViewModel?) {

selectedTabViewModel?.tab.$content
.sink { [weak self, weak selectedTabViewModel] content in
guard let self, let selectedTabViewModel else { return }
defer { lastTabContent = content }

resizeNavigationBarForHomePage(content == .newtab, animated: content == .newtab && lastTabContent != .newtab)
updateBookmarksBar(content)
if (content == .newtab) != (lastTabContent == .newtab) {
adjustFirstResponder(selectedTabViewModel: selectedTabViewModel, content: content)
}
}
.store(in: &self.tabViewModelCancellables)
}

private func updateBookmarksBar(_ content: Tab.TabContent, _ prefs: AppearancePreferences = AppearancePreferences.shared) {
Expand All @@ -318,29 +322,29 @@ final class MainViewController: NSViewController {
}
}

private func subscribeToFindInPage() {
tabCollectionViewModel.selectedTabViewModel?.findInPage?
private func subscribeToFindInPage(of selectedTabViewModel: TabViewModel?) {
selectedTabViewModel?.findInPage?
.$isVisible
.receive(on: DispatchQueue.main)
.sink { [weak self] _ in
self?.updateFindInPage()
}
.store(in: &self.navigationalCancellables)
.store(in: &self.tabViewModelCancellables)
}

private func subscribeToCanGoBackForward() {
tabCollectionViewModel.selectedTabViewModel?.$canGoBack.receive(on: DispatchQueue.main).sink { [weak self] _ in
private func subscribeToCanGoBackForward(of selectedTabViewModel: TabViewModel) {
selectedTabViewModel.$canGoBack.receive(on: DispatchQueue.main).sink { [weak self] _ in
self?.updateBackMenuItem()
}.store(in: &self.navigationalCancellables)
tabCollectionViewModel.selectedTabViewModel?.$canGoForward.receive(on: DispatchQueue.main).sink { [weak self] _ in
}.store(in: &self.tabViewModelCancellables)
selectedTabViewModel.$canGoForward.receive(on: DispatchQueue.main).sink { [weak self] _ in
self?.updateForwardMenuItem()
}.store(in: &self.navigationalCancellables)
tabCollectionViewModel.selectedTabViewModel?.$canReload.receive(on: DispatchQueue.main).sink { [weak self] _ in
}.store(in: &self.tabViewModelCancellables)
selectedTabViewModel.$canReload.receive(on: DispatchQueue.main).sink { [weak self] _ in
self?.updateReloadMenuItem()
}.store(in: &self.navigationalCancellables)
tabCollectionViewModel.selectedTabViewModel?.$isLoading.receive(on: DispatchQueue.main).sink { [weak self] _ in
}.store(in: &self.tabViewModelCancellables)
selectedTabViewModel.$isLoading.receive(on: DispatchQueue.main).sink { [weak self] _ in
self?.updateStopMenuItem()
}.store(in: &self.navigationalCancellables)
}.store(in: &self.tabViewModelCancellables)
}

private func updateFindInPage() {
Expand Down Expand Up @@ -403,39 +407,24 @@ final class MainViewController: NSViewController {

// MARK: - First responder

func adjustFirstResponder() {
guard let selectedTabViewModel = tabCollectionViewModel.selectedTabViewModel else {
os_log("MainViewController: No tab view model selected", type: .error)
func adjustFirstResponder(selectedTabViewModel: TabViewModel? = nil, content: Tab.TabContent? = nil) {
guard let selectedTabViewModel = selectedTabViewModel ?? tabCollectionViewModel.selectedTabViewModel else {
assertionFailure("No tab view model selected")
return
}
let content = content ?? selectedTabViewModel.tab.content

switch selectedTabViewModel.tab.content {
case .newtab:
if case .newtab = content {
navigationBarViewController.addressBarViewController?.addressBarTextField.makeMeFirstResponder()
case .onboarding:
self.view.makeMeFirstResponder()
case .url, .subscription:
browserTabViewController.makeWebViewFirstResponder()
case .settings:
browserTabViewController.preferencesViewController?.view.makeMeFirstResponder()
case .bookmarks:
browserTabViewController.bookmarksViewController?.view.makeMeFirstResponder()
case .none:
shouldAdjustFirstResponderOnContentChange = true
case .dataBrokerProtection:
browserTabViewController.preferencesViewController?.view.makeMeFirstResponder()
}
}

var shouldAdjustFirstResponderOnContentChange = false
} else {
self.view.window?.makeFirstResponder(nil)

func adjustFirstResponderOnContentChange(content: Tab.TabContent) {
guard shouldAdjustFirstResponderOnContentChange, content != .none else {
return
// ignore published tab switch: BrowserTabViewController
// adjusts first responder itself
guard selectedTabViewModel === tabCollectionViewModel.selectedTabViewModel else { return }
self.browserTabViewController.adjustFirstResponder()
}

shouldAdjustFirstResponderOnContentChange = false
adjustFirstResponder()
}

}
Expand Down
Loading
Loading