macOS: die App läuft jetzt auf dem Mac

Und dein Argument dafür war das beste: auf dem Mac kann ich selbst hinsehen.
Kein Simulator-Tunnel, der mitten im Prüfen abstürzt — `screencapture` auf das
Fenster der App, und zwar nur auf ihres, nicht auf den Bildschirm.

**Ein eigenes Ziel, nicht ein gemeinsames.** Die Info.plist der iOS-App ist
voller iOS-Angaben: Startbildschirm, erlaubte Ausrichtungen, Live Activities.
Die alle bedingt zu machen hieße, dass jede spätere Änderung an der iOS-Seite
über eine Stelle geht, die auch den Mac betrifft. Zwei Ziele sind ein paar
Zeilen mehr und eine Sorge weniger.

**Was den Unterschied ausmacht, steht an einer Stelle.** Ein neuer
`PlatformShims` in FlixyDesign übersetzt, was auf beiden Seiten verschieden
heißt: schmale Titelzeile, halbhohes Blatt, Eingabefelder ohne
Großschreibung, die Plätze in der Werkzeugleiste, die Zwischenablage. Zwanzig
Ansichten benutzen ihn, statt zwanzigmal `#if os(iOS)` zu tragen — sonst
wandert die Fallunterscheidung in jede neue Datei und wird beim übernächsten
Bildschirm vergessen.

Wirklich verschieden sind nur fünf Stellen: die Bildfläche (`UIView` gegen
`NSView`), der AirPlay-Knopf, die Ausrichtungssperre (auf dem Mac gibt es
nichts zu sperren), der App-Delegat für Hintergrund-Downloads und das
Anmeldefenster, das ein anderes Fenster als Anker braucht.

**Das Karussell blättert jetzt mit einem einrastenden Streifen** statt mit
`TabView(.page)` — den Seitenstil gibt es auf dem Mac nicht. Das ist nebenbei
die bessere Lösung: das verschachtelte TabView hatte die Eigenschaft, beim
Wechsel kurz zwei Seiten gleichzeitig zu zeigen.

**Was auf dem Mac fehlt und warum:** VLC. Das Binärpaket ist auf iOS
festgelegt; sein xcframework enthält zwar Mac-Teile, aber das ist eine eigene
Runde. Solange fällt die Wiedergabe dort auf den Systemplayer zurück — MKV und
DTS gehen also noch nicht. Live Activities gibt es auf dem Mac nicht, Bild-in-
Bild startet von Hand statt beim Verlassen der App.

Gesehen: die App startet, der Anmeldebildschirm steht, beide Wege sind da.
Angemeldet habe ich mich auf dem Mac **nicht** — das ginge nur, indem ich
einen Token in deinen Schlüsselbund schreibe, und dann fragt macOS dich beim
ersten Zugriff nach dem Passwort. Das machst du mit einem Klick selbst.

iOS baut unverändert, 263 Tests grün.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Scarriffle
2026-09-13 15:45:13 +02:00
co-authored by Claude Opus 5
parent 21c5a8b46b
commit d54954b9c2
33 changed files with 480 additions and 111 deletions
@@ -0,0 +1,110 @@
import SwiftUI
#if canImport(UIKit)
import UIKit
#else
import AppKit
#endif
/// Was auf iPhone und Mac verschieden heißt — an einer Stelle.
///
/// Nicht jede Ansicht soll `#if os(iOS)` tragen. Ein Formular, das auf beiden
/// Plattformen dasselbe meint, soll auf beiden gleich aussehen; wo die
/// Systeme verschiedene Namen dafür haben, steht der Unterschied hier und
/// nirgends sonst. Sonst wandert er in zwanzig Dateien und wird beim
/// nächsten Bildschirm vergessen.
extension View {
/// Eine schmale Titelzeile — auf dem Mac gibt es sie nicht.
public func flixyInlineTitle() -> some View {
#if os(iOS)
navigationBarTitleDisplayMode(.inline)
#else
self
#endif
}
/// Ein Blatt, das die halbe Höhe einnimmt.
///
/// Auf dem Mac ist ein Blatt ein Fenster: dort zählt keine Rastung,
/// sondern eine vernünftige Mindestgröße.
public func flixyMediumSheet() -> some View {
#if os(iOS)
presentationDetents([.medium])
#else
frame(minWidth: 420, minHeight: 460)
#endif
}
/// Dasselbe, aber auf Wunsch bis zur vollen Höhe aufziehbar.
public func flixyResizableSheet() -> some View {
#if os(iOS)
presentationDetents([.medium, .large])
#else
frame(minWidth: 460, minHeight: 520)
#endif
}
/// Eingabefelder für Adressen und Namen: keine Großschreibung, keine
/// Korrektur — auf dem Mac gibt es beides ohnehin nicht als Tastatur.
public func flixyPlainEntry(isAddress: Bool = false) -> some View {
#if os(iOS)
self
.keyboardType(isAddress ? .URL : .default)
.textInputAutocapitalization(.never)
.autocorrectionDisabled()
#else
autocorrectionDisabled()
#endif
}
}
extension View {
/// Keine eigene Fläche hinter der Titelzeile.
///
/// Auf der Startseite liegt darunter der Aufmacher — eine weichgezeichnete
/// Leiste verschleierte die Hälfte davon. Auf dem Mac gibt es die Leiste in
/// dieser Form nicht.
public func flixyClearToolbarBackground() -> some View {
#if os(iOS)
self
.toolbarBackground(.hidden, for: .navigationBar)
.toolbarColorScheme(.dark, for: .navigationBar)
#else
self
#endif
}
}
/// Etwas in die Zwischenablage legen.
///
/// UIKit und AppKit heißen verschieden und meinen dasselbe; die Diagnose soll
/// deswegen nicht mit `#if` beginnen.
public enum FlixyClipboard {
public static func copy(_ text: String) {
#if canImport(UIKit)
UIPasteboard.general.string = text
#else
NSPasteboard.general.clearContents()
NSPasteboard.general.setString(text, forType: .string)
#endif
}
}
extension ToolbarItemPlacement {
/// Rechts in der Titelzeile.
public static var flixyTrailing: ToolbarItemPlacement {
#if os(iOS)
.topBarTrailing
#else
.primaryAction
#endif
}
/// Links in der Titelzeile.
public static var flixyLeading: ToolbarItemPlacement {
#if os(iOS)
.topBarLeading
#else
.navigation
#endif
}
}