From f6e86afdc54ad9d6a33a07d611bb05da55ee62fb Mon Sep 17 00:00:00 2001 From: Brainitech Date: Sat, 20 Jun 2026 22:08:39 +0530 Subject: [PATCH 1/4] feat(ui): add smooth morph animations and fix tab glitches --- src/components/TabSwitcher.qml | 313 ++++++++++++++++++++------------- src/popups/Dashboard.qml | 30 +++- src/popups/NetworkPopup.qml | 28 ++- 3 files changed, 243 insertions(+), 128 deletions(-) diff --git a/src/components/TabSwitcher.qml b/src/components/TabSwitcher.qml index 14e6528..d65b0fd 100644 --- a/src/components/TabSwitcher.qml +++ b/src/components/TabSwitcher.qml @@ -65,70 +65,111 @@ Item { } // ── HORIZONTAL layout — Row ─────────────────────────────────────────────── - Row { - id: hRow + Item { + id: hContainer anchors.fill: parent visible: root.orientation === "horizontal" - Repeater { - model: root.orientation === "horizontal" ? root.model : [] + Rectangle { + id: hMorph + property int activeIdx: { + for (var i = 0; i < root.model.length; ++i) { + if (root.model[i].key === root.currentPage) return i; + } + return 0; + } + + property Item activeTab: hRepeater.count > 0 ? hRepeater.itemAt(activeIdx) : null + property real targetWidth: activeTab ? activeTab.bgWidth : 0 + + // isReady prevents animations until the item has rendered its first real width + property bool isReady: hMorph.width > 0 - delegate: Item { - id: hTab - readonly property bool isActive: root.currentPage === modelData.key + property real animIdx: activeIdx + Behavior on animIdx { + enabled: hMorph.isReady + NumberAnimation { duration: 350; easing.type: Easing.OutExpo } + } - width: hRow.width / root.model.length - height: hRow.height + property real animWidth: targetWidth + Behavior on animWidth { + enabled: hMorph.isReady + NumberAnimation { duration: 350; easing.type: Easing.OutExpo } + } - // Pill background - Rectangle { - id: hBg - anchors.centerIn: parent - width: hIcon.implicitWidth + hLabel.implicitWidth + Math.round(24 * localScale) - height: parent.height - Math.round(8 * localScale) - radius: height / 2 + height: parent.height - Math.round(8 * localScale) + y: Math.round(4 * localScale) + radius: height / 2 + color: Theme.active - color: hTab.isActive - ? Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.18) - : (hHov.hovered ? Qt.rgba(1, 1, 1, 0.07) : "transparent") + width: animWidth + + property real slotWidth: root.model.length > 0 ? hRow.width / root.model.length : 0 + x: slotWidth > 0 ? (animIdx * slotWidth) + (slotWidth - animWidth) / 2 : 0 + } - Behavior on color { ColorAnimation { duration: 120 } } - } + Row { + id: hRow + anchors.fill: parent + + Repeater { + id: hRepeater + model: root.orientation === "horizontal" ? root.model : [] + + delegate: Item { + id: hTab + readonly property bool isActive: root.currentPage === modelData.key + readonly property real bgWidth: hIcon.implicitWidth + (modelData.label !== undefined ? hLabel.implicitWidth : 0) + Math.round(24 * localScale) + + width: hRow.width / root.model.length + height: hRow.height - // Icon + label - Row { - anchors.centerIn: parent - spacing: Math.round(6 * localScale) - - Text { - id: hIcon - text: modelData.icon - font.pixelSize: Math.round(14 * localScale) - anchors.verticalCenter: parent.verticalCenter - color: hTab.isActive - ? Theme.active - : (hHov.hovered ? Qt.rgba(1, 1, 1, 0.75) : Qt.rgba(1, 1, 1, 0.4)) + // Hover background + Rectangle { + id: hHoverBg + anchors.centerIn: parent + width: hTab.bgWidth + height: parent.height - Math.round(8 * localScale) + radius: height / 2 + color: !hTab.isActive && hHov.hovered ? Qt.rgba(1, 1, 1, 0.07) : "transparent" Behavior on color { ColorAnimation { duration: 120 } } } - Text { - id: hLabel - visible: modelData.label !== undefined - text: modelData.label ?? "" - font.pixelSize: Math.round(12 * localScale) - font.weight: hTab.isActive ? Font.Medium : Font.Normal - anchors.verticalCenter: parent.verticalCenter - color: hTab.isActive - ? Theme.active - : (hHov.hovered ? Qt.rgba(1, 1, 1, 0.75) : Qt.rgba(1, 1, 1, 0.4)) - Behavior on color { ColorAnimation { duration: 120 } } + // Icon + label + Row { + anchors.centerIn: parent + spacing: Math.round(6 * localScale) + + Text { + id: hIcon + text: modelData.icon + font.pixelSize: Math.round(14 * localScale) + anchors.verticalCenter: parent.verticalCenter + color: hTab.isActive + ? Theme.background + : (hHov.hovered ? Qt.rgba(1, 1, 1, 0.75) : Qt.rgba(1, 1, 1, 0.4)) + Behavior on color { ColorAnimation { duration: 120 } } + } + + Text { + id: hLabel + visible: modelData.label !== undefined + text: modelData.label ?? "" + font.pixelSize: Math.round(12 * localScale) + font.weight: hTab.isActive ? Font.Medium : Font.Normal + anchors.verticalCenter: parent.verticalCenter + color: hTab.isActive + ? Theme.background + : (hHov.hovered ? Qt.rgba(1, 1, 1, 0.75) : Qt.rgba(1, 1, 1, 0.4)) + Behavior on color { ColorAnimation { duration: 120 } } + } } - } - HoverHandler { id: hHov; cursorShape: Qt.PointingHandCursor } - MouseArea { - anchors.fill: parent - onClicked: root.pageChanged(modelData.key) + HoverHandler { id: hHov; cursorShape: Qt.PointingHandCursor } + MouseArea { + anchors.fill: parent + onClicked: root.pageChanged(modelData.key) + } } } } @@ -145,14 +186,15 @@ Item { } // ── VERTICAL layout — Column ────────────────────────────────────────────── - Column { - id: vCol + Item { + id: vContainer anchors.centerIn: parent visible: root.orientation === "vertical" width: root.width + height: root.height readonly property int tabH: Math.round(60 * localScale) - spacing: root.model.length > 1 + readonly property real vSpacing: root.model.length > 1 ? (root.height - root.model.length * tabH) / (root.model.length - 1) : 0 @@ -160,73 +202,106 @@ Item { root.model.length > 0 && root.model[0].label !== undefined && root.model[0].label !== "" + + Rectangle { + id: vMorph + width: parent.width + height: vContainer.tabH + radius: Math.round(Theme.cornerRadius * 2 * localScale) + color: Theme.active + + property int activeIdx: { + for (var i = 0; i < root.model.length; ++i) { + if (root.model[i].key === root.currentPage) return i; + } + return 0; + } + + property bool isReady: vContainer.height > 0 + property real animIdx: activeIdx + + Behavior on animIdx { + enabled: vMorph.isReady + NumberAnimation { duration: 350; easing.type: Easing.OutExpo } + } + + y: animIdx * (vContainer.tabH + vContainer.vSpacing) + } - Repeater { - model: root.orientation === "vertical" ? root.model : [] - - delegate: Rectangle { - id: vTab - readonly property bool isActive: root.currentPage === modelData.key - - width: vCol.width - height: vCol.tabH - radius: Math.round(Theme.cornerRadius * 2 * localScale) - - color: vTab.isActive - ? Theme.active - : (vHov.hovered ? Qt.rgba(1, 1, 1, 0.08) : "transparent") - - Behavior on color { ColorAnimation { duration: 120 } } - - // Icon-only (no label) - Text { - visible: !vCol.hasLabels - anchors.centerIn: parent - text: modelData.icon - font.pixelSize: Math.round(16 * localScale) - color: vTab.isActive ? Theme.background : Theme.text - Behavior on color { ColorAnimation { duration: 120 } } - } - - // Icon + label row - Row { - visible: vCol.hasLabels - anchors { - left: parent.left - leftMargin: Math.round(16 * localScale) - verticalCenter: parent.verticalCenter - } - spacing: Math.round(12 * localScale) - - Text { - text: modelData.icon - font.pixelSize: Math.round(15 * localScale) - anchors.verticalCenter: parent.verticalCenter - color: vTab.isActive - ? Theme.background - : (vHov.hovered ? Qt.rgba(1, 1, 1, 0.80) : Qt.rgba(1, 1, 1, 0.42)) - Behavior on color { ColorAnimation { duration: 120 } } - } - - Text { - text: modelData.label ?? "" - font.pixelSize: Math.round(12 * localScale) - font.weight: vTab.isActive ? Font.Medium : Font.Normal - anchors.verticalCenter: parent.verticalCenter - color: vTab.isActive - ? Theme.background - : (vHov.hovered ? Qt.rgba(1, 1, 1, 0.80) : Qt.rgba(1, 1, 1, 0.42)) - Behavior on color { ColorAnimation { duration: 120 } } - } - } - - HoverHandler { id: vHov; cursorShape: Qt.PointingHandCursor } - MouseArea { - anchors.fill: parent - onClicked: root.pageChanged(modelData.key) - } - } - } + Column { + id: vCol + anchors.fill: parent + spacing: vContainer.vSpacing + + Repeater { + id: vRepeater + model: root.orientation === "vertical" ? root.model : [] + + delegate: Item { + id: vTab + readonly property bool isActive: root.currentPage === modelData.key + + width: vCol.width + height: vContainer.tabH + + // Hover background + Rectangle { + anchors.fill: parent + radius: Math.round(Theme.cornerRadius * 2 * localScale) + color: !vTab.isActive && vHov.hovered ? Qt.rgba(1, 1, 1, 0.08) : "transparent" + Behavior on color { ColorAnimation { duration: 120 } } + } + + // Icon-only (no label) + Text { + visible: !vContainer.hasLabels + anchors.centerIn: parent + text: modelData.icon + font.pixelSize: Math.round(16 * localScale) + color: vTab.isActive ? Theme.background : Theme.text + Behavior on color { ColorAnimation { duration: 120 } } + } + + // Icon + label row + Row { + visible: vContainer.hasLabels + anchors { + left: parent.left + leftMargin: Math.round(16 * localScale) + verticalCenter: parent.verticalCenter + } + spacing: Math.round(12 * localScale) + + Text { + text: modelData.icon + font.pixelSize: Math.round(15 * localScale) + anchors.verticalCenter: parent.verticalCenter + color: vTab.isActive + ? Theme.background + : (vHov.hovered ? Qt.rgba(1, 1, 1, 0.80) : Qt.rgba(1, 1, 1, 0.42)) + Behavior on color { ColorAnimation { duration: 120 } } + } + + Text { + text: modelData.label ?? "" + font.pixelSize: Math.round(12 * localScale) + font.weight: vTab.isActive ? Font.Medium : Font.Normal + anchors.verticalCenter: parent.verticalCenter + color: vTab.isActive + ? Theme.background + : (vHov.hovered ? Qt.rgba(1, 1, 1, 0.80) : Qt.rgba(1, 1, 1, 0.42)) + Behavior on color { ColorAnimation { duration: 120 } } + } + } + + HoverHandler { id: vHov; cursorShape: Qt.PointingHandCursor } + MouseArea { + anchors.fill: parent + onClicked: root.pageChanged(modelData.key) + } + } + } + } } } diff --git a/src/popups/Dashboard.qml b/src/popups/Dashboard.qml index 8735729..5b9b7e0 100644 --- a/src/popups/Dashboard.qml +++ b/src/popups/Dashboard.qml @@ -187,7 +187,11 @@ PanelWindow { Item { anchors.fill: parent - visible: root.page === "home" + opacity: root.page === "home" ? 1 : 0 + visible: opacity > 0 + scale: root.page === "home" ? 1 : 0.98 + Behavior on opacity { NumberAnimation { duration: 250; easing.type: Easing.OutQuart } } + Behavior on scale { NumberAnimation { duration: 250; easing.type: Easing.OutBack } } DashHome { anchors.fill: parent localScale: root.localScale @@ -196,7 +200,11 @@ PanelWindow { Item { anchors.fill: parent - visible: root.page === "stats" + opacity: root.page === "stats" ? 1 : 0 + visible: opacity > 0 + scale: root.page === "stats" ? 1 : 0.98 + Behavior on opacity { NumberAnimation { duration: 250; easing.type: Easing.OutQuart } } + Behavior on scale { NumberAnimation { duration: 250; easing.type: Easing.OutBack } } DashStats { anchors.fill: parent localScale: root.localScale @@ -205,7 +213,11 @@ PanelWindow { Item { anchors.fill: parent - visible: root.page === "kanban" + opacity: root.page === "kanban" ? 1 : 0 + visible: opacity > 0 + scale: root.page === "kanban" ? 1 : 0.98 + Behavior on opacity { NumberAnimation { duration: 250; easing.type: Easing.OutQuart } } + Behavior on scale { NumberAnimation { duration: 250; easing.type: Easing.OutBack } } KanbanBoard { anchors.fill: parent localScale: root.localScale @@ -214,7 +226,11 @@ PanelWindow { Item { anchors.fill: parent - visible: root.page === "launcher" + opacity: root.page === "launcher" ? 1 : 0 + visible: opacity > 0 + scale: root.page === "launcher" ? 1 : 0.98 + Behavior on opacity { NumberAnimation { duration: 250; easing.type: Easing.OutQuart } } + Behavior on scale { NumberAnimation { duration: 250; easing.type: Easing.OutBack } } AppLauncher { anchors.fill: parent localScale: root.localScale @@ -223,7 +239,11 @@ PanelWindow { Item { anchors.fill: parent - visible: root.page === "config" + opacity: root.page === "config" ? 1 : 0 + visible: opacity > 0 + scale: root.page === "config" ? 1 : 0.98 + Behavior on opacity { NumberAnimation { duration: 250; easing.type: Easing.OutQuart } } + Behavior on scale { NumberAnimation { duration: 250; easing.type: Easing.OutBack } } ShellConfig { anchors.fill: parent localScale: root.localScale diff --git a/src/popups/NetworkPopup.qml b/src/popups/NetworkPopup.qml index f9eedad..62bb80b 100644 --- a/src/popups/NetworkPopup.qml +++ b/src/popups/NetworkPopup.qml @@ -130,14 +130,24 @@ PanelWindow { Loader { anchors.fill: parent - active: root.page === "wifi" + property bool isCurrent: root.page === "wifi" + active: isCurrent || opacity > 0 + opacity: isCurrent ? 1 : 0 + scale: isCurrent ? 1 : 0.98 + Behavior on opacity { NumberAnimation { duration: 250; easing.type: Easing.OutQuart } } + Behavior on scale { NumberAnimation { duration: 250; easing.type: Easing.OutBack } } source: "WifiTab.qml" onLoaded: item.localScale = root.localScale } Loader { anchors.fill: parent - active: root.page === "bluetooth" + property bool isCurrent: root.page === "bluetooth" + active: isCurrent || opacity > 0 + opacity: isCurrent ? 1 : 0 + scale: isCurrent ? 1 : 0.98 + Behavior on opacity { NumberAnimation { duration: 250; easing.type: Easing.OutQuart } } + Behavior on scale { NumberAnimation { duration: 250; easing.type: Easing.OutBack } } source: "BluetoothTab.qml" onLoaded: item.localScale = root.localScale } @@ -145,7 +155,12 @@ PanelWindow { // VPN — WireGuard connections Loader { anchors.fill: parent - active: root.page === "vpn" + property bool isCurrent: root.page === "vpn" + active: isCurrent || opacity > 0 + opacity: isCurrent ? 1 : 0 + scale: isCurrent ? 1 : 0.98 + Behavior on opacity { NumberAnimation { duration: 250; easing.type: Easing.OutQuart } } + Behavior on scale { NumberAnimation { duration: 250; easing.type: Easing.OutBack } } source: "VPNTab.qml" onLoaded: item.localScale = root.localScale } @@ -153,7 +168,12 @@ PanelWindow { // Hotspot — virtual AP interface Loader { anchors.fill: parent - active: root.page === "hotspot" + property bool isCurrent: root.page === "hotspot" + active: isCurrent || opacity > 0 + opacity: isCurrent ? 1 : 0 + scale: isCurrent ? 1 : 0.98 + Behavior on opacity { NumberAnimation { duration: 250; easing.type: Easing.OutQuart } } + Behavior on scale { NumberAnimation { duration: 250; easing.type: Easing.OutBack } } source: "HotspotTab.qml" onLoaded: item.localScale = root.localScale } From 29cc31fe51744909fdffc1c5a3d733cbecdecd7e Mon Sep 17 00:00:00 2001 From: Brainitech Date: Sat, 20 Jun 2026 22:48:32 +0530 Subject: [PATCH 2/4] Animation Iteration_1 --- src/popups/Dashboard.qml | 74 ++++++++++++++++++++------------- src/popups/NetworkPopup.qml | 62 ++++++++++++++++----------- src/services/AudioControl.qml | 30 ++++++++++--- src/services/home/ClockCard.qml | 42 +++++++++++++++---- 4 files changed, 140 insertions(+), 68 deletions(-) diff --git a/src/popups/Dashboard.qml b/src/popups/Dashboard.qml index 5b9b7e0..ac0fef9 100644 --- a/src/popups/Dashboard.qml +++ b/src/popups/Dashboard.qml @@ -181,17 +181,27 @@ PanelWindow { Item { id: pageArea focus: true + clip: true width: parent.width height: parent.height - tabBar.height + + property int pageIdx: Math.max(0, ["home", "stats", "kanban", "launcher", "config"].indexOf(root.page)) + property real animIdx: pageIdx + + Behavior on animIdx { + enabled: pageArea.width > 0 + NumberAnimation { duration: 350; easing.type: Easing.OutExpo } + } Item { - anchors.fill: parent - opacity: root.page === "home" ? 1 : 0 - visible: opacity > 0 - scale: root.page === "home" ? 1 : 0.98 - Behavior on opacity { NumberAnimation { duration: 250; easing.type: Easing.OutQuart } } - Behavior on scale { NumberAnimation { duration: 250; easing.type: Easing.OutBack } } + readonly property int myIdx: 0 + property bool isCurrent: root.page === "home" + width: parent.width; height: parent.height + + x: (myIdx - pageArea.animIdx) * width + visible: Math.abs(x) < width || isCurrent + DashHome { anchors.fill: parent localScale: root.localScale @@ -199,12 +209,13 @@ PanelWindow { } Item { - anchors.fill: parent - opacity: root.page === "stats" ? 1 : 0 - visible: opacity > 0 - scale: root.page === "stats" ? 1 : 0.98 - Behavior on opacity { NumberAnimation { duration: 250; easing.type: Easing.OutQuart } } - Behavior on scale { NumberAnimation { duration: 250; easing.type: Easing.OutBack } } + readonly property int myIdx: 1 + property bool isCurrent: root.page === "stats" + width: parent.width; height: parent.height + + x: (myIdx - pageArea.animIdx) * width + visible: Math.abs(x) < width || isCurrent + DashStats { anchors.fill: parent localScale: root.localScale @@ -212,12 +223,13 @@ PanelWindow { } Item { - anchors.fill: parent - opacity: root.page === "kanban" ? 1 : 0 - visible: opacity > 0 - scale: root.page === "kanban" ? 1 : 0.98 - Behavior on opacity { NumberAnimation { duration: 250; easing.type: Easing.OutQuart } } - Behavior on scale { NumberAnimation { duration: 250; easing.type: Easing.OutBack } } + readonly property int myIdx: 2 + property bool isCurrent: root.page === "kanban" + width: parent.width; height: parent.height + + x: (myIdx - pageArea.animIdx) * width + visible: Math.abs(x) < width || isCurrent + KanbanBoard { anchors.fill: parent localScale: root.localScale @@ -225,12 +237,13 @@ PanelWindow { } Item { - anchors.fill: parent - opacity: root.page === "launcher" ? 1 : 0 - visible: opacity > 0 - scale: root.page === "launcher" ? 1 : 0.98 - Behavior on opacity { NumberAnimation { duration: 250; easing.type: Easing.OutQuart } } - Behavior on scale { NumberAnimation { duration: 250; easing.type: Easing.OutBack } } + readonly property int myIdx: 3 + property bool isCurrent: root.page === "launcher" + width: parent.width; height: parent.height + + x: (myIdx - pageArea.animIdx) * width + visible: Math.abs(x) < width || isCurrent + AppLauncher { anchors.fill: parent localScale: root.localScale @@ -238,12 +251,13 @@ PanelWindow { } Item { - anchors.fill: parent - opacity: root.page === "config" ? 1 : 0 - visible: opacity > 0 - scale: root.page === "config" ? 1 : 0.98 - Behavior on opacity { NumberAnimation { duration: 250; easing.type: Easing.OutQuart } } - Behavior on scale { NumberAnimation { duration: 250; easing.type: Easing.OutBack } } + readonly property int myIdx: 4 + property bool isCurrent: root.page === "config" + width: parent.width; height: parent.height + + x: (myIdx - pageArea.animIdx) * width + visible: Math.abs(x) < width || isCurrent + ShellConfig { anchors.fill: parent localScale: root.localScale diff --git a/src/popups/NetworkPopup.qml b/src/popups/NetworkPopup.qml index 62bb80b..6df004f 100644 --- a/src/popups/NetworkPopup.qml +++ b/src/popups/NetworkPopup.qml @@ -121,6 +121,16 @@ PanelWindow { // ── Tab page area ───────────────────────────────────────────────── Item { id: tabContent + clip: true + + property int pageIdx: Math.max(0, ["wifi", "bluetooth", "vpn", "hotspot"].indexOf(root.page)) + property real animIdx: pageIdx + + Behavior on animIdx { + enabled: tabContent.width > 0 + NumberAnimation { duration: 350; easing.type: Easing.OutExpo } + } + anchors { top: parent.top left: parent.left @@ -129,51 +139,55 @@ PanelWindow { } Loader { - anchors.fill: parent + readonly property int myIdx: 0 property bool isCurrent: root.page === "wifi" - active: isCurrent || opacity > 0 - opacity: isCurrent ? 1 : 0 - scale: isCurrent ? 1 : 0.98 - Behavior on opacity { NumberAnimation { duration: 250; easing.type: Easing.OutQuart } } - Behavior on scale { NumberAnimation { duration: 250; easing.type: Easing.OutBack } } + width: parent.width; height: parent.height + + x: (myIdx - tabContent.animIdx) * width + active: isCurrent || Math.abs(x) < width + visible: active + source: "WifiTab.qml" onLoaded: item.localScale = root.localScale } Loader { - anchors.fill: parent + readonly property int myIdx: 1 property bool isCurrent: root.page === "bluetooth" - active: isCurrent || opacity > 0 - opacity: isCurrent ? 1 : 0 - scale: isCurrent ? 1 : 0.98 - Behavior on opacity { NumberAnimation { duration: 250; easing.type: Easing.OutQuart } } - Behavior on scale { NumberAnimation { duration: 250; easing.type: Easing.OutBack } } + width: parent.width; height: parent.height + + x: (myIdx - tabContent.animIdx) * width + active: isCurrent || Math.abs(x) < width + visible: active + source: "BluetoothTab.qml" onLoaded: item.localScale = root.localScale } // VPN — WireGuard connections Loader { - anchors.fill: parent + readonly property int myIdx: 2 property bool isCurrent: root.page === "vpn" - active: isCurrent || opacity > 0 - opacity: isCurrent ? 1 : 0 - scale: isCurrent ? 1 : 0.98 - Behavior on opacity { NumberAnimation { duration: 250; easing.type: Easing.OutQuart } } - Behavior on scale { NumberAnimation { duration: 250; easing.type: Easing.OutBack } } + width: parent.width; height: parent.height + + x: (myIdx - tabContent.animIdx) * width + active: isCurrent || Math.abs(x) < width + visible: active + source: "VPNTab.qml" onLoaded: item.localScale = root.localScale } // Hotspot — virtual AP interface Loader { - anchors.fill: parent + readonly property int myIdx: 3 property bool isCurrent: root.page === "hotspot" - active: isCurrent || opacity > 0 - opacity: isCurrent ? 1 : 0 - scale: isCurrent ? 1 : 0.98 - Behavior on opacity { NumberAnimation { duration: 250; easing.type: Easing.OutQuart } } - Behavior on scale { NumberAnimation { duration: 250; easing.type: Easing.OutBack } } + width: parent.width; height: parent.height + + x: (myIdx - tabContent.animIdx) * width + active: isCurrent || Math.abs(x) < width + visible: active + source: "HotspotTab.qml" onLoaded: item.localScale = root.localScale } diff --git a/src/services/AudioControl.qml b/src/services/AudioControl.qml index 6d310ad..06cc960 100644 --- a/src/services/AudioControl.qml +++ b/src/services/AudioControl.qml @@ -59,14 +59,26 @@ Item { // ── Page content ────────────────────────────────────────────────────── Item { + id: contentArea width: parent.width - switcher.implicitWidth - parent.spacing - 1 - parent.spacing height: parent.height clip: true + property int pageIdx: Math.max(0, ["output", "input", "mixer"].indexOf(root.page)) + property real animIdx: pageIdx + + Behavior on animIdx { + enabled: contentArea.width > 0 + NumberAnimation { duration: 350; easing.type: Easing.OutExpo } + } + // Output PopupPage { - anchors.fill: parent - visible: root.page === "output" + readonly property int myIdx: 0 + width: parent.width; height: parent.height + + y: (myIdx - contentArea.animIdx) * height + visible: Math.abs(y) < height || root.page === "output" ChannelColumn { localScale: root.localScale @@ -94,8 +106,11 @@ Item { // Input PopupPage { - anchors.fill: parent - visible: root.page === "input" + readonly property int myIdx: 1 + width: parent.width; height: parent.height + + y: (myIdx - contentArea.animIdx) * height + visible: Math.abs(y) < height || root.page === "input" ChannelColumn { localScale: root.localScale @@ -117,8 +132,11 @@ Item { // Mixer PopupPage { - anchors.fill: parent - visible: root.page === "mixer" + readonly property int myIdx: 2 + width: parent.width; height: parent.height + + y: (myIdx - contentArea.animIdx) * height + visible: Math.abs(y) < height || root.page === "mixer" SectionLabel { text: "Output Devices" } diff --git a/src/services/home/ClockCard.qml b/src/services/home/ClockCard.qml index 35f8430..d8a6db4 100644 --- a/src/services/home/ClockCard.qml +++ b/src/services/home/ClockCard.qml @@ -228,10 +228,26 @@ StatCard { Item { anchors.fill: parent - // ── CLOCK ───────────────────────────────────────────────────────────── Item { + id: pagesContainer anchors { left: parent.left; right: parent.right; top: parent.top; bottom: tabs.top } - visible: root._mode === "clock" + clip: true + + property int pageIdx: Math.max(0, ["clock", "timer", "alarm", "stopwatch"].indexOf(root._mode)) + property real animIdx: pageIdx + + Behavior on animIdx { + enabled: pagesContainer.width > 0 + NumberAnimation { duration: 350; easing.type: Easing.OutExpo } + } + + // ── CLOCK ───────────────────────────────────────────────────────────── + Item { + readonly property int myIdx: 0 + width: parent.width; height: parent.height + + x: (myIdx - pagesContainer.animIdx) * width + visible: Math.abs(x) < width || root._mode === "clock" Row { anchors.centerIn: parent @@ -280,8 +296,11 @@ StatCard { // ── TIMER ───────────────────────────────────────────────────────────── Item { - anchors { left: parent.left; right: parent.right; top: parent.top; bottom: tabs.top } - visible: root._mode === "timer" + readonly property int myIdx: 1 + width: parent.width; height: parent.height + + x: (myIdx - pagesContainer.animIdx) * width + visible: Math.abs(x) < width || root._mode === "timer" // "+" / "x" toggle — top-right corner Item { @@ -512,8 +531,11 @@ StatCard { // ── ALARM ───────────────────────────────────────────────────────────── Item { - anchors { left: parent.left; right: parent.right; top: parent.top; bottom: tabs.top } - visible: root._mode === "alarm" + readonly property int myIdx: 2 + width: parent.width; height: parent.height + + x: (myIdx - pagesContainer.animIdx) * width + visible: Math.abs(x) < width || root._mode === "alarm" clip: true Item { @@ -703,8 +725,11 @@ StatCard { // ── STOPWATCH ───────────────────────────────────────────────────────── Item { - anchors { left: parent.left; right: parent.right; top: parent.top; bottom: tabs.top } - visible: root._mode === "stopwatch" + readonly property int myIdx: 3 + width: parent.width; height: parent.height + + x: (myIdx - pagesContainer.animIdx) * width + visible: Math.abs(x) < width || root._mode === "stopwatch" Column { anchors.centerIn: parent; spacing: Math.round(12 * localScale) @@ -764,6 +789,7 @@ StatCard { } } } + } // End of pagesContainer // ── Tab bar ─────────────────────────────────────────────────────────── TabSwitcher { From 7ed6b0ce17c4496b29c84268f96b949082be5103 Mon Sep 17 00:00:00 2001 From: Brainitech Date: Sun, 21 Jun 2026 14:42:21 +0530 Subject: [PATCH 3/4] Refactor: Unified Global Animation Engine and Live Settings Reload - Introduced a global `Anim` singleton (`src/theme/Anim.qml`) encapsulating all animation tokens (durations, easings, colors) to replace hardcoded values across the codebase. - Created `~/.config/Brain_Shell/src/user_data/animation_prefs.json` and tied it to a Quickshell `FileView` inside the `Anim` singleton, allowing users to toggle animation preferences (`slide`, `parallax`, `none`) and adjust duration speeds (`speed_multiplier`) at runtime. - Extensively refactored popup architectures (`ClockCard`, `AudioControl`, `NetworkPopup`, `Dashboard`) to utilize a single-slide engine state machine. - Integrated custom `parallax` transition behaviors leveraging synchronized `opacity` fading and slower positional displacement for inactive pages. - Resolved dynamic resizing overlap bugs in `Dashboard.qml` by unifying the tab transitions to a single, container-level `transitionProgress` mechanism instead of decoupled individual behaviors. - Eliminated `ReferenceErrors` across QML files by enforcing proper ID bindings in inline signals and fixing unresolved dependency paths. - Removed legacy `animIdx` multipliers and scattered `Animation` bindings globally. --- src/components/DiskBar.qml | 6 +- src/components/PopupSlide.qml | 4 +- src/components/ProfileButton.qml | 10 +- src/components/Speedometer.qml | 6 +- src/components/TabSwitcher.qml | 20 +- src/components/TimeInput.qml | 8 +- src/modules/Center/CenterContent.qml | 42 ++--- src/modules/Center/DiskPanel.qml | 2 +- src/modules/Left/LayoutDisplayer.qml | 10 +- src/modules/Left/Workspaces.qml | 18 +- src/modules/Right/Audio.qml | 6 +- src/modules/Right/Clock.qml | 2 +- src/modules/Right/Network.qml | 14 +- src/modules/Right/RightContent.qml | 6 +- src/modules/Right/SysTray.qml | 4 +- src/popups/ArchMenu.qml | 4 +- src/popups/AudioPopup.qml | 4 +- src/popups/BluetoothTab.qml | 76 ++++---- src/popups/ClipboardPopup.qml | 8 +- src/popups/Dashboard.qml | 104 ++++++----- src/popups/HistoryTab.qml | 32 ++-- src/popups/HotspotTab.qml | 8 +- src/popups/NetworkPopup.qml | 172 ++++++++++++++++-- src/popups/NotificationToast.qml | 14 +- src/popups/NotificationsPopup.qml | 6 +- src/popups/QuickControl.qml | 16 +- src/popups/ScreenRecOptionsPopup.qml | 6 +- src/popups/VPNTab.qml | 38 ++-- src/popups/WallpaperPopup.qml | 52 +++--- src/popups/WifiTab.qml | 58 +++--- src/qmldir | 1 + src/services/AppLauncher.qml | 12 +- src/services/AudioControl.qml | 148 ++++++++++++--- src/services/BatteryStatus.qml | 8 +- src/services/KanbanBoard.qml | 66 +++---- src/services/PowerMenu.qml | 2 +- src/services/config_tab/KeybindsPage.qml | 30 +-- src/services/home/CalendarCard.qml | 6 +- src/services/home/ClockCard.qml | 151 ++++++++++++--- src/services/home/PlayerCard.qml | 20 +- src/services/home/QuickSettings.qml | 30 +-- .../notifications/NotificationList.qml | 8 +- src/services/system/EnvyControl.qml | 4 +- src/state/Popups.qml | 4 +- src/theme/Anim.qml | 105 +++++++++++ src/theme/Metrics.qml | 2 - src/theme/Theme.qml | 1 - src/theme/qmldir | 1 + src/windows/Border.qml | 2 +- src/windows/ConfirmDialog.qml | 8 +- src/windows/TopBar.qml | 12 +- src/windows/UpdatePopup.qml | 26 +-- 52 files changed, 926 insertions(+), 477 deletions(-) create mode 100644 src/theme/Anim.qml diff --git a/src/components/DiskBar.qml b/src/components/DiskBar.qml index 63b8a96..1e4bb59 100644 --- a/src/components/DiskBar.qml +++ b/src/components/DiskBar.qml @@ -59,8 +59,8 @@ Item { radius: height / 2 color: root.barColor - Behavior on width { NumberAnimation { duration: 400; easing.type: Easing.OutCubic } } - Behavior on color { ColorAnimation { duration: 300 } } + Behavior on width { NumberAnimation { duration: Anim.slower; easing.type: Anim.outCubic} } + Behavior on color { ColorAnimation { duration: Anim.mediumSlow} } } } @@ -75,7 +75,7 @@ Item { color: root.barColor width: Math.round(28 * localScale) horizontalAlignment: Text.AlignRight - Behavior on color { ColorAnimation { duration: 300 } } + Behavior on color { ColorAnimation { duration: Anim.mediumSlow} } } // Size info — below the bar, aligned with bar diff --git a/src/components/PopupSlide.qml b/src/components/PopupSlide.qml index 233b66c..696b1aa 100644 --- a/src/components/PopupSlide.qml +++ b/src/components/PopupSlide.qml @@ -111,8 +111,8 @@ Item { y: root._effectiveOpen ? 0 : (root.edge === "top" ? -height : root.edge === "bottom" ? height : 0) - Behavior on x { NumberAnimation { duration: root.slideDuration; easing.type: Easing.OutCubic } } - Behavior on y { NumberAnimation { duration: root.slideDuration; easing.type: Easing.OutCubic } } + Behavior on x { NumberAnimation { duration: root.slideDuration; easing.type: Anim.outCubic} } + Behavior on y { NumberAnimation { duration: root.slideDuration; easing.type: Anim.outCubic} } // Self-hover tracking — automatically available to all popups HoverHandler { diff --git a/src/components/ProfileButton.qml b/src/components/ProfileButton.qml index 403a8ea..440c996 100644 --- a/src/components/ProfileButton.qml +++ b/src/components/ProfileButton.qml @@ -16,7 +16,7 @@ Item { implicitHeight: Math.round(28 * localScale) opacity: root.enabled ? 1 : 0.35 - Behavior on opacity { NumberAnimation { duration: 120 } } + Behavior on opacity { NumberAnimation { duration: Anim.color} } Rectangle { anchors.fill: parent @@ -30,8 +30,8 @@ Item { : Qt.rgba(1, 1, 1, 0.18) border.width: 1 - Behavior on color { ColorAnimation { duration: 120 } } - Behavior on border.color { ColorAnimation { duration: 120 } } + Behavior on color { ColorAnimation { duration: Anim.color} } + Behavior on border.color { ColorAnimation { duration: Anim.color} } } Row { @@ -45,7 +45,7 @@ Item { font.pixelSize: Math.round(12 * localScale) color: root.active ? Theme.background : Qt.rgba(1, 1, 1, 0.7) anchors.verticalCenter: parent.verticalCenter - Behavior on color { ColorAnimation { duration: 120 } } + Behavior on color { ColorAnimation { duration: Anim.color} } } Text { @@ -54,7 +54,7 @@ Item { font.weight: root.active ? Font.Medium : Font.Normal color: root.active ? Theme.background : Qt.rgba(1, 1, 1, 0.7) anchors.verticalCenter: parent.verticalCenter - Behavior on color { ColorAnimation { duration: 120 } } + Behavior on color { ColorAnimation { duration: Anim.color} } } } diff --git a/src/components/Speedometer.qml b/src/components/Speedometer.qml index 0eb0bec..24e22e0 100644 --- a/src/components/Speedometer.qml +++ b/src/components/Speedometer.qml @@ -31,7 +31,7 @@ Item { font.pixelSize: Math.max(7, Math.round(11 * root.size)) font.weight: Font.Medium color: root.active ? Qt.rgba(1,1,1,0.55) : Qt.rgba(1,1,1,0.2) - Behavior on color { ColorAnimation { duration: 200 } } + Behavior on color { ColorAnimation { duration: Anim.normal} } } // ── Arc canvas ──────────────────────────────────────────────────────────── @@ -103,7 +103,7 @@ Item { anchors.verticalCenterOffset: Math.round(6 * root.size) spacing: Math.round(2 * root.size) opacity: root.active ? 1 : 0 - Behavior on opacity { NumberAnimation { duration: 200 } } + Behavior on opacity { NumberAnimation { duration: Anim.normal} } Text { anchors.horizontalCenter: parent.horizontalCenter @@ -131,7 +131,7 @@ Item { font.weight: Font.Medium color: Qt.rgba(1, 1, 1, 0.25) opacity: root.active ? 0 : 1 - Behavior on opacity { NumberAnimation { duration: 200 } } + Behavior on opacity { NumberAnimation { duration: Anim.normal} } } } } diff --git a/src/components/TabSwitcher.qml b/src/components/TabSwitcher.qml index d65b0fd..ba40dca 100644 --- a/src/components/TabSwitcher.qml +++ b/src/components/TabSwitcher.qml @@ -88,13 +88,13 @@ Item { property real animIdx: activeIdx Behavior on animIdx { enabled: hMorph.isReady - NumberAnimation { duration: 350; easing.type: Easing.OutExpo } + NumberAnimation { duration: Anim.slow; easing.type: Anim.outExpo} } property real animWidth: targetWidth Behavior on animWidth { enabled: hMorph.isReady - NumberAnimation { duration: 350; easing.type: Easing.OutExpo } + NumberAnimation { duration: Anim.slow; easing.type: Anim.outExpo} } height: parent.height - Math.round(8 * localScale) @@ -132,7 +132,7 @@ Item { height: parent.height - Math.round(8 * localScale) radius: height / 2 color: !hTab.isActive && hHov.hovered ? Qt.rgba(1, 1, 1, 0.07) : "transparent" - Behavior on color { ColorAnimation { duration: 120 } } + Behavior on color { ColorAnimation { duration: Anim.color} } } // Icon + label @@ -148,7 +148,7 @@ Item { color: hTab.isActive ? Theme.background : (hHov.hovered ? Qt.rgba(1, 1, 1, 0.75) : Qt.rgba(1, 1, 1, 0.4)) - Behavior on color { ColorAnimation { duration: 120 } } + Behavior on color { ColorAnimation { duration: Anim.color} } } Text { @@ -161,7 +161,7 @@ Item { color: hTab.isActive ? Theme.background : (hHov.hovered ? Qt.rgba(1, 1, 1, 0.75) : Qt.rgba(1, 1, 1, 0.4)) - Behavior on color { ColorAnimation { duration: 120 } } + Behavior on color { ColorAnimation { duration: Anim.color} } } } @@ -222,7 +222,7 @@ Item { Behavior on animIdx { enabled: vMorph.isReady - NumberAnimation { duration: 350; easing.type: Easing.OutExpo } + NumberAnimation { duration: Anim.slow; easing.type: Anim.outExpo} } y: animIdx * (vContainer.tabH + vContainer.vSpacing) @@ -249,7 +249,7 @@ Item { anchors.fill: parent radius: Math.round(Theme.cornerRadius * 2 * localScale) color: !vTab.isActive && vHov.hovered ? Qt.rgba(1, 1, 1, 0.08) : "transparent" - Behavior on color { ColorAnimation { duration: 120 } } + Behavior on color { ColorAnimation { duration: Anim.color} } } // Icon-only (no label) @@ -259,7 +259,7 @@ Item { text: modelData.icon font.pixelSize: Math.round(16 * localScale) color: vTab.isActive ? Theme.background : Theme.text - Behavior on color { ColorAnimation { duration: 120 } } + Behavior on color { ColorAnimation { duration: Anim.color} } } // Icon + label row @@ -279,7 +279,7 @@ Item { color: vTab.isActive ? Theme.background : (vHov.hovered ? Qt.rgba(1, 1, 1, 0.80) : Qt.rgba(1, 1, 1, 0.42)) - Behavior on color { ColorAnimation { duration: 120 } } + Behavior on color { ColorAnimation { duration: Anim.color} } } Text { @@ -290,7 +290,7 @@ Item { color: vTab.isActive ? Theme.background : (vHov.hovered ? Qt.rgba(1, 1, 1, 0.80) : Qt.rgba(1, 1, 1, 0.42)) - Behavior on color { ColorAnimation { duration: 120 } } + Behavior on color { ColorAnimation { duration: Anim.color} } } } diff --git a/src/components/TimeInput.qml b/src/components/TimeInput.qml index 16171cf..346bbdb 100644 --- a/src/components/TimeInput.qml +++ b/src/components/TimeInput.qml @@ -47,7 +47,7 @@ Item { width: parent.width; height: Math.round(22 * localScale); radius: Math.round(6 * localScale) color: hUpH.hovered ? Qt.rgba(1,1,1,0.08) : Qt.rgba(1,1,1,0.04) border.color: Qt.rgba(1,1,1,0.08); border.width: 1 - Behavior on color { ColorAnimation { duration: 80 } } + Behavior on color { ColorAnimation { duration: Anim.superFast} } Text { anchors.centerIn: parent; text: "▲"; font.pixelSize: Math.round(9 * localScale); color: Qt.rgba(1,1,1,0.4) } HoverHandler { id: hUpH; cursorShape: Qt.PointingHandCursor } MouseArea { anchors.fill: parent; onClicked: root.incH() } @@ -78,7 +78,7 @@ Item { width: parent.width; height: Math.round(22 * localScale); radius: Math.round(6 * localScale) color: hDnH.hovered ? Qt.rgba(1,1,1,0.08) : Qt.rgba(1,1,1,0.04) border.color: Qt.rgba(1,1,1,0.08); border.width: 1 - Behavior on color { ColorAnimation { duration: 80 } } + Behavior on color { ColorAnimation { duration: Anim.superFast} } Text { anchors.centerIn: parent; text: "▼"; font.pixelSize: Math.round(9 * localScale); color: Qt.rgba(1,1,1,0.4) } HoverHandler { id: hDnH; cursorShape: Qt.PointingHandCursor } MouseArea { anchors.fill: parent; onClicked: root.decH() } @@ -111,7 +111,7 @@ Item { width: parent.width; height: Math.round(22 * localScale); radius: Math.round(6 * localScale) color: mUpH.hovered ? Qt.rgba(1,1,1,0.08) : Qt.rgba(1,1,1,0.04) border.color: Qt.rgba(1,1,1,0.08); border.width: 1 - Behavior on color { ColorAnimation { duration: 80 } } + Behavior on color { ColorAnimation { duration: Anim.superFast} } Text { anchors.centerIn: parent; text: "▲"; font.pixelSize: Math.round(9 * localScale); color: Qt.rgba(1,1,1,0.4) } HoverHandler { id: mUpH; cursorShape: Qt.PointingHandCursor } MouseArea { anchors.fill: parent; onClicked: root.incM() } @@ -142,7 +142,7 @@ Item { width: parent.width; height: Math.round(22 * localScale); radius: Math.round(6 * localScale) color: mDnH.hovered ? Qt.rgba(1,1,1,0.08) : Qt.rgba(1,1,1,0.04) border.color: Qt.rgba(1,1,1,0.08); border.width: 1 - Behavior on color { ColorAnimation { duration: 80 } } + Behavior on color { ColorAnimation { duration: Anim.superFast} } Text { anchors.centerIn: parent; text: "▼"; font.pixelSize: Math.round(9 * localScale); color: Qt.rgba(1,1,1,0.4) } HoverHandler { id: mDnH; cursorShape: Qt.PointingHandCursor } MouseArea { anchors.fill: parent; onClicked: root.decM() } diff --git a/src/modules/Center/CenterContent.qml b/src/modules/Center/CenterContent.qml index 1ea5a26..2a3bcef 100644 --- a/src/modules/Center/CenterContent.qml +++ b/src/modules/Center/CenterContent.qml @@ -211,7 +211,7 @@ Item { opacity: Popups.dashboardOpen ? 0 : 1 visible: opacity > 0 - Behavior on opacity { NumberAnimation { duration: 150 } } + Behavior on opacity { NumberAnimation { duration: Anim.mediumFast} } WheelHandler { acceptedDevices: PointerDevice.Mouse | PointerDevice.TouchPad @@ -242,7 +242,7 @@ Item { interactive: false Behavior on contentY { - NumberAnimation { duration: 300; easing.type: Easing.OutCubic } + NumberAnimation { duration: Anim.mediumSlow; easing.type: Anim.outCubic} } model: root._items @@ -360,7 +360,7 @@ Item { Theme.active.r, Theme.active.g, Theme.active.b, 0.28 + _amp * 0.72) Behavior on height { - NumberAnimation { duration: 50; easing.type: Easing.OutCubic } + NumberAnimation { duration: Anim.superFast; easing.type: Anim.outCubic} } } } @@ -384,7 +384,7 @@ Item { text: "󰔟" font.pixelSize: Math.round(16 * localScale) color: root.timerUrgent ? "#ff5555" : Theme.active - Behavior on color { ColorAnimation { duration: 200 } } + Behavior on color { ColorAnimation { duration: Anim.normal} } } // Time display — centered in remaining space @@ -403,15 +403,15 @@ Item { font.family: "JetBrains Mono" horizontalAlignment: Text.AlignHCenter color: root.timerUrgent ? "#ff5555" : Theme.text - Behavior on color { ColorAnimation { duration: 200 } } + Behavior on color { ColorAnimation { duration: Anim.normal} } // Blink when urgent — opacity pulses 1 → 0.25 → 1 SequentialAnimation on opacity { id: timerBlink running: root.timerUrgent loops: Animation.Infinite - NumberAnimation { to: 0.25; duration: 500; easing.type: Easing.InOutSine } - NumberAnimation { to: 1.0; duration: 500; easing.type: Easing.InOutSine } + NumberAnimation { to: 0.25; duration: Anim.verySlow; easing.type: Anim.inOutSine} + NumberAnimation { to: 1.0; duration: Anim.verySlow; easing.type: Anim.inOutSine} } // Snap back to full opacity when blink stops @@ -571,8 +571,8 @@ Item { ? Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.3) : Qt.rgba(1,1,1,0.1) border.width: 1 - Behavior on color { ColorAnimation { duration: 100 } } - Behavior on border.color { ColorAnimation { duration: 100 } } + Behavior on color { ColorAnimation { duration: Anim.fast} } + Behavior on border.color { ColorAnimation { duration: Anim.fast} } } Row { id: csRow @@ -584,7 +584,7 @@ Item { color: ScreenRecService.openStrip === "capture" ? Theme.active : Qt.rgba(1,1,1,0.7) anchors.verticalCenter: parent.verticalCenter - Behavior on color { ColorAnimation { duration: 100 } } + Behavior on color { ColorAnimation { duration: Anim.fast} } } Text { text: ScreenRecService.captureLabel @@ -592,7 +592,7 @@ Item { color: ScreenRecService.openStrip === "capture" ? Theme.active : Qt.rgba(1,1,1,0.7) anchors.verticalCenter: parent.verticalCenter - Behavior on color { ColorAnimation { duration: 100 } } + Behavior on color { ColorAnimation { duration: Anim.fast} } } Text { text: "▾"; font.pixelSize: Math.round(8 * localScale) @@ -633,8 +633,8 @@ Item { ? Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.3) : Qt.rgba(1,1,1,0.1) border.width: 1 - Behavior on color { ColorAnimation { duration: 100 } } - Behavior on border.color { ColorAnimation { duration: 100 } } + Behavior on color { ColorAnimation { duration: Anim.fast} } + Behavior on border.color { ColorAnimation { duration: Anim.fast} } } Row { id: asRow @@ -650,7 +650,7 @@ Item { color: ScreenRecService.openStrip === "audio" ? Theme.active : Qt.rgba(1,1,1,0.7) anchors.verticalCenter: parent.verticalCenter - Behavior on color { ColorAnimation { duration: 100 } } + Behavior on color { ColorAnimation { duration: Anim.fast} } } Text { text: "▾"; font.pixelSize: Math.round(8 * localScale) @@ -695,7 +695,7 @@ Item { color: recBtnH.hovered ? Qt.rgba(0.9, 0.2, 0.2, 0.85) : Qt.rgba(0.8, 0.1, 0.1, 0.7) - Behavior on color { ColorAnimation { duration: 100 } } + Behavior on color { ColorAnimation { duration: Anim.fast} } Row { anchors.centerIn: parent spacing: Math.round(5 * localScale) @@ -744,8 +744,8 @@ Item { SequentialAnimation on opacity { running: ScreenRecService.recording loops: Animation.Infinite - NumberAnimation { to: 0.25; duration: 600; easing.type: Easing.InOutSine } - NumberAnimation { to: 1.0; duration: 600; easing.type: Easing.InOutSine } + NumberAnimation { to: 0.25; duration: Anim.extraSlow; easing.type: Anim.inOutSine} + NumberAnimation { to: 1.0; duration: Anim.extraSlow; easing.type: Anim.inOutSine} } } @@ -790,7 +790,7 @@ Item { ? Qt.rgba(0.95, 0.3, 0.3, 0.30 + _amp * 0.70) : Qt.rgba(1, 1, 1, 0.10) Behavior on height { - NumberAnimation { duration: 50; easing.type: Easing.OutCubic } + NumberAnimation { duration: Anim.superFast; easing.type: Anim.outCubic} } } } @@ -814,7 +814,7 @@ Item { color: recDiscardH.hovered ? Qt.rgba(1, 1, 1, 0.12) : Qt.rgba(1, 1, 1, 0.05) - Behavior on color { ColorAnimation { duration: 100 } } + Behavior on color { ColorAnimation { duration: Anim.fast} } Text { anchors.centerIn: parent text: "󰩺" @@ -822,7 +822,7 @@ Item { color: recDiscardH.hovered ? Qt.rgba(1, 0.4, 0.4, 1.0) : Qt.rgba(1, 1, 1, 0.4) - Behavior on color { ColorAnimation { duration: 100 } } + Behavior on color { ColorAnimation { duration: Anim.fast} } } HoverHandler { id: recDiscardH } MouseArea { anchors.fill: parent; cursorShape: Qt.PointingHandCursor; onClicked: ScreenRecService.discardRecording() } @@ -835,7 +835,7 @@ Item { color: recStopH.hovered ? Qt.rgba(0.9, 0.2, 0.2, 0.55) : Qt.rgba(0.8, 0.1, 0.1, 0.32) - Behavior on color { ColorAnimation { duration: 100 } } + Behavior on color { ColorAnimation { duration: Anim.fast} } Text { anchors.centerIn: parent text: "⏹" diff --git a/src/modules/Center/DiskPanel.qml b/src/modules/Center/DiskPanel.qml index 68ca6e5..fce9bbf 100644 --- a/src/modules/Center/DiskPanel.qml +++ b/src/modules/Center/DiskPanel.qml @@ -68,7 +68,7 @@ Item { color: Qt.rgba(1, 1, 1, 0.5) opacity: vScroll.active ? 1.0 : 0.0 Behavior on opacity { - NumberAnimation { duration: 400; easing.type: Easing.InOutQuad } + NumberAnimation { duration: Anim.slower; easing.type: Anim.inOutQuad} } } diff --git a/src/modules/Left/LayoutDisplayer.qml b/src/modules/Left/LayoutDisplayer.qml index 8536265..f56a58c 100644 --- a/src/modules/Left/LayoutDisplayer.qml +++ b/src/modules/Left/LayoutDisplayer.qml @@ -136,7 +136,7 @@ Item { color: mouseArea.containsMouse ? Qt.rgba(1, 1, 1, 0.08) : "transparent" Behavior on color { - ColorAnimation { duration: 120 } + ColorAnimation { duration: Anim.color} } MouseArea { @@ -167,13 +167,13 @@ Item { SequentialAnimation { NumberAnimation { target: icon; property: "scale" - to: 0.6; duration: 80 - easing.type: Easing.InQuad + to: 0.6; duration: Anim.superFast + easing.type: Anim.inQuad } NumberAnimation { target: icon; property: "scale" - to: 1.0; duration: 120 - easing.type: Easing.OutBack + to: 1.0; duration: Anim.color + easing.type: Anim.outBack } } } diff --git a/src/modules/Left/Workspaces.qml b/src/modules/Left/Workspaces.qml index c403884..6d9267a 100644 --- a/src/modules/Left/Workspaces.qml +++ b/src/modules/Left/Workspaces.qml @@ -110,8 +110,8 @@ Rectangle { scale: root.isScratchpad ? 0.8 : 1 visible: opacity > 0 - Behavior on opacity { NumberAnimation { duration: 200 } } - Behavior on scale { NumberAnimation { duration: 200 } } + Behavior on opacity { NumberAnimation { duration: Anim.normal} } + Behavior on scale { NumberAnimation { duration: Anim.normal} } Repeater { model: 10 @@ -135,8 +135,8 @@ Rectangle { return Theme.wsEmpty } - Behavior on width { NumberAnimation { duration: 200; easing.type: Easing.OutBack } } - Behavior on color { ColorAnimation { duration: 200 } } + Behavior on width { NumberAnimation { duration: Anim.normal; easing.type: Anim.outBack} } + Behavior on color { ColorAnimation { duration: Anim.normal} } // --- Urgent pulse --- SequentialAnimation { @@ -147,15 +147,15 @@ Rectangle { target: dot property: "scale" to: 1.35 - duration: 400 - easing.type: Easing.InOutSine + duration: Anim.slower + easing.type: Anim.inOutSine } NumberAnimation { target: dot property: "scale" to: 1.0 - duration: 400 - easing.type: Easing.InOutSine + duration: Anim.slower + easing.type: Anim.inOutSine } } @@ -186,7 +186,7 @@ Rectangle { visible: opacity > 0 opacity: root.isScratchpad ? 1 : 0 - Behavior on opacity { NumberAnimation { duration: 200 } } + Behavior on opacity { NumberAnimation { duration: Anim.normal} } Text { anchors.centerIn: parent diff --git a/src/modules/Right/Audio.qml b/src/modules/Right/Audio.qml index 23a1efc..42c959e 100644 --- a/src/modules/Right/Audio.qml +++ b/src/modules/Right/Audio.qml @@ -43,7 +43,7 @@ Item { color: hov.hovered ? Theme.active : Theme.text font.pixelSize: Math.round(18 * localScale) anchors.verticalCenter: parent.verticalCenter - Behavior on color { ColorAnimation { duration: 120 } } + Behavior on color { ColorAnimation { duration: Anim.color} } } Item { @@ -53,7 +53,7 @@ Item { implicitHeight: pctText.implicitHeight clip: true anchors.verticalCenter: parent.verticalCenter - Behavior on implicitWidth { NumberAnimation { duration: Theme.animDuration; easing.type: Easing.InOutCubic } } + Behavior on implicitWidth { NumberAnimation { duration: Anim.transition; easing.type: Anim.inOutCubic} } Text { id: pctText @@ -61,7 +61,7 @@ Item { color: hov.hovered ? Theme.active : Theme.text font.pixelSize: Math.round(12 * localScale) anchors.verticalCenter: parent.verticalCenter - Behavior on color { ColorAnimation { duration: 120 } } + Behavior on color { ColorAnimation { duration: Anim.color} } } } } diff --git a/src/modules/Right/Clock.qml b/src/modules/Right/Clock.qml index e5616be..7d3b946 100644 --- a/src/modules/Right/Clock.qml +++ b/src/modules/Right/Clock.qml @@ -7,7 +7,7 @@ Text { text: Qt.formatDateTime(new Date(), "hh:mm") color: clockHov.hovered ? Theme.active : Theme.text - Behavior on color { ColorAnimation { duration: 120 } } + Behavior on color { ColorAnimation { duration: Anim.color} } font.bold: true anchors.verticalCenter: parent.verticalCenter font.pixelSize: Math.round(16 * localScale) diff --git a/src/modules/Right/Network.qml b/src/modules/Right/Network.qml index 7c797be..1394ff0 100644 --- a/src/modules/Right/Network.qml +++ b/src/modules/Right/Network.qml @@ -42,8 +42,8 @@ Item { property real _vpnOpacity: 1.0 SequentialAnimation on _vpnOpacity { running: ShellState.vpnConnecting; loops: Animation.Infinite - NumberAnimation { to: 0.20; duration: 500; easing.type: Easing.InOutSine } - NumberAnimation { to: 1.0; duration: 500; easing.type: Easing.InOutSine } + NumberAnimation { to: 0.20; duration: Anim.verySlow; easing.type: Anim.inOutSine} + NumberAnimation { to: 1.0; duration: Anim.verySlow; easing.type: Anim.inOutSine} } Connections { target: ShellState @@ -97,7 +97,7 @@ Item { color: root._netColor font.pixelSize: Math.round(16 * localScale) anchors.verticalCenter: parent.verticalCenter - Behavior on color { ColorAnimation { duration: 200 } } + Behavior on color { ColorAnimation { duration: Anim.normal} } MouseArea { anchors.fill: parent cursorShape: Qt.PointingHandCursor @@ -117,8 +117,8 @@ Item { anchors.verticalCenter: parent.verticalCenter opacity: root._vpnOpacity color: ShellState.vpnActive ? Theme.active : Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.70) - Behavior on color { ColorAnimation { duration: 200 } } - Behavior on opacity { NumberAnimation { duration: 80 } } + Behavior on color { ColorAnimation { duration: Anim.normal} } + Behavior on opacity { NumberAnimation { duration: Anim.superFast} } MouseArea { anchors.fill: parent cursorShape: Qt.PointingHandCursor @@ -137,7 +137,7 @@ Item { font.pixelSize: Math.round(14 * localScale) anchors.verticalCenter: parent.verticalCenter color: ShellState.btConnected ? (hov.hovered ? Theme.active : Theme.text) : Qt.rgba(1,1,1,0.32) - Behavior on color { ColorAnimation { duration: 200 } } + Behavior on color { ColorAnimation { duration: Anim.normal} } MouseArea { anchors.fill: parent cursorShape: Qt.PointingHandCursor @@ -156,7 +156,7 @@ Item { font.pixelSize: Math.round(14 * localScale) anchors.verticalCenter: parent.verticalCenter color: Theme.active - Behavior on color { ColorAnimation { duration: 200 } } + Behavior on color { ColorAnimation { duration: Anim.normal} } MouseArea { anchors.fill: parent cursorShape: Qt.PointingHandCursor diff --git a/src/modules/Right/RightContent.qml b/src/modules/Right/RightContent.qml index 4ebda25..49c9ebd 100644 --- a/src/modules/Right/RightContent.qml +++ b/src/modules/Right/RightContent.qml @@ -13,7 +13,7 @@ Item { implicitWidth: contentRow.implicitWidth //Behavior on implicitWidth { - // NumberAnimation { duration: Theme.animDuration; easing.type: Easing.InOutCubic } + // NumberAnimation { duration: Anim.transition; easing.type: Anim.inOutCubic} //} implicitHeight: parent.height @@ -28,7 +28,7 @@ Item { opacity: (Popups.notificationsOpen || Popups.networkOpen) ? 0 : 1 visible: opacity > 0 - Behavior on opacity { NumberAnimation { duration: 150 } } + Behavior on opacity { NumberAnimation { duration: Anim.mediumFast} } Network{ localScale: root.localScale @@ -64,6 +64,6 @@ Item { font.pixelSize: Math.round(14 * localScale) opacity: (Popups.notificationsOpen || Popups.networkOpen) ? 1 : 0 visible: opacity > 0 - Behavior on opacity { NumberAnimation { duration: 150 } } + Behavior on opacity { NumberAnimation { duration: Anim.mediumFast} } } } diff --git a/src/modules/Right/SysTray.qml b/src/modules/Right/SysTray.qml index 3ccbca6..f6a9051 100644 --- a/src/modules/Right/SysTray.qml +++ b/src/modules/Right/SysTray.qml @@ -23,8 +23,8 @@ RowLayout { Layout.preferredWidth: isOpen ? implicitWidth : 0 clip: true - Behavior on opacity { NumberAnimation { duration: Theme.animDuration; easing.type: Easing.OutCubic } } - Behavior on Layout.preferredWidth { NumberAnimation { duration: Theme.animDuration; easing.type: Easing.OutCubic } } + Behavior on opacity { NumberAnimation { duration: Anim.transition; easing.type: Anim.outCubic} } + Behavior on Layout.preferredWidth { NumberAnimation { duration: Anim.transition; easing.type: Anim.outCubic} } Repeater { model: SystemTray.items diff --git a/src/popups/ArchMenu.qml b/src/popups/ArchMenu.qml index 4180bd3..19ce6ba 100644 --- a/src/popups/ArchMenu.qml +++ b/src/popups/ArchMenu.qml @@ -74,8 +74,8 @@ PopupWindow { width: root.contentWidth + root.fw height: root.contentHeight + root.fh * 2 - Behavior on width { NumberAnimation { duration: Theme.animDuration; easing.type: Easing.InOutCubic } } - Behavior on height { NumberAnimation { duration: Theme.animDuration; easing.type: Easing.InOutCubic } } + Behavior on width { NumberAnimation { duration: Anim.transition; easing.type: Anim.inOutCubic} } + Behavior on height { NumberAnimation { duration: Anim.transition; easing.type: Anim.inOutCubic} } PopupShape { id: bg diff --git a/src/popups/AudioPopup.qml b/src/popups/AudioPopup.qml index 28e39bf..cca05f5 100644 --- a/src/popups/AudioPopup.qml +++ b/src/popups/AudioPopup.qml @@ -73,7 +73,7 @@ PopupWindow { Timer { id: audioResetTimer - interval: Theme.animDuration + 20 + interval: Anim.transition + 20 onTriggered: audioControl.reset() } @@ -86,7 +86,7 @@ PopupWindow { width: (root.pageWidths[audioControl.page] ?? root.maxWidth) height: root.popupHeight - Behavior on width { NumberAnimation { duration: Theme.animDuration; easing.type: Easing.InOutCubic } } + Behavior on width { NumberAnimation { duration: Anim.transition; easing.type: Anim.inOutCubic} } PopupShape { id: bg diff --git a/src/popups/BluetoothTab.qml b/src/popups/BluetoothTab.qml index 7b47a50..e2ec896 100644 --- a/src/popups/BluetoothTab.qml +++ b/src/popups/BluetoothTab.qml @@ -271,8 +271,8 @@ Item { running: root._scanning; loops: Animation.Infinite PauseAnimation { duration: index * 650 } ParallelAnimation { - NumberAnimation { property: "scale"; from: 0.08; to: 1.0; duration: 2200; easing.type: Easing.OutCubic } - NumberAnimation { property: "opacity"; from: 0.80; to: 0.0; duration: 2200; easing.type: Easing.OutQuad } + NumberAnimation { property: "scale"; from: 0.08; to: 1.0; duration: Anim.megaSlow; easing.type: Anim.outCubic} + NumberAnimation { property: "opacity"; from: 0.80; to: 0.0; duration: Anim.megaSlow; easing.type: Anim.outQuad} } } } @@ -282,8 +282,8 @@ Item { color: Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.55) SequentialAnimation on opacity { running: root._scanning; loops: Animation.Infinite - NumberAnimation { to: 0.20; duration: 700; easing.type: Easing.InOutSine } - NumberAnimation { to: 0.80; duration: 700; easing.type: Easing.InOutSine } + NumberAnimation { to: 0.20; duration: Anim.extraSlow; easing.type: Anim.inOutSine} + NumberAnimation { to: 0.80; duration: Anim.extraSlow; easing.type: Anim.inOutSine} } } } @@ -312,8 +312,8 @@ Item { ? Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.18) : dRow.isRemovePending ? Qt.rgba(248/255,113/255,113/255,0.22) : Qt.rgba(1,1,1,0.06) border.width: Math.max(1, Math.round(1 * localScale)) - Behavior on color { ColorAnimation { duration: 130 } } - Behavior on border.color { ColorAnimation { duration: 130 } } + Behavior on color { ColorAnimation { duration: Anim.color} } + Behavior on border.color { ColorAnimation { duration: Anim.color} } } Item { @@ -326,7 +326,7 @@ Item { text: root._glyph(dRow.device.iconType); font.pixelSize: Math.round(18 * localScale) color: dRow.isConnected ? Theme.active : (dRow.inAction || dRow.inRemove) ? Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.5) : Qt.rgba(1,1,1,0.32) - Behavior on color { ColorAnimation { duration: 150 } } + Behavior on color { ColorAnimation { duration: Anim.mediumFast} } } Column { @@ -357,8 +357,8 @@ Item { anchors.verticalCenter: parent.verticalCenter SequentialAnimation on opacity { running: dRow.inAction || dRow.inRemove; loops: Animation.Infinite - NumberAnimation { to: 0.15; duration: 450 } - NumberAnimation { to: 1.0; duration: 450 } + NumberAnimation { to: 0.15; duration: Anim.slower} + NumberAnimation { to: 1.0; duration: Anim.slower} } } @@ -370,11 +370,11 @@ Item { color: dRow.isConnected ? Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.14) : togH.hovered ? Qt.rgba(1,1,1,0.09) : Qt.rgba(1,1,1,0.04) border.color: dRow.isConnected ? Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.36) : Qt.rgba(1,1,1,0.11) border.width: Math.max(1, Math.round(1 * localScale)) - Behavior on color { ColorAnimation { duration: 120 } } + Behavior on color { ColorAnimation { duration: Anim.color} } Row { id: togContent; anchors.centerIn: parent; spacing: Math.round(7 * localScale) - Rectangle { width: Math.round(7 * localScale); height: Math.round(7 * localScale); radius: Math.round(4 * localScale); anchors.verticalCenter: parent.verticalCenter; color: dRow.isConnected ? Theme.active : Qt.rgba(1,1,1,0.25); Behavior on color { ColorAnimation { duration: 150 } } } - Text { text: dRow.isConnected ? "Connected" : "Connect"; font.pixelSize: Math.round(11 * localScale); font.weight: Font.Medium; anchors.verticalCenter: parent.verticalCenter; color: dRow.isConnected ? Theme.active : Qt.rgba(1,1,1,0.48); Behavior on color { ColorAnimation { duration: 120 } } } + Rectangle { width: Math.round(7 * localScale); height: Math.round(7 * localScale); radius: Math.round(4 * localScale); anchors.verticalCenter: parent.verticalCenter; color: dRow.isConnected ? Theme.active : Qt.rgba(1,1,1,0.25); Behavior on color { ColorAnimation { duration: Anim.mediumFast} } } + Text { text: dRow.isConnected ? "Connected" : "Connect"; font.pixelSize: Math.round(11 * localScale); font.weight: Font.Medium; anchors.verticalCenter: parent.verticalCenter; color: dRow.isConnected ? Theme.active : Qt.rgba(1,1,1,0.48); Behavior on color { ColorAnimation { duration: Anim.color} } } } HoverHandler { id: togH; cursorShape: Qt.PointingHandCursor } MouseArea { anchors.fill: parent; onClicked: dRow.isConnected ? root._disconnect(dRow.device.mac) : root._connect(dRow.device.mac) } @@ -384,8 +384,8 @@ Item { Item { visible: dRow.isPaired && !dRow.inAction && !dRow.inRemove width: Math.round(28 * localScale); height: Math.round(28 * localScale); anchors.verticalCenter: parent.verticalCenter - Rectangle { anchors.fill: parent; radius: Math.round(7 * localScale); color: rmH.hovered ? Qt.rgba(248/255,113/255,113/255,0.20) : dRow.isRemovePending ? Qt.rgba(248/255,113/255,113/255,0.12) : "transparent"; Behavior on color { ColorAnimation { duration: 100 } } } - Text { anchors.centerIn: parent; text: "󰗼"; font.pixelSize: Math.round(13 * localScale); color: (rmH.hovered || dRow.isRemovePending) ? "#f87171" : Qt.rgba(1,1,1,0.25); Behavior on color { ColorAnimation { duration: 100 } } } + Rectangle { anchors.fill: parent; radius: Math.round(7 * localScale); color: rmH.hovered ? Qt.rgba(248/255,113/255,113/255,0.20) : dRow.isRemovePending ? Qt.rgba(248/255,113/255,113/255,0.12) : "transparent"; Behavior on color { ColorAnimation { duration: Anim.fast} } } + Text { anchors.centerIn: parent; text: "󰗼"; font.pixelSize: Math.round(13 * localScale); color: (rmH.hovered || dRow.isRemovePending) ? "#f87171" : Qt.rgba(1,1,1,0.25); Behavior on color { ColorAnimation { duration: Anim.fast} } } HoverHandler { id: rmH; cursorShape: Qt.PointingHandCursor } MouseArea { anchors.fill: parent; onClicked: { root._pairingMac = ""; root._removeMac = dRow.isRemovePending ? "" : dRow.device.mac } } } @@ -400,7 +400,7 @@ Item { width: pairLbl.implicitWidth + Math.round(20 * localScale); height: Math.round(28 * localScale); radius: Math.round(8 * localScale) color: pairH.hovered ? Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.22) : Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.09) border.color: Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.35); border.width: Math.max(1, Math.round(1 * localScale)) - Behavior on color { ColorAnimation { duration: 100 } } + Behavior on color { ColorAnimation { duration: Anim.fast} } Text { id: pairLbl; anchors.centerIn: parent; text: "Pair"; font.pixelSize: Math.round(11 * localScale); font.weight: Font.Medium; color: Theme.active } HoverHandler { id: pairH; cursorShape: Qt.PointingHandCursor } MouseArea { anchors.fill: parent; onClicked: { root._removeMac = ""; root._pairingMac = ""; root._pair(dRow.device.mac, "") } } @@ -408,8 +408,8 @@ Item { Item { width: Math.round(24 * localScale); height: Math.round(28 * localScale); anchors.verticalCenter: parent?.verticalCenter - Rectangle { anchors.fill: parent; radius: Math.round(6 * localScale); color: pinH.hovered ? Qt.rgba(1,1,1,0.10) : dRow.isPairingOpen ? Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.12) : Qt.rgba(1,1,1,0.04); border.color: dRow.isPairingOpen ? Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.30) : Qt.rgba(1,1,1,0.09); border.width: Math.max(1, Math.round(1 * localScale)); Behavior on color { ColorAnimation { duration: 100 } } } - Text { anchors.centerIn: parent; text: "󰌾"; font.pixelSize: Math.round(12 * localScale); color: dRow.isPairingOpen ? Theme.active : pinH.hovered ? Qt.rgba(1,1,1,0.7) : Qt.rgba(1,1,1,0.28); Behavior on color { ColorAnimation { duration: 100 } } } + Rectangle { anchors.fill: parent; radius: Math.round(6 * localScale); color: pinH.hovered ? Qt.rgba(1,1,1,0.10) : dRow.isPairingOpen ? Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.12) : Qt.rgba(1,1,1,0.04); border.color: dRow.isPairingOpen ? Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.30) : Qt.rgba(1,1,1,0.09); border.width: Math.max(1, Math.round(1 * localScale)); Behavior on color { ColorAnimation { duration: Anim.fast} } } + Text { anchors.centerIn: parent; text: "󰌾"; font.pixelSize: Math.round(12 * localScale); color: dRow.isPairingOpen ? Theme.active : pinH.hovered ? Qt.rgba(1,1,1,0.7) : Qt.rgba(1,1,1,0.28); Behavior on color { ColorAnimation { duration: Anim.fast} } } HoverHandler { id: pinH; cursorShape: Qt.PointingHandCursor } MouseArea { anchors.fill: parent @@ -431,7 +431,7 @@ Item { anchors { top: baseRow.bottom; left: parent.left; right: parent.right } clip: true height: dRow.isRemovePending ? removeRow.implicitHeight + Math.round(16 * localScale) : dRow.isPairingOpen ? pinRow.implicitHeight + Math.round(16 * localScale) : 0 - Behavior on height { NumberAnimation { duration: 200; easing.type: Easing.OutCubic } } + Behavior on height { NumberAnimation { duration: Anim.normal; easing.type: Anim.outCubic} } // Remove confirmation Item { @@ -439,19 +439,19 @@ Item { anchors { left: parent.left; right: parent.right; top: parent.top; topMargin: Math.round(8 * localScale) } implicitHeight: Math.round(32 * localScale) opacity: dRow.isRemovePending ? 1 : 0 - Behavior on opacity { NumberAnimation { duration: 140 } } + Behavior on opacity { NumberAnimation { duration: Anim.color} } Rectangle { anchors { fill: parent; leftMargin: Math.round(8 * localScale); rightMargin: Math.round(8 * localScale) } radius: Math.round(8 * localScale); color: Qt.rgba(248/255,113/255,113/255,0.06); border.color: Qt.rgba(248/255,113/255,113/255,0.22); border.width: Math.max(1, Math.round(1 * localScale)) Row { anchors.centerIn: parent; spacing: Math.round(12 * localScale) Text { anchors.verticalCenter: parent.verticalCenter; text: "Remove this device?"; font.pixelSize: Math.round(11 * localScale); color: Qt.rgba(1,1,1,0.5) } - Rectangle { width: Math.round(58 * localScale); height: Math.round(24 * localScale); radius: Math.round(6 * localScale); color: cxH.hovered ? Qt.rgba(1,1,1,0.09) : Qt.rgba(1,1,1,0.04); Behavior on color { ColorAnimation { duration: 80 } } + Rectangle { width: Math.round(58 * localScale); height: Math.round(24 * localScale); radius: Math.round(6 * localScale); color: cxH.hovered ? Qt.rgba(1,1,1,0.09) : Qt.rgba(1,1,1,0.04); Behavior on color { ColorAnimation { duration: Anim.superFast} } Text { anchors.centerIn: parent; text: "Cancel"; font.pixelSize: Math.round(10 * localScale); color: Qt.rgba(1,1,1,0.42) } HoverHandler { id: cxH; cursorShape: Qt.PointingHandCursor } MouseArea { anchors.fill: parent; onClicked: root._removeMac = "" } } - Rectangle { width: Math.round(64 * localScale); height: Math.round(24 * localScale); radius: Math.round(6 * localScale); color: rxH.hovered ? Qt.rgba(248/255,113/255,113/255,0.40) : Qt.rgba(248/255,113/255,113/255,0.18); Behavior on color { ColorAnimation { duration: 80 } } + Rectangle { width: Math.round(64 * localScale); height: Math.round(24 * localScale); radius: Math.round(6 * localScale); color: rxH.hovered ? Qt.rgba(248/255,113/255,113/255,0.40) : Qt.rgba(248/255,113/255,113/255,0.18); Behavior on color { ColorAnimation { duration: Anim.superFast} } Text { anchors.centerIn: parent; text: "Remove"; font.pixelSize: Math.round(10 * localScale); font.weight: Font.Medium; color: "#f87171" } HoverHandler { id: rxH; cursorShape: Qt.PointingHandCursor } MouseArea { anchors.fill: parent; onClicked: root._remove(dRow.device.mac) } @@ -466,7 +466,7 @@ Item { anchors { left: parent.left; right: parent.right; top: parent.top; topMargin: Math.round(8 * localScale) } implicitHeight: pinCol.implicitHeight opacity: dRow.isPairingOpen ? 1 : 0 - Behavior on opacity { NumberAnimation { duration: 140 } } + Behavior on opacity { NumberAnimation { duration: Anim.color} } Column { id: pinCol anchors { left: parent.left; right: parent.right; leftMargin: Math.round(8 * localScale); rightMargin: Math.round(8 * localScale) } @@ -478,7 +478,7 @@ Item { width: parent.width - pairConfBtn.width - parent.spacing; height: Math.round(32 * localScale); radius: Math.round(8 * localScale) color: Qt.rgba(1,1,1,0.06) border.color: pinInput.activeFocus ? Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.55) : Qt.rgba(1,1,1,0.12) - border.width: Math.max(1, Math.round(1 * localScale)); Behavior on border.color { ColorAnimation { duration: 120 } } + border.width: Math.max(1, Math.round(1 * localScale)); Behavior on border.color { ColorAnimation { duration: Anim.color} } Text { anchors { left: parent.left; leftMargin: Math.round(10 * localScale); verticalCenter: parent.verticalCenter } text: "PIN (optional)…"; font.pixelSize: Math.round(12 * localScale); color: Qt.rgba(1,1,1,0.22); visible: pinInput.text === "" } TextInput { @@ -495,7 +495,7 @@ Item { id: pairConfBtn; width: Math.round(64 * localScale); height: Math.round(32 * localScale); radius: Math.round(8 * localScale) color: pcH.hovered ? Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.30) : Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.14) border.color: Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.42); border.width: Math.max(1, Math.round(1 * localScale)) - Behavior on color { ColorAnimation { duration: 100 } } + Behavior on color { ColorAnimation { duration: Anim.fast} } Text { anchors.centerIn: parent; text: "Pair"; font.pixelSize: Math.round(11 * localScale); font.weight: Font.Medium; color: Theme.active } HoverHandler { id: pcH; cursorShape: Qt.PointingHandCursor } MouseArea { anchors.fill: parent; onClicked: root._pair(dRow.device.mac, pinInput.text) } @@ -529,9 +529,9 @@ Item { width: Math.round(32 * localScale); height: Math.round(32 * localScale); radius: Math.round(8 * localScale) color: pwrH.hovered ? (root._btPowered ? Qt.rgba(248/255,113/255,113/255,0.18) : Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.18)) : Qt.rgba(1,1,1,0.04) border.color: root._btPowered ? Qt.rgba(1,1,1,0.10) : Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.30); border.width: Math.max(1, Math.round(1 * localScale)) - Behavior on color { ColorAnimation { duration: 120 } } - Behavior on border.color { ColorAnimation { duration: 120 } } - Text { anchors.centerIn: parent; text: "⏻"; font.pixelSize: Math.round(14 * localScale); color: root._btPowered ? (pwrH.hovered ? "#f87171" : Qt.rgba(1,1,1,0.32)) : Theme.active; Behavior on color { ColorAnimation { duration: 120 } } } + Behavior on color { ColorAnimation { duration: Anim.color} } + Behavior on border.color { ColorAnimation { duration: Anim.color} } + Text { anchors.centerIn: parent; text: "⏻"; font.pixelSize: Math.round(14 * localScale); color: root._btPowered ? (pwrH.hovered ? "#f87171" : Qt.rgba(1,1,1,0.32)) : Theme.active; Behavior on color { ColorAnimation { duration: Anim.color} } } HoverHandler { id: pwrH; cursorShape: Qt.PointingHandCursor } MouseArea { anchors.fill: parent; onClicked: root._setPower(!root._btPowered) } } @@ -541,8 +541,8 @@ Item { width: Math.round(32 * localScale); height: Math.round(32 * localScale); radius: Math.round(8 * localScale) color: settH.hovered ? Qt.rgba(1,1,1,0.09) : Qt.rgba(1,1,1,0.03) border.color: Qt.rgba(1,1,1,0.10); border.width: Math.max(1, Math.round(1 * localScale)) - Behavior on color { ColorAnimation { duration: 100 } } - Text { anchors.centerIn: parent; text: "󰒓"; font.pixelSize: Math.round(14 * localScale); color: settH.hovered ? Qt.rgba(1,1,1,0.75) : Qt.rgba(1,1,1,0.30); Behavior on color { ColorAnimation { duration: 100 } } } + Behavior on color { ColorAnimation { duration: Anim.fast} } + Text { anchors.centerIn: parent; text: "󰒓"; font.pixelSize: Math.round(14 * localScale); color: settH.hovered ? Qt.rgba(1,1,1,0.75) : Qt.rgba(1,1,1,0.30); Behavior on color { ColorAnimation { duration: Anim.fast} } } HoverHandler { id: settH; cursorShape: Qt.PointingHandCursor } MouseArea { anchors.fill: parent; onClicked: { bluemanProc.running = false; bluemanProc.running = true } } } @@ -551,22 +551,22 @@ Item { Rectangle { width: scanRow.implicitWidth + Math.round(20 * localScale); height: Math.round(30 * localScale); radius: Math.round(15 * localScale) opacity: root._btPowered ? 1.0 : 0.35 - Behavior on opacity { NumberAnimation { duration: 200 } } + Behavior on opacity { NumberAnimation { duration: Anim.normal} } color: root._scanning ? Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.18) : scanH.hovered && root._btPowered ? Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.12) : Qt.rgba(1,1,1,0.05) border.color: root._scanning ? Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.48) : Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.28); border.width: Math.max(1, Math.round(1 * localScale)) - Behavior on color { ColorAnimation { duration: 130 } } + Behavior on color { ColorAnimation { duration: Anim.color} } Row { id: scanRow; anchors.centerIn: parent; spacing: Math.round(7 * localScale) Rectangle { width: Math.round(7 * localScale); height: Math.round(7 * localScale); radius: Math.round(4 * localScale); anchors.verticalCenter: parent.verticalCenter color: root._scanning ? Theme.active : Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.55) - Behavior on color { ColorAnimation { duration: 120 } } + Behavior on color { ColorAnimation { duration: Anim.color} } SequentialAnimation on opacity { - running: root._scanning; loops: Animation.Infinite; NumberAnimation { to: 0.15; duration: 450 } - NumberAnimation { to: 1.0; duration: 450 } + running: root._scanning; loops: Animation.Infinite; NumberAnimation { to: 0.15; duration: Anim.slower} + NumberAnimation { to: 1.0; duration: Anim.slower} } } - Text { anchors.verticalCenter: parent.verticalCenter; text: root._scanning ? "Stop" : "Scan"; font.pixelSize: Math.round(12 * localScale); font.weight: Font.Medium; color: root._scanning ? Theme.active : Qt.rgba(1,1,1,0.6); Behavior on color { ColorAnimation { duration: 130 } } } + Text { anchors.verticalCenter: parent.verticalCenter; text: root._scanning ? "Stop" : "Scan"; font.pixelSize: Math.round(12 * localScale); font.weight: Font.Medium; color: root._scanning ? Theme.active : Qt.rgba(1,1,1,0.6); Behavior on color { ColorAnimation { duration: Anim.color} } } } HoverHandler { id: scanH; cursorShape: root._btPowered ? Qt.PointingHandCursor : Qt.ArrowCursor } MouseArea { anchors.fill: parent; onClicked: if (root._btPowered) root._startScan() } @@ -580,7 +580,7 @@ Item { // Scan animation strip Item { width: parent.width; height: root._scanning ? Math.round(90 * localScale) : 0; clip: true - Behavior on height { NumberAnimation { duration: 250; easing.type: Easing.OutCubic } } + Behavior on height { NumberAnimation { duration: Anim.mediumSlow; easing.type: Anim.outCubic} } ScanRings { anchors.centerIn: parent; width: Math.round(52 * localScale); height: Math.round(52 * localScale); centerGlyph: "󰂯"; glyphSize: Math.round(14 * localScale) } Text { anchors { horizontalCenter: parent.horizontalCenter; bottom: parent.bottom; bottomMargin: Math.round(6 * localScale) } text: "Scanning for devices…"; font.pixelSize: Math.round(10 * localScale); color: Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.50) } @@ -591,7 +591,7 @@ Item { height: parent.height - Math.round(49 * localScale) - (root._scanning ? Math.round(90 * localScale) : 0) contentWidth: width; contentHeight: devCol.height clip: true; boundsBehavior: Flickable.StopAtBounds - Behavior on height { NumberAnimation { duration: 250; easing.type: Easing.OutCubic } } + Behavior on height { NumberAnimation { duration: Anim.mediumSlow; easing.type: Anim.outCubic} } Column { id: devCol; width: parent.width; height: implicitHeight; spacing: Math.round(4 * localScale) @@ -647,7 +647,7 @@ Item { width: enableRow.implicitWidth + Math.round(24 * localScale); height: Math.round(34 * localScale); radius: Math.round(17 * localScale) color: enableH.hovered ? Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.22) : Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.12) border.color: Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.40); border.width: Math.max(1, Math.round(1 * localScale)) - Behavior on color { ColorAnimation { duration: 120 } } + Behavior on color { ColorAnimation { duration: Anim.color} } Row { id: enableRow; anchors.centerIn: parent; spacing: Math.round(8 * localScale) Text { anchors.verticalCenter: parent.verticalCenter; text: "󰂯"; font.pixelSize: Math.round(14 * localScale); color: Theme.active } Text { anchors.verticalCenter: parent.verticalCenter; text: "Turn On"; font.pixelSize: Math.round(12 * localScale); font.weight: Font.Medium; color: Theme.active } diff --git a/src/popups/ClipboardPopup.qml b/src/popups/ClipboardPopup.qml index 27d6bfd..cb72f86 100644 --- a/src/popups/ClipboardPopup.qml +++ b/src/popups/ClipboardPopup.qml @@ -54,7 +54,7 @@ PanelWindow { Timer { id: closeTimer - interval: Theme.animDuration + 20 + interval: Anim.transition + 20 onTriggered: { if (!Popups.clipboardOpen) root.windowVisible = false @@ -77,8 +77,8 @@ PanelWindow { width: Popups.clipboardOpen ? root.popupWidth + root.fw : 0 height: Popups.clipboardOpen ? root.popupHeight + root.fh : 0 - Behavior on width { NumberAnimation { duration: Theme.animDuration; easing.type: Easing.InOutCubic } } - Behavior on height { NumberAnimation { duration: Theme.animDuration; easing.type: Easing.InOutCubic } } + Behavior on width { NumberAnimation { duration: Anim.transition; easing.type: Anim.inOutCubic} } + Behavior on height { NumberAnimation { duration: Anim.transition; easing.type: Anim.inOutCubic} } MouseArea { anchors.fill: parent @@ -106,7 +106,7 @@ PanelWindow { opacity: Popups.clipboardOpen ? 1 : 0 Behavior on opacity { NumberAnimation { - duration: Popups.clipboardOpen ? Theme.animDuration * 0.5 : Theme.animDuration * 0.15 + duration: Popups.clipboardOpen ? Anim.transition * 0.5 : Anim.transition * 0.15 } } diff --git a/src/popups/Dashboard.qml b/src/popups/Dashboard.qml index ac0fef9..2add2ce 100644 --- a/src/popups/Dashboard.qml +++ b/src/popups/Dashboard.qml @@ -28,7 +28,7 @@ PanelWindow { readonly property int fw: Math.round(Theme.notchRadius * localScale) readonly property int fh: Math.round(Theme.notchRadius * localScale) - readonly property int animDuration: Theme.animDuration + readonly property int animDuration: Anim.transition property string page: Popups.dashboardPage @@ -118,8 +118,8 @@ PanelWindow { ? Math.min(Theme.dashboardHeight * localScale, (screen ? screen.height : 1080) * 0.90) : Theme.notchHeight / 2 - Behavior on width { NumberAnimation { duration: root.animDuration; easing.type: Easing.InOutCubic } } - Behavior on height { NumberAnimation { duration: root.animDuration; easing.type: Easing.InOutCubic } } + Behavior on width { NumberAnimation { duration: root.animDuration; easing.type: Anim.inOutCubic} } + Behavior on height { NumberAnimation { duration: root.animDuration; easing.type: Anim.inOutCubic} } MouseArea { anchors.fill: parent @@ -187,77 +187,93 @@ PanelWindow { height: parent.height - tabBar.height property int pageIdx: Math.max(0, ["home", "stats", "kanban", "launcher", "config"].indexOf(root.page)) - property real animIdx: pageIdx - Behavior on animIdx { - enabled: pageArea.width > 0 - NumberAnimation { duration: 350; easing.type: Easing.OutExpo } + property int oldIdx: 0 + property int newIdx: pageIdx + property real progress: 1.0 + + NumberAnimation { + id: progressAnim + target: pageArea + property: "progress" + from: 0.0 + to: 1.0 + duration: Anim.style === "none" ? 0 : Anim.slow + easing.type: Anim.outExpo + } + + onPageIdxChanged: { + oldIdx = newIdx; + newIdx = pageIdx; + progressAnim.restart(); } - Item { - readonly property int myIdx: 0 - property bool isCurrent: root.page === "home" + component SlidePage: Item { + property int myIdx + property bool isCurrent: myIdx === pageArea.pageIdx + property real parallaxFactor: Anim.style === "parallax" ? 0.3 : 1.0 + + property bool isIncoming: myIdx === pageArea.newIdx + property bool isOutgoing: myIdx === pageArea.oldIdx + property int slideDir: pageArea.newIdx > pageArea.oldIdx ? 1 : -1 + width: parent.width; height: parent.height - x: (myIdx - pageArea.animIdx) * width - visible: Math.abs(x) < width || isCurrent + x: { + if (Anim.style === "none") return 0; + if (isIncoming) { + return slideDir * root.scaledPageWidth * (1.0 - pageArea.progress); + } else if (isOutgoing) { + return -slideDir * root.scaledPageWidth * parallaxFactor * pageArea.progress; + } else { + return myIdx < pageArea.newIdx ? -root.scaledPageWidth : root.scaledPageWidth; + } + } + + opacity: { + if (Anim.style !== "parallax") return 1.0; + if (isIncoming) return pageArea.progress; + if (isOutgoing) return 1.0 - pageArea.progress; + return 0.0; + } + + visible: isCurrent || (isOutgoing && pageArea.progress < 1.0) + } + SlidePage { + myIdx: 0 DashHome { anchors.fill: parent localScale: root.localScale } } - Item { - readonly property int myIdx: 1 - property bool isCurrent: root.page === "stats" - width: parent.width; height: parent.height - - x: (myIdx - pageArea.animIdx) * width - visible: Math.abs(x) < width || isCurrent - + SlidePage { + myIdx: 1 DashStats { anchors.fill: parent localScale: root.localScale } } - Item { - readonly property int myIdx: 2 - property bool isCurrent: root.page === "kanban" - width: parent.width; height: parent.height - - x: (myIdx - pageArea.animIdx) * width - visible: Math.abs(x) < width || isCurrent - + SlidePage { + myIdx: 2 KanbanBoard { anchors.fill: parent localScale: root.localScale } } - Item { - readonly property int myIdx: 3 - property bool isCurrent: root.page === "launcher" - width: parent.width; height: parent.height - - x: (myIdx - pageArea.animIdx) * width - visible: Math.abs(x) < width || isCurrent - + SlidePage { + myIdx: 3 AppLauncher { anchors.fill: parent localScale: root.localScale } } - Item { - readonly property int myIdx: 4 - property bool isCurrent: root.page === "config" - width: parent.width; height: parent.height - - x: (myIdx - pageArea.animIdx) * width - visible: Math.abs(x) < width || isCurrent - + SlidePage { + myIdx: 4 ShellConfig { anchors.fill: parent localScale: root.localScale diff --git a/src/popups/HistoryTab.qml b/src/popups/HistoryTab.qml index 8537663..6f65557 100644 --- a/src/popups/HistoryTab.qml +++ b/src/popups/HistoryTab.qml @@ -77,8 +77,8 @@ Item { : Qt.rgba(1, 1, 1, 0.04) border.color: Qt.rgba(248/255, 113/255, 113/255, clearH.hovered ? 0.38 : 0.12) border.width: 1 - Behavior on color { ColorAnimation { duration: 150 } } - Behavior on border.color { ColorAnimation { duration: 150 } } + Behavior on color { ColorAnimation { duration: Anim.mediumFast} } + Behavior on border.color { ColorAnimation { duration: Anim.mediumFast} } Row { id: clearRow @@ -119,8 +119,8 @@ Item { text: "○"; font.pixelSize: 22; color: Theme.active SequentialAnimation on opacity { running: parent.visible; loops: Animation.Infinite - NumberAnimation { to: 0.15; duration: 500 } - NumberAnimation { to: 1.0; duration: 500 } + NumberAnimation { to: 0.15; duration: Anim.verySlow} + NumberAnimation { to: 1.0; duration: Anim.verySlow} } } Text { @@ -173,7 +173,7 @@ Item { // Smooth repositioning when items are removed displaced: Transition { - NumberAnimation { property: "y"; duration: 220; easing.type: Easing.OutCubic } + NumberAnimation { property: "y"; duration: Anim.normal; easing.type: Anim.outCubic} } Keys.onPressed: (event) => { @@ -289,8 +289,8 @@ component ClipRow: Item { opacity: _removing ? 0 : 1 clip: true - Behavior on height { NumberAnimation { duration: 210; easing.type: Easing.InCubic } } - Behavior on opacity { NumberAnimation { duration: 160 } } + Behavior on height { NumberAnimation { duration: Anim.normal; easing.type: Anim.inCubic} } + Behavior on opacity { NumberAnimation { duration: Anim.mediumFast} } // ── Card ────────────────────────────────────────────────────────────────── Rectangle { @@ -311,8 +311,8 @@ component ClipRow: Item { : rHov.hovered ? Qt.rgba(1, 1, 1, 0.13) : Qt.rgba(1, 1, 1, 0.065) border.width: 1 - Behavior on color { ColorAnimation { duration: 140 } } - Behavior on border.color { ColorAnimation { duration: 140 } } + Behavior on color { ColorAnimation { duration: Anim.color} } + Behavior on border.color { ColorAnimation { duration: Anim.color} } // ── Inner layout ────────────────────────────────────────────────────── Row { @@ -352,7 +352,7 @@ component ClipRow: Item { smooth: true asynchronous: true opacity: thumbImg.status === Image.Ready ? 1.0 : 0.0 - Behavior on opacity { NumberAnimation { duration: 280; easing.type: Easing.OutCubic } } + Behavior on opacity { NumberAnimation { duration: Anim.mediumSlow; easing.type: Anim.outCubic} } } // Placeholder while loading / no path yet @@ -408,7 +408,7 @@ component ClipRow: Item { anchors.verticalCenter: parent.verticalCenter spacing: 2 opacity: rHov.hovered || row.highlighted ? 1 : 0 - Behavior on opacity { NumberAnimation { duration: 160 } } + Behavior on opacity { NumberAnimation { duration: Anim.mediumFast} } // Copy ActionBtn { @@ -462,7 +462,7 @@ component ClipRow: Item { } scale: row.isPinned ? 1.0 : 0.0 - Behavior on scale { NumberAnimation { duration: 220; easing.type: Easing.OutBack } } + Behavior on scale { NumberAnimation { duration: Anim.normal; easing.type: Anim.outBack} } } } @@ -514,15 +514,15 @@ component ActionBtn: Rectangle { ? Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.22) : (aH.hovered ? Qt.rgba(1, 1, 1, 0.11) : "transparent") - Behavior on color { ColorAnimation { duration: 110 } } + Behavior on color { ColorAnimation { duration: Anim.color} } // Subtle scale-up on hover transform: Scale { origin.x: 13; origin.y: 13 xScale: aH.hovered ? 1.10 : 1.0 yScale: aH.hovered ? 1.10 : 1.0 - Behavior on xScale { NumberAnimation { duration: 130; easing.type: Easing.OutCubic } } - Behavior on yScale { NumberAnimation { duration: 130; easing.type: Easing.OutCubic } } + Behavior on xScale { NumberAnimation { duration: Anim.color; easing.type: Anim.outCubic} } + Behavior on yScale { NumberAnimation { duration: Anim.color; easing.type: Anim.outCubic} } } Text { @@ -534,7 +534,7 @@ component ActionBtn: Rectangle { : ab.active ? Theme.active : (aH.hovered ? Qt.rgba(1, 1, 1, 0.88) : Qt.rgba(1, 1, 1, 0.38)) - Behavior on color { ColorAnimation { duration: 110 } } + Behavior on color { ColorAnimation { duration: Anim.color} } } HoverHandler { id: aH; cursorShape: Qt.PointingHandCursor } diff --git a/src/popups/HotspotTab.qml b/src/popups/HotspotTab.qml index 1b210e6..b2b5cc1 100644 --- a/src/popups/HotspotTab.qml +++ b/src/popups/HotspotTab.qml @@ -88,7 +88,7 @@ Item { anchors { left: parent.left; leftMargin: Math.round(76 * localScale); verticalCenter: parent.verticalCenter } spacing: Math.round(6 * localScale) - Rectangle { width: Math.round(7 * localScale); height: Math.round(7 * localScale); radius: Math.round(4 * localScale); anchors.verticalCenter: parent.verticalCenter; color: ShellState.hotspot ? Theme.active : Qt.rgba(1,1,1,0.22); Behavior on color { ColorAnimation { duration: 200 } } } + Rectangle { width: Math.round(7 * localScale); height: Math.round(7 * localScale); radius: Math.round(4 * localScale); anchors.verticalCenter: parent.verticalCenter; color: ShellState.hotspot ? Theme.active : Qt.rgba(1,1,1,0.22); Behavior on color { ColorAnimation { duration: Anim.normal} } } Text { anchors.verticalCenter: parent.verticalCenter; text: ShellState.hotspot ? "Active" : "Inactive"; font.pixelSize: Math.round(11 * localScale); color: ShellState.hotspot ? Theme.active : Qt.rgba(1,1,1,0.32) } } } @@ -140,7 +140,7 @@ Item { height: Math.round(28 * localScale); radius: Math.round(7 * localScale) color: ssidInput.activeFocus ? Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.08) : Qt.rgba(1,1,1,0.05) border.color: ssidInput.activeFocus ? Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.45) : Qt.rgba(1,1,1,0.11); border.width: Math.max(1, Math.round(1 * localScale)) - Behavior on border.color { ColorAnimation { duration: 120 } } + Behavior on border.color { ColorAnimation { duration: Anim.color} } TextInput { id: ssidInput; anchors { fill: parent; leftMargin: Math.round(10 * localScale); rightMargin: Math.round(10 * localScale) } verticalAlignment: TextInput.AlignVCenter; color: Theme.text; font.pixelSize: Math.round(12 * localScale) @@ -162,7 +162,7 @@ Item { height: Math.round(28 * localScale); radius: Math.round(7 * localScale) color: passInput.activeFocus ? Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.08) : Qt.rgba(1,1,1,0.05) border.color: passInput.activeFocus ? Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.45) : Qt.rgba(1,1,1,0.11); border.width: Math.max(1, Math.round(1 * localScale)) - Behavior on border.color { ColorAnimation { duration: 120 } } + Behavior on border.color { ColorAnimation { duration: Anim.color} } TextInput { id: passInput; anchors { fill: parent; leftMargin: Math.round(10 * localScale); rightMargin: Math.round(10 * localScale) } verticalAlignment: TextInput.AlignVCenter; color: Theme.text; font.pixelSize: Math.round(12 * localScale) @@ -193,7 +193,7 @@ Item { ? Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.28) : Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.14) border.color: Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.40); border.width: Math.max(1, Math.round(1 * localScale)) - Behavior on color { ColorAnimation { duration: 100 } } + Behavior on color { ColorAnimation { duration: Anim.fast} } Text { anchors.centerIn: parent; text: "Save"; font.pixelSize: Math.round(12 * localScale); font.weight: Font.Medium; color: Theme.active } HoverHandler { id: saveH; cursorShape: Qt.PointingHandCursor } MouseArea { anchors.fill: parent; onClicked: root._save() } diff --git a/src/popups/NetworkPopup.qml b/src/popups/NetworkPopup.qml index 6df004f..d38469d 100644 --- a/src/popups/NetworkPopup.qml +++ b/src/popups/NetworkPopup.qml @@ -67,7 +67,7 @@ PanelWindow { Timer { id: closeTimer - interval: Theme.animDuration + 20 + interval: Anim.transition + 20 onTriggered: { if (!Popups.networkOpen) root.windowVisible = false } } @@ -85,8 +85,8 @@ PanelWindow { height: Popups.networkOpen ? root.popupHeight : 0 - Behavior on width { NumberAnimation { duration: Theme.animDuration; easing.type: Easing.InOutCubic } } - Behavior on height { NumberAnimation { duration: Theme.animDuration; easing.type: Easing.InOutCubic } } + Behavior on width { NumberAnimation { duration: Anim.transition; easing.type: Anim.inOutCubic} } + Behavior on height { NumberAnimation { duration: Anim.transition; easing.type: Anim.inOutCubic} } PopupShape { anchors.fill: parent @@ -113,8 +113,8 @@ PanelWindow { Behavior on opacity { NumberAnimation { duration: Popups.networkOpen - ? Theme.animDuration * 0.5 - : Theme.animDuration * 0.15 + ? Anim.transition * 0.5 + : Anim.transition * 0.15 } } @@ -124,12 +124,6 @@ PanelWindow { clip: true property int pageIdx: Math.max(0, ["wifi", "bluetooth", "vpn", "hotspot"].indexOf(root.page)) - property real animIdx: pageIdx - - Behavior on animIdx { - enabled: tabContent.width > 0 - NumberAnimation { duration: 350; easing.type: Easing.OutExpo } - } anchors { top: parent.top @@ -139,12 +133,47 @@ PanelWindow { } Loader { + id: tabWifi readonly property int myIdx: 0 property bool isCurrent: root.page === "wifi" + property bool wasCurrent: false + property real parallaxFactor: Anim.style === "parallax" ? 0.3 : 1.0 + onIsCurrentChanged: { + if (isCurrent) wasCurrent = false; + else if (Anim.style === "none") wasCurrent = false; + else wasCurrent = true; + } + width: parent.width; height: parent.height - x: (myIdx - tabContent.animIdx) * width - active: isCurrent || Math.abs(x) < width + property real targetX: { + if (Anim.style === "none") return 0; + if (isCurrent) return 0; + if (myIdx < tabContent.pageIdx) return -width * parallaxFactor; + return width; + } + + x: targetX + Behavior on x { + enabled: Anim.style !== "none" + NumberAnimation { + duration: Anim.slow; easing.type: Anim.outExpo + onRunningChanged: { if (!running && !tabWifi.isCurrent) tabWifi.wasCurrent = false; } + } + } + + property real targetOpacity: { + if (Anim.style !== "parallax") return 1.0; + if (isCurrent) return 1.0; + return 0.0; + } + opacity: targetOpacity + Behavior on opacity { + enabled: Anim.style === "parallax" + NumberAnimation { duration: Anim.slow; easing.type: Anim.outExpo } + } + + active: isCurrent || wasCurrent visible: active source: "WifiTab.qml" @@ -152,12 +181,47 @@ PanelWindow { } Loader { + id: tabBluetooth readonly property int myIdx: 1 property bool isCurrent: root.page === "bluetooth" + property bool wasCurrent: false + property real parallaxFactor: Anim.style === "parallax" ? 0.3 : 1.0 + onIsCurrentChanged: { + if (isCurrent) wasCurrent = false; + else if (Anim.style === "none") wasCurrent = false; + else wasCurrent = true; + } + width: parent.width; height: parent.height - x: (myIdx - tabContent.animIdx) * width - active: isCurrent || Math.abs(x) < width + property real targetX: { + if (Anim.style === "none") return 0; + if (isCurrent) return 0; + if (myIdx < tabContent.pageIdx) return -width * parallaxFactor; + return width; + } + + x: targetX + Behavior on x { + enabled: Anim.style !== "none" + NumberAnimation { + duration: Anim.slow; easing.type: Anim.outExpo + onRunningChanged: { if (!running && !tabBluetooth.isCurrent) tabBluetooth.wasCurrent = false; } + } + } + + property real targetOpacity: { + if (Anim.style !== "parallax") return 1.0; + if (isCurrent) return 1.0; + return 0.0; + } + opacity: targetOpacity + Behavior on opacity { + enabled: Anim.style === "parallax" + NumberAnimation { duration: Anim.slow; easing.type: Anim.outExpo } + } + + active: isCurrent || wasCurrent visible: active source: "BluetoothTab.qml" @@ -166,12 +230,47 @@ PanelWindow { // VPN — WireGuard connections Loader { + id: tabVpn readonly property int myIdx: 2 property bool isCurrent: root.page === "vpn" + property bool wasCurrent: false + property real parallaxFactor: Anim.style === "parallax" ? 0.3 : 1.0 + onIsCurrentChanged: { + if (isCurrent) wasCurrent = false; + else if (Anim.style === "none") wasCurrent = false; + else wasCurrent = true; + } + width: parent.width; height: parent.height - x: (myIdx - tabContent.animIdx) * width - active: isCurrent || Math.abs(x) < width + property real targetX: { + if (Anim.style === "none") return 0; + if (isCurrent) return 0; + if (myIdx < tabContent.pageIdx) return -width * parallaxFactor; + return width; + } + + x: targetX + Behavior on x { + enabled: Anim.style !== "none" + NumberAnimation { + duration: Anim.slow; easing.type: Anim.outExpo + onRunningChanged: { if (!running && !tabVpn.isCurrent) tabVpn.wasCurrent = false; } + } + } + + property real targetOpacity: { + if (Anim.style !== "parallax") return 1.0; + if (isCurrent) return 1.0; + return 0.0; + } + opacity: targetOpacity + Behavior on opacity { + enabled: Anim.style === "parallax" + NumberAnimation { duration: Anim.slow; easing.type: Anim.outExpo } + } + + active: isCurrent || wasCurrent visible: active source: "VPNTab.qml" @@ -180,12 +279,47 @@ PanelWindow { // Hotspot — virtual AP interface Loader { + id: tabHotspot readonly property int myIdx: 3 property bool isCurrent: root.page === "hotspot" + property bool wasCurrent: false + property real parallaxFactor: Anim.style === "parallax" ? 0.3 : 1.0 + onIsCurrentChanged: { + if (isCurrent) wasCurrent = false; + else if (Anim.style === "none") wasCurrent = false; + else wasCurrent = true; + } + width: parent.width; height: parent.height - x: (myIdx - tabContent.animIdx) * width - active: isCurrent || Math.abs(x) < width + property real targetX: { + if (Anim.style === "none") return 0; + if (isCurrent) return 0; + if (myIdx < tabContent.pageIdx) return -width * parallaxFactor; + return width; + } + + x: targetX + Behavior on x { + enabled: Anim.style !== "none" + NumberAnimation { + duration: Anim.slow; easing.type: Anim.outExpo + onRunningChanged: { if (!running && !tabHotspot.isCurrent) tabHotspot.wasCurrent = false; } + } + } + + property real targetOpacity: { + if (Anim.style !== "parallax") return 1.0; + if (isCurrent) return 1.0; + return 0.0; + } + opacity: targetOpacity + Behavior on opacity { + enabled: Anim.style === "parallax" + NumberAnimation { duration: Anim.slow; easing.type: Anim.outExpo } + } + + active: isCurrent || wasCurrent visible: active source: "HotspotTab.qml" diff --git a/src/popups/NotificationToast.qml b/src/popups/NotificationToast.qml index 4ea583a..d18b753 100644 --- a/src/popups/NotificationToast.qml +++ b/src/popups/NotificationToast.qml @@ -85,7 +85,7 @@ PopupWindow { Timer { id: slideOutTimer - interval: Theme.animDuration + 20 + interval: Anim.transition + 20 onTriggered: { if (root.queue.length > 0) { const next = root.queue[0] @@ -114,8 +114,8 @@ PopupWindow { ? (cardCol.y + cardCol.implicitHeight + Math.round(24 * root.localScale) + root.fh) : root.fh - Behavior on width { NumberAnimation { duration: Theme.animDuration; easing.type: Easing.InOutCubic } } - Behavior on height { NumberAnimation { duration: Theme.animDuration; easing.type: Easing.InOutCubic } } + Behavior on width { NumberAnimation { duration: Anim.transition; easing.type: Anim.inOutCubic} } + Behavior on height { NumberAnimation { duration: Anim.transition; easing.type: Anim.inOutCubic} } PopupShape { anchors.fill: parent @@ -150,7 +150,7 @@ PopupWindow { Item { anchors.fill: parent opacity: root.showing ? 1 : 0 - Behavior on opacity { NumberAnimation { duration: 150 } } + Behavior on opacity { NumberAnimation { duration: Anim.mediumFast} } Rectangle { id: progressBar anchors { @@ -170,7 +170,7 @@ PopupWindow { width: running ? 0 : root.toastWidth - Math.round(10 * root.localScale) Behavior on width { enabled: progressBar.running - NumberAnimation { duration: 5000; easing.type: Easing.Linear } + NumberAnimation { duration: Anim.megaSlow; easing.type: Anim.linear} } Connections { @@ -262,7 +262,7 @@ PopupWindow { anchors.fill: parent radius: width / 2 color: xHover.containsMouse ? Qt.rgba(1,1,1,0.12) : "transparent" - Behavior on color { ColorAnimation { duration: 100 } } + Behavior on color { ColorAnimation { duration: Anim.fast} } } Text { anchors.centerIn: parent @@ -316,7 +316,7 @@ PopupWindow { color: actHover.containsMouse ? Qt.rgba(1,1,1,0.18) : Qt.rgba(1,1,1,0.08) - Behavior on color { ColorAnimation { duration: 100 } } + Behavior on color { ColorAnimation { duration: Anim.fast} } } Text { id: actionLbl diff --git a/src/popups/NotificationsPopup.qml b/src/popups/NotificationsPopup.qml index a411f8d..df44fe8 100644 --- a/src/popups/NotificationsPopup.qml +++ b/src/popups/NotificationsPopup.qml @@ -18,7 +18,7 @@ PopupWindow { readonly property int maxHeight: Math.round(700 * root.localScale) readonly property int fw: Math.round(Theme.notchRadius * root.localScale) readonly property int fh: Math.round(Theme.notchRadius * root.localScale) - readonly property int animDuration: Theme.animDuration + readonly property int animDuration: Anim.transition // Fixed — never zero, never dynamic implicitWidth: popupWidth + fw @@ -86,8 +86,8 @@ PopupWindow { ? notifList.height + Math.round(Theme.popupPadding * 2 * root.localScale) + root.fh : root.fh - Behavior on width { NumberAnimation { duration: root.animDuration; easing.type: Easing.InOutCubic } } - Behavior on height { NumberAnimation { duration: root.animDuration; easing.type: Easing.InOutCubic } } + Behavior on width { NumberAnimation { duration: root.animDuration; easing.type: Anim.inOutCubic} } + Behavior on height { NumberAnimation { duration: root.animDuration; easing.type: Anim.inOutCubic} } // ── Background ───────────────────────────────────────── PopupShape { diff --git a/src/popups/QuickControl.qml b/src/popups/QuickControl.qml index 9b1fae0..8dd9abc 100644 --- a/src/popups/QuickControl.qml +++ b/src/popups/QuickControl.qml @@ -120,7 +120,7 @@ PopupWindow { width: root.popupWidth height: root.popupHeight - Behavior on width { NumberAnimation { duration: Theme.animDuration; easing.type: Easing.InOutCubic } } + Behavior on width { NumberAnimation { duration: Anim.transition; easing.type: Anim.inOutCubic} } PopupShape { id: bg @@ -214,7 +214,7 @@ PopupWindow { color: col.muted ? Qt.rgba(1,1,1,0.25) : Theme.text font.pixelSize: Math.round(13 * root.localScale) font.bold: true - Behavior on color { ColorAnimation { duration: 150 } } + Behavior on color { ColorAnimation { duration: Anim.mediumFast} } } Item { @@ -234,8 +234,8 @@ PopupWindow { height: Math.max(radius * 2, parent.height * col.value) radius: parent.radius color: col.muted ? Qt.rgba(1,1,1,0.15) : Theme.active - Behavior on color { ColorAnimation { duration: 150 } } - Behavior on height { NumberAnimation { duration: 80; easing.type: Easing.OutCubic } } + Behavior on color { ColorAnimation { duration: Anim.mediumFast} } + Behavior on height { NumberAnimation { duration: Anim.superFast; easing.type: Anim.outCubic} } } // Thumb @@ -250,7 +250,7 @@ PopupWindow { var travel = track.height - height return Math.max(0, Math.min(travel, (1.0 - col.value) * travel)) } - Behavior on color { ColorAnimation { duration: 150 } } + Behavior on color { ColorAnimation { duration: Anim.mediumFast} } } // Drag to change value @@ -286,20 +286,20 @@ PopupWindow { color: col.muted ? Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.2) : Qt.rgba(1,1,1,0.06) - Behavior on color { ColorAnimation { duration: 150 } } + Behavior on color { ColorAnimation { duration: Anim.mediumFast} } Text { anchors.centerIn: parent text: col.icon font.pixelSize: Math.round(14 * root.localScale) color: col.muted ? Theme.active : Qt.rgba(1,1,1,0.55) - Behavior on color { ColorAnimation { duration: 150 } } + Behavior on color { ColorAnimation { duration: Anim.mediumFast} } } Rectangle { anchors.fill: parent; radius: parent.radius color: muteHov.hovered ? Qt.rgba(1,1,1,0.05) : "transparent" - Behavior on color { ColorAnimation { duration: 100 } } + Behavior on color { ColorAnimation { duration: Anim.fast} } } HoverHandler { id: muteHov; cursorShape: Qt.PointingHandCursor } MouseArea { anchors.fill: parent; onClicked: col.muteToggled()} diff --git a/src/popups/ScreenRecOptionsPopup.qml b/src/popups/ScreenRecOptionsPopup.qml index 3226916..07a1bc8 100644 --- a/src/popups/ScreenRecOptionsPopup.qml +++ b/src/popups/ScreenRecOptionsPopup.qml @@ -121,7 +121,7 @@ PopupWindow { color: row._selected ? Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.18) : rH.hovered ? Qt.rgba(1, 1, 1, 0.07) : "transparent" - Behavior on color { ColorAnimation { duration: 100 } } + Behavior on color { ColorAnimation { duration: Anim.fast} } } Row { @@ -133,7 +133,7 @@ PopupWindow { font.pixelSize: Math.round(13 * root.localScale) color: row._selected ? Theme.active : Qt.rgba(1, 1, 1, 0.45) anchors.verticalCenter: parent.verticalCenter - Behavior on color { ColorAnimation { duration: 100 } } + Behavior on color { ColorAnimation { duration: Anim.fast} } } Text { id: _lbl @@ -141,7 +141,7 @@ PopupWindow { font.pixelSize: Math.round(12 * root.localScale) color: row._selected ? Theme.active : Qt.rgba(1, 1, 1, 0.70) anchors.verticalCenter: parent.verticalCenter - Behavior on color { ColorAnimation { duration: 100 } } + Behavior on color { ColorAnimation { duration: Anim.fast} } } } diff --git a/src/popups/VPNTab.qml b/src/popups/VPNTab.qml index 218f0bf..6c8a607 100644 --- a/src/popups/VPNTab.qml +++ b/src/popups/VPNTab.qml @@ -375,8 +375,8 @@ Item { ? Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.40) : Qt.rgba(1,1,1,0.10) border.width: Math.max(1, Math.round(1 * localScale)) - Behavior on color { ColorAnimation { duration: 130 } } - Behavior on border.color { ColorAnimation { duration: 130 } } + Behavior on color { ColorAnimation { duration: Anim.color} } + Behavior on border.color { ColorAnimation { duration: Anim.color} } Row { id: ksRow; anchors.centerIn: parent; spacing: Math.round(6 * localScale) @@ -385,13 +385,13 @@ Item { anchors.verticalCenter: parent.verticalCenter text: "󰒃"; font.pixelSize: Math.round(13 * localScale) color: root._killSwitch ? Theme.active : Qt.rgba(1,1,1,0.40) - Behavior on color { ColorAnimation { duration: 130 } } + Behavior on color { ColorAnimation { duration: Anim.color} } } Text { anchors.verticalCenter: parent.verticalCenter text: "Kill Switch"; font.pixelSize: Math.round(11 * localScale); font.weight: Font.Medium color: root._killSwitch ? Theme.active : Qt.rgba(1,1,1,0.45) - Behavior on color { ColorAnimation { duration: 130 } } + Behavior on color { ColorAnimation { duration: Anim.color} } } } @@ -405,18 +405,18 @@ Item { color: rfH.hovered ? Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.15) : Qt.rgba(1,1,1,0.05) border.color: Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.28) border.width: Math.max(1, Math.round(1 * localScale)) - Behavior on color { ColorAnimation { duration: 120 } } + Behavior on color { ColorAnimation { duration: Anim.color} } Text { id: rfIcon; anchors.centerIn: parent; text: "󰑐"; font.pixelSize: Math.round(15 * localScale) color: root._loading ? Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.4) : Theme.active - Behavior on color { ColorAnimation { duration: 150 } } + Behavior on color { ColorAnimation { duration: Anim.mediumFast} } RotationAnimator { - target: rfIcon; from: 0; to: 360; duration: 900 + target: rfIcon; from: 0; to: 360; duration: Anim.megaSlow loops: Animation.Infinite; running: root._loading - easing.type: Easing.Linear + easing.type: Anim.linear } } HoverHandler { id: rfH; cursorShape: Qt.PointingHandCursor } @@ -516,8 +516,8 @@ Item { SequentialAnimation on opacity { running: root._loading && root._connections.length === 0 loops: Animation.Infinite - NumberAnimation { to: 0.15; duration: 550 } - NumberAnimation { to: 1.0; duration: 550 } + NumberAnimation { to: 0.15; duration: Anim.verySlow} + NumberAnimation { to: 1.0; duration: Anim.verySlow} } } Text { anchors.horizontalCenter: parent.horizontalCenter; text: "Loading…"; font.pixelSize: Math.round(11 * localScale); color: Qt.rgba(1,1,1,0.25) } @@ -551,13 +551,13 @@ Item { ? Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.22) : Qt.rgba(1,1,1,0.07) border.width: Math.max(1, Math.round(1 * localScale)) - Behavior on color { ColorAnimation { duration: 200 } } - Behavior on border.color { ColorAnimation { duration: 200 } } + Behavior on color { ColorAnimation { duration: Anim.normal} } + Behavior on border.color { ColorAnimation { duration: Anim.normal} } SequentialAnimation { id: pulseAnim; running: false - ColorAnimation { target: card; to: Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.30); duration: 160 } - ColorAnimation { target: card; to: Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.08); duration: 500; easing.type: Easing.OutCubic } + ColorAnimation { target: card; to: Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.30); duration: Anim.mediumFast} + ColorAnimation { target: card; to: Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.08); duration: Anim.verySlow; easing.type: Anim.outCubic} } } @@ -574,7 +574,7 @@ Item { : vRow.con.busy ? Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.5) : Qt.rgba(1,1,1,0.28) - Behavior on color { ColorAnimation { duration: 200 } } + Behavior on color { ColorAnimation { duration: Anim.normal} } } Column { @@ -594,7 +594,7 @@ Item { color: vRow.con.busy ? Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.60) : vRow.con.active ? Theme.active : Qt.rgba(1,1,1,0.32) - Behavior on color { ColorAnimation { duration: 200 } } + Behavior on color { ColorAnimation { duration: Anim.normal} } } } } @@ -609,8 +609,8 @@ Item { text: "○"; font.pixelSize: Math.round(16 * localScale); color: Theme.active SequentialAnimation on opacity { running: vRow.con.busy; loops: Animation.Infinite - NumberAnimation { to: 0.15; duration: 450 } - NumberAnimation { to: 1.0; duration: 450 } + NumberAnimation { to: 0.15; duration: Anim.slower} + NumberAnimation { to: 1.0; duration: Anim.slower} } } @@ -620,7 +620,7 @@ Item { color: vRow.con.active ? Theme.active : vHov.hovered ? Qt.rgba(1,1,1,0.35) : Qt.rgba(1,1,1,0.18) - Behavior on color { ColorAnimation { duration: 200 } } + Behavior on color { ColorAnimation { duration: Anim.normal} } } } diff --git a/src/popups/WallpaperPopup.qml b/src/popups/WallpaperPopup.qml index d98243a..c4fe669 100644 --- a/src/popups/WallpaperPopup.qml +++ b/src/popups/WallpaperPopup.qml @@ -123,7 +123,7 @@ PanelWindow { Timer { id: closeTimer - interval: Theme.animDuration + 20 + interval: Anim.transition + 20 onTriggered: { if (!Popups.wallpaperOpen) root.windowVisible = false } } @@ -149,7 +149,7 @@ PanelWindow { Timer { id: centerLockTimer - interval: Theme.animDuration + interval: Anim.transition onTriggered: wallGrid.targetCenterIndex = -1 } @@ -168,8 +168,8 @@ PanelWindow { width: Popups.wallpaperOpen ? root.panelWidth + 2 * root.fw : Math.round(Theme.cNotchMinWidth * root.localScale) + 2 * root.fw height: Popups.wallpaperOpen ? root.panelHeight : 0 - Behavior on width { NumberAnimation { duration: Theme.animDuration; easing.type: Easing.InOutCubic } } - Behavior on height { NumberAnimation { duration: Theme.animDuration; easing.type: Easing.InOutCubic } } + Behavior on width { NumberAnimation { duration: Anim.transition; easing.type: Anim.inOutCubic} } + Behavior on height { NumberAnimation { duration: Anim.transition; easing.type: Anim.inOutCubic} } HoverHandler { onHoveredChanged: root.selfHovered = hovered @@ -221,11 +221,11 @@ PanelWindow { opacity: Popups.wallpaperOpen ? 1 : 0 transform: Translate { y: Popups.wallpaperOpen ? 0 : Math.round(40 * root.localScale) - Behavior on y { NumberAnimation { duration: Theme.animDuration; easing.type: Easing.OutExpo } } + Behavior on y { NumberAnimation { duration: Anim.transition; easing.type: Anim.outExpo} } } Behavior on opacity { NumberAnimation { - duration: Popups.wallpaperOpen ? Theme.animDuration * 0.5 : Theme.animDuration * 0.15 + duration: Popups.wallpaperOpen ? Anim.transition * 0.5 : Anim.transition * 0.15 } } @@ -272,7 +272,7 @@ PanelWindow { width: isPreview ? Math.round(130 * 1.2 * localScale) : Math.round(130 * localScale) height: isPreview ? wallGrid.height : wallGrid.height - Math.round(14 * localScale) - Behavior on width { NumberAnimation { duration: 120; easing.type: Easing.InOutCubic } } + Behavior on width { NumberAnimation { duration: Anim.color; easing.type: Anim.inOutCubic} } Item { id: cardContent @@ -337,8 +337,8 @@ PanelWindow { border.color: isPreview ? Theme.active : isCurrent ? Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.45) : Qt.rgba(1,1,1,0.15) - Behavior on border.color { ColorAnimation { duration: 120 } } - Behavior on border.width { NumberAnimation { duration: 120 } } + Behavior on border.color { ColorAnimation { duration: Anim.color} } + Behavior on border.width { NumberAnimation { duration: Anim.color} } } MouseArea { @@ -408,12 +408,12 @@ PanelWindow { ? Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.4) : Qt.rgba(1,1,1,0.09) border.width: 1 - Behavior on color { ColorAnimation { duration: 100 } } - Behavior on border.color { ColorAnimation { duration: 100 } } + Behavior on color { ColorAnimation { duration: Anim.fast} } + Behavior on border.color { ColorAnimation { duration: Anim.fast} } Text { anchors.centerIn: parent; text: "󰉋"; font.pixelSize: Math.round(15 * root.localScale) color: (content.folderMode || folderBtnMA.containsMouse) ? Theme.active : Qt.rgba(1,1,1,0.5) - Behavior on color { ColorAnimation { duration: 100 } } + Behavior on color { ColorAnimation { duration: Anim.fast} } } MouseArea { id: folderBtnMA @@ -444,8 +444,8 @@ PanelWindow { ? Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.5) : (filterBoxMA.containsMouse ? Qt.rgba(1,1,1,0.15) : Qt.rgba(1,1,1,0.1)) border.width: 1 - Behavior on color { ColorAnimation { duration: 100 } } - Behavior on border.color { ColorAnimation { duration: 100 } } + Behavior on color { ColorAnimation { duration: Anim.fast} } + Behavior on border.color { ColorAnimation { duration: Anim.fast} } MouseArea { id: filterBoxMA @@ -574,8 +574,8 @@ PanelWindow { ? Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.4) : Qt.rgba(1,1,1,0.09) border.width: 1 - Behavior on color { ColorAnimation { duration: 100 } } - Behavior on border.color { ColorAnimation { duration: 100 } } + Behavior on color { ColorAnimation { duration: Anim.fast} } + Behavior on border.color { ColorAnimation { duration: Anim.fast} } Row { id: schemeBtnRow; anchors.centerIn: parent; spacing: Math.round(7 * localScale) @@ -584,14 +584,14 @@ PanelWindow { font.pixelSize: Math.round(14 * localScale) color: (content.schemePopupOpen || schemeBtnMA.containsMouse) ? Theme.active : Qt.rgba(1,1,1,0.55) anchors.verticalCenter: parent.verticalCenter - Behavior on color { ColorAnimation { duration: 100 } } + Behavior on color { ColorAnimation { duration: Anim.fast} } } Text { text: WallpaperService.scheme font.pixelSize: Math.round(12 * localScale) color: (content.schemePopupOpen || schemeBtnMA.containsMouse) ? Theme.active : Qt.rgba(1,1,1,0.7) anchors.verticalCenter: parent.verticalCenter - Behavior on color { ColorAnimation { duration: 100 } } + Behavior on color { ColorAnimation { duration: Anim.fast} } } Text { text: content.schemePopupOpen ? "▴" : "▾" @@ -628,10 +628,10 @@ PanelWindow { ? Theme.active : Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.4) border.width: 1 - Behavior on width { NumberAnimation { duration: 200; easing.type: Easing.OutCubic } } - Behavior on opacity { NumberAnimation { duration: 160 } } - Behavior on color { ColorAnimation { duration: 100 } } - Behavior on border.color { ColorAnimation { duration: 100 } } + Behavior on width { NumberAnimation { duration: Anim.normal; easing.type: Anim.outCubic} } + Behavior on opacity { NumberAnimation { duration: Anim.mediumFast} } + Behavior on color { ColorAnimation { duration: Anim.fast} } + Behavior on border.color { ColorAnimation { duration: Anim.fast} } Text { anchors.centerIn: parent text: WallpaperService.applying ? "…" : "Apply" @@ -639,7 +639,7 @@ PanelWindow { font.weight: Font.Medium color: Theme.active opacity: applyBtn.active ? 1 : 0 - Behavior on opacity { NumberAnimation { duration: 100 } } + Behavior on opacity { NumberAnimation { duration: Anim.fast} } } MouseArea { id: applyBtnMA @@ -679,7 +679,7 @@ PanelWindow { border.width: 1 opacity: content.schemePopupOpen ? 1 : 0 - Behavior on opacity { NumberAnimation { duration: 140 } } + Behavior on opacity { NumberAnimation { duration: Anim.color} } onVisibleChanged: { if (visible) { @@ -721,8 +721,8 @@ PanelWindow { : "transparent" border.width: 1 - Behavior on color { ColorAnimation { duration: 100 } } - Behavior on border.color { ColorAnimation { duration: 100 } } + Behavior on color { ColorAnimation { duration: Anim.fast} } + Behavior on border.color { ColorAnimation { duration: Anim.fast} } Row { anchors.left: parent.left diff --git a/src/popups/WifiTab.qml b/src/popups/WifiTab.qml index a98b527..8ea8e1e 100644 --- a/src/popups/WifiTab.qml +++ b/src/popups/WifiTab.qml @@ -236,8 +236,8 @@ Item { running: root._scanning; loops: Animation.Infinite PauseAnimation { duration: index * 650 } ParallelAnimation { - NumberAnimation { property: "scale"; from: 0.08; to: 1.0; duration: 2200; easing.type: Easing.OutCubic } - NumberAnimation { property: "opacity"; from: 0.80; to: 0.0; duration: 2200; easing.type: Easing.OutQuad } + NumberAnimation { property: "scale"; from: 0.08; to: 1.0; duration: Anim.megaSlow; easing.type: Anim.outCubic} + NumberAnimation { property: "opacity"; from: 0.80; to: 0.0; duration: Anim.megaSlow; easing.type: Anim.outQuad} } } } @@ -247,8 +247,8 @@ Item { color: Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.55) SequentialAnimation on opacity { running: root._scanning; loops: Animation.Infinite - NumberAnimation { to: 0.20; duration: 700; easing.type: Easing.InOutSine } - NumberAnimation { to: 0.80; duration: 700; easing.type: Easing.InOutSine } + NumberAnimation { to: 0.20; duration: Anim.extraSlow; easing.type: Anim.inOutSine} + NumberAnimation { to: 0.80; duration: Anim.extraSlow; easing.type: Anim.inOutSine} } } } @@ -273,7 +273,7 @@ Item { }; return false } color: lit ? Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.85) : Qt.rgba(1,1,1,0.15) - Behavior on color { ColorAnimation { duration: 200 } } + Behavior on color { ColorAnimation { duration: Anim.normal} } } } } @@ -302,8 +302,8 @@ Item { ? Qt.rgba(245/255,196/255,122/255,0.30) : Qt.rgba(1,1,1,0.06) border.width: Math.max(1, Math.round(1 * localScale)) - Behavior on color { ColorAnimation { duration: 130 } } - Behavior on border.color { ColorAnimation { duration: 130 } } + Behavior on color { ColorAnimation { duration: Anim.color} } + Behavior on border.color { ColorAnimation { duration: Anim.color} } } Item { @@ -347,16 +347,16 @@ Item { anchors.centerIn: parent; text: "○"; font.pixelSize: Math.round(14 * localScale); color: Theme.active SequentialAnimation on opacity { running: netRow.isConnecting; loops: Animation.Infinite - NumberAnimation { to: 0.2; duration: 500 } - NumberAnimation { to: 1.0; duration: 500 } + NumberAnimation { to: 0.2; duration: Anim.verySlow} + NumberAnimation { to: 1.0; duration: Anim.verySlow} } } } // Disconnect Item { visible: netRow.isCurrent; width: Math.round(28 * localScale); height: Math.round(28 * localScale); anchors.verticalCenter: parent.verticalCenter - Rectangle { anchors.fill: parent; radius: Math.round(6 * localScale); color: dH.hovered ? Qt.rgba(1,1,1,0.10) : "transparent"; Behavior on color { ColorAnimation { duration: 100 } } } - Text { anchors.centerIn: parent; text: "󰖪"; font.pixelSize: Math.round(14 * localScale); color: dH.hovered ? Qt.rgba(1,1,1,0.65) : Qt.rgba(1,1,1,0.35); Behavior on color { ColorAnimation { duration: 100 } } } + Rectangle { anchors.fill: parent; radius: Math.round(6 * localScale); color: dH.hovered ? Qt.rgba(1,1,1,0.10) : "transparent"; Behavior on color { ColorAnimation { duration: Anim.fast} } } + Text { anchors.centerIn: parent; text: "󰖪"; font.pixelSize: Math.round(14 * localScale); color: dH.hovered ? Qt.rgba(1,1,1,0.65) : Qt.rgba(1,1,1,0.35); Behavior on color { ColorAnimation { duration: Anim.fast} } } HoverHandler { id: dH; cursorShape: Qt.PointingHandCursor } MouseArea { anchors.fill: parent; onClicked: root._disconnect() } } @@ -366,9 +366,9 @@ Item { Rectangle { anchors.fill: parent; radius: Math.round(6 * localScale) color: fH.hovered ? Qt.rgba(248/255,113/255,113/255,0.15) : netRow.isForgetPending ? Qt.rgba(248/255,113/255,113/255,0.10) : "transparent" - Behavior on color { ColorAnimation { duration: 100 } } + Behavior on color { ColorAnimation { duration: Anim.fast} } } - Text { anchors.centerIn: parent; text: "󰗼"; font.pixelSize: Math.round(13 * localScale); color: (fH.hovered || netRow.isForgetPending) ? "#f87171" : Qt.rgba(1,1,1,0.3); Behavior on color { ColorAnimation { duration: 100 } } } + Text { anchors.centerIn: parent; text: "󰗼"; font.pixelSize: Math.round(13 * localScale); color: (fH.hovered || netRow.isForgetPending) ? "#f87171" : Qt.rgba(1,1,1,0.3); Behavior on color { ColorAnimation { duration: Anim.fast} } } HoverHandler { id: fH; cursorShape: Qt.PointingHandCursor } MouseArea { anchors.fill: parent; onClicked: root._forgetSsid = netRow.isForgetPending ? "" : netRow.net.ssid } } @@ -379,7 +379,7 @@ Item { width: connectLbl.implicitWidth + Math.round(20 * localScale); height: Math.round(28 * localScale); radius: Math.round(8 * localScale) color: conH.hovered ? Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.22) : Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.09) border.color: Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.35); border.width: Math.max(1, Math.round(1 * localScale)) - Behavior on color { ColorAnimation { duration: 100 } } + Behavior on color { ColorAnimation { duration: Anim.fast} } Text { id: connectLbl; anchors.centerIn: parent; text: netRow.isExpanded ? "Retry" : "Connect"; font.pixelSize: Math.round(11 * localScale); font.weight: Font.Medium; color: Theme.active } HoverHandler { id: conH; cursorShape: Qt.PointingHandCursor } MouseArea { @@ -401,7 +401,7 @@ Item { anchors { top: baseRow.bottom; left: parent.left; right: parent.right } clip: true height: netRow.isForgetPending ? forgetRow.implicitHeight + Math.round(16 * localScale) : netRow.isExpanded ? passRow.implicitHeight + Math.round(16 * localScale) : 0 - Behavior on height { NumberAnimation { duration: 200; easing.type: Easing.OutCubic } } + Behavior on height { NumberAnimation { duration: Anim.normal; easing.type: Anim.outCubic} } Item { id: forgetRow @@ -409,7 +409,7 @@ Item { implicitHeight: Math.round(32 * localScale) opacity: netRow.isForgetPending ? 1 : 0 visible: opacity > 0 - Behavior on opacity { NumberAnimation { duration: 150 } } + Behavior on opacity { NumberAnimation { duration: Anim.mediumFast} } Rectangle { anchors { fill: parent; leftMargin: Math.round(10 * localScale); rightMargin: Math.round(10 * localScale) } radius: Math.round(8 * localScale); color: Qt.rgba(248/255,113/255,113/255,0.07) @@ -419,7 +419,7 @@ Item { Text { anchors.verticalCenter: parent.verticalCenter; text: "Forget this network?"; font.pixelSize: Math.round(11 * localScale); color: Qt.rgba(1,1,1,0.55) } Rectangle { width: Math.round(54 * localScale); height: Math.round(24 * localScale); radius: Math.round(6 * localScale); color: cfH.hovered ? Qt.rgba(1,1,1,0.09) : Qt.rgba(1,1,1,0.04) - Behavior on color { ColorAnimation { duration: 80 } } + Behavior on color { ColorAnimation { duration: Anim.superFast} } Text { anchors.centerIn: parent; text: "Cancel"; font.pixelSize: Math.round(10 * localScale); color: Qt.rgba(1,1,1,0.45) } HoverHandler { id: cfH; cursorShape: Qt.PointingHandCursor } MouseArea { anchors.fill: parent; onClicked: root._forgetSsid = "" } @@ -427,7 +427,7 @@ Item { Rectangle { width: Math.round(54 * localScale); height: Math.round(24 * localScale); radius: Math.round(6 * localScale) color: ffH.hovered ? Qt.rgba(248/255,113/255,113/255,0.35) : Qt.rgba(248/255,113/255,113/255,0.18) - Behavior on color { ColorAnimation { duration: 80 } } + Behavior on color { ColorAnimation { duration: Anim.superFast} } Text { anchors.centerIn: parent; text: "Forget"; font.pixelSize: Math.round(10 * localScale); font.weight: Font.Medium; color: "#f87171" } HoverHandler { id: ffH; cursorShape: Qt.PointingHandCursor } MouseArea { anchors.fill: parent; onClicked: root._forget(netRow.net.ssid) } @@ -442,7 +442,7 @@ Item { implicitHeight: Math.round(40 * localScale) opacity: netRow.isExpanded ? 1 : 0 visible: opacity > 0 - Behavior on opacity { NumberAnimation { duration: 150 } } + Behavior on opacity { NumberAnimation { duration: Anim.mediumFast} } Row { anchors { fill: parent; leftMargin: Math.round(10 * localScale); rightMargin: Math.round(10 * localScale) } spacing: Math.round(8 * localScale) @@ -450,7 +450,7 @@ Item { width: parent.width - parent.spacing; height: Math.round(32 * localScale); radius: Math.round(8 * localScale) color: Qt.rgba(1,1,1,0.06) border.color: passInput.activeFocus ? Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.55) : Qt.rgba(1,1,1,0.12) - border.width: Math.max(1, Math.round(1 * localScale)); Behavior on border.color { ColorAnimation { duration: 120 } } + border.width: Math.max(1, Math.round(1 * localScale)); Behavior on border.color { ColorAnimation { duration: Anim.color} } Text { anchors { left: parent.left; leftMargin: Math.round(10 * localScale); verticalCenter: parent.verticalCenter } text: "Password…"; font.pixelSize: Math.round(12 * localScale); color: Qt.rgba(1,1,1,0.22); visible: passInput.text === "" } TextInput { @@ -511,9 +511,9 @@ Item { color: wfPwrH.hovered ? (root._wifiEnabled ? Qt.rgba(248/255,113/255,113/255,0.18) : Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.18)) : Qt.rgba(1,1,1,0.04) border.color: root._wifiEnabled ? Qt.rgba(1,1,1,0.10) : Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.30) border.width: Math.max(1, Math.round(1 * localScale)) - Behavior on color { ColorAnimation { duration: 120 } } - Behavior on border.color { ColorAnimation { duration: 120 } } - Text { anchors.centerIn: parent; text: "⏻"; font.pixelSize: Math.round(14 * localScale); color: root._wifiEnabled ? (wfPwrH.hovered ? "#f87171" : Qt.rgba(1,1,1,0.32)) : Theme.active; Behavior on color { ColorAnimation { duration: 120 } } } + Behavior on color { ColorAnimation { duration: Anim.color} } + Behavior on border.color { ColorAnimation { duration: Anim.color} } + Text { anchors.centerIn: parent; text: "⏻"; font.pixelSize: Math.round(14 * localScale); color: root._wifiEnabled ? (wfPwrH.hovered ? "#f87171" : Qt.rgba(1,1,1,0.32)) : Theme.active; Behavior on color { ColorAnimation { duration: Anim.color} } } HoverHandler { id: wfPwrH; cursorShape: Qt.PointingHandCursor } MouseArea { anchors.fill: parent; onClicked: root._setWifiEnabled(!root._wifiEnabled) } } @@ -521,8 +521,8 @@ Item { Rectangle { width: Math.round(32 * localScale); height: Math.round(32 * localScale); radius: Math.round(8 * localScale) color: settH.hovered ? Qt.rgba(1,1,1,0.09) : Qt.rgba(1,1,1,0.03) - border.color: Qt.rgba(1,1,1,0.10); border.width: Math.max(1, Math.round(1 * localScale)); Behavior on color { ColorAnimation { duration: 100 } } - Text { anchors.centerIn: parent; text: "󰒓"; font.pixelSize: Math.round(14 * localScale); color: settH.hovered ? Qt.rgba(1,1,1,0.75) : Qt.rgba(1,1,1,0.30); Behavior on color { ColorAnimation { duration: 100 } } } + border.color: Qt.rgba(1,1,1,0.10); border.width: Math.max(1, Math.round(1 * localScale)); Behavior on color { ColorAnimation { duration: Anim.fast} } + Text { anchors.centerIn: parent; text: "󰒓"; font.pixelSize: Math.round(14 * localScale); color: settH.hovered ? Qt.rgba(1,1,1,0.75) : Qt.rgba(1,1,1,0.30); Behavior on color { ColorAnimation { duration: Anim.fast} } } HoverHandler { id: settH; cursorShape: Qt.PointingHandCursor } MouseArea { anchors.fill: parent; onClicked: { nmtuiProc.running = false; nmtuiProc.running = true } } } @@ -531,12 +531,12 @@ Item { width: Math.round(32 * localScale); height: Math.round(32 * localScale); radius: Math.round(8 * localScale) color: rfH.hovered ? Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.15) : Qt.rgba(1,1,1,0.05) border.color: Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.28); border.width: Math.max(1, Math.round(1 * localScale)) - Behavior on color { ColorAnimation { duration: 120 } } + Behavior on color { ColorAnimation { duration: Anim.color} } Text { id: rfIcon; anchors.centerIn: parent; text: "󰑐"; font.pixelSize: Math.round(15 * localScale) color: root._scanning ? Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.4) : (root._wifiEnabled ? Theme.active : Qt.rgba(1,1,1,0.18)) - Behavior on color { ColorAnimation { duration: 150 } } - RotationAnimator { target: rfIcon; from: 0; to: 360; duration: 900; loops: Animation.Infinite; running: root._scanning; easing.type: Easing.Linear } + Behavior on color { ColorAnimation { duration: Anim.mediumFast} } + RotationAnimator { target: rfIcon; from: 0; to: 360; duration: Anim.megaSlow; loops: Animation.Infinite; running: root._scanning; easing.type: Anim.linear} } HoverHandler { id: rfH; cursorShape: root._wifiEnabled ? Qt.PointingHandCursor : Qt.ArrowCursor } MouseArea { anchors.fill: parent; onClicked: if (!root._scanning && root._wifiEnabled) root._scan(true) } @@ -611,7 +611,7 @@ Item { width: wfEnRow.implicitWidth + Math.round(24 * localScale); height: Math.round(34 * localScale); radius: Math.round(17 * localScale) color: wfEnH.hovered ? Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.22) : Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.12) border.color: Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.40); border.width: Math.max(1, Math.round(1 * localScale)) - Behavior on color { ColorAnimation { duration: 120 } } + Behavior on color { ColorAnimation { duration: Anim.color} } Row { id: wfEnRow; anchors.centerIn: parent; spacing: Math.round(8 * localScale) Text { anchors.verticalCenter: parent.verticalCenter; text: "󰤨"; font.pixelSize: Math.round(14 * localScale); color: Theme.active } Text { anchors.verticalCenter: parent.verticalCenter; text: "Turn On"; font.pixelSize: Math.round(12 * localScale); font.weight: Font.Medium; color: Theme.active } diff --git a/src/qmldir b/src/qmldir index 8d07849..a7a7c70 100644 --- a/src/qmldir +++ b/src/qmldir @@ -1,4 +1,5 @@ singleton Theme theme/Theme.qml +singleton Anim theme/Anim.qml singleton Popups state/Popups.qml singleton IpcManager state/IpcManager.qml singleton ShellState state/ShellState.qml diff --git a/src/services/AppLauncher.qml b/src/services/AppLauncher.qml index d930a8f..922c789 100644 --- a/src/services/AppLauncher.qml +++ b/src/services/AppLauncher.qml @@ -80,7 +80,7 @@ Item { RotationAnimation on rotation { loops: Animation.Infinite from: 0; to: 360 - duration: 1500 + duration: Anim.megaSlow running: root.loading } } @@ -154,8 +154,8 @@ Item { : rowH.hovered ? Qt.rgba(1,1,1,0.08) : "transparent" border.width: 1 - Behavior on color { ColorAnimation { duration: 100 } } - Behavior on border.color { ColorAnimation { duration: 100 } } + Behavior on color { ColorAnimation { duration: Anim.fast} } + Behavior on border.color { ColorAnimation { duration: Anim.fast} } Row { anchors { @@ -221,7 +221,7 @@ Item { font.pixelSize: Math.round(13 * localScale) color: isSel ? Theme.active : Theme.text elide: Text.ElideRight - Behavior on color { ColorAnimation { duration: 100 } } + Behavior on color { ColorAnimation { duration: Anim.fast} } } } @@ -246,7 +246,7 @@ Item { ? Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.50) : Qt.rgba(1,1,1,0.12) border.width: 1 - Behavior on border.color { ColorAnimation { duration: 120 } } + Behavior on border.color { ColorAnimation { duration: Anim.color} } Row { anchors { fill: parent; leftMargin: Math.round(14 * localScale); rightMargin: Math.round(14 * localScale) } @@ -258,7 +258,7 @@ Item { color: searchInput.activeFocus ? Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.7) : Qt.rgba(1,1,1,0.35) - Behavior on color { ColorAnimation { duration: 120 } } + Behavior on color { ColorAnimation { duration: Anim.color} } } Item { diff --git a/src/services/AudioControl.qml b/src/services/AudioControl.qml index 06cc960..9143042 100644 --- a/src/services/AudioControl.qml +++ b/src/services/AudioControl.qml @@ -65,20 +65,50 @@ Item { clip: true property int pageIdx: Math.max(0, ["output", "input", "mixer"].indexOf(root.page)) - property real animIdx: pageIdx - - Behavior on animIdx { - enabled: contentArea.width > 0 - NumberAnimation { duration: 350; easing.type: Easing.OutExpo } - } // Output PopupPage { + id: pageOutput readonly property int myIdx: 0 + property bool isCurrent: root.page === "output" + property bool wasCurrent: false + property real parallaxFactor: Anim.style === "parallax" ? 0.3 : 1.0 + onIsCurrentChanged: { + if (isCurrent) wasCurrent = false; + else if (Anim.style === "none") wasCurrent = false; + else wasCurrent = true; + } + width: parent.width; height: parent.height - y: (myIdx - contentArea.animIdx) * height - visible: Math.abs(y) < height || root.page === "output" + property real targetY: { + if (Anim.style === "none") return 0; + if (isCurrent) return 0; + if (myIdx < contentArea.pageIdx) return -height * parallaxFactor; + return height; + } + + y: targetY + Behavior on y { + enabled: Anim.style !== "none" + NumberAnimation { + duration: Anim.slow; easing.type: Anim.outExpo + onRunningChanged: { if (!running && !pageOutput.isCurrent) pageOutput.wasCurrent = false; } + } + } + + property real targetOpacity: { + if (Anim.style !== "parallax") return 1.0; + if (isCurrent) return 1.0; + return 0.0; + } + opacity: targetOpacity + Behavior on opacity { + enabled: Anim.style === "parallax" + NumberAnimation { duration: Anim.slow; easing.type: Anim.outExpo } + } + + visible: isCurrent || wasCurrent ChannelColumn { localScale: root.localScale @@ -106,11 +136,47 @@ Item { // Input PopupPage { + id: pageInput readonly property int myIdx: 1 + property bool isCurrent: root.page === "input" + property bool wasCurrent: false + property real parallaxFactor: Anim.style === "parallax" ? 0.3 : 1.0 + onIsCurrentChanged: { + if (isCurrent) wasCurrent = false; + else if (Anim.style === "none") wasCurrent = false; + else wasCurrent = true; + } + width: parent.width; height: parent.height - y: (myIdx - contentArea.animIdx) * height - visible: Math.abs(y) < height || root.page === "input" + property real targetY: { + if (Anim.style === "none") return 0; + if (isCurrent) return 0; + if (myIdx < contentArea.pageIdx) return -height * parallaxFactor; + return height; + } + + y: targetY + Behavior on y { + enabled: Anim.style !== "none" + NumberAnimation { + duration: Anim.slow; easing.type: Anim.outExpo + onRunningChanged: { if (!running && !pageInput.isCurrent) pageInput.wasCurrent = false; } + } + } + + property real targetOpacity: { + if (Anim.style !== "parallax") return 1.0; + if (isCurrent) return 1.0; + return 0.0; + } + opacity: targetOpacity + Behavior on opacity { + enabled: Anim.style === "parallax" + NumberAnimation { duration: Anim.slow; easing.type: Anim.outExpo } + } + + visible: isCurrent || wasCurrent ChannelColumn { localScale: root.localScale @@ -132,11 +198,47 @@ Item { // Mixer PopupPage { + id: pageMixer readonly property int myIdx: 2 + property bool isCurrent: root.page === "mixer" + property bool wasCurrent: false + property real parallaxFactor: Anim.style === "parallax" ? 0.3 : 1.0 + onIsCurrentChanged: { + if (isCurrent) wasCurrent = false; + else if (Anim.style === "none") wasCurrent = false; + else wasCurrent = true; + } + width: parent.width; height: parent.height - y: (myIdx - contentArea.animIdx) * height - visible: Math.abs(y) < height || root.page === "mixer" + property real targetY: { + if (Anim.style === "none") return 0; + if (isCurrent) return 0; + if (myIdx < contentArea.pageIdx) return -height * parallaxFactor; + return height; + } + + y: targetY + Behavior on y { + enabled: Anim.style !== "none" + NumberAnimation { + duration: Anim.slow; easing.type: Anim.outExpo + onRunningChanged: { if (!running && !pageMixer.isCurrent) pageMixer.wasCurrent = false; } + } + } + + property real targetOpacity: { + if (Anim.style !== "parallax") return 1.0; + if (isCurrent) return 1.0; + return 0.0; + } + opacity: targetOpacity + Behavior on opacity { + enabled: Anim.style === "parallax" + NumberAnimation { duration: Anim.slow; easing.type: Anim.outExpo } + } + + visible: isCurrent || wasCurrent SectionLabel { text: "Output Devices" } @@ -246,7 +348,7 @@ Item { color: col.muted ? Qt.rgba(1,1,1,0.25) : Theme.text font.pixelSize: Math.round(13 * localScale) font.bold: true - Behavior on color { ColorAnimation { duration: 150 } } + Behavior on color { ColorAnimation { duration: Anim.mediumFast} } } Item { @@ -266,8 +368,8 @@ Item { height: Math.max(parent.radius * 2, parent.height * col.value) radius: parent.radius color: col.muted ? Qt.rgba(1,1,1,0.15) : Theme.active - Behavior on color { ColorAnimation { duration: 150 } } - Behavior on height { NumberAnimation { duration: 80; easing.type: Easing.OutCubic } } + Behavior on color { ColorAnimation { duration: Anim.mediumFast} } + Behavior on height { NumberAnimation { duration: Anim.superFast; easing.type: Anim.outCubic} } } // Thumb @@ -282,7 +384,7 @@ Item { var travel = track.height - height return Math.max(0, Math.min(travel, (1.0 - col.value) * travel)) } - Behavior on color { ColorAnimation { duration: 150 } } + Behavior on color { ColorAnimation { duration: Anim.mediumFast} } } // Drag to change volume @@ -319,7 +421,7 @@ Item { color: col.muted ? Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.2) : Qt.rgba(1,1,1,0.06) - Behavior on color { ColorAnimation { duration: 150 } } + Behavior on color { ColorAnimation { duration: Anim.mediumFast} } Row { anchors.centerIn: parent @@ -329,20 +431,20 @@ Item { font.pixelSize: Math.round(13 * localScale) color: col.muted ? Theme.active : Qt.rgba(1,1,1,0.55) anchors.verticalCenter: parent.verticalCenter - Behavior on color { ColorAnimation { duration: 150 } } + Behavior on color { ColorAnimation { duration: Anim.mediumFast} } } Text { text: col.muted ? "Muted" : "Mute" font.pixelSize: Math.round(11 * localScale) color: col.muted ? Theme.active : Qt.rgba(1,1,1,0.4) anchors.verticalCenter: parent.verticalCenter - Behavior on color { ColorAnimation { duration: 150 } } + Behavior on color { ColorAnimation { duration: Anim.mediumFast} } } } Rectangle { anchors.fill: parent; radius: parent.radius color: muteHov.hovered ? Qt.rgba(1,1,1,0.05) : "transparent" - Behavior on color { ColorAnimation { duration: 100 } } + Behavior on color { ColorAnimation { duration: Anim.fast} } } HoverHandler { id: muteHov; cursorShape: Qt.PointingHandCursor } MouseArea { anchors.fill: parent; onClicked: col.muteToggled() } @@ -390,7 +492,7 @@ Item { color: row.isDefault ? Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.12) : (rowHov.hovered ? Qt.rgba(1,1,1,0.05) : "transparent") - Behavior on color { ColorAnimation { duration: 120 } } + Behavior on color { ColorAnimation { duration: Anim.color} } } Row { @@ -401,7 +503,7 @@ Item { width: Math.round(6 * localScale); height: Math.round(6 * localScale); radius: width / 2 anchors.verticalCenter: parent.verticalCenter color: row.isDefault ? Theme.active : Qt.rgba(1,1,1,0.2) - Behavior on color { ColorAnimation { duration: 150 } } + Behavior on color { ColorAnimation { duration: Anim.mediumFast} } } Text { @@ -411,7 +513,7 @@ Item { elide: Text.ElideRight width: parent.width - Math.round(14 * localScale) - parent.spacing anchors.verticalCenter: parent.verticalCenter - Behavior on color { ColorAnimation { duration: 150 } } + Behavior on color { ColorAnimation { duration: Anim.mediumFast} } } } diff --git a/src/services/BatteryStatus.qml b/src/services/BatteryStatus.qml index f1416c7..abc3993 100644 --- a/src/services/BatteryStatus.qml +++ b/src/services/BatteryStatus.qml @@ -115,8 +115,8 @@ Item { id: pulseAnim running: root.pct <= 10 && !root.charging loops: Animation.Infinite - NumberAnimation { to: 0.2; duration: 600; easing.type: Easing.InOutSine } - NumberAnimation { to: 1.0; duration: 600; easing.type: Easing.InOutSine } + NumberAnimation { to: 0.2; duration: Anim.extraSlow; easing.type: Anim.inOutSine} + NumberAnimation { to: 1.0; duration: Anim.extraSlow; easing.type: Anim.inOutSine} } // Snap back when animation stops @@ -135,7 +135,7 @@ Item { implicitHeight: pctText.implicitHeight clip: true anchors.verticalCenter: parent.verticalCenter - Behavior on implicitWidth { NumberAnimation { duration: Theme.animDuration; easing.type: Easing.InOutCubic } } + Behavior on implicitWidth { NumberAnimation { duration: Anim.transition; easing.type: Anim.inOutCubic} } Text { id: pctText @@ -143,7 +143,7 @@ Item { color: hov.hovered ? Theme.active : Theme.text font.pixelSize: Math.round(12 * localScale) anchors.verticalCenter: parent.verticalCenter - Behavior on color { ColorAnimation { duration: 120 } } + Behavior on color { ColorAnimation { duration: Anim.color} } } } } diff --git a/src/services/KanbanBoard.qml b/src/services/KanbanBoard.qml index 0ab5cc8..0986874 100644 --- a/src/services/KanbanBoard.qml +++ b/src/services/KanbanBoard.qml @@ -367,7 +367,7 @@ Item { : Qt.rgba(1, 1, 1, 0.05) border.color: Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.20) border.width: 1 - Behavior on color { ColorAnimation { duration: 100 } } + Behavior on color { ColorAnimation { duration: Anim.fast} } Text { anchors.centerIn: parent; text: "+"; color: Theme.active; font.pixelSize: Math.round(15 * localScale) } HoverHandler { id: addH; cursorShape: Qt.PointingHandCursor } MouseArea { @@ -394,7 +394,7 @@ Item { id: draftWrap; z: 2; width: parent.width height: colItem.draftOpen ? draftRect.implicitHeight + Math.round(6 * localScale) : 0 clip: true - Behavior on height { NumberAnimation { duration: 180; easing.type: Easing.OutCubic } } + Behavior on height { NumberAnimation { duration: Anim.mediumFast; easing.type: Anim.outCubic} } Rectangle { id: draftRect @@ -406,7 +406,7 @@ Item { : Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.22) border.width: 1 implicitHeight: draftInput.contentHeight + Math.round(24 * localScale) - Behavior on border.color { ColorAnimation { duration: 100 } } + Behavior on border.color { ColorAnimation { duration: Anim.fast} } Text { anchors { left: parent.left; leftMargin: Math.round(10 * localScale); verticalCenter: parent.verticalCenter } @@ -508,7 +508,7 @@ Item { anchors { left: parent.left; verticalCenter: parent.verticalCenter } text: "‹"; font.pixelSize: Math.round(17 * localScale) color: pmH.hovered ? Qt.rgba(1,1,1,0.85) : Qt.rgba(1,1,1,0.30) - Behavior on color { ColorAnimation { duration: 80 } } + Behavior on color { ColorAnimation { duration: Anim.superFast} } HoverHandler { id: pmH; cursorShape: Qt.PointingHandCursor } MouseArea { anchors.fill: parent @@ -527,7 +527,7 @@ Item { anchors { right: parent.right; verticalCenter: parent.verticalCenter } text: "›"; font.pixelSize: Math.round(17 * localScale) color: nmH.hovered ? Qt.rgba(1,1,1,0.85) : Qt.rgba(1,1,1,0.30) - Behavior on color { ColorAnimation { duration: 80 } } + Behavior on color { ColorAnimation { duration: Anim.superFast} } HoverHandler { id: nmH; cursorShape: Qt.PointingHandCursor } MouseArea { anchors.fill: parent @@ -588,7 +588,7 @@ Item { : dayH.hovered && modelData.cur ? Qt.rgba(1,1,1,0.08) : "transparent" border.color: isNow && !isSel ? Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.35) : "transparent" border.width: 1 - Behavior on color { ColorAnimation { duration: 80 } } + Behavior on color { ColorAnimation { duration: Anim.superFast} } Text { anchors.centerIn: parent @@ -632,7 +632,7 @@ Item { width: Math.round(26 * localScale); height: Math.round(18 * localScale); radius: Math.round(4 * localScale) color: hUpH.hovered ? Qt.rgba(1,1,1,0.12) : Qt.rgba(1,1,1,0.05) border.color: Qt.rgba(1,1,1,0.10); border.width: 1 - Behavior on color { ColorAnimation { duration: 80 } } + Behavior on color { ColorAnimation { duration: Anim.superFast} } Text { anchors.centerIn: parent; text: "▲"; font.pixelSize: Math.round(7 * localScale); color: Qt.rgba(1,1,1,0.50) } HoverHandler { id: hUpH; cursorShape: Qt.PointingHandCursor } MouseArea { anchors.fill: parent; onClicked: root.pickerTimeH = (root.pickerTimeH + 1) % 24 } @@ -651,7 +651,7 @@ Item { width: Math.round(26 * localScale); height: Math.round(18 * localScale); radius: Math.round(4 * localScale) color: hDnH.hovered ? Qt.rgba(1,1,1,0.12) : Qt.rgba(1,1,1,0.05) border.color: Qt.rgba(1,1,1,0.10); border.width: 1 - Behavior on color { ColorAnimation { duration: 80 } } + Behavior on color { ColorAnimation { duration: Anim.superFast} } Text { anchors.centerIn: parent; text: "▼"; font.pixelSize: Math.round(7 * localScale); color: Qt.rgba(1,1,1,0.50) } HoverHandler { id: hDnH; cursorShape: Qt.PointingHandCursor } MouseArea { anchors.fill: parent; onClicked: root.pickerTimeH = (root.pickerTimeH + 23) % 24 } @@ -667,7 +667,7 @@ Item { width: Math.round(26 * localScale); height: Math.round(18 * localScale); radius: Math.round(4 * localScale) color: mUpH.hovered ? Qt.rgba(1,1,1,0.12) : Qt.rgba(1,1,1,0.05) border.color: Qt.rgba(1,1,1,0.10); border.width: 1 - Behavior on color { ColorAnimation { duration: 80 } } + Behavior on color { ColorAnimation { duration: Anim.superFast} } Text { anchors.centerIn: parent; text: "▲"; font.pixelSize: Math.round(7 * localScale); color: Qt.rgba(1,1,1,0.50) } HoverHandler { id: mUpH; cursorShape: Qt.PointingHandCursor } MouseArea { anchors.fill: parent; onClicked: root.pickerTimeM = (root.pickerTimeM + 5) % 60 } @@ -686,7 +686,7 @@ Item { width: Math.round(26 * localScale); height: Math.round(18 * localScale); radius: Math.round(4 * localScale) color: mDnH.hovered ? Qt.rgba(1,1,1,0.12) : Qt.rgba(1,1,1,0.05) border.color: Qt.rgba(1,1,1,0.10); border.width: 1 - Behavior on color { ColorAnimation { duration: 80 } } + Behavior on color { ColorAnimation { duration: Anim.superFast} } Text { anchors.centerIn: parent; text: "▼"; font.pixelSize: Math.round(7 * localScale); color: Qt.rgba(1,1,1,0.50) } HoverHandler { id: mDnH; cursorShape: Qt.PointingHandCursor } MouseArea { anchors.fill: parent; onClicked: root.pickerTimeM = (root.pickerTimeM + 55) % 60 } @@ -698,7 +698,7 @@ Item { anchors.verticalCenter: parent.verticalCenter width: Math.round(18 * localScale); height: Math.round(18 * localScale); radius: width / 2 color: clrTH.hovered ? Qt.rgba(1,1,1,0.14) : Qt.rgba(1,1,1,0.05) - Behavior on color { ColorAnimation { duration: 80 } } + Behavior on color { ColorAnimation { duration: Anim.superFast} } Text { anchors.centerIn: parent; text: "✕"; font.pixelSize: Math.round(8 * localScale); color: Qt.rgba(1,1,1,0.40) } HoverHandler { id: clrTH; cursorShape: Qt.PointingHandCursor } MouseArea { anchors.fill: parent; onClicked: root.pickerHasTime = false } @@ -714,12 +714,12 @@ Item { ? Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.15) : Qt.rgba(1,1,1,0.06) border.color: Qt.rgba(1,1,1,0.10); border.width: 1 - Behavior on color { ColorAnimation { duration: 80 } } + Behavior on color { ColorAnimation { duration: Anim.superFast} } Text { id: addTL; anchors.centerIn: parent text: "Add time"; font.pixelSize: Math.round(10 * localScale) color: addTH.hovered ? Theme.active : Qt.rgba(1,1,1,0.45) - Behavior on color { ColorAnimation { duration: 80 } } + Behavior on color { ColorAnimation { duration: Anim.superFast} } } HoverHandler { id: addTH; cursorShape: Qt.PointingHandCursor } MouseArea { @@ -741,7 +741,7 @@ Item { width: Math.round(86 * localScale); height: Math.round(28 * localScale); radius: Math.round(8 * localScale) color: clrH.hovered ? Qt.rgba(1,1,1,0.10) : Qt.rgba(1,1,1,0.05) border.color: Qt.rgba(1,1,1,0.10); border.width: 1 - Behavior on color { ColorAnimation { duration: 80 } } + Behavior on color { ColorAnimation { duration: Anim.superFast} } Text { anchors.centerIn: parent; text: "Clear"; font.pixelSize: Math.round(11 * localScale); color: Qt.rgba(1,1,1,0.50) } HoverHandler { id: clrH; cursorShape: Qt.PointingHandCursor } MouseArea { @@ -754,7 +754,7 @@ Item { width: Math.round(86 * localScale); height: Math.round(28 * localScale); radius: Math.round(8 * localScale) color: Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, doneH.hovered ? 0.28 : 0.16) border.color: Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.38); border.width: 1 - Behavior on color { ColorAnimation { duration: 80 } } + Behavior on color { ColorAnimation { duration: Anim.superFast} } Text { anchors.centerIn: parent; text: "Done" font.pixelSize: Math.round(11 * localScale); font.weight: Font.Medium; color: Theme.active @@ -795,7 +795,7 @@ Item { // Lift Effect: card scales down slightly when grabbed scale: dragHandler.active ? 0.94 : 1.0 - Behavior on scale { NumberAnimation { duration: 300; easing.type: Easing.OutBack; easing.overshoot: 1.5 } } + Behavior on scale { NumberAnimation { duration: Anim.mediumSlow; easing.type: Anim.outBack; easing.overshoot: 1.5 } } // Fluid Column Jumps: smooth gliding instead of teleporting Behavior on x { SpringAnimation { spring: 2.0; damping: 0.25 } } @@ -823,8 +823,8 @@ Item { NumberAnimation { id: xSpringAnim target: card; property: "xEntry"; to: 0 - duration: 400 - easing.type: Easing.OutBack + duration: Anim.slower + easing.type: Anim.outBack easing.overshoot: 1.6 } @@ -850,8 +850,8 @@ Item { // Elastic Snap: wobbles slightly when snapping back to place NumberAnimation { id: snapAnim; target: card; property: "dragX"; to: 0 - duration: 600 - easing.type: Easing.OutElastic + duration: Anim.extraSlow + easing.type: Anim.outElastic easing.amplitude: 1.2 easing.period: 0.6 } @@ -877,13 +877,13 @@ Item { return Qt.rgba(1, 1, 1, 0.10) } border.width: 1 - Behavior on border.color { ColorAnimation { duration: 150 } } + Behavior on border.color { ColorAnimation { duration: Anim.mediumFast} } implicitHeight: body.implicitHeight + Math.round(18 * localScale) // Drag direction tint Rectangle { anchors.fill: parent; radius: parent.radius; color: card.dragTint - Behavior on color { ColorAnimation { duration: 60 } } + Behavior on color { ColorAnimation { duration: Anim.superFast} } } Column { @@ -937,7 +937,7 @@ Item { color: sel ? (modelData === "" ? Qt.rgba(1,1,1,0.15) : root._urgColor(modelData)) : (uH.hovered ? Qt.rgba(1,1,1,0.10) : Qt.rgba(1,1,1,0.05)) border.color: Qt.rgba(1,1,1, sel ? 0.20 : 0.08); border.width: 1 - Behavior on color { ColorAnimation { duration: 100 } } + Behavior on color { ColorAnimation { duration: Anim.fast} } Text { id: uT; anchors.centerIn: parent; font.pixelSize: Math.round(9 * localScale) text: modelData === "" ? "None" : modelData.charAt(0).toUpperCase() + modelData.slice(1) @@ -961,12 +961,12 @@ Item { ? Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.15) : Qt.rgba(1,1,1,0.07) border.color: Qt.rgba(1,1,1,0.12); border.width: 1 - Behavior on color { ColorAnimation { duration: 80 } } + Behavior on color { ColorAnimation { duration: Anim.superFast} } Text { id: dueLbl; anchors.centerIn: parent; font.pixelSize: Math.round(9 * localScale) text: (card.taskData.dueDate || "") !== "" ? root._formatDue(card.taskData.dueDate) : "Set due date" color: (card.taskData.dueDate || "") !== "" ? Theme.active : Qt.rgba(1,1,1,0.40) - Behavior on color { ColorAnimation { duration: 80 } } + Behavior on color { ColorAnimation { duration: Anim.superFast} } } HoverHandler { id: dueBH; cursorShape: Qt.PointingHandCursor } MouseArea { anchors.fill: parent; onClicked: root._openPicker(card.taskData.id) } @@ -978,7 +978,7 @@ Item { anchors.verticalCenter: parent.verticalCenter width: Math.round(16 * localScale); height: Math.round(16 * localScale); radius: width / 2 color: clrDH.hovered ? Qt.rgba(1,1,1,0.12) : Qt.rgba(1,1,1,0.05) - Behavior on color { ColorAnimation { duration: 80 } } + Behavior on color { ColorAnimation { duration: Anim.superFast} } Text { anchors.centerIn: parent; text: "✕"; font.pixelSize: Math.round(8 * localScale); color: Qt.rgba(1,1,1,0.35) } HoverHandler { id: clrDH; cursorShape: Qt.PointingHandCursor } MouseArea { anchors.fill: parent; onClicked: root._patchTask(card.taskData.id, "dueDate", "") } @@ -995,7 +995,7 @@ Item { anchors { left: parent.left; verticalCenter: parent.verticalCenter } width: Math.round(20 * localScale); height: Math.round(20 * localScale); radius: Math.round(5 * localScale) color: optH.hovered ? Qt.rgba(1,1,1,0.10) : Qt.rgba(1,1,1,0.04) - Behavior on color { ColorAnimation { duration: 80 } } + Behavior on color { ColorAnimation { duration: Anim.superFast} } Text { anchors.centerIn: parent; text: card.showExtra ? "▴" : "▾"; font.pixelSize: Math.round(9 * localScale); color: Qt.rgba(1,1,1, optH.hovered ? 0.70 : 0.30) } HoverHandler { id: optH; cursorShape: Qt.PointingHandCursor } MouseArea { anchors.fill: parent; onClicked: card.showExtra = !card.showExtra } @@ -1010,7 +1010,7 @@ Item { visible: card.colIdx > 0 width: Math.round(20 * localScale); height: Math.round(20 * localScale); radius: Math.round(5 * localScale) color: lH.hovered ? Qt.rgba(1,1,1,0.10) : Qt.rgba(1,1,1,0.04) - Behavior on color { ColorAnimation { duration: 80 } } + Behavior on color { ColorAnimation { duration: Anim.superFast} } Text { anchors.centerIn: parent; text: "←"; font.pixelSize: Math.round(10 * localScale); color: Qt.rgba(1,1,1, lH.hovered ? 0.80 : 0.40) } HoverHandler { id: lH; cursorShape: Qt.PointingHandCursor } MouseArea { anchors.fill: parent; onClicked: root._moveTask(card.taskData.id, -1) } @@ -1021,7 +1021,7 @@ Item { visible: card.colIdx < 2 width: Math.round(20 * localScale); height: Math.round(20 * localScale); radius: Math.round(5 * localScale) color: rH.hovered ? Qt.rgba(1,1,1,0.10) : Qt.rgba(1,1,1,0.04) - Behavior on color { ColorAnimation { duration: 80 } } + Behavior on color { ColorAnimation { duration: Anim.superFast} } Text { anchors.centerIn: parent; text: "→"; font.pixelSize: Math.round(10 * localScale); color: Qt.rgba(1,1,1, rH.hovered ? 0.80 : 0.40) } HoverHandler { id: rH; cursorShape: Qt.PointingHandCursor } MouseArea { anchors.fill: parent; onClicked: root._moveTask(card.taskData.id, 1) } @@ -1031,11 +1031,11 @@ Item { Rectangle { width: Math.round(20 * localScale); height: Math.round(20 * localScale); radius: Math.round(5 * localScale) color: dH.hovered ? Qt.rgba(248/255,113/255,113/255,0.20) : Qt.rgba(1,1,1,0.04) - Behavior on color { ColorAnimation { duration: 80 } } + Behavior on color { ColorAnimation { duration: Anim.superFast} } Text { anchors.centerIn: parent; text: "✕"; font.pixelSize: Math.round(10 * localScale) color: Qt.rgba(248/255,113/255,113/255, dH.hovered ? 1.0 : 0.60) - Behavior on color { ColorAnimation { duration: 80 } } + Behavior on color { ColorAnimation { duration: Anim.superFast} } } HoverHandler { id: dH; cursorShape: Qt.PointingHandCursor } MouseArea { anchors.fill: parent; onClicked: root.delConfirmId = card.taskData.id } @@ -1065,7 +1065,7 @@ Item { width: Math.round(64 * localScale); height: Math.round(24 * localScale); radius: Math.round(6 * localScale) color: cnH.hovered ? Qt.rgba(1,1,1,0.10) : Qt.rgba(1,1,1,0.05) border.color: Qt.rgba(1,1,1,0.10); border.width: 1 - Behavior on color { ColorAnimation { duration: 80 } } + Behavior on color { ColorAnimation { duration: Anim.superFast} } Text { anchors.centerIn: parent; text: "Cancel"; font.pixelSize: Math.round(11 * localScale); color: Qt.rgba(1,1,1,0.60) } HoverHandler { id: cnH; cursorShape: Qt.PointingHandCursor } MouseArea { anchors.fill: parent; onClicked: root.delConfirmId = -1 } @@ -1073,7 +1073,7 @@ Item { Rectangle { width: Math.round(64 * localScale); height: Math.round(24 * localScale); radius: Math.round(6 * localScale) color: cfH.hovered ? "#cc3a3a" : "#993030" - Behavior on color { ColorAnimation { duration: 80 } } + Behavior on color { ColorAnimation { duration: Anim.superFast} } Text { anchors.centerIn: parent; text: "Delete"; font.pixelSize: Math.round(11 * localScale); font.weight: Font.Bold; color: "white" } HoverHandler { id: cfH; cursorShape: Qt.PointingHandCursor } MouseArea { anchors.fill: parent; onClicked: root._removeTask(card.taskData.id) } diff --git a/src/services/PowerMenu.qml b/src/services/PowerMenu.qml index 2e7994e..6f9471b 100644 --- a/src/services/PowerMenu.qml +++ b/src/services/PowerMenu.qml @@ -85,7 +85,7 @@ Column { ? (modelData.danger ? "#4d2020" : Theme.active) : "transparent" - Behavior on color { ColorAnimation { duration: 120 } } + Behavior on color { ColorAnimation { duration: Anim.color} } Row { anchors.centerIn: parent diff --git a/src/services/config_tab/KeybindsPage.qml b/src/services/config_tab/KeybindsPage.qml index ec23b58..7c0a403 100644 --- a/src/services/config_tab/KeybindsPage.qml +++ b/src/services/config_tab/KeybindsPage.qml @@ -71,7 +71,7 @@ Item { border.width: root.hasPending ? 1 : 0 radius: 8 - Behavior on height { NumberAnimation { duration: 180; easing.type: Easing.OutCubic } } + Behavior on height { NumberAnimation { duration: Anim.mediumFast; easing.type: Anim.outCubic} } Row { anchors { right: parent.right; verticalCenter: parent.verticalCenter; rightMargin: 10 } @@ -93,7 +93,7 @@ Item { width: 62; height: 26; radius: 7 color: _discardH.hovered ? Qt.rgba(1,1,1,0.08) : Qt.rgba(1,1,1,0.04) border.color: Qt.rgba(1,1,1,0.13); border.width: 1 - Behavior on color { ColorAnimation { duration: 100 } } + Behavior on color { ColorAnimation { duration: Anim.fast} } Text { anchors.centerIn: parent; text: "Discard"; font.pixelSize: 10 color: Qt.rgba(1,1,1,0.48) } HoverHandler { id: _discardH; cursorShape: Qt.PointingHandCursor } @@ -108,7 +108,7 @@ Item { : Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.16) border.color: Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.42) border.width: 1 - Behavior on color { ColorAnimation { duration: 100 } } + Behavior on color { ColorAnimation { duration: Anim.fast} } Text { anchors.centerIn: parent; text: "Save"; font.pixelSize: 10 font.weight: Font.Medium; color: Theme.active } HoverHandler { id: _saveH; cursorShape: Qt.PointingHandCursor } @@ -256,7 +256,7 @@ Item { height: isCapturing ? 58 : 36 clip: true - Behavior on height { NumberAnimation { duration: 160; easing.type: Easing.OutCubic } } + Behavior on height { NumberAnimation { duration: Anim.mediumFast; easing.type: Anim.outCubic} } onIsCapturingChanged: { if (isCapturing) { @@ -282,7 +282,7 @@ Item { ? Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.20) : "transparent" border.width: 1 - Behavior on color { ColorAnimation { duration: 120 } } + Behavior on color { ColorAnimation { duration: Anim.color} } } // ── Invisible focus target for key capture ──────────────────────────── @@ -356,7 +356,7 @@ Item { text: br._b ? br._b.label : br.action font.pixelSize: 12 color: br._savedDupe ? "#f87171" : (br._isUnbound ? Qt.rgba(1, 1, 1, 0.35) : Qt.rgba(1, 1, 1, 0.68)) - Behavior on color { ColorAnimation { duration: 120 } } + Behavior on color { ColorAnimation { duration: Anim.color} } } Row { @@ -377,7 +377,7 @@ Item { visible: br._pillText !== "Unbound" width: 22; height: 22; radius: 6 color: _clrH.hovered ? Qt.rgba(1,1,1,0.09) : "transparent" - Behavior on color { ColorAnimation { duration: 100 } } + Behavior on color { ColorAnimation { duration: Anim.fast} } Text { anchors.centerIn: parent; text: "󰩺"; font.pixelSize: 11 color: _clrH.hovered ? "#ff4444" : Qt.rgba(1,1,1,0.28) } HoverHandler { id: _clrH; cursorShape: Qt.PointingHandCursor } @@ -395,7 +395,7 @@ Item { visible: !br._isDefault width: 22; height: 22; radius: 6 color: _rstH.hovered ? Qt.rgba(1,1,1,0.09) : "transparent" - Behavior on color { ColorAnimation { duration: 100 } } + Behavior on color { ColorAnimation { duration: Anim.fast} } Text { anchors.centerIn: parent; text: "↺"; font.pixelSize: 11 color: _rstH.hovered ? Theme.active : Qt.rgba(1,1,1,0.28) } HoverHandler { id: _rstH; cursorShape: Qt.PointingHandCursor } @@ -439,9 +439,9 @@ Item { opacity: br._interactive ? (br._isUnbound ? 0.7 : 1.0) : 0.4 - Behavior on color { ColorAnimation { duration: 100 } } - Behavior on border.color { ColorAnimation { duration: 150 } } - Behavior on opacity { NumberAnimation { duration: 120 } } + Behavior on color { ColorAnimation { duration: Anim.fast} } + Behavior on border.color { ColorAnimation { duration: Anim.mediumFast} } + Behavior on opacity { NumberAnimation { duration: Anim.color} } Text { id: _pillT @@ -454,7 +454,7 @@ Item { ? Qt.rgba(1, 1, 1, 0.45) : (br._isPending ? Qt.rgba(1.0, 0.74, 0.22, 1.0) : Theme.active) - Behavior on color { ColorAnimation { duration: 150 } } + Behavior on color { ColorAnimation { duration: Anim.mediumFast} } } HoverHandler { id: _pillH; cursorShape: br._interactive ? Qt.PointingHandCursor : Qt.ArrowCursor } MouseArea { @@ -498,7 +498,7 @@ Item { : Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, br.capturedKey !== "" ? 0.40 : 0.18) border.width: 1 - Behavior on border.color { ColorAnimation { duration: 120 } } + Behavior on border.color { ColorAnimation { duration: Anim.color} } Text { id: _capT @@ -523,7 +523,7 @@ Item { Rectangle { width: 28; height: 24; radius: 6 color: _cnH.hovered ? Qt.rgba(1,1,1,0.09) : "transparent" - Behavior on color { ColorAnimation { duration: 100 } } + Behavior on color { ColorAnimation { duration: Anim.fast} } Text { anchors.centerIn: parent; text: "✕"; font.pixelSize: 10 color: Qt.rgba(1,1,1,0.38) } HoverHandler { id: _cnH; cursorShape: Qt.PointingHandCursor } @@ -536,7 +536,7 @@ Item { Item { width: parent.width; height: 22 opacity: (br.capturedKey !== "" && br._hasConflict) ? 1 : 0 - Behavior on opacity { NumberAnimation { duration: 140 } } + Behavior on opacity { NumberAnimation { duration: Anim.color} } Text { anchors { left: parent.left; leftMargin: 2; verticalCenter: parent.verticalCenter } diff --git a/src/services/home/CalendarCard.qml b/src/services/home/CalendarCard.qml index c6ded00..d83dfdc 100644 --- a/src/services/home/CalendarCard.qml +++ b/src/services/home/CalendarCard.qml @@ -90,7 +90,7 @@ StatCard { anchors { left: parent.left; verticalCenter: parent.verticalCenter } text: "‹"; font.pixelSize: Math.round(15 * localScale) color: pH.hovered ? Qt.rgba(1,1,1,0.7) : Qt.rgba(1,1,1,0.25) - Behavior on color { ColorAnimation { duration: 100 } } + Behavior on color { ColorAnimation { duration: Anim.fast} } HoverHandler { id: pH; cursorShape: Qt.PointingHandCursor } MouseArea { anchors.fill: parent; onClicked: root._prev() } } @@ -103,7 +103,7 @@ StatCard { anchors { right: parent.right; verticalCenter: parent.verticalCenter } text: "›"; font.pixelSize: Math.round(15 * localScale) color: nH.hovered ? Qt.rgba(1,1,1,0.7) : Qt.rgba(1,1,1,0.25) - Behavior on color { ColorAnimation { duration: 100 } } + Behavior on color { ColorAnimation { duration: Anim.fast} } HoverHandler { id: nH; cursorShape: Qt.PointingHandCursor } MouseArea { anchors.fill: parent; onClicked: root._next() } } @@ -157,7 +157,7 @@ StatCard { : dH.hovered && modelData.cur ? Qt.rgba(1,1,1,0.07) : "transparent" border.color: isToday ? Qt.rgba(166/255,208/255,247/255,0.3) : "transparent" border.width: 1 - Behavior on color { ColorAnimation { duration: 80 } } + Behavior on color { ColorAnimation { duration: Anim.superFast} } Text { anchors.centerIn: parent; text: modelData.n font.pixelSize: Math.round(9 * localScale); font.family: "JetBrains Mono" diff --git a/src/services/home/ClockCard.qml b/src/services/home/ClockCard.qml index d8a6db4..1a66e72 100644 --- a/src/services/home/ClockCard.qml +++ b/src/services/home/ClockCard.qml @@ -234,20 +234,50 @@ StatCard { clip: true property int pageIdx: Math.max(0, ["clock", "timer", "alarm", "stopwatch"].indexOf(root._mode)) - property real animIdx: pageIdx - - Behavior on animIdx { - enabled: pagesContainer.width > 0 - NumberAnimation { duration: 350; easing.type: Easing.OutExpo } - } // ── CLOCK ───────────────────────────────────────────────────────────── Item { + id: pageClock readonly property int myIdx: 0 + property bool isCurrent: root._mode === "clock" + property bool wasCurrent: false + property real parallaxFactor: Anim.style === "parallax" ? 0.3 : 1.0 + onIsCurrentChanged: { + if (isCurrent) wasCurrent = false; + else if (Anim.style === "none") wasCurrent = false; + else wasCurrent = true; + } + width: parent.width; height: parent.height - x: (myIdx - pagesContainer.animIdx) * width - visible: Math.abs(x) < width || root._mode === "clock" + property real targetX: { + if (Anim.style === "none") return 0; + if (isCurrent) return 0; + if (myIdx < pagesContainer.pageIdx) return -width * parallaxFactor; + return width; + } + + x: targetX + Behavior on x { + enabled: Anim.style !== "none" + NumberAnimation { + duration: Anim.slow; easing.type: Anim.outExpo + onRunningChanged: { if (!running && !pageClock.isCurrent) pageClock.wasCurrent = false; } + } + } + + property real targetOpacity: { + if (Anim.style !== "parallax") return 1.0; + if (isCurrent) return 1.0; + return 0.0; + } + opacity: targetOpacity + Behavior on opacity { + enabled: Anim.style === "parallax" + NumberAnimation { duration: Anim.slow; easing.type: Anim.outExpo } + } + + visible: isCurrent || wasCurrent Row { anchors.centerIn: parent @@ -296,11 +326,32 @@ StatCard { // ── TIMER ───────────────────────────────────────────────────────────── Item { + id: pageTimer readonly property int myIdx: 1 + property bool isCurrent: root._mode === "timer" + property bool wasCurrent: false + property real parallaxFactor: Anim.style === "parallax" ? 0.3 : 1.0 + onIsCurrentChanged: { if (!isCurrent) wasCurrent = true; else wasCurrent = false; } + width: parent.width; height: parent.height - x: (myIdx - pagesContainer.animIdx) * width - visible: Math.abs(x) < width || root._mode === "timer" + property real targetX: { + if (Anim.style === "none") return 0; + if (isCurrent) return 0; + if (myIdx < pagesContainer.pageIdx) return -width * parallaxFactor; + return width; + } + + x: targetX + Behavior on x { + enabled: Anim.style !== "none" + NumberAnimation { + duration: Anim.slow; easing.type: Anim.outExpo + onRunningChanged: { if (!running && !pageTimer.isCurrent) pageTimer.wasCurrent = false; } + } + } + + visible: isCurrent || wasCurrent // "+" / "x" toggle — top-right corner Item { @@ -314,7 +365,7 @@ StatCard { ? Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.15) : Qt.rgba(1,1,1,0.06) border.color: Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.2); border.width: 1 - Behavior on color { ColorAnimation { duration: 100 } } + Behavior on color { ColorAnimation { duration: Anim.fast} } Text { anchors.centerIn: parent text: root._addTimerOpen ? "x" : "+" @@ -391,7 +442,7 @@ StatCard { width: Math.round(36 * localScale); height: Math.round(22 * localScale); radius: Math.round(6 * localScale) color: _pH.hovered ? Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b,0.1) : Qt.rgba(1,1,1,0.05) border.color: Qt.rgba(1,1,1,0.1); border.width: 1 - Behavior on color { ColorAnimation { duration: 100 } } + Behavior on color { ColorAnimation { duration: Anim.fast} } Text { anchors.centerIn: parent text: modelData < 60 ? modelData+"m" : "1h" @@ -440,7 +491,7 @@ StatCard { ? Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b,0.18) : Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b,0.1) border.color: Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b,0.25); border.width: 1 - Behavior on color { ColorAnimation { duration: 100 } } + Behavior on color { ColorAnimation { duration: Anim.fast} } Text { anchors.centerIn: parent; text: "Set Timer" font.pixelSize: Math.round(11 * localScale); font.weight: Font.Medium @@ -480,7 +531,7 @@ StatCard { ? Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b,0.2) : Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b,0.12) border.color: Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b,0.22); border.width: 1 - Behavior on color { ColorAnimation { duration: 100 } } + Behavior on color { ColorAnimation { duration: Anim.fast} } Text { anchors.centerIn: parent text: root._timerRunning ? "Pause" : "Start" @@ -506,7 +557,7 @@ StatCard { ? Qt.rgba(1,1,1,0.1) : Qt.rgba(1,1,1,0.05) border.color: Qt.rgba(1,1,1,0.1); border.width: 1 - Behavior on color { ColorAnimation { duration: 100 } } + Behavior on color { ColorAnimation { duration: Anim.fast} } Text { anchors.centerIn: parent; text: "Reset" font.pixelSize: Math.round(10 * localScale); font.weight: Font.Medium @@ -531,11 +582,32 @@ StatCard { // ── ALARM ───────────────────────────────────────────────────────────── Item { + id: pageAlarm readonly property int myIdx: 2 + property bool isCurrent: root._mode === "alarm" + property bool wasCurrent: false + property real parallaxFactor: Anim.style === "parallax" ? 0.3 : 1.0 + onIsCurrentChanged: { if (!isCurrent) wasCurrent = true; else wasCurrent = false; } + width: parent.width; height: parent.height - x: (myIdx - pagesContainer.animIdx) * width - visible: Math.abs(x) < width || root._mode === "alarm" + property real targetX: { + if (Anim.style === "none") return 0; + if (isCurrent) return 0; + if (myIdx < pagesContainer.pageIdx) return -width * parallaxFactor; + return width; + } + + x: targetX + Behavior on x { + enabled: Anim.style !== "none" + NumberAnimation { + duration: Anim.slow; easing.type: Anim.outExpo + onRunningChanged: { if (!running && !pageAlarm.isCurrent) pageAlarm.wasCurrent = false; } + } + } + + visible: isCurrent || wasCurrent clip: true Item { @@ -564,7 +636,7 @@ StatCard { ? Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b,0.15) : Qt.rgba(1,1,1,0.06) border.color: Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b,0.2); border.width: 1 - Behavior on color { ColorAnimation { duration: 100 } } + Behavior on color { ColorAnimation { duration: Anim.fast} } Text { anchors.centerIn: parent text: root._addOpen ? "✕" : "+" @@ -603,8 +675,8 @@ StatCard { radius: Math.round(8 * localScale) border.color: Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b,0.1); border.width: 1 opacity: root._addOpen ? 1 : 0 - Behavior on height { NumberAnimation { duration: 180; easing.type: Easing.OutCubic } } - Behavior on opacity { NumberAnimation { duration: 150 } } + Behavior on height { NumberAnimation { duration: Anim.mediumFast; easing.type: Anim.outCubic} } + Behavior on opacity { NumberAnimation { duration: Anim.mediumFast} } Column { anchors.centerIn: parent @@ -624,7 +696,7 @@ StatCard { ? Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b,0.18) : Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b,0.1) border.color: Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b,0.25); border.width: 1 - Behavior on color { ColorAnimation { duration: 100 } } + Behavior on color { ColorAnimation { duration: Anim.fast} } Text { anchors.centerIn: parent; text: "Set Alarm" font.pixelSize: Math.round(11 * localScale); font.weight: Font.Medium @@ -683,14 +755,14 @@ StatCard { color: modelData.enabled ? Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b,0.25) : Qt.rgba(1,1,1,0.1) - Behavior on color { ColorAnimation { duration: 130 } } + Behavior on color { ColorAnimation { duration: Anim.color} } Rectangle { width: Math.round(12 * localScale); height: Math.round(12 * localScale); radius: Math.round(6 * localScale) anchors.verticalCenter: parent.verticalCenter x: modelData.enabled ? parent.width - width - Math.round(3 * localScale) : Math.round(3 * localScale) color: modelData.enabled ? Theme.active : Qt.rgba(1,1,1,0.3) - Behavior on x { NumberAnimation { duration: 130; easing.type: Easing.OutCubic } } - Behavior on color { ColorAnimation { duration: 130 } } + Behavior on x { NumberAnimation { duration: Anim.color; easing.type: Anim.outCubic} } + Behavior on color { ColorAnimation { duration: Anim.color} } } MouseArea { anchors.fill: parent; cursorShape: Qt.PointingHandCursor @@ -704,7 +776,7 @@ StatCard { anchors { right: parent.right; rightMargin: Math.round(10 * localScale); verticalCenter: parent.verticalCenter } width: Math.round(22 * localScale); height: Math.round(22 * localScale); radius: Math.round(6 * localScale) color: _delH.hovered ? Qt.rgba(248/255,113/255,113/255,0.18) : "transparent" - Behavior on color { ColorAnimation { duration: 100 } } + Behavior on color { ColorAnimation { duration: Anim.fast} } Text { anchors.centerIn: parent; text: "✕"; font.pixelSize: Math.round(10 * localScale); color: Qt.rgba(248/255,113/255,113/255,0.6) } HoverHandler { id: _delH; cursorShape: Qt.PointingHandCursor } MouseArea { anchors.fill: parent; onClicked: root._deleteAlarm(modelData.id) } @@ -725,11 +797,32 @@ StatCard { // ── STOPWATCH ───────────────────────────────────────────────────────── Item { + id: pageStopwatch readonly property int myIdx: 3 + property bool isCurrent: root._mode === "stopwatch" + property bool wasCurrent: false + property real parallaxFactor: Anim.style === "parallax" ? 0.3 : 1.0 + onIsCurrentChanged: { if (!isCurrent) wasCurrent = true; else wasCurrent = false; } + width: parent.width; height: parent.height - x: (myIdx - pagesContainer.animIdx) * width - visible: Math.abs(x) < width || root._mode === "stopwatch" + property real targetX: { + if (Anim.style === "none") return 0; + if (isCurrent) return 0; + if (myIdx < pagesContainer.pageIdx) return -width * parallaxFactor; + return width; + } + + x: targetX + Behavior on x { + enabled: Anim.style !== "none" + NumberAnimation { + duration: Anim.slow; easing.type: Anim.outExpo + onRunningChanged: { if (!running && !pageStopwatch.isCurrent) pageStopwatch.wasCurrent = false; } + } + } + + visible: isCurrent || wasCurrent Column { anchors.centerIn: parent; spacing: Math.round(12 * localScale) @@ -753,7 +846,7 @@ StatCard { ? Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b,0.2) : Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b,0.12) border.color: Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b,0.22); border.width: 1 - Behavior on color { ColorAnimation { duration: 100 } } + Behavior on color { ColorAnimation { duration: Anim.fast} } Text { anchors.centerIn: parent text: root._swRunning ? "Stop" : "Start" @@ -774,7 +867,7 @@ StatCard { ? Qt.rgba(1,1,1,0.1) : Qt.rgba(1,1,1,0.05) border.color: Qt.rgba(1,1,1,0.1); border.width: 1 - Behavior on color { ColorAnimation { duration: 100 } } + Behavior on color { ColorAnimation { duration: Anim.fast} } Text { anchors.centerIn: parent; text: "Reset" font.pixelSize: Math.round(10 * localScale); font.weight: Font.Medium diff --git a/src/services/home/PlayerCard.qml b/src/services/home/PlayerCard.qml index c82387b..f8b9c06 100644 --- a/src/services/home/PlayerCard.qml +++ b/src/services/home/PlayerCard.qml @@ -166,7 +166,7 @@ Item { blur: 0.5 blurMax: 32 saturation: 0.2 - Behavior on opacity { NumberAnimation { duration: 400 } } + Behavior on opacity { NumberAnimation { duration: Anim.slower} } } Rectangle { @@ -277,7 +277,7 @@ Item { : cH.hovered ? Qt.rgba(1,1,1,0.14) : Qt.rgba(1,1,1,0.06) border.color: isPlay ? Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.3) : "transparent" border.width: 1 - Behavior on color { ColorAnimation { duration: 100 } } + Behavior on color { ColorAnimation { duration: Anim.fast} } Text { anchors.centerIn: parent text: parent.dispIcon @@ -329,7 +329,7 @@ Item { anchors { left: parent.left; top: parent.top; bottom: parent.bottom } width: Math.max(radius * 2, parent.width * root._progress) radius: parent.radius; color: Theme.active - Behavior on width { NumberAnimation { duration: 200; easing.type: Easing.OutCubic } } + Behavior on width { NumberAnimation { duration: Anim.normal; easing.type: Anim.outCubic} } } } } @@ -381,7 +381,7 @@ Item { height: root._dropdownOpen ? (_rowH * root.filteredPlayers.length) : _rowH - Behavior on height { NumberAnimation { duration: 200; easing.type: Easing.OutCubic } } + Behavior on height { NumberAnimation { duration: Anim.normal; easing.type: Anim.outCubic} } radius: _rowH / 2 clip: true @@ -390,7 +390,7 @@ Item { ? Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.30) : "transparent" border.width: 1 - Behavior on border.color { ColorAnimation { duration: 150 } } + Behavior on border.color { ColorAnimation { duration: Anim.mediumFast} } // Stacks downward from the top Column { @@ -447,8 +447,8 @@ Item { visible: !isCurrent opacity: root._dropdownOpen ? 1 : 0 - Behavior on height { NumberAnimation { duration: 180; easing.type: Easing.OutCubic } } - Behavior on opacity { NumberAnimation { duration: 140 } } + Behavior on height { NumberAnimation { duration: Anim.mediumFast; easing.type: Anim.outCubic} } + Behavior on opacity { NumberAnimation { duration: Anim.color} } Row { anchors.centerIn: parent @@ -459,7 +459,7 @@ Item { text: root._playerIcon(modelData) font.pixelSize: Math.round(11 * localScale) color: rowH.hovered ? Qt.rgba(1,1,1,0.90) : Qt.rgba(1,1,1,0.55) - Behavior on color { ColorAnimation { duration: 100 } } + Behavior on color { ColorAnimation { duration: Anim.fast} } } Text { anchors.verticalCenter: parent.verticalCenter @@ -468,7 +468,7 @@ Item { color: rowH.hovered ? Qt.rgba(1,1,1,0.90) : Qt.rgba(1,1,1,0.55) width: Math.min(implicitWidth, Math.round(120 * localScale)) elide: Text.ElideRight - Behavior on color { ColorAnimation { duration: 100 } } + Behavior on color { ColorAnimation { duration: Anim.fast} } } } @@ -507,7 +507,7 @@ Item { height: Math.max(2, _amp * Math.round(32 * localScale)) radius: width / 2 color: Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.25 + _amp * 0.65) - Behavior on height { NumberAnimation { duration: 50; easing.type: Easing.OutCubic } } + Behavior on height { NumberAnimation { duration: Anim.superFast; easing.type: Anim.outCubic} } } } } diff --git a/src/services/home/QuickSettings.qml b/src/services/home/QuickSettings.qml index 88a4add..74ea326 100644 --- a/src/services/home/QuickSettings.qml +++ b/src/services/home/QuickSettings.qml @@ -658,7 +658,7 @@ StatCard { anchors { left: parent.left; top: parent.top; bottom: parent.bottom } width: Math.max(parent.radius * 2, parent.width * root._brightVal) radius: parent.radius; color: Theme.active - Behavior on width { NumberAnimation { duration: 80; easing.type: Easing.OutCubic } } + Behavior on width { NumberAnimation { duration: Anim.superFast; easing.type: Anim.outCubic} } } MouseArea { anchors.fill: parent; cursorShape: Qt.PointingHandCursor @@ -681,7 +681,7 @@ StatCard { width: btw.thumbD; height: btw.thumbD; radius: btw.thumbD / 2 color: "#ffffff"; anchors.verticalCenter: parent.verticalCenter x: Math.max(0, Math.min(btw.width - width, root._brightVal * (btw.width - width))) - Behavior on x { NumberAnimation { duration: 80; easing.type: Easing.OutCubic } } + Behavior on x { NumberAnimation { duration: Anim.superFast; easing.type: Anim.outCubic} } } } @@ -737,14 +737,14 @@ StatCard { ? Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.30) : Qt.rgba(Theme.text.r, Theme.text.g, Theme.text.b, 0.10) border.width: 1 - Behavior on color { ColorAnimation { duration: 130 } } - Behavior on border.color { ColorAnimation { duration: 130 } } + Behavior on color { ColorAnimation { duration: Anim.color} } + Behavior on border.color { ColorAnimation { duration: Anim.color} } Rectangle { anchors { top: parent.top; right: parent.right; margins: Math.round(8 * localScale) } width: Math.round(6 * localScale); height: Math.round(6 * localScale); radius: width / 2 color: btn.on ? Theme.active : Qt.rgba(Theme.text.r, Theme.text.g, Theme.text.b, 0.18) - Behavior on color { ColorAnimation { duration: 130 } } + Behavior on color { ColorAnimation { duration: Anim.color} } } Column { @@ -753,12 +753,12 @@ StatCard { Text { text: btn.icon; font.pixelSize: Math.round(17 * localScale) color: btn.on ? Theme.active : Qt.rgba(Theme.text.r, Theme.text.g, Theme.text.b, 0.40) - Behavior on color { ColorAnimation { duration: 130 } } + Behavior on color { ColorAnimation { duration: Anim.color} } } Text { text: btn.label; font.pixelSize: Math.round(9 * localScale); font.weight: Font.Medium color: btn.on ? Theme.text : Qt.rgba(Theme.text.r, Theme.text.g, Theme.text.b, 0.45) - Behavior on color { ColorAnimation { duration: 130 } } + Behavior on color { ColorAnimation { duration: Anim.color} } } Text { visible: btn.sublabel !== "" @@ -902,8 +902,8 @@ StatCard { // Subtle entrance scale + fade opacity: root.filterPickerOpen ? 1 : 0 scale: root.filterPickerOpen ? 1 : 0.95 - Behavior on opacity { NumberAnimation { duration: 140; easing.type: Easing.OutCubic } } - Behavior on scale { NumberAnimation { duration: 140; easing.type: Easing.OutCubic } } + Behavior on opacity { NumberAnimation { duration: Anim.color; easing.type: Anim.outCubic} } + Behavior on scale { NumberAnimation { duration: Anim.color; easing.type: Anim.outCubic} } transformOrigin: Item.BottomRight // Dismiss when clicking outside the picker @@ -944,7 +944,7 @@ StatCard { color: isActive ? Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.14) : offH.hovered ? Qt.rgba(Theme.text.r, Theme.text.g, Theme.text.b, 0.07) : "transparent" - Behavior on color { ColorAnimation { duration: 100 } } + Behavior on color { ColorAnimation { duration: Anim.fast} } Row { anchors { left: parent.left; leftMargin: Math.round(10 * localScale); verticalCenter: parent.verticalCenter } @@ -954,14 +954,14 @@ StatCard { font.pixelSize: Math.round(9 * localScale) color: parent.parent.isActive ? Theme.active : Qt.rgba(Theme.text.r, Theme.text.g, Theme.text.b, 0.30) anchors.verticalCenter: parent.verticalCenter - Behavior on color { ColorAnimation { duration: 100 } } + Behavior on color { ColorAnimation { duration: Anim.fast} } } Text { text: "Off" font.pixelSize: Math.round(12 * localScale) color: parent.parent.isActive ? Theme.active : Qt.rgba(Theme.text.r, Theme.text.g, Theme.text.b, 0.65) anchors.verticalCenter: parent.verticalCenter - Behavior on color { ColorAnimation { duration: 100 } } + Behavior on color { ColorAnimation { duration: Anim.fast} } } } HoverHandler { id: offH; cursorShape: Qt.PointingHandCursor } @@ -987,7 +987,7 @@ StatCard { color: isActive ? Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.14) : itemH.hovered ? Qt.rgba(Theme.text.r, Theme.text.g, Theme.text.b, 0.07) : "transparent" - Behavior on color { ColorAnimation { duration: 100 } } + Behavior on color { ColorAnimation { duration: Anim.fast} } Row { anchors { left: parent.left; leftMargin: Math.round(10 * localScale); verticalCenter: parent.verticalCenter } @@ -997,7 +997,7 @@ StatCard { font.pixelSize: Math.round(9 * localScale) color: parent.parent.isActive ? Theme.active : Qt.rgba(Theme.text.r, Theme.text.g, Theme.text.b, 0.30) anchors.verticalCenter: parent.verticalCenter - Behavior on color { ColorAnimation { duration: 100 } } + Behavior on color { ColorAnimation { duration: Anim.fast} } } Text { text: modelData @@ -1006,7 +1006,7 @@ StatCard { anchors.verticalCenter: parent.verticalCenter elide: Text.ElideRight width: pickerCol.width - Math.round(38 * localScale) - Behavior on color { ColorAnimation { duration: 100 } } + Behavior on color { ColorAnimation { duration: Anim.fast} } } } HoverHandler { id: itemH; cursorShape: Qt.PointingHandCursor } diff --git a/src/services/notifications/NotificationList.qml b/src/services/notifications/NotificationList.qml index 48ddbf1..a98ec54 100644 --- a/src/services/notifications/NotificationList.qml +++ b/src/services/notifications/NotificationList.qml @@ -42,7 +42,7 @@ Item { anchors.fill: parent radius: 13 color: clearHover.containsMouse ? Qt.rgba(1,1,1,0.10) : "transparent" - Behavior on color { ColorAnimation { duration: 120 } } + Behavior on color { ColorAnimation { duration: Anim.color} } } Text { id: clearLabel @@ -153,7 +153,7 @@ Item { Rectangle { anchors.fill: parent color: cardHover.containsMouse ? Qt.rgba(1, 1, 1, 0.05) : "transparent" - Behavior on color { ColorAnimation { duration: 120 } } + Behavior on color { ColorAnimation { duration: Anim.color} } } // Left urgency accent bar @@ -275,7 +275,7 @@ Item { color: actHover.containsMouse ? Qt.rgba(1,1,1,0.15) : Qt.rgba(1,1,1,0.07) - Behavior on color { ColorAnimation { duration: 100 } } + Behavior on color { ColorAnimation { duration: Anim.fast} } } Text { id: actionLbl @@ -301,7 +301,7 @@ Item { anchors.fill: parent radius: width / 2 color: xHover.containsMouse ? Qt.rgba(1,1,1,0.12) : "transparent" - Behavior on color { ColorAnimation { duration: 100 } } + Behavior on color { ColorAnimation { duration: Anim.fast} } } Text { anchors.centerIn: parent diff --git a/src/services/system/EnvyControl.qml b/src/services/system/EnvyControl.qml index e4a93b4..7935e81 100644 --- a/src/services/system/EnvyControl.qml +++ b/src/services/system/EnvyControl.qml @@ -138,14 +138,14 @@ Column { height: 24 radius: 12 color: root.dgpuEnabled ? Theme.active : Qt.rgba(1, 1, 1, 0.15) - Behavior on color { ColorAnimation { duration: 150 } } + Behavior on color { ColorAnimation { duration: Anim.mediumFast} } Rectangle { width: 18; height: 18; radius: 9 color: "white" anchors.verticalCenter: parent.verticalCenter x: root.dgpuEnabled ? parent.width - width - 3 : 3 - Behavior on x { NumberAnimation { duration: 150; easing.type: Easing.OutCubic } } + Behavior on x { NumberAnimation { duration: Anim.mediumFast; easing.type: Anim.outCubic} } } HoverHandler { cursorShape: Qt.PointingHandCursor } diff --git a/src/state/Popups.qml b/src/state/Popups.qml index 0f10773..7159e5c 100644 --- a/src/state/Popups.qml +++ b/src/state/Popups.qml @@ -35,8 +35,8 @@ QtObject { property bool quickTriggerHovered: false // ── Universal popup behavior settings ───────────────────────────────────── - property int slideDuration: Theme.animDuration - property int hoverCloseDelay: Theme.animDuration + 200 // delay after hover leaves before closing + property int slideDuration: Anim.transition + property int hoverCloseDelay: Anim.transition + 200 // delay after hover leaves before closing // ── Confirm dialog ──────────────────────────────────────────────────────── property bool confirmOpen: false diff --git a/src/theme/Anim.qml b/src/theme/Anim.qml new file mode 100644 index 0000000..428fc5c --- /dev/null +++ b/src/theme/Anim.qml @@ -0,0 +1,105 @@ +pragma Singleton +import QtQuick +import Quickshell +import Quickshell.Io + +QtObject { + id: root + + // "slide" | "parallax" | "none" + property string style: "slide" + + // Config persistence + readonly property string configPath: Quickshell.env("HOME") + "/.config/Brain_Shell/src/user_data/animation_prefs.json" + property var _prefsFile: FileView { + path: root.configPath + watchChanges: true + onFileChanged: reload() + onLoaded: { + var txt = text() + if (txt && txt !== "") { + try { + var obj = JSON.parse(txt) + if (obj.style && obj.style !== "") root.style = obj.style + if (obj.superFast) root.superFast = obj.superFast + if (obj.fast) root.fast = obj.fast + if (obj.color) root.color = obj.color + if (obj.mediumFast) root.mediumFast = obj.mediumFast + if (obj.normal) root.normal = obj.normal + if (obj.mediumSlow) root.mediumSlow = obj.mediumSlow + if (obj.slow) root.slow = obj.slow + if (obj.slower) root.slower = obj.slower + if (obj.verySlow) root.verySlow = obj.verySlow + if (obj.extraSlow) root.extraSlow = obj.extraSlow + if (obj.megaSlow) root.megaSlow = obj.megaSlow + if (obj.transition) root.transition = obj.transition + } catch(e) {} + } + } + } + + property var saveConfigProc: Process {} + + function setStyle(newStyle) { + root.style = newStyle + _save() + } + + function setSpeed(prop, val) { + root[prop] = val + _save() + } + + function _save() { + var json = JSON.stringify({ + "_comment_style": "Available styles: 'slide', 'parallax', 'none'", + "style": root.style, + "_comment_speeds": "You can override default animation speeds below (in milliseconds).", + "superFast": root.superFast, + "fast": root.fast, + "color": root.color, + "mediumFast": root.mediumFast, + "normal": root.normal, + "mediumSlow": root.mediumSlow, + "slow": root.slow, + "slower": root.slower, + "verySlow": root.verySlow, + "extraSlow": root.extraSlow, + "megaSlow": root.megaSlow, + "transition": root.transition + }, null, 4) + + saveConfigProc.command = [ + "bash", "-c", + "mkdir -p \"$(dirname '" + root.configPath + "')\" && " + + "cat << 'EOF' > '" + root.configPath + "'\n" + json + "\nEOF" + ] + saveConfigProc.running = true + } + // Standard durations + property int superFast: 80 + property int fast: 100 + property int color: 120 + property int mediumFast: 150 + property int normal: 200 + property int mediumSlow: 250 + property int slow: 350 + property int slower: 400 + property int verySlow: 500 + property int extraSlow: 600 + property int megaSlow: 900 + property int transition: 320 + + // Easings + property int outCubic: Easing.OutCubic + property int inOutCubic: Easing.InOutCubic + property int inOutSine: Easing.InOutSine + property int outExpo: Easing.OutExpo + property int outBack: Easing.OutBack + property int outQuad: Easing.OutQuad + property int inQuad: Easing.InQuad + property int inOutQuad: Easing.InOutQuad + property int outElastic: Easing.OutElastic + property int inCubic: Easing.InCubic + property int linear: Easing.Linear +} diff --git a/src/theme/Metrics.qml b/src/theme/Metrics.qml index 70d1970..d77fa0a 100644 --- a/src/theme/Metrics.qml +++ b/src/theme/Metrics.qml @@ -55,6 +55,4 @@ QtObject { property int wsPadding: 8 property int wsRadius: 16 - // -- Animations -- - property int animDuration: 320 } diff --git a/src/theme/Theme.qml b/src/theme/Theme.qml index e5d2f51..0fb4482 100644 --- a/src/theme/Theme.qml +++ b/src/theme/Theme.qml @@ -63,5 +63,4 @@ QtObject { property int wsPadding: Metrics.wsPadding property int wsRadius: Metrics.wsRadius - property int animDuration: Metrics.animDuration } diff --git a/src/theme/qmldir b/src/theme/qmldir index 41ac1ac..7f429b3 100644 --- a/src/theme/qmldir +++ b/src/theme/qmldir @@ -2,3 +2,4 @@ singleton Theme Theme.qml singleton Colors Colors.qml singleton Metrics Metrics.qml ColorLoader ColorLoader.qml +singleton Anim Anim.qml diff --git a/src/windows/Border.qml b/src/windows/Border.qml index 89eccf1..de14096 100644 --- a/src/windows/Border.qml +++ b/src/windows/Border.qml @@ -29,7 +29,7 @@ PanelWindow { margins { top: (edge !== "bottom") ? ShellState.focusMode ? Math.round(Theme.borderWidth * root.localScale) : Math.round((Theme.notchHeight-1) * root.localScale) : 0 - Behavior on top { NumberAnimation { duration: Theme.animDuration; easing.type: Easing.InOutCubic }} + Behavior on top { NumberAnimation { duration: Anim.transition; easing.type: Anim.inOutCubic}} bottom: (edge !== "bottom") ? radius : 0 } diff --git a/src/windows/ConfirmDialog.qml b/src/windows/ConfirmDialog.qml index acdc741..fd3ad8a 100644 --- a/src/windows/ConfirmDialog.qml +++ b/src/windows/ConfirmDialog.qml @@ -186,7 +186,7 @@ PanelWindow { height: Math.round(38 * localScale) radius: Math.round(Theme.cornerRadius * localScale) color: cancelHov.hovered ? Qt.rgba(1, 1, 1, 0.1) : Qt.rgba(1, 1, 1, 0.05) - Behavior on color { ColorAnimation { duration: 120 } } + Behavior on color { ColorAnimation { duration: Anim.color} } Text { anchors.centerIn: parent @@ -204,7 +204,7 @@ PanelWindow { height: Math.round(38 * localScale) radius: Math.round(Theme.cornerRadius * localScale) color: confirmHov.hovered ? "#cc3a3a" : "#993030" - Behavior on color { ColorAnimation { duration: 120 } } + Behavior on color { ColorAnimation { duration: Anim.color} } Text { anchors.centerIn: parent @@ -255,10 +255,10 @@ PanelWindow { target: spinnerCanvas from: 0 to: 360 - duration: 900 + duration: Anim.megaSlow loops: Animation.Infinite running: Popups.confirmRunning - easing.type: Easing.Linear + easing.type: Anim.linear } onPaint: { diff --git a/src/windows/TopBar.qml b/src/windows/TopBar.qml index a873808..348b4a4 100644 --- a/src/windows/TopBar.qml +++ b/src/windows/TopBar.qml @@ -32,12 +32,12 @@ PanelWindow { // PopupWindow is the one that must never have animated implicitHeight. implicitHeight: (ShellState.focusMode ? Math.round(Theme.borderWidth * root.localScale) : Math.round(Theme.notchHeight * root.localScale)) + 1 Behavior on implicitHeight { - NumberAnimation { duration: Theme.animDuration; easing.type: Easing.InOutCubic } + NumberAnimation { duration: Anim.transition; easing.type: Anim.inOutCubic} } exclusiveZone: ShellState.focusMode ? 0 : Math.round(Theme.exclusionGap * root.localScale) Behavior on exclusiveZone { - NumberAnimation { duration: Theme.animDuration; easing.type: Easing.InOutCubic } + NumberAnimation { duration: Anim.transition; easing.type: Anim.inOutCubic} } readonly property int lWidth: Math.max( @@ -56,7 +56,7 @@ PanelWindow { centerContent.implicitWidth + Math.round(Theme.notchPadding * 2 * root.localScale)) ) Behavior on cWidth { - NumberAnimation { duration: Theme.animDuration; easing.type: Easing.InOutCubic } + NumberAnimation { duration: Anim.transition; easing.type: Anim.inOutCubic} } // Width matches sizer open width: popupWidth + notchRadius (fw) in both popups @@ -74,7 +74,7 @@ PanelWindow { color: Theme.background opacity: ShellState.focusMode ? 1 : 0 Behavior on opacity { - NumberAnimation { duration: Theme.animDuration; easing.type: Easing.InOutCubic } + NumberAnimation { duration: Anim.transition; easing.type: Anim.inOutCubic} } } @@ -83,7 +83,7 @@ PanelWindow { anchors.fill: parent opacity: ShellState.focusMode ? 0 : 1 Behavior on opacity { - NumberAnimation { duration: Theme.animDuration; easing.type: Easing.InOutCubic } + NumberAnimation { duration: Anim.transition; easing.type: Anim.inOutCubic} } states: [ @@ -107,7 +107,7 @@ PanelWindow { transitions: [ Transition { // This animation ONLY runs when switching between popups (and toasts) and the base state. - NumberAnimation { property: "rWidth"; duration: Theme.animDuration; easing.type: Easing.InOutCubic } + NumberAnimation { property: "rWidth"; duration: Anim.transition; easing.type: Anim.inOutCubic} } ] diff --git a/src/windows/UpdatePopup.qml b/src/windows/UpdatePopup.qml index 18b7309..f7a00c6 100644 --- a/src/windows/UpdatePopup.qml +++ b/src/windows/UpdatePopup.qml @@ -94,7 +94,7 @@ PanelWindow { : (UpdateService.lastError !== "" && !UpdateService.updating) ? "#f38ba8" : Theme.active - Behavior on color { ColorAnimation { duration: 200 } } + Behavior on color { ColorAnimation { duration: Anim.normal} } } Item { visible: !UpdateService.updating @@ -104,7 +104,7 @@ PanelWindow { Rectangle { anchors.fill: parent; radius: Math.round(6 * localScale) color: xHov.hovered ? Qt.rgba(1,1,1,0.10) : "transparent" - Behavior on color { ColorAnimation { duration: 100 } } + Behavior on color { ColorAnimation { duration: Anim.fast} } } Text { anchors.centerIn: parent @@ -143,15 +143,15 @@ PanelWindow { : (UpdateService.lastError !== "" && !UpdateService.updating) ? "#f38ba8" : Theme.active - Behavior on color { ColorAnimation { duration: 200 } } + Behavior on color { ColorAnimation { duration: Anim.normal} } RotationAnimator { target: headerIcon from: 0; to: 360 - duration: 900 + duration: Anim.megaSlow loops: Animation.Infinite running: UpdateService.updating || UpdateService.checking - easing.type: Easing.Linear + easing.type: Anim.linear } } @@ -240,7 +240,7 @@ PanelWindow { : Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.13) border.color: Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.40) border.width: 1 - Behavior on color { ColorAnimation { duration: 120 } } + Behavior on color { ColorAnimation { duration: Anim.color} } Text { anchors.centerIn: parent text: "Update Now" @@ -256,7 +256,7 @@ PanelWindow { width: Math.round(58 * localScale); height: Math.round(30 * localScale); radius: Math.round(8 * localScale) color: skH.hovered ? Qt.rgba(1,1,1,0.08) : Qt.rgba(1,1,1,0.04) border.color: Qt.rgba(1,1,1,0.09); border.width: 1 - Behavior on color { ColorAnimation { duration: 120 } } + Behavior on color { ColorAnimation { duration: Anim.color} } Text { anchors.centerIn: parent; text: "Skip"; font.pixelSize: Math.round(11 * localScale); color: Qt.rgba(1,1,1,0.52) } HoverHandler { id: skH; cursorShape: Qt.PointingHandCursor } MouseArea { anchors.fill: parent; onClicked: UpdateService.dismiss() } @@ -267,7 +267,7 @@ PanelWindow { width: Math.round(82 * localScale); height: Math.round(30 * localScale); radius: Math.round(8 * localScale) color: disH.hovered ? Qt.rgba(1,1,1,0.06) : "transparent" border.color: Qt.rgba(1,1,1,0.07); border.width: 1 - Behavior on color { ColorAnimation { duration: 120 } } + Behavior on color { ColorAnimation { duration: Anim.color} } Text { anchors.centerIn: parent; text: "Disable"; font.pixelSize: Math.round(11 * localScale); color: Qt.rgba(1,1,1,0.28) } HoverHandler { id: disH; cursorShape: Qt.PointingHandCursor } MouseArea { anchors.fill: parent; onClicked: UpdateService.disableAutoUpdate() } @@ -321,7 +321,7 @@ PanelWindow { ? Qt.rgba(245/255, 196/255, 122/255, 0.22) : Qt.rgba(245/255, 196/255, 122/255, 0.10) border.color: Qt.rgba(245/255, 196/255, 122/255, 0.38); border.width: 1 - Behavior on color { ColorAnimation { duration: 120 } } + Behavior on color { ColorAnimation { duration: Anim.color} } Text { anchors.centerIn: parent text: "Stash & Update" @@ -337,7 +337,7 @@ PanelWindow { width: Math.round(72 * localScale); height: Math.round(30 * localScale); radius: Math.round(8 * localScale) color: cxH.hovered ? Qt.rgba(1,1,1,0.08) : Qt.rgba(1,1,1,0.04) border.color: Qt.rgba(1,1,1,0.09); border.width: 1 - Behavior on color { ColorAnimation { duration: 120 } } + Behavior on color { ColorAnimation { duration: Anim.color} } Text { anchors.centerIn: parent; text: "Cancel"; font.pixelSize: Math.round(11 * localScale); color: Qt.rgba(1,1,1,0.52) } HoverHandler { id: cxH; cursorShape: Qt.PointingHandCursor } MouseArea { anchors.fill: parent; onClicked: UpdateService.dismiss() } @@ -365,7 +365,7 @@ PanelWindow { width: Math.round(72 * localScale); height: Math.round(30 * localScale); radius: Math.round(8 * localScale) color: dmH.hovered ? Qt.rgba(1,1,1,0.08) : Qt.rgba(1,1,1,0.04) border.color: Qt.rgba(1,1,1,0.09); border.width: 1 - Behavior on color { ColorAnimation { duration: 120 } } + Behavior on color { ColorAnimation { duration: Anim.color} } Text { anchors.centerIn: parent; text: "Dismiss"; font.pixelSize: Math.round(11 * localScale); color: Qt.rgba(1,1,1,0.52) } HoverHandler { id: dmH; cursorShape: Qt.PointingHandCursor } MouseArea { anchors.fill: parent; onClicked: UpdateService.dismiss() } @@ -406,7 +406,7 @@ PanelWindow { : Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.09) border.color: Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.30) border.width: 1 - Behavior on color { ColorAnimation { duration: 120 } } + Behavior on color { ColorAnimation { duration: Anim.color} } Text { anchors.centerIn: parent; text: "Retry"; font.pixelSize: Math.round(11 * localScale); color: Theme.active } HoverHandler { id: rtH; cursorShape: Qt.PointingHandCursor } MouseArea { anchors.fill: parent; onClicked: UpdateService.check() } @@ -417,7 +417,7 @@ PanelWindow { width: Math.round(72 * localScale); height: Math.round(30 * localScale); radius: Math.round(8 * localScale) color: clH.hovered ? Qt.rgba(1,1,1,0.08) : Qt.rgba(1,1,1,0.04) border.color: Qt.rgba(1,1,1,0.09); border.width: 1 - Behavior on color { ColorAnimation { duration: 120 } } + Behavior on color { ColorAnimation { duration: Anim.color} } Text { anchors.centerIn: parent; text: "Close"; font.pixelSize: Math.round(11 * localScale); color: Qt.rgba(1,1,1,0.52) } HoverHandler { id: clH; cursorShape: Qt.PointingHandCursor } MouseArea { anchors.fill: parent; onClicked: UpdateService.dismiss() } From 9b730524184808da68fa7e23f11b13d7910bdd70 Mon Sep 17 00:00:00 2001 From: Brainitech Date: Sun, 21 Jun 2026 15:16:23 +0530 Subject: [PATCH 4/4] Fix: Quickshell import versioning and added global curve/speed modifiers --- src/theme/Anim.qml | 123 ++++++++++++++++++++++++++------------------- 1 file changed, 71 insertions(+), 52 deletions(-) diff --git a/src/theme/Anim.qml b/src/theme/Anim.qml index 428fc5c..46fe07f 100644 --- a/src/theme/Anim.qml +++ b/src/theme/Anim.qml @@ -9,6 +9,9 @@ QtObject { // "slide" | "parallax" | "none" property string style: "slide" + property real speedMultiplier: 1.0 + property string curveStyle: "smooth" + // Config persistence readonly property string configPath: Quickshell.env("HOME") + "/.config/Brain_Shell/src/user_data/animation_prefs.json" property var _prefsFile: FileView { @@ -21,18 +24,8 @@ QtObject { try { var obj = JSON.parse(txt) if (obj.style && obj.style !== "") root.style = obj.style - if (obj.superFast) root.superFast = obj.superFast - if (obj.fast) root.fast = obj.fast - if (obj.color) root.color = obj.color - if (obj.mediumFast) root.mediumFast = obj.mediumFast - if (obj.normal) root.normal = obj.normal - if (obj.mediumSlow) root.mediumSlow = obj.mediumSlow - if (obj.slow) root.slow = obj.slow - if (obj.slower) root.slower = obj.slower - if (obj.verySlow) root.verySlow = obj.verySlow - if (obj.extraSlow) root.extraSlow = obj.extraSlow - if (obj.megaSlow) root.megaSlow = obj.megaSlow - if (obj.transition) root.transition = obj.transition + if (obj.speed_multiplier) root.speedMultiplier = obj.speed_multiplier + if (obj.curve && obj.curve !== "") root.curveStyle = obj.curve } catch(e) {} } } @@ -45,8 +38,13 @@ QtObject { _save() } - function setSpeed(prop, val) { - root[prop] = val + function setSpeedMultiplier(val) { + root.speedMultiplier = val + _save() + } + + function setCurve(val) { + root.curveStyle = val _save() } @@ -54,19 +52,10 @@ QtObject { var json = JSON.stringify({ "_comment_style": "Available styles: 'slide', 'parallax', 'none'", "style": root.style, - "_comment_speeds": "You can override default animation speeds below (in milliseconds).", - "superFast": root.superFast, - "fast": root.fast, - "color": root.color, - "mediumFast": root.mediumFast, - "normal": root.normal, - "mediumSlow": root.mediumSlow, - "slow": root.slow, - "slower": root.slower, - "verySlow": root.verySlow, - "extraSlow": root.extraSlow, - "megaSlow": root.megaSlow, - "transition": root.transition + "_comment_speed": "Multiplier for all animations. 1.0 is default. 0.5 is 2x faster, 2.0 is 2x slower.", + "speed_multiplier": root.speedMultiplier, + "_comment_curve": "Available curves: 'smooth', 'spring', 'linear', 'cinematic'", + "curve": root.curveStyle }, null, 4) saveConfigProc.command = [ @@ -76,30 +65,60 @@ QtObject { ] saveConfigProc.running = true } - // Standard durations - property int superFast: 80 - property int fast: 100 - property int color: 120 - property int mediumFast: 150 - property int normal: 200 - property int mediumSlow: 250 - property int slow: 350 - property int slower: 400 - property int verySlow: 500 - property int extraSlow: 600 - property int megaSlow: 900 - property int transition: 320 - // Easings - property int outCubic: Easing.OutCubic - property int inOutCubic: Easing.InOutCubic - property int inOutSine: Easing.InOutSine - property int outExpo: Easing.OutExpo - property int outBack: Easing.OutBack - property int outQuad: Easing.OutQuad - property int inQuad: Easing.InQuad - property int inOutQuad: Easing.InOutQuad - property int outElastic: Easing.OutElastic - property int inCubic: Easing.InCubic - property int linear: Easing.Linear + // Standard durations automatically scaled by speedMultiplier + readonly property int superFast: Math.max(0, Math.round(80 * speedMultiplier)) + readonly property int fast: Math.max(0, Math.round(100 * speedMultiplier)) + readonly property int color: Math.max(0, Math.round(120 * speedMultiplier)) + readonly property int mediumFast: Math.max(0, Math.round(150 * speedMultiplier)) + readonly property int normal: Math.max(0, Math.round(200 * speedMultiplier)) + readonly property int mediumSlow: Math.max(0, Math.round(250 * speedMultiplier)) + readonly property int slow: Math.max(0, Math.round(350 * speedMultiplier)) + readonly property int slower: Math.max(0, Math.round(400 * speedMultiplier)) + readonly property int verySlow: Math.max(0, Math.round(500 * speedMultiplier)) + readonly property int extraSlow: Math.max(0, Math.round(600 * speedMultiplier)) + readonly property int megaSlow: Math.max(0, Math.round(900 * speedMultiplier)) + readonly property int transition: Math.max(0, Math.round(320 * speedMultiplier)) + + // Global Curve Modifier + readonly property int globalCurve: { + if (curveStyle === "spring") return Easing.OutBack; + if (curveStyle === "cinematic") return Easing.InOutCubic; + if (curveStyle === "linear") return Easing.Linear; + return Easing.OutExpo; // Default to smooth + } + + // Easings (Mapping legacy bindings to the new global curve where appropriate) + // To ensure a truly unified feel, we route the common transition easings through globalCurve. + readonly property int outCubic: globalCurve + readonly property int inOutCubic: globalCurve + readonly property int outExpo: globalCurve + readonly property int outBack: globalCurve + + // Explicit curves for specific UI micro-interactions (not globally mapped unless requested) + readonly property int inOutSine: Easing.InOutSine + readonly property int outQuad: Easing.OutQuad + readonly property int inQuad: Easing.InQuad + readonly property int inOutQuad: Easing.InOutQuad + readonly property int outElastic: Easing.OutElastic + readonly property int inCubic: Easing.InCubic + readonly property int linear: Easing.Linear + + Component.onCompleted: { + // Auto-create the JSON file if it doesn't exist yet on startup + var initProc = Qt.createQmlObject('import QtQuick; import Quickshell.Io; Process { }', root, "InitConfigProc") + initProc.command = [ + "bash", "-c", + "if [ ! -f '" + root.configPath + "' ]; then mkdir -p \"$(dirname '" + root.configPath + "')\" && cat << 'EOF' > '" + root.configPath + "'\n" + + "{\n" + + " \"_comment_style\": \"Available styles: 'slide', 'parallax', 'none'\",\n" + + " \"style\": \"slide\",\n" + + " \"_comment_speed\": \"Multiplier for all animations. 1.0 is default. 0.5 is 2x faster, 2.0 is 2x slower.\",\n" + + " \"speed_multiplier\": 1.0,\n" + + " \"_comment_curve\": \"Available curves: 'smooth', 'spring', 'linear', 'cinematic'\",\n" + + " \"curve\": \"smooth\"\n" + + "}\nEOF\nfi" + ] + initProc.running = true + } }