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. /// Auf was für einem Gerät läuft das hier gerade? public enum FlixyPlatform { /// Läuft die App auf einem Mac? /// /// **Zwei Wege führen dorthin, und für den Übersetzer sehen sie /// verschieden aus.** Catalyst ist ein eigener Bau und meldet sich als /// `targetEnvironment(macCatalyst)`. „Für iPad angepasst" ist dagegen /// buchstäblich der iOS-Bau, der auf Apple Silicon startet — dort ist /// dieselbe Abfrage schlicht falsch. /// /// Wer nur die erste Hälfte prüft, schreibt Code für den Mac, der auf dem /// Mac nicht läuft: übersetzt sauber, ist aber genau dort abgeschaltet, /// wo er gebraucht wird. Deshalb hier beide Wege, an einer Stelle. public static let isMac: Bool = { #if targetEnvironment(macCatalyst) true #elseif os(iOS) ProcessInfo.processInfo.isiOSAppOnMac #else true #endif }() } 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 Sheet, das die halbe Höhe einnimmt. /// /// Auf dem Mac ist ein Sheet ein Fenster: dort zählt keine Rastung, /// sondern eine vernünftige Mindestgröße. public func flixyMediumSheet() -> some View { // **Zur Laufzeit, nicht beim Übersetzen.** Der `#else`-Zweig für // macOS griff nie: auf dem Mac läuft der iOS-Bau, und damit bekam ein // grosses Fenster eine Sheet-Kante in iPhone-Höhe — ein schmaler // Streifen, der unten im Nichts klebt. presentationDetents(FlixyPlatform.isMac ? [.large] : [.medium]) } /// Dasselbe, aber auf Wunsch bis zur vollen Höhe aufziehbar. public func flixyResizableSheet() -> some View { // Siehe oben. Auf dem Mac gibt es kein „halb aufgezogen": ein Fenster // hat die Höhe, die es hat, und eine Liste soll sie nutzen. presentationDetents(FlixyPlatform.isMac ? [.large] : [.medium, .large]) } /// Ein Formular, das auf beiden Seiten gleich aussieht. /// /// Auf dem Mac setzt SwiftUI sonst den Spalten-Stil: Beschriftungen rechts /// ausgerichtet, keine abgesetzten Abschnitte, alles eng. Der gruppierte /// Stil ist derselbe, den iOS ohnehin nimmt — und der Grund, warum die /// Einstellungen auf dem Mac wie ein Systemdialog aus einem anderen /// Jahrzehnt aussahen. public func flixyForm() -> some View { #if os(macOS) formStyle(.grouped) #else self #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 } }