feat(auth): Guest-Mode + Login-optionale Surface
RootView ohne Hard-Login-Gate — TabBar zeigt sich immer, beim Start wechselt App bei .signedOut automatisch in den anonymen .guest-Modus (mana-swift-core v1.2.0). Auth-Sheets (Login, SignUp, Forgot, Reset) hängen jetzt als ManaAuthGate-Modifier am Root. AccountView zeigt im Guest-Modus eine eigene CTA-Surface („Anmelden / Konto erstellen" + Hinweis was Login bringt). signOut nutzt keepGuestMode: true → App bleibt nach Logout anonym nutzbar, Marketplace und lokale Daten gehen nicht verloren. DeckListView: Empty-State im Guest-Mode mit Login-CTA + Marketplace- Hinweis. Toolbar-„+"-Button via authGate.require gewrappt — Tap aus dem Guest-Modus öffnet erst das Sign-In-Sheet, danach den Editor. DeckListStore.refresh() skippt im Guest-Mode (kein 401-Spam). Cache wird so wie er ist gerendert (heute leer, später Marketplace-Klone). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
da6679770b
commit
8ca7bd3636
5 changed files with 276 additions and 160 deletions
|
|
@ -9,7 +9,7 @@ import WidgetKit
|
|||
@MainActor
|
||||
@Observable
|
||||
final class DeckListStore {
|
||||
enum State: Sendable {
|
||||
enum State {
|
||||
case idle
|
||||
case loading
|
||||
case loaded
|
||||
|
|
@ -21,15 +21,25 @@ final class DeckListStore {
|
|||
|
||||
private let api: CardsAPI
|
||||
private let context: ModelContext
|
||||
private let auth: AuthClient
|
||||
|
||||
init(auth: AuthClient, context: ModelContext) {
|
||||
api = CardsAPI(auth: auth)
|
||||
self.context = context
|
||||
self.auth = auth
|
||||
}
|
||||
|
||||
/// Holt Decks vom Server, aktualisiert Cache. Bei Netzfehler bleibt
|
||||
/// der Cache (offline-readable).
|
||||
/// der Cache (offline-readable). Im Guest-Mode wird kein Server-Call
|
||||
/// versucht — der Cache (leer oder über Marketplace-Klone gefüllt)
|
||||
/// wird so wie er ist gerendert.
|
||||
func refresh() async {
|
||||
guard case .signedIn = auth.status else {
|
||||
state = .idle
|
||||
errorMessage = nil
|
||||
return
|
||||
}
|
||||
|
||||
state = .loading
|
||||
errorMessage = nil
|
||||
|
||||
|
|
@ -69,8 +79,8 @@ final class DeckListStore {
|
|||
group.addTask { [api] in
|
||||
async let cards = api.cardCount(deckId: deck.id)
|
||||
async let due = api.dueCount(deckId: deck.id)
|
||||
let cardCount = (try? await cards) ?? 0
|
||||
let dueCount = (try? await due) ?? 0
|
||||
let cardCount = await (try? cards) ?? 0
|
||||
let dueCount = await (try? due) ?? 0
|
||||
return (deck.id, cardCount, dueCount)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue