name: Flixy options: bundleIdPrefix: com.scarriffleservices deploymentTarget: iOS: "26.0" macOS: "26.0" tvOS: "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. # - path: Flixy excludes: - "AppIcon.icon" - 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 Fassung für den Fernseher. # # **Eigene Ansichten, geteilte Modelle.** Die Quellenpfade sind die ganze # Aussage dieses Blocks: `FlixyTV/` gehört nur hierher, `Flixy/Session/` # gehört beiden. Keine Datei muss dafür umziehen — XcodeGen nimmt Pfade je # Ziel, und die iOS-Fassung sieht von der ganzen Sache nichts. FlixyTV: type: application platform: tvOS # Aus demselben Grund ausgeschrieben wie bei Flixy — siehe dort. scheme: {} sources: # Die eigenen Ansichten. - path: FlixyTV # Die Modelle. - path: Flixy/Session excludes: # Ein Fernseher dreht sich nicht. - "OrientationLock.swift" # Downloads gibt es hier nicht. - "DownloadService.swift" - "DownloadRefiller.swift" # Kommt mit dem Player in Schritt sieben. Solange es ihn nicht gibt, # hätte die Anmeldung beim System nichts anzumelden. - "NowPlaying.swift" # Reines Modell trotz des Ordnernamens: LoadState, ErrorText und # MediaRoute liegen zusammen in einer Datei. - path: Flixy/Views/LoadState.swift type: file - path: Flixy/Branding.swift type: file # Die Texte. Dieselben Schlüssel, dieselben Übersetzungen. - path: Flixy/Resources/Localizable.xcstrings type: file dependencies: - package: FlixyKit product: MediaKit # Mitgenommen, obwohl Plex in Fassung 1 nicht angeboten wird: # FlixySession kennt PlexResource und PlexBackend in seiner # Zustandsmaschine. Das Paket mitzunehmen ist billiger, als die Sitzung # zu spalten — PlexClientIdentity benutzt nur UIDevice, und das gibt es # auf tvOS. - package: FlixyKit product: PlexKit - package: FlixyKit product: JellyfinKit - package: FlixyKit product: FlixyDesign - package: FlixyKit product: FlixyPlayback settings: base: PRODUCT_BUNDLE_IDENTIFIER: com.scarriffleservices.flixy.tv PRODUCT_NAME: Flixy # Nur Apple TV. TARGETED_DEVICE_FAMILY: "3" # Kein AppIcon.icon: Icon Composer deckt iOS, macOS und watchOS ab, # tvOS nicht. Der Name zeigt auf die Brand-Assets-Gruppe im Katalog, # und der Katalog liegt unter FlixyTV/Resources. ASSETCATALOG_COMPILER_APPICON_NAME: "App Icon & Top Shelf Image" CODE_SIGN_STYLE: Automatic info: path: FlixyTV/Info.plist properties: CFBundleDisplayName: Flixy UIUserInterfaceStyle: Dark ITSAppUsesNonExemptEncryption: false # Was hier **nicht** steht, und warum: # # UILaunchScreen — tvOS hat kein Startbild dieser Art. # UISupportedInterfaceOrientations — ein Fernseher dreht sich nicht. # NSSupportsLiveActivities — ActivityKit fehlt im tvOS-SDK. # CFBundleURLTypes — das Schema ist für die Plex-Rückkehr. # UIBackgroundModes: audio — ein Apple TV schickt keine App in den # Hintergrund, aus dem sie weiterspielen müsste. NSAppTransportSecurity: NSAllowsLocalNetworking: true NSLocalNetworkUsageDescription: >- Flixy benötigt Zugriff auf das lokale Netzwerk, um deinen Jellyfin-Server zu erreichen. # 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 # 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. 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