refactor! : drop subprocess usage and centralize brightness service initialization

This commit is contained in:
sankalp committed 2026-07-08 12:25:02 +05:45
1 parent 06be28535a
commit 5b8d6a62aa
21 files changed
+834 -828

No files matched your search

+60 -30
View File
@@ -625,38 +625,63 @@ class NotificationWidget(Box):
return get_fallback_notification_icon((width, height))
def _get_notification_pixbuf(self, notification):
"""Simplified notification pixbuf with NO CACHING for image-pixmap to prevent disk bloat"""
notification_id = getattr(notification, "id", int(time.time()))
"""Notification pixbuf — loads notification image or app icon, scaled consistently."""
pixbuf = None
try:
# Try to get cached notification image first
if hasattr(notification, "image_pixbuf") and notification.image_pixbuf:
# 1. Try cache_metadata keys first (cheap — no disk/pixbuf load)
cache_meta = getattr(notification, "cache_metadata", {}) or {}
notif_key = cache_meta.get("notification_image_cache_key")
if notif_key:
try:
pixbuf = get_cached_notification_image(notif_key)
except Exception:
pass
# 2. Try notification image via image_pixbuf (only if no cached)
if not pixbuf:
try:
img = getattr(notification, "image_pixbuf", None)
if img is not None:
nid = getattr(notification, "id", 0)
ck = get_notification_image_cache_key(nid, img)
cached = get_cached_notification_image(ck)
if cached:
pixbuf = cached
except Exception:
pass
# 3. App icon via cache_metadata
if not pixbuf:
app_key = cache_meta.get("app_icon_cache_key")
if app_key:
try:
cache_key = get_notification_image_cache_key(
notification_id, notification.image_pixbuf
)
cached_image = get_cached_notification_image(cache_key)
if cached_image:
return cached_image
except Exception as image_error:
logger.debug(f"Notification image processing failed: {image_error}")
# Continue to app icon fallback
from window.notification.unified_cache import get_from_cache
except Exception as e:
logger.debug(f"Failed to process notification image: {e}")
pixbuf = get_from_cache(app_key, (35, 35))
except Exception:
pass
# 4. Direct app icon caching
if not pixbuf:
app_icon = getattr(notification, "app_icon", None)
if app_icon:
try:
pixbuf = cache_notification_icon(app_icon, (35, 35))
except Exception:
pass
# 5. Fallback
if not pixbuf:
pixbuf = get_fallback_notification_icon((35, 35))
# Use cached app icon as fallback
try:
app_icon_source = getattr(notification, "app_icon", None)
if app_icon_source:
cached_app_icon = cache_notification_icon(app_icon_source, (35, 35))
if cached_app_icon:
return cached_app_icon
except Exception as e:
logger.debug(f"Failed to get cached app icon: {e}")
# Ultimate fallback
return get_fallback_notification_icon((35, 35))
return pixbuf.scale_simple(
NOTIFICATION_IMAGE_SIZE,
NOTIFICATION_IMAGE_SIZE,
GdkPixbuf.InterpType.BILINEAR,
)
except Exception:
return pixbuf
def create_action_buttons(self, notification):
return Box(
@@ -1122,10 +1147,11 @@ class ModusNoti(Window):
self.current_notification = new_box
# Clear any existing children
# Clear and destroy any existing children
for child in list(self.notifications.children):
try:
self.notifications.remove(child)
child.destroy()
except Exception as e:
logger.error(f"An error occurred: {e}")
@@ -1154,10 +1180,11 @@ class ModusNoti(Window):
GLib.source_remove(self._transition_timer_id)
self._transition_timer_id = None
# Safely remove notification box
# Safely remove and destroy notification box
try:
if notification_box in self.notifications.children:
self.notifications.remove(notification_box)
notification_box.destroy()
except Exception as e:
logger.error(f"An error occurred: {e}")
@@ -1197,8 +1224,11 @@ class ModusNoti(Window):
# Also clean current notification if showing
if self.current_notification:
# Mark for cache cleanup when clearing queue
self.current_notification.notif_box._should_cleanup_cache = True
try:
self.current_notification.notification.close("dismissed-by-user")
except Exception as e:
logger.error(f"An error occurred: {e}")
# Clear animation timers
if self._transition_timer_id:
+20 -12
View File
@@ -698,6 +698,8 @@ class NotificationCenter(AppletWindow):
self.add_keybinding("Escape", self._on_escape_pressed)
MAX_GROUPS = 15
def _rebuild_notification_groups(self):
"""Rebuild notification groups from scratch with enhanced asset preloading and debugging"""
# Clear existing groups
@@ -709,23 +711,27 @@ class NotificationCenter(AppletWindow):
child.destroy()
# Group notifications by app name and preload assets with debugging
rebuild_count = 0
for cached_notification in notification_service.cached_notifications:
app_name = cached_notification._notification.app_name
getattr(cached_notification._notification, "id", None)
# Skip ignored apps during rebuild
if app_name in data.NOTIFICATION_IGNORED_APPS_HISTORY:
continue
# Preload assets for each cached notification to ensure display consistency
preload_notification_assets(cached_notification._notification)
self.notification_groups[app_name].append(cached_notification)
rebuild_count += 1
# Sort groups by most recent notification
sorted_groups = sorted(
self.notification_groups.items(),
key=lambda item: max(
(getattr(n._notification, "id", 0) for n in item[1]), default=0
),
reverse=True,
)[: self.MAX_GROUPS]
self.notification_groups.clear()
# Create group widgets and handle limited apps
for app_name, notifications in self.notification_groups.items():
for app_name, notifications in sorted_groups:
# Sort notifications by ID (highest ID first - newest notifications)
# This ensures the latest notifications appear at the top of each group
notifications.sort(
@@ -736,11 +742,10 @@ class NotificationCenter(AppletWindow):
if app_name in data.NOTIFICATION_LIMITED_APPS_HISTORY:
if len(notifications) > 5:
# Keep only the 5 most recent notifications
self.notification_groups[app_name] = notifications[:5]
notifications = notifications[:5]
group_widget = ExpandableNotificationGroup(
app_name, self.notification_groups[app_name]
)
group_widget = ExpandableNotificationGroup(app_name, notifications)
self.notification_groups[app_name] = notifications
self.group_widgets[app_name] = group_widget
self.notifications_box.add(group_widget)
@@ -809,9 +814,10 @@ class NotificationCenter(AppletWindow):
def _refresh_group_widget(self, group_widget):
"""Refresh a group widget's content"""
try:
# Remove existing children
# Remove and destroy existing children
for child in group_widget.get_children():
group_widget.remove(child)
child.destroy()
# Recreate content
group_widget.create_collapsed_state()
@@ -886,6 +892,8 @@ class NotificationCenter(AppletWindow):
# Clear all remaining cached notification images AND icons when clear all is clicked
cleanup_all_notification_caches() # Clear ALL caches (icons + images)
for child in self.notifications_box.get_children():
child.destroy()
notification_service.clear_all_cached_notifications()
self.hide()
+18 -3
View File
@@ -1,6 +1,7 @@
import hashlib
import time
import uuid
from collections import OrderedDict
from fabric.utils import GdkPixbuf, get_relative_path, logger, os
@@ -9,6 +10,9 @@ import shared.data as data
# Unified notification cache directory (for both app icons and notification images)
UNIFIED_NOTIFICATION_CACHE_DIR = os.path.join(data.CACHE_DIR, "notifications")
_MEMORY_PIXBUF_CACHE: OrderedDict[str, GdkPixbuf.Pixbuf] = OrderedDict()
_MEMORY_CACHE_MAX = 64
def ensure_cache_dir():
"""Ensure unified notification cache directory exists"""
@@ -72,16 +76,23 @@ def save_to_cache(pixbuf, cache_key, size=None):
def get_from_cache(cache_key, size=None):
"""Get a cached asset or return None if not found"""
mem_key = f"{cache_key}:{size}"
if mem_key in _MEMORY_PIXBUF_CACHE:
_MEMORY_PIXBUF_CACHE.move_to_end(mem_key)
return _MEMORY_PIXBUF_CACHE[mem_key]
try:
cache_path = os.path.join(UNIFIED_NOTIFICATION_CACHE_DIR, f"{cache_key}.png")
if os.path.exists(cache_path):
# logger.debug(f"Using cached asset: {cache_key}")
if size:
return GdkPixbuf.Pixbuf.new_from_file_at_scale(
pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_scale(
cache_path, size[0], size[1], True
)
else:
return GdkPixbuf.Pixbuf.new_from_file(cache_path)
pixbuf = GdkPixbuf.Pixbuf.new_from_file(cache_path)
while len(_MEMORY_PIXBUF_CACHE) >= _MEMORY_CACHE_MAX:
_MEMORY_PIXBUF_CACHE.popitem(last=False)
_MEMORY_PIXBUF_CACHE[mem_key] = pixbuf
return pixbuf
except Exception as e:
logger.warning(f"Failed to load cached asset: {e}")
return None
@@ -99,6 +110,9 @@ def cleanup_cache(cache_key=None):
)
if os.path.exists(cache_path):
os.unlink(cache_path)
mem_keys = [k for k in _MEMORY_PIXBUF_CACHE if k.startswith(cache_key)]
for k in mem_keys:
_MEMORY_PIXBUF_CACHE.pop(k, None)
else:
# Remove all cached assets
for filename in os.listdir(UNIFIED_NOTIFICATION_CACHE_DIR):
@@ -108,6 +122,7 @@ def cleanup_cache(cache_key=None):
os.unlink(filepath)
except Exception as e:
logger.warning(f"Failed to cleanup cache file {filename}: {e}")
_MEMORY_PIXBUF_CACHE.clear()
except Exception as e:
logger.warning(f"Failed to cleanup cache: {e}")