feat(cache): implement icon theme aware caching for notification icons and cleanup on theme change
This commit is contained in:
2 files changed
+80
-3
No files matched your search
@@ -3,7 +3,7 @@ import time
|
||||
import uuid
|
||||
from collections import OrderedDict
|
||||
|
||||
from fabric.utils import GdkPixbuf, get_relative_path, logger, os
|
||||
from fabric.utils import GdkPixbuf, get_relative_path, Gtk, logger, os
|
||||
|
||||
import shared.data as data
|
||||
|
||||
@@ -14,6 +14,28 @@ _MEMORY_PIXBUF_CACHE: OrderedDict[str, GdkPixbuf.Pixbuf] = OrderedDict()
|
||||
_MEMORY_CACHE_MAX = 64
|
||||
|
||||
|
||||
def _get_icon_theme_name():
|
||||
"""Get the current GTK icon theme name for cache invalidation"""
|
||||
try:
|
||||
settings = Gtk.Settings.get_default()
|
||||
if settings:
|
||||
return getattr(settings, "gtk_icon_theme_name", "") or ""
|
||||
except Exception:
|
||||
pass
|
||||
# Fallback: read from settings.ini
|
||||
try:
|
||||
settings_path = os.path.expanduser("~/.config/gtk-3.0/settings.ini")
|
||||
if os.path.exists(settings_path):
|
||||
with open(settings_path) as f:
|
||||
for line in f:
|
||||
line = line.strip()
|
||||
if line.startswith("gtk-icon-theme-name="):
|
||||
return line.split("=", 1)[1].strip()
|
||||
except Exception:
|
||||
pass
|
||||
return ""
|
||||
|
||||
|
||||
def ensure_cache_dir():
|
||||
"""Ensure unified notification cache directory exists"""
|
||||
os.makedirs(UNIFIED_NOTIFICATION_CACHE_DIR, exist_ok=True)
|
||||
@@ -36,10 +58,14 @@ def get_unified_cache_key(source_data, size=None, app_name=None):
|
||||
if source_data.startswith("file://"):
|
||||
source_data = source_data[7:]
|
||||
|
||||
# Create hash from file path and size
|
||||
# Create hash from file path, size, and icon theme
|
||||
hash_input = source_data
|
||||
if size:
|
||||
hash_input += f"_{size[0]}x{size[1]}"
|
||||
# Include icon theme so cache invalidates on theme change
|
||||
theme = _get_icon_theme_name()
|
||||
if theme:
|
||||
hash_input += f"|{theme}"
|
||||
|
||||
return hashlib.md5(hash_input.encode()).hexdigest()[:8]
|
||||
else:
|
||||
@@ -194,7 +220,58 @@ def get_fallback_icon(size=(48, 48)):
|
||||
return None
|
||||
|
||||
|
||||
# Theme tracking for cache invalidation
|
||||
_CURRENT_THEME_FILE = os.path.join(data.CACHE_DIR, ".current_icon_theme")
|
||||
|
||||
|
||||
def _get_stored_theme():
|
||||
"""Get the previously stored icon theme name"""
|
||||
try:
|
||||
if os.path.exists(_CURRENT_THEME_FILE):
|
||||
with open(_CURRENT_THEME_FILE) as f:
|
||||
return f.read().strip()
|
||||
except Exception:
|
||||
pass
|
||||
return ""
|
||||
|
||||
|
||||
def _store_theme(name):
|
||||
"""Store the current icon theme name"""
|
||||
try:
|
||||
os.makedirs(os.path.dirname(_CURRENT_THEME_FILE), exist_ok=True)
|
||||
with open(_CURRENT_THEME_FILE, "w") as f:
|
||||
f.write(name)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
|
||||
def cleanup_theme_changed_caches():
|
||||
"""Clear notification pixbuf caches if icon theme changed since last run"""
|
||||
current_theme = _get_icon_theme_name()
|
||||
stored_theme = _get_stored_theme()
|
||||
|
||||
if current_theme and stored_theme and current_theme != stored_theme:
|
||||
logger.info(
|
||||
f"[Cache] Icon theme changed: {stored_theme} -> {current_theme}, clearing notification caches"
|
||||
)
|
||||
cleanup_cache() # clear all pixbuf caches
|
||||
# Also clear the icon resolver cache since icon names may map differently
|
||||
try:
|
||||
from utils.icon_resolver import ICON_CACHE_FILE
|
||||
|
||||
if os.path.exists(ICON_CACHE_FILE):
|
||||
os.unlink(ICON_CACHE_FILE)
|
||||
logger.info("[Cache] Cleared icon resolver cache")
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
# Store current theme for next run
|
||||
if current_theme:
|
||||
_store_theme(current_theme)
|
||||
|
||||
|
||||
# Initialize cache on module load
|
||||
ensure_cache_dir()
|
||||
cleanup_old_cache_files()
|
||||
cleanup_theme_changed_caches()
|
||||
verify_cache_persistence()
|
||||
@@ -7,7 +7,7 @@ from fabric.widgets.label import Label
|
||||
|
||||
from shared.dialogs.about import AboutApp, get_about_window
|
||||
from shared.window.dropdown import ModusDropdown, dropdown_divider, dropdowns
|
||||
from services.globalmenu import get_global_menu_service
|
||||
from globalmenu.service import get_global_menu_service
|
||||
from utils.app_name_resolver import format_window
|
||||
from utils.roam import modus_service
|
||||
from utils.utils import setup_cursor_hover
|
||||
|
||||
Reference in new issue
Block a user