126 lines
4.7 KiB
Swift
126 lines
4.7 KiB
Swift
import SwiftUI
|
|
|
|
struct MessagesView: View {
|
|
@StateObject private var model: MessagesViewModel
|
|
|
|
init(model: MessagesViewModel? = nil) {
|
|
_model = StateObject(wrappedValue: model ?? DefaultContainer.makeMessagesModel())
|
|
}
|
|
|
|
var body: some View {
|
|
ZStack {
|
|
AITheme.canvas.ignoresSafeArea()
|
|
ScrollView {
|
|
LazyVStack(spacing: 12) {
|
|
filterBar
|
|
if let errorMessage = model.errorMessage {
|
|
AICard {
|
|
Text(errorMessage)
|
|
.font(.subheadline)
|
|
.foregroundStyle(AITheme.warning)
|
|
}
|
|
}
|
|
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)
|
|
}
|
|
}
|
|
ForEach(model.filteredRows) { message in
|
|
messageCard(message)
|
|
}
|
|
}
|
|
.padding(16)
|
|
}
|
|
}
|
|
.navigationTitle("消息中心")
|
|
.toolbar {
|
|
ToolbarItemGroup(placement: .primaryAction) {
|
|
Button {
|
|
model.showingSendForm = true
|
|
} label: {
|
|
Label("发送", systemImage: "paperplane")
|
|
}
|
|
.buttonStyle(AIButtonStyle(kind: .primary, size: .regular))
|
|
}
|
|
}
|
|
.refreshable {
|
|
await model.refresh()
|
|
}
|
|
.task {
|
|
await model.refresh()
|
|
}
|
|
.sheet(isPresented: $model.showingSendForm) {
|
|
SendMessageFormView(model: model)
|
|
}
|
|
}
|
|
|
|
private var filterBar: some View {
|
|
AICard {
|
|
VStack(spacing: 10) {
|
|
Picker("方向", selection: $model.direction) {
|
|
ForEach(MessagesViewModel.DirectionFilter.allCases) { item in
|
|
Text(item.rawValue).tag(item)
|
|
}
|
|
}
|
|
.pickerStyle(.segmented)
|
|
|
|
Picker("实例", selection: $model.selectedInstanceID) {
|
|
Text("全部实例").tag(Optional<UUID>.none)
|
|
ForEach(model.instances) { instance in
|
|
Text(instance.name).tag(Optional(instance.id))
|
|
}
|
|
}
|
|
.pickerStyle(.menu)
|
|
|
|
TextField("搜索号码或内容", text: $model.searchText)
|
|
.textFieldStyle(.plain)
|
|
.padding(.horizontal, 12)
|
|
.frame(minHeight: AITheme.buttonHeight)
|
|
.background(AITheme.canvas)
|
|
.clipShape(RoundedRectangle(cornerRadius: AITheme.buttonRadius))
|
|
.overlay {
|
|
RoundedRectangle(cornerRadius: AITheme.buttonRadius)
|
|
.strokeBorder(AITheme.line)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private func messageCard(_ message: SMSMessage) -> some View {
|
|
AICard {
|
|
VStack(alignment: .leading, spacing: 10) {
|
|
HStack(spacing: 8) {
|
|
Text(message.phoneNumber.isEmpty ? "未知号码" : message.phoneNumber)
|
|
.font(.headline)
|
|
Spacer()
|
|
AITag(message.direction.label, tint: message.direction == .outgoing ? AITheme.primary : AITheme.success)
|
|
}
|
|
Text(message.content)
|
|
.font(.subheadline)
|
|
.foregroundStyle(AITheme.ink)
|
|
HStack {
|
|
Text(message.instanceName)
|
|
.font(.caption)
|
|
.foregroundStyle(AITheme.muted)
|
|
Spacer()
|
|
Button("删除") {
|
|
Task { await model.delete(message) }
|
|
}
|
|
.buttonStyle(AIButtonStyle(kind: .danger, size: .compact))
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|