

























@@ -7,15 +7,18 @@ struct SettingsRootView: View {
77private let permissionMonitor = PermissionMonitor.shared
88@State private var monitoringPermissions = false
99@State private var selectedTab: SettingsTab = .general
10+@State private var cachedTabs: Set<SettingsTab>
1011@State private var snapshotPaths: (configPath: String?, stateDir: String?) = (nil, nil)
1112let updater: UpdaterProviding?
1213private let isPreview = ProcessInfo.processInfo.isPreview
1314private let isNixMode = ProcessInfo.processInfo.isNixMode
14151516init(state: AppState, updater: UpdaterProviding?, initialTab: SettingsTab? = nil) {
17+let initial = initialTab ?? .general
1618self.state = state
1719self.updater = updater
18-self._selectedTab = State(initialValue: initialTab ?? .general)
20+self._selectedTab = State(initialValue: initial)
21+self._cachedTabs = State(initialValue: [initial])
1922}
20232124var body: some View {
@@ -37,7 +40,7 @@ struct SettingsRootView: View {
3740if self.isNixMode {
3841self.nixManagedBanner
3942}
40-self.detailView(for: self.selectedTab)
43+self.cachedDetailViews
4144}
4245.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .topLeading)
4346.padding(.horizontal, 22)
@@ -49,14 +52,15 @@ struct SettingsRootView: View {
4952.onReceive(NotificationCenter.default.publisher(for: .openclawSelectSettingsTab)) { note in
5053if let tab = note.object as? SettingsTab {
5154withAnimation(.spring(response: 0.32, dampingFraction: 0.85)) {
52-self.selectedTab = tab
55+self.selectedTab = self.validTab(for: tab)
5356}
5457}
5558}
5659.onAppear {
5760if let pending = SettingsTabRouter.consumePending() {
5861self.selectedTab = self.validTab(for: pending)
5962}
63+self.cacheSelectedTab()
6064self.updatePermissionMonitoring(for: self.selectedTab)
6165}
6266.onChange(of: self.state.debugPaneEnabled) { _, enabled in
@@ -65,6 +69,7 @@ struct SettingsRootView: View {
6569}
6670}
6771.onChange(of: self.selectedTab) { _, newValue in
72+self.cachedTabs.insert(newValue)
6873self.updatePermissionMonitoring(for: newValue)
6974}
7075.onReceive(NotificationCenter.default.publisher(for: NSApplication.didBecomeActiveNotification)) { _ in
@@ -86,6 +91,11 @@ struct SettingsRootView: View {
8691SettingsTabGroup.defaultGroups(showDebug: self.state.debugPaneEnabled)
8792}
889394+private var cachedDetailTabs: [SettingsTab] {
95+let cached = self.cachedTabs.union([self.selectedTab])
96+return self.visibleGroups.flatMap(\.tabs).filter { cached.contains($0) }
97+}
98+8999private var nixManagedBanner: some View {
90100 // Prefer gateway-resolved paths; fall back to local env defaults if disconnected.
91101let configPath = self.snapshotPaths.configPath ?? OpenClawPaths.configURL.path
@@ -116,13 +126,27 @@ struct SettingsRootView: View {
116126.cornerRadius(10)
117127}
118128129+private var cachedDetailViews: some View {
130+ZStack(alignment: .topLeading) {
131+ForEach(self.cachedDetailTabs) { tab in
132+self.detailView(for: tab)
133+.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .topLeading)
134+.opacity(tab == self.selectedTab ? 1 : 0)
135+.allowsHitTesting(tab == self.selectedTab)
136+.disabled(tab != self.selectedTab)
137+.accessibilityHidden(tab != self.selectedTab)
138+}
139+}
140+.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .topLeading)
141+}
142+119143@ViewBuilder
120144private func detailView(for tab: SettingsTab) -> some View {
121145switch tab {
122146case .general:
123-GeneralSettings(state: self.state, page: .general)
147+GeneralSettings(state: self.state, page: .general, isActive: self.selectedTab == tab)
124148case .connection:
125-GeneralSettings(state: self.state, page: .connection)
149+GeneralSettings(state: self.state, page: .connection, isActive: self.selectedTab == tab)
126150case .permissions:
127151PermissionsSettings(
128152 status: self.permissionMonitor.status,
@@ -131,17 +155,17 @@ struct SettingsRootView: View {
131155case .voiceWake:
132156VoiceWakeSettings(state: self.state, isActive: self.selectedTab == .voiceWake)
133157case .channels:
134-ChannelsSettings()
158+ChannelsSettings(isActive: self.selectedTab == tab)
135159case .skills:
136160SkillsSettings(state: self.state)
137161case .cron:
138-CronSettings()
162+CronSettings(isActive: self.selectedTab == tab)
139163case .execApprovals:
140164ExecApprovalsSettings()
141165case .sessions:
142166SessionsSettings()
143167case .instances:
144-InstancesSettings()
168+InstancesSettings(isActive: self.selectedTab == tab)
145169case .config:
146170ConfigSettings()
147171case .debug:
@@ -156,6 +180,10 @@ struct SettingsRootView: View {
156180return requested
157181}
158182183+private func cacheSelectedTab() {
184+self.cachedTabs.insert(self.selectedTab)
185+}
186+159187@MainActor
160188private func refreshSnapshotPaths() async {
161189let paths = await GatewayConnection.shared.snapshotPaths()
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。