From 35b96b0bd232735a255a5e257abc4271ca3ebb24 Mon Sep 17 00:00:00 2001 From: LittleSheep Date: Tue, 18 Nov 2025 22:21:23 +0800 Subject: [PATCH] :lipstick: Optimize downloading and files --- assets/i18n/en-US.json | 3 +- lib/pods/upload_tasks.dart | 4 +++ lib/screens/files/file_detail.dart | 29 ++++++--------- lib/widgets/content/cloud_files.dart | 53 +++------------------------- lib/widgets/upload_overlay.dart | 37 ++++++++++++++++--- 5 files changed, 53 insertions(+), 73 deletions(-) diff --git a/assets/i18n/en-US.json b/assets/i18n/en-US.json index 8770a96f..d49b4c00 100644 --- a/assets/i18n/en-US.json +++ b/assets/i18n/en-US.json @@ -1338,5 +1338,6 @@ "enterNumberOfSplits": "Enter Splits Amount", "orCreateWith": "Or\ncreate with", "unindexedFiles": "Unindexed files", - "folder": "Folder" + "folder": "Folder", + "clearCompleted": "Clear Completed" } diff --git a/lib/pods/upload_tasks.dart b/lib/pods/upload_tasks.dart index d18895ce..2483af57 100644 --- a/lib/pods/upload_tasks.dart +++ b/lib/pods/upload_tasks.dart @@ -293,6 +293,10 @@ class UploadTasksNotifier extends StateNotifier> { .toList(); } + void clearAllTasks() { + state = []; + } + DriveTask? getTask(String taskId) { return state.where((task) => task.taskId == taskId).firstOrNull; } diff --git a/lib/screens/files/file_detail.dart b/lib/screens/files/file_detail.dart index 93b8282c..7c871410 100644 --- a/lib/screens/files/file_detail.dart +++ b/lib/screens/files/file_detail.dart @@ -233,9 +233,8 @@ class FileDetailScreen extends HookConsumerWidget { } Future _downloadFile(WidgetRef ref) async { - final taskId = ref - .read(uploadTasksProvider.notifier) - .addLocalDownloadTask(item); + final taskNotifier = ref.read(uploadTasksProvider.notifier); + final taskId = taskNotifier.addLocalDownloadTask(item); try { showSnackBar('Downloading file...'); @@ -253,12 +252,8 @@ class FileDetailScreen extends HookConsumerWidget { queryParameters: {'original': true}, onReceiveProgress: (count, total) { if (total > 0) { - ref - .read(uploadTasksProvider.notifier) - .updateDownloadProgress(taskId, count, total); - ref - .read(uploadTasksProvider.notifier) - .updateTransmissionProgress(taskId, count / total); + taskNotifier.updateDownloadProgress(taskId, count, total); + taskNotifier.updateTransmissionProgress(taskId, count / total); } }, ); @@ -267,18 +262,14 @@ class FileDetailScreen extends HookConsumerWidget { name: item.name.isEmpty ? '${item.id}.$extName' : item.name, file: File(filePath), ); - ref - .read(uploadTasksProvider.notifier) - .updateTaskStatus(taskId, DriveTaskStatus.completed); + taskNotifier.updateTaskStatus(taskId, DriveTaskStatus.completed); showSnackBar('File saved to downloads'); } catch (e) { - ref - .read(uploadTasksProvider.notifier) - .updateTaskStatus( - taskId, - DriveTaskStatus.failed, - errorMessage: e.toString(), - ); + taskNotifier.updateTaskStatus( + taskId, + DriveTaskStatus.failed, + errorMessage: e.toString(), + ); showErrorAlert(e); } } diff --git a/lib/widgets/content/cloud_files.dart b/lib/widgets/content/cloud_files.dart index 5b537c50..cefb9ab7 100644 --- a/lib/widgets/content/cloud_files.dart +++ b/lib/widgets/content/cloud_files.dart @@ -1,8 +1,5 @@ -import 'dart:io'; - import 'package:cached_network_image/cached_network_image.dart'; import 'package:easy_localization/easy_localization.dart'; -import 'package:file_saver/file_saver.dart'; import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:gap/gap.dart'; @@ -10,16 +7,11 @@ import 'package:go_router/go_router.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:island/models/file.dart'; import 'package:island/pods/config.dart'; -import 'package:island/pods/network.dart'; import 'package:island/services/time.dart'; import 'package:island/utils/format.dart'; -import 'package:island/widgets/alert.dart'; import 'package:material_symbols_icons/symbols.dart'; -import 'package:path/path.dart' show extension; -import 'package:path_provider/path_provider.dart'; import 'package:styled_widget/styled_widget.dart'; import 'package:island/widgets/data_saving_gate.dart'; -import 'package:island/widgets/content/file_info_sheet.dart'; import 'file_viewer_contents.dart'; import 'image.dart'; @@ -281,41 +273,13 @@ class CloudFileWidget extends HookConsumerWidget { 'audio' => AudioFileContent(item: item, uri: uri), _ => Builder( builder: (context) { - Future downloadFile() async { - try { - showSnackBar('Downloading file...'); - - final client = ref.read(apiClientProvider); - final tempDir = await getTemporaryDirectory(); - var extName = extension(item.name).trim(); - if (extName.isEmpty) { - extName = item.mimeType?.split('/').lastOrNull ?? 'bin'; - } - final filePath = '${tempDir.path}/${item.id}.$extName'; - - await client.download( - '/drive/files/${item.id}', - filePath, - queryParameters: {'original': true}, - ); - - await FileSaver.instance.saveFile( - name: item.name.isEmpty ? '${item.id}.$extName' : item.name, - file: File(filePath), - ); - showSnackBar('File saved to downloads'); - } catch (e) { - showErrorAlert(e); - } - } - return Container( decoration: BoxDecoration( border: Border.all( color: Theme.of(context).colorScheme.outline, width: 1, ), - borderRadius: BorderRadius.circular(8), + borderRadius: BorderRadius.circular(16), ), child: Column( mainAxisSize: MainAxisSize.min, @@ -347,19 +311,12 @@ class CloudFileWidget extends HookConsumerWidget { Row( mainAxisSize: MainAxisSize.min, children: [ - TextButton.icon( - onPressed: downloadFile, - icon: const Icon(Symbols.download), - label: Text('download').tr(), - ), - const Gap(8), TextButton.icon( onPressed: () { - showModalBottomSheet( - useRootNavigator: true, - context: context, - isScrollControlled: true, - builder: (context) => FileInfoSheet(item: item), + context.pushNamed( + 'fileDetail', + pathParameters: {'id': item.id}, + extra: item, ); }, icon: const Icon(Symbols.info), diff --git a/lib/widgets/upload_overlay.dart b/lib/widgets/upload_overlay.dart index 5ac9f39c..925a05bd 100644 --- a/lib/widgets/upload_overlay.dart +++ b/lib/widgets/upload_overlay.dart @@ -102,7 +102,9 @@ class _UploadOverlayContent extends HookConsumerWidget { return null; }, [isExpanded.value]); - final isMobile = MediaQuery.of(context).size.width < 600; + final isMobile = !isWideScreen(context); + + final taskNotifier = ref.read(uploadTasksProvider.notifier); return Padding( padding: EdgeInsets.only( @@ -246,7 +248,7 @@ class _UploadOverlayContent extends HookConsumerWidget { SliverToBoxAdapter( child: ListTile( dense: true, - title: const Text('Clear Completed'), + title: const Text('clearCompleted').tr(), leading: Icon( Symbols.clear_all, size: 18, @@ -256,9 +258,34 @@ class _UploadOverlayContent extends HookConsumerWidget { ).colorScheme.onSurfaceVariant, ), onTap: () { - ref - .read(uploadTasksProvider.notifier) - .clearCompletedTasks(); + taskNotifier.clearCompletedTasks(); + isExpanded.value = false; + }, + + tileColor: + Theme.of( + context, + ).colorScheme.surfaceContainerHighest, + ), + ), + + // Clear all tasks button + if (activeTasks.any( + (task) => + task.status != DriveTaskStatus.completed, + )) + SliverToBoxAdapter( + child: ListTile( + dense: true, + title: const Text('Clear All'), + leading: Icon( + Symbols.clear_all, + size: 18, + color: + Theme.of(context).colorScheme.error, + ), + onTap: () { + taskNotifier.clearAllTasks(); isExpanded.value = false; }, tileColor: