From 9d8db42edf378ef83421212fa44db886b82ae850 Mon Sep 17 00:00:00 2001 From: Laurent Date: Fri, 10 Mar 2023 16:03:46 +0100 Subject: [PATCH] Adds settings view --- LeCountdown.xcodeproj/project.pbxproj | 20 ++++------------ LeCountdown/Conductor.swift | 12 ++++++++-- LeCountdown/Utils/Preferences.swift | 2 ++ LeCountdown/Views/ContentView.swift | 19 ++++++++++++++-- LeCountdown/Views/SettingsView.swift | 29 ++++++++++++++++++++++++ LeCountdown/fr.lproj/Localizable.strings | 1 + 6 files changed, 63 insertions(+), 20 deletions(-) create mode 100644 LeCountdown/Views/SettingsView.swift diff --git a/LeCountdown.xcodeproj/project.pbxproj b/LeCountdown.xcodeproj/project.pbxproj index 706234a..ed20af1 100644 --- a/LeCountdown.xcodeproj/project.pbxproj +++ b/LeCountdown.xcodeproj/project.pbxproj @@ -69,12 +69,6 @@ C473C2FB29A8DC3A0056B38A /* LaunchWidgetAttributes.swift in Sources */ = {isa = PBXBuildFile; fileRef = C473C2F829A8DC0A0056B38A /* LaunchWidgetAttributes.swift */; }; C473C2FC29A8DC4B0056B38A /* Date+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4BA2B6929A4BE1800CB4FBA /* Date+Extensions.swift */; }; C473C2FD29A8DC690056B38A /* CoreDataRequests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C438C80C2982847300BF3EF9 /* CoreDataRequests.swift */; }; - C473C30329A91BB90056B38A /* en.xcloc in Resources */ = {isa = PBXBuildFile; fileRef = C473C30229A91BB90056B38A /* en.xcloc */; }; - C473C30429A91BB90056B38A /* en.xcloc in Resources */ = {isa = PBXBuildFile; fileRef = C473C30229A91BB90056B38A /* en.xcloc */; }; - C473C30529A91BB90056B38A /* en.xcloc in Resources */ = {isa = PBXBuildFile; fileRef = C473C30229A91BB90056B38A /* en.xcloc */; }; - C473C30729A91BCC0056B38A /* fr.xcloc in Resources */ = {isa = PBXBuildFile; fileRef = C473C30629A91BCB0056B38A /* fr.xcloc */; }; - C473C30829A91BCC0056B38A /* fr.xcloc in Resources */ = {isa = PBXBuildFile; fileRef = C473C30629A91BCB0056B38A /* fr.xcloc */; }; - C473C30929A91BCC0056B38A /* fr.xcloc in Resources */ = {isa = PBXBuildFile; fileRef = C473C30629A91BCB0056B38A /* fr.xcloc */; }; C473C31829A926F50056B38A /* LaunchWidget.intentdefinition in Sources */ = {isa = PBXBuildFile; fileRef = C473C31C29A926F50056B38A /* LaunchWidget.intentdefinition */; }; C473C31929A926F50056B38A /* LaunchWidget.intentdefinition in Sources */ = {isa = PBXBuildFile; fileRef = C473C31C29A926F50056B38A /* LaunchWidget.intentdefinition */; }; C473C31A29A926F50056B38A /* LaunchWidget.intentdefinition in Sources */ = {isa = PBXBuildFile; fileRef = C473C31C29A926F50056B38A /* LaunchWidget.intentdefinition */; }; @@ -170,6 +164,7 @@ C4E5D68429BB2425008E7465 /* SeparatorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4E5D68329BB2425008E7465 /* SeparatorView.swift */; }; C4E5D68629BB369E008E7465 /* TimersView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4E5D68529BB369E008E7465 /* TimersView.swift */; }; C4E5D68829BB3FE1008E7465 /* SiriTimerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4E5D68729BB3FE1008E7465 /* SiriTimerView.swift */; }; + C4E5D68A29BB7953008E7465 /* SettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4E5D68929BB7953008E7465 /* SettingsView.swift */; }; C4F8B1532987FE6F005C86A5 /* LaunchWidgetLiveActivity.swift in Sources */ = {isa = PBXBuildFile; fileRef = C438C7D72981216200BF3EF9 /* LaunchWidgetLiveActivity.swift */; }; C4F8B15729891271005C86A5 /* Conductor.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4F8B15629891271005C86A5 /* Conductor.swift */; }; C4F8B15929891528005C86A5 /* forest_stream.mp3 in Resources */ = {isa = PBXBuildFile; fileRef = C4F8B15829891528005C86A5 /* forest_stream.mp3 */; }; @@ -316,8 +311,6 @@ C445FA942987D01C0054D761 /* train_horn.mp3 */ = {isa = PBXFileReference; lastKnownFileType = audio.mp3; path = train_horn.mp3; sourceTree = ""; }; C4636D9B29AF46BD00994E31 /* ActivityKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ActivityKit.framework; path = System/Library/Frameworks/ActivityKit.framework; sourceTree = SDKROOT; }; C473C2F829A8DC0A0056B38A /* LaunchWidgetAttributes.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LaunchWidgetAttributes.swift; sourceTree = ""; }; - C473C30229A91BB90056B38A /* en.xcloc */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = en.xcloc; path = Localizations/en.xcloc; sourceTree = ""; }; - C473C30629A91BCB0056B38A /* fr.xcloc */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = fr.xcloc; path = Localizations/fr.xcloc; sourceTree = ""; }; C473C32729AA307D0056B38A /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.intentdefinition; name = Base; path = Base.lproj/LaunchWidget.intentdefinition; sourceTree = ""; }; C473C32929AA30890056B38A /* fr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fr; path = fr.lproj/LaunchWidget.strings; sourceTree = ""; }; C473C32B29AA330E0056B38A /* fr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fr; path = fr.lproj/Localizable.strings; sourceTree = ""; }; @@ -389,6 +382,7 @@ C4E5D68329BB2425008E7465 /* SeparatorView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SeparatorView.swift; sourceTree = ""; }; C4E5D68529BB369E008E7465 /* TimersView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimersView.swift; sourceTree = ""; }; C4E5D68729BB3FE1008E7465 /* SiriTimerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SiriTimerView.swift; sourceTree = ""; }; + C4E5D68929BB7953008E7465 /* SettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsView.swift; sourceTree = ""; }; C4F8B15629891271005C86A5 /* Conductor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Conductor.swift; sourceTree = ""; }; C4F8B15829891528005C86A5 /* forest_stream.mp3 */ = {isa = PBXFileReference; lastKnownFileType = audio.mp3; path = forest_stream.mp3; sourceTree = ""; }; C4F8B15E298961A7005C86A5 /* ReorderableForEach.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReorderableForEach.swift; sourceTree = ""; }; @@ -505,8 +499,6 @@ C4BA2B55299FFA3700CB4FBA /* Subscription */, C4060DC3297AE73D003FAB80 /* Assets.xcassets */, C438C80429813B3100BF3EF9 /* LeCountdown.entitlements */, - C473C30229A91BB90056B38A /* en.xcloc */, - C473C30629A91BCB0056B38A /* fr.xcloc */, C473C32A29AA330E0056B38A /* Localizable.strings */, C4E5D66F29B753D7008E7465 /* AppShortcuts.strings */, C4060DCD297AE73D003FAB80 /* Info.plist */, @@ -634,6 +626,7 @@ C498E59E298D4DEA00E90DE0 /* LiveTimerListView.swift */, C4BA2B03299A42EF00CB4FBA /* NewDataView.swift */, C4BA2B05299A8F8D00CB4FBA /* PresetsView.swift */, + C4E5D68929BB7953008E7465 /* SettingsView.swift */, C4E5D68529BB369E008E7465 /* TimersView.swift */, C498E5A2298D720600E90DE0 /* TestView.swift */, ); @@ -945,7 +938,6 @@ buildActionMask = 2147483647; files = ( C4060DC7297AE73D003FAB80 /* Preview Assets.xcassets in Resources */, - C473C30729A91BCC0056B38A /* fr.xcloc in Resources */, C4BA2AEA2995AD1C00CB4FBA /* SEM_Synths_Loop4_Nothing_Like_You.wav in Resources */, C473C32C29AA330E0056B38A /* Localizable.strings in Resources */, C4E5D68229B93583008E7465 /* PVP_Stab_Oneshot_Bleep_Em.wav in Resources */, @@ -959,7 +951,6 @@ C4BA2AE02995ABD200CB4FBA /* HighChords_Loop_River.wav in Resources */, C4E5D66D29B753D7008E7465 /* AppShortcuts.strings in Resources */, C4060DC4297AE73D003FAB80 /* Assets.xcassets in Resources */, - C473C30329A91BB90056B38A /* en.xcloc in Resources */, C4BA2AE62995AC3F00CB4FBA /* Loop_ToneSD_Boavista.wav in Resources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -983,9 +974,7 @@ buildActionMask = 2147483647; files = ( C445FA882984487F0054D761 /* Assets.xcassets in Resources */, - C473C30429A91BB90056B38A /* en.xcloc in Resources */, C438C7DD2981216300BF3EF9 /* Assets.xcassets in Resources */, - C473C30829A91BCC0056B38A /* fr.xcloc in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -993,9 +982,7 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( - C473C30529A91BB90056B38A /* en.xcloc in Resources */, C473C33029ACADC80056B38A /* Localizable.strings in Resources */, - C473C30929A91BCC0056B38A /* fr.xcloc in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1081,6 +1068,7 @@ C4BA2B43299FCB2B00CB4FBA /* RecordsView.swift in Sources */, C4BA2B2F299E69A000CB4FBA /* View+Extension.swift in Sources */, C4E5D68629BB369E008E7465 /* TimersView.swift in Sources */, + C4E5D68A29BB7953008E7465 /* SettingsView.swift in Sources */, C4060DF7297AFEF2003FAB80 /* NewCountdownView.swift in Sources */, C4060DCC297AE73D003FAB80 /* LeCountdown.xcdatamodeld in Sources */, C4BA2B49299FCE0C00CB4FBA /* IntervalGroup+CoreDataProperties.swift in Sources */, diff --git a/LeCountdown/Conductor.swift b/LeCountdown/Conductor.swift index 636e4bf..d3010ec 100644 --- a/LeCountdown/Conductor.swift +++ b/LeCountdown/Conductor.swift @@ -162,14 +162,17 @@ class Conductor: ObservableObject { let date = Date(timeIntervalSinceNow: countdown.duration) let soundFile = try SoundFile(fullName: countdown.soundName) - self._playSound(Const.confirmationSound.rawValue) - let soundPlayer = DelaySoundPlayer(soundFile: soundFile) self.delaySoundPlayer = soundPlayer try soundPlayer.start(in: countdown.duration, repeatCount: Int(countdown.repeatCount)) self.startCountdown(date, countdown: countdown) + + if Preferences.playConfirmationSound { + self._playSound(Const.confirmationSound.rawValue) + } + handler(.success(date)) } catch { Logger.error(error) @@ -184,6 +187,11 @@ class Conductor: ObservableObject { DispatchQueue.main.async { let now = Date() Conductor.maestro.currentStopwatches[stopwatch.stringId] = now + + if Preferences.playConfirmationSound { + self._playSound(Const.confirmationSound.rawValue) + } + self._launchLiveActivity(stopwatch: stopwatch, start: now) // self._createTimerIntent(stopwatch) diff --git a/LeCountdown/Utils/Preferences.swift b/LeCountdown/Utils/Preferences.swift index cbabe78..c145d80 100644 --- a/LeCountdown/Utils/Preferences.swift +++ b/LeCountdown/Utils/Preferences.swift @@ -10,6 +10,7 @@ import Foundation enum PreferenceKey: String { case countdowns case stopwatches + case playConfirmationSound case showSilentModeAlert case soundDurations case lastSoundPlayed @@ -24,6 +25,7 @@ class Preferences { @UserDefault(PreferenceKey.lastSoundPlayed.rawValue, defaultValue: [:]) static var lastSelectedSound: [String : 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 static var hideSilentModeAlerts: Bool { return UserDefaults.standard.bool(forKey: PreferenceKey.showSilentModeAlert.rawValue) diff --git a/LeCountdown/Views/ContentView.swift b/LeCountdown/Views/ContentView.swift index 5354de2..c60ad4e 100644 --- a/LeCountdown/Views/ContentView.swift +++ b/LeCountdown/Views/ContentView.swift @@ -53,6 +53,8 @@ struct ContentView: View { @State private var tipsShown: Bool = false @State private var siriTipShown: Bool = false + + @State private var showSettingsSheet: Bool = false var body: some View { @@ -98,10 +100,14 @@ struct ContentView: View { .alert("You need to accept notifications, please check your settings", isPresented: $boringContext.showPermissionAlert) { PermissionAlertView() } - .sheet(isPresented: $boringContext.isShowingNewData, content: { + .sheet(isPresented: self.$boringContext.isShowingNewData, content: { + }) + .sheet(isPresented: self.$showSettingsSheet, content: { + SettingsView() + .presentationDetents([.height(100.0)]) }) .toolbar { - ToolbarItem(placement: .navigationBarTrailing) { + ToolbarItem(placement: .navigationBarLeading) { Button { withAnimation { self.isEditing.toggle() @@ -110,6 +116,15 @@ struct ContentView: View { Text(self.isEditing ? "Done" : "Edit") } } + ToolbarItem(placement: .navigationBarTrailing) { + Button { + withAnimation { + self.showSettingsSheet.toggle() + } + } label: { + Image(systemName: "gearshape.fill") + } + } } .onAppear { self._askPermissions() diff --git a/LeCountdown/Views/SettingsView.swift b/LeCountdown/Views/SettingsView.swift new file mode 100644 index 0000000..14391d9 --- /dev/null +++ b/LeCountdown/Views/SettingsView.swift @@ -0,0 +1,29 @@ +// +// SettingsView.swift +// LeCountdown +// +// Created by Laurent Morvillier on 10/03/2023. +// + +import SwiftUI + +struct SettingsView: View { + + @State var confirmationSound = Preferences.playConfirmationSound + + var body: some View { + + Form { + Toggle("Play confirmation sound", isOn: self.$confirmationSound).onChange(of: self.confirmationSound) { newValue in + Preferences.playConfirmationSound = newValue + } + } + + } +} + +struct SettingsView_Previews: PreviewProvider { + static var previews: some View { + SettingsView() + } +} diff --git a/LeCountdown/fr.lproj/Localizable.strings b/LeCountdown/fr.lproj/Localizable.strings index 3bb8699..f94a1c0 100644 --- a/LeCountdown/fr.lproj/Localizable.strings +++ b/LeCountdown/fr.lproj/Localizable.strings @@ -248,3 +248,4 @@ "The timer has not been found in the app" = "Le minuteur n'a pas été trouvé dans l'app"; "In-app purchase disabled" = "Les achats in-app sont désactivés. Veuillez les activer si vous souhaitez vous abonner"; "You'll find your timers here. Start by creating them on the left screen" = "Vous retrouverez vos minuteurs ici. Commencez par en créer dans l'écran de gauche"; +"Settings" = "Réglages";