From f60dacc45dd35773fc205ef9c0a2640bb79030d7 Mon Sep 17 00:00:00 2001 From: Igor Sirotin Date: Mon, 8 Aug 2022 00:05:25 +0300 Subject: [PATCH] fix(Profile): Added menu to remove profile image --- .../Profile/popups/ChangeProfilePicModal.qml | 115 ---------- .../views/profile/MyProfileSettingsView.qml | 2 + ui/imports/shared/controls/ImageCropper.qml | 213 ------------------ .../shared/controls/chat/ProfileHeader.qml | 26 ++- .../shared/panels/CropCornerRectangle.qml | 29 --- .../shared/popups/ImageCropperModal.qml | 88 -------- 6 files changed, 27 insertions(+), 446 deletions(-) delete mode 100644 ui/app/AppLayouts/Profile/popups/ChangeProfilePicModal.qml delete mode 100644 ui/imports/shared/controls/ImageCropper.qml delete mode 100644 ui/imports/shared/panels/CropCornerRectangle.qml delete mode 100644 ui/imports/shared/popups/ImageCropperModal.qml diff --git a/ui/app/AppLayouts/Profile/popups/ChangeProfilePicModal.qml b/ui/app/AppLayouts/Profile/popups/ChangeProfilePicModal.qml deleted file mode 100644 index fd895a666f..0000000000 --- a/ui/app/AppLayouts/Profile/popups/ChangeProfilePicModal.qml +++ /dev/null @@ -1,115 +0,0 @@ -import QtQuick 2.13 -import QtQuick.Dialogs 1.3 - -import utils 1.0 - -import StatusQ.Controls 0.1 - -import shared 1.0 -import shared.panels 1.0 -import shared.popups 1.0 - -// TODO: replace with StatusModal -ModalPopup { - id: popup - title: qsTr("Profile picture") - - property var profileStore - - property string selectedImage // selectedImage is for us to be able to analyze it before setting it as current - property string uploadError - property url largeImage: popup.profileStore.profileLargeImage - property bool hasIdentityImage: !!popup.profileStore.profileLargeImage - - onClosed: { - destroy() - } - - onSelectedImageChanged: { - if (!selectedImage) { - return - } - - cropImageModal.open() - } - - Item { - anchors.fill: parent - - RoundedImage { - id: profilePic - source: popup.largeImage - width: 160 - height: 160 - anchors.verticalCenter: parent.verticalCenter - anchors.horizontalCenter: parent.horizontalCenter - border.width: 1 - border.color: Style.current.border - onClicked: imageDialog.open() - } - - StyledText { - visible: !!uploadError - text: uploadError - anchors.left: parent.left - anchors.right: parent.right - anchors.top: profilePic.bottom - horizontalAlignment: Text.AlignHCenter - font.pixelSize: 13 - wrapMode: Text.WordWrap - anchors.topMargin: 13 - font.weight: Font.Thin - color: Style.current.danger - } - - ImageCropperModal { - id: cropImageModal - - selectedImage: popup.selectedImage - ratio: "1:1" - onCropFinished: { - popup.uploadError = popup.profileStore.uploadImage(selectedImage, aX, aY, bX, bY) - } - } - } - - footer: Item { - width: parent.width - height: uploadBtn.height - - StatusFlatButton { - visible: popup.hasIdentityImage - type: StatusBaseButton.Type.Danger - text: qsTr("Remove") - anchors.right: uploadBtn.left - anchors.rightMargin: Style.current.padding - anchors.bottom: parent.bottom - onClicked: { - popup.uploadError = popup.profileStore.removeImage() - } - } - - StatusButton { - id: uploadBtn - text: qsTr("Upload") - anchors.right: parent.right - anchors.bottom: parent.bottom - onClicked: { - imageDialog.open() - } - - FileDialog { - id: imageDialog - title: qsTr("Please choose an image") - folder: shortcuts.pictures - nameFilters: [ - qsTr("Image files (*.jpg *.jpeg *.png)") - ] - onAccepted: { - selectedImage = imageDialog.fileUrls[0] - } - } - } - } -} - diff --git a/ui/app/AppLayouts/Profile/views/profile/MyProfileSettingsView.qml b/ui/app/AppLayouts/Profile/views/profile/MyProfileSettingsView.qml index fe8cade5ef..c37175c7ba 100644 --- a/ui/app/AppLayouts/Profile/views/profile/MyProfileSettingsView.qml +++ b/ui/app/AppLayouts/Profile/views/profile/MyProfileSettingsView.qml @@ -58,6 +58,8 @@ ColumnLayout { Layout.leftMargin: Style.current.padding Layout.rightMargin: Style.current.padding + store: root.profileStore + displayName: profileStore.name pubkey: profileStore.pubkey icon: profileStore.profileLargeImage diff --git a/ui/imports/shared/controls/ImageCropper.qml b/ui/imports/shared/controls/ImageCropper.qml deleted file mode 100644 index 4c57c6d5e3..0000000000 --- a/ui/imports/shared/controls/ImageCropper.qml +++ /dev/null @@ -1,213 +0,0 @@ -import QtQuick 2.13 - -import "../panels" - -import utils 1.0 - -Item { - id: root - property Image image - property alias selectorRectangle: selectorRectangle - property string ratio: "" - property var splitRatio: !!ratio ? ratio.split(":") : null - property int widthRatio: !!ratio ? parseInt(splitRatio[0]) : -1 - property int heightRatio: !!ratio ? parseInt(splitRatio[1]) : -1 - property bool settingCorners: false - property int draggedCorner: 0 - property bool ready: false - - readonly property int topLeft: 0 - readonly property int topRight: 1 - readonly property int bottomLeft: 2 - readonly property int bottomRight: 3 - - width: image.width - height: image.height - - Rectangle { - id: selectorRectangle - visible: false - x: 0 - y: 0 - border.width: 2 - border.color: Style.current.orange - color: Style.current.transparent - - function fitRatio(makeBigger) { - if (!!ratio) { - if ((makeBigger && selectorRectangle.width < selectorRectangle.height) || (!makeBigger && selectorRectangle.width > selectorRectangle.height)) { - selectorRectangle.width = (selectorRectangle.height/heightRatio) * widthRatio - } else { - selectorRectangle.height = (selectorRectangle.width/widthRatio) * heightRatio - } - } - } - - function initialSetup() { - selectorRectangle.width = image.width - selectorRectangle.height = image.height - - fitRatio() - topLeftCorner.x = 0 - topLeftCorner.y = 0 - topRightCorner.x = selectorRectangle.width - topRightCorner.width - topRightCorner.y = 0 - bottomLeftCorner.x = 0 - bottomLeftCorner.y = selectorRectangle.height - topRightCorner.height - bottomRightCorner.x = selectorRectangle.width - topRightCorner.width - bottomRightCorner.y = selectorRectangle.height - topRightCorner.height - } - - - function adjustRectangleSize() { - if (!selectorRectangle.visible) { - return - } - - selectorRectangle.width = bottomRightCorner.x + bottomRightCorner.width - topLeftCorner.x - selectorRectangle.height = bottomRightCorner.y + bottomRightCorner.height - topLeftCorner.y - selectorRectangle.x = topLeftCorner.x - selectorRectangle.y = topLeftCorner.y - - if (!!ratio) { - // FIXME with a ratio that is not 1:1, the rectangle can go out of bounds - fitRatio() - - switch(draggedCorner) { - case topLeft: - selectorRectangle.x = topLeftCorner.x - selectorRectangle.y = topLeftCorner.y - break - case topRight: - selectorRectangle.x = topRightCorner.x - selectorRectangle.width + topRightCorner.width - selectorRectangle.y = topRightCorner.y - break - case bottomLeft: - selectorRectangle.x = bottomLeftCorner.x - selectorRectangle.y = bottomLeftCorner.y - selectorRectangle.height + bottomLeftCorner.height - break - case bottomRight: - selectorRectangle.x = bottomRightCorner.x - selectorRectangle.width + bottomRightCorner.width - selectorRectangle.y = bottomRightCorner.y - selectorRectangle.height + bottomRightCorner.height - break - } - } - } - - Connections { - target: image - onStatusChanged: { - if (image.status === Image.Ready) { - selectorRectangle.initialSetup() - selectorRectangle.visible = true - root.ready = true - } - } - } - } - function putCorners() { - settingCorners = true - - topLeftCorner.x = selectorRectangle.x - topLeftCorner.y = selectorRectangle.y - topRightCorner.x = selectorRectangle.x + selectorRectangle.width - topRightCorner.width - topRightCorner.y = selectorRectangle.y - bottomLeftCorner.x = selectorRectangle.x - bottomLeftCorner.y = selectorRectangle.y + selectorRectangle.height - topRightCorner.height - bottomRightCorner.x = selectorRectangle.x + selectorRectangle.width - topRightCorner.width - bottomRightCorner.y = selectorRectangle.y + selectorRectangle.height - topRightCorner.height - - settingCorners = false - } - - - // Size calculations are only done on top-left and bottom-right, because the other two corners follow them - CropCornerRectangle { - id: topLeftCorner - onXChanged: { - if (settingCorners) return - if (x < 0) x = 0 - if (x > topRightCorner.x - width) x = topRightCorner.x - width - - bottomLeftCorner.x = x - selectorRectangle.adjustRectangleSize() - } - onYChanged: { - if (settingCorners) return - if (y < 0) y = 0 - if (y > bottomRightCorner.y - height) y = bottomRightCorner.y - height - - topRightCorner.y = y - selectorRectangle.adjustRectangleSize() - } - onPressed: { - draggedCorner = topLeft - } - - onReleased: { - putCorners() - } - } - - CropCornerRectangle { - id: topRightCorner - onXChanged: { - if (settingCorners) return - bottomRightCorner.x = x - } - onYChanged: { - if (settingCorners) return - topLeftCorner.y = y - } - onPressed: { - draggedCorner = topRight - } - onReleased: { - putCorners() - } - } - - CropCornerRectangle { - id: bottomLeftCorner - onXChanged: { - if (settingCorners) return - topLeftCorner.x = x - } - onYChanged: { - if (settingCorners) return - bottomRightCorner.y = y - } - onPressed: { - draggedCorner = bottomLeft - } - onReleased: { - putCorners() - } - } - - CropCornerRectangle { - id: bottomRightCorner - onXChanged: { - if (settingCorners) return - if (x < topLeftCorner.x + topLeftCorner.width) x = topLeftCorner.x + topLeftCorner.width - if (x > image.width - width) x = image.width - width - topRightCorner.x = x - - selectorRectangle.adjustRectangleSize() - } - onYChanged: { - if (settingCorners) return - if (y < topRightCorner.y + topRightCorner.height) y = topRightCorner.y + topRightCorner.height - if (y > image.height - height) y = image.height - height - bottomLeftCorner.y = y - - selectorRectangle.adjustRectangleSize() - } - onPressed: { - draggedCorner = bottomRight - } - onReleased: { - putCorners() - } - } -} diff --git a/ui/imports/shared/controls/chat/ProfileHeader.qml b/ui/imports/shared/controls/chat/ProfileHeader.qml index 429135de0c..11df8f8996 100644 --- a/ui/imports/shared/controls/chat/ProfileHeader.qml +++ b/ui/imports/shared/controls/chat/ProfileHeader.qml @@ -7,6 +7,7 @@ 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 { @@ -94,7 +95,12 @@ Item { icon.width: d.getSize(8, 12, 20) icon.height: d.getSize(8, 12, 20) - onClicked: Global.openChangeProfilePicPopup() + onClicked: { + if (!!root.store.profileLargeImage) + imageEditMenu.popup(this, mouse.x, mouse.y); + else + Global.openChangeProfilePicPopup(); + } } } @@ -210,4 +216,22 @@ Item { publicKey: root.pubkey } } + + StatusPopupMenu { + id: imageEditMenu + + StatusMenuItem { + text: qsTr("Upload a file") + icon.name: "download" + iconRotation: 180 + onTriggered: Global.openChangeProfilePicPopup() + } + + StatusMenuItem { + text: qsTr("Remove image") + type: StatusMenuItem.Danger + icon.name: "delete" + onTriggered: root.store.removeImage() + } + } } diff --git a/ui/imports/shared/panels/CropCornerRectangle.qml b/ui/imports/shared/panels/CropCornerRectangle.qml deleted file mode 100644 index ca38e4ec2b..0000000000 --- a/ui/imports/shared/panels/CropCornerRectangle.qml +++ /dev/null @@ -1,29 +0,0 @@ -import QtQuick 2.13 - -import utils 1.0 - -Rectangle { - signal released() - signal pressed() - - id: root - width: 25 - height: 25 - border.width: 2 - border.color: Style.current.orange - color: Utils.setColorAlpha(Style.current.orange, 0.5) - - Drag.active: dragArea.drag.active - - MouseArea { - id: dragArea - property int oldX - property int oldY - - anchors.fill: parent - drag.target: parent - cursorShape: Qt.PointingHandCursor - onReleased: root.released() - onPressed: root.pressed() - } -} diff --git a/ui/imports/shared/popups/ImageCropperModal.qml b/ui/imports/shared/popups/ImageCropperModal.qml deleted file mode 100644 index 429a7e42ed..0000000000 --- a/ui/imports/shared/popups/ImageCropperModal.qml +++ /dev/null @@ -1,88 +0,0 @@ -import QtQuick 2.13 -import QtQuick.Controls 2.13 -import QtQuick.Layouts 1.13 - -import utils 1.0 - -import StatusQ.Controls 0.1 - -import "../controls" -import "." - -// TODO: replace with StatusModal -ModalPopup { - property string selectedImage - property string ratio: "1:1" - property int aX: 0 - property int aY: 0 - property int bX: 0 - property int bY: 0 - signal cropFinished(aX: int, aY: int, bX: int, bY: int) - - id: cropImageModal - width: image.width + 50 - height: image.height + 170 - title: qsTr("Crop your image (optional)") - - Image { - id: image - width: 400 - source: cropImageModal.selectedImage - anchors.verticalCenter: parent.verticalCenter - anchors.horizontalCenter: parent.horizontalCenter - fillMode: Image.PreserveAspectFit - } - - ImageCropper { - id: imageCropper - x: image.x - y: image.y - image: image - ratio: cropImageModal.ratio - onReadyChanged: { - if (ready) { - // cropImageModal.calculateCrop() - cropImageModal.aX = Qt.binding(function() { - const aXPercent = imageCropper.selectorRectangle.x / image.width - return Math.round(aXPercent * image.sourceSize.width) - }) - cropImageModal.aY = Qt.binding(function() { - const aYPercent = imageCropper.selectorRectangle.y / image.height - return Math.round(aYPercent * image.sourceSize.height) - }) - cropImageModal.bX = Qt.binding(function() { - const bXPercent = (imageCropper.selectorRectangle.x + imageCropper.selectorRectangle.width) / image.width - return Math.round(bXPercent * image.sourceSize.width) - }) - cropImageModal.bY = Qt.binding(function() { - const bYPercent = (imageCropper.selectorRectangle.y + imageCropper.selectorRectangle.height) / image.height - return Math.round(bYPercent * image.sourceSize.height) - }) - } - } - - } - - footer: StatusButton { - id: doneBtn - text: qsTr("Finish") - anchors.right: parent.right - anchors.bottom: parent.bottom - onClicked: { - const aXPercent = imageCropper.selectorRectangle.x / image.width - const aYPercent = imageCropper.selectorRectangle.y / image.height - const bXPercent = (imageCropper.selectorRectangle.x + imageCropper.selectorRectangle.width) / image.width - const bYPercent = (imageCropper.selectorRectangle.y + imageCropper.selectorRectangle.height) / image.height - - - const aX = Math.round(aXPercent * image.sourceSize.width) - const aY = Math.round(aYPercent * image.sourceSize.height) - - const bX = Math.round(bXPercent * image.sourceSize.width) - const bY = Math.round(bYPercent * image.sourceSize.height) - - cropImageModal.cropFinished(aX, aY, bX, bY) - cropImageModal.close() - } - } -}