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

Feature: Fix NFC sometimes giving scanned status while not having anything scanned (KIDS-1592) #1210

Merged
merged 2 commits into from
Oct 29, 2024

Conversation

TammiLion
Copy link
Contributor

@TammiLion TammiLion commented Oct 29, 2024

Summary by CodeRabbit

Release Notes

  • New Features

    • Enhanced button functionalities across various components to support asynchronous operations, improving user experience during interactions.
  • Bug Fixes

    • Improved error handling and control flow in NFC scanning, ensuring better feedback and stability during scanning processes.
  • Documentation

    • Updated method signatures to reflect asynchronous capabilities for better clarity and future development.

@TammiLion TammiLion requested a review from a team as a code owner October 29, 2024 15:41
Copy link
Contributor

coderabbitai bot commented Oct 29, 2024

Walkthrough

The pull request introduces asynchronous modifications to various widget callback functions across multiple files. Notably, the onPressedExt parameter of the GivtBackButtonFlat widget is updated to support asynchronous operations in several classes, including CameraScreenFrame, CharityFinderAppBar, FamilySelectionScreen, NFCScanPage, and UsSignUpPage. Additionally, the ScanNfcCubit class enhances error handling and control flow with updates to several methods, allowing for improved NFC scanning functionality.

Changes

File Path Change Summary
lib/features/family/features/qr_scanner/widgets/camera_screen_frame.dart Updated onPressedExt from synchronous to asynchronous in CameraScreenFrame.
lib/features/family/features/recommendation/widgets/charity_finder_app_bar.dart Changed onPressedExt type from void Function()? to Future<void> Function()? in CharityFinderAppBar.
lib/features/family/features/reflect/presentation/pages/family_selection_screen.dart Updated onPressedExt from synchronous to asynchronous in FamilySelectionScreen.
lib/features/family/features/scan_nfc/cubit/scan_nfc_cubit.dart Modified methods for improved error handling and changed cancelScanning to return Future<void>.
lib/features/family/features/scan_nfc/nfc_scan_screen.dart Updated onPressedExt to be asynchronous in NFCScanPage and refined state handling in BlocConsumer.
lib/features/family/shared/widgets/buttons/givt_back_button_flat.dart Changed onPressedExt type from void Function()? to Future<void> Function()? and updated button handling.
lib/features/registration/pages/us_signup_page.dart Updated onPressedExt to be asynchronous in UsSignUpPage and modified listener method for state handling.

Assessment against linked issues

Objective Addressed Explanation
NFC functionality improvements (KIDS-1592)

Possibly related PRs

🐇 In the code, we hop and play,
With async calls, we pave the way.
Buttons now wait, no rush, no fuss,
NFC scans, no more to discuss!
In every click, a promise we keep,
As rabbits do, we code and leap! 🐇


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 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 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.

@github-actions github-actions bot added the bug Something isn't working label Oct 29, 2024
Copy link
Contributor

@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: 2

🧹 Outside diff range and nitpick comments (7)
lib/features/family/shared/widgets/buttons/givt_back_button_flat.dart (1)

33-34: Consider adding error handling for async operations

While the async flow is correct, it might be worth adding try-catch blocks around the onPressedExt?.call() to handle potential errors gracefully, especially since this is used in the NFC scanning flow where hardware operations could fail.

Here's a suggested improvement:

-        await onPressedExt?.call();
+        try {
+          await onPressedExt?.call();
+        } catch (e) {
+          if (context.mounted) {
+            ScaffoldMessenger.of(context).showSnackBar(
+              SnackBar(content: Text('An error occurred while going back')),
+            );
+          }
+        }
lib/features/family/features/recommendation/widgets/charity_finder_app_bar.dart (1)

24-24: Consider using BlocProvider.of for better error handling.

The async implementation looks good. However, consider using BlocProvider.of<FlowsCubit>(context) instead of context.read<FlowsCubit>() as it provides better error messages when the bloc is not found.

-            onPressedExt ?? () async => context.read<FlowsCubit>().resetFlow(),
+            onPressedExt ?? () async => BlocProvider.of<FlowsCubit>(context).resetFlow(),
lib/features/family/features/scan_nfc/cubit/scan_nfc_cubit.dart (3)

36-36: Consider adding error handling for stopSession call.

While adding the error message is good, the stopSession call could throw an exception that should be handled.

-      NfcManager.instance.stopSession(errorMessage: "stopScanningSession");
+      try {
+        await NfcManager.instance.stopSession(errorMessage: "stopScanningSession");
+      } catch (e) {
+        log('Failed to stop NFC session: $e');
+      }

135-135: Consider using a more descriptive alert message.

The current alert message is just a space character. Consider using a more meaningful message like "Scan completed" to improve user feedback.

-                  await NfcManager.instance.stopSession(alertMessage: ' ', errorMessage: 'onDiscovered');
+                  await NfcManager.instance.stopSession(alertMessage: 'Scan completed', errorMessage: 'onDiscovered');

178-178: Good error handling improvement!

The addition of error message and stack trace logging will help with debugging incorrect scan status issues.

Consider adding the error message to analytics event for better tracking:

-    AnalyticsHelper.logEvent(eventName: AmplitudeEvents.coinScannedError);
+    AnalyticsHelper.logEvent(
+      eventName: AmplitudeEvents.coinScannedError,
+      eventProperties: {'error': e.toString()},
+    );
lib/features/registration/pages/us_signup_page.dart (2)

Line range hint 256-321: Security: Consider strengthening password validation.

The current password validation requires:

  • Minimum length of 7 characters
  • At least one number
  • At least one uppercase letter

Consider enhancing security by:

  1. Increasing minimum length to 8 characters (industry standard)
  2. Requiring special characters
  3. Preventing common passwords

Line range hint 187-198: Security: Add rate limiting for registration attempts.

The _register function handles sensitive operations. Consider implementing rate limiting to prevent brute force attacks and protect user data.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between 608c3db and e246f70.

📒 Files selected for processing (7)
  • lib/features/family/features/qr_scanner/widgets/camera_screen_frame.dart (1 hunks)
  • lib/features/family/features/recommendation/widgets/charity_finder_app_bar.dart (1 hunks)
  • lib/features/family/features/reflect/presentation/pages/family_selection_screen.dart (1 hunks)
  • lib/features/family/features/scan_nfc/cubit/scan_nfc_cubit.dart (4 hunks)
  • lib/features/family/features/scan_nfc/nfc_scan_screen.dart (1 hunks)
  • lib/features/family/shared/widgets/buttons/givt_back_button_flat.dart (3 hunks)
  • lib/features/registration/pages/us_signup_page.dart (1 hunks)
🔇 Additional comments (12)
lib/features/family/shared/widgets/buttons/givt_back_button_flat.dart (3)

1-2: LGTM: Required import added for async support

The addition of dart:async import is necessary for using unawaited.


18-18: LGTM: Type signature updated for async support

The change from void Function()? to Future<void> Function()? properly reflects that the callback can now perform async operations.


28-37: Verify the order of operations in back button handler

The implementation looks correct with proper async handling, but let's verify a few aspects:

  1. Analytics and sound effects are properly fire-and-forget using unawaited
  2. Custom back action (onPressedExt) is awaited before navigation
  3. Context mounted check prevents navigation after async gap

Let's verify the usage patterns across the codebase:

✅ Verification successful

Based on the search results, I can now generate the final response:

Back button implementation follows safe async patterns

The verification confirms:

  1. All usages of GivtBackButtonFlat follow safe async patterns
  2. The original implementation with unawaited for analytics/sound and context mounted check is consistent with best practices
  3. Most usages either have no custom action or properly handle async operations before navigation
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for consistent async patterns in back button usage
# Verify that:
# 1. All usages properly await async operations
# 2. No direct context.pop() calls after async gaps without mounted check

# Search for GivtBackButtonFlat usage patterns
rg -A 5 "GivtBackButtonFlat\(" 

# Search for potential unsafe pop() calls after async operations
ast-grep --pattern 'async {
  $$$
  context.pop();
}'

Length of output: 14928

lib/features/family/features/recommendation/widgets/charity_finder_app_bar.dart (1)

17-17: Verify all callers of CharityFinderAppBar handle the async callback.

The change to make onPressedExt return Future<void> is appropriate for async operations. However, we should verify that all existing callers have been updated accordingly.

✅ Verification successful

Based on the search results, I can now generate the final response:

The async callback change is safe to proceed with

The search results show that all current usages of CharityFinderAppBar don't pass any callback to onPressedExt (they all use the default constructor with either no parameters or just showWallet). Since the parameter is optional and no existing code is actually passing a callback, the change from sync to async is non-breaking.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for all instantiations of CharityFinderAppBar to verify callback implementations
ast-grep --pattern 'CharityFinderAppBar(
  $$$
  onPressedExt: $_,
  $$$
)'

Length of output: 77


Script:

#!/bin/bash
# Let's try a broader search pattern to find usages of CharityFinderAppBar
rg "CharityFinderAppBar" -A 5 -B 5

Length of output: 7197

lib/features/family/features/qr_scanner/widgets/camera_screen_frame.dart (1)

32-34: Verify FlowsCubit's reset implementation.

The async callback change looks good and aligns with the app-wide standardization of async button handlers. However, we should verify that FlowsCubit.resetFlow() properly handles async context.

lib/features/family/features/scan_nfc/cubit/scan_nfc_cubit.dart (1)

Line range hint 100-104: Good improvement in error handling logic!

The systemIsBusy check prevents unnecessary session cancellation, which helps avoid the incorrect scan status issue mentioned in the PR objectives.

lib/features/family/features/reflect/presentation/pages/family_selection_screen.dart (2)

48-50: LGTM - Part of broader async refactoring.

The addition of the async keyword aligns with similar changes across other files, maintaining consistency in the codebase.


48-50: Consider if async is necessary here.

The callback only contains a synchronous Navigator.pop() call. Consider if the async keyword is really needed in this case, or if it's just added for consistency with other similar changes.

✅ Verification successful

Based on the analysis of the GivtBackButtonFlat widget implementation and its usages across the codebase, I can make a definitive conclusion:

The async keyword is necessary here.

The onPressedExt callback is defined as Future<void> Function()? in the widget, and several usages show that it's used to perform asynchronous operations before navigation, such as:

  1. Logging out users
  2. Resetting flows
  3. Canceling scanning operations
  4. Performing cleanup tasks

Additionally, the widget's own implementation uses await on both:

  • The onPressedExt?.call()
  • Checking context.mounted before navigation

Therefore, the async keyword is required to properly handle these asynchronous operations and ensure they complete before navigation occurs.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check if other GivtBackButtonFlat usages perform async operations
ast-grep --pattern 'GivtBackButtonFlat(
  $$$
  onPressedExt: $_($$$) async {
    $$$
  }
  $$$
)'

Length of output: 100


Script:

#!/bin/bash
# Search for GivtBackButtonFlat usages with onPressedExt
rg "GivtBackButtonFlat.*onPressedExt" -A 5

Length of output: 44


Script:

#!/bin/bash
# Search for any usage of Navigator.pop with async
ast-grep --pattern '($$$) async {
  $$$
  Navigator.of($_).pop();
  $$$
}'

Length of output: 76


Script:

#!/bin/bash
# Search for the GivtBackButtonFlat class definition to understand onPressedExt type
rg "class GivtBackButtonFlat"

Length of output: 152


Script:

#!/bin/bash
# Let's check the GivtBackButtonFlat widget implementation
cat lib/features/family/shared/widgets/buttons/givt_back_button_flat.dart

Length of output: 1174


Script:

#!/bin/bash
# Let's try a different pattern to find GivtBackButtonFlat usages
rg -l "GivtBackButtonFlat" | xargs cat

Length of output: 127584

lib/features/family/features/scan_nfc/nfc_scan_screen.dart (1)

127-129: 🛠️ Refactor suggestion

Consider improving the back button's error handling and operation order.

While making the callback async and awaiting cancelScanning() is good, there are a few improvements to consider:

  1. The flow reset should happen after successful scan cancellation to maintain UI consistency
  2. Error handling should be added for potential failures

Consider this implementation:

 onPressedExt: () async {
-  context.read<FlowsCubit>().resetFlow();
-  await context.read<ScanNfcCubit>().cancelScanning();
+  try {
+    await context.read<ScanNfcCubit>().cancelScanning();
+    context.read<FlowsCubit>().resetFlow();
+  } catch (e) {
+    // Handle cancellation failure
+    debugPrint('Failed to cancel NFC scanning: $e');
+  }
 },

Let's verify the UI state handling in the ScanNfcCubit:

lib/features/registration/pages/us_signup_page.dart (3)

99-102: LGTM: Async callback change is correct.

The conversion of onPressedExt to an async callback is consistent with the broader changes being made across the codebase to support asynchronous operations.


Line range hint 322-334: Security: Sanitize phone number input.

While there's validation for US phone numbers, ensure proper sanitization of the input to prevent potential injection attacks, especially since this data is likely stored in a database.

Let's check for input sanitization:

#!/bin/bash
# Search for phone number sanitization
rg -B 2 -A 2 "formatPhoneNrUs|phoneNumber" --type dart

99-102: Verify error handling during logout.

While the async conversion is correct, we should ensure proper error handling during logout to prevent the UI from becoming unresponsive.

Let's check the implementation of the logout helper:

Also applies to: 256-321

✅ Verification successful

Based on the code analysis, I can now provide a final response:

Error handling during logout is properly implemented

The logout implementation in AuthCubit has appropriate error handling:

  • Sets loading state before logout
  • Logs the action via LoggingInfo
  • Handles the logout operation through repository
  • Updates state to unauthenticated with preserved email
  • Clears analytics user properties
  • Any repository errors are caught and logged
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for the logout helper implementation
rg -A 5 "class LogoutHelper|void logout" --type dart

Length of output: 22484


Script:

#!/bin/bash
# Search for the logout implementation
rg -A 10 "void logout.*context" --type dart

Length of output: 45


Script:

#!/bin/bash
# Search for any auth-related logout methods
rg -A 10 "logout.*\{" --type dart

Length of output: 3754


Script:

#!/bin/bash
# Search for AuthCubit implementation which might handle logout
ast-grep --pattern 'class AuthCubit extends Cubit<$_> {
  $$$
}'

Length of output: 37725

Copy link
Contributor

@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

🧹 Outside diff range and nitpick comments (3)
lib/features/family/features/scan_nfc/cubit/scan_nfc_cubit.dart (3)

Line range hint 100-104: Add missing await for cancelScanning.

The error handling logic is good, but cancelScanning() needs to be awaited since it's now an async method.

Apply this fix:

-              cancelScanning();
+              await cancelScanning();

135-136: Document the purpose of the space in alertMessage.

The space character in alertMessage: ' ' seems like a workaround. Please add a comment explaining why this is necessary for iOS.

Apply this change:

-                  await NfcManager.instance.stopSession(alertMessage: ' ',);
+                  // iOS requires non-empty alertMessage to properly dismiss the NFC dialog
+                  await NfcManager.instance.stopSession(alertMessage: ' ',);

Line range hint 28-175: Consider architectural improvements for better maintainability.

To better handle the NFC scanning issues and improve maintainability:

  1. Extract platform-specific logic into separate classes/methods
  2. Create a dedicated service for simulator/device detection
  3. Consider using sealed classes or enums for more precise NFC scan states to prevent incorrect status

Example structure:

// Platform-specific implementations
abstract class NfcPlatformHandler {
  Future<void> stopSession();
  Future<void> startSession();
}

class IosNfcHandler extends NfcPlatformHandler { ... }
class AndroidNfcHandler extends NfcPlatformHandler { ... }

// Device detection
class DeviceEnvironment {
  Future<bool> isSimulator();
  Future<bool> isNfcAvailable();
}

// Enhanced states
enum NfcScanResult {
  ready,
  scanning,
  scanned(String mediumId),
  error(String message),
  unavailable
}
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between e246f70 and afc8adc.

📒 Files selected for processing (1)
  • lib/features/family/features/scan_nfc/cubit/scan_nfc_cubit.dart (3 hunks)

@TammiLion TammiLion merged commit 55cd189 into develop Oct 29, 2024
1 check passed
@TammiLion TammiLion deleted the bug/kids-1592-possible-nfc-fix branch October 29, 2024 16:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants