diff --git a/Flixy/Info-macOS.plist b/Flixy/Info-macOS.plist
index 988b4c7..6d51a6c 100644
--- a/Flixy/Info-macOS.plist
+++ b/Flixy/Info-macOS.plist
@@ -31,6 +31,8 @@
CFBundleVersion
1
+ ITSAppUsesNonExemptEncryption
+
LSApplicationCategoryType
public.app-category.entertainment
NSAppTransportSecurity
@@ -38,7 +40,22 @@
NSAllowsLocalNetworking
- NSHumanReadableCopyright
-
+ UIBackgroundModes
+
+ audio
+
+ UILaunchScreen
+
+ UIColorName
+ LaunchBackground
+
+ UISupportedInterfaceOrientations
+
+ UIInterfaceOrientationPortrait
+ UIInterfaceOrientationLandscapeLeft
+ UIInterfaceOrientationLandscapeRight
+
+ UIUserInterfaceStyle
+ Dark
diff --git a/Flixy/Session/PlaybackSettings.swift b/Flixy/Session/PlaybackSettings.swift
index b88b1c9..4e01696 100644
--- a/Flixy/Session/PlaybackSettings.swift
+++ b/Flixy/Session/PlaybackSettings.swift
@@ -1,4 +1,7 @@
import Foundation
+#if canImport(FlixyVLC)
+import FlixyVLC
+#endif
import Observation
import FlixyPlayback
@@ -53,6 +56,21 @@ final class PlaybackSettings {
/// Die Geschwindigkeiten, mit denen eine Wiedergabe beginnen kann.
static let rateChoices: [Double] = [0.75, 1.0, 1.25, 1.5, 1.75, 2.0]
+ /// Ob ein zweiter Spieler zur Verfügung steht.
+ ///
+ /// VLC steckt in einem eigenen Paket, das nur für iOS gebaut wird — sein
+ /// Binärpaket hat keinen Teil für Mac Catalyst. Wo es fehlt, übernimmt der
+ /// Server: MKV und DTS werden dann umgerechnet statt unverändert
+ /// übertragen. Das kostet ihn Rechenzeit und sieht man nicht, aber es
+ /// spielt.
+ static var hasFallbackEngine: Bool {
+ #if canImport(FlixyVLC)
+ true
+ #else
+ false
+ #endif
+ }
+
private let defaults: UserDefaults
var wifiQuality: Quality { didSet { defaults.set(wifiQuality.rawValue, forKey: Key.wifiQuality) } }
@@ -129,7 +147,10 @@ final class PlaybackSettings {
return PlaybackPolicy(
allowsTranscoding: true,
- allowsFallbackEngine: true,
+ // Nur, wenn es ihn auf dieser Plattform gibt. Ohne VLC wählte die
+ // Entscheidung sonst einen Spieler, den es nicht gibt — und die
+ // Wiedergabe bliebe schwarz, statt dass der Server umrechnet.
+ allowsFallbackEngine: Self.hasFallbackEngine,
maximumBitrate: quality.bitrateLimit
)
}
diff --git a/Packages/FlixyKit/Sources/FlixyDownloads/Engine/DownloadActivityPresenter.swift b/Packages/FlixyKit/Sources/FlixyDownloads/Engine/DownloadActivityPresenter.swift
index e4397f0..f1534f7 100644
--- a/Packages/FlixyKit/Sources/FlixyDownloads/Engine/DownloadActivityPresenter.swift
+++ b/Packages/FlixyKit/Sources/FlixyDownloads/Engine/DownloadActivityPresenter.swift
@@ -1,6 +1,9 @@
import Foundation
-#if os(iOS)
+// Catalyst ausdrücklich ausgenommen: dort gilt `os(iOS)`, aber ActivityKit
+// gibt es nicht — die Typen sind zwar da und jeder Aufruf ist als nicht
+// verfügbar markiert.
+#if os(iOS) && !targetEnvironment(macCatalyst)
// `@preconcurrency`, weil `Activity` und `ActivityContent` keine
// Sendable-Zusage tragen. Beide bleiben hier ohnehin auf dem Hauptakteur —
// die Klasse ist darauf festgelegt, und ActivityKit erwartet seine Aufrufe
diff --git a/Packages/FlixyKit/Sources/FlixyDownloads/Engine/DownloadCoordinator.swift b/Packages/FlixyKit/Sources/FlixyDownloads/Engine/DownloadCoordinator.swift
index 824fbf3..6a23a31 100644
--- a/Packages/FlixyKit/Sources/FlixyDownloads/Engine/DownloadCoordinator.swift
+++ b/Packages/FlixyKit/Sources/FlixyDownloads/Engine/DownloadCoordinator.swift
@@ -149,7 +149,9 @@ public final class DownloadCoordinator {
return created
}
- #if os(iOS)
+ // Catalyst ausdrücklich ausgenommen: dort gilt `os(iOS)`, aber
+ // ActivityKit gibt es nicht.
+ #if os(iOS) && !targetEnvironment(macCatalyst)
private let activityPresenter = DownloadActivityPresenter()
#endif
@@ -564,7 +566,10 @@ public final class DownloadCoordinator {
/// gleichzeitigen ist das der, der zuerst fertig wird, und damit der, auf
/// den man wartet.
private func updateActivity() {
- #if os(iOS)
+ // Catalyst ausdrücklich ausgenommen: dort gilt `os(iOS)`, aber
+ // ActivityKit gibt es nicht — die Typen sind zwar da, und jeder
+ // Aufruf ist als nicht verfügbar markiert.
+ #if os(iOS) && !targetEnvironment(macCatalyst)
let running = items.filter { $0.state == .downloading }
guard let leading = running.max(by: { ($0.progress ?? 0) < ($1.progress ?? 0) }) else {
Task { [activityPresenter] in await activityPresenter.update(with: nil) }
diff --git a/Packages/FlixyKit/Sources/FlixyDownloads/Model/DownloadActivityAttributes.swift b/Packages/FlixyKit/Sources/FlixyDownloads/Model/DownloadActivityAttributes.swift
index c3fa53c..9281876 100644
--- a/Packages/FlixyKit/Sources/FlixyDownloads/Model/DownloadActivityAttributes.swift
+++ b/Packages/FlixyKit/Sources/FlixyDownloads/Model/DownloadActivityAttributes.swift
@@ -3,7 +3,10 @@ import Foundation
// `os(iOS)` statt `canImport(ActivityKit)`: der Import gelingt auch auf
// macOS, die Typen darin sind dort aber als nicht verfügbar markiert. Eine
// Prüfung auf den Import allein übersetzt deshalb nicht.
-#if os(iOS)
+// Catalyst ausdrücklich ausgenommen: dort gilt `os(iOS)`, aber ActivityKit
+// gibt es nicht — die Typen sind zwar da und jeder Aufruf ist als nicht
+// verfügbar markiert.
+#if os(iOS) && !targetEnvironment(macCatalyst)
import ActivityKit
/// Was im Sperrbildschirm und in der Dynamic Island steht.
diff --git a/project.yml b/project.yml
index f82ea31..7413425 100644
--- a/project.yml
+++ b/project.yml
@@ -148,25 +148,27 @@ targets:
# Die Live Activity für Downloads. Eine eigene Erweiterung, weil iOS die
# Darstellung im Sperrbildschirm in einem getrennten Prozess zeichnet — die
# App selbst läuft zu dem Zeitpunkt meist gar nicht.
- # Dieselben Quellen, eigenes Ziel.
+ # Dieselben Quellen, dasselbe Aussehen.
#
- # Ein gemeinsames Target für beide Plattformen wäre weniger Text, aber die
- # Info.plist ist voller iOS-Angaben — Startbildschirm, erlaubte
- # Ausrichtungen, Live Activities. Die müssten dann alle bedingt werden, und
- # jede spätere Änderung an der iOS-Seite ginge über eine Stelle, die auch
- # den Mac betrifft. Zwei Ziele sind ein paar Zeilen mehr und ein Sorge
- # weniger.
+ # Mac Catalyst statt einer eigenen Mac-App: die iPad-Oberfläche läuft damit
+ # unverändert auf dem Mac — gleiche Schriftgrößen, gleiche Seitenleiste,
+ # gleiche Abstände. Eine native Mac-App war der erste Versuch; sie sah an
+ # zwei Dutzend Stellen anders aus, weil AppKit dieselben Dinge anders misst,
+ # und jede davon hätte einzeln nachgezogen werden müssen.
#
- # Ohne DownloadWidget (Live Activities gibt es auf dem Mac nicht) und ohne
- # FlixyVLC: das Binärpaket ist auf iOS festgelegt. Der Player fällt dort
- # allein auf den Systemplayer zurück — was er nicht öffnen kann, sagt er.
+ # Ohne DownloadWidget (Live Activities gibt es hier nicht) und **ohne
+ # FlixyVLC**: dessen Binärpaket hat keinen Teil für Catalyst. MKV und DTS
+ # werden dort deshalb vom Server umgerechnet statt unverändert übertragen —
+ # siehe `PlaybackSettings.hasFallbackEngine`.
FlixyMac:
type: application
- platform: macOS
+ platform: iOS
sources:
- path: Flixy
excludes:
- "AppIcon.icon"
+ - path: Flixy/AppIcon.icon
+ type: file
dependencies:
- package: FlixyKit
product: MediaKit
@@ -182,25 +184,42 @@ targets:
product: FlixyDownloads
settings:
base:
+ SUPPORTS_MACCATALYST: YES
+ # Nur Mac: dieses Ziel ist nicht dazu da, aufs iPhone zu wandern.
+ SUPPORTED_PLATFORMS: macosx
+ # „An das iPad angeglichen" statt „für den Mac optimiert" — genau
+ # darum geht es.
+ MACCATALYST_OPTIMIZE_FOR_MAC: NO
+ DERIVE_MACCATALYST_PRODUCT_BUNDLE_IDENTIFIER: NO
PRODUCT_BUNDLE_IDENTIFIER: com.scarriffleservices.flixy
PRODUCT_NAME: Flixy
- # Selbst signiert, ohne Entwicklerkonto: ein Build zum Ansehen soll
- # nicht jedes Mal nach dem Schlüsselbund-Passwort fragen.
+ ASSETCATALOG_COMPILER_APPICON_NAME: AppIcon
+ TARGETED_DEVICE_FAMILY: "2"
+ # Selbst signiert: ein Build zum Ansehen soll nicht jedes Mal nach dem
+ # Schlüsselbund-Passwort fragen.
CODE_SIGN_STYLE: Manual
CODE_SIGN_IDENTITY: "-"
DEVELOPMENT_TEAM: ""
ENABLE_HARDENED_RUNTIME: NO
- COMBINE_HIDPI_IMAGES: YES
info:
path: Flixy/Info-macOS.plist
properties:
CFBundleDisplayName: Flixy
+ UILaunchScreen:
+ UIColorName: LaunchBackground
+ UIUserInterfaceStyle: Dark
+ UISupportedInterfaceOrientations:
+ - UIInterfaceOrientationPortrait
+ - UIInterfaceOrientationLandscapeLeft
+ - UIInterfaceOrientationLandscapeRight
+ UIBackgroundModes:
+ - audio
LSApplicationCategoryType: public.app-category.entertainment
- NSHumanReadableCopyright: ""
CFBundleURLTypes:
- CFBundleURLName: com.scarriffleservices.flixy.auth
CFBundleURLSchemes:
- com.scarriffleservices.flixy
+ ITSAppUsesNonExemptEncryption: false
NSAppTransportSecurity:
NSAllowsLocalNetworking: true