- Schema v2: Note.AudioInfo, .m4a sidecar next to the note JSON in iCloud - AudioRecorderService (iOS/macOS) + SpeechAnalyzer transcription pipeline with enabled-language set and confidence-based auto-pick, re-transcribe menu - Settings > Transcription > Languages with asset download/reserve handling - watchOS app + accessory complication: one-button recorder, WCSession transferFile to phone, WatchInbox staging, direct-upsert ingestion - Player UI, transcription status chips, quick-capture mic in notes list - Version 0.2, changelog + README updated
59 lines
2.2 KiB
Swift
59 lines
2.2 KiB
Swift
import Foundation
|
|
import IndieBackup
|
|
import SwiftData
|
|
|
|
/// Owns all service objects; created asynchronously at launch and injected
|
|
/// into the SwiftUI environment.
|
|
@Observable
|
|
@MainActor
|
|
final class AppServices {
|
|
let modelContainer: ModelContainer
|
|
let syncEngine: SyncEngine
|
|
let contextService: ContextService
|
|
let backupController: BackupController
|
|
let audioRecorder: AudioRecorderService
|
|
let transcriptionSettings: TranscriptionSettings
|
|
let transcriptionService: TranscriptionService
|
|
|
|
init() async {
|
|
let container = NotesModelContainer.make()
|
|
self.modelContainer = container
|
|
let engine = SyncEngine(modelContainer: container)
|
|
self.syncEngine = engine
|
|
self.contextService = ContextService()
|
|
self.backupController = BackupController(
|
|
configuration: NotesBackupConfiguration(syncEngine: engine)
|
|
)
|
|
self.audioRecorder = AudioRecorderService()
|
|
let settings = TranscriptionSettings()
|
|
self.transcriptionSettings = settings
|
|
let transcription = TranscriptionService(
|
|
syncEngine: engine,
|
|
settings: settings,
|
|
modelContainer: container
|
|
)
|
|
self.transcriptionService = transcription
|
|
|
|
// A watch recording, once ingested, is this device's to transcribe.
|
|
engine.onAudioNoteIngested = { [weak transcription] id in
|
|
transcription?.enqueue(noteID: id)
|
|
}
|
|
}
|
|
|
|
/// The file extension this app owns for backup documents. Used to route
|
|
/// `onOpenURL` imports to a restore.
|
|
var backupFileExtension: String { backupController.configuration.backupFileExtension }
|
|
|
|
/// Slow startup work (iCloud container discovery) — runs after the UI is up.
|
|
func startDeferredServices() async {
|
|
await syncEngine.connect()
|
|
// Drain any watch recordings delivered while the app was closed — the
|
|
// container is connected now, so they can be written and ingested.
|
|
await syncEngine.ingestStagedWatchRecordings()
|
|
// Load the supported languages / reservation cap, then pick up any of
|
|
// this device's notes that were still pending when it last quit.
|
|
await transcriptionSettings.prepare()
|
|
transcriptionService.resumePendingWork()
|
|
}
|
|
}
|