feat(ios): unify list cards and loading states
This commit is contained in:
@@ -14,18 +14,10 @@ struct SettingsView: View {
|
||||
ScrollView {
|
||||
LazyVStack(spacing: 12) {
|
||||
if let errorMessage = model.errorMessage {
|
||||
AICard {
|
||||
Text(errorMessage)
|
||||
.font(.subheadline)
|
||||
.foregroundStyle(AITheme.danger)
|
||||
}
|
||||
AIStatusBanner(errorMessage, tint: AITheme.danger, systemImage: "exclamationmark.triangle")
|
||||
}
|
||||
if let notice = model.notice {
|
||||
AICard {
|
||||
Text(notice)
|
||||
.font(.subheadline)
|
||||
.foregroundStyle(AITheme.success)
|
||||
}
|
||||
AIStatusBanner(notice, tint: AITheme.success, systemImage: "checkmark.circle")
|
||||
}
|
||||
|
||||
runtimeCard
|
||||
@@ -38,12 +30,9 @@ struct SettingsView: View {
|
||||
.navigationTitle("设置")
|
||||
.toolbar {
|
||||
ToolbarItemGroup(placement: .primaryAction) {
|
||||
Button {
|
||||
AIToolbarButton("刷新", systemImage: "arrow.clockwise") {
|
||||
Task { await model.refresh() }
|
||||
} label: {
|
||||
Label("刷新", systemImage: "arrow.clockwise")
|
||||
}
|
||||
.buttonStyle(AIButtonStyle(kind: .secondary, size: .regular))
|
||||
.disabled(model.isLoading)
|
||||
}
|
||||
}
|
||||
@@ -68,10 +57,10 @@ struct SettingsView: View {
|
||||
private var runtimeCard: some View {
|
||||
AICard {
|
||||
VStack(alignment: .leading, spacing: 12) {
|
||||
sectionTitle("应用信息", systemImage: "info.circle")
|
||||
AISectionTitle("应用信息", systemImage: "info.circle")
|
||||
if let runtime = model.runtime {
|
||||
infoRow("版本", "\(runtime.marketingVersion) (\(runtime.buildVersion))")
|
||||
infoRow("设备", runtime.deviceModel)
|
||||
AIKeyValueRow("版本", value: "\(runtime.marketingVersion) (\(runtime.buildVersion))")
|
||||
AIKeyValueRow("设备", value: runtime.deviceModel)
|
||||
} else {
|
||||
Text("正在读取应用信息…")
|
||||
.font(.subheadline)
|
||||
@@ -84,16 +73,15 @@ struct SettingsView: View {
|
||||
private var storageCard: some View {
|
||||
AICard {
|
||||
VStack(alignment: .leading, spacing: 12) {
|
||||
sectionTitle("本地数据", systemImage: "externaldrive")
|
||||
infoRow("存储位置", "仅保存在本机应用沙盒")
|
||||
infoRow("当前占用", model.storageLabel)
|
||||
AISectionTitle("本地数据", systemImage: "externaldrive")
|
||||
AIKeyValueRow("存储位置", value: "仅保存在本机应用沙盒")
|
||||
AIKeyValueRow("当前占用", value: model.storageLabel)
|
||||
Button {
|
||||
showsClearDialog = true
|
||||
} label: {
|
||||
Label("清除运行日志", systemImage: "trash")
|
||||
}
|
||||
.frame(maxWidth: .infinity)
|
||||
.buttonStyle(AIButtonStyle(kind: .danger, size: .large))
|
||||
.buttonStyle(AIButtonStyle(kind: .danger, size: .large, fillsWidth: true))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -101,32 +89,11 @@ struct SettingsView: View {
|
||||
private var securityCard: some View {
|
||||
AICard {
|
||||
VStack(alignment: .leading, spacing: 12) {
|
||||
sectionTitle("安全与登录", systemImage: "lock.shield")
|
||||
infoRow("实例密码", "保存在 iOS 钥匙串")
|
||||
infoRow("登录会话", "仅保存在内存")
|
||||
AISectionTitle("安全与登录", systemImage: "lock.shield")
|
||||
AIKeyValueRow("实例密码", value: "保存在本机应用沙盒")
|
||||
AIKeyValueRow("登录会话", value: "仅保存在内存")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func sectionTitle(_ title: String, systemImage: String) -> some View {
|
||||
HStack(spacing: 8) {
|
||||
Image(systemName: systemImage)
|
||||
.foregroundStyle(AITheme.primary)
|
||||
Text(title)
|
||||
.font(.headline.weight(.bold))
|
||||
Spacer()
|
||||
}
|
||||
}
|
||||
|
||||
private func infoRow(_ title: String, _ value: String) -> some View {
|
||||
VStack(alignment: .leading, spacing: 4) {
|
||||
Text(title)
|
||||
.font(.caption)
|
||||
.foregroundStyle(AITheme.muted)
|
||||
Text(value)
|
||||
.font(.subheadline)
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
.textSelection(.enabled)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user