Revert auto reformatting and limit format to only emojies (text edit of chat).

Fix crash when creating video thumbnail on context management (let Qt to decide what to do).
This commit is contained in:
Julien Wadel 2023-04-14 09:52:48 +02:00
parent c5bb7f4a26
commit e326ba9437
7 changed files with 21 additions and 53 deletions

View file

@ -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())

View file

@ -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()){

View file

@ -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<uint> 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 = "<div>" + images +"</div>";
return images + "<p style=\"white-space:pre-wrap;\">" + replaceEmoji(formattedText.join("")) + "</p>";
return images + "<p style=\"white-space:pre-wrap;\">" + encodeEmojiToQmlRichFormat(formattedText.join("")) + "</p>";
}
QString Utils::getFileContent(const QString& filePath){

View file

@ -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);

View file

@ -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 <font> 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

View file

@ -377,7 +377,7 @@ Rectangle {
}
ChatEmojis{
id: chatEmojis
onEmojiClicked: textArea.insert(emoji)
onEmojiClicked: textArea.insertEmoji(emoji)
Layout.fillWidth: true
}
// -------------------------------------------------------------------------

View file

@ -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