feat: add error builder to chat detail screen for failed to load messages

This commit is contained in:
Joey Boerwinkel 2025-02-27 16:50:12 +01:00 committed by FlutterJoey
parent d3f839dc94
commit 6ecf073f15
5 changed files with 119 additions and 17 deletions

View file

@ -1,15 +1,14 @@
// exceptions
export "src/exceptions/chat.dart";
// Interfaces
export "src/interfaces/chat_repostory_interface.dart";
export "src/interfaces/user_repository_interface.dart";
// Local implementations
export "src/local/local_chat_repository.dart";
export "src/local/local_user_repository.dart";
// Models
export "src/models/chat_model.dart";
export "src/models/message_model.dart";
export "src/models/user_model.dart";
// Services
export "src/services/chat_service.dart";

View file

@ -0,0 +1,23 @@
/// An exception that is used to indicate the failure to load a chat for given
/// [chatId]
class ChatNotFoundException implements Exception {
/// Create an instance of the chat not found exception
const ChatNotFoundException({
required this.chatId,
});
/// The chat that was attempted to load, but never found.
final String chatId;
}
/// An exception that is used to indicate the failure to load the messages for a
/// given [chatId]
class ChatMessagesNotFoundException implements Exception {
/// Create an instance of the chatmessages not found exception
const ChatMessagesNotFoundException({
required this.chatId,
});
/// The chat for which messages were attempted to load, but never found.
final String chatId;
}

View file

@ -1,17 +1,15 @@
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/flutter_chat.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 {
/// The chat builders constructor
const ChatBuilders({
this.chatMessagesErrorBuilder,
this.baseScreenBuilder,
this.chatScreenBuilder,
this.messageInputBuilder,
@ -99,6 +97,10 @@ class ChatBuilders {
/// This is displayed in the list of chat messages when loading more messages
/// can be above and below the list
final WidgetBuilder loadingChatMessageBuilder;
/// Errorbuilder for when messages are not loading correctly on the detail
/// screen of a chat.
final ChatErrorBuilder? chatMessagesErrorBuilder;
}
/// The button builder
@ -189,3 +191,11 @@ typedef NoUsersPlaceholderBuilder = Widget Function(
BuildContext context,
ChatTranslations translations,
);
/// Builder for when there is an error on a chatscreen
typedef ChatErrorBuilder = Widget Function(
BuildContext context,
Object error,
StackTrace stackTrace,
ChatOptions options,
);

View file

@ -48,6 +48,7 @@ class ChatTranslations {
required this.selectedMembersHeader,
required this.createGroupChatButton,
required this.groupNameEmpty,
required this.messagesLoadingError,
required this.next,
});
@ -92,6 +93,7 @@ class ChatTranslations {
this.selectedMembersHeader = "Members: ",
this.createGroupChatButton = "Create groupchat",
this.groupNameEmpty = "Group",
this.messagesLoadingError = "Error loading messages, you can reload below:",
this.next = "Next",
});
@ -134,6 +136,10 @@ class ChatTranslations {
final String groupBioValidatorEmpty;
final String groupNameEmpty;
/// message shown in the default chat screen when the chat messages are unable
/// to be loaded.
final String messagesLoadingError;
final String next;
// copyWith method to override the default values
@ -174,6 +180,7 @@ class ChatTranslations {
String? selectedMembersHeader,
String? createGroupChatButton,
String? groupNameEmpty,
String? messagesLoadingError,
String? next,
}) =>
ChatTranslations(
@ -225,6 +232,7 @@ class ChatTranslations {
createGroupChatButton:
createGroupChatButton ?? this.createGroupChatButton,
groupNameEmpty: groupNameEmpty ?? this.groupNameEmpty,
messagesLoadingError: messagesLoadingError ?? this.messagesLoadingError,
next: next ?? this.next,
);
}

View file

@ -3,6 +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/chat_options.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";
@ -393,6 +394,41 @@ class _ChatBody extends HookWidget {
[autoScrollEnabled.value],
);
var chatBottomInputSection = ChatBottomInputSection(
chat: chat,
isLoading: chatIsLoading && !messagesSnapshot.hasData,
onPressSelectImage: () async => onPressSelectImage(
context,
options,
onUploadImage,
),
onMessageSubmit: onMessageSubmit,
);
if (messagesSnapshot.hasError) {
var errorBuilder = options.builders.chatMessagesErrorBuilder;
if (errorBuilder != null) {
return Column(
children: [
Expanded(
child: errorBuilder(
context,
messagesSnapshot.error!,
messagesSnapshot.stackTrace!,
options,
),
),
chatBottomInputSection,
],
);
}
return ErrorLoadingMessages(
options: options,
chatBottomInputSection: chatBottomInputSection,
);
}
var userMap = <String, UserModel>{};
for (var u in chatUsers) {
userMap[u.id] = u;
@ -449,17 +485,43 @@ class _ChatBody extends HookWidget {
),
),
],
ChatBottomInputSection(
chat: chat,
isLoading: chatIsLoading,
onPressSelectImage: () async => onPressSelectImage(
context,
options,
onUploadImage,
),
onMessageSubmit: onMessageSubmit,
),
chatBottomInputSection,
],
);
}
}
/// Default widget used when displaying an error for chats.
class ErrorLoadingMessages extends StatelessWidget {
/// Create default error displaying widget for error in loading messages
const ErrorLoadingMessages({
required this.options,
required this.chatBottomInputSection,
super.key,
});
/// the options of the current chat userstory
final ChatOptions options;
/// The widget
final ChatBottomInputSection chatBottomInputSection;
@override
Widget build(BuildContext context) => Column(
children: [
Expanded(
child: Center(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Text(
options.translations.messagesLoadingError,
),
],
),
),
),
chatBottomInputSection,
],
);
}