diff --git a/README.md b/README.md index 4a3d390..f0f3390 100644 --- a/README.md +++ b/README.md @@ -19,6 +19,23 @@ With the macOS 27 SDK, the player uses a private `ViewState` alias for the `Swif The resulting `.build/terebi.app` is self-contained: copy the whole app to a compatible Mac of the same architecture. No separate FFmpeg, Python, or yt-dlp installation is needed to run it. +### Apple SDK and UI API audit + +Audited on 2026-10-22 with Xcode 27.0, macOS SDK 27.0 and Swift 6.4, in Swift 6 language mode. The build uses the active `xcrun` toolchain, not a pinned old SDK. `Makefile`, `Package.swift` and `Resources/Info.plist` consistently retain macOS 15 as the minimum; the rebuilt player and bootstrap report SDK 27.0 / minimum OS 15.0 in their Mach-O build metadata. A newer build SDK does not require raising the minimum OS; newer APIs still need availability guards. + +**Keep the SwiftUI/AppKit architecture.** The app already uses SwiftUI `App`, `Window`, `Commands`, focus, typed URL drops, two-value `onChange` and `WindowDragGesture`. AppKit bridges serve specific native requirements, not a second legacy UI. + +| Area | Assessment and decision | +| --- | --- | +| Native views and windows | Keep `NSViewRepresentable` bridges in `Sources/App/TerebiApp.swift` and `CompactWindowController`. They preserve the Metal renderer, buffered slider drawing, user tracking versus Cast feedback, native input routing and same-window compact/fullscreen geometry. [Apple documents this interoperability](https://developer.apple.com/documentation/swiftui/nsviewrepresentable). | +| State observation | `PlayerModel` and `CastDiscovery` use supported `ObservableObject`/`@Published`. [Observation](https://developer.apple.com/documentation/swiftui/migrating-from-the-observable-object-protocol-to-the-observable-macro) is available from macOS 14 and can narrow view invalidation. Consider it when profiling demonstrates unnecessary updates; no performance defect was measured here. A migration must preserve manual compact/Cast notifications, bindings and focused commands together. | +| Cast discovery | The clearest platform migration candidate is `NetServiceBrowser`/`NetService` in `Sources/App/CastSession.swift`. SDK 27's `Foundation/NSNetServices.h` recommends Network framework using **future-deprecation** annotations (`API_TO_BE_DEPRECATED`), not a reached removal date. Prefer [`NWBrowser`](https://developer.apple.com/documentation/network/nwbrowser) in a scoped migration that retains TXT identity/name records, device removal/deduplication, resolved endpoints and receiver-host routing for the media server. Current discovery still compiles without warnings. | +| App activation | `Sources/App/Bootstrap.swift` and `Sources/App/TerebiApp.swift` use `activate(ignoringOtherApps:)`. SDK 27's `AppKit/NSApplication.h` recommends [`activate()`](https://developer.apple.com/documentation/appkit/nsapplication/activate()), available from macOS 14, with a future-deprecation annotation. Migrate deliberately: the replacement does not guarantee foreground activation, so launch, focus and error-alert behavior need native verification. | +| Glass/chrome | `PlayerGlass` uses supported `NSVisualEffectView`, not native Liquid Glass. [`glassEffect`](https://developer.apple.com/documentation/swiftui/view/glasseffect(_:in:)) / [`NSGlassEffectView`](https://developer.apple.com/documentation/appkit/nsglasseffectview) require macOS 26; AppKit's `effectIsInteractive` requires 27. Optional adoption belongs on controls/chrome, not every content background, with the macOS 15 path retained and visual/accessibility verification. See [Apple's materials guidance](https://developer.apple.com/design/human-interface-guidelines/materials). | +| Playback backend | Keep MetalKit `MTKView` and the Core Audio output callback in `Sources/macOS/Output.mm`. They implement rendering and audio-clock synchronization; SwiftUI is not a replacement for that backend. | + +Verification: forced recompilation of the Swift player, Objective-C++ renderer, bootstrap and CLI against the active SDK passed without compiler diagnostics; bundling/signature verification, CLI `--help`, and loading the rebuilt player dylib with its exported entry point passed. This was an API/toolchain audit, not a visual review, an exhaustive certification of every backend symbol, or a runtime test on macOS 15. No behavioral migrations were made. + ### Install ```sh diff --git a/TODO.md b/TODO.md index 3fb57bd..25ce5f9 100644 --- a/TODO.md +++ b/TODO.md @@ -17,5 +17,6 @@ - 200 ms fade/scale with animated row reflow; the button and ⇧⌘O toggle the same inline input, including while editing; native focus, draft-preservation and rapid-reversal checks cover mouse/shortcut interoperation - [x] change the youtube button to general streaming - Open Stream routes YouTube videos and explicit barelystarted.miruro.tv episode links; live Miruro video/audio and VTT seek checks passed, with shared validated source metadata and unchanged Tubular source/progress contracts; CLI handoff emitted v2 playback/end facts, but its GUI-state checker timed out without snapshots; physical UI/drop/Cast verification remains unverified -- [ ] check whether we're using appropriately new apple ui APIs / SDKs for the project. - - we should strive to use modern and idiomatic SDKs and APIs including SwiftUI among others \ No newline at end of file +- [x] check whether we're using appropriately new apple ui APIs / SDKs for the project. + - we should strive to use modern and idiomatic SDKs and APIs including SwiftUI among others + - audited SDK 27.0 / Swift 6.4 with a consistent macOS 15 minimum; SwiftUI already owns the UI, and native bridges retain required behavior. Scoped migration candidates: Network-framework Cast discovery and cooperative app activation; Observation and native Liquid Glass remain elective. Forced Swift/native builds, Mach-O SDK/minimum checks, CLI and dylib-load smoke passed; findings and Apple references are in README's Apple SDK and UI API audit. No runtime/UI behavior changed; macOS 15 runtime and visual verification were not performed. \ No newline at end of file