feat(@desktop/wallet): Implement loading animation
This commit is contained in:
parent
5e2fa14cd6
commit
5df7416fd9
Binary file not shown.
After Width: | Height: | Size: 61 KiB |
|
@ -0,0 +1,68 @@
|
|||
import QtQuick 2.14
|
||||
|
||||
import StatusQ.Controls 0.1
|
||||
import StatusQ.Components 0.1
|
||||
|
||||
Column {
|
||||
spacing: 10
|
||||
|
||||
StatusCheckBox {
|
||||
id: loadingButton
|
||||
text: checked ? "loaded": "loading"
|
||||
checkState: Qt.Unchecked
|
||||
}
|
||||
|
||||
StatusTextWithLoadingState {
|
||||
font.pixelSize: 15
|
||||
text: "Text is big"
|
||||
loading: loadingButton.checked
|
||||
width: 100
|
||||
}
|
||||
|
||||
StatusTextWithLoadingState {
|
||||
font.pixelSize: 22
|
||||
text: "Text is big"
|
||||
loading: loadingButton.checked
|
||||
width: 200
|
||||
}
|
||||
|
||||
StatusListItem {
|
||||
title: "Nokia 3310"
|
||||
subTitle: "Incoming device"
|
||||
asset.width: 40
|
||||
asset.height: 40
|
||||
asset.emoji: "😁"
|
||||
asset.color: "hotpink"
|
||||
asset.letterSize: 14
|
||||
asset.isLetterIdenticon: true
|
||||
statusListItemSubTitle.loading: loadingButton.checked
|
||||
}
|
||||
|
||||
StatusListItem {
|
||||
title: "Nokia 3310"
|
||||
subTitle: "Incoming device"
|
||||
asset.width: 40
|
||||
asset.height: 40
|
||||
asset.emoji: "😁"
|
||||
asset.color: "hotpink"
|
||||
asset.letterSize: 14
|
||||
asset.isLetterIdenticon: true
|
||||
statusListItemSubTitle.loading: loadingButton.checked
|
||||
statusListItemIcon.loading: loadingButton.checked
|
||||
}
|
||||
|
||||
StatusListItem {
|
||||
title: "Nokia 3310"
|
||||
subTitle: "Incoming device"
|
||||
asset.width: 40
|
||||
asset.height: 40
|
||||
asset.emoji: "😁"
|
||||
asset.color: "hotpink"
|
||||
asset.letterSize: 14
|
||||
asset.isLetterIdenticon: true
|
||||
statusListItemTitle.loading: loadingButton.checked
|
||||
statusListItemSubTitle.loading: loadingButton.checked
|
||||
statusListItemIcon.loading: loadingButton.checked
|
||||
}
|
||||
|
||||
}
|
|
@ -357,6 +357,11 @@ StatusWindow {
|
|||
selected: viewLoader.source.toString().includes(title)
|
||||
onClicked: mainPageView.page(title);
|
||||
}
|
||||
StatusNavigationListItem {
|
||||
title: "LoadingStates"
|
||||
selected: viewLoader.source.toString().includes(title)
|
||||
onClicked: mainPageView.control(title);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,30 +0,0 @@
|
|||
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
|
||||
}
|
||||
}
|
|
@ -1,24 +0,0 @@
|
|||
import QtQuick 2.14
|
||||
import QtGraphicalEffects 1.14
|
||||
|
||||
/*
|
||||
TODO: This component should be implemented as inline component of `SkeletonAnimation.qml`
|
||||
when we use Qt > 5.15
|
||||
*/
|
||||
|
||||
GradientStop {
|
||||
id: root
|
||||
|
||||
property real from: 0
|
||||
|
||||
color: "transparent"
|
||||
|
||||
NumberAnimation on position {
|
||||
easing.type: Easing.Linear
|
||||
loops: Animation.Infinite
|
||||
running: visible
|
||||
from: root.from
|
||||
to: from + 4
|
||||
duration: 2000
|
||||
}
|
||||
}
|
|
@ -1,4 +0,0 @@
|
|||
module StatusQ.Animations
|
||||
|
||||
SkeletonAnimation 0.1 SkeletonAnimation.qml
|
||||
SkeletonGradientStop 0.1 SkeletonGradientStop.qml
|
|
@ -0,0 +1,89 @@
|
|||
import QtQuick 2.13
|
||||
import QtQuick.Controls 2.12
|
||||
|
||||
import StatusQ.Core.Theme 0.1
|
||||
import QtGraphicalEffects 1.12
|
||||
|
||||
/*!
|
||||
\qmltype LoadingComponent
|
||||
\inherits Control
|
||||
\inqmlmodule StatusQ.Components
|
||||
\since StatusQ.Components 0.1
|
||||
\brief A componet that can be used to adding a loading state to a widget
|
||||
Example:
|
||||
|
||||
\qml
|
||||
StatusBaseText {
|
||||
id: root
|
||||
LoadingComponent {
|
||||
anchors.fill: parent
|
||||
radius: 8
|
||||
}
|
||||
}
|
||||
\endqml
|
||||
|
||||
For a list of components available see StatusQ.
|
||||
*/
|
||||
|
||||
Control {
|
||||
id: root
|
||||
|
||||
/*!
|
||||
\qmlproperty bool LoadingComponent::radius
|
||||
This property lets user set custom radius
|
||||
*/
|
||||
property int radius: 4
|
||||
|
||||
background: null
|
||||
|
||||
contentItem: Item {
|
||||
property real contentItemWidth: 0
|
||||
onWidthChanged: {
|
||||
contentItemWidth = width
|
||||
animation.restart()
|
||||
}
|
||||
Rectangle {
|
||||
id: rect
|
||||
anchors.fill: parent
|
||||
color: Theme.palette.statusLoadingHighlight
|
||||
radius: root.radius
|
||||
visible: false
|
||||
LinearGradient {
|
||||
id: gradient
|
||||
width: 100
|
||||
height: 2*parent.height
|
||||
x: -width
|
||||
y: -height/4
|
||||
start: Qt.point(0, height)
|
||||
end: Qt.point(width, height)
|
||||
gradient: Gradient {
|
||||
GradientStop { position: 0.2; color: "transparent"}
|
||||
GradientStop { position: 0.5; color: Theme.palette.statusLoadingHighlight2 }
|
||||
GradientStop { position: 0.8; color: "transparent"}
|
||||
}
|
||||
rotation: 20
|
||||
NumberAnimation on x {
|
||||
id: animation
|
||||
easing.type: Easing.Linear
|
||||
loops: Animation.Infinite
|
||||
running: root.visible
|
||||
from: -gradient.width
|
||||
to: contentItem.contentItemWidth + gradient.width
|
||||
duration: 800
|
||||
easing.period: 2
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
OpacityMask {
|
||||
anchors.fill: rect
|
||||
source: rect
|
||||
maskSource: Rectangle {
|
||||
width: root.width
|
||||
height: root.height
|
||||
radius: root.radius
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -5,7 +5,6 @@ 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"
|
||||
|
@ -139,7 +138,6 @@ Rectangle {
|
|||
anchors.left: parent.left
|
||||
anchors.leftMargin: statusListItem.leftPadding
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
visible: !iconOrImageLoadingOverlay.visible
|
||||
asset: statusListItem.asset
|
||||
name: statusListItem.title
|
||||
active: statusListItem.asset.isLetterIdenticon ||
|
||||
|
@ -147,20 +145,7 @@ Rectangle {
|
|||
!!statusListItem.asset.emoji
|
||||
badge.border.color: statusListItem.color
|
||||
ringSettings: statusListItem.ringSettings
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: iconOrImageLoadingOverlay
|
||||
visible: statusListItem.loading || statusListItem.loadingFailed
|
||||
anchors.fill: iconOrImage
|
||||
radius: width / 2
|
||||
color: statusListItem.loadingFailed ? Theme.palette.dangerColor2 : Theme.palette.baseColor1
|
||||
|
||||
SkeletonAnimation {
|
||||
anchors.fill: parent
|
||||
mask: parent
|
||||
visible: statusListItem.loading && !statusListItem.loadingFailed
|
||||
}
|
||||
loading: statusListItem.loading
|
||||
}
|
||||
|
||||
Item {
|
||||
|
@ -182,29 +167,8 @@ 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 {
|
||||
StatusTextWithLoadingState {
|
||||
id: statusListItemTitle
|
||||
opacity: titleLoadingOverlay.visible ? 0 : 1
|
||||
text: statusListItem.title
|
||||
font.pixelSize: 15
|
||||
height: visible ? contentHeight : 0
|
||||
|
@ -213,7 +177,7 @@ Rectangle {
|
|||
anchors.top: bottomModel.length === 0 ? undefined: parent.top
|
||||
anchors.topMargin: bottomModel.length === 0 ? undefined : 20
|
||||
width: Math.min(implicitWidth, parent.width)
|
||||
color: {
|
||||
customColor: {
|
||||
if (!statusListItem.enabled) {
|
||||
return Theme.palette.baseColor1
|
||||
}
|
||||
|
@ -226,6 +190,7 @@ Rectangle {
|
|||
return Theme.palette.dangerColor1
|
||||
}
|
||||
}
|
||||
loading: statusListItem.loading
|
||||
|
||||
StatusIcon {
|
||||
width: visible ? 12 : 0
|
||||
|
@ -258,7 +223,7 @@ Rectangle {
|
|||
}
|
||||
}
|
||||
|
||||
StatusBaseText {
|
||||
StatusTextWithLoadingState {
|
||||
id: statusListItemTitleAsideText
|
||||
anchors.left: statusListItemTitle.right
|
||||
anchors.leftMargin: 4
|
||||
|
@ -267,8 +232,9 @@ Rectangle {
|
|||
anchors.topMargin: bottomModel.length === 0 ? undefined : 20
|
||||
text: statusListItem.titleAsideText
|
||||
font.pixelSize: 10
|
||||
color: Theme.palette.baseColor1
|
||||
customColor: Theme.palette.baseColor1
|
||||
visible: !!statusListItem.titleAsideText
|
||||
loading: statusListItem.loading
|
||||
}
|
||||
|
||||
Loader {
|
||||
|
@ -287,7 +253,7 @@ Rectangle {
|
|||
width: parent.width
|
||||
spacing: 4
|
||||
|
||||
StatusBaseText {
|
||||
StatusTextWithLoadingState {
|
||||
id: statusListItemSubTitle
|
||||
objectName: "statusListItemSubTitle"
|
||||
|
||||
|
@ -296,26 +262,26 @@ Rectangle {
|
|||
|
||||
text: statusListItem.subTitle
|
||||
font.pixelSize: 15
|
||||
color: statusListItem.loadingFailed ? Theme.palette.dangerColor1
|
||||
: !statusListItem.enabled || !statusListItem.tertiaryTitle
|
||||
? Theme.palette.baseColor1
|
||||
: Theme.palette.directColor1
|
||||
customColor: !statusListItem.enabled || !statusListItem.tertiaryTitle ?
|
||||
Theme.palette.baseColor1 : Theme.palette.directColor1
|
||||
visible: !!statusListItem.subTitle
|
||||
wrapMode: Text.WrapAtWordBoundaryOrAnywhere
|
||||
loading: statusListItem.loading
|
||||
}
|
||||
|
||||
StatusBaseText {
|
||||
StatusTextWithLoadingState {
|
||||
id: dot
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
Layout.topMargin: -48
|
||||
|
||||
text: "."
|
||||
font.pixelSize: 40
|
||||
color: Theme.palette.baseColor1
|
||||
customColor: Theme.palette.baseColor1
|
||||
lineHeightMode: Text.FixedHeight
|
||||
lineHeight: 24
|
||||
|
||||
visible: inlineTagModelRepeater.count > 0
|
||||
loading: statusListItem.loading
|
||||
}
|
||||
|
||||
StatusScrollView {
|
||||
|
@ -340,16 +306,17 @@ Rectangle {
|
|||
}
|
||||
}
|
||||
|
||||
StatusBaseText {
|
||||
StatusTextWithLoadingState {
|
||||
id: statusListItemTertiaryTitle
|
||||
anchors.top: statusListItemSubtitleTagsRow.bottom
|
||||
width: parent.width
|
||||
height: visible ? contentHeight : 0
|
||||
text: statusListItem.tertiaryTitle
|
||||
color: Theme.palette.baseColor1
|
||||
customColor: Theme.palette.baseColor1
|
||||
font.pixelSize: 13
|
||||
visible: !!statusListItem.tertiaryTitle
|
||||
wrapMode: Text.WrapAtWordBoundaryOrAnywhere
|
||||
loading: statusListItem.loading
|
||||
}
|
||||
|
||||
StatusListItemBadge {
|
||||
|
@ -397,7 +364,7 @@ Rectangle {
|
|||
}
|
||||
}
|
||||
|
||||
StatusBaseText {
|
||||
StatusTextWithLoadingState {
|
||||
id: statusListItemLabel
|
||||
anchors.verticalCenter: bottomModel.length === 0 ? parent.verticalCenter : undefined
|
||||
anchors.top: bottomModel.length === 0 ? undefined: parent.top
|
||||
|
@ -407,8 +374,9 @@ Rectangle {
|
|||
|
||||
text: statusListItem.label
|
||||
font.pixelSize: 15
|
||||
color: Theme.palette.baseColor1
|
||||
customColor: Theme.palette.baseColor1
|
||||
visible: !!statusListItem.label
|
||||
loading: statusListItem.loading
|
||||
}
|
||||
|
||||
Row {
|
||||
|
|
|
@ -23,9 +23,11 @@ Loader {
|
|||
distinctiveColors: Theme.palette.identiconRingColors
|
||||
}
|
||||
|
||||
sourceComponent: (root.asset.isLetterIdenticon || root.asset.name === "") ? letterIdenticon :
|
||||
sourceComponent: root.loading ? loadingComp : (root.asset.isLetterIdenticon || root.asset.name === "") ? letterIdenticon :
|
||||
!root.asset.isImage ? roundedIcon : roundedImage
|
||||
|
||||
property bool loading: false
|
||||
|
||||
Component {
|
||||
id: roundedImage
|
||||
|
||||
|
@ -110,4 +112,14 @@ Loader {
|
|||
implicitWidth: 15
|
||||
z: root.dZ
|
||||
}
|
||||
|
||||
Component {
|
||||
id: loadingComp
|
||||
LoadingComponent {
|
||||
anchors.centerIn: parent
|
||||
radius: width/2
|
||||
height: root.asset.height
|
||||
width: root.asset.width
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -46,4 +46,5 @@ StatusCard 0.1 StatusCard.qml
|
|||
StatusDatePicker 0.1 StatusDatePicker.qml
|
||||
StatusChart 0.1 StatusChart.qml
|
||||
StatusChartPanel 0.1 StatusChartPanel.qml
|
||||
StatusStepper 0.1 StatusStepper.qml
|
||||
StatusStepper 0.1 StatusStepper.qml
|
||||
LoadingComponent 0.1 LoadingComponent.qml
|
||||
|
|
|
@ -0,0 +1,63 @@
|
|||
import QtQuick 2.13
|
||||
|
||||
import StatusQ.Core 0.1
|
||||
import StatusQ.Core.Theme 0.1
|
||||
import StatusQ.Components 0.1
|
||||
|
||||
/*!
|
||||
\qmltype StatusTextWithLoadingState
|
||||
\inherits StatusBaseText
|
||||
\inqmlmodule StatusQ.Controls
|
||||
\since StatusQ.Controls 0.1
|
||||
\brief A text control with support for loading state
|
||||
|
||||
Example:
|
||||
|
||||
\qml
|
||||
StatusTextWithLoadingState {
|
||||
title: "Account %1 of %2".arg(completedSteps).arg(totalSteps)
|
||||
loading: isLoading
|
||||
customColor: Theme.palette.directColor1
|
||||
}
|
||||
\endqml
|
||||
|
||||
\image statusLoadingText.png
|
||||
|
||||
For a list of components available see StatusQ.
|
||||
*/
|
||||
|
||||
StatusBaseText {
|
||||
id: root
|
||||
|
||||
/*!
|
||||
\qmlproperty bool StatusTextWithLoadingState::loading
|
||||
This property sets if the text is loading.
|
||||
*/
|
||||
property bool loading: false
|
||||
/*!
|
||||
\qmlproperty bool StatusTextWithLoadingState::customColor
|
||||
This property sets the user defined color for the text and handles
|
||||
transparency in loading state.
|
||||
*/
|
||||
property color customColor: Theme.palette.directColor1
|
||||
|
||||
color: loading ? "transparent" : customColor
|
||||
|
||||
Loader {
|
||||
anchors.left: parent.left
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
active: root.loading
|
||||
sourceComponent: LoadingComponent {
|
||||
anchors.centerIn: parent
|
||||
radius: textMetrics.font.pixelSize === 15 ? 4 : 8
|
||||
height: textMetrics.tightBoundingRect.height
|
||||
width: Math.min(root.width, 140)
|
||||
}
|
||||
}
|
||||
|
||||
TextMetrics {
|
||||
id: textMetrics
|
||||
font: root.font
|
||||
text: root.text
|
||||
}
|
||||
}
|
|
@ -53,3 +53,4 @@ StatusItemDelegate 0.1 StatusItemDelegate.qml
|
|||
StatusTextArea 0.1 StatusTextArea.qml
|
||||
StatusBackButton 0.1 StatusBackButton.qml
|
||||
StatusPasswordInput 0.1 StatusPasswordInput.qml
|
||||
StatusTextWithLoadingState 0.1 StatusTextWithLoadingState.qml
|
||||
|
|
|
@ -64,7 +64,9 @@ QtObject {
|
|||
'yellow': '#FFCA0F',
|
||||
'yellow2': '#EAD27B',
|
||||
|
||||
'blueHijab': '#CDF2FB'
|
||||
'blueHijab': '#CDF2FB',
|
||||
|
||||
'lightPattensBlue': '#D7DEE4',
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -62,6 +62,9 @@ ThemePalette {
|
|||
|
||||
statusFloatingButtonHighlight: getColor('blue4', 0.3)
|
||||
|
||||
statusLoadingHighlight: getColor('white', 0.03)
|
||||
statusLoadingHighlight2: getColor('white', 0.07)
|
||||
|
||||
userCustomizationColors: [
|
||||
"#AAC6FF",
|
||||
"#887AF9",
|
||||
|
|
|
@ -60,6 +60,9 @@ ThemePalette {
|
|||
|
||||
statusFloatingButtonHighlight: getColor('blueHijab')
|
||||
|
||||
statusLoadingHighlight: getColor('lightPattensBlue', 0.5)
|
||||
statusLoadingHighlight2: indirectColor3
|
||||
|
||||
userCustomizationColors: [
|
||||
"#2946C4",
|
||||
"#887AF9",
|
||||
|
|
|
@ -166,6 +166,9 @@ QtObject {
|
|||
|
||||
property color statusFloatingButtonHighlight
|
||||
|
||||
property color statusLoadingHighlight
|
||||
property color statusLoadingHighlight2
|
||||
|
||||
property var userCustomizationColors: []
|
||||
|
||||
property var identiconRingColors: []
|
||||
|
|
Loading…
Reference in New Issue