diff --git a/analysis_options.yaml b/analysis_options.yaml index 0d29021..2ea7792 100644 --- a/analysis_options.yaml +++ b/analysis_options.yaml @@ -23,6 +23,9 @@ linter: rules: # avoid_print: false # Uncomment to disable the `avoid_print` rule # prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule + # ?'key': value applies ? to the key (never null for string literals); + # the if (x != null) form is correct for nullable-value map entries. + use_null_aware_elements: false # Additional information about this file can be found at # https://dart.dev/guides/language/analysis-options diff --git a/lib/app.dart b/lib/app.dart index 8da63d7..963b26c 100644 --- a/lib/app.dart +++ b/lib/app.dart @@ -283,7 +283,13 @@ class _ShellState extends ConsumerState<_Shell> { body: Column( children: [ const _QuickCaptureBar(), - Expanded(child: child), + Expanded( + child: MediaQuery.removePadding( + context: context, + removeTop: true, + child: child, + ), + ), ], ), bottomNavigationBar: NavigationBar( diff --git a/lib/data/api/notes_api.dart b/lib/data/api/notes_api.dart index 139eb0f..048cdf7 100644 --- a/lib/data/api/notes_api.dart +++ b/lib/data/api/notes_api.dart @@ -38,7 +38,7 @@ class NotesApi { 'title': title, 'body': body, 'tags': tags, - ?'project_id': projectId, + if (projectId != null) 'project_id': projectId, }); return Note.fromJson(response.data as Map); } on DioException catch (e) { @@ -59,7 +59,7 @@ class NotesApi { 'title': title, 'body': body, 'tags': tags, - if (clearProject) 'project_id': null else ?'project_id': projectId, + if (clearProject) 'project_id': null else if (projectId != null) 'project_id': projectId, }); return Note.fromJson(response.data as Map); } on DioException catch (e) { diff --git a/lib/data/api/projects_api.dart b/lib/data/api/projects_api.dart index 6e7a08b..c28dbd4 100644 --- a/lib/data/api/projects_api.dart +++ b/lib/data/api/projects_api.dart @@ -44,7 +44,7 @@ class ProjectsApi { if (description != null && description.isNotEmpty) 'description': description, if (goal != null && goal.isNotEmpty) 'goal': goal, - ?'color': color, + if (color != null) 'color': color, }); return Project.fromJson(response.data as Map); } on DioException catch (e) { diff --git a/lib/data/api/tasks_api.dart b/lib/data/api/tasks_api.dart index 463202c..bb098b8 100644 --- a/lib/data/api/tasks_api.dart +++ b/lib/data/api/tasks_api.dart @@ -43,8 +43,8 @@ class TasksApi { 'status': status.value, 'priority': priority.value, 'due_date': dueDate?.toIso8601String(), - ?'project_id': projectId, - ?'parent_id': parentId, + if (projectId != null) 'project_id': projectId, + if (parentId != null) 'parent_id': parentId, }); return Task.fromJson(response.data as Map); } on DioException catch (e) { diff --git a/lib/providers/auth_provider.dart b/lib/providers/auth_provider.dart index 6cf1a0f..fe82d88 100644 --- a/lib/providers/auth_provider.dart +++ b/lib/providers/auth_provider.dart @@ -4,18 +4,15 @@ import 'api_client_provider.dart'; enum AuthStatus { unknown, authenticated, unauthenticated } -final authProvider = StateNotifierProvider((ref) { - return AuthNotifier(ref); -}); +final authProvider = NotifierProvider(AuthNotifier.new); -class AuthNotifier extends StateNotifier { - final Ref _ref; - - AuthNotifier(this._ref) : super(AuthStatus.unknown); +class AuthNotifier extends Notifier { + @override + AuthStatus build() => AuthStatus.unknown; Future verify() async { try { - final repo = _ref.read(authRepositoryProvider); + final repo = ref.read(authRepositoryProvider); final ok = await repo.verify(); state = ok ? AuthStatus.authenticated : AuthStatus.unauthenticated; } catch (_) { @@ -24,14 +21,14 @@ class AuthNotifier extends StateNotifier { } Future login(String username, String password) async { - final repo = _ref.read(authRepositoryProvider); + final repo = ref.read(authRepositoryProvider); await repo.login(username, password); state = AuthStatus.authenticated; } Future logout() async { try { - final repo = _ref.read(authRepositoryProvider); + final repo = ref.read(authRepositoryProvider); await repo.logout(); } finally { state = AuthStatus.unauthenticated; diff --git a/lib/providers/briefing_provider.dart b/lib/providers/briefing_provider.dart index 3597552..40786f1 100644 --- a/lib/providers/briefing_provider.dart +++ b/lib/providers/briefing_provider.dart @@ -5,7 +5,13 @@ import '../data/models/message.dart'; import 'api_client_provider.dart'; /// Drives the loading indicator in BriefingScreen's reply area. -final isBriefingStreamingProvider = StateProvider((ref) => false); +final isBriefingStreamingProvider = + NotifierProvider<_BoolNotifier, bool>(_BoolNotifier.new); + +class _BoolNotifier extends Notifier { + @override + bool build() => false; +} final briefingProvider = AsyncNotifierProvider( @@ -32,7 +38,7 @@ class BriefingNotifier extends AsyncNotifier { /// 3. SSE stream (best-effort) /// 4. Poll until complete Future sendReply(String content) async { - final conv = state.valueOrNull; + final conv = state.value; if (conv == null) return; final convId = conv.id; final chatApi = ref.read(chatApiProvider); @@ -65,7 +71,7 @@ class BriefingNotifier extends AsyncNotifier { try { await for (final chunk in chatApi.streamGeneration(convId)) { streamedContent = true; - final current = state.valueOrNull; + final current = state.value; if (current == null) break; final msgs = current.messages; if (msgs.isEmpty) continue; @@ -88,7 +94,7 @@ class BriefingNotifier extends AsyncNotifier { final hasContent = fresh.any( (m) => m.role == MessageRole.assistant && m.content.isNotEmpty, ); - final current = state.valueOrNull; + final current = state.value; if (current != null && (!streamedContent || done || hasContent)) { state = AsyncData(current.copyWith(messages: fresh)); } @@ -96,7 +102,7 @@ class BriefingNotifier extends AsyncNotifier { } } catch (_) { // Clear the generating placeholder so UI doesn't spin forever. - final current = state.valueOrNull; + final current = state.value; if (current != null) { final msgs = current.messages; if (msgs.isNotEmpty && msgs.last.status == 'generating') { diff --git a/lib/providers/capture_queue_provider.dart b/lib/providers/capture_queue_provider.dart index 89f2bcb..2805ac7 100644 --- a/lib/providers/capture_queue_provider.dart +++ b/lib/providers/capture_queue_provider.dart @@ -4,16 +4,20 @@ import 'package:shared_preferences/shared_preferences.dart'; import 'settings_provider.dart'; final captureQueueProvider = - StateNotifierProvider>( - (ref) => CaptureQueueNotifier(ref.watch(sharedPreferencesProvider)), + NotifierProvider>( + CaptureQueueNotifier.new, ); -class CaptureQueueNotifier extends StateNotifier> { +class CaptureQueueNotifier extends Notifier> { static const _key = 'capture_queue'; - final SharedPreferences _prefs; - CaptureQueueNotifier(this._prefs) - : super(_prefs.getStringList(_key) ?? []); + SharedPreferences get _prefs => ref.read(sharedPreferencesProvider); + + @override + List build() { + final prefs = ref.watch(sharedPreferencesProvider); + return prefs.getStringList(_key) ?? []; + } Future enqueue(String text) async { final updated = [...state, text]; diff --git a/lib/providers/capture_work_queue_provider.dart b/lib/providers/capture_work_queue_provider.dart index 3c83ed8..afa0f5a 100644 --- a/lib/providers/capture_work_queue_provider.dart +++ b/lib/providers/capture_work_queue_provider.dart @@ -15,20 +15,27 @@ class CaptureResult { /// The most recent capture result. UI watches this to show snackbars. /// Reset to null by the notifier before each new item so listeners always fire. -final captureResultProvider = StateProvider((_) => null); +final captureResultProvider = + NotifierProvider<_CaptureResultNotifier, CaptureResult?>( + _CaptureResultNotifier.new); + +class _CaptureResultNotifier extends Notifier { + @override + CaptureResult? build() => null; +} /// In-memory sequential work queue for quick captures. /// Separate from [captureQueueProvider] (which is the offline persistence queue). final captureWorkQueueProvider = - StateNotifierProvider>( - (ref) => CaptureWorkQueueNotifier(ref), + NotifierProvider>( + CaptureWorkQueueNotifier.new, ); -class CaptureWorkQueueNotifier extends StateNotifier> { - final Ref _ref; +class CaptureWorkQueueNotifier extends Notifier> { bool _running = false; - CaptureWorkQueueNotifier(this._ref) : super([]); + @override + List build() => []; /// Add text to the queue and start the drain loop if not already running. void enqueue(String text) { @@ -43,9 +50,9 @@ class CaptureWorkQueueNotifier extends StateNotifier> { while (state.isNotEmpty) { final text = state.first; // Signal "no result yet" so the same result value can re-trigger watch. - _ref.read(captureResultProvider.notifier).state = null; + ref.read(captureResultProvider.notifier).state = null; try { - final api = _ref.read(quickCaptureApiProvider); + final api = ref.read(quickCaptureApiProvider); final result = await api.capture(text); // Dequeue on success. @@ -54,32 +61,32 @@ class CaptureWorkQueueNotifier extends StateNotifier> { // Invalidate content providers so lists refresh. switch (result.type) { case 'note': - _ref.invalidate(notesProvider); + ref.invalidate(notesProvider); case 'task': case 'todo': - _ref.invalidate(tasksProvider); + ref.invalidate(tasksProvider); } // Publish result for snackbar. final msg = result.message.isNotEmpty ? result.message : '${_typeLabel(result.type)} created: ${result.title}'; - _ref.read(captureResultProvider.notifier).state = CaptureResult(msg); + ref.read(captureResultProvider.notifier).state = CaptureResult(msg); } on NetworkException catch (_) { // Persist to offline queue and stop draining — still offline. - await _ref.read(captureQueueProvider.notifier).enqueue(text); + await ref.read(captureQueueProvider.notifier).enqueue(text); state = state.length > 1 ? state.sublist(1) : []; - _ref.read(captureResultProvider.notifier).state = CaptureResult( + ref.read(captureResultProvider.notifier).state = CaptureResult( "You're offline — capture saved and will retry automatically.", ); break; } on AppException catch (e) { state = state.length > 1 ? state.sublist(1) : []; - _ref.read(captureResultProvider.notifier).state = + ref.read(captureResultProvider.notifier).state = CaptureResult(e.message, isError: true); } catch (_) { state = state.length > 1 ? state.sublist(1) : []; - _ref.read(captureResultProvider.notifier).state = + ref.read(captureResultProvider.notifier).state = CaptureResult('Capture failed. Please try again.', isError: true); } } diff --git a/lib/providers/chat_provider.dart b/lib/providers/chat_provider.dart index 50fa882..b52ba69 100644 --- a/lib/providers/chat_provider.dart +++ b/lib/providers/chat_provider.dart @@ -4,8 +4,19 @@ import '../data/models/conversation.dart'; import '../data/models/message.dart'; import 'api_client_provider.dart'; -// Separate StateProvider so UI re-builds immediately when streaming starts/stops. -final isStreamingProvider = StateProvider.family((ref, _) => false); +// Separate NotifierProvider.family so UI re-builds immediately when streaming starts/stops. +final isStreamingProvider = + NotifierProvider.family<_IsStreamingNotifier, bool, int>( + (convId) => _IsStreamingNotifier(convId), +); + +class _IsStreamingNotifier extends Notifier { + // ignore: avoid_unused_constructor_parameters + _IsStreamingNotifier(int convId); + + @override + bool build() => false; +} final conversationsProvider = AsyncNotifierProvider>( @@ -20,14 +31,14 @@ class ConversationsNotifier extends AsyncNotifier> { Future create(String title) async { final conv = await ref.read(chatRepositoryProvider).createConversation(title); - state = AsyncData([conv, ...state.valueOrNull ?? []]); + state = AsyncData([conv, ...state.value ?? []]); return conv; } Future delete(int id) async { await ref.read(chatRepositoryProvider).deleteConversation(id); state = AsyncData([ - for (final c in state.valueOrNull ?? []) + for (final c in state.value ?? []) if (c.id != id) c, ]); } @@ -35,7 +46,7 @@ class ConversationsNotifier extends AsyncNotifier> { // Called after a message is sent to patch the server-generated title // in-place without triggering a full reload or loading state. void patchConversation(Conversation updated) { - final list = state.valueOrNull; + final list = state.value; if (list == null) return; state = AsyncData([ for (final c in list) @@ -44,21 +55,26 @@ class ConversationsNotifier extends AsyncNotifier> { } } -final messagesProvider = AsyncNotifierProvider.family, int>(MessagesNotifier.new); +final messagesProvider = + AsyncNotifierProvider.family, int>( + (convId) => MessagesNotifier(convId), +); + +class MessagesNotifier extends AsyncNotifier> { + final int _convId; + MessagesNotifier(this._convId); -class MessagesNotifier extends FamilyAsyncNotifier, int> { @override - Future> build(int arg) async { + Future> build() async { final (_, messages) = - await ref.watch(chatRepositoryProvider).getMessages(arg); + await ref.watch(chatRepositoryProvider).getMessages(_convId); return messages; } Future sendMessage(String content) async { - final convId = arg; + final convId = _convId; final repo = ref.read(chatRepositoryProvider); - final previousMessages = state.valueOrNull ?? []; + final previousMessages = state.value ?? []; // Optimistic UI: show the user message + assistant placeholder immediately. final userMsg = Message( @@ -132,7 +148,7 @@ class MessagesNotifier extends FamilyAsyncNotifier, int> { } catch (_) { // Polling failed entirely — clear the generating placeholder so the UI // doesn't spin forever. - final msgs = state.valueOrNull; + final msgs = state.value; if (msgs != null && msgs.isNotEmpty && msgs.last.status == 'generating') { state = AsyncData([ ...msgs.sublist(0, msgs.length - 1), diff --git a/lib/providers/notes_provider.dart b/lib/providers/notes_provider.dart index 532f241..fcbaa14 100644 --- a/lib/providers/notes_provider.dart +++ b/lib/providers/notes_provider.dart @@ -21,7 +21,7 @@ class NotesNotifier extends AsyncNotifier> { final note = await ref .read(notesRepositoryProvider) .create(title, body, tags: tags, projectId: projectId); - state = AsyncData([...state.valueOrNull ?? [], note]); + state = AsyncData([...state.value ?? [], note]); return note; } @@ -42,7 +42,7 @@ class NotesNotifier extends AsyncNotifier> { clearProject: clearProject, ); state = AsyncData([ - for (final n in state.valueOrNull ?? []) + for (final n in state.value ?? []) if (n.id == id) updated else n, ]); return updated; @@ -51,7 +51,7 @@ class NotesNotifier extends AsyncNotifier> { Future delete(int id) async { await ref.read(notesRepositoryProvider).delete(id); state = AsyncData([ - for (final n in state.valueOrNull ?? []) + for (final n in state.value ?? []) if (n.id != id) n, ]); } diff --git a/lib/providers/projects_provider.dart b/lib/providers/projects_provider.dart index eac052b..5c9d940 100644 --- a/lib/providers/projects_provider.dart +++ b/lib/providers/projects_provider.dart @@ -25,7 +25,7 @@ class ProjectsNotifier extends AsyncNotifier> { goal: goal, color: color, ); - state = AsyncData([...state.valueOrNull ?? [], project]); + state = AsyncData([...state.value ?? [], project]); return project; } @@ -33,7 +33,7 @@ class ProjectsNotifier extends AsyncNotifier> { final updated = await ref.read(projectsRepositoryProvider).update(id, fields); state = AsyncData([ - for (final p in state.valueOrNull ?? []) + for (final p in state.value ?? []) if (p.id == id) updated else p, ]); return updated; @@ -42,7 +42,7 @@ class ProjectsNotifier extends AsyncNotifier> { Future delete(int id) async { await ref.read(projectsRepositoryProvider).delete(id); state = AsyncData([ - for (final p in state.valueOrNull ?? []) + for (final p in state.value ?? []) if (p.id != id) p, ]); } diff --git a/lib/providers/settings_provider.dart b/lib/providers/settings_provider.dart index 167e279..38478b4 100644 --- a/lib/providers/settings_provider.dart +++ b/lib/providers/settings_provider.dart @@ -15,16 +15,14 @@ final cookiesPathProvider = Provider((ref) { }); final themeModeProvider = - StateNotifierProvider((ref) { - final prefs = ref.watch(sharedPreferencesProvider); - return ThemeModeNotifier(prefs); -}); + NotifierProvider(ThemeModeNotifier.new); -class ThemeModeNotifier extends StateNotifier { - final SharedPreferences _prefs; - - ThemeModeNotifier(this._prefs) - : super(_fromString(_prefs.getString(_kThemeMode))); +class ThemeModeNotifier extends Notifier { + @override + ThemeMode build() { + final prefs = ref.watch(sharedPreferencesProvider); + return _fromString(prefs.getString(_kThemeMode)); + } static ThemeMode _fromString(String? value) => switch (value) { 'light' => ThemeMode.light, @@ -38,48 +36,49 @@ class ThemeModeNotifier extends StateNotifier { ThemeMode.dark => 'dark', _ => 'system', }; - await _prefs.setString(_kThemeMode, value); + await ref.read(sharedPreferencesProvider).setString(_kThemeMode, value); state = mode; } } final forgejoRepoUrlProvider = - StateNotifierProvider((ref) { - return ForgejoRepoUrlNotifier(ref.watch(sharedPreferencesProvider)); -}); + NotifierProvider( + ForgejoRepoUrlNotifier.new); -class ForgejoRepoUrlNotifier extends StateNotifier { - final SharedPreferences _prefs; - ForgejoRepoUrlNotifier(this._prefs) - : super(_prefs.getString(_kForgejoRepoUrl) ?? - 'https://git.fabledsword.com/bvandeusen/FabledApp'); +class ForgejoRepoUrlNotifier extends Notifier { + @override + String? build() { + final prefs = ref.watch(sharedPreferencesProvider); + return prefs.getString(_kForgejoRepoUrl) ?? + 'https://git.fabledsword.com/bvandeusen/FabledApp'; + } Future setUrl(String url) async { final clean = url.endsWith('/') ? url.substring(0, url.length - 1) : url; - await _prefs.setString(_kForgejoRepoUrl, clean); + await ref.read(sharedPreferencesProvider).setString(_kForgejoRepoUrl, clean); state = clean; } } -final serverUrlProvider = StateNotifierProvider((ref) { - final prefs = ref.watch(sharedPreferencesProvider); - return ServerUrlNotifier(prefs); -}); +final serverUrlProvider = + NotifierProvider(ServerUrlNotifier.new); -class ServerUrlNotifier extends StateNotifier { - final SharedPreferences _prefs; - - ServerUrlNotifier(this._prefs) : super(_prefs.getString(_kServerUrl)); +class ServerUrlNotifier extends Notifier { + @override + String? build() { + final prefs = ref.watch(sharedPreferencesProvider); + return prefs.getString(_kServerUrl); + } Future setUrl(String url) async { // Strip trailing slash final clean = url.endsWith('/') ? url.substring(0, url.length - 1) : url; - await _prefs.setString(_kServerUrl, clean); + await ref.read(sharedPreferencesProvider).setString(_kServerUrl, clean); state = clean; } Future clear() async { - await _prefs.remove(_kServerUrl); + await ref.read(sharedPreferencesProvider).remove(_kServerUrl); state = null; } } diff --git a/lib/providers/tasks_provider.dart b/lib/providers/tasks_provider.dart index 29b9855..b9555d4 100644 --- a/lib/providers/tasks_provider.dart +++ b/lib/providers/tasks_provider.dart @@ -28,14 +28,14 @@ class TasksNotifier extends AsyncNotifier> { dueDate: dueDate, projectId: projectId, ); - state = AsyncData([...state.valueOrNull ?? [], task]); + state = AsyncData([...state.value ?? [], task]); return task; } Future updateTask(int id, Map fields) async { final updated = await ref.read(tasksRepositoryProvider).update(id, fields); state = AsyncData([ - for (final t in state.valueOrNull ?? []) + for (final t in state.value ?? []) if (t.id == id) updated else t, ]); return updated; @@ -44,7 +44,7 @@ class TasksNotifier extends AsyncNotifier> { Future delete(int id) async { await ref.read(tasksRepositoryProvider).delete(id); state = AsyncData([ - for (final t in state.valueOrNull ?? []) + for (final t in state.value ?? []) if (t.id != id) t, ]); } diff --git a/lib/screens/chat/chat_screen.dart b/lib/screens/chat/chat_screen.dart index deb6169..91efd5d 100644 --- a/lib/screens/chat/chat_screen.dart +++ b/lib/screens/chat/chat_screen.dart @@ -70,7 +70,7 @@ class _ChatScreenState extends ConsumerState { final convTitle = ref .watch(conversationsProvider) - .valueOrNull + .value ?.where((c) => c.id == widget.conversationId) .firstOrNull ?.title; diff --git a/lib/screens/library/library_screen.dart b/lib/screens/library/library_screen.dart index a66578b..e39a216 100644 --- a/lib/screens/library/library_screen.dart +++ b/lib/screens/library/library_screen.dart @@ -228,8 +228,8 @@ class _LibraryScreenState extends ConsumerState { AsyncValue> notesAsync, AsyncValue> tasksAsync, ) { - final notes = notesAsync.valueOrNull ?? []; - final tasks = tasksAsync.valueOrNull ?? []; + final notes = notesAsync.value ?? []; + final tasks = tasksAsync.value ?? []; // Merge and sort by updatedAt desc final items = <(DateTime, Widget)>[]; diff --git a/lib/screens/notes/note_detail_screen.dart b/lib/screens/notes/note_detail_screen.dart index d547759..19dea9a 100644 --- a/lib/screens/notes/note_detail_screen.dart +++ b/lib/screens/notes/note_detail_screen.dart @@ -16,7 +16,7 @@ class NoteDetailScreen extends ConsumerWidget { @override Widget build(BuildContext context, WidgetRef ref) { final noteAsync = ref.watch(noteDetailProvider(noteId)); - final allNotes = ref.watch(notesProvider).valueOrNull ?? []; + final allNotes = ref.watch(notesProvider).value ?? []; void navigateByTitle(String title) { final matches = allNotes.where( diff --git a/pubspec.lock b/pubspec.lock index 65c7013..308afa8 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -1,6 +1,22 @@ # Generated by pub # See https://dart.dev/tools/pub/glossary#lockfile packages: + _fe_analyzer_shared: + dependency: transitive + description: + name: _fe_analyzer_shared + sha256: "8d7ff3948166b8ec5da0fbb5962000926b8e02f2ed9b3e51d1738905fbd4c98d" + url: "https://pub.dev" + source: hosted + version: "93.0.0" + analyzer: + dependency: transitive + description: + name: analyzer + sha256: de7148ed2fcec579b19f122c1800933dfa028f6d9fd38a152b04b1516cec120b + url: "https://pub.dev" + source: hosted + version: "10.0.1" archive: dependency: transitive description: @@ -49,6 +65,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.0.4" + cli_config: + dependency: transitive + description: + name: cli_config + sha256: ac20a183a07002b700f0c25e61b7ee46b23c309d76ab7b7640a028f18e4d99ec + url: "https://pub.dev" + source: hosted + version: "0.2.0" cli_util: dependency: transitive description: @@ -81,6 +105,14 @@ packages: 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" cookie_jar: dependency: "direct main" description: @@ -89,6 +121,14 @@ packages: url: "https://pub.dev" source: hosted version: "4.0.9" + coverage: + dependency: transitive + description: + name: coverage + sha256: "5da775aa218eaf2151c721b16c01c7676fbfdd99cebba2bf64e8b807a28ff94d" + url: "https://pub.dev" + source: hosted + version: "1.15.0" crypto: dependency: transitive description: @@ -109,26 +149,26 @@ packages: dependency: "direct main" description: name: dio - sha256: b9d46faecab38fc8cc286f80bc4d61a3bb5d4ac49e51ed877b4d6706efe57b25 + sha256: aff32c08f92787a557dd5c0145ac91536481831a01b4648136373cddb0e64f8c url: "https://pub.dev" source: hosted - version: "5.9.1" + version: "5.9.2" dio_cookie_manager: dependency: "direct main" description: name: dio_cookie_manager - sha256: d39c16abcc711c871b7b29bd51c6b5f3059ef39503916c6a9df7e22c4fc595e0 + sha256: "0db1a7b997a0455e488ac35744c68eed3f2a4280d3ab531835a65641b0a08744" url: "https://pub.dev" source: hosted - version: "3.3.0" + version: "3.4.0" dio_web_adapter: dependency: transitive description: name: dio_web_adapter - sha256: "7586e476d70caecaf1686d21eee7247ea43ef5c345eab9e0cc3583ff13378d78" + sha256: "2f9e64323a7c3c7ef69567d5c800424a11f8337b8b228bad02524c9fb3c1f340" url: "https://pub.dev" source: hosted - version: "2.1.1" + version: "2.1.2" fake_async: dependency: transitive description: @@ -250,10 +290,10 @@ packages: dependency: "direct main" description: name: flutter_riverpod - sha256: "9532ee6db4a943a1ed8383072a2e3eeda041db5657cdf6d2acecf3c21ecbe7e1" + sha256: "4e166be88e1dbbaa34a280bdb744aeae73b7ef25fdf8db7a3bb776760a3648e2" url: "https://pub.dev" source: hosted - version: "2.6.1" + version: "3.3.1" flutter_test: dependency: "direct dev" description: flutter @@ -264,6 +304,14 @@ packages: description: flutter source: sdk version: "0.0.0" + frontend_server_client: + dependency: transitive + description: + name: frontend_server_client + sha256: f64a0333a82f30b0cca061bc3d143813a486dc086b574bfb233b7c1372427694 + url: "https://pub.dev" + source: hosted + version: "4.0.0" glob: dependency: transitive description: @@ -276,26 +324,26 @@ packages: dependency: "direct main" description: name: go_router - sha256: f02fd7d2a4dc512fec615529824fdd217fecb3a3d3de68360293a551f21634b3 + sha256: "7974313e217a7771557add6ff2238acb63f635317c35fa590d348fb238f00896" url: "https://pub.dev" source: hosted - version: "14.8.1" + version: "17.1.0" google_fonts: dependency: "direct main" description: name: google_fonts - sha256: ba03d03bcaa2f6cb7bd920e3b5027181db75ab524f8891c8bc3aa603885b8055 + sha256: db9df7a5898d894eeda4c78143f35c30a243558be439518972366880b80bf88e url: "https://pub.dev" source: hosted - version: "6.3.3" + version: "8.0.2" hooks: dependency: transitive description: name: hooks - sha256: "7a08a0d684cb3b8fb604b78455d5d352f502b68079f7b80b831c62220ab0a4f6" + sha256: e79ed1e8e1929bc6ecb6ec85f0cb519c887aa5b423705ded0d0f2d9226def388 url: "https://pub.dev" source: hosted - version: "1.0.1" + version: "1.0.2" http: dependency: transitive description: @@ -304,6 +352,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.6.0" + http_multi_server: + dependency: transitive + description: + name: http_multi_server + sha256: aa6199f908078bb1c5efb8d8638d4ae191aac11b311132c3ef48ce352fb52ef8 + url: "https://pub.dev" + source: hosted + version: "3.2.2" http_parser: dependency: transitive description: @@ -320,6 +376,14 @@ packages: url: "https://pub.dev" source: hosted version: "4.8.0" + io: + dependency: transitive + description: + name: io + sha256: dfd5a80599cf0165756e3181807ed3e77daf6dd4137caaad72d0b7931597650b + url: "https://pub.dev" + source: hosted + version: "1.0.5" json_annotation: dependency: transitive description: @@ -412,10 +476,18 @@ packages: dependency: transitive description: name: native_toolchain_c - sha256: "89e83885ba09da5fdf2cdacc8002a712ca238c28b7f717910b34bcd27b0d03ac" + sha256: "92b2ca62c8bd2b8d2f267cdfccf9bfbdb7322f778f8f91b3ce5b5cda23a3899f" url: "https://pub.dev" source: hosted - version: "0.17.4" + version: "0.17.5" + node_preamble: + dependency: transitive + description: + name: node_preamble + sha256: "6e7eac89047ab8a8d26cf16127b5ed26de65209847630400f9aefd7cd5c730db" + url: "https://pub.dev" + source: hosted + version: "2.0.2" objective_c: dependency: transitive description: @@ -488,14 +560,22 @@ packages: url: "https://pub.dev" source: hosted version: "0.0.3" + package_config: + dependency: transitive + description: + name: package_config + sha256: f096c55ebb7deb7e384101542bfba8c52696c1b56fca2eb62827989ef2353bbc + url: "https://pub.dev" + source: hosted + version: "2.2.0" package_info_plus: dependency: "direct main" description: name: package_info_plus - sha256: "16eee997588c60225bda0488b6dcfac69280a6b7a3cf02c741895dd370a02968" + sha256: f69da0d3189a4b4ceaeb1a3defb0f329b3b352517f52bed4290f83d4f06bc08d url: "https://pub.dev" source: hosted - version: "8.3.1" + version: "9.0.0" package_info_plus_platform_interface: dependency: transitive description: @@ -584,6 +664,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.8" + pool: + dependency: transitive + description: + name: pool + sha256: "978783255c543aa3586a1b3c21f6e9d720eb315376a915872c61ef8b5c20177d" + url: "https://pub.dev" + source: hosted + version: "1.5.2" posix: dependency: transitive description: @@ -604,10 +692,10 @@ packages: dependency: transitive description: name: riverpod - sha256: "59062512288d3056b2321804332a13ffdd1bf16df70dcc8e506e411280a72959" + sha256: "8c22216be8ad3ef2b44af3a329693558c98eca7b8bd4ef495c92db0bba279f83" url: "https://pub.dev" source: hosted - version: "2.6.1" + version: "3.2.1" shared_preferences: dependency: "direct main" description: @@ -664,11 +752,59 @@ packages: url: "https://pub.dev" source: hosted version: "2.4.1" + shelf: + dependency: transitive + description: + name: shelf + sha256: e7dd780a7ffb623c57850b33f43309312fc863fb6aa3d276a754bb299839ef12 + url: "https://pub.dev" + source: hosted + version: "1.4.2" + shelf_packages_handler: + dependency: transitive + description: + name: shelf_packages_handler + sha256: "89f967eca29607c933ba9571d838be31d67f53f6e4ee15147d5dc2934fee1b1e" + url: "https://pub.dev" + source: hosted + version: "3.0.2" + shelf_static: + dependency: transitive + description: + name: shelf_static + sha256: c87c3875f91262785dade62d135760c2c69cb217ac759485334c5857ad89f6e3 + url: "https://pub.dev" + source: hosted + version: "1.1.3" + shelf_web_socket: + dependency: transitive + description: + name: shelf_web_socket + sha256: "3632775c8e90d6c9712f883e633716432a27758216dfb61bd86a8321c0580925" + url: "https://pub.dev" + source: hosted + version: "3.0.0" sky_engine: dependency: transitive description: flutter source: sdk version: "0.0.0" + source_map_stack_trace: + dependency: transitive + description: + name: source_map_stack_trace + sha256: c0713a43e323c3302c2abe2a1cc89aa057a387101ebd280371d6a6c9fa68516b + url: "https://pub.dev" + source: hosted + version: "2.1.2" + source_maps: + dependency: transitive + description: + name: source_maps + sha256: "190222579a448b03896e0ca6eca5998fa810fda630c1d65e2f78b3f638f54812" + url: "https://pub.dev" + source: hosted + version: "0.10.13" source_span: dependency: transitive description: @@ -717,6 +853,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.2.2" + test: + dependency: transitive + description: + name: test + sha256: "280d6d890011ca966ad08df7e8a4ddfab0fb3aa49f96ed6de56e3521347a9ae7" + url: "https://pub.dev" + source: hosted + version: "1.30.0" test_api: dependency: transitive description: @@ -725,6 +869,14 @@ packages: url: "https://pub.dev" source: hosted version: "0.7.10" + test_core: + dependency: transitive + description: + name: test_core + sha256: "0381bd1585d1a924763c308100f2138205252fb90c9d4eeaf28489ee65ccde51" + url: "https://pub.dev" + source: hosted + version: "0.6.16" typed_data: dependency: transitive description: @@ -757,6 +909,14 @@ packages: url: "https://pub.dev" source: hosted version: "15.0.2" + watcher: + dependency: transitive + description: + name: watcher + sha256: "1398c9f081a753f9226febe8900fce8f7d0a67163334e1c94a2438339d79d635" + url: "https://pub.dev" + source: hosted + version: "1.2.1" web: dependency: transitive description: @@ -765,6 +925,30 @@ packages: url: "https://pub.dev" source: hosted version: "1.1.1" + web_socket: + dependency: transitive + description: + name: web_socket + sha256: "34d64019aa8e36bf9842ac014bb5d2f5586ca73df5e4d9bf5c936975cae6982c" + url: "https://pub.dev" + source: hosted + version: "1.0.1" + web_socket_channel: + dependency: transitive + description: + name: web_socket_channel + sha256: d645757fb0f4773d602444000a8131ff5d48c9e47adfe9772652dd1a4f2d45c8 + url: "https://pub.dev" + source: hosted + version: "3.0.3" + webkit_inspection_protocol: + dependency: transitive + description: + name: webkit_inspection_protocol + sha256: "87d3f2333bb240704cd3f1c6b5b7acd8a10e7f0bc28c28dcf14e782014f4a572" + url: "https://pub.dev" + source: hosted + version: "1.2.1" win32: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 5c809fd..e13a650 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -12,19 +12,19 @@ dependencies: sdk: flutter cupertino_icons: ^1.0.8 - flutter_riverpod: ^2.5.1 - go_router: ^14.2.0 + flutter_riverpod: ^3.3.1 + go_router: ^17.1.0 dio: ^5.6.0 cookie_jar: ^4.0.8 dio_cookie_manager: ^3.1.1 path_provider: ^2.1.4 shared_preferences: ^2.3.2 markdown: ^7.2.2 - package_info_plus: ^8.0.0 + package_info_plus: ^9.0.0 open_file: ^3.3.2 flutter_inappwebview: ^6.1.5 flutter_markdown_plus: ^1.0.7 - google_fonts: ^6.2.1 + google_fonts: ^8.0.2 dev_dependencies: flutter_test: