Skip to content
Open
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
6 changes: 3 additions & 3 deletions examples/flyer_chat/macos/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,11 @@ EXTERNAL SOURCES:

SPEC CHECKSUMS:
file_picker: 7584aae6fa07a041af2b36a2655122d42f578c1a
file_selector_macos: 6280b52b459ae6c590af5d78fc35c7267a3c4b31
file_selector_macos: 9e9e068e90ebee155097d00e89ae91edb2374db7
FlutterMacOS: d0db08ddef1a9af05a5ec4b724367152bb0500b1
isar_flutter_libs: a65381780401f81ad6bf3f2e7cd0de5698fb98c4
path_provider_foundation: 080d55be775b7414fd5a5ef3ac137b97b097e564
url_launcher_macos: 0fba8ddabfc33ce0a9afe7c5fef5aab3d8d2d673
path_provider_foundation: bb55f6dbba17d0dccd6737fe6f7f34fbd0376880
url_launcher_macos: f87a979182d112f911de6820aefddaf56ee9fbfd

PODFILE CHECKSUM: 54d867c82ac51cbd61b565781b9fada492027009

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,15 @@ class FlyerChatFileMessage extends StatelessWidget {
/// The widget to display on top of the message.
final Widget? topWidget;

/// Builder for the status widget if not provided, will build a default widget with Icons
/// Will not be displayed if [showStatus] is false.
final Widget Function(BuildContext context, MessageStatus? status)?
statusBuilder;

/// Builder for the time widget, if not provided will build a default widget using the HH:mm format
/// Will not be displayed if [showTime] is false.
final Widget Function(BuildContext context, DateTime time)? timeBuilder;

/// Creates a widget to display a file message.
const FlyerChatFileMessage({
super.key,
Expand All @@ -96,7 +105,9 @@ class FlyerChatFileMessage extends StatelessWidget {
this.receivedSizeTextStyle,
this.timeStyle,
this.showTime = true,
this.timeBuilder,
this.showStatus = true,
this.statusBuilder,
this.timeAndStatusPosition = TimeAndStatusPosition.end,
this.topWidget,
});
Expand Down Expand Up @@ -127,7 +138,9 @@ class FlyerChatFileMessage extends StatelessWidget {
time: message.resolvedTime,
status: message.resolvedStatus,
showTime: showTime,
timeBuilder: timeBuilder,
showStatus: isSentByMe && showStatus,
statusBuilder: statusBuilder,
textStyle: timeStyle,
)
: null;
Expand Down Expand Up @@ -277,7 +290,7 @@ class FlyerChatFileMessage extends StatelessWidget {
theme.bodySmall.copyWith(color: theme.onSurface.withValues(alpha: 0.8));
}

TextStyle? _resolveTimeStyle(bool isSentByMe, _LocalTheme theme) {
TextStyle _resolveTimeStyle(bool isSentByMe, _LocalTheme theme) {
final color = isSentByMe ? theme.onPrimary : theme.onSurface;

return timeStyle ?? theme.labelSmall.copyWith(color: color);
Expand All @@ -299,41 +312,67 @@ class TimeAndStatus extends StatelessWidget {
final bool showStatus;

/// The text style for the time and status.
final TextStyle? textStyle;
final TextStyle textStyle;

/// Builder for the status widget if not provided, will build a default widget with Icons
final Widget Function(BuildContext context, MessageStatus? status)?
statusBuilder;

/// Builder for the time widget, if not provided will build a default widget using the HH:mm format
final Widget Function(BuildContext context, DateTime time)? timeBuilder;

/// Creates a widget for displaying time and status.
const TimeAndStatus({
super.key,
required this.time,
required this.textStyle,
this.status,
this.showTime = true,
this.showStatus = true,
this.textStyle,
this.timeBuilder,
this.statusBuilder,
});

@override
Widget build(BuildContext context) {
final timeWidgetBuilder = timeBuilder ?? _defaultTimeBuilder;
final statusWidgetBuilder = statusBuilder ?? _defaultStatusBuilder;

return IconTheme(
data: IconThemeData(color: textStyle.color, size: 12),
child: DefaultTextStyle(
style: textStyle,
child: Row(
spacing: 2,
mainAxisSize: MainAxisSize.min,
children: [
if (showTime && time != null) timeWidgetBuilder(context, time!),
if (showStatus && status != null)
statusWidgetBuilder(context, status),
],
),
),
);
}

Widget _defaultTimeBuilder(BuildContext context, DateTime time) {
final timeFormat = context.watch<DateFormat>();

return Row(
spacing: 2,
mainAxisSize: MainAxisSize.min,
children: [
if (showTime && time != null)
Text(timeFormat.format(time!.toLocal()), style: textStyle),
if (showStatus && status != null)
if (status == MessageStatus.sending)
SizedBox(
width: 6,
height: 6,
child: CircularProgressIndicator(
color: textStyle?.color,
strokeWidth: 2,
),
)
else
Icon(getIconForStatus(status!), color: textStyle?.color, size: 12),
],
);
return Text(timeFormat.format(time.toLocal()));
}

Widget _defaultStatusBuilder(BuildContext context, MessageStatus? status) {
if (status == MessageStatus.sending) {
return SizedBox(
width: 6,
height: 6,
child: CircularProgressIndicator(
color: textStyle.color,
strokeWidth: 2,
),
);
}

return Icon(getIconForStatus(status!));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,15 @@ class FlyerChatImageMessage extends StatefulWidget {
/// The widget to display on top of the message.
final Widget? topWidget;

/// Builder for the status widget if not provided, will build a default widget with Icons
/// Will not be displayed if [showStatus] is false.
final Widget Function(BuildContext context, MessageStatus? status)?
statusBuilder;

/// Builder for the time widget, if not provided will build a default widget using the HH:mm format
/// Will not be displayed if [showTime] is false.
final Widget Function(BuildContext context, DateTime time)? timeBuilder;

/// Creates a widget to display an image message.
const FlyerChatImageMessage({
super.key,
Expand All @@ -107,7 +116,9 @@ class FlyerChatImageMessage extends StatefulWidget {
this.timeStyle,
this.timeBackground,
this.showTime = true,
this.timeBuilder,
this.showStatus = true,
this.statusBuilder,
this.timeAndStatusPosition = TimeAndStatusPosition.end,
this.errorBuilder,
this.topWidget,
Expand Down Expand Up @@ -216,7 +227,9 @@ class _FlyerChatImageMessageState extends State<FlyerChatImageMessage>
time: widget.message.resolvedTime,
status: widget.message.resolvedStatus,
showTime: widget.showTime,
timeBuilder: widget.timeBuilder,
showStatus: isSentByMe && widget.showStatus,
statusBuilder: widget.statusBuilder,
backgroundColor:
widget.timeBackground ?? Colors.black.withValues(alpha: 0.6),
textStyle:
Expand Down Expand Up @@ -409,53 +422,75 @@ class TimeAndStatus extends StatelessWidget {
final Color? backgroundColor;

/// Text style for the time and status.
final TextStyle? textStyle;
final TextStyle textStyle;

/// Builder for the status widget if not provided, will build a default widget with Icons
final Widget Function(BuildContext context, MessageStatus? status)?
statusBuilder;

/// Builder for the time widget, if not provided will build a default widget using the HH:mm format
final Widget Function(BuildContext context, DateTime time)? timeBuilder;

/// Creates a widget for displaying time and status over an image.
const TimeAndStatus({
super.key,
required this.time,
required this.textStyle,
this.status,
this.showTime = true,
this.timeBuilder,
this.showStatus = true,
this.statusBuilder,
this.backgroundColor,
this.textStyle,
});

@override
Widget build(BuildContext context) {
final timeFormat = context.watch<DateFormat>();
final timeWidgetBuilder = timeBuilder ?? _defaultTimeBuilder;
final statusWidgetBuilder = statusBuilder ?? _defaultStatusBuilder;

return Container(
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
decoration: BoxDecoration(
color: backgroundColor,
borderRadius: BorderRadius.circular(12),
),
child: Row(
spacing: 2,
mainAxisSize: MainAxisSize.min,
children: [
if (showTime && time != null)
Text(timeFormat.format(time!.toLocal()), style: textStyle),
if (showStatus && status != null)
if (status == MessageStatus.sending)
SizedBox(
width: 6,
height: 6,
child: CircularProgressIndicator(
color: textStyle?.color,
strokeWidth: 2,
),
)
else
Icon(
getIconForStatus(status!),
color: textStyle?.color,
size: 12,
),
],
child: IconTheme(
data: IconThemeData(color: textStyle.color, size: 12),
child: DefaultTextStyle(
style: textStyle,
child: Row(
spacing: 2,
mainAxisSize: MainAxisSize.min,
children: [
if (showTime && time != null) timeWidgetBuilder(context, time!),
if (showStatus && status != null)
statusWidgetBuilder(context, status),
],
),
),
),
);
}

Widget _defaultTimeBuilder(BuildContext context, DateTime time) {
final timeFormat = context.watch<DateFormat>();

return Text(timeFormat.format(time.toLocal()));
}

Widget _defaultStatusBuilder(BuildContext context, MessageStatus? status) {
if (status == MessageStatus.sending) {
return SizedBox(
width: 6,
height: 6,
child: CircularProgressIndicator(
color: textStyle.color,
strokeWidth: 2,
),
);
}

return Icon(getIconForStatus(status!));
}
}
Loading