Serialized the capturing service calls for the RecordingViewModel view model in the Recording package target.
This commit is contained in:
@@ -43,6 +43,10 @@ extension RecordingView {
|
||||
@ObservationIgnored
|
||||
private let locale: Binding<Locale>
|
||||
|
||||
/// The task that serializes the calls to the capturing service, so rapid state changes can never reach the service out of order.
|
||||
@ObservationIgnored
|
||||
private var taskCapturer: Task<Void, Never>?
|
||||
|
||||
/// The task that updates ``elapsedSeconds`` from the measured recording time once per second while recording.
|
||||
@ObservationIgnored
|
||||
private var taskTimer: Task<Void, Never>?
|
||||
@@ -133,8 +137,8 @@ extension RecordingView {
|
||||
|
||||
stopTimer()
|
||||
|
||||
Task {
|
||||
try? await capturer.pause()
|
||||
enqueueCapturer {
|
||||
try? await self.capturer.pause()
|
||||
}
|
||||
case .paused:
|
||||
state = .recording
|
||||
@@ -156,8 +160,8 @@ extension RecordingView {
|
||||
|
||||
stopTimer()
|
||||
|
||||
Task {
|
||||
await processInput()
|
||||
enqueueCapturer {
|
||||
await self.processInput()
|
||||
}
|
||||
default:
|
||||
break
|
||||
@@ -207,21 +211,34 @@ private extension RecordingView.Model {
|
||||
state = .notRecording
|
||||
}
|
||||
|
||||
/// Enqueues an operation behind any previously enqueued ones, so the calls to the capturing service always reach it in the order
|
||||
/// the states changed, no matter how quickly the user presses the view's controls.
|
||||
///
|
||||
/// - Parameter operation: The operation on the capturing service to enqueue.
|
||||
func enqueueCapturer(
|
||||
_ operation: @escaping @MainActor () async -> Void
|
||||
) {
|
||||
taskCapturer = Task { [taskCapturer] in
|
||||
await taskCapturer?.value
|
||||
await operation()
|
||||
}
|
||||
}
|
||||
|
||||
/// Starts the audio capture through the attached ``Capturing``, falling back to the not-recording state when the service fails.
|
||||
///
|
||||
/// - Parameter isNewRecording: Whether a new recording should be started, as opposed to a paused one being resumed.
|
||||
func startCapturer(
|
||||
_ isNewRecording: Bool
|
||||
) {
|
||||
Task {
|
||||
enqueueCapturer {
|
||||
do {
|
||||
isNewRecording
|
||||
? try await capturer.start()
|
||||
: try await capturer.resume()
|
||||
? try await self.capturer.start()
|
||||
: try await self.capturer.resume()
|
||||
} catch {
|
||||
stopTimer()
|
||||
self.stopTimer()
|
||||
|
||||
state = .notRecording
|
||||
self.state = .notRecording
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user