diff --git a/src/app/modules/main/chat_section/module.nim b/src/app/modules/main/chat_section/module.nim index 95b6fdb413..97d588fac1 100644 --- a/src/app/modules/main/chat_section/module.nim +++ b/src/app/modules/main/chat_section/module.nim @@ -436,6 +436,14 @@ method makeChatWithIdActive*(self: Module, chatId: string) = self.setActiveItem(chatId) singletonInstance.localAccountSensitiveSettings.setSectionLastOpenChat(self.controller.getMySectionId(), chatId) +proc updateActiveChatMembership*(self: Module) = + let activeChatId = self.controller.getActiveChatId() + let chat = self.controller.getChatDetails(activeChatId) + + if chat.chatType == ChatType.PrivateGroupChat: + let amIMember = any(chat.members, proc (member: ChatMember): bool = member.id == singletonInstance.userProfile.getPubKey()) + self.view.setAmIMember(amIMember) + method activeItemSet*(self: Module, itemId: string) = let mySectionId = self.controller.getMySectionId() if (itemId == ""): @@ -453,6 +461,8 @@ method activeItemSet*(self: Module, itemId: string) = self.view.chatsModel().setActiveItem(itemId) self.view.activeItemSet(chat_item) + self.updateActiveChatMembership() + let activeChatId = self.controller.getActiveChatId() # # update child modules @@ -1162,6 +1172,10 @@ proc addOrUpdateChat(self: Module, if not self.chatsLoaded: return + let activeChatId = self.controller.getActiveChatId() + if chat.id == activeChatId: + self.updateActiveChatMembership() + if chatExists: if (chat.chatType == ChatType.PrivateGroupChat): self.onGroupChatDetailsUpdated(chat.id, chat.name, chat.color, chat.icon) diff --git a/ui/StatusQ/src/StatusQ/Components/StatusMessage.qml b/ui/StatusQ/src/StatusQ/Components/StatusMessage.qml index 56e15027ed..bf4a5ab84b 100644 --- a/ui/StatusQ/src/StatusQ/Components/StatusMessage.qml +++ b/ui/StatusQ/src/StatusQ/Components/StatusMessage.qml @@ -55,7 +55,6 @@ Control { property bool showHeader: true property bool isActiveMessage: false property bool disableHover: false - property bool hideQuickActions: false property bool disableEmojis: false property color overrideBackgroundColor: "transparent" property bool overrideBackground: false @@ -393,7 +392,7 @@ Control { } Loader { - active: root.hovered && !root.hideQuickActions + active: root.hovered && root.quickActions.length > 0 anchors.right: parent.right anchors.rightMargin: 20 anchors.top: parent.top diff --git a/ui/app/AppLayouts/Chat/stores/RootStore.qml b/ui/app/AppLayouts/Chat/stores/RootStore.qml index 0b34680373..30e09f21c8 100644 --- a/ui/app/AppLayouts/Chat/stores/RootStore.qml +++ b/ui/app/AppLayouts/Chat/stores/RootStore.qml @@ -1,4 +1,5 @@ -import QtQuick 2.13 +import QtQuick 2.15 +import QtQml 2.15 import utils 1.0 import SortFilterProxyModel 0.2 @@ -53,6 +54,10 @@ QtObject { expression: icon(model.icon) } } + + readonly property bool isUserAllowedToSendMessage: _d.isUserAllowedToSendMessage + readonly property string chatInputPlaceHolderText: _d.chatInputPlaceHolderText + readonly property var oneToOneChatContact: _d.oneToOneChatContact // Since qml component doesn't follow encaptulation from the backend side, we're introducing // a method which will return appropriate chat content module for selected chat/channel function currentChatContentModule(){ @@ -655,5 +660,77 @@ QtObject { // add others when needed.. } } + + readonly property string activeChatId: chatCommunitySectionModule && chatCommunitySectionModule.activeItem ? chatCommunitySectionModule.activeItem.id : "" + readonly property int activeChatType: chatCommunitySectionModule && chatCommunitySectionModule.activeItem ? chatCommunitySectionModule.activeItem.type : -1 + readonly property bool amIMember: chatCommunitySectionModule ? chatCommunitySectionModule.amIMember : false + + property var oneToOneChatContact: undefined + readonly property string oneToOneChatContactName: !!_d.oneToOneChatContact ? ProfileUtils.displayName(_d.oneToOneChatContact.localNickname, + _d.oneToOneChatContact.name, + _d.oneToOneChatContact.displayName, + _d.oneToOneChatContact.alias) : "" + + //Update oneToOneChatContact when the contact is updated + readonly property var myContactsModelConnection: Connections { + target: root.contactsStore.myContactsModel ?? null + enabled: _d.activeChatType === Constants.chatType.oneToOne + + function onItemChanged(pubKey) { + if (pubKey === _d.activeChatId) { + _d.oneToOneChatContact = Utils.getContactDetailsAsJson(pubKey, false) + } + } + } + + readonly property var receivedContactsReqModelConnection: Connections { + target: root.contactsStore.receivedContactRequestsModel ?? null + enabled: _d.activeChatType === Constants.chatType.oneToOne + + function onItemChanged(pubKey) { + if (pubKey === _d.activeChatId) { + _d.oneToOneChatContact = Utils.getContactDetailsAsJson(pubKey, false) + } + } + } + + readonly property var sentContactReqModelConnection: Connections { + target: root.contactsStore.sentContactRequestsModel ?? null + enabled: _d.activeChatType === Constants.chatType.oneToOne + + function onItemChanged(pubKey) { + if (pubKey === _d.activeChatId) { + _d.oneToOneChatContact = Utils.getContactDetailsAsJson(pubKey, false) + } + } + } + + readonly property bool isUserAllowedToSendMessage: { + if (_d.activeChatType === Constants.chatType.oneToOne && _d.oneToOneChatContact) { + return _d.oneToOneChatContact.contactRequestState == Constants.ContactRequestState.Mutual + } + else if(_d.activeChatType === Constants.chatType.privateGroupChat) { + return _d.amIMember + } + + return true + } + + readonly property string chatInputPlaceHolderText: { + if(!_d.isUserAllowedToSendMessage && _d.activeChatType === Constants.chatType.privateGroupChat) { + return qsTr("You need to be a member of this group to send messages") + } else if(!_d.isUserAllowedToSendMessage && _d.activeChatType === Constants.chatType.oneToOne) { + return qsTr("Add %1 as a contact to send a message").arg(_d.oneToOneChatContactName) + } + + return qsTr("Message") + } + + //Update oneToOneChatContact when activeChat id changes + Binding on oneToOneChatContact { + when: _d.activeChatId && _d.activeChatType === Constants.chatType.oneToOne + value: Utils.getContactDetailsAsJson(_d.activeChatId, false) + restoreMode: Binding.RestoreBindingOrValue + } } } diff --git a/ui/app/AppLayouts/Chat/views/ChatContentView.qml b/ui/app/AppLayouts/Chat/views/ChatContentView.qml index 784b506227..169fdc6da5 100644 --- a/ui/app/AppLayouts/Chat/views/ChatContentView.qml +++ b/ui/app/AppLayouts/Chat/views/ChatContentView.qml @@ -55,51 +55,10 @@ ColumnLayout { property Component sendTransactionWithEnsModal property bool isBlocked: false - property int contactRequestState: Constants.ContactRequestState.None + property bool isUserAllowedToSendMessage: root.rootStore.isUserAllowedToSendMessage + property string chatInputPlaceholder: root.rootStore.chatInputPlaceHolderText property bool stickersLoaded: false - onIsActiveChannelChanged: d.updateContactRequestState() - - QtObject { - id: d - - readonly property var conns1: Connections { - target: root.contactsStore.myContactsModel ?? null - - function onItemChanged(pubKey) { - if (pubKey === root.chatId) - d.updateContactRequestState() - } - } - - readonly property var conns2: Connections { - target: root.contactsStore.receivedContactRequestsModel ?? null - - function onItemChanged(pubKey) { - if (pubKey === root.chatId) - d.updateContactRequestState() - } - } - - readonly property var conns3: Connections { - target: root.contactsStore.sentContactRequestsModel ?? null - - function onItemChanged(pubKey) { - if (pubKey === root.chatId) - d.updateContactRequestState() - } - } - - function updateContactRequestState() { - if (root.chatType !== Constants.chatType.oneToOne) { - return - } - root.contactRequestState = Utils.getContactDetailsAsJson(root.chatId).contactRequestState - } - - Component.onCompleted: d.updateContactRequestState() - } - Loader { Layout.fillWidth: true active: root.isBlocked @@ -125,7 +84,7 @@ ColumnLayout { sourceComponent: MessageContextMenuView { store: root.rootStore reactionModel: root.rootStore.emojiReactionsModel - disabledForChat: root.chatType === Constants.chatType.oneToOne && root.contactRequestState !== Constants.ContactRequestState.Mutual + disabledForChat: !root.isUserAllowedToSendMessage onPinMessage: { messageStore.pinMessage(messageId) @@ -195,8 +154,7 @@ ColumnLayout { stickersLoaded: root.stickersLoaded publicKey: root.chatId isOneToOne: root.chatType === Constants.chatType.oneToOne - contactRequestState: root.contactRequestState - isChatBlocked: root.isBlocked + isChatBlocked: root.isBlocked || !root.isUserAllowedToSendMessage channelEmoji: !chatContentModule ? "" : (chatContentModule.chatDetails.emoji || "") isActiveChannel: root.isActiveChannel onShowReplyArea: { @@ -249,12 +207,13 @@ ColumnLayout { anchors.margins: Style.current.smallPadding enabled: root.rootStore.sectionDetails.joined && !root.rootStore.sectionDetails.amIBanned && - !(chatType === Constants.chatType.oneToOne && root.contactRequestState !== Constants.ContactRequestState.Mutual) + root.isUserAllowedToSendMessage store: root.rootStore usersStore: root.usersStore textInput.text: inputAreaLoader.preservedText + textInput.placeholderText: root.chatInputPlaceholder messageContextMenu: contextMenuLoader.item emojiPopup: root.emojiPopup stickersPopup: root.stickersPopup diff --git a/ui/app/AppLayouts/Chat/views/ChatMessagesView.qml b/ui/app/AppLayouts/Chat/views/ChatMessagesView.qml index acb47b3c1d..36f8058d92 100644 --- a/ui/app/AppLayouts/Chat/views/ChatMessagesView.qml +++ b/ui/app/AppLayouts/Chat/views/ChatMessagesView.qml @@ -39,7 +39,6 @@ Item { property bool isChatBlocked: false property bool isOneToOne: false property bool isActiveChannel: false - property int contactRequestState: Constants.ContactRequestState.None property var messageContextMenu @@ -253,7 +252,7 @@ Item { chatLogView: ListView.view isActiveChannel: root.isActiveChannel - isChatBlocked: root.isChatBlocked || (root.isOneToOne && root.contactRequestState !== Constants.ContactRequestState.Mutual) + isChatBlocked: root.isChatBlocked messageContextMenu: root.messageContextMenu messageId: model.id @@ -333,8 +332,8 @@ Item { } } header: { - if (root.isOneToOne) { - switch (root.contactRequestState) { + if (root.isOneToOne && root.rootStore.oneToOneChatContact) { + switch (root.rootStore.oneToOneChatContact.contactRequestState) { case Constants.ContactRequestState.None: // no break case Constants.ContactRequestState.Dismissed: return sendContactRequestComponent diff --git a/ui/app/AppLayouts/Profile/views/EnsListView.qml b/ui/app/AppLayouts/Profile/views/EnsListView.qml index e5c337a062..a0ea15a993 100644 --- a/ui/app/AppLayouts/Profile/views/EnsListView.qml +++ b/ui/app/AppLayouts/Profile/views/EnsListView.qml @@ -221,7 +221,6 @@ Item { timestamp: new Date().getTime() disableHover: true - hideQuickActions: true profileClickable: false messageDetails: StatusMessageDetails { diff --git a/ui/imports/shared/views/chat/MessageView.qml b/ui/imports/shared/views/chat/MessageView.qml index 9af76f1416..3f12c11ea9 100644 --- a/ui/imports/shared/views/chat/MessageView.qml +++ b/ui/imports/shared/views/chat/MessageView.qml @@ -432,6 +432,11 @@ Loader { readonly property int contentType: d.convertContentType(root.messageContentType) property string originalMessageText: "" + readonly property bool hideQuickActions: root.isChatBlocked || + root.placeholderMessage || + root.isInPinnedPopup || + root.editModeOn || + !root.rootStore.mainModuleInst.activeSection.joined function editCancelledHandler() { root.messageStore.setEditModeOff(root.messageId) @@ -493,12 +498,6 @@ Loader { (root.messageContextMenu && root.messageContextMenu.opened) || Global.popupOpened - hideQuickActions: root.isChatBlocked || - root.placeholderMessage || - root.isInPinnedPopup || - root.editModeOn || - !root.rootStore.mainModuleInst.activeSection.joined - disableEmojis: root.isChatBlocked hideMessage: d.hideMessage @@ -762,7 +761,7 @@ Loader { quickActions: [ Loader { - active: !root.isInPinnedPopup && delegate.hovered + active: !root.isInPinnedPopup && delegate.hovered && !delegate.hideQuickActions visible: active sourceComponent: StatusFlatRoundButton { width: d.chatButtonSize @@ -777,7 +776,7 @@ Loader { } }, Loader { - active: !root.isInPinnedPopup && delegate.hovered + active: !root.isInPinnedPopup && delegate.hovered && !delegate.hideQuickActions visible: active sourceComponent: StatusFlatRoundButton { objectName: "replyToMessageButton" @@ -795,7 +794,7 @@ Loader { } }, Loader { - active: !root.isInPinnedPopup && root.isText && !root.editModeOn && root.amISender && delegate.hovered + active: !root.isInPinnedPopup && root.isText && !root.editModeOn && root.amISender && delegate.hovered && !delegate.hideQuickActions visible: active sourceComponent: StatusFlatRoundButton { objectName: "editMessageButton" @@ -816,6 +815,9 @@ Loader { if (!root.messageStore) return false + + if(delegate.hideQuickActions) + return false; const chatType = root.messageStore.chatType; const pinMessageAllowedForMembers = root.messageStore.isPinMessageAllowedForMembers