1
0
mirror of https://github.com/AvengeMedia/DankMaterialShell.git synced 2026-01-24 21:42:51 -05:00

settings: add search

- because tabs arent loaded at runtime, we have to have a separate index
- Less ideal, but functional enough for now
This commit is contained in:
bbedward
2025-12-26 19:19:47 -05:00
parent d6fe7bea27
commit d9d6ab5776
30 changed files with 1142 additions and 47 deletions

View File

@@ -78,9 +78,7 @@ FloatingWindow {
closingModal();
} else {
Qt.callLater(() => {
if (contentFocusScope) {
contentFocusScope.forceActiveFocus();
}
sidebar.focusSearch();
});
}
}
@@ -141,19 +139,6 @@ FloatingWindow {
anchors.fill: parent
focus: true
Keys.onPressed: event => {
if (event.key === Qt.Key_Down || (event.key === Qt.Key_Tab && !event.modifiers)) {
sidebar.navigateNext();
event.accepted = true;
return;
}
if (event.key === Qt.Key_Up || event.key === Qt.Key_Backtab || (event.key === Qt.Key_Tab && event.modifiers & Qt.ShiftModifier)) {
sidebar.navigatePrevious();
event.accepted = true;
return;
}
}
Column {
anchors.fill: parent
spacing: 0

View File

@@ -1,6 +1,7 @@
pragma ComponentBehavior: Bound
import QtQuick
import Quickshell
import qs.Common
import qs.Modals.Settings
import qs.Services
@@ -16,6 +17,49 @@ Rectangle {
property var parentModal: null
property var expandedCategories: ({})
property var autoExpandedCategories: ({})
property bool searchActive: searchField.text.length > 0
property int searchSelectedIndex: 0
property int keyboardHighlightIndex: -1
function focusSearch() {
searchField.forceActiveFocus();
}
function highlightNext() {
var flatItems = getFlatNavigableItems();
if (flatItems.length === 0)
return;
var currentPos = flatItems.findIndex(item => item.tabIndex === keyboardHighlightIndex);
if (currentPos === -1) {
currentPos = flatItems.findIndex(item => item.tabIndex === currentIndex);
}
var nextPos = (currentPos + 1) % flatItems.length;
keyboardHighlightIndex = flatItems[nextPos].tabIndex;
autoExpandForTab(keyboardHighlightIndex);
}
function highlightPrevious() {
var flatItems = getFlatNavigableItems();
if (flatItems.length === 0)
return;
var currentPos = flatItems.findIndex(item => item.tabIndex === keyboardHighlightIndex);
if (currentPos === -1) {
currentPos = flatItems.findIndex(item => item.tabIndex === currentIndex);
}
var prevPos = (currentPos - 1 + flatItems.length) % flatItems.length;
keyboardHighlightIndex = flatItems[prevPos].tabIndex;
autoExpandForTab(keyboardHighlightIndex);
}
function selectHighlighted() {
if (keyboardHighlightIndex < 0)
return;
var oldIndex = currentIndex;
currentIndex = keyboardHighlightIndex;
autoCollapseIfNeeded(oldIndex, currentIndex);
keyboardHighlightIndex = -1;
Qt.callLater(searchField.forceActiveFocus);
}
readonly property var categoryStructure: [
{
@@ -437,6 +481,29 @@ Rectangle {
color: Theme.withAlpha(Theme.surfaceContainer, Theme.popupTransparency)
radius: Theme.cornerRadius
function selectSearchResult(result) {
if (!result)
return;
if (result.section) {
SettingsSearchService.navigateToSection(result.section);
}
var oldIndex = root.currentIndex;
root.currentIndex = result.tabIndex;
autoCollapseIfNeeded(oldIndex, result.tabIndex);
autoExpandForTab(result.tabIndex);
searchField.text = "";
SettingsSearchService.clear();
searchSelectedIndex = 0;
keyboardHighlightIndex = -1;
Qt.callLater(searchField.forceActiveFocus);
}
function navigateSearchResults(delta) {
if (SettingsSearchService.results.length === 0)
return;
searchSelectedIndex = Math.max(0, Math.min(searchSelectedIndex + delta, SettingsSearchService.results.length - 1));
}
DankFlickable {
anchors.fill: parent
clip: true
@@ -465,7 +532,198 @@ Rectangle {
Item {
width: parent.width - parent.leftPadding - parent.rightPadding
height: Theme.spacingM
height: Theme.spacingS
}
DankTextField {
id: searchField
width: parent.width - parent.leftPadding - parent.rightPadding
height: 40
placeholderText: I18n.tr("Search...")
backgroundColor: Theme.withAlpha(Theme.surfaceContainerHighest, Theme.popupTransparency)
normalBorderColor: Theme.outlineMedium
focusedBorderColor: Theme.primary
leftIconName: "search"
leftIconSize: Theme.iconSize - 4
showClearButton: text.length > 0
onTextChanged: {
SettingsSearchService.search(text);
root.searchSelectedIndex = 0;
}
keyForwardTargets: [keyHandler]
Item {
id: keyHandler
function navNext() {
if (root.searchActive) {
root.navigateSearchResults(1);
} else {
root.highlightNext();
}
}
function navPrev() {
if (root.searchActive) {
root.navigateSearchResults(-1);
} else {
root.highlightPrevious();
}
}
function navSelect() {
if (root.searchActive && SettingsSearchService.results.length > 0) {
root.selectSearchResult(SettingsSearchService.results[root.searchSelectedIndex]);
} else if (root.keyboardHighlightIndex >= 0) {
root.selectHighlighted();
}
}
Keys.onDownPressed: event => {
navNext();
event.accepted = true;
}
Keys.onUpPressed: event => {
navPrev();
event.accepted = true;
}
Keys.onTabPressed: event => {
navNext();
event.accepted = true;
}
Keys.onBacktabPressed: event => {
navPrev();
event.accepted = true;
}
Keys.onReturnPressed: event => {
navSelect();
event.accepted = true;
}
Keys.onEscapePressed: event => {
if (root.searchActive) {
searchField.text = "";
SettingsSearchService.clear();
} else {
root.keyboardHighlightIndex = -1;
}
event.accepted = true;
}
Keys.onPressed: event => {
if (event.key === Qt.Key_J) {
navNext();
event.accepted = true;
} else if (event.key === Qt.Key_K) {
navPrev();
event.accepted = true;
}
}
}
}
Column {
id: searchResultsColumn
width: parent.width - parent.leftPadding - parent.rightPadding
spacing: 2
visible: root.searchActive
Item {
width: parent.width
height: Theme.spacingS
}
Repeater {
model: ScriptModel {
values: SettingsSearchService.results
}
Rectangle {
id: resultDelegate
required property int index
required property var modelData
width: searchResultsColumn.width
height: resultContent.height + Theme.spacingM * 2
radius: Theme.cornerRadius
color: {
if (root.searchSelectedIndex === index)
return Theme.primary;
if (resultMouseArea.containsMouse)
return Theme.surfaceHover;
return "transparent";
}
Row {
id: resultContent
anchors.left: parent.left
anchors.leftMargin: Theme.spacingM
anchors.right: parent.right
anchors.rightMargin: Theme.spacingM
anchors.verticalCenter: parent.verticalCenter
spacing: Theme.spacingM
DankIcon {
name: resultDelegate.modelData.icon || "settings"
size: Theme.iconSize - 2
color: root.searchSelectedIndex === resultDelegate.index ? Theme.primaryText : Theme.surfaceText
anchors.verticalCenter: parent.verticalCenter
}
Column {
width: parent.width - Theme.iconSize - Theme.spacingM
anchors.verticalCenter: parent.verticalCenter
spacing: 2
StyledText {
text: resultDelegate.modelData.label
font.pixelSize: Theme.fontSizeMedium
font.weight: Font.Medium
color: root.searchSelectedIndex === resultDelegate.index ? Theme.primaryText : Theme.surfaceText
width: parent.width
wrapMode: Text.Wrap
}
StyledText {
text: resultDelegate.modelData.category
font.pixelSize: Theme.fontSizeSmall - 1
color: root.searchSelectedIndex === resultDelegate.index ? Theme.withAlpha(Theme.primaryText, 0.7) : Theme.surfaceVariantText
width: parent.width
wrapMode: Text.Wrap
}
}
}
MouseArea {
id: resultMouseArea
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: root.selectSearchResult(resultDelegate.modelData)
onContainsMouseChanged: {
if (containsMouse)
root.searchSelectedIndex = resultDelegate.index;
}
}
Behavior on color {
ColorAnimation {
duration: Theme.shortDuration
easing.type: Theme.standardEasing
}
}
}
}
StyledText {
width: parent.width
text: I18n.tr("No matches")
font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceVariantText
horizontalAlignment: Text.AlignHCenter
visible: searchField.text.length >= 2 && SettingsSearchService.results.length === 0
topPadding: Theme.spacingM
}
}
Item {
width: parent.width - parent.leftPadding - parent.rightPadding
height: Theme.spacingS
visible: !root.searchActive
}
Repeater {
@@ -477,7 +735,7 @@ Rectangle {
required property var modelData
width: parent.width - parent.leftPadding - parent.rightPadding
visible: root.isCategoryVisible(modelData)
visible: !root.searchActive && root.isCategoryVisible(modelData)
spacing: 2
Rectangle {
@@ -500,11 +758,16 @@ Rectangle {
height: 40
radius: Theme.cornerRadius
visible: categoryDelegate.modelData.separator !== true
readonly property bool hasTab: categoryDelegate.modelData.tabIndex !== undefined && !categoryDelegate.modelData.children
readonly property bool isActive: hasTab && root.currentIndex === categoryDelegate.modelData.tabIndex
readonly property bool isHighlighted: hasTab && root.keyboardHighlightIndex === categoryDelegate.modelData.tabIndex
color: {
var hasTab = categoryDelegate.modelData.tabIndex !== undefined && !categoryDelegate.modelData.children;
var isActive = hasTab && root.currentIndex === categoryDelegate.modelData.tabIndex;
if (isActive)
return Theme.primary;
if (isHighlighted)
return Theme.primaryHover;
if (categoryMouseArea.containsMouse)
return Theme.surfaceHover;
return "transparent";
@@ -521,28 +784,15 @@ Rectangle {
DankIcon {
name: categoryDelegate.modelData.icon || ""
size: Theme.iconSize - 2
color: {
var hasTab = categoryDelegate.modelData.tabIndex !== undefined && !categoryDelegate.modelData.children;
var isActive = hasTab && root.currentIndex === categoryDelegate.modelData.tabIndex;
return isActive ? Theme.primaryText : Theme.surfaceText;
}
color: categoryRow.isActive ? Theme.primaryText : Theme.surfaceText
anchors.verticalCenter: parent.verticalCenter
}
StyledText {
text: categoryDelegate.modelData.text || ""
font.pixelSize: Theme.fontSizeMedium
font.weight: {
var hasTab = categoryDelegate.modelData.tabIndex !== undefined && !categoryDelegate.modelData.children;
var isActive = hasTab && root.currentIndex === categoryDelegate.modelData.tabIndex;
var childActive = root.isChildActive(categoryDelegate.modelData);
return (isActive || childActive) ? Font.Medium : Font.Normal;
}
color: {
var hasTab = categoryDelegate.modelData.tabIndex !== undefined && !categoryDelegate.modelData.children;
var isActive = hasTab && root.currentIndex === categoryDelegate.modelData.tabIndex;
return isActive ? Theme.primaryText : Theme.surfaceText;
}
font.weight: (categoryRow.isActive || root.isChildActive(categoryDelegate.modelData)) ? Font.Medium : Font.Normal
color: categoryRow.isActive ? Theme.primaryText : Theme.surfaceText
anchors.verticalCenter: parent.verticalCenter
width: parent.width - Theme.iconSize - Theme.spacingM - (categoryDelegate.modelData.children ? expandIcon.width + Theme.spacingS : 0)
elide: Text.ElideRight
@@ -564,11 +814,13 @@ Rectangle {
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
root.keyboardHighlightIndex = -1;
if (categoryDelegate.modelData.children) {
root.toggleCategory(categoryDelegate.modelData.id);
} else if (categoryDelegate.modelData.tabIndex !== undefined) {
root.currentIndex = categoryDelegate.modelData.tabIndex;
}
Qt.callLater(searchField.forceActiveFocus);
}
}
@@ -595,14 +847,18 @@ Rectangle {
required property int index
required property var modelData
readonly property bool isActive: root.currentIndex === modelData.tabIndex
readonly property bool isHighlighted: root.keyboardHighlightIndex === modelData.tabIndex
width: childrenColumn.width
height: 36
radius: Theme.cornerRadius
visible: root.isItemVisible(modelData)
color: {
var isActive = root.currentIndex === modelData.tabIndex;
if (isActive)
return Theme.primary;
if (isHighlighted)
return Theme.primaryHover;
if (childMouseArea.containsMouse)
return Theme.surfaceHover;
return "transparent";
@@ -617,21 +873,15 @@ Rectangle {
DankIcon {
name: childDelegate.modelData.icon || ""
size: Theme.iconSize - 4
color: {
var isActive = root.currentIndex === childDelegate.modelData.tabIndex;
return isActive ? Theme.primaryText : Theme.surfaceVariantText;
}
color: childDelegate.isActive ? Theme.primaryText : Theme.surfaceVariantText
anchors.verticalCenter: parent.verticalCenter
}
StyledText {
text: childDelegate.modelData.text || ""
font.pixelSize: Theme.fontSizeSmall + 1
font.weight: root.currentIndex === childDelegate.modelData.tabIndex ? Font.Medium : Font.Normal
color: {
var isActive = root.currentIndex === childDelegate.modelData.tabIndex;
return isActive ? Theme.primaryText : Theme.surfaceText;
}
font.weight: childDelegate.isActive ? Font.Medium : Font.Normal
color: childDelegate.isActive ? Theme.primaryText : Theme.surfaceText
anchors.verticalCenter: parent.verticalCenter
}
}
@@ -642,7 +892,9 @@ Rectangle {
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
root.keyboardHighlightIndex = -1;
root.currentIndex = childDelegate.modelData.tabIndex;
Qt.callLater(searchField.forceActiveFocus);
}
}

View File

@@ -108,6 +108,7 @@ Item {
Column {
id: mainColumn
topPadding: 4
width: Math.min(550, parent.width - Theme.spacingL * 2)
anchors.horizontalCenter: parent.horizontalCenter

View File

@@ -200,6 +200,7 @@ Item {
Column {
id: mainColumn
topPadding: 4
width: Math.min(550, parent.width - Theme.spacingL * 2)
anchors.horizontalCenter: parent.horizontalCenter
spacing: Theme.spacingXL

View File

@@ -297,6 +297,7 @@ Item {
Column {
id: mainColumn
topPadding: 4
width: Math.min(550, parent.width - Theme.spacingL * 2)
anchors.horizontalCenter: parent.horizontalCenter
spacing: Theme.spacingXL
@@ -304,6 +305,7 @@ Item {
SettingsCard {
iconName: "dashboard"
title: I18n.tr("Bar Configurations")
settingKey: "barConfigurations"
RowLayout {
width: parent.width
@@ -491,6 +493,7 @@ Item {
SettingsCard {
iconName: "display_settings"
title: I18n.tr("Display Assignment")
settingKey: "barDisplay"
visible: selectedBarConfig?.enabled
StyledText {
@@ -594,6 +597,7 @@ Item {
SettingsCard {
iconName: "vertical_align_center"
title: I18n.tr("Position")
settingKey: "barPosition"
visible: selectedBarConfig?.enabled
Item {
@@ -654,6 +658,7 @@ Item {
SettingsCard {
iconName: "visibility_off"
title: I18n.tr("Visibility")
settingKey: "barVisibility"
visible: selectedBarConfig?.enabled
SettingsToggleRow {
@@ -855,6 +860,7 @@ Item {
SettingsCard {
iconName: "space_bar"
title: I18n.tr("Spacing")
settingKey: "barSpacing"
visible: selectedBarConfig?.enabled
SettingsSliderRow {
@@ -974,6 +980,7 @@ Item {
SettingsCard {
iconName: "rounded_corner"
title: I18n.tr("Corners & Background")
settingKey: "barCorners"
visible: selectedBarConfig?.enabled
SettingsToggleRow {
@@ -1224,6 +1231,7 @@ Item {
SettingsCard {
iconName: "opacity"
title: I18n.tr("Transparency")
settingKey: "barTransparency"
visible: selectedBarConfig?.enabled
SettingsSliderRow {

View File

@@ -35,6 +35,7 @@ Item {
Column {
id: mainColumn
topPadding: 4
width: Math.min(550, parent.width - Theme.spacingL * 2)
anchors.horizontalCenter: parent.horizontalCenter
spacing: Theme.spacingXL

View File

@@ -28,6 +28,7 @@ Item {
Column {
id: mainColumn
topPadding: 4
width: Math.min(550, parent.width - Theme.spacingL * 2)
anchors.horizontalCenter: parent.horizontalCenter

View File

@@ -123,6 +123,7 @@ Item {
Column {
id: mainColumn
topPadding: 4
width: Math.min(550, parent.width - Theme.spacingL * 2)
anchors.horizontalCenter: parent.horizontalCenter

View File

@@ -15,6 +15,7 @@ Item {
Column {
id: mainColumn
topPadding: 4
width: Math.min(550, parent.width - Theme.spacingL * 2)
anchors.horizontalCenter: parent.horizontalCenter
spacing: Theme.spacingXL
@@ -23,6 +24,7 @@ Item {
width: parent.width
iconName: "swap_vert"
title: I18n.tr("Dock Position")
settingKey: "dockPosition"
SettingsButtonGroupRow {
text: I18n.tr("Position")
@@ -66,6 +68,7 @@ Item {
width: parent.width
iconName: "dock_to_bottom"
title: I18n.tr("Dock Visibility")
settingKey: "dockVisibility"
SettingsToggleRow {
text: I18n.tr("Show Dock")
@@ -95,6 +98,7 @@ Item {
width: parent.width
iconName: "apps"
title: I18n.tr("Behavior")
settingKey: "dockBehavior"
SettingsToggleRow {
text: I18n.tr("Isolate Displays")
@@ -126,6 +130,7 @@ Item {
width: parent.width
iconName: "photo_size_select_large"
title: I18n.tr("Sizing")
settingKey: "dockSizing"
SettingsSliderRow {
text: I18n.tr("Icon Size")
@@ -141,6 +146,7 @@ Item {
width: parent.width
iconName: "space_bar"
title: I18n.tr("Spacing")
settingKey: "dockSpacing"
SettingsSliderRow {
text: I18n.tr("Padding")
@@ -174,6 +180,7 @@ Item {
width: parent.width
iconName: "opacity"
title: I18n.tr("Transparency")
settingKey: "dockTransparency"
SettingsSliderRow {
text: I18n.tr("Dock Transparency")
@@ -190,6 +197,7 @@ Item {
width: parent.width
iconName: "border_style"
title: I18n.tr("Border")
settingKey: "dockBorder"
SettingsToggleRow {
text: I18n.tr("Border")

View File

@@ -27,6 +27,7 @@ Item {
Column {
id: mainColumn
topPadding: 4
width: Math.min(550, parent.width - Theme.spacingL * 2)
anchors.horizontalCenter: parent.horizontalCenter

View File

@@ -25,6 +25,7 @@ Item {
Column {
id: mainColumn
topPadding: 4
width: Math.min(550, parent.width - Theme.spacingL * 2)
anchors.horizontalCenter: parent.horizontalCenter
spacing: Theme.spacingXL
@@ -33,6 +34,7 @@ Item {
width: parent.width
iconName: "apps"
title: I18n.tr("Launcher Button Logo")
settingKey: "launcherLogo"
StyledText {
width: parent.width
@@ -297,6 +299,7 @@ Item {
width: parent.width
iconName: "terminal"
title: I18n.tr("Launch Prefix")
settingKey: "launchPrefix"
StyledText {
width: parent.width
@@ -318,6 +321,7 @@ Item {
width: parent.width
iconName: "sort_by_alpha"
title: I18n.tr("Sorting & Layout")
settingKey: "launcherSorting"
SettingsToggleRow {
text: I18n.tr("Sort Alphabetically")
@@ -363,6 +367,7 @@ Item {
width: parent.width
iconName: "history"
title: I18n.tr("Recently Used Apps")
settingKey: "recentApps"
property var rankedAppsModel: {
var ranking = AppUsageHistoryData.appUsageRanking;

View File

@@ -16,6 +16,7 @@ Item {
Column {
id: mainColumn
topPadding: 4
width: Math.min(550, parent.width - Theme.spacingL * 2)
anchors.horizontalCenter: parent.horizontalCenter
spacing: Theme.spacingXL
@@ -24,6 +25,7 @@ Item {
width: parent.width
iconName: "lock"
title: I18n.tr("Lock Screen layout")
settingKey: "lockLayout"
SettingsToggleRow {
text: I18n.tr("Show Power Actions", "Enable power action icon on the lock screen window")
@@ -67,6 +69,7 @@ Item {
width: parent.width
iconName: "lock"
title: I18n.tr("Lock Screen behaviour")
settingKey: "lockBehavior"
StyledText {
text: I18n.tr("loginctl not available - lock integration requires DMS socket connection")
@@ -110,6 +113,7 @@ Item {
width: parent.width
iconName: "monitor"
title: I18n.tr("Lock Screen Display")
settingKey: "lockDisplay"
visible: Quickshell.screens.length > 1
StyledText {

View File

@@ -14,6 +14,7 @@ Item {
Column {
id: mainColumn
topPadding: 4
width: Math.min(550, parent.width - Theme.spacingL * 2)
anchors.horizontalCenter: parent.horizontalCenter
spacing: Theme.spacingXL
@@ -22,6 +23,7 @@ Item {
width: parent.width
iconName: "music_note"
title: I18n.tr("Media Player Settings")
settingKey: "mediaPlayer"
SettingsToggleRow {
text: I18n.tr("Wave Progress Bars")

View File

@@ -51,6 +51,7 @@ Item {
Column {
id: mainColumn
topPadding: 4
width: Math.min(600, parent.width - Theme.spacingL * 2)
anchors.horizontalCenter: parent.horizontalCenter

View File

@@ -81,6 +81,7 @@ Item {
Column {
id: mainColumn
topPadding: 4
width: Math.min(550, parent.width - Theme.spacingL * 2)
anchors.horizontalCenter: parent.horizontalCenter
spacing: Theme.spacingXL
@@ -89,6 +90,7 @@ Item {
width: parent.width
iconName: "notifications"
title: I18n.tr("Notification Popups")
settingKey: "notificationPopups"
SettingsDropdownRow {
text: I18n.tr("Popup Position")
@@ -144,6 +146,7 @@ Item {
width: parent.width
iconName: "notifications_off"
title: I18n.tr("Do Not Disturb")
settingKey: "doNotDisturb"
SettingsToggleRow {
text: I18n.tr("Enable Do Not Disturb")
@@ -157,6 +160,7 @@ Item {
width: parent.width
iconName: "timer"
title: I18n.tr("Notification Timeouts")
settingKey: "notificationTimeouts"
SettingsDropdownRow {
text: I18n.tr("Low Priority")

View File

@@ -14,6 +14,7 @@ Item {
Column {
id: mainColumn
topPadding: 4
width: Math.min(550, parent.width - Theme.spacingL * 2)
anchors.horizontalCenter: parent.horizontalCenter
spacing: Theme.spacingXL
@@ -22,6 +23,7 @@ Item {
width: parent.width
iconName: "tune"
title: I18n.tr("On-screen Displays")
settingKey: "osd"
SettingsDropdownRow {
text: I18n.tr("OSD Position")

View File

@@ -27,6 +27,7 @@ FocusScope {
Column {
id: mainColumn
topPadding: 4
width: Math.min(550, parent.width - Theme.spacingL * 2)
anchors.horizontalCenter: parent.horizontalCenter

View File

@@ -23,6 +23,7 @@ Item {
Column {
id: mainColumn
topPadding: 4
width: Math.min(550, parent.width - Theme.spacingL * 2)
anchors.horizontalCenter: parent.horizontalCenter
spacing: Theme.spacingXL
@@ -31,6 +32,7 @@ Item {
width: parent.width
iconName: "schedule"
title: I18n.tr("Idle Settings")
settingKey: "idleSettings"
Row {
width: parent.width
@@ -294,6 +296,7 @@ Item {
width: parent.width
iconName: "tune"
title: I18n.tr("Power Menu Customization")
settingKey: "powerMenu"
StyledText {
text: I18n.tr("Customize which actions appear in the power menu")
@@ -400,6 +403,7 @@ Item {
width: parent.width
iconName: "check_circle"
title: I18n.tr("Power Action Confirmation")
settingKey: "powerConfirmation"
SettingsToggleRow {
text: I18n.tr("Hold to Confirm Power Actions")
@@ -436,6 +440,7 @@ Item {
width: parent.width
iconName: "developer_mode"
title: I18n.tr("Custom Power Actions")
settingKey: "customPowerActions"
Repeater {
model: [
@@ -508,6 +513,7 @@ Item {
width: parent.width
iconName: "tune"
title: I18n.tr("Advanced")
settingKey: "powerAdvanced"
collapsible: true
expanded: false

View File

@@ -70,6 +70,7 @@ Item {
Column {
id: mainColumn
topPadding: 4
width: Math.min(600, parent.width - Theme.spacingL * 2)
anchors.horizontalCenter: parent.horizontalCenter

View File

@@ -14,6 +14,7 @@ Item {
Column {
id: mainColumn
topPadding: 4
width: Math.min(550, parent.width - Theme.spacingL * 2)
anchors.horizontalCenter: parent.horizontalCenter
spacing: Theme.spacingXL
@@ -22,6 +23,7 @@ Item {
width: parent.width
iconName: "apps"
title: I18n.tr("Running Apps Settings")
settingKey: "runningApps"
SettingsToggleRow {
text: I18n.tr("Running Apps Only In Current Workspace")

View File

@@ -15,6 +15,7 @@ Item {
Column {
id: mainColumn
topPadding: 4
width: Math.min(550, parent.width - Theme.spacingL * 2)
anchors.horizontalCenter: parent.horizontalCenter
@@ -24,6 +25,7 @@ Item {
tab: "sounds"
tags: ["sound", "audio", "notification", "volume"]
title: I18n.tr("System Sounds")
settingKey: "systemSounds"
iconName: SettingsData.soundsEnabled ? "volume_up" : "volume_off"
visible: AudioService.soundsAvailable

View File

@@ -14,6 +14,7 @@ Item {
Column {
id: mainColumn
topPadding: 4
width: Math.min(550, parent.width - Theme.spacingL * 2)
anchors.horizontalCenter: parent.horizontalCenter
spacing: Theme.spacingXL
@@ -22,6 +23,7 @@ Item {
width: parent.width
iconName: "refresh"
title: I18n.tr("System Updater")
settingKey: "systemUpdater"
SettingsToggleRow {
text: I18n.tr("Hide Updater Widget", "When updater widget is used, then hide it if no update found")

View File

@@ -45,6 +45,7 @@ Item {
Column {
id: mainColumn
topPadding: 4
width: Math.min(550, parent.width - Theme.spacingL * 2)
anchors.horizontalCenter: parent.horizontalCenter
@@ -54,6 +55,7 @@ Item {
tab: "theme"
tags: ["color", "palette", "theme", "appearance"]
title: I18n.tr("Theme Color")
settingKey: "themeColor"
iconName: "palette"
Column {
@@ -742,6 +744,7 @@ Item {
tab: "theme"
tags: ["light", "dark", "mode", "appearance"]
title: I18n.tr("Color Mode")
settingKey: "colorMode"
iconName: "contrast"
SettingsToggleRow {
@@ -762,6 +765,7 @@ Item {
tab: "theme"
tags: ["transparency", "opacity", "widget", "styling"]
title: I18n.tr("Widget Styling")
settingKey: "widgetStyling"
iconName: "opacity"
SettingsButtonGroupRow {
@@ -847,6 +851,7 @@ Item {
tab: "theme"
tags: ["niri", "layout", "gaps", "radius", "window"]
title: I18n.tr("Niri Layout Overrides")
settingKey: "niriLayout"
iconName: "crop_square"
visible: CompositorService.isNiri
@@ -917,6 +922,8 @@ Item {
SettingsCard {
tab: "theme"
tags: ["modal", "darken", "background", "overlay"]
title: I18n.tr("Modal Background")
settingKey: "modalBackground"
SettingsToggleRow {
tab: "theme"
@@ -933,6 +940,7 @@ Item {
tab: "theme"
tags: ["applications", "portal", "dark", "terminal"]
title: I18n.tr("Applications")
settingKey: "applications"
iconName: "terminal"
SettingsToggleRow {
@@ -960,6 +968,7 @@ Item {
tab: "theme"
tags: ["matugen", "templates", "theming"]
title: I18n.tr("Matugen Templates")
settingKey: "matugenTemplates"
iconName: "auto_awesome"
visible: Theme.matugenAvailable
@@ -1202,6 +1211,8 @@ Item {
SettingsCard {
tab: "theme"
tags: ["icon", "theme", "system"]
title: I18n.tr("Icon Theme")
settingKey: "iconTheme"
SettingsDropdownRow {
tab: "theme"
@@ -1227,6 +1238,7 @@ Item {
tab: "theme"
tags: ["system", "app", "theming", "gtk", "qt"]
title: I18n.tr("System App Theming")
settingKey: "systemAppTheming"
iconName: "extension"
visible: Theme.matugenAvailable

View File

@@ -17,6 +17,7 @@ Item {
Column {
id: mainColumn
topPadding: 4
width: Math.min(550, parent.width - Theme.spacingL * 2)
anchors.horizontalCenter: parent.horizontalCenter
@@ -26,6 +27,7 @@ Item {
tab: "time"
tags: ["time", "clock", "format", "24hour"]
title: I18n.tr("Time Format")
settingKey: "timeFormat"
iconName: "schedule"
SettingsToggleRow {
@@ -53,6 +55,7 @@ Item {
tab: "time"
tags: ["date", "format", "calendar"]
title: I18n.tr("Date Format")
settingKey: "dateFormat"
iconName: "calendar_today"
SettingsDropdownRow {
@@ -325,6 +328,7 @@ Item {
tab: "time"
tags: ["weather", "enable", "forecast"]
title: I18n.tr("Weather")
settingKey: "weather"
iconName: "cloud"
SettingsToggleRow {
@@ -546,6 +550,7 @@ Item {
tab: "time"
tags: ["weather", "current", "display"]
title: I18n.tr("Current Weather")
settingKey: "weather"
iconName: "visibility"
visible: SettingsData.weatherEnabled

View File

@@ -63,6 +63,7 @@ Item {
Column {
id: mainColumn
topPadding: 4
width: Math.min(550, parent.width - Theme.spacingL * 2)
anchors.horizontalCenter: parent.horizontalCenter
spacing: Theme.spacingXL
@@ -71,6 +72,7 @@ Item {
tab: "typography"
tags: ["font", "family", "text", "typography"]
title: I18n.tr("Typography")
settingKey: "typography"
iconName: "text_fields"
SettingsDropdownRow {
@@ -206,6 +208,7 @@ Item {
tab: "typography"
tags: ["animation", "speed", "motion", "duration"]
title: I18n.tr("Animation Speed")
settingKey: "animationSpeed"
iconName: "animation"
Item {

View File

@@ -28,6 +28,7 @@ Item {
Column {
id: mainColumn
topPadding: 4
width: Math.min(550, parent.width - Theme.spacingL * 2)
anchors.horizontalCenter: parent.horizontalCenter
@@ -37,6 +38,7 @@ Item {
tab: "wallpaper"
tags: ["background", "image", "picture"]
title: I18n.tr("Wallpaper")
settingKey: "wallpaper"
iconName: "wallpaper"
Row {
@@ -1186,8 +1188,9 @@ Item {
SettingsCard {
tab: "wallpaper"
tags: ["external", "disable", "swww", "hyprpaper", "swaybg"]
iconName: "wallpaper"
title: I18n.tr("External Wallpaper Management", "wallpaper settings external management")
settingKey: "disableWallpaper"
iconName: "wallpaper"
SettingsToggleRow {
tab: "wallpaper"
@@ -1215,6 +1218,8 @@ Item {
SettingsCard {
tab: "wallpaper"
tags: ["blur", "layer", "niri", "compositor"]
title: I18n.tr("Blur Wallpaper Layer")
settingKey: "blurWallpaper"
visible: CompositorService.isNiri
SettingsToggleRow {

View File

@@ -2,6 +2,7 @@ pragma ComponentBehavior: Bound
import QtQuick
import qs.Common
import qs.Services
import qs.Widgets
StyledRect {
@@ -12,6 +13,7 @@ StyledRect {
property string tab: ""
property var tags: []
property string settingKey: ""
property string title: ""
property string iconName: ""
@@ -20,6 +22,8 @@ StyledRect {
default property alias content: contentColumn.children
readonly property bool isHighlighted: settingKey !== "" && SettingsSearchService.highlightSection === settingKey
width: parent?.width ?? 0
height: {
var hasHeader = root.title !== "" || root.iconName !== "";
@@ -37,6 +41,32 @@ StyledRect {
readonly property bool hasHeader: root.title !== "" || root.iconName !== ""
property bool userToggledCollapse: false
function findParentFlickable() {
let p = root.parent;
while (p) {
if (p.hasOwnProperty("contentY") && p.hasOwnProperty("contentItem")) {
return p;
}
p = p.parent;
}
return null;
}
Component.onCompleted: {
if (settingKey) {
let flickable = findParentFlickable();
if (flickable) {
SettingsSearchService.registerCard(settingKey, root, flickable);
}
}
}
Component.onDestruction: {
if (settingKey) {
SettingsSearchService.unregisterCard(settingKey);
}
}
Behavior on height {
enabled: root.userToggledCollapse
NumberAnimation {
@@ -49,6 +79,26 @@ StyledRect {
}
}
Rectangle {
id: highlightBorder
anchors.fill: parent
anchors.margins: -2
radius: root.radius + 2
color: "transparent"
border.width: 2
border.color: Theme.primary
opacity: root.isHighlighted ? 1 : 0
visible: opacity > 0
z: 100
Behavior on opacity {
NumberAnimation {
duration: Theme.shortDuration
easing.type: Theme.standardEasing
}
}
}
Column {
id: mainColumn
anchors.fill: parent

View File

@@ -932,6 +932,7 @@ Item {
Column {
id: mainColumn
topPadding: 4
width: Math.min(550, parent.width - Theme.spacingL * 2)
anchors.horizontalCenter: parent.horizontalCenter
spacing: Theme.spacingXL

View File

@@ -15,6 +15,7 @@ Item {
Column {
id: mainColumn
topPadding: 4
width: Math.min(550, parent.width - Theme.spacingL * 2)
anchors.horizontalCenter: parent.horizontalCenter
spacing: Theme.spacingXL
@@ -23,6 +24,7 @@ Item {
width: parent.width
iconName: "view_module"
title: I18n.tr("Workspace Settings")
settingKey: "workspaceSettings"
SettingsToggleRow {
text: I18n.tr("Workspace Index Numbers")
@@ -114,6 +116,7 @@ Item {
width: parent.width
iconName: "label"
title: I18n.tr("Named Workspace Icons")
settingKey: "workspaceIcons"
visible: SettingsData.hasNamedWorkspaces()
StyledText {

View File

@@ -0,0 +1,725 @@
pragma Singleton
pragma ComponentBehavior: Bound
import QtQuick
import Quickshell
import qs.Common
Singleton {
id: root
property string query: ""
property var results: []
property string targetSection: ""
property string highlightSection: ""
property var registeredCards: ({})
function registerCard(settingKey, item, flickable) {
if (!settingKey)
return;
registeredCards[settingKey] = {
item: item,
flickable: flickable
};
if (targetSection === settingKey) {
scrollTimer.restart();
}
}
function unregisterCard(settingKey) {
if (!settingKey)
return;
let cards = registeredCards;
delete cards[settingKey];
registeredCards = cards;
}
function navigateToSection(section) {
targetSection = section;
if (registeredCards[section]) {
scrollTimer.restart();
}
}
function scrollToTarget() {
if (!targetSection)
return;
const entry = registeredCards[targetSection];
if (!entry || !entry.item || !entry.flickable)
return;
const flickable = entry.flickable;
const item = entry.item;
const contentItem = flickable.contentItem;
if (!contentItem)
return;
const mapped = item.mapToItem(contentItem, 0, 0);
const targetY = Math.max(0, mapped.y - 16);
flickable.contentY = targetY;
highlightSection = targetSection;
targetSection = "";
highlightTimer.restart();
}
function clearHighlight() {
highlightSection = "";
}
Timer {
id: scrollTimer
interval: 50
onTriggered: root.scrollToTarget()
}
Timer {
id: highlightTimer
interval: 2500
onTriggered: root.highlightSection = ""
}
readonly property var settingsIndex: [
{
label: I18n.tr("Wallpaper"),
keywords: ["background", "image", "picture", "desktop"],
tabIndex: 0,
icon: "wallpaper",
category: I18n.tr("Personalization"),
section: "wallpaper"
},
{
label: I18n.tr("Per-Mode Wallpapers"),
keywords: ["light", "dark", "mode", "theme"],
tabIndex: 0,
icon: "contrast",
category: I18n.tr("Personalization"),
section: "wallpaper"
},
{
label: I18n.tr("Blur on Overview"),
keywords: ["niri", "blur", "overview", "compositor"],
tabIndex: 0,
icon: "blur_on",
category: I18n.tr("Personalization"),
section: "blurWallpaper",
condition: () => CompositorService.isNiri
},
{
label: I18n.tr("Per-Monitor Wallpapers"),
keywords: ["multi-monitor", "display", "screen"],
tabIndex: 0,
icon: "monitor",
category: I18n.tr("Personalization"),
section: "wallpaper"
},
{
label: I18n.tr("Automatic Cycling"),
keywords: ["cycle", "rotate", "slideshow", "interval"],
tabIndex: 0,
icon: "slideshow",
category: I18n.tr("Personalization"),
section: "wallpaper"
},
{
label: I18n.tr("Transition Effect"),
keywords: ["animation", "change", "effect"],
tabIndex: 0,
icon: "animation",
category: I18n.tr("Personalization"),
section: "wallpaper"
},
{
label: I18n.tr("Disable Built-in Wallpapers"),
keywords: ["external", "swww", "hyprpaper", "swaybg"],
tabIndex: 0,
icon: "wallpaper",
category: I18n.tr("Personalization"),
section: "disableWallpaper"
},
{
label: I18n.tr("Duplicate Wallpaper with Blur"),
keywords: ["blur", "layer", "niri", "compositor"],
tabIndex: 0,
icon: "blur_on",
category: I18n.tr("Personalization"),
section: "blurWallpaper",
condition: () => CompositorService.isNiri
},
{
label: I18n.tr("Time Format"),
keywords: ["clock", "12h", "24h", "am", "pm"],
tabIndex: 1,
icon: "schedule",
category: I18n.tr("Time & Weather"),
section: "timeFormat"
},
{
label: I18n.tr("Date Format"),
keywords: ["calendar", "day", "month", "year"],
tabIndex: 1,
icon: "calendar_today",
category: I18n.tr("Time & Weather"),
section: "dateFormat"
},
{
label: I18n.tr("Weather"),
keywords: ["city", "temperature", "forecast", "location"],
tabIndex: 1,
icon: "thermostat",
category: I18n.tr("Time & Weather"),
section: "weather"
},
{
label: I18n.tr("Temperature Unit"),
keywords: ["celsius", "fahrenheit", "weather"],
tabIndex: 1,
icon: "thermostat",
category: I18n.tr("Time & Weather"),
section: "weather"
},
{
label: I18n.tr("Keyboard Shortcuts"),
keywords: ["keybinds", "hotkeys", "bindings"],
tabIndex: 2,
icon: "keyboard",
category: I18n.tr("Keyboard Shortcuts"),
section: "keybinds",
condition: () => KeybindsService.available
},
{
label: I18n.tr("Bar Configurations"),
keywords: ["panel", "multiple", "dankbar", "manage"],
tabIndex: 3,
icon: "dashboard",
category: I18n.tr("Dank Bar"),
section: "barConfigurations"
},
{
label: I18n.tr("Bar Position"),
keywords: ["top", "bottom", "left", "right", "panel"],
tabIndex: 3,
icon: "vertical_align_center",
category: I18n.tr("Dank Bar"),
section: "barPosition"
},
{
label: I18n.tr("Display Assignment"),
keywords: ["monitor", "screen", "display"],
tabIndex: 3,
icon: "display_settings",
category: I18n.tr("Dank Bar"),
section: "barDisplay"
},
{
label: I18n.tr("Bar Visibility"),
keywords: ["bar", "hide", "show", "auto-hide", "panel"],
tabIndex: 3,
icon: "visibility_off",
category: I18n.tr("Dank Bar"),
section: "barVisibility"
},
{
label: I18n.tr("Bar Spacing"),
keywords: ["gap", "margin", "padding", "spacing"],
tabIndex: 3,
icon: "space_bar",
category: I18n.tr("Dank Bar"),
section: "barSpacing"
},
{
label: I18n.tr("Corners & Background"),
keywords: ["rounded", "radius", "shape", "transparent"],
tabIndex: 3,
icon: "rounded_corner",
category: I18n.tr("Dank Bar"),
section: "barCorners"
},
{
label: I18n.tr("Bar Transparency"),
keywords: ["opacity", "alpha", "translucent"],
tabIndex: 3,
icon: "opacity",
category: I18n.tr("Dank Bar"),
section: "barTransparency"
},
{
label: I18n.tr("Workspaces"),
keywords: ["workspace", "label", "icon", "desktop"],
tabIndex: 4,
icon: "view_module",
category: I18n.tr("Workspaces"),
section: "workspaceSettings"
},
{
label: I18n.tr("Workspace Icons"),
keywords: ["workspace", "named", "icon"],
tabIndex: 4,
icon: "label",
category: I18n.tr("Workspaces"),
section: "workspaceIcons"
},
{
label: I18n.tr("Dock Position"),
keywords: ["taskbar", "bottom", "left", "right"],
tabIndex: 5,
icon: "dock_to_bottom",
category: I18n.tr("Dock"),
section: "dockPosition"
},
{
label: I18n.tr("Dock Visibility"),
keywords: ["hide", "show", "auto-hide", "taskbar"],
tabIndex: 5,
icon: "visibility_off",
category: I18n.tr("Dock"),
section: "dockVisibility"
},
{
label: I18n.tr("Dock Behavior"),
keywords: ["pinned", "apps", "click"],
tabIndex: 5,
icon: "apps",
category: I18n.tr("Dock"),
section: "dockBehavior"
},
{
label: I18n.tr("Dock Sizing"),
keywords: ["icon", "size", "scale"],
tabIndex: 5,
icon: "photo_size_select_large",
category: I18n.tr("Dock"),
section: "dockSizing"
},
{
label: I18n.tr("Dock Spacing"),
keywords: ["gap", "margin", "padding"],
tabIndex: 5,
icon: "space_bar",
category: I18n.tr("Dock"),
section: "dockSpacing"
},
{
label: I18n.tr("Dock Transparency"),
keywords: ["opacity", "alpha"],
tabIndex: 5,
icon: "opacity",
category: I18n.tr("Dock"),
section: "dockTransparency"
},
{
label: I18n.tr("Dock Border"),
keywords: ["outline", "stroke"],
tabIndex: 5,
icon: "border_style",
category: I18n.tr("Dock"),
section: "dockBorder"
},
{
label: I18n.tr("Network"),
keywords: ["wifi", "ethernet", "internet", "connection"],
tabIndex: 7,
icon: "wifi",
category: I18n.tr("Network"),
section: "network",
condition: () => !NetworkService.usingLegacy
},
{
label: I18n.tr("CUPS Print Server"),
keywords: ["cups", "print", "paper", "printer"],
tabIndex: 8,
icon: "print",
category: I18n.tr("System"),
section: "printers",
condition: () => CupsService.cupsAvailable
},
{
label: I18n.tr("Launcher Logo"),
keywords: ["app", "button", "icon", "drawer"],
tabIndex: 9,
icon: "grid_view",
category: I18n.tr("Launcher"),
section: "launcherLogo"
},
{
label: I18n.tr("Launch Prefix"),
keywords: ["terminal", "command", "prefix"],
tabIndex: 9,
icon: "terminal",
category: I18n.tr("Launcher"),
section: "launchPrefix"
},
{
label: I18n.tr("Sorting & Layout"),
keywords: ["grid", "list", "sort", "order"],
tabIndex: 9,
icon: "sort_by_alpha",
category: I18n.tr("Launcher"),
section: "launcherSorting"
},
{
label: I18n.tr("Recent Apps"),
keywords: ["history", "recent", "apps"],
tabIndex: 9,
icon: "history",
category: I18n.tr("Launcher"),
section: "recentApps"
},
{
label: I18n.tr("Theme Color"),
keywords: ["palette", "accent", "primary", "appearance"],
tabIndex: 10,
icon: "palette",
category: I18n.tr("Theme & Colors"),
section: "themeColor"
},
{
label: I18n.tr("Color Mode"),
keywords: ["light", "dark", "mode", "appearance"],
tabIndex: 10,
icon: "contrast",
category: I18n.tr("Theme & Colors"),
section: "colorMode"
},
{
label: I18n.tr("Widget Styling"),
keywords: ["colorful", "default", "appearance", "transparency"],
tabIndex: 10,
icon: "widgets",
category: I18n.tr("Theme & Colors"),
section: "widgetStyling"
},
{
label: I18n.tr("Niri Layout Overrides"),
keywords: ["gaps", "radius", "window", "niri"],
tabIndex: 10,
icon: "crop_square",
category: I18n.tr("Theme & Colors"),
section: "niriLayout",
condition: () => CompositorService.isNiri
},
{
label: I18n.tr("Modal Background"),
keywords: ["overlay", "dim", "popup", "modal", "darken"],
tabIndex: 10,
icon: "brightness_low",
category: I18n.tr("Theme & Colors"),
section: "modalBackground"
},
{
label: I18n.tr("Applications"),
keywords: ["dark", "system", "xdg", "portal", "terminal"],
tabIndex: 10,
icon: "apps",
category: I18n.tr("Theme & Colors"),
section: "applications"
},
{
label: I18n.tr("Matugen Templates"),
keywords: ["gtk", "qt", "firefox", "theming"],
tabIndex: 10,
icon: "auto_awesome",
category: I18n.tr("Theme & Colors"),
section: "matugenTemplates"
},
{
label: I18n.tr("Icon Theme"),
keywords: ["icons", "system", "adwaita"],
tabIndex: 10,
icon: "palette",
category: I18n.tr("Theme & Colors"),
section: "iconTheme"
},
{
label: I18n.tr("System App Theming"),
keywords: ["gtk", "qt", "application", "theming"],
tabIndex: 10,
icon: "settings",
category: I18n.tr("Theme & Colors"),
section: "systemAppTheming"
},
{
label: I18n.tr("Lock Screen Layout"),
keywords: ["lock", "power", "security", "layout"],
tabIndex: 11,
icon: "lock",
category: I18n.tr("Lock Screen"),
section: "lockLayout"
},
{
label: I18n.tr("Lock Screen Behaviour"),
keywords: ["dbus", "systemd", "lock", "behavior", "fingerprint"],
tabIndex: 11,
icon: "lock",
category: I18n.tr("Lock Screen"),
section: "lockBehavior"
},
{
label: I18n.tr("Lock Screen Display"),
keywords: ["display", "screen", "oled", "dpms", "monitor"],
tabIndex: 11,
icon: "monitor",
category: I18n.tr("Lock Screen"),
section: "lockDisplay"
},
{
label: I18n.tr("Plugins"),
keywords: ["extension", "addon", "widget"],
tabIndex: 12,
icon: "extension",
category: I18n.tr("Plugins"),
section: "plugins"
},
{
label: I18n.tr("About"),
keywords: ["version", "info", "credits"],
tabIndex: 13,
icon: "info",
category: I18n.tr("About"),
section: "about"
},
{
label: I18n.tr("Typography"),
keywords: ["font", "family", "text", "typeface"],
tabIndex: 14,
icon: "text_fields",
category: I18n.tr("Typography & Motion"),
section: "typography"
},
{
label: I18n.tr("Animation Speed"),
keywords: ["motion", "speed", "transition", "duration"],
tabIndex: 14,
icon: "animation",
category: I18n.tr("Typography & Motion"),
section: "animationSpeed"
},
{
label: I18n.tr("System Sounds"),
keywords: ["audio", "effects", "notification", "theme", "volume"],
tabIndex: 15,
icon: "volume_up",
category: I18n.tr("Sounds"),
section: "systemSounds",
condition: () => AudioService.soundsAvailable
},
{
label: I18n.tr("Media Player"),
keywords: ["mpris", "music", "controls", "style", "scroll"],
tabIndex: 16,
icon: "music_note",
category: I18n.tr("Media Player"),
section: "mediaPlayer"
},
{
label: I18n.tr("Notification Popups"),
keywords: ["toast", "alert", "message", "position"],
tabIndex: 17,
icon: "notifications",
category: I18n.tr("Notifications"),
section: "notificationPopups"
},
{
label: I18n.tr("Do Not Disturb"),
keywords: ["dnd", "quiet", "silent", "notification"],
tabIndex: 17,
icon: "notifications_off",
category: I18n.tr("Notifications"),
section: "doNotDisturb"
},
{
label: I18n.tr("Notification Timeouts"),
keywords: ["duration", "dismiss", "popup", "low", "normal", "critical"],
tabIndex: 17,
icon: "timer",
category: I18n.tr("Notifications"),
section: "notificationTimeouts"
},
{
label: I18n.tr("On-screen Displays"),
keywords: ["osd", "volume", "brightness", "indicator", "position"],
tabIndex: 18,
icon: "tune",
category: I18n.tr("On-screen Displays"),
section: "osd"
},
{
label: I18n.tr("Running Apps"),
keywords: ["taskbar", "window", "active", "style"],
tabIndex: 19,
icon: "apps",
category: I18n.tr("Running Apps"),
section: "runningApps",
condition: () => CompositorService.isNiri || CompositorService.isHyprland
},
{
label: I18n.tr("System Updater"),
keywords: ["package", "update", "upgrade", "widget"],
tabIndex: 20,
icon: "refresh",
category: I18n.tr("System Updater"),
section: "systemUpdater"
},
{
label: I18n.tr("Idle Settings"),
keywords: ["suspend", "hibernate", "idle", "timeout", "lock", "dpms"],
tabIndex: 21,
icon: "schedule",
category: I18n.tr("Power & Sleep"),
section: "idleSettings"
},
{
label: I18n.tr("Power Menu"),
keywords: ["shutdown", "reboot", "logout", "layout"],
tabIndex: 21,
icon: "power_settings_new",
category: I18n.tr("Power & Sleep"),
section: "powerMenu"
},
{
label: I18n.tr("Power Confirmation"),
keywords: ["hold", "confirm", "safety"],
tabIndex: 21,
icon: "check_circle",
category: I18n.tr("Power & Sleep"),
section: "powerConfirmation"
},
{
label: I18n.tr("Custom Power Actions"),
keywords: ["lock", "logout", "suspend", "script", "command"],
tabIndex: 21,
icon: "developer_mode",
category: I18n.tr("Power & Sleep"),
section: "customPowerActions"
},
{
label: I18n.tr("Power Advanced"),
keywords: ["battery", "charge", "limit", "inhibit", "caffeine"],
tabIndex: 21,
icon: "tune",
category: I18n.tr("Power & Sleep"),
section: "powerAdvanced"
},
{
label: I18n.tr("Bar Widgets"),
keywords: ["dankbar", "customize", "order", "left", "center", "right"],
tabIndex: 22,
icon: "widgets",
category: I18n.tr("Dank Bar"),
section: "widgets"
},
{
label: I18n.tr("Clipboard"),
keywords: ["copy", "paste", "cliphist", "history"],
tabIndex: 23,
icon: "content_paste",
category: I18n.tr("System"),
section: "clipboard",
condition: () => DMSService.isConnected && DMSService.apiVersion >= 23
},
{
label: I18n.tr("Monitor Configuration"),
keywords: ["display", "resolution", "refresh"],
tabIndex: 24,
icon: "display_settings",
category: I18n.tr("Displays"),
section: "displayConfig"
},
{
label: I18n.tr("Gamma Control"),
keywords: ["brightness", "color", "temperature", "night", "blue"],
tabIndex: 25,
icon: "brightness_6",
category: I18n.tr("Displays"),
section: "gammaControl"
},
{
label: I18n.tr("Display Widgets"),
keywords: ["monitor", "position", "screen"],
tabIndex: 26,
icon: "widgets",
category: I18n.tr("Displays"),
section: "displayWidgets"
},
{
label: I18n.tr("Desktop Widgets"),
keywords: ["clock", "monitor", "conky", "desktop"],
tabIndex: 27,
icon: "widgets",
category: I18n.tr("Desktop Widgets"),
section: "desktopWidgets"
}
]
function search(text) {
query = text;
if (!text || text.length < 2) {
results = [];
return;
}
const queryLower = text.toLowerCase().trim();
const queryWords = queryLower.split(/\s+/).filter(w => w.length > 0);
const scored = [];
for (const item of settingsIndex) {
if (item.condition && !item.condition())
continue;
const labelLower = item.label.toLowerCase();
const categoryLower = item.category.toLowerCase();
let score = 0;
if (labelLower === queryLower) {
score = 10000;
} else if (labelLower.startsWith(queryLower)) {
score = 5000;
} else if (labelLower.includes(queryLower)) {
score = 1000;
} else if (categoryLower.includes(queryLower)) {
score = 500;
}
if (score === 0) {
for (const keyword of item.keywords) {
if (keyword.startsWith(queryLower)) {
score = Math.max(score, 800);
break;
}
if (keyword.includes(queryLower)) {
score = Math.max(score, 400);
}
}
}
if (score === 0 && queryWords.length > 1) {
let allMatch = true;
for (const word of queryWords) {
const inLabel = labelLower.includes(word);
const inKeywords = item.keywords.some(k => k.includes(word));
const inCategory = categoryLower.includes(word);
if (!inLabel && !inKeywords && !inCategory) {
allMatch = false;
break;
}
}
if (allMatch)
score = 300;
}
if (score > 0) {
scored.push({
item: item,
score: score
});
}
}
scored.sort((a, b) => b.score - a.score);
results = scored.slice(0, 15).map(s => s.item);
}
function clear() {
query = "";
results = [];
}
}