feat(TransferOwnershipPopup): Updated transfer ownership popup according to new design

- Applied new design to transfer ownership popup.
- Added support in storybook.
- Added navigation to transfer ownership popup from community settings / owner token footer.
- Added navigation to transfer ownership popup from community settings / overview.
- Linked wallet send modal to the transactions popup with the needed pre-populated data.

Closes #12171
This commit is contained in:
Noelia 2023-09-14 12:02:51 +02:00 committed by Noelia
parent 4d22d8d56f
commit 717c243e02
10 changed files with 296 additions and 66 deletions

View File

@ -0,0 +1,114 @@
import QtQuick 2.14
import QtQuick.Controls 2.14
import QtQuick.Layouts 1.14
import Storybook 1.0
import Models 1.0
import AppLayouts.Communities.popups 1.0
import AppLayouts.Communities.helpers 1.0
SplitView {
Logs { id: logs }
SplitView {
orientation: Qt.Vertical
SplitView.fillWidth: true
Item {
SplitView.fillWidth: true
SplitView.fillHeight: true
PopupBackground {
anchors.fill: parent
}
Button {
anchors.centerIn: parent
text: "Reopen"
onClicked: dialog.open()
}
TransferOwnershipPopup {
id: dialog
anchors.centerIn: parent
communityName: communityNameText.text
communityLogo: ModelsData.collectibles.doodles
token: TokenObject {
name: "Owner-CatsComm"
symbol: "OWNCAT"
accountAddress: "0x012304123"
chainId: 1
artworkSource: ModelsData.collectibles.doodles
}
onCancelClicked: logs.logEvent("TransferOwnershipPopup::onCancelClicked")
}
}
LogsAndControlsPanel {
id: logsAndControlsPanel
SplitView.minimumHeight: 100
SplitView.preferredHeight: 150
logsView.logText: logs.logText
}
}
Pane {
SplitView.minimumWidth: 300
SplitView.preferredWidth: 300
Column {
spacing: 12
Label {
text: "Community Name"
font.bold: true
}
TextInput {
id: communityNameText
text: "Doodles"
}
Label {
text: "Community Logo"
font.bold: true
}
RadioButton {
id: doodleLogo
text: "Doodle"
checked: true
onCheckedChanged: dialog.communityLogo = ModelsData.collectibles.doodles
}
RadioButton {
id: manaLogo
text: "Mana"
onCheckedChanged: dialog.communityLogo = ModelsData.collectibles.mana
}
RadioButton {
id: superRareLogo
text: "Status"
onCheckedChanged: dialog.communityLogo = ModelsData.collectibles.custom
}
}
}
}
// category: Popups

View File

@ -23,6 +23,7 @@ StackLayout {
property var communitiesStore property var communitiesStore
property var sectionItemModel property var sectionItemModel
property var sendModalPopup
readonly property bool isOwner: sectionItemModel.memberRole === Constants.memberRole.owner readonly property bool isOwner: sectionItemModel.memberRole === Constants.memberRole.owner
readonly property bool isAdmin: sectionItemModel.memberRole === Constants.memberRole.admin readonly property bool isAdmin: sectionItemModel.memberRole === Constants.memberRole.admin
@ -167,6 +168,7 @@ StackLayout {
id: communitySettingsView id: communitySettingsView
rootStore: root.rootStore rootStore: root.rootStore
walletAccountsModel: WalletStore.RootStore.nonWatchAccounts walletAccountsModel: WalletStore.RootStore.nonWatchAccounts
sendModalPopup: root.sendModalPopup
chatCommunitySectionModule: root.rootStore.chatCommunitySectionModule chatCommunitySectionModule: root.rootStore.chatCommunitySectionModule
community: sectionItemModel community: sectionItemModel

View File

@ -11,17 +11,24 @@ import utils 1.0
Control { Control {
id: root id: root
property string communityName
property alias airdropEnabled: airdropButton.enabled property alias airdropEnabled: airdropButton.enabled
property alias retailEnabled: retailButton.enabled property alias retailEnabled: retailButton.enabled
property alias remotelyDestructEnabled: remotelyDestructButton.enabled property alias remotelyDestructEnabled: remotelyDestructButton.enabled
property alias burnEnabled: burnButton.enabled property alias burnEnabled: burnButton.enabled
property alias sendOwnershipEnabled: sendOwnershipButton.enabled
property alias airdropVisible: airdropButton.visible
property alias remotelyDestructVisible: remotelyDestructButton.visible property alias remotelyDestructVisible: remotelyDestructButton.visible
property alias burnVisible: burnButton.visible property alias burnVisible: burnButton.visible
property alias sendOwnershipVisible: sendOwnershipButton.visible
signal airdropClicked signal airdropClicked
signal retailClicked signal retailClicked
signal remotelyDestructClicked signal remotelyDestructClicked
signal burnClicked signal burnClicked
signal sendOwnershipClicked
height: 61 // by design height: 61 // by design
spacing: Style.current.padding spacing: Style.current.padding
@ -36,6 +43,15 @@ Control {
anchors.centerIn: parent anchors.centerIn: parent
spacing: root.spacing spacing: root.spacing
StatusFlatButton {
id: sendOwnershipButton
icon.name: "send"
text: qsTr("Send Owner token to transfer %1 Community ownership").arg(root.communityName)
onClicked: root.sendOwnershipClicked()
}
StatusFlatButton { StatusFlatButton {
id: airdropButton id: airdropButton

View File

@ -29,6 +29,7 @@ StackView {
required property string communityName required property string communityName
required property string communityLogo required property string communityLogo
required property color communityColor required property color communityColor
property var sendModalPopup
// User profile props: // User profile props:
required property bool isOwner required property bool isOwner
@ -655,10 +656,8 @@ StackView {
burnTokensPopup.close() burnTokensPopup.close()
} }
communityName: root.communityName
visible: { visible: {
if(tokenViewPage.isOwnerTokenItem)
// Always hidden
return false
if(tokenViewPage.isTMasterTokenItem) if(tokenViewPage.isTMasterTokenItem)
// Only footer if owner profile // Only footer if owner profile
return root.isOwner return root.isOwner
@ -673,10 +672,13 @@ StackView {
!!view.tokenOwnersModel && !!view.tokenOwnersModel &&
view.tokenOwnersModel.count > 0 view.tokenOwnersModel.count > 0
burnEnabled: deployStateCompleted burnEnabled: deployStateCompleted
sendOwnershipEnabled: deployStateCompleted
remotelyDestructVisible: token.remotelyDestruct sendOwnershipVisible: tokenViewPage.isOwnerTokenItem
burnVisible: !token.infiniteSupply airdropVisible: !tokenViewPage.isOwnerTokenItem
remotelyDestructVisible: !tokenViewPage.isOwnerTokenItem && token.remotelyDestruct
burnVisible: !tokenViewPage.isOwnerTokenItem && !token.infiniteSupply
onAirdropClicked: root.airdropToken( onAirdropClicked: root.airdropToken(
view.airdropKey, view.airdropKey,
@ -685,6 +687,11 @@ StackView {
onRemotelyDestructClicked: remotelyDestructPopup.open() onRemotelyDestructClicked: remotelyDestructPopup.open()
onBurnClicked: burnTokensPopup.open() onBurnClicked: burnTokensPopup.open()
onSendOwnershipClicked: Global.openTransferOwnershipPopup(root.communityName,
root.communityLogo,
tokenViewPage.token,
root.accounts,
root.sendModalPopup)
// helper properties to pass data through popups // helper properties to pass data through popups
property var walletsAndAmounts property var walletsAndAmounts

View File

@ -6,17 +6,22 @@ import StatusQ.Core 0.1
import StatusQ.Core.Theme 0.1 import StatusQ.Core.Theme 0.1
import StatusQ.Controls 0.1 import StatusQ.Controls 0.1
import StatusQ.Components 0.1 import StatusQ.Components 0.1
import StatusQ.Core.Utils 0.1 as SQUtils
import AppLayouts.Communities.layouts 1.0 import AppLayouts.Communities.layouts 1.0
import AppLayouts.Communities.panels 1.0 import AppLayouts.Communities.panels 1.0
import AppLayouts.Communities.popups 1.0
import AppLayouts.Communities.helpers 1.0
import shared.popups 1.0 import shared.popups 1.0
import utils 1.0 import utils 1.0
StackLayout { StackLayout {
id: root id: root
required property bool isOwner
property string communityId property string communityId
property string name property string name
property string description property string description
@ -32,6 +37,7 @@ StackLayout {
property bool requestToJoinEnabled property bool requestToJoinEnabled
property bool pinMessagesEnabled property bool pinMessagesEnabled
property string previousPageName: (currentIndex === 1) ? qsTr("Overview") : "" property string previousPageName: (currentIndex === 1) ? qsTr("Overview") : ""
property var sendModalPopup
property bool archiveSupporVisible: true property bool archiveSupporVisible: true
property bool editable: false property bool editable: false
@ -39,6 +45,9 @@ StackLayout {
property bool isControlNode: false property bool isControlNode: false
property int loginType: Constants.LoginType.Password property int loginType: Constants.LoginType.Password
property bool communitySettingsDisabled property bool communitySettingsDisabled
property var tokensModel
property var accounts // Wallet accounts model. Expected roles: address, name, color, emoji, walletType
readonly property var ownerToken: SQUtils.ModelUtils.getByKey(root.tokensModel, "privilegesLevel", Constants.TokenPrivilegesLevel.Owner)
property string overviewChartData: "" property string overviewChartData: ""
@ -98,6 +107,21 @@ StackLayout {
Item { Layout.fillWidth: true } Item { Layout.fillWidth: true }
StatusButton {
Layout.preferredHeight: 38
Layout.alignment: Qt.AlignTop
objectName: "communityOverviewSettingsTransferOwnershipButton"
visible: root.isOwner && !!root.ownerToken && root.ownerToken.deployState === Constants.ContractTransactionStatus.Completed
text: qsTr("Transfer ownership")
size: StatusBaseButton.Size.Small
onClicked: Global.openTransferOwnershipPopup(root.name,
root.logoImageData,
root.ownerToken,
root.accounts,
root.sendModalPopup)
}
StatusButton { StatusButton {
Layout.preferredHeight: 38 Layout.preferredHeight: 38
Layout.alignment: Qt.AlignTop Layout.alignment: Qt.AlignTop

View File

@ -1,93 +1,129 @@
import QtQuick 2.12 import QtQuick 2.15
import QtQuick.Controls 2.3 import QtQuick.Controls 2.15
import QtQuick.Layouts 1.14 import QtQuick.Layouts 1.15
import QtQml.Models 2.14 import QtQml.Models 2.15
import QtGraphicalEffects 1.0
import StatusQ.Core 0.1 import StatusQ.Core 0.1
import StatusQ.Core.Theme 0.1 import StatusQ.Core.Theme 0.1
import StatusQ.Core.Utils 0.1
import StatusQ.Controls 0.1 import StatusQ.Controls 0.1
import StatusQ.Popups 0.1 import StatusQ.Popups 0.1
import StatusQ.Popups.Dialog 0.1 import StatusQ.Popups.Dialog 0.1
import StatusQ.Core.Utils 0.1
import StatusQ.Components 0.1
import shared.popups 1.0
import utils 1.0 import utils 1.0
import shared.controls 1.0
import shared 1.0
StatusDialog { StatusDialog {
id: root id: root
property string privateKey // Community related props:
property var store property string communityName
property string communityLogo
title: qsTr("Transfer ownership") // Transaction related props:
property var token
property var accounts
property var sendModalPopup
signal cancelClicked
width: 640 // by design
padding: Style.current.padding padding: Style.current.padding
contentItem: ColumnLayout {
spacing: Style.current.bigPadding
width: 480 component CustomText : StatusBaseText {
ColumnLayout {
id: layout
anchors.left: parent.left
anchors.right: parent.right
spacing: Style.current.padding
StatusInput {
id: pKeyInput
Layout.fillWidth: true Layout.fillWidth: true
readonly property string elidedPkey: Utils.getElidedCommunityPK(root.privateKey) wrapMode: Text.WrapAtWordBoundaryOrAnywhere
font.pixelSize: Style.current.primaryTextFontSize
label: qsTr("Community private key") color: Theme.palette.directColor1
input.text: elidedPkey
input.edit.readOnly: true
input.edit.onActiveFocusChanged: {
pKeyInput.input.text = pKeyInput.input.edit.focus ? root.privateKey : elidedPkey
}
input.rightComponent: StatusButton {
anchors.right: parent.right
anchors.rightMargin: Style.current.halfPadding
anchors.verticalCenter: parent.verticalCenter
borderColor: Theme.palette.primaryColor1
size: StatusBaseButton.Size.Tiny
text: qsTr("Copy")
objectName: "copyCommunityPrivateKeyButton"
onClicked: {
text = qsTr("Copied")
Utils.copyToClipboard(root.privateKey)
}
}
} }
StatusBaseText { CustomText {
Layout.fillWidth: true Layout.topMargin: Style.current.halfPadding
text: qsTr("You should keep it safe and only share it with people you trust to take ownership of your community") text: qsTr("Are you sure you want to transfer ownership of %1? All ownership rights you currently hold for %1 will be transferred to the new owner.").arg(root.communityName)
wrapMode: Text.WordWrap
font.pixelSize: 13
color: Theme.palette.baseColor1
} }
StatusBaseText { CustomText {
Layout.fillWidth: true text: qsTr("To transfer ownership of %1:").arg(root.communityName)
font.bold: true
}
text: qsTr("You can also use this key to import your community on another device") CustomText {
wrapMode: Text.WordWrap text: qsTr("1. Send the %1 Owner token (%2) to the new owners address").arg(root.communityName).arg(token.name)
font.pixelSize: 13 }
color: Theme.palette.baseColor1
CustomText {
text: qsTr("2. Ask the new owner to setup the control node for %1 on their desktop device").arg(root.communityName)
}
StatusMenuSeparator {
Layout.fillWidth: true
}
CustomText {
text: qsTr("I acknowledge that...")
}
StatusCheckBox {
id: ackCheckBox
Layout.topMargin: -Style.current.halfPadding
Layout.bottomMargin: Style.current.halfPadding
font.pixelSize: Style.current.primaryTextFontSize
text: qsTr("My ownership rights will be removed and transferred to the recipient")
}
}
header: StatusDialogHeader {
headline.title: qsTr("Transfer ownership of %1").arg(root.communityName)
actions.closeButton.onClicked: root.close()
leftComponent: StatusSmartIdenticon {
asset.name: root.communityLogo
asset.isImage: !!asset.name
} }
} }
footer: StatusDialogFooter { footer: StatusDialogFooter {
leftButtons: ObjectModel { spacing: Style.current.padding
StatusBackButton { rightButtons: ObjectModel {
StatusFlatButton {
text: qsTr("Cancel")
onClicked: { onClicked: {
root.close() root.cancelClicked()
close()
}
}
StatusButton {
enabled: ackCheckBox.checked
text: qsTr("Send %1 owner token").arg(root.communityName)
type: StatusBaseButton.Type.Danger
onClicked: {
// Pre-populated dialog with the relevant Owner token info:
root.sendModalPopup.sendType = Constants.SendType.Transfer
root.sendModalPopup.selectedAccount = ModelUtils.getByKey(root.accounts, "address", token.accountAddress)
root.sendModalPopup.preSelectedHolding = {
uid : token.key,
chainId: token.chainId,
name: token.name,
imageUrl: token.artworkSource,
collectionUid: "",
collectionName: ""
}
root.sendModalPopup.preSelectedHoldingType = Constants.HoldingType.Collectible
root.sendModalPopup.open()
close()
} }
} }
} }
} }
} }

View File

@ -35,6 +35,7 @@ StatusSectionLayout {
property var community property var community
property var transactionStore: TransactionStore {} property var transactionStore: TransactionStore {}
property bool communitySettingsDisabled property bool communitySettingsDisabled
property var sendModalPopup
required property var walletAccountsModel // name, address, emoji, color required property var walletAccountsModel // name, address, emoji, color
@ -161,6 +162,7 @@ StatusSectionLayout {
readonly property string sectionIcon: "show" readonly property string sectionIcon: "show"
readonly property bool sectionEnabled: true readonly property bool sectionEnabled: true
isOwner: root.isOwner
communityId: root.community.id communityId: root.community.id
name: root.community.name name: root.community.name
description: root.community.description description: root.community.description
@ -182,6 +184,10 @@ StatusSectionLayout {
communitySettingsDisabled: root.communitySettingsDisabled communitySettingsDisabled: root.communitySettingsDisabled
overviewChartData: rootStore.overviewChartData overviewChartData: rootStore.overviewChartData
sendModalPopup: root.sendModalPopup
tokensModel: root.community.communityTokens
accounts: root.walletAccountsModel
onCollectCommunityMetricsMessagesCount: { onCollectCommunityMetricsMessagesCount: {
rootStore.collectCommunityMetricsMessagesCount(intervals) rootStore.collectCommunityMetricsMessagesCount(intervals)
} }
@ -305,6 +311,7 @@ StatusSectionLayout {
communityName: root.community.name communityName: root.community.name
communityLogo: root.community.image communityLogo: root.community.image
communityColor: root.community.color communityColor: root.community.color
sendModalPopup: root.sendModalPopup
// User profile props // User profile props
isOwner: root.isOwner isOwner: root.isOwner

View File

@ -1240,6 +1240,7 @@ Item {
} }
} }
sendModalPopup: sendModal
emojiPopup: statusEmojiPopup.item emojiPopup: statusEmojiPopup.item
stickersPopup: statusStickersPopupLoader.item stickersPopup: statusStickersPopupLoader.item
sectionItemModel: model sectionItemModel: model
@ -1337,6 +1338,7 @@ Item {
this.active = false this.active = false
} }
property var selectedAccount property var selectedAccount
property var preSelectedHolding
property string preSelectedHoldingID property string preSelectedHoldingID
property int preSelectedHoldingType property int preSelectedHoldingType
property int sendType: -1 property int sendType: -1
@ -1348,6 +1350,8 @@ Item {
sendModal.sendType = -1 sendModal.sendType = -1
sendModal.preSelectedHoldingID = "" sendModal.preSelectedHoldingID = ""
sendModal.preSelectedHoldingType = Constants.HoldingType.Unknown sendModal.preSelectedHoldingType = Constants.HoldingType.Unknown
sendModal.preSelectedHolding = undefined
sendModal.selectedAccount = undefined
} }
} }
onLoaded: { onLoaded: {
@ -1361,6 +1365,9 @@ Item {
item.preSelectedHoldingID = sendModal.preSelectedHoldingID item.preSelectedHoldingID = sendModal.preSelectedHoldingID
item.preSelectedHoldingType = sendModal.preSelectedHoldingType item.preSelectedHoldingType = sendModal.preSelectedHoldingType
} }
if(!!preSelectedHolding) {
item.preSelectedHolding = preSelectedHolding
}
} }
} }

View File

@ -65,6 +65,7 @@ QtObject {
Global.openExportControlNodePopup.connect(openExportControlNodePopup) Global.openExportControlNodePopup.connect(openExportControlNodePopup)
Global.openImportControlNodePopup.connect(openImportControlNodePopup) Global.openImportControlNodePopup.connect(openImportControlNodePopup)
Global.openEditSharedAddressesFlow.connect(openEditSharedAddressesPopup) Global.openEditSharedAddressesFlow.connect(openEditSharedAddressesPopup)
Global.openTransferOwnershipPopup.connect(openTransferOwnershipPopup)
} }
property var currentPopup property var currentPopup
@ -285,6 +286,10 @@ QtObject {
openPopup(importControlNodePopup, { community }) openPopup(importControlNodePopup, { community })
} }
function openTransferOwnershipPopup(communityName, communityLogo, token, accounts, sendModalPopup) {
openPopup(transferOwnershipPopup, { communityName, communityLogo, token, accounts, sendModalPopup })
}
readonly property list<Component> _components: [ readonly property list<Component> _components: [
Component { Component {
id: removeContactConfirmationDialog id: removeContactConfirmationDialog
@ -739,6 +744,13 @@ QtObject {
editSharedAddressesPopup.communityId, sharedAddresses, airdropAddress) editSharedAddressesPopup.communityId, sharedAddresses, airdropAddress)
onClosed: destroy() onClosed: destroy()
} }
},
Component {
id: transferOwnershipPopup
TransferOwnershipPopup {
onClosed: destroy()
}
} }
] ]
} }

View File

@ -49,6 +49,11 @@ QtObject {
signal openExportControlNodePopup(var community) signal openExportControlNodePopup(var community)
signal openImportControlNodePopup(var community) signal openImportControlNodePopup(var community)
signal contactRenamed(string publicKey) signal contactRenamed(string publicKey)
signal openTransferOwnershipPopup(string communityName,
string communityLogo,
var token,
var accounts,
var sendModalPopup)
signal openLink(string link) signal openLink(string link)