added upload with multiple files #61

Merged
MineTec merged 7 commits from develop-uploadMultipleFiles into develop 2024-04-09 08:21:55 +00:00
5 changed files with 376 additions and 278 deletions
Showing only changes of commit d8c72a5d28 - Show all commits

View File

@ -65,9 +65,7 @@ class SortOptions {
) )
}; };
static BetterSortOption getOption(SortOption option) { static BetterSortOption getOption(SortOption option) => options[option]!;
return options[option]!;
}
} }
class _FilesState extends State<Files> { class _FilesState extends State<Files> {
@ -99,7 +97,7 @@ class _FilesState extends State<Files> {
); );
} }
void mediaUpload(List<String>? paths) async { Future<void> mediaUpload(List<String>? paths) async {
if(paths == null) return; if(paths == null) return;
pushScreen( pushScreen(

View File

@ -43,21 +43,15 @@ class _FilesUploadDialogState extends State<FilesUploadDialog> {
super.initState(); super.initState();
_uploadableFiles = widget.filePaths.map((filePath) { _uploadableFiles = widget.filePaths.map((filePath) {
String fileName = filePath.split(Platform.pathSeparator).last; var fileName = filePath.split(Platform.pathSeparator).last;
return UploadableFile(filePath, fileName); return UploadableFile(filePath, fileName);
}).toList(); }).toList();
/*_uploadableFiles.addAll(widget.filePaths.map((filePath) {
String fileName = filePath.split(Platform.pathSeparator).last;
return UploadableFile(filePath, fileName);
}));*/
} }
Pupsi marked this conversation as resolved Outdated

was ist das für ein error code? Ein http status code?

Falls ja variable enstprechend umbenennen und in der message auch angeben

was ist das für ein error code? Ein http status code? Falls ja variable enstprechend umbenennen und in der message auch angeben
void showHttpErrorCode(int httpErrorCode){ void showHttpErrorCode(int httpErrorCode){
Pupsi marked this conversation as resolved
Review

ungenutzer code raus

ungenutzer code raus
showDialog( showDialog(
context: context, context: context,
builder: (BuildContext context) { builder: (BuildContext context) => AlertDialog(
return AlertDialog(
title: const Text('Ein Fehler ist aufgetreten'), title: const Text('Ein Fehler ist aufgetreten'),
contentPadding: const EdgeInsets.all(10), contentPadding: const EdgeInsets.all(10),
content: Text('Error code: $httpErrorCode'), content: Text('Error code: $httpErrorCode'),
@ -67,12 +61,11 @@ class _FilesUploadDialogState extends State<FilesUploadDialog> {
child: const Text('Schließen', textAlign: TextAlign.center), child: const Text('Schließen', textAlign: TextAlign.center),
), ),
], ],
); )
}
); );
} }
void uploadFiles({bool override = false}) async { Future<void> uploadFiles({bool override = false}) async {
setState(() { setState(() {
Pupsi marked this conversation as resolved
Review

dein ehemaliger name upload ist in diesem kontext doch besser, vielleicht auch uploadFiles

dein ehemaliger name `upload` ist in diesem kontext doch besser, vielleicht auch `uploadFiles`
_isUploading = true; _isUploading = true;
_infoText = 'Vorbereiten'; _infoText = 'Vorbereiten';
@ -81,41 +74,33 @@ class _FilesUploadDialogState extends State<FilesUploadDialog> {
} }
}); });
Pupsi marked this conversation as resolved
Review

setState für jede datei auszuführen ist unnötig und ressourcenintensiv.

Mit setState auf zeile 70 verbinden und inline schreiben mit

_uploadableFiles.foreach(f => f.isConflicting = false)

setState für jede datei auszuführen ist unnötig und ressourcenintensiv. Mit setState auf zeile 70 verbinden und inline schreiben mit `_uploadableFiles.foreach(f => f.isConflicting = false)`
WebDavClient webdavClient = await WebdavApi.webdav; var webdavClient = await WebdavApi.webdav;
if (!override) { if (!override) {
List<WebDavResponse> result = (await webdavClient.propfind(PathUri.parse(widget.remotePath))).responses; var result = (await webdavClient.propfind(PathUri.parse(widget.remotePath))).responses;
List<UploadableFile> conflictingFiles = _uploadableFiles.where((file) { var conflictingFiles = _uploadableFiles.where((file) {
String fileName = file.fileName; var fileName = file.fileName;
if (result.any((element) => Uri.decodeComponent(element.href!).endsWith('/$fileName'))) { return result.any((element) => Uri.decodeComponent(element.href!).endsWith('/$fileName'));
// konflikt
return true;
}
return false;
}).toList(); }).toList();
if(conflictingFiles.isNotEmpty) { if(conflictingFiles.isNotEmpty) {
bool replaceFiles = await showDialog( bool replaceFiles = await showDialog(
Pupsi marked this conversation as resolved
Review

umschreiben in fluente schreibweise

conflictingFiles = _uploadableFiles.where(...)
umschreiben in fluente schreibweise ``` conflictingFiles = _uploadableFiles.where(...) ```
context: context, context: context,
barrierDismissible: false, barrierDismissible: false,
builder: (context) { builder: (context) => AlertDialog(
Pupsi marked this conversation as resolved Outdated

einfaches return

return result.any((element) => Uri.decodeComponent(element.href!).endsWith('/$fileName'))

ggf auch ohne return als pfeilsyntax

einfaches return `return result.any((element) => Uri.decodeComponent(element.href!).endsWith('/$fileName'))` ggf auch ohne return als pfeilsyntax
return AlertDialog(
contentPadding: const EdgeInsets.all(10), contentPadding: const EdgeInsets.all(10),
title: const Text('Konflikt', textAlign: TextAlign.center), title: const Text('Konflikt', textAlign: TextAlign.center),
content: conflictingFiles.length == 1 ? content: conflictingFiles.length == 1 ?
Text( Text(
'Eine Datei mit dem Namen "${conflictingFiles.map((e) => e.fileName).first}" existiert bereits.\n' 'Eine Datei mit dem Namen "${conflictingFiles.map((e) => e.fileName).first}" existiert bereits.',
'(Datei ${_uploadableFiles.indexOf(conflictingFiles.first)+1})',
textAlign: TextAlign.left, textAlign: TextAlign.left,
) : ) :
SingleChildScrollView( SingleChildScrollView(
child: Text( child: Text(
'${conflictingFiles.length} Dateien mit den Namen: ${conflictingFiles.map((e) => '\n${e.fileName}').join(', ')}\n existieren bereits.\n' '${conflictingFiles.length} Dateien mit folgenden Namen existieren bereits: \n${conflictingFiles.map((e) => '\n - ${e.fileName}').join('')}',
'(Dateien ${conflictingFiles.map((e) => _uploadableFiles.indexOf(e)+1).join(', ')})',
textAlign: TextAlign.left, textAlign: TextAlign.left,
), ),
), ),
actions: [ actions: [
TextButton( TextButton(
onPressed: () { onPressed: () {
@ -127,55 +112,52 @@ class _FilesUploadDialogState extends State<FilesUploadDialog> {
onPressed: () { onPressed: () {
showDialog( showDialog(
context: context, context: context,
builder: (context) { builder: (context) => ConfirmDialog(
return ConfirmDialog( title: 'Bestätigen?',
title: 'Bestätigen', content: 'Bist du sicher, dass du ${conflictingFiles.length} Dateien überschreiben möchtest?',
content: 'Bist du sicher, dass du ${conflictingFiles.map((e) => e.fileName).toList()} überschreiben möchtest?', onConfirm: () {
onConfirm: () { Navigator.pop(context, true);
Pupsi marked this conversation as resolved Outdated

Umbenennen

`Umbenennen`
Outdated
Review

Passt Bearbeiten nicht besser? Es gibt ja dann auch noch die Möglichkeit neben dem Umbenennen auch die Datei zu löschen oder komplett abzubrechen.

Passt Bearbeiten nicht besser? Es gibt ja dann auch noch die Möglichkeit neben dem Umbenennen auch die Datei zu löschen oder komplett abzubrechen.
Navigator.pop(context, true); },
}, confirmButton: 'Ja',
confirmButton: 'Ja', cancelButton: 'Nein',
cancelButton: 'Nein', ),
);
}
); );
Pupsi marked this conversation as resolved Outdated

Überschreiben

diese Aktion sollte nochmal ein "Bist du sicher" dialog öffnen. Du kannst hierzu den bestehenden ConfirmDialog verwenden

`Überschreiben` diese Aktion sollte nochmal ein "Bist du sicher" dialog öffnen. Du kannst hierzu den bestehenden ConfirmDialog verwenden
}, },
child: const Text('Überschreiben', textAlign: TextAlign.center), child: const Text('Überschreiben', textAlign: TextAlign.center),
), ),
], ],
); )
}
); );
if(!replaceFiles) { if(!replaceFiles) {
for (var element in conflictingFiles) {
element.isConflicting = true;
}
setState(() { setState(() {
_isUploading = false; _isUploading = false;
_overallProgressValue = 0.0; _overallProgressValue = 0.0;
_infoText = ''; _infoText = '';
for (var element in conflictingFiles) {
element.isConflicting = true;
}
}); });
return; return;
} }
} }
} }
List<String> uploadetFilePaths = []; var uploadetFilePaths = <String>[];
for (var file in _uploadableFiles) { for (var file in _uploadableFiles) {
String fileName = file.fileName; var fileName = file.fileName;
String filePath = file.filePath; var filePath = file.filePath;
Pupsi marked this conversation as resolved Outdated

state variablen in setState ändern

state variablen in setState ändern
if(widget.uniqueNames) fileName = '${fileName.split('.').first}-${const Uuid().v4()}.${fileName.split('.').last}'; if(widget.uniqueNames) fileName = '${fileName.split('.').first}-${const Uuid().v4()}.${fileName.split('.').last}';
String fullRemotePath = '${widget.remotePath}/$fileName'; var fullRemotePath = '${widget.remotePath}/$fileName';
setState(() { setState(() {
_infoText = '${_uploadableFiles.indexOf(file) + 1}/${_uploadableFiles.length}'; _infoText = '${_uploadableFiles.indexOf(file) + 1}/${_uploadableFiles.length}';
}); });
HttpClientResponse uploadTask = await webdavClient.putFile( var uploadTask = await webdavClient.putFile(
File(filePath), File(filePath),
FileStat.statSync(filePath), FileStat.statSync(filePath),
PathUri.parse(fullRemotePath), PathUri.parse(fullRemotePath),
@ -211,8 +193,7 @@ class _FilesUploadDialogState extends State<FilesUploadDialog> {
} }
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) => Scaffold(
return Scaffold(
appBar: AppBar( appBar: AppBar(
title: const Text('Dateien hochladen'), title: const Text('Dateien hochladen'),
automaticallyImplyLeading: false, automaticallyImplyLeading: false,
@ -318,13 +299,25 @@ class _FilesUploadDialogState extends State<FilesUploadDialog> {
onPressed: () => uploadFiles(override: widget.uniqueNames), onPressed: () => uploadFiles(override: widget.uniqueNames),
child: const Text('Hochladen'), child: const Text('Hochladen'),
), ),
child: Stack( child: Visibility(
alignment: Alignment.center, visible: _infoText.length < 5,
children: [ replacement: Row(
CircularProgressIndicator(value: _overallProgressValue), children: [
Center(child: Text(_infoText)), Text(_infoText),
], const SizedBox(width: 15),
CircularProgressIndicator(value: _overallProgressValue),
],
),
child: Stack(
alignment: Alignment.center,
children: [
CircularProgressIndicator(value: _overallProgressValue),
Center(child: Text(_infoText)),
],
),
), ),
), ),
], ],
), ),
@ -333,5 +326,4 @@ class _FilesUploadDialogState extends State<FilesUploadDialog> {
), ),
), ),
); );
}
} }

View File

@ -35,7 +35,7 @@ class _ChatTextfieldState extends State<ChatTextfield> {
void share(String shareFolder, List<String> filePaths) { void share(String shareFolder, List<String> filePaths) {
for (var element in filePaths) { for (var element in filePaths) {
String fileName = element.split(Platform.pathSeparator).last; var fileName = element.split(Platform.pathSeparator).last;
FileSharingApi().share(FileSharingApiParams( FileSharingApi().share(FileSharingApiParams(
shareType: 10, shareType: 10,
shareWith: widget.sendToToken, shareWith: widget.sendToToken,
@ -44,10 +44,10 @@ class _ChatTextfieldState extends State<ChatTextfield> {
} }
} }
void mediaUpload(List<String>? paths) async { Future<void> mediaUpload(List<String>? paths) async {
if (paths == null) return; if (paths == null) return;
String shareFolder = 'MarianumMobile'; var shareFolder = 'MarianumMobile';
WebdavApi.webdav.then((webdav) { WebdavApi.webdav.then((webdav) {
webdav.mkcol(PathUri.parse('/$shareFolder')); webdav.mkcol(PathUri.parse('/$shareFolder'));
}); });