Consolidate onboarding into single login page with native styling and full localization
Merge the two-page welcome/login flow into a single page with the app icon, title, subtitle, and login inputs all on one screen. Replace the custom blue background and white-on-blue styling with native iOS system colors and button styles. Add missing translations (de, es, fr) for all onboarding strings and fix localization by using LocalizedStringKey and String(localized:). Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -15,56 +15,55 @@ struct TokenLoginView: View {
|
||||
@Binding var showAlert: Bool
|
||||
@Binding var alertMessage: String
|
||||
@FocusState private var focusedField: Field?
|
||||
|
||||
|
||||
@State var userSettings = UserSettings.shared
|
||||
|
||||
|
||||
// TextField handling
|
||||
enum Field {
|
||||
case server
|
||||
case username
|
||||
case token
|
||||
}
|
||||
|
||||
|
||||
var body: some View {
|
||||
VStack(alignment: .leading) {
|
||||
VStack(alignment: .leading, spacing: 16) {
|
||||
ServerAddressField()
|
||||
.padding(.bottom)
|
||||
|
||||
LoginLabel(text: "User name")
|
||||
BorderedLoginTextField(example: "username", text: $userSettings.username)
|
||||
.focused($focusedField, equals: .username)
|
||||
.textContentType(.username)
|
||||
.submitLabel(.next)
|
||||
.padding(.bottom)
|
||||
|
||||
|
||||
LoginLabel(text: "App Token")
|
||||
BorderedLoginTextField(example: "can be generated in security settings of your nextcloud", text: $userSettings.token)
|
||||
.focused($focusedField, equals: .token)
|
||||
.textContentType(.password)
|
||||
.submitLabel(.join)
|
||||
HStack{
|
||||
Spacer()
|
||||
Button {
|
||||
Task {
|
||||
if await loginCheck(nextcloudLogin: false) {
|
||||
userSettings.onboarding = false
|
||||
}
|
||||
}
|
||||
} label: {
|
||||
Text("Submit")
|
||||
.foregroundColor(.white)
|
||||
.font(.headline)
|
||||
.padding()
|
||||
.background(
|
||||
RoundedRectangle(cornerRadius: 10)
|
||||
.stroke(Color.white, lineWidth: 2)
|
||||
.foregroundColor(.clear)
|
||||
)
|
||||
}
|
||||
.padding()
|
||||
Spacer()
|
||||
|
||||
VStack(alignment: .leading, spacing: 6) {
|
||||
LoginLabel(text: "User name")
|
||||
BorderedLoginTextField(example: "username", text: $userSettings.username)
|
||||
.focused($focusedField, equals: .username)
|
||||
.textContentType(.username)
|
||||
.submitLabel(.next)
|
||||
}
|
||||
|
||||
VStack(alignment: .leading, spacing: 6) {
|
||||
LoginLabel(text: "App Token")
|
||||
BorderedLoginTextField(example: "can be generated in security settings of your nextcloud", text: $userSettings.token)
|
||||
.focused($focusedField, equals: .token)
|
||||
.textContentType(.password)
|
||||
.submitLabel(.join)
|
||||
}
|
||||
|
||||
Button {
|
||||
Task {
|
||||
if await loginCheck(nextcloudLogin: false) {
|
||||
userSettings.onboarding = false
|
||||
}
|
||||
}
|
||||
} label: {
|
||||
Label("Submit", systemImage: "person.badge.key")
|
||||
.font(.subheadline)
|
||||
.fontWeight(.medium)
|
||||
.frame(maxWidth: .infinity)
|
||||
.padding(.vertical, 10)
|
||||
.foregroundStyle(Color.nextcloudBlue)
|
||||
.background(
|
||||
RoundedRectangle(cornerRadius: 10)
|
||||
.fill(Color.nextcloudBlue.opacity(0.1))
|
||||
)
|
||||
}
|
||||
.padding(.top, 4)
|
||||
}
|
||||
.onSubmit {
|
||||
switch focusedField {
|
||||
@@ -77,14 +76,14 @@ struct TokenLoginView: View {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
func loginCheck(nextcloudLogin: Bool) async -> Bool {
|
||||
if userSettings.serverAddress == "" {
|
||||
alertMessage = "Please enter a server address!"
|
||||
alertMessage = String(localized: "Please enter a server address!")
|
||||
showAlert = true
|
||||
return false
|
||||
} else if !nextcloudLogin && (userSettings.username == "" || userSettings.token == "") {
|
||||
alertMessage = "Please enter a user name and app token!"
|
||||
alertMessage = String(localized: "Please enter a user name and app token!")
|
||||
showAlert = true
|
||||
return false
|
||||
}
|
||||
@@ -95,7 +94,7 @@ struct TokenLoginView: View {
|
||||
let _ = try await client.getCategories()
|
||||
return true
|
||||
} catch {
|
||||
alertMessage = "Login failed. Please check your inputs and internet connection."
|
||||
alertMessage = String(localized: "Login failed. Please check your inputs and internet connection.")
|
||||
showAlert = true
|
||||
return false
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user