emoji details

This commit is contained in:
Gaelle Braud 2025-06-17 17:11:55 +02:00
parent 7484962441
commit 1d7010c381
23 changed files with 540 additions and 44 deletions

View file

@ -63,7 +63,7 @@
#include "core/conference/ConferenceGui.hpp"
#include "core/conference/ConferenceInfoGui.hpp"
#include "core/conference/ConferenceInfoProxy.hpp"
#include "core/emoji/EmojiModel.hpp"
#include "core/emoji/EmojiProxy.hpp"
#include "core/fps-counter/FPSCounter.hpp"
#include "core/friend/FriendCore.hpp"
#include "core/friend/FriendGui.hpp"
@ -686,6 +686,7 @@ void App::initCppInterfaces() {
qmlRegisterType<CameraGui>(Constants::MainQmlUri, 1, 0, "CameraGui");
qmlRegisterType<FPSCounter>(Constants::MainQmlUri, 1, 0, "FPSCounter");
qmlRegisterType<EmojiModel>(Constants::MainQmlUri, 1, 0, "EmojiModel");
qmlRegisterType<EmojiProxy>(Constants::MainQmlUri, 1, 0, "EmojiProxy");
qmlRegisterType<SoundPlayerGui>(Constants::MainQmlUri, 1, 0, "SoundPlayerGui");
qmlRegisterType<RecorderGui>(Constants::MainQmlUri, 1, 0, "RecorderGui");

View file

@ -33,7 +33,9 @@ list(APPEND _LINPHONEAPP_SOURCES
core/chat/message/content/ChatMessageContentGui.cpp
core/chat/message/content/ChatMessageContentList.cpp
core/chat/message/content/ChatMessageContentProxy.cpp
core/emoji/EmojiList.cpp
core/emoji/EmojiModel.cpp
core/emoji/EmojiProxy.cpp
core/fps-counter/FPSCounter.cpp
core/friend/FriendCore.cpp
core/friend/FriendGui.cpp

View file

@ -97,6 +97,8 @@ ChatMessageCore::ChatMessageCore(const std::shared_ptr<linphone::ChatMessage> &c
mVoiceRecordingContent = contentCore;
}
}
//: "Reactions": all reactions for one message label
mTotalReactionsLabel = tr("all_reactions_label");
auto reac = chatmessage->getOwnReaction();
mOwnReaction = reac ? Utils::coreStringToAppString(reac->getBody()) : QString();
for (auto &reaction : chatmessage->getReactions()) {
@ -121,6 +123,8 @@ ChatMessageCore::ChatMessageCore(const std::shared_ptr<linphone::ChatMessage> &c
++count;
map.remove("count");
map.insert("count", count);
mReactionsSingletonMap.erase(it);
mReactionsSingletonMap.push_back(map);
}
}
}
@ -336,6 +340,10 @@ void ChatMessageCore::setOwnReaction(const QString &reaction) {
}
}
QString ChatMessageCore::getTotalReactionsLabel() const {
return mTotalReactionsLabel;
}
QList<Reaction> ChatMessageCore::getReactions() const {
return mReactions;
}
@ -344,6 +352,19 @@ QList<QVariant> ChatMessageCore::getReactionsSingleton() const {
return mReactionsSingletonMap;
}
QStringList ChatMessageCore::getReactionsSingletonAsStrings() const {
QStringList reacStringList;
int totalCount = 0;
for (auto &reac : mReactionsSingletonMap) {
auto map = reac.toMap();
auto count = map["count"].toInt();
totalCount += count;
reacStringList.append(QString("%1 %2").arg(map["body"].toString()).arg(count));
}
reacStringList.prepend(QString("%1 %2").arg(mTotalReactionsLabel).arg(totalCount));
return reacStringList;
}
QList<QSharedPointer<ChatMessageContentCore>> ChatMessageCore::getChatMessageContentList() const {
return mChatMessageContentList;
}

View file

@ -64,6 +64,7 @@ class ChatMessageCore : public QObject, public AbstractObject {
Q_PROPERTY(QString toAddress READ getToAddress CONSTANT)
Q_PROPERTY(QString peerName READ getPeerName CONSTANT)
Q_PROPERTY(QString fromName READ getFromName CONSTANT)
Q_PROPERTY(QString totalReactionsLabel READ getTotalReactionsLabel CONSTANT)
Q_PROPERTY(LinphoneEnums::ChatMessageState messageState READ getMessageState WRITE setMessageState NOTIFY
messageStateChanged)
Q_PROPERTY(bool isRemoteMessage READ isRemoteMessage CONSTANT)
@ -72,6 +73,8 @@ class ChatMessageCore : public QObject, public AbstractObject {
Q_PROPERTY(QString ownReaction READ getOwnReaction WRITE setOwnReaction NOTIFY messageReactionChanged)
Q_PROPERTY(QList<Reaction> reactions READ getReactions WRITE setReactions NOTIFY messageReactionChanged)
Q_PROPERTY(QList<QVariant> reactionsSingleton READ getReactionsSingleton NOTIFY singletonReactionMapChanged)
Q_PROPERTY(
QStringList reactionsSingletonAsStrings READ getReactionsSingletonAsStrings NOTIFY singletonReactionMapChanged)
Q_PROPERTY(bool isForward MEMBER mIsForward CONSTANT)
Q_PROPERTY(bool isReply MEMBER mIsReply CONSTANT)
Q_PROPERTY(bool hasFileContent MEMBER mHasFileContent CONSTANT)
@ -105,8 +108,10 @@ public:
QString getOwnReaction() const;
void setOwnReaction(const QString &reaction);
QString getTotalReactionsLabel() const;
QList<Reaction> getReactions() const;
QList<QVariant> getReactionsSingleton() const;
QStringList getReactionsSingletonAsStrings() const;
QList<QSharedPointer<ChatMessageContentCore>> getChatMessageContentList() const;
void removeOneReactionFromSingletonMap(const QString &body);
void resetReactionsSingleton();
@ -163,6 +168,7 @@ private:
bool mIsVoiceRecording = false;
bool mIsOutgoing = false;
QString mTotalReactionsLabel;
LinphoneEnums::ChatMessageState mMessageState;
QList<QSharedPointer<ChatMessageContentCore>> mChatMessageContentList;
// for voice recording creation message

View file

@ -0,0 +1,63 @@
/*
* Copyright (c) 2010-2024 Belledonne Communications SARL.
*
* This file is part of linphone-desktop
* (see https://www.linphone.org).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "EmojiList.hpp"
#include "core/App.hpp"
#include "core/chat/ChatCore.hpp"
#include "core/chat/message/content/ChatMessageContentGui.hpp"
#include <QMimeDatabase>
#include <QSharedPointer>
#include <linphone++/linphone.hh>
// =============================================================================
DEFINE_ABSTRACT_OBJECT(EmojiList)
QSharedPointer<EmojiList> EmojiList::create() {
auto model = QSharedPointer<EmojiList>(new EmojiList(), &QObject::deleteLater);
model->moveToThread(App::getInstance()->thread());
return model;
}
EmojiList::EmojiList(QObject *parent) : AbstractListProxy<Reaction>(parent) {
mustBeInMainThread(getClassName());
App::getInstance()->mEngine->setObjectOwnership(this, QQmlEngine::CppOwnership);
}
EmojiList::~EmojiList() {
mustBeInMainThread("~" + getClassName());
}
QList<Reaction> EmojiList::getReactions() {
return mList;
}
void EmojiList::setReactions(QList<Reaction> reactions) {
resetData(reactions);
}
QVariant EmojiList::data(const QModelIndex &index, int role) const {
int row = index.row();
if (!index.isValid() || row < 0 || row >= mList.count()) return QVariant();
if (role == Qt::DisplayRole) return QVariant::fromValue(mList.at(row));
return QVariant();
}

View file

@ -0,0 +1,52 @@
/*
* Copyright (c) 2010-2024 Belledonne Communications SARL.
*
* This file is part of linphone-desktop
* (see https://www.linphone.org).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef EMOJI_LIST_H_
#define EMOJI_LIST_H_
#include "core/chat/message/ChatMessageCore.hpp"
#include "core/proxy/AbstractListProxy.hpp"
#include "tool/AbstractObject.hpp"
#include "tool/thread/SafeConnection.hpp"
#include <QLocale>
// =============================================================================
class EmojiList : public AbstractListProxy<Reaction>, public AbstractObject {
Q_OBJECT
public:
static QSharedPointer<EmojiList> create();
EmojiList(QObject *parent = Q_NULLPTR);
~EmojiList();
QList<Reaction> getReactions();
void setReactions(QList<Reaction> reactions);
virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
signals:
void reactionsChanged();
private:
QList<Reaction> mReactions;
DECLARE_ABSTRACT_OBJECT
};
#endif

View file

@ -0,0 +1,65 @@
/*
* Copyright (c) 2010-2024 Belledonne Communications SARL.
*
* This file is part of linphone-desktop
* (see https://www.linphone.org).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "EmojiProxy.hpp"
#include "EmojiList.hpp"
#include "core/App.hpp"
// #include "core/chat/message/ChatMessageGui.hpp"
DEFINE_ABSTRACT_OBJECT(EmojiProxy)
EmojiProxy::EmojiProxy(QObject *parent) : LimitProxy(parent) {
mList = EmojiList::create();
setSourceModel(mList.get());
connect(mList.get(), &EmojiList::reactionsChanged, this, &EmojiProxy::reactionsChanged);
connect(this, &EmojiProxy::filterChanged, this, [this] { invalidate(); });
}
EmojiProxy::~EmojiProxy() {
}
QList<Reaction> EmojiProxy::getReactions() {
return mList->getReactions();
}
void EmojiProxy::setReactions(QList<Reaction> reactions) {
mList->setReactions(reactions);
}
QString EmojiProxy::getFilter() const {
return mFilter;
}
void EmojiProxy::setFilter(QString filter) {
if (mFilter != filter) {
mFilter = filter;
emit filterChanged();
}
}
bool EmojiProxy::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const {
auto emoji = mList->getAt(sourceRow);
return emoji.mBody.contains(mFilter);
}
bool EmojiProxy::lessThan(const QModelIndex &sourceLeft, const QModelIndex &sourceRight) const {
return true;
}

View file

@ -0,0 +1,62 @@
/*
* Copyright (c) 2010-2024 Belledonne Communications SARL.
*
* This file is part of linphone-desktop
* (see https://www.linphone.org).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef EMOJI_PROXY_H_
#define EMOJI_PROXY_H_
#include "core/chat/message/ChatMessageCore.hpp"
#include "core/emoji/EmojiModel.hpp"
#include "core/proxy/LimitProxy.hpp"
#include "tool/AbstractObject.hpp"
// =============================================================================
class EmojiList;
class EmojiProxy : public LimitProxy, public AbstractObject {
Q_OBJECT
Q_PROPERTY(QList<Reaction> reactions READ getReactions WRITE setReactions NOTIFY reactionsChanged)
Q_PROPERTY(QString filter READ getFilter WRITE setFilter NOTIFY filterChanged)
public:
EmojiProxy(QObject *parent = Q_NULLPTR);
~EmojiProxy();
QList<Reaction> getReactions();
void setReactions(QList<Reaction> reactions);
QString getFilter() const;
void setFilter(QString filter);
bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const override;
bool lessThan(const QModelIndex &sourceLeft, const QModelIndex &sourceRight) const override;
signals:
void reactionsChanged();
void filterChanged();
protected:
QString mFilter;
QSharedPointer<EmojiList> mList;
DECLARE_ABSTRACT_OBJECT
};
#endif

View file

@ -1802,31 +1802,31 @@
<context>
<name>ChatMessage</name>
<message>
<location filename="../../view/Control/Display/Chat/ChatMessage.qml" line="236"/>
<location filename="../../view/Control/Display/Chat/ChatMessage.qml" line="238"/>
<source>chat_message_copy_selection</source>
<extracomment>&quot;Copy selection&quot;</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../view/Control/Display/Chat/ChatMessage.qml" line="238"/>
<location filename="../../view/Control/Display/Chat/ChatMessage.qml" line="240"/>
<source>chat_message_copy</source>
<extracomment>&quot;Copy&quot;</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../view/Control/Display/Chat/ChatMessage.qml" line="246"/>
<location filename="../../view/Control/Display/Chat/ChatMessage.qml" line="248"/>
<source>chat_message_copied_to_clipboard_title</source>
<extracomment>Copied</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../view/Control/Display/Chat/ChatMessage.qml" line="248"/>
<location filename="../../view/Control/Display/Chat/ChatMessage.qml" line="250"/>
<source>chat_message_copied_to_clipboard_toast</source>
<extracomment>&quot;to clipboard&quot;</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../view/Control/Display/Chat/ChatMessage.qml" line="254"/>
<location filename="../../view/Control/Display/Chat/ChatMessage.qml" line="256"/>
<source>chat_message_delete</source>
<extracomment>&quot;Delete&quot;</extracomment>
<translation type="unfinished"></translation>
@ -1916,13 +1916,19 @@ Error</extracomment>
<context>
<name>ChatMessageCore</name>
<message>
<location filename="../../core/chat/message/ChatMessageCore.cpp" line="143"/>
<location filename="../../core/chat/message/ChatMessageCore.cpp" line="101"/>
<source>all_reactions_label</source>
<extracomment>&quot;Reactions&quot;: all reactions for one message label</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../core/chat/message/ChatMessageCore.cpp" line="145"/>
<source>info_toast_deleted_title</source>
<extracomment>Deleted</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../core/chat/message/ChatMessageCore.cpp" line="145"/>
<location filename="../../core/chat/message/ChatMessageCore.cpp" line="147"/>
<source>info_toast_deleted_message</source>
<extracomment>The message has been deleted</extracomment>
<translation type="unfinished"></translation>
@ -1975,20 +1981,20 @@ Error</extracomment>
<context>
<name>ChatMessagesListView</name>
<message>
<location filename="../../view/Control/Display/Chat/ChatMessagesListView.qml" line="89"/>
<location filename="../../view/Control/Display/Chat/ChatMessagesListView.qml" line="90"/>
<source>chat_message_list_encrypted_header_title</source>
<extracomment>End to end encrypted chat</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../view/Control/Display/Chat/ChatMessagesListView.qml" line="99"/>
<location filename="../../view/Control/Display/Chat/ChatMessagesListView.qml" line="100"/>
<source>chat_message_list_encrypted_header_message</source>
<extracomment>Les messages de cette conversation sont chiffrés de bout
en bout. Seul votre correspondant peut les déchiffrer.</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../view/Control/Display/Chat/ChatMessagesListView.qml" line="182"/>
<location filename="../../view/Control/Display/Chat/ChatMessagesListView.qml" line="184"/>
<source>chat_message_is_writing_info</source>
<extracomment>%1 is writing</extracomment>
<translation type="unfinished"></translation>
@ -4016,6 +4022,21 @@ Error</extracomment>
<translation>Wie Teilnehmer in Besprechungen angezeigt werden</translation>
</message>
</context>
<context>
<name>MessageReactionsInfos</name>
<message>
<location filename="../../view/Page/Layout/Chat/MessageReactionsInfos.qml" line="28"/>
<source>message_details_status title</source>
<extracomment>Message status</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../view/Page/Layout/Chat/MessageReactionsInfos.qml" line="91"/>
<source>click_to_delete_reaction_info</source>
<extracomment>Click to delete</extracomment>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>MultimediaSettings</name>
<message>
@ -4811,7 +4832,7 @@ Pour les activer dans un projet commercial, merci de nous contacter.</source>
<context>
<name>SelectedChatView</name>
<message>
<location filename="../../view/Page/Form/Chat/SelectedChatView.qml" line="33"/>
<location filename="../../view/Page/Form/Chat/SelectedChatView.qml" line="35"/>
<source>chat_view_group_call_toast_message</source>
<translation>Start a group call ?</translation>
</message>

View file

@ -1764,31 +1764,31 @@
<context>
<name>ChatMessage</name>
<message>
<location filename="../../view/Control/Display/Chat/ChatMessage.qml" line="236"/>
<location filename="../../view/Control/Display/Chat/ChatMessage.qml" line="238"/>
<source>chat_message_copy_selection</source>
<extracomment>&quot;Copy selection&quot;</extracomment>
<translation>Copy selection</translation>
</message>
<message>
<location filename="../../view/Control/Display/Chat/ChatMessage.qml" line="238"/>
<location filename="../../view/Control/Display/Chat/ChatMessage.qml" line="240"/>
<source>chat_message_copy</source>
<extracomment>&quot;Copy&quot;</extracomment>
<translation>Copy</translation>
</message>
<message>
<location filename="../../view/Control/Display/Chat/ChatMessage.qml" line="246"/>
<location filename="../../view/Control/Display/Chat/ChatMessage.qml" line="248"/>
<source>chat_message_copied_to_clipboard_title</source>
<extracomment>Copied</extracomment>
<translation>Copied</translation>
</message>
<message>
<location filename="../../view/Control/Display/Chat/ChatMessage.qml" line="248"/>
<location filename="../../view/Control/Display/Chat/ChatMessage.qml" line="250"/>
<source>chat_message_copied_to_clipboard_toast</source>
<extracomment>&quot;to clipboard&quot;</extracomment>
<translation>in clipboard</translation>
</message>
<message>
<location filename="../../view/Control/Display/Chat/ChatMessage.qml" line="254"/>
<location filename="../../view/Control/Display/Chat/ChatMessage.qml" line="256"/>
<source>chat_message_delete</source>
<extracomment>&quot;Delete&quot;</extracomment>
<translation>Delete</translation>
@ -1878,13 +1878,19 @@ Error</extracomment>
<context>
<name>ChatMessageCore</name>
<message>
<location filename="../../core/chat/message/ChatMessageCore.cpp" line="143"/>
<location filename="../../core/chat/message/ChatMessageCore.cpp" line="101"/>
<source>all_reactions_label</source>
<extracomment>&quot;Reactions&quot;: all reactions for one message label</extracomment>
<translation>Reactions</translation>
</message>
<message>
<location filename="../../core/chat/message/ChatMessageCore.cpp" line="145"/>
<source>info_toast_deleted_title</source>
<extracomment>Deleted</extracomment>
<translation>Deleted</translation>
</message>
<message>
<location filename="../../core/chat/message/ChatMessageCore.cpp" line="145"/>
<location filename="../../core/chat/message/ChatMessageCore.cpp" line="147"/>
<source>info_toast_deleted_message</source>
<extracomment>The message has been deleted</extracomment>
<translation>The message has been deleted</translation>
@ -1937,13 +1943,13 @@ Error</extracomment>
<context>
<name>ChatMessagesListView</name>
<message>
<location filename="../../view/Control/Display/Chat/ChatMessagesListView.qml" line="89"/>
<location filename="../../view/Control/Display/Chat/ChatMessagesListView.qml" line="90"/>
<source>chat_message_list_encrypted_header_title</source>
<extracomment>End to end encrypted chat</extracomment>
<translation>End to end encrypted chat</translation>
</message>
<message>
<location filename="../../view/Control/Display/Chat/ChatMessagesListView.qml" line="99"/>
<location filename="../../view/Control/Display/Chat/ChatMessagesListView.qml" line="100"/>
<source>chat_message_list_encrypted_header_message</source>
<extracomment>Les messages de cette conversation sont chiffrés de bout
en bout. Seul votre correspondant peut les déchiffrer.</extracomment>
@ -1951,7 +1957,7 @@ Error</extracomment>
Only your correspondent can decrypt them.</translation>
</message>
<message>
<location filename="../../view/Control/Display/Chat/ChatMessagesListView.qml" line="182"/>
<location filename="../../view/Control/Display/Chat/ChatMessagesListView.qml" line="184"/>
<source>chat_message_is_writing_info</source>
<extracomment>%1 is writing</extracomment>
<translation>%1 is writing</translation>
@ -3934,6 +3940,21 @@ Only your correspondent can decrypt them.</translation>
<translation>How participants are displayed in meetings</translation>
</message>
</context>
<context>
<name>MessageReactionsInfos</name>
<message>
<location filename="../../view/Page/Layout/Chat/MessageReactionsInfos.qml" line="28"/>
<source>message_details_status title</source>
<extracomment>Message status</extracomment>
<translation>Message status</translation>
</message>
<message>
<location filename="../../view/Page/Layout/Chat/MessageReactionsInfos.qml" line="91"/>
<source>click_to_delete_reaction_info</source>
<extracomment>Click to delete</extracomment>
<translation>Click to delete</translation>
</message>
</context>
<context>
<name>MultimediaSettings</name>
<message>
@ -4712,7 +4733,7 @@ To enable them in a commercial project, please contact us.</translation>
<context>
<name>SelectedChatView</name>
<message>
<location filename="../../view/Page/Form/Chat/SelectedChatView.qml" line="33"/>
<location filename="../../view/Page/Form/Chat/SelectedChatView.qml" line="35"/>
<source>chat_view_group_call_toast_message</source>
<translation>Start a group call ?</translation>
</message>

View file

@ -1764,31 +1764,31 @@
<context>
<name>ChatMessage</name>
<message>
<location filename="../../view/Control/Display/Chat/ChatMessage.qml" line="236"/>
<location filename="../../view/Control/Display/Chat/ChatMessage.qml" line="238"/>
<source>chat_message_copy_selection</source>
<extracomment>&quot;Copy selection&quot;</extracomment>
<translation>Copier la sélection</translation>
</message>
<message>
<location filename="../../view/Control/Display/Chat/ChatMessage.qml" line="238"/>
<location filename="../../view/Control/Display/Chat/ChatMessage.qml" line="240"/>
<source>chat_message_copy</source>
<extracomment>&quot;Copy&quot;</extracomment>
<translation>Copier</translation>
</message>
<message>
<location filename="../../view/Control/Display/Chat/ChatMessage.qml" line="246"/>
<location filename="../../view/Control/Display/Chat/ChatMessage.qml" line="248"/>
<source>chat_message_copied_to_clipboard_title</source>
<extracomment>Copied</extracomment>
<translation>Copié</translation>
</message>
<message>
<location filename="../../view/Control/Display/Chat/ChatMessage.qml" line="248"/>
<location filename="../../view/Control/Display/Chat/ChatMessage.qml" line="250"/>
<source>chat_message_copied_to_clipboard_toast</source>
<extracomment>&quot;to clipboard&quot;</extracomment>
<translation>dans le presse-papiers</translation>
</message>
<message>
<location filename="../../view/Control/Display/Chat/ChatMessage.qml" line="254"/>
<location filename="../../view/Control/Display/Chat/ChatMessage.qml" line="256"/>
<source>chat_message_delete</source>
<extracomment>&quot;Delete&quot;</extracomment>
<translation>Supprimer</translation>
@ -1878,13 +1878,19 @@ Error</extracomment>
<context>
<name>ChatMessageCore</name>
<message>
<location filename="../../core/chat/message/ChatMessageCore.cpp" line="143"/>
<location filename="../../core/chat/message/ChatMessageCore.cpp" line="101"/>
<source>all_reactions_label</source>
<extracomment>&quot;Reactions&quot;: all reactions for one message label</extracomment>
<translation>Réactions</translation>
</message>
<message>
<location filename="../../core/chat/message/ChatMessageCore.cpp" line="145"/>
<source>info_toast_deleted_title</source>
<extracomment>Deleted</extracomment>
<translation>Supprimé</translation>
</message>
<message>
<location filename="../../core/chat/message/ChatMessageCore.cpp" line="145"/>
<location filename="../../core/chat/message/ChatMessageCore.cpp" line="147"/>
<source>info_toast_deleted_message</source>
<extracomment>The message has been deleted</extracomment>
<translation>Le message a é supprimé</translation>
@ -1937,13 +1943,13 @@ Error</extracomment>
<context>
<name>ChatMessagesListView</name>
<message>
<location filename="../../view/Control/Display/Chat/ChatMessagesListView.qml" line="89"/>
<location filename="../../view/Control/Display/Chat/ChatMessagesListView.qml" line="90"/>
<source>chat_message_list_encrypted_header_title</source>
<extracomment>End to end encrypted chat</extracomment>
<translation>Conversation chiffrée de bout en bout</translation>
</message>
<message>
<location filename="../../view/Control/Display/Chat/ChatMessagesListView.qml" line="99"/>
<location filename="../../view/Control/Display/Chat/ChatMessagesListView.qml" line="100"/>
<source>chat_message_list_encrypted_header_message</source>
<extracomment>Les messages de cette conversation sont chiffrés de bout
en bout. Seul votre correspondant peut les déchiffrer.</extracomment>
@ -1951,7 +1957,7 @@ Error</extracomment>
en bout. Seul votre correspondant peut les déchiffrer.</translation>
</message>
<message>
<location filename="../../view/Control/Display/Chat/ChatMessagesListView.qml" line="182"/>
<location filename="../../view/Control/Display/Chat/ChatMessagesListView.qml" line="184"/>
<source>chat_message_is_writing_info</source>
<extracomment>%1 is writing</extracomment>
<translation>%1 est en train d&apos;écrire</translation>
@ -3934,6 +3940,21 @@ en bout. Seul votre correspondant peut les déchiffrer.</translation>
<translation>Le mode daffichage des participants en réunions</translation>
</message>
</context>
<context>
<name>MessageReactionsInfos</name>
<message>
<location filename="../../view/Page/Layout/Chat/MessageReactionsInfos.qml" line="28"/>
<source>message_details_status title</source>
<extracomment>Message status</extracomment>
<translation>Statut du message</translation>
</message>
<message>
<location filename="../../view/Page/Layout/Chat/MessageReactionsInfos.qml" line="91"/>
<source>click_to_delete_reaction_info</source>
<extracomment>Click to delete</extracomment>
<translation>Appuyez pour supprimer</translation>
</message>
</context>
<context>
<name>MultimediaSettings</name>
<message>
@ -4712,7 +4733,7 @@ Pour les activer dans un projet commercial, merci de nous contacter.</translatio
<context>
<name>SelectedChatView</name>
<message>
<location filename="../../view/Page/Form/Chat/SelectedChatView.qml" line="33"/>
<location filename="../../view/Page/Form/Chat/SelectedChatView.qml" line="35"/>
<source>chat_view_group_call_toast_message</source>
<translation>Démarrer un appel de groupe ?</translation>
</message>

View file

@ -154,6 +154,7 @@ list(APPEND _LINPHONEAPP_QML_FILES
view/Page/Layout/Settings/NetworkSettingsLayout.qml
view/Page/Layout/Settings/AdvancedSettingsLayout.qml
view/Page/Layout/Chat/GroupConversationInfos.qml
view/Page/Layout/Chat/MessageReactionsInfos.qml
view/Page/Layout/Chat/OneOneConversationInfos.qml
view/Page/Layout/Chat/ChatInfoActionsGroup.qml
view/Page/Layout/Chat/GroupChatInfoParticipants.qml

View file

@ -42,6 +42,7 @@ Control.Button {
icon.source: style?.iconSource || ""
MouseArea {
id: mouseArea
z: stacklayout.z + 1
anchors.fill: parent
hoverEnabled: true
cursorShape: containsMouse ? Qt.PointingHandCursor : Qt.ArrowCursor

View file

@ -88,7 +88,6 @@ Control.TabBar {
width: Math.min(implicitWidth, mainItem.width / mainItem.model.length)
font.weight: mainItem.textWeight
color: mainItem.currentIndex === index ? DefaultStyle.main2_600 : DefaultStyle.main2_400
font.family: DefaultStyle.defaultFont
font.pixelSize: mainItem.pixelSize
elide: Text.ElideRight
maximumLineCount: 1

View file

@ -263,6 +263,7 @@ ListView {
font {
pixelSize: Typography.p3.pixelSize
weight: Typography.p3.weight
italic: modelData.core.sendingText !== ""
}
//: %1 is writing
text: modelData.core.composingName !== ""

View file

@ -28,6 +28,7 @@ Control.Control {
signal messageDeletionRequested()
signal isFileHoveringChanged(bool isFileHovering)
signal showReactionsForMessageRequested()
background: Item {
anchors.fill: parent
@ -174,6 +175,7 @@ Control.Control {
property: "anchors.right"
value: chatBubble.right
}
onClicked: mainItem.showReactionsForMessageRequested()
anchors.topMargin: Math.round(-6 * DefaultStyle.dp)
topPadding: Math.round(8 * DefaultStyle.dp)
bottomPadding: Math.round(8 * DefaultStyle.dp)

View file

@ -14,6 +14,7 @@ ListView {
spacing: Math.round(4 * DefaultStyle.dp)
property ChatGui chat
property color backgroundColor
signal showReactionsForMessageRequested(ChatMessageGui chatMessage)
Component.onCompleted: {
var index = eventLogProxy.findFirstUnreadIndex()
@ -133,6 +134,7 @@ ListView {
: undefined
onMessageDeletionRequested: modelData.core.lDelete()
onShowReactionsForMessageRequested: mainItem.showReactionsForMessageRequested(modelData)
}
}

View file

@ -34,7 +34,7 @@ import 'qrc:/qt/qml/Linphone/view/Control/Tool/Helper/utils.js' as Utils
ColumnLayout {
id: mainItem
property var editor
property EmojiModel model: EmojiModel{
property EmojiModel model: EmojiModel {
id: emojiModel
iconsPath: "image://emoji/emojiSvgs/"
iconsType: '.svg'

View file

@ -114,8 +114,13 @@ Loader{
anchors.right: parent.right
anchors.rightMargin: stackView.width / 15
z: 1
source: account ? (account.core?.registrationState != LinphoneEnums.RegistrationState.Ok ? account.core?.registrationStateIcon : account.core?.presenceIcon)
: (contact ? contact.core?.presenceIcon : "")
source: account
? (account.core?.registrationState !== LinphoneEnums.RegistrationState.Ok
? account.core?.registrationStateIcon
: account.core?.presenceIcon)
: (contact
? contact.core?.presenceIcon
: "")
}
}

View file

@ -12,6 +12,8 @@ import 'qrc:/qt/qml/Linphone/view/Style/buttonStyle.js' as ButtonStyle
RowLayout {
id: mainItem
property ChatGui chat
// used to show chat message reactions in details panel
property ChatMessageGui chatMessage
property var contactObj: chat ? UtilsCpp.findFriendByAddress(mainItem.chat.core.peerAddress) : null
property var contact: contactObj?.value || null
property CallGui call
@ -112,12 +114,14 @@ RowLayout {
onPressed: mainItem.oneOneCall(true)
}
BigButton {
id: detailsPanelButton
style: ButtonStyle.noBackground
checkable: true
checkedImageColor: DefaultStyle.main1_500_main
icon.source: AppIcons.info
checked: detailsPanel.visible
onCheckedChanged: {
detailsPanel.visible = !detailsPanel.visible
detailsPanel.visible = checked
}
}
}
@ -147,6 +151,11 @@ RowLayout {
anchors.leftMargin: Math.round(18 * DefaultStyle.dp)
anchors.rightMargin: Math.round(18 * DefaultStyle.dp)
Control.ScrollBar.vertical: scrollbar
onShowReactionsForMessageRequested: (chatMessage) => {
mainItem.chatMessage = chatMessage
contentLoader.showingMessageReactions = true
detailsPanel.visible = true
}
Popup {
id: emojiPickerPopup
@ -313,6 +322,7 @@ RowLayout {
visible: false
Layout.fillHeight: true
Layout.preferredWidth: Math.round(387 * DefaultStyle.dp)
onVisibleChanged: if(!visible) contentLoader.showingMessageReactions = false
background: Rectangle {
color: DefaultStyle.grey_0
@ -321,9 +331,14 @@ RowLayout {
contentItem: Loader {
id: contentLoader
property bool showingMessageReactions: false
anchors.top: parent.top
anchors.topMargin: Math.round(39 * DefaultStyle.dp)
sourceComponent: mainItem.chat.core.isGroupChat ? groupInfoComponent : oneToOneInfoComponent
sourceComponent: showingMessageReactions
? messageReactionsComponent
: mainItem.chat.core.isGroupChat
? groupInfoComponent
: oneToOneInfoComponent
active: detailsPanel.visible
onLoaded: {
if (contentLoader.item) {
@ -345,6 +360,16 @@ RowLayout {
chatGui: mainItem.chat
}
}
}
}
Component {
id: messageReactionsComponent
MessageReactionsInfos {
chatMessageGui: mainItem.chatMessage
onGoBackRequested: {
detailsPanel.visible = false
mainItem.chatMessage = null
}
}
}
}
}

View file

@ -0,0 +1,118 @@
import QtCore
import QtQuick
import QtQuick.Controls.Basic as Control
import QtQuick.Dialogs
import QtQuick.Effects
import QtQuick.Layouts
import Linphone
import UtilsCpp
import SettingsCpp
import 'qrc:/qt/qml/Linphone/view/Style/buttonStyle.js' as ButtonStyle
ColumnLayout {
id: mainItem
property ChatMessageGui chatMessageGui
property var parentView
spacing: Math.round(25 * DefaultStyle.dp)
signal goBackRequested()
RowLayout {
BigButton {
icon.source: AppIcons.leftArrow
style: ButtonStyle.noBackground
onClicked: mainItem.goBackRequested()
}
Text {
//: Message status
text: qsTr("message_details_status title")
font {
pixelSize: Typography.h4.pixelSize
weight: Typography.h4.weight
}
}
}
ColumnLayout {
spacing: Math.round(11 * DefaultStyle.dp)
Layout.leftMargin: Math.round(16 * DefaultStyle.dp)
Layout.rightMargin: Math.round(16 * DefaultStyle.dp)
TabBar {
id: tabbar
Layout.fillWidth: true
model: mainItem.chatMessageGui ? mainItem.chatMessageGui.core.reactionsSingletonAsStrings : []
pixelSize: Typography.h3m.pixelSize
textWeight: Typography.h3m.weight
}
ListView {
id: reactionsList
Layout.fillWidth: true
Layout.fillHeight: true
spacing: Math.round(11 * DefaultStyle.dp)
model: EmojiProxy {
reactions: mainItem.chatMessageGui ? mainItem.chatMessageGui.core.reactions : []
// First index of reactionsSingletonAsStrings list is all reactions combined which does not appear
// in reactionsSingleton list
filter: tabbar.currentIndex >=1 && mainItem.chatMessageGui && mainItem.chatMessageGui.core.reactionsSingleton[tabbar.currentIndex-1].body || ""
}
delegate: Item {
width: reactionsList.width
height: delegateIn.implicitHeight
property var contactObj: modelData ? UtilsCpp.findFriendByAddress(modelData.address) : null
property var nameObj: modelData ? UtilsCpp.getDisplayName(modelData.address) : null
property var isMeObj: modelData ? UtilsCpp.isMe(modelData.address) : null
MouseArea {
anchors.fill: parent
enabled: isMeObj && isMeObj.value
cursorShape: containsMouse ? Qt.PointingHandCursor : Qt.ArrowCursor
hoverEnabled: true
onClicked: mainItem.chatMessageGui.core.lRemoveReaction()
}
RowLayout {
id: delegateIn
anchors.fill: parent
spacing: Math.round(16 * DefaultStyle.dp)
Avatar {
Layout.alignment: Qt.AlignHCenter
contact: contactObj?.value || null
displayNameVal: contact
? ""
: nameObj
? nameObj.value
: ""
Layout.preferredWidth: Math.round(45 * DefaultStyle.dp)
Layout.preferredHeight: Math.round(45 * DefaultStyle.dp)
}
ColumnLayout {
Text {
text: nameObj?.value || ""
font {
pixelSize: Typography.p1.pixelSize
weight: Typography.p1.weight
}
}
Text {
visible: isMeObj && isMeObj.value
//: Click to delete
text: qsTr("click_to_delete_reaction_info")
color: DefaultStyle.main2_400
font {
pixelSize: Typography.p3.pixelSize
weight: Typography.p3.weight
}
}
}
Item{Layout.fillWidth: true}
Text {
text: UtilsCpp.encodeEmojiToQmlRichFormat(modelData.body)
font {
pixelSize: Typography.h3.pixelSize
weight: Typography.p3.weight
}
}
}
}
}
}
}

View file

@ -13,7 +13,7 @@ ColumnLayout {
id: mainItem
property ChatGui chatGui
property var chatCore: chatGui.core
property var contactObj: chat ? UtilsCpp.findFriendByAddress(mainItem.chatCore.peerAddress) : null
property var contactObj: chatGui ? UtilsCpp.findFriendByAddress(mainItem.chatCore.peerAddress) : null
property var parentView
spacing: 0
@ -42,7 +42,7 @@ ColumnLayout {
}
Text {
visible: contactObj?.value
visible: contactObj && contactObj.value || false
font: Typography.p3
color: contactObj?.value != null ? contactObj?.value.core.presenceColor : "transparent"
text: contactObj?.value != null ? contactObj?.value.core.presenceStatus : ""

View file

@ -9,6 +9,13 @@ QtObject {
pixelSize: Math.round(16 * DefaultStyle.dp),
weight: Math.min(Math.round(800 * DefaultStyle.dp), 1000)
})
// Title/H3M - Bloc title
property font h3m: Qt.font( {
family: DefaultStyle.defaultFont,
pixelSize: Math.round(16 * DefaultStyle.dp),
weight: Math.min(Math.round(800 * DefaultStyle.dp), 1000)
})
// Title/H3 - Bloc title
property font h3: Qt.font( {