From 3547d8b0b0468770c773a03295502f48b602443e Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 3 Jun 2025 23:00:55 +0000 Subject: [PATCH 1/9] 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 --- .../bluetooth/scan_state.dart | 49 +++-- lib/main.dart | 2 + lib/providers/BadgeScanProvider.dart | 36 ++++ lib/view/badgeScanSettingsWidget.dart | 133 ++++++++++++ lib/view/save_badge_screen.dart | 18 +- lib/view/settings_screen.dart | 191 ++++++++++++------ lib/view/widgets/save_badge_card.dart | 140 +++++++++++-- 7 files changed, 464 insertions(+), 105 deletions(-) create mode 100644 lib/providers/BadgeScanProvider.dart create mode 100644 lib/view/badgeScanSettingsWidget.dart diff --git a/lib/bademagic_module/bluetooth/scan_state.dart b/lib/bademagic_module/bluetooth/scan_state.dart index 04c2a02bf..b9c7818e6 100644 --- a/lib/bademagic_module/bluetooth/scan_state.dart +++ b/lib/bademagic_module/bluetooth/scan_state.dart @@ -1,13 +1,20 @@ import 'dart:async'; import 'package:badgemagic/bademagic_module/bluetooth/connect_state.dart'; import 'package:badgemagic/bademagic_module/bluetooth/datagenerator.dart'; +import 'package:badgemagic/providers/BadgeScanProvider.dart'; import 'package:flutter_blue_plus/flutter_blue_plus.dart'; import 'base_ble_state.dart'; class ScanState extends NormalBleState { final DataTransferManager manager; + final BadgeScanMode mode; + final List allowedNames; - ScanState({required this.manager}); + ScanState({ + required this.manager, + required this.mode, + required this.allowedNames, + }); @override Future processState() async { @@ -25,21 +32,35 @@ class ScanState extends NormalBleState { if (isCompleted || results.isEmpty) return; try { + final normalizedAllowedNames = allowedNames + .map((e) => e.trim().toLowerCase()) + .where((e) => e.isNotEmpty) + .toList(); + final foundDevice = results.firstWhere( - (r) => r.advertisementData.serviceUuids.contains( - Guid("0000fee0-0000-1000-8000-00805f9b34fb"), - ), + (result) { + final matchesUuid = result.advertisementData.serviceUuids + .contains(Guid("0000fee0-0000-1000-8000-00805f9b34fb")); + + final deviceName = result.device.name.trim().toLowerCase(); + final matchesName = mode == BadgeScanMode.any || + normalizedAllowedNames.contains(deviceName); + + return matchesUuid && matchesName; + }, orElse: () => throw Exception("Matching device not found."), ); isCompleted = true; - await FlutterBluePlus.stopScan(); + FlutterBluePlus.stopScan(); toast.showToast('Device found. Connecting...'); - nextStateCompleter.complete( - ConnectState(scanResult: foundDevice, manager: manager), - ); - } catch (_) { - // Ignore and keep scanning + + nextStateCompleter.complete(ConnectState( + scanResult: foundDevice, + manager: manager, + )); + } catch (e) { + logger.w("No matching device found in this batch: $e"); } }, onError: (e) { @@ -48,19 +69,19 @@ class ScanState extends NormalBleState { FlutterBluePlus.stopScan(); logger.e("Scan error: $e"); toast.showErrorToast('Scan error occurred.'); +<<<<<<< HEAD nextStateCompleter.completeError( Exception("Error during scanning: $e"), ); +======= + nextStateCompleter.completeError(Exception("Scan error: $e")); +>>>>>>> f35b827 (chore(deps): upgrade Flutter to 3.32.1 (#1310)) } }, ); - await FlutterBluePlus.startScan( withServices: [Guid("0000fee0-0000-1000-8000-00805f9b34fb")], removeIfGone: const Duration(seconds: 5), - continuousUpdates: true, - timeout: const Duration(seconds: 15), - ); await Future.delayed(const Duration(seconds: 1)); diff --git a/lib/main.dart b/lib/main.dart index 7ea48008c..63e1f8370 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,3 +1,4 @@ +import 'package:badgemagic/providers/BadgeScanProvider.dart'; import 'package:badgemagic/providers/getitlocator.dart'; import 'package:badgemagic/providers/imageprovider.dart'; import 'package:badgemagic/view/about_us_screen.dart'; @@ -23,6 +24,7 @@ void main() { providers: [ ChangeNotifierProvider( create: (context) => getIt()), + ChangeNotifierProvider(create: (_) => BadgeScanProvider()), ], child: const MyApp(), )); diff --git a/lib/providers/BadgeScanProvider.dart b/lib/providers/BadgeScanProvider.dart new file mode 100644 index 000000000..e01690f5e --- /dev/null +++ b/lib/providers/BadgeScanProvider.dart @@ -0,0 +1,36 @@ +import 'package:flutter/material.dart'; + +enum BadgeScanMode { any, specific } + +class BadgeScanProvider with ChangeNotifier { + BadgeScanMode _mode = BadgeScanMode.any; + List _badgeNames = ['LSLED', 'VBLAB']; + + BadgeScanMode get mode => _mode; + List get badgeNames => List.unmodifiable(_badgeNames); + + void setMode(BadgeScanMode mode) { + _mode = mode; + notifyListeners(); + } + + void setBadgeNames(List names) { + _badgeNames = names.where((name) => name.trim().isNotEmpty).toList(); + notifyListeners(); + } + + void addBadgeName(String name) { + _badgeNames.add(name); + notifyListeners(); + } + + void removeBadgeNameAt(int index) { + _badgeNames.removeAt(index); + notifyListeners(); + } + + void updateBadgeName(int index, String newName) { + _badgeNames[index] = newName; + notifyListeners(); + } +} diff --git a/lib/view/badgeScanSettingsWidget.dart b/lib/view/badgeScanSettingsWidget.dart new file mode 100644 index 000000000..bcd054226 --- /dev/null +++ b/lib/view/badgeScanSettingsWidget.dart @@ -0,0 +1,133 @@ +import 'package:badgemagic/providers/BadgeScanProvider.dart'; +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; + +class BadgeScanSettingsWidget extends StatefulWidget { + final Function(BadgeScanMode mode, List names) onSave; + + const BadgeScanSettingsWidget({super.key, required this.onSave}); + + @override + State createState() => + _BadgeScanSettingsWidgetState(); +} + +class _BadgeScanSettingsWidgetState extends State { + late BadgeScanMode _mode; + final List _controllers = []; + + @override + void initState() { + super.initState(); + final provider = Provider.of(context, listen: false); + _mode = provider.mode; + for (var name in provider.badgeNames) { + _controllers.add(TextEditingController(text: name)); + } + } + + void _addBadgeName() { + setState(() { + _controllers.add(TextEditingController()); + }); + } + + void _removeBadgeName(int index) { + setState(() { + _controllers.removeAt(index).dispose(); + }); + } + + void _onSave() { + final updatedNames = _controllers + .map((c) => c.text.trim()) + .where((name) => name.isNotEmpty) + .toList(); + + final provider = Provider.of(context, listen: false); + provider.setMode(_mode); + provider.setBadgeNames(updatedNames); + + ScaffoldMessenger.of(context).showSnackBar( + const SnackBar(content: Text('Scan settings saved successfully')), + ); + + widget.onSave(_mode, updatedNames); + Navigator.pop(context); + } + + @override + void dispose() { + for (var c in _controllers) { + c.dispose(); + } + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + title: const Text('Badge Scan Settings'), + actions: [ + IconButton( + icon: const Icon(Icons.save), + onPressed: _onSave, + ), + ], + ), + body: Column( + children: [ + RadioListTile( + title: const Text('Connect to any badge'), + value: BadgeScanMode.any, + groupValue: _mode, + onChanged: (val) => setState(() => _mode = val!), + ), + RadioListTile( + title: const Text('Connect to badges with the following names'), + value: BadgeScanMode.specific, + groupValue: _mode, + onChanged: (val) => setState(() => _mode = val!), + ), + if (_mode == BadgeScanMode.specific) + Expanded( + child: ListView.builder( + itemCount: _controllers.length, + itemBuilder: (context, index) { + return Row( + children: [ + Expanded( + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 12.0), + child: TextField( + controller: _controllers[index], + decoration: const InputDecoration( + labelText: 'Badge Name', + ), + ), + ), + ), + IconButton( + icon: const Icon(Icons.remove_circle_outline), + onPressed: () => _removeBadgeName(index), + ), + ], + ); + }, + ), + ), + if (_mode == BadgeScanMode.specific) + Padding( + padding: const EdgeInsets.all(12.0), + child: ElevatedButton.icon( + onPressed: _addBadgeName, + icon: const Icon(Icons.add), + label: const Text("Add more"), + ), + ), + ], + ), + ); + } +} diff --git a/lib/view/save_badge_screen.dart b/lib/view/save_badge_screen.dart index 5937b3036..b384a6999 100644 --- a/lib/view/save_badge_screen.dart +++ b/lib/view/save_badge_screen.dart @@ -253,15 +253,15 @@ class _SaveBadgeScreenState extends State { final data = Data(messages: badgeDataList); badgeMessageProvider.checkAndTransfer( - null, - null, - null, - null, - null, - null, - data.toJson(), - true, - ); + null, + null, + null, + null, + null, + null, + data.toJson(), + true, + context); } : null, style: ElevatedButton.styleFrom( diff --git a/lib/view/settings_screen.dart b/lib/view/settings_screen.dart index e986d4c27..8791ac9f7 100644 --- a/lib/view/settings_screen.dart +++ b/lib/view/settings_screen.dart @@ -1,7 +1,9 @@ import 'package:badgemagic/constants.dart'; +import 'package:badgemagic/providers/BadgeScanProvider.dart'; import 'package:badgemagic/view/widgets/common_scaffold_widget.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; +import 'package:provider/provider.dart'; class SettingsScreen extends StatefulWidget { const SettingsScreen({super.key}); @@ -12,15 +14,21 @@ class SettingsScreen extends StatefulWidget { class SettingsScreenState extends State { String selectedLanguage = 'ENGLISH'; - String selectedBadge = 'LSLED'; - final List languages = ['ENGLISH', 'CHINESE']; - final List badges = ['LSLED', 'VBLAB']; + + late BadgeScanMode _scanMode; + late List _controllers; @override void initState() { - _setOrientation(); super.initState(); + _setOrientation(); + + final scanProvider = Provider.of(context, listen: false); + _scanMode = scanProvider.mode; + _controllers = scanProvider.badgeNames + .map((name) => TextEditingController(text: name)) + .toList(); } void _setOrientation() { @@ -30,83 +38,134 @@ class SettingsScreenState extends State { ]); } + @override + void dispose() { + for (final controller in _controllers) { + controller.dispose(); + } + super.dispose(); + } + @override Widget build(BuildContext context) { return CommonScaffold( index: 4, + title: 'Badge Magic', body: Padding( padding: const EdgeInsets.all(16.0), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, + child: ListView( children: [ - const Text( - 'Language', - style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold), + const Text('Language', + style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold)), + const SizedBox(height: 8), + _buildDropdown( + selectedValue: selectedLanguage, + values: languages, + onChanged: (value) => setState(() => selectedLanguage = value), ), + const SizedBox(height: 24), + const Text('Badge Scan Mode', + style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold)), const SizedBox(height: 8), - Container( - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(8), - ), - padding: const EdgeInsets.symmetric(horizontal: 12), - child: DropdownButtonHideUnderline( - child: DropdownButton( - value: selectedLanguage, - isExpanded: true, - icon: Icon(Icons.arrow_drop_down, color: mdGrey400), - onChanged: (String? newValue) { - setState(() { - selectedLanguage = newValue!; - }); - }, - items: - languages.map>((String value) { - return DropdownMenuItem( - value: value, - child: Text(value, - style: const TextStyle(color: Colors.black)), - ); - }).toList(), - ), - ), + RadioListTile( + title: const Text('Connect to any badge'), + value: BadgeScanMode.any, + groupValue: _scanMode, + onChanged: (value) => setState(() => _scanMode = value!), ), - const SizedBox(height: 20), - const Text( - 'Select Badge', - style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold), + RadioListTile( + title: const Text('Connect to badges with the following names'), + value: BadgeScanMode.specific, + groupValue: _scanMode, + onChanged: (value) => setState(() => _scanMode = value!), ), - const SizedBox(height: 8), - Container( - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(8), - ), - padding: const EdgeInsets.symmetric(horizontal: 12), - child: DropdownButtonHideUnderline( - child: DropdownButton( - value: selectedBadge, - isExpanded: true, - icon: Icon(Icons.arrow_drop_down, color: mdGrey400), - onChanged: (String? newValue) { - setState(() { - selectedBadge = newValue!; - }); - }, - items: badges.map>((String value) { - return DropdownMenuItem( - value: value, - child: Text(value, - style: const TextStyle(color: Colors.black)), - ); - }).toList(), - ), + if (_scanMode == BadgeScanMode.specific) + ..._controllers.asMap().entries.map((entry) { + final index = entry.key; + final controller = entry.value; + return Row( + children: [ + Expanded( + child: Padding( + padding: const EdgeInsets.symmetric(vertical: 4), + child: TextField( + controller: controller, + decoration: const InputDecoration( + hintText: 'Badge name', + border: OutlineInputBorder(), + ), + ), + ), + ), + IconButton( + icon: const Icon(Icons.remove_circle_outline), + onPressed: () { + setState(() { + controller.dispose(); + _controllers.removeAt(index); + }); + }, + ), + ], + ); + }).toList(), + if (_scanMode == BadgeScanMode.specific) + TextButton.icon( + onPressed: () => setState(() { + _controllers.add(TextEditingController()); + }), + icon: const Icon(Icons.add), + label: const Text('Add More'), ), - ), + const SizedBox(height: 24), + ElevatedButton.icon( + onPressed: () { + final provider = + Provider.of(context, listen: false); + provider.setMode(_scanMode); + provider.setBadgeNames( + _controllers.map((c) => c.text.trim()).toList(), + ); + ScaffoldMessenger.of(context).showSnackBar( + const SnackBar(content: Text('Scan settings saved')), + ); + }, + icon: const Icon(Icons.save), + label: const Text("Save Settings"), + ) ], ), ), - title: 'Badge Magic', + ); + } + + Widget _buildDropdown({ + required String selectedValue, + required List values, + required Function(String) onChanged, + }) { + return Container( + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(8), + ), + padding: const EdgeInsets.symmetric(horizontal: 12), + child: DropdownButtonHideUnderline( + child: DropdownButton( + value: selectedValue, + isExpanded: true, + icon: Icon(Icons.arrow_drop_down, color: mdGrey400), + onChanged: (String? newValue) { + if (newValue != null) onChanged(newValue); + }, + items: values.map>((String value) { + return DropdownMenuItem( + value: value, + child: Text(value, style: const TextStyle(color: Colors.black)), + ); + }).toList(), + ), + ), ); } } diff --git a/lib/view/widgets/save_badge_card.dart b/lib/view/widgets/save_badge_card.dart index 2bc5ebed4..133a79d65 100644 --- a/lib/view/widgets/save_badge_card.dart +++ b/lib/view/widgets/save_badge_card.dart @@ -72,22 +72,130 @@ class SaveBadgeCard extends StatelessWidget { @override Widget build(BuildContext context) { BadgeMessageProvider badge = BadgeMessageProvider(); - return GestureDetector( - onLongPress: onLongPress, - onTap: onTap, - child: Container( - width: 370.w, - padding: EdgeInsets.all(6.dg), - margin: EdgeInsets.all(10.dg), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(6.dg), - boxShadow: [ - BoxShadow( - color: Colors.grey.withOpacity(0.5), - spreadRadius: 2, - blurRadius: 5, - offset: const Offset(0, 3), + return Container( + width: 370.w, + padding: EdgeInsets.all(6.dg), + margin: EdgeInsets.all(10.dg), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(6.dg), + boxShadow: [ + BoxShadow( + color: Colors.grey.withOpacity(0.5), + spreadRadius: 2, + blurRadius: 5, + offset: const Offset(0, 3), + ), + ], + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + // Wrapping the text with Flexible to ensure it doesn't overflow. + Flexible( + child: Padding( + padding: EdgeInsets.only( + right: 8 + .w), // Adding some padding to separate text and buttons + child: Text( + badgeData.key.substring(0, badgeData.key.length - 5), + style: const TextStyle( + fontWeight: FontWeight.bold, + fontSize: 16, + ), + softWrap: true, + overflow: TextOverflow + .ellipsis, // Use ellipsis to indicate overflowed text + maxLines: 1, // Limit to 1 line for a cleaner look + ), + ), + ), + Consumer( + builder: (context, provider, widget) => Row( + mainAxisSize: MainAxisSize.min, // Keep the row compact + children: [ + IconButton( + icon: Image.asset( + "assets/icons/t_play.png", + height: 20, + color: Colors.black, + ), + onPressed: () { + provider.savedBadgeAnimation( + badgeData.value, + Provider.of(context, + listen: false)); + }, + ), + IconButton( + icon: const Icon( + Icons.edit, + color: Colors.black, + ), + onPressed: () { + List> data = hexStringToBool(file + .jsonToData(badgeData.value) + .messages[0] + .text + .join()) + .map((e) => e.map((e) => e ? 1 : 0).toList()) + .toList(); + Navigator.of(context).push( + MaterialPageRoute( + builder: (context) => DrawBadge( + filename: badgeData.key, + isSavedCard: true, + badgeGrid: data, + ), + ), + ); + }, + ), + IconButton( + icon: Image.asset( + "assets/icons/t_updown.png", + height: 24.h, + color: Colors.black, + ), + onPressed: () { + logger.d("BadgeData: ${badgeData.value}"); + //We can Acrtually call a method to generate the data just by transffering the JSON data + //so we would not necessarily need the Providers. + badge.checkAndTransfer(null, null, null, null, null, + null, badgeData.value, true, context); + }, + ), + IconButton( + icon: const Icon( + Icons.share, + color: Colors.black, + ), + onPressed: () { + file.shareBadgeData(badgeData.key); + }, + ), + IconButton( + icon: const Icon( + Icons.delete, + color: Colors.black, + ), + onPressed: () async { + //add a dialog for confirmation before deleting + await _showDeleteDialog(context).then((value) async { + if (value == true) { + file.deleteFile(badgeData.key); + toastUtils.showToast("Badge Deleted Successfully"); + await refreshBadgesCallback(badgeData); + } + }); + }, + ), + ], + ), ), ], border: From c0d5c8e7278c26f6c4af365ad04c7ed2c37b39e7 Mon Sep 17 00:00:00 2001 From: Samruddhi Rahegaonkar Date: Thu, 7 Aug 2025 21:26:02 +0530 Subject: [PATCH 2/9] fix: fix to resolve conflicts --- .../bluetooth/scan_state.dart | 9 +- lib/view/save_badge_screen.dart | 1 - lib/view/widgets/save_badge_card.dart | 2 +- pubspec.lock | 841 ------------------ pubspec.yaml | 1 - 5 files changed, 5 insertions(+), 849 deletions(-) delete mode 100644 pubspec.lock diff --git a/lib/bademagic_module/bluetooth/scan_state.dart b/lib/bademagic_module/bluetooth/scan_state.dart index b9c7818e6..e24bf6e81 100644 --- a/lib/bademagic_module/bluetooth/scan_state.dart +++ b/lib/bademagic_module/bluetooth/scan_state.dart @@ -69,19 +69,18 @@ class ScanState extends NormalBleState { FlutterBluePlus.stopScan(); logger.e("Scan error: $e"); toast.showErrorToast('Scan error occurred.'); -<<<<<<< HEAD nextStateCompleter.completeError( Exception("Error during scanning: $e"), ); -======= - nextStateCompleter.completeError(Exception("Scan error: $e")); ->>>>>>> f35b827 (chore(deps): upgrade Flutter to 3.32.1 (#1310)) } }, ); await FlutterBluePlus.startScan( withServices: [Guid("0000fee0-0000-1000-8000-00805f9b34fb")], - removeIfGone: const Duration(seconds: 5), + removeIfGone: Duration(seconds: 5), + continuousUpdates: true, + timeout: const Duration(seconds: 15), // Reduced scan timeout. + ); await Future.delayed(const Duration(seconds: 1)); diff --git a/lib/view/save_badge_screen.dart b/lib/view/save_badge_screen.dart index b384a6999..22fece260 100644 --- a/lib/view/save_badge_screen.dart +++ b/lib/view/save_badge_screen.dart @@ -227,7 +227,6 @@ class _SaveBadgeScreenState extends State { badgeData['messages'][0]); badgeDataList.add(message); } - while (badgeDataList.length < 8) { badgeDataList.add(Message(text: [])); } diff --git a/lib/view/widgets/save_badge_card.dart b/lib/view/widgets/save_badge_card.dart index 133a79d65..a4814be65 100644 --- a/lib/view/widgets/save_badge_card.dart +++ b/lib/view/widgets/save_badge_card.dart @@ -100,7 +100,7 @@ class SaveBadgeCard extends StatelessWidget { child: Padding( padding: EdgeInsets.only( right: 8 - .w), // Adding some padding to separate text and buttons + .w), // Adding some padding to separate text and buttons. child: Text( badgeData.key.substring(0, badgeData.key.length - 5), style: const TextStyle( diff --git a/pubspec.lock b/pubspec.lock deleted file mode 100644 index 86c2c198e..000000000 --- a/pubspec.lock +++ /dev/null @@ -1,841 +0,0 @@ -# Generated by pub -# See https://dart.dev/tools/pub/glossary#lockfile -packages: - _fe_analyzer_shared: - dependency: transitive - description: - name: _fe_analyzer_shared - sha256: a169e44fe3506e212963b56a0497aa4e711e68a269a4d645873c1849aabf1515 - url: "https://pub.dev" - source: hosted - version: "87.0.0" - analyzer: - dependency: transitive - description: - name: analyzer - sha256: "731195f2f1837dc1bf0dcc60bbfca0d769181a7bcf4b98221738b2b61a3f058d" - url: "https://pub.dev" - source: hosted - version: "8.1.0" - archive: - dependency: transitive - description: - name: archive - sha256: "2fde1607386ab523f7a36bb3e7edb43bd58e6edaf2ffb29d8a6d578b297fdbbd" - url: "https://pub.dev" - source: hosted - version: "4.0.7" - args: - dependency: transitive - description: - name: args - sha256: d0481093c50b1da8910eb0bb301626d4d8eb7284aa739614d2b394ee09e3ea04 - url: "https://pub.dev" - source: hosted - version: "2.7.0" - async: - dependency: transitive - description: - name: async - sha256: "758e6d74e971c3e5aceb4110bfd6698efc7f501675bcfe0c775459a8140750eb" - url: "https://pub.dev" - source: hosted - version: "2.13.0" - bluez: - dependency: transitive - description: - name: bluez - sha256: "61a7204381925896a374301498f2f5399e59827c6498ae1e924aaa598751b545" - url: "https://pub.dev" - source: hosted - version: "0.8.3" - boolean_selector: - dependency: transitive - description: - name: boolean_selector - sha256: "8aab1771e1243a5063b8b0ff68042d67334e3feab9e95b9490f9a6ebf73b42ea" - url: "https://pub.dev" - source: hosted - version: "2.1.2" - characters: - dependency: transitive - description: - name: characters - sha256: f71061c654a3380576a52b451dd5532377954cf9dbd272a78fc8479606670803 - url: "https://pub.dev" - source: hosted - version: "1.4.0" - clock: - dependency: transitive - description: - name: clock - sha256: fddb70d9b5277016c77a80201021d40a2247104d9f4aa7bab7157b7e3f05b84b - url: "https://pub.dev" - source: hosted - version: "1.1.2" - collection: - dependency: transitive - description: - name: collection - sha256: "2f5709ae4d3d59dd8f7cd309b4e023046b57d8a6c82130785d2b0e5868084e76" - url: "https://pub.dev" - source: hosted - version: "1.19.1" - convert: - dependency: transitive - description: - name: convert - sha256: b30acd5944035672bc15c6b7a8b47d773e41e2f17de064350988c5d02adb1c68 - url: "https://pub.dev" - source: hosted - version: "3.1.2" - cross_file: - dependency: transitive - description: - name: cross_file - sha256: "7caf6a750a0c04effbb52a676dce9a4a592e10ad35c34d6d2d0e4811160d5670" - url: "https://pub.dev" - source: hosted - version: "0.3.4+2" - crypto: - dependency: transitive - description: - name: crypto - sha256: "1e445881f28f22d6140f181e07737b22f1e099a5e1ff94b0af2f9e4a463f4855" - url: "https://pub.dev" - source: hosted - version: "3.0.6" - cupertino_icons: - dependency: "direct main" - description: - name: cupertino_icons - sha256: ba631d1c7f7bef6b729a622b7b752645a2d076dba9976925b8f25725a30e1ee6 - url: "https://pub.dev" - source: hosted - version: "1.0.8" - dart_style: - dependency: "direct dev" - description: - name: dart_style - sha256: c87dfe3d56f183ffe9106a18aebc6db431fc7c98c31a54b952a77f3d54a85697 - url: "https://pub.dev" - source: hosted - version: "3.1.2" - dbus: - dependency: transitive - description: - name: dbus - sha256: "79e0c23480ff85dc68de79e2cd6334add97e48f7f4865d17686dd6ea81a47e8c" - url: "https://pub.dev" - source: hosted - version: "0.7.11" - extended_text_field: - dependency: "direct main" - description: - name: extended_text_field - sha256: "3996195c117c6beb734026a7bc0ba80d7e4e84e4edd4728caa544d8209ab4d7d" - url: "https://pub.dev" - source: hosted - version: "16.0.2" - extended_text_library: - dependency: transitive - description: - name: extended_text_library - sha256: "13d99f8a10ead472d5e2cf4770d3d047203fe5054b152e9eb5dc692a71befbba" - url: "https://pub.dev" - source: hosted - version: "12.0.1" - fake_async: - dependency: transitive - description: - name: fake_async - sha256: "5368f224a74523e8d2e7399ea1638b37aecfca824a3cc4dfdf77bf1fa905ac44" - url: "https://pub.dev" - source: hosted - version: "1.3.3" - ffi: - dependency: transitive - description: - name: ffi - sha256: "289279317b4b16eb2bb7e271abccd4bf84ec9bdcbe999e278a94b804f5630418" - url: "https://pub.dev" - source: hosted - version: "2.1.4" - file: - dependency: transitive - description: - name: file - sha256: a3b4f84adafef897088c160faf7dfffb7696046cb13ae90b508c2cbc95d3b8d4 - url: "https://pub.dev" - source: hosted - version: "7.0.1" - file_picker: - dependency: "direct main" - description: - name: file_picker - sha256: "8f9f429998f9232d65bc4757af74475ce44fc80f10704ff5dfa8b1d14fc429b9" - url: "https://pub.dev" - source: hosted - version: "10.2.3" - fixnum: - dependency: transitive - description: - name: fixnum - sha256: b6dc7065e46c974bc7c5f143080a6764ec7a4be6da1285ececdc37be96de53be - url: "https://pub.dev" - source: hosted - version: "1.1.1" - flutter: - dependency: "direct main" - description: flutter - source: sdk - version: "0.0.0" - flutter_blue_plus: - dependency: "direct main" - description: - name: flutter_blue_plus - sha256: bfae0d24619940516261045d8b3c74b4c80ca82222426e05ffbf7f3ea9dbfb1a - url: "https://pub.dev" - source: hosted - version: "1.35.5" - flutter_blue_plus_android: - dependency: transitive - description: - name: flutter_blue_plus_android - sha256: "9723dd4ba7dcc3f27f8202e1159a302eb4cdb88ae482bb8e0dd733b82230a258" - url: "https://pub.dev" - source: hosted - version: "4.0.5" - flutter_blue_plus_darwin: - dependency: transitive - description: - name: flutter_blue_plus_darwin - sha256: f34123795352a9761e321589aa06356d3b53f007f13f7e23e3c940e733259b2d - url: "https://pub.dev" - source: hosted - version: "4.0.1" - flutter_blue_plus_linux: - dependency: transitive - description: - name: flutter_blue_plus_linux - sha256: "635443d1d333e3695733fd70e81ee0d87fa41e78aa81844103d2a8a854b0d593" - url: "https://pub.dev" - source: hosted - version: "3.0.2" - flutter_blue_plus_platform_interface: - dependency: transitive - description: - name: flutter_blue_plus_platform_interface - sha256: a4bb70fa6fd09e0be163b004d773bf19e31104e257a4eb846b67f884ddd87de2 - url: "https://pub.dev" - source: hosted - version: "4.0.2" - flutter_blue_plus_web: - dependency: transitive - description: - name: flutter_blue_plus_web - sha256: "03023c259dbbba1bc5ce0fcd4e88b364f43eec01d45425f393023b9b2722cf4d" - url: "https://pub.dev" - source: hosted - version: "3.0.1" - flutter_driver: - dependency: transitive - description: flutter - source: sdk - version: "0.0.0" - flutter_lints: - dependency: "direct dev" - description: - name: flutter_lints - sha256: "3105dc8492f6183fb076ccf1f351ac3d60564bff92e20bfc4af9cc1651f4e7e1" - url: "https://pub.dev" - source: hosted - version: "6.0.0" - flutter_plugin_android_lifecycle: - dependency: transitive - description: - name: flutter_plugin_android_lifecycle - sha256: "6382ce712ff69b0f719640ce957559dde459e55ecd433c767e06d139ddf16cab" - url: "https://pub.dev" - source: hosted - version: "2.0.29" - flutter_screenutil: - dependency: "direct main" - description: - name: flutter_screenutil - sha256: "8239210dd68bee6b0577aa4a090890342d04a136ce1c81f98ee513fc0ce891de" - url: "https://pub.dev" - source: hosted - version: "5.9.3" - flutter_svg: - dependency: "direct main" - description: - name: flutter_svg - sha256: cd57f7969b4679317c17af6fd16ee233c1e60a82ed209d8a475c54fd6fd6f845 - url: "https://pub.dev" - source: hosted - version: "2.2.0" - flutter_test: - dependency: "direct dev" - description: flutter - source: sdk - version: "0.0.0" - flutter_web_plugins: - dependency: transitive - description: flutter - source: sdk - version: "0.0.0" - fuchsia_remote_debug_protocol: - dependency: transitive - description: flutter - source: sdk - version: "0.0.0" - get_it: - dependency: "direct main" - description: - name: get_it - sha256: a4292e7cf67193f8e7c1258203104eb2a51ec8b3a04baa14695f4064c144297b - url: "https://pub.dev" - source: hosted - version: "8.2.0" - glob: - dependency: transitive - description: - name: glob - sha256: c3f1ee72c96f8f78935e18aa8cecced9ab132419e8625dc187e1c2408efc20de - url: "https://pub.dev" - source: hosted - version: "2.1.3" - go_router: - dependency: "direct main" - description: - name: go_router - sha256: "8b1f37dfaf6e958c6b872322db06f946509433bec3de753c3491a42ae9ec2b48" - url: "https://pub.dev" - source: hosted - version: "16.1.0" - google_fonts: - dependency: "direct main" - description: - name: google_fonts - sha256: df9763500dadba0155373e9cb44e202ce21bd9ed5de6bdbd05c5854e86839cb8 - url: "https://pub.dev" - source: hosted - version: "6.3.0" - http: - dependency: transitive - description: - name: http - sha256: bb2ce4590bc2667c96f318d68cac1b5a7987ec819351d32b1c987239a815e007 - url: "https://pub.dev" - source: hosted - version: "1.5.0" - http_parser: - dependency: transitive - description: - name: http_parser - sha256: "178d74305e7866013777bab2c3d8726205dc5a4dd935297175b19a23a2e66571" - url: "https://pub.dev" - source: hosted - version: "4.1.2" - image: - dependency: "direct main" - description: - name: image - sha256: "4e973fcf4caae1a4be2fa0a13157aa38a8f9cb049db6529aa00b4d71abc4d928" - url: "https://pub.dev" - source: hosted - version: "4.5.4" - integration_test: - dependency: "direct dev" - description: flutter - source: sdk - version: "0.0.0" - leak_tracker: - dependency: transitive - description: - name: leak_tracker - sha256: "6bb818ecbdffe216e81182c2f0714a2e62b593f4a4f13098713ff1685dfb6ab0" - url: "https://pub.dev" - source: hosted - version: "10.0.9" - leak_tracker_flutter_testing: - dependency: transitive - description: - name: leak_tracker_flutter_testing - sha256: f8b613e7e6a13ec79cfdc0e97638fddb3ab848452eff057653abd3edba760573 - url: "https://pub.dev" - source: hosted - version: "3.0.9" - leak_tracker_testing: - dependency: transitive - description: - name: leak_tracker_testing - sha256: "6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3" - url: "https://pub.dev" - source: hosted - version: "3.0.1" - lints: - dependency: transitive - description: - name: lints - sha256: a5e2b223cb7c9c8efdc663ef484fdd95bb243bff242ef5b13e26883547fce9a0 - url: "https://pub.dev" - source: hosted - version: "6.0.0" - logger: - dependency: "direct main" - description: - name: logger - sha256: "55d6c23a6c15db14920e037fe7e0dc32e7cdaf3b64b4b25df2d541b5b6b81c0c" - url: "https://pub.dev" - source: hosted - version: "2.6.1" - logging: - dependency: transitive - description: - name: logging - sha256: c8245ada5f1717ed44271ed1c26b8ce85ca3228fd2ffdb75468ab01979309d61 - url: "https://pub.dev" - source: hosted - version: "1.3.0" - matcher: - dependency: transitive - description: - name: matcher - sha256: dc58c723c3c24bf8d3e2d3ad3f2f9d7bd9cf43ec6feaa64181775e60190153f2 - url: "https://pub.dev" - source: hosted - version: "0.12.17" - material_color_utilities: - dependency: transitive - description: - name: material_color_utilities - sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec - url: "https://pub.dev" - source: hosted - version: "0.11.1" - meta: - dependency: transitive - description: - name: meta - sha256: e3641ec5d63ebf0d9b41bd43201a66e3fc79a65db5f61fc181f04cd27aab950c - url: "https://pub.dev" - source: hosted - version: "1.16.0" - mime: - dependency: transitive - description: - name: mime - sha256: "41a20518f0cb1256669420fdba0cd90d21561e560ac240f26ef8322e45bb7ed6" - url: "https://pub.dev" - source: hosted - version: "2.0.0" - nested: - dependency: transitive - description: - name: nested - sha256: "03bac4c528c64c95c722ec99280375a6f2fc708eec17c7b3f07253b626cd2a20" - url: "https://pub.dev" - source: hosted - version: "1.0.0" - package_config: - dependency: transitive - description: - name: package_config - sha256: f096c55ebb7deb7e384101542bfba8c52696c1b56fca2eb62827989ef2353bbc - url: "https://pub.dev" - source: hosted - version: "2.2.0" - path: - dependency: transitive - description: - name: path - sha256: "75cca69d1490965be98c73ceaea117e8a04dd21217b37b292c9ddbec0d955bc5" - url: "https://pub.dev" - source: hosted - version: "1.9.1" - path_parsing: - dependency: transitive - description: - name: path_parsing - sha256: "883402936929eac138ee0a45da5b0f2c80f89913e6dc3bf77eb65b84b409c6ca" - url: "https://pub.dev" - source: hosted - version: "1.1.0" - path_provider: - dependency: "direct main" - description: - name: path_provider - sha256: "50c5dd5b6e1aaf6fb3a78b33f6aa3afca52bf903a8a5298f53101fdaee55bbcd" - url: "https://pub.dev" - source: hosted - version: "2.1.5" - path_provider_android: - dependency: transitive - description: - name: path_provider_android - sha256: d0d310befe2c8ab9e7f393288ccbb11b60c019c6b5afc21973eeee4dda2b35e9 - url: "https://pub.dev" - source: hosted - version: "2.2.17" - path_provider_foundation: - dependency: transitive - description: - name: path_provider_foundation - sha256: "4843174df4d288f5e29185bd6e72a6fbdf5a4a4602717eed565497429f179942" - url: "https://pub.dev" - source: hosted - version: "2.4.1" - path_provider_linux: - dependency: transitive - description: - name: path_provider_linux - sha256: f7a1fe3a634fe7734c8d3f2766ad746ae2a2884abe22e241a8b301bf5cac3279 - url: "https://pub.dev" - source: hosted - version: "2.2.1" - path_provider_platform_interface: - dependency: transitive - description: - name: path_provider_platform_interface - sha256: "88f5779f72ba699763fa3a3b06aa4bf6de76c8e5de842cf6f29e2e06476c2334" - url: "https://pub.dev" - source: hosted - version: "2.1.2" - path_provider_windows: - dependency: transitive - description: - name: path_provider_windows - sha256: bd6f00dbd873bfb70d0761682da2b3a2c2fccc2b9e84c495821639601d81afe7 - url: "https://pub.dev" - source: hosted - version: "2.3.0" - petitparser: - dependency: transitive - description: - name: petitparser - sha256: "07c8f0b1913bcde1ff0d26e57ace2f3012ccbf2b204e070290dad3bb22797646" - url: "https://pub.dev" - source: hosted - version: "6.1.0" - platform: - dependency: transitive - description: - name: platform - sha256: "5d6b1b0036a5f331ebc77c850ebc8506cbc1e9416c27e59b439f917a902a4984" - url: "https://pub.dev" - source: hosted - version: "3.1.6" - plugin_platform_interface: - dependency: transitive - description: - name: plugin_platform_interface - sha256: "4820fbfdb9478b1ebae27888254d445073732dae3d6ea81f0b7e06d5dedc3f02" - url: "https://pub.dev" - source: hosted - version: "2.1.8" - posix: - dependency: transitive - description: - name: posix - sha256: "6323a5b0fa688b6a010df4905a56b00181479e6d10534cecfecede2aa55add61" - url: "https://pub.dev" - source: hosted - version: "6.0.3" - process: - dependency: transitive - description: - name: process - sha256: "107d8be718f120bbba9dcd1e95e3bd325b1b4a4f07db64154635ba03f2567a0d" - url: "https://pub.dev" - source: hosted - version: "5.0.3" - provider: - dependency: "direct main" - description: - name: provider - sha256: "4abbd070a04e9ddc287673bf5a030c7ca8b685ff70218720abab8b092f53dd84" - url: "https://pub.dev" - source: hosted - version: "6.1.5" - pub_semver: - dependency: transitive - description: - name: pub_semver - sha256: "5bfcf68ca79ef689f8990d1160781b4bad40a3bd5e5218ad4076ddb7f4081585" - url: "https://pub.dev" - source: hosted - version: "2.2.0" - rxdart: - dependency: transitive - description: - name: rxdart - sha256: "5c3004a4a8dbb94bd4bf5412a4def4acdaa12e12f269737a5751369e12d1a962" - url: "https://pub.dev" - source: hosted - version: "0.28.0" - share_plus: - dependency: "direct main" - description: - name: share_plus - sha256: b2961506569e28948d75ec346c28775bb111986bb69dc6a20754a457e3d97fa0 - url: "https://pub.dev" - source: hosted - version: "11.0.0" - share_plus_platform_interface: - dependency: transitive - description: - name: share_plus_platform_interface - sha256: "1032d392bc5d2095a77447a805aa3f804d2ae6a4d5eef5e6ebb3bd94c1bc19ef" - url: "https://pub.dev" - source: hosted - version: "6.0.0" - sky_engine: - dependency: transitive - description: flutter - source: sdk - version: "0.0.0" - source_span: - dependency: transitive - description: - name: source_span - sha256: "254ee5351d6cb365c859e20ee823c3bb479bf4a293c22d17a9f1bf144ce86f7c" - url: "https://pub.dev" - source: hosted - version: "1.10.1" - sprintf: - dependency: transitive - description: - name: sprintf - sha256: "1fc9ffe69d4df602376b52949af107d8f5703b77cda567c4d7d86a0693120f23" - url: "https://pub.dev" - source: hosted - version: "7.0.0" - stack_trace: - dependency: transitive - description: - name: stack_trace - sha256: "8b27215b45d22309b5cddda1aa2b19bdfec9df0e765f2de506401c071d38d1b1" - url: "https://pub.dev" - source: hosted - version: "1.12.1" - stream_channel: - dependency: transitive - description: - name: stream_channel - sha256: "969e04c80b8bcdf826f8f16579c7b14d780458bd97f56d107d3950fdbeef059d" - url: "https://pub.dev" - source: hosted - version: "2.1.4" - string_scanner: - dependency: transitive - description: - name: string_scanner - sha256: "921cd31725b72fe181906c6a94d987c78e3b98c2e205b397ea399d4054872b43" - url: "https://pub.dev" - source: hosted - version: "1.4.1" - sync_http: - dependency: transitive - description: - name: sync_http - sha256: "7f0cd72eca000d2e026bcd6f990b81d0ca06022ef4e32fb257b30d3d1014a961" - url: "https://pub.dev" - source: hosted - version: "0.3.1" - term_glyph: - dependency: transitive - description: - name: term_glyph - sha256: "7f554798625ea768a7518313e58f83891c7f5024f88e46e7182a4558850a4b8e" - url: "https://pub.dev" - source: hosted - version: "1.2.2" - test_api: - dependency: transitive - description: - name: test_api - sha256: fb31f383e2ee25fbbfe06b40fe21e1e458d14080e3c67e7ba0acfde4df4e0bbd - url: "https://pub.dev" - source: hosted - version: "0.7.4" - typed_data: - dependency: transitive - description: - name: typed_data - sha256: f9049c039ebfeb4cf7a7104a675823cd72dba8297f264b6637062516699fa006 - url: "https://pub.dev" - source: hosted - version: "1.4.0" - url_launcher: - dependency: "direct main" - description: - name: url_launcher - sha256: f6a7e5c4835bb4e3026a04793a4199ca2d14c739ec378fdfe23fc8075d0439f8 - url: "https://pub.dev" - source: hosted - version: "6.3.2" - url_launcher_android: - dependency: transitive - description: - name: url_launcher_android - sha256: "0aedad096a85b49df2e4725fa32118f9fa580f3b14af7a2d2221896a02cd5656" - url: "https://pub.dev" - source: hosted - version: "6.3.17" - url_launcher_ios: - dependency: transitive - description: - name: url_launcher_ios - sha256: "7f2022359d4c099eea7df3fdf739f7d3d3b9faf3166fb1dd390775176e0b76cb" - url: "https://pub.dev" - source: hosted - version: "6.3.3" - url_launcher_linux: - dependency: transitive - description: - name: url_launcher_linux - sha256: "4e9ba368772369e3e08f231d2301b4ef72b9ff87c31192ef471b380ef29a4935" - url: "https://pub.dev" - source: hosted - version: "3.2.1" - url_launcher_macos: - dependency: transitive - description: - name: url_launcher_macos - sha256: "17ba2000b847f334f16626a574c702b196723af2a289e7a93ffcb79acff855c2" - url: "https://pub.dev" - source: hosted - version: "3.2.2" - url_launcher_platform_interface: - dependency: transitive - description: - name: url_launcher_platform_interface - sha256: "552f8a1e663569be95a8190206a38187b531910283c3e982193e4f2733f01029" - url: "https://pub.dev" - source: hosted - version: "2.3.2" - url_launcher_web: - dependency: transitive - description: - name: url_launcher_web - sha256: "4bd2b7b4dc4d4d0b94e5babfffbca8eac1a126c7f3d6ecbc1a11013faa3abba2" - url: "https://pub.dev" - source: hosted - version: "2.4.1" - url_launcher_windows: - dependency: transitive - description: - name: url_launcher_windows - sha256: "3284b6d2ac454cf34f114e1d3319866fdd1e19cdc329999057e44ffe936cfa77" - url: "https://pub.dev" - source: hosted - version: "3.1.4" - uuid: - dependency: "direct main" - description: - name: uuid - sha256: a5be9ef6618a7ac1e964353ef476418026db906c4facdedaa299b7a2e71690ff - url: "https://pub.dev" - source: hosted - version: "4.5.1" - vector_graphics: - dependency: transitive - description: - name: vector_graphics - sha256: a4f059dc26fc8295b5921376600a194c4ec7d55e72f2fe4c7d2831e103d461e6 - url: "https://pub.dev" - source: hosted - version: "1.1.19" - vector_graphics_codec: - dependency: transitive - description: - name: vector_graphics_codec - sha256: "99fd9fbd34d9f9a32efd7b6a6aae14125d8237b10403b422a6a6dfeac2806146" - url: "https://pub.dev" - source: hosted - version: "1.1.13" - vector_graphics_compiler: - dependency: transitive - description: - name: vector_graphics_compiler - sha256: "557a315b7d2a6dbb0aaaff84d857967ce6bdc96a63dc6ee2a57ce5a6ee5d3331" - url: "https://pub.dev" - source: hosted - version: "1.1.17" - vector_math: - dependency: transitive - description: - name: vector_math - sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803" - url: "https://pub.dev" - source: hosted - version: "2.1.4" - vm_service: - dependency: transitive - description: - name: vm_service - sha256: ddfa8d30d89985b96407efce8acbdd124701f96741f2d981ca860662f1c0dc02 - url: "https://pub.dev" - source: hosted - version: "15.0.0" - watcher: - dependency: transitive - description: - name: watcher - sha256: "0b7fd4a0bbc4b92641dbf20adfd7e3fd1398fe17102d94b674234563e110088a" - url: "https://pub.dev" - source: hosted - version: "1.1.2" - web: - dependency: transitive - description: - name: web - sha256: "868d88a33d8a87b18ffc05f9f030ba328ffefba92d6c127917a2ba740f9cfe4a" - url: "https://pub.dev" - source: hosted - version: "1.1.1" - webdriver: - dependency: transitive - description: - name: webdriver - sha256: "2f3a14ca026957870cfd9c635b83507e0e51d8091568e90129fbf805aba7cade" - url: "https://pub.dev" - source: hosted - version: "3.1.0" - win32: - dependency: transitive - description: - name: win32 - sha256: "66814138c3562338d05613a6e368ed8cfb237ad6d64a9e9334be3f309acfca03" - url: "https://pub.dev" - source: hosted - version: "5.14.0" - xdg_directories: - dependency: transitive - description: - name: xdg_directories - sha256: "7a3f37b05d989967cdddcbb571f1ea834867ae2faa29725fd085180e0883aa15" - url: "https://pub.dev" - source: hosted - version: "1.1.0" - xml: - dependency: transitive - description: - name: xml - sha256: b015a8ad1c488f66851d762d3090a21c600e479dc75e68328c52774040cf9226 - url: "https://pub.dev" - source: hosted - version: "6.5.0" - yaml: - dependency: transitive - description: - name: yaml - sha256: b9da305ac7c39faa3f030eccd175340f968459dae4af175130b3fc47e40d76ce - url: "https://pub.dev" - source: hosted - version: "3.1.3" -sdks: - dart: ">=3.8.0 <4.0.0" - flutter: ">=3.32.4" diff --git a/pubspec.yaml b/pubspec.yaml index 4e3330083..6154ebf87 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -110,4 +110,3 @@ flutter: # # For details regarding fonts from package dependencies, # see https://flutter.dev/custom-fonts/#from-packages - From 21a66bb739bbb6966bc0f0a9088e53a2bd497551 Mon Sep 17 00:00:00 2001 From: Samruddhi Rahegaonkar Date: Sat, 16 Aug 2025 14:43:55 +0530 Subject: [PATCH 3/9] fix: fixing the logic ans conflicts --- lib/providers/animation_badge_provider.dart | 124 +--- lib/view/homescreen.dart | 648 +++++++------------- lib/view/widgets/save_badge_card.dart | 394 ++++-------- 3 files changed, 354 insertions(+), 812 deletions(-) diff --git a/lib/providers/animation_badge_provider.dart b/lib/providers/animation_badge_provider.dart index 00d79dd5b..f941d82d5 100644 --- a/lib/providers/animation_badge_provider.dart +++ b/lib/providers/animation_badge_provider.dart @@ -1,7 +1,4 @@ import 'dart:async'; -import 'package:badgemagic/providers/badge_message_provider.dart'; -import 'package:badgemagic/providers/imageprovider.dart'; -import 'package:badgemagic/providers/speed_dial_provider.dart'; import 'package:badgemagic/bademagic_module/utils/byte_array_utils.dart'; import 'package:badgemagic/bademagic_module/utils/converters.dart'; import 'package:badgemagic/badge_animation/ani_animation.dart'; @@ -13,10 +10,6 @@ import 'package:badgemagic/badge_animation/ani_picture.dart'; import 'package:badgemagic/badge_animation/ani_right.dart'; import 'package:badgemagic/badge_animation/ani_snowflake.dart'; import 'package:badgemagic/badge_animation/ani_up.dart'; -import 'package:badgemagic/badge_animation/ani_pacman.dart'; -import 'package:badgemagic/badge_animation/ani_chevron_left.dart'; -import 'package:badgemagic/badge_animation/ani_diamond.dart'; -import 'package:badgemagic/badge_animation/ani_broken_hearts.dart'; import 'package:badgemagic/badge_animation/animation_abstract.dart'; import 'package:badgemagic/badge_effect/badgeeffectabstract.dart'; import 'package:badgemagic/badge_effect/flash_effect.dart'; @@ -25,15 +18,6 @@ import 'package:badgemagic/badge_effect/marquee_effect.dart'; import 'package:badgemagic/constants.dart'; import 'package:flutter/material.dart'; -import 'package:badgemagic/badge_animation/ani_cupid.dart'; -import 'package:badgemagic/badge_animation/ani_feet.dart'; -import 'package:badgemagic/badge_animation/ani_fish.dart'; -import 'package:badgemagic/badge_animation/ani_diagonal.dart'; - -import 'package:badgemagic/badge_animation/ani_emergency.dart'; -import 'package:badgemagic/badge_animation/ani_beating_hearts.dart'; -import 'package:badgemagic/badge_animation/ani_fireworks.dart'; - Map animationMap = { 0: LeftAnimation(), 1: RightAnimation(), @@ -44,17 +28,6 @@ Map animationMap = { 6: SnowFlakeAnimation(), 7: PictureAnimation(), 8: LaserAnimation(), - 9: PacmanClassicAnimation(), // Pacman - 10: LeftChevronAnimation(), // Chevron left - 11: DiamondAnimation(), // Diamond - 12: BrokenHeartsAnimation(), // Broken Hearts - 13: CupidAnimation(), // Cupid - 14: FeetAnimation(), // Feet - 15: FishAnimation(), // Fish - 16: DiagonalAnimation(), // Diagonal - 17: EmergencyAnimation(), // Emergency - 18: BeatingHeartsAnimation(), // Beating Hearts - 19: FireworksAnimation(), // Fireworks }; Map effectMap = { @@ -81,33 +54,9 @@ class AnimationBadgeProvider extends ChangeNotifier { //function to get the state of the cell List> getPaintGrid() => _paintGrid; - // Helper: returns true if a special animation (custom) is selected - bool isSpecialAnimationSelected() { - int idx = getAnimationIndex() ?? 0; - // Add all special animation indices here (including Fireworks at 19): - return [9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19].contains(idx); - } - - // Call this to reset to text animation (LeftAnimation) - void resetToTextAnimation() { - setAnimationMode(LeftAnimation()); - } - //function to calculate duration for the animation void calculateDuration(int speed) { - int idx = getAnimationIndex() ?? 0; - int newSpeed; - if (idx == 9 || idx == 10 || idx == 11 || idx == 12) { - // Use slower mapping for custom animations - // (aniSpeedStrategy already uses the slower mapping if you want, or you can hardcode) - newSpeed = aniSpeedStrategy(speed - 1); // keep as is, or adjust if needed - } else { - // Use original (faster) mapping for text/standard animations - // For original: aniBaseSpeed = 200000us, minSpeed = 25000us (example) - const int originalBase = 200000; - const int minSpeed = 25000; - newSpeed = originalBase - ((speed - 1) * (originalBase - minSpeed) ~/ 8); - } + int newSpeed = aniSpeedStrategy(speed - 1); if (newSpeed != _animationSpeed) { _animationSpeed = newSpeed; _timer?.cancel(); @@ -178,27 +127,18 @@ class AnimationBadgeProvider extends ChangeNotifier { void startTimer() { _timer = Timer.periodic(Duration(microseconds: _animationSpeed), (Timer timer) { + // logger.i( + // "New Grid set to: ${getNewGrid().map((e) => e.map((e) => e ? 1 : 0).toList()).toList()}"); renderGrid(getNewGrid()); - if (_currentAnimation is CupidAnimation) { - int frameLimit = - CupidAnimation.frameCount(_paintGrid[0].length, _paintGrid.length); - _animationIndex = (_animationIndex + 1) % frameLimit; - } else { - _animationIndex++; - } + _animationIndex++; }); } void setAnimationMode(BadgeAnimation? animation) { - // Always reset the animation index and set the new animation _animationIndex = 0; _currentAnimation = animation ?? LeftAnimation(); - // Stop the timer if running - _timer?.cancel(); - // Start the timer for the new animation - startTimer(); notifyListeners(); - logger.i("Animation Mode set to: $_currentAnimation and timer restarted"); + logger.i("Animation Mode set to: $_currentAnimation"); } int? getAnimationIndex() { @@ -218,8 +158,7 @@ class AnimationBadgeProvider extends ChangeNotifier { void badgeAnimation( String message, Converters converters, bool isInverted) async { - bool isSpecial = isSpecialAnimationSelected(); - if (message.isEmpty && !isSpecial) { + if (message.isEmpty) { stopAllAnimations(); List> emptyGrid = List.generate(11, (i) => List.generate(44, (j) => false)); @@ -253,55 +192,4 @@ class AnimationBadgeProvider extends ChangeNotifier { _paintGrid = canvas; notifyListeners(); } - - /// Handles animation transfer selection logic for the current animation index. - Future handleAnimationTransfer({ - required BadgeMessageProvider badgeData, - required InlineImageProvider inlineImageProvider, - required SpeedDialProvider speedDialProvider, - required bool flash, - required bool marquee, - required bool invert, - }) async { - final int aniIndex = getAnimationIndex() ?? 0; - final int selectedSpeed = speedDialProvider.getOuterValue(); - if (aniIndex == 9) { - // Pacman - await transferPacmanAnimation(badgeData, selectedSpeed); - } else if (aniIndex == 10) { - await transferChevronAnimation(badgeData, selectedSpeed); - } else if (aniIndex == 11) { - await transferDiamondAnimation(badgeData, selectedSpeed); - } else if (aniIndex == 12) { - await transferBrokenHeartsAnimation(badgeData, selectedSpeed); - } else if (aniIndex == 13) { - await transferCupidAnimation(badgeData, selectedSpeed); - setAnimationMode(CupidAnimation()); - _animationIndex = 0; - if (_timer == null || !_timer!.isActive) startTimer(); - } else if (aniIndex == 14) { - await transferFeetAnimation(badgeData, selectedSpeed); - } else if (aniIndex == 15) { - await transferFishAnimation(badgeData, selectedSpeed); - } else if (aniIndex == 16) { - await transferDiagonalAnimation(badgeData, selectedSpeed); - } else if (aniIndex == 17) { - await transferEmergencyAnimation(badgeData, selectedSpeed); - } else if (aniIndex == 18) { - await transferBeatingHeartsAnimation(badgeData, selectedSpeed); - } else if (aniIndex == 19) { - await transferFireworksAnimation(badgeData, selectedSpeed); - } else { - await badgeData.checkAndTransfer( - inlineImageProvider.getController().text, - flash, - marquee, - invert, - selectedSpeed, - modeValueMap[aniIndex], - null, - false, - ); - } - } } diff --git a/lib/view/homescreen.dart b/lib/view/homescreen.dart index fffe5b545..8fc6f33bc 100644 --- a/lib/view/homescreen.dart +++ b/lib/view/homescreen.dart @@ -1,25 +1,19 @@ import 'dart:async'; -import 'package:badgemagic/bademagic_module/utils/badge_loader_helper.dart'; -import 'package:badgemagic/badge_effect/flash_effect.dart'; -import 'package:badgemagic/badge_effect/invert_led_effect.dart'; -import 'package:badgemagic/badge_effect/marquee_effect.dart'; import 'package:badgemagic/bademagic_module/utils/converters.dart'; - import 'package:badgemagic/bademagic_module/utils/image_utils.dart'; import 'package:badgemagic/bademagic_module/utils/toast_utils.dart'; -import 'package:badgemagic/bademagic_module/models/speed.dart'; +import 'package:badgemagic/badge_effect/flash_effect.dart'; +import 'package:badgemagic/badge_effect/invert_led_effect.dart'; +import 'package:badgemagic/badge_effect/marquee_effect.dart'; import 'package:badgemagic/constants.dart'; import 'package:badgemagic/providers/animation_badge_provider.dart'; -import 'package:badgemagic/providers/badge_message_provider.dart' - hide modeValueMap, speedMap; +import 'package:badgemagic/providers/badge_message_provider.dart'; import 'package:badgemagic/providers/imageprovider.dart'; -import 'package:badgemagic/providers/saved_badge_provider.dart'; import 'package:badgemagic/providers/speed_dial_provider.dart'; import 'package:badgemagic/view/special_text_field.dart'; import 'package:badgemagic/view/widgets/common_scaffold_widget.dart'; import 'package:badgemagic/view/widgets/homescreentabs.dart'; -import 'package:badgemagic/view/widgets/transitiontab.dart'; import 'package:badgemagic/view/widgets/save_badge_dialog.dart'; import 'package:badgemagic/view/widgets/speedial.dart'; import 'package:badgemagic/view/widgets/vectorview.dart'; @@ -32,16 +26,7 @@ import 'package:get_it/get_it.dart'; import 'package:provider/provider.dart'; class HomeScreen extends StatefulWidget { - // Add parameters for saved badge data when editing - - final String? savedBadgeFilename; - final int? initialSpeed; - - const HomeScreen({ - super.key, - this.savedBadgeFilename, - this.initialSpeed, - }); + const HomeScreen({super.key}); @override State createState() => _HomeScreenState(); @@ -53,81 +38,97 @@ class _HomeScreenState extends State AutomaticKeepAliveClientMixin, WidgetsBindingObserver { late final TabController _tabController; - AnimationBadgeProvider animationProvider = AnimationBadgeProvider(); late SpeedDialProvider speedDialProvider; - BadgeMessageProvider badgeData = BadgeMessageProvider(); - ImageUtils imageUtils = ImageUtils(); - InlineImageProvider inlineImageProvider = + final AnimationBadgeProvider animationProvider = AnimationBadgeProvider(); + final BadgeMessageProvider badgeData = BadgeMessageProvider(); + final ImageUtils imageUtils = ImageUtils(); + final InlineImageProvider inlineImageProvider = GetIt.instance(); - bool isPrefixIconClicked = false; - int textfieldLength = 0; - String previousText = ''; final TextEditingController inlineimagecontroller = GetIt.instance.get().getController(); + + bool isPrefixIconClicked = false; bool isDialInteracting = false; - String errorVal = ""; + String previousText = ''; + String _cachedText = ''; @override void initState() { + WidgetsBinding.instance.addObserver(this); inlineimagecontroller.addListener(handleTextChange); _setPortraitOrientation(); - speedDialProvider = SpeedDialProvider(animationProvider); - // If initialSpeed is provided, set it immediately - if (widget.initialSpeed != null) { - speedDialProvider.setDialValue(widget.initialSpeed!); - } - WidgetsBinding.instance.addPostFrameCallback((_) async { + WidgetsBinding.instance.addPostFrameCallback((_) { inlineImageProvider.setContext(context); - - // Apply saved badge data if we're editing a saved badge - if (widget.savedBadgeFilename != null) { - await _loadBadgeDataFromDisk(widget.savedBadgeFilename!); - } }); _startImageCaching(); + speedDialProvider = SpeedDialProvider(animationProvider); + _tabController = TabController(length: 3, vsync: this); super.initState(); + } - _tabController = TabController(length: 4, vsync: this); + @override + void dispose() { + WidgetsBinding.instance.removeObserver(this); + inlineimagecontroller.removeListener(handleTextChange); + inlineimagecontroller.removeListener(_controllerListner); + animationProvider.stopAnimation(); + _tabController.dispose(); + super.dispose(); } - // Loads badge data from disk and populates controllers/providers for editing - Future _loadBadgeDataFromDisk(String badgeFilename) async { - try { - final (badgeText, badgeData, savedData) = - await BadgeLoaderHelper.loadBadgeDataAndText(badgeFilename); - // Set the text in the controller - inlineimagecontroller.text = badgeText; - // Set animation effects - animationProvider.removeEffect(effectMap[0]); // Invert - animationProvider.removeEffect(effectMap[1]); // Flash - animationProvider.removeEffect(effectMap[2]); // Marquee - final message = badgeData.messages[0]; - if (message.flash) { - animationProvider.addEffect(effectMap[1]); - } - if (message.marquee) { - animationProvider.addEffect(effectMap[2]); + @override + void didChangeAppLifecycleState(AppLifecycleState state) { + if (state == AppLifecycleState.paused) { + _cachedText = inlineimagecontroller.text; + animationProvider.stopAnimation(); + } else if (state == AppLifecycleState.resumed) { + if (inlineimagecontroller.text.trim().isEmpty && + _cachedText.trim().isNotEmpty) { + inlineimagecontroller.text = _cachedText; } - if (savedData != null && - savedData.containsKey('invert') && - savedData['invert'] == true) { - animationProvider.addEffect(effectMap[0]); + animationProvider.badgeAnimation( + inlineimagecontroller.text, + Converters(), + animationProvider.isEffectActive(InvertLEDEffect()), + ); + } + } + + void _controllerListner() { + animationProvider.badgeAnimation( + inlineImageProvider.getController().text, + Converters(), + animationProvider.isEffectActive(InvertLEDEffect()), + ); + } + + void handleTextChange() { + final currentText = inlineimagecontroller.text; + final selection = inlineimagecontroller.selection; + + if (previousText.length > currentText.length) { + final deletionIndex = selection.baseOffset; + final regex = RegExp(r'<<\d+>>'); + final matches = regex.allMatches(previousText); + + bool placeholderDeleted = false; + + for (final match in matches) { + if (deletionIndex > match.start && deletionIndex < match.end) { + inlineimagecontroller.text = + previousText.replaceRange(match.start, match.end, ''); + inlineimagecontroller.selection = + TextSelection.collapsed(offset: match.start); + placeholderDeleted = true; + break; + } } - // Set animation mode - int modeValue = BadgeLoaderHelper.parseAnimationMode(message.mode); - animationProvider.setAnimationMode(animationMap[modeValue]); - // Set speed - try { - int speedDialValue = Speed.getIntValue(message.speed); - speedDialProvider.setDialValue(speedDialValue); - } catch (e) { - speedDialProvider.setDialValue(1); + + if (!placeholderDeleted) { + previousText = inlineimagecontroller.text; } - ToastUtils().showToast( - "Editing badge: ${badgeFilename.substring(0, badgeFilename.length - 5)}"); - } catch (e) { - print("Failed to load badge data: $e"); - ToastUtils().showToast("Failed to load badge data"); + } else { + previousText = currentText; } } @@ -147,374 +148,195 @@ class _HomeScreenState extends State } } - @override - void dispose() { - inlineimagecontroller.removeListener(handleTextChange); - animationProvider.stopAnimation(); - WidgetsBinding.instance.removeObserver(this); - _tabController.dispose(); - super.dispose(); - } - @override Widget build(BuildContext context) { super.build(context); - InlineImageProvider inlineImageProvider = - Provider.of(context); return MultiProvider( providers: [ ChangeNotifierProvider( - create: (context) => animationProvider, + create: (_) => animationProvider, ), ChangeNotifierProvider( - create: (context) { - inlineImageProvider.getController().addListener(_controllerListner); + create: (_) { + inlineimagecontroller.addListener(_controllerListner); return speedDialProvider; }, ), ], child: DefaultTabController( - length: 4, - child: CommonScaffold( - index: 0, - title: 'Badge Magic', - body: SafeArea( - child: SingleChildScrollView( - physics: isDialInteracting - ? const NeverScrollableScrollPhysics() - : const AlwaysScrollableScrollPhysics(), - child: Column( - children: [ - AnimationBadge(), - Container( - margin: EdgeInsets.all(15.w), - child: Material( - color: drawerHeaderTitle, - borderRadius: BorderRadius.circular(10.r), - elevation: 4, - child: ExtendedTextField( - onChanged: (value) {}, - controller: inlineimagecontroller, - specialTextSpanBuilder: ImageBuilder(), - decoration: InputDecoration( - border: OutlineInputBorder( - borderRadius: BorderRadius.circular(10.r), - ), - prefixIcon: IconButton( - onPressed: () { - setState(() { - isPrefixIconClicked = !isPrefixIconClicked; - }); - }, - icon: const Icon(Icons.tag_faces_outlined), - ), - focusedBorder: OutlineInputBorder( - borderRadius: - BorderRadius.all(Radius.circular(10.r)), - borderSide: BorderSide(color: colorPrimary), - ), + length: 3, + child: CommonScaffold( + index: 0, + title: 'Badge Magic', + scaffoldKey: const Key(homeScreenTitleKey), + body: SafeArea( + child: SingleChildScrollView( + physics: isDialInteracting + ? const NeverScrollableScrollPhysics() + : const AlwaysScrollableScrollPhysics(), + child: Column( + children: [ + AnimationBadge(), + Container( + margin: EdgeInsets.all(15.w), + child: Material( + color: drawerHeaderTitle, + borderRadius: BorderRadius.circular(10.r), + elevation: 4, + child: ExtendedTextField( + controller: inlineimagecontroller, + specialTextSpanBuilder: ImageBuilder(), + decoration: InputDecoration( + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(10.r), + ), + prefixIcon: IconButton( + onPressed: () { + setState(() { + isPrefixIconClicked = !isPrefixIconClicked; + }); + }, + icon: const Icon(Icons.tag_faces_outlined), + ), + focusedBorder: OutlineInputBorder( + borderRadius: + BorderRadius.all(Radius.circular(10.r)), + borderSide: BorderSide(color: colorPrimary), ), ), ), ), - Visibility( - visible: isPrefixIconClicked, - child: Container( - height: 170.h, - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(10.r), - color: Colors.grey[200]), - margin: EdgeInsets.symmetric(horizontal: 15.w), - padding: EdgeInsets.symmetric( - vertical: 10.h, horizontal: 10.w), - child: VectorGridView())), - TabBar( - isScrollable: false, - indicatorSize: TabBarIndicatorSize.tab, - labelStyle: TextStyle(fontSize: 12), - unselectedLabelStyle: TextStyle(fontSize: 12), - labelColor: Colors.black, - unselectedLabelColor: mdGrey400, - indicatorColor: colorPrimary, - controller: _tabController, - splashFactory: InkRipple.splashFactory, - overlayColor: WidgetStateProperty.resolveWith( - (states) => states.contains(WidgetState.pressed) - ? dividerColor - : null, + ), + Visibility( + visible: isPrefixIconClicked, + child: Container( + height: 170.h, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(10.r), + color: Colors.grey[200], ), - tabs: const [ - Tab(text: 'Speed'), - Tab(text: 'Animation'), - Tab(text: 'Transition'), - Tab(text: 'Effects'), - ], + margin: EdgeInsets.symmetric(horizontal: 15.w), + padding: EdgeInsets.symmetric( + vertical: 10.h, horizontal: 10.w), + child: VectorGridView(), ), - SizedBox( - height: 250.h, - child: TabBarView( - physics: const NeverScrollableScrollPhysics(), - controller: _tabController, - children: [ - GestureDetector( - onPanDown: (_) => - setState(() => isDialInteracting = true), - onPanCancel: () => - setState(() => isDialInteracting = false), - onPanEnd: (_) => - setState(() => isDialInteracting = false), - child: RadialDial(), - ), - TransitionTab(), - AnimationTab(), - EffectTab(), - ], - ), + ), + TabBar( + indicatorSize: TabBarIndicatorSize.tab, + labelColor: Colors.black, + unselectedLabelColor: mdGrey400, + indicatorColor: colorPrimary, + controller: _tabController, + splashFactory: InkRipple.splashFactory, + overlayColor: WidgetStateProperty.resolveWith( + (states) => states.contains(WidgetState.pressed) + ? dividerColor + : null, ), - Row( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, + tabs: const [ + Tab(text: 'Speed'), + Tab(text: 'Animation'), + Tab(text: 'Effects'), + ], + ), + SizedBox( + height: 250.h, + child: TabBarView( + physics: const NeverScrollableScrollPhysics(), + controller: _tabController, children: [ - Container( - padding: EdgeInsets.symmetric(vertical: 20.h), - child: Consumer( - builder: (context, animationProvider, _) { - final isSpecial = animationProvider - .isSpecialAnimationSelected(); - if (isSpecial) { - // Only show Transfer button, centered - return Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Container( - padding: - EdgeInsets.symmetric(vertical: 20.h), - child: GestureDetector( - onTap: () async { - await animationProvider - .handleAnimationTransfer( - badgeData: badgeData, - inlineImageProvider: - inlineImageProvider, - speedDialProvider: - speedDialProvider, - flash: animationProvider - .isEffectActive(FlashEffect()), - marquee: animationProvider - .isEffectActive( - MarqueeEffect()), - invert: animationProvider - .isEffectActive( - InvertLEDEffect()), - ); - }, - child: Container( - padding: EdgeInsets.symmetric( - horizontal: 33.w, vertical: 8.h), - decoration: BoxDecoration( - borderRadius: - BorderRadius.circular(2.r), - color: mdGrey400, - ), - child: const Text('Transfer'), - ), - ), - ), - ], - ); - } else { - // Show both Save and Transfer as before - return Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Container( - padding: - EdgeInsets.symmetric(vertical: 20.h), - child: GestureDetector( - onTap: () async { - if (inlineimagecontroller.text - .trim() - .isEmpty) { - ToastUtils().showToast( - "Please enter a message"); - return; - } - // If we're editing an existing badge, update it instead of showing save dialog - if (widget.savedBadgeFilename != - null) { - SavedBadgeProvider - savedBadgeProvider = - SavedBadgeProvider(); - String baseFilename = - widget.savedBadgeFilename!; - if (baseFilename - .endsWith('.json')) { - baseFilename = - baseFilename.substring(0, - baseFilename.length - 5); - } - await savedBadgeProvider - .updateBadgeData( - baseFilename, // Pass the filename without .json extension - inlineimagecontroller.text, - animationProvider.isEffectActive( - FlashEffect()), - animationProvider.isEffectActive( - MarqueeEffect()), - animationProvider.isEffectActive( - InvertLEDEffect()), - speedDialProvider.getOuterValue(), - animationProvider - .getAnimationIndex() ?? - 1, - ); - ToastUtils().showToast( - "Badge Updated Successfully"); - Navigator.pushNamedAndRemoveUntil( - context, - '/savedBadge', - (route) => false); - } else { - // Show save dialog for new badges - showDialog( - context: context, - builder: (context) { - return SaveBadgeDialog( - speed: speedDialProvider, - animationProvider: - animationProvider, - textController: - inlineimagecontroller, - isInverse: animationProvider - .isEffectActive( - InvertLEDEffect()), - ); - }, - ); - } - }, - child: Container( - padding: EdgeInsets.symmetric( - horizontal: 33.w, vertical: 8.h), - decoration: BoxDecoration( - borderRadius: - BorderRadius.circular(2.r), - color: mdGrey400, - ), - child: const Text('Save'), - ), - ), - ), - SizedBox(width: 100.w), - Container( - padding: - EdgeInsets.symmetric(vertical: 20.h), - child: GestureDetector( - onTap: () async { - await animationProvider - .handleAnimationTransfer( - badgeData: badgeData, - inlineImageProvider: - inlineImageProvider, - speedDialProvider: - speedDialProvider, - flash: animationProvider - .isEffectActive(FlashEffect()), - marquee: animationProvider - .isEffectActive( - MarqueeEffect()), - invert: animationProvider - .isEffectActive( - InvertLEDEffect()), - ); - }, - child: Container( - padding: EdgeInsets.symmetric( - horizontal: 20.w, vertical: 8.h), - decoration: BoxDecoration( - borderRadius: - BorderRadius.circular(2.r), - color: mdGrey400, - ), - child: const Text('Transfer'), - ), - ), - ), - ], + GestureDetector( + onPanDown: (_) => + setState(() => isDialInteracting = true), + onPanCancel: () => + setState(() => isDialInteracting = false), + onPanEnd: (_) => + setState(() => isDialInteracting = false), + child: RadialDial(), + ), + AnimationTab(), + EffectTab(), + ], + ), + ), + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Container( + padding: EdgeInsets.symmetric(vertical: 20.h), + child: GestureDetector( + onTap: () { + if (inlineimagecontroller.text.trim().isEmpty) { + ToastUtils() + .showErrorToast("Please enter a message"); + return; + } + showDialog( + context: context, + builder: (context) { + return SaveBadgeDialog( + speed: speedDialProvider, + animationProvider: animationProvider, + textController: inlineimagecontroller, + isInverse: animationProvider + .isEffectActive(InvertLEDEffect()), ); - } - }, + }, + ); + }, + child: Container( + padding: EdgeInsets.symmetric( + horizontal: 33.w, vertical: 8.h), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(2.r), + color: mdGrey400, + ), + child: const Text('Save'), ), ), - ], - ) - ], - ), + ), + SizedBox(width: 100.w), + Container( + padding: EdgeInsets.symmetric(vertical: 20.h), + child: GestureDetector( + onTap: () { + badgeData.checkAndTransfer( + inlineimagecontroller.text, + animationProvider.isEffectActive(FlashEffect()), + animationProvider.isEffectActive(MarqueeEffect()), + animationProvider + .isEffectActive(InvertLEDEffect()), + speedDialProvider.getOuterValue(), + modeValueMap[ + animationProvider.getAnimationIndex()], + null, + false, + context, // <== This is needed and now passed + ); + }, + child: Container( + padding: EdgeInsets.symmetric( + horizontal: 20.w, vertical: 8.h), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(2.r), + color: mdGrey400, + ), + child: const Text('Transfer'), + ), + ), + ), + ], + ), + ], ), ), - scaffoldKey: const Key(homeScreenTitleKey), - )), + ), + ), + ), ); } - void handleTextChange() { - final currentText = inlineimagecontroller.text; - final selection = inlineimagecontroller.selection; - - // Always reset to text animation if a special animation is selected and user types - if (animationProvider.isSpecialAnimationSelected() && - currentText.isNotEmpty) { - animationProvider.resetToTextAnimation(); - animationProvider.badgeAnimation(currentText, Converters(), - animationProvider.isEffectActive(InvertLEDEffect())); - setState(() {}); // Ensure UI updates - } - - if (previousText.length > currentText.length) { - final deletionIndex = selection.baseOffset; - final regex = RegExp(r'<<\d+>>'); - final matches = regex.allMatches(previousText); - - bool placeholderDeleted = false; - for (final match in matches) { - if (deletionIndex > match.start && deletionIndex < match.end) { - inlineimagecontroller.text = - previousText.replaceRange(match.start, match.end, ''); - inlineimagecontroller.selection = - TextSelection.collapsed(offset: match.start); - placeholderDeleted = true; - break; - } - } - if (!placeholderDeleted) { - previousText = inlineimagecontroller.text; - } - } else { - previousText = currentText; - } - } - - void _controllerListner() { - animationProvider.badgeAnimation(inlineImageProvider.getController().text, - Converters(), animationProvider.isEffectActive(InvertLEDEffect())); - } - @override bool get wantKeepAlive => true; - - @override - void didChangeAppLifecycleState(AppLifecycleState state) { - super.didChangeAppLifecycleState(state); - if (state == AppLifecycleState.resumed) { - inlineimagecontroller.clear(); - previousText = ''; - animationProvider.stopAllAnimations.call(); // If method exists - animationProvider.initializeAnimation.call(); // If method exists - if (mounted) setState(() {}); - } else if (state == AppLifecycleState.paused || - state == AppLifecycleState.inactive) { - animationProvider.stopAnimation(); - } - } } diff --git a/lib/view/widgets/save_badge_card.dart b/lib/view/widgets/save_badge_card.dart index a4814be65..00e36c2b7 100644 --- a/lib/view/widgets/save_badge_card.dart +++ b/lib/view/widgets/save_badge_card.dart @@ -8,7 +8,7 @@ import 'package:badgemagic/providers/animation_badge_provider.dart'; import 'package:badgemagic/providers/badge_message_provider.dart'; import 'package:badgemagic/providers/badge_slot_provider..dart'; import 'package:badgemagic/providers/saved_badge_provider.dart'; -import 'package:badgemagic/view/homescreen.dart'; +import 'package:badgemagic/view/draw_badge_screen.dart'; import 'package:badgemagic/view/widgets/badge_delete_dialog.dart'; import 'package:flutter/material.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; @@ -35,40 +35,6 @@ class SaveBadgeCard extends StatelessWidget { this.onTap, }); - // Helper methods to safely access badge data properties - bool _safeGetFlashValue(Map data) { - try { - return file.jsonToData(data).messages[0].flash; - } catch (e) { - // If there's an error, default to false - return false; - } - } - - bool _safeGetMarqueeValue(Map data) { - try { - return file.jsonToData(data).messages[0].marquee; - } catch (e) { - // If there's an error, default to false - return false; - } - } - - bool _safeGetInvertValue(Map data) { - try { - if (data.containsKey('messages') && - data['messages'] is List && - data['messages'].isNotEmpty && - data['messages'][0] is Map) { - return data['messages'][0]['invert'] ?? false; - } - return false; - } catch (e) { - // If there's an error, default to false - return false; - } - } - @override Widget build(BuildContext context) { BadgeMessageProvider badge = BadgeMessageProvider(); @@ -198,219 +164,38 @@ class SaveBadgeCard extends StatelessWidget { ), ), ], - border: - isSelected ? Border.all(color: colorPrimary, width: 2) : null, ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, + SizedBox(height: 8.h), + Row( children: [ Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - crossAxisAlignment: CrossAxisAlignment.center, children: [ - // Wrapping the text with Flexible to ensure it doesn't overflow. - Flexible( - child: Padding( - padding: EdgeInsets.only( - right: 8 - .w), // Adding some padding to separate text and buttons - child: Text( - badgeData.key.substring(0, badgeData.key.length - 5), - style: const TextStyle( - fontWeight: FontWeight.bold, - fontSize: 16, - ), - softWrap: true, - overflow: TextOverflow - .ellipsis, // Use ellipsis to indicate overflowed text - maxLines: 1, // Limit to 1 line for a cleaner look + Visibility( + visible: file.jsonToData(badgeData.value).messages[0].flash, + child: Container( + padding: + EdgeInsets.symmetric(horizontal: 10.w, vertical: 4.h), + decoration: BoxDecoration( + color: colorPrimary, + borderRadius: BorderRadius.circular(100), + ), + child: Row( + children: [ + Image.asset( + "assets/icons/flash.png", + color: Colors.white, + height: 14.h, + ) + ], ), ), ), - Consumer( - builder: (context, provider, widget) => Row( - mainAxisSize: MainAxisSize.min, // Keep the row compact - children: [ - IconButton( - icon: Image.asset( - "assets/icons/t_play.png", - height: 20, - color: Colors.black, - ), - onPressed: () { - provider.savedBadgeAnimation( - badgeData.value, - Provider.of(context, - listen: false)); - }, - ), - IconButton( - icon: const Icon( - Icons.edit, - color: Colors.black, - ), - onPressed: () async { - final shouldEdit = await showDialog( - context: context, - builder: (context) => AlertDialog( - title: const Text('Edit Badge'), - content: const Text( - 'Do you want to edit this badge?'), - actions: [ - TextButton( - onPressed: () => - Navigator.pop(context, false), - child: const Text('No'), - ), - TextButton( - onPressed: () => - Navigator.pop(context, true), - child: const Text('Yes'), - ), - ], - ), - ); - if (shouldEdit == true) { - // Extract the speed value from the saved badge - final speed = Speed.getIntValue(file - .jsonToData(badgeData.value) - .messages[0] - .speed); - String badgeFilename = badgeData.key; - Navigator.of(context).pushAndRemoveUntil( - MaterialPageRoute( - builder: (context) => HomeScreen( - savedBadgeFilename: badgeFilename, - initialSpeed: speed, // Pass the speed value - ), - ), - (route) => false, // Remove all previous routes - ); - } - }, - ), - IconButton( - icon: Image.asset( - "assets/icons/t_updown.png", - height: 24.h, - color: Colors.black, - ), - onPressed: () { - logger.d("BadgeData: ${badgeData.value}"); - //We can Acrtually call a method to generate the data just by transffering the JSON data - //so we would not necessarily need the Providers. - badge.checkAndTransfer(null, null, null, null, null, - null, badgeData.value, true); - }, - ), - IconButton( - icon: const Icon( - Icons.share, - color: Colors.black, - ), - onPressed: () { - file.shareBadgeData(badgeData.key); - }, - ), - IconButton( - icon: const Icon( - Icons.delete, - color: Colors.black, - ), - onPressed: () async { - //add a dialog for confirmation before deleting - await _showDeleteDialog(context) - .then((value) async { - if (value == true) { - file.deleteFile(badgeData.key); - toastUtils - .showToast("Badge Deleted Successfully"); - await refreshBadgesCallback(badgeData); - } - }); - }, - ), - ], - ), + SizedBox( + width: 8.w, ), - ], - ), - SizedBox(height: 8.h), - Row( - children: [ - Row( - children: [ - Visibility( - visible: _safeGetFlashValue(badgeData.value), - child: Container( - padding: EdgeInsets.symmetric( - horizontal: 10.w, vertical: 4.h), - decoration: BoxDecoration( - color: colorPrimary, - borderRadius: BorderRadius.circular(100), - ), - child: Row( - children: [ - Image.asset( - "assets/icons/flash.png", - color: Colors.white, - height: 14.h, - ) - ], - ), - ), - ), - SizedBox( - width: 8.w, - ), - Visibility( - visible: _safeGetMarqueeValue(badgeData.value), - child: Container( - padding: EdgeInsets.symmetric( - horizontal: 12.w, vertical: 4.h), - decoration: BoxDecoration( - color: colorPrimary, - borderRadius: BorderRadius.circular(100), - ), - child: Row( - children: [ - Image.asset( - "assets/icons/square.png", - color: Colors.white, - height: 14.h, - ) - ], - ), - ), - ), - SizedBox( - width: 8.w, - ), - Visibility( - visible: _safeGetInvertValue(badgeData.value), - child: Container( - padding: EdgeInsets.symmetric( - horizontal: 12.w, vertical: 4.h), - decoration: BoxDecoration( - color: colorPrimary, - borderRadius: BorderRadius.circular(100), - ), - child: Row( - children: [ - Image.asset( - "assets/icons/t_invert.png", - color: Colors.white, - height: 14.h, - ) - ], - ), - ), - ) - ], - ), - SizedBox(width: 8.w), - GestureDetector( - onTap: () {}, + Visibility( + visible: + file.jsonToData(badgeData.value).messages[0].marquee, child: Container( padding: EdgeInsets.symmetric(horizontal: 12.w, vertical: 4.h), @@ -421,26 +206,19 @@ class SaveBadgeCard extends StatelessWidget { child: Row( children: [ Image.asset( - "assets/icons/t_double.png", + "assets/icons/square.png", color: Colors.white, height: 14.h, - ), - const SizedBox(width: 4), - Text( - Speed.getIntValue(file - .jsonToData(badgeData.value) - .messages[0] - .speed) - .toString(), - style: const TextStyle(color: Colors.white), - ), + ) ], ), ), ), - SizedBox(width: 8.w), - GestureDetector( - onTap: () {}, + SizedBox( + width: 8.w, + ), + Visibility( + visible: badgeData.value['messages'][0]['invert'] ?? false, child: Container( padding: EdgeInsets.symmetric(horizontal: 12.w, vertical: 4.h), @@ -448,40 +226,94 @@ class SaveBadgeCard extends StatelessWidget { color: colorPrimary, borderRadius: BorderRadius.circular(100), ), - child: Text( - file - .jsonToData(badgeData.value) - .messages[0] - .mode - .toString() - .split('.') - .last - .toUpperCase(), - style: const TextStyle(color: Colors.white), + child: Row( + children: [ + Image.asset( + "assets/icons/t_invert.png", + color: Colors.white, + height: 14.h, + ) + ], ), ), + ) + ], + ), + SizedBox(width: 8.w), + GestureDetector( + onTap: () {}, + child: Container( + padding: + EdgeInsets.symmetric(horizontal: 12.w, vertical: 4.h), + decoration: BoxDecoration( + color: colorPrimary, + borderRadius: BorderRadius.circular(100), ), - const Spacer(), - Consumer( - builder: (context, selectionProvider, _) { - final isSelected = - selectionProvider.isSelected(badgeData.key); - return Switch( - value: isSelected, - onChanged: (selectionProvider.canSelectMore || - isSelected) - ? (value) => - selectionProvider.toggleSelection(badgeData.key) - : null, - activeColor: colorPrimary, - ); - }, + child: Row( + children: [ + Image.asset( + "assets/icons/t_double.png", + color: Colors.white, + height: 14.h, + ), + const SizedBox(width: 4), + Text( + ( + Speed.getIntValue(file + .jsonToData(badgeData.value) + .messages[0] + .speed) + .toString(), + style: const TextStyle(color: Colors.white), + ) as String, + ) + ], ), - ], + ), + ), + SizedBox(width: 8.w), + GestureDetector( + onTap: () {}, + child: Container( + padding: + EdgeInsets.symmetric(horizontal: 12.w, vertical: 4.h), + decoration: BoxDecoration( + color: colorPrimary, + borderRadius: BorderRadius.circular(100), + ), + child: Text( + file + .jsonToData(badgeData.value) + .messages[0] + .mode + .toString() + .split('.') + .last + .toUpperCase(), + style: const TextStyle(color: Colors.white), + ), + ), + ), + const Spacer(), + Consumer( + builder: (context, selectionProvider, _) { + final isSelected = + selectionProvider.isSelected(badgeData.key); + return Switch( + value: isSelected, + onChanged: (selectionProvider.canSelectMore || isSelected) + ? (value) => + selectionProvider.toggleSelection(badgeData.key) + : null, + activeColor: colorPrimary, + ); + }, ), ], ), - )); + ], + ), + ); } Future _showDeleteDialog(BuildContext context) async { From 7de40adda03dc44ca6e05336a2d514062c8b1c94 Mon Sep 17 00:00:00 2001 From: Samruddhi Rahegaonkar Date: Wed, 20 Aug 2025 21:52:45 +0530 Subject: [PATCH 4/9] fix: resolved conflicts --- lib/providers/badge_message_provider.dart | 49 +++++++++++++++-------- 1 file changed, 33 insertions(+), 16 deletions(-) diff --git a/lib/providers/badge_message_provider.dart b/lib/providers/badge_message_provider.dart index e9afc6f49..03fc447b9 100644 --- a/lib/providers/badge_message_provider.dart +++ b/lib/providers/badge_message_provider.dart @@ -1,6 +1,5 @@ import 'dart:io'; import 'dart:math'; -import 'dart:ui'; import 'package:badgemagic/bademagic_module/bluetooth/base_ble_state.dart'; import 'package:badgemagic/bademagic_module/bluetooth/datagenerator.dart'; import 'package:badgemagic/bademagic_module/utils/converters.dart'; @@ -12,7 +11,9 @@ import 'package:badgemagic/bademagic_module/models/messages.dart'; import 'package:badgemagic/bademagic_module/models/mode.dart'; import 'package:badgemagic/bademagic_module/models/speed.dart'; import 'package:badgemagic/badge_animation/ani_fish.dart'; +import 'package:badgemagic/providers/BadgeScanProvider.dart'; import 'package:badgemagic/providers/imageprovider.dart'; +import 'package:flutter/material.dart'; import 'package:flutter_blue_plus/flutter_blue_plus.dart'; import 'package:get_it/get_it.dart'; import 'package:logger/logger.dart'; @@ -23,6 +24,7 @@ import 'package:badgemagic/badge_animation/ani_diagonal.dart'; import 'package:badgemagic/badge_animation/ani_emergency.dart'; import 'package:badgemagic/badge_animation/ani_beating_hearts.dart'; import 'package:badgemagic/badge_animation/ani_fireworks.dart'; +import 'package:provider/provider.dart'; Map modeValueMap = { 0: Mode.left, @@ -91,14 +93,28 @@ class BadgeMessageProvider { } } - Future transferData(DataTransferManager manager) async { + Future transferData( + DataTransferManager manager, + BuildContext? context, + ) async { + final scanProvider = context != null + ? Provider.of(context, listen: false) + : null; + + final BleState? initialState = ScanState( + manager: manager, + mode: scanProvider!.mode, + allowedNames: scanProvider.badgeNames, + ); + + BleState? state = initialState; DateTime now = DateTime.now(); - BleState? state = ScanState(manager: manager); + while (state != null) { state = await state.process(); } - logger.d("Time to transfer data is = ${DateTime.now().difference(now)}"); + logger.d("Time to transfer data: ${DateTime.now().difference(now)}"); logger.d(".......Data transfer completed......."); } @@ -111,6 +127,7 @@ class BadgeMessageProvider { Mode? mode, Map? jsonData, bool isSavedBadge, + BuildContext context, {TextStyle? textStyle}) async { if (await FlutterBluePlus.isSupported == false) { ToastUtils().showErrorToast('Bluetooth is not supported by the device'); @@ -210,7 +227,7 @@ class BadgeMessageProvider { } DataTransferManager manager = DataTransferManager(data); - await transferData(manager); + await transferData(manager, context); } } @@ -257,7 +274,7 @@ Future transferFireworksAnimation( Data data = Data(messages: frames); DataTransferManager manager = DataTransferManager(data); - await badgeDataProvider.transferData(manager); + await badgeDataProvider.transferData(manager, null); logger.i('💡 Fireworks animation transfer completed successfully!'); } @@ -305,7 +322,7 @@ Future transferBeatingHeartsAnimation( Data data = Data(messages: heartFrames); DataTransferManager manager = DataTransferManager(data); - await badgeDataProvider.transferData(manager); + await badgeDataProvider.transferData(manager, null); logger.i('💡 Beating Hearts animation transfer completed successfully!'); } @@ -365,7 +382,7 @@ Future transferEmergencyAnimation( Data data = Data(messages: rotatedFrames); DataTransferManager manager = DataTransferManager(data); - await badgeDataProvider.transferData(manager); + await badgeDataProvider.transferData(manager, null); logger.i('💡 Emergency animation transfer completed successfully!'); } @@ -423,7 +440,7 @@ Future transferDiagonalAnimation( logger.i('V Diagonal Data object created. Starting transfer...'); try { - await badgeDataProvider.transferData(DataTransferManager(data)); + await badgeDataProvider.transferData(DataTransferManager(data), null); logger.i('V Diagonal animation transfer completed successfully!'); } catch (e, st) { logger.e('⛔ V Diagonal animation transfer failed: $e\n$st'); @@ -486,7 +503,7 @@ Future transferFishAnimation( logger.i('🐟 Fish Data object created. Starting transfer...'); try { - await badgeDataProvider.transferData(DataTransferManager(data)); + await badgeDataProvider.transferData(DataTransferManager(data), null); logger.i('🐟 Fish animation transfer completed successfully!'); } catch (e, st) { logger.e('⛔ Fish animation transfer failed: $e\n$st'); @@ -667,7 +684,7 @@ Future transferPacmanAnimation( Data data = Data(messages: pacmanFrames); logger.i('💡 Data object created. Starting transfer...'); try { - await badgeDataProvider.transferData(DataTransferManager(data)); + await badgeDataProvider.transferData(DataTransferManager(data), null); } catch (e, st) { logger.e('⛔ Pacman animation transfer failed: $e\n$st'); } @@ -741,7 +758,7 @@ Future transferChevronAnimation( Data data = Data(messages: chevronFrames); logger.i('💡 Data object created. Starting transfer...'); try { - await badgeDataProvider.transferData(DataTransferManager(data)); + await badgeDataProvider.transferData(DataTransferManager(data), null); } catch (e, st) { logger.e('⛔ Chevron animation transfer failed: $e\n$st'); } @@ -802,7 +819,7 @@ Future transferDiamondAnimation( Data data = Data(messages: diamondFrames); logger.i('💡 Data object created. Starting transfer...'); try { - await badgeDataProvider.transferData(DataTransferManager(data)); + await badgeDataProvider.transferData(DataTransferManager(data), null); } catch (e, st) { logger.e('⛔ Diamond animation transfer failed: $e\n$st'); } @@ -925,7 +942,7 @@ Future transferBrokenHeartsAnimation( Data data = Data(messages: heartFrames); logger.i('💡 Data object created. Starting transfer...'); try { - await badgeDataProvider.transferData(DataTransferManager(data)); + await badgeDataProvider.transferData(DataTransferManager(data), null); } catch (e, st) { logger.e('⛔ Broken Hearts animation transfer failed: $e\n$st'); } @@ -1006,7 +1023,7 @@ Future transferFeetAnimation( Data data = Data(messages: feetFrames); logger.i('🦶 Feet Data object created. Starting transfer...'); try { - await badgeDataProvider.transferData(DataTransferManager(data)); + await badgeDataProvider.transferData(DataTransferManager(data), null); } catch (e, st) { logger.e('⛔ Feet animation transfer failed: $e\n$st'); } @@ -1050,7 +1067,7 @@ Future transferCupidAnimation( Data data = Data(messages: cupidFrames); logger.i('💘 Cupid Data object created. Starting transfer...'); try { - await badgeDataProvider.transferData(DataTransferManager(data)); + await badgeDataProvider.transferData(DataTransferManager(data), null); } catch (e, st) { logger.e('⛔ Cupid animation transfer failed: $e\n$st'); } From 51ba22cf9cd4a4809cc1c805cd14fde88f51af7f Mon Sep 17 00:00:00 2001 From: Samruddhi Rahegaonkar Date: Tue, 26 Aug 2025 09:48:30 +0530 Subject: [PATCH 5/9] fix: made the feature persisted --- lib/main.dart | 4 +- lib/providers/BadgeScanProvider.dart | 46 +++++- lib/providers/getitlocator.dart | 2 + lib/view/badgeScanSettingsWidget.dart | 163 +++++++++++--------- lib/view/settings_screen.dart | 209 ++++++++++++++------------ pubspec.yaml | 1 + 6 files changed, 251 insertions(+), 174 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index 63e1f8370..b136dbee5 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -24,7 +24,9 @@ void main() { providers: [ ChangeNotifierProvider( create: (context) => getIt()), - ChangeNotifierProvider(create: (_) => BadgeScanProvider()), + ChangeNotifierProvider( + create: (_) => getIt(), + ), ], child: const MyApp(), )); diff --git a/lib/providers/BadgeScanProvider.dart b/lib/providers/BadgeScanProvider.dart index e01690f5e..120cb4065 100644 --- a/lib/providers/BadgeScanProvider.dart +++ b/lib/providers/BadgeScanProvider.dart @@ -1,36 +1,78 @@ import 'package:flutter/material.dart'; +import 'package:shared_preferences/shared_preferences.dart'; enum BadgeScanMode { any, specific } class BadgeScanProvider with ChangeNotifier { BadgeScanMode _mode = BadgeScanMode.any; List _badgeNames = ['LSLED', 'VBLAB']; + bool _isLoaded = false; BadgeScanMode get mode => _mode; List get badgeNames => List.unmodifiable(_badgeNames); + bool get isLoaded => _isLoaded; + BadgeScanProvider() { + _loadFromPrefs(); // Load persisted values in background + } + + // --- Persistence helpers --- + Future _loadFromPrefs() async { + final prefs = await SharedPreferences.getInstance(); + + // Load scan mode + final modeIndex = prefs.getInt('badge_scan_mode'); + if (modeIndex != null) { + _mode = BadgeScanMode.values[modeIndex]; + } + + // Load badge names + final storedNames = prefs.getStringList('badge_names'); + if (storedNames != null && storedNames.isNotEmpty) { + _badgeNames = storedNames; + } + + _isLoaded = true; + notifyListeners(); // Notify UI that values are loaded + } + + Future _saveToPrefs() async { + final prefs = await SharedPreferences.getInstance(); + await prefs.setInt('badge_scan_mode', _mode.index); + await prefs.setStringList('badge_names', _badgeNames); + } + + // --- Public methods to update values --- void setMode(BadgeScanMode mode) { _mode = mode; + _saveToPrefs(); notifyListeners(); } void setBadgeNames(List names) { _badgeNames = names.where((name) => name.trim().isNotEmpty).toList(); + _saveToPrefs(); notifyListeners(); } void addBadgeName(String name) { - _badgeNames.add(name); + if (name.trim().isEmpty) return; + _badgeNames.add(name.trim()); + _saveToPrefs(); notifyListeners(); } void removeBadgeNameAt(int index) { + if (index < 0 || index >= _badgeNames.length) return; _badgeNames.removeAt(index); + _saveToPrefs(); notifyListeners(); } void updateBadgeName(int index, String newName) { - _badgeNames[index] = newName; + if (index < 0 || index >= _badgeNames.length) return; + _badgeNames[index] = newName.trim(); + _saveToPrefs(); notifyListeners(); } } diff --git a/lib/providers/getitlocator.dart b/lib/providers/getitlocator.dart index 775c3a7f3..dc48c6bc6 100644 --- a/lib/providers/getitlocator.dart +++ b/lib/providers/getitlocator.dart @@ -1,3 +1,4 @@ +import 'package:badgemagic/providers/BadgeScanProvider.dart'; import 'package:badgemagic/providers/imageprovider.dart'; import 'package:get_it/get_it.dart'; @@ -5,4 +6,5 @@ final GetIt getIt = GetIt.instance; void setupLocator() { getIt.registerLazySingleton(() => InlineImageProvider()); + getIt.registerLazySingleton(() => BadgeScanProvider()); } diff --git a/lib/view/badgeScanSettingsWidget.dart b/lib/view/badgeScanSettingsWidget.dart index bcd054226..58d00a69f 100644 --- a/lib/view/badgeScanSettingsWidget.dart +++ b/lib/view/badgeScanSettingsWidget.dart @@ -3,9 +3,9 @@ import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; class BadgeScanSettingsWidget extends StatefulWidget { - final Function(BadgeScanMode mode, List names) onSave; + final Function(BadgeScanMode mode, List names)? onSave; - const BadgeScanSettingsWidget({super.key, required this.onSave}); + const BadgeScanSettingsWidget({super.key, this.onSave}); @override State createState() => @@ -21,9 +21,6 @@ class _BadgeScanSettingsWidgetState extends State { super.initState(); final provider = Provider.of(context, listen: false); _mode = provider.mode; - for (var name in provider.badgeNames) { - _controllers.add(TextEditingController(text: name)); - } } void _addBadgeName() { @@ -38,7 +35,7 @@ class _BadgeScanSettingsWidgetState extends State { }); } - void _onSave() { + Future _onSave() async { final updatedNames = _controllers .map((c) => c.text.trim()) .where((name) => name.isNotEmpty) @@ -52,82 +49,98 @@ class _BadgeScanSettingsWidgetState extends State { const SnackBar(content: Text('Scan settings saved successfully')), ); - widget.onSave(_mode, updatedNames); - Navigator.pop(context); - } - - @override - void dispose() { - for (var c in _controllers) { - c.dispose(); - } - super.dispose(); + widget.onSave?.call(_mode, updatedNames); + if (mounted) Navigator.pop(context); } @override Widget build(BuildContext context) { - return Scaffold( - appBar: AppBar( - title: const Text('Badge Scan Settings'), - actions: [ - IconButton( - icon: const Icon(Icons.save), - onPressed: _onSave, - ), - ], - ), - body: Column( - children: [ - RadioListTile( - title: const Text('Connect to any badge'), - value: BadgeScanMode.any, - groupValue: _mode, - onChanged: (val) => setState(() => _mode = val!), - ), - RadioListTile( - title: const Text('Connect to badges with the following names'), - value: BadgeScanMode.specific, - groupValue: _mode, - onChanged: (val) => setState(() => _mode = val!), + return Consumer( + builder: (context, provider, child) { + if (!provider.isLoaded) { + return const Scaffold( + body: Center(child: CircularProgressIndicator()), + ); + } + + if (_controllers.isEmpty) { + // Initialize controllers only after provider is loaded + for (var name in provider.badgeNames) { + _controllers.add(TextEditingController(text: name)); + } + } + + return Scaffold( + appBar: AppBar( + title: const Text('Badge Scan Settings'), + actions: [ + IconButton( + icon: const Icon(Icons.save), + onPressed: _onSave, + ), + ], ), - if (_mode == BadgeScanMode.specific) - Expanded( - child: ListView.builder( - itemCount: _controllers.length, - itemBuilder: (context, index) { - return Row( - children: [ - Expanded( - child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 12.0), - child: TextField( - controller: _controllers[index], - decoration: const InputDecoration( - labelText: 'Badge Name', - ), - ), - ), - ), - IconButton( - icon: const Icon(Icons.remove_circle_outline), - onPressed: () => _removeBadgeName(index), - ), - ], - ); - }, + body: Column( + children: [ + RadioListTile( + title: const Text('Connect to any badge'), + value: BadgeScanMode.any, + groupValue: _mode, + onChanged: (val) => setState(() => _mode = val!), ), - ), - if (_mode == BadgeScanMode.specific) - Padding( - padding: const EdgeInsets.all(12.0), - child: ElevatedButton.icon( - onPressed: _addBadgeName, - icon: const Icon(Icons.add), - label: const Text("Add more"), + RadioListTile( + title: const Text('Connect to badges with the following names'), + value: BadgeScanMode.specific, + groupValue: _mode, + onChanged: (val) => setState(() => _mode = val!), ), - ), - ], - ), + if (_mode == BadgeScanMode.specific) + Expanded( + child: ListView.builder( + itemCount: _controllers.length, + itemBuilder: (context, index) { + return Row( + children: [ + Expanded( + child: Padding( + padding: + const EdgeInsets.symmetric(horizontal: 12.0), + child: TextField( + controller: _controllers[index], + decoration: const InputDecoration( + labelText: 'Badge Name', + ), + ), + ), + ), + IconButton( + icon: const Icon(Icons.remove_circle_outline), + onPressed: () => _removeBadgeName(index), + ), + ], + ); + }, + ), + ), + if (_mode == BadgeScanMode.specific) + Padding( + padding: const EdgeInsets.all(12.0), + child: ElevatedButton.icon( + onPressed: _addBadgeName, + icon: const Icon(Icons.add), + label: const Text("Add more"), + ), + ), + ], + ), + ); + }, ); } + + @override + void dispose() { + for (var c in _controllers) c.dispose(); + super.dispose(); + } } diff --git a/lib/view/settings_screen.dart b/lib/view/settings_screen.dart index 8791ac9f7..2a5461762 100644 --- a/lib/view/settings_screen.dart +++ b/lib/view/settings_screen.dart @@ -1,4 +1,3 @@ -import 'package:badgemagic/constants.dart'; import 'package:badgemagic/providers/BadgeScanProvider.dart'; import 'package:badgemagic/view/widgets/common_scaffold_widget.dart'; import 'package:flutter/material.dart'; @@ -18,17 +17,12 @@ class SettingsScreenState extends State { late BadgeScanMode _scanMode; late List _controllers; + bool _initialized = false; @override void initState() { super.initState(); _setOrientation(); - - final scanProvider = Provider.of(context, listen: false); - _scanMode = scanProvider.mode; - _controllers = scanProvider.badgeNames - .map((name) => TextEditingController(text: name)) - .toList(); } void _setOrientation() { @@ -40,102 +34,125 @@ class SettingsScreenState extends State { @override void dispose() { - for (final controller in _controllers) { - controller.dispose(); + if (_initialized) { + for (final controller in _controllers) { + controller.dispose(); + } } super.dispose(); } @override Widget build(BuildContext context) { - return CommonScaffold( - index: 4, - title: 'Badge Magic', - body: Padding( - padding: const EdgeInsets.all(16.0), - child: ListView( - children: [ - const Text('Language', - style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold)), - const SizedBox(height: 8), - _buildDropdown( - selectedValue: selectedLanguage, - values: languages, - onChanged: (value) => setState(() => selectedLanguage = value), - ), - const SizedBox(height: 24), - const Text('Badge Scan Mode', - style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold)), - const SizedBox(height: 8), - RadioListTile( - title: const Text('Connect to any badge'), - value: BadgeScanMode.any, - groupValue: _scanMode, - onChanged: (value) => setState(() => _scanMode = value!), - ), - RadioListTile( - title: const Text('Connect to badges with the following names'), - value: BadgeScanMode.specific, - groupValue: _scanMode, - onChanged: (value) => setState(() => _scanMode = value!), - ), - if (_scanMode == BadgeScanMode.specific) - ..._controllers.asMap().entries.map((entry) { - final index = entry.key; - final controller = entry.value; - return Row( - children: [ - Expanded( - child: Padding( - padding: const EdgeInsets.symmetric(vertical: 4), - child: TextField( - controller: controller, - decoration: const InputDecoration( - hintText: 'Badge name', - border: OutlineInputBorder(), + return Consumer( + builder: (context, provider, child) { + if (!provider.isLoaded) { + return const Scaffold( + body: Center(child: CircularProgressIndicator()), + ); + } + + // Initialize controllers once after provider is loaded + if (!_initialized) { + _scanMode = provider.mode; + _controllers = provider.badgeNames + .map((name) => TextEditingController(text: name)) + .toList(); + _initialized = true; + } + + return CommonScaffold( + index: 4, + title: 'Badge Magic', + body: Padding( + padding: const EdgeInsets.all(16.0), + child: ListView( + children: [ + const Text('Language', + style: + TextStyle(fontSize: 16, fontWeight: FontWeight.bold)), + const SizedBox(height: 8), + _buildDropdown( + selectedValue: selectedLanguage, + values: languages, + onChanged: (value) => + setState(() => selectedLanguage = value), + ), + const SizedBox(height: 24), + const Text('Badge Scan Mode', + style: + TextStyle(fontSize: 16, fontWeight: FontWeight.bold)), + const SizedBox(height: 8), + RadioListTile( + title: const Text('Connect to any badge'), + value: BadgeScanMode.any, + groupValue: _scanMode, + onChanged: (value) => setState(() => _scanMode = value!), + ), + RadioListTile( + title: + const Text('Connect to badges with the following names'), + value: BadgeScanMode.specific, + groupValue: _scanMode, + onChanged: (value) => setState(() => _scanMode = value!), + ), + if (_scanMode == BadgeScanMode.specific) + ..._controllers.asMap().entries.map((entry) { + final index = entry.key; + final controller = entry.value; + return Row( + children: [ + Expanded( + child: Padding( + padding: const EdgeInsets.symmetric(vertical: 4), + child: TextField( + controller: controller, + decoration: const InputDecoration( + hintText: 'Badge name', + border: OutlineInputBorder(), + ), + ), ), ), - ), - ), - IconButton( - icon: const Icon(Icons.remove_circle_outline), - onPressed: () { - setState(() { - controller.dispose(); - _controllers.removeAt(index); - }); - }, - ), - ], - ); - }).toList(), - if (_scanMode == BadgeScanMode.specific) - TextButton.icon( - onPressed: () => setState(() { - _controllers.add(TextEditingController()); - }), - icon: const Icon(Icons.add), - label: const Text('Add More'), - ), - const SizedBox(height: 24), - ElevatedButton.icon( - onPressed: () { - final provider = - Provider.of(context, listen: false); - provider.setMode(_scanMode); - provider.setBadgeNames( - _controllers.map((c) => c.text.trim()).toList(), - ); - ScaffoldMessenger.of(context).showSnackBar( - const SnackBar(content: Text('Scan settings saved')), - ); - }, - icon: const Icon(Icons.save), - label: const Text("Save Settings"), - ) - ], - ), - ), + IconButton( + icon: const Icon(Icons.remove_circle_outline), + onPressed: () { + setState(() { + controller.dispose(); + _controllers.removeAt(index); + }); + }, + ), + ], + ); + }).toList(), + if (_scanMode == BadgeScanMode.specific) + TextButton.icon( + onPressed: () => setState(() { + _controllers.add(TextEditingController()); + }), + icon: const Icon(Icons.add), + label: const Text('Add More'), + ), + const SizedBox(height: 24), + ElevatedButton.icon( + onPressed: () { + provider.setMode(_scanMode); + provider.setBadgeNames( + _controllers.map((c) => c.text.trim()).toList(), + ); + ScaffoldMessenger.of(context).showSnackBar( + const SnackBar(content: Text('Scan settings saved')), + ); + }, + icon: const Icon(Icons.save), + label: const Text("Save Settings"), + ) + ], + ), + ), + ); + }, ); } @@ -154,7 +171,7 @@ class SettingsScreenState extends State { child: DropdownButton( value: selectedValue, isExpanded: true, - icon: Icon(Icons.arrow_drop_down, color: mdGrey400), + icon: const Icon(Icons.arrow_drop_down, color: Colors.grey), onChanged: (String? newValue) { if (newValue != null) onChanged(newValue); }, diff --git a/pubspec.yaml b/pubspec.yaml index 6154ebf87..ca7ad7bb4 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -31,6 +31,7 @@ environment: dependencies: flutter: sdk: flutter + shared_preferences: 2.5.3 # The following adds the Cupertino Icons font to your application. From 5e3bc35b2d10b9d6f357821c8e209e3b44f8402d Mon Sep 17 00:00:00 2001 From: Samruddhi Rahegaonkar Date: Tue, 26 Aug 2025 09:50:30 +0530 Subject: [PATCH 6/9] Resolve merge conflict by regenerating pubspec.lock --- pubspec.lock | 897 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 897 insertions(+) create mode 100644 pubspec.lock diff --git a/pubspec.lock b/pubspec.lock new file mode 100644 index 000000000..b64561b83 --- /dev/null +++ b/pubspec.lock @@ -0,0 +1,897 @@ +# Generated by pub +# See https://dart.dev/tools/pub/glossary#lockfile +packages: + _fe_analyzer_shared: + dependency: transitive + description: + name: _fe_analyzer_shared + sha256: f0bb5d1648339c8308cc0b9838d8456b3cfe5c91f9dc1a735b4d003269e5da9a + url: "https://pub.dev" + source: hosted + version: "88.0.0" + analyzer: + dependency: transitive + description: + name: analyzer + sha256: "0b7b9c329d2879f8f05d6c05b32ee9ec025f39b077864bdb5ac9a7b63418a98f" + url: "https://pub.dev" + source: hosted + version: "8.1.1" + archive: + dependency: transitive + description: + name: archive + sha256: "2fde1607386ab523f7a36bb3e7edb43bd58e6edaf2ffb29d8a6d578b297fdbbd" + url: "https://pub.dev" + source: hosted + version: "4.0.7" + args: + dependency: transitive + description: + name: args + sha256: d0481093c50b1da8910eb0bb301626d4d8eb7284aa739614d2b394ee09e3ea04 + url: "https://pub.dev" + source: hosted + version: "2.7.0" + async: + dependency: transitive + description: + name: async + sha256: "758e6d74e971c3e5aceb4110bfd6698efc7f501675bcfe0c775459a8140750eb" + url: "https://pub.dev" + source: hosted + version: "2.13.0" + bluez: + dependency: transitive + description: + name: bluez + sha256: "61a7204381925896a374301498f2f5399e59827c6498ae1e924aaa598751b545" + url: "https://pub.dev" + source: hosted + version: "0.8.3" + boolean_selector: + dependency: transitive + description: + name: boolean_selector + sha256: "8aab1771e1243a5063b8b0ff68042d67334e3feab9e95b9490f9a6ebf73b42ea" + url: "https://pub.dev" + source: hosted + version: "2.1.2" + characters: + dependency: transitive + description: + name: characters + sha256: f71061c654a3380576a52b451dd5532377954cf9dbd272a78fc8479606670803 + url: "https://pub.dev" + source: hosted + version: "1.4.0" + clock: + dependency: transitive + description: + name: clock + sha256: fddb70d9b5277016c77a80201021d40a2247104d9f4aa7bab7157b7e3f05b84b + url: "https://pub.dev" + source: hosted + version: "1.1.2" + collection: + dependency: transitive + description: + name: collection + sha256: "2f5709ae4d3d59dd8f7cd309b4e023046b57d8a6c82130785d2b0e5868084e76" + url: "https://pub.dev" + source: hosted + version: "1.19.1" + convert: + dependency: transitive + description: + name: convert + sha256: b30acd5944035672bc15c6b7a8b47d773e41e2f17de064350988c5d02adb1c68 + url: "https://pub.dev" + source: hosted + version: "3.1.2" + cross_file: + dependency: transitive + description: + name: cross_file + sha256: "7caf6a750a0c04effbb52a676dce9a4a592e10ad35c34d6d2d0e4811160d5670" + url: "https://pub.dev" + source: hosted + version: "0.3.4+2" + crypto: + dependency: transitive + description: + name: crypto + sha256: "1e445881f28f22d6140f181e07737b22f1e099a5e1ff94b0af2f9e4a463f4855" + url: "https://pub.dev" + source: hosted + version: "3.0.6" + cupertino_icons: + dependency: "direct main" + description: + name: cupertino_icons + sha256: ba631d1c7f7bef6b729a622b7b752645a2d076dba9976925b8f25725a30e1ee6 + url: "https://pub.dev" + source: hosted + version: "1.0.8" + dart_style: + dependency: "direct dev" + description: + name: dart_style + sha256: c87dfe3d56f183ffe9106a18aebc6db431fc7c98c31a54b952a77f3d54a85697 + url: "https://pub.dev" + source: hosted + version: "3.1.2" + dbus: + dependency: transitive + description: + name: dbus + sha256: "79e0c23480ff85dc68de79e2cd6334add97e48f7f4865d17686dd6ea81a47e8c" + url: "https://pub.dev" + source: hosted + version: "0.7.11" + extended_text_field: + dependency: "direct main" + description: + name: extended_text_field + sha256: "3996195c117c6beb734026a7bc0ba80d7e4e84e4edd4728caa544d8209ab4d7d" + url: "https://pub.dev" + source: hosted + version: "16.0.2" + extended_text_library: + dependency: transitive + description: + name: extended_text_library + sha256: "13d99f8a10ead472d5e2cf4770d3d047203fe5054b152e9eb5dc692a71befbba" + url: "https://pub.dev" + source: hosted + version: "12.0.1" + fake_async: + dependency: transitive + description: + name: fake_async + sha256: "5368f224a74523e8d2e7399ea1638b37aecfca824a3cc4dfdf77bf1fa905ac44" + url: "https://pub.dev" + source: hosted + version: "1.3.3" + ffi: + dependency: transitive + description: + name: ffi + sha256: "289279317b4b16eb2bb7e271abccd4bf84ec9bdcbe999e278a94b804f5630418" + url: "https://pub.dev" + source: hosted + version: "2.1.4" + file: + dependency: transitive + description: + name: file + sha256: a3b4f84adafef897088c160faf7dfffb7696046cb13ae90b508c2cbc95d3b8d4 + url: "https://pub.dev" + source: hosted + version: "7.0.1" + file_picker: + dependency: "direct main" + description: + name: file_picker + sha256: e7e16c9d15c36330b94ca0e2ad8cb61f93cd5282d0158c09805aed13b5452f22 + url: "https://pub.dev" + source: hosted + version: "10.3.2" + fixnum: + dependency: transitive + description: + name: fixnum + sha256: b6dc7065e46c974bc7c5f143080a6764ec7a4be6da1285ececdc37be96de53be + url: "https://pub.dev" + source: hosted + version: "1.1.1" + flutter: + dependency: "direct main" + description: flutter + source: sdk + version: "0.0.0" + flutter_blue_plus: + dependency: "direct main" + description: + name: flutter_blue_plus + sha256: bfae0d24619940516261045d8b3c74b4c80ca82222426e05ffbf7f3ea9dbfb1a + url: "https://pub.dev" + source: hosted + version: "1.35.5" + flutter_blue_plus_android: + dependency: transitive + description: + name: flutter_blue_plus_android + sha256: "9723dd4ba7dcc3f27f8202e1159a302eb4cdb88ae482bb8e0dd733b82230a258" + url: "https://pub.dev" + source: hosted + version: "4.0.5" + flutter_blue_plus_darwin: + dependency: transitive + description: + name: flutter_blue_plus_darwin + sha256: f34123795352a9761e321589aa06356d3b53f007f13f7e23e3c940e733259b2d + url: "https://pub.dev" + source: hosted + version: "4.0.1" + flutter_blue_plus_linux: + dependency: transitive + description: + name: flutter_blue_plus_linux + sha256: "635443d1d333e3695733fd70e81ee0d87fa41e78aa81844103d2a8a854b0d593" + url: "https://pub.dev" + source: hosted + version: "3.0.2" + flutter_blue_plus_platform_interface: + dependency: transitive + description: + name: flutter_blue_plus_platform_interface + sha256: a4bb70fa6fd09e0be163b004d773bf19e31104e257a4eb846b67f884ddd87de2 + url: "https://pub.dev" + source: hosted + version: "4.0.2" + flutter_blue_plus_web: + dependency: transitive + description: + name: flutter_blue_plus_web + sha256: "03023c259dbbba1bc5ce0fcd4e88b364f43eec01d45425f393023b9b2722cf4d" + url: "https://pub.dev" + source: hosted + version: "3.0.1" + flutter_driver: + dependency: transitive + description: flutter + source: sdk + version: "0.0.0" + flutter_lints: + dependency: "direct dev" + description: + name: flutter_lints + sha256: "3105dc8492f6183fb076ccf1f351ac3d60564bff92e20bfc4af9cc1651f4e7e1" + url: "https://pub.dev" + source: hosted + version: "6.0.0" + flutter_plugin_android_lifecycle: + dependency: transitive + description: + name: flutter_plugin_android_lifecycle + sha256: "6382ce712ff69b0f719640ce957559dde459e55ecd433c767e06d139ddf16cab" + url: "https://pub.dev" + source: hosted + version: "2.0.29" + flutter_screenutil: + dependency: "direct main" + description: + name: flutter_screenutil + sha256: "8239210dd68bee6b0577aa4a090890342d04a136ce1c81f98ee513fc0ce891de" + url: "https://pub.dev" + source: hosted + version: "5.9.3" + flutter_svg: + dependency: "direct main" + description: + name: flutter_svg + sha256: cd57f7969b4679317c17af6fd16ee233c1e60a82ed209d8a475c54fd6fd6f845 + url: "https://pub.dev" + source: hosted + version: "2.2.0" + flutter_test: + dependency: "direct dev" + description: flutter + source: sdk + version: "0.0.0" + flutter_web_plugins: + dependency: transitive + description: flutter + source: sdk + version: "0.0.0" + fuchsia_remote_debug_protocol: + dependency: transitive + description: flutter + source: sdk + version: "0.0.0" + get_it: + dependency: "direct main" + description: + name: get_it + sha256: a4292e7cf67193f8e7c1258203104eb2a51ec8b3a04baa14695f4064c144297b + url: "https://pub.dev" + source: hosted + version: "8.2.0" + glob: + dependency: transitive + description: + name: glob + sha256: c3f1ee72c96f8f78935e18aa8cecced9ab132419e8625dc187e1c2408efc20de + url: "https://pub.dev" + source: hosted + version: "2.1.3" + go_router: + dependency: "direct main" + description: + name: go_router + sha256: ced3fdc143c1437234ac3b8e985f3286cf138968bb83ca9a6f94d22f2951c6b9 + url: "https://pub.dev" + source: hosted + version: "16.2.0" + google_fonts: + dependency: "direct main" + description: + name: google_fonts + sha256: df9763500dadba0155373e9cb44e202ce21bd9ed5de6bdbd05c5854e86839cb8 + url: "https://pub.dev" + source: hosted + version: "6.3.0" + http: + dependency: transitive + description: + name: http + sha256: bb2ce4590bc2667c96f318d68cac1b5a7987ec819351d32b1c987239a815e007 + url: "https://pub.dev" + source: hosted + version: "1.5.0" + http_parser: + dependency: transitive + description: + name: http_parser + sha256: "178d74305e7866013777bab2c3d8726205dc5a4dd935297175b19a23a2e66571" + url: "https://pub.dev" + source: hosted + version: "4.1.2" + image: + dependency: "direct main" + description: + name: image + sha256: "4e973fcf4caae1a4be2fa0a13157aa38a8f9cb049db6529aa00b4d71abc4d928" + url: "https://pub.dev" + source: hosted + version: "4.5.4" + integration_test: + dependency: "direct dev" + description: flutter + source: sdk + version: "0.0.0" + leak_tracker: + dependency: transitive + description: + name: leak_tracker + sha256: "8dcda04c3fc16c14f48a7bb586d4be1f0d1572731b6d81d51772ef47c02081e0" + url: "https://pub.dev" + source: hosted + version: "11.0.1" + leak_tracker_flutter_testing: + dependency: transitive + description: + name: leak_tracker_flutter_testing + sha256: "1dbc140bb5a23c75ea9c4811222756104fbcd1a27173f0c34ca01e16bea473c1" + url: "https://pub.dev" + source: hosted + version: "3.0.10" + leak_tracker_testing: + dependency: transitive + description: + name: leak_tracker_testing + sha256: "8d5a2d49f4a66b49744b23b018848400d23e54caf9463f4eb20df3eb8acb2eb1" + url: "https://pub.dev" + source: hosted + version: "3.0.2" + lints: + dependency: transitive + description: + name: lints + sha256: a5e2b223cb7c9c8efdc663ef484fdd95bb243bff242ef5b13e26883547fce9a0 + url: "https://pub.dev" + source: hosted + version: "6.0.0" + logger: + dependency: "direct main" + description: + name: logger + sha256: "55d6c23a6c15db14920e037fe7e0dc32e7cdaf3b64b4b25df2d541b5b6b81c0c" + url: "https://pub.dev" + source: hosted + version: "2.6.1" + logging: + dependency: transitive + description: + name: logging + sha256: c8245ada5f1717ed44271ed1c26b8ce85ca3228fd2ffdb75468ab01979309d61 + url: "https://pub.dev" + source: hosted + version: "1.3.0" + matcher: + dependency: transitive + description: + name: matcher + sha256: dc58c723c3c24bf8d3e2d3ad3f2f9d7bd9cf43ec6feaa64181775e60190153f2 + url: "https://pub.dev" + source: hosted + version: "0.12.17" + material_color_utilities: + dependency: transitive + description: + name: material_color_utilities + sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec + url: "https://pub.dev" + source: hosted + version: "0.11.1" + meta: + dependency: transitive + description: + name: meta + sha256: e3641ec5d63ebf0d9b41bd43201a66e3fc79a65db5f61fc181f04cd27aab950c + url: "https://pub.dev" + source: hosted + version: "1.16.0" + mime: + dependency: transitive + description: + name: mime + sha256: "41a20518f0cb1256669420fdba0cd90d21561e560ac240f26ef8322e45bb7ed6" + url: "https://pub.dev" + source: hosted + version: "2.0.0" + nested: + dependency: transitive + description: + name: nested + sha256: "03bac4c528c64c95c722ec99280375a6f2fc708eec17c7b3f07253b626cd2a20" + url: "https://pub.dev" + source: hosted + version: "1.0.0" + package_config: + dependency: transitive + description: + name: package_config + sha256: f096c55ebb7deb7e384101542bfba8c52696c1b56fca2eb62827989ef2353bbc + url: "https://pub.dev" + source: hosted + version: "2.2.0" + path: + dependency: transitive + description: + name: path + sha256: "75cca69d1490965be98c73ceaea117e8a04dd21217b37b292c9ddbec0d955bc5" + url: "https://pub.dev" + source: hosted + version: "1.9.1" + path_parsing: + dependency: transitive + description: + name: path_parsing + sha256: "883402936929eac138ee0a45da5b0f2c80f89913e6dc3bf77eb65b84b409c6ca" + url: "https://pub.dev" + source: hosted + version: "1.1.0" + path_provider: + dependency: "direct main" + description: + name: path_provider + sha256: "50c5dd5b6e1aaf6fb3a78b33f6aa3afca52bf903a8a5298f53101fdaee55bbcd" + url: "https://pub.dev" + source: hosted + version: "2.1.5" + path_provider_android: + dependency: transitive + description: + name: path_provider_android + sha256: d0d310befe2c8ab9e7f393288ccbb11b60c019c6b5afc21973eeee4dda2b35e9 + url: "https://pub.dev" + source: hosted + version: "2.2.17" + path_provider_foundation: + dependency: transitive + description: + name: path_provider_foundation + sha256: "16eef174aacb07e09c351502740fa6254c165757638eba1e9116b0a781201bbd" + url: "https://pub.dev" + source: hosted + version: "2.4.2" + path_provider_linux: + dependency: transitive + description: + name: path_provider_linux + sha256: f7a1fe3a634fe7734c8d3f2766ad746ae2a2884abe22e241a8b301bf5cac3279 + url: "https://pub.dev" + source: hosted + version: "2.2.1" + path_provider_platform_interface: + dependency: transitive + description: + name: path_provider_platform_interface + sha256: "88f5779f72ba699763fa3a3b06aa4bf6de76c8e5de842cf6f29e2e06476c2334" + url: "https://pub.dev" + source: hosted + version: "2.1.2" + path_provider_windows: + dependency: transitive + description: + name: path_provider_windows + sha256: bd6f00dbd873bfb70d0761682da2b3a2c2fccc2b9e84c495821639601d81afe7 + url: "https://pub.dev" + source: hosted + version: "2.3.0" + petitparser: + dependency: transitive + description: + name: petitparser + sha256: "1a97266a94f7350d30ae522c0af07890c70b8e62c71e8e3920d1db4d23c057d1" + url: "https://pub.dev" + source: hosted + version: "7.0.1" + platform: + dependency: transitive + description: + name: platform + sha256: "5d6b1b0036a5f331ebc77c850ebc8506cbc1e9416c27e59b439f917a902a4984" + url: "https://pub.dev" + source: hosted + version: "3.1.6" + plugin_platform_interface: + dependency: transitive + description: + name: plugin_platform_interface + sha256: "4820fbfdb9478b1ebae27888254d445073732dae3d6ea81f0b7e06d5dedc3f02" + url: "https://pub.dev" + source: hosted + version: "2.1.8" + posix: + dependency: transitive + description: + name: posix + sha256: "6323a5b0fa688b6a010df4905a56b00181479e6d10534cecfecede2aa55add61" + url: "https://pub.dev" + source: hosted + version: "6.0.3" + process: + dependency: transitive + description: + name: process + sha256: c6248e4526673988586e8c00bb22a49210c258dc91df5227d5da9748ecf79744 + url: "https://pub.dev" + source: hosted + version: "5.0.5" + provider: + dependency: "direct main" + description: + name: provider + sha256: "4e82183fa20e5ca25703ead7e05de9e4cceed1fbd1eadc1ac3cb6f565a09f272" + url: "https://pub.dev" + source: hosted + version: "6.1.5+1" + pub_semver: + dependency: transitive + description: + name: pub_semver + sha256: "5bfcf68ca79ef689f8990d1160781b4bad40a3bd5e5218ad4076ddb7f4081585" + url: "https://pub.dev" + source: hosted + version: "2.2.0" + rxdart: + dependency: transitive + description: + name: rxdart + sha256: "5c3004a4a8dbb94bd4bf5412a4def4acdaa12e12f269737a5751369e12d1a962" + url: "https://pub.dev" + source: hosted + version: "0.28.0" + share_plus: + dependency: "direct main" + description: + name: share_plus + sha256: d7dc0630a923883c6328ca31b89aa682bacbf2f8304162d29f7c6aaff03a27a1 + url: "https://pub.dev" + source: hosted + version: "11.1.0" + share_plus_platform_interface: + dependency: transitive + description: + name: share_plus_platform_interface + sha256: "88023e53a13429bd65d8e85e11a9b484f49d4c190abbd96c7932b74d6927cc9a" + url: "https://pub.dev" + source: hosted + version: "6.1.0" + shared_preferences: + dependency: "direct main" + description: + name: shared_preferences + sha256: "6e8bf70b7fef813df4e9a36f658ac46d107db4b4cfe1048b477d4e453a8159f5" + url: "https://pub.dev" + source: hosted + version: "2.5.3" + shared_preferences_android: + dependency: transitive + description: + name: shared_preferences_android + sha256: "5bcf0772a761b04f8c6bf814721713de6f3e5d9d89caf8d3fe031b02a342379e" + url: "https://pub.dev" + source: hosted + version: "2.4.11" + shared_preferences_foundation: + dependency: transitive + description: + name: shared_preferences_foundation + sha256: "6a52cfcdaeac77cad8c97b539ff688ccfc458c007b4db12be584fbe5c0e49e03" + url: "https://pub.dev" + source: hosted + version: "2.5.4" + shared_preferences_linux: + dependency: transitive + description: + name: shared_preferences_linux + sha256: "580abfd40f415611503cae30adf626e6656dfb2f0cee8f465ece7b6defb40f2f" + url: "https://pub.dev" + source: hosted + version: "2.4.1" + shared_preferences_platform_interface: + dependency: transitive + description: + name: shared_preferences_platform_interface + sha256: "57cbf196c486bc2cf1f02b85784932c6094376284b3ad5779d1b1c6c6a816b80" + url: "https://pub.dev" + source: hosted + version: "2.4.1" + shared_preferences_web: + dependency: transitive + description: + name: shared_preferences_web + sha256: c49bd060261c9a3f0ff445892695d6212ff603ef3115edbb448509d407600019 + url: "https://pub.dev" + source: hosted + version: "2.4.3" + shared_preferences_windows: + dependency: transitive + description: + name: shared_preferences_windows + sha256: "94ef0f72b2d71bc3e700e025db3710911bd51a71cefb65cc609dd0d9a982e3c1" + url: "https://pub.dev" + source: hosted + version: "2.4.1" + sky_engine: + dependency: transitive + description: flutter + source: sdk + version: "0.0.0" + source_span: + dependency: transitive + description: + name: source_span + sha256: "254ee5351d6cb365c859e20ee823c3bb479bf4a293c22d17a9f1bf144ce86f7c" + url: "https://pub.dev" + source: hosted + version: "1.10.1" + sprintf: + dependency: transitive + description: + name: sprintf + sha256: "1fc9ffe69d4df602376b52949af107d8f5703b77cda567c4d7d86a0693120f23" + url: "https://pub.dev" + source: hosted + version: "7.0.0" + stack_trace: + dependency: transitive + description: + name: stack_trace + sha256: "8b27215b45d22309b5cddda1aa2b19bdfec9df0e765f2de506401c071d38d1b1" + url: "https://pub.dev" + source: hosted + version: "1.12.1" + stream_channel: + dependency: transitive + description: + name: stream_channel + sha256: "969e04c80b8bcdf826f8f16579c7b14d780458bd97f56d107d3950fdbeef059d" + url: "https://pub.dev" + source: hosted + version: "2.1.4" + string_scanner: + dependency: transitive + description: + name: string_scanner + sha256: "921cd31725b72fe181906c6a94d987c78e3b98c2e205b397ea399d4054872b43" + url: "https://pub.dev" + source: hosted + version: "1.4.1" + sync_http: + dependency: transitive + description: + name: sync_http + sha256: "7f0cd72eca000d2e026bcd6f990b81d0ca06022ef4e32fb257b30d3d1014a961" + url: "https://pub.dev" + source: hosted + version: "0.3.1" + term_glyph: + dependency: transitive + description: + name: term_glyph + sha256: "7f554798625ea768a7518313e58f83891c7f5024f88e46e7182a4558850a4b8e" + url: "https://pub.dev" + source: hosted + version: "1.2.2" + test_api: + dependency: transitive + description: + name: test_api + sha256: "522f00f556e73044315fa4585ec3270f1808a4b186c936e612cab0b565ff1e00" + url: "https://pub.dev" + source: hosted + version: "0.7.6" + typed_data: + dependency: transitive + description: + name: typed_data + sha256: f9049c039ebfeb4cf7a7104a675823cd72dba8297f264b6637062516699fa006 + url: "https://pub.dev" + source: hosted + version: "1.4.0" + url_launcher: + dependency: "direct main" + description: + name: url_launcher + sha256: f6a7e5c4835bb4e3026a04793a4199ca2d14c739ec378fdfe23fc8075d0439f8 + url: "https://pub.dev" + source: hosted + version: "6.3.2" + url_launcher_android: + dependency: transitive + description: + name: url_launcher_android + sha256: "0aedad096a85b49df2e4725fa32118f9fa580f3b14af7a2d2221896a02cd5656" + url: "https://pub.dev" + source: hosted + version: "6.3.17" + url_launcher_ios: + dependency: transitive + description: + name: url_launcher_ios + sha256: d80b3f567a617cb923546034cc94bfe44eb15f989fe670b37f26abdb9d939cb7 + url: "https://pub.dev" + source: hosted + version: "6.3.4" + url_launcher_linux: + dependency: transitive + description: + name: url_launcher_linux + sha256: "4e9ba368772369e3e08f231d2301b4ef72b9ff87c31192ef471b380ef29a4935" + url: "https://pub.dev" + source: hosted + version: "3.2.1" + url_launcher_macos: + dependency: transitive + description: + name: url_launcher_macos + sha256: c043a77d6600ac9c38300567f33ef12b0ef4f4783a2c1f00231d2b1941fea13f + url: "https://pub.dev" + source: hosted + version: "3.2.3" + url_launcher_platform_interface: + dependency: transitive + description: + name: url_launcher_platform_interface + sha256: "552f8a1e663569be95a8190206a38187b531910283c3e982193e4f2733f01029" + url: "https://pub.dev" + source: hosted + version: "2.3.2" + url_launcher_web: + dependency: transitive + description: + name: url_launcher_web + sha256: "4bd2b7b4dc4d4d0b94e5babfffbca8eac1a126c7f3d6ecbc1a11013faa3abba2" + url: "https://pub.dev" + source: hosted + version: "2.4.1" + url_launcher_windows: + dependency: transitive + description: + name: url_launcher_windows + sha256: "3284b6d2ac454cf34f114e1d3319866fdd1e19cdc329999057e44ffe936cfa77" + url: "https://pub.dev" + source: hosted + version: "3.1.4" + uuid: + dependency: "direct main" + description: + name: uuid + sha256: a5be9ef6618a7ac1e964353ef476418026db906c4facdedaa299b7a2e71690ff + url: "https://pub.dev" + source: hosted + version: "4.5.1" + vector_graphics: + dependency: transitive + description: + name: vector_graphics + sha256: a4f059dc26fc8295b5921376600a194c4ec7d55e72f2fe4c7d2831e103d461e6 + url: "https://pub.dev" + source: hosted + version: "1.1.19" + vector_graphics_codec: + dependency: transitive + description: + name: vector_graphics_codec + sha256: "99fd9fbd34d9f9a32efd7b6a6aae14125d8237b10403b422a6a6dfeac2806146" + url: "https://pub.dev" + source: hosted + version: "1.1.13" + vector_graphics_compiler: + dependency: transitive + description: + name: vector_graphics_compiler + sha256: d354a7ec6931e6047785f4db12a1f61ec3d43b207fc0790f863818543f8ff0dc + url: "https://pub.dev" + source: hosted + version: "1.1.19" + vector_math: + dependency: transitive + description: + name: vector_math + sha256: d530bd74fea330e6e364cda7a85019c434070188383e1cd8d9777ee586914c5b + url: "https://pub.dev" + source: hosted + version: "2.2.0" + vm_service: + dependency: transitive + description: + name: vm_service + sha256: "45caa6c5917fa127b5dbcfbd1fa60b14e583afdc08bfc96dda38886ca252eb60" + url: "https://pub.dev" + source: hosted + version: "15.0.2" + watcher: + dependency: transitive + description: + name: watcher + sha256: "5bf046f41320ac97a469d506261797f35254fa61c641741ef32dacda98b7d39c" + url: "https://pub.dev" + source: hosted + version: "1.1.3" + web: + dependency: transitive + description: + name: web + sha256: "868d88a33d8a87b18ffc05f9f030ba328ffefba92d6c127917a2ba740f9cfe4a" + url: "https://pub.dev" + source: hosted + version: "1.1.1" + webdriver: + dependency: transitive + description: + name: webdriver + sha256: "2f3a14ca026957870cfd9c635b83507e0e51d8091568e90129fbf805aba7cade" + url: "https://pub.dev" + source: hosted + version: "3.1.0" + win32: + dependency: transitive + description: + name: win32 + sha256: "66814138c3562338d05613a6e368ed8cfb237ad6d64a9e9334be3f309acfca03" + url: "https://pub.dev" + source: hosted + version: "5.14.0" + xdg_directories: + dependency: transitive + description: + name: xdg_directories + sha256: "7a3f37b05d989967cdddcbb571f1ea834867ae2faa29725fd085180e0883aa15" + url: "https://pub.dev" + source: hosted + version: "1.1.0" + xml: + dependency: transitive + description: + name: xml + sha256: "971043b3a0d3da28727e40ed3e0b5d18b742fa5a68665cca88e74b7876d5e025" + url: "https://pub.dev" + source: hosted + version: "6.6.1" + yaml: + dependency: transitive + description: + name: yaml + sha256: b9da305ac7c39faa3f030eccd175340f968459dae4af175130b3fc47e40d76ce + url: "https://pub.dev" + source: hosted + version: "3.1.3" +sdks: + dart: ">=3.8.0 <4.0.0" + flutter: ">=3.32.4" From 0d436afa2d9a2b73d6af42888b3b93165c535dd0 Mon Sep 17 00:00:00 2001 From: Samruddhi Rahegaonkar Date: Thu, 28 Aug 2025 18:39:19 +0530 Subject: [PATCH 7/9] fix: formated the file --- lib/main.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/main.dart b/lib/main.dart index b136dbee5..30b13ddc7 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -25,7 +25,7 @@ void main() { ChangeNotifierProvider( create: (context) => getIt()), ChangeNotifierProvider( - create: (_) => getIt(), + create: (_) => getIt(), ), ], child: const MyApp(), From be7693cae219435b4e66f867eea824ac6b25ce61 Mon Sep 17 00:00:00 2001 From: Samruddhi Rahegaonkar Date: Thu, 28 Aug 2025 19:18:31 +0530 Subject: [PATCH 8/9] fix: fixed it according to new version --- lib/providers/animation_badge_provider.dart | 124 +++++++++++++++++++- 1 file changed, 118 insertions(+), 6 deletions(-) diff --git a/lib/providers/animation_badge_provider.dart b/lib/providers/animation_badge_provider.dart index f941d82d5..080d491e0 100644 --- a/lib/providers/animation_badge_provider.dart +++ b/lib/providers/animation_badge_provider.dart @@ -1,4 +1,7 @@ import 'dart:async'; +import 'package:badgemagic/providers/badge_message_provider.dart'; +import 'package:badgemagic/providers/imageprovider.dart'; +import 'package:badgemagic/providers/speed_dial_provider.dart'; import 'package:badgemagic/bademagic_module/utils/byte_array_utils.dart'; import 'package:badgemagic/bademagic_module/utils/converters.dart'; import 'package:badgemagic/badge_animation/ani_animation.dart'; @@ -10,6 +13,17 @@ import 'package:badgemagic/badge_animation/ani_picture.dart'; import 'package:badgemagic/badge_animation/ani_right.dart'; import 'package:badgemagic/badge_animation/ani_snowflake.dart'; import 'package:badgemagic/badge_animation/ani_up.dart'; +import 'package:badgemagic/badge_animation/ani_pacman.dart'; +import 'package:badgemagic/badge_animation/ani_chevron_left.dart'; +import 'package:badgemagic/badge_animation/ani_diamond.dart'; +import 'package:badgemagic/badge_animation/ani_broken_hearts.dart'; +import 'package:badgemagic/badge_animation/ani_cupid.dart'; +import 'package:badgemagic/badge_animation/ani_feet.dart'; +import 'package:badgemagic/badge_animation/ani_fish.dart'; +import 'package:badgemagic/badge_animation/ani_diagonal.dart'; +import 'package:badgemagic/badge_animation/ani_emergency.dart'; +import 'package:badgemagic/badge_animation/ani_beating_hearts.dart'; +import 'package:badgemagic/badge_animation/ani_fireworks.dart'; import 'package:badgemagic/badge_animation/animation_abstract.dart'; import 'package:badgemagic/badge_effect/badgeeffectabstract.dart'; import 'package:badgemagic/badge_effect/flash_effect.dart'; @@ -28,6 +42,17 @@ Map animationMap = { 6: SnowFlakeAnimation(), 7: PictureAnimation(), 8: LaserAnimation(), + 9: PacmanClassicAnimation(), // Pacman + 10: LeftChevronAnimation(), // Chevron left + 11: DiamondAnimation(), // Diamond + 12: BrokenHeartsAnimation(), // Broken Hearts + 13: CupidAnimation(), // Cupid + 14: FeetAnimation(), // Feet + 15: FishAnimation(), // Fish + 16: DiagonalAnimation(), // Diagonal + 17: EmergencyAnimation(), // Emergency + 18: BeatingHeartsAnimation(), // Beating Hearts + 19: FireworksAnimation(), // Fireworks }; Map effectMap = { @@ -54,9 +79,33 @@ class AnimationBadgeProvider extends ChangeNotifier { //function to get the state of the cell List> getPaintGrid() => _paintGrid; + // Helper: returns true if a special animation (custom) is selected + bool isSpecialAnimationSelected() { + int idx = getAnimationIndex() ?? 0; + // Add all special animation indices here (including Fireworks at 19): + return [9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19].contains(idx); + } + + // Call this to reset to text animation (LeftAnimation) + void resetToTextAnimation() { + setAnimationMode(LeftAnimation()); + } + //function to calculate duration for the animation void calculateDuration(int speed) { - int newSpeed = aniSpeedStrategy(speed - 1); + int idx = getAnimationIndex() ?? 0; + int newSpeed; + if (idx == 9 || idx == 10 || idx == 11 || idx == 12) { + // Use slower mapping for custom animations + // (aniSpeedStrategy already uses the slower mapping if you want, or you can hardcode) + newSpeed = aniSpeedStrategy(speed - 1); // keep as is, or adjust if needed + } else { + // Use original (faster) mapping for text/standard animations + // For original: aniBaseSpeed = 200000us, minSpeed = 25000us (example) + const int originalBase = 200000; + const int minSpeed = 25000; + newSpeed = originalBase - ((speed - 1) * (originalBase - minSpeed) ~/ 8); + } if (newSpeed != _animationSpeed) { _animationSpeed = newSpeed; _timer?.cancel(); @@ -127,18 +176,27 @@ class AnimationBadgeProvider extends ChangeNotifier { void startTimer() { _timer = Timer.periodic(Duration(microseconds: _animationSpeed), (Timer timer) { - // logger.i( - // "New Grid set to: ${getNewGrid().map((e) => e.map((e) => e ? 1 : 0).toList()).toList()}"); renderGrid(getNewGrid()); - _animationIndex++; + if (_currentAnimation is CupidAnimation) { + int frameLimit = + CupidAnimation.frameCount(_paintGrid[0].length, _paintGrid.length); + _animationIndex = (_animationIndex + 1) % frameLimit; + } else { + _animationIndex++; + } }); } void setAnimationMode(BadgeAnimation? animation) { + // Always reset the animation index and set the new animation _animationIndex = 0; _currentAnimation = animation ?? LeftAnimation(); + // Stop the timer if running + _timer?.cancel(); + // Start the timer for the new animation + startTimer(); notifyListeners(); - logger.i("Animation Mode set to: $_currentAnimation"); + logger.i("Animation Mode set to: $_currentAnimation and timer restarted"); } int? getAnimationIndex() { @@ -158,7 +216,8 @@ class AnimationBadgeProvider extends ChangeNotifier { void badgeAnimation( String message, Converters converters, bool isInverted) async { - if (message.isEmpty) { + bool isSpecial = isSpecialAnimationSelected(); + if (message.isEmpty && !isSpecial) { stopAllAnimations(); List> emptyGrid = List.generate(11, (i) => List.generate(44, (j) => false)); @@ -192,4 +251,57 @@ class AnimationBadgeProvider extends ChangeNotifier { _paintGrid = canvas; notifyListeners(); } + + /// Handles animation transfer selection logic for the current animation index. + Future handleAnimationTransfer({ + required BadgeMessageProvider badgeData, + required InlineImageProvider inlineImageProvider, + required SpeedDialProvider speedDialProvider, + required bool flash, + required bool marquee, + required bool invert, + required BuildContext context, + }) async { + final int aniIndex = getAnimationIndex() ?? 0; + final int selectedSpeed = speedDialProvider.getOuterValue(); + if (aniIndex == 9) { + // Pacman + await transferPacmanAnimation(badgeData, selectedSpeed); + } else if (aniIndex == 10) { + await transferChevronAnimation(badgeData, selectedSpeed); + } else if (aniIndex == 11) { + await transferDiamondAnimation(badgeData, selectedSpeed); + } else if (aniIndex == 12) { + await transferBrokenHeartsAnimation(badgeData, selectedSpeed); + } else if (aniIndex == 13) { + await transferCupidAnimation(badgeData, selectedSpeed); + setAnimationMode(CupidAnimation()); + _animationIndex = 0; + if (_timer == null || !_timer!.isActive) startTimer(); + } else if (aniIndex == 14) { + await transferFeetAnimation(badgeData, selectedSpeed); + } else if (aniIndex == 15) { + await transferFishAnimation(badgeData, selectedSpeed); + } else if (aniIndex == 16) { + await transferDiagonalAnimation(badgeData, selectedSpeed); + } else if (aniIndex == 17) { + await transferEmergencyAnimation(badgeData, selectedSpeed); + } else if (aniIndex == 18) { + await transferBeatingHeartsAnimation(badgeData, selectedSpeed); + } else if (aniIndex == 19) { + await transferFireworksAnimation(badgeData, selectedSpeed); + } else { + await badgeData.checkAndTransfer( + inlineImageProvider.getController().text, + flash, + marquee, + invert, + selectedSpeed, + modeValueMap[aniIndex], + null, + false, + context, + ); + } + } } From aba7767eab40cd194865cdc98c3c81c60c9206b9 Mon Sep 17 00:00:00 2001 From: Samruddhi Rahegaonkar Date: Thu, 28 Aug 2025 19:29:25 +0530 Subject: [PATCH 9/9] fix: fixed homescreen according to new version --- lib/view/homescreen.dart | 404 +++++++++++++++++++++++++++++---------- 1 file changed, 304 insertions(+), 100 deletions(-) diff --git a/lib/view/homescreen.dart b/lib/view/homescreen.dart index 8fc6f33bc..4d713a438 100644 --- a/lib/view/homescreen.dart +++ b/lib/view/homescreen.dart @@ -1,19 +1,25 @@ import 'dart:async'; -import 'package:badgemagic/bademagic_module/utils/converters.dart'; -import 'package:badgemagic/bademagic_module/utils/image_utils.dart'; -import 'package:badgemagic/bademagic_module/utils/toast_utils.dart'; +import 'package:badgemagic/bademagic_module/utils/badge_loader_helper.dart'; import 'package:badgemagic/badge_effect/flash_effect.dart'; import 'package:badgemagic/badge_effect/invert_led_effect.dart'; import 'package:badgemagic/badge_effect/marquee_effect.dart'; +import 'package:badgemagic/bademagic_module/utils/converters.dart'; + +import 'package:badgemagic/bademagic_module/utils/image_utils.dart'; +import 'package:badgemagic/bademagic_module/utils/toast_utils.dart'; +import 'package:badgemagic/bademagic_module/models/speed.dart'; import 'package:badgemagic/constants.dart'; import 'package:badgemagic/providers/animation_badge_provider.dart'; -import 'package:badgemagic/providers/badge_message_provider.dart'; +import 'package:badgemagic/providers/badge_message_provider.dart' + hide modeValueMap, speedMap; import 'package:badgemagic/providers/imageprovider.dart'; +import 'package:badgemagic/providers/saved_badge_provider.dart'; import 'package:badgemagic/providers/speed_dial_provider.dart'; import 'package:badgemagic/view/special_text_field.dart'; import 'package:badgemagic/view/widgets/common_scaffold_widget.dart'; import 'package:badgemagic/view/widgets/homescreentabs.dart'; +import 'package:badgemagic/view/widgets/transitiontab.dart'; import 'package:badgemagic/view/widgets/save_badge_dialog.dart'; import 'package:badgemagic/view/widgets/speedial.dart'; import 'package:badgemagic/view/widgets/vectorview.dart'; @@ -26,7 +32,15 @@ import 'package:get_it/get_it.dart'; import 'package:provider/provider.dart'; class HomeScreen extends StatefulWidget { - const HomeScreen({super.key}); + // Add parameters for saved badge data when editing + final String? savedBadgeFilename; + final int? initialSpeed; + + const HomeScreen({ + super.key, + this.savedBadgeFilename, + this.initialSpeed, + }); @override State createState() => _HomeScreenState(); @@ -38,8 +52,8 @@ class _HomeScreenState extends State AutomaticKeepAliveClientMixin, WidgetsBindingObserver { late final TabController _tabController; - late SpeedDialProvider speedDialProvider; final AnimationBadgeProvider animationProvider = AnimationBadgeProvider(); + late SpeedDialProvider speedDialProvider; final BadgeMessageProvider badgeData = BadgeMessageProvider(); final ImageUtils imageUtils = ImageUtils(); final InlineImageProvider inlineImageProvider = @@ -51,19 +65,94 @@ class _HomeScreenState extends State bool isDialInteracting = false; String previousText = ''; String _cachedText = ''; + String errorVal = ""; @override void initState() { + super.initState(); WidgetsBinding.instance.addObserver(this); inlineimagecontroller.addListener(handleTextChange); _setPortraitOrientation(); - WidgetsBinding.instance.addPostFrameCallback((_) { + speedDialProvider = SpeedDialProvider(animationProvider); + + // If initialSpeed is provided, set it immediately + if (widget.initialSpeed != null) { + speedDialProvider.setDialValue(widget.initialSpeed!); + } + + WidgetsBinding.instance.addPostFrameCallback((_) async { inlineImageProvider.setContext(context); + + // Apply saved badge data if we're editing a saved badge + if (widget.savedBadgeFilename != null) { + await _loadBadgeDataFromDisk(widget.savedBadgeFilename!); + } }); _startImageCaching(); - speedDialProvider = SpeedDialProvider(animationProvider); - _tabController = TabController(length: 3, vsync: this); - super.initState(); + _tabController = TabController(length: 4, vsync: this); + } + + // Loads badge data from disk and populates controllers/providers for editing + Future _loadBadgeDataFromDisk(String badgeFilename) async { + try { + final (badgeText, badgeData, savedData) = + await BadgeLoaderHelper.loadBadgeDataAndText(badgeFilename); + + // Set the text in the controller + inlineimagecontroller.text = badgeText; + + // Set animation effects + animationProvider.removeEffect(effectMap[0]); // Invert + animationProvider.removeEffect(effectMap[1]); // Flash + animationProvider.removeEffect(effectMap[2]); // Marquee + + final message = badgeData.messages[0]; + if (message.flash) { + animationProvider.addEffect(effectMap[1]); + } + if (message.marquee) { + animationProvider.addEffect(effectMap[2]); + } + if (savedData != null && + savedData.containsKey('invert') && + savedData['invert'] == true) { + animationProvider.addEffect(effectMap[0]); + } + + // Set animation mode + int modeValue = BadgeLoaderHelper.parseAnimationMode(message.mode); + animationProvider.setAnimationMode(animationMap[modeValue]); + + // Set speed + try { + int speedDialValue = Speed.getIntValue(message.speed); + speedDialProvider.setDialValue(speedDialValue); + } catch (e) { + speedDialProvider.setDialValue(1); + } + + ToastUtils().showToast( + "Editing badge: ${badgeFilename.substring(0, badgeFilename.length - 5)}"); + } catch (e) { + print("Failed to load badge data: $e"); + ToastUtils().showToast("Failed to load badge data"); + } + } + + void _setPortraitOrientation() { + SystemChrome.setPreferredOrientations([ + DeviceOrientation.portraitUp, + DeviceOrientation.portraitDown, + ]); + } + + Future _startImageCaching() async { + if (!inlineImageProvider.isCacheInitialized) { + await inlineImageProvider.generateImageCache(); + setState(() { + inlineImageProvider.isCacheInitialized = true; + }); + } } @override @@ -78,10 +167,8 @@ class _HomeScreenState extends State @override void didChangeAppLifecycleState(AppLifecycleState state) { - if (state == AppLifecycleState.paused) { - _cachedText = inlineimagecontroller.text; - animationProvider.stopAnimation(); - } else if (state == AppLifecycleState.resumed) { + super.didChangeAppLifecycleState(state); + if (state == AppLifecycleState.resumed) { if (inlineimagecontroller.text.trim().isEmpty && _cachedText.trim().isNotEmpty) { inlineimagecontroller.text = _cachedText; @@ -91,28 +178,34 @@ class _HomeScreenState extends State Converters(), animationProvider.isEffectActive(InvertLEDEffect()), ); + if (mounted) setState(() {}); + } else if (state == AppLifecycleState.paused) { + _cachedText = inlineimagecontroller.text; + animationProvider.stopAnimation(); + } else if (state == AppLifecycleState.inactive) { + animationProvider.stopAnimation(); } } - void _controllerListner() { - animationProvider.badgeAnimation( - inlineImageProvider.getController().text, - Converters(), - animationProvider.isEffectActive(InvertLEDEffect()), - ); - } - void handleTextChange() { final currentText = inlineimagecontroller.text; final selection = inlineimagecontroller.selection; + // Always reset to text animation if a special animation is selected and user types + if (animationProvider.isSpecialAnimationSelected() && + currentText.isNotEmpty) { + animationProvider.resetToTextAnimation(); + animationProvider.badgeAnimation(currentText, Converters(), + animationProvider.isEffectActive(InvertLEDEffect())); + setState(() {}); // Ensure UI updates + } + if (previousText.length > currentText.length) { final deletionIndex = selection.baseOffset; final regex = RegExp(r'<<\d+>>'); final matches = regex.allMatches(previousText); bool placeholderDeleted = false; - for (final match in matches) { if (deletionIndex > match.start && deletionIndex < match.end) { inlineimagecontroller.text = @@ -123,7 +216,6 @@ class _HomeScreenState extends State break; } } - if (!placeholderDeleted) { previousText = inlineimagecontroller.text; } @@ -132,40 +224,34 @@ class _HomeScreenState extends State } } - void _setPortraitOrientation() { - SystemChrome.setPreferredOrientations([ - DeviceOrientation.portraitUp, - DeviceOrientation.portraitDown, - ]); - } - - Future _startImageCaching() async { - if (!inlineImageProvider.isCacheInitialized) { - await inlineImageProvider.generateImageCache(); - setState(() { - inlineImageProvider.isCacheInitialized = true; - }); - } + void _controllerListner() { + animationProvider.badgeAnimation( + inlineImageProvider.getController().text, + Converters(), + animationProvider.isEffectActive(InvertLEDEffect()), + ); } @override Widget build(BuildContext context) { super.build(context); + InlineImageProvider inlineImageProvider = + Provider.of(context); return MultiProvider( providers: [ ChangeNotifierProvider( - create: (_) => animationProvider, + create: (context) => animationProvider, ), ChangeNotifierProvider( - create: (_) { - inlineimagecontroller.addListener(_controllerListner); + create: (context) { + inlineImageProvider.getController().addListener(_controllerListner); return speedDialProvider; }, ), ], child: DefaultTabController( - length: 3, + length: 4, child: CommonScaffold( index: 0, title: 'Badge Magic', @@ -185,6 +271,7 @@ class _HomeScreenState extends State borderRadius: BorderRadius.circular(10.r), elevation: 4, child: ExtendedTextField( + onChanged: (value) {}, controller: inlineimagecontroller, specialTextSpanBuilder: ImageBuilder(), decoration: InputDecoration( @@ -223,7 +310,10 @@ class _HomeScreenState extends State ), ), TabBar( + isScrollable: false, indicatorSize: TabBarIndicatorSize.tab, + labelStyle: TextStyle(fontSize: 12), + unselectedLabelStyle: TextStyle(fontSize: 12), labelColor: Colors.black, unselectedLabelColor: mdGrey400, indicatorColor: colorPrimary, @@ -237,6 +327,7 @@ class _HomeScreenState extends State tabs: const [ Tab(text: 'Speed'), Tab(text: 'Animation'), + Tab(text: 'Transition'), Tab(text: 'Effects'), ], ), @@ -255,6 +346,7 @@ class _HomeScreenState extends State setState(() => isDialInteracting = false), child: RadialDial(), ), + TransitionTab(), AnimationTab(), EffectTab(), ], @@ -262,72 +354,184 @@ class _HomeScreenState extends State ), Row( mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, children: [ Container( padding: EdgeInsets.symmetric(vertical: 20.h), - child: GestureDetector( - onTap: () { - if (inlineimagecontroller.text.trim().isEmpty) { - ToastUtils() - .showErrorToast("Please enter a message"); - return; + child: Consumer( + builder: (context, animationProvider, _) { + final isSpecial = + animationProvider.isSpecialAnimationSelected(); + if (isSpecial) { + // Only show Transfer button, centered + return Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Container( + padding: + EdgeInsets.symmetric(vertical: 20.h), + child: GestureDetector( + onTap: () async { + await animationProvider + .handleAnimationTransfer( + badgeData: badgeData, + inlineImageProvider: + inlineImageProvider, + speedDialProvider: speedDialProvider, + flash: animationProvider + .isEffectActive(FlashEffect()), + marquee: animationProvider + .isEffectActive(MarqueeEffect()), + invert: + animationProvider.isEffectActive( + InvertLEDEffect()), + context: context, + ); + }, + child: Container( + padding: EdgeInsets.symmetric( + horizontal: 33.w, vertical: 8.h), + decoration: BoxDecoration( + borderRadius: + BorderRadius.circular(2.r), + color: mdGrey400, + ), + child: const Text('Transfer'), + ), + ), + ), + ], + ); + } else { + // Show both Save and Transfer as before + return Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Container( + padding: + EdgeInsets.symmetric(vertical: 20.h), + child: GestureDetector( + onTap: () async { + if (inlineimagecontroller.text + .trim() + .isEmpty) { + ToastUtils().showToast( + "Please enter a message"); + return; + } + // If we're editing an existing badge, update it instead of showing save dialog + if (widget.savedBadgeFilename != null) { + SavedBadgeProvider + savedBadgeProvider = + SavedBadgeProvider(); + String baseFilename = + widget.savedBadgeFilename!; + if (baseFilename.endsWith('.json')) { + baseFilename = + baseFilename.substring( + 0, baseFilename.length - 5); + } + await savedBadgeProvider + .updateBadgeData( + baseFilename, // Pass the filename without .json extension + inlineimagecontroller.text, + animationProvider + .isEffectActive(FlashEffect()), + animationProvider.isEffectActive( + MarqueeEffect()), + animationProvider.isEffectActive( + InvertLEDEffect()), + speedDialProvider.getOuterValue(), + animationProvider + .getAnimationIndex() ?? + 1, + ); + ToastUtils().showToast( + "Badge Updated Successfully"); + Navigator.pushNamedAndRemoveUntil( + context, + '/savedBadge', + (route) => false); + } else { + // Show save dialog for new badges + showDialog( + context: context, + builder: (context) { + return SaveBadgeDialog( + speed: speedDialProvider, + animationProvider: + animationProvider, + textController: + inlineimagecontroller, + isInverse: animationProvider + .isEffectActive( + InvertLEDEffect()), + ); + }, + ); + } + }, + child: Container( + padding: EdgeInsets.symmetric( + horizontal: 33.w, vertical: 8.h), + decoration: BoxDecoration( + borderRadius: + BorderRadius.circular(2.r), + color: mdGrey400, + ), + child: const Text('Save'), + ), + ), + ), + SizedBox(width: 100.w), + Container( + padding: + EdgeInsets.symmetric(vertical: 20.h), + child: GestureDetector( + onTap: () async { + if (inlineimagecontroller.text + .trim() + .isEmpty) { + ToastUtils().showErrorToast( + "Please enter a message"); + return; + } + await animationProvider + .handleAnimationTransfer( + badgeData: badgeData, + inlineImageProvider: + inlineImageProvider, + speedDialProvider: speedDialProvider, + flash: animationProvider + .isEffectActive(FlashEffect()), + marquee: animationProvider + .isEffectActive(MarqueeEffect()), + invert: + animationProvider.isEffectActive( + InvertLEDEffect()), + context: context, + ); + }, + child: Container( + padding: EdgeInsets.symmetric( + horizontal: 20.w, vertical: 8.h), + decoration: BoxDecoration( + borderRadius: + BorderRadius.circular(2.r), + color: mdGrey400, + ), + child: const Text('Transfer'), + ), + ), + ), + ], + ); } - showDialog( - context: context, - builder: (context) { - return SaveBadgeDialog( - speed: speedDialProvider, - animationProvider: animationProvider, - textController: inlineimagecontroller, - isInverse: animationProvider - .isEffectActive(InvertLEDEffect()), - ); - }, - ); }, - child: Container( - padding: EdgeInsets.symmetric( - horizontal: 33.w, vertical: 8.h), - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(2.r), - color: mdGrey400, - ), - child: const Text('Save'), - ), - ), - ), - SizedBox(width: 100.w), - Container( - padding: EdgeInsets.symmetric(vertical: 20.h), - child: GestureDetector( - onTap: () { - badgeData.checkAndTransfer( - inlineimagecontroller.text, - animationProvider.isEffectActive(FlashEffect()), - animationProvider.isEffectActive(MarqueeEffect()), - animationProvider - .isEffectActive(InvertLEDEffect()), - speedDialProvider.getOuterValue(), - modeValueMap[ - animationProvider.getAnimationIndex()], - null, - false, - context, // <== This is needed and now passed - ); - }, - child: Container( - padding: EdgeInsets.symmetric( - horizontal: 20.w, vertical: 8.h), - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(2.r), - color: mdGrey400, - ), - child: const Text('Transfer'), - ), ), ), ], - ), + ) ], ), ),