@tduncan / Cortana / commits / 776c844

Add splash bootstrap, remove sidebar theme toggle, fix TTS dialogs

abdulmominsakib committed May 16, 2026 at 23:49 UTC 776c844e136c3cbfdac0ee8c1a1bfa82781b5aa6
10 files changed +358 -127
android/.kotlin/sessions/kotlin-compiler-1529230861625166061.salive
lib/app.dart
-3
@@ -18,7 +18,6 @@ import 'features/onboarding/screens/onboarding_theme_screen.dart';
18 import 'features/personas/views/create_persona_screen.dart';
19 import 'features/personas/views/persona_list_screen.dart';
20 import 'features/servers/data/models/server.dart';
21 -import 'features/servers/providers/server_providers.dart';
21 import 'features/servers/views/add_server_screen.dart';
22 import 'features/servers/views/server_list_screen.dart';
23 import 'features/tts/views/tts_model_manager_screen.dart';
@@ -154,8 +153,6 @@ class App extends ConsumerWidget {
153 final router = ref.watch(routerProvider);
154 final appThemeType = ref.watch(themeModeProvider);
155
157 - ref.watch(ensureOnDeviceServerProvider);
158 -
156 ThemeData theme = AppTheme.lightTheme;
157 ThemeData darkTheme = AppTheme.darkTheme;
158 ThemeMode themeMode = ThemeMode.system;
lib/bootstrap/bootstrap_host.dart new
+116
@@ -0,0 +1,116 @@
1 +import 'package:flutter/material.dart';
2 +import 'package:flutter_riverpod/flutter_riverpod.dart';
3 +import 'package:shared_preferences/shared_preferences.dart';
4 +
5 +import '../app.dart';
6 +import '../core/providers/highlighter_provider.dart';
7 +import '../core/providers/storage_providers.dart';
8 +import '../core/storage/objectbox_store.dart';
9 +import '../features/on_device/providers/on_device_providers.dart';
10 +import '../core/models/enums.dart';
11 +import '../features/servers/data/models/server.dart';
12 +import '../features/servers/providers/server_providers.dart';
13 +import 'bootstrap_screen.dart';
14 +import 'bootstrap_state.dart';
15 +
16 +class BootstrapHost extends StatefulWidget {
17 + const BootstrapHost({super.key});
18 +
19 + @override
20 + State<BootstrapHost> createState() => _BootstrapHostState();
21 +}
22 +
23 +class _BootstrapHostState extends State<BootstrapHost> {
24 + BootstrapState _state = const BootstrapState();
25 + ProviderContainer? _container;
26 +
27 + @override
28 + void initState() {
29 + super.initState();
30 + _runBootstrap();
31 + }
32 +
33 + Future<void> _runBootstrap() async {
34 + _updateStage(BootstrapStage.initializing, 'Initializing...');
35 +
36 + try {
37 + final results = await Future.wait([
38 + initializeHighlighter(),
39 + SharedPreferences.getInstance(),
40 + ObjectBoxStore.create(),
41 + ]);
42 +
43 + final prefs = results[1] as SharedPreferences;
44 + final database = results[2] as ObjectBoxStore;
45 +
46 + _updateStage(BootstrapStage.preparingApp, 'Preparing app...');
47 +
48 + final container = ProviderContainer(
49 + overrides: [
50 + sharedPreferencesProvider.overrideWithValue(prefs),
51 + databaseProvider.overrideWithValue(database),
52 + ],
53 + );
54 +
55 + _updateStage(BootstrapStage.initializingServices, 'Initializing services...');
56 + await container.read(downloadNotificationServiceProvider).init();
57 +
58 + _updateStage(BootstrapStage.configuringServer, 'Configuring server...');
59 + final servers = await container.read(serversProvider.future);
60 + final hasOnDevice = servers.any((s) => s.type == ServerType.onDevice);
61 + if (!hasOnDevice) {
62 + final server = Server(
63 + id: 'on-device',
64 + name: 'On-Device',
65 + type: ServerType.onDevice,
66 + host: '',
67 + port: 0,
68 + isDefault: false,
69 + createdAt: DateTime.now(),
70 + lastConnectedAt: DateTime.now(),
71 + status: ConnectionStatus.connected,
72 + iconName: 'strokeRoundedSmartPhone01',
73 + );
74 + await container.read(serversProvider.notifier).addServer(server);
75 + }
76 +
77 + _container = container;
78 + _updateStage(BootstrapStage.done, 'Ready');
79 + } catch (e) {
80 + _state = BootstrapState(
81 + stage: BootstrapStage.error,
82 + statusMessage: 'Startup failed',
83 + error: e,
84 + );
85 + if (mounted) setState(() {});
86 + }
87 + }
88 +
89 + void _updateStage(BootstrapStage stage, String message) {
90 + if (!mounted) return;
91 + setState(() {
92 + _state = BootstrapState(stage: stage, statusMessage: message);
93 + });
94 + }
95 +
96 + @override
97 + void dispose() {
98 + _container?.dispose();
99 + super.dispose();
100 + }
101 +
102 + @override
103 + Widget build(BuildContext context) {
104 + if (_container != null) {
105 + return UncontrolledProviderScope(
106 + container: _container!,
107 + child: const App(),
108 + );
109 + }
110 +
111 + return BootstrapScreen(
112 + state: _state,
113 + onRetry: _state.stage == BootstrapStage.error ? _runBootstrap : null,
114 + );
115 + }
116 +}
lib/bootstrap/bootstrap_screen.dart new
+108
@@ -0,0 +1,108 @@
1 +import 'package:flutter/material.dart';
2 +import 'package:loading_animation_widget/loading_animation_widget.dart';
3 +import '../core/theme/colors.dart';
4 +import 'bootstrap_state.dart';
5 +
6 +class BootstrapScreen extends StatelessWidget {
7 + final BootstrapState state;
8 + final VoidCallback? onRetry;
9 +
10 + const BootstrapScreen({super.key, required this.state, this.onRetry});
11 +
12 + @override
13 + Widget build(BuildContext context) {
14 + final brightness =
15 + WidgetsBinding.instance.platformDispatcher.platformBrightness;
16 + final isDark = brightness == Brightness.dark;
17 +
18 + return Directionality(
19 + textDirection: TextDirection.ltr,
20 + child: Material(
21 + color: isDark ? AppColors.darkBackground : AppColors.lightBackground,
22 + child: SafeArea(
23 + child: Center(
24 + child: Padding(
25 + padding: const EdgeInsets.symmetric(horizontal: 32),
26 + child: Column(
27 + mainAxisSize: MainAxisSize.min,
28 + children: [
29 + ClipRRect(
30 + borderRadius: BorderRadius.circular(12),
31 + child: Image.asset(
32 + 'assets/images/logo.webp',
33 + width: 72,
34 + height: 72,
35 + ),
36 + ),
37 + const SizedBox(height: 24),
38 + Text(
39 + 'LocalMind',
40 + style: TextStyle(
41 + fontSize: 28,
42 + fontWeight: FontWeight.bold,
43 + color: isDark
44 + ? AppColors.darkPrimaryText
45 + : AppColors.lightPrimaryText,
46 + letterSpacing: 1,
47 + ),
48 + ),
49 + const SizedBox(height: 48),
50 + if (state.stage != BootstrapStage.error) ...[
51 + LoadingAnimationWidget.fourRotatingDots(
52 + size: 32,
53 + color: isDark
54 + ? AppColors.darkPrimaryText
55 + : AppColors.lightPrimaryText,
56 + ),
57 + const SizedBox(height: 24),
58 + Text(
59 + state.statusMessage,
60 + textAlign: TextAlign.center,
61 + style: TextStyle(
62 + fontSize: 14,
63 + color: isDark
64 + ? AppColors.darkMutedText
65 + : AppColors.lightMutedText,
66 + ),
67 + ),
68 + ] else ...[
69 + Icon(Icons.error_outline, size: 40, color: AppColors.error),
70 + const SizedBox(height: 16),
71 + Text(
72 + 'Something went wrong',
73 + style: TextStyle(
74 + fontSize: 16,
75 + fontWeight: FontWeight.w600,
76 + color: isDark
77 + ? AppColors.darkPrimaryText
78 + : AppColors.lightPrimaryText,
79 + ),
80 + ),
81 + const SizedBox(height: 8),
82 + Text(
83 + state.error?.toString() ?? 'Unknown error',
84 + textAlign: TextAlign.center,
85 + style: TextStyle(
86 + fontSize: 13,
87 + color: isDark
88 + ? AppColors.darkMutedText
89 + : AppColors.lightMutedText,
90 + ),
91 + ),
92 + const SizedBox(height: 24),
93 + if (onRetry != null)
94 + ElevatedButton.icon(
95 + onPressed: onRetry,
96 + icon: const Icon(Icons.refresh, size: 18),
97 + label: const Text('Retry'),
98 + ),
99 + ],
100 + ],
101 + ),
102 + ),
103 + ),
104 + ),
105 + ),
106 + );
107 + }
108 +}
lib/bootstrap/bootstrap_state.dart new
+22
@@ -0,0 +1,22 @@
1 +enum BootstrapStage {
2 + initializing,
3 + preparingApp,
4 + initializingServices,
5 + configuringServer,
6 + done,
7 + error,
8 +}
9 +
10 +class BootstrapState {
11 + final BootstrapStage stage;
12 + final String statusMessage;
13 + final Object? error;
14 + final double progress;
15 +
16 + const BootstrapState({
17 + this.stage = BootstrapStage.initializing,
18 + this.statusMessage = 'Initializing...',
19 + this.error,
20 + this.progress = 0.0,
21 + });
22 +}
lib/features/sidebar/sidebar_widget.dart
+1 -14
@@ -104,7 +104,7 @@ class SidebarWidget extends ConsumerWidget {
104 ),
105 DrawerNavItem(
106 iconData: HugeIcons.strokeRoundedVoice,
107 - label: 'TTS Models',
107 + label: 'Text To Speech',
108 isSelected: isTtsModels,
109 onTap: () {
110 if (Scaffold.maybeOf(context)?.isDrawerOpen ?? false) {
@@ -138,19 +138,6 @@ class SidebarWidget extends ConsumerWidget {
138 context.go(AppRoutes.settings);
139 },
140 ),
141 - DrawerNavItem(
142 - iconData: _getThemeIcon(themeMode),
143 - label: 'Appearance: ${_getThemeLabel(themeMode)}',
144 - isSelected: false,
145 - onTap: () {
146 - final nextMode =
147 - AppThemeType.values[(themeMode.index + 1) %
148 - AppThemeType.values.length];
149 - ref
150 - .read(themeModeProvider.notifier)
151 - .setThemeMode(nextMode);
152 - },
153 - ),
141 ],
142 ),
143 ),
lib/features/tts/views/tts_model_manager_screen.dart
+34 -36
@@ -22,7 +22,7 @@ class TtsModelManagerScreen extends ConsumerWidget {
22
23 return Scaffold(
24 drawer: const SidebarWidget(),
25 - appBar: AppBar(title: const Text('TTS Models')),
25 + appBar: AppBar(title: const Text('Text To Speech Models')),
26 body: ListView(
27 padding: const EdgeInsets.all(16),
28 children: [
@@ -203,32 +203,31 @@ class _KittenEngineCard extends ConsumerWidget {
203 WidgetRef ref,
204 KittenTtsModel model,
205 ) {
206 - showShadDialog(
206 + showDialog(
207 context: context,
208 - builder: (context) => ShadDialog(
208 + builder: (context) => AlertDialog(
209 title: const Text('Delete Model'),
210 - description: Text(
211 - 'Are you sure you want to delete ${model.displayName}? This will free up approximately ${_formatSize(model.totalSizeBytes)} of space.',
210 + content: Text(
211 + 'Are you sure you want to delete ${model.displayName}? This will '
212 + 'free up approximately ${_formatSize(model.totalSizeBytes)} of '
213 + 'space.\n\nYou can download this model again later if needed.',
214 ),
215 actions: [
214 - ShadButton.outline(
215 - child: const Text('Cancel'),
216 + TextButton(
217 onPressed: () => Navigator.of(context).pop(),
218 + child: const Text('Cancel'),
219 ),
218 - ShadButton.destructive(
219 - child: const Text('Delete'),
220 + TextButton(
221 onPressed: () {
222 ref
223 .read(ttsDownloadProgressProvider.notifier)
224 .deleteVariant(model.variant);
225 Navigator.of(context).pop();
226 },
227 + style: TextButton.styleFrom(foregroundColor: Colors.red),
228 + child: const Text('Delete'),
229 ),
230 ],
228 - child: const Padding(
229 - padding: EdgeInsets.symmetric(vertical: 20),
230 - child: Text('You can download this model again later if needed.'),
231 - ),
231 ),
232 );
233 }
@@ -364,17 +363,17 @@ class _PiperEngineCard extends ConsumerWidget {
363 Wrap(
364 spacing: 8,
365 runSpacing: 8,
367 - children: PiperTtsModelVariant.values
368 - .map(
369 - (variant) => _PiperVariantChip(
370 - variant: variant,
371 - voice: piperVoices.firstWhere(
372 - (voice) => voice.id == variant.id,
373 - orElse: () => selectedVoice,
374 - ),
375 - selected: selectedVariant == variant,
376 - installed: downloadedSet.contains(variant),
377 - onTap: () => ref
366 + children: PiperTtsModelVariant.values
367 + .map(
368 + (variant) => _PiperVariantChip(
369 + variant: variant,
370 + voice: piperVoices.firstWhere(
371 + (voice) => voice.id == variant.id,
372 + orElse: () => selectedVoice,
373 + ),
374 + selected: selectedVariant == variant,
375 + installed: downloadedSet.contains(variant),
376 + onTap: () => ref
377 .read(settingsProvider.notifier)
378 .setTtsVoiceId(variant.id),
379 ),
@@ -450,32 +449,31 @@ class _PiperEngineCard extends ConsumerWidget {
449 WidgetRef ref,
450 PiperTtsModelVariant variant,
451 ) {
453 - showShadDialog(
452 + showDialog(
453 context: context,
455 - builder: (context) => ShadDialog(
454 + builder: (context) => AlertDialog(
455 title: const Text('Delete Voice'),
457 - description: Text(
458 - 'Are you sure you want to delete ${variant.displayName}? This will free up approximately ${_formatSize(variant.totalSizeBytes)} of space.',
456 + content: Text(
457 + 'Are you sure you want to delete ${variant.displayName}? This will '
458 + 'free up approximately ${_formatSize(variant.totalSizeBytes)} of '
459 + 'space.\n\nYou can download this voice again later if needed.',
460 ),
461 actions: [
461 - ShadButton.outline(
462 - child: const Text('Cancel'),
462 + TextButton(
463 onPressed: () => Navigator.of(context).pop(),
464 + child: const Text('Cancel'),
465 ),
465 - ShadButton.destructive(
466 - child: const Text('Delete'),
466 + TextButton(
467 onPressed: () {
468 ref
469 .read(piperTtsDownloadProgressProvider.notifier)
470 .deleteVariant(variant);
471 Navigator.of(context).pop();
472 },
473 + style: TextButton.styleFrom(foregroundColor: Colors.red),
474 + child: const Text('Delete'),
475 ),
476 ],
475 - child: const Padding(
476 - padding: EdgeInsets.symmetric(vertical: 20),
477 - child: Text('You can download this voice again later if needed.'),
478 - ),
477 ),
478 );
479 }
lib/main.dart
+2 -24
@@ -1,30 +1,8 @@
1 import 'package:flutter/material.dart';
2 -import 'package:flutter_riverpod/flutter_riverpod.dart';
3 -import 'package:shared_preferences/shared_preferences.dart';
2
5 -import 'app.dart';
6 -import 'core/providers/highlighter_provider.dart';
7 -import 'core/providers/storage_providers.dart';
8 -import 'core/storage/objectbox_store.dart';
9 -import 'features/on_device/providers/on_device_providers.dart';
3 +import 'bootstrap/bootstrap_host.dart';
4
5 Future<void> main() async {
6 WidgetsFlutterBinding.ensureInitialized();
13 -
14 - await initializeHighlighter();
15 -
16 - final prefs = await SharedPreferences.getInstance();
17 - final database = await ObjectBoxStore.create();
18 -
19 - final container = ProviderContainer(
20 - overrides: [
21 - sharedPreferencesProvider.overrideWithValue(prefs),
22 - databaseProvider.overrideWithValue(database),
23 - ],
24 - );
25 -
26 - // Initialize services
27 - await container.read(downloadNotificationServiceProvider).init();
28 -
29 - runApp(UncontrolledProviderScope(container: container, child: const App()));
7 + runApp(const BootstrapHost());
8 }
pubspec.lock
+73 -49
@@ -117,18 +117,18 @@ packages:
117 dependency: transitive
118 description:
119 name: boxy
120 - sha256: "569373f23560f5a5dbe53c08a7463a698635e7ac72ba355ff4fa52516c0d2e32"
120 + sha256: "42ccafe13b2893878042acc5b7e2446025328e11a3197b0bb78db42ff76aa3f0"
121 url: "https://pub.dev"
122 source: hosted
123 - version: "2.2.2"
123 + version: "2.3.0"
124 build:
125 dependency: transitive
126 description:
127 name: build
128 - sha256: aadd943f4f8cc946882c954c187e6115a84c98c81ad1d9c6cbf0895a8c85da9c
128 + sha256: a156715e7cd728130c592f30552575908aae5b100005fbc1f0fb16b3c03a3d10
129 url: "https://pub.dev"
130 source: hosted
131 - version: "4.0.5"
131 + version: "4.0.6"
132 build_config:
133 dependency: transitive
134 description:
@@ -149,10 +149,10 @@ packages:
149 dependency: "direct dev"
150 description:
151 name: build_runner
152 - sha256: "521daf8d189deb79ba474e43a696b41c49fb3987818dbacf3308f1e03673a75e"
152 + sha256: "1523ce62448ebac2c15a8ba5fbad8acac169788658a7dd2a1c2d9c2a9318b9a6"
153 url: "https://pub.dev"
154 source: hosted
155 - version: "2.13.1"
155 + version: "2.15.0"
156 built_collection:
157 dependency: transitive
158 description:
@@ -165,10 +165,10 @@ packages:
165 dependency: transitive
166 description:
167 name: built_value
168 - sha256: "0730c18c770d05636a8f945c32a4d7d81cb6e0f0148c8db4ad12e7748f7e49af"
168 + sha256: "34e4067d30ce212937df995f03b69992eea683539ceeac7f679a1f1eba055b56"
169 url: "https://pub.dev"
170 source: hosted
171 - version: "8.12.5"
171 + version: "8.12.6"
172 change_app_package_name:
173 dependency: "direct dev"
174 description:
@@ -225,14 +225,6 @@ packages:
225 url: "https://pub.dev"
226 source: hosted
227 version: "1.0.0"
228 - code_builder:
229 - dependency: transitive
230 - description:
231 - name: code_builder
232 - sha256: "6a6cab2ba4680d6423f34a9b972a4c9a94ebe1b62ecec4e1a1f2cba91fd1319d"
233 - url: "https://pub.dev"
234 - source: hosted
235 - version: "4.11.1"
228 collection:
229 dependency: transitive
230 description:
@@ -535,10 +527,10 @@ packages:
527 dependency: transitive
528 description:
529 name: flutter_svg
538 - sha256: "1ded017b39c8e15c8948ea855070a5ff8ff8b3d5e83f3446e02d6bb12add7ad9"
530 + sha256: "35882981abcbfb8c15b286f0cd690ff25bac12d95eff3e25ee207f37d4c42e7f"
531 url: "https://pub.dev"
532 source: hosted
541 - version: "2.2.4"
533 + version: "2.3.0"
534 flutter_test:
535 dependency: "direct dev"
536 description: flutter
@@ -577,10 +569,10 @@ packages:
569 dependency: "direct main"
570 description:
571 name: go_router
580 - sha256: "7974313e217a7771557add6ff2238acb63f635317c35fa590d348fb238f00896"
572 + sha256: "92d8cee7c57dff0a6c409c05597b460002434eccf7424a712283225b3962d03f"
573 url: "https://pub.dev"
574 source: hosted
583 - version: "17.1.0"
575 + version: "17.2.3"
576 google_fonts:
577 dependency: "direct main"
578 description:
@@ -609,10 +601,10 @@ packages:
601 dependency: transitive
602 description:
603 name: hooks
612 - sha256: e79ed1e8e1929bc6ecb6ec85f0cb519c887aa5b423705ded0d0f2d9226def388
604 + sha256: "025f060e86d2d4c3c47b56e33caf7f93bf9283340f26d23424ebcfccf34f621e"
605 url: "https://pub.dev"
606 source: hosted
615 - version: "1.0.2"
607 + version: "1.0.3"
608 http:
609 dependency: transitive
610 description:
@@ -649,10 +641,10 @@ packages:
641 dependency: "direct main"
642 description:
643 name: hugeicons
652 - sha256: d19c0e2b57ccf455dd8ef08b84da40ae6dbba898c92960a0a0ada77df7865b8a
644 + sha256: "5a4bb3f3e0a34df5ab8c41f43eb8c63382af8b3dcb8d63e8231b3d4dda3433e5"
645 url: "https://pub.dev"
646 source: hosted
655 - version: "1.1.5"
647 + version: "1.1.7"
648 intl:
649 dependency: transitive
650 description:
@@ -669,6 +661,22 @@ packages:
661 url: "https://pub.dev"
662 source: hosted
663 version: "1.0.5"
664 + jni:
665 + dependency: transitive
666 + description:
667 + name: jni
668 + sha256: c2230682d5bc2362c1c9e8d3c7f406d9cbba23ab3f2e203a025dd47e0fb2e68f
669 + url: "https://pub.dev"
670 + source: hosted
671 + version: "1.0.0"
672 + jni_flutter:
673 + dependency: transitive
674 + description:
675 + name: jni_flutter
676 + sha256: "8b59e590786050b1cd866677dddaf76b1ade5e7bc751abe04b86e84d379d3ba6"
677 + url: "https://pub.dev"
678 + source: hosted
679 + version: "1.0.1"
680 js:
681 dependency: transitive
682 description:
@@ -681,10 +689,10 @@ packages:
689 dependency: transitive
690 description:
691 name: json_annotation
684 - sha256: cb09e7dac6210041fad964ed7fbee004f14258b4eca4040f72d1234062ace4c8
692 + sha256: "2a743920d81b7910627f68ee2c9ac1fc0bfee32b9fc3403587d7c6791ca12f80"
693 url: "https://pub.dev"
694 source: hosted
687 - version: "4.11.0"
695 + version: "4.12.0"
696 leak_tracker:
697 dependency: transitive
698 description:
@@ -717,6 +725,14 @@ packages:
725 url: "https://pub.dev"
726 source: hosted
727 version: "6.1.0"
728 + loading_animation_widget:
729 + dependency: "direct main"
730 + description:
731 + name: loading_animation_widget
732 + sha256: "9fe23381f3096e902f39e87e487648ff7f74925e86234353fa885bb9f6c98004"
733 + url: "https://pub.dev"
734 + source: hosted
735 + version: "1.3.0"
736 logger:
737 dependency: "direct main"
738 description:
@@ -737,10 +753,10 @@ packages:
753 dependency: transitive
754 description:
755 name: lucide_icons_flutter
740 - sha256: "39472ddc8c5fc586d06a619a3871817ea02dd17defd31e67dcfc9ec77658b2a1"
756 + sha256: "32d30fd06a84308204e0a2f7725b846a4b289d0ffefd880120989045c760cf94"
757 url: "https://pub.dev"
758 source: hosted
743 - version: "3.1.11"
759 + version: "3.1.14"
760 markdown:
761 dependency: transitive
762 description:
@@ -881,10 +897,10 @@ packages:
897 dependency: transitive
898 description:
899 name: path_provider_android
884 - sha256: "149441ca6e4f38193b2e004c0ca6376a3d11f51fa5a77552d8bd4d2b0c0912ba"
900 + sha256: "69cbd515a62b94d32a7944f086b2f82b4ac40a1d45bebfc00813a430ab2dabcd"
901 url: "https://pub.dev"
902 source: hosted
887 - version: "2.2.23"
903 + version: "2.3.1"
904 path_provider_foundation:
905 dependency: transitive
906 description:
@@ -981,6 +997,14 @@ packages:
997 url: "https://pub.dev"
998 source: hosted
999 version: "1.5.0"
1000 + record_use:
1001 + dependency: transitive
1002 + description:
1003 + name: record_use
1004 + sha256: "2551bd8eecfe95d14ae75f6021ad0248be5c27f138c2ec12fcb52b500b3ba1ed"
1005 + url: "https://pub.dev"
1006 + source: hosted
1007 + version: "0.6.0"
1008 riverpod:
1009 dependency: transitive
1010 description:
@@ -1001,10 +1025,10 @@ packages:
1025 dependency: "direct main"
1026 description:
1027 name: shadcn_ui
1004 - sha256: "342da1212a10d662a8a1e7c99a09b2c806303be24f06a7a4921159a130b6d06d"
1028 + sha256: "6c06f2bcebd8734b9ed0bf3f63ef5c71981573d5664923589b0302f8280e7eaf"
1029 url: "https://pub.dev"
1030 source: hosted
1007 - version: "0.53.3"
1031 + version: "0.53.6"
1032 shared_preferences:
1033 dependency: "direct main"
1034 description:
@@ -1190,10 +1214,10 @@ packages:
1214 dependency: transitive
1215 description:
1216 name: source_gen
1193 - sha256: "732792cfd197d2161a65bb029606a46e0a18ff30ef9e141a7a82172b05ea8ecd"
1217 + sha256: ec37cc0e6694374cbef59ed79685572c870a54ede6fa30a3e420feb3adffea02
1218 url: "https://pub.dev"
1219 source: hosted
1196 - version: "4.2.2"
1220 + version: "4.2.3"
1221 source_map_stack_trace:
1222 dependency: transitive
1223 description:
@@ -1327,10 +1351,10 @@ packages:
1351 dependency: transitive
1352 description:
1353 name: two_dimensional_scrollables
1330 - sha256: "45f77f28f3f084ac3c79f74b075c4d719937a3972e71191efc533d6f9487c045"
1354 + sha256: "4f25bd42783626c5f2810333418727455397195acb61e53710e638a6a98e0e5e"
1355 url: "https://pub.dev"
1356 source: hosted
1333 - version: "0.4.1"
1357 + version: "0.5.2"
1358 typed_data:
1359 dependency: transitive
1360 description:
@@ -1343,10 +1367,10 @@ packages:
1367 dependency: transitive
1368 description:
1369 name: universal_image
1346 - sha256: ef47a4a002158cf0b36ed3b7605af132d2476cc42703e41b8067d3603705c40d
1370 + sha256: "2eae13df84a47960cc4148fec88f09031ea64cbf667b4131ff2c907dd7b7c6d1"
1371 url: "https://pub.dev"
1372 source: hosted
1349 - version: "1.0.11"
1373 + version: "1.0.12"
1374 url_launcher:
1375 dependency: "direct main"
1376 description:
@@ -1399,10 +1423,10 @@ packages:
1423 dependency: transitive
1424 description:
1425 name: url_launcher_web
1402 - sha256: d0412fcf4c6b31ecfdb7762359b7206ffba3bbffd396c6d9f9c4616ece476c1f
1426 + sha256: "85c81589622fbc87c1c683aaea164d3604a7777495a79d91e39ffcdec39ddb34"
1427 url: "https://pub.dev"
1428 source: hosted
1405 - version: "2.4.2"
1429 + version: "2.4.3"
1430 url_launcher_windows:
1431 dependency: transitive
1432 description:
@@ -1423,10 +1447,10 @@ packages:
1447 dependency: transitive
1448 description:
1449 name: vector_graphics
1426 - sha256: "7076216a10d5c390315fbe536a30f1254c341e7543e6c4c8a815e591307772b1"
1450 + sha256: "4d35a36400983c3457c289d4d553b5308f506ea84f7e51c7a564651b5525209a"
1451 url: "https://pub.dev"
1452 source: hosted
1429 - version: "1.1.20"
1453 + version: "1.2.1"
1454 vector_graphics_codec:
1455 dependency: transitive
1456 description:
@@ -1439,10 +1463,10 @@ packages:
1463 dependency: transitive
1464 description:
1465 name: vector_graphics_compiler
1442 - sha256: "5a88dd14c0954a5398af544651c7fb51b457a2a556949bfb25369b210ef73a74"
1466 + sha256: "98e7e94de127b46a86ef46197fff84ff99f3d3b80a708390d717ad731efef598"
1467 url: "https://pub.dev"
1468 source: hosted
1445 - version: "1.2.0"
1469 + version: "1.2.2"
1470 vector_math:
1471 dependency: transitive
1472 description:
@@ -1455,10 +1479,10 @@ packages:
1479 dependency: transitive
1480 description:
1481 name: vm_service
1458 - sha256: "45caa6c5917fa127b5dbcfbd1fa60b14e583afdc08bfc96dda38886ca252eb60"
1482 + sha256: "0016aef94fc66495ac78af5859181e3f3bf2026bd8eecc72b9565601e19ab360"
1483 url: "https://pub.dev"
1484 source: hosted
1461 - version: "15.0.2"
1485 + version: "15.2.0"
1486 wakelock_plus:
1487 dependency: "direct main"
1488 description:
@@ -1471,10 +1495,10 @@ packages:
1495 dependency: transitive
1496 description:
1497 name: wakelock_plus_platform_interface
1474 - sha256: "14b2e5b9e35c2631e656913c47adecdd71633ae92896a27a64c8f1fcfabc21cc"
1498 + sha256: b13f99e992e7ae6a152e16c5559d3c07ff445b13330192662494e614ca3e7d7b
1499 url: "https://pub.dev"
1500 source: hosted
1477 - version: "1.5.0"
1501 + version: "1.5.1"
1502 watcher:
1503 dependency: transitive
1504 description:
@@ -1557,4 +1581,4 @@ packages:
1581 version: "3.1.3"
1582 sdks:
1583 dart: ">=3.11.0 <4.0.0"
1560 - flutter: ">=3.41.0"
1584 + flutter: ">=3.38.4"
pubspec.yaml
+2 -1
@@ -16,7 +16,7 @@ publish_to: "none" # Remove this line if you wish to publish to pub.dev
16 # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
17 # In Windows, build-name is used as the major, minor, and patch parts
18 # of the product and file versions while build-number is used as the build suffix.
19 -version: 1.2.3+22
19 +version: 1.2.4+23
20
21 environment:
22 sdk: ^3.11.0
@@ -63,6 +63,7 @@ dependencies:
63 device_info_plus: ^12.4.0
64 sherpa_onnx: ^1.13.2
65 archive: ^4.0.2
66 + loading_animation_widget: ^1.3.0
67
68 dev_dependencies:
69 flutter_test: