mirror of
https://github.com/zoriya/noctalia-shell.git
synced 2026-08-15 18:43:59 +00:00
Matugen/Code: add VSCodium support
This commit is contained in:
@@ -880,7 +880,7 @@
|
||||
"programs": {
|
||||
"code": {
|
||||
"description": "Schreibe {Dateipfad}. Das Hyprluna-Theme muss manuell installiert und aktiviert werden",
|
||||
"description-missing": "Benötigt die Installation von {app}"
|
||||
"description-missing": "Kein Code-Client erkannt. Installieren Sie VSCode oder VSCodium."
|
||||
},
|
||||
"description": "Anwendungsspezifisches Theming.",
|
||||
"discord": {
|
||||
|
||||
@@ -880,7 +880,7 @@
|
||||
"programs": {
|
||||
"code": {
|
||||
"description": "Write {filepath}. Hyprluna theme needs to be installed and activated manually.",
|
||||
"description-missing": "Requires {app} to be installed"
|
||||
"description-missing": "No Code client detected. Install VSCode or VSCodium."
|
||||
},
|
||||
"description": "Application-specific theming.",
|
||||
"discord": {
|
||||
|
||||
@@ -880,7 +880,7 @@
|
||||
"programs": {
|
||||
"code": {
|
||||
"description": "Escribe {filepath}. El tema Hyprluna debe ser instalado y activado manualmente.",
|
||||
"description-missing": "Requiere que {app} esté instalado/a."
|
||||
"description-missing": "No se detectó cliente de Code. Instala VSCode o VSCodium."
|
||||
},
|
||||
"description": "Tematización específica de aplicaciones.",
|
||||
"discord": {
|
||||
|
||||
@@ -880,7 +880,7 @@
|
||||
"programs": {
|
||||
"code": {
|
||||
"description": "Écrire {filepath}. Le thème Hyprluna doit être installé et activé manuellement.",
|
||||
"description-missing": "Nécessite l'installation de {app}"
|
||||
"description-missing": "Aucun client Code détecté. Installez VSCode ou VSCodium."
|
||||
},
|
||||
"description": "Thématisation spécifique aux applications.",
|
||||
"discord": {
|
||||
|
||||
@@ -880,7 +880,7 @@
|
||||
"programs": {
|
||||
"code": {
|
||||
"description": "Schrijf {filepath}. Het Hyprluna-thema moet handmatig worden geïnstalleerd en geactiveerd.",
|
||||
"description-missing": "Vereist dat {app} is geïnstalleerd."
|
||||
"description-missing": "Geen Code-client gedetecteerd. Installeer VSCode of VSCodium."
|
||||
},
|
||||
"description": "Toepassingsspecifieke theming.",
|
||||
"discord": {
|
||||
|
||||
@@ -880,7 +880,7 @@
|
||||
"programs": {
|
||||
"code": {
|
||||
"description": "Escreva em {filepath}. O tema Hyprluna precisa ser instalado e ativado manualmente.",
|
||||
"description-missing": "Requer que o {app} esteja instalado."
|
||||
"description-missing": "Nenhum cliente Code detectado. Instale VSCode ou VSCodium."
|
||||
},
|
||||
"description": "Tematização específica de aplicativos.",
|
||||
"discord": {
|
||||
|
||||
@@ -880,7 +880,7 @@
|
||||
"programs": {
|
||||
"code": {
|
||||
"description": "Записать {filepath}. Тему Hyprluna нужно установить и активировать вручную.",
|
||||
"description-missing": "Требуется установка {app}"
|
||||
"description-missing": "Клиент Code не обнаружен. Установите VSCode или VSCodium."
|
||||
},
|
||||
"description": "Тематика для конкретных приложений.",
|
||||
"discord": {
|
||||
|
||||
@@ -880,7 +880,7 @@
|
||||
"programs": {
|
||||
"code": {
|
||||
"description": "{filepath} dosyasına yaz. Hyprluna temasının kurulu ve manuel olarak etkinleştirilmiş olması gerekir.",
|
||||
"description-missing": "Kurulum için {app} gereklidir"
|
||||
"description-missing": "Code istemcisi tespit edilmedi. VSCode veya VSCodium kurun."
|
||||
},
|
||||
"description": "Uygulamaya özel temalandırma.",
|
||||
"discord": {
|
||||
|
||||
@@ -880,7 +880,7 @@
|
||||
"programs": {
|
||||
"code": {
|
||||
"description": "Записати {filepath}. Тему Hyprluna потрібно встановити та активувати вручну.",
|
||||
"description-missing": "Потрібна установка {app}"
|
||||
"description-missing": "Клієнт Code не виявлено. Встановіть VSCode або VSCodium."
|
||||
},
|
||||
"description": "Оформлення окремих програм.",
|
||||
"discord": {
|
||||
|
||||
@@ -880,7 +880,7 @@
|
||||
"programs": {
|
||||
"code": {
|
||||
"description": "写入 {filepath}。Hyprluna 主题需要手动安装和激活。",
|
||||
"description-missing": "需要安装 {app}"
|
||||
"description-missing": "未检测到 Code 客户端。请安装 VSCode 或 VSCodium。"
|
||||
},
|
||||
"description": "应用程序特定主题。",
|
||||
"discord": {
|
||||
|
||||
@@ -740,19 +740,48 @@ ColumnLayout {
|
||||
}
|
||||
}
|
||||
|
||||
// Code clients - single toggle with dynamic description
|
||||
NCheckbox {
|
||||
id: codeToggle
|
||||
label: "Code"
|
||||
description: ProgramCheckerService.codeAvailable ? I18n.tr("settings.color-scheme.templates.programs.code.description", {
|
||||
"filepath": "~/.vscode/extensions/hyprluna.hyprluna-theme-1.0.2/themes/hyprluna.json"
|
||||
}) : I18n.tr("settings.color-scheme.templates.programs.code.description-missing", {
|
||||
"app": "code"
|
||||
})
|
||||
checked: Settings.data.templates.code
|
||||
enabled: ProgramCheckerService.codeAvailable
|
||||
opacity: ProgramCheckerService.codeAvailable ? 1.0 : 0.6
|
||||
description: {
|
||||
if (ProgramCheckerService.availableCodeClients.length === 0) {
|
||||
return I18n.tr("settings.color-scheme.templates.programs.code.description-missing")
|
||||
} else {
|
||||
// Show detected clients
|
||||
var clientInfo = []
|
||||
for (var i = 0; i < ProgramCheckerService.availableCodeClients.length; i++) {
|
||||
var client = ProgramCheckerService.availableCodeClients[i]
|
||||
// Capitalize first letter and format nicely
|
||||
var clientName = client.name === "code" ? "VSCode" : "VSCodium"
|
||||
clientInfo.push(clientName)
|
||||
}
|
||||
return "Detected: " + clientInfo.join(", ")
|
||||
}
|
||||
}
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredWidth: -1
|
||||
checked: {
|
||||
// Check if any Code client template is enabled
|
||||
var anyEnabled = false
|
||||
for (var i = 0; i < ProgramCheckerService.availableCodeClients.length; i++) {
|
||||
var client = ProgramCheckerService.availableCodeClients[i]
|
||||
if (Settings.data.templates["code_" + client.name]) {
|
||||
anyEnabled = true
|
||||
break
|
||||
}
|
||||
}
|
||||
return anyEnabled
|
||||
}
|
||||
enabled: ProgramCheckerService.availableCodeClients.length > 0
|
||||
opacity: ProgramCheckerService.availableCodeClients.length > 0 ? 1.0 : 0.6
|
||||
onToggled: checked => {
|
||||
if (ProgramCheckerService.codeAvailable) {
|
||||
Settings.data.templates.code = checked
|
||||
// Enable/disable all detected Code clients
|
||||
for (var i = 0; i < ProgramCheckerService.availableCodeClients.length; i++) {
|
||||
var client = ProgramCheckerService.availableCodeClients[i]
|
||||
Settings.data.templates["code_" + client.name] = checked
|
||||
}
|
||||
if (ProgramCheckerService.availableCodeClients.length > 0) {
|
||||
AppThemeService.generate()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,6 +31,9 @@ Singleton {
|
||||
// Discord client auto-detection
|
||||
property var availableDiscordClients: []
|
||||
|
||||
// Code client auto-detection
|
||||
property var availableCodeClients: []
|
||||
|
||||
// Signal emitted when all checks are complete
|
||||
signal checksCompleted
|
||||
|
||||
@@ -97,6 +100,66 @@ Singleton {
|
||||
stderr: StdioCollector {}
|
||||
}
|
||||
|
||||
// Function to detect Code client by checking config directories
|
||||
function detectCodeClient() {
|
||||
// Build shell script to check each client
|
||||
var scriptParts = ["available_clients=\"\";"]
|
||||
|
||||
for (var i = 0; i < TemplateRegistry.codeClients.length; i++) {
|
||||
var client = TemplateRegistry.codeClients[i]
|
||||
var clientName = client.name
|
||||
var configPath = client.configPath
|
||||
|
||||
// Check if the config directory exists
|
||||
scriptParts.push("if [ -d \"$HOME" + configPath.substring(1) + "\" ]; then available_clients=\"$available_clients " + clientName + "\"; fi;")
|
||||
}
|
||||
|
||||
scriptParts.push("echo \"$available_clients\"")
|
||||
|
||||
// Use a Process to check directory existence for all clients
|
||||
codeDetector.command = ["sh", "-c", scriptParts.join(" ")]
|
||||
codeDetector.running = true
|
||||
}
|
||||
|
||||
// Process to detect Code client directories
|
||||
Process {
|
||||
id: codeDetector
|
||||
running: false
|
||||
|
||||
onExited: function (exitCode) {
|
||||
availableCodeClients = []
|
||||
|
||||
if (exitCode === 0) {
|
||||
var detectedClients = stdout.text.trim().split(/\s+/).filter(function (client) {
|
||||
return client.length > 0
|
||||
})
|
||||
|
||||
if (detectedClients.length > 0) {
|
||||
// Build list of available clients
|
||||
for (var i = 0; i < detectedClients.length; i++) {
|
||||
var clientName = detectedClients[i]
|
||||
for (var j = 0; j < TemplateRegistry.codeClients.length; j++) {
|
||||
var client = TemplateRegistry.codeClients[j]
|
||||
if (client.name === clientName) {
|
||||
availableCodeClients.push(client)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Logger.i("ProgramChecker", "Detected Code clients:", detectedClients.join(", "))
|
||||
}
|
||||
}
|
||||
|
||||
if (availableCodeClients.length === 0) {
|
||||
Logger.d("ProgramChecker", "No Code clients detected")
|
||||
}
|
||||
}
|
||||
|
||||
stdout: StdioCollector {}
|
||||
stderr: StdioCollector {}
|
||||
}
|
||||
|
||||
// Programs to check - maps property names to commands
|
||||
readonly property var programsToCheck: ({
|
||||
"matugenAvailable": ["which", "matugen"],
|
||||
@@ -140,8 +203,9 @@ Singleton {
|
||||
|
||||
// Check next program or emit completion signal
|
||||
if (root.completedChecks >= root.totalChecks) {
|
||||
// Run Discord client detection after all checks are complete
|
||||
// Run Discord and Code client detection after all checks are complete
|
||||
root.detectDiscordClient()
|
||||
root.detectCodeClient()
|
||||
root.checksCompleted()
|
||||
} else {
|
||||
root.checkNextProgram()
|
||||
|
||||
@@ -114,6 +114,18 @@ Singleton {
|
||||
}
|
||||
})
|
||||
}
|
||||
} else if (app.id === "code") {
|
||||
// Handle Code clients specially
|
||||
if (Settings.data.templates.code) {
|
||||
app.clients.forEach(client => {
|
||||
// Check if this specific client is detected
|
||||
if (isCodeClientEnabled(client.name)) {
|
||||
lines.push(`\n[templates.code_${client.name}]`)
|
||||
lines.push(`input_path = "${Quickshell.shellDir}/Assets/MatugenTemplates/${app.input}"`)
|
||||
lines.push(`output_path = "${client.path}"`)
|
||||
}
|
||||
})
|
||||
}
|
||||
} else {
|
||||
// Handle regular apps
|
||||
if (Settings.data.templates[app.id]) {
|
||||
@@ -140,6 +152,16 @@ Singleton {
|
||||
return false
|
||||
}
|
||||
|
||||
function isCodeClientEnabled(clientName) {
|
||||
// Check ProgramCheckerService to see if client is detected
|
||||
for (var i = 0; i < ProgramCheckerService.availableCodeClients.length; i++) {
|
||||
if (ProgramCheckerService.availableCodeClients[i].name === clientName) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
function buildMatugenScript(content, wallpaper, mode) {
|
||||
const delimiter = "MATUGEN_CONFIG_EOF_" + Math.random().toString(36).substr(2, 9)
|
||||
const pathEsc = dynamicConfigPath.replace(/'/g, "'\\''")
|
||||
@@ -163,6 +185,10 @@ Singleton {
|
||||
if (Settings.data.templates.discord) {
|
||||
script += processDiscordClients(app, colors, mode, homeDir)
|
||||
}
|
||||
} else if (app.id === "code") {
|
||||
if (Settings.data.templates.code) {
|
||||
script += processCodeClients(app, colors, mode, homeDir)
|
||||
}
|
||||
} else {
|
||||
if (Settings.data.templates[app.id]) {
|
||||
script += processTemplate(app, colors, mode, homeDir)
|
||||
@@ -198,6 +224,39 @@ Singleton {
|
||||
return script
|
||||
}
|
||||
|
||||
function processCodeClients(codeApp, colors, mode, homeDir) {
|
||||
let script = ""
|
||||
const palette = ColorPaletteGenerator.generatePalette(colors, Settings.data.colorSchemes.darkMode, false)
|
||||
|
||||
codeApp.clients.forEach(client => {
|
||||
if (!isCodeClientEnabled(client.name))
|
||||
return
|
||||
|
||||
const templatePath = `${Quickshell.shellDir}/Assets/MatugenTemplates/${codeApp.input}`
|
||||
const outputPath = client.path.replace("~", homeDir)
|
||||
const outputDir = outputPath.substring(0, outputPath.lastIndexOf('/'))
|
||||
|
||||
// Extract base config directory for checking
|
||||
var baseConfigDir = ""
|
||||
if (client.name === "code") {
|
||||
baseConfigDir = "~/.vscode".replace("~", homeDir)
|
||||
} else if (client.name === "codium") {
|
||||
baseConfigDir = "~/.vscode-oss".replace("~", homeDir)
|
||||
}
|
||||
|
||||
script += `\n`
|
||||
script += `if [ -d "${baseConfigDir}" ]; then\n`
|
||||
script += ` mkdir -p ${outputDir}\n`
|
||||
script += ` cp '${templatePath}' '${outputPath}'\n`
|
||||
script += ` ${replaceColorsInFile(outputPath, palette)}`
|
||||
script += `else\n`
|
||||
script += ` echo "Code client ${client.name} not found at ${baseConfigDir}, skipping"\n`
|
||||
script += `fi\n`
|
||||
})
|
||||
|
||||
return script
|
||||
}
|
||||
|
||||
function processTemplate(app, colors, mode, homeDir) {
|
||||
const palette = ColorPaletteGenerator.generatePalette(colors, Settings.data.colorSchemes.darkMode, app.strict || false)
|
||||
let script = ""
|
||||
|
||||
@@ -142,14 +142,18 @@ Singleton {
|
||||
"path": "~/.config/discord",
|
||||
"requiresThemesFolder": true
|
||||
}]
|
||||
}, // VSCode with hardcoded path (requirement #5)
|
||||
},
|
||||
{
|
||||
"id": "code",
|
||||
"name": "VSCode",
|
||||
"category": "applications",
|
||||
"input": "code.json",
|
||||
"outputs": [{
|
||||
"clients": [{
|
||||
"name": "code",
|
||||
"path": "~/.vscode/extensions/hyprluna.hyprluna-theme-1.0.2/themes/hyprluna.json"
|
||||
}, {
|
||||
"name": "codium",
|
||||
"path": "~/.vscode-oss/extensions/hyprluna.hyprluna-theme-1.0.2/themes/hyprluna.json"
|
||||
}]
|
||||
}, {
|
||||
"id": "spicetify",
|
||||
@@ -179,6 +183,33 @@ Singleton {
|
||||
return clients
|
||||
}
|
||||
|
||||
// Extract Code clients for ProgramCheckerService compatibility
|
||||
readonly property var codeClients: {
|
||||
var clients = []
|
||||
var codeApp = applications.find(app => app.id === "code")
|
||||
if (codeApp && codeApp.clients) {
|
||||
codeApp.clients.forEach(client => {
|
||||
// Extract base config directory from theme path
|
||||
var themePath = client.path
|
||||
var baseConfigDir = ""
|
||||
if (client.name === "code") {
|
||||
// For VSCode: ~/.vscode/extensions/... -> ~/.vscode
|
||||
baseConfigDir = "~/.vscode"
|
||||
} else if (client.name === "codium") {
|
||||
// For VSCodium: ~/.vscode-oss/extensions/... -> ~/.vscode-oss
|
||||
baseConfigDir = "~/.vscode-oss"
|
||||
}
|
||||
clients.push({
|
||||
"name": client.name,
|
||||
"configPath": baseConfigDir,
|
||||
"themePath": themePath,
|
||||
"requiresThemesFolder": false
|
||||
})
|
||||
})
|
||||
}
|
||||
return clients
|
||||
}
|
||||
|
||||
// Build user templates TOML content
|
||||
function buildUserTemplatesToml() {
|
||||
var lines = []
|
||||
|
||||
Reference in New Issue
Block a user