diff --git a/linphone-app/src/components/chat-room/ChatRoomProxyModel.cpp b/linphone-app/src/components/chat-room/ChatRoomProxyModel.cpp index 6848d9f7d..d0d1086db 100644 --- a/linphone-app/src/components/chat-room/ChatRoomProxyModel.cpp +++ b/linphone-app/src/components/chat-room/ChatRoomProxyModel.cpp @@ -87,7 +87,7 @@ ChatRoomProxyModel::~ChatRoomProxyModel(){ CREATE_PARENT_MODEL_FUNCTION(removeAllEntries) -CREATE_PARENT_MODEL_FUNCTION_WITH_PARAM(sendMessage, const QString &) + CREATE_PARENT_MODEL_FUNCTION_WITH_PARAM(forwardMessage, ChatMessageModel *) CREATE_PARENT_MODEL_FUNCTION_WITH_ID(removeRow) @@ -99,6 +99,11 @@ CREATE_PARENT_MODEL_FUNCTION(deleteChatRoom) #undef CREATE_PARENT_MODEL_FUNCTION_WITH_PARAM #undef CREATE_PARENT_MODEL_FUNCTION_WITH_ID +void ChatRoomProxyModel::sendMessage(const QString &text){ + QString trim = text.trimmed(); + if (mChatRoomModel && !trim.isEmpty()) + mChatRoomModel->sendMessage(trim); +} void ChatRoomProxyModel::compose (const QString& text) { if (mChatRoomModel && !text.isEmpty()) diff --git a/linphone-app/src/components/other/images/ImageModel.cpp b/linphone-app/src/components/other/images/ImageModel.cpp index aa4340814..e17eae237 100644 --- a/linphone-app/src/components/other/images/ImageModel.cpp +++ b/linphone-app/src/components/other/images/ImageModel.cpp @@ -159,23 +159,20 @@ QImage ImageModel::createThumbnail(const QString& path){ if(!format.isEmpty()) originalImage = QImage(path, format); else if(Utils::isVideo(path)){ - QMediaPlayer player; + QObject context; + QMediaPlayer player(&context); player.setMedia(QUrl::fromLocalFile(path)); player.setPosition(player.duration() / 2); - VideoFrameGrabber grabber; + VideoFrameGrabber grabber(&context); player.setVideoOutput(&grabber); - QObject * context = new QObject(); - QObject::connect(&grabber, &VideoFrameGrabber::frameAvailable, context, [&context,&originalImage, &player](QImage frame) mutable{ + QObject::connect(&grabber, &VideoFrameGrabber::frameAvailable, &context, [&context,&originalImage, &player](QImage frame) mutable{ originalImage = frame.copy(); player.stop(); - context->deleteLater();// This will destroy context and initializer - context = nullptr; }, Qt::DirectConnection); player.play(); do{ qApp->processEvents(); }while(player.state() != QMediaPlayer::State::StoppedState); - if(context) context->deleteLater(); } } if (!originalImage.isNull()){ diff --git a/linphone-app/src/utils/Utils.cpp b/linphone-app/src/utils/Utils.cpp index 893ef6ff8..88a3c63fe 100644 --- a/linphone-app/src/utils/Utils.cpp +++ b/linphone-app/src/utils/Utils.cpp @@ -705,7 +705,7 @@ bool Utils::codepointIsEmoji(uint code){ (code >= 0x1f000 && code <= 0x1faff) || code == 0x200d || code == 0xfe0f; } -QString Utils::replaceEmoji(const QString &body){ +QString Utils::encodeEmojiToQmlRichFormat(const QString &body){ QString fmtBody = ""; QVector utf32_string = body.toUcs4(); @@ -739,6 +739,7 @@ bool Utils::isOnlyEmojis(const QString& text){ return true; } + QString Utils::encodeTextToQmlRichFormat(const QString& text, const QVariantMap& options){ QString images; QStringList formattedText; @@ -794,7 +795,7 @@ QString Utils::encodeTextToQmlRichFormat(const QString& text, const QVariantMap& if(images != "") images = "
" + images +"
"; - return images + "

" + replaceEmoji(formattedText.join("")) + "

"; + return images + "

" + encodeEmojiToQmlRichFormat(formattedText.join("")) + "

"; } QString Utils::getFileContent(const QString& filePath){ diff --git a/linphone-app/src/utils/Utils.hpp b/linphone-app/src/utils/Utils.hpp index 43710e8f4..b33fbd127 100644 --- a/linphone-app/src/utils/Utils.hpp +++ b/linphone-app/src/utils/Utils.hpp @@ -78,8 +78,8 @@ public: Q_INVOKABLE static QPoint getCursorPosition(); Q_INVOKABLE static QString getFileChecksum(const QString& filePath); static bool codepointIsEmoji(uint code); - static QString replaceEmoji(const QString &body); Q_INVOKABLE static bool isOnlyEmojis(const QString& text); + Q_INVOKABLE static QString encodeEmojiToQmlRichFormat(const QString &body); Q_INVOKABLE static QString encodeTextToQmlRichFormat(const QString& text, const QVariantMap& options = QVariantMap()); Q_INVOKABLE static QString getFileContent(const QString& filePath); diff --git a/linphone-app/ui/modules/Common/Form/DroppableTextArea.qml b/linphone-app/ui/modules/Common/Form/DroppableTextArea.qml index eddeefbf8..b36ce87cf 100644 --- a/linphone-app/ui/modules/Common/Form/DroppableTextArea.qml +++ b/linphone-app/ui/modules/Common/Form/DroppableTextArea.qml @@ -59,7 +59,10 @@ Item { function getText(){ return textArea.getText(0, textArea.text.length) } - + function insertEmoji(code){ + code = UtilsCpp.encodeEmojiToQmlRichFormat(code) + textArea.insert(textArea.cursorPosition, code+' ') // Add a space or next text will be entered inside of emoji. + } Rectangle{ anchors.fill: parent color: DroppableTextAreaStyle.outsideBackgroundColor.color @@ -182,44 +185,10 @@ Item { height:flickableArea.height //onHeightChanged: height=flickableArea.height//TextArea change its height from content text. Force it to parent - Timer{// This timer is used to rewrite rich texts from new text only on idle. - id: refreshFormatTimer - //This fix having the wrong format while typing next to emojies. - property bool blockTextChanged : false // Block text changed signal when the format is converted. - property bool textChanged: false // The text has been changed while timer is running (it's true when only key has been pressed like control keys) - property bool restartFromInput : false // Keep in mind that the current time loop has been reset by user inputs. - - interval: restartFromInput ? 1000 : 300 // Longer wait if user is currently entering text - repeat: false - onTriggered: { - if(textChanged){ - blockTextChanged = true // Block onTextChanged - var backupCursorPosition = textArea.cursorPosition - var lastLength = textArea.length - textArea.text = UtilsCpp.encodeTextToQmlRichFormat(textArea.getText(0,textArea.text.length))// It will send onTextChanged - backupCursorPosition += (textArea.length - lastLength) - textArea.cursorPosition = backupCursorPosition - // Reset states - blockTextChanged = false - textChanged = false - restartFromInput = false - } - } - } - onTextChanged: { - if(!refreshFormatTimer.blockTextChanged){ - refreshFormatTimer.textChanged = true - refreshFormatTimer.restart() - } - } Component.onCompleted: forceActiveFocus() property var isAutoRepeating : false // shutdown repeating key feature to let optional menu appears and do normal stuff (like accents menu) Keys.onReleased: { - if(!refreshFormatTimer.blockTextChanged){ - refreshFormatTimer.restartFromInput = true - refreshFormatTimer.restart() - } if( event.isAutoRepeat){// We begin or are currently repeating a key if(!isAutoRepeating){// We start repeat. Check if this is an "ignore" character if(event.key > Qt.Key_Any && event.key <= Qt.Key_ydiaeresis)// Remove the previous character if it is a printable character @@ -229,10 +198,6 @@ Item { isAutoRepeating = false// We are no more repeating. Final decision is done on Releasing } Keys.onPressed: { - if(!refreshFormatTimer.blockTextChanged){ - refreshFormatTimer.restartFromInput = true - refreshFormatTimer.restart() - } if(event.isAutoRepeat){ isAutoRepeating = true// Where are repeating the key. Set the state. if(event.key > Qt.Key_Any && event.key <= Qt.Key_ydiaeresis){// Ignore character if it is repeating and printable character diff --git a/linphone-app/ui/modules/Linphone/Chat/Chat.qml b/linphone-app/ui/modules/Linphone/Chat/Chat.qml index 9d4471630..1d3e199b0 100644 --- a/linphone-app/ui/modules/Linphone/Chat/Chat.qml +++ b/linphone-app/ui/modules/Linphone/Chat/Chat.qml @@ -377,7 +377,7 @@ Rectangle { } ChatEmojis{ id: chatEmojis - onEmojiClicked: textArea.insert(emoji) + onEmojiClicked: textArea.insertEmoji(emoji) Layout.fillWidth: true } // ------------------------------------------------------------------------- diff --git a/linphone-app/ui/modules/Linphone/Chat/ChatContent.qml b/linphone-app/ui/modules/Linphone/Chat/ChatContent.qml index 1ca050026..206fb76e6 100644 --- a/linphone-app/ui/modules/Linphone/Chat/ChatContent.qml +++ b/linphone-app/ui/modules/Linphone/Chat/ChatContent.qml @@ -133,7 +133,7 @@ Loader{// Use of Loader because of Repeater (items cannot be loaded dynamically) delegate: ChatConferenceInvitationMessage{ id: calendarMessage contentModel: $modelData - width: parent.width + width: parent && parent.width availableWidth: mainItem.availableWidth gotoButtonMode: 1 onExpandToggle: isExpanded=!isExpanded @@ -203,7 +203,7 @@ Loader{// Use of Loader because of Repeater (items cannot be loaded dynamically) Component.onCompleted: messagesTextsList.updateBestWidth() delegate: ChatTextMessage { - width: parent.width + width: parent && parent.width contentModel: $modelData onLastTextSelectedChanged: mainItem.lastTextSelectedChanged(lastTextSelected) color: mainItem.useTextColor