Phase 4: Medien-Widget mit dreistufiger Kaskade
Adapter für alles inklusive Browser, AppleScript für Spotify und Musik, Medientasten als letzte Reserve. Die Reihenfolge ist keine Vorliebe, sondern Absicherung: Apple hat die Now-Playing-Schnittstelle in macOS 15.4 schon einmal zugemacht. Fällt der Adapter aus, verliert das Widget seine Anzeige — aber nicht seine Funktion. Deshalb bleiben die Transporttasten auch dann bedienbar, wenn gar keine Metadaten da sind. Der Fortschritt zählt zwischen den Ereignissen selbst hoch. Spike B hatte gezeigt, dass elapsedTime nicht laufend nachgeliefert wird: ein Scrubber, der stur den letzten Wert anzeigt, steht still, während der Titel läuft. Gerechnet wird aus asOf und playbackRate, begrenzt auf die Titellänge — sonst zeigt die Anzeige nach dem Ende weiter steigende Zahlen. Teilmeldungen (diff = true) ergänzen den Stand, statt ihn zu ersetzen. Eine Meldung mit nur der Position würde sonst Titel, Interpret und Cover löschen. In AnyDecodable wird Bool vor Double geprüft. Andernfalls wird "playing": true zu 1 und die Wiedergabe gilt für immer als angehalten. Play/Pause schaltet sofort um, statt auf das nächste Ereignis zu warten. Ein Knopf, der eine halbe Sekunde später reagiert, fühlt sich kaputt an; das echte Ereignis korrigiert den Stand ohnehin. Der Adapter liegt als Quellcode unter Vendor/ (BSD-3, Stand in ONYX-VERSION.txt) und wird beim Bauen kompiliert, statt als fertige Binary eingecheckt zu werden. Er wird bewusst nicht gelinkt: geladen wird er von /usr/bin/perl, im eigenen Prozess greift Apples Entitlement-Prüfung. 124 Tests grün.
This commit is contained in:
@@ -7,6 +7,7 @@ import OnyxMenuBar
|
||||
import OnyxWidgetKit
|
||||
import CalendarProvider
|
||||
import WeatherProvider
|
||||
import MediaProvider
|
||||
|
||||
@main
|
||||
struct OnyxApp: App {
|
||||
@@ -32,6 +33,7 @@ final class AppDelegate: NSObject, NSApplicationDelegate {
|
||||
private var onyxItem: NSStatusItem?
|
||||
private var calendarModel: CalendarModel?
|
||||
private var weatherModel: WeatherModel?
|
||||
private var mediaModel: MediaModel?
|
||||
private let settingsWindow = SettingsWindowController()
|
||||
|
||||
func applicationDidFinishLaunching(_ notification: Notification) {
|
||||
@@ -127,6 +129,10 @@ final class AppDelegate: NSObject, NSApplicationDelegate {
|
||||
self.weatherModel = weatherModel
|
||||
WidgetRegistry.shared.register(WeatherWidget(model: weatherModel))
|
||||
|
||||
let mediaModel = MediaModel()
|
||||
self.mediaModel = mediaModel
|
||||
WidgetRegistry.shared.register(MediaWidget(model: mediaModel))
|
||||
|
||||
PlaceholderWidgets.registerAll()
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user