From 32c1d174adb3deec157959a22cac5e22bdd6c6d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Cie=C5=9Blak?= Date: Thu, 7 Nov 2024 22:52:46 +0100 Subject: [PATCH] UserListPanel made store-independent, Storybook page fully operable Closes: #16717 --- storybook/pages/ProfileContextMenuPage.qml | 3 - storybook/pages/UserListPanelPage.qml | 102 ++++++-- storybook/src/Models/UsersModel.qml | 242 ++++++++++-------- .../AppLayouts/Chat/panels/UserListPanel.qml | 74 +++--- ui/app/AppLayouts/Chat/views/ChatView.qml | 45 +++- 5 files changed, 287 insertions(+), 179 deletions(-) diff --git a/storybook/pages/ProfileContextMenuPage.qml b/storybook/pages/ProfileContextMenuPage.qml index 5efdb72f99..eabac868f1 100644 --- a/storybook/pages/ProfileContextMenuPage.qml +++ b/storybook/pages/ProfileContextMenuPage.qml @@ -153,7 +153,6 @@ SplitView { { text: "Trusted", value: Constants.trustStatus.trusted }, { text: "Untrusted", value: Constants.trustStatus.untrustworthy } ] - currentIndex: 0 } } @@ -176,7 +175,6 @@ SplitView { { text: "Contact Request Received", value: Constants.contactType.contactRequestReceived }, { text: "Contact Request Sent", value: Constants.contactType.contactRequestSent } ] - currentIndex: 0 } } @@ -223,7 +221,6 @@ SplitView { { text: "Profile", value: Constants.chatType.profile }, { text: "Community Chat", value: Constants.chatType.communityChat } ] - currentIndex: 0 } } diff --git a/storybook/pages/UserListPanelPage.qml b/storybook/pages/UserListPanelPage.qml index 0be287d914..a4cae91ed3 100644 --- a/storybook/pages/UserListPanelPage.qml +++ b/storybook/pages/UserListPanelPage.qml @@ -1,47 +1,107 @@ import QtQuick 2.15 import QtQuick.Controls 2.15 +import QtQuick.Layouts 1.15 import AppLayouts.Chat.panels 1.0 -import StatusQ 0.1 -import Storybook 1.0 import Models 1.0 -import SortFilterProxyModel 0.2 +import utils 1.0 SplitView { - Logs { id: logs } - orientation: Qt.Vertical - UsersModel { - id: model - } - - UserListPanel { + Pane { SplitView.fillWidth: true SplitView.fillHeight: true - label: "Some label" + padding: 100 - usersModel: SortFilterProxyModel { - sourceModel: model + Rectangle { + anchors.fill: parent + anchors.margins: -1 + color: "transparent" + border.color: "black" + } - proxyRoles: FastExpressionRole { - name: "compressedKey" - expression: "compressed" - } + UserListPanel { + anchors.fill: parent + + usersModel: UsersModel {} + + label: labelTextField.text + isAdmin: isAdminCheckBox.checked + chatType: chatTypeSelector.currentValue + communityMemberReevaluationStatus: + communityMemberReevaluationStatusSelector.currentValue } } - LogsAndControlsPanel { - id: logsAndControlsPanel - + Pane { SplitView.minimumHeight: 100 SplitView.preferredHeight: 200 - logsView.logText: logs.logText + ColumnLayout { + RowLayout { + Label { + text: "Label:" + } + + TextField { + id: labelTextField + + text: "Some label here" + } + } + + CheckBox { + id: isAdminCheckBox + + text: "Is admin (allows to remove used from private group chat)" + } + + RowLayout { + Label { + text: "Chat Type:" + } + + ComboBox { + id: chatTypeSelector + + textRole: "text" + valueRole: "value" + model: [ + { text: "Unknown", value: Constants.chatType.unknown }, + { text: "Category", value: Constants.chatType.category }, + { text: "One-to-One", value: Constants.chatType.oneToOne }, + { text: "Public Chat", value: Constants.chatType.publicChat }, + { text: "Private Group Chat", value: Constants.chatType.privateGroupChat }, + { text: "Profile", value: Constants.chatType.profile }, + { text: "Community Chat", value: Constants.chatType.communityChat } + ] + } + } + + RowLayout { + Label { + text: "Community member reevaluation status:" + } + + ComboBox { + id: communityMemberReevaluationStatusSelector + + textRole: "text" + valueRole: "value" + model: [ + { text: "Unknown", value: Constants.CommunityMemberReevaluationStatus.None }, + { text: "InProgress", value: Constants.CommunityMemberReevaluationStatus.InProgress }, + { text: "Done", value: Constants.CommunityMemberReevaluationStatus.Done } + ] + } + } + } } } // category: Panels +// status: good diff --git a/storybook/src/Models/UsersModel.qml b/storybook/src/Models/UsersModel.qml index f330e94729..6101baf461 100644 --- a/storybook/src/Models/UsersModel.qml +++ b/storybook/src/Models/UsersModel.qml @@ -1,117 +1,133 @@ import QtQuick 2.15 -ListModel { - id: root +import utils 1.0 - ListElement { - pubKey: "0x043a7ed0e8d1012cf04" - onlineStatus: 1 - isContact: true - isVerified: false - isAdmin: false - isUntrustworthy: true - displayName: "Mike has a very long name that should elide eventually and result in a tooltip displayed instead" - alias: "" - localNickname: "" - ensName: "" - icon: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAlklEQVR4nOzW0QmDQBAG4SSkl7SUQlJGCrElq9F3QdjjVhh/5nv3cFhY9vUIYQiNITSG0BhCExPynn1gWf9bx498P7/ - nzPcxEzGExhBdJGYihtAYQlO+tUZvqrPbqeudo5iJGEJjCE15a3VtodH3q2ImYgiNITTlTdG1nUZ5a92VITQxITFiJmIIjSE0htAYQrMHAAD//+wwFVpz+yqXAAAAAElFTkSuQmCC" - colorId: 7 - isEnsVerified: false - colorHash: [ - ListElement {colorId: 0; segmentLength: 2}, - ListElement {colorId: 17; segmentLength: 2} - ] - isAwaitingAddress: false - memberRole: 0 // Constants.memberRole.none - } - ListElement { - pubKey: "0x04df12f12f12f12f1234" - onlineStatus: 0 - isContact: false - isVerified: false - isAdmin: false - isUntrustworthy: false - displayName: "Jane" - alias: "" - localNickname: "" - ensName: "" - icon: "" - colorId: 9 - isEnsVerified: false - colorHash: [ - ListElement {colorId: 0; segmentLength: 1}, - ListElement {colorId: 19; segmentLength: 2} - ] - isAwaitingAddress: false - memberRole: 1 // Constants.memberRole.owner - } - ListElement { - pubKey: "0x04d1b7cc0ef3f470f1238" - onlineStatus: 0 - isContact: false - isVerified: false - isAdmin: false - isUntrustworthy: true - displayName: "John" - alias: "" - localNickname: "Johnny Johny" - ensName: "" - icon: "https://cryptologos.cc/logos/status-snt-logo.svg?v=033" - colorId: 4 - isEnsVerified: false - isAwaitingAddress: false - memberRole: 0 - } - ListElement { - pubKey: "0x04d1bed192343f470f1257" - onlineStatus: 1 - isContact: true - isVerified: true - isAdmin: false - isUntrustworthy: true - displayName: "Maria" - alias: "meth" - localNickname: "86.eth" - ensName: "8⃣6⃣.eth" - icon: "" - colorId: 5 - isEnsVerified: true - isAwaitingAddress: false - memberRole: 0 - } - ListElement { - pubKey: "0x04d1bed192343f470f1255" - onlineStatus: 1 - isContact: true - isVerified: true - isAdmin: true - isUntrustworthy: true - displayName: "" - alias: "Richard The Lionheart" - localNickname: "" - ensName: "richard-the-lionheart.eth" - icon: "" - colorId: 3 - isEnsVerified: true - isAwaitingAddress: false - memberRole: 0 - } - ListElement { - pubKey: "0x04d1bed192343f470fabc" - onlineStatus: 0 - isContact: true - isVerified: false - isAdmin: false - isUntrustworthy: false - displayName: "" - alias: "" - localNickname: "" - ensName: "8⃣6⃣.eth" - icon: "" - colorId: 7 - isEnsVerified: true - isAwaitingAddress: true - memberRole: 0 - } +ListModel { + readonly property var data: [ + { + pubKey: "0x043a7ed0e8d1012cf04", + compressedPubKey: "zQ3shQBu4PRDX17vewYyvSczbTj344viTXxcMNvQLeyQsBDF4", + onlineStatus: Constants.onlineStatus.online, + isContact: true, + isVerified: false, + isAdmin: false, + isUntrustworthy: true, + displayName: "Mike has a very long name that should elide " + + "eventually and result in a tooltip displayed instead", + alias: "", + localNickname: "", + ensName: "", + icon: ModelsData.icons.cryptPunks, + colorId: 7, + isEnsVerified: false, + colorHash: [ + { colorId: 0, segmentLength: 2 }, + { colorId: 17, segmentLength: 2} + ], + isAwaitingAddress: false, + memberRole: Constants.memberRole.none, + trustStatus: Constants.trustStatus.untrustworthy + }, + { + pubKey: "0x04df12f12f12f12f1234", + compressedPubKey: "zQ3shQBAAPRDX17vewYyvSczbTj344viTXxcMNvQLeyQsBDF4", + onlineStatus: Constants.onlineStatus.inactive, + isContact: false, + isVerified: false, + isAdmin: false, + isUntrustworthy: false, + displayName: "Jane", + alias: "", + localNickname: "", + ensName: "", + icon: "", + colorId: 9, + isEnsVerified: false, + colorHash: [ + { colorId: 0, segmentLength: 1 }, + { colorId: 19, segmentLength: 2 } + ], + isAwaitingAddress: false, + memberRole: Constants.memberRole.owner, + trustStatus: Constants.trustStatus.trusted + }, + { + pubKey: "0x04d1b7cc0ef3f470f1238", + compressedPubKey: "zQ3shQ7u3PRDX17vewYyvSczbTj344viTXxcMNvQLeyQsCDF4", + onlineStatus: Constants.onlineStatus.inactive, + isContact: false, + isVerified: false, + isAdmin: false, + isUntrustworthy: true, + displayName: "John", + alias: "", + localNickname: "Johnny Johny", + ensName: "", + icon: ModelsData.icons.dragonereum, + colorId: 4, + isEnsVerified: false, + isAwaitingAddress: false, + memberRole: Constants.memberRole.none, + trustStatus: Constants.trustStatus.untrustworthy + }, + { + pubKey: "0x04d1bed192343f470f1257", + compressedPubKey: "zQ3shQAL4PRDX17vewYyvSczbTj344viTXxcMNvQLeyQsBDF4", + onlineStatus: Constants.onlineStatus.online, + isContact: true, + isVerified: true, + isAdmin: false, + isUntrustworthy: true, + displayName: "Maria", + alias: "meth", + localNickname: "86.eth", + ensName: "8⃣_6⃣.eth", + icon: "", + colorId: 5, + isEnsVerified: true, + isAwaitingAddress: false, + memberRole: Constants.memberRole.none, + trustStatus: Constants.trustStatus.untrustworthy + }, + { + pubKey: "0x04d1bed192343f470f1255", + compressedPubKey: "zQ3shQBu4PGDX17vewYyvSczbTj344viTXxcMNvQLeyQsBD1A", + onlineStatus: Constants.onlineStatus.online, + isContact: true, + isVerified: true, + isAdmin: true, + isUntrustworthy: true, + displayName: "", + alias: "Richard The Lionheart", + localNickname: "", + ensName: "richard-the-lionheart.eth", + icon: "", + colorId: 3, + isEnsVerified: true, + isAwaitingAddress: false, + memberRole: Constants.memberRole.none, + trustStatus: Constants.trustStatus.untrustworthy + }, + { + pubKey: "0x04d1bed192343f470fabc", + compressedPubKey: "zQ3shQBk4PRDX17vewYyvSczbTj344viTXxcMNvQLeyQsB994", + onlineStatus: Constants.onlineStatus.inactive, + isContact: true, + isVerified: false, + isAdmin: false, + isUntrustworthy: false, + displayName: "", + alias: "", + localNickname: "", + ensName: "8⃣6⃣.sth.eth", + icon: "", + colorId: 7, + isEnsVerified: true, + isAwaitingAddress: true, + memberRole: Constants.memberRole.none, + trustStatus: Constants.trustStatus.trusted + } + ] + + Component.onCompleted: append(data) } diff --git a/ui/app/AppLayouts/Chat/panels/UserListPanel.qml b/ui/app/AppLayouts/Chat/panels/UserListPanel.qml index 9252e2454d..047de9255a 100644 --- a/ui/app/AppLayouts/Chat/panels/UserListPanel.qml +++ b/ui/app/AppLayouts/Chat/panels/UserListPanel.qml @@ -2,44 +2,57 @@ import QtQuick 2.15 import QtQuick.Controls 2.15 import QtQuick.Layouts 1.15 -import StatusQ 0.1 import StatusQ.Core 0.1 import StatusQ.Core.Theme 0.1 import StatusQ.Components 0.1 import StatusQ.Controls 0.1 -import shared 1.0 -import shared.panels 1.0 -import shared.status 1.0 import shared.views.chat 1.0 - import utils 1.0 import SortFilterProxyModel 0.2 -import AppLayouts.Chat.stores 1.0 as ChatStores - Item { id: root - property ChatStores.RootStore store - property var usersModel + property string label + property int chatType: Constants.chatType.unknown + property bool isAdmin property int communityMemberReevaluationStatus: Constants.CommunityMemberReevaluationStatus.None + signal openProfileRequested(string pubKey) + signal createOneToOneChatRequested(string pubKey) + signal reviewContactRequestRequested(string pubKey) + signal sendContactRequestRequested(string pubKey) + signal editNicknameRequested(string pubKey) + signal removeNicknameRequested(string pubKey) + signal blockContactRequested(string pubKey) + signal unblockContactRequested(string pubKey) + signal markAsUntrustedRequested(string pubKey) + signal removeTrustStatusRequested(string pubKey) + signal removeContactRequested(string pubKey) + signal removeContactFromGroupRequested(string pubKey) + StatusBaseText { id: titleText + anchors.top: parent.top anchors.topMargin: Theme.padding anchors.left: parent.left anchors.leftMargin: Theme.padding + anchors.right: parent.right + anchors.rightMargin: Theme.padding + opacity: (root.width > 58) ? 1.0 : 0.0 visible: (opacity > 0.1) font.pixelSize: Theme.primaryTextFontSize font.weight: Font.Medium color: Theme.palette.directColor1 text: root.label + + wrapMode: Text.Wrap } StatusBaseText { @@ -108,6 +121,7 @@ Item { section.delegate: (root.width > 58) ? sectionDelegateComponent : null delegate: StatusMemberListItem { width: ListView.view.width + nickName: model.localNickname userName: ProfileUtils.displayName("", model.ensName, model.displayName, model.alias) pubKey: model.isEnsVerified ? "" : model.compressedPubKey @@ -125,9 +139,6 @@ Item { const profileType = Utils.getProfileType(model.isCurrentUser, false, model.isBlocked) const contactType = Utils.getContactType(model.contactRequest, model.isContact) - const chatType = chatContentModule.chatDetails.type - const isAdmin = chatContentModule.amIChatAdmin() - const params = { profileType, contactType, chatType, isAdmin, pubKey: model.pubKey, @@ -140,7 +151,9 @@ Item { trustStatus: model.trustStatus, onlineStatus: model.onlineStatus, ensVerified: model.isEnsVerified, - hasLocalNickname: !!model.localNickname + hasLocalNickname: !!model.localNickname, + chatType: root.chatType, + isAdmin: root.isAdmin } Global.openMenu(profileContextMenuComponent, this, params) @@ -154,9 +167,11 @@ Item { Component { id: sectionDelegateComponent + Item { width: ListView.view.width height: 24 + StatusBaseText { anchors.fill: parent anchors.leftMargin: Theme.padding @@ -184,25 +199,20 @@ Item { property string pubKey margins: 8 - onOpenProfileClicked: Global.openProfilePopup(profileContextMenu.pubKey, null) - onCreateOneToOneChat: { - Global.changeAppSectionBySectionType(Constants.appSection.chat) - root.store.chatCommunitySectionModule.createOneToOneChat("", profileContextMenu.pubKey, "") - } - onReviewContactRequest: Global.openReviewContactRequestPopup(profileContextMenu.pubKey, null) - onSendContactRequest: Global.openContactRequestPopup(profileContextMenu.pubKey, null) - onEditNickname: Global.openNicknamePopupRequested(profileContextMenu.pubKey, null) - onRemoveNickname: (displayName) => { - root.store.contactsStore.changeContactNickname(profileContextMenu.pubKey, "", displayName, true) - } - onUnblockContact: Global.unblockContactRequested(profileContextMenu.pubKey) - onMarkAsUntrusted: Global.markAsUntrustedRequested(profileContextMenu.pubKey) - onRemoveTrustStatus: root.store.contactsStore.removeTrustStatus(profileContextMenu.pubKey) - onRemoveContact: Global.removeContactRequested(profileContextMenu.pubKey) - onBlockContact: Global.blockContactRequested(profileContextMenu.pubKey) - onRemoveFromGroup: { - root.store.removeMemberFromGroupChat(profileContextMenu.pubKey) - } + + onOpenProfileClicked: root.openProfileRequested(pubKey) + onCreateOneToOneChat: root.createOneToOneChatRequested(pubKey) + onReviewContactRequest: root.reviewContactRequestRequested(pubKey) + onSendContactRequest: root.sendContactRequestRequested(pubKey) + onEditNickname: root.editNicknameRequested(pubKey) + onRemoveNickname: root.removeNicknameRequested(pubKey) + onUnblockContact: root.unblockContactRequested(pubKey) + onMarkAsUntrusted: root.markAsUntrustedRequested(pubKey) + onRemoveTrustStatus: root.removeTrustStatusRequested(pubKey) + onRemoveContact: root.removeContactRequested(pubKey) + onBlockContact: root.blockContactRequested(pubKey) + onRemoveFromGroup: root.removeContactFromGroupRequested(pubKey) + onClosed: destroy() } } diff --git a/ui/app/AppLayouts/Chat/views/ChatView.qml b/ui/app/AppLayouts/Chat/views/ChatView.qml index 82592982f0..9a7561d6e7 100644 --- a/ui/app/AppLayouts/Chat/views/ChatView.qml +++ b/ui/app/AppLayouts/Chat/views/ChatView.qml @@ -1,5 +1,7 @@ -import QtQuick 2.13 -import QtQuick.Controls 2.13 +import QtQuick 2.15 +import QtQuick.Controls 2.15 +import QtQuick.Layouts 1.15 + import Qt.labs.settings 1.0 import utils 1.0 @@ -13,15 +15,12 @@ import shared.stores.send 1.0 as SendStores import SortFilterProxyModel 0.2 import StatusQ 0.1 +import StatusQ.Controls 0.1 import StatusQ.Core 0.1 import StatusQ.Core.Theme 0.1 +import StatusQ.Core.Utils 0.1 import StatusQ.Layout 0.1 import StatusQ.Popups 0.1 -import StatusQ.Controls 0.1 -import QtQuick.Layouts 1.15 - -import "." -import "../panels" import AppLayouts.Communities.controls 1.0 import AppLayouts.Communities.panels 1.0 @@ -33,9 +32,10 @@ import AppLayouts.Wallet.stores 1.0 as WalletStore import AppLayouts.Chat.stores 1.0 as ChatStores -import "../popups" -import "../helpers" import "../controls" +import "../helpers" +import "../panels" +import "../popups" StatusSectionLayout { id: root @@ -183,7 +183,10 @@ StatusSectionLayout { } anchors.fill: parent - store: root.rootStore + + chatType: root.chatContentModule.chatDetails.type + isAdmin: root.chatContentModule.amIChatAdmin() + label: qsTr("Members") communityMemberReevaluationStatus: root.rootStore.communityMemberReevaluationStatus @@ -196,6 +199,28 @@ StatusSectionLayout { expectedRoles: ["pubKey"] } } + + onOpenProfileRequested: Global.openProfilePopup(pubKey, null) + onReviewContactRequestRequested: Global.openReviewContactRequestPopup(pubKey, null) + onSendContactRequestRequested: Global.openContactRequestPopup(pubKey, null) + onEditNicknameRequested: Global.openNicknamePopupRequested(pubKey, null) + onBlockContactRequested: Global.blockContactRequested(pubKey) + onUnblockContactRequested: Global.unblockContactRequested(pubKey) + onMarkAsUntrustedRequested: Global.markAsUntrustedRequested(pubKey) + onRemoveContactRequested: Global.removeContactRequested(pubKey) + + onRemoveNicknameRequested: { + const oldName = ModelUtils.getByKey(usersModel, "pubKey", pubKey, "localNickname") + root.contactsStore.changeContactNickname(pubKey, "", oldName, true) + } + + onCreateOneToOneChatRequested: { + Global.changeAppSectionBySectionType(Constants.appSection.chat) + root.rootStore.chatCommunitySectionModule.createOneToOneChat("", profileContextMenu.pubKey, "") + } + + onRemoveTrustStatusRequested: root.contactsStore.removeTrustStatus(pubKey) + onRemoveContactFromGroupRequested: root.rootStore.removeMemberFromGroupChat(pubKey) } }