From c74eca2913195e13b5935b04b69c6784f0068e84 Mon Sep 17 00:00:00 2001 From: samuelzielke Date: Sun, 13 Sep 2026 02:22:33 +0200 Subject: [PATCH] Konzept, Projektdefinition und Bildmarke --- README.md | 226 +++++++++++++++++++++++++++++++++++++++++++++++- assets/icon.svg | 11 +++ project.yml | 104 ++++++++++++++++++++++ 3 files changed, 340 insertions(+), 1 deletion(-) create mode 100644 assets/icon.svg create mode 100644 project.yml diff --git a/README.md b/README.md index 09e1e6d..6eaf412 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,226 @@ -# drop.two +
+ drop.two +

drop.two

+

9:16 rein. 9:16 und 4:5 raus.

+
+--- + +## Warum + +Alle Videos werden im Format 9:16 geschnitten. Nach der Freigabe müssen sie zusätzlich als 4:5 abgelegt werden. Das Framing wird beim Schnitt bereits so angelegt, dass der 4:5-Ausschnitt funktioniert — es braucht also keine zweite Timeline, sondern nur einen sauberen, mittigen Beschnitt des fertigen Masters. + +Bisher passiert das über ein selbstgebautes Python-CLI. `drop.two` macht daraus ein Werkzeug, das auch Kolleginnen und Kollegen ohne Terminal benutzen können: Dateien reinziehen, Ziel prüfen, fertig. + +## Was die App macht + +1. Eine oder mehrere 9:16-Dateien werden ausgewählt oder per Drag & Drop übergeben. +2. Aus dem Dateinamen wird das Projekt gelesen. +3. Im Zielordner entsteht ein Unterordner mit dem Projektnamen. +4. Dort landen beide Fassungen: das unveränderte 9:16-Original und die neu gerenderte 4:5-Version. + +Kein Preset-Dschungel, keine Timeline, kein Export-Dialog. + +## Namenskonvention + +``` +[Projekt]-[Format]-[Version]-[Sprache].[ext] +``` + +Beispiel: + +``` +SOMOS-9x16-v3-DE.mp4 → SOMOS/SOMOS-9x16-v3-DE.mp4 + SOMOS/SOMOS-4x5-v3-DE.mp4 +``` + +**Parsing-Regel:** Es wird **von rechts** gelesen. Die letzten drei Segmente sind Sprache, Version und Format; alles davor ist der Projektname. Nur so bleiben Projektnamen mit eigenem Bindestrich intakt: + +``` +Somos-Pendant-9x16-v3-DE.mp4 +└──── Projekt ────┘ └Fmt┘└Ver┘└Spr┘ +``` + +Für die Zielversion wird ausschließlich das Format-Segment ersetzt: `9x16` → `4x5`. Alle anderen Segmente bleiben zeichengleich erhalten. + +**Abbruchbedingungen** — die App verarbeitet nicht und meldet es sichtbar: + +- Dateiname entspricht nicht dem Schema (weniger als vier Segmente) +- Format-Segment ist nicht `9x16` +- Quelldatei hat kein 9:16-Seitenverhältnis +- Zieldatei existiert bereits (überschreiben nur nach Rückfrage) + +## Crop-Logik + +Der 4:5-Ausschnitt behält die **volle Breite** und beschneidet oben und unten: + +``` +Breite bleibt unverändert +Höhe = Breite × 5 ÷ 4 (auf gerade Zahl gerundet) +Anker vertikal zentriert (Offset später konfigurierbar) +``` + +| Quelle | Ziel | +|---|---| +| 1080 × 1920 | 1080 × 1350 | +| 2160 × 3840 | 2160 × 2700 | + +**Codec-Verhalten:** Der Quell-Codec wird erkannt und passend ausgespielt — ProRes bleibt ProRes, H.264 bleibt H.264 mit vergleichbarer Bitrate. Die Audiospur läuft per Passthrough durch, ohne Neukodierung. Framerate, Farbraum und Dauer bleiben unangetastet. + +## Funktionsumfang + +**MVP** + +- [ ] Dateiauswahl und Drag & Drop +- [ ] Einstellbarer Quellordner (Dialog öffnet direkt dort) +- [ ] Einstellbarer Zielordner, Projekt-Unterordner wird automatisch angelegt +- [ ] Dateiauswahl vorsortiert nach *zuletzt geändert* +- [ ] Fortschrittsanzeige pro Datei und gesamt +- [ ] Fehlerliste statt stiller Abbrüche + +**Danach** + +- [ ] Review-Ansicht: 9:16-Master mit eingeblendetem 4:5-Rahmen zur Framing-Kontrolle, scrubbar +- [ ] Menu-Bar-Betrieb mit Drop-Target +- [ ] Vertikaler Crop-Offset pro Datei justierbar +- [ ] In-App-Updates über Sparkle +- [ ] Batch-Verlauf der letzten Durchläufe + +## Tech-Stack + +**Swift + SwiftUI**, macOS 13+. + +| Baustein | Lösung | +|---|---| +| Oberfläche | SwiftUI, `MenuBarExtra` für den Hintergrundbetrieb | +| Video | **AVFoundation** — hardwarebeschleunigt über VideoToolbox | +| Review-Player | `AVPlayer` mit Overlay | +| Updates | **Sparkle 2** gegen `appcast.xml` auf eigenem Server | +| Einstellungen | `@AppStorage` + Security-Scoped Bookmarks für Ordnerzugriff | +| Projektdatei | **XcodeGen** (`project.yml`) — textbasiert, merge-freundlich | +| Paket | Signiertes `.dmg`, ca. 5 MB | + +**Warum kein ffmpeg:** Der Beschnitt ist rein geometrisch. AVFoundation erledigt ihn nativ über eine `AVMutableVideoComposition`. Das spart rund 80 MB Bundle-Größe, die GPL-Frage und ein mitzulieferndes Binary. + +**Warum nicht Python:** py2app- und PyInstaller-Bundles sind fragil, starten träge, wiegen ein Vielfaches und machen Code-Signing sowie Notarisierung unnötig schwer. Für ein Werkzeug, das Kollegen installieren sollen, ist das der falsche Unterbau. + +## Architektur + +``` +DropTwoCore Framework, komplett UI-frei +├── FileNameParser zerlegt und baut Dateinamen +├── VideoInspector liest Dimension, Codec, Framerate, Dauer +├── CropEngine AVAsset → VideoComposition → Export +└── JobQueue async/await, 1–2 parallele Exports + +DropTwo App-Target +├── Settings Pfade, Bookmarks, Presets +├── DropZone Auswahl und Drag & Drop +├── ProgressView Fortschritt und Fehlerliste +└── ReviewSheet AVPlayer mit 4:5-Overlay + +droptwo-cli Kommandozeilen-Target gegen denselben Core +``` + +Der Kern kennt keine Oberfläche. Das hält ihn testbar und macht das CLI-Target zum ehrlichen Prüfstein: Was dort funktioniert, funktioniert in der App. + +## Projektstruktur + +``` +drop.two/ +├── project.yml XcodeGen-Konfiguration +├── Sources/ +│ ├── DropTwoCore/ +│ ├── DropTwo/ +│ └── DropTwoCLI/ +├── Tests/ +│ └── DropTwoCoreTests/ +├── assets/ +│ ├── icon.svg Bildmarke +│ └── icon-menubar.svg Template-Variante für die Menu-Bar +├── scripts/ +│ ├── build.sh +│ └── release.sh +└── docs/ +``` + +Die `.xcodeproj` wird **nicht** eingecheckt — sie entsteht aus `project.yml`. + +## Einrichtung + +**Voraussetzungen** + +- Xcode (vollständig, aus dem App Store) — wegen macOS-SDK, `xcodebuild` und `notarytool` +- Homebrew + +```bash +brew install xcodegen swiftformat +git clone https://git.samuelzielke.de/samuelzielke/drop.two.git +cd drop.two +xcodegen generate +open DropTwo.xcodeproj # nur bei Bedarf +``` + +**Arbeiten ohne Xcode-Oberfläche:** VS Code mit der offiziellen Swift-Extension (SourceKit-LSP) deckt Autovervollständigung, Fehleranzeige und Navigation ab. Gebaut wird per `xcodebuild`. Xcode selbst braucht es für SwiftUI-Previews, Zertifikate und Instruments. + +```bash +xcodebuild -scheme DropTwo -configuration Debug build +xcodebuild -scheme DropTwoCoreTests test +``` + +## Release + +Vor dem ersten Release einmalig einzurichten: + +1. **Apple Developer Program** (99 €/Jahr, Anmeldung als Einzelperson). Liefert das *Developer ID Application*-Zertifikat. Ohne Signatur und Notarisierung blockiert Gatekeeper die App bei allen anderen. +2. **Sparkle-Schlüsselpaar** per `generate_keys`. Der private Schlüssel bleibt im macOS-Schlüsselbund und **niemals im Repo**; der öffentliche wandert als `SUPublicEDKey` in die `Info.plist`. +3. **Team-ID** in `project.yml` unter `DEVELOPMENT_TEAM` eintragen. + +> **Den privaten Sparkle-Schlüssel sichern.** Geht er verloren, lassen sich bereits installierte Kopien nie wieder aktualisieren — alle müssten neu installieren. + +Ablauf pro Release: + +```bash +xcodebuild -scheme DropTwo -configuration Release archive … +codesign --deep --options runtime --sign "Developer ID Application: …" DropTwo.app +create-dmg … +xcrun notarytool submit drop.two-1.0.dmg --keychain-profile "notary" --wait +xcrun stapler staple drop.two-1.0.dmg +sign_update drop.two-1.0.dmg # Signatur in appcast.xml eintragen +``` + +DMG und `appcast.xml` landen anschließend auf dem eigenen Server. Der Code liegt auf Gitea, die Release-Artefakte nicht. + +## Umsetzungsreihenfolge + +Die Reihenfolge ist bewusst gewählt: + +1. `FileNameParser` samt Unit-Tests — inklusive Bindestrich-Kantenfällen +2. `VideoInspector` und `CropEngine` +3. `droptwo-cli` als Prüfstein, echte Datei durchjagen, **Ausgabequalität bewerten** +4. Erst danach die Oberfläche +5. Review-Ansicht +6. Signierung, Notarisierung, Sparkle + +Schritt 3 entscheidet über das Projekt. Liefert AVFoundation nicht die nötige Qualität, muss das am ersten Tag auffallen — nicht nachdem die halbe App steht. + +## Offene Punkte + +- Zielpfad-Schema bei mehreren Sprachen oder Versionen desselben Projekts +- Verhalten bei bereits vorhandenem Zielordner: ergänzen oder warnen +- Ob das 9:16-Original kopiert oder verschoben wird +- Bitrate-Strategie bei H.264: Quellbitrate übernehmen oder fester Qualitätsfaktor +- Vertikaler Offset — global, pro Projekt oder pro Datei + +## Gestaltung + +Bildmarke: ein 9:16-Rahmen, darin der 4:5-Ausschnitt in voller Breite und vertikal zentriert — exakt das, was die App tut. + +| | | +|---|---| +| Dark | `#0B0B0C` | +| Light | `#F5F5F4` | +| Gold | `#C8A96A` | +| Mid Gray | `#B8B5B0` | + +Gold ist der einzige Akzent und bleibt sparsam eingesetzt. \ No newline at end of file diff --git a/assets/icon.svg b/assets/icon.svg new file mode 100644 index 0000000..0aa61bb --- /dev/null +++ b/assets/icon.svg @@ -0,0 +1,11 @@ +AAAWgmp1bWIAAAAeanVtZGMycGEAEQAQgAAAqgA4m3EDYzJwYQAAABZcanVtYgAAAEdqdW1kYzJtYQARABCAAACqADibcQN1cm46YzJwYTpmYTc3ZDFiYS1mZjU2LTRmNTQtOGE0NS0xZmU4MjdlM2E5NTgAAAADl2p1bWIAAAApanVtZGMyYXMAEQAQgAAAqgA4m3EDYzJwYS5hc3NlcnRpb25zAAAAALxqdW1iAAAARGp1bWRjYm9yABEAEIAAAKoAOJtxE2MycGEuaW5ncmVkaWVudC52MwAAAAAYYzJzaJ6GgLCyKLQZLoiYLNUFpOgAAABwY2JvcqNpZGM6Zm9ybWF0bWltYWdlL3N2Zyt4bWxqaW5zdGFuY2VJRHgseG1wOmlpZDpjYTk1YmY0ZS1mNDNkLTRjMTUtOWI4Ny0zYjJmZTExNzFlMWVscmVsYXRpb25zaGlwaHBhcmVudE9mAAAB4mp1bWIAAABBanVtZGNib3IAEQAQgAAAqgA4m3ETYzJwYS5hY3Rpb25zLnYyAAAAABhjMnNoKc4ByRiAOkXte5HCY00GpwAAAZljYm9yomdhY3Rpb25zgqJmYWN0aW9ua2MycGEub3BlbmVkanBhcmFtZXRlcnOha2luZ3JlZGllbnRzgaJjdXJseC1zZWxmI2p1bWJmPWMycGEuYXNzZXJ0aW9ucy9jMnBhLmluZ3JlZGllbnQudjNkaGFzaFggSp6emf71yKGXU7pprU95TLtn2rMdhohy0iLsfV26mkWkZmFjdGlvbngdY29tLmFudGhyb3BpYy5jbGF1ZGUucHJvdmlkZWRqcGFyYW1ldGVyc6F4H2NvbS5hbnRocm9waWMub3JpZ2luLWNvbmZpZGVuY2VndW5rbm93bmtkZXNjcmlwdGlvbnhmQ2xhdWRlIHByb3ZpZGVkIHRoaXMgZmlsZSBhdCB0aGUgcmVxdWVzdCBvZiBhIHVzZXIgYW5kIG1heSBoYXZlIGNyZWF0ZWQgb3IgbW9kaWZpZWQgdGhlIGZpbGUgY29udGVudHMubXNvZnR3YXJlQWdlbnShZG5hbWVmQ2xhdWRlcmFsbEFjdGlvbnNJbmNsdWRlZPUAAADIanVtYgAAAEBqdW1kY2JvcgARABCAAACqADibcRNjMnBhLmhhc2guZGF0YQAAAAAYYzJzaFoegZ2WUOyobSH2rdQmRNoAAACAY2JvcqVjYWxnZnNoYTI1NmNwYWRNAAAAAAAAAAAAAAAAAGRoYXNoWCA1ZO6Mz24dA5YOuy+/75RHjY88jLYRxLu5pK+jj3t9zWRuYW1lbmp1bWJmIG1hbmlmZXN0amV4Y2x1c2lvbnOBomVzdGFydBi7Zmxlbmd0aBkeBAAAAj5qdW1iAAAAJ2p1bWRjMmNsABEAEIAAAKoAOJtxA2MycGEuY2xhaW0udjIAAAACD2Nib3KlY2FsZ2ZzaGEyNTZpc2lnbmF0dXJleE1zZWxmI2p1bWJmPS9jMnBhL3VybjpjMnBhOmZhNzdkMWJhLWZmNTYtNGY1NC04YTQ1LTFmZTgyN2UzYTk1OC9jMnBhLnNpZ25hdHVyZWppbnN0YW5jZUlEeCx4bXA6aWlkOmNmMThiYzY1LTAxZDUtNDYyMi1hNTkyLTkyZDZhNzc2ZjRmZXJjcmVhdGVkX2Fzc2VydGlvbnODomN1cmx4LXNlbGYjanVtYmY9YzJwYS5hc3NlcnRpb25zL2MycGEuaW5ncmVkaWVudC52M2RoYXNoWCBKnp6Z/vXIoZdTummtT3lMu2fasx2GiHLSIux9XbqaRaJjdXJseCpzZWxmI2p1bWJmPWMycGEuYXNzZXJ0aW9ucy9jMnBhLmFjdGlvbnMudjJkaGFzaFggfwYv+K+XT7N1oK8t51Fr6lTiNPGHMqrZ7b114HJzCy+iY3VybHgpc2VsZiNqdW1iZj1jMnBhLmFzc2VydGlvbnMvYzJwYS5oYXNoLmRhdGFkaGFzaFggMSa8dEHOrq45btcqwQ4fxpPAocRm9hu/6NzXBfjU2rB0Y2xhaW1fZ2VuZXJhdG9yX2luZm+jZG5hbWVvQW50aHJvcGljIEZpbGVzZ3ZlcnNpb25lMS4wLjBrc3BlY1ZlcnNpb25lMi40LjAAABA4anVtYgAAAChqdW1kYzJjcwARABCAAACqADibcQNjMnBhLnNpZ25hdHVyZQAAABAIY2JvctKEWQISogEmGCFZAgowggIGMIIBjaADAgECAhRA5aAK7sI50L64g/oGQgU9Z1UTADAKBggqhkjOPQQDAzBJMRcwFQYDVQQKEw5BbnRocm9waWMsIFBCQzEuMCwGA1UEAxMlQW50aHJvcGljIENvbnRlbnQgQ3JlZGVudGlhbHMgUm9vdCBDQTAeFw0yNjA4MDcxODQzNTZaFw0yODA4MDYxOTQzNTZaMEQxFzAVBgNVBAoTDkFudGhyb3BpYywgUEJDMSkwJwYDVQQDEyBBbnRocm9waWMgQ2xhdWRlIENvbnRlbnQgU2lnbmluZzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABJh6CmvLUBgFFNU0vUKlOVtE6djd17L5SuwX0LemFisBM3dkd/3cyjxFA3Qo5S46fX0/ihY0VZ7mfb9KF703t5OjWDBWMA4GA1UdDwEB/wQEAwIHgDAVBgNVHSUEDjAMBgorBgEEAYPoXgIBMAwGA1UdEwEB/wQCMAAwHwYDVR0jBBgwFoAUzlHiBIFOZFsj+OPEz5o+nMHXXMIwCgYIKoZIzj0EAwMDZwAwZAIwMXMdFJ4BetLLVY7ORuE9noqbbAZOZn/aArXyTwFAZfKrPzxF2vPoJNf1+UCdg1XGAjBwX1zd9WGqYkqmL5SFqw1QySjr1zJfpJM9+1rdDwSPLMOPOjKuiXjoU/pUUeG9RwmhY3BhZFkNngAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPZYQNt3yqPUui2/UeVHzcBOpPPixT/MZ6s5vqepYn2v1bT8/eACpW9rC/VqKjIdvhrG92Dld562Rqa+Kq/r0wOWbEU= + + + + + + + + + diff --git a/project.yml b/project.yml new file mode 100644 index 0000000..4acf267 --- /dev/null +++ b/project.yml @@ -0,0 +1,104 @@ +name: DropTwo + +options: + bundleIdPrefix: dev.zielke + createIntermediateGroups: true + deploymentTarget: + macOS: "13.0" + +settings: + base: + SWIFT_VERSION: "5.9" + MARKETING_VERSION: "0.1.0" + CURRENT_PROJECT_VERSION: "1" + # Ad-hoc-Signatur: laeuft lokal auf dem eigenen Rechner, braucht keine Team-ID. + # Fuer den ersten echten Release auf Manual + DEVELOPMENT_TEAM umstellen. + CODE_SIGN_STYLE: Automatic + CODE_SIGN_IDENTITY: "-" + configs: + Release: + ENABLE_HARDENED_RUNTIME: YES # Pflicht fuer die Notarisierung + +# Sparkle kommt erst in Schritt 6 dazu. Bis dahin auskommentiert -- +# das haelt fruehe Builds schnell und die Signierung unkompliziert. +# packages: +# Sparkle: +# url: https://github.com/sparkle-project/Sparkle +# from: "2.6.0" + +targets: + + # Kern ohne jede UI-Abhaengigkeit -- von App und CLI gemeinsam genutzt. + DropTwoCore: + type: framework + platform: macOS + sources: + - Sources/DropTwoCore + settings: + base: + PRODUCT_BUNDLE_IDENTIFIER: dev.zielke.droptwo.core + + DropTwo: + type: application + platform: macOS + sources: + - Sources/DropTwo + dependencies: + - target: DropTwoCore + # - package: Sparkle + settings: + base: + PRODUCT_BUNDLE_IDENTIFIER: dev.zielke.droptwo + PRODUCT_NAME: drop.two + ASSETCATALOG_COMPILER_APPICON_NAME: AppIcon + info: + path: Sources/DropTwo/Info.plist + properties: + CFBundleName: drop.two + CFBundleDisplayName: drop.two + LSMinimumSystemVersion: "13.0" + LSUIElement: false # true = reiner Menu-Bar-Betrieb ohne Dock-Icon + NSHumanReadableCopyright: "(c) Samuel Zielke" + # Sparkle-Schluessel und Feed-URL folgen in Schritt 6: + # SUFeedURL: https://.../droptwo/appcast.xml + # SUPublicEDKey: ... + # SUEnableAutomaticChecks: true + + # Pruefstein fuer den Kern: echte Datei durchjagen, bevor Oberflaeche entsteht. + droptwo-cli: + type: tool + platform: macOS + sources: + - Sources/DropTwoCLI + dependencies: + - target: DropTwoCore + settings: + base: + PRODUCT_NAME: droptwo + + DropTwoCoreTests: + type: bundle.unit-test + platform: macOS + sources: + - Tests/DropTwoCoreTests + dependencies: + - target: DropTwoCore + +schemes: + DropTwo: + build: + targets: + DropTwo: all + run: + config: Debug + test: + config: Debug + targets: + - DropTwoCoreTests + + droptwo-cli: + build: + targets: + droptwo-cli: all + run: + config: Debug \ No newline at end of file