Skip to content

Commit 51ba22c

Browse files
fix: made the feature persisted
1 parent 7de40ad commit 51ba22c

File tree

6 files changed

+251
-174
lines changed

6 files changed

+251
-174
lines changed

lib/main.dart

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,9 @@ void main() {
2424
providers: [
2525
ChangeNotifierProvider<InlineImageProvider>(
2626
create: (context) => getIt<InlineImageProvider>()),
27-
ChangeNotifierProvider(create: (_) => BadgeScanProvider()),
27+
ChangeNotifierProvider<BadgeScanProvider>(
28+
create: (_) => getIt<BadgeScanProvider>(),
29+
),
2830
],
2931
child: const MyApp(),
3032
));

lib/providers/BadgeScanProvider.dart

Lines changed: 44 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,78 @@
11
import 'package:flutter/material.dart';
2+
import 'package:shared_preferences/shared_preferences.dart';
23

34
enum BadgeScanMode { any, specific }
45

56
class BadgeScanProvider with ChangeNotifier {
67
BadgeScanMode _mode = BadgeScanMode.any;
78
List<String> _badgeNames = ['LSLED', 'VBLAB'];
9+
bool _isLoaded = false;
810

911
BadgeScanMode get mode => _mode;
1012
List<String> get badgeNames => List.unmodifiable(_badgeNames);
13+
bool get isLoaded => _isLoaded;
1114

15+
BadgeScanProvider() {
16+
_loadFromPrefs(); // Load persisted values in background
17+
}
18+
19+
// --- Persistence helpers ---
20+
Future<void> _loadFromPrefs() async {
21+
final prefs = await SharedPreferences.getInstance();
22+
23+
// Load scan mode
24+
final modeIndex = prefs.getInt('badge_scan_mode');
25+
if (modeIndex != null) {
26+
_mode = BadgeScanMode.values[modeIndex];
27+
}
28+
29+
// Load badge names
30+
final storedNames = prefs.getStringList('badge_names');
31+
if (storedNames != null && storedNames.isNotEmpty) {
32+
_badgeNames = storedNames;
33+
}
34+
35+
_isLoaded = true;
36+
notifyListeners(); // Notify UI that values are loaded
37+
}
38+
39+
Future<void> _saveToPrefs() async {
40+
final prefs = await SharedPreferences.getInstance();
41+
await prefs.setInt('badge_scan_mode', _mode.index);
42+
await prefs.setStringList('badge_names', _badgeNames);
43+
}
44+
45+
// --- Public methods to update values ---
1246
void setMode(BadgeScanMode mode) {
1347
_mode = mode;
48+
_saveToPrefs();
1449
notifyListeners();
1550
}
1651

1752
void setBadgeNames(List<String> names) {
1853
_badgeNames = names.where((name) => name.trim().isNotEmpty).toList();
54+
_saveToPrefs();
1955
notifyListeners();
2056
}
2157

2258
void addBadgeName(String name) {
23-
_badgeNames.add(name);
59+
if (name.trim().isEmpty) return;
60+
_badgeNames.add(name.trim());
61+
_saveToPrefs();
2462
notifyListeners();
2563
}
2664

2765
void removeBadgeNameAt(int index) {
66+
if (index < 0 || index >= _badgeNames.length) return;
2867
_badgeNames.removeAt(index);
68+
_saveToPrefs();
2969
notifyListeners();
3070
}
3171

3272
void updateBadgeName(int index, String newName) {
33-
_badgeNames[index] = newName;
73+
if (index < 0 || index >= _badgeNames.length) return;
74+
_badgeNames[index] = newName.trim();
75+
_saveToPrefs();
3476
notifyListeners();
3577
}
3678
}

lib/providers/getitlocator.dart

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
1+
import 'package:badgemagic/providers/BadgeScanProvider.dart';
12
import 'package:badgemagic/providers/imageprovider.dart';
23
import 'package:get_it/get_it.dart';
34

45
final GetIt getIt = GetIt.instance;
56

67
void setupLocator() {
78
getIt.registerLazySingleton<InlineImageProvider>(() => InlineImageProvider());
9+
getIt.registerLazySingleton<BadgeScanProvider>(() => BadgeScanProvider());
810
}

lib/view/badgeScanSettingsWidget.dart

Lines changed: 88 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@ import 'package:flutter/material.dart';
33
import 'package:provider/provider.dart';
44

55
class BadgeScanSettingsWidget extends StatefulWidget {
6-
final Function(BadgeScanMode mode, List<String> names) onSave;
6+
final Function(BadgeScanMode mode, List<String> names)? onSave;
77

8-
const BadgeScanSettingsWidget({super.key, required this.onSave});
8+
const BadgeScanSettingsWidget({super.key, this.onSave});
99

1010
@override
1111
State<BadgeScanSettingsWidget> createState() =>
@@ -21,9 +21,6 @@ class _BadgeScanSettingsWidgetState extends State<BadgeScanSettingsWidget> {
2121
super.initState();
2222
final provider = Provider.of<BadgeScanProvider>(context, listen: false);
2323
_mode = provider.mode;
24-
for (var name in provider.badgeNames) {
25-
_controllers.add(TextEditingController(text: name));
26-
}
2724
}
2825

2926
void _addBadgeName() {
@@ -38,7 +35,7 @@ class _BadgeScanSettingsWidgetState extends State<BadgeScanSettingsWidget> {
3835
});
3936
}
4037

41-
void _onSave() {
38+
Future<void> _onSave() async {
4239
final updatedNames = _controllers
4340
.map((c) => c.text.trim())
4441
.where((name) => name.isNotEmpty)
@@ -52,82 +49,98 @@ class _BadgeScanSettingsWidgetState extends State<BadgeScanSettingsWidget> {
5249
const SnackBar(content: Text('Scan settings saved successfully')),
5350
);
5451

55-
widget.onSave(_mode, updatedNames);
56-
Navigator.pop(context);
57-
}
58-
59-
@override
60-
void dispose() {
61-
for (var c in _controllers) {
62-
c.dispose();
63-
}
64-
super.dispose();
52+
widget.onSave?.call(_mode, updatedNames);
53+
if (mounted) Navigator.pop(context);
6554
}
6655

6756
@override
6857
Widget build(BuildContext context) {
69-
return Scaffold(
70-
appBar: AppBar(
71-
title: const Text('Badge Scan Settings'),
72-
actions: [
73-
IconButton(
74-
icon: const Icon(Icons.save),
75-
onPressed: _onSave,
76-
),
77-
],
78-
),
79-
body: Column(
80-
children: [
81-
RadioListTile<BadgeScanMode>(
82-
title: const Text('Connect to any badge'),
83-
value: BadgeScanMode.any,
84-
groupValue: _mode,
85-
onChanged: (val) => setState(() => _mode = val!),
86-
),
87-
RadioListTile<BadgeScanMode>(
88-
title: const Text('Connect to badges with the following names'),
89-
value: BadgeScanMode.specific,
90-
groupValue: _mode,
91-
onChanged: (val) => setState(() => _mode = val!),
58+
return Consumer<BadgeScanProvider>(
59+
builder: (context, provider, child) {
60+
if (!provider.isLoaded) {
61+
return const Scaffold(
62+
body: Center(child: CircularProgressIndicator()),
63+
);
64+
}
65+
66+
if (_controllers.isEmpty) {
67+
// Initialize controllers only after provider is loaded
68+
for (var name in provider.badgeNames) {
69+
_controllers.add(TextEditingController(text: name));
70+
}
71+
}
72+
73+
return Scaffold(
74+
appBar: AppBar(
75+
title: const Text('Badge Scan Settings'),
76+
actions: [
77+
IconButton(
78+
icon: const Icon(Icons.save),
79+
onPressed: _onSave,
80+
),
81+
],
9282
),
93-
if (_mode == BadgeScanMode.specific)
94-
Expanded(
95-
child: ListView.builder(
96-
itemCount: _controllers.length,
97-
itemBuilder: (context, index) {
98-
return Row(
99-
children: [
100-
Expanded(
101-
child: Padding(
102-
padding: const EdgeInsets.symmetric(horizontal: 12.0),
103-
child: TextField(
104-
controller: _controllers[index],
105-
decoration: const InputDecoration(
106-
labelText: 'Badge Name',
107-
),
108-
),
109-
),
110-
),
111-
IconButton(
112-
icon: const Icon(Icons.remove_circle_outline),
113-
onPressed: () => _removeBadgeName(index),
114-
),
115-
],
116-
);
117-
},
83+
body: Column(
84+
children: [
85+
RadioListTile<BadgeScanMode>(
86+
title: const Text('Connect to any badge'),
87+
value: BadgeScanMode.any,
88+
groupValue: _mode,
89+
onChanged: (val) => setState(() => _mode = val!),
11890
),
119-
),
120-
if (_mode == BadgeScanMode.specific)
121-
Padding(
122-
padding: const EdgeInsets.all(12.0),
123-
child: ElevatedButton.icon(
124-
onPressed: _addBadgeName,
125-
icon: const Icon(Icons.add),
126-
label: const Text("Add more"),
91+
RadioListTile<BadgeScanMode>(
92+
title: const Text('Connect to badges with the following names'),
93+
value: BadgeScanMode.specific,
94+
groupValue: _mode,
95+
onChanged: (val) => setState(() => _mode = val!),
12796
),
128-
),
129-
],
130-
),
97+
if (_mode == BadgeScanMode.specific)
98+
Expanded(
99+
child: ListView.builder(
100+
itemCount: _controllers.length,
101+
itemBuilder: (context, index) {
102+
return Row(
103+
children: [
104+
Expanded(
105+
child: Padding(
106+
padding:
107+
const EdgeInsets.symmetric(horizontal: 12.0),
108+
child: TextField(
109+
controller: _controllers[index],
110+
decoration: const InputDecoration(
111+
labelText: 'Badge Name',
112+
),
113+
),
114+
),
115+
),
116+
IconButton(
117+
icon: const Icon(Icons.remove_circle_outline),
118+
onPressed: () => _removeBadgeName(index),
119+
),
120+
],
121+
);
122+
},
123+
),
124+
),
125+
if (_mode == BadgeScanMode.specific)
126+
Padding(
127+
padding: const EdgeInsets.all(12.0),
128+
child: ElevatedButton.icon(
129+
onPressed: _addBadgeName,
130+
icon: const Icon(Icons.add),
131+
label: const Text("Add more"),
132+
),
133+
),
134+
],
135+
),
136+
);
137+
},
131138
);
132139
}
140+
141+
@override
142+
void dispose() {
143+
for (var c in _controllers) c.dispose();
144+
super.dispose();
145+
}
133146
}

0 commit comments

Comments
 (0)