Skip to content

Commit b8fb76c

Browse files
feat(Snooze): Display alert when user tries to move a snoozed message/thread (#1771)
2 parents 1c5ed7d + 2c07d82 commit b8fb76c

16 files changed

+231
-145
lines changed

Mail/Utils/ShortcutModifier.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ struct ShortcutModifier: ViewModifier {
3131

3232
@LazyInjectService private var matomo: MatomoUtils
3333

34-
@ModalState private var flushAlert: FlushAlertState?
34+
@ModalState private var destructiveAlert: DestructiveActionAlertState?
3535

3636
@ObservedObject var viewModel: ThreadListViewModel
3737
@ObservedObject var multipleSelectionViewModel: MultipleSelectionViewModel
@@ -59,8 +59,8 @@ struct ShortcutModifier: ViewModifier {
5959

6060
content
6161
}
62-
.customAlert(item: $flushAlert) { item in
63-
FlushFolderAlertView(flushAlert: item, folder: viewModel.frozenFolder)
62+
.customAlert(item: $destructiveAlert) { item in
63+
DestructiveActionAlertView(destructiveAlert: item)
6464
}
6565
}
6666

@@ -79,7 +79,7 @@ struct ShortcutModifier: ViewModifier {
7979
try await actionsManager.performAction(
8080
target: messages,
8181
action: .delete,
82-
origin: .shortcut(originFolder: viewModel.frozenFolder, nearestFlushAlert: $flushAlert)
82+
origin: .shortcut(originFolder: viewModel.frozenFolder, nearestDestructiveAlert: $destructiveAlert)
8383
)
8484
}
8585
}

Mail/Views/Bottom sheets/Actions/ActionsPanelViewModifier.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ struct ActionsPanelViewModifier: ViewModifier {
5151
@ModalState private var blockSenderAlert: BlockRecipientAlertState?
5252
@ModalState private var blockSendersList: BlockRecipientState?
5353
@ModalState private var messagesToMove: [Message]?
54-
@ModalState private var flushAlert: FlushAlertState?
54+
@ModalState private var destructiveAlert: DestructiveActionAlertState?
5555
@ModalState private var shareMailLink: ShareMailLinkResult?
5656
@ModalState private var messagesToSnooze: [Message]?
5757
@ModalState private var messagesToDownload: [Message]?
@@ -66,7 +66,7 @@ struct ActionsPanelViewModifier: ViewModifier {
6666
.floatingPanel(
6767
source: panelSource,
6868
originFolder: originFolder?.freezeIfNeeded(),
69-
nearestFlushAlert: $flushAlert,
69+
nearestDestructiveAlert: $destructiveAlert,
7070
nearestMessagesToMoveSheet: $messagesToMove,
7171
nearestBlockSenderAlert: $blockSenderAlert,
7272
nearestBlockSendersList: $blockSendersList,
@@ -130,8 +130,8 @@ struct ActionsPanelViewModifier: ViewModifier {
130130
completionHandler: completionHandler
131131
)
132132
}
133-
.customAlert(item: $flushAlert) { item in
134-
FlushFolderAlertView(flushAlert: item, folder: originFolder)
133+
.customAlert(item: $destructiveAlert) { item in
134+
DestructiveActionAlertView(destructiveAlert: item)
135135
}
136136
.customAlert(item: $messagesToDownload) { messages in
137137
ConfirmationSaveThreadInKdrive(targetMessages: messages)
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
/*
2+
Infomaniak Mail - iOS App
3+
Copyright (C) 2024 Infomaniak Network SA
4+
5+
This program is free software: you can redistribute it and/or modify
6+
it under the terms of the GNU General Public License as published by
7+
the Free Software Foundation, either version 3 of the License, or
8+
(at your option) any later version.
9+
10+
This program is distributed in the hope that it will be useful,
11+
but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
GNU General Public License for more details.
14+
15+
You should have received a copy of the GNU General Public License
16+
along with this program. If not, see <http://www.gnu.org/licenses/>.
17+
*/
18+
19+
import DesignSystem
20+
import InfomaniakCoreCommonUI
21+
import InfomaniakCoreSwiftUI
22+
import InfomaniakDI
23+
import MailCore
24+
import MailResources
25+
import SwiftUI
26+
27+
extension DestructiveActionAlertState {
28+
var title: String {
29+
switch type {
30+
case .flushFolder(let frozenFolder):
31+
switch frozenFolder?.role {
32+
case .spam:
33+
return MailResourcesStrings.Localizable.threadListEmptySpamButton
34+
case .trash:
35+
return MailResourcesStrings.Localizable.threadListEmptyTrashButton
36+
default:
37+
return ""
38+
}
39+
40+
case .permanentlyDelete(let impactedMessages):
41+
return MailResourcesStrings.Localizable.threadListDeletionConfirmationAlertTitle(impactedMessages)
42+
43+
case .deleteSnooze:
44+
return MailResourcesStrings.Localizable.actionDelete
45+
46+
case .archiveSnooze:
47+
return MailResourcesStrings.Localizable.actionArchive
48+
49+
case .moveSnooze:
50+
return MailResourcesStrings.Localizable.actionMove
51+
}
52+
}
53+
54+
var description: String {
55+
switch type {
56+
case .flushFolder:
57+
return MailResourcesStrings.Localizable.threadListEmptyFolderAlertDescription
58+
59+
case .permanentlyDelete(let impactedMessages):
60+
return MailResourcesStrings.Localizable.threadListDeletionConfirmationAlertDescription(impactedMessages)
61+
62+
case .deleteSnooze(let impactedMessages):
63+
return MailResourcesStrings.Localizable.snoozeDeleteConfirmAlertDescription(impactedMessages)
64+
65+
case .archiveSnooze(let impactedMessages):
66+
return MailResourcesStrings.Localizable.snoozeArchiveConfirmAlertDescription(impactedMessages)
67+
68+
case .moveSnooze(let impactedMessages):
69+
return MailResourcesStrings.Localizable.snoozeArchiveConfirmAlertDescription(impactedMessages)
70+
}
71+
}
72+
}
73+
74+
struct DestructiveActionAlertView: View {
75+
@LazyInjectService private var matomo: MatomoUtils
76+
77+
let destructiveAlert: DestructiveActionAlertState
78+
79+
var body: some View {
80+
VStack(alignment: .leading, spacing: IKPadding.large) {
81+
Text(destructiveAlert.title)
82+
.textStyle(.bodyMedium)
83+
Text(destructiveAlert.description)
84+
.textStyle(.body)
85+
86+
ModalButtonsView(primaryButtonTitle: MailResourcesStrings.Localizable.buttonConfirm) {
87+
if case .flushFolder(let frozenFolder) = destructiveAlert.type, let frozenFolder {
88+
matomo.track(eventWithCategory: .threadList, name: "empty\(frozenFolder.matomoName.capitalized)Confirm")
89+
}
90+
await destructiveAlert.completion()
91+
}
92+
}
93+
}
94+
}
95+
96+
#Preview {
97+
DestructiveActionAlertView(destructiveAlert: DestructiveActionAlertState(type: .deleteSnooze(10)) { /* Preview */ })
98+
}

Mail/Views/Thread List/FlushFolderAlertView.swift

Lines changed: 0 additions & 79 deletions
This file was deleted.

Mail/Views/Thread List/FlushFolderView.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ struct FlushFolderView: View {
4040
let folder: Folder
4141
let mailboxManager: MailboxManager
4242

43-
@Binding var flushAlert: FlushAlertState?
43+
@Binding var destructiveAlert: DestructiveActionAlertState?
4444

4545
private var label: String {
4646
Self.labels[folder.role ?? .trash] ?? ""
@@ -60,7 +60,7 @@ struct FlushFolderView: View {
6060
matomo.track(eventWithCategory: .threadList, name: "empty\(folder.matomoName.capitalized)")
6161

6262
let frozenFolder = folder.freezeIfNeeded()
63-
flushAlert = FlushAlertState {
63+
destructiveAlert = DestructiveActionAlertState(type: .flushFolder(frozenFolder)) {
6464
await tryOrDisplayError {
6565
_ = try await mailboxManager.flushFolder(folder: frozenFolder)
6666
}
@@ -87,5 +87,5 @@ struct FlushFolderView: View {
8787
#Preview {
8888
FlushFolderView(folder: PreviewHelper.sampleFolder,
8989
mailboxManager: PreviewHelper.sampleMailboxManager,
90-
flushAlert: .constant(nil))
90+
destructiveAlert: .constant(nil))
9191
}

Mail/Views/Thread List/ThreadListCellContextMenu.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,6 @@ struct ThreadListCellContextMenu: ViewModifier {
7878
guard action != .archive else {
7979
return nil
8080
}
81-
return action.isDestructive ? .destructive : nil
81+
return action.isDestructive(for: thread) ? .destructive : nil
8282
}
8383
}

Mail/Views/Thread List/ThreadListModifiers.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ struct ThreadListToolbar: ViewModifier {
123123
action: action,
124124
origin: .multipleSelection(
125125
originFolder: originFolder,
126-
nearestFlushAlert: $mainViewState.flushAlert,
126+
nearestDestructiveAlert: $mainViewState.destructiveAlert,
127127
nearestMessagesToMoveSheet: nil
128128
)
129129
)

Mail/Views/Thread List/ThreadListSwipeAction.swift

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -33,15 +33,15 @@ private struct SwipeActionView: View {
3333

3434
@Binding var actionPanelMessages: [Message]?
3535
@Binding var moveSheetMessages: [Message]?
36-
@Binding var flushAlert: FlushAlertState?
36+
@Binding var destructiveAlert: DestructiveActionAlertState?
3737

3838
let viewModel: ThreadListable
3939
let thread: Thread
4040
let action: Action
4141

4242
private var isDestructive: Bool {
43-
let shouldWarnBeforeDeletion = thread.folder?.shouldWarnBeforeDeletion ?? false
44-
return action.isDestructive && networkMonitor.isConnected && !shouldWarnBeforeDeletion
43+
guard networkMonitor.isConnected else { return false }
44+
return action.isDestructive(for: thread)
4545
}
4646

4747
var body: some View {
@@ -56,7 +56,7 @@ private struct SwipeActionView: View {
5656
originFolder: thread.folder,
5757
nearestMessagesActionsPanel: $actionPanelMessages,
5858
nearestMessagesToMoveSheet: $moveSheetMessages,
59-
nearestFlushAlert: $flushAlert
59+
nearestDestructiveAlert: $destructiveAlert
6060
)
6161
)
6262

@@ -125,7 +125,7 @@ struct ThreadListSwipeActions: ViewModifier {
125125
SwipeActionView(
126126
actionPanelMessages: $actionPanelMessages,
127127
moveSheetMessages: $messagesToMove,
128-
flushAlert: $mainViewState.flushAlert,
128+
destructiveAlert: $mainViewState.destructiveAlert,
129129
viewModel: viewModel,
130130
thread: thread,
131131
action: action
@@ -149,7 +149,7 @@ extension View {
149149
SwipeActionView(
150150
actionPanelMessages: .constant(nil),
151151
moveSheetMessages: .constant(nil),
152-
flushAlert: .constant(nil),
152+
destructiveAlert: .constant(nil),
153153
viewModel: ThreadListViewModel(mailboxManager: PreviewHelper.sampleMailboxManager,
154154
frozenFolder: PreviewHelper.sampleFolder,
155155
selectedThreadOwner: PreviewHelper.mockSelectedThreadOwner),

Mail/Views/Thread List/ThreadListView.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ struct ThreadListView: View {
103103
FlushFolderView(
104104
folder: viewModel.frozenFolder,
105105
mailboxManager: viewModel.mailboxManager,
106-
flushAlert: $mainViewState.flushAlert
106+
destructiveAlert: $mainViewState.destructiveAlert
107107
)
108108
.threadListCellAppearance()
109109
}
@@ -220,8 +220,8 @@ struct ThreadListView: View {
220220
.task(id: viewModel.mailboxManager.mailbox.id) {
221221
updateFetchingTask()
222222
}
223-
.customAlert(item: $mainViewState.flushAlert) { item in
224-
FlushFolderAlertView(flushAlert: item, folder: viewModel.frozenFolder)
223+
.customAlert(item: $mainViewState.destructiveAlert) { item in
224+
DestructiveActionAlertView(destructiveAlert: item)
225225
}
226226
.customAlert(isPresented: $isShowingUpdateAlert) {
227227
// swiftlint:disable:next trailing_closure

Mail/Views/Thread/WebView/ThreadViewToolbarModifier.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ struct ThreadViewToolbarModifier: ViewModifier {
4343
@State private var replyOrReplyAllMessage: Message?
4444
@State private var messagesToMove: [Message]?
4545

46-
@ModalState private var nearestFlushAlert: FlushAlertState?
46+
@ModalState private var destructiveAlert: DestructiveActionAlertState?
4747

4848
private let frozenThread: Thread
4949

@@ -111,8 +111,8 @@ struct ThreadViewToolbarModifier: ViewModifier {
111111
}
112112
}
113113
}
114-
.customAlert(item: $nearestFlushAlert) { item in
115-
FlushFolderAlertView(flushAlert: item)
114+
.customAlert(item: $destructiveAlert) { item in
115+
DestructiveActionAlertView(destructiveAlert: item)
116116
}
117117
}
118118

@@ -147,7 +147,7 @@ struct ThreadViewToolbarModifier: ViewModifier {
147147
try await actionsManager.performAction(
148148
target: frozenMessages,
149149
action: action,
150-
origin: .toolbar(originFolder: frozenFolder, nearestFlushAlert: $nearestFlushAlert)
150+
origin: .toolbar(originFolder: frozenFolder, nearestDestructiveAlert: $destructiveAlert)
151151
)
152152
}
153153
}

0 commit comments

Comments
 (0)