Skip to content

feat: add badge scan mode selection and filtering support #1357

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

Open
wants to merge 4 commits into
base: development
Choose a base branch
from

Conversation

samruddhi-Rahegaonkar
Copy link
Member

@samruddhi-Rahegaonkar samruddhi-Rahegaonkar commented Jun 30, 2025

Fixes #1206

Changes

  • Added a unified BadgeScanMode enum in BadgeScanProvider.dart
  • Refactored BLE connection logic to respect user-specified scan preferences (any or specific names)
  • Created new BadgeScanSettingsWidget to allow user to configure scan mode and badge name filters via UI
  • Updated ScanState to match badge names based on the selected scan mode
  • Integrated the scan mode UI into SettingsScreen, enabling dynamic user preferences

Screenshots / Recordings

Screenshot 2025-06-30 at 7 11 55 PM Screenshot 2025-06-30 at 7 12 04 PM Screenshot 2025-06-30 at 7 12 11 PM Screenshot 2025-06-30 at 7 12 18 PM

Checklist:

  • No hard coding: I have used resources from constants.dart without hard coding any value.
  • No end of file edits: No modifications done at end of resource files.
  • Code reformatting: I have reformatted code and fixed indentation in every file included in this pull request.
  • Code analyzation: My code passes analyzations run in flutter analyze and tests run in flutter test.

Summary by Sourcery

Enable configurable badge scan modes by allowing users to choose between scanning any badge or only badges with specified names, manage these preferences via a provider, and apply the filters during BLE scanning and data transfer.

New Features:

  • Introduce BadgeScanProvider to store and manage scan mode and badge name filters
  • Add BadgeScanSettingsWidget and integrate scan mode selection UI into SettingsScreen
  • Persist and apply user-selected scan mode and badge names during BLE scanning and data transfer

Enhancements:

  • Refactor ScanState to filter scan results based on the provider’s mode and allowed badge names
  • Update badge message transfer methods to accept context and leverage scan settings
  • Refactor SettingsScreen and main app to use Provider for scan preferences and dispose controllers appropriately

Copy link
Contributor

sourcery-ai bot commented Jun 30, 2025

Reviewer's Guide

This PR introduces a new BadgeScanProvider and BadgeScanMode enum, adds UI components for selecting scan modes and badge-name filters, and refactors BLE scan and data transfer logic to honor these user preferences throughout the app.

Sequence diagram for BLE scan and data transfer with user scan preferences

sequenceDiagram
  actor User
  participant SettingsScreen
  participant BadgeScanProvider
  participant HomeScreen
  participant BadgeMessageProvider
  participant ScanState
  participant BLE

  User->>SettingsScreen: Open settings
  SettingsScreen->>BadgeScanProvider: setMode(mode), setBadgeNames(names)
  User->>HomeScreen: Initiate data transfer
  HomeScreen->>BadgeMessageProvider: checkAndTransfer(..., context)
  BadgeMessageProvider->>BadgeScanProvider: get mode, get badgeNames
  BadgeMessageProvider->>ScanState: new ScanState(manager, mode, allowedNames)
  ScanState->>BLE: scan for devices (using mode, allowedNames)
  BLE-->>ScanState: matching device found
  ScanState->>BadgeMessageProvider: proceed with connection and transfer
Loading

Class diagram for BadgeScanProvider and BadgeScanMode

classDiagram
  class BadgeScanProvider {
    - BadgeScanMode _mode
    - List<String> _badgeNames
    + BadgeScanMode get mode
    + List<String> get badgeNames
    + void setMode(BadgeScanMode mode)
    + void setBadgeNames(List<String> names)
    + void addBadgeName(String name)
    + void removeBadgeNameAt(int index)
    + void updateBadgeName(int index, String newName)
  }

  class BadgeScanMode {
    <<enum>>
    any
    specific
  }

  BadgeScanProvider ..> BadgeScanMode : uses
Loading

Class diagram for ScanState changes

classDiagram
  class ScanState {
    + DataTransferManager manager
    + BadgeScanMode mode
    + List<String> allowedNames
    + Future<BleState?> processState()
  }

  class BadgeScanMode {
    <<enum>>
    any
    specific
  }

  ScanState ..> BadgeScanMode : uses
Loading

Class diagram for BadgeScanSettingsWidget

classDiagram
  class BadgeScanSettingsWidget {
    + Function(BadgeScanMode, List<String>) onSave
  }
  class _BadgeScanSettingsWidgetState {
    - BadgeScanMode _mode
    - List<TextEditingController> _controllers
    + void _addBadgeName()
    + void _removeBadgeName(int index)
    + void _onSave()
  }
  BadgeScanSettingsWidget o-- _BadgeScanSettingsWidgetState
  _BadgeScanSettingsWidgetState ..> BadgeScanProvider : uses
  _BadgeScanSettingsWidgetState ..> BadgeScanMode : uses
Loading

File-Level Changes

Change Details Files
Introduce BadgeScanProvider and BadgeScanMode enum for managing scan preferences
  • Define BadgeScanMode enum with any/specific options and default names
  • Implement BadgeScanProvider with mode and badgeNames state and setters
  • Register the provider in main.dart under ChangeNotifierProviders
lib/providers/BadgeScanProvider.dart
lib/main.dart
Add and integrate BadgeScanSettingsWidget and scan mode UI in SettingsScreen
  • Create BadgeScanSettingsWidget to present radio buttons and dynamic badge-name fields
  • Extend SettingsScreen to include scan mode radios, inline text fields, save button
  • Extract dropdown UI into a reusable _buildDropdown helper
lib/view/badgeScanSettingsWidget.dart
lib/view/settings_screen.dart
Refactor ScanState to filter BLE devices by service UUID and selected scan mode or badge names
  • Extend ScanState constructor to accept mode and allowedNames
  • Normalize and apply badge-name filters alongside the service UUID check
  • Stop scanning on match, log mismatches, and complete with ConnectState
lib/bademagic_module/bluetooth/scan_state.dart
Update data transfer flow to consume user scan settings and pass BuildContext through BLE operations
  • Modify transferData and checkAndTransfer to take BuildContext and retrieve scanProvider
  • Initialize ScanState with provider.mode and badgeNames in transferData
  • Update all data transfer invocations (HomeScreen, SaveBadgeScreen, SaveBadgeCard) to pass context
  • Adjust imports and method signatures in badge_message_provider.dart to support new flow
lib/providers/badge_message_provider.dart
lib/view/homescreen.dart
lib/view/save_badge_screen.dart
lib/view/widgets/save_badge_card.dart

Assessment against linked issues

Issue Objective Addressed Explanation
#1206 Allow the user to select between connecting to any badge or connecting to badges with specific names.
#1206 If connecting to specific badges is selected, allow the user to input the names of the badges.

Possibly linked issues


Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

Copy link
Contributor

github-actions bot commented Jun 30, 2025

Build Status

Build successful. APKs to test: https://github.com/fossasia/badgemagic-app/actions/runs/16655413434/artifacts/3660498517.

Screenshots (Android)

Screenshots (iPhone)

Screenshots (iPad)

@samruddhi-Rahegaonkar samruddhi-Rahegaonkar force-pushed the issue1206 branch 2 times, most recently from 0b3bfe2 to de1fa4f Compare July 1, 2025 04:53
@samruddhi-Rahegaonkar samruddhi-Rahegaonkar marked this pull request as ready for review July 1, 2025 04:58
Copy link
Contributor

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

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

Hey @samruddhi-Rahegaonkar - I've reviewed your changes - here's some feedback:

  • You’re manually implementing the badge scan settings UI both in SettingsScreen and in BadgeScanSettingsWidget—extract and reuse one widget to DRY up that code.
  • The new transferData/checkAndTransfer signatures scatter the BuildContext parameter—standardize its position (e.g. always first) to keep calls consistent and readable.
  • In ScanState, make sure to cancel the scanResults subscription in finally (or after stopScan) to avoid any potential stream leaks.
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- You’re manually implementing the badge scan settings UI both in SettingsScreen and in BadgeScanSettingsWidget—extract and reuse one widget to DRY up that code.
- The new transferData/checkAndTransfer signatures scatter the BuildContext parameter—standardize its position (e.g. always first) to keep calls consistent and readable.
- In ScanState, make sure to cancel the scanResults subscription in finally (or after stopScan) to avoid any potential stream leaks.

## Individual Comments

### Comment 1
<location> `lib/providers/badge_message_provider.dart:97` </location>
<code_context>

-  Future<void> transferData(DataTransferManager manager) async {
+  /// Transfers data to the badge via BLE using current scan settings.
+  Future<void> transferData(
+    DataTransferManager manager,
+    BuildContext context,
+  ) async {
+    final scanProvider = Provider.of<BadgeScanProvider>(context, listen: false);
</code_context>

<issue_to_address>
transferData now requires BuildContext, which may not always be available.

This dependency may limit usage in non-UI or background scenarios. Consider decoupling BLE logic from BuildContext, or clearly document this requirement.
</issue_to_address>

### Comment 2
<location> `lib/view/badgeScanSettingsWidget.dart:35` </location>
<code_context>
+    });
+  }
+
+  void _removeBadgeName(int index) {
+    setState(() {
+      _controllers.removeAt(index).dispose();
+    });
</code_context>

<issue_to_address>
Controller is disposed after removal from the list, which may cause issues.

Dispose the controller before removing it from the list to prevent potential access to a disposed controller during synchronous rebuilds.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

feat: add badge scan mode selection and filtering support

fix: save and apply scan mode and badge names via provider

fix: unused variables and imports

fix: added comments

fix: resolved conflicts
Copy link
Contributor

@nope3472 nope3472 left a comment

Choose a reason for hiding this comment

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

State Inconsistency: Changing filters during a scan does not clearly cancel and restart the scan, potentially showing outdated results.

Resource Leaks: No logic prevents multiple scans from running if filters change quickly.

@samruddhi-Rahegaonkar
Copy link
Member Author

@nope3472 I have tested it on the badge and i don't think there is an issue in both the states, have you tested it on the badge itself ?

@samruddhi-Rahegaonkar
Copy link
Member Author

@nope3472 will you please tell me the exact issue like file or anything ?

@samruddhi-Rahegaonkar
Copy link
Member Author

State Inconsistency: Changing filters during a scan does not clearly cancel and restart the scan, potentially showing outdated results.

Resource Leaks: No logic prevents multiple scans from running if filters change quickly.

@nope3472
why do we will change filters during scan ? our apps flow is like Transfer -> Scan -> connect -> Transfer data, whatever the user need to do in the settings should be before Transfering the data, so i don't think this is an issue. Isn't it ?

@hpdang
Copy link
Member

hpdang commented Jul 15, 2025

Tested. Works as expected.

@hpdang hpdang self-requested a review July 15, 2025 10:26
@@ -23,6 +24,7 @@ void main() {
providers: [
ChangeNotifierProvider<InlineImageProvider>(
create: (context) => getIt<InlineImageProvider>()),
ChangeNotifierProvider(create: (_) => BadgeScanProvider()),
Copy link
Contributor

Choose a reason for hiding this comment

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

@samruddhi-Rahegaonkar try to avoid global providers if possible the BadgeScanProviders are only needed when there is ascanning or connecting to the badge happens rest of the files does not need it.

Copy link
Member Author

Choose a reason for hiding this comment

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

However, for now I've kept it global to simplify access across the current implementation and avoid extra wiring.Since it's a lightweight provider and doesn’t hold heavy state or long-lived connections, the impact should be minimal.

@@ -0,0 +1,36 @@
import 'package:flutter/material.dart';
Copy link
Contributor

Choose a reason for hiding this comment

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

@samruddhi-Rahegaonkar If we are saving the added badge using provider then if the app closes and starts it will be gone is this how this functionality is spossed to be ?

Copy link
Member Author

Choose a reason for hiding this comment

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

Yeah! for now it should work like this if we need to maintain the persistant storage then we need to use shared preferences or any other alternative.

@hpdang
Copy link
Member

hpdang commented Jul 30, 2025

@samruddhi-Rahegaonkar update please

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.

Change Select Badge Option to Enable Connection to Any Badge and User Input of other Names
4 participants