feat(chat): Improve keyboard shortcuts and accessibility in chat input

This commit is contained in:
cogwheel0
2025-12-05 18:23:00 +05:30
parent f676f50c85
commit e3b47ecf87

View File

@@ -1285,6 +1285,9 @@ class _ModernChatInputState extends ConsumerState<ModernChatInput>
}) { }) {
return GestureDetector( return GestureDetector(
behavior: HitTestBehavior.opaque, behavior: HitTestBehavior.opaque,
// Exclude from semantics so screen readers interact directly with the
// TextField, which provides its own accessibility via hintText.
excludeFromSemantics: true,
onTap: () { onTap: () {
if (!widget.enabled) return; if (!widget.enabled) return;
// Explicit user intent to focus: re-enable autofocus and focus // Explicit user intent to focus: re-enable autofocus and focus
@@ -1293,21 +1296,13 @@ class _ModernChatInputState extends ConsumerState<ModernChatInput>
} catch (_) {} } catch (_) {}
_ensureFocusedIfEnabled(); _ensureFocusedIfEnabled();
}, },
child: MergeSemantics(
child: Semantics(
label: AppLocalizations.of(context)!.messageInputLabel,
hint: AppLocalizations.of(context)!.messageInputHint,
child: Shortcuts( child: Shortcuts(
shortcuts: () { shortcuts: () {
final map = <LogicalKeySet, Intent>{ final map = <LogicalKeySet, Intent>{
LogicalKeySet( LogicalKeySet(LogicalKeyboardKey.meta, LogicalKeyboardKey.enter):
LogicalKeyboardKey.meta, const _SendMessageIntent(),
LogicalKeyboardKey.enter, LogicalKeySet(LogicalKeyboardKey.control, LogicalKeyboardKey.enter):
): const _SendMessageIntent(), const _SendMessageIntent(),
LogicalKeySet(
LogicalKeyboardKey.control,
LogicalKeyboardKey.enter,
): const _SendMessageIntent(),
}; };
if (sendOnEnter) { if (sendOnEnter) {
map[LogicalKeySet(LogicalKeyboardKey.enter)] = map[LogicalKeySet(LogicalKeyboardKey.enter)] =
@@ -1346,8 +1341,7 @@ class _ModernChatInputState extends ConsumerState<ModernChatInput>
return null; return null;
}, },
), ),
_SelectNextPromptIntent: _SelectNextPromptIntent: CallbackAction<_SelectNextPromptIntent>(
CallbackAction<_SelectNextPromptIntent>(
onInvoke: (intent) { onInvoke: (intent) {
_movePromptSelection(1); _movePromptSelection(1);
return null; return null;
@@ -1384,10 +1378,15 @@ class _ModernChatInputState extends ConsumerState<ModernChatInput>
final FontWeight recordingWeight = _isRecording final FontWeight recordingWeight = _isRecording
? FontWeight.w500 ? FontWeight.w500
: FontWeight.w400; : FontWeight.w400;
final TextStyle baseChatStyle = final TextStyle baseChatStyle = AppTypography.chatMessageStyle;
AppTypography.chatMessageStyle;
return TextField( // Wrap with Semantics to provide an accessible label for screen
// readers. We avoid MergeSemantics which caused double-
// announcements. The TextField provides its own text field
// semantics; this just adds the descriptive label.
return Semantics(
label: AppLocalizations.of(context)!.messageInputLabel,
child: TextField(
controller: _controller, controller: _controller,
focusNode: _focusNode, focusNode: _focusNode,
enabled: widget.enabled, enabled: widget.enabled,
@@ -1431,8 +1430,7 @@ class _ModernChatInputState extends ConsumerState<ModernChatInput>
alignLabelWithHint: true, alignLabelWithHint: true,
), ),
// Enable pasting images and files from clipboard // Enable pasting images and files from clipboard
contentInsertionConfiguration: contentInsertionConfiguration: ContentInsertionConfiguration(
ContentInsertionConfiguration(
allowedMimeTypes: ClipboardAttachmentService allowedMimeTypes: ClipboardAttachmentService
.supportedImageMimeTypes .supportedImageMimeTypes
.toList(), .toList(),
@@ -1447,13 +1445,12 @@ class _ModernChatInputState extends ConsumerState<ModernChatInput>
if (!widget.enabled) return; if (!widget.enabled) return;
_ensureFocusedIfEnabled(); _ensureFocusedIfEnabled();
}, },
),
); );
}, },
), ),
), ),
), ),
),
),
); );
} }