fix chat message research #LINQT-2047

try to fix persistent spinner on chat message state icon

remove medias section from contact page #LINQT-2060 #LINQT-2066
This commit is contained in:
Gaelle Braud 2025-10-13 17:03:46 +02:00
parent 82679ab997
commit 1f97112306
9 changed files with 119 additions and 47 deletions

View file

@ -267,7 +267,6 @@ void ChatMessageCore::setSelf(QSharedPointer<ChatMessageCore> me) {
mChatMessageModelConnection->makeConnectToModel( mChatMessageModelConnection->makeConnectToModel(
&ChatMessageModel::msgStateChanged, &ChatMessageModel::msgStateChanged,
[this](const std::shared_ptr<linphone::ChatMessage> &message, linphone::ChatMessage::State state) { [this](const std::shared_ptr<linphone::ChatMessage> &message, linphone::ChatMessage::State state) {
if (mChatMessageModel->getMonitor() != message) return;
auto imdnStatusList = computeDeliveryStatus(message); auto imdnStatusList = computeDeliveryStatus(message);
auto msgState = LinphoneEnums::fromLinphone(state); auto msgState = LinphoneEnums::fromLinphone(state);
mChatMessageModelConnection->invokeToCore([this, msgState, imdnStatusList] { mChatMessageModelConnection->invokeToCore([this, msgState, imdnStatusList] {

View file

@ -161,7 +161,7 @@ void EventLogList::displayMore() {
auto model = EventLogCore::create(it); auto model = EventLogCore::create(it);
events->push_back(model); events->push_back(model);
} }
mCoreModelConnection->invokeToCore([this, events, newCount] { mCoreModelConnection->invokeToCore([this, events] {
int currentCount = mList.count(); int currentCount = mList.count();
for (auto it = events->end() - 1; it >= events->begin(); --it) { for (auto it = events->end() - 1; it >= events->begin(); --it) {
connectItem(*it); connectItem(*it);
@ -171,6 +171,35 @@ void EventLogList::displayMore() {
}); });
} }
void EventLogList::loadMessagesUpTo(std::shared_ptr<linphone::EventLog> event) {
mustBeInLinphoneThread(log().arg(Q_FUNC_INFO));
auto oldestEventLoaded = getAt<EventLogCore>(0);
auto linOldest = std::const_pointer_cast<linphone::EventLog>(oldestEventLoaded->getModel()->getEventLog());
auto chatModel = mChatCore->getModel();
assert(chatModel);
if (!chatModel) return;
int filters = static_cast<int>(linphone::ChatRoom::HistoryFilter::ChatMessage) |
static_cast<int>(linphone::ChatRoom::HistoryFilter::InfoNoDevice);
auto beforeEvents = chatModel->getHistoryRangeNear(mItemsToLoadBeforeSearchResult, 0, event, filters);
auto linphoneLogs = chatModel->getHistoryRangeBetween(event, linOldest, filters);
QList<QSharedPointer<EventLogCore>> *events = new QList<QSharedPointer<EventLogCore>>();
for (auto it : beforeEvents) {
auto model = EventLogCore::create(it);
events->push_back(model);
}
for (auto it : linphoneLogs) {
auto model = EventLogCore::create(it);
events->push_back(model);
}
mCoreModelConnection->invokeToCore([this, events, event] {
for (auto &e : *events) {
connectItem(e);
add(e);
}
emit messagesLoadedUpTo(event);
});
}
int EventLogList::findFirstUnreadIndex() { int EventLogList::findFirstUnreadIndex() {
auto eventList = getSharedList<EventLogCore>(); auto eventList = getSharedList<EventLogCore>();
auto it = std::find_if(eventList.begin(), eventList.end(), [](const QSharedPointer<EventLogCore> item) { auto it = std::find_if(eventList.begin(), eventList.end(), [](const QSharedPointer<EventLogCore> item) {
@ -184,31 +213,47 @@ void EventLogList::findChatMessageWithFilter(QString filter,
bool forward, bool forward,
bool isFirstResearch) { bool isFirstResearch) {
if (mChatCore) { if (mChatCore) {
auto modelConnection = mChatCore->getChatModelConnection(); if (isFirstResearch) mLastFoundResult.reset();
auto chatModel = mChatCore->getModel(); auto chatModel = mChatCore->getModel();
auto startEventModel = startEvent ? startEvent->getModel() : nullptr; auto startEventModel = startEvent ? startEvent->getModel() : nullptr;
modelConnection->invokeToModel( mCoreModelConnection->invokeToModel([this, chatModel, startEventModel, filter, forward, isFirstResearch] {
[this, chatModel, startEventModel, filter, forward, modelConnection, isFirstResearch] { auto linStartEvent = startEventModel ? startEventModel->getEventLog() : nullptr;
auto linStartEvent = startEventModel ? startEventModel->getEventLog() : nullptr; auto eventLog = chatModel->searchMessageByText(filter, linStartEvent, forward);
auto eventLog = chatModel->searchMessageByText(filter, linStartEvent, forward); if (!eventLog)
// If it is the first research and event was not found from the start event, search in the // event not found, search in the entire history
// entire history auto eventLog = chatModel->searchMessageByText(filter, nullptr, forward);
if (!eventLog && isFirstResearch) { int index = -1;
auto firstEvent = getAt<EventLogCore>(0); if (eventLog) {
auto linFirst = firstEvent ? firstEvent->getModel()->getEventLog() : nullptr; auto eventList = getSharedList<EventLogCore>();
eventLog = chatModel->searchMessageByText(filter, nullptr, forward); auto it = std::find_if(eventList.begin(), eventList.end(),
} [eventLog](const QSharedPointer<EventLogCore> item) {
int index = -1; return item->getModel()->getEventLog() == eventLog;
if (eventLog) { });
auto eventList = getSharedList<EventLogCore>(); if (it != eventList.end()) {
auto it = std::find_if(eventList.begin(), eventList.end(), int index = std::distance(eventList.begin(), it);
[eventLog](const QSharedPointer<EventLogCore> item) { if (mLastFoundResult && mLastFoundResult == *it) index = -1;
return item->getModel()->getEventLog() == eventLog; mLastFoundResult = *it;
}); mCoreModelConnection->invokeToCore([this, index] { emit messageWithFilterFound(index); });
index = it == eventList.end() ? -1 : std::distance(eventList.begin(), it); } else {
} connect(this, &EventLogList::messagesLoadedUpTo, this,
modelConnection->invokeToCore([this, index] { emit messageWithFilterFound(index); }); [this](std::shared_ptr<linphone::EventLog> event) {
}); 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;
if (mLastFoundResult && mLastFoundResult == *it) index = -1;
mLastFoundResult = *it;
mCoreModelConnection->invokeToCore(
[this, index] { emit messageWithFilterFound(index); });
});
loadMessagesUpTo(eventLog);
}
} else {
mCoreModelConnection->invokeToCore([this, index] { emit messageWithFilterFound(index); });
}
});
} }
} }
@ -217,7 +262,6 @@ void EventLogList::setSelf(QSharedPointer<EventLogList> me) {
mCoreModelConnection->makeConnectToCore(&EventLogList::lUpdate, [this]() { mCoreModelConnection->makeConnectToCore(&EventLogList::lUpdate, [this]() {
mustBeInMainThread(log().arg(Q_FUNC_INFO)); mustBeInMainThread(log().arg(Q_FUNC_INFO));
if (mChatCore) qDebug() << "reset messages model for chat core" << mChatCore << mChatCore->getTitle();
setIsUpdating(true); setIsUpdating(true);
beginResetModel(); beginResetModel();
mList.clear(); mList.clear();
@ -234,7 +278,6 @@ void EventLogList::setSelf(QSharedPointer<EventLogList> me) {
} }
mCoreModelConnection->invokeToModel([this, chatModel]() { mCoreModelConnection->invokeToModel([this, chatModel]() {
mustBeInLinphoneThread(log().arg(Q_FUNC_INFO)); mustBeInLinphoneThread(log().arg(Q_FUNC_INFO));
qDebug() << "update history till" << mDisplayItemsStep;
auto linphoneLogs = chatModel->getHistoryRange(0, mDisplayItemsStep); auto linphoneLogs = chatModel->getHistoryRange(0, mDisplayItemsStep);
QList<QSharedPointer<EventLogCore>> *events = new QList<QSharedPointer<EventLogCore>>(); QList<QSharedPointer<EventLogCore>> *events = new QList<QSharedPointer<EventLogCore>>();
for (auto it : linphoneLogs) { for (auto it : linphoneLogs) {
@ -251,9 +294,8 @@ void EventLogList::setSelf(QSharedPointer<EventLogList> me) {
} }
for (auto &event : *events) { for (auto &event : *events) {
connectItem(event); connectItem(event);
mList.append(event);
} }
for (auto i : *events)
mList << i.template objectCast<QObject>();
endResetModel(); endResetModel();
setIsUpdating(false); setIsUpdating(false);
}); });

View file

@ -50,6 +50,10 @@ public:
void setIsUpdating(bool updating); void setIsUpdating(bool updating);
void loadMessagesUpTo(std::shared_ptr<linphone::EventLog> event);
void setLastFoundResult(const QSharedPointer<EventLogCore> &eventLog);
int findFirstUnreadIndex(); int findFirstUnreadIndex();
void displayMore(); void displayMore();
@ -73,6 +77,7 @@ signals:
void chatGuiChanged(); void chatGuiChanged();
void isUpdatingChanged(); void isUpdatingChanged();
void displayItemsStepChanged(); void displayItemsStepChanged();
void messagesLoadedUpTo(std::shared_ptr<linphone::EventLog> event);
private: private:
QString mFilter; QString mFilter;
@ -81,6 +86,8 @@ private:
QSharedPointer<SafeConnection<EventLogList, CoreModel>> mCoreModelConnection; QSharedPointer<SafeConnection<EventLogList, CoreModel>> mCoreModelConnection;
bool mIsUpdating = false; bool mIsUpdating = false;
int mDisplayItemsStep = 0; int mDisplayItemsStep = 0;
int mItemsToLoadBeforeSearchResult = 3;
QSharedPointer<EventLogCore> mLastFoundResult;
DECLARE_ABSTRACT_OBJECT DECLARE_ABSTRACT_OBJECT
}; };

View file

@ -48,29 +48,31 @@ void EventLogProxy::setSourceModel(QAbstractItemModel *model) {
connect(newEventLogList, &EventLogList::eventInserted, this, connect(newEventLogList, &EventLogList::eventInserted, this,
[this, newEventLogList](int index, EventLogGui *event) { [this, newEventLogList](int index, EventLogGui *event) {
invalidate(); invalidate();
int proxyIndex = -1;
if (index != -1) { if (index != -1) {
index = dynamic_cast<SortFilterList *>(sourceModel()) proxyIndex = dynamic_cast<SortFilterList *>(sourceModel())
->mapFromSource(newEventLogList->index(index, 0)) ->mapFromSource(newEventLogList->index(index, 0))
.row(); .row();
if (mMaxDisplayItems <= index) setMaxDisplayItems(index + mDisplayItemsStep);
} }
loadUntil(index); loadUntil(proxyIndex);
emit eventInserted(index, event); emit eventInserted(proxyIndex, event);
}); });
connect(newEventLogList, &EventLogList::messageWithFilterFound, this, [this, newEventLogList](int index) { connect(newEventLogList, &EventLogList::messageWithFilterFound, this, [this, newEventLogList](int i) {
if (index != -1) { connect(this, &EventLogProxy::layoutChanged, newEventLogList, [this, i, newEventLogList] {
disconnect(this, &EventLogProxy::layoutChanged, newEventLogList, nullptr);
auto model = getListModel<EventLogList>(); auto model = getListModel<EventLogList>();
mLastSearchStart = model->getAt<EventLogCore>(index); int proxyIndex =
index = dynamic_cast<SortFilterList *>(sourceModel()) dynamic_cast<SortFilterList *>(sourceModel())->mapFromSource(newEventLogList->index(i, 0)).row();
->mapFromSource(newEventLogList->index(index, 0)) if (i != -1) {
.row(); loadUntil(proxyIndex);
loadUntil(index); }
} emit indexWithFilterFound(proxyIndex);
emit indexWithFilterFound(index); });
invalidate();
}); });
} }
setSourceModels(new SortFilterList(model, Qt::DescendingOrder)); setSourceModels(new SortFilterList(model, Qt::DescendingOrder));
sort(0); sort(0, Qt::DescendingOrder);
} }
ChatGui *EventLogProxy::getChatGui() { ChatGui *EventLogProxy::getChatGui() {
@ -144,5 +146,8 @@ bool EventLogProxy::SortFilterList::filterAcceptsRow(int sourceRow, const QModel
} }
bool EventLogProxy::SortFilterList::lessThan(const QModelIndex &sourceLeft, const QModelIndex &sourceRight) const { bool EventLogProxy::SortFilterList::lessThan(const QModelIndex &sourceLeft, const QModelIndex &sourceRight) const {
auto l = getItemAtSource<EventLogList, EventLogCore>(sourceLeft.row());
auto r = getItemAtSource<EventLogList, EventLogCore>(sourceRight.row());
if (l && r) return l->getTimestamp() <= r->getTimestamp();
return true; return true;
} }

View file

@ -68,6 +68,18 @@ std::list<std::shared_ptr<linphone::EventLog>> ChatModel::getHistoryRange(int be
return mMonitor->getHistoryRangeEvents(begin, end); return mMonitor->getHistoryRangeEvents(begin, end);
} }
std::list<std::shared_ptr<linphone::EventLog>>
ChatModel::getHistoryRangeBetween(const std::shared_ptr<linphone::EventLog> firstEvent,
const std::shared_ptr<linphone::EventLog> lastEvent,
int filters) {
return mMonitor->getHistoryRangeBetween(firstEvent, lastEvent, filters);
}
std::list<std::shared_ptr<linphone::EventLog>>
ChatModel::getHistoryRangeNear(int before, int after, const std::shared_ptr<linphone::EventLog> event, int filters) {
return mMonitor->getHistoryRangeNear(before, after, event, filters);
}
std::list<std::shared_ptr<linphone::ChatMessage>> ChatModel::getChatMessageHistory() const { std::list<std::shared_ptr<linphone::ChatMessage>> ChatModel::getChatMessageHistory() const {
auto history = mMonitor->getHistory(0, (int)linphone::ChatRoom::HistoryFilter::ChatMessage); auto history = mMonitor->getHistory(0, (int)linphone::ChatRoom::HistoryFilter::ChatMessage);
std::list<std::shared_ptr<linphone::ChatMessage>> res; std::list<std::shared_ptr<linphone::ChatMessage>> res;

View file

@ -50,6 +50,12 @@ public:
std::list<std::shared_ptr<linphone::Content>> getSharedDocuments() const; std::list<std::shared_ptr<linphone::Content>> getSharedDocuments() const;
std::list<std::shared_ptr<linphone::EventLog>> getHistory() const; std::list<std::shared_ptr<linphone::EventLog>> getHistory() const;
std::list<std::shared_ptr<linphone::EventLog>> getHistoryRange(int begin, int end); std::list<std::shared_ptr<linphone::EventLog>> getHistoryRange(int begin, int end);
std::list<std::shared_ptr<linphone::EventLog>>
getHistoryRangeBetween(const std::shared_ptr<linphone::EventLog> firstEvent,
const std::shared_ptr<linphone::EventLog> lastEvent,
int filters);
std::list<std::shared_ptr<linphone::EventLog>>
getHistoryRangeNear(int before, int after, const std::shared_ptr<linphone::EventLog> firstEvent, int filters);
std::list<std::shared_ptr<linphone::ChatMessage>> getChatMessageHistory() const; std::list<std::shared_ptr<linphone::ChatMessage>> getChatMessageHistory() const;
int getHistorySizeEvents(); int getHistorySizeEvents();
QString getIdentifier() const; QString getIdentifier() const;

View file

@ -299,6 +299,7 @@ Control.Control {
} }
} }
EffectImage { EffectImage {
// Imdn status icon
visible: !mainItem.isRemoteMessage visible: !mainItem.isRemoteMessage
Layout.preferredWidth: visible ? 14 * DefaultStyle.dp : 0 Layout.preferredWidth: visible ? 14 * DefaultStyle.dp : 0
Layout.preferredHeight: visible ? 14 * DefaultStyle.dp : 0 Layout.preferredHeight: visible ? 14 * DefaultStyle.dp : 0

View file

@ -72,7 +72,7 @@ Item {
color: DefaultStyle.main1_200 color: DefaultStyle.main1_200
opacity: 0.5 opacity: 0.5
Image { Image {
anchors.fill: image anchors.fill: parent
z: parent.z + 1 z: parent.z + 1
visible: image.status == Image.Error || image.status == Image.Null || !UtilsCpp.fileExists(mainItem.filePath) visible: image.status == Image.Error || image.status == Image.Null || !UtilsCpp.fileExists(mainItem.filePath)
source: AppIcons.fileImage source: AppIcons.fileImage

View file

@ -606,7 +606,7 @@ FriendGui{
} }
} }
ContactDetailLayout { ContactDetailLayout {
visible: !SettingsCpp.disableChatFeature visible: false//!SettingsCpp.disableChatFeature
//: "Medias" //: "Medias"
label: qsTr("contact_details_medias_title") label: qsTr("contact_details_medias_title")
Layout.fillWidth: true Layout.fillWidth: true