feat: add composer autofocus management for improved chat input experience
- Introduced ComposerAutofocusEnabled provider to manage the auto-focus state of the chat composer, allowing for better control over user interactions. - Updated ModernChatInput to respect the autofocus setting, ensuring the keyboard behavior aligns with user intent and context. - Enhanced ChatPage to suppress auto-focus when opening the slide drawer, improving user experience during navigation. - Refactored SlideDrawer to include an onOpenStart callback for dismissing the keyboard, ensuring a smoother transition when the drawer is opened.
This commit is contained in:
@@ -67,6 +67,7 @@ class _ChatPageState extends ConsumerState<ChatPage> {
|
||||
bool _shouldAutoScrollToBottom = true;
|
||||
bool _autoScrollCallbackScheduled = false;
|
||||
bool _pendingConversationScrollReset = false;
|
||||
bool _suppressKeepPinnedOnce = false; // skip keep-pinned bottom after reset
|
||||
String? _cachedGreetingName;
|
||||
bool _greetingReady = false;
|
||||
|
||||
@@ -780,6 +781,7 @@ class _ChatPageState extends ConsumerState<ChatPage> {
|
||||
// When opening an existing conversation, start reading from the top
|
||||
_shouldAutoScrollToBottom = false;
|
||||
_resetScrollToTop();
|
||||
_suppressKeepPinnedOnce = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -788,6 +790,12 @@ class _ChatPageState extends ConsumerState<ChatPage> {
|
||||
} else {
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
if (!mounted) return;
|
||||
if (_suppressKeepPinnedOnce) {
|
||||
// Skip the one-time keep-pinned-to-bottom adjustment right after
|
||||
// a conversation switch so we remain at the top.
|
||||
_suppressKeepPinnedOnce = false;
|
||||
return;
|
||||
}
|
||||
const double keepPinnedThreshold = 60.0;
|
||||
final distanceFromBottom = _distanceFromBottom();
|
||||
if (distanceFromBottom > 0 &&
|
||||
@@ -1178,6 +1186,14 @@ class _ChatPageState extends ConsumerState<ChatPage> {
|
||||
edgeFraction: edgeFraction,
|
||||
settleFraction: 0.06, // even gentler settle for instant open feel
|
||||
scrimColor: scrim,
|
||||
onOpenStart: () {
|
||||
// Suppress composer auto-focus once we unfocus for the drawer
|
||||
try {
|
||||
ref
|
||||
.read(composerAutofocusEnabledProvider.notifier)
|
||||
.set(false);
|
||||
} catch (_) {}
|
||||
},
|
||||
drawer: SafeArea(
|
||||
top: true,
|
||||
bottom: true,
|
||||
@@ -1214,7 +1230,19 @@ class _ChatPageState extends ConsumerState<ChatPage> {
|
||||
),
|
||||
child: IconButton(
|
||||
onPressed: () {
|
||||
// Open slide drawer
|
||||
// Suppress auto-focus and dismiss keyboard, then open drawer
|
||||
try {
|
||||
ref
|
||||
.read(
|
||||
composerAutofocusEnabledProvider
|
||||
.notifier,
|
||||
)
|
||||
.set(false);
|
||||
FocusManager.instance.primaryFocus?.unfocus();
|
||||
SystemChannels.textInput.invokeMethod(
|
||||
'TextInput.hide',
|
||||
);
|
||||
} catch (_) {}
|
||||
SlideDrawer.of(ctx)?.open();
|
||||
},
|
||||
icon: Icon(
|
||||
|
||||
Reference in New Issue
Block a user