feat: Redesign server settings form with prompt parameters and quick input chips
- Remove redundant field labels, use prompt parameter instead - Add QuickInputChip component for quick URL entry - Add chips: http://, https://, 192.168., :8000 - Improve spacing and layout consistency - Cleaner, more modern UI appearance
This commit is contained in:
parent
819eb4fc56
commit
554e223bbc
@ -10,16 +10,16 @@ import SwiftUI
|
||||
struct SettingsServerView: View {
|
||||
@State private var viewModel = SettingsServerViewModel()
|
||||
@State private var showingLogoutAlert = false
|
||||
|
||||
|
||||
init(showingLogoutAlert: Bool = false) {
|
||||
self.showingLogoutAlert = showingLogoutAlert
|
||||
}
|
||||
|
||||
|
||||
var body: some View {
|
||||
VStack(spacing: 20) {
|
||||
SectionHeader(title: viewModel.isSetupMode ? "Server Settings".localized : "Server Connection".localized, icon: "server.rack")
|
||||
.padding(.bottom, 4)
|
||||
|
||||
|
||||
Text(viewModel.isSetupMode ?
|
||||
"Enter your Readeck server details to get started." :
|
||||
"Your current server connection and login credentials.")
|
||||
@ -27,23 +27,54 @@ struct SettingsServerView: View {
|
||||
.foregroundColor(.secondary)
|
||||
.multilineTextAlignment(.center)
|
||||
.padding(.bottom, 8)
|
||||
|
||||
|
||||
// Form
|
||||
VStack(spacing: 16) {
|
||||
VStack(alignment: .leading, spacing: 6) {
|
||||
Text("Server Endpoint")
|
||||
.font(.headline)
|
||||
// Server Endpoint
|
||||
VStack(alignment: .leading, spacing: 8) {
|
||||
if viewModel.isSetupMode {
|
||||
TextField("http://192.168.0.77:8000", text: $viewModel.endpoint)
|
||||
TextField("",
|
||||
text: $viewModel.endpoint,
|
||||
prompt: Text("Server Endpoint").foregroundColor(.secondary))
|
||||
.textFieldStyle(.roundedBorder)
|
||||
.keyboardType(.URL)
|
||||
.autocapitalization(.none)
|
||||
.disableAutocorrection(true)
|
||||
.tint(.gray)
|
||||
.onChange(of: viewModel.endpoint) {
|
||||
viewModel.clearMessages()
|
||||
}
|
||||
|
||||
// Quick Input Chips
|
||||
ScrollView(.horizontal, showsIndicators: false) {
|
||||
HStack(spacing: 8) {
|
||||
QuickInputChip(text: "http://", action: {
|
||||
if !viewModel.endpoint.starts(with: "http") {
|
||||
viewModel.endpoint = "http://" + viewModel.endpoint
|
||||
}
|
||||
})
|
||||
QuickInputChip(text: "https://", action: {
|
||||
if !viewModel.endpoint.starts(with: "http") {
|
||||
viewModel.endpoint = "https://" + viewModel.endpoint
|
||||
}
|
||||
})
|
||||
QuickInputChip(text: "192.168.", action: {
|
||||
if viewModel.endpoint.isEmpty || viewModel.endpoint == "http://" || viewModel.endpoint == "https://" {
|
||||
if viewModel.endpoint.starts(with: "http") {
|
||||
viewModel.endpoint += "192.168."
|
||||
} else {
|
||||
viewModel.endpoint = "http://192.168."
|
||||
}
|
||||
}
|
||||
})
|
||||
QuickInputChip(text: ":8000", action: {
|
||||
if !viewModel.endpoint.contains(":") || viewModel.endpoint.hasSuffix("://") {
|
||||
viewModel.endpoint += ":8000"
|
||||
}
|
||||
})
|
||||
}
|
||||
.padding(.horizontal, 1)
|
||||
}
|
||||
|
||||
Text("HTTP/HTTPS supported. HTTP only for local networks. Port optional. No trailing slash needed.")
|
||||
.font(.caption)
|
||||
.foregroundColor(.secondary)
|
||||
@ -60,11 +91,13 @@ struct SettingsServerView: View {
|
||||
.padding(.vertical, 8)
|
||||
}
|
||||
}
|
||||
VStack(alignment: .leading, spacing: 6) {
|
||||
Text("Username")
|
||||
.font(.headline)
|
||||
|
||||
// Username
|
||||
VStack(alignment: .leading, spacing: 8) {
|
||||
if viewModel.isSetupMode {
|
||||
TextField("Your Username", text: $viewModel.username)
|
||||
TextField("",
|
||||
text: $viewModel.username,
|
||||
prompt: Text("Username").foregroundColor(.secondary))
|
||||
.textFieldStyle(.roundedBorder)
|
||||
.autocapitalization(.none)
|
||||
.disableAutocorrection(true)
|
||||
@ -83,12 +116,13 @@ struct SettingsServerView: View {
|
||||
.padding(.vertical, 8)
|
||||
}
|
||||
}
|
||||
|
||||
// Password
|
||||
if viewModel.isSetupMode {
|
||||
VStack(alignment: .leading, spacing: 6) {
|
||||
Text("Password")
|
||||
.font(.headline)
|
||||
|
||||
SecureField("Your Password", text: $viewModel.password)
|
||||
VStack(alignment: .leading, spacing: 8) {
|
||||
SecureField("",
|
||||
text: $viewModel.password,
|
||||
prompt: Text("Password").foregroundColor(.secondary))
|
||||
.textFieldStyle(.roundedBorder)
|
||||
.onChange(of: viewModel.password) {
|
||||
viewModel.clearMessages()
|
||||
@ -96,7 +130,7 @@ struct SettingsServerView: View {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Messages
|
||||
if let errorMessage = viewModel.errorMessage {
|
||||
HStack {
|
||||
@ -107,7 +141,7 @@ struct SettingsServerView: View {
|
||||
.font(.caption)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if let successMessage = viewModel.successMessage {
|
||||
HStack {
|
||||
Image(systemName: "checkmark.circle.fill")
|
||||
@ -117,7 +151,7 @@ struct SettingsServerView: View {
|
||||
.font(.caption)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if viewModel.isSetupMode {
|
||||
VStack(spacing: 10) {
|
||||
Button(action: {
|
||||
@ -140,7 +174,7 @@ struct SettingsServerView: View {
|
||||
.foregroundColor(.white)
|
||||
.cornerRadius(10)
|
||||
}
|
||||
.disabled(!viewModel.canLogin || viewModel.isLoading)
|
||||
.disabled(!viewModel.canLogin || viewModel.isLoading)
|
||||
}
|
||||
} else {
|
||||
Button(action: {
|
||||
@ -176,3 +210,23 @@ struct SettingsServerView: View {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Quick Input Chip Component
|
||||
|
||||
struct QuickInputChip: View {
|
||||
let text: String
|
||||
let action: () -> Void
|
||||
|
||||
var body: some View {
|
||||
Button(action: action) {
|
||||
Text(text)
|
||||
.font(.caption)
|
||||
.fontWeight(.medium)
|
||||
.padding(.horizontal, 12)
|
||||
.padding(.vertical, 6)
|
||||
.background(Color(.systemGray5))
|
||||
.foregroundColor(.secondary)
|
||||
.cornerRadius(12)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user