mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2026-01-24 21:42:51 -05:00
feat: Updated DMS Animations
- Based on Material 3 Expressive - Now features custom timers options - Thanks to Soramane/Caelestia for converting Google's Material 3 Expressive curves
This commit is contained in:
@@ -25,10 +25,10 @@ Singleton {
|
||||
|
||||
enum AnimationSpeed {
|
||||
None,
|
||||
Shortest,
|
||||
Short,
|
||||
Medium,
|
||||
Long
|
||||
Long,
|
||||
Custom
|
||||
}
|
||||
|
||||
readonly property string defaultFontFamily: "Inter Variable"
|
||||
@@ -64,6 +64,7 @@ Singleton {
|
||||
property bool useFahrenheit: false
|
||||
property bool nightModeEnabled: false
|
||||
property int animationSpeed: SettingsData.AnimationSpeed.Short
|
||||
property int customAnimationDuration: 500
|
||||
property string wallpaperFillMode: "Fill"
|
||||
|
||||
property bool showLauncherButton: true
|
||||
@@ -489,6 +490,7 @@ Singleton {
|
||||
screenPreferences = settings.screenPreferences !== undefined ? settings.screenPreferences : ({})
|
||||
wallpaperFillMode = settings.wallpaperFillMode !== undefined ? settings.wallpaperFillMode : "Fill"
|
||||
animationSpeed = settings.animationSpeed !== undefined ? settings.animationSpeed : SettingsData.AnimationSpeed.Short
|
||||
customAnimationDuration = settings.customAnimationDuration !== undefined ? settings.customAnimationDuration : 500
|
||||
acMonitorTimeout = settings.acMonitorTimeout !== undefined ? settings.acMonitorTimeout : 0
|
||||
acLockTimeout = settings.acLockTimeout !== undefined ? settings.acLockTimeout : 0
|
||||
acSuspendTimeout = settings.acSuspendTimeout !== undefined ? settings.acSuspendTimeout : 0
|
||||
@@ -668,6 +670,7 @@ Singleton {
|
||||
"updaterTerminalAdditionalParams": updaterTerminalAdditionalParams,
|
||||
"screenPreferences": screenPreferences,
|
||||
"animationSpeed": animationSpeed,
|
||||
"customAnimationDuration": customAnimationDuration,
|
||||
"acMonitorTimeout": acMonitorTimeout,
|
||||
"acLockTimeout": acLockTimeout,
|
||||
"acSuspendTimeout": acSuspendTimeout,
|
||||
@@ -731,7 +734,7 @@ Singleton {
|
||||
"customPowerActionLock", "customPowerActionLogout", "customPowerActionSuspend",
|
||||
"customPowerActionHibernate", "customPowerActionReboot", "customPowerActionPowerOff",
|
||||
"updaterUseCustomCommand", "updaterCustomCommand", "updaterTerminalAdditionalParams",
|
||||
"screenPreferences", "animationSpeed", "acMonitorTimeout", "acLockTimeout",
|
||||
"screenPreferences", "animationSpeed", "customAnimationDuration", "acMonitorTimeout", "acLockTimeout",
|
||||
"acSuspendTimeout", "acHibernateTimeout", "batteryMonitorTimeout", "batteryLockTimeout",
|
||||
"batterySuspendTimeout", "batteryHibernateTimeout", "lockBeforeSuspend",
|
||||
"loginctlLockIntegration", "launchPrefix", "configVersion"
|
||||
@@ -1058,6 +1061,11 @@ Singleton {
|
||||
saveSettings()
|
||||
}
|
||||
|
||||
function setCustomAnimationDuration(duration) {
|
||||
customAnimationDuration = duration
|
||||
saveSettings()
|
||||
}
|
||||
|
||||
function setWallpaperFillMode(mode) {
|
||||
wallpaperFillMode = mode
|
||||
saveSettings()
|
||||
|
||||
@@ -313,6 +313,61 @@ Singleton {
|
||||
property int standardEasing: Easing.OutCubic
|
||||
property int emphasizedEasing: Easing.OutQuart
|
||||
|
||||
readonly property var expressiveCurves: {
|
||||
"emphasized": [0.05, 0, 2 / 15, 0.06, 1 / 6, 0.4, 5 / 24, 0.82, 0.25, 1, 1, 1],
|
||||
"emphasizedAccel": [0.3, 0, 0.8, 0.15, 1, 1],
|
||||
"emphasizedDecel": [0.05, 0.7, 0.1, 1, 1, 1],
|
||||
"standard": [0.2, 0, 0, 1, 1, 1],
|
||||
"standardAccel": [0.3, 0, 1, 1, 1, 1],
|
||||
"standardDecel": [0, 0, 0, 1, 1, 1],
|
||||
"expressiveFastSpatial": [0.42, 1.67, 0.21, 0.9, 1, 1],
|
||||
"expressiveDefaultSpatial": [0.38, 1.21, 0.22, 1, 1, 1],
|
||||
"expressiveEffects": [0.34, 0.8, 0.34, 1, 1, 1]
|
||||
}
|
||||
|
||||
readonly property var animationPresetDurations: {
|
||||
"none": 0,
|
||||
"short": 250,
|
||||
"medium": 500,
|
||||
"long": 750
|
||||
}
|
||||
|
||||
readonly property int currentAnimationBaseDuration: {
|
||||
if (typeof SettingsData === "undefined") return 500
|
||||
|
||||
if (SettingsData.animationSpeed === SettingsData.AnimationSpeed.Custom) {
|
||||
return SettingsData.customAnimationDuration
|
||||
}
|
||||
|
||||
const presetMap = [0, 250, 500, 750]
|
||||
return presetMap[SettingsData.animationSpeed] !== undefined ? presetMap[SettingsData.animationSpeed] : 500
|
||||
}
|
||||
|
||||
readonly property var expressiveDurations: {
|
||||
if (typeof SettingsData === "undefined") {
|
||||
return {
|
||||
"fast": 200,
|
||||
"normal": 400,
|
||||
"large": 600,
|
||||
"extraLarge": 1000,
|
||||
"expressiveFastSpatial": 350,
|
||||
"expressiveDefaultSpatial": 500,
|
||||
"expressiveEffects": 200
|
||||
}
|
||||
}
|
||||
|
||||
const baseDuration = currentAnimationBaseDuration
|
||||
return {
|
||||
"fast": baseDuration * 0.4,
|
||||
"normal": baseDuration * 0.8,
|
||||
"large": baseDuration * 1.2,
|
||||
"extraLarge": baseDuration * 2.0,
|
||||
"expressiveFastSpatial": baseDuration * 0.7,
|
||||
"expressiveDefaultSpatial": baseDuration,
|
||||
"expressiveEffects": baseDuration * 0.4
|
||||
}
|
||||
}
|
||||
|
||||
property real cornerRadius: typeof SettingsData !== "undefined" ? SettingsData.cornerRadius : 12
|
||||
property real spacingXS: 4
|
||||
property real spacingS: 8
|
||||
|
||||
@@ -35,8 +35,11 @@ PanelWindow {
|
||||
property bool closeOnEscapeKey: true
|
||||
property bool closeOnBackgroundClick: true
|
||||
property string animationType: "scale"
|
||||
property int animationDuration: Theme.shortDuration
|
||||
property var animationEasing: Theme.emphasizedEasing
|
||||
property int animationDuration: Theme.expressiveDurations.expressiveDefaultSpatial
|
||||
property real animationScaleCollapsed: 0.96
|
||||
property real animationOffset: Theme.spacingL
|
||||
property list<real> animationEnterCurve: Theme.expressiveCurves.expressiveDefaultSpatial
|
||||
property list<real> animationExitCurve: Theme.expressiveCurves.emphasized
|
||||
property color backgroundColor: Theme.surfaceContainer
|
||||
property color borderColor: Theme.outlineMedium
|
||||
property real borderWidth: 1
|
||||
@@ -104,7 +107,7 @@ PanelWindow {
|
||||
Timer {
|
||||
id: closeTimer
|
||||
|
||||
interval: animationDuration + 100
|
||||
interval: animationDuration + 120
|
||||
onTriggered: {
|
||||
visible = false
|
||||
}
|
||||
@@ -139,7 +142,8 @@ PanelWindow {
|
||||
Behavior on opacity {
|
||||
NumberAnimation {
|
||||
duration: root.animationDuration
|
||||
easing.type: root.animationEasing
|
||||
easing.type: Easing.BezierSpline
|
||||
easing.bezierCurve: root.shouldBeVisible ? root.animationEnterCurve : root.animationExitCurve
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -176,23 +180,67 @@ PanelWindow {
|
||||
border.width: root.borderWidth
|
||||
clip: false
|
||||
layer.enabled: true
|
||||
layer.smooth: true
|
||||
opacity: root.shouldBeVisible ? 1 : 0
|
||||
transform: root.animationType === "slide" ? slideTransform : null
|
||||
transform: [scaleTransform, motionTransform]
|
||||
|
||||
Scale {
|
||||
id: scaleTransform
|
||||
|
||||
origin.x: contentContainer.width / 2
|
||||
origin.y: contentContainer.height / 2
|
||||
xScale: root.shouldBeVisible ? 1 : root.animationScaleCollapsed
|
||||
yScale: root.shouldBeVisible ? 1 : root.animationScaleCollapsed
|
||||
|
||||
Behavior on xScale {
|
||||
NumberAnimation {
|
||||
duration: root.animationDuration
|
||||
easing.type: Easing.BezierSpline
|
||||
easing.bezierCurve: root.shouldBeVisible ? root.animationEnterCurve : root.animationExitCurve
|
||||
}
|
||||
}
|
||||
|
||||
Behavior on yScale {
|
||||
NumberAnimation {
|
||||
duration: root.animationDuration
|
||||
easing.type: Easing.BezierSpline
|
||||
easing.bezierCurve: root.shouldBeVisible ? root.animationEnterCurve : root.animationExitCurve
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Translate {
|
||||
id: slideTransform
|
||||
id: motionTransform
|
||||
|
||||
readonly property real rawX: root.shouldBeVisible ? 0 : 15
|
||||
readonly property real rawY: root.shouldBeVisible ? 0 : -30
|
||||
readonly property bool slide: root.animationType === "slide"
|
||||
readonly property real hiddenX: slide ? 15 : 0
|
||||
readonly property real hiddenY: slide ? -30 : root.animationOffset
|
||||
|
||||
x: Theme.snap(rawX, root.dpr)
|
||||
y: Theme.snap(rawY, root.dpr)
|
||||
x: Theme.snap(root.shouldBeVisible ? 0 : hiddenX, root.dpr)
|
||||
y: Theme.snap(root.shouldBeVisible ? 0 : hiddenY, root.dpr)
|
||||
|
||||
Behavior on x {
|
||||
NumberAnimation {
|
||||
duration: root.animationDuration
|
||||
easing.type: Easing.BezierSpline
|
||||
easing.bezierCurve: root.shouldBeVisible ? root.animationEnterCurve : root.animationExitCurve
|
||||
}
|
||||
}
|
||||
|
||||
Behavior on y {
|
||||
NumberAnimation {
|
||||
duration: root.animationDuration
|
||||
easing.type: Easing.BezierSpline
|
||||
easing.bezierCurve: root.shouldBeVisible ? root.animationEnterCurve : root.animationExitCurve
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Behavior on opacity {
|
||||
NumberAnimation {
|
||||
duration: animationDuration
|
||||
easing.type: animationEasing
|
||||
easing.type: Easing.BezierSpline
|
||||
easing.bezierCurve: root.shouldBeVisible ? root.animationEnterCurve : root.animationExitCurve
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1016,6 +1016,179 @@ Item {
|
||||
}
|
||||
}
|
||||
|
||||
// Animation Settings
|
||||
StyledRect {
|
||||
width: parent.width
|
||||
height: animationSection.implicitHeight + Theme.spacingL * 2
|
||||
radius: Theme.cornerRadius
|
||||
color: Theme.surfaceContainerHigh
|
||||
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2)
|
||||
border.width: 0
|
||||
|
||||
Column {
|
||||
id: animationSection
|
||||
|
||||
anchors.fill: parent
|
||||
anchors.margins: Theme.spacingL
|
||||
spacing: Theme.spacingM
|
||||
|
||||
Row {
|
||||
width: parent.width
|
||||
spacing: Theme.spacingM
|
||||
|
||||
DankIcon {
|
||||
name: "animation"
|
||||
size: Theme.iconSize
|
||||
color: Theme.primary
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
|
||||
StyledText {
|
||||
text: I18n.tr("Animation Speed")
|
||||
font.pixelSize: Theme.fontSizeLarge
|
||||
font.weight: Font.Medium
|
||||
color: Theme.surfaceText
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
width: parent.width
|
||||
height: childrenRect.height
|
||||
|
||||
DankButtonGroup {
|
||||
id: animationSpeedGroup
|
||||
x: (parent.width - width) / 2
|
||||
model: ["None", "Short", "Medium", "Long", "Custom"]
|
||||
selectionMode: "single"
|
||||
currentIndex: SettingsData.animationSpeed
|
||||
onSelectionChanged: (index, selected) => {
|
||||
if (selected) {
|
||||
SettingsData.setAnimationSpeed(index)
|
||||
}
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: SettingsData
|
||||
function onAnimationSpeedChanged() {
|
||||
animationSpeedGroup.currentIndex = SettingsData.animationSpeed
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Column {
|
||||
width: parent.width
|
||||
spacing: Theme.spacingM
|
||||
|
||||
Rectangle {
|
||||
width: parent.width
|
||||
height: 1
|
||||
color: Theme.outline
|
||||
opacity: 0.2
|
||||
}
|
||||
|
||||
Column {
|
||||
width: parent.width
|
||||
spacing: Theme.spacingS
|
||||
|
||||
Row {
|
||||
width: parent.width
|
||||
spacing: Theme.spacingM
|
||||
|
||||
StyledText {
|
||||
text: I18n.tr("Duration")
|
||||
font.pixelSize: Theme.fontSizeMedium
|
||||
color: Theme.surfaceText
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
|
||||
Item {
|
||||
width: 1
|
||||
height: 1
|
||||
}
|
||||
|
||||
StyledText {
|
||||
text: Theme.currentAnimationBaseDuration + "ms"
|
||||
font.pixelSize: Theme.fontSizeMedium
|
||||
color: Theme.primary
|
||||
font.weight: Font.Medium
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
}
|
||||
|
||||
Row {
|
||||
width: parent.width
|
||||
height: 40
|
||||
spacing: Theme.spacingM
|
||||
|
||||
StyledText {
|
||||
text: "0ms"
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
color: Theme.surfaceVariantText
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
|
||||
Item {
|
||||
width: parent.width - 100
|
||||
height: 40
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
|
||||
DankSlider {
|
||||
id: customDurationSlider
|
||||
anchors.fill: parent
|
||||
minimum: 0
|
||||
maximum: 750
|
||||
value: Theme.currentAnimationBaseDuration
|
||||
unit: "ms"
|
||||
showValue: false
|
||||
wheelEnabled: false
|
||||
|
||||
onSliderValueChanged: (newValue) => {
|
||||
SettingsData.setAnimationSpeed(SettingsData.AnimationSpeed.Custom)
|
||||
SettingsData.setCustomAnimationDuration(newValue)
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: SettingsData
|
||||
function onAnimationSpeedChanged() {
|
||||
if (SettingsData.animationSpeed !== SettingsData.AnimationSpeed.Custom) {
|
||||
customDurationSlider.value = Theme.currentAnimationBaseDuration
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: Theme
|
||||
function onCurrentAnimationBaseDurationChanged() {
|
||||
if (SettingsData.animationSpeed !== SettingsData.AnimationSpeed.Custom) {
|
||||
customDurationSlider.value = Theme.currentAnimationBaseDuration
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
StyledText {
|
||||
text: "750ms"
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
color: Theme.surfaceVariantText
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
}
|
||||
|
||||
StyledText {
|
||||
text: I18n.tr("Select a preset or drag the slider to customize")
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
color: Theme.surfaceVariantText
|
||||
wrapMode: Text.WordWrap
|
||||
width: parent.width
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
StyledRect {
|
||||
width: parent.width
|
||||
height: dynamicThemeSection.implicitHeight + Theme.spacingL * 2
|
||||
@@ -1189,62 +1362,6 @@ Item {
|
||||
}
|
||||
}
|
||||
|
||||
// Animation Settings
|
||||
StyledRect {
|
||||
width: parent.width
|
||||
height: animationSection.implicitHeight + Theme.spacingL * 2
|
||||
radius: Theme.cornerRadius
|
||||
color: Theme.surfaceContainerHigh
|
||||
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2)
|
||||
border.width: 0
|
||||
|
||||
Column {
|
||||
id: animationSection
|
||||
|
||||
anchors.fill: parent
|
||||
anchors.margins: Theme.spacingL
|
||||
spacing: Theme.spacingM
|
||||
|
||||
Row {
|
||||
width: parent.width
|
||||
spacing: Theme.spacingM
|
||||
|
||||
DankIcon {
|
||||
name: "animation"
|
||||
size: Theme.iconSize
|
||||
color: Theme.primary
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
|
||||
StyledText {
|
||||
text: I18n.tr("Animation Speed")
|
||||
font.pixelSize: Theme.fontSizeLarge
|
||||
font.weight: Font.Medium
|
||||
color: Theme.surfaceText
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
width: parent.width
|
||||
height: childrenRect.height
|
||||
|
||||
DankButtonGroup {
|
||||
id: animationSpeedGroup
|
||||
x: (parent.width - width) / 2
|
||||
model: ["None", "Shortest", "Short", "Medium", "Long"]
|
||||
selectionMode: "single"
|
||||
currentIndex: SettingsData.animationSpeed
|
||||
onSelectionChanged: (index, selected) => {
|
||||
if (selected) {
|
||||
SettingsData.setAnimationSpeed(index)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
StyledRect {
|
||||
width: parent.width
|
||||
height: soundsSection.implicitHeight + Theme.spacingL * 2
|
||||
|
||||
@@ -19,8 +19,11 @@ PanelWindow {
|
||||
property real triggerWidth: 40
|
||||
property string triggerSection: ""
|
||||
property string positioning: "center"
|
||||
property int animationDuration: Theme.shortDuration
|
||||
property var animationEasing: Theme.emphasizedEasing
|
||||
property int animationDuration: Theme.expressiveDurations.expressiveDefaultSpatial
|
||||
property real animationScaleCollapsed: 0.96
|
||||
property real animationOffset: Theme.spacingL
|
||||
property list<real> animationEnterCurve: Theme.expressiveCurves.expressiveDefaultSpatial
|
||||
property list<real> animationExitCurve: Theme.expressiveCurves.emphasized
|
||||
property bool shouldBeVisible: false
|
||||
|
||||
signal opened
|
||||
@@ -48,7 +51,7 @@ PanelWindow {
|
||||
|
||||
Timer {
|
||||
id: closeTimer
|
||||
interval: animationDuration + 50
|
||||
interval: animationDuration + 120
|
||||
onTriggered: {
|
||||
if (!shouldBeVisible) {
|
||||
visible = false
|
||||
@@ -126,13 +129,72 @@ PanelWindow {
|
||||
height: alignedHeight
|
||||
active: root.visible
|
||||
asynchronous: false
|
||||
transformOrigin: Item.Center
|
||||
layer.enabled: Quickshell.env("DMS_DISABLE_LAYER") !== "true"
|
||||
layer.smooth: true
|
||||
opacity: shouldBeVisible ? 1 : 0
|
||||
transform: [scaleTransform, motionTransform]
|
||||
|
||||
Scale {
|
||||
id: scaleTransform
|
||||
|
||||
origin.x: contentLoader.width / 2
|
||||
origin.y: contentLoader.height / 2
|
||||
xScale: root.shouldBeVisible ? 1 : root.animationScaleCollapsed
|
||||
yScale: root.shouldBeVisible ? 1 : root.animationScaleCollapsed
|
||||
|
||||
Behavior on xScale {
|
||||
NumberAnimation {
|
||||
duration: root.animationDuration
|
||||
easing.type: Easing.BezierSpline
|
||||
easing.bezierCurve: root.shouldBeVisible ? root.animationEnterCurve : root.animationExitCurve
|
||||
}
|
||||
}
|
||||
|
||||
Behavior on yScale {
|
||||
NumberAnimation {
|
||||
duration: root.animationDuration
|
||||
easing.type: Easing.BezierSpline
|
||||
easing.bezierCurve: root.shouldBeVisible ? root.animationEnterCurve : root.animationExitCurve
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Translate {
|
||||
id: motionTransform
|
||||
|
||||
readonly property bool barTop: SettingsData.dankBarPosition === SettingsData.Position.Top
|
||||
readonly property bool barBottom: SettingsData.dankBarPosition === SettingsData.Position.Bottom
|
||||
readonly property bool barLeft: SettingsData.dankBarPosition === SettingsData.Position.Left
|
||||
readonly property bool barRight: SettingsData.dankBarPosition === SettingsData.Position.Right
|
||||
readonly property real hiddenX: barLeft ? root.animationOffset : (barRight ? -root.animationOffset : 0)
|
||||
readonly property real hiddenY: barBottom ? -root.animationOffset : (barTop ? root.animationOffset : 0)
|
||||
|
||||
x: Theme.snap(root.shouldBeVisible ? 0 : hiddenX, root.dpr)
|
||||
y: Theme.snap(root.shouldBeVisible ? 0 : hiddenY, root.dpr)
|
||||
|
||||
Behavior on x {
|
||||
NumberAnimation {
|
||||
duration: root.animationDuration
|
||||
easing.type: Easing.BezierSpline
|
||||
easing.bezierCurve: root.shouldBeVisible ? root.animationEnterCurve : root.animationExitCurve
|
||||
}
|
||||
}
|
||||
|
||||
Behavior on y {
|
||||
NumberAnimation {
|
||||
duration: root.animationDuration
|
||||
easing.type: Easing.BezierSpline
|
||||
easing.bezierCurve: root.shouldBeVisible ? root.animationEnterCurve : root.animationExitCurve
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Behavior on opacity {
|
||||
NumberAnimation {
|
||||
duration: animationDuration
|
||||
easing.type: animationEasing
|
||||
easing.type: Easing.BezierSpline
|
||||
easing.bezierCurve: root.shouldBeVisible ? root.animationEnterCurve : root.animationExitCurve
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user