import 'dart:developer'; import 'dart:io'; import 'package:flutter/material.dart'; import 'package:loader_overlay/loader_overlay.dart'; import 'package:marianum_mobile/api/marianumcloud/webdav/queries/listFiles/cacheableFile.dart'; import 'package:marianum_mobile/screen/pages/files/fileUpload.dart'; import 'package:marianum_mobile/widget/errorView.dart'; import 'package:persistent_bottom_nav_bar/persistent_tab_view.dart'; import '../../../api/marianumcloud/webdav/queries/listFiles/listFilesCache.dart'; import '../../../api/marianumcloud/webdav/queries/listFiles/listFilesResponse.dart'; import '../../../api/marianumcloud/webdav/webdavApi.dart'; import '../../../data/files/filesProps.dart'; import '../../../widget/filePick.dart'; import 'fileElement.dart'; class Files extends StatefulWidget { List path; Files(this.path, {Key? key}) : super(key: key); @override State createState() => _FilesState(); } class BetterSortOption { String displayName; int Function(CacheableFile, CacheableFile) compare; IconData icon; BetterSortOption({required this.displayName, required this.icon, required this.compare}); } enum SortOption { name, date, size } class SortOptions { static Map options = { SortOption.name: BetterSortOption( displayName: "Name", icon: Icons.sort_by_alpha, compare: (CacheableFile a, CacheableFile b) => a.name.compareTo(b.name) ), SortOption.date: BetterSortOption( displayName: "Datum", icon: Icons.more_time_outlined, compare: (CacheableFile a, CacheableFile b) => a.modifiedAt!.compareTo(b.modifiedAt!) ), SortOption.size: BetterSortOption( displayName: "Größe", icon: Icons.monitor_weight, compare: (CacheableFile a, CacheableFile b) { if(a.isDirectory || b.isDirectory) return a.isDirectory ? 1 : 0; if(a.size == null) return 0; if(b.size == null) return 1; return a.size!.compareTo(b.size!); } ) }; static BetterSortOption getOption(SortOption option) { return options[option]!; } } class _FilesState extends State { FilesProps props = FilesProps(); ListFilesResponse? data; SortOption currentSort = SortOption.name; bool currentSortDirection = true; @override void initState() { super.initState(); _query(); } void _query() { ListFilesCache( path: widget.path.isEmpty ? "/" : widget.path.join("/"), onUpdate: (ListFilesResponse d) => { setState(() { data = d; }), } ); } @override Widget build(BuildContext context) { List files = (data?.files.toList() ?? List.empty())..sort(SortOptions.getOption(currentSort).compare); if(currentSortDirection) files = files.reversed.toList(); return Scaffold( appBar: AppBar( title: Text(widget.path.isNotEmpty ? widget.path.last : "Dateien"), actions: [ IconButton( icon: const Icon(Icons.search), onPressed: () => { // TODO implement search }, ), PopupMenuButton( icon: Icon(currentSortDirection ? Icons.text_rotate_up : Icons.text_rotation_down), itemBuilder: (context) { return [true, false].map((e) => PopupMenuItem( value: e, enabled: e != currentSortDirection, child: Row( children: [ Icon(e ? Icons.text_rotate_up : Icons.text_rotation_down, color: Colors.black), const SizedBox(width: 15), Text(e ? "Aufsteigend" : "Absteigend") ], ) )).toList(); }, onSelected: (e) { setState(() { currentSortDirection = e; }); }, ), PopupMenuButton( icon: const Icon(Icons.sort), itemBuilder: (context) { return SortOptions.options.keys.map((key) => PopupMenuItem( value: key, enabled: key != currentSort, child: Row( children: [ Icon(SortOptions.getOption(key).icon, color: Colors.black), const SizedBox(width: 15), Text(SortOptions.getOption(key).displayName) ], ) )).toList(); }, onSelected: (e) { setState(() { currentSort = e; }); }, ), ], ), floatingActionButton: FloatingActionButton( onPressed: () { showDialog(context: context, builder: (context) { return SimpleDialog( children: [ ListTile( leading: const Icon(Icons.folder), title: const Text("Neuer Ordner"), onTap: () { WebdavApi.webdav.then((webdav) { webdav.mkdirs("/MarianumMobileTest"); }); }, ), ListTile( leading: const Icon(Icons.file_open), title: const Text("Aus Dateien auswählen"), onTap: () { context.loaderOverlay.show(); FilePick.documentPick().then((value) { log(value ?? "?"); mediaUpload(value); }); Navigator.of(context).pop(); }, ), ListTile( leading: const Icon(Icons.image), title: const Text("Aus Gallerie auswählen"), onTap: () { context.loaderOverlay.show(); FilePick.galleryPick().then((value) { log(value?.path ?? "?"); mediaUpload(value?.path); }); Navigator.of(context).pop(); }, ), ], ); }); }, child: const Icon(Icons.upload), ), body: data == null ? const Center(child: CircularProgressIndicator()) : data!.files.isEmpty ? const ErrorView(icon: Icons.folder_off_rounded, text: "Der Ordner ist leer") : LoaderOverlay( child: RefreshIndicator( onRefresh: () { _query(); return Future.delayed(const Duration(seconds: 3)); }, child: ListView.builder( itemCount: files.length, itemBuilder: (context, index) { CacheableFile file = files.toList().skip(index).first; return FileElement(file, widget.path); }, ), ) ) ); } void mediaUpload(String? path) async { if(path == null) { context.loaderOverlay.hide(); return; } context.loaderOverlay.show(); File file = File(path); var remotePath = "${widget.path.join("/")}/${file.path.split(Platform.pathSeparator).last}"; PersistentNavBarNavigator.pushNewScreen(context, screen: FileUpload(localPath: path, remotePath: remotePath), withNavBar: false); } }