-
Notifications
You must be signed in to change notification settings - Fork 3
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
Add email login and remove phone login #81
Conversation
WalkthroughThe pull request introduces enhancements to the Splito application by adding email-based login functionality. Key changes include modifying the Changes
Possibly related PRs
Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media? 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 12
🧹 Outside diff range and nitpick comments (6)
Splito/UI/Login/EmailLogin/EmailLoginViewModel.swift (2)
73-79
: Remove commented codeThe
onLoginSuccess
method contains commented out code that should be either implemented or removed.
89-91
: Remove empty method or add implementationThe
onEditingChanged
method is empty and has a poorly named parameterabc
.Either remove this method if unused or implement it with proper parameter naming.
Splito/UI/Onboard/OnboardRouteView.swift (1)
Remove phone login routes and their associated files
Based on the search results, we found multiple references to phone login functionality across the codebase:
- Route definitions in
AppRoute.swift
(both in Splito/UI and Data/Data)- View and ViewModel implementations in:
Splito/UI/Login/PhoneLogin/PhoneLoginView.swift
Splito/UI/Login/PhoneLogin/PhoneLoginViewModel.swift
- Navigation logic in
LoginViewModel.swift
- Route handling in
OnboardRouteView.swift
All these files need to be updated or removed to completely eliminate phone login functionality.
🔗 Analysis chain
Line range hint
23-23
: Remove phone login related routesSince the PR aims to remove phone login functionality, we should remove:
- The
.PhoneLoginView
case- The
.VerifyOTPView
caseLet's verify if these routes are referenced elsewhere:
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash # Search for references to phone login routes rg "PhoneLoginView|VerifyOTPView"Length of output: 3100
Splito/UI/Router/AppRoute.swift (1)
64-65
: Maintain consistent key casingThe key for
EmailLoginView
uses PascalCase while other keys use camelCase.- "EmailLoginView" + "emailLoginView"Splito/UI/Login/EmailLogin/EmailLoginView.swift (1)
34-35
: Add loading state handling to PrimaryButtonThe button's loading state (
showLoader
) is bound but there's no visual feedback during the loading state. Consider disabling the button when loading.-PrimaryButton(text: "Sign in", isEnabled: !viewModel.email.isEmpty && !viewModel.password.isEmpty, - showLoader: viewModel.showLoader, onClick: viewModel.onEmailLoginClick) +PrimaryButton(text: "Sign in", + isEnabled: !viewModel.email.isEmpty && !viewModel.password.isEmpty && !viewModel.showLoader, + showLoader: viewModel.showLoader, + onClick: viewModel.onEmailLoginClick)Splito/UI/Login/LoginViewModel.swift (1)
130-132
: Consider adding error handling for navigationThe email login navigation should handle potential routing errors.
func onEmailLoginClick() { - router.push(.EmailLoginView) + do { + try router.push(.EmailLoginView) + } catch { + LogE("LoginViewModel: Failed to navigate to EmailLoginView: \(error)") + alert = .init(message: "Navigation failed") + showAlert = true + } }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
📒 Files selected for processing (10)
Data/Data/Model/AppUser.swift
(1 hunks)Splito.xcodeproj/project.pbxproj
(6 hunks)Splito/Localization/Localizable.xcstrings
(4 hunks)Splito/UI/Home/Account/User Profile/UserProfileViewModel.swift
(1 hunks)Splito/UI/Login/EmailLogin/EmailLoginView.swift
(1 hunks)Splito/UI/Login/EmailLogin/EmailLoginViewModel.swift
(1 hunks)Splito/UI/Login/LoginView.swift
(2 hunks)Splito/UI/Login/LoginViewModel.swift
(1 hunks)Splito/UI/Onboard/OnboardRouteView.swift
(1 hunks)Splito/UI/Router/AppRoute.swift
(2 hunks)
🔇 Additional comments (7)
Splito.xcodeproj/project.pbxproj (2)
369-377
: LGTM: EmailLogin group structure is well-organized.
The new EmailLogin group is properly structured within the project hierarchy, maintaining a clean separation of concerns by grouping related files together.
179-180
: LGTM: New email login files are properly integrated.
The EmailLoginView.swift and EmailLoginViewModel.swift files are correctly:
- Referenced in PBXFileReference section
- Added to the compilation phase
- Included in the project's source files
Also applies to: 1081-1081, 1135-1135
Splito/UI/Login/LoginView.swift (1)
71-71
: Email login button implementation looks good
The email login button is well-implemented with appropriate styling and icon choice, maintaining consistency with other login options.
Data/Data/Model/AppUser.swift (2)
70-70
: LGTM: Email login type addition
The Email case is correctly added to the LoginType enum.
69-69
:
Remove phone login related code
Since the PR aims to remove phone login functionality, we should also remove:
- The
Phone
case fromLoginType
enum - Consider deprecating
phoneNumber
field inAppUser
struct if it's no longer needed
Let's verify if phone login is still used elsewhere:
Splito/UI/Onboard/OnboardRouteView.swift (1)
29-30
: LGTM: Email login route addition
The EmailLoginView route is correctly added to the switch statement.
Splito/Localization/Localizable.xcstrings (1)
308-309
: LGTM: Email login localization strings
The new localization strings for email login functionality are properly structured and follow the existing pattern.
Also applies to: 371-372, 551-552, 987-988, 990-991
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Outside diff range and nitpick comments (3)
Splito/UI/Login/LoginViewModel.swift (2)
130-132
: LGTM! Consider adding loading state management.The email login navigation implementation is clean and follows the existing routing pattern. However, for consistency with Google and Apple login implementations, consider adding loading state management.
+ @Published private(set) var showEmailLoading = false + func onEmailLoginClick() { + showEmailLoading = true router.push(.EmailLoginView) }
Line range hint
1-150
: Consider standardizing authentication method implementations.The authentication methods in this view model show inconsistent patterns:
- Google/Apple login methods handle loading states and errors
- Email login doesn't handle loading states
- Different error handling approaches
Consider creating a standard protocol or base implementation for all authentication methods to ensure consistent behavior and maintainability.
Example approach:
protocol AuthenticationMethod { var isLoading: Bool { get set } func authenticate() async throws func handleError(_ error: Error) }Splito/UI/Login/LoginView.swift (1)
Line range hint
70-71
: Update login options UI to reflect the transition to email loginThe phone login button needs to be removed and replaced with the email login button to complete the transition.
Apply this diff to update the login options:
LoginOptionsButtonView(systemImage: ("apple.logo", primaryText, (14, 16)), buttonName: "Sign in with Apple", showLoader: showAppleLoading, onClick: onAppleLoginClick) - LoginOptionsButtonView(systemImage: ("phone.fill", primaryLightText, (12, 12)), - buttonName: "Sign in with Phone Number", bgColor: primaryColor, - buttonTextColor: primaryLightText, showLoader: false, onClick: onPhoneLoginClick) + LoginOptionsButtonView(systemImage: ("envelope.fill", primaryLightText, (12, 12)), + buttonName: "Sign in with E-mail", bgColor: primaryColor, + buttonTextColor: primaryLightText, showLoader: false, onClick: onEmailLoginClick)
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
📒 Files selected for processing (3)
Splito/Localization/Localizable.xcstrings
(4 hunks)Splito/UI/Login/LoginView.swift
(2 hunks)Splito/UI/Login/LoginViewModel.swift
(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- Splito/Localization/Localizable.xcstrings
🔇 Additional comments (4)
Splito/UI/Login/LoginViewModel.swift (1)
134-136
:
Remove phone login method as per PR objectives.
According to the PR objective to "remove phone login", this method should be removed.
- func onPhoneLoginClick() {
- router.push(.PhoneLoginView)
- }
Splito/UI/Login/LoginView.swift (3)
43-44
:
Remove phone login parameter as per PR objectives
The PR aims to remove phone login, but onPhoneLoginClick
parameter is still present. This is inconsistent with the PR objectives.
Apply this diff to align with PR objectives:
LoginOptionsView(showGoogleLoading: viewModel.showGoogleLoading,
showAppleLoading: viewModel.showAppleLoading,
onGoogleLoginClick: viewModel.onGoogleLoginClick,
onAppleLoginClick: viewModel.onAppleLoginClick,
- onPhoneLoginClick: viewModel.onPhoneLoginClick,
onEmailLoginClick: viewModel.onEmailLoginClick)
43-44
: Verify complete removal of phone login across the codebase
Several files still contain phone login related code that needs to be removed for consistency.
Also applies to: 64-64, 70-71
64-64
:
LGTM on email login property addition, but phone login property needs removal
The email login property is correctly added, but the phone login property still needs to be removed to complete the transition.
Apply this diff to complete the transition:
let onGoogleLoginClick: () -> Void
let onAppleLoginClick: () -> Void
- let onPhoneLoginClick: () -> Void
let onEmailLoginClick: () -> Void
Likely invalid or redundant comment.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Outside diff range and nitpick comments (2)
Splito/UI/Login/EmailLogin/EmailLoginViewModel.swift (1)
90-92
: Implement the forgot password functionalityThe
onForgotPasswordClick()
method is currently empty. Implementing this feature will enhance the user experience by allowing users to reset their passwords if they forget them.Here’s a suggested implementation:
func onForgotPasswordClick() { guard !email.isEmpty else { alert = .init(message: "Please enter your email address to reset your password.") showAlert = true return } FirebaseAuth.Auth.auth().sendPasswordReset(withEmail: email) { [weak self] error in guard let self else { return } if let error = error { LogE("Error sending password reset email: \(error)") self.alert = .init(message: error.localizedDescription) self.showAlert = true } else { self.alert = .init(message: "Password reset email sent successfully.") self.showAlert = true } } }Splito/UI/Login/EmailLogin/EmailLoginView.swift (1)
100-117
: Disable autocorrection for email inputTo improve user experience, consider disabling autocorrection for the email input field, as email addresses may not benefit from autocorrection.
Apply this diff to the
EmailFieldView
:TextField("Enter your email", text: $email) .font(.subTitle3()) .foregroundStyle(primaryText) .tint(primaryColor) .autocapitalization(.none) + .disableAutocorrection(true) .keyboardType(.emailAddress)
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
⛔ Files ignored due to path filters (1)
Splito/Resource/Assets.xcassets/Images/Login/EmailIcon.imageset/email_svgrepo.com.svg
is excluded by!**/*.svg
📒 Files selected for processing (6)
Splito/Localization/Localizable.xcstrings
(5 hunks)Splito/Resource/Assets.xcassets/Images/Login/EmailIcon.imageset/Contents.json
(1 hunks)Splito/UI/Login/EmailLogin/EmailLoginView.swift
(1 hunks)Splito/UI/Login/EmailLogin/EmailLoginViewModel.swift
(1 hunks)Splito/UI/Login/LoginView.swift
(3 hunks)Splito/UI/Login/PhoneLogin/PhoneLoginView.swift
(0 hunks)
💤 Files with no reviewable changes (1)
- Splito/UI/Login/PhoneLogin/PhoneLoginView.swift
✅ Files skipped from review due to trivial changes (1)
- Splito/Resource/Assets.xcassets/Images/Login/EmailIcon.imageset/Contents.json
🚧 Files skipped from review as they are similar to previous changes (2)
- Splito/UI/Login/LoginView.swift
- Splito/Localization/Localizable.xcstrings
🔇 Additional comments (3)
Splito/UI/Login/EmailLogin/EmailLoginViewModel.swift (2)
30-51
: Add input validation before creating a user account
As previously suggested, the onCreateAccountClick()
method should validate the email format and password strength before attempting authentication. This helps prevent unnecessary network calls and improves user experience.
53-74
: Add input validation before attempting login
Echoing earlier recommendations, please add input validation to ensure the email is in the correct format and the password meets security requirements before calling the authentication API.
Splito/UI/Login/EmailLogin/EmailLoginView.swift (1)
95-117
: Add email format validation
As previously noted, adding validation to the email field ensures that only valid email addresses are processed, enhancing the reliability of the login process.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Outside diff range and nitpick comments (1)
Splito/UI/Login/EmailLogin/EmailLoginView.swift (1)
17-83
: Consider extracting view components for better maintainabilityThe view hierarchy is quite nested with multiple groups and stacks. Consider extracting some of these into separate view components:
- Input form section
- Button section
- Alert section
struct EmailLoginView: View { // ... existing properties ... var body: some View { GeometryReader { proxy in VStack(alignment: .leading, spacing: 0) { ScrollView { VStack(alignment: .leading, spacing: 0) { AppLogoView(geometry: .constant(proxy)) - Group { - // ... current implementation ... - } + LoginFormSection(viewModel: viewModel, focusedField: $focusedField) + ButtonSection(viewModel: viewModel) } } } } // ... remaining modifiers ... } } + private struct LoginFormSection: View { + @ObservedObject var viewModel: EmailLoginViewModel + @FocusState var focusedField: EmailLoginViewModel.EmailLoginField? + // ... extract form fields here ... + }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
📒 Files selected for processing (3)
Splito/Localization/Localizable.xcstrings
(7 hunks)Splito/UI/Login/EmailLogin/EmailLoginView.swift
(1 hunks)Splito/UI/Login/EmailLogin/EmailLoginViewModel.swift
(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
- Splito/Localization/Localizable.xcstrings
- Splito/UI/Login/EmailLogin/EmailLoginViewModel.swift
🔇 Additional comments (5)
Splito/UI/Login/EmailLogin/EmailLoginView.swift (5)
11-16
: LGTM! Well-structured view setup
The view follows SwiftUI best practices with proper state management using @StateObject for the view model and @focusstate for input focus management.
52-53
:
Add input validation before enabling login
The login button is enabled solely based on non-empty fields. Consider adding proper validation before enabling the login button.
PrimaryButton(
text: "Login",
- isEnabled: !viewModel.email.isEmpty && !viewModel.password.isEmpty,
+ isEnabled: viewModel.isValidEmail && viewModel.isValidPassword,
showLoader: viewModel.isLoginInProgress,
onClick: viewModel.onEmailLoginClick
)
85-115
:
Implement real-time email validation
While the field has proper keyboard settings, it lacks real-time validation feedback. Consider adding visual indicators for email validity.
+ @State private var isValidEmail: Bool = false
TextField("Enter your email", text: $email)
// ... existing modifiers ...
+ .onChange(of: email) { newValue in
+ isValidEmail = viewModel.validateEmail(newValue)
+ }
+ .overlay {
+ RoundedRectangle(cornerRadius: 12)
+ .stroke(isValidEmail ? successColor : outlineColor, lineWidth: 1)
+ }
117-160
:
Enhance password field security features
While the password visibility toggle is implemented well, consider adding:
- Password strength indicators
- Minimum length requirement
- Visual feedback for password complexity
+ @State private var passwordStrength: PasswordStrength = .weak
ZStack(alignment: .trailing) {
// ... existing password field ...
+ VStack(alignment: .leading, spacing: 4) {
+ PasswordStrengthIndicator(strength: passwordStrength)
+ Text(passwordStrength.hint)
+ .font(.caption)
+ .foregroundColor(secondaryText)
+ }
}
.onChange(of: password) { newValue in
+ passwordStrength = viewModel.calculatePasswordStrength(newValue)
}
1-160
: Verify secure handling of sensitive data
Ensure that sensitive data (email/password) is not being logged or exposed in debug information.
✅ Verification successful
Based on the search results, I can see that the codebase uses a structured logging system (DDLogger) with different log levels (LogD, LogE, LogI, LogW) and there are no instances of directly logging sensitive data like email or password in the EmailLoginView.swift or related view models. The sensitive fields are only used for authentication purposes and are not logged.
No sensitive data exposure found in login implementation
The email and password fields are properly handled:
- Input fields are only used for authentication
- No debug logging of credentials
- Password field properly implements secure text entry
- Login operations use secure Firebase Auth methods
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Search for potential logging statements or print debugging that might expose sensitive data
rg -i "print|debug|log" --type swift
Length of output: 73602
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
🧹 Outside diff range and nitpick comments (3)
BaseStyle/BaseStyle/CustomUI/Buttons/PrimaryFloatingButton.swift (1)
20-22
: Consider improving parameter organizationWhile the initialization is functionally correct, the parameter organization could be improved for better readability and maintenance.
Consider grouping related parameters:
-public init(text: String, bottomPadding: CGFloat = 24, textColor: Color = primaryLightText, - bgColor: Color = primaryColor, isEnabled: Bool = true, - showLoader: Bool = false, onClick: (() -> Void)? = nil) +public init( + text: String, + // Style parameters + textColor: Color = primaryLightText, + bgColor: Color = primaryColor, + bottomPadding: CGFloat = 24, + // State parameters + isEnabled: Bool = true, + showLoader: Bool = false, + onClick: (() -> Void)? = nil +)Splito/UI/Login/EmailLogin/EmailLoginView.swift (2)
11-74
: Add accessibility labels to improve user experienceThe view implements a clean MVVM structure, but lacks accessibility labels which are crucial for users with screen readers.
Add accessibility modifiers to key interactive elements:
AppLogoView(geometry: .constant(proxy)) + .accessibilityLabel("App Logo") LoginTitleView(titleText: "Continue your journey") + .accessibilityAddTraits(.isHeader) PrimaryFloatingButton(text: "Login"...) + .accessibilityHint("Tap to sign in with email")
159-175
: Add loading state to forgot password buttonThe forgot password button should show a loading state while processing the request.
Add loading state:
Button(action: onForgotPasswordClick) { + if isLoading { + ProgressView() + .progressViewStyle(CircularProgressViewStyle()) + } else { Text("Forgot password?") .font(.caption1()) .foregroundStyle(disableText) + } } +.disabled(isLoading)
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
⛔ Files ignored due to path filters (2)
Splito/Resource/Assets.xcassets/Images/Login/LoginAppLogo.imageset/logo.svg
is excluded by!**/*.svg
Splito/Resource/Assets.xcassets/Images/Login/LoginAppLogo.imageset/user.svg
is excluded by!**/*.svg
📒 Files selected for processing (5)
BaseStyle/BaseStyle/CustomUI/Buttons/PrimaryFloatingButton.swift
(1 hunks)Splito/Localization/Localizable.xcstrings
(5 hunks)Splito/Resource/Assets.xcassets/Images/Login/LoginAppLogo.imageset/Contents.json
(1 hunks)Splito/UI/Login/EmailLogin/EmailLoginView.swift
(1 hunks)Splito/UI/Login/LoginView.swift
(6 hunks)
✅ Files skipped from review due to trivial changes (1)
- Splito/Resource/Assets.xcassets/Images/Login/LoginAppLogo.imageset/Contents.json
🚧 Files skipped from review as they are similar to previous changes (1)
- Splito/UI/Login/LoginView.swift
🔇 Additional comments (4)
BaseStyle/BaseStyle/CustomUI/Buttons/PrimaryFloatingButton.swift (1)
Line range hint 31-42
: Verify gradient background compatibility
The FloatingButtonGradientBackground
uses a fixed surfaceColor
. Ensure this doesn't conflict with the new color customization feature.
✅ Verification successful
Let me gather more information about the gradient background implementation.
Let me check the color customization implementation to understand how it interacts with surfaceColor.
Let me check the implementation of the FloatingButtonGradientBackground specifically.
The gradient background implementation is safe with color customization
The FloatingButtonGradientBackground
uses surfaceColor
which is defined as Color.surface
in AppColors.swift
. This is a system-level color that automatically adapts to theme changes, making it compatible with any color customization feature. The gradient implementation creates a fade-out effect using opacity variations of the same surface color, which ensures consistent theming behavior.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Search for other usages of PrimaryFloatingButton to ensure
# the gradient background works well with different color combinations
rg -l "PrimaryFloatingButton" | xargs rg -A 5 "PrimaryFloatingButton.*init"
Length of output: 345
Script:
#!/bin/bash
# Search for FloatingButtonGradientBackground implementation
ast-grep --pattern 'struct FloatingButtonGradientBackground {
$$$
}'
# Also search for any usage of surfaceColor in the codebase
rg "surfaceColor"
Length of output: 4111
Script:
#!/bin/bash
# Search for Color.surface definition and any color customization related code
rg "Color\.surface"
# Check for any color theme or style configuration
ast-grep --pattern 'struct $_ {
$$$
Color $$$
}'
Length of output: 161
Script:
#!/bin/bash
# Search for the full implementation of FloatingButtonGradientBackground
rg -A 10 "FloatingButtonGradientBackground"
# Also check if there are any color theme or style protocols that might affect surface color
rg "protocol.*Style|protocol.*Theme"
Length of output: 1170
Splito/UI/Login/EmailLogin/EmailLoginView.swift (2)
76-86
:
Add email validation before focus transition
The email field should validate the email format before transitioning focus to the password field.
88-96
:
Add password validation requirements
The password field lacks validation for minimum security requirements.
Splito/Localization/Localizable.xcstrings (1)
286-288
: LGTM: Localization strings are properly configured
All new strings for the email login feature are properly added with consistent formatting and manual extraction state.
Also applies to: 292-293, 397-398, 493-495, 737-739, 743-745
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 4
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
📒 Files selected for processing (4)
BaseStyle/BaseStyle/CustomUI/Buttons/PrimaryFloatingButton.swift
(2 hunks)Splito/Localization/Localizable.xcstrings
(16 hunks)Splito/UI/Login/EmailLogin/EmailLoginView.swift
(1 hunks)Splito/UI/Login/EmailLogin/EmailLoginViewModel.swift
(1 hunks)
🔇 Additional comments (5)
BaseStyle/BaseStyle/CustomUI/Buttons/PrimaryFloatingButton.swift (3)
14-15
: LGTM! Property declarations follow Swift best practices.
The new color properties are properly encapsulated and follow Swift naming conventions.
20-26
: LGTM! Well-structured initializer with semantic defaults.
The initializer is properly updated with the new color parameters, using meaningful default values and maintaining good parameter organization.
36-37
: LGTM! Color properties are now properly utilized.
The implementation correctly passes the color properties to the PrimaryButton, resolving the previous review comment about unused properties.
Splito/UI/Login/EmailLogin/EmailLoginView.swift (1)
33-35
: Add real-time input validation and visual feedback
Consider adding real-time validation for the email and password fields to provide immediate feedback to users as they input their credentials.
Implement .onChange
modifiers to validate inputs and display visual cues for invalid entries. This enhances usability and helps users correct errors before submission.
Also applies to: 39-40
Splito/Localization/Localizable.xcstrings (1)
782-785
: Verify the correctness of updated sign-in option strings
It appears that the strings for "Sign in with Email" and "Sign in with Google" have been modified. Please verify that these changes align with the intended functionality and that the correct strings are displayed in the app.
Run the following script to check the usage of these strings in the codebase:
This will help ensure that the strings are correctly referenced and displayed in the appropriate contexts.
✅ Verification successful
Sign-in option strings are correctly used and aligned with functionality
The verification confirms that both strings "Sign in with Email" and "Sign in with Google" are properly used in the login interface (LoginView.swift) and are correctly defined in the localization file (Localizable.xcstrings). The strings are consistently used as button names in the LoginOptionsButtonView components.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Verify the usage of sign-in option strings in the codebase.
# Search for usage of "Sign in with Email"
rg 'NSLocalizedString\("Sign in with Email",'
# Search for usage of "Sign in with Google"
rg 'NSLocalizedString\("Sign in with Google",'
Length of output: 96
Script:
#!/bin/bash
# Let's try a broader search for these strings in Swift files, considering different string usage patterns
# Search for "Sign in with Email" string
echo "=== Searching for 'Sign in with Email' ==="
rg -t swift "Sign in with Email"
# Search for "Sign in with Google" string
echo -e "\n=== Searching for 'Sign in with Google' ==="
rg -t swift "Sign in with Google"
# Also check for any localization-related files
echo -e "\n=== Checking Localization files ==="
fd -e strings -e stringsdict -e xcstrings -x cat {}
Length of output: 26837
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Outside diff range and nitpick comments (3)
Data/Data/Store/UserStore.swift (1)
Line range hint
1-85
: Consider implementing caching for better performance.Since this store is crucial for user authentication and profile management, consider implementing a local cache to:
- Reduce Firebase reads
- Improve app performance
- Handle offline scenarios better
You could use:
- Memory cache for active session
- Disk cache (e.g., UserDefaults or Core Data) for persistence
Would you like me to provide an example implementation of caching strategy for this store?
Data/Data/Repository/UserRepository.swift (2)
21-22
: Important fix: Properly awaiting async user additionThe addition of
await
ensures the async operation completes before returning. This is a critical fix that prevents potential race conditions. The debug logging is also a good addition for tracking new user creation.Consider adding error logging in a catch block to track failed user additions:
} else { LogD("User does not exist. Adding new user: \(user)") - try await store.addUser(user: user) + do { + try await store.addUser(user: user) + } catch { + LogE("Failed to add new user: \(error)") + throw error + } return user }
Line range hint
47-56
: Critical: Fix potential image URL loss and simplify logicThere are several issues in this method:
- When
newImageUrl
is nil, it incorrectly setsnewUser.imageUrl = newImageUrl
, discarding the current image URL- The if and else branches perform identical operations, making the condition redundant
- The image deletion is performed before ensuring the new image operation succeeds
Consider this safer implementation:
public func updateUserWithImage(imageData: Data?, newImageUrl: String?, user: AppUser) async throws -> AppUser { var newUser = user - if let currentUrl = user.imageUrl, newImageUrl == nil { - newUser.imageUrl = newImageUrl + if let currentUrl = user.imageUrl { + if newImageUrl == nil { + // Only delete the current image if we're explicitly removing it + try await storageManager.deleteImage(imageUrl: currentUrl) + } + } - _ = try await storageManager.deleteImage(imageUrl: currentUrl) - return try await performImageAction(imageData: imageData, user: newUser) - } else { - return try await performImageAction(imageData: imageData, user: newUser) - } + newUser.imageUrl = newImageUrl + return try await performImageAction(imageData: imageData, user: newUser) }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
📒 Files selected for processing (3)
Data/Data/Repository/UserRepository.swift
(1 hunks)Data/Data/Store/UserStore.swift
(1 hunks)Splito/UI/Login/EmailLogin/EmailLoginViewModel.swift
(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- Splito/UI/Login/EmailLogin/EmailLoginViewModel.swift
🔇 Additional comments (3)
Data/Data/Store/UserStore.swift (2)
37-44
: LGTM! Enhanced error handling and logging implementation.
The changes improve the robustness of the fetchUserBy
method by:
- Adding explicit existence check for the snapshot
- Including detailed logging for both success and failure scenarios
- Properly handling non-existent documents
Line range hint 1-85
: Verify error handling consistency across authentication flow.
Since this is part of the new email login feature, ensure consistent error handling across the authentication flow.
✅ Verification successful
Based on the shell script results, I can now generate the final response as there is sufficient evidence to verify the error handling consistency across the authentication flow.
Error handling is consistent across authentication flow with proper logging and user feedback.
- All authentication methods (email, phone, Google, Apple) follow consistent error handling patterns:
- Specific error cases are handled with user-friendly messages
- All errors are logged with
LogE
and proper context - User feedback is provided via alerts/toasts
- Loading states are properly managed
- Common error handling patterns observed:
- Firebase auth errors are handled with specific messages
- Network/server errors show appropriate fallback messages
- Input validation errors display field-specific guidance
- All sensitive operations (delete account, sign out) have proper error recovery
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Check error handling patterns in authentication-related files
# Look for error handling patterns in auth-related files
rg -A 3 "catch|throw|error|fail" --type swift
# Look for logging patterns in auth-related files
rg -A 2 "LogE|LogD" --type swift
# Find all auth-related view models to verify consistent error handling
ast-grep --pattern 'class $_LoginViewModel'
Length of output: 68702
Data/Data/Repository/UserRepository.swift (1)
18-18
: LGTM! Good addition of debug logging
The debug log provides valuable context about existing users in Firestore.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
🧹 Outside diff range and nitpick comments (1)
Splito/UI/Home/Account/User Profile/UserProfileViewModel.swift (1)
344-371
: Improve error handling and logging consistencyThe password prompt implementation is solid but has minor inconsistencies:
- Uses print instead of the established logging system
- Could improve error handling for the window scene lookup
Apply this diff to maintain consistency:
} else { - print("No active window scene found.") + LogE("UserProfileViewModel: \(#function) No active window scene found.") completion(nil) }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
📒 Files selected for processing (1)
Splito/UI/Home/Account/User Profile/UserProfileViewModel.swift
(2 hunks)
🔇 Additional comments (1)
Splito/UI/Home/Account/User Profile/UserProfileViewModel.swift (1)
264-266
: LGTM: Email authentication case properly integrated
The Email case is correctly added to the authentication flow, maintaining consistency with other authentication methods.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 3
🧹 Outside diff range and nitpick comments (7)
Splito/UI/Router/AppRoute.swift (1)
58-59
: Consider standardizing the key string format.The key string "EmailLoginView" differs from other keys that use camelCase (e.g., "loginView", "onboardView").
- "EmailLoginView" + "emailLoginView"Splito.xcodeproj/project.pbxproj (1)
Line range hint
1379-1380
: Consider updating the marketing versionThe app version is set to 1.0 with build number 10000000. Consider if this significant feature addition warrants a version bump.
Also applies to: 1433-1434
Splito/UI/Home/Groups/Add Member/JoinMemberView.swift (4)
Line range hint
30-34
: Consider extracting duplicated success callback logicThe success callback pattern is duplicated in both the text input view and the floating button. Consider extracting this into a single method in the view model to maintain DRY principles.
struct JoinMemberView: View { + private func handleSuccess(_ isSucceed: Bool) { + if isSucceed { dismiss() } + } // ... existing code ... - JoinMemberTextInputView(text: $viewModel.code, placeholder: "AF0R00", isFocused: $isFocused) { - viewModel.handleJoinMemberAction { isSucceed in - if isSucceed { dismiss() } - } + JoinMemberTextInputView(text: $viewModel.code, placeholder: "AF0R00", isFocused: $isFocused) { + viewModel.handleJoinMemberAction(handleSuccess) } // ... existing code ... - PrimaryFloatingButton(text: "Join", isEnabled: !viewModel.code.isEmpty, showLoader: viewModel.showLoader) { - viewModel.handleJoinMemberAction { isSucceed in - if isSucceed { dismiss() } - } + PrimaryFloatingButton(text: "Join", isEnabled: !viewModel.code.isEmpty, showLoader: viewModel.showLoader) { + viewModel.handleJoinMemberAction(handleSuccess) }Also applies to: 52-56
Line range hint
30-45
: Consider localizing hardcoded stringsThe text strings like "Enter the invite code", "AF0R00", and "Reach out to your friends..." should be moved to a localization file for better maintainability and internationalization support.
77-77
: Consider making CODE_TOTAL_CHARACTERS a public parameterThe hardcoded character limit might need to be configurable for different use cases since this is a public struct.
- private let CODE_TOTAL_CHARACTERS = 6 + private let codeLength: Int + + public init(text: Binding<String>, placeholder: String, codeLength: Int = 6, isFocused: FocusState<Bool>.Binding, onCodeChange: @escaping () -> Void) { + self._text = text + self.placeholder = placeholder + self.codeLength = codeLength + self.isFocused = isFocused + self.onCodeChange = onCodeChange + }
87-96
: Consider improving accessibilityThe view could benefit from improved accessibility support:
- Add accessibility identifier for testing
- Add accessibility label describing the purpose
- Consider adding accessibility hints about the expected format
TextField(placeholder.localized, text: $text) + .accessibilityIdentifier("joinGroupCodeInput") + .accessibilityLabel("Group invite code input") + .accessibilityHint("Enter the \(CODE_TOTAL_CHARACTERS) character invite code")Splito/UI/Home/Account/User Profile/UserProfileView.swift (1)
Line range hint
1-249
: Clean up phone-related remnants.The view still contains phone-related code despite the PR objective to remove phone login. This includes:
- Phone binding in UserDetailList
- Phone field in the profile options
- Phone-related navigation in the submit handler
Consider cleaning up these remnants to maintain code cleanliness and prevent confusion. Here's a suggested approach:
- Remove the phone binding:
private struct UserDetailList: View { @Binding var firstName: String @Binding var lastName: String @Binding var email: String - @Binding var phone: String @Binding var userLoginType: LoginType }
- Update the titles array:
var titles: [Binding<String>] { - [$firstName, $lastName, $phone, $email] + [$firstName, $lastName, $email] }
- Update the submit handler in UserProfileDataEditableTextField:
.onSubmit { if focused.wrappedValue == .firstName { focused.wrappedValue = .lastName } else if focused.wrappedValue == .lastName { - focused.wrappedValue = .phone - } else if focused.wrappedValue == .phone { focused.wrappedValue = .email } else if focused.wrappedValue == .email { focused.wrappedValue = .firstName } }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
📒 Files selected for processing (20)
BaseStyle/BaseStyle.xcodeproj/project.pbxproj
(0 hunks)BaseStyle/BaseStyle/CustomUI/OtpTextInputView.swift
(0 hunks)BaseStyle/BaseStyle/Extension/String+Extension.swift
(0 hunks)Data/Data.xcodeproj/project.pbxproj
(0 hunks)Data/Data/Model/AppUser.swift
(1 hunks)Data/Data/Model/Country.swift
(0 hunks)Data/Data/Repository/UserRepository.swift
(1 hunks)Splito.xcodeproj/project.pbxproj
(6 hunks)Splito/Localization/Localizable.xcstrings
(15 hunks)Splito/UI/Home/Account/User Profile/UserProfileView.swift
(1 hunks)Splito/UI/Home/Account/User Profile/UserProfileViewModel.swift
(3 hunks)Splito/UI/Home/Groups/Add Member/JoinMemberView.swift
(2 hunks)Splito/UI/Login/LoginView.swift
(6 hunks)Splito/UI/Login/LoginViewModel.swift
(1 hunks)Splito/UI/Login/PhoneLogin/PhoneLoginView.swift
(0 hunks)Splito/UI/Login/PhoneLogin/PhoneLoginViewModel.swift
(0 hunks)Splito/UI/Login/PhoneLogin/VerifyOtp/VerifyOtpView.swift
(0 hunks)Splito/UI/Login/PhoneLogin/VerifyOtp/VerifyOtpViewModel.swift
(0 hunks)Splito/UI/Onboard/OnboardRouteView.swift
(1 hunks)Splito/UI/Router/AppRoute.swift
(2 hunks)
💤 Files with no reviewable changes (9)
- BaseStyle/BaseStyle/Extension/String+Extension.swift
- BaseStyle/BaseStyle.xcodeproj/project.pbxproj
- Data/Data.xcodeproj/project.pbxproj
- Data/Data/Model/Country.swift
- BaseStyle/BaseStyle/CustomUI/OtpTextInputView.swift
- Splito/UI/Login/PhoneLogin/PhoneLoginViewModel.swift
- Splito/UI/Login/PhoneLogin/VerifyOtp/VerifyOtpViewModel.swift
- Splito/UI/Login/PhoneLogin/VerifyOtp/VerifyOtpView.swift
- Splito/UI/Login/PhoneLogin/PhoneLoginView.swift
🚧 Files skipped from review as they are similar to previous changes (5)
- Data/Data/Model/AppUser.swift
- Splito/UI/Login/LoginViewModel.swift
- Data/Data/Repository/UserRepository.swift
- Splito/UI/Login/LoginView.swift
- Splito/Localization/Localizable.xcstrings
🔇 Additional comments (8)
Splito/UI/Onboard/OnboardRouteView.swift (1)
25-26
: LGTM! Route handling for email login properly implemented.
The changes correctly integrate the new EmailLoginView into the routing logic, maintaining consistency with the router pattern.
Splito/UI/Router/AppRoute.swift (1)
19-19
: LGTM! AppRoute case properly added.
The EmailLoginView case follows the established naming convention.
Splito/UI/Home/Account/User Profile/UserProfileViewModel.swift (2)
28-28
: LGTM! Login type updated to reflect new authentication method.
The default login type correctly reflects the switch to email-based authentication.
305-326
:
Enhance security in email re-authentication.
The current implementation needs security improvements as previously identified.
Consider:
- Implement password complexity validation
- Add rate limiting for failed attempts
- Use secure error messages that don't reveal user existence
private func handleEmailLogin(completion: @escaping (AuthCredential?) -> Void) {
+ // Track failed attempts
+ let maxAttempts = 3
+ if failedAttempts >= maxAttempts {
+ showAlertFor(message: "Too many attempts. Please try again later.")
+ return
+ }
+
let alert = UIAlertController(title: "Re-authenticate",
message: "Please enter your password",
preferredStyle: .alert)
alert.addTextField { textField in
textField.placeholder = "Password"
textField.isSecureTextEntry = true
}
alert.addAction(UIAlertAction(title: "Cancel", style: .cancel) { _ in
self.isDeleteInProgress = false
})
alert.addAction(UIAlertAction(title: "Confirm", style: .default) { _ in
guard let password = alert.textFields?.first?.text,
+ password.count >= 8,
+ password.rangeOfCharacter(from: .uppercaseLetters) != nil,
+ password.rangeOfCharacter(from: .decimalDigits) != nil,
let email = self.preference.user?.emailId else {
self.isDeleteInProgress = false
- LogE("UserProfileViewModel: \(#function) No email found for email login.")
+ LogE("UserProfileViewModel: \(#function) Authentication failed.")
return
}
let credential = EmailAuthProvider.credential(withEmail: email, password: password)
completion(credential)
})
TopViewController.shared.topViewController()?.present(alert, animated: true)
}
Splito.xcodeproj/project.pbxproj (3)
361-369
: LGTM: EmailLogin group structure follows project conventions
The new EmailLogin group is properly organized within the Login section, maintaining a clean project structure.
175-176
: LGTM: New email login files are properly integrated
The EmailLoginView.swift and EmailLoginViewModel.swift files are:
- Correctly added to project references
- Included in the compile sources phase
- Follow MVVM pattern naming conventions
Also applies to: 1053-1053, 1104-1104
Line range hint 1246-1247
: Verify iOS deployment target compatibility
The project is configured with iOS 16.4 as the minimum deployment target. Ensure that the new email login implementation is compatible with this iOS version.
✅ Verification successful
Email login implementation is compatible with iOS 16.4
Based on the code analysis, the email login implementation uses standard SwiftUI components and APIs that are fully supported in iOS 16.4. The implementation uses basic SwiftUI views and controls like:
- TextField for email and password input
- ScrollView for content layout
- Button for actions
- Standard system images
- Basic SwiftUI modifiers
No iOS 16.4+ specific APIs or availability markers were found in the implementation.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Check for iOS version specific APIs in the email login files
# Search for potential iOS version specific APIs
rg -A 3 "@available|if #available|#if os\(" "EmailLoginView.swift" "EmailLoginViewModel.swift"
Length of output: 219
Script:
#!/bin/bash
# First, let's find the email login related files in the repository
fd -e swift -e m "EmailLogin|Login"
# Then, let's check the deployment target in the project file
rg "IPHONEOS_DEPLOYMENT_TARGET" "Splito.xcodeproj/project.pbxproj"
# Also check for any SwiftUI availability markers or iOS version checks
rg -l "@available|if #available|#if os\(" $(fd -e swift)
Length of output: 16509
Script:
#!/bin/bash
# Let's check the content of the email login files to verify iOS version compatibility
rg -A 5 "import.*SwiftUI|import.*UIKit|@main|struct.*View|class.*ViewModel" "Splito/UI/Login/EmailLogin/EmailLoginView.swift" "Splito/UI/Login/EmailLogin/EmailLoginViewModel.swift"
# Also check for any SwiftUI or UIKit APIs that might have version requirements
rg -A 3 "TextField|Button|NavigationView|List|ScrollView|Alert|Sheet|FullScreenCover|TextEditor|Toggle|Picker|DatePicker|ColorPicker|Map|Link|Menu|ProgressView|TabView|Form|Section|GroupBox|Label|Stepper|Slider|Image|VideoPlayer|ShareLink|PhotosPicker|NavigationStack|NavigationSplitView" "Splito/UI/Login/EmailLogin/EmailLoginView.swift"
Length of output: 4613
Splito/UI/Home/Account/User Profile/UserProfileView.swift (1)
135-135
: LGTM: Email field disablement logic is correct.
The logic to disable the email field only for Google login is appropriate, as Google-authenticated users shouldn't be able to modify their email.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
🧹 Outside diff range and nitpick comments (2)
Splito/UI/Home/Groups/Add Member/JoinMemberView.swift (2)
88-88
: Review the kerning value for readabilityA kerning value of 16 creates significant spacing between characters. Consider reducing this value to improve readability while maintaining visual separation.
- .kerning(16) + .kerning(8)
86-120
: Add accessibility improvementsConsider enhancing accessibility support:
- Add an accessibility label explaining this is an invite code input
- Consider adding an accessibility hint about the character limit
- Announce validation errors to VoiceOver users
public var body: some View { TextField(placeholder.localized, text: $text) + .accessibilityLabel("Group invite code input") + .accessibilityHint("Enter a \(CODE_TOTAL_CHARACTERS) character invite code") // ... existing modifiers ...
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
⛔ Files ignored due to path filters (1)
Splito/Resource/Assets.xcassets/Images/Login/EmailIcon.imageset/email_svgrepo.com.svg
is excluded by!**/*.svg
📒 Files selected for processing (2)
Splito/UI/Home/Groups/Add Member/JoinMemberView.swift
(2 hunks)Splito/UI/Login/EmailLogin/EmailLoginView.swift
(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- Splito/UI/Login/EmailLogin/EmailLoginView.swift
🔇 Additional comments (2)
Splito/UI/Home/Groups/Add Member/JoinMemberView.swift (2)
30-33
: LGTM! Clean integration of JoinMemberTextInputView
The replacement of OtpTextInputView with JoinMemberTextInputView is well implemented with proper state management and completion handling.
117-117
:
Replace UIKit-specific endEditing with SwiftUI focus management
Using UIApplication.shared.endEditing() is a UIKit-specific approach that might cause memory leaks.
- UIApplication.shared.endEditing()
+ isFocused.wrappedValue = false
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
🧹 Outside diff range and nitpick comments (2)
Splito/UI/Login/LoginViewModel.swift (1)
120-120
: Consider categorizing errors for better user feedback.While using a generic error message is good for security, consider categorizing common errors (e.g., network issues, validation errors) to provide more actionable feedback to users while still logging the detailed error for debugging.
- self.alert = .init(message: "Something went wrong! Please try after some time.") + let userMessage = error.isNetworkError ? "Please check your internet connection and try again." : + "Something went wrong! Please try after some time." + self.alert = .init(message: userMessage)Splito/UI/Home/Account/User Profile/UserProfileViewModel.swift (1)
Update required: Phone authentication remnants found in the codebase
The verification revealed inconsistencies that need to be addressed:
LoginType
enum inAppUser.swift
still includes thephone
caseFirebaseProvider
contains a reference tophoneAuthProvider
- The phone authentication setup needs to be removed since it's no longer used
🔗 Analysis chain
Line range hint
69-70
: Verify the login type transition across the codebaseThe transition from phone to email login requires verification of all login type references.
Also applies to: 28-28
Let me check the specific content of these files to better understand the context.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash # Description: Verify all references to LoginType cases # Check for any remaining references to .Phone case echo "Checking for .Phone references:" rg -l "\.Phone\b" --type swift # Check for any remaining phone authentication logic echo -e "\nChecking for phone authentication references:" rg -l "phoneAuth|verifyPhone|handlePhoneLogin" --type swift # Check for consistent casing in login type strings echo -e "\nChecking login type string values:" rg -l '"phone"|"email"|"apple"|"google"' --type swiftLength of output: 542
Script:
#!/bin/bash # Check the content of FirebaseProvider.swift for phone auth references echo "Content of FirebaseProvider.swift phone auth related code:" rg "phoneAuth|verifyPhone|handlePhoneLogin" -A 3 -B 3 Data/Data/Helper/Firebase/FirebaseProvider.swift # Check the content of EmailLoginView.swift and AppUser.swift for login type strings echo -e "\nContent of EmailLoginView.swift login type strings:" rg '"phone"|"email"|"apple"|"google"' -A 3 -B 3 Splito/UI/Login/EmailLogin/EmailLoginView.swift echo -e "\nContent of AppUser.swift login type strings:" rg '"phone"|"email"|"apple"|"google"' -A 3 -B 3 Data/Data/Model/AppUser.swiftLength of output: 1262
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
📒 Files selected for processing (8)
BaseStyle/BaseStyle/CustomUI/Buttons/PrimaryFloatingButton.swift
(2 hunks)Data/Data/Model/AppUser.swift
(1 hunks)Data/Data/Store/UserStore.swift
(1 hunks)Splito/UI/Home/Account/User Profile/UserProfileViewModel.swift
(3 hunks)Splito/UI/Home/Groups/Add Member/JoinMemberView.swift
(2 hunks)Splito/UI/Login/EmailLogin/EmailLoginView.swift
(1 hunks)Splito/UI/Login/EmailLogin/EmailLoginViewModel.swift
(1 hunks)Splito/UI/Login/LoginViewModel.swift
(2 hunks)
🚧 Files skipped from review as they are similar to previous changes (5)
- Data/Data/Store/UserStore.swift
- BaseStyle/BaseStyle/CustomUI/Buttons/PrimaryFloatingButton.swift
- Splito/UI/Login/EmailLogin/EmailLoginView.swift
- Splito/UI/Home/Groups/Add Member/JoinMemberView.swift
- Splito/UI/Login/EmailLogin/EmailLoginViewModel.swift
🔇 Additional comments (4)
Splito/UI/Login/LoginViewModel.swift (2)
130-132
: Verify EmailLoginView implementation.
The implementation looks good and aligns with the PR objectives. However, let's verify the dependencies are in place.
✅ Verification successful
Implementation and dependencies verified successfully
The verification confirms:
- EmailLoginView is implemented at
Splito/UI/Login/EmailLogin/EmailLoginView.swift
- Route case
EmailLoginView
is properly defined inAppRoute.swift
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Verify EmailLoginView exists and route is defined
# Check if EmailLoginView exists
echo "Checking for EmailLoginView implementation..."
fd -e swift "EmailLoginView.swift"
# Check if route is defined in AppRoute
echo "Checking route definition..."
rg "case EmailLoginView" -A 2
Length of output: 441
Line range hint 1-143
: Overall implementation review.
The changes successfully implement email login while removing phone login functionality. The implementation is clean and follows existing patterns. A few suggestions for completeness:
- Consider updating class documentation to reflect the supported login methods
- Ensure test coverage for the new email login path
- Consider adding analytics tracking for the new login method
Splito/UI/Home/Account/User Profile/UserProfileViewModel.swift (2)
28-28
: LGTM: Login type transition
The change from .Phone
to .Email
aligns with the PR objective to transition from phone to email login.
308-329
: Enhance security and validation in email authentication
While the implementation is functional, consider these security improvements:
- Avoid revealing whether an email exists in error messages
- Add password complexity validation
- Implement rate limiting for failed attempts
The previous review comment provided a detailed implementation suggestion that hasn't been addressed yet.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
🧹 Outside diff range and nitpick comments (2)
Splito/UI/Login/EmailLogin/EmailLoginView.swift (2)
177-181
: Improve forgot password functionalityAdd loading state and error handling for better user experience.
+ @State private var isLoading = false + - Button(action: onForgotPasswordClick) { + Button(action: { + isLoading = true + Task { + do { + try await onForgotPasswordClick() + } catch { + // Handle error + } + isLoading = false + } + }) { Text("Forgot password?") .font(.caption1()) .foregroundStyle(disableText) + .opacity(isLoading ? 0.5 : 1) + if isLoading { + ProgressView() + .progressViewStyle(CircularProgressViewStyle()) + } } + .disabled(isLoading)
13-13
: Consider implementing proper error handling in ViewModelThe view model should handle all possible error cases and provide appropriate feedback to the user.
The view model should implement proper error handling for:
- Network connectivity issues
- Invalid credentials
- Account existence verification
- Rate limiting
- Server errors
Would you like me to help create a comprehensive error handling implementation for the view model?
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
📒 Files selected for processing (4)
Data/Data/Model/AppUser.swift
(1 hunks)Splito/Localization/Localizable.xcstrings
(16 hunks)Splito/UI/Home/Account/User Profile/UserProfileViewModel.swift
(3 hunks)Splito/UI/Login/EmailLogin/EmailLoginView.swift
(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
- Data/Data/Model/AppUser.swift
- Splito/Localization/Localizable.xcstrings
🔇 Additional comments (7)
Splito/UI/Home/Account/User Profile/UserProfileViewModel.swift (4)
28-28
: LGTM: Login type change aligns with PR objectives
The change from .Phone
to .Email
as the default login type is consistent with the transition to email-based authentication.
256-260
: Remove redundant phone case
Since phone login is being removed, the .Phone
case with an empty break
statement should be removed.
case .Email:
handleEmailLogin(completion: completion)
- case .Phone:
- break
308-329
:
Enhance security in email re-authentication
While the basic re-authentication flow is implemented correctly, several security improvements are needed:
- Add password validation
- Implement rate limiting for failed attempts
- Use generic error messages
The previous review comment provided a detailed implementation addressing these security concerns. Please refer to that implementation for the recommended security improvements.
322-322
:
Use generic error messages in logs
The current error message could leak sensitive information about user accounts. Replace it with a generic message.
- LogE("UserProfileViewModel: \(#function) No email found for email login.")
+ LogE("UserProfileViewModel: \(#function) Re-authentication failed.")
Likely invalid or redundant comment.
Splito/UI/Login/EmailLogin/EmailLoginView.swift (3)
25-29
:
Localize all user-facing strings
The strings are still hardcoded. This issue was previously raised but hasn't been addressed.
- LoginTitleView(titleText: "Continue your journey")
+ LoginTitleView(titleText: LocalizedString.continueJourney)
- LoginSubtitleView(subtitleText: "Sign in to access your account and enjoy all its features.")
+ LoginSubtitleView(subtitleText: LocalizedString.signInDescription)
92-102
:
Add email validation and error states
The email field still lacks validation and error states. This issue was previously raised but hasn't been addressed.
+ @State private var isValidEmail = false
+ @State private var showError = false
TextField("Enter your email", text: $email)
.keyboardType(.emailAddress)
.font(.subTitle3())
.foregroundStyle(primaryText)
.tint(primaryColor)
.autocapitalization(.none)
.focused(focusedField, equals: .email)
.submitLabel(.next)
+ .onChange(of: email) { newValue in
+ isValidEmail = viewModel.isValidEmail(newValue)
+ showError = !newValue.isEmpty && !isValidEmail
+ }
+ .overlay(alignment: .trailing) {
+ if showError {
+ Image(systemName: "exclamationmark.circle.fill")
+ .foregroundColor(.red)
+ .padding(.trailing, 8)
+ }
+ }
127-159
:
Enhance password field security and simplify implementation
The current implementation has several concerns:
- No password strength validation
- Complex password masking logic could be simplified
- Missing secure text entry handling
Consider using the built-in SecureField for better security:
- ZStack(alignment: .trailing) {
- TextField("Enter your password", text: $visibleInput)
- .onChange(of: visibleInput) { newValue in
- guard isSecured else { password = newValue; return }
- if newValue.count >= password.count {
- let newItem = newValue.filter { $0 != Character("•") }
- password.append(newItem)
- } else {
- password.removeLast()
- }
- visibleInput = String(newValue.map { _ in Character("•") })
- }
+ ZStack(alignment: .trailing) {
+ if isSecured {
+ SecureField("Enter your password", text: $password)
+ } else {
+ TextField("Enter your password", text: $password)
+ }
Also add password strength validation:
+ @State private var passwordStrength: PasswordStrength = .weak
+
+ enum PasswordStrength {
+ case weak, medium, strong
+ }
+
+ private func updatePasswordStrength() {
+ // Add password strength validation logic
+ passwordStrength = viewModel.validatePasswordStrength(password)
+ }
Likely invalid or redundant comment.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
📒 Files selected for processing (2)
Data/Data/Model/AppUser.swift
(2 hunks)Data/Data/Repository/UserRepository.swift
(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- Data/Data/Repository/UserRepository.swift
🔇 Additional comments (2)
Data/Data/Model/AppUser.swift (2)
69-69
: LGTM: Email login type addition
The addition of the Email
case to LoginType
enum is well-implemented with consistent casing and raw value.
21-21
:
Breaking Change: isActive
property is now mutable
Changing isActive
from let
to var
is a breaking change that could affect API consumers. Please ensure this change is intentional and properly handled throughout the codebase.
Let's verify the usage of this property:
✅ Verification successful
Based on the search results, I can now generate the final response:
isActive
property mutation is properly handled across the codebase
The change from let
to var
for isActive
is justified and well-implemented:
- Used in repositories to toggle active state during delete/restore operations (GroupRepository, ExpenseRepository, TransactionRepository)
- Properly guarded in view models with conditional checks
- Consistently used across user, group, expense, and transaction models
- Changes are always accompanied by updating metadata (updatedBy, updatedAt)
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Search for all occurrences of isActive property access or modification
rg -A 3 "\.isActive"
Length of output: 10084
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Outside diff range and nitpick comments (1)
Splito/UI/Home/Groups/GroupListViewModel.swift (1)
234-236
: LGTM! Consider extracting filter conditions for better readability.The additional validation prevents showing an empty search bar when there are no groups to search, which improves the user experience.
Consider extracting the filter conditions into computed properties for better readability:
+ private var hasUnsettledGroups: Bool { + !combinedGroups.filter({ $0.userBalance != 0 }).isEmpty + } + + private var hasSettledGroups: Bool { + !combinedGroups.filter({ $0.userBalance == 0 }).isEmpty + } func handleSearchBarTap() { - if (combinedGroups.isEmpty) || - (selectedTab == .unsettled && combinedGroups.filter({ $0.userBalance != 0 }).isEmpty) || - (selectedTab == .settled && combinedGroups.filter({ $0.userBalance == 0 }).isEmpty) { + if combinedGroups.isEmpty || + (selectedTab == .unsettled && !hasUnsettledGroups) || + (selectedTab == .settled && !hasSettledGroups) { showToastFor(toast: .init(type: .info, title: "No groups yet", message: "There are no groups available to search.")) } else { withAnimation { searchedGroup = "" showSearchBar.toggle() } } }
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 3
🧹 Outside diff range and nitpick comments (1)
Splito/UI/Login/LoginViewModel.swift (1)
122-123
: Consider more specific error messagesThe generic error message "Something went wrong!" might not provide enough context to users or for debugging purposes.
Consider categorizing errors and providing more specific messages:
-self.alert = .init(message: "Something went wrong! Please try after some time.") +self.alert = .init(message: error.localizedDescription)
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
📒 Files selected for processing (9)
Data/Data/Model/AppUser.swift
(2 hunks)Data/Data/Router/AppRoute.swift
(1 hunks)Splito/UI/Home/Account/User Profile/UserProfileViewModel.swift
(3 hunks)Splito/UI/Home/HomeRouteView.swift
(2 hunks)Splito/UI/Home/HomeRouteViewModel.swift
(2 hunks)Splito/UI/Login/EmailLogin/EmailLoginViewModel.swift
(1 hunks)Splito/UI/Login/LoginViewModel.swift
(2 hunks)Splito/UI/Onboard/OnboardRouteView.swift
(1 hunks)Splito/UI/Router/AppRoute.swift
(2 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
- Splito/UI/Router/AppRoute.swift
- Splito/UI/Login/EmailLogin/EmailLoginViewModel.swift
🔇 Additional comments (16)
Data/Data/Router/AppRoute.swift (1)
17-17
: LGTM! Good addition of the optional onDismiss closure.
The modification to include an optional onDismiss
closure with a default value is a good practice, providing flexibility in handling view dismissal while maintaining backward compatibility.
Splito/UI/Home/HomeRouteView.swift (1)
53-61
: LGTM: Well-structured presentation flow
The implementation of the onboarding and profile presentation flows is well-structured:
- Proper use of
interactiveDismissDisabled()
for required flows - Clear separation between sheet and fullScreenCover presentations
- Appropriate dismissal handling through callbacks
Splito/UI/Home/HomeRouteViewModel.swift (3)
17-17
: LGTM: Property declaration follows SwiftUI conventions
The @Published
property wrapper is correctly used for SwiftUI state management, and the naming clearly indicates its purpose.
40-42
: LGTM: Clean and consistent implementation
The method follows the established pattern in the class (similar to dismissProfileView
) and adheres to the single responsibility principle.
Line range hint 1-48
: Consider authentication state transition handling
As part of the transition from phone to email authentication, ensure that:
- Existing users' authentication state is properly handled during the transition
- Any stored phone authentication data is cleaned up
- The onboarding flow properly handles both new and existing users migrating to email authentication
Let's verify the authentication state handling:
✅ Verification successful
Authentication state transition appears properly handled
Based on the verification results, the authentication state transition is well-managed:
- The
isVerifiedUser
flag inSplitoPreference
properly handles the authentication state - Email authentication sets the verification state correctly in
EmailLoginViewModel
- The only phone authentication reference is an unused provider in
FirebaseProvider
- User state transitions are handled appropriately in both onboarding and login flows
- The cleanup of old authentication data happens automatically as the
SplitoPreference.reset()
method clears the verification state
The implementation correctly handles both new and existing users, with proper state management for the email authentication transition.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Check for any remaining phone authentication references
rg -i "phone.*auth|auth.*phone" --type swift
# Check for proper cleanup of old authentication data
ast-grep --pattern 'func $cleanup() {
$$$
}'
Length of output: 217
Script:
#!/bin/bash
# Let's check for authentication-related cleanup methods and state handling
rg -i "auth.*clean|clean.*auth" --type swift -A 3
# Check for authentication state transitions and handling
ast-grep --pattern 'func $authMethod() {
$$$
}'
# Look for authentication state management
rg -i "auth.*state|isVerified|user.*state" --type swift -A 3
# Check for user migration or transition handling
rg -i "migrat|transition" --type swift -A 3
Length of output: 4292
Splito/UI/Onboard/OnboardRouteView.swift (3)
18-19
: LGTM: Proper closure declaration for navigation
The optional closure property is correctly declared for handling dismissal navigation.
26-28
: LGTM: Consistent routing implementation
The routing logic properly handles both LoginView and EmailLoginView cases, maintaining consistent navigation patterns by passing the onDismiss closure.
34-36
: Verify user verification logic
The condition checks both unverified users and nil users. Consider if these conditions should be combined with OR (current) or AND operator based on your business logic.
✅ Verification successful
Based on the search results, I can now provide a final response as the code patterns reveal consistent usage across the codebase.
The OR condition is correct for user verification
The current logic (!preference.isVerifiedUser || preference.user == nil)
is correctly implemented. Throughout the codebase, these two conditions are used independently to handle different scenarios:
isVerifiedUser
is used as a flag for completed user verification (e.g., in login flows)preference.user == nil
checks for user existence (e.g., in protected routes)
The OR condition is appropriate here because the login view should be shown if either:
- The user hasn't completed verification (even if user data exists)
- No user data exists (indicating no logged-in user)
This is consistent with other authentication patterns in the codebase, such as in HomeRouteViewModel.swift
where similar checks are performed.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Search for similar user verification patterns
rg "isVerifiedUser|preference\.user" -t swift
Length of output: 13488
Data/Data/Model/AppUser.swift (2)
21-21
: LGTM: Changed isActive to mutable
Making isActive mutable allows for user state updates.
69-69
:
Remove Phone case from LoginType enum
The PR aims to remove phone login functionality, but the Phone
case still exists in the LoginType
enum. This case should be removed to prevent potential usage since phone authentication is being completely removed from the app.
Splito/UI/Login/LoginViewModel.swift (2)
26-30
: LGTM: Proper initialization with optional closure
The onDismiss closure is correctly initialized and stored.
135-137
: LGTM: Email login navigation
The email login navigation is properly implemented with the onDismiss closure being passed through.
Splito/UI/Home/Account/User Profile/UserProfileViewModel.swift (4)
28-28
: LGTM: Login type transition
The change from .Phone
to .Email
as the default login type aligns with the PR's objective of transitioning to email-based authentication.
256-257
: LGTM: Email authentication handling
The email authentication case is properly integrated into the existing authentication flow, maintaining consistency with other authentication methods.
305-326
: 🛠️ Refactor suggestion
Enhance security in email re-authentication
Previous security concerns about password validation and rate limiting remain relevant.
Additional security considerations:
- Store sensitive information securely
- Clear password field after failed attempts
- Add timeout between re-authentication attempts
private func handleEmailLogin(completion: @escaping (AuthCredential?) -> Void) {
+ // Add timeout between re-authentication attempts
+ guard let lastAttemptTime = UserDefaults.standard.object(forKey: "lastReAuthAttempt") as? Date else {
+ UserDefaults.standard.set(Date(), forKey: "lastReAuthAttempt")
+ continueWithAuth()
+ return
+ }
+
+ let timeoutInterval: TimeInterval = 60 // 1 minute timeout
+ if Date().timeIntervalSince(lastAttemptTime) < timeoutInterval {
+ self.isDeleteInProgress = false
+ self.showAlertFor(message: "Please wait before trying again")
+ return
+ }
+
+ UserDefaults.standard.set(Date(), forKey: "lastReAuthAttempt")
+ continueWithAuth()
+}
+
+private func continueWithAuth() {
let alert = UIAlertController(title: "Re-authenticate", message: "Please enter your password", preferredStyle: .alert)
alert.addTextField { textField in
textField.placeholder = "Password"
textField.isSecureTextEntry = true
+ textField.autocorrectionType = .no
+ textField.spellCheckingType = .no
}
alert.addAction(UIAlertAction(title: "Cancel", style: .cancel) { _ in
self.isDeleteInProgress = false
})
alert.addAction(UIAlertAction(title: "Confirm", style: .default) { _ in
guard let password = alert.textFields?.first?.text,
let email = self.preference.user?.emailId else {
self.isDeleteInProgress = false
- LogE("UserProfileViewModel: \(#function) No email found for email login.")
+ LogE("UserProfileViewModel: \(#function) Re-authentication failed.")
return
}
+ // Clear password field
+ alert.textFields?.first?.text = ""
let credential = EmailAuthProvider.credential(withEmail: email, password: password)
completion(credential)
})
TopViewController.shared.topViewController()?.present(alert, animated: true)
}
Line range hint 28-326
: Verify complete removal of phone authentication
Let's ensure all phone authentication references have been removed and email authentication is properly integrated.
✅ Verification successful
Let me verify the login types to ensure complete removal of phone authentication.
Phone authentication has been properly removed, but there are remaining phone number fields
The verification shows:
- Login types are limited to Apple, Google, and Email only - no phone authentication exists
- Phone number is only used as an optional profile field (
phoneNumber: nil
in login flows) - No OTP or phone verification code handling remains
However, the app still maintains phone number as a non-authentication profile field:
phoneNumber
property exists inAppUser
model- Phone number input/display exists in profile views
- No validation or authentication is tied to these phone numbers
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Search for any remaining phone authentication references
echo "Checking for phone authentication references..."
rg -i "phone.*login|login.*phone" --type swift
echo "Checking for phone number validation or formatting..."
rg -i "phone.*number|number.*phone" --type swift
echo "Checking for OTP or verification code handling..."
rg -i "otp|verification.*code|code.*verification" --type swift
Length of output: 3256
Script:
#!/bin/bash
# Check LoginType enum definition and usage
echo "Checking LoginType enum..."
ast-grep --pattern 'enum LoginType'
echo "\nChecking all login type references..."
rg -i "logintype|login.*type" --type swift -A 2
Length of output: 4995
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Outside diff range and nitpick comments (2)
Splito/UI/Home/Expense/AddExpenseView.swift (2)
Line range hint
266-285
: Consider accessibility improvements for ImageAttachmentViewThe image attachment functionality could benefit from accessibility improvements:
- Add accessibility labels for the camera icon
- Consider adding accessibility hints for the image selection process
Image(.cameraIcon) .resizable() .scaledToFit() .frame(width: 24, height: 24) .padding(.horizontal, 8) .padding(.vertical, 4) + .accessibilityLabel("Add image") + .accessibilityHint("Double tap to select or capture an image") .onTouchGesture(handleImageBtnTap)
Line range hint
266-285
: Extract hardcoded dimensions into constantsThe image dimensions (24x24) are repeated multiple times. Consider extracting these into a constant or design token for better maintainability.
+private enum Constants { + static let iconSize: CGFloat = 24 +} // Then use Constants.iconSize instead of hardcoded 24Also applies to: 247-260
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
📒 Files selected for processing (1)
Splito/UI/Home/Expense/AddExpenseView.swift
(1 hunks)
🔇 Additional comments (1)
Splito/UI/Home/Expense/AddExpenseView.swift (1)
235-237
: LGTM! Verify ImagePickerOptionsView implementation
The implementation of the confirmation dialog for image picker options looks good and follows SwiftUI best practices.
Let's verify the ImagePickerOptionsView implementation:
✅ Verification successful
Implementation verified and properly used across the app ✅
The ImagePickerOptionsView is well-implemented and consistently used across the app:
- Properly handles all required parameters (image, imageUrl, handleActionSelection)
- Provides consistent image picking options (camera, gallery, remove)
- Used consistently in AddExpenseView, UserProfileView, and CreateGroupView
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Verify ImagePickerOptionsView implementation and its usage
# Expected: Find ImagePickerOptionsView definition and any other usages
# Search for ImagePickerOptionsView definition
echo "Searching for ImagePickerOptionsView definition..."
rg -p "struct ImagePickerOptionsView.*View"
# Search for other usages of ImagePickerOptionsView
echo "Searching for other usages of ImagePickerOptionsView..."
rg "ImagePickerOptionsView\(" --type swift
Length of output: 951
Script:
#!/bin/bash
# Let's examine the ImagePickerOptionsView implementation to ensure it properly handles the required parameters
rg -p -B 5 -A 15 "struct ImagePickerOptionsView.*View" --type swift
Length of output: 830
return storedUser | ||
if var fetchedUser = try await store.fetchUserBy(id: user.id) { | ||
LogD("UserRepository: \(#function) User already exists in Firestore.") | ||
if !fetchedUser.isActive { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why we are making user active if the user is already deleted from the store?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Because when we fetch deleted user then we need to make isActive true while restore the account.
@@ -72,11 +72,6 @@ struct UserProfileView: View { | |||
ImagePickerView(cropOption: .square, sourceType: !viewModel.sourceTypeIsCamera ? .photoLibrary : .camera, | |||
image: $viewModel.profileImage, isPresented: $viewModel.showImagePicker) | |||
} | |||
.sheet(isPresented: $viewModel.showOTPView) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Have you tried deleting an account with an email login as we needed this flow during account delete only?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes
Have you tested the forget password and delete account delete account flow? |
71467ee
to
4b311cb
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Outside diff range and nitpick comments (5)
Splito/UI/Home/HomeRouteViewModel.swift (1)
Line range hint
11-45
: Consider splitting navigation responsibilities.The
HomeRouteViewModel
is handling multiple navigation concerns (profile, onboarding, tabs, activity log). As the app grows, consider splitting these into separate coordinators or navigation handlers to better follow the Single Responsibility Principle.Splito/UI/Login/LoginView.swift (2)
71-72
: Consider the order of login optionsThe email login button is placed last in the list of options. Consider if email should be positioned first since it's becoming the primary login method.
VStack(spacing: 8) { + LoginOptionsButtonView(image: .emailIcon, buttonName: "Sign in with Email", bgColor: primaryColor, + buttonTextColor: primaryLightText, showLoader: false, onClick: onEmailLoginClick) LoginOptionsButtonView(image: .googleIcon, buttonName: "Sign in with Google", showLoader: showGoogleLoading, onClick: onGoogleLoginClick) LoginOptionsButtonView(systemImage: ("apple.logo", primaryText, (14, 16)), buttonName: "Sign in with Apple", showLoader: showAppleLoading, onClick: onAppleLoginClick) - LoginOptionsButtonView(image: .emailIcon, buttonName: "Sign in with Email", bgColor: primaryColor, - buttonTextColor: primaryLightText, showLoader: false, onClick: onEmailLoginClick) }
177-177
: Move hardcoded strings to constantsWhile the localization is good, consider moving the hardcoded strings to a constants file or string catalog:
enum LoginStrings { static let title = "Getting started with us" static let subtitle = "Sign up in the app to use amazing splitting features." }Also applies to: 192-197
Splito/UI/Home/Account/User Profile/UserProfileView.swift (1)
Remove phone-related code from user profile implementation
The verification confirms there are multiple phone-related code segments that need to be removed:
- In
UserProfileList.swift
:
- Remove
case phone
from the enum- Remove all associated phone case handling in computed properties
- In
UserProfileView.swift
:
- Remove phone binding and field from
UserDetailList
- Remove phone case from validation switch
- Update submit action flow in
UserProfileDataEditableTextField
- In
Data/Model/AppUser.swift
:
- Remove
phoneNumber
case from what appears to be a coding keys enum🔗 Analysis chain
Line range hint
1-248
: Clean up remaining phone-related codeThere are still phone-related remnants throughout the file that should be removed for consistency:
- Remove phone validation case in the validation switch
- Remove phone field handling in the submit action
- Update UserProfileList enum (in a separate file) to remove the phone case
Let's verify other phone-related code that needs cleanup:
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash # Search for remaining phone-related code in the codebase echo "=== Searching for phone-related code ===" rg "case.*phone|phone.*case" -i --type swift echo -e "\n=== Checking UserProfileList enum ===" rg "enum UserProfileList" -A 10 --type swiftLength of output: 2029
Splito.xcodeproj/project.pbxproj (1)
Phone authentication code has been mostly removed but some remnants exist
The phone authentication functionality has been mostly removed from the codebase, but there are a few remnants that should be cleaned up:
phoneNumber
field still exists in models but is only used asnil
PhoneAuthProvider
is declared in FirebaseProvider but never used- Phone auth mentioned in README.md but no longer supported
Suggested cleanup:
- Remove unused
phoneAuthProvider
from FirebaseProvider- Remove
phoneNumber
field from AppUser model and its usages- Update README.md to remove phone authentication from features list
🔗 Analysis chain
Line range hint
1-1500
: Verify removal of phone login related files.While new email login files are added, we should verify that all phone login related files have been completely removed from the project to avoid any residual references.
Let me check the remaining references to understand if they are just legacy code or actual phone login functionality.
Let me try a different approach to check the actual usage of phone authentication.
Let me check the FirebaseProvider implementation specifically since it's the only file that still has phone auth references.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash # Description: Search for any remaining phone login related files or references # Search for phone login related files echo "Searching for phone login related files..." fd -t f -e swift -e xib -e storyboard "Phone|OTP|Verify" # Search for phone login related strings in source files echo "Searching for phone login related strings in source code..." rg -i "phone.*login|verify.*otp|phone.*auth"Length of output: 784
Script:
#!/bin/bash # Check the actual implementation in LoginViewModel and FirebaseProvider # Check LoginViewModel implementation echo "=== LoginViewModel implementation ===" ast-grep --pattern 'class LoginViewModel { $$$ }' Splito/UI/Login/LoginViewModel.swift # Check FirebaseProvider implementation echo -e "\n=== FirebaseProvider implementation ===" ast-grep --pattern 'class FirebaseProvider { $$$ }' Data/Data/Helper/Firebase/FirebaseProvider.swiftLength of output: 375
Script:
#!/bin/bash # Search for phone authentication related method calls and implementations echo "=== Checking phone auth related method calls ===" rg -l "phoneAuthProvider|PhoneAuthProvider|verifyPhoneNumber|signInWithPhoneNumber" --type swift echo -e "\n=== Checking phone number parameter usage ===" rg "phoneNumber:" --type swift -C 2 echo -e "\n=== Checking phone related strings ===" rg "\"phone\"" --type swift -C 2Length of output: 2840
Script:
#!/bin/bash # Check FirebaseProvider implementation for phone auth usage echo "=== FirebaseProvider phone auth implementation ===" rg -A 10 -B 10 "phoneAuthProvider|PhoneAuthProvider" Data/Data/Helper/Firebase/FirebaseProvider.swift echo -e "\n=== Check if phone auth provider is used anywhere ===" rg -l "FirebaseProvider.phoneAuthProvider" --type swiftLength of output: 734
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
⛔ Files ignored due to path filters (3)
Splito/Resource/Assets.xcassets/Images/Login/EmailIcon.imageset/email_svgrepo.com.svg
is excluded by!**/*.svg
Splito/Resource/Assets.xcassets/Images/Login/LoginAppLogo.imageset/logo.svg
is excluded by!**/*.svg
Splito/Resource/Assets.xcassets/Images/Login/LoginAppLogo.imageset/user.svg
is excluded by!**/*.svg
📒 Files selected for processing (32)
BaseStyle/BaseStyle.xcodeproj/project.pbxproj
(0 hunks)BaseStyle/BaseStyle/CustomUI/Buttons/PrimaryFloatingButton.swift
(2 hunks)BaseStyle/BaseStyle/CustomUI/OtpTextInputView.swift
(0 hunks)BaseStyle/BaseStyle/Extension/String+Extension.swift
(0 hunks)BaseStyle/BaseStyle/Resource/Countries.json
(0 hunks)Data/Data.xcodeproj/project.pbxproj
(0 hunks)Data/Data/Model/AppUser.swift
(2 hunks)Data/Data/Model/Country.swift
(0 hunks)Data/Data/Repository/UserRepository.swift
(1 hunks)Data/Data/Router/AppRoute.swift
(4 hunks)Data/Data/Store/UserStore.swift
(1 hunks)Splito.xcodeproj/project.pbxproj
(6 hunks)Splito/Localization/Localizable.xcstrings
(16 hunks)Splito/Resource/Assets.xcassets/Images/Login/EmailIcon.imageset/Contents.json
(1 hunks)Splito/Resource/Assets.xcassets/Images/Login/LoginAppLogo.imageset/Contents.json
(1 hunks)Splito/UI/Home/Account/User Profile/UserProfileView.swift
(1 hunks)Splito/UI/Home/Account/User Profile/UserProfileViewModel.swift
(3 hunks)Splito/UI/Home/Expense/AddExpenseView.swift
(1 hunks)Splito/UI/Home/Groups/Add Member/JoinMemberView.swift
(2 hunks)Splito/UI/Home/Groups/GroupListViewModel.swift
(1 hunks)Splito/UI/Home/HomeRouteView.swift
(1 hunks)Splito/UI/Home/HomeRouteViewModel.swift
(2 hunks)Splito/UI/Login/EmailLogin/EmailLoginView.swift
(1 hunks)Splito/UI/Login/EmailLogin/EmailLoginViewModel.swift
(1 hunks)Splito/UI/Login/LoginView.swift
(6 hunks)Splito/UI/Login/LoginViewModel.swift
(2 hunks)Splito/UI/Login/PhoneLogin/PhoneLoginView.swift
(0 hunks)Splito/UI/Login/PhoneLogin/PhoneLoginViewModel.swift
(0 hunks)Splito/UI/Login/PhoneLogin/VerifyOtp/VerifyOtpView.swift
(0 hunks)Splito/UI/Login/PhoneLogin/VerifyOtp/VerifyOtpViewModel.swift
(0 hunks)Splito/UI/Onboard/OnboardRouteView.swift
(1 hunks)Splito/UI/Router/AppRoute.swift
(0 hunks)
💤 Files with no reviewable changes (11)
- BaseStyle/BaseStyle/Resource/Countries.json
- Data/Data.xcodeproj/project.pbxproj
- BaseStyle/BaseStyle/Extension/String+Extension.swift
- BaseStyle/BaseStyle/CustomUI/OtpTextInputView.swift
- Splito/UI/Login/PhoneLogin/PhoneLoginView.swift
- Splito/UI/Login/PhoneLogin/PhoneLoginViewModel.swift
- Splito/UI/Login/PhoneLogin/VerifyOtp/VerifyOtpViewModel.swift
- Data/Data/Model/Country.swift
- Splito/UI/Router/AppRoute.swift
- Splito/UI/Login/PhoneLogin/VerifyOtp/VerifyOtpView.swift
- BaseStyle/BaseStyle.xcodeproj/project.pbxproj
🚧 Files skipped from review as they are similar to previous changes (16)
- Splito/Resource/Assets.xcassets/Images/Login/EmailIcon.imageset/Contents.json
- Splito/Resource/Assets.xcassets/Images/Login/LoginAppLogo.imageset/Contents.json
- Data/Data/Store/UserStore.swift
- Splito/UI/Home/HomeRouteView.swift
- Data/Data/Model/AppUser.swift
- Data/Data/Router/AppRoute.swift
- Splito/UI/Home/Expense/AddExpenseView.swift
- Data/Data/Repository/UserRepository.swift
- Splito/UI/Login/EmailLogin/EmailLoginView.swift
- Splito/UI/Home/Groups/Add Member/JoinMemberView.swift
- BaseStyle/BaseStyle/CustomUI/Buttons/PrimaryFloatingButton.swift
- Splito/UI/Login/LoginViewModel.swift
- Splito/UI/Home/Groups/GroupListViewModel.swift
- Splito/Localization/Localizable.xcstrings
- Splito/UI/Onboard/OnboardRouteView.swift
- Splito/UI/Login/EmailLogin/EmailLoginViewModel.swift
🔇 Additional comments (14)
Splito/UI/Home/HomeRouteViewModel.swift (3)
17-17
: LGTM! Property declaration follows best practices.
The @Published
property is well-named and appropriately typed for managing onboarding flow visibility.
38-40
: LGTM! Method follows established patterns.
The dismissOnboardFlow
method is well-named and follows the same pattern as the existing dismissProfileView
method.
22-27
: 🛠️ Refactor suggestion
Simplify conditional logic and improve Swift idioms.
The current implementation could be more idiomatic and easier to maintain.
Consider this refactoring:
func openProfileOrOnboardFlow() {
if preference.user == nil {
openOnboardFlow = true
- } else if preference.isVerifiedUser && (preference.user?.firstName == nil || preference.user?.firstName == "") {
+ return
+ }
+
+ if preference.isVerifiedUser && (preference.user?.firstName?.isEmpty ?? true) {
openProfileView = true
}
}
This improves the code by:
- Using early return to reduce nesting
- Leveraging Swift's
isEmpty
property - Using optional chaining more effectively
Splito/UI/Home/Account/User Profile/UserProfileViewModel.swift (3)
28-28
: LGTM: Login type change aligns with email authentication transition
The change from .Phone
to .Email
as the default login type is consistent with the PR's objective to transition from phone to email-based authentication.
256-257
: LGTM: Email authentication handler properly integrated
The email authentication case is correctly integrated into the re-authentication flow, maintaining consistency with other authentication methods.
305-326
: 🛠️ Refactor suggestion
Enhance security and user experience in email authentication
While the basic implementation is functional, consider these improvements:
- Add password validation before credential creation
- Implement rate limiting for failed attempts
- Provide more user-friendly error messages
Apply this diff to enhance the implementation:
private func handleEmailLogin(completion: @escaping (AuthCredential?) -> Void) {
+ // Track failed attempts
+ private var failedAttempts = 0
+ private let maxAttempts = 3
+
+ if failedAttempts >= maxAttempts {
+ self.isDeleteInProgress = false
+ showAlertFor(message: "Too many attempts. Please try again later.")
+ return
+ }
+
let alert = UIAlertController(title: "Re-authenticate",
message: "Please enter your password",
preferredStyle: .alert)
alert.addTextField { textField in
textField.placeholder = "Password"
textField.isSecureTextEntry = true
}
alert.addAction(UIAlertAction(title: "Cancel", style: .cancel) { _ in
self.isDeleteInProgress = false
})
alert.addAction(UIAlertAction(title: "Confirm", style: .default) { _ in
guard let password = alert.textFields?.first?.text,
!password.isEmpty,
+ password.count >= 8, // Basic password validation
let email = self.preference.user?.emailId else {
self.isDeleteInProgress = false
- LogE("UserProfileViewModel: \(#function) No email found for email login.")
+ self.failedAttempts += 1
+ let errorMessage = password.isEmpty ? "Password cannot be empty" :
+ "Invalid password format"
+ self.showAlertFor(message: errorMessage)
return
}
let credential = EmailAuthProvider.credential(withEmail: email, password: password)
completion(credential)
})
TopViewController.shared.topViewController()?.present(alert, animated: true)
}
Splito/UI/Login/LoginView.swift (3)
43-43
: LGTM: Email login parameter addition is well-implemented
The addition of onEmailLoginClick
parameter follows SwiftUI conventions and aligns with the PR objectives.
Also applies to: 62-62
160-160
: Verify reduced logo padding
The bottom padding has been reduced from 40 to 16. Please ensure this adjustment doesn't create any spacing issues in the UI, particularly on different device sizes.
Line range hint 1-201
: Verify complete removal of phone login
While this file has been updated to remove phone login UI, please ensure all phone-related code is removed from the entire codebase as mentioned in previous reviews.
#!/bin/bash
# Search for remaining phone login references in Swift files
echo "Searching for phone login references..."
rg -i "phone.*login|login.*phone" --type swift
# Search for PhoneLogin directory
echo "Checking for PhoneLogin directory..."
fd -t d "PhoneLogin"
Splito/UI/Home/Account/User Profile/UserProfileView.swift (2)
128-128
: LGTM: Email field disabling logic is correct
The updated condition properly handles both Google and Email login types, preventing users from modifying their email when it's used as their authentication method.
135-138
:
Remove phone-related UI elements
While phone login has been removed, the phone field still exists in the UI but isn't included in validation. This creates an inconsistent user experience.
Consider one of these approaches:
- Remove the phone field entirely since phone login has been removed
- If phone number is needed for other purposes (e.g., user information only), add appropriate validation and update the UI to reflect its new purpose
// In UserDetailList struct
var titles: [Binding<String>] {
- [$firstName, $lastName, $phone, $email]
+ [$firstName, $lastName, $email]
}
// Update profileOptions to exclude phone
var profileOptions: [UserProfileList] {
- UserProfileList.allCases
+ UserProfileList.allCases.filter { $0 != .phone }
}
Splito.xcodeproj/project.pbxproj (3)
174-175
: LGTM: New email login files are properly referenced.
The file references for EmailLoginView.swift
and EmailLoginViewModel.swift
are correctly added to the project.
359-367
: LGTM: Email login group structure is well-organized.
The new EmailLogin
group is properly structured and placed in the appropriate location within the project hierarchy.
723-723
: LGTM: Build phases are correctly configured.
The new email login files are properly integrated into the build phases:
- Files are included in the compilation phase
- Source files are correctly referenced in the project structure
Also applies to: 1050-1050, 1101-1101
Simulator.Screen.Recording.-.iPhone.16.Pro.Max.-.2024-12-09.at.18.19.39.mp4
Simulator.Screen.Recording.-.iPhone.16.Pro.Max.-.2024-12-09.at.18.33.24.mp4
Summary by CodeRabbit
Release Notes
New Features
User Interface Enhancements
Localization
Bug Fixes
Removal of Phone Login
These changes enhance user experience and expand login options within the application.