Skip to content

Commit cbd3a24

Browse files
feat: Floating panel can be used for both schedule and snooze
1 parent 99ab0b3 commit cbd3a24

12 files changed

+144
-69
lines changed

Mail/Views/Alerts/CustomScheduleAlertView.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ struct CustomScheduleAlertView: View {
9494
}
9595

9696
confirmAction(selectedDate)
97+
UserDefaults.shared[keyPath: type.lastCustomScheduleDateKeyPath] = selectedDate
9798
matomo.track(eventWithCategory: type.matomoCategory, name: "customSchedule")
9899
}
99100
}

Mail/Views/New Message/ComposeMessageView.swift

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -267,7 +267,7 @@ struct ComposeMessageView: View {
267267
changeFolderAction: changeSelectedFolder
268268
) {
269269
mainViewState.isShowingMyKSuiteUpgrade = true
270-
matomo.track(eventWithCategory: .myKSuiteUpgrade, name: "dailyLimitReachedUpgrade")
270+
matomo.track(eventWithCategory: .myKSuiteUpgradeBottomSheet, name: "dailyLimitReachedUpgrade")
271271
}
272272
}
273273
.customAlert(item: $isShowingAlert) { alert in
@@ -304,10 +304,9 @@ struct ComposeMessageView: View {
304304
.matomoView(view: ["ComposeMessage"])
305305
.scheduleFloatingPanel(
306306
isPresented: $isShowingSchedulePanel,
307-
draftSaveOption: $draft.action,
308-
draftDate: $draft.scheduleDate,
309-
mailboxManager: mailboxManager,
310-
completionHandler: dismissMessageView
307+
type: .scheduledDraft,
308+
initialDate: draft.scheduleDate,
309+
completionHandler: didScheduleDraft
311310
)
312311
}
313312

@@ -338,6 +337,13 @@ struct ComposeMessageView: View {
338337
}
339338
}
340339

340+
private func didScheduleDraft(_ date: Date) {
341+
draft.action = .schedule
342+
draft.date = date
343+
344+
dismissMessageView()
345+
}
346+
341347
private func didTouchSend() {
342348
guard !draft.subject.isEmpty else {
343349
matomo.track(eventWithCategory: .newMessage, name: "sendWithoutSubject")
@@ -360,7 +366,7 @@ struct ComposeMessageView: View {
360366
message: MailResourcesStrings.Localizable.myKSuiteSpaceFullAlert,
361367
action: IKSnackBar.Action(title: MailResourcesStrings.Localizable.buttonUpgrade) {
362368
mainViewState.isShowingMyKSuiteUpgrade = true
363-
matomo.track(eventWithCategory: .myKSuiteUpgrade, name: "notEnoughStorageUpgrade")
369+
matomo.track(eventWithCategory: .myKSuiteUpgradeBottomSheet, name: "notEnoughStorageUpgrade")
364370
}
365371
)
366372
return

Mail/Views/Schedule/CustomScheduleButton.swift

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
*/
1818

1919
import DesignSystem
20+
import InfomaniakCoreCommonUI
2021
import InfomaniakDI
2122
import MailCore
2223
import MailCoreUI
@@ -25,12 +26,15 @@ import MyKSuite
2526
import SwiftUI
2627

2728
struct CustomScheduleButton: View {
29+
@LazyInjectService private var matomo: MatomoUtils
30+
2831
@Environment(\.dismiss) private var dismiss
32+
@EnvironmentObject private var mailboxManager: MailboxManager
2933

30-
@Binding var customSchedule: Bool
34+
@Binding var isShowingCustomScheduleAlert: Bool
3135
@Binding var isShowingMyKSuiteUpgrade: Bool
3236

33-
let isMyKSuiteStandard: Bool
37+
let type: ScheduleType
3438

3539
var body: some View {
3640
Button(action: showCustomSchedulePicker) {
@@ -42,7 +46,7 @@ struct CustomScheduleButton: View {
4246
.textStyle(.body)
4347
.frame(maxWidth: .infinity, alignment: .leading)
4448

45-
if isMyKSuiteStandard {
49+
if mailboxManager.mailbox.isMyKSuiteFree {
4650
MyKSuitePlusChip()
4751
}
4852

@@ -53,11 +57,24 @@ struct CustomScheduleButton: View {
5357
}
5458

5559
private func showCustomSchedulePicker() {
56-
if isMyKSuiteStandard {
60+
if mailboxManager.mailbox.isMyKSuiteFree {
61+
let eventName = type == .scheduledDraft ? "scheduledCustomDate" : "snoozeCustomDate"
62+
matomo.track(eventWithCategory: .myKSuiteUpgradeBottomSheet, name: eventName)
5763
isShowingMyKSuiteUpgrade = true
5864
} else {
59-
customSchedule = true
65+
matomo.track(eventWithCategory: type.matomoCategory, name: "customSchedule")
66+
isShowingCustomScheduleAlert = true
6067
}
68+
6169
dismiss()
6270
}
6371
}
72+
73+
#Preview {
74+
CustomScheduleButton(
75+
isShowingCustomScheduleAlert: .constant(true),
76+
isShowingMyKSuiteUpgrade: .constant(false),
77+
type: .scheduledDraft
78+
)
79+
.environmentObject(PreviewHelper.sampleMailboxManager)
80+
}

Mail/Views/Schedule/ScheduleFloatingPanel.swift

Lines changed: 35 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -27,58 +27,63 @@ import RealmSwift
2727
import SwiftModalPresentation
2828
import SwiftUI
2929

30+
extension ScheduleType {
31+
var floatingPanelTitle: String {
32+
switch self {
33+
case .scheduledDraft:
34+
return MailResourcesStrings.Localizable.scheduleSendingTitle
35+
case .snooze:
36+
return MailResourcesStrings.Localizable.actionSnooze
37+
}
38+
}
39+
}
40+
3041
extension View {
3142
func scheduleFloatingPanel(
3243
isPresented: Binding<Bool>,
33-
draftSaveOption: Binding<SaveDraftOption?>,
34-
draftDate: Binding<Date?>,
35-
mailboxManager: MailboxManager,
36-
completionHandler: (() -> Void)? = nil
44+
type: ScheduleType,
45+
initialDate: Date? = nil,
46+
completionHandler: @escaping (Date) -> Void
3747
) -> some View {
38-
modifier(ScheduleFloatingPanel(
39-
isPresented: isPresented,
40-
draftSaveOption: draftSaveOption,
41-
draftDate: draftDate,
42-
type: .scheduledDraft, // TODO: Change it if necessary
43-
mailBoxManager: mailboxManager,
44-
completionHandler: completionHandler
45-
))
48+
modifier(
49+
ScheduleFloatingPanel(
50+
isShowingFloatingPanel: isPresented,
51+
type: type,
52+
initialDate: initialDate,
53+
completionHandler: completionHandler
54+
)
55+
)
4656
}
4757
}
4858

4959
struct ScheduleFloatingPanel: ViewModifier {
50-
@AppStorage(UserDefaults.shared.key(.lastScheduleInterval)) private var lastScheduleInterval: Double = 0
51-
5260
@State private var isShowingMyKSuiteUpgrade = false
5361
@State private var panelShouldBeShown = false
54-
@ModalState(wrappedValue: false, context: ContextKeys.schedule) private var customSchedule: Bool
62+
@ModalState(wrappedValue: false, context: ContextKeys.schedule) private var isShowingCustomScheduleAlert: Bool
5563

56-
@Binding var isPresented: Bool
57-
@Binding var draftSaveOption: SaveDraftOption?
58-
@Binding var draftDate: Date?
64+
@Binding var isShowingFloatingPanel: Bool
5965

6066
let type: ScheduleType
61-
let mailBoxManager: MailboxManager
62-
let completionHandler: (() -> Void)?
67+
let initialDate: Date?
68+
let completionHandler: (Date) -> Void
6369

6470
func body(content: Content) -> some View {
6571
content
66-
.floatingPanel(isPresented: $isPresented, title: MailResourcesStrings.Localizable.scheduleSendingTitle) {
72+
.floatingPanel(isPresented: $isShowingFloatingPanel, title: type.floatingPanelTitle) {
6773
ScheduleFloatingPanelView(
68-
customSchedule: $customSchedule,
74+
isShowingCustomScheduleAlert: $isShowingCustomScheduleAlert,
6975
isShowingMyKSuiteUpgrade: $isShowingMyKSuiteUpgrade,
70-
isMyKSuiteStandard: mailBoxManager.mailbox.isFree && mailBoxManager.mailbox.isLimited,
71-
lastScheduleInterval: lastScheduleInterval,
72-
setScheduleAction: setSchedule
76+
type: type,
77+
setScheduleAction: completionHandler
7378
)
7479
}
75-
.customAlert(isPresented: $customSchedule) {
76-
CustomScheduleAlertView(type: type, date: draftDate, confirmAction: setCustomSchedule) {
80+
.customAlert(isPresented: $isShowingCustomScheduleAlert) {
81+
CustomScheduleAlertView(type: type, date: initialDate, confirmAction: completionHandler) {
7782
panelShouldBeShown = true
7883
}
7984
.onDisappear {
8085
if panelShouldBeShown {
81-
isPresented = true
86+
isShowingFloatingPanel = true
8287
panelShouldBeShown = false
8388
}
8489
}
@@ -87,13 +92,7 @@ struct ScheduleFloatingPanel: ViewModifier {
8792
}
8893

8994
private func setSchedule(_ scheduleDate: Date) {
90-
draftSaveOption = .schedule
91-
draftDate = scheduleDate
92-
completionHandler?()
93-
}
94-
95-
private func setCustomSchedule(_ scheduleDate: Date) {
96-
lastScheduleInterval = scheduleDate.timeIntervalSince1970
97-
setSchedule(scheduleDate)
95+
// draftSaveOption = .schedule
96+
// draftDate = scheduleDate
9897
}
9998
}

Mail/Views/Schedule/ScheduleFloatingPanelView.swift

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -23,32 +23,41 @@ import RealmSwift
2323
import SwiftUI
2424

2525
struct ScheduleFloatingPanelView: View {
26-
@Binding var customSchedule: Bool
26+
@Binding var isShowingCustomScheduleAlert: Bool
2727
@Binding var isShowingMyKSuiteUpgrade: Bool
2828

29-
let isMyKSuiteStandard: Bool
30-
let lastScheduleInterval: Double
29+
let type: ScheduleType
3130
let setScheduleAction: (Date) -> Void
3231

3332
private var scheduleOptions: [ScheduleSendOption] {
33+
let lastScheduledDate = UserDefaults.shared[keyPath: type.lastCustomScheduleDateKeyPath]
34+
3435
var allSimpleCases = ScheduleSendOption.allSimpleCases
35-
allSimpleCases.insert(ScheduleSendOption.lastSchedule(value: Date(timeIntervalSince1970: lastScheduleInterval)), at: 0)
36+
allSimpleCases.insert(ScheduleSendOption.lastSchedule(value: lastScheduledDate), at: 0)
3637
return allSimpleCases.filter { $0.shouldBeDisplayedNow }
3738
}
3839

3940
var body: some View {
4041
VStack(spacing: 0) {
4142
ForEach(scheduleOptions) { option in
42-
ScheduleOptionView(option: option, setScheduleAction: setScheduleAction)
43+
ScheduleOptionView(type: type, option: option, setScheduleAction: setScheduleAction)
4344

4445
IKDivider(type: .item)
4546
}
4647

4748
CustomScheduleButton(
48-
customSchedule: $customSchedule,
49+
isShowingCustomScheduleAlert: $isShowingCustomScheduleAlert,
4950
isShowingMyKSuiteUpgrade: $isShowingMyKSuiteUpgrade,
50-
isMyKSuiteStandard: isMyKSuiteStandard
51+
type: type
5152
)
5253
}
5354
}
5455
}
56+
57+
#Preview {
58+
ScheduleFloatingPanelView(
59+
isShowingCustomScheduleAlert: .constant(false),
60+
isShowingMyKSuiteUpgrade: .constant(false),
61+
type: .scheduledDraft
62+
) { _ in }
63+
}

Mail/Views/Schedule/ScheduleOptionView.swift

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -28,16 +28,13 @@ struct ScheduleOptionView: View {
2828

2929
@Environment(\.dismiss) private var dismiss
3030

31+
let type: ScheduleType
3132
let option: ScheduleSendOption
3233
let setScheduleAction: (Date) -> Void
3334

3435
var body: some View {
3536
if let scheduleDate = option.date {
36-
Button {
37-
matomo.track(eventWithCategory: .scheduleSend, name: option.matomoName)
38-
setScheduleAction(scheduleDate)
39-
dismiss()
40-
} label: {
37+
Button(action: didTapOption) {
4138
HStack(spacing: IKPadding.medium) {
4239
option.icon
4340
.iconSize(.large)
@@ -53,16 +50,24 @@ struct ScheduleOptionView: View {
5350
.padding(value: .medium)
5451
}
5552
}
53+
54+
private func didTapOption() {
55+
guard let scheduleDate = option.date else { return }
56+
57+
matomo.track(eventWithCategory: type.matomoCategory, name: option.matomoName)
58+
setScheduleAction(scheduleDate)
59+
dismiss()
60+
}
5661
}
5762

5863
#Preview {
59-
ScheduleOptionView(option: .nextMondayAfternoon) { date in
64+
ScheduleOptionView(type: .scheduledDraft, option: .nextMondayAfternoon) { date in
6065
print("Button \(date.formatted(.scheduleOption)) clicked !")
6166
}
62-
ScheduleOptionView(option: .lastSchedule(value: .now)) { date in
67+
ScheduleOptionView(type: .snooze, option: .lastSchedule(value: .now)) { date in
6368
print("Button \(date.formatted(.scheduleOption)) clicked !")
6469
}
65-
ScheduleOptionView(option: .thisAfternoon) { date in
70+
ScheduleOptionView(type: .scheduledDraft, option: .thisAfternoon) { date in
6671
print("Button \(date.formatted(.scheduleOption)) clicked !")
6772
}
6873
}

Mail/Views/Schedule/ScheduleType.swift

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,11 +32,24 @@ enum ScheduleType: Sendable {
3232
}
3333
}
3434

35-
private var minimumInterval: TimeInterval {
35+
var lastCustomScheduleDateKeyPath: ReferenceWritableKeyPath<UserDefaults, Date> {
36+
switch self {
37+
case .scheduledDraft:
38+
return \.lastCustomScheduledDraftDate
39+
case .snooze:
40+
return \.lastCustomSnoozeDate
41+
}
42+
}
43+
}
44+
45+
// MARK: - Minimum and maximum date
46+
47+
extension ScheduleType {
48+
internal var minimumInterval: TimeInterval {
3649
return 60 * 5 // 5 minutes
3750
}
3851

39-
private var maximumInterval: TimeInterval {
52+
internal var maximumInterval: TimeInterval {
4053
switch self {
4154
case .scheduledDraft:
4255
return 60 * 60 * 24 * 365 * 10 // 10 years

Mail/Views/Settings/Mailbox/MailboxSignatureSettingsView.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ struct MailboxSignatureSettingsView: View {
3535
let mailboxManager: MailboxManager
3636

3737
private var isKSuiteLimited: Bool {
38-
signatures.defaultSignature != nil && mailboxManager.mailbox.isFree && mailboxManager.mailbox.isLimited
38+
signatures.defaultSignature != nil && mailboxManager.mailbox.isMyKSuiteFree
3939
}
4040

4141
init(mailboxManager: MailboxManager) {
@@ -56,7 +56,7 @@ struct MailboxSignatureSettingsView: View {
5656
) {
5757
if isKSuiteLimited {
5858
isShowingMyKSuiteUpgrade = true
59-
matomo.track(eventWithCategory: .myKSuiteUpgrade, name: "emptySignature")
59+
matomo.track(eventWithCategory: .myKSuiteUpgradeBottomSheet, name: "emptySignature")
6060
} else {
6161
setAsDefault(nil)
6262
}

MailCore/Cache/DraftManager.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,7 @@ public final class DraftManager {
191191
mailboxManager: MailboxManager,
192192
showSnackbar: Bool,
193193
myKSuiteUpgradeAction: (() -> Void)?) async {
194-
if mailboxManager.mailbox.isFree && mailboxManager.mailbox.isLimited {
194+
if mailboxManager.mailbox.isMyKSuiteFree {
195195
alertDisplayable.show(
196196
message: MailResourcesStrings.Localizable.errorSendLimitExceeded,
197197
action: (MailResourcesStrings.Localizable.buttonUpgrade, {

MailCore/Models/Mailbox.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,10 @@ public class Mailbox: Object, Codable, Identifiable {
7575
return "mailbox-\(mailboxId)"
7676
}
7777

78+
public var isMyKSuiteFree: Bool {
79+
return isFree && isLimited
80+
}
81+
7882
enum CodingKeys: String, CodingKey {
7983
case uuid
8084
case email

0 commit comments

Comments
 (0)