diff --git a/client/lib/app.dart b/client/lib/app.dart index c44a2e0c..2be0b769 100644 --- a/client/lib/app.dart +++ b/client/lib/app.dart @@ -2,25 +2,17 @@ import 'package:flutter/material.dart'; import 'package:flutter_state_notifier/flutter_state_notifier.dart'; import 'package:go_router/go_router.dart'; import 'package:offtheline/offtheline.dart'; -import 'package:phylum/folder_view.dart'; import 'package:phylum/home_page.dart'; import 'package:phylum/libphylum/phylum_account.dart'; import 'package:provider/provider.dart'; final _router = GoRouter( routes: [ - ShellRoute( - builder: (context, state, child) => NavScaffold(child: child), - routes: [ - GoRoute(name: 'home', path: '/', builder: (context, state) => const HomePage()), - GoRoute( - name: 'dir', - path: '/dir/:id', - builder: (context, state) { - return FolderView(id: state.pathParameters['id']!); - }), - ], - ) + GoRoute( + name: 'home', + path: '/', + builder: (context, state) => const HomePage(), + ), ], ); @@ -57,20 +49,3 @@ class _AppContent extends StatelessWidget { ); } } - -class NavScaffold extends StatelessWidget { - final Widget child; - const NavScaffold({super.key, required this.child}); - - @override - Widget build(BuildContext context) { - final router = GoRouter.of(context); - return Scaffold( - appBar: AppBar( - title: const Text('Phylum'), - leading: router.canPop() ? BackButton(onPressed: router.pop) : null, - ), - body: child, - ); - } -} diff --git a/client/lib/folder_view.dart b/client/lib/folder_view.dart index 1a39ab34..cfb86a05 100644 --- a/client/lib/folder_view.dart +++ b/client/lib/folder_view.dart @@ -1,20 +1,78 @@ import 'package:flutter/material.dart'; -import 'package:go_router/go_router.dart'; +import 'package:flutter_state_notifier/flutter_state_notifier.dart'; import 'package:phylum/libphylum/db/db.dart'; import 'package:phylum/libphylum/phylum_account.dart'; import 'package:phylum/libphylum/requests/resource_detail_request.dart'; import 'package:provider/provider.dart'; -class FolderView extends StatefulWidget { - final String id; +class FolderNavigatorState { + final String root; + final List _stack; - const FolderView({super.key, required this.id}); + bool get isRoot => _stack.isEmpty; - @override - State createState() => _FolderViewState(); + String get folderId => isRoot ? root : _stack.last; + + const FolderNavigatorState({required this.root, required List stack}) : _stack = stack; } -class _FolderViewState extends State { +class FolderNavigator extends StateNotifier { + final String root; + + FolderNavigator(this.root) : super(FolderNavigatorState(root: root, stack: const [])); + + bool pop() { + if (state.isRoot) return false; + state = FolderNavigatorState(root: state.root, stack: state._stack.sublist(0, state._stack.length - 1).toList(growable: false)); + return true; + } + + void push(String id) { + state = FolderNavigatorState(root: state.root, stack: [...state._stack, id]); + } +} + +class FolderNavigatorView extends StatelessWidget { + final String root; + + const FolderNavigatorView({super.key, required this.root}); + + @override + Widget build(BuildContext context) { + return StateNotifierProvider( + create: (context) => FolderNavigator(root), + builder: (context, child) => const FolderScaffold(), + ); + } +} + +class FolderScaffold extends StatelessWidget { + const FolderScaffold({super.key}); + + @override + Widget build(BuildContext context) { + final nav = context.watch(); + final folderId = nav.folderId; + return Scaffold( + appBar: AppBar( + title: const Text('Phylum'), + leading: nav.isRoot ? null : BackButton(onPressed: context.read().pop), + ), + body: FolderContentsView(key: ValueKey(folderId), id: folderId), + ); + } +} + +class FolderContentsView extends StatefulWidget { + final String id; + + const FolderContentsView({super.key, required this.id}); + + @override + State createState() => _FolderContentsViewState(); +} + +class _FolderContentsViewState extends State { @override void initState() { super.initState(); @@ -34,20 +92,18 @@ class _FolderViewState extends State { child: Center( child: StreamBuilder( stream: account.datastore.db.managers.resources.filter((f) => f.parent.id.equals(widget.id)).watch(), - builder: (context, snapshot) { - return Column( - children: [ - if (snapshot.hasData) - for (final r in snapshot.data!) - ListTile( - leading: r.getIcon(), - title: Text(r.name), - trailing: r.dir ? null : Text(r.getSizeString()), - onTap: () => context.go('/dir/${r.id}'), - ), - ], - ); - }), + builder: (context, snapshot) => ListView( + children: [ + if (snapshot.hasData) + for (final r in snapshot.data!) + ListTile( + leading: r.getIcon(), + title: Text(r.name), + trailing: r.dir ? null : Text(r.getSizeString()), + onTap: () => context.read().push('/dir/${r.id}'), + ), + ], + )), ), ); } diff --git a/client/lib/home_page.dart b/client/lib/home_page.dart index a3655008..df87d223 100644 --- a/client/lib/home_page.dart +++ b/client/lib/home_page.dart @@ -1,5 +1,5 @@ import 'package:flutter/material.dart'; -import 'package:go_router/go_router.dart'; +import 'package:phylum/folder_view.dart'; import 'package:phylum/libphylum/phylum_account.dart'; import 'package:provider/provider.dart'; @@ -14,14 +14,10 @@ class _HomePageState extends State { @override void initState() { super.initState(); - final account = context.read(); - WidgetsBinding.instance.addPostFrameCallback((t) { - context.replace('/dir/${account.userHome}'); - }); } @override Widget build(BuildContext context) { - return Container(); + return FolderNavigatorView(root: context.read().userHome); } }