diff --git a/lib/api/marianumcloud/webdav/queries/listFiles/listFilesCache.dart b/lib/api/marianumcloud/webdav/queries/listFiles/listFilesCache.dart index b2f93c6..ea00d01 100644 --- a/lib/api/marianumcloud/webdav/queries/listFiles/listFilesCache.dart +++ b/lib/api/marianumcloud/webdav/queries/listFiles/listFilesCache.dart @@ -1,6 +1,4 @@ import 'dart:convert'; -import 'dart:developer'; - import 'package:marianum_mobile/api/marianumcloud/webdav/queries/listFiles/listFiles.dart'; import 'package:marianum_mobile/api/marianumcloud/webdav/queries/listFiles/listFilesParams.dart'; import 'package:marianum_mobile/api/marianumcloud/webdav/queries/listFiles/listFilesResponse.dart'; @@ -11,21 +9,17 @@ class ListFilesCache extends RequestCache<ListFilesResponse> { ListFilesCache({required onUpdate, required this.path}) : super(RequestCache.cacheNothing, onUpdate) { String cacheName = path.replaceAll(RegExp("[^A-Za-z0-9]"), "_"); //TODO this is very evil, "/ü/" > "___" also "/ä/" > "___" - log(cacheName); - start("MarianumMobile", "wd-folder-$cacheName"); } @override Future<ListFilesResponse> onLoad() async { - log("Loading remote data"); ListFilesResponse data = await ListFiles(ListFilesParams(path)).run(); return data; } @override ListFilesResponse onLocalData(String json) { - log("Loading local data"); return ListFilesResponse.fromJson(jsonDecode(json)); } diff --git a/lib/api/webuntis/webuntisApi.dart b/lib/api/webuntis/webuntisApi.dart index c5e435c..731beb0 100644 --- a/lib/api/webuntis/webuntisApi.dart +++ b/lib/api/webuntis/webuntisApi.dart @@ -1,5 +1,4 @@ import 'dart:convert'; -import 'dart:developer'; import 'package:marianum_mobile/api/apiRequest.dart'; import 'package:http/http.dart' as http; import 'package:marianum_mobile/api/webuntis/webuntisError.dart'; @@ -53,7 +52,6 @@ abstract class WebuntisApi extends ApiRequest { } Future<http.Response> post(String data, Map<String, String>? headers) async { - log("POST: $endpoint\n$data"); return await http .post(endpoint, body: data, headers: headers) .timeout( diff --git a/lib/app.dart b/lib/app.dart index 8aa19d5..3333d24 100644 --- a/lib/app.dart +++ b/lib/app.dart @@ -19,6 +19,25 @@ class App extends StatefulWidget { class _AppState extends State<App> { int currentPage = 0; + late AppBar _appBar; + + void setAppBar(BuildContext context, AppBar? appBar) { + setState(() { + _appBar = appBar ?? AppBar( + title: const Text("Marianum Fulda"), + actions: <Widget>[ + IconButton( + padding: const EdgeInsets.only(right: 15), + icon: const Icon(Icons.settings), + onPressed: () { + Navigator.push(context, MaterialPageRoute(builder: (context) => const Settings())); + }, + ) + ], + ); + }); + setState(() {}); + } @override void initState() { @@ -33,6 +52,8 @@ class _AppState extends State<App> { Provider.of<ChatListProps>(context, listen: false).run(); }); + setAppBar(context, null); + super.initState(); } @@ -41,18 +62,7 @@ class _AppState extends State<App> { final PageController pageController = PageController(); return Scaffold( resizeToAvoidBottomInset: false, - appBar: AppBar( - title: const Text("Marianum Fulda"), - actions: <Widget>[ - IconButton( - padding: const EdgeInsets.only(right: 15), - icon: const Icon(Icons.settings), - onPressed: () { - Navigator.push(context, MaterialPageRoute(builder: (context) => const Settings())); - }, - ) - ], - ), + appBar: _appBar, body: Column( children: [ Visibility( @@ -66,11 +76,11 @@ class _AppState extends State<App> { Flexible( child: PageView( controller: pageController, - children: const [ - Timetable(), - ChatList(), - Files(), - Overhang(), + children: [ + const Timetable(), + const ChatList(), + Files(setAppBar), + const Overhang(), ], onPageChanged: (page) { setState(() { @@ -132,6 +142,7 @@ class _AppState extends State<App> { currentIndex: currentPage, onTap: (item) { + setAppBar(context, null); setState(() { currentPage = item; pageController.jumpToPage(item); diff --git a/lib/data/files/filesProps.dart b/lib/data/files/filesProps.dart index ec0e577..eb6f0cd 100644 --- a/lib/data/files/filesProps.dart +++ b/lib/data/files/filesProps.dart @@ -1,12 +1,18 @@ -import 'dart:developer'; - import 'package:marianum_mobile/api/apiResponse.dart'; import 'package:marianum_mobile/api/marianumcloud/webdav/queries/listFiles/listFilesCache.dart'; import 'package:marianum_mobile/api/marianumcloud/webdav/queries/listFiles/listFilesResponse.dart'; import 'package:marianum_mobile/data/dataHolder.dart'; +extension ExtendedList on List { + T indexOrNull<T>(int index) => index +1 <= length ? this[index] : null; + T firstOrNull<T>() => isEmpty ? null : first; + T lastOrNull<T>() => isEmpty ? null : last; +} + class FilesProps extends DataHolder { - String _path = "/"; + List<String> folderPath = List<String>.empty(growable: true); + String currentFolderName = "Home"; + String? backPath; ListFilesResponse? _listFilesResponse; ListFilesResponse get listFilesResponse => _listFilesResponse!; @@ -18,21 +24,26 @@ class FilesProps extends DataHolder { @override void run() { + _listFilesResponse = null; notifyListeners(); ListFilesCache( - path: _path, + path: folderPath.isEmpty ? "/" : folderPath.join("/"), onUpdate: (ListFilesResponse data) => { - log("Got cache response"), _listFilesResponse = data, notifyListeners(), } ); } - void setPath(String path) { - _listFilesResponse = null; - _path = path; + void enterFolder(String name) { + folderPath.add(name); + currentFolderName = name; run(); } + void popFolder() { + folderPath.removeLast(); + if(folderPath.isEmpty) currentFolderName = "Home"; + run(); + } } \ No newline at end of file diff --git a/lib/screen/pages/files/files.dart b/lib/screen/pages/files/files.dart index 87a3e83..86fd567 100644 --- a/lib/screen/pages/files/files.dart +++ b/lib/screen/pages/files/files.dart @@ -1,19 +1,15 @@ - -import 'dart:developer'; - import 'package:filesize/filesize.dart'; import 'package:flutter/material.dart'; import 'package:jiffy/jiffy.dart'; import 'package:marianum_mobile/api/marianumcloud/webdav/queries/listFiles/cacheableFile.dart'; -import 'package:marianum_mobile/api/marianumcloud/webdav/queries/listFiles/listFilesParams.dart'; +import 'package:marianum_mobile/widget/errorView.dart'; import 'package:provider/provider.dart'; -import '../../../api/marianumcloud/webdav/queries/listFiles/listFiles.dart'; -import '../../../api/marianumcloud/webdav/queries/listFiles/listFilesResponse.dart'; import '../../../data/files/filesProps.dart'; class Files extends StatefulWidget { - const Files({Key? key}) : super(key: key); + Function appBar; + Files(this.appBar, {Key? key}) : super(key: key); @override State<Files> createState() => _FilesState(); @@ -23,23 +19,37 @@ class _FilesState extends State<Files> { @override void initState() { + super.initState(); + WidgetsBinding.instance.addPostFrameCallback((timeStamp) { Provider.of<FilesProps>(context, listen: false).run(); }); + } - super.initState(); - + void updateAppBar(FilesProps props) { + WidgetsBinding.instance.addPostFrameCallback((timeStamp) { + widget.appBar(context, AppBar( + leading: BackButton( + onPressed: () { + updateAppBar(props); + props.popFolder(); + }, + ), + title: Text(props.currentFolderName), + )); + }); } @override Widget build(BuildContext context) { - Future<ListFilesResponse> files = ListFiles(ListFilesParams("/")).run(); - files.then((value) => log(value.toJson().toString())); - return Consumer<FilesProps>( builder: (context, value, child) { if(value.primaryLoading()) return const Center(child: CircularProgressIndicator()); + if(value.listFilesResponse.files.isEmpty) { + return const ErrorView(text: "Der Ordner ist leer", icon: Icons.folder_off_outlined); + } + return ListView.builder( itemCount: value.listFilesResponse.files.length, itemBuilder: (context, index) { @@ -50,61 +60,43 @@ class _FilesState extends State<Files> { subtitle: file.isDirectory ? Text("geändert ${Jiffy(file.modifiedAt).fromNow()}") : Text("${filesize(file.size)}, ${Jiffy(file.modifiedAt).fromNow()}}"), trailing: Icon(file.isDirectory ? Icons.arrow_right : Icons.open_in_new), onTap: () { + FilesProps props = Provider.of<FilesProps>(context, listen: false); + updateAppBar(props); if(file.isDirectory) { - Provider.of<FilesProps>(context, listen: false).setPath(file.path); + props.enterFolder(file.name); + } else { + //TODO implement file download / view + showDialog(context: context, builder: (context) { + return const AlertDialog( + title: Text("Datei öffnen"), + content: Text("Das öffnen von Dateien ist noch nicht implementiert!"), + ); + }); } }, + onLongPress: () { + showModalBottomSheet<void>( + context: context, + builder: (context) { + return ListView( + children: [ + ListTile( + leading: const Icon(Icons.delete), + title: Text("'${file.name}' Löschen"), + ), + const ListTile( + leading: Icon(Icons.share), + title: Text("Teilen"), + ) + ], + ); + }, + ); + }, ); }, ); } ); - - // return Consumer<FilesProps>( - // builder: (context, data, child) { - // - // if(data.primaryLoading()) { - // return const Center(child: CircularProgressIndicator()); - // } - // - // List<ListTile> entries = List<ListTile>.empty(growable: true); - // - // data.listFilesResponse.files.forEach((element) { - // entries.add(ListTile( - // title: Text(element.name ?? "?"), - // leading: Icon(element.isDir ?? false ? Icons.folder : Icons.file_copy_outlined), - // onTap: () { - // if(element.isDir ?? false) { - // // TODO: Open Folder - // } else { - // // TODO: Open an File - // } - // }, - // - // onLongPress: () { - // showModalBottomSheet<void>( - // context: context, - // builder: (context) { - // return ListView( - // children: [ - // ListTile( - // leading: const Icon(Icons.delete), - // title: Text("'${element.name?.replaceRange(20, element.name?.length, " ...")}' Löschen"), - // ), - // const ListTile( - // leading: Icon(Icons.share), - // title: Text("Teilen"), - // ) - // ], - // ); - // }, - // ); - // }, - // )); - // }); - // - // return ListView(children: entries); - // }, - // ); } } diff --git a/lib/widget/offlineError.dart b/lib/widget/errorView.dart similarity index 78% rename from lib/widget/offlineError.dart rename to lib/widget/errorView.dart index a21e61a..4a04f3a 100644 --- a/lib/widget/offlineError.dart +++ b/lib/widget/errorView.dart @@ -1,9 +1,9 @@ import 'package:flutter/material.dart'; -class OfflineBanner extends StatelessWidget { +class ErrorView extends StatelessWidget { final IconData icon; final String text; - const OfflineBanner({Key? key, this.icon = Icons.report_gmailerrorred, this.text = "Es ist ein Fehler aufgetreten!"}) : super(key: key); + const ErrorView({Key? key, this.icon = Icons.report_gmailerrorred, this.text = "Es ist ein Fehler aufgetreten!"}) : super(key: key); @override Widget build(BuildContext context) {