feat(Community/FinaliseOwnership): Added finalise flow in the app

- Button from community column.
- Button from community overview.
- Updated storybook pages (settings overview related) according to new components requirements.

Part of #12174
This commit is contained in:
Noelia 2023-09-28 12:09:47 +02:00 committed by Noelia
parent 862d4f3add
commit 15927b0705
15 changed files with 377 additions and 154 deletions

View File

@ -1,6 +1,6 @@
import QtQuick 2.14
import QtQuick.Controls 2.14
import QtQuick.Layouts 1.14
import QtQuick 2.15
import QtQuick.Controls 2.15
import QtQuick.Layouts 1.15
import Storybook 1.0
import Models 1.0
@ -40,7 +40,6 @@ SplitView {
communityName: communityNameText.text
onCancelClicked: logs.logEvent("FinaliseOwnershipDeclinePopup::onCancelClicked")
onDeclineClicked: logs.logEvent("FinaliseOwnershipDeclinePopup::onDeclineClicked")
}
}

View File

@ -1,6 +1,6 @@
import QtQuick 2.14
import QtQuick.Controls 2.14
import QtQuick.Layouts 1.14
import QtQuick 2.15
import QtQuick.Controls 2.15
import QtQuick.Layouts 1.15
import Storybook 1.0
import Models 1.0

View File

@ -6,19 +6,44 @@ import AppLayouts.Communities.panels 1.0
import utils 1.0
import Storybook 1.0
SplitView {
id: root
Item {
id: wrapper
Logs { id: logs }
SplitView {
orientation: Qt.Vertical
SplitView.fillWidth: true
SplitView.fillHeight: true
OverviewSettingsFooter {
id: footer
width: parent.width
anchors.centerIn: parent
isControlNode: controlNodeSwitch.checked
communityName: "Socks"
Item {
id: wrapper
SplitView.fillWidth: true
SplitView.fillHeight: true
OverviewSettingsFooter {
id: footer
width: parent.width
anchors.centerIn: parent
isControlNode: controlNodeSwitch.checked
isPendingOwnershipRequest: pendingOwnershipSwitch.checked
communityName: "Socks"
communityColor: "orange"
onExportControlNodeClicked: logs.logEvent("OverviewSettingsFooter::onExportControlNodeClicked")
onImportControlNodeClicked: logs.logEvent("OverviewSettingsFooter::onImportControlNodeClicked")
onLearnMoreClicked: logs.logEvent("OverviewSettingsFooter::onLearnMoreClicked")
onFinaliseOwnershipTransferClicked: logs.logEvent("OverviewSettingsFooter::onFinaliseOwnershipTransferClicked")
}
}
LogsAndControlsPanel {
id: logsAndControlsPanel
SplitView.minimumHeight: 100
SplitView.preferredHeight: 150
logsView.logText: logs.logText
}
}
@ -32,6 +57,12 @@ SplitView {
text: "Control node on/off"
checked: true
}
Switch {
id: pendingOwnershipSwitch
text: "Is there a pending transfer ownership request?"
checked: true
}
}
}
}

View File

@ -24,15 +24,26 @@ SplitView {
communityShardingEnabled: communityEditor.shardingEnabled
communityShardIndex: communityEditor.shardIndex
isPendingOwnershipRequest: pendingOwnershipSwitch.checked
finaliseOwnershipTransferPopup: undefined
}
Pane {
SplitView.minimumWidth: 300
SplitView.preferredWidth: 300
CommunityInfoEditor {
id: communityEditor
anchors.fill: parent
ColumnLayout {
CommunityInfoEditor{
id: communityEditor
anchors.fill: parent
}
Switch {
id: pendingOwnershipSwitch
text: "Is there a pending transfer ownership request?"
checked: true
}
}
}
}

View File

@ -6,13 +6,17 @@ import utils 1.0
import shared.popups 1.0
import "views"
import AppLayouts.Communities.views 1.0
import "stores"
import AppLayouts.Communities.views 1.0
import AppLayouts.Communities.popups 1.0
import AppLayouts.Communities.helpers 1.0
import AppLayouts.Chat.stores 1.0
import AppLayouts.Wallet.stores 1.0 as WalletStore
import StatusQ.Core.Utils 0.1
StackLayout {
id: root
@ -38,6 +42,11 @@ StackLayout {
signal profileButtonClicked()
signal openAppSearch()
// Community transfer ownership related props/signals:
// TODO: Backend integrations:
property bool isPendingOwnershipRequest: false
signal ownershipDeclined()
onCurrentIndexChanged: {
Global.closeCreateChatView()
}
@ -134,6 +143,9 @@ StackLayout {
collectiblesModel: root.rootStore.collectiblesModel
isInvitationPending: root.rootStore.isCommunityRequestPending(chatView.communityId)
finaliseOwnershipTransferPopup: finaliseOwnershipPopup
isPendingOwnershipRequest: root.isPendingOwnershipRequest
onCommunityInfoButtonClicked: root.currentIndex = 1
onCommunityManageButtonClicked: root.currentIndex = 1
@ -170,6 +182,9 @@ StackLayout {
walletAccountsModel: WalletStore.RootStore.nonWatchAccounts
sendModalPopup: root.sendModalPopup
finaliseOwnershipTransferPopup: finaliseOwnershipPopup
isPendingOwnershipRequest: root.isPendingOwnershipRequest
chatCommunitySectionModule: root.rootStore.chatCommunitySectionModule
community: sectionItemModel
communitySettingsDisabled: root.communitySettingsDisabled
@ -223,6 +238,94 @@ StackLayout {
}
}
// Components related to transfer community ownership flow:
Component {
id: finaliseOwnershipPopup
FinaliseOwnershipPopup {
id: finalisePopup
readonly property var communityData: root.sectionItemModel
readonly property var ownerToken: ModelUtils.getByKey(communityData.communityTokens,
"privilegesLevel",
Constants.TokenPrivilegesLevel.Owner)
communityName: communityData.name
communityLogo: communityData.image
communityColor: communityData.color
tokenSymbol: ownerToken.symbol
tokenChainName: ownerToken.chainName
accounts: WalletStore.RootStore.nonWatchAccounts
feeText: feeSubscriber.feeText
feeErrorText: feeSubscriber.feeErrorText
isFeeLoading: !feeSubscriber.feesResponse
onRejectClicked: Global.openPopup(declineOwnershipPopup)
onFinaliseOwnershipClicked: signPopup.open()
onVisitCommunityClicked: rootStore.setActiveCommunity(communityData.id)
onOpenControlNodeDocClicked: Global.openLink(link)
DeployFeesSubscriber {
id: feeSubscriber
readonly property TransactionFeesBroker feesBroker: TransactionFeesBroker {
communityTokensStore: root.rootStore.communityTokensStore
}
chainId: finalisePopup.ownerToken.chainId
tokenType: finalisePopup.ownerToken.type
isOwnerDeployment: true
accountAddress: finalisePopup.ownerToken.accountAddress
enabled: finalisePopup.visible || signPopup.visible
Component.onCompleted: feesBroker.registerDeployFeesSubscriber(feeSubscriber)
}
SignTransactionsPopup {
id: signPopup
title: qsTr("Sign transaction - update %1 smart contract").arg(finalisePopup.communityData.name)
totalFeeText: finalisePopup.isFeeLoading ? "" : finalisePopup.feeText
errorText: finalisePopup.feeErrorText
accountName: finalisePopup.ownerToken.accountName
model: QtObject {
readonly property string title: finalisePopup.feeLabel
readonly property string feeText: signPopup.totalFeeText
readonly property bool error: finalisePopup.feeErrorText !== ""
}
onSignTransactionClicked: {
root.rootStore.communityTokensStore.updateSmartContract(finalisePopup.communityData.id, finalisePopup.ownerToken)
close()
}
}
Connections {
target: root
onOwnershipDeclined: finalisePopup.close()
}
}
}
Component {
id: declineOwnershipPopup
FinaliseOwnershipDeclinePopup {
readonly property var communityData: root.sectionItemModel
communityName: communityData.name
onDeclineClicked: {
console.warn("TODO: Backend update notification center and display a toast: Ownership Declined!")
root.ownershipDeclined()
}
}
}
// End of components related to transfer community ownership flow.
Connections {
target: root.rootStore
enabled: mainViewLoader.item

View File

@ -74,6 +74,10 @@ StatusSectionLayout {
return false
}
// Community transfer ownership related props:
required property var finaliseOwnershipTransferPopup
required property bool isPendingOwnershipRequest
signal communityInfoButtonClicked()
signal communityManageButtonClicked()
signal profileButtonClicked()
@ -242,6 +246,8 @@ StatusSectionLayout {
communitiesStore: root.communitiesStore
emojiPopup: root.emojiPopup
hasAddedContacts: root.hasAddedContacts
finaliseOwnershipTransferPopup: root.finaliseOwnershipTransferPopup
isPendingOwnershipRequest: root.isPendingOwnershipRequest
onInfoButtonClicked: root.communityInfoButtonClicked()
onManageButtonClicked: root.communityManageButtonClicked()
}

View File

@ -6,11 +6,12 @@ import utils 1.0
/*!
\qmltype SingleFeeSubscriber
\inherits QtObject
\brief Helper object that parses fees response and provides fee text and error text for single fee respnse
\brief Helper object that parses fees response and provides fee text and error text for single fee response
*/
QtObject {
id: root
// Published properties
property var feesResponse

View File

@ -112,6 +112,7 @@ QtObject {
function onDeployFeeUpdated(ethCurrency, fiatCurrency, errorCode, responseId) {
d.feesBroker.response(responseId, { ethCurrency: ethCurrency, fiatCurrency: fiatCurrency, errorCode: errorCode })
}
function onAirdropFeeUpdated(response) {
d.feesBroker.response(response.requestId, response)
}

View File

@ -12,12 +12,18 @@ import utils 1.0
Control {
id: root
property bool isControlNode: true
property bool isControlNode: true
property string communityName: ""
property string communityColor: ""
// Community transfer ownership related props:
required property bool isPendingOwnershipRequest
signal exportControlNodeClicked
signal importControlNodeClicked
signal learnMoreClicked
signal finaliseOwnershipTransferClicked
QtObject {
id: d
@ -31,6 +37,7 @@ Control {
property string secondaryButtonText
property string indicatorBgColor
property string indicatorColor
property string indicatorName
property var primaryButtonAction: root.exportControlNodeClicked
}
@ -45,7 +52,7 @@ Control {
Layout.column: 0
color: d.indicatorBgColor
asset.color: d.indicatorColor
asset.name: "desktop"
asset.name: d.indicatorName
}
ColumnLayout {
@ -103,25 +110,38 @@ Control {
// Behavior
states: [
State {
name: "isPendingOwnershipRequest"
when: root.isPendingOwnershipRequest
PropertyChanges { target: d; indicatorBgColor: Theme.palette.alphaColor(root.communityColor, 0.1) }
PropertyChanges { target: d; indicatorColor: root.communityColor }
PropertyChanges { target: d; paragraphTitle: qsTr("Finalise your ownership of the %1 Community").arg(root.communityName) }
PropertyChanges { target: d; paragraphSubtitle: qsTr("You currently hodl the Owner token for %1. Make your device the control node to finalise ownership.").arg(root.communityName) }
PropertyChanges { target: d; primaryButtonText: qsTr("Finalise %1 ownership").arg(root.communityName) }
PropertyChanges { target: d; primaryButtonAction: root.finaliseOwnershipTransferClicked }
PropertyChanges { target: d; indicatorName: "crown" }
},
State {
name: "isControlNode"
when: root.isControlNode
when: root.isControlNode && !root.isPendingOwnershipRequest
PropertyChanges { target: d; indicatorBgColor: Theme.palette.successColor2 }
PropertyChanges { target: d; indicatorColor: Theme.palette.successColor1 }
PropertyChanges { target: d; paragraphTitle: qsTr("This device is currently the control node for the %1 Community").arg(root.communityName) }
PropertyChanges { target: d; paragraphSubtitle: qsTr("For your Community to function correctly keep this device online with Status running as much as possible.") }
PropertyChanges { target: d; primaryButtonText: qsTr("How to move control node") }
PropertyChanges { target: d; primaryButtonAction: root.exportControlNodeClicked }
PropertyChanges { target: d; indicatorName: "desktop" }
},
State {
name: "isNotControlNode"
when: !root.isControlNode
when: !root.isControlNode && !root.isPendingOwnershipRequest
PropertyChanges { target: d; indicatorBgColor: Theme.palette.primaryColor3 }
PropertyChanges { target: d; indicatorColor: Theme.palette.primaryColor1 }
PropertyChanges { target: d; paragraphTitle: qsTr("Make this device the control node for the %1 Community").arg(root.communityName) }
PropertyChanges { target: d; paragraphSubtitle: qsTr("Ensure this is a device you can keep online with Status running.") }
PropertyChanges { target: d; primaryButtonText: qsTr("Make this device the control node") }
PropertyChanges { target: d; primaryButtonAction: root.importControlNodeClicked }
PropertyChanges { target: d; indicatorName: "desktop" }
}
]
}

View File

@ -52,6 +52,10 @@ StackLayout {
property bool communityShardingEnabled
property int communityShardIndex: -1
// Community transfer ownership related props:
required property var finaliseOwnershipTransferPopup
required property bool isPendingOwnershipRequest
function navigateBack() {
if (editSettingsPanelLoader.item.dirty)
@ -176,13 +180,17 @@ StackLayout {
Component {
id: overviewSettingsFooterComp
OverviewSettingsFooter {
rightPadding: 64
leftPadding: 64
bottomPadding: 64
topPadding: 0
communityName: root.name
communityColor: root.color
isControlNode: root.isControlNode
isPendingOwnershipRequest: root.isPendingOwnershipRequest
onExportControlNodeClicked:{
if(!!root.ownerToken && root.ownerToken.deployState === Constants.ContractTransactionStatus.Completed) {
root.exportControlNodeClicked()
@ -191,6 +199,7 @@ StackLayout {
}
}
onImportControlNodeClicked: root.importControlNodeClicked()
onFinaliseOwnershipTransferClicked: Global.openPopup(root.finaliseOwnershipTransferPopup)
//TODO update once the domain changes
onLearnMoreClicked: Global.openLink(Constants.statusHelpLinkPrefix + "status-communities/about-the-control-node-in-status-communities")
}

View File

@ -20,27 +20,20 @@ StatusDialog {
width: 480 // by design
padding: Style.current.padding
title: qsTr("Are you sure you dont want to be the owner?")
contentItem: StatusBaseText {
wrapMode: Text.WrapAtWordBoundaryOrAnywhere
text: qsTr("If you dont want to be the owner of the %1 Community it is important that you let the previous owner know so they can organise another owner to take over. You will have to send the Owner token back to them or on to the next designated owner.").arg(root.communityName)
lineHeight: 1.2
}
header: StatusDialogHeader {
headline.title: qsTr("Are you sure you dont want to be the owner?")
actions.closeButton.onClicked: root.close()
}
footer: StatusDialogFooter {
spacing: Style.current.padding
rightButtons: ObjectModel {
StatusFlatButton {
text: qsTr("Cancel")
onClicked: {
root.cancelClicked()
close()
}
onClicked: close()
}
StatusButton {

View File

@ -43,7 +43,7 @@ StatusDialog {
QtObject {
id: d
readonly property string controlNodeLink: "https://help.status.im/en/status-communities/about-the-control-node-in-status-communities/"
readonly property string controlNodeLink: Constants.statusHelpLinkPrefix + "status-communities/about-the-control-node-in-status-communities/"
readonly property int init: 0
readonly property int finalise: 1
@ -149,8 +149,6 @@ StatusDialog {
StatusButton {
id: acceptBtn
type: StatusBaseButton.Type.Normal
}
}
leftButtons: ObjectModel {
@ -171,7 +169,7 @@ StatusDialog {
CustomText {
textFormat: Text.RichText
text: qsTr("To finalise your ownership and assume ultimate admin rights for the %1 Community, you need to make your device the Community's <a style=\"color: inherit;\" href=\"%2\">control node</a><a style=\"color: inherit;text-decoration: none\" href=\"%2\">↗</a>. You will also need to sign a small transaction to update the %1 Community smart contract to make you the official signatory for all Community changes.").arg(root.communityName).arg(d.controlNodeLink)
text: qsTr("To finalise your ownership and assume ultimate admin rights for the %1 Community, you need to make your device the Community's <a style=\"color:%3;\" href=\"%2\">control node</a><a style=\"color:%3;text-decoration: none\" href=\"%2\">↗</a>. You will also need to sign a small transaction to update the %1 Community smart contract to make you the official signatory for all Community changes.").arg(root.communityName).arg(d.controlNodeLink).arg(color)
onLinkActivated: root.openControlNodeDocClicked(link)
}
@ -196,6 +194,7 @@ StatusDialog {
radius: 8
border.color: Theme.palette.baseColor2
color: "transparent"
ColumnLayout {
id: boxContent

View File

@ -40,6 +40,10 @@ Item {
property bool hasAddedContacts: false
property var communityData
// Community transfer ownership related props:
required property var finaliseOwnershipTransferPopup
required property bool isPendingOwnershipRequest
readonly property bool isSectionAdmin:
communityData.memberRole === Constants.memberRole.owner ||
communityData.memberRole === Constants.memberRole.admin ||
@ -48,6 +52,13 @@ Item {
signal infoButtonClicked
signal manageButtonClicked
QtObject {
id: d
readonly property bool showJoinButton: !communityData.joined || root.communityData.amIBanned
readonly property bool showFinaliseOwnershipButton: root.isPendingOwnershipRequest
}
ColumnHeaderPanel {
id: communityHeader
@ -64,98 +75,21 @@ Item {
onAdHocChatButtonClicked: root.store.openCloseCreateChatView()
}
StatusButton {
id: joinCommunityButton
property bool invitationPending: root.store.isCommunityRequestPending(communityData.id)
Loader {
id: columnHeaderButton
anchors.top: communityHeader.bottom
anchors.topMargin: Style.current.halfPadding
anchors.bottomMargin: Style.current.halfPadding
anchors.horizontalCenter: parent.horizontalCenter
enabled: !root.communityData.amIBanned
visible: !communityData.joined || root.communityData.amIBanned
text: {
if (root.communityData.amIBanned) return qsTr("You were banned from community")
if (invitationPending) return qsTr("Membership request pending...")
return root.communityData.access === Constants.communityChatOnRequestAccess ?
qsTr("Request to join") : qsTr("Join Community")
}
onClicked: {
Global.openPopup(communityIntroDialog);
}
Connections {
enabled: joinCommunityButton.loading
target: root.store.communitiesModuleInst
function onCommunityAccessRequested(communityId: string) {
if (communityId === communityData.id) {
joinCommunityButton.invitationPending = root.store.isCommunityRequestPending(communityData.id)
joinCommunityButton.loading = false
}
}
function onCommunityAccessFailed(communityId: string) {
if (communityId === communityData.id) {
joinCommunityButton.invitationPending = false
joinCommunityButton.loading = false
Global.displayToastMessage(qsTr("Request to join failed"),
qsTr("Please try again later"),
"",
false,
Constants.ephemeralNotificationType.normal,
"")
}
}
function onUserAuthenticationCanceled() {
joinCommunityButton.invitationPending = false
joinCommunityButton.loading = false
}
}
Component {
id: communityIntroDialog
CommunityIntroDialog {
isInvitationPending: joinCommunityButton.invitationPending
requirementsCheckPending: root.store.requirementsCheckPending
name: communityData.name
introMessage: communityData.introMessage
imageSrc: communityData.image
accessType: communityData.access
loginType: root.store.loginType
walletAccountsModel: WalletStore.RootStore.nonWatchAccounts
permissionsModel: {
root.store.prepareTokenModelForCommunity(communityData.id)
return root.store.permissionsModel
}
assetsModel: root.store.assetsModel
collectiblesModel: root.store.collectiblesModel
onJoined: {
joinCommunityButton.loading = true
root.store.requestToJoinCommunityWithAuthentication(communityData.id, root.store.userProfileInst.name, sharedAddresses, airdropAddress)
}
onCancelMembershipRequest: {
root.store.cancelPendingRequest(communityData.id)
joinCommunityButton.invitationPending = root.store.isCommunityRequestPending(communityData.id)
}
onSharedAddressesUpdated: {
root.store.updatePermissionsModel(communityData.id, sharedAddresses)
}
onClosed: destroy()
}
}
sourceComponent: d.showFinaliseOwnershipButton ? finaliseCommunityOwnershipBtn :
d.showJoinButton ? joinCommunityButton : undefined
}
ChatsLoadingPanel {
chatSectionModule: root.communitySectionModule
width: parent.width
anchors.top: joinCommunityButton.visible ? joinCommunityButton.bottom : communityHeader.bottom
anchors.top: columnHeaderButton.sourceComponent !== undefined ? columnHeaderButton.bottom : communityHeader.bottom
anchors.topMargin: active ? Style.current.halfPadding : 0
}
@ -208,7 +142,8 @@ Item {
StatusScrollView {
id: scrollView
anchors.top: joinCommunityButton.visible ? joinCommunityButton.bottom : communityHeader.bottom
anchors.top: columnHeaderButton.sourceComponent !== undefined ? columnHeaderButton.bottom : communityHeader.bottom
anchors.topMargin: Style.current.halfPadding
anchors.bottom: createChatOrCommunity.top
anchors.horizontalCenter: parent.horizontalCenter
@ -246,8 +181,8 @@ Item {
onChatListCategoryReordered: root.store.reorderCommunityCategories(categoryId, to)
onCategoryAddButtonClicked: Global.openPopup(createChannelPopup, {
categoryId: id
})
categoryId: id
})
popupMenu: StatusMenu {
StatusAction {
@ -314,12 +249,12 @@ Item {
text: qsTr("Edit Category")
icon.name: "edit"
onTriggered: {
Global.openPopup(createCategoryPopup, {
isEdit: true,
channels: [],
categoryId: categoryItem.itemId,
categoryName: categoryItem.name
})
Global.openPopup(createCategoryPopup, {
isEdit: true,
channels: [],
categoryId: categoryItem.itemId,
categoryName: categoryItem.name
})
}
}
@ -335,11 +270,11 @@ Item {
type: StatusAction.Type.Danger
onTriggered: {
Global.openPopup(deleteCategoryConfirmationDialogComponent, {
"headerSettings.title": qsTr("Delete '%1' category").arg(categoryItem.name),
confirmationText: qsTr("Are you sure you want to delete '%1' category? Channels inside the category won't be deleted.")
.arg(categoryItem.name),
categoryId: categoryItem.itemId
})
"headerSettings.title": qsTr("Delete '%1' category").arg(categoryItem.name),
confirmationText: qsTr("Are you sure you want to delete '%1' category? Channels inside the category won't be deleted.")
.arg(categoryItem.name),
categoryId: categoryItem.itemId
})
}
}
}
@ -415,14 +350,14 @@ Item {
onEditCommunityChannel: {
communitySectionModule.editCommunityChannel(
chatId,
newName,
newDescription,
newEmoji,
newColor,
newCategory,
channelPosition // TODO change this to the signal once it is modifiable
)
chatId,
newName,
newDescription,
newEmoji,
newColor,
newCategory,
channelPosition // TODO change this to the signal once it is modifiable
)
}
}
}
@ -458,16 +393,16 @@ Item {
width: parent.width
height: item.height
sourceComponent: Component {
ChannelsAndCategoriesBannerPanel {
id: channelsAndCategoriesBanner
communityId: communityData.id
onAddMembersClicked: {
Global.openPopup(createChannelPopup);
}
onAddCategoriesClicked: {
Global.openPopup(createCategoryPopup);
}
ChannelsAndCategoriesBannerPanel {
id: channelsAndCategoriesBanner
communityId: communityData.id
onAddMembersClicked: {
Global.openPopup(createChannelPopup);
}
onAddCategoriesClicked: {
Global.openPopup(createCategoryPopup);
}
}
}
} // Loader
} // Column
@ -510,22 +445,126 @@ Item {
adminPopupMenu.showInviteButton = false
adminPopupMenu.popup()
adminPopupMenu.y = Qt.binding(() => root.height - adminPopupMenu.height
- createChannelOrCategoryBtn.height - 20)
- createChannelOrCategoryBtn.height - 20)
}
}
}
}
}
Component {
id: joinCommunityButton
StatusButton {
property bool invitationPending: root.store.isCommunityRequestPending(communityData.id)
anchors.top: communityHeader.bottom
anchors.topMargin: Style.current.halfPadding
anchors.bottomMargin: Style.current.halfPadding
anchors.horizontalCenter: parent.horizontalCenter
enabled: !root.communityData.amIBanned
text: {
if (root.communityData.amIBanned) return qsTr("You were banned from community")
if (invitationPending) return qsTr("Membership request pending...")
return root.communityData.access === Constants.communityChatOnRequestAccess ?
qsTr("Request to join") : qsTr("Join Community")
}
onClicked: {
Global.openPopup(communityIntroDialog);
}
Connections {
enabled: joinCommunityButton.loading
target: root.store.communitiesModuleInst
function onCommunityAccessRequested(communityId: string) {
if (communityId === communityData.id) {
joinCommunityButton.invitationPending = root.store.isCommunityRequestPending(communityData.id)
joinCommunityButton.loading = false
}
}
function onCommunityAccessFailed(communityId: string) {
if (communityId === communityData.id) {
joinCommunityButton.invitationPending = false
joinCommunityButton.loading = false
Global.displayToastMessage(qsTr("Request to join failed"),
qsTr("Please try again later"),
"",
false,
Constants.ephemeralNotificationType.normal,
"")
}
}
function onUserAuthenticationCanceled() {
joinCommunityButton.invitationPending = false
joinCommunityButton.loading = false
}
}
Component {
id: communityIntroDialog
CommunityIntroDialog {
isInvitationPending: joinCommunityButton.invitationPending
requirementsCheckPending: root.store.requirementsCheckPending
name: communityData.name
introMessage: communityData.introMessage
imageSrc: communityData.image
accessType: communityData.access
loginType: root.store.loginType
walletAccountsModel: WalletStore.RootStore.nonWatchAccounts
permissionsModel: {
root.store.prepareTokenModelForCommunity(communityData.id)
return root.store.permissionsModel
}
assetsModel: root.store.assetsModel
collectiblesModel: root.store.collectiblesModel
onJoined: {
joinCommunityButton.loading = true
root.store.requestToJoinCommunityWithAuthentication(communityData.id, root.store.userProfileInst.name, sharedAddresses, airdropAddress)
}
onCancelMembershipRequest: {
root.store.cancelPendingRequest(communityData.id)
joinCommunityButton.invitationPending = root.store.isCommunityRequestPending(communityData.id)
}
onSharedAddressesUpdated: {
root.store.updatePermissionsModel(communityData.id, sharedAddresses)
}
onClosed: destroy()
}
}
}
}
Component {
id: finaliseCommunityOwnershipBtn
StatusButton {
anchors.top: communityHeader.bottom
anchors.topMargin: Style.current.halfPadding
anchors.bottomMargin: Style.current.halfPadding
anchors.horizontalCenter: parent.horizontalCenter
text: communityData.joined ? qsTr("Finalise community ownership") : qsTr("To join, finalise community ownership")
onClicked: Global.openPopup(root.finaliseOwnershipTransferPopup)
}
}
Component {
id: createChannelPopup
CreateChannelPopup {
communitiesStore: root.communitiesStore
emojiPopup: root.emojiPopup
onCreateCommunityChannel: function (chName, chDescription, chEmoji, chColor,
chCategoryId) {
chCategoryId) {
root.store.createCommunityChannel(chName, chDescription, chEmoji, chColor,
chCategoryId)
chCategoryId)
}
onClosed: {
destroy()

View File

@ -44,6 +44,10 @@ StatusSectionLayout {
readonly property bool isTokenMasterOwner: community.memberRole === Constants.memberRole.tokenMaster
readonly property bool isControlNode: community.isControlNode
// Community transfer ownership related props:
required property var finaliseOwnershipTransferPopup
required property bool isPendingOwnershipRequest
readonly property string filteredSelectedTags: {
let tagsArray = []
if (community && community.tags) {
@ -187,6 +191,9 @@ StatusSectionLayout {
tokensModel: root.community.communityTokens
accounts: root.walletAccountsModel
finaliseOwnershipTransferPopup: root.finaliseOwnershipTransferPopup
isPendingOwnershipRequest: root.isPendingOwnershipRequest
onCollectCommunityMetricsMessagesCount: {
rootStore.collectCommunityMetricsMessagesCount(intervals)
}

View File

@ -60,6 +60,10 @@ QtObject {
communityTokensModuleInst.removeCommunityToken(communityId, parts[0], parts[1])
}
function updateSmartContract(communityId, collectibleItem) {
console.warn("TODO: Backend to update smart contract and finalise community transfer ownership! The token owner is: " + collectibleItem.symbol)
}
readonly property Connections connections: Connections {
target: communityTokensModuleInst