import QtQuick import Quickshell import ".." as M Item { id: root property bool running: false property bool reducedMotion: M.Theme.reducedMotion Rectangle { anchors.fill: parent color: M.Theme.base01 } ShaderEffect { id: fx anchors.fill: parent fragmentShader: Quickshell.shellPath("modules/hex_wave.frag.qsb") property real uSize: 50.0 property real uWavePhase: -200 property real uBreath: 0 property real uGlitch: 0 property real uGlitchSeed: 0.0 property vector4d uResolution: Qt.vector4d(width, height, 0, 0) property color uC0: M.Theme.base0C property color uC1: M.Theme.base0E property color uC2: M.Theme.base09 // Reset animations when stopped onRunningChanged: { if (!root.running) { fx.uWavePhase = -200; fx.uBreath = 0; } } // Wave animation: 6s sweep + 8s pause SequentialAnimation on uWavePhase { loops: Animation.Infinite running: root.running && !root.reducedMotion NumberAnimation { from: -200 to: fx.width + 200 duration: 6000 easing.type: Easing.InOutSine } PauseAnimation { duration: 8000 } } // Breathing pulse SequentialAnimation on uBreath { loops: Animation.Infinite running: root.running && !root.reducedMotion NumberAnimation { from: 0 to: 1 duration: 2500 easing.type: Easing.InOutSine } NumberAnimation { from: 1 to: 0 duration: 2500 easing.type: Easing.InOutSine } } // Random subtle glitches - fire every 12-37s Timer { interval: 20000 repeat: true running: !root.reducedMotion onTriggered: { interval = 12000 + Math.floor(Math.random() * 25000); fx.uGlitchSeed = Math.random() * 1000.0; _glitchAnim.start(); } } SequentialAnimation { id: _glitchAnim NumberAnimation { target: fx property: "uGlitch" to: 0.7 duration: 50 easing.type: Easing.OutQuad } NumberAnimation { target: fx property: "uGlitch" to: 0.15 duration: 50 } NumberAnimation { target: fx property: "uGlitch" to: 0.85 duration: 60 easing.type: Easing.OutQuad } NumberAnimation { target: fx property: "uGlitch" to: 0 duration: 100 easing.type: Easing.InQuad } } } }