chore: defaultly save files on Android

- defaultly save files on Android instead of share
- add dedicated share button for files and images on Android
- use ListTile instead of row to display file event
- update file_picker_cross

Signed-off-by: TheOneWithTheBraid <the-one@with-the-braid.cf>
This commit is contained in:
TheOneWithTheBraid 2022-04-30 17:43:38 +02:00
parent 10798ac7ff
commit a9275fc4f6
9 changed files with 137 additions and 68 deletions

View File

@ -25,7 +25,7 @@
<uses-permission android:name="android.permission.CALL_PHONE" /> <uses-permission android:name="android.permission.CALL_PHONE" />
<uses-sdk <uses-sdk
tools:overrideLibrary="io.wazo.callkeep, net.touchcapture.qr.flutterqr, com.cloudwebrtc.webrtc, org.webrtc, com.it_nomads.fluttersecurestorage, com.pichillilorenzo.flutter_inappwebview, com.example.video_compress, com.otaliastudios.transcoder, com.otaliastudios.opengl"/> tools:overrideLibrary="io.wazo.callkeep, net.touchcapture.qr.flutterqr, com.cloudwebrtc.webrtc, org.webrtc, com.it_nomads.fluttersecurestorage, com.pichillilorenzo.flutter_inappwebview, com.example.video_compress, com.otaliastudios.transcoder, com.otaliastudios.opengl, com.kineapps.flutter_file_dialog"/>
<application <application
android:name=".Application" android:name=".Application"

View File

@ -1,8 +1,10 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/l10n.dart';
import 'package:matrix/matrix.dart'; import 'package:matrix/matrix.dart';
import 'package:fluffychat/utils/matrix_sdk_extensions.dart/event_extension.dart'; import 'package:fluffychat/utils/matrix_sdk_extensions.dart/event_extension.dart';
import 'package:fluffychat/utils/platform_infos.dart';
class MessageDownloadContent extends StatelessWidget { class MessageDownloadContent extends StatelessWidget {
final Event event; final Event event;
@ -28,24 +30,26 @@ class MessageDownloadContent extends StatelessWidget {
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: <Widget>[ children: <Widget>[
Row( ListTile(
children: [ leading: Icon(
Icon( Icons.file_download_outlined,
Icons.file_download_outlined, color: textColor,
),
title: Text(
filename,
maxLines: 1,
style: TextStyle(
color: textColor, color: textColor,
fontWeight: FontWeight.bold,
), ),
const SizedBox(width: 8), ),
Expanded( trailing: PlatformInfos.isAndroid
child: Text( ? IconButton(
filename, onPressed: () => event.shareFile(context),
maxLines: 1, tooltip: L10n.of(context)!.share,
style: TextStyle( icon: const Icon(Icons.share),
color: textColor, )
fontWeight: FontWeight.bold, : null,
),
),
),
],
), ),
const Divider(), const Divider(),
Row( Row(

View File

@ -28,6 +28,9 @@ class ImageViewerController extends State<ImageViewer> {
/// Save this file with a system call. /// Save this file with a system call.
void saveFileAction() => widget.event.saveFile(context); void saveFileAction() => widget.event.saveFile(context);
/// Save this file with a system call.
void shareFileAction() => widget.event.shareFile(context);
static const maxScaleFactor = 1.5; static const maxScaleFactor = 1.5;
/// Go back if user swiped it away /// Go back if user swiped it away

View File

@ -3,6 +3,7 @@ import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/l10n.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart';
import 'package:fluffychat/pages/chat/events/image_bubble.dart'; import 'package:fluffychat/pages/chat/events/image_bubble.dart';
import 'package:fluffychat/utils/platform_infos.dart';
import 'image_viewer.dart'; import 'image_viewer.dart';
class ImageViewerView extends StatelessWidget { class ImageViewerView extends StatelessWidget {
@ -37,6 +38,13 @@ class ImageViewerView extends StatelessWidget {
color: Colors.white, color: Colors.white,
tooltip: L10n.of(context)!.downloadFile, tooltip: L10n.of(context)!.downloadFile,
), ),
if (PlatformInfos.isAndroid)
IconButton(
onPressed: controller.shareFileAction,
tooltip: L10n.of(context)!.share,
color: Colors.white,
icon: const Icon(Icons.share),
)
], ],
), ),
body: InteractiveViewer( body: InteractiveViewer(

View File

@ -8,18 +8,28 @@ import 'package:matrix/matrix.dart';
import 'matrix_file_extension.dart'; import 'matrix_file_extension.dart';
extension LocalizedBody on Event { extension LocalizedBody on Event {
Future<LoadingDialogResult<MatrixFile?>> _getFile(BuildContext context) =>
showFutureLoadingDialog(
context: context,
future: () => downloadAndDecryptAttachmentCached(),
);
void saveFile(BuildContext context) async { void saveFile(BuildContext context) async {
final matrixFile = await showFutureLoadingDialog( final matrixFile = await _getFile(context);
context: context,
future: () => downloadAndDecryptAttachmentCached(),
);
matrixFile.result?.save(context); matrixFile.result?.save(context);
} }
void shareFile(BuildContext context) async {
final matrixFile = await _getFile(context);
matrixFile.result?.share(context);
}
bool get isAttachmentSmallEnough => bool get isAttachmentSmallEnough =>
infoMap['size'] is int && infoMap['size'] is int &&
infoMap['size'] < room.client.database!.maxFileSize; infoMap['size'] < room.client.database!.maxFileSize;
bool get isThumbnailSmallEnough => bool get isThumbnailSmallEnough =>
thumbnailInfoMap['size'] is int && thumbnailInfoMap['size'] is int &&
thumbnailInfoMap['size'] < room.client.database!.maxFileSize; thumbnailInfoMap['size'] < room.client.database!.maxFileSize;

View File

@ -13,23 +13,25 @@ import 'package:fluffychat/utils/platform_infos.dart';
extension MatrixFileExtension on MatrixFile { extension MatrixFileExtension on MatrixFile {
void save(BuildContext context) async { void save(BuildContext context) async {
final fileName = name.split('/').last; final fileName = name.split('/').last;
if (PlatformInfos.isMobile) {
final tmpDirectory = PlatformInfos.isAndroid final file = FilePickerCross(bytes);
? (await getExternalStorageDirectories( await file.exportToStorage(fileName: fileName, share: false);
type: StorageDirectory.downloads))! }
.first
: await getTemporaryDirectory(); void share(BuildContext context) async {
final path = '${tmpDirectory.path}$fileName'; final fileName = name.split('/').last;
await File(path).writeAsBytes(bytes); final tmpDirectory = PlatformInfos.isAndroid
await Share.shareFiles([path]); ? (await getExternalStorageDirectories(
ScaffoldMessenger.of(context).showSnackBar( type: StorageDirectory.downloads))!
SnackBar(content: Text(L10n.of(context)!.savedFileAs(path))), .first
); : await getTemporaryDirectory();
return; final path = '${tmpDirectory.path}$fileName';
} else { await File(path).writeAsBytes(bytes);
final file = FilePickerCross(bytes); await Share.shareFiles([path]);
await file.exportToStorage(fileName: fileName); ScaffoldMessenger.of(context).showSnackBar(
} SnackBar(content: Text(L10n.of(context)!.savedFileAs(path))),
);
return;
} }
MatrixFile get detectFileType { MatrixFile get detectFileType {

View File

@ -14,7 +14,7 @@ packages:
name: adaptive_dialog name: adaptive_dialog
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.4.0" version: "1.6.1"
adaptive_theme: adaptive_theme:
dependency: "direct main" dependency: "direct main"
description: description:
@ -422,7 +422,7 @@ packages:
name: file_picker_cross name: file_picker_cross
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "4.5.0" version: "4.6.0"
file_selector: file_selector:
dependency: transitive dependency: transitive
description: description:
@ -437,13 +437,6 @@ packages:
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "0.0.2+1" version: "0.0.2+1"
file_selector_macos:
dependency: transitive
description:
name: file_selector_macos
url: "https://pub.dartlang.org"
source: hosted
version: "0.0.4+1"
file_selector_platform_interface: file_selector_platform_interface:
dependency: transitive dependency: transitive
description: description:
@ -458,13 +451,6 @@ packages:
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "0.8.1+3" version: "0.8.1+3"
file_selector_windows:
dependency: transitive
description:
name: file_selector_windows
url: "https://pub.dartlang.org"
source: hosted
version: "0.0.2+1"
fluffybox: fluffybox:
dependency: transitive dependency: transitive
description: description:
@ -510,6 +496,13 @@ packages:
description: flutter description: flutter
source: sdk source: sdk
version: "0.0.0" version: "0.0.0"
flutter_file_dialog:
dependency: transitive
description:
name: flutter_file_dialog
url: "https://pub.dartlang.org"
source: hosted
version: "2.3.0"
flutter_highlight: flutter_highlight:
dependency: transitive dependency: transitive
description: description:
@ -878,6 +871,13 @@ packages:
description: flutter description: flutter
source: sdk source: sdk
version: "0.0.0" version: "0.0.0"
intersperse:
dependency: transitive
description:
name: intersperse
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.0"
intl: intl:
dependency: "direct main" dependency: "direct main"
description: description:
@ -978,6 +978,13 @@ packages:
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.2.2" version: "1.2.2"
macos_ui:
dependency: transitive
description:
name: macos_ui
url: "https://pub.dartlang.org"
source: hosted
version: "0.13.1"
markdown: markdown:
dependency: transitive dependency: transitive
description: description:
@ -1106,27 +1113,20 @@ packages:
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.0.2" version: "2.0.2"
package_info:
dependency: transitive
description:
name: package_info
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.2"
package_info_plus: package_info_plus:
dependency: "direct main" dependency: "direct main"
description: description:
name: package_info_plus name: package_info_plus
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.4.0" version: "1.4.2"
package_info_plus_linux: package_info_plus_linux:
dependency: transitive dependency: transitive
description: description:
name: package_info_plus_linux name: package_info_plus_linux
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.0.3" version: "1.0.5"
package_info_plus_macos: package_info_plus_macos:
dependency: transitive dependency: transitive
description: description:
@ -1147,14 +1147,14 @@ packages:
name: package_info_plus_web name: package_info_plus_web
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.0.4" version: "1.0.5"
package_info_plus_windows: package_info_plus_windows:
dependency: transitive dependency: transitive
description: description:
name: package_info_plus_windows name: package_info_plus_windows
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.0.4" version: "1.0.5"
path: path:
dependency: transitive dependency: transitive
description: description:
@ -1456,6 +1456,48 @@ packages:
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.0.4" version: "2.0.4"
share_plus:
dependency: transitive
description:
name: share_plus
url: "https://pub.dartlang.org"
source: hosted
version: "4.0.4"
share_plus_linux:
dependency: transitive
description:
name: share_plus_linux
url: "https://pub.dartlang.org"
source: hosted
version: "3.0.0"
share_plus_macos:
dependency: transitive
description:
name: share_plus_macos
url: "https://pub.dartlang.org"
source: hosted
version: "3.0.0"
share_plus_platform_interface:
dependency: transitive
description:
name: share_plus_platform_interface
url: "https://pub.dartlang.org"
source: hosted
version: "3.0.2"
share_plus_web:
dependency: transitive
description:
name: share_plus_web
url: "https://pub.dartlang.org"
source: hosted
version: "3.0.0"
share_plus_windows:
dependency: transitive
description:
name: share_plus_windows
url: "https://pub.dartlang.org"
source: hosted
version: "3.0.0"
shared_preferences: shared_preferences:
dependency: "direct main" dependency: "direct main"
description: description:

View File

@ -25,7 +25,7 @@ dependencies:
emoji_picker_flutter: ^1.1.2 emoji_picker_flutter: ^1.1.2
encrypt: ^5.0.1 encrypt: ^5.0.1
#fcm_shared_isolate: ^0.1.0 #fcm_shared_isolate: ^0.1.0
file_picker_cross: ^4.5.0 file_picker_cross: ^4.6.0
flutter: flutter:
sdk: flutter sdk: flutter
flutter_app_badger: ^1.3.0 flutter_app_badger: ^1.3.0
@ -152,4 +152,4 @@ dependency_overrides:
snapping_sheet: snapping_sheet:
git: git:
url: https://github.com/TheOneWithTheBraid/snapping_sheet.git url: https://github.com/TheOneWithTheBraid/snapping_sheet.git
ref: listenable ref: listenable

View File

@ -86,6 +86,6 @@ index c6295788..8dd17ce4 100644
encrypt: ^5.0.1 encrypt: ^5.0.1
- #fcm_shared_isolate: ^0.1.0 - #fcm_shared_isolate: ^0.1.0
+ fcm_shared_isolate: ^0.1.0 + fcm_shared_isolate: ^0.1.0
file_picker_cross: ^4.5.0 file_picker_cross: ^4.6.0
flutter: flutter:
sdk: flutter sdk: flutter