Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: authentication flow view -> Cloud password login - WPB-15222 #2455

Open
wants to merge 60 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 13 commits
Commits
Show all changes
60 commits
Select commit Hold shift + click to select a range
f940748
feat: add LoginWithClaimedDomainView
KaterinaWire Jan 28, 2025
8543fa4
Merge branch 'develop' into feat/authentication-ui-cloud-password-unc…
KaterinaWire Jan 29, 2025
18568ea
add LoginWithClaimedDomainView
KaterinaWire Jan 30, 2025
260dabf
Merge branch 'develop' into feat/authentication-ui-cloud-password-unc…
KaterinaWire Jan 30, 2025
8b394e3
Merge branch 'develop' into feat/authentication-ui-cloud-password-unc…
KaterinaWire Jan 30, 2025
97d2721
Merge branch 'develop' into feat/authentication-ui-cloud-password-unc…
KaterinaWire Jan 30, 2025
a1a9de5
add acc support for the PasswordField
KaterinaWire Jan 31, 2025
0fd8b6b
add LoginViaEmailViewModel
KaterinaWire Jan 31, 2025
7d8b498
add snapshots
KaterinaWire Jan 31, 2025
952a65b
Merge branch 'develop' into feat/authentication-ui-cloud-password-unc…
KaterinaWire Jan 31, 2025
bd02ab9
fix swiftFormat issues
KaterinaWire Feb 3, 2025
0df1b3e
fix swiftFormat issues
KaterinaWire Feb 3, 2025
6071d99
Merge branch 'develop' into feat/authentication-ui-cloud-password-unc…
KaterinaWire Feb 4, 2025
2973be6
merge from develop
KaterinaWire Feb 5, 2025
c7f4c59
temp
KaterinaWire Feb 5, 2025
379112a
Merge branch 'develop' into feat/authentication-ui-cloud-password-unc…
KaterinaWire Feb 5, 2025
a23e10d
Merge branch 'develop' into feat/authentication-ui-cloud-password-unc…
KaterinaWire Feb 5, 2025
706a9c6
update the color
KaterinaWire Feb 5, 2025
66f3656
Merge branch 'develop' into feat/authentication-ui-cloud-password-unc…
KaterinaWire Feb 5, 2025
7c6f0dd
temp
KaterinaWire Feb 6, 2025
3831907
temp
KaterinaWire Feb 6, 2025
8b2d969
Merge branch 'develop' into feat/authentication-ui-cloud-password-unc…
KaterinaWire Feb 7, 2025
990acff
Merge branch 'develop' into feat/authentication-ui-cloud-password-unc…
KaterinaWire Feb 7, 2025
d8efeed
add dependencies to the LoginViaEmailComponentDependency
KaterinaWire Feb 10, 2025
c6d2f51
fix PasswordField
KaterinaWire Feb 10, 2025
0d20e0c
Merge branch 'develop' into feat/authentication-ui-cloud-password-unc…
KaterinaWire Feb 10, 2025
b53e0fe
fix shapshot tests
KaterinaWire Feb 10, 2025
f7492a5
fix SwiftFormat issues
KaterinaWire Feb 10, 2025
a17a1f3
fix SwiftFormat issues
KaterinaWire Feb 10, 2025
01be383
Merge branch 'develop' into feat/authentication-ui-cloud-password-unc…
KaterinaWire Feb 10, 2025
9533b93
fix SwitchBackendConfirmationPreview init issue
KaterinaWire Feb 10, 2025
1ed2bf2
add LoginViaEmailViewTests tests
KaterinaWire Feb 10, 2025
acf39c3
add LoginViaEmailViewTests tests
KaterinaWire Feb 10, 2025
ad51580
add LoginOrRegisterViaEmailView tests
KaterinaWire Feb 10, 2025
9e13a01
add LoginOrRegisterViaEmailView tests
KaterinaWire Feb 10, 2025
9053a67
clean up
KaterinaWire Feb 10, 2025
83ec254
fix SwiftFormat issues
KaterinaWire Feb 10, 2025
0ca03d1
remove isPasswordValid
KaterinaWire Feb 10, 2025
1ed4650
address comments
KaterinaWire Feb 10, 2025
e72efc8
fix tests
KaterinaWire Feb 10, 2025
d015b3d
Merge branch 'develop' into feat/authentication-ui-cloud-password-unc…
KaterinaWire Feb 11, 2025
5079fcb
make properties private
KaterinaWire Feb 11, 2025
b3a02a5
clean up
KaterinaWire Feb 11, 2025
d50f8b1
fix SwidtFormat issues
KaterinaWire Feb 11, 2025
f060486
Merge branch 'develop' into feat/authentication-ui-cloud-password-unc…
KaterinaWire Feb 11, 2025
95b2d65
fix SwidtFormat issues
KaterinaWire Feb 11, 2025
5a4ab8b
Merge branch 'develop' into feat/authentication-ui-cloud-password-unc…
KaterinaWire Feb 11, 2025
eab2981
fix snapshots
KaterinaWire Feb 11, 2025
4534d53
update snapshots
KaterinaWire Feb 11, 2025
e53e43f
Merge branch 'develop' into feat/authentication-ui-cloud-password-unc…
KaterinaWire Feb 11, 2025
fe0356b
fix password
KaterinaWire Feb 11, 2025
59fad1f
update snapshots
KaterinaWire Feb 11, 2025
cd45ebc
fix parameters order
KaterinaWire Feb 11, 2025
e3ceae4
combine LoginOrRegisterViaEmailVie and LoginViaEmailVieww
KaterinaWire Feb 12, 2025
8df98b2
upate shanshots
KaterinaWire Feb 12, 2025
eb13a29
Merge branch 'develop' into feat/authentication-ui-cloud-password-unc…
KaterinaWire Feb 12, 2025
962ad4a
Merge branch 'develop' into feat/authentication-ui-cloud-password-unc…
KaterinaWire Feb 12, 2025
e56b785
clean up
KaterinaWire Feb 12, 2025
7defe15
Merge branch 'develop' into feat/authentication-ui-cloud-password-unc…
KaterinaWire Feb 12, 2025
463383f
Merge branch 'develop' into feat/authentication-ui-cloud-password-unc…
KaterinaWire Feb 13, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,15 @@
"authentication.identity.input.field.placeholder" = "Email or SSO code";
"authentication.identity.input.field.title" = "Email or SSO code";
"authentication.identity.input.submit" = "Next";
"authentication.identity.input.terms" = "By pressing on “Next”, you accept Wire’s [Terms and Conditions](%@)";

"cloud_user_login.title" = "Enter your password to log in";
"cloud_user_login.input_email.title" = "Email";
"cloud_user_login.input_password.title" = "Password";
"cloud_user_login.input_password.placeholder" = "Enter password";
"cloud_user_login.submit" = "Next";
"cloud_user_login.forgot_password" = "Forgot password?";
"create_personal_account.title" = "Don’t have a Wire account?";
"create_personal_account.button" = "Create Personal Account";

"switch_backend_confirmation.title" = "Redirect to an on-premises backend?";
"switch_backend_confirmation.message" = "If you proceed, you will be redirected to the following on-premises backend to log in:";
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
//
// Wire
// Copyright (C) 2025 Wire Swiss GmbH
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see http://www.gnu.org/licenses/.
//

import Foundation
import WireReusableUIComponents

package class LoginViaEmailViewModel {

let email: String
let forgotPasswordURL: URL
let passwordValidator: any PasswordValidator
let showCreateAccount: Bool
let onCreateAccount: @Sendable () -> Void
samwyndham marked this conversation as resolved.
Show resolved Hide resolved

// MARK: - Life cycle

package init(
email: String,
forgotPasswordURL: URL,
passwordValidator: any PasswordValidator,
showCreateAccount: Bool,
onCreateAccount: @Sendable @escaping () -> Void
) {
self.email = email
self.forgotPasswordURL = forgotPasswordURL
self.passwordValidator = passwordValidator
self.showCreateAccount = showCreateAccount
self.onCreateAccount = onCreateAccount
}

}
147 changes: 147 additions & 0 deletions WireUI/Sources/WireAuthenticationUI/Views/LoginViaEmailView.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
//
// Wire
// Copyright (C) 2025 Wire Swiss GmbH
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see http://www.gnu.org/licenses/.
//

import SwiftUI
import WireDesign
import WireReusableUIComponents

package struct LoginViaEmailView: View {
private let viewModel: LoginViaEmailViewModel

@State var password: String = ""
@State var isPasswordValid = true
KaterinaWire marked this conversation as resolved.
Show resolved Hide resolved

package init(
viewModel: LoginViaEmailViewModel
) {
self.viewModel = viewModel
}

package var body: some View {
VStack(alignment: .center, spacing: 14) {
LabeledTextField(
placeholder: nil,
title: L10n.CloudUserLogin.InputEmail.title,
string: .constant(viewModel.email)
)
.disabled(true)

PasswordField(
isPasswordValid: $isPasswordValid,
password: $password,
passwordValidator: viewModel.passwordValidator,
placeholder: L10n.CloudUserLogin.InputPassword.placeholder,
title: L10n.CloudUserLogin.InputPassword.title
)

Button(action: {
viewModel.onCreateAccount()
}, label: {
Text(L10n.CloudUserLogin.submit)
.lineLimit(nil)
})
.wireButtonStyle(.primary)
.disabled(!isPasswordValid)

Button(action: {
UIApplication.shared.open(viewModel.forgotPasswordURL)
}, label: {
Text(L10n.CloudUserLogin.forgotPassword)
.multilineTextAlignment(.center)
.lineLimit(nil)
.fixedSize(horizontal: false, vertical: true)
})
.wireButtonStyle(.link)

if viewModel.showCreateAccount {
KaterinaWire marked this conversation as resolved.
Show resolved Hide resolved
VStack(spacing: 4) {
Text(L10n.CreatePersonalAccount.title)
.multilineTextAlignment(.center)
.wireTextStyle(.body1)
.lineLimit(nil)
.fixedSize(horizontal: false, vertical: true)

Button(action: {
viewModel.onCreateAccount()
}, label: {
Text(L10n.CreatePersonalAccount.button)
.multilineTextAlignment(.center)
.lineLimit(nil)
.minimumScaleFactor(0.5)
.fixedSize(horizontal: false, vertical: true)
})
.wireButtonStyle(.link)
}
.frame(maxWidth: .infinity)
.padding()
.background {
if #available(iOS 17.0, *) {
RoundedRectangle(cornerRadius: 10)
.fill(ColorTheme.Backgrounds.backgroundVariant.color)
.stroke(ColorTheme.Strokes.outline.color, lineWidth: 1)
} else {
RoundedRectangle(cornerRadius: 10)
.stroke(ColorTheme.Strokes.outline.color, lineWidth: 1)
.background(ColorTheme.Backgrounds.backgroundVariant.color)
.cornerRadius(12)
}
}
}
}
.navigationTitle(L10n.CloudUserLogin.title)
.padding(32)
.background(ColorTheme.Backgrounds.surface.color)
.cornerRadius(16)
.overlay(
RoundedRectangle(cornerRadius: 16)
.stroke(ColorTheme.Backgrounds.surface.color, lineWidth: 1)
)
}
}

#Preview("Regular fonts") {
BackgroundView()
.overlay {
VStack(spacing: 0) {
Spacer()
.frame(maxHeight: .infinity)
LoginViaEmailPreview()
}
}
}

#Preview("Large fonts") {
BackgroundView()
.overlay {
VStack(spacing: 0) {
Spacer()
.frame(maxHeight: .infinity)
if #available(iOS 16.4, *) {
ScrollView(.vertical) {
LoginViaEmailPreview()
}
.scrollBounceBehavior(.basedOnSize)
} else {
ScrollView(.vertical) {
LoginViaEmailPreview()
}
}
}
}
.environment(\.sizeCategory, .accessibilityExtraExtraExtraLarge)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
//
// Wire
// Copyright (C) 2025 Wire Swiss GmbH
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see http://www.gnu.org/licenses/.
//

import SwiftUI
import WireFoundation
import WireReusableUIComponents

package struct LoginViaEmailPreview: View {
private let viewModel: LoginViaEmailViewModel

package init(
email: String = "[email protected]",
forgotPasswordURL: URL = URL(string: "https://example.com")!,
passwordValidator: any PasswordValidator = MockPasswordValidator(validationCallback: { _ in false }),
showCreateAccount: Bool = false,
onCreateAccount: @escaping (@Sendable () -> Void) = {}
) {
self.viewModel = LoginViaEmailViewModel(
email: email,
forgotPasswordURL: forgotPasswordURL,
passwordValidator: passwordValidator,
showCreateAccount: showCreateAccount,
onCreateAccount: onCreateAccount
)
}

package var body: some View {
LoginViaEmailView(
viewModel: viewModel
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@

import SwiftUI

package struct SwitchBackendConfirmationViewPreview: View {
package struct SwitchBackendConfirmationPreview: View {
package init() {}

package var body: some View {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ package struct SwitchBackendConfirmationView: View {
BackgroundView()
.overlay(
ZStack {
SwitchBackendConfirmationViewPreview()
SwitchBackendConfirmationPreview()
.padding()
}
.frame(maxWidth: .infinity, maxHeight: .infinity)
Expand All @@ -193,7 +193,7 @@ package struct SwitchBackendConfirmationView: View {
BackgroundView()
.overlay(
ZStack {
SwitchBackendConfirmationViewPreview()
SwitchBackendConfirmationPreview()
.padding()
}
.frame(maxWidth: .infinity, maxHeight: .infinity)
Expand Down
2 changes: 1 addition & 1 deletion WireUI/Sources/WireDesign/Colors/ColorTheme.swift
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ public enum ColorTheme {
static let selectedOutline = UIColor(light: .blue300Light, dark: .blue800Dark)
}

enum Tertiary {
public enum Tertiary {

static let enabled = UIColor(light: .white, dark: .gray90)
public static let onEnabled = UIColor(light: .black, dark: .white)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import WireFoundation

public struct LabeledTextField: View {
@Environment(\.isEnabled) private var isEnabled
@ScaledMetric private var fieldHeight: CGFloat = 48

private let isMandatory: Bool
private let placeholder: String?
Expand Down Expand Up @@ -60,19 +61,20 @@ public struct LabeledTextField: View {
.wireTextStyle(.body1)
.focused($isFocused)
.foregroundStyle(labelColor)
.padding(.vertical, 12)
.frame(height: fieldHeight)
if !string.isEmpty, isEnabled {
Button(action: {
string = ""
}, label: {
Image(systemName: "xmark.circle.fill")
.foregroundStyle(.black)
.foregroundStyle(ColorTheme.Buttons.Tertiary.onEnabled.color)
KaterinaWire marked this conversation as resolved.
Show resolved Hide resolved
.frame(width: 16, height: 16)
.padding(19)
})
}
}
.padding(.leading, 16)
.frame(height: fieldHeight)
.background {
if #available(iOS 17.0, *) {
RoundedRectangle(cornerRadius: 12)
Expand Down
Loading
Loading