SPB Git forge

spb/ka-ios

Public
20commits 1branches 0releases
17.2 MBsize
maindefault branch
29 days agolast push
Swift 100%
2.8 KB · 84 lines swift
Raw Blame History
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            PersonalizationStore.shared.record(.unfavorite, item: item)58        } else {59            let idx = collections.firstIndex { $0.id == collectionID } ?? 060            collections[idx].items.insert(item, at: 0)61            PersonalizationStore.shared.record(.favorite, item: item)62        }63        Haptics.tap()64    }6566    func addCollection(_ name: String) {67        let trimmed = name.trimmingCharacters(in: .whitespaces)68        guard !trimmed.isEmpty else { return }69        collections.append(FavCollection(name: trimmed))70    }7172    func removeCollection(_ id: UUID) {73        guard collections.count > 1 else { return }74        collections.removeAll { $0.id == id }75    }7677    func move(_ item: KAItem, to collectionID: UUID) {78        for i in collections.indices { collections[i].items.removeAll { $0.id == item.id } }79        if let idx = collections.firstIndex(where: { $0.id == collectionID }) {80            collections[idx].items.insert(item, at: 0)81        }82    }83}84