From 2b062b04a4434df9948dbba718152a0d915c533e Mon Sep 17 00:00:00 2001 From: Laurent Date: Thu, 1 Jun 2023 16:31:44 +0200 Subject: [PATCH] Multiples fixes and improvements --- LeCountdown.xcodeproj/project.pbxproj | 4 +- LeCountdown/Conductor.swift | 24 +++------ LeCountdown/Model/CoreDataRequests.swift | 3 +- .../Record+CoreDataProperties.swift | 5 +- .../.xccurrentversion | 2 +- .../LeCountdown.0.6.5.xcdatamodel/contents | 53 +++++++++++++++++++ LeCountdown/Sound/Sound.swift | 2 +- LeCountdown/Views/ContentView.swift | 24 +++------ .../Views/Countdown/CountdownFormView.swift | 1 + LeCountdown/Views/PresetsView.swift | 11 +++- .../Views/Reusable/SoundFormView.swift | 2 +- .../Views/Reusable/SoundSelectionView.swift | 15 ++++-- LeCountdown/Views/SettingsView.swift | 10 ++-- LeCountdown/Views/StartView.swift | 2 +- .../Views/Stopwatch/StopwatchFormView.swift | 1 + LeCountdown/en.lproj/Localizable.strings | 1 + LeCountdown/fr.lproj/Localizable.strings | 7 ++- 17 files changed, 113 insertions(+), 54 deletions(-) create mode 100644 LeCountdown/Model/LeCountdown.xcdatamodeld/LeCountdown.0.6.5.xcdatamodel/contents diff --git a/LeCountdown.xcodeproj/project.pbxproj b/LeCountdown.xcodeproj/project.pbxproj index 701aa12..ca9421d 100644 --- a/LeCountdown.xcodeproj/project.pbxproj +++ b/LeCountdown.xcodeproj/project.pbxproj @@ -412,6 +412,7 @@ C445FA8E2987B83B0054D761 /* SoundPlayer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SoundPlayer.swift; sourceTree = ""; }; C445FA902987C0CF0054D761 /* LeCountdown.0.2.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = LeCountdown.0.2.xcdatamodel; sourceTree = ""; }; C445FA912987CC8A0054D761 /* Sound.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Sound.swift; sourceTree = ""; }; + C454892C2A28D9610047D39E /* LeCountdown.0.6.5.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = LeCountdown.0.6.5.xcdatamodel; sourceTree = ""; }; C4556F6A29E40B7800DEB40B /* FileLogger.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileLogger.swift; sourceTree = ""; }; C4556F6E29E40BED00DEB40B /* FileUtils.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileUtils.swift; sourceTree = ""; }; C4556F7029E40DCF00DEB40B /* Codable+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Codable+Extensions.swift"; sourceTree = ""; }; @@ -2017,6 +2018,7 @@ C4060DCA297AE73D003FAB80 /* LeCountdown.xcdatamodeld */ = { isa = XCVersionGroup; children = ( + C454892C2A28D9610047D39E /* LeCountdown.0.6.5.xcdatamodel */, C4A16DCA29D323CF00143D5E /* LeCountdown.0.6.4.xcdatamodel */, C4A16DBD29D1C9DE00143D5E /* LeCountdown.0.6.3.xcdatamodel */, C4BA2B6B29A4C47100CB4FBA /* LeCountdown.0.6.2.xcdatamodel */, @@ -2030,7 +2032,7 @@ C418A14F298428CB00C22230 /* LeCountdown.0.1.xcdatamodel */, C4060DCB297AE73D003FAB80 /* LeCountdown.xcdatamodel */, ); - currentVersion = C4A16DCA29D323CF00143D5E /* LeCountdown.0.6.4.xcdatamodel */; + currentVersion = C454892C2A28D9610047D39E /* LeCountdown.0.6.5.xcdatamodel */; path = LeCountdown.xcdatamodeld; sourceTree = ""; versionGroupType = wrapper.xcdatamodel; diff --git a/LeCountdown/Conductor.swift b/LeCountdown/Conductor.swift index efd9175..9ff855f 100644 --- a/LeCountdown/Conductor.swift +++ b/LeCountdown/Conductor.swift @@ -137,17 +137,12 @@ class Conductor: ObservableObject { return self.cancelledCountdowns.contains(where: { $0 == countdown.stringId }) } -// func notifyUser(countdownId: String) { -// // self._playSound(timerId: countdownId) -// self._endCountdown(countdownId: countdownId, cancel: false) -// } - - fileprivate func _recordActivity(countdownId: String) { + fileprivate func _recordActivity(countdownId: String, cancelled: Bool) { let context = PersistenceController.shared.container.viewContext if let countdown: Countdown = context.object(stringId: countdownId), let dateInterval = self.currentCountdowns[countdownId] { do { - try CoreDataRequests.recordActivity(timer: countdown, dateInterval: dateInterval) + try CoreDataRequests.recordActivity(timer: countdown, dateInterval: dateInterval, cancelled: cancelled) } catch { Logger.error(error) // TODO: show error to user @@ -167,7 +162,6 @@ class Conductor: ObservableObject { if Preferences.playConfirmationSound { self._playConfirmationSound(timer: countdown) } - handler(.success(end)) } catch { FileLogger.log("start error : \(error.localizedDescription)") @@ -214,7 +208,7 @@ class Conductor: ObservableObject { CountdownScheduler.master.cancelCurrentNotifications(countdownId: id) self.cancelSoundPlayer(id: id) self.cancelledCountdowns.append(id) - self._endCountdown(countdownId: id, cancel: true) + self._recordAndRemoveCountdown(countdownId: id, cancel: true) self.pausedCountdowns.removeValue(forKey: id) if Preferences.playCancellationSound { @@ -270,13 +264,9 @@ class Conductor: ObservableObject { } } - fileprivate func _endCountdown(countdownId: String, cancel: Bool) { + fileprivate func _recordAndRemoveCountdown(countdownId: String, cancel: Bool) { DispatchQueue.main.async { - #if DEBUG - if !cancel { - self._recordActivity(countdownId: countdownId) - } - #endif + self._recordActivity(countdownId: countdownId, cancelled: cancel) self.currentCountdowns.removeValue(forKey: countdownId) self._endLiveActivity(timerId: countdownId) } @@ -313,7 +303,7 @@ class Conductor: ObservableObject { Conductor.maestro.currentStopwatches[stopwatch.stringId] = lsw do { - try CoreDataRequests.recordActivity(timer: stopwatch, dateInterval: DateInterval(start: lsw.start, end: end)) + try CoreDataRequests.recordActivity(timer: stopwatch, dateInterval: DateInterval(start: lsw.start, end: end), cancelled: false) } catch { Logger.error(error) } @@ -363,7 +353,7 @@ class Conductor: ObservableObject { let now = Date() for (key, value) in self.currentCountdowns { if value.end < now || self.cancelledCountdowns.contains(key) { - self._endCountdown(countdownId: key, cancel: false) + self._recordAndRemoveCountdown(countdownId: key, cancel: false) } } } diff --git a/LeCountdown/Model/CoreDataRequests.swift b/LeCountdown/Model/CoreDataRequests.swift index cc11ea7..4f19031 100644 --- a/LeCountdown/Model/CoreDataRequests.swift +++ b/LeCountdown/Model/CoreDataRequests.swift @@ -43,7 +43,7 @@ class CoreDataRequests { return activity } - static func recordActivity(timer: AbstractTimer, dateInterval: DateInterval) throws { + static func recordActivity(timer: AbstractTimer, dateInterval: DateInterval, cancelled: Bool) throws { guard let activity = timer.activity else { return @@ -54,6 +54,7 @@ class CoreDataRequests { record.start = dateInterval.start record.end = dateInterval.end record.activity = activity + record.cancelled = cancelled try context.save() } diff --git a/LeCountdown/Model/Generation/Record+CoreDataProperties.swift b/LeCountdown/Model/Generation/Record+CoreDataProperties.swift index 61fb1d6..f65dae7 100644 --- a/LeCountdown/Model/Generation/Record+CoreDataProperties.swift +++ b/LeCountdown/Model/Generation/Record+CoreDataProperties.swift @@ -2,7 +2,7 @@ // Record+CoreDataProperties.swift // LeCountdown // -// Created by Laurent Morvillier on 21/02/2023. +// Created by Laurent Morvillier on 01/06/2023. // // @@ -18,9 +18,10 @@ extension Record { @NSManaged public var duration: Double @NSManaged public var end: Date? + @NSManaged public var month: Int16 @NSManaged public var start: Date? @NSManaged public var year: Int16 - @NSManaged public var month: Int16 + @NSManaged public var cancelled: Bool @NSManaged public var activity: Activity? } diff --git a/LeCountdown/Model/LeCountdown.xcdatamodeld/.xccurrentversion b/LeCountdown/Model/LeCountdown.xcdatamodeld/.xccurrentversion index f257262..15b7600 100644 --- a/LeCountdown/Model/LeCountdown.xcdatamodeld/.xccurrentversion +++ b/LeCountdown/Model/LeCountdown.xcdatamodeld/.xccurrentversion @@ -3,6 +3,6 @@ _XCCurrentVersionName - LeCountdown.0.6.4.xcdatamodel + LeCountdown.0.6.5.xcdatamodel diff --git a/LeCountdown/Model/LeCountdown.xcdatamodeld/LeCountdown.0.6.5.xcdatamodel/contents b/LeCountdown/Model/LeCountdown.xcdatamodeld/LeCountdown.0.6.5.xcdatamodel/contents new file mode 100644 index 0000000..b93e3d9 --- /dev/null +++ b/LeCountdown/Model/LeCountdown.xcdatamodeld/LeCountdown.0.6.5.xcdatamodel/contents @@ -0,0 +1,53 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/LeCountdown/Sound/Sound.swift b/LeCountdown/Sound/Sound.swift index e8d05e5..c5a3a3c 100644 --- a/LeCountdown/Sound/Sound.swift +++ b/LeCountdown/Sound/Sound.swift @@ -56,7 +56,7 @@ enum Catalog { var playlists: [Playlist] { switch self { - case .ring: return [.nature, .stephanBodzin, .relax] + case .ring: return [.stephanBodzin, .nature, .relax] case .confirmation: return [.shorts] } } diff --git a/LeCountdown/Views/ContentView.swift b/LeCountdown/Views/ContentView.swift index 5a03eee..8329856 100644 --- a/LeCountdown/Views/ContentView.swift +++ b/LeCountdown/Views/ContentView.swift @@ -52,10 +52,8 @@ struct ContentView: View { Spacer() - #if !DEBUG - + #if !TARGET_IPHONE_SIMULATOR SiriVolumeView(timer: self.boringContext.siriTimer, siriTipShown: self.$siriTipShown) - #endif LiveTimerListView() @@ -205,13 +203,10 @@ struct MainToolbarView: ToolbarContent { self.showStatsSheet.toggle() } } label: { - Image(systemName: "chart.bar.doc.horizontal") + Image(systemName: "scroll") } .sheet(isPresented: self.$showStatsSheet, content: { NavigationStack { -// AppleMusicPickerView() { media in -// -// } ActivitiesView() } }) @@ -225,8 +220,10 @@ struct MainToolbarView: ToolbarContent { Image(systemName: "gearshape.fill") } .sheet(isPresented: self.$showSettingsSheet, content: { - SettingsView() - .presentationDetents([.height(280.0)]) + NavigationStack { + SettingsView() + .navigationBarTitleDisplayMode(.inline) + }.presentationDetents([.height(290.0)]) }) } Button { @@ -293,15 +290,6 @@ class TimerSpot : Identifiable, Equatable { } -//struct ContentView_Previews: PreviewProvider { -// static var previews: some View { -// ContentView() -// .environment(\.managedObjectContext, PersistenceController.preview.container.viewContext) -// .environmentObject(Conductor.maestro) -// -// } -//} - struct Toolbar_Previews: PreviewProvider { static var previews: some View { NavigationStack { diff --git a/LeCountdown/Views/Countdown/CountdownFormView.swift b/LeCountdown/Views/Countdown/CountdownFormView.swift index 8100e8a..841d516 100644 --- a/LeCountdown/Views/Countdown/CountdownFormView.swift +++ b/LeCountdown/Views/Countdown/CountdownFormView.swift @@ -34,6 +34,7 @@ struct CountdownFormView : View { Section(header: Text("Name for tracking the activity")) { TextField("name", text: nameBinding) .focused($focusedField, equals: .name) + .submitLabel(.continue) .onSubmit { self.focusedField = nil } diff --git a/LeCountdown/Views/PresetsView.swift b/LeCountdown/Views/PresetsView.swift index 02de946..51ac80c 100644 --- a/LeCountdown/Views/PresetsView.swift +++ b/LeCountdown/Views/PresetsView.swift @@ -204,6 +204,7 @@ enum PresetSection: Int, Identifiable, CaseIterable { case move case tea case cooking + case more var presets: [Preset] { switch self { @@ -212,6 +213,7 @@ enum PresetSection: Int, Identifiable, CaseIterable { // case .workout: return [.runningSplits] case .mindfullness: return [.nap, .meditation, .writing, .reading] case .move: return [.workout, .stretching, .toothbrushing] + case .more: return [.work] } } @@ -222,6 +224,7 @@ enum PresetSection: Int, Identifiable, CaseIterable { case .mindfullness: return NSLocalizedString("Self", comment: "") case .move: return NSLocalizedString("Move", comment: "") case .tea: return NSLocalizedString("Tea", comment: "") + case .more: return NSLocalizedString("More", comment: "") } } } @@ -236,6 +239,7 @@ struct CountdownInterval { var sound: Sound? } +// idee: coherence cardiaque enum Preset: Int, Identifiable, CaseIterable { var id: Int { return self.rawValue } @@ -255,7 +259,8 @@ enum Preset: Int, Identifiable, CaseIterable { case reading case stretching case cleaning - + case work + var localizedName: String { switch self { case .hardBoiledEggs: return NSLocalizedString("Hard boiled eggs", comment: "") @@ -274,6 +279,7 @@ enum Preset: Int, Identifiable, CaseIterable { case .reading: return NSLocalizedString("Reading", comment: "") case .stretching: return NSLocalizedString("Stretching", comment: "") case .cleaning: return NSLocalizedString("Cleaning", comment: "") + case .work: return NSLocalizedString("Work", comment: "") } } @@ -306,12 +312,13 @@ enum Preset: Int, Identifiable, CaseIterable { case .writing: return 30 * 60.0 case .reading: return 20 * 60.0 case .cleaning: return 60 * 60.0 + case .work: return 60 * 60.0 } } var playlist: Playlist { switch self { - case .softBoiled, .mediumBoiledEggs, .hardBoiledEggs, .pasta, .rice, .toothbrushing, .workout, .stretching: + case .softBoiled, .mediumBoiledEggs, .hardBoiledEggs, .pasta, .rice, .toothbrushing, .workout, .stretching, .work: return .stephanBodzin case .meditation, .blackTea, .greenTea, .writing, .reading: return .relax diff --git a/LeCountdown/Views/Reusable/SoundFormView.swift b/LeCountdown/Views/Reusable/SoundFormView.swift index 8200786..37eda61 100644 --- a/LeCountdown/Views/Reusable/SoundFormView.swift +++ b/LeCountdown/Views/Reusable/SoundFormView.swift @@ -49,7 +49,7 @@ struct SoundFormView : View { SoundLinkView(soundModel: self.model.confirmationSoundModel, catalog: .confirmation, - title: NSLocalizedString("Confirmation Sound", comment: "")) + title: NSLocalizedString("Start Sound", comment: "")) }.sheet(isPresented: self.$imageSelectionSheetShown) { ImageSelectionView(showBinding: self.$imageSelectionSheetShown, diff --git a/LeCountdown/Views/Reusable/SoundSelectionView.swift b/LeCountdown/Views/Reusable/SoundSelectionView.swift index 7c2281f..8942546 100644 --- a/LeCountdown/Views/Reusable/SoundSelectionView.swift +++ b/LeCountdown/Views/Reusable/SoundSelectionView.swift @@ -15,9 +15,18 @@ struct PlaylistsView: View { var body: some View { - Form { - ForEach(catalog.playlists) { playlist in - PlaylistSectionView(model: self.model, playlist: playlist) + VStack { + Form { + + Section { + EmptyView() + } header: { + Text("Select multiple sounds to randomize").font(.footnote) + } + + ForEach(catalog.playlists) { playlist in + PlaylistSectionView(model: self.model, playlist: playlist) + } } } .navigationTitle("Sounds") diff --git a/LeCountdown/Views/SettingsView.swift b/LeCountdown/Views/SettingsView.swift index 6b7d25c..874cad6 100644 --- a/LeCountdown/Views/SettingsView.swift +++ b/LeCountdown/Views/SettingsView.swift @@ -23,10 +23,10 @@ struct SettingsView: View { .onChange(of: self.confirmationSound) { newValue in Preferences.playConfirmationSound = newValue } - Toggle("Play cancellation sound", isOn: self.$cancellationSound) - .onChange(of: self.cancellationSound) { newValue in - Preferences.playCancellationSound = newValue - } +// Toggle("Play cancellation sound", isOn: self.$cancellationSound) +// .onChange(of: self.cancellationSound) { newValue in +// Preferences.playCancellationSound = newValue +// } HStack { Text("Default Volume") Spacer() @@ -56,6 +56,8 @@ struct SettingsView: View { }.sheet(isPresented: $showMailView) { MailView(isShowing: $showMailView) } + .navigationTitle("Settings") + } diff --git a/LeCountdown/Views/StartView.swift b/LeCountdown/Views/StartView.swift index 6bb45b3..523b16e 100644 --- a/LeCountdown/Views/StartView.swift +++ b/LeCountdown/Views/StartView.swift @@ -173,7 +173,7 @@ struct SoundButtonView: View { .navigationTitle("Sounds") .navigationBarTitleDisplayMode(.inline) } - .presentationDetents([.height(320.0)]) + .presentationDetents([.height(360.0)]) } } diff --git a/LeCountdown/Views/Stopwatch/StopwatchFormView.swift b/LeCountdown/Views/Stopwatch/StopwatchFormView.swift index 3b3d18c..d51e431 100644 --- a/LeCountdown/Views/Stopwatch/StopwatchFormView.swift +++ b/LeCountdown/Views/Stopwatch/StopwatchFormView.swift @@ -27,6 +27,7 @@ struct StopwatchFormView: View { Section(header: Text("Name for tracking the activity")) { TextField("name", text: nameBinding) .focused($focusedField, equals: .name) + .submitLabel(.continue) .onSubmit { self.focusedField = nil } diff --git a/LeCountdown/en.lproj/Localizable.strings b/LeCountdown/en.lproj/Localizable.strings index f6a3000..28c4b78 100644 --- a/LeCountdown/en.lproj/Localizable.strings +++ b/LeCountdown/en.lproj/Localizable.strings @@ -1,3 +1,4 @@ "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 have some feedback or an issue, please tell me about it through the settings or within Testflight!"; "Widget Tip" = "Quickly launch your timers with widget. You can add them by modifying your home or lock screen."; +"Play confirmation sound" = "Play sound on start"; diff --git a/LeCountdown/fr.lproj/Localizable.strings b/LeCountdown/fr.lproj/Localizable.strings index 36a52cc..e3b49ac 100644 --- a/LeCountdown/fr.lproj/Localizable.strings +++ b/LeCountdown/fr.lproj/Localizable.strings @@ -248,7 +248,7 @@ "Settings" = "Réglages"; "Pasta" = "Pasta"; "Rice" = "Riz"; -"Play confirmation sound" = "Jouer son de confirmation"; +"Play confirmation sound" = "Jouer son au démarrage"; "Play cancellation sound" = "Jouer son d'annulation"; "Contact us" = "Contactez-nous"; "Confirmation" = "Confirmation"; @@ -259,7 +259,7 @@ "Timer" = "Minuteur"; "Stopwatch" = "Chronomètre"; "Duration" = "Durée"; -"Confirmation Sound" = "Son de démarrage"; +"Start Sound" = "Son de démarrage"; "Name" = "Nom"; "Hours" = "Heures"; "Default Volume" = "Volume par défaut"; @@ -278,3 +278,6 @@ "Create your own" = "Créez les vôtres"; "Select some of the predefined timers and customize them, or create your own" = "Sélectionnez et personnalisez les minuteurs, ou créez les vôtres"; "Learn more" = "En savoir plus..."; +"Work" = "Travail"; +"More" = "Plus"; +"Select multiple sounds to randomize" = "Sélectionnez plusieurs sons pour varier les sonneries";