name: Flixy options: bundleIdPrefix: com.scarriffleservices deploymentTarget: iOS: "26.0" macOS: "26.0" createIntermediateGroups: true groupSortPosition: top developmentLanguage: en settings: base: DEVELOPMENT_TEAM: PP34X97WS3 SWIFT_VERSION: "6.0" MARKETING_VERSION: "0.1.0" CURRENT_PROJECT_VERSION: "1" SWIFT_STRICT_CONCURRENCY: complete packages: FlixyKit: path: Packages/FlixyKit # Eigenes Package, weil das VLCKit-Binärpaket 920 MB wiegt und sonst bei # jedem `swift test` in FlixyKit mitgezogen würde. FlixyVLC: path: Packages/FlixyVLC targets: Flixy: type: application platform: iOS # Ausdrücklich aufgeschrieben, statt Xcode raten zu lassen. # # Xcode legt für jedes Ziel von selbst ein Schema an — aber im # Benutzerordner, und `xcodegen generate` räumt den mit weg. Danach # findet `xcodebuild` kein Schema mehr und kann die Pakete nicht # auflösen. Hier steht es im Projekt und überlebt jedes Neuerzeugen. scheme: testTargets: - FlixyUITests sources: # Das Icon ist ein Bündel, also technisch ein Ordner. Ohne diesen # Ausschluss läuft XcodeGen hinein und trägt icon.json und play.svg # einzeln ein — dann fehlt das Icon, ohne dass irgendwo ein Fehler # auftaucht. # # Die Info.plist des jeweils anderen Ziels muss ebenfalls hinaus. # XcodeGen nimmt nur die eigene automatisch heraus; die fremde landet # als gewöhnliche Ressource unverarbeitet im Bündel — mitsamt dem # wörtlichen $(PRODUCT_BUNDLE_IDENTIFIER). Beim Installieren liest das # Gerät dann diese statt der richtigen und lehnt die App als „not a # valid bundle" ab. - path: Flixy excludes: - "AppIcon.icon" - "Info-macOS.plist" - "Flixy-macCatalyst.entitlements" - path: Flixy/AppIcon.icon type: file dependencies: - target: DownloadWidget # Die neutrale Grundschicht. Ausdrücklich genannt, obwohl sie über # PlexKit ohnehin im Baum hängt: die App soll sie direkt benutzen und # nicht davon abhängen, dass ein bestimmter Server sie mitschleppt. - package: FlixyKit product: MediaKit - package: FlixyKit product: PlexKit # Der zweite Server. Steht neben PlexKit, nicht darin: die beiden teilen # die neutrale Schicht und sonst nichts. - package: FlixyKit product: JellyfinKit - package: FlixyKit product: FlixyDesign - package: FlixyKit product: FlixyPlayback - package: FlixyKit product: FlixyDownloads - package: FlixyVLC product: FlixyVLC settings: base: PRODUCT_BUNDLE_IDENTIFIER: com.scarriffleservices.flixy PRODUCT_NAME: Flixy # Verweist auf AppIcon.icon. Der frühere leere AppIcon.appiconset im # Asset-Katalog ist entfernt — zwei Dinge namens AppIcon, und Xcode # nimmt das falsche. ASSETCATALOG_COMPILER_APPICON_NAME: AppIcon # iPhone und iPad aus demselben Target. TARGETED_DEVICE_FAMILY: "1,2" CODE_SIGN_STYLE: Automatic info: path: Flixy/Info.plist properties: CFBundleDisplayName: Flixy UILaunchScreen: UIColorName: LaunchBackground # Der harte Schalter für „nur dunkel". Eine Ansicht mit # .preferredColorScheme(.dark) allein reicht nicht: Systemdialoge, # Statusleiste und Tastatur richten sich danach nicht. UIUserInterfaceStyle: Dark # Alle drei bleiben eingetragen: die Info.plist sagt, was die App # grundsätzlich kann. Was davon gerade gilt, entscheidet zur Laufzeit # OrientationLock über den App-Delegaten — Hochformat beim Blättern, # Querformat im Player. UISupportedInterfaceOrientations: - UIInterfaceOrientationPortrait - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight UISupportedInterfaceOrientations~ipad: - UIInterfaceOrientationPortrait - UIInterfaceOrientationPortraitUpsideDown - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight # Ohne diesen Modus hält iOS die Wiedergabe an, sobald die App in den # Hintergrund geht — und Bild-in-Bild gäbe es gar nicht. UIBackgroundModes: - audio # Das Schema, über das Plex nach der Anmeldung zurückschickt. Ohne # diesen Eintrag kennt iOS es nicht, und ASWebAuthenticationSession # käme nie zurück — das Anmeldefenster bliebe offen stehen. CFBundleURLTypes: - CFBundleURLName: com.scarriffleservices.flixy.auth CFBundleURLSchemes: - com.scarriffleservices.flixy # Die Ausfuhr-Erklärung zur Verschlüsselung. # # `false` heißt: die App nutzt ausschließlich Verschlüsselung, die # unter die Ausnahmeregelung fällt. Das trifft hier zu — HTTPS über # URLSession und der Schlüsselbund für die Tokens, beides vom # Betriebssystem gestellt. Eigene Algorithmen gibt es keine. # # Ohne diesen Eintrag fragt App Store Connect bei JEDEM Build erneut # („Missing Compliance"), und der Build lässt sich bis dahin nicht # verteilen. # # Zu beachten, falls sich das ändert: VLCKit ist ein fremdes Binary # und bringt eigene Netzwerkbibliotheken mit. Solange nur Dateien vom # eigenen Server abgespielt werden, bleibt es bei Standardverfahren. # Käme irgendwann etwas mit eigener Verschlüsselung dazu — DRM etwa —, # gehört dieser Wert überprüft. ITSAppUsesNonExemptEncryption: false # Ohne diesen Schlüssel lehnt ActivityKit jede Anfrage ab — und # zwar wortlos, was die Suche nach dem Grund unangenehm macht. NSSupportsLiveActivities: true NSAppTransportSecurity: # Plex-Server im Heimnetz laufen überwiegend auf blankem HTTP an # Port 32400. Diese Ausnahme erlaubt genau das, ohne die # Transportsicherheit für das offene Netz abzuschalten. NSAllowsLocalNetworking: true # Seit iOS 14 verlangt jeder Zugriff auf Adressen im eigenen Netz eine # Freigabe. Fehlt der Text, verweigert das System sie kommentarlos und # die Serversuche findet dauerhaft nichts. NSLocalNetworkUsageDescription: >- Flixy benötigt Zugriff auf das lokale Netzwerk, um deinen Plex-Server zu finden und Medien direkt von ihm zu laden. # 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, dasselbe Aussehen. # # 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 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: iOS scheme: {} sources: # Siehe Flixy: umgekehrt genauso, sonst trägt das Mac-Bündel die # Info.plist des iPhones in seinen Ressourcen. - path: Flixy excludes: - "AppIcon.icon" - "Info.plist" - path: Flixy/AppIcon.icon type: file dependencies: - package: FlixyKit product: MediaKit - package: FlixyKit product: PlexKit - package: FlixyKit product: JellyfinKit - package: FlixyKit product: FlixyDesign - package: FlixyKit product: FlixyPlayback - package: FlixyKit 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 # **Eine eigene Kennung, nicht dieselbe wie die iPhone-App.** # # Hier stand `DERIVE_MACCATALYST_PRODUCT_BUNDLE_IDENTIFIER: NO`, und # damit trugen beide Programme `com.scarriffleservices.flixy`. Auf # einem Rechner, auf dem die iPad-Fassung installiert ist — und auf # einem Apple-Silicon-Mac ist sie das leicht — gibt es die Kennung # dann zweimal. Das System entscheidet sich für **eines** davon, und # nicht unbedingt für das eben gebaute: der Start sieht aus, als # geschähe nichts. # # Voreingestellt ist bei Apple `YES`, und zwar genau deshalb. Daraus # wird `maccatalyst.com.scarriffleservices.flixy`. DERIVE_MACCATALYST_PRODUCT_BUNDLE_IDENTIFIER: YES PRODUCT_BUNDLE_IDENTIFIER: com.scarriffleservices.flixy PRODUCT_NAME: Flixy ASSETCATALOG_COMPILER_APPICON_NAME: AppIcon TARGETED_DEVICE_FAMILY: "2" # Richtig signiert, wie die iPhone-App auch. # # Vorher war es eine Ad-hoc-Signatur ohne Team, damit ein Bau zum # Ansehen nicht nach dem Schlüsselbund fragt. Nur legt Flixy den # Server-Token im Schlüsselbund ab, und einem Sandbox-Programm ohne # `application-identifier` verweigert der das — die Anmeldung hielte # keinen Neustart aus. CODE_SIGN_STYLE: Automatic ENABLE_HARDENED_RUNTIME: NO CODE_SIGN_ENTITLEMENTS: Flixy/Flixy-macCatalyst.entitlements 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 CFBundleURLTypes: - CFBundleURLName: com.scarriffleservices.flixy.auth CFBundleURLSchemes: - com.scarriffleservices.flixy ITSAppUsesNonExemptEncryption: false NSAppTransportSecurity: NSAllowsLocalNetworking: true NSLocalNetworkUsageDescription: >- Flixy benötigt Zugriff auf das lokale Netzwerk, um deinen Medienserver zu finden und Filme direkt von ihm zu laden. # Nur zum Hinsehen: fährt die App mit der Attrappe in einen bestimmten # Zustand und hält sie dort an, damit von außen fotografiert werden kann. # Kein Teil der App, wird nie mitgeliefert. FlixyUITests: type: bundle.ui-testing platform: iOS sources: - FlixyUITests dependencies: - target: Flixy settings: base: PRODUCT_BUNDLE_IDENTIFIER: com.scarriffleservices.flixy.uitests TEST_TARGET_NAME: Flixy TARGETED_DEVICE_FAMILY: "1,2" CODE_SIGN_STYLE: Automatic GENERATE_INFOPLIST_FILE: YES DownloadWidget: type: app-extension platform: iOS sources: - path: DownloadWidget dependencies: - package: FlixyKit product: FlixyDownloads - package: FlixyKit product: FlixyDesign settings: base: PRODUCT_BUNDLE_IDENTIFIER: com.scarriffleservices.flixy.downloadwidget PRODUCT_NAME: DownloadWidget CODE_SIGN_STYLE: Automatic SKIP_INSTALL: YES # Von XcodeGen erzeugt statt von Hand geschrieben. Eine eigene Datei ohne # CFBundleIdentifier führt zu einer Erweiterung ganz ohne Kennung — und # der Fehler lautet dann „not prefixed with the parent app's bundle # identifier", was auf eine falsche Fährte führt. info: path: DownloadWidget/Info.plist properties: CFBundleDisplayName: Flixy Downloads NSExtension: NSExtensionPointIdentifier: com.apple.widgetkit-extension