fix(profile-settings): Add usage dirty values for preview and load image profile on save
Closes: #7920 #7917
This commit is contained in:
parent
7e7daa56e1
commit
13acb5730d
|
@ -73,30 +73,44 @@ QtObject:
|
||||||
proc getSocialLinksJson(self: View): string {.slot.} =
|
proc getSocialLinksJson(self: View): string {.slot.} =
|
||||||
$(%*self.socialLinksModel.items)
|
$(%*self.socialLinksModel.items)
|
||||||
|
|
||||||
|
proc temporarySocialLinksJsonChanged*(self: View) {.signal.}
|
||||||
|
proc getTemporarySocialLinksJson(self: View): string {.slot.} =
|
||||||
|
$(%*self.temporarySocialLinksModel.items)
|
||||||
|
|
||||||
|
|
||||||
QtProperty[string] socialLinksJson:
|
QtProperty[string] socialLinksJson:
|
||||||
read = getSocialLinksJson
|
read = getSocialLinksJson
|
||||||
notify = socialLinksJsonChanged
|
notify = socialLinksJsonChanged
|
||||||
|
|
||||||
|
QtProperty[string] temporarySocialLinksJson:
|
||||||
|
read = getTemporarySocialLinksJson
|
||||||
|
notify = temporarySocialLinksJsonChanged
|
||||||
|
|
||||||
QtProperty[bool] socialLinksDirty:
|
QtProperty[bool] socialLinksDirty:
|
||||||
read = areSocialLinksDirty
|
read = areSocialLinksDirty
|
||||||
notify = socialLinksDirtyChanged
|
notify = socialLinksDirtyChanged
|
||||||
|
|
||||||
proc createCustomLink(self: View, text: string, url: string) {.slot.} =
|
proc createCustomLink(self: View, text: string, url: string) {.slot.} =
|
||||||
self.temporarySocialLinksModel.appendItem(initSocialLinkItem(text, url, LinkType.Custom))
|
self.temporarySocialLinksModel.appendItem(initSocialLinkItem(text, url, LinkType.Custom))
|
||||||
|
self.temporarySocialLinksJsonChanged()
|
||||||
self.socialLinksDirtyChanged()
|
self.socialLinksDirtyChanged()
|
||||||
|
|
||||||
proc removeCustomLink(self: View, uuid: string) {.slot.} =
|
proc removeCustomLink(self: View, uuid: string) {.slot.} =
|
||||||
if (self.temporarySocialLinksModel.removeItem(uuid)):
|
if (self.temporarySocialLinksModel.removeItem(uuid)):
|
||||||
|
self.temporarySocialLinksJsonChanged()
|
||||||
self.socialLinksDirtyChanged()
|
self.socialLinksDirtyChanged()
|
||||||
|
|
||||||
proc updateLink(self: View, uuid: string, text: string, url: string): bool {.slot.} =
|
proc updateLink(self: View, uuid: string, text: string, url: string): bool {.slot.} =
|
||||||
if (self.temporarySocialLinksModel.updateItem(uuid, text, url)):
|
if (self.temporarySocialLinksModel.updateItem(uuid, text, url)):
|
||||||
|
self.temporarySocialLinksJsonChanged()
|
||||||
self.socialLinksDirtyChanged()
|
self.socialLinksDirtyChanged()
|
||||||
|
|
||||||
proc resetSocialLinks(self: View): bool {.slot.} =
|
proc resetSocialLinks(self: View): bool {.slot.} =
|
||||||
if (self.areSocialLinksDirty()):
|
if (self.areSocialLinksDirty()):
|
||||||
self.temporarySocialLinksModel.setItems(self.socialLinksModel.items)
|
self.temporarySocialLinksModel.setItems(self.socialLinksModel.items)
|
||||||
self.socialLinksDirtyChanged()
|
self.socialLinksDirtyChanged()
|
||||||
|
self.temporarySocialLinksJsonChanged()
|
||||||
|
|
||||||
|
|
||||||
proc saveSocialLinks(self: View): bool {.slot.} =
|
proc saveSocialLinks(self: View): bool {.slot.} =
|
||||||
result = self.delegate.saveSocialLinks()
|
result = self.delegate.saveSocialLinks()
|
||||||
|
@ -104,6 +118,7 @@ QtObject:
|
||||||
self.socialLinksModel.setItems(self.temporarySocialLinksModel.items)
|
self.socialLinksModel.setItems(self.temporarySocialLinksModel.items)
|
||||||
self.socialLinksDirtyChanged()
|
self.socialLinksDirtyChanged()
|
||||||
self.socialLinksJsonChanged()
|
self.socialLinksJsonChanged()
|
||||||
|
self.temporarySocialLinksJsonChanged()
|
||||||
|
|
||||||
proc bioChanged*(self: View) {.signal.}
|
proc bioChanged*(self: View) {.signal.}
|
||||||
proc getBio(self: View): string {.slot.} =
|
proc getBio(self: View): string {.slot.} =
|
||||||
|
|
|
@ -42,6 +42,13 @@ Loader {
|
||||||
color: root.asset.imgIsIdenticon ?
|
color: root.asset.imgIsIdenticon ?
|
||||||
Theme.palette.statusRoundedImage.backgroundColor :
|
Theme.palette.statusRoundedImage.backgroundColor :
|
||||||
root.asset.bgColor
|
root.asset.bgColor
|
||||||
|
image.fillMode: root.asset.cropRect ? Image.PreserveAspectCrop
|
||||||
|
: Image.PreserveAspectFit
|
||||||
|
image.scale: root.asset.scale
|
||||||
|
image.x: root.asset.cropRectangle ? -root.asset.cropRectangle.x
|
||||||
|
: 0
|
||||||
|
image.y: root.asset.cropRectangle ? -root.asset.cropRectangle.y
|
||||||
|
: 0
|
||||||
}
|
}
|
||||||
Loader {
|
Loader {
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
|
|
|
@ -34,4 +34,7 @@ QtObject {
|
||||||
property bool isImage: false
|
property bool isImage: false
|
||||||
property int imgStatus
|
property int imgStatus
|
||||||
property bool imgIsIdenticon: false
|
property bool imgIsIdenticon: false
|
||||||
|
|
||||||
|
// crop
|
||||||
|
property rect cropRect
|
||||||
}
|
}
|
||||||
|
|
|
@ -79,6 +79,8 @@ SettingsContentBase {
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
profileStore: root.profileStore
|
profileStore: root.profileStore
|
||||||
contactsStore: root.contactsStore
|
contactsStore: root.contactsStore
|
||||||
|
dirtyValues: settingsView.dirtyValues
|
||||||
|
dirty: settingsView.dirty
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,8 @@ import StatusQ.Core.Theme 0.1
|
||||||
Item {
|
Item {
|
||||||
property alias profileStore: profilePreview.profileStore
|
property alias profileStore: profilePreview.profileStore
|
||||||
property alias contactsStore: profilePreview.contactsStore
|
property alias contactsStore: profilePreview.contactsStore
|
||||||
|
property alias dirtyValues: profilePreview.dirtyValues
|
||||||
|
property alias dirty: profilePreview.dirty
|
||||||
|
|
||||||
implicitHeight: profilePreview.implicitHeight
|
implicitHeight: profilePreview.implicitHeight
|
||||||
+ profilePreview.anchors.topMargin
|
+ profilePreview.anchors.topMargin
|
||||||
|
|
|
@ -28,10 +28,18 @@ ColumnLayout {
|
||||||
property ProfileStore profileStore
|
property ProfileStore profileStore
|
||||||
property WalletStore walletStore
|
property WalletStore walletStore
|
||||||
|
|
||||||
|
property QtObject dirtyValues: QtObject {
|
||||||
|
property string displayName: descriptionPanel.displayName.text
|
||||||
|
property string bio: descriptionPanel.bio.text
|
||||||
|
property bool biomentricValue: biometricsSwitch.checked
|
||||||
|
property url profileLargeImage: profileHeader.icon
|
||||||
|
}
|
||||||
|
|
||||||
readonly property bool dirty: descriptionPanel.displayName.text !== profileStore.displayName ||
|
readonly property bool dirty: descriptionPanel.displayName.text !== profileStore.displayName ||
|
||||||
descriptionPanel.bio.text !== profileStore.bio ||
|
descriptionPanel.bio.text !== profileStore.bio ||
|
||||||
profileStore.socialLinksDirty ||
|
profileStore.socialLinksDirty ||
|
||||||
biometricsSwitch.checked != biometricsSwitch.currentStoredValue
|
biometricsSwitch.checked != biometricsSwitch.currentStoredValue ||
|
||||||
|
profileHeader.icon !== profileStore.profileLargeImage
|
||||||
|
|
||||||
readonly property bool valid: !!descriptionPanel.displayName.text && descriptionPanel.displayName.valid
|
readonly property bool valid: !!descriptionPanel.displayName.text && descriptionPanel.displayName.valid
|
||||||
|
|
||||||
|
@ -41,17 +49,28 @@ ColumnLayout {
|
||||||
profileStore.resetSocialLinks()
|
profileStore.resetSocialLinks()
|
||||||
descriptionPanel.reevaluateSocialLinkInputs()
|
descriptionPanel.reevaluateSocialLinkInputs()
|
||||||
biometricsSwitch.checked = Qt.binding(() => { return biometricsSwitch.currentStoredValue })
|
biometricsSwitch.checked = Qt.binding(() => { return biometricsSwitch.currentStoredValue })
|
||||||
|
profileHeader.icon = Qt.binding(() => { return profileStore.profileLargeImage })
|
||||||
}
|
}
|
||||||
|
|
||||||
function save() {
|
function save() {
|
||||||
profileStore.setDisplayName(descriptionPanel.displayName.text)
|
profileStore.setDisplayName(descriptionPanel.displayName.text)
|
||||||
profileStore.setBio(descriptionPanel.bio.text)
|
profileStore.setBio(descriptionPanel.bio.text)
|
||||||
profileStore.saveSocialLinks()
|
profileStore.saveSocialLinks()
|
||||||
|
if (profileHeader.icon === "") {
|
||||||
|
root.profileStore.removeImage()
|
||||||
|
} else {
|
||||||
|
profileStore.uploadImage(profileHeader.icon,
|
||||||
|
profileHeader.cropRect.x.toFixed(),
|
||||||
|
profileHeader.cropRect.y.toFixed(),
|
||||||
|
(profileHeader.cropRect.x + profileHeader.cropRect.width).toFixed(),
|
||||||
|
(profileHeader.cropRect.y + profileHeader.cropRect.height).toFixed());
|
||||||
|
}
|
||||||
if (biometricsSwitch.checked)
|
if (biometricsSwitch.checked)
|
||||||
Global.openPopup(storePasswordModal)
|
Global.openPopup(storePasswordModal)
|
||||||
else
|
else
|
||||||
localAccountSettings.storeToKeychainValue = Constants.keychain.storedValue.never;
|
localAccountSettings.storeToKeychainValue = Constants.keychain.storedValue.never;
|
||||||
|
|
||||||
|
reset()
|
||||||
}
|
}
|
||||||
|
|
||||||
function offerToStorePassword(password, runStoreToKeyChainPopup)
|
function offerToStorePassword(password, runStoreToKeyChainPopup)
|
||||||
|
@ -64,6 +83,7 @@ ColumnLayout {
|
||||||
}
|
}
|
||||||
|
|
||||||
ProfileHeader {
|
ProfileHeader {
|
||||||
|
id: profileHeader
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.leftMargin: Style.current.padding
|
Layout.leftMargin: Style.current.padding
|
||||||
Layout.rightMargin: Style.current.padding
|
Layout.rightMargin: Style.current.padding
|
||||||
|
|
|
@ -145,7 +145,7 @@ Item {
|
||||||
}
|
}
|
||||||
|
|
||||||
onOpenChangeProfilePicPopup: {
|
onOpenChangeProfilePicPopup: {
|
||||||
var popup = changeProfilePicComponent.createObject(appMain);
|
var popup = changeProfilePicComponent.createObject(appMain, {callback: cb});
|
||||||
popup.chooseImageToCrop();
|
popup.chooseImageToCrop();
|
||||||
}
|
}
|
||||||
onOpenBackUpSeedPopup: Global.openPopup(backupSeedModalComponent)
|
onOpenBackUpSeedPopup: Global.openPopup(backupSeedModalComponent)
|
||||||
|
@ -236,6 +236,15 @@ Item {
|
||||||
title: qsTr("Profile Picture")
|
title: qsTr("Profile Picture")
|
||||||
acceptButtonText: qsTr("Make this my Profile Pic")
|
acceptButtonText: qsTr("Make this my Profile Pic")
|
||||||
onImageCropped: {
|
onImageCropped: {
|
||||||
|
if (callback) {
|
||||||
|
callback(image,
|
||||||
|
cropRect.x.toFixed(),
|
||||||
|
cropRect.y.toFixed(),
|
||||||
|
(cropRect.x + cropRect.width).toFixed(),
|
||||||
|
(cropRect.y + cropRect.height).toFixed())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
appMain.rootStore.profileSectionStore.profileStore.uploadImage(image,
|
appMain.rootStore.profileSectionStore.profileStore.uploadImage(image,
|
||||||
cropRect.x.toFixed(),
|
cropRect.x.toFixed(),
|
||||||
cropRect.y.toFixed(),
|
cropRect.y.toFixed(),
|
||||||
|
|
|
@ -27,6 +27,7 @@ Item {
|
||||||
property bool isContact: false
|
property bool isContact: false
|
||||||
property bool isCurrentUser
|
property bool isCurrentUser
|
||||||
property bool userIsEnsVerified
|
property bool userIsEnsVerified
|
||||||
|
property rect cropRect: undefined
|
||||||
|
|
||||||
property int imageSize: ProfileHeader.ImageSize.Compact
|
property int imageSize: ProfileHeader.ImageSize.Compact
|
||||||
property bool displayNameVisible: true
|
property bool displayNameVisible: true
|
||||||
|
@ -82,9 +83,11 @@ Item {
|
||||||
imageWidth: d.getSize(36, 64, 160)
|
imageWidth: d.getSize(36, 64, 160)
|
||||||
imageHeight: imageWidth
|
imageHeight: imageWidth
|
||||||
showRing: !root.userIsEnsVerified
|
showRing: !root.userIsEnsVerified
|
||||||
|
cropRect: root.cropRect
|
||||||
}
|
}
|
||||||
|
|
||||||
StatusRoundButton {
|
StatusRoundButton {
|
||||||
|
id: editButton
|
||||||
visible: root.editImageButtonVisible
|
visible: root.editImageButtonVisible
|
||||||
anchors.bottom: userImage.bottom
|
anchors.bottom: userImage.bottom
|
||||||
anchors.right: userImage.right
|
anchors.right: userImage.right
|
||||||
|
@ -102,7 +105,12 @@ Item {
|
||||||
if (!!root.store.profileLargeImage)
|
if (!!root.store.profileLargeImage)
|
||||||
imageEditMenu.popup(this, mouse.x, mouse.y);
|
imageEditMenu.popup(this, mouse.x, mouse.y);
|
||||||
else
|
else
|
||||||
Global.openChangeProfilePicPopup();
|
Global.openChangeProfilePicPopup(tempIcon);
|
||||||
|
}
|
||||||
|
|
||||||
|
function tempIcon(image, aX, aY, bX, bY) {
|
||||||
|
root.icon = image
|
||||||
|
root.cropRect = Qt.rect(aX, aY, bX - aX, bY - aY)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -211,14 +219,14 @@ Item {
|
||||||
text: qsTr("Upload a file")
|
text: qsTr("Upload a file")
|
||||||
icon.name: "download"
|
icon.name: "download"
|
||||||
iconRotation: 180
|
iconRotation: 180
|
||||||
onTriggered: Global.openChangeProfilePicPopup()
|
onTriggered: Global.openChangeProfilePicPopup(editButton.tempIcon)
|
||||||
}
|
}
|
||||||
|
|
||||||
StatusMenuItem {
|
StatusMenuItem {
|
||||||
text: qsTr("Remove image")
|
text: qsTr("Remove image")
|
||||||
type: StatusMenuItem.Danger
|
type: StatusMenuItem.Danger
|
||||||
icon.name: "delete"
|
icon.name: "delete"
|
||||||
onTriggered: root.store.removeImage()
|
onTriggered: root.icon = ""
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,8 @@ Loader {
|
||||||
property bool interactive: true
|
property bool interactive: true
|
||||||
property bool disabled: false
|
property bool disabled: false
|
||||||
|
|
||||||
|
property rect cropRect: undefined
|
||||||
|
|
||||||
property int colorId: Utils.colorIdForPubkey(pubkey)
|
property int colorId: Utils.colorIdForPubkey(pubkey)
|
||||||
property var colorHash: Utils.getColorHashAsJson(pubkey)
|
property var colorHash: Utils.getColorHashAsJson(pubkey)
|
||||||
|
|
||||||
|
@ -34,6 +36,7 @@ Loader {
|
||||||
name: root.image
|
name: root.image
|
||||||
charactersLen: 2
|
charactersLen: 2
|
||||||
isImage: true
|
isImage: true
|
||||||
|
cropRect: root.cropRect
|
||||||
}
|
}
|
||||||
ringSettings {
|
ringSettings {
|
||||||
ringSpecModel: root.showRing ? root.colorHash : undefined
|
ringSpecModel: root.showRing ? root.colorHash : undefined
|
||||||
|
|
|
@ -14,6 +14,7 @@ Item {
|
||||||
id: root
|
id: root
|
||||||
objectName: "imageCropWorkflow"
|
objectName: "imageCropWorkflow"
|
||||||
|
|
||||||
|
property var callback: null
|
||||||
property alias aspectRatio: imageCropper.aspectRatio
|
property alias aspectRatio: imageCropper.aspectRatio
|
||||||
property alias windowStyle: imageCropper.windowStyle
|
property alias windowStyle: imageCropper.windowStyle
|
||||||
/*required*/ property string imageFileDialogTitle: ""
|
/*required*/ property string imageFileDialogTitle: ""
|
||||||
|
|
|
@ -27,6 +27,9 @@ Pane {
|
||||||
property var profileStore
|
property var profileStore
|
||||||
property var contactsStore
|
property var contactsStore
|
||||||
|
|
||||||
|
property QtObject dirtyValues: null
|
||||||
|
property bool dirty: false
|
||||||
|
|
||||||
signal closeRequested()
|
signal closeRequested()
|
||||||
|
|
||||||
padding: 0
|
padding: 0
|
||||||
|
@ -249,9 +252,11 @@ Pane {
|
||||||
UserImage {
|
UserImage {
|
||||||
Layout.alignment: Qt.AlignTop
|
Layout.alignment: Qt.AlignTop
|
||||||
objectName: "ProfileDialog_userImage"
|
objectName: "ProfileDialog_userImage"
|
||||||
name: d.userDisplayName
|
name: root.dirty ? root.dirtyValues.displayName
|
||||||
|
: d.userDisplayName
|
||||||
pubkey: root.publicKey
|
pubkey: root.publicKey
|
||||||
image: d.contactDetails.largeImage
|
image: root.dirty ? root.dirtyValues.profileLargeImage
|
||||||
|
: d.contactDetails.largeImage
|
||||||
interactive: false
|
interactive: false
|
||||||
imageWidth: 80
|
imageWidth: 80
|
||||||
imageHeight: imageWidth
|
imageHeight: imageWidth
|
||||||
|
@ -275,7 +280,8 @@ Pane {
|
||||||
font.bold: true
|
font.bold: true
|
||||||
font.pixelSize: 22
|
font.pixelSize: 22
|
||||||
elide: Text.ElideRight
|
elide: Text.ElideRight
|
||||||
text: d.userDisplayName
|
text: root.dirty ? root.dirtyValues.displayName
|
||||||
|
: d.userDisplayName
|
||||||
}
|
}
|
||||||
StatusContactVerificationIcons {
|
StatusContactVerificationIcons {
|
||||||
id: verificationIcons
|
id: verificationIcons
|
||||||
|
@ -543,8 +549,10 @@ Pane {
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.leftMargin: column.anchors.leftMargin + Style.current.halfPadding
|
Layout.leftMargin: column.anchors.leftMargin + Style.current.halfPadding
|
||||||
Layout.rightMargin: column.anchors.rightMargin + Style.current.halfPadding
|
Layout.rightMargin: column.anchors.rightMargin + Style.current.halfPadding
|
||||||
bio: d.contactDetails.bio
|
bio: root.dirty ? root.dirtyValues.bio
|
||||||
userSocialLinksJson: d.contactDetails.socialLinks
|
: d.contactDetails.bio
|
||||||
|
userSocialLinksJson: root.dirty ? root.profileStore.temporarySocialLinksJson
|
||||||
|
: d.contactDetails.socialLinks
|
||||||
}
|
}
|
||||||
|
|
||||||
GridLayout {
|
GridLayout {
|
||||||
|
|
|
@ -44,7 +44,7 @@ QtObject {
|
||||||
signal unblockContactRequested(string publicKey, string contactName)
|
signal unblockContactRequested(string publicKey, string contactName)
|
||||||
signal contactUnblocked(string publicKey)
|
signal contactUnblocked(string publicKey)
|
||||||
|
|
||||||
signal openChangeProfilePicPopup()
|
signal openChangeProfilePicPopup(var cb)
|
||||||
signal displayToastMessage(string title, string subTitle, string icon, bool loading, int ephNotifType, string url)
|
signal displayToastMessage(string title, string subTitle, string icon, bool loading, int ephNotifType, string url)
|
||||||
signal openEditDisplayNamePopup()
|
signal openEditDisplayNamePopup()
|
||||||
signal openActivityCenterPopupRequested
|
signal openActivityCenterPopupRequested
|
||||||
|
|
Loading…
Reference in New Issue