♻️ refactor(osd, switcher): use Animator for smooth value transitions in OSD scale and switcher window animation

This commit is contained in:
sankalp committed 2025-06-22 18:52:39 +05:45
1 parent 8b4d829681
commit 9c81dd69a4
5 files changed
+37 -65

No files matched your search

+31 -29
View File
@@ -9,16 +9,16 @@ from fabric.notifications import (
from fabric.widgets.box import Box
from fabric.widgets.button import Button
from fabric.widgets.centerbox import CenterBox
from fabric.widgets.circularprogressbar import CircularProgressBar
from fabric.widgets.image import Image
from fabric.widgets.label import Label
from fabric.widgets.revealer import Revealer
from fabric.widgets.circularprogressbar import CircularProgressBar
from gi.repository import Gdk, GdkPixbuf, GLib
from loguru import logger
from services import notification_service
from utils.animator import Animator
from utils.custom_image import CustomImage
from utils.wayland import WaylandWindow as Window
from utils.animator import Animator
class ActionButton(Button):
@@ -80,7 +80,6 @@ class NotificationWidget(Box):
self.timeout_ms = timeout_ms
self._timeout_id = None
self.close_button_animator = Animator(
bezier_curve=(0.25, 0.1, 0.25, 1.0),
duration=0.3,
@@ -88,7 +87,9 @@ class NotificationWidget(Box):
max_value=1.0,
repeat=False,
)
self.close_button_animator.connect("notify::value", self.on_hover_animation_value_changed)
self.close_button_animator.connect(
"notify::value", self.on_hover_animation_value_changed
)
self.timeout_progress_animator = Animator(
bezier_curve=(1.0, 0.0, 1.0, 1.0),
@@ -97,7 +98,9 @@ class NotificationWidget(Box):
max_value=1.0,
repeat=False,
)
self.timeout_progress_animator.connect("notify::value", self.on_timeout_progress_changed)
self.timeout_progress_animator.connect(
"notify::value", self.on_timeout_progress_changed
)
self.timeout_progress_animator.connect("finished", self.on_timeout_finished)
self.start_timeout()
@@ -223,10 +226,7 @@ class NotificationWidget(Box):
)
def create_close_button(self):
close_icon = Label(
name="notif-close-label",
markup=icons.cancel
)
close_icon = Label(name="notif-close-label", markup=icons.cancel)
self.close_progress_bar = CircularProgressBar(
name="notif-close-progress",
@@ -270,17 +270,14 @@ class NotificationWidget(Box):
# Only show chevron button if there's something to expand
# (either long text that gets ellipsized or action buttons)
has_expandable_content = (
(self.notification.body and len(self.notification.body) > 50) or # Long text
bool(self.notification.actions) # Has action buttons
(self.notification.body and len(self.notification.body) > 50) # Long text
or bool(self.notification.actions) # Has action buttons
)
if not has_expandable_content:
return Box() # Return empty box if nothing to expand
self.chevron_icon = Label(
name="notif-chevron-label",
markup=icons.chevron_down
)
self.chevron_icon = Label(name="notif-chevron-label", markup=icons.chevron_down)
chevron_button = Button(
name="notif-chevron-button",
@@ -302,9 +299,7 @@ class NotificationWidget(Box):
name="notification-expanded-content",
orientation="v",
spacing=8,
children=[
self.create_action_buttons(notification)
],
children=[self.create_action_buttons(notification)],
)
else:
return Box()
@@ -320,10 +315,11 @@ class NotificationWidget(Box):
self.chevron_icon.set_markup(icons.chevron_down)
# Toggle body label properties
if hasattr(self, 'body_label') and self.body_label:
if hasattr(self, "body_label") and self.body_label:
if self.is_expanded:
# Show full text without ellipsization and enable wrapping
self.body_label.set_markup(self.notification.body) # Keep original newlines
# Keep original newlines
self.body_label.set_markup(self.notification.body)
self.body_label.set_property("ellipsize", 0)
self.body_label.set_property("wrap", True)
self.body_label.set_property("wrap-mode", 2)
@@ -339,7 +335,7 @@ class NotificationWidget(Box):
pass
def on_timeout_progress_changed(self, animator, value):
if hasattr(self, 'close_progress_bar'):
if hasattr(self, "close_progress_bar"):
# Update progress bar value based on timeout progress (convert to float to avoid type issues)
self.close_progress_bar.value = float(animator.value)
@@ -349,7 +345,7 @@ class NotificationWidget(Box):
def start_timeout(self):
self.stop_timeout()
if hasattr(self, 'timeout_progress_animator'):
if hasattr(self, "timeout_progress_animator"):
self.timeout_progress_animator.play()
self._timeout_id = GLib.timeout_add(self.timeout_ms, self.close_notification)
@@ -357,7 +353,7 @@ class NotificationWidget(Box):
if self._timeout_id is not None:
GLib.source_remove(self._timeout_id)
self._timeout_id = None
if hasattr(self, 'timeout_progress_animator'):
if hasattr(self, "timeout_progress_animator"):
self.timeout_progress_animator.stop()
def close_notification(self):
@@ -373,9 +369,9 @@ class NotificationWidget(Box):
def destroy(self):
self.stop_timeout()
if hasattr(self, 'close_button_animator'):
if hasattr(self, "close_button_animator"):
self.close_button_animator.stop()
if hasattr(self, 'timeout_progress_animator'):
if hasattr(self, "timeout_progress_animator"):
self.timeout_progress_animator.stop()
super().destroy()
@@ -391,7 +387,7 @@ class NotificationWidget(Box):
self.set_pointer_cursor(button, "hand2")
# On hover, show full progress (indicating ready to close)
if hasattr(self, 'close_progress_bar'):
if hasattr(self, "close_progress_bar"):
self.close_progress_bar.value = 1.0
def unhover_button(self, button):
@@ -399,7 +395,9 @@ class NotificationWidget(Box):
self.set_pointer_cursor(button, "arrow")
# On unhover, resume showing timeout progress
if hasattr(self, 'timeout_progress_animator') and hasattr(self, 'close_progress_bar'):
if hasattr(self, "timeout_progress_animator") and hasattr(
self, "close_progress_bar"
):
# Resume the timeout progress display
current_progress = float(self.timeout_progress_animator.value)
self.close_progress_bar.value = current_progress
@@ -432,7 +430,11 @@ class NotificationRevealer(Revealer):
):
# Cache the notification to history when it's actually closed/dismissed
self.cache_service.cache_notification(notification)
logger.info(f"[Notification] Cached notification from {notification.app_name} (reason: {reason})")
logger.info(
f"[Notification] Cached notification from {notification.app_name} (reason: {
reason
})"
)
self.set_reveal_child(False)
@@ -465,7 +467,7 @@ class NotificationPopup(Window):
if not self.cache_notification_service.dont_disturb:
new_box = NotificationRevealer(
fabric_notif.get_notification_from_id(id),
self.cache_notification_service
self.cache_notification_service,
)
self.notifications.add(new_box)
new_box.set_reveal_child(True)