improve chat messages list view

fix auto scroll when receiving new message #LINQT-2154
This commit is contained in:
Gaelle Braud 2025-11-24 18:37:42 +01:00
parent 29691485bf
commit a7ba374b8f
9 changed files with 304 additions and 210 deletions

View file

@ -96,10 +96,12 @@ void EventLogList::setChatCore(QSharedPointer<ChatCore> core) {
[event](const QSharedPointer<EventLogCore> item) { return item == event; });
if (it == eventsList.end()) {
connectItem(event);
add(event);
prepend(event);
int index;
get(event.get(), &index);
emit eventInserted(index, new EventLogGui(event));
if (event->getChatMessageCore() && !event->getChatMessageCore()->isRemoteMessage()) {
emit eventInsertedByUser(index);
}
}
}
});
@ -122,6 +124,13 @@ void EventLogList::setDisplayItemsStep(int displayItemsStep) {
}
}
void EventLogList::markIndexAsRead(int index) {
if (index < mList.count()) {
auto eventLog = mList[index].objectCast<EventLogCore>();
if (eventLog && eventLog->getChatMessageCore()) eventLog->getChatMessageCore()->lMarkAsRead();
}
}
void EventLogList::displayMore() {
auto loadMoreItems = [this] {
if (!mChatCore) return;
@ -139,7 +148,7 @@ void EventLogList::displayMore() {
QList<QSharedPointer<EventLogCore>> *events = new QList<QSharedPointer<EventLogCore>>();
for (auto it : linphoneLogs) {
auto model = EventLogCore::create(it, chatModel->getMonitor());
events->push_back(model);
if (it->getChatMessage() || model->isHandled()) events->push_front(model);
}
mCoreModelConnection->invokeToCore([this, events] {
int currentCount = mList.count();
@ -147,8 +156,8 @@ void EventLogList::displayMore() {
for (int i = events->size() - 1; i >= 0; --i) {
const auto &ev = events->at(i);
connectItem(ev);
prepend(ev);
}
add(*events);
}
});
});
@ -166,8 +175,10 @@ 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 oldestEventLoaded = mList.count() > 0 ? getAt<EventLogCore>(mList.count() - 1) : nullptr;
auto linOldest = oldestEventLoaded
? std::const_pointer_cast<linphone::EventLog>(oldestEventLoaded->getModel()->getEventLog())
: nullptr;
auto chatModel = mChatCore->getModel();
assert(chatModel);
if (!chatModel) return;
@ -179,45 +190,52 @@ void EventLogList::loadMessagesUpTo(std::shared_ptr<linphone::EventLog> event) {
const auto &linChatRoom = chatModel->getMonitor();
for (const auto &it : beforeEvents) {
auto model = EventLogCore::create(it, linChatRoom);
events->push_back(model);
if (it->getChatMessage() || model->isHandled()) events->push_front(model);
}
for (const auto &it : linphoneLogs) {
auto model = EventLogCore::create(it, linChatRoom);
events->push_back(model);
if (it->getChatMessage() || model->isHandled()) events->push_front(model);
}
mCoreModelConnection->invokeToCore([this, events, event] {
for (const auto &e : *events) {
connectItem(e);
add(e);
}
add(*events);
emit messagesLoadedUpTo(event);
});
}
int EventLogList::findFirstUnreadIndex() {
auto eventList = getSharedList<EventLogCore>();
auto it = std::find_if(eventList.begin(), eventList.end(), [](const QSharedPointer<EventLogCore> item) {
return item->getChatMessageCore() && !item->getChatMessageCore()->isRead();
auto it = std::find_if(eventList.rbegin(), eventList.rend(), [](const QSharedPointer<EventLogCore> item) {
auto chatmessage = item->getChatMessageCore();
return chatmessage && !chatmessage->isRead();
});
return it == eventList.end() ? -1 : std::distance(eventList.begin(), it);
return it == eventList.rend() ? -1 : std::distance(it, eventList.rend()) - 1;
}
void EventLogList::findChatMessageWithFilter(QString filter,
QSharedPointer<EventLogCore> startEvent,
bool forward,
bool isFirstResearch) {
void EventLogList::findChatMessageWithFilter(QString filter, int startIndex, bool forward, bool isFirstResearch) {
if (mChatCore) {
if (isFirstResearch) mLastFoundResult.reset();
auto chatModel = mChatCore->getModel();
auto startEvent =
startIndex >= 0 && startIndex < mList.count() ? mList[startIndex].objectCast<EventLogCore>() : nullptr;
lInfo() << log().arg("searching event starting from index") << startIndex << "| event :"
<< (startEvent && startEvent->getChatMessageCore() ? startEvent->getChatMessageCore()->getText()
: "null")
<< "| filter :" << filter;
auto startEventModel = startEvent ? startEvent->getModel() : nullptr;
mCoreModelConnection->invokeToModel([this, chatModel, startEventModel, filter, forward, isFirstResearch] {
auto linStartEvent = startEventModel ? startEventModel->getEventLog() : nullptr;
auto eventLog = chatModel->searchMessageByText(filter, linStartEvent, forward);
if (!eventLog)
if (!eventLog) {
// event not found, search in the entire history
lInfo() << log().arg("not found, search in entire history");
auto eventLog = chatModel->searchMessageByText(filter, nullptr, forward);
}
int index = -1;
if (eventLog) {
lInfo() << log().arg("event with filter found") << eventLog.get();
auto eventList = getSharedList<EventLogCore>();
auto it = std::find_if(eventList.begin(), eventList.end(),
[eventLog](const QSharedPointer<EventLogCore> item) {
@ -245,6 +263,7 @@ void EventLogList::findChatMessageWithFilter(QString filter,
loadMessagesUpTo(eventLog);
}
} else {
lInfo() << log().arg("event not found at all in history");
mCoreModelConnection->invokeToCore([this, index] { emit messageWithFilterFound(index); });
}
});
@ -288,7 +307,7 @@ void EventLogList::setSelf(QSharedPointer<EventLogList> me) {
QList<QSharedPointer<EventLogCore>> *events = new QList<QSharedPointer<EventLogCore>>();
for (auto it : linphoneLogs) {
auto model = EventLogCore::create(it, chatModel->getMonitor());
events->push_back(model);
if (it->getChatMessage() || model->isHandled()) events->push_front(model);
}
mCoreModelConnection->invokeToCore([this, events] {
for (auto &event : *events) {

View file

@ -54,13 +54,12 @@ public:
int findFirstUnreadIndex();
void markIndexAsRead(int index);
void displayMore();
void setDisplayItemsStep(int displayItemsStep);
void findChatMessageWithFilter(QString filter,
QSharedPointer<EventLogCore> startEvent,
bool forward = true,
bool isFirstResearch = true);
void findChatMessageWithFilter(QString filter, int startIndex, bool forward = true, bool isFirstResearch = true);
void setSelf(QSharedPointer<EventLogList> me);
virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
@ -69,7 +68,7 @@ public:
signals:
void lUpdate();
void filterChanged(QString filter);
void eventInserted(int index, EventLogGui *message);
void eventInsertedByUser(int index);
void messageWithFilterFound(int index);
void listAboutToBeReset();
void chatGuiChanged();

View file

@ -26,7 +26,7 @@
DEFINE_ABSTRACT_OBJECT(EventLogProxy)
EventLogProxy::EventLogProxy(QObject *parent) : LimitProxy(parent) {
EventLogProxy::EventLogProxy(QObject *parent) : QSortFilterProxyModel(parent) {
mList = EventLogList::create();
setSourceModel(mList.get());
}
@ -35,58 +35,41 @@ EventLogProxy::~EventLogProxy() {
}
void EventLogProxy::setSourceModel(QAbstractItemModel *model) {
auto oldEventLogList = getListModel<EventLogList>();
auto oldEventLogList = dynamic_cast<EventLogList *>(sourceModel());
if (oldEventLogList) {
disconnect(oldEventLogList, &EventLogList::listAboutToBeReset, this, nullptr);
disconnect(oldEventLogList, &EventLogList::chatGuiChanged, this, nullptr);
disconnect(oldEventLogList, &EventLogList::displayItemsStepChanged, this, nullptr);
disconnect(oldEventLogList, &EventLogList::eventInserted, this, nullptr);
disconnect(oldEventLogList, &EventLogList::messageWithFilterFound, this, nullptr);
disconnect(oldEventLogList, &EventLogList::eventInsertedByUser, this, nullptr);
}
auto newEventLogList = dynamic_cast<EventLogList *>(model);
if (newEventLogList) {
connect(newEventLogList, &EventLogList::listAboutToBeReset, this, &EventLogProxy::listAboutToBeReset);
connect(newEventLogList, &EventLogList::chatGuiChanged, this, &EventLogProxy::chatGuiChanged);
connect(this, &EventLogProxy::displayItemsStepChanged, newEventLogList,
[this, newEventLogList] { newEventLogList->setDisplayItemsStep(mDisplayItemsStep); });
connect(newEventLogList, &EventLogList::eventInserted, this,
[this, newEventLogList](int index, EventLogGui *event) {
invalidate();
int proxyIndex = -1;
if (index != -1) {
proxyIndex = dynamic_cast<SortFilterList *>(sourceModel())
->mapFromSource(newEventLogList->index(index, 0))
.row();
}
loadUntil(proxyIndex);
emit eventInserted(proxyIndex, event);
});
connect(newEventLogList, &EventLogList::messageWithFilterFound, this, [this, newEventLogList](int i) {
connect(this, &EventLogProxy::layoutChanged, newEventLogList, [this, i, newEventLogList] {
disconnect(this, &EventLogProxy::layoutChanged, newEventLogList, nullptr);
auto model = getListModel<EventLogList>();
int proxyIndex =
dynamic_cast<SortFilterList *>(sourceModel())->mapFromSource(newEventLogList->index(i, 0)).row();
if (i != -1) {
loadUntil(proxyIndex);
}
emit indexWithFilterFound(proxyIndex);
});
invalidate();
auto model = dynamic_cast<EventLogList *>(sourceModel());
int proxyIndex = mapFromSource(newEventLogList->index(i, 0)).row();
if (i != -1) {
loadUntil(proxyIndex);
}
emit indexWithFilterFound(proxyIndex);
});
connect(newEventLogList, &EventLogList::eventInsertedByUser, this, [this, newEventLogList](int i) {
int proxyIndex = mapFromSource(newEventLogList->index(i, 0)).row();
emit eventInsertedByUser(proxyIndex);
});
}
setSourceModels(new SortFilterList(model, Qt::DescendingOrder));
sort(0, Qt::DescendingOrder);
QSortFilterProxyModel::setSourceModel(model);
}
ChatGui *EventLogProxy::getChatGui() {
auto model = getListModel<EventLogList>();
auto model = dynamic_cast<EventLogList *>(sourceModel());
if (!mChatGui && model) mChatGui = model->getChat();
return mChatGui;
}
void EventLogProxy::setChatGui(ChatGui *chat) {
getListModel<EventLogList>()->setChatGui(chat);
auto model = dynamic_cast<EventLogList *>(sourceModel());
if (model) model->setChatGui(chat);
}
EventLogGui *EventLogProxy::getEventAtIndex(int i) {
@ -94,29 +77,86 @@ EventLogGui *EventLogProxy::getEventAtIndex(int i) {
return eventCore == nullptr ? nullptr : new EventLogGui(eventCore);
}
int EventLogProxy::getCount() const {
return rowCount();
}
int EventLogProxy::getInitialDisplayItems() const {
return mInitialDisplayItems;
}
void EventLogProxy::setInitialDisplayItems(int initialItems) {
if (mInitialDisplayItems != initialItems) {
mInitialDisplayItems = initialItems;
if (getMaxDisplayItems() <= mInitialDisplayItems) setMaxDisplayItems(initialItems);
if (getDisplayItemsStep() <= 0) setDisplayItemsStep(initialItems);
emit initialDisplayItemsChanged();
}
}
int EventLogProxy::getDisplayCount(int listCount, int maxCount) {
return maxCount >= 0 ? qMin(listCount, maxCount) : listCount;
}
int EventLogProxy::getDisplayCount(int listCount) const {
return getDisplayCount(listCount, mMaxDisplayItems);
}
QSharedPointer<EventLogCore> EventLogProxy::getEventCoreAtIndex(int i) {
return getItemAt<SortFilterList, EventLogList, EventLogCore>(i);
auto model = dynamic_cast<EventLogList *>(sourceModel());
if (model) {
return model->getAt<EventLogCore>(mapToSource(index(i, 0)).row());
}
return nullptr;
}
void EventLogProxy::displayMore() {
auto model = getListModel<EventLogList>();
auto model = dynamic_cast<EventLogList *>(sourceModel());
if (model) {
model->displayMore();
}
}
int EventLogProxy::getMaxDisplayItems() const {
return mMaxDisplayItems;
}
void EventLogProxy::setMaxDisplayItems(int maxItems) {
if (mMaxDisplayItems != maxItems) {
auto model = sourceModel();
int modelCount = model ? model->rowCount() : 0;
int oldCount = getDisplayCount(modelCount);
mMaxDisplayItems = maxItems;
if (getInitialDisplayItems() > mMaxDisplayItems) setInitialDisplayItems(maxItems);
if (getDisplayItemsStep() <= 0) setDisplayItemsStep(maxItems);
emit maxDisplayItemsChanged();
if (model && getDisplayCount(modelCount) != oldCount) {
invalidate();
}
}
}
int EventLogProxy::getDisplayItemsStep() const {
return mDisplayItemsStep;
}
void EventLogProxy::setDisplayItemsStep(int step) {
if (step > 0 && mDisplayItemsStep != step) {
mDisplayItemsStep = step;
emit displayItemsStepChanged();
}
}
void EventLogProxy::loadUntil(int index) {
auto confInfoList = getListModel<EventLogList>();
if (mMaxDisplayItems < index) setMaxDisplayItems(index + mDisplayItemsStep);
}
int EventLogProxy::findFirstUnreadIndex() {
auto eventLogList = getListModel<EventLogList>();
auto eventLogList = dynamic_cast<EventLogList *>(sourceModel());
if (eventLogList) {
auto listIndex = eventLogList->findFirstUnreadIndex();
if (listIndex != -1) {
listIndex =
dynamic_cast<SortFilterList *>(sourceModel())->mapFromSource(eventLogList->index(listIndex, 0)).row();
listIndex = mapFromSource(eventLogList->index(listIndex, 0)).row();
if (mMaxDisplayItems <= listIndex) setMaxDisplayItems(listIndex + mDisplayItemsStep);
return listIndex;
} else {
@ -126,32 +166,43 @@ int EventLogProxy::findFirstUnreadIndex() {
return 0;
}
QString EventLogProxy::getFilterText() const {
return mFilterText;
}
void EventLogProxy::setFilterText(const QString &filter) {
if (mFilterText != filter) {
#if QT_VERSION >= QT_VERSION_CHECK(6, 10, 0)
beginFilterChange();
mFilterText = filter;
endFilterChange();
#else
mFilterText = filter;
invalidateFilter();
#endif
emit filterTextChanged();
}
}
QSharedPointer<EventLogCore> EventLogProxy::getAt(int atIndex) const {
auto model = dynamic_cast<EventLogList *>(sourceModel());
if (model) {
return model->getAt<EventLogCore>(mapToSource(index(atIndex, 0)).row());
}
return nullptr;
}
void EventLogProxy::markIndexAsRead(int proxyIndex) {
auto event = getItemAt<SortFilterList, EventLogList, EventLogCore>(proxyIndex);
auto event = getAt(proxyIndex);
if (event && event->getChatMessageCore()) event->getChatMessageCore()->lMarkAsRead();
}
void EventLogProxy::findIndexCorrespondingToFilter(int startIndex, bool forward, bool isFirstResearch) {
auto filter = getFilterText();
if (filter.isEmpty()) return;
auto eventLogList = getListModel<EventLogList>();
auto eventLogList = dynamic_cast<EventLogList *>(sourceModel());
if (eventLogList) {
auto startEvent = mLastSearchStart;
if (!startEvent) {
startEvent = getItemAt<SortFilterList, EventLogList, EventLogCore>(startIndex);
}
eventLogList->findChatMessageWithFilter(filter, startEvent, forward, isFirstResearch);
auto listIndex = mapToSource(index(startIndex, 0)).row();
eventLogList->findChatMessageWithFilter(filter, listIndex, forward, isFirstResearch);
}
}
bool EventLogProxy::SortFilterList::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const {
auto l = getItemAtSource<EventLogList, EventLogCore>(sourceRow);
return l != nullptr;
}
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;
}

View file

@ -22,19 +22,26 @@
#define EVENT_LIST_PROXY_H_
#include "EventLogList.hpp"
#include "core/proxy/LimitProxy.hpp"
// #include "core/proxy/LimitProxy.hpp"
#include "tool/AbstractObject.hpp"
#include <QSortFilterProxyModel>
// =============================================================================
class ChatGui;
class EventLogProxy : public LimitProxy, public AbstractObject {
class EventLogProxy : public QSortFilterProxyModel, public AbstractObject {
Q_OBJECT
Q_PROPERTY(int count READ getCount NOTIFY countChanged)
Q_PROPERTY(ChatGui *chatGui READ getChatGui WRITE setChatGui NOTIFY chatGuiChanged)
Q_PROPERTY(int initialDisplayItems READ getInitialDisplayItems WRITE setInitialDisplayItems NOTIFY
initialDisplayItemsChanged)
Q_PROPERTY(int maxDisplayItems READ getMaxDisplayItems WRITE setMaxDisplayItems NOTIFY maxDisplayItemsChanged)
Q_PROPERTY(int displayItemsStep READ getDisplayItemsStep WRITE setDisplayItemsStep NOTIFY displayItemsStepChanged)
Q_PROPERTY(QString filterText READ getFilterText WRITE setFilterText NOTIFY filterTextChanged)
public:
DECLARE_SORTFILTER_CLASS()
// DECLARE_SORTFILTER_CLASS()
EventLogProxy(QObject *parent = Q_NULLPTR);
~EventLogProxy();
@ -43,8 +50,27 @@ public:
void setChatGui(ChatGui *chat);
void setSourceModel(QAbstractItemModel *sourceModel) override;
virtual int getCount() const;
static int getDisplayCount(int listCount, int maxCount);
int getDisplayCount(int listCount) const;
int getInitialDisplayItems() const;
void setInitialDisplayItems(int initialItems);
Q_INVOKABLE void displayMore() override;
int getMaxDisplayItems() const;
void setMaxDisplayItems(int maxItems);
int getDisplayItemsStep() const;
void setDisplayItemsStep(int step);
QString getFilterText() const;
void setFilterText(const QString &filter);
// bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const override;
// bool lessThan(const QModelIndex &sourceLeft, const QModelIndex &sourceRight) const override;
QSharedPointer<EventLogCore> getAt(int atIndex) const;
Q_INVOKABLE void displayMore();
Q_INVOKABLE void loadUntil(int index);
Q_INVOKABLE EventLogGui *getEventAtIndex(int i);
QSharedPointer<EventLogCore> getEventCoreAtIndex(int i);
@ -53,15 +79,23 @@ public:
Q_INVOKABLE void findIndexCorrespondingToFilter(int startIndex, bool forward = true, bool isFirstResearch = true);
signals:
void eventInserted(int index, EventLogGui *message);
void eventInsertedByUser(int index);
void indexWithFilterFound(int index);
void listAboutToBeReset();
void chatGuiChanged();
void countChanged();
void initialDisplayItemsChanged();
void maxDisplayItemsChanged();
void displayItemsStepChanged();
void filterTextChanged();
protected:
QSharedPointer<EventLogList> mList;
QSharedPointer<EventLogCore> mLastSearchStart;
ChatGui *mChatGui = nullptr;
int mInitialDisplayItems = -1;
int mMaxDisplayItems = -1;
int mDisplayItemsStep = 5;
QString mFilterText;
DECLARE_ABSTRACT_OBJECT
};

View file

@ -2453,58 +2453,58 @@ Error</extracomment>
<context>
<name>ChatMessagesListView</name>
<message>
<location filename="../../view/Control/Display/Chat/ChatMessagesListView.qml" line="123"/>
<location filename="../../view/Control/Display/Chat/ChatMessagesListView.qml" line="134"/>
<location filename="../../view/Control/Display/Chat/ChatMessagesListView.qml" line="107"/>
<location filename="../../view/Control/Display/Chat/ChatMessagesListView.qml" line="118"/>
<source>popup_info_find_message_title</source>
<extracomment>Find message</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../view/Control/Display/Chat/ChatMessagesListView.qml" line="136"/>
<location filename="../../view/Control/Display/Chat/ChatMessagesListView.qml" line="120"/>
<source>info_popup_no_result_message</source>
<extracomment>No result found</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../view/Control/Display/Chat/ChatMessagesListView.qml" line="128"/>
<location filename="../../view/Control/Display/Chat/ChatMessagesListView.qml" line="112"/>
<source>info_popup_first_result_message</source>
<extracomment>First result reached</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../view/Control/Display/Chat/ChatMessagesListView.qml" line="126"/>
<location filename="../../view/Control/Display/Chat/ChatMessagesListView.qml" line="110"/>
<source>info_popup_last_result_message</source>
<extracomment>Last result reached</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../view/Control/Display/Chat/ChatMessagesListView.qml" line="173"/>
<location filename="../../view/Control/Display/Chat/ChatMessagesListView.qml" line="157"/>
<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="175"/>
<location filename="../../view/Control/Display/Chat/ChatMessagesListView.qml" line="159"/>
<source>unencrypted_conversation_warning</source>
<extracomment>This conversation is not encrypted !</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../view/Control/Display/Chat/ChatMessagesListView.qml" line="186"/>
<location filename="../../view/Control/Display/Chat/ChatMessagesListView.qml" line="170"/>
<source>chat_message_list_encrypted_header_message</source>
<extracomment>Messages in this conversation are e2e encrypted.
Only your correspondent can decrypt them.</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../view/Control/Display/Chat/ChatMessagesListView.qml" line="188"/>
<location filename="../../view/Control/Display/Chat/ChatMessagesListView.qml" line="172"/>
<source>chat_message_list_not_encrypted_header_message</source>
<extracomment>Messages are not end to end encrypted,
may sure you don&apos;t share any sensitive information !</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../view/Control/Display/Chat/ChatMessagesListView.qml" line="228"/>
<location filename="../../view/Control/Display/Chat/ChatMessagesListView.qml" line="212"/>
<source>chat_message_is_writing_info</source>
<extracomment>%1 is writing</extracomment>
<translation type="unfinished"></translation>
@ -3784,58 +3784,58 @@ Error</extracomment>
<context>
<name>EventLogCore</name>
<message>
<location filename="../../core/chat/message/EventLogCore.cpp" line="107"/>
<location filename="../../core/chat/message/EventLogCore.cpp" line="113"/>
<source>conference_created_event</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../core/chat/message/EventLogCore.cpp" line="110"/>
<location filename="../../core/chat/message/EventLogCore.cpp" line="119"/>
<source>conference_created_terminated</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../core/chat/message/EventLogCore.cpp" line="114"/>
<location filename="../../core/chat/message/EventLogCore.cpp" line="123"/>
<source>conference_participant_added_event</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../core/chat/message/EventLogCore.cpp" line="118"/>
<location filename="../../core/chat/message/EventLogCore.cpp" line="127"/>
<source>conference_participant_removed_event</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../core/chat/message/EventLogCore.cpp" line="127"/>
<location filename="../../core/chat/message/EventLogCore.cpp" line="129"/>
<location filename="../../core/chat/message/EventLogCore.cpp" line="136"/>
<location filename="../../core/chat/message/EventLogCore.cpp" line="138"/>
<source>conference_security_event</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../core/chat/message/EventLogCore.cpp" line="136"/>
<location filename="../../core/chat/message/EventLogCore.cpp" line="145"/>
<source>conference_ephemeral_message_enabled_event</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../core/chat/message/EventLogCore.cpp" line="142"/>
<location filename="../../core/chat/message/EventLogCore.cpp" line="151"/>
<source>conference_ephemeral_message_lifetime_changed_event</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../core/chat/message/EventLogCore.cpp" line="147"/>
<location filename="../../core/chat/message/EventLogCore.cpp" line="156"/>
<source>conference_ephemeral_message_disabled_event</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../core/chat/message/EventLogCore.cpp" line="151"/>
<location filename="../../core/chat/message/EventLogCore.cpp" line="160"/>
<source>conference_subject_changed_event</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../core/chat/message/EventLogCore.cpp" line="159"/>
<location filename="../../core/chat/message/EventLogCore.cpp" line="168"/>
<source>conference_participant_unset_admin_event</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../core/chat/message/EventLogCore.cpp" line="155"/>
<location filename="../../core/chat/message/EventLogCore.cpp" line="164"/>
<source>conference_participant_set_admin_event</source>
<translation type="unfinished"></translation>
</message>
@ -5828,42 +5828,42 @@ 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="50"/>
<location filename="../../view/Page/Form/Chat/SelectedChatView.qml" line="48"/>
<source>chat_view_group_call_toast_message</source>
<translation>Start a group call ?</translation>
</message>
<message>
<location filename="../../view/Page/Form/Chat/SelectedChatView.qml" line="133"/>
<location filename="../../view/Page/Form/Chat/SelectedChatView.qml" line="131"/>
<source>unencrypted_conversation_warning</source>
<extracomment>This conversation is not encrypted !</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../view/Page/Form/Chat/SelectedChatView.qml" line="419"/>
<location filename="../../view/Page/Form/Chat/SelectedChatView.qml" line="417"/>
<source>reply_to_label</source>
<extracomment>Reply to %1</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../view/Page/Form/Chat/SelectedChatView.qml" line="619"/>
<location filename="../../view/Page/Form/Chat/SelectedChatView.qml" line="617"/>
<source>shared_medias_title</source>
<extracomment>Shared medias</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../view/Page/Form/Chat/SelectedChatView.qml" line="621"/>
<location filename="../../view/Page/Form/Chat/SelectedChatView.qml" line="619"/>
<source>shared_documents_title</source>
<extracomment>Shared documents</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../view/Page/Form/Chat/SelectedChatView.qml" line="650"/>
<location filename="../../view/Page/Form/Chat/SelectedChatView.qml" line="648"/>
<source>forward_to_title</source>
<extracomment>Forward to</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../view/Page/Form/Chat/SelectedChatView.qml" line="684"/>
<location filename="../../view/Page/Form/Chat/SelectedChatView.qml" line="682"/>
<source>conversations_title</source>
<extracomment>Conversations</extracomment>
<translation>Konversationen</translation>

View file

@ -2425,44 +2425,44 @@ Error</extracomment>
<context>
<name>ChatMessagesListView</name>
<message>
<location filename="../../view/Control/Display/Chat/ChatMessagesListView.qml" line="123"/>
<location filename="../../view/Control/Display/Chat/ChatMessagesListView.qml" line="134"/>
<location filename="../../view/Control/Display/Chat/ChatMessagesListView.qml" line="107"/>
<location filename="../../view/Control/Display/Chat/ChatMessagesListView.qml" line="118"/>
<source>popup_info_find_message_title</source>
<extracomment>Find message</extracomment>
<translation>Find message</translation>
</message>
<message>
<location filename="../../view/Control/Display/Chat/ChatMessagesListView.qml" line="136"/>
<location filename="../../view/Control/Display/Chat/ChatMessagesListView.qml" line="120"/>
<source>info_popup_no_result_message</source>
<extracomment>No result found</extracomment>
<translation>No result found</translation>
</message>
<message>
<location filename="../../view/Control/Display/Chat/ChatMessagesListView.qml" line="128"/>
<location filename="../../view/Control/Display/Chat/ChatMessagesListView.qml" line="112"/>
<source>info_popup_first_result_message</source>
<extracomment>First result reached</extracomment>
<translation>First result reached</translation>
</message>
<message>
<location filename="../../view/Control/Display/Chat/ChatMessagesListView.qml" line="126"/>
<location filename="../../view/Control/Display/Chat/ChatMessagesListView.qml" line="110"/>
<source>info_popup_last_result_message</source>
<extracomment>Last result reached</extracomment>
<translation>Last result reached</translation>
</message>
<message>
<location filename="../../view/Control/Display/Chat/ChatMessagesListView.qml" line="173"/>
<location filename="../../view/Control/Display/Chat/ChatMessagesListView.qml" line="157"/>
<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="175"/>
<location filename="../../view/Control/Display/Chat/ChatMessagesListView.qml" line="159"/>
<source>unencrypted_conversation_warning</source>
<extracomment>This conversation is not encrypted !</extracomment>
<translation>This conversation is not encrypted !</translation>
</message>
<message>
<location filename="../../view/Control/Display/Chat/ChatMessagesListView.qml" line="186"/>
<location filename="../../view/Control/Display/Chat/ChatMessagesListView.qml" line="170"/>
<source>chat_message_list_encrypted_header_message</source>
<extracomment>Messages in this conversation are e2e encrypted.
Only your correspondent can decrypt them.</extracomment>
@ -2470,7 +2470,7 @@ Error</extracomment>
Only your correspondent can decrypt them.</translation>
</message>
<message>
<location filename="../../view/Control/Display/Chat/ChatMessagesListView.qml" line="188"/>
<location filename="../../view/Control/Display/Chat/ChatMessagesListView.qml" line="172"/>
<source>chat_message_list_not_encrypted_header_message</source>
<extracomment>Messages are not end to end encrypted,
may sure you don&apos;t share any sensitive information !</extracomment>
@ -2478,7 +2478,7 @@ Only your correspondent can decrypt them.</translation>
may sure you don&apos;t share any sensitive information !</translation>
</message>
<message>
<location filename="../../view/Control/Display/Chat/ChatMessagesListView.qml" line="228"/>
<location filename="../../view/Control/Display/Chat/ChatMessagesListView.qml" line="212"/>
<source>chat_message_is_writing_info</source>
<extracomment>%1 is writing</extracomment>
<translation>%1 is writing</translation>
@ -3703,59 +3703,59 @@ Only your correspondent can decrypt them.</translation>
<context>
<name>EventLogCore</name>
<message>
<location filename="../../core/chat/message/EventLogCore.cpp" line="107"/>
<location filename="../../core/chat/message/EventLogCore.cpp" line="113"/>
<source>conference_created_event</source>
<translation>You have joined the group</translation>
</message>
<message>
<location filename="../../core/chat/message/EventLogCore.cpp" line="110"/>
<location filename="../../core/chat/message/EventLogCore.cpp" line="119"/>
<source>conference_created_terminated</source>
<translation>You have left the group</translation>
</message>
<message>
<location filename="../../core/chat/message/EventLogCore.cpp" line="114"/>
<location filename="../../core/chat/message/EventLogCore.cpp" line="123"/>
<source>conference_participant_added_event</source>
<translation>%1 has joined</translation>
</message>
<message>
<location filename="../../core/chat/message/EventLogCore.cpp" line="118"/>
<location filename="../../core/chat/message/EventLogCore.cpp" line="127"/>
<source>conference_participant_removed_event</source>
<translation>%1 is no longer in the conversation</translation>
</message>
<message>
<location filename="../../core/chat/message/EventLogCore.cpp" line="155"/>
<location filename="../../core/chat/message/EventLogCore.cpp" line="164"/>
<source>conference_participant_set_admin_event</source>
<translation>%1 is now an admin</translation>
</message>
<message>
<location filename="../../core/chat/message/EventLogCore.cpp" line="159"/>
<location filename="../../core/chat/message/EventLogCore.cpp" line="168"/>
<source>conference_participant_unset_admin_event</source>
<translation>%1 is no longer an admin</translation>
</message>
<message>
<location filename="../../core/chat/message/EventLogCore.cpp" line="127"/>
<location filename="../../core/chat/message/EventLogCore.cpp" line="129"/>
<location filename="../../core/chat/message/EventLogCore.cpp" line="136"/>
<location filename="../../core/chat/message/EventLogCore.cpp" line="138"/>
<source>conference_security_event</source>
<translation>Security level degraded by %1</translation>
</message>
<message>
<location filename="../../core/chat/message/EventLogCore.cpp" line="136"/>
<location filename="../../core/chat/message/EventLogCore.cpp" line="145"/>
<source>conference_ephemeral_message_enabled_event</source>
<translation>Ephemeral messages enabled
Expiration : %1</translation>
</message>
<message>
<location filename="../../core/chat/message/EventLogCore.cpp" line="147"/>
<location filename="../../core/chat/message/EventLogCore.cpp" line="156"/>
<source>conference_ephemeral_message_disabled_event</source>
<translation>Ephemeral messages disabled</translation>
</message>
<message>
<location filename="../../core/chat/message/EventLogCore.cpp" line="151"/>
<location filename="../../core/chat/message/EventLogCore.cpp" line="160"/>
<source>conference_subject_changed_event</source>
<translation>New subject: %1</translation>
</message>
<message>
<location filename="../../core/chat/message/EventLogCore.cpp" line="142"/>
<location filename="../../core/chat/message/EventLogCore.cpp" line="151"/>
<source>conference_ephemeral_message_lifetime_changed_event</source>
<translation>Ephemeral messages updated
Expiration : %1</translation>
@ -5723,42 +5723,42 @@ 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="50"/>
<location filename="../../view/Page/Form/Chat/SelectedChatView.qml" line="48"/>
<source>chat_view_group_call_toast_message</source>
<translation>Start a group call ?</translation>
</message>
<message>
<location filename="../../view/Page/Form/Chat/SelectedChatView.qml" line="133"/>
<location filename="../../view/Page/Form/Chat/SelectedChatView.qml" line="131"/>
<source>unencrypted_conversation_warning</source>
<extracomment>This conversation is not encrypted !</extracomment>
<translation>This conversation is not encrypted !</translation>
</message>
<message>
<location filename="../../view/Page/Form/Chat/SelectedChatView.qml" line="419"/>
<location filename="../../view/Page/Form/Chat/SelectedChatView.qml" line="417"/>
<source>reply_to_label</source>
<extracomment>Reply to %1</extracomment>
<translation>Reply to %1</translation>
</message>
<message>
<location filename="../../view/Page/Form/Chat/SelectedChatView.qml" line="619"/>
<location filename="../../view/Page/Form/Chat/SelectedChatView.qml" line="617"/>
<source>shared_medias_title</source>
<extracomment>Shared medias</extracomment>
<translation>Shared medias</translation>
</message>
<message>
<location filename="../../view/Page/Form/Chat/SelectedChatView.qml" line="621"/>
<location filename="../../view/Page/Form/Chat/SelectedChatView.qml" line="619"/>
<source>shared_documents_title</source>
<extracomment>Shared documents</extracomment>
<translation>Shared documents</translation>
</message>
<message>
<location filename="../../view/Page/Form/Chat/SelectedChatView.qml" line="650"/>
<location filename="../../view/Page/Form/Chat/SelectedChatView.qml" line="648"/>
<source>forward_to_title</source>
<extracomment>Forward to</extracomment>
<translation>Froward to</translation>
</message>
<message>
<location filename="../../view/Page/Form/Chat/SelectedChatView.qml" line="684"/>
<location filename="../../view/Page/Form/Chat/SelectedChatView.qml" line="682"/>
<source>conversations_title</source>
<extracomment>Conversations</extracomment>
<translation>Conversations</translation>

View file

@ -2425,44 +2425,44 @@ Error</extracomment>
<context>
<name>ChatMessagesListView</name>
<message>
<location filename="../../view/Control/Display/Chat/ChatMessagesListView.qml" line="123"/>
<location filename="../../view/Control/Display/Chat/ChatMessagesListView.qml" line="134"/>
<location filename="../../view/Control/Display/Chat/ChatMessagesListView.qml" line="107"/>
<location filename="../../view/Control/Display/Chat/ChatMessagesListView.qml" line="118"/>
<source>popup_info_find_message_title</source>
<extracomment>Find message</extracomment>
<translation>Trouver un message</translation>
</message>
<message>
<location filename="../../view/Control/Display/Chat/ChatMessagesListView.qml" line="136"/>
<location filename="../../view/Control/Display/Chat/ChatMessagesListView.qml" line="120"/>
<source>info_popup_no_result_message</source>
<extracomment>No result found</extracomment>
<translation>Aucun résultat trouvé</translation>
</message>
<message>
<location filename="../../view/Control/Display/Chat/ChatMessagesListView.qml" line="128"/>
<location filename="../../view/Control/Display/Chat/ChatMessagesListView.qml" line="112"/>
<source>info_popup_first_result_message</source>
<extracomment>First result reached</extracomment>
<translation>Premier résultat atteint</translation>
</message>
<message>
<location filename="../../view/Control/Display/Chat/ChatMessagesListView.qml" line="126"/>
<location filename="../../view/Control/Display/Chat/ChatMessagesListView.qml" line="110"/>
<source>info_popup_last_result_message</source>
<extracomment>Last result reached</extracomment>
<translation>Dernier résultat atteint</translation>
</message>
<message>
<location filename="../../view/Control/Display/Chat/ChatMessagesListView.qml" line="173"/>
<location filename="../../view/Control/Display/Chat/ChatMessagesListView.qml" line="157"/>
<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="175"/>
<location filename="../../view/Control/Display/Chat/ChatMessagesListView.qml" line="159"/>
<source>unencrypted_conversation_warning</source>
<extracomment>This conversation is not encrypted !</extracomment>
<translation>Cette conversation n&apos;est pas chiffrée !</translation>
</message>
<message>
<location filename="../../view/Control/Display/Chat/ChatMessagesListView.qml" line="186"/>
<location filename="../../view/Control/Display/Chat/ChatMessagesListView.qml" line="170"/>
<source>chat_message_list_encrypted_header_message</source>
<extracomment>Messages in this conversation are e2e encrypted.
Only your correspondent can decrypt them.</extracomment>
@ -2470,7 +2470,7 @@ Error</extracomment>
en bout. Seul votre correspondant peut les déchiffrer.</translation>
</message>
<message>
<location filename="../../view/Control/Display/Chat/ChatMessagesListView.qml" line="188"/>
<location filename="../../view/Control/Display/Chat/ChatMessagesListView.qml" line="172"/>
<source>chat_message_list_not_encrypted_header_message</source>
<extracomment>Messages are not end to end encrypted,
may sure you don&apos;t share any sensitive information !</extracomment>
@ -2478,7 +2478,7 @@ en bout. Seul votre correspondant peut les déchiffrer.</translation>
assurez-vous de ne pas partager dinformations sensibles !</translation>
</message>
<message>
<location filename="../../view/Control/Display/Chat/ChatMessagesListView.qml" line="228"/>
<location filename="../../view/Control/Display/Chat/ChatMessagesListView.qml" line="212"/>
<source>chat_message_is_writing_info</source>
<extracomment>%1 is writing</extracomment>
<translation>%1 est en train d&apos;écrire</translation>
@ -3703,60 +3703,60 @@ en bout. Seul votre correspondant peut les déchiffrer.</translation>
<context>
<name>EventLogCore</name>
<message>
<location filename="../../core/chat/message/EventLogCore.cpp" line="107"/>
<location filename="../../core/chat/message/EventLogCore.cpp" line="113"/>
<source>conference_created_event</source>
<translation>Vous avez rejoint le groupe</translation>
</message>
<message>
<location filename="../../core/chat/message/EventLogCore.cpp" line="110"/>
<location filename="../../core/chat/message/EventLogCore.cpp" line="119"/>
<source>conference_created_terminated</source>
<translation>Vous avez quitté le groupe</translation>
</message>
<message>
<location filename="../../core/chat/message/EventLogCore.cpp" line="114"/>
<location filename="../../core/chat/message/EventLogCore.cpp" line="123"/>
<source>conference_participant_added_event</source>
<translation>%1 a rejoint le groupe</translation>
</message>
<message>
<location filename="../../core/chat/message/EventLogCore.cpp" line="118"/>
<location filename="../../core/chat/message/EventLogCore.cpp" line="127"/>
<source>conference_participant_removed_event</source>
<translation>%1 ne fait plus partie du groupe</translation>
</message>
<message>
<location filename="../../core/chat/message/EventLogCore.cpp" line="127"/>
<location filename="../../core/chat/message/EventLogCore.cpp" line="129"/>
<location filename="../../core/chat/message/EventLogCore.cpp" line="136"/>
<location filename="../../core/chat/message/EventLogCore.cpp" line="138"/>
<source>conference_security_event</source>
<translation>Niveau de sécurité dégradé par %1</translation>
</message>
<message>
<location filename="../../core/chat/message/EventLogCore.cpp" line="136"/>
<location filename="../../core/chat/message/EventLogCore.cpp" line="145"/>
<source>conference_ephemeral_message_enabled_event</source>
<translation>Messages éphémères activés
Expiration : %1</translation>
</message>
<message>
<location filename="../../core/chat/message/EventLogCore.cpp" line="142"/>
<location filename="../../core/chat/message/EventLogCore.cpp" line="151"/>
<source>conference_ephemeral_message_lifetime_changed_event</source>
<translation>Messages éphémères mis à jour
Expiration : %1</translation>
</message>
<message>
<location filename="../../core/chat/message/EventLogCore.cpp" line="147"/>
<location filename="../../core/chat/message/EventLogCore.cpp" line="156"/>
<source>conference_ephemeral_message_disabled_event</source>
<translation>Messages éphémères désactivés</translation>
</message>
<message>
<location filename="../../core/chat/message/EventLogCore.cpp" line="151"/>
<location filename="../../core/chat/message/EventLogCore.cpp" line="160"/>
<source>conference_subject_changed_event</source>
<translation>Nouveau sujet : %1</translation>
</message>
<message>
<location filename="../../core/chat/message/EventLogCore.cpp" line="159"/>
<location filename="../../core/chat/message/EventLogCore.cpp" line="168"/>
<source>conference_participant_unset_admin_event</source>
<translation>%1 n&apos;est plus admin</translation>
</message>
<message>
<location filename="../../core/chat/message/EventLogCore.cpp" line="155"/>
<location filename="../../core/chat/message/EventLogCore.cpp" line="164"/>
<source>conference_participant_set_admin_event</source>
<translation>%1 est maintenant admin</translation>
</message>
@ -5723,42 +5723,42 @@ 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="50"/>
<location filename="../../view/Page/Form/Chat/SelectedChatView.qml" line="48"/>
<source>chat_view_group_call_toast_message</source>
<translation>Démarrer un appel de groupe ?</translation>
</message>
<message>
<location filename="../../view/Page/Form/Chat/SelectedChatView.qml" line="133"/>
<location filename="../../view/Page/Form/Chat/SelectedChatView.qml" line="131"/>
<source>unencrypted_conversation_warning</source>
<extracomment>This conversation is not encrypted !</extracomment>
<translation>Cette conversation n&apos;est pas chiffrée !</translation>
</message>
<message>
<location filename="../../view/Page/Form/Chat/SelectedChatView.qml" line="419"/>
<location filename="../../view/Page/Form/Chat/SelectedChatView.qml" line="417"/>
<source>reply_to_label</source>
<extracomment>Reply to %1</extracomment>
<translation>Réponse à %1</translation>
</message>
<message>
<location filename="../../view/Page/Form/Chat/SelectedChatView.qml" line="619"/>
<location filename="../../view/Page/Form/Chat/SelectedChatView.qml" line="617"/>
<source>shared_medias_title</source>
<extracomment>Shared medias</extracomment>
<translation>Médias partagés</translation>
</message>
<message>
<location filename="../../view/Page/Form/Chat/SelectedChatView.qml" line="621"/>
<location filename="../../view/Page/Form/Chat/SelectedChatView.qml" line="619"/>
<source>shared_documents_title</source>
<extracomment>Shared documents</extracomment>
<translation>Documents partagés</translation>
</message>
<message>
<location filename="../../view/Page/Form/Chat/SelectedChatView.qml" line="650"/>
<location filename="../../view/Page/Form/Chat/SelectedChatView.qml" line="648"/>
<source>forward_to_title</source>
<extracomment>Forward to</extracomment>
<translation>Transférer à</translation>
</message>
<message>
<location filename="../../view/Page/Form/Chat/SelectedChatView.qml" line="684"/>
<location filename="../../view/Page/Form/Chat/SelectedChatView.qml" line="682"/>
<source>conversations_title</source>
<extracomment>Conversations</extracomment>
<translation>Conversations</translation>

View file

@ -18,6 +18,7 @@ ListView {
property real busyIndicatorSize: Utils.getSizeWithScreenRatio(60)
property bool loading: false
property bool isEncrypted: chat && chat.core.isEncrypted
highlightFollowsCurrentItem: false
verticalLayoutDirection: ListView.BottomToTop
signal showReactionsForMessageRequested(ChatMessageGui chatMessage)
@ -40,24 +41,16 @@ ListView {
property bool searchForward: true
onFindIndexWithFilter: (forward) => {
searchForward = forward
eventLogProxy.findIndexCorrespondingToFilter(currentIndex, forward, false)
}
Component.onCompleted: {
Qt.callLater(function() {
var index = eventLogProxy.findFirstUnreadIndex()
positionViewAtIndex(index, ListView.Beginning)
eventLogProxy.markIndexAsRead(index)
})
eventLogProxy.findIndexCorrespondingToFilter(currentIndex, searchForward, false)
}
Button {
visible: !mainItem.lastItemVisible
icon.source: AppIcons.downArrow
leftPadding: Utils.getSizeWithScreenRatio(16)
rightPadding: Utils.getSizeWithScreenRatio(16)
topPadding: Utils.getSizeWithScreenRatio(16)
bottomPadding: Utils.getSizeWithScreenRatio(16)
leftPadding: Utils.getSizeWithScreenRatio(20)
rightPadding: Utils.getSizeWithScreenRatio(20)
topPadding: Utils.getSizeWithScreenRatio(20)
bottomPadding: Utils.getSizeWithScreenRatio(20)
anchors.bottom: parent.bottom
style: ButtonStyle.main
anchors.right: parent.right
@ -65,20 +58,24 @@ ListView {
anchors.rightMargin: Utils.getSizeWithScreenRatio(18)
onClicked: {
var index = eventLogProxy.findFirstUnreadIndex()
mainItem.positionViewAtIndex(index, ListView.Beginning)
mainItem.positionViewAtIndex(index, ListView.Contain)
eventLogProxy.markIndexAsRead(index)
}
UnreadNotification {
anchors.top: parent.top
anchors.right: parent.right
anchors.topMargin: Utils.getSizeWithScreenRatio(-5)
anchors.rightMargin: Utils.getSizeWithScreenRatio(-5)
unread: mainItem.chat?.core.unreadMessagesCount || 0
}
}
onAtYEndChanged: if (atYEnd && chat) {
chat.core.lMarkAsRead()
}
// Workaround : check if there is already items in the list
// so this function is only called when the user actually scroll
// the view till the begining
onAtYBeginningChanged: if (atYBeginning && count !== 0) {
eventLogProxy.displayMore()
}
onAtYEndChanged: if (atYEnd && chat) {
chat.core.lMarkAsRead()
}
model: EventLogProxy {
id: eventLogProxy
@ -86,23 +83,18 @@ ListView {
filterText: mainItem.filterText
initialDisplayItems: 20
displayItemsStep: 20
onEventInserted: (index, gui) => {
if (!mainItem.visible) return
if(mainItem.lastItemVisible) {
mainItem.positionViewAtIndex(index, ListView.Beginning)
markIndexAsRead(index)
}
}
onModelAboutToBeReset: {
loading = true
}
onModelReset: {
loading = false
var index = eventLogProxy.findFirstUnreadIndex()
positionViewAtIndex(index, ListView.Beginning)
mainItem.positionViewAtIndex(index, ListView.Contain)
eventLogProxy.markIndexAsRead(index)
}
onChatGuiChanged: forceLayout()
onEventInsertedByUser: (index) => {
mainItem.positionViewAtIndex(index, ListView.Beginning)
}
onIndexWithFilterFound: (index) => {
if (index !== -1) {
currentIndex = index
@ -249,9 +241,10 @@ ListView {
}
}
Component.onCompleted: {
if (index === 0) mainItem.lastItemVisible = isFullyVisible
if (index === 0) {
mainItem.lastItemVisible = isFullyVisible
}
}
// onYChanged: if (index === 0) mainItem.lastItemVisible = isFullyVisible
chat: mainItem.chat
searchedTextPart: mainItem.filterText
maxWidth: Math.round(mainItem.width * (3/4))

View file

@ -27,13 +27,11 @@ FocusScope {
signal groupCall()
onActiveFocusChanged: if(activeFocus) {
console.log("selected has active focus, mark as read")
chat.core.lMarkAsRead()
if (chatMessagesListView.lastItemVisible) chat.core.lMarkAsRead()
}
MouseArea{
anchors.fill: parent
onPressed: {
console.log("selected chat view pressed")
forceActiveFocus()
}
}