refactor: modernize Cast discovery and app activation

This commit is contained in:
2026-10-22 09:16:19 +02:00
parent f1893a5a5f
commit 419ac8d677
8 changed files with 279 additions and 67 deletions
+3 -3
View File
@@ -29,12 +29,12 @@ Audited on 2026-10-22 with Xcode 27.0, macOS SDK 27.0 and Swift 6.4, in Swift 6
| --- | --- |
| 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. |
| Cast discovery | Uses [`NWBrowser`](https://developer.apple.com/documentation/network/nwbrowser) with TXT records. Receiver identity/name fallbacks, natural ordering, deduplication, removal and resolved host/port routing are retained. Discovery resolves endpoints without opening a Cast TCP/TLS session. |
| App activation | Production calls use [`activate()`](https://developer.apple.com/documentation/appkit/nsapplication/activate()), available from macOS 14. Activation is cooperative, not a guarantee of foreground focus; system permission dialogs and the lock screen take precedence. |
| 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.
Verification: SDK build/bundle checks, real Bonjour discovery, loopback Cast transitions and focused startup-error alerts passed. A production-app smoke with a cooperating foreground launcher passed cold start, CLI reuse/document handoff and keyboard pause/resume. The full CLI state-snapshot harness hit its existing no-snapshot timeout; macOS 15 runtime and physical-Chromecast verification remain unperformed. Native focus checks require an unlocked desktop and resolved Local Network permission prompts for disposable test copies.
### Install