Neues natives macOS-Settings-Fenster mit Sprache, Auto-Update-Check,
Farbschema (Standard/Kontrastreich), echter Textgrößen-Skalierung,
Bedienelement-Größe und LAN-Scanner-Refreshraten/Sparkline-Einstellungen.
- AppPreferences.swift: zentrale AppStorage-Keys, ColorTheme/AppTextSize/
UIDensity
- SettingsView.swift: 3-Tab-Settings-Scene
- .environment(\.dynamicTypeSize) erwies sich auf macOS als wirkungslos
(per ImageRenderer-Snapshot bewiesen) — durch eigenen appFontScale-
Mechanismus ersetzt, ~110 .font(...)-Aufrufe app-weit umgestellt
- Farbschema auf Wunsch auch auf Experte-Tab-Sidebar ausgeweitet
- Docs aktualisiert: README/HANDOFF/CHATLOG/Manual.md+PDF, found.md
Live bestätigt nach mehreren Nachbesserungsrunden ("passt, lassen wir so").
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
64 lines
3.5 KiB
Swift
64 lines
3.5 KiB
Swift
import SwiftUI
|
|
|
|
@main
|
|
struct RouterOSAssistantApp: App {
|
|
@StateObject private var connectionService = ConnectionService()
|
|
/// Manual language override — independent of the system locale, per the user's explicit
|
|
/// request for an in-app toggle button. `.environment(\.locale, ...)` does NOT make
|
|
/// `Text(LocalizedStringKey)` re-resolve against Localizable.xcstrings at runtime (confirmed
|
|
/// live: toggling had no visible effect), so views read this same AppStorage key directly and
|
|
/// translate via `L10n.t(_:_:)` instead.
|
|
@AppStorage("appLanguage") private var appLanguage: String = "de"
|
|
@AppStorage(AppPreferences.textSizeKey) private var textSizeRaw: String = AppTextSize.standard.rawValue
|
|
@AppStorage(AppPreferences.uiDensityKey) private var uiDensityRaw: String = UIDensity.standard.rawValue
|
|
|
|
init() {
|
|
AppPreferences.registerDefaults()
|
|
}
|
|
|
|
var body: some Scene {
|
|
WindowGroup {
|
|
TabView {
|
|
ConnectView(connectionService: connectionService)
|
|
.tabItem { Label(L10n.t("Verbinden", appLanguage), systemImage: "network") }
|
|
SetupView(connectionService: connectionService)
|
|
.tabItem { Label(L10n.t("Einrichten", appLanguage), systemImage: "checklist") }
|
|
OverviewView(connectionService: connectionService)
|
|
.tabItem { Label(L10n.t("Übersicht", appLanguage), systemImage: "point.3.connected.trianglepath.dotted") }
|
|
DevicesView(connectionService: connectionService)
|
|
.tabItem { Label(L10n.t("LAN-Scanner", appLanguage), systemImage: "laptopcomputer.and.iphone") }
|
|
ExpertView(connectionService: connectionService)
|
|
.tabItem { Label(L10n.t("Experte", appLanguage), systemImage: "wrench.and.screwdriver") }
|
|
BackupListView(connectionService: connectionService)
|
|
.tabItem { Label(L10n.t("Sicherungen", appLanguage), systemImage: "clock.arrow.circlepath") }
|
|
}
|
|
.toolbar {
|
|
ToolbarItem {
|
|
Button {
|
|
appLanguage = (appLanguage == "de") ? "en" : "de"
|
|
} label: {
|
|
// Flag of the language a tap switches TO — matches the "DE"/"EN" text
|
|
// labels this replaces, which showed the same "switch to" target.
|
|
Text(appLanguage == "de" ? "🇬🇧" : "🇩🇪")
|
|
}
|
|
.help(appLanguage == "de" ? "Switch to English" : "Auf Deutsch umschalten")
|
|
}
|
|
}
|
|
.controlSize((UIDensity(rawValue: uiDensityRaw) ?? .standard).controlSize)
|
|
.environment(\.appFontScale, (AppTextSize(rawValue: textSizeRaw) ?? .standard).scale)
|
|
// Fallback for every `Text`/`TextField`/`Label` that has no explicit `.font(...)` of
|
|
// its own (confirmed live: the Experte tab's whole sidebar list and every Parameter/
|
|
// Wert `TextField` have none — `.appFont(...)` only touches call sites that already
|
|
// had a `.font(...)` to replace, so unstyled text stayed fixed-size). `.environment
|
|
// (\.font, ...)` only ever supplies a *default*: anywhere `.appFont(...)` already sets
|
|
// an explicit font, that still wins.
|
|
.environment(\.font, .system(size: 13 * ((AppTextSize(rawValue: textSizeRaw) ?? .standard).scale)))
|
|
}
|
|
.environment(\.locale, Locale(identifier: appLanguage))
|
|
|
|
Settings {
|
|
SettingsView()
|
|
}
|
|
}
|
|
}
|