feat: improve launcher open

No janky stuff, use same Behavior pattern as launcher, and fix height
changes breaking.
Also allows for no initial load (though we still need to load Apps)
And for async launcher loader
This commit is contained in:
2 * r + 2 * t 2026-03-26 16:40:12 +11:00
parent d7d53260a7
commit 528a282e45

View file

@ -2,6 +2,7 @@ pragma ComponentBehavior: Bound
import QtQuick
import Quickshell
import qs.modules.launcher.services
import qs.components
import qs.config
@ -13,7 +14,6 @@ Item {
required property var panels
readonly property bool shouldBeActive: visibilities.launcher && Config.launcher.enabled
property int contentHeight
readonly property real maxHeight: {
let max = screen.height - Config.border.thickness * 2 - Appearance.spacing.large;
@ -22,94 +22,27 @@ Item {
return max;
}
onMaxHeightChanged: timer.start()
visible: anchors.bottomMargin > -implicitHeight - 5
anchors.bottomMargin: -implicitHeight - 5
implicitHeight: content.implicitHeight
implicitWidth: content.implicitWidth
property real offsetScale: shouldBeActive ? 0 : 1
onShouldBeActiveChanged: {
if (shouldBeActive) {
timer.stop();
hideAnim.stop();
showAnim.start();
} else {
showAnim.stop();
hideAnim.start();
}
if (shouldBeActive)
implicitHeight = Qt.binding(() => content.implicitHeight);
else
implicitHeight = implicitHeight; // Break binding during close anim
}
SequentialAnimation {
id: showAnim
visible: offsetScale < 1
anchors.bottomMargin: (-implicitHeight - 5) * offsetScale
implicitHeight: content.implicitHeight
implicitWidth: content.implicitWidth || 630 // Hard coded fallback for first open
Component.onCompleted: Qt.callLater(() => Apps) // Load apps on init
Behavior on offsetScale {
Anim {
target: root.anchors
property: "bottomMargin"
to: 0
duration: Appearance.anim.durations.expressiveDefaultSpatial
easing.bezierCurve: Appearance.anim.curves.expressiveDefaultSpatial
}
// ScriptAction {
// script: root.implicitHeight = Qt.binding(() => content.implicitHeight)
// }
}
SequentialAnimation {
id: hideAnim
// ScriptAction {
// script: root.implicitHeight = root.implicitHeight
// }
Anim {
target: root.anchors
property: "bottomMargin"
to: -content.implicitHeight - 5
// easing.bezierCurve: Appearance.anim.curves.emphasized
duration: Appearance.anim.durations.expressiveDefaultSpatial
easing.bezierCurve: Appearance.anim.curves.expressiveDefaultSpatial
}
}
Connections {
function onEnabledChanged(): void {
timer.start();
}
function onMaxShownChanged(): void {
timer.start();
}
target: Config.launcher
}
Connections {
function onValuesChanged(): void {
if (DesktopEntries.applications.values.length < Config.launcher.maxShown)
timer.start();
}
target: DesktopEntries.applications
}
Timer {
id: timer
interval: Appearance.anim.durations.extraLarge
onRunningChanged: {
if (running && !root.shouldBeActive) {
content.visible = false;
content.active = true;
} else {
root.contentHeight = Math.min(root.maxHeight, content.implicitHeight);
content.active = Qt.binding(() => root.shouldBeActive || root.visible);
content.visible = true;
if (showAnim.running) {
showAnim.stop();
showAnim.start();
}
}
}
}
Loader {
@ -118,16 +51,13 @@ Item {
anchors.top: parent.top
anchors.horizontalCenter: parent.horizontalCenter
visible: false
active: false
Component.onCompleted: timer.start()
asynchronous: true
active: root.shouldBeActive || root.visible
sourceComponent: Content {
visibilities: root.visibilities
panels: root.panels
maxHeight: root.maxHeight
Component.onCompleted: root.contentHeight = implicitHeight
}
}
}