diff --git a/src/app/modules/main/chat_section/controller.nim b/src/app/modules/main/chat_section/controller.nim index cc0adf49f58..3e5d84edf5f 100644 --- a/src/app/modules/main/chat_section/controller.nim +++ b/src/app/modules/main/chat_section/controller.nim @@ -258,6 +258,11 @@ proc init*(self: Controller) = if (args.communityId == self.sectionId): self.delegate.onCategoryUnmuted(args.categoryId) + self.events.on(SIGNAL_COMMUNITY_TOKEN_PERMISSION_CREATION_OR_UPDATE_SUCCEEDED) do(e: Args): + let args = CommunityTokenPermissionArgs(e) + if (args.communityId == self.sectionId): + self.delegate.onCommunityTokenPermissionCreationOrUpdateSucceeded(args.communityId) + self.events.on(SIGNAL_COMMUNITY_TOKEN_PERMISSION_CREATION_FAILED) do(e: Args): let args = CommunityTokenPermissionArgs(e) if (args.communityId == self.sectionId): diff --git a/src/app/modules/main/chat_section/io_interface.nim b/src/app/modules/main/chat_section/io_interface.nim index f0fecb881b4..93d02c6f8d8 100644 --- a/src/app/modules/main/chat_section/io_interface.nim +++ b/src/app/modules/main/chat_section/io_interface.nim @@ -349,6 +349,9 @@ method setCommunityMetrics*(self: AccessInterface, metrics: CommunityMetricsDto) method onCommunityTokenPermissionCreated*(self: AccessInterface, communityId: string, tokenPermission: CommunityTokenPermissionDto) {.base.} = raise newException(ValueError, "No implementation available") +method onCommunityTokenPermissionCreationOrUpdateSucceeded*(self: AccessInterface, communityId: string) {.base.} = + raise newException(ValueError, "No implementation available") + method onCommunityTokenPermissionCreationFailed*(self: AccessInterface, communityId: string) {.base.} = raise newException(ValueError, "No implementation available") diff --git a/src/app/modules/main/chat_section/module.nim b/src/app/modules/main/chat_section/module.nim index b25771459de..4faf9a294bc 100644 --- a/src/app/modules/main/chat_section/module.nim +++ b/src/app/modules/main/chat_section/module.nim @@ -1057,11 +1057,19 @@ method onCommunityTokenPermissionUpdated*(self: Module, communityId: string, tok if self.showPermissionUpdateNotification(community, tokenPermission): singletonInstance.globalEvents.showCommunityTokenPermissionUpdatedNotification(communityId, "Community permission updated", "A token permission has been updated") +method onCommunityTokenPermissionCreationOrUpdateSucceeded*(self: Module, communityId: string) = + self.view.setPermissionSaveInProgress(false) + self.view.permissionSavedSuccessfully() + method onCommunityTokenPermissionCreationFailed*(self: Module, communityId: string) = singletonInstance.globalEvents.showCommunityTokenPermissionCreationFailedNotification(communityId, "Failed to create community permission", "Something went wrong") + self.view.setPermissionSaveInProgress(false) + self.view.setErrorSavingPermission("Failed to create permission. Please try again.") method onCommunityTokenPermissionUpdateFailed*(self: Module, communityId: string) = singletonInstance.globalEvents.showCommunityTokenPermissionUpdateFailedNotification(communityId, "Failed to update community permission", "Something went wrong") + self.view.setPermissionSaveInProgress(false) + self.view.setErrorSavingPermission("Failed to update permission. Please try again.") method onCommunityTokenPermissionDeletionFailed*(self: Module, communityId: string) = singletonInstance.globalEvents.showCommunityTokenPermissionDeletionFailedNotification(communityId, "Failed to delete community permission", "Something went wrong") diff --git a/src/app/modules/main/chat_section/view.nim b/src/app/modules/main/chat_section/view.nim index bcc4a49ae9a..6099861e2bd 100644 --- a/src/app/modules/main/chat_section/view.nim +++ b/src/app/modules/main/chat_section/view.nim @@ -35,7 +35,11 @@ QtObject: memberMessagesModelVariant: QVariant requestToJoinState: RequestToJoinState communityMemberReevaluationStatus: int + permissionSaveInProgress: bool + errorSavingPermission: string + proc setPermissionSaveInProgress*(self: View, value: bool) + proc setErrorSavingPermission*(self: View, value: string) proc delete*(self: View) proc newView*(delegate: io_interface.AccessInterface): View = @@ -62,6 +66,8 @@ QtObject: result.memberMessagesModelVariant = newQVariant(result.memberMessagesModel) result.requestToJoinState = RequestToJoinState.None result.communityMemberReevaluationStatus = 0 + result.permissionSaveInProgress = false + result.errorSavingPermission = "" proc load*(self: View) = self.delegate.viewDidLoad() @@ -344,7 +350,8 @@ QtObject: read = getTokenPermissionsModel proc createOrEditCommunityTokenPermission*(self: View, permissionId: string, permissionType: int, tokenCriteriaJson: string, channelIDs: string, isPrivate: bool) {.slot.} = - + self.setPermissionSaveInProgress(true) + self.setErrorSavingPermission("") let chatIDs = channelIDs.split(',') self.delegate.createOrEditCommunityTokenPermission(permissionId, permissionType, tokenCriteriaJson, chatIDs, isPrivate) @@ -519,6 +526,36 @@ QtObject: proc markAllReadInCommunity*(self: View) {.slot.} = self.delegate.markAllReadInCommunity() + proc permissionSavedSuccessfully*(self: View) {.signal.} + + proc permissionSaveInProgressChanged*(self: View) {.signal.} + + proc getPermissionSaveInProgress*(self: View): bool {.slot.} = + return self.permissionSaveInProgress + + proc setPermissionSaveInProgress*(self: View, value: bool) = + if self.permissionSaveInProgress == value: + return + self.permissionSaveInProgress = value + self.permissionSaveInProgressChanged() + + QtProperty[bool] permissionSaveInProgress: + read = getPermissionSaveInProgress + notify = permissionSaveInProgressChanged + + proc errorSavingPermissionChanged*(self: View) {.signal.} + + proc setErrorSavingPermission*(self: View, value: string) = + if self.errorSavingPermission == value: + return + self.errorSavingPermission = value + self.errorSavingPermissionChanged() + + proc getErrorSavingPermission*(self: View): string {.slot.} = + return self.errorSavingPermission + QtProperty[string] errorSavingPermission: + read = getErrorSavingPermission + notify = errorSavingPermissionChanged + proc delete*(self: View) = self.QObject.delete - diff --git a/src/app_service/service/community/service.nim b/src/app_service/service/community/service.nim index e907af2c7cf..20c08a08e36 100644 --- a/src/app_service/service/community/service.nim +++ b/src/app_service/service/community/service.nim @@ -231,6 +231,7 @@ const SIGNAL_DISCORD_CHANNEL_IMPORT_CANCELED* = "discordChannelImportCanceled" const SIGNAL_MEMBER_REEVALUATION_STATUS* = "communityMemberReevaluationStatus" const SIGNAL_COMMUNITY_TOKEN_PERMISSION_CREATED* = "communityTokenPermissionCreated" +const SIGNAL_COMMUNITY_TOKEN_PERMISSION_CREATION_OR_UPDATE_SUCCEEDED* = "communityTokenPermissionCreationOrUpdateSucceeded" const SIGNAL_COMMUNITY_TOKEN_PERMISSION_CREATION_FAILED* = "communityTokenPermissionCreationFailed" const SIGNAL_COMMUNITY_TOKEN_PERMISSION_UPDATED* = "communityTokenPermissionUpdated" const SIGNAL_COMMUNITY_TOKEN_PERMISSION_UPDATE_FAILED* = "communityTokenPermissionUpdateFailed" @@ -2213,8 +2214,8 @@ QtObject: error "Error canceling discord channel import", msg = e.msg proc createOrEditCommunityTokenPermission*(self: Service, communityId: string, tokenPermission: CommunityTokenPermissionDto) = + let editing = tokenPermission.id != "" try: - let editing = tokenPermission.id != "" var response: RpcResponse[JsonNode] if editing: response = status_go.editCommunityTokenPermission(communityId, tokenPermission.id, int(tokenPermission.`type`), Json.encode(tokenPermission.tokenCriteria), tokenPermission.chatIDs, tokenPermission.isPrivate) @@ -2222,15 +2223,18 @@ QtObject: response = status_go.createCommunityTokenPermission(communityId, int(tokenPermission.`type`), Json.encode(tokenPermission.tokenCriteria), tokenPermission.chatIDs, tokenPermission.isPrivate) if response.result != nil and response.result.kind != JNull: + self.events.emit(SIGNAL_COMMUNITY_TOKEN_PERMISSION_CREATION_OR_UPDATE_SUCCEEDED, CommunityTokenPermissionArgs(communityId: communityId, tokenPermission: tokenPermission)) return + raise newException(RpcException, "No result returned from create/edit community token permission") + except Exception as e: + error "Error creating/editing community token permission", msg = e.msg + var signal = SIGNAL_COMMUNITY_TOKEN_PERMISSION_CREATION_FAILED if editing: signal = SIGNAL_COMMUNITY_TOKEN_PERMISSION_UPDATE_FAILED self.events.emit(signal, CommunityTokenPermissionArgs(communityId: communityId, tokenPermission: tokenPermission)) - except Exception as e: - error "Error creating/editing community token permission", msg = e.msg proc deleteCommunityTokenPermission*(self: Service, communityId: string, permissionId: string) = try: diff --git a/storybook/pages/EditPermissionViewPage.qml b/storybook/pages/EditPermissionViewPage.qml index c7831c28da6..38ac8595b72 100644 --- a/storybook/pages/EditPermissionViewPage.qml +++ b/storybook/pages/EditPermissionViewPage.qml @@ -28,6 +28,8 @@ SplitView { isPrivate: isPrivateCheckBox.checked permissionDuplicated: isPermissionDuplicatedCheckBox.checked permissionTypeLimitReached: isLimitReachedCheckBox.checked + saveInProgress: isSavingInProgressCheckBox.checked + errorSaving: errorSavingCheckBox.checked ? "Wrong permission data" : "" assetsModel: AssetsModel {} collectiblesModel: CollectiblesModel {} @@ -103,6 +105,18 @@ SplitView { text: "Is limit reached" } + + CheckBox { + id: isSavingInProgressCheckBox + + text: "Is saving in progress" + } + + CheckBox { + id: errorSavingCheckBox + + text: "Error saving" + } } Button { diff --git a/ui/app/AppLayouts/Communities/panels/PermissionsSettingsPanel.qml b/ui/app/AppLayouts/Communities/panels/PermissionsSettingsPanel.qml index b62e5152f30..ee10d901585 100644 --- a/ui/app/AppLayouts/Communities/panels/PermissionsSettingsPanel.qml +++ b/ui/app/AppLayouts/Communities/panels/PermissionsSettingsPanel.qml @@ -27,6 +27,8 @@ StackView { property bool showChannelSelector: true property bool ensCommunityPermissionsEnabled property alias initialPage: initialItem + property bool saveInProgress: false + property string errorSaving: "" // id, name, image, color, owner properties expected required property var communityDetails @@ -43,6 +45,11 @@ StackView { signal removePermissionRequested(string key) signal navigateToMintTokenSettings(bool isAssetType) + function permissionSavedSuccessfully() { + // Go back to the permissions list after successful save + root.pop(StackView.Immediate) + } + function navigateBack() { if (depth === 2 && currentItem.toast.active) currentItem.toast.notifyDirty() @@ -212,6 +219,8 @@ StackView { ensCommunityPermissionsEnabled: root.ensCommunityPermissionsEnabled holdingsRequired: selectedHoldingsModel ? selectedHoldingsModel.count > 0 : false + saveInProgress: root.saveInProgress + errorSaving: root.errorSaving permissionDuplicated: { // dependencies @@ -290,10 +299,6 @@ StackView { root.createPermissionRequested( dirtyValues.permissionType, holdings, channels, dirtyValues.isPrivate) - - if (root.showChannelSelector) { - root.pop(StackView.Immediate) - } } onNavigateToMintTokenSettings: root.navigateToMintTokenSettings(isAssetType) diff --git a/ui/app/AppLayouts/Communities/views/CommunitySettingsView.qml b/ui/app/AppLayouts/Communities/views/CommunitySettingsView.qml index dcea296ce26..1771e0f376d 100644 --- a/ui/app/AppLayouts/Communities/views/CommunitySettingsView.qml +++ b/ui/app/AppLayouts/Communities/views/CommunitySettingsView.qml @@ -350,6 +350,7 @@ StatusSectionLayout { // PERMISISONS Loader { + id: permissionsSettingsPanelLoader active: false readonly property int sectionKey: Constants.CommunitySettingsSections.Permissions readonly property string sectionName: qsTr("Permissions") @@ -372,6 +373,9 @@ StatusSectionLayout { collectiblesModel: rootStore.collectiblesModel channelsModel: rootStore.chatCommunitySectionModule.model + + saveInProgress: rootStore.chatCommunitySectionModule.permissionSaveInProgress + errorSaving: rootStore.chatCommunitySectionModule.errorSavingPermission ensCommunityPermissionsEnabled: root.ensCommunityPermissionsEnabled @@ -797,5 +801,12 @@ StatusSectionLayout { Global.openPopup(noPermissionsPopupCmp, properties) } + + function onPermissionSavedSuccessfully() { + if (!permissionsSettingsPanelLoader.active) { + return + } + permissionsSettingsPanelLoader.item.permissionSavedSuccessfully() + } } } diff --git a/ui/app/AppLayouts/Communities/views/EditPermissionView.qml b/ui/app/AppLayouts/Communities/views/EditPermissionView.qml index 6b42eb495f7..f591f8924a9 100644 --- a/ui/app/AppLayouts/Communities/views/EditPermissionView.qml +++ b/ui/app/AppLayouts/Communities/views/EditPermissionView.qml @@ -56,6 +56,9 @@ StatusScrollView { property bool showChannelSelector: true property bool ensCommunityPermissionsEnabled + property bool saveInProgress: false + property string errorSaving: "" + // roles: type, key, name, amount, imageSource property var selectedHoldingsModel: ListModel {} @@ -185,6 +188,7 @@ StatusScrollView { SequenceColumnLayout { id: sequenceColumnLayout + enabled: !root.saveInProgress width: root.availableWidth title: qsTr("Anyone") @@ -452,9 +456,12 @@ StatusScrollView { directParent: permissionsSelector.addButton - allowCommunityOptions: root.showChannelSelector + // Hide community options if we are in the Channel popup or if "Anyone is allowed to" is enabled + // since making everyone Admin doesn't make sense and anyone can join the community is the default. + allowCommunityOptions: root.showChannelSelector && d.dirtyValues.holdingsRequired initialPermissionType: d.dirtyValues.permissionType - enableAdminPermission: root.communityDetails.owner + // Only owners can assign Admin permissions + enableAdminPermission: root.communityDetails.owner onDone: function(permissionType) { if (d.dirtyValues.permissionType === permissionType) { @@ -654,6 +661,20 @@ StatusScrollView { iconColor: textColor } + StatusWarningBox { + Layout.fillWidth: true + Layout.maximumWidth: root.preferredContentWidth + Layout.rightMargin: root.internalRightPadding + + Layout.topMargin: Theme.padding + visible: root.errorSaving !== "" + icon: "close-circle" + text: qsTr("There was an error saving the permission: %1").arg(root.errorSaving) + borderColor: Theme.palette.baseColor1 + textColor: Theme.palette.dangerColor1 + iconColor: textColor + } + StatusButton { Layout.preferredHeight: 44 Layout.fillWidth: true @@ -665,6 +686,7 @@ StatusScrollView { objectName: "createPermissionButton" text: qsTr("Create permission") enabled: root.saveEnabled + loading: root.saveInProgress onClicked: root.createPermissionClicked() } diff --git a/ui/i18n/qml_base_en.ts b/ui/i18n/qml_base_en.ts index 1822357522b..8308722f72a 100644 --- a/ui/i18n/qml_base_en.ts +++ b/ui/i18n/qml_base_en.ts @@ -6620,6 +6620,10 @@ Remember your password and don't share it with anyone. Create permission + + There was an error saving the permission: %1 + + EditSlippagePanel diff --git a/ui/i18n/qml_base_lokalise_en.ts b/ui/i18n/qml_base_lokalise_en.ts index 188d8d29dc5..38aff2d2824 100644 --- a/ui/i18n/qml_base_lokalise_en.ts +++ b/ui/i18n/qml_base_lokalise_en.ts @@ -8086,6 +8086,11 @@ EditPermissionView Create permission + + There was an error saving the permission: %1 + EditPermissionView + There was an error saving the permission: %1 + EditSlippagePanel diff --git a/ui/i18n/qml_cs.ts b/ui/i18n/qml_cs.ts index 26114309344..2c51656da49 100644 --- a/ui/i18n/qml_cs.ts +++ b/ui/i18n/qml_cs.ts @@ -6657,6 +6657,10 @@ Pamatujte si své heslo a s nikým ho nesdílejte. Create permission Vytvořit oprávnění + + There was an error saving the permission: %1 + + EditSlippagePanel diff --git a/ui/i18n/qml_es.ts b/ui/i18n/qml_es.ts index 5c6d9d4a8bb..4ce964eeb42 100644 --- a/ui/i18n/qml_es.ts +++ b/ui/i18n/qml_es.ts @@ -6633,6 +6633,10 @@ Recuerda tu contraseña y no la compartas con nadie. Create permission Crear permiso + + There was an error saving the permission: %1 + + EditSlippagePanel diff --git a/ui/i18n/qml_ko.ts b/ui/i18n/qml_ko.ts index daaa56496cf..486a9b59786 100644 --- a/ui/i18n/qml_ko.ts +++ b/ui/i18n/qml_ko.ts @@ -6608,6 +6608,10 @@ Remember your password and don't share it with anyone. Create permission 권한 생성 + + There was an error saving the permission: %1 + + EditSlippagePanel diff --git a/vendor/status-go b/vendor/status-go index 63fe9e7227e..4df75ee7488 160000 --- a/vendor/status-go +++ b/vendor/status-go @@ -1 +1 @@ -Subproject commit 63fe9e7227e44394853f3f8b73ea655ef7903340 +Subproject commit 4df75ee7488f3f56ac68bfaa80e62b37cb243dc0