Die Seitenleiste lässt sich wieder bearbeiten: Ziehen zum Umsortieren, Haken zum Ein- und Ausblenden. Das Anordnen macht `Arrangement` aus MediaKit — dieselbe Rechnung samt Tests, die schon die Reihen der Startseite ordnet, mit ihren kniffligen Fällen: eine Mediathek, die neu auftaucht, und eine, die aus der gespeicherten Reihenfolge verschwindet. Gespeichert wird über eine feste Kennung **ohne** den Titel, damit eine umbenannte Mediathek ihren Platz behält. Die Suche ist auf dem iPhone kein eigener Reiter mehr. Die Leiste unten hat fünf Plätze, und einer davon für etwas, das man in einer Mediathek sucht, ist einer zu viel — sie sitzt jetzt über der Mediathek, neben Filter und Ansicht. Der Umschalter zwischen Seite und oben ließ sich auf dem Mac kaum treffen: ein Knopf aus einem Zeichen mit Rand hat ohne `contentShape` nur das Zeichen als Ziel. Beide Umschalter haben jetzt eine Fläche. Die Leiste oben trägt dieselbe Schriftgröße wie die Seitenleiste. In Beschriftungsgröße war sie auf einem großen Bildschirm winzig. Und eine Maske: der Aufmacher greift nach links unter die Seitenleiste, scrollt dabei aber, während die Leiste steht — über und unter ihr blieb je ein Streifen Bild stehen. Die Maske sitzt im festen Teil und lässt genau zwei Flächen übrig: alles ab der Inhaltskante, und die Fläche der Leiste. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
65 lines
2.2 KiB
Swift
65 lines
2.2 KiB
Swift
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<Element: Arrangeable>(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<Element: Arrangeable>(_ elements: [Element]) -> [Element] {
|
|
Arrangement(hidden: [], order: arrangement.order).apply(to: elements)
|
|
}
|
|
}
|