diff --git a/App/iOS/Delegates/SceneDelegate.swift b/App/iOS/Delegates/SceneDelegate.swift index e8d38da7b0c..bdbe5f78f0a 100644 --- a/App/iOS/Delegates/SceneDelegate.swift +++ b/App/iOS/Delegates/SceneDelegate.swift @@ -291,6 +291,20 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate { type: .newPrivateTab, using: browserViewController) } + return + case ActivityType.openHistoryList.identifier: + if let browserViewController = scene.browserViewController { + ActivityShortcutManager.shared.performShortcutActivity( + type: .openHistoryList, using: browserViewController) + } + + return + case ActivityType.openBookmarks.identifier: + if let browserViewController = scene.browserViewController { + ActivityShortcutManager.shared.performShortcutActivity( + type: .openBookmarks, using: browserViewController) + } + return case ActivityType.clearBrowsingHistory.identifier: if let browserViewController = scene.browserViewController { @@ -319,6 +333,11 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate { type: .openPlayList, using: browserViewController) } + case ActivityType.openSyncedTabs.identifier: + if let browserViewController = scene.browserViewController { + ActivityShortcutManager.shared.performShortcutActivity( + type: .openSyncedTabs, using: browserViewController) + } return default: break diff --git a/Sources/Brave/Frontend/Browser/BrowserViewController/BrowserViewController+ToolbarDelegate.swift b/Sources/Brave/Frontend/Browser/BrowserViewController/BrowserViewController+ToolbarDelegate.swift index ce645e8fcd2..0372f0cb518 100644 --- a/Sources/Brave/Frontend/Browser/BrowserViewController/BrowserViewController+ToolbarDelegate.swift +++ b/Sources/Brave/Frontend/Browser/BrowserViewController/BrowserViewController+ToolbarDelegate.swift @@ -23,7 +23,7 @@ import Playlist extension BrowserViewController: TopToolbarDelegate { - func showTabTray() { + func showTabTray(isExternallyPresented: Bool = false) { if tabManager.tabsForCurrentMode.isEmpty { return } @@ -42,6 +42,7 @@ extension BrowserViewController: TopToolbarDelegate { isTabTrayActive = true let tabTrayController = TabTrayController( + isExternallyPresented: isExternallyPresented, tabManager: tabManager, braveCore: braveCore, windowProtection: windowProtection).then { @@ -51,10 +52,12 @@ extension BrowserViewController: TopToolbarDelegate { let container = UINavigationController(rootViewController: tabTrayController) if !UIAccessibility.isReduceMotionEnabled { - container.transitioningDelegate = tabTrayController + if !isExternallyPresented { + container.transitioningDelegate = tabTrayController + } container.modalPresentationStyle = .fullScreen } - present(container, animated: true) + present(container, animated: !isExternallyPresented) } func topToolbarDidPressLockImageView(_ urlBar: TopToolbarView) { diff --git a/Sources/Brave/Frontend/Browser/Helpers/BrowserNavigationHelper.swift b/Sources/Brave/Frontend/Browser/Helpers/BrowserNavigationHelper.swift index 8d8e4e9c9ca..1c03af38254 100644 --- a/Sources/Brave/Frontend/Browser/Helpers/BrowserNavigationHelper.swift +++ b/Sources/Brave/Frontend/Browser/Helpers/BrowserNavigationHelper.swift @@ -55,10 +55,11 @@ class BrowserNavigationHelper { FileManager.default.openBraveDownloadsFolder(completion) } - func openHistory() { + func openHistory(isModal: Bool = false) { guard let bvc = bvc else { return } let vc = HistoryViewController( isPrivateBrowsing: bvc.privateBrowsingManager.isPrivateBrowsing, + isModallyPresented: isModal, historyAPI: bvc.braveCore.historyAPI, tabManager: bvc.tabManager) vc.toolbarUrlActionsDelegate = bvc diff --git a/Sources/Brave/Frontend/Browser/Tabs/TabTray/TabTrayController.swift b/Sources/Brave/Frontend/Browser/Tabs/TabTray/TabTrayController.swift index f8162935184..e2be7b2c558 100644 --- a/Sources/Brave/Frontend/Browser/Tabs/TabTray/TabTrayController.swift +++ b/Sources/Brave/Frontend/Browser/Tabs/TabTray/TabTrayController.swift @@ -97,6 +97,7 @@ class TabTrayController: AuthenticationController { var isTabTrayBeingSearched = false var tabTraySearchQuery: String? var tabTrayMode: TabTrayMode = .local + private var isExternallyPresented: Bool // The tab tray is presented by an action outside the application like shortcuts private var privateModeCancellable: AnyCancellable? private var initialScrollCompleted = false private var localAuthObservers = Set() @@ -180,7 +181,8 @@ class TabTrayController: AuthenticationController { // MARK: Lifecycle - init(tabManager: TabManager, braveCore: BraveCoreMain, windowProtection: WindowProtection?) { + init(isExternallyPresented: Bool = false, tabManager: TabManager, braveCore: BraveCoreMain, windowProtection: WindowProtection?) { + self.isExternallyPresented = isExternallyPresented self.tabManager = tabManager self.braveCore = braveCore @@ -319,6 +321,16 @@ class TabTrayController: AuthenticationController { becomeFirstResponder() } + override func viewDidAppear(_ animated: Bool) { + super.viewDidAppear(animated) + + // Navigate tabs from other devices + if isExternallyPresented { + tabTypeSelector.selectedSegmentIndex = 1 + tabTypeSelector.sendActions(for: UIControl.Event.valueChanged) + } + } + override func loadView() { createTypeSelectorItems() layoutTabTray() diff --git a/Sources/Brave/Frontend/Browser/Toolbars/BottomToolbar/Menu/Bookmarks/BookmarksViewController.swift b/Sources/Brave/Frontend/Browser/Toolbars/BottomToolbar/Menu/Bookmarks/BookmarksViewController.swift index d1be03526b9..3f248228ba2 100644 --- a/Sources/Brave/Frontend/Browser/Toolbars/BottomToolbar/Menu/Bookmarks/BookmarksViewController.swift +++ b/Sources/Brave/Frontend/Browser/Toolbars/BottomToolbar/Menu/Bookmarks/BookmarksViewController.swift @@ -15,11 +15,8 @@ import UniformTypeIdentifiers class BookmarksViewController: SiteTableViewController, ToolbarUrlActionsProtocol { - private var bookmarksFRC: BookmarksV2FetchResultsController? - private let bookmarkManager: BookmarkManager - /// Called when the bookmarks are updated via some user input (i.e. Delete, edit, etc.) - private var bookmarksDidChange: (() -> Void)? weak var toolbarUrlActionsDelegate: ToolbarUrlActionsDelegate? + private weak var addBookmarksFolderOkAction: UIAlertAction? private lazy var editBookmarksButton: UIBarButtonItem? = UIBarButtonItem().then { $0.image = UIImage(braveSystemNamed: "leo.edit.pencil") @@ -59,15 +56,16 @@ class BookmarksViewController: SiteTableViewController, ToolbarUrlActionsProtoco return items } - private weak var addBookmarksFolderOkAction: UIAlertAction? - - private var isEditingIndividualBookmark = false - + private var bookmarksFRC: BookmarksV2FetchResultsController? + private let bookmarkManager: BookmarkManager + /// Called when the bookmarks are updated via some user input (i.e. Delete, edit, etc.) + private var bookmarksDidChange: (() -> Void)? + private var currentFolder: Bookmarkv2? /// Certain bookmark actions are different in private browsing mode. private let isPrivateBrowsing: Bool - + private var isEditingIndividualBookmark = false private var isAtBookmarkRootLevel: Bool { return self.currentFolder == nil } diff --git a/Sources/Brave/Frontend/Browser/Toolbars/BottomToolbar/Menu/HistoryViewController.swift b/Sources/Brave/Frontend/Browser/Toolbars/BottomToolbar/Menu/HistoryViewController.swift index e9d19de7791..140068c876e 100644 --- a/Sources/Brave/Frontend/Browser/Toolbars/BottomToolbar/Menu/HistoryViewController.swift +++ b/Sources/Brave/Frontend/Browser/Toolbars/BottomToolbar/Menu/HistoryViewController.swift @@ -28,21 +28,20 @@ class HistoryViewController: SiteTableViewController, ToolbarUrlActionsProtocol private let historyAPI: BraveHistoryAPI private let tabManager: TabManager + private var historyFRC: HistoryV2FetchResultsController? - var historyFRC: HistoryV2FetchResultsController? - - /// Certain bookmark actions are different in private browsing mode. - let isPrivateBrowsing: Bool - - var isHistoryRefreshing = false + private let isPrivateBrowsing: Bool /// Certain bookmark actions are different in private browsing mode. + private let isModallyPresented: Bool + private var isHistoryRefreshing = false private var searchHistoryTimer: Timer? private var isHistoryBeingSearched = false private let searchController = UISearchController(searchResultsController: nil) private var searchQuery = "" - init(isPrivateBrowsing: Bool, historyAPI: BraveHistoryAPI, tabManager: TabManager) { + init(isPrivateBrowsing: Bool, isModallyPresented: Bool = false, historyAPI: BraveHistoryAPI, tabManager: TabManager) { self.isPrivateBrowsing = isPrivateBrowsing + self.isModallyPresented = isModallyPresented self.historyAPI = historyAPI self.tabManager = tabManager super.init(nibName: nil, bundle: nil) @@ -72,6 +71,10 @@ class HistoryViewController: SiteTableViewController, ToolbarUrlActionsProtocol $0.rightBarButtonItem = UIBarButtonItem(image: UIImage(braveSystemNamed: "leo.trash")!.template, style: .done, target: self, action: #selector(performDeleteAll)) } + + if isModallyPresented { + navigationItem.leftBarButtonItem = UIBarButtonItem(barButtonSystemItem: .done, target: self, action: #selector(performDone)) + } } definesPresentationContext = true @@ -178,6 +181,8 @@ class HistoryViewController: SiteTableViewController, ToolbarUrlActionsProtocol searchHistoryTimer = nil } } + + // MARK: Actions @objc private func performDeleteAll() { let style: UIAlertController.Style = UIDevice.current.userInterfaceIdiom == .pad ? .alert : .actionSheet @@ -212,6 +217,12 @@ class HistoryViewController: SiteTableViewController, ToolbarUrlActionsProtocol present(alert, animated: true, completion: nil) } + + @objc private func performDone() { + dismiss(animated: true) + } + + // MARK: UITableViewDelegate - UITableViewDataSource override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = super.tableView(tableView, cellForRowAt: indexPath) diff --git a/Sources/Brave/Frontend/Settings/General/ShortcutSettingsViewController.swift b/Sources/Brave/Frontend/Settings/General/ShortcutSettingsViewController.swift index 4e463f914f0..d08dc56285b 100644 --- a/Sources/Brave/Frontend/Settings/General/ShortcutSettingsViewController.swift +++ b/Sources/Brave/Frontend/Settings/General/ShortcutSettingsViewController.swift @@ -53,6 +53,30 @@ class ShortcutSettingsViewController: TableViewController { ], footer: .title(Strings.Shortcuts.shortcutSettingsOpenNewPrivateTabDescription)) ) + + dataSource.sections.append( + Section( + rows: [ + Row( + text: Strings.Shortcuts.shortcutSettingsOpenBookmarksTitle, + selection: { [unowned self] in + manageShortcutActivity(for: .openBookmarks) + }, accessory: .disclosureIndicator, cellClass: MultilineValue1Cell.self) + ], + footer: .title(Strings.Shortcuts.shortcutSettingsOpenBookmarksDescription)) + ) + + dataSource.sections.append( + Section( + rows: [ + Row( + text: Strings.Shortcuts.shortcutSettingsOpenHistoryListTitle, + selection: { [unowned self] in + manageShortcutActivity(for: .openHistoryList) + }, accessory: .disclosureIndicator, cellClass: MultilineValue1Cell.self) + ], + footer: .title(Strings.Shortcuts.shortcutSettingsOpenHistoryListDescription)) + ) dataSource.sections.append( Section( @@ -102,6 +126,18 @@ class ShortcutSettingsViewController: TableViewController { footer: .title(Strings.Shortcuts.shortcutSettingsOpenPlaylistDescription)) ) + dataSource.sections.append( + Section( + rows: [ + Row( + text: Strings.Shortcuts.shortcutSettingsOpenSyncedTabsTitle, + selection: { [unowned self] in + manageShortcutActivity(for: .openSyncedTabs) + }, accessory: .disclosureIndicator, cellClass: MultilineValue1Cell.self) + ], + footer: .title(Strings.Shortcuts.shortcutSettingsOpenSyncedTabsDescription)) + ) + dataSource.sections.append( Section( rows: [ diff --git a/Sources/Brave/Shortcuts/ActivityShortcutManager.swift b/Sources/Brave/Shortcuts/ActivityShortcutManager.swift index cf3ba8a86d5..4b9238c1c1c 100644 --- a/Sources/Brave/Shortcuts/ActivityShortcutManager.swift +++ b/Sources/Brave/Shortcuts/ActivityShortcutManager.swift @@ -22,10 +22,13 @@ import UniformTypeIdentifiers public enum ActivityType: String { case newTab = "NewTab" case newPrivateTab = "NewPrivateTab" + case openBookmarks = "OpenBookmarks" + case openHistoryList = "OpenHistoryList" case clearBrowsingHistory = "ClearBrowsingHistory" case enableBraveVPN = "EnableBraveVPN" case openBraveNews = "OpenBraveNews" case openPlayList = "OpenPlayList" + case openSyncedTabs = "OpenSyncedTabs" public var identifier: String { return "\(Bundle.main.bundleIdentifier ?? "").\(self.rawValue)" @@ -38,6 +41,10 @@ public enum ActivityType: String { return Strings.Shortcuts.activityTypeNewTabTitle case .newPrivateTab: return Strings.Shortcuts.activityTypeNewPrivateTabTitle + case .openBookmarks: + return Strings.Shortcuts.activityTypeOpenBookmarksTitle + case .openHistoryList: + return Strings.Shortcuts.activityTypeOpenHistoryListTitle case .clearBrowsingHistory: return Strings.Shortcuts.activityTypeClearHistoryTitle case .enableBraveVPN: @@ -46,6 +53,8 @@ public enum ActivityType: String { return Strings.Shortcuts.activityTypeOpenBraveNewsTitle case .openPlayList: return Strings.Shortcuts.activityTypeOpenPlaylistTitle + case .openSyncedTabs: + return Strings.Shortcuts.activityTypeOpenSyncedTabsTitle } } @@ -54,6 +63,10 @@ public enum ActivityType: String { switch self { case .newTab, .newPrivateTab: return Strings.Shortcuts.activityTypeTabDescription + case .openHistoryList: + return Strings.Shortcuts.activityTypeOpenHistoryListDescription + case .openBookmarks: + return Strings.Shortcuts.activityTypeOpenBookmarksDescription case .clearBrowsingHistory: return Strings.Shortcuts.activityTypeClearHistoryDescription case .enableBraveVPN: @@ -62,6 +75,8 @@ public enum ActivityType: String { return Strings.Shortcuts.activityTypeBraveNewsDescription case .openPlayList: return Strings.Shortcuts.activityTypeOpenPlaylistDescription + case .openSyncedTabs: + return Strings.Shortcuts.activityTypeOpenSyncedTabsDescription } } @@ -72,6 +87,10 @@ public enum ActivityType: String { return Strings.Shortcuts.activityTypeNewTabSuggestedPhrase case .newPrivateTab: return Strings.Shortcuts.activityTypeNewPrivateTabSuggestedPhrase + case .openBookmarks: + return Strings.Shortcuts.activityTypeOpenBookmarksSuggestedPhrase + case .openHistoryList: + return Strings.Shortcuts.activityTypeOpenHistoryListSuggestedPhrase case .clearBrowsingHistory: return Strings.Shortcuts.activityTypeClearHistorySuggestedPhrase case .enableBraveVPN: @@ -80,6 +99,8 @@ public enum ActivityType: String { return Strings.Shortcuts.activityTypeOpenBraveNewsSuggestedPhrase case .openPlayList: return Strings.Shortcuts.activityTypeOpenPlaylistSuggestedPhrase + case .openSyncedTabs: + return Strings.Shortcuts.activityTypeOpenSyncedTabsSuggestedPhrase } } } @@ -134,6 +155,12 @@ public class ActivityShortcutManager: NSObject { case .newPrivateTab: bvc.openBlankNewTab(attemptLocationFieldFocus: false, isPrivate: true, isExternal: true) bvc.popToBVC() + case .openBookmarks: + bvc.popToBVC() + bvc.navigationHelper.openBookmarks() + case .openHistoryList: + bvc.popToBVC() + bvc.navigationHelper.openHistory(isModal: true) case .clearBrowsingHistory: bvc.clearHistoryAndOpenNewTab() case .enableBraveVPN: @@ -185,6 +212,9 @@ public class ActivityShortcutManager: NSObject { PlaylistP3A.recordUsage() bvc.present(playlistController, animated: true) } + case .openSyncedTabs: + bvc.popToBVC() + bvc.showTabTray(isExternallyPresented: true) } } diff --git a/Sources/BraveStrings/BraveStrings.swift b/Sources/BraveStrings/BraveStrings.swift index 0766d584429..074db51fc45 100644 --- a/Sources/BraveStrings/BraveStrings.swift +++ b/Sources/BraveStrings/BraveStrings.swift @@ -2394,6 +2394,16 @@ extension Strings { NSLocalizedString("shortcuts.activityTypeNewPrivateTabTitle", tableName: "BraveShared", bundle: .module, value: "Open a New Private Browser Tab", comment: "") + + public static let activityTypeOpenBookmarksTitle = + NSLocalizedString("shortcuts.activityTypeOpenBookmarksTitle", tableName: "BraveShared", bundle: .module, + value: "Open Brave Browser Bookmarks", + comment: "") + + public static let activityTypeOpenHistoryListTitle = + NSLocalizedString("shortcuts.activityTypeOpenHistoryListTitle", tableName: "BraveShared", bundle: .module, + value: "Open Brave Browser History", + comment: "") public static let activityTypeClearHistoryTitle = NSLocalizedString("shortcuts.activityTypeClearHistoryTitle", tableName: "BraveShared", bundle: .module, @@ -2414,12 +2424,27 @@ extension Strings { NSLocalizedString("shortcuts.activityTypeOpenPlaylistTitle", tableName: "BraveShared", bundle: .module, value: "Open Playlist", comment: "") + + public static let activityTypeOpenSyncedTabsTitle = + NSLocalizedString("shortcuts.activityTypeOpenSyncedTabsTitle", tableName: "BraveShared", bundle: .module, + value: "Open Tabs from Other Devices", + comment: "") public static let activityTypeTabDescription = NSLocalizedString("shortcuts.activityTypeTabDescription", tableName: "BraveShared", bundle: .module, value: "Start Searching the Web Securely with Brave", comment: "") + public static let activityTypeOpenBookmarksDescription = + NSLocalizedString("shortcuts.activityTypeOpenBookmarksDescription", tableName: "BraveShared", bundle: .module, + value: "Open Browser Bookmarks Screen", + comment: "") + + public static let activityTypeOpenHistoryListDescription = + NSLocalizedString("shortcuts.activityTypeClearHistoryDescription", tableName: "BraveShared", bundle: .module, + value: "Open Browser History Screen", + comment: "") + public static let activityTypeClearHistoryDescription = NSLocalizedString("shortcuts.activityTypeClearHistoryDescription", tableName: "BraveShared", bundle: .module, value: "Open Browser in a New Tab and Delete All Private Browser History Data", @@ -2440,6 +2465,11 @@ extension Strings { value: "Start Playing your Videos in Playlist", comment: "") + public static let activityTypeOpenSyncedTabsDescription = + NSLocalizedString("shortcuts.activityTypeOpenSyncedTabsDescription", tableName: "BraveShared", bundle: .module, + value: "Open Brave Tabs Open in Other Devices", + comment: "") + public static let activityTypeNewTabSuggestedPhrase = NSLocalizedString("shortcuts.activityTypeNewTabSuggestedPhrase", tableName: "BraveShared", bundle: .module, value: "Open New Tab", @@ -2450,6 +2480,16 @@ extension Strings { value: "Open New Private Tab", comment: "") + public static let activityTypeOpenBookmarksSuggestedPhrase = + NSLocalizedString("shortcuts.activityTypeOpenBookmarksSuggestedPhrase", tableName: "BraveShared", bundle: .module, + value: "Open Bookmarks", + comment: "") + + public static let activityTypeOpenHistoryListSuggestedPhrase = + NSLocalizedString("shortcuts.activityTypeOpenHistoryListSuggestedPhrase", tableName: "BraveShared", bundle: .module, + value: "Open Browser History", + comment: "") + public static let activityTypeClearHistorySuggestedPhrase = NSLocalizedString("shortcuts.activityTypeClearHistorySuggestedPhrase", tableName: "BraveShared", bundle: .module, value: "Clear Browser History", @@ -2469,6 +2509,11 @@ extension Strings { NSLocalizedString("shortcuts.activityTypeOpenPlaylistSuggestedPhrase", tableName: "BraveShared", bundle: .module, value: "Open Playlist", comment: "") + + public static let activityTypeOpenSyncedTabsSuggestedPhrase = + NSLocalizedString("shortcuts.activityTypeOpenSyncedTabsSuggestedPhrase", tableName: "BraveShared", bundle: .module, + value: "Open Tabs from Other Devices", + comment: "") public static let customIntentOpenWebsiteSuggestedPhrase = NSLocalizedString("shortcuts.customIntentOpenWebsiteSuggestedPhrase", tableName: "BraveShared", bundle: .module, @@ -2510,6 +2555,26 @@ extension Strings { value: "Use Shortcuts to open a new private tab via Siri - Voice Assistant", comment: "") + public static let shortcutSettingsOpenBookmarksTitle = + NSLocalizedString("shortcuts.shortcutSettingsOpenBookmarksTitle", tableName: "BraveShared", bundle: .module, + value: "Open Bookmarks", + comment: "") + + public static let shortcutSettingsOpenBookmarksDescription = + NSLocalizedString("shortcuts.shortcutSettingsOpenBookmarksDescription", tableName: "BraveShared", bundle: .module, + value: "Use Shortcuts to open bookmarks screen via Siri - Voice Assistant", + comment: "") + + public static let shortcutSettingsOpenHistoryListTitle = + NSLocalizedString("shortcuts.shortcutSettingsOpenHistoryListTitle", tableName: "BraveShared", bundle: .module, + value: "Open Browser History", + comment: "") + + public static let shortcutSettingsOpenHistoryListDescription = + NSLocalizedString("shortcuts.shortcutSettingsOpenHistoryListDescription", tableName: "BraveShared", bundle: .module, + value: "Use Shortcuts to open browser history screen via Siri - Voice Assistant", + comment: "") + public static let shortcutSettingsClearBrowserHistoryTitle = NSLocalizedString("shortcuts.shortcutSettingsClearBrowserHistoryTitle", tableName: "BraveShared", bundle: .module, value: "Clear Browser History", @@ -2550,6 +2615,16 @@ extension Strings { value: "Use Shortcuts to open Playlist via Siri - Voice Assistant", comment: "Description of Open Playlist Siri Shortcut in Settings Screen") + public static let shortcutSettingsOpenSyncedTabsTitle = + NSLocalizedString("shortcuts.shortcutSettingsOpenSyncedTabsTitle", tableName: "BraveShared", bundle: .module, + value: "Open Tabs from Other Devices", + comment: "") + + public static let shortcutSettingsOpenSyncedTabsDescription = + NSLocalizedString("shortcuts.shortcutSettingsOpenSyncedTabsDescription", tableName: "BraveShared", bundle: .module, + value: "Use Shortcuts to open Tabs from Other Devices via Siri - Voice Assistant", + comment: "Description of Open Tabs from Other Devices Shortcut in Settings Screen") + public static let shortcutOpenApplicationSettingsTitle = NSLocalizedString("shortcuts.shortcutOpenApplicationSettingsTitle", tableName: "BraveShared", bundle: .module, value: "Open Settings",