`DERIVE_MACCATALYST_PRODUCT_BUNDLE_IDENTIFIER: NO` gab der Catalyst-Fassung dieselbe Bündelkennung wie der iPhone-App: `com.scarriffleservices.flixy`. Auf einem Apple-Silicon-Mac, auf dem die iPad-Fassung installiert ist, gibt es diese Kennung damit zweimal — und das System entscheidet sich für eine davon, nicht unbedingt für die eben gebaute. Der Start sah aus, als geschähe nichts. `lsregister` zeigte sechs Einträge unter derselben Kennung. Apples Voreinstellung ist `YES`, und zwar genau deshalb. Daraus wird `maccatalyst.com.scarriffleservices.flixy`. Dazu richtig signiert statt ad hoc: Flixy legt den Server-Token im Schlüsselbund ab, und dem verweigert er sich bei einem Sandbox-Programm ohne Team. Und die Schemata stehen jetzt im Projekt. Xcode legte sie im Benutzerordner an, wo `xcodegen generate` sie mitnahm — danach fand `xcodebuild` keines mehr und konnte die Pakete nicht auflösen. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
311 lines
12 KiB
YAML
311 lines
12 KiB
YAML
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
|