feat(ios): refine native ui controls

This commit is contained in:
chick
2026-09-09 11:14:39 +08:00
parent c568e496b2
commit 995206ac23
18 changed files with 397 additions and 212 deletions
@@ -2,6 +2,7 @@ import SwiftUI
struct MessagesView: View {
@StateObject private var model: MessagesViewModel
@State private var pendingDeleteMessage: SMSMessage?
init(model: MessagesViewModel? = nil) {
_model = StateObject(wrappedValue: model ?? DefaultContainer.makeMessagesModel())
@@ -54,6 +55,20 @@ struct MessagesView: View {
.buttonStyle(AIButtonStyle(kind: .primary, size: .regular))
}
}
.confirmationDialog(
"删除这条消息?操作不可恢复。",
isPresented: Binding(
get: { pendingDeleteMessage != nil },
set: { if !$0 { pendingDeleteMessage = nil } }
),
titleVisibility: .visible
) {
Button("删除消息", role: .destructive) {
guard let message = pendingDeleteMessage else { return }
Task { await model.delete(message) }
}
Button("取消", role: .cancel) {}
}
.refreshable {
await model.refresh()
}
@@ -83,16 +98,7 @@ struct MessagesView: View {
}
.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)
}
AISearchField("搜索号码或内容", text: $model.searchText)
}
}
}
@@ -115,7 +121,7 @@ struct MessagesView: View {
.foregroundStyle(AITheme.muted)
Spacer()
Button("删除") {
Task { await model.delete(message) }
pendingDeleteMessage = message
}
.buttonStyle(AIButtonStyle(kind: .danger, size: .compact))
}
@@ -7,6 +7,18 @@ struct SendMessageFormView: View {
@State private var content = ""
@State private var validationMessage: String?
private var trimmedPhoneNumber: String {
phoneNumber.trimmingCharacters(in: .whitespacesAndNewlines)
}
private var trimmedContent: String {
content.trimmingCharacters(in: .whitespacesAndNewlines)
}
private var canSend: Bool {
!trimmedPhoneNumber.isEmpty && !trimmedContent.isEmpty
}
var body: some View {
NavigationStack {
ZStack {
@@ -26,16 +38,19 @@ struct SendMessageFormView: View {
.pickerStyle(.menu)
TextField("收件号码", text: $phoneNumber)
.textFieldStyle(AIFieldStyle())
TextField("消息内容", text: $content, axis: .vertical)
.textFieldStyle(.plain)
.padding(.horizontal, 12)
.frame(minHeight: AITheme.buttonHeight)
.background(AITheme.canvas)
.clipShape(RoundedRectangle(cornerRadius: AITheme.buttonRadius))
TextField("消息内容", text: $content, axis: .vertical)
.overlay {
RoundedRectangle(cornerRadius: AITheme.buttonRadius)
.strokeBorder(AITheme.line)
}
.lineLimit(4...8)
.padding(12)
.background(AITheme.canvas)
.clipShape(RoundedRectangle(cornerRadius: AITheme.buttonRadius))
}
}
if let validationMessage {
@@ -57,6 +72,7 @@ struct SendMessageFormView: View {
ToolbarItem(placement: .confirmationAction) {
Button("发送") { send() }
.buttonStyle(AIButtonStyle(kind: .primary, size: .regular))
.disabled(!canSend)
}
}
}
@@ -65,7 +81,7 @@ struct SendMessageFormView: View {
private func send() {
Task {
do {
try await model.send(phoneNumber: phoneNumber, content: content)
try await model.send(phoneNumber: trimmedPhoneNumber, content: trimmedContent)
phoneNumber = ""
content = ""
validationMessage = nil