feat(ios): refine native ui controls
This commit is contained in:
@@ -9,6 +9,11 @@ struct InstanceFormView: View {
|
||||
@State private var password = ""
|
||||
@State private var validationMessage: String?
|
||||
|
||||
private var canSave: Bool {
|
||||
!name.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty
|
||||
&& !originText.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
NavigationStack {
|
||||
ZStack {
|
||||
@@ -20,19 +25,15 @@ struct InstanceFormView: View {
|
||||
field("名称", text: $name, placeholder: "Home Node")
|
||||
field("地址", text: $originText, placeholder: "http://192.168.1.10:3000")
|
||||
field("标签", text: $tagsText, placeholder: "home, primary")
|
||||
SecureField("实例密码(可选)", text: $password)
|
||||
.textContentType(.password)
|
||||
.padding(.horizontal, 12)
|
||||
.frame(minHeight: 38)
|
||||
.background(AITheme.canvas)
|
||||
.clipShape(RoundedRectangle(cornerRadius: AITheme.buttonRadius))
|
||||
field("实例密码", text: $password, placeholder: "可选,保存到钥匙串", secure: true)
|
||||
}
|
||||
}
|
||||
if let validationMessage {
|
||||
Text(validationMessage)
|
||||
.font(.subheadline)
|
||||
.foregroundStyle(AITheme.danger)
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
AICard {
|
||||
Label(validationMessage, systemImage: "exclamationmark.triangle")
|
||||
.font(.subheadline)
|
||||
.foregroundStyle(AITheme.danger)
|
||||
}
|
||||
}
|
||||
}
|
||||
.padding(16)
|
||||
@@ -49,26 +50,35 @@ struct InstanceFormView: View {
|
||||
save()
|
||||
}
|
||||
.buttonStyle(AIButtonStyle(kind: .primary, size: .regular))
|
||||
.disabled(!canSave)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func field(_ title: String, text: Binding<String>, placeholder: String) -> some View {
|
||||
private func field(
|
||||
_ title: String,
|
||||
text: Binding<String>,
|
||||
placeholder: String,
|
||||
secure: Bool = false
|
||||
) -> some View {
|
||||
VStack(alignment: .leading, spacing: 6) {
|
||||
Text(title)
|
||||
.font(.subheadline.weight(.semibold))
|
||||
.foregroundStyle(AITheme.ink)
|
||||
TextField(placeholder, text: text)
|
||||
.textFieldStyle(.plain)
|
||||
.padding(.horizontal, 12)
|
||||
.frame(minHeight: 38)
|
||||
.background(AITheme.canvas)
|
||||
.clipShape(RoundedRectangle(cornerRadius: AITheme.buttonRadius))
|
||||
if secure {
|
||||
SecureField(placeholder, text: text)
|
||||
.textFieldStyle(AIFieldStyle())
|
||||
.textContentType(.password)
|
||||
} else {
|
||||
TextField(placeholder, text: text)
|
||||
.textFieldStyle(AIFieldStyle())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func save() {
|
||||
let normalizedName = name.trimmingCharacters(in: .whitespacesAndNewlines)
|
||||
guard let origin = URL(string: originText.trimmingCharacters(in: .whitespacesAndNewlines)),
|
||||
origin.scheme == "http" || origin.scheme == "https",
|
||||
origin.host != nil
|
||||
@@ -81,7 +91,7 @@ struct InstanceFormView: View {
|
||||
.map { $0.trimmingCharacters(in: .whitespacesAndNewlines) }
|
||||
.filter { !$0.isEmpty }
|
||||
let input = InstanceInput(
|
||||
name: name,
|
||||
name: normalizedName,
|
||||
origin: origin,
|
||||
tags: tags,
|
||||
password: password.isEmpty ? nil : password
|
||||
|
||||
Reference in New Issue
Block a user