diff --git a/CMakeLists.txt b/CMakeLists.txt index 06af4bbe..20fcb029 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -602,7 +602,7 @@ if(USE_BUNDLED_MTXCLIENT) FetchContent_Declare( MatrixClient GIT_REPOSITORY https://github.com/Nheko-Reborn/mtxclient.git - GIT_TAG c8849cd033bb59bee39f3fb2eaca953853731eb2 + GIT_TAG dd2bdbd104ae8f70f82da9ff7b4b60007fc105c3 ) set(BUILD_LIB_EXAMPLES OFF CACHE INTERNAL "") set(BUILD_LIB_TESTS OFF CACHE INTERNAL "") diff --git a/io.github.NhekoReborn.Nheko.yaml b/io.github.NhekoReborn.Nheko.yaml index 3bcfdf52..97d0b770 100644 --- a/io.github.NhekoReborn.Nheko.yaml +++ b/io.github.NhekoReborn.Nheko.yaml @@ -213,7 +213,7 @@ modules: buildsystem: cmake-ninja name: mtxclient sources: - - commit: c8849cd033bb59bee39f3fb2eaca953853731eb2 + - commit: dd2bdbd104ae8f70f82da9ff7b4b60007fc105c3 #tag: v0.9.2 type: git url: https://github.com/Nheko-Reborn/mtxclient.git diff --git a/resources/qml/TimelineView.qml b/resources/qml/TimelineView.qml index a146a991..30ad9292 100644 --- a/resources/qml/TimelineView.qml +++ b/resources/qml/TimelineView.qml @@ -364,60 +364,10 @@ Item { onClicked: Rooms.resetCurrentRoom() } - ParticleSystem { id: confettiParticleSystem - Component.onCompleted: pause(); - paused: !shouldEffectsRun - } + TimelineEffects { + id: timelineEffects - 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 - maximumEmitted: 500 - 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 { @@ -428,7 +378,7 @@ Item { Timer { id: effectsTimer onTriggered: shouldEffectsRun = false; - interval: confettiEmitter.lifeSpan + interval: timelineEffects.maxLifespan repeat: false running: false } @@ -462,7 +412,7 @@ Item { return shouldEffectsRun = true; - confettiEmitter.pulse(parent.height * 2) + timelineEffects.pulseConfetti() room.markSpecialEffectsDone() } @@ -471,7 +421,25 @@ Item { if (!Settings.fancyEffects) return - effectsTimer.start(); + effectsTimer.restart(); + } + + function onRainfall() + { + if (!Settings.fancyEffects) + return + + shouldEffectsRun = true; + timelineEffects.pulseRainfall() + room.markSpecialEffectsDone() + } + + function onRainfallDone() + { + if (!Settings.fancyEffects) + return + + effectsTimer.restart(); } target: room diff --git a/resources/qml/delegates/MessageDelegate.qml b/resources/qml/delegates/MessageDelegate.qml index d298fa4e..c0bcec0d 100644 --- a/resources/qml/delegates/MessageDelegate.qml +++ b/resources/qml/delegates/MessageDelegate.qml @@ -51,7 +51,7 @@ Item { width: parent.width? parent.width: 0 // this should get rid of "cannot read property 'width' of null" DelegateChoice { - roleValue: MtxEvent.UnknownMessage + roleValue: MtxEvent.UnknownEvent Placeholder { typeString: d.typeString @@ -102,7 +102,21 @@ Item { } DelegateChoice { - roleValue: MtxEvent.ConfettiMessage + roleValue: MtxEvent.UnknownMessage + + TextMessage { + formatted: d.formattedBody + body: d.body + isOnlyEmoji: d.isOnlyEmoji + isReply: d.isReply + keepFullText: d.keepFullText + metadataWidth: d.metadataWidth + } + + } + + DelegateChoice { + roleValue: MtxEvent.ElementEffectMessage TextMessage { formatted: d.formattedBody diff --git a/resources/qml/ui/TimelineEffects.qml b/resources/qml/ui/TimelineEffects.qml new file mode 100644 index 00000000..aaff04a0 --- /dev/null +++ b/resources/qml/ui/TimelineEffects.qml @@ -0,0 +1,112 @@ +// SPDX-FileCopyrightText: Nheko Contributors +// +// SPDX-License-Identifier: GPL-3.0-or-later + +import QtQuick 2.15 +import QtQuick.Particles 2.15 + +Item { + readonly property int maxLifespan: Math.max(confettiEmitter.lifeSpan, rainfallEmitter.lifeSpan) + + function pulseConfetti() + { + confettiEmitter.pulse(parent.height * 2) + } + + function pulseRainfall() + { + rainfallEmitter.pulse(parent.height * 3.3) + } + + ParticleSystem { + id: particleSystem + + Component.onCompleted: pause(); + paused: !shouldEffectsRun + } + + Emitter { + id: confettiEmitter + + group: "confetti" + 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: particleSystem + maximumEmitted: 500 + 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: particleSystem + groups: ["confetti"] + 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: particleSystem + groups: ["confetti"] + anchors.fill: parent + magnitude: 350 + angle: 90 + } + + Emitter { + id: rainfallEmitter + + group: "rain" + width: parent.width + enabled: false + anchors.horizontalCenter: parent.horizontalCenter + y: -60 + emitRate: parent.width / 50 + lifeSpan: 10000 + system: particleSystem + velocity: PointDirection { + x: 0 + y: 300 + xVariation: 0 + yVariation: 75 + } + + ItemParticle { + system: particleSystem + groups: ["rain"] + fade: false + delegate: Rectangle { + width: 2 + height: 30 + 30 * Math.random() + radius: 2 + color: "#0099ff" + } + } + } +} diff --git a/resources/res.qrc b/resources/res.qrc index faa90495..3f1b2b65 100644 --- a/resources/res.qrc +++ b/resources/res.qrc @@ -197,6 +197,7 @@ qml/voip/VideoCall.qml confettiparticle.svg qml/delegates/EncryptionEnabled.qml + qml/ui/TimelineEffects.qml media/ring.ogg diff --git a/src/CommandCompleter.cpp b/src/CommandCompleter.cpp index 2ec427d6..8123b8e6 100644 --- a/src/CommandCompleter.cpp +++ b/src/CommandCompleter.cpp @@ -87,6 +87,10 @@ CommandCompleter::data(const QModelIndex &index, int role) const return QStringLiteral("/confetti "); case RainbowConfetti: return QStringLiteral("/rainbowconfetti "); + case Rainfall: + return QStringLiteral("/rainfall "); + case Msgtype: + return QStringLiteral("/msgtype "); case Goto: return QStringLiteral("/goto "); case ConvertToDm: @@ -156,6 +160,10 @@ CommandCompleter::data(const QModelIndex &index, int role) const return tr("/confetti [message]"); case RainbowConfetti: return tr("/rainbowconfetti [message]"); + case Rainfall: + return tr("/rainfall [message]"); + case Msgtype: + return tr("/msgtype [message]"); case Goto: return tr("/goto "); case ConvertToDm: @@ -225,6 +233,10 @@ CommandCompleter::data(const QModelIndex &index, int role) const return tr("Send a message with confetti."); case RainbowConfetti: return tr("Send a message in rainbow colors with confetti."); + case Rainfall: + return tr("Send a message with rain."); + case Msgtype: + return tr("Send a message with a custom message type."); case Goto: return tr("Go to a specific message using an event id, index or matrix: link"); case ConvertToDm: diff --git a/src/CommandCompleter.h b/src/CommandCompleter.h index fcbbe3e5..4f27fe29 100644 --- a/src/CommandCompleter.h +++ b/src/CommandCompleter.h @@ -46,6 +46,8 @@ public: RainbowNotice, Confetti, RainbowConfetti, + Rainfall, + Msgtype, Goto, ConvertToDm, ConvertToRoom, diff --git a/src/Utils.cpp b/src/Utils.cpp index c5b2abd1..2bf8eb3b 100644 --- a/src/Utils.cpp +++ b/src/Utils.cpp @@ -215,19 +215,20 @@ utils::getMessageDescription(const TimelineEvent &event, const QString &localUser, const QString &displayName) { - using Audio = mtx::events::RoomEvent; - using Emote = mtx::events::RoomEvent; - using File = mtx::events::RoomEvent; - using Image = mtx::events::RoomEvent; - using Notice = mtx::events::RoomEvent; - using Text = mtx::events::RoomEvent; - using Video = mtx::events::RoomEvent; - using Confetti = mtx::events::RoomEvent; - using CallInvite = mtx::events::RoomEvent; - using CallAnswer = mtx::events::RoomEvent; - using CallHangUp = mtx::events::RoomEvent; - using CallReject = mtx::events::RoomEvent; - using Encrypted = mtx::events::EncryptedEvent; + using Audio = mtx::events::RoomEvent; + using Emote = mtx::events::RoomEvent; + using File = mtx::events::RoomEvent; + using Image = mtx::events::RoomEvent; + using Notice = mtx::events::RoomEvent; + using Text = mtx::events::RoomEvent; + using Unknown = mtx::events::RoomEvent; + using Video = mtx::events::RoomEvent; + using ElementEffect = mtx::events::RoomEvent; + using CallInvite = mtx::events::RoomEvent; + using CallAnswer = mtx::events::RoomEvent; + using CallHangUp = mtx::events::RoomEvent; + using CallReject = mtx::events::RoomEvent; + using Encrypted = mtx::events::EncryptedEvent; if (std::holds_alternative