From 9e04968b2047c214ab29da0c964cb0713913de03 Mon Sep 17 00:00:00 2001 From: Christophe Deschamps Date: Tue, 20 May 2025 16:57:27 +0200 Subject: [PATCH] Leave chatroom --- Linphone/core/chat/ChatCore.cpp | 20 +++++++++++++++- Linphone/core/chat/ChatCore.hpp | 7 ++++++ Linphone/data/languages/en.ts | 18 +++++++++++++++ Linphone/data/languages/fr_FR.ts | 18 +++++++++++++++ Linphone/model/chat/ChatModel.cpp | 4 ++++ Linphone/model/chat/ChatModel.hpp | 1 + .../Container/Call/CallHistoryLayout.qml | 4 +++- .../view/Page/Form/Chat/SelectedChatView.qml | 23 +++++++++++++++++++ 8 files changed, 93 insertions(+), 2 deletions(-) diff --git a/Linphone/core/chat/ChatCore.cpp b/Linphone/core/chat/ChatCore.cpp index 566c77c4..d892f0a7 100644 --- a/Linphone/core/chat/ChatCore.cpp +++ b/Linphone/core/chat/ChatCore.cpp @@ -91,6 +91,7 @@ ChatCore::ChatCore(const std::shared_ptr &chatRoom) : QObjec 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); @@ -107,6 +108,8 @@ void ChatCore::setSelf(QSharedPointer me) { mChatModelConnection->makeConnectToCore(&ChatCore::lDeleteHistory, [this]() { mChatModelConnection->invokeToModel([this]() { mChatModel->deleteHistory(); }); }); + mChatModelConnection->makeConnectToCore( + &ChatCore::lLeave, [this]() { mChatModelConnection->invokeToModel([this]() { mChatModel->leave(); }); }); mChatModelConnection->makeConnectToModel(&ChatModel::historyDeleted, [this]() { mChatModelConnection->invokeToCore([this]() { clearMessagesList(); @@ -138,7 +141,11 @@ void ChatCore::setSelf(QSharedPointer me) { &ChatModel::stateChanged, [this](const std::shared_ptr &chatRoom, linphone::ChatRoom::State newState) { auto state = LinphoneEnums::fromLinphone(newState); - mChatModelConnection->invokeToCore([this, state]() { setChatRoomState(state); }); + bool isReadOnly = chatRoom->isReadOnly(); + mChatModelConnection->invokeToCore([this, state, isReadOnly]() { + setChatRoomState(state); + setIsReadOnly(isReadOnly); + }); }); mChatModelConnection->makeConnectToModel(&ChatModel::chatMessageReceived, @@ -296,6 +303,17 @@ void ChatCore::setChatRoomState(LinphoneEnums::ChatRoomState state) { } } +void ChatCore::setIsReadOnly(bool readOnly) { + if (mIsReadOnly != readOnly) { + mIsReadOnly = readOnly; + emit readOnlyChanged(); + } +} + +bool ChatCore::getIsReadOnly() const { + return mIsReadOnly; +} + ChatMessageGui *ChatCore::getLastMessage() const { return mLastMessage ? new ChatMessageGui(mLastMessage) : nullptr; } diff --git a/Linphone/core/chat/ChatCore.hpp b/Linphone/core/chat/ChatCore.hpp index 4972f8e4..4453c126 100644 --- a/Linphone/core/chat/ChatCore.hpp +++ b/Linphone/core/chat/ChatCore.hpp @@ -50,6 +50,7 @@ public: Q_PROPERTY(QString composingAddress READ getComposingAddress WRITE setComposingAddress NOTIFY composingUserChanged) Q_PROPERTY(bool isGroupChat READ isGroupChat CONSTANT) Q_PROPERTY(bool isEncrypted MEMBER mIsEncrypted) + Q_PROPERTY(bool isReadOnly READ getIsReadOnly WRITE setIsReadOnly NOTIFY readOnlyChanged) // Should be call from model Thread. Will be automatically in App thread after initialization static QSharedPointer create(const std::shared_ptr &chatRoom); @@ -75,6 +76,9 @@ public: LinphoneEnums::ChatRoomState getChatRoomState() const; void setChatRoomState(LinphoneEnums::ChatRoomState state); + bool getIsReadOnly() const; + void setIsReadOnly(bool readOnly); + QSharedPointer getLastMessageCore() const; void setLastMessage(QSharedPointer lastMessage); @@ -115,6 +119,7 @@ signals: void deleted(); void composingUserChanged(); void chatRoomStateChanged(); + void readOnlyChanged(); void lDeleteMessage(); void lDelete(); @@ -125,6 +130,7 @@ signals: void lUpdateLastUpdatedTime(); void lSendTextMessage(QString message); void lCompose(); + void lLeave(); private: QString id; @@ -139,6 +145,7 @@ private: QString mComposingAddress; bool mIsGroupChat = false; bool mIsEncrypted = false; + bool mIsReadOnly = false; LinphoneEnums::ChatRoomState mChatRoomState; std::shared_ptr mChatModel; QSharedPointer mLastMessage; diff --git a/Linphone/data/languages/en.ts b/Linphone/data/languages/en.ts index 87f21d12..883b4101 100644 --- a/Linphone/data/languages/en.ts +++ b/Linphone/data/languages/en.ts @@ -4197,6 +4197,24 @@ To enable them in a commercial project, please contact us. All the messages will be removed from the chat room. Do you want to continue ? All the messages will be removed from the chat room. Do you want to continue ? + + + chat_view_detail_leave_room_toast_button + "Leave chat room" + Leave chat room + + + + chat_view_detail_leave_room_toast_title + Leave chat room ? + Leave chat room ? + + + + chat_view_detail_leave_room_toast_message + You will not be able to send or receive messages in this room anymore, leave ? + You will not be able to send or receive messages in this room anymore, leave ? + SettingsPage diff --git a/Linphone/data/languages/fr_FR.ts b/Linphone/data/languages/fr_FR.ts index ffee3615..8a5303e2 100644 --- a/Linphone/data/languages/fr_FR.ts +++ b/Linphone/data/languages/fr_FR.ts @@ -4212,6 +4212,24 @@ Pour les activer dans un projet commercial, merci de nous contacter.All the messages will be removed from the chat room. Do you want to continue ? Tous les messages seront supprimés. Souhaitez-vous continuer ? + + + chat_view_detail_leave_room_toast_button + "Leave chat room" + Quitter la conversation + + + + chat_view_detail_leave_room_toast_title + Leave chat room ? + Quitter la conversation ? + + + + chat_view_detail_leave_room_toast_message + You will not be able to send or receive messages in this room anymore, leave ? + Vous ne recevrez ni pourrez envoyer des messages dans cette conversation, quitter ? + SettingsPage diff --git a/Linphone/model/chat/ChatModel.cpp b/Linphone/model/chat/ChatModel.cpp index 4787fa0d..5e1d1545 100644 --- a/Linphone/model/chat/ChatModel.cpp +++ b/Linphone/model/chat/ChatModel.cpp @@ -109,6 +109,10 @@ void ChatModel::deleteHistory() { emit historyDeleted(); } +void ChatModel::leave() { + mMonitor->leave(); +} + void ChatModel::deleteChatRoom() { CoreModel::getInstance()->getCore()->deleteChatRoom(mMonitor); emit deleted(); diff --git a/Linphone/model/chat/ChatModel.hpp b/Linphone/model/chat/ChatModel.hpp index 362dcfd4..18c76f7a 100644 --- a/Linphone/model/chat/ChatModel.hpp +++ b/Linphone/model/chat/ChatModel.hpp @@ -47,6 +47,7 @@ public: QString getIdentifier() const; void deleteHistory(); void deleteChatRoom(); + void leave(); std::shared_ptr createTextMessageFromText(QString text); void compose(); linphone::ChatRoom::State getState() const; diff --git a/Linphone/view/Control/Container/Call/CallHistoryLayout.qml b/Linphone/view/Control/Container/Call/CallHistoryLayout.qml index 20f42621..44425b5d 100644 --- a/Linphone/view/Control/Container/Call/CallHistoryLayout.qml +++ b/Linphone/view/Control/Container/Call/CallHistoryLayout.qml @@ -32,6 +32,8 @@ ColumnLayout { property alias buttonContent: rightButton.data property alias detailContent: detailControl.data + + property var hideChat: false component LabelButton: ColumnLayout { id: labelButton @@ -169,7 +171,7 @@ ColumnLayout { } } LabelButton { - visible: !mainItem.isConference && !SettingsCpp.disableChatFeature + visible: !mainItem.isConference && !SettingsCpp.disableChatFeature && !mainItem.hideChat width: Math.round(56 * DefaultStyle.dp) height: Math.round(56 * DefaultStyle.dp) button.icon.width: Math.round(24 * DefaultStyle.dp) diff --git a/Linphone/view/Page/Form/Chat/SelectedChatView.qml b/Linphone/view/Page/Form/Chat/SelectedChatView.qml index 143ce423..43878949 100644 --- a/Linphone/view/Page/Form/Chat/SelectedChatView.qml +++ b/Linphone/view/Page/Form/Chat/SelectedChatView.qml @@ -104,6 +104,7 @@ RowLayout { }, Control.Control { id: messageSender + visible: !mainItem.chat.core.isReadOnly anchors.bottom: parent.bottom anchors.left: parent.left anchors.right: parent.right @@ -268,6 +269,7 @@ RowLayout { } contentItem: CallHistoryLayout { chatGui: mainItem.chat + hideChat: mainItem.chat.core.isReadOnly detailContent: ColumnLayout { DetailLayout { //: Other actions @@ -284,6 +286,27 @@ RowLayout { // } // style: ButtonStyle.noBackground // } + IconLabelButton { + Layout.fillWidth: true + Layout.preferredHeight: Math.round(50 * DefaultStyle.dp) + icon.source: AppIcons.signOut + //: "Leave Chat Room" + text: qsTr("chat_view_detail_leave_room_toast_button") + visible: mainItem.chat.core.isGroupChat && !mainItem.chat.core.isReadOnly + onClicked: { + //: Leave Chat Room ? + mainWindow.showConfirmationLambdaPopup(qsTr("chat_view_detail_leave_room_toast_title"), + //: All the messages will be removed from the chat room. Do you want to continue ? + qsTr("chat_view_detail_leave_room_toast_message"), + "", + function(confirmed) { + if (confirmed) { + mainItem.chat.core.lLeave() + } + }) + } + style: ButtonStyle.noBackground + } IconLabelButton { Layout.fillWidth: true Layout.preferredHeight: Math.round(50 * DefaultStyle.dp)