Files
noctalia-shell/Services/MatugenService.qml
T

240 lines
7.4 KiB
QML

pragma Singleton
import QtQuick
import Quickshell
import Quickshell.Io
import qs.Commons
import qs.Services
import "../Helpers/ColorsConvert.js" as ColorsConvert
Singleton {
id: root
readonly property string colorsApplyScript: Quickshell.shellDir + '/Bin/colors-apply.sh'
property string dynamicConfigPath: Settings.cacheDir + "matugen.dynamic.toml"
// External state management
Connections {
target: WallpaperService
function onWallpaperChanged(screenName, path) {
// Only detect changes on main screen
if (screenName === Screen.name && Settings.data.colorSchemes.useWallpaperColors) {
generateFromWallpaper()
}
}
}
Connections {
target: Settings.data.colorSchemes
function onDarkModeChanged() {
Logger.log("Matugen", "Detected dark mode change")
if (Settings.data.colorSchemes.useWallpaperColors) {
MatugenService.generateFromWallpaper()
}
}
}
// --------------------------------
function init() {
// does nothing but ensure the singleton is created
// do not remove
Logger.log("Matugen", "Service started")
}
// --------------------------------
// Generate colors using current wallpaper and settings
function generateFromWallpaper() {
Logger.log("Matugen", "Generating from wallpaper on screen:", Screen.name)
var wp = WallpaperService.getWallpaper(Screen.name).replace(/'/g, "'\\''")
if (wp === "") {
Logger.error("Matugen", "No wallpaper was found")
return
}
var content = MatugenTemplates.buildConfigToml()
if (content === "") {
return
}
var mode = Settings.data.colorSchemes.darkMode ? "dark" : "light"
var pathEsc = dynamicConfigPath.replace(/'/g, "'\\''")
var script = buildMatugenScript(content, pathEsc, wp, mode)
generateProcess.command = ["bash", "-lc", script]
generateProcess.running = true
}
// --------------------------------
function buildMatugenScript(content, pathEsc, wallpaper, mode) {
var script = "cat > '" + pathEsc + "' << 'EOF'\n" + content + "EOF\n"
// Main matugen command
script += "matugen image '" + wallpaper + "' --config '" + pathEsc + "' --mode " + mode + " --type " + Settings.data.colorSchemes.matugenSchemeType
// Add user template execution if enabled
script += addUserTemplateExecution(wallpaper, mode)
return script + "\n"
}
// --------------------------------
function addUserTemplateExecution(input, mode) {
if (!Settings.data.templates.enableUserTemplates) {
return ""
}
var userConfigPath = getUserConfigPath()
var script = "\n# Execute user config if it exists\n"
script += "if [ -f '" + userConfigPath + "' ]; then\n"
script += " matugen image '" + input + "' --config '" + userConfigPath + "' --mode " + mode + " --type " + Settings.data.colorSchemes.matugenSchemeType + "\n"
script += "fi"
return script
}
// --------------------------------
function getUserConfigPath() {
return (Quickshell.env("HOME") + "/.config/matugen/config.toml").replace(/'/g, "'\\''")
}
// --------------------------------
function selectVibrantColor(schemeData, mode) {
var colors = []
colors.push(schemeData[mode]["mPrimary"])
colors.push(schemeData[mode]["mSecondary"])
colors.push(schemeData[mode]["mTertiary"])
var bestScore = 0
var bestScoreIndex = -1
for (var i = 0; i < colors.length; i++) {
var hsl = ColorsConvert.hexToHSL(colors[i])
var score = hsl['s']
if (score > bestScore) {
bestScore = score
bestScoreIndex = i
}
}
return colors[bestScoreIndex]
}
// --------------------------------
// Generate templates from predefined color scheme
function generateFromPredefinedScheme(schemeData) {
Logger.log("Matugen", "Generating templates from predefined color scheme")
// Handle terminal theme copying for predefined schemes
handleTerminalThemes()
var content = MatugenTemplates.buildConfigToml()
if (content === "") {
return
}
var mode = Settings.data.colorSchemes.darkMode ? "dark" : "light"
var pathEsc = dynamicConfigPath.replace(/'/g, "'\\''")
const color = selectVibrantColor(schemeData, mode)
var script = buildPredefinedSchemeScript(content, pathEsc, color, mode)
generateProcess.command = ["bash", "-lc", script]
generateProcess.running = true
}
// --------------------------------
function buildPredefinedSchemeScript(content, pathEsc, color, mode) {
var script = "cat > '" + pathEsc + "' << 'EOF'\n" + content + "EOF\n\n"
script += "matugen color hex '" + color + "' --config '" + pathEsc + "' --mode " + mode + "\n"
// Add user template execution if enabled
script += addUserTemplateExecutionForColor(color, mode)
return script
}
// --------------------------------
function addUserTemplateExecutionForColor(color, mode) {
if (!Settings.data.templates.enableUserTemplates) {
return ""
}
var userConfigPath = getUserConfigPath()
var script = "\n# Execute user config if it exists\n"
script += "if [ -f '" + userConfigPath + "' ]; then\n"
script += " matugen color hex '" + color + "' --config '" + userConfigPath + "' --mode " + mode + "\n"
script += "fi"
return script
}
// --------------------------------
function handleTerminalThemes() {
var terminals = {
"foot": "~/.config/foot/themes/noctalia",
"ghostty": "~/.config/ghostty/themes/noctalia",
"kitty": "~/.config/kitty/themes/noctalia.conf"
}
var copyCmd = Object.keys(terminals).filter(function (terminal) {
return Settings.data.templates[terminal]
}).map(function (terminal) {
var colorsPath = terminals[terminal]
var colorsPathParent = colorsPath.replace(/[^\/]*$/, "")
var terminalColorsTemplate = getTerminalColorsTemplate(terminal)
return ['mkdir -p ' + colorsPathParent, 'cp -f ' + terminalColorsTemplate + ' ' + colorsPath, colorsApplyScript + ' ' + terminal]
}).reduce(function (arr1, arr2) {
return arr1.concat(arr2)
}, []).join('; ')
if (copyCmd !== "") {
copyProcess.command = ["bash", "-lc", copyCmd]
copyProcess.running = true
}
}
// --------------------------------
function getTerminalColorsTemplate(terminal) {
var colorScheme = Settings.data.colorSchemes.predefinedScheme
const darkLight = Settings.data.colorSchemes.darkMode ? 'dark' : 'light'
// Convert display names back to folder names
var schemeMap = {
"Noctalia (default)": "Noctalia-default",
"Noctalia (legacy)": "Noctalia-legacy",
"Tokyo Night": "Tokyo-Night"
}
colorScheme = schemeMap[colorScheme] || colorScheme
var extension = terminal === 'kitty' ? ".conf" : ""
return `${Quickshell.shellDir}/Assets/ColorScheme/${colorScheme}/terminal/${terminal}/${colorScheme}-${darkLight}${extension}`
}
// --------------------------------
Process {
id: generateProcess
workingDirectory: Quickshell.shellDir
running: false
stderr: StdioCollector {
onStreamFinished: {
if (this.text !== "") {
Logger.warn("MatugenService", "GenerateProcess stderr:", this.text)
}
}
}
}
// --------------------------------
Process {
id: copyProcess
running: false
stderr: StdioCollector {
onStreamFinished: {
if (this.text !== "") {
Logger.warn("MatugenService", "CopyProcess stderr:", this.text)
}
}
}
}
}