mirror of
https://gitlab.linphone.org/BC/public/linphone-desktop.git
synced 2026-01-17 11:28:07 +00:00
Add events to chat
This commit is contained in:
parent
672ae55ea6
commit
460c0334c4
24 changed files with 908 additions and 382 deletions
|
|
@ -54,9 +54,10 @@
|
|||
#include "core/call/CallProxy.hpp"
|
||||
#include "core/camera/CameraGui.hpp"
|
||||
#include "core/chat/ChatProxy.hpp"
|
||||
#include "core/chat/message/EventLogGui.hpp"
|
||||
#include "core/chat/message/ChatMessageGui.hpp"
|
||||
#include "core/chat/message/ChatMessageList.hpp"
|
||||
#include "core/chat/message/ChatMessageProxy.hpp"
|
||||
#include "core/chat/message/EventLogList.hpp"
|
||||
#include "core/chat/message/EventLogProxy.hpp"
|
||||
#include "core/conference/ConferenceGui.hpp"
|
||||
#include "core/conference/ConferenceInfoGui.hpp"
|
||||
#include "core/conference/ConferenceInfoProxy.hpp"
|
||||
|
|
@ -661,9 +662,10 @@ void App::initCppInterfaces() {
|
|||
qmlRegisterType<ChatList>(Constants::MainQmlUri, 1, 0, "ChatList");
|
||||
qmlRegisterType<ChatProxy>(Constants::MainQmlUri, 1, 0, "ChatProxy");
|
||||
qmlRegisterType<ChatGui>(Constants::MainQmlUri, 1, 0, "ChatGui");
|
||||
qmlRegisterType<ChatMessageGui>(Constants::MainQmlUri, 1, 0, "ChatMessageGui");
|
||||
qmlRegisterType<ChatMessageList>(Constants::MainQmlUri, 1, 0, "ChatMessageList");
|
||||
qmlRegisterType<ChatMessageProxy>(Constants::MainQmlUri, 1, 0, "ChatMessageProxy");
|
||||
qmlRegisterType<EventLogGui>(Constants::MainQmlUri, 1, 0, "EventLogGui");
|
||||
qmlRegisterType<ChatMessageGui>(Constants::MainQmlUri, 1, 0, "ChatMessageGui");
|
||||
qmlRegisterType<EventLogList>(Constants::MainQmlUri, 1, 0, "EventLogList");
|
||||
qmlRegisterType<EventLogProxy>(Constants::MainQmlUri, 1, 0, "EventLogProxy");
|
||||
qmlRegisterUncreatableType<ConferenceCore>(Constants::MainQmlUri, 1, 0, "ConferenceCore",
|
||||
QLatin1String("Uncreatable"));
|
||||
qmlRegisterType<ConferenceGui>(Constants::MainQmlUri, 1, 0, "ConferenceGui");
|
||||
|
|
|
|||
|
|
@ -25,8 +25,10 @@ list(APPEND _LINPHONEAPP_SOURCES
|
|||
core/chat/ChatProxy.cpp
|
||||
core/chat/message/ChatMessageCore.cpp
|
||||
core/chat/message/ChatMessageGui.cpp
|
||||
core/chat/message/ChatMessageList.cpp
|
||||
core/chat/message/ChatMessageProxy.cpp
|
||||
core/chat/message/EventLogCore.cpp
|
||||
core/chat/message/EventLogGui.cpp
|
||||
core/chat/message/EventLogList.cpp
|
||||
core/chat/message/EventLogProxy.cpp
|
||||
core/emoji/EmojiModel.cpp
|
||||
core/fps-counter/FPSCounter.cpp
|
||||
core/friend/FriendCore.cpp
|
||||
|
|
|
|||
|
|
@ -76,25 +76,29 @@ ChatCore::ChatCore(const std::shared_ptr<linphone::ChatRoom> &chatRoom) : QObjec
|
|||
mChatModel->setSelf(mChatModel);
|
||||
auto lastMessage = chatRoom->getLastMessageInHistory();
|
||||
mLastMessage = lastMessage ? ChatMessageCore::create(lastMessage) : nullptr;
|
||||
auto history = chatRoom->getHistory(0, (int)linphone::ChatRoom::HistoryFilter::ChatMessage);
|
||||
std::list<std::shared_ptr<linphone::ChatMessage>> lHistory;
|
||||
|
||||
int filter = mIsGroupChat ? static_cast<int>(linphone::ChatRoom::HistoryFilter::ChatMessage) |
|
||||
static_cast<int>(linphone::ChatRoom::HistoryFilter::InfoNoDevice)
|
||||
: static_cast<int>(linphone::ChatRoom::HistoryFilter::ChatMessage);
|
||||
|
||||
auto history = chatRoom->getHistory(0, filter);
|
||||
std::list<std::shared_ptr<linphone::EventLog>> lHistory;
|
||||
for (auto &eventLog : history) {
|
||||
if (eventLog->getChatMessage()) lHistory.push_back(eventLog->getChatMessage());
|
||||
lHistory.push_back(eventLog);
|
||||
}
|
||||
QList<QSharedPointer<ChatMessageCore>> messageList;
|
||||
for (auto &message : lHistory) {
|
||||
if (!message) continue;
|
||||
auto chatMessage = ChatMessageCore::create(message);
|
||||
messageList.append(chatMessage);
|
||||
QList<QSharedPointer<EventLogCore>> eventList;
|
||||
for (auto &event : lHistory) {
|
||||
auto eventLogCore = EventLogCore::create(event);
|
||||
eventList.append(eventLogCore);
|
||||
}
|
||||
resetChatMessageList(messageList);
|
||||
resetEventLogList(eventList);
|
||||
mIdentifier = Utils::coreStringToAppString(chatRoom->getIdentifier());
|
||||
mChatRoomState = LinphoneEnums::fromLinphone(chatRoom->getState());
|
||||
mIsEncrypted = chatRoom->hasCapability((int)linphone::ChatRoom::Capabilities::Encrypted);
|
||||
mIsReadOnly = chatRoom->isReadOnly();
|
||||
connect(this, &ChatCore::messageListChanged, this, &ChatCore::lUpdateLastMessage);
|
||||
connect(this, &ChatCore::messagesInserted, this, &ChatCore::lUpdateLastMessage);
|
||||
connect(this, &ChatCore::messageRemoved, this, &ChatCore::lUpdateLastMessage);
|
||||
connect(this, &ChatCore::eventListChanged, this, &ChatCore::lUpdateLastMessage);
|
||||
connect(this, &ChatCore::eventsInserted, this, &ChatCore::lUpdateLastMessage);
|
||||
connect(this, &ChatCore::eventRemoved, this, &ChatCore::lUpdateLastMessage);
|
||||
}
|
||||
|
||||
ChatCore::~ChatCore() {
|
||||
|
|
@ -112,7 +116,7 @@ void ChatCore::setSelf(QSharedPointer<ChatCore> me) {
|
|||
&ChatCore::lLeave, [this]() { mChatModelConnection->invokeToModel([this]() { mChatModel->leave(); }); });
|
||||
mChatModelConnection->makeConnectToModel(&ChatModel::historyDeleted, [this]() {
|
||||
mChatModelConnection->invokeToCore([this]() {
|
||||
clearMessagesList();
|
||||
clearEventLogList();
|
||||
//: Deleted
|
||||
Utils::showInformationPopup(tr("info_toast_deleted_title"),
|
||||
//: Message history has been deleted
|
||||
|
|
@ -148,36 +152,30 @@ void ChatCore::setSelf(QSharedPointer<ChatCore> me) {
|
|||
});
|
||||
});
|
||||
|
||||
mChatModelConnection->makeConnectToModel(&ChatModel::chatMessageReceived,
|
||||
mChatModelConnection->makeConnectToModel(&ChatModel::chatMessageReceived, // TODO onNewEvent?
|
||||
[this](const std::shared_ptr<linphone::ChatRoom> &chatRoom,
|
||||
const std::shared_ptr<const linphone::EventLog> &eventLog) {
|
||||
if (mChatModel->getMonitor() != chatRoom) return;
|
||||
auto message = eventLog->getChatMessage();
|
||||
qDebug() << "EVENT LOG RECEIVED IN CHATROOM" << mChatModel->getTitle();
|
||||
if (message) {
|
||||
auto newMessage = ChatMessageCore::create(message);
|
||||
mChatModelConnection->invokeToCore([this, newMessage]() {
|
||||
appendMessageToMessageList(newMessage);
|
||||
emit lUpdateUnreadCount();
|
||||
emit lUpdateLastUpdatedTime();
|
||||
});
|
||||
}
|
||||
auto event = EventLogCore::create(eventLog);
|
||||
mChatModelConnection->invokeToCore([this, event]() {
|
||||
appendEventLogToEventLogList(event);
|
||||
emit lUpdateUnreadCount();
|
||||
emit lUpdateLastUpdatedTime();
|
||||
});
|
||||
});
|
||||
mChatModelConnection->makeConnectToModel(
|
||||
&ChatModel::chatMessagesReceived, [this](const std::shared_ptr<linphone::ChatRoom> &chatRoom,
|
||||
const std::list<std::shared_ptr<linphone::EventLog>> &chatMessages) {
|
||||
const std::list<std::shared_ptr<linphone::EventLog>> &eventsLog) {
|
||||
if (mChatModel->getMonitor() != chatRoom) return;
|
||||
qDebug() << "EVENT LOGS RECEIVED IN CHATROOM" << mChatModel->getTitle();
|
||||
QList<QSharedPointer<ChatMessageCore>> list;
|
||||
for (auto &m : chatMessages) {
|
||||
auto message = m->getChatMessage();
|
||||
if (message) {
|
||||
auto newMessage = ChatMessageCore::create(message);
|
||||
list.push_back(newMessage);
|
||||
}
|
||||
QList<QSharedPointer<EventLogCore>> list;
|
||||
for (auto &e : eventsLog) {
|
||||
auto event = EventLogCore::create(e);
|
||||
list.push_back(event);
|
||||
}
|
||||
mChatModelConnection->invokeToCore([this, list]() {
|
||||
appendMessagesToMessageList(list);
|
||||
appendEventLogsToEventLogList(list);
|
||||
emit lUpdateUnreadCount();
|
||||
emit lUpdateLastUpdatedTime();
|
||||
});
|
||||
|
|
@ -211,11 +209,8 @@ void ChatCore::setSelf(QSharedPointer<ChatCore> me) {
|
|||
mChatModelConnection->makeConnectToModel(
|
||||
&ChatModel::chatMessageSending, [this](const std::shared_ptr<linphone::ChatRoom> &chatRoom,
|
||||
const std::shared_ptr<const linphone::EventLog> &eventLog) {
|
||||
auto message = eventLog->getChatMessage();
|
||||
if (message) {
|
||||
auto newMessage = ChatMessageCore::create(message);
|
||||
mChatModelConnection->invokeToCore([this, newMessage]() { appendMessageToMessageList(newMessage); });
|
||||
}
|
||||
auto event = EventLogCore::create(eventLog);
|
||||
mChatModelConnection->invokeToCore([this, event]() { appendEventLogToEventLogList(event); });
|
||||
});
|
||||
mChatModelConnection->makeConnectToCore(
|
||||
&ChatCore::lCompose, [this]() { mChatModelConnection->invokeToModel([this]() { mChatModel->compose(); }); });
|
||||
|
|
@ -333,10 +328,6 @@ ChatMessageGui *ChatCore::getLastMessage() const {
|
|||
return mLastMessage ? new ChatMessageGui(mLastMessage) : nullptr;
|
||||
}
|
||||
|
||||
QSharedPointer<ChatMessageCore> ChatCore::getLastMessageCore() const {
|
||||
return mLastMessage;
|
||||
}
|
||||
|
||||
void ChatCore::setLastMessage(QSharedPointer<ChatMessageCore> lastMessage) {
|
||||
if (mLastMessage != lastMessage) {
|
||||
disconnect(mLastMessage.get());
|
||||
|
|
@ -357,45 +348,45 @@ void ChatCore::setUnreadMessagesCount(int count) {
|
|||
}
|
||||
}
|
||||
|
||||
QList<QSharedPointer<ChatMessageCore>> ChatCore::getChatMessageList() const {
|
||||
return mChatMessageList;
|
||||
QList<QSharedPointer<EventLogCore>> ChatCore::getEventLogList() const {
|
||||
return mEventLogList;
|
||||
}
|
||||
|
||||
void ChatCore::resetChatMessageList(QList<QSharedPointer<ChatMessageCore>> list) {
|
||||
mChatMessageList = list;
|
||||
emit messageListChanged();
|
||||
void ChatCore::resetEventLogList(QList<QSharedPointer<EventLogCore>> list) {
|
||||
mEventLogList = list;
|
||||
emit eventListChanged();
|
||||
}
|
||||
|
||||
void ChatCore::appendMessagesToMessageList(QList<QSharedPointer<ChatMessageCore>> list) {
|
||||
void ChatCore::appendEventLogsToEventLogList(QList<QSharedPointer<EventLogCore>> list) {
|
||||
int nbAdded = 0;
|
||||
for (auto &message : list) {
|
||||
if (mChatMessageList.contains(message)) continue;
|
||||
mChatMessageList.append(message);
|
||||
for (auto &e : list) {
|
||||
if (mEventLogList.contains(e)) continue;
|
||||
mEventLogList.append(e);
|
||||
++nbAdded;
|
||||
}
|
||||
if (nbAdded > 0) emit messagesInserted(list);
|
||||
if (nbAdded > 0) emit eventsInserted(list);
|
||||
}
|
||||
|
||||
void ChatCore::appendMessageToMessageList(QSharedPointer<ChatMessageCore> message) {
|
||||
if (mChatMessageList.contains(message)) return;
|
||||
mChatMessageList.append(message);
|
||||
emit messagesInserted({message});
|
||||
void ChatCore::appendEventLogToEventLogList(QSharedPointer<EventLogCore> e) {
|
||||
if (mEventLogList.contains(e)) return;
|
||||
mEventLogList.append(e);
|
||||
emit eventsInserted({e});
|
||||
}
|
||||
|
||||
void ChatCore::removeMessagesFromMessageList(QList<QSharedPointer<ChatMessageCore>> list) {
|
||||
void ChatCore::removeEventLogsFromEventLogList(QList<QSharedPointer<EventLogCore>> list) {
|
||||
int nbRemoved = 0;
|
||||
for (auto &message : list) {
|
||||
if (mChatMessageList.contains(message)) {
|
||||
mChatMessageList.removeAll(message);
|
||||
for (auto &e : list) {
|
||||
if (mEventLogList.contains(e)) {
|
||||
mEventLogList.removeAll(e);
|
||||
++nbRemoved;
|
||||
}
|
||||
}
|
||||
if (nbRemoved > 0) emit messageRemoved();
|
||||
if (nbRemoved > 0) emit eventRemoved();
|
||||
}
|
||||
|
||||
void ChatCore::clearMessagesList() {
|
||||
mChatMessageList.clear();
|
||||
emit messageListChanged();
|
||||
void ChatCore::clearEventLogList() {
|
||||
mEventLogList.clear();
|
||||
emit eventListChanged();
|
||||
}
|
||||
|
||||
QString ChatCore::getComposingName() const {
|
||||
|
|
|
|||
|
|
@ -21,7 +21,8 @@
|
|||
#ifndef CHAT_CORE_H_
|
||||
#define CHAT_CORE_H_
|
||||
|
||||
#include "core/chat/message/ChatMessageGui.hpp"
|
||||
#include "core/chat/message/EventLogGui.hpp"
|
||||
#include "message/ChatMessageGui.hpp"
|
||||
#include "model/chat/ChatModel.hpp"
|
||||
#include "model/search/MagicSearchModel.hpp"
|
||||
#include "tool/LinphoneEnums.hpp"
|
||||
|
|
@ -30,6 +31,8 @@
|
|||
#include <QSharedPointer>
|
||||
#include <linphone++/linphone.hh>
|
||||
|
||||
class EventLogCore;
|
||||
|
||||
class ChatCore : public QObject, public AbstractObject {
|
||||
Q_OBJECT
|
||||
|
||||
|
|
@ -94,12 +97,12 @@ public:
|
|||
QString getChatRoomAddress() const;
|
||||
QString getPeerAddress() const;
|
||||
|
||||
QList<QSharedPointer<ChatMessageCore>> getChatMessageList() const;
|
||||
void resetChatMessageList(QList<QSharedPointer<ChatMessageCore>> list);
|
||||
void appendMessageToMessageList(QSharedPointer<ChatMessageCore> message);
|
||||
void appendMessagesToMessageList(QList<QSharedPointer<ChatMessageCore>> list);
|
||||
void removeMessagesFromMessageList(QList<QSharedPointer<ChatMessageCore>> list);
|
||||
void clearMessagesList();
|
||||
QList<QSharedPointer<EventLogCore>> getEventLogList() const;
|
||||
void resetEventLogList(QList<QSharedPointer<EventLogCore>> list);
|
||||
void appendEventLogToEventLogList(QSharedPointer<EventLogCore> event);
|
||||
void appendEventLogsToEventLogList(QList<QSharedPointer<EventLogCore>> list);
|
||||
void removeEventLogsFromEventLogList(QList<QSharedPointer<EventLogCore>> list);
|
||||
void clearEventLogList();
|
||||
|
||||
QString getAvatarUri() const;
|
||||
void setAvatarUri(QString avatarUri);
|
||||
|
|
@ -118,9 +121,9 @@ signals:
|
|||
void lastMessageChanged();
|
||||
void titleChanged(QString title);
|
||||
void unreadMessagesCountChanged(int count);
|
||||
void messageListChanged();
|
||||
void messagesInserted(QList<QSharedPointer<ChatMessageCore>> list);
|
||||
void messageRemoved();
|
||||
void eventListChanged();
|
||||
void eventsInserted(QList<QSharedPointer<EventLogCore>> list);
|
||||
void eventRemoved();
|
||||
void avatarUriChanged();
|
||||
void deleted();
|
||||
void composingUserChanged();
|
||||
|
|
@ -157,7 +160,7 @@ private:
|
|||
LinphoneEnums::ChatRoomState mChatRoomState;
|
||||
std::shared_ptr<ChatModel> mChatModel;
|
||||
QSharedPointer<ChatMessageCore> mLastMessage;
|
||||
QList<QSharedPointer<ChatMessageCore>> mChatMessageList;
|
||||
QList<QSharedPointer<EventLogCore>> mEventLogList;
|
||||
QSharedPointer<SafeConnection<ChatCore, ChatModel>> mChatModelConnection;
|
||||
|
||||
DECLARE_ABSTRACT_OBJECT
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@
|
|||
#ifndef CHATMESSAGECORE_H_
|
||||
#define CHATMESSAGECORE_H_
|
||||
|
||||
#include "EventLogCore.hpp"
|
||||
#include "core/conference/ConferenceInfoCore.hpp"
|
||||
#include "core/conference/ConferenceInfoGui.hpp"
|
||||
#include "model/chat/message/ChatMessageModel.hpp"
|
||||
|
|
@ -48,6 +49,7 @@ public:
|
|||
};
|
||||
|
||||
class ChatCore;
|
||||
class EventLogCore;
|
||||
|
||||
class ChatMessageCore : public QObject, public AbstractObject {
|
||||
Q_OBJECT
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@
|
|||
*/
|
||||
|
||||
#include "ChatMessageGui.hpp"
|
||||
#include "ChatMessageCore.hpp"
|
||||
#include "core/App.hpp"
|
||||
|
||||
DEFINE_ABSTRACT_OBJECT(ChatMessageGui)
|
||||
|
|
|
|||
|
|
@ -1,136 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2010-2024 Belledonne Communications SARL.
|
||||
*
|
||||
* This file is part of linphone-desktop
|
||||
* (see https://www.linphone.org).
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "ChatMessageList.hpp"
|
||||
#include "ChatMessageCore.hpp"
|
||||
#include "ChatMessageGui.hpp"
|
||||
#include "core/App.hpp"
|
||||
#include "core/chat/ChatCore.hpp"
|
||||
#include "core/chat/ChatGui.hpp"
|
||||
|
||||
#include <QSharedPointer>
|
||||
#include <linphone++/linphone.hh>
|
||||
|
||||
// =============================================================================
|
||||
|
||||
DEFINE_ABSTRACT_OBJECT(ChatMessageList)
|
||||
|
||||
QSharedPointer<ChatMessageList> ChatMessageList::create() {
|
||||
auto model = QSharedPointer<ChatMessageList>(new ChatMessageList(), &QObject::deleteLater);
|
||||
model->moveToThread(App::getInstance()->thread());
|
||||
model->setSelf(model);
|
||||
return model;
|
||||
}
|
||||
|
||||
QSharedPointer<ChatMessageCore>
|
||||
ChatMessageList::createChatMessageCore(const std::shared_ptr<linphone::ChatMessage> &chatMessage) {
|
||||
auto chatMessageCore = ChatMessageCore::create(chatMessage);
|
||||
return chatMessageCore;
|
||||
}
|
||||
|
||||
ChatMessageList::ChatMessageList(QObject *parent) : ListProxy(parent) {
|
||||
mustBeInMainThread(getClassName());
|
||||
App::getInstance()->mEngine->setObjectOwnership(this, QQmlEngine::CppOwnership);
|
||||
}
|
||||
|
||||
ChatMessageList::~ChatMessageList() {
|
||||
mustBeInMainThread("~" + getClassName());
|
||||
mModelConnection = nullptr;
|
||||
}
|
||||
|
||||
ChatGui *ChatMessageList::getChat() const {
|
||||
if (mChatCore) return new ChatGui(mChatCore);
|
||||
else return nullptr;
|
||||
}
|
||||
|
||||
QSharedPointer<ChatCore> ChatMessageList::getChatCore() const {
|
||||
return mChatCore;
|
||||
}
|
||||
|
||||
void ChatMessageList::setChatCore(QSharedPointer<ChatCore> core) {
|
||||
if (mChatCore != core) {
|
||||
if (mChatCore) disconnect(mChatCore.get(), &ChatCore::messageListChanged, this, nullptr);
|
||||
mChatCore = core;
|
||||
if (mChatCore) connect(mChatCore.get(), &ChatCore::messageListChanged, this, &ChatMessageList::lUpdate);
|
||||
if (mChatCore)
|
||||
connect(mChatCore.get(), &ChatCore::messagesInserted, this,
|
||||
[this](QList<QSharedPointer<ChatMessageCore>> list) {
|
||||
auto chatList = getSharedList<ChatMessageCore>();
|
||||
for (auto &message : list) {
|
||||
auto it = std::find_if(
|
||||
chatList.begin(), chatList.end(),
|
||||
[message](const QSharedPointer<ChatMessageCore> item) { return item == message; });
|
||||
if (it == chatList.end()) {
|
||||
add(message);
|
||||
int index;
|
||||
get(message.get(), &index);
|
||||
emit messageInserted(index, new ChatMessageGui(message));
|
||||
}
|
||||
}
|
||||
});
|
||||
emit chatChanged();
|
||||
lUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
void ChatMessageList::setChatGui(ChatGui *chat) {
|
||||
auto chatCore = chat ? chat->mCore : nullptr;
|
||||
setChatCore(chatCore);
|
||||
}
|
||||
|
||||
int ChatMessageList::findFirstUnreadIndex() {
|
||||
auto chatList = getSharedList<ChatMessageCore>();
|
||||
auto it = std::find_if(chatList.begin(), chatList.end(),
|
||||
[](const QSharedPointer<ChatMessageCore> item) { return !item->isRead(); });
|
||||
return it == chatList.end() ? -1 : std::distance(chatList.begin(), it);
|
||||
}
|
||||
|
||||
void ChatMessageList::setSelf(QSharedPointer<ChatMessageList> me) {
|
||||
mModelConnection = SafeConnection<ChatMessageList, CoreModel>::create(me, CoreModel::getInstance());
|
||||
|
||||
mModelConnection->makeConnectToCore(&ChatMessageList::lUpdate, [this]() {
|
||||
for (auto &message : getSharedList<ChatMessageCore>()) {
|
||||
if (message) disconnect(message.get(), &ChatMessageCore::deleted, this, nullptr);
|
||||
}
|
||||
if (!mChatCore) return;
|
||||
auto messages = mChatCore->getChatMessageList();
|
||||
for (auto &message : messages) {
|
||||
connect(message.get(), &ChatMessageCore::deleted, this, [this, message] {
|
||||
emit mChatCore->lUpdateLastMessage();
|
||||
remove(message);
|
||||
});
|
||||
}
|
||||
resetData<ChatMessageCore>(messages);
|
||||
});
|
||||
|
||||
connect(this, &ChatMessageList::filterChanged, [this](QString filter) {
|
||||
mFilter = filter;
|
||||
lUpdate();
|
||||
});
|
||||
lUpdate();
|
||||
}
|
||||
|
||||
QVariant ChatMessageList::data(const QModelIndex &index, int role) const {
|
||||
int row = index.row();
|
||||
if (!index.isValid() || row < 0 || row >= mList.count()) return QVariant();
|
||||
if (role == Qt::DisplayRole)
|
||||
return QVariant::fromValue(new ChatMessageGui(mList[row].objectCast<ChatMessageCore>()));
|
||||
return QVariant();
|
||||
}
|
||||
|
|
@ -1,108 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2010-2024 Belledonne Communications SARL.
|
||||
*
|
||||
* This file is part of linphone-desktop
|
||||
* (see https://www.linphone.org).
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "ChatMessageProxy.hpp"
|
||||
#include "ChatMessageGui.hpp"
|
||||
//#include "core/chat/ChatGui.hpp"
|
||||
#include "core/App.hpp"
|
||||
|
||||
DEFINE_ABSTRACT_OBJECT(ChatMessageProxy)
|
||||
|
||||
ChatMessageProxy::ChatMessageProxy(QObject *parent) : LimitProxy(parent) {
|
||||
mList = ChatMessageList::create();
|
||||
setSourceModel(mList.get());
|
||||
}
|
||||
|
||||
ChatMessageProxy::~ChatMessageProxy() {
|
||||
}
|
||||
|
||||
void ChatMessageProxy::setSourceModel(QAbstractItemModel *model) {
|
||||
auto oldChatMessageList = getListModel<ChatMessageList>();
|
||||
if (oldChatMessageList) {
|
||||
disconnect(oldChatMessageList);
|
||||
}
|
||||
auto newChatMessageList = dynamic_cast<ChatMessageList *>(model);
|
||||
if (newChatMessageList) {
|
||||
connect(newChatMessageList, &ChatMessageList::chatChanged, this, &ChatMessageProxy::chatChanged);
|
||||
connect(newChatMessageList, &ChatMessageList::messageInserted, this,
|
||||
[this, newChatMessageList](int index, ChatMessageGui *message) {
|
||||
if (index != -1) {
|
||||
index = dynamic_cast<SortFilterList *>(sourceModel())
|
||||
->mapFromSource(newChatMessageList->index(index, 0))
|
||||
.row();
|
||||
if (mMaxDisplayItems <= index) setMaxDisplayItems(index + mDisplayItemsStep);
|
||||
}
|
||||
emit messageInserted(index, message);
|
||||
});
|
||||
}
|
||||
setSourceModels(new SortFilterList(model));
|
||||
sort(0);
|
||||
}
|
||||
|
||||
ChatGui *ChatMessageProxy::getChatGui() {
|
||||
auto model = getListModel<ChatMessageList>();
|
||||
if (!mChatGui && model) mChatGui = model->getChat();
|
||||
return mChatGui;
|
||||
}
|
||||
|
||||
void ChatMessageProxy::setChatGui(ChatGui *chat) {
|
||||
getListModel<ChatMessageList>()->setChatGui(chat);
|
||||
}
|
||||
|
||||
ChatMessageGui *ChatMessageProxy::getChatMessageAtIndex(int i) {
|
||||
auto model = getListModel<ChatMessageList>();
|
||||
auto sourceIndex = mapToSource(index(i, 0)).row();
|
||||
if (model) {
|
||||
auto chat = model->getAt<ChatMessageCore>(sourceIndex);
|
||||
if (chat) return new ChatMessageGui(chat);
|
||||
else return nullptr;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
int ChatMessageProxy::findFirstUnreadIndex() {
|
||||
auto chatMessageList = getListModel<ChatMessageList>();
|
||||
if (chatMessageList) {
|
||||
auto listIndex = chatMessageList->findFirstUnreadIndex();
|
||||
if (listIndex != -1) {
|
||||
listIndex = dynamic_cast<SortFilterList *>(sourceModel())
|
||||
->mapFromSource(chatMessageList->index(listIndex, 0))
|
||||
.row();
|
||||
if (mMaxDisplayItems <= listIndex) setMaxDisplayItems(listIndex + mDisplayItemsStep);
|
||||
return listIndex;
|
||||
} else {
|
||||
return std::max(0, getCount() - 1);
|
||||
}
|
||||
}
|
||||
return std::max(0, getCount() - 1);
|
||||
}
|
||||
|
||||
bool ChatMessageProxy::SortFilterList::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const {
|
||||
// auto l = getItemAtSource<ChatMessageList, ChatMessageCore>(sourceRow);
|
||||
// return l != nullptr;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ChatMessageProxy::SortFilterList::lessThan(const QModelIndex &sourceLeft, const QModelIndex &sourceRight) const {
|
||||
auto l = getItemAtSource<ChatMessageList, ChatMessageCore>(sourceLeft.row());
|
||||
auto r = getItemAtSource<ChatMessageList, ChatMessageCore>(sourceRight.row());
|
||||
if (l && r) return l->getTimestamp() <= r->getTimestamp();
|
||||
else return true;
|
||||
}
|
||||
148
Linphone/core/chat/message/EventLogCore.cpp
Normal file
148
Linphone/core/chat/message/EventLogCore.cpp
Normal file
|
|
@ -0,0 +1,148 @@
|
|||
/*
|
||||
* Copyright (c) 2010-2024 Belledonne Communications SARL.
|
||||
*
|
||||
* This file is part of linphone-desktop
|
||||
* (see https://www.linphone.org).
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "EventLogCore.hpp"
|
||||
#include "core/App.hpp"
|
||||
#include "core/chat/ChatCore.hpp"
|
||||
#include "model/tool/ToolModel.hpp"
|
||||
|
||||
DEFINE_ABSTRACT_OBJECT(EventLogCore)
|
||||
|
||||
QSharedPointer<EventLogCore> EventLogCore::create(const std::shared_ptr<const linphone::EventLog> &eventLog) {
|
||||
auto sharedPointer = QSharedPointer<EventLogCore>(new EventLogCore(eventLog), &QObject::deleteLater);
|
||||
sharedPointer->setSelf(sharedPointer);
|
||||
sharedPointer->moveToThread(App::getInstance()->thread());
|
||||
return sharedPointer;
|
||||
}
|
||||
|
||||
EventLogCore::EventLogCore(const std::shared_ptr<const linphone::EventLog> &eventLog) {
|
||||
mustBeInLinphoneThread(getClassName());
|
||||
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 = eventLog->getChatMessage()->getMessageId();
|
||||
} else if (eventLog->getCallLog()) {
|
||||
mCallHistoryCore = CallHistoryCore::create(eventLog->getCallLog());
|
||||
mEventId = eventLog->getCallLog()->getCallId();
|
||||
} else {
|
||||
mEventId = eventLog->getNotifyId();
|
||||
computeEvent(eventLog);
|
||||
}
|
||||
}
|
||||
|
||||
EventLogCore::~EventLogCore() {
|
||||
}
|
||||
|
||||
void EventLogCore::setSelf(QSharedPointer<EventLogCore> me) {
|
||||
}
|
||||
|
||||
std::string EventLogCore::getEventLogId() {
|
||||
return mEventId;
|
||||
}
|
||||
|
||||
QSharedPointer<ChatMessageCore> EventLogCore::getChatMessageCore() {
|
||||
return mChatMessageCore;
|
||||
}
|
||||
QSharedPointer<CallHistoryCore> EventLogCore::getCallHistoryCore() {
|
||||
return mCallHistoryCore;
|
||||
}
|
||||
|
||||
ChatMessageCore *EventLogCore::getChatMessageCorePointer() {
|
||||
return mChatMessageCore.get();
|
||||
}
|
||||
CallHistoryCore *EventLogCore::getCallHistoryCorePointer() {
|
||||
return mCallHistoryCore.get();
|
||||
}
|
||||
|
||||
// Events (other than ChatMessage and CallLog which are handled in their respective Core)
|
||||
|
||||
void EventLogCore::computeEvent(const std::shared_ptr<const linphone::EventLog> &eventLog) {
|
||||
mustBeInLinphoneThread(getClassName());
|
||||
mHandled = true;
|
||||
mImportant = false;
|
||||
auto participantAddress = eventLog->getParticipantAddress() ? eventLog->getParticipantAddress()->clone() : nullptr;
|
||||
|
||||
switch (eventLog->getType()) {
|
||||
case linphone::EventLog::Type::ConferenceCreated:
|
||||
mEventDetails = tr("conference_created_event");
|
||||
break;
|
||||
case linphone::EventLog::Type::ConferenceTerminated:
|
||||
mEventDetails = tr("conference_created_terminated");
|
||||
mImportant = true;
|
||||
break;
|
||||
case linphone::EventLog::Type::ConferenceParticipantAdded:
|
||||
mEventDetails = tr("conference_participant_added_event").arg(ToolModel::getDisplayName(participantAddress));
|
||||
break;
|
||||
case linphone::EventLog::Type::ConferenceParticipantRemoved:
|
||||
mEventDetails =
|
||||
tr("conference_participant_removed_event").arg(ToolModel::getDisplayName(participantAddress));
|
||||
mImportant = true;
|
||||
break;
|
||||
case linphone::EventLog::Type::ConferenceSecurityEvent: {
|
||||
if (eventLog->getSecurityEventType() == linphone::EventLog::SecurityEventType::SecurityLevelDowngraded) {
|
||||
auto faultyParticipant = eventLog->getSecurityEventFaultyDeviceAddress()
|
||||
? eventLog->getSecurityEventFaultyDeviceAddress()->clone()
|
||||
: nullptr;
|
||||
if (faultyParticipant)
|
||||
mEventDetails = tr("conference_security_event").arg(ToolModel::getDisplayName(faultyParticipant));
|
||||
else if (participantAddress)
|
||||
mEventDetails = tr("conference_security_event").arg(ToolModel::getDisplayName(participantAddress));
|
||||
mImportant = true;
|
||||
} else mHandled = false;
|
||||
break;
|
||||
}
|
||||
case linphone::EventLog::Type::ConferenceEphemeralMessageEnabled:
|
||||
mEventDetails = tr("conference_ephemeral_message_enabled_event")
|
||||
.arg(getEphemeralFormatedTime(eventLog->getEphemeralMessageLifetime()));
|
||||
break;
|
||||
case linphone::EventLog::Type::ConferenceEphemeralMessageLifetimeChanged:
|
||||
mEventDetails = tr("conference_ephemeral_message_lifetime_changed_event")
|
||||
.arg(getEphemeralFormatedTime(eventLog->getEphemeralMessageLifetime()));
|
||||
break;
|
||||
case linphone::EventLog::Type::ConferenceEphemeralMessageDisabled:
|
||||
mEventDetails = tr("conference_ephemeral_message_disabled_event");
|
||||
mImportant = true;
|
||||
break;
|
||||
case linphone::EventLog::Type::ConferenceSubjectChanged:
|
||||
mEventDetails = tr("conference_subject_changed_event").arg(QString::fromStdString(eventLog->getSubject()));
|
||||
break;
|
||||
case linphone::EventLog::Type::ConferenceParticipantSetAdmin:
|
||||
mEventDetails =
|
||||
tr("conference_participant_unset_admin_event").arg(ToolModel::getDisplayName(participantAddress));
|
||||
break;
|
||||
case linphone::EventLog::Type::ConferenceParticipantUnsetAdmin:
|
||||
mEventDetails =
|
||||
tr("conference_participant_set_admin_event").arg(ToolModel::getDisplayName(participantAddress));
|
||||
break;
|
||||
default:
|
||||
mHandled = false;
|
||||
}
|
||||
}
|
||||
|
||||
QString EventLogCore::getEphemeralFormatedTime(int selectedTime) {
|
||||
if (selectedTime == 60) return tr("nMinute", "", 1).arg(1);
|
||||
else if (selectedTime == 3600) return tr("nHour", "", 1).arg(1);
|
||||
else if (selectedTime == 86400) return tr("nDay", "", 1).arg(1);
|
||||
else if (selectedTime == 259200) return tr("nDay", "", 3).arg(3);
|
||||
else if (selectedTime == 604800) return tr("nWeek", "", 1).arg(1);
|
||||
else return tr("nSeconds", "", selectedTime).arg(selectedTime);
|
||||
}
|
||||
78
Linphone/core/chat/message/EventLogCore.hpp
Normal file
78
Linphone/core/chat/message/EventLogCore.hpp
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
/*
|
||||
* Copyright (c) 2010-2024 Belledonne Communications SARL.
|
||||
*
|
||||
* This file is part of linphone-desktop
|
||||
* (see https://www.linphone.org).
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef EVENT_LOG_CORE_H_
|
||||
#define EVENT_LOG_CORE_H_
|
||||
|
||||
#include "ChatMessageCore.hpp"
|
||||
#include "core/call-history/CallHistoryCore.hpp"
|
||||
#include "core/conference/ConferenceInfoCore.hpp"
|
||||
#include "core/conference/ConferenceInfoGui.hpp"
|
||||
#include "model/chat/message/ChatMessageModel.hpp"
|
||||
#include "tool/AbstractObject.hpp"
|
||||
#include "tool/LinphoneEnums.hpp"
|
||||
#include "tool/thread/SafeConnection.hpp"
|
||||
#include <QObject>
|
||||
#include <QSharedPointer>
|
||||
|
||||
#include <linphone++/linphone.hh>
|
||||
|
||||
class ChatMessageCore;
|
||||
|
||||
class EventLogCore : public QObject, public AbstractObject {
|
||||
Q_OBJECT
|
||||
|
||||
Q_PROPERTY(LinphoneEnums::EventLogType type MEMBER mEventLogType CONSTANT)
|
||||
Q_PROPERTY(ChatMessageCore *chatMessage READ getChatMessageCorePointer CONSTANT)
|
||||
// Q_PROPERTY(NotifyCore *notification MEMBER mNotifyCore CONSTANT)
|
||||
Q_PROPERTY(CallHistoryCore *callLog READ getCallHistoryCorePointer CONSTANT)
|
||||
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)
|
||||
|
||||
public:
|
||||
static QSharedPointer<EventLogCore> create(const std::shared_ptr<const linphone::EventLog> &eventLog);
|
||||
EventLogCore(const std::shared_ptr<const linphone::EventLog> &eventLog);
|
||||
~EventLogCore();
|
||||
void setSelf(QSharedPointer<EventLogCore> me);
|
||||
std::string getEventLogId();
|
||||
QSharedPointer<ChatMessageCore> getChatMessageCore();
|
||||
QSharedPointer<CallHistoryCore> getCallHistoryCore();
|
||||
|
||||
private:
|
||||
DECLARE_ABSTRACT_OBJECT
|
||||
std::string mEventId;
|
||||
|
||||
QSharedPointer<ChatMessageCore> mChatMessageCore = nullptr;
|
||||
QSharedPointer<CallHistoryCore> mCallHistoryCore = nullptr;
|
||||
LinphoneEnums::EventLogType mEventLogType;
|
||||
bool mHandled;
|
||||
bool mImportant;
|
||||
QString mEventDetails;
|
||||
QDateTime mTimestamp;
|
||||
|
||||
ChatMessageCore *getChatMessageCorePointer();
|
||||
CallHistoryCore *getCallHistoryCorePointer();
|
||||
void computeEvent(const std::shared_ptr<const linphone::EventLog> &eventLog);
|
||||
QString getEphemeralFormatedTime(int selectedTime);
|
||||
};
|
||||
|
||||
#endif // EventLogCore_H_
|
||||
38
Linphone/core/chat/message/EventLogGui.cpp
Normal file
38
Linphone/core/chat/message/EventLogGui.cpp
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* Copyright (c) 2010-2024 Belledonne Communications SARL.
|
||||
*
|
||||
* This file is part of linphone-desktop
|
||||
* (see https://www.linphone.org).
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "EventLogGui.hpp"
|
||||
#include "core/App.hpp"
|
||||
|
||||
DEFINE_ABSTRACT_OBJECT(EventLogGui)
|
||||
|
||||
EventLogGui::EventLogGui(QSharedPointer<EventLogCore> core) {
|
||||
App::getInstance()->mEngine->setObjectOwnership(this, QQmlEngine::JavaScriptOwnership);
|
||||
mCore = core;
|
||||
if (isInLinphoneThread()) moveToThread(App::getInstance()->thread());
|
||||
}
|
||||
|
||||
EventLogGui::~EventLogGui() {
|
||||
mustBeInMainThread("~" + getClassName());
|
||||
}
|
||||
|
||||
EventLogCore *EventLogGui::getCore() const {
|
||||
return mCore.get();
|
||||
}
|
||||
41
Linphone/core/chat/message/EventLogGui.hpp
Normal file
41
Linphone/core/chat/message/EventLogGui.hpp
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* Copyright (c) 2010-2024 Belledonne Communications SARL.
|
||||
*
|
||||
* This file is part of linphone-desktop
|
||||
* (see https://www.linphone.org).
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef EVENT_LOG_GUI_H_
|
||||
#define EVENT_LOG_GUI_H_
|
||||
|
||||
#include "EventLogCore.hpp"
|
||||
#include <QObject>
|
||||
#include <QSharedPointer>
|
||||
|
||||
class EventLogGui : public QObject, public AbstractObject {
|
||||
Q_OBJECT
|
||||
|
||||
Q_PROPERTY(EventLogCore *core READ getCore CONSTANT)
|
||||
|
||||
public:
|
||||
EventLogGui(QSharedPointer<EventLogCore> core);
|
||||
~EventLogGui();
|
||||
EventLogCore *getCore() const;
|
||||
QSharedPointer<EventLogCore> mCore;
|
||||
DECLARE_ABSTRACT_OBJECT
|
||||
};
|
||||
|
||||
#endif
|
||||
162
Linphone/core/chat/message/EventLogList.cpp
Normal file
162
Linphone/core/chat/message/EventLogList.cpp
Normal file
|
|
@ -0,0 +1,162 @@
|
|||
/*
|
||||
* Copyright (c) 2010-2024 Belledonne Communications SARL.
|
||||
*
|
||||
* This file is part of linphone-desktop
|
||||
* (see https://www.linphone.org).
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "EventLogList.hpp"
|
||||
#include "ChatMessageCore.hpp"
|
||||
#include "ChatMessageGui.hpp"
|
||||
#include "EventLogGui.hpp"
|
||||
#include "core/App.hpp"
|
||||
#include "core/call-history/CallHistoryGui.hpp"
|
||||
#include "core/chat/ChatCore.hpp"
|
||||
#include "core/chat/ChatGui.hpp"
|
||||
#include <QSharedPointer>
|
||||
#include <linphone++/linphone.hh>
|
||||
|
||||
// =============================================================================
|
||||
|
||||
DEFINE_ABSTRACT_OBJECT(EventLogList)
|
||||
|
||||
QSharedPointer<EventLogList> EventLogList::create() {
|
||||
auto model = QSharedPointer<EventLogList>(new EventLogList(), &QObject::deleteLater);
|
||||
model->moveToThread(App::getInstance()->thread());
|
||||
model->setSelf(model);
|
||||
return model;
|
||||
}
|
||||
|
||||
EventLogList::EventLogList(QObject *parent) : ListProxy(parent) {
|
||||
mustBeInMainThread(getClassName());
|
||||
App::getInstance()->mEngine->setObjectOwnership(this, QQmlEngine::CppOwnership);
|
||||
}
|
||||
|
||||
EventLogList::~EventLogList() {
|
||||
mustBeInMainThread("~" + getClassName());
|
||||
mModelConnection = nullptr;
|
||||
}
|
||||
|
||||
ChatGui *EventLogList::getChat() const {
|
||||
if (mChatCore) return new ChatGui(mChatCore);
|
||||
else return nullptr;
|
||||
}
|
||||
|
||||
QSharedPointer<ChatCore> EventLogList::getChatCore() const {
|
||||
return mChatCore;
|
||||
}
|
||||
|
||||
void EventLogList::setChatCore(QSharedPointer<ChatCore> core) {
|
||||
if (mChatCore != core) {
|
||||
if (mChatCore) disconnect(mChatCore.get(), &ChatCore::eventListChanged, this, nullptr);
|
||||
mChatCore = core;
|
||||
if (mChatCore) connect(mChatCore.get(), &ChatCore::eventListChanged, this, &EventLogList::lUpdate);
|
||||
if (mChatCore)
|
||||
connect(mChatCore.get(), &ChatCore::eventsInserted, this, [this](QList<QSharedPointer<EventLogCore>> list) {
|
||||
auto eventsList = getSharedList<EventLogCore>();
|
||||
for (auto &event : list) {
|
||||
auto it = std::find_if(eventsList.begin(), eventsList.end(),
|
||||
[event](const QSharedPointer<EventLogCore> item) { return item == event; });
|
||||
if (it == eventsList.end()) {
|
||||
add(event);
|
||||
int index;
|
||||
get(event.get(), &index);
|
||||
emit eventInserted(index, new EventLogGui(event));
|
||||
}
|
||||
}
|
||||
});
|
||||
emit eventChanged();
|
||||
lUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
void EventLogList::setChatGui(ChatGui *chat) {
|
||||
auto chatCore = chat ? chat->mCore : nullptr;
|
||||
setChatCore(chatCore);
|
||||
}
|
||||
|
||||
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();
|
||||
});
|
||||
return it == eventList.end() ? -1 : std::distance(eventList.begin(), it);
|
||||
}
|
||||
|
||||
void EventLogList::setSelf(QSharedPointer<EventLogList> me) {
|
||||
mModelConnection = SafeConnection<EventLogList, CoreModel>::create(me, CoreModel::getInstance());
|
||||
|
||||
mModelConnection->makeConnectToCore(&EventLogList::lUpdate, [this]() {
|
||||
for (auto &event : getSharedList<EventLogCore>()) {
|
||||
auto message = event->getChatMessageCore();
|
||||
if (message) disconnect(message.get(), &ChatMessageCore::deleted, this, nullptr);
|
||||
}
|
||||
if (!mChatCore) return;
|
||||
auto events = mChatCore->getEventLogList();
|
||||
for (auto &event : events) {
|
||||
auto message = event->getChatMessageCore();
|
||||
if (message)
|
||||
connect(message.get(), &ChatMessageCore::deleted, this, [this, message, event] {
|
||||
emit mChatCore->lUpdateLastMessage();
|
||||
remove(event);
|
||||
});
|
||||
}
|
||||
resetData<EventLogCore>(events);
|
||||
});
|
||||
|
||||
connect(this, &EventLogList::filterChanged, [this](QString filter) {
|
||||
mFilter = filter;
|
||||
lUpdate();
|
||||
});
|
||||
lUpdate();
|
||||
}
|
||||
|
||||
QVariant EventLogList::data(const QModelIndex &index, int role) const {
|
||||
int row = index.row();
|
||||
if (!index.isValid() || row < 0 || row >= mList.count()) return QVariant();
|
||||
|
||||
auto core = mList[row].objectCast<EventLogCore>();
|
||||
if (core->getChatMessageCore()) {
|
||||
switch (role) {
|
||||
case Qt::DisplayRole:
|
||||
return QVariant::fromValue(new ChatMessageGui(core->getChatMessageCore()));
|
||||
case Qt::DisplayRole + 1:
|
||||
return "chatMessage";
|
||||
}
|
||||
} else if (core->getCallHistoryCore()) {
|
||||
switch (role) {
|
||||
case Qt::DisplayRole:
|
||||
return QVariant::fromValue(new CallHistoryGui(core->getCallHistoryCore()));
|
||||
case Qt::DisplayRole + 1:
|
||||
return "callLog";
|
||||
}
|
||||
} else {
|
||||
switch (role) {
|
||||
case Qt::DisplayRole:
|
||||
return QVariant::fromValue(new EventLogGui(core));
|
||||
case Qt::DisplayRole + 1:
|
||||
return "event";
|
||||
}
|
||||
}
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
QHash<int, QByteArray> EventLogList::roleNames() const {
|
||||
QHash<int, QByteArray> roles;
|
||||
roles[Qt::DisplayRole] = "modelData";
|
||||
roles[Qt::DisplayRole + 1] = "eventType";
|
||||
return roles;
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
/*
|
||||
/*
|
||||
* Copyright (c) 2010-2024 Belledonne Communications SARL.
|
||||
*
|
||||
* This file is part of linphone-desktop
|
||||
|
|
@ -18,28 +18,25 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef CHAT_MESSAGE_LIST_H_
|
||||
#define CHAT_MESSAGE_LIST_H_
|
||||
#ifndef EVENT_LOG_LIST_H_
|
||||
#define EVENT_LOG_LIST_H_
|
||||
|
||||
#include "core/proxy/ListProxy.hpp"
|
||||
#include "tool/AbstractObject.hpp"
|
||||
#include "tool/thread/SafeConnection.hpp"
|
||||
#include <QLocale>
|
||||
|
||||
class ChatMessageGui;
|
||||
class ChatMessageCore;
|
||||
class EventLogGui;
|
||||
class ChatCore;
|
||||
class ChatGui;
|
||||
// =============================================================================
|
||||
|
||||
class ChatMessageList : public ListProxy, public AbstractObject {
|
||||
class EventLogList : public ListProxy, public AbstractObject {
|
||||
Q_OBJECT
|
||||
public:
|
||||
static QSharedPointer<ChatMessageList> create();
|
||||
// Create a ChatMessageCore and make connections to List.
|
||||
QSharedPointer<ChatMessageCore> createChatMessageCore(const std::shared_ptr<linphone::ChatMessage> &chatMessage);
|
||||
ChatMessageList(QObject *parent = Q_NULLPTR);
|
||||
~ChatMessageList();
|
||||
static QSharedPointer<EventLogList> create();
|
||||
EventLogList(QObject *parent = Q_NULLPTR);
|
||||
~EventLogList();
|
||||
|
||||
QSharedPointer<ChatCore> getChatCore() const;
|
||||
ChatGui *getChat() const;
|
||||
|
|
@ -48,18 +45,20 @@ public:
|
|||
|
||||
int findFirstUnreadIndex();
|
||||
|
||||
void setSelf(QSharedPointer<ChatMessageList> me);
|
||||
void setSelf(QSharedPointer<EventLogList> me);
|
||||
virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
||||
QHash<int, QByteArray> roleNames() const override;
|
||||
|
||||
signals:
|
||||
void lUpdate();
|
||||
void filterChanged(QString filter);
|
||||
void chatChanged();
|
||||
void messageInserted(int index, ChatMessageGui *message);
|
||||
void eventChanged();
|
||||
void eventInserted(int index, EventLogGui *message);
|
||||
|
||||
private:
|
||||
QString mFilter;
|
||||
QSharedPointer<ChatCore> mChatCore;
|
||||
QSharedPointer<SafeConnection<ChatMessageList, CoreModel>> mModelConnection;
|
||||
QSharedPointer<SafeConnection<EventLogList, CoreModel>> mModelConnection;
|
||||
DECLARE_ABSTRACT_OBJECT
|
||||
};
|
||||
|
||||
108
Linphone/core/chat/message/EventLogProxy.cpp
Normal file
108
Linphone/core/chat/message/EventLogProxy.cpp
Normal file
|
|
@ -0,0 +1,108 @@
|
|||
/*
|
||||
* Copyright (c) 2010-2024 Belledonne Communications SARL.
|
||||
*
|
||||
* This file is part of linphone-desktop
|
||||
* (see https://www.linphone.org).
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "EventLogProxy.hpp"
|
||||
#include "EventLogGui.hpp"
|
||||
#include "EventLogList.hpp"
|
||||
// #include "core/chat/ChatGui.hpp"
|
||||
#include "core/App.hpp"
|
||||
|
||||
DEFINE_ABSTRACT_OBJECT(EventLogProxy)
|
||||
|
||||
EventLogProxy::EventLogProxy(QObject *parent) : LimitProxy(parent) {
|
||||
mList = EventLogList::create();
|
||||
setSourceModel(mList.get());
|
||||
}
|
||||
|
||||
EventLogProxy::~EventLogProxy() {
|
||||
}
|
||||
|
||||
void EventLogProxy::setSourceModel(QAbstractItemModel *model) {
|
||||
auto oldEventLogList = getListModel<EventLogList>();
|
||||
if (oldEventLogList) {
|
||||
disconnect(oldEventLogList);
|
||||
}
|
||||
auto newEventLogList = dynamic_cast<EventLogList *>(model);
|
||||
if (newEventLogList) {
|
||||
connect(newEventLogList, &EventLogList::eventChanged, this, &EventLogProxy::eventChanged);
|
||||
connect(newEventLogList, &EventLogList::eventInserted, this,
|
||||
[this, newEventLogList](int index, EventLogGui *event) {
|
||||
if (index != -1) {
|
||||
index = dynamic_cast<SortFilterList *>(sourceModel())
|
||||
->mapFromSource(newEventLogList->index(index, 0))
|
||||
.row();
|
||||
if (mMaxDisplayItems <= index) setMaxDisplayItems(index + mDisplayItemsStep);
|
||||
}
|
||||
emit eventInserted(index, event);
|
||||
});
|
||||
}
|
||||
setSourceModels(new SortFilterList(model));
|
||||
sort(0);
|
||||
}
|
||||
|
||||
ChatGui *EventLogProxy::getChatGui() {
|
||||
auto model = getListModel<EventLogList>();
|
||||
if (!mChatGui && model) mChatGui = model->getChat();
|
||||
return mChatGui;
|
||||
}
|
||||
|
||||
void EventLogProxy::setChatGui(ChatGui *chat) {
|
||||
getListModel<EventLogList>()->setChatGui(chat);
|
||||
}
|
||||
|
||||
EventLogGui *EventLogProxy::getEventAtIndex(int i) {
|
||||
auto model = getListModel<EventLogList>();
|
||||
auto sourceIndex = mapToSource(index(i, 0)).row();
|
||||
if (model) {
|
||||
auto event = model->getAt<EventLogCore>(sourceIndex);
|
||||
if (event) return new EventLogGui(event);
|
||||
else return nullptr;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
int EventLogProxy::findFirstUnreadIndex() {
|
||||
auto eventLogList = getListModel<EventLogList>();
|
||||
if (eventLogList) {
|
||||
auto listIndex = eventLogList->findFirstUnreadIndex();
|
||||
if (listIndex != -1) {
|
||||
listIndex =
|
||||
dynamic_cast<SortFilterList *>(sourceModel())->mapFromSource(eventLogList->index(listIndex, 0)).row();
|
||||
if (mMaxDisplayItems <= listIndex) setMaxDisplayItems(listIndex + mDisplayItemsStep);
|
||||
return listIndex;
|
||||
} else {
|
||||
return std::max(0, getCount() - 1);
|
||||
}
|
||||
}
|
||||
return std::max(0, getCount() - 1);
|
||||
}
|
||||
|
||||
bool EventLogProxy::SortFilterList::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const {
|
||||
// auto l = getItemAtSource<EventLogList, ChatMessageCore>(sourceRow);
|
||||
// return l != nullptr;
|
||||
return true;
|
||||
}
|
||||
|
||||
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());
|
||||
if (l && r) return l->getTimestamp() <= r->getTimestamp();
|
||||
else return true;
|
||||
}
|
||||
|
|
@ -18,10 +18,10 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef CHAT_MESSAGE_PROXY_H_
|
||||
#define CHAT_MESSAGE_PROXY_H_
|
||||
#ifndef EVENT_LIST_PROXY_H_
|
||||
#define EVENT_LIST_PROXY_H_
|
||||
|
||||
#include "ChatMessageList.hpp"
|
||||
#include "EventLogList.hpp"
|
||||
#include "core/proxy/LimitProxy.hpp"
|
||||
#include "tool/AbstractObject.hpp"
|
||||
|
||||
|
|
@ -29,30 +29,30 @@
|
|||
|
||||
class ChatGui;
|
||||
|
||||
class ChatMessageProxy : public LimitProxy, public AbstractObject {
|
||||
class EventLogProxy : public LimitProxy, public AbstractObject {
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(ChatGui *chatGui READ getChatGui WRITE setChatGui NOTIFY chatChanged)
|
||||
Q_PROPERTY(ChatGui *chatGui READ getChatGui WRITE setChatGui NOTIFY eventChanged)
|
||||
|
||||
public:
|
||||
DECLARE_SORTFILTER_CLASS()
|
||||
|
||||
ChatMessageProxy(QObject *parent = Q_NULLPTR);
|
||||
~ChatMessageProxy();
|
||||
EventLogProxy(QObject *parent = Q_NULLPTR);
|
||||
~EventLogProxy();
|
||||
|
||||
ChatGui *getChatGui();
|
||||
void setChatGui(ChatGui *chat);
|
||||
|
||||
void setSourceModel(QAbstractItemModel *sourceModel) override;
|
||||
|
||||
Q_INVOKABLE ChatMessageGui *getChatMessageAtIndex(int index);
|
||||
Q_INVOKABLE EventLogGui *getEventAtIndex(int index);
|
||||
Q_INVOKABLE int findFirstUnreadIndex();
|
||||
|
||||
signals:
|
||||
void chatChanged();
|
||||
void messageInserted(int index, ChatMessageGui *message);
|
||||
void eventChanged();
|
||||
void eventInserted(int index, EventLogGui *message);
|
||||
|
||||
protected:
|
||||
QSharedPointer<ChatMessageList> mList;
|
||||
QSharedPointer<EventLogList> mList;
|
||||
ChatGui *mChatGui = nullptr;
|
||||
DECLARE_ABSTRACT_OBJECT
|
||||
};
|
||||
|
|
@ -5921,4 +5921,98 @@ Failed to create 1-1 conversation with %1 !</extracomment>
|
|||
<translation>Ok</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>EventLogCore</name>
|
||||
<message>
|
||||
<source>conference_created_event</source>
|
||||
<extracomment>'You have joined the group' : Little message to show on the event when the user join the chat group.</extracomment>
|
||||
<translation>You have joined the group</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>conference_created_terminated</source>
|
||||
<extracomment>'You have left the group' : Little message to show on the event when the user leave the chat group.</extracomment>
|
||||
<translation>You have left the group</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>conference_participant_added_event</source>
|
||||
<extracomment>'%1 has joined' : Little message to show on the event when someone join the chat group.</extracomment>
|
||||
<translation>%1 has joined</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>conference_participant_removed_event</source>
|
||||
<extracomment>'%1 has left' : Little message to show on the event when someone leave the chat group</extracomment>
|
||||
<translation>%1 has left</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>conference_participant_set_admin_event</source>
|
||||
<extracomment>'%1 is now an admin' : Little message to show on the event when someone get the admin status. %1 is somebody</extracomment>
|
||||
<translation>%1 is now an admin</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>conference_participant_unset_admin_event</source>
|
||||
<extracomment>'%1 is no longer an admin' : Little message to show on the event when somebody lost its admin status. %1 is somebody</extracomment>
|
||||
<translation>%1 is no longer an admin</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>conference_security_event</source>
|
||||
<extracomment>'Security level degraded by %1': Little message to show on the event when a security level has been lost.</extracomment>
|
||||
<translation>Security level degraded by %1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>conference_ephemeral_message_enabled_event</source>
|
||||
<extracomment>'Ephemeral messages have been enabled: %1' : Little message to show on the event when ephemeral has been activated. %1 is a date time</extracomment>
|
||||
<translation>Ephemeral messages have been enabled: %1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>conference_ephemeral_message_disabled_event</source>
|
||||
<extracomment>'Ephemeral messages have been disabled': Little message to show on the event when ephemeral has been deactivated.</extracomment>
|
||||
<translation>Ephemeral messages have been disabled</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>conference_subject_changed_event</source>
|
||||
<extracomment>'New subject : %1' : Little message to show on the event when the subject of the chat room has been changed. %1 is the new subject.</extracomment>
|
||||
<translation>New subject: %1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>conference_ephemeral_message_lifetime_changed_event</source>
|
||||
<extracomment>'Ephemeral messages have been updated: %1' : Little message to show on the event when ephemeral has been updated. %1 is a date time</extracomment>
|
||||
<translation>Ephemeral messages have been updated: %1</translation>
|
||||
</message>
|
||||
<message numerus="yes">
|
||||
<source>nSeconds</source>
|
||||
<translation>
|
||||
<numerusform>%1 second</numerusform>
|
||||
<numerusform>%1 seconds</numerusform>
|
||||
</translation>
|
||||
</message>
|
||||
<message numerus="yes">
|
||||
<source>nMinute</source>
|
||||
<translation>
|
||||
<numerusform>%1 minute</numerusform>
|
||||
<numerusform>%1 minutes</numerusform>
|
||||
</translation>
|
||||
</message>
|
||||
<message numerus="yes">
|
||||
<source>nHour</source>
|
||||
<translation>
|
||||
<numerusform>%1 hour</numerusform>
|
||||
<numerusform>%1 hours</numerusform>
|
||||
</translation>
|
||||
</message>
|
||||
<message numerus="yes">
|
||||
<source>nDay</source>
|
||||
<translation>
|
||||
<numerusform>%1 day</numerusform>
|
||||
<numerusform>%1 days</numerusform>
|
||||
</translation>
|
||||
</message>
|
||||
<message numerus="yes">
|
||||
<source>nWeek</source>
|
||||
<translation>
|
||||
<numerusform>%1 week</numerusform>
|
||||
<numerusform>%1 weeks</numerusform>
|
||||
</translation>
|
||||
</message>
|
||||
</context>
|
||||
|
||||
</TS>
|
||||
|
|
|
|||
|
|
@ -1885,3 +1885,24 @@ bool Utils::codepointIsEmoji(uint code) {
|
|||
(code >= 0x2700 && code <= 0x27BF) // Dingbats
|
||||
);
|
||||
}
|
||||
|
||||
QString Utils::toDateTimeString(QDateTime date, const QString &format) {
|
||||
if (date.date() == QDate::currentDate()) return toTimeString(date);
|
||||
else {
|
||||
return getOffsettedUTC(date).toString(format);
|
||||
}
|
||||
}
|
||||
|
||||
QDateTime Utils::getOffsettedUTC(const QDateTime &date) {
|
||||
QDateTime utc = date.toUTC();
|
||||
auto timezone = date.timeZone();
|
||||
int offset = timezone.offsetFromUtc(date);
|
||||
utc = utc.addSecs(offset);
|
||||
utc.setTimeZone(QTimeZone(offset));
|
||||
return utc;
|
||||
}
|
||||
|
||||
QString Utils::toTimeString(QDateTime date, const QString &format) {
|
||||
// Issue : date.toString() will not print the good time in timezones. Get it from date and add ourself the offset.
|
||||
return getOffsettedUTC(date).toString(format);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -158,6 +158,10 @@ public:
|
|||
Q_INVOKABLE static QString getFilename(QUrl url);
|
||||
static bool codepointIsEmoji(uint code);
|
||||
|
||||
Q_INVOKABLE static QString toDateTimeString(QDateTime date, const QString &format = "yyyy/MM/dd hh:mm:ss");
|
||||
static QDateTime getOffsettedUTC(const QDateTime &date);
|
||||
Q_INVOKABLE static QString toTimeString(QDateTime date, const QString &format = "hh:mm:ss");
|
||||
|
||||
// QDir findDirectoryByName(QString startPath, QString name);
|
||||
|
||||
static QString getApplicationProduct();
|
||||
|
|
|
|||
|
|
@ -57,6 +57,7 @@ list(APPEND _LINPHONEAPP_QML_FILES
|
|||
view/Control/Display/Chat/ChatMessage.qml
|
||||
view/Control/Display/Chat/ChatMessageInvitationBubble.qml
|
||||
view/Control/Display/Chat/ChatMessagesListView.qml
|
||||
view/Control/Display/Chat/Event.qml
|
||||
view/Control/Display/Contact/Avatar.qml
|
||||
view/Control/Display/Contact/Contact.qml
|
||||
view/Control/Display/Contact/Presence.qml
|
||||
|
|
|
|||
|
|
@ -246,7 +246,7 @@ ListView {
|
|||
unread: modelData.core.unreadMessagesCount
|
||||
}
|
||||
EffectImage {
|
||||
visible: modelData?.core.lastMessage && modelData?.core.lastMessageState !== LinphoneEnums.ChatMessageState.StateIdle
|
||||
visible: modelData?.core.lastEvent && modelData?.core.lastMessageState !== LinphoneEnums.ChatMessageState.StateIdle
|
||||
&& !modelData.core.lastMessage.core.isRemoteMessage
|
||||
Layout.preferredWidth: visible ? 14 * DefaultStyle.dp : 0
|
||||
Layout.preferredHeight: 14 * DefaultStyle.dp
|
||||
|
|
|
|||
|
|
@ -15,17 +15,17 @@ ListView {
|
|||
property color backgroundColor
|
||||
|
||||
Component.onCompleted: {
|
||||
var index = chatMessageProxy.findFirstUnreadIndex()
|
||||
var index = eventLogProxy.findFirstUnreadIndex()
|
||||
positionViewAtIndex(index, ListView.End)
|
||||
var chatMessage = chatMessageProxy.getChatMessageAtIndex(index)
|
||||
if (chatMessage && !chatMessage.core.isRead) chatMessage.core.lMarkAsRead()
|
||||
var chatMessage = eventLogProxy.getEventAtIndex(index)?.core?.chatMessage
|
||||
if (chatMessage && !chatMessage.isRead) chatMessage.lMarkAsRead()
|
||||
}
|
||||
|
||||
onCountChanged: if (atYEnd) {
|
||||
var index = chatMessageProxy.findFirstUnreadIndex()
|
||||
var index = eventLogProxy.findFirstUnreadIndex()
|
||||
mainItem.positionViewAtIndex(index, ListView.End)
|
||||
var chatMessage = chatMessageProxy.getChatMessageAtIndex(index)
|
||||
if (chatMessage && !chatMessage.core.isRead) chatMessage.core.lMarkAsRead()
|
||||
var chatMessage = eventLogProxy.getEventAtIndex(index)?.core?.chatMessage
|
||||
if (chatMessage && !chatMessage.isRead) chatMessage.lMarkAsRead()
|
||||
}
|
||||
|
||||
Button {
|
||||
|
|
@ -40,21 +40,22 @@ ListView {
|
|||
anchors.bottomMargin: Math.round(18 * DefaultStyle.dp)
|
||||
anchors.rightMargin: Math.round(18 * DefaultStyle.dp)
|
||||
onClicked: {
|
||||
var index = chatMessageProxy.findFirstUnreadIndex()
|
||||
var index = eventLogProxy.findFirstUnreadIndex()
|
||||
mainItem.positionViewAtIndex(index, ListView.End)
|
||||
var chatMessage = chatMessageProxy.getChatMessageAtIndex(index)
|
||||
if (chatMessage && !chatMessage.core.isRead) chatMessage.core.lMarkAsRead()
|
||||
var chatMessage = eventLogProxy.getEventAtIndex(index)?.core?.chatMessage
|
||||
if (chatMessage && !chatMessage.isRead) chatMessage.lMarkAsRead()
|
||||
}
|
||||
}
|
||||
|
||||
model: ChatMessageProxy {
|
||||
id: chatMessageProxy
|
||||
model: EventLogProxy {
|
||||
id: eventLogProxy
|
||||
chatGui: mainItem.chat
|
||||
// scroll when in view and message inserted
|
||||
onMessageInserted: (index, gui) => {
|
||||
onEventInserted: (index, gui) => {
|
||||
if (!mainItem.visible) return
|
||||
mainItem.positionViewAtIndex(index, ListView.End)
|
||||
if (!gui.core.isRead) gui.core.lMarkAsRead()
|
||||
if (gui.core.chatMessage && !gui.core.chatMessage.isRead)
|
||||
gui.core.chatMessage.lMarkAsRead()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -107,25 +108,51 @@ ListView {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
delegate: DelegateChooser {
|
||||
role: "eventType"
|
||||
|
||||
delegate: ChatMessage {
|
||||
chatMessage: modelData
|
||||
maxWidth: Math.round(mainItem.width * (3/4))
|
||||
onVisibleChanged: {
|
||||
if (visible && !modelData.core.isRead) modelData.core.lMarkAsRead()
|
||||
DelegateChoice {
|
||||
roleValue: "chatMessage"
|
||||
delegate:
|
||||
ChatMessage {
|
||||
chatMessage: modelData
|
||||
maxWidth: Math.round(mainItem.width * (3/4))
|
||||
onVisibleChanged: {
|
||||
if (visible && !modelData.core.isRead) modelData.core.lMarkAsRead()
|
||||
}
|
||||
width: mainItem.width
|
||||
property var previousIndex: index - 1
|
||||
property var previousFromAddress: eventLogProxy.getEventAtIndex(index-1)?.core.chatMessage?.fromAddress
|
||||
backgroundColor: isRemoteMessage ? DefaultStyle.main2_100 : DefaultStyle.main1_100
|
||||
isFirstMessage: !previousFromAddress || previousFromAddress !== modelData.core.fromAddress
|
||||
anchors.right: !isRemoteMessage && parent
|
||||
? parent.right
|
||||
: undefined
|
||||
|
||||
onMessageDeletionRequested: modelData.core.lDelete()
|
||||
}
|
||||
}
|
||||
width: mainItem.width
|
||||
property var previousIndex: index - 1
|
||||
property var previousFromAddress: chatMessageProxy.getChatMessageAtIndex(index-1)?.core.fromAddress
|
||||
backgroundColor: isRemoteMessage ? DefaultStyle.main2_100 : DefaultStyle.main1_100
|
||||
isFirstMessage: !previousFromAddress || previousFromAddress !== modelData.core.fromAddress
|
||||
anchors.right: !isRemoteMessage && parent
|
||||
? parent.right
|
||||
: undefined
|
||||
|
||||
onMessageDeletionRequested: modelData.core.lDelete()
|
||||
DelegateChoice {
|
||||
roleValue: "event"
|
||||
delegate:
|
||||
Item {
|
||||
property bool showTopMargin: !header.visible && index == 0
|
||||
width: mainItem.width
|
||||
height: (showTopMargin ? 30 : 0 * DefaultStyle.dp) + eventItem.implicitHeight
|
||||
Event {
|
||||
id: eventItem
|
||||
anchors.top: parent.top
|
||||
anchors.topMargin: showTopMargin ? 30 : 0 * DefaultStyle.dp
|
||||
width: parent.width
|
||||
eventLogGui: modelData
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
footerPositioning: ListView.OverlayFooter
|
||||
footer: Control.Control {
|
||||
visible: composeLayout.composingName !== ""
|
||||
|
|
|
|||
48
Linphone/view/Control/Display/Chat/Event.qml
Normal file
48
Linphone/view/Control/Display/Chat/Event.qml
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
import QtQuick
|
||||
import QtQuick.Layouts
|
||||
import Linphone
|
||||
import UtilsCpp
|
||||
|
||||
RowLayout {
|
||||
id: mainLayout
|
||||
height: 40 * DefaultStyle.dp
|
||||
visible: eventLogCore.handled
|
||||
property EventLogGui eventLogGui
|
||||
property var eventLogCore: eventLogGui.core
|
||||
|
||||
Rectangle {
|
||||
height: 1
|
||||
Layout.fillWidth: true
|
||||
color: DefaultStyle.main2_200
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
Layout.rightMargin: 20 * DefaultStyle.dp
|
||||
Layout.leftMargin: 20 * DefaultStyle.dp
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
|
||||
Text {
|
||||
id: message
|
||||
text: eventLogCore.eventDetails
|
||||
font: Typography.p3
|
||||
color: eventLogCore.important ? DefaultStyle.danger_500main : DefaultStyle.main2_500main
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
}
|
||||
Text {
|
||||
id: date
|
||||
text: UtilsCpp.toDateTimeString(eventLogCore.timestamp)
|
||||
font: Typography.p3
|
||||
color: DefaultStyle.main2_500main
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
height: 1
|
||||
Layout.fillWidth: true
|
||||
color: DefaultStyle.main2_200
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -16,10 +16,10 @@ RowLayout {
|
|||
property alias callHeaderContent: splitPanel.headerContent
|
||||
spacing: 0
|
||||
|
||||
onChatChanged: {
|
||||
//onEventChanged: {
|
||||
// TODO : call when all messages read after scroll to unread feature available
|
||||
// if (chat) chat.core.lMarkAsRead()
|
||||
}
|
||||
//}
|
||||
MainRightPanel {
|
||||
id: splitPanel
|
||||
Layout.fillWidth: true
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue