mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2026-08-01 19:18:28 -04:00
qs: large sweep of dead code removals
This commit is contained in:
@@ -791,23 +791,6 @@ Singleton {
|
||||
return null;
|
||||
}
|
||||
|
||||
function getAllPluginItems() {
|
||||
if (typeof PluginService === "undefined") {
|
||||
return [];
|
||||
}
|
||||
|
||||
let allItems = [];
|
||||
const launchers = PluginService.getLauncherPlugins();
|
||||
|
||||
for (const pluginId in launchers) {
|
||||
const categoryName = launchers[pluginId].name || pluginId;
|
||||
const items = getPluginItems(categoryName, "");
|
||||
allItems = allItems.concat(items);
|
||||
}
|
||||
|
||||
return allItems;
|
||||
}
|
||||
|
||||
function getPluginItems(category, query) {
|
||||
if (typeof PluginService === "undefined")
|
||||
return [];
|
||||
@@ -915,21 +898,6 @@ Singleton {
|
||||
return false;
|
||||
}
|
||||
|
||||
function getPluginPasteText(pluginId, item) {
|
||||
if (typeof PluginService === "undefined")
|
||||
return null;
|
||||
|
||||
const instance = PluginService.pluginInstances[pluginId];
|
||||
if (!instance)
|
||||
return null;
|
||||
|
||||
if (typeof instance.getPasteText === "function") {
|
||||
return instance.getPasteText(item);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
function getPluginPasteArgs(pluginId, item) {
|
||||
if (typeof PluginService === "undefined")
|
||||
return null;
|
||||
@@ -950,21 +918,6 @@ Singleton {
|
||||
return null;
|
||||
}
|
||||
|
||||
function searchPluginItems(query) {
|
||||
if (typeof PluginService === "undefined")
|
||||
return [];
|
||||
|
||||
let allItems = [];
|
||||
const launchers = PluginService.getLauncherPlugins();
|
||||
|
||||
for (const pluginId in launchers) {
|
||||
const items = getPluginItemsForPlugin(pluginId, query);
|
||||
allItems = allItems.concat(items);
|
||||
}
|
||||
|
||||
return allItems;
|
||||
}
|
||||
|
||||
function getPluginLauncherCategories(pluginId) {
|
||||
if (typeof PluginService === "undefined")
|
||||
return [];
|
||||
@@ -1001,15 +954,4 @@ Singleton {
|
||||
log.warn("Error setting category on plugin", pluginId, ":", e);
|
||||
}
|
||||
}
|
||||
|
||||
function pluginHasCategories(pluginId) {
|
||||
if (typeof PluginService === "undefined")
|
||||
return false;
|
||||
|
||||
const instance = PluginService.pluginInstances[pluginId];
|
||||
if (!instance)
|
||||
return false;
|
||||
|
||||
return typeof instance.getCategories === "function";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -85,7 +85,6 @@ Singleton {
|
||||
}
|
||||
}
|
||||
|
||||
// Used in playLoginSoundIfApplicable()
|
||||
Process {
|
||||
id: loginSoundChecker
|
||||
onExited: exitCode => {
|
||||
@@ -720,15 +719,10 @@ EOFCONFIG
|
||||
return "";
|
||||
}
|
||||
|
||||
// FIRST: Check if we have a custom alias in our deviceAliases map
|
||||
// This ensures we always show the user's custom name, regardless of
|
||||
// whether WirePlumber has applied it to the node properties yet
|
||||
if (node.name && deviceAliases[node.name]) {
|
||||
return deviceAliases[node.name];
|
||||
}
|
||||
|
||||
// Check node.properties["node.description"] for WirePlumber-applied aliases
|
||||
// This is the live property updated by WirePlumber rules
|
||||
if (node.properties && node.properties["node.description"]) {
|
||||
const desc = node.properties["node.description"];
|
||||
if (desc !== node.name) {
|
||||
@@ -736,22 +730,18 @@ EOFCONFIG
|
||||
}
|
||||
}
|
||||
|
||||
// Check cached description as fallback
|
||||
if (node.description && node.description !== node.name) {
|
||||
return node.description;
|
||||
}
|
||||
|
||||
// Fallback to device description property
|
||||
if (node.properties && node.properties["device.description"]) {
|
||||
return node.properties["device.description"];
|
||||
}
|
||||
|
||||
// Fallback to nickname
|
||||
if (node.nickname && node.nickname !== node.name) {
|
||||
return node.nickname;
|
||||
}
|
||||
|
||||
// Fallback to friendly names based on node name patterns
|
||||
if (node.name.includes("analog-stereo")) {
|
||||
return "Built-in Audio Analog Stereo";
|
||||
}
|
||||
@@ -773,10 +763,6 @@ EOFCONFIG
|
||||
return "";
|
||||
}
|
||||
|
||||
// Get the original name without checking for custom aliases
|
||||
// Check pattern-based friendly names FIRST (before device.description)
|
||||
// This ensures we show user-friendly names like "Built-in Audio Analog Stereo"
|
||||
// instead of hardware chip names like "ALC274 Analog"
|
||||
if (node.name.includes("analog-stereo")) {
|
||||
return "Built-in Audio Analog Stereo";
|
||||
}
|
||||
@@ -790,19 +776,16 @@ EOFCONFIG
|
||||
return "HDMI Audio";
|
||||
}
|
||||
if (node.name.includes("raop_sink")) {
|
||||
// Extract friendly name from RAOP node name
|
||||
const match = node.name.match(/raop_sink\.([^.]+)/);
|
||||
if (match) {
|
||||
return match[1].replace(/-/g, " ");
|
||||
}
|
||||
}
|
||||
|
||||
// Fallback to device.description property
|
||||
if (node.properties && node.properties["device.description"]) {
|
||||
return node.properties["device.description"];
|
||||
}
|
||||
|
||||
// Fallback to nickname
|
||||
if (node.nickname && node.nickname !== node.name) {
|
||||
return node.nickname;
|
||||
}
|
||||
@@ -889,28 +872,6 @@ EOFCONFIG
|
||||
return root.sink.audio.muted ? "Audio muted" : "Audio unmuted";
|
||||
}
|
||||
|
||||
function handleNodeVolumeWheel(node, wheelEvent) {
|
||||
if (!node?.audio)
|
||||
return;
|
||||
|
||||
SessionData.suppressOSDTemporarily();
|
||||
const delta = wheelEvent.angleDelta.y;
|
||||
if (delta === 0)
|
||||
return;
|
||||
|
||||
const current = Math.round(node.audio.volume * 100);
|
||||
const maxVol = getMaxVolumePercent(node);
|
||||
const newVolume = delta > 0 ? Math.min(maxVol, current + root.wheelVolumeStep) : Math.max(0, current - root.wheelVolumeStep);
|
||||
|
||||
node.audio.muted = false;
|
||||
node.audio.volume = newVolume / 100;
|
||||
|
||||
if (node === sink) {
|
||||
playVolumeChangeSoundIfEnabled();
|
||||
}
|
||||
wheelEvent.accepted = true;
|
||||
}
|
||||
|
||||
function setMicVolume(percentage) {
|
||||
if (!root.source?.audio) {
|
||||
return "No audio source available";
|
||||
|
||||
@@ -354,28 +354,6 @@ Singleton {
|
||||
return "Very Poor";
|
||||
}
|
||||
|
||||
function getSignalIcon(device) {
|
||||
if (!device || device.signalStrength === undefined || device.signalStrength <= 0) {
|
||||
return "signal_cellular_null";
|
||||
}
|
||||
|
||||
const signal = device.signalStrength;
|
||||
if (signal >= 80) {
|
||||
return "signal_cellular_4_bar";
|
||||
}
|
||||
if (signal >= 60) {
|
||||
return "signal_cellular_3_bar";
|
||||
}
|
||||
if (signal >= 40) {
|
||||
return "signal_cellular_2_bar";
|
||||
}
|
||||
if (signal >= 20) {
|
||||
return "signal_cellular_1_bar";
|
||||
}
|
||||
|
||||
return "signal_cellular_0_bar";
|
||||
}
|
||||
|
||||
function isDeviceBusy(device) {
|
||||
if (!device) {
|
||||
return false;
|
||||
@@ -622,40 +600,6 @@ Singleton {
|
||||
});
|
||||
}
|
||||
|
||||
function getCurrentCodec(device, callback) {
|
||||
if (!device || !device.connected || !isAudioDevice(device)) {
|
||||
callback("");
|
||||
return;
|
||||
}
|
||||
|
||||
whenCodecBackendReady(() => {
|
||||
if (root.wpexecAvailable) {
|
||||
root.queryCardProfiles(device, (codecs, current) => {
|
||||
if (current) {
|
||||
callback(current);
|
||||
return;
|
||||
}
|
||||
if (!root.dbusBridgeAvailable) {
|
||||
callback("");
|
||||
return;
|
||||
}
|
||||
root.queryBluezCodecState(device, (bluezCodecs, bluezCurrent) => {
|
||||
callback(bluezCurrent || "");
|
||||
});
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
if (!root.dbusBridgeAvailable) {
|
||||
callback("");
|
||||
return;
|
||||
}
|
||||
root.queryBluezCodecState(device, (codecs, current) => {
|
||||
callback(current || "");
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function getAvailableCodecs(device, callback) {
|
||||
if (!device || !device.connected || !isAudioDevice(device)) {
|
||||
callback([], "");
|
||||
|
||||
@@ -41,6 +41,12 @@ Singleton {
|
||||
return Theme.withAlpha(baseColor, hoverAlpha ?? 0.15);
|
||||
}
|
||||
|
||||
Binding {
|
||||
target: Theme
|
||||
property: "blurLayersActive"
|
||||
value: root.enabled
|
||||
}
|
||||
|
||||
Process {
|
||||
id: blurProbe
|
||||
running: false
|
||||
|
||||
@@ -1087,4 +1087,58 @@ Singleton {
|
||||
}
|
||||
log.warn("Cannot power on monitors, unknown compositor");
|
||||
}
|
||||
function escapeSwayWorkspaceName(name) {
|
||||
return String(name ?? "").replace(/\\/g, "\\\\").replace(/"/g, "\\\"");
|
||||
}
|
||||
|
||||
function dispatchSwayWorkspace(ws) {
|
||||
if (!ws)
|
||||
return;
|
||||
try {
|
||||
if (ws.num !== undefined && ws.num !== -1) {
|
||||
I3.dispatch(`workspace number ${ws.num}`);
|
||||
} else if (ws.name) {
|
||||
I3.dispatch(`workspace "${escapeSwayWorkspaceName(ws.name)}"`);
|
||||
}
|
||||
} catch (_) {}
|
||||
}
|
||||
|
||||
Binding {
|
||||
target: SettingsData
|
||||
property: "activeCompositor"
|
||||
value: root.compositor
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: SettingsData
|
||||
|
||||
function onCompositorLayoutRefreshNeeded(frame) {
|
||||
if (root.isNiri && typeof NiriService !== "undefined")
|
||||
NiriService.generateNiriLayoutConfig(frame);
|
||||
if (root.isHyprland && typeof HyprlandService !== "undefined")
|
||||
HyprlandService.generateLayoutConfig(frame);
|
||||
if (!frame && root.isMango && typeof MangoService !== "undefined")
|
||||
MangoService.generateLayoutConfig();
|
||||
}
|
||||
|
||||
function onCompositorInputRefreshNeeded() {
|
||||
if (root.isNiri && typeof NiriService !== "undefined")
|
||||
NiriService.generateNiriInputConfig();
|
||||
}
|
||||
|
||||
function onCompositorCursorRefreshNeeded() {
|
||||
if (root.isNiri && typeof NiriService !== "undefined") {
|
||||
NiriService.generateNiriCursorConfig();
|
||||
return;
|
||||
}
|
||||
if (root.isHyprland && typeof HyprlandService !== "undefined") {
|
||||
HyprlandService.generateCursorConfig();
|
||||
return;
|
||||
}
|
||||
if (root.isMango && typeof MangoService !== "undefined") {
|
||||
MangoService.generateCursorConfig();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -349,14 +349,6 @@ Singleton {
|
||||
return getPrinterStateTranslation(printer.state) + " (" + getPrinterStateReasonTranslation(printer.stateReason) + ")";
|
||||
}
|
||||
|
||||
function getCurrentPrinterStatePretty() {
|
||||
if (!cupsAvailable || !selectedPrinter)
|
||||
return "";
|
||||
|
||||
var printer = printers[selectedPrinter];
|
||||
return getPrinterStateTranslation(printer.state) + " (" + I18n.tr("Reason") + ": " + getPrinterStateReasonTranslation(printer.stateReason) + ")";
|
||||
}
|
||||
|
||||
function getCurrentPrinterJobs() {
|
||||
if (!cupsAvailable || !selectedPrinter)
|
||||
return [];
|
||||
@@ -372,14 +364,6 @@ Singleton {
|
||||
return printer.jobs;
|
||||
}
|
||||
|
||||
function getJobsNum(printerName) {
|
||||
if (!cupsAvailable)
|
||||
return 0;
|
||||
|
||||
var printer = printers[printerName];
|
||||
return printer.jobs.length;
|
||||
}
|
||||
|
||||
function pausePrinter(printerName) {
|
||||
if (!cupsAvailable)
|
||||
return;
|
||||
@@ -579,57 +563,6 @@ Singleton {
|
||||
});
|
||||
}
|
||||
|
||||
function setPrinterShared(printerName, shared) {
|
||||
if (!cupsAvailable)
|
||||
return;
|
||||
const params = {
|
||||
"printerName": printerName,
|
||||
"shared": shared
|
||||
};
|
||||
|
||||
DMSService.sendRequest("cups.setPrinterShared", params, response => {
|
||||
if (response.error) {
|
||||
ToastService.showError(I18n.tr("Failed to update sharing"), response.error);
|
||||
} else {
|
||||
getState();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function setPrinterLocation(printerName, location) {
|
||||
if (!cupsAvailable)
|
||||
return;
|
||||
const params = {
|
||||
"printerName": printerName,
|
||||
"location": location
|
||||
};
|
||||
|
||||
DMSService.sendRequest("cups.setPrinterLocation", params, response => {
|
||||
if (response.error) {
|
||||
ToastService.showError(I18n.tr("Failed to update location"), response.error);
|
||||
} else {
|
||||
getState();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function setPrinterInfo(printerName, info) {
|
||||
if (!cupsAvailable)
|
||||
return;
|
||||
const params = {
|
||||
"printerName": printerName,
|
||||
"info": info
|
||||
};
|
||||
|
||||
DMSService.sendRequest("cups.setPrinterInfo", params, response => {
|
||||
if (response.error) {
|
||||
ToastService.showError(I18n.tr("Failed to update description"), response.error);
|
||||
} else {
|
||||
getState();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function printTestPage(printerName) {
|
||||
if (!cupsAvailable)
|
||||
return;
|
||||
@@ -647,23 +580,6 @@ Singleton {
|
||||
});
|
||||
}
|
||||
|
||||
function moveJob(jobID, destPrinter) {
|
||||
if (!cupsAvailable)
|
||||
return;
|
||||
const params = {
|
||||
"jobID": jobID,
|
||||
"destPrinter": destPrinter
|
||||
};
|
||||
|
||||
DMSService.sendRequest("cups.moveJob", params, response => {
|
||||
if (response.error) {
|
||||
ToastService.showError(I18n.tr("Failed to move job"), response.error);
|
||||
} else {
|
||||
fetchAllJobs();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function restartJob(jobID) {
|
||||
if (!cupsAvailable)
|
||||
return;
|
||||
@@ -699,40 +615,6 @@ Singleton {
|
||||
});
|
||||
}
|
||||
|
||||
function addPrinterToClass(className, printerName) {
|
||||
if (!cupsAvailable)
|
||||
return;
|
||||
const params = {
|
||||
"className": className,
|
||||
"printerName": printerName
|
||||
};
|
||||
|
||||
DMSService.sendRequest("cups.addPrinterToClass", params, response => {
|
||||
if (response.error) {
|
||||
ToastService.showError(I18n.tr("Failed to add printer to class"), response.error);
|
||||
} else {
|
||||
getClasses();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function removePrinterFromClass(className, printerName) {
|
||||
if (!cupsAvailable)
|
||||
return;
|
||||
const params = {
|
||||
"className": className,
|
||||
"printerName": printerName
|
||||
};
|
||||
|
||||
DMSService.sendRequest("cups.removePrinterFromClass", params, response => {
|
||||
if (response.error) {
|
||||
ToastService.showError(I18n.tr("Failed to remove printer from class"), response.error);
|
||||
} else {
|
||||
getClasses();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function deleteClass(className) {
|
||||
if (!cupsAvailable)
|
||||
return;
|
||||
|
||||
@@ -1049,10 +1049,6 @@ Singleton {
|
||||
return activeUuids && activeUuids.indexOf(uuid) !== -1;
|
||||
}
|
||||
|
||||
function isActiveUuid(uuid) {
|
||||
return isActiveVpnUuid(uuid);
|
||||
}
|
||||
|
||||
function refreshNetworkState() {
|
||||
if (networkAvailable) {
|
||||
getState();
|
||||
|
||||
@@ -301,20 +301,6 @@ Singleton {
|
||||
}
|
||||
}
|
||||
|
||||
function subscribeAll() {
|
||||
subscribe(["all"]);
|
||||
}
|
||||
|
||||
function subscribeAllExcept(excludeServices) {
|
||||
if (!Array.isArray(excludeServices)) {
|
||||
excludeServices = [excludeServices];
|
||||
}
|
||||
|
||||
const allServices = ["network", "loginctl", "freedesktop", "gamma", "theme.auto", "bluetooth", "cups", "brightness", "browser", "dbus", "location"];
|
||||
const filtered = allServices.filter(s => !excludeServices.includes(s));
|
||||
subscribe(filtered);
|
||||
}
|
||||
|
||||
function handleSubscriptionEvent(response) {
|
||||
if (response.error) {
|
||||
if (response.error.includes("unknown method") && response.error.includes("subscribe")) {
|
||||
@@ -453,10 +439,6 @@ Singleton {
|
||||
}
|
||||
}
|
||||
|
||||
function ping(callback) {
|
||||
sendRequest("ping", null, callback);
|
||||
}
|
||||
|
||||
function listPlugins(callback) {
|
||||
sendRequest("plugins.list", null, response => {
|
||||
if (response.result) {
|
||||
@@ -481,30 +463,6 @@ Singleton {
|
||||
});
|
||||
}
|
||||
|
||||
function search(query, category, compositor, capability, callback) {
|
||||
const params = {
|
||||
"query": query
|
||||
};
|
||||
if (category) {
|
||||
params.category = category;
|
||||
}
|
||||
if (compositor) {
|
||||
params.compositor = compositor;
|
||||
}
|
||||
if (capability) {
|
||||
params.capability = capability;
|
||||
}
|
||||
|
||||
sendRequest("plugins.search", params, response => {
|
||||
if (response.result) {
|
||||
searchResultsReceived(response.result);
|
||||
}
|
||||
if (callback) {
|
||||
callback(response);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function install(pluginName, callback) {
|
||||
sendRequest("plugins.install", {
|
||||
"name": pluginName
|
||||
@@ -568,19 +526,6 @@ Singleton {
|
||||
});
|
||||
}
|
||||
|
||||
function searchThemes(query, callback) {
|
||||
sendRequest("themes.search", {
|
||||
"query": query
|
||||
}, response => {
|
||||
if (response.result) {
|
||||
themeSearchResultsReceived(response.result);
|
||||
}
|
||||
if (callback) {
|
||||
callback(response);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function installTheme(themeName, callback) {
|
||||
sendRequest("themes.install", {
|
||||
"name": themeName
|
||||
@@ -607,19 +552,6 @@ Singleton {
|
||||
});
|
||||
}
|
||||
|
||||
function updateTheme(themeName, callback) {
|
||||
sendRequest("themes.update", {
|
||||
"name": themeName
|
||||
}, response => {
|
||||
if (callback) {
|
||||
callback(response);
|
||||
}
|
||||
if (!response.error) {
|
||||
listInstalledThemes();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function lockSession(callback) {
|
||||
sendRequest("loginctl.lock", null, callback);
|
||||
}
|
||||
@@ -640,30 +572,12 @@ Singleton {
|
||||
}, callback);
|
||||
}
|
||||
|
||||
function bluetoothConnect(devicePath, callback) {
|
||||
sendRequest("bluetooth.connect", {
|
||||
"device": devicePath
|
||||
}, callback);
|
||||
}
|
||||
|
||||
function bluetoothDisconnect(devicePath, callback) {
|
||||
sendRequest("bluetooth.disconnect", {
|
||||
"device": devicePath
|
||||
}, callback);
|
||||
}
|
||||
|
||||
function bluetoothRemove(devicePath, callback) {
|
||||
sendRequest("bluetooth.remove", {
|
||||
"device": devicePath
|
||||
}, callback);
|
||||
}
|
||||
|
||||
function bluetoothTrust(devicePath, callback) {
|
||||
sendRequest("bluetooth.trust", {
|
||||
"device": devicePath
|
||||
}, callback);
|
||||
}
|
||||
|
||||
function bluetoothSubmitPairing(token, secrets, accept, callback) {
|
||||
sendRequest("bluetooth.pairing.submit", {
|
||||
"token": token,
|
||||
|
||||
@@ -18,7 +18,10 @@ Singleton {
|
||||
property bool systemdAutostartTargetChecked: false
|
||||
readonly property bool autostartAvailable: root.systemdAutostartTargetChecked && (!root.isSystemd || root.systemdAutostartTargetActive)
|
||||
|
||||
Component.onCompleted: initSystemCheckProcess.running = true
|
||||
Component.onCompleted: {
|
||||
Paths.desktopIconResolver = name => resolveIconPath(name);
|
||||
initSystemCheckProcess.running = true;
|
||||
}
|
||||
|
||||
Process {
|
||||
id: initSystemCheckProcess
|
||||
|
||||
@@ -156,10 +156,6 @@ Singleton {
|
||||
}
|
||||
}
|
||||
|
||||
function setGpuPciIds(pciIds) {
|
||||
gpuPciIds = Array.isArray(pciIds) ? pciIds : [];
|
||||
}
|
||||
|
||||
function addGpuPciId(pciId) {
|
||||
const currentCount = gpuPciIdRefCounts[pciId] || 0;
|
||||
gpuPciIdRefCounts[pciId] = currentCount + 1;
|
||||
@@ -203,12 +199,6 @@ Singleton {
|
||||
gpuPciIdRefCounts = Object.assign({}, gpuPciIdRefCounts);
|
||||
}
|
||||
|
||||
function setProcessOptions(limit = 20, sort = "cpu", disableCpu = false) {
|
||||
processLimit = limit;
|
||||
processSort = sort;
|
||||
noCpu = disableCpu;
|
||||
}
|
||||
|
||||
function updateAllStats() {
|
||||
if (dgopAvailable && refCount > 0 && enabledModules.length > 0) {
|
||||
isUpdating = true;
|
||||
@@ -476,44 +466,6 @@ Singleton {
|
||||
}
|
||||
}
|
||||
|
||||
function getProcessIcon(command) {
|
||||
const cmd = command.toLowerCase();
|
||||
if (cmd.includes("firefox") || cmd.includes("chrome") || cmd.includes("browser") || cmd.includes("chromium")) {
|
||||
return "web";
|
||||
}
|
||||
if (cmd.includes("code") || cmd.includes("editor") || cmd.includes("vim")) {
|
||||
return "code";
|
||||
}
|
||||
if (cmd.includes("terminal") || cmd.includes("bash") || cmd.includes("zsh")) {
|
||||
return "terminal";
|
||||
}
|
||||
if (cmd.includes("music") || cmd.includes("audio") || cmd.includes("spotify")) {
|
||||
return "music_note";
|
||||
}
|
||||
if (cmd.includes("video") || cmd.includes("vlc") || cmd.includes("mpv")) {
|
||||
return "play_circle";
|
||||
}
|
||||
if (cmd.includes("systemd") || cmd.includes("elogind") || cmd.includes("kernel") || cmd.includes("kthread") || cmd.includes("kworker")) {
|
||||
return "settings";
|
||||
}
|
||||
return "memory";
|
||||
}
|
||||
|
||||
function formatCpuUsage(cpu) {
|
||||
return (cpu || 0).toFixed(1) + "%";
|
||||
}
|
||||
|
||||
function formatMemoryUsage(memoryKB) {
|
||||
const mem = memoryKB || 0;
|
||||
if (mem < 1024) {
|
||||
return mem.toFixed(0) + " KB";
|
||||
} else if (mem < 1024 * 1024) {
|
||||
return (mem / 1024).toFixed(1) + " MB";
|
||||
} else {
|
||||
return (mem / (1024 * 1024)).toFixed(1) + " GB";
|
||||
}
|
||||
}
|
||||
|
||||
function formatSystemMemory(memoryKB) {
|
||||
const mem = memoryKB || 0;
|
||||
if (mem === 0) {
|
||||
@@ -526,12 +478,6 @@ Singleton {
|
||||
}
|
||||
}
|
||||
|
||||
function killProcess(pid) {
|
||||
if (pid > 0) {
|
||||
Quickshell.execDetached("kill", [pid.toString()]);
|
||||
}
|
||||
}
|
||||
|
||||
function updateUptime() {
|
||||
if (!bootTime) {
|
||||
uptime = "";
|
||||
|
||||
@@ -1228,10 +1228,6 @@ Singleton {
|
||||
});
|
||||
}
|
||||
|
||||
function setNightModeAutomationMode(mode) {
|
||||
SessionData.setNightModeAutoMode(mode);
|
||||
}
|
||||
|
||||
function evaluateNightMode() {
|
||||
if (!nightModeEnabled) {
|
||||
return;
|
||||
@@ -1355,6 +1351,14 @@ Singleton {
|
||||
brightnessChanged();
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: SessionData
|
||||
|
||||
function onBrightnessDisplayHintChanged(deviceName) {
|
||||
root.updateDeviceBrightnessDisplay(deviceName);
|
||||
}
|
||||
}
|
||||
|
||||
Timer {
|
||||
id: osdSuppressTimer
|
||||
interval: 2000
|
||||
|
||||
@@ -37,7 +37,10 @@ Singleton {
|
||||
}
|
||||
|
||||
onManagedThemeChanged: _rebuild()
|
||||
Component.onCompleted: _rebuild()
|
||||
Component.onCompleted: {
|
||||
Paths.iconResolver = name => resolve(name);
|
||||
_rebuild();
|
||||
}
|
||||
|
||||
function _bumpRevision() {
|
||||
if (_bumpPending)
|
||||
|
||||
@@ -574,18 +574,6 @@ Singleton {
|
||||
bindRemoved(key);
|
||||
}
|
||||
|
||||
function isDmsAction(action) {
|
||||
return Actions.isDmsAction(action);
|
||||
}
|
||||
|
||||
function isValidAction(action) {
|
||||
return Actions.isValidAction(action);
|
||||
}
|
||||
|
||||
function getActionType(action) {
|
||||
return Actions.getActionType(action);
|
||||
}
|
||||
|
||||
function getActionLabel(action) {
|
||||
return Actions.getActionLabel(action, currentProvider);
|
||||
}
|
||||
@@ -601,24 +589,4 @@ Singleton {
|
||||
function getDmsActions() {
|
||||
return Actions.getDmsActions(CompositorService.isNiri, CompositorService.isHyprland);
|
||||
}
|
||||
|
||||
function buildSpawnAction(command, args) {
|
||||
return Actions.buildSpawnAction(command, args);
|
||||
}
|
||||
|
||||
function buildShellAction(shellCmd, shell) {
|
||||
return Actions.buildShellAction(currentProvider, shellCmd, shell);
|
||||
}
|
||||
|
||||
function getShellFromAction(action) {
|
||||
return Actions.getShellFromAction(action);
|
||||
}
|
||||
|
||||
function parseSpawnCommand(action) {
|
||||
return Actions.parseSpawnCommand(action);
|
||||
}
|
||||
|
||||
function parseShellCommand(action) {
|
||||
return Actions.parseShellCommand(action);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,7 +48,6 @@ Singleton {
|
||||
// windowsChanged is auto-generated by the `windows` property's change signal.
|
||||
signal stateChanged
|
||||
|
||||
// ── State sockets ──────────────────────────────────────────────────────
|
||||
// One connection per watch target; mango streams a fresh full snapshot on
|
||||
// every change, so each line is treated as the complete state.
|
||||
|
||||
@@ -272,8 +271,6 @@ Singleton {
|
||||
root.windows = data.clients;
|
||||
}
|
||||
|
||||
// ── Tag API (dwl-style tag model) ──────────────────────────────────────
|
||||
|
||||
function getOutputState(outputName) {
|
||||
return (outputs && outputs[outputName]) ? outputs[outputName] : null;
|
||||
}
|
||||
@@ -296,20 +293,6 @@ Singleton {
|
||||
return at.length === 0 || at.every(t => t === 0);
|
||||
}
|
||||
|
||||
function getTagsWithClients(outputName) {
|
||||
const output = getOutputState(outputName);
|
||||
if (!output || !output.tags)
|
||||
return [];
|
||||
return output.tags.filter(tag => tag.clients > 0).map(tag => tag.tag);
|
||||
}
|
||||
|
||||
function getUrgentTags(outputName) {
|
||||
const output = getOutputState(outputName);
|
||||
if (!output || !output.tags)
|
||||
return [];
|
||||
return output.tags.filter(tag => tag.state === 2).map(tag => tag.tag);
|
||||
}
|
||||
|
||||
function getVisibleTags(outputName) {
|
||||
const output = getOutputState(outputName);
|
||||
if (!output || !output.tags)
|
||||
@@ -328,7 +311,6 @@ Singleton {
|
||||
return displayScales[outputName];
|
||||
}
|
||||
|
||||
// ── Window list ↔ wlr toplevel matching (per-tag sort/filter) ──────────
|
||||
// Match mango clients to wlr foreign-toplevels by appId+title to enrich them
|
||||
// with owning tags/monitor for per-tag filtering and stable ordering.
|
||||
|
||||
@@ -452,8 +434,6 @@ Singleton {
|
||||
return _matchAndEnrich(toplevels, clients);
|
||||
}
|
||||
|
||||
// ── Commands (mango verb IPC: dispatch <func>,<args> over the socket) ──
|
||||
|
||||
function suppressWatchedConfigReloads(ms) {
|
||||
root._ignoreWatchedReloadUntil = Math.max(root._ignoreWatchedReloadUntil, Date.now() + (ms || 1500));
|
||||
}
|
||||
@@ -539,8 +519,6 @@ Singleton {
|
||||
}
|
||||
}
|
||||
|
||||
// ── Config generation (mango config fragments under ~/.config/mango/dms) ─
|
||||
|
||||
Connections {
|
||||
target: SettingsData
|
||||
function onBarConfigsChanged() {
|
||||
|
||||
@@ -76,6 +76,28 @@ Singleton {
|
||||
generateNiriInputConfig();
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: Theme
|
||||
|
||||
function onScreenTransitionNeeded() {
|
||||
if (CompositorService.isNiri) {
|
||||
root.doScreenTransition();
|
||||
}
|
||||
}
|
||||
|
||||
function onThemeGenerationStarting() {
|
||||
if (CompositorService.isNiri) {
|
||||
root.suppressNextToast();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Binding {
|
||||
target: Theme
|
||||
property: "matugenToastSuppressed"
|
||||
value: root.matugenSuppression
|
||||
}
|
||||
|
||||
Timer {
|
||||
id: suppressToastTimer
|
||||
interval: 3000
|
||||
@@ -798,22 +820,6 @@ Singleton {
|
||||
});
|
||||
}
|
||||
|
||||
function moveWorkspaceDown() {
|
||||
return send({
|
||||
"Action": {
|
||||
"FocusWorkspaceDown": {}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function moveWorkspaceUp() {
|
||||
return send({
|
||||
"Action": {
|
||||
"FocusWorkspaceUp": {}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function switchToWorkspace(workspaceId) {
|
||||
return send({
|
||||
"Action": {
|
||||
@@ -925,10 +931,6 @@ Singleton {
|
||||
});
|
||||
}
|
||||
|
||||
function getCurrentOutputWorkspaceNumbers() {
|
||||
return currentOutputWorkspaces.map(w => w.idx + 1);
|
||||
}
|
||||
|
||||
function getCurrentOutputWorkspaces() {
|
||||
return currentOutputWorkspaces.slice();
|
||||
}
|
||||
@@ -952,24 +954,6 @@ Singleton {
|
||||
suppressResetTimer.restart();
|
||||
}
|
||||
|
||||
function findNiriWindow(toplevel) {
|
||||
if (!toplevel.appId)
|
||||
return null;
|
||||
|
||||
for (var j = 0; j < windows.length; j++) {
|
||||
const niriWindow = windows[j];
|
||||
if (niriWindow.app_id === toplevel.appId) {
|
||||
if (!niriWindow.title || niriWindow.title === toplevel.title) {
|
||||
return {
|
||||
"niriIndex": j,
|
||||
"niriWindow": niriWindow
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function sortToplevels(toplevels) {
|
||||
if (!toplevels || toplevels.length === 0 || !CompositorService.isNiri || windows.length === 0) {
|
||||
return [...toplevels];
|
||||
@@ -1371,23 +1355,6 @@ window-rule {
|
||||
writeCursorProcess.running = true;
|
||||
}
|
||||
|
||||
function updateOutputPosition(outputName, x, y) {
|
||||
if (!outputs || !outputs[outputName])
|
||||
return;
|
||||
const updatedOutputs = {};
|
||||
for (const name in outputs) {
|
||||
const output = outputs[name];
|
||||
if (name === outputName && output.logical) {
|
||||
updatedOutputs[name] = JSON.parse(JSON.stringify(output));
|
||||
updatedOutputs[name].logical.x = x;
|
||||
updatedOutputs[name].logical.y = y;
|
||||
} else {
|
||||
updatedOutputs[name] = output;
|
||||
}
|
||||
}
|
||||
outputs = updatedOutputs;
|
||||
}
|
||||
|
||||
function applyOutputConfig(outputName, config, callback) {
|
||||
if (!CompositorService.isNiri || !outputName) {
|
||||
if (callback)
|
||||
@@ -1786,6 +1753,31 @@ window-rule {
|
||||
writeInputProcess.running = true;
|
||||
}
|
||||
|
||||
function hasNamedWorkspaces() {
|
||||
if (!CompositorService.isNiri)
|
||||
return false;
|
||||
|
||||
for (var i = 0; i < allWorkspaces.length; i++) {
|
||||
var ws = allWorkspaces[i];
|
||||
if (ws.name && ws.name.trim() !== "")
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function getNamedWorkspaces() {
|
||||
var namedWorkspaces = [];
|
||||
if (!CompositorService.isNiri)
|
||||
return namedWorkspaces;
|
||||
|
||||
for (const ws of allWorkspaces) {
|
||||
if (ws.name && ws.name.trim() !== "") {
|
||||
namedWorkspaces.push(ws.name);
|
||||
}
|
||||
}
|
||||
return namedWorkspaces;
|
||||
}
|
||||
|
||||
IpcHandler {
|
||||
function screenshot(): string {
|
||||
if (!CompositorService.isNiri) {
|
||||
|
||||
@@ -259,36 +259,6 @@ Singleton {
|
||||
return historyList.filter(n => getHistoryTimeRange(n.timestamp) === range).length;
|
||||
}
|
||||
|
||||
function formatHistoryTime(timestamp) {
|
||||
root.timeUpdateTick;
|
||||
root.clockFormatChanged;
|
||||
const now = new Date();
|
||||
const date = new Date(timestamp);
|
||||
const diff = now.getTime() - timestamp;
|
||||
const minutes = Math.floor(diff / 60000);
|
||||
const hours = Math.floor(minutes / 60);
|
||||
if (hours < 1) {
|
||||
if (minutes < 1)
|
||||
return I18n.tr("now");
|
||||
return I18n.tr("%1m ago").arg(minutes);
|
||||
}
|
||||
const nowDate = new Date(now.getFullYear(), now.getMonth(), now.getDate());
|
||||
const itemDate = new Date(date.getFullYear(), date.getMonth(), date.getDate());
|
||||
const daysDiff = Math.floor((nowDate - itemDate) / (1000 * 60 * 60 * 24));
|
||||
const timeStr = SettingsData.use24HourClock ? date.toLocaleTimeString(Qt.locale(), "HH:mm") : date.toLocaleTimeString(Qt.locale(), "h:mm AP");
|
||||
if (daysDiff === 0)
|
||||
return timeStr;
|
||||
try {
|
||||
const localeName = (typeof I18n !== "undefined" && I18n.locale) ? I18n.locale().name : "en-US";
|
||||
const weekday = date.toLocaleDateString(localeName, {
|
||||
weekday: "long"
|
||||
});
|
||||
return weekday + ", " + timeStr;
|
||||
} catch (e) {
|
||||
return timeStr;
|
||||
}
|
||||
}
|
||||
|
||||
function _nowSec() {
|
||||
return Date.now() / 1000.0;
|
||||
}
|
||||
@@ -929,6 +899,56 @@ Singleton {
|
||||
notificationQueue = [];
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: SettingsData
|
||||
|
||||
function onNotificationPopupsInvalidated() {
|
||||
root.dismissAllPopups();
|
||||
}
|
||||
}
|
||||
|
||||
function sendTestNotifications() {
|
||||
dismissAllPopups();
|
||||
sendTestNotification(0);
|
||||
testNotifTimer1.start();
|
||||
testNotifTimer2.start();
|
||||
}
|
||||
|
||||
function sendTestNotification(index) {
|
||||
const notifications = [["Notification Position Test", "DMS test notification 1 of 3 ~ Hi there!", "preferences-system"], ["Second Test", "DMS Notification 2 of 3 ~ Check it out!", "applications-graphics"], ["Third Test", "DMS notification 3 of 3 ~ Enjoy!", "face-smile"]];
|
||||
|
||||
if (index < 0 || index >= notifications.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
const notif = notifications[index];
|
||||
testNotificationProcess.command = ["notify-send", "-h", "int:transient:1", "-a", "DMS", "-i", notif[2], notif[0], notif[1]];
|
||||
testNotificationProcess.running = true;
|
||||
}
|
||||
|
||||
property Process testNotificationProcess
|
||||
|
||||
testNotificationProcess: Process {
|
||||
command: []
|
||||
running: false
|
||||
}
|
||||
|
||||
property Timer testNotifTimer1
|
||||
|
||||
testNotifTimer1: Timer {
|
||||
interval: 400
|
||||
repeat: false
|
||||
onTriggered: root.sendTestNotification(1)
|
||||
}
|
||||
|
||||
property Timer testNotifTimer2
|
||||
|
||||
testNotifTimer2: Timer {
|
||||
interval: 800
|
||||
repeat: false
|
||||
onTriggered: root.sendTestNotification(2)
|
||||
}
|
||||
|
||||
function clearAllNotifications() {
|
||||
if (!notifications.length) {
|
||||
return;
|
||||
|
||||
@@ -252,11 +252,6 @@ Singleton {
|
||||
return paths;
|
||||
}
|
||||
|
||||
function pluginHasSurface(pluginId, surface) {
|
||||
const plugin = availablePlugins[pluginId];
|
||||
return !!(plugin && plugin.surfaces && plugin.surfaces.includes(surface));
|
||||
}
|
||||
|
||||
function _onManifestParsed(absPath, manifest, sourceTag, mtimeEpochMs) {
|
||||
if (!manifest || !manifest.id || !manifest.name || (!manifest.component && !manifest.components)) {
|
||||
log.error("invalid manifest fields:", absPath);
|
||||
@@ -839,10 +834,6 @@ Singleton {
|
||||
return plugin.pluginDirectory || "";
|
||||
}
|
||||
|
||||
function saveAllPluginSettings() {
|
||||
SettingsData.savePluginSettings();
|
||||
}
|
||||
|
||||
function getPluginStatePath(pluginId) {
|
||||
return Paths.strip(Paths.state) + "/plugins/" + pluginId + "_state.json";
|
||||
}
|
||||
|
||||
@@ -132,13 +132,6 @@ Singleton {
|
||||
}
|
||||
}
|
||||
|
||||
function setLightMode(isLightMode) {
|
||||
if (typeof SettingsData !== "undefined" && SettingsData.syncModeWithPortal === false) {
|
||||
return;
|
||||
}
|
||||
setSystemColorScheme(isLightMode);
|
||||
}
|
||||
|
||||
function setSystemColorScheme(isLightMode) {
|
||||
if (typeof SettingsData !== "undefined" && SettingsData.syncModeWithPortal === false) {
|
||||
return;
|
||||
@@ -211,6 +204,14 @@ Singleton {
|
||||
colorSchemeDetector.running = true;
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: Theme
|
||||
|
||||
function onIsLightModeChanged() {
|
||||
root.setSystemColorScheme(Theme.isLightMode);
|
||||
}
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: typeof SettingsData !== "undefined" ? SettingsData : null
|
||||
|
||||
|
||||
@@ -0,0 +1,541 @@
|
||||
pragma Singleton
|
||||
pragma ComponentBehavior: Bound
|
||||
|
||||
import QtQuick
|
||||
import Quickshell
|
||||
import qs.Common
|
||||
import qs.Services
|
||||
|
||||
Singleton {
|
||||
id: root
|
||||
readonly property var log: Log.scoped("ThemeAutoService")
|
||||
|
||||
property bool active: false
|
||||
|
||||
Component.onCompleted: {
|
||||
if (typeof SessionData !== "undefined" && SessionData.themeModeAutoEnabled) {
|
||||
start();
|
||||
}
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: SessionData
|
||||
enabled: typeof SessionData !== "undefined"
|
||||
|
||||
function onThemeModeAutoEnabledChanged() {
|
||||
if (SessionData.themeModeAutoEnabled) {
|
||||
root.start();
|
||||
} else {
|
||||
root.stop();
|
||||
}
|
||||
}
|
||||
|
||||
function onThemeModeAutoModeChanged() {
|
||||
if (root.active) {
|
||||
root.evaluate();
|
||||
root.syncTimeSchedule();
|
||||
root.syncLocationSchedule();
|
||||
}
|
||||
}
|
||||
|
||||
function onThemeModeStartHourChanged() {
|
||||
if (root.active && !SessionData.themeModeShareGammaSettings) {
|
||||
root.evaluate();
|
||||
root.syncTimeSchedule();
|
||||
}
|
||||
}
|
||||
|
||||
function onThemeModeStartMinuteChanged() {
|
||||
if (root.active && !SessionData.themeModeShareGammaSettings) {
|
||||
root.evaluate();
|
||||
root.syncTimeSchedule();
|
||||
}
|
||||
}
|
||||
|
||||
function onThemeModeEndHourChanged() {
|
||||
if (root.active && !SessionData.themeModeShareGammaSettings) {
|
||||
root.evaluate();
|
||||
root.syncTimeSchedule();
|
||||
}
|
||||
}
|
||||
|
||||
function onThemeModeEndMinuteChanged() {
|
||||
if (root.active && !SessionData.themeModeShareGammaSettings) {
|
||||
root.evaluate();
|
||||
root.syncTimeSchedule();
|
||||
}
|
||||
}
|
||||
|
||||
function onThemeModeShareGammaSettingsChanged() {
|
||||
if (root.active) {
|
||||
root.evaluate();
|
||||
root.syncTimeSchedule();
|
||||
root.syncLocationSchedule();
|
||||
}
|
||||
}
|
||||
|
||||
function onNightModeStartHourChanged() {
|
||||
if (root.active && SessionData.themeModeShareGammaSettings) {
|
||||
root.evaluate();
|
||||
root.syncTimeSchedule();
|
||||
}
|
||||
}
|
||||
|
||||
function onNightModeStartMinuteChanged() {
|
||||
if (root.active && SessionData.themeModeShareGammaSettings) {
|
||||
root.evaluate();
|
||||
root.syncTimeSchedule();
|
||||
}
|
||||
}
|
||||
|
||||
function onNightModeEndHourChanged() {
|
||||
if (root.active && SessionData.themeModeShareGammaSettings) {
|
||||
root.evaluate();
|
||||
root.syncTimeSchedule();
|
||||
}
|
||||
}
|
||||
|
||||
function onNightModeEndMinuteChanged() {
|
||||
if (root.active && SessionData.themeModeShareGammaSettings) {
|
||||
root.evaluate();
|
||||
root.syncTimeSchedule();
|
||||
}
|
||||
}
|
||||
|
||||
function onLatitudeChanged() {
|
||||
if (root.active && SessionData.themeModeAutoMode === "location") {
|
||||
if (!SessionData.nightModeUseIPLocation && SessionData.latitude !== 0.0 && SessionData.longitude !== 0.0 && typeof DMSService !== "undefined") {
|
||||
DMSService.sendRequest("wayland.gamma.setLocation", {
|
||||
"latitude": SessionData.latitude,
|
||||
"longitude": SessionData.longitude
|
||||
});
|
||||
}
|
||||
root.evaluate();
|
||||
root.syncLocationSchedule();
|
||||
}
|
||||
}
|
||||
|
||||
function onLongitudeChanged() {
|
||||
if (root.active && SessionData.themeModeAutoMode === "location") {
|
||||
if (!SessionData.nightModeUseIPLocation && SessionData.latitude !== 0.0 && SessionData.longitude !== 0.0 && typeof DMSService !== "undefined") {
|
||||
DMSService.sendRequest("wayland.gamma.setLocation", {
|
||||
"latitude": SessionData.latitude,
|
||||
"longitude": SessionData.longitude
|
||||
});
|
||||
}
|
||||
root.evaluate();
|
||||
root.syncLocationSchedule();
|
||||
}
|
||||
}
|
||||
|
||||
function onNightModeUseIPLocationChanged() {
|
||||
if (root.active && SessionData.themeModeAutoMode === "location") {
|
||||
if (typeof DMSService !== "undefined") {
|
||||
DMSService.sendRequest("wayland.gamma.setUseIPLocation", {
|
||||
"use": SessionData.nightModeUseIPLocation
|
||||
}, response => {
|
||||
if (!response.error && !SessionData.nightModeUseIPLocation && SessionData.latitude !== 0.0 && SessionData.longitude !== 0.0) {
|
||||
DMSService.sendRequest("wayland.gamma.setLocation", {
|
||||
"latitude": SessionData.latitude,
|
||||
"longitude": SessionData.longitude
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
root.evaluate();
|
||||
root.syncLocationSchedule();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: DisplayService
|
||||
enabled: typeof DisplayService !== "undefined" && typeof SessionData !== "undefined" && SessionData.themeModeAutoEnabled && SessionData.themeModeAutoMode === "location" && !root.backendAvailable()
|
||||
|
||||
function onGammaIsDayChanged() {
|
||||
if (Theme.isLightMode !== DisplayService.gammaIsDay) {
|
||||
Theme.setLightMode(DisplayService.gammaIsDay, true, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: DMSService
|
||||
|
||||
function onThemeAutoStateUpdate(data) {
|
||||
if (!SessionData.themeModeAutoEnabled) {
|
||||
return;
|
||||
}
|
||||
root.applyBackendState(data);
|
||||
}
|
||||
|
||||
function onConnectionStateChanged() {
|
||||
if (DMSService.isConnected && SessionData.themeModeAutoMode === "time") {
|
||||
root.syncTimeSchedule();
|
||||
}
|
||||
|
||||
if (DMSService.isConnected && SessionData.themeModeAutoMode === "location") {
|
||||
root.syncLocationSchedule();
|
||||
}
|
||||
|
||||
if (root.backendAvailable() && SessionData.themeModeAutoEnabled) {
|
||||
DMSService.sendRequest("theme.auto.getState", null, response => {
|
||||
if (response && response.result) {
|
||||
root.applyBackendState(response.result);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (!SessionData.themeModeAutoEnabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (DMSService.isConnected && SessionData.themeModeAutoMode === "location") {
|
||||
if (SessionData.nightModeUseIPLocation) {
|
||||
DMSService.sendRequest("wayland.gamma.setUseIPLocation", {
|
||||
"use": true
|
||||
}, response => {
|
||||
if (!response.error) {
|
||||
root.log.info("Theme automation: IP location enabled after connection");
|
||||
}
|
||||
});
|
||||
} else if (SessionData.latitude !== 0.0 && SessionData.longitude !== 0.0) {
|
||||
DMSService.sendRequest("wayland.gamma.setUseIPLocation", {
|
||||
"use": false
|
||||
}, response => {
|
||||
if (!response.error) {
|
||||
DMSService.sendRequest("wayland.gamma.setLocation", {
|
||||
"latitude": SessionData.latitude,
|
||||
"longitude": SessionData.longitude
|
||||
}, locationResponse => {
|
||||
if (locationResponse?.error) {
|
||||
root.log.warn("Theme automation: Failed to set location", locationResponse.error);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
} else {
|
||||
root.log.warn("Theme automation: No location configured");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: SessionService
|
||||
enabled: SessionData.themeModeAutoEnabled
|
||||
|
||||
function onSessionUnlocked() {
|
||||
root.refresh();
|
||||
}
|
||||
|
||||
function onSessionResumed() {
|
||||
root.refresh();
|
||||
}
|
||||
}
|
||||
|
||||
function refresh() {
|
||||
if (!backendAvailable()) {
|
||||
evaluate();
|
||||
return;
|
||||
}
|
||||
DMSService.sendRequest("theme.auto.trigger", {});
|
||||
}
|
||||
|
||||
function backendAvailable() {
|
||||
return typeof DMSService !== "undefined" && DMSService.isConnected && Array.isArray(DMSService.capabilities) && DMSService.capabilities.includes("theme.auto");
|
||||
}
|
||||
|
||||
function applyBackendState(state) {
|
||||
if (!state) {
|
||||
return;
|
||||
}
|
||||
if (state.config && state.config.mode && state.config.mode !== SessionData.themeModeAutoMode) {
|
||||
return;
|
||||
}
|
||||
if (typeof SessionData !== "undefined" && state.nextTransition !== undefined) {
|
||||
SessionData.themeModeNextTransition = state.nextTransition || "";
|
||||
}
|
||||
if (state.isLight !== undefined && Theme.isLightMode !== state.isLight) {
|
||||
Theme.setLightMode(state.isLight, true, true);
|
||||
}
|
||||
}
|
||||
|
||||
function syncTimeSchedule() {
|
||||
if (typeof SessionData === "undefined" || typeof DMSService === "undefined") {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!DMSService.isConnected) {
|
||||
return;
|
||||
}
|
||||
|
||||
const timeModeActive = SessionData.themeModeAutoEnabled && SessionData.themeModeAutoMode === "time";
|
||||
|
||||
if (!timeModeActive) {
|
||||
return;
|
||||
}
|
||||
|
||||
DMSService.sendRequest("theme.auto.setMode", {
|
||||
"mode": "time"
|
||||
});
|
||||
|
||||
const shareSettings = SessionData.themeModeShareGammaSettings;
|
||||
const startHour = shareSettings ? SessionData.nightModeStartHour : SessionData.themeModeStartHour;
|
||||
const startMinute = shareSettings ? SessionData.nightModeStartMinute : SessionData.themeModeStartMinute;
|
||||
const endHour = shareSettings ? SessionData.nightModeEndHour : SessionData.themeModeEndHour;
|
||||
const endMinute = shareSettings ? SessionData.nightModeEndMinute : SessionData.themeModeEndMinute;
|
||||
|
||||
DMSService.sendRequest("theme.auto.setSchedule", {
|
||||
"startHour": startHour,
|
||||
"startMinute": startMinute,
|
||||
"endHour": endHour,
|
||||
"endMinute": endMinute
|
||||
}, response => {
|
||||
if (response && response.error) {
|
||||
log.error("Theme automation: Failed to sync time schedule:", response.error);
|
||||
}
|
||||
});
|
||||
|
||||
DMSService.sendRequest("theme.auto.setEnabled", {
|
||||
"enabled": true
|
||||
});
|
||||
DMSService.sendRequest("theme.auto.trigger", {});
|
||||
}
|
||||
|
||||
function syncLocationSchedule() {
|
||||
if (typeof SessionData === "undefined" || typeof DMSService === "undefined") {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!DMSService.isConnected) {
|
||||
return;
|
||||
}
|
||||
|
||||
const locationModeActive = SessionData.themeModeAutoEnabled && SessionData.themeModeAutoMode === "location";
|
||||
|
||||
if (!locationModeActive) {
|
||||
return;
|
||||
}
|
||||
|
||||
DMSService.sendRequest("theme.auto.setMode", {
|
||||
"mode": "location"
|
||||
});
|
||||
|
||||
if (SessionData.nightModeUseIPLocation) {
|
||||
DMSService.sendRequest("theme.auto.setUseIPLocation", {
|
||||
"use": true
|
||||
});
|
||||
} else {
|
||||
DMSService.sendRequest("theme.auto.setUseIPLocation", {
|
||||
"use": false
|
||||
});
|
||||
if (SessionData.latitude !== 0.0 && SessionData.longitude !== 0.0) {
|
||||
DMSService.sendRequest("theme.auto.setLocation", {
|
||||
"latitude": SessionData.latitude,
|
||||
"longitude": SessionData.longitude
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
DMSService.sendRequest("theme.auto.setEnabled", {
|
||||
"enabled": true
|
||||
});
|
||||
DMSService.sendRequest("theme.auto.trigger", {});
|
||||
}
|
||||
|
||||
function evaluate() {
|
||||
if (typeof SessionData === "undefined" || !SessionData.themeModeAutoEnabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (backendAvailable()) {
|
||||
DMSService.sendRequest("theme.auto.getState", null, response => {
|
||||
if (response && response.result) {
|
||||
applyBackendState(response.result);
|
||||
}
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
const mode = SessionData.themeModeAutoMode;
|
||||
|
||||
if (mode === "location") {
|
||||
evaluateLocation();
|
||||
} else {
|
||||
evaluateTime();
|
||||
}
|
||||
}
|
||||
|
||||
function evaluateLocation() {
|
||||
if (typeof DisplayService !== "undefined") {
|
||||
const shouldBeLight = DisplayService.gammaIsDay;
|
||||
if (Theme.isLightMode !== shouldBeLight) {
|
||||
Theme.setLightMode(shouldBeLight, true, true);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (!SessionData.nightModeUseIPLocation && SessionData.latitude !== 0.0 && SessionData.longitude !== 0.0) {
|
||||
const shouldBeLight = calculateIsDaytime(SessionData.latitude, SessionData.longitude);
|
||||
if (Theme.isLightMode !== shouldBeLight) {
|
||||
Theme.setLightMode(shouldBeLight, true, true);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (root.active) {
|
||||
if (SessionData.nightModeUseIPLocation) {
|
||||
log.warn("Theme automation: Waiting for IP location from backend");
|
||||
} else {
|
||||
log.warn("Theme automation: Location mode requires coordinates");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function evaluateTime() {
|
||||
const shareSettings = SessionData.themeModeShareGammaSettings;
|
||||
|
||||
const startHour = shareSettings ? SessionData.nightModeStartHour : SessionData.themeModeStartHour;
|
||||
const startMinute = shareSettings ? SessionData.nightModeStartMinute : SessionData.themeModeStartMinute;
|
||||
const endHour = shareSettings ? SessionData.nightModeEndHour : SessionData.themeModeEndHour;
|
||||
const endMinute = shareSettings ? SessionData.nightModeEndMinute : SessionData.themeModeEndMinute;
|
||||
|
||||
const now = new Date();
|
||||
const currentMinutes = now.getHours() * 60 + now.getMinutes();
|
||||
const startMinutes = startHour * 60 + startMinute;
|
||||
const endMinutes = endHour * 60 + endMinute;
|
||||
|
||||
let shouldBeLight;
|
||||
if (startMinutes < endMinutes) {
|
||||
shouldBeLight = currentMinutes < startMinutes || currentMinutes >= endMinutes;
|
||||
} else {
|
||||
shouldBeLight = currentMinutes >= endMinutes && currentMinutes < startMinutes;
|
||||
}
|
||||
|
||||
if (Theme.isLightMode !== shouldBeLight) {
|
||||
Theme.setLightMode(shouldBeLight, true, true);
|
||||
}
|
||||
}
|
||||
|
||||
function calculateIsDaytime(lat, lng) {
|
||||
const now = new Date();
|
||||
const start = new Date(now.getFullYear(), 0, 0);
|
||||
const diff = now - start;
|
||||
const dayOfYear = Math.floor(diff / 86400000);
|
||||
const latRad = lat * Math.PI / 180;
|
||||
|
||||
const declination = 23.45 * Math.sin((360 / 365) * (dayOfYear - 81) * Math.PI / 180);
|
||||
const declinationRad = declination * Math.PI / 180;
|
||||
|
||||
const cosHourAngle = -Math.tan(latRad) * Math.tan(declinationRad);
|
||||
|
||||
if (cosHourAngle > 1) {
|
||||
return false;
|
||||
}
|
||||
if (cosHourAngle < -1) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const hourAngle = Math.acos(cosHourAngle);
|
||||
const hourAngleDeg = hourAngle * 180 / Math.PI;
|
||||
|
||||
const sunriseHour = 12 - hourAngleDeg / 15;
|
||||
const sunsetHour = 12 + hourAngleDeg / 15;
|
||||
|
||||
const timeZoneOffset = now.getTimezoneOffset() / 60;
|
||||
const localSunrise = sunriseHour - lng / 15 - timeZoneOffset;
|
||||
const localSunset = sunsetHour - lng / 15 - timeZoneOffset;
|
||||
|
||||
const currentHour = now.getHours() + now.getMinutes() / 60;
|
||||
|
||||
const normalizeSunrise = ((localSunrise % 24) + 24) % 24;
|
||||
const normalizeSunset = ((localSunset % 24) + 24) % 24;
|
||||
|
||||
return currentHour >= normalizeSunrise && currentHour < normalizeSunset;
|
||||
}
|
||||
|
||||
function sendLocationToBackend() {
|
||||
if (typeof SessionData === "undefined" || typeof DMSService === "undefined") {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!DMSService.isConnected) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (SessionData.nightModeUseIPLocation) {
|
||||
DMSService.sendRequest("wayland.gamma.setUseIPLocation", {
|
||||
"use": true
|
||||
}, response => {
|
||||
if (response?.error) {
|
||||
log.warn("Theme automation: Failed to enable IP location", response.error);
|
||||
}
|
||||
});
|
||||
return true;
|
||||
} else if (SessionData.latitude !== 0.0 && SessionData.longitude !== 0.0) {
|
||||
DMSService.sendRequest("wayland.gamma.setUseIPLocation", {
|
||||
"use": false
|
||||
}, response => {
|
||||
if (!response.error) {
|
||||
DMSService.sendRequest("wayland.gamma.setLocation", {
|
||||
"latitude": SessionData.latitude,
|
||||
"longitude": SessionData.longitude
|
||||
}, locResp => {
|
||||
if (locResp?.error) {
|
||||
log.warn("Theme automation: Failed to set location", locResp.error);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
Timer {
|
||||
id: locationRetryTimer
|
||||
interval: 1000
|
||||
repeat: true
|
||||
running: false
|
||||
property int retryCount: 0
|
||||
|
||||
onTriggered: {
|
||||
if (root.sendLocationToBackend()) {
|
||||
stop();
|
||||
retryCount = 0;
|
||||
root.evaluate();
|
||||
} else {
|
||||
retryCount++;
|
||||
if (retryCount >= 10) {
|
||||
stop();
|
||||
retryCount = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function start() {
|
||||
root.active = true;
|
||||
|
||||
syncTimeSchedule();
|
||||
syncLocationSchedule();
|
||||
|
||||
const sent = sendLocationToBackend();
|
||||
|
||||
if (!sent && typeof SessionData !== "undefined" && SessionData.themeModeAutoMode === "location") {
|
||||
locationRetryTimer.start();
|
||||
} else {
|
||||
evaluate();
|
||||
}
|
||||
}
|
||||
|
||||
function stop() {
|
||||
root.active = false;
|
||||
if (typeof DMSService !== "undefined" && DMSService.isConnected) {
|
||||
DMSService.sendRequest("theme.auto.setEnabled", {
|
||||
"enabled": false
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,10 @@
|
||||
pragma Singleton
|
||||
|
||||
pragma ComponentBehavior: Bound
|
||||
|
||||
import QtQuick
|
||||
import Quickshell
|
||||
import qs.Common
|
||||
import qs.Common.settings
|
||||
|
||||
Singleton {
|
||||
id: root
|
||||
@@ -26,151 +27,149 @@ Singleton {
|
||||
readonly property var stickyCategories: ["greeter-autologin-sync"]
|
||||
|
||||
function isStickyCategory(category) {
|
||||
return category && stickyCategories.indexOf(category) >= 0
|
||||
return category && stickyCategories.indexOf(category) >= 0;
|
||||
}
|
||||
|
||||
function showToast(message, level = levelInfo, details = "", command = "", category = "") {
|
||||
const now = Date.now()
|
||||
const messageKey = message + level
|
||||
const now = Date.now();
|
||||
const messageKey = message + level;
|
||||
|
||||
if (level === levelError) {
|
||||
const lastTime = lastErrorTime[messageKey] || 0
|
||||
const lastTime = lastErrorTime[messageKey] || 0;
|
||||
if (now - lastTime < errorThrottleMs) {
|
||||
return
|
||||
return;
|
||||
}
|
||||
lastErrorTime[messageKey] = now
|
||||
lastErrorTime[messageKey] = now;
|
||||
}
|
||||
|
||||
if (category && level === levelError) {
|
||||
if (currentCategory === category && toastVisible && currentLevel === levelError) {
|
||||
currentMessage = message
|
||||
currentDetails = details || ""
|
||||
currentCommand = command || ""
|
||||
hasDetails = currentDetails.length > 0 || currentCommand.length > 0
|
||||
resetToastState()
|
||||
currentMessage = message;
|
||||
currentDetails = details || "";
|
||||
currentCommand = command || "";
|
||||
hasDetails = currentDetails.length > 0 || currentCommand.length > 0;
|
||||
resetToastState();
|
||||
if (hasDetails) {
|
||||
toastTimer.interval = 8000
|
||||
toastTimer.interval = 8000;
|
||||
} else {
|
||||
toastTimer.interval = 5000
|
||||
toastTimer.interval = 5000;
|
||||
}
|
||||
toastTimer.restart()
|
||||
return
|
||||
toastTimer.restart();
|
||||
return;
|
||||
}
|
||||
|
||||
toastQueue = toastQueue.filter(t => t.category !== category)
|
||||
toastQueue = toastQueue.filter(t => t.category !== category);
|
||||
}
|
||||
|
||||
const isDuplicate = toastQueue.some(toast =>
|
||||
toast.message === message && toast.level === level
|
||||
)
|
||||
const isDuplicate = toastQueue.some(toast => toast.message === message && toast.level === level);
|
||||
if (isDuplicate) {
|
||||
return
|
||||
return;
|
||||
}
|
||||
|
||||
if (toastQueue.length >= maxQueueSize) {
|
||||
if (level === levelError) {
|
||||
toastQueue = toastQueue.filter(t => t.level !== levelError).slice(0, maxQueueSize - 1)
|
||||
toastQueue = toastQueue.filter(t => t.level !== levelError).slice(0, maxQueueSize - 1);
|
||||
} else {
|
||||
return
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
toastQueue.push({
|
||||
"message": message,
|
||||
"level": level,
|
||||
"details": details,
|
||||
"command": command,
|
||||
"category": category
|
||||
})
|
||||
"message": message,
|
||||
"level": level,
|
||||
"details": details,
|
||||
"command": command,
|
||||
"category": category
|
||||
});
|
||||
if (!toastVisible) {
|
||||
processQueue()
|
||||
processQueue();
|
||||
}
|
||||
}
|
||||
|
||||
function showInfo(message, details = "", command = "", category = "") {
|
||||
showToast(message, levelInfo, details, command, category)
|
||||
showToast(message, levelInfo, details, command, category);
|
||||
}
|
||||
|
||||
function showWarning(message, details = "", command = "", category = "") {
|
||||
showToast(message, levelWarn, details, command, category)
|
||||
showToast(message, levelWarn, details, command, category);
|
||||
}
|
||||
|
||||
function showError(message, details = "", command = "", category = "") {
|
||||
showToast(message, levelError, details, command, category)
|
||||
showToast(message, levelError, details, command, category);
|
||||
}
|
||||
|
||||
function dismissCategory(category) {
|
||||
if (!category) {
|
||||
return
|
||||
return;
|
||||
}
|
||||
|
||||
if (currentCategory === category && toastVisible) {
|
||||
hideToast()
|
||||
return
|
||||
hideToast();
|
||||
return;
|
||||
}
|
||||
|
||||
toastQueue = toastQueue.filter(t => t.category !== category)
|
||||
toastQueue = toastQueue.filter(t => t.category !== category);
|
||||
}
|
||||
|
||||
function hideToast() {
|
||||
toastVisible = false
|
||||
currentMessage = ""
|
||||
currentDetails = ""
|
||||
currentCommand = ""
|
||||
currentCategory = ""
|
||||
hasDetails = false
|
||||
currentLevel = levelInfo
|
||||
toastTimer.stop()
|
||||
resetToastState()
|
||||
toastVisible = false;
|
||||
currentMessage = "";
|
||||
currentDetails = "";
|
||||
currentCommand = "";
|
||||
currentCategory = "";
|
||||
hasDetails = false;
|
||||
currentLevel = levelInfo;
|
||||
toastTimer.stop();
|
||||
resetToastState();
|
||||
if (toastQueue.length > 0) {
|
||||
processQueue()
|
||||
processQueue();
|
||||
}
|
||||
}
|
||||
|
||||
function processQueue() {
|
||||
if (toastQueue.length === 0) {
|
||||
return
|
||||
return;
|
||||
}
|
||||
|
||||
const toast = toastQueue.shift()
|
||||
currentMessage = toast.message
|
||||
currentLevel = toast.level
|
||||
currentDetails = toast.details || ""
|
||||
currentCommand = toast.command || ""
|
||||
currentCategory = toast.category || ""
|
||||
hasDetails = currentDetails.length > 0 || currentCommand.length > 0
|
||||
toastVisible = true
|
||||
resetToastState()
|
||||
const toast = toastQueue.shift();
|
||||
currentMessage = toast.message;
|
||||
currentLevel = toast.level;
|
||||
currentDetails = toast.details || "";
|
||||
currentCommand = toast.command || "";
|
||||
currentCategory = toast.category || "";
|
||||
hasDetails = currentDetails.length > 0 || currentCommand.length > 0;
|
||||
toastVisible = true;
|
||||
resetToastState();
|
||||
|
||||
if (isStickyCategory(toast.category)) {
|
||||
toastTimer.stop()
|
||||
toastTimer.stop();
|
||||
} else if (toast.level === levelError && hasDetails) {
|
||||
toastTimer.interval = 8000
|
||||
toastTimer.start()
|
||||
toastTimer.interval = 8000;
|
||||
toastTimer.start();
|
||||
} else {
|
||||
toastTimer.interval = toast.level === levelError ? 5000 : toast.level === levelWarn ? 3000 : 1500
|
||||
toastTimer.start()
|
||||
toastTimer.interval = toast.level === levelError ? 5000 : toast.level === levelWarn ? 3000 : 1500;
|
||||
toastTimer.start();
|
||||
}
|
||||
}
|
||||
|
||||
signal resetToastState
|
||||
|
||||
function stopTimer() {
|
||||
toastTimer.stop()
|
||||
toastTimer.stop();
|
||||
}
|
||||
|
||||
function restartTimer() {
|
||||
if (isStickyCategory(currentCategory)) {
|
||||
return
|
||||
return;
|
||||
}
|
||||
if (hasDetails && currentLevel === levelError) {
|
||||
toastTimer.interval = 8000
|
||||
toastTimer.restart()
|
||||
toastTimer.interval = 8000;
|
||||
toastTimer.restart();
|
||||
}
|
||||
}
|
||||
|
||||
function clearWallpaperError() {
|
||||
wallpaperErrorStatus = ""
|
||||
wallpaperErrorStatus = "";
|
||||
}
|
||||
|
||||
Timer {
|
||||
@@ -181,4 +180,34 @@ Singleton {
|
||||
repeat: false
|
||||
onTriggered: hideToast()
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: SessionData
|
||||
|
||||
function onLoadErrorOccurred(file, message) {
|
||||
root.showError(I18n.tr("Failed to parse %1").arg(file), message);
|
||||
}
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: Processes
|
||||
|
||||
function onToastRequested(severity, title, body, command, category) {
|
||||
switch (severity) {
|
||||
case root.levelWarn:
|
||||
root.showWarning(title, body, command, category);
|
||||
break;
|
||||
case root.levelError:
|
||||
root.showError(title, body, command, category);
|
||||
break;
|
||||
default:
|
||||
root.showInfo(title, body, command, category);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
function onToastCategoryDismissed(category) {
|
||||
root.dismissCategory(category);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -53,6 +53,7 @@ Singleton {
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
Paths.trashHandler = (path, callback) => trashPath(path, callback);
|
||||
detectProc.running = true;
|
||||
refreshCount();
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
pragma Singleton
|
||||
pragma ComponentBehavior: Bound
|
||||
|
||||
import QtCore
|
||||
import QtQuick
|
||||
import Quickshell
|
||||
import Quickshell.Io
|
||||
@@ -281,4 +282,149 @@ Singleton {
|
||||
onStreamFinished: root.applyCycledWallpaper(text, prevCyclingProcess.currentWallpaper, prevCyclingProcess.targetScreenName, prevCyclingProcess.goToPrevious)
|
||||
}
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: SessionData
|
||||
|
||||
function onLoaded() {
|
||||
root.updateCyclingState();
|
||||
}
|
||||
}
|
||||
|
||||
IpcHandler {
|
||||
target: "wallpaper"
|
||||
|
||||
function get(): string {
|
||||
if (SessionData.perMonitorWallpaper) {
|
||||
return "ERROR: Per-monitor mode enabled. Use getFor(screenName) instead.";
|
||||
}
|
||||
return SessionData.wallpaperPath || "";
|
||||
}
|
||||
|
||||
function set(path: string): string {
|
||||
if (SessionData.perMonitorWallpaper) {
|
||||
return "ERROR: Per-monitor mode enabled. Use setFor(screenName, path) instead.";
|
||||
}
|
||||
|
||||
if (!path) {
|
||||
return "ERROR: No path provided";
|
||||
}
|
||||
|
||||
var absolutePath = path.startsWith("/") ? path : StandardPaths.writableLocation(StandardPaths.HomeLocation) + "/" + path;
|
||||
|
||||
try {
|
||||
SessionData.setWallpaper(absolutePath);
|
||||
return "SUCCESS: Wallpaper set to " + absolutePath;
|
||||
} catch (e) {
|
||||
return "ERROR: Failed to set wallpaper: " + e.toString();
|
||||
}
|
||||
}
|
||||
|
||||
function clear(): string {
|
||||
SessionData.setWallpaper("");
|
||||
SessionData.setPerMonitorWallpaper(false);
|
||||
SessionData.monitorWallpapers = {};
|
||||
SessionData.saveSettings();
|
||||
return "SUCCESS: All wallpapers cleared";
|
||||
}
|
||||
|
||||
function next(): string {
|
||||
if (SessionData.perMonitorWallpaper) {
|
||||
return "ERROR: Per-monitor mode enabled. Use nextFor(screenName) instead.";
|
||||
}
|
||||
|
||||
if (!SessionData.wallpaperPath) {
|
||||
return "ERROR: No wallpaper set";
|
||||
}
|
||||
|
||||
try {
|
||||
root.cycleNextManually();
|
||||
return "SUCCESS: Cycling to next wallpaper";
|
||||
} catch (e) {
|
||||
return "ERROR: Failed to cycle wallpaper: " + e.toString();
|
||||
}
|
||||
}
|
||||
|
||||
function prev(): string {
|
||||
if (SessionData.perMonitorWallpaper) {
|
||||
return "ERROR: Per-monitor mode enabled. Use prevFor(screenName) instead.";
|
||||
}
|
||||
|
||||
if (!SessionData.wallpaperPath) {
|
||||
return "ERROR: No wallpaper set";
|
||||
}
|
||||
|
||||
try {
|
||||
root.cyclePrevManually();
|
||||
return "SUCCESS: Cycling to previous wallpaper";
|
||||
} catch (e) {
|
||||
return "ERROR: Failed to cycle wallpaper: " + e.toString();
|
||||
}
|
||||
}
|
||||
|
||||
function getFor(screenName: string): string {
|
||||
if (!screenName) {
|
||||
return "ERROR: No screen name provided";
|
||||
}
|
||||
return SessionData.getMonitorWallpaper(screenName) || "";
|
||||
}
|
||||
|
||||
function setFor(screenName: string, path: string): string {
|
||||
if (!screenName) {
|
||||
return "ERROR: No screen name provided";
|
||||
}
|
||||
|
||||
if (!path) {
|
||||
return "ERROR: No path provided";
|
||||
}
|
||||
|
||||
var absolutePath = path.startsWith("/") ? path : StandardPaths.writableLocation(StandardPaths.HomeLocation) + "/" + path;
|
||||
|
||||
try {
|
||||
if (!SessionData.perMonitorWallpaper) {
|
||||
SessionData.setPerMonitorWallpaper(true);
|
||||
}
|
||||
SessionData.setMonitorWallpaper(screenName, absolutePath);
|
||||
return "SUCCESS: Wallpaper set for " + screenName + " to " + absolutePath;
|
||||
} catch (e) {
|
||||
return "ERROR: Failed to set wallpaper for " + screenName + ": " + e.toString();
|
||||
}
|
||||
}
|
||||
|
||||
function nextFor(screenName: string): string {
|
||||
if (!screenName) {
|
||||
return "ERROR: No screen name provided";
|
||||
}
|
||||
|
||||
var currentWallpaper = SessionData.getMonitorWallpaper(screenName);
|
||||
if (!currentWallpaper) {
|
||||
return "ERROR: No wallpaper set for " + screenName;
|
||||
}
|
||||
|
||||
try {
|
||||
root.cycleNextForMonitor(screenName);
|
||||
return "SUCCESS: Cycling to next wallpaper for " + screenName;
|
||||
} catch (e) {
|
||||
return "ERROR: Failed to cycle wallpaper for " + screenName + ": " + e.toString();
|
||||
}
|
||||
}
|
||||
|
||||
function prevFor(screenName: string): string {
|
||||
if (!screenName) {
|
||||
return "ERROR: No screen name provided";
|
||||
}
|
||||
|
||||
var currentWallpaper = SessionData.getMonitorWallpaper(screenName);
|
||||
if (!currentWallpaper) {
|
||||
return "ERROR: No wallpaper set for " + screenName;
|
||||
}
|
||||
|
||||
try {
|
||||
root.cyclePrevForMonitor(screenName);
|
||||
return "SUCCESS: Cycling to previous wallpaper for " + screenName;
|
||||
} catch (e) {
|
||||
return "ERROR: Failed to cycle wallpaper for " + screenName + ": " + e.toString();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user