From d21dc26a18156a6c4351711723c6037b7d35fbc3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Elias=20M=C3=BCller?= Date: Sun, 12 Mar 2023 17:23:55 +0100 Subject: [PATCH] Added inline file download progressbar, handle OpenFile directly and handle errors --- .../queries/listFiles/cacheableFile.dart | 6 +- .../queries/listFiles/cacheableFile.g.dart | 6 +- lib/screen/pages/files/fileDownload.dart | 97 ------------- lib/screen/pages/files/fileElement.dart | 136 ++++++++++++++++++ lib/screen/pages/files/files.dart | 45 +----- 5 files changed, 146 insertions(+), 144 deletions(-) delete mode 100644 lib/screen/pages/files/fileDownload.dart create mode 100644 lib/screen/pages/files/fileElement.dart diff --git a/lib/api/marianumcloud/webdav/queries/listFiles/cacheableFile.dart b/lib/api/marianumcloud/webdav/queries/listFiles/cacheableFile.dart index ab59a9f..56d468d 100644 --- a/lib/api/marianumcloud/webdav/queries/listFiles/cacheableFile.dart +++ b/lib/api/marianumcloud/webdav/queries/listFiles/cacheableFile.dart @@ -14,7 +14,11 @@ class CacheableFile { DateTime? createdAt; DateTime? modifiedAt; - CacheableFile(this.path, this.isDirectory, this.name, {this.mimeType, this.size, this.eTag, this.createdAt, this.modifiedAt}); + @JsonKey(includeFromJson: false, includeToJson: false) + bool currentlyDownloading = false; + + + CacheableFile({required this.path, required this.isDirectory, required this.name, this.mimeType, this.size, this.eTag, this.createdAt, this.modifiedAt}); CacheableFile.fromDavFile(WebDavFile file) { path = file.path; diff --git a/lib/api/marianumcloud/webdav/queries/listFiles/cacheableFile.g.dart b/lib/api/marianumcloud/webdav/queries/listFiles/cacheableFile.g.dart index 1e09407..99ba008 100644 --- a/lib/api/marianumcloud/webdav/queries/listFiles/cacheableFile.g.dart +++ b/lib/api/marianumcloud/webdav/queries/listFiles/cacheableFile.g.dart @@ -8,9 +8,9 @@ part of 'cacheableFile.dart'; CacheableFile _$CacheableFileFromJson(Map json) => CacheableFile( - json['path'] as String, - json['isDirectory'] as bool, - json['name'] as String, + path: json['path'] as String, + isDirectory: json['isDirectory'] as bool, + name: json['name'] as String, mimeType: json['mimeType'] as String?, size: json['size'] as int?, eTag: json['eTag'] as String?, diff --git a/lib/screen/pages/files/fileDownload.dart b/lib/screen/pages/files/fileDownload.dart deleted file mode 100644 index 7ef2fd0..0000000 --- a/lib/screen/pages/files/fileDownload.dart +++ /dev/null @@ -1,97 +0,0 @@ -import 'dart:developer'; -import 'dart:io'; - -import 'package:better_open_file/better_open_file.dart'; -import 'package:flowder/flowder.dart'; -import 'package:flutter/cupertino.dart'; -import 'package:flutter/material.dart'; -import 'package:marianum_mobile/api/marianumcloud/webdav/webdavApi.dart'; -import 'package:path_provider/path_provider.dart'; - -class FileDownload extends StatefulWidget { - String source; - String name; - FileDownload(this.source, this.name, {Key? key}) : super(key: key); - - @override - State createState() => _FileDownloadState(); -} - -class _FileDownloadState extends State { - late DownloaderCore core; - - void download(String remotePath, String name) async { - Directory paths = await getApplicationDocumentsDirectory(); - - String local = paths.path + Platform.pathSeparator + name; - - DownloaderUtils options = DownloaderUtils( - progressCallback: (current, total) { - final progress = (current / total) * 100; - setState(() => { - percent = progress, - }); - }, - file: File(local), - progress: ProgressImplementation(), - deleteOnCancel: true, - onDone: () { - Navigator.of(context).pop(); - showDialog(context: context, builder: (context) { - return AlertDialog( - icon: const Icon(Icons.link), - title: const Text("Dateipfad"), - content: Text(local), - actions: [ - TextButton( - child: Text("Öffnen mit"), - onPressed: () { - OpenFile.open(local).then((value) => () { - log("Result: ${value.toString()}"); - }); - }, - ) - ], - ); - }); - }, - ); - - log(local); - - core = await Flowder.download( - "${await WebdavApi.webdavConnectString}$remotePath", - options, - ); - } - - double percent = 0; - - @override - void initState() { - super.initState(); - log("Downloading file: Source(${widget.source}), Name(${widget.name})"); - download(widget.source, widget.name); - } - - @override - Widget build(BuildContext context) { - return AlertDialog( - title: const Text("Download"), - content: ListTile( - leading: const Icon(Icons.download), - title: LinearProgressIndicator(value: percent/100), - trailing: Text("${percent.round()}%"), - ), - actions: [ - TextButton( - child: const Text("Abbrechen"), - onPressed: () => () { - if(!core.isCancelled) core.cancel(); - Navigator.of(context, rootNavigator: true).pop(); - }, - ) - ], - ); - } -} diff --git a/lib/screen/pages/files/fileElement.dart b/lib/screen/pages/files/fileElement.dart new file mode 100644 index 0000000..9d2fba7 --- /dev/null +++ b/lib/screen/pages/files/fileElement.dart @@ -0,0 +1,136 @@ +import 'dart:developer'; +import 'dart:io'; + +import 'package:better_open_file/better_open_file.dart'; +import 'package:filesize/filesize.dart'; +import 'package:flowder/flowder.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:jiffy/jiffy.dart'; +import 'package:marianum_mobile/api/marianumcloud/webdav/queries/listFiles/cacheableFile.dart'; +import 'package:path_provider/path_provider.dart'; +import 'package:provider/provider.dart'; + +import '../../../api/marianumcloud/webdav/webdavApi.dart'; +import '../../../data/files/filesProps.dart'; + +class FileElement extends StatefulWidget { + CacheableFile file; + Function updateAppBar; + FileElement(this.file, this.updateAppBar, {Key? key}) : super(key: key); + + @override + State createState() => _FileElementState(); +} + +class _FileElementState extends State { + late DownloaderCore core; + double percent = 0; + + void download(String remotePath, String name) async { + + Directory paths = await getApplicationDocumentsDirectory(); + + String local = paths.path + Platform.pathSeparator + name; + + DownloaderUtils options = DownloaderUtils( + progressCallback: (current, total) { + final progress = (current / total) * 100; + setState(() => { + percent = progress, + }); + }, + file: File(local), + progress: ProgressImplementation(), + deleteOnCancel: true, + onDone: () { + Future result = OpenFile.open(local); + + result.then((value) => { + if(value.type != ResultType.done) { + showDialog(context: context, builder: (context) { + return AlertDialog( + title: Text("Download"), + content: Text(value.message), + ); + }) + } + }); + + widget.file.currentlyDownloading = false; + percent = 0; + }, + ); + + log(local); + + core = await Flowder.download( + "${await WebdavApi.webdavConnectString}$remotePath", + options, + ); + } + + Widget getSubtitle() { + if(widget.file.currentlyDownloading) { + return Row( + children: [ + Container( + margin: const EdgeInsets.only(right: 10), + child: const Text("Download:"), + ), + Expanded( + child: LinearProgressIndicator(value: percent/100), + ), + Container( + margin: const EdgeInsets.only(left: 10), + child: Text("${percent.round()}%"), + ), + ], + ); + } + return widget.file.isDirectory ? Text("geändert ${Jiffy(widget.file.modifiedAt).fromNow()}") : Text("${filesize(widget.file.size)}, ${Jiffy(widget.file.modifiedAt).fromNow()}"); + } + + @override + Widget build(BuildContext context) { + return ListTile( + leading: Icon(widget.file.isDirectory ? Icons.folder : Icons.file_open_outlined), + title: Text(widget.file.name), + subtitle: getSubtitle(), + trailing: Icon(widget.file.isDirectory ? Icons.arrow_right : Icons.open_in_browser), + onTap: () { + FilesProps props = Provider.of(context, listen: false); + widget.updateAppBar(props); + if(widget.file.isDirectory) { + props.enterFolder(widget.file.name); + } else { + setState(() { + widget.file.currentlyDownloading = true; + }); + + download(widget.file.path, widget.file.name); + + } + }, + onLongPress: () { + showModalBottomSheet( + context: context, + builder: (context) { + return ListView( + children: [ + ListTile( + leading: const Icon(Icons.delete), + title: Text("'${widget.file.name}' Löschen"), + ), + const ListTile( + leading: Icon(Icons.share), + title: Text("Teilen"), + ) + ], + ); + }, + ); + }, + ); + } +} diff --git a/lib/screen/pages/files/files.dart b/lib/screen/pages/files/files.dart index 0a5a368..f3750f9 100644 --- a/lib/screen/pages/files/files.dart +++ b/lib/screen/pages/files/files.dart @@ -1,14 +1,11 @@ -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/screen/pages/files/fileDownload.dart'; import 'package:marianum_mobile/widget/errorView.dart'; import 'package:provider/provider.dart'; import '../../../data/files/filesProps.dart'; +import 'fileElement.dart'; class Files extends StatefulWidget { Function appBar; @@ -57,45 +54,7 @@ class _FilesState extends State { itemCount: value.listFilesResponse.files.length, itemBuilder: (context, index) { CacheableFile file = value.listFilesResponse.files.skip(index).first; - return ListTile( - leading: Icon(file.isDirectory ? Icons.folder : Icons.file_open_outlined), - title: Text(file.name), - 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(context, listen: false); - updateAppBar(props); - if(file.isDirectory) { - props.enterFolder(file.name); - } else { - //TODO implement file download / view - log(file.path); - - showDialog(context: context, builder: (context) { - return FileDownload(file.path, file.name); - }); - } - }, - onLongPress: () { - showModalBottomSheet( - 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 FileElement(file, updateAppBar); }, ); }