Skip to content

Commit f35b827

Browse files
chore(deps): upgrade Flutter to 3.32.1 (#1310)
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
1 parent eb6ec45 commit f35b827

File tree

11 files changed

+646
-354
lines changed

11 files changed

+646
-354
lines changed

lib/bademagic_module/bluetooth/scan_state.dart

Lines changed: 43 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,50 +1,73 @@
11
import 'dart:async';
22
import 'package:badgemagic/bademagic_module/bluetooth/connect_state.dart';
33
import 'package:badgemagic/bademagic_module/bluetooth/datagenerator.dart';
4+
import 'package:badgemagic/providers/BadgeScanProvider.dart';
45
import 'package:flutter_blue_plus/flutter_blue_plus.dart';
56

67
import 'base_ble_state.dart';
78

89
class ScanState extends NormalBleState {
910
final DataTransferManager manager;
10-
ScanState({required this.manager});
11+
final BadgeScanMode mode;
12+
final List<String> allowedNames;
13+
14+
ScanState({
15+
required this.manager,
16+
required this.mode,
17+
required this.allowedNames,
18+
});
1119

1220
@override
1321
Future<BleState?> processState() async {
1422
StreamSubscription<List<ScanResult>>? subscription;
1523
toast.showToast("Searching for device...");
1624

17-
Completer<BleState?> nextStateCompleter = Completer();
25+
final Completer<BleState?> nextStateCompleter = Completer();
1826
bool isCompleted = false;
1927

20-
ScanResult? foundDevice;
21-
2228
try {
2329
subscription = FlutterBluePlus.scanResults.listen(
2430
(results) async {
25-
if (!isCompleted) {
26-
if (results.isNotEmpty) {
27-
foundDevice = results.firstWhere(
28-
(result) => result.advertisementData.serviceUuids
29-
.contains(Guid("0000fee0-0000-1000-8000-00805f9b34fb")),
30-
);
31-
if (foundDevice != null) {
32-
toast.showToast('Device found. Connecting...');
33-
isCompleted = true;
34-
nextStateCompleter.complete(ConnectState(
35-
scanResult: foundDevice!,
36-
manager: manager,
37-
));
38-
}
39-
}
31+
if (isCompleted || results.isEmpty) return;
32+
33+
try {
34+
final normalizedAllowedNames = allowedNames
35+
.map((e) => e.trim().toLowerCase())
36+
.where((e) => e.isNotEmpty)
37+
.toList();
38+
39+
final foundDevice = results.firstWhere(
40+
(result) {
41+
final matchesUuid = result.advertisementData.serviceUuids
42+
.contains(Guid("0000fee0-0000-1000-8000-00805f9b34fb"));
43+
44+
final deviceName = result.device.name.trim().toLowerCase();
45+
final matchesName = mode == BadgeScanMode.any ||
46+
normalizedAllowedNames.contains(deviceName);
47+
48+
return matchesUuid && matchesName;
49+
},
50+
orElse: () => throw Exception("Matching device not found."),
51+
);
52+
53+
isCompleted = true;
54+
FlutterBluePlus.stopScan();
55+
toast.showToast('Device found. Connecting...');
56+
57+
nextStateCompleter.complete(ConnectState(
58+
scanResult: foundDevice,
59+
manager: manager,
60+
));
61+
} catch (e) {
62+
logger.w("No matching device found in this batch: $e");
4063
}
4164
},
4265
onError: (e) async {
4366
if (!isCompleted) {
4467
isCompleted = true;
4568
logger.e("Scan error: $e");
4669
toast.showErrorToast('Scan error occurred.');
47-
nextStateCompleter.completeError(e);
70+
nextStateCompleter.completeError(Exception("Scan error: $e"));
4871
}
4972
},
5073
);

lib/main.dart

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import 'package:badgemagic/providers/BadgeScanProvider.dart';
12
import 'package:badgemagic/providers/getitlocator.dart';
23
import 'package:badgemagic/providers/imageprovider.dart';
34
import 'package:badgemagic/view/about_us_screen.dart';
@@ -23,6 +24,7 @@ void main() {
2324
providers: [
2425
ChangeNotifierProvider<InlineImageProvider>(
2526
create: (context) => getIt<InlineImageProvider>()),
27+
ChangeNotifierProvider(create: (_) => BadgeScanProvider()),
2628
],
2729
child: const MyApp(),
2830
));

lib/providers/BadgeScanProvider.dart

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import 'package:flutter/material.dart';
2+
3+
enum BadgeScanMode { any, specific }
4+
5+
class BadgeScanProvider with ChangeNotifier {
6+
BadgeScanMode _mode = BadgeScanMode.any;
7+
List<String> _badgeNames = ['LSLED', 'VBLAB'];
8+
9+
BadgeScanMode get mode => _mode;
10+
List<String> get badgeNames => List.unmodifiable(_badgeNames);
11+
12+
void setMode(BadgeScanMode mode) {
13+
_mode = mode;
14+
notifyListeners();
15+
}
16+
17+
void setBadgeNames(List<String> names) {
18+
_badgeNames = names.where((name) => name.trim().isNotEmpty).toList();
19+
notifyListeners();
20+
}
21+
22+
void addBadgeName(String name) {
23+
_badgeNames.add(name);
24+
notifyListeners();
25+
}
26+
27+
void removeBadgeNameAt(int index) {
28+
_badgeNames.removeAt(index);
29+
notifyListeners();
30+
}
31+
32+
void updateBadgeName(int index, String newName) {
33+
_badgeNames[index] = newName;
34+
notifyListeners();
35+
}
36+
}

lib/providers/badge_message_provider.dart

Lines changed: 84 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,24 @@
11
import 'dart:io';
22
import 'package:badgemagic/bademagic_module/bluetooth/base_ble_state.dart';
33
import 'package:badgemagic/bademagic_module/bluetooth/datagenerator.dart';
4-
import 'package:badgemagic/bademagic_module/utils/converters.dart';
5-
import 'package:badgemagic/bademagic_module/utils/file_helper.dart';
6-
import 'package:badgemagic/bademagic_module/utils/toast_utils.dart';
74
import 'package:badgemagic/bademagic_module/bluetooth/scan_state.dart';
85
import 'package:badgemagic/bademagic_module/models/data.dart';
96
import 'package:badgemagic/bademagic_module/models/messages.dart';
107
import 'package:badgemagic/bademagic_module/models/mode.dart';
118
import 'package:badgemagic/bademagic_module/models/speed.dart';
9+
import 'package:badgemagic/bademagic_module/utils/converters.dart';
10+
import 'package:badgemagic/bademagic_module/utils/file_helper.dart';
11+
import 'package:badgemagic/bademagic_module/utils/toast_utils.dart';
12+
import 'package:badgemagic/providers/BadgeScanProvider.dart';
1213
import 'package:badgemagic/providers/imageprovider.dart';
14+
import 'package:flutter/widgets.dart';
1315
import 'package:flutter_blue_plus/flutter_blue_plus.dart';
1416
import 'package:get_it/get_it.dart';
1517
import 'package:logger/logger.dart';
18+
import 'package:provider/provider.dart';
1619

17-
Map<int, Mode> modeValueMap = {
20+
/// Maps for speed and mode enums.
21+
final Map<int, Mode> modeValueMap = {
1822
0: Mode.left,
1923
1: Mode.right,
2024
2: Mode.up,
@@ -26,7 +30,7 @@ Map<int, Mode> modeValueMap = {
2630
8: Mode.laser
2731
};
2832

29-
Map<int, Speed> speedMap = {
33+
final Map<int, Speed> speedMap = {
3034
1: Speed.one,
3135
2: Speed.two,
3236
3: Speed.three,
@@ -39,84 +43,120 @@ Map<int, Speed> speedMap = {
3943

4044
class BadgeMessageProvider {
4145
static final Logger logger = Logger();
42-
InlineImageProvider controllerData =
46+
final InlineImageProvider controllerData =
4347
GetIt.instance.get<InlineImageProvider>();
44-
FileHelper fileHelper = FileHelper();
45-
Converters converters = Converters();
48+
final FileHelper fileHelper = FileHelper();
49+
final Converters converters = Converters();
4650

47-
Future<Data> getBadgeData(String text, bool flash, bool marq, Speed speed,
48-
Mode mode, bool isInverted) async {
49-
List<String> message = await converters.messageTohex(text, isInverted);
50-
Data data = Data(messages: [
51+
/// Generates badge data from text and config.
52+
Future<Data> getBadgeData(
53+
String text,
54+
bool flash,
55+
bool marq,
56+
Speed speed,
57+
Mode mode,
58+
bool isInverted,
59+
) async {
60+
final hexMessage = await converters.messageTohex(text, isInverted);
61+
return Data(messages: [
5162
Message(
52-
text: message,
63+
text: hexMessage,
5364
flash: flash,
5465
marquee: marq,
5566
speed: speed,
5667
mode: mode,
5768
)
5869
]);
59-
return data;
6070
}
6171

72+
/// Returns badge data from json or input fields.
6273
Future<Data> generateData(
63-
String? text,
64-
bool? flash,
65-
bool? marq,
66-
bool? inverted,
67-
Speed? speed,
68-
Mode? mode,
69-
Map<String, dynamic>? jsonData) async {
74+
String? text,
75+
bool? flash,
76+
bool? marq,
77+
bool? inverted,
78+
Speed? speed,
79+
Mode? mode,
80+
Map<String, dynamic>? jsonData,
81+
) async {
7082
if (jsonData != null) {
7183
return fileHelper.jsonToData(jsonData);
7284
} else {
73-
return getBadgeData(text ?? '', flash ?? false, marq ?? false,
74-
speed ?? Speed.one, mode ?? Mode.left, inverted ?? false);
85+
return getBadgeData(
86+
text ?? '',
87+
flash ?? false,
88+
marq ?? false,
89+
speed ?? Speed.one,
90+
mode ?? Mode.left,
91+
inverted ?? false,
92+
);
7593
}
7694
}
7795

78-
Future<void> transferData(DataTransferManager manager) async {
96+
/// Transfers data to the badge via BLE using current scan settings.
97+
Future<void> transferData(
98+
DataTransferManager manager,
99+
BuildContext context,
100+
) async {
101+
final scanProvider = Provider.of<BadgeScanProvider>(context, listen: false);
102+
103+
final BleState? initialState = ScanState(
104+
manager: manager,
105+
mode: scanProvider.mode,
106+
allowedNames: scanProvider.badgeNames,
107+
);
108+
109+
BleState? state = initialState;
79110
DateTime now = DateTime.now();
80-
BleState? state = ScanState(manager: manager);
111+
81112
while (state != null) {
82113
state = await state.process();
83114
}
84115

85-
logger.d("Time to transfer data is = ${DateTime.now().difference(now)}");
116+
logger.d("Time to transfer data: ${DateTime.now().difference(now)}");
86117
logger.d(".......Data transfer completed.......");
87118
}
88119

120+
/// Public method to initiate check and transfer sequence.
89121
Future<void> checkAndTransfer(
90-
String? text,
91-
bool? flash,
92-
bool? marq,
93-
bool? isInverted,
94-
int? speed,
95-
Mode? mode,
96-
Map<String, dynamic>? jsonData,
97-
bool isSavedBadge) async {
122+
String? text,
123+
bool? flash,
124+
bool? marq,
125+
bool? isInverted,
126+
int? speed,
127+
Mode? mode,
128+
Map<String, dynamic>? jsonData,
129+
bool isSavedBadge,
130+
BuildContext context,
131+
) async {
132+
// Check for Bluetooth support
98133
if (await FlutterBluePlus.isSupported == false) {
99134
ToastUtils().showErrorToast('Bluetooth is not supported by the device');
100135
return;
101136
}
102137

103-
if (controllerData.getController().text.isEmpty && isSavedBadge == false) {
138+
// Skip if no message typed and not saved
139+
if (controllerData.getController().text.isEmpty && !isSavedBadge) {
104140
ToastUtils().showErrorToast("Please enter a message");
105141
return;
106142
}
107143

108144
final adapterState = await FlutterBluePlus.adapterState.first;
145+
109146
if (adapterState == BluetoothAdapterState.on) {
110-
Data data;
111-
if (jsonData != null) {
112-
data = fileHelper.jsonToData(jsonData);
113-
} else {
114-
data = await generateData(
115-
text, flash, marq, isInverted, speedMap[speed], mode, jsonData);
116-
}
117-
DataTransferManager manager = DataTransferManager(data);
118-
await transferData(manager);
147+
final data = await generateData(
148+
text,
149+
flash,
150+
marq,
151+
isInverted,
152+
speedMap[speed],
153+
mode,
154+
jsonData,
155+
);
156+
final manager = DataTransferManager(data);
157+
await transferData(manager, context);
119158
} else {
159+
// Try enabling Bluetooth
120160
if (Platform.isAndroid) {
121161
ToastUtils().showToast('Turning on Bluetooth...');
122162
await FlutterBluePlus.turnOn();

0 commit comments

Comments
 (0)