quickshell: fuzzy launcher search; content reveals/wipes with the chrome morph
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
21db9825d5
commit
f2cf842ace
1 changed files with 37 additions and 15 deletions
|
|
@ -230,10 +230,21 @@ in
|
||||||
|
|
||||||
function score(name, extra, q) {
|
function score(name, extra, q) {
|
||||||
let n = name.toLowerCase();
|
let n = name.toLowerCase();
|
||||||
if (n.startsWith(q)) return 3;
|
if (n.startsWith(q)) return 5;
|
||||||
if (n.includes(" " + q)) return 2;
|
if (n.includes(" " + q)) return 4;
|
||||||
if (n.includes(q)) return 1;
|
if (n.includes(q)) return 3;
|
||||||
if (extra && extra.toLowerCase().includes(q)) return 1;
|
if (extra && extra.toLowerCase().includes(q)) return 2;
|
||||||
|
// Fuzzy: q as an in-order subsequence of n (vktop →
|
||||||
|
// vesktop); fewer skipped characters scores higher.
|
||||||
|
let qi = 0, gaps = 0, last = -1;
|
||||||
|
for (let i = 0; i < n.length && qi < q.length; i++) {
|
||||||
|
if (n[i] === q[qi]) {
|
||||||
|
if (last >= 0) gaps += i - last - 1;
|
||||||
|
last = i;
|
||||||
|
qi++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (qi === q.length) return 1 / (1 + gaps);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -575,8 +586,12 @@ in
|
||||||
if (dd.visible && !dd.closing) {
|
if (dd.visible && !dd.closing) {
|
||||||
dd.animateClose();
|
dd.animateClose();
|
||||||
} else {
|
} else {
|
||||||
if (activeDropdown && activeDropdown !== dd && activeDropdown.visible) {
|
// Retarget the chrome before closing the previous
|
||||||
activeDropdown.animateClose();
|
// dropdown so it morphs instead of dipping closed.
|
||||||
|
const prev = activeDropdown;
|
||||||
|
activeDropdown = dd;
|
||||||
|
if (prev && prev !== dd && prev.visible) {
|
||||||
|
prev.animateClose();
|
||||||
}
|
}
|
||||||
if (setupFn) setupFn();
|
if (setupFn) setupFn();
|
||||||
if (dd.closing) {
|
if (dd.closing) {
|
||||||
|
|
@ -584,7 +599,6 @@ in
|
||||||
} else {
|
} else {
|
||||||
dd.visible = true;
|
dd.visible = true;
|
||||||
}
|
}
|
||||||
activeDropdown = dd;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1080,6 +1094,11 @@ in
|
||||||
if (!visible || closing) return;
|
if (!visible || closing) return;
|
||||||
closing = true;
|
closing = true;
|
||||||
open = false;
|
open = false;
|
||||||
|
// Collapse the chrome immediately so the content fade
|
||||||
|
// and the panel animation run together (when switching
|
||||||
|
// dropdowns, toggleDropdown retargets activeDropdown
|
||||||
|
// first, so this doesn't fire and the chrome morphs).
|
||||||
|
if (bar.activeDropdown === dropdown) bar.activeDropdown = null;
|
||||||
_autoClose.stop();
|
_autoClose.stop();
|
||||||
_closeDelay.start();
|
_closeDelay.start();
|
||||||
}
|
}
|
||||||
|
|
@ -1126,7 +1145,7 @@ in
|
||||||
|
|
||||||
Timer {
|
Timer {
|
||||||
id: _closeDelay
|
id: _closeDelay
|
||||||
interval: 230
|
interval: 300
|
||||||
onTriggered: { dropdown.visible = false; dropdown.closing = false; if (bar.activeDropdown === dropdown) bar.activeDropdown = null; }
|
onTriggered: { dropdown.visible = false; dropdown.closing = false; if (bar.activeDropdown === dropdown) bar.activeDropdown = null; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1137,23 +1156,26 @@ in
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Content clipped to the chrome's animated height so it
|
// Content is clipped to the chrome's ANIMATED geometry —
|
||||||
// reveals/hides with the morph; fades on open/close.
|
// revealed as the panel slides/grows over it and wiped as
|
||||||
|
// the panel leaves, instead of popping in place. The inner
|
||||||
|
// item counter-offsets so content stays put while the clip
|
||||||
|
// window moves across it.
|
||||||
Item {
|
Item {
|
||||||
id: _dropdownRect
|
id: _dropdownRect
|
||||||
anchors.left: parent.left
|
x: (chrome.x + 8) - dropdown.x
|
||||||
anchors.leftMargin: 8
|
y: 0
|
||||||
anchors.top: parent.top
|
width: Math.max(0, chrome.width - (chrome.flushRight ? 8 : 16))
|
||||||
width: dropdown.fullWidth
|
|
||||||
height: Math.min(dropdown.fullHeight, chrome.height)
|
height: Math.min(dropdown.fullHeight, chrome.height)
|
||||||
clip: true
|
clip: true
|
||||||
opacity: dropdown.open ? 1 : 0
|
opacity: dropdown.open ? 1 : 0
|
||||||
Behavior on opacity {
|
Behavior on opacity {
|
||||||
NumberAnimation { duration: 150; easing.type: Easing.OutCubic }
|
NumberAnimation { duration: 200; easing.type: Easing.OutCubic }
|
||||||
}
|
}
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
id: dropdownContent
|
id: dropdownContent
|
||||||
|
x: 8 - _dropdownRect.x
|
||||||
width: dropdown.fullWidth
|
width: dropdown.fullWidth
|
||||||
height: dropdown.fullHeight
|
height: dropdown.fullHeight
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue