Zum Inhalt

apple/PhysarumApp/Sources/Model/AudioPresetStore.swift

import Foundation

/// Persists audio presets as JSON in Application Support (`Physarum/AudioPresets/<id>.json`),
/// ordered by `_order.json`. Mirrors PresetStore.
final class AudioPresetStore {
    private let dir: URL
    private let orderURL: URL
    private let fm = FileManager.default

    init(baseDir: URL? = nil) {
        if let base = baseDir { dir = base }
        else if let appSupport = try? FileManager.default.url(
            for: .applicationSupportDirectory, in: .userDomainMask, appropriateFor: nil, create: true) {
            dir = appSupport.appendingPathComponent("Physarum/AudioPresets", isDirectory: true)
        } else {
            dir = URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent("PhysarumAudioPresets", isDirectory: true)
        }
        orderURL = dir.appendingPathComponent("_order.json")
        try? fm.createDirectory(at: dir, withIntermediateDirectories: true)
    }

    func save(_ cfg: AudioConfig) throws {
        try JSONEncoder().encode(cfg).write(to: fileURL(cfg.id))
        var order = loadOrder()
        if !order.contains(cfg.id) { order.append(cfg.id); writeOrder(order) }
    }
    func loadAll() -> [AudioConfig] {
        let order = loadOrder(); let dec = JSONDecoder()
        let files = ((try? fm.contentsOfDirectory(at: dir, includingPropertiesForKeys: nil)) ?? [])
            .filter { $0.pathExtension == "json" && $0.lastPathComponent != "_order.json" }
        let byId = Dictionary(files.compactMap { try? dec.decode(AudioConfig.self, from: Data(contentsOf: $0)) }.map { ($0.id, $0) },
                              uniquingKeysWith: { a, _ in a })
        var result = order.compactMap { byId[$0] }
        for (id, c) in byId where !order.contains(id) { result.append(c) }
        return result
    }
    func delete(_ id: String) { try? fm.removeItem(at: fileURL(id)); writeOrder(loadOrder().filter { $0 != id }) }
    func reorder(_ ids: [String]) { writeOrder(ids) }

    private func fileURL(_ id: String) -> URL { dir.appendingPathComponent("\(id).json") }
    private func loadOrder() -> [String] {
        guard let d = try? Data(contentsOf: orderURL), let a = try? JSONDecoder().decode([String].self, from: d) else { return [] }
        return a
    }
    private func writeOrder(_ ids: [String]) { try? JSONEncoder().encode(ids).write(to: orderURL) }
}