diff --git a/resources/qml/MessageView.qml b/resources/qml/MessageView.qml
index c936c638..16c92ebf 100644
--- a/resources/qml/MessageView.qml
+++ b/resources/qml/MessageView.qml
@@ -4,6 +4,8 @@
import "./delegates"
import "./emoji"
+import "./ui"
+
import Qt.labs.platform 1.1 as Platform
import QtGraphicalEffects 1.0
import QtQuick 2.12
@@ -404,14 +406,13 @@ ScrollView {
}
- footer: BusyIndicator {
+ footer: Spinner {
anchors.horizontalCenter: parent.horizontalCenter
running: chat.model && chat.model.paginationInProgress
- height: 50
- width: 50
+ foreground: Nheko.colors.mid
+ visible: chat.model && chat.model.paginationInProgress
z: 3
}
-
}
Platform.Menu {
diff --git a/resources/qml/RoomSettings.qml b/resources/qml/RoomSettings.qml
index 1f7fe5de..d6e6c6a5 100644
--- a/resources/qml/RoomSettings.qml
+++ b/resources/qml/RoomSettings.qml
@@ -2,6 +2,7 @@
//
// SPDX-License-Identifier: GPL-3.0-or-later
+import "./ui"
import Qt.labs.platform 1.1 as Platform
import QtQuick 2.9
import QtQuick.Controls 2.3
@@ -49,10 +50,11 @@ ApplicationWindow {
}
}
- BusyIndicator {
+ Spinner {
Layout.alignment: Qt.AlignHCenter
- running: roomSettings.isLoading
visible: roomSettings.isLoading
+ foreground: Nheko.colors.mid
+ running: roomSettings.isLoading
}
Text {
diff --git a/resources/qml/TimelineView.qml b/resources/qml/TimelineView.qml
index 2c7c943a..0209054d 100644
--- a/resources/qml/TimelineView.qml
+++ b/resources/qml/TimelineView.qml
@@ -6,6 +6,8 @@ import "./delegates"
import "./device-verification"
import "./emoji"
import "./voip"
+import "./ui"
+
import Qt.labs.platform 1.1 as Platform
import QtGraphicalEffects 1.0
import QtQuick 2.9
@@ -29,12 +31,13 @@ Item {
color: Nheko.colors.text
}
- BusyIndicator {
- visible: running
+ Spinner {
+ visible: TimelineManager.isInitialSync
anchors.centerIn: parent
+ foreground: Nheko.colors.mid
running: TimelineManager.isInitialSync
- height: 200
- width: 200
+ // height is somewhat arbitrary here... don't set width because width scales w/ height
+ height: parent.height / 16
z: 3
}
diff --git a/resources/qml/UserProfile.qml b/resources/qml/UserProfile.qml
index 21f34f15..826d3165 100644
--- a/resources/qml/UserProfile.qml
+++ b/resources/qml/UserProfile.qml
@@ -3,6 +3,7 @@
// SPDX-License-Identifier: GPL-3.0-or-later
import "./device-verification"
+import "./ui"
import QtQuick 2.9
import QtQuick.Controls 2.3
import QtQuick.Layouts 1.2
@@ -47,10 +48,11 @@ ApplicationWindow {
onClicked: profile.isSelf ? profile.changeAvatar() : TimelineManager.openImageOverlay(profile.avatarUrl, "")
}
- BusyIndicator {
+ Spinner {
Layout.alignment: Qt.AlignHCenter
running: profile.isLoading
visible: profile.isLoading
+ foreground: Nheko.colors.mid
}
Text {
diff --git a/resources/qml/device-verification/AwaitingVerificationConfirmation.qml b/resources/qml/device-verification/AwaitingVerificationConfirmation.qml
index a6a7f027..91306140 100644
--- a/resources/qml/device-verification/AwaitingVerificationConfirmation.qml
+++ b/resources/qml/device-verification/AwaitingVerificationConfirmation.qml
@@ -2,6 +2,7 @@
//
// SPDX-License-Identifier: GPL-3.0-or-later
+import "../ui"
import QtQuick 2.3
import QtQuick.Controls 2.3
import QtQuick.Layouts 1.10
@@ -25,8 +26,9 @@ Pane {
verticalAlignment: Text.AlignVCenter
}
- BusyIndicator {
+ Spinner {
Layout.alignment: Qt.AlignHCenter
+ foreground: Nheko.colors.mid
}
RowLayout {
diff --git a/resources/qml/device-verification/Waiting.qml b/resources/qml/device-verification/Waiting.qml
index c521503b..e1401a47 100644
--- a/resources/qml/device-verification/Waiting.qml
+++ b/resources/qml/device-verification/Waiting.qml
@@ -2,6 +2,7 @@
//
// SPDX-License-Identifier: GPL-3.0-or-later
+import "../ui"
import QtQuick 2.3
import QtQuick.Controls 2.3
import QtQuick.Layouts 1.10
@@ -34,9 +35,9 @@ Pane {
verticalAlignment: Text.AlignVCenter
}
- BusyIndicator {
+ Spinner {
Layout.alignment: Qt.AlignHCenter
- palette: Nheko.colors
+ foreground: Nheko.colors.mid
}
RowLayout {
diff --git a/resources/qml/ui/Spinner.qml b/resources/qml/ui/Spinner.qml
new file mode 100644
index 00000000..a1a09a6a
--- /dev/null
+++ b/resources/qml/ui/Spinner.qml
@@ -0,0 +1,161 @@
+// SPDX-FileCopyrightText: 2021 Nheko Contributors
+//
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+import QtQuick 2.12
+import QtGraphicalEffects 1.12
+
+import "./animations"
+
+Item {
+ id: spinner
+
+ property int spacing: 0
+ property bool running: true
+ property var foreground: "#333"
+ readonly property int barCount: 6
+ readonly property real a: Math.PI / 6
+ readonly property var colors: ["#c0def5", "#87aade", "white"]
+ readonly property var anims: [anim1, anim2, anim3, anim4, anim5, anim6]
+ readonly property int pauseDuration: barCount * 150
+ readonly property int glowDuration: 300
+
+ height: 40
+ width: barCount * (height * 0.375)
+
+ Row {
+ id: row
+
+ Rectangle {
+ id: rect1
+
+ width: ((spinner.width / spinner.barCount) - (spinner.spacing)) * 1.5
+ height: spinner.height / 3.5
+ color: "white"
+ }
+
+ Rectangle {
+ id: rect2
+
+ width: (spinner.width / spinner.barCount) - spinner.spacing
+ height: spinner.height
+ color: spinner.colors[0]
+ }
+
+ Rectangle {
+ id: rect3
+
+ width: (spinner.width / spinner.barCount) - spinner.spacing
+ height: spinner.height
+ color: spinner.colors[1]
+ }
+
+ Rectangle {
+ id: rect4
+
+ width: (spinner.width / spinner.barCount) - spinner.spacing
+ height: spinner.height
+ color: spinner.colors[2]
+ }
+
+ Rectangle {
+ id: rect5
+
+ width: (spinner.width / (spinner.barCount + 1)) - spinner.spacing
+ height: spinner.height / 3.5
+ color: "white"
+ }
+
+ Rectangle {
+ id: rect6
+
+ width: (spinner.width / spinner.barCount) - spinner.spacing
+ height: spinner.height
+ color: "white"
+ }
+
+ BlinkAnimation {
+ id: anim1
+ target: rect1
+ pauseDuration: spinner.pauseDuration
+ glowDuration: spinner.glowDuration
+
+ loops: Animation.Infinite
+ }
+
+ BlinkAnimation {
+ id: anim2
+ target: rect2
+ pauseDuration: spinner.pauseDuration
+ glowDuration: spinner.glowDuration
+ }
+
+ BlinkAnimation {
+ id: anim3
+ target: rect3
+ pauseDuration: spinner.pauseDuration
+ glowDuration: spinner.glowDuration
+
+ }
+
+ BlinkAnimation {
+ id: anim4
+ target: rect4
+ pauseDuration: spinner.pauseDuration
+ glowDuration: spinner.glowDuration
+
+ }
+
+ BlinkAnimation {
+ id: anim5
+ target: rect5
+ pauseDuration: spinner.pauseDuration
+ glowDuration: spinner.glowDuration
+ }
+
+ BlinkAnimation {
+ id: anim6
+ target: rect6
+ pauseDuration: spinner.pauseDuration
+ glowDuration: spinner.glowDuration
+ }
+
+ transform: Matrix4x4 {
+ matrix: Qt.matrix4x4(Math.cos(spinner.a), -Math.sin(spinner.a), 0, 0, 0, Math.cos(spinner.a), 0, 0, 0, 0, 1, 0, 0, 0, 0, 1)
+ }
+
+ }
+
+ Timer {
+ // ----- Private Properties ----- //
+ property int _barIndex: 0
+
+ interval: 80
+ repeat: true
+ running: spinner.running
+ onTriggered: {
+ if (_barIndex === spinner.barCount) {
+ _barIndex = 0;
+ stop();
+ } else {
+ anims[_barIndex].start();
+ _barIndex++;
+ }
+ }
+ Component.onCompleted: start()
+ }
+
+ Glow {
+ anchors.fill: row
+ radius: 14
+ samples: 17
+ color: spinner.foreground
+ source: row
+
+ transform: Matrix4x4 {
+ matrix: Qt.matrix4x4(Math.cos(spinner.a), -Math.sin(spinner.a), 0, 0, 0, Math.cos(spinner.a), 0, 0, 0, 0, 1, 0, 0, 0, 0, 1)
+ }
+
+ }
+
+}
diff --git a/resources/qml/ui/animations/BlinkAnimation.qml b/resources/qml/ui/animations/BlinkAnimation.qml
new file mode 100644
index 00000000..73991a1f
--- /dev/null
+++ b/resources/qml/ui/animations/BlinkAnimation.qml
@@ -0,0 +1,26 @@
+// SPDX-FileCopyrightText: 2021 Nheko Contributors
+//
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+import QtQuick 2.12
+import QtGraphicalEffects 1.12
+
+SequentialAnimation {
+ property alias target: numberAnimation.target
+ property alias glowDuration: numberAnimation.duration
+ property alias pauseDuration: pauseAnimation.duration
+
+ loops: Animation.Infinite
+
+ NumberAnimation {
+ id: numberAnimation
+ property: "opacity"
+ from: 0
+ to: 1
+ }
+
+ PauseAnimation {
+ id: pauseAnimation
+ }
+
+}
\ No newline at end of file
diff --git a/resources/qml/ui/animations/qmldir b/resources/qml/ui/animations/qmldir
new file mode 100644
index 00000000..14f9ad86
--- /dev/null
+++ b/resources/qml/ui/animations/qmldir
@@ -0,0 +1,2 @@
+module im.nheko.UI.Animations
+BlinkAnimation 1.0 BlinkAnimation.qml
diff --git a/resources/qml/ui/qmldir b/resources/qml/ui/qmldir
index a8466a10..831a723d 100644
--- a/resources/qml/ui/qmldir
+++ b/resources/qml/ui/qmldir
@@ -1,2 +1,3 @@
module im.nheko.UI
-Ripple 1.0 Ripple.qml
\ No newline at end of file
+Ripple 1.0 Ripple.qml
+Spinner 1.0 Spinner.qml
\ No newline at end of file
diff --git a/resources/res.qrc b/resources/res.qrc
index 53c74ae3..9bb8ae2e 100644
--- a/resources/res.qrc
+++ b/resources/res.qrc
@@ -171,6 +171,8 @@
qml/device-verification/Success.qml
qml/dialogs/InputDialog.qml
qml/ui/Ripple.qml
+ qml/ui/Spinner.qml
+ qml/ui/animations/BlinkAnimation.qml
qml/voip/ActiveCallBar.qml
qml/voip/CallDevices.qml
qml/voip/CallInvite.qml