Skip to content

Commit

Permalink
Merge pull request #413 from openedx/develop
Browse files Browse the repository at this point in the history
Develop to main v1.5
  • Loading branch information
volodymyr-chekyrta authored Apr 22, 2024
2 parents 05d3073 + a0c4c17 commit 64b1c0e
Show file tree
Hide file tree
Showing 331 changed files with 19,251 additions and 6,567 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/unit_tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ on:
jobs:
tests:
name: Tests
runs-on: macos-13
runs-on: macos-14

concurrency:
# When running on develop, use the sha to allow all runs of this workflow to run concurrently.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,39 +14,45 @@ public enum AuthMethod: Equatable {
public var analyticsValue: String {
switch self {
case .password:
"Password"
"password"
case .socailAuth(let socialAuthMethod):
socialAuthMethod.rawValue
}
}
}

public enum SocialAuthMethod: String {
case facebook = "Facebook"
case google = "Google"
case microsoft = "Microsoft"
case apple = "Apple"
case facebook = "facebook"
case google = "google"
case microsoft = "microsoft"
case apple = "apple"
}

//sourcery: AutoMockable
public protocol AuthorizationAnalytics {
func setUserID(_ id: String)
func identify(id: String, username: String, email: String)
func userLogin(method: AuthMethod)
func signUpClicked()
func registerClicked()
func signInClicked()
func userSignInClicked()
func createAccountClicked()
func registrationSuccess()
func registrationSuccess(method: String)
func forgotPasswordClicked()
func resetPasswordClicked(success: Bool)
func resetPasswordClicked()
func resetPassword(success: Bool)
}

#if DEBUG
class AuthorizationAnalyticsMock: AuthorizationAnalytics {
public func setUserID(_ id: String) {}
func identify(id: String, username: String, email: String) {}
public func userLogin(method: AuthMethod) {}
public func signUpClicked() {}
public func registerClicked() {}
public func signInClicked() {}
public func userSignInClicked() {}
public func createAccountClicked() {}
public func registrationSuccess() {}
public func registrationSuccess(method: String) {}
public func forgotPasswordClicked() {}
public func resetPasswordClicked(success: Bool) {}
public func resetPasswordClicked() {}
public func resetPassword(success: Bool) {}
}
#endif
Original file line number Diff line number Diff line change
Expand Up @@ -94,8 +94,8 @@ struct FieldsView: View {
}
}
Text(.init(text))
.tint(Theme.Colors.accentColor)
.foregroundStyle(Theme.Colors.textSecondary)
.tint(Theme.Colors.infoColor)
.foregroundStyle(Theme.Colors.textSecondaryLight)
.font(Theme.Fonts.labelSmall)
.padding(.vertical, 3)
.id(UUID())
Expand Down
226 changes: 120 additions & 106 deletions Authorization/Authorization/Presentation/Login/SignInView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -34,14 +34,15 @@ public struct SignInView: View {
}.frame(maxWidth: .infinity, maxHeight: 200)
if viewModel.config.features.startupScreenEnabled {
VStack {
Button(action: { viewModel.router.back() }, label: {
CoreAssets.arrowLeft.swiftUIImage.renderingMode(.template)
.backButtonStyle(color: Theme.Colors.loginNavigationText)
})
.foregroundColor(Theme.Colors.styledButtonText)
BackNavigationButton(
color: Theme.Colors.loginNavigationText,
action: {
viewModel.router.back()
}
)
.backViewStyle()
.padding(.leading, isHorizontal ? 48 : 0)
.padding(.top, 11)
.accessibilityIdentifier("back_button")

}.frame(maxWidth: .infinity, alignment: .topLeading)
.padding(.top, isHorizontal ? 20 : 0)
Expand All @@ -50,117 +51,131 @@ public struct SignInView: View {
VStack(alignment: .center) {
ThemeAssets.appLogo.swiftUIImage
.resizable()
.frame(maxWidth: 189, maxHeight: 54)
.aspectRatio(contentMode: .fit)
.frame(maxWidth: 189, maxHeight: 89)
.padding(.top, isHorizontal ? 20 : 40)
.padding(.bottom, isHorizontal ? 10 : 40)
.accessibilityIdentifier("logo_image")

ScrollView {
VStack {
VStack(alignment: .leading) {
Text(AuthLocalization.SignIn.logInTitle)
.font(Theme.Fonts.displaySmall)
.foregroundColor(Theme.Colors.textPrimary)
.padding(.bottom, 4)
.accessibilityIdentifier("signin_text")
Text(AuthLocalization.SignIn.welcomeBack)
.font(Theme.Fonts.titleSmall)
.foregroundColor(Theme.Colors.textPrimary)
.padding(.bottom, 20)
.accessibilityIdentifier("welcome_back_text")

Text(AuthLocalization.SignIn.emailOrUsername)
.font(Theme.Fonts.labelLarge)
.foregroundColor(Theme.Colors.textPrimary)
.accessibilityIdentifier("username_text")
TextField(AuthLocalization.SignIn.emailOrUsername, text: $email)
.keyboardType(.emailAddress)
.textContentType(.emailAddress)
.autocapitalization(.none)
.autocorrectionDisabled()
.padding(.all, 14)
.background(
Theme.Shapes.textInputShape
.fill(Theme.Colors.textInputBackground)
)
.overlay(
Theme.Shapes.textInputShape
.stroke(lineWidth: 1)
.fill(Theme.Colors.textInputStroke)
)
.accessibilityIdentifier("username_textfield")

Text(AuthLocalization.SignIn.password)
.font(Theme.Fonts.labelLarge)
.foregroundColor(Theme.Colors.textPrimary)
.padding(.top, 18)
.accessibilityIdentifier("password_text")
SecureField(AuthLocalization.SignIn.password, text: $password)
.padding(.all, 14)
.background(
Theme.Shapes.textInputShape
.fill(Theme.Colors.textInputBackground)
)
.overlay(
Theme.Shapes.textInputShape
.stroke(lineWidth: 1)
.fill(Theme.Colors.textInputStroke)
)
.accessibilityIdentifier("password_textfield")
HStack {
if !viewModel.config.features.startupScreenEnabled {
Button(CoreLocalization.SignIn.registerBtn) {
viewModel.router.showRegisterScreen(sourceScreen: viewModel.sourceScreen)
GeometryReader { proxy in
ScrollView {
VStack {
VStack(alignment: .leading) {
Text(AuthLocalization.SignIn.logInTitle)
.font(Theme.Fonts.displaySmall)
.foregroundColor(Theme.Colors.textPrimary)
.padding(.bottom, 4)
.accessibilityIdentifier("signin_text")
Text(AuthLocalization.SignIn.welcomeBack)
.font(Theme.Fonts.titleSmall)
.foregroundColor(Theme.Colors.textPrimary)
.padding(.bottom, 20)
.accessibilityIdentifier("welcome_back_text")
Text(AuthLocalization.SignIn.emailOrUsername)
.font(Theme.Fonts.labelLarge)
.foregroundColor(Theme.Colors.textPrimary)
.accessibilityIdentifier("username_text")
TextField("", text: $email)
.font(Theme.Fonts.bodyLarge)
.foregroundColor(Theme.Colors.textInputTextColor)
.keyboardType(.emailAddress)
.textContentType(.emailAddress)
.autocapitalization(.none)
.autocorrectionDisabled()
.padding(.all, 14)
.background(
Theme.InputFieldBackground(
placeHolder: AuthLocalization.SignIn.emailOrUsername,
text: email,
padding: 15
)
)
.overlay(
Theme.Shapes.textInputShape
.stroke(lineWidth: 1)
.fill(Theme.Colors.textInputStroke)
)
.accessibilityIdentifier("username_textfield")

Text(AuthLocalization.SignIn.password)
.font(Theme.Fonts.labelLarge)
.foregroundColor(Theme.Colors.textPrimary)
.padding(.top, 18)
.accessibilityIdentifier("password_text")
SecureField("", text: $password)
.font(Theme.Fonts.bodyLarge)
.foregroundColor(Theme.Colors.textInputTextColor)
.padding(.all, 14)
.background(
Theme.InputFieldBackground(
placeHolder: AuthLocalization.SignIn.password,
text: password,
padding: 15
)
)
.overlay(
Theme.Shapes.textInputShape
.stroke(lineWidth: 1)
.fill(Theme.Colors.textInputStroke)
)
.accessibilityIdentifier("password_textfield")
HStack {
if !viewModel.config.features.startupScreenEnabled {
Button(CoreLocalization.register) {
viewModel.router.showRegisterScreen(sourceScreen: viewModel.sourceScreen)
}
.foregroundColor(Theme.Colors.accentColor)
.accessibilityIdentifier("register_button")

Spacer()
}
.foregroundColor(Theme.Colors.accentColor)
.accessibilityIdentifier("register_button")

Spacer()
Button(AuthLocalization.SignIn.forgotPassBtn) {
viewModel.trackForgotPasswordClicked()
viewModel.router.showForgotPasswordScreen()
}
.font(Theme.Fonts.bodyLarge)
.foregroundColor(Theme.Colors.infoColor)
.padding(.top, 0)
.accessibilityIdentifier("forgot_password_button")
}

Button(AuthLocalization.SignIn.forgotPassBtn) {
viewModel.trackForgotPasswordClicked()
viewModel.router.showForgotPasswordScreen()

if viewModel.isShowProgress {
HStack(alignment: .center) {
ProgressBar(size: 40, lineWidth: 8)
.padding(20)
.accessibilityIdentifier("progressbar")
}.frame(maxWidth: .infinity)
} else {
StyledButton(CoreLocalization.SignIn.logInBtn) {
Task {
await viewModel.login(username: email, password: password)
}
}
.frame(maxWidth: .infinity)
.padding(.top, 40)
.accessibilityIdentifier("signin_button")
}
.foregroundColor(Theme.Colors.accentColor)
.padding(.top, 0)
.accessibilityIdentifier("forgot_password_button")
}

if viewModel.isShowProgress {
HStack(alignment: .center) {
ProgressBar(size: 40, lineWidth: 8)
.padding(20)
.accessibilityIdentifier("progressbar")
}.frame(maxWidth: .infinity)
} else {
StyledButton(CoreLocalization.SignIn.logInBtn) {
Task {
await viewModel.login(username: email, password: password)
if viewModel.socialAuthEnabled {
SocialAuthView(
viewModel: .init(
config: viewModel.config
) { result in
Task { await viewModel.login(with: result) }
}
}
.frame(maxWidth: .infinity)
.padding(.top, 40)
.accessibilityIdentifier("signin_button")
)
}
agreements
Spacer()
}
if viewModel.socialAuthEnabled {
SocialAuthView(
viewModel: .init(
config: viewModel.config
) { result in
Task { await viewModel.login(with: result) }
}
)
}
agreements
Spacer()
.padding(.horizontal, 24)
.padding(.top, 50)
.frameLimit(width: proxy.size.width)
}
.padding(.horizontal, 24)
.padding(.top, 50)
}.roundedBackground(Theme.Colors.loginBackground)
.roundedBackground(Theme.Colors.loginBackground)
.scrollAvoidKeyboard(dismissKeyboardByTap: true)

}
}

// MARK: - Alert
Expand All @@ -186,7 +201,6 @@ public struct SignInView: View {
VStack {
Spacer()
SnackBarView(message: viewModel.errorMessage)
.accessibilityLabel("error_snackbar")
}.transition(.move(edge: .bottom))
.onAppear {
doAfter(Theme.Timeout.snackbarMessageLongTimeout) {
Expand Down Expand Up @@ -214,8 +228,8 @@ public struct SignInView: View {
policy
)
Text(.init(text))
.tint(Theme.Colors.accentColor)
.foregroundStyle(Theme.Colors.textSecondary)
.tint(Theme.Colors.infoColor)
.foregroundStyle(Theme.Colors.textSecondaryLight)
.font(Theme.Fonts.labelSmall)
.padding(.top, viewModel.socialAuthEnabled ? 0 : 15)
.padding(.bottom, 15)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,11 +75,11 @@ public class SignInViewModel: ObservableObject {
errorMessage = AuthLocalization.Error.invalidPasswordLenght
return
}

analytics.userSignInClicked()
isShowProgress = true
do {
let user = try await interactor.login(username: username, password: password)
analytics.setUserID("\(user.id)")
analytics.identify(id: "\(user.id)", username: user.username, email: user.email)
analytics.userLogin(method: .password)
router.showMainOrWhatsNewScreen(sourceScreen: sourceScreen)
} catch let error {
Expand Down Expand Up @@ -110,7 +110,7 @@ public class SignInViewModel: ObservableObject {
isShowProgress = true
do {
let user = try await interactor.login(externalToken: externalToken, backend: backend)
analytics.setUserID("\(user.id)")
analytics.identify(id: "\(user.id)", username: user.username, email: user.email)
analytics.userLogin(method: authMethod)
router.showMainOrWhatsNewScreen(sourceScreen: sourceScreen)
} catch let error {
Expand Down
Loading

0 comments on commit 64b1c0e

Please sign in to comment.