diff --git a/src/app/modules/main/profile_section/profile/io_interface.nim b/src/app/modules/main/profile_section/profile/io_interface.nim index 9598f38117..f91ab347c9 100644 --- a/src/app/modules/main/profile_section/profile/io_interface.nim +++ b/src/app/modules/main/profile_section/profile/io_interface.nim @@ -45,7 +45,7 @@ method onProfileShowcasePreferencesSaveSucceeded*(self: AccessInterface) {.base. method onProfileShowcasePreferencesSaveFailed*(self: AccessInterface) {.base.} = raise newException(ValueError, "No implementation available") -method saveProfileIdentity*(self: AccessInterface, identity: IdentitySaveData) {.base.} = +method saveProfileIdentityChanges*(self: AccessInterface, identity: IdentityChangesSaveData) {.base.} = raise newException(ValueError, "No implementation available") method saveProfileShowcasePreferences*(self: AccessInterface, showcase: ShowcaseSaveData) {.base.} = diff --git a/src/app/modules/main/profile_section/profile/models/profile_save_data.nim b/src/app/modules/main/profile_section/profile/models/profile_save_data.nim index c105dd1436..566045331b 100644 --- a/src/app/modules/main/profile_section/profile/models/profile_save_data.nim +++ b/src/app/modules/main/profile_section/profile/models/profile_save_data.nim @@ -1,4 +1,5 @@ import json, strutils, sequtils +import std/options include app_service/common/json_utils include app_service/common/utils @@ -30,10 +31,12 @@ type IdentityImage* = ref object of RootObj bX*: int bY*: int -type IdentitySaveData* = ref object of RootObj - displayName*: string - bio*: string - image*: IdentityImage +# Struct that contains the profile changes +# if field is none, it means that the user doesn't want to change it +type IdentityChangesSaveData* = ref object of RootObj + displayName*: Option[string] + bio*: Option[string] + image*: Option[IdentityImage] proc toShowcaseSaveEntry*(jsonObj: JsonNode): ShowcaseSaveEntry = result = ShowcaseSaveEntry() @@ -78,11 +81,11 @@ proc toIdentityImage*(jsonObj: JsonNode): IdentityImage = discard jsonObj.getProp("bX", result.bX) discard jsonObj.getProp("bY", result.bY) -proc toIdentitySaveData*(jsonObj: JsonNode): IdentitySaveData = - result = IdentitySaveData() - discard jsonObj.getProp("displayName", result.displayName) - discard jsonObj.getProp("bio", result.bio) +proc toIdentityChangesSaveData*(jsonObj: JsonNode): IdentityChangesSaveData = + result = IdentityChangesSaveData() + if jsonObj{"displayName"} != nil and jsonObj{"displayName"}.kind != JNull: + result.displayName = some(jsonObj{"displayName"}.getStr) + if jsonObj{"bio"} != nil and jsonObj{"bio"}.kind != JNull: + result.bio = some(jsonObj{"bio"}.getStr) if jsonObj{"image"} != nil and jsonObj{"image"}.kind != JNull: - result.image = jsonObj{"image"}.toIdentityImage() - else: - result.image = nil + result.image = some(jsonObj{"image"}.toIdentityImage()) diff --git a/src/app/modules/main/profile_section/profile/module.nim b/src/app/modules/main/profile_section/profile/module.nim index 8f6c12cd36..d327edb5d8 100644 --- a/src/app/modules/main/profile_section/profile/module.nim +++ b/src/app/modules/main/profile_section/profile/module.nim @@ -116,13 +116,24 @@ proc deleteIdentityImage*(self: Module): bool = let keyUid = singletonInstance.userProfile.getKeyUid() self.controller.deleteIdentityImage(keyUid) -method saveProfileIdentity*(self: Module, identity: IdentitySaveData) = - var ok = self.controller.setDisplayName(identity.displayName) - ok = ok and self.controller.setBio(identity.bio) - if identity.image != nil: - ok = ok and self.storeIdentityImage(identity.image) - else: - ok = ok and self.deleteIdentityImage() +method saveProfileIdentityChanges*(self: Module, identityChanges: IdentityChangesSaveData) = + var ok = true + + # Update only the fields that have changed + if identityChanges.displayName.isSome: + ok = self.controller.setDisplayName(identityChanges.displayName.get) + + if identityChanges.bio.isSome: + ok = ok and self.controller.setBio(identityChanges.bio.get) + + if identityChanges.image.isSome: + var image = identityChanges.image.get + # If the image source is empty, delete the image + if image.source.isEmptyOrWhitespace: + ok = ok and self.deleteIdentityImage() + else: + ok = ok and self.storeIdentityImage(image) + if ok: self.view.emitProfileIdentitySaveSucceededSignal() else: diff --git a/src/app/modules/main/profile_section/profile/view.nim b/src/app/modules/main/profile_section/profile/view.nim index 788ec2cd02..59e5883805 100644 --- a/src/app/modules/main/profile_section/profile/view.nim +++ b/src/app/modules/main/profile_section/profile/view.nim @@ -204,10 +204,10 @@ QtObject: QtProperty[QVariant] showcasePreferencesSocialLinksModel: read = getShowcasePreferencesSocialLinksModel - proc saveProfileIdentity(self: View, profileData: string) {.slot.} = - let profileDataObj = profileData.parseJson - let identityInfo = profileDataObj.toIdentitySaveData() - self.delegate.saveProfileIdentity(identityInfo) + proc saveProfileIdentityChanges(self: View, profileDataChanges: string) {.slot.} = + let profileDataChangesObj = profileDataChanges.parseJson + let identityChangesInfo = profileDataChangesObj.toIdentityChangesSaveData() + self.delegate.saveProfileIdentityChanges(identityChangesInfo) proc saveProfileShowcasePreferences(self: View, profileData: string) {.slot.} = let profileDataObj = profileData.parseJson diff --git a/ui/app/AppLayouts/Profile/stores/ProfileStore.qml b/ui/app/AppLayouts/Profile/stores/ProfileStore.qml index bf1beae4d6..92cec5710a 100644 --- a/ui/app/AppLayouts/Profile/stores/ProfileStore.qml +++ b/ui/app/AppLayouts/Profile/stores/ProfileStore.qml @@ -77,21 +77,14 @@ QtObject { globalUtils.copyToClipboard(value) } - // Identity related: - function saveProfileIdentity(displayName, bio, source, aX, aY, bX, bY) { - var identityInfo = { - "displayName": displayName, - "bio": bio, - "image": source ? { - "source": source, - "aX": aX, - "aY": aY, - "bX": bX, - "bY": bY - } : null - } - let json = JSON.stringify(identityInfo) - root.profileModule.saveProfileIdentity(json) + function saveProfileIdentityChanges(displayName, bio, imageInfo) { + const changes = Object.assign({}, + displayName !== undefined && { displayName }, + bio !== undefined && { bio }, + imageInfo !== undefined && { image: imageInfo }) + + const json = JSON.stringify(changes) + root.profileModule.saveProfileIdentityChanges(json) } function getProfileShowcaseEntriesLimit() { diff --git a/ui/app/AppLayouts/Profile/views/MyProfileView.qml b/ui/app/AppLayouts/Profile/views/MyProfileView.qml index 98082f30cb..3fde35ea90 100644 --- a/ui/app/AppLayouts/Profile/views/MyProfileView.qml +++ b/ui/app/AppLayouts/Profile/views/MyProfileView.qml @@ -231,15 +231,23 @@ SettingsContentBase { root.profileStore.saveProfileShowcasePreferences(showcaseModels.buildJSONModelsCurrentState()) } - // Identity info + // Identity info. Update only those fields that have changed if (isIdentityTabDirty) { - root.profileStore.saveProfileIdentity(descriptionPanel.displayName.text, - descriptionPanel.bio.text.trim(), - profileHeader.icon, - profileHeader.cropRect.x, - profileHeader.cropRect.y, - (profileHeader.cropRect.x + profileHeader.cropRect.width), - (profileHeader.cropRect.y + profileHeader.cropRect.height)) + const imageChanged = profileHeader.icon !== profileStore.profileLargeImage + const displayNameChanged = descriptionPanel.displayName.text !== profileStore.displayName + const bioChanged = descriptionPanel.bio.text.trim() !== profileStore.bio.trim() + + root.profileStore.saveProfileIdentityChanges( + displayNameChanged ? descriptionPanel.displayName.text : undefined, + bioChanged ? descriptionPanel.bio.text.trim() : undefined, + imageChanged ? { + source : profileHeader.icon, + aX: profileHeader.cropRect.x, + aY: profileHeader.cropRect.y, + bX: profileHeader.cropRect.x + profileHeader.cropRect.width, + bY: profileHeader.cropRect.y + profileHeader.cropRect.height + } : undefined + ) profileHeader.icon = Qt.binding(() => { return profileStore.profileLargeImage }) } }