Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 14 additions & 4 deletions examples/flyer_chat/lib/api/api.dart
Original file line number Diff line number Diff line change
Expand Up @@ -87,11 +87,21 @@ class ApiState extends State<Api> {
Chat(
builders: Builders(
textMessageBuilder:
(context, message, index) =>
FlyerChatTextMessage(message: message, index: index),
(
context,
message,
index, {
required bool isSentByMe,
MessageGroupStatus? groupStatus,
}) => FlyerChatTextMessage(message: message, index: index),
imageMessageBuilder:
(context, message, index) =>
FlyerChatImageMessage(message: message, index: index),
(
context,
message,
index, {
required bool isSentByMe,
MessageGroupStatus? groupStatus,
}) => FlyerChatImageMessage(message: message, index: index),
composerBuilder:
(context) => Composer(
topWidget: ComposerActionBar(
Expand Down
24 changes: 21 additions & 3 deletions examples/flyer_chat/lib/gemini.dart
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,13 @@ class GeminiState extends State<Gemini> {
);
},
imageMessageBuilder:
(context, message, index) => FlyerChatImageMessage(
(
context,
message,
index, {
required bool isSentByMe,
MessageGroupStatus? groupStatus,
}) => FlyerChatImageMessage(
message: message,
index: index,
showTime: false,
Expand All @@ -172,7 +178,13 @@ class GeminiState extends State<Gemini> {
),
),
textMessageBuilder:
(context, message, index) => FlyerChatTextMessage(
(
context,
message,
index, {
required bool isSentByMe,
MessageGroupStatus? groupStatus,
}) => FlyerChatTextMessage(
message: message,
index: index,
showTime: false,
Expand All @@ -186,7 +198,13 @@ class GeminiState extends State<Gemini> {
vertical: 10,
),
),
textStreamMessageBuilder: (context, message, index) {
textStreamMessageBuilder: (
context,
message,
index, {
required bool isSentByMe,
MessageGroupStatus? groupStatus,
}) {
// Watch the manager for state updates
final streamState = context.watch<GeminiStreamManager>().getState(
message.streamId,
Expand Down
45 changes: 36 additions & 9 deletions examples/flyer_chat/lib/local.dart
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,13 @@ class LocalState extends State<Local> {
);
},
customMessageBuilder:
(context, message, index) => Container(
(
context,
message,
index, {
required bool isSentByMe,
MessageGroupStatus? groupStatus,
}) => Container(
padding: const EdgeInsets.symmetric(
horizontal: 16,
vertical: 10,
Expand All @@ -85,11 +91,21 @@ class LocalState extends State<Local> {
child: IsTypingIndicator(),
),
imageMessageBuilder:
(context, message, index) =>
FlyerChatImageMessage(message: message, index: index),
(
context,
message,
index, {
required bool isSentByMe,
MessageGroupStatus? groupStatus,
}) => FlyerChatImageMessage(message: message, index: index),
systemMessageBuilder:
(context, message, index) =>
FlyerChatSystemMessage(message: message, index: index),
(
context,
message,
index, {
required bool isSentByMe,
MessageGroupStatus? groupStatus,
}) => FlyerChatSystemMessage(message: message, index: index),
composerBuilder:
(context) => Composer(
topWidget: ComposerActionBar(
Expand All @@ -114,18 +130,29 @@ class LocalState extends State<Local> {
),
),
textMessageBuilder:
(context, message, index) =>
FlyerChatTextMessage(message: message, index: index),
(
context,
message,
index, {
required bool isSentByMe,
MessageGroupStatus? groupStatus,
}) => FlyerChatTextMessage(message: message, index: index),
fileMessageBuilder:
(context, message, index) =>
FlyerChatFileMessage(message: message, index: index),
(
context,
message,
index, {
required bool isSentByMe,
MessageGroupStatus? groupStatus,
}) => FlyerChatFileMessage(message: message, index: index),
chatMessageBuilder: (
context,
message,
index,
animation,
child, {
bool? isRemoved,
required bool isSentByMe,
MessageGroupStatus? groupStatus,
}) {
final isSystemMessage = message.authorId == 'system';
Expand Down
73 changes: 64 additions & 9 deletions packages/flutter_chat_core/lib/src/models/builders.dart
Original file line number Diff line number Diff line change
Expand Up @@ -8,39 +8,93 @@ part 'builders.freezed.dart';

/// Signature for building a text message widget.
typedef TextMessageBuilder =
Widget Function(BuildContext, TextMessage, int index);
Widget Function(
BuildContext,
TextMessage,
int index, {
required bool isSentByMe,
MessageGroupStatus? groupStatus,
});

/// Signature for building a streaming text message widget.
typedef TextStreamMessageBuilder =
Widget Function(BuildContext, TextStreamMessage, int index);
Widget Function(
BuildContext,
TextStreamMessage,
int index, {
required bool isSentByMe,
MessageGroupStatus? groupStatus,
});

/// Signature for building an image message widget.
typedef ImageMessageBuilder =
Widget Function(BuildContext, ImageMessage, int index);
Widget Function(
BuildContext,
ImageMessage,
int index, {
required bool isSentByMe,
MessageGroupStatus? groupStatus,
});

/// Signature for building a file message widget.
typedef FileMessageBuilder =
Widget Function(BuildContext, FileMessage, int index);
Widget Function(
BuildContext,
FileMessage,
int index, {
required bool isSentByMe,
MessageGroupStatus? groupStatus,
});

/// Signature for building a video message widget.
typedef VideoMessageBuilder =
Widget Function(BuildContext, VideoMessage, int index);
Widget Function(
BuildContext,
VideoMessage,
int index, {
required bool isSentByMe,
MessageGroupStatus? groupStatus,
});

/// Signature for building an audio message widget.
typedef AudioMessageBuilder =
Widget Function(BuildContext, AudioMessage, int index);
Widget Function(
BuildContext,
AudioMessage,
int index, {
required bool isSentByMe,
MessageGroupStatus? groupStatus,
});

/// Signature for building a system message widget.
typedef SystemMessageBuilder =
Widget Function(BuildContext, SystemMessage, int index);
Widget Function(
BuildContext,
SystemMessage,
int index, {
required bool isSentByMe,
MessageGroupStatus? groupStatus,
});

/// Signature for building a custom message widget.
typedef CustomMessageBuilder =
Widget Function(BuildContext, CustomMessage, int index);
Widget Function(
BuildContext,
CustomMessage,
int index, {
required bool isSentByMe,
MessageGroupStatus? groupStatus,
});

/// Signature for building an unsupported message widget.
typedef UnsupportedMessageBuilder =
Widget Function(BuildContext, UnsupportedMessage, int index);
Widget Function(
BuildContext,
UnsupportedMessage,
int index, {
required bool isSentByMe,
MessageGroupStatus? groupStatus,
});

/// Signature for building the message composer widget.
typedef ComposerBuilder = Widget Function(BuildContext);
Expand All @@ -54,6 +108,7 @@ typedef ChatMessageBuilder =
Animation<double> animation,
Widget child, {
bool? isRemoved,
required bool isSentByMe,
MessageGroupStatus? groupStatus,
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,22 +90,27 @@ class _ChatMessageInternalState extends State<ChatMessageInternal> {
@override
Widget build(BuildContext context) {
final builders = context.read<Builders>();

final groupStatus = _resolveGroupStatus(context);
final isSentByMe = context.watch<UserID>() == _updatedMessage.authorId;

final child = _buildMessage(
context,
builders,
_updatedMessage,
widget.index,
isSentByMe,
groupStatus,
);

final groupStatus = _resolveGroupStatus(context);

return builders.chatMessageBuilder?.call(
context,
_updatedMessage,
widget.index,
widget.animation,
child,
isRemoved: widget.isRemoved,
isSentByMe: isSentByMe,
groupStatus: groupStatus,
) ??
ChatMessage(
Expand Down Expand Up @@ -171,21 +176,37 @@ class _ChatMessageInternalState extends State<ChatMessageInternal> {
Builders builders,
Message message,
int index,
bool isSentByMe,
MessageGroupStatus? groupStatus,
) {
switch (message) {
case TextMessage():
return builders.textMessageBuilder?.call(context, message, index) ??
return builders.textMessageBuilder?.call(
context,
message,
index,
isSentByMe: isSentByMe,
groupStatus: groupStatus,
) ??
SimpleTextMessage(message: message, index: index);
case TextStreamMessage():
return builders.textStreamMessageBuilder?.call(
context,
message,
index,
isSentByMe: isSentByMe,
groupStatus: groupStatus,
) ??
const SizedBox.shrink();
case ImageMessage():
final result =
builders.imageMessageBuilder?.call(context, message, index) ??
builders.imageMessageBuilder?.call(
context,
message,
index,
isSentByMe: isSentByMe,
groupStatus: groupStatus,
) ??
const SizedBox.shrink();
assert(
!(result is SizedBox && result.width == 0 && result.height == 0),
Expand All @@ -195,25 +216,57 @@ class _ChatMessageInternalState extends State<ChatMessageInternal> {
);
return result;
case FileMessage():
return builders.fileMessageBuilder?.call(context, message, index) ??
return builders.fileMessageBuilder?.call(
context,
message,
index,
isSentByMe: isSentByMe,
groupStatus: groupStatus,
) ??
const SizedBox.shrink();
case VideoMessage():
return builders.videoMessageBuilder?.call(context, message, index) ??
return builders.videoMessageBuilder?.call(
context,
message,
index,
isSentByMe: isSentByMe,
groupStatus: groupStatus,
) ??
const SizedBox.shrink();
case AudioMessage():
return builders.audioMessageBuilder?.call(context, message, index) ??
return builders.audioMessageBuilder?.call(
context,
message,
index,
isSentByMe: isSentByMe,
groupStatus: groupStatus,
) ??
const SizedBox.shrink();
case SystemMessage():
return builders.systemMessageBuilder?.call(context, message, index) ??
return builders.systemMessageBuilder?.call(
context,
message,
index,
isSentByMe: isSentByMe,
groupStatus: groupStatus,
) ??
const SizedBox.shrink();
case CustomMessage():
return builders.customMessageBuilder?.call(context, message, index) ??
return builders.customMessageBuilder?.call(
context,
message,
index,
isSentByMe: isSentByMe,
groupStatus: groupStatus,
) ??
const SizedBox.shrink();
case UnsupportedMessage():
return builders.unsupportedMessageBuilder?.call(
context,
message,
index,
isSentByMe: isSentByMe,
groupStatus: groupStatus,
) ??
const Text(
'This message is not supported. Please update your app.',
Expand Down