Adds code to display alarm and stopwatch

release
Laurent 3 years ago
parent 7ccb37479d
commit 676c813bab
  1. 168
      LeCountdown.xcodeproj/project.pbxproj
  2. 15
      LeCountdown/Model/Generation/AbstractSoundTimer+CoreDataClass.swift
  3. 22
      LeCountdown/Model/Generation/AbstractSoundTimer+CoreDataProperties.swift
  4. 16
      LeCountdown/Model/Generation/AbstractTimer+CoreDataClass.swift
  5. 27
      LeCountdown/Model/Generation/AbstractTimer+CoreDataProperties.swift
  6. 15
      LeCountdown/Model/Generation/Activity+CoreDataClass.swift
  7. 61
      LeCountdown/Model/Generation/Activity+CoreDataProperties.swift
  8. 16
      LeCountdown/Model/Generation/Alarm+CoreDataClass.swift
  9. 21
      LeCountdown/Model/Generation/Alarm+CoreDataProperties.swift
  10. 16
      LeCountdown/Model/Generation/Countdown+CoreDataClass.swift
  11. 21
      LeCountdown/Model/Generation/Countdown+CoreDataProperties.swift
  12. 15
      LeCountdown/Model/Generation/Record+CoreDataClass.swift
  13. 27
      LeCountdown/Model/Generation/Record+CoreDataProperties.swift
  14. 16
      LeCountdown/Model/Generation/Stopwatch+CoreDataClass.swift
  15. 23
      LeCountdown/Model/Generation/Stopwatch+CoreDataProperties.swift
  16. 20
      LeCountdown/Model/LeCountdown.xcdatamodeld/LeCountdown.0.3.xcdatamodel/contents
  17. 44
      LeCountdown/Model/Model+Extensions.swift
  18. 43
      LeCountdown/Views/Alarm/AlarmDialView.swift
  19. 0
      LeCountdown/Views/Alarm/AlarmFormView.swift
  20. 4
      LeCountdown/Views/Alarm/NewAlarmView.swift
  21. 121
      LeCountdown/Views/ContentView.swift
  22. 54
      LeCountdown/Views/Countdown/CountdownDialView.swift
  23. 0
      LeCountdown/Views/Countdown/CountdownFormView.swift
  24. 0
      LeCountdown/Views/Countdown/NewCountdownView.swift
  25. 0
      LeCountdown/Views/ImageSelectionView.swift
  26. 0
      LeCountdown/Views/SoundImageFormView.swift
  27. 14
      LeCountdown/Views/Stopwatch/NewStopwatchView.swift
  28. 36
      LeCountdown/Views/Stopwatch/StopwatchDialView.swift
  29. 0
      LeCountdown/Views/Stopwatch/StopwatchFormView.swift

@ -72,6 +72,54 @@
C4F8B166298A9ABB005C86A5 /* SoundImageFormView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4F8B165298A9ABB005C86A5 /* SoundImageFormView.swift */; };
C4F8B169298AA236005C86A5 /* StopwatchFormView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4F8B168298AA236005C86A5 /* StopwatchFormView.swift */; };
C4F8B16B298AA240005C86A5 /* NewStopwatchView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4F8B16A298AA240005C86A5 /* NewStopwatchView.swift */; };
C4F8B17A298AC234005C86A5 /* Countdown+CoreDataClass.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4F8B16C298AC234005C86A5 /* Countdown+CoreDataClass.swift */; };
C4F8B17C298AC234005C86A5 /* Record+CoreDataClass.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4F8B16E298AC234005C86A5 /* Record+CoreDataClass.swift */; };
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 */; };
C4F8B187298AC234005C86A5 /* Activity+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4F8B179298AC234005C86A5 /* Activity+CoreDataProperties.swift */; };
C4F8B18B298AC288005C86A5 /* Record+CoreDataClass.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4F8B16E298AC234005C86A5 /* Record+CoreDataClass.swift */; };
C4F8B18C298AC288005C86A5 /* Alarm+CoreDataClass.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4F8B170298AC234005C86A5 /* Alarm+CoreDataClass.swift */; };
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 */; };
C4F8B195298AC288005C86A5 /* Activity+CoreDataClass.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4F8B178298AC234005C86A5 /* Activity+CoreDataClass.swift */; };
C4F8B199298AC288005C86A5 /* Record+CoreDataClass.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4F8B16E298AC234005C86A5 /* Record+CoreDataClass.swift */; };
C4F8B19A298AC288005C86A5 /* Alarm+CoreDataClass.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4F8B170298AC234005C86A5 /* Alarm+CoreDataClass.swift */; };
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 */; };
C4F8B1C0298ACA61005C86A5 /* Model+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = C438C806298195E600BF3EF9 /* Model+Extensions.swift */; };
C4F8B1C3298ACBDB005C86A5 /* Sound.swift in Sources */ = {isa = PBXBuildFile; fileRef = C445FA912987CC8A0054D761 /* Sound.swift */; };
C4F8B1C6298ACC1F005C86A5 /* SoundPlayer.swift in Sources */ = {isa = PBXBuildFile; fileRef = C445FA8E2987B83B0054D761 /* SoundPlayer.swift */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
@ -178,6 +226,23 @@
C4F8B165298A9ABB005C86A5 /* SoundImageFormView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SoundImageFormView.swift; sourceTree = "<group>"; };
C4F8B168298AA236005C86A5 /* StopwatchFormView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StopwatchFormView.swift; sourceTree = "<group>"; };
C4F8B16A298AA240005C86A5 /* NewStopwatchView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NewStopwatchView.swift; sourceTree = "<group>"; };
C4F8B16C298AC234005C86A5 /* Countdown+CoreDataClass.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Countdown+CoreDataClass.swift"; sourceTree = "<group>"; };
C4F8B16E298AC234005C86A5 /* Record+CoreDataClass.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Record+CoreDataClass.swift"; sourceTree = "<group>"; };
C4F8B16F298AC234005C86A5 /* Record+CoreDataProperties.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Record+CoreDataProperties.swift"; sourceTree = "<group>"; };
C4F8B170298AC234005C86A5 /* Alarm+CoreDataClass.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Alarm+CoreDataClass.swift"; sourceTree = "<group>"; };
C4F8B174298AC234005C86A5 /* Stopwatch+CoreDataClass.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Stopwatch+CoreDataClass.swift"; sourceTree = "<group>"; };
C4F8B175298AC234005C86A5 /* Stopwatch+CoreDataProperties.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Stopwatch+CoreDataProperties.swift"; sourceTree = "<group>"; };
C4F8B176298AC234005C86A5 /* AbstractTimer+CoreDataClass.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "AbstractTimer+CoreDataClass.swift"; sourceTree = "<group>"; };
C4F8B177298AC234005C86A5 /* AbstractTimer+CoreDataProperties.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "AbstractTimer+CoreDataProperties.swift"; sourceTree = "<group>"; };
C4F8B178298AC234005C86A5 /* Activity+CoreDataClass.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Activity+CoreDataClass.swift"; sourceTree = "<group>"; };
C4F8B179298AC234005C86A5 /* Activity+CoreDataProperties.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Activity+CoreDataProperties.swift"; sourceTree = "<group>"; };
C4F8B1A5298AC2FC005C86A5 /* AbstractSoundTimer+CoreDataClass.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "AbstractSoundTimer+CoreDataClass.swift"; sourceTree = "<group>"; };
C4F8B1A6298AC2FC005C86A5 /* AbstractSoundTimer+CoreDataProperties.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "AbstractSoundTimer+CoreDataProperties.swift"; sourceTree = "<group>"; };
C4F8B1A9298AC3A0005C86A5 /* Countdown+CoreDataProperties.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Countdown+CoreDataProperties.swift"; sourceTree = "<group>"; };
C4F8B1AA298AC3A0005C86A5 /* Alarm+CoreDataProperties.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Alarm+CoreDataProperties.swift"; sourceTree = "<group>"; };
C4F8B1B7298AC81D005C86A5 /* CountdownDialView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CountdownDialView.swift; sourceTree = "<group>"; };
C4F8B1BC298AC8DE005C86A5 /* AlarmDialView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AlarmDialView.swift; sourceTree = "<group>"; };
C4F8B1BE298ACA0B005C86A5 /* StopwatchDialView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StopwatchDialView.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@ -338,6 +403,7 @@
C438C8092981DDF800BF3EF9 /* Model */ = {
isa = PBXGroup;
children = (
C4F8B188298AC248005C86A5 /* Generation */,
C4060DCA297AE73D003FAB80 /* LeCountdown.xcdatamodeld */,
C438C80C2982847300BF3EF9 /* CoreDataRequests.swift */,
C438C806298195E600BF3EF9 /* Model+Extensions.swift */,
@ -361,9 +427,13 @@
C438C80B2981DE2E00BF3EF9 /* Views */ = {
isa = PBXGroup;
children = (
C4F8B167298A9D91005C86A5 /* Data */,
C4F8B1BA298AC83F005C86A5 /* Alarm */,
C4F8B1B9298AC830005C86A5 /* Countdown */,
C4F8B1BB298AC848005C86A5 /* Stopwatch */,
C4060DC1297AE73B003FAB80 /* ContentView.swift */,
C438C80E29828B8600BF3EF9 /* RecordsView.swift */,
C4742B5A298414B000D5D950 /* ImageSelectionView.swift */,
C4F8B165298A9ABB005C86A5 /* SoundImageFormView.swift */,
C4F8B15E298961A7005C86A5 /* ReorderableForEach.swift */,
);
path = Views;
@ -387,19 +457,55 @@
path = Sound_Assets;
sourceTree = "<group>";
};
C4F8B167298A9D91005C86A5 /* Data */ = {
C4F8B188298AC248005C86A5 /* Generation */ = {
isa = PBXGroup;
children = (
C4F8B1A5298AC2FC005C86A5 /* AbstractSoundTimer+CoreDataClass.swift */,
C4F8B1A6298AC2FC005C86A5 /* AbstractSoundTimer+CoreDataProperties.swift */,
C4F8B176298AC234005C86A5 /* AbstractTimer+CoreDataClass.swift */,
C4F8B177298AC234005C86A5 /* AbstractTimer+CoreDataProperties.swift */,
C4F8B178298AC234005C86A5 /* Activity+CoreDataClass.swift */,
C4F8B179298AC234005C86A5 /* Activity+CoreDataProperties.swift */,
C4F8B170298AC234005C86A5 /* Alarm+CoreDataClass.swift */,
C4F8B1AA298AC3A0005C86A5 /* Alarm+CoreDataProperties.swift */,
C4F8B16C298AC234005C86A5 /* Countdown+CoreDataClass.swift */,
C4F8B1A9298AC3A0005C86A5 /* Countdown+CoreDataProperties.swift */,
C4F8B16E298AC234005C86A5 /* Record+CoreDataClass.swift */,
C4F8B16F298AC234005C86A5 /* Record+CoreDataProperties.swift */,
C4F8B174298AC234005C86A5 /* Stopwatch+CoreDataClass.swift */,
C4F8B175298AC234005C86A5 /* Stopwatch+CoreDataProperties.swift */,
);
path = Generation;
sourceTree = "<group>";
};
C4F8B1B9298AC830005C86A5 /* Countdown */ = {
isa = PBXGroup;
children = (
C4742B58298411E800D5D950 /* CountdownFormView.swift */,
C4742B5A298414B000D5D950 /* ImageSelectionView.swift */,
C4F8B1B7298AC81D005C86A5 /* CountdownDialView.swift */,
C4060DF6297AFEF2003FAB80 /* NewCountdownView.swift */,
C4F8B161298A9A1F005C86A5 /* NewAlarmView.swift */,
);
path = Countdown;
sourceTree = "<group>";
};
C4F8B1BA298AC83F005C86A5 /* Alarm */ = {
isa = PBXGroup;
children = (
C4F8B163298A9A92005C86A5 /* AlarmFormView.swift */,
C4F8B165298A9ABB005C86A5 /* SoundImageFormView.swift */,
C4F8B168298AA236005C86A5 /* StopwatchFormView.swift */,
C4F8B161298A9A1F005C86A5 /* NewAlarmView.swift */,
C4F8B1BC298AC8DE005C86A5 /* AlarmDialView.swift */,
);
path = Alarm;
sourceTree = "<group>";
};
C4F8B1BB298AC848005C86A5 /* Stopwatch */ = {
isa = PBXGroup;
children = (
C4F8B16A298AA240005C86A5 /* NewStopwatchView.swift */,
C4F8B168298AA236005C86A5 /* StopwatchFormView.swift */,
C4F8B1BE298ACA0B005C86A5 /* StopwatchDialView.swift */,
);
path = Data;
path = Stopwatch;
sourceTree = "<group>";
};
/* End PBXGroup section */
@ -596,31 +702,48 @@
buildActionMask = 2147483647;
files = (
C4060DC9297AE73D003FAB80 /* Persistence.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 */,
C4F8B186298AC234005C86A5 /* Activity+CoreDataClass.swift in Sources */,
C4F8B15729891271005C86A5 /* Conductor.swift in Sources */,
C4F8B17E298AC234005C86A5 /* Alarm+CoreDataClass.swift in Sources */,
C438C81129829EAF00BF3EF9 /* PropertyWrappers.swift in Sources */,
C4F8B1BF298ACA0B005C86A5 /* StopwatchDialView.swift in Sources */,
C438C807298195E600BF3EF9 /* Model+Extensions.swift in Sources */,
C438C7FF2981300500BF3EF9 /* IntentDataProvider.swift in Sources */,
C4F8B183298AC234005C86A5 /* Stopwatch+CoreDataProperties.swift in Sources */,
C4F8B1A8298AC2FC005C86A5 /* AbstractSoundTimer+CoreDataProperties.swift in Sources */,
C4F8B1B8298AC81D005C86A5 /* CountdownDialView.swift in Sources */,
C445FA922987CC8A0054D761 /* Sound.swift in Sources */,
C4742B59298411E800D5D950 /* CountdownFormView.swift in Sources */,
C4060DC2297AE73B003FAB80 /* ContentView.swift in Sources */,
C438C7C12980228B00BF3EF9 /* CountdownScheduler.swift in Sources */,
C445FA8F2987B83B0054D761 /* SoundPlayer.swift in Sources */,
C4F8B1A7298AC2FC005C86A5 /* AbstractSoundTimer+CoreDataClass.swift in Sources */,
C438C7C929803CA000BF3EF9 /* AppDelegate.swift in Sources */,
C4F8B185298AC234005C86A5 /* AbstractTimer+CoreDataProperties.swift in Sources */,
C4F8B169298AA236005C86A5 /* StopwatchFormView.swift in Sources */,
C4F8B1BD298AC8DE005C86A5 /* AlarmDialView.swift in Sources */,
C4F8B1532987FE6F005C86A5 /* LaunchWidgetLiveActivity.swift in Sources */,
C4F8B182298AC234005C86A5 /* Stopwatch+CoreDataClass.swift in Sources */,
C4F8B16B298AA240005C86A5 /* NewStopwatchView.swift in Sources */,
C4060DF5297AE9A7003FAB80 /* TimeInterval+Extensions.swift in Sources */,
C4F8B166298A9ABB005C86A5 /* SoundImageFormView.swift in Sources */,
C4F8B17D298AC234005C86A5 /* Record+CoreDataProperties.swift in Sources */,
C4F8B184298AC234005C86A5 /* AbstractTimer+CoreDataClass.swift in Sources */,
C4F8B17A298AC234005C86A5 /* Countdown+CoreDataClass.swift in Sources */,
C4F8B164298A9A92005C86A5 /* AlarmFormView.swift in Sources */,
C4060DF7297AFEF2003FAB80 /* NewCountdownView.swift in Sources */,
C4060DCC297AE73D003FAB80 /* LeCountdown.xcdatamodeld in Sources */,
C4F8B17C298AC234005C86A5 /* Record+CoreDataClass.swift in Sources */,
C4F8B162298A9A1F005C86A5 /* NewAlarmView.swift in Sources */,
C4742B5B298414B000D5D950 /* ImageSelectionView.swift in Sources */,
C438C7C5298024E900BF3EF9 /* NSManagedContext+Extensions.swift in Sources */,
C4F8B15F298961A7005C86A5 /* ReorderableForEach.swift in Sources */,
C4F8B1AC298AC3A0005C86A5 /* Alarm+CoreDataProperties.swift in Sources */,
C4060DC0297AE73B003FAB80 /* LeCountdownApp.swift in Sources */,
C438C7E02981216300BF3EF9 /* LaunchWidget.intentdefinition in Sources */,
C4742B5729840F6400D5D950 /* CoolPic.swift in Sources */,
@ -648,19 +771,33 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
C4F8B1AF298AC451005C86A5 /* Countdown+CoreDataProperties.swift in Sources */,
C445FA932987CF280054D761 /* Sound.swift in Sources */,
C438C7EB2981266F00BF3EF9 /* SingleCountdownView.swift in Sources */,
C438C7D62981216200BF3EF9 /* LaunchWidgetBundle.swift in Sources */,
C4F8B18B298AC288005C86A5 /* Record+CoreDataClass.swift in Sources */,
C4F8B195298AC288005C86A5 /* Activity+CoreDataClass.swift in Sources */,
C4F8B193298AC288005C86A5 /* Countdown+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 */,
C438C7D82981216200BF3EF9 /* LaunchWidgetLiveActivity.swift in Sources */,
C4F8B18C298AC288005C86A5 /* Alarm+CoreDataClass.swift in Sources */,
C438C8192982BFDB00BF3EF9 /* NSManagedContext+Extensions.swift in Sources */,
C438C7DA2981216200BF3EF9 /* LaunchWidget.swift in Sources */,
C4F8B192298AC288005C86A5 /* Activity+CoreDataProperties.swift in Sources */,
C4F8B18E298AC288005C86A5 /* AbstractTimer+CoreDataProperties.swift in Sources */,
C4F8B1AE298AC451005C86A5 /* Alarm+CoreDataProperties.swift in Sources */,
C4F8B18D298AC288005C86A5 /* Stopwatch+CoreDataClass.swift in Sources */,
C438C8182982BFC100BF3EF9 /* Persistence.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
@ -669,12 +806,29 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
C4F8B1C6298ACC1F005C86A5 /* SoundPlayer.swift in Sources */,
C4F8B1A2298AC288005C86A5 /* Record+CoreDataProperties.swift in Sources */,
C4F8B1B2298AC451005C86A5 /* Alarm+CoreDataProperties.swift in Sources */,
C4F8B1A1298AC288005C86A5 /* Countdown+CoreDataClass.swift in Sources */,
C438C7F529812BB200BF3EF9 /* IntentHandler.swift in Sources */,
C4F8B19C298AC288005C86A5 /* AbstractTimer+CoreDataProperties.swift in Sources */,
C4F8B1C0298ACA61005C86A5 /* Model+Extensions.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 */,
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 */,
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 */,
C445FA86298448720054D761 /* CoolPic.swift in Sources */,
C438C800298130E900BF3EF9 /* IntentDataProvider.swift in Sources */,
);

@ -0,0 +1,15 @@
//
// AbstractSoundTimer+CoreDataClass.swift
// LeCountdown
//
// Created by Laurent Morvillier on 01/02/2023.
//
//
import Foundation
import CoreData
@objc(AbstractSoundTimer)
public class AbstractSoundTimer: AbstractTimer {
}

@ -0,0 +1,22 @@
//
// AbstractSoundTimer+CoreDataProperties.swift
// LeCountdown
//
// Created by Laurent Morvillier on 01/02/2023.
//
//
import Foundation
import CoreData
extension AbstractSoundTimer {
@nonobjc public class func fetchRequest() -> NSFetchRequest<AbstractSoundTimer> {
return NSFetchRequest<AbstractSoundTimer>(entityName: "AbstractSoundTimer")
}
@NSManaged public var sound: Int16
@NSManaged public var repeats: Bool
}

@ -0,0 +1,16 @@
//
// AbstractTimer+CoreDataClass.swift
// LeCountdown
//
// Created by Laurent Morvillier on 01/02/2023.
//
//
import Foundation
import CoreData
import SwiftUI
@objc(AbstractTimer)
public class AbstractTimer: NSManagedObject {
}

@ -0,0 +1,27 @@
//
// AbstractTimer+CoreDataProperties.swift
// LeCountdown
//
// Created by Laurent Morvillier on 01/02/2023.
//
//
import Foundation
import CoreData
extension AbstractTimer {
@nonobjc public class func fetchRequest() -> NSFetchRequest<AbstractTimer> {
return NSFetchRequest<AbstractTimer>(entityName: "AbstractTimer")
}
@NSManaged public var order: Int16
@NSManaged public var image: String?
@NSManaged public var activity: Activity?
}
extension AbstractTimer : Identifiable {
}

@ -0,0 +1,15 @@
//
// Activity+CoreDataClass.swift
// LeCountdown
//
// Created by Laurent Morvillier on 01/02/2023.
//
//
import Foundation
import CoreData
@objc(Activity)
public class Activity: NSManagedObject {
}

@ -0,0 +1,61 @@
//
// Activity+CoreDataProperties.swift
// LeCountdown
//
// Created by Laurent Morvillier on 01/02/2023.
//
//
import Foundation
import CoreData
extension Activity {
@nonobjc public class func fetchRequest() -> NSFetchRequest<Activity> {
return NSFetchRequest<Activity>(entityName: "Activity")
}
@NSManaged public var name: String?
@NSManaged public var records: NSSet?
@NSManaged public var timers: NSSet?
}
// MARK: Generated accessors for records
extension Activity {
@objc(addRecordsObject:)
@NSManaged public func addToRecords(_ value: Record)
@objc(removeRecordsObject:)
@NSManaged public func removeFromRecords(_ value: Record)
@objc(addRecords:)
@NSManaged public func addToRecords(_ values: NSSet)
@objc(removeRecords:)
@NSManaged public func removeFromRecords(_ values: NSSet)
}
// MARK: Generated accessors for timers
extension Activity {
@objc(addTimersObject:)
@NSManaged public func addToTimers(_ value: AbstractTimer)
@objc(removeTimersObject:)
@NSManaged public func removeFromTimers(_ value: AbstractTimer)
@objc(addTimers:)
@NSManaged public func addToTimers(_ values: NSSet)
@objc(removeTimers:)
@NSManaged public func removeFromTimers(_ values: NSSet)
}
extension Activity : Identifiable {
}

@ -0,0 +1,16 @@
//
// Alarm+CoreDataClass.swift
// LeCountdown
//
// Created by Laurent Morvillier on 01/02/2023.
//
//
import Foundation
import CoreData
import SwiftUI
@objc(Alarm)
public class Alarm: AbstractSoundTimer {
}

@ -0,0 +1,21 @@
//
// Alarm+CoreDataProperties.swift
// LeCountdown
//
// Created by Laurent Morvillier on 01/02/2023.
//
//
import Foundation
import CoreData
extension Alarm {
@nonobjc public class func fetchRequest() -> NSFetchRequest<Alarm> {
return NSFetchRequest<Alarm>(entityName: "Alarm")
}
@NSManaged public var fireDate: Date?
}

@ -0,0 +1,16 @@
//
// Countdown+CoreDataClass.swift
// LeCountdown
//
// Created by Laurent Morvillier on 01/02/2023.
//
//
import Foundation
import CoreData
import SwiftUI
@objc(Countdown)
public class Countdown: AbstractSoundTimer {
}

@ -0,0 +1,21 @@
//
// Countdown+CoreDataProperties.swift
// LeCountdown
//
// Created by Laurent Morvillier on 01/02/2023.
//
//
import Foundation
import CoreData
extension Countdown {
@nonobjc public class func fetchRequest() -> NSFetchRequest<Countdown> {
return NSFetchRequest<Countdown>(entityName: "Countdown")
}
@NSManaged public var duration: Double
}

@ -0,0 +1,15 @@
//
// Record+CoreDataClass.swift
// LeCountdown
//
// Created by Laurent Morvillier on 01/02/2023.
//
//
import Foundation
import CoreData
@objc(Record)
public class Record: NSManagedObject {
}

@ -0,0 +1,27 @@
//
// Record+CoreDataProperties.swift
// LeCountdown
//
// Created by Laurent Morvillier on 01/02/2023.
//
//
import Foundation
import CoreData
extension Record {
@nonobjc public class func fetchRequest() -> NSFetchRequest<Record> {
return NSFetchRequest<Record>(entityName: "Record")
}
@NSManaged public var end: Date?
@NSManaged public var start: Date?
@NSManaged public var activity: Activity?
}
extension Record : Identifiable {
}

@ -0,0 +1,16 @@
//
// Stopwatch+CoreDataClass.swift
// LeCountdown
//
// Created by Laurent Morvillier on 01/02/2023.
//
//
import Foundation
import CoreData
import SwiftUI
@objc(Stopwatch)
public class Stopwatch: AbstractTimer {
}

@ -0,0 +1,23 @@
//
// Stopwatch+CoreDataProperties.swift
// LeCountdown
//
// Created by Laurent Morvillier on 01/02/2023.
//
//
import Foundation
import CoreData
extension Stopwatch {
@nonobjc public class func fetchRequest() -> NSFetchRequest<Stopwatch> {
return NSFetchRequest<Stopwatch>(entityName: "Stopwatch")
}
@NSManaged public var start: Date?
@NSManaged public var end: Date?
@NSManaged public var sound: Int16
}

@ -1,31 +1,31 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<model type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="21513" systemVersion="22A400" minimumToolsVersion="Automatic" sourceLanguage="Swift" usedWithCloudKit="YES" userDefinedModelVersionIdentifier="">
<entity name="AbstractTimer" representedClassName="AbstractTimer" isAbstract="YES" syncable="YES" codeGenerationType="class">
<entity name="AbstractSoundTimer" representedClassName="AbstractSoundTimer" isAbstract="YES" parentEntity="AbstractTimer" syncable="YES">
<attribute name="repeats" attributeType="Boolean" defaultValueString="YES" usesScalarValueType="YES"/>
<attribute name="sound" attributeType="Integer 16" defaultValueString="0" usesScalarValueType="YES"/>
</entity>
<entity name="AbstractTimer" representedClassName="AbstractTimer" isAbstract="YES" syncable="YES">
<attribute name="image" optional="YES" attributeType="String"/>
<attribute name="order" attributeType="Integer 16" defaultValueString="0" usesScalarValueType="YES"/>
<relationship name="activity" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="Activity" inverseName="timers" inverseEntity="Activity"/>
</entity>
<entity name="Activity" representedClassName="Activity" syncable="YES" codeGenerationType="class">
<entity name="Activity" representedClassName="Activity" syncable="YES">
<attribute name="name" attributeType="String" defaultValueString=""/>
<relationship name="records" optional="YES" toMany="YES" deletionRule="Nullify" destinationEntity="Record" inverseName="activity" inverseEntity="Record"/>
<relationship name="timers" optional="YES" toMany="YES" deletionRule="Nullify" destinationEntity="AbstractTimer" inverseName="activity" inverseEntity="AbstractTimer"/>
</entity>
<entity name="Alarm" representedClassName="Alarm" parentEntity="SoundTimer" syncable="YES" codeGenerationType="class">
<entity name="Alarm" representedClassName="Alarm" parentEntity="AbstractSoundTimer" syncable="YES">
<attribute name="fireDate" optional="YES" attributeType="Date" usesScalarValueType="NO"/>
</entity>
<entity name="Countdown" representedClassName="Countdown" parentEntity="SoundTimer" syncable="YES" codeGenerationType="class">
<entity name="Countdown" representedClassName="Countdown" parentEntity="AbstractSoundTimer" syncable="YES">
<attribute name="duration" attributeType="Double" defaultValueString="0" usesScalarValueType="YES"/>
</entity>
<entity name="Record" representedClassName="Record" syncable="YES" codeGenerationType="class">
<entity name="Record" representedClassName="Record" syncable="YES">
<attribute name="end" attributeType="Date" defaultDateTimeInterval="696425400" usesScalarValueType="NO"/>
<attribute name="start" attributeType="Date" defaultDateTimeInterval="696425400" usesScalarValueType="NO"/>
<relationship name="activity" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="Activity" inverseName="records" inverseEntity="Activity"/>
</entity>
<entity name="SoundTimer" representedClassName="SoundTimer" isAbstract="YES" parentEntity="AbstractTimer" syncable="YES" codeGenerationType="class">
<attribute name="repeats" attributeType="Boolean" defaultValueString="YES" usesScalarValueType="YES"/>
<attribute name="sound" attributeType="Integer 16" defaultValueString="0" usesScalarValueType="YES"/>
</entity>
<entity name="Stopwatch" representedClassName="Stopwatch" parentEntity="AbstractTimer" syncable="YES" codeGenerationType="class">
<entity name="Stopwatch" representedClassName="Stopwatch" parentEntity="AbstractTimer" syncable="YES">
<attribute name="end" optional="YES" attributeType="Date" usesScalarValueType="NO"/>
<attribute name="sound" optional="YES" attributeType="Integer 16" usesScalarValueType="YES"/>
<attribute name="start" optional="YES" attributeType="Date" usesScalarValueType="NO"/>

@ -9,7 +9,7 @@ import Foundation
import SwiftUI
import CoreData
extension Countdown {
extension AbstractTimer {
var displayName: String {
return self.name ?? self.coolpic.emoji
@ -38,6 +38,10 @@ extension Countdown {
return self.coolpic.rawValue
}
}
extension AbstractSoundTimer {
var coolSound: Sound {
return Sound.allCases[Int(self.sound)]
}
@ -46,8 +50,17 @@ extension Countdown {
coolSound.soundName
}
// var soundFile: SoundFile {
// return Sound.allCases[Int(self.sound)].soundFile
}
extension Countdown {
// override func view() -> any View {
// return CountdownLiveView(countdown: self)
// .environmentObject(Conductor.maestro)
// }
//
// override func editView() -> any View {
//
// }
static func fake(context: NSManagedObjectContext) -> Countdown {
@ -61,6 +74,31 @@ extension Countdown {
}
extension Alarm {
static func fake(context: NSManagedObjectContext) -> Alarm {
let alarm = Alarm(context: context)
alarm.fireDate = Date()
let activity = Activity(context: context)
activity.name = "Wakeup"
alarm.activity = activity
return alarm
}
}
extension Stopwatch {
static func fake(context: NSManagedObjectContext) -> Stopwatch {
let stopwatch = Stopwatch(context: context)
let activity = Activity(context: context)
activity.name = "Run"
stopwatch.activity = activity
return stopwatch
}
}
extension Record {
var details: String {

@ -0,0 +1,43 @@
//
// AlarmDialView.swift
// LeCountdown
//
// Created by Laurent Morvillier on 01/02/2023.
//
import SwiftUI
struct AlarmDialView: View {
@ObservedObject var alarm: Alarm
var body: some View {
VStack {
HStack {
Text(alarm.activity?.name?.uppercased() ?? "")
Spacer()
}
if let fireDate = alarm.fireDate {
HStack {
Text(fireDate, style: .time)
Spacer()
}
}
Spacer()
}
.padding(24.0)
.monospaced()
.font(Font.system(size: 16.0, weight: .semibold))
.foregroundColor(Color.white)
}
}
struct AlarmDialView_Previews: PreviewProvider {
static var previews: some View {
AlarmDialView(alarm: Alarm.fake(context: PersistenceController.preview.container.viewContext))
}
}

@ -16,14 +16,14 @@ struct NewAlarmView: View {
@Binding var isPresented: Bool
var body: some View {
EditAlarmView(isPresented: $isPresented)
AlarmEditView(isPresented: $isPresented)
.environment(\.managedObjectContext, viewContext)
.navigationTitle("New countdown")
}
}
struct EditAlarmView: View {
struct AlarmEditView: View {
@Environment(\.managedObjectContext) private var viewContext
@Environment(\.dismiss) private var dismiss

@ -8,46 +8,6 @@
import SwiftUI
import CoreData
struct CountdownLiveView: View {
@EnvironmentObject var environment: Conductor
@ObservedObject var countdown: Countdown
var body: some View {
VStack {
HStack {
Text(countdown.activity?.name?.uppercased() ?? "")
Spacer()
}
if let dateInterval = environment.notificationDates[countdown.stringId] {
Text(dateInterval.end, style: .timer)
Button {
CountdownScheduler.master.cancelCurrentNotifications(countdown: countdown)
} label: {
Text("Cancel")
.buttonStyle(.bordered)
.tint(.red)
}
} else {
HStack {
Text(countdown.duration.minuteSecond)
Spacer()
}
}
Spacer()
}
.padding(24.0)
.monospaced()
.font(Font.system(size: 16.0, weight: .semibold))
.foregroundColor(Color.white)
}
}
struct ContentView: View {
@EnvironmentObject var environment: Conductor
@ -55,15 +15,15 @@ struct ContentView: View {
@Environment(\.managedObjectContext) private var viewContext
@FetchRequest(
sortDescriptors: [NSSortDescriptor(keyPath: \Countdown.order, ascending: true)],
sortDescriptors: [NSSortDescriptor(keyPath: \AbstractTimer.order, ascending: true)],
animation: .default)
private var countdowns: FetchedResults<Countdown>
private var timers: FetchedResults<AbstractTimer>
fileprivate let itemSpacing: CGFloat = 10.0
@State private var isShowingNewCountdown = false
@State private var isShowingNewStopwatch = false
@State private var isShowingNewAlarm = false
@State private var isShowingNewData = false
// @State private var isShowingNewStopwatch = false
// @State private var isShowingNewAlarm = false
@State var error: Error?
@State var showDefaultAlert: Bool = false
@ -74,8 +34,8 @@ struct ContentView: View {
GridItem(spacing: 10.0),
]
var countdownsArray: [Countdown] {
return Array(countdowns)
var timersArray: [AbstractTimer] {
return Array(timers)
}
var body: some View {
@ -89,24 +49,21 @@ struct ContentView: View {
spacing: itemSpacing
) {
ReorderableForEach(items: countdownsArray) { countdown in
ReorderableForEach(items: timersArray) { timer in
ZStack(alignment: .topTrailing) {
Image(countdown.imageName).resizable()
Image(timer.imageName).resizable()
Button {
self._launchCountdown(countdown)
self._launchTimer(timer)
} label: {
CountdownLiveView(countdown: countdown)
.environmentObject(Conductor.maestro)
self._dialView(timer: timer)
}
NavigationLink {
CountdownEditView(countdown: countdown, isPresented: $isShowingNewCountdown)
.environment(\.managedObjectContext, viewContext)
self._editView(timer: timer, isPresented: $isShowingNewData)
} label: {
Image(systemName: "gearshape.fill")
.font(.system(size: 24, weight: .light))
@ -134,20 +91,20 @@ struct ContentView: View {
}
Button("OK", role: .cancel) { }
})
.sheet(isPresented: self.$isShowingNewCountdown, content: {
NewCountdownView(isPresented: $isShowingNewCountdown) .environment(\.managedObjectContext, viewContext)
.sheet(isPresented: self.$isShowingNewData, content: {
NewCountdownView(isPresented: $isShowingNewData) .environment(\.managedObjectContext, viewContext)
})
.sheet(isPresented: self.$isShowingNewStopwatch, content: {
NewStopwatchView(isPresented: $isShowingNewStopwatch) .environment(\.managedObjectContext, viewContext)
.sheet(isPresented: self.$isShowingNewData, content: {
NewStopwatchView(isPresented: $isShowingNewData) .environment(\.managedObjectContext, viewContext)
})
.sheet(isPresented: self.$isShowingNewAlarm, content: {
NewAlarmView(isPresented: $isShowingNewAlarm) .environment(\.managedObjectContext, viewContext)
.sheet(isPresented: self.$isShowingNewData, content: {
NewAlarmView(isPresented: $isShowingNewData) .environment(\.managedObjectContext, viewContext)
})
.toolbar {
ToolbarItemGroup(placement: .bottomBar) {
Button {
self.isShowingNewCountdown = true
self.isShowingNewData = true
} label: {
HStack {
Image(systemName: "timer")
@ -195,10 +152,38 @@ struct ContentView: View {
}
@ViewBuilder
fileprivate func _dialView(timer: AbstractTimer) -> some View {
switch timer {
case let countdown as Countdown:
CountdownDialView(countdown: countdown)
case let alarm as Alarm:
AlarmDialView(alarm: alarm)
case let stopwatch as Stopwatch:
StopwatchDialView(stopwatch: stopwatch)
default:
Text("missing dial view")
}
}
@ViewBuilder
fileprivate func _editView(timer: AbstractTimer, isPresented: Binding<Bool>) -> some View {
switch timer {
case let countdown as Countdown:
CountdownEditView(countdown: countdown, isPresented: isPresented)
case let alarm as Alarm:
AlarmEditView(alarm: alarm, isPresented: isPresented)
case let stopwatch as Stopwatch:
StopwatchEditView(stopwatch: stopwatch, isPresented: isPresented)
default:
Text("missing edit view")
}
}
fileprivate func _reorder(from: IndexSet, to: Int) {
var countdowns: [Countdown] = self.countdownsArray
countdowns.move(fromOffsets: from, toOffset: to)
for (i, countdown) in countdowns.enumerated() {
var timers: [AbstractTimer] = self.timersArray
timers.move(fromOffsets: from, toOffset: to)
for (i, countdown) in timers.enumerated() {
countdown.order = Int16(i)
}
do {
@ -222,6 +207,10 @@ struct ContentView: View {
}
fileprivate func _launchTimer(_ timer: AbstractTimer) {
}
fileprivate func _launchCountdown(_ countdown: Countdown) {
UNUserNotificationCenter.current().getNotificationSettings { settings in

@ -0,0 +1,54 @@
//
// CountdownLiveView.swift
// LeCountdown
//
// Created by Laurent Morvillier on 01/02/2023.
//
import SwiftUI
struct CountdownDialView: View {
@EnvironmentObject var environment: Conductor
@ObservedObject var countdown: Countdown
var body: some View {
VStack {
HStack {
Text(countdown.activity?.name?.uppercased() ?? "")
Spacer()
}
if let dateInterval = environment.notificationDates[countdown.stringId] {
Text(dateInterval.end, style: .timer)
Button {
CountdownScheduler.master.cancelCurrentNotifications(countdown: countdown)
} label: {
Text("Cancel")
.buttonStyle(.bordered)
.tint(.red)
}
} else {
HStack {
Text(countdown.duration.minuteSecond)
Spacer()
}
}
Spacer()
}
.padding(24.0)
.monospaced()
.font(Font.system(size: 16.0, weight: .semibold))
.foregroundColor(Color.white)
}
}
struct CountdownLiveView_Previews: PreviewProvider {
static var previews: some View {
CountdownDialView(countdown: Countdown.fake(context: PersistenceController.preview.container.viewContext))
}
}

@ -11,6 +11,20 @@ import WidgetKit
struct NewStopwatchView: View {
@Environment(\.managedObjectContext) private var viewContext
@Binding var isPresented: Bool
var body: some View {
StopwatchEditView(isPresented: $isPresented)
.environment(\.managedObjectContext, viewContext)
.navigationTitle("New countdown")
}
}
struct StopwatchEditView: View {
@Environment(\.managedObjectContext) private var viewContext
@Environment(\.dismiss) private var dismiss

@ -0,0 +1,36 @@
//
// StopwatchDialView.swift
// LeCountdown
//
// Created by Laurent Morvillier on 01/02/2023.
//
import SwiftUI
struct StopwatchDialView: View {
@ObservedObject var stopwatch: Stopwatch
var body: some View {
VStack {
HStack {
Text(stopwatch.activity?.name?.uppercased() ?? "")
Spacer()
}
Spacer()
}
.padding(24.0)
.monospaced()
.font(Font.system(size: 16.0, weight: .semibold))
.foregroundColor(Color.white)
}
}
struct StopwatchDialView_Previews: PreviewProvider {
static var previews: some View {
StopwatchDialView(stopwatch: Stopwatch.fake(context: PersistenceController.preview.container.viewContext))
}
}
Loading…
Cancel
Save