mirror of
https://github.com/Iconica-Development/flutter_chat.git
synced 2025-05-18 18:33:49 +02:00
feat: improve loading visualisation on the chatdetailscreen
This commit is contained in:
parent
5975e2f1c0
commit
313ead2029
6 changed files with 47 additions and 36 deletions
|
@ -21,6 +21,7 @@
|
||||||
- Added chatScreenBuilder to the userstory configuration to customize the specific chat screen with a ChatModel as argument
|
- Added chatScreenBuilder to the userstory configuration to customize the specific chat screen with a ChatModel as argument
|
||||||
- Added senderTitleResolver to the ChatOptions to resolve the title of the sender in the chat message
|
- Added senderTitleResolver to the ChatOptions to resolve the title of the sender in the chat message
|
||||||
- Added imageProviderResolver to the ChatOptions to resolve ImageProvider for all images in the userstory
|
- Added imageProviderResolver to the ChatOptions to resolve ImageProvider for all images in the userstory
|
||||||
|
- Added enabled boolean to the messageInputBuilder and made parameters named
|
||||||
|
|
||||||
## 4.0.0
|
## 4.0.0
|
||||||
- Move to the new user story architecture
|
- Move to the new user story architecture
|
||||||
|
|
|
@ -122,12 +122,13 @@ typedef ImagePickerBuilder = Future<Uint8List?> Function(
|
||||||
|
|
||||||
/// The text input builder
|
/// The text input builder
|
||||||
typedef TextInputBuilder = Widget Function(
|
typedef TextInputBuilder = Widget Function(
|
||||||
BuildContext context,
|
BuildContext context, {
|
||||||
TextEditingController textEditingController,
|
required TextEditingController textEditingController,
|
||||||
Widget suffixIcon,
|
required Widget suffixIcon,
|
||||||
ChatTranslations translations,
|
required ChatTranslations translations,
|
||||||
VoidCallback onSubmit,
|
required VoidCallback onSubmit,
|
||||||
);
|
required bool enabled,
|
||||||
|
});
|
||||||
|
|
||||||
/// The base screen builder
|
/// The base screen builder
|
||||||
/// [title] is the title of the screen and can be null while loading
|
/// [title] is the title of the screen and can be null while loading
|
||||||
|
|
|
@ -11,7 +11,7 @@ class ChatOptions {
|
||||||
ChatOptions({
|
ChatOptions({
|
||||||
this.dateformat,
|
this.dateformat,
|
||||||
this.groupChatEnabled = true,
|
this.groupChatEnabled = true,
|
||||||
this.enableLoadingIndicator = false,
|
this.enableLoadingIndicator = true,
|
||||||
this.translations = const ChatTranslations.empty(),
|
this.translations = const ChatTranslations.empty(),
|
||||||
this.builders = const ChatBuilders(),
|
this.builders = const ChatBuilders(),
|
||||||
this.spacing = const ChatSpacing(),
|
this.spacing = const ChatSpacing(),
|
||||||
|
|
|
@ -69,6 +69,10 @@ class ChatDetailScreen extends HookWidget {
|
||||||
var usersSnapshot = useStream(allUsersStream);
|
var usersSnapshot = useStream(allUsersStream);
|
||||||
var allUsers = usersSnapshot.data ?? [];
|
var allUsers = usersSnapshot.data ?? [];
|
||||||
|
|
||||||
|
var chatIsloading =
|
||||||
|
chatSnapshot.connectionState == ConnectionState.waiting ||
|
||||||
|
usersSnapshot.connectionState == ConnectionState.waiting;
|
||||||
|
|
||||||
useEffect(
|
useEffect(
|
||||||
() {
|
() {
|
||||||
if (chat == null) return;
|
if (chat == null) return;
|
||||||
|
@ -106,6 +110,7 @@ class ChatDetailScreen extends HookWidget {
|
||||||
onUploadImage: onUploadImage,
|
onUploadImage: onUploadImage,
|
||||||
onMessageSubmit: onMessageSubmit,
|
onMessageSubmit: onMessageSubmit,
|
||||||
onReadChat: onReadChat,
|
onReadChat: onReadChat,
|
||||||
|
chatIsLoading: chatIsloading,
|
||||||
);
|
);
|
||||||
|
|
||||||
if (options.builders.chatScreenBuilder != null) {
|
if (options.builders.chatScreenBuilder != null) {
|
||||||
|
@ -231,6 +236,7 @@ class _ChatBody extends HookWidget {
|
||||||
required this.onUploadImage,
|
required this.onUploadImage,
|
||||||
required this.onMessageSubmit,
|
required this.onMessageSubmit,
|
||||||
required this.onReadChat,
|
required this.onReadChat,
|
||||||
|
required this.chatIsLoading,
|
||||||
});
|
});
|
||||||
|
|
||||||
final String chatId;
|
final String chatId;
|
||||||
|
@ -240,6 +246,7 @@ class _ChatBody extends HookWidget {
|
||||||
final Function(Uint8List image) onUploadImage;
|
final Function(Uint8List image) onUploadImage;
|
||||||
final Function(String text) onMessageSubmit;
|
final Function(String text) onMessageSubmit;
|
||||||
final Function(ChatModel chat) onReadChat;
|
final Function(ChatModel chat) onReadChat;
|
||||||
|
final bool chatIsLoading;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
@ -377,11 +384,6 @@ class _ChatBody extends HookWidget {
|
||||||
[autoScrollEnabled.value],
|
[autoScrollEnabled.value],
|
||||||
);
|
);
|
||||||
|
|
||||||
if (chat == null) {
|
|
||||||
if (!options.enableLoadingIndicator) return const SizedBox.shrink();
|
|
||||||
return options.builders.loadingWidgetBuilder.call(context);
|
|
||||||
}
|
|
||||||
|
|
||||||
var userMap = <String, UserModel>{};
|
var userMap = <String, UserModel>{};
|
||||||
for (var u in chatUsers) {
|
for (var u in chatUsers) {
|
||||||
userMap[u.id] = u;
|
userMap[u.id] = u;
|
||||||
|
@ -424,18 +426,23 @@ class _ChatBody extends HookWidget {
|
||||||
|
|
||||||
return Column(
|
return Column(
|
||||||
children: [
|
children: [
|
||||||
Expanded(
|
if (chatIsLoading && options.enableLoadingIndicator) ...[
|
||||||
child: ListView.builder(
|
Expanded(child: options.builders.loadingWidgetBuilder.call(context)),
|
||||||
reverse: false,
|
] else ...[
|
||||||
controller: scrollController,
|
Expanded(
|
||||||
physics: const AlwaysScrollableScrollPhysics(),
|
child: ListView.builder(
|
||||||
padding: const EdgeInsets.only(top: 24),
|
reverse: false,
|
||||||
itemCount: listViewChildren.length,
|
controller: scrollController,
|
||||||
itemBuilder: (context, index) => listViewChildren[index],
|
physics: const AlwaysScrollableScrollPhysics(),
|
||||||
|
padding: const EdgeInsets.only(top: 24),
|
||||||
|
itemCount: listViewChildren.length,
|
||||||
|
itemBuilder: (context, index) => listViewChildren[index],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
],
|
||||||
ChatBottomInputSection(
|
ChatBottomInputSection(
|
||||||
chat: chat!,
|
chat: chat,
|
||||||
|
isLoading: chatIsLoading,
|
||||||
onPressSelectImage: () async => onPressSelectImage(
|
onPressSelectImage: () async => onPressSelectImage(
|
||||||
context,
|
context,
|
||||||
options,
|
options,
|
||||||
|
|
|
@ -8,13 +8,18 @@ class ChatBottomInputSection extends HookWidget {
|
||||||
/// Creates a new [ChatBottomInputSection].
|
/// Creates a new [ChatBottomInputSection].
|
||||||
const ChatBottomInputSection({
|
const ChatBottomInputSection({
|
||||||
required this.chat,
|
required this.chat,
|
||||||
|
required this.isLoading,
|
||||||
required this.onMessageSubmit,
|
required this.onMessageSubmit,
|
||||||
this.onPressSelectImage,
|
this.onPressSelectImage,
|
||||||
super.key,
|
super.key,
|
||||||
});
|
});
|
||||||
|
|
||||||
/// The chat model.
|
/// The chat model.
|
||||||
final ChatModel chat;
|
final ChatModel? chat;
|
||||||
|
|
||||||
|
/// Whether the chat is still loading.
|
||||||
|
/// The inputfield is disabled when the chat is loading.
|
||||||
|
final bool isLoading;
|
||||||
|
|
||||||
/// Callback function invoked when a message is submitted.
|
/// Callback function invoked when a message is submitted.
|
||||||
final Function(String text) onMessageSubmit;
|
final Function(String text) onMessageSubmit;
|
||||||
|
@ -65,7 +70,7 @@ class ChatBottomInputSection extends HookWidget {
|
||||||
children: [
|
children: [
|
||||||
IconButton(
|
IconButton(
|
||||||
alignment: Alignment.bottomRight,
|
alignment: Alignment.bottomRight,
|
||||||
onPressed: onPressSelectImage,
|
onPressed: isLoading ? null : onPressSelectImage,
|
||||||
icon: Icon(
|
icon: Icon(
|
||||||
Icons.image_outlined,
|
Icons.image_outlined,
|
||||||
color: options.iconEnabledColor,
|
color: options.iconEnabledColor,
|
||||||
|
@ -75,7 +80,7 @@ class ChatBottomInputSection extends HookWidget {
|
||||||
alignment: Alignment.bottomRight,
|
alignment: Alignment.bottomRight,
|
||||||
disabledColor: options.iconDisabledColor,
|
disabledColor: options.iconDisabledColor,
|
||||||
color: options.iconEnabledColor,
|
color: options.iconEnabledColor,
|
||||||
onPressed: onClickSendMessage,
|
onPressed: isLoading ? null : onClickSendMessage,
|
||||||
icon: const Icon(Icons.send_rounded),
|
icon: const Icon(Icons.send_rounded),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
@ -95,6 +100,7 @@ class ChatBottomInputSection extends HookWidget {
|
||||||
keyboardType: TextInputType.multiline,
|
keyboardType: TextInputType.multiline,
|
||||||
maxLines: null,
|
maxLines: null,
|
||||||
controller: textController,
|
controller: textController,
|
||||||
|
enabled: !isLoading,
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
enabledBorder: OutlineInputBorder(
|
enabledBorder: OutlineInputBorder(
|
||||||
borderRadius: BorderRadius.circular(25),
|
borderRadius: BorderRadius.circular(25),
|
||||||
|
@ -141,10 +147,11 @@ class ChatBottomInputSection extends HookWidget {
|
||||||
constraints: const BoxConstraints(maxHeight: 120, minHeight: 45),
|
constraints: const BoxConstraints(maxHeight: 120, minHeight: 45),
|
||||||
child: options.builders.messageInputBuilder?.call(
|
child: options.builders.messageInputBuilder?.call(
|
||||||
context,
|
context,
|
||||||
textController,
|
textEditingController: textController,
|
||||||
messageSendButtons,
|
suffixIcon: messageSendButtons,
|
||||||
options.translations,
|
translations: options.translations,
|
||||||
onSubmitField,
|
onSubmit: onSubmitField,
|
||||||
|
enabled: !isLoading,
|
||||||
) ??
|
) ??
|
||||||
defaultInputField,
|
defaultInputField,
|
||||||
),
|
),
|
||||||
|
|
|
@ -11,13 +11,8 @@ class DefaultChatLoadingOverlay extends StatelessWidget {
|
||||||
const DefaultChatLoadingOverlay();
|
const DefaultChatLoadingOverlay();
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) => const Column(
|
Widget build(BuildContext context) =>
|
||||||
children: [
|
const Center(child: CircularProgressIndicator());
|
||||||
SizedBox(height: 12),
|
|
||||||
Center(child: CircularProgressIndicator()),
|
|
||||||
SizedBox(height: 12),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A small row spinner item to show partial loading
|
/// A small row spinner item to show partial loading
|
||||||
|
|
Loading…
Reference in a new issue