1
0
mirror of https://github.com/AvengeMedia/DankMaterialShell.git synced 2026-05-03 02:52:07 -04:00

numerous animation improvements, convert a bunch of stuff to use

Animator, etc.
This commit is contained in:
bbedward
2026-04-30 16:54:33 -04:00
committed by purian23
parent 7138c546e1
commit 9018002959
67 changed files with 1525 additions and 989 deletions

View File

@@ -26,9 +26,7 @@ Rectangle {
spacing: 2
StyledText {
text: keyboardHints.enterToPaste
? I18n.tr("↑/↓: Navigate • Enter: Paste • Del: Delete • F10: Help", "Keyboard hints when enter-to-paste is enabled")
: I18n.tr("↑/↓: Navigate • Enter/Ctrl+C: Copy • Del: Delete • F10: Help")
text: keyboardHints.enterToPaste ? I18n.tr("↑/↓: Navigate • Enter: Paste • Del: Delete • F10: Help", "Keyboard hints when enter-to-paste is enabled") : I18n.tr("↑/↓: Navigate • Enter/Ctrl+C: Copy • Del: Delete • F10: Help")
font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceText
anchors.horizontalCenter: parent.horizontalCenter
@@ -43,7 +41,7 @@ Rectangle {
}
Behavior on opacity {
NumberAnimation {
OpacityAnimator {
duration: Theme.shortDuration
easing.type: Theme.standardEasing
}

View File

@@ -154,6 +154,36 @@ Item {
});
}
property bool _animSyncQueued: false
function _queueAnimSync() {
if (_animSyncQueued)
return;
_animSyncQueued = true;
Qt.callLater(() => {
if (root && typeof root._flushAnimSync === "function")
root._flushAnimSync();
});
}
function _flushAnimSync() {
_animSyncQueued = false;
_syncModalAnim();
}
property bool _bodySyncQueued: false
function _queueBodySync() {
if (_bodySyncQueued)
return;
_bodySyncQueued = true;
Qt.callLater(() => {
if (root && typeof root._flushBodySync === "function")
root._flushBodySync();
});
}
function _flushBodySync() {
_bodySyncQueued = false;
_syncModalBody();
}
function _syncModalAnim() {
if (!frameOwnsConnectedChrome || !_chromeClaimId)
return;
@@ -185,10 +215,10 @@ Item {
onFrameOwnsConnectedChromeChanged: _syncModalChromeState()
onResolvedConnectedBarSideChanged: _queueFullSync()
onShouldBeVisibleChanged: _queueFullSync()
onAlignedXChanged: _syncModalBody()
onAlignedYChanged: _syncModalBody()
onAlignedWidthChanged: _syncModalBody()
onAlignedHeightChanged: _syncModalBody()
onAlignedXChanged: _queueBodySync()
onAlignedYChanged: _queueBodySync()
onAlignedWidthChanged: _queueBodySync()
onAlignedHeightChanged: _queueBodySync()
Component.onDestruction: _releaseModalChrome()
@@ -456,8 +486,8 @@ Item {
readonly property real s: Math.min(1, modalContainer.scaleValue)
blurX: modalContainer.x + modalContainer.width * (1 - s) * 0.5 + Theme.snap(modalContainer.animX, root.dpr)
blurY: modalContainer.y + modalContainer.height * (1 - s) * 0.5 + Theme.snap(modalContainer.animY, root.dpr)
blurWidth: (root.shouldBeVisible && animatedContent.opacity > 0 && !root.frameOwnsConnectedChrome) ? modalContainer.width * s : 0
blurHeight: (root.shouldBeVisible && animatedContent.opacity > 0 && !root.frameOwnsConnectedChrome) ? modalContainer.height * s : 0
blurWidth: (root.shouldBeVisible && animatedContent.publishedOpacity > 0 && !root.frameOwnsConnectedChrome) ? modalContainer.width * s : 0
blurHeight: (root.shouldBeVisible && animatedContent.publishedOpacity > 0 && !root.frameOwnsConnectedChrome) ? modalContainer.height * s : 0
blurRadius: root.effectiveCornerRadius
}
@@ -666,9 +696,9 @@ Item {
property real animY: root.shouldBeVisible ? 0 : root.frozenMotionOffsetY
onAnimXChanged: if (root.frameOwnsConnectedChrome)
root._syncModalAnim()
root._queueAnimSync()
onAnimYChanged: if (root.frameOwnsConnectedChrome)
root._syncModalAnim()
root._queueAnimSync()
readonly property real computedScaleCollapsed: root.animationScaleCollapsed
property real scaleValue: root.shouldBeVisible ? 1.0 : computedScaleCollapsed
@@ -711,11 +741,23 @@ Item {
id: animatedContent
anchors.fill: parent
clip: false
property real publishedOpacity: (Theme.isDirectionalEffect && !Theme.isConnectedEffect) ? 1 : (root.shouldBeVisible ? 1 : 0)
opacity: (Theme.isDirectionalEffect && !Theme.isConnectedEffect) ? 1 : (root.shouldBeVisible ? 1 : 0)
scale: modalContainer.scaleValue
transformOrigin: Item.Center
Behavior on opacity {
enabled: root.animationsEnabled && (!Theme.isDirectionalEffect || Theme.isConnectedEffect)
OpacityAnimator {
duration: Math.round(Theme.variantDuration(animationDuration, root.shouldBeVisible) * Theme.variantOpacityDurationScale)
easing.type: Easing.BezierSpline
easing.bezierCurve: root.shouldBeVisible ? root.animationEnterCurve : root.animationExitCurve
}
}
Behavior on publishedOpacity {
enabled: root.animationsEnabled && (!Theme.isDirectionalEffect || Theme.isConnectedEffect)
NumberAnimation {
duration: Math.round(Theme.variantDuration(animationDuration, root.shouldBeVisible) * Theme.variantOpacityDurationScale)

View File

@@ -241,8 +241,8 @@ Item {
readonly property real s: Math.min(1, modalContainer.scaleValue)
blurX: modalContainer.x + modalContainer.width * (1 - s) * 0.5 + Theme.snap(modalContainer.animX, root.dpr)
blurY: modalContainer.y + modalContainer.height * (1 - s) * 0.5 + Theme.snap(modalContainer.animY, root.dpr)
blurWidth: (shouldBeVisible && animatedContent.opacity > 0) ? modalContainer.width * s : 0
blurHeight: (shouldBeVisible && animatedContent.opacity > 0) ? modalContainer.height * s : 0
blurWidth: (shouldBeVisible && animatedContent.publishedOpacity > 0) ? modalContainer.width * s : 0
blurHeight: (shouldBeVisible && animatedContent.publishedOpacity > 0) ? modalContainer.height * s : 0
blurRadius: root.cornerRadius
}
@@ -318,7 +318,8 @@ Item {
Behavior on opacity {
enabled: root.animationsEnabled
DankAnim {
OpacityAnimator {
easing.type: Easing.BezierSpline
duration: root.animationDuration
easing.bezierCurve: root.shouldBeVisible ? root.animationEnterCurve : root.animationExitCurve
}
@@ -398,12 +399,24 @@ Item {
id: animatedContent
anchors.fill: parent
clip: false
property real publishedOpacity: root.shouldBeVisible ? 1 : 0
opacity: root.shouldBeVisible ? 1 : 0
scale: modalContainer.scaleValue
x: Theme.snap(modalContainer.animX, root.dpr) + (parent.width - width) * (1 - modalContainer.scaleValue) * 0.5
y: Theme.snap(modalContainer.animY, root.dpr) + (parent.height - height) * (1 - modalContainer.scaleValue) * 0.5
Behavior on opacity {
enabled: root.animationsEnabled
OpacityAnimator {
duration: animationDuration
easing.type: Easing.BezierSpline
easing.bezierCurve: root.shouldBeVisible ? root.animationEnterCurve : root.animationExitCurve
}
}
Behavior on publishedOpacity {
enabled: root.animationsEnabled
NumberAnimation {
duration: animationDuration

View File

@@ -250,6 +250,36 @@ Item {
});
}
property bool _animSyncQueued: false
function _queueAnimSync() {
if (_animSyncQueued)
return;
_animSyncQueued = true;
Qt.callLater(() => {
if (root && typeof root._flushAnimSync === "function")
root._flushAnimSync();
});
}
function _flushAnimSync() {
_animSyncQueued = false;
_syncModalAnim();
}
property bool _bodySyncQueued: false
function _queueBodySync() {
if (_bodySyncQueued)
return;
_bodySyncQueued = true;
Qt.callLater(() => {
if (root && typeof root._flushBodySync === "function")
root._flushBodySync();
});
}
function _flushBodySync() {
_bodySyncQueued = false;
_syncModalBody();
}
function _syncModalAnim() {
if (!frameOwnsConnectedChrome || !_chromeClaimId)
return;
@@ -281,10 +311,10 @@ Item {
onFrameOwnsConnectedChromeChanged: _syncModalChromeState()
onResolvedConnectedBarSideChanged: _queueFullSync()
onSpotlightOpenChanged: _queueFullSync()
onAlignedXChanged: _syncModalBody()
onAlignedYChanged: _syncModalBody()
onAlignedWidthChanged: _syncModalBody()
onAlignedHeightChanged: _syncModalBody()
onAlignedXChanged: _queueBodySync()
onAlignedYChanged: _queueBodySync()
onAlignedWidthChanged: _queueBodySync()
onAlignedHeightChanged: _queueBodySync()
Component.onDestruction: _releaseModalChrome()
@@ -571,7 +601,8 @@ Item {
Behavior on opacity {
enabled: root.animationsEnabled && (!Theme.isDirectionalEffect || Theme.isConnectedEffect)
DankAnim {
NumberAnimation {
easing.type: Easing.BezierSpline
duration: Math.round(Theme.variantDuration(root.launcherAnimationDuration, launcherMotionVisible) * Theme.variantOpacityDurationScale)
easing.bezierCurve: launcherMotionVisible ? root.launcherEnterCurve : root.launcherExitCurve
}
@@ -597,8 +628,8 @@ Item {
readonly property real s: Math.min(1, contentContainer.scaleValue)
blurX: root._ccX + root.alignedWidth * (1 - s) * 0.5 + Theme.snap(contentContainer.animX, root.dpr)
blurY: root._ccY + root.alignedHeight * (1 - s) * 0.5 + Theme.snap(contentContainer.animY, root.dpr)
blurWidth: (root.spotlightOpen || root.isClosing) && contentWrapper.opacity > 0 && !root.frameOwnsConnectedChrome ? root.alignedWidth * s : 0
blurHeight: (root.spotlightOpen || root.isClosing) && contentWrapper.opacity > 0 && !root.frameOwnsConnectedChrome ? root.alignedHeight * s : 0
blurWidth: (root.spotlightOpen || root.isClosing) && contentWrapper.publishedOpacity > 0 && !root.frameOwnsConnectedChrome ? root.alignedWidth * s : 0
blurHeight: (root.spotlightOpen || root.isClosing) && contentWrapper.publishedOpacity > 0 && !root.frameOwnsConnectedChrome ? root.alignedHeight * s : 0
blurRadius: root.cornerRadius
}
@@ -716,9 +747,9 @@ Item {
property real scaleValue: root._motionActive ? 1.0 : Theme.effectScaleCollapsed
onAnimXChanged: if (root.frameOwnsConnectedChrome)
root._syncModalAnim()
root._queueAnimSync()
onAnimYChanged: if (root.frameOwnsConnectedChrome)
root._syncModalAnim()
root._queueAnimSync()
Behavior on animX {
enabled: root.animationsEnabled
@@ -769,7 +800,7 @@ Item {
id: launcherShadowLayer
width: parent.width
height: parent.height
opacity: contentWrapper.opacity
opacity: contentWrapper.publishedOpacity
scale: contentWrapper.scale
x: contentWrapper.x
y: contentWrapper.y
@@ -787,20 +818,44 @@ Item {
id: contentWrapper
width: parent.width
height: parent.height
property bool _renderActive: (Theme.isDirectionalEffect && !Theme.isConnectedEffect) || launcherMotionVisible
property real publishedOpacity: (Theme.isDirectionalEffect && !Theme.isConnectedEffect) ? 1 : (launcherMotionVisible ? 1 : 0)
opacity: (Theme.isDirectionalEffect && !Theme.isConnectedEffect) ? 1 : (launcherMotionVisible ? 1 : 0)
visible: opacity > 0
visible: _renderActive
scale: contentContainer.scaleValue
x: Theme.snap(contentContainer.animX + (parent.width - width) * (1 - contentContainer.scaleValue) * 0.5, root.dpr)
y: Theme.snap(contentContainer.animY + (parent.height - height) * (1 - contentContainer.scaleValue) * 0.5, root.dpr)
Behavior on opacity {
enabled: root.animationsEnabled && (!Theme.isDirectionalEffect || Theme.isConnectedEffect)
DankAnim {
OpacityAnimator {
easing.type: Easing.BezierSpline
duration: Math.round(Theme.variantDuration(root.launcherAnimationDuration, launcherMotionVisible) * Theme.variantOpacityDurationScale)
easing.bezierCurve: launcherMotionVisible ? root.launcherEnterCurve : root.launcherExitCurve
}
}
Behavior on publishedOpacity {
enabled: root.animationsEnabled && (!Theme.isDirectionalEffect || Theme.isConnectedEffect)
NumberAnimation {
easing.type: Easing.BezierSpline
duration: Math.round(Theme.variantDuration(root.launcherAnimationDuration, launcherMotionVisible) * Theme.variantOpacityDurationScale)
easing.bezierCurve: launcherMotionVisible ? root.launcherEnterCurve : root.launcherExitCurve
onRunningChanged: if (!running && contentWrapper.publishedOpacity === 0)
contentWrapper._renderActive = false
}
}
Connections {
target: root
function onLauncherMotionVisibleChanged() {
if (root.launcherMotionVisible)
contentWrapper._renderActive = true;
}
}
MouseArea {
anchors.fill: parent
onPressed: mouse => mouse.accepted = true

View File

@@ -350,11 +350,11 @@ Item {
WindowBlur {
targetWindow: launcherWindow
readonly property real s: Math.min(1, modalContainer.scale)
readonly property real s: Math.min(1, modalContainer.publishedScale)
blurX: modalContainer.x + modalContainer.width * (1 - s) * 0.5
blurY: modalContainer.y + modalContainer.height * (1 - s) * 0.5
blurWidth: (contentVisible && modalContainer.opacity > 0) ? modalContainer.width * s : 0
blurHeight: (contentVisible && modalContainer.opacity > 0) ? modalContainer.height * s : 0
blurWidth: (contentVisible && modalContainer.publishedOpacity > 0) ? modalContainer.width * s : 0
blurHeight: (contentVisible && modalContainer.publishedOpacity > 0) ? modalContainer.height * s : 0
blurRadius: root.cornerRadius
}
@@ -411,23 +411,55 @@ Item {
y: root.contentY
width: root.alignedWidth
height: root.alignedHeight
visible: contentVisible || opacity > 0
visible: _renderActive
property bool _renderActive: contentVisible
property real publishedOpacity: contentVisible ? 1 : 0
property real publishedScale: contentVisible ? 1 : 0.96
opacity: contentVisible ? 1 : 0
scale: contentVisible ? 1 : 0.96
transformOrigin: Item.Center
Behavior on opacity {
DankAnim {
OpacityAnimator {
easing.type: Easing.BezierSpline
duration: Theme.modalAnimationDuration
easing.bezierCurve: contentVisible ? Theme.expressiveCurves.expressiveDefaultSpatial : Theme.expressiveCurves.emphasized
}
}
Behavior on scale {
DankAnim {
Behavior on publishedOpacity {
NumberAnimation {
easing.type: Easing.BezierSpline
duration: Theme.modalAnimationDuration
easing.bezierCurve: contentVisible ? Theme.expressiveCurves.expressiveDefaultSpatial : Theme.expressiveCurves.emphasized
onRunningChanged: if (!running && modalContainer.publishedOpacity === 0)
modalContainer._renderActive = false
}
}
Behavior on scale {
ScaleAnimator {
easing.type: Easing.BezierSpline
duration: Theme.modalAnimationDuration
easing.bezierCurve: contentVisible ? Theme.expressiveCurves.expressiveDefaultSpatial : Theme.expressiveCurves.emphasized
}
}
Behavior on publishedScale {
NumberAnimation {
easing.type: Easing.BezierSpline
duration: Theme.modalAnimationDuration
easing.bezierCurve: contentVisible ? Theme.expressiveCurves.expressiveDefaultSpatial : Theme.expressiveCurves.emphasized
}
}
Connections {
target: root
function onContentVisibleChanged() {
if (root.contentVisible)
modalContainer._renderActive = true;
}
}

View File

@@ -1,5 +1,4 @@
import QtQuick
import QtCore
import Quickshell.Io
import qs.Common
import qs.Widgets
@@ -22,9 +21,9 @@ Rectangle {
onShowFileInfoChanged: {
if (showFileInfo && currentFileName && currentPath) {
const fullPath = currentPath + "/" + currentFileName
fileStatProcess.selectedFilePath = fullPath
fileStatProcess.running = true
const fullPath = currentPath + "/" + currentFileName;
fileStatProcess.selectedFilePath = fullPath;
fileStatProcess.running = true;
}
}
@@ -38,14 +37,14 @@ Rectangle {
stdout: StdioCollector {
onStreamFinished: {
if (text && text.trim()) {
const parts = text.trim().split('|')
const parts = text.trim().split('|');
if (parts.length >= 4) {
fileStatProcess.fileStats = {
"modifiedTime": parts[0],
"permissions": parts[1],
"size": parseInt(parts[2]) || 0,
"fullPath": parts[3]
}
};
}
}
}
@@ -60,31 +59,31 @@ Rectangle {
onCurrentFileNameChanged: {
if (showFileInfo && currentFileName && currentPath) {
const fullPath = currentPath + "/" + currentFileName
const fullPath = currentPath + "/" + currentFileName;
if (fullPath !== fileStatProcess.selectedFilePath) {
fileStatProcess.selectedFilePath = fullPath
fileStatProcess.running = true
fileStatProcess.selectedFilePath = fullPath;
fileStatProcess.running = true;
}
}
}
function updateFileInfo(filePath, fileName, isDirectory) {
if (filePath && filePath !== fileStatProcess.selectedFilePath) {
fileStatProcess.selectedFilePath = filePath
currentFileName = fileName || ""
currentFileIsDir = isDirectory || false
fileStatProcess.selectedFilePath = filePath;
currentFileName = fileName || "";
currentFileIsDir = isDirectory || false;
let ext = ""
let ext = "";
if (!isDirectory && fileName) {
const lastDot = fileName.lastIndexOf('.')
const lastDot = fileName.lastIndexOf('.');
if (lastDot > 0) {
ext = fileName.substring(lastDot + 1).toLowerCase()
ext = fileName.substring(lastDot + 1).toLowerCase();
}
}
currentFileExtension = ext
currentFileExtension = ext;
if (showFileInfo) {
fileStatProcess.running = true
fileStatProcess.running = true;
}
}
}
@@ -100,10 +99,10 @@ Rectangle {
"permissions": "",
"extension": "",
"position": "N/A"
}
};
}
const hasValidFile = currentFileName !== ""
const hasValidFile = currentFileName !== "";
return {
"exists": hasValidFile,
"name": hasValidFile ? currentFileName : "Loading...",
@@ -113,7 +112,7 @@ Rectangle {
"permissions": fileStatProcess.fileStats ? fileStatProcess.fileStats.permissions : "Loading...",
"extension": currentFileExtension,
"position": sourceFolderModel ? ((selectedIndex + 1) + " of " + sourceFolderModel.count) : "N/A"
}
};
}
Column {
@@ -209,27 +208,27 @@ Rectangle {
function formatFileSize(bytes) {
if (bytes === 0 || !bytes) {
return "0 B"
return "0 B";
}
const k = 1024
const sizes = ['B', 'KB', 'MB', 'GB', 'TB']
const i = Math.floor(Math.log(bytes) / Math.log(k))
return parseFloat((bytes / Math.pow(k, i)).toFixed(1)) + ' ' + sizes[i]
const k = 1024;
const sizes = ['B', 'KB', 'MB', 'GB', 'TB'];
const i = Math.floor(Math.log(bytes) / Math.log(k));
return parseFloat((bytes / Math.pow(k, i)).toFixed(1)) + ' ' + sizes[i];
}
function formatDateTime(dateTimeString) {
if (!dateTimeString) {
return "Unknown"
return "Unknown";
}
const parts = dateTimeString.split(' ')
const parts = dateTimeString.split(' ');
if (parts.length >= 2) {
return parts[0] + " " + parts[1].split('.')[0]
return parts[0] + " " + parts[1].split('.')[0];
}
return dateTimeString
return dateTimeString;
}
Behavior on opacity {
NumberAnimation {
OpacityAnimator {
duration: Theme.shortDuration
easing.type: Theme.standardEasing
}

View File

@@ -42,7 +42,7 @@ Rectangle {
}
Behavior on opacity {
NumberAnimation {
OpacityAnimator {
duration: Theme.shortDuration
easing.type: Theme.standardEasing
}

View File

@@ -180,7 +180,7 @@ Item {
opacity: (root.hasRun && !root.isRunning) ? 1 : 0
Behavior on opacity {
NumberAnimation {
OpacityAnimator {
duration: Theme.mediumDuration
easing.type: Theme.emphasizedEasing
}

View File

@@ -22,7 +22,7 @@ Rectangle {
scale: mouseArea.pressed ? 0.97 : 1
Behavior on scale {
NumberAnimation {
ScaleAnimator {
duration: Theme.shortDuration
easing.type: Theme.emphasizedEasing
}

View File

@@ -772,7 +772,7 @@ DankModal {
opacity: root.showHoldHint ? 1 : 0.5
Behavior on opacity {
NumberAnimation {
OpacityAnimator {
duration: 150
}
}