fix network
This commit is contained in:
+41
-2
@@ -1,5 +1,6 @@
|
||||
import SwiftUI
|
||||
import SwiftData
|
||||
import Combine
|
||||
|
||||
/// 应用入口。
|
||||
/// 负责初始化 SwiftData 容器,并将全局状态 `AppState` 注入到根视图。
|
||||
@@ -7,6 +8,8 @@ import SwiftData
|
||||
struct tvboxApp: App {
|
||||
/// 全局运行时状态(配置加载状态、当前源、分栏布局状态等)。
|
||||
@StateObject private var appState = AppState()
|
||||
/// 网络状态监控。
|
||||
@StateObject private var networkMonitor = NetworkMonitor.shared
|
||||
|
||||
/// 全局共享的 SwiftData 容器。
|
||||
/// 这里显式声明 Schema,确保收藏/历史/缓存三类数据使用同一持久化存储。
|
||||
@@ -29,6 +32,7 @@ struct tvboxApp: App {
|
||||
WindowGroup {
|
||||
ContentView()
|
||||
.environmentObject(appState)
|
||||
.environmentObject(networkMonitor)
|
||||
}
|
||||
.modelContainer(sharedModelContainer)
|
||||
#if os(macOS)
|
||||
@@ -47,6 +51,11 @@ class AppState: ObservableObject {
|
||||
@Published var isConfigLoaded = false
|
||||
/// 当前首页选中的视频源 key(用于跨页面同步)。
|
||||
@Published var currentSourceKey: String = ""
|
||||
/// 配置加载错误信息,供 UI 展示。
|
||||
@Published var configLoadError: String?
|
||||
/// 是否正在重试加载配置。
|
||||
@Published var isRetryingConfig = false
|
||||
|
||||
#if os(macOS)
|
||||
/// macOS 三栏布局可见性(侧栏/内容/详情)。
|
||||
@Published var splitViewVisibility: NavigationSplitViewVisibility = .all
|
||||
@@ -54,6 +63,15 @@ class AppState: ObservableObject {
|
||||
private var splitViewVisibilityBeforePlayerFullScreen: NavigationSplitViewVisibility?
|
||||
#endif
|
||||
|
||||
/// 上次尝试加载的配置地址(用于自动重试)。
|
||||
private var lastVodUrl: String = ""
|
||||
private var lastLiveUrl: String = ""
|
||||
private var networkRestoredCancellable: AnyCancellable?
|
||||
|
||||
init() {
|
||||
setupNetworkRestoredAutoRetry()
|
||||
}
|
||||
|
||||
/// 仅提供点播地址时的快捷加载入口(直播地址默认与点播一致)。
|
||||
func loadConfig(url: String) async {
|
||||
await loadConfig(vodUrl: url, liveUrl: nil)
|
||||
@@ -69,21 +87,42 @@ class AppState: ObservableObject {
|
||||
guard !trimmedVod.isEmpty else { return }
|
||||
let resolvedLive = trimmedLive.isEmpty ? trimmedVod : trimmedLive
|
||||
|
||||
lastVodUrl = trimmedVod
|
||||
lastLiveUrl = resolvedLive
|
||||
configLoadError = nil
|
||||
|
||||
do {
|
||||
try await ApiConfig.shared.loadConfigs(vodApiUrl: trimmedVod, liveApiUrl: resolvedLive)
|
||||
applyLoadedConfigState()
|
||||
} catch {
|
||||
print("Failed to load config: \(error)")
|
||||
if !(error is CancellationError) {
|
||||
configLoadError = error.localizedDescription
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// 将“配置已加载”的统一状态写回全局。
|
||||
/// 将"配置已加载"的统一状态写回全局。
|
||||
/// 该方法会在设置页和启动自动加载两个入口中复用。
|
||||
func applyLoadedConfigState() {
|
||||
isConfigLoaded = true
|
||||
configLoadError = nil
|
||||
currentSourceKey = ApiConfig.shared.homeSourceBean?.key ?? ""
|
||||
}
|
||||
|
||||
/// 网络恢复时,若配置未成功加载过,自动重试一次。
|
||||
private func setupNetworkRestoredAutoRetry() {
|
||||
networkRestoredCancellable = NetworkMonitor.shared.networkRestoredPublisher
|
||||
.sink { [weak self] in
|
||||
guard let self else { return }
|
||||
Task { @MainActor [weak self] in
|
||||
guard let self, !self.isConfigLoaded, !self.lastVodUrl.isEmpty else { return }
|
||||
self.isRetryingConfig = true
|
||||
await self.loadConfig(vodUrl: self.lastVodUrl, liveUrl: self.lastLiveUrl)
|
||||
self.isRetryingConfig = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if os(macOS)
|
||||
/// 进入播放器全屏时隐藏侧栏,减少播放器可视区域干扰。
|
||||
func enterPlayerFullScreen() {
|
||||
|
||||
Reference in New Issue
Block a user