1
0
mirror of https://github.com/AvengeMedia/DankMaterialShell.git synced 2026-06-08 12:13:31 -04:00
Files
DankMaterialShell/quickshell/Modals/DankLauncherV2/SpotlightResultsList.qml
T
purian23 fb9ec8e721 feat: (Launcher/Spotlight): Updated w/New Settings & QOL features
- New Spotlight toggle to show/hide chips, off by default
- Updated blur effects on all launcher inputs and footers
- Fixed previous queries resurfacing
- Upated Spotlight keyboard navigation
- Added functionality to show and shortcut to keybinds from the Launcher tab
2026-05-21 01:05:56 -04:00

188 lines
6.7 KiB
QML

pragma ComponentBehavior: Bound
import QtQuick
import Quickshell
import qs.Common
import qs.Services
import qs.Widgets
Item {
id: root
property var controller: null
property bool hasQuery: false
property var rows: []
readonly property real bottomInset: Theme.spacingS
signal itemRightClicked(int index, var item, real mouseX, real mouseY)
function resetScroll() {
mainListView.contentY = mainListView.originY;
}
function ensureVisible(flatIndex) {
if (!controller || flatIndex < 0)
return;
for (let i = 0; i < rows.length; i++) {
if ((rows[i]?.flatIndex ?? -1) === flatIndex) {
mainListView.positionViewAtIndex(i, ListView.Contain);
return;
}
}
}
function getSelectedItemPosition() {
const fallback = mapToItem(null, width / 2, Math.min(height / 2, 56));
if (!controller || controller.selectedFlatIndex < 0)
return fallback;
for (let i = 0; i < rows.length; i++) {
if ((rows[i]?.flatIndex ?? -1) === controller.selectedFlatIndex) {
const rowY = i * mainListView.rowHeight - mainListView.contentY + mainListView.originY;
return mapToItem(null, width / 2, Math.max(28, Math.min(height - 28, rowY + mainListView.rowHeight / 2)));
}
}
return fallback;
}
Connections {
target: root.controller
function onSelectedFlatIndexChanged() {
if (root.controller?.keyboardNavigationActive)
Qt.callLater(() => root.ensureVisible(root.controller.selectedFlatIndex));
}
}
DankListView {
id: mainListView
anchors.top: parent.top
anchors.left: parent.left
anchors.right: parent.right
anchors.bottom: parent.bottom
anchors.bottomMargin: root.bottomInset
clip: true
visible: root.rows.length > 0
readonly property int rowHeight: 64
model: ScriptModel {
values: root.rows
objectProp: "_rowId"
}
delegate: Item {
id: delegateRoot
required property var modelData
required property int index
width: mainListView.width
height: mainListView.rowHeight
SpotlightResultRow {
anchors.fill: parent
anchors.leftMargin: Theme.spacingS
anchors.rightMargin: Theme.spacingS
anchors.topMargin: 3
anchors.bottomMargin: 3
item: delegateRoot.modelData?.item ?? null
sectionTitle: delegateRoot.modelData?.sectionTitle ?? ""
sectionIcon: delegateRoot.modelData?.sectionIcon ?? ""
flatIndex: delegateRoot.modelData?.flatIndex ?? -1
controller: root.controller
isSelected: (delegateRoot.modelData?.flatIndex ?? -1) === root.controller?.selectedFlatIndex
onClicked: {
if (root.controller && delegateRoot.modelData?.item)
root.controller.executeItem(delegateRoot.modelData.item);
}
onRightClicked: (mouseX, mouseY) => {
root.itemRightClicked(delegateRoot.modelData?.flatIndex ?? -1, delegateRoot.modelData?.item ?? null, mouseX, mouseY);
}
}
}
}
Item {
anchors.top: parent.top
anchors.left: parent.left
anchors.right: parent.right
anchors.bottom: parent.bottom
anchors.bottomMargin: root.bottomInset
visible: root.hasQuery && root.rows.length === 0
Row {
anchors.centerIn: parent
spacing: Theme.spacingM
Rectangle {
width: 40
height: 40
radius: Theme.cornerRadius
anchors.verticalCenter: parent.verticalCenter
color: Theme.surfaceContainerHigh
DankIcon {
anchors.centerIn: parent
name: root.controller?.isSearching || root.controller?.isFileSearching ? "search" : statusIcon()
size: 22
color: Theme.surfaceVariantText
function statusIcon() {
const mode = root.controller?.searchMode ?? "all";
if (mode === "files")
return "folder_open";
if (mode === "plugins")
return "extension";
if (mode === "apps")
return "apps";
return "search_off";
}
}
}
Column {
anchors.verticalCenter: parent.verticalCenter
width: Math.min(420, root.width - 88)
spacing: 2
StyledText {
width: parent.width
text: statusTitle()
font.pixelSize: Theme.fontSizeMedium
font.weight: Font.Medium
color: Theme.surfaceText
elide: Text.ElideRight
function statusTitle() {
if (root.controller?.isSearching || root.controller?.isFileSearching)
return I18n.tr("Searching");
if ((root.controller?.searchMode ?? "") === "files" && !DSearchService.dsearchAvailable)
return I18n.tr("File search unavailable");
if ((root.controller?.searchMode ?? "") === "files" && (root.controller?.searchQuery?.length ?? 0) < 2)
return I18n.tr("Keep typing");
return I18n.tr("No results");
}
}
StyledText {
width: parent.width
text: statusSubtitle()
font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceVariantText
maximumLineCount: 2
wrapMode: Text.WordWrap
elide: Text.ElideRight
function statusSubtitle() {
if ((root.controller?.searchMode ?? "") === "files" && !DSearchService.dsearchAvailable)
return I18n.tr("Install dsearch to search files.");
if ((root.controller?.searchMode ?? "") === "files" && (root.controller?.searchQuery?.length ?? 0) < 2)
return I18n.tr("Type at least 2 characters to search files.");
return I18n.tr("Try a different search or switch filters.");
}
}
}
}
}
}