Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Logout functionality #2483

Merged
merged 6 commits into from
Feb 19, 2025
Merged

Logout functionality #2483

merged 6 commits into from
Feb 19, 2025

Conversation

Mozart299
Copy link
Contributor

@Mozart299 Mozart299 commented Feb 19, 2025

Summary of Changes (What does this PR do?)

  • Please include a summary of the change and which issue is fixed. Please also include relevant motivation and context. List any dependencies that are required for this change.

Status of maturity (all need to be checked before merging):

  • I've tested this locally
  • I consider this code done
  • This change ready to hit production in its current state
  • The title of the PR states what changed and the related issues number (used for the release note).
  • I've included issue number in the "Closes #ISSUE-NUMBER" part of the "What are the relevant tickets?" section to link the issue.
  • I've updated corresponding documentation for the changes in this PR.
  • I have written unit and/or e2e tests for my change(s).

How should this be manually tested?

  • Please include the steps to be done inorder to setup and test this PR.

What are the relevant tickets?

Screenshots (optional)

Summary by CodeRabbit

  • New Features
    • Introduced an enhanced logout experience that guides users through a confirmation process and ensures a secure return to the welcome screen.
  • Refactor
    • Improved overall authentication flow with streamlined state transitions and error handling for better reliability during login and logout.
  • Bug Fixes
    • Implemented error handling for unexpected exceptions during the logout process.
  • UI Changes
    • Updated messaging in the lesson completion screen and removed interactive buttons for a simplified user experience.
  • Code Cleanup
    • Disabled navigation logic for user profiles based on authentication status while maintaining visual representation of user avatars.
  • Configuration Updates
    • Enhanced API key management for Google services, allowing for alternative sources and clearer error messaging.

Copy link

coderabbitai bot commented Feb 19, 2025

📝 Walkthrough

Walkthrough

This update introduces structured logout functionality in the authentication flow. The AuthBloc now includes a dedicated _onLogoutUser method with error handling, along with an updated login flow that saves tokens using a Hive repository. Additionally, a new LogoutUser event is added to the AuthEvent class. In the UI layer, the SettingsWidget dispatches this event upon confirmation and navigates to the WelcomeScreen, ensuring previous routes are cleared.

Changes

File(s) Change Summary
mobile-v3/lib/src/app/auth/bloc/auth_bloc.dart
mobile-v3/lib/src/app/auth/bloc/auth_event.dart
Added a new LogoutUser event and implemented _onLogoutUser in AuthBloc for handling logout. Enhanced token management and error extraction in login functionality.
mobile-v3/lib/src/app/profile/pages/widgets/settings_widget.dart Updated imports and modified the _showLogoutConfirmation method to dispatch the LogoutUser event, then navigate to WelcomeScreen while clearing the previous routes.
mobile-v3/lib/src/app/dashboard/pages/dashboard_page.dart Commented out navigation logic for user profiles based on authentication state, replacing it with a BlocBuilder for displaying user avatars.
mobile-v3/lib/src/app/learn/pages/lesson_finished.dart Modified displayed text and removed interactive buttons from the LessonFinishedWidget, simplifying the layout.
mobile-v3/android/app/build.gradle
mobile-v3/android/app/src/main/AndroidManifest.xml
Updated API key retrieval logic in build.gradle to allow fallback to secrets.properties. Modified metadata entries in AndroidManifest.xml to correctly reference API keys.

Possibly related PRs

  • Settings screen redesign #2396: The changes in the main PR, specifically the addition of the _onLogoutUser method in the AuthBloc class, are directly related to the new LogoutUser event in the retrieved PR, which dispatches this event to handle the logout process.
  • Feedback address #2466: The changes in the main PR are related to the modifications in the AuthBloc class and the addition of the LogoutUser event, which are both directly referenced in the retrieved PR's updates to the AuthBloc and AuthEvent classes.
  • Remove non functional features #2362: The changes in the main PR, specifically the addition of the _onLogoutUser method in the AuthBloc class and the new LogoutUser event, are directly related to the modifications in the retrieved PR, which includes the implementation of the _handleLogout method that dispatches the LogoutUser event to the AuthBloc.

Suggested reviewers

  • Baalmart

Poem

In cascades of code, a logout now sings,
Tokens vanish, and error hope takes wing.
A new event leads the digital dance,
Clearing the path for a fresh screen glance.
Code flows like art—a seamless, joyful prance.

Warning

Review ran into problems

🔥 Problems

Errors were encountered while retrieving linked issues.

Errors (1)
  • JIRA integration encountered authorization issues. Please disconnect and reconnect the integration in the CodeRabbit UI.

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?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

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)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR. (Beta)
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai or @coderabbitai title anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@Mozart299 Mozart299 requested a review from Baalmart February 19, 2025 12:05
Copy link

@coderabbitai coderabbitai bot left a 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

🧹 Nitpick comments (1)
mobile-v3/lib/src/app/auth/bloc/auth_bloc.dart (1)

75-85: Consider enhancing logout cleanup process.

While the basic logout functionality is implemented correctly, consider:

  1. Clearing all user-related data from Hive, not just the token
  2. Specifying error types in the catch block for more precise error handling
 Future<void> _onLogoutUser(LogoutUser event, Emitter<AuthState> emit) async {
   emit(AuthLoading());
   try {
-    await HiveRepository.deleteData(
-        'token', HiveBoxNames.authBox); // Remove token from Hive
+    // Clear all user-related data
+    await Future.wait([
+      HiveRepository.deleteData('token', HiveBoxNames.authBox),
+      HiveRepository.deleteData('user_preferences', HiveBoxNames.authBox),
+      // Add other user-related data cleanup
+    ]);
     emit(GuestUser()); // Emit guest state after logout
-  } catch (e) {
+  } catch (e) when (e is HiveError) {
+    debugPrint("Hive storage error during logout: $e");
+    emit(AuthLoadingError("Storage error during logout. Please try again."));
+  } catch (e) {
     debugPrint("Logout error: $e");
     emit(AuthLoadingError("Failed to log out. Please try again."));
   }
 }
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d07a316 and 843e0c0.

📒 Files selected for processing (3)
  • mobile-v3/lib/src/app/auth/bloc/auth_bloc.dart (4 hunks)
  • mobile-v3/lib/src/app/auth/bloc/auth_event.dart (1 hunks)
  • mobile-v3/lib/src/app/profile/pages/widgets/settings_widget.dart (3 hunks)
🔇 Additional comments (2)
mobile-v3/lib/src/app/auth/bloc/auth_event.dart (1)

30-32: Clean implementation of LogoutUser event!

The implementation follows the established pattern and maintains consistency with other event classes.

mobile-v3/lib/src/app/auth/bloc/auth_bloc.dart (1)

22-22: LGTM! Event handler registration is clean.

The LogoutUser event is properly registered in the constructor.

Comment on lines 46 to 56
onPressed: () {
// TODO: Implement actual logout logic
// e.g., clear user session, revoke tokens
Navigator.of(context).pushReplacementNamed('/login');
context
.read<AuthBloc>()
.add(LogoutUser());

Navigator.pushAndRemoveUntil(
context,
MaterialPageRoute(builder: (context) => WelcomeScreen()),
(Route<dynamic> route) => false,
);
},
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Add loading state and handle logout completion.

The current implementation doesn't wait for the logout process to complete before navigation. This could lead to a poor user experience if the logout fails.

 onPressed: () {
-  context
-      .read<AuthBloc>()
-      .add(LogoutUser());
-
-  Navigator.pushAndRemoveUntil(
-    context,
-    MaterialPageRoute(builder: (context) => WelcomeScreen()),
-    (Route<dynamic> route) => false,
-  );
+  // Show loading indicator
+  showDialog(
+    context: context,
+    barrierDismissible: false,
+    builder: (context) => const Center(child: CircularProgressIndicator()),
+  );
+  
+  // Listen for state changes
+  context.read<AuthBloc>().stream.listen((state) {
+    if (state is GuestUser) {
+      Navigator.pushAndRemoveUntil(
+        context,
+        MaterialPageRoute(builder: (context) => WelcomeScreen()),
+        (Route<dynamic> route) => false,
+      );
+    } else if (state is AuthLoadingError) {
+      Navigator.pop(context); // Remove loading
+      ScaffoldMessenger.of(context).showSnackBar(
+        SnackBar(content: Text(state.message)),
+      );
+    }
+  });
+  
+  context.read<AuthBloc>().add(LogoutUser());
 },
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
onPressed: () {
// TODO: Implement actual logout logic
// e.g., clear user session, revoke tokens
Navigator.of(context).pushReplacementNamed('/login');
context
.read<AuthBloc>()
.add(LogoutUser());
Navigator.pushAndRemoveUntil(
context,
MaterialPageRoute(builder: (context) => WelcomeScreen()),
(Route<dynamic> route) => false,
);
},
onPressed: () {
// Show loading indicator
showDialog(
context: context,
barrierDismissible: false,
builder: (context) => const Center(child: CircularProgressIndicator()),
);
// Listen for state changes
context.read<AuthBloc>().stream.listen((state) {
if (state is GuestUser) {
Navigator.pushAndRemoveUntil(
context,
MaterialPageRoute(builder: (context) => WelcomeScreen()),
(Route<dynamic> route) => false,
);
} else if (state is AuthLoadingError) {
Navigator.pop(context); // Remove loading
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text(state.message)),
);
}
});
context.read<AuthBloc>().add(LogoutUser());
},

Copy link

@coderabbitai coderabbitai bot left a 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

🧹 Nitpick comments (2)
mobile-v3/lib/src/app/profile/pages/widgets/settings_widget.dart (2)

123-125: Consider implementing account deletion logic.

The TODO comment indicates pending implementation. Consider creating a separate ticket to track this feature.

Would you like me to help create an issue for implementing the account deletion functionality?


157-157: Replace print statements with proper logging.

Consider replacing print statements with a proper logging mechanism for better debugging in production.

-                print("Location setting: $value");
+                log.debug("Location setting updated", {"enabled": value});

-                print("Notifications setting: $value");
+                log.debug("Notifications setting updated", {"enabled": value});

Also applies to: 172-172

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 843e0c0 and 5d081e6.

📒 Files selected for processing (1)
  • mobile-v3/lib/src/app/profile/pages/widgets/settings_widget.dart (3 hunks)
🔇 Additional comments (3)
mobile-v3/lib/src/app/profile/pages/widgets/settings_widget.dart (3)

1-3: LGTM! Clean import additions.

The new imports are well-organized and necessary for the auth functionality.


37-47: LGTM! Proper dialog context handling.

Using dialogContext instead of the outer context for dialog operations prevents potential context conflicts.


54-89: Implementation follows suggested pattern.

The logout implementation incorporates the previously suggested improvements, including:

  • Loading indicator during logout
  • Proper state handling for success and errors
  • Error boundary for unexpected exceptions

Copy link

@coderabbitai coderabbitai bot left a 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
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5d081e6 and c065691.

📒 Files selected for processing (3)
  • mobile-v3/lib/src/app/dashboard/pages/dashboard_page.dart (1 hunks)
  • mobile-v3/lib/src/app/learn/pages/lesson_finished.dart (1 hunks)
  • mobile-v3/lib/src/app/profile/pages/widgets/settings_widget.dart (3 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • mobile-v3/lib/src/app/profile/pages/widgets/settings_widget.dart
🔇 Additional comments (3)
mobile-v3/lib/src/app/learn/pages/lesson_finished.dart (2)

17-17: Nice improvement to the message tone! 👍

The change from "invite" to "teach" empowers users by recognizing their newly acquired knowledge and ability to educate others about air pollution.


21-29: Verify the removal of sharing functionality.

The commented-out sharing and rating buttons seem unrelated to the PR's logout functionality objective. Consider:

  1. If these changes are intentional, they should be in a separate PR focused on UI modifications
  2. If temporary, using version control is preferred over commenting out code

Could you clarify if removing these social features is intentional and how it relates to the logout functionality?

mobile-v3/lib/src/app/dashboard/pages/dashboard_page.dart (1)

127-170: Well-structured auth state handling!

The BlocBuilder implementation effectively manages different authentication states and provides appropriate avatar displays. The code:

  • Handles guest users with a default avatar
  • Shows user initials for authenticated users
  • Includes proper loading states

Comment on lines +109 to +126
// onTap: () {
// final authState = context.read<AuthBloc>().state;
// if (authState is GuestUser) {

Navigator.of(context).push(
MaterialPageRoute(
builder: (context) => GuestProfilePage(),
),
);
} else {
// Navigate to the regular profile page
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) => ProfilePage(),
),
);
}
},
// Navigator.of(context).push(
// MaterialPageRoute(
// builder: (context) => GuestProfilePage(),
// ),
// );
// } else {
// // Navigate to the regular profile page
// Navigator.of(context).push(
// MaterialPageRoute(
// builder: (context) => ProfilePage(),
// ),
// );
// }
// },
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Remove commented-out code instead of keeping it.

The commented-out navigation logic should be removed rather than left as comments. If this code needs to be referenced later, it can be found in the git history.

Apply this diff to clean up the code:

-                // onTap: () {
-                //   final authState = context.read<AuthBloc>().state;
-                //   if (authState is GuestUser) {
-                    
-                //     Navigator.of(context).push(
-                //       MaterialPageRoute(
-                //         builder: (context) => GuestProfilePage(),
-                //       ),
-                //     );
-                //   } else {
-                //     // Navigate to the regular profile page
-                //     Navigator.of(context).push(
-                //       MaterialPageRoute(
-                //         builder: (context) => ProfilePage(),
-                //       ),
-                //     );
-                //   }
-                // },
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
// onTap: () {
// final authState = context.read<AuthBloc>().state;
// if (authState is GuestUser) {
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) => GuestProfilePage(),
),
);
} else {
// Navigate to the regular profile page
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) => ProfilePage(),
),
);
}
},
// Navigator.of(context).push(
// MaterialPageRoute(
// builder: (context) => GuestProfilePage(),
// ),
// );
// } else {
// // Navigate to the regular profile page
// Navigator.of(context).push(
// MaterialPageRoute(
// builder: (context) => ProfilePage(),
// ),
// );
// }
// },
// (All the commented-out onTap navigation code has been removed)

Copy link

@coderabbitai coderabbitai bot left a 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

🧹 Nitpick comments (1)
mobile-v3/android/app/src/main/AndroidManifest.xml (1)

15-18: Addition of Google Places API Metadata

A new metadata entry has been added for the Google Places API key using the placeholder ${PLACES_API_KEY}. Make sure that this placeholder is defined and managed (via gradle or properties files) similarly to the maps key to avoid runtime issues with unresolved references.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c065691 and 1b270b1.

📒 Files selected for processing (2)
  • mobile-v3/android/app/build.gradle (1 hunks)
  • mobile-v3/android/app/src/main/AndroidManifest.xml (1 hunks)
🔇 Additional comments (3)
mobile-v3/android/app/src/main/AndroidManifest.xml (1)

12-13: Review of Google Maps API Metadata Update

The metadata entry for the Google Maps API key now references ${googleMapsKey}. This is a clear improvement if it aligns with the build script injection. Please double-check that your gradle configuration and manifest placeholders are consistently updated to use this new naming.

mobile-v3/android/app/build.gradle (2)

42-45: Robust Fallback for Production Google Maps API Key

The implementation that retrieves the production Google Maps API key using a fallback from the secrets file is robust. The error message clearly instructs where to define the key if missing. This helps prevent misconfiguration.


47-50: Robust Fallback for Development Google Maps API Key

Similarly, the fallback logic for the development API key improves the resiliency of key retrieval. The combined use of the properties file and secrets file is well-handled, and the error message provides precise guidance.

@Baalmart Baalmart merged commit 75924ef into staging Feb 19, 2025
31 checks passed
@Baalmart Baalmart deleted the logout-functionality branch February 19, 2025 14:21
@Baalmart Baalmart mentioned this pull request Feb 19, 2025
1 task
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants