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:
@@ -68,6 +68,7 @@ class _ChatPageState extends ConsumerState<ChatPage> {
|
||||
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<ChatPage> {
|
||||
}
|
||||
|
||||
_shouldAutoScrollToBottom = true;
|
||||
_pendingConversationScrollReset = false;
|
||||
_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}) {
|
||||
if (!_scrollController.hasClients) return;
|
||||
final position = _scrollController.position;
|
||||
@@ -763,6 +781,17 @@ class _ChatPageState extends ConsumerState<ChatPage> {
|
||||
|
||||
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<ChatPage> {
|
||||
);
|
||||
if (conversationId != _lastConversationId) {
|
||||
_lastConversationId = conversationId;
|
||||
if (conversationId == null) {
|
||||
_shouldAutoScrollToBottom = true;
|
||||
_pendingConversationScrollReset = false;
|
||||
_scheduleAutoScrollToBottom();
|
||||
} else {
|
||||
_pendingConversationScrollReset = true;
|
||||
_shouldAutoScrollToBottom = false;
|
||||
}
|
||||
}
|
||||
final conversationTitle = ref.watch(
|
||||
activeConversationProvider.select((conv) => conv?.title),
|
||||
|
||||
@@ -1276,25 +1276,12 @@ class _ModernChatInputState extends ConsumerState<ModernChatInput>
|
||||
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<Color>(
|
||||
context.conduitTheme.error,
|
||||
),
|
||||
),
|
||||
),
|
||||
Icon(
|
||||
child: Center(
|
||||
child: Icon(
|
||||
Platform.isIOS ? CupertinoIcons.stop_fill : Icons.stop,
|
||||
size: IconSize.medium,
|
||||
size: IconSize.large,
|
||||
color: context.conduitTheme.error,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
Reference in New Issue
Block a user