Compare commits
77
Commits
fix/issue-6930
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
17d82a7be0 | ||
|
|
a219e95a5c | ||
|
|
73d7e09536 | ||
|
|
2c43dbb207 | ||
|
|
3202294a11 | ||
|
|
d892a84227 | ||
|
|
ea5c83710b | ||
|
|
a94d9338bf | ||
|
|
7d96b2d4c1 | ||
|
|
9135b90ada | ||
|
|
fa3ba834e2 | ||
|
|
27acdd959b | ||
|
|
f79cf81db2 | ||
|
|
865fee22b8 | ||
|
|
d02fea1cd3 | ||
|
|
524a86b0cc | ||
|
|
1dc5592636 | ||
|
|
ef5f8746d5 | ||
|
|
9a24d59ea8 | ||
|
|
e17088304b | ||
|
|
1381b1bd15 | ||
|
|
f89b0a8c6f | ||
|
|
b1025fabd7 | ||
|
|
efc5be38bd | ||
|
|
c3bbb396ec | ||
|
|
21f1c4ce52 | ||
|
|
7108ac87cf | ||
|
|
384924ce58 | ||
|
|
8c683bf83c | ||
|
|
f6424328d8 | ||
|
|
60137c39b5 | ||
|
|
4d16ac17a8 | ||
|
|
504053a6bf | ||
|
|
fc10a0d43d | ||
|
|
3b6a6067af | ||
|
|
f1d7bdb069 | ||
|
|
32db0bb023 | ||
|
|
9688113d7f | ||
|
|
98d0d2163e | ||
|
|
e146ccaed4 | ||
|
|
5e7a0d8251 | ||
|
|
ecc44cfae0 | ||
|
|
ad8bc322d1 | ||
|
|
80a9cc9b3f | ||
|
|
803a7637bf | ||
|
|
4d9cec541f | ||
|
|
4d73c25c7a | ||
|
|
8646daa401 | ||
|
|
db0f8e9fb5 | ||
|
|
9d6cea7051 | ||
|
|
780ade987d | ||
|
|
fd6d735df8 | ||
|
|
4d63af303c | ||
|
|
1e12636abd | ||
|
|
89049fd56b | ||
|
|
be24401a50 | ||
|
|
8214e64684 | ||
|
|
50299f8d83 | ||
|
|
6e93b4ec41 | ||
|
|
6c107b5760 | ||
|
|
a9c0c88101 | ||
|
|
b59295d56b | ||
|
|
b9882c6ff6 | ||
|
|
72750ef60c | ||
|
|
9f6f9905e9 | ||
|
|
a22d8252b1 | ||
|
|
02bb67a266 | ||
|
|
f15b0d4de4 | ||
|
|
8f06729c1a | ||
|
|
c721a67c70 | ||
|
|
b2e8a0e282 | ||
|
|
76cc5fda22 | ||
|
|
e1d8d934b3 | ||
|
|
9fa6fb2324 | ||
|
|
ce22d8759c | ||
|
|
91cafca41f | ||
|
|
151097e466 |
@@ -2,6 +2,9 @@
|
||||
|
||||
> An emerging reusable QML UI component library for Status applications.
|
||||
|
||||
:bangbang: | This repository is set to read-only. `StatusQ` library is further developed in the [status-desktop](https://github.com/status-im/status-desktop) repository.
|
||||
:---: | :---
|
||||
|
||||
## Usage
|
||||
|
||||
StatusQ introduces a module namespace that semantically groups components so they can be easily imported.
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 122 KiB |
+4
-4
@@ -63,7 +63,7 @@ Rectangle {
|
||||
visible: titleStyle === "windows"
|
||||
}
|
||||
|
||||
StatusAppLayout {
|
||||
StatusMainLayout {
|
||||
id: statusAppLayout
|
||||
anchors.top: windowsTitle.visible ? windowsTitle.bottom : demoApp.top
|
||||
anchors.left: demoApp.left
|
||||
@@ -73,7 +73,7 @@ Rectangle {
|
||||
height: demoApp.height - demoApp.border.width * 2
|
||||
width: demoApp.width - demoApp.border.width * 2
|
||||
|
||||
appNavBar: StatusAppNavBar {
|
||||
leftPanel: StatusAppNavBar {
|
||||
|
||||
id: navBar
|
||||
|
||||
@@ -181,7 +181,7 @@ Rectangle {
|
||||
}
|
||||
}
|
||||
|
||||
appView: Loader {
|
||||
rightPanel: Loader {
|
||||
id: appView
|
||||
anchors.fill: parent
|
||||
sourceComponent: statusAppChatView
|
||||
@@ -197,7 +197,7 @@ Rectangle {
|
||||
id: statusAppCommunityView
|
||||
StatusAppCommunityView {
|
||||
communityDetailModalTitle: demoCommunityDetailModal.header.title
|
||||
communityDetailModalImage: demoCommunityDetailModal.header.image.source
|
||||
communityDetailModalImage: demoCommunityDetailModal.header.asset.name
|
||||
onChatInfoButtonClicked: {
|
||||
demoCommunityDetailModal.open();
|
||||
}
|
||||
|
||||
@@ -21,18 +21,37 @@ Column {
|
||||
StatusButton {
|
||||
text: "Button"
|
||||
type: StatusBaseButton.Type.Primary
|
||||
|
||||
StatusToolTip {
|
||||
visible: parent.hovered
|
||||
text: "Look I'm a tooltip on a button!"
|
||||
}
|
||||
onClicked: console.warn("Primary button clicked")
|
||||
onPressed: console.warn("Primary button pressed")
|
||||
}
|
||||
|
||||
StatusButton {
|
||||
text: "Button"
|
||||
enabled: false
|
||||
type: StatusBaseButton.Type.Primary
|
||||
|
||||
StatusToolTip {
|
||||
visible: parent.hovered
|
||||
text: "Tooltip on a disabled button, should not be visible!"
|
||||
}
|
||||
onClicked: console.warn("Primary disabled button clicked, this should not happen !!!")
|
||||
}
|
||||
|
||||
StatusButton {
|
||||
text: "Button"
|
||||
loading: true
|
||||
type: StatusBaseButton.Type.Primary
|
||||
|
||||
StatusToolTip {
|
||||
visible: parent.hovered
|
||||
text: "Look I'm a tooltip on a loading button!"
|
||||
}
|
||||
onClicked: console.warn("Primary loading button clicked, this should not happen !!!")
|
||||
}
|
||||
|
||||
// Large
|
||||
@@ -50,6 +69,25 @@ Column {
|
||||
loading: true
|
||||
}
|
||||
|
||||
// Large + Icon
|
||||
StatusButton {
|
||||
text: "Button"
|
||||
icon.name: "info"
|
||||
}
|
||||
|
||||
StatusButton {
|
||||
text: "Button"
|
||||
enabled: false
|
||||
icon.name: "info"
|
||||
}
|
||||
|
||||
StatusButton {
|
||||
text: "Button"
|
||||
loading: true
|
||||
icon.name: "info"
|
||||
}
|
||||
|
||||
// Danger
|
||||
StatusButton {
|
||||
text: "Button"
|
||||
type: StatusBaseButton.Type.Danger
|
||||
@@ -67,6 +105,7 @@ Column {
|
||||
type: StatusBaseButton.Type.Danger
|
||||
}
|
||||
|
||||
// Flat
|
||||
StatusFlatButton {
|
||||
text: "Button"
|
||||
}
|
||||
@@ -74,7 +113,6 @@ Column {
|
||||
StatusFlatButton {
|
||||
text: "Button"
|
||||
enabled: false
|
||||
|
||||
}
|
||||
|
||||
StatusFlatButton {
|
||||
@@ -82,6 +120,7 @@ Column {
|
||||
loading: true
|
||||
}
|
||||
|
||||
// Flat + Danger
|
||||
StatusFlatButton {
|
||||
text: "Button"
|
||||
type: StatusBaseButton.Type.Danger
|
||||
@@ -117,6 +156,7 @@ Column {
|
||||
loading: true
|
||||
}
|
||||
|
||||
// Small + danger
|
||||
StatusButton {
|
||||
text: "Button"
|
||||
type: StatusBaseButton.Type.Danger
|
||||
@@ -137,6 +177,7 @@ Column {
|
||||
loading: true
|
||||
}
|
||||
|
||||
// Flat + small
|
||||
StatusFlatButton {
|
||||
text: "Button"
|
||||
size: StatusBaseButton.Size.Small
|
||||
@@ -359,7 +400,12 @@ Column {
|
||||
// Button with emoji
|
||||
StatusButton {
|
||||
text: "Button with Emoji"
|
||||
icon.emoji: "🖼️️"
|
||||
asset.emoji: "🖼️️"
|
||||
}
|
||||
|
||||
StatusButton {
|
||||
width: parent.width
|
||||
text: "wide"
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
|
||||
@@ -113,18 +113,33 @@ GridLayout {
|
||||
StatusSwitch {
|
||||
|
||||
}
|
||||
StatusSwitch {
|
||||
text: "Switch with text"
|
||||
}
|
||||
|
||||
StatusRadioButton {
|
||||
text: "i'm radio!"
|
||||
text: "Radio button 1"
|
||||
checked: true
|
||||
}
|
||||
StatusRadioButton {
|
||||
text: "Radio button 2 (clicking on this text will uncheck the above)"
|
||||
}
|
||||
StatusRadioButton {
|
||||
LayoutMirroring.enabled : true
|
||||
text: "Radio button 3 (forced right-to-left)"
|
||||
}
|
||||
|
||||
StatusCheckBox {}
|
||||
StatusCheckBox { checkState: Qt.Checked}
|
||||
StatusCheckBox { text: "Check me on left side"}
|
||||
StatusCheckBox { text: "Check me on right side"; leftSide: false}
|
||||
|
||||
StatusChatInfoButton {
|
||||
title: "Iuri Matias"
|
||||
subTitle: "Contact"
|
||||
icon.color: Theme.palette.miscColor7
|
||||
image.source: "qrc:/demoapp/data/profile-image-1.jpeg"
|
||||
asset.color: Theme.palette.miscColor7
|
||||
asset.isImage: true
|
||||
asset.name: "qrc:/demoapp/data/profile-image-1.jpeg"
|
||||
type: StatusChatInfoButton.Type.OneToOneChat
|
||||
muted: true
|
||||
pinnedMessagesCount: 1
|
||||
@@ -135,12 +150,13 @@ GridLayout {
|
||||
implicitHeight: 48
|
||||
StatusChatInfoButton {
|
||||
title: "Iuri Matias elided"
|
||||
subTitle: "Contact"
|
||||
icon.color: Theme.palette.miscColor7
|
||||
image.source: "qrc:/demoapp/data/profile-image-1.jpeg"
|
||||
subTitle: "Very long subtitle should elide as well"
|
||||
asset.color: Theme.palette.miscColor7
|
||||
asset.isImage: true
|
||||
asset.name: "qrc:/demoapp/data/profile-image-1.jpeg"
|
||||
type: StatusChatInfoButton.Type.OneToOneChat
|
||||
muted: true
|
||||
pinnedMessagesCount: 1
|
||||
pinnedMessagesCount: 10
|
||||
width: 100
|
||||
}
|
||||
}
|
||||
@@ -151,8 +167,9 @@ GridLayout {
|
||||
StatusChatInfoButton {
|
||||
title: "Iuri Matias big not elided"
|
||||
subTitle: "Contact"
|
||||
icon.color: Theme.palette.miscColor7
|
||||
image.source: "qrc:/demoapp/data/profile-image-1.jpeg"
|
||||
asset.color: Theme.palette.miscColor7
|
||||
asset.isImage: true
|
||||
asset.name: "qrc:/demoapp/data/profile-image-1.jpeg"
|
||||
type: StatusChatInfoButton.Type.OneToOneChat
|
||||
muted: true
|
||||
pinnedMessagesCount: 1
|
||||
@@ -164,24 +181,32 @@ GridLayout {
|
||||
title: "group"
|
||||
subTitle: "Group Chat"
|
||||
pinnedMessagesCount: 1
|
||||
icon.color: Theme.palette.miscColor7
|
||||
asset.color: Theme.palette.miscColor7
|
||||
type: StatusChatInfoButton.Type.GroupChat
|
||||
}
|
||||
|
||||
StatusChatInfoButton {
|
||||
title: "public-chat"
|
||||
subTitle: "Public Chat"
|
||||
icon.color: Theme.palette.miscColor7
|
||||
asset.color: Theme.palette.miscColor7
|
||||
type: StatusChatInfoButton.Type.PublicChat
|
||||
}
|
||||
|
||||
StatusChatInfoButton {
|
||||
title: "community-channel"
|
||||
subTitle: "Community Chat"
|
||||
icon.color: Theme.palette.miscColor7
|
||||
asset.color: Theme.palette.miscColor7
|
||||
type: StatusChatInfoButton.Type.CommunityChat
|
||||
}
|
||||
|
||||
StatusChatInfoButton {
|
||||
title: "community-channel"
|
||||
subTitle: "Some very long description text to see how the whole item wraps or elides"
|
||||
asset.color: Theme.palette.miscColor7
|
||||
type: StatusChatInfoButton.Type.CommunityChat
|
||||
pinnedMessagesCount: 3
|
||||
}
|
||||
|
||||
StatusSlider {
|
||||
width: 360
|
||||
from: 0
|
||||
|
||||
+67
-69
@@ -12,93 +12,94 @@ import StatusQ.Popups 0.1
|
||||
Column {
|
||||
spacing: 10
|
||||
|
||||
StatusChatToolBar {
|
||||
toolbarComponent: chatInfoButton1
|
||||
StatusToolBar {
|
||||
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
|
||||
}
|
||||
headerContent: StatusChatInfoButton {
|
||||
width: Math.min(implicitWidth, parent.width)
|
||||
title: "Some contact"
|
||||
subTitle: "Contact"
|
||||
asset.color: Theme.palette.miscColor7
|
||||
type: StatusChatInfoButton.Type.OneToOneChat
|
||||
}
|
||||
}
|
||||
|
||||
StatusChatToolBar {
|
||||
toolbarComponent: chatInfoButton2
|
||||
StatusToolBar {
|
||||
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
|
||||
}
|
||||
headerContent: StatusChatInfoButton {
|
||||
width: Math.min(implicitWidth, parent.width)
|
||||
title: "Muted public chat"
|
||||
subTitle: "Some subtitle"
|
||||
asset.color: Theme.palette.miscColor7
|
||||
type: StatusChatInfoButton.Type.PublicChat
|
||||
pinnedMessagesCount: 1
|
||||
muted: true
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
StatusChatToolBar {
|
||||
StatusToolBar {
|
||||
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
|
||||
}
|
||||
headerContent: StatusChatInfoButton {
|
||||
width: Math.min(implicitWidth, parent.width)
|
||||
title: "Group chat"
|
||||
subTitle: "Group chat subtitle"
|
||||
asset.color: Theme.palette.miscColor7
|
||||
type: StatusChatInfoButton.Type.GroupChat
|
||||
pinnedMessagesCount: 1
|
||||
}
|
||||
}
|
||||
|
||||
StatusChatToolBar {
|
||||
notificationCount: 1
|
||||
toolbarComponent: tagSelector
|
||||
StatusToolBar {
|
||||
width: 518
|
||||
|
||||
Component {
|
||||
id: tagSelector
|
||||
headerContent: StatusChatInfoButton {
|
||||
title: "Community chat"
|
||||
subTitle: "Some very long description text to see how the whole item wraps or ellides"
|
||||
asset.color: Theme.palette.miscColor7
|
||||
type: StatusChatInfoButton.Type.CommunityChat
|
||||
pinnedMessagesCount: 3
|
||||
}
|
||||
}
|
||||
|
||||
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: ""
|
||||
}
|
||||
StatusToolBar {
|
||||
headerContent: StatusChatInfoButton {
|
||||
title: "Very long chat name"
|
||||
asset.color: Theme.palette.miscColor7
|
||||
type: StatusChatInfoButton.Type.CommunityChat
|
||||
pinnedMessagesCount: 1234567891
|
||||
}
|
||||
}
|
||||
|
||||
StatusToolBar {
|
||||
notificationCount: 1
|
||||
width: 518
|
||||
|
||||
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")
|
||||
}
|
||||
toLabelText: qsTr("To: ")
|
||||
warningText: qsTr("USER LIMIT REACHED")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -493,8 +494,5 @@ Column {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+202
-62
@@ -1,4 +1,6 @@
|
||||
import QtQuick 2.14
|
||||
import QtQuick.Controls 2.14
|
||||
import QtQml.Models 2.14
|
||||
import QtQuick.Layouts 1.14
|
||||
import StatusQ.Core 0.1
|
||||
import StatusQ.Core.Theme 0.1
|
||||
@@ -6,10 +8,8 @@ import StatusQ.Controls 0.1
|
||||
import StatusQ.Components 0.1
|
||||
import StatusQ.Core.Utils 0.1
|
||||
|
||||
GridLayout {
|
||||
columns: 1
|
||||
columnSpacing: 5
|
||||
rowSpacing: 5
|
||||
ColumnLayout {
|
||||
spacing: 5
|
||||
|
||||
StatusNavigationListItem {
|
||||
title: "Menu Item"
|
||||
@@ -17,18 +17,18 @@ GridLayout {
|
||||
|
||||
StatusNavigationListItem {
|
||||
title: "Menu Item"
|
||||
icon.name: "info"
|
||||
asset.name: "info"
|
||||
}
|
||||
|
||||
StatusNavigationListItem {
|
||||
title: "Menu Item"
|
||||
icon.name: "info"
|
||||
asset.name: "info"
|
||||
badge.value: 1
|
||||
}
|
||||
StatusNavigationListItem {
|
||||
title: "Menu Item (selected) with very long text"
|
||||
selected: true
|
||||
icon.name: "info"
|
||||
asset.name: "info"
|
||||
badge.value: 1
|
||||
}
|
||||
|
||||
@@ -55,6 +55,59 @@ GridLayout {
|
||||
opened: true
|
||||
}
|
||||
|
||||
StatusChatListCategoryItem {
|
||||
id: categoryItemInteractive
|
||||
title: "Chat category interactive"
|
||||
showActionButtons: true
|
||||
onAddButtonClicked: testEventsList.eventTriggered("Add button clicked")
|
||||
onMenuButtonClicked: testEventsList.eventTriggered("Menu button clicked")
|
||||
onToggleButtonClicked: {
|
||||
opened = !opened
|
||||
testEventsList.eventTriggered("Toggle button clicked")
|
||||
}
|
||||
onTitleClicked: {
|
||||
testEventsList.eventTriggered("Title clicked")
|
||||
}
|
||||
onClicked: {
|
||||
opened = !opened
|
||||
testEventsList.eventTriggered("Item clicked", itemId)
|
||||
}
|
||||
}
|
||||
|
||||
ListView {
|
||||
id: testEventsList
|
||||
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: categoryItemInteractive.opened ? 20 * count : 0
|
||||
|
||||
clip: true
|
||||
|
||||
function eventTriggered(message) {
|
||||
let obj = eventDelegateComponent.createObject()
|
||||
obj.text = message
|
||||
model.insert(0, obj)
|
||||
}
|
||||
|
||||
Component {
|
||||
id: eventDelegateComponent
|
||||
|
||||
ItemDelegate {
|
||||
implicitHeight: 20
|
||||
|
||||
property int index: ObjectModel.index
|
||||
|
||||
Timer {
|
||||
interval: 5000; running: true
|
||||
onTriggered: testObjectModel.remove(index)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
model: ObjectModel {
|
||||
id: testObjectModel
|
||||
}
|
||||
}
|
||||
|
||||
StatusChatListItem {
|
||||
name: "group-chat"
|
||||
type: StatusChatListItem.Type.GroupChat
|
||||
@@ -68,18 +121,20 @@ GridLayout {
|
||||
StatusChatListItem {
|
||||
name: "community-channel-emoji"
|
||||
type: StatusChatListItem.Type.CommunityChat
|
||||
icon.emoji: "😁"
|
||||
asset.emoji: "😁"
|
||||
}
|
||||
|
||||
StatusChatListItem {
|
||||
name: "community-channel-with-image"
|
||||
image.source: "qrc:/demoapp/data/profile-image-1.jpeg"
|
||||
asset.isImage: true
|
||||
asset.name: "qrc:/demoapp/data/profile-image-1.jpeg"
|
||||
type: StatusChatListItem.Type.CommunityChat
|
||||
}
|
||||
|
||||
StatusChatListItem {
|
||||
name: "Weird Crazy Otter"
|
||||
image.source: "qrc:/demoapp/data/profile-image-1.jpeg"
|
||||
asset.isImage: true
|
||||
asset.name: "qrc:/demoapp/data/profile-image-1.jpeg"
|
||||
type: StatusChatListItem.Type.OneToOneChat
|
||||
}
|
||||
|
||||
@@ -164,7 +219,7 @@ GridLayout {
|
||||
title: "Title"
|
||||
subTitle: "Super long description that causes a multiline paragraph and makes the size of the component grow. Let's see how it behaves."
|
||||
tertiaryTitle: "Tertiary title"
|
||||
icon.name: "info"
|
||||
asset.name: "info"
|
||||
|
||||
statusListItemTitle.font.pixelSize: 17
|
||||
statusListItemTitle.font.weight: Font.Bold
|
||||
@@ -173,27 +228,29 @@ GridLayout {
|
||||
StatusListItem {
|
||||
title: "Title"
|
||||
subTitle: "Subtitle"
|
||||
icon.name: "info"
|
||||
asset.name: "info"
|
||||
}
|
||||
|
||||
StatusListItem {
|
||||
title: "Title"
|
||||
subTitle: "Subtitle"
|
||||
image.source: "qrc:/demoapp/data/profile-image-1.jpeg"
|
||||
asset.isImage: true
|
||||
asset.name: "qrc:/demoapp/data/profile-image-1.jpeg"
|
||||
}
|
||||
|
||||
StatusListItem {
|
||||
title: "Title"
|
||||
subTitle: "Subtitle"
|
||||
image.source: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAlklEQVR4nOzW0QmDQBAG4SSkl7SUQlJGCrElq9F3QdjjVhh/5nv3cFhY9vUIYQiNITSG0Bh
|
||||
CExPynn1gWf9bx498P7/nzPcxEzGExhBdJGYihtAYQlO+tUZvqrPbqeudo5iJGEJjCE15a3VtodH3q2ImYgiNITTlTdG1nUZ5a92VITQxITFiJmIIjSE0htAYQrMHAAD//+wwFVpz+yqXAAAAAElFTkSuQmCC"
|
||||
image.isIdenticon: true
|
||||
asset.isImage: true
|
||||
asset.name: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAlklEQVR4nOzW0QmDQBAG4SSkl7SUQlJGCrElq9F3QdjjVhh/5nv3cFhY9vUIYQiNITSG0BhCExPynn1gWf9bx498P7/
|
||||
nzPcxEzGExhBdJGYihtAYQlO+tUZvqrPbqeudo5iJGEJjCE15a3VtodH3q2ImYgiNITTlTdG1nUZ5a92VITQxITFiJmIIjSE0htAYQrMHAAD//+wwFVpz+yqXAAAAAElFTkSuQmCC"
|
||||
asset.imgIsIdenticon: true
|
||||
}
|
||||
|
||||
StatusListItem {
|
||||
title: "Title"
|
||||
subTitle: "Subtitle"
|
||||
icon.name: "info"
|
||||
asset.name: "info"
|
||||
components: [StatusButton {
|
||||
text: "Button"
|
||||
size: StatusBaseButton.Size.Small
|
||||
@@ -203,35 +260,35 @@ CExPynn1gWf9bx498P7/nzPcxEzGExhBdJGYihtAYQlO+tUZvqrPbqeudo5iJGEJjCE15a3VtodH3q2I
|
||||
StatusListItem {
|
||||
title: "Title"
|
||||
subTitle: "Subtitle"
|
||||
icon.name: "info"
|
||||
asset.name: "info"
|
||||
components: [StatusSwitch {}]
|
||||
}
|
||||
|
||||
StatusListItem {
|
||||
title: "Title"
|
||||
subTitle: "Subtitle"
|
||||
icon.name: "info"
|
||||
asset.name: "info"
|
||||
components: [StatusRadioButton {}]
|
||||
}
|
||||
|
||||
StatusListItem {
|
||||
title: "Title"
|
||||
subTitle: "Subtitle"
|
||||
icon.name: "info"
|
||||
asset.name: "info"
|
||||
components: [StatusCheckBox {}]
|
||||
}
|
||||
|
||||
StatusListItem {
|
||||
title: "Title"
|
||||
subTitle: "Subtitle"
|
||||
icon.name: "info"
|
||||
asset.name: "info"
|
||||
label: "Text"
|
||||
}
|
||||
|
||||
StatusListItem {
|
||||
title: "Title"
|
||||
subTitle: "Subtitle"
|
||||
icon.name: "info"
|
||||
asset.name: "info"
|
||||
label: "Text"
|
||||
components: [
|
||||
StatusButton {
|
||||
@@ -244,7 +301,7 @@ CExPynn1gWf9bx498P7/nzPcxEzGExhBdJGYihtAYQlO+tUZvqrPbqeudo5iJGEJjCE15a3VtodH3q2I
|
||||
StatusListItem {
|
||||
title: "Title"
|
||||
subTitle: "Subtitle"
|
||||
icon.name: "info"
|
||||
asset.name: "info"
|
||||
label: "Text"
|
||||
components: [StatusSwitch {}]
|
||||
}
|
||||
@@ -252,7 +309,7 @@ CExPynn1gWf9bx498P7/nzPcxEzGExhBdJGYihtAYQlO+tUZvqrPbqeudo5iJGEJjCE15a3VtodH3q2I
|
||||
StatusListItem {
|
||||
title: "Title"
|
||||
subTitle: "Subtitle"
|
||||
icon.name: "info"
|
||||
asset.name: "info"
|
||||
label: "Text"
|
||||
components: [
|
||||
StatusRadioButton {}
|
||||
@@ -262,7 +319,7 @@ CExPynn1gWf9bx498P7/nzPcxEzGExhBdJGYihtAYQlO+tUZvqrPbqeudo5iJGEJjCE15a3VtodH3q2I
|
||||
StatusListItem {
|
||||
title: "Title"
|
||||
subTitle: "Subtitle"
|
||||
icon.name: "info"
|
||||
asset.name: "info"
|
||||
label: "Text"
|
||||
components: [StatusCheckBox {}]
|
||||
}
|
||||
@@ -270,7 +327,7 @@ CExPynn1gWf9bx498P7/nzPcxEzGExhBdJGYihtAYQlO+tUZvqrPbqeudo5iJGEJjCE15a3VtodH3q2I
|
||||
StatusListItem {
|
||||
title: "Title"
|
||||
subTitle: "Subtitle"
|
||||
icon.name: "info"
|
||||
asset.name: "info"
|
||||
label: "Text"
|
||||
components: [
|
||||
StatusBadge {
|
||||
@@ -287,14 +344,14 @@ CExPynn1gWf9bx498P7/nzPcxEzGExhBdJGYihtAYQlO+tUZvqrPbqeudo5iJGEJjCE15a3VtodH3q2I
|
||||
|
||||
StatusListItem {
|
||||
title: "Title"
|
||||
icon.name: "info"
|
||||
asset.name: "info"
|
||||
type: StatusListItem.Type.Secondary
|
||||
}
|
||||
|
||||
StatusListItem {
|
||||
title: "Title"
|
||||
icon.isLetterIdenticon: true
|
||||
icon.color: "orange"
|
||||
asset.isLetterIdenticon: true
|
||||
asset.color: "orange"
|
||||
}
|
||||
|
||||
StatusListItem {
|
||||
@@ -304,17 +361,19 @@ CExPynn1gWf9bx498P7/nzPcxEzGExhBdJGYihtAYQlO+tUZvqrPbqeudo5iJGEJjCE15a3VtodH3q2I
|
||||
|
||||
StatusListItem {
|
||||
title: "Title"
|
||||
icon.name: "delete"
|
||||
asset.name: "delete"
|
||||
type: StatusListItem.Type.Danger
|
||||
}
|
||||
|
||||
StatusListItem {
|
||||
title: "List Item with Badge"
|
||||
subTitle: "Subtitle"
|
||||
image.source: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAlklEQVR4nOzW0QmDQBAG4SSkl7SUQlJGCrElq9F3QdjjVhh/5nv3cFhY9vUIYQiNITSG0Bh
|
||||
CExPynn1gWf9bx498P7/nzPcxEzGExhBdJGYihtAYQlO+tUZvqrPbqeudo5iJGEJjCE15a3VtodH3q2ImYgiNITTlTdG1nUZ5a92VITQxITFiJmIIjSE0htAYQrMHAAD//+wwFVpz+yqXAAAAAElFTkSuQmCC"
|
||||
image.isIdenticon: true
|
||||
badge.image.source: "qrc:/demoapp/data/profile-image-1.jpeg"
|
||||
asset.isImage: true
|
||||
asset.name: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAlklEQVR4nOzW0QmDQBAG4SSkl7SUQlJGCrElq9F3QdjjVhh/5nv3cFhY9vUIYQiNITSG0BhCExPynn1gWf9bx498P7/
|
||||
nzPcxEzGExhBdJGYihtAYQlO+tUZvqrPbqeudo5iJGEJjCE15a3VtodH3q2ImYgiNITTlTdG1nUZ5a92VITQxITFiJmIIjSE0htAYQrMHAAD//+wwFVpz+yqXAAAAAElFTkSuQmCC"
|
||||
asset.imgIsIdenticon: true
|
||||
badge.asset.isImage: true
|
||||
badge.asset.name: "qrc:/demoapp/data/profile-image-1.jpeg"
|
||||
badge.primaryText: "CryptoKitties"
|
||||
badge.secondaryText: "#test"
|
||||
}
|
||||
@@ -322,36 +381,57 @@ CExPynn1gWf9bx498P7/nzPcxEzGExhBdJGYihtAYQlO+tUZvqrPbqeudo5iJGEJjCE15a3VtodH3q2I
|
||||
StatusListItem {
|
||||
title: "List Item with Badge 2"
|
||||
subTitle: "Subtitle"
|
||||
icon.isLetterIdenticon: true
|
||||
asset.isLetterIdenticon: true
|
||||
badge.primaryText: "CryptoKitties"
|
||||
badge.secondaryText: "#test"
|
||||
badge.icon.color: "orange"
|
||||
badge.icon.isLetterIdenticon: true
|
||||
badge.asset.color: "orange"
|
||||
badge.asset.isLetterIdenticon: true
|
||||
}
|
||||
|
||||
StatusListItem {
|
||||
title: "List Item with Tags"
|
||||
icon.isLetterIdenticon: true
|
||||
asset.isLetterIdenticon: true
|
||||
bottomModel: 3
|
||||
bottomDelegate: StatusListItemTag {
|
||||
title: "tag"
|
||||
icon.isLetterIdenticon: true
|
||||
asset.isLetterIdenticon: true
|
||||
}
|
||||
}
|
||||
|
||||
StatusListItem {
|
||||
title: "List Item with Inline Tags"
|
||||
icon.isLetterIdenticon: true
|
||||
tagsModel : 2
|
||||
asset.isLetterIdenticon: true
|
||||
tagsModel: ListModel{
|
||||
ListElement {
|
||||
name: "helloworld.eth"
|
||||
emoji: "😁"
|
||||
}
|
||||
ListElement {
|
||||
name: "account1"
|
||||
emoji: "😁"
|
||||
}
|
||||
ListElement {
|
||||
name: "account2"
|
||||
emoji: "😁"
|
||||
}
|
||||
ListElement {
|
||||
name: "account3"
|
||||
emoji: "😁"
|
||||
}
|
||||
ListElement {
|
||||
name: "account4"
|
||||
emoji: "😁"
|
||||
}
|
||||
}
|
||||
tagsDelegate: StatusListItemTag {
|
||||
color: "blue"
|
||||
height: 24
|
||||
radius: 6
|
||||
closeButtonVisible: false
|
||||
icon.emoji: "😁"
|
||||
icon.emojiSize: Emoji.size.verySmall
|
||||
icon.isLetterIdenticon: true
|
||||
title: "helloworld.eth"
|
||||
asset.emoji: model.emoji
|
||||
asset.emojiSize: Emoji.size.verySmall
|
||||
asset.isLetterIdenticon: true
|
||||
title: model.name
|
||||
titleText.font.pixelSize: 12
|
||||
titleText.color: Theme.palette.indirectColor1
|
||||
}
|
||||
@@ -360,10 +440,10 @@ CExPynn1gWf9bx498P7/nzPcxEzGExhBdJGYihtAYQlO+tUZvqrPbqeudo5iJGEJjCE15a3VtodH3q2I
|
||||
StatusListItem {
|
||||
title: "List Item with Emoji"
|
||||
subTitle: "Emoji"
|
||||
icon.emoji: "😁"
|
||||
icon.color: "yellow"
|
||||
icon.letterSize: 14
|
||||
icon.isLetterIdenticon: true
|
||||
asset.emoji: "😁"
|
||||
asset.color: "yellow"
|
||||
asset.letterSize: 14
|
||||
asset.isLetterIdenticon: true
|
||||
}
|
||||
|
||||
StatusDescriptionListItem {
|
||||
@@ -382,7 +462,7 @@ CExPynn1gWf9bx498P7/nzPcxEzGExhBdJGYihtAYQlO+tUZvqrPbqeudo5iJGEJjCE15a3VtodH3q2I
|
||||
title: "Title"
|
||||
subTitle: "Subtitle"
|
||||
tooltip.text: "Tooltip"
|
||||
icon.name: "info"
|
||||
asset.name: "info"
|
||||
iconButton.onClicked: tooltip.visible = !tooltip.visible
|
||||
}
|
||||
|
||||
@@ -397,9 +477,10 @@ CExPynn1gWf9bx498P7/nzPcxEzGExhBdJGYihtAYQlO+tUZvqrPbqeudo5iJGEJjCE15a3VtodH3q2I
|
||||
pubKey: "0x043a7ed0e8752236a4688563652fd0296453cef00a5dcddbe252dc74f72cc1caa97a2b65e4a1a52d9c30a84c9966beaaaf6b333d659cbdd2e486b443ed1012cf04"
|
||||
isVerified: true
|
||||
isContact: true
|
||||
image.source: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAlklEQVR4nOzW0QmDQBAG4SSkl7SUQlJGCrElq9F3QdjjVhh/5nv3cFhY9vUIYQiNITSG0BhCExPynn1gWf9bx498P7/
|
||||
asset.isImage: true
|
||||
asset.name: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAlklEQVR4nOzW0QmDQBAG4SSkl7SUQlJGCrElq9F3QdjjVhh/5nv3cFhY9vUIYQiNITSG0BhCExPynn1gWf9bx498P7/
|
||||
nzPcxEzGExhBdJGYihtAYQlO+tUZvqrPbqeudo5iJGEJjCE15a3VtodH3q2ImYgiNITTlTdG1nUZ5a92VITQxITFiJmIIjSE0htAYQrMHAAD//+wwFVpz+yqXAAAAAElFTkSuQmCC"
|
||||
image.isIdenticon: true
|
||||
asset.imgIsIdenticon: true
|
||||
status: 1 // FIXME: use enum
|
||||
ringSettings.ringSpecModel:
|
||||
ListModel {
|
||||
@@ -417,16 +498,27 @@ CExPynn1gWf9bx498P7/nzPcxEzGExhBdJGYihtAYQlO+tUZvqrPbqeudo5iJGEJjCE15a3VtodH3q2I
|
||||
StatusMemberListItem {
|
||||
nickName: "carmen.eth"
|
||||
isUntrustworthy: true
|
||||
asset.isLetterIdenticon: true
|
||||
}
|
||||
|
||||
StatusMemberListItem {
|
||||
nickName: "very-long-annoying-nickname.eth"
|
||||
isUntrustworthy: true
|
||||
asset.isLetterIdenticon: true
|
||||
}
|
||||
|
||||
StatusMemberListItem {
|
||||
nickName: "untrusted-admin.eth"
|
||||
asset.isLetterIdenticon: true
|
||||
isUntrustworthy: true
|
||||
isAdmin: true
|
||||
isContact: true
|
||||
}
|
||||
|
||||
StatusMemberListItem {
|
||||
nickName: "This girl I know from work"
|
||||
userName: "annabelle"
|
||||
asset.isLetterIdenticon: true
|
||||
status: 1 // FIXME: use enum
|
||||
}
|
||||
|
||||
@@ -435,15 +527,21 @@ CExPynn1gWf9bx498P7/nzPcxEzGExhBdJGYihtAYQlO+tUZvqrPbqeudo5iJGEJjCE15a3VtodH3q2I
|
||||
userName: "annabelle"
|
||||
pubKey: "0x043a7ed0e8752236a4688563652fd0296453cef00a5dcddbe252dc74f72cc1caa97a2b65e4a1a52d9c30a84c9966beaaaf6b333d659cbdd2e486b443ed1012cf04"
|
||||
isContact: true
|
||||
image.source: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAlklEQVR4nOzW0QmDQBAG4SSkl7SUQlJGCrElq9F3QdjjVhh/5nv3cFhY9vUIYQiNITSG0BhCExPynn1gWf9bx498P7/
|
||||
asset.isImage: true
|
||||
asset.name: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAlklEQVR4nOzW0QmDQBAG4SSkl7SUQlJGCrElq9F3QdjjVhh/5nv3cFhY9vUIYQiNITSG0BhCExPynn1gWf9bx498P7/
|
||||
nzPcxEzGExhBdJGYihtAYQlO+tUZvqrPbqeudo5iJGEJjCE15a3VtodH3q2ImYgiNITTlTdG1nUZ5a92VITQxITFiJmIIjSE0htAYQrMHAAD//+wwFVpz+yqXAAAAAElFTkSuQmCC"
|
||||
image.isIdenticon: true
|
||||
asset.imgIsIdenticon: true
|
||||
}
|
||||
|
||||
StatusMemberListItem {
|
||||
nickName: "admin.guy"
|
||||
userName: "adguy"
|
||||
isAdmin: true
|
||||
asset.isLetterIdenticon: true
|
||||
isUntrustworthy: true
|
||||
Component.onCompleted: {
|
||||
print(asset.name, asset.isImage, asset.isLetterIdenticon)
|
||||
}
|
||||
}
|
||||
|
||||
StatusBaseText {
|
||||
@@ -457,10 +555,12 @@ CExPynn1gWf9bx498P7/nzPcxEzGExhBdJGYihtAYQlO+tUZvqrPbqeudo5iJGEJjCE15a3VtodH3q2I
|
||||
title: "Nokia 3310"
|
||||
subTitle: "Incoming device"
|
||||
label: "loading: true"
|
||||
icon.emoji: "😁"
|
||||
icon.color: "hotpink"
|
||||
icon.letterSize: 14
|
||||
icon.isLetterIdenticon: true
|
||||
asset.width: 40
|
||||
asset.height: 40
|
||||
asset.emoji: "😁"
|
||||
asset.color: "hotpink"
|
||||
asset.letterSize: 14
|
||||
asset.isLetterIdenticon: true
|
||||
loading: true
|
||||
}
|
||||
|
||||
@@ -468,10 +568,50 @@ CExPynn1gWf9bx498P7/nzPcxEzGExhBdJGYihtAYQlO+tUZvqrPbqeudo5iJGEJjCE15a3VtodH3q2I
|
||||
title: "Nokia 3310"
|
||||
subTitle: "Device"
|
||||
label: "loadingFailed: true"
|
||||
icon.emoji: "😁"
|
||||
icon.color: "hotpink"
|
||||
icon.letterSize: 14
|
||||
icon.isLetterIdenticon: true
|
||||
asset.width: 40
|
||||
asset.height: 40
|
||||
asset.emoji: "😁"
|
||||
asset.color: "hotpink"
|
||||
asset.letterSize: 14
|
||||
asset.isLetterIdenticon: true
|
||||
loadingFailed: true
|
||||
}
|
||||
|
||||
StatusListItem {
|
||||
implicitWidth: 600
|
||||
title: "List Item with Tags"
|
||||
subTitle: "03:32"
|
||||
asset.isLetterIdenticon: true
|
||||
inlineTagModel: 6
|
||||
inlineTagDelegate: StatusListItemTag {
|
||||
height: 24
|
||||
title: "tag"
|
||||
asset.isLetterIdenticon: true
|
||||
}
|
||||
components: [
|
||||
ColumnLayout {
|
||||
Row {
|
||||
Layout.alignment: Qt.AlignRight
|
||||
spacing: 4
|
||||
StatusIcon {
|
||||
color: Theme.palette.successColor1
|
||||
icon: "arrow-up"
|
||||
rotation: 135
|
||||
height: 18
|
||||
}
|
||||
StatusBaseText {
|
||||
text: "0.0000015 ETH"
|
||||
font.pixelSize: 15
|
||||
color: Theme.palette.directColor1
|
||||
}
|
||||
}
|
||||
StatusBaseText {
|
||||
Layout.alignment: Qt.AlignRight
|
||||
text: "1201.10 USD"
|
||||
font.pixelSize: 15
|
||||
color: Theme.palette.baseColor1
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,7 +40,7 @@ ColumnLayout {
|
||||
}
|
||||
|
||||
StatusRoundIcon {
|
||||
icon.name: "info"
|
||||
asset.name: "info"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+24
-20
@@ -109,7 +109,8 @@ Column {
|
||||
anchors.centerIn: parent
|
||||
header.title: "Some Title"
|
||||
header.subTitle: "Subtitle"
|
||||
header.image.source: "qrc:/demoapp/data/profile-image-1.jpeg"
|
||||
header.asset.isImage: true
|
||||
header.asset.name: "qrc:/demoapp/data/profile-image-1.jpeg"
|
||||
}
|
||||
|
||||
StatusModal {
|
||||
@@ -117,7 +118,8 @@ Column {
|
||||
anchors.centerIn: parent
|
||||
header.title: "Some Title"
|
||||
header.subTitle: "Subtitle"
|
||||
header.image.source: "qrc:/demoapp/data/profile-image-1.jpeg"
|
||||
header.asset.isImage: true
|
||||
header.asset.name: "qrc:/demoapp/data/profile-image-1.jpeg"
|
||||
leftButtons: [
|
||||
StatusBackButton { }
|
||||
]
|
||||
@@ -136,7 +138,8 @@ Column {
|
||||
anchors.centerIn: parent
|
||||
header.title: "Some Title"
|
||||
header.subTitle: "Subtitle"
|
||||
header.image.source: "qrc:/demoapp/data/profile-image-1.jpeg"
|
||||
header.asset.isImage: true
|
||||
header.asset.name: "qrc:/demoapp/data/profile-image-1.jpeg"
|
||||
|
||||
headerActionButton: StatusFlatRoundButton {
|
||||
type: StatusFlatRoundButton.Type.Secondary
|
||||
@@ -164,7 +167,8 @@ Column {
|
||||
StatusModal {
|
||||
id: modalExample
|
||||
anchors.centerIn: parent
|
||||
header.image.source: "qrc:/demoapp/data/profile-image-1.jpeg"
|
||||
header.asset.isImage: true
|
||||
header.asset.name: "qrc:/demoapp/data/profile-image-1.jpeg"
|
||||
header.title: "Header"
|
||||
header.subTitle: "SubTitle"
|
||||
rightButtons: [
|
||||
@@ -227,8 +231,8 @@ Column {
|
||||
anchors.centerIn: parent
|
||||
header.title: "Header"
|
||||
header.subTitle: "SubTitle"
|
||||
header.icon.isLetterIdenticon: true
|
||||
header.icon.background.color: "red"
|
||||
header.asset.isLetterIdenticon: true
|
||||
header.asset.bgColor: "red"
|
||||
|
||||
contentItem: StatusBaseText {
|
||||
anchors.centerIn: parent
|
||||
@@ -252,9 +256,9 @@ Column {
|
||||
anchors.centerIn: parent
|
||||
header.title: "Header"
|
||||
header.subTitle: "SubTitle"
|
||||
header.image.source: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAlklEQVR4nOzW0QmDQBAG4SSkl7SUQlJGCrElq9F3QdjjVhh/5nv3cFhY9vUIYQiNITSG0Bh
|
||||
CExPynn1gWf9bx498P7/nzPcxEzGExhBdJGYihtAYQlO+tUZvqrPbqeudo5iJGEJjCE15a3VtodH3q2ImYgiNITTlTdG1nUZ5a92VITQxITFiJmIIjSE0htAYQrMHAAD//+wwFVpz+yqXAAAAAElFTkSuQmCC"
|
||||
header.image.isIdenticon: true
|
||||
header.asset.name: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAlklEQVR4nOzW0QmDQBAG4SSkl7SUQlJGCrElq9F3QdjjVhh/5nv3cFhY9vUIYQiNITSG0BhCExPynn1gWf9bx498P7/
|
||||
nzPcxEzGExhBdJGYihtAYQlO+tUZvqrPbqeudo5iJGEJjCE15a3VtodH3q2ImYgiNITTlTdG1nUZ5a92VITQxITFiJmIIjSE0htAYQrMHAAD//+wwFVpz+yqXAAAAAElFTkSuQmCC"
|
||||
header.asset.imgIsIdenticon: true
|
||||
|
||||
contentItem: StatusBaseText {
|
||||
anchors.centerIn: parent
|
||||
@@ -279,9 +283,9 @@ CExPynn1gWf9bx498P7/nzPcxEzGExhBdJGYihtAYQlO+tUZvqrPbqeudo5iJGEJjCE15a3VtodH3q2I
|
||||
header.title: "Header"
|
||||
header.subTitle: "SubTitle"
|
||||
header.headerImageEditable: true
|
||||
header.image.source: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAlklEQVR4nOzW0QmDQBAG4SSkl7SUQlJGCrElq9F3QdjjVhh/5nv3cFhY9vUIYQiNITSG0Bh
|
||||
CExPynn1gWf9bx498P7/nzPcxEzGExhBdJGYihtAYQlO+tUZvqrPbqeudo5iJGEJjCE15a3VtodH3q2ImYgiNITTlTdG1nUZ5a92VITQxITFiJmIIjSE0htAYQrMHAAD//+wwFVpz+yqXAAAAAElFTkSuQmCC"
|
||||
header.image.isIdenticon: true
|
||||
header.asset.name: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAlklEQVR4nOzW0QmDQBAG4SSkl7SUQlJGCrElq9F3QdjjVhh/5nv3cFhY9vUIYQiNITSG0BhCExPynn1gWf9bx498P7/
|
||||
nzPcxEzGExhBdJGYihtAYQlO+tUZvqrPbqeudo5iJGEJjCE15a3VtodH3q2ImYgiNITTlTdG1nUZ5a92VITQxITFiJmIIjSE0htAYQrMHAAD//+wwFVpz+yqXAAAAAElFTkSuQmCC"
|
||||
header.asset.imgIsIdenticon: true
|
||||
|
||||
contentItem: StatusBaseText {
|
||||
anchors.centerIn: parent
|
||||
@@ -306,9 +310,9 @@ CExPynn1gWf9bx498P7/nzPcxEzGExhBdJGYihtAYQlO+tUZvqrPbqeudo5iJGEJjCE15a3VtodH3q2I
|
||||
header.title: "Some super long text here that exceeds the available space"
|
||||
header.subTitle: "Some super long text here that exceeds the available space"
|
||||
header.subTitleElide: Text.ElideMiddle
|
||||
header.image.source: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAlklEQVR4nOzW0QmDQBAG4SSkl7SUQlJGCrElq9F3QdjjVhh/5nv3cFhY9vUIYQiNITSG0Bh
|
||||
CExPynn1gWf9bx498P7/nzPcxEzGExhBdJGYihtAYQlO+tUZvqrPbqeudo5iJGEJjCE15a3VtodH3q2ImYgiNITTlTdG1nUZ5a92VITQxITFiJmIIjSE0htAYQrMHAAD//+wwFVpz+yqXAAAAAElFTkSuQmCC"
|
||||
header.image.isIdenticon: true
|
||||
header.asset.name: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAlklEQVR4nOzW0QmDQBAG4SSkl7SUQlJGCrElq9F3QdjjVhh/5nv3cFhY9vUIYQiNITSG0BhCExPynn1gWf9bx498P7/
|
||||
nzPcxEzGExhBdJGYihtAYQlO+tUZvqrPbqeudo5iJGEJjCE15a3VtodH3q2ImYgiNITTlTdG1nUZ5a92VITQxITFiJmIIjSE0htAYQrMHAAD//+wwFVpz+yqXAAAAAElFTkSuQmCC"
|
||||
header.asset.imgIsIdenticon: true
|
||||
|
||||
contentItem: StatusBaseText {
|
||||
anchors.centerIn: parent
|
||||
@@ -340,7 +344,7 @@ CExPynn1gWf9bx498P7/nzPcxEzGExhBdJGYihtAYQlO+tUZvqrPbqeudo5iJGEJjCE15a3VtodH3q2I
|
||||
sourceComponent: popupMenu.delegate
|
||||
onLoaded: {
|
||||
item.action.text = model.name
|
||||
item.action.iconSettings.name = model.iconName
|
||||
item.action.assetSettings.name = model.iconName
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -415,11 +419,11 @@ CExPynn1gWf9bx498P7/nzPcxEzGExhBdJGYihtAYQlO+tUZvqrPbqeudo5iJGEJjCE15a3VtodH3q2I
|
||||
topPadding: 8
|
||||
bottomPadding: 0
|
||||
implicitHeight: 32
|
||||
defaultLeftPadding: 4
|
||||
leftPadding: 4
|
||||
text: name
|
||||
icon.emoji: !!emoji ? emoji: ""
|
||||
icon.emojiSize: Emoji.size.middle
|
||||
icon.name: !emoji ? "filled-account": ""
|
||||
asset.emoji: !!emoji ? emoji: ""
|
||||
asset.emojiSize: Emoji.size.middle
|
||||
asset.name: !emoji ? "filled-account": ""
|
||||
normalColor: "transparent"
|
||||
highlighted: index === floatingHeader.currentIndex
|
||||
onClicked: {
|
||||
|
||||
@@ -14,9 +14,10 @@ ListView {
|
||||
anchors.fill: parent
|
||||
anchors.margins: 15
|
||||
clip: true
|
||||
|
||||
delegate: StatusMessage {
|
||||
id: delegate
|
||||
width: parent.width
|
||||
width: ListView.view.width
|
||||
|
||||
audioMessageInfoText: "Audio Message"
|
||||
cancelButtonText: "Cancel"
|
||||
@@ -26,44 +27,69 @@ ListView {
|
||||
resendText: "Resend"
|
||||
pinnedMsgInfoText: "Pinned by"
|
||||
|
||||
timestamp: model.timestamp
|
||||
isAReply: model.isReply
|
||||
hasMention: model.hasMention
|
||||
isPinned: model.isPinned
|
||||
pinnedBy: model.pinnedBy
|
||||
hasExpired: model.hasExpired
|
||||
reactionsModel: model.reactions || []
|
||||
|
||||
messageDetails: StatusMessageDetails {
|
||||
contentType: model.contentType
|
||||
messageContent: model.messageContent
|
||||
amISender: model.amIsender
|
||||
displayName: model.userName
|
||||
secondaryName: model.localName !== "" && model.ensName.startsWith("@") ? model.ensName: ""
|
||||
chatID: model.chatKey
|
||||
profileImage: StatusImageSettings {
|
||||
sender.id: model.senderId
|
||||
sender.displayName: model.senderDisplayName
|
||||
sender.secondaryName: model.senderOptionalName
|
||||
sender.isContact: model.isContact
|
||||
sender.trustIndicator: model.trustIndicator
|
||||
sender.profileImage: StatusProfileImageSettings {
|
||||
width: 40
|
||||
height: 40
|
||||
source: model.profileImage
|
||||
isIdenticon: model.isIdenticon
|
||||
pubkey: model.senderId
|
||||
name: model.profileImage || ""
|
||||
colorId: 1
|
||||
colorHash: ListModel {
|
||||
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 }
|
||||
}
|
||||
}
|
||||
|
||||
messageText: model.message
|
||||
hasMention: model.hasMention
|
||||
isContact: model.isContact
|
||||
trustIndicator: model.trustIndicator
|
||||
isPinned: model.isPinned
|
||||
pinnedBy: model.pinnedBy
|
||||
hasExpired: model.hasExpired
|
||||
}
|
||||
timestamp.text: "10:00 am"
|
||||
timestamp.tooltip.text: "10:01 am"
|
||||
// reply related data
|
||||
isAReply: model.isReply
|
||||
|
||||
replyDetails: StatusMessageDetails {
|
||||
amISender: model.isReply ? model.replyAmISender : ""
|
||||
displayName: model.isReply ? model.replySenderName: ""
|
||||
profileImage: StatusImageSettings {
|
||||
amISender: model.isReply && model.replyAmISender
|
||||
sender.id: model.replySenderId || ""
|
||||
sender.displayName: model.isReply ? model.replySenderName: ""
|
||||
sender.secondaryName: model.isReply ? model.replySenderEnsName : ""
|
||||
sender.profileImage: StatusProfileImageSettings {
|
||||
width: 20
|
||||
height: 20
|
||||
source: model.isReply ? model.replyProfileImage: ""
|
||||
isIdenticon: model.isReply ? model.replyIsIdenticon: ""
|
||||
name: model.isReply ? model.replyProfileImage: ""
|
||||
pubkey: model.replySenderId
|
||||
colorId: 1
|
||||
colorHash: ListModel {
|
||||
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 }
|
||||
}
|
||||
}
|
||||
messageText: model.isReply ? model.replyMessageText: ""
|
||||
contentType: model.replyContentType
|
||||
messageContent: model.replyMessageContent
|
||||
}
|
||||
|
||||
quickActions: [
|
||||
StatusFlatRoundButton {
|
||||
id: emojiBtn
|
||||
|
||||
@@ -98,16 +98,15 @@ Page {
|
||||
anchors.fill: parent
|
||||
|
||||
StatusBaseText {
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: 252
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: 252
|
||||
width: Math.min(553, parent.width - 32)
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.verticalCenterOffset: -(headerRow.height/2)
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
visible: contactsModel.count === 0
|
||||
wrapMode: Text.WordWrap
|
||||
font.pixelSize: 15
|
||||
color: Theme.palette.baseColor1
|
||||
text: qsTr("You can only send direct messages to your Contacts.\n
|
||||
Send a contact request to the person you would like to chat with, you will be able to chat with them once they have accepted your contact request.")
|
||||
|
||||
@@ -13,7 +13,8 @@ StatusModal {
|
||||
|
||||
header.title: "Cryptokitties"
|
||||
header.subTitle: "Public Community"
|
||||
header.image.source: "qrc:/demoapp/data/profile-image-1.jpeg"
|
||||
header.asset.isImage: true
|
||||
header.asset.name: "qrc:/demoapp/data/profile-image-1.jpeg"
|
||||
|
||||
contentItem: Column {
|
||||
width: root.width
|
||||
@@ -43,7 +44,7 @@ StatusModal {
|
||||
title: "Share community"
|
||||
subTitle: "https://join.status.im/u/0x04...45f19"
|
||||
tooltip.text: "Copy to clipboard"
|
||||
icon.name: "copy"
|
||||
asset.name: "copy"
|
||||
iconButton.onClicked: tooltip.visible = !tooltip.visible
|
||||
width: parent.width
|
||||
}
|
||||
@@ -57,7 +58,7 @@ StatusModal {
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
statusListItemTitle.font.pixelSize: 17
|
||||
title: "Members"
|
||||
icon.name: "group-chat"
|
||||
asset.name: "group-chat"
|
||||
label: "184"
|
||||
components: [
|
||||
StatusIcon {
|
||||
@@ -72,7 +73,7 @@ StatusModal {
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
statusListItemTitle.font.pixelSize: 17
|
||||
title: "Notifications"
|
||||
icon.name: "notification"
|
||||
asset.name: "notification"
|
||||
components: [
|
||||
StatusSwitch {}
|
||||
]
|
||||
@@ -87,7 +88,7 @@ StatusModal {
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
statusListItemTitle.font.pixelSize: 17
|
||||
title: "Edit community"
|
||||
icon.name: "edit"
|
||||
asset.name: "edit"
|
||||
type: StatusListItem.Type.Secondary
|
||||
}
|
||||
|
||||
@@ -95,7 +96,7 @@ StatusModal {
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
statusListItemTitle.font.pixelSize: 17
|
||||
title: "Transfer ownership"
|
||||
icon.name: "exchange"
|
||||
asset.name: "exchange"
|
||||
type: StatusListItem.Type.Secondary
|
||||
}
|
||||
|
||||
@@ -103,7 +104,7 @@ StatusModal {
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
statusListItemTitle.font.pixelSize: 17
|
||||
title: "Leave community"
|
||||
icon.name: "arrow-left"
|
||||
asset.name: "arrow-left"
|
||||
type: StatusListItem.Type.Secondary
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,10 +10,113 @@ import StatusQ.Core.Theme 0.1
|
||||
|
||||
import "data" 1.0
|
||||
|
||||
StatusAppThreePanelLayout {
|
||||
StatusSectionLayout {
|
||||
id: root
|
||||
property bool createChat: false
|
||||
|
||||
notificationCount: 1
|
||||
onNotificationButtonClicked: { notificationCount = 0; }
|
||||
showHeader: !root.createChat
|
||||
|
||||
headerContent: RowLayout {
|
||||
id: chatHeader
|
||||
|
||||
signal chatInfoButtonClicked()
|
||||
signal menuButtonClicked()
|
||||
signal membersButtonClicked()
|
||||
signal searchButtonClicked()
|
||||
|
||||
StatusChatInfoButton {
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
Layout.alignment: Qt.AlignLeft
|
||||
Layout.leftMargin: padding
|
||||
title: "Amazing Funny Squirrel"
|
||||
subTitle: "Contact"
|
||||
asset.color: Theme.palette.miscColor7
|
||||
type: StatusChatInfoButton.Type.OneToOneChat
|
||||
pinnedMessagesCount: 1
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
id: actionButtons
|
||||
Layout.alignment: Qt.AlignRight
|
||||
Layout.rightMargin: padding
|
||||
spacing: 8
|
||||
|
||||
StatusFlatRoundButton {
|
||||
id: menuButton
|
||||
objectName: "chatToolbarMoreOptionsButton"
|
||||
width: 32
|
||||
height: 32
|
||||
icon.name: "more"
|
||||
type: StatusFlatRoundButton.Type.Secondary
|
||||
|
||||
// initializing the tooltip
|
||||
tooltip.visible: !!tooltip.text && menuButton.hovered && !contextMenu.open
|
||||
tooltip.text: qsTr("More")
|
||||
tooltip.orientation: StatusToolTip.Orientation.Bottom
|
||||
tooltip.y: parent.height + 12
|
||||
|
||||
property bool showMoreMenu: false
|
||||
onClicked: {
|
||||
menuButton.highlighted = true
|
||||
|
||||
let originalOpenHandler = contextMenu.openHandler
|
||||
let originalCloseHandler = contextMenu.closeHandler
|
||||
|
||||
contextMenu.openHandler = function () {
|
||||
if (!!originalOpenHandler) {
|
||||
originalOpenHandler()
|
||||
}
|
||||
}
|
||||
|
||||
contextMenu.closeHandler = function () {
|
||||
menuButton.highlighted = false
|
||||
if (!!originalCloseHandler) {
|
||||
originalCloseHandler()
|
||||
}
|
||||
}
|
||||
|
||||
contextMenu.openHandler = originalOpenHandler
|
||||
contextMenu.popup(-contextMenu.width + menuButton.width, menuButton.height + 4)
|
||||
}
|
||||
StatusPopupMenu {
|
||||
id: contextMenu
|
||||
|
||||
StatusMenuItem {
|
||||
text: "Mute Chat"
|
||||
icon.name: "notification"
|
||||
}
|
||||
StatusMenuItem {
|
||||
text: "Mark as Read"
|
||||
icon.name: "checkmark-circle"
|
||||
}
|
||||
StatusMenuItem {
|
||||
text: "Clear History"
|
||||
icon.name: "close-circle"
|
||||
}
|
||||
|
||||
StatusMenuSeparator {}
|
||||
|
||||
StatusMenuItem {
|
||||
text: "Leave Chat"
|
||||
icon.name: "arrow-left"
|
||||
type: StatusMenuItem.Type.Danger
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
width: 1
|
||||
height: 24
|
||||
color: Theme.palette.directColor7
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
visible: (notificationButton.visible && menuButton.visible)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
leftPanel: Item {
|
||||
anchors.fill: parent
|
||||
anchors.margins: 16
|
||||
@@ -76,7 +179,7 @@ StatusAppThreePanelLayout {
|
||||
topPadding: 8
|
||||
bottomPadding: 8
|
||||
placeholderText: "Search"
|
||||
input.icon.name: "search"
|
||||
input.asset.name: "search"
|
||||
}
|
||||
|
||||
Column {
|
||||
@@ -91,7 +194,7 @@ StatusAppThreePanelLayout {
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
title: "Contact requests"
|
||||
requestsCount: 3
|
||||
sensor.onClicked: demoContactRequestsModal.open()
|
||||
onClicked: demoContactRequestsModal.open()
|
||||
}
|
||||
|
||||
StatusChatList {
|
||||
@@ -166,56 +269,4 @@ StatusAppThreePanelLayout {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
rightPanel: Item {
|
||||
anchors.fill: parent
|
||||
|
||||
StatusChatToolBar {
|
||||
width: parent.width
|
||||
toolbarComponent: statusChatInfoButton
|
||||
searchButton.visible: false
|
||||
membersButton.visible: false
|
||||
notificationCount: 1
|
||||
|
||||
onNotificationButtonClicked: notificationCount = 0
|
||||
|
||||
popupMenu: StatusPopupMenu {
|
||||
id: contextMenu
|
||||
|
||||
StatusMenuItem {
|
||||
text: "Mute Chat"
|
||||
icon.name: "notification"
|
||||
}
|
||||
StatusMenuItem {
|
||||
text: "Mark as Read"
|
||||
icon.name: "checkmark-circle"
|
||||
}
|
||||
StatusMenuItem {
|
||||
text: "Clear History"
|
||||
icon.name: "close-circle"
|
||||
}
|
||||
|
||||
StatusMenuSeparator {}
|
||||
|
||||
StatusMenuItem {
|
||||
text: "Leave Chat"
|
||||
icon.name: "arrow-left"
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,12 +5,12 @@ import QtQuick.Layouts 1.13
|
||||
import StatusQ.Core 0.1
|
||||
import StatusQ.Core.Theme 0.1
|
||||
import StatusQ.Controls 0.1
|
||||
import StatusQ.Layout 0.1
|
||||
import StatusQ.Components 0.1
|
||||
|
||||
import "../demoapp/data" 1.0
|
||||
|
||||
|
||||
StatusScrollView {
|
||||
StatusSectionLayout {
|
||||
id: root
|
||||
|
||||
QtObject {
|
||||
@@ -31,124 +31,127 @@ StatusScrollView {
|
||||
console.info("Clicked community ID: " + communityId)
|
||||
}
|
||||
}
|
||||
centerPanel: Item {
|
||||
anchors.fill: parent
|
||||
clip: true
|
||||
StatusScrollView {
|
||||
anchors.fill: parent
|
||||
contentHeight: column.height + d.layoutVMargin
|
||||
contentWidth: column.width + d.layoutHMargin
|
||||
|
||||
contentHeight: column.height + d.layoutVMargin
|
||||
contentWidth: column.width + d.layoutHMargin
|
||||
clip: true
|
||||
ColumnLayout {
|
||||
id: column
|
||||
spacing: 18
|
||||
|
||||
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 {
|
||||
text: qsTr("Find community")
|
||||
font.weight: Font.Bold
|
||||
font.pixelSize: d.titlePixelSize
|
||||
color: Theme.palette.directColor1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
StatusBaseText {
|
||||
Layout.leftMargin: d.layoutHMargin
|
||||
Layout.topMargin: 20
|
||||
text: qsTr("Featured")
|
||||
font.weight: Font.Bold
|
||||
font.pixelSize: d.subtitlePixelSize
|
||||
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
|
||||
|
||||
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: "👻"}
|
||||
Repeater {
|
||||
model: d.tagsModel
|
||||
delegate: StatusListItemTag {
|
||||
border.color: Theme.palette.baseColor2
|
||||
color: "transparent"
|
||||
height: 32
|
||||
radius: 36
|
||||
closeButtonVisible: false
|
||||
asset.emoji: model.emoji
|
||||
asset.height: 32
|
||||
asset.width: asset.height
|
||||
asset.color: "transparent"
|
||||
asset.isLetterIdenticon: true
|
||||
title: model.name
|
||||
titleText.font.pixelSize: 15
|
||||
titleText.color: Theme.palette.primaryColor1
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
StatusBaseText {
|
||||
Layout.leftMargin: d.layoutHMargin
|
||||
Layout.topMargin: 20
|
||||
text: qsTr("Featured")
|
||||
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
|
||||
GridLayout {
|
||||
id: featuredGrid
|
||||
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
|
||||
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) }
|
||||
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) }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import QtQuick 2.12
|
||||
import QtQuick.Controls 2.14
|
||||
import QtQuick.Layouts 1.12
|
||||
|
||||
import StatusQ.Core 0.1
|
||||
import StatusQ.Popups 0.1
|
||||
@@ -10,7 +11,7 @@ import StatusQ.Core.Theme 0.1
|
||||
|
||||
import "data" 1.0
|
||||
|
||||
StatusAppThreePanelLayout {
|
||||
StatusSectionLayout {
|
||||
id: root
|
||||
|
||||
property string communityDetailModalTitle: ""
|
||||
@@ -22,6 +23,101 @@ StatusAppThreePanelLayout {
|
||||
color: SplitHandle.pressed ? Theme.palette.baseColor2
|
||||
: (SplitHandle.hovered ? Qt.darker(Theme.palette.baseColor5, 1.1) : "transparent")
|
||||
}
|
||||
|
||||
headerContent: RowLayout {
|
||||
id: statusToolBar
|
||||
|
||||
StatusFlatRoundButton {
|
||||
id: searchButton
|
||||
Layout.alignment: Qt.AlignLeft
|
||||
Layout.leftMargin: padding
|
||||
icon.name: "search"
|
||||
type: StatusFlatRoundButton.Type.Secondary
|
||||
// initializing the tooltip
|
||||
tooltip.text: qsTr("Search")
|
||||
tooltip.orientation: StatusToolTip.Orientation.Bottom
|
||||
tooltip.y: parent.height + 12
|
||||
onClicked: {
|
||||
searchButton.highlighted = !searchButton.highlighted;
|
||||
searchPopup.setSearchSelection(communityDetailModalTitle,
|
||||
"",
|
||||
communityDetailModalImage);
|
||||
searchPopup.open();
|
||||
}
|
||||
}
|
||||
|
||||
StatusChatInfoButton {
|
||||
Layout.preferredWidth: Math.min(implicitWidth, parent.width)
|
||||
Layout.fillHeight: true
|
||||
title: "general"
|
||||
subTitle: "Community Chat"
|
||||
asset.color: Theme.palette.miscColor6
|
||||
type: StatusChatInfoButton.Type.CommunityChat
|
||||
}
|
||||
|
||||
Item {
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
|
||||
StatusFlatRoundButton {
|
||||
id: membersButton
|
||||
icon.name: "group-chat"
|
||||
type: StatusFlatRoundButton.Type.Secondary
|
||||
// initializing the tooltip
|
||||
tooltip.text: qsTr("Members")
|
||||
tooltip.orientation: StatusToolTip.Orientation.Bottom
|
||||
tooltip.y: parent.height + 12
|
||||
onClicked: {
|
||||
membersButton.highlighted = !membersButton.highlighted;
|
||||
root.showRightPanel = !root.showRightPanel;
|
||||
}
|
||||
}
|
||||
|
||||
StatusSearchPopup {
|
||||
id: searchPopup
|
||||
searchOptionsPopupMenu: searchPopupMenu
|
||||
onAboutToHide: {
|
||||
if (searchPopupMenu.visible) {
|
||||
searchPopupMenu.close();
|
||||
}
|
||||
//clear menu
|
||||
for (var i = 2; i < searchPopupMenu.count; i++) {
|
||||
searchPopupMenu.removeItem(searchPopupMenu.takeItem(i));
|
||||
}
|
||||
}
|
||||
onClosed: {
|
||||
statusToolBar.searchButton.highlighted = false
|
||||
searchPopupMenu.dismiss();
|
||||
}
|
||||
onSearchTextChanged: {
|
||||
if (searchPopup.searchText !== "") {
|
||||
searchPopup.loading = true;
|
||||
searchModelSimTimer.start();
|
||||
} else {
|
||||
searchPopup.searchResults = [];
|
||||
searchModelSimTimer.stop();
|
||||
}
|
||||
}
|
||||
Timer {
|
||||
id: searchModelSimTimer
|
||||
interval: 500
|
||||
onTriggered: {
|
||||
if (searchPopup.searchText.startsWith("c")) {
|
||||
searchPopup.searchResults = Models.searchResultsA;
|
||||
} else {
|
||||
searchPopup.searchResults = Models.searchResultsB;
|
||||
}
|
||||
searchPopup.loading = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
StatusSearchLocationMenu {
|
||||
id: searchPopupMenu
|
||||
searchPopup: searchPopup
|
||||
locationModel: Models.optionsModel
|
||||
}
|
||||
}
|
||||
|
||||
leftPanel: Item {
|
||||
id: leftPanel
|
||||
|
||||
@@ -33,8 +129,9 @@ StatusAppThreePanelLayout {
|
||||
|
||||
chatInfoButton.title: "CryptoKitties"
|
||||
chatInfoButton.subTitle: "128 Members"
|
||||
chatInfoButton.image.source: "qrc:/demoapp/data/profile-image-1.jpeg"
|
||||
chatInfoButton.icon.color: Theme.palette.miscColor6
|
||||
chatInfoButton.asset.isImage: true
|
||||
chatInfoButton.asset.name: "qrc:/demoapp/data/profile-image-1.jpeg"
|
||||
chatInfoButton.asset.color: Theme.palette.miscColor6
|
||||
chatInfoButton.onClicked: { chatInfoButtonClicked(); }
|
||||
|
||||
popupMenu: StatusPopupMenu {
|
||||
@@ -164,79 +261,11 @@ StatusAppThreePanelLayout {
|
||||
}
|
||||
|
||||
centerPanel: Item {
|
||||
StatusChatToolBar {
|
||||
id: statusChatToolBar
|
||||
|
||||
width: parent.width
|
||||
toolbarComponent: statusChatInfoButton
|
||||
|
||||
onSearchButtonClicked: {
|
||||
searchButton.highlighted = !searchButton.highlighted;
|
||||
searchPopup.setSearchSelection(communityDetailModalTitle,
|
||||
"",
|
||||
communityDetailModalImage);
|
||||
searchPopup.open();
|
||||
}
|
||||
membersButton.onClicked: membersButton.highlighted = !membersButton.highlighted
|
||||
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 {
|
||||
id: searchPopup
|
||||
searchOptionsPopupMenu: searchPopupMenu
|
||||
onAboutToHide: {
|
||||
if (searchPopupMenu.visible) {
|
||||
searchPopupMenu.close();
|
||||
}
|
||||
//clear menu
|
||||
for (var i = 2; i < searchPopupMenu.count; i++) {
|
||||
searchPopupMenu.removeItem(searchPopupMenu.takeItem(i));
|
||||
}
|
||||
}
|
||||
onClosed: {
|
||||
statusChatToolBar.searchButton.highlighted = false
|
||||
searchPopupMenu.dismiss();
|
||||
}
|
||||
onSearchTextChanged: {
|
||||
if (searchPopup.searchText !== "") {
|
||||
searchPopup.loading = true;
|
||||
searchModelSimTimer.start();
|
||||
} else {
|
||||
searchPopup.searchResults = [];
|
||||
searchModelSimTimer.stop();
|
||||
}
|
||||
}
|
||||
Timer {
|
||||
id: searchModelSimTimer
|
||||
interval: 500
|
||||
onTriggered: {
|
||||
if (searchPopup.searchText.startsWith("c")) {
|
||||
searchPopup.searchResults = Models.searchResultsA;
|
||||
} else {
|
||||
searchPopup.searchResults = Models.searchResultsB;
|
||||
}
|
||||
searchPopup.loading = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
StatusSearchLocationMenu {
|
||||
id: searchPopupMenu
|
||||
searchPopup: searchPopup
|
||||
locationModel: Models.optionsModel
|
||||
anchors.fill: parent
|
||||
StatusBaseText {
|
||||
anchors.centerIn: parent
|
||||
font.pixelSize: 15
|
||||
text: qsTr("Community content here")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -273,8 +302,10 @@ StatusAppThreePanelLayout {
|
||||
isVerified: model.isVerified
|
||||
isUntrustworthy: model.isUntrustworthy
|
||||
isContact: model.isContact
|
||||
image.source: model.icon
|
||||
image.isIdenticon: false
|
||||
asset.name: model.icon
|
||||
asset.isImage: (asset.name !== "")
|
||||
asset.isLetterIdenticon: (asset.name === "")
|
||||
asset.imgIsIdenticon: false
|
||||
status: model.onlineStatus
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ import StatusQ.Core.Theme 0.1
|
||||
|
||||
import "data" 1.0
|
||||
|
||||
StatusAppTwoPanelLayout {
|
||||
StatusSectionLayout {
|
||||
id: root
|
||||
|
||||
leftPanel: Item {
|
||||
@@ -41,7 +41,7 @@ StatusAppTwoPanelLayout {
|
||||
model: Models.demoProfileGeneralMenuItems
|
||||
delegate: StatusNavigationListItem {
|
||||
title: model.title
|
||||
icon.name: model.icon
|
||||
asset.name: model.icon
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,7 +51,7 @@ StatusAppTwoPanelLayout {
|
||||
model: Models.demoProfileSettingsMenuItems
|
||||
delegate: StatusNavigationListItem {
|
||||
title: model.title
|
||||
icon.name: model.icon
|
||||
asset.name: model.icon
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,7 +65,7 @@ StatusAppTwoPanelLayout {
|
||||
model: Models.demoProfileOtherMenuItems
|
||||
delegate: StatusNavigationListItem {
|
||||
title: model.title
|
||||
icon.name: model.icon
|
||||
asset.name: model.icon
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+420
-183
File diff suppressed because one or more lines are too long
@@ -35,7 +35,7 @@ ColumnLayout {
|
||||
id: searchInput
|
||||
|
||||
Layout.fillWidth: true
|
||||
input.icon.name: "search"
|
||||
input.asset.name: "search"
|
||||
placeholderText: "nickname.."
|
||||
}
|
||||
|
||||
@@ -43,7 +43,7 @@ ColumnLayout {
|
||||
id: contactBtn
|
||||
|
||||
icon.name: "tiny/tiny-contact"
|
||||
identicon.icon.color: Theme.palette.primaryColor1
|
||||
identicon.asset.color: Theme.palette.primaryColor1
|
||||
onClicked: highlighted = !highlighted
|
||||
}
|
||||
|
||||
@@ -51,7 +51,7 @@ ColumnLayout {
|
||||
id: verifiedBtn
|
||||
|
||||
icon.name: "tiny/tiny-checkmark"
|
||||
identicon.icon.color: Theme.palette.primaryColor1
|
||||
identicon.asset.color: Theme.palette.primaryColor1
|
||||
onClicked: highlighted = !highlighted
|
||||
}
|
||||
}
|
||||
@@ -94,6 +94,7 @@ ColumnLayout {
|
||||
nickName: model.nick
|
||||
isVerified: model.isVerified
|
||||
isContact: model.isContact
|
||||
asset.isLetterIdenticon: true
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+47
-29
@@ -63,11 +63,11 @@ StatusWindow {
|
||||
}
|
||||
}
|
||||
|
||||
StatusAppLayout {
|
||||
StatusMainLayout {
|
||||
id: appLayout
|
||||
anchors.fill: parent
|
||||
|
||||
appNavBar: StatusAppNavBar {
|
||||
leftPanel: StatusAppNavBar {
|
||||
height: rootWindow.height
|
||||
|
||||
communityTypeRole: "sectionType"
|
||||
@@ -105,30 +105,34 @@ StatusWindow {
|
||||
}
|
||||
}
|
||||
|
||||
appView: StackView {
|
||||
id: stackView
|
||||
rightPanel: Item {
|
||||
anchors.fill: parent
|
||||
initialItem: libraryDocumentationCmp
|
||||
}
|
||||
|
||||
ThemeSwitch {
|
||||
anchors.top: parent.top
|
||||
anchors.topMargin: 32
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: 32
|
||||
lightThemeEnabled: storeSettings.lightTheme
|
||||
onLightThemeEnabledChanged: {
|
||||
Theme.palette = lightThemeEnabled ? rootWindow.darkTheme : rootWindow.lightTheme
|
||||
storeSettings.lightTheme = lightThemeEnabled
|
||||
StackView {
|
||||
id: stackView
|
||||
anchors.fill: parent
|
||||
initialItem: libraryDocumentationCmp
|
||||
}
|
||||
ThemeSwitch {
|
||||
anchors.top: parent.top
|
||||
anchors.topMargin: 32
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: 32
|
||||
lightThemeEnabled: storeSettings.lightTheme
|
||||
onLightThemeEnabledChanged: {
|
||||
Theme.palette = lightThemeEnabled ? rootWindow.darkTheme : rootWindow.lightTheme
|
||||
storeSettings.lightTheme = lightThemeEnabled
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Component {
|
||||
id: libraryDocumentationCmp
|
||||
|
||||
StatusAppTwoPanelLayout {
|
||||
StatusSectionLayout {
|
||||
id: mainPageView
|
||||
showHeader: false
|
||||
|
||||
function page(name, fillPage) {
|
||||
storeSettings.fillPage = fillPage ? true : false
|
||||
@@ -298,6 +302,16 @@ StatusWindow {
|
||||
selected: viewLoader.source.toString().includes(title)
|
||||
onClicked: mainPageView.page(title);
|
||||
}
|
||||
StatusNavigationListItem {
|
||||
title: "StatusItemSelector"
|
||||
selected: viewLoader.source.toString().includes(title)
|
||||
onClicked: mainPageView.page(title, true);
|
||||
}
|
||||
StatusNavigationListItem {
|
||||
title: "StatusChartPanel"
|
||||
selected: viewLoader.source.toString().includes(title)
|
||||
onClicked: mainPageView.page(title, true);
|
||||
}
|
||||
StatusListSectionHeadline { text: "StatusQ.Popup" }
|
||||
StatusNavigationListItem {
|
||||
title: "StatusPopupMenu"
|
||||
@@ -343,8 +357,8 @@ StatusWindow {
|
||||
}
|
||||
}
|
||||
|
||||
rightPanel: Item {
|
||||
id: rightPanel
|
||||
centerPanel: Item {
|
||||
id: centerPanel
|
||||
anchors.fill: parent
|
||||
|
||||
StatusScrollView {
|
||||
@@ -357,7 +371,7 @@ StatusWindow {
|
||||
|
||||
Item {
|
||||
id: pageWrapper
|
||||
width: rightPanel.width
|
||||
width: centerPanel.width
|
||||
anchors.top: parent.top
|
||||
height: Math.max(rootWindow.height, viewLoader.height + 128)
|
||||
scale: rootWindow.factor
|
||||
@@ -415,8 +429,9 @@ StatusWindow {
|
||||
Component {
|
||||
id: examplesCmp
|
||||
|
||||
StatusAppTwoPanelLayout {
|
||||
StatusSectionLayout {
|
||||
id: examplesView
|
||||
showHeader: false
|
||||
|
||||
function example(name) {
|
||||
examplesLoader.source = Qt.resolvedUrl("./examples/" + name + ".qml")
|
||||
@@ -444,16 +459,19 @@ StatusWindow {
|
||||
}
|
||||
}
|
||||
|
||||
rightPanel: StatusScrollView {
|
||||
id: examplesRightPanel
|
||||
centerPanel: Item {
|
||||
anchors.fill: parent
|
||||
anchors.margins: 64
|
||||
anchors.topMargin: anchors.margins + 32
|
||||
StatusScrollView {
|
||||
id: examplesCenterPanel
|
||||
anchors.fill: parent
|
||||
anchors.margins: 64
|
||||
anchors.topMargin: anchors.margins + 32
|
||||
|
||||
Loader {
|
||||
id: examplesLoader
|
||||
width: examplesRightPanel.availableWidth
|
||||
source: storeSettings.selectedExample !== "" ? storeSettings.selectedExample : examplesView.defaultExampleSource
|
||||
Loader {
|
||||
id: examplesLoader
|
||||
width: examplesCenterPanel.availableWidth
|
||||
source: storeSettings.selectedExample !== "" ? storeSettings.selectedExample : examplesView.defaultExampleSource
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,193 @@
|
||||
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 {
|
||||
|
||||
QtObject {
|
||||
id: d
|
||||
//dummy data
|
||||
property real stepSize: 1000
|
||||
property real minStep: 12000
|
||||
property real maxStep: 22000
|
||||
|
||||
property var graphTabsModel: [{text: "Price", enabled: true}, {text: "Balance", enabled: false}]
|
||||
property var timeRangeTabsModel: [{text: "1H", enabled: true},
|
||||
{text: "1D", enabled: true},{text: "7D", enabled: true},
|
||||
{text: "1M", enabled: true}, {text: "6M", enabled: true},
|
||||
{text: "1Y", enabled: true}, {text: "ALL", enabled: true}]
|
||||
|
||||
property var simTimer: Timer {
|
||||
running: true
|
||||
interval: 3000
|
||||
repeat: true
|
||||
onTriggered: {
|
||||
d.generateData();
|
||||
}
|
||||
}
|
||||
|
||||
function minutes(minutes = 0) {
|
||||
var newMinute = new Date(new Date().getTime() - (minutes * 60 * 1000)).toString();
|
||||
if (newMinute.slice(10,12) === "00") {
|
||||
var dateToday = new Date(Date.now()).toString();
|
||||
return dateToday.slice(4,7) + " " + dateToday.slice(8,10);
|
||||
}
|
||||
return newMinute.slice(10,16);
|
||||
}
|
||||
|
||||
function hour(hours = 0) {
|
||||
var newHour = new Date(new Date().getTime() - (hours * 60 * 60 * 1000)).toString();
|
||||
if (newHour.slice(10,12) === "00") {
|
||||
var dateToday = new Date(Date.now()).toString();
|
||||
return dateToday.slice(4,7) + " " + dateToday.slice(8,10);
|
||||
}
|
||||
return newHour.slice(10,16);
|
||||
}
|
||||
|
||||
function day(before = 0) {
|
||||
var newDay = new Date(Date.now() - before * 24 * 60 * 60 * 1000).toString();
|
||||
return newDay.slice(4,7) + " " + newDay.slice(8,10);
|
||||
}
|
||||
|
||||
function month(before = 0) {
|
||||
var newMonth = new Date(Date.now() - before * 24 * 60 * 60 * 1000).toString();
|
||||
return newMonth.slice(4,7) + " '" + newMonth.slice(newMonth.indexOf("G")-3, newMonth.indexOf("G")-1);
|
||||
}
|
||||
|
||||
property var timeRange: [
|
||||
{'1H': [minutes(60), minutes(55), minutes(50), minutes(45), minutes(40), minutes(35), minutes(30), minutes(25), minutes(20), minutes(15), minutes(10), minutes(5), minutes()]},
|
||||
{'1D': [hour(24), hour(23), hour(22), hour(21), hour(20), hour(19), hour(18), hour(17), hour(16), hour(15), hour(14), hour(13),
|
||||
hour(12), hour(11), hour(10), hour(9), hour(8), hour(7), hour(6), hour(5), hour(4), hour(3), hour(2), hour(1), hour()]},
|
||||
{'7D': [day(6), day(5), day(4), day(3), day(2), day(1), day()]},
|
||||
{'1M': [day(30), day(28), day(26), day(24), day(22), day(20), day(18), day(16), day(14), day(12), day(10), day(8), day(6), day(4), day()]},
|
||||
{'6M': [month(150), month(120), month(90), month(60), month(30), month()]},
|
||||
{'1Y': [month(330), month(300), month(270), month(240), month(210), month(180), month(150), month(120), month(90), month(60), month(30), month()]},
|
||||
{'ALL': ['2016', '2017', '2018', '2019', '2020', '2021', '2022']}
|
||||
]
|
||||
|
||||
function generateData() {
|
||||
var result = [];
|
||||
for (var i = 0; i < timeRange[graphDetail.timeRangeTabBarIndex][graphDetail.selectedTimeRange].length; ++i) {
|
||||
result[i] = Math.random() * (maxStep - minStep) + minStep;
|
||||
}
|
||||
graphDetail.chart.chartData.datasets[0].data = result;
|
||||
graphDetail.chart.animateToNewData();
|
||||
}
|
||||
}
|
||||
|
||||
StatusChartPanel {
|
||||
id: graphDetail
|
||||
height: 290
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: 24
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: 24
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
graphsModel: d.graphTabsModel
|
||||
timeRangeModel: d.timeRangeTabsModel
|
||||
onHeaderTabClicked: {
|
||||
//TODO
|
||||
//if time range tab
|
||||
d.generateData();
|
||||
//if graph bar
|
||||
//switch graph
|
||||
}
|
||||
chart.chartType: 'line'
|
||||
chart.chartData: {
|
||||
return {
|
||||
labels: d.timeRange[graphDetail.timeRangeTabBarIndex][graphDetail.selectedTimeRange],
|
||||
datasets: [{
|
||||
label: 'Price',
|
||||
xAxisId: 'x-axis-1',
|
||||
yAxisId: 'y-axis-1',
|
||||
backgroundColor: (Theme.palette.name === "dark") ? 'rgba(136, 176, 255, 0.2)' : 'rgba(67, 96, 223, 0.2)',
|
||||
borderColor: (Theme.palette.name === "dark") ? 'rgba(136, 176, 255, 1)' : 'rgba(67, 96, 223, 1)',
|
||||
borderWidth: 3,
|
||||
pointRadius: 0,
|
||||
//data: d.generateData()
|
||||
}]
|
||||
}
|
||||
}
|
||||
|
||||
chart.chartOptions: {
|
||||
return {
|
||||
maintainAspectRatio: false,
|
||||
responsive: true,
|
||||
legend: {
|
||||
display: false
|
||||
},
|
||||
//TODO enable zoom
|
||||
// zoom: {
|
||||
// enabled: true,
|
||||
// drag: true,
|
||||
// speed: 0.1,
|
||||
// threshold: 2
|
||||
// },
|
||||
// pan:{enabled:true,mode:'x'},
|
||||
tooltips: {
|
||||
intersect: false,
|
||||
displayColors: false,
|
||||
callbacks: {
|
||||
footer: function(tooltipItem, data) { return 'Vol: $43,042,678,876'; },
|
||||
label: function(tooltipItem, data) {
|
||||
let label = data.datasets[tooltipItem.datasetIndex].label || '';
|
||||
if (label) {
|
||||
label += ': ';
|
||||
}
|
||||
label += tooltipItem.yLabel.toFixed(2);
|
||||
return label.slice(0,label.indexOf(":")+1)+ " $"+label.slice(label.indexOf(":")+2, label.length);
|
||||
}
|
||||
}
|
||||
},
|
||||
scales: {
|
||||
xAxes: [{
|
||||
id: 'x-axis-1',
|
||||
position: 'bottom',
|
||||
gridLines: {
|
||||
drawOnChartArea: false,
|
||||
drawBorder: false,
|
||||
drawTicks: false,
|
||||
},
|
||||
ticks: {
|
||||
fontSize: 10,
|
||||
fontColor: (Theme.palette.name === "dark") ? '#909090' : '#939BA1',
|
||||
padding: 16
|
||||
}
|
||||
}],
|
||||
yAxes: [{
|
||||
position: 'left',
|
||||
id: 'y-axis-1',
|
||||
gridLines: {
|
||||
borderDash: [8, 4],
|
||||
drawBorder: false,
|
||||
drawTicks: false,
|
||||
color: (Theme.palette.name === "dark") ? '#909090' : '#939BA1'
|
||||
},
|
||||
beforeDataLimits: (axis) => {
|
||||
axis.paddingTop = 25;
|
||||
axis.paddingBottom = 0;
|
||||
},
|
||||
ticks: {
|
||||
fontSize: 10,
|
||||
fontColor: (Theme.palette.name === "dark") ? '#909090' : '#939BA1',
|
||||
padding: 8,
|
||||
min: d.minStep,
|
||||
max: d.maxStep,
|
||||
stepSize: d.stepSize,
|
||||
callback: function(value, index, ticks) {
|
||||
return '$' + value;
|
||||
},
|
||||
}
|
||||
}]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -14,8 +14,9 @@ GridLayout {
|
||||
StatusChatInfoToolBar {
|
||||
chatInfoButton.title: "Cryptokitties"
|
||||
chatInfoButton.subTitle: "128 Members"
|
||||
chatInfoButton.image.source: "qrc:/demoapp/data/profile-image-1.jpeg"
|
||||
chatInfoButton.icon.color: Theme.palette.miscColor6
|
||||
chatInfoButton.asset.isImage: true
|
||||
chatInfoButton.asset.name: "qrc:/demoapp/data/profile-image-1.jpeg"
|
||||
chatInfoButton.asset.color: Theme.palette.miscColor6
|
||||
|
||||
popupMenu: StatusPopupMenu {
|
||||
|
||||
|
||||
@@ -36,7 +36,7 @@ Item {
|
||||
leftPadding: 0
|
||||
rightPadding: 0
|
||||
label: qsTr("Select tags that will fit your Community")
|
||||
input.icon.name: "search"
|
||||
input.asset.name: "search"
|
||||
placeholderText: qsTr("Search tags")
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ Column {
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
|
||||
expandable: false
|
||||
icon.name: "seed-phrase"
|
||||
asset.name: "seed-phrase"
|
||||
primaryText: "Back up seed phrase"
|
||||
secondaryText: "Back up your seed phrase now to secure this account ajhaDH SDHSAHDLSADBSA,DLISAHDLASD ADASDHASLDHALSDHAS DAS,DASJDGLIASGD"
|
||||
button.text: qsTr("Back up seed phrase")
|
||||
@@ -36,7 +36,7 @@ Column {
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
|
||||
expandable: true
|
||||
icon.name: "secret"
|
||||
asset.name: "secret"
|
||||
primaryText: "Account signing phrase"
|
||||
secondaryText: "View your signing phrase and ensure that you never get scammed. View your signing phrase and ensure that you never get scammed."
|
||||
expandableComponent: notImplemented
|
||||
@@ -46,7 +46,7 @@ Column {
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
|
||||
expandable: true
|
||||
icon.name: "seed-phrase"
|
||||
asset.name: "seed-phrase"
|
||||
primaryText: "View private key"
|
||||
secondaryText: "Back up your seed phrase now to secure this account"
|
||||
expandableComponent: notImplemented
|
||||
@@ -74,7 +74,8 @@ Column {
|
||||
|
||||
type: StatusExpandableItem.Type.Secondary
|
||||
expandable: true
|
||||
image.source: "qrc:/demoapp/data/profile-image-1.jpeg"
|
||||
asset.isImage: true
|
||||
asset.name: "qrc:/demoapp/data/profile-image-1.jpeg"
|
||||
primaryText: "CryptoKitties"
|
||||
additionalText: "1456 USD"
|
||||
expandableComponent: notImplemented
|
||||
@@ -85,7 +86,8 @@ Column {
|
||||
|
||||
type: StatusExpandableItem.Type.Secondary
|
||||
expandable: true
|
||||
image.source: "qrc:/demoapp/data/profile-image-1.jpeg"
|
||||
asset.isImage: true
|
||||
asset.name: "qrc:/demoapp/data/profile-image-1.jpeg"
|
||||
primaryText: "Adding Really long text to test scenario of having very long text along with tertiary text"
|
||||
additionalText: "564.90 USD"
|
||||
expandableComponent: notImplemented
|
||||
|
||||
@@ -33,9 +33,8 @@ Column {
|
||||
|
||||
StatusInput {
|
||||
label: "Label"
|
||||
|
||||
input.icon.name: "search"
|
||||
placeholderText: "Input with icon"
|
||||
input.asset.name: "search"
|
||||
input.placeholderText: "Input with icon"
|
||||
}
|
||||
|
||||
StatusInput {
|
||||
@@ -57,6 +56,15 @@ Column {
|
||||
input.clearable: true
|
||||
}
|
||||
|
||||
StatusPasswordInput {
|
||||
placeholderText: "Password"
|
||||
}
|
||||
|
||||
StatusPasswordInput {
|
||||
signingPhrase: "orange hello cygnet"
|
||||
placeholderText: "Password"
|
||||
}
|
||||
|
||||
Item {
|
||||
implicitWidth: 480
|
||||
implicitHeight: 82
|
||||
@@ -112,9 +120,9 @@ Column {
|
||||
StatusInput {
|
||||
label: "StatusInput"
|
||||
secondaryLabel: "with right icon"
|
||||
input.icon.width: 15
|
||||
input.icon.height: 11
|
||||
input.icon.name: text !== "" ? "checkmark" : ""
|
||||
input.asset.width: 15
|
||||
input.asset.height: 11
|
||||
input.asset.name: text !== "" ? "checkmark" : ""
|
||||
input.leftIcon: false
|
||||
}
|
||||
|
||||
@@ -192,9 +200,9 @@ Column {
|
||||
StatusInput {
|
||||
property bool toggled: true
|
||||
label: "Input with emoji icon"
|
||||
placeholderText: "Enter Name"
|
||||
input.icon.emoji: toggled ? "😁" : "🧸"
|
||||
input.icon.color: "blue"
|
||||
input.placeholderText: "Enter Name"
|
||||
input.asset.emoji: toggled ? "😁" : "🧸"
|
||||
input.asset.color: "blue"
|
||||
input.isIconSelectable: true
|
||||
onIconClicked: {
|
||||
toggled = !toggled
|
||||
@@ -204,10 +212,10 @@ Column {
|
||||
StatusInput {
|
||||
property bool toggled: true
|
||||
label: "Input with selectable icon which is not an emoji"
|
||||
placeholderText: "Enter Name"
|
||||
input.icon.emoji: ""
|
||||
input.icon.name: toggled ? "filled-account" : "image"
|
||||
input.icon.color: "blue"
|
||||
input.placeholderText: "Enter Name"
|
||||
input.asset.emoji: ""
|
||||
input.asset.name: toggled ? "filled-account" : "image"
|
||||
input.asset.color: "blue"
|
||||
input.isIconSelectable: true
|
||||
onIconClicked: {
|
||||
toggled = !toggled
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import QtQuick 2.0
|
||||
import QtQuick 2.14
|
||||
import QtQuick.Layouts 1.14
|
||||
|
||||
import StatusQ.Components 0.1
|
||||
@@ -15,25 +15,44 @@ ColumnLayout {
|
||||
defaultItemText: "Example: Empty items"
|
||||
andOperatorText: "and"
|
||||
orOperatorText: "or"
|
||||
popupItem: StatusDropdown {
|
||||
|
||||
itemsModel: ListModel {
|
||||
id: model
|
||||
}
|
||||
|
||||
StatusDropdown {
|
||||
id: dropdown
|
||||
|
||||
parent: selector.addButton
|
||||
width: 200
|
||||
contentItem: ColumnLayout {
|
||||
spacing: 10
|
||||
StatusInput {
|
||||
id: input
|
||||
text: "Sample"
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
StatusButton {
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
text: "Add element"
|
||||
onClicked: {
|
||||
selector.addItem(input.text, "qrc:/images/SNT.png", selector.itemsModel.count > 0 ? Utils.Operators.Or : Utils.Operators.None)
|
||||
model.append({
|
||||
text: input.text,
|
||||
imageSource: "qrc:/images/SNT.png",
|
||||
operator: model.count > 0 ? Utils.Operators.Or : Utils.Operators.None
|
||||
})
|
||||
|
||||
dropdown.close()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
addButton.onClicked: {
|
||||
dropdown.x = mouse.x
|
||||
dropdown.y = mouse.y
|
||||
dropdown.open()
|
||||
}
|
||||
}
|
||||
|
||||
StatusButton {
|
||||
|
||||
@@ -72,4 +72,73 @@ Column {
|
||||
text: "Introduced PIN: " + regexPinInput.pinInput
|
||||
font.pixelSize: 12
|
||||
}
|
||||
|
||||
// PUK input that accepts only numbers
|
||||
StatusBaseText {
|
||||
topPadding: 100
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
color: Theme.palette.directColor1
|
||||
text: "Enter Keycard PUK"
|
||||
font.pixelSize: 30
|
||||
font.bold: true
|
||||
}
|
||||
|
||||
StatusPinInput {
|
||||
id: numbersPukInput
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
validator: StatusRegularExpressionValidator { regularExpression: /[0-9]+/ }
|
||||
pinLen: 12
|
||||
}
|
||||
|
||||
StatusBaseText {
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
color: Theme.palette.dangerColor1
|
||||
text: "Only numbers allowed"
|
||||
font.pixelSize: 16
|
||||
}
|
||||
|
||||
StatusBaseText {
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
color: Theme.palette.directColor1
|
||||
text: "Introduced PUK: " + numbersPukInput.pinInput
|
||||
font.pixelSize: 12
|
||||
}
|
||||
|
||||
// PUK input that accepts only numbers
|
||||
StatusBaseText {
|
||||
topPadding: 100
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
color: Theme.palette.directColor1
|
||||
text: "Enter Keycard PUK"
|
||||
font.pixelSize: 30
|
||||
font.bold: true
|
||||
}
|
||||
|
||||
StatusPinInput {
|
||||
id: numbersPukInputWithSpacing
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
validator: StatusRegularExpressionValidator { regularExpression: /[0-9]+/ }
|
||||
pinLen: 12
|
||||
additionalSpacing: 32
|
||||
additionalSpacingOnEveryNItems: 4
|
||||
|
||||
Component.onCompleted: {
|
||||
numbersPukInputWithSpacing.statesInitialization()
|
||||
numbersPukInputWithSpacing.forceFocus()
|
||||
}
|
||||
}
|
||||
|
||||
StatusBaseText {
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
color: Theme.palette.dangerColor1
|
||||
text: "Only numbers allowed"
|
||||
font.pixelSize: 16
|
||||
}
|
||||
|
||||
StatusBaseText {
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
color: Theme.palette.directColor1
|
||||
text: "Introduced PUK: " + numbersPukInputWithSpacing.pinInput
|
||||
font.pixelSize: 12
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,30 +55,30 @@ GridLayout {
|
||||
|
||||
StatusMenuItem {
|
||||
text: "One"
|
||||
iconSettings.name: "info"
|
||||
assetSettings.name: "info"
|
||||
}
|
||||
|
||||
StatusMenuSeparator {}
|
||||
|
||||
StatusMenuItem {
|
||||
text: "Two"
|
||||
iconSettings.name: "info"
|
||||
assetSettings.name: "info"
|
||||
}
|
||||
|
||||
StatusMenuItem {
|
||||
text: "Three"
|
||||
iconSettings.name: "info"
|
||||
assetSettings.name: "info"
|
||||
}
|
||||
|
||||
StatusPopupMenu {
|
||||
title: "Four"
|
||||
StatusMenuItem {
|
||||
text: "One"
|
||||
iconSettings.name: "info"
|
||||
assetSettings.name: "info"
|
||||
}
|
||||
StatusMenuItem {
|
||||
text: "Three"
|
||||
iconSettings.name: "info"
|
||||
assetSettings.name: "info"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -108,14 +108,16 @@ GridLayout {
|
||||
|
||||
StatusMenuItem {
|
||||
text: "vitalik.eth"
|
||||
image.source: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAlklEQVR4nOzW0QmDQBAG4SSkl7SUQlJGCrElq9F3QdjjVhh/5nv3cFhY9vUIYQiNITSG0Bh
|
||||
assetSettings.isImage: true
|
||||
assetSettings.name: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAlklEQVR4nOzW0QmDQBAG4SSkl7SUQlJGCrElq9F3QdjjVhh/5nv3cFhY9vUIYQiNITSG0Bh
|
||||
CExPynn1gWf9bx498P7/nzPcxEzGExhBdJGYihtAYQlO+tUZvqrPbqeudo5iJGEJjCE15a3VtodH3q2ImYgiNITTlTdG1nUZ5a92VITQxITFiJmIIjSE0htAYQrMHAAD//+wwFVpz+yqXAAAAAElFTkSuQmCC"
|
||||
image.isIdenticon: true
|
||||
assetSettings.imgIsIdenticon: true
|
||||
}
|
||||
|
||||
StatusMenuItem {
|
||||
text: "Pascal"
|
||||
image.source: "qrc:/demoapp/data/profile-image-1.jpeg"
|
||||
assetSettings.isImage: true
|
||||
assetSettings.name: "qrc:/demoapp/data/profile-image-1.jpeg"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -124,21 +126,21 @@ CExPynn1gWf9bx498P7/nzPcxEzGExhBdJGYihtAYQlO+tUZvqrPbqeudo5iJGEJjCE15a3VtodH3q2I
|
||||
|
||||
StatusMenuItem {
|
||||
text: "welcome"
|
||||
iconSettings.name: "channel"
|
||||
iconSettings.color: Theme.palette.directColor1
|
||||
assetSettings.name: "channel"
|
||||
assetSettings.color: Theme.palette.directColor1
|
||||
}
|
||||
StatusMenuItem {
|
||||
text: "support"
|
||||
iconSettings.name: "channel"
|
||||
iconSettings.color: Theme.palette.directColor1
|
||||
assetSettings.name: "channel"
|
||||
assetSettings.color: Theme.palette.directColor1
|
||||
}
|
||||
|
||||
StatusMenuHeadline { text: "Public" }
|
||||
|
||||
StatusMenuItem {
|
||||
text: "news"
|
||||
iconSettings.name: "channel"
|
||||
iconSettings.color: Theme.palette.directColor1
|
||||
assetSettings.name: "channel"
|
||||
assetSettings.color: Theme.palette.directColor1
|
||||
}
|
||||
}
|
||||
|
||||
@@ -147,8 +149,8 @@ CExPynn1gWf9bx498P7/nzPcxEzGExhBdJGYihtAYQlO+tUZvqrPbqeudo5iJGEJjCE15a3VtodH3q2I
|
||||
|
||||
StatusMenuItem {
|
||||
text: "welcome"
|
||||
iconSettings.isLetterIdenticon: true
|
||||
iconSettings.background.color: "red"
|
||||
assetSettings.isLetterIdenticon: true
|
||||
assetSettings.bgColor: "red"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,7 +43,7 @@ Column {
|
||||
selectMenu.delegate: StatusMenuItemDelegate {
|
||||
statusPopupMenu: select
|
||||
action: StatusMenuItem {
|
||||
iconSettings.name: "filled-account"
|
||||
assetSettings.name: "filled-account"
|
||||
text: name
|
||||
onTriggered: {
|
||||
selectedItem.text = name
|
||||
|
||||
@@ -75,11 +75,8 @@
|
||||
<file>main.qml</file>
|
||||
<file>ThemeSwitch.qml</file>
|
||||
<file>examples/FilteringSorting.qml</file>
|
||||
<file>images/RARI.png</file>
|
||||
<file>images/SRToken.png</file>
|
||||
<file>demoapp/data/profile-image-1.jpeg</file>
|
||||
<file>demoapp/data/profile-image-2.jpeg</file>
|
||||
<file>pages/StatusItemSelectorPage.qml</file>
|
||||
<file>pages/StatusComboBoxPage.qml</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
||||
@@ -239,7 +239,7 @@ Rectangle {
|
||||
id: waitTimer
|
||||
interval: lockTimeout
|
||||
onTriggered: {
|
||||
if(advancedInput.edit.text)
|
||||
if(advancedInput.text)
|
||||
advancedInput.locked = true
|
||||
}
|
||||
}
|
||||
@@ -311,7 +311,7 @@ Rectangle {
|
||||
}
|
||||
PropertyChanges {
|
||||
target: advancedInput
|
||||
edit.color: Theme.palette.directColor1
|
||||
input.color: Theme.palette.directColor1
|
||||
}
|
||||
PropertyChanges {
|
||||
target: basicInput
|
||||
@@ -370,7 +370,7 @@ Rectangle {
|
||||
}
|
||||
PropertyChanges {
|
||||
target: advancedInput
|
||||
edit.color: disabled ? Theme.palette.directColor5 : Theme.palette.dangerColor1
|
||||
input.edit.color: disabled ? Theme.palette.directColor5 : Theme.palette.dangerColor1
|
||||
}
|
||||
PropertyChanges {
|
||||
target: basicInput
|
||||
@@ -429,7 +429,7 @@ Rectangle {
|
||||
}
|
||||
PropertyChanges {
|
||||
target: advancedInput
|
||||
edit.color: Theme.palette.directColor1
|
||||
input.color: Theme.palette.directColor1
|
||||
}
|
||||
PropertyChanges {
|
||||
target: basicInput
|
||||
@@ -488,7 +488,7 @@ Rectangle {
|
||||
}
|
||||
PropertyChanges {
|
||||
target: advancedInput
|
||||
edit.color: Theme.palette.directColor1
|
||||
input.color: Theme.palette.directColor1
|
||||
}
|
||||
PropertyChanges {
|
||||
target: basicInput
|
||||
|
||||
@@ -0,0 +1,144 @@
|
||||
import QtQuick 2.14
|
||||
import QtQuick.Controls 2.14
|
||||
import QtQuick.Layouts 1.14
|
||||
import StatusQ.Controls 0.1
|
||||
|
||||
import "private/chart"
|
||||
|
||||
/*!
|
||||
\qmltype StatusChartPanel
|
||||
\inherits Page
|
||||
\inqmlmodule StatusQ.Components
|
||||
\since StatusQ.Components 0.1
|
||||
\brief Displays a chart component together with an optional header in order to add a list of options.
|
||||
Inherits \l{https://doc.qt.io/qt-5/qml-qtquick-controls2-page.html}{Page}.
|
||||
|
||||
The \c StatusChartPanel displays a customizable chart component. Additionally, options
|
||||
can be added in the header in both right and left sides given graphTabsModel and timeRangeTabsModel
|
||||
property are set respectively.
|
||||
|
||||
For example:
|
||||
|
||||
\qml
|
||||
StatusChartPanel {
|
||||
id: graphDetail
|
||||
width: parent.width
|
||||
height: 290
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
graphsModel: d.graphTabsModel
|
||||
timeRangeModel: d.timeRangeTabsModel
|
||||
chart.chartType: 'line'
|
||||
chart.chartData: {
|
||||
return {
|
||||
datasets: [{
|
||||
data: d.data
|
||||
}],
|
||||
...
|
||||
}
|
||||
}
|
||||
chart.chartOptions: {
|
||||
return {
|
||||
legend: {
|
||||
display: false
|
||||
},
|
||||
...
|
||||
}
|
||||
}
|
||||
}
|
||||
\endqml
|
||||
|
||||
\image status_chart_panel.png
|
||||
|
||||
For a list of components available see StatusQ.
|
||||
*/
|
||||
|
||||
Page {
|
||||
id: root
|
||||
|
||||
/*!
|
||||
\qmlproperty var StatusChartPanel::graphsModel
|
||||
This property holds the graphs model options to be set on the left side tab bar of the header.
|
||||
*/
|
||||
property var graphsModel
|
||||
/*!
|
||||
\qmlproperty var StatusChartPanel::timeRangeModel
|
||||
This property holds the time range options to be set on the right side tab bar of the header.
|
||||
*/
|
||||
property var timeRangeModel
|
||||
|
||||
/*!
|
||||
\qmlproperty alias StatusChartPanel::graphComponent
|
||||
This property holds holds a reference to the graph component.
|
||||
*/
|
||||
property alias chart: graphComponent
|
||||
|
||||
/*!
|
||||
\qmlproperty alias StatusChartPanel::timeRangeTabBarIndex
|
||||
This property holds holds a reference to the time range tab bar current index.
|
||||
*/
|
||||
property alias timeRangeTabBarIndex: timeRangeTabBar.currentIndex
|
||||
|
||||
/*!
|
||||
\qmlproperty string StatusChartPanel::selectedTimeRange
|
||||
This property holds holds the text of the current time range tab bar selected tab.
|
||||
*/
|
||||
property string selectedTimeRange: timeRangeTabBar.currentItem.text
|
||||
|
||||
/*!
|
||||
\qmlsignal
|
||||
This signal is emitted when a header tab bar is clicked.
|
||||
*/
|
||||
signal headerTabClicked(string text)
|
||||
|
||||
Component {
|
||||
id: tabButton
|
||||
StatusTabButton {
|
||||
leftPadding: 0
|
||||
width: implicitWidth
|
||||
onClicked: {
|
||||
root.headerTabClicked(text);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
if (!!timeRangeModel) {
|
||||
for (var i = 0; i < timeRangeModel.length; i++) {
|
||||
var timeTab = tabButton.createObject(root, { text: timeRangeModel[i].text,
|
||||
enabled: timeRangeModel[i].enabled });
|
||||
timeRangeTabBar.addItem(timeTab);
|
||||
}
|
||||
}
|
||||
if (!!graphsModel) {
|
||||
for (var j = 0; j < graphsModel.length; j++) {
|
||||
var graphTab = tabButton.createObject(root, { text: graphsModel[j].text,
|
||||
enabled: graphsModel[j].enabled });
|
||||
graphsTabBar.addItem(graphTab);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
background: null
|
||||
header: Item {
|
||||
height: childrenRect.height
|
||||
RowLayout {
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: 46
|
||||
anchors.right: parent.right
|
||||
StatusTabBar {
|
||||
id: graphsTabBar
|
||||
}
|
||||
StatusTabBar {
|
||||
id: timeRangeTabBar
|
||||
Layout.alignment: Qt.AlignRight
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
contentItem: Item {
|
||||
Chart {
|
||||
id: graphComponent
|
||||
anchors.fill: parent
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -118,12 +118,12 @@ Column {
|
||||
notificationsCount: model.notificationsCount
|
||||
highlightWhenCreated: !!model.highlight
|
||||
selected: (model.active && root.highlightItem)
|
||||
|
||||
icon.emoji: model.emoji
|
||||
icon.color: !!model.color ? model.color : Theme.palette.userCustomizationColors[model.colorId]
|
||||
image.isIdenticon: false
|
||||
image.source: model.icon
|
||||
asset.emoji: !!model.emoji ? model.emoji : ""
|
||||
asset.color: !!model.color ? model.color : Theme.palette.userCustomizationColors[model.colorId]
|
||||
asset.isImage: model.icon.includes("data")
|
||||
asset.name: model.icon
|
||||
ringSettings.ringSpecModel: model.colorHash
|
||||
onlineStatus: model.onlineStatus
|
||||
|
||||
sensor.cursorShape: dragSensor.cursorShape
|
||||
|
||||
@@ -228,9 +228,9 @@ Column {
|
||||
notificationsCount: model.notificationsCount
|
||||
selected: draggable.chatListItem.selected
|
||||
|
||||
icon.color: draggable.chatListItem.icon.color
|
||||
image.isIdenticon: draggable.chatListItem.image.isIdenticon
|
||||
image.source: draggable.chatListItem.image.source
|
||||
asset.color: draggable.chatListItem.asset.color
|
||||
asset.imgIsIdenticon: draggable.chatListItem.asset.imgIsIdenticon
|
||||
asset.name: draggable.chatListItem.asset.name
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ Item {
|
||||
property bool draggableCategories: false
|
||||
// Keeps track of expanded category state. Should only be modified
|
||||
// internally at runtime.
|
||||
property var openedCategoryState: new Object({})
|
||||
property var openedCategoryState: ({})
|
||||
|
||||
property Component categoryPopupMenu
|
||||
property Component chatListPopupMenu
|
||||
@@ -71,6 +71,7 @@ Item {
|
||||
spacing: 4
|
||||
|
||||
StatusChatList {
|
||||
objectName: "statusChatListAndCategoriesChatList"
|
||||
id: statusChatList
|
||||
visible: statusChatList.model.count > 0
|
||||
onChatItemSelected: root.chatItemSelected(categoryId, id)
|
||||
@@ -113,6 +114,7 @@ Item {
|
||||
|
||||
delegate: Item {
|
||||
id: draggable
|
||||
objectName: model.name
|
||||
width: statusChatListCategory.width
|
||||
height: statusChatListCategory.height
|
||||
property alias chatListCategory: statusChatListCategory
|
||||
@@ -259,6 +261,7 @@ Item {
|
||||
|
||||
Repeater {
|
||||
id: statusChatListCategories
|
||||
objectName: "communityChatListCategories"
|
||||
visible: !!model && model.count > 0
|
||||
model: delegateModel
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@ Column {
|
||||
property bool opened: true
|
||||
property bool dragged: false
|
||||
|
||||
property alias statusChatListCategoryItem: statusChatListCategoryItem
|
||||
property alias showActionButtons: statusChatListCategoryItem.showActionButtons
|
||||
property alias addButton: statusChatListCategoryItem.addButton
|
||||
property alias menuButton: statusChatListCategoryItem.menuButton
|
||||
@@ -37,20 +38,20 @@ Column {
|
||||
title: statusChatListCategory.name
|
||||
opened: statusChatListCategory.opened
|
||||
sensor.pressAndHoldInterval: 150
|
||||
|
||||
propagateTitleClicks: true // title click is handled as a normal click (fallthru)
|
||||
showMenuButton: showActionButtons && !!statusChatListCategory.popupMenu
|
||||
highlighted: statusChatListCategory.dragged
|
||||
sensor.onClicked: {
|
||||
onClicked: {
|
||||
if (sensor.enabled) {
|
||||
if (mouse.button === Qt.RightButton && showActionButtons && !!statusChatListCategory.popupMenu) {
|
||||
highlighted = true;
|
||||
popupMenuSlot.item.popup(mouse.x + 4, mouse.y + 6);
|
||||
return
|
||||
} else if (mouse.button === Qt.LeftButton) {
|
||||
statusChatListCategory.opened = !statusChatListCategory.opened
|
||||
}
|
||||
}
|
||||
}
|
||||
onTitleClicked: statusChatListCategory.opened = !opened
|
||||
onToggleButtonClicked: statusChatListCategory.opened = !opened
|
||||
onToggleButtonClicked: statusChatListCategory.opened = !statusChatListCategory.opened
|
||||
onMenuButtonClicked: {
|
||||
highlighted = true
|
||||
menuButton.highlighted = true
|
||||
|
||||
@@ -60,15 +60,7 @@ StatusListItem {
|
||||
icon.name: "chevron-down"
|
||||
icon.width: 18
|
||||
icon.rotation: statusChatListCategoryItem.opened ? 0 : 270
|
||||
onPressed: {
|
||||
sensor.enabled = false;
|
||||
}
|
||||
onClicked: {
|
||||
statusChatListCategoryItem.toggleButtonClicked(mouse);
|
||||
}
|
||||
onReleased: {
|
||||
sensor.enabled = true;
|
||||
}
|
||||
onClicked: statusChatListCategoryItem.toggleButtonClicked(mouse)
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -21,11 +21,9 @@ Rectangle {
|
||||
property bool hasUnreadMessages: false
|
||||
property int notificationsCount: 0
|
||||
property bool muted: false
|
||||
property StatusImageSettings image: StatusImageSettings {
|
||||
width: 24
|
||||
height: 24
|
||||
}
|
||||
property StatusIconSettings icon: StatusIconSettings {
|
||||
property int onlineStatus: StatusChatListItem.OnlineStatus.Inactive
|
||||
|
||||
property StatusAssetSettings asset: StatusAssetSettings {
|
||||
width: 24
|
||||
height: 24
|
||||
color: Theme.palette.miscColor5
|
||||
@@ -53,6 +51,11 @@ Rectangle {
|
||||
CommunityChat // 6
|
||||
}
|
||||
|
||||
enum OnlineStatus {
|
||||
Inactive,
|
||||
Online
|
||||
}
|
||||
|
||||
implicitWidth: 288
|
||||
implicitHeight: 40
|
||||
|
||||
@@ -85,9 +88,17 @@ Rectangle {
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: 8
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
image: root.image
|
||||
icon: root.icon
|
||||
asset: root.asset
|
||||
name: root.name
|
||||
|
||||
badge {
|
||||
visible: type === StatusChatListItem.Type.OneToOneChat
|
||||
color: onlineStatus === StatusChatListItem.OnlineStatus.Online ? Theme.palette.successColor1 : Theme.palette.baseColor1
|
||||
border.width: 1
|
||||
border.color: root.color
|
||||
implicitHeight: 9
|
||||
implicitWidth: 9
|
||||
}
|
||||
}
|
||||
|
||||
StatusIcon {
|
||||
@@ -112,17 +123,14 @@ Rectangle {
|
||||
|
||||
icon: {
|
||||
switch (root.type) {
|
||||
case StatusChatListItem.Type.PublicCat:
|
||||
return Theme.palette.name == "light" ? "tiny/public-chat" : "tiny/public-chat-white"
|
||||
break;
|
||||
case StatusChatListItem.Type.PublicChat:
|
||||
return Theme.palette.name === "light" ? "tiny/public-chat" : "tiny/public-chat-white"
|
||||
case StatusChatListItem.Type.GroupChat:
|
||||
return Theme.palette.name == "light" ? "tiny/group" : "tiny/group-white"
|
||||
break;
|
||||
return Theme.palette.name === "light" ? "tiny/group" : "tiny/group-white"
|
||||
case StatusChatListItem.Type.CommunityChat:
|
||||
return Theme.palette.name == "light" ? "tiny/channel" : "tiny/channel-white"
|
||||
break;
|
||||
return Theme.palette.name === "light" ? "tiny/channel" : "tiny/channel-white"
|
||||
default:
|
||||
return Theme.palette.name == "light" ? "tiny/public-chat" : "tiny/public-chat-white"
|
||||
return Theme.palette.name === "light" ? "tiny/public-chat" : "tiny/public-chat-white"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,149 +0,0 @@
|
||||
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
|
||||
Item {
|
||||
id: statusChatToolBar
|
||||
|
||||
property alias menuButton: menuButton
|
||||
property alias notificationButton: notificationButton
|
||||
property alias membersButton: membersButton
|
||||
property alias searchButton: searchButton
|
||||
|
||||
property int padding: 8
|
||||
property int notificationCount: 0
|
||||
property Component popupMenu
|
||||
property var toolbarComponent
|
||||
|
||||
signal chatInfoButtonClicked()
|
||||
signal menuButtonClicked()
|
||||
signal notificationButtonClicked()
|
||||
signal membersButtonClicked()
|
||||
signal searchButtonClicked()
|
||||
|
||||
implicitWidth: 518
|
||||
implicitHeight: 60
|
||||
|
||||
onPopupMenuChanged: {
|
||||
if (!!popupMenu) {
|
||||
popupMenuSlot.sourceComponent = popupMenu
|
||||
}
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
width: parent.width
|
||||
spacing: padding / 2
|
||||
|
||||
Loader {
|
||||
id: loader
|
||||
sourceComponent: statusChatToolBar.toolbarComponent
|
||||
Layout.fillWidth: true
|
||||
Layout.alignment: Qt.AlignTop | Qt.AlignLeft
|
||||
Layout.topMargin: padding
|
||||
Layout.leftMargin: padding
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
id: actionButtons
|
||||
Layout.alignment: Qt.AlignTop | Qt.AlignRight
|
||||
Layout.topMargin: padding
|
||||
Layout.rightMargin: padding
|
||||
spacing: 8
|
||||
|
||||
StatusFlatRoundButton {
|
||||
id: searchButton
|
||||
width: 32
|
||||
height: 32
|
||||
icon.name: "search"
|
||||
type: StatusFlatRoundButton.Type.Secondary
|
||||
onClicked: statusChatToolBar.searchButtonClicked()
|
||||
|
||||
// initializing the tooltip
|
||||
tooltip.text: qsTr("Search")
|
||||
tooltip.orientation: StatusToolTip.Orientation.Bottom
|
||||
tooltip.y: parent.height + 12
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
StatusFlatRoundButton {
|
||||
id: menuButton
|
||||
objectName: "chatToolbarMoreOptionsButton"
|
||||
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: qsTr("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()
|
||||
}
|
||||
|
||||
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()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -360,11 +360,11 @@ Rectangle {
|
||||
height: 24
|
||||
radius: 20
|
||||
closeButtonVisible: false
|
||||
icon.emoji: model.emoji
|
||||
icon.height: 24
|
||||
icon.width: icon.height
|
||||
icon.color: "transparent"
|
||||
icon.isLetterIdenticon: true
|
||||
asset.emoji: model.emoji
|
||||
asset.width: 24
|
||||
asset.height: 24
|
||||
asset.color: "transparent"
|
||||
asset.isLetterIdenticon: true
|
||||
title: model.name
|
||||
titleText.font.pixelSize: 13
|
||||
titleText.color: d.fontColor
|
||||
|
||||
@@ -9,16 +9,14 @@ Row {
|
||||
property bool isContact: false
|
||||
property var trustIndicator: StatusContactVerificationIcons.TrustedType.None
|
||||
|
||||
property StatusIconSettings mutualConnectionIcon: StatusIconSettings {
|
||||
property StatusAssetSettings mutualConnectionIcon: StatusAssetSettings {
|
||||
name: "tiny/tiny-contact"
|
||||
color: Theme.palette.indirectColor1
|
||||
width: dummyImage.width
|
||||
height: dummyImage.height
|
||||
background: StatusIconBackgroundSettings {
|
||||
width: 10
|
||||
height: 10
|
||||
color: Theme.palette.primaryColor1
|
||||
}
|
||||
bgWidth: 10
|
||||
bgHeight: 10
|
||||
bgColor: Theme.palette.primaryColor1
|
||||
// Only used to get implicit width and height from the actual image
|
||||
property Image dummyImage: Image {
|
||||
source: mutualConnectionIcon.name ? "../../assets/img/icons/" + mutualConnectionIcon.name + ".svg": ""
|
||||
@@ -26,17 +24,15 @@ Row {
|
||||
}
|
||||
}
|
||||
|
||||
property StatusIconSettings trustContactIcon: StatusIconSettings {
|
||||
property StatusAssetSettings trustContactIcon: StatusAssetSettings {
|
||||
// None and Untrustworthy types, same aspect (Icon will not be visible in case of None type):
|
||||
name: root.trustIndicator === StatusContactVerificationIcons.TrustedType.Verified ? "tiny/tiny-checkmark" : "tiny/subtract"
|
||||
color: Theme.palette.indirectColor1
|
||||
width: dummyImage.width
|
||||
height: dummyImage.height
|
||||
background: StatusIconBackgroundSettings {
|
||||
width: 10
|
||||
height: 10
|
||||
color: root.trustIndicator === StatusContactVerificationIcons.TrustedType.Verified ? Theme.palette.primaryColor1 : Theme.palette.dangerColor1
|
||||
}
|
||||
bgWidth: 10
|
||||
bgHeight: 10
|
||||
bgColor: root.trustIndicator === StatusContactVerificationIcons.TrustedType.Verified ? Theme.palette.primaryColor1 : Theme.palette.dangerColor1
|
||||
// Only used to get implicit width and height from the actual image
|
||||
property Image dummyImage: Image {
|
||||
source: trustContactIcon.name ? "../../assets/img/icons/" + trustContactIcon.name + ".svg": ""
|
||||
@@ -55,25 +51,25 @@ Row {
|
||||
|
||||
StatusRoundIcon {
|
||||
visible: root.isContact
|
||||
icon.name: root.mutualConnectionIcon.name
|
||||
icon.width: root.mutualConnectionIcon.width
|
||||
icon.height: root.mutualConnectionIcon.height
|
||||
icon.rotation: root.mutualConnectionIcon.rotation
|
||||
icon.color: root.mutualConnectionIcon.color
|
||||
icon.background.color: root.mutualConnectionIcon.background.color
|
||||
icon.background.width: root.mutualConnectionIcon.background.width
|
||||
icon.background.height: root.mutualConnectionIcon.background.height
|
||||
asset.name: root.mutualConnectionIcon.name
|
||||
asset.width: root.mutualConnectionIcon.width
|
||||
asset.height: root.mutualConnectionIcon.height
|
||||
asset.rotation: root.mutualConnectionIcon.rotation
|
||||
asset.color: root.mutualConnectionIcon.color
|
||||
asset.bgColor: root.mutualConnectionIcon.bgColor
|
||||
asset.bgWidth: root.mutualConnectionIcon.bgWidth
|
||||
asset.bgHeight: root.mutualConnectionIcon.bgHeight
|
||||
}
|
||||
|
||||
StatusRoundIcon {
|
||||
visible: root.trustIndicator !== StatusContactVerificationIcons.TrustedType.None
|
||||
icon.name: root.trustContactIcon.name
|
||||
icon.width: root.trustContactIcon.width
|
||||
icon.height: root.trustContactIcon.height
|
||||
icon.rotation: root.trustContactIcon.rotation
|
||||
icon.color: root.trustContactIcon.color
|
||||
icon.background.color: root.trustContactIcon.background.color
|
||||
icon.background.width: root.trustContactIcon.background.width
|
||||
icon.background.height: root.trustContactIcon.background.height
|
||||
asset.name: root.trustContactIcon.name
|
||||
asset.width: root.trustContactIcon.width
|
||||
asset.height: root.trustContactIcon.height
|
||||
asset.rotation: root.trustContactIcon.rotation
|
||||
asset.color: root.trustContactIcon.color
|
||||
asset.bgColor: root.trustContactIcon.bgColor
|
||||
asset.bgWidth: root.trustContactIcon.bgWidth
|
||||
asset.bgHeight: root.trustContactIcon.bgHeight
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
import QtQuick 2.14
|
||||
|
||||
import StatusQ.Core 0.1
|
||||
import StatusQ.Core.Theme 0.1
|
||||
|
||||
StatusBaseText {
|
||||
id: root
|
||||
|
||||
property int previousMessageIndex: -1
|
||||
property double previousMessageTimestamp
|
||||
property double messageTimestamp
|
||||
|
||||
font.pixelSize: 13
|
||||
color: Theme.palette.baseColor1
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
|
||||
text: {
|
||||
if (previousMessageIndex === -1)
|
||||
return "";
|
||||
|
||||
const currentMsgDate = new Date(messageTimestamp);
|
||||
const prevMsgDate = new Date(previousMessageTimestamp);
|
||||
|
||||
if (!!prevMsgDate && currentMsgDate.getDay() === prevMsgDate.getDay())
|
||||
return "";
|
||||
|
||||
const now = new Date();
|
||||
if (now.getFullYear() == currentMsgDate.getFullYear() && now.getMonth() == currentMsgDate.getMonth() && now.getDate() == currentMsgDate.getDate())
|
||||
return qsTr("Today");
|
||||
|
||||
const yesterday = new Date();
|
||||
yesterday.setDate(now.getDate()-1);
|
||||
if (yesterday.getFullYear() == currentMsgDate.getFullYear() && yesterday.getMonth() == currentMsgDate.getMonth() && yesterday.getDate() == currentMsgDate.getDate())
|
||||
return qsTr("Yesterday");
|
||||
|
||||
// FIXME Qt6: replace with Intl.DateTimeFormat
|
||||
const monthName = Qt.locale().standaloneMonthName(currentMsgDate.getMonth(), Locale.LongFormat)
|
||||
if (now.getFullYear() > currentMsgDate.getFullYear())
|
||||
return "%1 %2, %3".arg(monthName).arg(currentMsgDate.getDate()).arg(currentMsgDate.getFullYear())
|
||||
return "%1, %2".arg(monthName).arg(currentMsgDate.getDate())
|
||||
}
|
||||
}
|
||||
@@ -10,7 +10,7 @@ Rectangle {
|
||||
property string subTitle: ""
|
||||
property alias subTitleComponent: statusDescriptionListItemSubTitle
|
||||
property string value: ""
|
||||
property StatusIconSettings icon: StatusIconSettings {
|
||||
property StatusAssetSettings asset: StatusAssetSettings {
|
||||
width: 23
|
||||
height: 23
|
||||
}
|
||||
@@ -59,7 +59,7 @@ Rectangle {
|
||||
|
||||
StatusFlatRoundButton {
|
||||
id: statusFlatRoundButton
|
||||
visible: !!statusDescriptionListItem.icon.name
|
||||
visible: !!statusDescriptionListItem.asset.name
|
||||
anchors.verticalCenter: statusDescriptionListItemSubTitle.verticalCenter
|
||||
anchors.left: statusDescriptionListItemSubTitle.right
|
||||
anchors.leftMargin: 4
|
||||
@@ -67,9 +67,9 @@ Rectangle {
|
||||
width: 32
|
||||
height: 32
|
||||
|
||||
icon.name: statusDescriptionListItem.icon.name
|
||||
icon.width: statusDescriptionListItem.icon.width
|
||||
icon.height: statusDescriptionListItem.icon.height
|
||||
icon.name: statusDescriptionListItem.asset.name
|
||||
icon.width: statusDescriptionListItem.asset.width
|
||||
icon.height: statusDescriptionListItem.asset.height
|
||||
|
||||
StatusToolTip {
|
||||
id: statusToolTip
|
||||
|
||||
@@ -13,24 +13,19 @@ Rectangle {
|
||||
property alias button: button
|
||||
property alias expandableComponent: expandableRegion.sourceComponent
|
||||
property alias expandableItem: expandableRegion.item
|
||||
property bool separatorVisible: true
|
||||
|
||||
property int type: StatusExpandableItem.Type.Primary
|
||||
property bool expandable: true
|
||||
property bool expanded: false
|
||||
|
||||
property StatusIconSettings icon: StatusIconSettings {
|
||||
width: !!statusExpandableItem.icon.name.toString() ? 24 : 40
|
||||
height: !!statusExpandableItem.icon.name.toString() ? 24 : 40
|
||||
property StatusAssetSettings asset: StatusAssetSettings {
|
||||
width: !statusExpandableItem.asset.isImage ? 24 : 40
|
||||
height: !statusExpandableItem.asset.isImage ? 24 : 40
|
||||
color: Theme.palette.directColor1
|
||||
background: StatusIconBackgroundSettings {
|
||||
width: 32
|
||||
height: 32
|
||||
color: Theme.palette.primaryColor2
|
||||
}
|
||||
}
|
||||
property StatusImageSettings image: StatusImageSettings {
|
||||
width: 40
|
||||
height: 40
|
||||
bgWidth: 32
|
||||
bgHeight: 32
|
||||
bgColor: Theme.palette.primaryColor2
|
||||
}
|
||||
|
||||
enum Type {
|
||||
@@ -55,7 +50,7 @@ Rectangle {
|
||||
height: 1
|
||||
|
||||
color: Theme.palette.baseColor2
|
||||
visible: (statusExpandableItem.type === StatusExpandableItem.Type.Tertiary)
|
||||
visible: (statusExpandableItem.type === StatusExpandableItem.Type.Tertiary) && separatorVisible
|
||||
}
|
||||
|
||||
|
||||
@@ -63,7 +58,7 @@ Rectangle {
|
||||
id: header
|
||||
anchors.top: parent.top
|
||||
width: parent.width
|
||||
height: 64
|
||||
height: statusExpandableItem.type === StatusExpandableItem.Type.Tertiary ? 40 : 64
|
||||
radius: (statusExpandableItem.type === StatusExpandableItem.Type.Secondary) ? 8 : 0
|
||||
color: statusExpandableItem.type === StatusExpandableItem.Type.Secondary && sensor.containsMouse ? Theme.palette.baseColor2 : "transparent"
|
||||
|
||||
@@ -73,8 +68,7 @@ Rectangle {
|
||||
anchors.topMargin: (statusExpandableItem.type === StatusExpandableItem.Type.Secondary) ? 12.5 : 25
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: (statusExpandableItem.type === StatusExpandableItem.Type.Secondary) ? 16 : 11
|
||||
image: statusExpandableItem.image
|
||||
icon: statusExpandableItem.icon
|
||||
asset: statusExpandableItem.asset
|
||||
name: primaryText.text
|
||||
active: (statusExpandableItem.type !== StatusExpandableItem.Type.Tertiary)
|
||||
}
|
||||
@@ -85,14 +79,14 @@ Rectangle {
|
||||
(statusExpandableItem.type === StatusExpandableItem.Type.Tertiary) ? parent.top : undefined
|
||||
anchors.topMargin: (statusExpandableItem.type === StatusExpandableItem.Type.Tertiary) ? 29 : 17
|
||||
anchors.left: identicon.active ? identicon.right : parent.left
|
||||
anchors.leftMargin: (statusExpandableItem.type === StatusExpandableItem.Type.Primary) ? 10 : 16
|
||||
anchors.leftMargin: (statusExpandableItem.type === StatusExpandableItem.Type.Primary) ? 10 : !identicon.active ? 0 : 16
|
||||
|
||||
anchors.verticalCenter: (statusExpandableItem.type === StatusExpandableItem.Type.Secondary) ? identicon.verticalCenter : undefined
|
||||
|
||||
width: !!additionalText.text ? (button.visible ? parent.width - icon.background.width - button.width - additionalText.contentWidth - 110 :
|
||||
parent.width - icon.background.width - additionalText.contentWidth - 110) :
|
||||
(button.visible ? parent.width - icon.background.width - button.width - 70 :
|
||||
parent.width - icon.background.width - 70)
|
||||
width: !!additionalText.text ? (button.visible ? parent.width - asset.bgWidth - button.width - additionalText.contentWidth - 110 :
|
||||
parent.width - asset.bgWidth - additionalText.contentWidth - 110) :
|
||||
(button.visible ? parent.width - asset.bgWidth - button.width - 70 :
|
||||
parent.width - asset.bgWidth - 70)
|
||||
|
||||
font.weight: (statusExpandableItem.type === StatusExpandableItem.Type.Primary) ? Font.Medium : Font.Normal
|
||||
font.pixelSize: (statusExpandableItem.type === StatusExpandableItem.Type.Primary) ? 15 : 17
|
||||
@@ -181,7 +175,7 @@ Rectangle {
|
||||
Loader {
|
||||
id: expandableRegion
|
||||
anchors.top: header.bottom
|
||||
anchors.topMargin: 16
|
||||
anchors.topMargin: (statusExpandableItem.type === StatusExpandableItem.Type.Tertiary) ? 24 : 16
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: (statusExpandableItem.type === StatusExpandableItem.Type.Primary) ? 48 : 0
|
||||
anchors.right: parent.right
|
||||
@@ -202,7 +196,7 @@ Rectangle {
|
||||
State {
|
||||
name: "EXPANDED"
|
||||
PropertyChanges {target: expandImage; icon: "chevron-up"}
|
||||
PropertyChanges {target: statusExpandableItem; height: 82 + expandableRegion.height + 22}
|
||||
PropertyChanges {target: statusExpandableItem; height: 82 + expandableRegion.height}
|
||||
PropertyChanges {target: expandableRegion; visible: true}
|
||||
},
|
||||
State {
|
||||
|
||||
@@ -216,6 +216,7 @@ Item {
|
||||
anchors.fill: parent
|
||||
|
||||
enabled: root.interactive
|
||||
cursorShape: Qt.SizeAllCursor
|
||||
|
||||
property var lastDragPoint: null
|
||||
onReleased: lastDragPoint = null
|
||||
|
||||
@@ -27,12 +27,15 @@ import StatusQ.Core.Utils 0.1
|
||||
defaultItemText: qsTr("Example: 10 SNT")
|
||||
andOperatorText: qsTr("and")
|
||||
orOperatorText: qsTr("or")
|
||||
popupItem: CustomPopup {
|
||||
id: customPopup
|
||||
onAddItem: {
|
||||
tokensSelector.addItem(itemText, itemImage, operator)
|
||||
customPopup.close()
|
||||
}
|
||||
|
||||
CustomPopup {
|
||||
id: popup
|
||||
}
|
||||
|
||||
addButton.onClicked: {
|
||||
popup.x = mouse.x
|
||||
popup.y = mouse.y
|
||||
popup.open()
|
||||
}
|
||||
}
|
||||
\endqml
|
||||
@@ -66,10 +69,10 @@ Rectangle {
|
||||
*/
|
||||
property url defaultItemImageSource: ""
|
||||
/*!
|
||||
\qmlproperty QC.Popup StatusItemSelector::popupItem
|
||||
This property holds a custom popup item to be opened near the `add` button in order to select new items.
|
||||
\qmlproperty StatusRoundButton StatusItemSelector::addButton
|
||||
This property holds an alias to the `add` button.
|
||||
*/
|
||||
property QC.Popup popupItem
|
||||
readonly property alias addButton: addItemButton
|
||||
/*!
|
||||
\qmlproperty ListModel StatusItemSelector::itemsModel
|
||||
This property holds the data that will be populated in the items selector.
|
||||
@@ -90,7 +93,13 @@ Rectangle {
|
||||
}
|
||||
\endqml
|
||||
*/
|
||||
property ListModel itemsModel: ListModel { }
|
||||
property var itemsModel: ListModel { }
|
||||
/*!
|
||||
\qmlproperty bool StatusItemSelector::useIcons
|
||||
This property determines if the imageSource role from the model will be handled as
|
||||
an image or an icon.
|
||||
*/
|
||||
property bool useIcons: false
|
||||
/*!
|
||||
\qmlproperty string StatusItemSelector::andOperatorText
|
||||
This property holds the string text representation for an `AND` logical operator.
|
||||
@@ -101,27 +110,24 @@ Rectangle {
|
||||
This property holds the string text representation for an `OR` logical operator.
|
||||
*/
|
||||
property string orOperatorText: qsTr("or")
|
||||
/*
|
||||
\qmlmethod StatusItemSelector::addItem()
|
||||
It is used to add new items into the selector control. The expected arguments are:
|
||||
string `text`, url `imageSource` and int `operator` (None = 0, And = 1 and Or = 2)
|
||||
/*!
|
||||
\qmlsignal StatusItemSelector::itemClicked
|
||||
This signal is emitted when the item is clicked.
|
||||
*/
|
||||
function addItem(text, imageSource, operator) {
|
||||
itemsModel.insert(itemsModel.count, { "text": text, "imageSource": imageSource.toString(), "operator": operator })
|
||||
}
|
||||
signal itemClicked(var item, int index, var mouse)
|
||||
|
||||
|
||||
QtObject {
|
||||
id: d
|
||||
|
||||
function operatorTextFormat(operator) {
|
||||
switch(operator)
|
||||
{
|
||||
case Utils.Operators.And:
|
||||
return root.andOperatorText
|
||||
case Utils.Operators.Or:
|
||||
return root.orOperatorText
|
||||
case Utils.Operators.None:
|
||||
return ""
|
||||
switch(operator) {
|
||||
case Utils.Operators.And:
|
||||
return root.andOperatorText
|
||||
case Utils.Operators.Or:
|
||||
return root.orOperatorText
|
||||
case Utils.Operators.None:
|
||||
return ""
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -168,9 +174,10 @@ Rectangle {
|
||||
Layout.fillWidth: true
|
||||
spacing: 6
|
||||
StatusListItemTag {
|
||||
visible: itemsModel.count === 0
|
||||
visible: !itemsModel || itemsModel.count === 0
|
||||
title: root.defaultItemText
|
||||
image.source: root.defaultItemImageSource
|
||||
asset.name: root.defaultItemImageSource
|
||||
asset.isImage: true
|
||||
color: Theme.palette.baseColor2
|
||||
closeButtonVisible: false
|
||||
titleText.color: Theme.palette.baseColor1
|
||||
@@ -178,8 +185,10 @@ Rectangle {
|
||||
}
|
||||
Repeater {
|
||||
model: itemsModel
|
||||
|
||||
RowLayout {
|
||||
spacing: flow.spacing
|
||||
|
||||
StatusBaseText {
|
||||
visible: model.operator !== Utils.Operators.None
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
@@ -200,12 +209,20 @@ Rectangle {
|
||||
}
|
||||
StatusListItemTag {
|
||||
title: model.text
|
||||
image.source: model.imageSource
|
||||
asset.name: model.imageSource
|
||||
asset.isImage: !root.useIcons
|
||||
asset.bgColor: "transparent"
|
||||
color: Theme.palette.primaryColor3
|
||||
closeButtonVisible: false
|
||||
titleText.color: Theme.palette.primaryColor1
|
||||
titleText.font.pixelSize: 15
|
||||
//onClicked: // TODO: Open remove or edit dialog
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
acceptedButtons: Qt.LeftButton | Qt.RightButton
|
||||
onClicked: root.itemClicked(parent, model.index, mouse)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -216,11 +233,6 @@ Rectangle {
|
||||
height: width
|
||||
type: StatusRoundButton.Type.Secondary
|
||||
icon.name: "add"
|
||||
onClicked: {
|
||||
root.popupItem.x = addItemButton.x + addItemButton.width + 4 * flow.spacing
|
||||
root.popupItem.y = addItemButton.y + addItemButton.height
|
||||
root.popupItem.open()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,46 +23,42 @@ Rectangle {
|
||||
property string titleTextIcon: ""
|
||||
property real leftPadding: 16
|
||||
property real rightPadding: 16
|
||||
property bool enabled: true
|
||||
property bool highlighted: false
|
||||
property bool propagateTitleClicks: true
|
||||
property int type: StatusListItem.Type.Primary
|
||||
property list<Item> components
|
||||
property var bottomModel: []
|
||||
property Component bottomDelegate
|
||||
property var tagsModel: []
|
||||
property alias tagsModel: tagsRepeater.model
|
||||
property Component tagsDelegate
|
||||
property var inlineTagModel: []
|
||||
property Component inlineTagDelegate
|
||||
property bool loading: false
|
||||
property bool loadingFailed: false
|
||||
|
||||
property StatusIconSettings icon: StatusIconSettings {
|
||||
height: isLetterIdenticon ? 40 : 20
|
||||
width: isLetterIdenticon ? 40 : 20
|
||||
property StatusAssetSettings asset: StatusAssetSettings {
|
||||
height: isImage ? 40 : 20
|
||||
width: isImage ? 40 : 20
|
||||
rotation: 0
|
||||
isLetterIdenticon: false
|
||||
letterSize: 21
|
||||
charactersLen: 1
|
||||
color: isLetterIdenticon ? background.color : type === StatusListItem.Type.Danger ?
|
||||
color: isLetterIdenticon ? bgColor : type === StatusListItem.Type.Danger ?
|
||||
Theme.palette.dangerColor1 : Theme.palette.primaryColor1
|
||||
background: StatusIconBackgroundSettings {
|
||||
width: 40
|
||||
height: 40
|
||||
color: {
|
||||
if (sensor.containsMouse) {
|
||||
return type === StatusListItem.Type.Secondary ||
|
||||
type === StatusListItem.Type.Danger ? "transparent" :
|
||||
Theme.palette.primaryColor3
|
||||
}
|
||||
return type === StatusListItem.Type.Danger ?
|
||||
Theme.palette.dangerColor3 : Theme.palette.primaryColor3
|
||||
bgWidth: 40
|
||||
bgHeight: 40
|
||||
bgColor: {
|
||||
if (sensor.containsMouse) {
|
||||
return type === StatusListItem.Type.Secondary ||
|
||||
type === StatusListItem.Type.Danger ? "transparent" :
|
||||
Theme.palette.primaryColor3
|
||||
}
|
||||
return type === StatusListItem.Type.Danger ?
|
||||
Theme.palette.dangerColor3 : Theme.palette.primaryColor3
|
||||
}
|
||||
imgIsIdenticon: false
|
||||
}
|
||||
property StatusImageSettings image: StatusImageSettings {
|
||||
width: 40
|
||||
height: 40
|
||||
isIdenticon: false
|
||||
}
|
||||
|
||||
property StatusIdenticonRingSettings ringSettings: StatusIdenticonRingSettings {
|
||||
initalAngleRad: 0
|
||||
ringPxSize: 1.5
|
||||
@@ -122,33 +118,32 @@ Rectangle {
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: sensor
|
||||
|
||||
enabled: statusListItem.enabled
|
||||
anchors.fill: parent
|
||||
cursorShape: enabled ? Qt.PointingHandCursor : Qt.ArrowCursor
|
||||
acceptedButtons: Qt.LeftButton | Qt.RightButton
|
||||
hoverEnabled: true
|
||||
preventStealing: true
|
||||
|
||||
onClicked: {
|
||||
statusListItem.clicked(statusListItem.itemId, mouse)
|
||||
}
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: sensor
|
||||
|
||||
anchors.fill: parent
|
||||
cursorShape: containsMouse ? Qt.PointingHandCursor : Qt.ArrowCursor
|
||||
acceptedButtons: Qt.NoButton
|
||||
hoverEnabled: true
|
||||
|
||||
StatusSmartIdenticon {
|
||||
id: iconOrImage
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: statusListItem.leftPadding
|
||||
anchors.top: parent.top
|
||||
anchors.topMargin: 12
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
visible: !iconOrImageLoadingOverlay.visible
|
||||
image: statusListItem.image
|
||||
icon: statusListItem.icon
|
||||
asset: statusListItem.asset
|
||||
name: statusListItem.title
|
||||
active: statusListItem.icon.isLetterIdenticon ||
|
||||
!!statusListItem.icon.name ||
|
||||
!!statusListItem.image.source.toString() ||
|
||||
!!statusListItem.icon.emoji
|
||||
active: statusListItem.asset.isLetterIdenticon ||
|
||||
!!statusListItem.asset.name ||
|
||||
!!statusListItem.asset.emoji
|
||||
badge.border.color: statusListItem.color
|
||||
ringSettings: statusListItem.ringSettings
|
||||
}
|
||||
@@ -181,7 +176,7 @@ Rectangle {
|
||||
anchors.left: iconOrImage.active ? iconOrImage.right : parent.left
|
||||
anchors.right: statusListItemLabel.visible ? statusListItemLabel.left : statusListItemComponentsSlot.left
|
||||
anchors.leftMargin: iconOrImage.active ? 16 : statusListItem.leftPadding
|
||||
anchors.rightMargin: statusListItem.rightPadding
|
||||
anchors.rightMargin: Math.max(statusListItem.rightPadding, titleIconsRow.requiredWidth)
|
||||
anchors.verticalCenter: bottomModel.length === 0 ? parent.verticalCenter : undefined
|
||||
|
||||
height: childrenRect.height
|
||||
@@ -277,30 +272,76 @@ Rectangle {
|
||||
|
||||
Loader {
|
||||
id: titleIconsRow
|
||||
|
||||
readonly property int requiredWidth: active ? width + anchors.leftMargin * 2 : 0
|
||||
|
||||
anchors.left: !statusListItem.titleAsideText ? statusListItemTitle.right : statusListItemTitleAsideText.right
|
||||
anchors.verticalCenter: statusListItemTitle.verticalCenter
|
||||
anchors.leftMargin: 4
|
||||
}
|
||||
|
||||
StatusBaseText {
|
||||
id: statusListItemSubTitle
|
||||
objectName: "statusListItemSubTitle"
|
||||
RowLayout {
|
||||
id: statusListItemSubtitleTagsRow
|
||||
anchors.top: statusListItemTitle.bottom
|
||||
width: parent.width
|
||||
text: statusListItem.subTitle
|
||||
font.pixelSize: 15
|
||||
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
|
||||
spacing: 4
|
||||
|
||||
StatusBaseText {
|
||||
id: statusListItemSubTitle
|
||||
objectName: "statusListItemSubTitle"
|
||||
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
Layout.preferredWidth: inlineTagModelRepeater.count > 0 ? contentWidth : parent.width
|
||||
|
||||
text: statusListItem.subTitle
|
||||
font.pixelSize: 15
|
||||
color: statusListItem.loadingFailed ? Theme.palette.dangerColor1
|
||||
: !statusListItem.enabled || !statusListItem.tertiaryTitle
|
||||
? Theme.palette.baseColor1
|
||||
: Theme.palette.directColor1
|
||||
visible: !!statusListItem.subTitle
|
||||
wrapMode: Text.WrapAtWordBoundaryOrAnywhere
|
||||
}
|
||||
|
||||
StatusBaseText {
|
||||
id: dot
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
Layout.topMargin: -48
|
||||
|
||||
text: "."
|
||||
font.pixelSize: 40
|
||||
color: Theme.palette.baseColor1
|
||||
lineHeightMode: Text.FixedHeight
|
||||
lineHeight: 24
|
||||
|
||||
visible: inlineTagModelRepeater.count > 0
|
||||
}
|
||||
|
||||
StatusScrollView {
|
||||
id: inlineTagModelRepeaterRow
|
||||
Layout.fillWidth: true
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
Layout.preferredHeight: row.height
|
||||
contentHeight: row.height
|
||||
contentWidth: row.width
|
||||
padding: 0
|
||||
clip: true
|
||||
interactive: false
|
||||
Row {
|
||||
id: row
|
||||
spacing: 4
|
||||
Repeater {
|
||||
id: inlineTagModelRepeater
|
||||
model: inlineTagModel
|
||||
delegate: inlineTagDelegate
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
StatusBaseText {
|
||||
id: statusListItemTertiaryTitle
|
||||
anchors.top: statusListItemSubTitle.bottom
|
||||
anchors.top: statusListItemSubtitleTagsRow.bottom
|
||||
width: parent.width
|
||||
height: visible ? contentHeight : 0
|
||||
text: statusListItem.tertiaryTitle
|
||||
@@ -317,16 +358,24 @@ Rectangle {
|
||||
implicitHeight: visible ? 22 : 0
|
||||
}
|
||||
|
||||
Row {
|
||||
id: statusListItemTagsSlotInline
|
||||
ScrollView {
|
||||
visible: tagsRepeater.count > 0
|
||||
anchors.top: statusListItemTertiaryTitle.bottom
|
||||
anchors.topMargin: visible? 8 : 0
|
||||
width: parent.width
|
||||
spacing: 10
|
||||
height: visible? contentHeight + 12 : contentHeight
|
||||
clip: true
|
||||
|
||||
Repeater {
|
||||
model: tagsModel
|
||||
delegate: tagsDelegate
|
||||
ScrollBar.vertical.policy: ScrollBar.AlwaysOff
|
||||
|
||||
Row {
|
||||
id: statusListItemTagsSlotInline
|
||||
spacing: 10
|
||||
|
||||
Repeater {
|
||||
id: tagsRepeater
|
||||
delegate: tagsDelegate
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -351,7 +400,7 @@ Rectangle {
|
||||
id: statusListItemLabel
|
||||
anchors.verticalCenter: bottomModel.length === 0 ? parent.verticalCenter : undefined
|
||||
anchors.top: bottomModel.length === 0 ? undefined: parent.top
|
||||
anchors.topMargin: bottomModel.length === 0 ? undefined : 16
|
||||
anchors.topMargin: bottomModel.length === 0 ? 0 : 16
|
||||
anchors.right: statusListItemComponentsSlot.left
|
||||
anchors.rightMargin: statusListItemComponentsSlot.width > 0 ? 10 : 0
|
||||
|
||||
|
||||
@@ -13,17 +13,12 @@ Control {
|
||||
property string primaryText: ""
|
||||
property string secondaryText: ""
|
||||
|
||||
property StatusImageSettings image: StatusImageSettings {
|
||||
height: 16
|
||||
width: 16
|
||||
isIdenticon: false
|
||||
}
|
||||
property StatusIconSettings icon: StatusIconSettings {
|
||||
property StatusAssetSettings asset: StatusAssetSettings {
|
||||
height: 16
|
||||
width: 16
|
||||
isLetterIdenticon: false
|
||||
background: StatusIconBackgroundSettings {}
|
||||
color: "transparent"
|
||||
imgIsIdenticon: false
|
||||
}
|
||||
|
||||
background: Rectangle {
|
||||
@@ -43,22 +38,22 @@ Control {
|
||||
anchors.horizontalCenterOffset: -spacing
|
||||
spacing: 2
|
||||
StatusRoundedImage {
|
||||
implicitWidth: root.image.width
|
||||
implicitHeight: root.image.height
|
||||
visible: !root.icon.isLetterIdenticon
|
||||
image.source: root.image.source
|
||||
implicitWidth: root.asset.width
|
||||
implicitHeight: root.asset.height
|
||||
visible: !root.asset.isLetterIdenticon
|
||||
image.source: root.asset.name
|
||||
border.color: Theme.palette.baseColor1
|
||||
border.width: root.image.isIdenticon ? 1 : 0
|
||||
border.width: root.asset.imgIsIdenticon ? 1 : 0
|
||||
}
|
||||
StatusLetterIdenticon {
|
||||
implicitWidth: root.icon.width
|
||||
implicitHeight: root.icon.width
|
||||
implicitWidth: root.asset.width
|
||||
implicitHeight: root.asset.width
|
||||
letterSize: 11
|
||||
visible: root.icon.isLetterIdenticon
|
||||
color: root.icon.color
|
||||
visible: root.asset.isLetterIdenticon
|
||||
color: root.asset.color
|
||||
name: root.primaryText
|
||||
emoji: root.icon.emoji
|
||||
emojiSize: root.icon.emojiSize
|
||||
emoji: root.asset.emoji
|
||||
emojiSize: root.asset.emojiSize
|
||||
}
|
||||
StatusBaseText {
|
||||
font.weight: Font.Medium
|
||||
|
||||
@@ -6,8 +6,8 @@ import StatusQ.Core.Theme 0.1
|
||||
|
||||
Rectangle {
|
||||
id: root
|
||||
width: layout.width + layout.anchors.margins
|
||||
height: 30
|
||||
implicitWidth: layout.width + layout.anchors.margins
|
||||
implicitHeight: 30
|
||||
color: Theme.palette.primaryColor3
|
||||
radius: 15
|
||||
|
||||
@@ -15,26 +15,19 @@ Rectangle {
|
||||
|
||||
property string title: ""
|
||||
property bool closeButtonVisible: true
|
||||
signal clicked()
|
||||
signal clicked(var mouse)
|
||||
|
||||
property StatusImageSettings image: StatusImageSettings {
|
||||
width: 20
|
||||
height: 20
|
||||
isIdenticon: false
|
||||
}
|
||||
|
||||
property StatusIconSettings icon: StatusIconSettings {
|
||||
property StatusAssetSettings asset: StatusAssetSettings {
|
||||
height: 20
|
||||
width: 20
|
||||
rotation: 0
|
||||
isLetterIdenticon: false
|
||||
letterSize: 10
|
||||
color: Theme.palette.primaryColor1
|
||||
background: StatusIconBackgroundSettings {
|
||||
width: 15
|
||||
height: 15
|
||||
color: Theme.palette.primaryColor3
|
||||
}
|
||||
bgWidth: 15
|
||||
bgHeight: 15
|
||||
bgColor: Theme.palette.primaryColor3
|
||||
imgIsIdenticon: false
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
@@ -45,12 +38,10 @@ Rectangle {
|
||||
StatusSmartIdenticon {
|
||||
id: iconOrImage
|
||||
Layout.leftMargin: 4
|
||||
image: root.image
|
||||
icon: root.icon
|
||||
asset: root.asset
|
||||
name: root.title
|
||||
active: root.icon.isLetterIdenticon ||
|
||||
!!root.icon.name ||
|
||||
!!root.image.source.toString()
|
||||
active: root.asset.isLetterIdenticon ||
|
||||
!!root.asset.name
|
||||
}
|
||||
|
||||
StatusBaseText {
|
||||
@@ -70,9 +61,7 @@ Rectangle {
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onClicked: {
|
||||
root.clicked()
|
||||
}
|
||||
onClicked: root.clicked(mouse)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -294,7 +294,7 @@ Item {
|
||||
bottomPadding: 0
|
||||
placeholderText: root.placeholderSearchText
|
||||
text: root.searchText
|
||||
input.icon.name: "search"
|
||||
input.asset.name: "search"
|
||||
|
||||
onTextChanged: root.searchText = text
|
||||
}
|
||||
@@ -303,11 +303,11 @@ Item {
|
||||
width: content.itemWidth
|
||||
height: content.itemHeight
|
||||
color: mouseArea.containsMouse ? Theme.palette.baseColor4 : "transparent"
|
||||
image: StatusImageSettings {
|
||||
source: root.proxy.imageSource(model) ? root.proxy.imageSource(model) : ""
|
||||
asset: StatusAssetSettings {
|
||||
name: root.proxy.imageSource(model) ? root.proxy.imageSource(model) : ""
|
||||
width: 15
|
||||
height: 15
|
||||
isIdenticon: false
|
||||
imgIsIdenticon: false
|
||||
}
|
||||
name: root.proxy.name(model)
|
||||
shortName: root.proxy.shortName(model)
|
||||
|
||||
@@ -120,7 +120,6 @@ StatusListItem {
|
||||
}
|
||||
subTitle: d.composeSubtitile()
|
||||
statusListItemSubTitle.font.pixelSize: 10
|
||||
icon.isLetterIdenticon: !root.image.source.toString()
|
||||
statusListItemIcon.badge.visible: true
|
||||
statusListItemIcon.badge.color: root.status === 1 ? Theme.palette.successColor1 : Theme.palette.baseColor1 // FIXME
|
||||
color: sensor.containsMouse ? Theme.palette.baseColor2 : Theme.palette.baseColor4
|
||||
@@ -129,10 +128,8 @@ StatusListItem {
|
||||
implicitWidth: 256
|
||||
implicitHeight: Math.max(56, statusListItemTitleArea.height + leftPadding)
|
||||
leftPadding: 8
|
||||
image.width: 32
|
||||
image.height: 32
|
||||
icon.width: 32
|
||||
icon.height: 32
|
||||
asset.width: 32
|
||||
asset.height: 32
|
||||
statusListItemIcon.anchors.verticalCenter: sensor.verticalCenter
|
||||
statusListItemIcon.anchors.top: undefined
|
||||
statusListItemIcon.badge.border.width: 2
|
||||
|
||||
@@ -1,14 +1,16 @@
|
||||
import QtQuick 2.14
|
||||
import QtQuick.Layouts 1.14
|
||||
import QtQuick.Controls 2.14
|
||||
|
||||
import StatusQ.Core 0.1
|
||||
import StatusQ.Core.Theme 0.1
|
||||
import StatusQ.Core.Utils 0.1
|
||||
import StatusQ.Controls 0.1
|
||||
|
||||
import "./private/statusMessage"
|
||||
|
||||
Rectangle {
|
||||
id: statusMessage
|
||||
id: root
|
||||
|
||||
enum ContentType {
|
||||
Unknown = 0,
|
||||
@@ -21,12 +23,12 @@ Rectangle {
|
||||
Invitation = 7
|
||||
}
|
||||
|
||||
property alias messageHeader: messageHeader
|
||||
property alias quickActions:quickActionsPanel.quickActions
|
||||
property alias quickActions: quickActionsPanel.items
|
||||
property alias statusChatInput: editComponent.inputComponent
|
||||
property alias linksComponent: linksLoader.sourceComponent
|
||||
property alias footerComponent: footer.sourceComponent
|
||||
property alias timestamp: messageHeader.timestamp
|
||||
property alias transcationComponent: transactionBubbleLoader.sourceComponent
|
||||
property alias invitationComponent: invitationBubbleLoader.sourceComponent
|
||||
property alias mouseArea: mouseArea
|
||||
|
||||
property string resendText: ""
|
||||
property string cancelButtonText: ""
|
||||
@@ -35,155 +37,397 @@ Rectangle {
|
||||
property string errorLoadingImageText: ""
|
||||
property string audioMessageInfoText: ""
|
||||
property string pinnedMsgInfoText: ""
|
||||
property string messageAttachments: ""
|
||||
property var reactionIcons: [
|
||||
Emoji.iconSource("❤"),
|
||||
Emoji.iconSource("👍"),
|
||||
Emoji.iconSource("👎"),
|
||||
Emoji.iconSource("🤣"),
|
||||
Emoji.iconSource("😥"),
|
||||
Emoji.iconSource("😠")
|
||||
]
|
||||
|
||||
property string messageId: ""
|
||||
property bool isAppWindowActive: false
|
||||
property bool editMode: false
|
||||
property bool isAReply: false
|
||||
property bool isEdited: false
|
||||
property bool isChatBlocked: false
|
||||
|
||||
property bool hasMention: false
|
||||
property bool isPinned: false
|
||||
property string pinnedBy: ""
|
||||
property bool hasExpired: false
|
||||
property double timestamp: 0
|
||||
property var reactionsModel: []
|
||||
|
||||
readonly property bool dateGroupVisible: dateGroupLabel.visible
|
||||
property bool showHeader: true
|
||||
property bool isActiveMessage: false
|
||||
property bool disableHover: false
|
||||
property bool hideQuickActions: false
|
||||
property color overrideBackgroundColor: "transparent"
|
||||
property bool overrideBackground: false
|
||||
property bool profileClickable: true
|
||||
property bool hideMessage: false
|
||||
|
||||
property alias previousMessageIndex: dateGroupLabel.previousMessageIndex
|
||||
property alias previousMessageTimestamp: dateGroupLabel.previousMessageTimestamp
|
||||
|
||||
property StatusMessageDetails messageDetails: StatusMessageDetails {}
|
||||
property StatusMessageDetails replyDetails: StatusMessageDetails {}
|
||||
|
||||
signal profilePictureClicked()
|
||||
signal senderNameClicked()
|
||||
signal editCompleted(var newMsgText)
|
||||
signal replyProfileClicked()
|
||||
signal stickerLoaded()
|
||||
signal imageClicked(var imageSource)
|
||||
property string timestampString: Qt.formatTime(new Date(timestamp), "hh:mm");
|
||||
property string timestampTooltipString: Qt.formatTime(new Date(timestamp), "dddd, MMMM d, yyyy hh:mm:ss t");
|
||||
|
||||
signal clicked(var sender, var mouse)
|
||||
signal profilePictureClicked(var sender, var mouse)
|
||||
signal senderNameClicked(var sender, var mouse)
|
||||
signal replyProfileClicked(var sender, var mouse)
|
||||
|
||||
signal addReactionClicked(var sender, var mouse)
|
||||
signal toggleReactionClicked(int emojiId)
|
||||
signal imageClicked(var image, var mouse, var imageSource)
|
||||
signal stickerClicked()
|
||||
signal resendClicked()
|
||||
|
||||
height: childrenRect.height
|
||||
color: hoverHandler.hovered ? (messageDetails.hasMention ? Theme.palette.mentionColor3 : messageDetails.isPinned ? Theme.palette.pinColor2 : Theme.palette.baseColor2) : messageDetails.hasMention ? Theme.palette.mentionColor4 : messageDetails.isPinned ? Theme.palette.pinColor3 : "transparent"
|
||||
signal editCompleted(var newMsgText)
|
||||
signal editCancelled()
|
||||
signal stickerLoaded()
|
||||
signal linkActivated(string link)
|
||||
|
||||
signal hoverChanged(string messageId, bool hovered)
|
||||
signal activeChanged(string messageId, bool active)
|
||||
|
||||
function startMessageFoundAnimation() {
|
||||
messageFoundAnimation.start();
|
||||
}
|
||||
|
||||
onMessageAttachmentsChanged: {
|
||||
root.prepareAttachmentsModel()
|
||||
}
|
||||
|
||||
function prepareAttachmentsModel() {
|
||||
attachmentsModel.clear()
|
||||
if (!root.messageAttachments) {
|
||||
return
|
||||
}
|
||||
root.messageAttachments.split(" ").forEach(source => {
|
||||
attachmentsModel.append({source})
|
||||
})
|
||||
}
|
||||
|
||||
implicitWidth: messageLayout.implicitWidth
|
||||
+ messageLayout.anchors.leftMargin
|
||||
+ messageLayout.anchors.rightMargin
|
||||
|
||||
implicitHeight: messageLayout.implicitHeight
|
||||
+ messageLayout.anchors.topMargin
|
||||
+ messageLayout.anchors.bottomMargin
|
||||
|
||||
color: {
|
||||
if (root.overrideBackground)
|
||||
return root.overrideBackgroundColor;
|
||||
|
||||
if (root.editMode)
|
||||
return Theme.palette.baseColor2;
|
||||
|
||||
if (hoverHandler.hovered || root.isActiveMessage) {
|
||||
if (root.hasMention)
|
||||
return Theme.palette.mentionColor3;
|
||||
if (root.isPinned)
|
||||
return Theme.palette.pinColor2;
|
||||
return Theme.palette.baseColor2;
|
||||
}
|
||||
|
||||
if (root.hasMention)
|
||||
return Theme.palette.mentionColor4;
|
||||
if (root.isPinned)
|
||||
return Theme.palette.pinColor3;
|
||||
return "transparent";
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
anchors {
|
||||
top: parent.top
|
||||
bottom: parent.bottom
|
||||
left: parent.left
|
||||
}
|
||||
width: 2
|
||||
visible: root.isPinned
|
||||
color: Theme.palette.pinColor1
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
anchors {
|
||||
top: parent.top
|
||||
bottom: parent.bottom
|
||||
left: parent.left
|
||||
}
|
||||
width: 2
|
||||
visible: root.hasMention
|
||||
color: Theme.palette.mentionColor1
|
||||
}
|
||||
|
||||
SequentialAnimation {
|
||||
id: messageFoundAnimation
|
||||
|
||||
PauseAnimation {
|
||||
duration: 600
|
||||
}
|
||||
NumberAnimation {
|
||||
target: highlightRect
|
||||
property: "opacity"
|
||||
to: 1.0
|
||||
duration: 1500
|
||||
}
|
||||
PauseAnimation {
|
||||
duration: 1000
|
||||
}
|
||||
NumberAnimation {
|
||||
target: highlightRect
|
||||
property: "opacity"
|
||||
to: 0.0
|
||||
duration: 1500
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: highlightRect
|
||||
anchors.fill: parent
|
||||
opacity: 0
|
||||
visible: opacity > 0.001
|
||||
color: Theme.palette.baseColor2
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: mouseArea
|
||||
anchors.fill: parent
|
||||
}
|
||||
|
||||
HoverHandler {
|
||||
id: hoverHandler
|
||||
enabled: !root.isActiveMessage && !root.disableHover
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
id: messageLayout
|
||||
width: parent.width
|
||||
StatusMessageReply {
|
||||
anchors.fill: parent
|
||||
anchors.topMargin: 8
|
||||
anchors.bottomMargin: 8
|
||||
|
||||
StatusDateGroupLabel {
|
||||
id: dateGroupLabel
|
||||
Layout.fillWidth: true
|
||||
visible: isAReply
|
||||
replyDetails: statusMessage.replyDetails
|
||||
onReplyProfileClicked: statusMessage.replyProfileClicked()
|
||||
audioMessageInfoText: statusMessage.audioMessageInfoText
|
||||
Layout.topMargin: 20
|
||||
messageTimestamp: root.timestamp
|
||||
visible: text !== ""
|
||||
}
|
||||
RowLayout {
|
||||
spacing: 8
|
||||
|
||||
Loader {
|
||||
Layout.fillWidth: true
|
||||
StatusSmartIdenticon {
|
||||
id: profileImage
|
||||
active: isAReply
|
||||
visible: active
|
||||
sourceComponent: StatusMessageReply {
|
||||
replyDetails: root.replyDetails
|
||||
profileClickable: root.profileClickable
|
||||
onReplyProfileClicked: root.replyProfileClicked(sender, mouse)
|
||||
audioMessageInfoText: root.audioMessageInfoText
|
||||
}
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
Layout.fillWidth: true
|
||||
Layout.leftMargin: 16
|
||||
Layout.rightMargin: 16
|
||||
spacing: 8
|
||||
|
||||
Item {
|
||||
implicitWidth: root.messageDetails.sender.profileImage.assetSettings.width
|
||||
implicitHeight: profileImage.visible ? profileImage.height : 0
|
||||
Layout.alignment: Qt.AlignTop
|
||||
Layout.topMargin: 10
|
||||
Layout.leftMargin: 16
|
||||
image: messageDetails.profileImage
|
||||
name: messageHeader.displayName
|
||||
MouseArea {
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
acceptedButtons: Qt.LeftButton | Qt.RightButton
|
||||
anchors.fill: parent
|
||||
onClicked: statusMessage.profilePictureClicked()
|
||||
StatusSmartIdenticon {
|
||||
id: profileImage
|
||||
active: root.showHeader
|
||||
visible: active
|
||||
name: root.messageDetails.sender.displayName
|
||||
asset: root.messageDetails.sender.profileImage.assetSettings
|
||||
ringSettings: root.messageDetails.sender.profileImage.ringSettings
|
||||
|
||||
MouseArea {
|
||||
cursorShape: enabled ? Qt.PointingHandCursor : Qt.ArrowCursor
|
||||
acceptedButtons: Qt.LeftButton | Qt.RightButton
|
||||
anchors.fill: parent
|
||||
enabled: root.profileClickable
|
||||
onClicked: root.profilePictureClicked(this, mouse)
|
||||
}
|
||||
}
|
||||
}
|
||||
Column {
|
||||
|
||||
ColumnLayout {
|
||||
|
||||
spacing: 4
|
||||
Layout.alignment: Qt.AlignTop
|
||||
Layout.topMargin: 10
|
||||
Layout.fillWidth: true
|
||||
StatusPinMessageDetails {
|
||||
visible: messageDetails.isPinned && !editMode
|
||||
pinnedMsgInfoText: statusMessage.pinnedMsgInfoText
|
||||
pinnedBy: messageDetails.pinnedBy
|
||||
|
||||
Loader {
|
||||
active: root.isPinned && !editMode
|
||||
visible: active
|
||||
sourceComponent: StatusPinMessageDetails {
|
||||
pinnedMsgInfoText: root.pinnedMsgInfoText
|
||||
pinnedBy: root.pinnedBy
|
||||
}
|
||||
}
|
||||
StatusMessageHeader {
|
||||
id: messageHeader
|
||||
width: parent.width
|
||||
displayName: messageDetails.displayName
|
||||
secondaryName: messageDetails.secondaryName
|
||||
tertiaryDetail: messageDetails.chatID
|
||||
isContact: messageDetails.isContact
|
||||
trustIndicator: messageDetails.trustIndicator
|
||||
resendText: statusMessage.resendText
|
||||
showResendButton: messageDetails.hasExpired && messageDetails.amISender
|
||||
onClicked: statusMessage.senderNameClicked()
|
||||
onResendClicked: statusMessage.resendClicked()
|
||||
visible: !editMode
|
||||
Layout.fillWidth: true
|
||||
sender: root.messageDetails.sender
|
||||
amISender: root.messageDetails.amISender
|
||||
messageOriginInfo: root.messageDetails.messageOriginInfo
|
||||
resendText: root.resendText
|
||||
showResendButton: root.hasExpired && root.messageDetails.amISender
|
||||
onClicked: root.senderNameClicked(sender, mouse)
|
||||
onResendClicked: root.resendClicked()
|
||||
visible: root.showHeader && !editMode
|
||||
timestamp.text: root.timestampString
|
||||
timestamp.tooltip.text: root.timestampTooltipString
|
||||
displayNameClickable: root.profileClickable
|
||||
}
|
||||
Loader {
|
||||
active: !editMode && !!messageDetails.messageText
|
||||
width: parent.width
|
||||
Layout.fillWidth: true
|
||||
active: !root.editMode && !!root.messageDetails.messageText && !root.hideMessage
|
||||
visible: active
|
||||
sourceComponent: StatusTextMessage {
|
||||
width: parent.width
|
||||
textField.text: messageDetails.messageText
|
||||
objectName: "StatusMessage_textMessage"
|
||||
textField.text: {
|
||||
if (root.messageDetails.contentType === StatusMessage.ContentType.Sticker)
|
||||
return "";
|
||||
|
||||
const formattedMessage = Utils.linkifyAndXSS(root.messageDetails.messageText);
|
||||
|
||||
if (root.messageDetails.contentType === StatusMessage.ContentType.Emoji)
|
||||
return Emoji.parse(formattedMessage, Emoji.size.middle, Emoji.format.png);
|
||||
|
||||
if (root.isEdited) {
|
||||
const index = formattedMessage.endsWith("code>") ? formattedMessage.length : formattedMessage.length - 4;
|
||||
const editedMessage = formattedMessage.slice(0, index)
|
||||
+ ` <span class="isEdited">` + qsTr("(edited)") + `</span>`
|
||||
+ formattedMessage.slice(index);
|
||||
return Utils.getMessageWithStyle(Emoji.parse(editedMessage), textField.hoveredLink)
|
||||
}
|
||||
|
||||
return Utils.getMessageWithStyle(Emoji.parse(formattedMessage), textField.hoveredLink)
|
||||
}
|
||||
onLinkActivated: {
|
||||
root.linkActivated(link);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Loader {
|
||||
active: messageDetails.contentType === StatusMessage.ContentType.Image && !editMode
|
||||
active: root.messageDetails.contentType === StatusMessage.ContentType.Image && !editMode
|
||||
visible: active
|
||||
sourceComponent: StatusImageMessage {
|
||||
source: messageDetails.contentType === StatusMessage.ContentType.Image ? messageDetails.messageContent : ""
|
||||
onClicked: statusMessage.imageClicked()
|
||||
shapeType: messageDetails.amISender ? StatusImageMessage.ShapeType.RIGHT_ROUNDED : StatusImageMessage.ShapeType.LEFT_ROUNDED
|
||||
source: root.messageDetails.contentType === StatusMessage.ContentType.Image ? root.messageDetails.messageContent : ""
|
||||
onClicked: root.imageClicked(image, mouse, imageSource)
|
||||
shapeType: root.messageDetails.amISender ? StatusImageMessage.ShapeType.RIGHT_ROUNDED : StatusImageMessage.ShapeType.LEFT_ROUNDED
|
||||
}
|
||||
}
|
||||
StatusSticker {
|
||||
visible: messageDetails.contentType === StatusMessage.ContentType.Sticker && !editMode
|
||||
image.source: messageDetails.messageContent
|
||||
onLoaded: statusMessage.stickerLoaded()
|
||||
|
||||
Loader {
|
||||
active: !!root.messageAttachments && !editMode
|
||||
visible: active
|
||||
sourceComponent: Column {
|
||||
spacing: 4
|
||||
Layout.fillWidth: true
|
||||
Repeater {
|
||||
model: attachmentsModel
|
||||
delegate: StatusImageMessage {
|
||||
source: model.source
|
||||
onClicked: root.imageClicked(image, mouse, imageSource)
|
||||
shapeType: root.messageDetails.amISender ? StatusImageMessage.ShapeType.RIGHT_ROUNDED : StatusImageMessage.ShapeType.LEFT_ROUNDED
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loader {
|
||||
active: root.messageDetails.contentType === StatusMessage.ContentType.Sticker && !editMode
|
||||
visible: active
|
||||
sourceComponent: StatusSticker {
|
||||
asset.isImage: true
|
||||
asset.name: root.messageDetails.messageContent
|
||||
onLoaded: root.stickerLoaded()
|
||||
onClicked: {
|
||||
root.stickerClicked()
|
||||
}
|
||||
}
|
||||
}
|
||||
Loader {
|
||||
active: messageDetails.contentType === StatusMessage.ContentType.Audio && !editMode
|
||||
active: root.messageDetails.contentType === StatusMessage.ContentType.Audio && !editMode
|
||||
visible: active
|
||||
sourceComponent: StatusAudioMessage {
|
||||
audioSource: messageDetails.messageContent
|
||||
audioSource: root.messageDetails.messageContent
|
||||
hovered: hoverHandler.hovered
|
||||
audioMessageInfoText: statusMessage.audioMessageInfoText
|
||||
audioMessageInfoText: root.audioMessageInfoText
|
||||
}
|
||||
}
|
||||
Loader {
|
||||
id: linksLoader
|
||||
active: !!linksLoader.sourceComponent
|
||||
active: !root.editMode
|
||||
visible: active
|
||||
}
|
||||
Loader {
|
||||
id: transactionBubbleLoader
|
||||
active: messageDetails.contentType === StatusMessage.ContentType.Transaction && !editMode
|
||||
active: root.messageDetails.contentType === StatusMessage.ContentType.Transaction && !editMode
|
||||
visible: active
|
||||
}
|
||||
Loader {
|
||||
id: invitationBubbleLoader
|
||||
active: messageDetails.contentType === StatusMessage.ContentType.Invitation && !editMode
|
||||
active: root.messageDetails.contentType === StatusMessage.ContentType.Invitation && !editMode
|
||||
visible: active
|
||||
}
|
||||
StatusEditMessage {
|
||||
id: editComponent
|
||||
width: parent.width
|
||||
msgText: messageDetails.messageText
|
||||
visible: editMode
|
||||
saveButtonText: statusMessage.saveButtonText
|
||||
cancelButtonText: statusMessage.cancelButtonText
|
||||
onCancelEditClicked: editMode = false
|
||||
onEditCompleted: {
|
||||
editMode = false
|
||||
statusMessage.editCompleted(newMsgText)
|
||||
}
|
||||
Layout.fillWidth: true
|
||||
Layout.rightMargin: 16
|
||||
active: root.editMode
|
||||
visible: active
|
||||
msgText: root.messageDetails.messageText
|
||||
saveButtonText: root.saveButtonText
|
||||
cancelButtonText: root.cancelButtonText
|
||||
onEditCancelled: root.editCancelled()
|
||||
onEditCompleted: root.editCompleted(newMsgText)
|
||||
}
|
||||
StatusBaseText {
|
||||
id: retryLbl
|
||||
color: Theme.palette.dangerColor1
|
||||
text: statusMessage.resendText
|
||||
text: root.resendText
|
||||
font.pixelSize: 12
|
||||
visible: messageDetails.hasExpired && messageDetails.amISender && !messageDetails.timestamp && !editMode
|
||||
visible: root.hasExpired && root.messageDetails.amISender && !root.timestamp && !editMode
|
||||
MouseArea {
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
anchors.fill: parent
|
||||
onClicked: statusMessage.resendClicked()
|
||||
onClicked: root.resendClicked()
|
||||
}
|
||||
}
|
||||
Loader {
|
||||
id: footer
|
||||
active: sourceComponent && !editMode
|
||||
active: root.reactionsModel.count > 0
|
||||
visible: active
|
||||
sourceComponent: StatusMessageEmojiReactions {
|
||||
id: emojiReactionsPanel
|
||||
|
||||
emojiReactionsModel: root.reactionsModel
|
||||
store: root.messageStore
|
||||
icons: root.reactionIcons
|
||||
|
||||
onHoverChanged: {
|
||||
root.hoverChanged(messageId, hovered)
|
||||
}
|
||||
|
||||
isCurrentUser: root.messageDetails.amISender
|
||||
onAddEmojiClicked: root.addReactionClicked(sender, mouse)
|
||||
onToggleReaction: root.toggleReactionClicked(emojiID)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -195,6 +439,13 @@ Rectangle {
|
||||
anchors.rightMargin: 20
|
||||
anchors.top: parent.top
|
||||
anchors.topMargin: -8
|
||||
visible: hoverHandler.hovered && !editMode
|
||||
visible: hoverHandler.hovered && !root.hideQuickActions
|
||||
}
|
||||
|
||||
ListModel {
|
||||
id: attachmentsModel
|
||||
Component.onCompleted: {
|
||||
root.prepareAttachmentsModel()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,24 +6,10 @@ QtObject {
|
||||
id: msgDetails
|
||||
|
||||
property bool amISender: false
|
||||
property string displayName: ""
|
||||
property string secondaryName: ""
|
||||
property string chatID: ""
|
||||
property StatusImageSettings profileImage: StatusImageSettings {
|
||||
width: 40
|
||||
height: 40
|
||||
}
|
||||
property StatusMessageSenderDetails sender: StatusMessageSenderDetails { }
|
||||
property bool isEdited: false
|
||||
property string messageText: ""
|
||||
property int contentType: 0
|
||||
property string messageText: ""
|
||||
property string messageContent: ""
|
||||
property bool isContact: false
|
||||
property var trustIndicator: StatusContactVerificationIcons.TrustedType.None
|
||||
property bool hasMention: false
|
||||
property bool isPinned: false
|
||||
property string pinnedBy: ""
|
||||
property bool hasExpired: false
|
||||
property string timestamp: ""
|
||||
property string messageOriginInfo: ""
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
import QtQuick 2.0
|
||||
import StatusQ.Core 0.1
|
||||
|
||||
QtObject {
|
||||
id: root
|
||||
|
||||
property string id: ""
|
||||
property string displayName: ""
|
||||
property string secondaryName: ""
|
||||
|
||||
property bool isEnsVerified: false
|
||||
property bool isContact: false
|
||||
property int trustIndicator: StatusContactVerificationIcons.TrustedType.None
|
||||
|
||||
property StatusProfileImageSettings profileImage: StatusProfileImageSettings {
|
||||
pubkey: root.id
|
||||
showRing: !root.isEnsVerified
|
||||
width: 40
|
||||
height: 40
|
||||
}
|
||||
}
|
||||
@@ -12,9 +12,9 @@ StatusListItem {
|
||||
implicitWidth: 286
|
||||
implicitHeight: 48
|
||||
|
||||
icon.background.width: 20
|
||||
icon.background.height: 20
|
||||
icon.background.color: "transparent"
|
||||
asset.bgWidth: 20
|
||||
asset.bgHeight: 20
|
||||
asset.bgColor: "transparent"
|
||||
|
||||
statusListItemIcon.anchors.topMargin: 14
|
||||
|
||||
|
||||
@@ -5,33 +5,31 @@ import StatusQ.Core.Theme 0.1
|
||||
Rectangle {
|
||||
id: statusRoundedIcon
|
||||
|
||||
property StatusIconSettings icon: StatusIconSettings {
|
||||
property StatusAssetSettings asset: StatusAssetSettings {
|
||||
width: 24
|
||||
height: 24
|
||||
rotation: 0
|
||||
color: Theme.palette.primaryColor1
|
||||
background: StatusIconBackgroundSettings {
|
||||
width: 40
|
||||
height: 40
|
||||
color: Theme.palette.primaryColor3
|
||||
}
|
||||
bgWidth: 40
|
||||
bgHeight: 40
|
||||
bgColor: Theme.palette.primaryColor3
|
||||
}
|
||||
|
||||
color: icon.background.color
|
||||
implicitWidth: icon.background.width
|
||||
implicitHeight: icon.background.height
|
||||
radius: icon.background.width / 2
|
||||
color: asset.bgColor
|
||||
implicitWidth: asset.bgWidth
|
||||
implicitHeight: asset.bgHeight
|
||||
radius: asset.bgWidth / 2
|
||||
|
||||
|
||||
StatusIcon {
|
||||
id: statusIcon
|
||||
anchors.centerIn: parent
|
||||
|
||||
width: statusRoundedIcon.icon.width
|
||||
height: statusRoundedIcon.icon.height
|
||||
width: statusRoundedIcon.asset.width
|
||||
height: statusRoundedIcon.asset.height
|
||||
|
||||
color: statusRoundedIcon.icon.color
|
||||
icon: statusRoundedIcon.icon.name
|
||||
rotation: statusRoundedIcon.icon.rotation
|
||||
color: statusRoundedIcon.asset.color
|
||||
icon: statusRoundedIcon.asset.name
|
||||
rotation: statusRoundedIcon.asset.rotation
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ import StatusQ.Core.Theme 0.1
|
||||
import StatusQ.Controls 0.1
|
||||
|
||||
Loader {
|
||||
id: statusSmartIdenticon
|
||||
id: root
|
||||
|
||||
property string name: ""
|
||||
property int dZ: 100
|
||||
@@ -12,51 +12,46 @@ Loader {
|
||||
// Badge color properties must be set if badgeItem.visible = true
|
||||
property alias badge: statusBadge
|
||||
|
||||
property StatusIconSettings icon: StatusIconSettings {
|
||||
width: 40
|
||||
height: 40
|
||||
}
|
||||
|
||||
property StatusImageSettings image: StatusImageSettings {
|
||||
property StatusAssetSettings asset: StatusAssetSettings {
|
||||
width: 40
|
||||
height: 40
|
||||
}
|
||||
|
||||
property StatusIdenticonRingSettings ringSettings: StatusIdenticonRingSettings {
|
||||
initalAngleRad: 0
|
||||
ringPxSize: Math.max(1.5, statusSmartIdenticon.image.width / 24.0)
|
||||
ringPxSize: Math.max(1.5, root.asset.width/ 24.0)
|
||||
distinctiveColors: Theme.palette.identiconRingColors
|
||||
}
|
||||
|
||||
sourceComponent: statusSmartIdenticon.icon.isLetterIdenticon ? letterIdenticon :
|
||||
!!statusSmartIdenticon.image.source.toString() ? roundedImage :
|
||||
!!statusSmartIdenticon.icon.name.toString() ? roundedIcon : letterIdenticon
|
||||
sourceComponent: (root.asset.isLetterIdenticon || root.asset.name === "") ? letterIdenticon :
|
||||
!root.asset.isImage ? roundedIcon : roundedImage
|
||||
|
||||
Component {
|
||||
id: roundedImage
|
||||
Item {
|
||||
width: statusSmartIdenticon.image.width
|
||||
height: statusSmartIdenticon.image.height
|
||||
width: root.asset.width
|
||||
height: root.asset.height
|
||||
StatusRoundedImage {
|
||||
id: statusRoundImage
|
||||
width: parent.width
|
||||
height: parent.height
|
||||
image.source: statusSmartIdenticon.image.source
|
||||
image.source: root.asset.name
|
||||
showLoadingIndicator: true
|
||||
border.width: statusSmartIdenticon.image.isIdenticon ? 1 : 0
|
||||
border.width: root.asset.imgIsIdenticon ? 1 : 0
|
||||
border.color: Theme.palette.directColor7
|
||||
color: statusSmartIdenticon.image.isIdenticon ?
|
||||
color: root.asset.imgIsIdenticon ?
|
||||
Theme.palette.statusRoundedImage.backgroundColor :
|
||||
"transparent"
|
||||
}
|
||||
Loader {
|
||||
anchors.centerIn: parent
|
||||
active: statusRoundImage.image.status === Image.Error
|
||||
active: root.asset.imgStatus === Image.Error ||
|
||||
statusRoundImage.image.status === Image.Error
|
||||
sourceComponent: letterIdenticon
|
||||
onLoaded: {
|
||||
item.color = Theme.palette.miscColor5
|
||||
item.width = statusSmartIdenticon.image.width
|
||||
item.height = statusSmartIdenticon.image.height
|
||||
item.width = root.asset.width
|
||||
item.height = root.asset.height
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -65,14 +60,14 @@ Loader {
|
||||
Component {
|
||||
id: roundedIcon
|
||||
StatusRoundIcon {
|
||||
icon.background.width: statusSmartIdenticon.icon.background.width
|
||||
icon.background.height: statusSmartIdenticon.icon.background.height
|
||||
icon.background.color: statusSmartIdenticon.icon.background.color
|
||||
icon.width: statusSmartIdenticon.icon.width
|
||||
icon.height: statusSmartIdenticon.icon.height
|
||||
icon.name: statusSmartIdenticon.icon.name
|
||||
icon.rotation: statusSmartIdenticon.icon.rotation
|
||||
icon.color: statusSmartIdenticon.icon.color
|
||||
asset.bgWidth: root.asset.bgWidth
|
||||
asset.bgHeight: root.asset.bgHeight
|
||||
asset.bgColor: root.asset.bgColor
|
||||
asset.width: root.asset.width
|
||||
asset.height: root.asset.height
|
||||
asset.name: root.asset.name
|
||||
asset.rotation: root.asset.rotation
|
||||
asset.color: root.asset.color
|
||||
}
|
||||
}
|
||||
|
||||
@@ -80,33 +75,35 @@ Loader {
|
||||
id: letterIdenticon
|
||||
StatusLetterIdenticon {
|
||||
objectName: "statusSmartIdenticonLetter"
|
||||
width: statusSmartIdenticon.icon.width
|
||||
height: statusSmartIdenticon.icon.height
|
||||
color: statusSmartIdenticon.icon.color
|
||||
name: statusSmartIdenticon.name
|
||||
emoji: statusSmartIdenticon.icon.emoji
|
||||
emojiSize: statusSmartIdenticon.icon.emojiSize
|
||||
letterSize: statusSmartIdenticon.icon.letterSize
|
||||
charactersLen: statusSmartIdenticon.icon.charactersLen
|
||||
width: root.asset.width
|
||||
height: root.asset.height
|
||||
color: root.asset.color
|
||||
name: root.name
|
||||
emoji: root.asset.emoji
|
||||
emojiSize: root.asset.emojiSize
|
||||
letterSize: root.asset.letterSize
|
||||
charactersLen: root.asset.charactersLen
|
||||
}
|
||||
}
|
||||
|
||||
// Next components are painted above main sourceComponent
|
||||
StatusIdenticonRing {
|
||||
settings: statusSmartIdenticon.ringSettings
|
||||
settings: root.ringSettings
|
||||
anchors.fill: parent
|
||||
z: statusSmartIdenticon.dZ/2
|
||||
z: root.dZ/2
|
||||
}
|
||||
|
||||
// State component
|
||||
StatusBadge {
|
||||
id: statusBadge
|
||||
visible: false
|
||||
anchors.bottom: statusSmartIdenticon.bottom
|
||||
anchors.right: statusSmartIdenticon.right
|
||||
anchors.bottom: root.bottom
|
||||
anchors.right: root.right
|
||||
anchors.rightMargin: -border.width
|
||||
anchors.bottomMargin: -border.width
|
||||
border.width: 3
|
||||
implicitHeight: 15
|
||||
implicitWidth: 15
|
||||
z: statusSmartIdenticon.dZ
|
||||
z: root.dZ
|
||||
}
|
||||
}
|
||||
|
||||
@@ -180,6 +180,7 @@ Item {
|
||||
"isContact": entry.isContact,
|
||||
"ringSpecModel": entry.ringSpecModel,
|
||||
"icon": entry.icon,
|
||||
"isImage": entry.isImage,
|
||||
"onlineStatus": entry.onlineStatus,
|
||||
"tagIcon": entry.tagIcon ? entry.tagIcon : "",
|
||||
"isReadonly": !!entry.isReadonly});
|
||||
@@ -305,8 +306,11 @@ Item {
|
||||
if ((event.key === Qt.Key_Backspace || event.key === Qt.Key_Escape)
|
||||
&& getText(cursorPosition, (cursorPosition-1)) === ""
|
||||
&& (namesList.count-1) >= 0) {
|
||||
removeMember(namesModel.get(namesList.count-1).pubKey);
|
||||
namesModel.remove((namesList.count-1), 1);
|
||||
const item = namesModel.get(namesList.count-1)
|
||||
if (!item.isReadonly) {
|
||||
removeMember(item.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,
|
||||
@@ -412,9 +416,10 @@ Item {
|
||||
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)]
|
||||
asset.name: model.icon
|
||||
asset.color: Theme.palette.userCustomizationColors[root.colorIdForPubkeyGetter(model.pubKey)]
|
||||
asset.isImage: (asset.name !== "")
|
||||
asset.isLetterIdenticon: (asset.name === "")
|
||||
status: model.onlineStatus
|
||||
statusListItemIcon.badge.border.color: sensor.containsMouse ? Theme.palette.baseColor2 : Theme.palette.baseColor4
|
||||
ringSettings.ringSpecModel: root.ringSpecModelGetter(model.pubKey)
|
||||
|
||||
@@ -75,10 +75,10 @@ Control {
|
||||
property int duration: 0
|
||||
|
||||
/*!
|
||||
\qmlproperty StatusIconSettings StatusToastMessage::icon
|
||||
\qmlproperty StatusAssetSettings StatusToastMessage::icon
|
||||
This property holds a set of settings for the icon of the ToastMessage.
|
||||
*/
|
||||
property StatusIconSettings icon: StatusIconSettings {
|
||||
property StatusAssetSettings icon: StatusAssetSettings {
|
||||
width: 23
|
||||
height: 23
|
||||
}
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
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
|
||||
|
||||
ToolBar {
|
||||
id: root
|
||||
|
||||
property string backButtonName: ""
|
||||
property int notificationCount: 0
|
||||
property Item headerContent
|
||||
property alias notificationButton: notificationButton
|
||||
|
||||
signal backButtonClicked()
|
||||
signal notificationButtonClicked()
|
||||
|
||||
implicitWidth: visible ? 518 : 0
|
||||
implicitHeight: visible ? 60 : 0
|
||||
padding: 8
|
||||
background: null
|
||||
|
||||
RowLayout {
|
||||
anchors.fill: parent
|
||||
spacing: 0
|
||||
StatusFlatButton {
|
||||
icon.name: "arrow-left"
|
||||
icon.width: 20
|
||||
icon.height: 20
|
||||
Layout.alignment: Qt.AlignLeft | Qt.AlignVCenter
|
||||
Layout.leftMargin: 12
|
||||
visible: !!root.backButtonName
|
||||
text: root.backButtonName
|
||||
size: StatusBaseButton.Size.Large
|
||||
onClicked: { root.backButtonClicked(); }
|
||||
}
|
||||
|
||||
Control {
|
||||
id: headerContentItem
|
||||
Layout.fillWidth: !!headerContent
|
||||
Layout.fillHeight: !!headerContent
|
||||
background: null
|
||||
contentItem: (!!headerContent) ? headerContent : null
|
||||
}
|
||||
|
||||
Item {
|
||||
Layout.fillWidth: !headerContent
|
||||
}
|
||||
|
||||
StatusActivityCenterButton {
|
||||
id: notificationButton
|
||||
unreadNotificationsCount: root.notificationCount
|
||||
onClicked: root.notificationButtonClicked()
|
||||
}
|
||||
}
|
||||
}
|
||||
+20787
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,139 @@
|
||||
/*!
|
||||
* Elypson's Chart.qml adaptor to Chart.js
|
||||
* (c) 2020 ChartJs2QML contributors (starting with Elypson, Michael A. Voelkel, https://github.com/Elypson)
|
||||
* Released under the MIT License
|
||||
*/
|
||||
|
||||
import QtQuick 2.13
|
||||
import "Chart.js" as Chart
|
||||
|
||||
Canvas {
|
||||
id: root
|
||||
|
||||
property var jsChart: undefined
|
||||
property string chartType
|
||||
property var chartData
|
||||
property var chartOptions
|
||||
property double chartAnimationProgress: 0.1
|
||||
property var animationEasingType: Easing.InOutExpo
|
||||
property double animationDuration: 500
|
||||
property var memorizedContext
|
||||
property var memorizedData
|
||||
property var memorizedOptions
|
||||
property alias animationRunning: chartAnimator.running
|
||||
|
||||
signal animationFinished()
|
||||
|
||||
function animateToNewData()
|
||||
{
|
||||
chartAnimationProgress = 0.1;
|
||||
jsChart.update();
|
||||
chartAnimator.restart();
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: event
|
||||
anchors.fill: root
|
||||
hoverEnabled: true
|
||||
enabled: true
|
||||
property var handler: undefined
|
||||
|
||||
property QtObject mouseEvent: QtObject {
|
||||
property int left: 0
|
||||
property int top: 0
|
||||
property int x: 0
|
||||
property int y: 0
|
||||
property int clientX: 0
|
||||
property int clientY: 0
|
||||
property string type: ""
|
||||
property var target
|
||||
}
|
||||
|
||||
function submitEvent(mouse, type) {
|
||||
mouseEvent.type = type
|
||||
mouseEvent.clientX = mouse ? mouse.x : 0;
|
||||
mouseEvent.clientY = mouse ? mouse.y : 0;
|
||||
mouseEvent.x = mouse ? mouse.x : 0;
|
||||
mouseEvent.y = mouse ? mouse.y : 0;
|
||||
mouseEvent.left = 0;
|
||||
mouseEvent.top = 0;
|
||||
mouseEvent.target = root;
|
||||
|
||||
if(handler) {
|
||||
handler(mouseEvent);
|
||||
}
|
||||
|
||||
root.requestPaint();
|
||||
}
|
||||
|
||||
onClicked: {
|
||||
submitEvent(mouse, "click");
|
||||
}
|
||||
onPositionChanged: {
|
||||
submitEvent(mouse, "mousemove");
|
||||
}
|
||||
onExited: {
|
||||
submitEvent(undefined, "mouseout");
|
||||
}
|
||||
onEntered: {
|
||||
submitEvent(undefined, "mouseenter");
|
||||
}
|
||||
onPressed: {
|
||||
submitEvent(mouse, "mousedown");
|
||||
}
|
||||
onReleased: {
|
||||
submitEvent(mouse, "mouseup");
|
||||
}
|
||||
}
|
||||
|
||||
PropertyAnimation {
|
||||
id: chartAnimator
|
||||
target: root
|
||||
property: "chartAnimationProgress"
|
||||
alwaysRunToEnd: true
|
||||
to: 1
|
||||
duration: root.animationDuration
|
||||
easing.type: root.animationEasingType
|
||||
onFinished: {
|
||||
root.animationFinished();
|
||||
}
|
||||
}
|
||||
|
||||
onChartAnimationProgressChanged: {
|
||||
root.requestPaint();
|
||||
}
|
||||
|
||||
onPaint: {
|
||||
if(root.getContext('2d') != null && memorizedContext != root.getContext('2d') || memorizedData != root.chartData || memorizedOptions != root.chartOptions) {
|
||||
var ctx = root.getContext('2d');
|
||||
|
||||
jsChart = new Chart.build(ctx, {
|
||||
type: root.chartType,
|
||||
data: root.chartData,
|
||||
options: root.chartOptions
|
||||
});
|
||||
|
||||
memorizedData = root.chartData ;
|
||||
memorizedContext = root.getContext('2d');
|
||||
memorizedOptions = root.chartOptions;
|
||||
|
||||
root.jsChart.bindEvents(function(newHandler) {event.handler = newHandler;});
|
||||
|
||||
chartAnimator.start();
|
||||
}
|
||||
|
||||
jsChart.draw(chartAnimationProgress);
|
||||
}
|
||||
|
||||
onWidthChanged: {
|
||||
if(jsChart) {
|
||||
jsChart.resize();
|
||||
}
|
||||
}
|
||||
|
||||
onHeightChanged: {
|
||||
if(jsChart) {
|
||||
jsChart.resize();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2020 ChartJs2QML contributors (starting with Elypson, Michael A. Voelkel, https://github.com/Elypson)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
@@ -6,45 +6,63 @@ import StatusQ.Core.Theme 0.1
|
||||
import StatusQ.Controls 0.1
|
||||
|
||||
Item {
|
||||
id: editText
|
||||
id: root
|
||||
|
||||
property alias inputComponent: chatInputLoader.sourceComponent
|
||||
property alias active: chatInputLoader.active
|
||||
|
||||
property string cancelButtonText: ""
|
||||
property string saveButtonText: ""
|
||||
property string msgText: ""
|
||||
|
||||
signal cancelEditClicked()
|
||||
signal editCancelled()
|
||||
signal editCompleted(var newMsgText)
|
||||
|
||||
height: childrenRect.height
|
||||
implicitHeight: layout.implicitHeight
|
||||
implicitWidth: layout.implicitWidth
|
||||
|
||||
ColumnLayout {
|
||||
id: layout
|
||||
|
||||
anchors.fill: parent
|
||||
spacing: 4
|
||||
|
||||
Loader {
|
||||
id: chatInputLoader
|
||||
// To-Do: Move to StatusChatInput once its moved to StatusQ
|
||||
Layout.fillWidth: true
|
||||
|
||||
/*
|
||||
NOTE: sourceComponent must have `messageText` property
|
||||
TODO: Replace with StatusChatInput once its moved to StatusQ.
|
||||
*/
|
||||
|
||||
sourceComponent: StatusInput {
|
||||
width: editText.width
|
||||
placeholderText: ""
|
||||
readonly property string messageText: input.text
|
||||
width: parent.width
|
||||
input.placeholderText: ""
|
||||
input.text: msgText
|
||||
maximumHeight: 40
|
||||
}
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
spacing: 4
|
||||
StatusFlatButton {
|
||||
id: cancelBtn
|
||||
text: cancelButtonText
|
||||
size: StatusBaseButton.Size.Small
|
||||
onClicked: cancelEditClicked()
|
||||
onClicked: {
|
||||
editCancelled()
|
||||
}
|
||||
}
|
||||
StatusButton {
|
||||
id: saveBtn
|
||||
text: saveButtonText
|
||||
size: StatusBaseButton.Size.Small
|
||||
enabled: chatInputLoader.item.input.text.trim().length > 0
|
||||
onClicked: editCompleted(chatInputLoader.item.input.text)
|
||||
enabled: !!chatInputLoader.item && chatInputLoader.item.messageText.trim().length > 0
|
||||
onClicked: {
|
||||
editCompleted(!chatInputLoader.item ? "" : chatInputLoader.item.messageText)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,10 +25,10 @@ Item {
|
||||
property string loadingImageText: ""
|
||||
property string errorLoadingImageText: ""
|
||||
|
||||
signal clicked(var image, var mouse)
|
||||
signal clicked(var image, var mouse, var imageSource)
|
||||
|
||||
width: loadingImage.visible ? loadingImage.width : imageMessage.width
|
||||
height: loadingImage.visible ? loadingImage.height : imageMessage.paintedHeight
|
||||
implicitWidth: loadingImage.visible ? loadingImage.width : imageMessage.width
|
||||
implicitHeight: loadingImage.visible ? loadingImage.height : imageMessage.paintedHeight
|
||||
|
||||
QtObject {
|
||||
id: _internal
|
||||
@@ -87,7 +87,7 @@ Item {
|
||||
_internal.pausePlaying = ! _internal.pausePlaying
|
||||
return
|
||||
}
|
||||
imageContainer.clicked(imageMessage, mouse)
|
||||
imageContainer.clicked(imageMessage, mouse, imageMessage.source)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,191 @@
|
||||
import QtQuick 2.3
|
||||
import QtQuick.Controls 2.13
|
||||
import QtQuick.Layouts 1.14
|
||||
import QtGraphicalEffects 1.13
|
||||
|
||||
import StatusQ.Core 0.1
|
||||
import StatusQ.Core.Theme 0.1
|
||||
import StatusQ.Core.Utils 0.1
|
||||
import StatusQ.Controls 0.1
|
||||
import StatusQ.Components 0.1
|
||||
|
||||
Item {
|
||||
id: root
|
||||
|
||||
implicitHeight: 22
|
||||
implicitWidth: childrenRect.width
|
||||
|
||||
property int imageMargin: 4
|
||||
signal addEmojiClicked(var sender, var mouse)
|
||||
signal hoverChanged(bool hovered)
|
||||
signal toggleReaction(int emojiID)
|
||||
|
||||
property var store
|
||||
property bool isCurrentUser
|
||||
property var emojiReactionsModel
|
||||
|
||||
property var icons: []
|
||||
|
||||
QtObject {
|
||||
id: d
|
||||
|
||||
function lastTwoItems(nodes) {
|
||||
return nodes.join(qsTr(" and "));
|
||||
}
|
||||
|
||||
function showReactionAuthors(jsonArrayOfUsersReactedWithThisEmoji, emojiId) {
|
||||
const listOfUsers = JSON.parse(jsonArrayOfUsersReactedWithThisEmoji)
|
||||
if (listOfUsers.error) {
|
||||
console.error("error parsing users who reacted to a message, error: ", obj.error)
|
||||
return
|
||||
}
|
||||
|
||||
let author;
|
||||
if (listOfUsers.length === 1) {
|
||||
author = listOfUsers[0]
|
||||
} else if (listOfUsers.length === 2) {
|
||||
author = lastTwoItems(listOfUsers);
|
||||
} else {
|
||||
var leftNode = [];
|
||||
var rightNode = [];
|
||||
const maxReactions = 12
|
||||
let maximum = Math.min(maxReactions, listOfUsers.length)
|
||||
|
||||
if (listOfUsers.length > maxReactions) {
|
||||
leftNode = listOfUsers.slice(0, maxReactions);
|
||||
rightNode = listOfUsers.slice(maxReactions, listOfUsers.length);
|
||||
return (rightNode.length === 1) ?
|
||||
lastTwoItems([leftNode.join(", "), rightNode[0]]) :
|
||||
lastTwoItems([leftNode.join(", "), qsTr("%1 more").arg(rightNode.length)]);
|
||||
}
|
||||
|
||||
leftNode = listOfUsers.slice(0, maximum - 1);
|
||||
rightNode = listOfUsers.slice(maximum - 1, listOfUsers.length);
|
||||
author = lastTwoItems([leftNode.join(", "), rightNode[0]])
|
||||
}
|
||||
return qsTr("%1 reacted with %2")
|
||||
.arg(author)
|
||||
.arg(Emoji.getEmojiFromId(emojiId));
|
||||
}
|
||||
}
|
||||
|
||||
Row {
|
||||
spacing: root.imageMargin
|
||||
|
||||
Repeater {
|
||||
id: reactionRepeater
|
||||
|
||||
width: childrenRect.width
|
||||
model: root.emojiReactionsModel
|
||||
|
||||
Control {
|
||||
id: reactionDelegate
|
||||
|
||||
topPadding: 2
|
||||
bottomPadding: 2
|
||||
leftPadding: 2
|
||||
rightPadding: 6
|
||||
|
||||
background: Rectangle {
|
||||
radius: 10
|
||||
color: model.didIReactWithThisEmoji
|
||||
? (reactionDelegate.hovered ? Theme.palette.statusMessage.emojiReactionActiveBackgroundHovered
|
||||
: Theme.palette.statusMessage.emojiReactionActiveBackground)
|
||||
: (reactionDelegate.hovered ? Theme.palette.statusMessage.emojiReactionBackgroundHovered
|
||||
: Theme.palette.statusMessage.emojiReactionBackground)
|
||||
|
||||
// Rounded corner to cover one corner
|
||||
Rectangle {
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
width: 10
|
||||
height: 10
|
||||
radius: 2
|
||||
color: parent.color
|
||||
}
|
||||
}
|
||||
|
||||
contentItem: Row {
|
||||
spacing: 4
|
||||
|
||||
StatusEmoji {
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
width: 15
|
||||
height: 15
|
||||
|
||||
source: {
|
||||
if (model.emojiId >= 1 && model.emojiId <= root.icons.length)
|
||||
return root.icons[model.emojiId - 1];
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
StatusBaseText {
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
text: model.numberOfReactions
|
||||
font.pixelSize: 12
|
||||
color: model.didIReactWithThisEmoji ? Theme.palette.indirectColor1 : Theme.palette.directColor1
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
StatusToolTip {
|
||||
visible: reactionDelegate.hovered
|
||||
maxWidth: 400
|
||||
text: d.showReactionAuthors(model.jsonArrayOfUsersReactedWithThisEmoji, model.emojiId)
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: mouseArea
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onEntered: {
|
||||
root.hoverChanged(true)
|
||||
}
|
||||
onExited: {
|
||||
root.hoverChanged(false)
|
||||
}
|
||||
onClicked: {
|
||||
root.toggleReaction(model.emojiId)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
width: addEmojiButton.width + addEmojiButton.anchors.leftMargin // there is more margin between the button and the emojis than between each emoji
|
||||
height: addEmojiButton.height
|
||||
|
||||
StatusIcon {
|
||||
id: addEmojiButton
|
||||
|
||||
readonly property bool isHovered: addEmojiButtonMouseArea.containsMouse
|
||||
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: 2.5
|
||||
|
||||
icon: "reaction-b"
|
||||
width: 16.5
|
||||
height: 16.5
|
||||
|
||||
color: addEmojiButton.isHovered ? Theme.palette.primaryColor1 : Theme.palette.baseColor1
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: addEmojiButtonMouseArea
|
||||
anchors.fill: addEmojiButton
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
hoverEnabled: true
|
||||
onClicked: {
|
||||
root.addEmojiClicked(this, mouse);
|
||||
}
|
||||
}
|
||||
|
||||
StatusToolTip {
|
||||
visible: addEmojiButton.isHovered
|
||||
text: qsTr("Add reaction")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,36 +3,41 @@ import QtQuick.Layouts 1.14
|
||||
|
||||
import StatusQ.Core 0.1
|
||||
import StatusQ.Core.Theme 0.1
|
||||
import StatusQ.Core.Utils 0.1
|
||||
import StatusQ.Components 0.1
|
||||
import StatusQ.Controls 0.1
|
||||
|
||||
Item {
|
||||
id: statusMessageHeader
|
||||
id: root
|
||||
|
||||
property StatusMessageSenderDetails sender: StatusMessageSenderDetails { }
|
||||
|
||||
property alias displayNameLabel: primaryDisplayName
|
||||
property alias secondaryNameLabel: secondaryDisplayName
|
||||
property alias tertiaryDetailsLabel: tertiaryDetailText
|
||||
property alias timestamp: timestampText
|
||||
|
||||
property string displayName: ""
|
||||
property string secondaryName: ""
|
||||
property string tertiaryDetail: ""
|
||||
property string tertiaryDetail: sender.id
|
||||
property string resendText: ""
|
||||
property bool showResendButton: false
|
||||
property bool isContact: false
|
||||
property var trustIndicator: StatusContactVerificationIcons.TrustedType.None
|
||||
property bool isContact: sender.isContact
|
||||
property int trustIndicator: sender.trustIndicator
|
||||
property bool amISender: false
|
||||
property bool displayNameClickable: true
|
||||
property string messageOriginInfo: ""
|
||||
|
||||
signal clicked()
|
||||
signal clicked(var sender, var mouse)
|
||||
signal resendClicked()
|
||||
|
||||
height: childrenRect.height
|
||||
width: primaryDisplayName.width + (secondaryDisplayName.visible ? secondaryDisplayName.width + header.spacing : 0)
|
||||
implicitHeight: layout.implicitHeight
|
||||
implicitWidth: layout.implicitWidth
|
||||
|
||||
RowLayout {
|
||||
id: header
|
||||
id: layout
|
||||
spacing: 4
|
||||
TextEdit {
|
||||
id: primaryDisplayName
|
||||
Layout.alignment: Qt.AlignBottom
|
||||
font.family: Theme.palette.baseFont.name
|
||||
font.weight: Font.Medium
|
||||
font.pixelSize: 15
|
||||
@@ -41,55 +46,62 @@ Item {
|
||||
wrapMode: Text.WordWrap
|
||||
selectByMouse: true
|
||||
color: Theme.palette.primaryColor1
|
||||
text: displayName
|
||||
text: root.amISender ? qsTr("You") : root.sender.displayName
|
||||
MouseArea {
|
||||
id: mouseArea
|
||||
anchors.fill: parent
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
cursorShape: enabled ? Qt.PointingHandCursor : Qt.ArrowCursor
|
||||
acceptedButtons: Qt.LeftButton | Qt.RightButton
|
||||
enabled: root.displayNameClickable
|
||||
hoverEnabled: true
|
||||
onClicked: {
|
||||
statusMessageHeader.clicked()
|
||||
root.clicked(this, mouse)
|
||||
}
|
||||
}
|
||||
Layout.alignment: Qt.AlignBottom
|
||||
}
|
||||
StatusBaseText {
|
||||
id: messageOriginInfo
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
visible: root.messageOriginInfo !== ""
|
||||
color: Theme.palette.baseColor1
|
||||
font.pixelSize: 10
|
||||
text: root.messageOriginInfo
|
||||
}
|
||||
StatusContactVerificationIcons {
|
||||
isContact: statusMessageHeader.isContact
|
||||
trustIndicator: statusMessageHeader.trustIndicator
|
||||
visible: !root.amISender
|
||||
isContact: root.isContact
|
||||
trustIndicator: root.trustIndicator
|
||||
}
|
||||
StatusBaseText {
|
||||
id: secondaryDisplayName
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
visible: !root.amISender && !!root.sender.secondaryName
|
||||
color: Theme.palette.baseColor1
|
||||
font.pixelSize: 10
|
||||
text: secondaryName
|
||||
visible: !!text
|
||||
text: `(${root.sender.secondaryName})`
|
||||
}
|
||||
StatusBaseText {
|
||||
id: dotSeparator1
|
||||
Layout.fillHeight: true
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
visible: secondaryDisplayName.visible
|
||||
font.pixelSize: 10
|
||||
color: Theme.palette.baseColor1
|
||||
text: "."
|
||||
visible: secondaryDisplayName.visible
|
||||
text: "•"
|
||||
}
|
||||
StatusBaseText {
|
||||
id: tertiaryDetailText
|
||||
visible: !root.amISender && root.messageOriginInfo === ""
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
Layout.maximumWidth: 58
|
||||
font.pixelSize: 10
|
||||
elide: Text.ElideMiddle
|
||||
color: Theme.palette.baseColor1
|
||||
text: tertiaryDetail
|
||||
text: Utils.elideText(tertiaryDetail, 5, 3)
|
||||
}
|
||||
StatusBaseText {
|
||||
id: dotSeparator2
|
||||
Layout.fillHeight: true
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
visible: tertiaryDetailText.visible
|
||||
font.pixelSize: 10
|
||||
color: Theme.palette.baseColor1
|
||||
text: "."
|
||||
visible: tertiaryDetailText.visible
|
||||
text: "•"
|
||||
}
|
||||
StatusTimeStampLabel {
|
||||
id: timestampText
|
||||
@@ -98,12 +110,12 @@ Item {
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
color: Theme.palette.dangerColor1
|
||||
font.pixelSize: 12
|
||||
text: statusMessageHeader.resendText
|
||||
text: root.resendText
|
||||
visible: showResendButton && !!timestampText.text
|
||||
MouseArea {
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
anchors.fill: parent
|
||||
onClicked: statusMessageHeader.resendClicked()
|
||||
onClicked: root.resendClicked()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,29 +6,29 @@ import StatusQ.Controls 0.1
|
||||
import StatusQ.Core.Theme 0.1
|
||||
|
||||
Rectangle {
|
||||
id: buttonsContainer
|
||||
id: root
|
||||
|
||||
property list<Item> quickActions
|
||||
property list<Item> items
|
||||
|
||||
QtObject {
|
||||
id: _internal
|
||||
readonly property int containerMargin: 2
|
||||
}
|
||||
|
||||
width: buttonRow.width + _internal.containerMargin * 2
|
||||
height: 36
|
||||
implicitWidth: buttonRow.width + _internal.containerMargin * 2
|
||||
implicitHeight: 36
|
||||
radius: 8
|
||||
color: Theme.palette.statusSelect.menuItemBackgroundColor
|
||||
|
||||
layer.enabled: true
|
||||
layer.effect: DropShadow {
|
||||
width: buttonsContainer.width
|
||||
height: buttonsContainer.height
|
||||
x: buttonsContainer.x
|
||||
y: buttonsContainer.y + 10
|
||||
width: root.width
|
||||
height: root.height
|
||||
x: root.x
|
||||
y: root.y + 10
|
||||
horizontalOffset: 0
|
||||
verticalOffset: 2
|
||||
source: buttonsContainer
|
||||
source: root
|
||||
radius: 10
|
||||
samples: 15
|
||||
color: Theme.palette.dropShadow
|
||||
@@ -39,13 +39,13 @@ Rectangle {
|
||||
spacing: _internal.containerMargin
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: _internal.containerMargin
|
||||
anchors.verticalCenter: buttonsContainer.verticalCenter
|
||||
anchors.verticalCenter: root.verticalCenter
|
||||
height: parent.height - 2 * _internal.containerMargin
|
||||
}
|
||||
|
||||
onQuickActionsChanged: {
|
||||
for (let idx in quickActions) {
|
||||
quickActions[idx].parent = buttonRow
|
||||
onItemsChanged: {
|
||||
for (let idx in items) {
|
||||
items[idx].parent = buttonRow
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,18 +7,20 @@ import StatusQ.Core 0.1
|
||||
import StatusQ.Core.Theme 0.1
|
||||
import StatusQ.Components 0.1
|
||||
|
||||
Loader {
|
||||
id: chatReply
|
||||
Item {
|
||||
id: root
|
||||
|
||||
property StatusMessageDetails replyDetails
|
||||
property string audioMessageInfoText: ""
|
||||
property bool profileClickable: true
|
||||
|
||||
signal replyProfileClicked()
|
||||
signal replyProfileClicked(var sender, var mouse)
|
||||
|
||||
active: visible
|
||||
implicitHeight: layout.implicitHeight
|
||||
implicitWidth: layout.implicitWidth
|
||||
|
||||
sourceComponent: RowLayout {
|
||||
id: replyLayout
|
||||
RowLayout {
|
||||
id: layout
|
||||
spacing: 8
|
||||
Shape {
|
||||
id: replyCorner
|
||||
@@ -56,13 +58,15 @@ Loader {
|
||||
StatusSmartIdenticon {
|
||||
id: profileImage
|
||||
Layout.alignment: Qt.AlignTop
|
||||
image: replyDetails.profileImage
|
||||
name: replyDetails.displayName
|
||||
name: replyDetails.sender.displayName
|
||||
asset: replyDetails.sender.profileImage.assetSettings
|
||||
ringSettings: replyDetails.sender.profileImage.ringSettings
|
||||
MouseArea {
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
cursorShape: enabled ? Qt.PointingHandCursor : Qt.ArrowCursor
|
||||
acceptedButtons: Qt.LeftButton | Qt.RightButton
|
||||
anchors.fill: parent
|
||||
onClicked: replyProfileClicked()
|
||||
enabled: root.profileClickable
|
||||
onClicked: replyProfileClicked(this, mouse)
|
||||
}
|
||||
}
|
||||
TextEdit {
|
||||
@@ -74,7 +78,7 @@ Loader {
|
||||
font.weight: Font.Medium
|
||||
selectByMouse: true
|
||||
readOnly: true
|
||||
text: replyDetails.displayName
|
||||
text: replyDetails.amISender ? qsTr("You") : replyDetails.sender.displayName
|
||||
}
|
||||
}
|
||||
StatusTextMessage {
|
||||
@@ -85,13 +89,14 @@ Loader {
|
||||
textField.height: 18
|
||||
clip: true
|
||||
visible: !!replyDetails.messageText
|
||||
allowShowMore: false
|
||||
}
|
||||
StatusImageMessage {
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: imageAlias.paintedHeight
|
||||
imageWidth: 56
|
||||
source: replyDetails.contentType === StatusMessage.ContentType.Image ? replyDetails.messageContent : ""
|
||||
visible: replyDetails.contentType === StatusMessage.ContentType.Image
|
||||
// visible: replyDetails.contentType === StatusMessage.ContentType.Image
|
||||
shapeType: StatusImageMessage.ShapeType.ROUNDED
|
||||
}
|
||||
Item {
|
||||
@@ -100,9 +105,10 @@ Loader {
|
||||
Layout.alignment: Qt.AlignLeft
|
||||
visible: replyDetails.contentType === StatusMessage.ContentType.Sticker
|
||||
StatusSticker {
|
||||
image.width: 48
|
||||
image.height: 48
|
||||
image.source: replyDetails.messageContent
|
||||
asset.width: 48
|
||||
asset.height: 48
|
||||
asset.name: replyDetails.messageContent
|
||||
asset.isImage: true
|
||||
}
|
||||
}
|
||||
Item {
|
||||
@@ -116,7 +122,7 @@ Loader {
|
||||
height: 22
|
||||
isPreview: true
|
||||
audioSource: replyDetails.messageContent
|
||||
audioMessageInfoText: chatReply.audioMessageInfoText
|
||||
audioMessageInfoText: root.audioMessageInfoText
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import QtQuick 2.13
|
||||
import QtQuick.Controls 2.14
|
||||
import QtQuick.Layouts 1.14
|
||||
import QtGraphicalEffects 1.13
|
||||
|
||||
@@ -11,14 +12,35 @@ Loader {
|
||||
|
||||
active: visible
|
||||
|
||||
sourceComponent: Rectangle {
|
||||
height: 24
|
||||
width: layout.width + 16
|
||||
color: Theme.palette.pinColor2
|
||||
radius: 12
|
||||
RowLayout {
|
||||
id: layout
|
||||
anchors.centerIn: parent
|
||||
sourceComponent: Control {
|
||||
verticalPadding: 3
|
||||
leftPadding: 2
|
||||
rightPadding: 6
|
||||
|
||||
background: Rectangle {
|
||||
readonly property color translucentColor: Theme.palette.pinColor2
|
||||
|
||||
implicitWidth: 24
|
||||
implicitHeight: 24
|
||||
color: Qt.rgba(translucentColor.r,
|
||||
translucentColor.g,
|
||||
translucentColor.b, 1)
|
||||
opacity: translucentColor.a
|
||||
layer.enabled: true
|
||||
radius: 12
|
||||
|
||||
Rectangle {
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.left: parent.left
|
||||
width: parent.width / 2
|
||||
height: parent.height / 2
|
||||
color: parent.color
|
||||
radius: 4
|
||||
}
|
||||
}
|
||||
|
||||
contentItem: RowLayout {
|
||||
spacing: 4
|
||||
StatusIcon {
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
Layout.preferredWidth: 16
|
||||
@@ -35,7 +57,6 @@ Loader {
|
||||
}
|
||||
StatusBaseText {
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
Layout.leftMargin: -4
|
||||
color: Theme.palette.directColor1
|
||||
font.pixelSize: 13
|
||||
font.weight: Font.Medium
|
||||
|
||||
@@ -10,7 +10,7 @@ Loader {
|
||||
|
||||
property bool noHover: false
|
||||
property bool noMouseArea: false
|
||||
property StatusImageSettings image: StatusImageSettings {
|
||||
property StatusAssetSettings asset: StatusAssetSettings {
|
||||
width: 140
|
||||
height: 140
|
||||
}
|
||||
@@ -26,8 +26,8 @@ Loader {
|
||||
color: Theme.palette.baseColor2
|
||||
radius: 16
|
||||
|
||||
width: image.width
|
||||
height: image.height
|
||||
width: asset.width
|
||||
height: asset.height
|
||||
|
||||
function reload() {
|
||||
// From the documentation (https://doc.qt.io/qt-5/qml-qtquick-image.html#sourceSize-prop)
|
||||
@@ -53,7 +53,7 @@ Loader {
|
||||
horizontalAlignment: Image.AlignHCenter
|
||||
verticalAlignment: Image.AlignVCenter
|
||||
cache: true
|
||||
source: image.source
|
||||
source: asset.name
|
||||
|
||||
onStatusChanged: {
|
||||
if (status === Image.Ready) {
|
||||
|
||||
@@ -6,24 +6,34 @@ import StatusQ.Controls 0.1
|
||||
import StatusQ.Core.Theme 0.1
|
||||
|
||||
Item {
|
||||
id: textMessage
|
||||
id: root
|
||||
|
||||
property int contentType: 0
|
||||
property alias textField: chatText
|
||||
property bool allowShowMore: true
|
||||
|
||||
signal linkActivated(url link)
|
||||
signal linkActivated(string link)
|
||||
|
||||
implicitHeight: showMoreLoader.active ? childrenRect.height : chatText.height
|
||||
implicitWidth: chatText.implicitWidth
|
||||
implicitHeight: chatText.effectiveHeight + d.showMoreHeight
|
||||
|
||||
QtObject {
|
||||
id: _internal
|
||||
id: d
|
||||
property bool readMore: false
|
||||
property bool veryLongChatText: chatText.length > 1000
|
||||
readonly property bool veryLongChatText: chatText.length > 1000
|
||||
readonly property int showMoreHeight: showMoreLoader.visible ? showMoreLoader.height : 0
|
||||
}
|
||||
|
||||
TextEdit {
|
||||
id: chatText
|
||||
visible: !showMoreLoader.active || _internal.readMore
|
||||
objectName: "StatusTextMessage_chatText"
|
||||
|
||||
readonly property int effectiveHeight: d.veryLongChatText && !d.readMore ? Math.min(chatText.implicitHeight, 200)
|
||||
: chatText.implicitHeight
|
||||
|
||||
width: parent.width
|
||||
height: effectiveHeight + d.showMoreHeight / 2
|
||||
visible: !opMask.active
|
||||
clip: true
|
||||
selectedTextColor: Theme.palette.directColor1
|
||||
selectionColor: Theme.palette.primaryColor3
|
||||
color: Theme.palette.directColor1
|
||||
@@ -33,12 +43,12 @@ Item {
|
||||
wrapMode: Text.Wrap
|
||||
readOnly: true
|
||||
selectByMouse: true
|
||||
height: _internal.veryLongChatText && !_internal.readMore ? Math.min(implicitHeight, 200) : implicitHeight
|
||||
width: parent.width
|
||||
clip: height < implicitHeight
|
||||
onLinkActivated: textMessage.linkActivated(link)
|
||||
onLinkActivated: {
|
||||
root.linkActivated(link);
|
||||
}
|
||||
onLinkHovered: {
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
// Strange thing. Without this empty stub the cursorShape
|
||||
// is not changed to pointingHandCursor.
|
||||
}
|
||||
}
|
||||
|
||||
@@ -60,7 +70,7 @@ Item {
|
||||
|
||||
Loader {
|
||||
id: opMask
|
||||
active: showMoreLoader.active && !_internal.readMore
|
||||
active: showMoreLoader.active && !d.readMore
|
||||
anchors.fill: chatText
|
||||
sourceComponent: OpacityMask {
|
||||
source: chatText
|
||||
@@ -70,17 +80,17 @@ Item {
|
||||
|
||||
Loader {
|
||||
id: showMoreLoader
|
||||
active: _internal.veryLongChatText
|
||||
anchors.top: chatText.bottom
|
||||
anchors.topMargin: -10
|
||||
active: root.allowShowMore && d.veryLongChatText
|
||||
visible: active
|
||||
anchors.verticalCenter: chatText.bottom
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
sourceComponent: StatusRoundButton {
|
||||
implicitWidth: 24
|
||||
implicitHeight: 24
|
||||
type: StatusRoundButton.Type.Secondary
|
||||
icon.name: _internal.readMore ? "chevron-up": "chevron-down"
|
||||
icon.name: d.readMore ? "chevron-up": "chevron-down"
|
||||
onClicked: {
|
||||
_internal.readMore = !_internal.readMore
|
||||
d.readMore = !d.readMore
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,10 +9,11 @@ StatusChatListItem 0.1 StatusChatListItem.qml
|
||||
StatusChatListCategory 0.1 StatusChatListCategory.qml
|
||||
StatusChatListCategoryItem 0.1 StatusChatListCategoryItem.qml
|
||||
StatusChatListAndCategories 0.1 StatusChatListAndCategories.qml
|
||||
StatusChatToolBar 0.1 StatusChatToolBar.qml
|
||||
StatusToolBar 0.1 StatusToolBar.qml
|
||||
StatusContactRequestsIndicatorListItem 0.1 StatusContactRequestsIndicatorListItem.qml
|
||||
StatusEmoji 0.1 StatusEmoji.qml
|
||||
StatusContactVerificationIcons 0.1 StatusContactVerificationIcons.qml
|
||||
StatusDateGroupLabel 0.1 StatusDateGroupLabel.qml
|
||||
StatusDescriptionListItem 0.1 StatusDescriptionListItem.qml
|
||||
StatusLetterIdenticon 0.1 StatusLetterIdenticon.qml
|
||||
StatusListItem 0.1 StatusListItem.qml
|
||||
@@ -31,6 +32,7 @@ StatusExpandableItem 0.1 StatusExpandableItem.qml
|
||||
StatusSmartIdenticon 0.1 StatusSmartIdenticon.qml
|
||||
StatusMessage 0.1 StatusMessage.qml
|
||||
StatusMessageDetails 0.1 StatusMessageDetails.qml
|
||||
StatusMessageSenderDetails 0.1 StatusMessageSenderDetails.qml
|
||||
StatusTagSelector 0.1 StatusTagSelector.qml
|
||||
StatusToastMessage 0.1 StatusToastMessage.qml
|
||||
StatusWizardStepper 0.1 StatusWizardStepper.qml
|
||||
@@ -41,3 +43,5 @@ StatusCommunityTags 0.1 StatusCommunityTags.qml
|
||||
StatusItemSelector 0.1 StatusItemSelector.qml
|
||||
StatusCard 0.1 StatusCard.qml
|
||||
StatusDatePicker 0.1 StatusDatePicker.qml
|
||||
StatusChart 0.1 StatusChart.qml
|
||||
StatusChartPanel 0.1 StatusChartPanel.qml
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
import QtQuick 2.14
|
||||
import QtQuick.Layouts 1.14
|
||||
import QtQuick.Controls 2.14
|
||||
|
||||
import StatusQ.Core 0.1
|
||||
import StatusQ.Core.Theme 0.1
|
||||
import StatusQ.Components 0.1
|
||||
import StatusQ.Core.Utils 0.1
|
||||
|
||||
Rectangle {
|
||||
id: statusBaseButton
|
||||
Button {
|
||||
id: root
|
||||
|
||||
enum Size {
|
||||
Tiny,
|
||||
@@ -19,158 +22,106 @@ Rectangle {
|
||||
Primary
|
||||
}
|
||||
|
||||
property StatusIconSettings icon: StatusIconSettings {
|
||||
width: 24
|
||||
height: 24
|
||||
}
|
||||
property StatusAssetSettings asset: StatusAssetSettings { }
|
||||
|
||||
property bool loading: false
|
||||
property bool loading
|
||||
|
||||
property alias hovered: sensor.containsMouse
|
||||
property color normalColor
|
||||
property color hoverColor
|
||||
property color disabledColor
|
||||
|
||||
property color textColor
|
||||
property color disabledTextColor
|
||||
property color borderColor: "transparent"
|
||||
|
||||
property int size: StatusBaseButton.Size.Large
|
||||
property int type: StatusBaseButton.Type.Normal
|
||||
|
||||
property alias text: label.text
|
||||
property alias font: label.font
|
||||
|
||||
property real defaultLeftPadding: size === StatusBaseButton.Size.Large ? 24 : 12
|
||||
property real defaultRightPadding: size === StatusBaseButton.Size.Large ? 24 : 12
|
||||
property real defaultTopPadding: {
|
||||
switch (size) {
|
||||
case StatusBaseButton.Size.Tiny:
|
||||
return 5
|
||||
case StatusBaseButton.Size.Small:
|
||||
return 10
|
||||
case StatusBaseButton.Size.Large:
|
||||
default:
|
||||
return 11
|
||||
}
|
||||
}
|
||||
property real defaultBottomPadding: {
|
||||
switch (size) {
|
||||
case StatusBaseButton.Size.Tiny:
|
||||
return 5
|
||||
case StatusBaseButton.Size.Small:
|
||||
return 10
|
||||
case StatusBaseButton.Size.Large:
|
||||
default:
|
||||
return 11
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
property real leftPadding: defaultLeftPadding
|
||||
property real rightPadding: defaultRightPadding
|
||||
property real topPadding: defaultTopPadding
|
||||
property real bottomPadding: defaultBottomPadding
|
||||
|
||||
property color normalColor
|
||||
property color hoverColor
|
||||
property color disaledColor
|
||||
|
||||
property color textColor
|
||||
property color disabledTextColor
|
||||
|
||||
signal pressed(var mouse)
|
||||
signal released(var mouse)
|
||||
signal clicked(var mouse)
|
||||
signal pressAndHold(var mouse)
|
||||
|
||||
property bool highlighted: false
|
||||
|
||||
|
||||
/// Implementation
|
||||
implicitWidth: layout.width + statusBaseButton.leftPadding + statusBaseButton.rightPadding
|
||||
implicitHeight: layout.height + statusBaseButton.topPadding + statusBaseButton.bottomPadding
|
||||
|
||||
|
||||
radius: size !== StatusBaseButton.Size.Tiny ? 8 : 6
|
||||
|
||||
color: {
|
||||
if (statusBaseButton.enabled)
|
||||
return sensor.containsMouse || highlighted ? hoverColor
|
||||
: normalColor;
|
||||
return disaledColor
|
||||
}
|
||||
|
||||
QtObject {
|
||||
id: d
|
||||
readonly property color textColor: statusBaseButton.enabled ? statusBaseButton.textColor : statusBaseButton.disabledTextColor
|
||||
readonly property color textColor: root.enabled || root.loading ? root.textColor : root.disabledTextColor
|
||||
}
|
||||
|
||||
font.family: Theme.palette.baseFont.name
|
||||
font.weight: Font.Medium
|
||||
font.pixelSize: size === StatusBaseButton.Size.Large ? 15 : 13
|
||||
|
||||
horizontalPadding: {
|
||||
if (root.icon.name) {
|
||||
return size === StatusBaseButton.Size.Large ? 18 : 16
|
||||
}
|
||||
return size === StatusBaseButton.Size.Large ? 24 : 12
|
||||
}
|
||||
verticalPadding: {
|
||||
switch (size) {
|
||||
case StatusBaseButton.Size.Tiny:
|
||||
return 5
|
||||
case StatusBaseButton.Size.Small:
|
||||
return 10
|
||||
case StatusBaseButton.Size.Large:
|
||||
default:
|
||||
return 11
|
||||
}
|
||||
}
|
||||
|
||||
spacing: root.size === StatusBaseButton.Size.Large ? 6 : 4
|
||||
|
||||
icon.height: 24
|
||||
icon.width: 24
|
||||
|
||||
background: Rectangle {
|
||||
radius: root.size === StatusBaseButton.Size.Tiny ? 6 : 8
|
||||
border.color: root.borderColor
|
||||
color: {
|
||||
if (root.enabled)
|
||||
return !root.loading && (root.hovered || root.highlighted) ? hoverColor : normalColor;
|
||||
return disabledColor;
|
||||
}
|
||||
}
|
||||
|
||||
contentItem: RowLayout {
|
||||
spacing: root.spacing
|
||||
StatusIcon {
|
||||
Layout.preferredWidth: visible ? root.icon.width : 0
|
||||
Layout.preferredHeight: visible ? root.icon.height : 0
|
||||
icon: root.icon.name
|
||||
rotation: root.asset.rotation
|
||||
opacity: !loading && root.icon.name !== ""
|
||||
visible: root.icon.name !== ""
|
||||
color: d.textColor
|
||||
}
|
||||
StatusEmoji {
|
||||
Layout.preferredWidth: visible ? root.icon.width : 0
|
||||
Layout.preferredHeight: visible ? root.icon.height : 0
|
||||
visible: root.asset.emoji
|
||||
emojiId: Emoji.iconId(root.asset.emoji, root.asset.emojiSize) || ""
|
||||
}
|
||||
StatusBaseText {
|
||||
Layout.alignment: Qt.AlignVCenter | Qt.AlignHCenter
|
||||
opacity: !loading
|
||||
font: root.font
|
||||
text: root.text
|
||||
color: d.textColor
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
}
|
||||
}
|
||||
|
||||
Loader {
|
||||
anchors.centerIn: parent
|
||||
active: root.loading
|
||||
sourceComponent: StatusLoadingIndicator {
|
||||
color: d.textColor
|
||||
}
|
||||
}
|
||||
|
||||
// stop the mouse clicks in the "loading" state w/o disabling the whole button
|
||||
// as this would make it impossible to have hover events or a tooltip
|
||||
MouseArea {
|
||||
id: sensor
|
||||
anchors.fill: parent
|
||||
cursorShape: loading ? Qt.ArrowCursor
|
||||
: Qt.PointingHandCursor
|
||||
|
||||
hoverEnabled: true
|
||||
enabled: !loading && statusBaseButton.enabled
|
||||
|
||||
Loader {
|
||||
anchors.centerIn: parent
|
||||
active: loading
|
||||
sourceComponent: StatusLoadingIndicator {
|
||||
color: d.textColor
|
||||
} // Indicator
|
||||
} // Loader
|
||||
|
||||
Row {
|
||||
id: layout
|
||||
anchors.centerIn: parent
|
||||
spacing: 4
|
||||
StatusIcon {
|
||||
id: statusIcon
|
||||
width: statusBaseButton.icon.width
|
||||
height: statusBaseButton.icon.height
|
||||
icon: statusBaseButton.icon.name
|
||||
rotation: statusBaseButton.icon.rotation
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
opacity: !loading && statusBaseButton.icon.name !== ""
|
||||
visible: statusBaseButton.icon.name !== ""
|
||||
color: d.textColor
|
||||
} // Icon
|
||||
StatusEmoji {
|
||||
width: statusBaseButton.icon.width
|
||||
height: statusBaseButton.icon.height
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
visible: statusBaseButton.icon.emoji
|
||||
emojiId: Emoji.iconId(statusBaseButton.icon.emoji, statusBaseButton.icon.emojiSize) || ""
|
||||
} // Emoji
|
||||
StatusBaseText {
|
||||
id: label
|
||||
opacity: !loading
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
font.pixelSize: size === StatusBaseButton.Size.Large ? 15 : 13 // by design
|
||||
|
||||
color: d.textColor
|
||||
} // Text
|
||||
} // Row
|
||||
|
||||
|
||||
onPressed: {
|
||||
if (!loading) {
|
||||
statusBaseButton.pressed(mouse)
|
||||
}
|
||||
}
|
||||
|
||||
onReleased: {
|
||||
if (!loading) {
|
||||
statusBaseButton.released(mouse)
|
||||
}
|
||||
}
|
||||
|
||||
onClicked: {
|
||||
if (!loading) {
|
||||
statusBaseButton.clicked(mouse)
|
||||
}
|
||||
}
|
||||
|
||||
onPressAndHold: {
|
||||
if (!loading) {
|
||||
statusBaseButton.pressAndHold(mouse)
|
||||
}
|
||||
}
|
||||
} // Sensor
|
||||
acceptedButtons: Qt.AllButtons
|
||||
enabled: root.loading
|
||||
onPressed: mouse.accepted = true
|
||||
onWheel: wheel.accepted = true
|
||||
cursorShape: !root.loading ? Qt.PointingHandCursor: undefined // always works; 'undefined' resets to default cursor
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ import StatusQ.Components 0.1
|
||||
import StatusQ.Controls 0.1
|
||||
import StatusQ.Core 0.1
|
||||
import StatusQ.Core.Theme 0.1
|
||||
import StatusQ.Core.Utils 0.1
|
||||
|
||||
/*!
|
||||
\qmltype StatusBaseInput
|
||||
@@ -182,9 +183,9 @@ Item {
|
||||
|
||||
/*!
|
||||
\qmlproperty bool StatusBaseInput::valid
|
||||
This property sets the valid state. Default value is true.
|
||||
This property sets the valid state. Default value is false.
|
||||
*/
|
||||
property bool valid: true
|
||||
property bool valid: false
|
||||
/*!
|
||||
\qmlproperty bool StatusBaseInput::pristine
|
||||
This property sets the pristine. Default value is true.
|
||||
@@ -217,21 +218,19 @@ Item {
|
||||
property bool showBackground: true
|
||||
|
||||
/*!
|
||||
\qmlproperty StatusIconSettings StatusBaseInput::icon
|
||||
\qmlproperty StatusAssetSettings StatusBaseInput::icon
|
||||
This property holds a set of settings for the icon of the StatusBaseInput.
|
||||
*/
|
||||
property StatusIconSettings icon: StatusIconSettings {
|
||||
property StatusAssetSettings asset: StatusAssetSettings {
|
||||
width: 24
|
||||
height: 24
|
||||
name: ""
|
||||
color: Theme.palette.baseColor1
|
||||
emoji: ""
|
||||
letterSize: emoji ? 11 : 14
|
||||
background: StatusIconBackgroundSettings {
|
||||
width: 30
|
||||
height: 30
|
||||
color: Theme.palette.indirectColor1
|
||||
}
|
||||
bgWidth: 30
|
||||
bgHeight: 30
|
||||
bgColor: Theme.palette.indirectColor1
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -317,8 +316,8 @@ Item {
|
||||
sourceComponent: {
|
||||
if (root.leftComponent) return root.leftComponent
|
||||
if (!root.leftIcon) return undefined
|
||||
if (root.icon.emoji || root.icon.isLetterIdenticon) return identiconComponent
|
||||
if (root.icon.name) return isIconSelectable ? identiconComponent : iconComponent
|
||||
if (root.asset.emoji || root.asset.isLetterIdenticon) return identiconComponent
|
||||
if (root.asset.name) return isIconSelectable ? identiconComponent : iconComponent
|
||||
return undefined
|
||||
}
|
||||
}
|
||||
@@ -339,17 +338,6 @@ Item {
|
||||
}
|
||||
clip: true
|
||||
|
||||
function ensureVisible(r) {
|
||||
if (contentX >= r.x)
|
||||
contentX = r.x
|
||||
else if (contentX + width <= r.x + r.width)
|
||||
contentX = r.x + r.width - width
|
||||
if (contentY >= r.y)
|
||||
contentY = r.y
|
||||
else if (contentY + height <= r.y + r.height)
|
||||
contentY = r.y + r.height - height
|
||||
}
|
||||
|
||||
TextEdit {
|
||||
id: edit
|
||||
property string previousText: text
|
||||
@@ -374,7 +362,7 @@ Item {
|
||||
edit.keyEvent = event.key
|
||||
root.keyPressed(event);
|
||||
}
|
||||
onCursorRectangleChanged: flick.ensureVisible(cursorRectangle)
|
||||
onCursorRectangleChanged: Utils.ensureVisible(flick, cursorRectangle)
|
||||
onActiveFocusChanged: if (root.pristine) root.pristine = false
|
||||
onTextChanged: {
|
||||
if (previousText === text) {
|
||||
@@ -430,8 +418,8 @@ Item {
|
||||
if (root.rightComponent) return root.rightComponent
|
||||
if (root.clearable) return clearButton
|
||||
if (root.leftIcon) return undefined
|
||||
if (root.icon.emoji) return identiconComponent
|
||||
if (root.icon.name) return isIconSelectable ? identiconComponent : iconComponent
|
||||
if (root.asset.emoji) return identiconComponent
|
||||
if (root.asset.name) return isIconSelectable ? identiconComponent : iconComponent
|
||||
return undefined
|
||||
}
|
||||
}
|
||||
@@ -465,14 +453,16 @@ Item {
|
||||
StatusSmartIdenticon {
|
||||
id: identicon
|
||||
|
||||
icon.width: 24
|
||||
icon.height: 24
|
||||
icon.background: root.icon.background
|
||||
icon.color: root.icon.color
|
||||
icon.letterSize: root.icon.letterSize
|
||||
icon.emoji: root.icon.emoji
|
||||
icon.name: !root.icon.emoji ? root.icon.name : ""
|
||||
icon.isLetterIdenticon: root.icon.isLetterIdenticon
|
||||
asset.width: 24
|
||||
asset.height: 24
|
||||
asset.bgWidth: root.asset.bgWidth
|
||||
asset.bgHeight: root.asset.bgHeight
|
||||
asset.bgColor: root.asset.bgColor
|
||||
asset.color: root.asset.color
|
||||
asset.letterSize: root.asset.letterSize
|
||||
asset.emoji: root.asset.emoji
|
||||
asset.name: !root.asset.emoji ? root.asset.name : ""
|
||||
asset.isLetterIdenticon: root.asset.isLetterIdenticon
|
||||
name: root.letterIconName
|
||||
|
||||
MouseArea {
|
||||
@@ -492,10 +482,10 @@ Item {
|
||||
StatusIcon {
|
||||
id: statusIcon
|
||||
|
||||
icon: root.icon.name
|
||||
width: root.icon.width
|
||||
height: root.icon.height
|
||||
color: root.icon.color
|
||||
icon: root.asset.name
|
||||
width: root.asset.width
|
||||
height: root.asset.height
|
||||
color: root.asset.color
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,12 +11,10 @@ StatusBaseButton {
|
||||
hoverColor: type === StatusBaseButton.Type.Primary ? Theme.palette.hoverColor(normalColor) :
|
||||
type === StatusBaseButton.Type.Normal ? Theme.palette.primaryColor2
|
||||
: Theme.palette.dangerColor2
|
||||
disaledColor: Theme.palette.baseColor2
|
||||
disabledColor: Theme.palette.baseColor2
|
||||
|
||||
textColor: type === StatusBaseButton.Type.Primary ? Theme.palette.white :
|
||||
type === StatusBaseButton.Type.Normal ? Theme.palette.primaryColor1
|
||||
: Theme.palette.dangerColor1
|
||||
disabledTextColor: Theme.palette.baseColor1
|
||||
|
||||
font.weight: type === StatusBaseButton.Type.Primary ? Font.Medium : Font.Normal
|
||||
}
|
||||
|
||||
@@ -16,10 +16,9 @@ Rectangle {
|
||||
|
||||
signal clicked(var mouse)
|
||||
|
||||
property StatusIconSettings icon: StatusIconSettings {
|
||||
property StatusAssetSettings icon: StatusAssetSettings {
|
||||
width: 24
|
||||
height: 24
|
||||
background: StatusIconBackgroundSettings {}
|
||||
}
|
||||
|
||||
color: {
|
||||
@@ -41,14 +40,14 @@ Rectangle {
|
||||
}
|
||||
|
||||
StatusRoundIcon {
|
||||
icon.name: root.icon.name
|
||||
icon.width: root.icon.width
|
||||
icon.height: root.icon.height
|
||||
icon.rotation: root.icon.rotation
|
||||
icon.color: Theme.palette.white
|
||||
icon.background.width: 40
|
||||
icon.background.height: 40
|
||||
icon.background.color: root.icon.color
|
||||
asset.name: root.icon.name
|
||||
asset.width: root.icon.width
|
||||
asset.height: root.icon.height
|
||||
asset.rotation: root.icon.rotation
|
||||
asset.color: Theme.palette.white
|
||||
asset.bgWidth: 40
|
||||
asset.bgHeight: 40
|
||||
asset.bgColor: root.icon.color
|
||||
anchors.top: parent.top
|
||||
anchors.topMargin: 8
|
||||
anchors.left: parent.left
|
||||
|
||||
@@ -1,29 +1,22 @@
|
||||
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
|
||||
|
||||
Rectangle {
|
||||
id: statusChatInfoButton
|
||||
Button {
|
||||
id: root
|
||||
objectName: "chatInfoButton"
|
||||
|
||||
implicitWidth: identicon.width +
|
||||
Math.max(
|
||||
statusChatInfoButtonTitle.anchors.leftMargin + statusChatInfoButtonTitle.implicitWidth,
|
||||
statusChatInfoButtonTitle.anchors.leftMargin + statusChatInfoButtonSubTitle.implicitWidth
|
||||
) + 8
|
||||
implicitHeight: 48
|
||||
property string title: text
|
||||
property string subTitle
|
||||
property bool muted
|
||||
property int pinnedMessagesCount
|
||||
|
||||
property string title: ""
|
||||
property string subTitle: ""
|
||||
property bool muted: false
|
||||
property int pinnedMessagesCount: 0
|
||||
property StatusImageSettings image: StatusImageSettings {
|
||||
width: 36
|
||||
height: 36
|
||||
}
|
||||
property StatusIconSettings icon: StatusIconSettings {
|
||||
property StatusAssetSettings asset: StatusAssetSettings {
|
||||
width: 36
|
||||
height: 36
|
||||
charactersLen: 2
|
||||
@@ -32,9 +25,7 @@ Rectangle {
|
||||
|
||||
property int type: StatusChatInfoButton.Type.PublicChat
|
||||
property alias tooltip: statusToolTip
|
||||
property alias sensor: sensor
|
||||
|
||||
signal clicked(var mouse)
|
||||
signal pinnedMessagesCountClicked(var mouse)
|
||||
signal unmute()
|
||||
signal linkActivated(string link)
|
||||
@@ -49,192 +40,163 @@ Rectangle {
|
||||
CommunityChat // 6
|
||||
}
|
||||
|
||||
radius: 8
|
||||
color: sensor.enabled && sensor.containsMouse ? Theme.palette.baseColor2 : "transparent"
|
||||
horizontalPadding: 4
|
||||
verticalPadding: 2
|
||||
spacing: 4
|
||||
|
||||
MouseArea {
|
||||
id: sensor
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
cursorShape: enabled ? Qt.PointingHandCursor : Qt.ArrowCursor
|
||||
background: Rectangle {
|
||||
radius: 8
|
||||
color: root.enabled && root.hovered ? Theme.palette.baseColor2 : "transparent"
|
||||
|
||||
onClicked: statusChatInfoButton.clicked(mouse)
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
acceptedButtons: Qt.NoButton
|
||||
cursorShape: root.hovered ? Qt.PointingHandCursor : undefined
|
||||
}
|
||||
}
|
||||
|
||||
contentItem: RowLayout {
|
||||
spacing: root.spacing
|
||||
|
||||
// identicon
|
||||
StatusSmartIdenticon {
|
||||
id: identicon
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: 4
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
image: statusChatInfoButton.image
|
||||
icon: statusChatInfoButton.icon
|
||||
name: statusChatInfoButton.title
|
||||
asset: root.asset
|
||||
name: root.title
|
||||
}
|
||||
|
||||
Item {
|
||||
id: statusChatInfoButtonTitle
|
||||
anchors.top: identicon.top
|
||||
anchors.topMargin: statusChatInfoButtonSubTitle.visible ? 0 : 8
|
||||
anchors.left: identicon.right
|
||||
anchors.leftMargin: 8
|
||||
// text
|
||||
ColumnLayout {
|
||||
Layout.fillWidth: true
|
||||
spacing: 2
|
||||
|
||||
width: Math.min(parent.width - anchors.leftMargin
|
||||
- identicon.width - identicon.anchors.leftMargin,
|
||||
implicitWidth)
|
||||
height: chatName.height
|
||||
// title
|
||||
RowLayout {
|
||||
Layout.fillWidth: true
|
||||
Layout.alignment: Qt.AlignLeading | Qt.AlignBottom
|
||||
spacing: root.spacing
|
||||
|
||||
implicitWidth: statusIcon.width + chatName.anchors.leftMargin + chatName.implicitWidth
|
||||
+ mutedDelta
|
||||
StatusIcon {
|
||||
visible: root.type !== StatusChatInfoButton.Type.OneToOneChat
|
||||
Layout.preferredWidth: 14
|
||||
Layout.preferredHeight: 14
|
||||
color: root.muted ? Theme.palette.baseColor1 : Theme.palette.directColor1
|
||||
icon: {
|
||||
switch (root.type) {
|
||||
case StatusChatInfoButton.Type.PublicCat:
|
||||
return "tiny/public-chat"
|
||||
case StatusChatInfoButton.Type.GroupChat:
|
||||
return "tiny/group"
|
||||
case StatusChatInfoButton.Type.CommunityChat:
|
||||
return "tiny/channel"
|
||||
default:
|
||||
return "tiny/public-chat"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
property real mutedDelta: mutedIcon.visible ? mutedIcon.width + 8 : 0
|
||||
StatusBaseText {
|
||||
objectName: "statusChatInfoButtonNameText"
|
||||
Layout.fillWidth: true
|
||||
elide: Text.ElideRight
|
||||
text: root.type === StatusChatInfoButton.Type.PublicChat && !root.title.startsWith("#") ?
|
||||
"#" + root.title
|
||||
: root.title
|
||||
color: root.muted ? Theme.palette.directColor5 : Theme.palette.directColor1
|
||||
font.weight: Font.Medium
|
||||
}
|
||||
|
||||
StatusIcon {
|
||||
id: statusIcon
|
||||
anchors.top: parent.top
|
||||
anchors.topMargin: -2
|
||||
anchors.left: parent.left
|
||||
StatusIcon {
|
||||
objectName: "mutedIcon"
|
||||
Layout.preferredWidth: 13
|
||||
Layout.preferredHeight: 13
|
||||
icon: "tiny/muted"
|
||||
color: mutedIconSensor.containsMouse ? Theme.palette.directColor1 : Theme.palette.baseColor1
|
||||
visible: root.muted
|
||||
|
||||
visible: statusChatInfoButton.type !== StatusChatInfoButton.Type.OneToOneChat
|
||||
width: visible ? 14 : 0
|
||||
color: statusChatInfoButton.muted ? Theme.palette.baseColor1 : Theme.palette.directColor1
|
||||
icon: {
|
||||
switch (statusChatInfoButton.type) {
|
||||
case StatusChatInfoButton.Type.PublicCat:
|
||||
return "tiny/public-chat"
|
||||
break;
|
||||
case StatusChatInfoButton.Type.GroupChat:
|
||||
return "tiny/group"
|
||||
break;
|
||||
case StatusChatInfoButton.Type.CommunityChat:
|
||||
return "tiny/channel"
|
||||
break;
|
||||
default:
|
||||
return "tiny/public-chat"
|
||||
MouseArea {
|
||||
id: mutedIconSensor
|
||||
hoverEnabled: true
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
anchors.fill: parent
|
||||
onClicked: root.unmute()
|
||||
}
|
||||
|
||||
StatusToolTip {
|
||||
id: statusToolTip
|
||||
text: qsTr("Unmute")
|
||||
visible: mutedIconSensor.containsMouse
|
||||
orientation: StatusToolTip.Orientation.Bottom
|
||||
y: parent.height + 12
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
StatusBaseText {
|
||||
id: chatName
|
||||
objectName: "statusChatInfoButtonNameText"
|
||||
// subtitle
|
||||
RowLayout {
|
||||
id: subtitleRow
|
||||
Layout.fillWidth: true
|
||||
Layout.alignment: Qt.AlignLeading | Qt.AlignTop
|
||||
Layout.rightMargin: 4
|
||||
spacing: 0
|
||||
|
||||
anchors.left: statusIcon.visible ? statusIcon.right : parent.left
|
||||
anchors.leftMargin: statusIcon.visible ? 1 : 0
|
||||
anchors.top: parent.top
|
||||
|
||||
elide: Text.ElideRight
|
||||
width: Math.min(implicitWidth, parent.width
|
||||
- statusIcon.width
|
||||
- statusChatInfoButtonTitle.mutedDelta)
|
||||
|
||||
text: statusChatInfoButton.type === StatusChatInfoButton.Type.PublicChat &&
|
||||
!statusChatInfoButton.title.startsWith("#") ?
|
||||
"#" + statusChatInfoButton.title :
|
||||
statusChatInfoButton.title
|
||||
color: statusChatInfoButton.muted ? Theme.palette.directColor5 : Theme.palette.directColor1
|
||||
font.pixelSize: 15
|
||||
font.weight: Font.Medium
|
||||
}
|
||||
|
||||
StatusIcon {
|
||||
objectName: "mutedIcon"
|
||||
id: mutedIcon
|
||||
anchors.left: chatName.right
|
||||
anchors.leftMargin: 4
|
||||
anchors.top: chatName.top
|
||||
anchors.topMargin: -2
|
||||
width: 13
|
||||
icon: "tiny/muted"
|
||||
color: mutedIconSensor.containsMouse ? Theme.palette.directColor1 : Theme.palette.baseColor1
|
||||
visible: statusChatInfoButton.muted
|
||||
|
||||
MouseArea {
|
||||
id: mutedIconSensor
|
||||
hoverEnabled: true
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
anchors.fill: parent
|
||||
onClicked: statusChatInfoButton.unmute()
|
||||
StatusSelectableText {
|
||||
Layout.fillWidth: implicitWidth + separator.width + pinIcon.width + pinText.width > subtitleRow.width
|
||||
text: root.subTitle
|
||||
visible: root.subTitle
|
||||
color: Theme.palette.baseColor1
|
||||
font.pixelSize: 12
|
||||
onLinkActivated: root.linkActivated(link)
|
||||
}
|
||||
|
||||
StatusToolTip {
|
||||
id: statusToolTip
|
||||
text: "Unmute"
|
||||
visible: mutedIconSensor.containsMouse
|
||||
orientation: StatusToolTip.Orientation.Bottom
|
||||
y: parent.height + 12
|
||||
Rectangle {
|
||||
id: separator
|
||||
Layout.preferredHeight: 12
|
||||
Layout.preferredWidth: 1
|
||||
Layout.leftMargin: 4
|
||||
Layout.rightMargin: 2
|
||||
color: Theme.palette.directColor7
|
||||
visible: root.subTitle && root.pinnedMessagesCount
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
id: statusChatInfoButtonSubTitle
|
||||
anchors.left: statusChatInfoButtonTitle.left
|
||||
anchors.top: statusChatInfoButtonTitle.bottom
|
||||
visible: !!statusChatInfoButton.subTitle || statusChatInfoButton.pinnedMessagesCount > 0
|
||||
height: visible ? chatType.height : 0
|
||||
width: Math.min(parent.width - statusChatInfoButtonTitle.anchors.leftMargin
|
||||
- identicon.width - identicon.anchors.leftMargin - 8,
|
||||
implicitWidth)
|
||||
|
||||
implicitWidth: chatType.implicitWidth + pinIconDelta + 8
|
||||
|
||||
|
||||
property real pinIconDelta: pinIcon.visible ? pinIcon.width + pinIcon.anchors.leftMargin
|
||||
+ divider.width + divider.anchors.leftMargin
|
||||
: 0
|
||||
|
||||
StatusSelectableText {
|
||||
id: chatType
|
||||
text: statusChatInfoButton.subTitle
|
||||
color: Theme.palette.baseColor1
|
||||
font.pixelSize: 12
|
||||
width: Math.min(parent.width - (pinIcon.visible ? divider.width + divider.anchors.leftMargin + pinIcon.width + pinIcon.anchors.leftMargin : 0),
|
||||
implicitWidth)
|
||||
onLinkActivated: statusChatInfoButton.linkActivated(link)
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: divider
|
||||
height: 12
|
||||
width: 1
|
||||
color: Theme.palette.directColor7
|
||||
anchors.left: chatType.right
|
||||
anchors.leftMargin: 4
|
||||
anchors.verticalCenter: chatType.verticalCenter
|
||||
visible: !!chatType.text && pinIcon.visible
|
||||
}
|
||||
|
||||
StatusIcon {
|
||||
id: pinIcon
|
||||
|
||||
anchors.left: divider.visible ? divider.right : parent.left
|
||||
anchors.leftMargin: -2
|
||||
anchors.verticalCenter: chatType.verticalCenter
|
||||
height: 14
|
||||
visible: statusChatInfoButton.pinnedMessagesCount > 0
|
||||
icon: "pin"
|
||||
color: Theme.palette.baseColor1
|
||||
}
|
||||
|
||||
StatusBaseText {
|
||||
anchors.left: pinIcon.right
|
||||
anchors.leftMargin: -6
|
||||
anchors.verticalCenter: pinIcon.verticalCenter
|
||||
|
||||
width: 14
|
||||
text: statusChatInfoButton.pinnedMessagesCount
|
||||
font.pixelSize: 12
|
||||
font.underline: pinCountSensor.containsMouse
|
||||
visible: pinIcon.visible
|
||||
color: pinCountSensor.containsMouse ? Theme.palette.directColor1 : Theme.palette.baseColor1
|
||||
|
||||
MouseArea {
|
||||
objectName: "pinMessagesCounterSensor"
|
||||
id: pinCountSensor
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onClicked: statusChatInfoButton.pinnedMessagesCountClicked(mouse)
|
||||
StatusIcon {
|
||||
id: pinIcon
|
||||
Layout.preferredHeight: 14
|
||||
Layout.preferredWidth: 14
|
||||
visible: root.pinnedMessagesCount > 0
|
||||
icon: "pin"
|
||||
color: Theme.palette.baseColor1
|
||||
}
|
||||
|
||||
StatusBaseText {
|
||||
id: pinText
|
||||
TextMetrics {
|
||||
id: tm
|
||||
font: pinText.font
|
||||
elide: Text.ElideRight
|
||||
elideWidth: pinText.width
|
||||
text: qsTr("%Ln pinned message(s)", "", root.pinnedMessagesCount)
|
||||
}
|
||||
|
||||
objectName: "StatusChatInfo_pinText"
|
||||
Layout.fillWidth: true
|
||||
text: tm.elidedText !== tm.text ? root.pinnedMessagesCount : tm.text
|
||||
font.pixelSize: 12
|
||||
font.underline: pinCountSensor.containsMouse
|
||||
visible: root.pinnedMessagesCount
|
||||
color: pinCountSensor.containsMouse ? Theme.palette.directColor1 : Theme.palette.baseColor1
|
||||
|
||||
MouseArea {
|
||||
objectName: "pinMessagesCounterSensor"
|
||||
id: pinCountSensor
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onClicked: root.pinnedMessagesCountClicked(mouse)
|
||||
}
|
||||
}
|
||||
|
||||
Item { Layout.fillWidth: true }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,16 +8,20 @@ import StatusQ.Components 0.1
|
||||
|
||||
|
||||
CheckBox {
|
||||
id: statusCheckBox
|
||||
id: root
|
||||
|
||||
property bool leftSide: true
|
||||
|
||||
indicator: Rectangle {
|
||||
anchors.left: root.leftSide? parent.left : undefined
|
||||
anchors.right: !root.leftSide? parent.right : undefined
|
||||
implicitWidth: 18
|
||||
implicitHeight: 18
|
||||
x: statusCheckBox.leftPadding
|
||||
x: !root.leftSide? root.rightPadding : root.leftPadding
|
||||
y: parent.height / 2 - height / 2
|
||||
radius: 2
|
||||
color: (statusCheckBox.down || statusCheckBox.checked) ? Theme.palette.primaryColor1
|
||||
: Theme.palette.directColor8
|
||||
color: (root.down || root.checked) ? Theme.palette.primaryColor1
|
||||
: Theme.palette.directColor8
|
||||
|
||||
StatusIcon {
|
||||
icon: "checkbox"
|
||||
@@ -26,19 +30,21 @@ CheckBox {
|
||||
anchors.centerIn: parent
|
||||
anchors.horizontalCenterOffset: 1
|
||||
color: Theme.palette.white
|
||||
visible: statusCheckBox.down || statusCheckBox.checked
|
||||
visible: root.down || root.checked
|
||||
}
|
||||
}
|
||||
|
||||
contentItem: StatusBaseText {
|
||||
text: statusCheckBox.text
|
||||
font.pixelSize: statusCheckBox.font.pixelSize
|
||||
text: root.text
|
||||
font.pixelSize: root.font.pixelSize
|
||||
opacity: enabled ? 1.0 : 0.3
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
wrapMode: Text.WordWrap
|
||||
width: parent.width
|
||||
color: Theme.palette.directColor1
|
||||
leftPadding: !!statusCheckBox.text ? statusCheckBox.indicator.width + statusCheckBox.spacing
|
||||
: statusCheckBox.indicator.width
|
||||
leftPadding: root.leftSide? (!!root.text ? root.indicator.width + root.spacing
|
||||
: root.indicator.width) : 0
|
||||
rightPadding: !root.leftSide? (!!root.text ? root.indicator.width + root.spacing
|
||||
: root.indicator.width) : 0
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,11 +8,13 @@ RadioButton {
|
||||
|
||||
property string radioButtonColor: ""
|
||||
property string selectionColor: StatusColors.colors['white']
|
||||
property int diameter: 48
|
||||
property int selectorDiameter: 20
|
||||
property int diameter: 44
|
||||
property int selectorDiameter: 16
|
||||
|
||||
implicitWidth: 48
|
||||
implicitHeight: 48
|
||||
spacing: 0
|
||||
|
||||
implicitWidth: 44
|
||||
implicitHeight: 44
|
||||
|
||||
indicator: Rectangle {
|
||||
implicitWidth: control.diameter
|
||||
@@ -21,13 +23,13 @@ RadioButton {
|
||||
color: radioButtonColor
|
||||
|
||||
Rectangle {
|
||||
anchors.centerIn: parent
|
||||
width: control.selectorDiameter
|
||||
height: control.selectorDiameter
|
||||
visible: control.checked
|
||||
radius: width/2
|
||||
color: selectionColor
|
||||
border.color: StatusColors.colors['grey3']
|
||||
visible: control.checked
|
||||
anchors.centerIn: parent
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,6 +36,7 @@ Column {
|
||||
|
||||
StatusBaseText {
|
||||
id: title
|
||||
width: parent.width
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
font.pixelSize: 13
|
||||
color: Theme.palette.baseColor1
|
||||
@@ -46,7 +47,9 @@ Column {
|
||||
columns: 6
|
||||
rowSpacing: 16
|
||||
columnSpacing: 32
|
||||
|
||||
Repeater {
|
||||
objectName: "statusColorRepeater"
|
||||
model: root.model
|
||||
delegate: StatusColorRadioButton {
|
||||
implicitWidth: root.diameter
|
||||
|
||||
@@ -24,6 +24,8 @@ Item {
|
||||
property alias label: labelItem.text
|
||||
property alias validationError: validationErrorItem.text
|
||||
|
||||
property string popupContentItemObjectName: ""
|
||||
|
||||
implicitWidth: layout.implicitWidth
|
||||
implicitHeight: layout.implicitHeight
|
||||
|
||||
@@ -74,6 +76,13 @@ Item {
|
||||
: comboBox.hovered
|
||||
? Theme.palette.primaryColor2
|
||||
: "transparent"
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
acceptedButtons: Qt.NoButton
|
||||
enabled: root.enabled
|
||||
}
|
||||
}
|
||||
|
||||
contentItem: StatusBaseText {
|
||||
@@ -123,7 +132,7 @@ Item {
|
||||
|
||||
contentItem: StatusListView {
|
||||
id: listView
|
||||
|
||||
objectName: root.popupContentItemObjectName
|
||||
implicitWidth: contentWidth
|
||||
implicitHeight: contentHeight
|
||||
|
||||
|
||||
@@ -3,19 +3,15 @@ import StatusQ.Core 0.1
|
||||
import StatusQ.Core.Theme 0.1
|
||||
|
||||
StatusBaseButton {
|
||||
id: statusFlatButton
|
||||
|
||||
normalColor: "transparent"
|
||||
hoverColor: type === StatusBaseButton.Type.Normal ? Theme.palette.primaryColor3
|
||||
: Theme.palette.dangerColor3
|
||||
disaledColor: "transparent"
|
||||
hoverColor: type === StatusBaseButton.Type.Normal ? Theme.palette.primaryColor3
|
||||
: Theme.palette.dangerColor3
|
||||
disabledColor: "transparent"
|
||||
|
||||
textColor: type === StatusBaseButton.Type.Normal ? Theme.palette.primaryColor1
|
||||
: Theme.palette.dangerColor1
|
||||
disabledTextColor: Theme.palette.baseColor1
|
||||
|
||||
border.color: type === StatusBaseButton.Type.Normal || hovered ? "transparent"
|
||||
: Theme.palette.baseColor2
|
||||
rightPadding: icon.name !== "" ? 18 : defaultRightPadding
|
||||
leftPadding: icon.name !== "" ? 14 : defaultLeftPadding
|
||||
borderColor: (type === StatusBaseButton.Type.Normal || hovered) && !loading ? "transparent"
|
||||
: Theme.palette.baseColor2
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ import StatusQ.Components 0.1
|
||||
Rectangle {
|
||||
id: statusFlatRoundButton
|
||||
|
||||
property StatusIconSettings icon: StatusIconSettings {
|
||||
property StatusAssetSettings icon: StatusAssetSettings {
|
||||
width: 23
|
||||
height: 23
|
||||
rotation: 0
|
||||
|
||||
@@ -113,12 +113,11 @@ Row {
|
||||
implicitHeight: 32
|
||||
topPadding: 8
|
||||
bottomPadding: 0
|
||||
defaultLeftPadding: 4
|
||||
defaultRightPadding: 4
|
||||
horizontalPadding: 4
|
||||
hoverColor: Theme.palette.statusFloatingButtonHighlight
|
||||
normalColor: Theme.palette.baseColor3
|
||||
icon.name: "more"
|
||||
icon.background.color: "transparent"
|
||||
asset.name: "more"
|
||||
asset.bgColor: "transparent"
|
||||
onClicked: popupMenu.popup(parent.x, y + height + 8)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,14 +26,13 @@ TabButton {
|
||||
id: identicon
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
image.source: statusIconTabButton.icon.source
|
||||
image.width: 28
|
||||
image.height: 28
|
||||
icon.height: statusIconTabButton.icon.height
|
||||
icon.width: statusIconTabButton.icon.width
|
||||
icon.name: statusIconTabButton.icon.name
|
||||
icon.color: (statusIconTabButton.hovered || highlighted || statusIconTabButton.checked) ? Theme.palette.primaryColor1 : statusIconTabButton.icon.color
|
||||
icon.isLetterIdenticon: statusIconTabButton.name !== "" && !statusIconTabButton.icon.source.toString()
|
||||
asset.isImage: (statusIconTabButton.icon.source.toString() !== "")
|
||||
asset.name: asset.isImage ?
|
||||
statusIconTabButton.icon.source : statusIconTabButton.icon.name
|
||||
asset.width: asset.isImage ? 28 : statusIconTabButton.icon.width
|
||||
asset.height: asset.isImage ? 28 : statusIconTabButton.icon.height
|
||||
asset.color: (statusIconTabButton.hovered || highlighted || statusIconTabButton.checked) ? Theme.palette.primaryColor1 : statusIconTabButton.icon.color
|
||||
asset.isLetterIdenticon: statusIconTabButton.name !== "" && !asset.isImage
|
||||
name: statusIconTabButton.name
|
||||
}
|
||||
}
|
||||
|
||||
@@ -64,6 +64,7 @@ AbstractButton {
|
||||
width: root.icon.width
|
||||
height: root.icon.height
|
||||
rotation: root.iconRotation
|
||||
visible: status == Image.Ready
|
||||
}
|
||||
StatusBaseText {
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
|
||||
@@ -48,6 +48,7 @@ Item {
|
||||
This property holds a reference to the TextEdit's valid property.
|
||||
*/
|
||||
property alias valid: statusBaseInput.valid
|
||||
|
||||
/*!
|
||||
\qmlproperty alias StatusInput::pending
|
||||
This property holds a reference to the TextEdit's pending property.
|
||||
@@ -243,7 +244,7 @@ Item {
|
||||
This function resets the text input validation and text.
|
||||
*/
|
||||
function reset() {
|
||||
statusBaseInput.valid = true
|
||||
statusBaseInput.valid = false
|
||||
statusBaseInput.pristine = true
|
||||
statusBaseInput.text = ""
|
||||
root.errorMessage = ""
|
||||
@@ -276,8 +277,12 @@ Item {
|
||||
valid: result
|
||||
}
|
||||
}
|
||||
result.errorMessage = validator.errorMessage
|
||||
errors[validator.name] = result
|
||||
|
||||
// the only way to trigger bindings for var property
|
||||
errors = errors
|
||||
result.errorMessage = validator.errorMessage
|
||||
|
||||
statusBaseInput.valid = statusBaseInput.valid && false
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,11 +15,10 @@ ItemDelegate {
|
||||
icon.width: 16
|
||||
icon.height: 16
|
||||
|
||||
contentItem: RowLayout {
|
||||
contentItem: RowLayout {
|
||||
spacing: root.spacing
|
||||
|
||||
StatusIcon {
|
||||
id: iconItem
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
visible: !!icon
|
||||
icon: root.icon.name
|
||||
@@ -43,7 +42,14 @@ ItemDelegate {
|
||||
|
||||
background: Rectangle {
|
||||
color: root.highlighted
|
||||
? Theme.palette.statusPopupMenu.hoverBackgroundColor
|
||||
: "transparent"
|
||||
? Theme.palette.statusPopupMenu.hoverBackgroundColor
|
||||
: "transparent"
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
acceptedButtons: Qt.NoButton
|
||||
enabled: root.enabled
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,10 +39,10 @@ Rectangle {
|
||||
id: root
|
||||
|
||||
/*!
|
||||
\qmlproperty string StatusItemPicker::image
|
||||
This property holds the image settings information.
|
||||
\qmlproperty string StatusItemPicker::asset
|
||||
This property holds the asset(image/icon) settings information.
|
||||
*/
|
||||
property StatusImageSettings image
|
||||
property StatusAssetSettings asset
|
||||
|
||||
/*!
|
||||
\qmlproperty string StatusItemPicker::name
|
||||
@@ -50,6 +50,12 @@ Rectangle {
|
||||
*/
|
||||
property string name
|
||||
|
||||
/*!
|
||||
\qmlproperty int StatusItemPicker::namePixelSize
|
||||
This property holds pixel size of the name to be displayed.
|
||||
*/
|
||||
property int namePixelSize: 15
|
||||
|
||||
/*!
|
||||
\qmlproperty string StatusItemPicker::shortName
|
||||
This property holds the secondary text or short name to be displayed.
|
||||
@@ -81,6 +87,15 @@ Rectangle {
|
||||
*/
|
||||
property ButtonGroup radioGroup
|
||||
|
||||
/*!
|
||||
\qmlproperty int StatusItemPicker::radioButtonSize
|
||||
This property holds size type of the radio button.
|
||||
Possible values are:
|
||||
- Small
|
||||
- Large (default size)
|
||||
*/
|
||||
property int radioButtonSize: StatusRadioButton.Size.Large
|
||||
|
||||
/*!
|
||||
\qmlsignal StatusItemPicker::checkedChanged(bool checked)
|
||||
This signal is emitted when the item is selected by pressing the radiobutton or the checkbox.
|
||||
@@ -95,7 +110,7 @@ Rectangle {
|
||||
QtObject {
|
||||
id: d
|
||||
|
||||
property int minShortNameWidth: 50
|
||||
readonly property int minShortNameWidth: root.shortName ? 50 : 0
|
||||
|
||||
function availableTextWidth() {
|
||||
return root.width - imageItem.width - row.spacing - shortNameItem.anchors.rightMargin - selector.width - selector.anchors.rightMargin - 24/*Margin between both texts*/
|
||||
@@ -112,10 +127,10 @@ Rectangle {
|
||||
StatusIcon {
|
||||
id: imageItem
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
source: root.image.source ? root.image.source : ""
|
||||
width: root.image.width
|
||||
height: root.image.height
|
||||
visible: root.image.source !== undefined
|
||||
source: root.asset && root.asset.name ? root.asset.name : ""
|
||||
width: root.asset ? root.asset.width : 0
|
||||
height: root.asset ? root.asset.height : 0
|
||||
visible: root.asset && root.asset.name !== undefined
|
||||
}
|
||||
|
||||
StatusBaseText {
|
||||
@@ -126,7 +141,7 @@ Rectangle {
|
||||
dummyNameItem.width
|
||||
text: root.name
|
||||
color: Theme.palette.directColor1
|
||||
font.pixelSize: 15
|
||||
font.pixelSize: root.namePixelSize
|
||||
clip: true
|
||||
elide: Text.ElideRight
|
||||
}
|
||||
@@ -167,6 +182,7 @@ Rectangle {
|
||||
Component {
|
||||
id: radioBtn
|
||||
StatusRadioButton {
|
||||
size: root.radioButtonSize
|
||||
ButtonGroup.group: root.radioGroup
|
||||
checked: root.selected
|
||||
onCheckedChanged: {
|
||||
|
||||
@@ -0,0 +1,108 @@
|
||||
import QtQuick 2.14
|
||||
import QtQuick.Layouts 1.12
|
||||
import QtQuick.Controls 2.14
|
||||
|
||||
import StatusQ.Core 0.1
|
||||
import StatusQ.Core.Theme 0.1
|
||||
import StatusQ.Controls 0.1
|
||||
|
||||
/*!
|
||||
\qmltype StatusPasswordInput
|
||||
\inherits Item
|
||||
\inqmlmodule StatusQ.Controls
|
||||
\since StatusQ.Controls 0.1
|
||||
\brief The StatusPasswordInput control provides a generic user password input with an option to display signing phrase
|
||||
|
||||
Example of how to use it:
|
||||
|
||||
\qml
|
||||
StatusPasswordInput {
|
||||
signingPhrase: "orange hello cygnet"
|
||||
placeholderText: qsTr("Password")
|
||||
}
|
||||
\endqml
|
||||
|
||||
For a list of available components see StatusQ.
|
||||
*/
|
||||
|
||||
TextField {
|
||||
id: root
|
||||
|
||||
/*!
|
||||
\qmlproperty string StatusPasswordInput::signingPhrase
|
||||
This property sets the signingPhrase of TextField field and signing seed phrase.
|
||||
*/
|
||||
property string signingPhrase: ""
|
||||
|
||||
QtObject {
|
||||
id: d
|
||||
|
||||
readonly property int inputTextPadding: 16
|
||||
readonly property int pixelSize: 15
|
||||
readonly property int radius: 8
|
||||
readonly property int signingPhrasePadding: 8
|
||||
readonly property int signingPhraseWordPadding: 8
|
||||
readonly property int signingPhraseWordsSpacing: 8
|
||||
readonly property int signingPhraseWordsHeight: 30
|
||||
|
||||
}
|
||||
|
||||
leftPadding: d.inputTextPadding
|
||||
rightPadding: root.signingPhrase !== ""?
|
||||
phrase.width + phrase.anchors.leftMargin + phrase.anchors.rightMargin :
|
||||
d.inputTextPadding
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
implicitWidth: 480
|
||||
implicitHeight: 44
|
||||
|
||||
|
||||
placeholderTextColor: Theme.palette.baseColor1
|
||||
echoMode: TextInput.Password
|
||||
font.pixelSize: d.pixelSize
|
||||
font.family: Theme.palette.baseFont.name
|
||||
color: Theme.palette.directColor1
|
||||
selectionColor: Theme.palette.primaryColor2
|
||||
selectedTextColor: Theme.palette.directColor1
|
||||
background: Rectangle {
|
||||
id: inputRectangle
|
||||
anchors.fill: parent
|
||||
color: Theme.palette.baseColor5
|
||||
radius: d.radius
|
||||
border.width: root.focus ? 1 : 0
|
||||
border.color: {
|
||||
if (root.focus) {
|
||||
return Theme.palette.primaryColor1
|
||||
}
|
||||
return "transparent"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
RowLayout {
|
||||
id: phrase
|
||||
anchors.right: parent.right
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.leftMargin: d.signingPhrasePadding
|
||||
anchors.rightMargin: d.signingPhrasePadding
|
||||
spacing: d.signingPhraseWordsSpacing
|
||||
visible: root.signingPhrase !== ""
|
||||
Repeater {
|
||||
model: root.signingPhrase.split(" ")
|
||||
delegate: Rectangle {
|
||||
width: signingPhraseWord.implicitWidth + 2 * d.signingPhraseWordPadding
|
||||
height: d.signingPhraseWordsHeight
|
||||
color: Theme.palette.indirectColor1
|
||||
radius: d.radius
|
||||
|
||||
StatusBaseText {
|
||||
id: signingPhraseWord
|
||||
anchors.centerIn: parent
|
||||
color: Theme.palette.primaryColor1
|
||||
font.pixelSize: root.font.pixelSize
|
||||
font.family: root.font.family
|
||||
text: modelData
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -14,13 +14,13 @@ Button {
|
||||
property var type: StatusPickerButton.Type.Next
|
||||
|
||||
/*!
|
||||
\qmlproperty StatusImageSettings StatusPickerButton::image
|
||||
\qmlproperty StatusAssetSettings StatusPickerButton::image
|
||||
This property holds the image settings information.
|
||||
*/
|
||||
property StatusImageSettings image: StatusImageSettings {
|
||||
property StatusAssetSettings asset: StatusAssetSettings {
|
||||
width: 20
|
||||
height: 20
|
||||
isIdenticon: false
|
||||
imgIsIdenticon: false
|
||||
}
|
||||
|
||||
enum Type {
|
||||
@@ -51,11 +51,11 @@ Button {
|
||||
height: root.icon.height
|
||||
}
|
||||
StatusRoundedImage {
|
||||
visible: root.image.source.toString() !== ""
|
||||
visible: root.asset.name.toString() !== ""
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
Layout.preferredWidth: root.image.width
|
||||
Layout.preferredHeight: root.image.height
|
||||
image.source: root.image.source
|
||||
Layout.preferredWidth: root.asset.width
|
||||
Layout.preferredHeight: root.asset.height
|
||||
image.source: root.asset.name
|
||||
}
|
||||
StatusBaseText {
|
||||
Layout.fillWidth: true
|
||||
|
||||
@@ -77,6 +77,20 @@ Item {
|
||||
*/
|
||||
property int circleDiameter: 16
|
||||
|
||||
/*!
|
||||
\qmlproperty int StatusPinInput::additionalSpacingOnEveryNItems
|
||||
This property allows you to customize spacing among every N-th pin. By default the value is 0, which
|
||||
means only regular `circleSpacing` will be applied, meaning that spacing among all pins will be the same.
|
||||
*/
|
||||
property int additionalSpacingOnEveryNItems: 0
|
||||
|
||||
/*!
|
||||
\qmlproperty int StatusPinInput::additionalSpacing
|
||||
This property allows you to customize spacing between pin circles on every `additionalSpacingOnEveryNItems` items.
|
||||
This additionalSpacing won't be applied if `additionalSpacingOnEveryNItems` is set to `0`.
|
||||
*/
|
||||
property int additionalSpacing: 0
|
||||
|
||||
QtObject {
|
||||
id: d
|
||||
property int currentPinIndex: 0
|
||||
@@ -151,8 +165,8 @@ Item {
|
||||
}
|
||||
}
|
||||
|
||||
width: (root.circleDiameter + root.circleSpacing) * root.pinLen - root.circleSpacing
|
||||
height: root.circleDiameter
|
||||
implicitWidth: childrenRect.width
|
||||
implicitHeight: childrenRect.height
|
||||
|
||||
// Pin input data management object:
|
||||
TextInput {
|
||||
@@ -196,56 +210,66 @@ Item {
|
||||
id: repeater
|
||||
model: root.pinLen
|
||||
|
||||
Rectangle {
|
||||
id: background
|
||||
Item {
|
||||
id: container
|
||||
property string innerState: "EMPTY"
|
||||
property alias blinkingAnimation: blinkingAnimation
|
||||
property alias innerOpacity: inner.opacity
|
||||
|
||||
width: root.circleDiameter
|
||||
height: width
|
||||
color: Theme.palette.primaryColor2
|
||||
radius: 0.5 * width
|
||||
height: root.circleDiameter
|
||||
width: {
|
||||
if (index > 0 && index < root.pinLen-1 && (index+1) % root.additionalSpacingOnEveryNItems == 0) {
|
||||
return root.circleDiameter + root.additionalSpacing
|
||||
}
|
||||
return root.circleDiameter
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: inner
|
||||
state: background.innerState
|
||||
anchors.centerIn: parent
|
||||
height: width
|
||||
color: Theme.palette.primaryColor1
|
||||
radius: 0.5 * width
|
||||
states: [
|
||||
State {
|
||||
name: "NEXT"
|
||||
StateChangeScript { script: { if(inputText.focus) blinkingAnimation.start() } }
|
||||
PropertyChanges {target: inner; width: root.circleDiameter / 2}
|
||||
},
|
||||
State {
|
||||
name: "FILLED"
|
||||
StateChangeScript { script: if(blinkingAnimation.running) blinkingAnimation.stop() }
|
||||
PropertyChanges {target: inner; width: root.circleDiameter}
|
||||
PropertyChanges {target: inner; opacity: 1}
|
||||
},
|
||||
State {
|
||||
name: "EMPTY"
|
||||
StateChangeScript { script: if(blinkingAnimation.running) blinkingAnimation.stop() }
|
||||
PropertyChanges {target: inner; width: 0}
|
||||
PropertyChanges {target: inner; opacity: 1}
|
||||
}
|
||||
]
|
||||
Rectangle {
|
||||
width: root.circleDiameter
|
||||
height: width
|
||||
color: Theme.palette.primaryColor2
|
||||
radius: 0.5 * width
|
||||
|
||||
// Animation on transitions
|
||||
Behavior on width { NumberAnimation { duration: 200 } }
|
||||
Rectangle {
|
||||
id: inner
|
||||
state: container.innerState
|
||||
anchors.centerIn: parent
|
||||
height: width
|
||||
color: Theme.palette.primaryColor1
|
||||
radius: 0.5 * width
|
||||
states: [
|
||||
State {
|
||||
name: "NEXT"
|
||||
StateChangeScript { script: { if(inputText.focus) blinkingAnimation.start() } }
|
||||
PropertyChanges {target: inner; width: root.circleDiameter / 2}
|
||||
},
|
||||
State {
|
||||
name: "FILLED"
|
||||
StateChangeScript { script: if(blinkingAnimation.running) blinkingAnimation.stop() }
|
||||
PropertyChanges {target: inner; width: root.circleDiameter}
|
||||
PropertyChanges {target: inner; opacity: 1}
|
||||
},
|
||||
State {
|
||||
name: "EMPTY"
|
||||
StateChangeScript { script: if(blinkingAnimation.running) blinkingAnimation.stop() }
|
||||
PropertyChanges {target: inner; width: 0}
|
||||
PropertyChanges {target: inner; opacity: 1}
|
||||
}
|
||||
]
|
||||
|
||||
// Animation on "cursor" blinking
|
||||
SequentialAnimation {
|
||||
id: blinkingAnimation
|
||||
loops: Animation.Infinite
|
||||
running: visible
|
||||
NumberAnimation { target: inner; property: "opacity"; to: 0; duration: 800;}
|
||||
NumberAnimation { target: inner; property: "opacity"; to: 1; duration: 800;}
|
||||
}
|
||||
}
|
||||
// Animation on transitions
|
||||
Behavior on width { NumberAnimation { duration: 200 } }
|
||||
|
||||
// Animation on "cursor" blinking
|
||||
SequentialAnimation {
|
||||
id: blinkingAnimation
|
||||
loops: Animation.Infinite
|
||||
running: visible
|
||||
NumberAnimation { target: inner; property: "opacity"; to: 0; duration: 800;}
|
||||
NumberAnimation { target: inner; property: "opacity"; to: 1; duration: 800;}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,41 +1,50 @@
|
||||
import QtQuick 2.14
|
||||
import QtQuick.Controls 2.14
|
||||
import QtQml 2.14
|
||||
|
||||
import StatusQ.Core 0.1
|
||||
import StatusQ.Core.Theme 0.1
|
||||
import StatusQ.Components 0.1
|
||||
|
||||
|
||||
RadioButton {
|
||||
id: statusRadioButton
|
||||
id: root
|
||||
|
||||
width: indicator.implicitWidth
|
||||
/*!
|
||||
\qmlproperty int StatusRadioButton::size
|
||||
This property holds size type of the radio button.
|
||||
Possible values are:
|
||||
- Small
|
||||
- Large (default size)
|
||||
*/
|
||||
property int size: StatusRadioButton.Size.Large
|
||||
|
||||
enum Size {
|
||||
Small,
|
||||
Large
|
||||
}
|
||||
|
||||
indicator: Rectangle {
|
||||
implicitWidth: 20
|
||||
implicitHeight: 20
|
||||
x: 0
|
||||
y: 6
|
||||
radius: 10
|
||||
color: statusRadioButton.checked ? Theme.palette.primaryColor1
|
||||
: Theme.palette.directColor8
|
||||
implicitWidth: root.size === StatusRadioButton.Size.Large ? 20 : 14
|
||||
implicitHeight: root.size === StatusRadioButton.Size.Large ? 20 : 14
|
||||
x: root.text ? (root.mirrored ? root.width - width - root.rightPadding : root.leftPadding) : root.leftPadding + (root.availableWidth - width) / 2
|
||||
y: root.topPadding + (root.availableHeight - height) / 2
|
||||
radius: width / 2
|
||||
color: root.checked ? Theme.palette.primaryColor1 : Theme.palette.directColor8
|
||||
|
||||
Rectangle {
|
||||
width: 12
|
||||
height: 12
|
||||
radius: 6
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
color: statusRadioButton.checked ? Theme.palette.white : "transparent"
|
||||
visible: statusRadioButton.checked
|
||||
width: root.size === StatusRadioButton.Size.Large ? 12 : 8
|
||||
height: root.size === StatusRadioButton.Size.Large ? 12 : 8
|
||||
radius: width / 2
|
||||
anchors.centerIn: parent
|
||||
color: Theme.palette.white
|
||||
visible: root.checked
|
||||
}
|
||||
}
|
||||
contentItem: StatusBaseText {
|
||||
text: statusRadioButton.text
|
||||
font: root.font
|
||||
text: root.text
|
||||
color: Theme.palette.directColor1
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
leftPadding: !!statusRadioButton.text ? statusRadioButton.indicator.width + statusRadioButton.spacing
|
||||
: statusRadioButton.indicator.width
|
||||
leftPadding: root.indicator && !root.mirrored ? root.indicator.width + root.spacing : 0
|
||||
rightPadding: root.indicator && root.mirrored ? root.indicator.width + root.spacing : 0
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ import StatusQ.Components 0.1
|
||||
Rectangle {
|
||||
id: statusRoundButton
|
||||
|
||||
property StatusIconSettings icon: StatusIconSettings {
|
||||
property StatusAssetSettings icon: StatusAssetSettings {
|
||||
width: 23
|
||||
height: 23
|
||||
rotation: 0
|
||||
|
||||
@@ -47,7 +47,7 @@ T.ScrollBar {
|
||||
|
||||
contentItem: Rectangle {
|
||||
color: Theme.palette.primaryColor2
|
||||
opacity: enabled && (root.hovered || root.active) ? 1.0 : 0.0
|
||||
opacity: enabled && (root.hovered || root.active || (root.policy === T.ScrollBar.AlwaysOn)) ? 1.0 : 0.0
|
||||
radius: Math.min(width, height) / 2
|
||||
|
||||
Behavior on opacity { NumberAnimation { duration: 100 } }
|
||||
|
||||
@@ -23,6 +23,7 @@ Item {
|
||||
property var model
|
||||
property alias selectMenu: selectMenu
|
||||
property color bgColorHover: bgColor
|
||||
// TODO: Fix the indirect handling of children
|
||||
property alias selectedItemComponent: selectedItemContainer.children
|
||||
property bool caretVisible: true
|
||||
property int caretRightMargin: 16
|
||||
@@ -54,7 +55,7 @@ Item {
|
||||
Rectangle {
|
||||
property bool hovered: false
|
||||
id: inputRectangle
|
||||
height: 56
|
||||
height: selectedItemContainer.implicitHeight
|
||||
color: hovered ? bgColorHover : bgColor
|
||||
radius: 8
|
||||
anchors.top: root.hasLabel ? inputLabel.bottom : parent.top
|
||||
@@ -64,7 +65,7 @@ Item {
|
||||
border.width: !!validationError ? 1 : 0
|
||||
border.color: Theme.palette.dangerColor1
|
||||
|
||||
Item {
|
||||
GridLayout {
|
||||
id: selectedItemContainer
|
||||
anchors.fill: parent
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import QtQuick.Controls 2.14 as QC
|
||||
import StatusQ.Controls 0.1
|
||||
import StatusQ.Core 0.1
|
||||
import StatusQ.Core.Theme 0.1
|
||||
import StatusQ.Core.Utils 0.1
|
||||
|
||||
|
||||
Item {
|
||||
@@ -57,18 +58,7 @@ Item {
|
||||
contentHeight: edit.paintedHeight
|
||||
boundsBehavior: Flickable.StopAtBounds
|
||||
QC.ScrollBar.vertical: QC.ScrollBar { interactive: multiline; enabled: multiline }
|
||||
function ensureVisible(r) {
|
||||
if (width-contentX >= r.x) {
|
||||
contentX = 0;
|
||||
}
|
||||
else if (contentX+width <= r.x+r.width) {
|
||||
contentX = r.x+r.width-width;
|
||||
}
|
||||
if (contentY >= r.y)
|
||||
contentY = r.y;
|
||||
else if (contentY+height <= r.y+r.height)
|
||||
contentY = r.y+r.height-height;
|
||||
}
|
||||
|
||||
TextEdit {
|
||||
id: edit
|
||||
width: flick.width
|
||||
@@ -83,7 +73,7 @@ Item {
|
||||
font.family: Theme.palette.baseFont.name
|
||||
color: Theme.palette.directColor1
|
||||
textFormat: Text.RichText
|
||||
onCursorRectangleChanged: flick.ensureVisible(cursorRectangle)
|
||||
onCursorRectangleChanged: Utils.ensureVisible(flick, cursorRectangle)
|
||||
wrapMode: statusSelectableText.multiline ? Text.WrapAtWordBoundaryOrAnywhere : TextEdit.NoWrap
|
||||
|
||||
Keys.forwardTo: [statusSelectableText]
|
||||
|
||||
@@ -6,7 +6,7 @@ import StatusQ.Core.Theme 0.1
|
||||
Item {
|
||||
id: root
|
||||
|
||||
property StatusIconSettings icon: StatusIconSettings {
|
||||
property StatusAssetSettings icon: StatusAssetSettings {
|
||||
width: 24
|
||||
height: 24
|
||||
name: ""
|
||||
|
||||
@@ -25,17 +25,21 @@ import StatusQ.Components 0.1
|
||||
TabButton {
|
||||
id: root
|
||||
|
||||
property alias badge: statusBadge
|
||||
readonly property alias badge: statusBadge
|
||||
|
||||
leftPadding: 12
|
||||
rightPadding: 12
|
||||
|
||||
background: Item { }
|
||||
|
||||
contentItem: Item {
|
||||
contentItem: MouseArea {
|
||||
implicitWidth: contentItemGrid.implicitWidth
|
||||
implicitHeight: contentItemGrid.implicitHeight + 15
|
||||
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
acceptedButtons: Qt.NoButton
|
||||
enabled: root.enabled
|
||||
|
||||
RowLayout {
|
||||
id: contentItemGrid
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ ToolTip {
|
||||
property int offset: 0
|
||||
property alias arrow: arrow
|
||||
|
||||
implicitWidth: Math.min(maxWidth, textContent.implicitWidth + 16)
|
||||
implicitWidth: Math.min(maxWidth, contentItem.implicitWidth + 16)
|
||||
leftPadding: 8
|
||||
rightPadding: 8
|
||||
topPadding: 8
|
||||
@@ -65,7 +65,6 @@ ToolTip {
|
||||
}
|
||||
}
|
||||
contentItem: StatusBaseText {
|
||||
id: textContent
|
||||
text: statusToolTip.text
|
||||
color: Theme.palette.white
|
||||
wrapMode: Text.WordWrap
|
||||
|
||||
@@ -51,3 +51,4 @@ StatusComboBox 0.1 StatusComboBox.qml
|
||||
StatusItemDelegate 0.1 StatusItemDelegate.qml
|
||||
StatusTextArea 0.1 StatusTextArea.qml
|
||||
StatusBackButton 0.1 StatusBackButton.qml
|
||||
StatusPasswordInput 0.1 StatusPasswordInput.qml
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user