velody/apps/apple/VelodyMac/Sources/MacLibraryViewModel.swift

77 lines
2.4 KiB
Swift

import Foundation
import Observation
import VelodyDomain
import VelodyPersistence
@MainActor
@Observable
final class MacLibraryViewModel {
var tracks: [LibraryTrack] = []
var selectedFolderPath = "No folder selected"
var scanStatus = "Choose a folder to begin local discovery."
var discoveredTrackCount = 0
var isScanning = false
private let folderAccessService: any VelodyPersistence.FolderAccessService
private let localMusicScanner: any LocalMusicScanner
private let store = InMemoryLocalLibraryStore()
private var hasLoaded = false
init() {
let folderAccessService = FolderAccessService()
let localMusicScanner = FileSystemLocalMusicScanner(
metadataReader: AVFoundationMetadataReader()
)
self.folderAccessService = folderAccessService
self.localMusicScanner = localMusicScanner
if let url = folderAccessService.storedFolderURL() {
selectedFolderPath = url.path
scanStatus = "Folder restored. Run a manual scan to discover MP3 files."
}
}
func loadIfNeeded() async {
guard !hasLoaded else { return }
hasLoaded = true
tracks = await store.loadTracks()
discoveredTrackCount = tracks.count
}
func chooseFolder() {
if let url = folderAccessService.chooseFolder() {
selectedFolderPath = url.path
scanStatus = "Folder selected. Run a manual scan to discover MP3 files."
tracks = []
discoveredTrackCount = 0
Task {
await store.replaceTracks([])
}
}
}
func scanMP3Files() async {
guard let folderURL = folderAccessService.storedFolderURL() else {
scanStatus = "Choose a folder before scanning."
return
}
isScanning = true
scanStatus = "Scanning MP3 files..."
defer {
isScanning = false
}
do {
let discoveredTracks = try await localMusicScanner.scanFolder(at: folderURL)
await store.replaceTracks(discoveredTracks)
tracks = await store.loadTracks()
discoveredTrackCount = tracks.count
scanStatus = "Scan finished. Found \(discoveredTrackCount) MP3 file(s)."
} catch {
scanStatus = "Scan failed: \(error.localizedDescription)"
}
}
}