From 5eabcd27251cfe97faebf9e156a42c89a8fcaa27 Mon Sep 17 00:00:00 2001 From: emizzle Date: Wed, 23 Sep 2020 18:18:23 +1000 Subject: [PATCH] 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. --- .../MessageComponents/ChatImage.qml | 1 - .../MessageComponents/ImageMessage.qml | 1 - .../MessageComponents/NormalMessage.qml | 1 + .../ChatColumn/MessageComponents/Sticker.qml | 5 +- .../Chat/components/StickerList.qml | 13 +- ui/app/img/reload.svg | 3 + ui/shared/ImageLoader.qml | 133 ++++++++++++++++++ ui/shared/RoundedImage.qml | 13 +- 8 files changed, 146 insertions(+), 24 deletions(-) create mode 100644 ui/app/img/reload.svg create mode 100644 ui/shared/ImageLoader.qml diff --git a/ui/app/AppLayouts/Chat/ChatColumn/MessageComponents/ChatImage.qml b/ui/app/AppLayouts/Chat/ChatColumn/MessageComponents/ChatImage.qml index 0b0f1bb05e..4a5b73e16d 100644 --- a/ui/app/AppLayouts/Chat/ChatColumn/MessageComponents/ChatImage.qml +++ b/ui/app/AppLayouts/Chat/ChatColumn/MessageComponents/ChatImage.qml @@ -1,5 +1,4 @@ import QtQuick 2.3 -import "../../../../../shared" import "../../../../../imports" Rectangle { diff --git a/ui/app/AppLayouts/Chat/ChatColumn/MessageComponents/ImageMessage.qml b/ui/app/AppLayouts/Chat/ChatColumn/MessageComponents/ImageMessage.qml index f230fb35b8..d63799c427 100644 --- a/ui/app/AppLayouts/Chat/ChatColumn/MessageComponents/ImageMessage.qml +++ b/ui/app/AppLayouts/Chat/ChatColumn/MessageComponents/ImageMessage.qml @@ -1,5 +1,4 @@ import QtQuick 2.3 -import "../../../../../shared" import "../../../../../imports" Rectangle { diff --git a/ui/app/AppLayouts/Chat/ChatColumn/MessageComponents/NormalMessage.qml b/ui/app/AppLayouts/Chat/ChatColumn/MessageComponents/NormalMessage.qml index 1c9ea83312..e9eece9010 100644 --- a/ui/app/AppLayouts/Chat/ChatColumn/MessageComponents/NormalMessage.qml +++ b/ui/app/AppLayouts/Chat/ChatColumn/MessageComponents/NormalMessage.qml @@ -144,6 +144,7 @@ Item { anchors.leftMargin: chatBox.chatHorizontalPadding anchors.top: parent.top anchors.topMargin: chatBox.chatVerticalPadding + color: Style.current.transparent } MessageMouseArea { diff --git a/ui/app/AppLayouts/Chat/ChatColumn/MessageComponents/Sticker.qml b/ui/app/AppLayouts/Chat/ChatColumn/MessageComponents/Sticker.qml index ed9c3073dc..ca9d04ad8d 100644 --- a/ui/app/AppLayouts/Chat/ChatColumn/MessageComponents/Sticker.qml +++ b/ui/app/AppLayouts/Chat/ChatColumn/MessageComponents/Sticker.qml @@ -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) : "" } diff --git a/ui/app/AppLayouts/Chat/components/StickerList.qml b/ui/app/AppLayouts/Chat/components/StickerList.qml index 58d93fe667..7eb7386451 100644 --- a/ui/app/AppLayouts/Chat/components/StickerList.qml +++ b/ui/app/AppLayouts/Chat/components/StickerList.qml @@ -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) } } } diff --git a/ui/app/img/reload.svg b/ui/app/img/reload.svg new file mode 100644 index 0000000000..f0a4c4717c --- /dev/null +++ b/ui/app/img/reload.svg @@ -0,0 +1,3 @@ + + + diff --git a/ui/shared/ImageLoader.qml b/ui/shared/ImageLoader.qml new file mode 100644 index 0000000000..eb394eb0cb --- /dev/null +++ b/ui/shared/ImageLoader.qml @@ -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() + } + } + } +} diff --git a/ui/shared/RoundedImage.qml b/ui/shared/RoundedImage.qml index 453a009fc8..4831c6f8a8 100644 --- a/ui/shared/RoundedImage.qml +++ b/ui/shared/RoundedImage.qml @@ -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() } } \ No newline at end of file