mirror of
https://gitlab.linphone.org/BC/public/linphone-desktop.git
synced 2026-05-03 22:56:49 +00:00
Fix reactions synchronizations.
Generic reactions (support any emojies) but display in priority a fix list (defined in Constants). Clean old codes and make a ChatReactions UI.
This commit is contained in:
parent
267d70535d
commit
f496600004
14 changed files with 170 additions and 225 deletions
|
|
@ -346,6 +346,7 @@
|
|||
<file>ui/modules/Linphone/Chat/ChatFilePreview.qml</file>
|
||||
<file>ui/modules/Linphone/Chat/ChatForwardMessage.qml</file>
|
||||
<file>ui/modules/Linphone/Chat/ChatMessagePreview.qml</file>
|
||||
<file>ui/modules/Linphone/Chat/ChatReactions.qml</file>
|
||||
<file>ui/modules/Linphone/Chat/ChatReactionsDetails.qml</file>
|
||||
<file>ui/modules/Linphone/Chat/ChatReplyMessage.qml</file>
|
||||
<file>ui/modules/Linphone/Chat/ChatReplyPreview.qml</file>
|
||||
|
|
|
|||
|
|
@ -262,7 +262,7 @@ void ChatMessageModel::sendChatReaction(const QString& reaction){
|
|||
return; // TODO : remove return when sending empty emoji will be supported.
|
||||
}
|
||||
chatReaction->send();
|
||||
mChatReactionListModel->updateChatReaction(chatReaction);
|
||||
emit newMessageReaction(mChatMessage, chatReaction);
|
||||
}
|
||||
|
||||
void ChatMessageModel::deleteEvent(){
|
||||
|
|
@ -327,7 +327,7 @@ void ChatMessageModel::onMsgStateChanged (const std::shared_ptr<linphone::ChatMe
|
|||
}
|
||||
|
||||
void ChatMessageModel::onNewMessageReaction(const std::shared_ptr<linphone::ChatMessage> & message, const std::shared_ptr<const linphone::ChatMessageReaction> & reaction){
|
||||
mChatReactionListModel->updateChatReaction(reaction);
|
||||
emit newMessageReaction(message, reaction);
|
||||
}
|
||||
|
||||
void ChatMessageModel::onParticipantImdnStateChanged(const std::shared_ptr<linphone::ChatMessage> & message, const std::shared_ptr<const linphone::ParticipantImdnState> & state){
|
||||
|
|
|
|||
|
|
@ -146,6 +146,7 @@ signals:
|
|||
void fileContentChanged();
|
||||
void remove(ChatMessageModel* model);
|
||||
|
||||
void newMessageReaction(const std::shared_ptr<linphone::ChatMessage> & message, const std::shared_ptr<const linphone::ChatMessageReaction> & reaction);
|
||||
|
||||
private:
|
||||
void connectTo(ChatMessageListener * listener);
|
||||
|
|
|
|||
|
|
@ -27,11 +27,15 @@
|
|||
// =============================================================================
|
||||
|
||||
ChatReactionListModel::ChatReactionListModel (ChatMessageModel * message, QObject* parent) : ProxyAbstractListModel<QVariantMap>(parent) {
|
||||
mParent = message;
|
||||
setChatMessageModel(message);
|
||||
}
|
||||
|
||||
void ChatReactionListModel::setChatMessageModel(ChatMessageModel * message) {
|
||||
if(mParent)
|
||||
disconnect(message, &ChatMessageModel::newMessageReaction, this, &ChatReactionListModel::onNewMessageReaction);
|
||||
mParent = message;
|
||||
if(mParent)
|
||||
connect(message, &ChatMessageModel::newMessageReaction, this, &ChatReactionListModel::onNewMessageReaction);
|
||||
if(message){
|
||||
auto reactions = message->getChatMessage()->getReactions();
|
||||
mReactions.clear();
|
||||
|
|
@ -45,6 +49,7 @@ void ChatReactionListModel::setChatMessageModel(ChatMessageModel * message) {
|
|||
}
|
||||
}
|
||||
updateList();
|
||||
emit bodiesChanged();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -69,41 +74,18 @@ QSharedPointer<ChatReactionModel> ChatReactionListModel::add(std::shared_ptr<lin
|
|||
}
|
||||
|
||||
|
||||
void ChatReactionListModel::remove(ChatReactionModel * model){/*
|
||||
int count = 0;
|
||||
for(auto it = mList.begin() ; it != mList.end() ; ++count, ++it) {
|
||||
if( it->get() == model) {
|
||||
removeRow(count, QModelIndex());
|
||||
return;
|
||||
}
|
||||
}*/
|
||||
void ChatReactionListModel::remove(ChatReactionModel * model){
|
||||
}
|
||||
|
||||
void ChatReactionListModel::clear(){
|
||||
resetData();
|
||||
}
|
||||
|
||||
/*
|
||||
QSharedPointer<ChatReactionModel> ChatReactionListModel::getChatReactionModel(const std::shared_ptr<const linphone::ChatMessageReaction>& reaction){
|
||||
for(auto item : mList){
|
||||
auto c = item.objectCast<ChatReactionModel>();
|
||||
if(c->get() == content)
|
||||
return c;
|
||||
}
|
||||
if(content->isFileTransfer() || content->isFile() || content->isFileEncrypted()){
|
||||
for(auto item : mList){// Content object can be different for file (like while data transfer)
|
||||
auto c = item.objectCast<ContentModel>();
|
||||
if(c->getContent()->getFilePath() == content->getFilePath())
|
||||
return c;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
*/
|
||||
void ChatReactionListModel::updateChatReaction(const std::shared_ptr<const linphone::ChatMessageReaction>& reaction) {
|
||||
QString address = Utils::coreStringToAppString(reaction->getFromAddress()->asStringUriOnly());
|
||||
auto itReaction = mReactions.find(address);
|
||||
int oldReactionCount = mReactions.size();
|
||||
auto oldBodies = getBodies();
|
||||
if( itReaction == mReactions.end()) {// New
|
||||
auto reactionModel = QSharedPointer<ChatReactionModel>::create(reaction);
|
||||
auto body = reactionModel->getBody();
|
||||
|
|
@ -127,6 +109,7 @@ void ChatReactionListModel::updateChatReaction(const std::shared_ptr<const linph
|
|||
updateList();
|
||||
if(oldReactionCount != mReactions.size())
|
||||
emit chatReactionCountChanged();
|
||||
emit bodiesChanged();
|
||||
}
|
||||
void ChatReactionListModel::updateList(){
|
||||
QList<QVariantMap> data;
|
||||
|
|
@ -177,54 +160,19 @@ void ChatReactionListModel::setGroupBy(ChatReactionListModel::GROUP_BY_TYPE mode
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
|
||||
void ContentListModel::updateContent(std::shared_ptr<linphone::Content> oldContent, std::shared_ptr<linphone::Content> newContent){
|
||||
int row = 0;
|
||||
for(auto content = mList.begin() ; content != mList.end() ; ++content, ++row){
|
||||
auto contentModel = content->objectCast<ContentModel>();
|
||||
if( contentModel->getContent() == oldContent){
|
||||
mList.replace(row, QSharedPointer<ContentModel>::create(newContent, contentModel->getChatMessageModel()));
|
||||
emit dataChanged(index(row,0), index(row,0));
|
||||
return;
|
||||
QStringList ChatReactionListModel::getBodies() const {
|
||||
auto bodies = mBodies.keys();
|
||||
auto reactions = Constants::getReactionsList();
|
||||
std::sort(bodies.begin(), bodies.end(), [&](const QString& a, const QString& b){
|
||||
for(auto reaction : reactions){
|
||||
if( a == reaction) return true;
|
||||
if( b == reaction) return false;
|
||||
}
|
||||
}
|
||||
return a < b;
|
||||
});
|
||||
return bodies;
|
||||
}
|
||||
|
||||
void ContentListModel::updateContents(ChatMessageModel * messageModel){
|
||||
std::list<std::shared_ptr<linphone::Content>> contents = messageModel->getChatMessage()->getContents() ;
|
||||
int count = 0;
|
||||
beginResetModel();
|
||||
for(auto content : contents){
|
||||
if( count >= mList.size()){// New content
|
||||
mList.insert(count, QSharedPointer<ContentModel>::create(content, messageModel));
|
||||
}else if(mList.at(count).objectCast<ContentModel>()->getContent() != content){ // This content is not at its place
|
||||
int c = count + 1;
|
||||
while( c < mList.size() && mList.at(c).objectCast<ContentModel>()->getContent() != content)
|
||||
++c;
|
||||
if( c < mList.size()){// Found => swap position
|
||||
#if QT_VERSION < QT_VERSION_CHECK(5, 13, 0)
|
||||
mList.swap(count, c);
|
||||
#else
|
||||
mList.swapItemsAt(count, c);
|
||||
#endif
|
||||
}else{// content is new
|
||||
mList.insert(count, QSharedPointer<ContentModel>::create(content, messageModel));
|
||||
}
|
||||
}
|
||||
++count;
|
||||
}
|
||||
if(count < mList.size())// Remove all old contents
|
||||
mList.erase(mList.begin()+count, mList.end());
|
||||
endResetModel();
|
||||
void ChatReactionListModel::onNewMessageReaction(const std::shared_ptr<linphone::ChatMessage> & message, const std::shared_ptr<const linphone::ChatMessageReaction> & reaction){
|
||||
updateChatReaction(reaction);
|
||||
}
|
||||
|
||||
void ContentListModel::updateAllTransferData(){
|
||||
emit updateTransferDataRequested();
|
||||
}
|
||||
|
||||
void ContentListModel::downloaded(){
|
||||
for(auto content : mList)
|
||||
content.objectCast<ContentModel>()->createThumbnail();
|
||||
}*/
|
||||
|
|
|
|||
|
|
@ -52,6 +52,8 @@ public:
|
|||
ChatReactionListModel::GROUP_BY_TYPE getGroupBy() const;
|
||||
void setGroupBy(ChatReactionListModel::GROUP_BY_TYPE mode);
|
||||
|
||||
QStringList getBodies() const;
|
||||
|
||||
//QSharedPointer<ChatReactionModel> getChatReactionModel(const std::shared_ptr<const linphone::ChatMessageReaction>& reaction);
|
||||
|
||||
bool exists(std::shared_ptr<linphone::ChatMessageReaction> reaction) const;
|
||||
|
|
@ -61,13 +63,16 @@ public:
|
|||
void updateChatReaction(ChatMessageModel * messageModel);
|
||||
|
||||
void updateList();
|
||||
|
||||
void onNewMessageReaction(const std::shared_ptr<linphone::ChatMessage> & message, const std::shared_ptr<const linphone::ChatMessageReaction> & reaction);
|
||||
signals:
|
||||
void chatReactionsChanged();
|
||||
void chatReactionCountChanged();
|
||||
void groupByChanged();
|
||||
void bodiesChanged();
|
||||
|
||||
private:
|
||||
ChatMessageModel * mParent;
|
||||
ChatMessageModel * mParent = nullptr;
|
||||
QMap<QString, QSharedPointer<ChatReactionModel>> mReactions;
|
||||
QMap<QString, QVector<QSharedPointer<ChatReactionModel>>> mBodies;
|
||||
GROUP_BY_TYPE mGroupBy = EMOJIES;
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ ChatReactionProxyModel::ChatReactionProxyModel (QObject * parent) : SortFilterPr
|
|||
mContents = QSharedPointer<ChatReactionListModel>::create();
|
||||
connect(mContents.get(), &ChatReactionListModel::chatReactionCountChanged, this, &ChatReactionProxyModel::chatReactionCountChanged);
|
||||
connect(mContents.get(), &ChatReactionListModel::groupByChanged, this, &ChatReactionProxyModel::groupByChanged);
|
||||
connect(mContents.get(), &ChatReactionListModel::bodiesChanged, this, &ChatReactionProxyModel::bodiesChanged);
|
||||
setSourceModel(mContents.get());
|
||||
sort(0);
|
||||
}
|
||||
|
|
@ -90,13 +91,13 @@ void ChatReactionProxyModel::setFilter(const QString& filter) {
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
void ChatReactionProxyModel::setContentListModel(ContentListModel * model){
|
||||
setSourceModel(model);
|
||||
sort(0);
|
||||
emit chatMessageModelChanged();
|
||||
QStringList ChatReactionProxyModel::getBodies() const {
|
||||
auto model = qobject_cast<ChatReactionListModel*>(sourceModel());
|
||||
if(model) {
|
||||
return model->getBodies();
|
||||
}else
|
||||
return QStringList();
|
||||
}
|
||||
*/
|
||||
|
||||
bool ChatReactionProxyModel::filterAcceptsRow (
|
||||
int sourceRow,
|
||||
|
|
@ -122,46 +123,8 @@ bool ChatReactionProxyModel::filterAcceptsRow (
|
|||
|
||||
/*
|
||||
bool ChatReactionProxyModel::lessThan (const QModelIndex &left, const QModelIndex &right) const {
|
||||
const ContentModel *contentA = sourceModel()->data(left).value<ContentModel *>();
|
||||
const ContentModel *contentB = sourceModel()->data(right).value<ContentModel *>();
|
||||
bool aIsForward = contentA->getChatMessageModel() && contentA->getChatMessageModel()->isForward();
|
||||
bool aIsReply = contentA->getChatMessageModel() && contentA->getChatMessageModel()->isReply();
|
||||
bool aIsVoiceRecording = contentA->isVoiceRecording();
|
||||
bool aIsFile = contentA->isFile() || contentA->isFileEncrypted() || contentA->isFileTransfer();
|
||||
bool aIsText = contentA->isText() ;
|
||||
bool bIsForward = contentB->getChatMessageModel() && contentB->getChatMessageModel()->isForward();
|
||||
bool bIsReply = contentB->getChatMessageModel() && contentB->getChatMessageModel()->isReply();
|
||||
bool bIsVoiceRecording = contentB->isVoiceRecording();
|
||||
bool bIsFile = contentB->isFile() || contentB->isFileEncrypted() || contentB->isFileTransfer();
|
||||
bool bIsText = contentB->isText() ;
|
||||
auto a = sourceModel()->data(left).value<QVariantMap>();
|
||||
auto b = sourceModel()->data(right).value<QVariantMap>();
|
||||
|
||||
return !bIsForward && (aIsForward
|
||||
|| !bIsReply && (aIsReply
|
||||
|| !bIsVoiceRecording && (aIsVoiceRecording
|
||||
|| !bIsFile && (aIsFile
|
||||
|| aIsText && !bIsText
|
||||
)
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
*/
|
||||
/*
|
||||
void ChatReactionProxyModel::remove(ContentModel * model){
|
||||
qobject_cast<ContentListModel*>(sourceModel())->remove(model);
|
||||
}
|
||||
|
||||
void ChatReactionProxyModel::clear(){
|
||||
qobject_cast<ContentListModel*>(sourceModel())->clear();
|
||||
}
|
||||
|
||||
ContentProxyModel::FilterContentType ChatReactionProxyModel::getFilter() const{
|
||||
return mFilter;
|
||||
}
|
||||
void ChatReactionProxyModel::setFilter(const FilterContentType& contentType){
|
||||
if(contentType != mFilter){
|
||||
mFilter = contentType;
|
||||
emit filterChanged();
|
||||
invalidate();
|
||||
}
|
||||
}*/
|
||||
*/
|
||||
|
|
@ -36,19 +36,8 @@ public:
|
|||
Q_PROPERTY(int reactionCount READ getChatReactionCount NOTIFY chatReactionCountChanged)
|
||||
Q_PROPERTY(ChatReactionListModel::GROUP_BY_TYPE groupBy READ getGroupBy WRITE setGroupBy NOTIFY groupByChanged)
|
||||
Q_PROPERTY(QString filter READ getFilter WRITE setFilter NOTIFY filterChanged)
|
||||
/*
|
||||
Q_PROPERTY(FilterContentType filter READ getFilter WRITE setFilter NOTIFY filterChanged)
|
||||
Q_PROPERTY(QStringList bodies READ getBodies NOTIFY bodiesChanged)
|
||||
|
||||
enum FilterContentType {
|
||||
All,
|
||||
File,
|
||||
Text,
|
||||
Voice,
|
||||
Conference,
|
||||
Unknown
|
||||
};
|
||||
Q_ENUM(FilterContentType)
|
||||
*/
|
||||
ChatMessageModel * getChatMessageModel() const;
|
||||
void setChatMessageModel(ChatMessageModel * message);
|
||||
Q_INVOKABLE void setChatMessageModel(ChatMessageModel * message, ChatReactionListModel::GROUP_BY_TYPE groupByMode);
|
||||
|
|
@ -61,16 +50,15 @@ public:
|
|||
|
||||
QString getFilter() const;
|
||||
void setFilter(const QString& filter);
|
||||
//Q_INVOKABLE void setContentListModel(ContentListModel * model);
|
||||
//Q_INVOKABLE void addFile(const QString& path);
|
||||
//Q_INVOKABLE void remove(ContentModel * model);
|
||||
//Q_INVOKABLE void clear();
|
||||
|
||||
QStringList getBodies() const;
|
||||
|
||||
signals:
|
||||
void chatMessageModelChanged();
|
||||
void chatReactionCountChanged();
|
||||
void groupByChanged();
|
||||
void filterChanged();
|
||||
void bodiesChanged();
|
||||
|
||||
|
||||
protected:
|
||||
|
|
|
|||
|
|
@ -26,7 +26,9 @@ constexpr char Constants::DefaultFont[];
|
|||
constexpr int Constants::DefaultFontPointSize;
|
||||
constexpr char Constants::DefaultEmojiFont[];
|
||||
constexpr int Constants::DefaultEmojiFontPointSize;
|
||||
|
||||
QStringList Constants::getReactionsList(){
|
||||
return {"❤️", "👍", "😂", "😮", "😢"};
|
||||
}
|
||||
constexpr char Constants::QtDomain[];
|
||||
constexpr size_t Constants::MaxLogsCollectionSize;
|
||||
constexpr char Constants::SrcPattern[];
|
||||
|
|
|
|||
|
|
@ -45,6 +45,7 @@ public:
|
|||
static constexpr char DefaultEmojiFont[] = "Noto Color Emoji";
|
||||
#endif
|
||||
static constexpr int DefaultEmojiFontPointSize = 10;
|
||||
static QStringList getReactionsList();
|
||||
|
||||
static constexpr size_t MaxLogsCollectionSize = 10485760*5; // 50MB.
|
||||
|
||||
|
|
@ -93,6 +94,7 @@ public:
|
|||
Q_PROPERTY(QString ContactUrl MEMBER ContactUrl CONSTANT)
|
||||
Q_PROPERTY(QString TranslationUrl MEMBER TranslationUrl CONSTANT)
|
||||
Q_PROPERTY(int maxMosaicParticipants MEMBER MaxMosaicParticipants CONSTANT)
|
||||
Q_PROPERTY(QStringList reactionsList READ getReactionsList CONSTANT)
|
||||
|
||||
// For Webviews
|
||||
static constexpr char DefaultAssistantRegistrationUrl[] = "https://subscribe.linphone.org/register";
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import Linphone.Styles 1.0
|
|||
import TextToSpeech 1.0
|
||||
import Utils 1.0
|
||||
import Units 1.0
|
||||
import ConstantsCpp 1.0
|
||||
import UtilsCpp 1.0
|
||||
import LinphoneEnums 1.0
|
||||
|
||||
|
|
@ -53,7 +54,7 @@ Item {
|
|||
Layout.fillWidth: true
|
||||
spacing:0
|
||||
Repeater{
|
||||
model: ['❤️','👍','😂','😮','😢']
|
||||
model: ConstantsCpp.reactionsList
|
||||
delegate: Text{
|
||||
Layout.fillWidth: true
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
|
|
|
|||
72
linphone-app/ui/modules/Linphone/Chat/ChatReactions.qml
Normal file
72
linphone-app/ui/modules/Linphone/Chat/ChatReactions.qml
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
import QtQuick 2.7
|
||||
import QtQuick.Layouts 1.3
|
||||
import QtQml.Models 2.15
|
||||
|
||||
import Common 1.0
|
||||
import Linphone 1.0
|
||||
|
||||
import Units 1.0
|
||||
|
||||
// =============================================================================
|
||||
|
||||
Rectangle{
|
||||
id: mainItem
|
||||
|
||||
property ChatReactionProxyModel model
|
||||
property var modelData
|
||||
|
||||
signal reactionsClicked()
|
||||
|
||||
height: visible ? reactionList.height +10 : 0
|
||||
width: visible ? reactionLayout.width + 10 : 0
|
||||
|
||||
visible: reactionList.count > 0
|
||||
property font customFont : SettingsModel.textMessageFont
|
||||
property font customEmojiFont : SettingsModel.emojiFont
|
||||
|
||||
RowLayout{
|
||||
id: reactionLayout
|
||||
anchors.centerIn: parent
|
||||
ListView{
|
||||
id: reactionList
|
||||
Layout.preferredWidth: contentItem.childrenRect.width
|
||||
Layout.preferredHeight: reactionMetrics.height
|
||||
TextMetrics{
|
||||
id: reactionMetrics
|
||||
text: '😮'
|
||||
font.family: mainItem.customEmojiFont.family
|
||||
font.pointSize: Units.dp * mainItem.customEmojiFont.pointSize * 2
|
||||
}
|
||||
orientation: ListView.Horizontal
|
||||
model: mainItem.model
|
||||
spacing: 10
|
||||
delegate:
|
||||
Text{
|
||||
width: reactionMetrics.width
|
||||
height: reactionList.height
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
font.family: mainItem.customEmojiFont.family
|
||||
font.pointSize: Units.dp * mainItem.customEmojiFont.pointSize * 2
|
||||
text: $modelData.body || ''
|
||||
}
|
||||
}
|
||||
|
||||
Text{
|
||||
Layout.preferredWidth: contentWidth
|
||||
Layout.preferredHeight: reactionList.height
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
font.family: mainItem.customFont.family
|
||||
font.pointSize: Units.dp * mainItem.customFont.pointSize
|
||||
visible: mainItem.model && mainItem.model.count != mainItem.model.reactionCount
|
||||
|
||||
text: mainItem.model && mainItem.model.reactionCount || ''
|
||||
}
|
||||
}
|
||||
MouseArea{
|
||||
anchors.fill: parent
|
||||
onClicked: mainItem.reactionsClicked()
|
||||
}
|
||||
}
|
||||
|
|
@ -28,9 +28,6 @@ Rectangle{
|
|||
}
|
||||
|
||||
color: ChatReactionsDetailsStyle.backgroundColorModel.color
|
||||
onVisibleChanged: if(visible){
|
||||
tabBar.currentIndex = 0
|
||||
}
|
||||
MouseArea{
|
||||
anchors.fill: parent
|
||||
onClicked: mainItem.visible = false
|
||||
|
|
@ -45,11 +42,23 @@ Rectangle{
|
|||
ColumnLayout{
|
||||
anchors.fill: parent
|
||||
spacing: 0
|
||||
TabBar {
|
||||
Loader{
|
||||
id: loader
|
||||
Layout.fillWidth: true
|
||||
id: tabBar
|
||||
TabButton {
|
||||
Layout.fillWidth: true
|
||||
active: mainItem.visible
|
||||
function refresh(){
|
||||
active = false
|
||||
active = true
|
||||
}
|
||||
Connections{
|
||||
target: chatReactionsList
|
||||
onChatMessageModelChanged: loader.refresh()
|
||||
onBodiesChanged: loader.refresh()
|
||||
}
|
||||
sourceComponent: TabBar {
|
||||
id: tabBar
|
||||
Component.onCompleted: currentIndex = 0
|
||||
TabButton {
|
||||
//: "%1<br>reactions" : count of all chat reactions with a jump line between count and text.
|
||||
text: UtilsCpp.encodeTextToQmlRichFormat(qsTr('reactionsCount', '', chatReactionsList.reactionCount).arg(chatReactionsList.reactionCount), {noLink:1}).toUpperCase()
|
||||
// noLink=1 to avoid <br> convertion
|
||||
|
|
@ -59,24 +68,20 @@ Rectangle{
|
|||
stretchContent: false
|
||||
style: TabButtonStyle.popup
|
||||
}
|
||||
Repeater{
|
||||
model: ['❤️','👍','😂','😮','😢']
|
||||
delegate: TabButton {
|
||||
width: visible ? undefined : 0
|
||||
property int reactionCount: 0
|
||||
visible: reactionCount > 0
|
||||
text: UtilsCpp.encodeTextToQmlRichFormat(modelData + ' '+reactionCount)
|
||||
textFont.family: mainItem.textFont.family
|
||||
textFont.pointSize: ChatReactionsDetailsStyle.tabBar.pointSize
|
||||
|
||||
onIsSelectedChanged: if(isSelected) chatReactionsList.filter = modelData
|
||||
displaySelector: true
|
||||
stretchContent: false
|
||||
style: TabButtonStyle.popup
|
||||
|
||||
Connections{
|
||||
target: chatReactionsList
|
||||
onChatMessageModelChanged: reactionCount = chatReactionsList.getChatReactionCount(modelData)
|
||||
Repeater{
|
||||
model: chatReactionsList.bodies
|
||||
delegate: TabButton {
|
||||
width: visible ? undefined : 0
|
||||
property int reactionCount: chatReactionsList.getChatReactionCount(modelData)
|
||||
visible: reactionCount > 0
|
||||
text: UtilsCpp.encodeTextToQmlRichFormat(modelData + ' '+reactionCount)
|
||||
textFont.family: mainItem.textFont.family
|
||||
textFont.pointSize: ChatReactionsDetailsStyle.tabBar.pointSize
|
||||
|
||||
onIsSelectedChanged: if(isSelected) chatReactionsList.filter = modelData
|
||||
displaySelector: true
|
||||
stretchContent: false
|
||||
style: TabButtonStyle.popup
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -42,11 +42,11 @@ Item {
|
|||
signal conferenceIcsCopied()
|
||||
signal addContactClicked(string contactAddress)
|
||||
signal viewContactClicked(string contactAddress)
|
||||
signal reactionsClicked(ChatMessageModel message);
|
||||
signal reactionsClicked(ChatMessageModel message)
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
property string lastTextSelected
|
||||
implicitHeight: (deliveryLayout.visible? deliveryLayout.height : 0) +(ephemeralTimerRow.visible? 16 : 0) + chatContent.height + reactionItem.height-10
|
||||
implicitHeight: (deliveryLayout.visible? deliveryLayout.height : 0) +(ephemeralTimerRow.visible? 16 : 0) + chatContent.height + reactionLoader.height-10
|
||||
Rectangle {
|
||||
id: rectangle
|
||||
property int availableWidth: parent.width
|
||||
|
|
@ -56,7 +56,7 @@ Item {
|
|||
anchors.left: !$chatEntry.isOutgoing ? parent.left : undefined
|
||||
anchors.right: $chatEntry.isOutgoing ? parent.right : undefined
|
||||
|
||||
height: parent.height - (deliveryLayout.visible? deliveryLayout.height : 0) - (reactionItem.height-10)
|
||||
height: parent.height - (deliveryLayout.visible? deliveryLayout.height : 0) - (reactionLoader.height-10)
|
||||
radius: ChatStyle.entry.message.radius
|
||||
clip: false
|
||||
color: colorModel.color
|
||||
|
|
@ -144,69 +144,25 @@ Item {
|
|||
|
||||
chatMessageModel: $chatEntry
|
||||
}
|
||||
Rectangle{
|
||||
id: reactionItem
|
||||
Loader{
|
||||
id: reactionLoader
|
||||
anchors.top: rectangle.bottom
|
||||
anchors.left: !$chatEntry.isOutgoing ? rectangle.left : undefined
|
||||
anchors.right: $chatEntry.isOutgoing ? rectangle.right : undefined
|
||||
anchors.topMargin: -10
|
||||
anchors.leftMargin: 5
|
||||
anchors.rightMargin: 5
|
||||
height: visible ? reactionList.height +10 : 0
|
||||
width: visible ? reactionLayout.width + 10 : 0
|
||||
color: rectangle.color
|
||||
radius: rectangle.radius
|
||||
visible: reactionList.count > 0
|
||||
property font customFont : SettingsModel.textMessageFont
|
||||
property font customEmojiFont : SettingsModel.emojiFont
|
||||
|
||||
RowLayout{
|
||||
id: reactionLayout
|
||||
anchors.centerIn: parent
|
||||
ListView{
|
||||
id: reactionList
|
||||
Layout.preferredWidth: contentItem.childrenRect.width
|
||||
Layout.preferredHeight: reactionMetrics.height
|
||||
TextMetrics{
|
||||
id: reactionMetrics
|
||||
text: '😮'
|
||||
font.family: reactionItem.customEmojiFont.family
|
||||
font.pointSize: Units.dp * reactionItem.customEmojiFont.pointSize * 2
|
||||
}
|
||||
orientation: ListView.Horizontal
|
||||
model: ChatReactionProxyModel{
|
||||
id: chatReactionProxyModel
|
||||
chatMessageModel: $chatEntry
|
||||
}
|
||||
spacing: 10
|
||||
delegate:
|
||||
Text{
|
||||
width: reactionMetrics.width
|
||||
height: reactionList.height
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
font.family: reactionItem.customEmojiFont.family
|
||||
font.pointSize: Units.dp * reactionItem.customEmojiFont.pointSize * 2
|
||||
text: $modelData.body || ''
|
||||
}
|
||||
}
|
||||
|
||||
Text{
|
||||
Layout.preferredWidth: contentWidth
|
||||
Layout.preferredHeight: reactionList.height
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
font.family: reactionItem.customFont.family
|
||||
font.pointSize: Units.dp * reactionItem.customFont.pointSize
|
||||
visible: chatReactionProxyModel.count != chatReactionProxyModel.reactionCount
|
||||
|
||||
text: chatReactionProxyModel.reactionCount
|
||||
}
|
||||
ChatReactionProxyModel{
|
||||
id: chatReactionProxyModel
|
||||
chatMessageModel: $chatEntry
|
||||
}
|
||||
MouseArea{
|
||||
anchors.fill: parent
|
||||
onClicked: container.reactionsClicked($chatEntry)
|
||||
active: chatReactionProxyModel.count > 0
|
||||
asynchronous: true
|
||||
sourceComponent: ChatReactions{
|
||||
color: rectangle.color
|
||||
radius: rectangle.radius
|
||||
model: chatReactionProxyModel
|
||||
onReactionsClicked: container.reactionsClicked($chatEntry)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ ChatEmojis 1.0 Chat/ChatEmojis.qml
|
|||
ChatFullContent 1.0 Chat/ChatFullContent.qml
|
||||
ChatMessagePreview 1.0 Chat/ChatMessagePreview.qml
|
||||
ChatForwardMessage 1.0 Chat/ChatForwardMessage.qml
|
||||
ChatReactions 1.0 Chat/ChatReactions.qml
|
||||
ChatReactionsDetails 1.0 Chat/ChatReactionsDetails.qml
|
||||
ChatReplyMessage 1.0 Chat/ChatReplyMessage.qml
|
||||
ChatReplyPreview 1.0 Chat/ChatReplyPreview.qml
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue