From acb56141fae171267357d3835395d348d361feef Mon Sep 17 00:00:00 2001 From: Igor Sirotin Date: Wed, 22 Jun 2022 10:40:17 +0300 Subject: [PATCH] feat(StatusListItem): Added `loading` and `loadingFailed` properties (#736) --- ui/StatusQ/sandbox/controls/ListItems.qml | 29 ++++++++++++ .../StatusQ/Animations/SkeletonAnimation.qml | 30 ++++++++++++ .../Animations/SkeletonGradientStop.qml | 23 +++++++++ ui/StatusQ/src/StatusQ/Animations/qmldir | 4 ++ .../src/StatusQ/Components/StatusListItem.qml | 47 ++++++++++++++++++- ui/StatusQ/statusq.qrc | 3 ++ 6 files changed, 135 insertions(+), 1 deletion(-) create mode 100644 ui/StatusQ/src/StatusQ/Animations/SkeletonAnimation.qml create mode 100644 ui/StatusQ/src/StatusQ/Animations/SkeletonGradientStop.qml create mode 100644 ui/StatusQ/src/StatusQ/Animations/qmldir diff --git a/ui/StatusQ/sandbox/controls/ListItems.qml b/ui/StatusQ/sandbox/controls/ListItems.qml index 0cbd609ba3..215ef0dd26 100644 --- a/ui/StatusQ/sandbox/controls/ListItems.qml +++ b/ui/StatusQ/sandbox/controls/ListItems.qml @@ -445,4 +445,33 @@ CExPynn1gWf9bx498P7/nzPcxEzGExhBdJGYihtAYQlO+tUZvqrPbqeudo5iJGEJjCE15a3VtodH3q2I isAdmin: true isUntrustworthy: true } + + StatusBaseText { + Layout.fillWidth: true + Layout.topMargin: 16 + text: "Loading features:" + font.pixelSize: 17 + } + + StatusListItem { + title: "Nokia 3310" + subTitle: "Incoming device" + label: "loading: true" + icon.emoji: "😁" + icon.color: "hotpink" + icon.letterSize: 14 + icon.isLetterIdenticon: true + loading: true + } + + StatusListItem { + title: "Nokia 3310" + subTitle: "Device" + label: "loadingFailed: true" + icon.emoji: "😁" + icon.color: "hotpink" + icon.letterSize: 14 + icon.isLetterIdenticon: true + loadingFailed: true + } } diff --git a/ui/StatusQ/src/StatusQ/Animations/SkeletonAnimation.qml b/ui/StatusQ/src/StatusQ/Animations/SkeletonAnimation.qml new file mode 100644 index 0000000000..f8c2264a98 --- /dev/null +++ b/ui/StatusQ/src/StatusQ/Animations/SkeletonAnimation.qml @@ -0,0 +1,30 @@ +import QtQuick 2.14 +import QtGraphicalEffects 1.14 + +Item { + id: root + + property Item mask + property color color: "#F6F8FA" + + Rectangle { + id: gradient + anchors.fill: parent + visible: false + + gradient: Gradient { + orientation: Gradient.Horizontal + SkeletonGradientStop { color: "transparent"; from: -3; } + SkeletonGradientStop { color: "transparent"; from: -2; } + SkeletonGradientStop { color: root.color; from: -1 ; } + SkeletonGradientStop { color: "transparent"; from: 0; } + SkeletonGradientStop { color: "transparent"; from: 1; } + } + } + + OpacityMask { + anchors.fill: parent + source: gradient + maskSource: root.mask + } +} diff --git a/ui/StatusQ/src/StatusQ/Animations/SkeletonGradientStop.qml b/ui/StatusQ/src/StatusQ/Animations/SkeletonGradientStop.qml new file mode 100644 index 0000000000..a9119931f3 --- /dev/null +++ b/ui/StatusQ/src/StatusQ/Animations/SkeletonGradientStop.qml @@ -0,0 +1,23 @@ +import QtQuick 2.14 +import QtGraphicalEffects 1.14 + +/* + TODO: This component should be implemented as inline component of `SkeletonAnimation.qml` + when we use Qt > 5.15 +*/ + +GradientStop { + id: root + + property real from: 0 + + color: "transparent" + + NumberAnimation on position { + easing.type: Easing.Linear + loops: Animation.Infinite + from: root.from + to: from + 4 + duration: 2000 + } +} diff --git a/ui/StatusQ/src/StatusQ/Animations/qmldir b/ui/StatusQ/src/StatusQ/Animations/qmldir new file mode 100644 index 0000000000..e31b677241 --- /dev/null +++ b/ui/StatusQ/src/StatusQ/Animations/qmldir @@ -0,0 +1,4 @@ +module StatusQ.Animations + +SkeletonAnimation 0.1 SkeletonAnimation.qml +SkeletonGradientStop 0.1 SkeletonGradientStop.qml diff --git a/ui/StatusQ/src/StatusQ/Components/StatusListItem.qml b/ui/StatusQ/src/StatusQ/Components/StatusListItem.qml index 7cb333a900..99e2ddd017 100644 --- a/ui/StatusQ/src/StatusQ/Components/StatusListItem.qml +++ b/ui/StatusQ/src/StatusQ/Components/StatusListItem.qml @@ -5,6 +5,10 @@ import StatusQ.Core 0.1 import StatusQ.Core.Theme 0.1 import StatusQ.Components 0.1 import StatusQ.Controls 0.1 +import StatusQ.Animations 0.1 +import QtGraphicalEffects 1.14 + +import "private" Rectangle { id: statusListItem @@ -27,6 +31,8 @@ Rectangle { property Component bottomDelegate property var tagsModel: [] property Component tagsDelegate + property bool loading: false + property bool loadingFailed: false property StatusIconSettings icon: StatusIconSettings { height: isLetterIdenticon ? 40 : 20 @@ -134,6 +140,7 @@ Rectangle { anchors.leftMargin: statusListItem.leftPadding anchors.top: parent.top anchors.topMargin: 12 + visible: !iconOrImageLoadingOverlay.visible image: statusListItem.image icon: statusListItem.icon name: statusListItem.title @@ -145,6 +152,20 @@ Rectangle { ringSettings: statusListItem.ringSettings } + Rectangle { + id: iconOrImageLoadingOverlay + visible: statusListItem.loading || statusListItem.loadingFailed + anchors.fill: iconOrImage + radius: width / 2 + color: statusListItem.loadingFailed ? Theme.palette.dangerColor2 : Theme.palette.baseColor1 + + SkeletonAnimation { + anchors.fill: parent + mask: parent + visible: statusListItem.loading && !statusListItem.loadingFailed + } + } + Item { id: statusListItemTitleArea @@ -164,8 +185,29 @@ Rectangle { height: childrenRect.height + Rectangle { + id: titleLoadingOverlay + visible: statusListItem.loading || statusListItem.loadingFailed + anchors { + left: statusListItemTitle.left + top: statusListItemTitle.top + bottom: statusListItemTitle.bottom + } + + width: Math.max(95, statusListItemTitle.width) + radius: 4 + color: statusListItem.loadingFailed ? Theme.palette.dangerColor2 : Theme.palette.baseColor1 + + SkeletonAnimation { + anchors.fill: parent + mask: parent + visible: statusListItem.loading && !statusListItem.loadingFailed + } + } + StatusBaseText { id: statusListItemTitle + opacity: titleLoadingOverlay.visible ? 0 : 1 text: statusListItem.title font.pixelSize: 15 height: visible ? contentHeight : 0 @@ -235,7 +277,10 @@ Rectangle { width: parent.width text: statusListItem.subTitle font.pixelSize: 15 - color: !statusListItem.enabled || !statusListItem.tertiaryTitle ? Theme.palette.baseColor1 : Theme.palette.directColor1 + color: statusListItem.loadingFailed ? Theme.palette.dangerColor1 + : !statusListItem.enabled || !statusListItem.tertiaryTitle + ? Theme.palette.baseColor1 + : Theme.palette.directColor1 height: visible ? contentHeight : 0 visible: !!statusListItem.subTitle wrapMode: Text.WrapAtWordBoundaryOrAnywhere diff --git a/ui/StatusQ/statusq.qrc b/ui/StatusQ/statusq.qrc index ce1e48cc92..9a76dede20 100644 --- a/ui/StatusQ/statusq.qrc +++ b/ui/StatusQ/statusq.qrc @@ -10502,5 +10502,8 @@ src/assets/twemoji/LICENSE src/StatusQ/Controls/StatusTabBar.qml src/StatusQ/Controls/StatusTagItem.qml + src/StatusQ/Animations/SkeletonAnimation.qml + src/StatusQ/Animations/SkeletonGradientStop.qml + src/StatusQ/Animations/qmldir