Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2a8f4127ee | ||
|
|
c4421d3552 | ||
|
|
cdf3059d3d | ||
|
|
5e590056ff | ||
|
|
7b8cf2ffb5 | ||
|
|
6da838c81f | ||
|
|
a2e9f813a5 | ||
|
|
64d6beb4a0 | ||
|
|
84c529d58d | ||
|
|
fe355eebf8 | ||
|
|
b064f9ebd8 | ||
|
|
604bb7a74c | ||
|
|
7d064d6c6e | ||
|
|
1730fe756d | ||
|
|
996717885d | ||
|
|
34c223b581 | ||
|
|
7b35be6691 | ||
|
|
2186259c06 | ||
|
|
69b5cb1988 | ||
|
|
cb900fe494 | ||
|
|
1d618f72f7 | ||
|
|
d5df8b42a7 | ||
|
|
c0639d8b8e | ||
|
|
b816643e2d | ||
|
|
33a3ee3d6e | ||
|
|
2f24b69462 | ||
|
|
40db66f763 | ||
|
|
5361b56e9f | ||
|
|
0e73530b05 | ||
|
|
0f5c1ce4c6 | ||
|
|
b569782d4c | ||
|
|
d69b0598bf | ||
|
|
70834fc187 | ||
|
|
18d385cf2b | ||
|
|
648406c442 | ||
|
|
5f7bd307ef | ||
|
|
890ef86e1c | ||
|
|
0b855bfb48 | ||
|
|
10cd9b23c1 | ||
|
|
bf3578cf7c | ||
|
|
da22cde5e6 | ||
|
|
312858b420 | ||
|
|
a4d0c13662 | ||
|
|
61007c32e9 | ||
|
|
1cadfc051b | ||
|
|
46cd904ced | ||
|
|
9120a0fa1c | ||
|
|
406e4a1177 | ||
|
|
be0f49a8d8 | ||
|
|
24228c5568 | ||
|
|
6056db73cf | ||
|
|
ee3effcdd1 | ||
|
|
07e711e30c | ||
|
|
0b1a910b06 | ||
|
|
81cbab3f66 | ||
|
|
d31dddac7e | ||
|
|
485647d1c3 | ||
|
|
e1db639340 | ||
|
|
b918897241 | ||
|
|
6ba2d8f3e6 | ||
|
|
c01f623305 | ||
|
|
6dc6ebb2fb | ||
|
|
2d031244ca | ||
|
|
9498be05ef | ||
|
|
1b25ddd2b5 | ||
|
|
9741f98b70 | ||
|
|
02923f7947 | ||
|
|
6c5957a492 | ||
|
|
eb96e5e08d | ||
|
|
457e5fe4af | ||
|
|
1c0d4b0133 | ||
|
|
ba79f62fda | ||
|
|
a9c79b0359 | ||
|
|
a668afef35 | ||
|
|
deb8b38b1f | ||
|
|
b4ebc520e1 | ||
|
|
5def2102c7 | ||
|
|
0f511ebc60 | ||
|
|
b09210cf1f | ||
|
|
3bdfc3e528 | ||
|
|
baf5948c90 | ||
|
|
4b1516c990 | ||
|
|
1a5990f24b | ||
|
|
82e1845056 | ||
|
|
75a76afcf1 | ||
|
|
0922cf507a | ||
|
|
32c5f7f8df | ||
|
|
148505ba6b | ||
|
|
d960c6dcec | ||
|
|
bb9f08155f | ||
|
|
934db52126 | ||
|
|
dcef08f3b3 | ||
|
|
20e7b345e1 | ||
|
|
5f8453659d | ||
|
|
c7ff011649 | ||
|
|
2b71ccf50f | ||
|
|
310be728a3 | ||
|
|
e2728285e1 | ||
|
|
1d9abf8e95 | ||
|
|
31e90c2d47 | ||
|
|
ae1e72fb23 | ||
|
|
7710470559 | ||
|
|
2069399979 | ||
|
|
29dd4da2e4 | ||
|
|
394040a039 | ||
|
|
a8e1ed863c | ||
|
|
d7b1ae9fbc | ||
|
|
f0c7d950ea | ||
|
|
1e5d389b53 | ||
|
|
1cda85fc0e | ||
|
|
4999368dfe | ||
|
|
7e4d69be05 | ||
|
|
3abbd3d4cd | ||
|
|
8fc5276090 | ||
|
|
cf4b092112 | ||
|
|
ddf4a8d4f1 | ||
|
|
9c1edc80db | ||
|
|
20bf5b07a6 | ||
|
|
ade6bd2d0d | ||
|
|
125760b934 | ||
|
|
e231c0a6cb | ||
|
|
a16bc6bb6e | ||
|
|
51989c0f5d | ||
|
|
88b7f6eab8 | ||
|
|
2df3c0a03e | ||
|
|
1e9cc07e2d | ||
|
|
6221c0a540 | ||
|
|
ddbffa7f28 | ||
|
|
555ad8bea8 | ||
|
|
a561a3fff8 | ||
|
|
70ec009edd | ||
|
|
31a1c60eb1 | ||
|
|
0a2cf6ab6e | ||
|
|
07fa2a1b0c | ||
|
|
43b8e43303 | ||
|
|
2cec51ff8d | ||
|
|
684f45cc08 | ||
|
|
eae4e0f405 | ||
|
|
b2ac2794bb | ||
|
|
b565a32c7e | ||
|
|
a1835164d9 | ||
|
|
06e931d749 |
@@ -16,3 +16,4 @@ sandbox/qmlcache_loader.cpp
|
||||
doc/html
|
||||
CMakeLists.txt.user
|
||||
.vscode
|
||||
build/
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
cmake_minimum_required(VERSION 3.19)
|
||||
|
||||
project(StatusQ)
|
||||
|
||||
add_subdirectory(tests)
|
||||
|
After Width: | Height: | Size: 44 KiB |
|
After Width: | Height: | Size: 3.4 KiB |
|
After Width: | Height: | Size: 11 KiB |
|
After Width: | Height: | Size: 21 KiB |
|
After Width: | Height: | Size: 7.5 KiB |
|
After Width: | Height: | Size: 40 KiB |
|
After Width: | Height: | Size: 72 KiB |
|
After Width: | Height: | Size: 60 KiB |
|
After Width: | Height: | Size: 35 KiB |
|
After Width: | Height: | Size: 25 KiB |
|
After Width: | Height: | Size: 28 KiB |
|
After Width: | Height: | Size: 49 KiB |
@@ -22,6 +22,7 @@
|
||||
\li \l{StatusDescriptionListItem}
|
||||
\li \l{StatusLetterIdenticon}
|
||||
\li \l{StatusListItem}
|
||||
\li \l{StatusListPicker}
|
||||
\li \l{StatusListSectionHeadline}
|
||||
\li \l{StatusLoadingIndicator}
|
||||
\li \l{StatusMemberListItem}
|
||||
@@ -37,5 +38,6 @@
|
||||
\li \l{StatusMessageDetails}
|
||||
\li \l{StatusTagSelector}
|
||||
\li \l{StatusToastMessage}
|
||||
\li \l{StatusWizardStepper}
|
||||
\endlist
|
||||
*/
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
\li \l{StatusBaseInput}
|
||||
\li \l{StatusIdenticonRing}
|
||||
\li \l{StatusInput}
|
||||
\li \l{StatusItemPicker}
|
||||
\li \l{StatusPickerButton}
|
||||
\li \l{StatusPinInput}
|
||||
\li \l{StatusProgressBar}
|
||||
@@ -43,5 +44,6 @@
|
||||
\li \l{StatusWalletColorSelect}
|
||||
\li \l{StatusRegularExpressionValidator}
|
||||
\li \l{StatusIntValidator}
|
||||
\li \l{StatusSeedPhraseInput}
|
||||
\endlist
|
||||
*/
|
||||
|
||||
@@ -25,10 +25,11 @@ Rectangle {
|
||||
id: appSectionType
|
||||
readonly property int chat: 0
|
||||
readonly property int community: 1
|
||||
readonly property int wallet: 2
|
||||
readonly property int communitiesPortal: 2
|
||||
readonly property int wallet: 3
|
||||
readonly property int browser: 3
|
||||
readonly property int nodeManagement: 4
|
||||
readonly property int profileSettings: 5
|
||||
readonly property int nodeManagement: 5
|
||||
readonly property int profileSettings: 6
|
||||
readonly property int apiDocumentation: 100
|
||||
readonly property int demoApp: 101
|
||||
}
|
||||
@@ -118,6 +119,11 @@ Rectangle {
|
||||
appView.sourceComponent = statusAppChatView
|
||||
demoApp.setActiveItem(model.sectionId)
|
||||
}
|
||||
else if(model.sectionType === appSectionType.communitiesPortal)
|
||||
{
|
||||
appView.sourceComponent = statusCommunityPortalView
|
||||
demoApp.setActiveItem(model.sectionId)
|
||||
}
|
||||
else if(model.sectionType === appSectionType.profileSettings)
|
||||
{
|
||||
appView.sourceComponent = statusAppProfileSettingsView
|
||||
@@ -205,6 +211,11 @@ Rectangle {
|
||||
StatusAppProfileSettingsView { }
|
||||
}
|
||||
|
||||
Component {
|
||||
id: statusCommunityPortalView
|
||||
StatusAppCommunitiesPortalView { }
|
||||
}
|
||||
|
||||
DemoContactRequestsModal {
|
||||
id: demoContactRequestsModal
|
||||
anchors.centerIn: parent
|
||||
|
||||
@@ -7,6 +7,8 @@ Item {
|
||||
id: themeSwitchWrapper
|
||||
signal checkedChanged()
|
||||
|
||||
property alias lightThemeEnabled: switchControl.checked
|
||||
|
||||
width: themeSwitch.width
|
||||
height: themeSwitch.height
|
||||
|
||||
@@ -26,6 +28,7 @@ Item {
|
||||
}
|
||||
|
||||
StatusSwitch {
|
||||
id: switchControl
|
||||
onCheckedChanged: themeSwitchWrapper.checkedChanged()
|
||||
|
||||
StatusToolTip {
|
||||
|
||||
@@ -3,9 +3,10 @@ import QtQuick.Layouts 1.14
|
||||
import QtQuick.Dialogs 1.3
|
||||
|
||||
import StatusQ.Controls 0.1
|
||||
import StatusQ.Popups 0.1
|
||||
import StatusQ.Core 0.1
|
||||
import StatusQ.Core.Theme 0.1
|
||||
|
||||
|
||||
Column {
|
||||
spacing: 10
|
||||
Grid {
|
||||
@@ -173,6 +174,25 @@ Column {
|
||||
loading: true
|
||||
}
|
||||
|
||||
// transparent
|
||||
|
||||
StatusRoundButton {
|
||||
type: StatusRoundButton.Type.Tertiary
|
||||
icon.name: "info"
|
||||
}
|
||||
|
||||
StatusRoundButton {
|
||||
type: StatusRoundButton.Type.Tertiary
|
||||
icon.name: "info"
|
||||
enabled: false
|
||||
}
|
||||
|
||||
StatusRoundButton {
|
||||
type: StatusRoundButton.Type.Tertiary
|
||||
icon.name: "info"
|
||||
loading: true
|
||||
}
|
||||
|
||||
// Rounded blue
|
||||
|
||||
StatusFlatRoundButton {
|
||||
@@ -307,12 +327,20 @@ Column {
|
||||
onClicked: {
|
||||
colorDialog.open();
|
||||
}
|
||||
ColorDialog {
|
||||
id: colorDialog
|
||||
property bool colorSelected: false
|
||||
onAccepted: {
|
||||
colorSelected = true;
|
||||
}
|
||||
}
|
||||
|
||||
StatusColorDialog {
|
||||
id: colorDialog
|
||||
anchors.centerIn: parent
|
||||
property bool colorSelected: false
|
||||
onAccepted: {
|
||||
colorSelected = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Button with emoji
|
||||
StatusButton {
|
||||
text: "Button with Emoji"
|
||||
icon.emoji: "🖼️️"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -189,6 +189,16 @@ GridLayout {
|
||||
value: 40
|
||||
}
|
||||
|
||||
StatusLabeledSlider {
|
||||
width: 360
|
||||
model: [ qsTr("XS"), qsTr("S"), qsTr("M"), qsTr("L"), qsTr("XL"), qsTr("XXL")]
|
||||
}
|
||||
|
||||
StatusLabeledSlider {
|
||||
width: 360
|
||||
model: [ qsTr("50%"), qsTr("100%"), qsTr("150%"), qsTr("200%")]
|
||||
}
|
||||
|
||||
StatusBanner {
|
||||
id: banner
|
||||
width: 360
|
||||
@@ -198,7 +208,7 @@ GridLayout {
|
||||
}
|
||||
|
||||
StatusProgressBar {
|
||||
id: progressBar
|
||||
id: progressBar
|
||||
text: "Weak"
|
||||
value: 0.5
|
||||
fillColor : Theme.palette.pinColor1
|
||||
|
||||
@@ -10,31 +10,96 @@ import StatusQ.Layout 0.1
|
||||
import StatusQ.Popups 0.1
|
||||
|
||||
Column {
|
||||
spacing: 5
|
||||
spacing: 10
|
||||
|
||||
StatusChatToolBar {
|
||||
chatInfoButton.title: "Some contact"
|
||||
chatInfoButton.subTitle: "Contact"
|
||||
chatInfoButton.icon.color: Theme.palette.miscColor7
|
||||
chatInfoButton.type: StatusChatInfoButton.Type.OneToOneChat
|
||||
toolbarComponent: chatInfoButton1
|
||||
width: 518
|
||||
|
||||
Component {
|
||||
id: chatInfoButton1
|
||||
|
||||
StatusChatInfoButton {
|
||||
width: Math.min(implicitWidth, parent.width)
|
||||
title: "Some contact"
|
||||
subTitle: "Contact"
|
||||
icon.color: Theme.palette.miscColor7
|
||||
type: StatusChatInfoButton.Type.OneToOneChat
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
StatusChatToolBar {
|
||||
chatInfoButton.title: "Some contact"
|
||||
chatInfoButton.subTitle: "Contact"
|
||||
chatInfoButton.icon.color: Theme.palette.miscColor7
|
||||
chatInfoButton.type: StatusChatInfoButton.Type.PublicChat
|
||||
chatInfoButton.pinnedMessagesCount: 1
|
||||
chatInfoButton.muted: true
|
||||
toolbarComponent: chatInfoButton2
|
||||
width: 518
|
||||
|
||||
Component {
|
||||
id: chatInfoButton2
|
||||
StatusChatInfoButton {
|
||||
width: Math.min(implicitWidth, parent.width)
|
||||
title: "Some contact"
|
||||
subTitle: "Contact"
|
||||
icon.color: Theme.palette.miscColor7
|
||||
type: StatusChatInfoButton.Type.PublicChat
|
||||
pinnedMessagesCount: 1
|
||||
muted: true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
StatusChatToolBar {
|
||||
chatInfoButton.title: "Some contact"
|
||||
chatInfoButton.subTitle: "Contact"
|
||||
chatInfoButton.icon.color: Theme.palette.miscColor7
|
||||
chatInfoButton.type: StatusChatInfoButton.Type.OneToOneChat
|
||||
chatInfoButton.pinnedMessagesCount: 1
|
||||
notificationCount: 1
|
||||
toolbarComponent: chatInfoButton3
|
||||
width: 518
|
||||
|
||||
Component {
|
||||
id: chatInfoButton3
|
||||
|
||||
StatusChatInfoButton {
|
||||
width: Math.min(implicitWidth, parent.width)
|
||||
title: "Some contact"
|
||||
subTitle: "Contact"
|
||||
icon.color: Theme.palette.miscColor7
|
||||
type: StatusChatInfoButton.Type.OneToOneChat
|
||||
pinnedMessagesCount: 1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
StatusChatToolBar {
|
||||
notificationCount: 1
|
||||
toolbarComponent: tagSelector
|
||||
width: 518
|
||||
|
||||
Component {
|
||||
id: tagSelector
|
||||
|
||||
StatusTagSelector {
|
||||
namesModel: ListModel {
|
||||
ListElement {
|
||||
publicId: "0x0"
|
||||
name: "Maria"
|
||||
icon: ""
|
||||
isIdenticon: false
|
||||
onlineStatus: 3
|
||||
isReadonly: true
|
||||
tagIcon: "crown"
|
||||
}
|
||||
ListElement {
|
||||
publicId: "0x1"
|
||||
name: "James"
|
||||
icon: ""
|
||||
isIdenticon: false
|
||||
onlineStatus: 1
|
||||
isReadonly: false
|
||||
tagIcon: ""
|
||||
}
|
||||
}
|
||||
toLabelText: qsTr("To: ")
|
||||
warningText: qsTr("USER LIMIT REACHED")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Row {
|
||||
|
||||
@@ -4,6 +4,7 @@ import StatusQ.Core 0.1
|
||||
import StatusQ.Core.Theme 0.1
|
||||
import StatusQ.Controls 0.1
|
||||
import StatusQ.Components 0.1
|
||||
import StatusQ.Core.Utils 0.1
|
||||
|
||||
GridLayout {
|
||||
columns: 1
|
||||
@@ -25,7 +26,7 @@ GridLayout {
|
||||
badge.value: 1
|
||||
}
|
||||
StatusNavigationListItem {
|
||||
title: "Menu Item (selected)"
|
||||
title: "Menu Item (selected) with very long text"
|
||||
selected: true
|
||||
icon.name: "info"
|
||||
badge.value: 1
|
||||
@@ -338,6 +339,24 @@ CExPynn1gWf9bx498P7/nzPcxEzGExhBdJGYihtAYQlO+tUZvqrPbqeudo5iJGEJjCE15a3VtodH3q2I
|
||||
}
|
||||
}
|
||||
|
||||
StatusListItem {
|
||||
title: "List Item with Inline Tags"
|
||||
icon.isLetterIdenticon: true
|
||||
tagsModel : 2
|
||||
tagsDelegate: StatusListItemTag {
|
||||
color: "blue"
|
||||
height: 24
|
||||
radius: 6
|
||||
closeButtonVisible: false
|
||||
icon.emoji: "😁"
|
||||
icon.emojiSize: Emoji.size.verySmall
|
||||
icon.isLetterIdenticon: true
|
||||
title: "helloworld.eth"
|
||||
titleText.font.pixelSize: 12
|
||||
titleText.color: Theme.palette.indirectColor1
|
||||
}
|
||||
}
|
||||
|
||||
StatusListItem {
|
||||
title: "List Item with Emoji"
|
||||
subTitle: "Emoji"
|
||||
@@ -375,13 +394,13 @@ CExPynn1gWf9bx498P7/nzPcxEzGExhBdJGYihtAYQlO+tUZvqrPbqeudo5iJGEJjCE15a3VtodH3q2I
|
||||
StatusMemberListItem {
|
||||
nickName: "This is an example"
|
||||
userName: "annabelle"
|
||||
chatKey: "0x043a7ed0e8752236a4688563652fd0296453cef00a5dcddbe252dc74f72cc1caa97a2b65e4a1a52d9c30a84c9966beaaaf6b333d659cbdd2e486b443ed1012cf04"
|
||||
trustIndicator: StatusContactVerificationIcons.TrustedType.Verified
|
||||
isMutualContact: true
|
||||
pubKey: "0x043a7ed0e8752236a4688563652fd0296453cef00a5dcddbe252dc74f72cc1caa97a2b65e4a1a52d9c30a84c9966beaaaf6b333d659cbdd2e486b443ed1012cf04"
|
||||
isVerified: true
|
||||
isContact: true
|
||||
image.source: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAlklEQVR4nOzW0QmDQBAG4SSkl7SUQlJGCrElq9F3QdjjVhh/5nv3cFhY9vUIYQiNITSG0BhCExPynn1gWf9bx498P7/
|
||||
nzPcxEzGExhBdJGYihtAYQlO+tUZvqrPbqeudo5iJGEJjCE15a3VtodH3q2ImYgiNITTlTdG1nUZ5a92VITQxITFiJmIIjSE0htAYQrMHAAD//+wwFVpz+yqXAAAAAElFTkSuQmCC"
|
||||
image.isIdenticon: true
|
||||
isOnline: true
|
||||
status: 1 // FIXME: use enum
|
||||
ringSettings.ringSpecModel:
|
||||
ListModel {
|
||||
ListElement {colorId: 13; segmentLength: 5}
|
||||
@@ -397,23 +416,62 @@ CExPynn1gWf9bx498P7/nzPcxEzGExhBdJGYihtAYQlO+tUZvqrPbqeudo5iJGEJjCE15a3VtodH3q2I
|
||||
|
||||
StatusMemberListItem {
|
||||
nickName: "carmen.eth"
|
||||
isOnline: false
|
||||
trustIndicator: StatusContactVerificationIcons.TrustedType.Untrustworthy
|
||||
isUntrustworthy: true
|
||||
}
|
||||
|
||||
StatusMemberListItem {
|
||||
nickName: "very-long-annoying-nickname.eth"
|
||||
isUntrustworthy: true
|
||||
}
|
||||
|
||||
StatusMemberListItem {
|
||||
nickName: "This girl I know from work"
|
||||
userName: "annabelle"
|
||||
isOnline: true
|
||||
status: 1 // FIXME: use enum
|
||||
}
|
||||
|
||||
StatusMemberListItem {
|
||||
nickName: "Mark Cuban"
|
||||
userName: "annabelle"
|
||||
chatKey: "0x043a7ed0e8752236a4688563652fd0296453cef00a5dcddbe252dc74f72cc1caa97a2b65e4a1a52d9c30a84c9966beaaaf6b333d659cbdd2e486b443ed1012cf04"
|
||||
isMutualContact: true
|
||||
pubKey: "0x043a7ed0e8752236a4688563652fd0296453cef00a5dcddbe252dc74f72cc1caa97a2b65e4a1a52d9c30a84c9966beaaaf6b333d659cbdd2e486b443ed1012cf04"
|
||||
isContact: true
|
||||
image.source: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAlklEQVR4nOzW0QmDQBAG4SSkl7SUQlJGCrElq9F3QdjjVhh/5nv3cFhY9vUIYQiNITSG0BhCExPynn1gWf9bx498P7/
|
||||
nzPcxEzGExhBdJGYihtAYQlO+tUZvqrPbqeudo5iJGEJjCE15a3VtodH3q2ImYgiNITTlTdG1nUZ5a92VITQxITFiJmIIjSE0htAYQrMHAAD//+wwFVpz+yqXAAAAAElFTkSuQmCC"
|
||||
image.isIdenticon: true
|
||||
}
|
||||
|
||||
StatusMemberListItem {
|
||||
nickName: "admin.guy"
|
||||
isAdmin: true
|
||||
isUntrustworthy: true
|
||||
}
|
||||
|
||||
StatusBaseText {
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: 16
|
||||
text: "Loading features:"
|
||||
font.pixelSize: 17
|
||||
}
|
||||
|
||||
StatusListItem {
|
||||
title: "Nokia 3310"
|
||||
subTitle: "Incoming device"
|
||||
label: "loading: true"
|
||||
icon.emoji: "😁"
|
||||
icon.color: "hotpink"
|
||||
icon.letterSize: 14
|
||||
icon.isLetterIdenticon: true
|
||||
loading: true
|
||||
}
|
||||
|
||||
StatusListItem {
|
||||
title: "Nokia 3310"
|
||||
subTitle: "Device"
|
||||
label: "loadingFailed: true"
|
||||
icon.emoji: "😁"
|
||||
icon.color: "hotpink"
|
||||
icon.letterSize: 14
|
||||
icon.isLetterIdenticon: true
|
||||
loadingFailed: true
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,38 +4,58 @@ import StatusQ.Core 0.1
|
||||
import StatusQ.Core.Theme 0.1
|
||||
import StatusQ.Components 0.1
|
||||
|
||||
GridLayout {
|
||||
columns: 6
|
||||
columnSpacing: 5
|
||||
rowSpacing: 5
|
||||
ColumnLayout {
|
||||
GridLayout {
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
|
||||
StatusLoadingIndicator {
|
||||
color: Theme.palette.directColor4
|
||||
columns: 6
|
||||
columnSpacing: 5
|
||||
rowSpacing: 5
|
||||
|
||||
StatusLoadingIndicator {
|
||||
color: Theme.palette.directColor4
|
||||
}
|
||||
|
||||
StatusLetterIdenticon {
|
||||
name: "#status"
|
||||
}
|
||||
|
||||
StatusRoundedImage {
|
||||
image.source: "https://pbs.twimg.com/profile_images/1369221718338895873/T_5fny6o_400x400.jpg"
|
||||
}
|
||||
|
||||
StatusBadge {}
|
||||
|
||||
StatusBadge {
|
||||
value: 1
|
||||
}
|
||||
|
||||
StatusBadge {
|
||||
value: 10
|
||||
}
|
||||
|
||||
StatusBadge {
|
||||
value: 100
|
||||
}
|
||||
|
||||
StatusRoundIcon {
|
||||
icon.name: "info"
|
||||
}
|
||||
}
|
||||
|
||||
StatusLetterIdenticon {
|
||||
name: "#status"
|
||||
}
|
||||
Flow {
|
||||
Layout.fillWidth: true
|
||||
spacing: 4
|
||||
|
||||
StatusRoundedImage {
|
||||
image.source: "https://pbs.twimg.com/profile_images/1369221718338895873/T_5fny6o_400x400.jpg"
|
||||
}
|
||||
|
||||
StatusBadge {}
|
||||
|
||||
StatusBadge {
|
||||
value: 1
|
||||
}
|
||||
|
||||
StatusBadge {
|
||||
value: 10
|
||||
}
|
||||
|
||||
StatusBadge {
|
||||
value: 100
|
||||
}
|
||||
|
||||
StatusRoundIcon {
|
||||
icon.name: "info"
|
||||
Repeater {
|
||||
model: 12
|
||||
StatusLetterIdenticon {
|
||||
name: "A"
|
||||
color: Theme.palette.userCustomizationColors[index]
|
||||
letterSize: 16
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -4,6 +4,9 @@ import StatusQ.Core 0.1
|
||||
import StatusQ.Core.Theme 0.1
|
||||
import StatusQ.Controls 0.1
|
||||
import StatusQ.Popups 0.1
|
||||
import StatusQ.Components 0.1
|
||||
import StatusQ.Popups 0.1
|
||||
import StatusQ.Core.Utils 0.1
|
||||
|
||||
Column {
|
||||
spacing: 20
|
||||
@@ -83,6 +86,12 @@ Column {
|
||||
onClicked: advancedHeaderFooterModal.open()
|
||||
}
|
||||
|
||||
|
||||
StatusButton {
|
||||
text: "Modal with Floating header Buttons"
|
||||
onClicked: floatingHeaderModal.open()
|
||||
}
|
||||
|
||||
StatusModal {
|
||||
id: simpleModal
|
||||
anchors.centerIn: parent
|
||||
@@ -394,10 +403,57 @@ CExPynn1gWf9bx498P7/nzPcxEzGExhBdJGYihtAYQlO+tUZvqrPbqeudo5iJGEJjCE15a3VtodH3q2I
|
||||
}
|
||||
}
|
||||
|
||||
StatusModal {
|
||||
id: floatingHeaderModal
|
||||
anchors.centerIn: parent
|
||||
height: 200
|
||||
showHeader: false
|
||||
showFooter: false
|
||||
showAdvancedHeader: true
|
||||
hasFloatingButtons: true
|
||||
advancedHeaderComponent: StatusFloatingButtonsSelector {
|
||||
id: floatingHeader
|
||||
model: dummyAccountsModel
|
||||
delegate: Rectangle {
|
||||
width: button.width
|
||||
height: button.height
|
||||
radius: 8
|
||||
visible: visibleIndices.includes(index)
|
||||
StatusButton {
|
||||
id: button
|
||||
topPadding: 8
|
||||
bottomPadding: 0
|
||||
implicitHeight: 32
|
||||
defaultLeftPadding: 4
|
||||
text: name
|
||||
icon.emoji: !!emoji ? emoji: ""
|
||||
icon.emojiSize: Emoji.size.middle
|
||||
icon.name: !emoji ? "filled-account": ""
|
||||
normalColor: "transparent"
|
||||
highlighted: index === floatingHeader.currentIndex
|
||||
onClicked: {
|
||||
floatingHeader.currentIndex = index
|
||||
}
|
||||
}
|
||||
}
|
||||
popupMenuDelegate: StatusListItem {
|
||||
implicitWidth: 272
|
||||
title: name
|
||||
onClicked: floatingHeader.itemSelected(index)
|
||||
visible: !visibleIndices.includes(index)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ListModel {
|
||||
id: dummyAccountsModel
|
||||
ListElement{name: "Account 1"; iconName: "filled-account"}
|
||||
ListElement{name: "Account 1"; iconName: "filled-account"; emoji: "🥑"}
|
||||
ListElement{name: "Account 2"; iconName: "filled-account"}
|
||||
ListElement{name: "Account 3"; iconName: "filled-account"}
|
||||
ListElement{name: "Account 4"; iconName: "filled-account"}
|
||||
ListElement{name: "Account 5"; iconName: "filled-account"}
|
||||
ListElement{name: "Account 6"; iconName: "filled-account"}
|
||||
ListElement{name: "Account 7"; iconName: "filled-account"}
|
||||
}
|
||||
|
||||
StatusSpellcheckingMenuItems {
|
||||
|
||||
@@ -30,10 +30,46 @@ Page {
|
||||
toLabelText: qsTr("To: ")
|
||||
warningText: qsTr("USER LIMIT REACHED")
|
||||
listLabel: qsTr("Contacts")
|
||||
ringSpecModelGetter: function(pubKey) {
|
||||
//for simulation purposes only, in real app
|
||||
//this would be Utils.getColorHashAsJson(pubKey)
|
||||
var index = -1;
|
||||
if (!!contactsModel) {
|
||||
for (var i = 0; i < contactsModel.count; i++) {
|
||||
if (contactsModel.get(i).pubKey === pubKey) {
|
||||
index = i;
|
||||
}
|
||||
}
|
||||
return contactsModel.get(index).ringSpecModel;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
compressedKeyGetter: function(pubKey) {
|
||||
//for simulation purposes only, in real app
|
||||
//this would be Utils.getCompressedPk(pubKey);
|
||||
var possibleCharacters = pubKey.split('');
|
||||
var randomStringLength = 12; // assuming you want random strings of 12 characters
|
||||
var randomString = [];
|
||||
for (var i=0; i<randomStringLength; ++i) {
|
||||
var index = (Math.random() * possibleCharacters.length).toFixed(0);
|
||||
var nextChar = possibleCharacters[index];
|
||||
randomString.push(nextChar);
|
||||
}
|
||||
return randomString.join().toString().replace(/,/g, '');
|
||||
}
|
||||
colorIdForPubkeyGetter: function (pubKey) {
|
||||
//for simulation purposes only, in real app
|
||||
//this would be Utils.colorIdForPubkey(pubKey);
|
||||
return Math.floor(Math.random() * 10);
|
||||
}
|
||||
onTextChanged: {
|
||||
sortModel(root.contactsModel);
|
||||
}
|
||||
Component.onCompleted: { sortModel(root.contactsModel); }
|
||||
Component.onCompleted: {
|
||||
textEdit.forceActiveFocus();
|
||||
sortModel(root.contactsModel);
|
||||
}
|
||||
}
|
||||
|
||||
StatusButton {
|
||||
|
||||
@@ -27,21 +27,19 @@ StatusAppThreePanelLayout {
|
||||
|
||||
RowLayout {
|
||||
id: searchInputWrapper
|
||||
width: parent.width
|
||||
width: 288
|
||||
height: searchInput.height
|
||||
anchors.top: headline.bottom
|
||||
anchors.topMargin: 16
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: 8
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
|
||||
StatusBaseInput {
|
||||
id: searchInput
|
||||
Layout.fillWidth: true
|
||||
Layout.alignment: Qt.AlignVCenter | Qt.AlignLeft
|
||||
Layout.leftMargin: 17
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
implicitHeight: 36
|
||||
topPadding: 8
|
||||
bottomPadding: 0
|
||||
bottomPadding: 8
|
||||
placeholderText: "Search"
|
||||
icon.name: "search"
|
||||
}
|
||||
@@ -61,7 +59,7 @@ StatusAppThreePanelLayout {
|
||||
Column {
|
||||
anchors.top: searchInputWrapper.bottom
|
||||
anchors.topMargin: 16
|
||||
width: parent.width
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
spacing: 8
|
||||
|
||||
StatusContactRequestsIndicatorListItem {
|
||||
@@ -72,8 +70,8 @@ StatusAppThreePanelLayout {
|
||||
}
|
||||
|
||||
StatusChatList {
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
model: Models.demoChatListItems
|
||||
highlightItem: !root.createChat
|
||||
onChatItemUnmuted: {
|
||||
for (var i = 0; i < Models.demoChatListItems.count; i++) {
|
||||
let item = Models.demoChatListItems.get(i);
|
||||
@@ -128,19 +126,18 @@ StatusAppThreePanelLayout {
|
||||
centerPanel: Loader {
|
||||
anchors.fill: parent
|
||||
sourceComponent: root.createChat ? createChatView : chatChannelView
|
||||
}
|
||||
|
||||
Component {
|
||||
id: createChatView
|
||||
CreateChatView {
|
||||
contactsModel: Models.dummyContactsModel
|
||||
Component {
|
||||
id: createChatView
|
||||
CreateChatView {
|
||||
contactsModel: Models.membersListModel
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: chatChannelView
|
||||
ChatChannelView {
|
||||
model: Models.chatMessagesModel
|
||||
Component {
|
||||
id: chatChannelView
|
||||
ChatChannelView {
|
||||
model: Models.chatMessagesModel
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -148,15 +145,8 @@ StatusAppThreePanelLayout {
|
||||
anchors.fill: parent
|
||||
|
||||
StatusChatToolBar {
|
||||
anchors.top: parent.top
|
||||
width: parent.width
|
||||
|
||||
chatInfoButton.title: "Amazing Funny Squirrel"
|
||||
chatInfoButton.subTitle: "Contact"
|
||||
chatInfoButton.icon.color: Theme.palette.miscColor7
|
||||
chatInfoButton.type: StatusChatInfoButton.Type.OneToOneChat
|
||||
chatInfoButton.pinnedMessagesCount: 1
|
||||
|
||||
toolbarComponent: statusChatInfoButton
|
||||
searchButton.visible: false
|
||||
membersButton.visible: false
|
||||
notificationCount: 1
|
||||
@@ -189,6 +179,19 @@ StatusAppThreePanelLayout {
|
||||
type: StatusMenuItem.Type.Danger
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: statusChatInfoButton
|
||||
|
||||
StatusChatInfoButton {
|
||||
width: Math.min(implicitWidth, parent.width)
|
||||
title: "Amazing Funny Squirrel"
|
||||
subTitle: "Contact"
|
||||
icon.color: Theme.palette.miscColor7
|
||||
type: StatusChatInfoButton.Type.OneToOneChat
|
||||
pinnedMessagesCount: 1
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,156 @@
|
||||
import QtQuick 2.13
|
||||
import QtQuick.Controls 2.13
|
||||
import QtQuick.Layouts 1.13
|
||||
|
||||
import StatusQ.Core 0.1
|
||||
import StatusQ.Core.Theme 0.1
|
||||
import StatusQ.Controls 0.1
|
||||
import StatusQ.Components 0.1
|
||||
|
||||
import "../demoapp/data" 1.0
|
||||
|
||||
|
||||
ScrollView {
|
||||
id: root
|
||||
|
||||
QtObject {
|
||||
id: d
|
||||
|
||||
property ListModel featuredCommunitiesModel: Models.featuredCommunitiesModel
|
||||
property ListModel popularCommunitiesModel: Models.curatedCommunitiesModel
|
||||
property ListModel tagsModel: Models.tagsModel
|
||||
|
||||
property string searchText: ""
|
||||
property int layoutVMargin: 70
|
||||
property int layoutHMargin: 64
|
||||
property int titlePixelSize: 28
|
||||
property int subtitlePixelSize: 17
|
||||
property int stylePadding: 16
|
||||
|
||||
function navigateToCommunity(communityId) {
|
||||
console.info("Clicked community ID: " + communityId)
|
||||
}
|
||||
}
|
||||
|
||||
contentHeight: column.height + d.layoutVMargin
|
||||
contentWidth: column.width + d.layoutHMargin
|
||||
clip: true
|
||||
|
||||
ColumnLayout {
|
||||
id: column
|
||||
spacing: 18
|
||||
|
||||
StatusBaseText {
|
||||
Layout.topMargin: d.layoutVMargin
|
||||
Layout.leftMargin: d.layoutHMargin
|
||||
text: qsTr("Find community")
|
||||
font.weight: Font.Bold
|
||||
font.pixelSize: d.titlePixelSize
|
||||
color: Theme.palette.directColor1
|
||||
}
|
||||
|
||||
// Tags definition - Now hidden - Out of scope
|
||||
// TODO: Replace by `StatusListItemTagRow`
|
||||
Row {
|
||||
visible: d.tagsModel.count > 0
|
||||
Layout.leftMargin: d.layoutHMargin
|
||||
Layout.rightMargin: d.layoutHMargin
|
||||
width: 1234 // by design
|
||||
spacing: d.stylePadding/2
|
||||
|
||||
Repeater {
|
||||
model: d.tagsModel
|
||||
delegate: StatusListItemTag {
|
||||
border.color: Theme.palette.baseColor2
|
||||
color: "transparent"
|
||||
height: 32
|
||||
radius: 36
|
||||
closeButtonVisible: false
|
||||
icon.emoji: model.emoji
|
||||
icon.height: 32
|
||||
icon.width: icon.height
|
||||
icon.color: "transparent"
|
||||
icon.isLetterIdenticon: true
|
||||
title: model.name
|
||||
titleText.font.pixelSize: 15
|
||||
titleText.color: Theme.palette.primaryColor1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
StatusBaseText {
|
||||
Layout.leftMargin: d.layoutHMargin
|
||||
Layout.topMargin: 20
|
||||
text: qsTr("Featured")
|
||||
font.weight: Font.Bold
|
||||
font.pixelSize: d.subtitlePixelSize
|
||||
color: Theme.palette.directColor1
|
||||
}
|
||||
|
||||
GridLayout {
|
||||
id: featuredGrid
|
||||
Layout.leftMargin: d.layoutHMargin
|
||||
columns: 3
|
||||
columnSpacing: d.stylePadding
|
||||
rowSpacing: d.stylePadding
|
||||
|
||||
Repeater {
|
||||
model: d.featuredCommunitiesModel
|
||||
delegate: StatusCommunityCard {
|
||||
locale: "es"
|
||||
communityId: model.communityId
|
||||
loaded: model.available
|
||||
logo: model.logo
|
||||
name: model.name
|
||||
description: model.description
|
||||
members: model.members
|
||||
popularity: model.popularity
|
||||
communityColor: model.communityColor
|
||||
categories: ListModel {
|
||||
ListElement { name: "sport"; emoji: "🎾"}
|
||||
ListElement { name: "food"; emoji: "🥑"}
|
||||
ListElement { name: "privacy"; emoji: "👻"}
|
||||
}
|
||||
|
||||
onClicked: { d.navigateToCommunity(communityId) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
StatusBaseText {
|
||||
Layout.leftMargin: d.layoutHMargin
|
||||
Layout.topMargin: 20
|
||||
text: qsTr("Popular")
|
||||
font.weight: Font.Bold
|
||||
font.pixelSize: d.subtitlePixelSize
|
||||
color: Theme.palette.directColor1
|
||||
}
|
||||
|
||||
GridLayout {
|
||||
Layout.leftMargin: d.layoutHMargin
|
||||
columns: 3
|
||||
columnSpacing: d.stylePadding
|
||||
rowSpacing: d.stylePadding
|
||||
|
||||
Repeater {
|
||||
model: d.popularCommunitiesModel
|
||||
delegate: StatusCommunityCard {
|
||||
locale: "es"
|
||||
communityId: model.communityId
|
||||
loaded: model.available
|
||||
logo: model.logo
|
||||
name: model.name
|
||||
description: model.description
|
||||
members: model.members
|
||||
activeUsers: model.activeUsers
|
||||
popularity: model.popularity
|
||||
tokenLogo: model.tokenLogo
|
||||
isPrivate: model.isPrivate
|
||||
banner: model.banner
|
||||
|
||||
onClicked: { d.navigateToCommunity(communityId) }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -166,13 +166,10 @@ StatusAppThreePanelLayout {
|
||||
centerPanel: Item {
|
||||
StatusChatToolBar {
|
||||
id: statusChatToolBar
|
||||
anchors.top: parent.top
|
||||
width: parent.width
|
||||
|
||||
chatInfoButton.title: "general"
|
||||
chatInfoButton.subTitle: "Community Chat"
|
||||
chatInfoButton.icon.color: Theme.palette.miscColor6
|
||||
chatInfoButton.type: StatusChatInfoButton.Type.CommunityChat
|
||||
width: parent.width
|
||||
toolbarComponent: statusChatInfoButton
|
||||
|
||||
onSearchButtonClicked: {
|
||||
searchButton.highlighted = !searchButton.highlighted;
|
||||
searchPopup.setSearchSelection(communityDetailModalTitle,
|
||||
@@ -184,6 +181,18 @@ StatusAppThreePanelLayout {
|
||||
onMembersButtonClicked: {
|
||||
root.showRightPanel = !root.showRightPanel;
|
||||
}
|
||||
|
||||
Component {
|
||||
id: statusChatInfoButton
|
||||
|
||||
StatusChatInfoButton {
|
||||
width: Math.min(implicitWidth, parent.width)
|
||||
title: "general"
|
||||
subTitle: "Community Chat"
|
||||
icon.color: Theme.palette.miscColor6
|
||||
type: StatusChatInfoButton.Type.CommunityChat
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
StatusSearchPopup {
|
||||
@@ -258,16 +267,15 @@ StatusAppThreePanelLayout {
|
||||
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
|
||||
ringSettings.ringSpecModel: model.ringSpecModel
|
||||
ringSettings.distinctiveColors: Theme.palette.identiconRingColors
|
||||
nickName: model.localNickname
|
||||
userName: model.displayName
|
||||
pubKey: model.pubKey
|
||||
isVerified: model.isVerified
|
||||
isUntrustworthy: model.isUntrustworthy
|
||||
isContact: model.isContact
|
||||
image.source: model.icon
|
||||
image.isIdenticon: false
|
||||
status: model.onlineStatus
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,65 +4,15 @@ import StatusQ.Components 0.1
|
||||
|
||||
QtObject {
|
||||
|
||||
property ListModel dummyContactsModel: ListModel {
|
||||
ListElement {
|
||||
publicId: "0x0"
|
||||
name: "Maria"
|
||||
icon: ""
|
||||
isIdenticon: false
|
||||
onlineStatus: 3
|
||||
}
|
||||
ListElement {
|
||||
publicId: "0x1"
|
||||
name: "James"
|
||||
icon: "https://pbs.twimg.com/profile_images/1369221718338895873/T_5fny6o_400x400.jpg"
|
||||
isIdenticon: false
|
||||
onlineStatus: 1
|
||||
}
|
||||
ListElement {
|
||||
publicId: "0x2"
|
||||
name: "Paul"
|
||||
icon: ""
|
||||
isIdenticon: false
|
||||
onlineStatus: 2
|
||||
}
|
||||
ListElement {
|
||||
publicId: "0x3"
|
||||
name: "Tracy"
|
||||
icon: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAlklEQVR4nOzW0QmDQBAG4SSkl7SUQlJGCrElq9F3QdjjVhh/5nv3cFhY9vUIYQiNITSG0BhCExPynn1gWf9bx498P7/nzPcxEzGExhBdJGYihtAYQlO+tUZvqrPbqeudo5iJGEJjCE15a3VtodH3q2ImYgiNITTlTdG1nUZ5a92VITQxITFiJmIIjSE0htAYQrMHAAD//+wwFVpz+yqXAAAAAElFTkSuQmCC"
|
||||
isIdenticon: true
|
||||
onlineStatus: 3
|
||||
}
|
||||
ListElement {
|
||||
publicId: "0x4"
|
||||
name: "Nick"
|
||||
icon: ""
|
||||
isIdenticon: false
|
||||
onlineStatus: 3
|
||||
}
|
||||
ListElement {
|
||||
publicId: "0x5"
|
||||
name: "Steven"
|
||||
icon: ""
|
||||
isIdenticon: false
|
||||
onlineStatus: 2
|
||||
}
|
||||
ListElement {
|
||||
publicId: "0x6"
|
||||
name: "Helen"
|
||||
icon: ""
|
||||
isIdenticon: false
|
||||
onlineStatus: 3
|
||||
}
|
||||
}
|
||||
|
||||
property var demoChatListItems: ListModel {
|
||||
id: demoChatListItems
|
||||
ListElement {
|
||||
itemId: "x012340000"
|
||||
name: "#status"
|
||||
icon: ""
|
||||
emoji: ""
|
||||
isIdenticon: false
|
||||
colorHash: []
|
||||
color: "blue"
|
||||
description: ""
|
||||
type: StatusChatListItem.Type.PublicChat
|
||||
@@ -78,7 +28,9 @@ QtObject {
|
||||
itemId: "x012340001"
|
||||
name: "status-desktop"
|
||||
icon: ""
|
||||
emoji: ""
|
||||
isIdenticon: false
|
||||
colorHash: []
|
||||
color: "red"
|
||||
description: ""
|
||||
type: StatusChatListItem.Type.PublicChat
|
||||
@@ -95,7 +47,9 @@ QtObject {
|
||||
name: "Amazing Funny Squirrel"
|
||||
icon: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAlklEQVR4nOzW0QmDQBAG4SSkl7SUQlJGCrElq9F3QdjjVhh/5nv3cFhY9vUIYQiNITSG0Bh
|
||||
CExPynn1gWf9bx498P7/nzPcxEzGExhBdJGYihtAYQlO+tUZvqrPbqeudo5iJGEJjCE15a3VtodH3q2ImYgiNITTlTdG1nUZ5a92VITQxITFiJmIIjSE0htAYQrMHAAD//+wwFVpz+yqXAAAAAElFTkSuQmCC"
|
||||
emoji: ""
|
||||
isIdenticon: true
|
||||
colorHash: []
|
||||
color: "green"
|
||||
description: ""
|
||||
type: StatusChatListItem.Type.OneToOneChat
|
||||
@@ -111,7 +65,9 @@ CExPynn1gWf9bx498P7/nzPcxEzGExhBdJGYihtAYQlO+tUZvqrPbqeudo5iJGEJjCE15a3VtodH3q2I
|
||||
itemId: "x012340003"
|
||||
name: "Black Ops"
|
||||
icon: ""
|
||||
emoji: ""
|
||||
isIdenticon: false
|
||||
colorHash: []
|
||||
color: "purple"
|
||||
description: ""
|
||||
type: StatusChatListItem.Type.OneToOneChat
|
||||
@@ -127,7 +83,9 @@ CExPynn1gWf9bx498P7/nzPcxEzGExhBdJGYihtAYQlO+tUZvqrPbqeudo5iJGEJjCE15a3VtodH3q2I
|
||||
itemId: "x012340004"
|
||||
name: "Spectacular Growing Otter"
|
||||
icon: ""
|
||||
emoji: ""
|
||||
isIdenticon: false
|
||||
colorHash: []
|
||||
color: "orange"
|
||||
description: ""
|
||||
type: StatusChatListItem.Type.OneToOneChat
|
||||
@@ -143,7 +101,9 @@ CExPynn1gWf9bx498P7/nzPcxEzGExhBdJGYihtAYQlO+tUZvqrPbqeudo5iJGEJjCE15a3VtodH3q2I
|
||||
itemId: "x012340005"
|
||||
name: "channel-with-a-super-duper-long-name"
|
||||
icon: ""
|
||||
emoji: ""
|
||||
isIdenticon: false
|
||||
colorHash: []
|
||||
color: "green"
|
||||
description: ""
|
||||
type: StatusChatListItem.Type.PublicChat
|
||||
@@ -397,7 +357,6 @@ CExPynn1gWf9bx498P7/nzPcxEzGExhBdJGYihtAYQlO+tUZvqrPbqeudo5iJGEJjCE15a3VtodH3q2I
|
||||
imageSource: ""
|
||||
iconName: "chat"
|
||||
iconColor: ""
|
||||
isIdenticon: false
|
||||
subItems: [
|
||||
ListElement {
|
||||
value: "sub_item_1_1"
|
||||
@@ -405,7 +364,6 @@ CExPynn1gWf9bx498P7/nzPcxEzGExhBdJGYihtAYQlO+tUZvqrPbqeudo5iJGEJjCE15a3VtodH3q2I
|
||||
imageSource: "https://pbs.twimg.com/profile_images/1369221718338895873/T_5fny6o_400x400.jpg"
|
||||
iconName: ""
|
||||
iconColor: ""
|
||||
isIdenticon: false
|
||||
},
|
||||
ListElement {
|
||||
value: "sub_item_1_2"
|
||||
@@ -413,7 +371,6 @@ CExPynn1gWf9bx498P7/nzPcxEzGExhBdJGYihtAYQlO+tUZvqrPbqeudo5iJGEJjCE15a3VtodH3q2I
|
||||
imageSource: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAlklEQVR4nOzW0QmDQBAG4SSkl7SUQlJGCrElq9F3QdjjVhh/5nv3cFhY9vUIYQiNITSG0BhCExPynn1gWf9bx498P7/nzPcxEzGExhBdJGYihtAYQlO+tUZvqrPbqeudo5iJGEJjCE15a3VtodH3q2ImYgiNITTlTdG1nUZ5a92VITQxITFiJmIIjSE0htAYQrMHAAD//+wwFVpz+yqXAAAAAElFTkSuQmCC"
|
||||
iconName: ""
|
||||
iconColor: ""
|
||||
isIdenticon: true
|
||||
}]}
|
||||
ListElement {
|
||||
value: "item_2"
|
||||
@@ -421,7 +378,6 @@ CExPynn1gWf9bx498P7/nzPcxEzGExhBdJGYihtAYQlO+tUZvqrPbqeudo5iJGEJjCE15a3VtodH3q2I
|
||||
imageSource: "https://pbs.twimg.com/profile_images/1369221718338895873/T_5fny6o_400x400.jpg"
|
||||
iconName: ""
|
||||
iconColor: ""
|
||||
isIdenticon: false
|
||||
subItems: [
|
||||
ListElement {
|
||||
value: "sub_item_2_1"
|
||||
@@ -429,7 +385,6 @@ CExPynn1gWf9bx498P7/nzPcxEzGExhBdJGYihtAYQlO+tUZvqrPbqeudo5iJGEJjCE15a3VtodH3q2I
|
||||
imageSource: ""
|
||||
iconName: "channel"
|
||||
iconColor: ""
|
||||
isIdenticon: false
|
||||
},
|
||||
ListElement {
|
||||
value: "sub_item_2_2"
|
||||
@@ -437,7 +392,6 @@ CExPynn1gWf9bx498P7/nzPcxEzGExhBdJGYihtAYQlO+tUZvqrPbqeudo5iJGEJjCE15a3VtodH3q2I
|
||||
imageSource: ""
|
||||
iconName: "channel"
|
||||
iconColor: ""
|
||||
isIdenticon: false
|
||||
},
|
||||
ListElement {
|
||||
value: "sub_item_2_3"
|
||||
@@ -445,7 +399,6 @@ CExPynn1gWf9bx498P7/nzPcxEzGExhBdJGYihtAYQlO+tUZvqrPbqeudo5iJGEJjCE15a3VtodH3q2I
|
||||
imageSource: ""
|
||||
iconName: "channel"
|
||||
iconColor: ""
|
||||
isIdenticon: false
|
||||
}]}
|
||||
ListElement {
|
||||
value: "item_3"
|
||||
@@ -453,7 +406,6 @@ CExPynn1gWf9bx498P7/nzPcxEzGExhBdJGYihtAYQlO+tUZvqrPbqeudo5iJGEJjCE15a3VtodH3q2I
|
||||
imageSource: "";
|
||||
iconName: "info"
|
||||
iconColor: ""
|
||||
isIdenticon: false
|
||||
subItems: [
|
||||
ListElement {
|
||||
value: "sub_item_3_1"
|
||||
@@ -461,7 +413,6 @@ CExPynn1gWf9bx498P7/nzPcxEzGExhBdJGYihtAYQlO+tUZvqrPbqeudo5iJGEJjCE15a3VtodH3q2I
|
||||
imageSource: ""
|
||||
iconName: "channel"
|
||||
iconColor: ""
|
||||
isIdenticon: false
|
||||
}]}
|
||||
ListElement {
|
||||
value: "item_4"
|
||||
@@ -469,7 +420,6 @@ CExPynn1gWf9bx498P7/nzPcxEzGExhBdJGYihtAYQlO+tUZvqrPbqeudo5iJGEJjCE15a3VtodH3q2I
|
||||
imageSource: "";
|
||||
iconName: ""
|
||||
iconColor: "red"
|
||||
isIdenticon: false
|
||||
subItems: [
|
||||
ListElement {
|
||||
value: "sub_item_4_1"
|
||||
@@ -477,7 +427,6 @@ CExPynn1gWf9bx498P7/nzPcxEzGExhBdJGYihtAYQlO+tUZvqrPbqeudo5iJGEJjCE15a3VtodH3q2I
|
||||
imageSource: ""
|
||||
iconName: "channel"
|
||||
iconColor: ""
|
||||
isIdenticon: false
|
||||
}]}
|
||||
}
|
||||
|
||||
@@ -894,69 +843,50 @@ CExPynn1gWf9bx498P7/nzPcxEzGExhBdJGYihtAYQlO+tUZvqrPbqeudo5iJGEJjCE15a3VtodH3q2I
|
||||
property var membersListModel: ListModel {
|
||||
id: membersList
|
||||
ListElement {
|
||||
nickName: "This is an example"
|
||||
userName: "annabelle"
|
||||
chatKey: "0x043a7ed0e8752236a4688563652fd0296453cef00a5dcddbe252dc74f72cc1caa97a2b65e4a1a52d9c30a84c9966beaaaf6b333d659cbdd2e486b443ed1012cf04"
|
||||
trustIndicator: StatusContactVerificationIcons.TrustedType.Verified
|
||||
isMutualContact: true
|
||||
isOnline: true
|
||||
source: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAlklEQVR4nOzW0QmDQBAG4SSkl7SUQlJGCrElq9F3QdjjVhh/5nv3cFhY9vUIYQiNITSG0BhCExPynn1gWf9bx498P7/
|
||||
localNickname: "This is an example"
|
||||
displayName: "Maria"
|
||||
pubKey: "0x043a7ed0e8752236a4688563652fd0296453cef00a5dcddbe252dc74f72cc1caa97a2b65e4a1a52d9c30a84c9966beaaaf6b333d659cbdd2e486b443ed1012cf04"
|
||||
isVerified: true
|
||||
isUntrustworthy: false
|
||||
isContact: true
|
||||
onlineStatus: 1
|
||||
icon: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAlklEQVR4nOzW0QmDQBAG4SSkl7SUQlJGCrElq9F3QdjjVhh/5nv3cFhY9vUIYQiNITSG0BhCExPynn1gWf9bx498P7/
|
||||
nzPcxEzGExhBdJGYihtAYQlO+tUZvqrPbqeudo5iJGEJjCE15a3VtodH3q2ImYgiNITTlTdG1nUZ5a92VITQxITFiJmIIjSE0htAYQrMHAAD//+wwFVpz+yqXAAAAAElFTkSuQmCC"
|
||||
isIdenticon: true
|
||||
ringSpecModel: [ ListElement {colorId: 13; segmentLength: 5},
|
||||
ListElement {colorId: 31; segmentLength: 5},
|
||||
ListElement {colorId: 10; segmentLength: 1},
|
||||
ListElement {colorId: 2; segmentLength: 5},
|
||||
ListElement {colorId: 26; segmentLength: 2},
|
||||
ListElement {colorId: 19; segmentLength: 4},
|
||||
ListElement {colorId: 28; segmentLength: 3} ]
|
||||
isAdmin: false
|
||||
}
|
||||
ListElement {
|
||||
nickName: "carmen.eth"
|
||||
userName: ""
|
||||
chatKey: ""
|
||||
trustIndicator: StatusContactVerificationIcons.TrustedType.Untrustworthy
|
||||
isMutualContact: false
|
||||
isOnline: false
|
||||
source: ""
|
||||
isIdenticon: false
|
||||
localNickname: ""
|
||||
displayName: "carmen.eth"
|
||||
pubKey: "0x043a7ed78362567894688563652fd0296453cef00a5dcddbe252dc74f72cc1caa97a2b65e4a1a52d9c30a84c9966beaaaf6b333d659cbdd2e486b443ed1012cf04"
|
||||
isVerified: false
|
||||
isUntrustworthy: true
|
||||
isContact: false
|
||||
onlineStatus: 0
|
||||
icon: ""
|
||||
isAdmin: false
|
||||
}
|
||||
ListElement {
|
||||
nickName: "This girl I know from work"
|
||||
userName: "annabelle"
|
||||
chatKey: ""
|
||||
trustIndicator: StatusContactVerificationIcons.TrustedType.None
|
||||
isMutualContact: false
|
||||
isOnline: true
|
||||
source: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAiElEQVR4nOzXUQpAQBRGYWQvLNAyLJDV8C5qpiGnv/M9al5Ot27X0IUwhMYQGkNoDKGJCRlLH67bftx9X+ap/+P9VcxEDK
|
||||
localNickname: "This girl I know from work"
|
||||
displayName: "annabelle"
|
||||
pubKey: "0x043a7ed0e8752236a4688563652fd0296453cef00a5dcddbe252dc74f72cc1caa97a2b65e4a1a52d9c30a84c9966beaaaf6b333d659cbdd2e486dsfkjghyu2cf04"
|
||||
isVerified: false
|
||||
isUntrustworthy: false
|
||||
isContact: false
|
||||
onlineStatus: 1
|
||||
isAdmin: false
|
||||
icon: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAiElEQVR4nOzXUQpAQBRGYWQvLNAyLJDV8C5qpiGnv/M9al5Ot27X0IUwhMYQGkNoDKGJCRlLH67bftx9X+ap/+P9VcxEDK
|
||||
ExhKZ4a9Uq3TZviZmIITSG0DRvlqcbqVbrlouZiCE0htD4h0hjCI0hNN5aNIbQGKKPxEzEEBpDaAyhMYTmDAAA//+gYCErzmCpCQAAAABJRU5ErkJggg=="
|
||||
isIdenticon: true
|
||||
ringSpecModel: [ ListElement {colorId: 11; segmentLength: 1},
|
||||
ListElement {colorId: 23; segmentLength: 5},
|
||||
ListElement {colorId: 23; segmentLength: 5},
|
||||
ListElement {colorId: 10; segmentLength: 4},
|
||||
ListElement {colorId: 15; segmentLength: 3},
|
||||
ListElement {colorId: 26; segmentLength: 2},
|
||||
ListElement {colorId: 29; segmentLength: 5} ]
|
||||
}
|
||||
ListElement {
|
||||
nickName: "Mark Cuban"
|
||||
userName: "annabelle"
|
||||
chatKey: "0x043a7ed0e8752236a4688563652fd0296453cef00a5dcddbe252dc74f72cc1caa97a2b65e4a1a52d9c30a84c9966beaaaf6b333d659cbdd2e486b443ed1012cf04"
|
||||
trustIndicator: StatusContactVerificationIcons.TrustedType.Untrustworthy
|
||||
isMutualContact: true
|
||||
isOnline: false
|
||||
source: ""
|
||||
isIdenticon: false
|
||||
ringSpecModel: [ ListElement {colorId: 0; segmentLength: 1},
|
||||
ListElement {colorId: 28; segmentLength: 1},
|
||||
ListElement {colorId: 31; segmentLength: 1},
|
||||
ListElement {colorId: 22; segmentLength: 4},
|
||||
ListElement {colorId: 28; segmentLength: 3},
|
||||
ListElement {colorId: 27; segmentLength: 5},
|
||||
ListElement {colorId: 7; segmentLength: 5},
|
||||
ListElement {colorId: 13; segmentLength: 1},
|
||||
ListElement {colorId: 25; segmentLength: 4}]
|
||||
localNickname: "Mark Cuban"
|
||||
displayName: "mark.eth"
|
||||
pubKey: "0x043a7ed0e8752236a4688563652fd0296453cef00a5dcddbe252dc79872cc1caa97a2b65e4a1a52d9c30a84c9966beaaaf6b333d659cbdd2e486b443ed1012cf04"
|
||||
isVerified: false
|
||||
isUntrustworthy: true
|
||||
isContact: true
|
||||
onlineStatus: 0
|
||||
icon: ""
|
||||
isAdmin: false
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1019,8 +949,19 @@ CExPynn1gWf9bx498P7/nzPcxEzGExhBdJGYihtAYQlO+tUZvqrPbqeudo5iJGEJjCE15a3VtodH3q2I
|
||||
notificationsCount: 0
|
||||
}
|
||||
ListElement {
|
||||
sectionId: "wallet"
|
||||
sectionId: "communitiesPortal"
|
||||
sectionType: 2
|
||||
name: "Communities Portal"
|
||||
active: false
|
||||
image: ""
|
||||
icon: "communities"
|
||||
color: ""
|
||||
hasNotification: false
|
||||
notificationsCount: 0
|
||||
}
|
||||
ListElement {
|
||||
sectionId: "wallet"
|
||||
sectionType: 3
|
||||
name: "Wallet"
|
||||
active: false
|
||||
image: ""
|
||||
@@ -1031,7 +972,7 @@ CExPynn1gWf9bx498P7/nzPcxEzGExhBdJGYihtAYQlO+tUZvqrPbqeudo5iJGEJjCE15a3VtodH3q2I
|
||||
}
|
||||
ListElement {
|
||||
sectionId: "browser"
|
||||
sectionType: 3
|
||||
sectionType: 4
|
||||
name: "Browser"
|
||||
active: false
|
||||
image: ""
|
||||
@@ -1052,4 +993,491 @@ CExPynn1gWf9bx498P7/nzPcxEzGExhBdJGYihtAYQlO+tUZvqrPbqeudo5iJGEJjCE15a3VtodH3q2I
|
||||
notificationsCount: 0
|
||||
}
|
||||
}
|
||||
|
||||
property ListModel currencyPickerModel: ListModel {
|
||||
ListElement {
|
||||
key: 0
|
||||
name: "United States Dollar"
|
||||
shortName: "USD"
|
||||
symbol: "$"
|
||||
imageSource: "../../assets/twemoji/26x26/1f4b4.png"
|
||||
category: ""
|
||||
selected: false
|
||||
}
|
||||
ListElement {
|
||||
key: 1
|
||||
name: "British Pound"
|
||||
shortName: "GBP"
|
||||
symbol: "£"
|
||||
imageSource: "../../assets/twemoji/26x26/1f4b5.png"
|
||||
category: ""
|
||||
selected: false
|
||||
}
|
||||
ListElement {
|
||||
key: 2
|
||||
name: "Euro"
|
||||
shortName: "EUR"
|
||||
symbol: "€"
|
||||
imageSource: "../../assets/twemoji/26x26/1f4b6.png"
|
||||
category: ""
|
||||
selected: true
|
||||
}
|
||||
ListElement {
|
||||
key: 3
|
||||
name: "Shout Korean Won"
|
||||
shortName: "KRW"
|
||||
symbol: "₩"
|
||||
imageSource: "../../assets/twemoji/26x26/1f4b8.png"
|
||||
category: ""
|
||||
selected: false
|
||||
}
|
||||
ListElement {
|
||||
key: 4
|
||||
name: "Ethereum"
|
||||
shortName: "ETH"
|
||||
symbol: "Ξ"
|
||||
imageSource: "../../assets/twemoji/26x26/1f4b7.png"
|
||||
category: "Tokens"
|
||||
selected: true
|
||||
}
|
||||
ListElement {
|
||||
key: 5
|
||||
name: "Bitcoin"
|
||||
shortName: "BTC"
|
||||
symbol: "฿"
|
||||
imageSource: "../../assets/twemoji/26x26/1f4b4.png"
|
||||
category: "Tokens"
|
||||
selected: false
|
||||
}
|
||||
ListElement {
|
||||
key: 6
|
||||
name: "Status Network Token"
|
||||
shortName: "SNT"
|
||||
symbol: ""
|
||||
imageSource: "../../assets/twemoji/26x26/1f4b8.png"
|
||||
category: "Tokens"
|
||||
selected: false
|
||||
}
|
||||
|
||||
ListElement {
|
||||
key: 7
|
||||
name: "Emirati Dirham"
|
||||
shortName: "AED"
|
||||
symbol: "د.إ"
|
||||
imageSource: "../../assets/twemoji/26x26/1f4b4.png"
|
||||
category: "Other Fiat"
|
||||
selected: false
|
||||
}
|
||||
ListElement {
|
||||
key: 8
|
||||
name: "Afghani"
|
||||
shortName: "AFN"
|
||||
symbol: "؋"
|
||||
imageSource: "../../assets/twemoji/26x26/1f4b7.png"
|
||||
category: "Other Fiat"
|
||||
selected: false
|
||||
}
|
||||
ListElement {
|
||||
key: 9
|
||||
name: "Argentine Peso"
|
||||
shortName: "AFN"
|
||||
symbol: "$"
|
||||
imageSource: "../../assets/twemoji/26x26/1f4b4.png"
|
||||
category: "Other Fiat"
|
||||
selected: false
|
||||
}
|
||||
}
|
||||
|
||||
property ListModel currencyPickerModel2: ListModel {
|
||||
ListElement {
|
||||
key: 0
|
||||
name: "United States Dollar"
|
||||
shortName: "USD"
|
||||
symbol: "$"
|
||||
imageSource: "../../assets/twemoji/26x26/1f4b4.png"
|
||||
category: ""
|
||||
selected: false
|
||||
}
|
||||
ListElement {
|
||||
key: 1
|
||||
name: "British Pound"
|
||||
shortName: "GBP"
|
||||
symbol: "£"
|
||||
imageSource: "../../assets/twemoji/26x26/1f4b5.png"
|
||||
category: ""
|
||||
selected: false
|
||||
}
|
||||
ListElement {
|
||||
key: 2
|
||||
name: "Euro"
|
||||
shortName: "EUR"
|
||||
symbol: "€"
|
||||
imageSource: "../../assets/twemoji/26x26/1f4b6.png"
|
||||
category: ""
|
||||
selected: true
|
||||
}
|
||||
ListElement {
|
||||
key: 3
|
||||
name: "Shout Korean Won"
|
||||
shortName: "KRW"
|
||||
symbol: "₩"
|
||||
imageSource: "../../assets/twemoji/26x26/1f4b8.png"
|
||||
category: ""
|
||||
selected: false
|
||||
}
|
||||
ListElement {
|
||||
key: 4
|
||||
name: "Ethereum"
|
||||
shortName: "ETH"
|
||||
symbol: "Ξ"
|
||||
imageSource: "../../assets/twemoji/26x26/1f4b7.png"
|
||||
category: "Tokens"
|
||||
selected: true
|
||||
}
|
||||
ListElement {
|
||||
key: 5
|
||||
name: "Bitcoin"
|
||||
shortName: "BTC"
|
||||
symbol: "฿"
|
||||
imageSource: "../../assets/twemoji/26x26/1f4b4.png"
|
||||
category: "Tokens"
|
||||
selected: false
|
||||
}
|
||||
ListElement {
|
||||
key: 6
|
||||
name: "Status Network Token"
|
||||
shortName: "SNT"
|
||||
symbol: ""
|
||||
imageSource: "../../assets/twemoji/26x26/1f4b8.png"
|
||||
category: "Tokens"
|
||||
selected: false
|
||||
}
|
||||
|
||||
ListElement {
|
||||
key: 7
|
||||
name: "Emirati Dirham"
|
||||
shortName: "AED"
|
||||
symbol: "د.إ"
|
||||
imageSource: "../../assets/twemoji/26x26/1f4b4.png"
|
||||
category: "Other Fiat"
|
||||
selected: false
|
||||
}
|
||||
ListElement {
|
||||
key: 8
|
||||
name: "Afghani"
|
||||
shortName: "AFN"
|
||||
symbol: "؋"
|
||||
imageSource: "../../assets/twemoji/26x26/1f4b7.png"
|
||||
category: "Other Fiat"
|
||||
selected: false
|
||||
}
|
||||
ListElement {
|
||||
key: 9
|
||||
name: "Argentine Peso"
|
||||
shortName: "AFN"
|
||||
symbol: "$"
|
||||
imageSource: "../../assets/twemoji/26x26/1f4b4.png"
|
||||
category: "Other Fiat"
|
||||
selected: false
|
||||
}
|
||||
}
|
||||
|
||||
property ListModel languagePickerModel: ListModel {
|
||||
ListElement {
|
||||
key: 0
|
||||
name: "English"
|
||||
shortName: "English"
|
||||
imageSource: "../../assets/twemoji/26x26/1f1ec-1f1e7.png"
|
||||
category: ""
|
||||
selected: false
|
||||
}
|
||||
ListElement {
|
||||
key: 1
|
||||
name: "Korean"
|
||||
shortName: "한국어"
|
||||
imageSource: "../../assets/twemoji/26x26/1f1f0-1f1f7.png"
|
||||
category: ""
|
||||
selected: false
|
||||
}
|
||||
ListElement {
|
||||
key: 2
|
||||
name: "Portuguese (Brazilian)"
|
||||
shortName: "Português"
|
||||
imageSource: "../../assets/twemoji/26x26/1f1e7-1f1f7.png"
|
||||
category: ""
|
||||
selected: true
|
||||
}
|
||||
ListElement {
|
||||
key: 3
|
||||
name: "Dutch"
|
||||
shortName: "Nederlands"
|
||||
imageSource: "../../assets/twemoji/26x26/1f1f3-1f1f1.png"
|
||||
category: "Beta Languages"
|
||||
selected: false
|
||||
}
|
||||
ListElement {
|
||||
key: 4
|
||||
name: "Indonesian"
|
||||
shortName: "Bahasa Indonesia"
|
||||
imageSource: "../../assets/twemoji/26x26/1f1ee-1f1e9.png"
|
||||
category: "Beta Languages"
|
||||
selected: false
|
||||
}
|
||||
ListElement {
|
||||
key: 5
|
||||
name: "Spanish"
|
||||
shortName: "Español"
|
||||
imageSource: "../../assets/twemoji/26x26/1f1ea-1f1e6.png"
|
||||
category: "Beta Languages"
|
||||
selected: false
|
||||
}
|
||||
}
|
||||
|
||||
property ListModel languageNoImagePickerModel: ListModel {
|
||||
ListElement {
|
||||
key: 0
|
||||
name: "Chinese (Mainland China)"
|
||||
shortName: "普通话"
|
||||
category: ""
|
||||
selected: true
|
||||
}
|
||||
ListElement {
|
||||
key: 1
|
||||
name: "Russian"
|
||||
shortName: "Русский Язык"
|
||||
category: ""
|
||||
selected: false
|
||||
}
|
||||
ListElement {
|
||||
key: 2
|
||||
name: "Arabic"
|
||||
shortName: "اَلْعَرَبِيَّةُ"
|
||||
category: "Beta Languages"
|
||||
selected: true
|
||||
}
|
||||
ListElement {
|
||||
key: 3
|
||||
name: "Chinese (Taiwan)"
|
||||
shortName: "臺灣華語"
|
||||
category: "Beta Languages"
|
||||
selected: false
|
||||
}
|
||||
ListElement {
|
||||
key: 4
|
||||
name: "Filipino"
|
||||
shortName: "Wikang Filipino"
|
||||
category: "Beta Languages"
|
||||
selected: false
|
||||
}
|
||||
ListElement {
|
||||
key: 5
|
||||
name: "French"
|
||||
shortName: "Français"
|
||||
category: "Beta Languages"
|
||||
selected: false
|
||||
}
|
||||
ListElement {
|
||||
key: 6
|
||||
name: "Italian"
|
||||
shortName: "Italiano"
|
||||
category: "Beta Languages"
|
||||
selected: false
|
||||
}
|
||||
ListElement {
|
||||
key: 7
|
||||
name: "Turkish"
|
||||
shortName: "Türkçe"
|
||||
category: "Beta Languages"
|
||||
selected: false
|
||||
}
|
||||
ListElement {
|
||||
key: 8
|
||||
name: "Urdu"
|
||||
shortName: "اُردُو"
|
||||
category: "Beta Languages"
|
||||
selected: false
|
||||
}
|
||||
}
|
||||
|
||||
property ListModel featuredCommunitiesModel : ListModel {
|
||||
ListElement {
|
||||
name: "CryptoKitties";
|
||||
description: "A community of cat lovers, meow!";
|
||||
logo:"qrc:/images/CryptoKitties.png";
|
||||
members: 1045;
|
||||
categories: [];
|
||||
communityId: "341";
|
||||
available: true;
|
||||
popularity: 1;
|
||||
communityColor: "pink"
|
||||
}
|
||||
ListElement {
|
||||
name: "Friends with Benefits";
|
||||
description: "A group chat full of out favorite thinkers and creators.";
|
||||
logo:"qrc:/images/FriendsBenefits.png";
|
||||
members: 452;
|
||||
categories: [];
|
||||
communityId: "232";
|
||||
available: true;
|
||||
popularity: 2;
|
||||
communityColor: "grey"
|
||||
}
|
||||
ListElement {
|
||||
name: "Status Hi!!";
|
||||
description: "A new community description with long long long and repetitive repetitive repetitive repetitive explanation!!";
|
||||
logo:"qrc:/images/SNT.png";
|
||||
members: 89;
|
||||
categories: [];
|
||||
communityId: "223";
|
||||
available: true;
|
||||
popularity: 3
|
||||
communityColor: "blue"
|
||||
}
|
||||
}
|
||||
|
||||
property ListModel curatedCommunitiesModel : ListModel {
|
||||
ListElement {
|
||||
name: "Status.im";
|
||||
description: "Your portal to Web3. Secure wallet. dApp browser. Private messaging. All-in-one.";
|
||||
logo: "qrc:/images/SNT.png";
|
||||
banner: "qrc:/images/CommunityBanner1.png";
|
||||
members: 299500;
|
||||
activeUsers: 71400;
|
||||
categories: [];
|
||||
communityId: "1";
|
||||
available: true;
|
||||
popularity: 1
|
||||
isPrivate: true
|
||||
tokenLogo: "qrc:/images/SNT.png";
|
||||
}
|
||||
ListElement {
|
||||
name: "SuperRare";
|
||||
description: "The future of CryptoArt markets—a network governed by artists, collectors and curators.";
|
||||
logo:"qrc:/images/SR.png";
|
||||
banner: "qrc:/images/SuperRareCommunityBanner.png";
|
||||
members: 299500;
|
||||
activeUsers: 71400;
|
||||
categories: [];
|
||||
communityId: "2";
|
||||
available: true;
|
||||
popularity: 2
|
||||
isPrivate: true
|
||||
tokenLogo: "qrc:/images/SRToken.png";
|
||||
}
|
||||
ListElement {
|
||||
name: "Coinbase";
|
||||
description: "Jump start your crypto portfolio with the easiest place to buy and sell crypto. ";
|
||||
logo:"qrc:/images/Coinbase.png";
|
||||
banner: "qrc:/images/CoinBaseCommunityBanner.png";
|
||||
members: 4900000;
|
||||
activeUsers: 245600;
|
||||
categories: [];
|
||||
communityId: "3";
|
||||
available: true;
|
||||
popularity: 3
|
||||
isPrivate: false
|
||||
tokenLogo: "";
|
||||
}
|
||||
ListElement {
|
||||
name: "Rarible";
|
||||
description: "Multichain community-centric NFT marketplace. Create, sell and collect NFTs.";
|
||||
logo:"qrc:/images/Rarible.png";
|
||||
banner: "qrc:/images/RaribleCommunityBanner.png";
|
||||
members: 629200;
|
||||
activeUsers: 112100;
|
||||
categories: [];
|
||||
communityId: "4";
|
||||
available: true;
|
||||
popularity: 4
|
||||
isPrivate: true
|
||||
tokenLogo: "qrc:/images/RARI.png";
|
||||
}
|
||||
ListElement {
|
||||
name: "Spotify";
|
||||
description: "Listening is everything";
|
||||
logo:"qrc:/images/Spotify.png";
|
||||
banner: "qrc:/images/SpotifyCommunityBanner.png";
|
||||
members: 207500;
|
||||
activeUsers: 52200;
|
||||
categories: [];
|
||||
communityId: "5";
|
||||
available: true;
|
||||
popularity: 5
|
||||
isPrivate: false
|
||||
tokenLogo: "";
|
||||
}
|
||||
ListElement {
|
||||
name: "Dribbble";
|
||||
description: "Open source platform to write and distribute decentralized applications..";
|
||||
logo:"qrc:/images/Fluff.png";
|
||||
banner: "qrc:/images/DribbbleCommunityBanner.png";
|
||||
members: 2300000;
|
||||
activeUsers: 112100;
|
||||
categories: [];
|
||||
communityId: "6";
|
||||
available: true;
|
||||
popularity: 6
|
||||
isPrivate: false
|
||||
tokenLogo: "";
|
||||
}
|
||||
ListElement {
|
||||
name: "Status.im";
|
||||
description: "Your portal to Web3. Secure wallet. dApp browser. Private messaging. All-in-one.";
|
||||
logo:"qrc:/images/SNT.png";
|
||||
banner: ""
|
||||
members: 299500;
|
||||
activeUsers: 71400;
|
||||
categories: [];
|
||||
communityId: "7";
|
||||
available: true;
|
||||
popularity: 1
|
||||
isPrivate: false
|
||||
tokenLogo: "";
|
||||
}
|
||||
ListElement {
|
||||
name: "CryptoPunks";
|
||||
description: "Community description goes here. Community description goes here. Community description goes here. Community description goes here. Community description goes here. Community description goes here.";
|
||||
logo:"qrc:/images/CryptoPunks.png";
|
||||
banner: "";
|
||||
members: 4900;
|
||||
activeUsers: 245600;
|
||||
categories: [];
|
||||
communityId: "8";
|
||||
available: false;
|
||||
popularity: 8
|
||||
isPrivate: false
|
||||
tokenLogo: "";
|
||||
}
|
||||
ListElement {
|
||||
name: "Socks";
|
||||
description: "Community description goes here.";
|
||||
logo:"qrc:/images/Socks.png";
|
||||
banner: "";
|
||||
members: 4900;
|
||||
activeUsers: 245600;
|
||||
categories: [];
|
||||
communityId: "9";
|
||||
available: false;
|
||||
popularity: 9
|
||||
isPrivate: false
|
||||
tokenLogo: "";
|
||||
}
|
||||
}
|
||||
|
||||
property ListModel tagsModel : ListModel {
|
||||
ListElement { name: "gaming"; emoji: "🎮"}
|
||||
ListElement { name: "art"; emoji: "🖼️️"}
|
||||
ListElement { name: "crypto"; emoji: "💸"}
|
||||
ListElement { name: "nsfw"; emoji: "🍆"}
|
||||
ListElement { name: "markets"; emoji: "💎"}
|
||||
ListElement { name: "defi"; emoji: "📈"}
|
||||
ListElement { name: "travel"; emoji: "🚁"}
|
||||
ListElement { name: "web3"; emoji: "🗺"}
|
||||
ListElement { name: "sport"; emoji: "🎾"}
|
||||
ListElement { name: "food"; emoji: "🥑"}
|
||||
ListElement { name: "enviroment"; emoji: "☠️"}
|
||||
ListElement { name: "privacy"; emoji: "👻"}
|
||||
}
|
||||
|
||||
property var communityTags :{"Activism":"✊","Art":"🎨","Blockchain":"🔗","Books & blogs":"📚","Career":"💼","Collaboration":"🤝","Commerce":"🛒","Crypto":"Ξ","Culture":"🎎","DAO":"🚀","DIY":"🔨","DeFi":"📈","Design":"🧩","Education":"🎒","Entertainment":"🍿","Environment":"🌿","Event":"🗓","Fantasy":"🧙♂️","Fashion":"🧦","Food":"🌶","Gaming":"🎮","Global":"🌍","Health":"🧠","Hobby":"📐","Innovation":"🧪","Language":"📜","Lifestyle":"✨","Local":"📍","Love":"❤️","Markets":"💎","Movies & TV":"🎞","Music":"🎶","NFT":"🖼","NSFW":"🍆","News":"🗞","Non-profit":"🙏","Org":"🏢","Pets":"🐶","Play":"🎲","Podcast":"🎙️","Politics":"🗳️","Privacy":"👻","Product":"🍱","Psyche":"🍁","Security":"🔒","Social":"☕","Software dev":"👩💻","Sports":"⚽️","Tech":"📱","Travel":"🗺","Vehicles":"🚕","Web3":"🌐"}
|
||||
}
|
||||
|
||||
|
After Width: | Height: | Size: 190 KiB |
|
After Width: | Height: | Size: 9.5 KiB |
|
After Width: | Height: | Size: 1.6 KiB |
|
After Width: | Height: | Size: 33 KiB |
|
After Width: | Height: | Size: 2.8 KiB |
|
After Width: | Height: | Size: 838 B |
|
After Width: | Height: | Size: 1.5 KiB |
|
After Width: | Height: | Size: 21 KiB |
|
After Width: | Height: | Size: 398 B |
|
After Width: | Height: | Size: 22 KiB |
|
After Width: | Height: | Size: 2.1 KiB |
|
After Width: | Height: | Size: 2.5 KiB |
|
After Width: | Height: | Size: 957 B |
|
After Width: | Height: | Size: 1009 B |
|
After Width: | Height: | Size: 1.2 KiB |
|
After Width: | Height: | Size: 50 KiB |
|
After Width: | Height: | Size: 730 B |
|
After Width: | Height: | Size: 1.4 KiB |
|
After Width: | Height: | Size: 1.3 KiB |
|
After Width: | Height: | Size: 2.2 KiB |
|
After Width: | Height: | Size: 3.4 KiB |
|
After Width: | Height: | Size: 9.7 KiB |
|
After Width: | Height: | Size: 3.0 KiB |
|
After Width: | Height: | Size: 45 KiB |
|
After Width: | Height: | Size: 190 KiB |
@@ -11,6 +11,13 @@ int main(int argc, char *argv[])
|
||||
#endif
|
||||
|
||||
SandboxApp app(argc, argv);
|
||||
|
||||
qputenv("QT_QUICK_CONTROLS_HOVER_ENABLED", QByteArrayLiteral("1"));
|
||||
|
||||
app.setOrganizationName("Status");
|
||||
app.setOrganizationDomain("status.im");
|
||||
app.setApplicationName("Sandbox");
|
||||
|
||||
app.startEngine();
|
||||
|
||||
return app.exec();
|
||||
|
||||
@@ -2,6 +2,8 @@ import QtQuick 2.14
|
||||
import QtQuick.Window 2.14
|
||||
import QtQuick.Controls 2.14
|
||||
import QtGraphicalEffects 1.13
|
||||
import QtQuick.Layouts 1.14
|
||||
import Qt.labs.settings 1.0
|
||||
|
||||
import Sandbox 0.1
|
||||
|
||||
@@ -31,10 +33,7 @@ StatusWindow {
|
||||
|
||||
property real factor: 1.0
|
||||
|
||||
Component.onCompleted: {
|
||||
Theme.palette = lightTheme
|
||||
rootWindow.updatePosition();
|
||||
}
|
||||
Component.onCompleted: rootWindow.updatePosition()
|
||||
|
||||
QtObject {
|
||||
id: appSectionType
|
||||
@@ -110,12 +109,10 @@ StatusWindow {
|
||||
anchors.topMargin: 32
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: 32
|
||||
onCheckedChanged: {
|
||||
if (Theme.palette === rootWindow.lightTheme) {
|
||||
Theme.palette = rootWindow.darkTheme
|
||||
} else {
|
||||
Theme.palette = rootWindow.lightTheme
|
||||
}
|
||||
lightThemeEnabled: storeSettings.lightTheme
|
||||
onLightThemeEnabledChanged: {
|
||||
Theme.palette = lightThemeEnabled ? rootWindow.darkTheme : rootWindow.lightTheme
|
||||
storeSettings.lightTheme = lightThemeEnabled
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -126,11 +123,13 @@ StatusWindow {
|
||||
StatusAppTwoPanelLayout {
|
||||
id: mainPageView
|
||||
|
||||
function page(name) {
|
||||
function page(name, fillPage) {
|
||||
storeSettings.fillPage = fillPage ? true : false
|
||||
viewLoader.source = Qt.resolvedUrl("./pages/" + name + "Page.qml");
|
||||
}
|
||||
function control(name) {
|
||||
viewLoader.source = Qt.resolvedUrl("./controls/" + name + ".qml");
|
||||
storeSettings.fillPage = false
|
||||
}
|
||||
|
||||
leftPanel: Item {
|
||||
@@ -150,76 +149,81 @@ StatusWindow {
|
||||
spacing: 0
|
||||
|
||||
StatusListSectionHeadline { text: "StatusQ.Core" }
|
||||
StatusNavigationListItem {
|
||||
StatusNavigationListItem {
|
||||
title: "Icons"
|
||||
selected: viewLoader.source.toString().includes(title)
|
||||
onClicked: mainPageView.control(title);
|
||||
}
|
||||
|
||||
StatusListSectionHeadline { text: "StatusQ.Layout" }
|
||||
StatusNavigationListItem {
|
||||
StatusNavigationListItem {
|
||||
title: "Layouts"
|
||||
selected: viewLoader.source.toString().includes(title)
|
||||
onClicked: mainPageView.control(title.substring(0, title.length - 1));
|
||||
}
|
||||
|
||||
StatusListSectionHeadline { text: "StatusQ.Controls" }
|
||||
StatusNavigationListItem {
|
||||
StatusNavigationListItem {
|
||||
title: "Buttons"
|
||||
selected: viewLoader.source.toString().includes(title)
|
||||
onClicked: mainPageView.control(title);
|
||||
}
|
||||
StatusNavigationListItem {
|
||||
StatusNavigationListItem {
|
||||
title: "StatusSwitchTab"
|
||||
selected: viewLoader.source.toString().includes(title)
|
||||
onClicked: mainPageView.page("StatusTabSwitch");
|
||||
}
|
||||
StatusNavigationListItem {
|
||||
StatusNavigationListItem {
|
||||
title: "StatusChatCommandButton"
|
||||
selected: viewLoader.source.toString().includes(title)
|
||||
onClicked: mainPageView.page(title);
|
||||
}
|
||||
StatusNavigationListItem {
|
||||
StatusNavigationListItem {
|
||||
title: "Controls"
|
||||
selected: viewLoader.source.toString().includes(title)
|
||||
onClicked: mainPageView.control(title);
|
||||
}
|
||||
StatusNavigationListItem {
|
||||
title: "StatusTabBarButton"
|
||||
selected: viewLoader.source.toString().includes(title)
|
||||
onClicked: mainPageView.page(title);
|
||||
}
|
||||
StatusNavigationListItem {
|
||||
title: "StatusTabBarIconButton"
|
||||
selected: viewLoader.source.toString().includes(title)
|
||||
onClicked: mainPageView.page(title);
|
||||
}
|
||||
StatusNavigationListItem {
|
||||
StatusNavigationListItem {
|
||||
title: "StatusInput"
|
||||
selected: viewLoader.source.toString().includes(title)
|
||||
onClicked: mainPageView.page(title);
|
||||
}
|
||||
StatusNavigationListItem {
|
||||
StatusNavigationListItem {
|
||||
title: "StatusSelect"
|
||||
selected: viewLoader.source.toString().includes(title)
|
||||
onClicked: mainPageView.page(title);
|
||||
}
|
||||
StatusNavigationListItem {
|
||||
StatusNavigationListItem {
|
||||
title: "StatusAccountSelector"
|
||||
selected: viewLoader.source.toString().includes(title)
|
||||
onClicked: mainPageView.page(title);
|
||||
}
|
||||
StatusNavigationListItem {
|
||||
StatusNavigationListItem {
|
||||
title: "StatusAssetSelector"
|
||||
selected: viewLoader.source.toString().includes(title)
|
||||
onClicked: mainPageView.page(title);
|
||||
}
|
||||
StatusNavigationListItem {
|
||||
StatusNavigationListItem {
|
||||
title: "StatusColorSelector"
|
||||
selected: viewLoader.source.toString().includes(title)
|
||||
onClicked: mainPageView.page(title);
|
||||
}
|
||||
StatusNavigationListItem {
|
||||
StatusNavigationListItem {
|
||||
title: "StatusWalletColorButton"
|
||||
selected: viewLoader.source.toString().includes(title)
|
||||
onClicked: mainPageView.page(title);
|
||||
}
|
||||
StatusNavigationListItem {
|
||||
StatusNavigationListItem {
|
||||
title: "StatusWalletColorSelect"
|
||||
selected: viewLoader.source.toString().includes(title)
|
||||
onClicked: mainPageView.page(title);
|
||||
@@ -235,22 +239,22 @@ StatusWindow {
|
||||
onClicked: mainPageView.page(title);
|
||||
}
|
||||
StatusListSectionHeadline { text: "StatusQ.Components" }
|
||||
StatusNavigationListItem {
|
||||
StatusNavigationListItem {
|
||||
title: "StatusAddress"
|
||||
selected: viewLoader.source.toString().includes(title)
|
||||
onClicked: mainPageView.page(title);
|
||||
}
|
||||
StatusNavigationListItem {
|
||||
StatusNavigationListItem {
|
||||
title: "List Items"
|
||||
selected: viewLoader.source.toString().includes(title.replace(/\s+/g, ''))
|
||||
onClicked: mainPageView.control(title.replace(/\s+/g, ''));
|
||||
}
|
||||
StatusNavigationListItem {
|
||||
StatusNavigationListItem {
|
||||
title: "StatusChatInfoToolBar"
|
||||
selected: viewLoader.source.toString().includes(title)
|
||||
onClicked: mainPageView.page(title);
|
||||
}
|
||||
StatusNavigationListItem {
|
||||
StatusNavigationListItem {
|
||||
title: "Others"
|
||||
selected: viewLoader.source.toString().includes(title)
|
||||
onClicked: mainPageView.control(title);
|
||||
@@ -275,18 +279,37 @@ StatusWindow {
|
||||
selected: viewLoader.source.toString().includes(title)
|
||||
onClicked: mainPageView.page(title);
|
||||
}
|
||||
StatusNavigationListItem {
|
||||
title: "StatusListPicker"
|
||||
selected: viewLoader.source.toString().includes(title)
|
||||
onClicked: mainPageView.page(title);
|
||||
}
|
||||
StatusNavigationListItem {
|
||||
title: "StatusCommunityCard"
|
||||
selected: viewLoader.source.toString().includes(title)
|
||||
onClicked: mainPageView.page(title);
|
||||
}
|
||||
StatusNavigationListItem {
|
||||
title: "StatusCommunityTags"
|
||||
selected: viewLoader.source.toString().includes(title)
|
||||
onClicked: mainPageView.page(title);
|
||||
}
|
||||
StatusListSectionHeadline { text: "StatusQ.Popup" }
|
||||
StatusNavigationListItem {
|
||||
StatusNavigationListItem {
|
||||
title: "StatusPopupMenu"
|
||||
selected: viewLoader.source.toString().includes(title)
|
||||
onClicked: mainPageView.page(title);
|
||||
}
|
||||
|
||||
StatusNavigationListItem {
|
||||
title: "StatusModal"
|
||||
selected: viewLoader.source.toString().includes("Popups")
|
||||
onClicked: mainPageView.control("Popups");
|
||||
}
|
||||
StatusNavigationListItem {
|
||||
title: "StatusDialog"
|
||||
selected: viewLoader.source.toString().includes(title)
|
||||
onClicked: mainPageView.page(title);
|
||||
}
|
||||
StatusListSectionHeadline { text: "StatusQ.Platform" }
|
||||
StatusNavigationListItem {
|
||||
title: "StatusMacNotification"
|
||||
@@ -298,6 +321,16 @@ StatusWindow {
|
||||
selected: viewLoader.source.toString().includes(title)
|
||||
onClicked: mainPageView.page(title);
|
||||
}
|
||||
StatusNavigationListItem {
|
||||
title: "StatusImageCropPanel"
|
||||
selected: viewLoader.source.toString().includes(title)
|
||||
onClicked: mainPageView.page(title, true);
|
||||
}
|
||||
StatusNavigationListItem {
|
||||
title: "StatusColorSpace"
|
||||
selected: viewLoader.source.toString().includes(title)
|
||||
onClicked: mainPageView.page(title, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -305,8 +338,11 @@ StatusWindow {
|
||||
rightPanel: Item {
|
||||
id: rightPanel
|
||||
anchors.fill: parent
|
||||
|
||||
ScrollView {
|
||||
visible: !storeSettings.fillPage
|
||||
anchors.fill: parent
|
||||
anchors.topMargin: 64
|
||||
contentHeight: (pageWrapper.height + pageWrapper.anchors.topMargin) * rootWindow.factor
|
||||
contentWidth: (pageWrapper.width * rootWindow.factor)
|
||||
clip: true
|
||||
@@ -315,14 +351,16 @@ StatusWindow {
|
||||
id: pageWrapper
|
||||
width: rightPanel.width
|
||||
anchors.top: parent.top
|
||||
anchors.topMargin: 64
|
||||
height: Math.max(rootWindow.height, viewLoader.height + 128)
|
||||
scale: rootWindow.factor
|
||||
|
||||
Loader {
|
||||
id: viewLoader
|
||||
active: !storeSettings.fillPage
|
||||
anchors.centerIn: parent
|
||||
source: mainPageView.control("Icons")
|
||||
source: storeSettings.selected.length === 0 ? mainPageView.control("Icons") : storeSettings.selected
|
||||
onSourceChanged: {
|
||||
storeSettings.selected = viewLoader.source
|
||||
if (source.toString().includes("Icons")) {
|
||||
item.iconColor = Theme.palette.primaryColor1;
|
||||
}
|
||||
@@ -330,6 +368,15 @@ StatusWindow {
|
||||
}
|
||||
}
|
||||
}
|
||||
Loader {
|
||||
active: storeSettings.fillPage
|
||||
anchors.fill: parent
|
||||
anchors.topMargin: 64
|
||||
visible: storeSettings.fillPage
|
||||
clip: true
|
||||
|
||||
source: viewLoader.source
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -447,4 +494,11 @@ StatusWindow {
|
||||
rootWindow.toggleFullScreen()
|
||||
}
|
||||
}
|
||||
|
||||
Settings {
|
||||
id: storeSettings
|
||||
property string selected: ""
|
||||
property bool lightTheme: true
|
||||
property bool fillPage: false
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,110 @@
|
||||
import QtQuick 2.14
|
||||
import QtQuick.Controls 2.14
|
||||
import QtQuick.Layouts 1.14
|
||||
|
||||
import StatusQ.Core 0.1
|
||||
import StatusQ.Core.Theme 0.1
|
||||
import StatusQ.Controls 0.1
|
||||
import StatusQ.Components 0.1
|
||||
|
||||
import Sandbox 0.1
|
||||
|
||||
Item {
|
||||
|
||||
ColumnLayout {
|
||||
anchors.centerIn: parent
|
||||
|
||||
StatusBaseText {
|
||||
text: qsTr("Thickness")
|
||||
}
|
||||
|
||||
StatusSlider {
|
||||
id: thicknessSlider
|
||||
from: colorSpace.width / 8
|
||||
to: colorSpace.width / 16
|
||||
value: colorSpace.width / 10
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
|
||||
StatusBaseText {
|
||||
text: qsTr("Min saturate: ") + colorSpace.minSaturate.toFixed(2)
|
||||
}
|
||||
|
||||
StatusSlider {
|
||||
id: minSatSlider
|
||||
from: 0
|
||||
to: 0.5
|
||||
value: 0
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
|
||||
StatusBaseText {
|
||||
text: qsTr("Max saturate: ") + colorSpace.maxSaturate.toFixed(2)
|
||||
}
|
||||
|
||||
StatusSlider {
|
||||
id: maxSatSlider
|
||||
from: 0.51
|
||||
to: 1.0
|
||||
value: 1.0
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
|
||||
StatusBaseText {
|
||||
text: qsTr("Min value: ") + colorSpace.minValue.toFixed(2)
|
||||
}
|
||||
|
||||
StatusSlider {
|
||||
id: minValSlider
|
||||
from: 0
|
||||
to: 0.5
|
||||
value: 0
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
|
||||
StatusBaseText {
|
||||
text: qsTr("Max value: ") + colorSpace.maxValue.toFixed(2)
|
||||
}
|
||||
|
||||
StatusSlider {
|
||||
id: maxValSlider
|
||||
from: 0.51
|
||||
to: 1.0
|
||||
value: 1.0
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
|
||||
StatusColorSpace {
|
||||
id: colorSpace
|
||||
color: "#ed77eb"
|
||||
thickness: thicknessSlider.value
|
||||
minSaturate: minSatSlider.value
|
||||
maxSaturate: maxSatSlider.value
|
||||
minValue: minValSlider.value
|
||||
maxValue: maxValSlider.value
|
||||
}
|
||||
|
||||
StatusBaseText {
|
||||
text: qsTr("Color") + ": " + colorSpace.color
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
color: colorSpace.color
|
||||
implicitHeight: 48
|
||||
radius: 10
|
||||
Layout.fillWidth: true
|
||||
|
||||
StatusBaseText {
|
||||
anchors.centerIn: parent
|
||||
color: Theme.palette.white
|
||||
font.pixelSize: 15
|
||||
text: "Quick brown fox jumps over the lazy dog"
|
||||
}
|
||||
}
|
||||
|
||||
StatusButton {
|
||||
text: "Randomize"
|
||||
onPressed: colorSpace.color = Qt.rgba(Math.random(), Math.random(), Math.random(), 1)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
import QtQuick 2.0
|
||||
import QtQuick.Layouts 1.13
|
||||
|
||||
import StatusQ.Components 0.1
|
||||
|
||||
import "../demoapp/data" 1.0
|
||||
|
||||
GridLayout {
|
||||
|
||||
QtObject {
|
||||
id: d
|
||||
|
||||
function navigateToCommunity(communityID) {
|
||||
console.log("Clicked community: " + communityID)
|
||||
}
|
||||
}
|
||||
|
||||
Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter
|
||||
columns: 2
|
||||
columnSpacing: 28
|
||||
rowSpacing: 28
|
||||
|
||||
Repeater {
|
||||
model: Models.curatedCommunitiesModel
|
||||
delegate: StatusCommunityCard {
|
||||
locale: "en"
|
||||
communityId: model.communityId
|
||||
loaded: model.available
|
||||
logo: model.logo
|
||||
banner: model.banner
|
||||
name: model.name
|
||||
description: model.description
|
||||
members: model.members
|
||||
activeUsers: model.activeUsers
|
||||
popularity: model.popularity
|
||||
isPrivate: model.isPrivate
|
||||
tokenLogo: model.tokenLogo
|
||||
categories: ListModel {
|
||||
ListElement { name: "Crypto"; emoji: "🔗"}
|
||||
ListElement { name: "Privacy"; emoji: "👻"}
|
||||
ListElement { name: "Social"; emoji: "☕"}
|
||||
}
|
||||
|
||||
onClicked: { d.navigateToCommunity(communityId) }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
import QtQuick 2.14
|
||||
import QtQuick.Controls 2.14
|
||||
import QtQuick.Layouts 1.14
|
||||
|
||||
import StatusQ.Core 0.1
|
||||
import StatusQ.Core.Theme 0.1
|
||||
import StatusQ.Controls 0.1
|
||||
import StatusQ.Components 0.1
|
||||
|
||||
import Sandbox 0.1
|
||||
|
||||
import "../demoapp/data" 1.0
|
||||
|
||||
Item {
|
||||
|
||||
property int cntSelectedTags: 0
|
||||
property int maxSelectedTags: 4
|
||||
property ListModel tagsModel: ListModel {}
|
||||
|
||||
Component.onCompleted: {
|
||||
tagsModel.clear();
|
||||
for (const key of Object.keys(Models.communityTags)) {
|
||||
tagsModel.append({ name: key, emoji: Models.communityTags[key], selected: false });
|
||||
}
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
id: column
|
||||
anchors.centerIn: parent
|
||||
width: 600
|
||||
height: 500
|
||||
spacing: 20
|
||||
|
||||
StatusInput {
|
||||
id: tagsFilter
|
||||
leftPadding: 0
|
||||
rightPadding: 0
|
||||
label: qsTr("Select tags that will fit your Community")
|
||||
input.icon.name: "search"
|
||||
input.placeholderText: qsTr("Search tags")
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
|
||||
StatusCommunityTags {
|
||||
filterString: tagsFilter.text
|
||||
model: tagsModel
|
||||
enabled: cntSelectedTags < maxSelectedTags
|
||||
onClicked: {
|
||||
cntSelectedTags++;
|
||||
item.selected = true;
|
||||
}
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
StatusBaseText {
|
||||
text: qsTr("Selected tags")
|
||||
font.pixelSize: 15
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
|
||||
StatusBaseText {
|
||||
text: cntSelectedTags + "/" + maxSelectedTags
|
||||
color: Theme.palette.baseColor1
|
||||
font.pixelSize: 13
|
||||
}
|
||||
}
|
||||
|
||||
StatusCommunityTags {
|
||||
model: tagsModel
|
||||
showOnlySelected: true
|
||||
onClicked: {
|
||||
cntSelectedTags--;
|
||||
item.selected = false;
|
||||
}
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
|
||||
Item {
|
||||
Layout.fillHeight: true
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,282 @@
|
||||
import QtQuick 2.14
|
||||
import QtQuick.Controls 2.14
|
||||
import QtQuick.Layouts 1.14
|
||||
import QtQml.Models 2.14
|
||||
|
||||
import StatusQ.Core 0.1
|
||||
import StatusQ.Controls 0.1
|
||||
import StatusQ.Popups.Dialog 0.1
|
||||
import StatusQ.Core.Theme 0.1
|
||||
import StatusQ.Components 0.1
|
||||
|
||||
ColumnLayout {
|
||||
id: root
|
||||
|
||||
StatusButton {
|
||||
text: "Content"
|
||||
onClicked: contentDialog.open()
|
||||
|
||||
StatusDialog {
|
||||
id: contentDialog
|
||||
|
||||
standardButtons: Dialog.ApplyRole
|
||||
|
||||
StatusBaseText {
|
||||
anchors.fill: parent
|
||||
text: "Content"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
StatusButton {
|
||||
text: "Title and content"
|
||||
onClicked: titleContentDialog.open()
|
||||
|
||||
StatusDialog {
|
||||
id: titleContentDialog
|
||||
title: "Title"
|
||||
|
||||
StatusBaseText {
|
||||
anchors.fill: parent
|
||||
text: "Content"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
StatusButton {
|
||||
text: "No buttons"
|
||||
onClicked: noButtonsDialog.open()
|
||||
|
||||
StatusDialog {
|
||||
id: noButtonsDialog
|
||||
title: "No buttons"
|
||||
|
||||
standardButtons: Dialog.NoButton
|
||||
|
||||
StatusBaseText {
|
||||
anchors.fill: parent
|
||||
text: "Content"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
StatusButton {
|
||||
text: "Long title"
|
||||
onClicked: longTitleDialog.open()
|
||||
|
||||
StatusDialog {
|
||||
id: longTitleDialog
|
||||
title: "Long title long title Long title long title Long title long title"
|
||||
|
||||
StatusBaseText {
|
||||
anchors.fill: parent
|
||||
text: "Content"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
StatusButton {
|
||||
text: "Long title elided"
|
||||
onClicked: longTitleElidedDialog.open()
|
||||
|
||||
StatusDialog {
|
||||
id: longTitleElidedDialog
|
||||
title: "Long title long title Long title long title Long title long title"
|
||||
|
||||
width: 400
|
||||
|
||||
StatusBaseText {
|
||||
anchors.fill: parent
|
||||
text: "Content"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
StatusButton {
|
||||
text: "Title subtitle"
|
||||
onClicked: titleSubtitleDialog.open()
|
||||
|
||||
StatusDialog {
|
||||
id: titleSubtitleDialog
|
||||
title: "This title will be ignored"
|
||||
|
||||
header: StatusDialogHeader {
|
||||
headline.title: "Title"
|
||||
headline.subtitle: "Subtitle"
|
||||
|
||||
actions.closeButton.onClicked: titleSubtitleDialog.close()
|
||||
}
|
||||
|
||||
StatusBaseText {
|
||||
anchors.fill: parent
|
||||
text: "Content"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
StatusButton {
|
||||
text: "Auto adjustable"
|
||||
onClicked: autoAdjustableDialog.open()
|
||||
|
||||
StatusDialog {
|
||||
id: autoAdjustableDialog
|
||||
|
||||
header: StatusDialogHeader {
|
||||
headline.title: "Dialog size will auto adapt"
|
||||
headline.subtitle: "To conent size"
|
||||
|
||||
actions.closeButton.onClicked: autoAdjustableDialog.close()
|
||||
}
|
||||
|
||||
footer: StatusDialogFooter {
|
||||
leftButtons: ObjectModel {
|
||||
StatusRoundButton {
|
||||
icon.name: "arrow-left"
|
||||
onClicked: autoAdjustableDialogContent.implicitWidth -= 100
|
||||
}
|
||||
StatusRoundButton {
|
||||
icon.name: "arrow-right"
|
||||
onClicked: autoAdjustableDialogContent.implicitWidth += 100
|
||||
}
|
||||
}
|
||||
rightButtons: ObjectModel {
|
||||
StatusRoundButton {
|
||||
icon.name: "arrow-down"
|
||||
onClicked: autoAdjustableDialogContent.implicitHeight -= 100
|
||||
}
|
||||
StatusRoundButton {
|
||||
icon.name: "arrow-up"
|
||||
onClicked: autoAdjustableDialogContent.implicitHeight += 100
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: autoAdjustableDialogContent
|
||||
|
||||
anchors.fill: parent
|
||||
|
||||
implicitWidth: 200
|
||||
implicitHeight: 200
|
||||
|
||||
color: Theme.palette.primaryColor3
|
||||
|
||||
StatusBaseText {
|
||||
anchors.centerIn: parent
|
||||
text: "W: %1 H: %2\nIW: %3 IH: %4".arg(parent.width).arg(parent.height).arg(parent.implicitWidth).arg(parent.implicitHeight)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
StatusButton {
|
||||
text: "Complex dialog"
|
||||
onClicked: complexDialog.open()
|
||||
|
||||
StatusDialog {
|
||||
id: complexDialog
|
||||
|
||||
header: StatusDialogHeader {
|
||||
id: dialogHeader
|
||||
|
||||
headline.title: "Complex dialog"
|
||||
headline.subtitle: "identicon, title subtitle, custom actions"
|
||||
|
||||
leftComponent: StatusLetterIdenticon {
|
||||
name: dialogHeader.headline.title
|
||||
}
|
||||
|
||||
actions {
|
||||
infoButton.visible: true
|
||||
|
||||
customButtons: ObjectModel {
|
||||
StatusFlatRoundButton {
|
||||
icon.name: "warning"
|
||||
icon.width: 20
|
||||
icon.height: 20
|
||||
}
|
||||
}
|
||||
|
||||
closeButton.onClicked: complexDialog.close()
|
||||
}
|
||||
}
|
||||
|
||||
footer: StatusDialogFooter {
|
||||
leftButtons: ObjectModel {
|
||||
StatusRoundButton {
|
||||
icon.name: "arrow-left"
|
||||
}
|
||||
}
|
||||
rightButtons: ObjectModel {
|
||||
StatusButton {
|
||||
text: "Custom cancel action"
|
||||
type: StatusButton.Danger
|
||||
}
|
||||
StatusButton {
|
||||
text: "Custom approve action"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
anchors.fill: parent
|
||||
|
||||
StatusBaseText {
|
||||
text: "Content A"
|
||||
}
|
||||
|
||||
StatusBaseText {
|
||||
text: "Content B"
|
||||
}
|
||||
|
||||
StatusBaseText {
|
||||
text: "Content C"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
StatusButton {
|
||||
text: "Custom header/footer"
|
||||
onClicked: customHeaderAndFooter.open()
|
||||
|
||||
StatusDialog {
|
||||
id: customHeaderAndFooter
|
||||
title: "No buttons"
|
||||
|
||||
header: Rectangle {
|
||||
implicitHeight: customHeaderText.height * 2
|
||||
implicitWidth: customHeaderText.width * 2
|
||||
|
||||
border.width: 2
|
||||
color: Theme.palette.statusPopupMenu.hoverBackgroundColor
|
||||
|
||||
StatusBaseText {
|
||||
id: customHeaderText
|
||||
anchors.centerIn: parent
|
||||
text: "Custom header"
|
||||
}
|
||||
}
|
||||
|
||||
footer: Rectangle {
|
||||
implicitHeight: customHeaderText.height * 2
|
||||
implicitWidth: customHeaderText.width * 2
|
||||
|
||||
border.width: 2
|
||||
color: Theme.palette.statusPopupMenu.hoverBackgroundColor
|
||||
|
||||
StatusBaseText {
|
||||
id: customFooter
|
||||
anchors.centerIn: parent
|
||||
text: "Custom footer"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
StatusBaseText {
|
||||
anchors.fill: parent
|
||||
text: "Content"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
import QtQuick 2.14
|
||||
import QtQuick.Layouts 1.14
|
||||
|
||||
import StatusQ.Controls 0.1
|
||||
import StatusQ.Components 0.1
|
||||
|
||||
import QtGraphicalEffects 1.14
|
||||
|
||||
Item {
|
||||
id: root
|
||||
|
||||
implicitWidth: mainLayout.implicitWidth
|
||||
implicitHeight: mainLayout.implicitHeight
|
||||
|
||||
property var testControls: [ctrl1, ctrl2, ctrl3]
|
||||
|
||||
property bool globalStylePreferRound: true
|
||||
|
||||
ColumnLayout {
|
||||
id: mainLayout
|
||||
|
||||
anchors.fill: parent
|
||||
|
||||
RowLayout {
|
||||
ColumnLayout {
|
||||
Text {
|
||||
text: `AR: ${ctrl1.aspectRatio.toFixed(2)}`
|
||||
}
|
||||
|
||||
StatusImageCropPanel {
|
||||
id: ctrl1
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
|
||||
source: "qrc:/demoapp/data/logo-test-image.png"
|
||||
windowStyle: globalStylePreferRound ? StatusImageCrop.WindowStyle.Rounded : StatusImageCrop.WindowStyle.Rectangular
|
||||
}
|
||||
Text {
|
||||
text: `AR: ${ctrl2.aspectRatio.toFixed(2)}`
|
||||
}
|
||||
StatusImageCropPanel {
|
||||
id: ctrl2
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
|
||||
source: "qrc:/demoapp/data/logo-test-image.png"
|
||||
windowStyle: globalStylePreferRound ? StatusImageCrop.WindowStyle.Rectangular : StatusImageCrop.WindowStyle.Rounded
|
||||
aspectRatio: 16/9
|
||||
enableCheckers: true
|
||||
}
|
||||
}
|
||||
ColumnLayout {
|
||||
Text {
|
||||
text: `AR: ${ctrl3.aspectRatio.toFixed(2)}`
|
||||
}
|
||||
StatusImageCropPanel {
|
||||
id: ctrl3
|
||||
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
|
||||
source: "qrc:/demoapp/data/logo-test-image.png"
|
||||
windowStyle: globalStylePreferRound ? StatusImageCrop.WindowStyle.Rounded : StatusImageCrop.WindowStyle.Rectangular
|
||||
aspectRatio: 0.8
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Shortcut {
|
||||
sequence: StandardKey.ZoomIn
|
||||
onActivated: {
|
||||
for(let i in testControls) {
|
||||
const c = testControls[i]
|
||||
c.setCropRect(ctrl1.inflateRectBy(c.cropRect, -0.05))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Shortcut {
|
||||
sequence: StandardKey.ZoomOut
|
||||
onActivated: {
|
||||
for(let i in testControls) {
|
||||
const c = testControls[i]
|
||||
c.setCropRect(ctrl1.inflateRectBy(c.cropRect, 0.05))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Shortcut {
|
||||
sequences: ["Ctrl+W"]
|
||||
onActivated: globalStylePreferRound = !globalStylePreferRound
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -59,12 +59,13 @@ Column {
|
||||
|
||||
Item {
|
||||
implicitWidth: 480
|
||||
implicitHeight: 102
|
||||
implicitHeight: 82
|
||||
z: 100000
|
||||
StatusSeedPhraseInput {
|
||||
id: statusSeedInput
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
height: parent.height
|
||||
textEdit.input.anchors.leftMargin: 16
|
||||
textEdit.input.anchors.rightMargin: 16
|
||||
textEdit.input.anchors.topMargin: 11
|
||||
@@ -88,7 +89,6 @@ Column {
|
||||
label: "Label"
|
||||
charLimit: 30
|
||||
errorMessage: "Error message"
|
||||
|
||||
input.clearable: true
|
||||
input.valid: false
|
||||
input.placeholderText: "Placeholder"
|
||||
|
||||
@@ -0,0 +1,81 @@
|
||||
import QtQuick 2.0
|
||||
import QtQuick.Layouts 1.14
|
||||
|
||||
import StatusQ.Controls 0.1
|
||||
import StatusQ.Components 0.1
|
||||
import StatusQ.Core.Theme 0.1
|
||||
import StatusQ.Core 0.1
|
||||
|
||||
import "../demoapp/data" 1.0
|
||||
|
||||
GridLayout {
|
||||
id: root
|
||||
columns: 1
|
||||
rowSpacing: 150
|
||||
|
||||
GridLayout {
|
||||
Layout.alignment: Qt.AlignVCenter | Qt.AlignHCenter
|
||||
rows: 4
|
||||
columns: 2
|
||||
rowSpacing: 170
|
||||
columnSpacing: 150
|
||||
z: 100
|
||||
StatusListPicker {
|
||||
id: languagePicker
|
||||
z: 100
|
||||
inputList: Models.languagePickerModel
|
||||
placeholderSearchText: qsTr("Search Languages")
|
||||
menuAlignment: StatusListPicker.MenuAlignment.Left
|
||||
}
|
||||
|
||||
StatusListPicker {
|
||||
id: languagePicker2
|
||||
z: 100
|
||||
inputList: Models.languageNoImagePickerModel
|
||||
placeholderSearchText: qsTr("Search Languages")
|
||||
menuAlignment: StatusListPicker.MenuAlignment.Center
|
||||
}
|
||||
|
||||
StatusListPicker {
|
||||
id: currencyPicker
|
||||
inputList: Models.currencyPickerModel
|
||||
placeholderSearchText: qsTr("Search Currencies")
|
||||
multiSelection: true
|
||||
}
|
||||
|
||||
StatusListPicker {
|
||||
id: currencyPicker2
|
||||
inputList: Models.currencyPickerModel2
|
||||
placeholderSearchText: qsTr("Search Currencies")
|
||||
multiSelection: true
|
||||
printSymbol: true
|
||||
enableSelectableItem: false
|
||||
}
|
||||
}
|
||||
|
||||
StatusBaseText {
|
||||
id: pageDesc
|
||||
Layout.alignment: Qt.AlignVCenter | Qt.AlignHCenter
|
||||
height: 100
|
||||
width: 500
|
||||
text: "4 different configurations for the `StatusListPicker` component:\n
|
||||
* Single selection. \n
|
||||
* Single selection but dynamically changed to multiple selection (model provides multiple selected items).\n
|
||||
* Multiple selection.\n
|
||||
* Multiple selection and displayed name is the symbol + shortName\n"
|
||||
color: Theme.palette.baseColor1
|
||||
font.pixelSize: 15
|
||||
}
|
||||
|
||||
// Outsite area
|
||||
MouseArea {
|
||||
height: root.height
|
||||
width: root.width
|
||||
onClicked: {
|
||||
languagePicker.close()
|
||||
languagePicker2.close()
|
||||
currencyPicker.close()
|
||||
currencyPicker2.close()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
import QtQuick 2.14
|
||||
|
||||
import StatusQ.Core 0.1
|
||||
import StatusQ.Core.Theme 0.1
|
||||
import StatusQ.Controls 0.1
|
||||
|
||||
import Sandbox 0.1
|
||||
|
||||
Column {
|
||||
spacing: 8
|
||||
|
||||
StatusTabBar {
|
||||
StatusTabButton {
|
||||
width: implicitWidth
|
||||
text: "Button 1"
|
||||
}
|
||||
StatusTabButton {
|
||||
width: implicitWidth
|
||||
text: "Button 2"
|
||||
}
|
||||
StatusTabButton {
|
||||
width: implicitWidth
|
||||
text: "Button 3"
|
||||
badge.value: 42
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -9,17 +9,21 @@ Item {
|
||||
property ListModel asortedContacts: ListModel {
|
||||
ListElement {
|
||||
publicId: "0x0"
|
||||
name: "Maria"
|
||||
name: "emily.eth"
|
||||
icon: ""
|
||||
isIdenticon: false
|
||||
onlineStatus: 3
|
||||
isReadonly: false
|
||||
tagIcon: ""
|
||||
}
|
||||
ListElement {
|
||||
publicId: "0x1"
|
||||
name: "James"
|
||||
name: "vitalikbuterin"
|
||||
icon: "https://pbs.twimg.com/profile_images/1369221718338895873/T_5fny6o_400x400.jpg"
|
||||
isIdenticon: false
|
||||
onlineStatus: 1
|
||||
isReadonly: false
|
||||
tagIcon: ""
|
||||
}
|
||||
ListElement {
|
||||
publicId: "0x2"
|
||||
@@ -27,13 +31,17 @@ Item {
|
||||
icon: ""
|
||||
isIdenticon: false
|
||||
onlineStatus: 2
|
||||
isReadonly: false
|
||||
tagIcon: ""
|
||||
}
|
||||
ListElement {
|
||||
publicId: "0x3"
|
||||
name: "Tracy"
|
||||
name: "carmen.eth"
|
||||
icon: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAlklEQVR4nOzW0QmDQBAG4SSkl7SUQlJGCrElq9F3QdjjVhh/5nv3cFhY9vUIYQiNITSG0BhCExPynn1gWf9bx498P7/nzPcxEzGExhBdJGYihtAYQlO+tUZvqrPbqeudo5iJGEJjCE15a3VtodH3q2ImYgiNITTlTdG1nUZ5a92VITQxITFiJmIIjSE0htAYQrMHAAD//+wwFVpz+yqXAAAAAElFTkSuQmCC"
|
||||
isIdenticon: true
|
||||
onlineStatus: 3
|
||||
isReadonly: true
|
||||
tagIcon: "crown"
|
||||
}
|
||||
ListElement {
|
||||
publicId: "0x4"
|
||||
@@ -41,6 +49,8 @@ Item {
|
||||
icon: ""
|
||||
isIdenticon: false
|
||||
onlineStatus: 3
|
||||
isReadonly: false
|
||||
tagIcon: ""
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -15,10 +15,11 @@ Item {
|
||||
width: parent.width
|
||||
height: childrenRect.height
|
||||
model: [
|
||||
{"title":"anna.eth wants to verify your identity", "subTitle":"Provide the code in the letter I sent to you on February 1st.", "icon":"contact", "loading":false, "type":0,"url":""},
|
||||
{"title":"Verification Request Sent", "subTitle":"", "icon":"checkmark-circle", "loading":false, "type":1,"url":""},
|
||||
{"title":"Collectible is being minted...", "subTitle":"View on Etherscan", "icon":"", "loading":true, "type":0,"url":"http://google.com"},
|
||||
{"title":"Contact request sent", "subTitle":"", "icon":"checkmark-circle", "loading":false, "type":1,"url":""}
|
||||
{"title":"anna.eth wants to verify your identity", "subTitle":"Provide the code in the letter I sent to you on February 1st.", "icon":"contact", "loading":false, "type":0,"url":"", "duration":0},
|
||||
{"title":"Verification Request Sent", "subTitle":"", "icon":"checkmark-circle", "loading":false, "type":1,"url":"", "duration":4000},
|
||||
{"title":"Collectible is being minted...", "subTitle":"View on Etherscan", "icon":"", "loading":true, "type":0,"url":"http://google.com", "duration":0},
|
||||
{"title":"Contact request sent", "subTitle":"", "icon":"checkmark-circle", "loading":false, "type":1,"url":"", "duration":4000},
|
||||
{"title":"Test User", "subTitle":"Hello message...", "icon":"", "loading":false, "type":0,"url":"", "duration":4000}
|
||||
]
|
||||
delegate: StatusToastMessage {
|
||||
primaryText: modelData.title
|
||||
@@ -27,12 +28,15 @@ Item {
|
||||
loading: modelData.loading
|
||||
type: modelData.type
|
||||
linkUrl: modelData.url
|
||||
duration: modelData.duration
|
||||
onLinkActivated: {
|
||||
Qt.openUrlExternally(link);
|
||||
}
|
||||
//simulate open
|
||||
Component.onCompleted: {
|
||||
open = true;
|
||||
onClose: {
|
||||
console.warn("toast closed: ", modelData.title)
|
||||
}
|
||||
onClicked: {
|
||||
console.warn("toast clicked")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,6 +12,6 @@ Column {
|
||||
spacing: 8
|
||||
|
||||
StatusWalletColorSelect {
|
||||
model: Theme.palette.accountColors
|
||||
model: Theme.palette.userCustomizationColors
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
<file>pages/StatusTabSwitchPage.qml</file>
|
||||
<file>pages/StatusWalletColorButtonPage.qml</file>
|
||||
<file>pages/StatusWalletColorSelectPage.qml</file>
|
||||
<file>pages/StatusPasswordStrengthIndicatorPage.qml</file>
|
||||
<file>pages/StatusPasswordStrengthIndicatorPage.qml</file>
|
||||
<file>controls/Buttons.qml</file>
|
||||
<file>controls/Controls.qml</file>
|
||||
<file>controls/Icons.qml</file>
|
||||
@@ -24,6 +24,8 @@
|
||||
<file>controls/ListItems.qml</file>
|
||||
<file>controls/Others.qml</file>
|
||||
<file>controls/Popups.qml</file>
|
||||
<file>demoapp/ChatChannelView.qml</file>
|
||||
<file>demoapp/CreateChatView.qml</file>
|
||||
<file>demoapp/DemoCommunityDetailModal.qml</file>
|
||||
<file>demoapp/DemoContactRequestsModal.qml</file>
|
||||
<file>demoapp/StatusAppChatView.qml</file>
|
||||
@@ -31,5 +33,40 @@
|
||||
<file>demoapp/StatusAppProfileSettingsView.qml</file>
|
||||
<file>demoapp/data/Models.qml</file>
|
||||
<file>demoapp/data/qmldir</file>
|
||||
<file>demoapp/data/logo-test-image.png</file>
|
||||
<file>DemoApp.qml</file>
|
||||
<file>ThemeSwitch.qml</file>
|
||||
<file>pages/StatusColorSelectorGridPage.qml</file>
|
||||
<file>pages/StatusListPickerPage.qml</file>
|
||||
<file>pages/StatusPinInputPage.qml</file>
|
||||
<file>pages/StatusTagSelectorPage.qml</file>
|
||||
<file>pages/StatusToastMessagePage.qml</file>
|
||||
<file>pages/StatusWizardStepperPage.qml</file>
|
||||
<file>pages/StatusTabBarButtonPage.qml</file>
|
||||
<file>pages/StatusColorSpacePage.qml</file>
|
||||
<file>images/CryptoKitties.png</file>
|
||||
<file>images/CryptoPunks.png</file>
|
||||
<file>images/Dragonerum.png</file>
|
||||
<file>images/FriendsBenefits.png</file>
|
||||
<file>images/logo-test-image.png</file>
|
||||
<file>images/P2PCrypto.png</file>
|
||||
<file>images/SNT.png</file>
|
||||
<file>images/Socks.png</file>
|
||||
<file>images/StatusPunks.png</file>
|
||||
<file>images/CommunityBanner1.png</file>
|
||||
<file>images/Coinbase.png</file>
|
||||
<file>images/CoinBaseCommunityBanner.png</file>
|
||||
<file>images/DribbbleCommunityBanner.png</file>
|
||||
<file>images/Ethereum.png</file>
|
||||
<file>images/EthereumCommunityBanner.png</file>
|
||||
<file>images/Fluff.png</file>
|
||||
<file>images/Rarible.png</file>
|
||||
<file>images/RaribleCommunityBanner.png</file>
|
||||
<file>images/Spotify.png</file>
|
||||
<file>images/SpotifyCommunityBanner.png</file>
|
||||
<file>images/SR.png</file>
|
||||
<file>images/SuperRareCommunityBanner.png</file>
|
||||
<file>images/RARI.png</file>
|
||||
<file>images/SRToken.png</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
</RCC>
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
QT += quick svg
|
||||
|
||||
CONFIG += c++11 warn_on qtquickcompiler
|
||||
CONFIG += resources_big
|
||||
|
||||
QML_IMPORT_PATH= $$PWD/../src
|
||||
|
||||
DEFINES += QT_DEPRECATED_WARNINGS
|
||||
|
||||
QMAKE_LFLAGS += $$(LDFLAGS)
|
||||
|
||||
# You can make your code fail to compile if it uses deprecated APIs.
|
||||
# In order to do so, uncomment the following line.
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
import QtQuick 2.14
|
||||
import QtGraphicalEffects 1.14
|
||||
|
||||
Item {
|
||||
id: root
|
||||
|
||||
property Item mask
|
||||
property color color: "#F6F8FA"
|
||||
|
||||
Rectangle {
|
||||
id: gradient
|
||||
anchors.fill: parent
|
||||
visible: false
|
||||
|
||||
gradient: Gradient {
|
||||
orientation: Gradient.Horizontal
|
||||
SkeletonGradientStop { color: "transparent"; from: -3; }
|
||||
SkeletonGradientStop { color: "transparent"; from: -2; }
|
||||
SkeletonGradientStop { color: root.color; from: -1 ; }
|
||||
SkeletonGradientStop { color: "transparent"; from: 0; }
|
||||
SkeletonGradientStop { color: "transparent"; from: 1; }
|
||||
}
|
||||
}
|
||||
|
||||
OpacityMask {
|
||||
anchors.fill: parent
|
||||
source: gradient
|
||||
maskSource: root.mask
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
import QtQuick 2.14
|
||||
import QtGraphicalEffects 1.14
|
||||
|
||||
/*
|
||||
TODO: This component should be implemented as inline component of `SkeletonAnimation.qml`
|
||||
when we use Qt > 5.15
|
||||
*/
|
||||
|
||||
GradientStop {
|
||||
id: root
|
||||
|
||||
property real from: 0
|
||||
|
||||
color: "transparent"
|
||||
|
||||
NumberAnimation on position {
|
||||
easing.type: Easing.Linear
|
||||
loops: Animation.Infinite
|
||||
running: visible
|
||||
from: root.from
|
||||
to: from + 4
|
||||
duration: 2000
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
module StatusQ.Animations
|
||||
|
||||
SkeletonAnimation 0.1 SkeletonAnimation.qml
|
||||
SkeletonGradientStop 0.1 SkeletonGradientStop.qml
|
||||
@@ -32,7 +32,7 @@ Rectangle {
|
||||
anchors.centerIn: parent
|
||||
text: {
|
||||
if (statusBadge.value > 99) {
|
||||
return "99+";
|
||||
return qsTr("99+");
|
||||
}
|
||||
return statusBadge.value;
|
||||
}
|
||||
|
||||
@@ -27,7 +27,6 @@ Item {
|
||||
id: statusChatInfoButton
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: 5
|
||||
anchors.right: (implicitWidth > parent.width - 50) ? statusMenuButton.left : undefined
|
||||
anchors.rightMargin: 5
|
||||
type: StatusChatInfoButton.Type.OneToOneChat
|
||||
@@ -37,7 +36,6 @@ Item {
|
||||
StatusRoundButton {
|
||||
id: statusMenuButton
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: 8
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
|
||||
visible: popupMenuSlot.active
|
||||
@@ -75,6 +73,7 @@ Item {
|
||||
duration: 150
|
||||
direction: RotationAnimation.Clockwise
|
||||
easing.type: Easing.InCubic
|
||||
running: visible
|
||||
}
|
||||
},
|
||||
Transition {
|
||||
@@ -84,6 +83,7 @@ Item {
|
||||
duration: 150
|
||||
direction: RotationAnimation.Counterclockwise
|
||||
easing.type: Easing.OutCubic
|
||||
running: visible
|
||||
}
|
||||
}
|
||||
]
|
||||
@@ -104,5 +104,4 @@ Item {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@ Column {
|
||||
property string categoryId: ""
|
||||
property var model: null
|
||||
property bool draggableItems: false
|
||||
property bool highlightItem: true
|
||||
|
||||
property alias statusChatListItems: statusChatListItems
|
||||
|
||||
@@ -90,23 +91,25 @@ Column {
|
||||
}
|
||||
|
||||
StatusChatListItem {
|
||||
|
||||
id: statusChatListItem
|
||||
|
||||
opacity: dragSensor.active ? 0.0 : 1.0
|
||||
originalOrder: model.position
|
||||
chatId: model.itemId
|
||||
categoryId: model.parentItemId? model.parentItemId : ""
|
||||
name: model.name
|
||||
icon.emoji: model.emoji
|
||||
type: !!model.type ? model.type : StatusChatListItem.Type.CommunityChat
|
||||
muted: model.muted
|
||||
hasUnreadMessages: model.hasUnreadMessages
|
||||
notificationsCount: model.notificationsCount
|
||||
highlightWhenCreated: !!model.highlight
|
||||
selected: model.active
|
||||
icon.color: model.color
|
||||
image.isIdenticon: model.isIdenticon
|
||||
selected: (model.active && statusChatList.highlightItem)
|
||||
|
||||
icon.emoji: model.emoji
|
||||
icon.color: !!model.color ? model.color : Theme.palette.userCustomizationColors[model.colorId]
|
||||
image.isIdenticon: false
|
||||
image.source: model.icon
|
||||
ringSettings.ringSpecModel: model.colorHash
|
||||
|
||||
sensor.cursorShape: dragSensor.cursorShape
|
||||
onClicked: {
|
||||
|
||||
@@ -14,10 +14,10 @@ Item {
|
||||
implicitWidth: chatListsAndCategories.width
|
||||
|
||||
property StatusTooltipSettings categoryAddButtonToolTip: StatusTooltipSettings {
|
||||
text: "Add channel inside category"
|
||||
text: qsTr("Add channel inside category")
|
||||
}
|
||||
property StatusTooltipSettings categoryMenuButtonToolTip: StatusTooltipSettings {
|
||||
text: "More"
|
||||
text: qsTr("More")
|
||||
}
|
||||
|
||||
property var model: []
|
||||
@@ -68,7 +68,6 @@ Item {
|
||||
|
||||
StatusChatList {
|
||||
id: statusChatList
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
visible: statusChatList.model.count > 0
|
||||
onChatItemSelected: statusChatListAndCategories.chatItemSelected(categoryId, id)
|
||||
onChatItemUnmuted: statusChatListAndCategories.chatItemUnmuted(id)
|
||||
|
||||
@@ -48,7 +48,6 @@ Column {
|
||||
popupMenuSlot.item.popup(mouse.x + 4, mouse.y + 6);
|
||||
return
|
||||
}
|
||||
statusChatListCategory.opened = !opened;
|
||||
}
|
||||
}
|
||||
onTitleClicked: statusChatListCategory.opened = !opened
|
||||
|
||||
@@ -39,21 +39,21 @@ StatusListItem {
|
||||
id: addButton
|
||||
icon.name: "add"
|
||||
icon.width: 20
|
||||
visible: statusChatListCategoryItem.showAddButton &&
|
||||
visible: statusChatListCategoryItem.showAddButton &&
|
||||
(statusChatListCategoryItem.highlighted ||
|
||||
statusChatListCategoryItem.sensor.containsMouse)
|
||||
onClicked: statusChatListCategoryItem.addButtonClicked(mouse)
|
||||
tooltip.text: "Add channel inside category"
|
||||
tooltip.text: qsTr("Add channel inside category")
|
||||
},
|
||||
StatusChatListCategoryItemButton {
|
||||
id: menuButton
|
||||
icon.name: "more"
|
||||
icon.width: 21
|
||||
visible: statusChatListCategoryItem.showMenuButton &&
|
||||
visible: statusChatListCategoryItem.showMenuButton &&
|
||||
(statusChatListCategoryItem.highlighted ||
|
||||
statusChatListCategoryItem.sensor.containsMouse)
|
||||
onClicked: statusChatListCategoryItem.menuButtonClicked(mouse)
|
||||
tooltip.text: "More"
|
||||
tooltip.text: qsTr("More")
|
||||
},
|
||||
StatusChatListCategoryItemButton {
|
||||
id: toggleButton
|
||||
|
||||
@@ -10,7 +10,7 @@ import StatusQ.Components 0.1
|
||||
import StatusQ.Controls 0.1
|
||||
|
||||
Rectangle {
|
||||
id: statusChatListItem
|
||||
id: root
|
||||
|
||||
objectName: "chatItem"
|
||||
property int originalOrder: -1
|
||||
@@ -29,11 +29,10 @@ Rectangle {
|
||||
width: 24
|
||||
height: 24
|
||||
color: Theme.palette.miscColor5
|
||||
letterSize: emoji ? 11 : 15
|
||||
emoji: ""
|
||||
emojiSize: Emoji.size.verySmall
|
||||
charactersLen: 1
|
||||
charactersLen: root.type === StatusChatListItem.Type.OneToOneChat ? 2 : 1
|
||||
}
|
||||
property alias ringSettings: identicon.ringSettings
|
||||
property int type: StatusChatListItem.Type.PublicChat
|
||||
property bool highlighted: false
|
||||
property bool highlightWhenCreated: false
|
||||
@@ -79,16 +78,16 @@ Rectangle {
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
acceptedButtons: Qt.LeftButton | Qt.RightButton
|
||||
|
||||
onClicked: statusChatListItem.clicked(mouse)
|
||||
onClicked: root.clicked(mouse)
|
||||
|
||||
StatusSmartIdenticon {
|
||||
id: identicon
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: 8
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
image: statusChatListItem.image
|
||||
icon: statusChatListItem.icon
|
||||
name: statusChatListItem.name
|
||||
image: root.image
|
||||
icon: root.icon
|
||||
name: root.name
|
||||
}
|
||||
|
||||
StatusIcon {
|
||||
@@ -98,21 +97,21 @@ Rectangle {
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
|
||||
width: 14
|
||||
visible: statusChatListItem.type !== StatusChatListItem.Type.OneToOneChat
|
||||
visible: root.type !== StatusChatListItem.Type.OneToOneChat
|
||||
opacity: {
|
||||
if (statusChatListItem.muted && !hoverHander.hovered && !statusChatListItem.highlighted) {
|
||||
if (root.muted && !hoverHander.hovered && !root.highlighted) {
|
||||
return 0.4
|
||||
}
|
||||
return statusChatListItem.hasUnreadMessages ||
|
||||
statusChatListItem.notificationsCount > 0 ||
|
||||
statusChatListItem.selected ||
|
||||
statusChatListItem.highlighted ||
|
||||
return root.hasUnreadMessages ||
|
||||
root.notificationsCount > 0 ||
|
||||
root.selected ||
|
||||
root.highlighted ||
|
||||
statusBadge.visible ||
|
||||
hoverHander.hovered ? 1.0 : 0.7
|
||||
}
|
||||
|
||||
icon: {
|
||||
switch (statusChatListItem.type) {
|
||||
switch (root.type) {
|
||||
case StatusChatListItem.Type.PublicCat:
|
||||
return Theme.palette.name == "light" ? "tiny/public-chat" : "tiny/public-chat-white"
|
||||
break;
|
||||
@@ -137,27 +136,27 @@ Rectangle {
|
||||
anchors.rightMargin: 6
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
|
||||
text: (statusChatListItem.type === StatusChatListItem.Type.PublicChat &&
|
||||
!statusChatListItem.name.startsWith("#") ?
|
||||
"#" + statusChatListItem.name :
|
||||
statusChatListItem.name)
|
||||
text: (root.type === StatusChatListItem.Type.PublicChat &&
|
||||
!root.name.startsWith("#") ?
|
||||
"#" + root.name :
|
||||
root.name)
|
||||
elide: Text.ElideRight
|
||||
color: {
|
||||
if (statusChatListItem.muted && !hoverHander.hovered && !statusChatListItem.highlighted) {
|
||||
if (root.muted && !hoverHander.hovered && !root.highlighted) {
|
||||
return Theme.palette.directColor5
|
||||
}
|
||||
return statusChatListItem.hasUnreadMessages ||
|
||||
statusChatListItem.notificationsCount > 0 ||
|
||||
statusChatListItem.selected ||
|
||||
statusChatListItem.highlighted ||
|
||||
statusChatListItem.highlightWhenCreated ||
|
||||
return root.hasUnreadMessages ||
|
||||
root.notificationsCount > 0 ||
|
||||
root.selected ||
|
||||
root.highlighted ||
|
||||
root.highlightWhenCreated ||
|
||||
hoverHander.hovered ||
|
||||
statusBadge.visible ? Theme.palette.directColor1 : Theme.palette.directColor4
|
||||
}
|
||||
font.weight: !statusChatListItem.muted &&
|
||||
(statusChatListItem.hasUnreadMessages ||
|
||||
statusChatListItem.notificationsCount > 0 ||
|
||||
statusChatListItem.highlightWhenCreated ||
|
||||
font.weight: !root.muted &&
|
||||
(root.hasUnreadMessages ||
|
||||
root.notificationsCount > 0 ||
|
||||
root.highlightWhenCreated ||
|
||||
statusBadge.visible) ? Font.Bold : Font.Medium
|
||||
font.pixelSize: 15
|
||||
}
|
||||
@@ -170,18 +169,18 @@ Rectangle {
|
||||
width: 14
|
||||
opacity: mutedIconSensor.containsMouse ? 1.0 : 0.2
|
||||
icon: Theme.palette.name === "light" ? "tiny/muted" : "tiny/muted-white"
|
||||
visible: statusChatListItem.muted
|
||||
visible: root.muted
|
||||
|
||||
MouseArea {
|
||||
id: mutedIconSensor
|
||||
hoverEnabled: true
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
anchors.fill: parent
|
||||
onClicked: statusChatListItem.unmute()
|
||||
onClicked: root.unmute()
|
||||
}
|
||||
|
||||
StatusToolTip {
|
||||
text: "Unmute"
|
||||
text: qsTr("Unmute")
|
||||
visible: mutedIconSensor.containsMouse
|
||||
}
|
||||
}
|
||||
@@ -193,11 +192,11 @@ Rectangle {
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: 8
|
||||
|
||||
color: statusChatListItem.muted ? Theme.palette.primaryColor2 : Theme.palette.primaryColor1
|
||||
color: root.muted ? Theme.palette.primaryColor2 : Theme.palette.primaryColor1
|
||||
border.width: 4
|
||||
border.color: color
|
||||
value: statusChatListItem.notificationsCount
|
||||
visible: statusChatListItem.notificationsCount > 0
|
||||
value: root.notificationsCount
|
||||
visible: root.notificationsCount > 0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,24 +1,22 @@
|
||||
import QtQuick 2.14
|
||||
import QtQuick.Controls 2.14
|
||||
import QtQuick.Layouts 1.13
|
||||
|
||||
import StatusQ.Core 0.1
|
||||
import StatusQ.Core.Theme 0.1
|
||||
import StatusQ.Controls 0.1
|
||||
|
||||
Rectangle {
|
||||
Item {
|
||||
id: statusChatToolBar
|
||||
implicitWidth: 518
|
||||
height: 56
|
||||
color: Theme.palette.statusAppLayout.backgroundColor
|
||||
|
||||
property alias chatInfoButton: statusChatInfoButton
|
||||
property alias menuButton: menuButton
|
||||
property alias notificationButton: notificationButton
|
||||
property alias membersButton: membersButton
|
||||
property alias searchButton: searchButton
|
||||
property int notificationCount: 0
|
||||
|
||||
property int padding: 8
|
||||
property int notificationCount: 0
|
||||
property Component popupMenu
|
||||
property var toolbarComponent
|
||||
|
||||
signal chatInfoButtonClicked()
|
||||
signal menuButtonClicked()
|
||||
@@ -26,150 +24,125 @@ Rectangle {
|
||||
signal membersButtonClicked()
|
||||
signal searchButtonClicked()
|
||||
|
||||
implicitWidth: 518
|
||||
implicitHeight: 60
|
||||
|
||||
onPopupMenuChanged: {
|
||||
if (!!popupMenu) {
|
||||
popupMenuSlot.sourceComponent = popupMenu
|
||||
}
|
||||
}
|
||||
|
||||
StatusChatInfoButton {
|
||||
id: statusChatInfoButton
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: 12
|
||||
width: Math.min(implicitWidth, parent.width - actionButtons.implicitWidth - anchors.leftMargin * 2)
|
||||
onClicked: statusChatToolBar.chatInfoButtonClicked()
|
||||
}
|
||||
RowLayout {
|
||||
width: parent.width
|
||||
spacing: padding / 2
|
||||
|
||||
Row {
|
||||
id: actionButtons
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: 8
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
|
||||
spacing: 8
|
||||
|
||||
StatusFlatRoundButton {
|
||||
id: searchButton
|
||||
width: 32
|
||||
height: 32
|
||||
icon.name: "search"
|
||||
type: StatusFlatRoundButton.Type.Secondary
|
||||
onClicked: statusChatToolBar.searchButtonClicked()
|
||||
|
||||
// initializing the tooltip
|
||||
tooltip.text: "Search"
|
||||
tooltip.orientation: StatusToolTip.Orientation.Bottom
|
||||
tooltip.y: parent.height + 12
|
||||
Loader {
|
||||
id: loader
|
||||
sourceComponent: statusChatToolBar.toolbarComponent
|
||||
Layout.fillWidth: true
|
||||
Layout.alignment: Qt.AlignTop | Qt.AlignLeft
|
||||
Layout.topMargin: padding
|
||||
Layout.leftMargin: padding
|
||||
}
|
||||
|
||||
StatusFlatRoundButton {
|
||||
id: membersButton
|
||||
width: 32
|
||||
height: 32
|
||||
icon.name: "group-chat"
|
||||
type: StatusFlatRoundButton.Type.Secondary
|
||||
onClicked: statusChatToolBar.membersButtonClicked()
|
||||
RowLayout {
|
||||
id: actionButtons
|
||||
Layout.alignment: Qt.AlignTop | Qt.AlignRight
|
||||
Layout.topMargin: padding
|
||||
Layout.rightMargin: padding
|
||||
spacing: 8
|
||||
|
||||
// initializing the tooltip
|
||||
tooltip.text: "Members"
|
||||
tooltip.orientation: StatusToolTip.Orientation.Bottom
|
||||
tooltip.y: parent.height + 12
|
||||
}
|
||||
StatusFlatRoundButton {
|
||||
id: searchButton
|
||||
width: 32
|
||||
height: 32
|
||||
icon.name: "search"
|
||||
type: StatusFlatRoundButton.Type.Secondary
|
||||
onClicked: statusChatToolBar.searchButtonClicked()
|
||||
|
||||
StatusFlatRoundButton {
|
||||
id: menuButton
|
||||
width: 32
|
||||
height: 32
|
||||
icon.name: "more"
|
||||
type: StatusFlatRoundButton.Type.Secondary
|
||||
visible: !!statusChatToolBar.popupMenu
|
||||
|
||||
// initializing the tooltip
|
||||
tooltip.visible: !!tooltip.text && menuButton.hovered && !popupMenuSlot.item.opened
|
||||
tooltip.text: "More"
|
||||
tooltip.orientation: StatusToolTip.Orientation.Bottom
|
||||
tooltip.y: parent.height + 12
|
||||
|
||||
property bool showMoreMenu: false
|
||||
onClicked: {
|
||||
menuButton.highlighted = true
|
||||
|
||||
let originalOpenHandler = popupMenuSlot.item.openHandler
|
||||
let originalCloseHandler = popupMenuSlot.item.closeHandler
|
||||
|
||||
popupMenuSlot.item.openHandler = function () {
|
||||
if (!!originalOpenHandler) {
|
||||
originalOpenHandler()
|
||||
}
|
||||
}
|
||||
|
||||
popupMenuSlot.item.closeHandler = function () {
|
||||
menuButton.highlighted = false
|
||||
if (!!originalCloseHandler) {
|
||||
originalCloseHandler()
|
||||
}
|
||||
}
|
||||
|
||||
popupMenuSlot.item.openHandler = originalOpenHandler
|
||||
popupMenuSlot.item.popup(-popupMenuSlot.item.width + menuButton.width, menuButton.height + 4)
|
||||
statusChatToolBar.menuButtonClicked()
|
||||
// initializing the tooltip
|
||||
tooltip.text: qsTr("Search")
|
||||
tooltip.orientation: StatusToolTip.Orientation.Bottom
|
||||
tooltip.y: parent.height + 12
|
||||
}
|
||||
|
||||
Loader {
|
||||
id: popupMenuSlot
|
||||
active: !!statusChatToolBar.popupMenu
|
||||
StatusFlatRoundButton {
|
||||
id: membersButton
|
||||
width: 32
|
||||
height: 32
|
||||
icon.name: "group-chat"
|
||||
type: StatusFlatRoundButton.Type.Secondary
|
||||
onClicked: statusChatToolBar.membersButtonClicked()
|
||||
|
||||
// initializing the tooltip
|
||||
tooltip.text: qsTr("Members")
|
||||
tooltip.orientation: StatusToolTip.Orientation.Bottom
|
||||
tooltip.y: parent.height + 12
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
height: 24
|
||||
width: 1
|
||||
color: Theme.palette.directColor7
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
visible: notificationButton.visible &&
|
||||
(menuButton.visible || membersButton.visible || searchButton.visible)
|
||||
}
|
||||
StatusFlatRoundButton {
|
||||
id: menuButton
|
||||
width: 32
|
||||
height: 32
|
||||
icon.name: "more"
|
||||
type: StatusFlatRoundButton.Type.Secondary
|
||||
visible: !!statusChatToolBar.popupMenu
|
||||
|
||||
StatusFlatRoundButton {
|
||||
id: notificationButton
|
||||
width: 32
|
||||
height: 32
|
||||
// initializing the tooltip
|
||||
tooltip.visible: !!tooltip.text && menuButton.hovered && !popupMenuSlot.item.opened
|
||||
tooltip.text: qsTr("More")
|
||||
tooltip.orientation: StatusToolTip.Orientation.Bottom
|
||||
tooltip.y: parent.height + 12
|
||||
|
||||
icon.name: "notification"
|
||||
icon.height: 21
|
||||
type: StatusFlatRoundButton.Type.Secondary
|
||||
property bool showMoreMenu: false
|
||||
onClicked: {
|
||||
menuButton.highlighted = true
|
||||
|
||||
// initializing the tooltip
|
||||
tooltip.text: "Activity"
|
||||
tooltip.orientation: StatusToolTip.Orientation.Bottom
|
||||
tooltip.y: parent.height + 12
|
||||
let originalOpenHandler = popupMenuSlot.item.openHandler
|
||||
let originalCloseHandler = popupMenuSlot.item.closeHandler
|
||||
|
||||
onClicked: statusChatToolBar.notificationButtonClicked()
|
||||
|
||||
StatusBadge {
|
||||
id: statusBadge
|
||||
|
||||
visible: value > 0
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.right
|
||||
anchors.topMargin: -3
|
||||
anchors.leftMargin: {
|
||||
if (statusBadge.value > 99) {
|
||||
return -22
|
||||
popupMenuSlot.item.openHandler = function () {
|
||||
if (!!originalOpenHandler) {
|
||||
originalOpenHandler()
|
||||
}
|
||||
}
|
||||
if (statusBadge.value > 9) {
|
||||
return -21
|
||||
|
||||
popupMenuSlot.item.closeHandler = function () {
|
||||
menuButton.highlighted = false
|
||||
if (!!originalCloseHandler) {
|
||||
originalCloseHandler()
|
||||
}
|
||||
}
|
||||
return -18
|
||||
|
||||
popupMenuSlot.item.openHandler = originalOpenHandler
|
||||
popupMenuSlot.item.popup(-popupMenuSlot.item.width + menuButton.width, menuButton.height + 4)
|
||||
statusChatToolBar.menuButtonClicked()
|
||||
}
|
||||
|
||||
value: statusChatToolBar.notificationCount
|
||||
border.width: 2
|
||||
border.color: parent.hovered ? Theme.palette.baseColor2 : Theme.palette.statusAppLayout.backgroundColor
|
||||
Loader {
|
||||
id: popupMenuSlot
|
||||
active: !!statusChatToolBar.popupMenu
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
height: 24
|
||||
width: 1
|
||||
color: Theme.palette.directColor7
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
visible: notificationButton.visible &&
|
||||
(menuButton.visible || membersButton.visible || searchButton.visible)
|
||||
}
|
||||
|
||||
StatusActivityCenterButton {
|
||||
id: notificationButton
|
||||
width: 32
|
||||
height: width
|
||||
unreadNotificationsCount: statusChatToolBar.notificationCount
|
||||
onClicked: statusChatToolBar.notificationButtonClicked()
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,201 @@
|
||||
import QtQuick 2.14
|
||||
import QtGraphicalEffects 1.0
|
||||
|
||||
import StatusQ.Core 0.1
|
||||
import StatusQ.Core.Theme 0.1
|
||||
|
||||
Item {
|
||||
id: root
|
||||
|
||||
property int thickness: width * 0.1
|
||||
property real minSaturate: 0.0
|
||||
property real minValue: 0.0
|
||||
property real maxSaturate: 1.0
|
||||
property real maxValue: 1.0
|
||||
property color color: "red"
|
||||
property color rootColor: Qt.hsva(color.hsvHue, 1, 1, 1)
|
||||
|
||||
function pickColorFromHueGauge(x, y) {
|
||||
// Get angle of picked color
|
||||
let theta = Math.atan2(y - hueGauge.height / 2, x - hueGauge.width / 2) * 0.5 / Math.PI;
|
||||
if (theta < 0.0)
|
||||
theta += 1.0;
|
||||
|
||||
// Convert angle value to color
|
||||
return Qt.hsva(1 - theta, 1, 1, 1)
|
||||
}
|
||||
|
||||
function pickColorFromSatValRect(x, y) {
|
||||
// x for saturation, reversed y for value
|
||||
let sat = mapFromRange(Math.min(Math.max(x, 0), satValRect.width),
|
||||
minSaturate, maxSaturate, satValRect.width);
|
||||
let val = 1 - mapFromRange(Math.min(Math.max(y, 0), satValRect.height),
|
||||
1 - maxValue, 1 - minValue, satValRect.height);
|
||||
return Qt.hsva(rootColor.hsvHue, sat, val, 1);
|
||||
}
|
||||
|
||||
function angleOnHueGauge(pickingColor) {
|
||||
// color hue to angle
|
||||
return (1 - pickingColor.hsvHue) * 2 * Math.PI;
|
||||
}
|
||||
|
||||
// TODO: mapToRange & mapFromRange to helper js
|
||||
function mapToRange(value, minValue, maxValue, range) {
|
||||
return (value - minValue) / (maxValue - minValue) * range;
|
||||
}
|
||||
|
||||
function mapFromRange(pos, minValue, maxValue, range) {
|
||||
return pos / range * (maxValue - minValue) + minValue;
|
||||
}
|
||||
|
||||
onColorChanged: {
|
||||
// update root color if only we are not picking on satValRect
|
||||
if (!d.pickingSatVal)
|
||||
rootColor = Qt.hsva(color.hsvHue, 1, 1, 1)
|
||||
}
|
||||
|
||||
implicitWidth: 340
|
||||
implicitHeight: 340
|
||||
|
||||
QtObject {
|
||||
id: d
|
||||
|
||||
property bool pickingSatVal: false
|
||||
}
|
||||
|
||||
ConicalGradient {
|
||||
id: hueGauge
|
||||
anchors.fill: parent
|
||||
angle: 90.0
|
||||
gradient: Gradient {
|
||||
GradientStop { position: 0.000; color: Qt.hsva(1.000, 1, 1, 1) }
|
||||
GradientStop { position: 0.167; color: Qt.hsva(0.833, 1, 1, 1) }
|
||||
GradientStop { position: 0.333; color: Qt.hsva(0.666, 1, 1, 1) }
|
||||
GradientStop { position: 0.500; color: Qt.hsva(0.500, 1, 1, 1) }
|
||||
GradientStop { position: 0.667; color: Qt.hsva(0.333, 1, 1, 1) }
|
||||
GradientStop { position: 0.833; color: Qt.hsva(0.166, 1, 1, 1) }
|
||||
GradientStop { position: 1.000; color: Qt.hsva(0.000, 1, 1, 1) }
|
||||
}
|
||||
layer.enabled: true
|
||||
layer.effect: OpacityMask {
|
||||
maskSource: Item {
|
||||
width: root.width
|
||||
height: root.height
|
||||
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
radius: Math.min(width, height) / 2
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: hueArea
|
||||
|
||||
property bool pressedOnGauge: false
|
||||
|
||||
anchors.fill: parent
|
||||
preventStealing: true
|
||||
onPressed: {
|
||||
// Check we clicked on gauge
|
||||
let dist = Math.sqrt(Math.pow(width / 2 - mouseX, 2) +
|
||||
Math.pow(height / 2 - mouseY, 2));
|
||||
let radius = Math.min(width, height) / 2;
|
||||
if (dist < radius - thickness || dist > radius)
|
||||
return;
|
||||
|
||||
pressedOnGauge = true;
|
||||
pickRootColor();
|
||||
}
|
||||
onReleased: pressedOnGauge = false
|
||||
onPositionChanged: if (pressedOnGauge) pickRootColor()
|
||||
|
||||
function pickRootColor() {
|
||||
// Update both colors
|
||||
rootColor = pickColorFromHueGauge(mouseX, mouseY);
|
||||
color.hsvHue = rootColor.hsvHue;
|
||||
color.hsvSaturation = Math.min(maxSaturate, Math.max(minSaturate, color.hsvSaturation));
|
||||
color.hsvValue = Math.min(maxValue, Math.max(minValue, color.hsvValue));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
anchors.margins: root.thickness
|
||||
radius: Math.min(width, height) / 2
|
||||
|
||||
color: Theme.palette.baseColor5
|
||||
|
||||
Rectangle {
|
||||
id: satValRect
|
||||
anchors.centerIn: parent
|
||||
width: parent.width * 0.55
|
||||
height: width
|
||||
border.color: Theme.palette.baseColor3
|
||||
gradient: Gradient {
|
||||
orientation: Gradient.Horizontal
|
||||
GradientStop { position: -minSaturate; color: "white" }
|
||||
GradientStop { position: 2.0 - maxSaturate; color: rootColor }
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
gradient: Gradient {
|
||||
orientation: Gradient.Vertical
|
||||
GradientStop { position: maxValue - 1; color: "transparent" }
|
||||
GradientStop { position: 1.0 + minValue; color: "black" }
|
||||
}
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: satValArea
|
||||
anchors.fill: parent
|
||||
preventStealing: true
|
||||
onPressed: {
|
||||
d.pickingSatVal = true;
|
||||
pickColor();
|
||||
}
|
||||
onReleased: d.pickingSatVal = false
|
||||
onPositionChanged: pickColor()
|
||||
|
||||
function pickColor() {
|
||||
root.color = pickColorFromSatValRect(mouseX, mouseY);
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: satValLens
|
||||
x: mapToRange(root.color.hsvSaturation, minSaturate, maxSaturate,
|
||||
satValRect.width) - radius
|
||||
y: mapToRange(1 - root.color.hsvValue, 1 - maxValue, 1 - minValue,
|
||||
satValRect.height) - radius
|
||||
width: thickness * 1.3
|
||||
height: width
|
||||
radius: height / 2
|
||||
border.width: 2
|
||||
border.color: Theme.palette.baseColor3
|
||||
color: root.color
|
||||
visible: x + 1 >= -radius && x - 1 <= satValRect.width - radius &&
|
||||
y + 1 >= -radius && y - 1 <= satValRect.height - radius
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: hueLens
|
||||
|
||||
property real theta: angleOnHueGauge(rootColor);
|
||||
property real dist: (hueGauge.width - width) / 2 + thickness / 6;
|
||||
|
||||
anchors.centerIn: parent
|
||||
anchors.horizontalCenterOffset: dist * Math.cos(theta);
|
||||
anchors.verticalCenterOffset: dist * Math.sin(theta);
|
||||
width: thickness * 1.3
|
||||
height: width
|
||||
radius: height / 2
|
||||
border.width: 2
|
||||
border.color: Theme.palette.baseColor3
|
||||
color: rootColor
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,469 @@
|
||||
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: 335
|
||||
property int bannerHeigth: 64
|
||||
property int cardHeigth: 190
|
||||
property int totalHeigth: 230
|
||||
property int margins: 12
|
||||
property int bannerRadius: 20
|
||||
property int cardRadius: 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: 2
|
||||
radius: sensor.containsMouse ? 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: 16
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: 12
|
||||
width: 48
|
||||
height: width
|
||||
radius: width / 2
|
||||
color: root.loaded ? d.cardColor : d.loadingColor1
|
||||
|
||||
StatusRoundedImage {
|
||||
visible: root.loaded
|
||||
anchors.centerIn: parent
|
||||
width: parent.width - 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: 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: 8
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: anchors.topMargin
|
||||
width: 48
|
||||
height: 24
|
||||
color: d.loadingColor2
|
||||
radius: 200
|
||||
StatusIcon {
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.leftMargin: 6
|
||||
anchors.left: parent.left
|
||||
icon: "tiny/unlocked"
|
||||
width: 16
|
||||
height: 16
|
||||
color: Theme.palette.baseColor1
|
||||
}
|
||||
StatusRoundedImage {
|
||||
anchors.rightMargin: 2
|
||||
anchors.right: parent.right
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
width: 20
|
||||
height: width
|
||||
image.source: root.tokenLogo
|
||||
color: "transparent"
|
||||
}
|
||||
}
|
||||
// Community info
|
||||
ColumnLayout {
|
||||
anchors.fill: parent
|
||||
anchors.topMargin: 32
|
||||
anchors.leftMargin: d.margins
|
||||
anchors.rightMargin: d.margins
|
||||
anchors.bottomMargin: d.margins
|
||||
clip: true
|
||||
spacing: 6
|
||||
StatusBaseText {
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
text: root.name
|
||||
font.weight: Font.Bold
|
||||
font.pixelSize: 19
|
||||
color: d.fontColor
|
||||
}
|
||||
StatusBaseText {
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
text: root.description
|
||||
font.pixelSize: 15
|
||||
lineHeight: 1.2
|
||||
color: d.fontColor
|
||||
maximumLineCount: 2
|
||||
wrapMode: Text.WordWrap
|
||||
elide: Text.ElideRight
|
||||
clip: true
|
||||
}
|
||||
}
|
||||
ColumnLayout {
|
||||
anchors.fill: parent
|
||||
anchors.topMargin: 116
|
||||
anchors.leftMargin: d.margins
|
||||
anchors.rightMargin: d.margins
|
||||
anchors.bottomMargin: d.margins
|
||||
clip: true
|
||||
spacing: 18
|
||||
Row {
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
spacing: 20
|
||||
// Members
|
||||
Row {
|
||||
height: membersTxt.height
|
||||
spacing: 4
|
||||
StatusIcon {
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
icon: "tiny/members"
|
||||
width: 16
|
||||
height: 16
|
||||
}
|
||||
StatusBaseText {
|
||||
id: membersTxt
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
text: d.numberFormat(root.members)
|
||||
font.pixelSize: 15
|
||||
color: d.fontColor
|
||||
}
|
||||
}
|
||||
// Active users:
|
||||
Row {
|
||||
height: activeUsersTxt.height
|
||||
spacing: 4
|
||||
StatusIcon {
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
icon: "tiny/flash"
|
||||
width: 14
|
||||
height: 14
|
||||
}
|
||||
StatusBaseText {
|
||||
id: activeUsersTxt
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
text: d.numberFormat(root.activeUsers)
|
||||
font.pixelSize: 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: 8
|
||||
clip: true
|
||||
|
||||
Repeater {
|
||||
model: root.categories
|
||||
delegate: StatusListItemTag {
|
||||
border.color: Theme.palette.baseColor2
|
||||
color: "transparent"
|
||||
height: 24
|
||||
radius: 20
|
||||
closeButtonVisible: false
|
||||
icon.emoji: model.emoji
|
||||
icon.height: 24
|
||||
icon.width: icon.height
|
||||
icon.color: "transparent"
|
||||
icon.isLetterIdenticon: true
|
||||
title: model.name
|
||||
titleText.font.pixelSize: 13
|
||||
titleText.color: d.fontColor
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} // End of content card
|
||||
|
||||
// Loading card
|
||||
Rectangle {
|
||||
visible: !root.loaded
|
||||
anchors.top: parent.top
|
||||
anchors.topMargin: 40
|
||||
width: d.cardWidth
|
||||
height: d.cardHeigth
|
||||
color: d.cardColor
|
||||
radius: d.cardRadius
|
||||
clip: true
|
||||
Rectangle {
|
||||
anchors.top: parent.top
|
||||
anchors.topMargin: 8
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: anchors.topMargin
|
||||
width: 48
|
||||
height: 24
|
||||
color: d.loadingColor2
|
||||
radius: 200
|
||||
}
|
||||
ColumnLayout {
|
||||
anchors.fill: parent
|
||||
anchors.topMargin: 32
|
||||
anchors.margins: d.margins
|
||||
clip: true
|
||||
spacing: 9
|
||||
Rectangle {
|
||||
width: 84
|
||||
height: 16
|
||||
color: d.loadingColor1
|
||||
radius: 5
|
||||
}
|
||||
Rectangle {
|
||||
width: 311
|
||||
height: 16
|
||||
color: d.loadingColor1
|
||||
radius: 5
|
||||
}
|
||||
Rectangle {
|
||||
width: 271
|
||||
height: 16
|
||||
color: d.loadingColor1
|
||||
radius: 5
|
||||
}
|
||||
Row {
|
||||
Layout.topMargin: 22 - 9
|
||||
spacing: 16
|
||||
Repeater {
|
||||
model: 2
|
||||
delegate: Row {
|
||||
spacing: 4
|
||||
Rectangle {
|
||||
width: 14
|
||||
height: 14
|
||||
color: d.loadingColor1
|
||||
radius: width / 2
|
||||
}
|
||||
Rectangle {
|
||||
width: 50
|
||||
height: 12
|
||||
color: d.loadingColor2
|
||||
radius: 5
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Row {
|
||||
Layout.topMargin: 21 - 9
|
||||
spacing: 8
|
||||
Repeater {
|
||||
model: 3
|
||||
delegate:
|
||||
Rectangle {
|
||||
width: 76
|
||||
height: 24
|
||||
color: d.loadingColor2
|
||||
radius: 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)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
import QtQuick 2.14
|
||||
|
||||
import StatusQ.Core 0.1
|
||||
import StatusQ.Controls 0.1
|
||||
|
||||
Item {
|
||||
id: root
|
||||
|
||||
property string filterString
|
||||
property bool showOnlySelected: false
|
||||
property bool active: true
|
||||
|
||||
property alias model: repeater.model
|
||||
property alias contentWidth: flow.width
|
||||
|
||||
signal clicked(var item)
|
||||
|
||||
implicitWidth: flow.implicitWidth
|
||||
implicitHeight: flow.implicitHeight
|
||||
|
||||
Flow {
|
||||
id: flow
|
||||
anchors.centerIn: parent
|
||||
width: {
|
||||
let itemsWidth = 0;
|
||||
for (let i = 0; i < repeater.count; ++i) {
|
||||
itemsWidth += spacing + repeater.itemAt(i).width;
|
||||
}
|
||||
return Math.min(parent.width, itemsWidth);
|
||||
}
|
||||
spacing: 10
|
||||
|
||||
Repeater {
|
||||
id: repeater
|
||||
|
||||
delegate: StatusCommunityTag {
|
||||
emoji: model.emoji
|
||||
name: model.name
|
||||
visible: (root.showOnlySelected ? model.selected : !model.selected) &&
|
||||
(filterString == 0 || name.toUpperCase().indexOf(filterString.toUpperCase()) !== -1)
|
||||
width: visible ? implicitWidth : -10
|
||||
height: visible ? implicitHeight : 0
|
||||
removable: root.showOnlySelected && root.active
|
||||
onClicked: root.clicked(model)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
import QtQuick 2.13
|
||||
import StatusQ.Core 0.1
|
||||
|
||||
|
||||
Image {
|
||||
id: root
|
||||
|
||||
property string emojiId: ""
|
||||
|
||||
width: 14
|
||||
height: 14
|
||||
sourceSize.width: width
|
||||
sourceSize.height: height
|
||||
|
||||
fillMode: Image.PreserveAspectFit
|
||||
mipmap: true
|
||||
antialiasing: true
|
||||
source: emojiId ? `../../assets/twemoji/svg/${emojiId}.svg` : ""
|
||||
}
|
||||
@@ -12,6 +12,7 @@ Rectangle {
|
||||
property alias additionalText: additionalText.text
|
||||
property alias button: button
|
||||
property alias expandableComponent: expandableRegion.sourceComponent
|
||||
property alias expandableItem: expandableRegion.item
|
||||
|
||||
property int type: StatusExpandableItem.Type.Primary
|
||||
property bool expandable: true
|
||||
@@ -185,7 +186,7 @@ Rectangle {
|
||||
anchors.leftMargin: (statusExpandableItem.type === StatusExpandableItem.Type.Primary) ? 48 : 0
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: (statusExpandableItem.type === StatusExpandableItem.Type.Primary) ? 16 : 0
|
||||
active: false
|
||||
visible: false
|
||||
}
|
||||
|
||||
onExpandedChanged: {
|
||||
@@ -202,13 +203,13 @@ Rectangle {
|
||||
name: "EXPANDED"
|
||||
PropertyChanges {target: expandImage; icon: "chevron-up"}
|
||||
PropertyChanges {target: statusExpandableItem; height: 82 + expandableRegion.height + 22}
|
||||
PropertyChanges {target: expandableRegion; active: true}
|
||||
PropertyChanges {target: expandableRegion; visible: true}
|
||||
},
|
||||
State {
|
||||
name: "COLLAPSED"
|
||||
PropertyChanges {target: expandImage; icon: "chevron-down"}
|
||||
PropertyChanges {target: statusExpandableItem; height: 82}
|
||||
PropertyChanges {target: expandableRegion; active: false}
|
||||
PropertyChanges {target: expandableRegion; visible: false}
|
||||
}
|
||||
]
|
||||
|
||||
@@ -216,12 +217,12 @@ Rectangle {
|
||||
Transition {
|
||||
from: "COLLAPSED"
|
||||
to: "EXPANDED"
|
||||
NumberAnimation { properties: "height"; duration: 200 }
|
||||
NumberAnimation { properties: "height"; duration: 200; running: visible }
|
||||
},
|
||||
Transition {
|
||||
from: "EXPANDED"
|
||||
to: "COLLAPSED"
|
||||
NumberAnimation { properties: "height"; duration: 200 }
|
||||
NumberAnimation { properties: "height"; duration: 200; running: visible }
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -0,0 +1,271 @@
|
||||
import QtQuick 2.14
|
||||
import QtQuick.Layouts 1.14
|
||||
|
||||
import StatusQ.Core 0.1
|
||||
import StatusQ.Controls 0.1
|
||||
|
||||
/*!
|
||||
\qmltype StatusImageCropPanel
|
||||
\inherits Item
|
||||
\inqmlmodule StatusQ.Components
|
||||
\since StatusQ.Components 0.1
|
||||
\brief Draw a crop-window onto an image and allows manipulating the position of the crop-window. Inherits \l{https://doc.qt.io/qt-5/qml-qtquick-item.html}{Item}.
|
||||
|
||||
Adds mouse pan and zoom functionality on top of StatusImageCrop functionality. Also adds small
|
||||
practical features and optimizes drawing by minimizing StatusImageCrop area
|
||||
|
||||
\sa StatusImageCrop for more details
|
||||
|
||||
Example of how to use it:
|
||||
|
||||
\qml
|
||||
StatusImageCropPanel {
|
||||
width: 400
|
||||
height: 200
|
||||
source: "qrc:/demoapp/data/logo-test-image.png"
|
||||
windowStyle: StatusImageCrop.WindowStyle.Rectangular
|
||||
Component.onCompleted: setCropRect(Qt.rect(10, 0, sourceSize.width - 20, sourceSize.height))
|
||||
}
|
||||
\endqml
|
||||
|
||||
For a list of components available see StatusQ.
|
||||
*/
|
||||
Item {
|
||||
id: root
|
||||
|
||||
implicitWidth: mainLayout.implicitWidth
|
||||
implicitHeight: mainLayout.implicitHeight
|
||||
|
||||
/*!
|
||||
\qmlproperty real StatusImageCrop::aspectRatio
|
||||
Initial aspect-ratio of the crop-window
|
||||
*/
|
||||
property real aspectRatio: 1
|
||||
/*!
|
||||
\qmlproperty bool StatusImageCrop::interactive
|
||||
If true allows user to interact with the image. Set to false for previewing existing crop-data
|
||||
*/
|
||||
property bool interactive: true
|
||||
/*!
|
||||
\qmlproperty bool StatusImageCrop::margins
|
||||
Space to keep around the control borders and crop area
|
||||
*/
|
||||
property int margins: 10
|
||||
|
||||
/*!
|
||||
\qmlproperty url StatusImageCropPanel::source
|
||||
\sa StatusImageCrop::source
|
||||
*/
|
||||
/*required*/ property alias source: cropEditor.source
|
||||
|
||||
/*!
|
||||
\qmlproperty WindowStyle StatusImageCropPanel::windowStyle
|
||||
\sa StatusImageCrop::windowStyle
|
||||
*/
|
||||
property alias windowStyle: cropEditor.windowStyle
|
||||
/*!
|
||||
\qmlproperty int StatusImageCropPanel::radius
|
||||
\sa StatusImageCrop::radius
|
||||
*/
|
||||
property alias radius: cropEditor.radius
|
||||
/*!
|
||||
\qmlproperty color StatusImageCropPanel::wallColor
|
||||
\sa StatusImageCrop::wallColor
|
||||
*/
|
||||
property alias wallColor: cropEditor.wallColor
|
||||
/*!
|
||||
\qmlproperty real StatusImageCropPanel::wallTransparency
|
||||
\sa StatusImageCrop::wallTransparency
|
||||
*/
|
||||
property alias wallTransparency: cropEditor.wallTransparency
|
||||
/*!
|
||||
\qmlproperty rect StatusImageCropPanel::cropRect
|
||||
\sa StatusImageCrop::cropRect
|
||||
*/
|
||||
readonly property alias cropRect: cropEditor.cropRect
|
||||
/*!
|
||||
\qmlproperty real StatusImageCrop::scrollZoomFactor
|
||||
How fast is image scaled (zoomed) when using mouse scroll
|
||||
*/
|
||||
property real scrollZoomFactor: 0.5
|
||||
/*!
|
||||
\qmlproperty bool StatusImageCropPanel::enableCheckers
|
||||
Shows helper guiding checkers pattern where image is not covering
|
||||
*/
|
||||
property bool enableCheckers: root.interactive
|
||||
/*!
|
||||
\qmlproperty size StatusImageCropPanel::sourceSize
|
||||
\sa StatusImageCrop::sourceSize
|
||||
*/
|
||||
property alias sourceSize: cropEditor.sourceSize
|
||||
|
||||
/*
|
||||
\qmlmethod StatusImageCropPanel::setCropRect(rect)
|
||||
\sa StatusImageCrop::cropRect
|
||||
*/
|
||||
function setCropRect(newRect) {
|
||||
cropEditor.setCropRect(newRect)
|
||||
aspectRatio = cropEditor.aspectRatio
|
||||
}
|
||||
|
||||
QtObject {
|
||||
id: d
|
||||
|
||||
readonly property int referenceWindowWidth: 1000
|
||||
function updateAspectRatio(newAR) {
|
||||
if(root.sourceSize.width === 0 || root.sourceSize.height === 0)
|
||||
return
|
||||
cropEditor.setCropRect(cropEditor.fillContentInWindow(root.sourceSize, Qt.size(referenceWindowWidth, referenceWindowWidth / root.aspectRatio)))
|
||||
}
|
||||
}
|
||||
|
||||
Component.onCompleted: d.updateAspectRatio(root.aspectRatio)
|
||||
onAspectRatioChanged: d.updateAspectRatio(root.aspectRatio)
|
||||
onSourceSizeChanged: d.updateAspectRatio(root.aspectRatio)
|
||||
|
||||
ColumnLayout {
|
||||
id: mainLayout
|
||||
|
||||
anchors.fill: parent
|
||||
|
||||
Item {
|
||||
id: cropSpaceItem
|
||||
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
|
||||
clip: true
|
||||
|
||||
Rectangle {
|
||||
id: leftOverlay
|
||||
anchors.left: parent.left
|
||||
anchors.top: parent.top
|
||||
anchors.right: cropEditor.left
|
||||
anchors.bottom: parent.bottom
|
||||
color: wallColor
|
||||
opacity: wallTransparency
|
||||
z: cropEditor.z + 1
|
||||
}
|
||||
Rectangle {
|
||||
id: topOverlay
|
||||
anchors.left: leftOverlay.right
|
||||
anchors.top: parent.top
|
||||
anchors.right: rightOverlay.left
|
||||
anchors.bottom: cropEditor.top
|
||||
color: wallColor
|
||||
opacity: wallTransparency
|
||||
z: cropEditor.z + 1
|
||||
}
|
||||
|
||||
StatusImageCrop {
|
||||
id: cropEditor
|
||||
anchors.centerIn: parent
|
||||
width: aspectRatio < cropSpaceItem.width/cropSpaceItem.height ? cropSpaceItem.height * aspectRatio : cropSpaceItem.width - root.margins * 2
|
||||
height: aspectRatio < cropSpaceItem.width/cropSpaceItem.height ? cropSpaceItem.height - root.margins * 2 : cropSpaceItem.width / aspectRatio
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: rightOverlay
|
||||
anchors.left: cropEditor.right
|
||||
anchors.top: parent.top
|
||||
anchors.right: parent.right
|
||||
anchors.bottom: parent.bottom
|
||||
color: wallColor
|
||||
opacity: wallTransparency
|
||||
z: cropEditor.z + 1
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: bottomOverlay
|
||||
anchors.left: leftOverlay.right
|
||||
anchors.top: cropEditor.bottom
|
||||
anchors.right: rightOverlay.left
|
||||
anchors.bottom: parent.bottom
|
||||
color: wallColor
|
||||
opacity: wallTransparency
|
||||
z: cropEditor.z + 1
|
||||
}
|
||||
|
||||
// Checkers
|
||||
Canvas {
|
||||
visible: root.enableCheckers
|
||||
anchors.fill: parent
|
||||
onPaint: {
|
||||
var ctx = getContext("2d")
|
||||
for(let xI = 0; xI < Math.ceil(width/10); xI++) {
|
||||
for(let yI = 0; yI < Math.ceil(height/10); yI++) {
|
||||
ctx.fillStyle = (xI % 2) === (yI % 2) ? "#FFFFFE" : "#DBDBDB"
|
||||
ctx.fillRect(xI * 10, yI * 10, 10, 10)
|
||||
}
|
||||
}
|
||||
}
|
||||
z: cropEditor.z - 1
|
||||
}
|
||||
|
||||
// Drag and zoom
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
|
||||
enabled: root.interactive
|
||||
|
||||
property var lastDragPoint: null
|
||||
onReleased: lastDragPoint = null
|
||||
|
||||
onMouseXChanged: updateDrag(Qt.point(mouse.x, mouse.y))
|
||||
onMouseYChanged: updateDrag(Qt.point(mouse.x, mouse.y))
|
||||
|
||||
onWheel: {
|
||||
const delta = wheel.angleDelta.y / 120
|
||||
cropEditor.setCropRect(cropEditor.getZoomRect(cropEditor.zoomScale + delta * root.scrollZoomFactor))
|
||||
}
|
||||
|
||||
function moveRect(r /*rect*/, delta /*real*/) {
|
||||
return Qt.rect(r.x + delta.x, r.y + delta.y, r.width, r.height)
|
||||
}
|
||||
|
||||
function scaleSize(sz /*size*/, s /*size*/) {
|
||||
return Qt.point(sz.width * s, sz.height * s)
|
||||
}
|
||||
|
||||
function updateDrag(p) {
|
||||
let delta = (lastDragPoint ? Qt.size(lastDragPoint.x - p.x, lastDragPoint.y - p.y) : Qt.size(0, 0))
|
||||
delta = scaleSize(delta, 1/cropEditor.scrToImgScale)
|
||||
cropEditor.setCropRect(moveRect(cropEditor.cropRect, delta))
|
||||
lastDragPoint = p
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
visible: root.interactive
|
||||
|
||||
StatusIcon {
|
||||
icon: "remove-circle"
|
||||
|
||||
Layout.preferredWidth: 20
|
||||
Layout.preferredHeight: 20
|
||||
}
|
||||
StatusSlider {
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: 20
|
||||
Layout.bottomMargin: 25
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
|
||||
enabled: root.interactive
|
||||
|
||||
from: cropEditor.minZoomScale
|
||||
to: cropEditor.maxZoomScale
|
||||
value: cropEditor.zoomScale
|
||||
live: false
|
||||
onMoved: cropEditor.setCropRect(cropEditor.getZoomRect(valueAt(visualPosition)))
|
||||
}
|
||||
StatusIcon {
|
||||
icon: "add-circle"
|
||||
|
||||
Layout.preferredWidth: 20
|
||||
Layout.preferredHeight: 20
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ Rectangle {
|
||||
property alias identiconText: identiconText
|
||||
property string name
|
||||
property string emoji
|
||||
property string emojiSize
|
||||
property string emojiSize: Emoji.size.small
|
||||
property int letterSize: 21
|
||||
property int charactersLen: 1
|
||||
|
||||
@@ -18,9 +18,18 @@ Rectangle {
|
||||
height: 40
|
||||
radius: width / 2
|
||||
|
||||
StatusEmoji {
|
||||
visible: root.emoji
|
||||
anchors.centerIn: parent
|
||||
width: Math.round(parent.width / 2)
|
||||
height: Math.round(parent.height / 2)
|
||||
emojiId: Emoji.iconId(root.emoji, root.emojiSize) || ""
|
||||
}
|
||||
|
||||
StatusBaseText {
|
||||
id: identiconText
|
||||
|
||||
visible: !root.emoji
|
||||
anchors.alignWhenCentered: false
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
@@ -29,21 +38,23 @@ Rectangle {
|
||||
|
||||
font.weight: Font.Bold
|
||||
font.pixelSize: root.letterSize
|
||||
color: Qt.rgba(255, 255, 255, 0.7)
|
||||
color: d.luminance(root.color) > 0.5 ? Qt.rgba(0, 0, 0, 0.5) : Qt.rgba(255, 255, 255, 0.7)
|
||||
|
||||
text: {
|
||||
if (emoji) {
|
||||
if(Utils.isHtml(emoji))
|
||||
return emoji
|
||||
else
|
||||
return Emoji.parse(emoji, emojiSize || undefined)
|
||||
}
|
||||
|
||||
const shift = (root.name.charAt(0) === "#") ||
|
||||
(root.name.charAt(0) === "@")
|
||||
|
||||
return root.name.substring(shift, shift + charactersLen).toUpperCase()
|
||||
}
|
||||
}
|
||||
|
||||
QtObject {
|
||||
id: d
|
||||
function luminance(color) {
|
||||
let r = Math.pow(color.r, 2.2) * 0.2126
|
||||
let g = Math.pow(color.g, 2.2) * 0.7151
|
||||
let b = Math.pow(color.b, 2.2) * 0.0721
|
||||
return r + g + b
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -5,6 +5,10 @@ import StatusQ.Core 0.1
|
||||
import StatusQ.Core.Theme 0.1
|
||||
import StatusQ.Components 0.1
|
||||
import StatusQ.Controls 0.1
|
||||
import StatusQ.Animations 0.1
|
||||
import QtGraphicalEffects 1.14
|
||||
|
||||
import "private"
|
||||
|
||||
Rectangle {
|
||||
id: statusListItem
|
||||
@@ -14,17 +18,21 @@ Rectangle {
|
||||
property string title: ""
|
||||
property string titleAsideText: ""
|
||||
property string subTitle: ""
|
||||
property string tertiaryTitle: ""
|
||||
property string tertiaryTitle: ""
|
||||
property string label: ""
|
||||
property real leftPadding: 16
|
||||
property real rightPadding: 16
|
||||
property bool enabled: true
|
||||
property bool highlighted: false
|
||||
property bool propagateTitleClicks: true
|
||||
property bool propagateTitleClicks: true
|
||||
property int type: StatusListItem.Type.Primary
|
||||
property list<Item> components
|
||||
property var bottomModel: []
|
||||
property Component bottomDelegate
|
||||
property var tagsModel: []
|
||||
property Component tagsDelegate
|
||||
property bool loading: false
|
||||
property bool loadingFailed: false
|
||||
|
||||
property StatusIconSettings icon: StatusIconSettings {
|
||||
height: isLetterIdenticon ? 40 : 20
|
||||
@@ -71,8 +79,9 @@ Rectangle {
|
||||
property alias statusListItemTertiaryTitle: statusListItemTertiaryTitle
|
||||
property alias statusListItemComponentsSlot: statusListItemComponentsSlot
|
||||
property alias statusListItemTagsSlot: statusListItemTagsSlot
|
||||
property alias statusListItemInlineTagsSlot: statusListItemTagsSlotInline
|
||||
|
||||
signal clicked(string itemId)
|
||||
signal clicked(string itemId, var mouse)
|
||||
signal titleClicked(string titleId)
|
||||
|
||||
enum Type {
|
||||
@@ -122,7 +131,7 @@ Rectangle {
|
||||
preventStealing: true
|
||||
|
||||
onClicked: {
|
||||
statusListItem.clicked(statusListItem.itemId)
|
||||
statusListItem.clicked(statusListItem.itemId, mouse)
|
||||
}
|
||||
|
||||
StatusSmartIdenticon {
|
||||
@@ -131,16 +140,32 @@ Rectangle {
|
||||
anchors.leftMargin: statusListItem.leftPadding
|
||||
anchors.top: parent.top
|
||||
anchors.topMargin: 12
|
||||
visible: !iconOrImageLoadingOverlay.visible
|
||||
image: statusListItem.image
|
||||
icon: statusListItem.icon
|
||||
name: statusListItem.title
|
||||
active: statusListItem.icon.isLetterIdenticon ||
|
||||
!!statusListItem.icon.name ||
|
||||
!!statusListItem.image.source.toString()
|
||||
!!statusListItem.image.source.toString() ||
|
||||
!!statusListItem.icon.emoji
|
||||
badge.border.color: statusListItem.color
|
||||
ringSettings: statusListItem.ringSettings
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: iconOrImageLoadingOverlay
|
||||
visible: statusListItem.loading || statusListItem.loadingFailed
|
||||
anchors.fill: iconOrImage
|
||||
radius: width / 2
|
||||
color: statusListItem.loadingFailed ? Theme.palette.dangerColor2 : Theme.palette.baseColor1
|
||||
|
||||
SkeletonAnimation {
|
||||
anchors.fill: parent
|
||||
mask: parent
|
||||
visible: statusListItem.loading && !statusListItem.loadingFailed
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
id: statusListItemTitleArea
|
||||
|
||||
@@ -160,31 +185,60 @@ Rectangle {
|
||||
|
||||
height: childrenRect.height
|
||||
|
||||
Rectangle {
|
||||
id: titleLoadingOverlay
|
||||
visible: statusListItem.loading || statusListItem.loadingFailed
|
||||
anchors {
|
||||
left: statusListItemTitle.left
|
||||
top: statusListItemTitle.top
|
||||
bottom: statusListItemTitle.bottom
|
||||
}
|
||||
|
||||
width: Math.max(95, statusListItemTitle.width)
|
||||
radius: 4
|
||||
color: statusListItem.loadingFailed ? Theme.palette.dangerColor2 : Theme.palette.baseColor1
|
||||
|
||||
SkeletonAnimation {
|
||||
anchors.fill: parent
|
||||
mask: parent
|
||||
visible: statusListItem.loading && !statusListItem.loadingFailed
|
||||
}
|
||||
}
|
||||
|
||||
StatusBaseText {
|
||||
id: statusListItemTitle
|
||||
opacity: titleLoadingOverlay.visible ? 0 : 1
|
||||
text: statusListItem.title
|
||||
font.pixelSize: 15
|
||||
height: visible ? contentHeight : 0
|
||||
wrapMode: Text.WrapAtWordBoundaryOrAnywhere
|
||||
elide: Text.ElideRight
|
||||
anchors.left: parent.left
|
||||
anchors.right: !statusListItem.titleAsideText && !titleIconsRow.sourceComponent ? parent.right : undefined
|
||||
anchors.top: bottomModel.length === 0 ? undefined: parent.top
|
||||
anchors.topMargin: bottomModel.length === 0 ? undefined : 20
|
||||
width: Math.min(implicitWidth, parent.width)
|
||||
color: {
|
||||
if (!statusListItem.enabled) {
|
||||
return Theme.palette.baseColor1
|
||||
}
|
||||
switch (statusListItem.type) {
|
||||
case StatusListItem.Type.Primary:
|
||||
return Theme.palette.directColor1
|
||||
case StatusListItem.Type.Secondary:
|
||||
return Theme.palette.primaryColor1
|
||||
case StatusListItem.Type.Danger:
|
||||
return Theme.palette.dangerColor1
|
||||
}
|
||||
if (!statusListItem.enabled) {
|
||||
return Theme.palette.baseColor1
|
||||
}
|
||||
switch (statusListItem.type) {
|
||||
case StatusListItem.Type.Primary:
|
||||
return Theme.palette.directColor1
|
||||
case StatusListItem.Type.Secondary:
|
||||
return Theme.palette.primaryColor1
|
||||
case StatusListItem.Type.Danger:
|
||||
return Theme.palette.dangerColor1
|
||||
}
|
||||
}
|
||||
|
||||
StatusToolTip {
|
||||
id: statusListItemTitleTooltip
|
||||
text: statusListItemTitle.text
|
||||
delay: 0
|
||||
visible: statusListItemTitle.truncated && statusListItemTitleMouseArea.containsMouse
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: statusListItemTitleMouseArea
|
||||
anchors.fill: parent
|
||||
enabled: statusListItem.enabled
|
||||
cursorShape: sensor.enabled && containsMouse ? Qt.PointingHandCursor : Qt.ArrowCursor
|
||||
@@ -223,7 +277,10 @@ Rectangle {
|
||||
width: parent.width
|
||||
text: statusListItem.subTitle
|
||||
font.pixelSize: 15
|
||||
color: !statusListItem.enabled || !statusListItem.tertiaryTitle ? Theme.palette.baseColor1 : Theme.palette.directColor1
|
||||
color: statusListItem.loadingFailed ? Theme.palette.dangerColor1
|
||||
: !statusListItem.enabled || !statusListItem.tertiaryTitle
|
||||
? Theme.palette.baseColor1
|
||||
: Theme.palette.directColor1
|
||||
height: visible ? contentHeight : 0
|
||||
visible: !!statusListItem.subTitle
|
||||
wrapMode: Text.WrapAtWordBoundaryOrAnywhere
|
||||
@@ -247,7 +304,19 @@ Rectangle {
|
||||
width: contentItem.width
|
||||
implicitHeight: visible ? 22 : 0
|
||||
}
|
||||
|
||||
|
||||
Row {
|
||||
id: statusListItemTagsSlotInline
|
||||
anchors.top: statusListItemTertiaryTitle.bottom
|
||||
width: parent.width
|
||||
spacing: 10
|
||||
clip: true
|
||||
|
||||
Repeater {
|
||||
model: tagsModel
|
||||
delegate: tagsDelegate
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Row {
|
||||
|
||||
@@ -6,7 +6,7 @@ import StatusQ.Core.Theme 0.1
|
||||
|
||||
Rectangle {
|
||||
id: root
|
||||
width: layout.width
|
||||
width: layout.width + layout.anchors.margins
|
||||
height: 30
|
||||
color: Theme.palette.primaryColor3
|
||||
radius: 15
|
||||
@@ -39,13 +39,12 @@ Rectangle {
|
||||
|
||||
RowLayout {
|
||||
id: layout
|
||||
|
||||
height: parent.height
|
||||
spacing: 5
|
||||
anchors.margins: 6
|
||||
|
||||
StatusSmartIdenticon {
|
||||
id: iconOrImage
|
||||
Layout.leftMargin: 5
|
||||
Layout.leftMargin: 4
|
||||
image: root.image
|
||||
icon: root.icon
|
||||
name: root.title
|
||||
@@ -66,7 +65,6 @@ Rectangle {
|
||||
color: Theme.palette.primaryColor1
|
||||
icon: "close-circle"
|
||||
visible: closeButtonVisible
|
||||
Layout.rightMargin: 5
|
||||
MouseArea {
|
||||
id: mouseArea
|
||||
anchors.fill: parent
|
||||
|
||||
@@ -0,0 +1,392 @@
|
||||
import QtQuick 2.13
|
||||
import QtQuick.Controls 2.13
|
||||
import QtGraphicalEffects 1.13
|
||||
|
||||
import StatusQ.Core 0.1
|
||||
import StatusQ.Core.Theme 0.1
|
||||
import StatusQ.Controls 0.1
|
||||
|
||||
/*!
|
||||
\qmltype StatusListPicker
|
||||
\inherits Item
|
||||
\inqmlmodule StatusQ.Components
|
||||
\since StatusQ.Components 0.1
|
||||
\brief It is a combination of StatusPickerButton and a drop-down list component that provides a way of presenting a list of selectable options to the user. Inherits \l{https://doc.qt.io/qt-5/qml-qtquick-item.html}{Item}.
|
||||
|
||||
The \c StatusListPicker is populated with a data model. The data model is commonly a JavaScript array or a ListModel object.
|
||||
|
||||
StatusListPicker can be made as a single or multiple options picker by setting its StatusListPicker::multiSelection property properly or will be auto-set if the model contains / provides more than one selected items.
|
||||
The StatusPickerButton text holds the text of the current item selected in the list picker. If there is more than one item selected, a string composed will be displayed.
|
||||
The drop-down list incorporates a searcher by the following model roles: `name` or / and `shortName`.
|
||||
|
||||
NOTE: Make sure to set the appropriate z-index when instantiating the component in order to place it on top of your view in order to display the drop-down data properly.
|
||||
Make sure to position the component inside its parent also when it is spanned in order to achieve a better user experience.
|
||||
|
||||
Example of how the component looks like:
|
||||
\image status_list_picker.png
|
||||
Example of how to use it:
|
||||
\qml
|
||||
StatusListPicker {
|
||||
id: currencyPicker
|
||||
inputList: Models.currencyPickerModel
|
||||
searchText: qsTr("Search Language")
|
||||
multiSelection: true
|
||||
printSymbol: true
|
||||
}
|
||||
\endqml
|
||||
For a list of components available see StatusQ.
|
||||
*/
|
||||
Item {
|
||||
id: root
|
||||
|
||||
/*!
|
||||
\qmlproperty string StatusListPicker::inputList
|
||||
This property holds the data that will be populated in the list picker.
|
||||
|
||||
NOTE: This model property should not change so it is an in / out property where the selected role will be dynamically changed according to user actions.
|
||||
|
||||
Here an example of the model roles expected:
|
||||
\qml
|
||||
inputList: ListModel {
|
||||
ListElement {
|
||||
key: 0
|
||||
name: "United States Dollar"
|
||||
shortName: "USD"
|
||||
symbol: "$"
|
||||
imageSource: "../../assets/twemoji/26x26/1f4b4.png"
|
||||
category: "fiat"
|
||||
selected: true
|
||||
}
|
||||
ListElement {
|
||||
key: 1
|
||||
name: "British Pound"
|
||||
shortName: "GBP"
|
||||
symbol: "£"
|
||||
imageSource: "../../assets/twemoji/26x26/1f4b5.png"
|
||||
category: "fiat"
|
||||
selected: false
|
||||
}
|
||||
}
|
||||
\endqml
|
||||
*/
|
||||
property ListModel inputList: ListModel { }
|
||||
|
||||
/*!
|
||||
\qmlproperty string StatusListPicker::searchText
|
||||
This property holds the search text the searcher input displays by default.
|
||||
*/
|
||||
property string searchText: ""
|
||||
|
||||
/*!
|
||||
\qmlproperty string StatusListPicker::placeholderSearchText
|
||||
This property holds the placeholder text the searcher input displays by default.
|
||||
*/
|
||||
property string placeholderSearchText: qsTr("Search")
|
||||
|
||||
/*!
|
||||
\qmlproperty string StatusListPicker::multiSelection
|
||||
This property holds whether the list picker is a single or a multiple picker option by displaying a StatusRadioButton or StatusCheckBox instead.
|
||||
*/
|
||||
property bool multiSelection: false
|
||||
|
||||
/*!
|
||||
\qmlproperty string StatusListPicker::printSymbol
|
||||
This property holds whether the selected items will display a composition of the role `symbol` in the StatusPickerButton text or just only the role `shortName`.
|
||||
*/
|
||||
property bool printSymbol: false
|
||||
|
||||
/*!
|
||||
\qmlproperty string StatusListPicker::maxPickerHeight
|
||||
This property holds the maximum drop-down list height allowed. The drop-down list height will be set as the minimum value between the list content height and the maxPickerHeight property.
|
||||
*/
|
||||
property int maxPickerHeight: 718
|
||||
|
||||
/*!
|
||||
\qmlproperty string StatusListPicker::enableSelectableItem
|
||||
This property holds if the item in the list will be highlighted when hovering and clickable in its complete area or just not highlighted and able to be selected by clicking only the checbox or radiobutton area.
|
||||
*/
|
||||
property bool enableSelectableItem: true
|
||||
|
||||
/*!
|
||||
\qmlproperty string StatusListPicker::menuAlignment
|
||||
This property holds the allignment of the menu in terms of the button
|
||||
*/
|
||||
property int menuAlignment: StatusListPicker.MenuAlignment.Right
|
||||
|
||||
/*!
|
||||
\qmlproperty enum StatusListPicker::MenuAlignment
|
||||
This property holds the allignment of the menu in terms of the button
|
||||
values can be Left, Right or Center
|
||||
*/
|
||||
enum MenuAlignment {
|
||||
Left,
|
||||
Right,
|
||||
Center
|
||||
}
|
||||
|
||||
/*
|
||||
\qmlmethod StatusListPicker::close()
|
||||
It can be used to force to close the drop-down picker list whenever the consumer needs it. For example by adding an outside MouseArea to close the picker when user clicks outsite the component:
|
||||
\qml
|
||||
// Outsite area
|
||||
MouseArea {
|
||||
height: root.height
|
||||
width: root.width
|
||||
onClicked: { currencyPicker.close() }
|
||||
}
|
||||
\endqml
|
||||
*/
|
||||
function close() {
|
||||
picker.visible = false
|
||||
|
||||
// Reset searcher:
|
||||
root.searchText = ""
|
||||
}
|
||||
|
||||
/*!
|
||||
\qmlsignal StatusListPicker::itemPickerChanged(string key, bool selected)
|
||||
This signal is emitted when an item changes its selected value.
|
||||
*/
|
||||
signal itemPickerChanged(string key, bool selected)
|
||||
|
||||
QtObject {
|
||||
id: d
|
||||
property var filteredModel: ListModel { }
|
||||
|
||||
// Used to set up component and the needed private properties
|
||||
function initialize() {
|
||||
if(filteredModel.count === 0) {
|
||||
// It is necessary to load the model, not loaded yet!
|
||||
var selected = 0
|
||||
var selectionText = ""
|
||||
for(var i = 0; i < root.inputList.count; i++) {
|
||||
var item = root.inputList.get(i)
|
||||
d.filteredModel.append(item)
|
||||
if(item.selected) selected++;
|
||||
}
|
||||
|
||||
// If the given model has more than one selected elements, the behaviour of the list picker will be as a multiple selector with checkboxes although it is
|
||||
// set in the radiobutton mode. Radiobutton mode is only for mutial-exclusion.
|
||||
if(selected > 1)
|
||||
multiSelection = true
|
||||
|
||||
// Update selected items text:
|
||||
d.getSelectedItemsText()
|
||||
}
|
||||
}
|
||||
|
||||
// Used to update model elements given a specific text by filtering them for its `name` and / or `shortName`.
|
||||
function applyFilter(text) {
|
||||
const input = text.toLowerCase()
|
||||
filteredModel.clear()
|
||||
for(var i = 0; i < root.inputList.count; i++) {
|
||||
let item = root.inputList.get(i)
|
||||
if(item.name.toLowerCase().includes(input) || item.shortName.toLowerCase().includes(input))
|
||||
filteredModel.append(item)
|
||||
}
|
||||
}
|
||||
|
||||
function formatSymbolShortNameText(symbol, shortName) {
|
||||
var formattedText = ""
|
||||
if(root.printSymbol && symbol)
|
||||
formattedText = symbol + shortName
|
||||
else
|
||||
formattedText = shortName
|
||||
return formattedText
|
||||
}
|
||||
|
||||
function getSelectedItemsText() {
|
||||
var res = ""
|
||||
for(var i = 0; i < root.inputList.count; i++) {
|
||||
var item = root.inputList.get(i)
|
||||
if(item.selected) {
|
||||
if(res != "")
|
||||
res += ", "
|
||||
res += d.formatSymbolShortNameText(item.symbol, item.shortName)
|
||||
}
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
// Used to update the base input list model with the new selected property
|
||||
function updateInputListModel(key, selected, isSingleSelection) {
|
||||
// If it is a single selection we must ensure that when a new key is selected others are cleared.
|
||||
// It must be done manually because as there is the option of filterning, the model visualized changes
|
||||
// and it could be possible to have a filtered list without an element selected (but in the base model
|
||||
// it is) so, the binding to not selected will not be executed, as in the current filtered model
|
||||
// there are no changes to update, just only the selected one.
|
||||
for(var i = 0; i < root.inputList.count; i++) {
|
||||
if(root.inputList.get(i).key === key) {
|
||||
root.inputList.get(i).selected = selected
|
||||
}
|
||||
else if(isSingleSelection && selected) {
|
||||
// Clear all the list
|
||||
root.inputList.get(i).selected = false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
width: 110
|
||||
height: 38
|
||||
|
||||
Component.onCompleted: d.initialize()
|
||||
|
||||
StatusPickerButton {
|
||||
id: btn
|
||||
anchors.fill: parent
|
||||
bgColor: Theme.palette.primaryColor3
|
||||
contentColor: Theme.palette.primaryColor1
|
||||
text: picker.selectedItemsText
|
||||
textPixelSize: 13
|
||||
type: StatusPickerButton.Type.Down
|
||||
|
||||
onClicked: {
|
||||
picker.visible = !picker.visible
|
||||
|
||||
// Restart list position:
|
||||
content.positionViewAtBeginning()
|
||||
content.forceActiveFocus()
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: picker
|
||||
|
||||
property string selectedItemsText: ""
|
||||
|
||||
width: content.itemWidth
|
||||
height: Math.min(content.contentHeight + content.anchors.topMargin + content.anchors.bottomMargin, root.maxPickerHeight)
|
||||
anchors.left: root.menuAlignment === StatusListPicker.MenuAlignment.Left ? btn.left : undefined
|
||||
anchors.right: root.menuAlignment === StatusListPicker.MenuAlignment.Right ? btn.right : undefined
|
||||
anchors.horizontalCenter: root.menuAlignment === StatusListPicker.MenuAlignment.Center ? btn.horizontalCenter : undefined
|
||||
anchors.top: btn.bottom
|
||||
anchors.topMargin: 4
|
||||
visible: false
|
||||
color: Theme.palette.statusPopupMenu.backgroundColor
|
||||
radius: 8
|
||||
layer.enabled: true
|
||||
layer.effect: DropShadow {
|
||||
source: picker
|
||||
horizontalOffset: 0
|
||||
verticalOffset: 4
|
||||
radius: 12
|
||||
samples: 25
|
||||
spread: 0.2
|
||||
color: Theme.palette.dropShadow
|
||||
}
|
||||
|
||||
ListView {
|
||||
id: content
|
||||
|
||||
property int itemHeight: 40
|
||||
property int itemWidth: 360
|
||||
|
||||
model: d.filteredModel
|
||||
width: itemWidth
|
||||
anchors.top: parent.top
|
||||
anchors.topMargin: 8
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.bottomMargin: 8
|
||||
currentIndex: -1
|
||||
clip: true
|
||||
headerPositioning: ListView.OverlayHeader
|
||||
header: Rectangle {
|
||||
id: header
|
||||
width: content.itemWidth
|
||||
height: searchInput.height + 24
|
||||
color: Theme.palette.statusPopupMenu.backgroundColor
|
||||
z: 3 // Above delegate (z=1) and above section.delegate (z = 2)
|
||||
|
||||
StatusBaseInput {
|
||||
id: searchInput
|
||||
implicitHeight: 36
|
||||
width: content.itemWidth - 2 * 18
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
topPadding: 0
|
||||
bottomPadding: 0
|
||||
placeholderText: root.placeholderSearchText
|
||||
text: root.searchText
|
||||
icon.name: "search"
|
||||
|
||||
onTextChanged: {
|
||||
d.applyFilter(text)
|
||||
root.searchText = text
|
||||
}
|
||||
}
|
||||
}// End of search input item
|
||||
delegate: StatusItemPicker {
|
||||
width: content.itemWidth
|
||||
height: content.itemHeight
|
||||
color: mouseArea.containsMouse ? Theme.palette.baseColor4 : "transparent"
|
||||
image: StatusImageSettings {
|
||||
source: model.imageSource ? model.imageSource : ""
|
||||
width: 15
|
||||
height: 15
|
||||
isIdenticon: false
|
||||
}
|
||||
name: model.name
|
||||
shortName: model.shortName
|
||||
selectorType: root.multiSelection ? StatusItemPicker.SelectorType.CheckBox : StatusItemPicker.SelectorType.RadioButton
|
||||
selected: model.selected
|
||||
radioGroup: radioBtnGroup
|
||||
|
||||
onCheckedChanged: {
|
||||
d.updateInputListModel(model.key, checked, selectorType === StatusItemPicker.SelectorType.RadioButton)
|
||||
if(selectorType === StatusItemPicker.SelectorType.RadioButton && checked) {
|
||||
// Update selected item text
|
||||
picker.selectedItemsText = d.formatSymbolShortNameText(model.symbol, model.shortName)
|
||||
}
|
||||
else {
|
||||
// Update selected items text (multiple selection, text chain).
|
||||
picker.selectedItemsText = d.getSelectedItemsText()
|
||||
}
|
||||
|
||||
// Used to notify selected property changes in the specific item picker.
|
||||
itemPickerChanged(model.key, checked)
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: mouseArea
|
||||
enabled: root.enableSelectableItem
|
||||
anchors.fill: parent
|
||||
cursorShape: root.enableSelectableItem ? Qt.PointingHandCursor : Qt.ArrowCursor
|
||||
hoverEnabled: true
|
||||
onClicked: {
|
||||
if(selectorType === StatusItemPicker.SelectorType.RadioButton) {
|
||||
// Just only allow to select, not unselect in case of single selection (radiobutton)
|
||||
if(!selected) selected = !selected
|
||||
}
|
||||
else
|
||||
// In case of multiple selections you can both select and unselect.
|
||||
selected = !selected
|
||||
}
|
||||
}
|
||||
}
|
||||
section.property: "category"
|
||||
section.criteria: ViewSection.FullString
|
||||
section.delegate: Item {
|
||||
width: content.itemWidth
|
||||
height: content.itemHeight
|
||||
|
||||
StatusBaseText {
|
||||
anchors.leftMargin: 18
|
||||
anchors.left: parent.left
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
text: section
|
||||
color: Theme.palette.baseColor1
|
||||
font.pixelSize: 15
|
||||
elide: Text.ElideRight
|
||||
}
|
||||
}// End of Category item
|
||||
|
||||
onActiveFocusChanged: { if(!activeFocus) root.close() }
|
||||
|
||||
// Not visual element to control mutual-exclusion of radiobuttons that are not sharing the same parent (inside list view)
|
||||
ButtonGroup {
|
||||
id: radioBtnGroup
|
||||
}
|
||||
}// End of Content
|
||||
}// End of Rectangle picker
|
||||
}
|
||||
@@ -11,7 +11,7 @@ StatusIcon {
|
||||
from: 0;
|
||||
to: 360;
|
||||
duration: 1200
|
||||
running: true
|
||||
running: visible
|
||||
loops: Animation.Infinite
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,49 +2,127 @@ import QtQuick 2.0
|
||||
import StatusQ.Core.Theme 0.1
|
||||
import StatusQ.Core 0.1
|
||||
|
||||
/*!
|
||||
\qmltype StatusMemberListItem
|
||||
\inherits StatusListItem
|
||||
\inqmlmodule StatusQ.Components
|
||||
\since StatusQ.Components 0.1
|
||||
\brief It is a list item with a specific format to display members of a community or chat. Inherits from \c StatusListItem.
|
||||
|
||||
The \c StatusMemberListItem is a clickable / hovering list item with a specific format to display members of a community or chat.
|
||||
|
||||
It displays the member avatar, trust and mutual contact indicators, nick name, user name, chat key and information about the member connectivity.
|
||||
|
||||
Example of how the control looks like:
|
||||
\image status_member_list_item.png
|
||||
|
||||
Example of how to use it:
|
||||
|
||||
\qml
|
||||
StatusMemberListItem {
|
||||
nickName: "carmen.eth"
|
||||
isOnline: false
|
||||
trustIndicator: StatusContactVerificationIcons.TrustedType.Untrustworthy
|
||||
}
|
||||
|
||||
StatusMemberListItem {
|
||||
nickName: "This girl I know from work"
|
||||
userName: "annabelle"
|
||||
isOnline: true
|
||||
}
|
||||
\endqml
|
||||
|
||||
For a list of components available see StatusQ.
|
||||
*/
|
||||
StatusListItem {
|
||||
id: root
|
||||
|
||||
/*!
|
||||
\qmlproperty string StatusMemberListItem::nickName
|
||||
This property holds the nick name of the member represented.
|
||||
*/
|
||||
property string nickName: ""
|
||||
/*!
|
||||
\qmlproperty string StatusMemberListItem::userName
|
||||
This property holds the user name of the member represented.
|
||||
*/
|
||||
property string userName: ""
|
||||
property string chatKey: ""
|
||||
property bool isMutualContact: false
|
||||
property var trustIndicator: StatusContactVerificationIcons.TrustedType.None
|
||||
property bool isOnline: false
|
||||
/*!
|
||||
\qmlproperty string StatusMemberListItem::pubKey
|
||||
This property holds the chat public key of the member represented.
|
||||
*/
|
||||
property string pubKey: ""
|
||||
/*!
|
||||
\qmlproperty string StatusMemberListItem::isContact
|
||||
This property holds if the member represented is contact.
|
||||
*/
|
||||
property bool isContact: false
|
||||
/*!
|
||||
\qmlproperty string StatusMemberListItem::isVerified
|
||||
This property holds if the member represented is verified contact.
|
||||
*/
|
||||
property bool isVerified: false
|
||||
/*!
|
||||
\qmlproperty string StatusMemberListItem::isUntrustworthy
|
||||
This property holds if the member represented is untrustworthy.
|
||||
*/
|
||||
property bool isUntrustworthy: false
|
||||
/*!
|
||||
\qmlproperty string StatusMemberListItem::status
|
||||
This property holds the connectivity status of the member represented.
|
||||
0 - offline
|
||||
1 - online
|
||||
2 - doNotDisturb
|
||||
3 - idle
|
||||
*/
|
||||
// FIXME: move Constants.userStatus from status-desktop
|
||||
property int status: 0
|
||||
/*!
|
||||
\qmlproperty string StatusMemberListItem::isAdmin
|
||||
This property holds the admin status of the member represented.
|
||||
*/
|
||||
property bool isAdmin: false
|
||||
|
||||
// Subtitle composition:
|
||||
function composeSubtitile() {
|
||||
var compose = ""
|
||||
if(root.userName !== "")
|
||||
compose = "(" + root.userName + ")"
|
||||
QtObject {
|
||||
id: d
|
||||
|
||||
if(compose !== "" && root.chatKey !== "")
|
||||
// Composition
|
||||
compose += " • " + composeShortKeyChat(root.chatKey)
|
||||
// Subtitle composition:
|
||||
function composeSubtitile() {
|
||||
var compose = ""
|
||||
if(root.userName !== "" && root.nickName !== "")
|
||||
compose = "(" + root.userName + ")"
|
||||
|
||||
else if(root.chatKey !== "")
|
||||
compose = composeShortKeyChat(root.chatKey)
|
||||
if(compose !== "" && root.pubKey !== "")
|
||||
// Composition
|
||||
compose += " • " + composeShortKeyChat(root.pubKey)
|
||||
|
||||
return compose
|
||||
}
|
||||
else if(root.pubKey !== "")
|
||||
compose = composeShortKeyChat(root.pubKey)
|
||||
|
||||
// Short keychat composition:
|
||||
function composeShortKeyChat(chatKey) {
|
||||
return chatKey.substring(0, 5) + "..." + chatKey.substring(chatKey.length - 3)
|
||||
return compose
|
||||
}
|
||||
|
||||
// Short keychat composition:
|
||||
function composeShortKeyChat(pubKey) {
|
||||
return pubKey.substring(0, 5) + "..." + pubKey.substring(pubKey.length - 3)
|
||||
}
|
||||
}
|
||||
|
||||
// root object settings:
|
||||
title: root.nickName
|
||||
title: (root.nickName === "") ? root.userName : root.nickName
|
||||
statusListItemTitleIcons.sourceComponent: StatusContactVerificationIcons {
|
||||
isMutualContact: root.isMutualContact
|
||||
trustIndicator: root.trustIndicator
|
||||
isMutualContact: root.isContact
|
||||
trustIndicator: {
|
||||
if (root.isVerified) return StatusContactVerificationIcons.TrustedType.Verified
|
||||
else if (root.isUntrustworthy) return StatusContactVerificationIcons.TrustedType.Untrustworthy
|
||||
return StatusContactVerificationIcons.TrustedType.None
|
||||
}
|
||||
}
|
||||
subTitle: composeSubtitile()
|
||||
subTitle: d.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
|
||||
statusListItemIcon.badge.color: root.status === 1 ? Theme.palette.successColor1 : Theme.palette.baseColor1 // FIXME
|
||||
color: sensor.containsMouse ? Theme.palette.baseColor2 : Theme.palette.baseColor4
|
||||
|
||||
// Default sizes / positions by design
|
||||
@@ -60,4 +138,12 @@ StatusListItem {
|
||||
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
|
||||
components: [
|
||||
StatusIcon {
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
visible: root.isAdmin
|
||||
icon: "crown"
|
||||
color: Theme.palette.directColor1
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ StatusListItem {
|
||||
anchors.fill: parent
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
hoverEnabled: true
|
||||
onClicked: statusNavigationListItem.clicked(mouse)
|
||||
onClicked: statusNavigationListItem.clicked(statusNavigationListItem.itemId, mouse)
|
||||
}
|
||||
|
||||
components: [
|
||||
|
||||
@@ -28,11 +28,19 @@ Rectangle {
|
||||
id: image
|
||||
width: statusRoundImage.width
|
||||
height: statusRoundImage.height
|
||||
sourceSize.width: parent.width * 2
|
||||
sourceSize.height: parent.height * 2
|
||||
fillMode: Image.PreserveAspectFit
|
||||
anchors.centerIn: parent
|
||||
cache: true
|
||||
|
||||
onSourceChanged: {
|
||||
if (sourceSize.width < width || sourceSize.height < height) {
|
||||
sourceSize = Qt.binding(function() {
|
||||
return Qt.size(width * 2, height * 2)
|
||||
})
|
||||
}
|
||||
else {
|
||||
sourceSize = undefined
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loader {
|
||||
|
||||
@@ -15,7 +15,6 @@ Loader {
|
||||
property StatusIconSettings icon: StatusIconSettings {
|
||||
width: 40
|
||||
height: 40
|
||||
charactersLen: 1
|
||||
}
|
||||
|
||||
property StatusImageSettings image: StatusImageSettings {
|
||||
@@ -25,7 +24,7 @@ Loader {
|
||||
|
||||
property StatusIdenticonRingSettings ringSettings: StatusIdenticonRingSettings {
|
||||
initalAngleRad: 0
|
||||
ringPxSize: 1.5
|
||||
ringPxSize: Math.max(1.5, statusSmartIdenticon.image.width / 24.0)
|
||||
distinctiveColors: Theme.palette.identiconRingColors
|
||||
}
|
||||
|
||||
@@ -87,7 +86,6 @@ Loader {
|
||||
emoji: statusSmartIdenticon.icon.emoji
|
||||
emojiSize: statusSmartIdenticon.icon.emojiSize
|
||||
letterSize: statusSmartIdenticon.icon.letterSize
|
||||
identiconText.color: statusSmartIdenticon.icon.textColor
|
||||
charactersLen: statusSmartIdenticon.icon.charactersLen
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,47 +5,184 @@ import QtGraphicalEffects 1.0
|
||||
|
||||
import StatusQ.Core 0.1
|
||||
import StatusQ.Core.Theme 0.1
|
||||
import StatusQ.Controls 0.1
|
||||
|
||||
/*!
|
||||
\qmltype StatusTagSelector
|
||||
\inherits Item
|
||||
\inqmlmodule StatusQ.Components
|
||||
\since StatusQ.Components 0.1
|
||||
\brief Displays a tag selector component together with a list of where to select and add the tags from.
|
||||
Inherits \l{https://doc.qt.io/qt-5/qml-qtquick-item.html}{Item}.
|
||||
|
||||
The \c StatusTagSelector displays a list of asorted elements together with a text input where tags are added. As the user
|
||||
types some text, the list elements are filtered and if the user selects any of those a new tag is created.
|
||||
For example:
|
||||
|
||||
\qml
|
||||
StatusTagSelector {
|
||||
width: 650
|
||||
height: 44
|
||||
anchors.centerIn: parent
|
||||
namesModel: ListModel {
|
||||
ListElement {
|
||||
pubKey: "0x0"
|
||||
name: "Maria"
|
||||
icon: ""
|
||||
onlineStatus: 3
|
||||
}
|
||||
ListElement {
|
||||
pubKey: "0x1"
|
||||
name: "James"
|
||||
icon: "https://pbs.twimg.com/profile_images/1369221718338895873/T_5fny6o_400x400.jpg"
|
||||
onlineStatus: 1
|
||||
}
|
||||
ListElement {
|
||||
pubKey: "0x2"
|
||||
name: "Paul"
|
||||
icon: ""
|
||||
onlineStatus: 2
|
||||
}
|
||||
}
|
||||
toLabelText: qsTr("To: ")
|
||||
warningText: qsTr("USER LIMIT REACHED")
|
||||
}
|
||||
\endqml
|
||||
|
||||
\image status_tag_selector.png
|
||||
|
||||
For a list of components available see StatusQ.
|
||||
*/
|
||||
|
||||
Item {
|
||||
id: root
|
||||
|
||||
implicitWidth: 448
|
||||
implicitHeight: 44 + ((userListView.count > 0) ? 44 + ((((userListView.count * 64) > root.maxHeight)
|
||||
? root.maxHeight : (userListView.count * 64))) :0)
|
||||
|
||||
property real maxHeight
|
||||
/*!
|
||||
\qmlproperty real StatusTagSelector::maxHeight
|
||||
This property holds the maximum height of the component.
|
||||
*/
|
||||
property real maxHeight: (488 + contactsLabel.height + contactsLabel.anchors.topMargin) //default min
|
||||
/*!
|
||||
\qmlproperty alias StatusTagSelector::textEdit
|
||||
This property holds a reference to the TextEdit component.
|
||||
*/
|
||||
property alias textEdit: edit
|
||||
/*!
|
||||
\qmlproperty alias StatusTagSelector::text
|
||||
This property holds a reference to the TextEdit's text property.
|
||||
*/
|
||||
property alias text: edit.text
|
||||
/*!
|
||||
\qmlproperty string StatusTagSelector::warningText
|
||||
This property sets the warning text.
|
||||
*/
|
||||
property string warningText: ""
|
||||
/*!
|
||||
\qmlproperty string StatusTagSelector::toLabelText
|
||||
This property sets the 'to' label text.
|
||||
*/
|
||||
property string toLabelText: ""
|
||||
/*!
|
||||
\qmlproperty string StatusTagSelector::listLabel
|
||||
This property sets the elements list label text.
|
||||
*/
|
||||
property string listLabel: ""
|
||||
/*!
|
||||
\qmlproperty int StatusTagSelector::nameCountLimit
|
||||
This property sets the tags count limit.
|
||||
*/
|
||||
property int nameCountLimit: 5
|
||||
|
||||
property ListModel sortedList: ListModel { }
|
||||
property ListModel namesModel: ListModel { }
|
||||
/*!
|
||||
\qmlproperty var StatusTagSelector::ringSpecModelGetter
|
||||
This property holds the function to calculate the ring spec model
|
||||
based on the public key.
|
||||
*/
|
||||
property var ringSpecModelGetter: (pubKey) => { /*return ringSpecModel*/ }
|
||||
|
||||
/*!
|
||||
\qmlproperty var StatusTagSelector::compressKeyGetter
|
||||
This property holds the function to calculate the compressed
|
||||
key based on the public key.
|
||||
*/
|
||||
property var compressedKeyGetter: (pubKey) => { /*return compressed key;*/ }
|
||||
|
||||
/*!
|
||||
\qmlproperty var StatusTagSelector::colorIdForPubkeyGetter
|
||||
This property holds the function to calculate the color Id
|
||||
based on the public key.
|
||||
*/
|
||||
property var colorIdForPubkeyGetter: (pubKey) => { /*return color Id;*/ }
|
||||
|
||||
/*!
|
||||
\qmlproperty ListModel StatusTagSelector::sortedList
|
||||
This property holds the sorted list model.
|
||||
*/
|
||||
property ListModel sortedList: ListModel { }
|
||||
/*!
|
||||
\qmlproperty ListModel StatusTagSelector::namesModel
|
||||
This property holds the asorted names model.
|
||||
*/
|
||||
property ListModel namesModel: ListModel { }
|
||||
/*!
|
||||
\qmlproperty bool StatusTagSelector::showSortedListOnlyWhenText
|
||||
This property will decide if the sorted list view info is displayed before entering some text in the input or after.
|
||||
By default is set to false.
|
||||
*/
|
||||
property bool showSortedListOnlyWhenText: false
|
||||
/*!
|
||||
\qmlproperty bool StatusTagSelector::orderByReadonly
|
||||
This property will decide if the displayed tag names will be ordered from left to right starting with the items that are marked as `isReadonly`.
|
||||
By default is set to true (readonly names at left).
|
||||
*/
|
||||
property bool orderByReadonly: true
|
||||
|
||||
/*!
|
||||
\qmlmethod
|
||||
This function is used to find an entry in a model.
|
||||
*/
|
||||
function find(model, criteria) {
|
||||
for (var i = 0; i < model.count; ++i) if (criteria(model.get(i))) return model.get(i);
|
||||
return null;
|
||||
}
|
||||
|
||||
function insertTag(name, id) {
|
||||
if (!find(namesModel, function(item) { return item.publicId === id }) && namesModel.count < root.nameCountLimit) {
|
||||
namesModel.insert(namesModel.count, {"name": name, "publicId": id});
|
||||
/*!
|
||||
\qmlmethod
|
||||
This function is used to insert a new tag.
|
||||
*/
|
||||
function insertTag(name, id, isReadonly, tagIcon) {
|
||||
if (!find(namesModel, function(item) { return item.pubKey === id }) && namesModel.count < root.nameCountLimit) {
|
||||
if(orderByReadonly && isReadonly)
|
||||
namesModel.insert(0, {"name": name, "pubKey": id, "isReadonly": !!isReadonly, "tagIcon": tagIcon ? tagIcon : ""});
|
||||
else
|
||||
namesModel.insert(namesModel.count, {"name": name, "pubKey": id, "isReadonly": !!isReadonly, "tagIcon": tagIcon ? tagIcon : ""});
|
||||
addMember(id);
|
||||
edit.clear();
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\qmlmethod
|
||||
This function is used to sort the source model.
|
||||
*/
|
||||
function sortModel(inputModel) {
|
||||
sortedList.clear();
|
||||
if (text !== "") {
|
||||
for (var i = 0; i < inputModel.count; i++ ) {
|
||||
var entry = inputModel.get(i);
|
||||
if (entry.name.toLowerCase().includes(text.toLowerCase())) {
|
||||
sortedList.insert(sortedList.count, {"publicId": entry.publicId, "name": entry.name,
|
||||
"icon": entry.icon, "isIdenticon": entry.isIdenticon,
|
||||
"onlineStatus": entry.onlineStatus});
|
||||
if (entry.displayName.toLowerCase().includes(text.toLowerCase()) &&
|
||||
!find(namesModel, function(item) { return item.name === entry.displayName })) {
|
||||
sortedList.append({"pubKey": entry.pubKey,
|
||||
"displayName": entry.displayName,
|
||||
"localNickname": entry.localNickname,
|
||||
"isVerified": entry.isVerified,
|
||||
"isUntrustworthy": entry.isUntrustworthy,
|
||||
"isContact": entry.isMutualContact,
|
||||
"ringSpecModel": entry.ringSpecModel,
|
||||
"icon": entry.icon,
|
||||
"onlineStatus": entry.onlineStatus,
|
||||
"tagIcon": entry.tagIcon ? entry.tagIcon : "",
|
||||
"isReadonly": !!entry.isReadonly});
|
||||
userListView.model = sortedList;
|
||||
}
|
||||
}
|
||||
@@ -54,16 +191,54 @@ Item {
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\qmlsignal
|
||||
This signal is emitted when a new tag is created.
|
||||
*/
|
||||
signal addMember(string memberId)
|
||||
|
||||
/*!
|
||||
\qmlsignal
|
||||
This signal is emitted when a tag is removed.
|
||||
*/
|
||||
signal removeMember(string memberId)
|
||||
|
||||
QtObject {
|
||||
id: d
|
||||
|
||||
property real suggestionContainerHeight: suggestionsContainer.visible ? contactsLabel.height + contactsLabel.anchors.topMargin +
|
||||
suggestionsContainer.anchors.topMargin + suggestionsContainer.anchors.bottomMargin +
|
||||
2 * bgRect.anchors.margins +
|
||||
userListView.anchors.topMargin + userListView.anchors.bottomMargin +
|
||||
(userListView.model.count * 64): 0
|
||||
|
||||
function orderNamesModel() {
|
||||
if(root.orderByReadonly) {
|
||||
for(var i = 0; i < namesModel.count; i++) {
|
||||
var entry = namesModel.get(i)
|
||||
if(entry.isReadonly) {
|
||||
namesModel.move(i, 0, 1)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
implicitWidth: 448
|
||||
implicitHeight: (tagSelectorRect.height + d.suggestionContainerHeight) > root.maxHeight ? root.maxHeight : (tagSelectorRect.height + d.suggestionContainerHeight)
|
||||
|
||||
onOrderByReadonlyChanged: { d.orderNamesModel() }
|
||||
Component.onCompleted: {
|
||||
// Component initialization:
|
||||
d.orderNamesModel()
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: tagSelectorRect
|
||||
width: parent.width
|
||||
height: 44
|
||||
radius: 8
|
||||
color: Theme.palette.baseColor2
|
||||
|
||||
RowLayout {
|
||||
anchors.fill: parent
|
||||
anchors.leftMargin: 16
|
||||
@@ -71,14 +246,15 @@ Item {
|
||||
spacing: 8
|
||||
StatusBaseText {
|
||||
Layout.preferredWidth: 22
|
||||
Layout.alignment: Qt.AlignVCenter | Qt.AlignLeft
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
color: Theme.palette.baseColor1
|
||||
text: root.toLabelText
|
||||
visible: (parent.width>22)
|
||||
}
|
||||
|
||||
ScrollView {
|
||||
Layout.preferredWidth: (namesList.contentWidth > (parent.width - 142)) ?
|
||||
(parent.width - 142) : namesList.contentWidth
|
||||
Layout.preferredWidth: (parent.width - 177) > 0 ? ((namesList.contentWidth > (parent.width - 177)) ?
|
||||
(parent.width - 177) : namesList.contentWidth) : 0
|
||||
implicitHeight: 30
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
visible: (namesList.count > 0)
|
||||
@@ -92,67 +268,60 @@ Item {
|
||||
model: namesModel
|
||||
orientation: ListView.Horizontal
|
||||
spacing: 8
|
||||
onCountChanged: {
|
||||
contentX = contentWidth;
|
||||
function scrollToEnd() {
|
||||
if (contentWidth > width) {
|
||||
contentX = contentWidth;
|
||||
}
|
||||
}
|
||||
delegate: Rectangle {
|
||||
id: nameDelegate
|
||||
width: (nameText.contentWidth + 34)
|
||||
height: 30
|
||||
color: mouseArea.containsMouse ? Theme.palette.miscColor1 : Theme.palette.primaryColor1
|
||||
radius: 8
|
||||
StatusBaseText {
|
||||
id: nameText
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: 8
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
color: Theme.palette.indirectColor1
|
||||
text: name
|
||||
}
|
||||
StatusIcon {
|
||||
anchors.left: nameText.right
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
color: Theme.palette.indirectColor1
|
||||
icon: "close"
|
||||
}
|
||||
MouseArea {
|
||||
id: mouseArea
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onClicked: {
|
||||
removeMember(publicId);
|
||||
namesModel.remove(index, 1);
|
||||
}
|
||||
onWidthChanged: { scrollToEnd(); }
|
||||
onCountChanged: { scrollToEnd(); }
|
||||
delegate: StatusTagItem {
|
||||
isReadonly: model.isReadonly
|
||||
text: model.name
|
||||
icon: model.tagIcon
|
||||
|
||||
onClicked: {
|
||||
removeMember(model.pubKey);
|
||||
namesModel.remove(index, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TextEdit {
|
||||
TextInput {
|
||||
id: edit
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
focus: true
|
||||
color: Theme.palette.directColor1
|
||||
clip: true
|
||||
font.pixelSize: 15
|
||||
wrapMode: TextEdit.NoWrap
|
||||
font.family: Theme.palette.baseFont.name
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: 44
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
visible: (namesModel.count < 5)
|
||||
enabled: visible
|
||||
focus: true
|
||||
font.pixelSize: 15
|
||||
font.family: Theme.palette.baseFont.name
|
||||
color: Theme.palette.directColor1
|
||||
visible: (parent.width>22)
|
||||
Keys.onPressed: {
|
||||
if ((event.key === Qt.Key_Backspace || event.key === Qt.Key_Escape)
|
||||
&& getText(cursorPosition, (cursorPosition-1)) === "") {
|
||||
removeMember(namesModel.get(namesList.count-1).publicId);
|
||||
&& getText(cursorPosition, (cursorPosition-1)) === ""
|
||||
&& (namesList.count-1) >= 0) {
|
||||
removeMember(namesModel.get(namesList.count-1).pubKey);
|
||||
namesModel.remove((namesList.count-1), 1);
|
||||
}
|
||||
if ((event.key === Qt.Key_Return || event.key === Qt.Key_Enter) && (sortedList.count > 0)) {
|
||||
root.insertTag(sortedList.get(userListView.currentIndex).name,
|
||||
sortedList.get(userListView.currentIndex).pubKey,
|
||||
sortedList.get(userListView.currentIndex).isReadonly,
|
||||
sortedList.get(userListView.currentIndex).tagIcon);
|
||||
}
|
||||
}
|
||||
Keys.onUpPressed: { userListView.decrementCurrentIndex(); }
|
||||
Keys.onDownPressed: { userListView.incrementCurrentIndex(); }
|
||||
}
|
||||
|
||||
StatusBaseText {
|
||||
id: warningTextLabel
|
||||
visible: (namesModel.count === root.nameCountLimit)
|
||||
Layout.preferredWidth: 120
|
||||
Layout.preferredWidth: visible ? 120 : 0
|
||||
Layout.alignment: Qt.AlignVCenter | Qt.AlignRight
|
||||
font.pixelSize: 10
|
||||
color: Theme.palette.dangerColor1
|
||||
@@ -167,8 +336,9 @@ Item {
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: 8
|
||||
anchors.top: tagSelectorRect.bottom
|
||||
anchors.topMargin: 32
|
||||
visible: (namesModel.count === 0)
|
||||
anchors.topMargin: visible ? 32 : 0
|
||||
height: visible ? contentHeight : 0
|
||||
visible: (root.sortedList.count === 0)
|
||||
color: Theme.palette.baseColor1
|
||||
text: root.listLabel
|
||||
}
|
||||
@@ -178,24 +348,24 @@ Item {
|
||||
width: 360
|
||||
anchors {
|
||||
top: (root.sortedList.count > 0) ? tagSelectorRect.bottom : contactsLabel.bottom
|
||||
topMargin: 8//Style.current.padding
|
||||
topMargin: 8//Style.current.halfPadding
|
||||
bottom: parent.bottom
|
||||
bottomMargin: 20//Style.current.bigPadding
|
||||
bottomMargin: 16//Style.current.padding
|
||||
}
|
||||
visible: ((root.namesModel.count === 0) || (root.sortedList.count > 0))
|
||||
x: ((root.namesModel.count > 0) && ((edit.x + 8) <= (root.width - suggestionsContainer.width)))
|
||||
clip: true
|
||||
visible: (!root.showSortedListOnlyWhenText && ((root.sortedList.count > 0) || (edit.text === ""))) ||
|
||||
((edit.text !== "") && (root.sortedList.count > 0))
|
||||
x: ((root.namesModel.count > 0) && (root.sortedList.count > 0) && ((edit.x + 8) <= (root.width - suggestionsContainer.width)))
|
||||
? (edit.x + 8) : 0
|
||||
background: Rectangle {
|
||||
id: bgRect
|
||||
anchors.fill: parent
|
||||
anchors.margins: 8
|
||||
visible: (root.sortedList.count > 0)
|
||||
color: Theme.palette.statusPopupMenu.backgroundColor
|
||||
radius: 8
|
||||
layer.enabled: true
|
||||
layer.effect: DropShadow {
|
||||
width: bgRect.width
|
||||
height: bgRect.height
|
||||
x: bgRect.x
|
||||
source: bgRect
|
||||
horizontalOffset: 0
|
||||
verticalOffset: 4
|
||||
@@ -207,77 +377,48 @@ Item {
|
||||
}
|
||||
contentItem: ListView {
|
||||
id: userListView
|
||||
anchors.fill: parent
|
||||
anchors.topMargin: 8
|
||||
anchors.bottomMargin: 8
|
||||
clip: true
|
||||
anchors {
|
||||
fill: parent
|
||||
topMargin: 16
|
||||
leftMargin: 8
|
||||
rightMargin: 8
|
||||
}
|
||||
ScrollBar.vertical: ScrollBar {
|
||||
policy: ScrollBar.AsNeeded
|
||||
}
|
||||
boundsBehavior: Flickable.StopAtBounds
|
||||
delegate: Item {
|
||||
id: wrapper
|
||||
anchors.right: parent.right
|
||||
onCountChanged: {
|
||||
userListView.currentIndex = 0;
|
||||
}
|
||||
delegate: StatusMemberListItem {
|
||||
anchors.left: parent.left
|
||||
height: 64
|
||||
property bool hovered: false
|
||||
Rectangle {
|
||||
id: rectangle
|
||||
anchors.fill: parent
|
||||
anchors.rightMargin: 8
|
||||
anchors.leftMargin: 8
|
||||
radius: 8
|
||||
visible: (root.sortedList.count > 0)
|
||||
color: (wrapper.hovered) ? Theme.palette.baseColor2 : "transparent"
|
||||
anchors.leftMargin: bgRect.visible ? 8 : 0
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: bgRect.visible ? 8 : 0
|
||||
height: visible ? 64 : 0
|
||||
visible: {
|
||||
for (let i = 0; i < namesModel.count; i++) {
|
||||
if (namesModel.get(i).pubKey === model.pubKey) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
StatusSmartIdenticon {
|
||||
id: contactImage
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: 16//Style.current.padding
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
name: model.name
|
||||
icon: StatusIconSettings {
|
||||
width: 40
|
||||
height: 40
|
||||
letterSize: 15
|
||||
}
|
||||
image: StatusImageSettings {
|
||||
width: 40
|
||||
height: 40
|
||||
source: model.icon
|
||||
isIdenticon: model.isIdenticon
|
||||
}
|
||||
}
|
||||
|
||||
StatusBaseText {
|
||||
id: contactInfo
|
||||
text: model.name
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: 8
|
||||
anchors.left: contactImage.right
|
||||
anchors.leftMargin: 16
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
elide: Text.ElideRight
|
||||
color: Theme.palette.directColor1
|
||||
font.weight: Font.Medium
|
||||
font.pixelSize: 15
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
cursorShape: enabled ? Qt.PointingHandCursor : Qt.ArrowCursor
|
||||
acceptedButtons: Qt.LeftButton | Qt.RightButton
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
onEntered: {
|
||||
wrapper.hovered = true;
|
||||
}
|
||||
onExited: {
|
||||
wrapper.hovered = false;
|
||||
}
|
||||
onClicked: {
|
||||
root.insertTag(model.name, model.publicId);
|
||||
}
|
||||
nickName: model.localNickname
|
||||
userName: model.displayName
|
||||
pubKey: root.compressedKeyGetter(model.pubKey)
|
||||
isVerified: model.isVerified
|
||||
isUntrustworthy: model.isUntrustworthy
|
||||
isContact: model.isContact
|
||||
image.source: model.icon
|
||||
image.isIdenticon: false
|
||||
icon.color: Theme.palette.userCustomizationColors[root.colorIdForPubkeyGetter(model.pubKey)]
|
||||
status: model.onlineStatus
|
||||
statusListItemIcon.badge.border.color: sensor.containsMouse ? Theme.palette.baseColor2 : Theme.palette.baseColor4
|
||||
ringSettings.ringSpecModel: root.ringSpecModelGetter(model.pubKey)
|
||||
color: (sensor.containsMouse || highlighted) ? Theme.palette.baseColor2 : "transparent"
|
||||
onClicked: {
|
||||
root.insertTag(model.displayName, model.pubKey, model.isAdmin, model.isAdmin ? "crown" : "");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,30 +7,114 @@ import StatusQ.Core 0.1
|
||||
import StatusQ.Controls 0.1
|
||||
import StatusQ.Core.Theme 0.1
|
||||
|
||||
/*!
|
||||
\qmltype StatusToastMessage
|
||||
\inherits Control
|
||||
\inqmlmodule StatusQ.Components
|
||||
\since StatusQ.Components 0.1
|
||||
\brief Displays a toast message in the UI. Inherits \l{https://doc.qt.io/qt-5/qml-qtquick-controls2-control.html}{Control}.
|
||||
|
||||
The \c StatusToastMessage displays a toast message in the UI either standalone or as part
|
||||
of a stack of toast messages.
|
||||
For example:
|
||||
|
||||
\qml
|
||||
StatusToastMessage {
|
||||
primaryText: qsTr("Collectible is being minted...")
|
||||
secondaryText: qsTr("View on Etherscan")
|
||||
loading: true
|
||||
type: 0
|
||||
linkUrl: "http://google.com"
|
||||
duration: 5000
|
||||
}
|
||||
\endqml
|
||||
|
||||
\image status_toast_message.png
|
||||
|
||||
For a list of components available see StatusQ.
|
||||
*/
|
||||
|
||||
|
||||
Control {
|
||||
id: root
|
||||
width: 343
|
||||
height: !!secondaryText ? 68 : 48
|
||||
anchors.right: parent.right
|
||||
|
||||
property bool open: false
|
||||
/*!
|
||||
\qmlproperty bool StatusToastMessage::open
|
||||
This property represents all steps and their descriptions as provided by the user.
|
||||
*/
|
||||
property bool open: true
|
||||
/*!
|
||||
\qmlproperty string StatusToastMessage::primaryText
|
||||
This property represents the title text of the ToastMessage.
|
||||
*/
|
||||
property string primaryText: ""
|
||||
/*!
|
||||
\qmlproperty string StatusToastMessage::secondaryText
|
||||
This property represents the subtitle text of the ToastMessage.
|
||||
*/
|
||||
property string secondaryText: ""
|
||||
/*!
|
||||
\qmlproperty bool StatusToastMessage::loading
|
||||
This property represents activates/deactivates the loading indicator of the ToastMessage.
|
||||
*/
|
||||
property bool loading: false
|
||||
property string iconName: ""
|
||||
/*!
|
||||
\qmlproperty string StatusToastMessage::linkUrl
|
||||
This property represents all steps and their descriptions as provided by the user.
|
||||
*/
|
||||
property string linkUrl: ""
|
||||
|
||||
/*!
|
||||
\qmlproperty int StatusToastMessage::duration
|
||||
This property represents duration in milliseconds, for how long a toast will be visible. If 0 is set for
|
||||
duration, that means a toast won't dissapear without user's interaction (click on close).
|
||||
*/
|
||||
property int duration: 0
|
||||
|
||||
/*!
|
||||
\qmlproperty StatusIconSettings StatusToastMessage::icon
|
||||
This property holds a set of settings for the icon of the ToastMessage.
|
||||
*/
|
||||
property StatusIconSettings icon: StatusIconSettings {
|
||||
width: 23
|
||||
height: 23
|
||||
}
|
||||
|
||||
/*!
|
||||
\qmlproperty int StatusToastMessage::type
|
||||
This property holds the type of the ToastMessage. Values are:
|
||||
\list
|
||||
\li Default
|
||||
\li Success
|
||||
\endlist
|
||||
|
||||
*/
|
||||
property int type: StatusToastMessage.Type.Default
|
||||
enum Type {
|
||||
Default,
|
||||
Success
|
||||
}
|
||||
|
||||
/*!
|
||||
\qmlmethod
|
||||
This function is used to open the ToastMessage setting all its properties.
|
||||
Examples of usage:
|
||||
\qml
|
||||
StatusToastMessage {
|
||||
id: toastMessage
|
||||
}
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
toastMessage.open(qsTr("Verification Request Sent"), "", "checkmark-circle", 1, false,"");
|
||||
}
|
||||
}
|
||||
\endqml
|
||||
|
||||
*/
|
||||
function open(title, subTitle, iconName, type, loading, url) {
|
||||
root.primaryText = title;
|
||||
root.secondaryText = subTitle;
|
||||
@@ -41,12 +125,41 @@ Control {
|
||||
root.open = true;
|
||||
}
|
||||
|
||||
/*!
|
||||
\qmlsignal
|
||||
This signal is emitted when the ToastMessage is clicked.
|
||||
*/
|
||||
signal clicked()
|
||||
/*!
|
||||
\qmlsignal
|
||||
This signal is emitted when the ToastMessage is closed (after animation).
|
||||
*/
|
||||
signal close()
|
||||
/*!
|
||||
\qmlsignal
|
||||
This signal is emitted when the ToastMessage contains a url and this url
|
||||
is clicked by the user.
|
||||
*/
|
||||
signal linkActivated(var link)
|
||||
|
||||
QtObject {
|
||||
id: d
|
||||
|
||||
readonly property string openedState: "opened"
|
||||
readonly property string closedState: "closed"
|
||||
}
|
||||
|
||||
Timer {
|
||||
interval: root.duration
|
||||
running: root.duration > 0
|
||||
onTriggered: {
|
||||
root.open = false;
|
||||
}
|
||||
}
|
||||
|
||||
states: [
|
||||
State {
|
||||
name: "opened"
|
||||
name: d.openedState
|
||||
when: root.open
|
||||
PropertyChanges {
|
||||
target: root
|
||||
@@ -55,16 +168,13 @@ Control {
|
||||
}
|
||||
},
|
||||
State {
|
||||
name: "closed"
|
||||
name: d.closedState
|
||||
when: !root.open
|
||||
PropertyChanges {
|
||||
target: root
|
||||
anchors.rightMargin: -width
|
||||
opacity: 0.0
|
||||
}
|
||||
StateChangeScript {
|
||||
script: { root.close(); }
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
@@ -72,6 +182,12 @@ Control {
|
||||
Transition {
|
||||
to: "*"
|
||||
NumberAnimation { properties: "anchors.rightMargin,opacity"; duration: 400 }
|
||||
|
||||
onRunningChanged: {
|
||||
if(!running && state == d.closedState) {
|
||||
root.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
@@ -103,6 +219,9 @@ Control {
|
||||
onMouseXChanged: {
|
||||
root.open = (mouseX < (root.width/3));
|
||||
}
|
||||
onClicked: {
|
||||
root.clicked();
|
||||
}
|
||||
}
|
||||
RowLayout {
|
||||
anchors.fill: parent
|
||||
@@ -114,9 +233,14 @@ Control {
|
||||
radius: (root.width/2)
|
||||
color: (root.type === StatusToastMessage.Type.Success) ?
|
||||
Theme.palette.successColor2 : Theme.palette.primaryColor3
|
||||
visible: loader.sourceComponent != undefined
|
||||
Loader {
|
||||
id: loader
|
||||
anchors.centerIn: parent
|
||||
sourceComponent: root.loading ? loadingInd : statusIcon
|
||||
sourceComponent: root.loading ? loadingInd :
|
||||
root.icon.name != ""? statusIcon :
|
||||
undefined
|
||||
|
||||
Component {
|
||||
id: loadingInd
|
||||
StatusLoadingIndicator {
|
||||
|
||||
@@ -6,10 +6,42 @@ import StatusQ.Core 0.1
|
||||
import StatusQ.Controls 0.1
|
||||
import StatusQ.Core.Theme 0.1
|
||||
|
||||
/*!
|
||||
\qmltype StatusWizardStepper
|
||||
\inherits Item
|
||||
\inqmlmodule StatusQ.Components
|
||||
\since StatusQ.Components 0.1
|
||||
\brief Displays a step sequence provided by the stepsModel. Inherits \l{https://doc.qt.io/qt-5/qml-qtquick-item.html}{Item}.
|
||||
|
||||
The \c StatusWizardStepper steps and their descriptions as provided by the stepsModel.
|
||||
For example:
|
||||
|
||||
\qml
|
||||
StatusWizardStepper {
|
||||
id: wizardStepper
|
||||
stepsModel: ListModel {
|
||||
ListElement {description: qsTr("Send Request"); loadingTime: 0; stepCompleted: false}
|
||||
ListElement {description: qsTr("Receive Response"); loadingTime: 0; stepCompleted: false}
|
||||
ListElement {description: qsTr("Confirm Identity"); loadingTime: 0; stepCompleted: false}
|
||||
}
|
||||
}
|
||||
\endqml
|
||||
|
||||
\image status_wizard_stepper.png
|
||||
|
||||
For a list of components available see StatusQ.
|
||||
*/
|
||||
|
||||
Item {
|
||||
property int maxDuration: 2000
|
||||
|
||||
id: wizardWrapper
|
||||
width: parent.width
|
||||
height: 56
|
||||
/*!
|
||||
\qmlproperty ListModel StatusWizardStepper::stepsModel
|
||||
This property represents all steps and their descriptions as provided by the user.
|
||||
*/
|
||||
property ListModel stepsModel: ListModel { }
|
||||
|
||||
ListView {
|
||||
@@ -35,8 +67,7 @@ Item {
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.verticalCenterOffset: -12
|
||||
from: 0
|
||||
//TODO what is to: here?
|
||||
to: 2000
|
||||
to: wizardWrapper.maxDuration
|
||||
value: loadingTime
|
||||
backgroundColor: "transparent"
|
||||
backgroundBorderColor: Theme.palette.primaryColor1
|
||||
|
||||
@@ -115,6 +115,7 @@ Rectangle {
|
||||
properties: "scale";
|
||||
duration: 100;
|
||||
easing.type: Easing.InOutQuad
|
||||
running: visible
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@ StatusChatListCategoryItem 0.1 StatusChatListCategoryItem.qml
|
||||
StatusChatListAndCategories 0.1 StatusChatListAndCategories.qml
|
||||
StatusChatToolBar 0.1 StatusChatToolBar.qml
|
||||
StatusContactRequestsIndicatorListItem 0.1 StatusContactRequestsIndicatorListItem.qml
|
||||
StatusEmoji 0.1 StatusEmoji.qml
|
||||
StatusContactVerificationIcons 0.1 StatusContactVerificationIcons.qml
|
||||
StatusDescriptionListItem 0.1 StatusDescriptionListItem.qml
|
||||
StatusLetterIdenticon 0.1 StatusLetterIdenticon.qml
|
||||
@@ -24,6 +25,7 @@ StatusRoundedImage 0.1 StatusRoundedImage.qml
|
||||
StatusMacWindowButtons 0.1 StatusMacWindowButtons.qml
|
||||
StatusListItemBadge 0.1 StatusListItemBadge.qml
|
||||
StatusListItemTag 0.1 StatusListItemTag.qml
|
||||
StatusListPicker 0.1 StatusListPicker.qml
|
||||
StatusExpandableItem 0.1 StatusExpandableItem.qml
|
||||
StatusSmartIdenticon 0.1 StatusSmartIdenticon.qml
|
||||
StatusMessage 0.1 StatusMessage.qml
|
||||
@@ -31,3 +33,7 @@ StatusMessageDetails 0.1 StatusMessageDetails.qml
|
||||
StatusTagSelector 0.1 StatusTagSelector.qml
|
||||
StatusToastMessage 0.1 StatusToastMessage.qml
|
||||
StatusWizardStepper 0.1 StatusWizardStepper.qml
|
||||
StatusImageCropPanel 0.1 StatusImageCropPanel.qml
|
||||
StatusColorSpace 0.0 StatusColorSpace.qml
|
||||
StatusCommunityCard 0.1 StatusCommunityCard.qml
|
||||
StatusCommunityTags 0.1 StatusCommunityTags.qml
|
||||
|
||||