1
0
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:
bbedward
2026-07-26 23:22:22 -04:00
parent bab2078dfd
commit c67b185076
113 changed files with 1467 additions and 3254 deletions
Generated
+3 -3
View File
@@ -3,11 +3,11 @@
"dank-qml-common": { "dank-qml-common": {
"flake": false, "flake": false,
"locked": { "locked": {
"lastModified": 1784935106, "lastModified": 1785121997,
"narHash": "sha256-aVgOBRynme6XNKYCZlf/oCjPDZFwddyUQPRRkEupC3c=", "narHash": "sha256-/MslqFCpjxws8DZqipEKCCTBa0m/SCV3+v1NRT6EuvQ=",
"owner": "AvengeMedia", "owner": "AvengeMedia",
"repo": "dank-qml-common", "repo": "dank-qml-common",
"rev": "a172b39841d8f42bac46ac133b76cade1fae91b4", "rev": "7cc4564e5903a2955fe7da76969f20252cacf9bf",
"type": "github" "type": "github"
}, },
"original": { "original": {
-29
View File
@@ -1,29 +0,0 @@
pragma Singleton
pragma ComponentBehavior: Bound
import QtQuick
import Quickshell
import qs.Common
Singleton {
id: root
function clearImageCache() {
Quickshell.execDetached(["rm", "-rf", Paths.stringify(Paths.imagecache)]);
Paths.mkdir(Paths.imagecache);
}
function clearOldCache(ageInMinutes) {
Quickshell.execDetached(["find", Paths.stringify(Paths.imagecache), "-name", "*.png", "-mmin", `+${ageInMinutes}`, "-delete"]);
}
function clearCacheForSize(size) {
Quickshell.execDetached(["find", Paths.stringify(Paths.imagecache), "-name", `*@${size}x${size}.png`, "-delete"]);
}
function getCacheSize(callback) {
Proc.runCommand("cache_size", ["du", "-sm", Paths.stringify(Paths.imagecache)], function (output, exitCode) {
const sizeMB = parseInt(output.split("\t")[0]) || 0;
callback(sizeMB);
});
}
}
@@ -114,26 +114,6 @@ function withRevision(descriptor, revision) {
return next; return next;
} }
function withAnimationOffset(descriptor, x, y) {
var next = normalize(descriptor);
next.animationOffset = {
"x": x === undefined ? next.animationOffset.x : _number(x, next.animationOffset.x),
"y": y === undefined ? next.animationOffset.y : _number(y, next.animationOffset.y)
};
return next;
}
function withBodyRect(descriptor, x, y, width, height) {
var next = normalize(descriptor);
next.bodyRect = {
"x": x === undefined ? next.bodyRect.x : _number(x, next.bodyRect.x),
"y": y === undefined ? next.bodyRect.y : _number(y, next.bodyRect.y),
"width": width === undefined ? next.bodyRect.width : Math.max(0, _number(width, next.bodyRect.width)),
"height": height === undefined ? next.bodyRect.height : Math.max(0, _number(height, next.bodyRect.height))
};
return next;
}
function same(a, b, threshold) { function same(a, b, threshold) {
if (!a || !b) if (!a || !b)
return false; return false;
@@ -162,21 +162,6 @@ function fillBounds(rect, side, seamOverlap, dpr) {
}; };
} }
function clipEnvelope(rect, side, radii, seamOverlap, dpr) {
var fill = fillBounds(rect, side, seamOverlap, dpr);
var chrome = chromeBounds(fill, side, radii.start, radii.end, radii.farExtent, dpr);
return {
"x": chrome.x,
"y": chrome.y,
"width": chrome.width,
"height": chrome.height,
"bodyX": snap(fill.x - chrome.x, dpr),
"bodyY": snap(fill.y - chrome.y, dpr),
"bodyWidth": fill.width,
"bodyHeight": fill.height
};
}
function blurRegions(descriptor, rect, radii, dpr) { function blurRegions(descriptor, rect, radii, dpr) {
var side = descriptor.barSide; var side = descriptor.barSide;
var regions = [bodyRect(rect, dpr)]; var regions = [bodyRect(rect, dpr)];
@@ -219,14 +204,3 @@ function unionBounds(rects, padding, dpr) {
"height": Math.max(0, snap(maxY - minY + pad * 2, dpr)) "height": Math.max(0, snap(maxY - minY + pad * 2, dpr))
}; };
} }
function shadowSourceBounds(descriptor, rect, radii, padding, dpr) {
return unionBounds(blurRegions(descriptor, rect, radii, dpr), padding, dpr);
}
function stableEqual(a, b, dpr) {
if (!a || !b)
return false;
var threshold = 0.5 / (dpr || 1);
return Math.abs(a.x - b.x) < threshold && Math.abs(a.y - b.y) < threshold && Math.abs(a.width - b.width) < threshold && Math.abs(a.height - b.height) < threshold;
}
-10
View File
@@ -44,16 +44,6 @@ function connectorX(barSide, baseX, bodyWidth, placement, spacing, radius) {
return barSide === "left" ? s : s - w; return barSide === "left" ? s : s - w;
} }
function connectorY(barSide, baseY, bodyHeight, placement, spacing, radius) {
var s = seamY(barSide, baseY, bodyHeight, placement);
var h = connectorHeight(barSide, spacing, radius);
if (barSide === "top")
return s;
if (barSide === "bottom")
return s - h;
return placement === "left" ? s - h : s;
}
// Which corner of the connector's bounding rect hosts the concave arc that // Which corner of the connector's bounding rect hosts the concave arc that
// carves into the body. Used for arc-sweep orientation. // carves into the body. Used for arc-sweep orientation.
function arcCorner(barSide, placement) { function arcCorner(barSide, placement) {
+72
View File
@@ -0,0 +1,72 @@
.pragma library
function formatRate(bytesPerSec, gbDecimals) {
if (bytesPerSec < 1024)
return bytesPerSec.toFixed(0) + " B/s";
if (bytesPerSec < 1024 * 1024)
return (bytesPerSec / 1024).toFixed(1) + " KB/s";
if (bytesPerSec < 1024 * 1024 * 1024)
return (bytesPerSec / (1024 * 1024)).toFixed(1) + " MB/s";
return (bytesPerSec / (1024 * 1024 * 1024)).toFixed(gbDecimals ?? 2) + " GB/s";
}
function formatBytes(bytes) {
if (bytes < 1024)
return bytes.toFixed(0) + "B";
if (bytes < 1024 * 1024)
return (bytes / 1024).toFixed(0) + "K";
if (bytes < 1024 * 1024 * 1024)
return (bytes / (1024 * 1024)).toFixed(1) + "M";
return (bytes / (1024 * 1024 * 1024)).toFixed(1) + "G";
}
function formatIsoTime(isoString) {
if (!isoString)
return "";
try {
const date = new Date(isoString);
if (isNaN(date.getTime()))
return "";
return date.toLocaleTimeString(Qt.locale(), "HH:mm");
} catch (e) {
return "";
}
}
function formatRemaining(ms, zeroText, minText, hText, hmText) {
if (ms <= 0)
return zeroText;
const totalMinutes = Math.ceil(ms / 60000);
if (totalMinutes < 60)
return minText.arg(totalMinutes);
const hours = Math.floor(totalMinutes / 60);
const mins = totalMinutes - hours * 60;
if (mins === 0)
return hText.arg(hours);
return hmText.arg(hours).arg(mins);
}
function pad2(n) {
return n < 10 ? "0" + n : "" + n;
}
function formatUntil(ts, use24h) {
if (!ts)
return "";
const d = new Date(ts);
const hours = d.getHours();
const minutes = d.getMinutes();
if (use24h)
return pad2(hours) + ":" + pad2(minutes);
const suffix = hours >= 12 ? "PM" : "AM";
const h12 = ((hours + 11) % 12) + 1;
return h12 + ":" + pad2(minutes) + " " + suffix;
}
function addToHistory(arr, val, max) {
const newArr = arr.slice();
newArr.push(val);
if (newArr.length > max)
newArr.shift();
return newArr;
}
-7
View File
@@ -1370,10 +1370,3 @@ function buildDmsAction(baseKey, args) {
return parts.join(" "); return parts.join(" ");
} }
function getScreenshotOptions() {
return [
{ id: "write-to-disk", label: "Save to disk", type: "bool" },
{ id: "show-pointer", label: "Show pointer", type: "bool" }
];
}
+15 -5
View File
@@ -22,6 +22,10 @@ Singleton {
readonly property url imagecache: `${cache}/imagecache` readonly property url imagecache: `${cache}/imagecache`
property var iconResolver: null
property var desktopIconResolver: null
property var trashHandler: null
Component.onCompleted: mkdir(imagecache) Component.onCompleted: mkdir(imagecache)
function stringify(path: url): string { function stringify(path: url): string {
@@ -88,7 +92,7 @@ Singleton {
function themedIconPath(name: string): string { function themedIconPath(name: string): string {
if (!name) if (!name)
return ""; return "";
const themed = (typeof IconThemeService !== "undefined") ? IconThemeService.resolve(name) : ""; const themed = iconResolver ? iconResolver(name) : "";
if (themed) if (themed)
return themed; return themed;
return Quickshell.iconPath(name, true); return Quickshell.iconPath(name, true);
@@ -105,11 +109,15 @@ Singleton {
return moddedId; return moddedId;
return themedIconPath(moddedId); return themedIconPath(moddedId);
} }
return themedIconPath(iconName) || DesktopService.resolveIconPath(iconName); if (!desktopIconResolver)
return themedIconPath(iconName);
return themedIconPath(iconName) || desktopIconResolver(iconName);
} }
function trashPath(path: string, callback): void { function trashPath(path: string, callback): void {
TrashService.trashPath(path, callback); if (!trashHandler)
return;
trashHandler(path, callback);
} }
function copyPathToClipboard(path: string): void { function copyPathToClipboard(path: string): void {
@@ -125,7 +133,7 @@ Singleton {
return toFileUrl(expandTilde(target)); return toFileUrl(expandTilde(target));
if (target.startsWith("file://")) if (target.startsWith("file://"))
return target; return target;
const themed = (typeof IconThemeService !== "undefined") ? IconThemeService.resolve(target) : ""; const themed = iconResolver ? iconResolver(target) : "";
if (themed) if (themed)
return themed; return themed;
return "image://icon/" + target; return "image://icon/" + target;
@@ -148,7 +156,9 @@ Singleton {
if (icon && icon !== "") if (icon && icon !== "")
return icon; return icon;
return DesktopService.resolveIconPath(appId); if (!desktopIconResolver)
return "";
return desktopIconResolver(appId);
} }
function getAppName(appId: string, desktopEntry: var): string { function getAppName(appId: string, desktopEntry: var): string {
+27
View File
@@ -0,0 +1,27 @@
.pragma library
function findParentFlickable(item) {
while (item) {
if (item.hasOwnProperty("contentY") && item.hasOwnProperty("contentItem"))
return item;
item = item.parent;
}
return null;
}
function findSettings(item) {
while (item) {
if (item.saveValue !== undefined && item.loadValue !== undefined)
return item;
item = item.parent;
}
return null;
}
function normalizePinList(value) {
if (Array.isArray(value))
return value.filter(v => v);
if (typeof value === "string" && value.length > 0)
return [value];
return [];
}
+9 -200
View File
@@ -16,6 +16,10 @@ Singleton {
readonly property int sessionConfigVersion: 3 readonly property int sessionConfigVersion: 3
signal loaded
signal brightnessDisplayHintChanged(string deviceName)
signal loadErrorOccurred(string file, string message)
property bool _parseError: false property bool _parseError: false
property bool _hasLoaded: false property bool _hasLoaded: false
property bool _isReadOnly: false property bool _isReadOnly: false
@@ -276,15 +280,14 @@ Singleton {
if (typeof Theme !== "undefined") if (typeof Theme !== "undefined")
Theme.generateSystemThemesFromCurrentTheme(); Theme.generateSystemThemesFromCurrentTheme();
if (typeof WallpaperCyclingService !== "undefined") loaded();
WallpaperCyclingService.updateCyclingState();
_checkSessionWritable(); _checkSessionWritable();
} catch (e) { } catch (e) {
_parseError = true; _parseError = true;
const msg = e.message; const msg = e.message;
log.error("Failed to parse session.json - file will not be overwritten."); log.error("Failed to parse session.json - file will not be overwritten.");
Qt.callLater(() => ToastService.showError(I18n.tr("Failed to parse %1").arg("session.json"), msg)); Qt.callLater(() => loadErrorOccurred("session.json", msg));
} }
} }
@@ -358,13 +361,12 @@ Singleton {
if (typeof Theme !== "undefined") if (typeof Theme !== "undefined")
Theme.generateSystemThemesFromCurrentTheme(); Theme.generateSystemThemesFromCurrentTheme();
if (typeof WallpaperCyclingService !== "undefined") loaded();
WallpaperCyclingService.updateCyclingState();
} catch (e) { } catch (e) {
_parseError = true; _parseError = true;
const msg = e.message; const msg = e.message;
log.error("Failed to parse session.json - file will not be overwritten."); log.error("Failed to parse session.json - file will not be overwritten.");
Qt.callLater(() => ToastService.showError(I18n.tr("Failed to parse %1").arg("session.json"), msg)); Qt.callLater(() => loadErrorOccurred("session.json", msg));
} }
} }
@@ -465,11 +467,6 @@ Singleton {
saveSettings(); saveSettings();
} }
function setWallpaperPath(path) {
wallpaperPath = path;
saveSettings();
}
function setWallpaper(imagePath) { function setWallpaper(imagePath) {
wallpaperPath = imagePath; wallpaperPath = imagePath;
if (perModeWallpaper) { if (perModeWallpaper) {
@@ -848,11 +845,6 @@ Singleton {
saveSettings(); saveSettings();
} }
function setNightModeLocationProvider(provider) {
nightModeLocationProvider = provider;
saveSettings();
}
function setThemeModeAutoEnabled(enabled) { function setThemeModeAutoEnabled(enabled) {
themeModeAutoEnabled = enabled; themeModeAutoEnabled = enabled;
saveSettings(); saveSettings();
@@ -941,10 +933,6 @@ Singleton {
setBarPinnedApps(currentPinned); setBarPinnedApps(currentPinned);
} }
function isBarPinnedApp(appId) {
return appId && barPinnedApps.indexOf(appId) !== -1;
}
function hideTrayId(trayId) { function hideTrayId(trayId) {
if (!trayId) if (!trayId)
return; return;
@@ -1007,11 +995,6 @@ Singleton {
saveSettings(); saveSettings();
} }
function setLaunchPrefix(prefix) {
launchPrefix = prefix;
saveSettings();
}
function setLastBrightnessDevice(device) { function setLastBrightnessDevice(device) {
lastBrightnessDevice = device; lastBrightnessDevice = device;
saveSettings(); saveSettings();
@@ -1026,10 +1009,7 @@ Singleton {
} }
brightnessExponentialDevices = newSettings; brightnessExponentialDevices = newSettings;
saveSettings(); saveSettings();
brightnessDisplayHintChanged(deviceName);
if (typeof DisplayService !== "undefined") {
DisplayService.updateDeviceBrightnessDisplay(deviceName);
}
} }
function getBrightnessExponential(deviceName) { function getBrightnessExponential(deviceName) {
@@ -1043,10 +1023,6 @@ Singleton {
saveSettings(); saveSettings();
} }
function getBrightnessUserSetValue(deviceName) {
return brightnessUserSetValues[deviceName];
}
function clearBrightnessUserSetValue(deviceName) { function clearBrightnessUserSetValue(deviceName) {
var newValues = Object.assign({}, brightnessUserSetValues); var newValues = Object.assign({}, brightnessUserSetValues);
delete newValues[deviceName]; delete newValues[deviceName];
@@ -1070,21 +1046,6 @@ Singleton {
return value !== undefined ? value : 1.2; return value !== undefined ? value : 1.2;
} }
function setSelectedGpuIndex(index) {
selectedGpuIndex = index;
saveSettings();
}
function setNvidiaGpuTempEnabled(enabled) {
nvidiaGpuTempEnabled = enabled;
saveSettings();
}
function setNonNvidiaGpuTempEnabled(enabled) {
nonNvidiaGpuTempEnabled = enabled;
saveSettings();
}
function setEnabledGpuPciIds(pciIds) { function setEnabledGpuPciIds(pciIds) {
enabledGpuPciIds = pciIds; enabledGpuPciIds = pciIds;
saveSettings(); saveSettings();
@@ -1200,15 +1161,6 @@ Singleton {
return deviceMaxVolumes[nodeName] ?? 100; return deviceMaxVolumes[nodeName] ?? 100;
} }
function removeDeviceMaxVolume(nodeName) {
if (!nodeName)
return;
const updated = Object.assign({}, deviceMaxVolumes);
delete updated[nodeName];
deviceMaxVolumes = updated;
saveSettings();
}
function updateLocale() { function updateLocale() {
if (!locale) { if (!locale) {
I18n._pickTranslation(); I18n._pickTranslation();
@@ -1272,12 +1224,6 @@ Singleton {
saveSettings(); saveSettings();
} }
function clearLauncherHistory() {
launcherLastQuery = "";
launcherSearchHistory = [];
saveSettings();
}
function setAppDrawerLastMode(mode) { function setAppDrawerLastMode(mode) {
appDrawerLastMode = mode; appDrawerLastMode = mode;
saveSettings(); saveSettings();
@@ -1417,141 +1363,4 @@ Singleton {
} }
} }
} }
IpcHandler {
target: "wallpaper"
function get(): string {
if (root.perMonitorWallpaper) {
return "ERROR: Per-monitor mode enabled. Use getFor(screenName) instead.";
}
return root.wallpaperPath || "";
}
function set(path: string): string {
if (root.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 {
root.setWallpaper(absolutePath);
return "SUCCESS: Wallpaper set to " + absolutePath;
} catch (e) {
return "ERROR: Failed to set wallpaper: " + e.toString();
}
}
function clear(): string {
root.setWallpaper("");
root.setPerMonitorWallpaper(false);
root.monitorWallpapers = {};
root.saveSettings();
return "SUCCESS: All wallpapers cleared";
}
function next(): string {
if (root.perMonitorWallpaper) {
return "ERROR: Per-monitor mode enabled. Use nextFor(screenName) instead.";
}
if (!root.wallpaperPath) {
return "ERROR: No wallpaper set";
}
try {
WallpaperCyclingService.cycleNextManually();
return "SUCCESS: Cycling to next wallpaper";
} catch (e) {
return "ERROR: Failed to cycle wallpaper: " + e.toString();
}
}
function prev(): string {
if (root.perMonitorWallpaper) {
return "ERROR: Per-monitor mode enabled. Use prevFor(screenName) instead.";
}
if (!root.wallpaperPath) {
return "ERROR: No wallpaper set";
}
try {
WallpaperCyclingService.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 root.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 (!root.perMonitorWallpaper) {
root.setPerMonitorWallpaper(true);
}
root.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 = root.getMonitorWallpaper(screenName);
if (!currentWallpaper) {
return "ERROR: No wallpaper set for " + screenName;
}
try {
WallpaperCyclingService.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 = root.getMonitorWallpaper(screenName);
if (!currentWallpaper) {
return "ERROR: No wallpaper set for " + screenName;
}
try {
WallpaperCyclingService.cyclePrevForMonitor(screenName);
return "SUCCESS: Cycling to previous wallpaper for " + screenName;
} catch (e) {
return "ERROR: Failed to cycle wallpaper for " + screenName + ": " + e.toString();
}
}
}
} }
+19 -465
View File
@@ -712,16 +712,23 @@ Singleton {
property bool notepadUseCompositorGap: false property bool notepadUseCompositorGap: false
property int notepadEdgeGap: 0 property int notepadEdgeGap: 0
property string activeCompositor: ""
// Compositor layout gap when enabled and available, else the manual value. // Compositor layout gap when enabled and available, else the manual value.
readonly property int notepadEffectiveEdgeGap: { readonly property int notepadEffectiveEdgeGap: {
if (notepadUseCompositorGap) { if (notepadUseCompositorGap) {
var g = -1; var g = -1;
if (CompositorService.isNiri) switch (activeCompositor) {
case "niri":
g = niriLayoutGapsOverride; g = niriLayoutGapsOverride;
else if (CompositorService.isHyprland) break;
case "hyprland":
g = hyprlandLayoutGapsOverride; g = hyprlandLayoutGapsOverride;
else if (CompositorService.isMango) break;
case "mango":
g = mangoLayoutGapsOverride; g = mangoLayoutGapsOverride;
break;
}
if (g >= 0) if (g >= 0)
return g; return g;
} }
@@ -1126,44 +1133,6 @@ Singleton {
saveSettings(); saveSettings();
} }
function getSystemMonitorVariants() {
return systemMonitorVariants || [];
}
function createSystemMonitorVariant(name, config) {
const id = "sysmon_" + Date.now() + "_" + Math.random().toString(36).substr(2, 9);
const variant = {
id: id,
name: name,
config: config || getDefaultSystemMonitorConfig()
};
const variants = JSON.parse(JSON.stringify(systemMonitorVariants || []));
variants.push(variant);
systemMonitorVariants = variants;
saveSettings();
return variant;
}
function updateSystemMonitorVariant(variantId, updates) {
const variants = JSON.parse(JSON.stringify(systemMonitorVariants || []));
const idx = variants.findIndex(v => v.id === variantId);
if (idx === -1)
return;
Object.assign(variants[idx], updates);
systemMonitorVariants = variants;
saveSettings();
}
function removeSystemMonitorVariant(variantId) {
const variants = (systemMonitorVariants || []).filter(v => v.id !== variantId);
systemMonitorVariants = variants;
saveSettings();
}
function getSystemMonitorVariant(variantId) {
return (systemMonitorVariants || []).find(v => v.id === variantId) || null;
}
function getDefaultSystemMonitorConfig() { function getDefaultSystemMonitorConfig() {
return { return {
showHeader: true, showHeader: true,
@@ -1304,70 +1273,6 @@ Singleton {
return (desktopWidgetInstances || []).find(inst => inst.id === instanceId) || null; return (desktopWidgetInstances || []).find(inst => inst.id === instanceId) || null;
} }
function getDesktopWidgetInstancesOfType(widgetType) {
return (desktopWidgetInstances || []).filter(inst => inst.widgetType === widgetType);
}
function getEnabledDesktopWidgetInstances() {
return (desktopWidgetInstances || []).filter(inst => inst.enabled);
}
function moveDesktopWidgetInstance(instanceId, direction) {
const instances = JSON.parse(JSON.stringify(desktopWidgetInstances || []));
const idx = instances.findIndex(inst => inst.id === instanceId);
if (idx === -1)
return false;
const targetIdx = direction === "up" ? idx - 1 : idx + 1;
if (targetIdx < 0 || targetIdx >= instances.length)
return false;
const temp = instances[idx];
instances[idx] = instances[targetIdx];
instances[targetIdx] = temp;
desktopWidgetInstances = instances;
saveSettings();
return true;
}
function reorderDesktopWidgetInstance(instanceId, newIndex) {
const instances = JSON.parse(JSON.stringify(desktopWidgetInstances || []));
const idx = instances.findIndex(inst => inst.id === instanceId);
if (idx === -1 || newIndex < 0 || newIndex >= instances.length)
return false;
const [item] = instances.splice(idx, 1);
instances.splice(newIndex, 0, item);
desktopWidgetInstances = instances;
saveSettings();
return true;
}
function reorderDesktopWidgetInstanceInGroup(instanceId, groupId, newIndexInGroup) {
const instances = JSON.parse(JSON.stringify(desktopWidgetInstances || []));
const groups = desktopWidgetGroups || [];
const groupMatches = inst => {
if (groupId === null)
return !inst.group || !groups.some(g => g.id === inst.group);
return inst.group === groupId;
};
const groupInstances = instances.filter(groupMatches);
const currentGroupIdx = groupInstances.findIndex(inst => inst.id === instanceId);
if (currentGroupIdx === -1 || currentGroupIdx === newIndexInGroup)
return false;
if (newIndexInGroup < 0 || newIndexInGroup >= groupInstances.length)
return false;
const globalIdx = instances.findIndex(inst => inst.id === instanceId);
if (globalIdx === -1)
return false;
const [item] = instances.splice(globalIdx, 1);
const targetInstance = groupInstances[newIndexInGroup];
let targetGlobalIdx = instances.findIndex(inst => inst.id === targetInstance.id);
if (newIndexInGroup > currentGroupIdx)
targetGlobalIdx++;
instances.splice(targetGlobalIdx, 0, item);
desktopWidgetInstances = instances;
saveSettings();
return true;
}
function moveDesktopWidgetInstanceToGroup(instanceId, groupId, newIndexInGroup) { function moveDesktopWidgetInstanceToGroup(instanceId, groupId, newIndexInGroup) {
const instances = JSON.parse(JSON.stringify(desktopWidgetInstances || [])); const instances = JSON.parse(JSON.stringify(desktopWidgetInstances || []));
const groups = desktopWidgetGroups || []; const groups = desktopWidgetGroups || [];
@@ -1433,22 +1338,14 @@ Singleton {
saveSettings(); saveSettings();
} }
function getDesktopWidgetGroup(groupId) {
return (desktopWidgetGroups || []).find(g => g.id === groupId) || null;
}
function getDesktopWidgetInstancesByGroup(groupId) {
return (desktopWidgetInstances || []).filter(inst => inst.group === groupId);
}
function getUngroupedDesktopWidgetInstances() {
return (desktopWidgetInstances || []).filter(inst => !inst.group);
}
signal forceDankBarLayoutRefresh signal forceDankBarLayoutRefresh
signal forceDockLayoutRefresh signal forceDockLayoutRefresh
signal widgetDataChanged signal widgetDataChanged
signal workspaceIconsUpdated signal workspaceIconsUpdated
signal compositorLayoutRefreshNeeded(bool frame)
signal compositorInputRefreshNeeded
signal compositorCursorRefreshNeeded
signal notificationPopupsInvalidated
function refreshAuthAvailability() { function refreshAuthAvailability() {
Processes.detectAuthCapabilities(); Processes.detectAuthCapabilities();
@@ -1483,31 +1380,15 @@ Singleton {
} }
function updateCompositorLayout() { function updateCompositorLayout() {
if (typeof CompositorService === "undefined") compositorLayoutRefreshNeeded(false);
return;
if (CompositorService.isNiri && typeof NiriService !== "undefined")
NiriService.generateNiriLayoutConfig();
if (CompositorService.isHyprland && typeof HyprlandService !== "undefined")
HyprlandService.generateLayoutConfig();
if (CompositorService.isMango && typeof MangoService !== "undefined")
MangoService.generateLayoutConfig();
} }
function updateCompositorInput() { function updateCompositorInput() {
if (typeof CompositorService === "undefined") compositorInputRefreshNeeded();
return;
if (CompositorService.isNiri && typeof NiriService !== "undefined")
NiriService.generateNiriInputConfig();
} }
function updateFrameCompositorLayout() { function updateFrameCompositorLayout() {
// Generate before begin() so compositor readiness is already pending at transitionRequested compositorLayoutRefreshNeeded(true);
if (typeof CompositorService !== "undefined") {
if (CompositorService.isNiri && typeof NiriService !== "undefined")
NiriService.generateNiriLayoutConfig(true);
if (CompositorService.isHyprland && typeof HyprlandService !== "undefined")
HyprlandService.generateLayoutConfig(true);
}
FrameTransitionState.begin(); FrameTransitionState.begin();
} }
@@ -2160,14 +2041,6 @@ Singleton {
return showSeconds ? "h:mm:ss AP" : "h:mm AP"; return showSeconds ? "h:mm:ss AP" : "h:mm AP";
} }
function getEffectiveClockDateFormat() {
return clockDateFormat && clockDateFormat.length > 0 ? clockDateFormat : "ddd d";
}
function getEffectiveLockDateFormat() {
return lockDateFormat && lockDateFormat.length > 0 ? lockDateFormat : Locale.LongFormat;
}
function initializeListModels() { function initializeListModels() {
const defaultBar = barConfigs[0] || getBarConfig("default"); const defaultBar = barConfigs[0] || getBarConfig("default");
if (defaultBar) { if (defaultBar) {
@@ -2180,39 +2053,6 @@ Singleton {
widgetDataChanged(); widgetDataChanged();
} }
function hasNamedWorkspaces() {
if (typeof NiriService === "undefined" || !CompositorService.isNiri)
return false;
for (var i = 0; i < NiriService.allWorkspaces.length; i++) {
var ws = NiriService.allWorkspaces[i];
if (ws.name && ws.name.trim() !== "")
return true;
}
return false;
}
function getNamedWorkspaces() {
var namedWorkspaces = [];
if (typeof NiriService === "undefined" || !CompositorService.isNiri)
return namedWorkspaces;
for (const ws of NiriService.allWorkspaces) {
if (ws.name && ws.name.trim() !== "") {
namedWorkspaces.push(ws.name);
}
}
return namedWorkspaces;
}
function getPopupYPosition(barHeight) {
const defaultBar = barConfigs[0] || getBarConfig("default");
const gothOffset = defaultBar?.gothCornersEnabled ? Theme.cornerRadius : 0;
const spacing = defaultBar?.spacing ?? 4;
const bottomGap = defaultBar?.bottomGap ?? 0;
return barHeight + spacing + bottomGap - gothOffset + Theme.popupDistance;
}
function getPopupTriggerPosition(pos, screen, barThickness, widgetWidth, barSpacing, barPosition, barConfig) { function getPopupTriggerPosition(pos, screen, barThickness, widgetWidth, barSpacing, barPosition, barConfig) {
const relativeX = pos.x; const relativeX = pos.x;
const relativeY = pos.y; const relativeY = pos.y;
@@ -2506,51 +2346,10 @@ Singleton {
updateBarConfigs(); updateBarConfigs();
if (positionChanged) { if (positionChanged) {
NotificationService.dismissAllPopups(); notificationPopupsInvalidated();
} }
} }
function checkBarCollisions(barId) {
const bar = getBarConfig(barId);
if (!bar || !bar.enabled)
return [];
const conflicts = [];
const enabledBars = getEnabledBarConfigs();
for (var i = 0; i < enabledBars.length; i++) {
const other = enabledBars[i];
if (other.id === barId)
continue;
const samePosition = bar.position === other.position;
if (!samePosition)
continue;
const barScreens = bar.screenPreferences || ["all"];
const otherScreens = other.screenPreferences || ["all"];
const hasAll = barScreens.includes("all") || otherScreens.includes("all");
if (hasAll) {
conflicts.push({
"barId": other.id,
"barName": other.name,
"reason": "Same position on all screens"
});
continue;
}
const overlapping = barScreens.some(screen => otherScreens.includes(screen));
if (overlapping) {
conflicts.push({
"barId": other.id,
"barName": other.name,
"reason": "Same position on overlapping screens"
});
}
}
return conflicts;
}
function deleteBarConfig(barId) { function deleteBarConfig(barId) {
if (barId === "default") if (barId === "default")
return; return;
@@ -2699,38 +2498,6 @@ Singleton {
return filtered; return filtered;
} }
function getFrameFilteredScreens() {
var prefs = frameScreenPreferences || ["all"];
if (!prefs || prefs.length === 0 || prefs.includes("all")) {
return Quickshell.screens;
}
return Quickshell.screens.filter(screen => isScreenInPreferences(screen, prefs));
}
function getActiveBarEdgeForScreen(screen) {
if (!screen)
return "";
for (var i = 0; i < barConfigs.length; i++) {
var bc = barConfigs[i];
if (!bc.enabled)
continue;
var prefs = bc.screenPreferences || ["all"];
if (!prefs.includes("all") && !isScreenInPreferences(screen, prefs))
continue;
switch (bc.position ?? 0) {
case SettingsData.Position.Top:
return "top";
case SettingsData.Position.Bottom:
return "bottom";
case SettingsData.Position.Left:
return "left";
case SettingsData.Position.Right:
return "right";
}
}
return "";
}
function getActiveBarEdgesForScreen(screen) { function getActiveBarEdgesForScreen(screen) {
if (!screen) if (!screen)
return []; return [];
@@ -2796,46 +2563,6 @@ Singleton {
return edges.includes(side) ? frameBarSize : frameThickness; return edges.includes(side) ? frameBarSize : frameThickness;
} }
function getActiveBarThicknessForScreen(screen) {
if (frameEnabled)
return frameBarSize;
if (!screen)
return frameThickness;
for (var i = 0; i < barConfigs.length; i++) {
var bc = barConfigs[i];
if (!bc.enabled)
continue;
var prefs = bc.screenPreferences || ["all"];
if (!prefs.includes("all") && !isScreenInPreferences(screen, prefs))
continue;
const innerPadding = bc.innerPadding ?? 4;
const barT = Math.max(26 + innerPadding * 0.6, Theme.barHeight - 4 - (8 - innerPadding));
const spacing = bc.spacing ?? 4;
const bottomGap = bc.bottomGap ?? 0;
return barT + spacing + bottomGap;
}
return frameThickness;
}
function sendTestNotifications() {
NotificationService.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;
}
function setMatugenScheme(scheme) { function setMatugenScheme(scheme) {
var normalized = scheme || "scheme-tonal-spot"; var normalized = scheme || "scheme-tonal-spot";
if (matugenScheme === normalized) if (matugenScheme === normalized)
@@ -2852,15 +2579,6 @@ Singleton {
set("matugenContrast", value); set("matugenContrast", value);
} }
function setRunUserMatugenTemplates(enabled) {
if (runUserMatugenTemplates === enabled)
return;
set("runUserMatugenTemplates", enabled);
if (typeof Theme !== "undefined") {
Theme.generateSystemThemesFromCurrentTheme();
}
}
function setMatugenTargetMonitor(monitorName) { function setMatugenTargetMonitor(monitorName) {
if (matugenTargetMonitor === monitorName) if (matugenTargetMonitor === monitorName)
return; return;
@@ -2879,11 +2597,6 @@ Singleton {
SessionData.setWeatherLocation(displayName, coordinates); SessionData.setWeatherLocation(displayName, coordinates);
} }
function setIconTheme(themeName) {
const light = iconThemePerMode && typeof SessionData !== "undefined" && SessionData.isLightMode;
setIconThemeForMode(themeName, light);
}
function setIconThemeForMode(themeName, light) { function setIconThemeForMode(themeName, light) {
if (light) if (light)
iconThemeLight = themeName; iconThemeLight = themeName;
@@ -2929,20 +2642,7 @@ Singleton {
// https://github.com/Supreeeme/xwayland-satellite/issues/104 // https://github.com/Supreeeme/xwayland-satellite/issues/104
// no idea if this matters on other compositors but we also set XCURSOR stuff in the launcher // no idea if this matters on other compositors but we also set XCURSOR stuff in the launcher
function updateCompositorCursor() { function updateCompositorCursor() {
if (typeof CompositorService === "undefined") compositorCursorRefreshNeeded();
return;
if (CompositorService.isNiri && typeof NiriService !== "undefined") {
NiriService.generateNiriCursorConfig();
return;
}
if (CompositorService.isHyprland && typeof HyprlandService !== "undefined") {
HyprlandService.generateCursorConfig();
return;
}
if (CompositorService.isMango && typeof MangoService !== "undefined") {
MangoService.generateCursorConfig();
return;
}
} }
function updateXResources() { function updateXResources() {
@@ -3010,20 +2710,6 @@ Singleton {
return env; return env;
} }
function setGtkThemingEnabled(enabled) {
set("gtkThemingEnabled", enabled);
if (enabled && typeof Theme !== "undefined") {
Theme.generateSystemThemesFromCurrentTheme();
}
}
function setQtThemingEnabled(enabled) {
set("qtThemingEnabled", enabled);
if (enabled && typeof Theme !== "undefined") {
Theme.generateSystemThemesFromCurrentTheme();
}
}
function setShowDock(enabled) { function setShowDock(enabled) {
showDock = enabled; showDock = enabled;
const defaultBar = barConfigs[0] || getBarConfig("default"); const defaultBar = barConfigs[0] || getBarConfig("default");
@@ -3069,16 +2755,6 @@ Singleton {
Qt.callLater(() => forceDockLayoutRefresh()); Qt.callLater(() => forceDockLayoutRefresh());
} }
function setDankBarSpacing(spacing) {
const defaultBar = barConfigs[0] || getBarConfig("default");
if (defaultBar) {
updateBarConfig(defaultBar.id, {
"spacing": spacing
});
}
updateCompositorLayout();
}
function setDankBarPosition(position) { function setDankBarPosition(position) {
const defaultBar = barConfigs[0] || getBarConfig("default"); const defaultBar = barConfigs[0] || getBarConfig("default");
if (!defaultBar) if (!defaultBar)
@@ -3134,39 +2810,6 @@ Singleton {
} }
} }
function resetDankBarWidgetsToDefault() {
var defaultLeft = ["launcherButton", "workspaceSwitcher", "focusedWindow"];
var defaultCenter = ["music", "clock", "weather"];
var defaultRight = ["systemTray", "clipboard", "notificationButton", "battery", "controlCenterButton"];
const defaultBar = barConfigs[0] || getBarConfig("default");
if (defaultBar) {
updateBarConfig(defaultBar.id, {
"leftWidgets": defaultLeft,
"centerWidgets": defaultCenter,
"rightWidgets": defaultRight
});
}
updateListModel(leftWidgetsModel, defaultLeft);
updateListModel(centerWidgetsModel, defaultCenter);
updateListModel(rightWidgetsModel, defaultRight);
showLauncherButton = true;
showWorkspaceSwitcher = true;
showFocusedWindow = true;
showWeather = true;
showMusic = true;
showClipboard = true;
showCpuUsage = true;
showMemUsage = true;
showCpuTemp = true;
showGpuTemp = true;
showSystemTray = true;
showClock = true;
showNotificationButton = true;
showBattery = true;
showControlCenterButton = true;
showCapsLockIndicator = true;
}
function setWorkspaceNameIcon(workspaceName, iconData) { function setWorkspaceNameIcon(workspaceName, iconData) {
var iconMap = JSON.parse(JSON.stringify(workspaceNameIcons)); var iconMap = JSON.parse(JSON.stringify(workspaceNameIcons));
iconMap[workspaceName] = iconData; iconMap[workspaceName] = iconData;
@@ -3448,15 +3091,6 @@ Singleton {
Theme.reloadCustomThemeVariant(); Theme.reloadCustomThemeVariant();
} }
function toggleDankBarVisible() {
const defaultBar = barConfigs[0] || getBarConfig("default");
if (defaultBar) {
updateBarConfig(defaultBar.id, {
"visible": !defaultBar.visible
});
}
}
function toggleShowDock() { function toggleShowDock() {
setShowDock(!showDock); setShowDock(!showDock);
} }
@@ -3478,13 +3112,6 @@ Singleton {
savePluginSettings(); savePluginSettings();
} }
function removePluginSettings(pluginId) {
if (pluginSettings[pluginId]) {
delete pluginSettings[pluginId];
savePluginSettings();
}
}
function getPluginSettingsForPlugin(pluginId) { function getPluginSettingsForPlugin(pluginId) {
const settings = pluginSettings[pluginId]; const settings = pluginSettings[pluginId];
return settings ? JSON.parse(JSON.stringify(settings)) : {}; return settings ? JSON.parse(JSON.stringify(settings)) : {};
@@ -3510,22 +3137,6 @@ Singleton {
return settings ? JSON.parse(JSON.stringify(settings)) : {}; return settings ? JSON.parse(JSON.stringify(settings)) : {};
} }
function setNiriOutputSettings(outputId, settings) {
const updated = JSON.parse(JSON.stringify(niriOutputSettings));
updated[outputId] = settings;
niriOutputSettings = updated;
saveSettings();
}
function removeNiriOutputSettings(outputId) {
if (!niriOutputSettings[outputId])
return;
const updated = JSON.parse(JSON.stringify(niriOutputSettings));
delete updated[outputId];
niriOutputSettings = updated;
saveSettings();
}
function getHyprlandOutputSetting(outputId, key, defaultValue) { function getHyprlandOutputSetting(outputId, key, defaultValue) {
if (!hyprlandOutputSettings[outputId]) if (!hyprlandOutputSettings[outputId])
return defaultValue; return defaultValue;
@@ -3550,40 +3161,6 @@ Singleton {
saveSettings(); saveSettings();
} }
function getHyprlandOutputSettings(outputId) {
const settings = hyprlandOutputSettings[outputId];
return settings ? JSON.parse(JSON.stringify(settings)) : {};
}
function setHyprlandOutputSettings(outputId, settings) {
const updated = JSON.parse(JSON.stringify(hyprlandOutputSettings));
updated[outputId] = settings;
hyprlandOutputSettings = updated;
saveSettings();
}
function removeHyprlandOutputSettings(outputId) {
if (!hyprlandOutputSettings[outputId])
return;
const updated = JSON.parse(JSON.stringify(hyprlandOutputSettings));
delete updated[outputId];
hyprlandOutputSettings = updated;
saveSettings();
}
function getDisplayProfiles(compositor) {
return displayProfiles[compositor] || {};
}
function setDisplayProfile(compositor, profileId, data) {
const updated = JSON.parse(JSON.stringify(displayProfiles));
if (!updated[compositor])
updated[compositor] = {};
updated[compositor][profileId] = data;
displayProfiles = updated;
saveSettings();
}
function removeDisplayProfile(compositor, profileId) { function removeDisplayProfile(compositor, profileId) {
if (!displayProfiles[compositor] || !displayProfiles[compositor][profileId]) if (!displayProfiles[compositor] || !displayProfiles[compositor][profileId])
return; return;
@@ -3637,29 +3214,6 @@ Singleton {
id: rightWidgetsModel id: rightWidgetsModel
} }
property Process testNotificationProcess
testNotificationProcess: Process {
command: []
running: false
}
property Timer testNotifTimer1
testNotifTimer1: Timer {
interval: 400
repeat: false
onTriggered: sendTestNotification(1)
}
property Timer testNotifTimer2
testNotifTimer2: Timer {
interval: 800
repeat: false
onTriggered: sendTestNotification(2)
}
property alias settingsFile: settingsFile property alias settingsFile: settingsFile
Timer { Timer {
-26
View File
@@ -416,24 +416,6 @@ const StockThemes = {
}, },
}; };
const ThemeCategories = {
GENERIC: {
name: "Generic",
variants: [
"blue",
"purple",
"green",
"orange",
"red",
"cyan",
"pink",
"amber",
"coral",
"monochrome",
],
},
};
const ThemeNames = { const ThemeNames = {
BLUE: "blue", BLUE: "blue",
PURPLE: "purple", PURPLE: "purple",
@@ -448,10 +430,6 @@ const ThemeNames = {
DYNAMIC: "dynamic", DYNAMIC: "dynamic",
}; };
function isStockTheme(themeName) {
return Object.keys(StockThemes.DARK).includes(themeName);
}
function getAvailableThemes(isLight = false) { function getAvailableThemes(isLight = false) {
return isLight ? StockThemes.LIGHT : StockThemes.DARK; return isLight ? StockThemes.LIGHT : StockThemes.DARK;
} }
@@ -464,7 +442,3 @@ function getThemeByName(themeName, isLight = false) {
function getAllThemeNames() { function getAllThemeNames() {
return Object.keys(StockThemes.DARK); return Object.keys(StockThemes.DARK);
} }
function getThemeCategories() {
return ThemeCategories;
}
+17 -602
View File
@@ -107,8 +107,11 @@ Singleton {
property int _colorsRetryCount: 0 property int _colorsRetryCount: 0
property double _lastGenerateMs: 0 property double _lastGenerateMs: 0
property bool themeModeAutomationActive: false property bool blurLayersActive: false
property bool dmsServiceWasDisconnected: true property bool matugenToastSuppressed: false
signal screenTransitionNeeded
signal themeGenerationStarting
readonly property var dank16: { readonly property var dank16: {
const raw = matugenColors?.dank16; const raw = matugenColors?.dank16;
@@ -196,235 +199,6 @@ Singleton {
const currentIsLight = (typeof SessionData !== "undefined") ? SessionData.isLightMode : false; const currentIsLight = (typeof SessionData !== "undefined") ? SessionData.isLightMode : false;
SettingsData.updateCosmicThemeMode(currentIsLight); SettingsData.updateCosmicThemeMode(currentIsLight);
} }
if (typeof SessionData !== "undefined" && SessionData.themeModeAutoEnabled) {
startThemeModeAutomation();
}
}
Connections {
target: SessionData
enabled: typeof SessionData !== "undefined"
function onThemeModeAutoEnabledChanged() {
if (SessionData.themeModeAutoEnabled) {
root.startThemeModeAutomation();
} else {
root.stopThemeModeAutomation();
}
}
function onThemeModeAutoModeChanged() {
if (root.themeModeAutomationActive) {
root.evaluateThemeMode();
root.syncTimeThemeSchedule();
root.syncLocationThemeSchedule();
}
}
function onThemeModeStartHourChanged() {
if (root.themeModeAutomationActive && !SessionData.themeModeShareGammaSettings) {
root.evaluateThemeMode();
root.syncTimeThemeSchedule();
}
}
function onThemeModeStartMinuteChanged() {
if (root.themeModeAutomationActive && !SessionData.themeModeShareGammaSettings) {
root.evaluateThemeMode();
root.syncTimeThemeSchedule();
}
}
function onThemeModeEndHourChanged() {
if (root.themeModeAutomationActive && !SessionData.themeModeShareGammaSettings) {
root.evaluateThemeMode();
root.syncTimeThemeSchedule();
}
}
function onThemeModeEndMinuteChanged() {
if (root.themeModeAutomationActive && !SessionData.themeModeShareGammaSettings) {
root.evaluateThemeMode();
root.syncTimeThemeSchedule();
}
}
function onThemeModeShareGammaSettingsChanged() {
if (root.themeModeAutomationActive) {
root.evaluateThemeMode();
root.syncTimeThemeSchedule();
root.syncLocationThemeSchedule();
}
}
function onNightModeStartHourChanged() {
if (root.themeModeAutomationActive && SessionData.themeModeShareGammaSettings) {
root.evaluateThemeMode();
root.syncTimeThemeSchedule();
}
}
function onNightModeStartMinuteChanged() {
if (root.themeModeAutomationActive && SessionData.themeModeShareGammaSettings) {
root.evaluateThemeMode();
root.syncTimeThemeSchedule();
}
}
function onNightModeEndHourChanged() {
if (root.themeModeAutomationActive && SessionData.themeModeShareGammaSettings) {
root.evaluateThemeMode();
root.syncTimeThemeSchedule();
}
}
function onNightModeEndMinuteChanged() {
if (root.themeModeAutomationActive && SessionData.themeModeShareGammaSettings) {
root.evaluateThemeMode();
root.syncTimeThemeSchedule();
}
}
function onLatitudeChanged() {
if (root.themeModeAutomationActive && 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.evaluateThemeMode();
root.syncLocationThemeSchedule();
}
}
function onLongitudeChanged() {
if (root.themeModeAutomationActive && 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.evaluateThemeMode();
root.syncLocationThemeSchedule();
}
}
function onNightModeUseIPLocationChanged() {
if (root.themeModeAutomationActive && 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.evaluateThemeMode();
root.syncLocationThemeSchedule();
}
}
}
// React to gamma backend's isDay state changes for location-based mode
Connections {
target: DisplayService
enabled: typeof DisplayService !== "undefined" && typeof SessionData !== "undefined" && SessionData.themeModeAutoEnabled && SessionData.themeModeAutoMode === "location" && !themeAutoBackendAvailable()
function onGammaIsDayChanged() {
if (root.isLightMode !== DisplayService.gammaIsDay) {
root.setLightMode(DisplayService.gammaIsDay, true, true);
}
}
}
Connections {
target: DMSService
function onThemeAutoStateUpdate(data) {
if (!SessionData.themeModeAutoEnabled) {
return;
}
applyThemeAutoState(data);
}
function onConnectionStateChanged() {
if (DMSService.isConnected && SessionData.themeModeAutoMode === "time") {
root.syncTimeThemeSchedule();
}
if (DMSService.isConnected && SessionData.themeModeAutoMode === "location") {
root.syncLocationThemeSchedule();
}
if (themeAutoBackendAvailable() && SessionData.themeModeAutoEnabled) {
DMSService.sendRequest("theme.auto.getState", null, response => {
if (response && response.result) {
applyThemeAutoState(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) {
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) {
log.warn("Theme automation: Failed to set location", locationResponse.error);
}
});
}
});
} else {
log.warn("Theme automation: No location configured");
}
}
}
}
Connections {
target: SessionService
enabled: SessionData.themeModeAutoEnabled
function onSessionUnlocked() {
root.triggerThemeAutomationRefresh();
}
function onSessionResumed() {
root.triggerThemeAutomationRefresh();
}
}
function triggerThemeAutomationRefresh() {
if (!themeAutoBackendAvailable()) {
root.evaluateThemeMode();
return;
}
DMSService.sendRequest("theme.auto.trigger", {});
} }
function getMatugenColor(path, fallback) { function getMatugenColor(path, fallback) {
@@ -571,8 +345,8 @@ Singleton {
property color surfaceVariantAlpha: withAlpha(surfaceVariant, 0.2) property color surfaceVariantAlpha: withAlpha(surfaceVariant, 0.2)
readonly property bool foregroundLayers: typeof SettingsData === "undefined" || (SettingsData.blurForegroundLayers ?? true) readonly property bool foregroundLayers: typeof SettingsData === "undefined" || (SettingsData.blurForegroundLayers ?? true)
readonly property bool blurForegroundLayers: BlurService.enabled && foregroundLayers readonly property bool blurForegroundLayers: blurLayersActive && foregroundLayers
readonly property bool transparentBlurLayers: BlurService.enabled && !foregroundLayers readonly property bool transparentBlurLayers: blurLayersActive && !foregroundLayers
readonly property bool notificationForegroundLayers: typeof SettingsData === "undefined" || (SettingsData.notificationForegroundLayers ?? true) readonly property bool notificationForegroundLayers: typeof SettingsData === "undefined" || (SettingsData.notificationForegroundLayers ?? true)
readonly property color readableSurface: withAlpha(surfaceContainer, popupTransparency) readonly property color readableSurface: withAlpha(surfaceContainer, popupTransparency)
readonly property color readableSurfaceHigh: withAlpha(surfaceContainerHigh, popupTransparency) readonly property color readableSurfaceHigh: withAlpha(surfaceContainerHigh, popupTransparency)
@@ -658,7 +432,7 @@ Singleton {
} }
} }
readonly property color ccTileInactiveBg: transparentBlurLayers ? withAlpha(surfaceContainerHigh, 0.16) : (foregroundLayers ? withAlpha(surfaceContainerHigh, BlurService.enabled ? Math.min(popupTransparency, 0.24) : popupTransparency) : withAlpha(surfaceContainer, 0)) readonly property color ccTileInactiveBg: transparentBlurLayers ? withAlpha(surfaceContainerHigh, 0.16) : (foregroundLayers ? withAlpha(surfaceContainerHigh, blurLayersActive ? Math.min(popupTransparency, 0.24) : popupTransparency) : withAlpha(surfaceContainer, 0))
readonly property color ccPillInactiveBg: transparentBlurLayers ? withAlpha(surfaceContainerHigh, 0.08) : nestedSurface readonly property color ccPillInactiveBg: transparentBlurLayers ? withAlpha(surfaceContainerHigh, 0.08) : nestedSurface
readonly property color ccPillInactiveHoverBg: transparentBlurLayers ? withAlpha(primary, 0.10) : primaryPressed readonly property color ccPillInactiveHoverBg: transparentBlurLayers ? withAlpha(primary, 0.10) : primaryPressed
readonly property color ccSliderTrackColor: transparentBlurLayers ? surfaceText : surfaceContainerHigh readonly property color ccSliderTrackColor: transparentBlurLayers ? surfaceText : surfaceContainerHigh
@@ -978,22 +752,6 @@ Singleton {
}; };
} }
function elevationTintOpacity(level) {
if (!level)
return 0;
if (level === elevationLevel1)
return 0.05;
if (level === elevationLevel2)
return 0.08;
if (level === elevationLevel3)
return 0.11;
if (level === elevationLevel4)
return 0.12;
if (level === elevationLevel5)
return 0.14;
return 0.08;
}
readonly property var animationDurations: [ readonly property var animationDurations: [
{ {
"shorter": 0, "shorter": 0,
@@ -1261,9 +1019,7 @@ Singleton {
} }
function screenTransition() { function screenTransition() {
if (CompositorService.isNiri) { screenTransitionNeeded();
NiriService.doScreenTransition();
}
} }
function switchTheme(themeName, savePrefs = true, enableTransition = true) { function switchTheme(themeName, savePrefs = true, enableTransition = true) {
@@ -1315,7 +1071,6 @@ Singleton {
SessionData.setLightMode(light); SessionData.setLightMode(light);
} }
PortalService.setLightMode(light);
if (typeof SettingsData !== "undefined") { if (typeof SettingsData !== "undefined") {
SettingsData.updateCosmicThemeMode(light); SettingsData.updateCosmicThemeMode(light);
} }
@@ -1326,22 +1081,6 @@ Singleton {
setLightMode(!isLightMode, savePrefs, true); setLightMode(!isLightMode, savePrefs, true);
} }
function forceGenerateSystemThemes() {
if (!matugenAvailable) {
return;
}
generateSystemThemesFromCurrentTheme();
}
function getAvailableThemes() {
return StockThemes.getAllThemeNames();
}
function getThemeDisplayName(themeName) {
const themeData = StockThemes.getThemeByName(themeName, isLightMode);
return themeData.name;
}
function getThemeColors(themeName) { function getThemeColors(themeName) {
if (themeName === "custom" && customThemeData) { if (themeName === "custom" && customThemeData) {
return customThemeData; return customThemeData;
@@ -1457,10 +1196,6 @@ Singleton {
readonly property var _availableThemeNames: StockThemes.getAllThemeNames() readonly property var _availableThemeNames: StockThemes.getAllThemeNames()
property string currentThemeName: currentTheme property string currentThemeName: currentTheme
function panelBackground() {
return withAlpha(surfaceContainer, panelTransparency);
}
property real notepadTransparency: SettingsData.notepadTransparencyOverride >= 0 ? SettingsData.notepadTransparencyOverride : popupTransparency property real notepadTransparency: SettingsData.notepadTransparencyOverride >= 0 ? SettingsData.notepadTransparencyOverride : popupTransparency
property bool widgetBackgroundHasAlpha: { property bool widgetBackgroundHasAlpha: {
@@ -1537,10 +1272,6 @@ Singleton {
} }
} }
function isColorDark(c) {
return (0.299 * c.r + 0.587 * c.g + 0.114 * c.b) < 0.5;
}
function barIconSize(barThickness, offset, maximizeIcon, iconScale) { function barIconSize(barThickness, offset, maximizeIcon, iconScale) {
const defaultOffset = offset !== undefined ? offset : -6; const defaultOffset = offset !== undefined ? offset : -6;
const size = (maximizeIcon ?? false) ? iconSizeLarge : iconSize; const size = (maximizeIcon ?? false) ? iconSizeLarge : iconSize;
@@ -1623,19 +1354,6 @@ Singleton {
} }
} }
function getPowerProfileDescription(profile) {
switch (profile) {
case 0:
return I18n.tr("Extend battery life", "power profile description");
case 1:
return I18n.tr("Balance power and performance", "power profile description");
case 2:
return I18n.tr("Prioritize performance", "power profile description");
default:
return I18n.tr("Custom power profile", "power profile description");
}
}
function onLightModeChanged() { function onLightModeChanged() {
if (currentTheme === "custom" && customThemeFileView.path) { if (currentTheme === "custom" && customThemeFileView.path) {
customThemeFileView.reload(); customThemeFileView.reload();
@@ -1663,9 +1381,7 @@ Singleton {
log.info("Setting desired theme -", kind, "mode:", isLight ? "light" : "dark", stockColors ? "(stock colors)" : "(dynamic)"); log.info("Setting desired theme -", kind, "mode:", isLight ? "light" : "dark", stockColors ? "(stock colors)" : "(dynamic)");
if (typeof NiriService !== "undefined" && CompositorService.isNiri) { themeGenerationStarting();
NiriService.suppressNextToast();
}
const desired = { const desired = {
"kind": kind, "kind": kind,
@@ -1777,8 +1493,7 @@ Singleton {
if (currentTheme === dynamic) { if (currentTheme === dynamic) {
if (!rawWallpaperPath) { if (!rawWallpaperPath) {
log.warn("Auto theme has no wallpaper - skipping matugen, syncing portal mode only"); log.warn("Auto theme has no wallpaper - skipping matugen");
PortalService.setLightMode(isLight);
return; return;
} }
const selectedMatugenType = (typeof SettingsData !== "undefined" && SettingsData.matugenScheme) ? SettingsData.matugenScheme : "scheme-tonal-spot"; const selectedMatugenType = (typeof SettingsData !== "undefined" && SettingsData.matugenScheme) ? SettingsData.matugenScheme : "scheme-tonal-spot";
@@ -1978,7 +1693,7 @@ Singleton {
const isLight = (typeof SessionData !== "undefined" && SessionData.isLightMode) ? "true" : "false"; const isLight = (typeof SessionData !== "undefined" && SessionData.isLightMode) ? "true" : "false";
Proc.runCommand("gtkApplier", ["bash", shellDir + "/scripts/gtk.sh", configDir, "apply", isLight, shellDir], (output, exitCode) => { Proc.runCommand("gtkApplier", ["bash", shellDir + "/scripts/gtk.sh", configDir, "apply", isLight, shellDir], (output, exitCode) => {
if (exitCode === 0) { if (exitCode === 0) {
if (typeof ToastService !== "undefined" && typeof NiriService !== "undefined" && !NiriService.matugenSuppression) { if (typeof ToastService !== "undefined" && !root.matugenToastSuppressed) {
ToastService.showInfo(I18n.tr("GTK colors applied successfully")); ToastService.showInfo(I18n.tr("GTK colors applied successfully"));
} }
} else { } else {
@@ -2016,18 +1731,17 @@ Singleton {
return Qt.rgba(c.r, c.g, c.b, a); return Qt.rgba(c.r, c.g, c.b, a);
} }
function popupLayerColor(baseColor) {
if (isConnectedEffect)
return connectedSurfaceColor;
return withAlpha(baseColor, popupTransparency);
}
function blendAlpha(c, a) { function blendAlpha(c, a) {
if (!c || c.r === undefined) if (!c || c.r === undefined)
return Qt.rgba(0, 0, 0, 0); return Qt.rgba(0, 0, 0, 0);
return Qt.rgba(c.r, c.g, c.b, c.a * a); return Qt.rgba(c.r, c.g, c.b, c.a * a);
} }
function hoverTint(base) {
const factor = 1.2;
return isLightMode ? Qt.darker(base, factor) : Qt.lighter(base, factor);
}
function blend(c1, c2, r) { function blend(c1, c2, r) {
return Qt.rgba(c1.r * (1 - r) + c2.r * r, c1.g * (1 - r) + c2.g * r, c1.b * (1 - r) + c2.b * r, c1.a * (1 - r) + c2.a * r); return Qt.rgba(c1.r * (1 - r) + c2.r * r, c1.g * (1 - r) + c2.g * r, c1.b * (1 - r) + c2.b * r, c1.a * (1 - r) + c2.a * r);
} }
@@ -2344,303 +2058,4 @@ Singleton {
root.switchTheme(defaultTheme, true, false); root.switchTheme(defaultTheme, true, false);
} }
} }
// Theme mode automation functions
function themeAutoBackendAvailable() {
return typeof DMSService !== "undefined" && DMSService.isConnected && Array.isArray(DMSService.capabilities) && DMSService.capabilities.includes("theme.auto");
}
function applyThemeAutoState(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 && root.isLightMode !== state.isLight) {
root.setLightMode(state.isLight, true, true);
}
}
function syncTimeThemeSchedule() {
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 syncLocationThemeSchedule() {
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 evaluateThemeMode() {
if (typeof SessionData === "undefined" || !SessionData.themeModeAutoEnabled) {
return;
}
if (themeAutoBackendAvailable()) {
DMSService.sendRequest("theme.auto.getState", null, response => {
if (response && response.result) {
applyThemeAutoState(response.result);
}
});
return;
}
const mode = SessionData.themeModeAutoMode;
if (mode === "location") {
evaluateLocationBasedThemeMode();
} else {
evaluateTimeBasedThemeMode();
}
}
function evaluateLocationBasedThemeMode() {
if (typeof DisplayService !== "undefined") {
const shouldBeLight = DisplayService.gammaIsDay;
if (root.isLightMode !== shouldBeLight) {
root.setLightMode(shouldBeLight, true, true);
}
return;
}
if (!SessionData.nightModeUseIPLocation && SessionData.latitude !== 0.0 && SessionData.longitude !== 0.0) {
const shouldBeLight = calculateIsDaytime(SessionData.latitude, SessionData.longitude);
if (root.isLightMode !== shouldBeLight) {
root.setLightMode(shouldBeLight, true, true);
}
return;
}
if (root.themeModeAutomationActive) {
if (SessionData.nightModeUseIPLocation) {
log.warn("Theme automation: Waiting for IP location from backend");
} else {
log.warn("Theme automation: Location mode requires coordinates");
}
}
}
function evaluateTimeBasedThemeMode() {
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 (root.isLightMode !== shouldBeLight) {
root.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; // Polar night
}
if (cosHourAngle < -1) {
return true; // Midnight sun
}
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;
}
// Helper function to send location to backend
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.evaluateThemeMode();
} else {
retryCount++;
if (retryCount >= 10) {
stop();
retryCount = 0;
}
}
}
}
function startThemeModeAutomation() {
root.themeModeAutomationActive = true;
root.syncTimeThemeSchedule();
root.syncLocationThemeSchedule();
const sent = root.sendLocationToBackend();
if (!sent && typeof SessionData !== "undefined" && SessionData.themeModeAutoMode === "location") {
locationRetryTimer.start();
} else {
root.evaluateThemeMode();
}
}
function stopThemeModeAutomation() {
root.themeModeAutomationActive = false;
if (typeof DMSService !== "undefined" && DMSService.isConnected) {
DMSService.sendRequest("theme.auto.setEnabled", {
"enabled": false
});
}
}
} }
+2 -21
View File
@@ -4,17 +4,13 @@
function markdownToHtml(text) { function markdownToHtml(text) {
if (!text) return ""; if (!text) return "";
// Store code blocks and inline code to protect them from further processing
const codeBlocks = []; const codeBlocks = [];
const inlineCode = []; const inlineCode = [];
let blockIndex = 0; let blockIndex = 0;
let inlineIndex = 0; let inlineIndex = 0;
// First, extract and replace code blocks with placeholders
let html = text.replace(/```([\s\S]*?)```/g, (match, code) => { let html = text.replace(/```([\s\S]*?)```/g, (match, code) => {
// Trim leading and trailing blank lines only
const trimmedCode = code.replace(/^\n+|\n+$/g, ''); const trimmedCode = code.replace(/^\n+|\n+$/g, '');
// Escape HTML entities in code
const escapedCode = trimmedCode.replace(/&/g, '&amp;') const escapedCode = trimmedCode.replace(/&/g, '&amp;')
.replace(/</g, '&lt;') .replace(/</g, '&lt;')
.replace(/>/g, '&gt;'); .replace(/>/g, '&gt;');
@@ -22,9 +18,7 @@ function markdownToHtml(text) {
return `\x00CODEBLOCK${blockIndex++}\x00`; return `\x00CODEBLOCK${blockIndex++}\x00`;
}); });
// Extract and replace inline code
html = html.replace(/`([^`]+)`/g, (match, code) => { html = html.replace(/`([^`]+)`/g, (match, code) => {
// Escape HTML entities in code
const escapedCode = code.replace(/&/g, '&amp;') const escapedCode = code.replace(/&/g, '&amp;')
.replace(/</g, '&lt;') .replace(/</g, '&lt;')
.replace(/>/g, '&gt;'); .replace(/>/g, '&gt;');
@@ -40,12 +34,10 @@ function markdownToHtml(text) {
return prefix + `\x00URL${urlIndex++}\x00`; return prefix + `\x00URL${urlIndex++}\x00`;
}); });
// Escape HTML entities (but not in code blocks or URLs)
html = html.replace(/&/g, '&amp;') html = html.replace(/&/g, '&amp;')
.replace(/</g, '&lt;') .replace(/</g, '&lt;')
.replace(/>/g, '&gt;'); .replace(/>/g, '&gt;');
// Headers
html = html.replace(/^### (.*?)$/gm, '<h3>$1</h3>'); html = html.replace(/^### (.*?)$/gm, '<h3>$1</h3>');
html = html.replace(/^## (.*?)$/gm, '<h2>$1</h2>'); html = html.replace(/^## (.*?)$/gm, '<h2>$1</h2>');
html = html.replace(/^# (.*?)$/gm, '<h1>$1</h1>'); html = html.replace(/^# (.*?)$/gm, '<h1>$1</h1>');
@@ -58,20 +50,16 @@ function markdownToHtml(text) {
html = html.replace(/__(.*?)__/g, '<b>$1</b>'); html = html.replace(/__(.*?)__/g, '<b>$1</b>');
html = html.replace(/_(.*?)_/g, '<i>$1</i>'); html = html.replace(/_(.*?)_/g, '<i>$1</i>');
// Links
html = html.replace(/\[([^\]]+)\]\(([^)]+)\)/g, '<a href="$2">$1</a>'); html = html.replace(/\[([^\]]+)\]\(([^)]+)\)/g, '<a href="$2">$1</a>');
// Lists
html = html.replace(/^\* (.*?)$/gm, '<li>$1</li>'); html = html.replace(/^\* (.*?)$/gm, '<li>$1</li>');
html = html.replace(/^- (.*?)$/gm, '<li>$1</li>'); html = html.replace(/^- (.*?)$/gm, '<li>$1</li>');
html = html.replace(/^\d+\. (.*?)$/gm, '<li>$1</li>'); html = html.replace(/^\d+\. (.*?)$/gm, '<li>$1</li>');
// Wrap consecutive list items in ul/ol tags
html = html.replace(/(<li>[\s\S]*?<\/li>\s*)+/g, function(match) { html = html.replace(/(<li>[\s\S]*?<\/li>\s*)+/g, function(match) {
return '<ul>' + match + '</ul>'; return '<ul>' + match + '</ul>';
}); });
// Restore extracted URLs as anchor tags (preserves raw & in href)
html = html.replace(/\x00URL(\d+)\x00/g, (_, index) => { html = html.replace(/\x00URL(\d+)\x00/g, (_, index) => {
const url = urls[parseInt(index)]; const url = urls[parseInt(index)];
const display = url.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;'); const display = url.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
@@ -87,30 +75,23 @@ function markdownToHtml(text) {
return inlineCode[parseInt(index)]; return inlineCode[parseInt(index)];
}); });
// Line breaks (after code blocks are restored)
html = html.replace(/\n\n/g, '</p><p>'); html = html.replace(/\n\n/g, '</p><p>');
html = html.replace(/\n/g, '<br/>'); html = html.replace(/\n/g, '<br/>');
// Wrap in paragraph tags if not already wrapped
if (!html.startsWith('<')) { if (!html.startsWith('<')) {
html = '<p>' + html + '</p>'; html = '<p>' + html + '</p>';
} }
// Clean up the final HTML
// Remove <br/> tags immediately before block elements
html = html.replace(/<br\/>\s*<pre>/g, '<pre>'); html = html.replace(/<br\/>\s*<pre>/g, '<pre>');
html = html.replace(/<br\/>\s*<ul>/g, '<ul>'); html = html.replace(/<br\/>\s*<ul>/g, '<ul>');
html = html.replace(/<br\/>\s*<h[1-6]>/g, '<h$1>'); html = html.replace(/<br\/>\s*<h[1-6]>/g, '<h$1>');
// Remove empty paragraphs
html = html.replace(/<p>\s*<\/p>/g, ''); html = html.replace(/<p>\s*<\/p>/g, '');
html = html.replace(/<p>\s*<br\/>\s*<\/p>/g, ''); html = html.replace(/<p>\s*<br\/>\s*<\/p>/g, '');
// Remove excessive line breaks html = html.replace(/(<br\/>){3,}/g, '<br/><br/>');
html = html.replace(/(<br\/>){3,}/g, '<br/><br/>'); // Max 2 consecutive line breaks html = html.replace(/(<\/p>)\s*(<p>)/g, '$1$2');
html = html.replace(/(<\/p>)\s*(<p>)/g, '$1$2'); // Remove whitespace between paragraphs
// Remove leading/trailing whitespace
html = html.trim(); html = html.trim();
return html; return html;
+15 -13
View File
@@ -5,11 +5,13 @@ import QtQuick
import Quickshell import Quickshell
import Quickshell.Io import Quickshell.Io
import qs.Common import qs.Common
import qs.Services
Singleton { Singleton {
id: root id: root
signal toastRequested(int severity, string title, string body, string command, string category)
signal toastCategoryDismissed(string category)
property var settingsRoot: null property var settingsRoot: null
onSettingsRootChanged: { onSettingsRootChanged: {
@@ -317,7 +319,7 @@ Singleton {
function launchAuthApplyTerminalFallback(fromPrecheck, details) { function launchAuthApplyTerminalFallback(fromPrecheck, details) {
authApplyTerminalFallbackFromPrecheck = fromPrecheck; authApplyTerminalFallbackFromPrecheck = fromPrecheck;
if (details && details !== "") if (details && details !== "")
ToastService.showInfo(I18n.tr("Authentication changes need sudo. Opening terminal so you can use password or fingerprint."), details, "", "auth-sync"); toastRequested(0, I18n.tr("Authentication changes need sudo. Opening terminal so you can use password or fingerprint."), details, "", "auth-sync");
authApplyTerminalFallbackStderr = ""; authApplyTerminalFallbackStderr = "";
authApplyTerminalFallbackProcess.running = true; authApplyTerminalFallbackProcess.running = true;
} }
@@ -364,21 +366,21 @@ Singleton {
} }
function deferGreeterAutoLoginSyncToPill(details) { function deferGreeterAutoLoginSyncToPill(details) {
ToastService.dismissCategory("greeter-autologin-sync"); toastCategoryDismissed("greeter-autologin-sync");
if (settingsRoot) if (settingsRoot)
settingsRoot.set("greeterSyncPending", true); settingsRoot.set("greeterSyncPending", true);
ToastService.showWarning(I18n.tr("Auto-login change needs a sync"), I18n.tr("Administrator access is required. Use the Sync button in Settings → Greeter to apply.") + (details ? "\n\n" + details : ""), "dms-greeter sync --autologin", "greeter-autologin-sync"); toastRequested(1, I18n.tr("Auto-login change needs a sync"), I18n.tr("Administrator access is required. Use the Sync button in Settings → Greeter to apply.") + (details ? "\n\n" + details : ""), "dms-greeter sync --autologin", "greeter-autologin-sync");
finishGreeterAutoLoginSync(); finishGreeterAutoLoginSync();
} }
function greeterAutoLoginSyncSuccessToast(details) { function greeterAutoLoginSyncSuccessToast(details) {
const enabling = settingsRoot && settingsRoot.greeterAutoLogin; const enabling = settingsRoot && settingsRoot.greeterAutoLogin;
// Clear the sticky in-progress toast, then confirm with an auto-dismissing toast. // Clear the sticky in-progress toast, then confirm with an auto-dismissing toast.
ToastService.dismissCategory("greeter-autologin-sync"); toastCategoryDismissed("greeter-autologin-sync");
if (enabling) { if (enabling) {
ToastService.showWarning(I18n.tr("Auto-login enabled"), I18n.tr("You'll skip the greeter password after the next reboot. The lock screen and signing out still require your password.") + (details ? "\n\n" + details : "")); toastRequested(1, I18n.tr("Auto-login enabled"), I18n.tr("You'll skip the greeter password after the next reboot. The lock screen and signing out still require your password.") + (details ? "\n\n" + details : ""), "", "");
} else { } else {
ToastService.showInfo(I18n.tr("Auto-login disabled"), I18n.tr("You'll enter your password at the greeter after the next reboot.") + (details ? "\n\n" + details : "")); toastRequested(0, I18n.tr("Auto-login disabled"), I18n.tr("You'll enter your password at the greeter after the next reboot.") + (details ? "\n\n" + details : ""), "", "");
} }
} }
@@ -575,7 +577,7 @@ Singleton {
onExited: exitCode => { onExited: exitCode => {
const enabling = root.settingsRoot && root.settingsRoot.greeterAutoLogin; const enabling = root.settingsRoot && root.settingsRoot.greeterAutoLogin;
if (exitCode === 0) { if (exitCode === 0) {
ToastService.showWarning(enabling ? I18n.tr("Applying auto-login on startup...") : I18n.tr("Disabling auto-login on startup..."), "", "dms-greeter sync --autologin", "greeter-autologin-sync"); root.toastRequested(1, enabling ? I18n.tr("Applying auto-login on startup...") : I18n.tr("Disabling auto-login on startup..."), "", "dms-greeter sync --autologin", "greeter-autologin-sync");
root.greeterAutoLoginSyncProcess.running = true; root.greeterAutoLoginSyncProcess.running = true;
return; return;
} }
@@ -604,7 +606,7 @@ Singleton {
let details = out; let details = out;
if (err !== "") if (err !== "")
details = details !== "" ? details + "\n\nstderr:\n" + err : "stderr:\n" + err; details = details !== "" ? details + "\n\nstderr:\n" + err : "stderr:\n" + err;
ToastService.showInfo(I18n.tr("Authentication changes applied"), details, "", "auth-sync"); root.toastRequested(0, I18n.tr("Authentication changes applied"), details, "", "auth-sync");
root.detectAuthCapabilities(); root.detectAuthCapabilities();
root.finishAuthApply(); root.finishAuthApply();
return; return;
@@ -615,7 +617,7 @@ Singleton {
details = out; details = out;
if (err !== "") if (err !== "")
details = details !== "" ? details + "\n\nstderr:\n" + err : "stderr:\n" + err; details = details !== "" ? details + "\n\nstderr:\n" + err : "stderr:\n" + err;
ToastService.showWarning(I18n.tr("Background authentication sync failed. Trying terminal mode."), details, "", "auth-sync"); root.toastRequested(1, I18n.tr("Background authentication sync failed. Trying terminal mode."), details, "", "auth-sync");
root.launchAuthApplyTerminalFallback(false, ""); root.launchAuthApplyTerminalFallback(false, "");
} }
} }
@@ -631,7 +633,7 @@ Singleton {
onExited: exitCode => { onExited: exitCode => {
const err = (root.authApplySudoProbeStderr || "").trim(); const err = (root.authApplySudoProbeStderr || "").trim();
if (exitCode === 0) { if (exitCode === 0) {
ToastService.showInfo(I18n.tr("Applying authentication changes..."), "", "", "auth-sync"); root.toastRequested(0, I18n.tr("Applying authentication changes..."), "", "", "auth-sync");
root.authApplyProcess.running = true; root.authApplyProcess.running = true;
return; return;
} }
@@ -651,10 +653,10 @@ Singleton {
onExited: exitCode => { onExited: exitCode => {
if (exitCode === 0) { if (exitCode === 0) {
const message = root.authApplyTerminalFallbackFromPrecheck ? I18n.tr("Terminal opened. Complete authentication there; it will close automatically when done.") : I18n.tr("Terminal fallback opened. Complete authentication there; it will close automatically when done."); const message = root.authApplyTerminalFallbackFromPrecheck ? I18n.tr("Terminal opened. Complete authentication there; it will close automatically when done.") : I18n.tr("Terminal fallback opened. Complete authentication there; it will close automatically when done.");
ToastService.showInfo(message, "", "", "auth-sync"); root.toastRequested(0, message, "", "", "auth-sync");
} else { } else {
let details = (root.authApplyTerminalFallbackStderr || "").trim(); let details = (root.authApplyTerminalFallbackStderr || "").trim();
ToastService.showError(I18n.tr("Terminal fallback failed. Install a supported terminal emulator or run 'dms auth sync' manually.") + " (exit " + exitCode + ")", details, "", "auth-sync"); root.toastRequested(2, I18n.tr("Terminal fallback failed. Install a supported terminal emulator or run 'dms auth sync' manually.") + " (exit " + exitCode + ")", details, "", "auth-sync");
} }
root.finishAuthApply(); root.finishAuthApply();
} }
@@ -75,26 +75,3 @@ function migrateToVersion(obj, targetVersion, settingsData) {
return session; return session;
} }
function cleanup(fileText) {
var getValidKeys = SpecModule.getValidKeys;
if (!fileText || !fileText.trim()) return null;
try {
var session = JSON.parse(fileText);
var validKeys = getValidKeys();
var needsSave = false;
for (var key in session) {
if (validKeys.indexOf(key) < 0) {
delete session[key];
needsSave = true;
}
}
return needsSave ? JSON.stringify(session, null, 2) : null;
} catch (e) {
console.warn("SessionData: Failed to cleanup unused keys:", e.message);
return null;
}
}
@@ -291,26 +291,3 @@ function migrateToVersion(obj, targetVersion) {
return settings; return settings;
} }
function cleanup(fileText) {
var getValidKeys = SpecModule.getValidKeys;
if (!fileText || !fileText.trim()) return;
try {
var settings = JSON.parse(fileText);
var validKeys = getValidKeys();
var needsSave = false;
for (var key in settings) {
if (validKeys.indexOf(key) < 0) {
delete settings[key];
needsSave = true;
}
}
return needsSave ? JSON.stringify(settings, null, 2) : null;
} catch (e) {
console.warn("SettingsData: Failed to cleanup unused keys:", e.message);
return null;
}
}
-65
View File
@@ -122,11 +122,6 @@ const times = [
// adds a custom time to the times config // adds a custom time to the times config
function addTime(angle, riseName, setName) {
times.push([angle, riseName, setName]);
};
// calculations for sun times // calculations for sun times
const J0 = 0.0009; const J0 = 0.0009;
@@ -246,63 +241,3 @@ function getMoonIllumination(date) {
angle angle
}; };
}; };
function hoursLater(date, h) {
return new Date(date.valueOf() + h * dayMs / 24);
}
// calculations for moon rise/set times are based on http://www.stargazing.net/kepler/moonrise.html article
function getMoonTimes(date, lat, lng, inUTC) {
const t = new Date(date);
if (inUTC) t.setUTCHours(0, 0, 0, 0);
else t.setHours(0, 0, 0, 0);
const hc = 0.133 * rad;
let h0 = getMoonPosition(t, lat, lng).altitude - hc,
rise, set, ye;
// go in 2-hour chunks, each time seeing if a 3-point quadratic curve crosses zero (which means rise or set)
for (let i = 1; i <= 24; i += 2) {
const h1 = getMoonPosition(hoursLater(t, i), lat, lng).altitude - hc;
const h2 = getMoonPosition(hoursLater(t, i + 1), lat, lng).altitude - hc;
const a = (h0 + h2) / 2 - h1;
const b = (h2 - h0) / 2;
const xe = -b / (2 * a);
const d = b * b - 4 * a * h1;
let roots = 0, x1 = 0, x2 = 0;
ye = (a * xe + b) * xe + h1;
if (d >= 0) {
const dx = Math.sqrt(d) / (Math.abs(a) * 2);
x1 = xe - dx;
x2 = xe + dx;
if (Math.abs(x1) <= 1) roots++;
if (Math.abs(x2) <= 1) roots++;
if (x1 < -1) x1 = x2;
}
if (roots === 1) {
if (h0 < 0) rise = i + x1;
else set = i + x1;
} else if (roots === 2) {
rise = i + (ye < 0 ? x2 : x1);
set = i + (ye < 0 ? x1 : x2);
}
if (rise && set) break;
h0 = h2;
}
const result = {};
if (rise) result.rise = hoursLater(t, rise);
if (set) result.set = hoursLater(t, set);
if (!rise && !set) result[ye > 0 ? 'alwaysUp' : 'alwaysDown'] = true;
return result;
};
+5
View File
@@ -233,6 +233,11 @@ Item {
PolkitService.polkitAvailable; PolkitService.polkitAvailable;
DisplayConfigState.hasOutputBackend; DisplayConfigState.hasOutputBackend;
PortalService.systemColorScheme; PortalService.systemColorScheme;
IconThemeService.revision;
DesktopService.isSystemd;
TrashService.count;
WallpaperCyclingService.cyclingActive;
ThemeAutoService.active;
} }
Loader { Loader {
@@ -314,26 +314,20 @@ Item {
readonly property real alignedWidth: Theme.px(modalWidth, dpr) readonly property real alignedWidth: Theme.px(modalWidth, dpr)
readonly property real alignedHeight: Theme.px(modalHeight, dpr) readonly property real alignedHeight: Theme.px(modalHeight, dpr)
function _frameEdgeInset(side) {
if (!effectiveScreen)
return 0;
return SettingsData.frameEdgeInsetForSide(effectiveScreen, side);
}
readonly property real _connectedAlignedX: { readonly property real _connectedAlignedX: {
switch (resolvedConnectedBarSide) { switch (resolvedConnectedBarSide) {
case "top": case "top":
case "bottom": case "bottom":
{ {
const insetL = _frameEdgeInset("left"); const insetL = SettingsData.frameEdgeInsetForSide(effectiveScreen, "left");
const insetR = _frameEdgeInset("right"); const insetR = SettingsData.frameEdgeInsetForSide(effectiveScreen, "right");
const usable = Math.max(0, screenWidth - insetL - insetR); const usable = Math.max(0, screenWidth - insetL - insetR);
return insetL + Math.max(0, (usable - alignedWidth) / 2); return insetL + Math.max(0, (usable - alignedWidth) / 2);
} }
case "left": case "left":
return _frameEdgeInset("left"); return SettingsData.frameEdgeInsetForSide(effectiveScreen, "left");
case "right": case "right":
return screenWidth - alignedWidth - _frameEdgeInset("right"); return screenWidth - alignedWidth - SettingsData.frameEdgeInsetForSide(effectiveScreen, "right");
} }
return 0; return 0;
} }
@@ -341,14 +335,14 @@ Item {
readonly property real _connectedAlignedY: { readonly property real _connectedAlignedY: {
switch (resolvedConnectedBarSide) { switch (resolvedConnectedBarSide) {
case "top": case "top":
return _frameEdgeInset("top"); return SettingsData.frameEdgeInsetForSide(effectiveScreen, "top");
case "bottom": case "bottom":
return screenHeight - alignedHeight - _frameEdgeInset("bottom"); return screenHeight - alignedHeight - SettingsData.frameEdgeInsetForSide(effectiveScreen, "bottom");
case "left": case "left":
case "right": case "right":
{ {
const insetT = _frameEdgeInset("top"); const insetT = SettingsData.frameEdgeInsetForSide(effectiveScreen, "top");
const insetB = _frameEdgeInset("bottom"); const insetB = SettingsData.frameEdgeInsetForSide(effectiveScreen, "bottom");
const usable = Math.max(0, screenHeight - insetT - insetB); const usable = Math.max(0, screenHeight - insetT - insetB);
return insetT + Math.max(0, (usable - alignedHeight) / 2); return insetT + Math.max(0, (usable - alignedHeight) / 2);
} }
@@ -105,12 +105,6 @@ Item {
} }
readonly property bool _dockBlocksEmergence: frameOwnsConnectedChrome && _dockOccupiesSide(resolvedConnectedBarSide) readonly property bool _dockBlocksEmergence: frameOwnsConnectedChrome && _dockOccupiesSide(resolvedConnectedBarSide)
function _frameEdgeInset(side) {
if (!effectiveScreen)
return 0;
return SettingsData.frameEdgeInsetForSide(effectiveScreen, side);
}
readonly property var _connectedModalPos: { readonly property var _connectedModalPos: {
const fallback = { const fallback = {
"x": (screenWidth - modalWidth) / 2, "x": (screenWidth - modalWidth) / 2,
@@ -120,10 +114,10 @@ Item {
case "top": case "top":
case "bottom": case "bottom":
{ {
const insetL = _frameEdgeInset("left"); const insetL = SettingsData.frameEdgeInsetForSide(effectiveScreen, "left");
const insetR = _frameEdgeInset("right"); const insetR = SettingsData.frameEdgeInsetForSide(effectiveScreen, "right");
const insetT = _frameEdgeInset("top"); const insetT = SettingsData.frameEdgeInsetForSide(effectiveScreen, "top");
const insetB = _frameEdgeInset("bottom"); const insetB = SettingsData.frameEdgeInsetForSide(effectiveScreen, "bottom");
const usable = Math.max(0, screenWidth - insetL - insetR); const usable = Math.max(0, screenWidth - insetL - insetR);
const usableH = Math.max(0, screenHeight - insetT - insetB); const usableH = Math.max(0, screenHeight - insetT - insetB);
return { return {
@@ -134,11 +128,11 @@ Item {
case "left": case "left":
case "right": case "right":
{ {
const insetT = _frameEdgeInset("top"); const insetT = SettingsData.frameEdgeInsetForSide(effectiveScreen, "top");
const insetB = _frameEdgeInset("bottom"); const insetB = SettingsData.frameEdgeInsetForSide(effectiveScreen, "bottom");
const usable = Math.max(0, screenHeight - insetT - insetB); const usable = Math.max(0, screenHeight - insetT - insetB);
return { return {
"x": resolvedConnectedBarSide === "left" ? _frameEdgeInset("left") : screenWidth - modalWidth - _frameEdgeInset("right"), "x": resolvedConnectedBarSide === "left" ? SettingsData.frameEdgeInsetForSide(effectiveScreen, "left") : screenWidth - modalWidth - SettingsData.frameEdgeInsetForSide(effectiveScreen, "right"),
"y": insetT + Math.max(0, (usable - modalHeight) / 2) "y": insetT + Math.max(0, (usable - modalHeight) / 2)
}; };
} }
@@ -188,16 +182,16 @@ Item {
readonly property real _connectedChromeY: { readonly property real _connectedChromeY: {
if (!launcherArcExtenderActive) if (!launcherArcExtenderActive)
return alignedY; return alignedY;
return resolvedConnectedBarSide === "top" ? Theme.snap(_frameEdgeInset("top"), dpr) : alignedY; return resolvedConnectedBarSide === "top" ? Theme.snap(SettingsData.frameEdgeInsetForSide(effectiveScreen, "top"), dpr) : alignedY;
} }
readonly property real _connectedChromeWidth: alignedWidth readonly property real _connectedChromeWidth: alignedWidth
readonly property real _connectedChromeHeight: { readonly property real _connectedChromeHeight: {
if (!launcherArcExtenderActive) if (!launcherArcExtenderActive)
return alignedHeight; return alignedHeight;
if (resolvedConnectedBarSide === "top") if (resolvedConnectedBarSide === "top")
return Theme.snap(Math.max(alignedHeight, alignedY + alignedHeight - _frameEdgeInset("top")), dpr); return Theme.snap(Math.max(alignedHeight, alignedY + alignedHeight - SettingsData.frameEdgeInsetForSide(effectiveScreen, "top")), dpr);
if (resolvedConnectedBarSide === "bottom") if (resolvedConnectedBarSide === "bottom")
return Theme.snap(Math.max(alignedHeight, screenHeight - _frameEdgeInset("bottom") - alignedY), dpr); return Theme.snap(Math.max(alignedHeight, screenHeight - SettingsData.frameEdgeInsetForSide(effectiveScreen, "bottom") - alignedY), dpr);
return alignedHeight; return alignedHeight;
} }
readonly property real contentSurfaceHeight: launcherArcExtenderActive ? _connectedChromeHeight : alignedHeight readonly property real contentSurfaceHeight: launcherArcExtenderActive ? _connectedChromeHeight : alignedHeight
@@ -89,15 +89,6 @@ function fuzzyScore(text, query) {
return bestScore return bestScore
} }
function getTimeBucketWeight(daysSinceUsed) {
for (var i = 0; i < TimeBuckets.length; i++) {
if (daysSinceUsed <= TimeBuckets[i].maxDays) {
return TimeBuckets[i].weight
}
}
return 10
}
function calculateTextScore(name, query) { function calculateTextScore(name, query) {
if (name === query) return Weights.exactMatch if (name === query) return Weights.exactMatch
if (name.startsWith(query)) return Weights.prefixMatch if (name.startsWith(query)) return Weights.prefixMatch
+14 -1
View File
@@ -18,6 +18,19 @@ DankModal {
open(); open();
} }
function getPowerProfileDescription(profile) {
switch (profile) {
case 0:
return I18n.tr("Extend battery life", "power profile description");
case 1:
return I18n.tr("Balance power and performance", "power profile description");
case 2:
return I18n.tr("Prioritize performance", "power profile description");
default:
return I18n.tr("Custom power profile", "power profile description");
}
}
function hideDialog() { function hideDialog() {
close(); close();
} }
@@ -244,7 +257,7 @@ DankModal {
// Selected power profile description // Selected power profile description
StyledText { StyledText {
text: (root.selectedIndex >= 0 && root.selectedIndex < root.profileModel.length) ? Theme.getPowerProfileDescription(root.profileModel[root.selectedIndex]) : "" text: (root.selectedIndex >= 0 && root.selectedIndex < root.profileModel.length) ? root.getPowerProfileDescription(root.profileModel[root.selectedIndex]) : ""
font.pixelSize: Theme.fontSizeMedium font.pixelSize: Theme.fontSizeMedium
color: Theme.surfaceTextMedium color: Theme.surfaceTextMedium
horizontalAlignment: Text.AlignHCenter horizontalAlignment: Text.AlignHCenter
+3 -12
View File
@@ -6,6 +6,7 @@ import qs.Common
import qs.Modules.ProcessList import qs.Modules.ProcessList
import qs.Services import qs.Services
import qs.Widgets import qs.Widgets
import "../Common/Format.js" as Format
FloatingWindow { FloatingWindow {
id: processListModal id: processListModal
@@ -67,16 +68,6 @@ FloatingWindow {
show(); show();
} }
function formatBytes(bytes) {
if (bytes < 1024)
return bytes.toFixed(0) + " B/s";
if (bytes < 1024 * 1024)
return (bytes / 1024).toFixed(1) + " KB/s";
if (bytes < 1024 * 1024 * 1024)
return (bytes / (1024 * 1024)).toFixed(1) + " MB/s";
return (bytes / (1024 * 1024 * 1024)).toFixed(2) + " GB/s";
}
function nextTab() { function nextTab() {
currentTab = (currentTab + 1) % 4; currentTab = (currentTab + 1) % 4;
} }
@@ -541,7 +532,7 @@ FloatingWindow {
} }
StyledText { StyledText {
text: "↓" + formatBytes(DgopService.networkRxRate) + " ↑" + formatBytes(DgopService.networkTxRate) text: "↓" + Format.formatRate(DgopService.networkRxRate) + " ↑" + Format.formatRate(DgopService.networkTxRate)
font.pixelSize: Theme.fontSizeSmall font.pixelSize: Theme.fontSizeSmall
font.family: SettingsData.monoFontFamily font.family: SettingsData.monoFontFamily
color: Theme.surfaceText color: Theme.surfaceText
@@ -559,7 +550,7 @@ FloatingWindow {
} }
StyledText { StyledText {
text: "↓" + formatBytes(DgopService.diskReadRate) + " ↑" + formatBytes(DgopService.diskWriteRate) text: "↓" + Format.formatRate(DgopService.diskReadRate) + " ↑" + Format.formatRate(DgopService.diskWriteRate)
font.pixelSize: Theme.fontSizeSmall font.pixelSize: Theme.fontSizeSmall
font.family: SettingsData.monoFontFamily font.family: SettingsData.monoFontFamily
color: Theme.surfaceText color: Theme.surfaceText
+2 -25
View File
@@ -25,29 +25,6 @@ Item {
property bool effectActive: false property bool effectActive: false
property bool useNextForEffect: false property bool useNextForEffect: false
function getFillMode(modeName) {
switch (modeName) {
case "Stretch":
return Image.Stretch;
case "Fit":
case "PreserveAspectFit":
return Image.PreserveAspectFit;
case "Fill":
case "PreserveAspectCrop":
return Image.PreserveAspectCrop;
case "Tile":
return Image.Tile;
case "TileVertically":
return Image.TileVertically;
case "TileHorizontally":
return Image.TileHorizontally;
case "Pad":
return Image.Pad;
default:
return Image.PreserveAspectCrop;
}
}
Component.onCompleted: { Component.onCompleted: {
if (initialSource && initialSource !== wallpaperSource && !(CompositorService.isNiri && SessionData.isSwitchingMode)) { if (initialSource && initialSource !== wallpaperSource && !(CompositorService.isNiri && SessionData.isSwitchingMode)) {
currentWallpaper.source = initialSource; currentWallpaper.source = initialSource;
@@ -144,7 +121,7 @@ Item {
smooth: true smooth: true
cache: true cache: true
sourceSize: root.blurTextureSize sourceSize: root.blurTextureSize
fillMode: root.getFillMode(SessionData.getMonitorWallpaperFillMode(root.screenName)) fillMode: Theme.getFillMode(SessionData.getMonitorWallpaperFillMode(root.screenName))
onStatusChanged: { onStatusChanged: {
if (status === Image.Error) { if (status === Image.Error) {
@@ -166,7 +143,7 @@ Item {
smooth: true smooth: true
cache: true cache: true
sourceSize: root.blurTextureSize sourceSize: root.blurTextureSize
fillMode: root.getFillMode(SessionData.getMonitorWallpaperFillMode(root.screenName)) fillMode: Theme.getFillMode(SessionData.getMonitorWallpaperFillMode(root.screenName))
onStatusChanged: { onStatusChanged: {
if (status === Image.Error) { if (status === Image.Error) {
@@ -4,6 +4,7 @@ import Quickshell
import qs.Common import qs.Common
import qs.Services import qs.Services
import qs.Widgets import qs.Widgets
import "../../Common/Format.js" as Format
Item { Item {
id: root id: root
@@ -188,16 +189,6 @@ Item {
return DgopService.availableGpus.find(g => g.pciId === selectedGpuPciId); return DgopService.availableGpus.find(g => g.pciId === selectedGpuPciId);
} }
function formatBytes(bytes) {
if (bytes < 1024)
return bytes.toFixed(0) + "B";
if (bytes < 1024 * 1024)
return (bytes / 1024).toFixed(0) + "K";
if (bytes < 1024 * 1024 * 1024)
return (bytes / (1024 * 1024)).toFixed(1) + "M";
return (bytes / (1024 * 1024 * 1024)).toFixed(1) + "G";
}
function formatMemKB(kb) { function formatMemKB(kb) {
if (kb < 1024) if (kb < 1024)
return kb.toFixed(0) + "K"; return kb.toFixed(0) + "K";
@@ -206,26 +197,18 @@ Item {
return (kb / (1024 * 1024)).toFixed(1) + "G"; return (kb / (1024 * 1024)).toFixed(1) + "G";
} }
function addToHistory(arr, val) {
var newArr = arr.slice();
newArr.push(val);
if (newArr.length > historySize)
newArr.shift();
return newArr;
}
function sampleData() { function sampleData() {
if (showCpuGraph) if (showCpuGraph)
cpuHistory = addToHistory(cpuHistory, DgopService.cpuUsage); cpuHistory = Format.addToHistory(cpuHistory, DgopService.cpuUsage, historySize);
if (showMemoryGraph) if (showMemoryGraph)
memHistory = addToHistory(memHistory, DgopService.memoryUsage); memHistory = Format.addToHistory(memHistory, DgopService.memoryUsage, historySize);
if (showNetworkGraph) { if (showNetworkGraph) {
netRxHistory = addToHistory(netRxHistory, DgopService.networkRxRate); netRxHistory = Format.addToHistory(netRxHistory, DgopService.networkRxRate, historySize);
netTxHistory = addToHistory(netTxHistory, DgopService.networkTxRate); netTxHistory = Format.addToHistory(netTxHistory, DgopService.networkTxRate, historySize);
} }
if (showDisk) { if (showDisk) {
diskReadHistory = addToHistory(diskReadHistory, DgopService.diskReadRate); diskReadHistory = Format.addToHistory(diskReadHistory, DgopService.diskReadRate, historySize);
diskWriteHistory = addToHistory(diskWriteHistory, DgopService.diskWriteRate); diskWriteHistory = Format.addToHistory(diskWriteHistory, DgopService.diskWriteRate, historySize);
} }
} }
@@ -519,7 +502,7 @@ Item {
color: root.accentColor color: root.accentColor
} }
StyledText { StyledText {
text: root.formatBytes(DgopService.networkRxRate) + "/s" text: Format.formatBytes(DgopService.networkRxRate) + "/s"
isMonospace: true isMonospace: true
font.pixelSize: Theme.fontSizeMedium font.pixelSize: Theme.fontSizeMedium
color: root.textColor color: root.textColor
@@ -533,7 +516,7 @@ Item {
color: root.dimColor color: root.dimColor
} }
StyledText { StyledText {
text: root.formatBytes(DgopService.networkTxRate) + "/s" text: Format.formatBytes(DgopService.networkTxRate) + "/s"
isMonospace: true isMonospace: true
font.pixelSize: Theme.fontSizeMedium font.pixelSize: Theme.fontSizeMedium
color: root.textColor color: root.textColor
@@ -552,7 +535,7 @@ Item {
color: root.accentColor color: root.accentColor
} }
StyledText { StyledText {
text: root.formatBytes(DgopService.diskReadRate) + "/s" text: Format.formatBytes(DgopService.diskReadRate) + "/s"
isMonospace: true isMonospace: true
font.pixelSize: Theme.fontSizeMedium font.pixelSize: Theme.fontSizeMedium
color: root.textColor color: root.textColor
@@ -566,7 +549,7 @@ Item {
color: root.dimColor color: root.dimColor
} }
StyledText { StyledText {
text: root.formatBytes(DgopService.diskWriteRate) + "/s" text: Format.formatBytes(DgopService.diskWriteRate) + "/s"
isMonospace: true isMonospace: true
font.pixelSize: Theme.fontSizeMedium font.pixelSize: Theme.fontSizeMedium
color: root.textColor color: root.textColor
@@ -1,7 +1,7 @@
import QtQuick import QtQuick
import qs.Common import qs.Common
import qs.Services import qs.Services
import qs.Widgets import qs.Modules.ControlCenter.Details
import qs.Modules.Plugins import qs.Modules.Plugins
PluginComponent { PluginComponent {
@@ -1,131 +0,0 @@
import QtQuick
import qs.Common
import qs.Widgets
Rectangle {
id: root
LayoutMirroring.enabled: I18n.isRtl
LayoutMirroring.childrenInherit: true
property string iconName: ""
property string text: ""
property string secondaryText: ""
property bool isActive: false
property int widgetIndex: 0
property var widgetData: null
property bool editMode: false
signal clicked
width: parent ? parent.width : 200
height: 60
radius: {
if (Theme.cornerRadius === 0)
return 0;
return isActive ? Theme.cornerRadius : Theme.cornerRadius + 4;
}
readonly property color _tileBgActive: Theme.ccTileActiveBg
readonly property color _tileBgInactive: Theme.ccPillInactiveBg
readonly property color _tileRingActive: Theme.ccTileRing
color: isActive ? _tileBgActive : _tileBgInactive
border.color: isActive ? _tileRingActive : Theme.outlineMedium
border.width: isActive ? 1 : Theme.layerOutlineWidth
opacity: enabled ? 1.0 : 0.6
function hoverTint(base) {
const factor = 1.2;
return Theme.isLightMode ? Qt.darker(base, factor) : Qt.lighter(base, factor);
}
Rectangle {
anchors.fill: parent
radius: Theme.cornerRadius
color: mouseArea.containsMouse ? hoverTint(root.color) : Theme.withAlpha(hoverTint(root.color), 0)
opacity: mouseArea.containsMouse ? 0.08 : 0.0
Behavior on opacity {
NumberAnimation {
duration: Theme.shortDuration
}
}
}
Row {
anchors.fill: parent
anchors.leftMargin: Theme.spacingL + 2
anchors.rightMargin: Theme.spacingM
spacing: Theme.spacingM
DankIcon {
name: root.iconName
size: Theme.iconSize
color: isActive ? Theme.ccTileActiveText : Theme.ccTileInactiveIcon
anchors.verticalCenter: parent.verticalCenter
}
Item {
width: parent.width - Theme.iconSize - parent.spacing
height: parent.height
Column {
anchors.left: parent.left
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
spacing: Theme.spacingXXS
Typography {
width: parent.width
text: root.text
style: Typography.Style.Body
color: isActive ? Theme.ccTileActiveText : Theme.surfaceText
elide: Text.ElideRight
wrapMode: Text.NoWrap
horizontalAlignment: Text.AlignLeft
}
Typography {
width: parent.width
text: root.secondaryText
style: Typography.Style.Caption
color: isActive ? Theme.ccTileActiveText : Theme.surfaceVariantText
visible: text.length > 0
elide: Text.ElideRight
wrapMode: Text.NoWrap
horizontalAlignment: Text.AlignLeft
}
}
}
}
DankRipple {
id: ripple
cornerRadius: root.radius
}
MouseArea {
id: mouseArea
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
enabled: root.enabled
onPressed: mouse => ripple.trigger(mouse.x, mouse.y)
onClicked: root.clicked()
}
Behavior on color {
ColorAnimation {
duration: Theme.shortDuration
easing.type: Theme.standardEasing
}
}
Behavior on radius {
NumberAnimation {
duration: Theme.shortDuration
easing.type: Theme.standardEasing
}
}
}
@@ -1,91 +0,0 @@
import QtQuick
import qs.Common
import qs.Modules.ControlCenter.Details
Item {
id: root
property string expandedSection: ""
property var expandedWidgetData: null
height: active ? 250 : 0
visible: active
readonly property bool active: expandedSection !== ""
Loader {
anchors.fill: parent
anchors.topMargin: Theme.spacingS
sourceComponent: {
if (!root.active)
return null;
if (expandedSection.startsWith("diskUsage_")) {
return diskUsageDetailComponent;
}
switch (expandedSection) {
case "wifi":
return networkDetailComponent;
case "bluetooth":
return bluetoothDetailComponent;
case "audioOutput":
return audioOutputDetailComponent;
case "audioInput":
return audioInputDetailComponent;
case "battery":
return batteryDetailComponent;
default:
return null;
}
}
}
Component {
id: networkDetailComponent
NetworkDetail {}
}
Component {
id: bluetoothDetailComponent
BluetoothDetail {}
}
Component {
id: audioOutputDetailComponent
AudioOutputDetail {}
}
Component {
id: audioInputDetailComponent
AudioInputDetail {}
}
Component {
id: batteryDetailComponent
BatteryDetail {}
}
Component {
id: diskUsageDetailComponent
DiskUsageDetail {
currentMountPath: root.expandedWidgetData?.mountPath || "/"
instanceId: root.expandedWidgetData?.instanceId || ""
onMountPathChanged: newMountPath => {
if (root.expandedWidgetData && root.expandedWidgetData.id === "diskUsage") {
const widgets = SettingsData.controlCenterWidgets || [];
const newWidgets = widgets.map(w => {
if (w.id === "diskUsage" && w.instanceId === root.expandedWidgetData.instanceId) {
const updatedWidget = Object.assign({}, w);
updatedWidget.mountPath = newMountPath;
return updatedWidget;
}
return w;
});
SettingsData.set("controlCenterWidgets", newWidgets);
}
}
}
}
}
@@ -1,55 +0,0 @@
import QtQuick
import qs.Common
import qs.Widgets
Rectangle {
id: root
LayoutMirroring.enabled: I18n.isRtl
LayoutMirroring.childrenInherit: true
property string iconName: ""
property string text: ""
signal pressed
height: 34
radius: Theme.cornerRadius
color: mouseArea.containsMouse ? Theme.primaryHover : Theme.withAlpha(Theme.surfaceVariant, 0.5)
Row {
anchors.centerIn: parent
spacing: Theme.spacingXS
DankIcon {
name: root.iconName
size: Theme.fontSizeSmall
color: mouseArea.containsMouse ? Theme.primary : Theme.surfaceText
anchors.verticalCenter: parent.verticalCenter
}
Typography {
text: root.text
style: Typography.Style.Button
color: mouseArea.containsMouse ? Theme.primary : Theme.surfaceText
anchors.verticalCenter: parent.verticalCenter
}
}
DankRipple {
id: ripple
cornerRadius: root.radius
}
MouseArea {
id: mouseArea
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onPressed: mouse => {
ripple.trigger(mouse.x, mouse.y);
root.pressed();
}
}
}
@@ -4,6 +4,7 @@ import Quickshell.Services.Pipewire
import qs.Common import qs.Common
import qs.Services import qs.Services
import qs.Widgets import qs.Widgets
import "../../../Common/QmlUtils.js" as QmlUtils
Rectangle { Rectangle {
id: root id: root
@@ -150,17 +151,9 @@ Rectangle {
property int maxPinnedInputs: 3 property int maxPinnedInputs: 3
function normalizePinList(value) {
if (Array.isArray(value))
return value.filter(v => v);
if (typeof value === "string" && value.length > 0)
return [value];
return [];
}
function getPinnedInputs() { function getPinnedInputs() {
const pins = CacheData.audioInputDevicePins || {}; const pins = CacheData.audioInputDevicePins || {};
return normalizePinList(pins["preferredInput"]); return QmlUtils.normalizePinList(pins["preferredInput"]);
} }
Column { Column {
@@ -316,7 +309,7 @@ Rectangle {
onPressed: mouse => pinRipple.trigger(mouse.x, mouse.y) onPressed: mouse => pinRipple.trigger(mouse.x, mouse.y)
onClicked: { onClicked: {
const pins = JSON.parse(JSON.stringify(CacheData.audioInputDevicePins || {})); const pins = JSON.parse(JSON.stringify(CacheData.audioInputDevicePins || {}));
let pinnedList = audioContent.normalizePinList(pins["preferredInput"]); let pinnedList = QmlUtils.normalizePinList(pins["preferredInput"]);
const pinIndex = pinnedList.indexOf(modelData.name); const pinIndex = pinnedList.indexOf(modelData.name);
if (pinIndex !== -1) { if (pinIndex !== -1) {
@@ -4,6 +4,7 @@ import Quickshell.Services.Pipewire
import qs.Common import qs.Common
import qs.Services import qs.Services
import qs.Widgets import qs.Widgets
import "../../../Common/QmlUtils.js" as QmlUtils
Rectangle { Rectangle {
id: root id: root
@@ -160,17 +161,9 @@ Rectangle {
property int maxPinnedOutputs: 3 property int maxPinnedOutputs: 3
function normalizePinList(value) {
if (Array.isArray(value))
return value.filter(v => v);
if (typeof value === "string" && value.length > 0)
return [value];
return [];
}
function getPinnedOutputs() { function getPinnedOutputs() {
const pins = CacheData.audioOutputDevicePins || {}; const pins = CacheData.audioOutputDevicePins || {};
return normalizePinList(pins["preferredOutput"]); return QmlUtils.normalizePinList(pins["preferredOutput"]);
} }
Column { Column {
@@ -325,7 +318,7 @@ Rectangle {
onPressed: mouse => pinRipple.trigger(mouse.x, mouse.y) onPressed: mouse => pinRipple.trigger(mouse.x, mouse.y)
onClicked: { onClicked: {
const pins = JSON.parse(JSON.stringify(CacheData.audioOutputDevicePins || {})); const pins = JSON.parse(JSON.stringify(CacheData.audioOutputDevicePins || {}));
let pinnedList = audioContent.normalizePinList(pins["preferredOutput"]); let pinnedList = QmlUtils.normalizePinList(pins["preferredOutput"]);
const pinIndex = pinnedList.indexOf(modelData.name); const pinIndex = pinnedList.indexOf(modelData.name);
if (pinIndex !== -1) { if (pinIndex !== -1) {
@@ -5,6 +5,7 @@ import Quickshell.Bluetooth
import qs.Common import qs.Common
import qs.Services import qs.Services
import qs.Widgets import qs.Widgets
import "../../../Common/QmlUtils.js" as QmlUtils
Rectangle { Rectangle {
id: root id: root
@@ -95,17 +96,9 @@ Rectangle {
BluetoothService.updateDeviceCodec(deviceAddress, codecName); BluetoothService.updateDeviceCodec(deviceAddress, codecName);
} }
function normalizePinList(value) {
if (Array.isArray(value))
return value.filter(v => v);
if (typeof value === "string" && value.length > 0)
return [value];
return [];
}
function getPinnedDevices() { function getPinnedDevices() {
const pins = CacheData.bluetoothDevicePins || {}; const pins = CacheData.bluetoothDevicePins || {};
return normalizePinList(pins["preferredDevice"]); return QmlUtils.normalizePinList(pins["preferredDevice"]);
} }
Row { Row {
@@ -396,7 +389,7 @@ Rectangle {
cursorShape: Qt.PointingHandCursor cursorShape: Qt.PointingHandCursor
onClicked: { onClicked: {
const pins = JSON.parse(JSON.stringify(CacheData.bluetoothDevicePins || {})); const pins = JSON.parse(JSON.stringify(CacheData.bluetoothDevicePins || {}));
let pinnedList = root.normalizePinList(pins["preferredDevice"]); let pinnedList = QmlUtils.normalizePinList(pins["preferredDevice"]);
const pinIndex = pinnedList.indexOf(pairedDelegate.modelData.address); const pinIndex = pinnedList.indexOf(pairedDelegate.modelData.address);
if (pinIndex !== -1) { if (pinIndex !== -1) {
@@ -1,6 +1,7 @@
import QtQuick import QtQuick
import qs.Common import qs.Common
import qs.Widgets import qs.Widgets
import "../../../Common/Format.js" as Format
Rectangle { Rectangle {
id: root id: root
@@ -23,33 +24,8 @@ Rectangle {
onTriggered: root.nowMs = Date.now() onTriggered: root.nowMs = Date.now()
} }
function _pad2(n) {
return n < 10 ? "0" + n : "" + n;
}
function formatUntil(ts) {
if (!ts)
return "";
const d = new Date(ts);
const use24h = (typeof SettingsData !== "undefined") ? SettingsData.use24HourClock : true;
if (use24h)
return _pad2(d.getHours()) + ":" + _pad2(d.getMinutes());
const suffix = d.getHours() >= 12 ? "PM" : "AM";
const h12 = ((d.getHours() + 11) % 12) + 1;
return h12 + ":" + _pad2(d.getMinutes()) + " " + suffix;
}
function formatRemaining(ms) { function formatRemaining(ms) {
if (ms <= 0) return Format.formatRemaining(ms, "", I18n.tr("%1 min left"), I18n.tr("%1 h left"), I18n.tr("%1 h %2 m left"));
return "";
const totalMinutes = Math.ceil(ms / 60000);
if (totalMinutes < 60)
return I18n.tr("%1 min left").arg(totalMinutes);
const hours = Math.floor(totalMinutes / 60);
const mins = totalMinutes - hours * 60;
if (mins === 0)
return I18n.tr("%1 h left").arg(hours);
return I18n.tr("%1 h %2 m left").arg(hours).arg(mins);
} }
function minutesUntilTomorrowMorning() { function minutesUntilTomorrowMorning() {
@@ -125,7 +101,7 @@ Rectangle {
if (SessionData.doNotDisturbUntil <= 0) if (SessionData.doNotDisturbUntil <= 0)
return I18n.tr("On indefinitely"); return I18n.tr("On indefinitely");
const remaining = Math.max(0, SessionData.doNotDisturbUntil - root.nowMs); const remaining = Math.max(0, SessionData.doNotDisturbUntil - root.nowMs);
return root.formatRemaining(remaining) + " · " + I18n.tr("until %1").arg(root.formatUntil(SessionData.doNotDisturbUntil)); return root.formatRemaining(remaining) + " · " + I18n.tr("until %1").arg(Format.formatUntil(SessionData.doNotDisturbUntil, SettingsData.use24HourClock));
} }
font.pixelSize: Theme.fontSizeSmall font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceVariantText color: Theme.surfaceVariantText
@@ -7,6 +7,7 @@ import qs.Services
import qs.Widgets import qs.Widgets
import qs.Modals import qs.Modals
import qs.Modals.Common import qs.Modals.Common
import "../../../Common/QmlUtils.js" as QmlUtils
Rectangle { Rectangle {
id: root id: root
@@ -66,17 +67,9 @@ Rectangle {
PopoutService.openSettingsWithTab("network_wifi"); PopoutService.openSettingsWithTab("network_wifi");
} }
function normalizePinList(value) {
if (Array.isArray(value))
return value.filter(v => v);
if (typeof value === "string" && value.length > 0)
return [value];
return [];
}
function getPinnedNetworks() { function getPinnedNetworks() {
const pins = CacheData.wifiNetworkPins || {}; const pins = CacheData.wifiNetworkPins || {};
return normalizePinList(pins["preferredWifi"]); return QmlUtils.normalizePinList(pins["preferredWifi"]);
} }
property int currentPreferenceIndex: { property int currentPreferenceIndex: {
@@ -908,7 +901,7 @@ Rectangle {
onPressed: mouse => pinRipple.trigger(mouse.x, mouse.y) onPressed: mouse => pinRipple.trigger(mouse.x, mouse.y)
onClicked: { onClicked: {
const pins = JSON.parse(JSON.stringify(CacheData.wifiNetworkPins || {})); const pins = JSON.parse(JSON.stringify(CacheData.wifiNetworkPins || {}));
let pinnedList = root.normalizePinList(pins["preferredWifi"]); let pinnedList = QmlUtils.normalizePinList(pins["preferredWifi"]);
const pinIndex = pinnedList.indexOf(modelData.ssid); const pinIndex = pinnedList.indexOf(modelData.ssid);
if (pinIndex !== -1) { if (pinIndex !== -1) {
@@ -1,72 +0,0 @@
import QtQuick
import qs.Common
import qs.Widgets
Rectangle {
id: root
LayoutMirroring.enabled: I18n.isRtl
LayoutMirroring.childrenInherit: true
property string iconName: ""
property color iconColor: Theme.surfaceText
property string labelText: ""
property real value: 0.0
property real maximumValue: 1.0
property real minimumValue: 0.0
signal sliderValueChanged(real value)
width: parent ? parent.width : 200
height: 60
radius: Theme.cornerRadius
color: Theme.nestedSurface
border.color: Theme.outlineMedium
border.width: Theme.layerOutlineWidth
opacity: enabled ? 1.0 : 0.6
Row {
anchors.left: parent.left
anchors.verticalCenter: parent.verticalCenter
anchors.leftMargin: Theme.spacingM
anchors.right: sliderContainer.left
anchors.rightMargin: Theme.spacingS
spacing: Theme.spacingS
DankIcon {
name: root.iconName
size: Theme.iconSize
color: root.iconColor
anchors.verticalCenter: parent.verticalCenter
}
StyledText {
text: root.labelText
font.pixelSize: Theme.fontSizeMedium
color: Theme.surfaceText
font.weight: Font.Medium
anchors.verticalCenter: parent.verticalCenter
}
}
Rectangle {
id: sliderContainer
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
anchors.rightMargin: Theme.spacingM
width: 120
height: parent.height - Theme.spacingS * 2
DankSlider {
anchors.centerIn: parent
width: parent.width
enabled: root.enabled
minimum: Math.round(root.minimumValue * 100)
maximum: Math.round(root.maximumValue * 100)
value: Math.round(root.value * 100)
trackColor: Theme.ccSliderTrackColor
trackOpacity: Theme.ccSliderTrackOpacity
onSliderValueChanged: root.sliderValueChanged(newValue / 100.0)
}
}
}
@@ -25,11 +25,6 @@ Rectangle {
height: 60 height: 60
radius: Theme.cornerRadius radius: Theme.cornerRadius
function hoverTint(base) {
const factor = 1.2;
return Theme.isLightMode ? Qt.darker(base, factor) : Qt.lighter(base, factor);
}
readonly property color _containerBg: Theme.ccPillInactiveBg readonly property color _containerBg: Theme.ccPillInactiveBg
color: { color: {
@@ -61,7 +56,7 @@ Rectangle {
radius: root.radius radius: root.radius
z: 0 z: 0
visible: false visible: false
color: hoverTint(_containerBg) color: Theme.hoverTint(_containerBg)
opacity: 0.08 opacity: 0.08
antialiasing: true antialiasing: true
Behavior on opacity { Behavior on opacity {
@@ -98,7 +93,7 @@ Rectangle {
Rectangle { Rectangle {
anchors.fill: parent anchors.fill: parent
radius: _tileRadius radius: _tileRadius
color: hoverTint(iconTile.color) color: Theme.hoverTint(iconTile.color)
opacity: tileMouse.pressed ? 0.3 : (tileMouse.containsMouse ? 0.2 : 0.0) opacity: tileMouse.pressed ? 0.3 : (tileMouse.containsMouse ? 0.2 : 0.0)
visible: opacity > 0 visible: opacity > 0
antialiasing: true antialiasing: true
@@ -1,23 +0,0 @@
import QtQuick
Rectangle {
id: root
property string title: ""
property Component content: null
property bool isVisible: true
property int contentHeight: 300
width: parent ? parent.width : 400
implicitHeight: isVisible ? contentHeight : 0
height: implicitHeight
color: "transparent"
clip: true
Loader {
id: contentLoader
anchors.fill: parent
sourceComponent: root.content
asynchronous: true
}
}
@@ -22,11 +22,6 @@ Rectangle {
return isActive ? Theme.cornerRadius : Theme.cornerRadius + 4; return isActive ? Theme.cornerRadius : Theme.cornerRadius + 4;
} }
function hoverTint(base) {
const factor = 1.2;
return Theme.isLightMode ? Qt.darker(base, factor) : Qt.lighter(base, factor);
}
readonly property color _tileBgActive: Theme.ccTileActiveBg readonly property color _tileBgActive: Theme.ccTileActiveBg
readonly property color _tileBgInactive: Theme.ccPillInactiveBg readonly property color _tileBgInactive: Theme.ccPillInactiveBg
readonly property color _tileRingActive: Theme.ccTileRing readonly property color _tileRingActive: Theme.ccTileRing
@@ -47,7 +42,7 @@ Rectangle {
Rectangle { Rectangle {
anchors.fill: parent anchors.fill: parent
radius: parent.radius radius: parent.radius
color: hoverTint(root.color) color: Theme.hoverTint(root.color)
opacity: mouseArea.pressed ? 0.3 : (mouseArea.containsMouse ? 0.2 : 0.0) opacity: mouseArea.pressed ? 0.3 : (mouseArea.containsMouse ? 0.2 : 0.0)
visible: opacity > 0 visible: opacity > 0
antialiasing: true antialiasing: true
@@ -16,11 +16,6 @@ Rectangle {
height: 48 height: 48
radius: Theme.cornerRadius === 0 ? 0 : Theme.cornerRadius radius: Theme.cornerRadius === 0 ? 0 : Theme.cornerRadius
function hoverTint(base) {
const factor = 1.2;
return Theme.isLightMode ? Qt.darker(base, factor) : Qt.lighter(base, factor);
}
color: Theme.primary color: Theme.primary
border.color: Theme.ccTileRing border.color: Theme.ccTileRing
border.width: 1 border.width: 1
@@ -29,7 +24,7 @@ Rectangle {
Rectangle { Rectangle {
anchors.fill: parent anchors.fill: parent
radius: parent.radius radius: parent.radius
color: hoverTint(root.color) color: Theme.hoverTint(root.color)
opacity: mouseArea.pressed ? 0.3 : (mouseArea.containsMouse ? 0.2 : 0.0) opacity: mouseArea.pressed ? 0.3 : (mouseArea.containsMouse ? 0.2 : 0.0)
visible: opacity > 0 visible: opacity > 0
antialiasing: true antialiasing: true
@@ -25,11 +25,6 @@ Rectangle {
return isActive ? Theme.cornerRadius : Theme.cornerRadius + 4; return isActive ? Theme.cornerRadius : Theme.cornerRadius + 4;
} }
function hoverTint(base) {
const factor = 1.2;
return Theme.isLightMode ? Qt.darker(base, factor) : Qt.lighter(base, factor);
}
readonly property color _tileBgActive: Theme.ccTileActiveBg readonly property color _tileBgActive: Theme.ccTileActiveBg
readonly property color _tileBgInactive: Theme.ccPillInactiveBg readonly property color _tileBgInactive: Theme.ccPillInactiveBg
readonly property color _tileRingActive: Theme.ccTileRing readonly property color _tileRingActive: Theme.ccTileRing
@@ -50,7 +45,7 @@ Rectangle {
Rectangle { Rectangle {
anchors.fill: parent anchors.fill: parent
radius: parent.radius radius: parent.radius
color: hoverTint(root.color) color: Theme.hoverTint(root.color)
opacity: mouseArea.pressed ? 0.3 : (mouseArea.containsMouse ? 0.2 : 0.0) opacity: mouseArea.pressed ? 0.3 : (mouseArea.containsMouse ? 0.2 : 0.0)
visible: opacity > 0 visible: opacity > 0
antialiasing: true antialiasing: true
@@ -34,11 +34,6 @@ Rectangle {
height: 48 height: 48
radius: Theme.cornerRadius + 4 radius: Theme.cornerRadius + 4
function hoverTint(base) {
const factor = 1.2;
return Theme.isLightMode ? Qt.darker(base, factor) : Qt.lighter(base, factor);
}
readonly property color _tileBg: Theme.ccPillInactiveBg readonly property color _tileBg: Theme.ccPillInactiveBg
color: mouseArea.containsMouse ? Theme.ccPillInactiveHoverBg : _tileBg color: mouseArea.containsMouse ? Theme.ccPillInactiveHoverBg : _tileBg
@@ -50,7 +45,7 @@ Rectangle {
Rectangle { Rectangle {
anchors.fill: parent anchors.fill: parent
radius: parent.radius radius: parent.radius
color: hoverTint(root.color) color: Theme.hoverTint(root.color)
opacity: mouseArea.pressed ? 0.3 : (mouseArea.containsMouse ? 0.2 : 0.0) opacity: mouseArea.pressed ? 0.3 : (mouseArea.containsMouse ? 0.2 : 0.0)
visible: opacity > 0 visible: opacity > 0
antialiasing: true antialiasing: true
@@ -20,11 +20,6 @@ Rectangle {
return isActive ? Theme.cornerRadius : Theme.cornerRadius + 4; return isActive ? Theme.cornerRadius : Theme.cornerRadius + 4;
} }
function hoverTint(base) {
const factor = 1.2;
return Theme.isLightMode ? Qt.darker(base, factor) : Qt.lighter(base, factor);
}
readonly property color _tileBgActive: Theme.ccTileActiveBg readonly property color _tileBgActive: Theme.ccTileActiveBg
readonly property color _tileBgInactive: Theme.ccPillInactiveBg readonly property color _tileBgInactive: Theme.ccPillInactiveBg
readonly property color _tileRingActive: Theme.ccTileRing readonly property color _tileRingActive: Theme.ccTileRing
@@ -45,7 +40,7 @@ Rectangle {
Rectangle { Rectangle {
anchors.fill: parent anchors.fill: parent
radius: parent.radius radius: parent.radius
color: hoverTint(root.color) color: Theme.hoverTint(root.color)
opacity: mouseArea.pressed ? 0.3 : (mouseArea.containsMouse ? 0.2 : 0.0) opacity: mouseArea.pressed ? 0.3 : (mouseArea.containsMouse ? 0.2 : 0.0)
visible: opacity > 0 visible: opacity > 0
antialiasing: true antialiasing: true
@@ -39,17 +39,12 @@ Rectangle {
border.width: isActive ? 1 : Theme.layerOutlineWidth border.width: isActive ? 1 : Theme.layerOutlineWidth
opacity: enabled ? 1.0 : 0.6 opacity: enabled ? 1.0 : 0.6
function hoverTint(base) {
const factor = 1.2;
return Theme.isLightMode ? Qt.darker(base, factor) : Qt.lighter(base, factor);
}
readonly property color _containerBg: Theme.ccPillInactiveBg readonly property color _containerBg: Theme.ccPillInactiveBg
Rectangle { Rectangle {
anchors.fill: parent anchors.fill: parent
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: mouseArea.containsMouse ? hoverTint(_containerBg) : Theme.withAlpha(_containerBg, 0) color: mouseArea.containsMouse ? Theme.hoverTint(_containerBg) : Theme.withAlpha(_containerBg, 0)
opacity: mouseArea.containsMouse ? 0.08 : 0.0 opacity: mouseArea.containsMouse ? 0.08 : 0.0
Behavior on opacity { Behavior on opacity {
+1 -17
View File
@@ -274,22 +274,6 @@ Item {
return ws.num !== -1 ? ws.num : ws.name; return ws.num !== -1 ? ws.num : ws.name;
} }
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 (_) {}
}
function switchWorkspace(direction) { function switchWorkspace(direction) {
const realWorkspaces = getRealWorkspaces(); const realWorkspaces = getRealWorkspaces();
if (realWorkspaces.length < 2) { if (realWorkspaces.length < 2) {
@@ -334,7 +318,7 @@ Item {
const nextIndex = direction > 0 ? Math.min(validIndex + 1, realWorkspaces.length - 1) : Math.max(validIndex - 1, 0); const nextIndex = direction > 0 ? Math.min(validIndex + 1, realWorkspaces.length - 1) : Math.max(validIndex - 1, 0);
if (nextIndex !== validIndex) { if (nextIndex !== validIndex) {
dispatchSwayWorkspace(realWorkspaces[nextIndex]); CompositorService.dispatchSwayWorkspace(realWorkspaces[nextIndex]);
} }
} }
} }
@@ -3,6 +3,7 @@ import QtQuick.Layouts
import qs.Common import qs.Common
import qs.Services import qs.Services
import qs.Widgets import qs.Widgets
import qs.Modules.ControlCenter.Details
DankPopout { DankPopout {
id: root id: root
@@ -3,22 +3,11 @@ import qs.Common
import qs.Modules.Plugins import qs.Modules.Plugins
import qs.Services import qs.Services
import qs.Widgets import qs.Widgets
import "../../../Common/Format.js" as Format
BasePill { BasePill {
id: root id: root
function formatNetworkSpeed(bytesPerSec) {
if (bytesPerSec < 1024) {
return bytesPerSec.toFixed(0) + " B/s";
} else if (bytesPerSec < 1024 * 1024) {
return (bytesPerSec / 1024).toFixed(1) + " KB/s";
} else if (bytesPerSec < 1024 * 1024 * 1024) {
return (bytesPerSec / (1024 * 1024)).toFixed(1) + " MB/s";
} else {
return (bytesPerSec / (1024 * 1024 * 1024)).toFixed(1) + " GB/s";
}
}
Component.onCompleted: { Component.onCompleted: {
DgopService.addRef(["network"]); DgopService.addRef(["network"]);
} }
@@ -97,7 +86,7 @@ BasePill {
} }
StyledText { StyledText {
text: DgopService.networkRxRate > 0 ? root.formatNetworkSpeed(DgopService.networkRxRate) : "0 B/s" text: DgopService.networkRxRate > 0 ? Format.formatRate(DgopService.networkRxRate, 1) : "0 B/s"
font.pixelSize: Theme.barTextSize(root.barThickness, root.barConfig?.fontScale, root.barConfig?.maximizeWidgetText) font.pixelSize: Theme.barTextSize(root.barThickness, root.barConfig?.fontScale, root.barConfig?.maximizeWidgetText)
color: Theme.widgetTextColor color: Theme.widgetTextColor
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
@@ -126,7 +115,7 @@ BasePill {
} }
StyledText { StyledText {
text: DgopService.networkTxRate > 0 ? root.formatNetworkSpeed(DgopService.networkTxRate) : "0 B/s" text: DgopService.networkTxRate > 0 ? Format.formatRate(DgopService.networkTxRate, 1) : "0 B/s"
font.pixelSize: Theme.barTextSize(root.barThickness, root.barConfig?.fontScale, root.barConfig?.maximizeWidgetText) font.pixelSize: Theme.barTextSize(root.barThickness, root.barConfig?.fontScale, root.barConfig?.maximizeWidgetText)
color: Theme.widgetTextColor color: Theme.widgetTextColor
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
@@ -228,22 +228,6 @@ Item {
return ws.num !== -1 ? ws.num : ws.name; return ws.num !== -1 ? ws.num : ws.name;
} }
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 (_) {}
}
function getSwayActiveWorkspace() { function getSwayActiveWorkspace() {
if (!root.screenName || SettingsData.workspaceFollowFocus) { if (!root.screenName || SettingsData.workspaceFollowFocus) {
const focusedWs = I3.workspaces?.values?.find(ws => ws.focused === true); const focusedWs = I3.workspaces?.values?.find(ws => ws.focused === true);
@@ -711,7 +695,7 @@ Item {
case "sway": case "sway":
case "scroll": case "scroll":
case "miracle": case "miracle":
dispatchSwayWorkspace(data); CompositorService.dispatchSwayWorkspace(data);
break; break;
} }
} }
@@ -818,7 +802,7 @@ Item {
return; return;
} }
dispatchSwayWorkspace(realWorkspaces[nextIndex]); CompositorService.dispatchSwayWorkspace(realWorkspaces[nextIndex]);
} }
} }
@@ -1486,7 +1470,7 @@ Item {
} else if (root.isMango && modelData?.tag !== undefined) { } else if (root.isMango && modelData?.tag !== undefined) {
MangoService.switchToTag(root.screenName, modelData.tag); MangoService.switchToTag(root.screenName, modelData.tag);
} else if ((CompositorService.isSway || CompositorService.isScroll || CompositorService.isMiracle) && modelData?.num !== undefined) { } else if ((CompositorService.isSway || CompositorService.isScroll || CompositorService.isMiracle) && modelData?.num !== undefined) {
root.dispatchSwayWorkspace(modelData); CompositorService.dispatchSwayWorkspace(modelData);
} }
} else if (mouse.button === Qt.RightButton) { } else if (mouse.button === Qt.RightButton) {
if (CompositorService.isNiri) { if (CompositorService.isNiri) {
@@ -415,11 +415,24 @@ Item {
} }
} }
onWheel: wheelEvent => { onWheel: wheelEvent => {
if (SettingsData.audioDeviceScrollVolumeEnabled && wheelEvent.x >= deviceMouseArea.width / 2) { if (!SettingsData.audioDeviceScrollVolumeEnabled || wheelEvent.x < deviceMouseArea.width / 2) {
AudioService.handleNodeVolumeWheel(modelData, wheelEvent);
} else {
wheelEvent.accepted = false; wheelEvent.accepted = false;
return;
} }
if (!modelData?.audio)
return;
SessionData.suppressOSDTemporarily();
const delta = wheelEvent.angleDelta.y;
if (delta === 0)
return;
const current = Math.round(modelData.audio.volume * 100);
const maxVol = AudioService.getMaxVolumePercent(modelData);
const newVolume = delta > 0 ? Math.min(maxVol, current + AudioService.wheelVolumeStep) : Math.max(0, current - AudioService.wheelVolumeStep);
modelData.audio.muted = false;
modelData.audio.volume = newVolume / 100;
if (modelData === AudioService.sink)
AudioService.playVolumeChangeSoundIfEnabled();
wheelEvent.accepted = true;
} }
onClicked: mouse => { onClicked: mouse => {
if (mouse.button === Qt.RightButton) { if (mouse.button === Qt.RightButton) {
@@ -451,6 +451,9 @@ Item {
height: width height: width
anchors.centerIn: parent anchors.centerIn: parent
activePlayer: root.activePlayer activePlayer: root.activePlayer
artUrl: TrackArtService.resolvedArtUrl
accentColor: MediaAccentService.accent
cavaService: CavaService
} }
} }
@@ -522,6 +525,10 @@ Item {
height: 20 height: 20
anchors.horizontalCenter: parent.horizontalCenter anchors.horizontalCenter: parent.horizontalCenter
activePlayer: root.activePlayer activePlayer: root.activePlayer
stableLength: MprisController.activePlayerStableLength
accentColor: MediaAccentService.accent
accentTrackColor: MediaAccentService.accentTrack
accentSubtleColor: MediaAccentService.accentSubtle
isSeeking: root.isSeeking isSeeking: root.isSeeking
onIsSeekingChanged: root.isSeeking = isSeeking onIsSeekingChanged: root.isSeeking = isSeeking
} }
@@ -77,6 +77,9 @@ Card {
height: 80 height: 80
anchors.centerIn: parent anchors.centerIn: parent
activePlayer: root.activePlayer activePlayer: root.activePlayer
artUrl: TrackArtService.resolvedArtUrl
accentColor: MediaAccentService.accent
cavaService: CavaService
albumSize: 76 albumSize: 76
animationScale: 1.05 animationScale: 1.05
} }
@@ -114,6 +117,10 @@ Card {
height: 20 height: 20
x: -2 x: -2
activePlayer: root.activePlayer activePlayer: root.activePlayer
stableLength: MprisController.activePlayerStableLength
accentColor: MediaAccentService.accent
accentTrackColor: MediaAccentService.accentTrack
accentSubtleColor: MediaAccentService.accentSubtle
isSeeking: root.isSeeking isSeeking: root.isSeeking
onIsSeekingChanged: root.isSeeking = isSeeking onIsSeekingChanged: root.isSeeking = isSeeking
} }
+4 -8
View File
@@ -114,10 +114,6 @@ Item {
readonly property real positionSpacing: barSpacing + effectiveDockBottomGap + effectiveDockMargin readonly property real positionSpacing: barSpacing + effectiveDockBottomGap + effectiveDockMargin
readonly property real joinedEdgeMargin: dockGeometry.joinedEdgeMargin readonly property real joinedEdgeMargin: dockGeometry.joinedEdgeMargin
readonly property real _dpr: (dock.screen && dock.screen.devicePixelRatio) ? dock.screen.devicePixelRatio : 1 readonly property real _dpr: (dock.screen && dock.screen.devicePixelRatio) ? dock.screen.devicePixelRatio : 1
function px(v) {
return Math.round(v * _dpr) / _dpr;
}
DockGeometry { DockGeometry {
id: dockGeometry id: dockGeometry
@@ -397,8 +393,8 @@ Item {
property real animationHeadroom: Math.ceil(SettingsData.dockIconSize * 0.35) property real animationHeadroom: Math.ceil(SettingsData.dockIconSize * 0.35)
readonly property real surfaceImplicitWidth: isVertical ? (px(dockGeometry.surfaceThickness + SettingsData.dockIconSize * 0.3) + animationHeadroom) : 0 readonly property real surfaceImplicitWidth: isVertical ? (Theme.px(dockGeometry.surfaceThickness + SettingsData.dockIconSize * 0.3, _dpr) + animationHeadroom) : 0
readonly property real surfaceImplicitHeight: !isVertical ? (px(dockGeometry.surfaceThickness + SettingsData.dockIconSize * 0.3) + animationHeadroom) : 0 readonly property real surfaceImplicitHeight: !isVertical ? (Theme.px(dockGeometry.surfaceThickness + SettingsData.dockIconSize * 0.3, _dpr) + animationHeadroom) : 0
readonly property real blurX: dockBackground.x + dockContainer.x + dockMouseArea.x + dockCore.x + dockSlide.x readonly property real blurX: dockBackground.x + dockContainer.x + dockMouseArea.x + dockCore.x + dockSlide.x
readonly property real blurY: dockBackground.y + dockContainer.y + dockMouseArea.y + dockCore.y + dockSlide.y readonly property real blurY: dockBackground.y + dockContainer.y + dockMouseArea.y + dockCore.y + dockSlide.y
@@ -585,11 +581,11 @@ Item {
// Keep the taller hit area regardless of the reveal state to prevent shrinking loop // Keep the taller hit area regardless of the reveal state to prevent shrinking loop
return Math.min(Math.max(dockBackground.height + 64, 200), maxDockHeight); return Math.min(Math.max(dockBackground.height + 64, 200), maxDockHeight);
} }
return dock.reveal ? px(dockGeometry.motionThickness) : 1; return dock.reveal ? Theme.px(dockGeometry.motionThickness, _dpr) : 1;
} }
width: { width: {
if (dock.isVertical) { if (dock.isVertical) {
return dock.reveal ? px(dockGeometry.motionThickness) : 1; return dock.reveal ? Theme.px(dockGeometry.motionThickness, _dpr) : 1;
} }
// Keep the wider hit area regardless of the reveal state to prevent shrinking loop // Keep the wider hit area regardless of the reveal state to prevent shrinking loop
return Math.min(dockBackground.width + 8 + dock.borderThickness, maxDockWidth); return Math.min(dockBackground.width + 8 + dock.borderThickness, maxDockWidth);
+1 -5
View File
@@ -19,10 +19,6 @@ QtObject {
property real barSpacing: 0 property real barSpacing: 0
property real dpr: 1 property real dpr: 1
function px(value) {
return Math.round(value * dpr) / dpr;
}
readonly property bool frameExclusionActive: CompositorService.frameWindowVisibleForScreen(screen) readonly property bool frameExclusionActive: CompositorService.frameWindowVisibleForScreen(screen)
readonly property bool usesConnectedFrameChrome: CompositorService.usesConnectedFrameChromeForScreen(screen) readonly property bool usesConnectedFrameChrome: CompositorService.usesConnectedFrameChromeForScreen(screen)
readonly property bool connectedBarActiveOnEdge: usesConnectedFrameChrome && !!screen && SettingsData.getActiveBarEdgesForScreen(screen).includes(edge) readonly property bool connectedBarActiveOnEdge: usesConnectedFrameChrome && !!screen && SettingsData.getActiveBarEdgesForScreen(screen).includes(edge)
@@ -56,6 +52,6 @@ QtObject {
// Frame/bar edge exclusions already reserve the edge itself, so the dock // Frame/bar edge exclusions already reserve the edge itself, so the dock
// reservation covers only the dock body and user offset beyond that edge. // reservation covers only the dock body and user offset beyond that edge.
readonly property real reserveZone: px(bodyThickness + reserveOffset + effectiveMargin) readonly property real reserveZone: Theme.px(bodyThickness + reserveOffset + effectiveMargin, dpr)
readonly property bool shouldReserveSpace: dockVisible && !autoHide && barSpacing <= 0 readonly property bool shouldReserveSpace: dockVisible && !autoHide && barSpacing <= 0
} }
@@ -2,6 +2,7 @@ import QtQuick
import qs.Common import qs.Common
import qs.Services import qs.Services
import qs.Widgets import qs.Widgets
import "../../../Common/Format.js" as Format
Rectangle { Rectangle {
id: root id: root
@@ -22,36 +23,8 @@ Rectangle {
onTriggered: root.nowMs = Date.now() onTriggered: root.nowMs = Date.now()
} }
function _pad2(n) {
return n < 10 ? "0" + n : "" + n;
}
function formatRemaining(ms) { function formatRemaining(ms) {
if (ms <= 0) return Format.formatRemaining(ms, I18n.tr("Off"), I18n.tr("%1 min left"), I18n.tr("%1 h left"), I18n.tr("%1 h %2 m left"));
return I18n.tr("Off");
const totalMinutes = Math.ceil(ms / 60000);
if (totalMinutes < 60)
return I18n.tr("%1 min left").arg(totalMinutes);
const hours = Math.floor(totalMinutes / 60);
const mins = totalMinutes - hours * 60;
if (mins === 0)
return I18n.tr("%1 h left").arg(hours);
return I18n.tr("%1 h %2 m left").arg(hours).arg(mins);
}
function formatUntilTimestamp(ts) {
if (!ts)
return "";
const d = new Date(ts);
const hours = d.getHours();
const minutes = d.getMinutes();
const use24h = (typeof SettingsData !== "undefined") ? SettingsData.use24HourClock : true;
if (use24h) {
return _pad2(hours) + ":" + _pad2(minutes);
}
const suffix = hours >= 12 ? "PM" : "AM";
const h12 = ((hours + 11) % 12) + 1;
return h12 + ":" + _pad2(minutes) + " " + suffix;
} }
function minutesUntilTomorrowMorning() { function minutesUntilTomorrowMorning() {
@@ -149,7 +122,7 @@ Rectangle {
visible: root.currentlyActive visible: root.currentlyActive
text: { text: {
if (SessionData.doNotDisturbUntil > 0) { if (SessionData.doNotDisturbUntil > 0) {
return root.formatRemaining(root.currentRemainingMs) + " · " + I18n.tr("until %1").arg(root.formatUntilTimestamp(SessionData.doNotDisturbUntil)); return root.formatRemaining(root.currentRemainingMs) + " · " + I18n.tr("until %1").arg(Format.formatUntil(SessionData.doNotDisturbUntil, SettingsData.use24HourClock));
} }
return I18n.tr("On indefinitely"); return I18n.tr("On indefinitely");
} }
@@ -27,6 +27,36 @@ Rectangle {
readonly property real collapsedContentHeight: iconSize + cardPadding readonly property real collapsedContentHeight: iconSize + cardPadding
readonly property real baseCardHeight: cardPadding * 2 + collapsedContentHeight readonly property real baseCardHeight: cardPadding * 2 + collapsedContentHeight
function formatHistoryTime(timestamp) {
NotificationService.timeUpdateTick;
NotificationService.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;
}
}
width: parent ? parent.width : 400 width: parent ? parent.width : 400
height: baseCardHeight + contentItem.extraHeight height: baseCardHeight + contentItem.extraHeight
radius: Theme.cornerRadius radius: Theme.cornerRadius
@@ -219,7 +249,7 @@ Rectangle {
} }
StyledText { StyledText {
id: historyTimeText id: historyTimeText
text: NotificationService.formatHistoryTime(historyItem.timestamp) text: root.formatHistoryTime(historyItem.timestamp)
color: Theme.surfaceTextMedium color: Theme.surfaceTextMedium
font.pixelSize: Theme.fontSizeSmall font.pixelSize: Theme.fontSizeSmall
font.weight: Font.Normal font.weight: Font.Normal
+3 -13
View File
@@ -2,6 +2,7 @@ import QtQuick
import qs.Common import qs.Common
import qs.Services import qs.Services
import qs.Widgets import qs.Widgets
import "../../Common/QmlUtils.js" as QmlUtils
Column { Column {
id: root id: root
@@ -18,7 +19,7 @@ Column {
property bool isInitialized: false property bool isInitialized: false
function loadValue() { function loadValue() {
const settings = findSettings(); const settings = QmlUtils.findSettings(root.parent);
if (settings && settings.pluginService) { if (settings && settings.pluginService) {
const loadedValue = settings.loadValue(settingKey, defaultValue); const loadedValue = settings.loadValue(settingKey, defaultValue);
value = loadedValue; value = loadedValue;
@@ -33,23 +34,12 @@ Column {
onValueChanged: { onValueChanged: {
if (!isInitialized) if (!isInitialized)
return; return;
const settings = findSettings(); const settings = QmlUtils.findSettings(root.parent);
if (settings) { if (settings) {
settings.saveValue(settingKey, value); settings.saveValue(settingKey, value);
} }
} }
function findSettings() {
let item = parent;
while (item) {
if (item.saveValue !== undefined && item.loadValue !== undefined) {
return item;
}
item = item.parent;
}
return null;
}
StyledText { StyledText {
text: root.label text: root.label
font.pixelSize: Theme.fontSizeMedium font.pixelSize: Theme.fontSizeMedium
+3 -13
View File
@@ -1,6 +1,7 @@
import QtQuick import QtQuick
import qs.Common import qs.Common
import qs.Widgets import qs.Widgets
import "../../Common/QmlUtils.js" as QmlUtils
Column { Column {
id: root id: root
@@ -16,30 +17,19 @@ Column {
spacing: Theme.spacingM spacing: Theme.spacingM
Component.onCompleted: { Component.onCompleted: {
const settings = findSettings(); const settings = QmlUtils.findSettings(root.parent);
if (settings) { if (settings) {
items = settings.loadValue(settingKey, defaultValue); items = settings.loadValue(settingKey, defaultValue);
} }
} }
onItemsChanged: { onItemsChanged: {
const settings = findSettings(); const settings = QmlUtils.findSettings(root.parent);
if (settings) { if (settings) {
settings.saveValue(settingKey, items); settings.saveValue(settingKey, items);
} }
} }
function findSettings() {
let item = parent;
while (item) {
if (item.saveValue !== undefined && item.loadValue !== undefined) {
return item;
}
item = item.parent;
}
return null;
}
function addItem(item) { function addItem(item) {
items = items.concat([item]); items = items.concat([item]);
} }
@@ -1,6 +1,7 @@
import QtQuick import QtQuick
import qs.Common import qs.Common
import qs.Widgets import qs.Widgets
import "../../Common/QmlUtils.js" as QmlUtils
Column { Column {
id: root id: root
@@ -22,7 +23,7 @@ Column {
} }
function loadValue() { function loadValue() {
const settings = findSettings(); const settings = QmlUtils.findSettings(root.parent);
if (settings) { if (settings) {
isLoading = true; isLoading = true;
items = settings.loadValue(settingKey, defaultValue); items = settings.loadValue(settingKey, defaultValue);
@@ -34,23 +35,12 @@ Column {
if (isLoading) { if (isLoading) {
return; return;
} }
const settings = findSettings(); const settings = QmlUtils.findSettings(root.parent);
if (settings) { if (settings) {
settings.saveValue(settingKey, items); settings.saveValue(settingKey, items);
} }
} }
function findSettings() {
let item = parent;
while (item) {
if (item.saveValue !== undefined && item.loadValue !== undefined) {
return item;
}
item = item.parent;
}
return null;
}
function addItem(item) { function addItem(item) {
items = items.concat([item]); items = items.concat([item]);
} }
@@ -1,43 +0,0 @@
import QtQuick
import qs.Common
import qs.Services
import qs.Widgets
Item {
id: root
property string pluginId: ""
property var pluginInstance: null
property bool isCompoundPill: false
property bool isSmallToggle: false
readonly property bool hasDetail: pluginInstance?.ccDetailContent !== null
readonly property string iconName: pluginInstance?.ccWidgetIcon || "extension"
readonly property string primaryText: pluginInstance?.ccWidgetPrimaryText || "Plugin"
readonly property string secondaryText: pluginInstance?.ccWidgetSecondaryText || ""
readonly property bool isActive: pluginInstance?.ccWidgetIsActive || false
readonly property Component detailContent: pluginInstance?.ccDetailContent || null
readonly property real detailHeight: pluginInstance?.ccDetailHeight || 250
signal toggled
signal expanded
Component.onCompleted: {
if (pluginInstance) {
pluginInstance.ccWidgetToggled.connect(toggled);
pluginInstance.ccWidgetExpanded.connect(expanded);
}
}
function invokeToggle() {
if (pluginInstance) {
pluginInstance.ccWidgetToggled();
}
}
function invokeExpand() {
if (pluginInstance) {
pluginInstance.ccWidgetExpanded();
}
}
}
+20 -30
View File
@@ -1,6 +1,7 @@
import QtQuick import QtQuick
import qs.Common import qs.Common
import qs.Widgets import qs.Widgets
import "../../Common/QmlUtils.js" as QmlUtils
Column { Column {
id: root id: root
@@ -16,68 +17,57 @@ Column {
spacing: Theme.spacingS spacing: Theme.spacingS
function loadValue() { function loadValue() {
const settings = findSettings() const settings = QmlUtils.findSettings(root.parent);
if (settings && settings.pluginService) { if (settings && settings.pluginService) {
value = settings.loadValue(settingKey, defaultValue) value = settings.loadValue(settingKey, defaultValue);
} }
} }
Component.onCompleted: { Component.onCompleted: {
loadValue() loadValue();
} }
readonly property var optionLabels: { readonly property var optionLabels: {
const labels = [] const labels = [];
for (let i = 0; i < options.length; i++) { for (let i = 0; i < options.length; i++) {
labels.push(options[i].label || options[i]) labels.push(options[i].label || options[i]);
} }
return labels return labels;
} }
readonly property var valueToLabel: { readonly property var valueToLabel: {
const map = {} const map = {};
for (let i = 0; i < options.length; i++) { for (let i = 0; i < options.length; i++) {
const opt = options[i] const opt = options[i];
if (typeof opt === 'object') { if (typeof opt === 'object') {
map[opt.value] = opt.label map[opt.value] = opt.label;
} else { } else {
map[opt] = opt map[opt] = opt;
} }
} }
return map return map;
} }
readonly property var labelToValue: { readonly property var labelToValue: {
const map = {} const map = {};
for (let i = 0; i < options.length; i++) { for (let i = 0; i < options.length; i++) {
const opt = options[i] const opt = options[i];
if (typeof opt === 'object') { if (typeof opt === 'object') {
map[opt.label] = opt.value map[opt.label] = opt.value;
} else { } else {
map[opt] = opt map[opt] = opt;
} }
} }
return map return map;
} }
onValueChanged: { onValueChanged: {
const settings = findSettings() const settings = QmlUtils.findSettings(root.parent);
if (settings) { if (settings) {
settings.saveValue(settingKey, value) settings.saveValue(settingKey, value);
} }
} }
function findSettings() {
let item = parent
while (item) {
if (item.saveValue !== undefined && item.loadValue !== undefined) {
return item
}
item = item.parent
}
return null
}
DankDropdown { DankDropdown {
width: parent.width width: parent.width
text: root.label text: root.label
@@ -85,7 +75,7 @@ Column {
currentValue: root.valueToLabel[root.value] || root.value currentValue: root.valueToLabel[root.value] || root.value
options: root.optionLabels options: root.optionLabels
onValueChanged: newValue => { onValueChanged: newValue => {
root.value = root.labelToValue[newValue] || newValue root.value = root.labelToValue[newValue] || newValue;
} }
} }
} }
+3 -13
View File
@@ -1,6 +1,7 @@
import QtQuick import QtQuick
import qs.Common import qs.Common
import qs.Widgets import qs.Widgets
import "../../Common/QmlUtils.js" as QmlUtils
Column { Column {
id: root id: root
@@ -20,7 +21,7 @@ Column {
spacing: Theme.spacingS spacing: Theme.spacingS
function loadValue() { function loadValue() {
const settings = findSettings(); const settings = QmlUtils.findSettings(root.parent);
if (settings && settings.pluginService) { if (settings && settings.pluginService) {
value = settings.loadValue(settingKey, defaultValue); value = settings.loadValue(settingKey, defaultValue);
} }
@@ -31,23 +32,12 @@ Column {
} }
onValueChanged: { onValueChanged: {
const settings = findSettings(); const settings = QmlUtils.findSettings(root.parent);
if (settings) { if (settings) {
settings.saveValue(settingKey, value); settings.saveValue(settingKey, value);
} }
} }
function findSettings() {
let item = parent;
while (item) {
if (item.saveValue !== undefined && item.loadValue !== undefined) {
return item;
}
item = item.parent;
}
return null;
}
StyledText { StyledText {
text: root.label text: root.label
font.pixelSize: Theme.fontSizeMedium font.pixelSize: Theme.fontSizeMedium
+3 -13
View File
@@ -1,6 +1,7 @@
import QtQuick import QtQuick
import qs.Common import qs.Common
import qs.Widgets import qs.Widgets
import "../../Common/QmlUtils.js" as QmlUtils
Column { Column {
id: root id: root
@@ -18,7 +19,7 @@ Column {
property bool isInitialized: false property bool isInitialized: false
function loadValue() { function loadValue() {
const settings = findSettings(); const settings = QmlUtils.findSettings(root.parent);
if (settings && settings.pluginService) { if (settings && settings.pluginService) {
const loadedValue = settings.loadValue(settingKey, defaultValue); const loadedValue = settings.loadValue(settingKey, defaultValue);
if (textField.activeFocus && isInitialized) if (textField.activeFocus && isInitialized)
@@ -39,22 +40,11 @@ Column {
if (textField.text === value) if (textField.text === value)
return; return;
value = textField.text; value = textField.text;
const settings = findSettings(); const settings = QmlUtils.findSettings(root.parent);
if (settings) if (settings)
settings.saveValue(settingKey, value); settings.saveValue(settingKey, value);
} }
function findSettings() {
let item = parent;
while (item) {
if (item.saveValue !== undefined && item.loadValue !== undefined) {
return item;
}
item = item.parent;
}
return null;
}
StyledText { StyledText {
text: root.label text: root.label
font.pixelSize: Theme.fontSizeMedium font.pixelSize: Theme.fontSizeMedium
+3 -13
View File
@@ -1,6 +1,7 @@
import QtQuick import QtQuick
import qs.Common import qs.Common
import qs.Widgets import qs.Widgets
import "../../Common/QmlUtils.js" as QmlUtils
Row { Row {
id: root id: root
@@ -17,7 +18,7 @@ Row {
property bool isInitialized: false property bool isInitialized: false
function loadValue() { function loadValue() {
const settings = findSettings(); const settings = QmlUtils.findSettings(root.parent);
if (settings && settings.pluginService) { if (settings && settings.pluginService) {
const loadedValue = settings.loadValue(settingKey, defaultValue); const loadedValue = settings.loadValue(settingKey, defaultValue);
value = loadedValue; value = loadedValue;
@@ -32,23 +33,12 @@ Row {
onValueChanged: { onValueChanged: {
if (!isInitialized) if (!isInitialized)
return; return;
const settings = findSettings(); const settings = QmlUtils.findSettings(root.parent);
if (settings) { if (settings) {
settings.saveValue(settingKey, value); settings.saveValue(settingKey, value);
} }
} }
function findSettings() {
let item = parent;
while (item) {
if (item.saveValue !== undefined && item.loadValue !== undefined) {
return item;
}
item = item.parent;
}
return null;
}
Column { Column {
width: parent.width - toggle.width - Theme.spacingM width: parent.width - toggle.width - Theme.spacingM
spacing: Theme.spacingXS spacing: Theme.spacingXS
+3 -12
View File
@@ -3,20 +3,11 @@ import QtQuick.Layouts
import qs.Common import qs.Common
import qs.Services import qs.Services
import qs.Widgets import qs.Widgets
import "../../Common/Format.js" as Format
Item { Item {
id: root id: root
function formatSpeed(bytesPerSec) {
if (bytesPerSec < 1024)
return bytesPerSec.toFixed(0) + " B/s";
if (bytesPerSec < 1024 * 1024)
return (bytesPerSec / 1024).toFixed(1) + " KB/s";
if (bytesPerSec < 1024 * 1024 * 1024)
return (bytesPerSec / (1024 * 1024)).toFixed(1) + " MB/s";
return (bytesPerSec / (1024 * 1024 * 1024)).toFixed(2) + " GB/s";
}
Component.onCompleted: { Component.onCompleted: {
DgopService.addRef(["disk", "diskmounts"]); DgopService.addRef(["disk", "diskmounts"]);
} }
@@ -76,7 +67,7 @@ Item {
} }
StyledText { StyledText {
text: root.formatSpeed(DgopService.diskReadRate) text: Format.formatRate(DgopService.diskReadRate)
font.pixelSize: Theme.fontSizeSmall font.pixelSize: Theme.fontSizeSmall
font.family: SettingsData.monoFontFamily font.family: SettingsData.monoFontFamily
font.weight: Font.Bold font.weight: Font.Bold
@@ -94,7 +85,7 @@ Item {
} }
StyledText { StyledText {
text: root.formatSpeed(DgopService.diskWriteRate) text: Format.formatRate(DgopService.diskWriteRate)
font.pixelSize: Theme.fontSizeSmall font.pixelSize: Theme.fontSizeSmall
font.family: SettingsData.monoFontFamily font.family: SettingsData.monoFontFamily
font.weight: Font.Bold font.weight: Font.Bold
@@ -4,6 +4,7 @@ import Quickshell
import qs.Common import qs.Common
import qs.Services import qs.Services
import qs.Widgets import qs.Widgets
import "../../Common/Format.js" as Format
Item { Item {
id: root id: root
@@ -17,31 +18,13 @@ Item {
property var diskReadHistory: [] property var diskReadHistory: []
property var diskWriteHistory: [] property var diskWriteHistory: []
function formatBytes(bytes) {
if (bytes < 1024)
return bytes.toFixed(0) + " B/s";
if (bytes < 1024 * 1024)
return (bytes / 1024).toFixed(1) + " KB/s";
if (bytes < 1024 * 1024 * 1024)
return (bytes / (1024 * 1024)).toFixed(1) + " MB/s";
return (bytes / (1024 * 1024 * 1024)).toFixed(2) + " GB/s";
}
function addToHistory(arr, val) {
const newArr = arr.slice();
newArr.push(val);
if (newArr.length > historySize)
newArr.shift();
return newArr;
}
function sampleData() { function sampleData() {
cpuHistory = addToHistory(cpuHistory, DgopService.cpuUsage); cpuHistory = Format.addToHistory(cpuHistory, DgopService.cpuUsage, historySize);
memoryHistory = addToHistory(memoryHistory, DgopService.memoryUsage); memoryHistory = Format.addToHistory(memoryHistory, DgopService.memoryUsage, historySize);
networkRxHistory = addToHistory(networkRxHistory, DgopService.networkRxRate); networkRxHistory = Format.addToHistory(networkRxHistory, DgopService.networkRxRate, historySize);
networkTxHistory = addToHistory(networkTxHistory, DgopService.networkTxRate); networkTxHistory = Format.addToHistory(networkTxHistory, DgopService.networkTxRate, historySize);
diskReadHistory = addToHistory(diskReadHistory, DgopService.diskReadRate); diskReadHistory = Format.addToHistory(diskReadHistory, DgopService.diskReadRate, historySize);
diskWriteHistory = addToHistory(diskWriteHistory, DgopService.diskWriteRate); diskWriteHistory = Format.addToHistory(diskWriteHistory, DgopService.diskWriteRate, historySize);
} }
Component.onCompleted: { Component.onCompleted: {
@@ -111,8 +94,8 @@ Item {
Layout.fillHeight: true Layout.fillHeight: true
title: I18n.tr("Network") title: I18n.tr("Network")
icon: "swap_horiz" icon: "swap_horiz"
value: "↓ " + root.formatBytes(DgopService.networkRxRate) value: "↓ " + Format.formatRate(DgopService.networkRxRate)
subtitle: "↑ " + root.formatBytes(DgopService.networkTxRate) subtitle: "↑ " + Format.formatRate(DgopService.networkTxRate)
accentColor: Theme.info accentColor: Theme.info
history: root.networkRxHistory history: root.networkRxHistory
history2: root.networkTxHistory history2: root.networkTxHistory
@@ -127,8 +110,8 @@ Item {
Layout.fillHeight: true Layout.fillHeight: true
title: I18n.tr("Disk") title: I18n.tr("Disk")
icon: "storage" icon: "storage"
value: "R: " + root.formatBytes(DgopService.diskReadRate) value: "R: " + Format.formatRate(DgopService.diskReadRate)
subtitle: "W: " + root.formatBytes(DgopService.diskWriteRate) subtitle: "W: " + Format.formatRate(DgopService.diskWriteRate)
accentColor: Theme.warning accentColor: Theme.warning
history: root.diskReadHistory history: root.diskReadHistory
history2: root.diskWriteHistory history2: root.diskWriteHistory
@@ -36,6 +36,36 @@ Item {
cachedProcesses = filteredProcesses; cachedProcesses = filteredProcesses;
} }
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";
if (mem < 1024 * 1024)
return (mem / 1024).toFixed(1) + " MB";
return (mem / (1024 * 1024)).toFixed(1) + " GB";
}
readonly property var filteredProcesses: { readonly property var filteredProcesses: {
if (!DgopService.allProcesses || DgopService.allProcesses.length === 0) if (!DgopService.allProcesses || DgopService.allProcesses.length === 0)
return []; return [];
@@ -521,7 +551,7 @@ Item {
spacing: Theme.spacingS spacing: Theme.spacingS
DankIcon { DankIcon {
name: DgopService.getProcessIcon(processItemRoot.processCmd) name: root.getProcessIcon(processItemRoot.processCmd)
size: Theme.iconSize - 4 size: Theme.iconSize - 4
color: { color: {
if (processItemRoot.processCpu > 80) if (processItemRoot.processCpu > 80)
@@ -566,7 +596,7 @@ Item {
StyledText { StyledText {
anchors.centerIn: parent anchors.centerIn: parent
text: DgopService.formatCpuUsage(processItemRoot.processCpu) text: root.formatCpuUsage(processItemRoot.processCpu)
font.pixelSize: Theme.fontSizeSmall font.pixelSize: Theme.fontSizeSmall
font.family: SettingsData.monoFontFamily font.family: SettingsData.monoFontFamily
font.weight: Font.Bold font.weight: Font.Bold
@@ -600,7 +630,7 @@ Item {
StyledText { StyledText {
anchors.centerIn: parent anchors.centerIn: parent
text: DgopService.formatMemoryUsage(processItemRoot.processMemKB) text: root.formatMemoryUsage(processItemRoot.processMemKB)
font.pixelSize: Theme.fontSizeSmall font.pixelSize: Theme.fontSizeSmall
font.family: SettingsData.monoFontFamily font.family: SettingsData.monoFontFamily
font.weight: Font.Bold font.weight: Font.Bold
@@ -387,7 +387,6 @@ Singleton {
}); });
} }
// Extract neutral per-output config from current live state
function extractOutputNeutralConfig(outputName, outputData, niriSettings, hyprlandSettings) { function extractOutputNeutralConfig(outputName, outputData, niriSettings, hyprlandSettings) {
const modeData = (outputData.modes && outputData.current_mode !== undefined) ? outputData.modes[outputData.current_mode] : null; const modeData = (outputData.modes && outputData.current_mode !== undefined) ? outputData.modes[outputData.current_mode] : null;
const modeStr = modeData ? modeData.width + "x" + modeData.height + "@" + (modeData.refresh_rate / 1000).toFixed(3) : null; const modeStr = modeData ? modeData.width + "x" + modeData.height + "@" + (modeData.refresh_rate / 1000).toFixed(3) : null;
@@ -421,7 +420,6 @@ Singleton {
return cfg; return cfg;
} }
// Convert monitors.json config entry internal outputsData map
function profileKeyMatchesOutput(outputId, output, name) { function profileKeyMatchesOutput(outputId, output, name) {
if (name === outputId || getOutputIdentifier(output, name) === outputId) if (name === outputId || getOutputIdentifier(output, name) === outputId)
return true; return true;
@@ -438,7 +436,6 @@ Singleton {
const cfgOutputs = configEntry.outputs || {}; const cfgOutputs = configEntry.outputs || {};
for (const outputId in cfgOutputs) { for (const outputId in cfgOutputs) {
const cfg = cfgOutputs[outputId]; const cfg = cfgOutputs[outputId];
// Find matching live output to get modes list
let liveOutput = null; let liveOutput = null;
for (const name in outputs) { for (const name in outputs) {
if (profileKeyMatchesOutput(outputId, outputs[name], name)) { if (profileKeyMatchesOutput(outputId, outputs[name], name)) {
@@ -476,7 +473,6 @@ Singleton {
return result; return result;
} }
// Extract niri settings map from a neutral config entry.
function getNiriSettingsFromConfig(configEntry) { function getNiriSettingsFromConfig(configEntry) {
const result = {}; const result = {};
for (const outputId in (configEntry.outputs || {})) { for (const outputId in (configEntry.outputs || {})) {
@@ -490,7 +486,6 @@ Singleton {
return result; return result;
} }
// Extract hyprland settings map from neutral config entry
function getHyprlandSettingsFromConfig(configEntry) { function getHyprlandSettingsFromConfig(configEntry) {
const result = {}; const result = {};
for (const outputId in (configEntry.outputs || {})) { for (const outputId in (configEntry.outputs || {})) {
@@ -537,7 +532,6 @@ Singleton {
return true; return true;
} }
// Write compositor config from a neutral config entry and optionally reload
function applyConfigEntry(configEntry, configId, profileName, isManual) { function applyConfigEntry(configEntry, configId, profileName, isManual) {
if (CompositorService.isHyprland && readOnly) { if (CompositorService.isHyprland && readOnly) {
if (isManual) { if (isManual) {
@@ -580,8 +574,6 @@ Singleton {
}); });
} }
// Profile management
function validateProfiles() { function validateProfiles() {
log.info("Validating profiles against current outputs..."); log.info("Validating profiles against current outputs...");
readMonitorsJson(data => { readMonitorsJson(data => {
@@ -2072,7 +2064,6 @@ Singleton {
return pending !== undefined ? pending : originalValue; return pending !== undefined ? pending : originalValue;
} }
// Returns true if the given output can currently be disabled.
// Prevents disabling all outputs and prevents disabling the only output // Prevents disabling all outputs and prevents disabling the only output
// in a single-display configuration. // in a single-display configuration.
function canDisableOutput() { function canDisableOutput() {
@@ -3,23 +3,11 @@ import qs.Common
import qs.Services import qs.Services
import qs.Widgets import qs.Widgets
import qs.Modules.Settings.Widgets import qs.Modules.Settings.Widgets
import "../../Common/Format.js" as Format
Item { Item {
id: root id: root
function formatGammaTime(isoString) {
if (!isoString)
return "";
try {
const date = new Date(isoString);
if (isNaN(date.getTime()))
return "";
return date.toLocaleTimeString(Qt.locale(), "HH:mm");
} catch (e) {
return "";
}
}
DankFlickable { DankFlickable {
anchors.fill: parent anchors.fill: parent
clip: true clip: true
@@ -195,7 +183,7 @@ Item {
} }
onTabClicked: index => { onTabClicked: index => {
DisplayService.setNightModeAutomationMode(index === 1 ? "location" : "time"); SessionData.setNightModeAutoMode(index === 1 ? "location" : "time");
currentIndex = index; currentIndex = index;
} }
@@ -562,7 +550,7 @@ Item {
} }
StyledText { StyledText {
text: root.formatGammaTime(DisplayService.gammaSunriseTime) text: Format.formatIsoTime(DisplayService.gammaSunriseTime)
font.pixelSize: Theme.fontSizeLarge font.pixelSize: Theme.fontSizeLarge
font.weight: Font.Medium font.weight: Font.Medium
color: Theme.surfaceText color: Theme.surfaceText
@@ -598,7 +586,7 @@ Item {
} }
StyledText { StyledText {
text: root.formatGammaTime(DisplayService.gammaSunsetTime) text: Format.formatIsoTime(DisplayService.gammaSunsetTime)
font.pixelSize: Theme.fontSizeLarge font.pixelSize: Theme.fontSizeLarge
font.weight: Font.Medium font.weight: Font.Medium
color: Theme.surfaceText color: Theme.surfaceText
@@ -645,7 +633,7 @@ Item {
} }
StyledText { StyledText {
text: root.formatGammaTime(DisplayService.gammaNextTransition) text: Format.formatIsoTime(DisplayService.gammaNextTransition)
font.pixelSize: Theme.fontSizeMedium font.pixelSize: Theme.fontSizeMedium
font.weight: Font.Medium font.weight: Font.Medium
color: Theme.surfaceText color: Theme.surfaceText
@@ -6,8 +6,8 @@ import Quickshell.Wayland
import qs.Common import qs.Common
import qs.Services import qs.Services
import qs.Widgets import qs.Widgets
import "../Common/KeyUtils.js" as KeyUtils import "../../Common/KeyUtils.js" as KeyUtils
import "../Common/KeybindActions.js" as Actions import "../../Common/KeybindActions.js" as Actions
Item { Item {
id: root id: root
@@ -240,7 +240,7 @@ Item {
required property var modelData required property var modelData
required property int index required property int index
readonly property bool isActive: DMSNetworkService.isActiveUuid(modelData.uuid) readonly property bool isActive: DMSNetworkService.isActiveVpnUuid(modelData.uuid)
readonly property bool isTransient: !!modelData.transient readonly property bool isTransient: !!modelData.transient
readonly property bool canExpand: modelData.canExpand !== false readonly property bool canExpand: modelData.canExpand !== false
readonly property bool canDelete: modelData.canDelete !== false readonly property bool canDelete: modelData.canDelete !== false
+3 -10
View File
@@ -9,6 +9,7 @@ import qs.Modules.Settings.Widgets
import qs.Modals.Common import qs.Modals.Common
import qs.Services import qs.Services
import qs.Widgets import qs.Widgets
import "../../Common/QmlUtils.js" as QmlUtils
Item { Item {
id: networkWifiTab id: networkWifiTab
@@ -46,22 +47,14 @@ Item {
property string expandedSavedWifiSsid: "" property string expandedSavedWifiSsid: ""
property int maxPinnedWifiNetworks: 3 property int maxPinnedWifiNetworks: 3
function normalizePinList(value) {
if (Array.isArray(value))
return value.filter(v => v);
if (typeof value === "string" && value.length > 0)
return [value];
return [];
}
function getPinnedWifiNetworks() { function getPinnedWifiNetworks() {
const pins = CacheData.wifiNetworkPins || {}; const pins = CacheData.wifiNetworkPins || {};
return normalizePinList(pins["preferredWifi"]); return QmlUtils.normalizePinList(pins["preferredWifi"]);
} }
function toggleWifiPin(ssid) { function toggleWifiPin(ssid) {
const pins = JSON.parse(JSON.stringify(CacheData.wifiNetworkPins || {})); const pins = JSON.parse(JSON.stringify(CacheData.wifiNetworkPins || {}));
let pinnedList = normalizePinList(pins["preferredWifi"]); let pinnedList = QmlUtils.normalizePinList(pins["preferredWifi"]);
const pinIndex = pinnedList.indexOf(ssid); const pinIndex = pinnedList.indexOf(ssid);
if (pinIndex !== -1) { if (pinIndex !== -1) {
@@ -1,5 +1,6 @@
import QtQuick import QtQuick
import qs.Common import qs.Common
import qs.Services
import qs.Widgets import qs.Widgets
import qs.Modules.Settings.Widgets import qs.Modules.Settings.Widgets
@@ -215,7 +216,7 @@ Item {
currentValue: (SettingsData.notificationSummaryFontSize || I18n.tr("Unset")).toString() currentValue: (SettingsData.notificationSummaryFontSize || I18n.tr("Unset")).toString()
onValueChanged: value => { onValueChanged: value => {
SettingsData.set("notificationSummaryFontSize", Number(value === I18n.tr("Unset") ? 0 : value)); SettingsData.set("notificationSummaryFontSize", Number(value === I18n.tr("Unset") ? 0 : value));
SettingsData.sendTestNotifications(); NotificationService.sendTestNotifications();
} }
} }
@@ -228,7 +229,7 @@ Item {
currentValue: (SettingsData.notificationBodyFontSize || I18n.tr("Unset")).toString() currentValue: (SettingsData.notificationBodyFontSize || I18n.tr("Unset")).toString()
onValueChanged: value => { onValueChanged: value => {
SettingsData.set("notificationBodyFontSize", Number(value === I18n.tr("Unset") ? 0 : value)); SettingsData.set("notificationBodyFontSize", Number(value === I18n.tr("Unset") ? 0 : value));
SettingsData.sendTestNotifications(); NotificationService.sendTestNotifications();
} }
} }
@@ -277,7 +278,7 @@ Item {
SettingsData.set("notificationPopupPosition", SettingsData.Position.Bottom); SettingsData.set("notificationPopupPosition", SettingsData.Position.Bottom);
break; break;
} }
SettingsData.sendTestNotifications(); NotificationService.sendTestNotifications();
} }
} }
+2 -14
View File
@@ -8,6 +8,7 @@ import qs.Services
import qs.Widgets import qs.Widgets
import qs.Modules.Settings.Widgets import qs.Modules.Settings.Widgets
import "../../Common/ConfigIncludeResolve.js" as ConfigIncludeResolve import "../../Common/ConfigIncludeResolve.js" as ConfigIncludeResolve
import "../../Common/Format.js" as Format
Item { Item {
id: themeColorsTab id: themeColorsTab
@@ -215,19 +216,6 @@ Item {
ToastService.showError(I18n.tr("Missing Environment Variables", "qt theme env error title"), I18n.tr("You need to set either:\nQT_QPA_PLATFORMTHEME=gtk3 OR\nQT_QPA_PLATFORMTHEME=qt6ct\nas environment variables, and then restart the shell.\n\nqt6ct requires qt6ct-kde to be installed.", "qt theme env error body")); ToastService.showError(I18n.tr("Missing Environment Variables", "qt theme env error title"), I18n.tr("You need to set either:\nQT_QPA_PLATFORMTHEME=gtk3 OR\nQT_QPA_PLATFORMTHEME=qt6ct\nas environment variables, and then restart the shell.\n\nqt6ct requires qt6ct-kde to be installed.", "qt theme env error body"));
} }
function formatThemeAutoTime(isoString) {
if (!isoString)
return "";
try {
const date = new Date(isoString);
if (isNaN(date.getTime()))
return "";
return date.toLocaleTimeString(Qt.locale(), "HH:mm");
} catch (e) {
return "";
}
}
function refreshMatugenSchemePreviews() { function refreshMatugenSchemePreviews() {
if (!Theme.matugenAvailable) if (!Theme.matugenAvailable)
return; return;
@@ -1566,7 +1554,7 @@ Item {
} }
StyledText { StyledText {
text: themeColorsTab.formatThemeAutoTime(SessionData.themeModeNextTransition) text: Format.formatIsoTime(SessionData.themeModeNextTransition)
font.pixelSize: Theme.fontSizeMedium font.pixelSize: Theme.fontSizeMedium
font.weight: Font.Medium font.weight: Font.Medium
color: Theme.surfaceText color: Theme.surfaceText
@@ -4,6 +4,7 @@ import QtQuick
import qs.Common import qs.Common
import qs.Services import qs.Services
import qs.Widgets import qs.Widgets
import "../../../Common/QmlUtils.js" as QmlUtils
Item { Item {
id: root id: root
@@ -20,16 +21,6 @@ Item {
readonly property bool isHighlighted: settingKey !== "" && SettingsSearchService.highlightSection === settingKey readonly property bool isHighlighted: settingKey !== "" && SettingsSearchService.highlightSection === settingKey
function findParentFlickable() {
let p = root.parent;
while (p) {
if (p.hasOwnProperty("contentY") && p.hasOwnProperty("contentItem"))
return p;
p = p.parent;
}
return null;
}
Component.onCompleted: { Component.onCompleted: {
if (!settingKey) if (!settingKey)
return; return;
@@ -37,7 +28,7 @@ Item {
Qt.callLater(() => { Qt.callLater(() => {
if (!root.parent) if (!root.parent)
return; return;
var flickable = findParentFlickable(); var flickable = QmlUtils.findParentFlickable(root.parent);
if (flickable) if (flickable)
SettingsSearchService.registerCard(key, root, flickable); SettingsSearchService.registerCard(key, root, flickable);
}); });
@@ -4,6 +4,7 @@ import QtQuick
import qs.Common import qs.Common
import qs.Services import qs.Services
import qs.Widgets import qs.Widgets
import "../../../Common/QmlUtils.js" as QmlUtils
StyledRect { StyledRect {
id: root id: root
@@ -43,17 +44,6 @@ StyledRect {
readonly property bool hasHeader: root.title !== "" || root.iconName !== "" readonly property bool hasHeader: root.title !== "" || root.iconName !== ""
property bool userToggledCollapse: false property bool userToggledCollapse: false
function findParentFlickable() {
let p = root.parent;
while (p) {
if (p.hasOwnProperty("contentY") && p.hasOwnProperty("contentItem")) {
return p;
}
p = p.parent;
}
return null;
}
Component.onCompleted: { Component.onCompleted: {
if (!settingKey) if (!settingKey)
return; return;
@@ -61,7 +51,7 @@ StyledRect {
Qt.callLater(() => { Qt.callLater(() => {
if (!root.parent) if (!root.parent)
return; return;
var flickable = findParentFlickable(); var flickable = QmlUtils.findParentFlickable(root.parent);
if (flickable) if (flickable)
SettingsSearchService.registerCard(key, root, flickable); SettingsSearchService.registerCard(key, root, flickable);
}); });
@@ -4,6 +4,7 @@ import QtQuick
import qs.Common import qs.Common
import qs.Services import qs.Services
import qs.Widgets import qs.Widgets
import "../../../Common/QmlUtils.js" as QmlUtils
DankDropdown { DankDropdown {
id: root id: root
@@ -35,16 +36,6 @@ DankDropdown {
} }
} }
function findParentFlickable() {
let p = root.parent;
while (p) {
if (p.hasOwnProperty("contentY") && p.hasOwnProperty("contentItem"))
return p;
p = p.parent;
}
return null;
}
Component.onCompleted: { Component.onCompleted: {
if (!settingKey) if (!settingKey)
return; return;
@@ -52,7 +43,7 @@ DankDropdown {
Qt.callLater(() => { Qt.callLater(() => {
if (!root.parent) if (!root.parent)
return; return;
var flickable = findParentFlickable(); var flickable = QmlUtils.findParentFlickable(root.parent);
if (flickable) if (flickable)
SettingsSearchService.registerCard(key, root, flickable); SettingsSearchService.registerCard(key, root, flickable);
}); });
@@ -4,6 +4,7 @@ import QtQuick
import qs.Common import qs.Common
import qs.Services import qs.Services
import qs.Widgets import qs.Widgets
import "../../../Common/QmlUtils.js" as QmlUtils
StyledRect { StyledRect {
id: root id: root
@@ -36,16 +37,6 @@ StyledRect {
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: Theme.surfaceContainerHigh color: Theme.surfaceContainerHigh
function findParentFlickable() {
let p = root.parent;
while (p) {
if (p.hasOwnProperty("contentY") && p.hasOwnProperty("contentItem"))
return p;
p = p.parent;
}
return null;
}
Component.onCompleted: { Component.onCompleted: {
if (!settingKey) if (!settingKey)
return; return;
@@ -53,7 +44,7 @@ StyledRect {
Qt.callLater(() => { Qt.callLater(() => {
if (!root.parent) if (!root.parent)
return; return;
const flickable = findParentFlickable(); const flickable = QmlUtils.findParentFlickable(root.parent);
if (flickable) if (flickable)
SettingsSearchService.registerCard(key, root, flickable); SettingsSearchService.registerCard(key, root, flickable);
}); });
@@ -4,6 +4,7 @@ import QtQuick
import qs.Common import qs.Common
import qs.Services import qs.Services
import qs.Widgets import qs.Widgets
import "../../../Common/QmlUtils.js" as QmlUtils
Item { Item {
id: root id: root
@@ -20,16 +21,6 @@ Item {
readonly property bool isHighlighted: settingKey !== "" && SettingsSearchService.highlightSection === settingKey readonly property bool isHighlighted: settingKey !== "" && SettingsSearchService.highlightSection === settingKey
function findParentFlickable() {
let p = root.parent;
while (p) {
if (p.hasOwnProperty("contentY") && p.hasOwnProperty("contentItem"))
return p;
p = p.parent;
}
return null;
}
Component.onCompleted: { Component.onCompleted: {
if (!settingKey) if (!settingKey)
return; return;
@@ -37,7 +28,7 @@ Item {
Qt.callLater(() => { Qt.callLater(() => {
if (!root.parent) if (!root.parent)
return; return;
var flickable = findParentFlickable(); var flickable = QmlUtils.findParentFlickable(root.parent);
if (flickable) if (flickable)
SettingsSearchService.registerCard(key, root, flickable); SettingsSearchService.registerCard(key, root, flickable);
}); });
@@ -4,6 +4,7 @@ import QtQuick
import qs.Common import qs.Common
import qs.Services import qs.Services
import qs.Widgets import qs.Widgets
import "../../../Common/QmlUtils.js" as QmlUtils
StyledRect { StyledRect {
id: root id: root
@@ -30,16 +31,6 @@ StyledRect {
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: Theme.surfaceContainerHigh color: Theme.surfaceContainerHigh
function findParentFlickable() {
let p = root.parent;
while (p) {
if (p.hasOwnProperty("contentY") && p.hasOwnProperty("contentItem"))
return p;
p = p.parent;
}
return null;
}
Component.onCompleted: { Component.onCompleted: {
if (!settingKey) if (!settingKey)
return; return;
@@ -47,7 +38,7 @@ StyledRect {
Qt.callLater(() => { Qt.callLater(() => {
if (!root.parent) if (!root.parent)
return; return;
const flickable = findParentFlickable(); const flickable = QmlUtils.findParentFlickable(root.parent);
if (flickable) if (flickable)
SettingsSearchService.registerCard(key, root, flickable); SettingsSearchService.registerCard(key, root, flickable);
}); });
@@ -4,6 +4,7 @@ import QtQuick
import qs.Common import qs.Common
import qs.Services import qs.Services
import qs.Widgets import qs.Widgets
import "../../../Common/QmlUtils.js" as QmlUtils
DankToggle { DankToggle {
id: root id: root
@@ -19,16 +20,6 @@ DankToggle {
width: parent?.width ?? 0 width: parent?.width ?? 0
function findParentFlickable() {
let p = root.parent;
while (p) {
if (p.hasOwnProperty("contentY") && p.hasOwnProperty("contentItem"))
return p;
p = p.parent;
}
return null;
}
Component.onCompleted: { Component.onCompleted: {
if (!settingKey) if (!settingKey)
return; return;
@@ -36,7 +27,7 @@ DankToggle {
Qt.callLater(() => { Qt.callLater(() => {
if (!root.parent) if (!root.parent)
return; return;
var flickable = findParentFlickable(); var flickable = QmlUtils.findParentFlickable(root.parent);
if (flickable) if (flickable)
SettingsSearchService.registerCard(key, root, flickable); SettingsSearchService.registerCard(key, root, flickable);
}); });
@@ -207,7 +207,7 @@ Item {
iconName: "label" iconName: "label"
title: I18n.tr("Named Workspace Icons") title: I18n.tr("Named Workspace Icons")
settingKey: "workspaceIcons" settingKey: "workspaceIcons"
visible: SettingsData.hasNamedWorkspaces() visible: NiriService.hasNamedWorkspaces()
StyledText { StyledText {
width: parent.width width: parent.width
@@ -218,7 +218,7 @@ Item {
} }
Repeater { Repeater {
model: SettingsData.getNamedWorkspaces() model: NiriService.getNamedWorkspaces()
Rectangle { Rectangle {
width: parent.width width: parent.width
+3 -28
View File
@@ -114,7 +114,7 @@ Variants {
} }
property real transitionProgress: 0 property real transitionProgress: 0
property real shaderFillMode: getFillMode(SessionData.getMonitorWallpaperFillMode(modelData.name)) property real shaderFillMode: Theme.getFillMode(SessionData.getMonitorWallpaperFillMode(modelData.name))
property vector4d fillColor: Qt.vector4d(0, 0, 0, 1) property vector4d fillColor: Qt.vector4d(0, 0, 0, 1)
property real edgeSmoothness: 0.1 property real edgeSmoothness: 0.1
@@ -321,31 +321,6 @@ Variants {
Qt.callLater(() => root.changeWallpaper(pending, true)); Qt.callLater(() => root.changeWallpaper(pending, true));
} }
function getFillMode(modeName) {
switch (modeName) {
case "Scrolling":
return Image.PreserveAspectCrop;
case "Stretch":
return Image.Stretch;
case "Fit":
case "PreserveAspectFit":
return Image.PreserveAspectFit;
case "Fill":
case "PreserveAspectCrop":
return Image.PreserveAspectCrop;
case "Tile":
return Image.Tile;
case "TileVertically":
return Image.TileVertically;
case "TileHorizontally":
return Image.TileHorizontally;
case "Pad":
return Image.Pad;
default:
return Image.PreserveAspectCrop;
}
}
function updateWorkspaceData() { function updateWorkspaceData() {
if (!scrollingEnabled) if (!scrollingEnabled)
return; return;
@@ -740,7 +715,7 @@ Variants {
cache: true cache: true
sourceSize: Qt.size(root.textureWidth, root.textureHeight) sourceSize: Qt.size(root.textureWidth, root.textureHeight)
fillMode: root.getFillMode(SessionData.getMonitorWallpaperFillMode(modelData.name)) fillMode: Theme.getFillMode(SessionData.getMonitorWallpaperFillMode(modelData.name))
onStatusChanged: { onStatusChanged: {
if (status === Image.Error) { if (status === Image.Error) {
@@ -772,7 +747,7 @@ Variants {
cache: true cache: true
sourceSize: Qt.size(root.textureWidth, root.textureHeight) sourceSize: Qt.size(root.textureWidth, root.textureHeight)
fillMode: root.getFillMode(SessionData.getMonitorWallpaperFillMode(modelData.name)) fillMode: Theme.getFillMode(SessionData.getMonitorWallpaperFillMode(modelData.name))
onStatusChanged: { onStatusChanged: {
if (status === Image.Error) { if (status === Image.Error) {
@@ -218,13 +218,21 @@ Scope {
} }
if (event.key === Qt.Key_Up) { if (event.key === Qt.Key_Up) {
NiriService.moveWorkspaceUp(); NiriService.send({
"Action": {
"FocusWorkspaceUp": {}
}
});
event.accepted = true; event.accepted = true;
return; return;
} }
if (event.key === Qt.Key_Down) { if (event.key === Qt.Key_Down) {
NiriService.moveWorkspaceDown(); NiriService.send({
"Action": {
"FocusWorkspaceDown": {}
}
});
event.accepted = true; event.accepted = true;
return; return;
} }
-58
View File
@@ -791,23 +791,6 @@ Singleton {
return null; 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) { function getPluginItems(category, query) {
if (typeof PluginService === "undefined") if (typeof PluginService === "undefined")
return []; return [];
@@ -915,21 +898,6 @@ Singleton {
return false; 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) { function getPluginPasteArgs(pluginId, item) {
if (typeof PluginService === "undefined") if (typeof PluginService === "undefined")
return null; return null;
@@ -950,21 +918,6 @@ Singleton {
return null; 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) { function getPluginLauncherCategories(pluginId) {
if (typeof PluginService === "undefined") if (typeof PluginService === "undefined")
return []; return [];
@@ -1001,15 +954,4 @@ Singleton {
log.warn("Error setting category on plugin", pluginId, ":", e); 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";
}
} }
-39
View File
@@ -85,7 +85,6 @@ Singleton {
} }
} }
// Used in playLoginSoundIfApplicable()
Process { Process {
id: loginSoundChecker id: loginSoundChecker
onExited: exitCode => { onExited: exitCode => {
@@ -720,15 +719,10 @@ EOFCONFIG
return ""; 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]) { if (node.name && deviceAliases[node.name]) {
return 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"]) { if (node.properties && node.properties["node.description"]) {
const desc = node.properties["node.description"]; const desc = node.properties["node.description"];
if (desc !== node.name) { if (desc !== node.name) {
@@ -736,22 +730,18 @@ EOFCONFIG
} }
} }
// Check cached description as fallback
if (node.description && node.description !== node.name) { if (node.description && node.description !== node.name) {
return node.description; return node.description;
} }
// Fallback to device description property
if (node.properties && node.properties["device.description"]) { if (node.properties && node.properties["device.description"]) {
return node.properties["device.description"]; return node.properties["device.description"];
} }
// Fallback to nickname
if (node.nickname && node.nickname !== node.name) { if (node.nickname && node.nickname !== node.name) {
return node.nickname; return node.nickname;
} }
// Fallback to friendly names based on node name patterns
if (node.name.includes("analog-stereo")) { if (node.name.includes("analog-stereo")) {
return "Built-in Audio Analog Stereo"; return "Built-in Audio Analog Stereo";
} }
@@ -773,10 +763,6 @@ EOFCONFIG
return ""; 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")) { if (node.name.includes("analog-stereo")) {
return "Built-in Audio Analog Stereo"; return "Built-in Audio Analog Stereo";
} }
@@ -790,19 +776,16 @@ EOFCONFIG
return "HDMI Audio"; return "HDMI Audio";
} }
if (node.name.includes("raop_sink")) { if (node.name.includes("raop_sink")) {
// Extract friendly name from RAOP node name
const match = node.name.match(/raop_sink\.([^.]+)/); const match = node.name.match(/raop_sink\.([^.]+)/);
if (match) { if (match) {
return match[1].replace(/-/g, " "); return match[1].replace(/-/g, " ");
} }
} }
// Fallback to device.description property
if (node.properties && node.properties["device.description"]) { if (node.properties && node.properties["device.description"]) {
return node.properties["device.description"]; return node.properties["device.description"];
} }
// Fallback to nickname
if (node.nickname && node.nickname !== node.name) { if (node.nickname && node.nickname !== node.name) {
return node.nickname; return node.nickname;
} }
@@ -889,28 +872,6 @@ EOFCONFIG
return root.sink.audio.muted ? "Audio muted" : "Audio unmuted"; 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) { function setMicVolume(percentage) {
if (!root.source?.audio) { if (!root.source?.audio) {
return "No audio source available"; return "No audio source available";
-56
View File
@@ -354,28 +354,6 @@ Singleton {
return "Very Poor"; 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) { function isDeviceBusy(device) {
if (!device) { if (!device) {
return false; 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) { function getAvailableCodecs(device, callback) {
if (!device || !device.connected || !isAudioDevice(device)) { if (!device || !device.connected || !isAudioDevice(device)) {
callback([], ""); callback([], "");
+6
View File
@@ -41,6 +41,12 @@ Singleton {
return Theme.withAlpha(baseColor, hoverAlpha ?? 0.15); return Theme.withAlpha(baseColor, hoverAlpha ?? 0.15);
} }
Binding {
target: Theme
property: "blurLayersActive"
value: root.enabled
}
Process { Process {
id: blurProbe id: blurProbe
running: false running: false
+54
View File
@@ -1087,4 +1087,58 @@ Singleton {
} }
log.warn("Cannot power on monitors, unknown compositor"); 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;
}
}
}
} }
-118
View File
@@ -349,14 +349,6 @@ Singleton {
return getPrinterStateTranslation(printer.state) + " (" + getPrinterStateReasonTranslation(printer.stateReason) + ")"; 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() { function getCurrentPrinterJobs() {
if (!cupsAvailable || !selectedPrinter) if (!cupsAvailable || !selectedPrinter)
return []; return [];
@@ -372,14 +364,6 @@ Singleton {
return printer.jobs; return printer.jobs;
} }
function getJobsNum(printerName) {
if (!cupsAvailable)
return 0;
var printer = printers[printerName];
return printer.jobs.length;
}
function pausePrinter(printerName) { function pausePrinter(printerName) {
if (!cupsAvailable) if (!cupsAvailable)
return; 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) { function printTestPage(printerName) {
if (!cupsAvailable) if (!cupsAvailable)
return; 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) { function restartJob(jobID) {
if (!cupsAvailable) if (!cupsAvailable)
return; 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) { function deleteClass(className) {
if (!cupsAvailable) if (!cupsAvailable)
return; return;
@@ -1049,10 +1049,6 @@ Singleton {
return activeUuids && activeUuids.indexOf(uuid) !== -1; return activeUuids && activeUuids.indexOf(uuid) !== -1;
} }
function isActiveUuid(uuid) {
return isActiveVpnUuid(uuid);
}
function refreshNetworkState() { function refreshNetworkState() {
if (networkAvailable) { if (networkAvailable) {
getState(); getState();
-86
View File
@@ -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) { function handleSubscriptionEvent(response) {
if (response.error) { if (response.error) {
if (response.error.includes("unknown method") && response.error.includes("subscribe")) { 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) { function listPlugins(callback) {
sendRequest("plugins.list", null, response => { sendRequest("plugins.list", null, response => {
if (response.result) { 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) { function install(pluginName, callback) {
sendRequest("plugins.install", { sendRequest("plugins.install", {
"name": pluginName "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) { function installTheme(themeName, callback) {
sendRequest("themes.install", { sendRequest("themes.install", {
"name": themeName "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) { function lockSession(callback) {
sendRequest("loginctl.lock", null, callback); sendRequest("loginctl.lock", null, callback);
} }
@@ -640,30 +572,12 @@ Singleton {
}, callback); }, 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) { function bluetoothRemove(devicePath, callback) {
sendRequest("bluetooth.remove", { sendRequest("bluetooth.remove", {
"device": devicePath "device": devicePath
}, callback); }, callback);
} }
function bluetoothTrust(devicePath, callback) {
sendRequest("bluetooth.trust", {
"device": devicePath
}, callback);
}
function bluetoothSubmitPairing(token, secrets, accept, callback) { function bluetoothSubmitPairing(token, secrets, accept, callback) {
sendRequest("bluetooth.pairing.submit", { sendRequest("bluetooth.pairing.submit", {
"token": token, "token": token,
+4 -1
View File
@@ -18,7 +18,10 @@ Singleton {
property bool systemdAutostartTargetChecked: false property bool systemdAutostartTargetChecked: false
readonly property bool autostartAvailable: root.systemdAutostartTargetChecked && (!root.isSystemd || root.systemdAutostartTargetActive) 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 { Process {
id: initSystemCheckProcess id: initSystemCheckProcess
-54
View File
@@ -156,10 +156,6 @@ Singleton {
} }
} }
function setGpuPciIds(pciIds) {
gpuPciIds = Array.isArray(pciIds) ? pciIds : [];
}
function addGpuPciId(pciId) { function addGpuPciId(pciId) {
const currentCount = gpuPciIdRefCounts[pciId] || 0; const currentCount = gpuPciIdRefCounts[pciId] || 0;
gpuPciIdRefCounts[pciId] = currentCount + 1; gpuPciIdRefCounts[pciId] = currentCount + 1;
@@ -203,12 +199,6 @@ Singleton {
gpuPciIdRefCounts = Object.assign({}, gpuPciIdRefCounts); gpuPciIdRefCounts = Object.assign({}, gpuPciIdRefCounts);
} }
function setProcessOptions(limit = 20, sort = "cpu", disableCpu = false) {
processLimit = limit;
processSort = sort;
noCpu = disableCpu;
}
function updateAllStats() { function updateAllStats() {
if (dgopAvailable && refCount > 0 && enabledModules.length > 0) { if (dgopAvailable && refCount > 0 && enabledModules.length > 0) {
isUpdating = true; 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) { function formatSystemMemory(memoryKB) {
const mem = memoryKB || 0; const mem = memoryKB || 0;
if (mem === 0) { if (mem === 0) {
@@ -526,12 +478,6 @@ Singleton {
} }
} }
function killProcess(pid) {
if (pid > 0) {
Quickshell.execDetached("kill", [pid.toString()]);
}
}
function updateUptime() { function updateUptime() {
if (!bootTime) { if (!bootTime) {
uptime = ""; uptime = "";
+8 -4
View File
@@ -1228,10 +1228,6 @@ Singleton {
}); });
} }
function setNightModeAutomationMode(mode) {
SessionData.setNightModeAutoMode(mode);
}
function evaluateNightMode() { function evaluateNightMode() {
if (!nightModeEnabled) { if (!nightModeEnabled) {
return; return;
@@ -1355,6 +1351,14 @@ Singleton {
brightnessChanged(); brightnessChanged();
} }
Connections {
target: SessionData
function onBrightnessDisplayHintChanged(deviceName) {
root.updateDeviceBrightnessDisplay(deviceName);
}
}
Timer { Timer {
id: osdSuppressTimer id: osdSuppressTimer
interval: 2000 interval: 2000
+4 -1
View File
@@ -37,7 +37,10 @@ Singleton {
} }
onManagedThemeChanged: _rebuild() onManagedThemeChanged: _rebuild()
Component.onCompleted: _rebuild() Component.onCompleted: {
Paths.iconResolver = name => resolve(name);
_rebuild();
}
function _bumpRevision() { function _bumpRevision() {
if (_bumpPending) if (_bumpPending)
-32
View File
@@ -574,18 +574,6 @@ Singleton {
bindRemoved(key); 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) { function getActionLabel(action) {
return Actions.getActionLabel(action, currentProvider); return Actions.getActionLabel(action, currentProvider);
} }
@@ -601,24 +589,4 @@ Singleton {
function getDmsActions() { function getDmsActions() {
return Actions.getDmsActions(CompositorService.isNiri, CompositorService.isHyprland); 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);
}
} }
-22
View File
@@ -48,7 +48,6 @@ Singleton {
// windowsChanged is auto-generated by the `windows` property's change signal. // windowsChanged is auto-generated by the `windows` property's change signal.
signal stateChanged signal stateChanged
// State sockets
// One connection per watch target; mango streams a fresh full snapshot on // One connection per watch target; mango streams a fresh full snapshot on
// every change, so each line is treated as the complete state. // every change, so each line is treated as the complete state.
@@ -272,8 +271,6 @@ Singleton {
root.windows = data.clients; root.windows = data.clients;
} }
// Tag API (dwl-style tag model)
function getOutputState(outputName) { function getOutputState(outputName) {
return (outputs && outputs[outputName]) ? outputs[outputName] : null; return (outputs && outputs[outputName]) ? outputs[outputName] : null;
} }
@@ -296,20 +293,6 @@ Singleton {
return at.length === 0 || at.every(t => t === 0); 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) { function getVisibleTags(outputName) {
const output = getOutputState(outputName); const output = getOutputState(outputName);
if (!output || !output.tags) if (!output || !output.tags)
@@ -328,7 +311,6 @@ Singleton {
return displayScales[outputName]; 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 // Match mango clients to wlr foreign-toplevels by appId+title to enrich them
// with owning tags/monitor for per-tag filtering and stable ordering. // with owning tags/monitor for per-tag filtering and stable ordering.
@@ -452,8 +434,6 @@ Singleton {
return _matchAndEnrich(toplevels, clients); return _matchAndEnrich(toplevels, clients);
} }
// Commands (mango verb IPC: dispatch <func>,<args> over the socket)
function suppressWatchedConfigReloads(ms) { function suppressWatchedConfigReloads(ms) {
root._ignoreWatchedReloadUntil = Math.max(root._ignoreWatchedReloadUntil, Date.now() + (ms || 1500)); 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 { Connections {
target: SettingsData target: SettingsData
function onBarConfigsChanged() { function onBarConfigsChanged() {

Some files were not shown because too many files have changed in this diff Show More