mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2026-10-16 08:14:03 -04:00
175 lines
6.5 KiB
QML
175 lines
6.5 KiB
QML
pragma Singleton
|
|
|
|
import QtQuick
|
|
import Quickshell
|
|
import qs.Common
|
|
import qs.Services
|
|
|
|
Singleton {
|
|
id: root
|
|
|
|
property var previews: CacheData.matugenPreviews.previews ?? ({})
|
|
property string requestKey: ""
|
|
property string loadedKey: CacheData.matugenPreviews.key ?? ""
|
|
property bool failed: false
|
|
property var seedPreviews: CacheData.matugenSeedPreviews
|
|
property var seedQueue: []
|
|
property string seedRequestKey: ""
|
|
property var seedFailed: ({})
|
|
property bool seedDirty: false
|
|
readonly property int seedCacheLimit: 32
|
|
|
|
readonly property string source: SettingsData.matugenSeedColor || (!Theme.rawWallpaperPath ? Theme.materialWallpaperSeed : Theme.getMatugenColor("source_color", Theme.primary).toString())
|
|
readonly property string image: (!SettingsData.matugenSeedColor && Theme.rawWallpaperPath && !Theme.rawWallpaperPath.startsWith("#")) ? Theme.rawWallpaperPath : ""
|
|
readonly property string keySuffix: "|" + (SettingsData.matugenContrast ?? 0) + "|" + SettingsData.matugenSpec
|
|
readonly property string key: source + "|" + (SettingsData.matugenContrast ?? 0) + "|" + image + "|" + SettingsData.matugenSpec
|
|
readonly property bool ready: loadedKey === key || failed || !Theme.matugenAvailable
|
|
readonly property bool seedBusy: seedRequestKey !== "" || seedQueue.length > 0
|
|
readonly property bool seedPreviewFailed: Object.keys(seedFailed).length > 0
|
|
readonly property var schemeOptions: {
|
|
const mode = SessionData.isLightMode ? "light" : "dark";
|
|
const options = [];
|
|
for (const option of Theme.availableMatugenSchemes) {
|
|
if (option.value === "scheme-smart" && !DMSService.matugenSmartSupported)
|
|
continue;
|
|
if (SettingsData.matugenSpec !== "2021" && !option.spec2025)
|
|
continue;
|
|
const colors = (previews[option.value] ?? previews["scheme-tonal-spot"])?.[mode];
|
|
// a dms binary older than the tri-color preview returns the primary hex as a plain string
|
|
const primary = typeof colors === "string" ? colors : (colors?.primary ?? Theme.primary.toString());
|
|
options.push({
|
|
"value": option.value,
|
|
"label": option.label,
|
|
"primary": primary,
|
|
"secondary": colors?.secondary ?? primary,
|
|
"tertiary": colors?.tertiary ?? primary
|
|
});
|
|
}
|
|
return options;
|
|
}
|
|
|
|
function seedKey(seed) {
|
|
return seed.toLowerCase() + keySuffix;
|
|
}
|
|
|
|
function seedPalette(seed, light = SessionData.isLightMode) {
|
|
const entry = seedPreviews[seedKey(seed)];
|
|
if (!entry)
|
|
return null;
|
|
const colors = (entry[SettingsData.matugenScheme] ?? entry["scheme-tonal-spot"])?.[light ? "light" : "dark"];
|
|
if (!colors)
|
|
return null;
|
|
if (typeof colors === "string")
|
|
return {
|
|
primary: colors,
|
|
secondary: colors,
|
|
tertiary: colors
|
|
};
|
|
return colors;
|
|
}
|
|
|
|
function requestSeeds(seeds) {
|
|
if (!Theme.matugenAvailable)
|
|
return;
|
|
const wanted = [];
|
|
for (const seed of seeds) {
|
|
const key = seedKey(seed);
|
|
if (seedPreviews[key] || seedFailed[key] || seedQueue.includes(key) || key === seedRequestKey || wanted.includes(key))
|
|
continue;
|
|
wanted.push(key);
|
|
}
|
|
if (!wanted.length)
|
|
return;
|
|
seedQueue = seedQueue.concat(wanted);
|
|
pumpSeeds();
|
|
}
|
|
|
|
function retrySeeds(seeds) {
|
|
seedFailed = {};
|
|
requestSeeds(seeds);
|
|
}
|
|
|
|
function pumpSeeds() {
|
|
if (seedRequestKey || !seedQueue.length)
|
|
return;
|
|
const key = seedQueue[0];
|
|
seedQueue = seedQueue.slice(1);
|
|
seedRequestKey = key;
|
|
const [source, contrast, spec] = key.split("|");
|
|
const args = [Proc.dmsBin, "matugen", "preview", "--source-color", source, "--contrast", contrast];
|
|
if (spec !== "2021")
|
|
args.push("--spec", spec);
|
|
Proc.runCommand("", args, (output, exitCode) => {
|
|
if (root.seedRequestKey !== key)
|
|
return;
|
|
root.seedRequestKey = "";
|
|
let parsed = null;
|
|
try {
|
|
parsed = exitCode === 0 ? JSON.parse(output.trim()) : null;
|
|
} catch (e) {
|
|
parsed = null;
|
|
}
|
|
if (!parsed || typeof parsed !== "object") {
|
|
root.seedFailed = Object.assign({}, root.seedFailed, {
|
|
[key]: true
|
|
});
|
|
} else {
|
|
const next = Object.assign({}, root.seedPreviews, {
|
|
[key]: parsed
|
|
});
|
|
const keys = Object.keys(next);
|
|
for (const stale of keys.slice(0, Math.max(0, keys.length - root.seedCacheLimit)))
|
|
delete next[stale];
|
|
root.seedPreviews = next;
|
|
CacheData.matugenSeedPreviews = next;
|
|
root.seedDirty = true;
|
|
}
|
|
if (!root.seedQueue.length && root.seedDirty) {
|
|
root.seedDirty = false;
|
|
CacheData.saveCache();
|
|
}
|
|
root.pumpSeeds();
|
|
});
|
|
}
|
|
|
|
function refresh() {
|
|
if (!Theme.matugenAvailable)
|
|
return;
|
|
const wanted = key;
|
|
if (wanted === loadedKey) {
|
|
requestKey = "";
|
|
return;
|
|
}
|
|
if (wanted === requestKey)
|
|
return;
|
|
requestKey = wanted;
|
|
failed = false;
|
|
|
|
const args = [Proc.dmsBin, "matugen", "preview", "--source-color", source, "--contrast", String(SettingsData.matugenContrast ?? 0)];
|
|
if (image)
|
|
args.push("--image", image);
|
|
if (SettingsData.matugenSpec !== "2021")
|
|
args.push("--spec", SettingsData.matugenSpec);
|
|
Proc.runCommand("", args, (output, exitCode) => {
|
|
if (wanted !== root.requestKey)
|
|
return;
|
|
root.requestKey = "";
|
|
if (exitCode !== 0) {
|
|
root.failed = true;
|
|
return;
|
|
}
|
|
try {
|
|
root.previews = JSON.parse(output.trim());
|
|
root.loadedKey = wanted;
|
|
CacheData.matugenPreviews = {
|
|
"key": wanted,
|
|
"previews": root.previews
|
|
};
|
|
CacheData.saveCache();
|
|
} catch (e) {
|
|
root.failed = true;
|
|
}
|
|
});
|
|
}
|
|
}
|