diff --git a/lib/features/chat/widgets/modern_chat_input.dart b/lib/features/chat/widgets/modern_chat_input.dart index d152c0c..8dd5383 100644 --- a/lib/features/chat/widgets/modern_chat_input.dart +++ b/lib/features/chat/widgets/modern_chat_input.dart @@ -1293,157 +1293,163 @@ class _ModernChatInputState extends ConsumerState } catch (_) {} _ensureFocusedIfEnabled(); }, - child: Semantics( - textField: true, - label: AppLocalizations.of(context)!.messageInputLabel, - hint: AppLocalizations.of(context)!.messageInputHint, - child: Shortcuts( - shortcuts: () { - final map = { - LogicalKeySet(LogicalKeyboardKey.meta, LogicalKeyboardKey.enter): - const _SendMessageIntent(), - LogicalKeySet( - LogicalKeyboardKey.control, - LogicalKeyboardKey.enter, - ): const _SendMessageIntent(), - }; - if (sendOnEnter) { - map[LogicalKeySet(LogicalKeyboardKey.enter)] = - const _SendMessageIntent(); - map[LogicalKeySet( - LogicalKeyboardKey.shift, - LogicalKeyboardKey.enter, - )] = - const _InsertNewlineIntent(); - } - if (_showPromptOverlay) { - map[LogicalKeySet(LogicalKeyboardKey.arrowDown)] = - const _SelectNextPromptIntent(); - map[LogicalKeySet(LogicalKeyboardKey.arrowUp)] = - const _SelectPreviousPromptIntent(); - map[LogicalKeySet(LogicalKeyboardKey.escape)] = - const _DismissPromptIntent(); - } - return map; - }(), - child: Actions( - actions: >{ - _SendMessageIntent: CallbackAction<_SendMessageIntent>( - onInvoke: (intent) { - if (_showPromptOverlay) { - _confirmPromptSelection(); - return null; - } - _sendMessage(); - return null; - }, - ), - _InsertNewlineIntent: CallbackAction<_InsertNewlineIntent>( - onInvoke: (intent) { - _insertNewline(); - return null; - }, - ), - _SelectNextPromptIntent: CallbackAction<_SelectNextPromptIntent>( - onInvoke: (intent) { - _movePromptSelection(1); - return null; - }, - ), - _SelectPreviousPromptIntent: - CallbackAction<_SelectPreviousPromptIntent>( - onInvoke: (intent) { - _movePromptSelection(-1); + child: MergeSemantics( + child: Semantics( + label: AppLocalizations.of(context)!.messageInputLabel, + hint: AppLocalizations.of(context)!.messageInputHint, + child: Shortcuts( + shortcuts: () { + final map = { + LogicalKeySet( + LogicalKeyboardKey.meta, + LogicalKeyboardKey.enter, + ): const _SendMessageIntent(), + LogicalKeySet( + LogicalKeyboardKey.control, + LogicalKeyboardKey.enter, + ): const _SendMessageIntent(), + }; + if (sendOnEnter) { + map[LogicalKeySet(LogicalKeyboardKey.enter)] = + const _SendMessageIntent(); + map[LogicalKeySet( + LogicalKeyboardKey.shift, + LogicalKeyboardKey.enter, + )] = + const _InsertNewlineIntent(); + } + if (_showPromptOverlay) { + map[LogicalKeySet(LogicalKeyboardKey.arrowDown)] = + const _SelectNextPromptIntent(); + map[LogicalKeySet(LogicalKeyboardKey.arrowUp)] = + const _SelectPreviousPromptIntent(); + map[LogicalKeySet(LogicalKeyboardKey.escape)] = + const _DismissPromptIntent(); + } + return map; + }(), + child: Actions( + actions: >{ + _SendMessageIntent: CallbackAction<_SendMessageIntent>( + onInvoke: (intent) { + if (_showPromptOverlay) { + _confirmPromptSelection(); return null; - }, - ), - _DismissPromptIntent: CallbackAction<_DismissPromptIntent>( - onInvoke: (intent) { - _hidePromptOverlay(); - return null; - }, - ), - }, - child: Builder( - builder: (context) { - final double factor = isActive ? 1.0 : 0.0; - final Color animatedPlaceholder = Color.lerp( - placeholderBase, - placeholderFocused, - factor, - )!; - final Color animatedTextColor = Color.lerp( - context.conduitTheme.inputText.withValues(alpha: 0.88), - context.conduitTheme.inputText, - factor, - )!; + } + _sendMessage(); + return null; + }, + ), + _InsertNewlineIntent: CallbackAction<_InsertNewlineIntent>( + onInvoke: (intent) { + _insertNewline(); + return null; + }, + ), + _SelectNextPromptIntent: + CallbackAction<_SelectNextPromptIntent>( + onInvoke: (intent) { + _movePromptSelection(1); + return null; + }, + ), + _SelectPreviousPromptIntent: + CallbackAction<_SelectPreviousPromptIntent>( + onInvoke: (intent) { + _movePromptSelection(-1); + return null; + }, + ), + _DismissPromptIntent: CallbackAction<_DismissPromptIntent>( + onInvoke: (intent) { + _hidePromptOverlay(); + return null; + }, + ), + }, + child: Builder( + builder: (context) { + final double factor = isActive ? 1.0 : 0.0; + final Color animatedPlaceholder = Color.lerp( + placeholderBase, + placeholderFocused, + factor, + )!; + final Color animatedTextColor = Color.lerp( + context.conduitTheme.inputText.withValues(alpha: 0.88), + context.conduitTheme.inputText, + factor, + )!; - final FontWeight recordingWeight = _isRecording - ? FontWeight.w500 - : FontWeight.w400; - final TextStyle baseChatStyle = AppTypography.chatMessageStyle; + final FontWeight recordingWeight = _isRecording + ? FontWeight.w500 + : FontWeight.w400; + final TextStyle baseChatStyle = + AppTypography.chatMessageStyle; - return TextField( - controller: _controller, - focusNode: _focusNode, - enabled: widget.enabled, - autofocus: false, - minLines: 1, - maxLines: null, - keyboardType: TextInputType.multiline, - textCapitalization: TextCapitalization.sentences, - textInputAction: sendOnEnter - ? TextInputAction.send - : TextInputAction.newline, - autofillHints: const [], - showCursor: true, - scrollPadding: const EdgeInsets.only(bottom: 80), - keyboardAppearance: brightness, - cursorColor: animatedTextColor, - style: baseChatStyle.copyWith( - color: animatedTextColor, - fontStyle: _isRecording - ? FontStyle.italic - : FontStyle.normal, - fontWeight: recordingWeight, - ), - decoration: InputDecoration( - hintText: AppLocalizations.of(context)!.messageHintText, - hintStyle: baseChatStyle.copyWith( - color: animatedPlaceholder, - fontWeight: recordingWeight, + return TextField( + controller: _controller, + focusNode: _focusNode, + enabled: widget.enabled, + autofocus: false, + minLines: 1, + maxLines: null, + keyboardType: TextInputType.multiline, + textCapitalization: TextCapitalization.sentences, + textInputAction: sendOnEnter + ? TextInputAction.send + : TextInputAction.newline, + autofillHints: const [], + showCursor: true, + scrollPadding: const EdgeInsets.only(bottom: 80), + keyboardAppearance: brightness, + cursorColor: animatedTextColor, + style: baseChatStyle.copyWith( + color: animatedTextColor, fontStyle: _isRecording ? FontStyle.italic : FontStyle.normal, + fontWeight: recordingWeight, ), - filled: false, - border: InputBorder.none, - enabledBorder: InputBorder.none, - focusedBorder: InputBorder.none, - errorBorder: InputBorder.none, - disabledBorder: InputBorder.none, - contentPadding: contentPadding, - isDense: true, - alignLabelWithHint: true, - ), - // Enable pasting images and files from clipboard - contentInsertionConfiguration: ContentInsertionConfiguration( - allowedMimeTypes: ClipboardAttachmentService - .supportedImageMimeTypes - .toList(), - onContentInserted: _handleContentInserted, - ), - onSubmitted: (_) { - if (sendOnEnter) { - _sendMessage(); - } - }, - onTap: () { - if (!widget.enabled) return; - _ensureFocusedIfEnabled(); - }, - ); - }, + decoration: InputDecoration( + hintText: AppLocalizations.of(context)!.messageHintText, + hintStyle: baseChatStyle.copyWith( + color: animatedPlaceholder, + fontWeight: recordingWeight, + fontStyle: _isRecording + ? FontStyle.italic + : FontStyle.normal, + ), + filled: false, + border: InputBorder.none, + enabledBorder: InputBorder.none, + focusedBorder: InputBorder.none, + errorBorder: InputBorder.none, + disabledBorder: InputBorder.none, + contentPadding: contentPadding, + isDense: true, + alignLabelWithHint: true, + ), + // Enable pasting images and files from clipboard + contentInsertionConfiguration: + ContentInsertionConfiguration( + allowedMimeTypes: ClipboardAttachmentService + .supportedImageMimeTypes + .toList(), + onContentInserted: _handleContentInserted, + ), + onSubmitted: (_) { + if (sendOnEnter) { + _sendMessage(); + } + }, + onTap: () { + if (!widget.enabled) return; + _ensureFocusedIfEnabled(); + }, + ); + }, + ), ), ), ),