diff --git a/src/app/modules/main/profile_section/contacts/view.nim b/src/app/modules/main/profile_section/contacts/view.nim index 5c8a80301f..2979f5cd06 100644 --- a/src/app/modules/main/profile_section/contacts/view.nim +++ b/src/app/modules/main/profile_section/contacts/view.nim @@ -123,6 +123,12 @@ QtObject: proc isMyMutualContact*(self: View, publicKey: string): bool {.slot.} = return self.myMutualContactsModel.isContactWithIdAdded(publicKey) + proc isBlockedContact*(self: View, publicKey: string): bool {.slot.} = + return self.blockedContactsModel.isContactWithIdAdded(publicKey) + + proc hasPendingContactRequest*(self: View, publicKey: string): bool {.slot.} = + return self.sentContactRequestsModel.isContactWithIdAdded(publicKey) + proc sendContactRequest*(self: View, publicKey: string, message: string) {.slot.} = self.delegate.sendContactRequest(publicKey, message) diff --git a/ui/app/AppLayouts/Chat/popups/PinnedMessagesPopup.qml b/ui/app/AppLayouts/Chat/popups/PinnedMessagesPopup.qml index 377df3161b..6b6feec1e8 100644 --- a/ui/app/AppLayouts/Chat/popups/PinnedMessagesPopup.qml +++ b/ui/app/AppLayouts/Chat/popups/PinnedMessagesPopup.qml @@ -191,7 +191,7 @@ ModalPopup { } onOpenProfileClicked: { - Global.openProfilePopup(publicKey) + Global.openProfilePopup(publicKey, null, state) } } } diff --git a/ui/app/AppLayouts/Chat/views/ChatContentView.qml b/ui/app/AppLayouts/Chat/views/ChatContentView.qml index 0c8c424c70..698bc67295 100644 --- a/ui/app/AppLayouts/Chat/views/ChatContentView.qml +++ b/ui/app/AppLayouts/Chat/views/ChatContentView.qml @@ -384,7 +384,7 @@ ColumnLayout { } onOpenProfileClicked: { - Global.openProfilePopup(publicKey) + Global.openProfilePopup(publicKey, null, state) } onDeleteMessage: { diff --git a/ui/app/AppLayouts/Chat/views/ChatView.qml b/ui/app/AppLayouts/Chat/views/ChatView.qml index cb2ea37fdc..25c34ac14c 100644 --- a/ui/app/AppLayouts/Chat/views/ChatView.qml +++ b/ui/app/AppLayouts/Chat/views/ChatView.qml @@ -191,7 +191,7 @@ StatusAppThreePanelLayout { store: root.rootStore onOpenProfileClicked: { - Global.openProfilePopup(publicKey) + Global.openProfilePopup(publicKey, null, state) } onCreateOneToOneChat: { Global.changeAppSectionBySectionType(Constants.appSection.chat) diff --git a/ui/app/AppLayouts/Profile/stores/ContactsStore.qml b/ui/app/AppLayouts/Profile/stores/ContactsStore.qml index 8807527e5c..f1008f1521 100644 --- a/ui/app/AppLayouts/Profile/stores/ContactsStore.qml +++ b/ui/app/AppLayouts/Profile/stores/ContactsStore.qml @@ -36,6 +36,14 @@ QtObject { return root.contactsModule.isMyMutualContact(pubKey) } + function isBlockedContact(pubKey) { + return root.contactsModule.isBlockedContact(pubKey) + } + + function hasPendingContactRequest(pubKey) { + return root.contactsModule.hasPendingContactRequest(pubKey) + } + function joinPrivateChat(pubKey) { Global.changeAppSectionBySectionType(Constants.appSection.chat) root.contactsModule.switchToOrCreateOneToOneChat(pubKey) diff --git a/ui/app/AppLayouts/Profile/views/ContactsView.qml b/ui/app/AppLayouts/Profile/views/ContactsView.qml index 90846ba426..029d3ae993 100644 --- a/ui/app/AppLayouts/Profile/views/ContactsView.qml +++ b/ui/app/AppLayouts/Profile/views/ContactsView.qml @@ -119,7 +119,7 @@ SettingsContentBase { } onOpenChangeNicknamePopup: { - Global.openProfilePopup(publicKey, null, true) + Global.openProfilePopup(publicKey, null, "openNickname") } } @@ -140,7 +140,7 @@ SettingsContentBase { } onOpenChangeNicknamePopup: { - Global.openProfilePopup(publicKey, null, true) + Global.openProfilePopup(publicKey, null, "openNickname") } } @@ -181,7 +181,7 @@ SettingsContentBase { } onOpenChangeNicknamePopup: { - Global.openProfilePopup(publicKey, null, true) + Global.openProfilePopup(publicKey, null, "openNickname") } onContactRequestAccepted: { @@ -207,7 +207,7 @@ SettingsContentBase { } onOpenChangeNicknamePopup: { - Global.openProfilePopup(publicKey, null, true) + Global.openProfilePopup(publicKey, null, "openNickname") } } diff --git a/ui/app/mainui/AppMain.qml b/ui/app/mainui/AppMain.qml index 1087119290..dbdb7a7521 100644 --- a/ui/app/mainui/AppMain.qml +++ b/ui/app/mainui/AppMain.qml @@ -90,10 +90,10 @@ Item { } onOpenProfilePopupRequested: { var popup = profilePopupComponent.createObject(appMain); - if (parentPopup){ + if (parentPopup) { popup.parentPopup = parentPopup; } - popup.openPopup(publicKey, openNicknamePopup); + popup.openPopup(publicKey, state); Global.profilePopupOpened = true; } onOpenChangeProfilePicPopup: { diff --git a/ui/imports/shared/controls/chat/menuItems/SendContactRequestMenuItem.qml b/ui/imports/shared/controls/chat/menuItems/SendContactRequestMenuItem.qml new file mode 100644 index 0000000000..69a07b8611 --- /dev/null +++ b/ui/imports/shared/controls/chat/menuItems/SendContactRequestMenuItem.qml @@ -0,0 +1,8 @@ +import QtQuick 2.14 + +import StatusQ.Popups 0.1 + +StatusMenuItem { + text: qsTr("Send Contact Request") + icon.name: "add-contact" +} diff --git a/ui/imports/shared/controls/chat/menuItems/qmldir b/ui/imports/shared/controls/chat/menuItems/qmldir index 74afe357aa..7e16a36ec8 100644 --- a/ui/imports/shared/controls/chat/menuItems/qmldir +++ b/ui/imports/shared/controls/chat/menuItems/qmldir @@ -1,3 +1,4 @@ ViewProfileMenuItem 1.0 ViewProfileMenuItem.qml MuteChatMenuItem 1.0 MuteChatMenuItem.qml SendMessageMenuItem 1.0 SendMessageMenuItem.qml +SendContactRequestMenuItem 1.0 SendContactRequestMenuItem.qml diff --git a/ui/imports/shared/popups/ProfilePopup.qml b/ui/imports/shared/popups/ProfilePopup.qml index 7e8f811ce4..32deb78f8e 100644 --- a/ui/imports/shared/popups/ProfilePopup.qml +++ b/ui/imports/shared/popups/ProfilePopup.qml @@ -43,29 +43,47 @@ StatusModal { signal contactUnblocked(publicKey: string) signal contactBlocked(publicKey: string) - function openPopup(publicKey, openNicknamePopup) { + function openPopup(publicKey, state = "") { // All this should be improved more, but for now we leave it like this. - let contactDetails = Utils.getContactDetailsAsJson(publicKey) - userPublicKey = publicKey - userDisplayName = contactDetails.displayName - userName = contactDetails.alias - userNickname = contactDetails.localNickname - userEnsName = contactDetails.name - userIcon = contactDetails.displayIcon - userIsEnsVerified = contactDetails.ensVerified - userIsBlocked = contactDetails.isBlocked - isAddedContact = contactDetails.isContact + let contactDetails = Utils.getContactDetailsAsJson(publicKey); + userPublicKey = publicKey; + userDisplayName = contactDetails.displayName; + userName = contactDetails.alias; + userNickname = contactDetails.localNickname; + userEnsName = contactDetails.name; + userIcon = contactDetails.displayIcon; + userIsEnsVerified = contactDetails.ensVerified; + userIsBlocked = contactDetails.isBlocked; + isAddedContact = contactDetails.isContact; - text = "" // this is most likely unneeded - isCurrentUser = popup.profileStore.pubkey === publicKey - showFooter = !isCurrentUser - popup.open() + text = ""; // this is most likely unneeded + isCurrentUser = popup.profileStore.pubkey === publicKey; + showFooter = !isCurrentUser; + popup.open(); - if (openNicknamePopup) { - nicknamePopup.open() + if (state == "openNickname") { + nicknamePopup.open(); + } else if (state == "contactRequest") { + sendContactRequestModal.open() + } else if (state == "blockUser") { + blockUser(); + } else if (state == "unblockUser") { + unblockUser(); } } + function blockUser() { + contentItem.blockContactConfirmationDialog.contactName = userName; + contentItem.blockContactConfirmationDialog.contactAddress = userPublicKey; + contentItem.blockContactConfirmationDialog.open(); + } + + function unblockUser() { + contentItem.unblockContactConfirmationDialog.contactName = userName; + contentItem.unblockContactConfirmationDialog.contactAddress = userPublicKey; + contentItem.unblockContactConfirmationDialog.open(); + } + header.title: userDisplayName + qsTr("'s Profile") header.subTitle: userIsEnsVerified ? userName : Utils.getElidedCompressedPk(userPublicKey) header.subTitleElide: Text.ElideMiddle @@ -315,17 +333,7 @@ StatusModal { qsTr("Unblock User") : qsTr("Block User") type: StatusBaseButton.Type.Danger - onClicked: { - if (userIsBlocked) { - contentItem.unblockContactConfirmationDialog.contactName = userName; - contentItem.unblockContactConfirmationDialog.contactAddress = userPublicKey; - contentItem.unblockContactConfirmationDialog.open(); - return; - } - contentItem.blockContactConfirmationDialog.contactName = userName; - contentItem.blockContactConfirmationDialog.contactAddress = userPublicKey; - contentItem.blockContactConfirmationDialog.open(); - } + onClicked: userIsBlocked ? unblockUser() : blockUser() }, StatusFlatButton { diff --git a/ui/imports/shared/popups/SendContactRequestModal.qml b/ui/imports/shared/popups/SendContactRequestModal.qml index 959bbe80b4..9d6ea2c591 100644 --- a/ui/imports/shared/popups/SendContactRequestModal.qml +++ b/ui/imports/shared/popups/SendContactRequestModal.qml @@ -27,7 +27,7 @@ StatusModal { readonly property int contentMargins: 16 } - contentItem: ColumnLayout { + ColumnLayout { id: content anchors.left: parent.left anchors.right: parent.right diff --git a/ui/imports/shared/views/chat/MessageContextMenuView.qml b/ui/imports/shared/views/chat/MessageContextMenuView.qml index df2060ae83..19200f2540 100644 --- a/ui/imports/shared/views/chat/MessageContextMenuView.qml +++ b/ui/imports/shared/views/chat/MessageContextMenuView.qml @@ -17,7 +17,6 @@ import shared.controls.chat.menuItems 1.0 StatusPopupMenu { id: root - width: emojiContainer.visible ? emojiContainer.width : 176 property var store property var reactionModel @@ -26,9 +25,6 @@ StatusPopupMenu { property string myPublicKey: "" property bool amIChatAdmin: false property bool pinMessageAllowedForMembers: false - property bool isMyMessage: { - return root.messageSenderId !== "" && root.messageSenderId == root.myPublicKey - } property int chatType: Constants.chatType.publicChat property string messageId: "" @@ -49,12 +45,28 @@ StatusPopupMenu { property bool pinnedMessage: false property bool canPin: false + readonly property bool isMyMessage: { + return root.messageSenderId !== "" && root.messageSenderId == root.myPublicKey; + } + readonly property bool isMe: { + return root.selectedUserPublicKey == root.store.contactsStore.myPublicKey; + } + readonly property bool isMyMutualContact: { + return root.selectedUserPublicKey !== "" && root.store.contactsStore.isMyMutualContact(root.selectedUserPublicKey); + } + readonly property bool isBlockedContact: { + return root.selectedUserPublicKey !== "" && root.store.contactsStore.isBlockedContact(root.selectedUserPublicKey); + } + readonly property bool hasPendingContactRequest: { + return root.selectedUserPublicKey !== "" && root.store.contactsStore.hasPendingContactRequest(root.selectedUserPublicKey); + } + property var setXPosition: function() {return 0} property var setYPosition: function() {return 0} property var emojiReactionsReactedByUser: [] - signal openProfileClicked(string publicKey) + signal openProfileClicked(string publicKey, string state) signal pinMessage(string messageId) signal unpinMessage(string messageId) signal pinnedMessagesLimitReached(string messageId) @@ -66,14 +78,6 @@ StatusPopupMenu { signal deleteMessage(string messageId) signal editClicked(string messageId) - onHeightChanged: { - root.y = setYPosition() - } - - onWidthChanged: { - root.x = setXPosition() - } - function show(userNameParam, fromAuthorParam, identiconParam, textParam, nicknameParam, emojiReactionsModel) { let newEmojiReactions = [] if (!!emojiReactionsModel) { @@ -91,6 +95,11 @@ StatusPopupMenu { popup() } + onHeightChanged: { root.y = setYPosition(); } + onWidthChanged: { root.x = setXPosition(); } + + width: Math.max(emojiContainer.visible ? emojiContainer.width : 0, 200) + Item { id: emojiContainer width: emojiRow.width @@ -163,22 +172,62 @@ StatusPopupMenu { ViewProfileMenuItem { id: viewProfileAction + enabled: root.isProfile && !root.pinnedPopup onTriggered: { - root.openProfileClicked(root.selectedUserPublicKey) + root.openProfileClicked(root.selectedUserPublicKey, "") root.close() } - enabled: root.isProfile && !root.pinnedPopup } SendMessageMenuItem { id: sendMessageMenuItem - enabled: root.isProfile && root.store.contactsStore.isMyMutualContact(root.selectedUserPublicKey) + enabled: root.isProfile && root.isMyMutualContact && !root.isBlockedContact onTriggered: { root.createOneToOneChat("", root.selectedUserPublicKey, "") root.close() } } + SendContactRequestMenuItem { + enabled: root.isProfile && !root.isMe && !root.isMyMutualContact + && !root.isBlockedContact && !root.hasPendingContactRequest + onTriggered: { + root.openProfileClicked(root.selectedUserPublicKey, "contactRequest") + root.close() + } + } + + StatusMenuItem { + text: qsTr("Block User") + icon.name: "cancel" + icon.color: Style.current.danger + enabled: root.isProfile && !root.isMe && !root.isBlockedContact + onTriggered: { + root.openProfileClicked(root.selectedUserPublicKey, "blockUser") + root.close() + } + } + + StatusMenuItem { + text: qsTr("Unblock User") + icon.name: "remove" + enabled: root.isProfile && !root.isMe && root.isBlockedContact + onTriggered: { + root.openProfileClicked(root.selectedUserPublicKey, "unblockUser") + root.close() + } + } + + StatusMenuItem { + text: qsTr("Rename") + icon.name: "edit_pencil" + enabled: root.isProfile && !root.isMe + onTriggered: { + root.openProfileClicked(root.selectedUserPublicKey, "openNickname") + root.close() + } + } + StatusMenuItem { id: replyToMenuItem text: qsTr("Reply to") diff --git a/ui/imports/utils/Global.qml b/ui/imports/utils/Global.qml index 39b77b1d74..80ec3de7d3 100644 --- a/ui/imports/utils/Global.qml +++ b/ui/imports/utils/Global.qml @@ -29,12 +29,12 @@ QtObject { signal openCreateChatView() signal closeCreateChatView() - signal openProfilePopupRequested(string publicKey, var parentPopup, bool openNicknamePopup) + signal openProfilePopupRequested(string publicKey, var parentPopup, string state) signal openChangeProfilePicPopup() signal displayToastMessage(string title, string subTitle, string icon, bool loading, int ephNotifType, string url) - function openProfilePopup(publicKey, parentPopup, openNicknamePopup){ - openProfilePopupRequested(publicKey, parentPopup, openNicknamePopup); + function openProfilePopup(publicKey, parentPopup, state = "") { + openProfilePopupRequested(publicKey, parentPopup, state); } function openPopup(popupComponent, params = {}) {