Timer plays sound when expired

This commit is contained in:
VincentMeilinger
2024-01-11 20:55:18 +01:00
parent 9b225f63b5
commit c6c60faf01
6 changed files with 52 additions and 0 deletions

View File

@@ -50,6 +50,7 @@
A9CA6CEF2B4C086100F78AB5 /* RecipeExporter.swift in Sources */ = {isa = PBXBuildFile; fileRef = A9CA6CEE2B4C086100F78AB5 /* RecipeExporter.swift */; }; A9CA6CEF2B4C086100F78AB5 /* RecipeExporter.swift in Sources */ = {isa = PBXBuildFile; fileRef = A9CA6CEE2B4C086100F78AB5 /* RecipeExporter.swift */; };
A9CA6CF62B4C63F200F78AB5 /* TPPDF in Frameworks */ = {isa = PBXBuildFile; productRef = A9CA6CF52B4C63F200F78AB5 /* TPPDF */; }; A9CA6CF62B4C63F200F78AB5 /* TPPDF in Frameworks */ = {isa = PBXBuildFile; productRef = A9CA6CF52B4C63F200F78AB5 /* TPPDF */; };
A9D89AB02B4FE97800F49D92 /* TimerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A9D89AAF2B4FE97800F49D92 /* TimerView.swift */; }; A9D89AB02B4FE97800F49D92 /* TimerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A9D89AAF2B4FE97800F49D92 /* TimerView.swift */; };
A9FA2AB62B5079B200A43702 /* alarm_sound_0.mp3 in Resources */ = {isa = PBXBuildFile; fileRef = A9FA2AB52B5079B200A43702 /* alarm_sound_0.mp3 */; };
/* End PBXBuildFile section */ /* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */ /* Begin PBXContainerItemProxy section */
@@ -115,6 +116,7 @@
A7FB0D7D2B25C6A200A3469E /* V2LoginView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = V2LoginView.swift; sourceTree = "<group>"; }; A7FB0D7D2B25C6A200A3469E /* V2LoginView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = V2LoginView.swift; sourceTree = "<group>"; };
A9CA6CEE2B4C086100F78AB5 /* RecipeExporter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RecipeExporter.swift; sourceTree = "<group>"; }; A9CA6CEE2B4C086100F78AB5 /* RecipeExporter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RecipeExporter.swift; sourceTree = "<group>"; };
A9D89AAF2B4FE97800F49D92 /* TimerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimerView.swift; sourceTree = "<group>"; }; A9D89AAF2B4FE97800F49D92 /* TimerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimerView.swift; sourceTree = "<group>"; };
A9FA2AB52B5079B200A43702 /* alarm_sound_0.mp3 */ = {isa = PBXFileReference; lastKnownFileType = audio.mp3; path = alarm_sound_0.mp3; sourceTree = "<group>"; };
/* End PBXFileReference section */ /* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */ /* Begin PBXFrameworksBuildPhase section */
@@ -147,6 +149,7 @@
A70171752AA8E71900064C43 = { A70171752AA8E71900064C43 = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
A9FA2AB42B50798800A43702 /* Resources */,
A781E75E2AE9133B00452F6F /* Screenshots */, A781E75E2AE9133B00452F6F /* Screenshots */,
A70171802AA8E71900064C43 /* Nextcloud Cookbook iOS Client */, A70171802AA8E71900064C43 /* Nextcloud Cookbook iOS Client */,
A70171922AA8E72000064C43 /* Nextcloud Cookbook iOS ClientTests */, A70171922AA8E72000064C43 /* Nextcloud Cookbook iOS ClientTests */,
@@ -323,6 +326,14 @@
path = RecipeExport; path = RecipeExport;
sourceTree = "<group>"; sourceTree = "<group>";
}; };
A9FA2AB42B50798800A43702 /* Resources */ = {
isa = PBXGroup;
children = (
A9FA2AB52B5079B200A43702 /* alarm_sound_0.mp3 */,
);
path = Resources;
sourceTree = "<group>";
};
/* End PBXGroup section */ /* End PBXGroup section */
/* Begin PBXNativeTarget section */ /* Begin PBXNativeTarget section */
@@ -438,6 +449,7 @@
isa = PBXResourcesBuildPhase; isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
A9FA2AB62B5079B200A43702 /* alarm_sound_0.mp3 in Resources */,
A701718A2AA8E71F00064C43 /* Preview Assets.xcassets in Resources */, A701718A2AA8E71F00064C43 /* Preview Assets.xcassets in Resources */,
A70171862AA8E71F00064C43 /* Assets.xcassets in Resources */, A70171862AA8E71F00064C43 /* Assets.xcassets in Resources */,
A7AEAE642AD5521400135378 /* Localizable.xcstrings in Resources */, A7AEAE642AD5521400135378 /* Localizable.xcstrings in Resources */,

View File

@@ -2853,6 +2853,9 @@
} }
} }
} }
},
"Timer alert!" : {
}, },
"Title" : { "Title" : {
"localizations" : { "localizations" : {
@@ -3161,6 +3164,9 @@
} }
} }
} }
},
"Your timer is expired!" : {
} }
}, },
"version" : "1.0" "version" : "1.0"

View File

@@ -623,4 +623,8 @@ extension MainViewModel {
func getTimer(forRecipe recipeId: String, duration: DurationComponents) -> RecipeTimer { func getTimer(forRecipe recipeId: String, duration: DurationComponents) -> RecipeTimer {
return timers[recipeId] ?? createTimer(forRecipe: recipeId, duration: duration) return timers[recipeId] ?? createTimer(forRecipe: recipeId, duration: duration)
} }
func deleteTimer(forRecipe recipeId: String) {
timers.removeValue(forKey: recipeId)
}
} }

View File

@@ -8,10 +8,13 @@
import Foundation import Foundation
import SwiftUI import SwiftUI
import Combine import Combine
import AVFoundation
struct TimerView: View { struct TimerView: View {
@ObservedObject var timer: RecipeTimer @ObservedObject var timer: RecipeTimer
@State var audioPlayer: AVAudioPlayer?
@State var presentTimerAlert: Bool = false
var body: some View { var body: some View {
HStack { HStack {
@@ -56,6 +59,31 @@ struct TimerView: View {
RoundedRectangle(cornerRadius: 20) RoundedRectangle(cornerRadius: 20)
.foregroundStyle(.ultraThickMaterial) .foregroundStyle(.ultraThickMaterial)
} }
.alert("Timer alert!", isPresented: $timer.timerExpired) {
Button {
timer.timerExpired = false
audioPlayer?.stop()
} label: {
Text("Your timer is expired!")
}
.onAppear {
playSound()
}
}
}
func playSound() {
if let path = Bundle.main.path(forResource: "alarm_sound_0", ofType: "mp3") {
do {
audioPlayer = try AVAudioPlayer(contentsOf: URL(fileURLWithPath: path))
audioPlayer?.prepareToPlay()
} catch {
// Handle the error
print("Error loading sound file.")
return
}
}
audioPlayer?.play()
} }
} }
@@ -68,6 +96,7 @@ class RecipeTimer: ObservableObject {
private var pauseDate: Date? private var pauseDate: Date?
@Published var timeElapsed: Double = 0 @Published var timeElapsed: Double = 0
@Published var isRunning: Bool = false @Published var isRunning: Bool = false
@Published var timerExpired: Bool = false
private var timer: Timer.TimerPublisher? private var timer: Timer.TimerPublisher?
private var timerCancellable: Cancellable? private var timerCancellable: Cancellable?
@@ -95,6 +124,7 @@ class RecipeTimer: ObservableObject {
self.timeElapsed = elapsed self.timeElapsed = elapsed
self.duration.fromSeconds(Int(self.timeTotal - self.timeElapsed)) self.duration.fromSeconds(Int(self.timeTotal - self.timeElapsed))
} else { } else {
self.timerExpired = true
self.timeElapsed = self.timeTotal self.timeElapsed = self.timeTotal
self.duration.fromSeconds(Int(self.timeTotal - self.timeElapsed)) self.duration.fromSeconds(Int(self.timeTotal - self.timeElapsed))
self.pause() self.pause()

BIN
Resources/alarm_sound_0.mp3 Normal file

Binary file not shown.