import Foundation import Observation import MediaKit /// Welche Einträge die Navigation zeigt und in welcher Reihenfolge. /// /// Hält nur die Einstellung und ihre Speicherung. Das Anordnen selbst macht /// `Arrangement` in MediaKit — dieselbe Rechnung, die schon die Reihen der /// Startseite ordnet, samt ihrer Tests. Dort liegen die kniffligen Fälle: /// eine Mediathek, die neu auf dem Server auftaucht, und eine, die aus der /// gespeicherten Reihenfolge verschwindet. @MainActor @Observable final class NavigationLayoutSettings { private enum Key { static let hidden = "flixy.navigation.hidden" static let order = "flixy.navigation.order" } private let defaults: UserDefaults private(set) var arrangement: Arrangement init(defaults: UserDefaults = .standard) { self.defaults = defaults arrangement = Arrangement( hidden: Set(defaults.stringArray(forKey: Key.hidden) ?? []), order: defaults.stringArray(forKey: Key.order) ?? [] ) } func isHidden(_ id: String) -> Bool { arrangement.hidden.contains(id) } func setHidden(_ hidden: Bool, for id: String) { if hidden { arrangement.hidden.insert(id) } else { arrangement.hidden.remove(id) } defaults.set(Array(arrangement.hidden), forKey: Key.hidden) } /// Legt die Reihenfolge neu fest. /// /// Gespeichert wird die **vollständige** Liste, auch die ausgeblendeten /// Einträge. Sonst rutschte ein Eintrag, den man aus- und wieder /// einblendet, ans Ende — er stünde in der Reihenfolge nicht mehr drin. func setOrder(_ ids: [String]) { arrangement.order = ids defaults.set(ids, forKey: Key.order) } /// Wendet Auswahl und Reihenfolge an. func apply(to elements: [Element]) -> [Element] { arrangement.apply(to: elements) } /// Nur die Reihenfolge, ohne auszublenden — für den Bearbeiten-Modus, in /// dem auch die ausgeblendeten Einträge zu sehen sein müssen. func ordered(_ elements: [Element]) -> [Element] { Arrangement(hidden: [], order: arrangement.order).apply(to: elements) } }