import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:persistent_bottom_nav_bar_v2/persistent_bottom_nav_bar_v2.dart'; import '../../../routing/app_routes.dart'; import '../../../share_intent/pending_share.dart'; import '../../../share_intent/share_intent_listener.dart'; import '../../../state/app/infrastructure/loadable_state/loadable_state.dart'; import '../../../state/app/infrastructure/loadable_state/view/loadable_state_consumer.dart'; import '../../../state/app/infrastructure/utility_widgets/bloc_module.dart'; import '../../../state/app/modules/files/bloc/files_bloc.dart'; import '../../../state/app/modules/files/bloc/files_state.dart'; import '../../../state/app/modules/settings/bloc/settings_cubit.dart'; import '../../../widget/placeholder_view.dart'; import '../files/data/sort_options.dart'; import '../files/files_upload_dialog.dart'; import '../files/widgets/add_file_menu.dart'; import '../files/widgets/files_sort_actions.dart'; class ShareFolderPicker extends StatelessWidget { final PendingShare share; const ShareFolderPicker({super.key, required this.share}); @override Widget build(BuildContext context) => BlocModule>( create: (_) => FilesBloc(), child: (context, _, _) => _ShareFolderPickerView(share: share), ); } class _ShareFolderPickerView extends StatefulWidget { final PendingShare share; const _ShareFolderPickerView({required this.share}); @override State<_ShareFolderPickerView> createState() => _ShareFolderPickerViewState(); } class _ShareFolderPickerViewState extends State<_ShareFolderPickerView> { late final SettingsCubit _settings; late SortOption _currentSort; late bool _ascending; @override void initState() { super.initState(); _settings = context.read(); _currentSort = _settings.val().fileSettings.sortBy; _ascending = _settings.val().fileSettings.ascending; } void _enter(FilesBloc bloc, List currentPath, String folderName) { bloc.setPath([...currentPath, folderName]); } void _goUp(FilesBloc bloc, List currentPath) { if (currentPath.isEmpty) return; bloc.setPath(currentPath.sublist(0, currentPath.length - 1)); } Future _uploadHere(List currentPath) async { await pushScreen( context, withNavBar: false, screen: FilesUploadDialog( filePaths: widget.share.filePaths, remotePath: currentPath.join('/'), onUploadFinished: (_) => _afterUploaded(currentPath), ), ); } void _afterUploaded(List targetPath) { ShareIntentListener.instance.clear(); if (!mounted) return; Navigator.of(context).popUntil((route) => route.isFirst); AppRoutes.openFolder(context, targetPath); } @override Widget build(BuildContext context) { final bloc = context.read(); return BlocBuilder>( buildWhen: (a, b) => a.data?.currentPath != b.data?.currentPath, builder: (_, outerState) { final currentPath = outerState.data?.currentPath ?? const []; return PopScope( // Back navigates one level up while inside a sub-folder; only the // root level actually closes the picker. Matches the standard // files-app pattern and keeps the AppBar back-arrow consistent // with the chat picker. canPop: currentPath.isEmpty, onPopInvokedWithResult: (didPop, _) { if (didPop) return; if (currentPath.isNotEmpty) _goUp(bloc, currentPath); }, child: _buildScaffold(context, bloc, currentPath), ); }, ); } Widget _buildScaffold( BuildContext context, FilesBloc bloc, List currentPath, ) => Scaffold( appBar: AppBar( title: Text( currentPath.isEmpty ? 'Ordner wählen' : '/${currentPath.join('/')}', overflow: TextOverflow.ellipsis, ), actions: [ IconButton( icon: const Icon(Icons.create_new_folder_outlined), tooltip: 'Ordner erstellen', onPressed: () => showCreateFolderDialog(context, bloc), ), FilesSortActions( currentSort: _currentSort, ascending: _ascending, onDirectionChanged: (e) { setState(() { _ascending = e; _settings.val(write: true).fileSettings.ascending = e; }); }, onSortChanged: (e) { setState(() { _currentSort = e; _settings.val(write: true).fileSettings.sortBy = e; }); }, ), ], ), floatingActionButton: FloatingActionButton.extended( heroTag: 'shareUploadHere', onPressed: () => _uploadHere(currentPath), icon: const Icon(Icons.upload), label: const Text('Hier hochladen'), ), body: LoadableStateConsumer( isReady: (state) => state.listing != null, child: (state, _) { final listing = state.listing!; final entries = listing.sortBy( sortOption: _currentSort, foldersToTop: _settings.val().fileSettings.sortFoldersToTop, reversed: _ascending, ); if (entries.isEmpty) { return PlaceholderView( icon: Icons.folder_off_rounded, text: state.currentPath.isEmpty ? 'Leer. Du kannst hier direkt hochladen.' : 'Ordner ist leer. Du kannst hier hochladen.', ); } return ListView.builder( padding: EdgeInsets.zero, itemCount: entries.length, itemBuilder: (context, i) { final entry = entries[i]; if (entry.isDirectory) { return ListTile( leading: const Icon(Icons.folder_outlined), title: Text(entry.name), trailing: const Icon(Icons.chevron_right), onTap: () => _enter(bloc, state.currentPath, entry.name), ); } return ListTile( enabled: false, leading: const Icon(Icons.description_outlined), title: Text(entry.name), ); }, ); }, ), ); }