💄 Mergeable chat messages

This commit is contained in:
LittleSheep 2024-11-17 22:42:09 +08:00
parent 2065350698
commit 432705c570
2 changed files with 67 additions and 13 deletions

View File

@ -76,9 +76,10 @@ class _ChatRoomScreenState extends State<ChatRoomScreen> {
Expanded(
child: InfiniteList(
reverse: true,
padding: const EdgeInsets.symmetric(
horizontal: 12,
vertical: 12,
padding: const EdgeInsets.only(
left: 12,
right: 12,
top: 12,
),
hasReachedMax: _messageController.isAllLoaded,
itemCount: _messageController.messages.length,
@ -88,8 +89,32 @@ class _ChatRoomScreenState extends State<ChatRoomScreen> {
},
itemBuilder: (context, idx) {
final message = _messageController.messages[idx];
final nextMessage =
idx < _messageController.messages.length - 1
? _messageController.messages[idx + 1]
: null;
final previousMessage =
idx > 0 ? _messageController.messages[idx - 1] : null;
final canMerge = nextMessage != null &&
nextMessage.senderId == message.senderId &&
message.createdAt
.difference(nextMessage.createdAt)
.inMinutes
.abs() <=
3;
final canMergePrevious = previousMessage != null &&
previousMessage.senderId == message.senderId &&
message.createdAt
.difference(previousMessage.createdAt)
.inMinutes
.abs() <=
3;
return ChatMessage(
data: message,
isMerged: canMerge,
hasMerged: canMergePrevious,
isPending: _messageController.unconfirmedMessages
.contains(message.uuid),
);

View File

@ -1,3 +1,4 @@
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:gap/gap.dart';
import 'package:provider/provider.dart';
@ -9,32 +10,60 @@ import 'package:surface/widgets/markdown_content.dart';
class ChatMessage extends StatelessWidget {
final SnChatMessage data;
final bool isMerged;
final bool hasMerged;
final bool isPending;
const ChatMessage({super.key, required this.data, this.isPending = false});
const ChatMessage({
super.key,
required this.data,
this.isMerged = false,
this.hasMerged = false,
this.isPending = false,
});
@override
Widget build(BuildContext context) {
final ud = context.read<UserDirectoryProvider>();
final user = ud.getAccountFromCache(data.sender.accountId);
final dateFormatter = DateFormat('MM/dd HH:mm');
return Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
AccountImage(
content: user?.avatar,
),
if (!isMerged)
AccountImage(
content: user?.avatar,
)
else
const Gap(40),
const Gap(8),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
(data.sender.nick?.isNotEmpty ?? false)
? data.sender.nick!
: user!.nick,
).bold(),
if (!isMerged)
Row(
crossAxisAlignment: CrossAxisAlignment.baseline,
textBaseline: TextBaseline.alphabetic,
children: [
Text(
(data.sender.nick?.isNotEmpty ?? false)
? data.sender.nick!
: user!.nick,
).bold(),
const Gap(6),
Text(
dateFormatter.format(data.createdAt.toLocal()),
).fontSize(13),
],
),
if (data.body['text'] != null)
MarkdownTextContent(content: data.body['text']),
MarkdownTextContent(
content: data.body['text'],
isAutoWarp: true,
),
if (!hasMerged) const Gap(8),
],
),
)