refactor: improve chat page scrolling behavior and reset logic

- Introduced a new boolean flag `_pendingConversationScrollReset` to manage scrolling behavior when switching conversations.
- Added a method `_resetScrollToTop` to handle scrolling to the top of the chat when necessary, enhancing user experience.
- Updated the logic in the chat page to ensure proper scrolling behavior based on conversation state, improving usability during conversation transitions.
- Refactored the chat input widget to simplify the layout and enhance responsiveness, ensuring better integration with the overall chat interface.
This commit is contained in:
cogwheel0
2025-10-02 12:34:12 +05:30
parent ba239c47f0
commit 0f6d1ba464
2 changed files with 43 additions and 21 deletions

View File

@@ -68,6 +68,7 @@ class _ChatPageState extends ConsumerState<ChatPage> {
String? _lastConversationId; String? _lastConversationId;
bool _shouldAutoScrollToBottom = true; bool _shouldAutoScrollToBottom = true;
bool _autoScrollCallbackScheduled = false; bool _autoScrollCallbackScheduled = false;
bool _pendingConversationScrollReset = false;
String _formatModelDisplayName(String name, {required bool omitProvider}) { String _formatModelDisplayName(String name, {required bool omitProvider}) {
var display = name.trim(); var display = name.trim();
@@ -104,6 +105,7 @@ class _ChatPageState extends ConsumerState<ChatPage> {
} }
_shouldAutoScrollToBottom = true; _shouldAutoScrollToBottom = true;
_pendingConversationScrollReset = false;
_scheduleAutoScrollToBottom(); _scheduleAutoScrollToBottom();
} }
@@ -599,6 +601,22 @@ class _ChatPageState extends ConsumerState<ChatPage> {
}); });
} }
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}) { void _scrollToBottom({bool smooth = true}) {
if (!_scrollController.hasClients) return; if (!_scrollController.hasClients) return;
final position = _scrollController.position; final position = _scrollController.position;
@@ -763,6 +781,17 @@ class _ChatPageState extends ConsumerState<ChatPage> {
final apiService = ref.watch(apiServiceProvider); 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) { if (_shouldAutoScrollToBottom) {
_scheduleAutoScrollToBottom(); _scheduleAutoScrollToBottom();
} else { } else {
@@ -1031,8 +1060,14 @@ class _ChatPageState extends ConsumerState<ChatPage> {
); );
if (conversationId != _lastConversationId) { if (conversationId != _lastConversationId) {
_lastConversationId = conversationId; _lastConversationId = conversationId;
_shouldAutoScrollToBottom = true; if (conversationId == null) {
_scheduleAutoScrollToBottom(); _shouldAutoScrollToBottom = true;
_pendingConversationScrollReset = false;
_scheduleAutoScrollToBottom();
} else {
_pendingConversationScrollReset = true;
_shouldAutoScrollToBottom = false;
}
} }
final conversationTitle = ref.watch( final conversationTitle = ref.watch(
activeConversationProvider.select((conv) => conv?.title), activeConversationProvider.select((conv) => conv?.title),

View File

@@ -1276,25 +1276,12 @@ class _ModernChatInputState extends ConsumerState<ModernChatInput>
borderRadius: BorderRadius.circular(radius), borderRadius: BorderRadius.circular(radius),
boxShadow: ConduitShadows.button, boxShadow: ConduitShadows.button,
), ),
child: Stack( child: Center(
alignment: Alignment.center, child: Icon(
children: [ Platform.isIOS ? CupertinoIcons.stop_fill : Icons.stop,
SizedBox( size: IconSize.large,
width: buttonSize - 18, color: context.conduitTheme.error,
height: buttonSize - 18, ),
child: CircularProgressIndicator(
strokeWidth: BorderWidth.medium,
valueColor: AlwaysStoppedAnimation<Color>(
context.conduitTheme.error,
),
),
),
Icon(
Platform.isIOS ? CupertinoIcons.stop_fill : Icons.stop,
size: IconSize.medium,
color: context.conduitTheme.error,
),
],
), ),
), ),
), ),