fix(StatusCard): fix some visual glitches
- correct propagation of hover events, fixes card flicker - improve the ugly thick border - token icons are now correctly rounded - fix text descent lines are cut of ("y" and "p" truncated at the bottom) due to excessive clipping, set correct max line count - fix tag outline not being visible in dark mode - add/update the corresponding SB page, with more controls to play around with the different params Fixes #14555
This commit is contained in:
parent
d191a2d9ec
commit
22a9ca72b3
|
@ -19,8 +19,7 @@ ColumnLayout {
|
||||||
property url banner: ctrlCommunityBanner.checked ? Style.png("settings/communities@2x") : ""
|
property url banner: ctrlCommunityBanner.checked ? Style.png("settings/communities@2x") : ""
|
||||||
readonly property bool shardingEnabled: ctrlShardingEnabled.checked
|
readonly property bool shardingEnabled: ctrlShardingEnabled.checked
|
||||||
property alias shardIndex: ctrlShardIndex.value
|
property alias shardIndex: ctrlShardIndex.value
|
||||||
|
property bool adminControlsEnabled: true
|
||||||
spacing: 12
|
|
||||||
|
|
||||||
ColumnLayout {
|
ColumnLayout {
|
||||||
Label {
|
Label {
|
||||||
|
@ -59,7 +58,7 @@ ColumnLayout {
|
||||||
Slider {
|
Slider {
|
||||||
value: root.membersCount
|
value: root.membersCount
|
||||||
from: 0
|
from: 0
|
||||||
to: 1000
|
to: 3000
|
||||||
onValueChanged: root.membersCount = value
|
onValueChanged: root.membersCount = value
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -108,6 +107,7 @@ ColumnLayout {
|
||||||
}
|
}
|
||||||
|
|
||||||
RowLayout {
|
RowLayout {
|
||||||
|
visible: root.adminControlsEnabled
|
||||||
Label {
|
Label {
|
||||||
text: "Is community admin:"
|
text: "Is community admin:"
|
||||||
}
|
}
|
||||||
|
@ -118,6 +118,7 @@ ColumnLayout {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
RowLayout {
|
RowLayout {
|
||||||
|
visible: root.adminControlsEnabled
|
||||||
Label {
|
Label {
|
||||||
text: "Is community editable:"
|
text: "Is community editable:"
|
||||||
}
|
}
|
||||||
|
@ -142,6 +143,7 @@ ColumnLayout {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
RowLayout {
|
RowLayout {
|
||||||
|
visible: root.adminControlsEnabled
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
CheckBox {
|
CheckBox {
|
||||||
id: ctrlShardingEnabled
|
id: ctrlShardingEnabled
|
||||||
|
|
|
@ -1,23 +1,16 @@
|
||||||
import QtQuick 2.14
|
import QtQuick 2.15
|
||||||
import QtQuick.Controls 2.14
|
import QtQuick.Controls 2.15
|
||||||
import QtQuick.Layouts 1.14
|
import QtQuick.Layouts 1.15
|
||||||
|
|
||||||
|
import StatusQ.Components 0.1
|
||||||
|
import StatusQ.Core.Theme 0.1
|
||||||
|
|
||||||
import Storybook 1.0
|
import Storybook 1.0
|
||||||
|
|
||||||
SplitView {
|
SplitView {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
orientation: Qt.Vertical
|
orientation: Qt.Horizontal
|
||||||
|
|
||||||
readonly property string source: `
|
|
||||||
import QtQml 2.14
|
|
||||||
import StatusQ.Components 0.1
|
|
||||||
Component {
|
|
||||||
StatusCommunityCard {
|
|
||||||
name: nameTextField.text
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`
|
|
||||||
|
|
||||||
Logs { id: logs }
|
Logs { id: logs }
|
||||||
|
|
||||||
|
@ -25,72 +18,60 @@ SplitView {
|
||||||
SplitView.fillWidth: true
|
SplitView.fillWidth: true
|
||||||
SplitView.fillHeight: true
|
SplitView.fillHeight: true
|
||||||
|
|
||||||
HotLoader {
|
StatusCommunityCard {
|
||||||
id: loader
|
|
||||||
|
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
source: sourceCodeBox.sourceCode
|
cardSize: ctrlSize.checked ? StatusCommunityCard.Size.Big : StatusCommunityCard.Size.Small
|
||||||
|
communityId: "community_id"
|
||||||
|
name: infoEditor.name
|
||||||
|
description: infoEditor.description
|
||||||
|
members: infoEditor.membersCount
|
||||||
|
activeUsers: members/2
|
||||||
|
//popularity: 4 // not visualized?
|
||||||
|
banner: infoEditor.banner
|
||||||
|
asset.source: infoEditor.image
|
||||||
|
asset.isImage: true
|
||||||
|
communityColor: infoEditor.color
|
||||||
|
loaded: !ctrlLoading.checked
|
||||||
|
|
||||||
Connections {
|
categories: ListModel {
|
||||||
target: loader.item
|
ListElement { name: "gaming"; emoji: "🎮"; selected: false }
|
||||||
|
ListElement { name: "art"; emoji: "🖼️️"; selected: false }
|
||||||
function onClicked() {
|
ListElement { name: "crypto"; emoji: "💸"; selected: true }
|
||||||
logs.logEvent("StatusCommunityCard::clicked",
|
ListElement { name: "nsfw"; emoji: "🍆"; selected: false }
|
||||||
["communityId"], arguments)
|
ListElement { name: "markets"; emoji: "💎"; selected: false }
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
Pane {
|
onClicked: logs.logEvent("StatusCommunityCard::onClicked", ["communityId"], arguments)
|
||||||
anchors.fill: parent
|
onRightClicked: logs.logEvent("StatusCommunityCard::onRightClicked", ["communityId"], arguments)
|
||||||
visible: !!loader.errors
|
|
||||||
|
|
||||||
CompilationErrorsBox {
|
|
||||||
anchors.fill: parent
|
|
||||||
errors: loader.errors
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
LogsAndControlsPanel {
|
LogsAndControlsPanel {
|
||||||
id: logsAndControlsPanel
|
SplitView.preferredWidth: 250
|
||||||
|
|
||||||
SplitView.minimumHeight: 100
|
|
||||||
SplitView.preferredHeight: 200
|
|
||||||
|
|
||||||
logsView.logText: logs.logText
|
logsView.logText: logs.logText
|
||||||
|
|
||||||
RowLayout {
|
CommunityInfoEditor {
|
||||||
anchors.fill: parent
|
id: infoEditor
|
||||||
|
colorVisible: true
|
||||||
|
adminControlsEnabled: false
|
||||||
|
|
||||||
Item {
|
Switch {
|
||||||
Layout.fillWidth: true
|
id: ctrlSize
|
||||||
Layout.fillHeight: true
|
text: "Big card"
|
||||||
|
checked: true
|
||||||
ColumnLayout {
|
|
||||||
anchors.fill: parent
|
|
||||||
|
|
||||||
TextField {
|
|
||||||
id: nameTextField
|
|
||||||
text: "Card name!"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SourceCodeBox {
|
Switch {
|
||||||
id: sourceCodeBox
|
id: ctrlLoading
|
||||||
|
text: "Loading"
|
||||||
Layout.preferredWidth: root.width / 2
|
checked: false
|
||||||
Layout.fillHeight: true
|
|
||||||
|
|
||||||
sourceCode: root.source
|
|
||||||
hasErrors: !!loader.errors
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// category: Panels
|
// category: Components
|
||||||
|
|
||||||
// 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%3A416159
|
||||||
// https://www.figma.com/file/17fc13UBFvInrLgNUKJJg5/Kuba%E2%8E%9CDesktop?node-id=8159%3A416160
|
// https://www.figma.com/file/17fc13UBFvInrLgNUKJJg5/Kuba%E2%8E%9CDesktop?node-id=8159%3A416160
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import QtQuick 2.13
|
import QtQuick 2.15
|
||||||
import QtQuick.Layouts 1.14
|
import QtQuick.Layouts 1.15
|
||||||
import QtGraphicalEffects 1.0
|
import QtGraphicalEffects 1.15
|
||||||
|
|
||||||
import StatusQ.Core 0.1
|
import StatusQ.Core 0.1
|
||||||
import StatusQ.Core.Theme 0.1
|
import StatusQ.Core.Theme 0.1
|
||||||
|
@ -51,7 +51,7 @@ Rectangle {
|
||||||
\qmlproperty bool StatusCommunityCard::hovered
|
\qmlproperty bool StatusCommunityCard::hovered
|
||||||
This property indicates whether the card contains mouse.
|
This property indicates whether the card contains mouse.
|
||||||
*/
|
*/
|
||||||
property bool hovered: sensor.containsMouse
|
readonly property bool hovered: sensor.hovered
|
||||||
/*!
|
/*!
|
||||||
\qmlproperty int StatusCommunityCard::titleFontSize
|
\qmlproperty int StatusCommunityCard::titleFontSize
|
||||||
This property holds the title's font size.
|
This property holds the title's font size.
|
||||||
|
@ -61,7 +61,7 @@ Rectangle {
|
||||||
\qmlproperty int StatusCommunityCard::descriptionFontSize
|
\qmlproperty int StatusCommunityCard::descriptionFontSize
|
||||||
This property holds the description's font size.
|
This property holds the description's font size.
|
||||||
*/
|
*/
|
||||||
property int descriptionFontSize: 15
|
property int descriptionFontSize: cardSize === StatusCommunityCard.Size.Big ? 15 : 13
|
||||||
/*!
|
/*!
|
||||||
\qmlproperty string StatusCommunityCard::communityId
|
\qmlproperty string StatusCommunityCard::communityId
|
||||||
This property holds the community identifier value.
|
This property holds the community identifier value.
|
||||||
|
@ -136,14 +136,14 @@ Rectangle {
|
||||||
property url tokenLogo: ""
|
property url tokenLogo: ""
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\qmlproperty Item StatusCommunityCard::rigthHeaderComponent
|
\qmlproperty Component StatusCommunityCard::rigthHeaderComponent
|
||||||
This property holds an extra info header component that will be displayed on top right of the card.
|
This property holds an extra info header component that will be displayed on top right of the card.
|
||||||
Example: Community token permissions row.
|
Example: Community token permissions row.
|
||||||
*/
|
*/
|
||||||
property alias rigthHeaderComponent: rightHeaderLoader.sourceComponent
|
property alias rigthHeaderComponent: rightHeaderLoader.sourceComponent
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\qmlproperty Item StatusCommunityCard::bottomRowComponent
|
\qmlproperty Component StatusCommunityCard::bottomRowComponent
|
||||||
This property holds an extra info bottom row component that will be displayed on bottom left of the card.
|
This property holds an extra info bottom row component that will be displayed on bottom left of the card.
|
||||||
Example: Community token permissions row.
|
Example: Community token permissions row.
|
||||||
*/
|
*/
|
||||||
|
@ -168,7 +168,13 @@ Rectangle {
|
||||||
\qmlsignal StatusCommunityCard::clicked(string communityId)
|
\qmlsignal StatusCommunityCard::clicked(string communityId)
|
||||||
This signal is emitted when the card item is clicked.
|
This signal is emitted when the card item is clicked.
|
||||||
*/
|
*/
|
||||||
signal clicked(var mouse, string communityId)
|
signal clicked(string communityId)
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\qmlsignal StatusCommunityCard::rightClicked(string communityId)
|
||||||
|
This signal is emitted when the card item is clicked with RMB.
|
||||||
|
*/
|
||||||
|
signal rightClicked(string communityId)
|
||||||
|
|
||||||
QtObject {
|
QtObject {
|
||||||
id: d
|
id: d
|
||||||
|
@ -208,15 +214,16 @@ Rectangle {
|
||||||
implicitHeight: d.totalHeigth
|
implicitHeight: d.totalHeigth
|
||||||
radius: d.bannerRadius
|
radius: d.bannerRadius
|
||||||
color: "transparent"
|
color: "transparent"
|
||||||
|
border.color: Theme.palette.directColor8
|
||||||
layer.enabled: true
|
layer.enabled: true
|
||||||
layer.effect: DropShadow {
|
layer.effect: DropShadow {
|
||||||
source: root
|
source: root
|
||||||
horizontalOffset: 0
|
horizontalOffset: 0
|
||||||
verticalOffset: 2
|
verticalOffset: 2
|
||||||
radius: sensor.containsMouse ? d.bannerRadiusHovered : d.bannerRadius
|
radius: root.hovered ? d.bannerRadiusHovered : d.bannerRadius
|
||||||
samples: 25
|
samples: 25
|
||||||
spread: 0
|
spread: 0
|
||||||
color: sensor.containsMouse ? Theme.palette.backdropColor : Theme.palette.dropShadow
|
color: root.hovered ? Theme.palette.backdropColor : Theme.palette.dropShadow
|
||||||
}
|
}
|
||||||
|
|
||||||
// Community banner:
|
// Community banner:
|
||||||
|
@ -293,8 +300,6 @@ Rectangle {
|
||||||
height: d.cardHeigth
|
height: d.cardHeigth
|
||||||
color: d.cardColor
|
color: d.cardColor
|
||||||
radius: d.cardRadius
|
radius: d.cardRadius
|
||||||
border.color: root.border.color
|
|
||||||
clip: true
|
|
||||||
|
|
||||||
// Right header extra info component
|
// Right header extra info component
|
||||||
Loader {
|
Loader {
|
||||||
|
@ -315,8 +320,7 @@ Rectangle {
|
||||||
anchors.rightMargin: d.margins
|
anchors.rightMargin: d.margins
|
||||||
spacing: (root.cardSize === StatusCommunityCard.Size.Big) ? 6 : 0
|
spacing: (root.cardSize === StatusCommunityCard.Size.Big) ? 6 : 0
|
||||||
StatusBaseText {
|
StatusBaseText {
|
||||||
Layout.alignment: Qt.AlignVCenter
|
Layout.fillWidth: true
|
||||||
Layout.fillWidth: (root.cardSize === StatusCommunityCard.Size.Big)
|
|
||||||
Layout.preferredHeight: 22
|
Layout.preferredHeight: 22
|
||||||
text: root.name
|
text: root.name
|
||||||
font.weight: d.titleFontWeight
|
font.weight: d.titleFontWeight
|
||||||
|
@ -326,16 +330,13 @@ Rectangle {
|
||||||
}
|
}
|
||||||
StatusBaseText {
|
StatusBaseText {
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.fillHeight: (root.cardSize === StatusCommunityCard.Size.Big)
|
|
||||||
Layout.preferredHeight: 16
|
|
||||||
text: root.description
|
text: root.description
|
||||||
font.pixelSize: root.descriptionFontSize
|
font.pixelSize: root.descriptionFontSize
|
||||||
lineHeight: 1.2
|
lineHeight: 1.2
|
||||||
color: root.descriptionFontColor
|
color: root.descriptionFontColor
|
||||||
maximumLineCount: 2
|
maximumLineCount: root.cardSize === StatusCommunityCard.Size.Big ? 2 : 1
|
||||||
wrapMode: Text.WordWrap
|
wrapMode: Text.WordWrap
|
||||||
elide: Text.ElideRight
|
elide: Text.ElideRight
|
||||||
clip: true
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ColumnLayout {
|
ColumnLayout {
|
||||||
|
@ -347,7 +348,6 @@ Rectangle {
|
||||||
anchors.bottomMargin: d.margins
|
anchors.bottomMargin: d.margins
|
||||||
spacing: (root.cardSize === StatusCommunityCard.Size.Big) ? 18 : 0
|
spacing: (root.cardSize === StatusCommunityCard.Size.Big) ? 18 : 0
|
||||||
Row {
|
Row {
|
||||||
Layout.alignment: Qt.AlignVCenter
|
|
||||||
spacing: 20
|
spacing: 20
|
||||||
// Members
|
// Members
|
||||||
visible: root.memberCountVisible
|
visible: root.memberCountVisible
|
||||||
|
@ -364,7 +364,7 @@ Rectangle {
|
||||||
id: membersTxt
|
id: membersTxt
|
||||||
Layout.alignment: Qt.AlignVCenter
|
Layout.alignment: Qt.AlignVCenter
|
||||||
text: d.numberFormat(root.members)
|
text: d.numberFormat(root.members)
|
||||||
font.pixelSize: 15
|
font.pixelSize: root.descriptionFontSize
|
||||||
color: d.fontColor
|
color: d.fontColor
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -382,7 +382,7 @@ Rectangle {
|
||||||
id: activeUsersTxt
|
id: activeUsersTxt
|
||||||
Layout.alignment: Qt.AlignVCenter
|
Layout.alignment: Qt.AlignVCenter
|
||||||
text: d.numberFormat(root.activeUsers)
|
text: d.numberFormat(root.activeUsers)
|
||||||
font.pixelSize: 15
|
font.pixelSize: root.descriptionFontSize
|
||||||
color: d.fontColor
|
color: d.fontColor
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -404,16 +404,16 @@ Rectangle {
|
||||||
|
|
||||||
// TODO: Replace by `StatusListItemTagRow` - To be done!
|
// TODO: Replace by `StatusListItemTagRow` - To be done!
|
||||||
content: Row {
|
content: Row {
|
||||||
spacing: 8
|
spacing: 4
|
||||||
clip: true
|
|
||||||
|
|
||||||
Repeater {
|
Repeater {
|
||||||
model: root.categories
|
model: root.categories
|
||||||
delegate: StatusListItemTag {
|
delegate: StatusListItemTag {
|
||||||
bgColor: "transparent"
|
bgColor: "transparent"
|
||||||
bgRadius: 20
|
bgRadius: 20
|
||||||
bgBorderColor: Theme.palette.baseColor2
|
bgBorderColor: Theme.palette.directColor8
|
||||||
height: 24
|
height: 24
|
||||||
|
spacing: 0
|
||||||
closeButtonVisible: false
|
closeButtonVisible: false
|
||||||
asset.emoji: model.emoji
|
asset.emoji: model.emoji
|
||||||
asset.width: 24
|
asset.width: 24
|
||||||
|
@ -421,7 +421,7 @@ Rectangle {
|
||||||
asset.color: "transparent"
|
asset.color: "transparent"
|
||||||
asset.isLetterIdenticon: true
|
asset.isLetterIdenticon: true
|
||||||
title: model.name
|
title: model.name
|
||||||
titleText.font.pixelSize: 13
|
titleText.font.pixelSize: 12
|
||||||
titleText.color: d.fontColor
|
titleText.color: d.fontColor
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -514,14 +514,20 @@ Rectangle {
|
||||||
}
|
}
|
||||||
} // End of loading card
|
} // End of loading card
|
||||||
|
|
||||||
MouseArea {
|
HoverHandler {
|
||||||
id: sensor
|
id: sensor
|
||||||
enabled: root.loaded
|
cursorShape: root.loaded ? Qt.PointingHandCursor : undefined
|
||||||
anchors.fill: parent
|
}
|
||||||
cursorShape: root.loaded ? Qt.PointingHandCursor : Qt.ArrowCursor
|
|
||||||
hoverEnabled: true
|
|
||||||
acceptedButtons: Qt.LeftButton | Qt.RightButton
|
|
||||||
|
|
||||||
onClicked: root.clicked(mouse ,root.communityId)
|
TapHandler {
|
||||||
|
enabled: root.loaded
|
||||||
|
acceptedButtons: Qt.LeftButton
|
||||||
|
onTapped: root.clicked(root.communityId)
|
||||||
|
onLongPressed: root.rightClicked(root.communityId)
|
||||||
|
}
|
||||||
|
TapHandler {
|
||||||
|
enabled: root.loaded
|
||||||
|
acceptedButtons: Qt.RightButton
|
||||||
|
onTapped: root.rightClicked(root.communityId)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import QtQuick 2.14
|
import QtQuick 2.14
|
||||||
|
|
||||||
|
import StatusQ 0.1
|
||||||
import StatusQ.Core 0.1
|
import StatusQ.Core 0.1
|
||||||
import StatusQ.Controls 0.1
|
import StatusQ.Controls 0.1
|
||||||
|
|
||||||
|
@ -53,19 +54,21 @@ Item {
|
||||||
}
|
}
|
||||||
|
|
||||||
filters: [
|
filters: [
|
||||||
ExpressionFilter {
|
FastExpressionFilter {
|
||||||
enabled: root.filterString !== ""
|
enabled: root.filterString !== ""
|
||||||
expression: {
|
expression: {
|
||||||
root.filterString
|
root.filterString
|
||||||
return model.name.toUpperCase().indexOf(root.filterString.toUpperCase()) !== -1
|
return model.name.toUpperCase().indexOf(root.filterString.toUpperCase()) !== -1
|
||||||
}
|
}
|
||||||
|
expectedRoles: ["name"]
|
||||||
},
|
},
|
||||||
ExpressionFilter {
|
FastExpressionFilter {
|
||||||
enabled: root.mode !== StatusCommunityTags.Highlight
|
enabled: root.mode !== StatusCommunityTags.Highlight
|
||||||
expression: {
|
expression: {
|
||||||
root.mode
|
root.mode
|
||||||
return filterModel.selectionPredicate(model.selected)
|
return filterModel.selectionPredicate(model.selected)
|
||||||
}
|
}
|
||||||
|
expectedRoles: ["selected"]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
@ -93,6 +93,7 @@ StatusScrollView {
|
||||||
collectiblesModel: root.collectiblesModel
|
collectiblesModel: root.collectiblesModel
|
||||||
model: card.permissionsList
|
model: card.permissionsList
|
||||||
requirementsMet: card.requirementsMet
|
requirementsMet: card.requirementsMet
|
||||||
|
overlappingBorder: 0
|
||||||
}
|
}
|
||||||
|
|
||||||
onClicked: root.cardClicked(communityId)
|
onClicked: root.cardClicked(communityId)
|
||||||
|
|
|
@ -132,12 +132,13 @@ Item {
|
||||||
onClicked: {
|
onClicked: {
|
||||||
if (root.readOnly)
|
if (root.readOnly)
|
||||||
return
|
return
|
||||||
if (mouse.button === Qt.LeftButton) {
|
Global.switchToCommunity(model.id)
|
||||||
Global.switchToCommunity(model.id);
|
root.closeRequested()
|
||||||
root.closeRequested();
|
}
|
||||||
} else {
|
onRightClicked: {
|
||||||
Global.openMenu(delegatesActionsMenu, this, { communityId: model.id, url: Utils.getCommunityShareLink(model.id) });
|
if (root.readOnly)
|
||||||
}
|
return
|
||||||
|
Global.openMenu(delegatesActionsMenu, this, { communityId: model.id, url: Utils.getCommunityShareLink(model.id) })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue