better time and status position

This commit is contained in:
Christien Rioux 2025-05-28 13:34:57 -05:00
parent b8eca1161e
commit 8aaca62ea7
5 changed files with 119 additions and 116 deletions

View file

@ -22,7 +22,6 @@ class VcTextMessageWidget extends StatelessWidget {
this.timeStyle,
this.showTime = true,
this.showStatus = true,
this.timeAndStatusPosition = TimeAndStatusPosition.end,
super.key,
});
@ -63,9 +62,6 @@ class VcTextMessageWidget extends StatelessWidget {
/// for sent messages.
final bool showStatus;
/// Position of the timestamp and status indicator relative to the text.
final TimeAndStatusPosition timeAndStatusPosition;
bool get _isOnlyEmoji => message.metadata?['isOnlyEmoji'] == true;
@override
@ -98,7 +94,11 @@ class VcTextMessageWidget extends StatelessWidget {
: textStyle,
);
return Container(
return Column(
crossAxisAlignment:
isSentByMe ? CrossAxisAlignment.end : CrossAxisAlignment.start,
children: [
Container(
padding: _isOnlyEmoji
? EdgeInsets.symmetric(
horizontal: (padding?.horizontal ?? 0) / 2,
@ -111,49 +111,9 @@ class VcTextMessageWidget extends StatelessWidget {
color: backgroundColor,
borderRadius: borderRadius ?? chatTheme.shape,
),
child: _buildContentBasedOnPosition(
context: context,
textContent: textContent,
timeAndStatus: timeAndStatus,
textStyle: textStyle,
),
);
}
Widget _buildContentBasedOnPosition({
required BuildContext context,
required Widget textContent,
TimeAndStatus? timeAndStatus,
TextStyle? textStyle,
}) {
if (timeAndStatus == null) {
return textContent;
}
switch (timeAndStatusPosition) {
case TimeAndStatusPosition.start:
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: [textContent, timeAndStatus],
);
case TimeAndStatusPosition.inline:
return Row(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.end,
children: [
Flexible(child: textContent),
const SizedBox(width: 4),
timeAndStatus,
],
);
case TimeAndStatusPosition.end:
return Column(
crossAxisAlignment: CrossAxisAlignment.end,
mainAxisSize: MainAxisSize.min,
children: [textContent, timeAndStatus],
);
}
child: textContent),
if (timeAndStatus != null) timeAndStatus,
]);
}
Color _resolveBackgroundColor(bool isSentByMe, ScaleChatTheme theme) {
@ -170,11 +130,8 @@ class VcTextMessageWidget extends StatelessWidget {
return receivedTextStyle ?? theme.receivedMessageBodyTextStyle;
}
TextStyle _resolveTimeStyle(bool isSentByMe, ScaleChatTheme theme) {
final ts = _resolveTextStyle(isSentByMe, theme);
return theme.timeStyle.copyWith(color: ts.color);
}
TextStyle _resolveTimeStyle(bool isSentByMe, ScaleChatTheme theme) =>
theme.timeStyle;
@override
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
@ -193,9 +150,7 @@ class VcTextMessageWidget extends StatelessWidget {
'receivedTextStyle', receivedTextStyle))
..add(DiagnosticsProperty<TextStyle?>('timeStyle', timeStyle))
..add(DiagnosticsProperty<bool>('showTime', showTime))
..add(DiagnosticsProperty<bool>('showStatus', showStatus))
..add(EnumProperty<TimeAndStatusPosition>(
'timeAndStatusPosition', timeAndStatusPosition));
..add(DiagnosticsProperty<bool>('showStatus', showStatus));
}
}

View file

@ -261,18 +261,36 @@ class _ChatComponentWidgetState extends State<ChatComponentWidget> {
chatAnimatedListBuilder: (context, itemBuilder) =>
ChatAnimatedListReversed(
scrollController: _scrollController,
messageGroupingTimeoutInSeconds: 60,
itemBuilder: itemBuilder),
// Text message builder
textMessageBuilder: (context, message, index) =>
VcTextMessageWidget(
textMessageBuilder: (context, message, index) {
var showTime = true;
if (_chatController.messages.length > 1 &&
index < _chatController.messages.length - 1 &&
message.time != null) {
final nextMessage =
_chatController.messages[index + 1];
if (nextMessage.time != null) {
if (nextMessage.time!
.difference(message.time!)
.inSeconds <
60 &&
nextMessage.authorId == message.authorId) {
showTime = false;
}
}
}
return VcTextMessageWidget(
message: message,
index: index,
padding: const EdgeInsets.symmetric(
vertical: 12, horizontal: 16)
.scaled(context)
// showTime: true,
// showStatus: true,
),
.scaled(context),
showTime: showTime,
showStatus: showTime,
);
},
// Composer builder
composerBuilder: (ctx) => VcComposerWidget(
autofocus: true,

View file

@ -56,11 +56,9 @@ class ChatListWidget extends StatelessWidget {
valueMapper: (c) => c.value);
final chatListV = context.watch<ChatListCubit>().state;
return chatListV
.builder((context, chatList) => SizedBox.expand(
child: styledTitleContainer(
return chatListV.builder((context, chatList) => SizedBox.expand(
child: styledContainer(
context: context,
title: translate('chat_list.chats'),
child: (chatList.isEmpty)
? const SizedBox.expand(child: EmptyChatListWidget())
: TapRegion(
@ -77,22 +75,19 @@ class ChatListWidget extends StatelessWidget {
contactMap,
);
case proto.Chat_Kind.group:
return const Text(
'group chats not yet supported!');
return const Text('group chats not yet supported!');
case proto.Chat_Kind.notSet:
throw StateError('unknown chat kind');
}
},
filter: (value) =>
_itemFilter(contactMap, chatList, value),
searchFieldPadding:
const EdgeInsets.fromLTRB(0, 0, 0, 4),
searchFieldPadding: const EdgeInsets.fromLTRB(0, 0, 0, 4),
inputDecoration: InputDecoration(
labelText: translate('chat_list.search'),
),
)).paddingAll(8),
)))
.paddingLTRB(8, 0, 8, 8);
)));
});
}
}

View file

@ -354,7 +354,10 @@ extension ScaleChatThemeExt on ScaleTheme {
: scheme.primaryScale.calloutText,
),
onlyEmojiFontSize: 64,
timeStyle: textTheme.bodySmall!.copyWith(fontSize: 9),
timeStyle: textTheme.bodySmall!.copyWith(fontSize: 9).copyWith(
color: config.preferBorders || config.useVisualIndicators
? scheme.primaryScale.calloutBackground
: scheme.primaryScale.borderText),
receivedMessageBodyTextStyle: textTheme.bodyLarge!.copyWith(
color: config.preferBorders
? scheme.secondaryScale.calloutBackground

View file

@ -464,6 +464,38 @@ Widget styledTitleContainer({
]));
}
Widget styledContainer({
required BuildContext context,
required Widget child,
Color? borderColor,
Color? backgroundColor,
}) {
final theme = Theme.of(context);
final scale = theme.extension<ScaleScheme>()!;
final scaleConfig = theme.extension<ScaleConfig>()!;
return DecoratedBox(
decoration: ShapeDecoration(
color: borderColor ?? scale.primaryScale.border,
shape: RoundedRectangleBorder(
borderRadius:
BorderRadius.circular(8 * scaleConfig.borderRadiusScale),
)),
child: Column(children: [
DecoratedBox(
decoration: ShapeDecoration(
color:
backgroundColor ?? scale.primaryScale.subtleBackground,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(
8 * scaleConfig.borderRadiusScale),
)),
child: child)
.paddingAll(4)
.expanded()
]));
}
Widget styledCard({
required BuildContext context,
required Widget child,