286 lines
9.2 KiB
QML
Raw Permalink Normal View History

import QtQuick 2.15
import QtQuick.Layouts 1.15
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
2025-01-13 10:08:34 +01:00
import AppLayouts.Profile.panels 1.0
import AppLayouts.Profile.popups 1.0
import AppLayouts.Profile.stores 1.0
2025-01-13 10:08:34 +01:00
import shared 1.0
import shared.controls 1.0
import shared.stores 1.0 as SharedStores
import shared.views 1.0
import shared.views.chat 1.0
2025-01-13 10:08:34 +01:00
import utils 1.0
import SortFilterProxyModel 0.2
2020-05-27 17:28:25 -04:00
SettingsContentBase {
id: root
property ContactsStore contactsStore
property SharedStores.UtilsStore utilsStore
required property var mutualContactsModel
required property var blockedContactsModel
required property var pendingContactsModel
required property int pendingReceivedContactsCount
required property var dismissedReceivedRequestContactsModel
property alias searchStr: searchBox.text
titleRowComponentLoader.sourceComponent: StatusButton {
objectName: "ContactsView_ContactRequest_Button"
2025-01-13 10:08:34 +01:00
text: qsTr("Send contact request to chat key")
onClicked: sendContactRequestComponent.createObject(root).open()
}
function openContextMenu(model, pubKey) {
const entry = ModelUtils.getByKey(model, "pubKey", pubKey)
const profileType = Utils.getProfileType(entry.isCurrentUser, false, entry.isBlocked)
const contactType = Utils.getContactType(entry.contactRequest, entry.isContact)
refactor ProfileContextMenu to make it a functional component refactor ProfileContextMenu to make it a functional component refactor ProfileContextMenu to make it a functional component refactor ProfileContextMenu to make it a functional component This refactor ProfileContextMenu to make it a functional component by: refactored out direct calls to backend, and passing backend data structures and moved this logic to the callers, also refactored common calls between the callers common types of context menus have been extracted to their sub components which removes a lot of logic too and makes the behaviour very clear user verification workflow (which was already disabled) has been removed refactor: use signals and call singletons on the parent instead remove unused code for now from profile context menu refactor profile context menu into two components; add property to storybook extract blocked profile context menu and self profile context menu use profileType instead of individual bools refactor to pass trustStatus as an argument make contact type a parameter remove unnecessary method from RegularProfileContextMenu add ensVerified property to ProfileContextMenu components add onlineStatus property to ProfileContextMenu components move ProfileContextMenu storybook controls to the right sidebar move contactDetails logic up from the view add local nickname property to ProfileContextMenu components fix issue with missing signal; fix logs in storybook use constant for profileType instead of string refactor common code into a single method refactor getProfileContext remove references to contactDetails which are not longer needed remove unnecessary comments fix bridged constant refactor into a single ProfileContextMenu component refactor into a single ProfileContextMenu component refactor into a single ProfileContextMenu component simplify imports remove unused store field move methods from utils to contacts store remove onClosed signal remove unused param rename ProfileContextMenu variables simplify signals in ProfileContextMenu remove ; refactor: do early return simplify ifs move ProfileContextMenu to its own storybook page fix wrong params fix profile context menu separator add missing signals to profile context menu on the members tab panel
2024-09-06 11:55:44 -04:00
const params = {
pubKey, profileType, contactType,
compressedPubKey: entry.compressedPubKey,
emojiHash: root.utilsStore.getEmojiHash(pubKey),
displayName: entry.preferredDisplayName,
userIcon: entry.icon,
colorHash: entry.colorHash,
colorId: entry.colorId,
trustStatus: entry.trustStatus,
onlineStatus: entry.onlineStatus,
ensVerified: entry.isEnsVerified,
hasLocalNickname: !!entry.localNickname
}
Global.openMenu(contactContextMenuComponent, this, params)
}
headerComponents: ColumnLayout {
width: root.contentWidth
spacing: Theme.padding
StatusTabBar {
id: contactsTabBar
2025-01-13 10:08:34 +01:00
Layout.fillWidth: true
StatusTabButton {
2025-01-13 10:08:34 +01:00
objectName: "ContactsView_Contacts_Button"
width: implicitWidth
text: qsTr("Contacts")
}
StatusTabButton {
objectName: "ContactsView_PendingRequest_Button"
2025-01-13 10:08:34 +01:00
width: implicitWidth
2025-01-13 10:08:34 +01:00
enabled: !root.pendingContactsModel.ModelCount.empty
text: qsTr("Pending Requests")
badge.value: root.pendingReceivedContactsCount
}
StatusTabButton {
objectName: "ContactsView_DismissedRequest_Button"
width: implicitWidth
enabled: !root.dismissedReceivedRequestContactsModel.ModelCount.empty
text: qsTr("Dismissed Requests")
}
StatusTabButton {
objectName: "ContactsView_Blocked_Button"
2025-01-13 10:08:34 +01:00
width: implicitWidth
2025-01-13 10:08:34 +01:00
enabled: !root.blockedContactsModel.ModelCount.empty
text: qsTr("Blocked")
}
}
SearchBox {
id: searchBox
2025-01-13 10:08:34 +01:00
Layout.fillWidth: true
placeholderText: qsTr("Search by name or chat key")
}
}
2025-01-13 10:08:34 +01:00
StackLayout {
width: root.contentWidth
height: root.availableHeight
2025-01-13 10:08:34 +01:00
currentIndex: contactsTabBar.currentIndex
ContactsList {
inviteButtonVisible: searchBox.text === ""
model: SortFilterProxyModel {
sourceModel: root.mutualContactsModel
filters: UserSearchFilter {
searchString: searchBox.text
}
sorters: [
RoleSorter {
roleName: "isVerified"
sortOrder: Qt.DescendingOrder
},
StringSorter {
roleName: "preferredDisplayName"
caseSensitivity: Qt.CaseInsensitive
}
]
}
2025-01-13 10:08:34 +01:00
section.property: "isVerified"
section.delegate: SectionComponent {
text: section === "true" ? qsTr("Trusted Contacts")
: qsTr("Contacts")
}
2025-01-13 10:08:34 +01:00
section.labelPositioning: ViewSection.InlineLabels |
ViewSection.CurrentLabelAtStart
}
2025-01-13 10:08:34 +01:00
ContactsList {
model: SortFilterProxyModel {
sourceModel: root.pendingContactsModel
filters: UserSearchFilter {
searchString: searchBox.text
}
2025-01-13 10:08:34 +01:00
sorters: [
FilterSorter { // Received CRs first
ValueFilter {
roleName: "contactRequest"
value: Constants.ContactRequestState.Received
}
},
StringSorter {
roleName: "preferredDisplayName"
caseSensitivity: Qt.CaseInsensitive
}
]
}
2025-01-13 10:08:34 +01:00
section.property: "contactRequest"
section.delegate: SectionComponent {
text: section === `${Constants.ContactRequestState.Received}`
? qsTr("Received") : qsTr("Sent")
}
2025-01-13 10:08:34 +01:00
section.labelPositioning: ViewSection.InlineLabels |
ViewSection.CurrentLabelAtStart
}
ContactsList {
model: SortFilterProxyModel {
sourceModel: root.dismissedReceivedRequestContactsModel
filters: UserSearchFilter {
searchString: searchBox.text
}
sorters: StringSorter {
roleName: "preferredDisplayName"
caseSensitivity: Qt.CaseInsensitive
}
}
}
2025-01-13 10:08:34 +01:00
ContactsList {
model: SortFilterProxyModel {
sourceModel: root.blockedContactsModel
filters: UserSearchFilter {
searchString: searchBox.text
}
sorters: StringSorter {
roleName: "preferredDisplayName"
caseSensitivity: Qt.CaseInsensitive
}
}
}
}
2025-01-13 10:08:34 +01:00
component ContactsList: ContactsListPanel {
onProfilePopupRequested: Global.openProfilePopup(publicKey)
onContextMenuRequested: root.openContextMenu(model, publicKey)
onSendMessageRequested: root.contactsStore.joinPrivateChat(publicKey)
onAcceptContactRequested: root.contactsStore.acceptContactRequest(publicKey, "")
onRejectContactRequested: root.contactsStore.dismissContactRequest(publicKey, "")
onRejectionRemoved: root.contactsStore.acceptContactRequest(publicKey, "")
2025-01-13 10:08:34 +01:00
}
component SectionComponent: Rectangle {
required property string section
property alias text: sectionText.text
width: ListView.view.width
height: sectionText.implicitHeight
color: Theme.palette.statusListItem.backgroundColor
StatusBaseText {
id: sectionText
width: parent.width
anchors.verticalCenter: parent.verticalCenter
topPadding: Theme.halfPadding
bottomPadding: Theme.halfPadding
color: Theme.palette.baseColor1
font.pixelSize: Theme.additionalTextSize
font.weight: Font.Medium
elide: Text.ElideRight
}
}
2025-01-13 10:08:34 +01:00
Component {
id: sendContactRequestComponent
SendContactRequestModal {
contactsStore: root.contactsStore
onClosed: destroy()
}
}
Component {
id: contactContextMenuComponent
ProfileContextMenu {
id: menu
property string pubKey
onOpenProfileClicked: Global.openProfilePopup(menu.pubKey, null, null)
onReviewContactRequest: Global.openReviewContactRequestPopup(menu.pubKey, null)
onSendContactRequest: Global.openContactRequestPopup(menu.pubKey, null)
onEditNickname: Global.openNicknamePopupRequested(menu.pubKey, null)
onUnblockContact: Global.unblockContactRequested(menu.pubKey)
onMarkAsUntrusted: Global.markAsUntrustedRequested(menu.pubKey)
onRemoveContact: Global.removeContactRequested(menu.pubKey)
onBlockContact: Global.blockContactRequested(menu.pubKey)
onCreateOneToOneChat: root.contactsStore.joinPrivateChat(menu.pubKey)
onRemoveTrustStatus: root.contactsStore.removeTrustStatus(menu.pubKey)
onRemoveNickname: root.contactsStore.changeContactNickname(menu.pubKey, "",
menu.displayName, true)
onMarkAsTrusted: Global.openMarkAsIDVerifiedPopup(menu.pubKey, null)
onRemoveTrustedMark: Global.openRemoveIDVerificationDialog(menu.pubKey, null)
onClosed: destroy()
}
}
}