mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2025-12-06 05:25:41 -05:00
keyboard shortcuts: comprehensive keyboard shortcut management interface
- niri only for now - requires quickshell-git, hidden otherwise - Add, Edit, Delete keybinds - Large suite of pre-defined and custom actions - Works with niri 25.11+ include feature
This commit is contained in:
@@ -329,79 +329,79 @@ Item {
|
||||
|
||||
IpcHandler {
|
||||
function toggle(provider: string): string {
|
||||
if (!provider) {
|
||||
if (!provider)
|
||||
return "ERROR: No provider specified";
|
||||
}
|
||||
|
||||
KeybindsService.loadProvider(provider);
|
||||
KeybindsService.currentProvider = provider;
|
||||
KeybindsService.loadBinds();
|
||||
root.hyprKeybindsModalLoader.active = true;
|
||||
|
||||
if (root.hyprKeybindsModalLoader.item) {
|
||||
if (root.hyprKeybindsModalLoader.item.shouldBeVisible) {
|
||||
root.hyprKeybindsModalLoader.item.close();
|
||||
} else {
|
||||
root.hyprKeybindsModalLoader.item.open();
|
||||
}
|
||||
return `KEYBINDS_TOGGLE_SUCCESS: ${provider}`;
|
||||
if (!root.hyprKeybindsModalLoader.item)
|
||||
return `KEYBINDS_TOGGLE_FAILED: ${provider}`;
|
||||
|
||||
if (root.hyprKeybindsModalLoader.item.shouldBeVisible) {
|
||||
root.hyprKeybindsModalLoader.item.close();
|
||||
} else {
|
||||
root.hyprKeybindsModalLoader.item.open();
|
||||
}
|
||||
return `KEYBINDS_TOGGLE_FAILED: ${provider}`;
|
||||
return `KEYBINDS_TOGGLE_SUCCESS: ${provider}`;
|
||||
}
|
||||
|
||||
function toggleWithPath(provider: string, path: string): string {
|
||||
if (!provider) {
|
||||
if (!provider)
|
||||
return "ERROR: No provider specified";
|
||||
}
|
||||
|
||||
KeybindsService.loadProviderWithPath(provider, path);
|
||||
KeybindsService.currentProvider = provider;
|
||||
KeybindsService.loadBinds();
|
||||
root.hyprKeybindsModalLoader.active = true;
|
||||
|
||||
if (root.hyprKeybindsModalLoader.item) {
|
||||
if (root.hyprKeybindsModalLoader.item.shouldBeVisible) {
|
||||
root.hyprKeybindsModalLoader.item.close();
|
||||
} else {
|
||||
root.hyprKeybindsModalLoader.item.open();
|
||||
}
|
||||
return `KEYBINDS_TOGGLE_SUCCESS: ${provider} (${path})`;
|
||||
if (!root.hyprKeybindsModalLoader.item)
|
||||
return `KEYBINDS_TOGGLE_FAILED: ${provider}`;
|
||||
|
||||
if (root.hyprKeybindsModalLoader.item.shouldBeVisible) {
|
||||
root.hyprKeybindsModalLoader.item.close();
|
||||
} else {
|
||||
root.hyprKeybindsModalLoader.item.open();
|
||||
}
|
||||
return `KEYBINDS_TOGGLE_FAILED: ${provider}`;
|
||||
return `KEYBINDS_TOGGLE_SUCCESS: ${provider} (${path})`;
|
||||
}
|
||||
|
||||
function open(provider: string): string {
|
||||
if (!provider) {
|
||||
if (!provider)
|
||||
return "ERROR: No provider specified";
|
||||
}
|
||||
|
||||
KeybindsService.loadProvider(provider);
|
||||
KeybindsService.currentProvider = provider;
|
||||
KeybindsService.loadBinds();
|
||||
root.hyprKeybindsModalLoader.active = true;
|
||||
|
||||
if (root.hyprKeybindsModalLoader.item) {
|
||||
root.hyprKeybindsModalLoader.item.open();
|
||||
return `KEYBINDS_OPEN_SUCCESS: ${provider}`;
|
||||
}
|
||||
return `KEYBINDS_OPEN_FAILED: ${provider}`;
|
||||
if (!root.hyprKeybindsModalLoader.item)
|
||||
return `KEYBINDS_OPEN_FAILED: ${provider}`;
|
||||
|
||||
root.hyprKeybindsModalLoader.item.open();
|
||||
return `KEYBINDS_OPEN_SUCCESS: ${provider}`;
|
||||
}
|
||||
|
||||
function openWithPath(provider: string, path: string): string {
|
||||
if (!provider) {
|
||||
if (!provider)
|
||||
return "ERROR: No provider specified";
|
||||
}
|
||||
|
||||
KeybindsService.loadProviderWithPath(provider, path);
|
||||
KeybindsService.currentProvider = provider;
|
||||
KeybindsService.loadBinds();
|
||||
root.hyprKeybindsModalLoader.active = true;
|
||||
|
||||
if (root.hyprKeybindsModalLoader.item) {
|
||||
root.hyprKeybindsModalLoader.item.open();
|
||||
return `KEYBINDS_OPEN_SUCCESS: ${provider} (${path})`;
|
||||
}
|
||||
return `KEYBINDS_OPEN_FAILED: ${provider}`;
|
||||
if (!root.hyprKeybindsModalLoader.item)
|
||||
return `KEYBINDS_OPEN_FAILED: ${provider}`;
|
||||
|
||||
root.hyprKeybindsModalLoader.item.open();
|
||||
return `KEYBINDS_OPEN_SUCCESS: ${provider} (${path})`;
|
||||
}
|
||||
|
||||
function close(): string {
|
||||
if (root.hyprKeybindsModalLoader.item) {
|
||||
root.hyprKeybindsModalLoader.item.close();
|
||||
return "KEYBINDS_CLOSE_SUCCESS";
|
||||
}
|
||||
return "KEYBINDS_CLOSE_FAILED";
|
||||
if (!root.hyprKeybindsModalLoader.item)
|
||||
return "KEYBINDS_CLOSE_FAILED";
|
||||
|
||||
root.hyprKeybindsModalLoader.item.close();
|
||||
return "KEYBINDS_CLOSE_SUCCESS";
|
||||
}
|
||||
|
||||
target: "keybinds"
|
||||
@@ -409,44 +409,48 @@ Item {
|
||||
|
||||
IpcHandler {
|
||||
function openBinds(): string {
|
||||
if (!CompositorService.isHyprland) {
|
||||
if (!CompositorService.isHyprland)
|
||||
return "HYPR_NOT_AVAILABLE";
|
||||
}
|
||||
KeybindsService.loadProvider("hyprland");
|
||||
|
||||
KeybindsService.currentProvider = "hyprland";
|
||||
KeybindsService.loadBinds();
|
||||
root.hyprKeybindsModalLoader.active = true;
|
||||
if (root.hyprKeybindsModalLoader.item) {
|
||||
root.hyprKeybindsModalLoader.item.open();
|
||||
return "HYPR_KEYBINDS_OPEN_SUCCESS";
|
||||
}
|
||||
return "HYPR_KEYBINDS_OPEN_FAILED";
|
||||
|
||||
if (!root.hyprKeybindsModalLoader.item)
|
||||
return "HYPR_KEYBINDS_OPEN_FAILED";
|
||||
|
||||
root.hyprKeybindsModalLoader.item.open();
|
||||
return "HYPR_KEYBINDS_OPEN_SUCCESS";
|
||||
}
|
||||
|
||||
function closeBinds(): string {
|
||||
if (!CompositorService.isHyprland) {
|
||||
if (!CompositorService.isHyprland)
|
||||
return "HYPR_NOT_AVAILABLE";
|
||||
}
|
||||
if (root.hyprKeybindsModalLoader.item) {
|
||||
root.hyprKeybindsModalLoader.item.close();
|
||||
return "HYPR_KEYBINDS_CLOSE_SUCCESS";
|
||||
}
|
||||
return "HYPR_KEYBINDS_CLOSE_FAILED";
|
||||
|
||||
if (!root.hyprKeybindsModalLoader.item)
|
||||
return "HYPR_KEYBINDS_CLOSE_FAILED";
|
||||
|
||||
root.hyprKeybindsModalLoader.item.close();
|
||||
return "HYPR_KEYBINDS_CLOSE_SUCCESS";
|
||||
}
|
||||
|
||||
function toggleBinds(): string {
|
||||
if (!CompositorService.isHyprland) {
|
||||
if (!CompositorService.isHyprland)
|
||||
return "HYPR_NOT_AVAILABLE";
|
||||
}
|
||||
KeybindsService.loadProvider("hyprland");
|
||||
|
||||
KeybindsService.currentProvider = "hyprland";
|
||||
KeybindsService.loadBinds();
|
||||
root.hyprKeybindsModalLoader.active = true;
|
||||
if (root.hyprKeybindsModalLoader.item) {
|
||||
if (root.hyprKeybindsModalLoader.item.shouldBeVisible) {
|
||||
root.hyprKeybindsModalLoader.item.close();
|
||||
} else {
|
||||
root.hyprKeybindsModalLoader.item.open();
|
||||
}
|
||||
return "HYPR_KEYBINDS_TOGGLE_SUCCESS";
|
||||
|
||||
if (!root.hyprKeybindsModalLoader.item)
|
||||
return "HYPR_KEYBINDS_TOGGLE_FAILED";
|
||||
|
||||
if (root.hyprKeybindsModalLoader.item.shouldBeVisible) {
|
||||
root.hyprKeybindsModalLoader.item.close();
|
||||
} else {
|
||||
root.hyprKeybindsModalLoader.item.open();
|
||||
}
|
||||
return "HYPR_KEYBINDS_TOGGLE_FAILED";
|
||||
return "HYPR_KEYBINDS_TOGGLE_SUCCESS";
|
||||
}
|
||||
|
||||
function toggleOverview(): string {
|
||||
@@ -490,60 +494,108 @@ Item {
|
||||
|
||||
function getBarConfig(selector: string, value: string): var {
|
||||
const barSelectors = ["id", "name", "index"];
|
||||
if (!barSelectors.includes(selector)) return { error: "BAR_INVALID_SELECTOR" };
|
||||
if (!barSelectors.includes(selector))
|
||||
return {
|
||||
error: "BAR_INVALID_SELECTOR"
|
||||
};
|
||||
const index = selector === "index" ? Number(value) : SettingsData.barConfigs.findIndex(bar => bar[selector] == value);
|
||||
const barConfig = SettingsData.barConfigs?.[index];
|
||||
if (!barConfig) return { error: "BAR_NOT_FOUND" };
|
||||
return { barConfig };
|
||||
if (!barConfig)
|
||||
return {
|
||||
error: "BAR_NOT_FOUND"
|
||||
};
|
||||
return {
|
||||
barConfig
|
||||
};
|
||||
}
|
||||
|
||||
IpcHandler {
|
||||
function reveal(selector: string, value: string): string {
|
||||
const { barConfig, error } = getBarConfig(selector, value);
|
||||
if (error) return error;
|
||||
SettingsData.updateBarConfig(barConfig.id, {visible: true});
|
||||
const {
|
||||
barConfig,
|
||||
error
|
||||
} = getBarConfig(selector, value);
|
||||
if (error)
|
||||
return error;
|
||||
SettingsData.updateBarConfig(barConfig.id, {
|
||||
visible: true
|
||||
});
|
||||
return "BAR_SHOW_SUCCESS";
|
||||
}
|
||||
|
||||
function hide(selector: string, value: string): string {
|
||||
const { barConfig, error } = getBarConfig(selector, value);
|
||||
if (error) return error;
|
||||
SettingsData.updateBarConfig(barConfig.id, {visible: false});
|
||||
const {
|
||||
barConfig,
|
||||
error
|
||||
} = getBarConfig(selector, value);
|
||||
if (error)
|
||||
return error;
|
||||
SettingsData.updateBarConfig(barConfig.id, {
|
||||
visible: false
|
||||
});
|
||||
return "BAR_HIDE_SUCCESS";
|
||||
}
|
||||
|
||||
function toggle(selector: string, value: string): string {
|
||||
const { barConfig, error } = getBarConfig(selector, value);
|
||||
if (error) return error;
|
||||
SettingsData.updateBarConfig(barConfig.id, {visible: !barConfig.visible});
|
||||
const {
|
||||
barConfig,
|
||||
error
|
||||
} = getBarConfig(selector, value);
|
||||
if (error)
|
||||
return error;
|
||||
SettingsData.updateBarConfig(barConfig.id, {
|
||||
visible: !barConfig.visible
|
||||
});
|
||||
return !barConfig.visible ? "BAR_SHOW_SUCCESS" : "BAR_HIDE_SUCCESS";
|
||||
}
|
||||
|
||||
function status(selector: string, value: string): string {
|
||||
const { barConfig, error } = getBarConfig(selector, value);
|
||||
if (error) return error;
|
||||
const {
|
||||
barConfig,
|
||||
error
|
||||
} = getBarConfig(selector, value);
|
||||
if (error)
|
||||
return error;
|
||||
return barConfig.visible ? "visible" : "hidden";
|
||||
}
|
||||
|
||||
function autoHide(selector: string, value: string): string {
|
||||
const { barConfig, error } = getBarConfig(selector, value);
|
||||
if (error) return error;
|
||||
SettingsData.updateBarConfig(barConfig.id, {autoHide: true});
|
||||
const {
|
||||
barConfig,
|
||||
error
|
||||
} = getBarConfig(selector, value);
|
||||
if (error)
|
||||
return error;
|
||||
SettingsData.updateBarConfig(barConfig.id, {
|
||||
autoHide: true
|
||||
});
|
||||
return "BAR_AUTO_HIDE_SUCCESS";
|
||||
}
|
||||
|
||||
function manualHide(selector: string, value: string): string {
|
||||
const { barConfig, error } = getBarConfig(selector, value);
|
||||
if (error) return error;
|
||||
SettingsData.updateBarConfig(barConfig.id, {autoHide: false});
|
||||
const {
|
||||
barConfig,
|
||||
error
|
||||
} = getBarConfig(selector, value);
|
||||
if (error)
|
||||
return error;
|
||||
SettingsData.updateBarConfig(barConfig.id, {
|
||||
autoHide: false
|
||||
});
|
||||
return "BAR_MANUAL_HIDE_SUCCESS";
|
||||
}
|
||||
|
||||
function toggleAutoHide(selector: string, value: string): string {
|
||||
const { barConfig, error } = getBarConfig(selector, value);
|
||||
if (error) return error;
|
||||
SettingsData.updateBarConfig(barConfig.id, {autoHide: !barConfig.autoHide});
|
||||
return barConfig.autoHide ? "BAR_MANUAL_HIDE_SUCCESS": "BAR_AUTO_HIDE_SUCCESS";
|
||||
const {
|
||||
barConfig,
|
||||
error
|
||||
} = getBarConfig(selector, value);
|
||||
if (error)
|
||||
return error;
|
||||
SettingsData.updateBarConfig(barConfig.id, {
|
||||
autoHide: !barConfig.autoHide
|
||||
});
|
||||
return barConfig.autoHide ? "BAR_MANUAL_HIDE_SUCCESS" : "BAR_AUTO_HIDE_SUCCESS";
|
||||
}
|
||||
|
||||
target: "bar"
|
||||
@@ -570,20 +622,20 @@ Item {
|
||||
}
|
||||
|
||||
function autoHide(): string {
|
||||
SettingsData.dockAutoHide = true
|
||||
SettingsData.saveSettings()
|
||||
SettingsData.dockAutoHide = true;
|
||||
SettingsData.saveSettings();
|
||||
return "BAR_AUTO_HIDE_SUCCESS";
|
||||
}
|
||||
|
||||
function manualHide(): string {
|
||||
SettingsData.dockAutoHide = false
|
||||
SettingsData.saveSettings()
|
||||
SettingsData.dockAutoHide = false;
|
||||
SettingsData.saveSettings();
|
||||
return "BAR_MANUAL_HIDE_SUCCESS";
|
||||
}
|
||||
|
||||
function toggleAutoHide(): string {
|
||||
SettingsData.dockAutoHide = !SettingsData.dockAutoHide
|
||||
SettingsData.saveSettings()
|
||||
SettingsData.dockAutoHide = !SettingsData.dockAutoHide;
|
||||
SettingsData.saveSettings();
|
||||
return SettingsData.dockAutoHide ? "BAR_AUTO_HIDE_SUCCESS" : "BAR_MANUAL_HIDE_SUCCESS";
|
||||
}
|
||||
|
||||
@@ -612,49 +664,51 @@ Item {
|
||||
}
|
||||
|
||||
function get(key: string): string {
|
||||
return JSON.stringify(SettingsData?.[key])
|
||||
return JSON.stringify(SettingsData?.[key]);
|
||||
}
|
||||
|
||||
function set(key: string, value: string): string {
|
||||
|
||||
if (!(key in SettingsData)) {
|
||||
console.warn("Cannot set property, not found:", key)
|
||||
return "SETTINGS_INVALID_KEY"
|
||||
console.warn("Cannot set property, not found:", key);
|
||||
return "SETTINGS_INVALID_KEY";
|
||||
}
|
||||
|
||||
const typeName = typeof SettingsData?.[key]
|
||||
const typeName = typeof SettingsData?.[key];
|
||||
|
||||
try {
|
||||
switch (typeName) {
|
||||
case "boolean":
|
||||
if (value === "true" || value === "false") value = (value === "true")
|
||||
else throw `${value} is not a Boolean`
|
||||
break
|
||||
if (value === "true" || value === "false")
|
||||
value = (value === "true");
|
||||
else
|
||||
throw `${value} is not a Boolean`;
|
||||
break;
|
||||
case "number":
|
||||
value = Number(value)
|
||||
if (isNaN(value)) throw `${value} is not a Number`
|
||||
break
|
||||
value = Number(value);
|
||||
if (isNaN(value))
|
||||
throw `${value} is not a Number`;
|
||||
break;
|
||||
case "string":
|
||||
value = String(value)
|
||||
break
|
||||
value = String(value);
|
||||
break;
|
||||
case "object":
|
||||
// NOTE: Parsing lists is messed up upstream and not sure if we want
|
||||
// to make sure objects are well structured or just let people set
|
||||
// whatever they want but risking messed up settings.
|
||||
// Objects & Arrays are disabled for now
|
||||
// https://github.com/quickshell-mirror/quickshell/pull/22
|
||||
throw "Setting Objects and Arrays not supported"
|
||||
throw "Setting Objects and Arrays not supported";
|
||||
default:
|
||||
throw "Unsupported type"
|
||||
throw "Unsupported type";
|
||||
}
|
||||
|
||||
console.warn("Setting:", key, value)
|
||||
SettingsData[key] = value
|
||||
SettingsData.saveSettings()
|
||||
return "SETTINGS_SET_SUCCESS"
|
||||
console.warn("Setting:", key, value);
|
||||
SettingsData[key] = value;
|
||||
SettingsData.saveSettings();
|
||||
return "SETTINGS_SET_SUCCESS";
|
||||
} catch (e) {
|
||||
console.warn("Failed to set property:", key, "error:", e)
|
||||
return "SETTINGS_SET_FAILURE"
|
||||
console.warn("Failed to set property:", key, "error:", e);
|
||||
return "SETTINGS_SET_FAILURE";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -97,14 +97,12 @@ DankModal {
|
||||
const bind = binds[i];
|
||||
if (bind.subcat) {
|
||||
hasSubcats = true;
|
||||
if (!subcats[bind.subcat]) {
|
||||
if (!subcats[bind.subcat])
|
||||
subcats[bind.subcat] = [];
|
||||
}
|
||||
subcats[bind.subcat].push(bind);
|
||||
} else {
|
||||
if (!subcats["_root"]) {
|
||||
if (!subcats["_root"])
|
||||
subcats["_root"] = [];
|
||||
}
|
||||
subcats["_root"].push(bind);
|
||||
}
|
||||
}
|
||||
@@ -121,12 +119,10 @@ DankModal {
|
||||
|
||||
function distributeCategories(cols) {
|
||||
const columns = [];
|
||||
for (let i = 0; i < cols; i++) {
|
||||
for (let i = 0; i < cols; i++)
|
||||
columns.push([]);
|
||||
}
|
||||
for (let i = 0; i < categoryKeys.length; i++) {
|
||||
for (let i = 0; i < categoryKeys.length; i++)
|
||||
columns[i % cols].push(categoryKeys[i]);
|
||||
}
|
||||
return columns;
|
||||
}
|
||||
|
||||
|
||||
@@ -57,13 +57,32 @@ FocusScope {
|
||||
}
|
||||
|
||||
Loader {
|
||||
id: topBarLoader
|
||||
id: keybindsLoader
|
||||
|
||||
anchors.fill: parent
|
||||
active: root.currentIndex === 2
|
||||
visible: active
|
||||
focus: active
|
||||
|
||||
sourceComponent: KeybindsTab {
|
||||
parentModal: root.parentModal
|
||||
}
|
||||
|
||||
onActiveChanged: {
|
||||
if (active && item) {
|
||||
Qt.callLater(() => item.forceActiveFocus());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loader {
|
||||
id: topBarLoader
|
||||
|
||||
anchors.fill: parent
|
||||
active: root.currentIndex === 3
|
||||
visible: active
|
||||
focus: active
|
||||
|
||||
sourceComponent: DankBarTab {
|
||||
parentModal: root.parentModal
|
||||
}
|
||||
@@ -79,7 +98,7 @@ FocusScope {
|
||||
id: widgetsLoader
|
||||
|
||||
anchors.fill: parent
|
||||
active: root.currentIndex === 3
|
||||
active: root.currentIndex === 4
|
||||
visible: active
|
||||
focus: active
|
||||
|
||||
@@ -96,7 +115,7 @@ FocusScope {
|
||||
id: dockLoader
|
||||
|
||||
anchors.fill: parent
|
||||
active: root.currentIndex === 4
|
||||
active: root.currentIndex === 5
|
||||
visible: active
|
||||
focus: active
|
||||
|
||||
@@ -115,7 +134,7 @@ FocusScope {
|
||||
id: displaysLoader
|
||||
|
||||
anchors.fill: parent
|
||||
active: root.currentIndex === 5
|
||||
active: root.currentIndex === 6
|
||||
visible: active
|
||||
focus: active
|
||||
|
||||
@@ -132,7 +151,7 @@ FocusScope {
|
||||
id: networkLoader
|
||||
|
||||
anchors.fill: parent
|
||||
active: root.currentIndex === 6
|
||||
active: root.currentIndex === 7
|
||||
visible: active
|
||||
focus: active
|
||||
|
||||
@@ -149,7 +168,7 @@ FocusScope {
|
||||
id: printerLoader
|
||||
|
||||
anchors.fill: parent
|
||||
active: root.currentIndex === 7
|
||||
active: root.currentIndex === 8
|
||||
visible: active
|
||||
focus: active
|
||||
|
||||
@@ -166,7 +185,7 @@ FocusScope {
|
||||
id: launcherLoader
|
||||
|
||||
anchors.fill: parent
|
||||
active: root.currentIndex === 8
|
||||
active: root.currentIndex === 9
|
||||
visible: active
|
||||
focus: active
|
||||
|
||||
@@ -183,7 +202,7 @@ FocusScope {
|
||||
id: themeColorsLoader
|
||||
|
||||
anchors.fill: parent
|
||||
active: root.currentIndex === 9
|
||||
active: root.currentIndex === 10
|
||||
visible: active
|
||||
focus: active
|
||||
|
||||
@@ -200,7 +219,7 @@ FocusScope {
|
||||
id: powerLoader
|
||||
|
||||
anchors.fill: parent
|
||||
active: root.currentIndex === 10
|
||||
active: root.currentIndex === 11
|
||||
visible: active
|
||||
focus: active
|
||||
|
||||
@@ -217,7 +236,7 @@ FocusScope {
|
||||
id: pluginsLoader
|
||||
|
||||
anchors.fill: parent
|
||||
active: root.currentIndex === 11
|
||||
active: root.currentIndex === 12
|
||||
visible: active
|
||||
focus: active
|
||||
|
||||
@@ -236,7 +255,7 @@ FocusScope {
|
||||
id: aboutLoader
|
||||
|
||||
anchors.fill: parent
|
||||
active: root.currentIndex === 12
|
||||
active: root.currentIndex === 13
|
||||
visible: active
|
||||
focus: active
|
||||
|
||||
|
||||
@@ -22,62 +22,68 @@ Rectangle {
|
||||
"icon": "schedule",
|
||||
"tabIndex": 1
|
||||
},
|
||||
{
|
||||
"text": I18n.tr("Keyboard Shortcuts"),
|
||||
"icon": "keyboard",
|
||||
"shortcutsOnly": true,
|
||||
"tabIndex": 2
|
||||
},
|
||||
{
|
||||
"text": I18n.tr("Dank Bar"),
|
||||
"icon": "toolbar",
|
||||
"tabIndex": 2
|
||||
"tabIndex": 3
|
||||
},
|
||||
{
|
||||
"text": I18n.tr("Widgets"),
|
||||
"icon": "widgets",
|
||||
"tabIndex": 3
|
||||
"tabIndex": 4
|
||||
},
|
||||
{
|
||||
"text": I18n.tr("Dock"),
|
||||
"icon": "dock_to_bottom",
|
||||
"tabIndex": 4
|
||||
"tabIndex": 5
|
||||
},
|
||||
{
|
||||
"text": I18n.tr("Displays"),
|
||||
"icon": "monitor",
|
||||
"tabIndex": 5
|
||||
"tabIndex": 6
|
||||
},
|
||||
{
|
||||
"text": I18n.tr("Network"),
|
||||
"icon": "wifi",
|
||||
"dmsOnly": true,
|
||||
"tabIndex": 6
|
||||
"tabIndex": 7
|
||||
},
|
||||
{
|
||||
"text": I18n.tr("Printers"),
|
||||
"icon": "print",
|
||||
"cupsOnly": true,
|
||||
"tabIndex": 7
|
||||
"tabIndex": 8
|
||||
},
|
||||
{
|
||||
"text": I18n.tr("Launcher"),
|
||||
"icon": "apps",
|
||||
"tabIndex": 8
|
||||
"tabIndex": 9
|
||||
},
|
||||
{
|
||||
"text": I18n.tr("Theme & Colors"),
|
||||
"icon": "palette",
|
||||
"tabIndex": 9
|
||||
"tabIndex": 10
|
||||
},
|
||||
{
|
||||
"text": I18n.tr("Power & Security"),
|
||||
"icon": "power",
|
||||
"tabIndex": 10
|
||||
"tabIndex": 11
|
||||
},
|
||||
{
|
||||
"text": I18n.tr("Plugins"),
|
||||
"icon": "extension",
|
||||
"tabIndex": 11
|
||||
"tabIndex": 12
|
||||
},
|
||||
{
|
||||
"text": I18n.tr("About"),
|
||||
"icon": "info",
|
||||
"tabIndex": 12
|
||||
"tabIndex": 13
|
||||
}
|
||||
]
|
||||
readonly property var sidebarItems: allSidebarItems.filter(item => {
|
||||
@@ -85,6 +91,8 @@ Rectangle {
|
||||
return false;
|
||||
if (item.cupsOnly && !CupsService.cupsAvailable)
|
||||
return false;
|
||||
if (item.shortcutsOnly && !KeybindsService.available)
|
||||
return false;
|
||||
return true;
|
||||
})
|
||||
|
||||
|
||||
548
quickshell/Modules/Settings/KeybindsTab.qml
Normal file
548
quickshell/Modules/Settings/KeybindsTab.qml
Normal file
@@ -0,0 +1,548 @@
|
||||
pragma ComponentBehavior: Bound
|
||||
|
||||
import QtQuick
|
||||
import Quickshell
|
||||
import qs.Common
|
||||
import qs.Services
|
||||
import qs.Widgets
|
||||
|
||||
Item {
|
||||
id: keybindsTab
|
||||
|
||||
property var parentModal: null
|
||||
property string selectedCategory: ""
|
||||
property string searchQuery: ""
|
||||
property string expandedKey: ""
|
||||
property bool showingNewBind: false
|
||||
|
||||
property int _lastDataVersion: -1
|
||||
property var _cachedCategories: []
|
||||
property var _filteredBinds: []
|
||||
|
||||
function _updateFiltered() {
|
||||
const allBinds = KeybindsService.getFlatBinds();
|
||||
if (!searchQuery && !selectedCategory) {
|
||||
_filteredBinds = allBinds;
|
||||
return;
|
||||
}
|
||||
|
||||
const q = searchQuery.toLowerCase();
|
||||
const isOverrideFilter = selectedCategory === "__overrides__";
|
||||
const result = [];
|
||||
|
||||
for (let i = 0; i < allBinds.length; i++) {
|
||||
const group = allBinds[i];
|
||||
if (q) {
|
||||
let keyMatch = false;
|
||||
for (let k = 0; k < group.keys.length; k++) {
|
||||
if (group.keys[k].key.toLowerCase().indexOf(q) !== -1) {
|
||||
keyMatch = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!keyMatch && group.desc.toLowerCase().indexOf(q) === -1 && group.action.toLowerCase().indexOf(q) === -1)
|
||||
continue;
|
||||
}
|
||||
if (isOverrideFilter) {
|
||||
let hasOverride = false;
|
||||
for (let k = 0; k < group.keys.length; k++) {
|
||||
if (group.keys[k].isOverride) {
|
||||
hasOverride = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!hasOverride)
|
||||
continue;
|
||||
} else if (selectedCategory && group.category !== selectedCategory) {
|
||||
continue;
|
||||
}
|
||||
result.push(group);
|
||||
}
|
||||
_filteredBinds = result;
|
||||
}
|
||||
|
||||
function _updateCategories() {
|
||||
_cachedCategories = ["__overrides__"].concat(KeybindsService.getCategories());
|
||||
}
|
||||
|
||||
function getCategoryLabel(cat) {
|
||||
if (cat === "__overrides__")
|
||||
return I18n.tr("Overrides");
|
||||
return cat;
|
||||
}
|
||||
|
||||
function toggleExpanded(action) {
|
||||
expandedKey = expandedKey === action ? "" : action;
|
||||
}
|
||||
|
||||
function startNewBind() {
|
||||
showingNewBind = true;
|
||||
expandedKey = "";
|
||||
}
|
||||
|
||||
function cancelNewBind() {
|
||||
showingNewBind = false;
|
||||
}
|
||||
|
||||
function saveNewBind(bindData) {
|
||||
KeybindsService.saveBind("", bindData);
|
||||
showingNewBind = false;
|
||||
}
|
||||
|
||||
function scrollToTop() {
|
||||
flickable.contentY = 0;
|
||||
}
|
||||
|
||||
Timer {
|
||||
id: searchDebounce
|
||||
interval: 150
|
||||
onTriggered: keybindsTab._updateFiltered()
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: KeybindsService
|
||||
function onBindsLoaded() {
|
||||
keybindsTab._lastDataVersion = KeybindsService._dataVersion;
|
||||
keybindsTab._updateCategories();
|
||||
keybindsTab._updateFiltered();
|
||||
}
|
||||
}
|
||||
|
||||
function _ensureNiriProvider() {
|
||||
if (!KeybindsService.available)
|
||||
return;
|
||||
const cachedProvider = KeybindsService.keybinds?.provider;
|
||||
if (cachedProvider !== "niri" || KeybindsService._dataVersion === 0) {
|
||||
KeybindsService.currentProvider = "niri";
|
||||
KeybindsService.loadBinds();
|
||||
return;
|
||||
}
|
||||
if (_lastDataVersion !== KeybindsService._dataVersion) {
|
||||
_lastDataVersion = KeybindsService._dataVersion;
|
||||
_updateCategories();
|
||||
_updateFiltered();
|
||||
}
|
||||
}
|
||||
|
||||
Component.onCompleted: _ensureNiriProvider()
|
||||
|
||||
onVisibleChanged: {
|
||||
if (!visible)
|
||||
return;
|
||||
Qt.callLater(scrollToTop);
|
||||
_ensureNiriProvider();
|
||||
}
|
||||
|
||||
DankFlickable {
|
||||
id: flickable
|
||||
anchors.fill: parent
|
||||
clip: true
|
||||
contentWidth: width
|
||||
contentHeight: contentColumn.implicitHeight
|
||||
|
||||
Column {
|
||||
id: contentColumn
|
||||
width: flickable.width
|
||||
spacing: Theme.spacingL
|
||||
topPadding: Theme.spacingXL
|
||||
bottomPadding: Theme.spacingXL
|
||||
|
||||
StyledRect {
|
||||
width: Math.min(650, parent.width - Theme.spacingL * 2)
|
||||
height: headerSection.implicitHeight + Theme.spacingL * 2
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
radius: Theme.cornerRadius
|
||||
color: Theme.withAlpha(Theme.surfaceContainerHigh, Theme.popupTransparency)
|
||||
border.width: 0
|
||||
|
||||
Column {
|
||||
id: headerSection
|
||||
anchors.fill: parent
|
||||
anchors.margins: Theme.spacingL
|
||||
spacing: Theme.spacingM
|
||||
|
||||
Row {
|
||||
width: parent.width
|
||||
spacing: Theme.spacingM
|
||||
|
||||
DankIcon {
|
||||
name: "keyboard"
|
||||
size: Theme.iconSize
|
||||
color: Theme.primary
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
|
||||
Column {
|
||||
width: parent.width - Theme.iconSize - Theme.spacingM * 2
|
||||
spacing: Theme.spacingXS
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
|
||||
StyledText {
|
||||
text: I18n.tr("Keyboard Shortcuts")
|
||||
font.pixelSize: Theme.fontSizeLarge
|
||||
font.weight: Font.Medium
|
||||
color: Theme.surfaceText
|
||||
}
|
||||
|
||||
StyledText {
|
||||
text: I18n.tr("Click any shortcut to edit. Changes save to dms/binds.kdl")
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
color: Theme.surfaceVariantText
|
||||
wrapMode: Text.WordWrap
|
||||
width: parent.width
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Row {
|
||||
width: parent.width
|
||||
spacing: Theme.spacingM
|
||||
|
||||
DankTextField {
|
||||
id: searchField
|
||||
width: parent.width - addButton.width - Theme.spacingM
|
||||
height: 44
|
||||
placeholderText: I18n.tr("Search keybinds...")
|
||||
leftIconName: "search"
|
||||
onTextChanged: {
|
||||
keybindsTab.searchQuery = text;
|
||||
searchDebounce.restart();
|
||||
}
|
||||
}
|
||||
|
||||
DankActionButton {
|
||||
id: addButton
|
||||
width: 44
|
||||
height: 44
|
||||
circular: false
|
||||
iconName: "add"
|
||||
iconSize: Theme.iconSize
|
||||
iconColor: Theme.primary
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
enabled: !keybindsTab.showingNewBind
|
||||
opacity: enabled ? 1 : 0.5
|
||||
onClicked: keybindsTab.startNewBind()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
StyledRect {
|
||||
width: Math.min(650, parent.width - Theme.spacingL * 2)
|
||||
height: warningSection.implicitHeight + Theme.spacingL * 2
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
radius: Theme.cornerRadius
|
||||
color: Theme.withAlpha(Theme.error, 0.15)
|
||||
border.color: Theme.withAlpha(Theme.error, 0.3)
|
||||
border.width: 1
|
||||
visible: !KeybindsService.dmsBindsIncluded && !KeybindsService.loading
|
||||
|
||||
Column {
|
||||
id: warningSection
|
||||
anchors.fill: parent
|
||||
anchors.margins: Theme.spacingL
|
||||
spacing: Theme.spacingM
|
||||
|
||||
Row {
|
||||
width: parent.width
|
||||
spacing: Theme.spacingM
|
||||
|
||||
DankIcon {
|
||||
name: "warning"
|
||||
size: Theme.iconSize
|
||||
color: Theme.error
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
|
||||
Column {
|
||||
width: parent.width - Theme.iconSize - 100 - Theme.spacingM * 2
|
||||
spacing: Theme.spacingXS
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
|
||||
StyledText {
|
||||
text: I18n.tr("Binds Include Missing")
|
||||
font.pixelSize: Theme.fontSizeMedium
|
||||
font.weight: Font.Medium
|
||||
color: Theme.error
|
||||
}
|
||||
|
||||
StyledText {
|
||||
text: I18n.tr("dms/binds.kdl is not included in config.kdl. Custom keybinds will not work until this is fixed.")
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
color: Theme.surfaceVariantText
|
||||
wrapMode: Text.WordWrap
|
||||
width: parent.width
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: fixButton
|
||||
width: fixButtonText.implicitWidth + Theme.spacingL * 2
|
||||
height: 36
|
||||
radius: Theme.cornerRadius
|
||||
color: KeybindsService.fixing ? Theme.withAlpha(Theme.error, 0.6) : Theme.error
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
|
||||
StyledText {
|
||||
id: fixButtonText
|
||||
text: KeybindsService.fixing ? I18n.tr("Fixing...") : I18n.tr("Fix Now")
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
font.weight: Font.Medium
|
||||
color: Theme.surface
|
||||
anchors.centerIn: parent
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
enabled: !KeybindsService.fixing
|
||||
onClicked: KeybindsService.fixDmsBindsInclude()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
StyledRect {
|
||||
width: Math.min(650, parent.width - Theme.spacingL * 2)
|
||||
height: categorySection.implicitHeight + Theme.spacingL * 2
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
radius: Theme.cornerRadius
|
||||
color: Theme.withAlpha(Theme.surfaceContainerHigh, Theme.popupTransparency)
|
||||
border.width: 0
|
||||
|
||||
Column {
|
||||
id: categorySection
|
||||
anchors.fill: parent
|
||||
anchors.margins: Theme.spacingL
|
||||
spacing: Theme.spacingM
|
||||
|
||||
Flow {
|
||||
width: parent.width
|
||||
spacing: Theme.spacingS
|
||||
|
||||
Rectangle {
|
||||
width: allChip.implicitWidth + Theme.spacingL
|
||||
height: 32
|
||||
radius: 16
|
||||
color: !keybindsTab.selectedCategory ? Theme.primary : Theme.surfaceContainerHighest
|
||||
|
||||
StyledText {
|
||||
id: allChip
|
||||
text: I18n.tr("All")
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
color: !keybindsTab.selectedCategory ? Theme.primaryText : Theme.surfaceVariantText
|
||||
anchors.centerIn: parent
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onClicked: {
|
||||
keybindsTab.selectedCategory = "";
|
||||
keybindsTab._updateFiltered();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Repeater {
|
||||
model: keybindsTab._cachedCategories
|
||||
|
||||
delegate: Rectangle {
|
||||
required property string modelData
|
||||
required property int index
|
||||
|
||||
width: catText.implicitWidth + Theme.spacingL
|
||||
height: 32
|
||||
radius: 16
|
||||
color: keybindsTab.selectedCategory === modelData ? Theme.primary : (modelData === "__overrides__" ? Theme.withAlpha(Theme.primary, 0.15) : Theme.surfaceContainerHighest)
|
||||
|
||||
StyledText {
|
||||
id: catText
|
||||
text: keybindsTab.getCategoryLabel(modelData)
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
color: keybindsTab.selectedCategory === modelData ? Theme.primaryText : (modelData === "__overrides__" ? Theme.primary : Theme.surfaceVariantText)
|
||||
anchors.centerIn: parent
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onClicked: {
|
||||
keybindsTab.selectedCategory = modelData;
|
||||
keybindsTab._updateFiltered();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
StyledRect {
|
||||
width: Math.min(650, parent.width - Theme.spacingL * 2)
|
||||
height: newBindSection.implicitHeight + Theme.spacingL * 2
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
radius: Theme.cornerRadius
|
||||
color: Theme.withAlpha(Theme.surfaceContainerHigh, Theme.popupTransparency)
|
||||
border.color: Theme.outlineVariant
|
||||
border.width: 1
|
||||
visible: keybindsTab.showingNewBind
|
||||
|
||||
Column {
|
||||
id: newBindSection
|
||||
anchors.fill: parent
|
||||
anchors.margins: Theme.spacingL
|
||||
spacing: Theme.spacingM
|
||||
|
||||
Row {
|
||||
width: parent.width
|
||||
spacing: Theme.spacingM
|
||||
|
||||
DankIcon {
|
||||
name: "add"
|
||||
size: Theme.iconSize
|
||||
color: Theme.surfaceText
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
|
||||
StyledText {
|
||||
text: I18n.tr("New Keybind")
|
||||
font.pixelSize: Theme.fontSizeMedium
|
||||
font.weight: Font.Medium
|
||||
color: Theme.surfaceText
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
}
|
||||
|
||||
KeybindItem {
|
||||
width: parent.width
|
||||
isNew: true
|
||||
isExpanded: true
|
||||
bindData: ({
|
||||
keys: [
|
||||
{
|
||||
key: "",
|
||||
source: "dms",
|
||||
isOverride: true
|
||||
}
|
||||
],
|
||||
action: "",
|
||||
desc: ""
|
||||
})
|
||||
panelWindow: keybindsTab.parentModal
|
||||
onSaveBind: (originalKey, newData) => keybindsTab.saveNewBind(newData)
|
||||
onCancelEdit: keybindsTab.cancelNewBind()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
StyledRect {
|
||||
width: Math.min(650, parent.width - Theme.spacingL * 2)
|
||||
height: bindsListHeader.implicitHeight + Theme.spacingL * 2
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
radius: Theme.cornerRadius
|
||||
color: Theme.withAlpha(Theme.surfaceContainerHigh, Theme.popupTransparency)
|
||||
border.width: 0
|
||||
|
||||
Column {
|
||||
id: bindsListHeader
|
||||
anchors.fill: parent
|
||||
anchors.margins: Theme.spacingL
|
||||
spacing: Theme.spacingM
|
||||
|
||||
Row {
|
||||
width: parent.width
|
||||
spacing: Theme.spacingM
|
||||
|
||||
DankIcon {
|
||||
name: "list"
|
||||
size: Theme.iconSize
|
||||
color: Theme.primary
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
|
||||
StyledText {
|
||||
text: KeybindsService.loading ? I18n.tr("Shortcuts") : I18n.tr("Shortcuts") + " (" + keybindsTab._filteredBinds.length + ")"
|
||||
font.pixelSize: Theme.fontSizeMedium
|
||||
font.weight: Font.Medium
|
||||
color: Theme.surfaceText
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
}
|
||||
|
||||
Row {
|
||||
width: parent.width
|
||||
spacing: Theme.spacingM
|
||||
visible: KeybindsService.loading
|
||||
|
||||
DankIcon {
|
||||
id: loadingIcon
|
||||
name: "sync"
|
||||
size: 20
|
||||
color: Theme.primary
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
|
||||
RotationAnimation on rotation {
|
||||
from: 0
|
||||
to: 360
|
||||
duration: 1000
|
||||
loops: Animation.Infinite
|
||||
running: KeybindsService.loading
|
||||
}
|
||||
}
|
||||
|
||||
StyledText {
|
||||
text: I18n.tr("Loading keybinds...")
|
||||
font.pixelSize: Theme.fontSizeMedium
|
||||
color: Theme.surfaceVariantText
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
}
|
||||
|
||||
StyledText {
|
||||
text: I18n.tr("No keybinds found")
|
||||
font.pixelSize: Theme.fontSizeMedium
|
||||
color: Theme.surfaceVariantText
|
||||
visible: !KeybindsService.loading && keybindsTab._filteredBinds.length === 0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Column {
|
||||
width: parent.width
|
||||
spacing: Theme.spacingXS
|
||||
|
||||
Repeater {
|
||||
model: ScriptModel {
|
||||
values: keybindsTab._filteredBinds
|
||||
objectProp: "action"
|
||||
}
|
||||
|
||||
delegate: Item {
|
||||
required property var modelData
|
||||
required property int index
|
||||
|
||||
width: parent.width
|
||||
height: bindItem.height
|
||||
|
||||
KeybindItem {
|
||||
id: bindItem
|
||||
width: Math.min(650, parent.width - Theme.spacingL * 2)
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
bindData: modelData
|
||||
isExpanded: keybindsTab.expandedKey === modelData.action
|
||||
panelWindow: keybindsTab.parentModal
|
||||
onToggleExpand: keybindsTab.toggleExpanded(modelData.action)
|
||||
onSaveBind: (originalKey, newData) => {
|
||||
KeybindsService.saveBind(originalKey, newData);
|
||||
keybindsTab.expandedKey = modelData.action;
|
||||
}
|
||||
onRemoveBind: key => KeybindsService.removeBind(key)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,8 +2,6 @@ import QtQuick
|
||||
import QtQuick.Effects
|
||||
import Quickshell
|
||||
import Quickshell.Wayland
|
||||
import Quickshell.Widgets
|
||||
import Quickshell.Io
|
||||
import qs.Common
|
||||
import qs.Services
|
||||
import qs.Widgets
|
||||
@@ -22,13 +20,13 @@ PanelWindow {
|
||||
target: ToastService
|
||||
function onToastVisibleChanged() {
|
||||
if (ToastService.toastVisible) {
|
||||
shouldBeVisible = true
|
||||
visible = true
|
||||
shouldBeVisible = true;
|
||||
visible = true;
|
||||
} else {
|
||||
// Freeze the width before starting exit animation
|
||||
frozenWidth = toast.width
|
||||
shouldBeVisible = false
|
||||
closeTimer.restart()
|
||||
frozenWidth = toast.width;
|
||||
shouldBeVisible = false;
|
||||
closeTimer.restart();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -38,7 +36,7 @@ PanelWindow {
|
||||
interval: Theme.mediumDuration + 50
|
||||
onTriggered: {
|
||||
if (!shouldBeVisible) {
|
||||
visible = false
|
||||
visible = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -65,7 +63,7 @@ PanelWindow {
|
||||
Connections {
|
||||
target: ToastService
|
||||
function onResetToastState() {
|
||||
toast.expanded = false
|
||||
toast.expanded = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -76,13 +74,13 @@ PanelWindow {
|
||||
color: {
|
||||
switch (ToastService.currentLevel) {
|
||||
case ToastService.levelError:
|
||||
return Theme.error
|
||||
return Theme.error;
|
||||
case ToastService.levelWarn:
|
||||
return Theme.warning
|
||||
return Theme.warning;
|
||||
case ToastService.levelInfo:
|
||||
return Theme.surfaceContainer
|
||||
return Theme.surfaceContainer;
|
||||
default:
|
||||
return Theme.surfaceContainer
|
||||
return Theme.surfaceContainer;
|
||||
}
|
||||
}
|
||||
radius: Theme.cornerRadius
|
||||
@@ -109,13 +107,13 @@ PanelWindow {
|
||||
name: {
|
||||
switch (ToastService.currentLevel) {
|
||||
case ToastService.levelError:
|
||||
return "error"
|
||||
return "error";
|
||||
case ToastService.levelWarn:
|
||||
return "warning"
|
||||
return "warning";
|
||||
case ToastService.levelInfo:
|
||||
return "info"
|
||||
return "info";
|
||||
default:
|
||||
return "info"
|
||||
return "info";
|
||||
}
|
||||
}
|
||||
size: Theme.iconSize
|
||||
@@ -123,9 +121,9 @@ PanelWindow {
|
||||
switch (ToastService.currentLevel) {
|
||||
case ToastService.levelError:
|
||||
case ToastService.levelWarn:
|
||||
return SessionData.isLightMode ? Theme.surfaceText : Theme.background
|
||||
return SessionData.isLightMode ? Theme.surfaceText : Theme.background;
|
||||
default:
|
||||
return Theme.surfaceText
|
||||
return Theme.surfaceText;
|
||||
}
|
||||
}
|
||||
anchors.left: parent.left
|
||||
@@ -140,9 +138,9 @@ PanelWindow {
|
||||
switch (ToastService.currentLevel) {
|
||||
case ToastService.levelError:
|
||||
case ToastService.levelWarn:
|
||||
return SessionData.isLightMode ? Theme.surfaceText : Theme.background
|
||||
return SessionData.isLightMode ? Theme.surfaceText : Theme.background;
|
||||
default:
|
||||
return Theme.surfaceText
|
||||
return Theme.surfaceText;
|
||||
}
|
||||
}
|
||||
font.weight: Font.Medium
|
||||
@@ -163,9 +161,9 @@ PanelWindow {
|
||||
switch (ToastService.currentLevel) {
|
||||
case ToastService.levelError:
|
||||
case ToastService.levelWarn:
|
||||
return SessionData.isLightMode ? Theme.surfaceText : Theme.background
|
||||
return SessionData.isLightMode ? Theme.surfaceText : Theme.background;
|
||||
default:
|
||||
return Theme.surfaceText
|
||||
return Theme.surfaceText;
|
||||
}
|
||||
}
|
||||
buttonSize: Theme.iconSize + 8
|
||||
@@ -175,11 +173,11 @@ PanelWindow {
|
||||
visible: ToastService.hasDetails
|
||||
|
||||
onClicked: {
|
||||
toast.expanded = !toast.expanded
|
||||
toast.expanded = !toast.expanded;
|
||||
if (toast.expanded) {
|
||||
ToastService.stopTimer()
|
||||
ToastService.stopTimer();
|
||||
} else {
|
||||
ToastService.restartTimer()
|
||||
ToastService.restartTimer();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -192,9 +190,9 @@ PanelWindow {
|
||||
switch (ToastService.currentLevel) {
|
||||
case ToastService.levelError:
|
||||
case ToastService.levelWarn:
|
||||
return SessionData.isLightMode ? Theme.surfaceText : Theme.background
|
||||
return SessionData.isLightMode ? Theme.surfaceText : Theme.background;
|
||||
default:
|
||||
return Theme.surfaceText
|
||||
return Theme.surfaceText;
|
||||
}
|
||||
}
|
||||
buttonSize: Theme.iconSize + 8
|
||||
@@ -203,7 +201,7 @@ PanelWindow {
|
||||
visible: ToastService.hasDetails || ToastService.currentLevel === ToastService.levelError
|
||||
|
||||
onClicked: {
|
||||
ToastService.hideToast()
|
||||
ToastService.hideToast();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -211,7 +209,7 @@ PanelWindow {
|
||||
Rectangle {
|
||||
width: parent.width
|
||||
height: detailsColumn.height + Theme.spacingS * 2
|
||||
color: Qt.rgba(0, 0, 0, 0.2)
|
||||
color: ToastService.currentDetails.length > 0 ? Qt.rgba(0, 0, 0, 0.2) : "transparent"
|
||||
radius: Theme.cornerRadius / 2
|
||||
visible: toast.expanded && ToastService.hasDetails
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
@@ -232,9 +230,9 @@ PanelWindow {
|
||||
switch (ToastService.currentLevel) {
|
||||
case ToastService.levelError:
|
||||
case ToastService.levelWarn:
|
||||
return SessionData.isLightMode ? Theme.surfaceText : Theme.background
|
||||
return SessionData.isLightMode ? Theme.surfaceText : Theme.background;
|
||||
default:
|
||||
return Theme.surfaceText
|
||||
return Theme.surfaceText;
|
||||
}
|
||||
}
|
||||
visible: ToastService.currentDetails.length > 0
|
||||
@@ -259,9 +257,9 @@ PanelWindow {
|
||||
switch (ToastService.currentLevel) {
|
||||
case ToastService.levelError:
|
||||
case ToastService.levelWarn:
|
||||
return SessionData.isLightMode ? Theme.surfaceText : Theme.background
|
||||
return SessionData.isLightMode ? Theme.surfaceText : Theme.background;
|
||||
default:
|
||||
return Theme.surfaceText
|
||||
return Theme.surfaceText;
|
||||
}
|
||||
}
|
||||
isMonospace: true
|
||||
@@ -281,9 +279,9 @@ PanelWindow {
|
||||
switch (ToastService.currentLevel) {
|
||||
case ToastService.levelError:
|
||||
case ToastService.levelWarn:
|
||||
return SessionData.isLightMode ? Theme.surfaceText : Theme.background
|
||||
return SessionData.isLightMode ? Theme.surfaceText : Theme.background;
|
||||
default:
|
||||
return Theme.surfaceText
|
||||
return Theme.surfaceText;
|
||||
}
|
||||
}
|
||||
buttonSize: Theme.iconSizeSmall + 8
|
||||
@@ -295,9 +293,9 @@ PanelWindow {
|
||||
property bool showTooltip: false
|
||||
|
||||
onClicked: {
|
||||
Quickshell.execDetached(["wl-copy", ToastService.currentCommand])
|
||||
showTooltip = true
|
||||
tooltipTimer.start()
|
||||
Quickshell.execDetached(["wl-copy", ToastService.currentCommand]);
|
||||
showTooltip = true;
|
||||
tooltipTimer.start();
|
||||
}
|
||||
|
||||
Timer {
|
||||
@@ -346,7 +344,6 @@ PanelWindow {
|
||||
shadowOpacity: 0.3
|
||||
}
|
||||
|
||||
|
||||
Behavior on opacity {
|
||||
NumberAnimation {
|
||||
duration: Theme.mediumDuration
|
||||
|
||||
@@ -422,7 +422,6 @@ Singleton {
|
||||
isLabwc = false;
|
||||
compositor = "niri";
|
||||
console.info("CompositorService: Detected Niri with socket:", niriSocket);
|
||||
NiriService.generateNiriBinds();
|
||||
NiriService.generateNiriBlurrule();
|
||||
}
|
||||
}, 0);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,59 +0,0 @@
|
||||
binds {
|
||||
Mod+Space hotkey-overlay-title="Application Launcher" {
|
||||
spawn "dms" "ipc" "call" "spotlight" "toggle";
|
||||
}
|
||||
|
||||
Mod+V hotkey-overlay-title="Clipboard Manager" {
|
||||
spawn "dms" "ipc" "call" "clipboard" "toggle";
|
||||
}
|
||||
|
||||
Mod+M hotkey-overlay-title="Task Manager" {
|
||||
spawn "dms" "ipc" "call" "processlist" "toggle";
|
||||
}
|
||||
|
||||
Mod+Comma hotkey-overlay-title="Settings" {
|
||||
spawn "dms" "ipc" "call" "settings" "toggle";
|
||||
}
|
||||
|
||||
Mod+N hotkey-overlay-title="Notification Center" {
|
||||
spawn "dms" "ipc" "call" "notifications" "toggle";
|
||||
}
|
||||
|
||||
Mod+Y hotkey-overlay-title="Browse Wallpapers" {
|
||||
spawn "dms" "ipc" "call" "dankdash" "wallpaper";
|
||||
}
|
||||
|
||||
Mod+Shift+N hotkey-overlay-title="Notepad" {
|
||||
spawn "dms" "ipc" "call" "notepad" "toggle";
|
||||
}
|
||||
|
||||
Mod+Alt+L hotkey-overlay-title="Lock Screen" {
|
||||
spawn "dms" "ipc" "call" "lock" "lock";
|
||||
}
|
||||
|
||||
Ctrl+Alt+Delete hotkey-overlay-title="Task Manager" {
|
||||
spawn "dms" "ipc" "call" "processlist" "toggle";
|
||||
}
|
||||
|
||||
// Audio
|
||||
XF86AudioRaiseVolume allow-when-locked=true {
|
||||
spawn "dms" "ipc" "call" "audio" "increment" "3";
|
||||
}
|
||||
XF86AudioLowerVolume allow-when-locked=true {
|
||||
spawn "dms" "ipc" "call" "audio" "decrement" "3";
|
||||
}
|
||||
XF86AudioMute allow-when-locked=true {
|
||||
spawn "dms" "ipc" "call" "audio" "mute";
|
||||
}
|
||||
XF86AudioMicMute allow-when-locked=true {
|
||||
spawn "dms" "ipc" "call" "audio" "micmute";
|
||||
}
|
||||
|
||||
// BL
|
||||
XF86MonBrightnessUp allow-when-locked=true {
|
||||
spawn "dms" "ipc" "call" "brightness" "increment" "5" "";
|
||||
}
|
||||
XF86MonBrightnessDown allow-when-locked=true {
|
||||
spawn "dms" "ipc" "call" "brightness" "decrement" "5" "";
|
||||
}
|
||||
}
|
||||
1150
quickshell/Widgets/KeybindItem.qml
Normal file
1150
quickshell/Widgets/KeybindItem.qml
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user