feat(ios): unify list cards and loading states

This commit is contained in:
chick
2026-09-10 01:35:12 +08:00
parent 995206ac23
commit c841748971
32 changed files with 1297 additions and 607 deletions
@@ -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)
}
}
}