Files
homelab/dotfiles/quickshell/widgets/launcher/CyberDock.qml
T

89 lines
2.6 KiB
QML

pragma ComponentBehavior: Bound
import Quickshell
import Quickshell.Hyprland
import Quickshell.Wayland
import QtQuick
import qs.widgets.theme
// Variant 11 — cyberpunk bottom dock inspired by V5's rising carousel.
Scope {
id: root
property bool active: false
function toggle() { root.active = !root.active; }
onActiveChanged: {
LauncherState.dockOpen = root.active;
if (root.active)
win.prepareOpen();
}
GlobalShortcut {
name: "launcher11"
description: "Toggle app launcher (Cyber Dock)"
onPressed: root.toggle()
}
PanelWindow {
id: win
visible: root.active || deck.y < height
WlrLayershell.layer: WlrLayer.Overlay
WlrLayershell.keyboardFocus: root.active ? WlrKeyboardFocus.Exclusive : WlrKeyboardFocus.None
exclusionMode: ExclusionMode.Ignore
color: Theme.textAlpha(0)
anchors { bottom: true; left: true; right: true }
margins { bottom: 10; left: 12; right: 12 }
implicitHeight: 290
property int selectedIndex: 0
function prepareOpen() {
deck.clearSearch();
selectedIndex = 0;
deck.focusSearch();
}
function clampSelection(index) {
return model.apps.length === 0 ? 0 : Math.max(0, Math.min(model.apps.length - 1, index));
}
function move(delta) {
const count = model.apps.length;
if (count === 0)
return;
selectedIndex = ((selectedIndex + delta) % count + count) % count;
}
function launch(index) {
if (model.launch(index))
root.active = false;
}
AppModel { id: model; search: deck.query }
CyberDockContent {
id: deck
width: 1440
height: 272
x: (parent.width - width) / 2
y: root.active ? parent.height - height : parent.height + 4
scale: Math.min(1, (parent.width - 16) / width)
transformOrigin: Item.Bottom
apps: model.apps
selectedIndex: win.selectedIndex
Behavior on y {
NumberAnimation {
duration: 240
easing.type: root.active ? Easing.OutCubic : Easing.InCubic
}
}
onSelectionRequested: index => win.selectedIndex = win.clampSelection(index)
onMoveRequested: delta => win.move(delta)
onLaunchRequested: index => win.launch(index)
onDismissRequested: root.active = false
}
}
}