mirror of
https://gitlab.linphone.org/BC/public/linphone-desktop.git
synced 2026-04-17 20:08:28 +00:00
scroll to original message on click on reply message #LINQT-2390
This commit is contained in:
parent
ca0bf41ee7
commit
92f4a92f86
9 changed files with 122 additions and 16 deletions
|
|
@ -194,6 +194,7 @@ ChatMessageCore::ChatMessageCore(const std::shared_ptr<linphone::ChatMessage> &c
|
||||||
|
|
||||||
mIsForward = chatmessage->isForward();
|
mIsForward = chatmessage->isForward();
|
||||||
mIsReply = chatmessage->isReply();
|
mIsReply = chatmessage->isReply();
|
||||||
|
mReplyMessageId = Utils::coreStringToAppString(chatmessage->getReplyMessageId());
|
||||||
if (mIsReply) {
|
if (mIsReply) {
|
||||||
auto replymessage = chatmessage->getReplyMessage();
|
auto replymessage = chatmessage->getReplyMessage();
|
||||||
if (replymessage) {
|
if (replymessage) {
|
||||||
|
|
|
||||||
|
|
@ -107,6 +107,7 @@ class ChatMessageCore : public QObject, public AbstractObject {
|
||||||
Q_PROPERTY(bool isForward MEMBER mIsForward CONSTANT)
|
Q_PROPERTY(bool isForward MEMBER mIsForward CONSTANT)
|
||||||
Q_PROPERTY(bool isReply MEMBER mIsReply CONSTANT)
|
Q_PROPERTY(bool isReply MEMBER mIsReply CONSTANT)
|
||||||
Q_PROPERTY(QString replyText MEMBER mReplyText CONSTANT)
|
Q_PROPERTY(QString replyText MEMBER mReplyText CONSTANT)
|
||||||
|
Q_PROPERTY(QString replyMessageId MEMBER mReplyMessageId CONSTANT)
|
||||||
Q_PROPERTY(QString repliedToName MEMBER mRepliedToName CONSTANT)
|
Q_PROPERTY(QString repliedToName MEMBER mRepliedToName CONSTANT)
|
||||||
Q_PROPERTY(bool hasFileContent MEMBER mHasFileContent CONSTANT)
|
Q_PROPERTY(bool hasFileContent MEMBER mHasFileContent CONSTANT)
|
||||||
Q_PROPERTY(bool isVoiceRecording MEMBER mIsVoiceRecording CONSTANT)
|
Q_PROPERTY(bool isVoiceRecording MEMBER mIsVoiceRecording CONSTANT)
|
||||||
|
|
@ -220,6 +221,7 @@ private:
|
||||||
bool mIsForward = false;
|
bool mIsForward = false;
|
||||||
bool mIsReply = false;
|
bool mIsReply = false;
|
||||||
QString mReplyText;
|
QString mReplyText;
|
||||||
|
QString mReplyMessageId;
|
||||||
QString mRepliedToName;
|
QString mRepliedToName;
|
||||||
bool mHasFileContent = false;
|
bool mHasFileContent = false;
|
||||||
bool mIsCalendarInvite = false;
|
bool mIsCalendarInvite = false;
|
||||||
|
|
|
||||||
|
|
@ -201,7 +201,10 @@ void EventLogList::loadMessagesUpTo(std::shared_ptr<linphone::EventLog> event) {
|
||||||
: nullptr;
|
: nullptr;
|
||||||
auto chatModel = mChatCore->getModel();
|
auto chatModel = mChatCore->getModel();
|
||||||
assert(chatModel);
|
assert(chatModel);
|
||||||
if (!chatModel) return;
|
if (!chatModel) {
|
||||||
|
emit messagesLoadedUpTo(nullptr);
|
||||||
|
return;
|
||||||
|
}
|
||||||
int filters = static_cast<int>(linphone::ChatRoom::HistoryFilter::ChatMessage) |
|
int filters = static_cast<int>(linphone::ChatRoom::HistoryFilter::ChatMessage) |
|
||||||
static_cast<int>(linphone::ChatRoom::HistoryFilter::InfoNoDevice);
|
static_cast<int>(linphone::ChatRoom::HistoryFilter::InfoNoDevice);
|
||||||
auto beforeEvents = chatModel->getHistoryRangeNear(mItemsToLoadBeforeSearchResult, 0, event, filters);
|
auto beforeEvents = chatModel->getHistoryRangeNear(mItemsToLoadBeforeSearchResult, 0, event, filters);
|
||||||
|
|
@ -273,19 +276,24 @@ void EventLogList::findChatMessageWithFilter(QString filter, int startIndex, boo
|
||||||
mLastFoundResult = *it;
|
mLastFoundResult = *it;
|
||||||
mCoreModelConnection->invokeToCore([this, index] { emit messageWithFilterFound(index); });
|
mCoreModelConnection->invokeToCore([this, index] { emit messageWithFilterFound(index); });
|
||||||
} else {
|
} else {
|
||||||
connect(this, &EventLogList::messagesLoadedUpTo, this,
|
connect(
|
||||||
[this](std::shared_ptr<linphone::EventLog> event) {
|
this, &EventLogList::messagesLoadedUpTo, this,
|
||||||
auto eventList = getSharedList<EventLogCore>();
|
[this](std::shared_ptr<linphone::EventLog> event) {
|
||||||
auto it = std::find_if(eventList.begin(), eventList.end(),
|
if (event == nullptr) emit messageWithFilterFound(-1);
|
||||||
[event](const QSharedPointer<EventLogCore> item) {
|
else {
|
||||||
return item->getModel()->getEventLog() == event;
|
auto eventList = getSharedList<EventLogCore>();
|
||||||
});
|
auto it = std::find_if(eventList.begin(), eventList.end(),
|
||||||
int index = it != eventList.end() ? std::distance(eventList.begin(), it) : -1;
|
[event](const QSharedPointer<EventLogCore> item) {
|
||||||
if (mLastFoundResult && mLastFoundResult == *it) index = -1;
|
return item->getModel()->getEventLog() == event;
|
||||||
mLastFoundResult = *it;
|
});
|
||||||
mCoreModelConnection->invokeToCore(
|
int index = it != eventList.end() ? std::distance(eventList.begin(), it) : -1;
|
||||||
[this, index] { emit messageWithFilterFound(index); });
|
if (mLastFoundResult && mLastFoundResult == *it) index = -1;
|
||||||
});
|
mLastFoundResult = *it;
|
||||||
|
mCoreModelConnection->invokeToCore(
|
||||||
|
[this, index] { emit messageWithFilterFound(index); });
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Qt::SingleShotConnection);
|
||||||
loadMessagesUpTo(eventLog);
|
loadMessagesUpTo(eventLog);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -296,6 +304,55 @@ void EventLogList::findChatMessageWithFilter(QString filter, int startIndex, boo
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void EventLogList::findChatMessageById(const QString &messageId) {
|
||||||
|
lInfo() << log().arg("Try to find message by id :");
|
||||||
|
auto eventList = getSharedList<EventLogCore>();
|
||||||
|
auto it = std::find_if(eventList.begin(), eventList.end(), [messageId](const QSharedPointer<EventLogCore> item) {
|
||||||
|
auto messageCore = item->getChatMessageCore();
|
||||||
|
if (!messageCore) return false;
|
||||||
|
return messageCore->getMessageId() == messageId;
|
||||||
|
});
|
||||||
|
if (it != eventList.end()) {
|
||||||
|
int index = std::distance(eventList.begin(), it);
|
||||||
|
if (index != -1) emit foundMessagById(index);
|
||||||
|
} else {
|
||||||
|
lInfo() << log().arg("Not found in displayed messages, search in entire history");
|
||||||
|
auto chatModel = mChatCore->getModel();
|
||||||
|
mCoreModelConnection->invokeToModel([this, chatModel, messageId] {
|
||||||
|
auto history = chatModel->getHistory();
|
||||||
|
auto it = std::find_if(history.begin(), history.end(),
|
||||||
|
[messageId](const std::shared_ptr<linphone::EventLog> eventLog) {
|
||||||
|
auto chatMessage = eventLog->getChatMessage();
|
||||||
|
if (!chatMessage) return false;
|
||||||
|
return Utils::coreStringToAppString(chatMessage->getMessageId()) == messageId;
|
||||||
|
});
|
||||||
|
// int index = it != history.end() ? std::distance(history.begin(), it) : -1;
|
||||||
|
// if (index != -1) emit foundMessagById(index);
|
||||||
|
if (it != history.end()) {
|
||||||
|
lInfo() << log().arg("Found in entire history, load messages up to it");
|
||||||
|
connect(
|
||||||
|
this, &EventLogList::messagesLoadedUpTo, this,
|
||||||
|
[this](std::shared_ptr<linphone::EventLog> event) {
|
||||||
|
if (event == nullptr) return;
|
||||||
|
auto eventList = getSharedList<EventLogCore>();
|
||||||
|
auto it = std::find_if(eventList.begin(), eventList.end(),
|
||||||
|
[event](const QSharedPointer<EventLogCore> item) {
|
||||||
|
return item->getModel()->getEventLog() == event;
|
||||||
|
});
|
||||||
|
int index = it != eventList.end() ? std::distance(eventList.begin(), it) : -1;
|
||||||
|
lInfo() << log().arg("Index corresponding to chat message id :") << index;
|
||||||
|
mCoreModelConnection->invokeToCore([this, index] { emit foundMessagById(index); });
|
||||||
|
},
|
||||||
|
Qt::SingleShotConnection);
|
||||||
|
loadMessagesUpTo(*it);
|
||||||
|
} else {
|
||||||
|
lInfo() << log().arg("Not found in entire history, event must have been deleted");
|
||||||
|
emit foundMessagById(-1);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void EventLogList::setSelf(QSharedPointer<EventLogList> me) {
|
void EventLogList::setSelf(QSharedPointer<EventLogList> me) {
|
||||||
mCoreModelConnection = SafeConnection<EventLogList, CoreModel>::create(me, CoreModel::getInstance());
|
mCoreModelConnection = SafeConnection<EventLogList, CoreModel>::create(me, CoreModel::getInstance());
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -60,6 +60,7 @@ public:
|
||||||
void setDisplayItemsStep(int displayItemsStep);
|
void setDisplayItemsStep(int displayItemsStep);
|
||||||
|
|
||||||
void findChatMessageWithFilter(QString filter, int startIndex, bool forward = true, bool isFirstResearch = true);
|
void findChatMessageWithFilter(QString filter, int startIndex, bool forward = true, bool isFirstResearch = true);
|
||||||
|
void findChatMessageById(const QString &messageId);
|
||||||
|
|
||||||
void setSelf(QSharedPointer<EventLogList> me);
|
void setSelf(QSharedPointer<EventLogList> me);
|
||||||
virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
||||||
|
|
@ -71,6 +72,7 @@ signals:
|
||||||
void filterChanged(QString filter);
|
void filterChanged(QString filter);
|
||||||
void eventInsertedByUser(int index);
|
void eventInsertedByUser(int index);
|
||||||
void messageWithFilterFound(int index);
|
void messageWithFilterFound(int index);
|
||||||
|
void foundMessagById(int index);
|
||||||
void listAboutToBeReset();
|
void listAboutToBeReset();
|
||||||
void chatGuiChanged();
|
void chatGuiChanged();
|
||||||
void displayItemsStepChanged();
|
void displayItemsStepChanged();
|
||||||
|
|
|
||||||
|
|
@ -39,6 +39,7 @@ void EventLogProxy::setSourceModel(QAbstractItemModel *model) {
|
||||||
if (oldEventLogList) {
|
if (oldEventLogList) {
|
||||||
disconnect(oldEventLogList, &EventLogList::displayItemsStepChanged, this, nullptr);
|
disconnect(oldEventLogList, &EventLogList::displayItemsStepChanged, this, nullptr);
|
||||||
disconnect(oldEventLogList, &EventLogList::messageWithFilterFound, this, nullptr);
|
disconnect(oldEventLogList, &EventLogList::messageWithFilterFound, this, nullptr);
|
||||||
|
disconnect(oldEventLogList, &EventLogList::foundMessagById, this, nullptr);
|
||||||
disconnect(oldEventLogList, &EventLogList::eventInsertedByUser, this, nullptr);
|
disconnect(oldEventLogList, &EventLogList::eventInsertedByUser, this, nullptr);
|
||||||
}
|
}
|
||||||
auto newEventLogList = dynamic_cast<EventLogList *>(model);
|
auto newEventLogList = dynamic_cast<EventLogList *>(model);
|
||||||
|
|
@ -53,6 +54,19 @@ void EventLogProxy::setSourceModel(QAbstractItemModel *model) {
|
||||||
}
|
}
|
||||||
emit indexWithFilterFound(proxyIndex);
|
emit indexWithFilterFound(proxyIndex);
|
||||||
});
|
});
|
||||||
|
connect(newEventLogList, &EventLogList::foundMessagById, this, [this, newEventLogList](int i) {
|
||||||
|
auto model = dynamic_cast<EventLogList *>(sourceModel());
|
||||||
|
int proxyIndex = mapFromSource(newEventLogList->index(i, 0)).row();
|
||||||
|
if (i != -1) {
|
||||||
|
loadUntil(proxyIndex);
|
||||||
|
lInfo() << "Found index by id, request highlight at index" << proxyIndex;
|
||||||
|
emit foundMessagById(proxyIndex);
|
||||||
|
} else {
|
||||||
|
Utils::showInformationPopup("info_popup_error_title",
|
||||||
|
//: Original message not found. It may have been deleted
|
||||||
|
"info_popup_reply_message_not_found_error");
|
||||||
|
}
|
||||||
|
});
|
||||||
connect(newEventLogList, &EventLogList::eventInsertedByUser, this, [this, newEventLogList](int i) {
|
connect(newEventLogList, &EventLogList::eventInsertedByUser, this, [this, newEventLogList](int i) {
|
||||||
int proxyIndex = mapFromSource(newEventLogList->index(i, 0)).row();
|
int proxyIndex = mapFromSource(newEventLogList->index(i, 0)).row();
|
||||||
emit eventInsertedByUser(proxyIndex);
|
emit eventInsertedByUser(proxyIndex);
|
||||||
|
|
@ -207,3 +221,10 @@ void EventLogProxy::findIndexCorrespondingToFilter(int startIndex, bool forward,
|
||||||
eventLogList->findChatMessageWithFilter(filter, listIndex, forward, isFirstResearch);
|
eventLogList->findChatMessageWithFilter(filter, listIndex, forward, isFirstResearch);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void EventLogProxy::findChatMessageById(const QString &messageId) {
|
||||||
|
auto eventLogList = dynamic_cast<EventLogList *>(sourceModel());
|
||||||
|
if (eventLogList) {
|
||||||
|
eventLogList->findChatMessageById(messageId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -77,10 +77,12 @@ public:
|
||||||
Q_INVOKABLE int findFirstUnreadIndex();
|
Q_INVOKABLE int findFirstUnreadIndex();
|
||||||
Q_INVOKABLE void markIndexAsRead(int proxyIndex);
|
Q_INVOKABLE void markIndexAsRead(int proxyIndex);
|
||||||
Q_INVOKABLE void findIndexCorrespondingToFilter(int startIndex, bool forward = true, bool isFirstResearch = true);
|
Q_INVOKABLE void findIndexCorrespondingToFilter(int startIndex, bool forward = true, bool isFirstResearch = true);
|
||||||
|
Q_INVOKABLE void findChatMessageById(const QString &messageId);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void eventInsertedByUser(int index);
|
void eventInsertedByUser(int index);
|
||||||
void indexWithFilterFound(int index);
|
void indexWithFilterFound(int index);
|
||||||
|
void foundMessagById(int index);
|
||||||
void chatGuiChanged();
|
void chatGuiChanged();
|
||||||
void countChanged();
|
void countChanged();
|
||||||
void initialDisplayItemsChanged();
|
void initialDisplayItemsChanged();
|
||||||
|
|
|
||||||
|
|
@ -109,7 +109,7 @@ void ChatMessageContentCore::setSelf(QSharedPointer<ChatMessageContentCore> me)
|
||||||
mChatMessageContentModelConnection->invokeToCore([this, error] {
|
mChatMessageContentModelConnection->invokeToCore([this, error] {
|
||||||
//: Error downloading file %1
|
//: Error downloading file %1
|
||||||
if (error->isEmpty()) *error = tr("download_file_default_error").arg(mName);
|
if (error->isEmpty()) *error = tr("download_file_default_error").arg(mName);
|
||||||
Utils::showInformationPopup(tr("info_popup_error_titile"), *error, false);
|
Utils::showInformationPopup(tr("info_popup_error_title"), *error, false);
|
||||||
delete error;
|
delete error;
|
||||||
});
|
});
|
||||||
} else delete error;
|
} else delete error;
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,8 @@ Control.Control {
|
||||||
property bool isFromChatGroup: chatMessage? chatMessage.core.isFromChatGroup : false
|
property bool isFromChatGroup: chatMessage? chatMessage.core.isFromChatGroup : false
|
||||||
property bool isReply: chatMessage? chatMessage.core.isReply : false
|
property bool isReply: chatMessage? chatMessage.core.isReply : false
|
||||||
property bool isForward: chatMessage? chatMessage.core.isForward : false
|
property bool isForward: chatMessage? chatMessage.core.isForward : false
|
||||||
property string replyText: chatMessage? chatMessage.core.replyText : false
|
property string replyText: chatMessage? chatMessage.core.replyText : ""
|
||||||
|
property string replyMessageId: chatMessage? chatMessage.core.replyMessageId : ""
|
||||||
property var msgState: chatMessage ? chatMessage.core.messageState : LinphoneEnums.ChatMessageState.StateIdle
|
property var msgState: chatMessage ? chatMessage.core.messageState : LinphoneEnums.ChatMessageState.StateIdle
|
||||||
hoverEnabled: true
|
hoverEnabled: true
|
||||||
property bool linkHovered: false
|
property bool linkHovered: false
|
||||||
|
|
@ -40,6 +41,7 @@ Control.Control {
|
||||||
signal forwardMessageRequested()
|
signal forwardMessageRequested()
|
||||||
signal endOfVoiceRecordingReached()
|
signal endOfVoiceRecordingReached()
|
||||||
signal requestAutoPlayVoiceRecording()
|
signal requestAutoPlayVoiceRecording()
|
||||||
|
signal searchMessageByIdRequested(string id)
|
||||||
onRequestAutoPlayVoiceRecording: chatBubbleContent.requestAutoPlayVoiceRecording()
|
onRequestAutoPlayVoiceRecording: chatBubbleContent.requestAutoPlayVoiceRecording()
|
||||||
|
|
||||||
Timer {
|
Timer {
|
||||||
|
|
@ -154,6 +156,13 @@ Control.Control {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
color: DefaultStyle.grey_200
|
color: DefaultStyle.grey_200
|
||||||
radius: Utils.getSizeWithScreenRatio(16)
|
radius: Utils.getSizeWithScreenRatio(16)
|
||||||
|
MouseArea {
|
||||||
|
anchors.fill: parent
|
||||||
|
cursorShape: Qt.PointingHandCursor
|
||||||
|
onClicked: {
|
||||||
|
mainItem.searchMessageByIdRequested(mainItem.replyMessageId)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
contentItem: Text {
|
contentItem: Text {
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,7 @@ ListView {
|
||||||
signal editMessageRequested(ChatMessageGui chatMessage)
|
signal editMessageRequested(ChatMessageGui chatMessage)
|
||||||
signal requestHighlight(int indexToHighlight)
|
signal requestHighlight(int indexToHighlight)
|
||||||
signal requestAutoPlayVoiceRecording(int indexToPlay)
|
signal requestAutoPlayVoiceRecording(int indexToPlay)
|
||||||
|
signal searchMessageByIdRequested(string id)
|
||||||
currentIndex: -1
|
currentIndex: -1
|
||||||
|
|
||||||
property string filterText
|
property string filterText
|
||||||
|
|
@ -45,6 +46,9 @@ ListView {
|
||||||
searchForward = forward
|
searchForward = forward
|
||||||
eventLogProxy.findIndexCorrespondingToFilter(currentIndex, searchForward, false)
|
eventLogProxy.findIndexCorrespondingToFilter(currentIndex, searchForward, false)
|
||||||
}
|
}
|
||||||
|
onSearchMessageByIdRequested: (id) => {
|
||||||
|
eventLogProxy.findChatMessageById(id)
|
||||||
|
}
|
||||||
|
|
||||||
Button {
|
Button {
|
||||||
visible: !mainItem.lastItemVisible
|
visible: !mainItem.lastItemVisible
|
||||||
|
|
@ -127,6 +131,13 @@ ListView {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
onFoundMessagById: (index) => {
|
||||||
|
if (index !== -1) {
|
||||||
|
currentIndex = index
|
||||||
|
mainItem.positionViewAtIndex(index, ListView.Center)
|
||||||
|
mainItem.requestHighlight(index)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
footer: Item {
|
footer: Item {
|
||||||
|
|
@ -327,6 +338,7 @@ ListView {
|
||||||
onShowReactionsForMessageRequested: mainItem.showReactionsForMessageRequested(chatMessage)
|
onShowReactionsForMessageRequested: mainItem.showReactionsForMessageRequested(chatMessage)
|
||||||
onShowImdnStatusForMessageRequested: mainItem.showImdnStatusForMessageRequested(chatMessage)
|
onShowImdnStatusForMessageRequested: mainItem.showImdnStatusForMessageRequested(chatMessage)
|
||||||
onReplyToMessageRequested: mainItem.replyToMessageRequested(chatMessage)
|
onReplyToMessageRequested: mainItem.replyToMessageRequested(chatMessage)
|
||||||
|
onSearchMessageByIdRequested: (id) => mainItem.searchMessageByIdRequested(id)
|
||||||
onForwardMessageRequested: mainItem.forwardMessageRequested(chatMessage)
|
onForwardMessageRequested: mainItem.forwardMessageRequested(chatMessage)
|
||||||
onEndOfVoiceRecordingReached: {
|
onEndOfVoiceRecordingReached: {
|
||||||
if (nextChatMessage && nextChatMessage.core.isVoiceRecording) mainItem.requestAutoPlayVoiceRecording(index - 1)
|
if (nextChatMessage && nextChatMessage.core.isVoiceRecording) mainItem.requestAutoPlayVoiceRecording(index - 1)
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue