ManaFeedbackButton-Zeile im extra-Slot ersetzt durch die geteilte ManaFeedbackCard an fester Position via ManaAccountView.feedbackClient. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
112 lines
3.9 KiB
Swift
112 lines
3.9 KiB
Swift
import ManaAuthUI
|
|
import ManaCore
|
|
import ManaLLMUI
|
|
import ManaTokens
|
|
import SwiftUI
|
|
|
|
/// Konto-Tab — vereinheitlicht über das geteilte `ManaAccountView`
|
|
/// (E-Mail/Passwort ändern, 2FA, Konto löschen, Abmelden, Sign-In-CTA).
|
|
/// Pageta-spezifische Sektionen (Darstellung, Badge, lokale KI, Feedback,
|
|
/// Über) hängen im `extra`-Slot und sind — soft-auth — immer sichtbar.
|
|
struct AccountTabView: View {
|
|
@Environment(AuthClient.self) private var auth
|
|
@Environment(ManaAuthGate.self) private var authGate
|
|
|
|
@AppStorage(BadgeManager.userDefaultsKey) private var badgeEnabled = false
|
|
@AppStorage(ManaTheme.storageKey) private var variantRaw: String = ManaTheme.pagetaDefault
|
|
.rawValue
|
|
|
|
private var theme: ManaTheme { ManaTheme(rawValue: variantRaw) ?? .paper }
|
|
|
|
/// Kontext für die geteilten `ManaLLMUI`-Sections — Pageta-spezifisch.
|
|
/// Wird auch von der macOS-`SettingsView` konsumiert, deshalb static.
|
|
static let llmContext = ManaLLMContext(
|
|
useCaseShort: "Artikel-Zusammenfassung",
|
|
useCaseLong: "fasst Artikel auf Knopfdruck in zwei Sätze zusammen"
|
|
)
|
|
|
|
var body: some View {
|
|
NavigationStack {
|
|
ManaAccountView(
|
|
auth: auth,
|
|
config: .init(
|
|
changeEmailCallbackLink: URL(string: "https://pageta.com/auth/email-changed"),
|
|
signedOutMessage: "Marker, Notizen und dein Stapel funktionieren auch "
|
|
+ "ohne Konto — alles bleibt lokal auf diesem Gerät. Mit Anmeldung wird es "
|
|
+ "geräteübergreifend synchronisiert und gesichert; bestehende lokale Daten "
|
|
+ "werden dabei übernommen."
|
|
),
|
|
onSignIn: { authGate.require(reason: "konto") {} },
|
|
onSignOut: {
|
|
// Spotlight-Index leeren, sonst leaken die saved-Articles
|
|
// über Account-Wechsel.
|
|
await SpotlightIndex().clearAll()
|
|
await auth.signOut()
|
|
},
|
|
// Feedback an fester Position (geteilte ManaFeedbackCard, direkt
|
|
// nach dem Konto-Block) statt unscheinbar tief im extra-Slot.
|
|
feedbackClient: FeedbackClient(appId: "pageta") { try? await auth.freshAccessToken() },
|
|
extra: { appSections }
|
|
)
|
|
.navigationTitle("Konto")
|
|
.paperBackground()
|
|
.manaBrand(PagetaBrand.config(for: theme))
|
|
}
|
|
}
|
|
|
|
/// Pageta-spezifische Sektionen — immer sichtbar (auch ausgeloggt).
|
|
@ViewBuilder
|
|
private var appSections: some View {
|
|
Section {
|
|
PagetaAppearancePicker()
|
|
.listRowInsets(EdgeInsets(top: 8, leading: 16, bottom: 8, trailing: 16))
|
|
PagetaThemeGallery()
|
|
.listRowInsets(EdgeInsets(top: 4, leading: 16, bottom: 12, trailing: 16))
|
|
} header: {
|
|
Text("Darstellung")
|
|
} footer: {
|
|
Text(
|
|
"„Automatisch\" folgt dem System (Hell/Dunkel). Das Thema bestimmt die Farbwelt — frei wählbar, deine Wahl gilt sofort in der ganzen App."
|
|
)
|
|
}
|
|
Section {
|
|
Toggle("App-Icon-Badge zeigen", isOn: $badgeEnabled)
|
|
.onChange(of: badgeEnabled) { _, enabled in
|
|
Task { await handleBadgeToggle(enabled: enabled) }
|
|
}
|
|
} header: {
|
|
Text("Benachrichtigungen")
|
|
} footer: {
|
|
Text(
|
|
"Zeigt die Anzahl ungelesener Artikel am App-Icon. Beim Aktivieren wird die System-Berechtigung abgefragt."
|
|
)
|
|
}
|
|
ManaLLMSettingsView(context: AccountTabView.llmContext)
|
|
Section("Über") {
|
|
LabeledContent(
|
|
"Version",
|
|
value: Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String ?? "0.1.0"
|
|
)
|
|
LabeledContent(
|
|
"Build",
|
|
value: Bundle.main.infoDictionary?["CFBundleVersion"] as? String ?? "1"
|
|
)
|
|
Link("Web-App", destination: URL(string: "https://pageta.com")!)
|
|
Link("Verein", destination: URL(string: "https://mana-ev.ch")!)
|
|
}
|
|
}
|
|
|
|
/// Wenn der User Badge aktiviert: System-Permission anfragen, bei
|
|
/// Denial das Toggle zurücksetzen. Wenn deaktiviert: Badge auf 0
|
|
/// löschen, damit die alte Zahl nicht stehenbleibt.
|
|
private func handleBadgeToggle(enabled: Bool) async {
|
|
if enabled {
|
|
let granted = await BadgeManager.requestPermission()
|
|
if !granted {
|
|
badgeEnabled = false
|
|
}
|
|
} else {
|
|
await BadgeManager.setBadge(count: 0)
|
|
}
|
|
}
|
|
}
|