diff --git a/lib/features/chat/views/chat_page.dart b/lib/features/chat/views/chat_page.dart index fe31ae1..eb3d26a 100644 --- a/lib/features/chat/views/chat_page.dart +++ b/lib/features/chat/views/chat_page.dart @@ -68,6 +68,7 @@ class _ChatPageState extends ConsumerState { String? _lastConversationId; bool _shouldAutoScrollToBottom = true; bool _autoScrollCallbackScheduled = false; + bool _pendingConversationScrollReset = false; String _formatModelDisplayName(String name, {required bool omitProvider}) { var display = name.trim(); @@ -104,6 +105,7 @@ class _ChatPageState extends ConsumerState { } _shouldAutoScrollToBottom = true; + _pendingConversationScrollReset = false; _scheduleAutoScrollToBottom(); } @@ -599,6 +601,22 @@ class _ChatPageState extends ConsumerState { }); } + void _resetScrollToTop() { + if (!_scrollController.hasClients) { + WidgetsBinding.instance.addPostFrameCallback((_) { + if (!mounted || !_scrollController.hasClients) { + return; + } + _scrollController.jumpTo(0); + }); + return; + } + + if (_scrollController.position.pixels != 0) { + _scrollController.jumpTo(0); + } + } + void _scrollToBottom({bool smooth = true}) { if (!_scrollController.hasClients) return; final position = _scrollController.position; @@ -763,6 +781,17 @@ class _ChatPageState extends ConsumerState { final apiService = ref.watch(apiServiceProvider); + if (_pendingConversationScrollReset) { + _pendingConversationScrollReset = false; + if (messages.length <= 1) { + _shouldAutoScrollToBottom = true; + } else { + // When opening an existing conversation, start reading from the top + _shouldAutoScrollToBottom = false; + _resetScrollToTop(); + } + } + if (_shouldAutoScrollToBottom) { _scheduleAutoScrollToBottom(); } else { @@ -1031,8 +1060,14 @@ class _ChatPageState extends ConsumerState { ); if (conversationId != _lastConversationId) { _lastConversationId = conversationId; - _shouldAutoScrollToBottom = true; - _scheduleAutoScrollToBottom(); + if (conversationId == null) { + _shouldAutoScrollToBottom = true; + _pendingConversationScrollReset = false; + _scheduleAutoScrollToBottom(); + } else { + _pendingConversationScrollReset = true; + _shouldAutoScrollToBottom = false; + } } final conversationTitle = ref.watch( activeConversationProvider.select((conv) => conv?.title), diff --git a/lib/features/chat/widgets/modern_chat_input.dart b/lib/features/chat/widgets/modern_chat_input.dart index 8b34179..2d2ef63 100644 --- a/lib/features/chat/widgets/modern_chat_input.dart +++ b/lib/features/chat/widgets/modern_chat_input.dart @@ -1276,25 +1276,12 @@ class _ModernChatInputState extends ConsumerState borderRadius: BorderRadius.circular(radius), boxShadow: ConduitShadows.button, ), - child: Stack( - alignment: Alignment.center, - children: [ - SizedBox( - width: buttonSize - 18, - height: buttonSize - 18, - child: CircularProgressIndicator( - strokeWidth: BorderWidth.medium, - valueColor: AlwaysStoppedAnimation( - context.conduitTheme.error, - ), - ), - ), - Icon( - Platform.isIOS ? CupertinoIcons.stop_fill : Icons.stop, - size: IconSize.medium, - color: context.conduitTheme.error, - ), - ], + child: Center( + child: Icon( + Platform.isIOS ? CupertinoIcons.stop_fill : Icons.stop, + size: IconSize.large, + color: context.conduitTheme.error, + ), ), ), ),