修复离线路径误弹位置上报超时窗,并优化提醒设置与定位 Loading 展示。
离线或倒计时未进入提醒窗口时不再弹出超时提醒;全局 Loading 支持按需展示定位文案,提前提醒选项抽成共用组件。 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@ -16,10 +16,12 @@ final class GlobalLoadingCenter {
|
||||
fileprivate let state = GlobalLoadingState()
|
||||
|
||||
/// 显示全局 Loading;多次调用会通过引用计数叠加。
|
||||
func show(message: String = "") {
|
||||
func show(message: String = "", showsMessage: Bool = false) {
|
||||
if !message.isEmpty {
|
||||
state.message = message
|
||||
}
|
||||
state.messageDisplayLevels.append(showsMessage)
|
||||
state.showsMessage = state.messageDisplayLevels.contains(true)
|
||||
state.activeCount += 1
|
||||
state.isVisible = true
|
||||
}
|
||||
@ -27,9 +29,15 @@ final class GlobalLoadingCenter {
|
||||
/// 隐藏一次全局 Loading;所有调用方都结束后才真正关闭。
|
||||
func hide() {
|
||||
state.activeCount = max(0, state.activeCount - 1)
|
||||
if !state.messageDisplayLevels.isEmpty {
|
||||
state.messageDisplayLevels.removeLast()
|
||||
}
|
||||
state.showsMessage = state.messageDisplayLevels.contains(true)
|
||||
guard state.activeCount == 0 else { return }
|
||||
state.isVisible = false
|
||||
state.message = ""
|
||||
state.messageDisplayLevels = []
|
||||
state.showsMessage = false
|
||||
}
|
||||
|
||||
/// 更新当前 Loading 文案,仅在 Loading 可见且文案非空时生效。
|
||||
@ -41,9 +49,10 @@ final class GlobalLoadingCenter {
|
||||
/// 包裹一个异步操作,操作结束或抛错时自动关闭 Loading。
|
||||
func withLoading<T>(
|
||||
message: String = "",
|
||||
showsMessage: Bool = false,
|
||||
operation: () async throws -> T
|
||||
) async rethrows -> T {
|
||||
show(message: message)
|
||||
show(message: message, showsMessage: showsMessage)
|
||||
defer { hide() }
|
||||
return try await operation()
|
||||
}
|
||||
@ -52,10 +61,11 @@ final class GlobalLoadingCenter {
|
||||
func withOptionalLoading<T>(
|
||||
_ enabled: Bool,
|
||||
message: String = "",
|
||||
showsMessage: Bool = false,
|
||||
operation: () async throws -> T
|
||||
) async rethrows -> T {
|
||||
if enabled {
|
||||
return try await withLoading(message: message, operation: operation)
|
||||
return try await withLoading(message: message, showsMessage: showsMessage, operation: operation)
|
||||
}
|
||||
return try await operation()
|
||||
}
|
||||
@ -66,7 +76,8 @@ final class GlobalLoadingCenter {
|
||||
GlobalLoadingSnapshot(
|
||||
isVisible: state.isVisible,
|
||||
message: state.message,
|
||||
activeCount: state.activeCount
|
||||
activeCount: state.activeCount,
|
||||
showsMessage: state.showsMessage
|
||||
)
|
||||
}
|
||||
#endif
|
||||
@ -77,7 +88,9 @@ final class GlobalLoadingCenter {
|
||||
fileprivate final class GlobalLoadingState: ObservableObject {
|
||||
@Published fileprivate var isVisible = false
|
||||
@Published fileprivate var message = ""
|
||||
@Published fileprivate var showsMessage = false
|
||||
@Published fileprivate var activeCount = 0
|
||||
fileprivate var messageDisplayLevels: [Bool] = []
|
||||
}
|
||||
|
||||
/// Lottie Loading 动画容器,负责播放主包中的 loading.json。
|
||||
@ -146,6 +159,14 @@ private struct GlobalLoadingOverlayHost: View {
|
||||
|
||||
VStack(spacing: 14) {
|
||||
loadingAnimation
|
||||
if state.showsMessage, !state.message.isEmpty {
|
||||
Text(state.message)
|
||||
.font(.system(size: 15, weight: .medium))
|
||||
.foregroundStyle(AppDesign.textPrimary)
|
||||
.multilineTextAlignment(.center)
|
||||
.padding(.horizontal, 8)
|
||||
.padding(.bottom, 6)
|
||||
}
|
||||
}
|
||||
.padding(.horizontal, 10)
|
||||
.padding(.vertical, 10)
|
||||
@ -155,10 +176,12 @@ private struct GlobalLoadingOverlayHost: View {
|
||||
.transition(.opacity)
|
||||
.zIndex(10_000)
|
||||
.accessibilityElement(children: .combine)
|
||||
.accessibilityLabel("加载中")
|
||||
.accessibilityLabel(state.showsMessage && !state.message.isEmpty ? state.message : "加载中")
|
||||
}
|
||||
}
|
||||
.animation(.easeInOut(duration: 0.2), value: state.isVisible)
|
||||
.animation(.easeInOut(duration: 0.2), value: state.showsMessage)
|
||||
.animation(.easeInOut(duration: 0.2), value: state.message)
|
||||
}
|
||||
|
||||
@ViewBuilder
|
||||
@ -200,6 +223,7 @@ struct GlobalLoadingSnapshot: Equatable {
|
||||
let isVisible: Bool
|
||||
let message: String
|
||||
let activeCount: Int
|
||||
let showsMessage: Bool
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
Reference in New Issue
Block a user