mirror of
https://github.com/Iconica-Development/flutter_chat.git
synced 2025-05-18 18:33:49 +02:00
feat: add pagination controls to ChatOptions
This commit is contained in:
parent
ab8a9d9e6f
commit
f57ba9a736
5 changed files with 69 additions and 28 deletions
|
@ -13,6 +13,7 @@
|
|||
- Changed baseScreenBuilder to include a chatTitle that can be used to show provide the title logic to apps that use the baseScreenBuilder
|
||||
- Added loadNewMessagesAfter, loadOldMessagesBefore and removed pagination from getMessages in the ChatRepositoryInterface to change pagination behavior to rely on the stream and two methods indicating that more messages should be added to the stream
|
||||
- Added chatTitleResolver that can be used to resolve the chat title from the chat model or return null to allow for default behavior
|
||||
- Added ChatPaginationControls to the ChatOptions to allow for more control over the pagination
|
||||
|
||||
## 4.0.0
|
||||
- Move to the new user story architecture
|
||||
|
|
|
@ -22,6 +22,7 @@ class ChatBuilders {
|
|||
this.chatMessageBuilder = DefaultChatMessageBuilder.builder,
|
||||
this.usernameBuilder,
|
||||
this.loadingWidgetBuilder = DefaultChatLoadingOverlay.builder,
|
||||
this.loadingChatMessageBuilder = DefaultChatMessageLoader.builder,
|
||||
});
|
||||
|
||||
/// The base screen builder
|
||||
|
@ -75,7 +76,14 @@ class ChatBuilders {
|
|||
final ImagePickerContainerBuilder? imagePickerContainerBuilder;
|
||||
|
||||
/// The loading widget builder
|
||||
final Widget Function(BuildContext context) loadingWidgetBuilder;
|
||||
/// This is used to build the loading widget that is displayed on the chat
|
||||
/// screen when loading the chat
|
||||
final WidgetBuilder loadingWidgetBuilder;
|
||||
|
||||
/// The loading widget builder for chat messages
|
||||
/// This is displayed in the list of chat messages when loading more messages
|
||||
/// can be above and below the list
|
||||
final WidgetBuilder loadingChatMessageBuilder;
|
||||
}
|
||||
|
||||
/// The button builder
|
||||
|
|
|
@ -14,6 +14,7 @@ class ChatOptions {
|
|||
this.translations = const ChatTranslations.empty(),
|
||||
this.builders = const ChatBuilders(),
|
||||
this.spacing = const ChatSpacing(),
|
||||
this.paginationControls = const ChatPaginationControls(),
|
||||
this.messageTheme,
|
||||
this.messageThemeResolver = _defaultMessageThemeResolver,
|
||||
this.chatTitleResolver,
|
||||
|
@ -45,6 +46,9 @@ class ChatOptions {
|
|||
//// The spacing between elements of the chat
|
||||
final ChatSpacing spacing;
|
||||
|
||||
/// The pagination settings for the chat
|
||||
final ChatPaginationControls paginationControls;
|
||||
|
||||
/// [groupChatEnabled] is a boolean that indicates if group chat is enabled.
|
||||
final bool groupChatEnabled;
|
||||
|
||||
|
@ -230,3 +234,24 @@ class ChatSpacing {
|
|||
/// sender.
|
||||
final double chatBetweenMessagesPadding;
|
||||
}
|
||||
|
||||
/// The chat pagination controls
|
||||
/// Use this to define how sensitive the chat pagination should be.
|
||||
class ChatPaginationControls {
|
||||
/// The chat pagination controls constructor
|
||||
const ChatPaginationControls({
|
||||
this.scrollOffset = 50.0,
|
||||
this.loadingIndicatorForNewMessages = true,
|
||||
this.loadingIndicatorForOldMessages = true,
|
||||
});
|
||||
|
||||
/// The minimum scroll offset to trigger the pagination to call for more pages
|
||||
/// on both sides of the chat. Defaults to 50.0
|
||||
final double scrollOffset;
|
||||
|
||||
/// Whether to show a loading indicator for new messages loading
|
||||
final bool loadingIndicatorForNewMessages;
|
||||
|
||||
/// Whether to show a loading indicator for old messages loading
|
||||
final bool loadingIndicatorForOldMessages;
|
||||
}
|
||||
|
|
|
@ -259,7 +259,7 @@ class _ChatBody extends HookWidget {
|
|||
var oldCount = messages.length;
|
||||
|
||||
try {
|
||||
debugPrint("loading from message: ${oldestMsg.id}");
|
||||
debugPrint("loading old messages from message: ${oldestMsg.id}");
|
||||
await service.loadOldMessagesBefore(firstMessage: oldestMsg);
|
||||
} finally {
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
|
@ -284,7 +284,7 @@ class _ChatBody extends HookWidget {
|
|||
|
||||
var newestMsg = messages.last;
|
||||
try {
|
||||
debugPrint("loading from message: ${newestMsg.id}");
|
||||
debugPrint("loading new messages from message: ${newestMsg.id}");
|
||||
await service.loadNewMessagesAfter(lastMessage: newestMsg);
|
||||
} finally {
|
||||
isLoadingNewer.value = false;
|
||||
|
@ -298,11 +298,13 @@ class _ChatBody extends HookWidget {
|
|||
var offset = scrollController.offset;
|
||||
var maxScroll = scrollController.position.maxScrollExtent;
|
||||
|
||||
if ((maxScroll - offset) <= 50 && !isLoadingOlder.value) {
|
||||
if ((maxScroll - offset) <= options.paginationControls.scrollOffset &&
|
||||
!isLoadingOlder.value) {
|
||||
unawaited(loadOlderMessages());
|
||||
}
|
||||
|
||||
if (offset <= 50 && !isLoadingNewer.value) {
|
||||
if (offset <= options.paginationControls.scrollOffset &&
|
||||
!isLoadingNewer.value) {
|
||||
unawaited(loadNewerMessages());
|
||||
}
|
||||
}
|
||||
|
@ -326,12 +328,14 @@ class _ChatBody extends HookWidget {
|
|||
userMap[u.id] = u;
|
||||
}
|
||||
|
||||
var topSpinner = (isLoadingOlder.value && options.enableLoadingIndicator)
|
||||
? const _LoaderItem()
|
||||
var topSpinner = (isLoadingOlder.value &&
|
||||
options.paginationControls.loadingIndicatorForOldMessages)
|
||||
? options.builders.loadingChatMessageBuilder.call(context)
|
||||
: const SizedBox.shrink();
|
||||
|
||||
var bottomSpinner = (isLoadingNewer.value && options.enableLoadingIndicator)
|
||||
? const _LoaderItem()
|
||||
var bottomSpinner = (isLoadingNewer.value &&
|
||||
options.paginationControls.loadingIndicatorForNewMessages)
|
||||
? options.builders.loadingChatMessageBuilder.call(context)
|
||||
: const SizedBox.shrink();
|
||||
|
||||
var reversedMessages = messages.reversed.toList();
|
||||
|
@ -348,7 +352,6 @@ class _ChatBody extends HookWidget {
|
|||
|
||||
bubbleChildren.add(
|
||||
ChatBubble(
|
||||
key: ValueKey(msg.id),
|
||||
message: msg,
|
||||
previousMessage: prevMsg,
|
||||
sender: userMap[msg.senderId],
|
||||
|
@ -370,7 +373,6 @@ class _ChatBody extends HookWidget {
|
|||
child: Align(
|
||||
alignment: options.chatAlignment ?? Alignment.bottomCenter,
|
||||
child: ListView(
|
||||
shrinkWrap: true,
|
||||
reverse: true,
|
||||
controller: scrollController,
|
||||
physics: const AlwaysScrollableScrollPhysics(),
|
||||
|
@ -392,20 +394,3 @@ class _ChatBody extends HookWidget {
|
|||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// A small row spinner item to show partial loading
|
||||
class _LoaderItem extends StatelessWidget {
|
||||
const _LoaderItem();
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) => const Padding(
|
||||
padding: EdgeInsets.all(8.0),
|
||||
child: Center(
|
||||
child: SizedBox(
|
||||
width: 24,
|
||||
height: 24,
|
||||
child: CircularProgressIndicator(strokeWidth: 2),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
|
|
@ -19,3 +19,25 @@ class DefaultChatLoadingOverlay extends StatelessWidget {
|
|||
],
|
||||
);
|
||||
}
|
||||
|
||||
/// A small row spinner item to show partial loading
|
||||
class DefaultChatMessageLoader extends StatelessWidget {
|
||||
/// Creates a new default chat message loader
|
||||
const DefaultChatMessageLoader({super.key});
|
||||
|
||||
/// Builds the default chat message loader
|
||||
static Widget builder(BuildContext context) =>
|
||||
const DefaultChatMessageLoader();
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) => const Padding(
|
||||
padding: EdgeInsets.all(8.0),
|
||||
child: Center(
|
||||
child: SizedBox(
|
||||
width: 24,
|
||||
height: 24,
|
||||
child: CircularProgressIndicator(strokeWidth: 2),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue