From 16f248ceab86ce25754c344299f088dd8922041c Mon Sep 17 00:00:00 2001 From: LittleSheep Date: Tue, 26 Aug 2025 00:03:43 +0800 Subject: [PATCH] :lipstick: Optimize file saving --- .../content/cloud_file_collection.dart | 94 ++++++++----------- linux/flutter/generated_plugin_registrant.cc | 4 + linux/flutter/generated_plugins.cmake | 1 + macos/Flutter/GeneratedPluginRegistrant.swift | 2 + pubspec.lock | 20 ++-- .../flutter/generated_plugin_registrant.cc | 3 + windows/flutter/generated_plugins.cmake | 1 + 7 files changed, 65 insertions(+), 60 deletions(-) diff --git a/lib/widgets/content/cloud_file_collection.dart b/lib/widgets/content/cloud_file_collection.dart index d3ea9c33..5f1d990d 100644 --- a/lib/widgets/content/cloud_file_collection.dart +++ b/lib/widgets/content/cloud_file_collection.dart @@ -1,9 +1,12 @@ import 'dart:convert'; +import 'dart:io'; import 'dart:math' as math; import 'dart:ui'; import 'package:dismissible_page/dismissible_page.dart'; import 'package:easy_localization/easy_localization.dart'; +import 'package:file_saver/file_saver.dart'; +import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_blurhash/flutter_blurhash.dart'; @@ -321,7 +324,7 @@ class CloudFileZoomIn extends HookConsumerWidget { Future saveToGallery() async { try { // Show loading indicator - showSnackBar('Saving image to gallery...'); + showSnackBar('Saving image...'); // Get the image URL final client = ref.watch(apiClientProvider); @@ -339,10 +342,18 @@ class CloudFileZoomIn extends HookConsumerWidget { filePath, queryParameters: {'original': true}, ); - await Gal.putImage(filePath, album: 'Solar Network'); - - // Show success message - showSnackBar('Image saved to gallery'); + if (!kIsWeb && (Platform.isAndroid || Platform.isIOS)) { + // Save to gallery + await Gal.putImage(filePath, album: 'Solar Network'); + // Show success message + showSnackBar('Image saved to gallery'); + } else { + await FileSaver.instance.saveFile( + name: item.name.isEmpty ? '${item.id}.$extName' : item.name, + file: File(filePath), + ); + showSnackBar('Image saved to $filePath'); + } } catch (e) { showErrorAlert(e); } @@ -623,6 +634,10 @@ class CloudFileZoomIn extends HookConsumerWidget { ); } + final shadow = [ + Shadow(color: Colors.black54, blurRadius: 5.0, offset: Offset(1.0, 1.0)), + ]; + return DismissiblePage( isFullScreen: true, backgroundColor: Colors.transparent, @@ -660,22 +675,17 @@ class CloudFileZoomIn extends HookConsumerWidget { children: [ Row( children: [ - IconButton( - icon: Icon( - Icons.save_alt, - color: Colors.white, - shadows: [ - Shadow( - color: Colors.black54, - blurRadius: 5.0, - offset: Offset(1.0, 1.0), - ), - ], + if (!kIsWeb) + IconButton( + icon: Icon( + Icons.save_alt, + color: Colors.white, + shadows: shadow, + ), + onPressed: () async { + saveToGallery(); + }, ), - onPressed: () async { - saveToGallery(); - }, - ), IconButton( onPressed: () { showOriginal.value = !showOriginal.value; @@ -683,29 +693,13 @@ class CloudFileZoomIn extends HookConsumerWidget { icon: Icon( showOriginal.value ? Symbols.hd : Symbols.sd, color: Colors.white, - shadows: [ - Shadow( - color: Colors.black54, - blurRadius: 5.0, - offset: Offset(1.0, 1.0), - ), - ], + shadows: shadow, ), ), ], ), IconButton( - icon: Icon( - Icons.close, - color: Colors.white, - shadows: [ - Shadow( - color: Colors.black54, - blurRadius: 5.0, - offset: Offset(1.0, 1.0), - ), - ], - ), + icon: Icon(Icons.close, color: Colors.white, shadows: shadow), onPressed: () => Navigator.of(context).pop(), ), ], @@ -722,26 +716,24 @@ class CloudFileZoomIn extends HookConsumerWidget { icon: Icon( Icons.info_outline, color: Colors.white, - shadows: [ - Shadow( - color: Colors.black54, - blurRadius: 5.0, - offset: Offset(1.0, 1.0), - ), - ], + shadows: shadow, ), onPressed: showInfoSheet, ), Spacer(), IconButton( - icon: Icon(Icons.remove, color: Colors.white), + icon: Icon( + Icons.remove, + color: Colors.white, + shadows: shadow, + ), onPressed: () { photoViewController.scale = (photoViewController.scale ?? 1) - 0.05; }, ), IconButton( - icon: Icon(Icons.add, color: Colors.white), + icon: Icon(Icons.add, color: Colors.white, shadows: shadow), onPressed: () { photoViewController.scale = (photoViewController.scale ?? 1) + 0.05; @@ -752,13 +744,7 @@ class CloudFileZoomIn extends HookConsumerWidget { icon: Icon( Icons.rotate_left, color: Colors.white, - shadows: [ - Shadow( - color: Colors.black54, - blurRadius: 5.0, - offset: Offset(1.0, 1.0), - ), - ], + shadows: shadow, ), onPressed: () { rotation.value = (rotation.value - 1) % 4; diff --git a/linux/flutter/generated_plugin_registrant.cc b/linux/flutter/generated_plugin_registrant.cc index 388e8356..af4a44d3 100644 --- a/linux/flutter/generated_plugin_registrant.cc +++ b/linux/flutter/generated_plugin_registrant.cc @@ -7,6 +7,7 @@ #include "generated_plugin_registrant.h" #include +#include #include #include #include @@ -28,6 +29,9 @@ void fl_register_plugins(FlPluginRegistry* registry) { g_autoptr(FlPluginRegistrar) bitsdojo_window_linux_registrar = fl_plugin_registry_get_registrar_for_plugin(registry, "BitsdojoWindowPlugin"); bitsdojo_window_plugin_register_with_registrar(bitsdojo_window_linux_registrar); + g_autoptr(FlPluginRegistrar) file_saver_registrar = + fl_plugin_registry_get_registrar_for_plugin(registry, "FileSaverPlugin"); + file_saver_plugin_register_with_registrar(file_saver_registrar); g_autoptr(FlPluginRegistrar) file_selector_linux_registrar = fl_plugin_registry_get_registrar_for_plugin(registry, "FileSelectorPlugin"); file_selector_plugin_register_with_registrar(file_selector_linux_registrar); diff --git a/linux/flutter/generated_plugins.cmake b/linux/flutter/generated_plugins.cmake index 4a1b2498..7e6ab7fe 100644 --- a/linux/flutter/generated_plugins.cmake +++ b/linux/flutter/generated_plugins.cmake @@ -4,6 +4,7 @@ list(APPEND FLUTTER_PLUGIN_LIST bitsdojo_window_linux + file_saver file_selector_linux flutter_platform_alert flutter_secure_storage_linux diff --git a/macos/Flutter/GeneratedPluginRegistrant.swift b/macos/Flutter/GeneratedPluginRegistrant.swift index aae600e6..17e367f9 100644 --- a/macos/Flutter/GeneratedPluginRegistrant.swift +++ b/macos/Flutter/GeneratedPluginRegistrant.swift @@ -9,6 +9,7 @@ import bitsdojo_window_macos import connectivity_plus import device_info_plus import file_picker +import file_saver import file_selector_macos import firebase_analytics import firebase_core @@ -45,6 +46,7 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { ConnectivityPlusPlugin.register(with: registry.registrar(forPlugin: "ConnectivityPlusPlugin")) DeviceInfoPlusMacosPlugin.register(with: registry.registrar(forPlugin: "DeviceInfoPlusMacosPlugin")) FilePickerPlugin.register(with: registry.registrar(forPlugin: "FilePickerPlugin")) + FileSaverPlugin.register(with: registry.registrar(forPlugin: "FileSaverPlugin")) FileSelectorPlugin.register(with: registry.registrar(forPlugin: "FileSelectorPlugin")) FirebaseAnalyticsPlugin.register(with: registry.registrar(forPlugin: "FirebaseAnalyticsPlugin")) FLTFirebaseCorePlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseCorePlugin")) diff --git a/pubspec.lock b/pubspec.lock index 18343a08..0f8af119 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -569,6 +569,14 @@ packages: url: "https://pub.dev" source: hosted version: "10.3.2" + file_saver: + dependency: "direct main" + description: + name: file_saver + sha256: "9d93db09bd4da9e43238f9dd485360fc51a5c138eea5ef5f407ec56e58079ac0" + url: "https://pub.dev" + source: hosted + version: "0.3.1" file_selector_linux: dependency: transitive description: @@ -1921,10 +1929,10 @@ packages: dependency: transitive description: name: record_ios - sha256: "895c9467faec72d8e718a3142b51114958f42f18053836a8b484a74f9372f51a" + sha256: "13e241ed9cbc220534a40ae6b66222e21288db364d96dd66fb762ebd3cb77c71" url: "https://pub.dev" source: hosted - version: "1.1.1" + version: "1.1.2" record_linux: dependency: transitive description: @@ -2041,10 +2049,10 @@ packages: dependency: transitive description: name: screen_brightness_android - sha256: fb5fa43cb89d0c9b8534556c427db1e97e46594ac5d66ebdcf16063b773d54ed + sha256: d34f5321abd03bc3474f4c381f53d189117eba0b039eac1916aa92cca5fd0a96 url: "https://pub.dev" source: hosted - version: "2.1.2" + version: "2.1.3" screen_brightness_platform_interface: dependency: transitive description: @@ -2640,10 +2648,10 @@ packages: dependency: transitive description: name: watcher - sha256: "0b7fd4a0bbc4b92641dbf20adfd7e3fd1398fe17102d94b674234563e110088a" + sha256: "5bf046f41320ac97a469d506261797f35254fa61c641741ef32dacda98b7d39c" url: "https://pub.dev" source: hosted - version: "1.1.2" + version: "1.1.3" waveform_flutter: dependency: "direct main" description: diff --git a/windows/flutter/generated_plugin_registrant.cc b/windows/flutter/generated_plugin_registrant.cc index 48ba56e0..69437071 100644 --- a/windows/flutter/generated_plugin_registrant.cc +++ b/windows/flutter/generated_plugin_registrant.cc @@ -8,6 +8,7 @@ #include #include +#include #include #include #include @@ -35,6 +36,8 @@ void RegisterPlugins(flutter::PluginRegistry* registry) { registry->GetRegistrarForPlugin("BitsdojoWindowPlugin")); ConnectivityPlusWindowsPluginRegisterWithRegistrar( registry->GetRegistrarForPlugin("ConnectivityPlusWindowsPlugin")); + FileSaverPluginRegisterWithRegistrar( + registry->GetRegistrarForPlugin("FileSaverPlugin")); FileSelectorWindowsRegisterWithRegistrar( registry->GetRegistrarForPlugin("FileSelectorWindows")); FirebaseCorePluginCApiRegisterWithRegistrar( diff --git a/windows/flutter/generated_plugins.cmake b/windows/flutter/generated_plugins.cmake index 3c82a131..f18218b0 100644 --- a/windows/flutter/generated_plugins.cmake +++ b/windows/flutter/generated_plugins.cmake @@ -5,6 +5,7 @@ list(APPEND FLUTTER_PLUGIN_LIST bitsdojo_window_windows connectivity_plus + file_saver file_selector_windows firebase_core flutter_inappwebview_windows