diff --git a/ui/StatusQ/sandbox/controls/ListItems.qml b/ui/StatusQ/sandbox/controls/ListItems.qml index 0d7ac34ff4..15fe32298b 100644 --- a/ui/StatusQ/sandbox/controls/ListItems.qml +++ b/ui/StatusQ/sandbox/controls/ListItems.qml @@ -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 + } } diff --git a/ui/StatusQ/sandbox/demoapp/StatusAppCommunityView.qml b/ui/StatusQ/sandbox/demoapp/StatusAppCommunityView.qml index df49e54173..9c971ce651 100644 --- a/ui/StatusQ/sandbox/demoapp/StatusAppCommunityView.qml +++ b/ui/StatusQ/sandbox/demoapp/StatusAppCommunityView.qml @@ -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 } } } diff --git a/ui/StatusQ/sandbox/demoapp/data/Models.qml b/ui/StatusQ/sandbox/demoapp/data/Models.qml index dcc5778c29..4c7213e57b 100644 --- a/ui/StatusQ/sandbox/demoapp/data/Models.qml +++ b/ui/StatusQ/sandbox/demoapp/data/Models.qml @@ -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 + } + } } diff --git a/ui/StatusQ/src/StatusQ/Components/StatusListItem.qml b/ui/StatusQ/src/StatusQ/Components/StatusListItem.qml index 07be3f7778..bbcabb1330 100644 --- a/ui/StatusQ/src/StatusQ/Components/StatusListItem.qml +++ b/ui/StatusQ/src/StatusQ/Components/StatusListItem.qml @@ -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 tertiaryTitle: "" + property string label: "" property real leftPadding: 16 property real rightPadding: 16 property bool enabled: true + property int type: StatusListItem.Type.Primary + property list 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 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 diff --git a/ui/StatusQ/src/StatusQ/Components/StatusMemberListItem.qml b/ui/StatusQ/src/StatusQ/Components/StatusMemberListItem.qml new file mode 100644 index 0000000000..8111ba410c --- /dev/null +++ b/ui/StatusQ/src/StatusQ/Components/StatusMemberListItem.qml @@ -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 +} diff --git a/ui/StatusQ/src/StatusQ/Components/StatusSmartIdenticon.qml b/ui/StatusQ/src/StatusQ/Components/StatusSmartIdenticon.qml index c058af76cf..9e053b6951 100644 --- a/ui/StatusQ/src/StatusQ/Components/StatusSmartIdenticon.qml +++ b/ui/StatusQ/src/StatusQ/Components/StatusSmartIdenticon.qml @@ -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 + } } diff --git a/ui/StatusQ/src/StatusQ/Components/qmldir b/ui/StatusQ/src/StatusQ/Components/qmldir index 2e12be9774..568befdd14 100644 --- a/ui/StatusQ/src/StatusQ/Components/qmldir +++ b/ui/StatusQ/src/StatusQ/Components/qmldir @@ -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 diff --git a/ui/StatusQ/statusq.qrc b/ui/StatusQ/statusq.qrc index c4ce56e13c..80dead5b85 100644 --- a/ui/StatusQ/statusq.qrc +++ b/ui/StatusQ/statusq.qrc @@ -318,5 +318,6 @@ src/StatusQ/Controls/StatusBanner.qml src/StatusQ/Controls/StatusProgressBar.qml src/StatusQ/Controls/StatusPasswordStrengthIndicator.qml + src/StatusQ/Components/StatusMemberListItem.qml