diff --git a/resources/confettiparticle.png b/resources/confettiparticle.png
new file mode 100644
index 00000000..808429d8
--- /dev/null
+++ b/resources/confettiparticle.png
Binary files differdiff --git a/resources/confettiparticle.svg b/resources/confettiparticle.svg
new file mode 100644
index 00000000..80b85629
--- /dev/null
+++ b/resources/confettiparticle.svg
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ version="1.0"
+ width="32.000000pt"
+ height="10.000000pt"
+ viewBox="0 0 32.000000 10.000000"
+ preserveAspectRatio="xMidYMid meet"
+ id="svg4"
+ sodipodi:docname="confettiparticle.svg"
+ inkscape:version="1.2.1 (9c6d41e410, 2022-07-14)"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:svg="http://www.w3.org/2000/svg">
+ <defs
+ id="defs8" />
+ <sodipodi:namedview
+ id="namedview6"
+ pagecolor="#ffffff"
+ bordercolor="#000000"
+ borderopacity="0.25"
+ inkscape:showpageshadow="2"
+ inkscape:pageopacity="0.0"
+ inkscape:pagecheckerboard="0"
+ inkscape:deskcolor="#d1d1d1"
+ inkscape:document-units="pt"
+ showgrid="false"
+ inkscape:zoom="17.7"
+ inkscape:cx="7.1751412"
+ inkscape:cy="0.64971751"
+ inkscape:window-width="1920"
+ inkscape:window-height="1015"
+ inkscape:window-x="0"
+ inkscape:window-y="0"
+ inkscape:window-maximized="1"
+ inkscape:current-layer="svg4" />
+ <g
+ transform="translate(0.000000,10.000000) scale(0.100000,-0.100000)"
+ fill="#000000"
+ stroke="none"
+ id="g2" />
+ <rect
+ style="fill:#ffffff;stroke-width:0.75"
+ id="rect307"
+ width="32.033897"
+ height="10"
+ x="0"
+ y="0" />
+</svg>
diff --git a/resources/qml/MessageView.qml b/resources/qml/MessageView.qml
index 8e6ad8d2..e3e02ee9 100644
--- a/resources/qml/MessageView.qml
+++ b/resources/qml/MessageView.qml
@@ -59,7 +59,6 @@ Item {
onCountChanged: {
// Mark timeline as read
if (atYEnd && room) model.currentIndex = 0;
-
}
ScrollBar.vertical: scrollbar
diff --git a/resources/qml/TimelineView.qml b/resources/qml/TimelineView.qml
index ab1bbc28..dff23700 100644
--- a/resources/qml/TimelineView.qml
+++ b/resources/qml/TimelineView.qml
@@ -13,6 +13,7 @@ import Qt.labs.platform 1.1 as Platform
import QtQuick 2.15
import QtQuick.Controls 2.5
import QtQuick.Layouts 1.3
+import QtQuick.Particles 2.15
import QtQuick.Window 2.13
import im.nheko 1.0
import im.nheko.EmojiModel 1.0
@@ -25,6 +26,8 @@ Item {
property bool showBackButton: false
clip: true
+ onRoomChanged: if (room != null) room.triggerSpecialEffects()
+
Shortcut {
sequence: StandardKey.Close
onActivated: Rooms.resetCurrentRoom()
@@ -298,6 +301,58 @@ Item {
onClicked: Rooms.resetCurrentRoom()
}
+ ParticleSystem { id: confettiParticleSystem }
+
+ Emitter {
+ id: confettiEmitter
+
+ width: parent.width * 3/4
+ enabled: false
+ anchors.horizontalCenter: parent.horizontalCenter
+ y: parent.height
+ emitRate: Math.min(400 * Math.sqrt(parent.width * parent.height) / 870, 1000)
+ lifeSpan: 15000
+ system: confettiParticleSystem
+ velocityFromMovement: 8
+ size: 16
+ sizeVariation: 4
+ velocity: PointDirection {
+ x: 0
+ y: -Math.min(450 * parent.height / 700, 1000)
+ xVariation: Math.min(4 * parent.width / 7, 450)
+ yVariation: 250
+ }
+
+ ImageParticle {
+ system: confettiParticleSystem
+ source: "qrc:/confettiparticle.svg"
+ rotationVelocity: 0
+ rotationVelocityVariation: 360
+ colorVariation: 1
+ color: "white"
+ entryEffect: ImageParticle.None
+ xVector: PointDirection {
+ x: 1
+ y: 0
+ xVariation: 0.2
+ yVariation: 0.2
+ }
+ yVector: PointDirection {
+ x: 0
+ y: 0.5
+ xVariation: 0.2
+ yVariation: 0.2
+ }
+ }
+ }
+
+ Gravity {
+ system: confettiParticleSystem
+ anchors.fill: parent
+ magnitude: 350
+ angle: 90
+ }
+
NhekoDropArea {
anchors.fill: parent
roomid: room ? room.roomId : ""
@@ -321,6 +376,15 @@ Item {
timelineRoot.destroyOnClose(dialog);
}
+ function onConfetti()
+ {
+ if (!Settings.fancyEffects)
+ return
+
+ confettiEmitter.pulse(parent.height * 2)
+ room.markSpecialEffectsDone()
+ }
+
target: room
}
diff --git a/resources/qml/delegates/MessageDelegate.qml b/resources/qml/delegates/MessageDelegate.qml
index a2a44cb2..3725be05 100644
--- a/resources/qml/delegates/MessageDelegate.qml
+++ b/resources/qml/delegates/MessageDelegate.qml
@@ -76,6 +76,20 @@ Item {
}
DelegateChoice {
+ roleValue: MtxEvent.ConfettiMessage
+
+ TextMessage {
+ formatted: d.formattedBody
+ body: d.body
+ isOnlyEmoji: d.isOnlyEmoji
+ isReply: d.isReply
+ keepFullText: d.keepFullText
+ metadataWidth: d.metadataWidth
+ }
+
+ }
+
+ DelegateChoice {
roleValue: MtxEvent.NoticeMessage
NoticeMessage {
diff --git a/resources/res.qrc b/resources/res.qrc
index 595dd5a7..e9320a1b 100644
--- a/resources/res.qrc
+++ b/resources/res.qrc
@@ -193,6 +193,7 @@
<file>qml/voip/PlaceCall.qml</file>
<file>qml/voip/ScreenShare.qml</file>
<file>qml/voip/VideoCall.qml</file>
+ <file>confettiparticle.svg</file>
</qresource>
<qresource prefix="/media">
<file>media/ring.ogg</file>
|