SPB Git

spb/ka-ios

Public
2.7 KB · 82 lines swift
1// Auteur : Simon-Pierre Boucher — contact@spboucher.ai2// FavoritesStore.swift — favoris et collections UNIFIÉS (tous univers dans une3// même collection : « Déménagement à Val-d'Or » peut contenir un 4½, une auto4// et un resto). Persistance JSON locale (consultation hors ligne).5import Foundation6import SwiftUI78@MainActor9final class FavoritesStore: ObservableObject {10    static let shared = FavoritesStore()1112    struct FavCollection: Identifiable, Codable, Hashable {13        var id: UUID = UUID()14        var name: String15        var items: [KAItem] = []16    }1718    @Published private(set) var collections: [FavCollection] = [] {19        didSet { save() }20    }2122    private var fileURL: URL {23        let dir = FileManager.default.urls(for: .applicationSupportDirectory, in: .userDomainMask)[0]24        try? FileManager.default.createDirectory(at: dir, withIntermediateDirectories: true)25        return dir.appendingPathComponent("ka-favoris.json")26    }2728    init() {29        if let data = try? Data(contentsOf: fileURL),30           let saved = try? JSONDecoder().decode([FavCollection].self, from: data) {31            collections = saved32        }33        if collections.isEmpty {34            collections = [FavCollection(name: "Mes favoris")]35        }36    }3738    private func save() {39        if let data = try? JSONEncoder().encode(collections) {40            try? data.write(to: fileURL, options: .atomic)41        }42    }4344    // MARK: API4546    var allItems: [KAItem] { collections.flatMap(\.items) }4748    func isFavorite(_ item: KAItem) -> Bool {49        collections.contains { $0.items.contains { $0.id == item.id } }50    }5152    func toggle(_ item: KAItem, in collectionID: UUID? = nil) {53        if isFavorite(item) {54            for i in collections.indices {55                collections[i].items.removeAll { $0.id == item.id }56            }57        } else {58            let idx = collections.firstIndex { $0.id == collectionID } ?? 059            collections[idx].items.insert(item, at: 0)60        }61        Haptics.tap()62    }6364    func addCollection(_ name: String) {65        let trimmed = name.trimmingCharacters(in: .whitespaces)66        guard !trimmed.isEmpty else { return }67        collections.append(FavCollection(name: trimmed))68    }6970    func removeCollection(_ id: UUID) {71        guard collections.count > 1 else { return }72        collections.removeAll { $0.id == id }73    }7475    func move(_ item: KAItem, to collectionID: UUID) {76        for i in collections.indices { collections[i].items.removeAll { $0.id == item.id } }77        if let idx = collections.firstIndex(where: { $0.id == collectionID }) {78            collections[idx].items.insert(item, at: 0)79        }80    }81}82
Files · 49720973fdf7a4e5315f9bb1e1fdf61c629116cd
Menu

Theme