From e7dae22afbd71595657ae535c31551d041ead19e Mon Sep 17 00:00:00 2001 From: OrlaM Date: Wed, 7 Feb 2024 14:20:27 -0500 Subject: [PATCH] Bugfix FXIOS-8364 [v123] Add confirmation dialog (#18581) * Add confirmation dialog * Fix swiftlint --- .../Browser/Tabs/Action/TabPanelAction.swift | 2 ++ .../Middleware/TabManagerMiddleware.swift | 2 +- .../Browser/Tabs/State/TabTrayState.swift | 23 +++++++++++++++---- .../Browser/Tabs/State/TabsPanelState.swift | 11 +++++---- .../Tabs/Views/TabTrayViewController.swift | 21 +++++++++++++++++ 5 files changed, 49 insertions(+), 10 deletions(-) diff --git a/firefox-ios/Client/Frontend/Browser/Tabs/Action/TabPanelAction.swift b/firefox-ios/Client/Frontend/Browser/Tabs/Action/TabPanelAction.swift index 76e09e3ada55..db033bd2e782 100644 --- a/firefox-ios/Client/Frontend/Browser/Tabs/Action/TabPanelAction.swift +++ b/firefox-ios/Client/Frontend/Browser/Tabs/Action/TabPanelAction.swift @@ -96,6 +96,7 @@ enum TabPanelAction: Action { case closeTab(TabUUIDContext) case undoClose(ActionContext) case closeAllTabs(ActionContext) + case confirmCloseAllTabs(ActionContext) case undoCloseAllTabs(ActionContext) case moveTab(MoveTabContext) case toggleInactiveTabs(ActionContext) @@ -122,6 +123,7 @@ enum TabPanelAction: Action { .closeTab(let context as ActionContext), .undoClose(let context), .closeAllTabs(let context), + .confirmCloseAllTabs(let context), .undoCloseAllTabs(let context), .moveTab(let context as ActionContext), .toggleInactiveTabs(let context), diff --git a/firefox-ios/Client/Frontend/Browser/Tabs/Middleware/TabManagerMiddleware.swift b/firefox-ios/Client/Frontend/Browser/Tabs/Middleware/TabManagerMiddleware.swift index e051fcc33416..919e8c0a6a1e 100644 --- a/firefox-ios/Client/Frontend/Browser/Tabs/Middleware/TabManagerMiddleware.swift +++ b/firefox-ios/Client/Frontend/Browser/Tabs/Middleware/TabManagerMiddleware.swift @@ -54,7 +54,7 @@ class TabManagerMiddleware { case TabPanelAction.undoClose: self.undoCloseTab(state: state, uuid: uuid) - case TabPanelAction.closeAllTabs: + case TabPanelAction.confirmCloseAllTabs: self.closeAllTabs(state: state, uuid: uuid) case TabPanelAction.undoCloseAllTabs: diff --git a/firefox-ios/Client/Frontend/Browser/Tabs/State/TabTrayState.swift b/firefox-ios/Client/Frontend/Browser/Tabs/State/TabTrayState.swift index 9326a1bce609..64779509e1e1 100644 --- a/firefox-ios/Client/Frontend/Browser/Tabs/State/TabTrayState.swift +++ b/firefox-ios/Client/Frontend/Browser/Tabs/State/TabTrayState.swift @@ -19,6 +19,7 @@ struct TabTrayState: ScreenState, Equatable { var shouldDismiss: Bool var shareURL: URL? var windowUUID: WindowUUID + var showCloseConfirmation: Bool var navigationTitle: String { return selectedPanel.navTitle @@ -42,7 +43,8 @@ struct TabTrayState: ScreenState, Equatable { normalTabsCount: panelState.normalTabsCount, hasSyncableAccount: panelState.hasSyncableAccount, shouldDismiss: panelState.shouldDismiss, - shareURL: panelState.shareURL) + shareURL: panelState.shareURL, + showCloseConfirmation: panelState.showCloseConfirmation) } init(windowUUID: WindowUUID) { @@ -68,7 +70,8 @@ struct TabTrayState: ScreenState, Equatable { normalTabsCount: String, hasSyncableAccount: Bool, shouldDismiss: Bool = false, - shareURL: URL? = nil) { + shareURL: URL? = nil, + showCloseConfirmation: Bool = false) { self.windowUUID = windowUUID self.isPrivateMode = isPrivateMode self.selectedPanel = selectedPanel @@ -76,6 +79,7 @@ struct TabTrayState: ScreenState, Equatable { self.hasSyncableAccount = hasSyncableAccount self.shouldDismiss = shouldDismiss self.shareURL = shareURL + self.showCloseConfirmation = showCloseConfirmation } static let reducer: Reducer = { state, action in @@ -134,14 +138,25 @@ struct TabTrayState: ScreenState, Equatable { // Only update the nomal tab count if the tabs being refreshed are not private let tabModel = context.tabDisplayModel let isPrivate = tabModel.tabs.first?.isPrivate ?? false - let tabCount = tabModel.normalTabsCount + let tabCount = isPrivate ? state.normalTabsCount : tabModel.normalTabsCount return TabTrayState(windowUUID: state.windowUUID, isPrivateMode: state.isPrivateMode, selectedPanel: state.selectedPanel, normalTabsCount: tabCount, hasSyncableAccount: state.hasSyncableAccount) + case TabPanelAction.closeAllTabs(let context): + return TabTrayState(windowUUID: state.windowUUID, + isPrivateMode: state.isPrivateMode, + selectedPanel: state.selectedPanel, + normalTabsCount: state.normalTabsCount, + hasSyncableAccount: state.hasSyncableAccount, + showCloseConfirmation: true) default: - return state + return TabTrayState(windowUUID: state.windowUUID, + isPrivateMode: state.isPrivateMode, + selectedPanel: state.selectedPanel, + normalTabsCount: state.normalTabsCount, + hasSyncableAccount: state.hasSyncableAccount) } } } diff --git a/firefox-ios/Client/Frontend/Browser/Tabs/State/TabsPanelState.swift b/firefox-ios/Client/Frontend/Browser/Tabs/State/TabsPanelState.swift index 173eac6cf416..02644624eb0e 100644 --- a/firefox-ios/Client/Frontend/Browser/Tabs/State/TabsPanelState.swift +++ b/firefox-ios/Client/Frontend/Browser/Tabs/State/TabsPanelState.swift @@ -115,11 +115,12 @@ struct TabsPanelState: ScreenState, Equatable { tabs: state.tabs, inactiveTabs: state.inactiveTabs, isInactiveTabsExpanded: state.isInactiveTabsExpanded) - default: return TabsPanelState(windowUUID: state.windowUUID, - isPrivateMode: state.isPrivateMode, - tabs: state.tabs, - inactiveTabs: state.inactiveTabs, - isInactiveTabsExpanded: state.isInactiveTabsExpanded) + default: + return TabsPanelState(windowUUID: state.windowUUID, + isPrivateMode: state.isPrivateMode, + tabs: state.tabs, + inactiveTabs: state.inactiveTabs, + isInactiveTabsExpanded: state.isInactiveTabsExpanded) } } } diff --git a/firefox-ios/Client/Frontend/Browser/Tabs/Views/TabTrayViewController.swift b/firefox-ios/Client/Frontend/Browser/Tabs/Views/TabTrayViewController.swift index a8d92f059bd6..2f450b0ecef4 100644 --- a/firefox-ios/Client/Frontend/Browser/Tabs/Views/TabTrayViewController.swift +++ b/firefox-ios/Client/Frontend/Browser/Tabs/Views/TabTrayViewController.swift @@ -282,6 +282,9 @@ class TabTrayViewController: UIViewController, if let url = tabTrayState.shareURL { navigationHandler?.shareTab(url: url, sourceView: self.view) } + if tabTrayState.showCloseConfirmation { + showCloseAllConfirmation() + } } func updateTabCountImage(count: String) { @@ -460,6 +463,24 @@ class TabTrayViewController: UIViewController, store.dispatch(TabPanelAction.closeAllTabs(windowUUID.context)) } + private func showCloseAllConfirmation() { + let controller = AlertController(title: nil, message: nil, preferredStyle: .actionSheet) + controller.addAction(UIAlertAction(title: .AppMenu.AppMenuCloseAllTabsTitleString, + style: .default, + handler: { _ in self.confirmCloseAll() }), + accessibilityIdentifier: AccessibilityIdentifiers.TabTray.deleteCloseAllButton) + controller.addAction(UIAlertAction(title: .TabTrayCloseAllTabsPromptCancel, + style: .cancel, + handler: nil), + accessibilityIdentifier: AccessibilityIdentifiers.TabTray.deleteCancelButton) + controller.popoverPresentationController?.barButtonItem = deleteButton + present(controller, animated: true, completion: nil) + } + + private func confirmCloseAll() { + store.dispatch(TabPanelAction.confirmCloseAllTabs(windowUUID.context)) + } + @objc private func newTabButtonTapped() { let context = AddNewTabContext(urlRequest: nil, isPrivate: tabTrayState.isPrivateMode, windowUUID: windowUUID)