mirror of
https://github.com/noctalia-dev/noctalia-shell.git
synced 2026-05-11 17:08:27 +08:00
fix(theming): skip theme writes and hooks when wallpaper change produces no diff
Issue: #2400
This commit is contained in:
@@ -22,7 +22,7 @@ import re
|
||||
import sys
|
||||
from dataclasses import dataclass, field
|
||||
from pathlib import Path
|
||||
from typing import Any, Optional, Union
|
||||
from typing import Any, Optional, Tuple, Union
|
||||
|
||||
try:
|
||||
import tomllib
|
||||
@@ -970,13 +970,15 @@ class TemplateRenderer:
|
||||
|
||||
return result
|
||||
|
||||
def render_file(self, input_path: Path, output_path: Path) -> bool:
|
||||
def render_file(self, input_path: Path, output_path: Path) -> Tuple[bool, bool]:
|
||||
"""Render a template file to an output path.
|
||||
|
||||
Returns True if successful, False if skipped due to errors.
|
||||
Returns (success, wrote) where wrote is False if the file was skipped because
|
||||
content was already identical (avoids mtime bumps and app reloads).
|
||||
"""
|
||||
self._current_file = str(input_path)
|
||||
success = False
|
||||
wrote = False
|
||||
try:
|
||||
template_text = input_path.read_text()
|
||||
rendered_text = self.render(template_text)
|
||||
@@ -984,8 +986,18 @@ class TemplateRenderer:
|
||||
if self._error_count > 0:
|
||||
print(f"Skipping {output_path}: template has {self._error_count} error(s)", file=sys.stderr)
|
||||
else:
|
||||
output_path.parent.mkdir(parents=True, exist_ok=True)
|
||||
output_path.write_text(rendered_text)
|
||||
out = Path(output_path).expanduser()
|
||||
out.parent.mkdir(parents=True, exist_ok=True)
|
||||
skip_write = False
|
||||
if out.is_file():
|
||||
try:
|
||||
if out.read_text() == rendered_text:
|
||||
skip_write = True
|
||||
except OSError:
|
||||
pass
|
||||
if not skip_write:
|
||||
out.write_text(rendered_text)
|
||||
wrote = True
|
||||
success = True
|
||||
except FileNotFoundError:
|
||||
self._log_error(f"Template file not found: {input_path}")
|
||||
@@ -995,7 +1007,7 @@ class TemplateRenderer:
|
||||
self._log_error(f"Unexpected error: {e}")
|
||||
finally:
|
||||
self._current_file = None
|
||||
return success
|
||||
return success, wrote
|
||||
|
||||
# --- Custom Colors ---
|
||||
|
||||
@@ -1151,7 +1163,13 @@ class TemplateRenderer:
|
||||
rendered_compare_to = self.render(compare_to)
|
||||
self.closest_color = find_closest_color(rendered_compare_to, colors_to_compare)
|
||||
|
||||
self.render_file(Path(input_path).expanduser(), Path(output_path).expanduser())
|
||||
ok, wrote = self.render_file(Path(input_path).expanduser(), Path(output_path).expanduser())
|
||||
if not ok:
|
||||
continue
|
||||
|
||||
# Hooks reload external apps (e.g. Discord); skip when output unchanged
|
||||
if not wrote:
|
||||
continue
|
||||
|
||||
# Execute pre_hook if specified
|
||||
pre_hook = template.get("pre_hook")
|
||||
|
||||
@@ -23,8 +23,11 @@ Singleton {
|
||||
|
||||
if (Settings.data.colorSchemes.useWallpaperColors) {
|
||||
generateFromWallpaper();
|
||||
} else if (ColorSchemeService.lastPredefinedSchemeData) {
|
||||
// Regenerate templates only; skip applyScheme so colors.json and scheme reload stay untouched
|
||||
// when outputs are unchanged (see template processor skip-identical writes).
|
||||
generateFromPredefinedScheme(ColorSchemeService.lastPredefinedSchemeData);
|
||||
} else {
|
||||
// Re-run predefined scheme templates so {{image}} reflects the new wallpaper path
|
||||
ColorSchemeService.applyScheme(Settings.data.colorSchemes.predefinedScheme);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,9 @@ Singleton {
|
||||
property string schemesDirectory: Quickshell.shellDir + "/Assets/ColorScheme"
|
||||
property string downloadedSchemesDirectory: Settings.configDir + "colorschemes"
|
||||
property string colorsJsonFilePath: Settings.configDir + "colors.json"
|
||||
// Last successfully parsed predefined scheme JSON (full object). Used to refresh app templates
|
||||
// on wallpaper changes without re-running applyScheme (avoids rewriting colors.json when unchanged).
|
||||
property var lastPredefinedSchemeData: null
|
||||
readonly property string gtkRefreshScript: Quickshell.shellDir + "/Scripts/python/src/theming/gtk-refresh.py"
|
||||
|
||||
// prefer-light/prefer-dark only; GTK template post_hook still runs full gtk-refresh.
|
||||
@@ -203,6 +206,7 @@ Singleton {
|
||||
}
|
||||
}
|
||||
writeColorsToDisk(variant);
|
||||
lastPredefinedSchemeData = data;
|
||||
Logger.i("ColorScheme", "Applying color scheme:", getBasename(path));
|
||||
|
||||
// Generate templates for predefined color schemes
|
||||
|
||||
Reference in New Issue
Block a user