348 lines
13 KiB
QML
348 lines
13 KiB
QML
import QtQuick 2.15
|
|
import QtQml.Models 2.15
|
|
import QtQuick.Controls 2.15
|
|
import QtQuick.Layouts 1.15
|
|
import QtGraphicalEffects 1.15
|
|
|
|
import StatusQ 0.1
|
|
import StatusQ.Core 0.1
|
|
import StatusQ.Components 0.1
|
|
import StatusQ.Controls 0.1
|
|
import StatusQ.Core.Theme 0.1
|
|
import StatusQ.Core.Utils 0.1
|
|
import StatusQ.Internal 0.1 as SQInternal
|
|
|
|
import SortFilterProxyModel 0.2
|
|
|
|
import AppLayouts.Profile.controls 1.0
|
|
import AppLayouts.Communities.controls 1.0
|
|
import AppLayouts.Communities.views 1.0
|
|
import AppLayouts.Communities.helpers 1.0
|
|
|
|
import utils 1.0
|
|
|
|
Control {
|
|
id: root
|
|
|
|
required property string componentUid
|
|
required property bool isEditMode
|
|
required property var selectedSharedAddressesMap // Map[address, [keyUid, selected, isAirdrop]
|
|
property var currentSharedAddressesMap // Map[address, [keyUid, selected, isAirdrop]
|
|
required property int totalNumOfAddressesForSharing
|
|
required property bool profileProvesOwnershipOfSelectedAddresses
|
|
required property bool allAddressesToRevealBelongToSingleNonProfileKeypair
|
|
required property int /*PermissionTypes.Type*/ eligibleToJoinAs
|
|
|
|
property bool requirementsCheckPending
|
|
property bool checkingPermissionToJoinInProgress
|
|
property bool joinPermissionsCheckCompletedWithoutErrors
|
|
|
|
required property string communityId
|
|
required property string communityName
|
|
required property string communityIcon
|
|
|
|
required property var walletAssetsModel
|
|
required property var walletCollectiblesModel
|
|
|
|
required property var walletAccountsModel // name, address, emoji, colorId
|
|
required property var permissionsModel // id, key, permissionType, holdingsListModel, channelsListModel, isPrivate, tokenCriteriaMet
|
|
|
|
required property var assetsModel
|
|
required property var collectiblesModel
|
|
|
|
readonly property string title: isEditMode ? qsTr("Edit which addresses you share with %1").arg(root.communityName)
|
|
: qsTr("Select addresses to share with %1").arg(root.communityName)
|
|
|
|
readonly property var rightButtons: root.isEditMode? [d.cancelButton, d.saveButton] : [d.shareAddressesButton]
|
|
|
|
property var getCurrencyAmount: function (balance, symbol){}
|
|
|
|
signal toggleAddressSelection(string keyUid, string address)
|
|
signal airdropAddressSelected (string address)
|
|
signal shareSelectedAddressesClicked()
|
|
signal close()
|
|
|
|
padding: 0
|
|
spacing: Style.current.padding
|
|
|
|
QtObject {
|
|
id: d
|
|
|
|
// internal logic
|
|
readonly property bool hasPermissions: permissionsView.hasAnyVisiblePermission
|
|
readonly property int selectedSharedAddressesCount: root.selectedSharedAddressesMap.size
|
|
|
|
readonly property bool dirty: {
|
|
if (root.currentSharedAddressesMap.size !== root.selectedSharedAddressesMap.size) {
|
|
return true
|
|
}
|
|
for (const [key, value] of root.currentSharedAddressesMap) {
|
|
const obj = root.selectedSharedAddressesMap.get(key)
|
|
if (!obj || value.selected !== obj.selected || value.isAirdrop !== obj.isAirdrop) {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
property var tokenCountMap: new Map()
|
|
function getTokenCount(address) {
|
|
if (d.tokenCountMap.has(address))
|
|
return d.tokenCountMap.get(address)
|
|
return 0
|
|
}
|
|
|
|
// warning states
|
|
readonly property bool lostCommunityPermission: root.isEditMode && permissionsView.lostPermissionToJoin
|
|
readonly property bool lostChannelPermissions: root.isEditMode && permissionsView.lostChannelPermissions
|
|
|
|
readonly property var cancelButton: StatusFlatButton {
|
|
visible: root.isEditMode
|
|
borderColor: Theme.palette.baseColor2
|
|
text: qsTr("Cancel")
|
|
onClicked: root.close()
|
|
}
|
|
|
|
readonly property string tooltipText: {
|
|
if (root.requirementsCheckPending || root.checkingPermissionToJoinInProgress)
|
|
return qsTr("Requirements check pending")
|
|
|
|
if (!root.joinPermissionsCheckCompletedWithoutErrors)
|
|
return qsTr("Checking permissions failed")
|
|
|
|
return ""
|
|
}
|
|
|
|
readonly property var saveButton: StatusButton {
|
|
visible: root.isEditMode
|
|
interactive: d.dirty && !root.requirementsCheckPending && root.joinPermissionsCheckCompletedWithoutErrors
|
|
loading: root.requirementsCheckPending
|
|
type: d.lostCommunityPermission || d.lostChannelPermissions ? StatusBaseButton.Type.Danger : StatusBaseButton.Type.Normal
|
|
tooltip.text: {
|
|
if (interactive)
|
|
return ""
|
|
|
|
return d.tooltipText
|
|
}
|
|
text: {
|
|
if (d.lostCommunityPermission) {
|
|
return qsTr("Save changes & leave %1").arg(root.communityName)
|
|
}
|
|
if (d.lostChannelPermissions) {
|
|
return qsTr("Save changes & update my permissions")
|
|
}
|
|
if (d.selectedSharedAddressesCount === root.totalNumOfAddressesForSharing) {
|
|
return qsTr("Reveal all addresses")
|
|
}
|
|
return qsTr("Reveal %n address(s)", "", d.selectedSharedAddressesCount)
|
|
}
|
|
|
|
icon.name: {
|
|
if (!d.lostCommunityPermission
|
|
&& !d.lostChannelPermissions
|
|
&& root.profileProvesOwnershipOfSelectedAddresses) {
|
|
if (userProfile.usingBiometricLogin) {
|
|
return "touch-id"
|
|
}
|
|
|
|
if (userProfile.isKeycardUser) {
|
|
return "keycard"
|
|
}
|
|
|
|
return "password"
|
|
}
|
|
if (root.allAddressesToRevealBelongToSingleNonProfileKeypair) {
|
|
return "keycard"
|
|
}
|
|
|
|
return ""
|
|
}
|
|
|
|
onClicked: {
|
|
root.shareSelectedAddressesClicked()
|
|
}
|
|
}
|
|
|
|
readonly property var shareAddressesButton: StatusButton {
|
|
visible: !root.isEditMode
|
|
interactive: !root.checkingPermissionToJoinInProgress && root.eligibleToJoinAs !== PermissionTypes.Type.None && root.joinPermissionsCheckCompletedWithoutErrors
|
|
loading: root.checkingPermissionToJoinInProgress
|
|
tooltip.text: {
|
|
if (interactive)
|
|
return ""
|
|
|
|
return d.tooltipText
|
|
}
|
|
text: {
|
|
if (d.selectedSharedAddressesCount === root.totalNumOfAddressesForSharing) {
|
|
return qsTr("Share all addresses to join")
|
|
}
|
|
return qsTr("Share %n address(s) to join", "", d.selectedSharedAddressesCount)
|
|
}
|
|
|
|
icon.name: {
|
|
if (root.profileProvesOwnershipOfSelectedAddresses) {
|
|
if (userProfile.usingBiometricLogin) {
|
|
return "touch-id"
|
|
}
|
|
|
|
if (userProfile.isKeycardUser) {
|
|
return "keycard"
|
|
}
|
|
|
|
return "password"
|
|
}
|
|
if (root.allAddressesToRevealBelongToSingleNonProfileKeypair) {
|
|
return "keycard"
|
|
}
|
|
|
|
return ""
|
|
}
|
|
|
|
onClicked: {
|
|
root.shareSelectedAddressesClicked()
|
|
}
|
|
}
|
|
}
|
|
|
|
contentItem: ColumnLayout {
|
|
anchors.fill: parent
|
|
spacing: 0
|
|
|
|
// warning panel
|
|
Rectangle {
|
|
Layout.fillWidth: true
|
|
Layout.preferredHeight: 32
|
|
color: Theme.palette.dangerColor1
|
|
visible: d.lostCommunityPermission || d.lostChannelPermissions
|
|
|
|
StatusBaseText {
|
|
width: parent.width
|
|
anchors.verticalCenter: parent.verticalCenter
|
|
horizontalAlignment: Qt.AlignHCenter
|
|
elide: Text.ElideRight
|
|
text: d.lostCommunityPermission ? qsTr("Selected addresses have insufficient tokens to maintain %1 membership").arg(root.communityName) :
|
|
d.lostChannelPermissions ? qsTr("By deselecting these addresses, you will lose channel permissions") :
|
|
""
|
|
font.pixelSize: Style.current.additionalTextSize
|
|
font.weight: Font.Medium
|
|
color: Theme.palette.indirectColor1
|
|
}
|
|
}
|
|
|
|
// addresses
|
|
SharedAddressesAccountSelector {
|
|
id: accountSelector
|
|
hasPermissions: d.hasPermissions
|
|
|
|
Layout.fillWidth: true
|
|
Layout.preferredHeight: contentHeight + topMargin + bottomMargin
|
|
Layout.maximumHeight: hasPermissions ? permissionsView.implicitHeight > root.availableHeight / 2 ? root.availableHeight / 2 : root.availableHeight : -1
|
|
Layout.fillHeight: !hasPermissions
|
|
implicitHeight: contentHeight
|
|
|
|
uniquePermissionAssetsKeys:
|
|
PermissionsHelpers.getUniquePermissionTokenKeys(
|
|
root.permissionsModel, Constants.TokenType.ERC20)
|
|
|
|
uniquePermissionCollectiblesKeys:
|
|
PermissionsHelpers.getUniquePermissionTokenKeys(
|
|
root.permissionsModel, Constants.TokenType.ERC721)
|
|
|
|
model: SortFilterProxyModel {
|
|
sourceModel: root.walletAccountsModel
|
|
proxyRoles: FastExpressionRole {
|
|
name: "tokenCount"
|
|
expression: {
|
|
d.tokenCountMap
|
|
return d.getTokenCount(model.address.toLowerCase())
|
|
}
|
|
expectedRoles: ["address"]
|
|
}
|
|
|
|
sorters: [
|
|
// FIXME add sort token-relevant accounts first; https://github.com/status-im/status-desktop/issues/14192
|
|
RoleSorter {
|
|
roleName: "tokenCount"
|
|
sortOrder: Qt.DescendingOrder
|
|
},
|
|
RoleSorter {
|
|
roleName: "name"
|
|
}
|
|
]
|
|
}
|
|
walletAssetsModel: root.walletAssetsModel
|
|
walletCollectiblesModel: root.walletCollectiblesModel
|
|
|
|
communityId: root.communityId
|
|
communityCollectiblesModel: root.collectiblesModel
|
|
|
|
selectedSharedAddressesMap: root.selectedSharedAddressesMap
|
|
|
|
onToggleAddressSelection: {
|
|
root.toggleAddressSelection(keyUid, address)
|
|
}
|
|
|
|
onAirdropAddressSelected: {
|
|
root.airdropAddressSelected(address)
|
|
}
|
|
|
|
getCurrencyAmount: function (balance, symbol) {
|
|
return root.getCurrencyAmount(balance, symbol)
|
|
}
|
|
|
|
Component.onCompleted: {
|
|
const tmpTokenCountMap = new Map()
|
|
for (let i = 0; i < accountSelector.count; i++) {
|
|
const item = accountSelector.itemAtIndex(i)
|
|
if (!!item) {
|
|
tmpTokenCountMap.set(item.address.toLowerCase(), item.tokenCount)
|
|
}
|
|
}
|
|
d.tokenCountMap = tmpTokenCountMap
|
|
}
|
|
}
|
|
|
|
// divider with top rounded corners + drop shadow
|
|
Rectangle {
|
|
Layout.fillWidth: true
|
|
Layout.preferredHeight: Style.current.padding * 2
|
|
color: permissionsView.color
|
|
radius: Style.current.padding
|
|
border.width: 1
|
|
border.color: Theme.palette.baseColor3
|
|
visible: permissionsView.hasAnyVisiblePermission
|
|
|
|
layer.enabled: true
|
|
layer.effect: DropShadow {
|
|
horizontalOffset: 0
|
|
verticalOffset: -9
|
|
radius: 14
|
|
samples: 29
|
|
color: Qt.rgba(0, 0, 0, 0.04)
|
|
}
|
|
}
|
|
|
|
// permissions
|
|
SharedAddressesPermissionsPanel {
|
|
id: permissionsView
|
|
isEditMode: root.isEditMode
|
|
isDirty: d.dirty
|
|
permissionsModel: root.permissionsModel
|
|
assetsModel: root.assetsModel
|
|
collectiblesModel: root.collectiblesModel
|
|
requirementsCheckPending: root.requirementsCheckPending
|
|
checkingPermissionToJoinInProgress: root.checkingPermissionToJoinInProgress
|
|
joinPermissionsCheckCompletedWithoutErrors: root.joinPermissionsCheckCompletedWithoutErrors
|
|
communityName: root.communityName
|
|
communityIcon: root.communityIcon
|
|
eligibleToJoinAs: root.eligibleToJoinAs
|
|
|
|
Layout.fillHeight: true
|
|
Layout.fillWidth: true
|
|
Layout.topMargin: -Style.current.padding // compensate for the half-rounded divider above
|
|
visible: permissionsView.hasAnyVisiblePermission
|
|
}
|
|
}
|
|
}
|