Files
DankMaterialShell/quickshell/Modals/DankLauncherV2/Controller.qml
T
bbedward 8e9cd3f4a5 Squashed commit of the following:
commit f9bcdfdce1ab4a028cd9ccc08bc5fc6748e2d9e8
Author: bbedward <[email protected]>
Date:   Thu Sep 17 16:37:31 2026 -0400

    wallpaper: regenerate colors when the active light/dark wallpaper changes

commit 0b2dd37971a7b360f26b1a302297335963282313
Author: bbedward <[email protected]>
Date:   Thu Sep 17 16:16:03 2026 -0400

    lyrics: keep the active line in place when rows above resize, remember the lyrics view

commit db56722c7af9cb50a9c779a39e12a54dc5a607a6
Author: bbedward <[email protected]>
Date:   Thu Sep 17 16:04:33 2026 -0400

    lyrics: emphasize vocals per part instead of per group

commit 934e0676d9d63f6a7cb314c693ac256c1b56e057
Author: bbedward <[email protected]>
Date:   Thu Sep 17 15:59:56 2026 -0400

    lyrics: drop focus from overlapping lines when their vocals end

commit 3fe092446b1f27d7acc1a0a2a2ecc5d19f455275
Author: bbedward <[email protected]>
Date:   Thu Sep 17 15:17:28 2026 -0400

    media: add lyrics attribution, unison provider, shrink album art
    slightly when its low res

commit f54b3e2c1dc589451f449218d4985758b88757b4
Author: bbedward <[email protected]>
Date:   Thu Sep 17 14:35:52 2026 -0400

    media/zurvan: style changes

commit 9ea5aecfba4c638e2f08ab288706d2fb3143ea0b
Author: bbedward <[email protected]>
Date:   Thu Sep 17 14:02:03 2026 -0400

    rebase fixes

commit b2b04d12d2e9118346d0e5950b348aa222d58e50
Author: bbedward <[email protected]>
Date:   Thu Sep 17 13:46:03 2026 -0400

    i18n: overhaul
    battery popout: redesign
    clipboard: fix style of pinned button and remove number sidebar

commit 3057940bb28a29de22f90f5630a2c68113707d16
Author: bbedward <[email protected]>
Date:   Thu Sep 17 11:48:16 2026 -0400

    displayconfig: show valid fractional scales only, fix custom setter

commit 2bbe9e4b4c4278d1aca8632d650feba912a1c0af
Author: bbedward <[email protected]>
Date:   Thu Sep 17 10:47:43 2026 -0400

    media/zurvan: restyle

commit 33299ef45261c4f0a7e8e663c1ed2f0996e3ac78
Author: purian23 <[email protected]>
Date:   Thu Sep 17 02:50:08 2026 -0400

    refactor(clipboard): add click to open image previews & misc adjustments

commit 9809aad3c466bf4974b887a37a806039e58b47ed
Author: purian23 <[email protected]>
Date:   Thu Sep 17 02:35:20 2026 -0400

    add(media): dynamic sizing

    - tests: start the fixture bus with dbus-broker or dbus-daemon

commit 75a20eeb5a1299af1b0dd0d99cb374b4c5c8f15f
Author: purian23 <[email protected]>
Date:   Thu Sep 17 00:30:04 2026 -0400

    fix(dash): position bar-triggered popout once

commit 1536691beb0bf2cd58fa3e1b2106eeeb9317a39c
Author: purian23 <[email protected]>
Date:   Wed Sep 16 23:58:50 2026 -0400

    dash & cc: operation freedom

commit f3a2ae13bffbbdb92134af23138dc9a253f69e09
Author: bbedward <[email protected]>
Date:   Wed Sep 16 23:12:58 2026 -0400

    lyrics: keep track identity independent of mpris length

commit a59dd84908486f23e07172a6fca4c76eed27d31f
Author: bbedward <[email protected]>
Date:   Wed Sep 16 22:41:44 2026 -0400

    more zurvan changes

commit fda890225576e6fc740946486c5c05cdc58ebd77
Author: bbedward <[email protected]>
Date:   Wed Sep 16 22:10:55 2026 -0400

    media: more style changes

commit 2170f055e3700466f87c0f6a072cb67e5e610574
Author: bbedward <[email protected]>
Date:   Wed Sep 16 20:00:36 2026 -0400

    zurvan style tweaks

commit 10795b2f2c41fcd1c24f5625324ff0ea7dd3e4ae
Author: bbedward <[email protected]>
Date:   Wed Sep 16 18:32:48 2026 -0400

    media: adjust styling of zurvan player

commit 363eb10f7f53681d8f36fc6e9648205c9d5879d2
Author: bbedward <[email protected]>
Date:   Wed Sep 16 17:30:05 2026 -0400

    lyrics: dont classify 401s as failures

commit 0267c7110e14285fe4a611dbc78aee93e77e6ec8
Author: bbedward <[email protected]>
Date:   Wed Sep 16 17:07:34 2026 -0400

    media: create the dank lyrics engine with multiple providers and
    priority support
    media: add zurvan style player and make it default

commit 0aae835377cc96c5ec8383650df914058f604a42
Author: bbedward <[email protected]>
Date:   Wed Sep 16 10:22:36 2026 -0400

    remove dumb test

commit 8610121b1cb20b4b4b557170b7df52af39f4efff
Author: bbedward <[email protected]>
Date:   Wed Sep 16 10:16:00 2026 -0400

    notifications: redesign card header

commit 868b73740a575d51577fa3aaff5abc1ccd53043c
Author: bbedward <[email protected]>
Date:   Wed Sep 16 09:24:13 2026 -0400

    clipboard: tweak image preview style

commit 6de9a1ba7c306269889227b892703dc822049ac9
Author: purian23 <[email protected]>
Date:   Tue Sep 15 22:52:40 2026 -0400

    clipboard: new size variants & image previews

commit 05909190a2fb93a3a2c68fc711c07c3ffc09a529
Author: bbedward <[email protected]>
Date:   Tue Sep 15 19:14:41 2026 -0400

    qs: drop the delegates the layout and output migrations left behind

commit 6ca48caf7c2141e7e5f55a7d4634e0803a90c6b9
Author: bbedward <[email protected]>
Date:   Tue Sep 15 19:03:03 2026 -0400

    config: one implementation of the compositor fragment mechanics

commit 9f024c001e0c661a19c35b92bb36a6a9758f9d4d
Author: bbedward <[email protected]>
Date:   Tue Sep 15 18:34:03 2026 -0400

    compositor: name capabilities instead of checking identity in the ui

commit 90067f14ed38e0cbf919e35cbf333f62240bc585
Author: bbedward <[email protected]>
Date:   Tue Sep 15 18:19:57 2026 -0400

    settings: read every default from the spec

commit 7f7ae95ed3093c5df7cb4bf5d23b718497a769ff
Author: bbedward <[email protected]>
Date:   Tue Sep 15 15:47:13 2026 -0400

    notifications: watch screen sharing from the service side

commit a470ed448cbddb849922e80afdd2b13eb85f08f9
Author: bbedward <[email protected]>
Date:   Tue Sep 15 15:15:38 2026 -0400

    rebase fix

commit dc8f05fa0ca4650a40e32fb59614ca1b7df75f38
Author: bbedward <[email protected]>
Date:   Tue Sep 15 10:57:38 2026 -0400

    dash: keep cards still when edit mode opens

commit bc2001359613fd9b47ba0000a8f8f081d412a166
Author: bbedward <[email protected]>
Date:   Tue Sep 15 10:16:48 2026 -0400

    settings: own the full spec again and merge the shared greeter keys
    settings: drop sidebar hints that repeat their own label
    cc/dash: change edit interface design slightly

commit ee963f54b259eced7ec23701194539441b264db0
Author: purian23 <[email protected]>
Date:   Mon Sep 14 23:43:56 2026 -0400

    settings: update island notification handling to use bar context

commit 4d6f9fde4401001625f0352f97821ce5034a7e1c
Author: bbedward <[email protected]>
Date:   Mon Sep 14 23:21:28 2026 -0400

    greeter: read the shared settings schema instead of a duplicated one

commit 70e4bdaec84efa3d68438ef235e46762cee38101
Author: bbedward <[email protected]>
Date:   Mon Sep 14 22:42:31 2026 -0400

    osd, toast, launcher: start open motion after onFrameSwapped signal

commit ddfd28b7be6dd4b0940512897d835107dbab1f23
Author: bbedward <[email protected]>
Date:   Mon Sep 14 21:12:37 2026 -0400

    notifications: wait for onFrameSwapped signal before showing
    notification popup

    Lets the layer-surface map before rendering the body, resulting in
    better animation appearance

commit 24efe6f8a18b36bb42c6b399086ffa5c5e2aa9c5
Author: purian23 <[email protected]>
Date:   Mon Sep 14 18:55:46 2026 -0400

    notifications: adjust animation durations

    - Mapped the layer-shell surface
    - Fixed group chevron/dismiss button

commit 52389ecf5cc586e912c26a345004814e37f4048a
Author: bbedward <[email protected]>
Date:   Mon Sep 14 18:10:33 2026 -0400

    dash: spacing tweak of tabbart

commit 0285a70c1b07d09558c450c1eeb925a5c903069f
Author: bbedward <[email protected]>
Date:   Mon Sep 14 17:55:43 2026 -0400

    blah

commit a1abc7a8df94032b01b51189b214aa21543f7218
Author: bbedward <[email protected]>
Date:   Mon Sep 14 17:40:10 2026 -0400

    shrink window CSD height

commit db20f7e9bb93c7dce503e410e82e15e7a03b1e7d
Author: bbedward <[email protected]>
Date:   Mon Sep 14 17:16:16 2026 -0400

    windows: center titles

commit 7268712bdf58c5c1903606f24a392d64655a4ad5
Author: purian23 <[email protected]>
Date:   Mon Sep 14 16:45:44 2026 -0400

    notifications: updated entry/exit paths

    - Added popout option in island mode
    - Fixed cards getting stuck & out of place when multiples arise at once

commit 3a3f0b3061bd0a7ce895152ec5a056600e41e7e8
Author: bbedward <[email protected]>
Date:   Mon Sep 14 16:34:36 2026 -0400

    battery: make cc variant consistent

commit ee569ddef3bf2875d42347d18b57f493f492b243
Author: bbedward <[email protected]>
Date:   Mon Sep 14 16:15:42 2026 -0400

    battery: remove bottom text footer thing

commit 817c4e46eac52c95d91f418e3ddbafdab0888b5c
Author: purian23 <[email protected]>
Date:   Mon Sep 14 15:34:18 2026 -0400

    settings: rework interface style and bar hub layouts

    - Separate global surface styling from per-surface overrides on Interface style
    - Move bar management into the hub header and render island settings inline
    - Cut redirect banners down to one per page and point them at the right row

commit 03a4e45d65aec83c927c7419a4a0f3f252e0e955
Author: bbedward <[email protected]>
Date:   Mon Sep 14 14:52:20 2026 -0400

    launcher: fix inconsistency in niri overview variant

commit e74246d058a5db215200606eb9f9c662706d8689
Author: bbedward <[email protected]>
Date:   Mon Sep 14 14:21:10 2026 -0400

    plugins: eval symlinks in repo lookup

commit 7dd2cddebf4819da51ff7da792560372f5d9a03e
Author: bbedward <[email protected]>
Date:   Mon Sep 14 09:09:46 2026 -0400

    update common

commit a8c1f77fe2d952b1ec33e622b2951e5382860c9e
Author: purian23 <[email protected]>
Date:   Mon Sep 14 02:05:09 2026 -0400

    island: fix search input focus on launcher

commit 2d1f8bf5338ca5e0a4a58f0f18b54b92dfe5e5ee
Author: purian23 <[email protected]>
Date:   Mon Sep 14 01:29:05 2026 -0400

    tooltips: add further label & accessibility parity

commit 3ebfe85d57553b4803b52d5e5ea417b8abec5bcf
Author: bbedward <[email protected]>
Date:   Sun Sep 13 23:28:29 2026 -0400

    ui: drop tooltips from obvious icon buttons, keep labels on Accessible.name

commit a8e7a072b2bad394c5c5d9fd60eaff5240ce37d4
Author: bbedward <[email protected]>
Date:   Sun Sep 13 22:55:28 2026 -0400

    widgets: dim filled action buttons when disabled

commit 0dc58825344ebfc5479d2a3bc75b5d2ae014131a
Author: bbedward <[email protected]>
Date:   Sun Sep 13 22:45:34 2026 -0400

    settings: one compositor include workflow for outputs, layout, input, window rules, cursor and binds

commit 9fc8c8e53c18de18b33ccdfe1e1abed84e01b219
Author: purian23 <[email protected]>
Date:   Sun Sep 13 22:27:28 2026 -0400

    theme: add focus ring settings & replace text fields w/search fields aligned to m3e specs

commit 8359fea68230172b1c10df08831efdf944fbbd64
Author: bbedward <[email protected]>
Date:   Sun Sep 13 20:37:49 2026 -0400

    auth: share one pam stack parser between the greeter, lock probe and polkit

commit bf05136e78aada16e41a7d0b7164a7f543d65760
Author: bbedward <[email protected]>
Date:   Sun Sep 13 20:24:01 2026 -0400

    tests: replace golden files and dump-only fixtures with hand-written assertions

commit f2cd6a877b561a5078e7b6cbad8348e9165158ca
Author: bbedward <[email protected]>
Date:   Sun Sep 13 19:15:02 2026 -0400

    display: split DisplayService into brightness, night mode and refresh rate services

commit fa7ce5fe836e4f00646c80eb3cb50ecc004f4524
Author: bbedward <[email protected]>
Date:   Sun Sep 13 18:19:26 2026 -0400

    battery: m3e redesign

commit 04576106158c009374d9564d18852cf7ea1f9284
Author: bbedward <[email protected]>
Date:   Sun Sep 13 17:21:32 2026 -0400

    shell: one window model and one keyboard layout source
    hosts: put change handlers on the observed object instead of proxy properties

commit e4750c767b27d4650b95d42930410ad090d6ca87
Author: bbedward <[email protected]>
Date:   Sun Sep 13 15:39:10 2026 -0400

    shell: replace connections with bound property handlers in per-item and per-screen components

commit 8efb05dc014f0d09b36d6112b03e6f4e1f60d1d2
Author: bbedward <[email protected]>
Date:   Sun Sep 13 13:43:10 2026 -0400

    display config: move output parsing, identifiers and geometry into a pure model

commit e9b8174812b2da316eeae42e3989f2f269ef5649
Author: bbedward <[email protected]>
Date:   Sun Sep 13 12:52:46 2026 -0400

    slideout: build content on first open

commit b899f307650cf5cc646de90ac666b6e1731bbc4f
Author: bbedward <[email protected]>
Date:   Sun Sep 13 12:28:11 2026 -0400

    services: stop using weakmap for workspace, window and term caches

commit b90e9a4c2a72744685f79cf613ab80660721389f
Author: bbedward <[email protected]>
Date:   Sun Sep 13 10:35:48 2026 -0400

    workspaces: one model with per-compositor adapters, no compositor branches in widgets
    shell: stop hot reload while the session lock is held

commit e200e17e96e06b4fd7e0dd596b50dcbbc254494a
Author: purian23 <[email protected]>
Date:   Sun Sep 13 02:36:41 2026 -0400

    dock: mix widgets between pinned apps

    - Pinned apps become individual units in edit mode with a saved per-dock order, while running windows stay one unit in compositor order.
    - Fix the Window.window Connections crash
    - Add right-click-to-edit empty dock space option and dock edit / editFor ipc commands

commit cad3ba78727695419a4fe8a96c90146bbf5e6120
Author: bbedward <[email protected]>
Date:   Sun Sep 13 00:51:35 2026 -0400

    launcher: create plugin instances only when a query needs them

commit aed25c3c75d0c24a17a940c162a6956a372c4e0f
Author: bbedward <[email protected]>
Date:   Sat Sep 12 23:45:19 2026 -0400

    settings: rebuild about, printer, wifi, display and window rules pages on settings blocks
    popouts: drop inconsistent headers

commit 3a20c2c9528fe1fed3464085492af3bebdcdf809
Author: bbedward <[email protected]>
Date:   Sat Sep 12 17:41:18 2026 -0400

    launcher: consolidate host code and logic

commit 4e53b470d5beaffa54687c8164e492ee41472e49
Author: bbedward <[email protected]>
Date:   Sat Sep 12 15:37:44 2026 -0400

    surfaces: collapse connected/standalone popout and modal hosts
    typography: make font weight work and follow m3 weights
    settings: fix reset to default shifting rows

commit ce71b5dc3ca0e96ee11b906b1ea3399d3d7d93ac
Author: bbedward <[email protected]>
Date:   Sat Sep 12 15:02:25 2026 -0400

    dock: move widgets, launcher, apps and trash as units in edit mode

commit 6ebaef52d885744a45f3db7d48c3b6d0924993b2
Author: bbedward <[email protected]>
Date:   Sat Sep 12 13:24:31 2026 -0400

    plugins: add examples for dash and dock

commit 067cabc95991f5676a19746d3cad0700eb525082
Author: bbedward <[email protected]>
Date:   Sat Sep 12 12:25:59 2026 -0400

    settings: fix v18 migration

commit 55d07f3bba352972c768acdd7b6705f80fac4e0f
Author: bbedward <[email protected]>
Date:   Sat Sep 12 12:09:56 2026 -0400

    ci: fix fails

commit 2e81531dd6980f0331af80fe5beca1d695c58f06
Author: bbedward <[email protected]>
Date:   Sat Sep 12 11:49:39 2026 -0400

    surfaces: add windowRadius token to make surfaces actually follow
    settings and match the compositor windows
    surfaces: change default radius (Strength 50) from 12->16
    settings: add result to default for everything
    settings: further re-organization and re-structuring position of things
    settings: remove dead keys
    dock: remove hardcoded border and respect border setting
    bar: add a third style and color options
    ci: hookup QML testing

commit a2fd8abd37e0ff1ef67af9bfa4e7679e7aa338bd
Author: bbedward <[email protected]>
Date:   Sat Sep 12 09:20:00 2026 -0400

    dash: size surface width to the width of the largest tab

commit 93394549a2cb3f7647b564ba71621e113c83e106
Author: bbedward <[email protected]>
Date:   Sat Sep 12 00:11:15 2026 -0400

    bar/workspaces: restore old style, respect color choices, make pills
    default  > segments

commit 71f8351a3b11f8d06e45dd28db4d501e54a27f9a
Author: purian23 <[email protected]>
Date:   Fri Sep 11 23:48:04 2026 -0400

    dbar: initial M3E remaster pass on shared chrome w/dock & island

commit 1711716073f660afd519ab0af88d3c8177f1a8c8
Author: bbedward <[email protected]>
Date:   Fri Sep 11 21:44:31 2026 -0400

    dash: only show focus ring when KB navigating

commit 6037de06471e7fa80ec36088e9e86cbf2e4d3941
Author: bbedward <[email protected]>
Date:   Fri Sep 11 21:41:53 2026 -0400

    launcher: scope plugin and clipboard refreshes, paint the keystroke before plugin search

commit 78c9ab990b7665e76762dadd65d1a1d23275a405
Author: bbedward <[email protected]>
Date:   Fri Sep 11 21:16:36 2026 -0400

    launcher: one open-session reset, faster keystroke settle

commit 01b15051363715bfb2bfe1d905b4b573fb4e49ac
Author: bbedward <[email protected]>
Date:   Fri Sep 11 20:47:45 2026 -0400

    dash: fix kb navigation  on overview

commit 27465074e1fa395a844cc3b804a362ee7a4e4f70
Author: bbedward <[email protected]>
Date:   Fri Sep 11 16:58:53 2026 -0400

    dash: replace material shapes on resource cards with a ring gauge

commit 5e41b85a1df69885c57a41ab44a43ef38b0c5560
Author: bbedward <[email protected]>
Date:   Fri Sep 11 16:33:48 2026 -0400

    qml: share bases for registry browsers, fade windows and plugin list settings

    Fixes fade window focus, list setting load write-back and the missing Theme.onError

commit be3542ab8fc1949a256d6498b5c4a0379b86e023
Author: bbedward <[email protected]>
Date:   Fri Sep 11 16:11:15 2026 -0400

    popout: fix pixel jumps

commit 2ad0e9e2f5b12f13f0acc9733c29c4c42d640df7
Author: bbedward <[email protected]>
Date:   Fri Sep 11 15:52:52 2026 -0400

    popout: fade the surface fill with the content

commit 4b11e21b1a09895f67ca1b6b858fe772500e4a2c
Author: bbedward <[email protected]>
Date:   Fri Sep 11 15:13:14 2026 -0400

    desktop widgets: read and write saved geometry through one path

commit 21ed01bbb20627d4d68bbb704b9f2bb50b45c911
Author: bbedward <[email protected]>
Date:   Fri Sep 11 15:10:02 2026 -0400

    surfaces: bind modal and popout backends to their handle

commit 362859d810b768621061f0429c39b17ff3b00184
Author: bbedward <[email protected]>
Date:   Fri Sep 11 14:30:27 2026 -0400

    notifications: move the popup context menu onto DankContextMenu

commit 8942b622f5929e854fbcf145e7f34f4637904731
Author: bbedward <[email protected]>
Date:   Fri Sep 11 14:20:49 2026 -0400

    colorpicker: design changes
    consolidate context menus

commit 29be554d488aefd9a8f6e4e5f5d094147e3b214d
Author: bbedward <[email protected]>
Date:   Fri Sep 11 12:48:02 2026 -0400

    dash: add analog clock option

commit 43748726983a466e19e4b642399ea040d4095de9
Author: bbedward <[email protected]>
Date:   Fri Sep 11 12:12:51 2026 -0400

    popouts: fix spacing inconsistencies
    dash: redesign overview media card
    osd: more redesign
    dash/overview: remove row cap and make it dynamic

commit 14a3a315d94336cac6e8eb77e08965503717d780
Author: bbedward <[email protected]>
Date:   Fri Sep 11 09:23:53 2026 -0400

    shell: dedupe bar ipc handlers, weather resets, color options, launcher icons

commit 9f2b6d4bbe6f5954a33b5853ecea0ef0ac4b483e
Author: purian23 <[email protected]>
Date:   Thu Sep 10 23:52:39 2026 -0400

    dock: add spacing option & update defaults

commit 3e6cb55488a42ade23728bcf4d8608efab2e6e0f
Author: bbedward <[email protected]>
Date:   Thu Sep 10 23:29:07 2026 -0400

    session: collapse the monitor cycling setters onto one helper

commit 613e756d8bf88b3c2e6ae7edcede4c680da72456
Author: bbedward <[email protected]>
Date:   Thu Sep 10 21:56:38 2026 -0400

    dock: share the hover bounce animation across dock buttons

commit 8d8f801874ddf5dcc3b299405de458183e758c7c
Author: bbedward <[email protected]>
Date:   Thu Sep 10 21:46:44 2026 -0400

    settings: share one picker window for bar and desktop widgets

commit e3c90efbce4d7d11adf0cceefb8e9758e7d9099c
Author: bbedward <[email protected]>
Date:   Thu Sep 10 21:24:10 2026 -0400

    network: merge wired and wifi info modals

commit 43f75e6a3dfc988f3adc8c7d659fff5529ed6db8
Author: purian23 <[email protected]>
Date:   Thu Sep 10 21:22:06 2026 -0400

    island: unify new dashboard dynamic sizing & activities

    - New wallpaper carousel and Colum/Row options
    - Fixed island controller overlap in bar widget settings
    - Fixed island widgets click to hide activity
    - Expanded island IPC cyle targets

commit 805611efca91bea029894436dad9baa6dd492461
Author: bbedward <[email protected]>
Date:   Thu Sep 10 19:40:27 2026 -0400

    bar: share context menu window and tooltip offset across widgets

    also fix Media art glitches and things

commit 17a08c4c7e56312d0b3a7732978223f569828aaf
Author: bbedward <[email protected]>
Date:   Thu Sep 10 19:00:48 2026 -0400

    osd/media: respect follow album accent option

commit 6a753a7ab6304568f178bc3ec0910a9132020dd2
Author: bbedward <[email protected]>
Date:   Thu Sep 10 18:57:15 2026 -0400

    theme: fix surface elevation

commit af4f44eba649923bfb0928423a24fc6d115518c4
Author: bbedward <[email protected]>
Date:   Thu Sep 10 18:45:09 2026 -0400

    m3e: redesign OSDs, Forms, etc.

commit 1d2add180a661157b3c06a1221edae21bdbcb765
Author: bbedward <[email protected]>
Date:   Thu Sep 10 17:19:07 2026 -0400

    rebase fixes

commit ac39a7745cfe88bcfd3826f64cfd55ed41b18b3e
Author: bbedward <[email protected]>
Date:   Thu Sep 10 16:51:16 2026 -0400

    tray: share one item delegate and icon for both bar orientations

commit 642eeb0f4b5d0a912fc44c134fc10adf8a5b5291
Author: bbedward <[email protected]>
Date:   Thu Sep 10 16:33:36 2026 -0400

    bar: share one delegate for running apps in both orientations

commit 7f69e42f3bef9025d411acfc768deb3865338922
Author: bbedward <[email protected]>
Date:   Thu Sep 10 15:56:33 2026 -0400

    bar: share one monitor pill for cpu, ram, temp and disk widgets

commit f5507dc3b2df6929521e87cd820eb45a3e3077ad
Author: bbedward <[email protected]>
Date:   Thu Sep 10 14:03:00 2026 -0400

    island: reuse widget model, surface palette and layout metrics in hosts

commit aceac03ba0c9a2b0aa1a47f1b62a380fc785ec6d
Author: bbedward <[email protected]>
Date:   Thu Sep 10 13:36:47 2026 -0400

    osd: share one level osd for volume, brightness, mic and media

commit 1b4a68d10c5b59f3ecf3e7c44974a2cb83964246
Author: bbedward <[email protected]>
Date:   Thu Sep 10 13:12:30 2026 -0400

    shell: consolidate connected surface state into one slot store

commit d7edc23cf14a10cd275fdf3888d24482d43a15f3
Author: bbedward <[email protected]>
Date:   Thu Sep 10 12:19:30 2026 -0400

    shell: restore centered dash popout for center-section widgets

commit d2f9405de9e7ade7db402826cfb0520249c58a2b
Author: bbedward <[email protected]>
Date:   Thu Sep 10 12:11:29 2026 -0400

    dash/media: always show placeholder player when no players are playing

commit 55535082f53163914440e1e858aa78246bc4e40a
Author: bbedward <[email protected]>
Date:   Thu Sep 10 12:08:10 2026 -0400

    dock: fix sizing, exclusive zone, edit mode and multi-instance settings

commit c82cc738ca2d20e7a4363b7abb86ad6d9e7bb172
Author: bbedward <[email protected]>
Date:   Thu Sep 10 11:08:40 2026 -0400

    settings/plugins: redesign page

commit 9c283e0f6c4b7d812362124fdd36fc15327ef03c
Author: bbedward <[email protected]>
Date:   Wed Sep 9 20:44:26 2026 -0400

    shell: route widget instances and support same-edge layouts

commit 405a3b397c264688b2271d6acec881a4aea4864f
Author: bbedward <[email protected]>
Date:   Wed Sep 9 18:05:37 2026 -0400

    shell: share bar content and clock presentation

commit 65a6d2df8e870af259b1542c896fce60be4f6cb6
Author: bbedward <[email protected]>
Date:   Wed Sep 9 15:49:23 2026 -0400

    shell: centralize layout ownership

commit 585aeb4e1cba737cc4007fc214ac1e109d3e0f19
Author: purian23 <[email protected]>
Date:   Wed Sep 9 18:05:13 2026 -0400

    dock: initial m3e remaster

commit a2e646f2fb364f042fb134e74e9014386b80971b
Author: bbedward <[email protected]>
Date:   Wed Sep 9 14:58:38 2026 -0400

    plugins: consolidate upgrade path

commit 139253504c5f62d522fbc6109689c11ccaec7493
Author: bbedward <[email protected]>
Date:   Wed Sep 9 14:43:28 2026 -0400

    settings: use icons on all outlined text fields

commit a9c1e569b8428e4f3748da345200e8a62c90ba20
Author: bbedward <[email protected]>
Date:   Wed Sep 9 14:32:33 2026 -0400

    launcher: fix KB navigation focus and modes

commit ac64eb52d360322a0e952844b41b58532d5ae32f
Author: bbedward <[email protected]>
Date:   Wed Sep 9 14:05:10 2026 -0400

    m3e: remove inconsistent widget usage, adjust SystemUpdater rredesign,
    fix window decoration inconsistencies

commit 0eac1d3e22cb879c7b7e9205fba0ed9c17b89dcd
Author: bbedward <[email protected]>
Date:   Wed Sep 9 13:25:44 2026 -0400

    server: consolidate ipc routing and subscription forwarding

commit ed289e5c2c867eb2d6e1319d9517885e6e80d1a3
Author: bbedward <[email protected]>
Date:   Wed Sep 9 12:56:29 2026 -0400

    plugins: redesign management and browsers with m3 expressive

commit 7f3a526e2d38c24edbb5d51c4c9c550a0bc93752
Author: bbedward <[email protected]>
Date:   Wed Sep 9 11:00:07 2026 -0400

    settings: fix inconsistent ripple effect radius

commit 8f1fb8a11e92b1811808325c136199fef10d4a53
Author: bbedward <[email protected]>
Date:   Wed Sep 9 10:26:39 2026 -0400

    aqueous: fix variant terms

commit 2ba861947092cb657d983702c842e88ffc6fb0fa
Author: bbedward <[email protected]>
Date:   Wed Sep 9 10:01:50 2026 -0400

    running apps: fix delegate bug

commit b37c925e85cb6902bbb3005d92a5b522e3648116
Author: bbedward <[email protected]>
Date:   Wed Sep 9 00:18:57 2026 -0400

    bump dml-common

commit 5e83c40c56c624df74306efc839d707ec8d6aa14
Author: bbedward <[email protected]>
Date:   Wed Sep 9 00:12:16 2026 -0400

    settings: incorporate user & accounts tab, consolidate security, add M3E
    textfield

commit 278370c7909226ca42f0a53cbd9ca2bd5f2fb4e7
Author: bbedward <[email protected]>
Date:   Tue Sep 8 18:17:25 2026 -0400

    m3e: unify shell surfaces and refresh process monitoring

commit e2d5860d3952da717ba9073e857133f2538a70b0
Author: bbedward <[email protected]>
Date:   Tue Sep 8 15:15:17 2026 -0400

    notifications: fix expansion timing and simplify the header

commit d8f29c221474c2884ec482d26c827de09d581539
Author: bbedward <[email protected]>
Date:   Tue Sep 8 14:53:11 2026 -0400

    icon: install app icon under the conventional name (app id)

commit ebeebb70fd4c7538ef5ea867116d9fa7118eee27
Author: bbedward <[email protected]>
Date:   Tue Sep 8 14:47:09 2026 -0400

    notifications: refine card styling and separate app icons from image previews

commit d6133d93ed314ca02a9a3b634872ee32484a0bb3
Author: bbedward <[email protected]>
Date:   Tue Sep 8 14:27:18 2026 -0400

    settings: unify expressive rows and drag and drop

commit 0a4d14752a2a1e8dd60b3056fd006d02d818d6a4
Author: bbedward <[email protected]>
Date:   Tue Sep 8 12:32:16 2026 -0400

    settings: use native action button hover state

commit dc8c4564cc964ab50ed28a3e9e4ca7b13ebfbcb1
Author: bbedward <[email protected]>
Date:   Tue Sep 8 09:55:42 2026 -0400

    shell: refine weather, slider controls, and tooltips

commit bec5c6ad0119e22a3cb69975d135d3b72654f77e
Author: bbedward <[email protected]>
Date:   Mon Sep 7 18:43:39 2026 -0400

    theme: tweak token values

commit 8519cbc4bbb396a8b6779764ff0f5a0945156dcf
Author: bbedward <[email protected]>
Date:   Mon Sep 7 13:43:53 2026 -0400

    dankdash: fix grid sizing, controls, notifications, and popout blur

commit f2405f2925aa63eba480cff4ddc55119818f8057
Author: bbedward <[email protected]>
Date:   Mon Sep 7 10:38:07 2026 -0400

    dash: redesign media player and migrate its appearance options

commit cb57ce04fbd50920a17d9a8ad33e4d20fc856021
Author: bbedward <[email protected]>
Date:   Mon Sep 7 09:07:01 2026 -0400

    lock: add lock m3e redesign

commit e89909e3743993dad1bdf17d57ab17f1122dfa3c
Author: bbedward <[email protected]>
Date:   Sun Sep 6 21:24:48 2026 -0400

    qs: more loaders, less repetition

commit 288335fef67b523f51e22bb234c81bd8b88e7e2c
Author: bbedward <[email protected]>
Date:   Sun Sep 6 20:16:41 2026 -0400

    launcher: initial m3e redesign

commit 5b7fc75c473491bf086b65a41416325697ae330c
Author: purian23 <[email protected]>
Date:   Sun Sep 6 19:50:14 2026 -0400

    feat(motion): new fluid animation variant

    - Refactored Popouts/Modals for performance passes

commit 0fc4f51f4d0b1d297c1886b19be8062d279c505b
Author: bbedward <[email protected]>
Date:   Sun Sep 6 15:36:22 2026 -0400

    notifications: tweak animnation stacking behavior on popups

commit 4369233794e3bebd890a2b830c6450d0a65eb31a
Author: bbedward <[email protected]>
Date:   Sun Sep 6 15:15:55 2026 -0400

    notifications: initial M3E redesign

commit eb67a51779c543038ad885ecd406bfe21aecd1e2
Author: bbedward <[email protected]>
Date:   Sat Sep 5 15:10:37 2026 -0400

    ddash: exhaustive overhaul of even more pieces of the system

commit 14554a39effd677206f7a3c4b5944d2ae47c2b03
Author: bbedward <[email protected]>
Date:   Sat Sep 5 12:47:06 2026 -0400

    settings: rebase fixes

commit d6e0bb604bdb15ed94d77f9e1d85a26381ed6836
Author: bbedward <[email protected]>
Date:   Sat Sep 5 10:18:38 2026 -0400

    ddash: initial rewrite

commit 29903114d0d8849b25c6f6e9161765b0ad03da49
Author: bbedward <[email protected]>
Date:   Fri Sep 4 16:48:23 2026 -0400

    cc: tweak s lider size

commit 8d14a07864972e4b705e77b371d21f5fdb7c4c07
Author: bbedward <[email protected]>
Date:   Fri Sep 4 16:44:53 2026 -0400

    cc: initial M3E re-design

commit 976f968967166c61cec423f3bb3f7a28a5a9ac76
Author: bbedward <[email protected]>
Date:   Fri Sep 4 15:00:35 2026 -0400

    settings: continue to iterate

commit a99a1c5ad183e34435a20dd90f19ed84099a1070
Author: bbedward <[email protected]>
Date:   Fri Sep 4 09:44:55 2026 -0400

    stash m3e work
2026-09-17 16:51:27 -04:00

2338 lines
81 KiB
QML

pragma ComponentBehavior: Bound
import QtQuick
import Quickshell
import Quickshell.Io
import qs.Common
import qs.Services
import "Scorer.js" as Scorer
import "ControllerUtils.js" as Utils
import "NavigationHelpers.js" as Nav
import "ItemTransformers.js" as Transform
Item {
id: root
property string searchQuery: ""
property string searchMode: "all"
property string previousSearchMode: "all"
property bool autoSwitchedToFiles: false
property bool isFileSearching: false
property var sections: []
property var flatModel: []
property int selectedFlatIndex: 0
property var selectedItem: null
property bool isSearching: false
property string activePluginId: ""
property var collapsedSections: ({})
property bool keyboardNavigationActive: false
property bool active: false
property var _modeSectionsCache: ({})
property bool _queryDrivenSearch: false
property bool _diskCacheConsumed: false
property var sectionViewModes: ({})
property var pluginViewPreferences: ({})
property int gridColumns: SettingsData.appLauncherGridColumns
property int viewModeVersion: 0
property string viewModeContext: "spotlight"
property bool forceLinearNavigation: false
property bool explicitQuerySession: false
signal itemExecuted
signal searchCompleted
signal modeChanged(string mode, bool userInitiated)
signal queryChanged(string query)
signal viewModeChanged(string sectionId, string mode)
signal searchQueryRequested(string query)
signal sectionExpanded(string sectionId)
Ref {
service: AppSearchService
}
onActiveChanged: {
ClipboardService.invalidateLauncherSearchCache();
if (active)
return;
SessionData.addLauncherHistory(searchQuery, explicitQuerySession);
sections = [];
flatModel = [];
selectedItem = null;
_clearModeCache();
}
onSearchModeChanged: {
if (searchMode === "apps") {
_loadAppCategories();
} else {
appCategory = "";
appCategories = [];
}
}
Connections {
target: SettingsData
function onSortAppsAlphabeticallyChanged() {
AppSearchService.invalidateLauncherCache();
_clearModeCache();
}
function onLauncherPluginVisibilityChanged() {
AppSearchService.invalidateLauncherCache();
_clearModeCache();
if (active)
performSearch();
}
function onBuiltInPluginSettingsChanged() {
AppSearchService.invalidateLauncherCache();
_clearModeCache();
if (active)
performSearch();
}
}
Connections {
target: ClipboardService
function onLauncherSearchReady(query) {
if (!active)
return;
const clipboardBuiltInActive = activePluginId === "dms_clipboard_search";
if (!clipboardBuiltInActive && !clipboardSearchEnabledInAll())
return;
if (!clipboardBuiltInActive && searchMode !== "all")
return;
const trimmed = (searchQuery || "").trim();
if (trimmed.length < 2 && query.length > 0)
return;
const triggerMatch = detectTrigger(trimmed);
const effectiveQuery = clipboardBuiltInActive && triggerMatch.pluginId === "dms_clipboard_search" ? triggerMatch.query : trimmed;
if (query !== effectiveQuery)
return;
if (!clipboardBuiltInActive && _refreshClipboardResults())
return;
root.requestSearch();
}
}
readonly property int searchCacheVersion: AppSearchService.cacheVersion
onSearchCacheVersionChanged: {
if (!active)
return;
_clearModeCache();
if (searchMode === "apps") {
_loadAppCategories();
performSearch();
} else if (!searchQuery && searchMode === "all") {
performSearch();
}
}
Connections {
target: PluginService
function onRequestLauncherUpdate(pluginId) {
if (!active || !PluginService.pluginInstances[pluginId])
return;
if (activePluginId === pluginId) {
if (activePluginCategories.length <= 1)
loadPluginCategories(pluginId);
performSearch();
return;
}
if (!searchQuery)
return;
if (_refreshPluginResults(pluginId))
return;
performSearch();
}
}
Process {
id: copyProcess
running: false
onExited: pasteTimer.start()
}
Timer {
id: pasteTimer
interval: 200
repeat: false
onTriggered: ClipboardService.sendPasteKeystroke()
}
function pasteSelected() {
if (!selectedItem)
return;
if (selectedItem.type === "clipboard") {
if (SettingsData.clipboardEnterToPaste) {
ClipboardService.copyEntry(selectedItem.data, function () {
root.itemExecuted();
});
} else {
ClipboardService.pasteEntry(selectedItem.data, function () {
root.itemExecuted();
});
}
return;
}
const pluginId = selectedItem.pluginId;
if (!pluginId)
return;
const pasteArgs = AppSearchService.getPluginPasteArgs(pluginId, selectedItem.data);
if (!pasteArgs)
return;
copyProcess.command = pasteArgs;
copyProcess.running = true;
itemExecuted();
}
readonly property var sectionDefinitions: [
{
id: "favorites",
title: I18n.tr("Pinned"),
icon: "push_pin",
priority: 1,
defaultViewMode: "list"
},
{
id: "apps",
title: I18n.tr("Applications", "launcher section title and settings page name"),
icon: "apps",
priority: 2,
defaultViewMode: "list"
},
{
id: "settings",
title: I18n.tr("Settings", "settings window title"),
icon: "settings",
priority: 2.35,
defaultViewMode: "list"
},
{
id: "clipboard",
title: I18n.tr("Clipboard"),
icon: "content_paste",
priority: 2.45,
defaultViewMode: "list"
},
{
id: "browse_plugins",
title: I18n.tr("Browse"),
icon: "category",
priority: 2.5,
defaultViewMode: "grid"
},
{
id: "files",
title: I18n.tr("Files", "launcher file search section title and filter option"),
icon: "folder",
priority: 4,
defaultViewMode: "list"
},
{
id: "fallback",
title: I18n.tr("Commands", "noun, launcher results section title"),
icon: "terminal",
priority: 5,
defaultViewMode: "list"
}
]
property int historyIndex: -1
property string typingBackup: ""
function navigateHistory(direction) {
let history = SessionData.launcherQueryHistory;
if (history.length === 0)
return;
if (historyIndex === -1)
typingBackup = searchQuery;
let nextIndex = historyIndex + (direction === "up" ? 1 : -1);
if (nextIndex >= history.length)
nextIndex = history.length - 1;
if (nextIndex < -1)
nextIndex = -1;
if (nextIndex === historyIndex)
return;
historyIndex = nextIndex;
let targetText = (historyIndex === -1) ? typingBackup : history[historyIndex];
setSearchQuery(targetText);
searchQueryRequested(targetText);
}
property string fileSearchType: "all"
property string fileSearchExt: ""
property string fileSearchFolder: ""
property string fileSearchSort: "score"
property string pluginFilter: ""
property string activePluginName: ""
property var activePluginCategories: []
property string activePluginCategory: ""
property string appCategory: ""
property var appCategories: []
function sectionViewPreference(sectionId) {
switch (sectionId) {
case "clipboard":
return getPluginViewPref("dms_clipboard_search");
case "settings":
return getPluginViewPref("dms_settings_search");
default:
if (sectionId?.startsWith("plugin_"))
return getPluginViewPref(sectionId.substring(7));
return null;
}
}
function getSectionViewMode(sectionId) {
if (sectionId === "browse_plugins")
return "list";
var sectionPref = sectionViewPreference(sectionId);
if (sectionPref?.enforced)
return sectionPref.mode;
if (pluginViewPreferences[sectionId]?.enforced)
return pluginViewPreferences[sectionId].mode;
if (sectionViewModes[sectionId])
return sectionViewModes[sectionId];
var savedModes = viewModeContext === "appDrawer" ? (SettingsData.appDrawerSectionViewModes || {}) : (SettingsData.spotlightSectionViewModes || {});
if (savedModes[sectionId])
return savedModes[sectionId];
for (var i = 0; i < sectionDefinitions.length; i++) {
if (sectionDefinitions[i].id === sectionId)
return sectionDefinitions[i].defaultViewMode || "list";
}
if (pluginViewPreferences[sectionId]?.mode)
return pluginViewPreferences[sectionId].mode;
return "list";
}
function setSectionViewMode(sectionId, mode) {
if (sectionId === "browse_plugins")
return;
if (sectionViewPreference(sectionId)?.enforced)
return;
if (pluginViewPreferences[sectionId]?.enforced)
return;
sectionViewModes = Object.assign({}, sectionViewModes, {
[sectionId]: mode
});
viewModeVersion++;
if (viewModeContext === "appDrawer") {
var savedModes = Object.assign({}, SettingsData.appDrawerSectionViewModes || {}, {
[sectionId]: mode
});
SettingsData.appDrawerSectionViewModes = savedModes;
} else {
var savedModes = Object.assign({}, SettingsData.spotlightSectionViewModes || {}, {
[sectionId]: mode
});
SettingsData.spotlightSectionViewModes = savedModes;
}
viewModeChanged(sectionId, mode);
}
function canChangeSectionViewMode(sectionId) {
if (sectionId === "browse_plugins")
return false;
if (sectionViewPreference(sectionId)?.enforced)
return false;
return !pluginViewPreferences[sectionId]?.enforced;
}
function canCollapseSection(sectionId) {
return searchMode === "all";
}
function setPluginViewPreference(pluginId, mode, enforced) {
var prefs = Object.assign({}, pluginViewPreferences);
prefs[pluginId] = {
mode: mode,
enforced: enforced || false
};
pluginViewPreferences = prefs;
}
function applyActivePluginViewPreference(pluginId, isBuiltIn) {
var sectionId = "plugin_" + pluginId;
var pref = null;
if (isBuiltIn) {
var builtIn = AppSearchService.builtInPlugins[pluginId];
if (builtIn && builtIn.viewMode) {
pref = {
mode: builtIn.viewMode,
enforced: builtIn.viewModeEnforced === true
};
}
} else {
pref = PluginService.getPluginViewPreference(pluginId);
}
if (pref && pref.mode) {
setPluginViewPreference(sectionId, pref.mode, pref.enforced);
} else {
var prefs = Object.assign({}, pluginViewPreferences);
delete prefs[sectionId];
pluginViewPreferences = prefs;
}
}
function clearActivePluginViewPreference() {
var prefs = {};
for (var key in pluginViewPreferences) {
if (!key.startsWith("plugin_")) {
prefs[key] = pluginViewPreferences[key];
}
}
pluginViewPreferences = prefs;
}
property int _searchVersion: 0
property bool _pluginPhasePending: false
property bool _pluginPhaseForceFirst: false
property var _phase1Items: []
property var _lastPhase1Items: []
property var _lastAppItems: []
property string _lastPhase1Query: ""
property var _lastSettingsItems: []
property var _lastClipboardItems: []
property var _lastPluginItems: ({})
property var _lastPluginOrder: []
property string _lastPluginQuery: ""
property string _lastPluginMode: ""
property bool _searchPending: false
// Leading-edge debounce: search immediately when idle, coalesce bursts
function requestSearch() {
if (searchDebounce.running) {
_searchPending = true;
searchDebounce.restart();
return;
}
_searchPending = false;
performSearch();
searchDebounce.restart();
}
Timer {
id: searchDebounce
interval: 60
onTriggered: {
if (!root._searchPending)
return;
root._searchPending = false;
root.performSearch();
}
}
Timer {
id: pluginPhaseTimer
interval: 16
onTriggered: {
if (!root._pluginPhasePending)
return;
root._performPluginPhase();
}
}
function _schedulePluginPhase() {
pluginPhaseTimer.restart();
}
Timer {
id: fileSearchDebounce
interval: 200
onTriggered: root.performFileSearch()
}
function getOrTransformApp(app) {
return AppSearchService.getOrTransformApp(app, transformApp);
}
function setSearchQuery(query) {
_searchVersion++;
_queryDrivenSearch = true;
_pluginPhasePending = false;
_phase1Items = [];
searchQuery = query;
requestSearch();
if (autoSwitchedToFiles && !query.startsWith("/")) {
restorePreviousMode();
return;
}
if (query.startsWith("/")) {
var prefix = Utils.parseFileSearchPrefix(query);
var explicitType = prefix && prefix.type !== null ? prefix.type : null;
var targetType = explicitType !== null ? explicitType : (SessionData.launcherLastFileSearchType || "all");
if (searchMode !== "files") {
setMode("files", true, targetType);
} else if (fileSearchType !== targetType) {
fileSearchType = targetType;
}
if (explicitType !== null && SessionData.launcherLastFileSearchType !== explicitType) {
SessionData.setLauncherLastFileSearchType(explicitType);
}
}
var filesInAll = searchMode === "all" && (SettingsData.dankLauncherV2IncludeFilesInAll || SettingsData.dankLauncherV2IncludeFoldersInAll);
if (searchMode !== "plugins" && (searchMode === "files" || query.startsWith("/") || filesInAll) && query.length > 0) {
fileSearchDebounce.restart();
}
}
function setMode(mode, isAutoSwitch, fileTypeOverride, notPersist) {
if (searchMode === mode) {
if (mode === "files" && fileTypeOverride !== undefined && fileSearchType !== fileTypeOverride) {
fileSearchType = fileTypeOverride;
performFileSearch();
}
return;
}
if (isAutoSwitch) {
previousSearchMode = searchMode;
autoSwitchedToFiles = true;
} else {
autoSwitchedToFiles = false;
}
searchMode = mode;
if (mode === "files") {
fileSearchType = fileTypeOverride !== undefined ? fileTypeOverride : (SessionData.launcherLastFileSearchType || "all");
}
modeChanged(mode, !isAutoSwitch && notPersist !== true);
performSearch();
var filesInAll = mode === "all" && (SettingsData.dankLauncherV2IncludeFilesInAll || SettingsData.dankLauncherV2IncludeFoldersInAll) && searchQuery.length > 0;
if (mode === "files" || filesInAll) {
fileSearchDebounce.restart();
}
}
function restorePreviousMode() {
if (!autoSwitchedToFiles)
return;
autoSwitchedToFiles = false;
searchMode = previousSearchMode;
modeChanged(previousSearchMode, false);
performSearch();
}
function cycleMode(reverse = false) {
var modes = ["all", "apps", "files", "plugins"];
var currentIndex = modes.indexOf(searchMode);
if (!reverse)
var nextIndex = (currentIndex + 1) % modes.length;
else
var nextIndex = (currentIndex - 1 + modes.length) % modes.length;
setMode(modes[nextIndex]);
}
function reset() {
searchQuery = "";
searchMode = "all";
previousSearchMode = "all";
autoSwitchedToFiles = false;
isFileSearching = false;
fileSearchType = "all";
fileSearchExt = "";
fileSearchFolder = "";
fileSearchSort = "score";
sections = [];
flatModel = [];
selectedFlatIndex = 0;
selectedItem = null;
isSearching = false;
activePluginId = "";
activePluginName = "";
activePluginCategories = [];
activePluginCategory = "";
appCategory = "";
appCategories = [];
pluginFilter = "";
collapsedSections = {};
_clearModeCache();
_queryDrivenSearch = false;
_pluginPhasePending = false;
_pluginPhaseForceFirst = false;
_phase1Items = [];
}
function openSession(query, explicitQuery, mode, searchWhenEmpty) {
if (appCategory !== "" || Object.keys(collapsedSections).length > 0)
_clearModeCache();
appCategory = "";
collapsedSections = {};
explicitQuerySession = explicitQuery;
historyIndex = -1;
previousSearchMode = "all";
autoSwitchedToFiles = false;
isFileSearching = false;
fileSearchType = SessionData.launcherLastFileSearchType || "all";
fileSearchExt = "";
fileSearchFolder = "";
fileSearchSort = "score";
activePluginId = "";
activePluginName = "";
activePluginCategories = [];
activePluginCategory = "";
pluginFilter = "";
selectedFlatIndex = 0;
selectedItem = null;
_queryDrivenSearch = false;
_pluginPhasePending = false;
_pluginPhaseForceFirst = false;
_phase1Items = [];
searchMode = mode;
if (query) {
setSearchQuery(query);
return;
}
searchQuery = "";
if (searchWhenEmpty) {
performSearch();
return;
}
sections = [];
flatModel = [];
}
function loadPluginCategories(pluginId) {
if (!pluginId) {
if (activePluginCategories.length > 0) {
activePluginCategories = [];
activePluginCategory = "";
}
return;
}
const categories = AppSearchService.getPluginLauncherCategories(pluginId);
if (categories.length === activePluginCategories.length) {
let same = true;
for (let i = 0; i < categories.length; i++) {
if (categories[i].id !== activePluginCategories[i]?.id) {
same = false;
break;
}
}
if (same)
return;
}
activePluginCategories = categories;
activePluginCategory = "";
AppSearchService.setPluginLauncherCategory(pluginId, "");
}
function setActivePluginCategory(categoryId) {
if (activePluginCategory === categoryId)
return;
activePluginCategory = categoryId;
AppSearchService.setPluginLauncherCategory(activePluginId, categoryId);
performSearch();
}
function setAppCategory(category) {
if (appCategory === category)
return;
appCategory = category;
_queryDrivenSearch = true;
_clearModeCache();
performSearch();
}
function _loadAppCategories() {
appCategories = AppSearchService.getAllCategories();
}
function setFileSearchType(type) {
if (fileSearchType === type)
return;
fileSearchType = type;
SessionData.setLauncherLastFileSearchType(type);
performFileSearch();
}
function setFileSearchExt(ext) {
if (fileSearchExt === ext)
return;
fileSearchExt = ext;
performFileSearch();
}
function setFileSearchFolder(folder) {
if (fileSearchFolder === folder)
return;
fileSearchFolder = folder;
performFileSearch();
}
function setFileSearchSort(sort) {
if (fileSearchSort === sort)
return;
fileSearchSort = sort;
performFileSearch();
}
function clearPluginFilter() {
if (pluginFilter) {
pluginFilter = "";
performSearch();
return true;
}
return false;
}
function preserveSelectionAfterUpdate(forceFirst) {
if (forceFirst)
return function () {
return getFirstItemIndex();
};
var previousSelectedId = selectedItem?.id || "";
return function (newFlatModel) {
if (!previousSelectedId)
return getFirstItemIndex();
for (var i = 0; i < newFlatModel.length; i++) {
if (!newFlatModel[i].isHeader && newFlatModel[i].item?.id === previousSelectedId)
return i;
}
return getFirstItemIndex();
};
}
function performSearch() {
queryChanged(searchQuery);
var currentVersion = _searchVersion;
isSearching = true;
var shouldResetSelection = _queryDrivenSearch;
_queryDrivenSearch = false;
var restoreSelection = preserveSelectionAfterUpdate(shouldResetSelection);
var cachedSections = AppSearchService.getCachedDefaultSections();
if (!cachedSections && !_diskCacheConsumed && !searchQuery && searchMode === "all" && !pluginFilter) {
_diskCacheConsumed = true;
var diskSections = _loadDiskCache();
if (diskSections) {
activePluginId = "";
activePluginName = "";
activePluginCategories = [];
activePluginCategory = "";
clearActivePluginViewPreference();
for (var i = 0; i < diskSections.length; i++) {
if (collapsedSections[diskSections[i].id] !== undefined)
diskSections[i].collapsed = collapsedSections[diskSections[i].id];
}
_applyHighlights(diskSections, "");
flatModel = Scorer.flattenSections(diskSections);
sections = diskSections;
selectedFlatIndex = restoreSelection(flatModel);
updateSelectedItem();
isSearching = false;
searchCompleted();
return;
}
}
if (cachedSections && !searchQuery && searchMode === "all" && !pluginFilter) {
activePluginId = "";
activePluginName = "";
activePluginCategories = [];
activePluginCategory = "";
clearActivePluginViewPreference();
var modeCache = _getCachedModeData("all");
if (modeCache) {
_applyHighlights(modeCache.sections, "");
sections = modeCache.sections;
flatModel = modeCache.flatModel;
} else {
var newSections = cachedSections.map(function (s) {
var copy = Object.assign({}, s, {
items: s.items ? s.items.slice() : []
});
if (collapsedSections[s.id] !== undefined)
copy.collapsed = collapsedSections[s.id];
return copy;
});
_applyHighlights(newSections, "");
flatModel = Scorer.flattenSections(newSections);
sections = newSections;
_setCachedModeData("all", sections, flatModel);
}
selectedFlatIndex = restoreSelection(flatModel);
updateSelectedItem();
isSearching = false;
searchCompleted();
return;
}
var allItems = [];
var triggerMatch = detectTrigger(searchQuery);
if (triggerMatch.pluginId) {
var pluginChanged = activePluginId !== triggerMatch.pluginId;
activePluginId = triggerMatch.pluginId;
activePluginName = getPluginName(triggerMatch.pluginId, triggerMatch.isBuiltIn);
applyActivePluginViewPreference(triggerMatch.pluginId, triggerMatch.isBuiltIn);
if (pluginChanged && !triggerMatch.isBuiltIn)
loadPluginCategories(triggerMatch.pluginId);
var pluginItems = getPluginItems(triggerMatch.pluginId, triggerMatch.query);
for (var k = 0; k < pluginItems.length; k++)
allItems.push(pluginItems[k]);
if (triggerMatch.isBuiltIn) {
var builtInItems = AppSearchService.getBuiltInLauncherItems(triggerMatch.pluginId, triggerMatch.query);
for (var j = 0; j < builtInItems.length; j++) {
builtInItems[j]._preScored = 1000 - j;
allItems.push(transformBuiltInSearchItem(builtInItems[j], triggerMatch.pluginId));
}
}
var dynamicDefs = buildDynamicSectionDefs(allItems);
var scoredItems = Scorer.scoreItems(allItems, triggerMatch.query, getFrecencyForItem);
var sortAlpha = !triggerMatch.query && SettingsData.sortAppsAlphabetically;
var newSections = Scorer.groupBySection(scoredItems, dynamicDefs, sortAlpha, 500);
for (var sid in collapsedSections) {
for (var i = 0; i < newSections.length; i++) {
if (newSections[i].id === sid) {
newSections[i].collapsed = collapsedSections[sid];
}
}
}
_applyHighlights(newSections, triggerMatch.query);
flatModel = Scorer.flattenSections(newSections);
sections = newSections;
selectedFlatIndex = restoreSelection(flatModel);
updateSelectedItem();
isSearching = false;
searchCompleted();
return;
}
activePluginId = "";
activePluginName = "";
activePluginCategories = [];
activePluginCategory = "";
clearActivePluginViewPreference();
if (searchMode === "files") {
var prefixInfo = Utils.parseFileSearchPrefix(searchQuery);
var fileQuery = prefixInfo ? prefixInfo.query : searchQuery.trim();
isFileSearching = fileQuery.length >= 2 && DSearchService.dsearchAvailable;
sections = [];
flatModel = [];
selectedFlatIndex = 0;
selectedItem = null;
isSearching = false;
searchCompleted();
return;
}
if (searchMode === "apps") {
var isCategoryFiltered = appCategory && appCategory !== I18n.tr("All");
var cachedSections = AppSearchService.getCachedDefaultSections();
if (cachedSections && !searchQuery && !isCategoryFiltered) {
var modeCache = _getCachedModeData("apps");
if (modeCache) {
_applyHighlights(modeCache.sections, "");
sections = modeCache.sections;
flatModel = modeCache.flatModel;
} else {
var appSectionIds = ["favorites", "apps"];
var newSections = cachedSections.filter(function (s) {
return appSectionIds.indexOf(s.id) !== -1;
}).map(function (s) {
var copy = Object.assign({}, s, {
items: s.items ? s.items.slice() : []
});
if (collapsedSections[s.id] !== undefined)
copy.collapsed = collapsedSections[s.id];
return copy;
});
_applyHighlights(newSections, "");
flatModel = Scorer.flattenSections(newSections);
sections = newSections;
_setCachedModeData("apps", sections, flatModel);
}
selectedFlatIndex = restoreSelection(flatModel);
updateSelectedItem();
isSearching = false;
searchCompleted();
return;
}
if (isCategoryFiltered) {
var rawApps = AppSearchService.getAppsInCategory(appCategory);
for (var i = 0; i < rawApps.length; i++) {
allItems.push(getOrTransformApp(rawApps[i]));
}
var allCoreApps = AppSearchService.getCoreApps("");
for (var i = 0; i < allCoreApps.length; i++) {
var coreAppCats = AppSearchService.getCategoriesForApp(allCoreApps[i]);
if (coreAppCats.indexOf(appCategory) !== -1)
allItems.push(transformCoreApp(allCoreApps[i]));
}
} else {
var apps = searchApps(searchQuery);
for (var i = 0; i < apps.length; i++) {
allItems.push(apps[i]);
}
}
var scoredItems = Scorer.scoreItems(allItems, searchQuery, getFrecencyForItem);
var sortAlpha = !searchQuery && SettingsData.sortAppsAlphabetically;
var newSections = Scorer.groupBySection(scoredItems, buildDynamicSectionDefs(allItems), sortAlpha, searchQuery ? 50 : 500);
for (var sid in collapsedSections) {
for (var i = 0; i < newSections.length; i++) {
if (newSections[i].id === sid) {
newSections[i].collapsed = collapsedSections[sid];
}
}
}
_applyHighlights(newSections, searchQuery);
flatModel = Scorer.flattenSections(newSections);
sections = newSections;
selectedFlatIndex = restoreSelection(flatModel);
updateSelectedItem();
isSearching = false;
searchCompleted();
return;
}
if (searchMode === "plugins") {
if (!searchQuery && !pluginFilter) {
var browseItems = getPluginBrowseItems();
for (var k = 0; k < browseItems.length; k++)
allItems.push(browseItems[k]);
} else if (pluginFilter) {
var isBuiltInFilter = !!AppSearchService.builtInPlugins[pluginFilter];
applyActivePluginViewPreference(pluginFilter, isBuiltInFilter);
var filterItems = getPluginItems(pluginFilter, searchQuery);
for (var k = 0; k < filterItems.length; k++)
allItems.push(filterItems[k]);
var builtInItems = AppSearchService.getBuiltInLauncherItems(pluginFilter, searchQuery, true);
for (var j = 0; j < builtInItems.length; j++) {
allItems.push(transformBuiltInSearchItem(builtInItems[j], pluginFilter));
}
} else {
var emptyTriggerPlugins = getEmptyTriggerPlugins();
for (var i = 0; i < emptyTriggerPlugins.length; i++) {
var pluginId = emptyTriggerPlugins[i];
var pItems = getPluginItems(pluginId, searchQuery);
for (var k = 0; k < pItems.length; k++)
allItems.push(pItems[k]);
}
var builtInLauncherPlugins = getBuiltInEmptyTriggerLaunchers();
for (var i = 0; i < builtInLauncherPlugins.length; i++) {
var pluginId = builtInLauncherPlugins[i];
var blItems = AppSearchService.getBuiltInLauncherItems(pluginId, searchQuery);
for (var j = 0; j < blItems.length; j++) {
allItems.push(transformBuiltInSearchItem(blItems[j], pluginId));
}
}
}
var dynamicDefs = buildDynamicSectionDefs(allItems);
var scoredItems = Scorer.scoreItems(allItems, searchQuery, getFrecencyForItem);
var sortAlpha = !searchQuery && SettingsData.sortAppsAlphabetically;
var newSections = Scorer.groupBySection(scoredItems, dynamicDefs, sortAlpha, 500);
for (var sid in collapsedSections) {
for (var i = 0; i < newSections.length; i++) {
if (newSections[i].id === sid) {
newSections[i].collapsed = collapsedSections[sid];
}
}
}
_applyHighlights(newSections, searchQuery);
flatModel = Scorer.flattenSections(newSections);
sections = newSections;
selectedFlatIndex = restoreSelection(flatModel);
updateSelectedItem();
isSearching = false;
searchCompleted();
return;
}
var apps = searchApps(searchQuery);
for (var i = 0; i < apps.length; i++) {
allItems.push(apps[i]);
}
_lastAppItems = apps;
_lastPhase1Query = searchQuery;
if (searchMode === "all") {
appendSharedAllResults(allItems, searchQuery);
if (searchQuery && searchQuery.length >= 2) {
_pluginPhasePending = true;
_phase1Items = allItems.slice();
_pluginPhaseForceFirst = shouldResetSelection;
_schedulePluginPhase();
isSearching = true;
searchCompleted();
return;
} else if (!searchQuery) {
_pluginPhasePending = true;
_phase1Items = allItems.slice();
_pluginPhaseForceFirst = shouldResetSelection;
_schedulePluginPhase();
}
}
var dynamicDefs = buildDynamicSectionDefs(allItems);
if (currentVersion !== _searchVersion) {
isSearching = false;
return;
}
var scoredItems = Scorer.scoreItems(allItems, searchQuery, getFrecencyForItem);
var sortAlpha = !searchQuery && SettingsData.sortAppsAlphabetically;
var newSections = Scorer.groupBySection(scoredItems, dynamicDefs, sortAlpha, searchQuery ? 50 : 500);
if (currentVersion !== _searchVersion) {
isSearching = false;
return;
}
for (var i = 0; i < newSections.length; i++) {
var sid = newSections[i].id;
if (collapsedSections[sid] !== undefined) {
newSections[i].collapsed = collapsedSections[sid];
}
}
_applyHighlights(newSections, searchQuery);
flatModel = Scorer.flattenSections(newSections);
sections = newSections;
selectedFlatIndex = restoreSelection(flatModel);
updateSelectedItem();
isSearching = _pluginPhasePending;
searchCompleted();
}
function _performPluginPhase() {
_pluginPhasePending = false;
if (searchMode !== "all")
return;
if (searchQuery && searchQuery.length < 2)
return;
var currentVersion = _searchVersion;
var restoreSelection = preserveSelectionAfterUpdate(_pluginPhaseForceFirst);
var allItems = _phase1Items;
_phase1Items = [];
if (!searchQuery) {
var emptyTriggerOrdered = getEmptyTriggerPluginsOrdered();
for (var i = 0; i < emptyTriggerOrdered.length; i++) {
if (currentVersion !== _searchVersion)
return;
var plugin = emptyTriggerOrdered[i];
if (plugin.isBuiltIn) {
var blItems = AppSearchService.getBuiltInLauncherItems(plugin.id, searchQuery);
for (var j = 0; j < blItems.length; j++)
allItems.push(transformBuiltInSearchItem(blItems[j], plugin.id));
} else {
var pItems = getPluginItems(plugin.id, searchQuery);
for (var j = 0; j < pItems.length; j++)
allItems.push(pItems[j]);
}
}
var browseItems = getPluginBrowseItems();
for (var i = 0; i < browseItems.length; i++)
allItems.push(browseItems[i]);
} else {
var phase1Items = allItems.slice();
var pluginItems = {};
var pluginOrder = [];
var allPluginsOrdered = getAllVisiblePluginsOrdered();
for (var i = 0; i < allPluginsOrdered.length; i++) {
if (currentVersion !== _searchVersion)
return;
var plugin = allPluginsOrdered[i];
if (plugin.isBuiltIn && (plugin.id === "dms_settings_search" || plugin.id === "dms_clipboard_search"))
continue;
var items = _pluginQueryItems(plugin);
pluginItems[plugin.id] = items;
pluginOrder.push(plugin.id);
for (var j = 0; j < items.length; j++)
allItems.push(items[j]);
}
_lastPhase1Items = phase1Items;
_lastPluginItems = pluginItems;
_lastPluginOrder = pluginOrder;
_lastPluginQuery = searchQuery;
_lastPluginMode = searchMode;
}
if (currentVersion !== _searchVersion)
return;
_publishPluginResults(allItems, restoreSelection);
}
function _pluginQueryItems(plugin) {
var maxPerPlugin = 10;
var items = [];
if (plugin.isBuiltIn) {
var blItems = AppSearchService.getBuiltInLauncherItems(plugin.id, searchQuery);
var blLimit = Math.min(blItems.length, maxPerPlugin);
for (var j = 0; j < blLimit; j++) {
var item = transformBuiltInSearchItem(blItems[j], plugin.id);
item._preScored = 900 - j;
items.push(item);
}
return items;
}
var pItems = getPluginItems(plugin.id, searchQuery, maxPerPlugin);
for (var k = 0; k < pItems.length; k++) {
pItems[k]._preScored = 900 - k;
items.push(pItems[k]);
}
return items;
}
function _refreshPluginResults(pluginId) {
if (_pluginPhasePending || _lastPluginQuery !== searchQuery || _lastPluginMode !== searchMode)
return false;
if (_lastPluginItems[pluginId] === undefined)
return false;
var plugin = getAllVisiblePluginsOrdered().find(entry => entry.id === pluginId);
if (!plugin)
return false;
var fresh = _pluginQueryItems(plugin);
if (_samePluginItems(_lastPluginItems[pluginId], fresh))
return true;
var updated = Object.assign({}, _lastPluginItems);
updated[pluginId] = fresh;
_lastPluginItems = updated;
var allItems = _lastPhase1Items.slice();
for (var i = 0; i < _lastPluginOrder.length; i++) {
var items = updated[_lastPluginOrder[i]] || [];
for (var j = 0; j < items.length; j++)
allItems.push(items[j]);
}
_publishPluginResults(allItems, preserveSelectionAfterUpdate(false));
return true;
}
function _samePluginItems(previous, next) {
if (!previous || previous.length !== next.length)
return false;
for (var i = 0; i < next.length; i++) {
if (previous[i].id !== next[i].id || previous[i].name !== next[i].name || previous[i].subtitle !== next[i].subtitle)
return false;
}
return true;
}
function _publishPluginResults(allItems, restoreSelection) {
var dynamicDefs = buildDynamicSectionDefs(allItems);
var scoredItems = Scorer.scoreItems(allItems, searchQuery, getFrecencyForItem);
var sortAlpha = !searchQuery && SettingsData.sortAppsAlphabetically;
var newSections = Scorer.groupBySection(scoredItems, dynamicDefs, sortAlpha, searchQuery ? 50 : 500);
for (var i = 0; i < newSections.length; i++) {
var sid = newSections[i].id;
if (collapsedSections[sid] !== undefined)
newSections[i].collapsed = collapsedSections[sid];
}
_applyHighlights(newSections, searchQuery);
flatModel = Scorer.flattenSections(newSections);
sections = newSections;
if (!AppSearchService.isCacheValid() && !searchQuery && !pluginFilter) {
AppSearchService.setCachedDefaultSections(sections, flatModel);
_saveDiskCache(sections);
}
selectedFlatIndex = restoreSelection(flatModel);
updateSelectedItem();
isSearching = false;
searchCompleted();
}
function performFileSearch() {
if (!DSearchService.dsearchAvailable)
return;
var fileQuery = "";
var effectiveType = fileSearchType || "all";
var includeFiles = SettingsData.dankLauncherV2IncludeFilesInAll;
var includeFolders = SettingsData.dankLauncherV2IncludeFoldersInAll;
if (searchQuery.startsWith("/")) {
var prefixInfo = Utils.parseFileSearchPrefix(searchQuery);
fileQuery = prefixInfo ? prefixInfo.query : searchQuery.substring(1).trim();
} else if (searchMode === "files") {
fileQuery = searchQuery.trim();
} else if (searchMode === "all" && (includeFiles || includeFolders)) {
fileQuery = searchQuery.trim();
if (includeFiles && !includeFolders)
effectiveType = "file";
else if (!includeFiles && includeFolders)
effectiveType = "dir";
else
effectiveType = "all";
} else {
return;
}
if (fileQuery.length < 2) {
isFileSearching = false;
return;
}
isFileSearching = true;
var splitBothTypes = searchMode === "all" && includeFiles && includeFolders && DSearchService.supportsTypeFilter;
var queryTypes = splitBothTypes ? ["file", "dir"] : [effectiveType];
var pending = queryTypes.length;
var aggregatedItems = [];
for (var t = 0; t < queryTypes.length; t++) {
var queryType = queryTypes[t];
var params = {
limit: 20,
fuzzy: true,
sort: fileSearchSort || "score",
desc: true
};
if (DSearchService.supportsTypeFilter) {
params.type = (queryType && queryType !== "all") ? queryType : "all";
}
if (fileSearchExt) {
params.ext = fileSearchExt;
}
if (fileSearchFolder) {
params.folder = fileSearchFolder;
}
DSearchService.search(fileQuery, params, function (response) {
pending--;
if (!response.error) {
var hits = response.result?.hits || [];
for (var i = 0; i < hits.length; i++) {
var hit = hits[i];
var docTypes = hit.locations?.doc_type;
var isDir = docTypes ? !!docTypes["dir"] : false;
aggregatedItems.push(transformFileResult({
path: hit.id || "",
score: hit.score || 0,
is_dir: isDir
}));
}
}
if (pending > 0)
return;
isFileSearching = false;
_applyFileSearchResults(aggregatedItems, effectiveType);
});
}
}
function _applyFileSearchResults(fileItems, effectiveType) {
var fileSections = [];
var showType = effectiveType;
var order = SettingsData.launcherPluginOrder || [];
var filesOrderIdx = order.indexOf("__files");
var foldersOrderIdx = order.indexOf("__folders");
var filesPriority = filesOrderIdx !== -1 ? 2.6 + filesOrderIdx * 0.01 : 4;
var foldersPriority = foldersOrderIdx !== -1 ? 2.6 + foldersOrderIdx * 0.01 : 4.1;
if (showType === "all" && DSearchService.supportsTypeFilter) {
var onlyFiles = [];
var onlyDirs = [];
for (var j = 0; j < fileItems.length; j++) {
if (fileItems[j].data?.is_dir)
onlyDirs.push(fileItems[j]);
else
onlyFiles.push(fileItems[j]);
}
if (onlyFiles.length > 0) {
fileSections.push({
id: "files",
title: I18n.tr("Files"),
icon: "insert_drive_file",
priority: filesPriority,
items: onlyFiles,
collapsed: collapsedSections["files"] || false,
flatStartIndex: 0
});
}
if (onlyDirs.length > 0) {
fileSections.push({
id: "folders",
title: I18n.tr("Folders", "launcher file search section title and filter option"),
icon: "folder",
priority: foldersPriority,
items: onlyDirs,
collapsed: collapsedSections["folders"] || false,
flatStartIndex: 0
});
}
} else {
var filesIcon = showType === "dir" ? "folder" : showType === "file" ? "insert_drive_file" : "folder";
var filesTitle = showType === "dir" ? I18n.tr("Folders") : I18n.tr("Files");
var singlePriority = showType === "dir" ? foldersPriority : filesPriority;
if (fileItems.length > 0) {
fileSections.push({
id: "files",
title: filesTitle,
icon: filesIcon,
priority: singlePriority,
items: fileItems,
collapsed: collapsedSections["files"] || false,
flatStartIndex: 0
});
}
}
var newSections;
if (searchMode === "files") {
newSections = fileSections;
} else {
var existingNonFile = sections.filter(function (s) {
return s.id !== "files" && s.id !== "folders";
});
newSections = existingNonFile.concat(fileSections);
}
newSections.sort(function (a, b) {
return a.priority - b.priority;
});
_applyHighlights(newSections, searchQuery);
flatModel = Scorer.flattenSections(newSections);
sections = newSections;
selectedFlatIndex = getFirstItemIndex();
updateSelectedItem();
}
function searchApps(query) {
var apps = AppSearchService.searchApplications(query);
var items = [];
for (var i = 0; i < apps.length; i++) {
items.push(getOrTransformApp(apps[i]));
}
var coreApps = AppSearchService.getCoreApps(query);
for (var i = 0; i < coreApps.length; i++) {
items.push(transformCoreApp(coreApps[i]));
}
return items;
}
function transformApp(app) {
var appId = app.id || app.execString || app.exec || "";
var override = SessionData.getAppOverride(appId);
return Transform.transformApp(app, override, [], I18n.tr("Launch"));
}
function transformCoreApp(app) {
return Transform.transformCoreApp(app, I18n.tr("Open"));
}
function transformBuiltInLauncherItem(item, pluginId) {
return Transform.transformBuiltInLauncherItem(item, pluginId, I18n.tr("Open"));
}
function transformBuiltInSearchItem(item, pluginId) {
if (pluginId === "dms_clipboard_search" || item.type === "clipboard") {
var transformed = transformClipboardEntry(item.data || item);
if (item._preScored !== undefined)
transformed._preScored = item._preScored;
return transformed;
}
return transformBuiltInLauncherItem(item, pluginId);
}
function transformFileResult(file) {
return Transform.transformFileResult(file, I18n.tr("Open"), I18n.tr("Open folder"), I18n.tr("Copy path"), I18n.tr("Open in terminal"));
}
function transformClipboardEntry(entry) {
var copyLabel = I18n.tr("Copy");
var pasteLabel = I18n.tr("Paste");
var primaryLabel = SettingsData.clipboardEnterToPaste ? pasteLabel : copyLabel;
var pasteHintLabel = SettingsData.clipboardEnterToPaste ? I18n.tr("Shift+Enter to copy") : I18n.tr("Shift+Enter to paste");
return Transform.transformClipboardItem(entry, copyLabel, pasteLabel, primaryLabel, I18n.tr("Image"), I18n.tr("Text"), I18n.tr("Pinned"), pasteHintLabel, "", I18n.tr("Clipboard"));
}
function builtInLauncherVisibleInAll(pluginId) {
return SettingsData.getBuiltInPluginSetting(pluginId, "enabled", true) && SettingsData.getPluginAllowWithoutTrigger(pluginId);
}
function clipboardSearchEnabledInAll() {
return builtInLauncherVisibleInAll("dms_clipboard_search") && ClipboardService.clipboardAvailable;
}
function appendSharedAllResults(allItems, query) {
if (!query || query.length < 2)
return;
var settingsItems = _settingsSharedItems(query);
var clipboardItems = _clipboardSharedItems(query);
for (var i = 0; i < settingsItems.length; i++)
allItems.push(settingsItems[i]);
for (var j = 0; j < clipboardItems.length; j++)
allItems.push(clipboardItems[j]);
_lastSettingsItems = settingsItems;
_lastClipboardItems = clipboardItems;
}
function _settingsSharedItems(query) {
var items = [];
if (!builtInLauncherVisibleInAll("dms_settings_search"))
return items;
var settingsItems = AppSearchService.getBuiltInLauncherItems("dms_settings_search", query);
var settingsLimit = Math.min(settingsItems.length, 8);
for (var i = 0; i < settingsLimit; i++) {
settingsItems[i]._preScored = 890 - i;
items.push(transformBuiltInSearchItem(settingsItems[i], "dms_settings_search"));
}
return items;
}
function _clipboardSharedItems(query) {
var items = [];
if (!clipboardSearchEnabledInAll())
return items;
var clipboardItems = AppSearchService.getBuiltInLauncherItems("dms_clipboard_search", query);
var clipboardLimit = Math.min(clipboardItems.length, 8);
for (var j = 0; j < clipboardLimit; j++) {
clipboardItems[j]._preScored = 840 - j;
items.push(transformBuiltInSearchItem(clipboardItems[j], "dms_clipboard_search"));
}
return items;
}
function _refreshClipboardResults() {
if (searchMode !== "all" || searchQuery.length < 2 || _lastPhase1Query !== searchQuery)
return false;
var fresh = _clipboardSharedItems(searchQuery);
if (_samePluginItems(_lastClipboardItems, fresh))
return true;
_lastClipboardItems = fresh;
var phase1 = _lastAppItems.slice();
for (var i = 0; i < _lastSettingsItems.length; i++)
phase1.push(_lastSettingsItems[i]);
for (var j = 0; j < fresh.length; j++)
phase1.push(fresh[j]);
if (_pluginPhasePending) {
_phase1Items = phase1;
return true;
}
if (_lastPluginQuery !== searchQuery || _lastPluginMode !== searchMode)
return false;
var allItems = phase1;
for (var k = 0; k < _lastPluginOrder.length; k++) {
var items = _lastPluginItems[_lastPluginOrder[k]] || [];
for (var m = 0; m < items.length; m++)
allItems.push(items[m]);
}
_publishPluginResults(allItems, preserveSelectionAfterUpdate(false));
return true;
}
function detectTrigger(query) {
if (!query || query.length === 0)
return {
pluginId: null,
query: query
};
var pluginTriggers = PluginService.getAllPluginTriggers();
for (var trigger in pluginTriggers) {
if (trigger && query.startsWith(trigger)) {
return {
pluginId: pluginTriggers[trigger],
query: query.substring(trigger.length).trim()
};
}
}
var builtInTriggers = AppSearchService.getBuiltInLauncherTriggers();
for (var trigger in builtInTriggers) {
if (trigger && query.startsWith(trigger)) {
return {
pluginId: builtInTriggers[trigger],
query: query.substring(trigger.length).trim(),
isBuiltIn: true
};
}
}
return {
pluginId: null,
query: query
};
}
function getEmptyTriggerPlugins() {
var plugins = PluginService.getPluginsWithEmptyTrigger();
var visible = plugins.filter(function (pluginId) {
return SettingsData.getPluginAllowWithoutTrigger(pluginId);
});
return sortPluginIdsByOrder(visible);
}
function getAllLauncherPluginIds() {
var launchers = PluginService.getLauncherPlugins();
return Object.keys(launchers);
}
function getVisibleLauncherPluginIds() {
var launchers = PluginService.getLauncherPlugins();
var visible = Object.keys(launchers).filter(function (pluginId) {
return SettingsData.getPluginAllowWithoutTrigger(pluginId);
});
return sortPluginIdsByOrder(visible);
}
function getAllBuiltInLauncherIds() {
var launchers = AppSearchService.getBuiltInLauncherPlugins();
return Object.keys(launchers);
}
function getVisibleBuiltInLauncherIds() {
var launchers = AppSearchService.getBuiltInLauncherPlugins();
var visible = Object.keys(launchers).filter(function (pluginId) {
return SettingsData.getPluginAllowWithoutTrigger(pluginId);
});
return sortPluginIdsByOrder(visible);
}
function sortPluginIdsByOrder(pluginIds) {
return Utils.sortPluginIdsByOrder(pluginIds, SettingsData.launcherPluginOrder || []);
}
function getAllVisiblePluginsOrdered() {
var thirdPartyLaunchers = PluginService.getLauncherPlugins() || {};
var builtInLaunchers = AppSearchService.getBuiltInLauncherPlugins() || {};
var all = [];
for (var id in thirdPartyLaunchers) {
if (SettingsData.getPluginAllowWithoutTrigger(id))
all.push({
id: id,
isBuiltIn: false
});
}
for (var id in builtInLaunchers) {
if (SettingsData.getPluginAllowWithoutTrigger(id))
all.push({
id: id,
isBuiltIn: true
});
}
return Utils.sortPluginsOrdered(all, SettingsData.launcherPluginOrder || []);
}
function getEmptyTriggerPluginsOrdered() {
var thirdParty = PluginService.getPluginsWithEmptyTrigger() || [];
var builtIn = AppSearchService.getBuiltInLauncherPluginsWithEmptyTrigger() || [];
var all = [];
for (var i = 0; i < thirdParty.length; i++) {
var id = thirdParty[i];
if (SettingsData.getPluginAllowWithoutTrigger(id))
all.push({
id: id,
isBuiltIn: false
});
}
for (var i = 0; i < builtIn.length; i++) {
var id = builtIn[i];
if (SettingsData.getPluginAllowWithoutTrigger(id))
all.push({
id: id,
isBuiltIn: true
});
}
return Utils.sortPluginsOrdered(all, SettingsData.launcherPluginOrder || []);
}
function getPluginBrowseItems() {
var items = [];
var browseLabel = I18n.tr("Browse");
var triggerLabel = I18n.tr("Trigger: %1");
var noTriggerLabel = I18n.tr("No trigger");
var launchers = PluginService.getLauncherPlugins();
for (var pluginId in launchers) {
var trigger = PluginService.getPluginTrigger(pluginId);
var isAllowed = SettingsData.getPluginAllowWithoutTrigger(pluginId);
items.push(Transform.createPluginBrowseItem(pluginId, launchers[pluginId], trigger, false, isAllowed, browseLabel, triggerLabel, noTriggerLabel));
}
var builtInLaunchers = AppSearchService.getBuiltInLauncherPlugins();
for (var pluginId in builtInLaunchers) {
var trigger = AppSearchService.getBuiltInPluginTrigger(pluginId);
var isAllowed = SettingsData.getPluginAllowWithoutTrigger(pluginId);
items.push(Transform.createPluginBrowseItem(pluginId, builtInLaunchers[pluginId], trigger, true, isAllowed, browseLabel, triggerLabel, noTriggerLabel));
}
return items;
}
function getBuiltInEmptyTriggerLaunchers() {
var plugins = AppSearchService.getBuiltInLauncherPluginsWithEmptyTrigger();
var visible = plugins.filter(function (pluginId) {
return SettingsData.getPluginAllowWithoutTrigger(pluginId);
});
return sortPluginIdsByOrder(visible);
}
function getPluginItems(pluginId, query, limit) {
var items = AppSearchService.getPluginItemsForPlugin(pluginId, query);
var count = limit > 0 && limit < items.length ? limit : items.length;
var transformed = [];
for (var i = 0; i < count; i++) {
transformed.push(transformPluginItem(items[i], pluginId));
}
return transformed;
}
function getPluginName(pluginId, isBuiltIn) {
if (isBuiltIn) {
var plugin = AppSearchService.builtInPlugins[pluginId];
return plugin ? plugin.name : pluginId;
}
var launchers = PluginService.getLauncherPlugins();
if (launchers[pluginId]) {
return launchers[pluginId].name || pluginId;
}
return pluginId;
}
function getPluginMetadata(pluginId) {
var builtIn = AppSearchService.builtInPlugins[pluginId];
if (builtIn) {
return {
name: builtIn.name || pluginId,
icon: builtIn.cornerIcon || "extension"
};
}
var launchers = PluginService.getLauncherPlugins();
if (launchers[pluginId]) {
var rawIcon = launchers[pluginId].icon || "extension";
return {
name: launchers[pluginId].name || pluginId,
icon: Utils.stripIconPrefix(rawIcon)
};
}
return {
name: pluginId,
icon: "extension"
};
}
function buildDynamicSectionDefs(items) {
var baseDefs = sectionDefinitions.map(function (def) {
return Object.assign({}, def);
});
var pluginSections = {};
var order = SettingsData.launcherPluginOrder || [];
var orderMap = {};
for (var k = 0; k < order.length; k++)
orderMap[order[k]] = k;
var unorderedPriority = 2.6 + order.length * 0.01;
for (var d = 0; d < baseDefs.length; d++) {
var virtualId = baseDefs[d].id === "settings" ? "dms_settings_search" : baseDefs[d].id === "clipboard" ? "dms_clipboard_search" : "";
if (virtualId && orderMap[virtualId] !== undefined)
baseDefs[d].priority = 2.6 + orderMap[virtualId] * 0.01;
}
for (var i = 0; i < items.length; i++) {
var section = items[i].section;
if (!section || !section.startsWith("plugin_"))
continue;
if (pluginSections[section])
continue;
var pluginId = section.substring(7);
var meta = getPluginMetadata(pluginId);
var viewPref = getPluginViewPref(pluginId);
var orderIdx = orderMap[pluginId];
var defaultPriority = AppSearchService.builtInPlugins[pluginId]?.defaultSectionPriority;
var priority;
if (orderIdx !== undefined) {
priority = 2.6 + orderIdx * 0.01;
} else if (defaultPriority !== undefined) {
priority = defaultPriority;
} else {
priority = unorderedPriority;
unorderedPriority += 0.01;
}
pluginSections[section] = {
id: section,
title: meta.name,
icon: meta.icon,
priority: priority,
defaultViewMode: viewPref.mode || "list"
};
if (viewPref.mode)
setPluginViewPreference(section, viewPref.mode, viewPref.enforced);
}
for (var sectionId in pluginSections) {
baseDefs.push(pluginSections[sectionId]);
}
baseDefs.sort(function (a, b) {
return a.priority - b.priority;
});
return baseDefs;
}
function getPluginViewPref(pluginId) {
var builtIn = AppSearchService.builtInPlugins[pluginId];
if (builtIn && builtIn.viewMode) {
return {
mode: builtIn.viewMode,
enforced: builtIn.viewModeEnforced === true
};
}
var pref = PluginService.getPluginViewPreference(pluginId);
if (pref && pref.mode) {
return pref;
}
return {
mode: "list",
enforced: false
};
}
function transformPluginItem(item, pluginId) {
return Transform.transformPluginItem(item, pluginId, I18n.tr("Select", "verb, primary action label for a launcher plugin item"));
}
function getFrecencyForItem(item) {
if (item.type !== "app")
return null;
var appId = item.id;
var usageRanking = AppUsageHistoryData.appUsageRanking || {};
var idVariants = [appId, appId.replace(".desktop", "")];
var usageData = null;
for (var i = 0; i < idVariants.length; i++) {
if (usageRanking[idVariants[i]]) {
usageData = usageRanking[idVariants[i]];
break;
}
}
return {
usageCount: usageData?.usageCount || 0
};
}
function getFirstItemIndex() {
return Nav.getFirstItemIndex(flatModel);
}
function _getCachedModeData(mode) {
return _modeSectionsCache[mode] || null;
}
function _setCachedModeData(mode, sectionsData, flatModelData) {
var cache = Object.assign({}, _modeSectionsCache);
cache[mode] = {
sections: sectionsData,
flatModel: flatModelData
};
_modeSectionsCache = cache;
}
function _clearModeCache() {
_modeSectionsCache = {};
}
function _saveDiskCache(sectionsData) {
var serializable = [];
for (var i = 0; i < sectionsData.length; i++) {
var s = sectionsData[i];
var items = [];
var srcItems = s.items || [];
for (var j = 0; j < srcItems.length; j++) {
var it = srcItems[j];
items.push({
id: it.id,
type: it.type,
name: it.name || "",
subtitle: it.subtitle || "",
icon: it.icon || "",
iconType: it.iconType || "image",
iconFull: it.iconFull || "",
section: it.section || "",
isCore: it.isCore || false,
isBuiltInLauncher: it.isBuiltInLauncher || false,
pluginId: it.pluginId || "",
source: it.source || ""
});
}
serializable.push({
id: s.id,
title: s.title || "",
icon: s.icon || "",
priority: s.priority || 0,
items: items
});
}
CacheData.saveLauncherCache(serializable);
}
function _actionsFromDesktopEntry(appId) {
if (!appId)
return [];
var entry = DesktopEntries.heuristicLookup(appId);
if (!entry || !entry.actions || entry.actions.length === 0)
return [];
var result = [];
for (var i = 0; i < entry.actions.length; i++) {
result.push({
name: entry.actions[i].name,
icon: "play_arrow",
actionData: entry.actions[i]
});
}
return result;
}
function _diskCacheSectionDef(sectionId) {
for (var i = 0; i < sectionDefinitions.length; i++) {
if (sectionDefinitions[i].id === sectionId)
return sectionDefinitions[i];
}
return null;
}
function _diskCacheSection(def, items) {
return {
id: def.id || "",
title: def.title || "",
icon: def.icon || "",
priority: def.priority || 0,
items: items,
collapsed: false,
flatStartIndex: 0
};
}
function _loadDiskCache() {
var cached = CacheData.loadLauncherCache();
if (!cached || !Array.isArray(cached) || cached.length === 0)
return null;
var browseItems = getPluginBrowseItems();
var liveCoreItems = {};
var liveCoreApps = AppSearchService.getCoreApps("");
for (var c = 0; c < liveCoreApps.length; c++) {
var coreItem = transformCoreApp(liveCoreApps[c]);
liveCoreItems[coreItem.id] = coreItem;
}
var sectionsData = [];
var browseSectionSeen = false;
for (var i = 0; i < cached.length; i++) {
var s = cached[i];
if (s.id === "browse_plugins") {
browseSectionSeen = true;
if (browseItems.length > 0)
sectionsData.push(_diskCacheSection(_diskCacheSectionDef(s.id) || s, browseItems));
continue;
}
var items = [];
var srcItems = s.items || [];
for (var j = 0; j < srcItems.length; j++) {
var it = srcItems[j];
if (it.isCore) {
if (liveCoreItems[it.id])
items.push(liveCoreItems[it.id]);
continue;
}
if (it.type === "plugin_browse" || it.isBuiltInLauncher || it.pluginId)
continue;
items.push({
id: it.id || "",
type: it.type || "app",
name: it.name || "",
subtitle: it.subtitle || "",
icon: it.icon || "",
iconType: it.iconType || "image",
iconFull: it.iconFull || "",
section: it.section || "",
source: it.source || "",
data: {
id: it.id
},
actions: _actionsFromDesktopEntry(it.id),
primaryAction: it.type === "app" ? {
name: I18n.tr("Launch"),
icon: "open_in_new",
action: "launch"
} : null,
_diskCached: true,
_hName: "",
_hSub: "",
_hRich: false,
_preScored: undefined
});
}
if (items.length > 0)
sectionsData.push(_diskCacheSection(s, items));
}
if (!browseSectionSeen && browseItems.length > 0) {
var browseDef = _diskCacheSectionDef("browse_plugins");
if (browseDef)
sectionsData.push(_diskCacheSection(browseDef, browseItems));
}
if (sectionsData.length === 0)
return null;
sectionsData.sort(function (a, b) {
return a.priority - b.priority;
});
return sectionsData;
}
function updateSelectedItem() {
if (selectedFlatIndex >= 0 && selectedFlatIndex < flatModel.length) {
var entry = flatModel[selectedFlatIndex];
selectedItem = entry.isHeader ? null : entry.item;
} else {
selectedItem = null;
}
}
function _applyHighlights(sectionsData, query) {
if (!query || query.length === 0) {
for (var i = 0; i < sectionsData.length; i++) {
var items = sectionsData[i].items;
for (var j = 0; j < items.length; j++) {
var item = items[j];
item._hName = item.name || "";
item._hSub = item.subtitle || "";
item._hRich = false;
}
}
return;
}
var lowerQuery = query.toLowerCase();
for (var i = 0; i < sectionsData.length; i++) {
var items = sectionsData[i].items;
for (var j = 0; j < items.length; j++) {
var item = items[j];
item._hName = _highlightField(item.name || "", lowerQuery, query.length);
item._hSub = _highlightField(item.subtitle || "", lowerQuery, query.length);
item._hRich = true;
}
}
}
function _highlightField(text, lowerQuery, queryLen) {
if (!text)
return "";
var idx = text.toLowerCase().indexOf(lowerQuery);
if (idx === -1)
return _escapeRichText(text);
var before = text.substring(0, idx);
var match = text.substring(idx, idx + queryLen);
var after = text.substring(idx + queryLen);
return _escapeRichText(before) + '<b>' + _escapeRichText(match) + '</b>' + _escapeRichText(after);
}
function _escapeRichText(text) {
return String(text).replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#039;");
}
function getCurrentSectionViewMode() {
if (selectedFlatIndex < 0 || selectedFlatIndex >= flatModel.length)
return "list";
var entry = flatModel[selectedFlatIndex];
if (!entry || entry.isHeader)
return "list";
return getSectionViewMode(entry.sectionId);
}
function getGridColumns(sectionId) {
return Nav.getGridColumns(getSectionViewMode(sectionId), gridColumns);
}
function _cancelPendingSelectionReset() {
_queryDrivenSearch = false;
_pluginPhaseForceFirst = false;
}
function selectNext() {
keyboardNavigationActive = true;
_cancelPendingSelectionReset();
var newIndex = forceLinearNavigation ? Nav.findNextNonHeaderIndex(flatModel, selectedFlatIndex + 1) : Nav.calculateNextIndex(flatModel, selectedFlatIndex, null, null, gridColumns, getSectionViewMode);
if (newIndex === -1)
newIndex = selectedFlatIndex;
if (newIndex !== selectedFlatIndex) {
selectedFlatIndex = newIndex;
updateSelectedItem();
}
}
function selectPrevious() {
keyboardNavigationActive = true;
_cancelPendingSelectionReset();
var newIndex = forceLinearNavigation ? Nav.findPrevNonHeaderIndex(flatModel, selectedFlatIndex - 1) : Nav.calculatePrevIndex(flatModel, selectedFlatIndex, null, null, gridColumns, getSectionViewMode);
if (newIndex === -1)
newIndex = selectedFlatIndex;
if (newIndex !== selectedFlatIndex) {
selectedFlatIndex = newIndex;
updateSelectedItem();
}
}
function selectRight() {
keyboardNavigationActive = true;
_cancelPendingSelectionReset();
var newIndex = Nav.calculateRightIndex(flatModel, selectedFlatIndex, getSectionViewMode);
if (newIndex !== selectedFlatIndex) {
selectedFlatIndex = newIndex;
updateSelectedItem();
}
}
function selectLeft() {
keyboardNavigationActive = true;
_cancelPendingSelectionReset();
var newIndex = Nav.calculateLeftIndex(flatModel, selectedFlatIndex, getSectionViewMode);
if (newIndex !== selectedFlatIndex) {
selectedFlatIndex = newIndex;
updateSelectedItem();
}
}
function selectNextSection() {
keyboardNavigationActive = true;
_cancelPendingSelectionReset();
var newIndex = Nav.calculateNextSectionIndex(flatModel, selectedFlatIndex);
if (newIndex !== selectedFlatIndex) {
selectedFlatIndex = newIndex;
updateSelectedItem();
}
}
function selectPreviousSection() {
keyboardNavigationActive = true;
_cancelPendingSelectionReset();
var newIndex = Nav.calculatePrevSectionIndex(flatModel, selectedFlatIndex);
if (newIndex !== selectedFlatIndex) {
selectedFlatIndex = newIndex;
updateSelectedItem();
}
}
function selectPageDown(visibleItems) {
keyboardNavigationActive = true;
_cancelPendingSelectionReset();
var newIndex = Nav.calculatePageDownIndex(flatModel, selectedFlatIndex, visibleItems);
if (newIndex !== selectedFlatIndex) {
selectedFlatIndex = newIndex;
updateSelectedItem();
}
}
function selectPageUp(visibleItems) {
keyboardNavigationActive = true;
_cancelPendingSelectionReset();
var newIndex = Nav.calculatePageUpIndex(flatModel, selectedFlatIndex, visibleItems);
if (newIndex !== selectedFlatIndex) {
selectedFlatIndex = newIndex;
updateSelectedItem();
}
}
function selectIndex(index) {
keyboardNavigationActive = false;
if (index >= 0 && index < flatModel.length && !flatModel[index].isHeader) {
selectedFlatIndex = index;
updateSelectedItem();
}
}
function toggleSection(sectionId) {
_clearModeCache();
var newCollapsed = Object.assign({}, collapsedSections);
var currentState = newCollapsed[sectionId];
if (currentState === undefined) {
for (var i = 0; i < sections.length; i++) {
if (sections[i].id === sectionId) {
currentState = sections[i].collapsed || false;
break;
}
}
}
newCollapsed[sectionId] = !currentState;
collapsedSections = newCollapsed;
var newSections = sections.slice();
for (var i = 0; i < newSections.length; i++) {
if (newSections[i].id === sectionId) {
newSections[i] = Object.assign({}, newSections[i], {
collapsed: newCollapsed[sectionId]
});
}
}
flatModel = Scorer.flattenSections(newSections);
sections = newSections;
if (selectedFlatIndex >= flatModel.length) {
selectedFlatIndex = getFirstItemIndex();
}
updateSelectedItem();
if (!newCollapsed[sectionId])
sectionExpanded(sectionId);
}
function executeSelected() {
if (_searchPending) {
_searchPending = false;
searchDebounce.stop();
performSearch();
}
if (!selectedItem)
return;
executeItem(selectedItem, true);
}
function executeItem(item, isKeyboard = false) {
if (!item)
return;
SessionData.addLauncherHistory(searchQuery, explicitQuerySession);
if (item.type === "plugin_browse") {
var browsePluginId = item.data?.pluginId;
if (!browsePluginId)
return;
var browseTrigger = item.data.isBuiltIn ? AppSearchService.getBuiltInPluginTrigger(browsePluginId) : PluginService.getPluginTrigger(browsePluginId);
if (browseTrigger && browseTrigger.length > 0) {
searchQueryRequested(browseTrigger);
} else {
setMode("plugins", false, undefined, true);
pluginFilter = browsePluginId;
performSearch();
}
return;
}
switch (item.type) {
case "app":
if (item.isCore) {
AppSearchService.executeCoreApp(item.data);
} else if (item.data?.isAction) {
launchAppAction(item.data);
} else {
launchApp(item.data);
}
break;
case "plugin":
if (item.isBuiltInLauncher) {
AppSearchService.executeBuiltInLauncherItem(item.data);
} else {
AppSearchService.executePluginItem(item.data, item.pluginId);
}
break;
case "setting":
AppSearchService.executeBuiltInLauncherItem(item.data);
break;
case "clipboard":
var shouldPaste = isKeyboard ? SettingsData.clipboardEnterToPaste : SettingsData.clipboardClickToPaste;
if (shouldPaste) {
ClipboardService.pasteEntry(item.data, function () {
root.itemExecuted();
});
} else {
ClipboardService.copyEntry(item.data, function () {
root.itemExecuted();
});
}
return;
case "file":
openFile(item.data?.path);
break;
default:
return;
}
itemExecuted();
}
function executeAction(item, action) {
if (!item || !action)
return;
switch (action.action) {
case "launch":
executeItem(item);
break;
case "open":
openFile(item.data.path);
break;
case "open_folder":
openFolder(item.data.path);
break;
case "copy_path":
copyToClipboard(item.data.path);
break;
case "open_terminal":
openTerminal(item.data.path);
break;
case "copy":
copyToClipboard(item.name);
break;
case "execute":
executeItem(item);
break;
case "clipboard_copy":
ClipboardService.copyEntry(item.data, function () {
root.itemExecuted();
});
return;
case "clipboard_paste":
ClipboardService.pasteEntry(item.data, function () {
root.itemExecuted();
});
return;
case "launch_dgpu":
if (item.type === "app" && item.data) {
launchAppWithNvidia(item.data);
}
break;
case "toggle_all_visibility":
if (item.type === "plugin_browse" && item.data?.pluginId) {
var pluginId = item.data.pluginId;
var currentState = SettingsData.getPluginAllowWithoutTrigger(pluginId);
SettingsData.setPluginAllowWithoutTrigger(pluginId, !currentState);
performSearch();
}
return;
default:
if (item.type === "app" && action.actionData) {
launchAppAction({
parentApp: item.data,
actionData: action.actionData
});
}
}
itemExecuted();
}
function _resolveDesktopEntry(app) {
if (!app)
return null;
if (app.command)
return app;
var id = app.id || app.execString || app.exec || "";
if (!id)
return null;
return DesktopEntries.heuristicLookup(id);
}
function launchApp(app) {
var entry = _resolveDesktopEntry(app);
if (!entry)
return;
SessionService.launchDesktopEntry(entry);
AppUsageHistoryData.addAppUsage(entry);
}
function launchAppWithNvidia(app) {
var entry = _resolveDesktopEntry(app);
if (!entry)
return;
SessionService.launchDesktopEntry(entry, true);
AppUsageHistoryData.addAppUsage(entry);
}
function launchAppAction(actionItem) {
if (!actionItem || !actionItem.actionData)
return;
var entry = _resolveDesktopEntry(actionItem.parentApp);
if (!entry)
return;
SessionService.launchDesktopAction(entry, actionItem.actionData);
AppUsageHistoryData.addAppUsage(entry);
}
function openFile(path) {
if (!path)
return;
Qt.openUrlExternally("file://" + path);
}
function openFolder(path) {
if (!path)
return;
var folder = path.substring(0, path.lastIndexOf("/"));
Qt.openUrlExternally("file://" + folder);
}
function openTerminal(path) {
if (!path)
return;
var terminal = SessionData.resolveTerminal() || "xterm";
Quickshell.execDetached({
command: [terminal],
workingDirectory: path
});
}
function copyToClipboard(text) {
if (!text)
return;
Quickshell.execDetached(["dms", "cl", "copy", text]);
}
}