diff --git a/analysis_options.yaml b/analysis_options.yaml index f9b3034..c9303ad 100644 --- a/analysis_options.yaml +++ b/analysis_options.yaml @@ -1 +1,4 @@ include: package:flutter_lints/flutter.yaml +analyzer: + plugins: + - custom_lint diff --git a/lib/main.dart b/lib/main.dart index ffdfa68..679409a 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,8 +1,9 @@ import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:fluxcloud/sftp_connection_list.dart'; void main() { - runApp(const MainApp()); + runApp(ProviderScope(child: const MainApp())); } class MainApp extends StatelessWidget { diff --git a/lib/providers/sftp_state.dart b/lib/providers/sftp_state.dart new file mode 100644 index 0000000..ab21852 --- /dev/null +++ b/lib/providers/sftp_state.dart @@ -0,0 +1,75 @@ +import 'package:dartssh2/dartssh2.dart'; +import 'package:fluxcloud/sftp_worker.dart'; +import 'package:riverpod_annotation/riverpod_annotation.dart'; + +part 'sftp_state.g.dart'; + +class SftpState { + final String path; + final bool isLoading; + final List dirContents; + + final double? uploadProgress; + final double? downloadProgress; + + SftpState({ + required this.path, + required this.isLoading, + required this.dirContents, + required this.uploadProgress, + required this.downloadProgress + }); + + SftpState copyWith({ + String? path, + bool? isLoading, + List? dirContents, + double? uploadProgress, + double? downloadProgress, + }) => SftpState( + path: path ?? this.path, + isLoading: isLoading ?? this.isLoading, + dirContents: dirContents ?? this.dirContents, + uploadProgress: uploadProgress ?? this.uploadProgress, + downloadProgress: downloadProgress ?? this.downloadProgress + ); + +} + +@riverpod +class SftpNotifier extends _$SftpNotifier { + + @override + SftpState build(SftpWorker sftpWorker) { + Future.microtask(listDir); + return SftpState(path: '/', isLoading: false, dirContents: [], uploadProgress: null, downloadProgress: null); + } + + + Future listDir() async { + state = state.copyWith(isLoading: true); + final dirContents = await sftpWorker.listdir(state.path); + state = state.copyWith(isLoading: false, dirContents: dirContents); + } + + void goToDir(String path) { + state = state.copyWith(path: path); + listDir(); + } + + void goToPrevDir() { + String path = state.path.substring(0, state.path.length - 1); + path = path.substring(0, path.lastIndexOf('/')+1); + state = state.copyWith(path: path); + listDir(); + } + + void setUploadProgress(double? progress) { + state = state.copyWith(uploadProgress: progress); + } + + void setDownloadProgress(double? progress) { + state = state.copyWith(downloadProgress: progress); + } + +} diff --git a/lib/providers/sftp_state.g.dart b/lib/providers/sftp_state.g.dart new file mode 100644 index 0000000..b922c5b --- /dev/null +++ b/lib/providers/sftp_state.g.dart @@ -0,0 +1,161 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'sftp_state.dart'; + +// ************************************************************************** +// RiverpodGenerator +// ************************************************************************** + +String _$sftpNotifierHash() => r'819f80135b516bf1d8d3e7dd9022edf3b23a9e0c'; + +/// Copied from Dart SDK +class _SystemHash { + _SystemHash._(); + + static int combine(int hash, int value) { + // ignore: parameter_assignments + hash = 0x1fffffff & (hash + value); + // ignore: parameter_assignments + hash = 0x1fffffff & (hash + ((0x0007ffff & hash) << 10)); + return hash ^ (hash >> 6); + } + + static int finish(int hash) { + // ignore: parameter_assignments + hash = 0x1fffffff & (hash + ((0x03ffffff & hash) << 3)); + // ignore: parameter_assignments + hash = hash ^ (hash >> 11); + return 0x1fffffff & (hash + ((0x00003fff & hash) << 15)); + } +} + +abstract class _$SftpNotifier extends BuildlessAutoDisposeNotifier { + late final SftpWorker sftpWorker; + + SftpState build(SftpWorker sftpWorker); +} + +/// See also [SftpNotifier]. +@ProviderFor(SftpNotifier) +const sftpNotifierProvider = SftpNotifierFamily(); + +/// See also [SftpNotifier]. +class SftpNotifierFamily extends Family { + /// See also [SftpNotifier]. + const SftpNotifierFamily(); + + /// See also [SftpNotifier]. + SftpNotifierProvider call(SftpWorker sftpWorker) { + return SftpNotifierProvider(sftpWorker); + } + + @override + SftpNotifierProvider getProviderOverride( + covariant SftpNotifierProvider provider, + ) { + return call(provider.sftpWorker); + } + + static const Iterable? _dependencies = null; + + @override + Iterable? get dependencies => _dependencies; + + static const Iterable? _allTransitiveDependencies = null; + + @override + Iterable? get allTransitiveDependencies => + _allTransitiveDependencies; + + @override + String? get name => r'sftpNotifierProvider'; +} + +/// See also [SftpNotifier]. +class SftpNotifierProvider + extends AutoDisposeNotifierProviderImpl { + /// See also [SftpNotifier]. + SftpNotifierProvider(SftpWorker sftpWorker) + : this._internal( + () => SftpNotifier()..sftpWorker = sftpWorker, + from: sftpNotifierProvider, + name: r'sftpNotifierProvider', + debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product') + ? null + : _$sftpNotifierHash, + dependencies: SftpNotifierFamily._dependencies, + allTransitiveDependencies: + SftpNotifierFamily._allTransitiveDependencies, + sftpWorker: sftpWorker, + ); + + SftpNotifierProvider._internal( + super._createNotifier, { + required super.name, + required super.dependencies, + required super.allTransitiveDependencies, + required super.debugGetCreateSourceHash, + required super.from, + required this.sftpWorker, + }) : super.internal(); + + final SftpWorker sftpWorker; + + @override + SftpState runNotifierBuild(covariant SftpNotifier notifier) { + return notifier.build(sftpWorker); + } + + @override + Override overrideWith(SftpNotifier Function() create) { + return ProviderOverride( + origin: this, + override: SftpNotifierProvider._internal( + () => create()..sftpWorker = sftpWorker, + from: from, + name: null, + dependencies: null, + allTransitiveDependencies: null, + debugGetCreateSourceHash: null, + sftpWorker: sftpWorker, + ), + ); + } + + @override + AutoDisposeNotifierProviderElement createElement() { + return _SftpNotifierProviderElement(this); + } + + @override + bool operator ==(Object other) { + return other is SftpNotifierProvider && other.sftpWorker == sftpWorker; + } + + @override + int get hashCode { + var hash = _SystemHash.combine(0, runtimeType.hashCode); + hash = _SystemHash.combine(hash, sftpWorker.hashCode); + + return _SystemHash.finish(hash); + } +} + +@Deprecated('Will be removed in 3.0. Use Ref instead') +// ignore: unused_element +mixin SftpNotifierRef on AutoDisposeNotifierProviderRef { + /// The parameter `sftpWorker` of this provider. + SftpWorker get sftpWorker; +} + +class _SftpNotifierProviderElement + extends AutoDisposeNotifierProviderElement + with SftpNotifierRef { + _SftpNotifierProviderElement(super.provider); + + @override + SftpWorker get sftpWorker => (origin as SftpNotifierProvider).sftpWorker; +} + +// ignore_for_file: type=lint +// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member, deprecated_member_use_from_same_package diff --git a/lib/sftp_explorer.dart b/lib/sftp_explorer.dart index 9c50dc4..001be24 100644 --- a/lib/sftp_explorer.dart +++ b/lib/sftp_explorer.dart @@ -1,57 +1,23 @@ import 'dart:io'; -import 'package:dartssh2/dartssh2.dart'; import 'package:file_picker/file_picker.dart'; import 'package:file_selector/file_selector.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:fluxcloud/main.dart'; +import 'package:fluxcloud/providers/sftp_state.dart'; import 'package:fluxcloud/sftp_worker.dart'; import 'widgets/operation_buttons.dart'; -class SftpExplorer extends StatefulWidget { +class SftpExplorer extends ConsumerWidget { const SftpExplorer({super.key, required this.sftpWorker}); final SftpWorker sftpWorker; @override - State createState() => _SftpExplorerState(); -} - -class _SftpExplorerState extends State { - - String path = '/'; - - bool _isLoading = true; - late List _dirContents; - - double? _uploadProgress; - double? _downloadProgress; - - void _setDownloadProgress(double? progress) => setState(() => _downloadProgress = progress); - - @override - void initState() { - super.initState(); - _listDir(); - } - - Future _listDir() async { - setState(() => _isLoading = true); - try { - _dirContents = await widget.sftpWorker.listdir(path); - } - catch (e) { - if (mounted) { - ScaffoldMessenger.of(context).showSnackBar(buildErrorSnackBar(context, e.toString())); - } - } - setState(() => _isLoading = false); - } - - - @override - Widget build(BuildContext context) { + Widget build(BuildContext context, WidgetRef ref) { + final sftpState = ref.watch(sftpNotifierProvider(sftpWorker)); return Scaffold( appBar: AppBar( toolbarHeight: 75, @@ -60,25 +26,23 @@ class _SftpExplorerState extends State { actionsPadding: EdgeInsets.only(right: 20), leading: IconButton( onPressed: () { - if (path == '/') { + if (sftpState.path == '/') { // TODO: figure this out // Navigator.pop(context); } else { - path = path.substring(0, path.length - 1); - path = path.substring(0, path.lastIndexOf('/')+1); - _listDir(); + ref.read(sftpNotifierProvider(sftpWorker).notifier).goToPrevDir(); } }, icon: Icon(Icons.arrow_back) ), actions: [ - if (_uploadProgress != null) + if (sftpState.uploadProgress != null) Stack( alignment: Alignment.center, children: [ TweenAnimationBuilder( - tween: Tween(begin: 0, end: _uploadProgress), + tween: Tween(begin: 0, end: sftpState.uploadProgress), duration: Duration(milliseconds: 300), builder: (context, value, _) => CircularProgressIndicator(strokeWidth: 3, value: value,) ), @@ -90,12 +54,12 @@ class _SftpExplorerState extends State { ), ] ), - if (_downloadProgress != null) + if (sftpState.downloadProgress != null) Stack( alignment: Alignment.center, children: [ TweenAnimationBuilder( - tween: Tween(begin: 0, end: _downloadProgress), + tween: Tween(begin: 0, end: sftpState.downloadProgress), duration: Duration(milliseconds: 300), builder: (context, value, _) => CircularProgressIndicator(strokeWidth: 3, value: value,) ), @@ -109,14 +73,12 @@ class _SftpExplorerState extends State { ), ], ), - floatingActionButton: _buildFABs(context), + floatingActionButton: _buildFABs(context, ref), body: PopScope( canPop: false, onPopInvokedWithResult: (_, _) { - if (path != '/') { - path = path.substring(0, path.length - 1); - path = path.substring(0, path.lastIndexOf('/')+1); - _listDir(); + if (sftpState.path != '/') { + ref.read(sftpNotifierProvider(sftpWorker).notifier).goToPrevDir(); } }, child: AnimatedSwitcher( @@ -137,19 +99,18 @@ class _SftpExplorerState extends State { ), ); }, - child: _isLoading ? Center(child: CircularProgressIndicator()) : ListView.builder( - key: ValueKey(path), - itemCount: _dirContents.length, + child: sftpState.isLoading ? Center(child: CircularProgressIndicator()) : ListView.builder( + key: ValueKey(sftpState.path), + itemCount: sftpState.dirContents.length, itemBuilder: (context, index) { - final dirEntry = _dirContents[index]; + final dirEntry = sftpState.dirContents[index]; return ListTile( leading: Icon(dirEntry.attr.isDirectory ? Icons.folder : Icons.description), title: Text(dirEntry.filename), - trailing: OperationButtons(sftpWorker: widget.sftpWorker, path: path, dirEntries: [dirEntry], listDir: _listDir, setDownloadProgress: _setDownloadProgress,), + trailing: OperationButtons(sftpWorker: sftpWorker, dirEntries: [dirEntry],), onTap: () { if (dirEntry.attr.isDirectory) { - path = '$path${dirEntry.filename}/'; - _listDir(); + ref.read(sftpNotifierProvider(sftpWorker).notifier).goToDir('${sftpState.path}${dirEntry.filename}/'); } }, ); @@ -160,7 +121,8 @@ class _SftpExplorerState extends State { ); } - Widget _buildFABs(BuildContext context) { + Widget _buildFABs(BuildContext context, WidgetRef ref) { + final sftpState = ref.read(sftpNotifierProvider(sftpWorker)); return Row( mainAxisSize: MainAxisSize.min, spacing: 10, @@ -184,8 +146,8 @@ class _SftpExplorerState extends State { TextButton( onPressed: () async { try { - await widget.sftpWorker.mkdir('$path${nameController.text}'); - _listDir(); + await sftpWorker.mkdir('${sftpState.path}${nameController.text}'); + ref.read(sftpNotifierProvider(sftpWorker).notifier).listDir(); } catch (e) { if (context.mounted) { @@ -217,16 +179,10 @@ class _SftpExplorerState extends State { filePaths = files.map((file) => file.path).toList(); } try { - bool start = true; - await for (final progress in widget.sftpWorker.uploadFiles(path, filePaths)) { - if (start) { - start = false; - _listDir(); - } - setState(() => _uploadProgress = progress); + await for (final progress in sftpWorker.uploadFiles(sftpState.path, filePaths)) { + ref.read(sftpNotifierProvider(sftpWorker).notifier).setUploadProgress(progress); if (progress == 1) { - // TODO: fix: next file also starts to show - _listDir(); + ref.read(sftpNotifierProvider(sftpWorker).notifier).listDir(); } } } @@ -235,8 +191,8 @@ class _SftpExplorerState extends State { ScaffoldMessenger.of(context).showSnackBar(buildErrorSnackBar(context, e.toString())); } } - setState(() => _uploadProgress = null); - _listDir(); + ref.read(sftpNotifierProvider(sftpWorker).notifier).setUploadProgress(null); + ref.read(sftpNotifierProvider(sftpWorker).notifier).listDir(); }, child: Icon(Icons.upload), ), diff --git a/lib/widgets/operation_buttons.dart b/lib/widgets/operation_buttons.dart index 5b09634..05bb28c 100644 --- a/lib/widgets/operation_buttons.dart +++ b/lib/widgets/operation_buttons.dart @@ -1,23 +1,23 @@ import 'package:dartssh2/dartssh2.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:fluxcloud/main.dart'; +import 'package:fluxcloud/providers/sftp_state.dart'; import 'package:fluxcloud/sftp_worker.dart'; import 'package:path_provider/path_provider.dart'; -class OperationButtons extends StatelessWidget { +class OperationButtons extends ConsumerWidget { const OperationButtons({ super.key, - required this.sftpWorker, required this.path, required this.dirEntries, required this.listDir, required this.setDownloadProgress, + required this.sftpWorker, required this.dirEntries, }); final SftpWorker sftpWorker; - final String path; final List dirEntries; - final Function listDir; - final Function(double? progress) setDownloadProgress; @override - Widget build(BuildContext context) { + Widget build(BuildContext context, WidgetRef ref) { + final sftpState = ref.watch(sftpNotifierProvider(sftpWorker)); return Row( mainAxisSize: MainAxisSize.min, children: [ @@ -54,8 +54,8 @@ class OperationButtons extends StatelessWidget { TextButton( onPressed: () async { try { - await sftpWorker.rename('$path${dirEntry.filename}', '$path${newNameController.text}'); - listDir(); + await sftpWorker.rename('${sftpState.path}${dirEntry.filename}', '${sftpState.path}${newNameController.text}'); + ref.read(sftpNotifierProvider(sftpWorker).notifier).listDir(); } on SftpStatusError catch (e) { if (context.mounted) { @@ -97,14 +97,14 @@ class OperationButtons extends StatelessWidget { onPressed: () async { for (final dirEntry in dirEntries) { try { - await sftpWorker.remove(dirEntry, path); + await sftpWorker.remove(dirEntry, sftpState.path); } catch (e) { if (context.mounted) { ScaffoldMessenger.of(context).showSnackBar(buildErrorSnackBar(context, e.toString())); } } - listDir(); + ref.read(sftpNotifierProvider(sftpWorker).notifier).listDir(); if (context.mounted) { Navigator.pop(context); } @@ -124,10 +124,10 @@ class OperationButtons extends StatelessWidget { final downloadsDir = await getDownloadsDirectory(); if (downloadsDir == null) return; try { - await for (final progress in sftpWorker.downloadFiles(dirEntries, path, downloadsDir.path)) { - setDownloadProgress(progress); + await for (final progress in sftpWorker.downloadFiles(dirEntries, sftpState.path, downloadsDir.path)) { + ref.read(sftpNotifierProvider(sftpWorker).notifier).setDownloadProgress(progress); } - setDownloadProgress(null); + ref.read(sftpNotifierProvider(sftpWorker).notifier).setDownloadProgress(null); } catch (e) { if (context.mounted) { diff --git a/pubspec.lock b/pubspec.lock index 2a4a94f..01137fc 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -1,6 +1,38 @@ # Generated by pub # See https://dart.dev/tools/pub/glossary#lockfile packages: + _fe_analyzer_shared: + dependency: transitive + description: + name: _fe_analyzer_shared + sha256: da0d9209ca76bde579f2da330aeb9df62b6319c834fa7baae052021b0462401f + url: "https://pub.dev" + source: hosted + version: "85.0.0" + analyzer: + dependency: transitive + description: + name: analyzer + sha256: f4ad0fea5f102201015c9aae9d93bc02f75dd9491529a8c21f88d17a8523d44c + url: "https://pub.dev" + source: hosted + version: "7.6.0" + analyzer_plugin: + dependency: transitive + description: + name: analyzer_plugin + sha256: a5ab7590c27b779f3d4de67f31c4109dbe13dd7339f86461a6f2a8ab2594d8ce + url: "https://pub.dev" + source: hosted + version: "0.13.4" + args: + dependency: transitive + description: + name: args + sha256: d0481093c50b1da8910eb0bb301626d4d8eb7284aa739614d2b394ee09e3ea04 + url: "https://pub.dev" + source: hosted + version: "2.7.0" asn1lib: dependency: transitive description: @@ -25,6 +57,70 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.2" + build: + dependency: transitive + description: + name: build + sha256: "51dc711996cbf609b90cbe5b335bbce83143875a9d58e4b5c6d3c4f684d3dda7" + url: "https://pub.dev" + source: hosted + version: "2.5.4" + build_config: + dependency: transitive + description: + name: build_config + sha256: "4ae2de3e1e67ea270081eaee972e1bd8f027d459f249e0f1186730784c2e7e33" + url: "https://pub.dev" + source: hosted + version: "1.1.2" + build_daemon: + dependency: transitive + description: + name: build_daemon + sha256: "8e928697a82be082206edb0b9c99c5a4ad6bc31c9e9b8b2f291ae65cd4a25daa" + url: "https://pub.dev" + source: hosted + version: "4.0.4" + build_resolvers: + dependency: transitive + description: + name: build_resolvers + sha256: ee4257b3f20c0c90e72ed2b57ad637f694ccba48839a821e87db762548c22a62 + url: "https://pub.dev" + source: hosted + version: "2.5.4" + build_runner: + dependency: "direct dev" + description: + name: build_runner + sha256: "382a4d649addbfb7ba71a3631df0ec6a45d5ab9b098638144faf27f02778eb53" + url: "https://pub.dev" + source: hosted + version: "2.5.4" + build_runner_core: + dependency: transitive + description: + name: build_runner_core + sha256: "85fbbb1036d576d966332a3f5ce83f2ce66a40bea1a94ad2d5fc29a19a0d3792" + url: "https://pub.dev" + source: hosted + version: "9.1.2" + built_collection: + dependency: transitive + description: + name: built_collection + sha256: "376e3dd27b51ea877c28d525560790aee2e6fbb5f20e2f85d5081027d94e2100" + url: "https://pub.dev" + source: hosted + version: "5.1.1" + built_value: + dependency: transitive + description: + name: built_value + sha256: ba95c961bafcd8686d1cf63be864eb59447e795e124d98d6a27d91fcd13602fb + url: "https://pub.dev" + source: hosted + version: "8.11.1" characters: dependency: transitive description: @@ -33,6 +129,30 @@ packages: url: "https://pub.dev" source: hosted version: "1.4.0" + checked_yaml: + dependency: transitive + description: + name: checked_yaml + sha256: "959525d3162f249993882720d52b7e0c833978df229be20702b33d48d91de70f" + url: "https://pub.dev" + source: hosted + version: "2.0.4" + ci: + dependency: transitive + description: + name: ci + sha256: "145d095ce05cddac4d797a158bc4cf3b6016d1fe63d8c3d2fbd7212590adca13" + url: "https://pub.dev" + source: hosted + version: "0.1.0" + cli_util: + dependency: transitive + description: + name: cli_util + sha256: ff6785f7e9e3c38ac98b2fb035701789de90154024a75b6cb926445e83197d1c + url: "https://pub.dev" + source: hosted + version: "0.4.2" clock: dependency: transitive description: @@ -41,6 +161,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.1.2" + code_builder: + dependency: transitive + description: + name: code_builder + sha256: "0ec10bf4a89e4c613960bf1e8b42c64127021740fb21640c29c909826a5eea3e" + url: "https://pub.dev" + source: hosted + version: "4.10.1" collection: dependency: transitive description: @@ -65,6 +193,54 @@ packages: 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" + custom_lint: + dependency: "direct dev" + description: + name: custom_lint + sha256: "9656925637516c5cf0f5da018b33df94025af2088fe09c8ae2ca54c53f2d9a84" + url: "https://pub.dev" + source: hosted + version: "0.7.6" + custom_lint_builder: + dependency: transitive + description: + name: custom_lint_builder + sha256: "6cdc8e87e51baaaba9c43e283ed8d28e59a0c4732279df62f66f7b5984655414" + url: "https://pub.dev" + source: hosted + version: "0.7.6" + custom_lint_core: + dependency: transitive + description: + name: custom_lint_core + sha256: "31110af3dde9d29fb10828ca33f1dce24d2798477b167675543ce3d208dee8be" + url: "https://pub.dev" + source: hosted + version: "0.7.5" + custom_lint_visitor: + dependency: transitive + description: + name: custom_lint_visitor + sha256: "4a86a0d8415a91fbb8298d6ef03e9034dc8e323a599ddc4120a0e36c433983a2" + url: "https://pub.dev" + source: hosted + version: "1.0.0+7.7.0" + dart_style: + dependency: transitive + description: + name: dart_style + sha256: "8a0e5fba27e8ee025d2ffb4ee820b4e6e2cf5e4246a6b1a477eb66866947e0bb" + url: "https://pub.dev" + source: hosted + version: "3.1.1" dartssh2: dependency: "direct main" description: @@ -89,6 +265,14 @@ packages: 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: @@ -161,6 +345,14 @@ packages: url: "https://pub.dev" source: hosted version: "0.9.3+4" + fixnum: + dependency: transitive + description: + name: fixnum + sha256: b6dc7065e46c974bc7c5f143080a6764ec7a4be6da1285ececdc37be96de53be + url: "https://pub.dev" + source: hosted + version: "1.1.1" flutter: dependency: "direct main" description: flutter @@ -182,6 +374,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.0.28" + flutter_riverpod: + dependency: "direct main" + description: + name: flutter_riverpod + sha256: "9532ee6db4a943a1ed8383072a2e3eeda041db5657cdf6d2acecf3c21ecbe7e1" + url: "https://pub.dev" + source: hosted + version: "2.6.1" flutter_secure_storage: dependency: "direct main" description: @@ -240,6 +440,46 @@ packages: description: flutter source: sdk version: "0.0.0" + freezed_annotation: + dependency: transitive + description: + name: freezed_annotation + sha256: "7294967ff0a6d98638e7acb774aac3af2550777accd8149c90af5b014e6d44d8" + url: "https://pub.dev" + source: hosted + version: "3.1.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: + name: glob + sha256: c3f1ee72c96f8f78935e18aa8cecced9ab132419e8625dc187e1c2408efc20de + url: "https://pub.dev" + source: hosted + version: "2.1.3" + graphs: + dependency: transitive + description: + name: graphs + sha256: "741bbf84165310a68ff28fe9e727332eef1407342fca52759cb21ad8177bb8d0" + url: "https://pub.dev" + source: hosted + version: "2.3.2" + hotreloader: + dependency: transitive + description: + name: hotreloader + sha256: bc167a1163807b03bada490bfe2df25b0d744df359227880220a5cbd04e5734b + url: "https://pub.dev" + source: hosted + version: "4.3.0" http: dependency: transitive description: @@ -248,6 +488,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.4.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: @@ -256,6 +504,14 @@ packages: url: "https://pub.dev" source: hosted version: "4.1.2" + io: + dependency: transitive + description: + name: io + sha256: dfd5a80599cf0165756e3181807ed3e77daf6dd4137caaad72d0b7931597650b + url: "https://pub.dev" + source: hosted + version: "1.0.5" js: dependency: transitive description: @@ -264,6 +520,14 @@ packages: url: "https://pub.dev" source: hosted version: "0.6.7" + json_annotation: + dependency: transitive + description: + name: json_annotation + sha256: "1ce844379ca14835a50d2f019a3099f419082cfdd231cd86a142af94dd5c6bb1" + url: "https://pub.dev" + source: hosted + version: "4.9.0" leak_tracker: dependency: transitive description: @@ -296,6 +560,14 @@ packages: url: "https://pub.dev" source: hosted version: "5.1.1" + logging: + dependency: transitive + description: + name: logging + sha256: c8245ada5f1717ed44271ed1c26b8ce85ca3228fd2ffdb75468ab01979309d61 + url: "https://pub.dev" + source: hosted + version: "1.3.0" matcher: dependency: transitive description: @@ -320,6 +592,22 @@ packages: 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" + package_config: + dependency: transitive + description: + name: package_config + sha256: f096c55ebb7deb7e384101542bfba8c52696c1b56fca2eb62827989ef2353bbc + url: "https://pub.dev" + source: hosted + version: "2.2.0" path: dependency: "direct main" description: @@ -408,11 +696,107 @@ packages: url: "https://pub.dev" source: hosted version: "3.9.1" + pool: + dependency: transitive + description: + name: pool + sha256: "20fe868b6314b322ea036ba325e6fc0711a22948856475e2c2b6306e8ab39c2a" + url: "https://pub.dev" + source: hosted + version: "1.5.1" + pub_semver: + dependency: transitive + description: + name: pub_semver + sha256: "5bfcf68ca79ef689f8990d1160781b4bad40a3bd5e5218ad4076ddb7f4081585" + url: "https://pub.dev" + source: hosted + version: "2.2.0" + pubspec_parse: + dependency: transitive + description: + name: pubspec_parse + sha256: "0560ba233314abbed0a48a2956f7f022cce7c3e1e73df540277da7544cad4082" + url: "https://pub.dev" + source: hosted + version: "1.5.0" + riverpod: + dependency: transitive + description: + name: riverpod + sha256: "59062512288d3056b2321804332a13ffdd1bf16df70dcc8e506e411280a72959" + url: "https://pub.dev" + source: hosted + version: "2.6.1" + riverpod_analyzer_utils: + dependency: transitive + description: + name: riverpod_analyzer_utils + sha256: "03a17170088c63aab6c54c44456f5ab78876a1ddb6032ffde1662ddab4959611" + url: "https://pub.dev" + source: hosted + version: "0.5.10" + riverpod_annotation: + dependency: "direct main" + description: + name: riverpod_annotation + sha256: e14b0bf45b71326654e2705d462f21b958f987087be850afd60578fcd502d1b8 + url: "https://pub.dev" + source: hosted + version: "2.6.1" + riverpod_generator: + dependency: "direct dev" + description: + name: riverpod_generator + sha256: "44a0992d54473eb199ede00e2260bd3c262a86560e3c6f6374503d86d0580e36" + url: "https://pub.dev" + source: hosted + version: "2.6.5" + riverpod_lint: + dependency: "direct dev" + description: + name: riverpod_lint + sha256: "89a52b7334210dbff8605c3edf26cfe69b15062beed5cbfeff2c3812c33c9e35" + url: "https://pub.dev" + source: hosted + version: "2.6.5" + rxdart: + dependency: transitive + description: + name: rxdart + sha256: "5c3004a4a8dbb94bd4bf5412a4def4acdaa12e12f269737a5751369e12d1a962" + url: "https://pub.dev" + source: hosted + version: "0.28.0" + shelf: + dependency: transitive + description: + name: shelf + sha256: e7dd780a7ffb623c57850b33f43309312fc863fb6aa3d276a754bb299839ef12 + url: "https://pub.dev" + source: hosted + version: "1.4.2" + 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_gen: + dependency: transitive + description: + name: source_gen + sha256: "35c8150ece9e8c8d263337a265153c3329667640850b9304861faea59fc98f6b" + url: "https://pub.dev" + source: hosted + version: "2.0.0" source_span: dependency: transitive description: @@ -421,6 +805,14 @@ packages: 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: @@ -429,6 +821,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.12.1" + state_notifier: + dependency: transitive + description: + name: state_notifier + sha256: b8677376aa54f2d7c58280d5a007f9e8774f1968d1fb1c096adcb4792fba29bb + url: "https://pub.dev" + source: hosted + version: "1.0.0" stream_channel: dependency: transitive description: @@ -437,6 +837,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.4" + stream_transform: + dependency: transitive + description: + name: stream_transform + sha256: ad47125e588cfd37a9a7f86c7d6356dde8dfe89d071d293f80ca9e9273a33871 + url: "https://pub.dev" + source: hosted + version: "2.1.1" string_scanner: dependency: transitive description: @@ -461,6 +869,14 @@ packages: url: "https://pub.dev" source: hosted version: "0.7.4" + timing: + dependency: transitive + description: + name: timing + sha256: "62ee18aca144e4a9f29d212f5a4c6a053be252b895ab14b5821996cff4ed90fe" + url: "https://pub.dev" + source: hosted + version: "1.0.2" typed_data: dependency: transitive description: @@ -469,6 +885,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.4.0" + uuid: + dependency: transitive + description: + name: uuid + sha256: a5be9ef6618a7ac1e964353ef476418026db906c4facdedaa299b7a2e71690ff + url: "https://pub.dev" + source: hosted + version: "4.5.1" vector_math: dependency: transitive description: @@ -485,6 +909,14 @@ packages: 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: @@ -493,6 +925,22 @@ 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" win32: dependency: transitive description: @@ -509,6 +957,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.1.0" + yaml: + dependency: transitive + description: + name: yaml + sha256: b9da305ac7c39faa3f030eccd175340f968459dae4af175130b3fc47e40d76ce + url: "https://pub.dev" + source: hosted + version: "3.1.3" sdks: dart: ">=3.8.1 <4.0.0" flutter: ">=3.27.0" diff --git a/pubspec.yaml b/pubspec.yaml index 6b69008..f078b88 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -15,11 +15,17 @@ dependencies: path: ^1.9.1 file_picker: ^10.2.0 path_provider: ^2.1.5 + flutter_riverpod: ^2.6.1 + riverpod_annotation: ^2.6.1 dev_dependencies: flutter_test: sdk: flutter flutter_lints: ^5.0.0 + riverpod_generator: ^2.6.5 + build_runner: ^2.5.4 + custom_lint: ^0.7.6 + riverpod_lint: ^2.6.5 flutter: uses-material-design: true