Files
multi-simadmin/apps/ios/Sources/MultiSimAdmin/Features/Messages/MessagesView.swift
T

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))
}
}
}
}
}