fix: unify location report state

This commit is contained in:
2026-07-07 16:24:26 +08:00
parent 9378748a4d
commit 97060c2a32
4 changed files with 143 additions and 10 deletions
@@ -8,6 +8,8 @@ import Foundation
/// 首页在线状态与 2 小时倒计时存储,对齐 Android `LocationStateRepository`。
final class HomeLocationStateStore {
static let shared = HomeLocationStateStore(store: .shared)
static let onlineDurationMillis: Int64 = 2 * 60 * 60 * 1000
private(set) var isOnline = false
@@ -15,11 +17,10 @@ final class HomeLocationStateStore {
private(set) var nextReportCountdownSeconds: Int64 = 0
private(set) var reminderMinutes = 0
var onStateChange: (() -> Void)?
private let store: AppStore
private var countdownTask: Task<Void, Never>?
private var anchorTimestamp: Int64?
private var observers: [ObjectIdentifier: StateObserver] = [:]
init(store: AppStore = .shared) {
self.store = store
@@ -27,11 +28,38 @@ final class HomeLocationStateStore {
isOnline = store.onlineStatus
}
deinit {
countdownTask?.cancel()
}
/// 监听状态变化,允许首页与独立位置上报页同时刷新。
func observe(_ owner: AnyObject, handler: @escaping () -> Void) {
observers[ObjectIdentifier(owner)] = StateObserver(owner: owner, handler: handler)
}
/// 移除指定监听者。
func removeObserver(_ owner: AnyObject) {
observers.removeValue(forKey: ObjectIdentifier(owner))
}
/// 启动时恢复在线倒计时。
func restoreStateIfNeeded() {
guard store.onlineStatus else { return }
reminderMinutes = store.locationReminderMinutes
guard store.onlineStatus else {
isOnline = false
stopCountdown()
notifyChange()
return
}
let lastTime = store.lastLocationReportTime
guard lastTime > 0 else { return }
guard lastTime > 0 else {
isOnline = false
store.onlineStatus = false
store.clearLastLocationReportTime()
stopCountdown()
notifyChange()
return
}
let now = Int64(Date().timeIntervalSince1970 * 1000)
let elapsed = now - lastTime
@@ -147,6 +175,17 @@ final class HomeLocationStateStore {
}
private func notifyChange() {
onStateChange?()
observers = observers.filter { $0.value.owner != nil }
observers.values.forEach { $0.handler() }
}
}
private final class StateObserver {
weak var owner: AnyObject?
let handler: () -> Void
init(owner: AnyObject, handler: @escaping () -> Void) {
self.owner = owner
self.handler = handler
}
}
@@ -37,7 +37,7 @@ final class HomeViewModel {
init(
appStore: AppStore = .shared,
locationStateStore: HomeLocationStateStore = HomeLocationStateStore(),
locationStateStore: HomeLocationStateStore = .shared,
commonMenuStore: HomeCommonMenuStore = HomeCommonMenuStore(),
locationProvider: any LocationProviding = LocationProvider.shared
) {
@@ -50,11 +50,15 @@ final class HomeViewModel {
locationProvider: locationProvider
)
self.commonMenuStore = commonMenuStore
self.locationStateStore.onStateChange = { [weak self] in
self.locationStateStore.observe(self) { [weak self] in
self?.notifyStateChange()
}
}
deinit {
locationStateStore.removeObserver(self)
}
var isOnline: Bool { locationStateStore.isOnline }
var countdownDisplayText: String { locationStateStore.countdownDisplayText }
var reminderMinutes: Int { locationStateStore.reminderMinutes }
@@ -73,6 +77,7 @@ final class HomeViewModel {
/// 按需重新拉取权限。
func reloadIfNeeded(api: HomeAPI) async {
locationStateStore.restoreStateIfNeeded()
guard needsPermissionReload else {
refreshLocalDisplayState()
rebuildCommonMenus()