feat(StatusMemberListItem): Implement `StatusMemberListItem` (#539)
Create component StatusMemberListItem. Add StatusMemberListItem component in sandbox\controls\ListItems for testing all its variants and demo app. Add new properties in StatusListItem. Reorganize StatusListItem.qml following Qt conventions. Add badge in StatusSmartIndenticon component that allows configure a colored state. Closes #515
This commit is contained in:
parent
a400a4c6a3
commit
2e11b7f203
|
@ -345,4 +345,38 @@ CExPynn1gWf9bx498P7/nzPcxEzGExhBdJGYihtAYQlO+tUZvqrPbqeudo5iJGEJjCE15a3VtodH3q2I
|
|||
title: "Contact requests"
|
||||
requestsCount: 3
|
||||
}
|
||||
|
||||
StatusMemberListItem {
|
||||
nickName: "This is an example"
|
||||
userName: "annabelle"
|
||||
chatKey: "0x043a7ed0e8752236a4688563652fd0296453cef00a5dcddbe252dc74f72cc1caa97a2b65e4a1a52d9c30a84c9966beaaaf6b333d659cbdd2e486b443ed1012cf04"
|
||||
trustIndicator: StatusMemberListItem.TrustedType.Verified
|
||||
isMutualContact: true
|
||||
image.source: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAlklEQVR4nOzW0QmDQBAG4SSkl7SUQlJGCrElq9F3QdjjVhh/5nv3cFhY9vUIYQiNITSG0BhCExPynn1gWf9bx498P7/
|
||||
nzPcxEzGExhBdJGYihtAYQlO+tUZvqrPbqeudo5iJGEJjCE15a3VtodH3q2ImYgiNITTlTdG1nUZ5a92VITQxITFiJmIIjSE0htAYQrMHAAD//+wwFVpz+yqXAAAAAElFTkSuQmCC"
|
||||
image.isIdenticon: true
|
||||
isOnline: true
|
||||
}
|
||||
|
||||
StatusMemberListItem {
|
||||
nickName: "carmen.eth"
|
||||
isOnline: false
|
||||
trustIndicator: StatusMemberListItem.TrustedType.Untrustworthy
|
||||
}
|
||||
|
||||
StatusMemberListItem {
|
||||
nickName: "This girl I know from work"
|
||||
userName: "annabelle"
|
||||
isOnline: true
|
||||
}
|
||||
|
||||
StatusMemberListItem {
|
||||
nickName: "Mark Cuban"
|
||||
userName: "annabelle"
|
||||
chatKey: "0x043a7ed0e8752236a4688563652fd0296453cef00a5dcddbe252dc74f72cc1caa97a2b65e4a1a52d9c30a84c9966beaaaf6b333d659cbdd2e486b443ed1012cf04"
|
||||
isMutualContact: true
|
||||
image.source: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAlklEQVR4nOzW0QmDQBAG4SSkl7SUQlJGCrElq9F3QdjjVhh/5nv3cFhY9vUIYQiNITSG0BhCExPynn1gWf9bx498P7/
|
||||
nzPcxEzGExhBdJGYihtAYQlO+tUZvqrPbqeudo5iJGEJjCE15a3VtodH3q2ImYgiNITTlTdG1nUZ5a92VITQxITFiJmIIjSE0htAYQrMHAAD//+wwFVpz+yqXAAAAAElFTkSuQmCC"
|
||||
image.isIdenticon: true
|
||||
}
|
||||
}
|
||||
|
|
|
@ -257,26 +257,17 @@ StatusAppThreePanelLayout {
|
|||
anchors.bottom: parent.bottom
|
||||
anchors.bottomMargin: 16
|
||||
boundsBehavior: Flickable.StopAtBounds
|
||||
model: ["John", "Nick", "Maria", "Mike"]
|
||||
delegate: Row {
|
||||
width: parent.width
|
||||
height: 30
|
||||
spacing: 8
|
||||
Rectangle {
|
||||
width: 24
|
||||
height: 24
|
||||
radius: width/2
|
||||
color: Qt.rgba(Math.random(), Math.random(), Math.random(), 255)
|
||||
}
|
||||
StatusBaseText {
|
||||
height: parent.height
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
opacity: (rightPanel.width > 50) ? 1.0 : 0.0
|
||||
visible: (opacity > 0.1)
|
||||
font.pixelSize: 15
|
||||
color: Theme.palette.directColor1
|
||||
text: modelData
|
||||
}
|
||||
model: Models.membersListModel
|
||||
delegate: StatusMemberListItem {
|
||||
implicitWidth: parent.width
|
||||
nickName: model.nickName
|
||||
userName: model.userName
|
||||
chatKey: model.chatKey
|
||||
trustIndicator: model.trustIndicator
|
||||
isMutualContact: model.isMutualContact
|
||||
image.source: model.source
|
||||
image.isIdenticon: model.isIdenticon
|
||||
isOnline: model.isOnline
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -730,4 +730,43 @@ CExPynn1gWf9bx498P7/nzPcxEzGExhBdJGYihtAYQlO+tUZvqrPbqeudo5iJGEJjCE15a3VtodH3q2I
|
|||
hasExpired: false
|
||||
}
|
||||
}
|
||||
|
||||
property var membersListModel: ListModel {
|
||||
id: membersList
|
||||
ListElement {
|
||||
nickName: "This is an example"
|
||||
userName: "annabelle"
|
||||
chatKey: "0x043a7ed0e8752236a4688563652fd0296453cef00a5dcddbe252dc74f72cc1caa97a2b65e4a1a52d9c30a84c9966beaaaf6b333d659cbdd2e486b443ed1012cf04"
|
||||
trustIndicator: StatusMemberListItem.TrustedType.Verified
|
||||
isMutualContact: true
|
||||
isOnline: true
|
||||
source: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAlklEQVR4nOzW0QmDQBAG4SSkl7SUQlJGCrElq9F3QdjjVhh/5nv3cFhY9vUIYQiNITSG0BhCExPynn1gWf9bx498P7/
|
||||
nzPcxEzGExhBdJGYihtAYQlO+tUZvqrPbqeudo5iJGEJjCE15a3VtodH3q2ImYgiNITTlTdG1nUZ5a92VITQxITFiJmIIjSE0htAYQrMHAAD//+wwFVpz+yqXAAAAAElFTkSuQmCC"
|
||||
isIdenticon: true
|
||||
}
|
||||
ListElement {
|
||||
nickName: "carmen.eth"
|
||||
trustIndicator: StatusMemberListItem.TrustedType.Untrustworthy
|
||||
isOnline: false
|
||||
}
|
||||
ListElement {
|
||||
nickName: "This girl I know from work"
|
||||
userName: "annabelle"
|
||||
isOnline: true
|
||||
source: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAiElEQVR4nOzXUQpAQBRGYWQvLNAyLJDV8C5qpiGnv/M9al5Ot27X0IUwhMYQGkNoDKGJCRlLH67bftx9X+ap/+P9VcxEDK
|
||||
ExhKZ4a9Uq3TZviZmIITSG0DRvlqcbqVbrlouZiCE0htD4h0hjCI0hNN5aNIbQGKKPxEzEEBpDaAyhMYTmDAAA//+gYCErzmCpCQAAAABJRU5ErkJggg=="
|
||||
isIdenticon: true
|
||||
}
|
||||
ListElement {
|
||||
nickName: "Mark Cuban"
|
||||
userName: "annabelle"
|
||||
chatKey: "0x043a7ed0e8752236a4688563652fd0296453cef00a5dcddbe252dc74f72cc1caa97a2b65e4a1a52d9c30a84c9966beaaaf6b333d659cbdd2e486b443ed1012cf04"
|
||||
trustIndicator: StatusMemberListItem.TrustedType.Untrustworthy
|
||||
isMutualContact: true
|
||||
isOnline: false
|
||||
source: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAlklEQVR4nOzW0QmDQBAG4SSkl7SUQlJGCrElq9F3QdjjVhh/5nv3cFhY9vUIYQiNITSG0BhCExPynn1gWf9bx498P7/
|
||||
nzPcxEzGExhBdJGYihtAYQlO+tUZvqrPbqeudo5iJGEJjCE15a3VtodH3q2ImYgiNITTlTdG1nUZ5a92VITQxITFiJmIIjSE0htAYQrMHAAD//+wwFVpz+yqXAAAAAElFTkSuQmCC"
|
||||
isIdenticon: true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,43 +9,21 @@ import StatusQ.Controls 0.1
|
|||
Rectangle {
|
||||
id: statusListItem
|
||||
|
||||
implicitWidth: 448
|
||||
implicitHeight: Math.max(64, statusListItemTitleArea.height + 16)
|
||||
|
||||
enum Type {
|
||||
Primary,
|
||||
Secondary,
|
||||
Danger
|
||||
}
|
||||
|
||||
color: {
|
||||
if (sensor.containsMouse) {
|
||||
switch(type) {
|
||||
case StatusListItem.Type.Primary:
|
||||
return Theme.palette.baseColor2
|
||||
case StatusListItem.Type.Secondary:
|
||||
return Theme.palette.statusListItem.secondaryHoverBackgroundColor
|
||||
case StatusListItem.Type.Danger:
|
||||
return Theme.palette.dangerColor3
|
||||
}
|
||||
}
|
||||
return Theme.palette.statusListItem.backgroundColor
|
||||
}
|
||||
|
||||
radius: 8
|
||||
|
||||
property string itemId: ""
|
||||
property string titleId: ""
|
||||
|
||||
property string title: ""
|
||||
property string titleAsideText: ""
|
||||
property bool titleIcon1Visible
|
||||
property bool titleIcon2Visible
|
||||
property string subTitle: ""
|
||||
property string tertiaryTitle: ""
|
||||
property alias badge: statusListItemBadge
|
||||
|
||||
property string label: ""
|
||||
property real leftPadding: 16
|
||||
property real rightPadding: 16
|
||||
property bool enabled: true
|
||||
property int type: StatusListItem.Type.Primary
|
||||
property list<Item> components
|
||||
|
||||
property StatusIconSettings icon: StatusIconSettings {
|
||||
height: isLetterIdenticon ? 40 : 20
|
||||
width: isLetterIdenticon ? 40 : 20
|
||||
|
@ -73,24 +51,69 @@ Rectangle {
|
|||
height: 40
|
||||
isIdenticon: false
|
||||
}
|
||||
property string label: ""
|
||||
|
||||
property int type: StatusListItem.Type.Primary
|
||||
property StatusIconSettings titleIcon1: StatusIconSettings {
|
||||
width: dummyImage.width
|
||||
height: dummyImage.height
|
||||
background: StatusIconBackgroundSettings {
|
||||
width: 10
|
||||
height: 10
|
||||
}
|
||||
// Only used to get implicit width and height from the actual image
|
||||
property Image dummyImage: Image {
|
||||
source: titleIcon1.name ? "../../assets/img/icons/" + titleIcon1.name + ".svg": ""
|
||||
visible: false
|
||||
}
|
||||
}
|
||||
property StatusIconSettings titleIcon2: StatusIconSettings {
|
||||
width: dummyImage.width
|
||||
height: dummyImage.height
|
||||
background: StatusIconBackgroundSettings {
|
||||
width: 10
|
||||
height: 10
|
||||
}
|
||||
// Only used to get implicit width and height from the actual image
|
||||
property Image dummyImage: Image {
|
||||
source: titleIcon2.name ? "../../assets/img/icons/" + titleIcon2.name + ".svg": ""
|
||||
visible: false
|
||||
}
|
||||
}
|
||||
|
||||
property alias sensor: sensor
|
||||
|
||||
property alias badge: statusListItemBadge
|
||||
property alias statusListItemIcon: iconOrImage
|
||||
property alias statusListItemTitle: statusListItemTitle
|
||||
property alias statusListItemTitleAside: statusListItemTitleAsideText
|
||||
property alias statusListItemTitleArea: statusListItemTitleArea
|
||||
property alias statusListItemSubTitle: statusListItemSubTitle
|
||||
property alias statusListItemTertiaryTitle: statusListItemTertiaryTitle
|
||||
property alias statusListItemComponentsSlot: statusListItemComponentsSlot
|
||||
|
||||
property list<Item> components
|
||||
|
||||
signal clicked(string itemId)
|
||||
signal titleClicked(string titleId)
|
||||
|
||||
enum Type {
|
||||
Primary,
|
||||
Secondary,
|
||||
Danger
|
||||
}
|
||||
|
||||
implicitWidth: 448
|
||||
implicitHeight: Math.max(64, statusListItemTitleArea.height + 16)
|
||||
color: {
|
||||
if (sensor.containsMouse) {
|
||||
switch(type) {
|
||||
case StatusListItem.Type.Primary:
|
||||
return Theme.palette.baseColor2
|
||||
case StatusListItem.Type.Secondary:
|
||||
return Theme.palette.statusListItem.secondaryHoverBackgroundColor
|
||||
case StatusListItem.Type.Danger:
|
||||
return Theme.palette.dangerColor3
|
||||
}
|
||||
}
|
||||
return Theme.palette.statusListItem.backgroundColor
|
||||
}
|
||||
radius: 8
|
||||
|
||||
onComponentsChanged: {
|
||||
if (components.length) {
|
||||
for (let idx in components) {
|
||||
|
@ -125,6 +148,7 @@ Rectangle {
|
|||
active: statusListItem.icon.isLetterIdenticon ||
|
||||
!!statusListItem.icon.name ||
|
||||
!!statusListItem.image.source.toString()
|
||||
badge.border.color: statusListItem.color
|
||||
}
|
||||
|
||||
Item {
|
||||
|
@ -144,7 +168,8 @@ Rectangle {
|
|||
height: visible ? contentHeight : 0
|
||||
wrapMode: Text.WrapAtWordBoundaryOrAnywhere
|
||||
anchors.left: parent.left
|
||||
anchors.right: !statusListItem.titleAsideText ? parent.right : undefined
|
||||
anchors.right: !statusListItem.titleAsideText && !statusListItem.titleIcon1Visible && !statusListItem.titleIcon2Visible
|
||||
? parent.right : undefined
|
||||
color: {
|
||||
if (!statusListItem.enabled) {
|
||||
return Theme.palette.baseColor1
|
||||
|
@ -182,6 +207,38 @@ Rectangle {
|
|||
visible: !!statusListItem.titleAsideText
|
||||
}
|
||||
|
||||
Row {
|
||||
id: titleIconsRow
|
||||
spacing: 4
|
||||
anchors.left: !statusListItem.titleAsideText ? statusListItemTitle.right : statusListItemTitleAsideText.right
|
||||
anchors.verticalCenter: statusListItemTitle.verticalCenter
|
||||
anchors.leftMargin: titleIconsRow.spacing
|
||||
|
||||
StatusRoundIcon {
|
||||
visible: statusListItem.titleIcon1Visible
|
||||
icon.name: statusListItem.titleIcon1.name
|
||||
icon.width: statusListItem.titleIcon1.width
|
||||
icon.height: statusListItem.titleIcon1.height
|
||||
icon.rotation: statusListItem.titleIcon1.rotation
|
||||
icon.color: statusListItem.titleIcon1.color
|
||||
icon.background.color: statusListItem.titleIcon1.background.color
|
||||
icon.background.width: statusListItem.titleIcon1.background.width
|
||||
icon.background.height: statusListItem.titleIcon1.background.height
|
||||
}
|
||||
|
||||
StatusRoundIcon {
|
||||
visible: statusListItem.titleIcon2Visible
|
||||
icon.name: statusListItem.titleIcon2.name
|
||||
icon.width: statusListItem.titleIcon2.width
|
||||
icon.height: statusListItem.titleIcon2.height
|
||||
icon.rotation: statusListItem.titleIcon2.rotation
|
||||
icon.color: statusListItem.titleIcon2.color
|
||||
icon.background.color: statusListItem.titleIcon2.background.color
|
||||
icon.background.width: statusListItem.titleIcon2.background.width
|
||||
icon.background.height: statusListItem.titleIcon2.background.height
|
||||
}
|
||||
}
|
||||
|
||||
StatusBaseText {
|
||||
id: statusListItemSubTitle
|
||||
anchors.top: statusListItemTitle.bottom
|
||||
|
|
|
@ -0,0 +1,76 @@
|
|||
import QtQuick 2.0
|
||||
import StatusQ.Core.Theme 0.1
|
||||
import StatusQ.Core 0.1
|
||||
|
||||
|
||||
StatusListItem {
|
||||
id: root
|
||||
|
||||
property string nickName: ""
|
||||
property string userName: ""
|
||||
property string chatKey: ""
|
||||
property bool isMutualContact: false
|
||||
property var trustIndicator: StatusMemberListItem.TrustedType.None
|
||||
property bool isOnline: false
|
||||
|
||||
enum TrustedType {
|
||||
None, //0
|
||||
Verified, //1
|
||||
Untrustworthy //2
|
||||
}
|
||||
|
||||
// Subtitle composition:
|
||||
function composeSubtitile() {
|
||||
var compose = ""
|
||||
if(root.userName !== "")
|
||||
compose = "(" + root.userName + ")"
|
||||
|
||||
if(compose !== "" && root.chatKey !== "")
|
||||
// Composition
|
||||
compose += " • " + composeShortKeyChat(root.chatKey)
|
||||
|
||||
else if(root.chatKey !== "")
|
||||
compose = composeShortKeyChat(root.chatKey)
|
||||
|
||||
return compose
|
||||
}
|
||||
|
||||
// Short keychat composition:
|
||||
function composeShortKeyChat(chatKey) {
|
||||
return chatKey.substring(0, 5) + "..." + chatKey.substring(chatKey.length - 3)
|
||||
}
|
||||
|
||||
// root object settings:
|
||||
title: root.nickName
|
||||
titleIcon1Visible: root.isMutualContact
|
||||
titleIcon2Visible: root.trustIndicator !== StatusMemberListItem.TrustedType.None
|
||||
subTitle: composeSubtitile()
|
||||
statusListItemSubTitle.font.pixelSize: 10
|
||||
icon.isLetterIdenticon: !root.image.source.toString()
|
||||
statusListItemIcon.badge.visible: true
|
||||
statusListItemIcon.badge.color: root.isOnline ? Theme.palette.successColor1 : Theme.palette.baseColor1
|
||||
color: sensor.containsMouse ? Theme.palette.baseColor2 : Theme.palette.baseColor4
|
||||
|
||||
// Default sizes/positions by design
|
||||
implicitWidth: 256
|
||||
implicitHeight: Math.max(56, statusListItemTitleArea.height + leftPadding)
|
||||
leftPadding: 8
|
||||
image.width: 32
|
||||
image.height: 32
|
||||
icon.width: 32
|
||||
icon.height: 32
|
||||
statusListItemIcon.anchors.verticalCenter: sensor.verticalCenter
|
||||
statusListItemIcon.anchors.top: undefined
|
||||
statusListItemIcon.badge.border.width: 2
|
||||
statusListItemIcon.badge.implicitHeight: 12 // 8 px + 2 px * 2 borders
|
||||
statusListItemIcon.badge.implicitWidth: 12 // 8 px + 2 px * 2 borders
|
||||
|
||||
// Trusted type icons definition:
|
||||
titleIcon1.name: "tiny/tiny-contact"
|
||||
titleIcon1.color: Theme.palette.indirectColor1
|
||||
titleIcon1.background.color: Theme.palette.primaryColor1
|
||||
// None and Untrustworthy types, same aspect (Icon will not be visible in case of None type):
|
||||
titleIcon2.name: trustIndicator === StatusMemberListItem.TrustedType.Verified ? "tiny/tiny-checkmark" : "tiny/subtract"
|
||||
titleIcon2.color: Theme.palette.indirectColor1
|
||||
titleIcon2.background.color: trustIndicator === StatusMemberListItem.TrustedType.Verified ? Theme.palette.primaryColor1 : Theme.palette.dangerColor1
|
||||
}
|
|
@ -7,6 +7,9 @@ Loader {
|
|||
|
||||
property string name: ""
|
||||
|
||||
// Badge color properties must be set if badgeItem.visible = true
|
||||
property alias badge: statusBadge
|
||||
|
||||
property StatusIconSettings icon: StatusIconSettings {
|
||||
width: 40
|
||||
height: 40
|
||||
|
@ -75,4 +78,16 @@ Loader {
|
|||
letterSize: statusSmartIdenticon.icon.letterSize
|
||||
}
|
||||
}
|
||||
|
||||
// State component
|
||||
StatusBadge {
|
||||
id: statusBadge
|
||||
visible: false
|
||||
anchors.bottom: statusSmartIdenticon.bottom
|
||||
anchors.right: statusSmartIdenticon.right
|
||||
border.width: 3
|
||||
implicitHeight: 15
|
||||
implicitWidth: 15
|
||||
z: 100
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,6 +15,7 @@ StatusLetterIdenticon 0.1 StatusLetterIdenticon.qml
|
|||
StatusListItem 0.1 StatusListItem.qml
|
||||
StatusListSectionHeadline 0.1 StatusListSectionHeadline.qml
|
||||
StatusLoadingIndicator 0.1 StatusLoadingIndicator.qml
|
||||
StatusMemberListItem 0.1 StatusMemberListItem.qml
|
||||
StatusNavigationListItem 0.1 StatusNavigationListItem.qml
|
||||
StatusNavigationPanelHeadline 0.1 StatusNavigationPanelHeadline.qml
|
||||
StatusRoundIcon 0.1 StatusRoundIcon.qml
|
||||
|
|
|
@ -318,5 +318,6 @@
|
|||
<file>src/StatusQ/Controls/StatusBanner.qml</file>
|
||||
<file>src/StatusQ/Controls/StatusProgressBar.qml</file>
|
||||
<file>src/StatusQ/Controls/StatusPasswordStrengthIndicator.qml</file>
|
||||
<file>src/StatusQ/Components/StatusMemberListItem.qml</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
|
Loading…
Reference in New Issue