added support for simultan downloads in files and talk, support for background downloads, enhanced loading in files with retry
This commit is contained in:
@@ -10,12 +10,13 @@ import '../../../../model/endpoint_data.dart';
|
||||
import '../../../../routing/app_routes.dart';
|
||||
import '../../../../share_intent/remote_file_ref.dart';
|
||||
import '../../../../state/app/modules/nextcloud_capabilities/bloc/nextcloud_capabilities_cubit.dart';
|
||||
import '../../../../utils/download_manager.dart';
|
||||
import '../../../../utils/downloads/download_job.dart';
|
||||
import '../../../../utils/file_clipboard.dart';
|
||||
import '../../../../utils/haptics.dart';
|
||||
import '../../../../widget/centered_leading.dart';
|
||||
import '../../../../widget/confirm_dialog.dart';
|
||||
import '../../../../widget/details_bottom_sheet.dart';
|
||||
import '../../../../widget/downloads/download_trigger.dart';
|
||||
import '../../../../widget/info_dialog.dart';
|
||||
import '../../talk/widgets/highlighted_linkify.dart';
|
||||
import '../sharing/share_sheet.dart';
|
||||
@@ -43,101 +44,32 @@ class FileElement extends StatefulWidget {
|
||||
State<FileElement> createState() => _FileElementState();
|
||||
}
|
||||
|
||||
class _FileElementState extends State<FileElement> {
|
||||
DownloadJob? _job;
|
||||
class _FileElementState extends State<FileElement>
|
||||
with DownloadTrigger<FileElement> {
|
||||
@override
|
||||
String? get downloadRemotePath =>
|
||||
widget.file.isDirectory ? null : widget.file.path;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_attachJob(DownloadManager.instance.jobFor(widget.file.path));
|
||||
initDownloadTrigger();
|
||||
}
|
||||
|
||||
@override
|
||||
void didUpdateWidget(covariant FileElement oldWidget) {
|
||||
super.didUpdateWidget(oldWidget);
|
||||
if (oldWidget.file.path != widget.file.path) {
|
||||
_detachJob();
|
||||
_attachJob(DownloadManager.instance.jobFor(widget.file.path));
|
||||
}
|
||||
if (oldWidget.file.path != widget.file.path) refreshDownloadTrigger();
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_detachJob();
|
||||
disposeDownloadTrigger();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
void _attachJob(DownloadJob? job) {
|
||||
_job = job;
|
||||
if (job == null) return;
|
||||
job.status.addListener(_onStatusChange);
|
||||
if (job.isFinished) {
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) => _onStatusChange());
|
||||
}
|
||||
}
|
||||
|
||||
void _detachJob() {
|
||||
_job?.status.removeListener(_onStatusChange);
|
||||
_job = null;
|
||||
}
|
||||
|
||||
void _onStatusChange() {
|
||||
if (!mounted) return;
|
||||
final job = _job;
|
||||
if (job == null) return;
|
||||
final status = job.status.value;
|
||||
if (status is DownloadDone) {
|
||||
Haptics.success();
|
||||
DownloadManager.instance.clear(widget.file.path);
|
||||
_detachJob();
|
||||
AppRoutes.openFileViewer(
|
||||
context,
|
||||
status.localPath,
|
||||
remoteFile: RemoteFileRef.fromCacheable(widget.file),
|
||||
);
|
||||
setState(() {});
|
||||
} else if (status is DownloadFailed) {
|
||||
final message = status.message;
|
||||
DownloadManager.instance.clear(widget.file.path);
|
||||
_detachJob();
|
||||
setState(() {});
|
||||
InfoDialog.show(context, message, title: 'Download', copyable: true);
|
||||
} else if (status is DownloadCancelled) {
|
||||
DownloadManager.instance.clear(widget.file.path);
|
||||
_detachJob();
|
||||
setState(() {});
|
||||
} else {
|
||||
setState(() {});
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _startDownload() async {
|
||||
final job = await DownloadManager.instance.start(
|
||||
remotePath: widget.file.path,
|
||||
name: widget.file.name,
|
||||
);
|
||||
if (!mounted) return;
|
||||
if (_job == job) return;
|
||||
_detachJob();
|
||||
_attachJob(job);
|
||||
setState(() {});
|
||||
}
|
||||
|
||||
void _confirmCancel() {
|
||||
showDialog<void>(
|
||||
context: context,
|
||||
builder: (dialogContext) => ConfirmDialog(
|
||||
title: 'Download abbrechen?',
|
||||
content: 'Möchtest du den Download abbrechen?',
|
||||
cancelButton: 'Nein',
|
||||
confirmButton: 'Ja, Abbrechen',
|
||||
onConfirm: () => _job?.cancel(),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget? _subtitle() {
|
||||
final status = _job?.status.value;
|
||||
final status = downloadJob?.status.value;
|
||||
if (status is DownloadInProgress) {
|
||||
return Row(
|
||||
children: [
|
||||
@@ -180,12 +112,14 @@ class _FileElementState extends State<FileElement> {
|
||||
);
|
||||
return;
|
||||
}
|
||||
final status = _job?.status.value;
|
||||
if (status is DownloadInProgress) {
|
||||
_confirmCancel();
|
||||
if (isDownloading) {
|
||||
confirmCancelDownload();
|
||||
return;
|
||||
}
|
||||
_startDownload();
|
||||
startDownload(
|
||||
name: widget.file.name,
|
||||
remoteFile: RemoteFileRef.fromCacheable(widget.file),
|
||||
);
|
||||
}
|
||||
|
||||
// All paths here are relative to the WebDAV root (matching CacheableFile.path).
|
||||
|
||||
Reference in New Issue
Block a user