💫 Message list fully animated

This commit is contained in:
2025-10-13 00:16:50 +08:00
parent 51b4754182
commit 8d1c145b0b

View File

@@ -561,13 +561,31 @@ class ChatRoomScreen extends HookConsumerWidget {
.abs() >
3;
final key = ValueKey('$messageKeyPrefix${message.id}');
// Use a stable animation key that doesn't change during message lifecycle
final animationKey = ValueKey(
'message-anim-${message.nonce ?? message.id}',
);
return chatIdentity.when(
return TweenAnimationBuilder<double>(
key: animationKey,
tween: Tween<double>(begin: 0.0, end: 1.0),
duration: Duration(
milliseconds: 400 + (index % 5) * 50,
), // Staggered delay
curve: Curves.easeOutCubic,
builder: (context, animationValue, child) {
return Transform.translate(
offset: Offset(
0,
20 * (1 - animationValue),
), // Slide up from bottom
child: Opacity(opacity: animationValue, child: child),
);
},
child: chatIdentity.when(
skipError: true,
data:
(identity) => MessageItem(
key: key,
message: message,
isCurrentUser: identity?.id == message.senderId,
onAction: (action) {
@@ -605,7 +623,6 @@ class ChatRoomScreen extends HookConsumerWidget {
),
loading:
() => MessageItem(
key: key,
message: message,
isCurrentUser: false,
onAction: null,
@@ -613,7 +630,8 @@ class ChatRoomScreen extends HookConsumerWidget {
showAvatar: false,
onJump: (_) {},
),
error: (_, _) => SizedBox.shrink(key: key),
error: (_, _) => SizedBox.shrink(),
),
);
},
);
@@ -692,21 +710,45 @@ class ChatRoomScreen extends HookConsumerWidget {
child: Column(
children: [
Expanded(
child: AnimatedSwitcher(
duration: const Duration(milliseconds: 300),
switchInCurve: Curves.easeOutCubic,
switchOutCurve: Curves.easeInCubic,
transitionBuilder: (
Widget child,
Animation<double> animation,
) {
return SlideTransition(
position: Tween<Offset>(
begin: const Offset(0, 0.05),
end: Offset.zero,
).animate(animation),
child: FadeTransition(opacity: animation, child: child),
);
},
child: messages.when(
data:
(messageList) =>
messageList.isEmpty
? Center(child: Text('No messages yet'.tr()))
? Center(
key: const ValueKey('empty-messages'),
child: Text('No messages yet'.tr()),
)
: chatMessageListWidget(messageList),
loading:
() => const Center(child: CircularProgressIndicator()),
() => const Center(
key: ValueKey('loading-messages'),
child: CircularProgressIndicator(),
),
error:
(error, _) => ResponseErrorWidget(
key: const ValueKey('error-messages'),
error: error,
onRetry: () => messagesNotifier.loadInitial(),
),
),
),
),
chatRoom.when(
data:
(room) => Column(