From e638398b2e1511399b4bc7566c4e1faa587e089a Mon Sep 17 00:00:00 2001 From: Pierre HUBERT Date: Fri, 12 Mar 2021 22:18:32 +0100 Subject: [PATCH] Work progress on conversation form --- lib/ui/screens/conversation_screen.dart | 209 +++++++++++++++++------- pubspec.lock | 7 + pubspec.yaml | 3 + 3 files changed, 158 insertions(+), 61 deletions(-) diff --git a/lib/ui/screens/conversation_screen.dart b/lib/ui/screens/conversation_screen.dart index af5cb6d..32aeac0 100644 --- a/lib/ui/screens/conversation_screen.dart +++ b/lib/ui/screens/conversation_screen.dart @@ -22,6 +22,7 @@ import 'package:comunic/utils/list_utils.dart'; import 'package:comunic/utils/log_utils.dart'; import 'package:comunic/utils/ui_utils.dart'; import 'package:comunic/utils/video_utils.dart'; +import 'package:emoji_picker/emoji_picker.dart'; import 'package:flutter/material.dart'; import 'package:mime/mime.dart'; @@ -32,6 +33,34 @@ import 'package:mime/mime.dart'; enum ErrorLevel { NONE, MINOR, MAJOR } enum _OlderMessagesLevel { NONE, LOADING, NO_MORE_AVAILABLE } +Color get _senderColor => + darkTheme() ? Color(0xff2b343b) : Colors.green.shade900; + +Color get _receiverColor => + darkTheme() ? Color(0xff1e2225) : Colors.grey.shade600; + +const _greyColor = Color(0xff8f8f8f); + +Color get _gradientColorStart => darkTheme() ? Color(0xff00b6f3) : Colors.green; + +Color get _gradientColorEnd => + darkTheme() ? Color(0xff0184dc) : Colors.greenAccent; + +Color get _separatorColor => + darkTheme() ? Color(0xff272c35) : Color(0xffBEBEBE); + +LinearGradient get _fabGradient => LinearGradient( + colors: [_gradientColorStart, _gradientColorEnd], + begin: Alignment.topLeft, + end: Alignment.bottomRight, + ); + +LinearGradient get _disabledGradient => LinearGradient( + colors: [_greyColor, _receiverColor], + begin: Alignment.topLeft, + end: Alignment.bottomRight, + ); + class ConversationScreen extends StatefulWidget { final int conversationID; @@ -53,13 +82,18 @@ class _ConversationScreenState extends SafeState { ConversationMessagesList _messages; UsersList _usersInfo = UsersList(); ErrorLevel _error = ErrorLevel.NONE; + final _textFieldFocus = FocusNode(); + + bool _showEmojiPicker = false; bool _isSendingMessage = false; - TextEditingController _textEditingController = TextEditingController(); + TextEditingController _textController = TextEditingController(); ScrollWatcher _scrollController; _OlderMessagesLevel _loadingOlderMessages = _OlderMessagesLevel.NONE; - String get textMessage => _textEditingController.text; + bool get _isWriting => !_isSendingMessage && _textController.text.isNotEmpty; + + String get textMessage => _textController.text; bool get _isMessageValid => textMessage.length >= @@ -67,6 +101,14 @@ class _ConversationScreenState extends SafeState { textMessage.length < ServerConfigurationHelper.config.conversationsPolicy.maxMessageLen; + showKeyboard() => _textFieldFocus.requestFocus(); + + hideKeyboard() => _textFieldFocus.unfocus(); + + hideEmojiContainer() => setState(() => _showEmojiPicker = false); + + showEmojiContainer() => setState(() => _showEmojiPicker = true); + @override void initState() { super.initState(); @@ -293,7 +335,7 @@ class _ConversationScreenState extends SafeState { /// Clear send message form void _clearSendMessageForm() { - setState(() => _textEditingController = TextEditingController()); + setState(() => _textController = TextEditingController()); } /// Check if a message is the last message of a user or not @@ -358,67 +400,111 @@ class _ConversationScreenState extends SafeState { ); } - /// Send message form - Widget _buildSendMessageForm() { - return new Container( - margin: const EdgeInsets.symmetric(horizontal: 8.0), - child: new Row( - children: [ - // Image area - new Container( - margin: new EdgeInsets.symmetric(horizontal: 4.0), - child: new IconButton( - icon: new Icon( - Icons.add, - color: _isSendingMessage - ? Theme.of(context).disabledColor - : Theme.of(context).accentColor, - ), - onPressed: () => _sendFileMessage(), - ), - ), - - // Message area - new Flexible( - child: new TextField( - keyboardType: TextInputType.text, - maxLines: null, - maxLength: ServerConfigurationHelper - .config.conversationsPolicy.maxMessageLen, - maxLengthEnforced: true, - - // Show max length only when there is some text already typed - buildCounter: smartInputCounterWidgetBuilder, - - enabled: !_isSendingMessage, - controller: _textEditingController, - onChanged: (s) => setState(() {}), - onSubmitted: _isMessageValid ? (s) => _submitTextMessage() : null, - decoration: new InputDecoration.collapsed( - hintText: tr("Send a message"), + /// Send new message form + Widget _buildSendMessageForm() => Container( + padding: EdgeInsets.all(10), + child: Row( + children: [ + GestureDetector( + onTap: !_isSendingMessage ? _sendFileMessage : null, + child: Container( + padding: EdgeInsets.all(10), + decoration: BoxDecoration( + gradient: + _isSendingMessage ? _disabledGradient : _fabGradient, + shape: BoxShape.circle, + ), + child: Icon( + Icons.add, + color: darkTheme() ? Colors.black : Colors.white, + ), ), ), - ), - - // Send button - new Container( - margin: const EdgeInsets.symmetric(horizontal: 4.0), - child: new IconButton( - icon: new Icon( - Icons.send, - color: !_isSendingMessage && _isMessageValid - ? Theme.of(context).accentColor - : Theme.of(context).disabledColor, + SizedBox(width: 5), + Expanded( + child: Stack( + alignment: Alignment.centerRight, + children: [ + TextField( + enabled: !_isSendingMessage, + maxLines: 10, + minLines: 1, + controller: _textController, + focusNode: _textFieldFocus, + onTap: () => hideEmojiContainer(), + textInputAction: TextInputAction.send, + onSubmitted: (s) => _submitTextMessage(), + style: TextStyle( + color: darkTheme() ? Colors.white : Colors.black, + ), + onChanged: (s) => setState(() {}), + decoration: InputDecoration( + hintText: tr("New message..."), + hintStyle: TextStyle( + color: _greyColor, + ), + border: OutlineInputBorder( + borderRadius: const BorderRadius.all( + const Radius.circular(50.0), + ), + borderSide: BorderSide.none), + contentPadding: EdgeInsets.fromLTRB(20, 10, 32, 10), + filled: true, + fillColor: _separatorColor, + ), + ), + IconButton( + splashColor: Colors.transparent, + highlightColor: Colors.transparent, + onPressed: () { + if (!_showEmojiPicker) { + // keyboard is visible + hideKeyboard(); + Future.delayed(Duration(milliseconds: 100), + () => showEmojiContainer()); + } else { + //keyboard is hidden + showKeyboard(); + hideEmojiContainer(); + } + }, + icon: Icon( + Icons.face, + color: _showEmojiPicker ? Colors.green : null, + ), + ), + ], ), - onPressed: !_isSendingMessage && _isMessageValid - ? () => _submitTextMessage() - : null, ), - ), - ], - ), - ); - } + Container( + margin: EdgeInsets.only(left: 10), + decoration: BoxDecoration( + gradient: _isWriting ? _fabGradient : _disabledGradient, + shape: BoxShape.circle, + ), + child: IconButton( + icon: Icon( + Icons.send, + size: 15, + color: darkTheme() ? Colors.black : Colors.white, + ), + onPressed: _isWriting ? _submitTextMessage : null, + )) + ], + ), + ); + + Widget _buildEmojiContainer() => EmojiPicker( + bgColor: Colors.green, + indicatorColor: Colors.green, + rows: 3, + columns: 7, + onEmojiSelected: (emoji, category) { + _textController.text = _textController.text + emoji.emoji; + }, + recommendKeywords: ["face", "happy", "party", "sad"], + numRecommended: 50, + ); @override Widget build(BuildContext context) { @@ -438,7 +524,8 @@ class _ConversationScreenState extends SafeState { ), _messages.length == 0 ? _buildNoMessagesNotice() : _buildMessagesList(), Divider(), - _buildSendMessageForm() + _buildSendMessageForm(), + _showEmojiPicker ? _buildEmojiContainer() : Container(), ], ); } diff --git a/pubspec.lock b/pubspec.lock index 1cc7a64..eaa93bc 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -155,6 +155,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "0.0.3" + emoji_picker: + dependency: "direct main" + description: + name: emoji_picker + url: "https://pub.dartlang.org" + source: hosted + version: "0.1.0" event_bus: dependency: "direct main" description: diff --git a/pubspec.yaml b/pubspec.yaml index c254548..73afd3e 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -118,6 +118,9 @@ dependencies: # Request permissions permission_handler: ^5.1.0+2 + # Emojies picker + emoji_picker: ^0.1.0 + dev_dependencies: flutter_test: sdk: flutter