Compare commits

..
Author SHA1 Message Date
Khushboo Mehta 9d77bd5ce4 fix(StatusSelect): Expose a property to make arrow in the select item visible/invisible 2022-07-26 15:56:28 +02:00
Khushboo Mehta 96740dd474 chore: Remove StatusAssetSelector from StatusQ as its base component StatusSelect is enough to build this further on desktop side.
This component also has dependecy on BE and hence should be moved out.

BREAKING CHANGE:
2022-07-25 21:15:09 +02:00
165 changed files with 2564 additions and 6367 deletions
+7 -5
View File
@@ -63,7 +63,7 @@ Rectangle {
visible: titleStyle === "windows"
}
StatusMainLayout {
StatusAppLayout {
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
leftPanel: StatusAppNavBar {
appNavBar: StatusAppNavBar {
id: navBar
@@ -174,14 +174,16 @@ Rectangle {
StatusMenuItem {
text: qsTr("Leave Community")
icon.name: "arrow-left"
icon.name: "arrow-right"
icon.width: 14
iconRotation: 180
type: StatusMenuItem.Type.Danger
}
}
}
}
rightPanel: Loader {
appView: Loader {
id: appView
anchors.fill: parent
sourceComponent: statusAppChatView
@@ -197,7 +199,7 @@ Rectangle {
id: statusAppCommunityView
StatusAppCommunityView {
communityDetailModalTitle: demoCommunityDetailModal.header.title
communityDetailModalImage: demoCommunityDetailModal.header.asset.name
communityDetailModalImage: demoCommunityDetailModal.header.image.source
onChatInfoButtonClicked: {
demoCommunityDetailModal.open();
}
-18
View File
@@ -17,24 +17,6 @@ Column {
horizontalItemAlignment: Grid.AlignHCenter
// Primary
StatusButton {
text: "Button"
type: StatusBaseButton.Type.Primary
}
StatusButton {
text: "Button"
enabled: false
type: StatusBaseButton.Type.Primary
}
StatusButton {
text: "Button"
loading: true
type: StatusBaseButton.Type.Primary
}
// Large
StatusButton {
text: "Button"
+10 -27
View File
@@ -113,33 +113,18 @@ GridLayout {
StatusSwitch {
}
StatusSwitch {
text: "Switch with text"
}
StatusRadioButton {
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)"
text: "i'm radio!"
}
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"
asset.color: Theme.palette.miscColor7
asset.isImage: true
asset.name: "qrc:/demoapp/data/profile-image-1.jpeg"
icon.color: Theme.palette.miscColor7
image.source: "qrc:/demoapp/data/profile-image-1.jpeg"
type: StatusChatInfoButton.Type.OneToOneChat
muted: true
pinnedMessagesCount: 1
@@ -151,9 +136,8 @@ GridLayout {
StatusChatInfoButton {
title: "Iuri Matias elided"
subTitle: "Contact"
asset.color: Theme.palette.miscColor7
asset.isImage: true
asset.name: "qrc:/demoapp/data/profile-image-1.jpeg"
icon.color: Theme.palette.miscColor7
image.source: "qrc:/demoapp/data/profile-image-1.jpeg"
type: StatusChatInfoButton.Type.OneToOneChat
muted: true
pinnedMessagesCount: 1
@@ -167,9 +151,8 @@ GridLayout {
StatusChatInfoButton {
title: "Iuri Matias big not elided"
subTitle: "Contact"
asset.color: Theme.palette.miscColor7
asset.isImage: true
asset.name: "qrc:/demoapp/data/profile-image-1.jpeg"
icon.color: Theme.palette.miscColor7
image.source: "qrc:/demoapp/data/profile-image-1.jpeg"
type: StatusChatInfoButton.Type.OneToOneChat
muted: true
pinnedMessagesCount: 1
@@ -181,21 +164,21 @@ GridLayout {
title: "group"
subTitle: "Group Chat"
pinnedMessagesCount: 1
asset.color: Theme.palette.miscColor7
icon.color: Theme.palette.miscColor7
type: StatusChatInfoButton.Type.GroupChat
}
StatusChatInfoButton {
title: "public-chat"
subTitle: "Public Chat"
asset.color: Theme.palette.miscColor7
icon.color: Theme.palette.miscColor7
type: StatusChatInfoButton.Type.PublicChat
}
StatusChatInfoButton {
title: "community-channel"
subTitle: "Community Chat"
asset.color: Theme.palette.miscColor7
icon.color: Theme.palette.miscColor7
type: StatusChatInfoButton.Type.CommunityChat
}
+78 -50
View File
@@ -12,73 +12,93 @@ import StatusQ.Popups 0.1
Column {
spacing: 10
StatusToolBar {
StatusChatToolBar {
toolbarComponent: chatInfoButton1
width: 518
headerContent: StatusChatInfoButton {
width: Math.min(implicitWidth, parent.width)
title: "Some contact"
subTitle: "Contact"
asset.color: Theme.palette.miscColor7
type: StatusChatInfoButton.Type.OneToOneChat
Component {
id: chatInfoButton1
StatusChatInfoButton {
width: Math.min(implicitWidth, parent.width)
title: "Some contact"
subTitle: "Contact"
icon.color: Theme.palette.miscColor7
type: StatusChatInfoButton.Type.OneToOneChat
}
}
}
StatusToolBar {
StatusChatToolBar {
toolbarComponent: chatInfoButton2
width: 518
headerContent: StatusChatInfoButton {
width: Math.min(implicitWidth, parent.width)
title: "Some contact"
subTitle: "Contact"
asset.color: Theme.palette.miscColor7
type: StatusChatInfoButton.Type.PublicChat
pinnedMessagesCount: 1
muted: true
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
}
}
}
StatusToolBar {
StatusChatToolBar {
notificationCount: 1
toolbarComponent: chatInfoButton3
width: 518
headerContent: StatusChatInfoButton {
width: Math.min(implicitWidth, parent.width)
title: "Some contact"
subTitle: "Contact"
asset.color: Theme.palette.miscColor7
type: StatusChatInfoButton.Type.OneToOneChat
pinnedMessagesCount: 1
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
}
}
}
StatusToolBar {
StatusChatToolBar {
notificationCount: 1
toolbarComponent: tagSelector
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: ""
Component {
id: tagSelector
StatusTagSelector {
namesModel: ListModel {
ListElement {
publicId: "0x0"
name: "Maria"
icon: ""
isIdenticon: false
onlineStatus: 3
isReadonly: true
tagIcon: "crown"
}
ListElement {
publicId: "0x1"
name: "James"
icon: ""
isIdenticon: false
onlineStatus: 1
isReadonly: false
tagIcon: ""
}
}
toLabelText: qsTr("To: ")
warningText: qsTr("USER LIMIT REACHED")
}
toLabelText: qsTr("To: ")
warningText: qsTr("USER LIMIT REACHED")
}
}
@@ -203,7 +223,9 @@ Column {
StatusMenuItem {
text: qsTr("Leave Community")
icon.name: "arrow-left"
icon.name: "arrow-right"
icon.width: 14
iconRotation: 180
type: StatusMenuItem.Type.Danger
}
}
@@ -286,7 +308,9 @@ Column {
StatusMenuItem {
text: qsTr("Leave Community")
icon.name: "arrow-left"
icon.name: "arrow-right"
icon.width: 14
iconRotation: 180
type: StatusMenuItem.Type.Danger
}
}
@@ -374,7 +398,9 @@ Column {
StatusMenuItem {
text: qsTr("Leave Community")
icon.name: "arrow-left"
icon.name: "arrow-right"
icon.width: 14
iconRotation: 180
type: StatusMenuItem.Type.Danger
}
}
@@ -467,7 +493,9 @@ Column {
StatusMenuItem {
text: qsTr("Leave Community")
icon.name: "arrow-left"
icon.name: "arrow-right"
icon.width: 14
iconRotation: 180
type: StatusMenuItem.Type.Danger
}
}
+62 -164
View File
@@ -1,6 +1,4 @@
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
@@ -8,8 +6,10 @@ import StatusQ.Controls 0.1
import StatusQ.Components 0.1
import StatusQ.Core.Utils 0.1
ColumnLayout {
spacing: 5
GridLayout {
columns: 1
columnSpacing: 5
rowSpacing: 5
StatusNavigationListItem {
title: "Menu Item"
@@ -17,18 +17,18 @@ ColumnLayout {
StatusNavigationListItem {
title: "Menu Item"
asset.name: "info"
icon.name: "info"
}
StatusNavigationListItem {
title: "Menu Item"
asset.name: "info"
icon.name: "info"
badge.value: 1
}
StatusNavigationListItem {
title: "Menu Item (selected) with very long text"
selected: true
asset.name: "info"
icon.name: "info"
badge.value: 1
}
@@ -55,59 +55,6 @@ ColumnLayout {
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
@@ -121,20 +68,18 @@ ColumnLayout {
StatusChatListItem {
name: "community-channel-emoji"
type: StatusChatListItem.Type.CommunityChat
asset.emoji: "😁"
icon.emoji: "😁"
}
StatusChatListItem {
name: "community-channel-with-image"
asset.isImage: true
asset.name: "qrc:/demoapp/data/profile-image-1.jpeg"
image.source: "qrc:/demoapp/data/profile-image-1.jpeg"
type: StatusChatListItem.Type.CommunityChat
}
StatusChatListItem {
name: "Weird Crazy Otter"
asset.isImage: true
asset.name: "qrc:/demoapp/data/profile-image-1.jpeg"
image.source: "qrc:/demoapp/data/profile-image-1.jpeg"
type: StatusChatListItem.Type.OneToOneChat
}
@@ -219,7 +164,7 @@ ColumnLayout {
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"
asset.name: "info"
icon.name: "info"
statusListItemTitle.font.pixelSize: 17
statusListItemTitle.font.weight: Font.Bold
@@ -228,29 +173,27 @@ ColumnLayout {
StatusListItem {
title: "Title"
subTitle: "Subtitle"
asset.name: "info"
icon.name: "info"
}
StatusListItem {
title: "Title"
subTitle: "Subtitle"
asset.isImage: true
asset.name: "qrc:/demoapp/data/profile-image-1.jpeg"
image.source: "qrc:/demoapp/data/profile-image-1.jpeg"
}
StatusListItem {
title: "Title"
subTitle: "Subtitle"
asset.isImage: true
asset.name: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAlklEQVR4nOzW0QmDQBAG4SSkl7SUQlJGCrElq9F3QdjjVhh/5nv3cFhY9vUIYQiNITSG0BhCExPynn1gWf9bx498P7/
nzPcxEzGExhBdJGYihtAYQlO+tUZvqrPbqeudo5iJGEJjCE15a3VtodH3q2ImYgiNITTlTdG1nUZ5a92VITQxITFiJmIIjSE0htAYQrMHAAD//+wwFVpz+yqXAAAAAElFTkSuQmCC"
asset.imgIsIdenticon: true
image.source: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAlklEQVR4nOzW0QmDQBAG4SSkl7SUQlJGCrElq9F3QdjjVhh/5nv3cFhY9vUIYQiNITSG0Bh
CExPynn1gWf9bx498P7/nzPcxEzGExhBdJGYihtAYQlO+tUZvqrPbqeudo5iJGEJjCE15a3VtodH3q2ImYgiNITTlTdG1nUZ5a92VITQxITFiJmIIjSE0htAYQrMHAAD//+wwFVpz+yqXAAAAAElFTkSuQmCC"
image.isIdenticon: true
}
StatusListItem {
title: "Title"
subTitle: "Subtitle"
asset.name: "info"
icon.name: "info"
components: [StatusButton {
text: "Button"
size: StatusBaseButton.Size.Small
@@ -260,35 +203,35 @@ ColumnLayout {
StatusListItem {
title: "Title"
subTitle: "Subtitle"
asset.name: "info"
icon.name: "info"
components: [StatusSwitch {}]
}
StatusListItem {
title: "Title"
subTitle: "Subtitle"
asset.name: "info"
icon.name: "info"
components: [StatusRadioButton {}]
}
StatusListItem {
title: "Title"
subTitle: "Subtitle"
asset.name: "info"
icon.name: "info"
components: [StatusCheckBox {}]
}
StatusListItem {
title: "Title"
subTitle: "Subtitle"
asset.name: "info"
icon.name: "info"
label: "Text"
}
StatusListItem {
title: "Title"
subTitle: "Subtitle"
asset.name: "info"
icon.name: "info"
label: "Text"
components: [
StatusButton {
@@ -301,7 +244,7 @@ ColumnLayout {
StatusListItem {
title: "Title"
subTitle: "Subtitle"
asset.name: "info"
icon.name: "info"
label: "Text"
components: [StatusSwitch {}]
}
@@ -309,7 +252,7 @@ ColumnLayout {
StatusListItem {
title: "Title"
subTitle: "Subtitle"
asset.name: "info"
icon.name: "info"
label: "Text"
components: [
StatusRadioButton {}
@@ -319,7 +262,7 @@ ColumnLayout {
StatusListItem {
title: "Title"
subTitle: "Subtitle"
asset.name: "info"
icon.name: "info"
label: "Text"
components: [StatusCheckBox {}]
}
@@ -327,7 +270,7 @@ ColumnLayout {
StatusListItem {
title: "Title"
subTitle: "Subtitle"
asset.name: "info"
icon.name: "info"
label: "Text"
components: [
StatusBadge {
@@ -344,14 +287,14 @@ ColumnLayout {
StatusListItem {
title: "Title"
asset.name: "info"
icon.name: "info"
type: StatusListItem.Type.Secondary
}
StatusListItem {
title: "Title"
asset.isLetterIdenticon: true
asset.color: "orange"
icon.isLetterIdenticon: true
icon.color: "orange"
}
StatusListItem {
@@ -361,19 +304,17 @@ ColumnLayout {
StatusListItem {
title: "Title"
asset.name: "delete"
icon.name: "delete"
type: StatusListItem.Type.Danger
}
StatusListItem {
title: "List Item with Badge"
subTitle: "Subtitle"
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"
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"
badge.primaryText: "CryptoKitties"
badge.secondaryText: "#test"
}
@@ -381,57 +322,36 @@ ColumnLayout {
StatusListItem {
title: "List Item with Badge 2"
subTitle: "Subtitle"
asset.isLetterIdenticon: true
icon.isLetterIdenticon: true
badge.primaryText: "CryptoKitties"
badge.secondaryText: "#test"
badge.asset.color: "orange"
badge.asset.isLetterIdenticon: true
badge.icon.color: "orange"
badge.icon.isLetterIdenticon: true
}
StatusListItem {
title: "List Item with Tags"
asset.isLetterIdenticon: true
icon.isLetterIdenticon: true
bottomModel: 3
bottomDelegate: StatusListItemTag {
title: "tag"
asset.isLetterIdenticon: true
icon.isLetterIdenticon: true
}
}
StatusListItem {
title: "List Item with Inline Tags"
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: "😁"
}
}
icon.isLetterIdenticon: true
tagsModel : 2
tagsDelegate: StatusListItemTag {
color: "blue"
height: 24
radius: 6
closeButtonVisible: false
asset.emoji: model.emoji
asset.emojiSize: Emoji.size.verySmall
asset.isLetterIdenticon: true
title: model.name
icon.emoji: "😁"
icon.emojiSize: Emoji.size.verySmall
icon.isLetterIdenticon: true
title: "helloworld.eth"
titleText.font.pixelSize: 12
titleText.color: Theme.palette.indirectColor1
}
@@ -440,10 +360,10 @@ ColumnLayout {
StatusListItem {
title: "List Item with Emoji"
subTitle: "Emoji"
asset.emoji: "😁"
asset.color: "yellow"
asset.letterSize: 14
asset.isLetterIdenticon: true
icon.emoji: "😁"
icon.color: "yellow"
icon.letterSize: 14
icon.isLetterIdenticon: true
}
StatusDescriptionListItem {
@@ -462,7 +382,7 @@ ColumnLayout {
title: "Title"
subTitle: "Subtitle"
tooltip.text: "Tooltip"
asset.name: "info"
icon.name: "info"
iconButton.onClicked: tooltip.visible = !tooltip.visible
}
@@ -477,10 +397,9 @@ ColumnLayout {
pubKey: "0x043a7ed0e8752236a4688563652fd0296453cef00a5dcddbe252dc74f72cc1caa97a2b65e4a1a52d9c30a84c9966beaaaf6b333d659cbdd2e486b443ed1012cf04"
isVerified: true
isContact: true
asset.isImage: true
asset.name: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAlklEQVR4nOzW0QmDQBAG4SSkl7SUQlJGCrElq9F3QdjjVhh/5nv3cFhY9vUIYQiNITSG0BhCExPynn1gWf9bx498P7/
image.source: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAlklEQVR4nOzW0QmDQBAG4SSkl7SUQlJGCrElq9F3QdjjVhh/5nv3cFhY9vUIYQiNITSG0BhCExPynn1gWf9bx498P7/
nzPcxEzGExhBdJGYihtAYQlO+tUZvqrPbqeudo5iJGEJjCE15a3VtodH3q2ImYgiNITTlTdG1nUZ5a92VITQxITFiJmIIjSE0htAYQrMHAAD//+wwFVpz+yqXAAAAAElFTkSuQmCC"
asset.imgIsIdenticon: true
image.isIdenticon: true
status: 1 // FIXME: use enum
ringSettings.ringSpecModel:
ListModel {
@@ -498,27 +417,16 @@ ColumnLayout {
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
}
@@ -527,21 +435,15 @@ ColumnLayout {
userName: "annabelle"
pubKey: "0x043a7ed0e8752236a4688563652fd0296453cef00a5dcddbe252dc74f72cc1caa97a2b65e4a1a52d9c30a84c9966beaaaf6b333d659cbdd2e486b443ed1012cf04"
isContact: true
asset.isImage: true
asset.name: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAlklEQVR4nOzW0QmDQBAG4SSkl7SUQlJGCrElq9F3QdjjVhh/5nv3cFhY9vUIYQiNITSG0BhCExPynn1gWf9bx498P7/
image.source: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAlklEQVR4nOzW0QmDQBAG4SSkl7SUQlJGCrElq9F3QdjjVhh/5nv3cFhY9vUIYQiNITSG0BhCExPynn1gWf9bx498P7/
nzPcxEzGExhBdJGYihtAYQlO+tUZvqrPbqeudo5iJGEJjCE15a3VtodH3q2ImYgiNITTlTdG1nUZ5a92VITQxITFiJmIIjSE0htAYQrMHAAD//+wwFVpz+yqXAAAAAElFTkSuQmCC"
asset.imgIsIdenticon: true
image.isIdenticon: true
}
StatusMemberListItem {
nickName: "admin.guy"
userName: "adguy"
isAdmin: true
asset.isLetterIdenticon: true
isUntrustworthy: true
Component.onCompleted: {
print(asset.name, asset.isImage, asset.isLetterIdenticon)
}
}
StatusBaseText {
@@ -555,12 +457,10 @@ ColumnLayout {
title: "Nokia 3310"
subTitle: "Incoming device"
label: "loading: true"
asset.width: 40
asset.height: 40
asset.emoji: "😁"
asset.color: "hotpink"
asset.letterSize: 14
asset.isLetterIdenticon: true
icon.emoji: "😁"
icon.color: "hotpink"
icon.letterSize: 14
icon.isLetterIdenticon: true
loading: true
}
@@ -568,12 +468,10 @@ ColumnLayout {
title: "Nokia 3310"
subTitle: "Device"
label: "loadingFailed: true"
asset.width: 40
asset.height: 40
asset.emoji: "😁"
asset.color: "hotpink"
asset.letterSize: 14
asset.isLetterIdenticon: true
icon.emoji: "😁"
icon.color: "hotpink"
icon.letterSize: 14
icon.isLetterIdenticon: true
loadingFailed: true
}
}
+2 -5
View File
@@ -40,7 +40,7 @@ ColumnLayout {
}
StatusRoundIcon {
asset.name: "info"
icon.name: "info"
}
}
@@ -57,8 +57,5 @@ ColumnLayout {
}
}
}
StatusDatePicker {
label: "Select date"
}
}
+28 -23
View File
@@ -109,8 +109,7 @@ Column {
anchors.centerIn: parent
header.title: "Some Title"
header.subTitle: "Subtitle"
header.asset.isImage: true
header.asset.name: "qrc:/demoapp/data/profile-image-1.jpeg"
header.image.source: "qrc:/demoapp/data/profile-image-1.jpeg"
}
StatusModal {
@@ -118,10 +117,12 @@ Column {
anchors.centerIn: parent
header.title: "Some Title"
header.subTitle: "Subtitle"
header.asset.isImage: true
header.asset.name: "qrc:/demoapp/data/profile-image-1.jpeg"
header.image.source: "qrc:/demoapp/data/profile-image-1.jpeg"
leftButtons: [
StatusBackButton { }
StatusRoundButton {
icon.name: "arrow-right"
rotation: 180
}
]
rightButtons: [
StatusButton {
@@ -138,8 +139,7 @@ Column {
anchors.centerIn: parent
header.title: "Some Title"
header.subTitle: "Subtitle"
header.asset.isImage: true
header.asset.name: "qrc:/demoapp/data/profile-image-1.jpeg"
header.image.source: "qrc:/demoapp/data/profile-image-1.jpeg"
headerActionButton: StatusFlatRoundButton {
type: StatusFlatRoundButton.Type.Secondary
@@ -152,7 +152,10 @@ Column {
}
leftButtons: [
StatusBackButton { }
StatusRoundButton {
icon.name: "arrow-right"
rotation: 180
}
]
rightButtons: [
StatusButton {
@@ -167,8 +170,7 @@ Column {
StatusModal {
id: modalExample
anchors.centerIn: parent
header.asset.isImage: true
header.asset.name: "qrc:/demoapp/data/profile-image-1.jpeg"
header.image.source: "qrc:/demoapp/data/profile-image-1.jpeg"
header.title: "Header"
header.subTitle: "SubTitle"
rightButtons: [
@@ -181,7 +183,10 @@ Column {
]
leftButtons: [
StatusBackButton { }
StatusRoundButton {
icon.name: "arrow-right"
rotation: 180
}
]
contentItem: StatusBaseText {
@@ -231,8 +236,8 @@ Column {
anchors.centerIn: parent
header.title: "Header"
header.subTitle: "SubTitle"
header.asset.isLetterIdenticon: true
header.asset.bgColor: "red"
header.icon.isLetterIdenticon: true
header.icon.background.color: "red"
contentItem: StatusBaseText {
anchors.centerIn: parent
@@ -256,9 +261,9 @@ Column {
anchors.centerIn: parent
header.title: "Header"
header.subTitle: "SubTitle"
header.asset.name: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAlklEQVR4nOzW0QmDQBAG4SSkl7SUQlJGCrElq9F3QdjjVhh/5nv3cFhY9vUIYQiNITSG0BhCExPynn1gWf9bx498P7/
nzPcxEzGExhBdJGYihtAYQlO+tUZvqrPbqeudo5iJGEJjCE15a3VtodH3q2ImYgiNITTlTdG1nUZ5a92VITQxITFiJmIIjSE0htAYQrMHAAD//+wwFVpz+yqXAAAAAElFTkSuQmCC"
header.asset.imgIsIdenticon: true
header.image.source: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAlklEQVR4nOzW0QmDQBAG4SSkl7SUQlJGCrElq9F3QdjjVhh/5nv3cFhY9vUIYQiNITSG0Bh
CExPynn1gWf9bx498P7/nzPcxEzGExhBdJGYihtAYQlO+tUZvqrPbqeudo5iJGEJjCE15a3VtodH3q2ImYgiNITTlTdG1nUZ5a92VITQxITFiJmIIjSE0htAYQrMHAAD//+wwFVpz+yqXAAAAAElFTkSuQmCC"
header.image.isIdenticon: true
contentItem: StatusBaseText {
anchors.centerIn: parent
@@ -283,9 +288,9 @@ Column {
header.title: "Header"
header.subTitle: "SubTitle"
header.headerImageEditable: true
header.asset.name: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAlklEQVR4nOzW0QmDQBAG4SSkl7SUQlJGCrElq9F3QdjjVhh/5nv3cFhY9vUIYQiNITSG0BhCExPynn1gWf9bx498P7/
nzPcxEzGExhBdJGYihtAYQlO+tUZvqrPbqeudo5iJGEJjCE15a3VtodH3q2ImYgiNITTlTdG1nUZ5a92VITQxITFiJmIIjSE0htAYQrMHAAD//+wwFVpz+yqXAAAAAElFTkSuQmCC"
header.asset.imgIsIdenticon: true
header.image.source: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAlklEQVR4nOzW0QmDQBAG4SSkl7SUQlJGCrElq9F3QdjjVhh/5nv3cFhY9vUIYQiNITSG0Bh
CExPynn1gWf9bx498P7/nzPcxEzGExhBdJGYihtAYQlO+tUZvqrPbqeudo5iJGEJjCE15a3VtodH3q2ImYgiNITTlTdG1nUZ5a92VITQxITFiJmIIjSE0htAYQrMHAAD//+wwFVpz+yqXAAAAAElFTkSuQmCC"
header.image.isIdenticon: true
contentItem: StatusBaseText {
anchors.centerIn: parent
@@ -310,9 +315,9 @@ Column {
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.asset.name: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAlklEQVR4nOzW0QmDQBAG4SSkl7SUQlJGCrElq9F3QdjjVhh/5nv3cFhY9vUIYQiNITSG0BhCExPynn1gWf9bx498P7/
nzPcxEzGExhBdJGYihtAYQlO+tUZvqrPbqeudo5iJGEJjCE15a3VtodH3q2ImYgiNITTlTdG1nUZ5a92VITQxITFiJmIIjSE0htAYQrMHAAD//+wwFVpz+yqXAAAAAElFTkSuQmCC"
header.asset.imgIsIdenticon: true
header.image.source: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAlklEQVR4nOzW0QmDQBAG4SSkl7SUQlJGCrElq9F3QdjjVhh/5nv3cFhY9vUIYQiNITSG0Bh
CExPynn1gWf9bx498P7/nzPcxEzGExhBdJGYihtAYQlO+tUZvqrPbqeudo5iJGEJjCE15a3VtodH3q2ImYgiNITTlTdG1nUZ5a92VITQxITFiJmIIjSE0htAYQrMHAAD//+wwFVpz+yqXAAAAAElFTkSuQmCC"
header.image.isIdenticon: true
contentItem: StatusBaseText {
anchors.centerIn: parent
@@ -344,7 +349,7 @@ Column {
sourceComponent: popupMenu.delegate
onLoaded: {
item.action.text = model.name
item.action.assetSettings.name = model.iconName
item.action.iconSettings.name = model.iconName
}
}
}
+22 -49
View File
@@ -14,10 +14,9 @@ ListView {
anchors.fill: parent
anchors.margins: 15
clip: true
delegate: StatusMessage {
id: delegate
width: ListView.view.width
width: parent.width
audioMessageInfoText: "Audio Message"
cancelButtonText: "Cancel"
@@ -27,70 +26,44 @@ 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
sender.id: model.senderId
sender.userName: model.userName
sender.localName: model.localName
sender.ensName: model.ensName
sender.isContact: model.isContact
sender.trustIndicator: model.trustIndicator
sender.profileImage: StatusProfileImageSettings {
displayName: model.userName
secondaryName: model.localName !== "" && model.ensName.startsWith("@") ? model.ensName: ""
chatID: model.chatKey
profileImage: StatusImageSettings {
width: 40
height: 40
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 }
}
source: model.profileImage
isIdenticon: model.isIdenticon
}
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
sender.id: model.replySenderId || ""
sender.userName: model.isReply ? model.replySenderName: ""
sender.ensName: model.isReply ? model.replySenderEnsName : ""
sender.profileImage: StatusProfileImageSettings {
amISender: model.isReply ? model.replyAmISender : ""
displayName: model.isReply ? model.replySenderName: ""
profileImage: StatusImageSettings {
width: 20
height: 20
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 }
}
source: model.isReply ? model.replyProfileImage: ""
isIdenticon: model.isReply ? model.replyIsIdenticon: ""
}
messageText: model.isReply ? model.replyMessageText: ""
contentType: model.replyContentType
messageContent: model.replyMessageContent
}
quickActions: [
StatusFlatRoundButton {
id: emojiBtn
+5 -10
View File
@@ -70,12 +70,6 @@ Page {
Component.onCompleted: {
textEdit.forceActiveFocus();
sortModel(root.contactsModel);
//add admin tag
namesModel.append({
"pubKey": "0x043a7ed78362567894688563652fd0296453cef00a5dcddbe252dc74f72cc1caa97a2b65e4a1a52d9c30a84c9966beaaaf6b333d659cbdd2e486b443ed1012cf04",
"name": "carmen.eth",
"tagIcon": "crown",
"isReadonly": true});
}
}
@@ -83,7 +77,7 @@ Page {
implicitWidth: 106
implicitHeight: 44
Layout.alignment: Qt.AlignTop
enabled: (tagSelector.namesModel.count > 1)
enabled: (tagSelector.namesModel.count > 0)
text: "Confirm"
}
@@ -104,15 +98,16 @@ Page {
anchors.fill: parent
StatusBaseText {
width: Math.min(553, parent.width - 32)
anchors.horizontalCenter: parent.horizontalCenter
anchors.left: parent.left
anchors.leftMargin: 252
anchors.right: parent.right
anchors.rightMargin: 252
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.")
+8 -8
View File
@@ -13,8 +13,7 @@ StatusModal {
header.title: "Cryptokitties"
header.subTitle: "Public Community"
header.asset.isImage: true
header.asset.name: "qrc:/demoapp/data/profile-image-1.jpeg"
header.image.source: "qrc:/demoapp/data/profile-image-1.jpeg"
contentItem: Column {
width: root.width
@@ -44,7 +43,7 @@ StatusModal {
title: "Share community"
subTitle: "https://join.status.im/u/0x04...45f19"
tooltip.text: "Copy to clipboard"
asset.name: "copy"
icon.name: "copy"
iconButton.onClicked: tooltip.visible = !tooltip.visible
width: parent.width
}
@@ -58,7 +57,7 @@ StatusModal {
anchors.horizontalCenter: parent.horizontalCenter
statusListItemTitle.font.pixelSize: 17
title: "Members"
asset.name: "group-chat"
icon.name: "group-chat"
label: "184"
components: [
StatusIcon {
@@ -73,7 +72,7 @@ StatusModal {
anchors.horizontalCenter: parent.horizontalCenter
statusListItemTitle.font.pixelSize: 17
title: "Notifications"
asset.name: "notification"
icon.name: "notification"
components: [
StatusSwitch {}
]
@@ -88,7 +87,7 @@ StatusModal {
anchors.horizontalCenter: parent.horizontalCenter
statusListItemTitle.font.pixelSize: 17
title: "Edit community"
asset.name: "edit"
icon.name: "edit"
type: StatusListItem.Type.Secondary
}
@@ -96,7 +95,7 @@ StatusModal {
anchors.horizontalCenter: parent.horizontalCenter
statusListItemTitle.font.pixelSize: 17
title: "Transfer ownership"
asset.name: "exchange"
icon.name: "exchange"
type: StatusListItem.Type.Secondary
}
@@ -104,7 +103,8 @@ StatusModal {
anchors.horizontalCenter: parent.horizontalCenter
statusListItemTitle.font.pixelSize: 17
title: "Leave community"
asset.name: "arrow-left"
icon.name: "arrow-right"
icon.rotation: 180
type: StatusListItem.Type.Secondary
}
}
+57 -106
View File
@@ -10,113 +10,10 @@ import StatusQ.Core.Theme 0.1
import "data" 1.0
StatusSectionLayout {
StatusAppThreePanelLayout {
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
@@ -179,7 +76,7 @@ StatusSectionLayout {
topPadding: 8
bottomPadding: 8
placeholderText: "Search"
input.asset.name: "search"
input.icon.name: "search"
}
Column {
@@ -194,7 +91,7 @@ StatusSectionLayout {
anchors.horizontalCenter: parent.horizontalCenter
title: "Contact requests"
requestsCount: 3
onClicked: demoContactRequestsModal.open()
sensor.onClicked: demoContactRequestsModal.open()
}
StatusChatList {
@@ -269,4 +166,58 @@ StatusSectionLayout {
}
}
}
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-right"
icon.width: 14
iconRotation: 180
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
}
}
}
}
}
+109 -114
View File
@@ -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
StatusSectionLayout {
StatusScrollView {
id: root
QtObject {
@@ -31,129 +31,124 @@ StatusSectionLayout {
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
ColumnLayout {
id: column
spacing: 18
contentHeight: column.height + d.layoutVMargin
contentWidth: column.width + d.layoutHMargin
clip: true
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
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
}
}
}
// 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
StatusBaseText {
Layout.leftMargin: d.layoutHMargin
Layout.topMargin: 20
text: qsTr("Featured")
font.weight: Font.Bold
font.pixelSize: d.subtitlePixelSize
color: Theme.palette.directColor1
}
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
}
GridLayout {
id: featuredGrid
Layout.leftMargin: d.layoutHMargin
columns: 3
columnSpacing: d.stylePadding
rowSpacing: d.stylePadding
Repeater {
model: d.featuredCommunitiesModel
delegate: StatusCommunityCard {
locale: "es"
communityId: model.communityId
loaded: model.available
logo: model.logo
name: model.name
description: model.description
members: model.members
popularity: model.popularity
communityColor: model.communityColor
categories: ListModel {
ListElement { name: "sport"; emoji: "🎾"}
ListElement { name: "food"; emoji: "🥑"}
ListElement { name: "privacy"; emoji: "👻"}
}
onClicked: { d.navigateToCommunity(communityId) }
}
}
}
StatusBaseText {
Layout.leftMargin: d.layoutHMargin
Layout.topMargin: 20
text: qsTr("Featured")
font.weight: Font.Bold
font.pixelSize: d.subtitlePixelSize
color: Theme.palette.directColor1
}
StatusBaseText {
Layout.leftMargin: d.layoutHMargin
Layout.topMargin: 20
text: qsTr("Popular")
font.weight: Font.Bold
font.pixelSize: d.subtitlePixelSize
color: Theme.palette.directColor1
}
GridLayout {
id: featuredGrid
Layout.leftMargin: d.layoutHMargin
columns: 3
columnSpacing: d.stylePadding
rowSpacing: d.stylePadding
GridLayout {
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.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) }
}
}
}
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) }
}
}
onClicked: { d.navigateToCommunity(communityId) }
}
}
}
+78 -109
View File
@@ -1,6 +1,5 @@
import QtQuick 2.12
import QtQuick.Controls 2.14
import QtQuick.Layouts 1.12
import StatusQ.Core 0.1
import StatusQ.Popups 0.1
@@ -11,7 +10,7 @@ import StatusQ.Core.Theme 0.1
import "data" 1.0
StatusSectionLayout {
StatusAppThreePanelLayout {
id: root
property string communityDetailModalTitle: ""
@@ -23,101 +22,6 @@ StatusSectionLayout {
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
@@ -129,9 +33,8 @@ StatusSectionLayout {
chatInfoButton.title: "CryptoKitties"
chatInfoButton.subTitle: "128 Members"
chatInfoButton.asset.isImage: true
chatInfoButton.asset.name: "qrc:/demoapp/data/profile-image-1.jpeg"
chatInfoButton.asset.color: Theme.palette.miscColor6
chatInfoButton.image.source: "qrc:/demoapp/data/profile-image-1.jpeg"
chatInfoButton.icon.color: Theme.palette.miscColor6
chatInfoButton.onClicked: { chatInfoButtonClicked(); }
popupMenu: StatusPopupMenu {
@@ -261,11 +164,79 @@ StatusSectionLayout {
}
centerPanel: Item {
anchors.fill: parent
StatusBaseText {
anchors.centerIn: parent
font.pixelSize: 15
text: qsTr("Community content here")
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
}
}
@@ -302,10 +273,8 @@ StatusSectionLayout {
isVerified: model.isVerified
isUntrustworthy: model.isUntrustworthy
isContact: model.isContact
asset.name: model.icon
asset.isImage: (asset.name !== "")
asset.isLetterIdenticon: (asset.name === "")
asset.imgIsIdenticon: false
image.source: model.icon
image.isIdenticon: false
status: model.onlineStatus
}
}
@@ -8,7 +8,7 @@ import StatusQ.Core.Theme 0.1
import "data" 1.0
StatusSectionLayout {
StatusAppTwoPanelLayout {
id: root
leftPanel: Item {
@@ -41,7 +41,7 @@ StatusSectionLayout {
model: Models.demoProfileGeneralMenuItems
delegate: StatusNavigationListItem {
title: model.title
asset.name: model.icon
icon.name: model.icon
}
}
@@ -51,7 +51,7 @@ StatusSectionLayout {
model: Models.demoProfileSettingsMenuItems
delegate: StatusNavigationListItem {
title: model.title
asset.name: model.icon
icon.name: model.icon
}
}
@@ -65,7 +65,7 @@ StatusSectionLayout {
model: Models.demoProfileOtherMenuItems
delegate: StatusNavigationListItem {
title: model.title
asset.name: model.icon
icon.name: model.icon
}
}
}
File diff suppressed because one or more lines are too long
+3 -4
View File
@@ -35,7 +35,7 @@ ColumnLayout {
id: searchInput
Layout.fillWidth: true
input.asset.name: "search"
input.icon.name: "search"
placeholderText: "nickname.."
}
@@ -43,7 +43,7 @@ ColumnLayout {
id: contactBtn
icon.name: "tiny/tiny-contact"
identicon.asset.color: Theme.palette.primaryColor1
identicon.icon.color: Theme.palette.primaryColor1
onClicked: highlighted = !highlighted
}
@@ -51,7 +51,7 @@ ColumnLayout {
id: verifiedBtn
icon.name: "tiny/tiny-checkmark"
identicon.asset.color: Theme.palette.primaryColor1
identicon.icon.color: Theme.palette.primaryColor1
onClicked: highlighted = !highlighted
}
}
@@ -94,7 +94,6 @@ ColumnLayout {
nickName: model.nick
isVerified: model.isVerified
isContact: model.isContact
asset.isLetterIdenticon: true
}
}
+6
View File
@@ -0,0 +1,6 @@
#include "handler.h"
Handler::Handler(QObject *parent) : QObject(parent)
{
}
+16
View File
@@ -0,0 +1,16 @@
#ifndef HANDLER_H
#define HANDLER_H
#include <QObject>
class Handler : public QObject
{
Q_OBJECT
public:
explicit Handler(QObject *parent = nullptr);
signals:
void restartQml();
};
#endif // HANDLER_H
+29 -52
View File
@@ -63,11 +63,11 @@ StatusWindow {
}
}
StatusMainLayout {
StatusAppLayout {
id: appLayout
anchors.fill: parent
leftPanel: StatusAppNavBar {
appNavBar: StatusAppNavBar {
height: rootWindow.height
communityTypeRole: "sectionType"
@@ -105,34 +105,30 @@ StatusWindow {
}
}
rightPanel: Item {
appView: StackView {
id: stackView
anchors.fill: parent
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
}
}
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
StatusSectionLayout {
StatusAppTwoPanelLayout {
id: mainPageView
showHeader: false
function page(name, fillPage) {
storeSettings.fillPage = fillPage ? true : false
@@ -201,21 +197,11 @@ StatusWindow {
selected: viewLoader.source.toString().includes(title)
onClicked: mainPageView.page(title);
}
StatusNavigationListItem {
title: "StatusTextArea"
selected: viewLoader.source.toString().includes(title)
onClicked: mainPageView.page(title);
}
StatusNavigationListItem {
title: "StatusSelect"
selected: viewLoader.source.toString().includes(title)
onClicked: mainPageView.page(title);
}
StatusNavigationListItem {
title: "StatusComboBox"
selected: viewLoader.source.toString().includes(title)
onClicked: mainPageView.page(title);
}
StatusNavigationListItem {
title: "StatusAccountSelector"
selected: viewLoader.source.toString().includes(title)
@@ -302,11 +288,6 @@ 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);
}
StatusListSectionHeadline { text: "StatusQ.Popup" }
StatusNavigationListItem {
title: "StatusPopupMenu"
@@ -352,8 +333,8 @@ StatusWindow {
}
}
centerPanel: Item {
id: centerPanel
rightPanel: Item {
id: rightPanel
anchors.fill: parent
StatusScrollView {
@@ -366,7 +347,7 @@ StatusWindow {
Item {
id: pageWrapper
width: centerPanel.width
width: rightPanel.width
anchors.top: parent.top
height: Math.max(rootWindow.height, viewLoader.height + 128)
scale: rootWindow.factor
@@ -424,9 +405,8 @@ StatusWindow {
Component {
id: examplesCmp
StatusSectionLayout {
StatusAppTwoPanelLayout {
id: examplesView
showHeader: false
function example(name) {
examplesLoader.source = Qt.resolvedUrl("./examples/" + name + ".qml")
@@ -454,19 +434,16 @@ StatusWindow {
}
}
centerPanel: Item {
rightPanel: StatusScrollView {
id: examplesRightPanel
anchors.fill: parent
StatusScrollView {
id: examplesCenterPanel
anchors.fill: parent
anchors.margins: 64
anchors.topMargin: anchors.margins + 32
anchors.margins: 64
anchors.topMargin: anchors.margins + 32
Loader {
id: examplesLoader
width: examplesCenterPanel.availableWidth
source: storeSettings.selectedExample !== "" ? storeSettings.selectedExample : examplesView.defaultExampleSource
}
Loader {
id: examplesLoader
width: examplesRightPanel.availableWidth
source: storeSettings.selectedExample !== "" ? storeSettings.selectedExample : examplesView.defaultExampleSource
}
}
}
+47 -51
View File
@@ -8,61 +8,57 @@ import StatusQ.Core.Theme 0.1
import StatusQ.Controls 0.1
import StatusQ.Popups 0.1
Column {
spacing: 8
StatusAccountSelector {
id: selector1
width: 300
accounts: accountsModel
}
ListModel {
id: accountsModel
ListElement {
name: "Pascal"
address: "0x1234567891011"
path: ""
color: "red"
publicKey: ""
walletType: "generated"
isChat: ""
currencyBalance: "1199.02"
assets: []
}
ListElement {
name: "Boris"
address: "0x123"
path: ""
color: "red"
publicKey: ""
walletType: "generated"
isChat: ""
currencyBalance: "42.42"
assets: []
}
ListElement {
name: "Alexandra"
address: "0x123"
path: ""
color: "yellow"
publicKey: ""
walletType: "generated"
isChat: ""
currencyBalance: "0"
assets: []
}
ListElement {
name: "Khushboo"
address: "0x123"
path: ""
color: "blue"
publicKey: ""
walletType: "watch" // Will be automatically filtered by StatusAccountSelector
isChat: ""
currencyBalance: "0"
assets: []
id: accountSelector
accounts: ListModel {
ListElement {
name: "Pascal"
address: "0x1234567891011"
path: ""
color: "red"
publicKey: ""
walletType: "generated"
isChat: ""
currencyBalance: "1199.02"
assets: []
}
ListElement {
name: "Boris"
address: "0x123"
path: ""
color: "red"
publicKey: ""
walletType: "generated"
isChat: ""
currencyBalance: "0"
assets: []
}
ListElement {
name: "Alexandra"
address: "0x123"
path: ""
color: "yellow"
publicKey: ""
walletType: "generated"
isChat: ""
currencyBalance: "0"
assets: []
}
ListElement {
name: "Khushboo"
address: "0x123"
path: ""
color: "blue"
publicKey: ""
walletType: "generated"
isChat: ""
currencyBalance: "0"
assets: []
}
}
}
}
+9 -82
View File
@@ -2,97 +2,24 @@ import QtQuick 2.14
import QtQuick.Controls 2.14
import QtQuick.Layouts 1.14
import StatusQ.Core 0.1
import StatusQ.Components 0.1
import Sandbox 0.1
Item {
id: root
Column {
spacing: 8
implicitWidth: mainLayout.implicitWidth
implicitHeight: mainLayout.implicitHeight
StatusAddress {
text: "0x9ce0056c5fc6bb9459a4dcfa35eaad8c1fee5ce9"
}
GridLayout {
id: mainLayout
columns: 2
anchors.fill: parent
columnSpacing: 15
rowSpacing: 8
StatusBaseText { text: "StatusAddress\nsimple" }
Item {
width: 200
height: childrenRect.height
StatusAddress {
text: "0x9ce0056c5fc6bb9459a4dcfa35eaad8c1fee5ce9"
}
StatusBaseText { text: "StatusAddress\nclick-expandable" }
StatusAddress {
text: "0x9ce0056c5fc6bb9459a4dcfa35eaad8c1fee5ce9"
Layout.preferredWidth: 200
expandable: true
}
StatusBaseText { text: `StatusAddressPanel\nfont.pixelSize: 13, copyable, no frame`}
StatusAddressPanel {
address: "0xDC2c4826f6C56F61C1b9cC6Bb531d0Fe45402fC9"
font.pixelSize: 13
font.weight: Font.Normal
showFrame: false
onDoCopy: copyAction.text = address
}
StatusBaseText { text: `StatusAddressPanel\ncompact; width ${simpleAddressPanel.width}px ${simpleAddressPanel.height}px`}
StatusAddressPanel {
id: simpleAddressPanel
address: "0xd8593DEACe2f44dF35dd23fD2BAFC2daeC2ae033"
showCopy: false
expanded: false
onDoCopy: copyAction.text = address
expandable: true
}
StatusBaseText { text: "StatusAddressPanel\ncopy-icon, non-expandable" }
StatusAddressPanel {
address: "0xDd5A0755e99D66a583253372B569231968A6CF7b"
onDoCopy: copyAction.text = address
}
StatusBaseText { text: "StatusAddressPanel\ncopy hiden" }
StatusAddressPanel {
address: "0xd2D44C2A1E78975506e474Ecdc7E4F272D7e9A6c"
autHideCopyIcon: true
onDoCopy: copyAction.text = address
expandable: true
}
StatusBaseText { text: "StatusAddressPanel\ncopy hiden, non-expandable" }
StatusAddressPanel {
address: "0xd2a44BA31E78975506e474Ecdc7E4F272D7F3BC5"
autHideCopyIcon: true
expanded: false
onDoCopy: copyAction.text = address
}
Rectangle {
color: "lightblue"
Layout.fillWidth: true
Layout.columnSpan: mainLayout.columns
Layout.preferredHeight: 2
}
StatusBaseText {
text: qsTr("Copy Action: ")
}
StatusBaseText {
id: copyAction
width: parent.width
}
}
}
+34 -20
View File
@@ -19,24 +19,9 @@ Item {
spacing: 20
RowLayout {
Layout.fillWidth: true
StatusCard {
id: card
Layout.alignment: Qt.AlignVCenter
primaryText: "Mainnet"
secondaryText: state === "unavailable" ? "No Gas" : "75"
tertiaryText: state === "unpreferred" ? "UNPREFERRED" : "BALANCE: " + 250
cardIconName: "status"
advancedInputText: "75"
disabledText: "Disabled"
}
StatusComboBox {
Layout.alignment: Qt.AlignVCenter
Layout.maximumWidth: 200
label: "Card State"
onCurrentValueChanged: card.state = currentValue
StatusSelect {
id: select
label: "Select Card State"
model: ListModel {
ListElement {
name: "default"
@@ -51,18 +36,47 @@ Item {
name: "unpreferred"
}
}
selectMenu.delegate: StatusMenuItemDelegate {
statusPopupMenu: select
action: StatusMenuItem {
text: name
onTriggered: {
selectedItem.text = name
card.state = name
}
}
}
selectedItemComponent: Item {
id: selectedItem
anchors.fill: parent
property string text: "default"
StatusBaseText {
text: selectedItem.text
anchors.centerIn: parent
color: Theme.palette.directColor1
}
}
}
StatusCheckBox {
Layout.alignment: Qt.AlignVCenter
text: "advancedMode"
font.family: Theme.palette.monoFont.name
onClicked: {
card.advancedMode = checked
}
}
}
StatusCard {
id: card
primaryText: "Mainnet"
secondaryText: state === "unavailable" ? "No Gas" : "75"
tertiaryText: state === "unpreferred" ? "UNPREFERRED" : "BALANCE: " + 250
cardIconName: "status"
advancedInputText: "75"
disabledText: "Disabled"
}
Rectangle {
height: 1
width: 700
+2 -3
View File
@@ -14,9 +14,8 @@ GridLayout {
StatusChatInfoToolBar {
chatInfoButton.title: "Cryptokitties"
chatInfoButton.subTitle: "128 Members"
chatInfoButton.asset.isImage: true
chatInfoButton.asset.name: "qrc:/demoapp/data/profile-image-1.jpeg"
chatInfoButton.asset.color: Theme.palette.miscColor6
chatInfoButton.image.source: "qrc:/demoapp/data/profile-image-1.jpeg"
chatInfoButton.icon.color: Theme.palette.miscColor6
popupMenu: StatusPopupMenu {
+1 -1
View File
@@ -8,7 +8,7 @@ import StatusQ.Controls 0.1
import Sandbox 0.1
Row {
Column {
spacing: 8
StatusColorSelector {
-72
View File
@@ -1,72 +0,0 @@
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.Popups 0.1
import Sandbox 0.1
Column {
spacing: 20
ListModel {
id: commmonModel
ListElement {
name: "Pascal"
}
ListElement {
name: "Khushboo"
}
ListElement {
name: "Alexandra"
}
ListElement {
name: "Eric"
}
}
StatusComboBox {
id: combobox
label: "ComboBox"
model: commmonModel
}
StatusComboBox {
id: comboBox1
label: "ComboBox with custom delegate"
model: commmonModel
delegate: StatusItemDelegate {
width: comboBox1.control.width
highlighted: comboBox1.control.highlightedIndex === index
text: modelData
font: comboBox1.control.font
icon {
name: "filled-account"
color: Theme.palette.primaryColor1
}
enabled: index != 2
}
}
StatusComboBox {
model: commmonModel
label: "Disabled ComboBox"
enabled: false
}
StatusComboBox {
model: commmonModel
label: "ComboBox with validation error"
validationError: "Validation failed example"
}
StatusComboBox {
model: commmonModel
label: "Mirrored ComboBox"
LayoutMirroring.enabled: true
}
}
+1 -1
View File
@@ -36,7 +36,7 @@ Item {
leftPadding: 0
rightPadding: 0
label: qsTr("Select tags that will fit your Community")
input.asset.name: "search"
input.icon.name: "search"
placeholderText: qsTr("Search tags")
Layout.fillWidth: true
}
@@ -26,7 +26,7 @@ Column {
anchors.horizontalCenter: parent.horizontalCenter
expandable: false
asset.name: "seed-phrase"
icon.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
asset.name: "secret"
icon.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
asset.name: "seed-phrase"
icon.name: "seed-phrase"
primaryText: "View private key"
secondaryText: "Back up your seed phrase now to secure this account"
expandableComponent: notImplemented
@@ -74,8 +74,7 @@ Column {
type: StatusExpandableItem.Type.Secondary
expandable: true
asset.isImage: true
asset.name: "qrc:/demoapp/data/profile-image-1.jpeg"
image.source: "qrc:/demoapp/data/profile-image-1.jpeg"
primaryText: "CryptoKitties"
additionalText: "1456 USD"
expandableComponent: notImplemented
@@ -86,8 +85,7 @@ Column {
type: StatusExpandableItem.Type.Secondary
expandable: true
asset.isImage: true
asset.name: "qrc:/demoapp/data/profile-image-1.jpeg"
image.source: "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
+19 -184
View File
@@ -1,20 +1,11 @@
import QtQuick 2.14
import QtQuick.Controls 2.14
import QtQuick.Layouts 1.14
import QtQuick.Dialogs 1.3
import QtQml 2.14
import StatusQ.Controls 0.1
import StatusQ.Components 0.1
import QtGraphicalEffects 1.14
import StatusQ.Components 0.1
import StatusQ.Controls 0.1
import StatusQ.Core 0.1
import StatusQ.Core.Theme 0.1
import StatusQ.Popups 0.1
Item {
id: root
@@ -24,12 +15,6 @@ Item {
property var testControls: [ctrl1, ctrl2, ctrl3]
property bool globalStylePreferRound: true
property var testImageList: ["qrc:/demoapp/data/logo-test-image.png",
"qrc:/demoapp/data/profile-image-2.jpeg",
"qrc:/demoapp/data/profile-image-1.jpeg"]
property int testImageIndex: 0
property int testSpacing: 0
property int testFrameMargins: 10
ColumnLayout {
id: mainLayout
@@ -37,12 +22,7 @@ Item {
anchors.fill: parent
RowLayout {
spacing: root.testSpacing
ColumnLayout {
spacing: root.testSpacing
Layout.margins: root.testSpacing
Text {
text: `AR: ${ctrl1.aspectRatio.toFixed(2)}`
}
@@ -52,9 +32,8 @@ Item {
Layout.fillWidth: true
Layout.fillHeight: true
source: root.testImageList[root.testImageIndex]
source: "qrc:/demoapp/data/logo-test-image.png"
windowStyle: globalStylePreferRound ? StatusImageCrop.WindowStyle.Rounded : StatusImageCrop.WindowStyle.Rectangular
margins: root.testFrameMargins
}
Text {
text: `AR: ${ctrl2.aspectRatio.toFixed(2)}`
@@ -64,15 +43,13 @@ Item {
Layout.fillWidth: true
Layout.fillHeight: true
source: root.testImageList[root.testImageIndex]
source: "qrc:/demoapp/data/logo-test-image.png"
windowStyle: globalStylePreferRound ? StatusImageCrop.WindowStyle.Rectangular : StatusImageCrop.WindowStyle.Rounded
aspectRatio: 16/9
enableCheckers: true
margins: root.testFrameMargins + 2
}
}
ColumnLayout {
Layout.margins: root.testSpacing
Text {
text: `AR: ${ctrl3.aspectRatio.toFixed(2)}`
}
@@ -82,178 +59,36 @@ Item {
Layout.fillWidth: true
Layout.fillHeight: true
source: root.testImageList[root.testImageIndex]
source: "qrc:/demoapp/data/logo-test-image.png"
windowStyle: globalStylePreferRound ? StatusImageCrop.WindowStyle.Rounded : StatusImageCrop.WindowStyle.Rectangular
aspectRatio: 0.8
margins: root.testFrameMargins + 5.3
}
}
}
RowLayout {
StatusButton {
text: qsTr("Cycle image")
onClicked: {
let newIndex = root.testImageIndex
newIndex++
if(newIndex >= root.testImageList.length)
newIndex = 0
root.testImageIndex = newIndex
}
}
StatusButton {
text: qsTr("Cycle spacing")
onClicked: {
root.testSpacing += (root.testSpacing/2) + 1
if(root.testSpacing > 35)
root.testSpacing = 0
}
}
StatusButton {
text: qsTr("Cycle frame margins")
onClicked: {
root.testFrameMargins += (root.testFrameMargins/2) + 1
if(root.testFrameMargins > 50)
root.testFrameMargins = 0
}
}
StatusButton {
text: qsTr("Load external image")
onClicked: workflowLoader.active = true
}
}
}
Loader {
id: workflowLoader
sourceComponent: workflowComponent
active: false
onStatusChanged: {
if(status === Loader.Ready) {
item.imageFileDialogTitle = qsTr("Test Title")
item.title = "Test popup"
item.acceptButtonText = "Load Custom Image"
item.chooseImageToCrop()
Shortcut {
sequence: StandardKey.ZoomIn
onActivated: {
for(let i in testControls) {
const c = testControls[i]
c.setCropRect(ctrl1.inflateRectBy(c.cropRect, -0.05))
}
}
}
Connections {
target: workflowLoader.item
function onImageCropped(image, cropRect) {
ctrl1.source = image
ctrl2.source = image
ctrl3.source = image
}
function onCanceled() {
workflowLoader.active = false
}
}
}
Component {
id: workflowComponent
Item {
id: workflowItem
property alias aspectRatio: imageCropper.aspectRatio
property alias windowStyle: imageCropper.windowStyle
/*required*/ property string imageFileDialogTitle: ""
/*required*/ property string title: ""
/*required*/ property string acceptButtonText: ""
property bool roundedImage: true
signal imageCropped(var image, var cropRect)
signal canceled()
function chooseImageToCrop() {
fileDialog.open()
}
FileDialog {
id: fileDialog
title: workflowItem.imageFileDialogTitle
folder: workflowItem.userSelectedImage ? imageCropper.source.substr(0, imageCropper.source.lastIndexOf("/")) : shortcuts.pictures
nameFilters: [qsTr("Supported image formats (%1)").arg("*.jpg *.jpeg *.jfif *.webp *.png *.heif")]
onAccepted: {
if (fileDialog.fileUrls.length > 0) {
imageCropper.source = fileDialog.fileUrls[0]
imageCropperModal.open()
}
Shortcut {
sequence: StandardKey.ZoomOut
onActivated: {
for(let i in testControls) {
const c = testControls[i]
c.setCropRect(ctrl1.inflateRectBy(c.cropRect, 0.05))
}
onRejected: workflowItem.canceled()
} // FileDialog
StatusModal {
id: imageCropperModal
header.title: workflowItem.title
anchors.centerIn: Overlay.overlay
width: workflowItem.roundedImage ? 480 : 580
onClosed: workflowItem.canceled()
StatusImageCropPanel {
id: imageCropper
implicitHeight: workflowItem.roundedImage ? 350 : 370
anchors {
fill: parent
leftMargin: 10 * 2
rightMargin: 10 * 2
topMargin: 15
bottomMargin: 15
}
margins: workflowItem.roundedImage ? 10 : 20
windowStyle: workflowItem.roundedImage ? StatusImageCrop.WindowStyle.Rounded : StatusImageCrop.WindowStyle.Rectangular
enableCheckers: true
}
rightButtons: [
StatusButton {
text: workflowItem.acceptButtonText
enabled: imageCropper.sourceSize.width > 0 && imageCropper.sourceSize.height > 0
onClicked: {
workflowItem.imageCropped(imageCropper.source, imageCropper.cropRect)
imageCropperModal.close()
}
}
]
} // StatusModal
} // Item
}
Shortcut {
sequence: StandardKey.ZoomIn
onActivated: {
for(let i in testControls) {
const c = testControls[i]
c.setCropRect(ctrl1.inflateRectBy(c.cropRect, -0.05))
}
}
}
Shortcut {
sequence: StandardKey.ZoomOut
onActivated: {
for(let i in testControls) {
const c = testControls[i]
c.setCropRect(ctrl1.inflateRectBy(c.cropRect, 0.05))
}
Shortcut {
sequences: ["Ctrl+W"]
onActivated: globalStylePreferRound = !globalStylePreferRound
}
}
Shortcut {
sequences: ["Ctrl+W"]
onActivated: globalStylePreferRound = !globalStylePreferRound
}
}
+16 -41
View File
@@ -33,8 +33,9 @@ Column {
StatusInput {
label: "Label"
input.asset.name: "search"
input.placeholderText: "Input with icon"
input.icon.name: "search"
placeholderText: "Input with icon"
}
StatusInput {
@@ -56,15 +57,6 @@ Column {
input.clearable: true
}
StatusPasswordInput {
placeholderText: "Password"
}
StatusPasswordInput {
signingPhrase: "orange hello cygnet"
placeholderText: "Password"
}
Item {
implicitWidth: 480
implicitHeight: 82
@@ -77,34 +69,19 @@ Column {
textEdit.input.anchors.leftMargin: 16
textEdit.input.anchors.rightMargin: 16
textEdit.input.anchors.topMargin: 11
textEdit.label: "Input with drop down selection list" + (insertedWord ? ` (${insertedWord})` : "")
textEdit.label: "Input with drop down selection list"
leftComponentText: "1"
inputList: ListModel {
ListElement {
seedWord: "add"
}
ListElement {
seedWord: "address"
}
ListElement {
seedWord: "panda"
}
ListElement {
seedWord: "posible"
}
ListElement {
seedWord: "win"
}
ListElement {
seedWord: "wine"
}
ListElement {
seedWord: "wing"
}
}
property string insertedWord: ""
onDoneInsertingWord: insertedWord = word
}
}
@@ -120,9 +97,9 @@ Column {
StatusInput {
label: "StatusInput"
secondaryLabel: "with right icon"
input.asset.width: 15
input.asset.height: 11
input.asset.name: text !== "" ? "checkmark" : ""
input.icon.width: 15
input.icon.height: 11
input.icon.name: text !== "" ? "checkmark" : ""
input.leftIcon: false
}
@@ -130,8 +107,7 @@ Column {
label: "Label"
secondaryLabel: "secondary label"
placeholderText: "Placeholder"
minimumHeight: 56
maximumHeight: 56
input.implicitHeight: 56
}
StatusInput {
@@ -186,8 +162,7 @@ Column {
StatusInput {
input.multiline: true
placeholderText: "Multiline with static height"
minimumHeight: 100
maximumHeight: 100
input.implicitHeight: 100
}
StatusInput {
@@ -200,9 +175,9 @@ Column {
StatusInput {
property bool toggled: true
label: "Input with emoji icon"
input.placeholderText: "Enter Name"
input.asset.emoji: toggled ? "😁" : "🧸"
input.asset.color: "blue"
placeholderText: "Enter Name"
input.icon.emoji: toggled ? "😁" : "🧸"
input.icon.color: "blue"
input.isIconSelectable: true
onIconClicked: {
toggled = !toggled
@@ -212,10 +187,10 @@ Column {
StatusInput {
property bool toggled: true
label: "Input with selectable icon which is not an emoji"
input.placeholderText: "Enter Name"
input.asset.emoji: ""
input.asset.name: toggled ? "filled-account" : "image"
input.asset.color: "blue"
placeholderText: "Enter Name"
input.icon.emoji: ""
input.icon.name: toggled ? "filled-account" : "image"
input.icon.color: "blue"
input.isIconSelectable: true
onIconClicked: {
toggled = !toggled
+3 -22
View File
@@ -1,4 +1,4 @@
import QtQuick 2.14
import QtQuick 2.0
import QtQuick.Layouts 1.14
import StatusQ.Components 0.1
@@ -15,44 +15,25 @@ ColumnLayout {
defaultItemText: "Example: Empty items"
andOperatorText: "and"
orOperatorText: "or"
itemsModel: ListModel {
id: model
}
StatusDropdown {
popupItem: 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: {
model.append({
text: input.text,
imageSource: "qrc:/images/SNT.png",
operator: model.count > 0 ? Utils.Operators.Or : Utils.Operators.None
})
selector.addItem(input.text, "qrc:/images/SNT.png", selector.itemsModel.count > 0 ? Utils.Operators.Or : Utils.Operators.None)
dropdown.close()
}
}
}
}
addButton.onClicked: {
dropdown.x = mouse.x
dropdown.y = mouse.y
dropdown.open()
}
}
StatusButton {
+1 -2
View File
@@ -34,7 +34,6 @@ GridLayout {
inputList: Models.languageNoImagePickerModel
placeholderSearchText: qsTr("Search Languages")
menuAlignment: StatusListPicker.MenuAlignment.Center
multiSelection: true
}
StatusListPicker {
@@ -61,7 +60,7 @@ GridLayout {
width: 500
text: "4 different configurations for the `StatusListPicker` component:\n
* Single selection. \n
* Multiple selection without images.\n
* Single selection but dynamically changed to multiple selection (model provides multiple selected items).\n
* Multiple selection.\n
* Multiple selection and displayed name is the symbol + shortName\n"
color: Theme.palette.baseColor1
+16 -18
View File
@@ -55,30 +55,30 @@ GridLayout {
StatusMenuItem {
text: "One"
assetSettings.name: "info"
iconSettings.name: "info"
}
StatusMenuSeparator {}
StatusMenuItem {
text: "Two"
assetSettings.name: "info"
iconSettings.name: "info"
}
StatusMenuItem {
text: "Three"
assetSettings.name: "info"
iconSettings.name: "info"
}
StatusPopupMenu {
title: "Four"
StatusMenuItem {
text: "One"
assetSettings.name: "info"
iconSettings.name: "info"
}
StatusMenuItem {
text: "Three"
assetSettings.name: "info"
iconSettings.name: "info"
}
}
}
@@ -108,16 +108,14 @@ GridLayout {
StatusMenuItem {
text: "vitalik.eth"
assetSettings.isImage: true
assetSettings.name: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAlklEQVR4nOzW0QmDQBAG4SSkl7SUQlJGCrElq9F3QdjjVhh/5nv3cFhY9vUIYQiNITSG0Bh
image.source: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAlklEQVR4nOzW0QmDQBAG4SSkl7SUQlJGCrElq9F3QdjjVhh/5nv3cFhY9vUIYQiNITSG0Bh
CExPynn1gWf9bx498P7/nzPcxEzGExhBdJGYihtAYQlO+tUZvqrPbqeudo5iJGEJjCE15a3VtodH3q2ImYgiNITTlTdG1nUZ5a92VITQxITFiJmIIjSE0htAYQrMHAAD//+wwFVpz+yqXAAAAAElFTkSuQmCC"
assetSettings.imgIsIdenticon: true
image.isIdenticon: true
}
StatusMenuItem {
text: "Pascal"
assetSettings.isImage: true
assetSettings.name: "qrc:/demoapp/data/profile-image-1.jpeg"
image.source: "qrc:/demoapp/data/profile-image-1.jpeg"
}
}
@@ -126,21 +124,21 @@ CExPynn1gWf9bx498P7/nzPcxEzGExhBdJGYihtAYQlO+tUZvqrPbqeudo5iJGEJjCE15a3VtodH3q2I
StatusMenuItem {
text: "welcome"
assetSettings.name: "channel"
assetSettings.color: Theme.palette.directColor1
iconSettings.name: "channel"
iconSettings.color: Theme.palette.directColor1
}
StatusMenuItem {
text: "support"
assetSettings.name: "channel"
assetSettings.color: Theme.palette.directColor1
iconSettings.name: "channel"
iconSettings.color: Theme.palette.directColor1
}
StatusMenuHeadline { text: "Public" }
StatusMenuItem {
text: "news"
assetSettings.name: "channel"
assetSettings.color: Theme.palette.directColor1
iconSettings.name: "channel"
iconSettings.color: Theme.palette.directColor1
}
}
@@ -149,8 +147,8 @@ CExPynn1gWf9bx498P7/nzPcxEzGExhBdJGYihtAYQlO+tUZvqrPbqeudo5iJGEJjCE15a3VtodH3q2I
StatusMenuItem {
text: "welcome"
assetSettings.isLetterIdenticon: true
assetSettings.bgColor: "red"
iconSettings.isLetterIdenticon: true
iconSettings.background.color: "red"
}
}
}
+16 -29
View File
@@ -8,49 +8,36 @@ import StatusQ.Controls 0.1
import StatusQ.Popups 0.1
import Sandbox 0.1
Column {
spacing: 20
ListModel {
id: commmonModel
ListElement {
name: "Pascal"
}
ListElement {
name: "Khushboo"
}
ListElement {
name: "Alexandra"
}
ListElement {
name: "Eric"
}
}
StatusBaseText {
font.pixelSize: 16
color: Theme.palette.dangerColor1
text: "This component should no longer be used.<br />Please, use `StatusComboBox` instead."
textFormat: Text.MarkdownText
}
spacing: 8
StatusSelect {
id: select
label: "Some label"
model: commmonModel
model: ListModel {
ListElement {
name: "Pascal"
}
ListElement {
name: "Khushboo"
}
ListElement {
name: "Alexandra"
}
ListElement {
name: "Eric"
}
}
selectMenu.delegate: StatusMenuItemDelegate {
statusPopupMenu: select
action: StatusMenuItem {
assetSettings.name: "filled-account"
iconSettings.name: "filled-account"
text: name
onTriggered: {
selectedItem.text = name
}
}
}
selectedItemComponent: Item {
id: selectedItem
anchors.fill: parent
-61
View File
@@ -1,61 +0,0 @@
import QtQuick 2.14
import QtQuick.Controls 2.14
import StatusQ.Core 0.1
import StatusQ.Core.Theme 0.1
import StatusQ.Controls 0.1
Column {
id: root
spacing: 8
Component.onCompleted: {
focusedTextArea.forceActiveFocus()
}
StatusTextArea {
id: focusedTextArea
width: parent.width
placeholderText: "Initially focused text area"
KeyNavigation.tab: unfocusedTextArea
}
StatusTextArea {
id: unfocusedTextArea
width: parent.width
placeholderText: "Unfocused text area (hover me to see the color change)"
KeyNavigation.tab: invalidTextArea
}
StatusTextArea {
id: invalidTextArea
width: parent.width
valid: false
placeholderText: "Invalid text area, should display red border"
KeyNavigation.tab: longTextArea
}
StatusScrollView {
padding: 0 // use our own (StatusTextArea) padding
width: parent.width
height: 120
TextArea.flickable: longTextArea
StatusTextArea {
id: longTextArea
text: "Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Integer imperdiet lectus quis justo. Sed vel lectus. \
Donec odio tempus molestie, porttitor ut, iaculis quis, sem. Morbi scelerisque luctus velit. Nunc auctor. Nullam at \
arcu a est sollicitudin euismod. Cras elementum. Class aptent taciti sociosqu ad litora torquent per conubia nostra, \
per inceptos hymenaeos. Fusce aliquam vestibulum ipsum. Etiam sapien elit, consequat eget, tristique non, venenatis quis, ante. \
Nullam sit amet magna in magna gravida vehicula. Cras pede libero, dapibus nec, pretium sit amet, tempor quis. Nullam faucibus \
mi quis velit. Nam sed tellus id magna elementum tincidunt. Duis bibendum, lectus ut viverra rhoncus, dolor nunc faucibus libero, \
eget facilisis enim ipsum id lacus. Maecenas aliquet accumsan leo. Aliquam erat volutpat."
KeyNavigation.tab: focusedTextArea
}
}
StatusTextArea {
enabled: false
placeholderText: "Disabled text area"
}
}
+3 -1
View File
@@ -44,6 +44,7 @@
<file>images/SuperRareCommunityBanner.png</file>
<file>pages/StatusAccountSelectorPage.qml</file>
<file>pages/StatusAddressPage.qml</file>
<file>pages/StatusAssetSelectorPage.qml</file>
<file>pages/StatusCardPage.qml</file>
<file>pages/StatusChatCommandButtonPage.qml</file>
<file>pages/StatusChatInfoToolBarPage.qml</file>
@@ -75,8 +76,9 @@
<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/StatusComboBoxPage.qml</file>
</qresource>
</RCC>
+7 -17
View File
@@ -3,20 +3,15 @@
#include <QQmlContext>
#include <QWindow>
#include <QDebug>
#include <QDirIterator>
#include "statuswindow.h"
#include "spellchecker.h"
SandboxApp::SandboxApp(int &argc, char **argv)
: QGuiApplication(argc, argv)
: QGuiApplication(argc, argv),
m_handler(new Handler(this))
{
#ifdef QT_DEBUG
connect(&m_watcher, &QFileSystemWatcher::directoryChanged, [this](const QString&) {
restartEngine();
});
#endif
connect(m_handler, &Handler::restartQml, this, &SandboxApp::restartEngine, Qt::QueuedConnection);
}
void SandboxApp::startEngine()
@@ -26,18 +21,13 @@ void SandboxApp::startEngine()
#ifdef QT_DEBUG
const QUrl url = QUrl::fromLocalFile(SRC_DIR + QStringLiteral("/main.qml"));
m_watcher.addPath(applicationDirPath() + "/../");
QDirIterator it(applicationDirPath() + "/../", QDir::Dirs | QDir::NoDotAndDotDot, QDirIterator::Subdirectories);
while (it.hasNext()) {
if (!it.filePath().isEmpty()) {
m_watcher.addPath(it.filePath());
}
it.next();
}
#else
const QUrl url(QStringLiteral("qrc:/main.qml"));
#endif
m_engine.rootContext()->setContextProperty("app", m_handler);
#ifdef QT_DEBUG
m_engine.addImportPath(SRC_DIR + QStringLiteral("/../src"));
#else
@@ -54,7 +44,7 @@ void SandboxApp::startEngine()
void SandboxApp::restartEngine()
{
const QUrl url = QUrl::fromLocalFile(SRC_DIR + QStringLiteral("/main.qml"));
const QUrl url(applicationDirPath() + "/../main.qml");
QWindow *rootWindow = qobject_cast<QWindow*>(m_engine.rootObjects().at(0));
if (rootWindow) {
rootWindow->close();
+2 -7
View File
@@ -4,9 +4,7 @@
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#ifdef QT_DEBUG
#include <QFileSystemWatcher>
#endif
#include "handler.h"
class SandboxApp : public QGuiApplication
{
@@ -20,10 +18,7 @@ public slots:
private:
QQmlApplicationEngine m_engine;
#ifdef QT_DEBUG
QFileSystemWatcher m_watcher;
#endif
Handler *m_handler;
};
#endif // SANDBOXAPP_H
+3 -3
View File
@@ -4,7 +4,6 @@ import StatusQ.Core 0.1
import StatusQ.Core.Theme 0.1
import StatusQ.Controls 0.1
/// Forces size, hard to reuse it
StatusBaseText {
id: root
@@ -19,6 +18,7 @@ StatusBaseText {
color: Theme.palette.baseColor1
Component.onCompleted: {
maxWidth = width
expanded = actualWidth <= maxWidth
}
@@ -29,9 +29,9 @@ StatusBaseText {
onClicked: {
if (root.expanded) {
root.width = root.maxWidth
width = root.width = root.maxWidth
} else {
root.width = root.actualWidth
width = root.width = root.actualWidth
}
root.expanded = !root.expanded
}
@@ -1,189 +0,0 @@
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
/*!
\qmltype StatusAddressPanel
\inherits Item
\inqmlmodule StatusQ.Components
\since StatusQ.Components 0.1
\brief Show an address as defined efined in design https://www.figma.com/file/FkFClTCYKf83RJWoifWgoX/Wallet-v2?node-id=4222%3A178403 and https://www.figma.com/file/h2Ab3k4wy1Y7SFHEvbcZZx/%E2%9A%99%EF%B8%8F-Settings-%7C-Desktop-(Copy)?node-id=1009%3A106451
Panel's components:
- Address: displays the rquired \c address property
- Frame: a rounded frame and the \c 0x icon prefix
- Copy action: clickable copy icon. Activable using \c showCopy
\qmlproperty string address address to show
\qmlproperty bool showCopy if \c true shows the copy action which triggers \c doCopy signal
\qmlproperty bool autHideCopyIcon if \c true shows the copy action when hovered. \see showCopy
\qmlproperty alias showFrame if \c true displays frame and \c 0x prefix
\qmlproperty bool expandable if \c true user can toggle between expanded and compact version; \see expanded
\qmlproperty bool expanded if \c true show address in full; if \c false show the address in compact mode eliding in the middle
\qmlproperty font: statusAddress.font
signal doCopy(string address)
\see StatusImageCrop for more details
Usage example:
\qml
StatusAddressPanel {
address: currentAccount.mixedcaseAddress
autHideCopyIcon: true
expanded: false
onDoCopy: (address) => root.store.copyToClipboard(address)
}
\endqml
For a list of components available see StatusQ.
*/
Item {
id: root
/*required*/ property string address: ""
property bool showCopy: true
property bool autHideCopyIcon: false
property alias showFrame: frameRect.visible
property bool expandable: false
property bool expanded: true
property alias font: statusAddress.font
signal doCopy(string address)
implicitWidth: frameLayout.implicitWidth
implicitHeight: frameLayout.implicitHeight
RowLayout {
id: frameLayout
anchors.fill: parent
RowLayout {
Layout.leftMargin: frameRect.visible ? 8 : undefined // Theme.geometry.halfPadding
Layout.rightMargin: Layout.leftMargin
Layout.alignment: Qt.AlignVCenter | Qt.AlignHCenter
Layout.minimumWidth: 120
Layout.preferredHeight: 32
spacing: 6
StatusIcon {
icon: "address"
Layout.alignment: Qt.AlignVCenter
Layout.preferredWidth: 19
Layout.preferredHeight: 19
visible: frameRect.visible
color: Theme.palette.baseColor1
opacity: 0.5
}
// Ensure the eliding is done in the middle of the value not taking into account `0x`
RowLayout {
spacing: 0
Layout.alignment: Qt.AlignVCenter
StatusBaseText {
text: "0x"
Layout.alignment: Qt.AlignVCenter
font: statusAddress.font
color: statusAddress.color
}
StatusBaseText {
id: statusAddress
text: root.address.replace("0x", "").replace("0X", "")
Layout.preferredWidth: expanded ? implicitWidth : (implicitWidth * 0.25).toFixed()
Layout.alignment: Qt.AlignVCenter
font.family: Theme.palette.monoFont.name
font.pixelSize: 15
font.weight: Font.Medium
elide: Text.ElideMiddle
color: Theme.palette.baseColor1
}
}
StatusIcon {
icon: "copy"
visible: root.autHideCopyIcon ? (mainMouseArea.containsMouse || copyMouseArea.containsMouse )
: root.showCopy
Layout.alignment: Qt.AlignVCenter
Layout.preferredWidth: (statusAddress.font.pixelSize * 1.2).toFixed()
Layout.preferredHeight: Layout.preferredWidth
color: Theme.palette.baseColor1
MouseArea {
id: copyMouseArea
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.ArrowCursor
preventStealing: true
onClicked: root.doCopy(root.address)
z: frameRect.z + 1
}
StatusIcon {
icon: parent.icon
x: 1
y: 1
width: parent.width
height: parent.height
visible: copyMouseArea.containsMouse && !copyMouseArea.pressed
color: "black"
opacity: 0.4
z: parent.z + 1
}
}
}
}
Rectangle {
id: frameRect
anchors.fill: frameLayout
color: "transparent"
border.width: 1
border.color: Theme.palette.baseColor2
radius: 36
}
MouseArea {
id: mainMouseArea
anchors.fill: parent
hoverEnabled: root.expandable || root.autHideCopyIcon
enabled: (root.autHideCopyIcon && root.showCopy) || root.expandable
acceptedButtons: root.expandable ? Qt.LeftButton : Qt.NoButton
cursorShape: root.expandable ? Qt.PointingHandCursor : Qt.ArrowCursor
onClicked: root.expanded = !root.expanded
z: frameLayout.z - 1
}
}
+5 -5
View File
@@ -239,7 +239,7 @@ Rectangle {
id: waitTimer
interval: lockTimeout
onTriggered: {
if(advancedInput.text)
if(advancedInput.edit.text)
advancedInput.locked = true
}
}
@@ -311,7 +311,7 @@ Rectangle {
}
PropertyChanges {
target: advancedInput
input.color: Theme.palette.directColor1
edit.color: Theme.palette.directColor1
}
PropertyChanges {
target: basicInput
@@ -370,7 +370,7 @@ Rectangle {
}
PropertyChanges {
target: advancedInput
input.edit.color: disabled ? Theme.palette.directColor5 : Theme.palette.dangerColor1
edit.color: disabled ? Theme.palette.directColor5 : Theme.palette.dangerColor1
}
PropertyChanges {
target: basicInput
@@ -429,7 +429,7 @@ Rectangle {
}
PropertyChanges {
target: advancedInput
input.color: Theme.palette.directColor1
edit.color: Theme.palette.directColor1
}
PropertyChanges {
target: basicInput
@@ -488,7 +488,7 @@ Rectangle {
}
PropertyChanges {
target: advancedInput
input.color: Theme.palette.directColor1
edit.color: Theme.palette.directColor1
}
PropertyChanges {
target: basicInput
+31 -59
View File
@@ -9,7 +9,7 @@ import StatusQ.Components 0.1
import StatusQ.Controls 0.1
Column {
id: root
id: statusChatList
spacing: 4
width: 288
@@ -23,6 +23,8 @@ Column {
property Component popupMenu
property var filterFn
signal chatItemSelected(string categoryId, string id)
signal chatItemUnmuted(string id)
signal chatItemReordered(string id, int from, int to)
@@ -33,36 +35,22 @@ Column {
}
}
onDraggableItemsChanged: delegateModel.items.setGroups(0, delegateModel.items.count, "unsorted")
QtObject {
id: d
property int destinationPosition: -1
}
DelegateModel {
id: delegateModel
model: root.model
items.includeByDefault: !root.draggableItems
groups: DelegateModelGroup {
id: unsortedItems
name: "unsorted"
includeByDefault: root.draggableItems
onChanged: Utils.delegateModelSort(unsortedItems, delegateModel.items,
(a, b) => a.position < b.position)
}
model: statusChatList.model
delegate: Item {
id: draggable
objectName: model.name
width: root.width
width: statusChatList.width
height: statusChatListItem.height
property alias chatListItem: statusChatListItem
visible: {
if (!!statusChatList.filterFn) {
return statusChatList.filterFn(model)
}
return true
}
MouseArea {
id: dragSensor
@@ -70,7 +58,7 @@ Column {
cursorShape: active ? Qt.ClosedHandCursor : Qt.PointingHandCursor
hoverEnabled: true
pressAndHoldInterval: 150
enabled: root.draggableItems
enabled: statusChatList.draggableItems
property bool active: false
property real startY: 0
@@ -86,8 +74,8 @@ Column {
}
onPressAndHold: active = true
onReleased: {
if (active && d.destinationPosition !== -1 && statusChatListItem.originalOrder !== d.destinationPosition) {
root.chatItemReordered(statusChatListItem.chatId, statusChatListItem.originalOrder, d.destinationPosition)
if (active) {
statusChatList.chatItemReordered(statusChatListItem.chatId, statusChatListItem.originalOrder, statusChatListItem.originalOrder)
}
active = false
}
@@ -101,7 +89,6 @@ Column {
active = true
}
}
onActiveChanged: d.destinationPosition = -1
StatusChatListItem {
id: statusChatListItem
@@ -117,34 +104,19 @@ Column {
hasUnreadMessages: model.hasUnreadMessages
notificationsCount: model.notificationsCount
highlightWhenCreated: !!model.highlight
selected: (model.active && root.highlightItem)
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
selected: (model.active && statusChatList.highlightItem)
icon.emoji: model.emoji
icon.color: !!model.color ? model.color : Theme.palette.userCustomizationColors[model.colorId]
image.isIdenticon: false
image.source: model.icon
ringSettings.ringSpecModel: model.colorHash
sensor.cursorShape: dragSensor.cursorShape
Connections {
target: statusChatListItem
enabled: root.draggableItems
function onOriginalOrderChanged() {
Qt.callLater(() => {
if (!delegateModel)
return
delegateModel.items.setGroups(0, delegateModel.items.count, "unsorted")
})
}
}
onClicked: {
highlightWhenCreated = false
if (mouse.button === Qt.RightButton && !!root.popupMenu) {
if (mouse.button === Qt.RightButton && !!statusChatList.popupMenu) {
statusChatListItem.highlighted = true
let originalOpenHandler = popupMenuSlot.item.openHandler
@@ -165,17 +137,17 @@ Column {
}
}
let p = statusChatListItem.mapToItem(root, mouse.x, mouse.y)
let p = statusChatListItem.mapToItem(statusChatList, mouse.x, mouse.y)
popupMenuSlot.item.popup(p.x + 4, p.y + 6)
popupMenuSlot.item.openHandler = originalOpenHandler
return
}
if (!statusChatListItem.selected) {
root.chatItemSelected(model.parentItemId, model.itemId)
statusChatList.chatItemSelected(model.parentItemId, model.itemId)
}
}
onUnmute: root.chatItemUnmuted(model.itemId)
onUnmute: statusChatList.chatItemUnmuted(model.itemId)
}
}
@@ -186,6 +158,7 @@ Column {
keys: ["chat-item-category-" + statusChatListItem.categoryId]
onEntered: reorderDelay.start()
onDropped: statusChatList.chatItemReordered(statusChatListItem.chatId, drag.source.originalOrder, statusChatListItem.DelegateModel.itemsIndex)
Timer {
id: reorderDelay
@@ -193,7 +166,7 @@ Column {
repeat: false
onTriggered: {
if (dropArea.containsDrag) {
d.destinationPosition = delegateModel.model.get(draggable.DelegateModel.itemsIndex).position
dropArea.drag.source.chatListItem.originalOrder = statusChatListItem.originalOrder
delegateModel.items.move(dropArea.drag.source.DelegateModel.itemsIndex, draggable.DelegateModel.itemsIndex)
}
}
@@ -227,9 +200,9 @@ Column {
notificationsCount: model.notificationsCount
selected: draggable.chatListItem.selected
asset.color: draggable.chatListItem.asset.color
asset.imgIsIdenticon: draggable.chatListItem.asset.imgIsIdenticon
asset.name: draggable.chatListItem.asset.name
icon.color: draggable.chatListItem.icon.color
image.isIdenticon: draggable.chatListItem.image.isIdenticon
image.source: draggable.chatListItem.image.source
}
}
}
@@ -237,12 +210,11 @@ Column {
Repeater {
id: statusChatListItems
objectName: "chatListItems"
model: delegateModel
}
Loader {
id: popupMenuSlot
active: !!root.popupMenu
active: !!statusChatList.popupMenu
}
}
@@ -7,10 +7,8 @@ import StatusQ.Components 0.1
import StatusQ.Popups 0.1
import StatusQ.Core 0.1
import SortFilterProxyModel 0.2
Item {
id: root
id: statusChatListAndCategories
implicitHeight: chatListsAndCategories.height
implicitWidth: chatListsAndCategories.width
@@ -32,7 +30,7 @@ Item {
property bool draggableCategories: false
// Keeps track of expanded category state. Should only be modified
// internally at runtime.
property var openedCategoryState: ({})
property var openedCategoryState: new Object({})
property Component categoryPopupMenu
property Component chatListPopupMenu
@@ -53,11 +51,11 @@ Item {
MouseArea {
id: sensor
anchors.top: parent.top
width: root.width
height: root.height
width: statusChatListAndCategories.width
height: statusChatListAndCategories.height
acceptedButtons: Qt.LeftButton | Qt.RightButton
onClicked: {
if (mouse.button === Qt.RightButton && showPopupMenu && !!root.popupMenu) {
if (mouse.button === Qt.RightButton && showPopupMenu && !!statusChatListAndCategories.popupMenu) {
popupMenuSlot.item.popup(mouse.x + 4, mouse.y + 6)
return
}
@@ -71,50 +69,24 @@ Item {
spacing: 4
StatusChatList {
objectName: "statusChatListAndCategoriesChatList"
id: statusChatList
visible: statusChatList.model.count > 0
onChatItemSelected: root.chatItemSelected(categoryId, id)
onChatItemUnmuted: root.chatItemUnmuted(id)
onChatItemReordered: root.chatItemReordered(categoryId, id, from, to)
draggableItems: root.draggableItems
model: SortFilterProxyModel {
sourceModel: root.model
filters: ValueFilter { roleName: "isCategory"; value: false }
sorters: RoleSorter { roleName: "position" }
onChatItemSelected: statusChatListAndCategories.chatItemSelected(categoryId, id)
onChatItemUnmuted: statusChatListAndCategories.chatItemUnmuted(id)
onChatItemReordered: statusChatListAndCategories.chatItemReordered(categoryId, id, from, to)
draggableItems: statusChatListAndCategories.draggableItems
model: statusChatListAndCategories.model
filterFn: function (model) {
return !model.isCategory
}
popupMenu: root.chatListPopupMenu
popupMenu: statusChatListAndCategories.chatListPopupMenu
}
DelegateModel {
id: delegateModel
property int destinationPosition: -1
model: SortFilterProxyModel {
sourceModel: root.model
filters: ValueFilter { roleName: "isCategory"; value: true }
sorters: RoleSorter { roleName: "position" }
}
items.includeByDefault: false
groups: DelegateModelGroup {
id: unsortedItems
name: "unsorted"
includeByDefault: true
onChanged: Utils.delegateModelSort(unsortedItems, delegateModel.items,
(a, b) => a.position < b.position)
}
model: statusChatListAndCategories.model
delegate: Item {
id: draggable
objectName: model.name
width: statusChatListCategory.width
height: statusChatListCategory.height
property alias chatListCategory: statusChatListCategory
@@ -132,13 +104,13 @@ Item {
dragSensor.drag.threshold: 0.1
dragSensor.drag.filterChildren: true
dragSensor.onPressAndHold: {
if (root.draggableCategories) {
if (statusChatListAndCategories.draggableCategories) {
dragActive = true
}
}
dragSensor.onReleased: {
if (dragActive && delegateModel.destinationPosition !== -1 && statusChatListCategory.originalOrder !== delegateModel.destinationPosition) {
root.chatListCategoryReordered(statusChatListCategory.categoryId, statusChatListCategory.originalOrder, delegateModel.destinationPosition)
if (dragActive) {
statusChatListAndCategories.chatListCategoryReordered(statusChatListCategory.categoryId, statusChatListCategory.originalOrder, statusChatListCategory.originalOrder)
}
dragActive = false
}
@@ -148,44 +120,38 @@ Item {
startX = dragSensor.mouseX
}
dragSensor.onMouseYChanged: {
if (root.draggableCategories && (Math.abs(startY - dragSensor.mouseY) > 1) && dragSensor.pressed) {
if (statusChatListAndCategories.draggableCategories && (Math.abs(startY - dragSensor.mouseY) > 1) && dragSensor.pressed) {
dragActive = true
}
}
dragSensor.onMouseXChanged: {
if (root.draggableCategories && (Math.abs(startX - dragSensor.mouseX) > 1) && dragSensor.pressed) {
if (statusChatListAndCategories.draggableCategories && (Math.abs(startX - dragSensor.mouseX) > 1) && dragSensor.pressed) {
dragActive = true
}
}
onDragActiveChanged: delegateModel.destinationPosition = -1
addButton.tooltip: root.categoryAddButtonToolTip
menuButton.tooltip: root.categoryMenuButtonToolTip
addButton.tooltip: statusChatListAndCategories.categoryAddButtonToolTip
menuButton.tooltip: statusChatListAndCategories.categoryMenuButtonToolTip
originalOrder: model.position
categoryId: model.itemId
name: model.name
showActionButtons: statusChatListAndCategories.showCategoryActionButtons
addButton.onClicked: statusChatListAndCategories.categoryAddButtonClicked(model.itemId)
showActionButtons: root.showCategoryActionButtons
addButton.onClicked: root.categoryAddButtonClicked(model.itemId)
chatList.model: model.subItems
chatList.onChatItemSelected: statusChatListAndCategories.chatItemSelected(categoryId, id)
chatList.onChatItemUnmuted: statusChatListAndCategories.chatItemUnmuted(id)
chatList.onChatItemReordered: statusChatListAndCategories.chatItemReordered(model.itemId, id, from, to)
chatList.draggableItems: statusChatListAndCategories.draggableItems
chatList.model: SortFilterProxyModel {
sourceModel: model.subItems
sorters: RoleSorter { roleName: "position" }
}
chatList.onChatItemSelected: root.chatItemSelected(categoryId, id)
chatList.onChatItemUnmuted: root.chatItemUnmuted(id)
chatList.onChatItemReordered: root.chatItemReordered(model.itemId, id, from, to)
chatList.draggableItems: root.draggableItems
popupMenu: root.categoryPopupMenu
chatListPopupMenu: root.chatListPopupMenu
popupMenu: statusChatListAndCategories.categoryPopupMenu
chatListPopupMenu: statusChatListAndCategories.chatListPopupMenu
// Used to set the initial value of "opened" when the
// model is bound/changed.
opened: {
let openedState = root.openedCategoryState[model.itemId]
let openedState = statusChatListAndCategories.openedCategoryState[model.itemId]
return openedState !== undefined ? openedState : true // defaults to open
}
@@ -194,18 +160,7 @@ Item {
// as the state would be lost each time the model is
// changed.
onOpenedChanged: {
root.openedCategoryState[model.itemId] = statusChatListCategory.opened
}
Connections {
function onOriginalOrderChanged() {
Qt.callLater(() => {
if (!delegateModel)
return
delegateModel.items.setGroups(0, delegateModel.items.count, "unsorted")
})
}
statusChatListAndCategories.openedCategoryState[model.itemId] = statusChatListCategory.opened
}
}
@@ -216,6 +171,7 @@ Item {
keys: ["chat-category"]
onEntered: reorderDelay.start()
onDropped: statusChatListAndCategories.chatListCategoryReordered(statusChatListCategory.categoryId, drag.source.originalOrder, statusChatListCategory.DelegateModel.itemsIndex)
Timer {
id: reorderDelay
@@ -223,7 +179,7 @@ Item {
repeat: false
onTriggered: {
if (dropArea.containsDrag) {
delegateModel.destinationPosition = delegateModel.model.get(draggable.DelegateModel.itemsIndex).position
dropArea.drag.source.chatListCategory.originalOrder = statusChatListCategory.originalOrder
delegateModel.items.move(dropArea.drag.source.DelegateModel.itemsIndex, draggable.DelegateModel.itemsIndex)
}
}
@@ -261,7 +217,6 @@ Item {
Repeater {
id: statusChatListCategories
objectName: "communityChatListCategories"
visible: !!model && model.count > 0
model: delegateModel
}
@@ -270,6 +225,6 @@ Item {
Loader {
id: popupMenuSlot
active: !!root.popupMenu
active: !!statusChatListAndCategories.popupMenu
}
}
@@ -16,7 +16,6 @@ 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
@@ -36,22 +35,23 @@ Column {
StatusChatListCategoryItem {
id: statusChatListCategoryItem
title: statusChatListCategory.name
visible: model.isCategory
opened: statusChatListCategory.opened
sensor.pressAndHoldInterval: 150
propagateTitleClicks: true // title click is handled as a normal click (fallthru)
showMenuButton: showActionButtons && !!statusChatListCategory.popupMenu
highlighted: statusChatListCategory.dragged
onClicked: {
sensor.onClicked: {
if (sensor.enabled) {
if (mouse.button === Qt.RightButton && showActionButtons && !!statusChatListCategory.popupMenu) {
highlighted = true;
popupMenuSlot.item.popup(mouse.x + 4, mouse.y + 6);
} else if (mouse.button === Qt.LeftButton) {
statusChatListCategory.opened = !statusChatListCategory.opened
return
}
}
}
onToggleButtonClicked: statusChatListCategory.opened = !statusChatListCategory.opened
onTitleClicked: statusChatListCategory.opened = !opened
onToggleButtonClicked: statusChatListCategory.opened = !opened
onMenuButtonClicked: {
highlighted = true
menuButton.highlighted = true
@@ -66,6 +66,9 @@ Column {
anchors.horizontalCenter: parent.horizontalCenter
visible: statusChatListCategory.opened
categoryId: statusChatListCategory.categoryId
filterFn: function (model) {
return !!model.parentItemId && model.parentItemId === statusChatList.categoryId
}
popupMenu: statusChatListCategory.chatListPopupMenu
}
@@ -60,7 +60,15 @@ StatusListItem {
icon.name: "chevron-down"
icon.width: 18
icon.rotation: statusChatListCategoryItem.opened ? 0 : 270
onClicked: statusChatListCategoryItem.toggleButtonClicked(mouse)
onPressed: {
sensor.enabled = false;
}
onClicked: {
statusChatListCategoryItem.toggleButtonClicked(mouse);
}
onReleased: {
sensor.enabled = true;
}
}
]
}
+15 -8
View File
@@ -21,8 +21,11 @@ Rectangle {
property bool hasUnreadMessages: false
property int notificationsCount: 0
property bool muted: false
property StatusAssetSettings asset: StatusAssetSettings {
property StatusImageSettings image: StatusImageSettings {
width: 24
height: 24
}
property StatusIconSettings icon: StatusIconSettings {
width: 24
height: 24
color: Theme.palette.miscColor5
@@ -82,7 +85,8 @@ Rectangle {
anchors.left: parent.left
anchors.leftMargin: 8
anchors.verticalCenter: parent.verticalCenter
asset: root.asset
image: root.image
icon: root.icon
name: root.name
}
@@ -108,14 +112,17 @@ Rectangle {
icon: {
switch (root.type) {
case StatusChatListItem.Type.PublicChat:
return Theme.palette.name === "light" ? "tiny/public-chat" : "tiny/public-chat-white"
case StatusChatListItem.Type.PublicCat:
return Theme.palette.name == "light" ? "tiny/public-chat" : "tiny/public-chat-white"
break;
case StatusChatListItem.Type.GroupChat:
return Theme.palette.name === "light" ? "tiny/group" : "tiny/group-white"
return Theme.palette.name == "light" ? "tiny/group" : "tiny/group-white"
break;
case StatusChatListItem.Type.CommunityChat:
return Theme.palette.name === "light" ? "tiny/channel" : "tiny/channel-white"
return Theme.palette.name == "light" ? "tiny/channel" : "tiny/channel-white"
break;
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"
}
}
}
@@ -0,0 +1,149 @@
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
asset.emoji: model.emoji
asset.width: 24
asset.height: 24
asset.color: "transparent"
asset.isLetterIdenticon: true
icon.emoji: model.emoji
icon.height: 24
icon.width: icon.height
icon.color: "transparent"
icon.isLetterIdenticon: true
title: model.name
titleText.font.pixelSize: 13
titleText.color: d.fontColor
+10 -12
View File
@@ -13,23 +13,21 @@ Item {
property alias model: repeater.model
property alias contentWidth: flow.width
readonly property int itemsWidth: {
let result = 0;
for (let i = 0; i < repeater.count; ++i) {
result += flow.spacing + repeater.itemAt(i).width;
}
return result;
}
signal clicked(var item)
implicitWidth: itemsWidth
implicitHeight: flow.height
implicitWidth: flow.implicitWidth
implicitHeight: flow.implicitHeight
Flow {
id: flow
anchors.centerIn: parent
width: Math.min(parent.width, root.itemsWidth);
width: {
let itemsWidth = 0;
for (let i = 0; i < repeater.count; ++i) {
itemsWidth += spacing + repeater.itemAt(i).width;
}
return Math.min(parent.width, itemsWidth);
}
spacing: 10
Repeater {
@@ -40,7 +38,7 @@ Item {
name: model.name
visible: (root.showOnlySelected ? model.selected : !model.selected) &&
(filterString == 0 || name.toUpperCase().indexOf(filterString.toUpperCase()) !== -1)
width: visible ? implicitWidth : -flow.spacing
width: visible ? implicitWidth : -10
height: visible ? implicitHeight : 0
removable: root.showOnlySelected && root.active
onClicked: root.clicked(model)
@@ -9,14 +9,16 @@ Row {
property bool isContact: false
property var trustIndicator: StatusContactVerificationIcons.TrustedType.None
property StatusAssetSettings mutualConnectionIcon: StatusAssetSettings {
property StatusIconSettings mutualConnectionIcon: StatusIconSettings {
name: "tiny/tiny-contact"
color: Theme.palette.indirectColor1
width: dummyImage.width
height: dummyImage.height
bgWidth: 10
bgHeight: 10
bgColor: Theme.palette.primaryColor1
background: StatusIconBackgroundSettings {
width: 10
height: 10
color: 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": ""
@@ -24,15 +26,17 @@ Row {
}
}
property StatusAssetSettings trustContactIcon: StatusAssetSettings {
property StatusIconSettings trustContactIcon: StatusIconSettings {
// 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
bgWidth: 10
bgHeight: 10
bgColor: root.trustIndicator === StatusContactVerificationIcons.TrustedType.Verified ? Theme.palette.primaryColor1 : Theme.palette.dangerColor1
background: StatusIconBackgroundSettings {
width: 10
height: 10
color: 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": ""
@@ -51,25 +55,25 @@ Row {
StatusRoundIcon {
visible: root.isContact
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
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
}
StatusRoundIcon {
visible: root.trustIndicator !== StatusContactVerificationIcons.TrustedType.None
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
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
}
}
@@ -1,42 +0,0 @@
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())
}
}
-184
View File
@@ -1,184 +0,0 @@
import QtQuick 2.14
import QtQuick.Controls 2.14
import QtQuick.Layouts 1.14
import Qt.labs.calendar 1.0
import StatusQ.Core 0.1
import StatusQ.Controls 0.1
import StatusQ.Core.Theme 0.1
/*!
\qmltype StatusDatePicker
\inherits StatusQ.Controls.StatusComboBox
\inqmlmodule StatusQ.Components
\since StatusQ.Components 0.1
\brief Displays a date picker based on a combobox with a calendar popup
The \c StatusDatePicker displays a date picker based on a combobox with a calendar popup.
The property \p selectedDate reflects the currently chosen date (defaults to today).
For a list of components available see StatusQ.
*/
StatusComboBox {
id: root
/*!
\qmlproperty string StatusDatePicker::dateFormat
This property specifies how the selected date will be displayed to the user.
By default it is current locale's short date format. For a list of available types
and formatting characters, see https://doc.qt.io/qt-5/qdate.html#toString-2
*/
property string dateFormat: Qt.locale().dateFormat(Locale.ShortFormat)
/*!
\qmlproperty date StatusDatePicker::selectedDate
This property holds the currently selected date.
\sa QtQml.Date
*/
property alias selectedDate: d.selectedDate
QtObject {
id: d
property date selectedDate: new Date()
}
control.delegate: null
control.displayText: root.selectedDate.toLocaleDateString(Qt.locale(), root.dateFormat)
control.popup.horizontalPadding: 8
control.popup.onAboutToShow: {
// always open the popup showing the last (currently) selected date
grid.year = d.selectedDate.getFullYear()
grid.month = d.selectedDate.getMonth()
}
control.popup.contentItem: Item {
property alias grid: grid
GridLayout {
anchors.fill: parent
columns: 2
RowLayout {
Layout.fillWidth: true
Layout.columnSpan: 2
spacing: 0
StatusFlatButton {
leftPadding: 8
rightPadding: 8
text: "<<"
onClicked: grid.year = grid.year - 1
StatusToolTip {
text: qsTr("Previous year")
visible: parent.hovered
}
}
StatusFlatButton {
leftPadding: 8
rightPadding: 8
text: "<"
onClicked: {
// switch to previous month (and optionally prev year in January)
const date = new Date(grid.year, grid.month)
date.setMonth(date.getMonth() - 1)
grid.month = date.getMonth()
grid.year = date.getFullYear()
}
StatusToolTip {
text: qsTr("Previous month")
visible: parent.hovered
}
}
StatusFlatButton {
Layout.fillWidth: true
text: grid.title
font.pixelSize: 18
font.weight: Font.Medium
onClicked: {
const date = new Date()
grid.month = date.getMonth()
grid.year = date.getFullYear()
}
StatusToolTip {
text: qsTr("Show current month")
visible: parent.hovered
}
}
StatusFlatButton {
leftPadding: 8
rightPadding: 8
text: ">"
onClicked: {
// switch to next month (and optionally next year in December)
const date = new Date(grid.year, grid.month)
date.setMonth(date.getMonth() + 1)
grid.month = date.getMonth()
grid.year = date.getFullYear()
}
StatusToolTip {
text: qsTr("Next month")
visible: parent.hovered
}
}
StatusFlatButton {
leftPadding: 8
rightPadding: 8
text: ">>"
onClicked: grid.year = grid.year + 1
StatusToolTip {
text: qsTr("Next year")
visible: parent.hovered
}
}
}
DayOfWeekRow {
Layout.row: 1
Layout.column: 1
Layout.fillWidth: true
delegate: StatusBaseText {
text: model.shortName
color: Theme.palette.directColor3
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
}
}
WeekNumberColumn {
id: weekColumn
month: grid.month
year: grid.year
Layout.fillHeight: true
delegate: StatusBaseText {
text: model.weekNumber
color: Theme.palette.directColor3
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
}
}
MonthGrid {
id: grid
month: d.selectedDate.getMonth()
year: d.selectedDate.getFullYear()
Layout.fillWidth: true
Layout.fillHeight: true
delegate: StatusFlatButton {
readonly property bool selected: d.selectedDate.getFullYear() === model.year &&
d.selectedDate.getMonth() === model.month &&
d.selectedDate.getDate() === model.day
opacity: model.month === grid.month ? 1 : 0.5
text: model.day
textColor: selected ? Theme.palette.primaryColor1 : Theme.palette.directColor1
font.bold: selected || model.today
onClicked: {
d.selectedDate = model.date
root.control.popup.close()
}
}
}
}
}
}
@@ -10,7 +10,7 @@ Rectangle {
property string subTitle: ""
property alias subTitleComponent: statusDescriptionListItemSubTitle
property string value: ""
property StatusAssetSettings asset: StatusAssetSettings {
property StatusIconSettings icon: StatusIconSettings {
width: 23
height: 23
}
@@ -59,7 +59,7 @@ Rectangle {
StatusFlatRoundButton {
id: statusFlatRoundButton
visible: !!statusDescriptionListItem.asset.name
visible: !!statusDescriptionListItem.icon.name
anchors.verticalCenter: statusDescriptionListItemSubTitle.verticalCenter
anchors.left: statusDescriptionListItemSubTitle.right
anchors.leftMargin: 4
@@ -67,9 +67,9 @@ Rectangle {
width: 32
height: 32
icon.name: statusDescriptionListItem.asset.name
icon.width: statusDescriptionListItem.asset.width
icon.height: statusDescriptionListItem.asset.height
icon.name: statusDescriptionListItem.icon.name
icon.width: statusDescriptionListItem.icon.width
icon.height: statusDescriptionListItem.icon.height
StatusToolTip {
id: statusToolTip
+18 -11
View File
@@ -18,13 +18,19 @@ Rectangle {
property bool expandable: true
property bool expanded: false
property StatusAssetSettings asset: StatusAssetSettings {
width: !statusExpandableItem.asset.isImage ? 24 : 40
height: !statusExpandableItem.asset.isImage ? 24 : 40
property StatusIconSettings icon: StatusIconSettings {
width: !!statusExpandableItem.icon.name.toString() ? 24 : 40
height: !!statusExpandableItem.icon.name.toString() ? 24 : 40
color: Theme.palette.directColor1
bgWidth: 32
bgHeight: 32
bgColor: Theme.palette.primaryColor2
background: StatusIconBackgroundSettings {
width: 32
height: 32
color: Theme.palette.primaryColor2
}
}
property StatusImageSettings image: StatusImageSettings {
width: 40
height: 40
}
enum Type {
@@ -67,7 +73,8 @@ Rectangle {
anchors.topMargin: (statusExpandableItem.type === StatusExpandableItem.Type.Secondary) ? 12.5 : 25
anchors.left: parent.left
anchors.leftMargin: (statusExpandableItem.type === StatusExpandableItem.Type.Secondary) ? 16 : 11
asset: statusExpandableItem.asset
image: statusExpandableItem.image
icon: statusExpandableItem.icon
name: primaryText.text
active: (statusExpandableItem.type !== StatusExpandableItem.Type.Tertiary)
}
@@ -82,10 +89,10 @@ Rectangle {
anchors.verticalCenter: (statusExpandableItem.type === StatusExpandableItem.Type.Secondary) ? identicon.verticalCenter : undefined
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)
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)
font.weight: (statusExpandableItem.type === StatusExpandableItem.Type.Primary) ? Font.Medium : Font.Normal
font.pixelSize: (statusExpandableItem.type === StatusExpandableItem.Type.Primary) ? 15 : 17
@@ -3,7 +3,6 @@ import QtQuick.Layouts 1.14
import StatusQ.Core 0.1
import StatusQ.Controls 0.1
import StatusQ.Core.Theme 0.1
/*!
\qmltype StatusImageCropPanel
@@ -128,15 +127,12 @@ Item {
id: mainLayout
anchors.fill: parent
spacing: 1
Item {
id: cropSpaceItem
Layout.fillWidth: true
Layout.fillHeight: true
Layout.leftMargin: 10
Layout.rightMargin: 10
clip: true
@@ -146,7 +142,6 @@ Item {
anchors.top: parent.top
anchors.right: cropEditor.left
anchors.bottom: parent.bottom
anchors.bottomMargin: -1
color: wallColor
opacity: wallTransparency
z: cropEditor.z + 1
@@ -165,9 +160,8 @@ Item {
StatusImageCrop {
id: cropEditor
anchors.centerIn: parent
readonly property bool cropARSmall: aspectRatio < cropSpaceItem.width/cropSpaceItem.height
width: cropARSmall ? cropSpaceItem.height * aspectRatio : cropSpaceItem.width - root.margins * 2
height: cropARSmall ? cropSpaceItem.height - root.margins * 2 : cropSpaceItem.width / aspectRatio
width: aspectRatio < cropSpaceItem.width/cropSpaceItem.height ? cropSpaceItem.height * aspectRatio : cropSpaceItem.width - root.margins * 2
height: aspectRatio < cropSpaceItem.width/cropSpaceItem.height ? cropSpaceItem.height - root.margins * 2 : cropSpaceItem.width / aspectRatio
}
Rectangle {
@@ -176,7 +170,6 @@ Item {
anchors.top: parent.top
anchors.right: parent.right
anchors.bottom: parent.bottom
anchors.bottomMargin: -1
color: wallColor
opacity: wallTransparency
z: cropEditor.z + 1
@@ -188,7 +181,6 @@ Item {
anchors.top: cropEditor.bottom
anchors.right: rightOverlay.left
anchors.bottom: parent.bottom
anchors.bottomMargin: -1
color: wallColor
opacity: wallTransparency
z: cropEditor.z + 1
@@ -198,7 +190,6 @@ Item {
Canvas {
visible: root.enableCheckers
anchors.fill: parent
anchors.bottomMargin: -1
onPaint: {
var ctx = getContext("2d")
for(let xI = 0; xI < Math.ceil(width/10); xI++) {
@@ -216,7 +207,6 @@ Item {
anchors.fill: parent
enabled: root.interactive
cursorShape: Qt.SizeAllCursor
property var lastDragPoint: null
onReleased: lastDragPoint = null
@@ -248,20 +238,17 @@ Item {
RowLayout {
visible: root.interactive
spacing: 10
StatusIcon {
icon: "remove-circle"
color: Theme.palette.baseColor1
Layout.alignment: Qt.AlignVCenter
Layout.preferredWidth: 24
Layout.preferredHeight: 24
Layout.preferredWidth: 20
Layout.preferredHeight: 20
}
StatusSlider {
Layout.fillWidth: true
Layout.topMargin: 10
Layout.bottomMargin: 10
Layout.topMargin: 20
Layout.bottomMargin: 25
Layout.alignment: Qt.AlignVCenter
enabled: root.interactive
@@ -274,11 +261,9 @@ Item {
}
StatusIcon {
icon: "add-circle"
color: Theme.palette.baseColor1
Layout.alignment: Qt.AlignVCenter
Layout.preferredWidth: 24
Layout.preferredHeight: 24
Layout.preferredWidth: 20
Layout.preferredHeight: 20
}
}
}
+33 -38
View File
@@ -27,15 +27,12 @@ import StatusQ.Core.Utils 0.1
defaultItemText: qsTr("Example: 10 SNT")
andOperatorText: qsTr("and")
orOperatorText: qsTr("or")
CustomPopup {
id: popup
}
addButton.onClicked: {
popup.x = mouse.x
popup.y = mouse.y
popup.open()
popupItem: CustomPopup {
id: customPopup
onAddItem: {
tokensSelector.addItem(itemText, itemImage, operator)
customPopup.close()
}
}
}
\endqml
@@ -69,10 +66,10 @@ Rectangle {
*/
property url defaultItemImageSource: ""
/*!
\qmlproperty StatusRoundButton StatusItemSelector::addButton
This property holds an alias to the `add` button.
\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.
*/
readonly property alias addButton: addItemButton
property QC.Popup popupItem
/*!
\qmlproperty ListModel StatusItemSelector::itemsModel
This property holds the data that will be populated in the items selector.
@@ -93,7 +90,7 @@ Rectangle {
}
\endqml
*/
property var itemsModel: ListModel { }
property ListModel itemsModel: ListModel { }
/*!
\qmlproperty string StatusItemSelector::andOperatorText
This property holds the string text representation for an `AND` logical operator.
@@ -104,24 +101,27 @@ Rectangle {
This property holds the string text representation for an `OR` logical operator.
*/
property string orOperatorText: qsTr("or")
/*!
\qmlsignal StatusItemSelector::itemClicked
This signal is emitted when the item is clicked.
/*
\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)
*/
signal itemClicked(var item, int index, var mouse)
function addItem(text, imageSource, operator) {
itemsModel.insert(itemsModel.count, { "text": text, "imageSource": imageSource.toString(), "operator": operator })
}
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 ""
}
}
}
@@ -170,8 +170,7 @@ Rectangle {
StatusListItemTag {
visible: itemsModel.count === 0
title: root.defaultItemText
asset.name: root.defaultItemImageSource
asset.isImage: true
image.source: root.defaultItemImageSource
color: Theme.palette.baseColor2
closeButtonVisible: false
titleText.color: Theme.palette.baseColor1
@@ -179,10 +178,8 @@ Rectangle {
}
Repeater {
model: itemsModel
RowLayout {
spacing: flow.spacing
StatusBaseText {
visible: model.operator !== Utils.Operators.None
Layout.alignment: Qt.AlignVCenter
@@ -203,19 +200,12 @@ Rectangle {
}
StatusListItemTag {
title: model.text
asset.name: model.imageSource
asset.isImage: true
image.source: model.imageSource
color: Theme.palette.primaryColor3
closeButtonVisible: false
titleText.color: Theme.palette.primaryColor1
titleText.font.pixelSize: 15
MouseArea {
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
acceptedButtons: Qt.LeftButton | Qt.RightButton
onClicked: root.itemClicked(parent, model.index, mouse)
}
//onClicked: // TODO: Open remove or edit dialog
}
}
}
@@ -226,6 +216,11 @@ 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()
}
}
}
}
+45 -50
View File
@@ -23,40 +23,46 @@ 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 alias tagsModel: tagsRepeater.model
property var tagsModel: []
property Component tagsDelegate
property bool loading: false
property bool loadingFailed: false
property StatusAssetSettings asset: StatusAssetSettings {
height: isImage ? 40 : 20
width: isImage ? 40 : 20
property StatusIconSettings icon: StatusIconSettings {
height: isLetterIdenticon ? 40 : 20
width: isLetterIdenticon ? 40 : 20
rotation: 0
isLetterIdenticon: false
letterSize: 21
charactersLen: 1
color: isLetterIdenticon ? bgColor : type === StatusListItem.Type.Danger ?
color: isLetterIdenticon ? background.color : type === StatusListItem.Type.Danger ?
Theme.palette.dangerColor1 : Theme.palette.primaryColor1
bgWidth: 40
bgHeight: 40
bgColor: {
if (sensor.containsMouse) {
return type === StatusListItem.Type.Secondary ||
type === StatusListItem.Type.Danger ? "transparent" :
Theme.palette.primaryColor3
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
}
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
@@ -116,32 +122,33 @@ 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.verticalCenter: parent.verticalCenter
anchors.top: parent.top
anchors.topMargin: 12
visible: !iconOrImageLoadingOverlay.visible
asset: statusListItem.asset
image: statusListItem.image
icon: statusListItem.icon
name: statusListItem.title
active: statusListItem.asset.isLetterIdenticon ||
!!statusListItem.asset.name ||
!!statusListItem.asset.emoji
active: statusListItem.icon.isLetterIdenticon ||
!!statusListItem.icon.name ||
!!statusListItem.image.source.toString() ||
!!statusListItem.icon.emoji
badge.border.color: statusListItem.color
ringSettings: statusListItem.ringSettings
}
@@ -174,7 +181,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: Math.max(statusListItem.rightPadding, titleIconsRow.requiredWidth)
anchors.rightMargin: statusListItem.rightPadding
anchors.verticalCenter: bottomModel.length === 0 ? parent.verticalCenter : undefined
height: childrenRect.height
@@ -270,9 +277,6 @@ 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
@@ -280,7 +284,6 @@ Rectangle {
StatusBaseText {
id: statusListItemSubTitle
objectName: "statusListItemSubTitle"
anchors.top: statusListItemTitle.bottom
width: parent.width
text: statusListItem.subTitle
@@ -313,24 +316,16 @@ Rectangle {
implicitHeight: visible ? 22 : 0
}
ScrollView {
visible: tagsRepeater.count > 0
Row {
id: statusListItemTagsSlotInline
anchors.top: statusListItemTertiaryTitle.bottom
anchors.topMargin: visible? 8 : 0
width: parent.width
height: visible? contentHeight + 12 : contentHeight
spacing: 10
clip: true
ScrollBar.vertical.policy: ScrollBar.AlwaysOff
Row {
id: statusListItemTagsSlotInline
spacing: 10
Repeater {
id: tagsRepeater
delegate: tagsDelegate
}
Repeater {
model: tagsModel
delegate: tagsDelegate
}
}
}
@@ -355,7 +350,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 ? 0 : 16
anchors.topMargin: bottomModel.length === 0 ? undefined : 16
anchors.right: statusListItemComponentsSlot.left
anchors.rightMargin: statusListItemComponentsSlot.width > 0 ? 10 : 0
+18 -13
View File
@@ -13,12 +13,17 @@ Control {
property string primaryText: ""
property string secondaryText: ""
property StatusAssetSettings asset: StatusAssetSettings {
property StatusImageSettings image: StatusImageSettings {
height: 16
width: 16
isIdenticon: false
}
property StatusIconSettings icon: StatusIconSettings {
height: 16
width: 16
isLetterIdenticon: false
background: StatusIconBackgroundSettings {}
color: "transparent"
imgIsIdenticon: false
}
background: Rectangle {
@@ -38,22 +43,22 @@ Control {
anchors.horizontalCenterOffset: -spacing
spacing: 2
StatusRoundedImage {
implicitWidth: root.asset.width
implicitHeight: root.asset.height
visible: !root.asset.isLetterIdenticon
image.source: root.asset.name
implicitWidth: root.image.width
implicitHeight: root.image.height
visible: !root.icon.isLetterIdenticon
image.source: root.image.source
border.color: Theme.palette.baseColor1
border.width: root.asset.imgIsIdenticon ? 1 : 0
border.width: root.image.isIdenticon ? 1 : 0
}
StatusLetterIdenticon {
implicitWidth: root.asset.width
implicitHeight: root.asset.width
implicitWidth: root.icon.width
implicitHeight: root.icon.width
letterSize: 11
visible: root.asset.isLetterIdenticon
color: root.asset.color
visible: root.icon.isLetterIdenticon
color: root.icon.color
name: root.primaryText
emoji: root.asset.emoji
emojiSize: root.asset.emojiSize
emoji: root.icon.emoji
emojiSize: root.icon.emojiSize
}
StatusBaseText {
font.weight: Font.Medium
+23 -12
View File
@@ -6,8 +6,8 @@ import StatusQ.Core.Theme 0.1
Rectangle {
id: root
implicitWidth: layout.width + layout.anchors.margins
implicitHeight: 30
width: layout.width + layout.anchors.margins
height: 30
color: Theme.palette.primaryColor3
radius: 15
@@ -15,19 +15,26 @@ Rectangle {
property string title: ""
property bool closeButtonVisible: true
signal clicked(var mouse)
signal clicked()
property StatusAssetSettings asset: StatusAssetSettings {
property StatusImageSettings image: StatusImageSettings {
width: 20
height: 20
isIdenticon: false
}
property StatusIconSettings icon: StatusIconSettings {
height: 20
width: 20
rotation: 0
isLetterIdenticon: false
letterSize: 10
color: Theme.palette.primaryColor1
bgWidth: 15
bgHeight: 15
bgColor: Theme.palette.primaryColor3
imgIsIdenticon: false
background: StatusIconBackgroundSettings {
width: 15
height: 15
color: Theme.palette.primaryColor3
}
}
RowLayout {
@@ -38,10 +45,12 @@ Rectangle {
StatusSmartIdenticon {
id: iconOrImage
Layout.leftMargin: 4
asset: root.asset
image: root.image
icon: root.icon
name: root.title
active: root.asset.isLetterIdenticon ||
!!root.asset.name
active: root.icon.isLetterIdenticon ||
!!root.icon.name ||
!!root.image.source.toString()
}
StatusBaseText {
@@ -61,7 +70,9 @@ Rectangle {
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: root.clicked(mouse)
onClicked: {
root.clicked()
}
}
}
}
+94 -71
View File
@@ -6,8 +6,6 @@ import StatusQ.Core 0.1
import StatusQ.Core.Theme 0.1
import StatusQ.Controls 0.1
import SortFilterProxyModel 0.2
/*!
\qmltype StatusListPicker
\inherits Item
@@ -17,7 +15,7 @@ import SortFilterProxyModel 0.2
The \c StatusListPicker is populated with a data model. The data model is commonly a JavaScript array or a ListModel object.
StatusListPicker can be made as a single or multiple options picker by setting its StatusListPicker::multiSelection property properly.
StatusListPicker can be made as a single or multiple options picker by setting its StatusListPicker::multiSelection property properly or will be auto-set if the model contains / provides more than one selected items.
The StatusPickerButton text holds the text of the current item selected in the list picker. If there is more than one item selected, a string composed will be displayed.
The drop-down list incorporates a searcher by the following model roles: `name` or / and `shortName`.
@@ -46,7 +44,6 @@ Item {
This property holds the data that will be populated in the list picker.
NOTE: This model property should not change so it is an in / out property where the selected role will be dynamically changed according to user actions.
NOTE: Be sure provided model is compatible with StatusListPicker::multiSelection property.
Here an example of the model roles expected:
\qml
@@ -72,9 +69,7 @@ Item {
}
\endqml
*/
property var inputList: ListModel { }
readonly property StatusListPickerProxies proxy: StatusListPickerProxies {}
property ListModel inputList: ListModel { }
/*!
\qmlproperty string StatusListPicker::searchText
@@ -156,65 +151,93 @@ Item {
QtObject {
id: d
property var filteredModel: ListModel { }
readonly property SortFilterProxyModel selectedItems: SortFilterProxyModel {
sourceModel: root.inputList
// NOTE: ValueFilter would crash if source model does not contain given role
// FIXME: use ValueFilter when its fixed
filters: ExpressionFilter {
expression: root.proxy.selected(model)
// Used to set up component and the needed private properties
function initialize() {
if(filteredModel.count === 0) {
// It is necessary to load the model, not loaded yet!
var selected = 0
var selectionText = ""
for(var i = 0; i < root.inputList.count; i++) {
var item = root.inputList.get(i)
d.filteredModel.append(item)
if(item.selected) selected++;
}
// If the given model has more than one selected elements, the behaviour of the list picker will be as a multiple selector with checkboxes although it is
// set in the radiobutton mode. Radiobutton mode is only for mutial-exclusion.
if(selected > 1)
multiSelection = true
// Update selected items text:
d.getSelectedItemsText()
}
}
readonly property string selectedItemsText: {
function formatSymbolShortNameText(symbol, shortName) {
var formattedText = ""
if(root.printSymbol && symbol)
formattedText = symbol + shortName
else
formattedText = shortName
return formattedText
// Used to update model elements given a specific text by filtering them for its `name` and / or `shortName`.
function applyFilter(text) {
const input = text.toLowerCase()
filteredModel.clear()
for(var i = 0; i < root.inputList.count; i++) {
let item = root.inputList.get(i)
if(item.name.toLowerCase().includes(input) || item.shortName.toLowerCase().includes(input))
filteredModel.append(item)
}
}
function formatSymbolShortNameText(symbol, shortName) {
var formattedText = ""
if(root.printSymbol && symbol)
formattedText = symbol + shortName
else
formattedText = shortName
return formattedText
}
function getSelectedItemsText() {
var res = ""
for(var i = 0; i < selectedItems.count; i++) {
var item = selectedItems.get(i)
if(res != "")
res += ", "
res += formatSymbolShortNameText(root.proxy.symbol(item), root.proxy.shortName(item))
for(var i = 0; i < root.inputList.count; i++) {
var item = root.inputList.get(i)
if(item.selected) {
if(res != "")
res += ", "
res += d.formatSymbolShortNameText(item.symbol, item.shortName)
}
}
return res
}
// Used to update the base input list model with the new selected property
function updateInputListModel(key, selected, isSingleSelection) {
// If it is a single selection we must ensure that when a new key is selected others are cleared.
// It must be done manually because as there is the option of filterning, the model visualized changes
// and it could be possible to have a filtered list without an element selected (but in the base model
// it is) so, the binding to not selected will not be executed, as in the current filtered model
// there are no changes to update, just only the selected one.
for(var i = 0; i < root.inputList.count; i++) {
if(root.inputList.get(i).key === key) {
root.inputList.get(i).selected = selected
}
else if(isSingleSelection && selected) {
// Clear all the list
root.inputList.get(i).selected = false
}
}
}
}
width: 110
height: 38
Repeater {
// Used to update the base input list model with the new selected property
// If it is a single selection we must ensure that when a new key is selected others are cleared.
id: itemsSelectorHelper
signal selectItem(var key, bool checked)
model: root.inputList
delegate: Item {
Connections {
target: itemsSelectorHelper
function onSelectItem(key, checked) {
if (root.proxy.key(model) === key) root.proxy.setSelected(model, checked)
else if (!root.multiSelection && checked) root.proxy.setSelected(model, false)
}
}
}
}
Component.onCompleted: d.initialize()
StatusPickerButton {
id: btn
anchors.fill: parent
bgColor: Theme.palette.primaryColor3
contentColor: Theme.palette.primaryColor1
text: d.selectedItemsText
text: picker.selectedItemsText
font.pixelSize: 13
type: StatusPickerButton.Type.Down
@@ -230,6 +253,8 @@ Item {
Rectangle {
id: picker
property string selectedItemsText: ""
width: content.itemWidth
height: Math.min(content.contentHeight + content.anchors.topMargin + content.anchors.bottomMargin, root.maxPickerHeight)
anchors.left: root.menuAlignment === StatusListPicker.MenuAlignment.Left ? btn.left : undefined
@@ -252,23 +277,12 @@ Item {
}
ListView {
id: content
id: content
property int itemHeight: 40
property int itemWidth: 360
model: SortFilterProxyModel {
sourceModel: root.inputList
delayed: true
filters: ExpressionFilter {
expression: {
root.searchText // ensure expression is reevaluated when searchText changes
return root.proxy.name(model).toLowerCase().includes(root.searchText.toLowerCase()) ||
root.proxy.shortName(model).toLowerCase().includes(root.searchText.toLowerCase())
}
}
}
model: d.filteredModel
width: itemWidth
anchors.top: parent.top
anchors.topMargin: 8
@@ -294,34 +308,43 @@ Item {
bottomPadding: 0
placeholderText: root.placeholderSearchText
text: root.searchText
input.asset.name: "search"
input.icon.name: "search"
onTextChanged: root.searchText = text
onTextChanged: {
d.applyFilter(text)
root.searchText = text
}
}
}// End of search input item
delegate: StatusItemPicker {
width: content.itemWidth
height: content.itemHeight
color: mouseArea.containsMouse ? Theme.palette.baseColor4 : "transparent"
asset: StatusAssetSettings {
name: root.proxy.imageSource(model) ? root.proxy.imageSource(model) : ""
image: StatusImageSettings {
source: model.imageSource ? model.imageSource : ""
width: 15
height: 15
imgIsIdenticon: false
isIdenticon: false
}
name: root.proxy.name(model)
shortName: root.proxy.shortName(model)
name: model.name
shortName: model.shortName
selectorType: root.multiSelection ? StatusItemPicker.SelectorType.CheckBox : StatusItemPicker.SelectorType.RadioButton
selected: root.proxy.selected(model)
selected: model.selected
radioGroup: radioBtnGroup
onCheckedChanged: {
if (checked !== root.proxy.selected(model)) {
itemsSelectorHelper.selectItem(root.proxy.key(model), checked)
d.updateInputListModel(model.key, checked, selectorType === StatusItemPicker.SelectorType.RadioButton)
if(selectorType === StatusItemPicker.SelectorType.RadioButton && checked) {
// Update selected item text
picker.selectedItemsText = d.formatSymbolShortNameText(model.symbol, model.shortName)
}
else {
// Update selected items text (multiple selection, text chain).
picker.selectedItemsText = d.getSelectedItemsText()
}
// Used to notify selected property changes in the specific item picker.
itemPickerChanged(root.proxy.key(model), checked)
itemPickerChanged(model.key, checked)
}
MouseArea {
@@ -363,7 +386,7 @@ Item {
// Not visual element to control mutual-exclusion of radiobuttons that are not sharing the same parent (inside list view)
ButtonGroup {
id: radioBtnGroup
}
}// End of Content
}
}// End of Content
}// End of Rectangle picker
}
@@ -1,30 +0,0 @@
import QtQuick 2.14
/*!
Enables StatusListPicker to work with incompatible models.
\qml
StatusListPicker {
id: currencyPicker
inputList: ListModel {
ListElement { incompatibleA: 0 ... incomatibleZ: false }
ListElement { incompatibleA: 1 ... incomatibleZ: false }
ListElement { incompatibleA: 2 ... incomatibleZ: false }
}
proxy { // StatusListPickerProxies
key: (model) => model.incompatibleA
...
selected: (model) => model.incompatibleZ
}
}
\endqml
*/
QtObject {
property var key: (model) => model.key
property var name: (model) => model.name
property var shortName: (model) => model.shortName
property var symbol: (model) => model.symbol
property var imageSource: (model) => model.imageSource
property var category: (model) => model.category
property var selected: (model) => model.selected
property var setSelected: (model, val) => model.selected = val
}
@@ -120,6 +120,7 @@ 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
@@ -128,8 +129,10 @@ StatusListItem {
implicitWidth: 256
implicitHeight: Math.max(56, statusListItemTitleArea.height + leftPadding)
leftPadding: 8
asset.width: 32
asset.height: 32
image.width: 32
image.height: 32
icon.width: 32
icon.height: 32
statusListItemIcon.anchors.verticalCenter: sensor.verticalCenter
statusListItemIcon.anchors.top: undefined
statusListItemIcon.badge.border.width: 2
+84 -293
View File
@@ -1,16 +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.Core.Utils 0.1
import StatusQ.Controls 0.1
import "./private/statusMessage"
Rectangle {
id: root
id: statusMessage
enum ContentType {
Unknown = 0,
@@ -23,12 +21,12 @@ Rectangle {
Invitation = 7
}
property alias quickActions: quickActionsPanel.items
property alias messageHeader: messageHeader
property alias quickActions:quickActionsPanel.quickActions
property alias statusChatInput: editComponent.inputComponent
property alias linksComponent: linksLoader.sourceComponent
property alias transcationComponent: transactionBubbleLoader.sourceComponent
property alias invitationComponent: invitationBubbleLoader.sourceComponent
property alias mouseArea: mouseArea
property alias footerComponent: footer.sourceComponent
property alias timestamp: messageHeader.timestamp
property string resendText: ""
property string cancelButtonText: ""
@@ -37,362 +35,155 @@ Rectangle {
property string errorLoadingImageText: ""
property string audioMessageInfoText: ""
property string pinnedMsgInfoText: ""
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 alias previousMessageIndex: dateGroupLabel.previousMessageIndex
property alias previousMessageTimestamp: dateGroupLabel.previousMessageTimestamp
property StatusMessageDetails messageDetails: StatusMessageDetails {}
property StatusMessageDetails replyDetails: StatusMessageDetails {}
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 profilePictureClicked()
signal senderNameClicked()
signal editCompleted(var newMsgText)
signal replyProfileClicked()
signal stickerLoaded()
signal imageClicked(var imageSource)
signal resendClicked()
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();
}
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
}
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"
HoverHandler {
id: hoverHandler
enabled: !root.isActiveMessage && !root.disableHover
}
ColumnLayout {
id: messageLayout
anchors.fill: parent
anchors.topMargin: 8
anchors.bottomMargin: 8
StatusDateGroupLabel {
id: dateGroupLabel
width: parent.width
StatusMessageReply {
Layout.fillWidth: true
Layout.topMargin: 20
messageTimestamp: root.timestamp
visible: text !== ""
visible: isAReply
replyDetails: statusMessage.replyDetails
onReplyProfileClicked: statusMessage.replyProfileClicked()
audioMessageInfoText: statusMessage.audioMessageInfoText
}
Loader {
Layout.fillWidth: true
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: profileImage.width
implicitHeight: profileImage.visible ? profileImage.height : 0
Layout.fillWidth: true
StatusSmartIdenticon {
id: profileImage
Layout.alignment: Qt.AlignTop
StatusSmartIdenticon {
id: profileImage
active: root.showHeader
visible: active
name: root.messageDetails.sender.userName
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)
}
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()
}
}
ColumnLayout {
Column {
spacing: 4
Layout.alignment: Qt.AlignTop
Layout.topMargin: 10
Layout.fillWidth: true
Loader {
active: root.isPinned && !editMode
visible: active
sourceComponent: StatusPinMessageDetails {
pinnedMsgInfoText: root.pinnedMsgInfoText
pinnedBy: root.pinnedBy
}
StatusPinMessageDetails {
visible: messageDetails.isPinned && !editMode
pinnedMsgInfoText: statusMessage.pinnedMsgInfoText
pinnedBy: messageDetails.pinnedBy
}
StatusMessageHeader {
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
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
}
Loader {
Layout.fillWidth: true
active: !editMode && !!root.messageDetails.messageText
active: !editMode && !!messageDetails.messageText
width: parent.width
visible: active
sourceComponent: StatusTextMessage {
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);
}
width: parent.width
textField.text: messageDetails.messageText
}
}
Loader {
active: root.messageDetails.contentType === StatusMessage.ContentType.Image && !editMode
active: messageDetails.contentType === StatusMessage.ContentType.Image && !editMode
visible: active
sourceComponent: StatusImageMessage {
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
source: messageDetails.contentType === StatusMessage.ContentType.Image ? messageDetails.messageContent : ""
onClicked: statusMessage.imageClicked()
shapeType: 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()
}
}
StatusSticker {
visible: messageDetails.contentType === StatusMessage.ContentType.Sticker && !editMode
image.source: messageDetails.messageContent
onLoaded: statusMessage.stickerLoaded()
}
Loader {
active: root.messageDetails.contentType === StatusMessage.ContentType.Audio && !editMode
active: messageDetails.contentType === StatusMessage.ContentType.Audio && !editMode
visible: active
sourceComponent: StatusAudioMessage {
audioSource: root.messageDetails.messageContent
audioSource: messageDetails.messageContent
hovered: hoverHandler.hovered
audioMessageInfoText: root.audioMessageInfoText
audioMessageInfoText: statusMessage.audioMessageInfoText
}
}
Loader {
id: linksLoader
active: !root.editMode
active: !!linksLoader.sourceComponent
visible: active
}
Loader {
id: transactionBubbleLoader
active: root.messageDetails.contentType === StatusMessage.ContentType.Transaction && !editMode
active: messageDetails.contentType === StatusMessage.ContentType.Transaction && !editMode
visible: active
}
Loader {
id: invitationBubbleLoader
active: root.messageDetails.contentType === StatusMessage.ContentType.Invitation && !editMode
active: messageDetails.contentType === StatusMessage.ContentType.Invitation && !editMode
visible: active
}
StatusEditMessage {
id: editComponent
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)
width: parent.width
msgText: messageDetails.messageText
visible: editMode
saveButtonText: statusMessage.saveButtonText
cancelButtonText: statusMessage.cancelButtonText
onCancelEditClicked: editMode = false
onEditCompleted: {
editMode = false
statusMessage.editCompleted(newMsgText)
}
}
StatusBaseText {
id: retryLbl
color: Theme.palette.dangerColor1
text: root.resendText
text: statusMessage.resendText
font.pixelSize: 12
visible: root.hasExpired && root.messageDetails.amISender && !root.timestamp && !editMode
visible: messageDetails.hasExpired && messageDetails.amISender && !messageDetails.timestamp && !editMode
MouseArea {
cursorShape: Qt.PointingHandCursor
anchors.fill: parent
onClicked: root.resendClicked()
onClicked: statusMessage.resendClicked()
}
}
Loader {
active: root.reactionsModel.count > 0
id: footer
active: sourceComponent && !editMode
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)
}
}
}
}
@@ -404,6 +195,6 @@ Rectangle {
anchors.rightMargin: 20
anchors.top: parent.top
anchors.topMargin: -8
visible: hoverHandler.hovered && !root.hideQuickActions
visible: hoverHandler.hovered && !editMode
}
}
@@ -6,10 +6,24 @@ QtObject {
id: msgDetails
property bool amISender: false
property StatusMessageSenderDetails sender: StatusMessageSenderDetails { }
property string displayName: ""
property string secondaryName: ""
property string chatID: ""
property StatusImageSettings profileImage: StatusImageSettings {
width: 40
height: 40
}
property bool isEdited: false
property int contentType: 0
property string messageText: ""
property int contentType: 0
property string messageContent: ""
property string messageOriginInfo: ""
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: ""
}
@@ -1,33 +0,0 @@
import QtQuick 2.0
import StatusQ.Core 0.1
QtObject {
id: root
property string id: ""
property string userName: ""
property string ensName: ""
property string localName: ""
property bool isContact: false
property int trustIndicator: StatusContactVerificationIcons.TrustedType.None
property StatusProfileImageSettings profileImage: StatusProfileImageSettings {
pubkey: root.id
showRing: !root.ensName
width: 40
height: 40
}
readonly property string displayName: root.localName !== ""
? root.localName
: root.ensName !== ""
? root.ensName
: root.userName
readonly property string secondaryName: root.localName === ""
? ""
: root.ensName !== ""
? root.ensName
: root.userName
}
@@ -12,9 +12,9 @@ StatusListItem {
implicitWidth: 286
implicitHeight: 48
asset.bgWidth: 20
asset.bgHeight: 20
asset.bgColor: "transparent"
icon.background.width: 20
icon.background.height: 20
icon.background.color: "transparent"
statusListItemIcon.anchors.topMargin: 14
+15 -13
View File
@@ -5,31 +5,33 @@ import StatusQ.Core.Theme 0.1
Rectangle {
id: statusRoundedIcon
property StatusAssetSettings asset: StatusAssetSettings {
property StatusIconSettings icon: StatusIconSettings {
width: 24
height: 24
rotation: 0
color: Theme.palette.primaryColor1
bgWidth: 40
bgHeight: 40
bgColor: Theme.palette.primaryColor3
background: StatusIconBackgroundSettings {
width: 40
height: 40
color: Theme.palette.primaryColor3
}
}
color: asset.bgColor
implicitWidth: asset.bgWidth
implicitHeight: asset.bgHeight
radius: asset.bgWidth / 2
color: icon.background.color
implicitWidth: icon.background.width
implicitHeight: icon.background.height
radius: icon.background.width / 2
StatusIcon {
id: statusIcon
anchors.centerIn: parent
width: statusRoundedIcon.asset.width
height: statusRoundedIcon.asset.height
width: statusRoundedIcon.icon.width
height: statusRoundedIcon.icon.height
color: statusRoundedIcon.asset.color
icon: statusRoundedIcon.asset.name
rotation: statusRoundedIcon.asset.rotation
color: statusRoundedIcon.icon.color
icon: statusRoundedIcon.icon.name
rotation: statusRoundedIcon.icon.rotation
}
}
+40 -36
View File
@@ -4,7 +4,7 @@ import StatusQ.Core.Theme 0.1
import StatusQ.Controls 0.1
Loader {
id: root
id: statusSmartIdenticon
property string name: ""
property int dZ: 100
@@ -12,46 +12,51 @@ Loader {
// Badge color properties must be set if badgeItem.visible = true
property alias badge: statusBadge
property StatusAssetSettings asset: StatusAssetSettings {
property StatusIconSettings icon: StatusIconSettings {
width: 40
height: 40
}
property StatusImageSettings image: StatusImageSettings {
width: 40
height: 40
}
property StatusIdenticonRingSettings ringSettings: StatusIdenticonRingSettings {
initalAngleRad: 0
ringPxSize: Math.max(1.5, root.asset.width/ 24.0)
ringPxSize: Math.max(1.5, statusSmartIdenticon.image.width / 24.0)
distinctiveColors: Theme.palette.identiconRingColors
}
sourceComponent: (root.asset.isLetterIdenticon || root.asset.name === "") ? letterIdenticon :
!root.asset.isImage ? roundedIcon : roundedImage
sourceComponent: statusSmartIdenticon.icon.isLetterIdenticon ? letterIdenticon :
!!statusSmartIdenticon.image.source.toString() ? roundedImage :
!!statusSmartIdenticon.icon.name.toString() ? roundedIcon : letterIdenticon
Component {
id: roundedImage
Item {
width: root.asset.width
height: root.asset.height
width: statusSmartIdenticon.image.width
height: statusSmartIdenticon.image.height
StatusRoundedImage {
id: statusRoundImage
width: parent.width
height: parent.height
image.source: root.asset.name
image.source: statusSmartIdenticon.image.source
showLoadingIndicator: true
border.width: root.asset.imgIsIdenticon ? 1 : 0
border.width: statusSmartIdenticon.image.isIdenticon ? 1 : 0
border.color: Theme.palette.directColor7
color: root.asset.imgIsIdenticon ?
color: statusSmartIdenticon.image.isIdenticon ?
Theme.palette.statusRoundedImage.backgroundColor :
"transparent"
}
Loader {
anchors.centerIn: parent
active: root.asset.imgStatus === Image.Error ||
statusRoundImage.image.status === Image.Error
active: statusRoundImage.image.status === Image.Error
sourceComponent: letterIdenticon
onLoaded: {
item.color = Theme.palette.miscColor5
item.width = root.asset.width
item.height = root.asset.height
item.width = statusSmartIdenticon.image.width
item.height = statusSmartIdenticon.image.height
}
}
}
@@ -60,48 +65,47 @@ Loader {
Component {
id: roundedIcon
StatusRoundIcon {
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
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
}
}
Component {
id: letterIdenticon
StatusLetterIdenticon {
objectName: "statusSmartIdenticonLetter"
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
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
}
}
// Next components are painted above main sourceComponent
StatusIdenticonRing {
settings: root.ringSettings
settings: statusSmartIdenticon.ringSettings
anchors.fill: parent
z: root.dZ/2
z: statusSmartIdenticon.dZ/2
}
// State component
StatusBadge {
id: statusBadge
visible: false
anchors.bottom: root.bottom
anchors.right: root.right
anchors.bottom: statusSmartIdenticon.bottom
anchors.right: statusSmartIdenticon.right
border.width: 3
implicitHeight: 15
implicitWidth: 15
z: root.dZ
z: statusSmartIdenticon.dZ
}
}
+6 -12
View File
@@ -180,7 +180,6 @@ Item {
"isContact": entry.isContact,
"ringSpecModel": entry.ringSpecModel,
"icon": entry.icon,
"isImage": entry.isImage,
"onlineStatus": entry.onlineStatus,
"tagIcon": entry.tagIcon ? entry.tagIcon : "",
"isReadonly": !!entry.isReadonly});
@@ -217,7 +216,7 @@ Item {
if(root.orderByReadonly) {
for(var i = 0; i < namesModel.count; i++) {
var entry = namesModel.get(i)
if(entry.tagIcon === "crown") {
if(entry.isReadonly) {
namesModel.move(i, 0, 1)
}
}
@@ -306,11 +305,8 @@ Item {
if ((event.key === Qt.Key_Backspace || event.key === Qt.Key_Escape)
&& getText(cursorPosition, (cursorPosition-1)) === ""
&& (namesList.count-1) >= 0) {
const item = namesModel.get(namesList.count-1)
if (!item.isReadonly) {
removeMember(item.pubKey);
namesModel.remove((namesList.count-1), 1);
}
removeMember(namesModel.get(namesList.count-1).pubKey);
namesModel.remove((namesList.count-1), 1);
}
if ((event.key === Qt.Key_Return || event.key === Qt.Key_Enter) && (sortedList.count > 0)) {
root.insertTag(sortedList.get(userListView.currentIndex).name,
@@ -382,7 +378,6 @@ Item {
}
contentItem: ListView {
id: userListView
objectName: "tagSelectorUserList"
anchors {
fill: parent
topMargin: 16
@@ -416,10 +411,9 @@ Item {
isVerified: model.isVerified
isUntrustworthy: model.isUntrustworthy
isContact: model.isContact
asset.name: model.icon
asset.color: Theme.palette.userCustomizationColors[root.colorIdForPubkeyGetter(model.pubKey)]
asset.isImage: (asset.name !== "")
asset.isLetterIdenticon: (asset.name === "")
image.source: model.icon
image.isIdenticon: false
icon.color: Theme.palette.userCustomizationColors[root.colorIdForPubkeyGetter(model.pubKey)]
status: model.onlineStatus
statusListItemIcon.badge.border.color: sensor.containsMouse ? Theme.palette.baseColor2 : Theme.palette.baseColor4
ringSettings.ringSpecModel: root.ringSpecModelGetter(model.pubKey)
@@ -75,10 +75,10 @@ Control {
property int duration: 0
/*!
\qmlproperty StatusAssetSettings StatusToastMessage::icon
\qmlproperty StatusIconSettings StatusToastMessage::icon
This property holds a set of settings for the icon of the ToastMessage.
*/
property StatusAssetSettings icon: StatusAssetSettings {
property StatusIconSettings icon: StatusIconSettings {
width: 23
height: 23
}
-44
View File
@@ -1,44 +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
ToolBar {
id: root
property int notificationCount: 0
property Item headerContent
property alias notificationButton: notificationButton
signal notificationButtonClicked()
implicitWidth: visible ? 518 : 0
implicitHeight: visible ? 60 : 0
padding: 8
background: null
RowLayout {
anchors.fill: parent
spacing: 0
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()
}
}
}
@@ -6,63 +6,45 @@ import StatusQ.Core.Theme 0.1
import StatusQ.Controls 0.1
Item {
id: root
id: editText
property alias inputComponent: chatInputLoader.sourceComponent
property alias active: chatInputLoader.active
property string cancelButtonText: ""
property string saveButtonText: ""
property string msgText: ""
signal editCancelled()
signal cancelEditClicked()
signal editCompleted(var newMsgText)
implicitHeight: layout.implicitHeight
implicitWidth: layout.implicitWidth
height: childrenRect.height
ColumnLayout {
id: layout
anchors.fill: parent
spacing: 4
Loader {
id: chatInputLoader
Layout.fillWidth: true
/*
NOTE: sourceComponent must have `messageText` property
TODO: Replace with StatusChatInput once its moved to StatusQ.
*/
// To-Do: Move to StatusChatInput once its moved to StatusQ
sourceComponent: StatusInput {
readonly property string messageText: input.text
width: parent.width
input.placeholderText: ""
width: editText.width
placeholderText: ""
input.text: msgText
maximumHeight: 40
input.implicitHeight: 40
}
}
RowLayout {
spacing: 4
StatusFlatButton {
id: cancelBtn
text: cancelButtonText
size: StatusBaseButton.Size.Small
onClicked: {
editCancelled()
}
onClicked: cancelEditClicked()
}
StatusButton {
id: saveBtn
text: saveButtonText
size: StatusBaseButton.Size.Small
enabled: !!chatInputLoader.item && chatInputLoader.item.messageText.trim().length > 0
onClicked: {
editCompleted(!chatInputLoader.item ? "" : chatInputLoader.item.messageText)
}
enabled: chatInputLoader.item.input.text.trim().length > 0
onClicked: editCompleted(chatInputLoader.item.input.text)
}
}
}
@@ -25,10 +25,10 @@ Item {
property string loadingImageText: ""
property string errorLoadingImageText: ""
signal clicked(var image, var mouse, var imageSource)
signal clicked(var image, var mouse)
implicitWidth: loadingImage.visible ? loadingImage.width : imageMessage.width
implicitHeight: loadingImage.visible ? loadingImage.height : imageMessage.paintedHeight
width: loadingImage.visible ? loadingImage.width : imageMessage.width
height: loadingImage.visible ? loadingImage.height : imageMessage.paintedHeight
QtObject {
id: _internal
@@ -87,7 +87,7 @@ Item {
_internal.pausePlaying = ! _internal.pausePlaying
return
}
imageContainer.clicked(imageMessage, mouse, imageMessage.source)
imageContainer.clicked(imageMessage, mouse)
}
}
}
@@ -1,227 +0,0 @@
import QtQuick 2.3
import QtQuick.Controls 2.13
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
Rectangle {
id: emojiContainer
readonly property bool isHovered: mouseArea.containsMouse
width: emojiImage.width + emojiCount.width + (root.imageMargin * 2) + + 8
height: 20
radius: 10
color: model.didIReactWithThisEmoji ?
(isHovered ? Theme.palette.statusMessage.emojiReactionActiveBackgroundHovered : Theme.palette.statusMessage.emojiReactionActiveBackground) :
(isHovered ? Theme.palette.statusMessage.emojiReactionBackgroundHovered : Theme.palette.statusMessage.emojiReactionBackground)
StatusToolTip {
visible: mouseArea.containsMouse
maxWidth: 400
text: d.showReactionAuthors(model.jsonArrayOfUsersReactedWithThisEmoji, model.emojiId)
}
// Rounded corner to cover one corner
Rectangle {
color: parent.color
width: 10
height: 10
anchors.top: parent.top
anchors.left: !root.isCurrentUser ? parent.left : undefined
anchors.leftMargin: 0
anchors.right: !root.isCurrentUser ? undefined : parent.right
anchors.rightMargin: 0
radius: 2
z: -1
}
// This is a workaround to get a "border" around the rectangle including the weird rectangle
Loader {
active: model.didIReactWithThisEmoji
anchors.top: parent.top
anchors.topMargin: -1
anchors.left: parent.left
anchors.leftMargin: -1
z: -2
sourceComponent: Component {
Rectangle {
width: emojiContainer.width + 2
height: emojiContainer.height + 2
radius: emojiContainer.radius
color: Theme.palette.primaryColor1
Rectangle {
color: parent.color
width: 10
height: 10
anchors.top: parent.top
anchors.left: !root.isCurrentUser ? parent.left : undefined
anchors.leftMargin: 0
anchors.right: !root.isCurrentUser ? undefined : parent.right
anchors.rightMargin: 0
radius: 2
z: -1
}
}
}
}
// TODO: Use Row
StatusEmoji {
id: emojiImage
anchors.verticalCenter: parent.verticalCenter
anchors.left: parent.left
anchors.leftMargin: root.imageMargin
width: 15
height: 15
source: {
if (model.emojiId >= 1 && model.emojiId <= root.icons.length)
return root.icons[model.emojiId - 1];
return "";
}
}
StatusBaseText {
id: emojiCount
text: model.numberOfReactions
anchors.verticalCenter: parent.verticalCenter
anchors.left: emojiImage.right
anchors.leftMargin: root.imageMargin
font.pixelSize: 12
color: model.didIReactWithThisEmoji ? Theme.palette.primaryColor1 : Theme.palette.directColor1
}
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
property bool isHovered: false // TODO: Replace with mouseArea.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
onEntered: addEmojiButton.isHovered = true
onExited: addEmojiButton.isHovered = false
onClicked: {
root.addEmojiClicked(this, mouse);
}
}
StatusToolTip {
visible: addEmojiButton.isHovered
text: qsTr("Add reaction")
}
}
}
}
@@ -3,41 +3,36 @@ 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: root
property StatusMessageSenderDetails sender: StatusMessageSenderDetails { }
id: statusMessageHeader
property alias displayNameLabel: primaryDisplayName
property alias secondaryNameLabel: secondaryDisplayName
property alias tertiaryDetailsLabel: tertiaryDetailText
property alias timestamp: timestampText
property string tertiaryDetail: sender.id
property string displayName: ""
property string secondaryName: ""
property string tertiaryDetail: ""
property string resendText: ""
property bool showResendButton: false
property bool isContact: sender.isContact
property int trustIndicator: sender.trustIndicator
property bool amISender: false
property bool displayNameClickable: true
property string messageOriginInfo: ""
property bool isContact: false
property var trustIndicator: StatusContactVerificationIcons.TrustedType.None
signal clicked(var sender, var mouse)
signal clicked()
signal resendClicked()
implicitHeight: layout.implicitHeight
implicitWidth: layout.implicitWidth
height: childrenRect.height
width: primaryDisplayName.width + (secondaryDisplayName.visible ? secondaryDisplayName.width + header.spacing : 0)
RowLayout {
id: layout
id: header
spacing: 4
TextEdit {
id: primaryDisplayName
Layout.alignment: Qt.AlignBottom
font.family: Theme.palette.baseFont.name
font.weight: Font.Medium
font.pixelSize: 15
@@ -46,62 +41,55 @@ Item {
wrapMode: Text.WordWrap
selectByMouse: true
color: Theme.palette.primaryColor1
text: root.amISender ? qsTr("You") : root.sender.displayName
text: displayName
MouseArea {
id: mouseArea
anchors.fill: parent
cursorShape: enabled ? Qt.PointingHandCursor : Qt.ArrowCursor
cursorShape: Qt.PointingHandCursor
acceptedButtons: Qt.LeftButton | Qt.RightButton
enabled: root.displayNameClickable
hoverEnabled: true
onClicked: {
root.clicked(this, mouse)
statusMessageHeader.clicked()
}
}
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 {
visible: !root.amISender
isContact: root.isContact
trustIndicator: root.trustIndicator
isContact: statusMessageHeader.isContact
trustIndicator: statusMessageHeader.trustIndicator
}
StatusBaseText {
id: secondaryDisplayName
Layout.alignment: Qt.AlignVCenter
visible: !root.amISender && !!root.sender.secondaryName
color: Theme.palette.baseColor1
font.pixelSize: 10
text: `(${root.sender.secondaryName})`
text: secondaryName
visible: !!text
}
StatusBaseText {
Layout.alignment: Qt.AlignVCenter
visible: secondaryDisplayName.visible
id: dotSeparator1
Layout.fillHeight: true
font.pixelSize: 10
color: Theme.palette.baseColor1
text: ""
text: "."
visible: secondaryDisplayName.visible
}
StatusBaseText {
id: tertiaryDetailText
visible: !root.amISender && messageOriginInfo == ""
Layout.alignment: Qt.AlignVCenter
Layout.maximumWidth: 58
font.pixelSize: 10
elide: Text.ElideMiddle
color: Theme.palette.baseColor1
text: Utils.elideText(tertiaryDetail, 5, 3)
text: tertiaryDetail
}
StatusBaseText {
Layout.alignment: Qt.AlignVCenter
visible: tertiaryDetailText.visible
id: dotSeparator2
Layout.fillHeight: true
font.pixelSize: 10
color: Theme.palette.baseColor1
text: ""
text: "."
visible: tertiaryDetailText.visible
}
StatusTimeStampLabel {
id: timestampText
@@ -110,12 +98,12 @@ Item {
Layout.alignment: Qt.AlignVCenter
color: Theme.palette.dangerColor1
font.pixelSize: 12
text: root.resendText
text: statusMessageHeader.resendText
visible: showResendButton && !!timestampText.text
MouseArea {
cursorShape: Qt.PointingHandCursor
anchors.fill: parent
onClicked: root.resendClicked()
onClicked: statusMessageHeader.resendClicked()
}
}
}
@@ -6,29 +6,29 @@ import StatusQ.Controls 0.1
import StatusQ.Core.Theme 0.1
Rectangle {
id: root
id: buttonsContainer
property list<Item> items
property list<Item> quickActions
QtObject {
id: _internal
readonly property int containerMargin: 2
}
implicitWidth: buttonRow.width + _internal.containerMargin * 2
implicitHeight: 36
width: buttonRow.width + _internal.containerMargin * 2
height: 36
radius: 8
color: Theme.palette.statusSelect.menuItemBackgroundColor
layer.enabled: true
layer.effect: DropShadow {
width: root.width
height: root.height
x: root.x
y: root.y + 10
width: buttonsContainer.width
height: buttonsContainer.height
x: buttonsContainer.x
y: buttonsContainer.y + 10
horizontalOffset: 0
verticalOffset: 2
source: root
source: buttonsContainer
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: root.verticalCenter
anchors.verticalCenter: buttonsContainer.verticalCenter
height: parent.height - 2 * _internal.containerMargin
}
onItemsChanged: {
for (let idx in items) {
items[idx].parent = buttonRow
onQuickActionsChanged: {
for (let idx in quickActions) {
quickActions[idx].parent = buttonRow
}
}
}
@@ -7,20 +7,18 @@ import StatusQ.Core 0.1
import StatusQ.Core.Theme 0.1
import StatusQ.Components 0.1
Item {
id: root
Loader {
id: chatReply
property StatusMessageDetails replyDetails
property string audioMessageInfoText: ""
property bool profileClickable: true
signal replyProfileClicked(var sender, var mouse)
signal replyProfileClicked()
implicitHeight: layout.implicitHeight
implicitWidth: layout.implicitWidth
active: visible
RowLayout {
id: layout
sourceComponent: RowLayout {
id: replyLayout
spacing: 8
Shape {
id: replyCorner
@@ -58,15 +56,13 @@ Item {
StatusSmartIdenticon {
id: profileImage
Layout.alignment: Qt.AlignTop
name: replyDetails.sender.userName
asset: replyDetails.sender.profileImage.assetSettings
ringSettings: replyDetails.sender.profileImage.ringSettings
image: replyDetails.profileImage
name: replyDetails.displayName
MouseArea {
cursorShape: enabled ? Qt.PointingHandCursor : Qt.ArrowCursor
cursorShape: Qt.PointingHandCursor
acceptedButtons: Qt.LeftButton | Qt.RightButton
anchors.fill: parent
enabled: root.profileClickable
onClicked: replyProfileClicked(this, mouse)
onClicked: replyProfileClicked()
}
}
TextEdit {
@@ -78,7 +74,7 @@ Item {
font.weight: Font.Medium
selectByMouse: true
readOnly: true
text: replyDetails.amISender ? qsTr("You") : replyDetails.sender.displayName
text: replyDetails.displayName
}
}
StatusTextMessage {
@@ -89,14 +85,13 @@ Item {
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 {
@@ -105,10 +100,9 @@ Item {
Layout.alignment: Qt.AlignLeft
visible: replyDetails.contentType === StatusMessage.ContentType.Sticker
StatusSticker {
asset.width: 48
asset.height: 48
asset.name: replyDetails.messageContent
asset.isImage: true
image.width: 48
image.height: 48
image.source: replyDetails.messageContent
}
}
Item {
@@ -122,7 +116,7 @@ Item {
height: 22
isPreview: true
audioSource: replyDetails.messageContent
audioMessageInfoText: root.audioMessageInfoText
audioMessageInfoText: chatReply.audioMessageInfoText
}
}
}
@@ -1,5 +1,4 @@
import QtQuick 2.13
import QtQuick.Controls 2.14
import QtQuick.Layouts 1.14
import QtGraphicalEffects 1.13
@@ -12,34 +11,14 @@ Loader {
active: visible
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 {
sourceComponent: Rectangle {
height: 24
width: layout.width + 16
color: Theme.palette.pinColor2
radius: 12
RowLayout {
id: layout
anchors.centerIn: parent
StatusIcon {
Layout.alignment: Qt.AlignVCenter
Layout.preferredWidth: 16
@@ -10,7 +10,7 @@ Loader {
property bool noHover: false
property bool noMouseArea: false
property StatusAssetSettings asset: StatusAssetSettings {
property StatusImageSettings image: StatusImageSettings {
width: 140
height: 140
}
@@ -26,8 +26,8 @@ Loader {
color: Theme.palette.baseColor2
radius: 16
width: asset.width
height: asset.height
width: image.width
height: image.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: asset.name
source: image.source
onStatusChanged: {
if (status === Image.Ready) {
@@ -6,34 +6,24 @@ import StatusQ.Controls 0.1
import StatusQ.Core.Theme 0.1
Item {
id: root
id: textMessage
property int contentType: 0
property alias textField: chatText
property bool allowShowMore: true
signal linkActivated(string link)
signal linkActivated(url link)
implicitWidth: chatText.implicitWidth
implicitHeight: chatText.effectiveHeight + d.showMoreHeight
implicitHeight: showMoreLoader.active ? childrenRect.height : chatText.height
QtObject {
id: d
id: _internal
property bool readMore: false
readonly property bool veryLongChatText: chatText.length > 1000
readonly property int showMoreHeight: showMoreLoader.visible ? showMoreLoader.height : 0
property bool veryLongChatText: chatText.length > 1000
}
TextEdit {
id: chatText
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
visible: !showMoreLoader.active || _internal.readMore
selectedTextColor: Theme.palette.directColor1
selectionColor: Theme.palette.primaryColor3
color: Theme.palette.directColor1
@@ -43,12 +33,12 @@ Item {
wrapMode: Text.Wrap
readOnly: true
selectByMouse: true
onLinkActivated: {
root.linkActivated(link);
}
height: _internal.veryLongChatText && !_internal.readMore ? Math.min(implicitHeight, 200) : implicitHeight
width: parent.width
clip: height < implicitHeight
onLinkActivated: textMessage.linkActivated(link)
onLinkHovered: {
// Strange thing. Without this empty stub the cursorShape
// is not changed to pointingHandCursor.
cursorShape: Qt.PointingHandCursor
}
}
@@ -70,7 +60,7 @@ Item {
Loader {
id: opMask
active: showMoreLoader.active && !d.readMore
active: showMoreLoader.active && !_internal.readMore
anchors.fill: chatText
sourceComponent: OpacityMask {
source: chatText
@@ -80,17 +70,17 @@ Item {
Loader {
id: showMoreLoader
active: root.allowShowMore && d.veryLongChatText
visible: active
anchors.verticalCenter: chatText.bottom
active: _internal.veryLongChatText
anchors.top: chatText.bottom
anchors.topMargin: -10
anchors.horizontalCenter: parent.horizontalCenter
sourceComponent: StatusRoundButton {
implicitWidth: 24
implicitHeight: 24
type: StatusRoundButton.Type.Secondary
icon.name: d.readMore ? "chevron-up": "chevron-down"
icon.name: _internal.readMore ? "chevron-up": "chevron-down"
onClicked: {
d.readMore = !d.readMore
_internal.readMore = !_internal.readMore
}
}
}
+1 -5
View File
@@ -1,7 +1,6 @@
module StatusQ.Components
StatusAddress 0.1 StatusAddress.qml
StatusAddressPanel 0.1 StatusAddressPanel.qml
StatusBadge 0.1 StatusBadge.qml
StatusChatInfoToolBar 0.1 StatusChatInfoToolBar.qml
StatusChatList 0.1 StatusChatList.qml
@@ -9,11 +8,10 @@ StatusChatListItem 0.1 StatusChatListItem.qml
StatusChatListCategory 0.1 StatusChatListCategory.qml
StatusChatListCategoryItem 0.1 StatusChatListCategoryItem.qml
StatusChatListAndCategories 0.1 StatusChatListAndCategories.qml
StatusToolBar 0.1 StatusToolBar.qml
StatusChatToolBar 0.1 StatusChatToolBar.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
@@ -32,7 +30,6 @@ 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
@@ -42,4 +39,3 @@ StatusCommunityCard 0.1 StatusCommunityCard.qml
StatusCommunityTags 0.1 StatusCommunityTags.qml
StatusItemSelector 0.1 StatusItemSelector.qml
StatusCard 0.1 StatusCard.qml
StatusDatePicker 0.1 StatusDatePicker.qml
+124 -133
View File
@@ -8,17 +8,17 @@ import StatusQ.Core.Theme 0.1
import StatusQ.Core.Utils 0.1
import StatusQ.Controls 0.1
import SortFilterProxyModel 0.2
Item {
id: root
property string label: "Choose account"
property bool showAccountDetails: !!selectedAccount
property var accounts
property var selectedAccount
property string currency: "usd"
property alias selectField: select
implicitWidth: 448
height: select.height +
(selectedAccountDetails.visible ? selectedAccountDetails.height + selectedAccountDetails.anchors.topMargin : 0)
// set to asset symbol to display asset's balance top right
// NOTE: if this asset is not selected as a wallet token in the UI, then
// nothing will be displayed
@@ -27,10 +27,10 @@ Item {
property double minRequiredAssetBalance: 0
property int dropdownWidth: width
property int chainId: 0
property alias dropdownAlignment: select.menuAlignment
property bool isValid: true
property bool readOnly: false
property var assetBalanceTextFn: function (foundValue) {
return "Balance: " + (parseFloat(foundValue) === 0.0 ? "0" : Utils.stripTrailingZeros(foundValue))
}
@@ -51,23 +51,18 @@ Item {
return root.isValid
}
implicitWidth: 448
implicitHeight: comboBox.height +
(selectedAccountDetails.visible ? selectedAccountDetails.height + selectedAccountDetails.anchors.topMargin
: 0)
onSelectedAccountChanged: {
if (!selectedAccount) {
return
}
if (selectedAccount.color) {
d.selectedIconColor = Utils.getThemeAccountColor(selectedAccount.color, Theme.palette.userCustomizationColors) || Theme.palette.userCustomizationColors[0]
selectedIconImg.color = Utils.getThemeAccountColor(selectedAccount.color, Theme.palette.userCustomizationColors) || Theme.palette.userCustomizationColors[0]
}
if (selectedAccount.name) {
d.selectedText = selectedAccount.name
selectedTextField.text = selectedAccount.name
}
if (selectedAccount.address) {
textSelectedAddress.text = selectedAccount.address
textSelectedAddress.text = selectedAccount.address + " •"
}
if (selectedAccount.currencyBalance) {
textSelectedAddressFiatBalance.text = selectedAccount.currencyBalance + " " + currency.toUpperCase()
@@ -92,20 +87,14 @@ Item {
txtAssetSymbol.text = " " + assetFound.symbol
}
QtObject {
id: d
property color selectedIconColor: "transparent"
property string selectedText: ""
}
StatusBaseText {
id: txtAssetBalance
visible: root.assetFound !== undefined
anchors.bottom: comboBox.top
anchors.bottom: select.top
anchors.bottomMargin: -18
anchors.right: txtAssetSymbol.left
anchors.left: comboBox.left
anchors.leftMargin: comboBox.width / 2.5
anchors.left: select.left
anchors.leftMargin: select.width / 2.5
color: !root.isValid ? Theme.palette.dangerColor1 : Theme.palette.baseColor1
elide: Text.ElideRight
@@ -127,7 +116,6 @@ Item {
onExited: assetTooltip.visible = false
}
}
StatusBaseText {
id: txtAssetSymbol
visible: txtAssetBalance.visible
@@ -138,150 +126,153 @@ Item {
font.pixelSize: 13
height: txtAssetBalance.height
}
StatusComboBox {
id: comboBox
StatusSelect {
id: select
label: root.label
model: root.accounts
width: parent.width
model: SortFilterProxyModel {
sourceModel: root.accounts
filters: [
ValueFilter {
roleName: "walletType"
value: root.watchWalletType
inverted: true
}
]
}
contentItem: RowLayout {
spacing: 8
menuAlignment: StatusSelect.MenuAlignment.Left
selectMenu.delegate: menuItem
selectMenu.width: dropdownWidth
selectedItemComponent: Item {
anchors.fill: parent
StatusIcon {
Layout.alignment: Qt.AlignVCenter
Layout.preferredWidth: 20
Layout.preferredHeight: 20
id: selectedIconImg
anchors.left: parent.left
anchors.leftMargin: 16
anchors.verticalCenter: parent.verticalCenter
width: 20
height: 20
icon: "filled-account"
color: d.selectedIconColor
}
StatusBaseText {
id: selectedTextField
elide: Text.ElideRight
Layout.fillWidth: true
Layout.fillHeight: true
anchors.left: selectedIconImg.right
anchors.leftMargin: 8
anchors.right: parent.right
anchors.rightMargin: select.selectedItemRightMargin
anchors.verticalCenter: parent.verticalCenter
font.pixelSize: 15
verticalAlignment: Text.AlignVCenter
height: 22
color: Theme.palette.directColor1
text: d.selectedText
}
}
}
delegate: StatusItemDelegate {
highlighted: index === comboBox.control.highlightedIndex
width: comboBox.width
padding: 16
Row {
id: selectedAccountDetails
visible: root.showAccountDetails
anchors.top: select.bottom
anchors.topMargin: 8
anchors.left: parent.left
anchors.leftMargin: 2
onClicked: {
// WARNING: Settings comboBox value from delegate is wrong.
// ComboBox must have a single role as "value"
// This should be refactored later. Probably roleValue should be 'address'.
// All other needed values should be retrived from model by the user of component.
root.selectedAccount = { address, name, color: model.color, assets, currencyBalance };
}
StatusBaseText {
id: textSelectedAddress
font.pixelSize: 12
elide: Text.ElideMiddle
width: 90
color: Theme.palette.baseColor1
}
StatusBaseText {
id: textSelectedAddressFiatBalance
font.pixelSize: 12
color: Theme.palette.baseColor1
}
}
Component {
id: menuItem
MenuItem {
id: itemContainer
visible: walletType !== root.watchWalletType
property bool isFirstItem: index === 0
property bool isLastItem: index === accounts.rowCount() - 1
Component.onCompleted: {
// WARNING: Same here, this is wrong, check comment above.
if (!root.selectedAccount && index === 0) {
if (!root.selectedAccount && isFirstItem) {
root.selectedAccount = { address, name, color: model.color, assets, currencyBalance }
}
}
contentItem: RowLayout {
spacing: 0
height: walletType === root.watchWalletType ? 0 : (accountName.height + 14 + accountAddress.height + 14)
StatusIcon {
id: iconImg
Layout.preferredWidth: 20
Layout.preferredHeight: 20
icon: "filled-account"
color: Utils.getThemeAccountColor(model.color, Theme.palette.userCustomizationColors) ||
Theme.palette.userCustomizationColors[0]
}
StatusIcon {
id: iconImg
anchors.left: parent.left
anchors.leftMargin: 16
anchors.verticalCenter: parent.verticalCenter
width: 20
height: 20
icon: "filled-account"
color: Utils.getThemeAccountColor(model.color, Theme.palette.userCustomizationColors) || Theme.palette.userCustomizationColors[0]
}
ColumnLayout {
id: column
Layout.fillWidth: true
Layout.leftMargin: 14
Layout.rightMargin: 8
spacing: 0
Column {
id: column
anchors.left: iconImg.right
anchors.leftMargin: 14
anchors.right: txtFiatBalance.left
anchors.rightMargin: 8
anchors.verticalCenter: parent.verticalCenter
StatusBaseText {
id: accountName
Layout.fillWidth: true
text: model.name
elide: Text.ElideRight
font.pixelSize: 15
color: Theme.palette.directColor1
}
StatusBaseText {
id: accountAddress
Layout.fillWidth: true
Layout.maximumWidth: 80
text: address
elide: Text.ElideMiddle
color: Theme.palette.baseColor1
font.pixelSize: 12
}
}
StatusBaseText {
id: txtFiatBalance
Layout.rightMargin: 4
id: accountName
text: model.name
elide: Text.ElideRight
font.pixelSize: 15
text: currencyBalance
anchors.left: parent.left
anchors.right: parent.right
height: 22
color: Theme.palette.directColor1
}
StatusBaseText {
id: fiatCurrencySymbol
font.pixelSize: 15
id: accountAddress
text: address
elide: Text.ElideMiddle
width: 80
color: Theme.palette.baseColor1
text: root.currency.toUpperCase()
font.pixelSize: 12
height: 16
}
}
StatusBaseText {
id: txtFiatBalance
anchors.right: fiatCurrencySymbol.left
anchors.rightMargin: 4
anchors.verticalCenter: parent.verticalCenter
font.pixelSize: 15
height: 22
text: currencyBalance
color: Theme.palette.directColor1
}
StatusBaseText {
id: fiatCurrencySymbol
anchors.right: parent.right
anchors.rightMargin: 16
anchors.verticalCenter: parent.verticalCenter
font.pixelSize: 15
height: 22
color: Theme.palette.baseColor1
text: root.currency.toUpperCase()
}
background: Rectangle {
color: itemContainer.highlighted ? Theme.palette.statusSelect.menuItemHoverBackgroundColor : Theme.palette.statusSelect.menuItemBackgroundColor
}
MouseArea {
cursorShape: Qt.PointingHandCursor
anchors.fill: itemContainer
onClicked: {
root.selectedAccount = { address, name, color: model.color, assets, currencyBalance }
select.selectMenu.close()
}
}
}
}
RowLayout {
id: selectedAccountDetails
visible: root.showAccountDetails
anchors.top: comboBox.bottom
anchors.topMargin: 8
anchors.left: parent.left
anchors.leftMargin: 2
anchors.right: parent.right
anchors.rightMargin: 4
spacing: 2
StatusBaseText {
id: textSelectedAddress
Layout.maximumWidth: 80
font.pixelSize: 12
elide: Text.ElideMiddle
color: Theme.palette.baseColor1
}
StatusBaseText {
font.pixelSize: 12
color: Theme.palette.baseColor1
text: "•"
}
StatusBaseText {
id: textSelectedAddressFiatBalance
Layout.fillWidth: true
font.pixelSize: 12
color: Theme.palette.baseColor1
}
}
}
@@ -1,6 +0,0 @@
import QtQuick 2.14
import StatusQ.Controls 0.1
StatusRoundButton {
icon.name: "arrow-left"
}
+6 -6
View File
@@ -15,11 +15,10 @@ Rectangle {
enum Type {
Normal,
Danger,
Primary
Danger
}
property StatusAssetSettings icon: StatusAssetSettings {
property StatusIconSettings icon: StatusIconSettings {
width: 24
height: 24
}
@@ -89,7 +88,7 @@ Rectangle {
color: {
if (statusBaseButton.enabled)
return !statusBaseButton.loading && (sensor.containsMouse || highlighted) ? hoverColor
return sensor.containsMouse || highlighted ? hoverColor
: normalColor;
return disaledColor
}
@@ -106,7 +105,7 @@ Rectangle {
: Qt.PointingHandCursor
hoverEnabled: true
enabled: statusBaseButton.enabled
enabled: !loading && statusBaseButton.enabled
Loader {
anchors.centerIn: parent
@@ -146,7 +145,7 @@ Rectangle {
color: d.textColor
} // Text
} // Row
} // Ro
onPressed: {
@@ -173,4 +172,5 @@ Rectangle {
}
}
} // Sensor
}
+37 -29
View File
@@ -7,7 +7,6 @@ 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
@@ -183,9 +182,9 @@ Item {
/*!
\qmlproperty bool StatusBaseInput::valid
This property sets the valid state. Default value is false.
This property sets the valid state. Default value is true.
*/
property bool valid: false
property bool valid: true
/*!
\qmlproperty bool StatusBaseInput::pristine
This property sets the pristine. Default value is true.
@@ -218,19 +217,21 @@ Item {
property bool showBackground: true
/*!
\qmlproperty StatusAssetSettings StatusBaseInput::icon
\qmlproperty StatusIconSettings StatusBaseInput::icon
This property holds a set of settings for the icon of the StatusBaseInput.
*/
property StatusAssetSettings asset: StatusAssetSettings {
property StatusIconSettings icon: StatusIconSettings {
width: 24
height: 24
name: ""
color: Theme.palette.baseColor1
emoji: ""
letterSize: emoji ? 11 : 14
bgWidth: 30
bgHeight: 30
bgColor: Theme.palette.indirectColor1
background: StatusIconBackgroundSettings {
width: 30
height: 30
color: Theme.palette.indirectColor1
}
}
/*!
@@ -316,8 +317,8 @@ Item {
sourceComponent: {
if (root.leftComponent) return root.leftComponent
if (!root.leftIcon) return undefined
if (root.asset.emoji || root.asset.isLetterIdenticon) return identiconComponent
if (root.asset.name) return isIconSelectable ? identiconComponent : iconComponent
if (root.icon.emoji || root.icon.isLetterIdenticon) return identiconComponent
if (root.icon.name) return isIconSelectable ? identiconComponent : iconComponent
return undefined
}
}
@@ -326,7 +327,6 @@ Item {
id: flick
Layout.fillWidth: true
Layout.fillHeight: true
Layout.leftMargin: !!leftComponentLoader.item ? 8 : 0
Layout.topMargin: root.topPadding
Layout.bottomMargin: root.bottomPadding
contentWidth: edit.paintedWidth
@@ -338,6 +338,17 @@ 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
@@ -362,7 +373,7 @@ Item {
edit.keyEvent = event.key
root.keyPressed(event);
}
onCursorRectangleChanged: Utils.ensureVisible(flick, cursorRectangle)
onCursorRectangleChanged: flick.ensureVisible(cursorRectangle)
onActiveFocusChanged: if (root.pristine) root.pristine = false
onTextChanged: {
if (previousText === text) {
@@ -405,7 +416,6 @@ Item {
anchors.fill: parent
verticalAlignment: parent.verticalAlignment
font.pixelSize: 15
wrapMode: root.multiline ? Text.WordWrap : Text.NoWrap
elide: StatusBaseText.ElideRight
font.family: Theme.palette.baseFont.name
color: root.enabled ? Theme.palette.baseColor1 : Theme.palette.directColor6
@@ -418,8 +428,8 @@ Item {
if (root.rightComponent) return root.rightComponent
if (root.clearable) return clearButton
if (root.leftIcon) return undefined
if (root.asset.emoji) return identiconComponent
if (root.asset.name) return isIconSelectable ? identiconComponent : iconComponent
if (root.icon.emoji) return identiconComponent
if (root.icon.name) return isIconSelectable ? identiconComponent : iconComponent
return undefined
}
}
@@ -453,16 +463,14 @@ Item {
StatusSmartIdenticon {
id: identicon
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
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
name: root.letterIconName
MouseArea {
@@ -482,10 +490,10 @@ Item {
StatusIcon {
id: statusIcon
icon: root.asset.name
width: root.asset.width
height: root.asset.height
color: root.asset.color
icon: root.icon.name
width: root.icon.width
height: root.icon.height
color: root.icon.color
}
}
}
+6 -11
View File
@@ -5,18 +5,13 @@ import StatusQ.Core.Theme 0.1
StatusBaseButton {
id: statusButton
normalColor: type === StatusBaseButton.Type.Primary ? Theme.palette.primaryColor1 :
type === StatusBaseButton.Type.Normal ? Theme.palette.primaryColor3
: Theme.palette.dangerColor3
hoverColor: type === StatusBaseButton.Type.Primary ? Theme.palette.hoverColor(normalColor) :
type === StatusBaseButton.Type.Normal ? Theme.palette.primaryColor2
: Theme.palette.dangerColor2
normalColor: type === StatusBaseButton.Type.Normal ? Theme.palette.primaryColor3
: Theme.palette.dangerColor3
hoverColor: type === StatusBaseButton.Type.Normal ? Theme.palette.primaryColor2
: Theme.palette.dangerColor2
disaledColor: Theme.palette.baseColor2
textColor: type === StatusBaseButton.Type.Primary ? Theme.palette.white :
type === StatusBaseButton.Type.Normal ? Theme.palette.primaryColor1
: Theme.palette.dangerColor1
textColor: 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,9 +16,10 @@ Rectangle {
signal clicked(var mouse)
property StatusAssetSettings icon: StatusAssetSettings {
property StatusIconSettings icon: StatusIconSettings {
width: 24
height: 24
background: StatusIconBackgroundSettings {}
}
color: {
@@ -40,14 +41,14 @@ Rectangle {
}
StatusRoundIcon {
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
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
anchors.top: parent.top
anchors.topMargin: 8
anchors.left: parent.left
@@ -6,7 +6,6 @@ import StatusQ.Components 0.1
Rectangle {
id: statusChatInfoButton
objectName: "chatInfoButton"
implicitWidth: identicon.width +
Math.max(
@@ -19,8 +18,11 @@ Rectangle {
property string subTitle: ""
property bool muted: false
property int pinnedMessagesCount: 0
property StatusAssetSettings asset: StatusAssetSettings {
property StatusImageSettings image: StatusImageSettings {
width: 36
height: 36
}
property StatusIconSettings icon: StatusIconSettings {
width: 36
height: 36
charactersLen: 2
@@ -62,7 +64,8 @@ Rectangle {
anchors.left: parent.left
anchors.leftMargin: 4
anchors.verticalCenter: parent.verticalCenter
asset: statusChatInfoButton.asset
image: statusChatInfoButton.image
icon: statusChatInfoButton.icon
name: statusChatInfoButton.title
}
@@ -212,7 +215,6 @@ Rectangle {
}
StatusBaseText {
objectName: "StatusChatInfo_pinText"
anchors.left: pinIcon.right
anchors.leftMargin: -6
anchors.verticalCenter: pinIcon.verticalCenter
+9 -15
View File
@@ -8,20 +8,16 @@ import StatusQ.Components 0.1
CheckBox {
id: root
property bool leftSide: true
id: statusCheckBox
indicator: Rectangle {
anchors.left: root.leftSide? parent.left : undefined
anchors.right: !root.leftSide? parent.right : undefined
implicitWidth: 18
implicitHeight: 18
x: !root.leftSide? root.rightPadding : root.leftPadding
x: statusCheckBox.leftPadding
y: parent.height / 2 - height / 2
radius: 2
color: (root.down || root.checked) ? Theme.palette.primaryColor1
: Theme.palette.directColor8
color: (statusCheckBox.down || statusCheckBox.checked) ? Theme.palette.primaryColor1
: Theme.palette.directColor8
StatusIcon {
icon: "checkbox"
@@ -30,21 +26,19 @@ CheckBox {
anchors.centerIn: parent
anchors.horizontalCenterOffset: 1
color: Theme.palette.white
visible: root.down || root.checked
visible: statusCheckBox.down || statusCheckBox.checked
}
}
contentItem: StatusBaseText {
text: root.text
font.pixelSize: root.font.pixelSize
text: statusCheckBox.text
font.pixelSize: statusCheckBox.font.pixelSize
opacity: enabled ? 1.0 : 0.3
verticalAlignment: Text.AlignVCenter
wrapMode: Text.WordWrap
width: parent.width
color: Theme.palette.directColor1
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
leftPadding: !!statusCheckBox.text ? statusCheckBox.indicator.width + statusCheckBox.spacing
: statusCheckBox.indicator.width
}
}
@@ -8,21 +8,19 @@ RadioButton {
property string radioButtonColor: ""
property string selectionColor: StatusColors.colors['white']
property int diameter: 48
property int selectorDiameter: 20
implicitWidth: 48
implicitHeight: 48
indicator: Rectangle {
implicitWidth: control.diameter
implicitHeight: control.diameter
implicitWidth: 48
implicitHeight: 48
radius: width/2
color: radioButtonColor
Rectangle {
width: control.selectorDiameter
height: control.selectorDiameter
width: 20
height: 20
radius: width/2
color: selectionColor
border.color: StatusColors.colors['grey3']
+29 -21
View File
@@ -2,28 +2,36 @@ import QtQuick 2.13
import QtQuick.Controls 2.13
import StatusQ.Controls 0.1
StatusComboBox {
id: root
Item {
id: root
property string selectedColor
property string label: "Color"
property var model
height: accountColorInput.height
implicitWidth: 448
label: qsTr("Color")
StatusSelect {
id: accountColorInput
bgColor: selectedColor
label: root.label
model: root.model
control.popup.horizontalPadding: 0
contentItem: null
control.background: Rectangle {
implicitWidth: 448
radius: 8
color: root.control.currentValue
}
delegate: StatusItemDelegate {
width: parent.width
background: Rectangle {
width: parent.width
implicitHeight: 52
color: modelData
}
}
selectMenu.delegate: Component {
MenuItem {
property bool isFirstItem: index === 0
property bool isLastItem: index === root.model.length - 1
height: 52
width: parent.width
padding: 10
onTriggered: function () {
const selectedColor = root.model[index]
root.selectedColor = selectedColor
}
background: Rectangle {
color: root.model[index] || "transparent"
}
}
}
}
}
@@ -12,9 +12,6 @@ Column {
property alias title: title
property alias columns: grid.columns
property int diameter: 48
property int selectorDiameter: 20
property int selectedColorIndex: 0
property string selectedColor: ""
property var model:[ StatusColors.colors['black'],
@@ -47,13 +44,8 @@ Column {
rowSpacing: 16
columnSpacing: 32
Repeater {
objectName: "statusColorRepeater"
model: root.model
delegate: StatusColorRadioButton {
implicitWidth: root.diameter
implicitHeight: root.diameter
diameter: root.diameter
selectorDiameter: root.selectorDiameter
checked: index === selectedColorIndex
radioButtonColor: root.model[index] || "transparent"
onCheckedChanged: {
-167
View File
@@ -1,167 +0,0 @@
import QtQuick 2.14
import QtQuick.Window 2.14
import QtQuick.Controls 2.14
import QtQuick.Layouts 1.14
import QtGraphicalEffects 1.13
import StatusQ.Core 0.1
import StatusQ.Core.Theme 0.1
import StatusQ.Popups 0.1
import QtQuick.Templates 2.14 as T
Item {
id: root
property alias control: comboBox
property alias model: comboBox.model
property alias delegate: comboBox.delegate
property alias contentItem: comboBox.contentItem
property alias currentIndex: comboBox.currentIndex
property alias currentValue: comboBox.currentValue
property alias label: labelItem.text
property alias validationError: validationErrorItem.text
property string popupContentItemObjectName: ""
implicitWidth: layout.implicitWidth
implicitHeight: layout.implicitHeight
LayoutMirroring.childrenInherit: true
ColumnLayout {
id: layout
anchors.fill: parent
spacing: 0
StatusBaseText {
id: labelItem
Layout.fillWidth: true
visible: !!text
font.pixelSize: 15
color: root.enabled ? Theme.palette.directColor1 : Theme.palette.baseColor1
}
ComboBox {
id: comboBox
property color bgColor: Theme.palette.baseColor2
property color bgColorHover: bgColor
Layout.fillWidth: true
Layout.fillHeight: true
Layout.topMargin: labelItem.visible ? 7 : 0
enabled: root.enabled
font.family: Theme.palette.baseFont.name
font.pixelSize: 14
padding: 16
spacing: 16
background: Rectangle {
implicitHeight: 56
implicitWidth: 448
color: Theme.palette.baseColor2
radius: 8
border.width: !!root.validationError || comboBox.hovered || comboBox.down || comboBox.activeFocus ? 1 : 0
border.color: !!root.validationError
? Theme.palette.dangerColor1
: comboBox.activeFocus
? Theme.palette.primaryColor1
: comboBox.hovered
? Theme.palette.primaryColor2
: "transparent"
MouseArea {
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
acceptedButtons: Qt.NoButton
enabled: root.enabled
}
}
contentItem: StatusBaseText {
font: comboBox.font
verticalAlignment: Text.AlignVCenter
elide: Text.ElideRight
text: comboBox.displayText
color: root.enabled ? Theme.palette.directColor1 : Theme.palette.baseColor1
}
indicator: StatusIcon {
x: comboBox.mirrored ? comboBox.padding : comboBox.width - width - comboBox.padding
y: comboBox.topPadding + (comboBox.availableHeight - height) / 2
width: 24
height: 24
icon: "chevron-down"
color: Theme.palette.baseColor1
}
popup: Popup {
closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutsideParent
y: comboBox.height + 8
width: comboBox.width
height: Math.min(implicitContentHeight + topPadding + bottomPadding,
comboBox.Window.height - topMargin - bottomMargin)
margins: 8
padding: 1
verticalPadding: 8
background: Rectangle {
id: backgroundItem
color: Theme.palette.statusSelect.menuItemBackgroundColor
radius: 8
border.color: Theme.palette.baseColor2
layer.enabled: true
layer.effect: DropShadow {
horizontalOffset: 0
verticalOffset: 4
radius: 12
samples: 25
spread: 0.2
color: Theme.palette.dropShadow
}
}
contentItem: StatusListView {
id: listView
objectName: root.popupContentItemObjectName
implicitWidth: contentWidth
implicitHeight: contentHeight
model: comboBox.popup.visible ? comboBox.delegateModel : null
currentIndex: comboBox.highlightedIndex
}
}
delegate: StatusItemDelegate {
width: comboBox.width
highlighted: comboBox.highlightedIndex === index
font: comboBox.font
text: control.textRole ? (Array.isArray(control.model)
? modelData[control.textRole]
: model[control.textRole])
: modelData
}
}
StatusBaseText {
id: validationErrorItem
Layout.fillWidth: true
Layout.topMargin: 11
visible: !!text
font.pixelSize: 12
color: Theme.palette.dangerColor1
horizontalAlignment: TextEdit.AlignRight
wrapMode: Text.WordWrap
}
}
}
+1 -5
View File
@@ -33,8 +33,6 @@ Rectangle {
anchors.centerIn: parent
StatusEmoji {
width: 18
height: 18
emojiId: root.emoji != "" ? Emoji.iconHex(root.emoji) : ""
anchors.verticalCenter: parent.verticalCenter
}
@@ -46,9 +44,7 @@ Rectangle {
StatusBaseText {
anchors.verticalCenter: parent.verticalCenter
font.pixelSize: 15
font.weight: Font.DemiBold
font.capitalization: Font.AllLowercase
font.pixelSize: 13
color: root.enabled ? Theme.palette.primaryColor1 : Theme.palette.baseColor1
text: root.name
}
@@ -7,7 +7,7 @@ import StatusQ.Components 0.1
Rectangle {
id: statusFlatRoundButton
property StatusAssetSettings icon: StatusAssetSettings {
property StatusIconSettings icon: StatusIconSettings {
width: 23
height: 23
rotation: 0
@@ -42,14 +42,6 @@ import StatusQ.Popups 0.1
Row {
id: floatingButtons
/*!
\qmlproperty repeater
This property represents the repeater of selectable items shown to the user.
Can be used to assign objectName to the repeater
\endqml
*/
readonly property alias repeater: itemSelectionRepeater
/*!
\qmlproperty delegate
This property represents the delegate of selectable items shown to the user.
@@ -115,10 +107,9 @@ Row {
bottomPadding: 0
defaultLeftPadding: 4
defaultRightPadding: 4
hoverColor: Theme.palette.statusFloatingButtonHighlight
normalColor: Theme.palette.baseColor3
normalColor: "transparent"
icon.name: "more"
icon.bgColor: "transparent"
icon.background.color: "transparent"
onClicked: popupMenu.popup(parent.x, y + height + 8)
}
}
+8 -7
View File
@@ -26,13 +26,14 @@ TabButton {
id: identicon
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
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
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()
name: statusIconTabButton.name
}
}
@@ -64,7 +64,6 @@ AbstractButton {
width: root.icon.width
height: root.icon.height
rotation: root.iconRotation
visible: status == Image.Ready
}
StatusBaseText {
Layout.alignment: Qt.AlignVCenter
+7 -14
View File
@@ -303,6 +303,8 @@ Item {
anchors.fill: parent
layer.enabled: true
property bool widthFit: (root.width / root.aspectRatio) <= root.height
// Window width
property real wW: widthFit ? root.width : root.height * root.aspectRatio
@@ -310,31 +312,22 @@ Item {
property real wH: widthFit ? root.width / root.aspectRatio : root.height
onPaint: {
const wSize = Qt.size(wW, wH)
const contentSize = canvasSize
const clearSize = Qt.size(Math.ceil(canvasSize.width), Math.ceil(canvasSize.height))
const r = root.radius
var ctx = getContext("2d")
ctx.save()
ctx.clearRect(0, 0, clearSize.width, clearSize.height)
// TODO: observed drawing artefacts at the edge. Draw one pixel more for now until root cause is found
ctx.clearRect(0, 0, width + 1, height + 1)
// Fill all with wallColor in order to clip the window from it
ctx.fillStyle = Qt.rgba(root.wallColor.r, root.wallColor.g, root.wallColor.b, root.wallTransparency)
ctx.fillRect(0, 0, clearSize.width, clearSize.height)
ctx.fillRect(0, 0, width + 1, height + 1)
// Cut opaque new pixels from background
ctx.globalCompositeOperation = "source-out"
// Draw the window
ctx.beginPath()
const cW = Qt.rect((contentSize.width - wSize.width)/2, (contentSize.height - wSize.height)/2, wSize.width, wSize.height)
const cW = Qt.rect((width - wW)/2, (height - wH)/2, wW, wH)
if(root.windowStyle === StatusImageCrop.WindowStyle.Rounded)
ctx.ellipse(cW.x, cW.y, cW.width, cW.height)
else if(root.windowStyle === StatusImageCrop.WindowStyle.Rectangular)
ctx.roundedRect(cW.x, cW.y, cW.width, cW.height, r, r)
ctx.roundedRect(cW.x, cW.y, cW.width, cW.height, root.radius, root.radius)
ctx.fill()
ctx.restore()
}
+15 -38
View File
@@ -48,7 +48,6 @@ 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.
@@ -95,11 +94,6 @@ Item {
\qmlproperty string StatusInput::label
This property sets the label text.
*/
property int labelPadding: 8
/*!
\qmlproperty string StatusInput::label
This property sets the label text.
*/
property string label: ""
/*!
\qmlproperty string StatusInput::secondaryLabel
@@ -138,14 +132,14 @@ Item {
property alias bottomPadding: statusBaseInput.bottomPadding
/*!
\qmlproperty real StatusInput::minimumHeight
This property sets the minimum height. Default value is 44px.
This property sets the minimum height.
*/
property real minimumHeight: 44
property real minimumHeight: 0
/*!
\qmlproperty alias StatusInput::maximumHeight
This property sets the maximum height. Default value is 44px.
This property sets the maximum height.
*/
property real maximumHeight: 44
property real maximumHeight: 0
/*!
\qmlproperty list StatusBaseInput::validators
This property sets the list of validators to be considered.
@@ -244,7 +238,7 @@ Item {
This function resets the text input validation and text.
*/
function reset() {
statusBaseInput.valid = false
statusBaseInput.valid = true
statusBaseInput.pristine = true
statusBaseInput.text = ""
root.errorMessage = ""
@@ -255,8 +249,9 @@ Item {
\qmlmethod
This function validates the text input's text.
*/
function validate(force) {
if (!force && !statusBaseInput.dirty && validationMode === StatusInput.ValidationMode.OnlyWhenDirty) {
function validate() {
if (!statusBaseInput.dirty && validationMode === StatusInput.ValidationMode.OnlyWhenDirty) {
return
}
statusBaseInput.valid = true
@@ -277,12 +272,8 @@ Item {
valid: result
}
}
errors[validator.name] = result
// the only way to trigger bindings for var property
errors = errors
result.errorMessage = validator.errorMessage
errors[validator.name] = result
statusBaseInput.valid = statusBaseInput.valid && false
}
}
@@ -357,7 +348,7 @@ Item {
}
implicitWidth: 448
implicitHeight: inputLayout.implicitHeight
implicitHeight: (internal.inputHeight + topRow.height + errorMessage.height + (2*inputLayout.spacing))
Component.onCompleted: {
validate()
@@ -366,13 +357,11 @@ Item {
ColumnLayout {
id: inputLayout
anchors.fill: parent
spacing: 0
spacing: ((topRow.height > 0) || (errorMessage.height > 0)) ? 8 : 0
RowLayout {
id: topRow
Layout.fillWidth: true
Layout.preferredHeight: (!!root.label || !!root.secondaryLabel || root.charLimit > 0) ? 22 : 0
Layout.preferredHeight: (!!root.label || !!root.secondaryLabel || root.charLimit > 0) ? 22 :0
StatusBaseText {
id: label
visible: !!text
@@ -412,8 +401,6 @@ Item {
id: statusBaseInput
implicitWidth: parent.width
implicitHeight: internal.inputHeight
Layout.alignment: Qt.AlignTop
Layout.topMargin: (topRow.height > 0) ? labelPadding : 0
maximumLength: root.charLimit
onTextChanged: root.validate()
Keys.forwardTo: [root]
@@ -428,22 +415,12 @@ Item {
StatusBaseText {
id: errorMessage
visible: {
if (!text)
return false;
if ((root.validationMode == StatusInput.ValidationMode.OnlyWhenDirty && statusBaseInput.dirty) ||
root.validationMode == StatusInput.ValidationMode.Always)
return !statusBaseInput.valid;
return false;
}
visible: !!text && !statusBaseInput.valid
height: visible ? contentHeight : 0
font.pixelSize: 12
color: Theme.palette.dangerColor1
Layout.alignment: Qt.AlignVCenter
wrapMode: Text.WordWrap
horizontalAlignment: Text.AlignRight
Layout.topMargin: 8
Layout.fillWidth: true
}
}
}
@@ -1,55 +0,0 @@
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
ItemDelegate {
id: root
padding: 8
spacing: 8
icon.width: 16
icon.height: 16
contentItem: RowLayout {
spacing: root.spacing
StatusIcon {
Layout.alignment: Qt.AlignVCenter
visible: !!icon
icon: root.icon.name
color: root.enabled ? root.icon.color : Theme.palette.baseColor1
width: root.icon.width
height: root.icon.height
}
StatusBaseText {
id: textItem
Layout.fillWidth: true
Layout.fillHeight: true
font: root.font
text: root.text
horizontalAlignment: Text.AlignLeft
verticalAlignment: Text.AlignVCenter
elide: Text.ElideRight
color: root.enabled ? Theme.palette.directColor1 : Theme.palette.baseColor1
}
}
background: Rectangle {
color: root.highlighted
? Theme.palette.statusPopupMenu.hoverBackgroundColor
: "transparent"
MouseArea {
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
acceptedButtons: Qt.NoButton
enabled: root.enabled
}
}
}

Some files were not shown because too many files have changed in this diff Show More