pageta-native/Sources/Features/SettingsView.swift
Till JS 8d6fc1a666 i18n: pageta-native voll über PagetaStrings (Phase 4)
Alle UI-Strings der Feature-/App-Schicht ziehen aus mana/i18n
(Listen/Detail/Marker/Feed/Rückblick/Zusammenfassen/Settings/Account
+ Archiv/Bulk/Note-Sheet/Palette); Interpolation als generierte Funktionen.
Verwaisten-Check grün (0 hartkodierte UI-Strings). Onboarding bleibt
seine eigene SOT (mana/content/onboarding).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-09 16:06:55 +02:00

141 lines
3.1 KiB
Swift

#if os(macOS)
import ManaAuthUI
import ManaCore
import ManaLLMUI
import SwiftUI
/// macOS-Settings-Scene (`Settings { ... }` in `PagetaNativeApp`),
/// erreichbar über **⌘,** — der erwartete native Pattern für
/// App-Konfiguration auf dem Mac. Vier Sub-Tabs:
///
/// - **Konto**: Email-Status, Abmelden
/// - **Darstellung**: Light/Dark/Automatisch-Picker
/// - **Benachrichtigungen**: App-Icon-Badge
/// - **KI**: lokales LLM für Artikel-Zusammenfassung (geteilt mit
/// anderen mana-Apps via App-Group)
///
/// Auf iOS lebt die identische Konfig im normalen Konto-Tab
/// — `AccountTabView` ist dort der Settings-Hub.
struct SettingsView: View {
var body: some View {
TabView {
AccountSettingsPane()
.tabItem { Label("Konto", systemImage: "person.crop.circle") }
AppearanceSettingsPane()
.tabItem { Label("Darstellung", systemImage: "paintbrush") }
NotificationSettingsPane()
.tabItem { Label("Benachrichtigungen", systemImage: "bell") }
AISettingsPane()
.tabItem { Label("KI", systemImage: "sparkles") }
}
.frame(width: 520, height: 360)
}
}
private struct AISettingsPane: View {
var body: some View {
Form {
ManaLLMSettingsView(context: AccountTabView.llmContext)
}
.formStyle(.grouped)
.padding(20)
}
}
private struct AccountSettingsPane: View {
@Environment(AuthClient.self) private var auth
@Environment(ManaAuthGate.self) private var authGate
private var isSignedIn: Bool {
if case .signedIn = auth.status { return true }
return false
}
var body: some View {
Form {
Section {
if let email = auth.currentEmail {
LabeledContent("E-Mail", value: email)
} else {
Text(PagetaStrings.settingsNotSignedIn)
.foregroundStyle(.secondary)
}
}
Section {
if isSignedIn {
HStack {
Spacer()
Button("Abmelden", role: .destructive) {
Task {
await SpotlightIndex().clearAll()
await auth.signOut()
}
}
}
} else {
Button {
authGate.require(reason: "konto") {}
} label: {
Label(
PagetaStrings.settingsSignIn,
systemImage: "person.crop.circle.badge.checkmark"
)
}
}
}
}
.formStyle(.grouped)
.padding(20)
}
}
private struct AppearanceSettingsPane: View {
var body: some View {
Form {
PagetaAppearanceSection()
}
.formStyle(.grouped)
.padding(20)
}
}
private struct NotificationSettingsPane: View {
@AppStorage(BadgeManager.userDefaultsKey) private var badgeEnabled = false
var body: some View {
Form {
Section {
Toggle("App-Icon-Badge zeigen", isOn: $badgeEnabled)
.onChange(of: badgeEnabled) { _, enabled in
Task { await handleBadgeToggle(enabled: enabled) }
}
} footer: {
Text(
PagetaStrings.settingsBadgeHintMac
)
.font(.footnote)
.foregroundStyle(.secondary)
}
}
.formStyle(.grouped)
.padding(20)
}
private func handleBadgeToggle(enabled: Bool) async {
if enabled {
let granted = await BadgeManager.requestPermission()
if !granted {
badgeEnabled = false
}
} else {
await BadgeManager.setBadge(count: 0)
}
}
}
#endif