mirror of
https://github.com/Iconica-Development/flutter_chat.git
synced 2025-05-18 18:33:49 +02:00
feat: add imagePickerBuilder to builders to override the default imagepicker for selecting an image
This commit is contained in:
parent
0fc0153463
commit
4e9feeadb2
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
|
||||
- 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 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
|
||||
- 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:flutter/material.dart";
|
||||
import "package:flutter_chat/src/config/chat_translations.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_message_builder.dart";
|
||||
import "package:flutter_chat/src/screens/creation/widgets/default_image_picker.dart";
|
||||
|
||||
/// The chat builders
|
||||
class ChatBuilders {
|
||||
|
@ -20,6 +23,7 @@ class ChatBuilders {
|
|||
this.noUsersPlaceholderBuilder,
|
||||
this.chatTitleBuilder,
|
||||
this.chatMessageBuilder = DefaultChatMessageBuilder.builder,
|
||||
this.imagePickerBuilder = DefaultImagePickerDialog.builder,
|
||||
this.usernameBuilder,
|
||||
this.loadingWidgetBuilder = DefaultChatLoadingOverlay.builder,
|
||||
this.loadingChatMessageBuilder = DefaultChatMessageLoader.builder,
|
||||
|
@ -75,6 +79,11 @@ class ChatBuilders {
|
|||
/// The image picker container builder
|
||||
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
|
||||
/// This is used to build the loading widget that is displayed on the chat
|
||||
/// screen when loading the chat
|
||||
|
@ -100,6 +109,11 @@ typedef ImagePickerContainerBuilder = Widget Function(
|
|||
ChatTranslations translations,
|
||||
);
|
||||
|
||||
/// Builder definition for providing an image picker implementation
|
||||
typedef ImagePickerBuilder = Future<Uint8List?> Function(
|
||||
BuildContext context,
|
||||
);
|
||||
|
||||
/// The text input builder
|
||||
typedef TextInputBuilder = Widget Function(
|
||||
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/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/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_hooks/flutter_hooks.dart";
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@ import "dart:typed_data";
|
|||
import "package:chat_repository_interface/chat_repository_interface.dart";
|
||||
import "package:flutter/material.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_hooks/flutter_hooks.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