wip: bloc for files

This commit is contained in:
Elias Müller 2024-08-23 20:49:19 +02:00
parent 54b777237f
commit 5bdfb9f766
7 changed files with 73 additions and 56 deletions

View File

@ -97,7 +97,7 @@ class _AppState extends State<App> with WidgetsBindingObserver {
controller: Main.bottomNavigator, controller: Main.bottomNavigator,
navBarOverlap: const NavBarOverlap.none(), navBarOverlap: const NavBarOverlap.none(),
backgroundColor: Theme.of(context).colorScheme.primary, backgroundColor: Theme.of(context).colorScheme.primary,
handleAndroidBackButtonPress: false, handleAndroidBackButtonPress: true,
screenTransitionAnimation: const ScreenTransitionAnimation(curve: Curves.easeOutQuad, duration: Duration(milliseconds: 200)), screenTransitionAnimation: const ScreenTransitionAnimation(curve: Curves.easeOutQuad, duration: Duration(milliseconds: 200)),
tabs: [ tabs: [

View File

@ -17,13 +17,16 @@ class LoadableStateConsumer<TController extends Bloc<LoadableHydratedBlocEvent<T
final Widget Function(TState state, bool loading) child; final Widget Function(TState state, bool loading) child;
final void Function(TState state)? onLoad; final void Function(TState state)? onLoad;
final bool wrapWithScrollView; final bool wrapWithScrollView;
const LoadableStateConsumer({required this.child, this.onLoad, this.wrapWithScrollView = false, super.key}); final TController? controllerByValue;
const LoadableStateConsumer({required this.child, this.onLoad, this.wrapWithScrollView = false, this.controllerByValue = null, super.key});
static Duration animationDuration = const Duration(milliseconds: 200); static Duration animationDuration = const Duration(milliseconds: 200);
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
var loadableState = context.watch<TController>().state; var loadableState = controllerByValue != null
? controllerByValue!.state
: context.watch<TController>().state;
if(!loadableState.isLoading && onLoad != null) { if(!loadableState.isLoading && onLoad != null) {
WidgetsBinding.instance.addPostFrameCallback((timeStamp) => onLoad!(loadableState.data)); WidgetsBinding.instance.addPostFrameCallback((timeStamp) => onLoad!(loadableState.data));

View File

@ -1,6 +1,8 @@
import 'dart:developer'; import 'dart:developer';
import 'package:sorted/sorted.dart';
import '../../../infrastructure/utilityWidgets/loadableHydratedBloc/loadable_hydrated_bloc.dart'; import '../../../infrastructure/utilityWidgets/loadableHydratedBloc/loadable_hydrated_bloc.dart';
import '../../../infrastructure/utilityWidgets/loadableHydratedBloc/loadable_hydrated_bloc_event.dart'; import '../../../infrastructure/utilityWidgets/loadableHydratedBloc/loadable_hydrated_bloc_event.dart';
import '../repository/files_repository.dart'; import '../repository/files_repository.dart';
@ -36,6 +38,10 @@ class FilesBloc extends LoadableHydratedBloc<FilesEvent, FilesState, FilesReposi
return pathSegments.join(basePath) + basePath; return pathSegments.join(basePath) + basePath;
} }
List currentSortConfiguration() => [
SortedComparable<File, DateTime>((file) => file.updatedAt ?? DateTime.now()),
];
@override @override
FilesState fromNothing() => const FilesState(currentFolder: basePath, files: {}); FilesState fromNothing() => const FilesState(currentFolder: basePath, files: {});

View File

@ -1,17 +1,9 @@
import 'dart:developer';
import 'package:filesize/filesize.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:jiffy/jiffy.dart';
import '../../../../../widget/centeredLeading.dart';
import '../../../../../widget/list_view_util.dart';
import '../../../infrastructure/loadableState/loadable_state.dart'; import '../../../infrastructure/loadableState/loadable_state.dart';
import '../../../infrastructure/loadableState/view/loadable_state_consumer.dart';
import '../../../infrastructure/utilityWidgets/bloc_module.dart'; import '../../../infrastructure/utilityWidgets/bloc_module.dart';
import '../bloc/files_bloc.dart'; import '../bloc/files_bloc.dart';
import '../bloc/files_event.dart';
import '../bloc/files_state.dart'; import '../bloc/files_state.dart';
import 'folder_view.dart';
class FilesView extends StatelessWidget { class FilesView extends StatelessWidget {
const FilesView({super.key}); const FilesView({super.key});
@ -20,48 +12,6 @@ class FilesView extends StatelessWidget {
Widget build(BuildContext context) => BlocModule<FilesBloc, LoadableState<FilesState>>( Widget build(BuildContext context) => BlocModule<FilesBloc, LoadableState<FilesState>>(
create: (context) => FilesBloc(), create: (context) => FilesBloc(),
autoRebuild: true, autoRebuild: true,
child: (context, bloc, state) { child: (context, bloc, state) => FolderView(bloc),
var goBackButton = !bloc.canGoBack() ? null : IconButton(
icon: const Icon(Icons.arrow_back),
onPressed: () {
bloc.add(EnterFolder(bloc.goBackLocation()));
},
);
return PopScope(
canPop: false,
onPopInvoked: (didPop) => bloc.add(EnterFolder(bloc.goBackLocation())),
child: Scaffold(
appBar: AppBar(
leading: goBackButton,
title: Text(bloc.getCurrentFolderName()),
actions: [
IconButton(onPressed: () {
log(bloc.innerState?.toJson().toString() ?? 'leer');
}, icon: const Icon(Icons.bug_report)),
IconButton(onPressed: () {
bloc.add(EnterFolder('/'));
}, icon: const Icon(Icons.home)),
],
),
body: LoadableStateConsumer<FilesBloc, FilesState>(
child: (state, loading) => ListViewUtil.fromList<File>(bloc.getVisibleFiles(), (file) => ListTile(
leading: CenteredLeading(Icon(file.isFolder ? Icons.folder : Icons.description_outlined)),
title: Text(file.name),
subtitle: file.isFolder
? Text('geändert ${Jiffy.parseFromDateTime(file.updatedAt ?? DateTime.now()).fromNow()}')
: Text('${filesize(file.size)}, ${Jiffy.parseFromDateTime(file.updatedAt ?? DateTime.now()).fromNow()}'),
trailing: Icon(file.isFolder ? Icons.arrow_right : null),
onTap: () {
log(file.path);
if(!file.isFolder) return;
bloc.add(EnterFolder(file.path));
},
))
)
),
);
},
); );
} }

View File

@ -0,0 +1,57 @@
import 'dart:developer';
import 'package:filesize/filesize.dart';
import 'package:flutter/material.dart';
import 'package:jiffy/jiffy.dart';
import '../../../../../widget/centeredLeading.dart';
import '../../../../../widget/list_view_util.dart';
import '../../../infrastructure/loadableState/view/loadable_state_consumer.dart';
import '../bloc/files_bloc.dart';
import '../bloc/files_event.dart';
import '../bloc/files_state.dart';
class FolderView extends StatelessWidget {
final FilesBloc bloc;
const FolderView(this.bloc, {super.key});
@override
Widget build(BuildContext context) => Scaffold(
appBar: AppBar(
leading: !bloc.canGoBack() ? null : IconButton(
icon: const Icon(Icons.arrow_back),
onPressed: () {
bloc.add(EnterFolder(bloc.goBackLocation()));
Navigator.of(context).pop();
},
),
title: Text(bloc.getCurrentFolderName()),
actions: [
IconButton(onPressed: () {
log(bloc.innerState?.toJson().toString() ?? 'leer');
}, icon: const Icon(Icons.bug_report)),
IconButton(onPressed: () {
bloc.add(EnterFolder('/'));
}, icon: const Icon(Icons.home)),
],
),
body: LoadableStateConsumer<FilesBloc, FilesState>(
controllerByValue: bloc,
child: (state, loading) => ListViewUtil.fromList<File>(bloc.getVisibleFiles(), (file) => ListTile(
leading: CenteredLeading(Icon(file.isFolder ? Icons.folder : Icons.description_outlined)),
title: Text(file.name),
subtitle: file.isFolder
? Text('geändert ${Jiffy.parseFromDateTime(file.updatedAt ?? DateTime.now()).fromNow()}')
: Text('${filesize(file.size)}, ${Jiffy.parseFromDateTime(file.updatedAt ?? DateTime.now()).fromNow()}'),
trailing: Icon(file.isFolder ? Icons.arrow_right : null),
onTap: () {
log(file.path);
if(!file.isFolder) return;
Navigator.of(context).push(MaterialPageRoute(builder: (context) => FolderView(bloc)));
bloc.add(EnterFolder(file.path));
},
))
)
);
}

View File

@ -8,6 +8,6 @@ class LightAppTheme {
colorScheme: ColorScheme.fromSeed(seedColor: marianumRed), colorScheme: ColorScheme.fromSeed(seedColor: marianumRed),
floatingActionButtonTheme: const FloatingActionButtonThemeData( floatingActionButtonTheme: const FloatingActionButtonThemeData(
foregroundColor: Colors.white foregroundColor: Colors.white
) ),
); );
} }

View File

@ -104,6 +104,7 @@ dependencies:
connectivity_plus: ^6.0.3 connectivity_plus: ^6.0.3
hydrated_bloc: ^9.1.5 hydrated_bloc: ^9.1.5
dio: ^4.0.6 dio: ^4.0.6
sorted: ^2.1.0
dev_dependencies: dev_dependencies:
flutter_test: flutter_test: