mirror of
https://github.com/Iconica-Development/flutter_chat.git
synced 2025-05-19 10:53:51 +02:00
feat: add imagePickerBuilder to builders to override the default imagepicker for selecting an image
This commit is contained in:
parent
cfb11d01ab
commit
ba112415fd
6 changed files with 122 additions and 85 deletions
|
@ -16,6 +16,7 @@
|
||||||
- Added ChatPaginationControls to the ChatOptions to allow for more control over the pagination
|
- Added ChatPaginationControls to the ChatOptions to allow for more control over the pagination
|
||||||
- Fixed that chat message is automatically sent when the user presses enter on the keyboard in the chat input
|
- Fixed that chat message is automatically sent when the user presses enter on the keyboard in the chat input
|
||||||
- Added sender and chatId to uploadImage in the ChatRepositoryInterface
|
- Added sender and chatId to uploadImage in the ChatRepositoryInterface
|
||||||
|
- Added imagePickerBuilder to the builders in the ChatOptions to override the image picker with a custom implementation that needs to return a Future<Uint8List?>
|
||||||
|
|
||||||
## 4.0.0
|
## 4.0.0
|
||||||
- Move to the new user story architecture
|
- Move to the new user story architecture
|
||||||
|
|
|
@ -1,9 +1,12 @@
|
||||||
|
import "dart:typed_data";
|
||||||
|
|
||||||
import "package:chat_repository_interface/chat_repository_interface.dart";
|
import "package:chat_repository_interface/chat_repository_interface.dart";
|
||||||
import "package:flutter/material.dart";
|
import "package:flutter/material.dart";
|
||||||
import "package:flutter_chat/src/config/chat_translations.dart";
|
import "package:flutter_chat/src/config/chat_translations.dart";
|
||||||
import "package:flutter_chat/src/config/screen_types.dart";
|
import "package:flutter_chat/src/config/screen_types.dart";
|
||||||
import "package:flutter_chat/src/screens/chat_detail/widgets/default_loader.dart";
|
import "package:flutter_chat/src/screens/chat_detail/widgets/default_loader.dart";
|
||||||
import "package:flutter_chat/src/screens/chat_detail/widgets/default_message_builder.dart";
|
import "package:flutter_chat/src/screens/chat_detail/widgets/default_message_builder.dart";
|
||||||
|
import "package:flutter_chat/src/screens/creation/widgets/default_image_picker.dart";
|
||||||
|
|
||||||
/// The chat builders
|
/// The chat builders
|
||||||
class ChatBuilders {
|
class ChatBuilders {
|
||||||
|
@ -20,6 +23,7 @@ class ChatBuilders {
|
||||||
this.noUsersPlaceholderBuilder,
|
this.noUsersPlaceholderBuilder,
|
||||||
this.chatTitleBuilder,
|
this.chatTitleBuilder,
|
||||||
this.chatMessageBuilder = DefaultChatMessageBuilder.builder,
|
this.chatMessageBuilder = DefaultChatMessageBuilder.builder,
|
||||||
|
this.imagePickerBuilder = DefaultImagePickerDialog.builder,
|
||||||
this.usernameBuilder,
|
this.usernameBuilder,
|
||||||
this.loadingWidgetBuilder = DefaultChatLoadingOverlay.builder,
|
this.loadingWidgetBuilder = DefaultChatLoadingOverlay.builder,
|
||||||
this.loadingChatMessageBuilder = DefaultChatMessageLoader.builder,
|
this.loadingChatMessageBuilder = DefaultChatMessageLoader.builder,
|
||||||
|
@ -75,6 +79,11 @@ class ChatBuilders {
|
||||||
/// The image picker container builder
|
/// The image picker container builder
|
||||||
final ImagePickerContainerBuilder? imagePickerContainerBuilder;
|
final ImagePickerContainerBuilder? imagePickerContainerBuilder;
|
||||||
|
|
||||||
|
/// A way to provide your own image picker implementation
|
||||||
|
/// If not provided the [DefaultImagePicker.builder] will be used which
|
||||||
|
/// shows a modal buttom sheet with the option for a camera or gallery image
|
||||||
|
final ImagePickerBuilder imagePickerBuilder;
|
||||||
|
|
||||||
/// The loading widget builder
|
/// The loading widget builder
|
||||||
/// This is used to build the loading widget that is displayed on the chat
|
/// This is used to build the loading widget that is displayed on the chat
|
||||||
/// screen when loading the chat
|
/// screen when loading the chat
|
||||||
|
@ -100,6 +109,11 @@ typedef ImagePickerContainerBuilder = Widget Function(
|
||||||
ChatTranslations translations,
|
ChatTranslations translations,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/// Builder definition for providing an image picker implementation
|
||||||
|
typedef ImagePickerBuilder = Future<Uint8List?> Function(
|
||||||
|
BuildContext context,
|
||||||
|
);
|
||||||
|
|
||||||
/// The text input builder
|
/// The text input builder
|
||||||
typedef TextInputBuilder = Widget Function(
|
typedef TextInputBuilder = Widget Function(
|
||||||
BuildContext context,
|
BuildContext context,
|
||||||
|
|
|
@ -6,7 +6,7 @@ import "package:flutter/material.dart";
|
||||||
import "package:flutter_chat/src/config/screen_types.dart";
|
import "package:flutter_chat/src/config/screen_types.dart";
|
||||||
import "package:flutter_chat/src/screens/chat_detail/widgets/chat_bottom.dart";
|
import "package:flutter_chat/src/screens/chat_detail/widgets/chat_bottom.dart";
|
||||||
import "package:flutter_chat/src/screens/chat_detail/widgets/chat_widgets.dart";
|
import "package:flutter_chat/src/screens/chat_detail/widgets/chat_widgets.dart";
|
||||||
import "package:flutter_chat/src/screens/creation/widgets/image_picker.dart";
|
import "package:flutter_chat/src/screens/creation/widgets/default_image_picker.dart";
|
||||||
import "package:flutter_chat/src/util/scope.dart";
|
import "package:flutter_chat/src/util/scope.dart";
|
||||||
import "package:flutter_hooks/flutter_hooks.dart";
|
import "package:flutter_hooks/flutter_hooks.dart";
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@ import "dart:typed_data";
|
||||||
import "package:chat_repository_interface/chat_repository_interface.dart";
|
import "package:chat_repository_interface/chat_repository_interface.dart";
|
||||||
import "package:flutter/material.dart";
|
import "package:flutter/material.dart";
|
||||||
import "package:flutter_chat/src/config/screen_types.dart";
|
import "package:flutter_chat/src/config/screen_types.dart";
|
||||||
import "package:flutter_chat/src/screens/creation/widgets/image_picker.dart";
|
import "package:flutter_chat/src/screens/creation/widgets/default_image_picker.dart";
|
||||||
import "package:flutter_chat/src/util/scope.dart";
|
import "package:flutter_chat/src/util/scope.dart";
|
||||||
import "package:flutter_hooks/flutter_hooks.dart";
|
import "package:flutter_hooks/flutter_hooks.dart";
|
||||||
import "package:flutter_profile/flutter_profile.dart";
|
import "package:flutter_profile/flutter_profile.dart";
|
||||||
|
|
|
@ -0,0 +1,105 @@
|
||||||
|
import "dart:typed_data";
|
||||||
|
|
||||||
|
import "package:flutter/material.dart";
|
||||||
|
import "package:flutter_chat/src/config/chat_options.dart";
|
||||||
|
import "package:flutter_chat/src/config/chat_translations.dart";
|
||||||
|
import "package:flutter_chat/src/util/scope.dart";
|
||||||
|
import "package:flutter_image_picker/flutter_image_picker.dart";
|
||||||
|
|
||||||
|
/// The function to call when the user selects an image
|
||||||
|
Future<void> onPressSelectImage(
|
||||||
|
BuildContext context,
|
||||||
|
ChatOptions options,
|
||||||
|
Function(Uint8List image) onUploadImage,
|
||||||
|
) async {
|
||||||
|
var image = await options.builders.imagePickerBuilder.call(context);
|
||||||
|
|
||||||
|
if (image == null) return;
|
||||||
|
if (!context.mounted) return;
|
||||||
|
var messenger = ScaffoldMessenger.of(context)
|
||||||
|
..showSnackBar(
|
||||||
|
_getImageLoadingSnackbar(options.translations),
|
||||||
|
)
|
||||||
|
..activate();
|
||||||
|
await onUploadImage(image);
|
||||||
|
await Future.delayed(const Duration(seconds: 1));
|
||||||
|
messenger.hideCurrentSnackBar();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Default image picker dialog for selecting an image from the gallery or
|
||||||
|
/// taking a photo.
|
||||||
|
class DefaultImagePickerDialog extends StatelessWidget {
|
||||||
|
/// Creates a new default image picker dialog.
|
||||||
|
const DefaultImagePickerDialog({
|
||||||
|
super.key,
|
||||||
|
});
|
||||||
|
|
||||||
|
/// Builds the default image picker dialog.
|
||||||
|
static Future<Uint8List?> builder(BuildContext context) async =>
|
||||||
|
showModalBottomSheet<Uint8List?>(
|
||||||
|
context: context,
|
||||||
|
builder: (context) => const DefaultImagePickerDialog(),
|
||||||
|
);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
var chatScope = ChatScope.of(context);
|
||||||
|
var options = chatScope.options;
|
||||||
|
var translations = options.translations;
|
||||||
|
var theme = Theme.of(context);
|
||||||
|
var textTheme = theme.textTheme;
|
||||||
|
|
||||||
|
return options.builders.imagePickerContainerBuilder?.call(
|
||||||
|
context,
|
||||||
|
() => Navigator.of(context).pop(),
|
||||||
|
translations,
|
||||||
|
) ??
|
||||||
|
Container(
|
||||||
|
padding: const EdgeInsets.all(8.0),
|
||||||
|
color: Colors.white,
|
||||||
|
child: ImagePicker(
|
||||||
|
theme: ImagePickerTheme(
|
||||||
|
spaceBetweenIcons: 32.0,
|
||||||
|
iconColor: theme.primaryColor,
|
||||||
|
title: translations.imagePickerTitle,
|
||||||
|
titleStyle: textTheme.titleMedium,
|
||||||
|
iconSize: 60.0,
|
||||||
|
makePhotoText: translations.takePicture,
|
||||||
|
selectImageText: translations.uploadFile,
|
||||||
|
selectImageIcon: Icon(
|
||||||
|
color: theme.primaryColor,
|
||||||
|
Icons.insert_drive_file_rounded,
|
||||||
|
size: 60,
|
||||||
|
),
|
||||||
|
closeButtonBuilder: (ontap) => TextButton(
|
||||||
|
onPressed: () => Navigator.of(context).pop(),
|
||||||
|
child: Text(
|
||||||
|
translations.cancelImagePickerBtn,
|
||||||
|
style: textTheme.bodyMedium!.copyWith(
|
||||||
|
fontSize: 18,
|
||||||
|
decoration: TextDecoration.underline,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SnackBar _getImageLoadingSnackbar(ChatTranslations translations) => SnackBar(
|
||||||
|
duration: const Duration(minutes: 1),
|
||||||
|
content: Row(
|
||||||
|
children: [
|
||||||
|
const SizedBox(
|
||||||
|
width: 25,
|
||||||
|
height: 25,
|
||||||
|
child: CircularProgressIndicator(color: Colors.grey),
|
||||||
|
),
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.only(left: 16.0),
|
||||||
|
child: Text(translations.imageUploading),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
|
@ -1,83 +0,0 @@
|
||||||
import "dart:typed_data";
|
|
||||||
|
|
||||||
import "package:flutter/material.dart";
|
|
||||||
import "package:flutter_chat/src/config/chat_options.dart";
|
|
||||||
import "package:flutter_chat/src/config/chat_translations.dart";
|
|
||||||
import "package:flutter_image_picker/flutter_image_picker.dart";
|
|
||||||
|
|
||||||
/// The function to call when the user selects an image
|
|
||||||
Future<void> onPressSelectImage(
|
|
||||||
BuildContext context,
|
|
||||||
ChatOptions options,
|
|
||||||
Function(Uint8List image) onUploadImage,
|
|
||||||
) async =>
|
|
||||||
showModalBottomSheet<Uint8List?>(
|
|
||||||
context: context,
|
|
||||||
builder: (BuildContext context) =>
|
|
||||||
options.builders.imagePickerContainerBuilder?.call(
|
|
||||||
context,
|
|
||||||
() => Navigator.of(context).pop(),
|
|
||||||
options.translations,
|
|
||||||
) ??
|
|
||||||
Container(
|
|
||||||
padding: const EdgeInsets.all(8.0),
|
|
||||||
color: Colors.white,
|
|
||||||
child: ImagePicker(
|
|
||||||
theme: ImagePickerTheme(
|
|
||||||
spaceBetweenIcons: 32.0,
|
|
||||||
iconColor: Theme.of(context).primaryColor,
|
|
||||||
title: options.translations.imagePickerTitle,
|
|
||||||
titleStyle: Theme.of(context).textTheme.titleMedium,
|
|
||||||
iconSize: 60.0,
|
|
||||||
makePhotoText: options.translations.takePicture,
|
|
||||||
selectImageText: options.translations.uploadFile,
|
|
||||||
selectImageIcon: Icon(
|
|
||||||
color: Theme.of(context).primaryColor,
|
|
||||||
Icons.insert_drive_file_rounded,
|
|
||||||
size: 60,
|
|
||||||
),
|
|
||||||
closeButtonBuilder: (ontap) => TextButton(
|
|
||||||
onPressed: () => Navigator.of(context).pop(),
|
|
||||||
child: Text(
|
|
||||||
options.translations.cancelImagePickerBtn,
|
|
||||||
style: Theme.of(context).textTheme.bodyMedium!.copyWith(
|
|
||||||
fontSize: 18,
|
|
||||||
decoration: TextDecoration.underline,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
).then(
|
|
||||||
(image) async {
|
|
||||||
if (image == null) return;
|
|
||||||
if (!context.mounted) return;
|
|
||||||
var messenger = ScaffoldMessenger.of(context)
|
|
||||||
..showSnackBar(
|
|
||||||
_getImageLoadingSnackbar(options.translations),
|
|
||||||
)
|
|
||||||
..activate();
|
|
||||||
await onUploadImage(image);
|
|
||||||
Future.delayed(const Duration(seconds: 1), () {
|
|
||||||
messenger.hideCurrentSnackBar();
|
|
||||||
});
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
SnackBar _getImageLoadingSnackbar(ChatTranslations translations) => SnackBar(
|
|
||||||
duration: const Duration(minutes: 1),
|
|
||||||
content: Row(
|
|
||||||
children: [
|
|
||||||
const SizedBox(
|
|
||||||
width: 25,
|
|
||||||
height: 25,
|
|
||||||
child: CircularProgressIndicator(color: Colors.grey),
|
|
||||||
),
|
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.only(left: 16.0),
|
|
||||||
child: Text(translations.imageUploading),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
);
|
|
Loading…
Reference in a new issue