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
@@ -15,26 +15,18 @@ struct MessagesView: View {
LazyVStack(spacing: 12) {
filterBar
if let errorMessage = model.errorMessage {
AICard {
Text(errorMessage)
.font(.subheadline)
.foregroundStyle(AITheme.warning)
}
AIStatusBanner(errorMessage, tint: AITheme.warning, systemImage: "exclamationmark.triangle")
}
if model.isLoading && model.filteredRows.isEmpty {
AILoadingCard("正在同步消息")
}
if model.filteredRows.isEmpty && !model.isLoading {
AICard {
VStack(spacing: 10) {
Image(systemName: "message")
.font(.system(size: 28))
.foregroundStyle(AITheme.muted)
Text("暂无消息")
.font(.headline)
Text("刷新后从实例同步短信。")
.font(.subheadline)
.foregroundStyle(AITheme.muted)
}
.frame(maxWidth: .infinity)
.padding(.vertical, 18)
AIEmptyState(
systemImage: "message",
title: "暂无消息",
message: "刷新后从实例同步短信。"
)
}
}
ForEach(model.filteredRows) { message in
@@ -45,15 +37,13 @@ struct MessagesView: View {
}
}
.navigationTitle("消息中心")
.toolbar {
ToolbarItemGroup(placement: .primaryAction) {
Button {
model.showingSendForm = true
} label: {
Label("发送", systemImage: "paperplane")
}
.buttonStyle(AIButtonStyle(kind: .primary, size: .regular))
.aiBottomActionBar {
Button {
model.showingSendForm = true
} label: {
Label("发送消息", systemImage: "paperplane")
}
.buttonStyle(AIButtonStyle(kind: .primary, size: .regular, fillsWidth: true))
}
.confirmationDialog(
"删除这条消息?操作不可恢复。",
@@ -97,6 +87,7 @@ struct MessagesView: View {
}
}
.pickerStyle(.menu)
.aiSelectSurface()
AISearchField("搜索号码或内容", text: $model.searchText)
}
@@ -115,15 +106,25 @@ struct MessagesView: View {
Text(message.content)
.font(.subheadline)
.foregroundStyle(AITheme.ink)
.fixedSize(horizontal: false, vertical: true)
HStack {
Text(message.instanceName)
.font(.caption)
.foregroundStyle(AITheme.muted)
.lineLimit(1)
.truncationMode(.middle)
.layoutPriority(1)
Spacer()
Button("删除") {
pendingDeleteMessage = message
}
.buttonStyle(AIButtonStyle(kind: .danger, size: .compact))
.buttonStyle(
AIButtonStyle(
kind: .danger,
size: .compact,
fixedWidth: AITheme.listActionButtonWidth
)
)
}
}
}