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 QtQuick
import Quickshell import Quickshell
import qs.modules.launcher.services
import qs.components import qs.components
import qs.config import qs.config
@ -13,7 +14,6 @@ Item {
required property var panels required property var panels
readonly property bool shouldBeActive: visibilities.launcher && Config.launcher.enabled readonly property bool shouldBeActive: visibilities.launcher && Config.launcher.enabled
property int contentHeight
readonly property real maxHeight: { readonly property real maxHeight: {
let max = screen.height - Config.border.thickness * 2 - Appearance.spacing.large; let max = screen.height - Config.border.thickness * 2 - Appearance.spacing.large;
@ -22,94 +22,27 @@ Item {
return max; return max;
} }
onMaxHeightChanged: timer.start() property real offsetScale: shouldBeActive ? 0 : 1
visible: anchors.bottomMargin > -implicitHeight - 5
anchors.bottomMargin: -implicitHeight - 5
implicitHeight: content.implicitHeight
implicitWidth: content.implicitWidth
onShouldBeActiveChanged: { onShouldBeActiveChanged: {
if (shouldBeActive) { if (shouldBeActive)
timer.stop(); implicitHeight = Qt.binding(() => content.implicitHeight);
hideAnim.stop(); else
showAnim.start(); implicitHeight = implicitHeight; // Break binding during close anim
} else {
showAnim.stop();
hideAnim.start();
}
} }
SequentialAnimation { visible: offsetScale < 1
id: showAnim 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 { Anim {
target: root.anchors
property: "bottomMargin"
to: 0
duration: Appearance.anim.durations.expressiveDefaultSpatial duration: Appearance.anim.durations.expressiveDefaultSpatial
easing.bezierCurve: Appearance.anim.curves.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 { Loader {
@ -118,16 +51,13 @@ Item {
anchors.top: parent.top anchors.top: parent.top
anchors.horizontalCenter: parent.horizontalCenter anchors.horizontalCenter: parent.horizontalCenter
visible: false asynchronous: true
active: false active: root.shouldBeActive || root.visible
Component.onCompleted: timer.start()
sourceComponent: Content { sourceComponent: Content {
visibilities: root.visibilities visibilities: root.visibilities
panels: root.panels panels: root.panels
maxHeight: root.maxHeight maxHeight: root.maxHeight
Component.onCompleted: root.contentHeight = implicitHeight
} }
} }
} }