Fixes in chat messages (navigation with read button, sorting)

This commit is contained in:
Gaëlle Braud 2025-07-23 21:09:14 +00:00
parent 8ac30ed393
commit ecf79d530a
8 changed files with 40 additions and 36 deletions

View file

@ -382,13 +382,6 @@ QDateTime ChatMessageCore::getTimestamp() const {
return mTimestamp;
}
void ChatMessageCore::setTimestamp(QDateTime timestamp) {
if (mTimestamp != timestamp) {
mTimestamp = timestamp;
emit timestampChanged(timestamp);
}
}
QString ChatMessageCore::getText() const {
return mText;
}

View file

@ -77,7 +77,7 @@ class EventLogCore;
class ChatMessageCore : public QObject, public AbstractObject {
Q_OBJECT
Q_PROPERTY(QDateTime timestamp READ getTimestamp WRITE setTimestamp NOTIFY timestampChanged)
Q_PROPERTY(QDateTime timestamp READ getTimestamp CONSTANT)
Q_PROPERTY(QString text READ getText WRITE setText NOTIFY textChanged)
Q_PROPERTY(QString utf8Text MEMBER mUtf8Text CONSTANT)
Q_PROPERTY(bool hasTextContent MEMBER mHasTextContent CONSTANT)
@ -119,9 +119,6 @@ public:
QList<ImdnStatus> computeDeliveryStatus(const std::shared_ptr<linphone::ChatMessage> &message);
QDateTime getTimestamp() const;
void setTimestamp(QDateTime timestamp);
QString getText() const;
void setText(QString text);
@ -138,6 +135,7 @@ public:
bool isEphemeral() const;
int getEphemeralDuration() const;
void setEphemeralDuration(int duration);
QDateTime getTimestamp() const;
bool hasFileContent() const;
@ -168,7 +166,6 @@ public:
Q_INVOKABLE ChatMessageContentGui *getVoiceRecordingContent() const;
signals:
void timestampChanged(QDateTime timestamp);
void textChanged(QString text);
void utf8TextChanged(QString text);
void isReadChanged(bool read);

View file

@ -37,9 +37,11 @@ EventLogCore::EventLogCore(const std::shared_ptr<const linphone::EventLog> &even
App::getInstance()->mEngine->setObjectOwnership(this, QQmlEngine::CppOwnership);
mEventLogType = LinphoneEnums::fromLinphone(eventLog->getType());
mTimestamp = QDateTime::fromMSecsSinceEpoch(eventLog->getCreationTime() * 1000);
if (eventLog->getChatMessage()) {
mChatMessageCore = ChatMessageCore::create(eventLog->getChatMessage());
mEventId = Utils::coreStringToAppString(eventLog->getChatMessage()->getMessageId());
auto chatmessage = eventLog->getChatMessage();
if (chatmessage) {
mChatMessageCore = ChatMessageCore::create(chatmessage);
mEventId = Utils::coreStringToAppString(chatmessage->getMessageId());
mTimestamp = QDateTime::fromSecsSinceEpoch(chatmessage->getTime());
} else if (eventLog->getCallLog()) {
mCallHistoryCore = CallHistoryCore::create(eventLog->getCallLog());
mEventId = Utils::coreStringToAppString(eventLog->getCallLog()->getCallId());
@ -80,6 +82,10 @@ CallHistoryCore *EventLogCore::getCallHistoryCorePointer() {
return mCallHistoryCore.get();
}
QDateTime EventLogCore::getTimestamp() const {
return mTimestamp;
}
// Events (other than ChatMessage and CallLog which are handled in their respective Core)
void EventLogCore::computeEvent(const std::shared_ptr<const linphone::EventLog> &eventLog) {

View file

@ -47,7 +47,7 @@ class EventLogCore : public QObject, public AbstractObject {
Q_PROPERTY(bool important MEMBER mImportant CONSTANT)
Q_PROPERTY(bool handled MEMBER mHandled CONSTANT)
Q_PROPERTY(QString eventDetails MEMBER mEventDetails CONSTANT)
Q_PROPERTY(QDateTime timestamp MEMBER mTimestamp CONSTANT)
Q_PROPERTY(QDateTime timestamp READ getTimestamp CONSTANT)
public:
static QSharedPointer<EventLogCore> create(const std::shared_ptr<const linphone::EventLog> &eventLog);
@ -58,6 +58,9 @@ public:
QSharedPointer<ChatMessageCore> getChatMessageCore();
ChatMessageGui *getChatMessageGui();
QSharedPointer<CallHistoryCore> getCallHistoryCore();
QDateTime getTimestamp() const;
bool isHandled() const {
return mHandled;
}

View file

@ -141,14 +141,14 @@ QVariant EventLogList::data(const QModelIndex &index, int role) const {
if (core->getChatMessageCore()) {
switch (role) {
case Qt::DisplayRole:
return QVariant::fromValue(new ChatMessageGui(core->getChatMessageCore()));
return QVariant::fromValue(new EventLogGui(core));
case Qt::DisplayRole + 1:
return "chatMessage";
}
} else if (core->getCallHistoryCore()) {
switch (role) {
case Qt::DisplayRole:
return QVariant::fromValue(new CallHistoryGui(core->getCallHistoryCore()));
return QVariant::fromValue(new EventLogGui(core));
case Qt::DisplayRole + 1:
return "callLog";
}

View file

@ -53,7 +53,7 @@ void EventLogProxy::setSourceModel(QAbstractItemModel *model) {
emit eventInserted(index, event);
});
}
setSourceModels(new SortFilterList(model));
setSourceModels(new SortFilterList(model, Qt::AscendingOrder));
sort(0);
}
@ -94,6 +94,11 @@ int EventLogProxy::findFirstUnreadIndex() {
return std::max(0, getCount() - 1);
}
void EventLogProxy::markIndexAsRead(int proxyIndex) {
auto event = getItemAt<SortFilterList, EventLogList, EventLogCore>(proxyIndex);
if (event && event->getChatMessageCore()) event->getChatMessageCore()->lMarkAsRead();
}
int EventLogProxy::findIndexCorrespondingToFilter(int startIndex, bool goingBackward) {
auto filter = getFilterText();
if (filter.isEmpty()) return startIndex;
@ -117,8 +122,8 @@ bool EventLogProxy::SortFilterList::filterAcceptsRow(int sourceRow, const QModel
}
bool EventLogProxy::SortFilterList::lessThan(const QModelIndex &sourceLeft, const QModelIndex &sourceRight) const {
auto l = getItemAtSource<EventLogList, ChatMessageCore>(sourceLeft.row());
auto r = getItemAtSource<EventLogList, ChatMessageCore>(sourceRight.row());
auto l = getItemAtSource<EventLogList, EventLogCore>(sourceLeft.row());
auto r = getItemAtSource<EventLogList, EventLogCore>(sourceRight.row());
if (l && r) return l->getTimestamp() <= r->getTimestamp();
else return true;
}

View file

@ -46,6 +46,7 @@ public:
Q_INVOKABLE EventLogGui *getEventAtIndex(int index);
Q_INVOKABLE int findFirstUnreadIndex();
Q_INVOKABLE void markIndexAsRead(int proxyIndex);
Q_INVOKABLE int findIndexCorrespondingToFilter(int startIndex, bool goingBackward = false);
signals:

View file

@ -5,6 +5,7 @@ import QtQuick.Controls.Basic as Control
import Qt.labs.qmlmodels
import Linphone
import UtilsCpp
import 'qrc:/qt/qml/Linphone/view/Style/buttonStyle.js' as ButtonStyle
ListView {
id: mainItem
@ -57,6 +58,7 @@ ListView {
Qt.callLater(function() {
var index = eventLogProxy.findFirstUnreadIndex()
positionViewAtIndex(index, ListView.End)
eventLogProxy.markIndexAsRead(index)
})
}
@ -73,18 +75,21 @@ ListView {
topPadding: Math.round(16 * DefaultStyle.dp)
bottomPadding: Math.round(16 * DefaultStyle.dp)
anchors.bottom: parent.bottom
style: ButtonStyle.main
anchors.right: parent.right
anchors.bottomMargin: Math.round(18 * DefaultStyle.dp)
anchors.rightMargin: Math.round(18 * DefaultStyle.dp)
onClicked: {
var index = eventLogProxy.findFirstUnreadIndex()
mainItem.positionViewAtIndex(index, ListView.End)
eventLogProxy.markIndexAsRead(index)
}
}
onAtYEndChanged: if (atYEnd) {
if (eventLogProxy.haveMore)
eventLogProxy.displayMore()
else chat.core.lMarkAsRead()
}
model: EventLogProxy {
@ -94,11 +99,12 @@ ListView {
filterText: mainItem.filterText
onEventInserted: (index, gui) => {
if (!mainItem.visible) return
mainItem.positionViewAtIndex(index, ListView.End)
if(mainItem.lastItemVisible) mainItem.positionViewAtIndex(index, ListView.End)
}
onModelReset: Qt.callLater(function() {
var index = eventLogProxy.findFirstUnreadIndex()
positionViewAtIndex(index, ListView.End)
eventLogProxy.markIndexAsRead(index)
})
}
@ -162,23 +168,16 @@ ListView {
id: chatMessageDelegate
property int yoff: Math.round(chatMessageDelegate.y - mainItem.contentY)
property bool isFullyVisible: (yoff > mainItem.y && yoff + height < mainItem.y + mainItem.height)
chatMessage: modelData.core.chatMessageGui
onIsFullyVisibleChanged: {
if (index === mainItem.count - 1) {
mainItem.lastItemVisible = isFullyVisible
}
if (isFullyVisible)
modelData.core.lMarkAsRead()
}
Component.onCompleted: if (index === mainItem.count - 1) mainItem.lastItemVisible = isFullyVisible
chatMessage: modelData
chat: mainItem.chat
searchedTextPart: mainItem.filterText
maxWidth: Math.round(mainItem.width * (3/4))
onVisibleChanged: {
if (visible) {
modelData.core.lMarkAsRead()
}
}
width: mainItem.width
property var previousIndex: index - 1
property ChatMessageGui nextChatMessage: index >= (mainItem.count - 1)
@ -188,16 +187,16 @@ ListView {
: null
property var previousFromAddress: eventLogProxy.getEventAtIndex(index-1)?.core.chatMessage?.fromAddress
backgroundColor: isRemoteMessage ? DefaultStyle.main2_100 : DefaultStyle.main1_100
isFirstMessage: !previousFromAddress || previousFromAddress !== modelData.core.fromAddress
isFirstMessage: !previousFromAddress || previousFromAddress !== chatMessage.core.fromAddress
anchors.right: !isRemoteMessage && parent
? parent.right
: undefined
onMessageDeletionRequested: modelData.core.lDelete()
onShowReactionsForMessageRequested: mainItem.showReactionsForMessageRequested(modelData)
onShowImdnStatusForMessageRequested: mainItem.showImdnStatusForMessageRequested(modelData)
onReplyToMessageRequested: mainItem.replyToMessageRequested(modelData)
onForwardMessageRequested: mainItem.forwardMessageRequested(modelData)
onMessageDeletionRequested: chatMessage.core.lDelete()
onShowReactionsForMessageRequested: mainItem.showReactionsForMessageRequested(chatMessage)
onShowImdnStatusForMessageRequested: mainItem.showImdnStatusForMessageRequested(chatMessage)
onReplyToMessageRequested: mainItem.replyToMessageRequested(chatMessage)
onForwardMessageRequested: mainItem.forwardMessageRequested(chatMessage)
onEndOfVoiceRecordingReached: {
if (nextChatMessage && nextChatMessage.core.isVoiceRecording) mainItem.requestAutoPlayVoiceRecording(index + 1)
}