feat: Add loading and reload states to stickers/packs

Related to: #586.

Adds a loading state to stickers, so that a loading indicator appears while the sticker is being downloaded from IPFS.

In the case of a network failure or timetout, a reload button is shown instead. Once network is restored and the reload button is clicked, the image is reloaded from the network, going through the same lifecycle of showing the loading state first.
This commit is contained in:
emizzle 2020-09-23 18:18:23 +10:00 committed by Iuri Matias
parent 1fc0e26a0f
commit 5eabcd2725
8 changed files with 146 additions and 24 deletions

View File

@ -1,5 +1,4 @@
import QtQuick 2.3
import "../../../../../shared"
import "../../../../../imports"
Rectangle {

View File

@ -1,5 +1,4 @@
import QtQuick 2.3
import "../../../../../shared"
import "../../../../../imports"
Rectangle {

View File

@ -144,6 +144,7 @@ Item {
anchors.leftMargin: chatBox.chatHorizontalPadding
anchors.top: parent.top
anchors.topMargin: chatBox.chatVerticalPadding
color: Style.current.transparent
}
MessageMouseArea {

View File

@ -1,12 +1,11 @@
import QtQuick 2.3
import "../../../../../shared" as Shared
import "../../../../../imports"
Image {
Shared.ImageLoader {
id: stickerId
visible: contentType === Constants.stickerType
width: 140
height: this.visible ? 140 : 0
sourceSize.width: width
sourceSize.height: height
source: this.visible ? ("https://ipfs.infura.io/ipfs/" + sticker) : ""
}

View File

@ -22,19 +22,12 @@ GridView {
anchors.fill: parent
anchors.topMargin: 4
anchors.leftMargin: 4
Image {
ImageLoader {
width: 80
height: 80
sourceSize.width: width
sourceSize.height: height
fillMode: Image.PreserveAspectFit
source: "https://ipfs.infura.io/ipfs/" + url
MouseArea {
cursorShape: Qt.PointingHandCursor
anchors.fill: parent
onClicked: {
root.stickerClicked(hash, packId)
}
onClicked: {
root.stickerClicked(hash, packId)
}
}
}

3
ui/app/img/reload.svg Normal file
View File

@ -0,0 +1,3 @@
<svg width="16" height="20" viewBox="0 0 16 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M8 4.25C12.2802 4.25 15.75 7.71979 15.75 12C15.75 16.2802 12.2802 19.75 8 19.75C3.71979 19.75 0.25 16.2802 0.25 12C0.25 11.5858 0.585787 11.25 1 11.25C1.41421 11.25 1.75 11.5858 1.75 12C1.75 15.4518 4.54822 18.25 8 18.25C11.4518 18.25 14.25 15.4518 14.25 12C14.25 8.54822 11.4518 5.75 8 5.75H7.01777C6.57232 5.75 6.34923 6.28857 6.66421 6.60355L8.53033 8.46967C8.82322 8.76256 8.82322 9.23744 8.53033 9.53033C8.23744 9.82322 7.76256 9.82322 7.46967 9.53033L3.46967 5.53033C3.17678 5.23744 3.17678 4.76256 3.46967 4.46967L7.46967 0.469669C7.76256 0.176777 8.23744 0.176777 8.53033 0.469669C8.82322 0.762564 8.82322 1.23744 8.53033 1.53033L6.66421 3.39645C6.34923 3.71143 6.57232 4.25 7.01777 4.25H8Z" fill="black"/>
</svg>

After

Width:  |  Height:  |  Size: 827 B

133
ui/shared/ImageLoader.qml Normal file
View File

@ -0,0 +1,133 @@
import QtQuick 2.3
import QtGraphicalEffects 1.13
import "../imports"
Rectangle {
id: root
property url source
signal clicked
color: Style.current.backgroundHover
state: "loading"
radius: width / 2
states: [
State {
name: "loading"
when: image.status === Image.Loading
PropertyChanges {
target: loading
visible: true
}
PropertyChanges {
target: reload
visible: false
}
PropertyChanges {
target: image
visible: false
}
},
State {
name: "error"
when: image.status === Image.Error
PropertyChanges {
target: loading
visible: false
}
PropertyChanges {
target: reload
visible: true
}
PropertyChanges {
target: image
visible: false
}
},
State {
name: "ready"
when: image.status === Image.Ready
PropertyChanges {
target: root
color: Style.current.transparent
}
PropertyChanges {
target: loading
visible: false
}
PropertyChanges {
target: reload
visible: false
}
PropertyChanges {
target: image
visible: true
height: root.height
width: root.width
}
}
]
function reload() {
// From the documentation (https://doc.qt.io/qt-5/qml-qtquick-image.html#sourceSize-prop)
// Note: Changing this property dynamically causes the image source to
// be reloaded, potentially even from the network, if it is not in the
// disk cache.
image.sourceSize.width += 1
image.sourceSize.width -= 1
}
LoadingImage {
id: loading
width: 23
height: 23
anchors.verticalCenter: parent.verticalCenter
anchors.horizontalCenter: parent.horizontalCenter
ColorOverlay {
anchors.fill: parent
source: parent
color: Style.current.secondaryText
antialiasing: true
}
}
SVGImage {
id: reload
source: "../app/img/reload.svg"
width: 15.5
height: 19.5
fillMode: Image.PreserveAspectFit
anchors.verticalCenter: parent.verticalCenter
anchors.horizontalCenter: parent.horizontalCenter
ColorOverlay {
anchors.fill: parent
source: parent
color: Style.current.textColor
antialiasing: true
}
MouseArea {
cursorShape: Qt.PointingHandCursor
anchors.fill: parent
onClicked: {
root.reload()
}
}
}
Image {
id: image
width: 0
height: 0
sourceSize.width: root.width * 2
sourceSize.height: root.height * 2
source: root.source
horizontalAlignment: Image.AlignHCenter
verticalAlignment: Image.AlignVCenter
cache: true
MouseArea {
cursorShape: Qt.PointingHandCursor
anchors.fill: parent
onClicked: {
root.clicked()
}
}
}
}

View File

@ -2,7 +2,7 @@ import QtQuick 2.12
import QtGraphicalEffects 1.0
Rectangle {
id: root;
id: root
signal clicked
property alias source: imgStickerPackThumb.source
@ -22,18 +22,13 @@ Rectangle {
}
}
Image {
ImageLoader {
id: imgStickerPackThumb
opacity: 1
smooth: false
radius: root.radius
anchors.fill: parent
source: "https://ipfs.infura.io/ipfs/" + thumbnail
sourceSize.width: width
sourceSize.height: height
MouseArea {
cursorShape: Qt.PointingHandCursor
anchors.fill: parent
onClicked: root.clicked()
}
onClicked: root.clicked()
}
}