mirror of
				https://gitlab.com/famedly/fluffychat.git
				synced 2025-10-31 12:07:24 +01:00 
			
		
		
		
	Merge branch 'krille/matrix-sdk-image-thumbnailing' into 'main'
fix: Set image width and height See merge request famedly/fluffychat!708
This commit is contained in:
		
						commit
						0a909dcfb9
					
				| @ -13,7 +13,6 @@ import 'package:fluffychat/pages/add_story/add_story_view.dart'; | ||||
| import 'package:fluffychat/pages/add_story/invite_story_page.dart'; | ||||
| import 'package:fluffychat/utils/matrix_sdk_extensions.dart/matrix_file_extension.dart'; | ||||
| import 'package:fluffychat/utils/resize_image.dart'; | ||||
| import 'package:fluffychat/utils/room_send_file_extension.dart'; | ||||
| import 'package:fluffychat/utils/string_color.dart'; | ||||
| import 'package:fluffychat/widgets/matrix.dart'; | ||||
| import '../../utils/matrix_sdk_extensions.dart/client_stories_extension.dart'; | ||||
| @ -29,8 +28,8 @@ class AddStoryController extends State<AddStoryPage> { | ||||
|   final TextEditingController controller = TextEditingController(); | ||||
|   late Color backgroundColor; | ||||
|   late Color backgroundColorDark; | ||||
|   MatrixFile? image; | ||||
|   MatrixFile? video; | ||||
|   MatrixImageFile? image; | ||||
|   MatrixVideoFile? video; | ||||
| 
 | ||||
|   VideoPlayerController? videoPlayerController; | ||||
| 
 | ||||
| @ -49,8 +48,13 @@ class AddStoryController extends State<AddStoryPage> { | ||||
|     ); | ||||
|     final fileName = picked.fileName; | ||||
|     if (fileName == null) return; | ||||
|     final shrinked = await MatrixImageFile.shrink( | ||||
|       bytes: picked.toUint8List(), | ||||
|       name: fileName, | ||||
|       compute: Matrix.of(context).client.runInBackground, | ||||
|     ); | ||||
|     setState(() { | ||||
|       image = MatrixFile(bytes: picked.toUint8List(), name: fileName); | ||||
|       image = shrinked; | ||||
|     }); | ||||
|   } | ||||
| 
 | ||||
| @ -60,8 +64,13 @@ class AddStoryController extends State<AddStoryPage> { | ||||
|     ); | ||||
|     if (picked == null) return; | ||||
|     final bytes = await picked.readAsBytes(); | ||||
|     final shrinked = await MatrixImageFile.shrink( | ||||
|       bytes: bytes, | ||||
|       name: picked.name, | ||||
|       compute: Matrix.of(context).client.runInBackground, | ||||
|     ); | ||||
|     setState(() { | ||||
|       image = MatrixFile(bytes: bytes, name: picked.name); | ||||
|       image = shrinked; | ||||
|     }); | ||||
|   } | ||||
| 
 | ||||
| @ -73,7 +82,7 @@ class AddStoryController extends State<AddStoryPage> { | ||||
|     final bytes = await picked.readAsBytes(); | ||||
| 
 | ||||
|     setState(() { | ||||
|       video = MatrixFile(bytes: bytes, name: picked.name); | ||||
|       video = MatrixVideoFile(bytes: bytes, name: picked.name); | ||||
|       videoPlayerController = VideoPlayerController.file(File(picked.path)) | ||||
|         ..setLooping(true); | ||||
|     }); | ||||
| @ -109,16 +118,17 @@ class AddStoryController extends State<AddStoryPage> { | ||||
|         var video = this.video?.detectFileType; | ||||
|         if (video != null) { | ||||
|           video = await video.resizeVideo(); | ||||
|           await storiesRoom.sendFileEventWithThumbnail( | ||||
|           final thumbnail = await video.getVideoThumbnail(); | ||||
|           await storiesRoom.sendFileEvent( | ||||
|             video, | ||||
|             extraContent: {'body': controller.text}, | ||||
|             thumbnail: thumbnail, | ||||
|           ); | ||||
|           return; | ||||
|         } | ||||
|         var image = this.image?.detectFileType; | ||||
|         final image = this.image; | ||||
|         if (image != null) { | ||||
|           image = await image.resizeImage(); | ||||
|           await storiesRoom.sendFileEventWithThumbnail( | ||||
|           await storiesRoom.sendFileEvent( | ||||
|             image, | ||||
|             extraContent: {'body': controller.text}, | ||||
|           ); | ||||
| @ -142,9 +152,10 @@ class AddStoryController extends State<AddStoryPage> { | ||||
|     final shareContent = Matrix.of(context).shareContent; | ||||
|     // ignore: unnecessary_null_comparison | ||||
|     if (shareContent != null) { | ||||
|       image = shareContent.tryGet<MatrixFile>('file'); | ||||
|       final shareFile = shareContent.tryGet<MatrixFile>('file')?.detectFileType; | ||||
| 
 | ||||
|       controller.text = shareContent.tryGet<String>('body') ?? ''; | ||||
|       if (shareContent.tryGet<String>('msgtype') == MessageTypes.Image) { | ||||
|       if (shareFile is MatrixImageFile) { | ||||
|         Event( | ||||
|           content: shareContent, | ||||
|           type: EventTypes.Message, | ||||
| @ -154,10 +165,10 @@ class AddStoryController extends State<AddStoryPage> { | ||||
|           originServerTs: DateTime.now(), | ||||
|         ).downloadAndDecryptAttachment().then((file) { | ||||
|           setState(() { | ||||
|             image = file; | ||||
|             image = shareFile; | ||||
|           }); | ||||
|         }); | ||||
|       } else if (shareContent.tryGet<String>('msgtype') == MessageTypes.Video) { | ||||
|       } else if (shareFile is MatrixVideoFile) { | ||||
|         Event( | ||||
|           content: shareContent, | ||||
|           type: EventTypes.Message, | ||||
| @ -167,7 +178,7 @@ class AddStoryController extends State<AddStoryPage> { | ||||
|           originServerTs: DateTime.now(), | ||||
|         ).downloadAndDecryptAttachment().then((file) { | ||||
|           setState(() { | ||||
|             video = file; | ||||
|             video = shareFile; | ||||
|           }); | ||||
|         }); | ||||
|       } | ||||
|  | ||||
| @ -6,7 +6,6 @@ import 'package:matrix/matrix.dart'; | ||||
| 
 | ||||
| import '../../utils/matrix_sdk_extensions.dart/matrix_file_extension.dart'; | ||||
| import '../../utils/resize_image.dart'; | ||||
| import '../../utils/room_send_file_extension.dart'; | ||||
| 
 | ||||
| class SendFileDialog extends StatefulWidget { | ||||
|   final Room room; | ||||
| @ -31,15 +30,21 @@ class _SendFileDialogState extends State<SendFileDialog> { | ||||
| 
 | ||||
|   Future<void> _send() async { | ||||
|     var file = widget.file; | ||||
|     MatrixImageFile? thumbnail; | ||||
|     if (file is MatrixImageFile && | ||||
|         !origImage && | ||||
|         file.bytes.length > minSizeToCompress) { | ||||
|       file = await file.resizeImage(); | ||||
|       file = await MatrixImageFile.shrink( | ||||
|         bytes: file.bytes, | ||||
|         name: file.name, | ||||
|         compute: widget.room.client.runInBackground, | ||||
|       ); | ||||
|     } | ||||
|     if (file is MatrixVideoFile && file.bytes.length > minSizeToCompress) { | ||||
|       file = await file.resizeVideo(); | ||||
|       thumbnail = await file.getVideoThumbnail(); | ||||
|     } | ||||
|     await widget.room.sendFileEventWithThumbnail(file); | ||||
|     await widget.room.sendFileEvent(file, thumbnail: thumbnail); | ||||
|   } | ||||
| 
 | ||||
|   @override | ||||
|  | ||||
| @ -7,7 +7,6 @@ import 'package:future_loading_dialog/future_loading_dialog.dart'; | ||||
| import 'package:matrix/matrix.dart'; | ||||
| import 'package:vrouter/vrouter.dart'; | ||||
| 
 | ||||
| import '../../utils/resize_image.dart'; | ||||
| import '../../widgets/matrix.dart'; | ||||
| import 'settings_emotes_view.dart'; | ||||
| 
 | ||||
| @ -206,14 +205,19 @@ class EmotesSettingsController extends State<EmotesSettings> { | ||||
|       name: result.fileName!, | ||||
|     ); | ||||
|     try { | ||||
|       file = await file.resizeImage(calcBlurhash: false); | ||||
|       file = (await file.generateThumbnail( | ||||
|         compute: Matrix.of(context).client.runInBackground, | ||||
|       ))!; | ||||
|     } catch (_) { | ||||
|       // do nothing | ||||
|     } | ||||
|     final uploadResp = await showFutureLoadingDialog( | ||||
|       context: context, | ||||
|       future: () => Matrix.of(context).client.uploadContent(file.bytes, | ||||
|           filename: file.name, contentType: file.mimeType), | ||||
|       future: () => Matrix.of(context).client.uploadContent( | ||||
|             file.bytes, | ||||
|             filename: file.name, | ||||
|             contentType: file.mimeType, | ||||
|           ), | ||||
|     ); | ||||
|     if (uploadResp.error == null) { | ||||
|       setState(() { | ||||
|  | ||||
| @ -1,9 +1,6 @@ | ||||
| import 'dart:io'; | ||||
| import 'dart:math' as math; | ||||
| import 'dart:typed_data'; | ||||
| 
 | ||||
| import 'package:flutter/foundation.dart'; | ||||
| 
 | ||||
| import 'package:blurhash_dart/blurhash_dart.dart'; | ||||
| import 'package:image/image.dart'; | ||||
| import 'package:matrix/matrix.dart'; | ||||
| @ -50,74 +47,15 @@ extension ResizeImage on MatrixFile { | ||||
|       return MatrixImageFile( | ||||
|         bytes: bytes, | ||||
|         name: name, | ||||
|       ).resizeImage(); | ||||
|       ); | ||||
|     } catch (e, s) { | ||||
|       SentryController.captureException(e, s); | ||||
|     } | ||||
|     return null; | ||||
|   } | ||||
| 
 | ||||
|   Future<MatrixImageFile> resizeImage({ | ||||
|     bool calcBlurhash = true, | ||||
|     int max = ResizeImage.max, | ||||
|     int quality = ResizeImage.quality, | ||||
|   }) async { | ||||
|     final bytes = mimeType == 'image/gif' | ||||
|         ? this.bytes | ||||
|         : await compute<_ResizeBytesConfig, Uint8List>( | ||||
|             resizeBytes, | ||||
|             _ResizeBytesConfig( | ||||
|               bytes: this.bytes, | ||||
|               mimeType: mimeType, | ||||
|               max: max, | ||||
|               quality: quality, | ||||
|             )); | ||||
|     final blurhash = calcBlurhash | ||||
|         ? await compute<Uint8List, BlurHash>(createBlurHash, bytes) | ||||
|         : null; | ||||
|     return MatrixImageFile( | ||||
|       bytes: bytes, | ||||
|       name: '${name.split('.').first}_thumbnail_$max.jpg', | ||||
|       blurhash: blurhash?.hash, | ||||
|     ); | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| Future<BlurHash> createBlurHash(Uint8List file) async { | ||||
|   final image = decodeImage(file)!; | ||||
|   return BlurHash.encode(image, numCompX: 4, numCompY: 3); | ||||
| } | ||||
| 
 | ||||
| Future<Uint8List> resizeBytes(_ResizeBytesConfig config) async { | ||||
|   var image = decodeImage(config.bytes)!; | ||||
| 
 | ||||
|   // Is file already smaller than max? Then just return. | ||||
|   if (math.max(image.width, image.height) > config.max) { | ||||
|     // Use the larger side to resize. | ||||
|     final useWidth = image.width >= image.height; | ||||
|     image = useWidth | ||||
|         ? copyResize(image, width: config.max) | ||||
|         : copyResize(image, height: config.max); | ||||
|   } | ||||
| 
 | ||||
|   const pngMimeType = 'image/png'; | ||||
|   final encoded = config.mimeType.toLowerCase() == pngMimeType | ||||
|       ? encodePng(image) | ||||
|       : encodeJpg(image, quality: config.quality); | ||||
| 
 | ||||
|   return Uint8List.fromList(encoded); | ||||
| } | ||||
| 
 | ||||
| class _ResizeBytesConfig { | ||||
|   final Uint8List bytes; | ||||
|   final int max; | ||||
|   final int quality; | ||||
|   final String mimeType; | ||||
| 
 | ||||
|   const _ResizeBytesConfig({ | ||||
|     required this.bytes, | ||||
|     this.max = ResizeImage.max, | ||||
|     this.quality = ResizeImage.quality, | ||||
|     required this.mimeType, | ||||
|   }); | ||||
| } | ||||
|  | ||||
| @ -1,35 +0,0 @@ | ||||
| import 'package:matrix/matrix.dart'; | ||||
| 
 | ||||
| import 'resize_image.dart'; | ||||
| 
 | ||||
| extension RoomSendFileExtension on Room { | ||||
|   Future<Uri> sendFileEventWithThumbnail( | ||||
|     MatrixFile file, { | ||||
|     String? txid, | ||||
|     Event? inReplyTo, | ||||
|     String? editEventId, | ||||
|     bool? waitUntilSent, | ||||
|     Map<String, dynamic>? extraContent, | ||||
|   }) async { | ||||
|     MatrixImageFile? thumbnail; | ||||
|     if (file is MatrixImageFile) { | ||||
|       thumbnail = await file.resizeImage(); | ||||
| 
 | ||||
|       if (thumbnail.size > file.size ~/ 2) { | ||||
|         thumbnail = null; | ||||
|       } | ||||
|     } else if (file is MatrixVideoFile) { | ||||
|       thumbnail = await file.getVideoThumbnail(); | ||||
|     } | ||||
| 
 | ||||
|     return sendFileEvent( | ||||
|       file, | ||||
|       txid: txid, | ||||
|       inReplyTo: inReplyTo, | ||||
|       editEventId: editEventId, | ||||
|       waitUntilSent: waitUntilSent ?? false, | ||||
|       thumbnail: thumbnail, | ||||
|       extraContent: extraContent, | ||||
|     ); | ||||
|   } | ||||
| } | ||||
| @ -486,7 +486,7 @@ packages: | ||||
|       name: flutter_native_splash | ||||
|       url: "https://pub.dartlang.org" | ||||
|     source: hosted | ||||
|     version: "1.3.3" | ||||
|     version: "2.0.1+1" | ||||
|   flutter_olm: | ||||
|     dependency: "direct main" | ||||
|     description: | ||||
| @ -818,7 +818,7 @@ packages: | ||||
|       name: matrix | ||||
|       url: "https://pub.dartlang.org" | ||||
|     source: hosted | ||||
|     version: "0.7.3" | ||||
|     version: "0.8.0" | ||||
|   matrix_api_lite: | ||||
|     dependency: transitive | ||||
|     description: | ||||
|  | ||||
| @ -50,7 +50,7 @@ dependencies: | ||||
|   intl: any | ||||
|   localstorage: ^4.0.0+1 | ||||
|   lottie: ^1.2.1 | ||||
|   matrix: ^0.7.3 | ||||
|   matrix: ^0.8.0 | ||||
|   matrix_link_text: ^1.0.2 | ||||
|   open_noti_settings: ^0.4.0 | ||||
|   package_info_plus: ^1.2.1 | ||||
| @ -82,7 +82,7 @@ dependencies: | ||||
| dev_dependencies: | ||||
|   dart_code_metrics: ^4.2.0-dev.3 | ||||
|   flutter_lints: ^1.0.4 | ||||
|   flutter_native_splash: ^1.2.4 | ||||
|   flutter_native_splash: ^2.0.1+1 | ||||
|   flutter_test: | ||||
|     sdk: flutter | ||||
|   import_sorter: ^4.6.0 | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Krille Fear
						Krille Fear