diff --git a/LeCountdown/Model/Model+Extensions.swift b/LeCountdown/Model/Model+Extensions.swift index da88dad..cfa7ffd 100644 --- a/LeCountdown/Model/Model+Extensions.swift +++ b/LeCountdown/Model/Model+Extensions.swift @@ -32,10 +32,6 @@ extension AbstractSoundTimer { return self.playables.reduce(Set()) { $0.union($1.soundList) } } -// func setSounds(_ sounds: Set) { -// self.soundList = sounds.stringRepresentation -// } - var confirmationSounds: Set { if let confirmationSoundList { return Set(confirmationSoundList.enumItems()) @@ -53,15 +49,22 @@ extension AbstractSoundTimer { sounds = sounds.filter { !$0.isRestricted } } - // remove last played sound if the playlist has at least 3 sounds + // remove last played sound if at least 3 sounds remains + if sounds.count > 2, + let lastSoundId = Preferences.lastSoundPlayed, + let lastSound = Sound(rawValue: lastSoundId) { + sounds.remove(lastSound) + } + // remove last played sound by timer if the playlist has at least 3 sounds if sounds.count > 2, - let lastSoundId = Preferences.lastSelectedSound[self.stringId], + let lastSoundId = Preferences.lastSelectedSoundByTimer[self.stringId], let lastSound = Sound(rawValue: lastSoundId) { sounds.remove(lastSound) } if let random = sounds.randomElement() { - Preferences.lastSelectedSound[self.stringId] = random.id + Preferences.lastSelectedSoundByTimer[self.stringId] = random.id + Preferences.lastSoundPlayed = random.id return random } diff --git a/LeCountdown/Sound/DelaySoundPlayer.swift b/LeCountdown/Sound/DelaySoundPlayer.swift index 9e26f8b..6cc00a6 100644 --- a/LeCountdown/Sound/DelaySoundPlayer.swift +++ b/LeCountdown/Sound/DelaySoundPlayer.swift @@ -47,7 +47,7 @@ import AVFoundation Logger.log("self._player.deviceCurrentTime = \(self._player.deviceCurrentTime)") let time: TimeInterval = self._player.deviceCurrentTime + duration let result = self._player.play(atTime: time) - FileLogger.log("play \(String(describing: self._player.url)) >atTime: \(time), result = \(result), isMainThread = \(Thread.isMainThread)") + FileLogger.log("play \(String(describing: self._player.url)) >atTime: \(time.timeFormatted), result = \(result), isMainThread = \(Thread.isMainThread)") if !result { throw SoundPlayerError.playReturnedFalse diff --git a/LeCountdown/Utils/Codable+Extensions.swift b/LeCountdown/Utils/Codable+Extensions.swift index 576ea02..382e747 100644 --- a/LeCountdown/Utils/Codable+Extensions.swift +++ b/LeCountdown/Utils/Codable+Extensions.swift @@ -19,6 +19,7 @@ extension Encodable { var jsonData: Data? { let encoder: JSONEncoder = JSONEncoder() + encoder.outputFormatting = .prettyPrinted do { return try encoder.encode(self) } catch { diff --git a/LeCountdown/Utils/Preferences.swift b/LeCountdown/Utils/Preferences.swift index 63453bf..393cfea 100644 --- a/LeCountdown/Utils/Preferences.swift +++ b/LeCountdown/Utils/Preferences.swift @@ -15,6 +15,7 @@ enum PreferenceKey: String { case playCancellationSound case showSilentModeAlert case soundDurations + case lastSoundPlayedByTimer case lastSoundPlayed case tips case timerSiriTips @@ -26,7 +27,9 @@ class Preferences { @UserDefault(PreferenceKey.countdowns.rawValue, defaultValue: [:]) static var savedCountdowns: [String : DateInterval] @UserDefault(PreferenceKey.soundDurations.rawValue, defaultValue: [:]) static var soundDurations: [String : TimeInterval] - @UserDefault(PreferenceKey.lastSoundPlayed.rawValue, defaultValue: [:]) static var lastSelectedSound: [String : Int] + @UserDefault(PreferenceKey.lastSoundPlayedByTimer.rawValue, defaultValue: [:]) static var lastSelectedSoundByTimer: [String : Int] + @UserDefault(PreferenceKey.lastSoundPlayed.rawValue, defaultValue: nil) static var lastSoundPlayed: Int? + @UserDefault(PreferenceKey.tips.rawValue, defaultValue: nil) static var lastShownTip: Int? @UserDefault(PreferenceKey.timerSiriTips.rawValue, defaultValue: []) static var timerSiriTips: Set @UserDefault(PreferenceKey.playConfirmationSound.rawValue, defaultValue: true) static var playConfirmationSound: Bool diff --git a/LeCountdown/Utils/TimeInterval+Extensions.swift b/LeCountdown/Utils/TimeInterval+Extensions.swift index 61da2e2..489e689 100644 --- a/LeCountdown/Utils/TimeInterval+Extensions.swift +++ b/LeCountdown/Utils/TimeInterval+Extensions.swift @@ -48,4 +48,11 @@ extension TimeInterval { Int((self*100).truncatingRemainder(dividingBy: 100)) } + var timeFormatted: String { + let dateformatter = DateFormatter() + dateformatter.dateStyle = .none + dateformatter.timeStyle = .short + return dateformatter.string(from: Date(timeIntervalSince1970: self)) + } + } diff --git a/LeCountdown/Views/ContentView.swift b/LeCountdown/Views/ContentView.swift index eacfb93..05d29ed 100644 --- a/LeCountdown/Views/ContentView.swift +++ b/LeCountdown/Views/ContentView.swift @@ -168,7 +168,6 @@ struct MainToolbarView: ToolbarContent { @State var showAddSheet: Bool = false @State var showTimerSheet: Bool = false @State var showStopwatchSheet: Bool = false - @State var showLogsSheet: Bool = false var body: some ToolbarContent { ToolbarItem(placement: .navigationBarLeading) { @@ -181,18 +180,18 @@ struct MainToolbarView: ToolbarContent { } } ToolbarItemGroup(placement: .navigationBarTrailing) { - Button { - withAnimation { - self.showLogsSheet.toggle() - } - } label: { - Image(systemName: "list.dash") - } - .sheet(isPresented: self.$showLogsSheet, content: { - NavigationStack { - LogsView().navigationTitle("Logs") - } - }) +// Button { +// withAnimation { +// self.showLogsSheet.toggle() +// } +// } label: { +// Image(systemName: "list.dash") +// } +// .sheet(isPresented: self.$showLogsSheet, content: { +// NavigationStack { +// LogsView().navigationTitle("Logs") +// } +// }) if self.haveRecords() { Button { withAnimation { @@ -219,7 +218,7 @@ struct MainToolbarView: ToolbarContent { } .sheet(isPresented: self.$showSettingsSheet, content: { SettingsView() - .presentationDetents([.height(240.0)]) + .presentationDetents([.height(280.0)]) }) Button { withAnimation { @@ -301,12 +300,11 @@ class TimerSpot : Identifiable, Equatable { struct Toolbar_Previews: PreviewProvider { static var previews: some View { NavigationStack { - Text("Hello") + Text(NSLocalizedString("Disclaimer", comment: "")).padding(32.0).multilineTextAlignment(.center) } .navigationTitle("Title") .toolbar { MainToolbarView(isEditing: .constant(false)) } - } } diff --git a/LeCountdown/Views/Reusable/MailView.swift b/LeCountdown/Views/Reusable/MailView.swift index b490b35..756fe0e 100644 --- a/LeCountdown/Views/Reusable/MailView.swift +++ b/LeCountdown/Views/Reusable/MailView.swift @@ -46,6 +46,14 @@ struct MailView: UIViewControllerRepresentable { vc.mailComposeDelegate = context.coordinator vc.setSubject(Bundle.main.applicationName) vc.setToRecipients(["laurent@staxriver.com"]) + + let lastLogs = FileLogger.main.logs.suffix(40).reversed() + let logs = lastLogs.map { $0.date.formattedDateTime + "\n" + $0.content } + let content = logs.joined(separator: "\n") + + if let logsData = content.data(using: .utf8) { + vc.addAttachmentData(logsData, mimeType: "text/plain", fileName: "logs.txt") + } return vc } diff --git a/LeCountdown/Views/SettingsView.swift b/LeCountdown/Views/SettingsView.swift index 59ec738..6b7d25c 100644 --- a/LeCountdown/Views/SettingsView.swift +++ b/LeCountdown/Views/SettingsView.swift @@ -14,18 +14,19 @@ struct SettingsView: View { @State var defaultVolume: Float = Preferences.defaultVolume @State var showMailView: Bool = false - + @State var showLogsSheet: Bool = false + var body: some View { Form { Toggle("Play confirmation sound", isOn: self.$confirmationSound) .onChange(of: self.confirmationSound) { newValue in - Preferences.playConfirmationSound = newValue - } + Preferences.playConfirmationSound = newValue + } Toggle("Play cancellation sound", isOn: self.$cancellationSound) .onChange(of: self.cancellationSound) { newValue in - Preferences.playCancellationSound = newValue - } + Preferences.playCancellationSound = newValue + } HStack { Text("Default Volume") Spacer() @@ -40,6 +41,18 @@ struct SettingsView: View { } label: { Text("Contact us") } + Button { + withAnimation { + self.showLogsSheet.toggle() + } + } label: { + Text("Logs") + } + .sheet(isPresented: self.$showLogsSheet, content: { + NavigationStack { + LogsView().navigationTitle("Logs") + } + }) }.sheet(isPresented: $showMailView) { MailView(isShowing: $showMailView) } diff --git a/LeCountdown/Views/TimersView.swift b/LeCountdown/Views/TimersView.swift index 420097e..e6ead01 100644 --- a/LeCountdown/Views/TimersView.swift +++ b/LeCountdown/Views/TimersView.swift @@ -68,7 +68,7 @@ struct TimersView: View { } .padding(.horizontal, itemSpacing) } else { - Text("You'll find your timers here. Start by creating them on the left screen") + Text("Disclaimer") .padding() .multilineTextAlignment(.center) } diff --git a/LeCountdown/en.lproj/Localizable.strings b/LeCountdown/en.lproj/Localizable.strings index 6d741f3..f5c092c 100644 --- a/LeCountdown/en.lproj/Localizable.strings +++ b/LeCountdown/en.lproj/Localizable.strings @@ -1 +1,2 @@ "You'll find your timers here. Start by creating them on the left screen" = "You'll find your timers here.\nStart by creating using the top right button!"; +"Disclaimer" = "This is a beta version of Enchant.\n\nPlease don't depend on the app for critical events :)\n\n If you ever encounter an issue, please let me know about it by going in the settings."; diff --git a/LeCountdown/fr.lproj/Localizable.strings b/LeCountdown/fr.lproj/Localizable.strings index e450788..9c803c0 100644 --- a/LeCountdown/fr.lproj/Localizable.strings +++ b/LeCountdown/fr.lproj/Localizable.strings @@ -265,3 +265,4 @@ "Default Volume" = "Volume par défaut"; "Cancel %@" = "Annuler %@"; "Calendar" = "Calendrier"; +"Disclaimer" = "Ceci est une version beta d'Enchante.\n\nVeillez à ne dépendre de l'app pour des évènements trop critiques :)\n\n Si jamais vous rencontrez un problème, merci de me contacter en allant dans les réglages.";