Added inline file download progressbar, handle OpenFile directly and handle errors

This commit is contained in:
Elias Müller 2023-03-12 17:23:55 +01:00
parent 58bbfc6329
commit d21dc26a18
5 changed files with 146 additions and 144 deletions
lib
api/marianumcloud/webdav/queries/listFiles
screen/pages/files

@ -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;

@ -8,9 +8,9 @@ part of 'cacheableFile.dart';
CacheableFile _$CacheableFileFromJson(Map<String, dynamic> 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?,

@ -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<FileDownload> createState() => _FileDownloadState();
}
class _FileDownloadState extends State<FileDownload> {
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();
},
)
],
);
}
}

@ -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<FileElement> createState() => _FileElementState();
}
class _FileElementState extends State<FileElement> {
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<OpenResult> 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<FilesProps>(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<void>(
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"),
)
],
);
},
);
},
);
}
}

@ -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<Files> {
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<FilesProps>(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<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 FileElement(file, updateAppBar);
},
);
}