parent
c867e8f98c
commit
9fe3456e8f
|
@ -145,6 +145,10 @@ ListModel {
|
|||
title: "HoldingsDropdown"
|
||||
section: "Popups"
|
||||
}
|
||||
ListElement {
|
||||
title: "MembersDropdown"
|
||||
section: "Popups"
|
||||
}
|
||||
ListElement {
|
||||
title: "InDropdown"
|
||||
section: "Popups"
|
||||
|
|
|
@ -24,6 +24,9 @@
|
|||
"https://www.figma.com/file/idUoxN7OIW2Jpp3PMJ1Rl8/%E2%9A%99%EF%B8%8F-Settings-%7C-Desktop?node-id=448%3A36296",
|
||||
"https://www.figma.com/file/idUoxN7OIW2Jpp3PMJ1Rl8/%E2%9A%99%EF%B8%8F-Settings-%7C-Desktop?node-id=1573%3A296338"
|
||||
],
|
||||
"ChatAnchorButtonsPanel": [
|
||||
"https://www.figma.com/file/Mr3rqxxgKJ2zMQ06UAKiWL/%F0%9F%92%AC-Chat%E2%8E%9CDesktop?node-id=14632-460085&t=SGTU2JeRA8ifbv2E-0"
|
||||
],
|
||||
"CommunitiesPortalLayout": [
|
||||
"https://www.figma.com/file/17fc13UBFvInrLgNUKJJg5/Kuba%E2%8E%9CDesktop?node-id=8159%3A415655",
|
||||
"https://www.figma.com/file/17fc13UBFvInrLgNUKJJg5/Kuba%E2%8E%9CDesktop?node-id=8159%3A415935"
|
||||
|
@ -76,6 +79,9 @@
|
|||
"https://www.figma.com/file/17fc13UBFvInrLgNUKJJg5/Kuba%E2%8E%9CDesktop?node-id=2975%3A489607",
|
||||
"https://www.figma.com/file/17fc13UBFvInrLgNUKJJg5/Kuba%E2%8E%9CDesktop?node-id=2975%3A492910"
|
||||
],
|
||||
"DerivationPathInput": [
|
||||
"https://www.figma.com/file/FkFClTCYKf83RJWoifWgoX/Wallet-v2?node-id=12272%3A269692&t=YiipgcxOhdOvqprP-0"
|
||||
],
|
||||
"DidYouKnowSplashScreen": [
|
||||
"https://www.figma.com/file/17fc13UBFvInrLgNUKJJg5/Kuba⎜Desktop?node-id=25878%3A518438&t=C7xTpNib38t7s7XU-4"
|
||||
],
|
||||
|
@ -118,6 +124,10 @@
|
|||
"LoginView": [
|
||||
"https://www.figma.com/file/17fc13UBFvInrLgNUKJJg5/Kuba%E2%8E%9CDesktop?node-id=1080%3A313192"
|
||||
],
|
||||
"MembersDropdown": [
|
||||
"https://www.figma.com/file/17fc13UBFvInrLgNUKJJg5/Kuba%E2%8E%9CDesktop?node-id=22647-498410",
|
||||
"https://www.figma.com/file/17fc13UBFvInrLgNUKJJg5/Kuba%E2%8E%9CDesktop?node-id=22642-497015"
|
||||
],
|
||||
"NetworkSelectPopup": [
|
||||
"https://www.figma.com/file/FkFClTCYKf83RJWoifWgoX/Wallet-v2?node-id=13200-352357&t=jKciSCy3BVlrZmBs-0",
|
||||
"https://www.figma.com/file/FkFClTCYKf83RJWoifWgoX/Wallet-v2?node-id=13185-350333&t=b2AclcJgxjXDL6Wl-0",
|
||||
|
@ -172,11 +182,5 @@
|
|||
"StatusCommunityCard": [
|
||||
"https://www.figma.com/file/17fc13UBFvInrLgNUKJJg5/Kuba%E2%8E%9CDesktop?node-id=8159%3A416159",
|
||||
"https://www.figma.com/file/17fc13UBFvInrLgNUKJJg5/Kuba%E2%8E%9CDesktop?node-id=8159%3A416160"
|
||||
],
|
||||
"ChatAnchorButtonsPanel": [
|
||||
"https://www.figma.com/file/Mr3rqxxgKJ2zMQ06UAKiWL/%F0%9F%92%AC-Chat%E2%8E%9CDesktop?node-id=14632-460085&t=SGTU2JeRA8ifbv2E-0"
|
||||
],
|
||||
"DerivationPathInput": [
|
||||
"https://www.figma.com/file/FkFClTCYKf83RJWoifWgoX/Wallet-v2?node-id=12272%3A269692&t=YiipgcxOhdOvqprP-0"
|
||||
]
|
||||
}
|
||||
|
|
|
@ -0,0 +1,315 @@
|
|||
import QtQuick 2.15
|
||||
import QtQuick.Controls 2.15
|
||||
import QtQuick.Layouts 1.15
|
||||
import QtQml 2.15
|
||||
|
||||
import AppLayouts.Chat.controls.community 1.0
|
||||
|
||||
import utils 1.0
|
||||
import SortFilterProxyModel 0.2
|
||||
|
||||
import Storybook 1.0
|
||||
|
||||
SplitView {
|
||||
id: root
|
||||
|
||||
property bool globalUtilsReady: false
|
||||
property bool mainModuleReady: false
|
||||
|
||||
orientation: Qt.Vertical
|
||||
|
||||
Logs { id: logs }
|
||||
|
||||
QtObject {
|
||||
function isCompressedPubKey(publicKey) {
|
||||
return true
|
||||
}
|
||||
|
||||
function getColorId(publicKey) {
|
||||
return Math.floor(Math.random() * 10)
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
Utils.globalUtilsInst = this
|
||||
globalUtilsReady = true
|
||||
|
||||
}
|
||||
Component.onDestruction: {
|
||||
globalUtilsReady = false
|
||||
Utils.globalUtilsInst = {}
|
||||
}
|
||||
}
|
||||
|
||||
QtObject {
|
||||
function getContactDetailsAsJson() {
|
||||
return JSON.stringify({ ensVerified: true })
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
mainModuleReady = true
|
||||
Utils.mainModuleInst = this
|
||||
}
|
||||
Component.onDestruction: {
|
||||
mainModuleReady = false
|
||||
Utils.mainModuleInst = {}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ListModel {
|
||||
id: members
|
||||
|
||||
property int counter: 0
|
||||
|
||||
function addMember() {
|
||||
const i = counter++
|
||||
const key = `pub_key_${i}`
|
||||
|
||||
const firstLetters = ["a", "b", "c", "d"]
|
||||
const firstLetterIdx = Math.min(Math.floor(i / firstLetters.length),
|
||||
firstLetters.length - 1)
|
||||
const firstLetter = firstLetters[firstLetterIdx]
|
||||
|
||||
append({
|
||||
alias: "",
|
||||
colorId: "1",
|
||||
displayName: `${firstLetter}contact ${i}`,
|
||||
ensName: "",
|
||||
icon: "",
|
||||
isContact: true,
|
||||
localNickname: "",
|
||||
onlineStatus: 1,
|
||||
pubKey: key,
|
||||
isVerified: true,
|
||||
isUntrustworthy: false
|
||||
})
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
for (let i = 0; i < 33; i++)
|
||||
addMember()
|
||||
}
|
||||
}
|
||||
|
||||
Pane {
|
||||
id: container
|
||||
|
||||
SplitView.fillWidth: true
|
||||
SplitView.fillHeight: true
|
||||
|
||||
Rectangle {
|
||||
id: startRect
|
||||
|
||||
border.color: "green"
|
||||
color: "lightgreen"
|
||||
border.width: 3
|
||||
width: 50
|
||||
height: width
|
||||
|
||||
x: 70
|
||||
y: 70
|
||||
|
||||
radius: width / 2
|
||||
|
||||
Drag.active: dragArea.drag.active
|
||||
|
||||
MouseArea {
|
||||
id: dragArea
|
||||
|
||||
anchors.fill: parent
|
||||
drag.target: parent
|
||||
}
|
||||
}
|
||||
|
||||
Loader {
|
||||
id: loader
|
||||
|
||||
anchors.centerIn: parent
|
||||
active: globalUtilsReady && mainModuleReady
|
||||
|
||||
sourceComponent: MembersDropdown {
|
||||
id: membersDropdown
|
||||
|
||||
closePolicy: Popup.NoAutoClose
|
||||
|
||||
model: SortFilterProxyModel {
|
||||
Binding on sourceModel {
|
||||
when: globalUtilsReady && mainModuleReady
|
||||
value: members
|
||||
restoreMode: Binding.RestoreBindingOrValue
|
||||
}
|
||||
|
||||
filters: [
|
||||
ExpressionFilter {
|
||||
enabled: membersDropdown.searchText !== ""
|
||||
|
||||
function matchesAlias(name, filter) {
|
||||
return name.split(" ").some(p => p.startsWith(filter))
|
||||
}
|
||||
|
||||
expression: {
|
||||
membersDropdown.selectedKeys
|
||||
membersDropdown.searchText
|
||||
|
||||
if (membersDropdown.selectedKeys.indexOf(model.pubKey) > -1)
|
||||
return true
|
||||
|
||||
const filter = membersDropdown.searchText.toLowerCase()
|
||||
return matchesAlias(model.alias.toLowerCase(), filter)
|
||||
|| model.displayName.toLowerCase().includes(filter)
|
||||
|| model.ensName.toLowerCase().includes(filter)
|
||||
|| model.localNickname.toLowerCase().includes(filter)
|
||||
|| model.pubKey.toLowerCase().includes(filter)
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
onBackButtonClicked: {
|
||||
logs.logEvent("MembersDropdown::backButtonClicked")
|
||||
}
|
||||
|
||||
onAddButtonClicked: {
|
||||
logs.logEvent("MembersDropdown::addButtonClicked, keys: "
|
||||
+ membersDropdown.selectedKeys)
|
||||
}
|
||||
|
||||
Component.onCompleted: open()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LogsAndControlsPanel {
|
||||
SplitView.minimumHeight: 100
|
||||
SplitView.preferredHeight: 250
|
||||
|
||||
logsView.logText: logs.logText
|
||||
|
||||
Loader {
|
||||
active: loader.item
|
||||
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
|
||||
sourceComponent: ColumnLayout {
|
||||
readonly property MembersDropdown membersDropdown: loader.item
|
||||
|
||||
RowLayout {
|
||||
Label {
|
||||
text: "maximum list height:"
|
||||
}
|
||||
|
||||
Slider {
|
||||
id: maxListHeightSlider
|
||||
from: 100
|
||||
to: 500
|
||||
stepSize: 1
|
||||
|
||||
Component.onCompleted: {
|
||||
value = membersDropdown.maximumListHeight
|
||||
membersDropdown.maximumListHeight
|
||||
= Qt.binding(() => value)
|
||||
}
|
||||
}
|
||||
|
||||
Label {
|
||||
text: maxListHeightSlider.value
|
||||
}
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
Label {
|
||||
text: "margins:"
|
||||
}
|
||||
|
||||
Slider {
|
||||
id: marginsSlider
|
||||
from: -1
|
||||
to: 50
|
||||
stepSize: 1
|
||||
|
||||
Component.onCompleted: {
|
||||
value = membersDropdown.margins
|
||||
membersDropdown.margins = Qt.binding(() => value)
|
||||
}
|
||||
}
|
||||
|
||||
Label {
|
||||
text: marginsSlider.value
|
||||
}
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
Label {
|
||||
text: "bottom inset:"
|
||||
}
|
||||
|
||||
Slider {
|
||||
id: bottomInsetSlider
|
||||
from: 0
|
||||
to: 50
|
||||
stepSize: 1
|
||||
|
||||
Component.onCompleted: {
|
||||
value = membersDropdown.bottomInset
|
||||
membersDropdown.bottomInset = Qt.binding(() => value)
|
||||
}
|
||||
}
|
||||
|
||||
Label {
|
||||
text: bottomInsetSlider.value
|
||||
}
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
RadioButton {
|
||||
id: anchorToItemRadioButton
|
||||
text: "anchor to item"
|
||||
|
||||
checked: true
|
||||
}
|
||||
RadioButton {
|
||||
id: anchorToOverlayRadioButton
|
||||
text: "anchor to overlay"
|
||||
|
||||
}
|
||||
|
||||
Binding {
|
||||
target: membersDropdown
|
||||
property: "parent"
|
||||
value: anchorToItemRadioButton.checked
|
||||
? startRect : membersDropdown.Overlay.overlay
|
||||
}
|
||||
|
||||
Binding {
|
||||
target: membersDropdown.anchors
|
||||
when: anchorToOverlayRadioButton.checked
|
||||
property: "centerIn"
|
||||
value: membersDropdown.parent
|
||||
restoreMode: Binding.RestoreBindingOrValue
|
||||
}
|
||||
|
||||
Binding {
|
||||
target: membersDropdown
|
||||
property: "x"
|
||||
value: anchorToItemRadioButton.checked
|
||||
? startRect.width / 2 : 0
|
||||
}
|
||||
|
||||
Binding {
|
||||
target: membersDropdown
|
||||
property: "y"
|
||||
value: anchorToItemRadioButton.checked
|
||||
? startRect.height / 2 : 0
|
||||
}
|
||||
}
|
||||
|
||||
Label {
|
||||
Layout.fillWidth: true
|
||||
text: `selected members: ${membersDropdown.selectedKeys}`
|
||||
wrapMode: Label.Wrap
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -166,10 +166,9 @@ StatusDropdown {
|
|||
visible: statesStack.size > 1
|
||||
spacing: 0
|
||||
leftPadding: 4
|
||||
statusIcon: "next"
|
||||
statusIcon: "previous"
|
||||
icon.width: 12
|
||||
icon.height: 12
|
||||
iconRotation: 180
|
||||
text: qsTr("Back")
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,234 @@
|
|||
import QtQuick 2.15
|
||||
import QtQuick.Controls 2.15
|
||||
import QtQuick.Layouts 1.15
|
||||
|
||||
import StatusQ.Core 0.1
|
||||
import StatusQ.Core.Theme 0.1
|
||||
import StatusQ.Controls 0.1
|
||||
import StatusQ.Core.Utils 0.1
|
||||
|
||||
import shared.controls 1.0
|
||||
import shared.controls.delegates 1.0
|
||||
|
||||
StatusDropdown {
|
||||
id: root
|
||||
|
||||
property var selectedKeys: []
|
||||
property int maximumListHeight: 288
|
||||
|
||||
property alias model: listView.model
|
||||
readonly property alias count: listView.count
|
||||
|
||||
readonly property alias searchText: filterInput.text
|
||||
|
||||
property bool fixedYPosition: !anchors.centerIn && margins < 0
|
||||
|
||||
signal backButtonClicked
|
||||
signal addButtonClicked
|
||||
|
||||
width: 295
|
||||
|
||||
height: Math.min(
|
||||
d.availableExternalHeight,
|
||||
content.requestedHeight + d.vPadding)
|
||||
|
||||
padding: 11
|
||||
bottomInset: 10
|
||||
bottomPadding: padding + bottomInset
|
||||
|
||||
QtObject {
|
||||
id: d
|
||||
|
||||
readonly property int sectionDelegateHeight: 40
|
||||
readonly property int delegateHeight: 47
|
||||
|
||||
readonly property int vPadding: root.topPadding + root.bottomPadding
|
||||
|
||||
readonly property int availableExternalHeight:
|
||||
(root.Overlay.overlay ? root.Overlay.overlay.height : 0) - root.bottomMargin -
|
||||
(root.fixedYPosition ? contentItem.parent.y : root.topMargin)
|
||||
}
|
||||
|
||||
contentItem: ColumnLayout {
|
||||
id: content
|
||||
|
||||
spacing: 8
|
||||
height: root.availableHeight
|
||||
clip: true
|
||||
|
||||
readonly property int requestedHeight:
|
||||
backButton.height +
|
||||
spacing + filterInput.height +
|
||||
spacing + (listView.count
|
||||
? Math.min(listView.contentHeight, root.maximumListHeight)
|
||||
: noContactsText.Layout.preferredHeight) +
|
||||
spacing + addButton.height
|
||||
|
||||
StatusIconTextButton {
|
||||
id: backButton
|
||||
|
||||
Layout.preferredHeight: 48
|
||||
Layout.maximumWidth: root.availableWidth
|
||||
|
||||
spacing: 0
|
||||
leftPadding: 4
|
||||
statusIcon: "previous"
|
||||
icon.width: 12
|
||||
icon.height: 12
|
||||
text: qsTr("Back")
|
||||
|
||||
onClicked: root.backButtonClicked()
|
||||
}
|
||||
|
||||
SearchBox {
|
||||
id: filterInput
|
||||
|
||||
Layout.fillWidth: true
|
||||
|
||||
placeholderText: qsTr("Search members")
|
||||
maximumHeight: 36
|
||||
topPadding: 0
|
||||
bottomPadding: 0
|
||||
|
||||
input.asset.width: 15
|
||||
input.asset.height: 15
|
||||
input.leftPadding: 13
|
||||
input.font.pixelSize: 13
|
||||
input.placeholder.font.pixelSize: 13
|
||||
}
|
||||
|
||||
StatusBaseText {
|
||||
id: noContactsText
|
||||
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: 50
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
|
||||
visible: listView.count === 0
|
||||
|
||||
text: qsTr("No contacts found")
|
||||
color: Theme.palette.baseColor1
|
||||
font.pixelSize: Theme.tertiaryTextFontSize
|
||||
elide: Text.ElideRight
|
||||
lineHeight: 1.2
|
||||
}
|
||||
|
||||
StatusListView {
|
||||
id: listView
|
||||
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
|
||||
visible: count > 0
|
||||
|
||||
header: StatusCheckBox {
|
||||
width: ListView.view.width
|
||||
|
||||
text: qsTr("Select all")
|
||||
font.weight: Font.Medium
|
||||
|
||||
checked: root.selectedKeys.length === listView.count
|
||||
|
||||
leftSide: false
|
||||
size: StatusCheckBox.Size.Small
|
||||
indicator.anchors.rightMargin: 12
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
|
||||
onClicked: {
|
||||
if (listView.headerItem.checked) {
|
||||
root.selectedKeys = []
|
||||
return
|
||||
}
|
||||
|
||||
const count = root.model.rowCount()
|
||||
const keys = []
|
||||
|
||||
for (let i = 0; i < count; i++) {
|
||||
const key = ModelUtils.get(root.model, i, "pubKey")
|
||||
keys.push(key)
|
||||
}
|
||||
|
||||
root.selectedKeys = keys
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
delegate: ContactListItemDelegate {
|
||||
id: delegateRoot
|
||||
|
||||
width: ListView.view.width
|
||||
height: d.delegateHeight
|
||||
asset.width: 29
|
||||
asset.height: 29
|
||||
|
||||
rightPadding: 0
|
||||
leftPadding: 6
|
||||
|
||||
color: "transparent"
|
||||
|
||||
onClicked: {
|
||||
const index = root.selectedKeys.indexOf(model.pubKey)
|
||||
const selectedKeysCopy = Object.assign(
|
||||
[], root.selectedKeys)
|
||||
|
||||
if (index === -1)
|
||||
selectedKeysCopy.push(model.pubKey)
|
||||
else
|
||||
selectedKeysCopy.splice(index, 1)
|
||||
|
||||
root.selectedKeys = selectedKeysCopy
|
||||
}
|
||||
|
||||
components: [
|
||||
StatusCheckBox {
|
||||
id: contactCheckbox
|
||||
|
||||
size: StatusCheckBox.Size.Small
|
||||
checked: root.selectedKeys.indexOf(model.pubKey) > -1
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
|
||||
onClicked: delegateRoot.clicked(
|
||||
delegateRoot.itemId, mouse)
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
section.property: "displayName"
|
||||
section.criteria: ViewSection.FirstCharacter
|
||||
section.delegate: StatusBaseText {
|
||||
text: section.toUpperCase()
|
||||
|
||||
width: ListView.view.width
|
||||
height: d.sectionDelegateHeight
|
||||
|
||||
padding: 5
|
||||
verticalAlignment: Qt.AlignVCenter
|
||||
|
||||
color: Theme.palette.baseColor1
|
||||
font.pixelSize: Theme.tertiaryTextFontSize
|
||||
}
|
||||
}
|
||||
|
||||
StatusButton {
|
||||
id: addButton
|
||||
|
||||
Layout.fillWidth: true
|
||||
|
||||
textFillWidth: true
|
||||
enabled: root.selectedKeys.length > 0
|
||||
text: enabled
|
||||
? qsTr("Add %n member(s)", "", root.selectedKeys.length)
|
||||
: qsTr("Add")
|
||||
|
||||
onClicked: root.addButtonClicked()
|
||||
}
|
||||
}
|
||||
}
|
|
@ -8,6 +8,7 @@ HoldingTypes 1.0 HoldingTypes.qml
|
|||
HoldingsDropdown 1.0 HoldingsDropdown.qml
|
||||
InDropdown 1.0 InDropdown.qml
|
||||
InlineNetworksComboBox 1.0 InlineNetworksComboBox.qml
|
||||
MembersDropdown 1.0 MembersDropdown.qml
|
||||
MembersSelectorPanel 1.0 MembersSelectorPanel.qml
|
||||
PermissionItem 1.0 PermissionItem.qml
|
||||
PermissionsDropdown 1.0 PermissionsDropdown.qml
|
||||
|
|
|
@ -23,13 +23,6 @@ Item {
|
|||
|
||||
readonly property alias count: contactGridView.count
|
||||
|
||||
signal contactClicked(var contact)
|
||||
|
||||
function matchesAlias(name, filter) {
|
||||
let parts = name.split(" ")
|
||||
return parts.some(p => p.startsWith(filter))
|
||||
}
|
||||
|
||||
StatusGridView {
|
||||
id: contactGridView
|
||||
anchors.fill: parent
|
||||
|
|
Loading…
Reference in New Issue