feat(ios): simplify navigation and ship 0.2.0
Move diagnostics into settings, remove the app-local notification module, unify the global theme switcher, refine privacy copy and the instance detail experience, and rebuild the app icon.
This commit is contained in:
@@ -2,6 +2,7 @@ import SwiftUI
|
||||
|
||||
struct SettingsView: View {
|
||||
@StateObject private var model: SettingsViewModel
|
||||
@ObservedObject private var themeStore = ThemeStore.shared
|
||||
@State private var showsClearDialog = false
|
||||
|
||||
init(model: SettingsViewModel? = nil) {
|
||||
@@ -20,6 +21,7 @@ struct SettingsView: View {
|
||||
}
|
||||
|
||||
runtimeCard
|
||||
themeCard
|
||||
storageCard
|
||||
securityCard
|
||||
dangerZoneCard
|
||||
@@ -75,24 +77,54 @@ struct SettingsView: View {
|
||||
}
|
||||
}
|
||||
|
||||
private var storageCard: some View {
|
||||
private var themeCard: some View {
|
||||
AICard {
|
||||
VStack(alignment: .leading, spacing: 12) {
|
||||
AISectionTitle("本地数据", systemImage: "externaldrive")
|
||||
AIKeyValueRow("存储位置", value: "仅保存在本机应用沙盒")
|
||||
AIKeyValueRow("当前占用", value: model.storageLabel)
|
||||
AISectionTitle("外观", systemImage: "circle.lefthalf.filled", detail: themeStore.mode.label)
|
||||
AISegmentedControl(
|
||||
"主题模式",
|
||||
selection: Binding(
|
||||
get: { themeStore.mode },
|
||||
set: { themeStore.set($0) }
|
||||
),
|
||||
options: ThemeMode.allCases.map { (value: $0, title: $0.label) }
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private var storageCard: some View {
|
||||
AICard {
|
||||
NavigationLink {
|
||||
LogsView()
|
||||
} label: {
|
||||
VStack(alignment: .leading, spacing: 12) {
|
||||
HStack(spacing: 10) {
|
||||
AISectionTitle("本地数据", systemImage: "externaldrive")
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
Image(systemName: "chevron.right")
|
||||
.font(.footnote.weight(.semibold))
|
||||
.foregroundStyle(AITheme.muted)
|
||||
.accessibilityHidden(true)
|
||||
}
|
||||
AIKeyValueRow("数据位置", value: "仅保存在本机设备")
|
||||
AIKeyValueRow("当前占用", value: model.storageLabel)
|
||||
}
|
||||
}
|
||||
.buttonStyle(.plain)
|
||||
.accessibilityHint("进入日志与诊断")
|
||||
}
|
||||
}
|
||||
|
||||
private var securityCard: some View {
|
||||
AICard {
|
||||
VStack(alignment: .leading, spacing: 12) {
|
||||
AISectionTitle("隐私与安全", systemImage: "lock.shield")
|
||||
AIKeyValueRow("实例密码", value: "保存在本机应用沙盒")
|
||||
AIKeyValueRow("登录会话", value: "仅保存在内存")
|
||||
AISectionTitle("隐私与数据", systemImage: "lock.shield")
|
||||
AIKeyValueRow("节点信息", value: "仅保存在本机设备")
|
||||
AIKeyValueRow("实例密码", value: "保存在本地数据文件中")
|
||||
AIKeyValueRow("登录会话", value: "应用关闭后自动清除")
|
||||
AIStatusBanner(
|
||||
"实例凭据只保存在本机应用沙盒,登录会话只保留在内存中,应用关闭后自动失效。",
|
||||
"节点地址、实例密码和运行数据都保存在本机。应用只连接你添加的节点,登录会话关闭应用后即被清除。",
|
||||
tint: AITheme.primary,
|
||||
systemImage: "shield.checkered"
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user