import QtQuick 2.14 import QtQuick.Layouts 1.14 import utils 1.0 import shared.panels 1.0 import shared.controls 1.0 import StatusQ.Controls 0.1 import StatusQ.Components 0.1 import StatusQ.Popups 0.1 import StatusQ.Core.Utils 0.1 as StatusQUtils Item { id: root enum ImageSize { Compact, Middle, Big } property var store property string displayName property string pubkey property string icon property url previewIcon: icon property int trustStatus property int onlineStatus: Constants.onlineStatus.unknown property bool isContact: false property bool isBlocked property bool isCurrentUser property bool userIsEnsVerified property rect cropRect property int imageSize: ProfileHeader.ImageSize.Compact property bool displayNameVisible: true property bool displayNamePlusIconsVisible: false property bool pubkeyVisible: true property bool pubkeyVisibleWithCopy: false property bool emojiHashVisible: true property bool editImageButtonVisible: false property bool editButtonVisible: displayNamePlusIconsVisible property bool loading: false readonly property bool compact: root.imageSize === ProfileHeader.ImageSize.Compact property bool isBridgedAccount: false signal clicked() signal editClicked() Binding on previewIcon { value: icon } implicitWidth: contentContainer.implicitWidth implicitHeight: contentContainer.implicitHeight QtObject { id: d function getSize(compact, normal, big) { switch(root.imageSize) { case ProfileHeader.ImageSize.Compact: return compact; case ProfileHeader.ImageSize.Middle: return normal; case ProfileHeader.ImageSize.Big: return big; } } } Item { id: tmpCroppedImageHelper visible: false Image { id: tmpImage mipmap: true cache: false } property var keepGrabResultAlive; function setCroppedTmpIcon(source, x, y, width, height) { tmpCroppedImageHelper.width = width tmpCroppedImageHelper.height = height tmpImage.x = -x tmpImage.y = -y tmpImage.source = source tmpCroppedImageHelper.grabToImage(result => { keepGrabResultAlive = result root.previewIcon = result.url tmpImage.source = "" }) } } ColumnLayout { id: contentContainer spacing: root.compact ? 4 : 12 anchors { left: parent.left right: parent.right leftMargin: Style.current.smallPadding rightMargin: Style.current.smallPadding } Item { Layout.alignment: Qt.AlignHCenter implicitWidth: userImage.width implicitHeight: userImage.height UserImage { id: userImage objectName: "ProfileHeader_userImage" name: root.displayName pubkey: root.pubkey image: root.previewIcon interactive: false imageWidth: d.getSize(36, 64, 170) imageHeight: imageWidth ensVerified: root.userIsEnsVerified loading: root.loading onlineStatus: root.onlineStatus isBridgedAccount: root.isBridgedAccount } StatusRoundButton { id: editButton visible: root.editImageButtonVisible anchors.top: userImage.top anchors.right: userImage.right anchors.rightMargin: Math.round(userImage.width / 10) width: d.getSize(10, 24, 40) height: width type: StatusRoundButton.Type.Secondary icon.name: "edit_pencil" icon.width: d.getSize(8, 12, 24) icon.height: d.getSize(8, 12, 24) onClicked: { if (!!root.store.profileLargeImage) Global.openMenu(editImageMenuComponent, this) else Global.openChangeProfilePicPopup(tempIcon); } function tempIcon(image, aX, aY, bX, bY) { root.icon = image root.cropRect = Qt.rect(aX, aY, bX - aX, bY - aY) tmpCroppedImageHelper.setCroppedTmpIcon( image, aX, aY, bX - aX, bY - aY) } } } Item { Layout.fillWidth: true implicitHeight: displayNameLabel.implicitHeight visible: root.displayNameVisible StyledText { id: displayNameLabel width: parent.width height: parent.height text: root.displayName visible: !root.loading horizontalAlignment: Text.AlignHCenter elide: Text.ElideRight maximumLineCount: 3 wrapMode: Text.Wrap font { bold: true pixelSize: 17 } } Loader { anchors.centerIn: parent height: parent.height width: 100 visible: root.loading active: visible sourceComponent: LoadingComponent { radius: 4 } } } RowLayout { spacing: compact ? 4 : Style.current.halfPadding Layout.fillWidth: true Layout.alignment: Qt.AlignHCenter visible: root.displayNamePlusIconsVisible StyledText { objectName: "ProfileHeader_displayName" Layout.maximumWidth: root.width - verificationIcons.width - contentContainer.anchors.leftMargin - contentContainer.anchors.rightMargin - (editButtonLoader.active ? editButtonLoader.item.width : 0) text: root.displayName elide: Text.ElideRight font { weight: Font.Medium pixelSize: Style.current.primaryTextFontSize } } StatusContactVerificationIcons { id: verificationIcons visible: !root.isCurrentUser && !root.isBridgedAccount isContact: root.isContact trustIndicator: root.trustStatus isBlocked: root.isBlocked } Loader { id: editButtonLoader sourceComponent: SVGImage { objectName: "ProfileHeader_displayNameEditIcon" height: compact ? 10 : 16 width: compact ? 10 : 16 source: Style.svg("edit-message") MouseArea { anchors.fill: parent cursorShape: Qt.PointingHandCursor acceptedButtons: Qt.LeftButton onClicked: { root.editClicked() } } } active: root.editButtonVisible visible: active } } StyledText { Layout.fillWidth: true Layout.alignment: Qt.AlignHCenter visible: root.pubkeyVisible text: root.isBridgedAccount ? qsTr("Bridged from Discord") : Utils.getElidedCompressedPk(pubkey) horizontalAlignment: Text.AlignHCenter font.pixelSize: 13 color: Style.current.secondaryText } RowLayout { Layout.alignment: Qt.AlignHCenter visible: root.pubkeyVisibleWithCopy && !root.isBridgedAccount StyledText { id: txtChatKey text: qsTr("Chatkey:%1...").arg(pubkey.substring(0, 32)) horizontalAlignment: Text.AlignHCenter font.pixelSize: Style.current.primaryTextFontSize color: Style.current.secondaryText } CopyToClipBoardButton { id: copyBtn Layout.preferredWidth: 20 Layout.preferredHeight: 20 color: Style.current.transparent textToCopy: pubkey onCopyClicked: root.store.copyToClipboard(textToCopy) } } EmojiHash { id: emojiHash Layout.alignment: Qt.AlignHCenter visible: root.emojiHashVisible && !root.isBridgedAccount compact: root.compact publicKey: root.pubkey } } Component { id: editImageMenuComponent StatusMenu { StatusAction { text: !!root.icon ? qsTr("Select different image") : qsTr("Select image") assetSettings.name: "image" onTriggered: Global.openChangeProfilePicPopup(editButton.tempIcon) } StatusAction { text: qsTr("Use a collectible") assetSettings.name: "nft-profile" onTriggered: Global.openChangeProfilePicPopup(editButton.tempIcon) enabled: false // TODO enable this with the profile showcase (#13418) } StatusMenuSeparator {} StatusAction { text: qsTr("Remove image") type: StatusAction.Danger assetSettings.name: "delete" onTriggered: root.icon = "" } } } }