diff --git a/lib/src/models/config_models/send_message_configuration.dart b/lib/src/models/config_models/send_message_configuration.dart index 8909d7a3..0f02bd55 100644 --- a/lib/src/models/config_models/send_message_configuration.dart +++ b/lib/src/models/config_models/send_message_configuration.dart @@ -168,6 +168,10 @@ class TextFieldConfiguration { /// Default is [true]. final bool enabled; + /// Determines if pressing enter submits the message. + /// Defaults to false. + final bool enableEnterToSubmit; + const TextFieldConfiguration({ this.contentPadding, this.maxLines, @@ -184,6 +188,7 @@ class TextFieldConfiguration { this.inputFormatters, this.textCapitalization, this.enabled = true, + this.enableEnterToSubmit = false, }); } diff --git a/lib/src/widgets/chatui_textfield.dart b/lib/src/widgets/chatui_textfield.dart index ec6cf0bc..917610af 100644 --- a/lib/src/widgets/chatui_textfield.dart +++ b/lib/src/widgets/chatui_textfield.dart @@ -76,35 +76,28 @@ class _ChatUITextFieldState extends State { SendMessageConfiguration? get sendMessageConfig => widget.sendMessageConfig; - VoiceRecordingConfiguration? get voiceRecordingConfig => - widget.sendMessageConfig?.voiceRecordingConfiguration; + VoiceRecordingConfiguration? get voiceRecordingConfig => widget.sendMessageConfig?.voiceRecordingConfiguration; - ImagePickerIconsConfiguration? get imagePickerIconsConfig => - sendMessageConfig?.imagePickerIconsConfig; + ImagePickerIconsConfiguration? get imagePickerIconsConfig => sendMessageConfig?.imagePickerIconsConfig; - TextFieldConfiguration? get textFieldConfig => - sendMessageConfig?.textFieldConfig; + TextFieldConfiguration? get textFieldConfig => sendMessageConfig?.textFieldConfig; - CancelRecordConfiguration? get cancelRecordConfiguration => - sendMessageConfig?.cancelRecordConfiguration; + CancelRecordConfiguration? get cancelRecordConfiguration => sendMessageConfig?.cancelRecordConfiguration; OutlineInputBorder get _outLineBorder => OutlineInputBorder( borderSide: const BorderSide(color: Colors.transparent), - borderRadius: widget.sendMessageConfig?.textFieldConfig?.borderRadius ?? - BorderRadius.circular(textFieldBorderRadius), + borderRadius: + widget.sendMessageConfig?.textFieldConfig?.borderRadius ?? BorderRadius.circular(textFieldBorderRadius), ); - ValueNotifier composingStatus = - ValueNotifier(TypeWriterStatus.typed); + ValueNotifier composingStatus = ValueNotifier(TypeWriterStatus.typed); late Debouncer debouncer; @override void initState() { attachListeners(); - debouncer = Debouncer( - sendMessageConfig?.textFieldConfig?.compositionThresholdTime ?? - const Duration(seconds: 1)); + debouncer = Debouncer(sendMessageConfig?.textFieldConfig?.compositionThresholdTime ?? const Duration(seconds: 1)); super.initState(); if (!kIsWeb && (Platform.isIOS || Platform.isAndroid)) { @@ -123,8 +116,7 @@ class _ChatUITextFieldState extends State { void attachListeners() { composingStatus.addListener(() { - widget.sendMessageConfig?.textFieldConfig?.onMessageTyping - ?.call(composingStatus.value); + widget.sendMessageConfig?.textFieldConfig?.onMessageTyping?.call(composingStatus.value); }); } @@ -132,12 +124,10 @@ class _ChatUITextFieldState extends State { Widget build(BuildContext context) { final outlineBorder = _outLineBorder; return Container( - padding: - textFieldConfig?.padding ?? const EdgeInsets.symmetric(horizontal: 6), + padding: textFieldConfig?.padding ?? const EdgeInsets.symmetric(horizontal: 6), margin: textFieldConfig?.margin, decoration: BoxDecoration( - borderRadius: textFieldConfig?.borderRadius ?? - BorderRadius.circular(textFieldBorderRadius), + borderRadius: textFieldConfig?.borderRadius ?? BorderRadius.circular(textFieldBorderRadius), color: sendMessageConfig?.textFieldBackgroundColor ?? Colors.white, ), child: ValueListenableBuilder( @@ -164,9 +154,7 @@ class _ChatUITextFieldState extends State { WaveStyle( extendWaveform: true, showMiddleLine: false, - waveColor: - voiceRecordingConfig?.waveStyle?.waveColor ?? - Colors.black, + waveColor: voiceRecordingConfig?.waveStyle?.waveColor ?? Colors.black, ), ), ) @@ -175,21 +163,21 @@ class _ChatUITextFieldState extends State { child: TextField( focusNode: widget.focusNode, controller: widget.textEditingController, - style: textFieldConfig?.textStyle ?? - const TextStyle(color: Colors.white), + style: textFieldConfig?.textStyle ?? const TextStyle(color: Colors.white), maxLines: textFieldConfig?.maxLines ?? 5, minLines: textFieldConfig?.minLines ?? 1, keyboardType: textFieldConfig?.textInputType, inputFormatters: textFieldConfig?.inputFormatters, onChanged: _onChanged, - enabled: textFieldConfig?.enabled, - textCapitalization: textFieldConfig?.textCapitalization ?? - TextCapitalization.sentences, + enabled: textFieldConfig?.enabled ?? true, + textCapitalization: textFieldConfig?.textCapitalization ?? TextCapitalization.sentences, + onSubmitted: (textFieldConfig?.enableEnterToSubmit ?? false) ? _onSubmit : null, + textInputAction: (textFieldConfig?.enableEnterToSubmit ?? false) + ? TextInputAction.send + : TextInputAction.newline, decoration: InputDecoration( - hintText: - textFieldConfig?.hintText ?? PackageStrings.message, - fillColor: sendMessageConfig?.textFieldBackgroundColor ?? - Colors.white, + hintText: textFieldConfig?.hintText ?? PackageStrings.message, + fillColor: sendMessageConfig?.textFieldBackgroundColor ?? Colors.white, filled: true, hintStyle: textFieldConfig?.hintStyle ?? TextStyle( @@ -198,8 +186,7 @@ class _ChatUITextFieldState extends State { color: Colors.grey.shade600, letterSpacing: 0.25, ), - contentPadding: textFieldConfig?.contentPadding ?? - const EdgeInsets.symmetric(horizontal: 6), + contentPadding: textFieldConfig?.contentPadding ?? const EdgeInsets.symmetric(horizontal: 6), border: outlineBorder, focusedBorder: outlineBorder, enabledBorder: outlineBorder, @@ -212,57 +199,47 @@ class _ChatUITextFieldState extends State { builder: (_, inputTextValue, child) { if (inputTextValue.isNotEmpty) { return IconButton( - color: sendMessageConfig?.defaultSendButtonColor ?? - Colors.green, + color: sendMessageConfig?.defaultSendButtonColor ?? Colors.green, onPressed: (textFieldConfig?.enabled ?? true) ? () { widget.onPressed(); _inputText.value = ''; } : null, - icon: sendMessageConfig?.sendButtonIcon ?? - const Icon(Icons.send), + icon: sendMessageConfig?.sendButtonIcon ?? const Icon(Icons.send), ); } else { return Row( children: [ if (!isRecordingValue) ...[ - if (sendMessageConfig?.enableCameraImagePicker ?? - true) + if (sendMessageConfig?.enableCameraImagePicker ?? true) IconButton( constraints: const BoxConstraints(), onPressed: (textFieldConfig?.enabled ?? true) ? () => _onIconPressed( ImageSource.camera, - config: sendMessageConfig - ?.imagePickerConfiguration, + config: sendMessageConfig?.imagePickerConfiguration, ) : null, - icon: imagePickerIconsConfig - ?.cameraImagePickerIcon ?? + icon: imagePickerIconsConfig?.cameraImagePickerIcon ?? Icon( Icons.camera_alt_outlined, - color: - imagePickerIconsConfig?.cameraIconColor, + color: imagePickerIconsConfig?.cameraIconColor, ), ), - if (sendMessageConfig?.enableGalleryImagePicker ?? - true) + if (sendMessageConfig?.enableGalleryImagePicker ?? true) IconButton( constraints: const BoxConstraints(), onPressed: (textFieldConfig?.enabled ?? true) ? () => _onIconPressed( ImageSource.gallery, - config: sendMessageConfig - ?.imagePickerConfiguration, + config: sendMessageConfig?.imagePickerConfiguration, ) : null, - icon: imagePickerIconsConfig - ?.galleryImagePickerIcon ?? + icon: imagePickerIconsConfig?.galleryImagePickerIcon ?? Icon( Icons.image, - color: imagePickerIconsConfig - ?.galleryIconColor, + color: imagePickerIconsConfig?.galleryIconColor, ), ), ], @@ -270,29 +247,21 @@ class _ChatUITextFieldState extends State { !kIsWeb && (Platform.isIOS || Platform.isAndroid)) IconButton( - onPressed: (textFieldConfig?.enabled ?? true) - ? _recordOrStop - : null, - icon: (isRecordingValue - ? voiceRecordingConfig?.stopIcon - : voiceRecordingConfig?.micIcon) ?? + onPressed: (textFieldConfig?.enabled ?? true) ? _recordOrStop : null, + icon: (isRecordingValue ? voiceRecordingConfig?.stopIcon : voiceRecordingConfig?.micIcon) ?? Icon( isRecordingValue ? Icons.stop : Icons.mic, - color: - voiceRecordingConfig?.recorderIconColor, + color: voiceRecordingConfig?.recorderIconColor, ), ), - if (isRecordingValue && - cancelRecordConfiguration != null) + if (isRecordingValue && cancelRecordConfiguration != null) IconButton( onPressed: () { cancelRecordConfiguration?.onCancel?.call(); _cancelRecording(); }, - icon: cancelRecordConfiguration?.icon ?? - const Icon(Icons.cancel_outlined), - color: cancelRecordConfiguration?.iconColor ?? - voiceRecordingConfig?.recorderIconColor, + icon: cancelRecordConfiguration?.icon ?? const Icon(Icons.cancel_outlined), + color: cancelRecordConfiguration?.iconColor ?? voiceRecordingConfig?.recorderIconColor, ), ], ); @@ -308,8 +277,7 @@ class _ChatUITextFieldState extends State { FutureOr _cancelRecording() async { assert( - defaultTargetPlatform == TargetPlatform.iOS || - defaultTargetPlatform == TargetPlatform.android, + defaultTargetPlatform == TargetPlatform.iOS || defaultTargetPlatform == TargetPlatform.android, "Voice messages are only supported with android and ios platform", ); if (!isRecording.value) return; @@ -329,8 +297,7 @@ class _ChatUITextFieldState extends State { Future _recordOrStop() async { assert( - defaultTargetPlatform == TargetPlatform.iOS || - defaultTargetPlatform == TargetPlatform.android, + defaultTargetPlatform == TargetPlatform.iOS || defaultTargetPlatform == TargetPlatform.android, "Voice messages are only supported with android and ios platform", ); if (!isRecording.value) { @@ -359,8 +326,7 @@ class _ChatUITextFieldState extends State { maxHeight: config?.maxHeight, maxWidth: config?.maxWidth, imageQuality: config?.imageQuality, - preferredCameraDevice: - config?.preferredCameraDevice ?? CameraDevice.rear, + preferredCameraDevice: config?.preferredCameraDevice ?? CameraDevice.rear, ); String? imagePath = image?.path; if (config?.onImagePicked != null) { @@ -381,4 +347,11 @@ class _ChatUITextFieldState extends State { }); _inputText.value = inputText; } + + void _onSubmit(String inputText) { + if (inputText.isNotEmpty) { + widget.onPressed(); + _inputText.value = ''; + } + } }