diff --git a/lib/src/services/api/mediafiles/upload.service.dart b/lib/src/services/api/mediafiles/upload.service.dart index afbe91d..0c2e930 100644 --- a/lib/src/services/api/mediafiles/upload.service.dart +++ b/lib/src/services/api/mediafiles/upload.service.dart @@ -87,7 +87,6 @@ Future initializeMediaUpload( Future insertMediaFileInMessagesTable( MediaFileService mediaService, List groupIds, - Future? imageStoreAwait, ) async { await twonlyDB.mediaFilesDao.updateAllMediaFiles( const MediaFilesCompanion( @@ -118,13 +117,6 @@ Future insertMediaFileInMessagesTable( } } - if (imageStoreAwait != null) { - if (await imageStoreAwait == null) { - Log.error('image store as original did return false...'); - return; - } - } - unawaited(startBackgroundMediaUpload(mediaService)); } diff --git a/lib/src/views/camera/image_editor/data/layer.dart b/lib/src/views/camera/image_editor/data/layer.dart index fb1fdd9..b8e8622 100755 --- a/lib/src/views/camera/image_editor/data/layer.dart +++ b/lib/src/views/camera/image_editor/data/layer.dart @@ -35,6 +35,7 @@ class BackgroundLayerData extends Layer { required this.image, }); ImageItem image; + bool imageLoaded = false; } class FilterLayerData extends Layer { diff --git a/lib/src/views/camera/image_editor/layers/background_layer.dart b/lib/src/views/camera/image_editor/layers/background_layer.dart index e69ca60..300ae17 100755 --- a/lib/src/views/camera/image_editor/layers/background_layer.dart +++ b/lib/src/views/camera/image_editor/layers/background_layer.dart @@ -1,7 +1,6 @@ import 'package:flutter/material.dart'; import 'package:twonly/src/views/camera/image_editor/data/layer.dart'; -/// Main layer class BackgroundLayer extends StatefulWidget { const BackgroundLayer({ required this.layerData, @@ -23,7 +22,17 @@ class _BackgroundLayerState extends State { height: widget.layerData.image.height.toDouble(), // color: Theme.of(context).colorScheme.surface, padding: EdgeInsets.zero, - child: Image.memory(widget.layerData.image.bytes), + child: Image.memory( + widget.layerData.image.bytes, + frameBuilder: (context, child, frame, wasSynchronouslyLoaded) { + if (wasSynchronouslyLoaded || frame != null) { + WidgetsBinding.instance.addPostFrameCallback((_) { + widget.layerData.imageLoaded = true; + }); + } + return child; + }, + ), ); } } diff --git a/lib/src/views/camera/share_image_editor_view.dart b/lib/src/views/camera/share_image_editor_view.dart index 3b87ed7..3f12c0e 100644 --- a/lib/src/views/camera/share_image_editor_view.dart +++ b/lib/src/views/camera/share_image_editor_view.dart @@ -64,6 +64,7 @@ class _ShareImageEditorView extends State { VideoPlayerController? videoController; ImageItem currentImage = ImageItem(); ScreenshotController screenshotController = ScreenshotController(); + Timer? _imageLoadingTimer; MediaFileService get mediaService => widget.mediaFileService; MediaFile get media => widget.mediaFileService.mediaFile; @@ -120,6 +121,7 @@ class _ShareImageEditorView extends State { isDraftMedia: Value(false), ), ); + _imageLoadingTimer?.cancel(); super.dispose(); } @@ -535,16 +537,34 @@ class _ShareImageEditorView extends State { } }); - layers.insert( - 0, - BackgroundLayerData( - key: GlobalKey(), - image: currentImage, - ), - ); setState(() { - sendingOrLoadingImage = false; - loadingImage = false; + layers.insert( + 0, + BackgroundLayerData( + key: GlobalKey(), + image: currentImage, + ), + ); + }); + // It is important that the user can sending the image only when the image is fully loaded otherwise if the user + // will click on send before the image is painted the screenshot will be transparent.. + _imageLoadingTimer = + Timer.periodic(const Duration(milliseconds: 10), (timer) { + final imageLayer = layers.first; + if (imageLayer is BackgroundLayerData) { + if (imageLayer.imageLoaded) { + timer.cancel(); + Future.delayed(const Duration(milliseconds: 50), () { + Log.info(imageLayer.imageLoaded); + if (context.mounted) { + setState(() { + sendingOrLoadingImage = false; + loadingImage = false; + }); + } + }); + } + } }); } @@ -556,16 +576,16 @@ class _ShareImageEditorView extends State { if (!context.mounted) return; + // must be awaited so the widget for the screenshot is not already disposed when sending.. + await storeImageAsOriginal(); + // Insert media file into the messages database and start uploading process in the background - unawaited( - insertMediaFileInMessagesTable( - mediaService, - [widget.sendToGroup!.groupId], - storeImageAsOriginal(), - ), + await insertMediaFileInMessagesTable( + mediaService, + [widget.sendToGroup!.groupId], ); - if (context.mounted) { + if (mounted) { Navigator.pop(context, true); } } diff --git a/lib/src/views/camera/share_image_view.dart b/lib/src/views/camera/share_image_view.dart index 83a4ed3..423725c 100644 --- a/lib/src/views/camera/share_image_view.dart +++ b/lib/src/views/camera/share_image_view.dart @@ -286,7 +286,6 @@ class _ShareImageView extends State { await insertMediaFileInMessagesTable( widget.mediaFileService, widget.selectedGroupIds.toList(), - null, ); if (context.mounted) { diff --git a/lib/src/views/chats/chat_messages_components/message_input.dart b/lib/src/views/chats/chat_messages_components/message_input.dart index cf0a1bb..24d252a 100644 --- a/lib/src/views/chats/chat_messages_components/message_input.dart +++ b/lib/src/views/chats/chat_messages_components/message_input.dart @@ -151,7 +151,6 @@ class _MessageInputState extends State { await insertMediaFileInMessagesTable( mediaFileService, [widget.group.groupId], - null, ); }