Files
suixinkan_ios_new/suixinkan/App/State/SessionBootstrapper.swift
2026-06-22 11:28:01 +08:00

114 lines
4.0 KiB
Swift
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//
// SessionBootstrapper.swift
// suixinkan
//
// Created by Codex on 2026/6/20.
//
import Foundation
import Observation
@MainActor
@Observable
/// token
final class SessionBootstrapper {
@ObservationIgnored private let tokenStore: SessionTokenStore
@ObservationIgnored private let snapshotStore: AccountSnapshotStore
private var didAttemptRestore = false
/// token
init(
tokenStore: SessionTokenStore,
snapshotStore: AccountSnapshotStore
) {
self.tokenStore = tokenStore
self.snapshotStore = snapshotStore
}
/// 使
convenience init() {
self.init(
tokenStore: SessionTokenStore(),
snapshotStore: AccountSnapshotStore()
)
}
///
func restore(
appSession: AppSession,
accountContext: AccountContext,
permissionContext: PermissionContext,
profileAPI: UserProfileServing,
accountContextAPI: AccountContextServing,
toastCenter: ToastCenter
) async {
guard !didAttemptRestore, !appSession.isLoggedIn else { return }
didAttemptRestore = true
guard let token = tokenStore.load() else {
appSession.logout()
return
}
appSession.beginRestoring(token: token)
let cachedSnapshot = restoreCachedSnapshot(to: accountContext)
do {
try await AccountContextLoader().refresh(
accountContext: accountContext,
permissionContext: permissionContext,
profileAPI: profileAPI,
accountContextAPI: accountContextAPI,
cachedCurrentRoleId: cachedSnapshot?.currentRoleId,
cachedCurrentScenicId: cachedSnapshot?.currentScenicId,
cachedCurrentStoreId: cachedSnapshot?.currentStoreId
)
saveLatestSnapshot(from: accountContext, permissionContext: permissionContext)
appSession.markLoggedIn(token: token)
} catch {
if APIError.isAuthenticationExpired(error) {
try? tokenStore.clear()
snapshotStore.clear()
accountContext.reset()
permissionContext.reset()
appSession.logout()
toastCenter.show("登录状态已失效,请重新登录")
} else {
appSession.markLoggedIn(token: token)
toastCenter.show("网络异常,已使用本地登录状态")
}
}
}
///
private func restoreCachedSnapshot(to accountContext: AccountContext) -> AccountSnapshot? {
guard let snapshot = snapshotStore.load() else { return nil }
accountContext.applyLogin(profile: snapshot.profile)
accountContext.replaceScopes(
scenic: snapshot.scenicScopes,
stores: snapshot.storeScopes,
currentScenicId: snapshot.currentScenicId,
currentStoreId: snapshot.currentStoreId
)
return snapshot
}
///
private func saveLatestSnapshot(from accountContext: AccountContext, permissionContext: PermissionContext) {
let existing = snapshotStore.load()
snapshotStore.save(
AccountSnapshot(
profile: accountContext.profile,
accountType: existing?.accountType,
businessUserId: existing?.businessUserId,
currentRoleId: permissionContext.currentRole?.id ?? existing?.currentRoleId,
scenicScopes: accountContext.scenicScopes,
storeScopes: accountContext.storeScopes,
currentScenicId: accountContext.currentScenic?.id,
currentStoreId: accountContext.currentStore?.id
)
)
}
}