Files
plezy/macos/Runner/MainFlutterWindow.swift
T
edde746 31b3689740 fix(settings): list external players only when they are installed
Detection now runs off the UI isolate and covers every platform where
the answer can be trusted.

Availability was a plain platform check, so Linux always listed VLC, mpv
and Celluloid, macOS always listed VLC and IINA, and Windows always
listed VLC and PotPlayer whether or not any of them existed. Each player
now has a detector that asks exactly the question its launcher asks:
`sh -c 'command -v'` for PATH launches so the kernel performs the
executable check, NSWorkspace/Launch Services for `open -a`, `where.exe`
plus the concrete install paths for Windows VLC, and the registered URL
handler for PotPlayer and the iOS players.

Detection is asynchronous and memoised behind KnownPlayers.probe rather
than a Process.runSync in a static initialiser, which forked three
shells on the UI isolate during ExternalPlayerScreen.build. It is
prewarmed from startup, fails open when a probe throws, and keeps the
selected player listed when a detector misses it so a false negative
cannot leave the list with nothing selected.

iOS and tvOS gained LSApplicationQueriesSchemes entries for vlc and
infuse. Without them canOpenURL returns false for both schemes, so
_launchUrlScheme was already refusing to hand off to either player.

Android keeps the platform check: package visibility needs native
declarations, and a wrong answer there hides a working player.
2026-07-28 04:38:33 +02:00

57 lines
2.1 KiB
Swift

import Cocoa
import FlutterMacOS
class MainFlutterWindow: NSWindow {
override func awakeFromNib() {
let flutterViewController = FlutterViewController()
// Keep the window itself opaque so WindowServer does not have to blend the
// whole video window with the desktop every frame. Flutter stays clear so
// the native video layer behind it remains visible.
self.isOpaque = true
self.backgroundColor = NSColor.black
flutterViewController.backgroundColor = NSColor.clear
let windowFrame = self.frame
self.contentViewController = flutterViewController
self.setFrame(windowFrame, display: true)
// Apply initial window configuration BEFORE frame restoration
// This prevents the window from shrinking on launch
self.titlebarAppearsTransparent = true
self.titleVisibility = .hidden
self.styleMask.insert(.fullSizeContentView)
// Add forwarding toolbar for click-through in titlebar area
let toolbar = ForwardingToolbar(flutterViewController: flutterViewController)
self.toolbar = toolbar
// Register MPV player plugin for video playback
MpvPlayerPlugin.register(
with: flutterViewController.registrar(forPlugin: "MpvPlayerPlugin"))
// Register the audio-only MPV player plugin for music playback
MpvAudioPlayerPlugin.register(
with: flutterViewController.registrar(forPlugin: "MpvAudioPlayerPlugin"))
// Register window utils plugin for dynamic titlebar/fullscreen control from Dart
WindowUtilsPlugin.register(
with: flutterViewController.registrar(forPlugin: "WindowUtilsPlugin"))
WindowUtilsPlugin.setWindow(self)
WindowUtilsPlugin.installWindowDelegate()
WindowUtilsPlugin.syncWindowChrome()
// Register Launch Services lookups used to detect installed external players
AppLookupPlugin.register(
with: flutterViewController.registrar(forPlugin: "AppLookupPlugin"))
RegisterGeneratedPlugins(registry: flutterViewController)
// Enable window position/size persistence
self.setFrameAutosaveName("com.edde746.plezy.MainWindow")
WindowUtilsPlugin.syncWindowChrome()
super.awakeFromNib()
}
}