From a5deb81cbcaf15051cbd811eb31ac92580edbd66 Mon Sep 17 00:00:00 2001 From: Laurent Date: Mon, 4 Dec 2023 14:43:33 +0100 Subject: [PATCH] Adds sounds configuration to steps --- LeCountdown.xcodeproj/project.pbxproj | 8 +-- LeCountdown/AppDelegate.swift | 4 +- LeCountdown/Conductor.swift | 6 +- .../Generation/Step+CoreDataProperties.swift | 2 +- LeCountdown/Model/Model+Extensions.swift | 5 +- LeCountdown/Sound/Sound.swift | 2 +- .../Views/Countdown/CountdownFormView.swift | 3 +- .../Views/Countdown/NewCountdownView.swift | 2 +- ...RangeFormView.swift => StepFormView.swift} | 56 ++++++++++++------- .../Views/Reusable/SoundFormView.swift | 17 ++++++ LeCountdown/Views/TimerModel.swift | 9 ++- 11 files changed, 76 insertions(+), 38 deletions(-) rename LeCountdown/Views/Countdown/{RangeFormView.swift => StepFormView.swift} (50%) diff --git a/LeCountdown.xcodeproj/project.pbxproj b/LeCountdown.xcodeproj/project.pbxproj index 7b37d2c..63e96cd 100644 --- a/LeCountdown.xcodeproj/project.pbxproj +++ b/LeCountdown.xcodeproj/project.pbxproj @@ -142,7 +142,7 @@ C47C933629F01B6600C780E2 /* FileUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4556F6E29E40BED00DEB40B /* FileUtils.swift */; }; C47C933729F01B7A00C780E2 /* Codable+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4556F7029E40DCF00DEB40B /* Codable+Extensions.swift */; }; C47C933929F13BD100C780E2 /* AppleMusicPickerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C47C933829F13BD100C780E2 /* AppleMusicPickerView.swift */; }; - C48920672B0E57C900F6F4D8 /* RangeFormView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C48920662B0E57C900F6F4D8 /* RangeFormView.swift */; }; + C48920672B0E57C900F6F4D8 /* StepFormView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C48920662B0E57C900F6F4D8 /* StepFormView.swift */; }; C48940DE2AC307860086F4FA /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = C48940DD2AC307860086F4FA /* GoogleService-Info.plist */; }; C48940DF2AC307860086F4FA /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = C48940DD2AC307860086F4FA /* GoogleService-Info.plist */; }; C48940E02AC307860086F4FA /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = C48940DD2AC307860086F4FA /* GoogleService-Info.plist */; }; @@ -443,7 +443,7 @@ C47A9AF22AD1B32C00618A50 /* URLs.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = URLs.swift; sourceTree = ""; }; C47C933829F13BD100C780E2 /* AppleMusicPickerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppleMusicPickerView.swift; sourceTree = ""; }; C47C933C29F13DBD00C780E2 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; - C48920662B0E57C900F6F4D8 /* RangeFormView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RangeFormView.swift; sourceTree = ""; }; + C48920662B0E57C900F6F4D8 /* StepFormView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StepFormView.swift; sourceTree = ""; }; C48940DD2AC307860086F4FA /* GoogleService-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "GoogleService-Info.plist"; sourceTree = ""; }; C498E59E298D4DEA00E90DE0 /* LiveTimerListView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LiveTimerListView.swift; sourceTree = ""; }; C498E5A0298D543900E90DE0 /* LiveTimer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LiveTimer.swift; sourceTree = ""; }; @@ -946,7 +946,7 @@ C4742B58298411E800D5D950 /* CountdownFormView.swift */, C4F8B1B7298AC81D005C86A5 /* CountdownDialView.swift */, C4060DF6297AFEF2003FAB80 /* NewCountdownView.swift */, - C48920662B0E57C900F6F4D8 /* RangeFormView.swift */, + C48920662B0E57C900F6F4D8 /* StepFormView.swift */, ); path = Countdown; sourceTree = ""; @@ -1288,7 +1288,7 @@ C4BA2B36299F82FB00CB4FBA /* Fakes.swift in Sources */, C4556F7629E411A400DEB40B /* LogsView.swift in Sources */, C498E5A1298D543900E90DE0 /* LiveTimer.swift in Sources */, - C48920672B0E57C900F6F4D8 /* RangeFormView.swift in Sources */, + C48920672B0E57C900F6F4D8 /* StepFormView.swift in Sources */, C4BA2B6329A3C34600CB4FBA /* Stat.swift in Sources */, C4C8266C2B0E41D20036C666 /* Countdown+CoreDataProperties.swift in Sources */, C415D3E229C0C0C20037B215 /* MailView.swift in Sources */, diff --git a/LeCountdown/AppDelegate.swift b/LeCountdown/AppDelegate.swift index 2c74e16..de9f0dc 100644 --- a/LeCountdown/AppDelegate.swift +++ b/LeCountdown/AppDelegate.swift @@ -91,10 +91,10 @@ extension AppDelegate: UNUserNotificationCenterDelegate { func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse) async { - print("didReceive notification") + Logger.log("didReceive notification") FileLogger.log("userNotificationCenter didReceive > cancelling sound player") if let timerId = self._timerId(notificationId: response.notification.request.identifier) { - Conductor.maestro.cancelSoundPlayer(id: timerId) + Conductor.maestro.cancelSoundPlayers(id: timerId) } } diff --git a/LeCountdown/Conductor.swift b/LeCountdown/Conductor.swift index 5a25bd6..e5c575e 100644 --- a/LeCountdown/Conductor.swift +++ b/LeCountdown/Conductor.swift @@ -246,7 +246,7 @@ class Conductor: ObservableObject { self.currentCountdowns.removeValue(forKey: id) self.removeLiveTimer(id: id) - self.cancelSoundPlayer(id: id) + self.cancelSoundPlayers(id: id) self._recordAndRemoveCountdown(countdownId: id, cancel: true) // self.pausedCountdowns.removeValue(forKey: id) @@ -295,7 +295,7 @@ class Conductor: ObservableObject { // cancel stuff self.cancelCurrentNotifications(countdownId: id) - self.cancelSoundPlayer(id: id) + self.cancelSoundPlayers(id: id) self._endLiveActivity(timerId: id) } @@ -563,7 +563,7 @@ class Conductor: ObservableObject { } } - func cancelSoundPlayer(id: TimerID) { + func cancelSoundPlayers(id: TimerID) { let players = self._soundPlayers(id: id) for (key, player) in players { diff --git a/LeCountdown/Model/Generation/Step+CoreDataProperties.swift b/LeCountdown/Model/Generation/Step+CoreDataProperties.swift index 15936e2..6e5b34c 100644 --- a/LeCountdown/Model/Generation/Step+CoreDataProperties.swift +++ b/LeCountdown/Model/Generation/Step+CoreDataProperties.swift @@ -2,7 +2,7 @@ // Step+CoreDataProperties.swift // LeCountdown // -// Created by Laurent Morvillier on 30/11/2023. +// Created by Laurent Morvillier on 04/12/2023. // // diff --git a/LeCountdown/Model/Model+Extensions.swift b/LeCountdown/Model/Model+Extensions.swift index 43e0934..52389cf 100644 --- a/LeCountdown/Model/Model+Extensions.swift +++ b/LeCountdown/Model/Model+Extensions.swift @@ -9,14 +9,15 @@ import Foundation import SwiftUI import CoreData -protocol StoresSound: ManagedObject { +protocol StoresSound { var playableIds: String? { get } + var stringId: String { get } } extension StoresSound { var playables: [any Playable] { - return playables(idList: self.playableIds) + return self.playables(idList: self.playableIds) } func playables(idList: String?) -> [any Playable] { diff --git a/LeCountdown/Sound/Sound.swift b/LeCountdown/Sound/Sound.swift index 6951b48..493cb86 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 [.stephanBodzin, .nature, .relax] + case .ring: return [.stephanBodzin, .nature, .relax, .shorts] case .confirmation: return [.shorts] } } diff --git a/LeCountdown/Views/Countdown/CountdownFormView.swift b/LeCountdown/Views/Countdown/CountdownFormView.swift index 3f95835..c3e9b17 100644 --- a/LeCountdown/Views/Countdown/CountdownFormView.swift +++ b/LeCountdown/Views/Countdown/CountdownFormView.swift @@ -99,9 +99,10 @@ struct CountdownFormView : View { SoundFormView(model: self.model) } .sheet(item: self.$selectedStepItem, onDismiss: { + // TODO: improve lag self.model.objectWillChange.send() }) { item in - RangeFormView(stepItem: item) + StepFormView(stepItem: item) } } diff --git a/LeCountdown/Views/Countdown/NewCountdownView.swift b/LeCountdown/Views/Countdown/NewCountdownView.swift index 947273f..92520fa 100644 --- a/LeCountdown/Views/Countdown/NewCountdownView.swift +++ b/LeCountdown/Views/Countdown/NewCountdownView.swift @@ -324,7 +324,7 @@ struct CountdownEditView : View { fileprivate extension Step { var item: StepItem { - return StepItem(name: self.name, duration: self.duration) + return StepItem(name: self.name, duration: self.duration, playableIds: self.playableIds) } } diff --git a/LeCountdown/Views/Countdown/RangeFormView.swift b/LeCountdown/Views/Countdown/StepFormView.swift similarity index 50% rename from LeCountdown/Views/Countdown/RangeFormView.swift rename to LeCountdown/Views/Countdown/StepFormView.swift index 3f14a24..6a70f9f 100644 --- a/LeCountdown/Views/Countdown/RangeFormView.swift +++ b/LeCountdown/Views/Countdown/StepFormView.swift @@ -7,7 +7,7 @@ import SwiftUI -struct RangeFormView: View { +struct StepFormView: View { @Environment(\.dismiss) private var dismiss @@ -17,36 +17,49 @@ struct RangeFormView: View { @State var name: String = "" @State var duration: TimeInterval = 0.0 + var soundModel: SoundModel = SoundModel() + var body: some View { - Form { - Section(header: Text("Name")) { - TextField(self.namePlaceholder, text: self.$name) - } - - Section { - TimePickerView(duration: self.$duration) - } header: { - LabeledContent("Duration", value: self.duration.hourMinuteSecond) - .font(.footnote) - } - - Section { - Button { - self._doneHandler() - } label: { - HStack { - Spacer() - Text("Done").fontWeight(.bold) - Spacer() + NavigationStack { + + Form { + Section(header: Text("Name")) { + TextField(self.namePlaceholder, text: self.$name) + } + + Section { + TimePickerView(duration: self.$duration) + } header: { + LabeledContent("Duration", value: self.duration.hourMinuteSecond) + .font(.footnote) + } + + Section { + SoundLightLinkView(soundModel: self.soundModel, + catalog: .ring, + title: NSLocalizedString("Sound", comment: "") ) + } + + Section { + Button { + self._doneHandler() + } label: { + HStack { + Spacer() + Text("Done").fontWeight(.bold) + Spacer() + } } } + } }.onAppear { if let name = self.stepItem.name, !name.isEmpty { self.namePlaceholder = name } self.duration = self.stepItem.duration + self.soundModel.setPlayables(self.stepItem.playables) } } @@ -57,6 +70,7 @@ struct RangeFormView: View { self.stepItem.name = self.name } self.stepItem.duration = self.duration + self.stepItem.playableIds = self.soundModel.playableIds self.dismiss() } diff --git a/LeCountdown/Views/Reusable/SoundFormView.swift b/LeCountdown/Views/Reusable/SoundFormView.swift index a1fe059..39707df 100644 --- a/LeCountdown/Views/Reusable/SoundFormView.swift +++ b/LeCountdown/Views/Reusable/SoundFormView.swift @@ -67,6 +67,23 @@ struct SoundLinkView: View { } +struct SoundLightLinkView: View { + + @StateObject var soundModel: SoundModel + var catalog: Catalog + var title: String + + var body: some View { + NavigationLink { + PlaylistsView(model: self.soundModel, + catalog: self.catalog) + } label: { + LabeledContent(self.title, value: self.soundModel.soundSelection()) + } + } + +} + struct SoundImageFormView_Previews: PreviewProvider { static var previews: some View { diff --git a/LeCountdown/Views/TimerModel.swift b/LeCountdown/Views/TimerModel.swift index 17778c8..5b3aa55 100644 --- a/LeCountdown/Views/TimerModel.swift +++ b/LeCountdown/Views/TimerModel.swift @@ -15,23 +15,28 @@ protocol SoundHolder { func selectPlaylist(_ playlist: Playlist, selected: Bool) } -class StepItem: Identifiable, ObservableObject { +class StepItem: Identifiable, ObservableObject, StoresSound { let id: String = UUID().uuidString var name: String? = nil var duration: TimeInterval = 0.0 + var playableIds: String? = nil - init(name: String? = nil, duration: TimeInterval = 0.0) { + init(name: String? = nil, duration: TimeInterval = 0.0, playableIds: String? = nil) { self.name = name self.duration = duration + self.playableIds = playableIds } func step(context: NSManagedObjectContext) -> Step { let step = Step(context: context) step.name = self.name step.duration = self.duration + step.playableIds = self.playableIds return step } + var stringId: String { return self.id } + } class TimerModel: ObservableObject {