diff --git a/LaunchWidget/SingleTimerView.swift b/LaunchWidget/SingleTimerView.swift index 974515e..e73dddf 100644 --- a/LaunchWidget/SingleTimerView.swift +++ b/LaunchWidget/SingleTimerView.swift @@ -73,7 +73,7 @@ struct LockScreenCountdownView: View { case .systemSmall, .systemMedium, .systemLarge, .systemExtraLarge: return .body case .accessoryCircular: - return .footnote + return Font.system(.callout, weight: .medium) default: return .body } diff --git a/LeCountdown.xcodeproj/project.pbxproj b/LeCountdown.xcodeproj/project.pbxproj index 486e813..0221b8e 100644 --- a/LeCountdown.xcodeproj/project.pbxproj +++ b/LeCountdown.xcodeproj/project.pbxproj @@ -88,6 +88,25 @@ C4BA2AFD299A3A3700CB4FBA /* AppleMusicPlayer.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4BA2AFC299A3A3700CB4FBA /* AppleMusicPlayer.swift */; }; C4BA2B04299A42EF00CB4FBA /* NewDataView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4BA2B03299A42EF00CB4FBA /* NewDataView.swift */; }; C4BA2B06299A8F8D00CB4FBA /* PresetsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4BA2B05299A8F8D00CB4FBA /* PresetsView.swift */; }; + C4BA2B0F299BE61E00CB4FBA /* Interval+CoreDataClass.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4BA2B0A299BE61E00CB4FBA /* Interval+CoreDataClass.swift */; }; + C4BA2B10299BE61E00CB4FBA /* Interval+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4BA2B0B299BE61E00CB4FBA /* Interval+CoreDataProperties.swift */; }; + C4BA2B11299BE61E00CB4FBA /* IntervalGroup+CoreDataClass.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4BA2B0C299BE61E00CB4FBA /* IntervalGroup+CoreDataClass.swift */; }; + C4BA2B12299BE61E00CB4FBA /* IntervalGroup+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4BA2B0D299BE61E00CB4FBA /* IntervalGroup+CoreDataProperties.swift */; }; + C4BA2B13299BE61E00CB4FBA /* Countdown+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4BA2B0E299BE61E00CB4FBA /* Countdown+CoreDataProperties.swift */; }; + C4BA2B14299BE6A000CB4FBA /* IntervalGroup+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4BA2B0D299BE61E00CB4FBA /* IntervalGroup+CoreDataProperties.swift */; }; + C4BA2B15299BE6A000CB4FBA /* Interval+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4BA2B0B299BE61E00CB4FBA /* Interval+CoreDataProperties.swift */; }; + C4BA2B16299BE6A000CB4FBA /* IntervalGroup+CoreDataClass.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4BA2B0C299BE61E00CB4FBA /* IntervalGroup+CoreDataClass.swift */; }; + C4BA2B17299BE6A000CB4FBA /* Stopwatch+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4BA2AEC2996A11900CB4FBA /* Stopwatch+CoreDataProperties.swift */; }; + C4BA2B18299BE6A000CB4FBA /* Interval+CoreDataClass.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4BA2B0A299BE61E00CB4FBA /* Interval+CoreDataClass.swift */; }; + C4BA2B19299BE6A000CB4FBA /* Countdown+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4BA2B0E299BE61E00CB4FBA /* Countdown+CoreDataProperties.swift */; }; + C4BA2B1A299BE6A100CB4FBA /* IntervalGroup+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4BA2B0D299BE61E00CB4FBA /* IntervalGroup+CoreDataProperties.swift */; }; + C4BA2B1B299BE6A100CB4FBA /* Interval+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4BA2B0B299BE61E00CB4FBA /* Interval+CoreDataProperties.swift */; }; + C4BA2B1C299BE6A100CB4FBA /* IntervalGroup+CoreDataClass.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4BA2B0C299BE61E00CB4FBA /* IntervalGroup+CoreDataClass.swift */; }; + C4BA2B1D299BE6A100CB4FBA /* Stopwatch+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4BA2AEC2996A11900CB4FBA /* Stopwatch+CoreDataProperties.swift */; }; + C4BA2B1E299BE6A100CB4FBA /* Interval+CoreDataClass.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4BA2B0A299BE61E00CB4FBA /* Interval+CoreDataClass.swift */; }; + C4BA2B1F299BE6A100CB4FBA /* Countdown+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4BA2B0E299BE61E00CB4FBA /* Countdown+CoreDataProperties.swift */; }; + C4BA2B22299BE82E00CB4FBA /* AbstractSoundTimer+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4BA2AEF2996A11900CB4FBA /* AbstractSoundTimer+CoreDataProperties.swift */; }; + C4BA2B23299BE82E00CB4FBA /* AbstractSoundTimer+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4BA2AEF2996A11900CB4FBA /* AbstractSoundTimer+CoreDataProperties.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 */; }; @@ -103,7 +122,6 @@ C4F8B17D298AC234005C86A5 /* Record+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4F8B16F298AC234005C86A5 /* Record+CoreDataProperties.swift */; }; C4F8B17E298AC234005C86A5 /* Alarm+CoreDataClass.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4F8B170298AC234005C86A5 /* Alarm+CoreDataClass.swift */; }; C4F8B182298AC234005C86A5 /* Stopwatch+CoreDataClass.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4F8B174298AC234005C86A5 /* Stopwatch+CoreDataClass.swift */; }; - C4F8B183298AC234005C86A5 /* Stopwatch+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4F8B175298AC234005C86A5 /* Stopwatch+CoreDataProperties.swift */; }; C4F8B184298AC234005C86A5 /* AbstractTimer+CoreDataClass.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4F8B176298AC234005C86A5 /* AbstractTimer+CoreDataClass.swift */; }; C4F8B185298AC234005C86A5 /* AbstractTimer+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4F8B177298AC234005C86A5 /* AbstractTimer+CoreDataProperties.swift */; }; C4F8B186298AC234005C86A5 /* Activity+CoreDataClass.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4F8B178298AC234005C86A5 /* Activity+CoreDataClass.swift */; }; @@ -113,7 +131,6 @@ C4F8B18D298AC288005C86A5 /* Stopwatch+CoreDataClass.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4F8B174298AC234005C86A5 /* Stopwatch+CoreDataClass.swift */; }; C4F8B18E298AC288005C86A5 /* AbstractTimer+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4F8B177298AC234005C86A5 /* AbstractTimer+CoreDataProperties.swift */; }; C4F8B18F298AC288005C86A5 /* AbstractTimer+CoreDataClass.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4F8B176298AC234005C86A5 /* AbstractTimer+CoreDataClass.swift */; }; - C4F8B190298AC288005C86A5 /* Stopwatch+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4F8B175298AC234005C86A5 /* Stopwatch+CoreDataProperties.swift */; }; C4F8B192298AC288005C86A5 /* Activity+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4F8B179298AC234005C86A5 /* Activity+CoreDataProperties.swift */; }; C4F8B193298AC288005C86A5 /* Countdown+CoreDataClass.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4F8B16C298AC234005C86A5 /* Countdown+CoreDataClass.swift */; }; C4F8B194298AC288005C86A5 /* Record+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4F8B16F298AC234005C86A5 /* Record+CoreDataProperties.swift */; }; @@ -123,23 +140,16 @@ C4F8B19B298AC288005C86A5 /* Stopwatch+CoreDataClass.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4F8B174298AC234005C86A5 /* Stopwatch+CoreDataClass.swift */; }; C4F8B19C298AC288005C86A5 /* AbstractTimer+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4F8B177298AC234005C86A5 /* AbstractTimer+CoreDataProperties.swift */; }; C4F8B19D298AC288005C86A5 /* AbstractTimer+CoreDataClass.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4F8B176298AC234005C86A5 /* AbstractTimer+CoreDataClass.swift */; }; - C4F8B19E298AC288005C86A5 /* Stopwatch+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4F8B175298AC234005C86A5 /* Stopwatch+CoreDataProperties.swift */; }; C4F8B1A0298AC288005C86A5 /* Activity+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4F8B179298AC234005C86A5 /* Activity+CoreDataProperties.swift */; }; C4F8B1A1298AC288005C86A5 /* Countdown+CoreDataClass.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4F8B16C298AC234005C86A5 /* Countdown+CoreDataClass.swift */; }; C4F8B1A2298AC288005C86A5 /* Record+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4F8B16F298AC234005C86A5 /* Record+CoreDataProperties.swift */; }; C4F8B1A3298AC288005C86A5 /* Activity+CoreDataClass.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4F8B178298AC234005C86A5 /* Activity+CoreDataClass.swift */; }; C4F8B1A7298AC2FC005C86A5 /* AbstractSoundTimer+CoreDataClass.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4F8B1A5298AC2FC005C86A5 /* AbstractSoundTimer+CoreDataClass.swift */; }; - C4F8B1A8298AC2FC005C86A5 /* AbstractSoundTimer+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4F8B1A6298AC2FC005C86A5 /* AbstractSoundTimer+CoreDataProperties.swift */; }; - C4F8B1AB298AC3A0005C86A5 /* Countdown+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4F8B1A9298AC3A0005C86A5 /* Countdown+CoreDataProperties.swift */; }; C4F8B1AC298AC3A0005C86A5 /* Alarm+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4F8B1AA298AC3A0005C86A5 /* Alarm+CoreDataProperties.swift */; }; C4F8B1AD298AC451005C86A5 /* AbstractSoundTimer+CoreDataClass.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4F8B1A5298AC2FC005C86A5 /* AbstractSoundTimer+CoreDataClass.swift */; }; C4F8B1AE298AC451005C86A5 /* Alarm+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4F8B1AA298AC3A0005C86A5 /* Alarm+CoreDataProperties.swift */; }; - C4F8B1AF298AC451005C86A5 /* Countdown+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4F8B1A9298AC3A0005C86A5 /* Countdown+CoreDataProperties.swift */; }; - C4F8B1B0298AC451005C86A5 /* AbstractSoundTimer+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4F8B1A6298AC2FC005C86A5 /* AbstractSoundTimer+CoreDataProperties.swift */; }; C4F8B1B1298AC451005C86A5 /* AbstractSoundTimer+CoreDataClass.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4F8B1A5298AC2FC005C86A5 /* AbstractSoundTimer+CoreDataClass.swift */; }; C4F8B1B2298AC451005C86A5 /* Alarm+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4F8B1AA298AC3A0005C86A5 /* Alarm+CoreDataProperties.swift */; }; - C4F8B1B3298AC451005C86A5 /* Countdown+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4F8B1A9298AC3A0005C86A5 /* Countdown+CoreDataProperties.swift */; }; - C4F8B1B4298AC451005C86A5 /* AbstractSoundTimer+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4F8B1A6298AC2FC005C86A5 /* AbstractSoundTimer+CoreDataProperties.swift */; }; C4F8B1B8298AC81D005C86A5 /* CountdownDialView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4F8B1B7298AC81D005C86A5 /* CountdownDialView.swift */; }; C4F8B1BD298AC8DE005C86A5 /* AlarmDialView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4F8B1BC298AC8DE005C86A5 /* AlarmDialView.swift */; }; C4F8B1BF298ACA0B005C86A5 /* StopwatchDialView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4F8B1BE298ACA0B005C86A5 /* StopwatchDialView.swift */; }; @@ -271,6 +281,12 @@ C4BA2AFE299A3A9E00CB4FBA /* MusicKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MusicKit.framework; path = System/Library/Frameworks/MusicKit.framework; sourceTree = SDKROOT; }; C4BA2B03299A42EF00CB4FBA /* NewDataView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NewDataView.swift; sourceTree = ""; }; C4BA2B05299A8F8D00CB4FBA /* PresetsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PresetsView.swift; sourceTree = ""; }; + C4BA2B07299BDAE000CB4FBA /* LeCountdown.0.6.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = LeCountdown.0.6.xcdatamodel; sourceTree = ""; }; + C4BA2B0A299BE61E00CB4FBA /* Interval+CoreDataClass.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Interval+CoreDataClass.swift"; sourceTree = ""; }; + C4BA2B0B299BE61E00CB4FBA /* Interval+CoreDataProperties.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Interval+CoreDataProperties.swift"; sourceTree = ""; }; + C4BA2B0C299BE61E00CB4FBA /* IntervalGroup+CoreDataClass.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "IntervalGroup+CoreDataClass.swift"; sourceTree = ""; }; + C4BA2B0D299BE61E00CB4FBA /* IntervalGroup+CoreDataProperties.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "IntervalGroup+CoreDataProperties.swift"; sourceTree = ""; }; + C4BA2B0E299BE61E00CB4FBA /* Countdown+CoreDataProperties.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Countdown+CoreDataProperties.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 = ""; }; @@ -285,14 +301,11 @@ C4F8B16F298AC234005C86A5 /* Record+CoreDataProperties.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Record+CoreDataProperties.swift"; sourceTree = ""; }; C4F8B170298AC234005C86A5 /* Alarm+CoreDataClass.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Alarm+CoreDataClass.swift"; sourceTree = ""; }; C4F8B174298AC234005C86A5 /* Stopwatch+CoreDataClass.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Stopwatch+CoreDataClass.swift"; sourceTree = ""; }; - C4F8B175298AC234005C86A5 /* Stopwatch+CoreDataProperties.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Stopwatch+CoreDataProperties.swift"; sourceTree = ""; }; C4F8B176298AC234005C86A5 /* AbstractTimer+CoreDataClass.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "AbstractTimer+CoreDataClass.swift"; sourceTree = ""; }; C4F8B177298AC234005C86A5 /* AbstractTimer+CoreDataProperties.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "AbstractTimer+CoreDataProperties.swift"; sourceTree = ""; }; C4F8B178298AC234005C86A5 /* Activity+CoreDataClass.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Activity+CoreDataClass.swift"; sourceTree = ""; }; C4F8B179298AC234005C86A5 /* Activity+CoreDataProperties.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Activity+CoreDataProperties.swift"; sourceTree = ""; }; C4F8B1A5298AC2FC005C86A5 /* AbstractSoundTimer+CoreDataClass.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "AbstractSoundTimer+CoreDataClass.swift"; sourceTree = ""; }; - C4F8B1A6298AC2FC005C86A5 /* AbstractSoundTimer+CoreDataProperties.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "AbstractSoundTimer+CoreDataProperties.swift"; sourceTree = ""; }; - C4F8B1A9298AC3A0005C86A5 /* Countdown+CoreDataProperties.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Countdown+CoreDataProperties.swift"; sourceTree = ""; }; C4F8B1AA298AC3A0005C86A5 /* Alarm+CoreDataProperties.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Alarm+CoreDataProperties.swift"; sourceTree = ""; }; C4F8B1B7298AC81D005C86A5 /* CountdownDialView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CountdownDialView.swift; sourceTree = ""; }; C4F8B1BC298AC8DE005C86A5 /* AlarmDialView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AlarmDialView.swift; sourceTree = ""; }; @@ -476,12 +489,12 @@ C438C80A2981DE1A00BF3EF9 /* Utils */ = { isa = PBXGroup; children = ( + C4BA2AFC299A3A3700CB4FBA /* AppleMusicPlayer.swift */, C4742B5629840F6400D5D950 /* CoolPic.swift */, C438C81029829EAF00BF3EF9 /* PropertyWrappers.swift */, + C40FDB612992985C0042A390 /* TextToSpeechRecorder.swift */, C4060DF4297AE9A7003FAB80 /* TimeInterval+Extensions.swift */, C4742B5E2984205000D5D950 /* ViewModifiers.swift */, - C40FDB612992985C0042A390 /* TextToSpeechRecorder.swift */, - C4BA2AFC299A3A3700CB4FBA /* AppleMusicPlayer.swift */, ); path = Utils; sourceTree = ""; @@ -550,15 +563,17 @@ C4F8B170298AC234005C86A5 /* Alarm+CoreDataClass.swift */, C4F8B1AA298AC3A0005C86A5 /* Alarm+CoreDataProperties.swift */, C4F8B16C298AC234005C86A5 /* Countdown+CoreDataClass.swift */, - C4F8B1A9298AC3A0005C86A5 /* Countdown+CoreDataProperties.swift */, + C4BA2B0E299BE61E00CB4FBA /* Countdown+CoreDataProperties.swift */, C4BA2AED2996A11900CB4FBA /* CustomSound+CoreDataClass.swift */, C4BA2AEE2996A11900CB4FBA /* CustomSound+CoreDataProperties.swift */, + C4BA2B0A299BE61E00CB4FBA /* Interval+CoreDataClass.swift */, + C4BA2B0B299BE61E00CB4FBA /* Interval+CoreDataProperties.swift */, + C4BA2B0C299BE61E00CB4FBA /* IntervalGroup+CoreDataClass.swift */, + C4BA2B0D299BE61E00CB4FBA /* IntervalGroup+CoreDataProperties.swift */, C4F8B16E298AC234005C86A5 /* Record+CoreDataClass.swift */, C4F8B16F298AC234005C86A5 /* Record+CoreDataProperties.swift */, C4F8B174298AC234005C86A5 /* Stopwatch+CoreDataClass.swift */, C4BA2AEC2996A11900CB4FBA /* Stopwatch+CoreDataProperties.swift */, - C4F8B1A6298AC2FC005C86A5 /* AbstractSoundTimer+CoreDataProperties.swift */, - C4F8B175298AC234005C86A5 /* Stopwatch+CoreDataProperties.swift */, ); path = Generation; sourceTree = ""; @@ -809,12 +824,12 @@ C4F8B1D2298BF646005C86A5 /* PermissionAlertView.swift in Sources */, C4060DC9297AE73D003FAB80 /* Persistence.swift in Sources */, C498E5A1298D543900E90DE0 /* LiveTimer.swift in Sources */, - C4F8B1AB298AC3A0005C86A5 /* Countdown+CoreDataProperties.swift in Sources */, C438C80F29828B8600BF3EF9 /* RecordsView.swift in Sources */, C4F8B187298AC234005C86A5 /* Activity+CoreDataProperties.swift in Sources */, C438C80D2982847300BF3EF9 /* CoreDataRequests.swift in Sources */, C4742B5F2984205000D5D950 /* ViewModifiers.swift in Sources */, C4F8B1D8298C0727005C86A5 /* TimerRouter.swift in Sources */, + C4BA2B13299BE61E00CB4FBA /* Countdown+CoreDataProperties.swift in Sources */, C4F8B186298AC234005C86A5 /* Activity+CoreDataClass.swift in Sources */, C4F8B15729891271005C86A5 /* Conductor.swift in Sources */, C4F8B17E298AC234005C86A5 /* Alarm+CoreDataClass.swift in Sources */, @@ -823,14 +838,14 @@ C438C807298195E600BF3EF9 /* Model+Extensions.swift in Sources */, C4BA2B04299A42EF00CB4FBA /* NewDataView.swift in Sources */, C438C7FF2981300500BF3EF9 /* IntentDataProvider.swift in Sources */, - C4F8B183298AC234005C86A5 /* Stopwatch+CoreDataProperties.swift in Sources */, C4BA2AD62993F62700CB4FBA /* SoundSelectionView.swift in Sources */, - C4F8B1A8298AC2FC005C86A5 /* AbstractSoundTimer+CoreDataProperties.swift in Sources */, C498E5A5299152B400E90DE0 /* GreenCheckmarkView.swift in Sources */, C4F8B1B8298AC81D005C86A5 /* CountdownDialView.swift in Sources */, C445FA922987CC8A0054D761 /* Sound.swift in Sources */, C4F8B1D0298BF2E2005C86A5 /* DialView.swift in Sources */, + C4BA2B11299BE61E00CB4FBA /* IntervalGroup+CoreDataClass.swift in Sources */, C4BA2AFD299A3A3700CB4FBA /* AppleMusicPlayer.swift in Sources */, + C4BA2B12299BE61E00CB4FBA /* IntervalGroup+CoreDataProperties.swift in Sources */, C4BA2AF32996A11900CB4FBA /* AbstractSoundTimer+CoreDataProperties.swift in Sources */, C4742B59298411E800D5D950 /* CountdownFormView.swift in Sources */, C4BA2AF12996A11900CB4FBA /* CustomSound+CoreDataClass.swift in Sources */, @@ -855,6 +870,7 @@ C4F8B17D298AC234005C86A5 /* Record+CoreDataProperties.swift in Sources */, C4F8B184298AC234005C86A5 /* AbstractTimer+CoreDataClass.swift in Sources */, C4F8B17A298AC234005C86A5 /* Countdown+CoreDataClass.swift in Sources */, + C4BA2B0F299BE61E00CB4FBA /* Interval+CoreDataClass.swift in Sources */, C4F8B164298A9A92005C86A5 /* AlarmFormView.swift in Sources */, C40FDB622992985C0042A390 /* TextToSpeechRecorder.swift in Sources */, C4060DF7297AFEF2003FAB80 /* NewCountdownView.swift in Sources */, @@ -864,6 +880,7 @@ C4742B5B298414B000D5D950 /* ImageSelectionView.swift in Sources */, C438C7C5298024E900BF3EF9 /* NSManagedContext+Extensions.swift in Sources */, C4F8B15F298961A7005C86A5 /* ReorderableForEach.swift in Sources */, + C4BA2B10299BE61E00CB4FBA /* Interval+CoreDataProperties.swift in Sources */, C4F8B1AC298AC3A0005C86A5 /* Alarm+CoreDataProperties.swift in Sources */, C498E59F298D4DEA00E90DE0 /* LiveTimerListView.swift in Sources */, C4060DC0297AE73B003FAB80 /* LeCountdownApp.swift in Sources */, @@ -893,36 +910,40 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - C4F8B1AF298AC451005C86A5 /* Countdown+CoreDataProperties.swift in Sources */, + C4BA2B15299BE6A000CB4FBA /* Interval+CoreDataProperties.swift in Sources */, C445FA932987CF280054D761 /* Sound.swift in Sources */, C498E5A6299152C600E90DE0 /* GreenCheckmarkView.swift in Sources */, C438C7EB2981266F00BF3EF9 /* SingleTimerView.swift in Sources */, C438C7D62981216200BF3EF9 /* LaunchWidgetBundle.swift in Sources */, + C4BA2B16299BE6A000CB4FBA /* IntervalGroup+CoreDataClass.swift in Sources */, C4F8B18B298AC288005C86A5 /* Record+CoreDataClass.swift in Sources */, C4F8B195298AC288005C86A5 /* Activity+CoreDataClass.swift in Sources */, + C4BA2B22299BE82E00CB4FBA /* AbstractSoundTimer+CoreDataProperties.swift in Sources */, C4F8B193298AC288005C86A5 /* Countdown+CoreDataClass.swift in Sources */, + C4BA2B17299BE6A000CB4FBA /* Stopwatch+CoreDataProperties.swift in Sources */, C4BA2AF72996A4EF00CB4FBA /* CustomSound+CoreDataClass.swift in Sources */, C4F8B1AD298AC451005C86A5 /* AbstractSoundTimer+CoreDataClass.swift in Sources */, C445FA87298448730054D761 /* CoolPic.swift in Sources */, C438C8172982BE9C00BF3EF9 /* Model+Extensions.swift in Sources */, C438C8162982BE1E00BF3EF9 /* LeCountdown.xcdatamodeld in Sources */, C4F8B194298AC288005C86A5 /* Record+CoreDataProperties.swift in Sources */, - C4F8B190298AC288005C86A5 /* Stopwatch+CoreDataProperties.swift in Sources */, C438C8152982BD9000BF3EF9 /* IntentDataProvider.swift in Sources */, C438C7DF2981216300BF3EF9 /* LaunchWidget.intentdefinition in Sources */, - C4F8B1B0298AC451005C86A5 /* AbstractSoundTimer+CoreDataProperties.swift in Sources */, C4F8B15B29892D40005C86A5 /* SoundPlayer.swift in Sources */, C438C7E82981255D00BF3EF9 /* TimeInterval+Extensions.swift in Sources */, C4F8B18F298AC288005C86A5 /* AbstractTimer+CoreDataClass.swift in Sources */, + C4BA2B19299BE6A000CB4FBA /* Countdown+CoreDataProperties.swift in Sources */, C438C7D82981216200BF3EF9 /* LaunchWidgetLiveActivity.swift in Sources */, C4F8B18C298AC288005C86A5 /* Alarm+CoreDataClass.swift in Sources */, C438C8192982BFDB00BF3EF9 /* NSManagedContext+Extensions.swift in Sources */, C438C7DA2981216200BF3EF9 /* LaunchWidget.swift in Sources */, C4BA2AF62996A4EF00CB4FBA /* CustomSound+CoreDataProperties.swift in Sources */, C4F8B192298AC288005C86A5 /* Activity+CoreDataProperties.swift in Sources */, + C4BA2B18299BE6A000CB4FBA /* Interval+CoreDataClass.swift in Sources */, C4F8B18E298AC288005C86A5 /* AbstractTimer+CoreDataProperties.swift in Sources */, C4F8B1AE298AC451005C86A5 /* Alarm+CoreDataProperties.swift in Sources */, C4F8B18D298AC288005C86A5 /* Stopwatch+CoreDataClass.swift in Sources */, + C4BA2B14299BE6A000CB4FBA /* IntervalGroup+CoreDataProperties.swift in Sources */, C438C8182982BFC100BF3EF9 /* Persistence.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -938,25 +959,29 @@ C4F8B1A1298AC288005C86A5 /* Countdown+CoreDataClass.swift in Sources */, C438C7F529812BB200BF3EF9 /* IntentHandler.swift in Sources */, C4F8B19C298AC288005C86A5 /* AbstractTimer+CoreDataProperties.swift in Sources */, + C4BA2B1C299BE6A100CB4FBA /* IntervalGroup+CoreDataClass.swift in Sources */, C4F8B1C0298ACA61005C86A5 /* Model+Extensions.swift in Sources */, + C4BA2B1F299BE6A100CB4FBA /* Countdown+CoreDataProperties.swift in Sources */, C4F8B1A3298AC288005C86A5 /* Activity+CoreDataClass.swift in Sources */, C4F8B1C3298ACBDB005C86A5 /* Sound.swift in Sources */, - C4F8B1B3298AC451005C86A5 /* Countdown+CoreDataProperties.swift in Sources */, - C4F8B1B4298AC451005C86A5 /* AbstractSoundTimer+CoreDataProperties.swift in Sources */, C4F8B19A298AC288005C86A5 /* Alarm+CoreDataClass.swift in Sources */, C438C80529813FB400BF3EF9 /* TimeInterval+Extensions.swift in Sources */, + C4BA2B1B299BE6A100CB4FBA /* Interval+CoreDataProperties.swift in Sources */, C438C802298132B900BF3EF9 /* LeCountdown.xcdatamodeld in Sources */, C4F8B19B298AC288005C86A5 /* Stopwatch+CoreDataClass.swift in Sources */, C4F8B1A0298AC288005C86A5 /* Activity+CoreDataProperties.swift in Sources */, C438C81A2982BFF100BF3EF9 /* NSManagedContext+Extensions.swift in Sources */, C4F8B19D298AC288005C86A5 /* AbstractTimer+CoreDataClass.swift in Sources */, C4BA2AF82996A4F000CB4FBA /* CustomSound+CoreDataProperties.swift in Sources */, - C4F8B19E298AC288005C86A5 /* Stopwatch+CoreDataProperties.swift in Sources */, C4F8B199298AC288005C86A5 /* Record+CoreDataClass.swift in Sources */, C438C8012981327600BF3EF9 /* Persistence.swift in Sources */, C438C7FD29812BF700BF3EF9 /* LaunchWidget.intentdefinition in Sources */, C4F8B1B1298AC451005C86A5 /* AbstractSoundTimer+CoreDataClass.swift in Sources */, + C4BA2B1E299BE6A100CB4FBA /* Interval+CoreDataClass.swift in Sources */, + C4BA2B1A299BE6A100CB4FBA /* IntervalGroup+CoreDataProperties.swift in Sources */, + C4BA2B1D299BE6A100CB4FBA /* Stopwatch+CoreDataProperties.swift in Sources */, C445FA86298448720054D761 /* CoolPic.swift in Sources */, + C4BA2B23299BE82E00CB4FBA /* AbstractSoundTimer+CoreDataProperties.swift in Sources */, C438C800298130E900BF3EF9 /* IntentDataProvider.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -1412,6 +1437,7 @@ C4060DCA297AE73D003FAB80 /* LeCountdown.xcdatamodeld */ = { isa = XCVersionGroup; children = ( + C4BA2B07299BDAE000CB4FBA /* LeCountdown.0.6.xcdatamodel */, C4BA2AEB2996A09600CB4FBA /* LeCountdown.0.5.1.xcdatamodel */, C4BA2AD72993F7D200CB4FBA /* LeCountdown.0.5.xcdatamodel */, C40FDB672993D5E80042A390 /* LeCountdown.0.4.xcdatamodel */, @@ -1420,7 +1446,7 @@ C418A14F298428CB00C22230 /* LeCountdown.0.1.xcdatamodel */, C4060DCB297AE73D003FAB80 /* LeCountdown.xcdatamodel */, ); - currentVersion = C4BA2AEB2996A09600CB4FBA /* LeCountdown.0.5.1.xcdatamodel */; + currentVersion = C4BA2B07299BDAE000CB4FBA /* LeCountdown.0.6.xcdatamodel */; path = LeCountdown.xcdatamodeld; sourceTree = ""; versionGroupType = wrapper.xcdatamodel; diff --git a/LeCountdown/CountdownScheduler.swift b/LeCountdown/CountdownScheduler.swift index fef8779..5d9a803 100644 --- a/LeCountdown/CountdownScheduler.swift +++ b/LeCountdown/CountdownScheduler.swift @@ -45,7 +45,9 @@ class CountdownScheduler { let sound = countdown.soundName print("Selected sound = \(sound)") - content.sound = UNNotificationSound(named: UNNotificationSoundName(rawValue: sound)) +// content.sound = UNNotificationSound(named: UNNotificationSoundName(rawValue: sound)) + + content.sound = UNNotificationSound.criticalSoundNamed(UNNotificationSoundName(rawValue: sound), withAudioVolume: 1.0) content.interruptionLevel = .critical content.relevanceScore = 1.0 diff --git a/LeCountdown/Model/Generation/Countdown+CoreDataProperties.swift b/LeCountdown/Model/Generation/Countdown+CoreDataProperties.swift index 4c605a7..79d4b93 100644 --- a/LeCountdown/Model/Generation/Countdown+CoreDataProperties.swift +++ b/LeCountdown/Model/Generation/Countdown+CoreDataProperties.swift @@ -2,7 +2,7 @@ // Countdown+CoreDataProperties.swift // LeCountdown // -// Created by Laurent Morvillier on 01/02/2023. +// Created by Laurent Morvillier on 14/02/2023. // // @@ -17,5 +17,6 @@ extension Countdown { } @NSManaged public var duration: Double + @NSManaged public var group: IntervalGroup? } diff --git a/LeCountdown/Model/Generation/Interval+CoreDataClass.swift b/LeCountdown/Model/Generation/Interval+CoreDataClass.swift new file mode 100644 index 0000000..31550c7 --- /dev/null +++ b/LeCountdown/Model/Generation/Interval+CoreDataClass.swift @@ -0,0 +1,15 @@ +// +// Interval+CoreDataClass.swift +// LeCountdown +// +// Created by Laurent Morvillier on 14/02/2023. +// +// + +import Foundation +import CoreData + +@objc(Interval) +public class Interval: NSManagedObject { + +} diff --git a/LeCountdown/Model/Generation/Interval+CoreDataProperties.swift b/LeCountdown/Model/Generation/Interval+CoreDataProperties.swift new file mode 100644 index 0000000..a2d4520 --- /dev/null +++ b/LeCountdown/Model/Generation/Interval+CoreDataProperties.swift @@ -0,0 +1,27 @@ +// +// Interval+CoreDataProperties.swift +// LeCountdown +// +// Created by Laurent Morvillier on 14/02/2023. +// +// + +import Foundation +import CoreData + + +extension Interval { + + @nonobjc public class func fetchRequest() -> NSFetchRequest { + return NSFetchRequest(entityName: "Interval") + } + + @NSManaged public var duration: Double + @NSManaged public var soundList: String? + @NSManaged public var group: IntervalGroup? + +} + +extension Interval : Identifiable { + +} diff --git a/LeCountdown/Model/Generation/IntervalGroup+CoreDataClass.swift b/LeCountdown/Model/Generation/IntervalGroup+CoreDataClass.swift new file mode 100644 index 0000000..3c3ba48 --- /dev/null +++ b/LeCountdown/Model/Generation/IntervalGroup+CoreDataClass.swift @@ -0,0 +1,15 @@ +// +// IntervalGroup+CoreDataClass.swift +// LeCountdown +// +// Created by Laurent Morvillier on 14/02/2023. +// +// + +import Foundation +import CoreData + +@objc(IntervalGroup) +public class IntervalGroup: NSManagedObject { + +} diff --git a/LeCountdown/Model/Generation/IntervalGroup+CoreDataProperties.swift b/LeCountdown/Model/Generation/IntervalGroup+CoreDataProperties.swift new file mode 100644 index 0000000..abb7c2f --- /dev/null +++ b/LeCountdown/Model/Generation/IntervalGroup+CoreDataProperties.swift @@ -0,0 +1,27 @@ +// +// IntervalGroup+CoreDataProperties.swift +// LeCountdown +// +// Created by Laurent Morvillier on 14/02/2023. +// +// + +import Foundation +import CoreData + + +extension IntervalGroup { + + @nonobjc public class func fetchRequest() -> NSFetchRequest { + return NSFetchRequest(entityName: "IntervalGroup") + } + + @NSManaged public var repeatCount: Int16 + @NSManaged public var intervals: Interval? + @NSManaged public var countdown: Countdown? + +} + +extension IntervalGroup : Identifiable { + +} diff --git a/LeCountdown/Model/LeCountdown.xcdatamodeld/.xccurrentversion b/LeCountdown/Model/LeCountdown.xcdatamodeld/.xccurrentversion index 6dd84f4..44ed1f5 100644 --- a/LeCountdown/Model/LeCountdown.xcdatamodeld/.xccurrentversion +++ b/LeCountdown/Model/LeCountdown.xcdatamodeld/.xccurrentversion @@ -3,6 +3,6 @@ _XCCurrentVersionName - LeCountdown.0.5.1.xcdatamodel + LeCountdown.0.6.xcdatamodel diff --git a/LeCountdown/Model/LeCountdown.xcdatamodeld/LeCountdown.0.6.xcdatamodel/contents b/LeCountdown/Model/LeCountdown.xcdatamodeld/LeCountdown.0.6.xcdatamodel/contents new file mode 100644 index 0000000..3240459 --- /dev/null +++ b/LeCountdown/Model/LeCountdown.xcdatamodeld/LeCountdown.0.6.xcdatamodel/contents @@ -0,0 +1,48 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/LeCountdown/Views/ContentView.swift b/LeCountdown/Views/ContentView.swift index 345c388..bb690b9 100644 --- a/LeCountdown/Views/ContentView.swift +++ b/LeCountdown/Views/ContentView.swift @@ -86,106 +86,106 @@ struct ContentView: View { var body: some View { - GeometryReader { reader in - let width: CGFloat = reader.size.width / 2 - 15.0 + GeometryReader { reader in + let width: CGFloat = reader.size.width / 2 - 15.0 + + VStack { - VStack { + ScrollView { - ScrollView { + LazyVGrid( + columns: columns, + spacing: itemSpacing + ) { - LazyVGrid( - columns: columns, - spacing: itemSpacing - ) { + if !self.isEditing { - if !self.isEditing { - - ForEach(self.model.spots) { spot in - if let timer = spot.timer { - DialView(timer: timer, isEditingBinding: self.$isEditing, frameSize: width) - .environment(\.managedObjectContext, viewContext) - .environmentObject(Conductor.maestro) - .environmentObject(boringContext) - - } else { - Color.clear - .frame(width: width, height: 80.0) - .cornerRadius(20.0) - } + ForEach(self.model.spots) { spot in + if let timer = spot.timer { + DialView(timer: timer, isEditingBinding: self.$isEditing, frameSize: width) + .environment(\.managedObjectContext, viewContext) + .environmentObject(Conductor.maestro) + .environmentObject(boringContext) + + } else { + Color.clear + .frame(width: width, height: 80.0) + .cornerRadius(20.0) } + } + + } else { + + ReorderableForEach(items: self.model.spots) { spot in - } else { - - ReorderableForEach(items: self.model.spots) { spot in + if let timer = spot.timer { + DialView(timer: timer, isEditingBinding: self.$isEditing, frameSize: width) + .environment(\.managedObjectContext, viewContext) + .environmentObject(Conductor.maestro) + .environmentObject(boringContext) - if let timer = spot.timer { - DialView(timer: timer, isEditingBinding: self.$isEditing, frameSize: width) - .environment(\.managedObjectContext, viewContext) - .environmentObject(Conductor.maestro) - .environmentObject(boringContext) - - } else { - - Color(white: 0.9) - .frame(width: width, height: 80.0) - .cornerRadius(20.0) - } + } else { - } moveAction: { from, to in - self._reorderSpots(from: from, to: to) + Color(white: 0.9) + .frame(width: width, height: 80.0) + .cornerRadius(20.0) } + + } moveAction: { from, to in + self._reorderSpots(from: from, to: to) } } - }.padding(.horizontal, itemSpacing) - - if !conductor.liveTimers.isEmpty { - LiveTimerListView() - .environment(\.managedObjectContext, viewContext) - .environmentObject(conductor) - .background(Color(white: 0.9)) - .padding(.bottom, 40.0) - .cornerRadius(16.0, corners: [.topRight, .topLeft]) } + }.padding(.horizontal, itemSpacing) + + if !conductor.liveTimers.isEmpty { + LiveTimerListView() + .environment(\.managedObjectContext, viewContext) + .environmentObject(conductor) + .background(Color(white: 0.9)) + .padding(.bottom, 40.0) + .cornerRadius(16.0, corners: [.topRight, .topLeft]) } } - .navigationTitle("Home") - .alert(boringContext.error?.localizedDescription ?? "missing error", isPresented: $boringContext.showDefaultAlert) { - Button("OK", role: .cancel) { } - } - .alert("You need to accept notifications, please check your settings", isPresented: $boringContext.showPermissionAlert) { - PermissionAlertView() - } - .sheet(isPresented: $boringContext.isShowingNewData, content: { - self._newView(isPresented: $boringContext.isShowingNewData) - .environment(\.managedObjectContext, viewContext) - }) - .toolbar { - ToolbarItem(placement: .navigationBarTrailing) { - Button { - self.boringContext.isShowingNewData = true - } label: { - HStack { - Image(systemName: "plus") - } + } + .navigationTitle("Home") + .alert(boringContext.error?.localizedDescription ?? "missing error", isPresented: $boringContext.showDefaultAlert) { + Button("OK", role: .cancel) { } + } + .alert("You need to accept notifications, please check your settings", isPresented: $boringContext.showPermissionAlert) { + PermissionAlertView() + } + .sheet(isPresented: $boringContext.isShowingNewData, content: { + self._newView(isPresented: $boringContext.isShowingNewData) + .environment(\.managedObjectContext, viewContext) + }) + .toolbar { + ToolbarItem(placement: .navigationBarTrailing) { + Button { + self.boringContext.isShowingNewData = true + } label: { + HStack { + Image(systemName: "plus") } } - ToolbarItem(placement: .navigationBarLeading) { - Button { - withAnimation { - self.isEditing.toggle() - } - } label: { - Text(self.isEditing ? "Done" : "Edit") + } + ToolbarItem(placement: .navigationBarLeading) { + Button { + withAnimation { + self.isEditing.toggle() } + } label: { + Text(self.isEditing ? "Done" : "Edit") } } - .onAppear { - self._buildItemsList() - self._askPermissions() - } - .onOpenURL { url in - self._performActionIfPossible(url: url) - } + } + .onAppear { + self._buildItemsList() + self._askPermissions() + } + .onOpenURL { url in + self._performActionIfPossible(url: url) + } } diff --git a/LeCountdown/Views/PresetsView.swift b/LeCountdown/Views/PresetsView.swift index 279e722..483b8f7 100644 --- a/LeCountdown/Views/PresetsView.swift +++ b/LeCountdown/Views/PresetsView.swift @@ -10,15 +10,15 @@ import SwiftUI enum PresetSection: Int, Identifiable, CaseIterable { var id: Int { return self.rawValue } - case cooking case workout - case meditation + case chill + case cooking var presets: [Preset] { switch self { case .cooking: return [.softBoiled, .mediumBoiledEggs, .hardBoiledEggs] - case .workout: return [] - case .meditation: return [] + case .workout: return [.runningSplits] + case .chill: return [.nap, .meditation] } } @@ -26,23 +26,51 @@ enum PresetSection: Int, Identifiable, CaseIterable { switch self { case .cooking: return NSLocalizedString("Cooking", comment: "") case .workout: return NSLocalizedString("Workout", comment: "") - case .meditation: return NSLocalizedString("Meditation", comment: "") + case .chill: return NSLocalizedString("Chill", comment: "") } } } + +struct CountdownIntervalGroup { + var repeatCount: Int + var intervals: [CountdownInterval] +} + +struct CountdownInterval { + var duration: TimeInterval + var sound: Sound? +} + enum Preset: Int, Identifiable, CaseIterable { var id: Int { return self.rawValue } case softBoiled case mediumBoiledEggs case hardBoiledEggs + case meditation + case nap + case runningSplits var localizedName: String { switch self { case .hardBoiledEggs: return NSLocalizedString("Hard boiled eggs", comment: "") case .softBoiled: return NSLocalizedString("Soft boiled eggs", comment: "") case .mediumBoiledEggs: return NSLocalizedString("Medium boiled eggs", comment: "") + case .meditation: return NSLocalizedString("Meditation", comment: "") + case .nap: return NSLocalizedString("Nap", comment: "") + case .runningSplits: return NSLocalizedString("Running splits", comment: "") + } + } + + var intervalGroup: CountdownIntervalGroup? { + switch self { + case .runningSplits: + let runInterval = CountdownInterval(duration: 30.0, sound: Sound.sbArpeggio_Loop_River) + let breakInterval = CountdownInterval(duration: 30.0, sound: Sound.sbLoop_ToneSD_Boavista) + return CountdownIntervalGroup(repeatCount: 8, intervals: [runInterval, breakInterval]) + default: + return nil } } @@ -51,16 +79,38 @@ enum Preset: Int, Identifiable, CaseIterable { case .softBoiled: return 3 * 60 case .mediumBoiledEggs: return 6 * 60 case .hardBoiledEggs: return 10 * 60 + case .meditation: return 15 * 60 + case .nap: return 20 * 60 + case .runningSplits: return 13 } } + + var formattedDuration: String { + if let group = self.intervalGroup { + let count = group.repeatCount.formatted() + let durations = group.intervals.map { $0.duration.formatted() } + let formattedIntervals = durations.joined(separator: "/") + return "\(count) * [\(formattedIntervals)]" + } else { + return self.duration.minuteSecond + } + + } var sound: Set { switch self { case .softBoiled: return [] case .mediumBoiledEggs: return [] case .hardBoiledEggs: return [] + case .meditation: return [] + case .nap: return [] + case .runningSplits: return [] } } + + var soundTitle: String { + return "Great sound" + } } @@ -80,24 +130,50 @@ struct PresetsView: View { var tabSelection: Binding + private let columns: [GridItem] = [ + GridItem(spacing: 10.0), + GridItem(spacing: 10.0), + ] + var body: some View { - List { - ForEach(PresetSection.allCases) { section in - Section(header: Text(section.localizedName)) { - ForEach(section.presets) { preset in - - Button { - self.model.selectedPreset = preset - self.isPresented = true - } label: { - Text(preset.localizedName) + VStack { + + Text("You can edit the duration, sound and label before adding") + .padding() + .font(.callout) + + LazyVGrid( + columns: columns, + spacing: 10.0 + ) { + + ForEach(PresetSection.allCases) { section in + Section { + ForEach(section.presets) { preset in + + Button { + self.model.selectedPreset = preset + self.isPresented = true + } label: { + + TimerItemView(name: preset.localizedName, duration: preset.formattedDuration, sound: preset.soundTitle) + + } + + } + } header: { + HStack { + Text(section.localizedName.uppercased()) + Spacer() } - } } - } + }.padding(.horizontal) + + Spacer() } + .sheet(isPresented: $isPresented, content: { CountdownEditView(isPresented: $isPresented, preset: self.model.selectedPreset, tabSelection: self.tabSelection) .environment(\.managedObjectContext, viewContext) @@ -107,8 +183,37 @@ struct PresetsView: View { } } +struct TimerItemView: View { + + var name: String + var duration: String + var sound: String + + var body: some View { + HStack { + VStack(alignment: .leading) { + Text(name.uppercased()).multilineTextAlignment(.leading) + Text(duration) + Text(sound.uppercased()).foregroundColor(Color(white: 0.7)) + }.padding() + Spacer() + }.background(Color(white: 0.15)) + .cornerRadius(16.0) + .monospaced() + .font(Font.system(size: 16.0, weight: .semibold)) + .foregroundColor(Color.white) + } + +} + struct PresetsView_Previews: PreviewProvider { static var previews: some View { PresetsView(tabSelection: .constant(0)) } } + +struct TimerItemView_Previews: PreviewProvider { + static var previews: some View { + TimerItemView(name: "Hard boiled eggs", duration: "10:00", sound: "Stephan Bodzin").frame(width: UIScreen.main.bounds.width / 2.0) + } +}