From 3fbcf5d076f1ade04c20cde7eefd299857ae37aa Mon Sep 17 00:00:00 2001 From: Kiril Tijsma Date: Mon, 10 Mar 2025 11:26:01 +0100 Subject: [PATCH] feat(chat-service/pending-messages): add pending images --- .../lib/src/extension/uint8list_data_uri.dart | 25 +++++++++++++++++++ .../lib/src/local/local_chat_repository.dart | 3 ++- .../lib/src/services/chat_service.dart | 4 ++- .../chat_repository_interface/pubspec.yaml | 1 + .../lib/src/config/chat_options.dart | 5 +++- packages/flutter_chat/lib/src/routes.dart | 1 + 6 files changed, 36 insertions(+), 3 deletions(-) create mode 100644 packages/chat_repository_interface/lib/src/extension/uint8list_data_uri.dart diff --git a/packages/chat_repository_interface/lib/src/extension/uint8list_data_uri.dart b/packages/chat_repository_interface/lib/src/extension/uint8list_data_uri.dart new file mode 100644 index 0000000..940fe84 --- /dev/null +++ b/packages/chat_repository_interface/lib/src/extension/uint8list_data_uri.dart @@ -0,0 +1,25 @@ +import "dart:convert"; +import "dart:typed_data"; +import "package:mime/mime.dart"; + +/// Error thrown when there is no +/// mimetype found +class MimetypeMissingError extends Error { + @override + String toString() => "You can only provide files that contain a mimetype"; +} + +/// Extension that provides a converter function from +/// Uin8List to a base64Encoded data uri. +extension ToDataUri on Uint8List { + /// This function converts the Uint8List into + /// a uri with a data-scheme. + String toDataUri() { + var mimeType = lookupMimeType("", headerBytes: this); + if (mimeType == null) throw MimetypeMissingError(); + + var base64Data = base64Encode(this); + + return "data:$mimeType;base64,$base64Data"; + } +} diff --git a/packages/chat_repository_interface/lib/src/local/local_chat_repository.dart b/packages/chat_repository_interface/lib/src/local/local_chat_repository.dart index 6defe58..a0f45e7 100644 --- a/packages/chat_repository_interface/lib/src/local/local_chat_repository.dart +++ b/packages/chat_repository_interface/lib/src/local/local_chat_repository.dart @@ -3,6 +3,7 @@ import "dart:math" as math; import "dart:typed_data"; import "package:chat_repository_interface/chat_repository_interface.dart"; +import "package:chat_repository_interface/src/extension/uint8list_data_uri.dart"; import "package:chat_repository_interface/src/local/local_memory_db.dart"; import "package:collection/collection.dart"; import "package:rxdart/rxdart.dart"; @@ -272,7 +273,7 @@ class LocalChatRepository implements ChatRepositoryInterface { required String chatId, required String senderId, }) => - Future.value("https://picsum.photos/200/300"); + Future.value(image.toDataUri()); /// All the chats of the local memory database List get getLocalChats => chats; diff --git a/packages/chat_repository_interface/lib/src/services/chat_service.dart b/packages/chat_repository_interface/lib/src/services/chat_service.dart index 0ff32db..6d5d8ea 100644 --- a/packages/chat_repository_interface/lib/src/services/chat_service.dart +++ b/packages/chat_repository_interface/lib/src/services/chat_service.dart @@ -1,6 +1,7 @@ import "dart:async"; import "dart:typed_data"; +import "package:chat_repository_interface/src/extension/uint8list_data_uri.dart"; import "package:chat_repository_interface/src/interfaces/chat_repostory_interface.dart"; import "package:chat_repository_interface/src/interfaces/pending_message_repository_interface.dart"; import "package:chat_repository_interface/src/interfaces/user_repository_interface.dart"; @@ -203,6 +204,7 @@ class ChatService { String? text, String? messageType, String? imageUrl, + Uint8List? imageData, }) async { await pendingMessageRepository.createMessage( chatId: chatId, @@ -210,7 +212,7 @@ class ChatService { messageId: messageId, text: text, messageType: messageType, - imageUrl: imageUrl, + imageUrl: imageData?.toDataUri() ?? imageUrl, ); unawaited( diff --git a/packages/chat_repository_interface/pubspec.yaml b/packages/chat_repository_interface/pubspec.yaml index 482ab27..c4aa64a 100644 --- a/packages/chat_repository_interface/pubspec.yaml +++ b/packages/chat_repository_interface/pubspec.yaml @@ -9,6 +9,7 @@ environment: sdk: ">=3.4.3 <4.0.0" dependencies: + mime: any rxdart: any collection: any diff --git a/packages/flutter_chat/lib/src/config/chat_options.dart b/packages/flutter_chat/lib/src/config/chat_options.dart index 4ee7526..2799d7a 100644 --- a/packages/flutter_chat/lib/src/config/chat_options.dart +++ b/packages/flutter_chat/lib/src/config/chat_options.dart @@ -284,7 +284,10 @@ ImageProvider _defaultImageProviderResolver( BuildContext context, Uri image, ) => - CachedNetworkImageProvider(image.toString()); + switch (image.scheme) { + "data" => MemoryImage(image.data!.contentAsBytes()), + _ => CachedNetworkImageProvider(image.toString()), + }; /// All configurable paddings and whitespaces within the userstory class ChatSpacing { diff --git a/packages/flutter_chat/lib/src/routes.dart b/packages/flutter_chat/lib/src/routes.dart index 952fc81..8682754 100644 --- a/packages/flutter_chat/lib/src/routes.dart +++ b/packages/flutter_chat/lib/src/routes.dart @@ -61,6 +61,7 @@ MaterialPageRoute chatDetailRoute({ chatId: chatId, senderId: userId, imageUrl: path, + imageData: data, ); }, onMessageSubmit: (text) async {