Files
status-qml/src/StatusQ/Components/StatusCommunityCard.qml
T

470 lines
16 KiB
QML
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import QtQuick 2.13
import QtQuick.Layouts 1.14
import QtGraphicalEffects 1.0
import StatusQ.Core 0.1
import StatusQ.Core.Theme 0.1
/*!
\qmltype StatusCommunityCard
\inherits Rectangle
\inqmlmodule StatusQ.Components
\since StatusQ.Components 0.1
\brief It is a community card item that provides relevant information about a community model. Inherits \l{https://doc.qt.io/qt-5/qml-qtquick-rectangle.html}{Rectangle}.
The \c StatusCommunityCard is a community card clickable item that represents a data model. The data model is commonly a JavaScript array or a ListModel object.
Example of how the component looks like:
\image status_community_card.png
Example of how to use it:
\qml
StatusCommunityCard {
locale: "en"
communityId: model.communityId
loaded: model.available
logo: model.icon
name: model.name
description: model.description
members: model.members
popularity: model.popularity
categories: model.categories
onClicked: { d.navigateToCommunity(communityId) }
}
\endqml
For a list of components available see StatusQ.
*/
Rectangle {
id: root
/*!
\qmlproperty string StatusCommunityCard::communityId
This property holds the community identifier value.
*/
property string communityId: ""
/*!
\qmlproperty bool StatusCommunityCard::loaded
This property holds a boolean value that represents if the community information is loaded or not.
*/
property bool loaded: true
/*!
\qmlproperty url StatusCommunityCard::logo
This property holds the community logo source.
*/
property url logo: ""
/*!
\qmlproperty string StatusCommunityCard::name
This property holds the community name.
*/
property string name: ""
/*!
\qmlproperty string StatusCommunityCard::description
This property holds the community description.
*/
property string description: ""
/*!
\qmlproperty int StatusCommunityCard::members
This property holds the community members value.
*/
property int members: 0
/*!
\qmlproperty int StatusCommunityCard::activeUsers
This property holds the community active users value.
*/
property int activeUsers: 0
/*!
\qmlproperty int StatusCommunityCard::popularity
This property holds the community popularity (community rate).
*/
property int popularity: 0
/*!
\qmlproperty string StatusCommunityCard::categories
This property holds the data that will be populated as the tags row of the community.
Here an example of the model roles expected:
\qml
categories: ListModel {
ListElement { name: "gaming"; emoji: "🎮"; selected: false}
ListElement { name: "art"; emoji: "🖼️"; selected: false}
ListElement { name: "crypto"; emoji: "💸"; selected: false}
ListElement { name: "nsfw"; emoji: "🍆"; selected: false}
ListElement { name: "markets"; emoji: "💎"; selected: false}
}
\endqml
*/
property ListModel categories: ListModel {}
/*!
\qmlproperty string StatusCommunityCard::locale
This property holds the application locale used to give format to members number representation.
If not provided, default value is "en".
*/
property string locale: "en"
/*!
\qmlproperty url StatusCommunityCard::banner
This property holds the community banner image url.
*/
property url banner: ""
/*!
\qmlproperty color StatusCommunityCard::communityColor
This property holds the community color.
If not provided, default value in Light Theme is "#4360DF" and in Dark Theme is "#88B0FF".
*/
property color communityColor: Theme.palette.primaryColor1
/*!
\qmlproperty bool StatusCommunityCard::isPrivate
This property holds if the community is private.
If not provided, default value is false.
*/
property bool isPrivate: false
/*!
\qmlproperty url StatusCommunityCard::tokenLogo
This property holds the image of the token needed if the community is private.
*/
property url tokenLogo: ""
/*!
\qmlsignal StatusCommunityCard::clicked(string communityId)
This signal is emitted when the card item is clicked.
*/
signal clicked(string communityId)
QtObject {
id: d
property int cardWidth: Theme.dp(335)
property int bannerHeigth: Theme.dp(64)
property int cardHeigth: Theme.dp(190)
property int totalHeigth: Theme.dp(230)
property int margins: Theme.dp(12)
property int bannerRadius: Theme.dp(20)
property int cardRadius: Theme.dp(16)
property color cardColor: Theme.palette.indirectColor1
property color fontColor: Theme.palette.directColor1
property color loadingColor1: Theme.palette.baseColor5
property color loadingColor2: Theme.palette.baseColor4
function numberFormat(number) {
var res = number
const million = 1000000
const ks = 1000
if(number > million) {
res = number / million
res = Number(number / million).toLocaleString(Qt.locale(root.locale), 'f', 1) + 'M'
}
else if(number > ks) {
res = number / ks
res = Number(number / ks).toLocaleString(Qt.locale(root.locale), 'f', 1) + 'K'
}
else
res = Number(number).toLocaleString(Qt.locale(root.locale), 'f', 0)
return res
}
}
implicitWidth: d.cardWidth
implicitHeight: d.totalHeigth
radius: d.bannerRadius
color: "transparent"
layer.enabled: true
layer.effect: DropShadow {
source: root
horizontalOffset: 0
verticalOffset: Theme.dp(2)
radius: sensor.containsMouse ? Theme.dp(30) : d.bannerRadius
samples: 25
spread: 0
color: sensor.containsMouse ? Theme.palette.backdropColor : Theme.palette.dropShadow
}
// Community banner:
Item {
id: banner
anchors.top: parent.top
width: d.cardWidth
height: d.bannerHeigth
Rectangle {
id: mask
anchors.fill: parent
radius: d.bannerRadius
color: root.loaded ? root.communityColor : d.loadingColor2
}
Image {
id: image
source: root.banner
anchors.fill: parent
anchors.centerIn: parent
fillMode: Image.PreserveAspectFit
smooth: true
visible: !root.loaded || !root.banner
}
OpacityMask {
anchors.fill: image
source: image
maskSource: mask
}
}
// Community logo:
Rectangle {
z: content.z + 1
anchors.top: parent.top
anchors.topMargin: Theme.dp(16)
anchors.left: parent.left
anchors.leftMargin: Theme.dp(12)
width: Theme.dp(48)
height: width
radius: width / 2
color: root.loaded ? d.cardColor : d.loadingColor1
StatusRoundedImage {
visible: root.loaded
anchors.centerIn: parent
width: parent.width - Theme.dp(4)
height: width
image.source: root.logo
color: "transparent"
}
} // End of community logo
// Content card
Rectangle {
id: content
z: banner.z + 1
visible: root.loaded
anchors.top: parent.top
anchors.topMargin: Theme.dp(40)
width: d.cardWidth
height: d.cardHeigth
color: d.cardColor
radius: d.cardRadius
clip: true
// Community restriccions
Rectangle {
visible: root.isPrivate
anchors.top: parent.top
anchors.topMargin: Theme.dp(8)
anchors.right: parent.right
anchors.rightMargin: anchors.topMargin
width: Theme.dp(48)
height: Theme.dp(24)
color: d.loadingColor2
radius: Theme.dp(200)
StatusIcon {
anchors.verticalCenter: parent.verticalCenter
anchors.leftMargin: 6
anchors.left: parent.left
icon: "tiny/unlocked"
width: Theme.dp(16)
height: Theme.dp(16)
color: Theme.palette.baseColor1
}
StatusRoundedImage {
anchors.rightMargin: Theme.dp(2)
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
width: Theme.dp(20)
height: width
image.source: root.tokenLogo
color: "transparent"
}
}
// Community info
ColumnLayout {
anchors.fill: parent
anchors.topMargin: Theme.dp(32)
anchors.leftMargin: d.margins
anchors.rightMargin: d.margins
anchors.bottomMargin: d.margins
clip: true
spacing: Theme.dp(6)
StatusBaseText {
Layout.alignment: Qt.AlignVCenter
text: root.name
font.weight: Font.Bold
font.pixelSize: Theme.dp(19)
color: d.fontColor
}
StatusBaseText {
Layout.fillWidth: true
Layout.fillHeight: true
text: root.description
font.pixelSize: Theme.dp(15)
lineHeight: 1.2
color: d.fontColor
maximumLineCount: 2
wrapMode: Text.WordWrap
elide: Text.ElideRight
clip: true
}
}
ColumnLayout {
anchors.fill: parent
anchors.topMargin: Theme.dp(116)
anchors.leftMargin: d.margins
anchors.rightMargin: d.margins
anchors.bottomMargin: d.margins
clip: true
spacing: Theme.dp(18)
Row {
Layout.alignment: Qt.AlignVCenter
spacing: Theme.dp(20)
// Members
Row {
height: membersTxt.height
spacing: Theme.dp(4)
StatusIcon {
anchors.verticalCenter: parent.verticalCenter
icon: "tiny/members"
width: Theme.dp(16)
height: Theme.dp(16)
}
StatusBaseText {
id: membersTxt
Layout.alignment: Qt.AlignVCenter
text: d.numberFormat(root.members)
font.pixelSize: Theme.dp(15)
color: d.fontColor
}
}
// Active users:
Row {
height: activeUsersTxt.height
spacing: Theme.dp(4)
StatusIcon {
anchors.verticalCenter: parent.verticalCenter
icon: "tiny/flash"
width: Theme.dp(14)
height: Theme.dp(14)
}
StatusBaseText {
id: activeUsersTxt
Layout.alignment: Qt.AlignVCenter
text: d.numberFormat(root.activeUsers)
font.pixelSize: Theme.dp(15)
color: d.fontColor
}
}
}
// TODO: Replace by `StatusListItemTagRow` - To be done!
Row {
visible: root.categories.count > 0
Layout.alignment: Qt.AlignVCenter
Layout.fillWidth: true
spacing: Theme.dp(8)
clip: true
Repeater {
model: root.categories
delegate: StatusListItemTag {
border.color: Theme.palette.baseColor2
color: "transparent"
height: Theme.dp(24)
radius: Theme.dp(20)
closeButtonVisible: false
icon.emoji: model.emoji
icon.height: Theme.dp(24)
icon.width: icon.height
icon.color: "transparent"
icon.isLetterIdenticon: true
title: model.name
titleText.font.pixelSize: Theme.dp(13)
titleText.color: d.fontColor
}
}
}
}
} // End of content card
// Loading card
Rectangle {
visible: !root.loaded
anchors.top: parent.top
anchors.topMargin: Theme.dp(40)
width: d.cardWidth
height: d.cardHeigth
color: d.cardColor
radius: d.cardRadius
clip: true
Rectangle {
anchors.top: parent.top
anchors.topMargin: Theme.dp(8)
anchors.right: parent.right
anchors.rightMargin: anchors.topMargin
width: Theme.dp(48)
height: Theme.dp(24)
color: d.loadingColor2
radius: Theme.dp(200)
}
ColumnLayout {
anchors.fill: parent
anchors.topMargin: Theme.dp(32)
anchors.margins: d.margins
clip: true
spacing: Theme.dp(9)
Rectangle {
width: Theme.dp(84)
height: Theme.dp(16)
color: d.loadingColor1
radius: Theme.dp(5)
}
Rectangle {
width: Theme.dp(311)
height: Theme.dp(16)
color: d.loadingColor1
radius: Theme.dp(5)
}
Rectangle {
width: Theme.dp(271)
height: Theme.dp(16)
color: d.loadingColor1
radius: Theme.dp(5)
}
Row {
Layout.topMargin: Theme.dp(13)
spacing: Theme.dp(16)
Repeater {
model: 2
delegate: Row {
spacing: Theme.dp(4)
Rectangle {
width: Theme.dp(14)
height: Theme.dp(14)
color: d.loadingColor1
radius: width / 2
}
Rectangle {
width: 50
height: 12
color: d.loadingColor2
radius: 5
}
}
}
}
Row {
Layout.topMargin: Theme.dp(12)
spacing: Theme.dp(8)
Repeater {
model: 3
delegate:
Rectangle {
width: Theme.dp(76)
height: Theme.dp(24)
color: d.loadingColor2
radius: Theme.dp(20)
}
}
}
}
} // End of loading card
MouseArea {
id: sensor
enabled: root.loaded
anchors.fill: parent
cursorShape: root.loaded ? Qt.PointingHandCursor : Qt.ArrowCursor
hoverEnabled: true
onClicked: root.clicked(root.communityId)
}
}