Files
notes/Notes/AppServices/AppServices.swift
T
rzen 86d74806c9 Add voice notes: on-device transcription, multi-language, watch capture
- 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
2026-07-15 13:30:43 -04:00

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()
}
}