mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2026-08-09 06:58:29 -04:00
feat(theme): add extract dynamic theme to JSON file (#3009)
* feat(theme): add extract current theme to JSON file
Adds an 'Extract' button in Settings > Theme Color that exports the
current theme (generic/dynamic/custom/registry) to a dual-mode dark+light
JSON file via the DMS file save dialog.
* refactor(theme): simplify extract button to single DankButton
* refactor(theme): move extract button inside dynamic theme section
* fix(theme): address review feedback on extract theme save
* refactor: utilize dankActionButton
---------
(cherry picked from commit bde4decc5d)
This commit is contained in:
committed by
dms-ci[bot]
parent
0313e96e8e
commit
f971b6bcff
@@ -436,6 +436,10 @@ Singleton {
|
||||
|
||||
function getMatugenColor(path, fallback) {
|
||||
const colorMode = (typeof SessionData !== "undefined" && SessionData.isLightMode) ? "light" : "dark";
|
||||
return getMatugenColorForMode(colorMode, path, fallback);
|
||||
}
|
||||
|
||||
function getMatugenColorForMode(colorMode, path, fallback) {
|
||||
let cur = matugenColors && matugenColors.colors && matugenColors.colors[colorMode];
|
||||
for (const part of path.split(".")) {
|
||||
if (!cur || typeof cur !== "object" || !(part in cur))
|
||||
@@ -445,6 +449,82 @@ Singleton {
|
||||
return cur || fallback;
|
||||
}
|
||||
|
||||
function extractCurrentTheme(themeName) {
|
||||
var name = themeName || "Extracted Theme";
|
||||
var dark = {};
|
||||
var light = {};
|
||||
|
||||
if (currentTheme === dynamic) {
|
||||
dark = buildExtractedDynamicMode("dark", name + " Dark");
|
||||
light = buildExtractedDynamicMode("light", name + " Light");
|
||||
} else if (currentTheme === custom && customThemeRawData) {
|
||||
var rawDark = customThemeRawData.dark || null;
|
||||
var rawLight = customThemeRawData.light || null;
|
||||
if (rawDark) {
|
||||
dark = JSON.parse(JSON.stringify(rawDark));
|
||||
if (!dark.name)
|
||||
dark.name = name + " Dark";
|
||||
} else if (rawLight) {
|
||||
dark = buildExtractedDynamicMode("dark", name + " Dark");
|
||||
} else {
|
||||
dark = currentThemeData ? JSON.parse(JSON.stringify(currentThemeData)) : {};
|
||||
dark.name = name + " Dark";
|
||||
}
|
||||
if (rawLight) {
|
||||
light = JSON.parse(JSON.stringify(rawLight));
|
||||
if (!light.name)
|
||||
light.name = name + " Light";
|
||||
} else if (rawDark) {
|
||||
light = buildExtractedDynamicMode("light", name + " Light");
|
||||
} else {
|
||||
light = currentThemeData ? JSON.parse(JSON.stringify(currentThemeData)) : {};
|
||||
light.name = name + " Light";
|
||||
}
|
||||
} else {
|
||||
var darkTheme = StockThemes.getThemeByName(currentTheme, false);
|
||||
var lightTheme = StockThemes.getThemeByName(currentTheme, true);
|
||||
dark = darkTheme ? JSON.parse(JSON.stringify(darkTheme)) : {};
|
||||
light = lightTheme ? JSON.parse(JSON.stringify(lightTheme)) : {};
|
||||
dark.name = name + " Dark";
|
||||
light.name = name + " Light";
|
||||
}
|
||||
|
||||
return JSON.stringify({
|
||||
dark: dark,
|
||||
light: light
|
||||
}, null, 2);
|
||||
}
|
||||
|
||||
function buildExtractedDynamicMode(colorMode, name) {
|
||||
return {
|
||||
"name": name,
|
||||
"primary": getMatugenColorForMode(colorMode, "primary", "#42a5f5"),
|
||||
"primaryText": getMatugenColorForMode(colorMode, "on_primary", "#ffffff"),
|
||||
"primaryContainer": getMatugenColorForMode(colorMode, "primary_container", "#1976d2"),
|
||||
"secondary": getMatugenColorForMode(colorMode, "secondary", "#8ab4f8"),
|
||||
"secondaryContainer": getMatugenColorForMode(colorMode, "secondary_container", getMatugenColorForMode(colorMode, "surface_container_high", "#292b2f")),
|
||||
"tertiary": getMatugenColorForMode(colorMode, "tertiary", "#efb8c8"),
|
||||
"tertiaryContainer": getMatugenColorForMode(colorMode, "tertiary_container", getMatugenColorForMode(colorMode, "surface_container_high", "#292b2f")),
|
||||
"surface": getMatugenColorForMode(colorMode, "surface", "#1a1c1e"),
|
||||
"surfaceText": getMatugenColorForMode(colorMode, "on_background", "#e3e8ef"),
|
||||
"surfaceVariant": getMatugenColorForMode(colorMode, "surface_variant", "#44464f"),
|
||||
"surfaceVariantText": getMatugenColorForMode(colorMode, "on_surface_variant", "#c4c7c5"),
|
||||
"surfaceTint": getMatugenColorForMode(colorMode, "surface_tint", "#8ab4f8"),
|
||||
"background": getMatugenColorForMode(colorMode, "background", "#1a1c1e"),
|
||||
"backgroundText": getMatugenColorForMode(colorMode, "on_background", "#e3e8ef"),
|
||||
"outline": getMatugenColorForMode(colorMode, "outline", "#8e918f"),
|
||||
"surfaceContainerLowest": getMatugenColorForMode(colorMode, "surface_container_lowest", "#0e1013"),
|
||||
"surfaceContainerLow": getMatugenColorForMode(colorMode, "surface_container_low", "#181a1d"),
|
||||
"surfaceContainer": getMatugenColorForMode(colorMode, "surface_container", "#1e2023"),
|
||||
"surfaceContainerHigh": getMatugenColorForMode(colorMode, "surface_container_high", "#292b2f"),
|
||||
"surfaceContainerHighest": getMatugenColorForMode(colorMode, "surface_container_highest", "#343740"),
|
||||
"error": getMatugenColorForMode(colorMode, "error", "#F2B8B5"),
|
||||
"warning": "#FF9800",
|
||||
"info": "#2196F3",
|
||||
"success": "#4CAF50"
|
||||
};
|
||||
}
|
||||
|
||||
readonly property var currentThemeData: {
|
||||
if (currentTheme === "custom") {
|
||||
return customThemeData || StockThemes.getThemeByName("purple", isLightMode);
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import QtCore
|
||||
import QtQuick
|
||||
import Quickshell
|
||||
import Quickshell.Io
|
||||
import Quickshell.Widgets
|
||||
import qs.Common
|
||||
import qs.Modals.FileBrowser
|
||||
@@ -13,6 +14,7 @@ Item {
|
||||
id: themeColorsTab
|
||||
|
||||
property var parentModal: null
|
||||
property string pendingExtractJson: ""
|
||||
readonly property bool connectedFrameModeActive: SettingsData.connectedFrameModeActive
|
||||
readonly property bool frameModeActive: SettingsData.frameEnabled
|
||||
property var cachedIconThemes: SettingsData.availableIconThemes
|
||||
@@ -564,7 +566,7 @@ Item {
|
||||
}
|
||||
|
||||
Column {
|
||||
width: parent.width - 120 - Theme.spacingM
|
||||
width: parent.width - 120 - Theme.spacingM - 36 - Theme.spacingM
|
||||
spacing: Theme.spacingS
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
|
||||
@@ -586,6 +588,7 @@ Item {
|
||||
}
|
||||
|
||||
StyledText {
|
||||
id: wallpaperPathText
|
||||
text: {
|
||||
if (ToastService.wallpaperErrorStatus === "error")
|
||||
return I18n.tr("Wallpaper processing failed", "wallpaper processing error");
|
||||
@@ -603,6 +606,22 @@ Item {
|
||||
wrapMode: Text.WordWrap
|
||||
}
|
||||
}
|
||||
|
||||
DankActionButton {
|
||||
buttonSize: 36
|
||||
iconName: "download"
|
||||
iconSize: Theme.iconSize
|
||||
backgroundColor: Theme.primaryHover
|
||||
iconColor: Theme.primary
|
||||
tooltipText: I18n.tr("Extract theme to JSON", "extract theme tooltip")
|
||||
anchors.bottom: wallpaperPathText.bottom
|
||||
onClicked: {
|
||||
pendingExtractJson = Theme.extractCurrentTheme();
|
||||
saveBrowserLoader.active = true;
|
||||
if (saveBrowserLoader.item)
|
||||
saveBrowserLoader.item.open();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SettingsDropdownRow {
|
||||
@@ -2977,6 +2996,28 @@ Item {
|
||||
}
|
||||
}
|
||||
|
||||
LazyLoader {
|
||||
id: saveBrowserLoader
|
||||
active: false
|
||||
|
||||
FileBrowserSurfaceModal {
|
||||
id: saveBrowser
|
||||
|
||||
browserTitle: I18n.tr("Save Extracted Theme", "extract theme save dialog title")
|
||||
browserIcon: "download"
|
||||
browserType: "default"
|
||||
fileExtensions: ["*.json"]
|
||||
allowStacking: true
|
||||
saveMode: true
|
||||
defaultFileName: "dms-extracted-theme.json"
|
||||
|
||||
onFileSelected: path => {
|
||||
saveExtractedTheme(pendingExtractJson, Paths.strip(path));
|
||||
close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LazyLoader {
|
||||
id: themeBrowserLoader
|
||||
active: false
|
||||
@@ -2992,4 +3033,26 @@ Item {
|
||||
if (themeBrowserLoader.item)
|
||||
themeBrowserLoader.item.show();
|
||||
}
|
||||
|
||||
FileView {
|
||||
id: extractSaveFileView
|
||||
blockWrites: true
|
||||
preload: false
|
||||
atomicWrites: true
|
||||
printErrors: true
|
||||
|
||||
onSaved: {
|
||||
ToastService.showInfo(I18n.tr("Theme extracted to: %1", "extract theme success").arg(Paths.strip(extractSaveFileView.path)));
|
||||
}
|
||||
|
||||
onSaveFailed: error => {
|
||||
ToastService.showError(I18n.tr("Failed to extract theme", "extract theme error"));
|
||||
log.warn("Failed to write extracted theme to " + extractSaveFileView.path + ": " + error);
|
||||
}
|
||||
}
|
||||
|
||||
function saveExtractedTheme(json, outputPath) {
|
||||
extractSaveFileView.path = outputPath;
|
||||
extractSaveFileView.setText(json);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user