mirror of
https://gitlab.linphone.org/BC/public/linphone-desktop.git
synced 2026-01-17 03:18:07 +00:00
delete history for chatroom
delete chat message delete chat room
This commit is contained in:
parent
179be1bb15
commit
bdff2bddcd
24 changed files with 435 additions and 97 deletions
|
|
@ -52,11 +52,11 @@
|
|||
#include "core/call/CallGui.hpp"
|
||||
#include "core/call/CallList.hpp"
|
||||
#include "core/call/CallProxy.hpp"
|
||||
#include "core/chat/ChatProxy.hpp"
|
||||
#include "core/chat/message/ChatMessageProxy.hpp"
|
||||
#include "core/chat/message/ChatMessageList.hpp"
|
||||
#include "core/chat/message/ChatMessageGui.hpp"
|
||||
#include "core/camera/CameraGui.hpp"
|
||||
#include "core/chat/ChatProxy.hpp"
|
||||
#include "core/chat/message/ChatMessageGui.hpp"
|
||||
#include "core/chat/message/ChatMessageList.hpp"
|
||||
#include "core/chat/message/ChatMessageProxy.hpp"
|
||||
#include "core/conference/ConferenceGui.hpp"
|
||||
#include "core/conference/ConferenceInfoGui.hpp"
|
||||
#include "core/conference/ConferenceInfoProxy.hpp"
|
||||
|
|
@ -263,7 +263,7 @@ void App::setAutoStart(bool enabled) {
|
|||
// -----------------------------------------------------------------------------
|
||||
|
||||
App::App(int &argc, char *argv[])
|
||||
: SingleApplication(argc, argv, true, Mode::User | Mode::ExcludeAppPath | Mode::ExcludeAppVersion) {
|
||||
: SingleApplication(argc, argv, true, Mode::User | Mode::ExcludeAppPath | Mode::ExcludeAppVersion) {
|
||||
// Do not use APPLICATION_NAME here.
|
||||
// The EXECUTABLE_NAME will be used in qt standard paths. It's our goal.
|
||||
QThread::currentThread()->setPriority(QThread::HighPriority);
|
||||
|
|
@ -526,7 +526,7 @@ void App::initCore() {
|
|||
setLocale(settings->getConfigLocale());
|
||||
setAutoStart(settings->getAutoStart());
|
||||
setQuitOnLastWindowClosed(settings->getExitOnClose());
|
||||
}
|
||||
}
|
||||
const QUrl url("qrc:/qt/qml/Linphone/view/Page/Window/Main/MainWindow.qml");
|
||||
QObject::connect(
|
||||
mEngine, &QQmlApplicationEngine::objectCreated, this,
|
||||
|
|
@ -577,28 +577,28 @@ void App::initLocale() {
|
|||
mLocale = QLocale(QLocale::English);
|
||||
if (!installLocale(*this, *mDefaultTranslatorCore, mLocale)) qFatal("Unable to install default translator.");
|
||||
|
||||
// if (installLocale(*this, *mTranslatorCore, getLocale())) {
|
||||
// qDebug() << "installed locale" << getLocale().name();
|
||||
// return;
|
||||
// }
|
||||
// if (installLocale(*this, *mTranslatorCore, getLocale())) {
|
||||
// qDebug() << "installed locale" << getLocale().name();
|
||||
// return;
|
||||
// }
|
||||
|
||||
// Try to use system locale.
|
||||
// #ifdef Q_OS_MACOS
|
||||
// Use this workaround if there is still an issue about detecting wrong language from system on Mac. Qt doesn't use
|
||||
// the current system language on QLocale::system(). So we need to get it from user settings and overwrite its
|
||||
// Locale.
|
||||
// QSettings settings;
|
||||
// QString preferredLanguage = settings.value("AppleLanguages").toStringList().first();
|
||||
// QStringList qtLocale = QLocale::system().name().split('_');
|
||||
// if(qtLocale[0] != preferredLanguage){
|
||||
// qInfo() << "Override Qt language from " << qtLocale[0] << " to the preferred language : " <<
|
||||
// preferredLanguage; qtLocale[0] = preferredLanguage;
|
||||
// }
|
||||
// QLocale sysLocale = QLocale(qtLocale.join('_'));
|
||||
// #else
|
||||
// Try to use system locale.
|
||||
// #ifdef Q_OS_MACOS
|
||||
// Use this workaround if there is still an issue about detecting wrong language from system on Mac. Qt doesn't use
|
||||
// the current system language on QLocale::system(). So we need to get it from user settings and overwrite its
|
||||
// Locale.
|
||||
// QSettings settings;
|
||||
// QString preferredLanguage = settings.value("AppleLanguages").toStringList().first();
|
||||
// QStringList qtLocale = QLocale::system().name().split('_');
|
||||
// if(qtLocale[0] != preferredLanguage){
|
||||
// qInfo() << "Override Qt language from " << qtLocale[0] << " to the preferred language : " <<
|
||||
// preferredLanguage; qtLocale[0] = preferredLanguage;
|
||||
// }
|
||||
// QLocale sysLocale = QLocale(qtLocale.join('_'));
|
||||
// #else
|
||||
QLocale sysLocale(QLocale::system().name()); // Use Locale from name because Qt has a bug where it didn't use the
|
||||
// QLocale::language (aka : translator.language != locale.language) on
|
||||
// Mac. #endif
|
||||
// QLocale::language (aka : translator.language != locale.language) on
|
||||
// Mac. #endif
|
||||
if (installLocale(*this, *mTranslatorCore, sysLocale)) {
|
||||
qDebug() << "installed sys locale" << sysLocale.name();
|
||||
setLocale(sysLocale.name());
|
||||
|
|
@ -785,34 +785,36 @@ void App::createCommandParser() {
|
|||
//: "A free and open source SIP video-phone."
|
||||
mParser->setApplicationDescription(tr("application_description"));
|
||||
//: "Send an order to the application towards a command line"
|
||||
mParser->addPositionalArgument("command", tr("command_line_arg_order").replace("%1", APPLICATION_NAME), "[command]");
|
||||
mParser->addPositionalArgument("command", tr("command_line_arg_order").replace("%1", APPLICATION_NAME),
|
||||
"[command]");
|
||||
mParser->addOptions({
|
||||
//: "Show this help"
|
||||
{{"h", "help"}, tr("command_line_option_show_help")},
|
||||
//: "Show this help"
|
||||
{{"h", "help"}, tr("command_line_option_show_help")},
|
||||
|
||||
//{"cli-help", tr("commandLineOptionCliHelp").replace("%1", APPLICATION_NAME)},
|
||||
|
||||
//:"Show app version"
|
||||
{{"v", "version"}, tr("command_line_option_show_app_version")},
|
||||
//:"Show app version"
|
||||
{{"v", "version"}, tr("command_line_option_show_app_version")},
|
||||
|
||||
//{"config", tr("command_line_option_config").replace("%1", EXECUTABLE_NAME), tr("command_line_option_config_arg")},
|
||||
//{"config", tr("command_line_option_config").replace("%1", EXECUTABLE_NAME),
|
||||
// tr("command_line_option_config_arg")},
|
||||
|
||||
{"fetch-config",
|
||||
//: "Specify the linphone configuration file to be fetched. It will be merged with the current configuration."
|
||||
tr("command_line_option_config_to_fetch")
|
||||
.replace("%1", EXECUTABLE_NAME),
|
||||
//: "URL, path or file"
|
||||
tr("command_line_option_config_to_fetch_arg")},
|
||||
//: "Specify the linphone configuration file to be fetched. It will be merged with the current configuration."
|
||||
tr("command_line_option_config_to_fetch").replace("%1", EXECUTABLE_NAME),
|
||||
//: "URL, path or file"
|
||||
tr("command_line_option_config_to_fetch_arg")},
|
||||
|
||||
//{{"c", "call"}, tr("command_line_option_call").replace("%1", EXECUTABLE_NAME), tr("command_line_option_call_arg")},
|
||||
//{{"c", "call"}, tr("command_line_option_call").replace("%1", EXECUTABLE_NAME),
|
||||
// tr("command_line_option_call_arg")},
|
||||
|
||||
{"minimized", tr("command_line_option_minimized")},
|
||||
{"minimized", tr("command_line_option_minimized")},
|
||||
|
||||
//: "Log to stdout some debug information while running"
|
||||
{{"V", "verbose"}, tr("command_line_option_log_to_stdout")},
|
||||
//: "Log to stdout some debug information while running"
|
||||
{{"V", "verbose"}, tr("command_line_option_log_to_stdout")},
|
||||
|
||||
//: "Print only logs from the application"
|
||||
{"qt-logs-only", tr("command_line_option_print_app_logs_only")},
|
||||
//: "Print only logs from the application"
|
||||
{"qt-logs-only", tr("command_line_option_print_app_logs_only")},
|
||||
});
|
||||
}
|
||||
// Should be call only at first start
|
||||
|
|
@ -1174,7 +1176,7 @@ void App::setSysTrayIcon() {
|
|||
//: "Afficher"
|
||||
restoreAction->setText(visible ? tr("hide_action") : tr("show_action"));
|
||||
};
|
||||
setRestoreActionText(root->isVisible());
|
||||
setRestoreActionText(root ? root->isVisible() : false);
|
||||
connect(root, &QWindow::visibleChanged, restoreAction, setRestoreActionText);
|
||||
|
||||
root->connect(restoreAction, &QAction::triggered, this, [this, restoreAction](bool checked) {
|
||||
|
|
|
|||
|
|
@ -88,18 +88,80 @@ ChatCore::~ChatCore() {
|
|||
|
||||
void ChatCore::setSelf(QSharedPointer<ChatCore> me) {
|
||||
mChatModelConnection = SafeConnection<ChatCore, ChatModel>::create(me, mChatModel);
|
||||
// mChatModelConnection->makeConnectToCore(&ChatCore::lSetMicrophoneMuted, [this](bool isMuted) {
|
||||
// mChatModelConnection->invokeToModel(
|
||||
// [this, isMuted]() { mChatModel->setMicrophoneMuted(isMuted); });
|
||||
// });
|
||||
mChatModelConnection->makeConnectToCore(&ChatCore::lDeleteHistory, [this]() {
|
||||
mChatModelConnection->invokeToModel([this]() { mChatModel->deleteHistory(); });
|
||||
});
|
||||
mChatModelConnection->makeConnectToModel(&ChatModel::historyDeleted, [this]() {
|
||||
mChatModelConnection->invokeToCore([this]() {
|
||||
qDebug() << log().arg("history deleted for chatRoom") << this;
|
||||
clearMessagesList();
|
||||
Utils::showInformationPopup(tr("Supprimé"), tr("L'historique des messages a été supprimé."), true);
|
||||
});
|
||||
});
|
||||
mChatModelConnection->makeConnectToCore(&ChatCore::lUpdateUnreadCount, [this]() {
|
||||
mChatModelConnection->invokeToModel([this]() {
|
||||
auto count = mChatModel->getUnreadMessagesCount();
|
||||
mChatModelConnection->invokeToCore([this, count] { setUnreadMessagesCount(count); });
|
||||
});
|
||||
});
|
||||
|
||||
mChatModelConnection->makeConnectToCore(&ChatCore::lDelete, [this]() {
|
||||
mChatModelConnection->invokeToModel([this]() { mChatModel->deleteChatRoom(); });
|
||||
});
|
||||
mChatModelConnection->makeConnectToModel(
|
||||
&ChatModel::deleted, [this]() { mChatModelConnection->invokeToCore([this]() { emit deleted(); }); });
|
||||
|
||||
mChatModelConnection->makeConnectToModel(&ChatModel::chatMessageReceived,
|
||||
[this](const std::shared_ptr<linphone::ChatRoom> &chatRoom,
|
||||
const std::shared_ptr<const linphone::EventLog> &eventLog) {
|
||||
if (mChatModel->getMonitor() != chatRoom) return;
|
||||
qDebug() << "MESSAGE RECEIVED IN CHATROOM" << mChatModel->getTitle();
|
||||
// mChatModelConnection->invokeToCore([this, isMuted]() {
|
||||
// setMicrophoneMuted(isMuted); });
|
||||
emit lUpdateLastMessage();
|
||||
emit lUpdateUnreadCount();
|
||||
auto message = eventLog->getChatMessage();
|
||||
qDebug() << "EVENT LOG RECEIVED IN CHATROOM" << mChatModel->getTitle();
|
||||
if (message) {
|
||||
auto newMessage = ChatMessageCore::create(message);
|
||||
mChatModelConnection->invokeToCore([this, newMessage]() {
|
||||
qDebug() << log().arg("append message to chatRoom") << this;
|
||||
appendMessageToMessageList(newMessage);
|
||||
});
|
||||
}
|
||||
});
|
||||
mChatModelConnection->makeConnectToModel(
|
||||
&ChatModel::chatMessagesReceived, [this](const std::shared_ptr<linphone::ChatRoom> &chatRoom,
|
||||
const std::list<std::shared_ptr<linphone::EventLog>> &chatMessages) {
|
||||
if (mChatModel->getMonitor() != chatRoom) return;
|
||||
emit lUpdateLastMessage();
|
||||
emit lUpdateUnreadCount();
|
||||
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);
|
||||
}
|
||||
}
|
||||
mChatModelConnection->invokeToCore([this, list]() {
|
||||
qDebug() << log().arg("append messages to chatRoom") << this;
|
||||
appendMessagesToMessageList(list);
|
||||
});
|
||||
});
|
||||
|
||||
mChatModelConnection->makeConnectToCore(&ChatCore::lMarkAsRead, [this]() {
|
||||
mChatModelConnection->invokeToModel([this]() { mChatModel->markAsRead(); });
|
||||
});
|
||||
mChatModelConnection->makeConnectToModel(&ChatModel::messagesRead, [this]() {
|
||||
auto unread = mChatModel->getUnreadMessagesCount();
|
||||
mChatModelConnection->invokeToCore([this, unread]() { setUnreadMessagesCount(unread); });
|
||||
});
|
||||
|
||||
mChatModelConnection->makeConnectToCore(&ChatCore::lUpdateLastMessage, [this]() {
|
||||
mChatModelConnection->invokeToModel([this]() {
|
||||
auto message = mChatModel->getLastMessageInHistory();
|
||||
mChatModelConnection->invokeToCore([this, message]() { setLastMessageInHistory(message); });
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
QDateTime ChatCore::getLastUpdatedTime() const {
|
||||
|
|
@ -175,6 +237,7 @@ void ChatCore::setUnreadMessagesCount(int count) {
|
|||
QList<QSharedPointer<ChatMessageCore>> ChatCore::getChatMessageList() const {
|
||||
return mChatMessageList;
|
||||
}
|
||||
|
||||
void ChatCore::resetChatMessageList(QList<QSharedPointer<ChatMessageCore>> list) {
|
||||
mChatMessageList = list;
|
||||
emit messageListChanged();
|
||||
|
|
@ -190,6 +253,12 @@ void ChatCore::appendMessagesToMessageList(QList<QSharedPointer<ChatMessageCore>
|
|||
if (nbAdded > 0) emit messageListChanged();
|
||||
}
|
||||
|
||||
void ChatCore::appendMessageToMessageList(QSharedPointer<ChatMessageCore> message) {
|
||||
if (mChatMessageList.contains(message)) return;
|
||||
mChatMessageList.append(message);
|
||||
emit messageListChanged();
|
||||
}
|
||||
|
||||
void ChatCore::removeMessagesFromMessageList(QList<QSharedPointer<ChatMessageCore>> list) {
|
||||
int nbRemoved = 0;
|
||||
for (auto &message : list) {
|
||||
|
|
@ -201,6 +270,11 @@ void ChatCore::removeMessagesFromMessageList(QList<QSharedPointer<ChatMessageCor
|
|||
if (nbRemoved > 0) emit messageListChanged();
|
||||
}
|
||||
|
||||
void ChatCore::clearMessagesList() {
|
||||
mChatMessageList.clear();
|
||||
emit messageListChanged();
|
||||
}
|
||||
|
||||
std::shared_ptr<ChatModel> ChatCore::getModel() const {
|
||||
return mChatModel;
|
||||
}
|
||||
|
|
@ -70,8 +70,10 @@ public:
|
|||
|
||||
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();
|
||||
|
||||
QString getAvatarUri() const;
|
||||
void setAvatarUri(QString avatarUri);
|
||||
|
|
@ -86,6 +88,14 @@ signals:
|
|||
void unreadMessagesCountChanged(int count);
|
||||
void messageListChanged();
|
||||
void avatarUriChanged();
|
||||
void deleted();
|
||||
|
||||
void lDeleteMessage();
|
||||
void lDelete();
|
||||
void lDeleteHistory();
|
||||
void lMarkAsRead();
|
||||
void lUpdateLastMessage();
|
||||
void lUpdateUnreadCount();
|
||||
|
||||
private:
|
||||
QString id;
|
||||
|
|
|
|||
|
|
@ -67,6 +67,17 @@ void ChatList::setSelf(QSharedPointer<ChatList> me) {
|
|||
chats->push_back(model);
|
||||
}
|
||||
mModelConnection->invokeToCore([this, chats]() {
|
||||
for (auto &chat : getSharedList<ChatCore>()) {
|
||||
if (chat) disconnect(chat.get(), &ChatCore::deleted, this, nullptr);
|
||||
}
|
||||
for (auto &chat : *chats) {
|
||||
connect(chat.get(), &ChatCore::deleted, this, [this, chat] {
|
||||
remove(chat);
|
||||
// We cannot use countChanged here because it is called before mList
|
||||
// really has removed the item, then emit specific signal
|
||||
emit chatRemoved(chat ? new ChatGui(chat) : nullptr);
|
||||
});
|
||||
}
|
||||
mustBeInMainThread(getClassName());
|
||||
resetData<ChatCore>(*chats);
|
||||
delete chats;
|
||||
|
|
@ -78,7 +89,7 @@ void ChatList::setSelf(QSharedPointer<ChatList> me) {
|
|||
&CoreModel::chatRoomStateChanged,
|
||||
[this](const std::shared_ptr<linphone::Core> &core, const std::shared_ptr<linphone::ChatRoom> &chatRoom,
|
||||
linphone::ChatRoom::State state) {
|
||||
// check account, filtre, puis ajout si c'est bon
|
||||
// check account, filter, then add if ok
|
||||
if (chatRoom->getAccount() == core->getDefaultAccount()) {
|
||||
if (state == linphone::ChatRoom::State::Created) {
|
||||
auto list = getSharedList<ChatCore>();
|
||||
|
|
|
|||
|
|
@ -46,6 +46,7 @@ public:
|
|||
signals:
|
||||
void lUpdate();
|
||||
void filterChanged(QString filter);
|
||||
void chatRemoved(ChatGui *chat);
|
||||
|
||||
private:
|
||||
QString mFilter;
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@ void ChatProxy::setSourceModel(QAbstractItemModel *model) {
|
|||
if (newChatList) {
|
||||
connect(this, &ChatProxy::filterTextChanged, newChatList,
|
||||
[this, newChatList] { emit newChatList->filterChanged(getFilterText()); });
|
||||
connect(newChatList, &ChatList::chatRemoved, this, &ChatProxy::chatRemoved);
|
||||
}
|
||||
setSourceModels(new SortFilterList(model));
|
||||
sort(0);
|
||||
|
|
|
|||
|
|
@ -41,6 +41,9 @@ public:
|
|||
|
||||
Q_INVOKABLE int findChatIndex(ChatGui *chatGui);
|
||||
|
||||
signals:
|
||||
void chatRemoved(ChatGui *chat);
|
||||
|
||||
protected:
|
||||
QSharedPointer<ChatList> mList;
|
||||
DECLARE_ABSTRACT_OBJECT
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@
|
|||
|
||||
#include "ChatMessageCore.hpp"
|
||||
#include "core/App.hpp"
|
||||
#include "core/chat/ChatCore.hpp"
|
||||
#include "model/tool/ToolModel.hpp"
|
||||
|
||||
DEFINE_ABSTRACT_OBJECT(ChatMessageCore)
|
||||
|
|
@ -51,6 +52,13 @@ ChatMessageCore::~ChatMessageCore() {
|
|||
|
||||
void ChatMessageCore::setSelf(QSharedPointer<ChatMessageCore> me) {
|
||||
mChatMessageModelConnection = SafeConnection<ChatMessageCore, ChatMessageModel>::create(me, mChatMessageModel);
|
||||
mChatMessageModelConnection->makeConnectToCore(&ChatMessageCore::lDelete, [this] {
|
||||
mChatMessageModelConnection->invokeToModel([this] { mChatMessageModel->deleteMessageFromChatRoom(); });
|
||||
});
|
||||
mChatMessageModelConnection->makeConnectToModel(&ChatMessageModel::messageDeleted, [this]() {
|
||||
Utils::showInformationPopup(tr("Supprimé"), tr("Message supprimé"), true);
|
||||
emit deleted();
|
||||
});
|
||||
}
|
||||
|
||||
QDateTime ChatMessageCore::getTimestamp() const {
|
||||
|
|
@ -93,3 +101,7 @@ void ChatMessageCore::setIsRemoteMessage(bool isRemote) {
|
|||
emit isRemoteMessageChanged(isRemote);
|
||||
}
|
||||
}
|
||||
|
||||
std::shared_ptr<ChatMessageModel> ChatMessageCore::getModel() const {
|
||||
return mChatMessageModel;
|
||||
}
|
||||
|
|
@ -29,6 +29,8 @@
|
|||
|
||||
#include <linphone++/linphone.hh>
|
||||
|
||||
class ChatCore;
|
||||
|
||||
class ChatMessageCore : public QObject, public AbstractObject {
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(QDateTime timestamp READ getTimestamp WRITE setTimestamp NOTIFY timestampChanged)
|
||||
|
|
@ -55,14 +57,18 @@ public:
|
|||
bool isRemoteMessage() const;
|
||||
void setIsRemoteMessage(bool isRemote);
|
||||
|
||||
std::shared_ptr<ChatMessageModel> getModel() const;
|
||||
|
||||
signals:
|
||||
void timestampChanged(QDateTime timestamp);
|
||||
void textChanged(QString text);
|
||||
void isRemoteMessageChanged(bool isRemote);
|
||||
|
||||
void lDelete();
|
||||
void deleted();
|
||||
|
||||
private:
|
||||
DECLARE_ABSTRACT_OBJECT
|
||||
QString mText;
|
||||
DECLARE_ABSTRACT_OBJECT QString mText;
|
||||
QString mPeerAddress;
|
||||
QString mPeerName;
|
||||
QDateTime mTimestamp;
|
||||
|
|
|
|||
|
|
@ -21,9 +21,9 @@
|
|||
#include "ChatMessageList.hpp"
|
||||
#include "ChatMessageCore.hpp"
|
||||
#include "ChatMessageGui.hpp"
|
||||
#include "core/App.hpp"
|
||||
#include "core/chat/ChatCore.hpp"
|
||||
#include "core/chat/ChatGui.hpp"
|
||||
#include "core/App.hpp"
|
||||
|
||||
#include <QSharedPointer>
|
||||
#include <linphone++/linphone.hh>
|
||||
|
|
@ -39,7 +39,8 @@ QSharedPointer<ChatMessageList> ChatMessageList::create() {
|
|||
return model;
|
||||
}
|
||||
|
||||
QSharedPointer<ChatMessageCore> ChatMessageList::createChatMessageCore(const std::shared_ptr<linphone::ChatMessage> &chatMessage) {
|
||||
QSharedPointer<ChatMessageCore>
|
||||
ChatMessageList::createChatMessageCore(const std::shared_ptr<linphone::ChatMessage> &chatMessage) {
|
||||
auto chatMessageCore = ChatMessageCore::create(chatMessage);
|
||||
return chatMessageCore;
|
||||
}
|
||||
|
|
@ -55,7 +56,7 @@ ChatMessageList::~ChatMessageList() {
|
|||
mModelConnection = nullptr;
|
||||
}
|
||||
|
||||
ChatGui* ChatMessageList::getChat() const {
|
||||
ChatGui *ChatMessageList::getChat() const {
|
||||
if (mChatCore) return new ChatGui(mChatCore);
|
||||
else return nullptr;
|
||||
}
|
||||
|
|
@ -66,12 +67,14 @@ QSharedPointer<ChatCore> ChatMessageList::getChatCore() const {
|
|||
|
||||
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);
|
||||
emit chatChanged();
|
||||
}
|
||||
}
|
||||
|
||||
void ChatMessageList::setChatGui(ChatGui* chat) {
|
||||
void ChatMessageList::setChatGui(ChatGui *chat) {
|
||||
auto chatCore = chat ? chat->mCore : nullptr;
|
||||
setChatCore(chatCore);
|
||||
}
|
||||
|
|
@ -80,17 +83,17 @@ void ChatMessageList::setSelf(QSharedPointer<ChatMessageList> me) {
|
|||
mModelConnection = SafeConnection<ChatMessageList, CoreModel>::create(me, CoreModel::getInstance());
|
||||
|
||||
mModelConnection->makeConnectToCore(&ChatMessageList::lUpdate, [this]() {
|
||||
// mModelConnection->invokeToModel([this]() {
|
||||
// // Avoid copy to lambdas
|
||||
// QList<QSharedPointer<CallCore>> *calls = new QList<QSharedPointer<CallCore>>();
|
||||
// mustBeInLinphoneThread(getClassName());
|
||||
// mModelConnection->invokeToCore([this, calls, currentCallCore]() {
|
||||
// mustBeInMainThread(getClassName());
|
||||
// resetData<CallCore>(*calls);
|
||||
// });
|
||||
// });
|
||||
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);
|
||||
});
|
||||
|
||||
|
|
@ -104,6 +107,7 @@ void ChatMessageList::setSelf(QSharedPointer<ChatMessageList> me) {
|
|||
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>()));
|
||||
if (role == Qt::DisplayRole)
|
||||
return QVariant::fromValue(new ChatMessageGui(mList[row].objectCast<ChatMessageCore>()));
|
||||
return QVariant();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -103,6 +103,22 @@ QString ChatModel::getLastMessageInHistory(std::list<std::shared_ptr<linphone::C
|
|||
int ChatModel::getUnreadMessagesCount() const {
|
||||
return mMonitor->getUnreadMessagesCount();
|
||||
}
|
||||
|
||||
void ChatModel::markAsRead() {
|
||||
mMonitor->markAsRead();
|
||||
emit messagesRead();
|
||||
}
|
||||
|
||||
void ChatModel::deleteHistory() {
|
||||
mMonitor->deleteHistory();
|
||||
emit historyDeleted();
|
||||
}
|
||||
|
||||
void ChatModel::deleteChatRoom() {
|
||||
CoreModel::getInstance()->getCore()->deleteChatRoom(mMonitor);
|
||||
emit deleted();
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------//
|
||||
|
||||
void ChatModel::onIsComposingReceived(const std::shared_ptr<linphone::ChatRoom> &chatRoom,
|
||||
|
|
|
|||
|
|
@ -42,8 +42,16 @@ public:
|
|||
QString getPeerAddress() const;
|
||||
QString getLastMessageInHistory(std::list<std::shared_ptr<linphone::Content>> startList = {}) const;
|
||||
int getUnreadMessagesCount() const;
|
||||
void markAsRead();
|
||||
std::list<std::shared_ptr<linphone::ChatMessage>> getHistory() const;
|
||||
QString getIdentifier() const;
|
||||
void deleteHistory();
|
||||
void deleteChatRoom();
|
||||
|
||||
signals:
|
||||
void historyDeleted();
|
||||
void messagesRead();
|
||||
void deleted();
|
||||
|
||||
private:
|
||||
DECLARE_ABSTRACT_OBJECT
|
||||
|
|
|
|||
|
|
@ -59,3 +59,11 @@ ChatMessageModel::onFileTransferSend(const std::shared_ptr<linphone::ChatMessage
|
|||
size_t size) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void ChatMessageModel::deleteMessageFromChatRoom() {
|
||||
auto chatRoom = mMonitor->getChatRoom();
|
||||
if (chatRoom) {
|
||||
chatRoom->deleteMessage(mMonitor);
|
||||
emit messageDeleted();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -42,6 +42,11 @@ public:
|
|||
|
||||
QString getPeerAddress() const;
|
||||
|
||||
void deleteMessageFromChatRoom();
|
||||
|
||||
signals:
|
||||
void messageDeleted();
|
||||
|
||||
private:
|
||||
DECLARE_ABSTRACT_OBJECT
|
||||
virtual std::shared_ptr<linphone::Buffer> onFileTransferSend(const std::shared_ptr<linphone::ChatMessage> &message,
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ list(APPEND _LINPHONEAPP_QML_FILES
|
|||
view/Control/Button/Settings/SwitchSetting.qml
|
||||
|
||||
view/Control/Container/Carousel.qml
|
||||
view/Control/Container/DetailLayout.qml
|
||||
view/Control/Container/FormItemLayout.qml
|
||||
view/Control/Container/ScrollBar.qml
|
||||
view/Control/Container/Section.qml
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ ColumnLayout {
|
|||
spacing: Math.round(30 * DefaultStyle.dp)
|
||||
|
||||
property var callHistoryGui
|
||||
property var chatGui
|
||||
|
||||
property FriendGui contact
|
||||
property var conferenceInfo: callHistoryGui?.core.conferenceInfo
|
||||
|
|
|
|||
54
Linphone/view/Control/Container/DetailLayout.qml
Normal file
54
Linphone/view/Control/Container/DetailLayout.qml
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
import QtQuick
|
||||
import QtQuick.Effects
|
||||
import QtQuick.Layouts
|
||||
import QtQuick.Controls.Basic as Control
|
||||
import Linphone
|
||||
import UtilsCpp
|
||||
import SettingsCpp
|
||||
import 'qrc:/qt/qml/Linphone/view/Style/buttonStyle.js' as ButtonStyle
|
||||
|
||||
ColumnLayout {
|
||||
id: mainItem
|
||||
spacing: Math.round(15 * DefaultStyle.dp)
|
||||
property string label
|
||||
property var icon
|
||||
property alias content: contentControl.contentItem
|
||||
signal titleIconClicked
|
||||
RowLayout {
|
||||
spacing: Math.round(10 * DefaultStyle.dp)
|
||||
Text {
|
||||
text: mainItem.label
|
||||
color: DefaultStyle.main1_500_main
|
||||
font {
|
||||
pixelSize: Typography.h4.pixelSize
|
||||
weight: Typography.h4.weight
|
||||
}
|
||||
}
|
||||
RoundButton {
|
||||
visible: mainItem.icon != undefined
|
||||
icon.source: mainItem.icon
|
||||
style: ButtonStyle.noBackgroundOrange
|
||||
onClicked: mainItem.titleIconClicked()
|
||||
}
|
||||
Item {
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
RoundButton {
|
||||
id: expandButton
|
||||
style: ButtonStyle.noBackground
|
||||
checkable: true
|
||||
checked: true
|
||||
icon.source: checked ? AppIcons.upArrow : AppIcons.downArrow
|
||||
KeyNavigation.down: contentControl
|
||||
}
|
||||
}
|
||||
RoundedPane {
|
||||
id: contentControl
|
||||
visible: expandButton.checked
|
||||
Layout.fillWidth: true
|
||||
leftPadding: Math.round(20 * DefaultStyle.dp)
|
||||
rightPadding: Math.round(20 * DefaultStyle.dp)
|
||||
topPadding: Math.round(17 * DefaultStyle.dp)
|
||||
bottomPadding: Math.round(17 * DefaultStyle.dp)
|
||||
}
|
||||
}
|
||||
|
|
@ -31,13 +31,18 @@ ListView {
|
|||
}
|
||||
filterText: mainItem.searchText
|
||||
onFilterTextChanged: maxDisplayItems = initialDisplayItems
|
||||
initialDisplayItems: Math.max(
|
||||
20,
|
||||
2 * mainItem.height / (Math.round(56 * DefaultStyle.dp)))
|
||||
displayItemsStep: 3 * initialDisplayItems / 2
|
||||
onModelReset: {
|
||||
mainItem.resultsReceived()
|
||||
}
|
||||
initialDisplayItems: Math.max(
|
||||
20,
|
||||
2 * mainItem.height / (Math.round(56 * DefaultStyle.dp)))
|
||||
displayItemsStep: 3 * initialDisplayItems / 2
|
||||
onModelReset: {
|
||||
mainItem.resultsReceived()
|
||||
}
|
||||
onChatRemoved: {
|
||||
var indexToSelect = mainItem.currentIndex
|
||||
mainItem.currentIndex = -1
|
||||
mainItem.currentIndex = indexToSelect
|
||||
}
|
||||
}
|
||||
// flickDeceleration: 10000
|
||||
spacing: Math.round(10 * DefaultStyle.dp)
|
||||
|
|
@ -56,19 +61,15 @@ ListView {
|
|||
|
||||
onActiveFocusChanged: if (activeFocus && currentIndex < 0 && count > 0)
|
||||
currentIndex = 0
|
||||
onCountChanged: {
|
||||
if (currentIndex < 0 && count > 0) {
|
||||
mainItem.currentIndex = 0 // Select first item after loading model
|
||||
}
|
||||
if (atYBeginning)
|
||||
positionViewAtBeginning() // Stay at beginning
|
||||
}
|
||||
|
||||
onAtYEndChanged: {
|
||||
if (atYEnd && count > 0) {
|
||||
chatProxy.displayMore()
|
||||
}
|
||||
}
|
||||
onCountChanged: {
|
||||
if (count > 0 && currentIndex < 0) currentIndex = 0
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------
|
||||
function moveToCurrentItem() {
|
||||
|
|
@ -93,10 +94,6 @@ ListView {
|
|||
}
|
||||
|
||||
// //----------------------------------------------------------------
|
||||
onVisibleChanged: {
|
||||
// if (!visible)
|
||||
// currentIndex = -1
|
||||
}
|
||||
|
||||
BusyIndicator {
|
||||
anchors.horizontalCenter: mainItem.horizontalCenter
|
||||
|
|
@ -218,8 +215,39 @@ ListView {
|
|||
//sourdine, éphémère, IMDN
|
||||
}
|
||||
}
|
||||
PopupButton {
|
||||
id: chatroomPopup
|
||||
// z: 1
|
||||
popup.x: 0
|
||||
popup.padding: Math.round(10 * DefaultStyle.dp)
|
||||
visible: mouseArea.containsMouse || hovered || popup.opened
|
||||
enabled: visible
|
||||
popup.contentItem: ColumnLayout {
|
||||
IconLabelButton {
|
||||
//: "Supprimer"
|
||||
text: qsTr("chat_room_delete")
|
||||
icon.source: AppIcons.trashCan
|
||||
spacing: Math.round(10 * DefaultStyle.dp)
|
||||
Layout.fillWidth: true
|
||||
onClicked: {
|
||||
mainWindow.showConfirmationLambdaPopup(qsTr("Supprimer le chat ?"),
|
||||
qsTr("Le chat ainsi que tous ses messages seront supprimés. Souhaitez-vous continuer ?"),
|
||||
"",
|
||||
function(confirmed) {
|
||||
if (confirmed) {
|
||||
modelData.core.lDelete()
|
||||
chatroomPopup.close()
|
||||
}
|
||||
})
|
||||
}
|
||||
style: ButtonStyle.noBackgroundRed
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
MouseArea {
|
||||
id: mouseArea
|
||||
hoverEnabled: true
|
||||
anchors.fill: parent
|
||||
focus: true
|
||||
|
|
|
|||
|
|
@ -16,10 +16,59 @@ Control.Control {
|
|||
|
||||
property string imgUrl
|
||||
property string contentText
|
||||
|
||||
topPadding: Math.round(12 * DefaultStyle.dp)
|
||||
bottomPadding: Math.round(12 * DefaultStyle.dp)
|
||||
leftPadding: Math.round(18 * DefaultStyle.dp)
|
||||
rightPadding: Math.round(18 * DefaultStyle.dp)
|
||||
|
||||
signal messageDeletionRequested()
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
acceptedButtons: Qt.RightButton
|
||||
onClicked: (mouse) => {
|
||||
console.log("message clicked")
|
||||
if (mouse.button === Qt.RightButton) {
|
||||
optionsMenu.x = mouse.x
|
||||
optionsMenu.open()
|
||||
}
|
||||
}
|
||||
}
|
||||
Popup {
|
||||
id: optionsMenu
|
||||
background: Item {
|
||||
anchors.fill: parent
|
||||
Rectangle {
|
||||
id: popupBackground
|
||||
anchors.fill: parent
|
||||
color: DefaultStyle.grey_0
|
||||
radius: Math.round(16 * DefaultStyle.dp)
|
||||
}
|
||||
MultiEffect {
|
||||
source: popupBackground
|
||||
anchors.fill: popupBackground
|
||||
shadowEnabled: true
|
||||
shadowBlur: 0.1
|
||||
shadowColor: DefaultStyle.grey_1000
|
||||
shadowOpacity: 0.4
|
||||
}
|
||||
}
|
||||
contentItem: ColumnLayout {
|
||||
IconLabelButton {
|
||||
//: "Supprimer"
|
||||
text: qsTr("chat_message_delete")
|
||||
icon.source: AppIcons.trashCan
|
||||
spacing: Math.round(10 * DefaultStyle.dp)
|
||||
Layout.fillWidth: true
|
||||
onClicked: {
|
||||
mainItem.messageDeletionRequested()
|
||||
optionsMenu.close()
|
||||
}
|
||||
style: ButtonStyle.noBackgroundRed
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
background: Item {
|
||||
anchors.fill: parent
|
||||
|
|
|
|||
|
|
@ -15,6 +15,8 @@ ListView {
|
|||
|
||||
Component.onCompleted: positionViewAtEnd()
|
||||
|
||||
onCountChanged: positionViewAtEnd();
|
||||
|
||||
model: ChatMessageProxy {
|
||||
chatGui: mainItem.chat
|
||||
}
|
||||
|
|
@ -34,5 +36,7 @@ ListView {
|
|||
anchors.right: !isRemoteMessage && parent
|
||||
? parent.right
|
||||
: undefined
|
||||
|
||||
onMessageDeletionRequested: modelData.core.lDelete()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,6 +15,11 @@ RowLayout {
|
|||
property CallGui call
|
||||
property alias callHeaderContent: splitPanel.headerContent
|
||||
spacing: 0
|
||||
|
||||
onChatChanged: {
|
||||
// TODO : call when all messages read after scroll to unread feature available
|
||||
if (chat) chat.core.lMarkAsRead()
|
||||
}
|
||||
MainRightPanel {
|
||||
id: splitPanel
|
||||
Layout.fillWidth: true
|
||||
|
|
@ -62,9 +67,10 @@ RowLayout {
|
|||
BigButton {
|
||||
style: ButtonStyle.noBackground
|
||||
checkable: true
|
||||
checkedImageColor: DefaultStyle.main1_500_main
|
||||
icon.source: AppIcons.info
|
||||
onCheckedChanged: {
|
||||
|
||||
detailsPanel.visible = !detailsPanel.visible
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -184,8 +190,46 @@ RowLayout {
|
|||
color: DefaultStyle.grey_0
|
||||
anchors.fill: parent
|
||||
}
|
||||
contentItem: ColumnLayout {
|
||||
contentItem: CallHistoryLayout {
|
||||
chatGui: mainItem.chat
|
||||
detailContent: ColumnLayout {
|
||||
DetailLayout {
|
||||
//: Other actions
|
||||
label: qsTr("Autres actions")
|
||||
content: ColumnLayout {
|
||||
// IconLabelButton {
|
||||
// Layout.fillWidth: true
|
||||
// Layout.preferredHeight: Math.round(50 * DefaultStyle.dp)
|
||||
// icon.source: AppIcons.signOut
|
||||
// //: "Quitter la conversation"
|
||||
// text: qsTr("Quitter la conversation")
|
||||
// onClicked: {
|
||||
|
||||
// }
|
||||
// style: ButtonStyle.noBackground
|
||||
// }
|
||||
IconLabelButton {
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: Math.round(50 * DefaultStyle.dp)
|
||||
icon.source: AppIcons.trashCan
|
||||
//: "Supprimer l'historique"
|
||||
text: qsTr("Supprimer l'historique")
|
||||
onClicked: {
|
||||
mainWindow.showConfirmationLambdaPopup(qsTr("Supprimer l'historique ?"),
|
||||
qsTr("Tous les messages seront supprimés de la chatroom.Souhaitez-vous continuer ?"),
|
||||
"",
|
||||
function(confirmed) {
|
||||
if (confirmed) {
|
||||
mainItem.chat.core.lDeleteHistory()
|
||||
}
|
||||
})
|
||||
}
|
||||
style: ButtonStyle.noBackgroundRed
|
||||
}
|
||||
}
|
||||
}
|
||||
Item {Layout.fillHeight: true}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -154,9 +154,6 @@ AbstractMainPage {
|
|||
onCurrentIndexChanged: {
|
||||
mainItem.selectedChatGui = model.getAt(currentIndex)
|
||||
}
|
||||
onCountChanged: {
|
||||
mainItem.selectedChatGui = model.getAt(currentIndex)
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: mainItem
|
||||
|
|
@ -185,9 +182,6 @@ AbstractMainPage {
|
|||
objectName: "newChatItem"
|
||||
width: parent?.width
|
||||
height: parent?.height
|
||||
Control.StackView.onActivated: {
|
||||
callContactsList.forceActiveFocus()
|
||||
}
|
||||
ColumnLayout {
|
||||
anchors.fill: parent
|
||||
spacing: 0
|
||||
|
|
|
|||
|
|
@ -92,6 +92,7 @@ QtObject {
|
|||
property string settings: "image://internal/gear.svg"
|
||||
property string clock: "image://internal/clock.svg"
|
||||
property string note: "image://internal/note.svg"
|
||||
property string signOut: "image://internal/sign-out.svg"
|
||||
property string userRectangle: "image://internal/user-rectangle.svg"
|
||||
property string usersTwo: "image://internal/users.svg"
|
||||
property string globe: "image://internal/globe-hemisphere-west.svg"
|
||||
|
|
|
|||
|
|
@ -132,7 +132,7 @@
|
|||
normal: "#00000000",
|
||||
hovered: "#00000000",
|
||||
pressed: "#00000000",
|
||||
checked: Linphone.DefaultStyle.main1_500main
|
||||
checked: "#00000000"
|
||||
},
|
||||
text: {
|
||||
normal: Linphone.DefaultStyle.main2_600,
|
||||
|
|
@ -144,7 +144,7 @@
|
|||
normal: Linphone.DefaultStyle.main2_600,
|
||||
hovered: Linphone.DefaultStyle.main2_700,
|
||||
pressed: Linphone.DefaultStyle.main2_800,
|
||||
checked: Linphone.DefaultStyle.main1_500main
|
||||
checked: Linphone.DefaultStyle.main1_500main,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -163,7 +163,8 @@
|
|||
image: {
|
||||
normal: Linphone.DefaultStyle.danger_500main,
|
||||
hovered: Linphone.DefaultStyle.danger_700,
|
||||
pressed: Linphone.DefaultStyle.danger_900
|
||||
pressed: Linphone.DefaultStyle.danger_900,
|
||||
checked: Linphone.DefaultStyle.danger_900
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue