From e436d6937d257c2d2ef48732bb431ab52548ab3f Mon Sep 17 00:00:00 2001 From: Igor Sirotin Date: Wed, 7 Dec 2022 00:12:09 +0300 Subject: [PATCH] fix: Removing and releasing ENS names --- src/app/boot/app_controller.nim | 1 - src/app/global/user_profile.nim | 22 ---- .../ens_usernames/controller.nim | 3 + .../ens_usernames/io_interface.nim | 3 + .../profile_section/ens_usernames/module.nim | 12 +- .../profile_section/ens_usernames/view.nim | 3 + src/app_service/service/settings/service.nim | 13 +++ .../Profile/stores/EnsUsernamesStore.qml | 6 + .../Profile/stores/ProfileStore.qml | 2 +- .../Profile/views/EnsDetailsView.qml | 60 +++++++--- .../AppLayouts/Profile/views/EnsListView.qml | 109 +++++------------- 11 files changed, 111 insertions(+), 123 deletions(-) diff --git a/src/app/boot/app_controller.nim b/src/app/boot/app_controller.nim index 83ae74361a..5507b96cbe 100644 --- a/src/app/boot/app_controller.nim +++ b/src/app/boot/app_controller.nim @@ -400,7 +400,6 @@ proc buildAndRegisterUserProfile(self: AppController) = singletonInstance.userProfile.setDisplayName(displayName) singletonInstance.userProfile.setPreferredName(preferredName) singletonInstance.userProfile.setEnsName(firstEnsName) - singletonInstance.userProfile.setFirstEnsName(firstEnsName) singletonInstance.userProfile.setThumbnailImage(thumbnail) singletonInstance.userProfile.setLargeImage(large) singletonInstance.userProfile.setCurrentUserStatus(currentUserStatus.statusType.int) diff --git a/src/app/global/user_profile.nim b/src/app/global/user_profile.nim index 8b025f3a16..c78a35e6db 100644 --- a/src/app/global/user_profile.nim +++ b/src/app/global/user_profile.nim @@ -13,7 +13,6 @@ QtObject: # fields which may change during runtime ensName: string displayName: string - firstEnsName: string preferredName: string thumbnailImage: string largeImage: string @@ -82,25 +81,6 @@ QtObject: read = getEnsName notify = nameChanged - # this is not a slot - proc setFirstEnsName*(self: UserProfile, name: string) = - if(self.firstEnsName == name): - return - self.firstEnsName = name - self.nameChanged() - - proc getFirstEnsName*(self: UserProfile): string {.slot.} = - self.firstEnsName - QtProperty[string] firstEnsName: - read = getFirstEnsName - notify = nameChanged - - proc getPrettyFirstEnsName*(self: UserProfile): string {.slot.} = - self.firstEnsName - QtProperty[string] prettyFirstEnsName: - read = getPrettyFirstEnsName - notify = nameChanged - # this is not a slot proc setPreferredName*(self: UserProfile, name: string) = @@ -137,8 +117,6 @@ QtObject: proc getName*(self: UserProfile): string {.slot.} = if(self.preferredName.len > 0): return self.getPrettyPreferredName() - elif(self.firstEnsName.len > 0): - return self.getPrettyFirstEnsName() elif(self.ensName.len > 0): return self.ensName elif(self.displayName.len > 0): diff --git a/src/app/modules/main/profile_section/ens_usernames/controller.nim b/src/app/modules/main/profile_section/ens_usernames/controller.nim index 187996045e..35d62c3b7b 100644 --- a/src/app/modules/main/profile_section/ens_usernames/controller.nim +++ b/src/app/modules/main/profile_section/ens_usernames/controller.nim @@ -88,6 +88,9 @@ proc getSigningPhrase*(self: Controller): string = proc saveNewEnsUsername*(self: Controller, ensUsername: string): bool = return self.settingsService.saveNewEnsUsername(ensUsername) +proc removeEnsUsername*(self: Controller, ensUsername: string): bool = + return self.settingsService.removeEnsUsername(ensUsername) + proc getPreferredEnsUsername*(self: Controller): string = return self.settingsService.getPreferredName() diff --git a/src/app/modules/main/profile_section/ens_usernames/io_interface.nim b/src/app/modules/main/profile_section/ens_usernames/io_interface.nim index f126c1c8d6..fba4e7a381 100644 --- a/src/app/modules/main/profile_section/ens_usernames/io_interface.nim +++ b/src/app/modules/main/profile_section/ens_usernames/io_interface.nim @@ -49,6 +49,9 @@ method authenticateAndSetPubKey*(self: AccessInterface, ensUsername: string, add maxPriorityFeePerGas: string, maxFeePerGas: string, eip1559Enabled: bool) {.base.} = raise newException(ValueError, "No implementation available") +method removeEnsUsername*(self: AccessInterface, ensUsername: string): bool {.base.} = + raise newException(ValueError, "No implementation available") + method releaseEnsEstimate*(self: AccessInterface, ensUsername: string, address: string): int {.base.} = raise newException(ValueError, "No implementation available") diff --git a/src/app/modules/main/profile_section/ens_usernames/module.nim b/src/app/modules/main/profile_section/ens_usernames/module.nim index 3d3edf902f..1cf456def4 100644 --- a/src/app/modules/main/profile_section/ens_usernames/module.nim +++ b/src/app/modules/main/profile_section/ens_usernames/module.nim @@ -177,6 +177,15 @@ method authenticateAndReleaseEns*(self: Module, ensUsername: string, address: st else: self.controller.authenticateUser() +method removeEnsUsername*(self: Module, ensUsername: string): bool = + if (not self.controller.removeEnsUsername(ensUsername)): + info "an error occurred removing ens username", methodName="removeEnsUsername" + return false + if (self.controller.getPreferredEnsUsername() == ensUsername): + self.controller.setPreferredName("") + self.view.model().removeItemByEnsUsername(ensUsername) + return true + method releaseEns*(self: Module, password: string) = let response = self.controller.release( self.tmpSendEnsTransactionDetails.ensUsername, @@ -205,8 +214,7 @@ method releaseEns*(self: Module, password: string) = var result: string if(responseObj.getProp("result", result)): - self.controller.setPreferredName("") - self.view.model().removeItemByEnsUsername(self.tmpSendEnsTransactionDetails.ensUsername) + let removed = self.removeEnsUsername(self.tmpSendEnsTransactionDetails.ensUsername) self.view.emitTransactionWasSentSignal(response) proc formatUsername(self: Module, ensUsername: string, isStatus: bool): string = diff --git a/src/app/modules/main/profile_section/ens_usernames/view.nim b/src/app/modules/main/profile_section/ens_usernames/view.nim index f237ed8395..6e58e717ce 100644 --- a/src/app/modules/main/profile_section/ens_usernames/view.nim +++ b/src/app/modules/main/profile_section/ens_usernames/view.nim @@ -91,6 +91,9 @@ QtObject: revertReason: string) = self.transactionCompleted(success, txHash, username, trxType, revertReason) + proc removeEnsUsername*(self: View, ensUsername: string): bool {.slot.} = + return self.delegate.removeEnsUsername(ensUsername) + proc releaseEnsEstimate*(self: View, ensUsername: string, address: string): int {.slot.} = return self.delegate.releaseEnsEstimate(ensUsername, address) diff --git a/src/app_service/service/settings/service.nim b/src/app_service/service/settings/service.nim index 372ce60737..fe697deaf8 100644 --- a/src/app_service/service/settings/service.nim +++ b/src/app_service/service/settings/service.nim @@ -163,6 +163,19 @@ QtObject: return true return false + proc removeEnsUsername*(self: Service, username: string): bool = + var newEnsUsernames = self.settings.ensUsernames + let index = newEnsUsernames.find(username) + if (index < 0): + return false + newEnsUsernames.delete(index) + let newEnsUsernamesAsJson = %* newEnsUsernames + + if(self.saveSetting(KEY_ENS_USERNAMES, newEnsUsernamesAsJson)): + self.settings.ensUsernames = newEnsUsernames + return true + return false + proc getEnsUsernames*(self: Service): seq[string] = return self.settings.ensUsernames diff --git a/ui/app/AppLayouts/Profile/stores/EnsUsernamesStore.qml b/ui/app/AppLayouts/Profile/stores/EnsUsernamesStore.qml index 438d49cb2a..1e671ef751 100644 --- a/ui/app/AppLayouts/Profile/stores/EnsUsernamesStore.qml +++ b/ui/app/AppLayouts/Profile/stores/EnsUsernamesStore.qml @@ -147,5 +147,11 @@ QtObject { return "" return ensUsernamesModule.getChainIdForEns() } + + function removeEnsUsername(ensUsername) { + if(!root.ensUsernamesModule) + return "" + return ensUsernamesModule.removeEnsUsername(ensUsername) + } } diff --git a/ui/app/AppLayouts/Profile/stores/ProfileStore.qml b/ui/app/AppLayouts/Profile/stores/ProfileStore.qml index 3a4ca244ef..fcade8b0fa 100644 --- a/ui/app/AppLayouts/Profile/stores/ProfileStore.qml +++ b/ui/app/AppLayouts/Profile/stores/ProfileStore.qml @@ -10,7 +10,7 @@ QtObject { property string name: userProfile.name // in case of ens returns pretty ens form property string username: userProfile.username property string displayName: userProfile.displayName - property string ensName: userProfile.preferredName || userProfile.firstEnsName || userProfile.ensName + property string ensName: userProfile.preferredName || userProfile.ensName property string profileLargeImage: userProfile.largeImage property string icon: userProfile.icon property bool userDeclinedBackupBanner: localAccountSensitiveSettings.userDeclinedBackupBanner diff --git a/ui/app/AppLayouts/Profile/views/EnsDetailsView.qml b/ui/app/AppLayouts/Profile/views/EnsDetailsView.qml index 00a361bfb0..7c19cd3450 100644 --- a/ui/app/AppLayouts/Profile/views/EnsDetailsView.qml +++ b/ui/app/AppLayouts/Profile/views/EnsDetailsView.qml @@ -18,11 +18,16 @@ Item { property string username: "" property string walletAddress: "-" property string key: "-" - property var expiration: 0 signal backBtnClicked(); signal usernameReleased(username: string); + QtObject { + id: d + + property int expirationTimestamp: 0 + } + StatusBaseText { id: sectionTitle text: username @@ -60,18 +65,21 @@ Item { walletAddressLbl.visible = true; keyLbl.visible = true; releaseBtn.visible = isStatus - releaseBtn.enabled = (Date.now() / 1000) > expirationTime && expirationTime > 0 && - root.ensUsernamesStore.preferredUsername != username - releaseBtn.enabled = true - expiration = new Date(expirationTime * 1000).getTime() + removeButton.visible = true + releaseBtn.enabled = expirationTime > 0 + && (Date.now() / 1000) > expirationTime + && root.ensUsernamesStore.preferredUsername !== username + d.expirationTimestamp = expirationTime * 1000 } onLoading: { loadingImg.active = isLoading - if(!isLoading) return; + if (!isLoading) + return; walletAddressLbl.visible = false; keyLbl.visible = false; releaseBtn.visible = false; - expiration = 0; + removeButton.visible = false; + d.expirationTimestamp = 0; } } @@ -171,31 +179,49 @@ Item { } } - StatusQControls.StatusButton { - id: releaseBtn - visible: false - enabled: false + RowLayout { + id: actionsLayout + anchors.top: keyLbl.bottom anchors.topMargin: 24 anchors.left: parent.left anchors.leftMargin: 24 - text: qsTr("Release username") - onClicked: { - Global.openPopup(transactionDialogComponent) + + StatusQControls.StatusButton { + id: removeButton + visible: false + type: StatusQControls.StatusBaseButton.Type.Danger + text: qsTr("Remove username") + onClicked: { + root.ensUsernamesStore.removeEnsUsername(root.username) + root.backBtnClicked() + } + } + + StatusQControls.StatusButton { + id: releaseBtn + visible: false + enabled: false + text: qsTr("Release username") + onClicked: { + Global.openPopup(transactionDialogComponent) + } } } Text { visible: releaseBtn.visible && !releaseBtn.enabled - anchors.top: releaseBtn.bottom + anchors.top: actionsLayout.bottom anchors.topMargin: 2 anchors.left: parent.left anchors.leftMargin: 24 - text: qsTr("Username locked. You won't be able to release it until %1").arg(Utils.formatShortDateStr(new Date(expiration).toDateString())) + text: { + const formattedDate = Utils.formatShortDate(d.expirationTimestamp, localAccountSensitiveSettings.isDDMMYYDateFormat) + return qsTr("Username locked. You won't be able to release it until %1").arg(formattedDate) + } color: Style.current.darkGrey } - StatusQControls.StatusButton { anchors.bottom: parent.bottom anchors.bottomMargin: Style.current.padding diff --git a/ui/app/AppLayouts/Profile/views/EnsListView.qml b/ui/app/AppLayouts/Profile/views/EnsListView.qml index b29b84ddaf..990ebe7689 100644 --- a/ui/app/AppLayouts/Profile/views/EnsListView.qml +++ b/ui/app/AppLayouts/Profile/views/EnsListView.qml @@ -55,83 +55,6 @@ Item { width: profileContentWidth anchors.horizontalCenter: parent.horizontalCenter - Component { - id: statusENS - Item { - Text { - id: usernameTxt - text: username.substr(0, username.indexOf(".")) + " " + (isPending ? qsTr("(pending)") : "") - color: Style.current.textColor - } - - Text { - - anchors.top: usernameTxt.bottom - anchors.topMargin: 2 - text: username.substr(username.indexOf(".")) - color: Theme.palette.baseColor1 - } - } - } - - Component { - id: normalENS - Item { - Text { - id: usernameTxt - text: username + " " + (isPending ? qsTr("(pending)") : "") - font.pixelSize: 16 - color: Theme.palette.directColor1 - anchors.top: parent.top - anchors.topMargin: 5 - } - } - } - - Component { - id: ensDelegate - Item { - height: 45 - anchors.left: parent.left - anchors.right: parent.right - - MouseArea { - enabled: !model.isPending - anchors.fill: parent - cursorShape:enabled ? Qt.PointingHandCursor : Qt.ArrowCursor - onClicked: selectEns(model.ensUsername) - } - - Rectangle { - id: circle - width: 35 - height: 35 - radius: 35 - color: Theme.palette.primaryColor1 - - StatusBaseText { - text: "@" - opacity: 0.7 - font.weight: Font.Bold - font.pixelSize: 16 - color: Theme.palette.indirectColor1 - anchors.centerIn: parent - verticalAlignment: Text.AlignVCenter - anchors.verticalCenter: parent.verticalCenter - } - } - - Loader { - sourceComponent: model.ensUsername.endsWith(".stateofus.eth") ? statusENS : normalENS - property string username: model.ensUsername - property bool isPending: model.isPending - active: true - anchors.left: circle.right - anchors.leftMargin: Style.current.smallPadding - } - } - } - StatusBaseText { id: sectionTitle text: qsTr("ENS usernames") @@ -201,9 +124,36 @@ Item { anchors.fill: parent model: root.ensUsernamesStore.ensUsernamesModel spacing: 10 - delegate: ensDelegate + delegate: StatusListItem { + readonly property int indexOfDomainStart: model.ensUsername.indexOf(".") + + width: ListView.view.width + title: model.ensUsername.substr(0, indexOfDomainStart) + subTitle: model.ensUsername.substr(indexOfDomainStart) + titleAsideText: model.isPending ? qsTr("(pending)") : "" + + statusListItemTitle.font.pixelSize: 17 + statusListItemTitle.font.bold: true + + asset.isImage: false + asset.isLetterIdenticon: true + asset.bgColor: Theme.palette.primaryColor1 + asset.width: 40 + asset.height: 40 + + components: [ + StatusIcon { + icon: "chevron-down" + rotation: 270 + color: Theme.palette.baseColor1 + } + ] + + onClicked: { + root.selectEns(model.ensUsername) + } + } - ScrollBar.vertical: ScrollBar { policy: ScrollBar.AsNeeded } } } @@ -306,4 +256,3 @@ Item { } } } -