♻️ refactor(notification): improve notification animation and limit count
This commit is contained in:
5 files changed
+61
-14
No files matched your search
@@ -0,0 +1,30 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
id="svg8"
|
||||
version="1.1"
|
||||
width="24"
|
||||
height="24">
|
||||
<metadata
|
||||
id="metadata14">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<defs
|
||||
id="defs12" />
|
||||
<path
|
||||
id="path4"
|
||||
d="M 6.3515625 4.7363281 L 5.4121094 5.6777344 L 18.955078 19.220703 L 19.894531 18.279297 L 18.488281 16.873047 A 1 1 0 0 0 18.828125 16.560547 L 21.765625 12.642578 A 1 1 0 0 0 21.794922 12.605469 A 1 1 0 0 0 22 11.998047 A 1 1 0 0 0 21.746094 11.335938 L 18.851562 7.4746094 A 1 1 0 0 0 17.998047 7 A 1 1 0 0 0 17 8.0019531 A 1 1 0 0 0 17.199219 8.5976562 L 17.195312 8.5996094 L 19.746094 12.001953 L 17.195312 15.404297 L 17.197266 15.40625 A 1 1 0 0 0 17.128906 15.513672 L 14.447266 12.832031 A 1 1 0 0 0 15 13 A 1 1 0 0 0 15 11 A 1 1 0 0 0 14.169922 12.554688 L 6.3515625 4.7363281 z M 5.5234375 7.1191406 A 1 1 0 0 0 5.1484375 7.4746094 L 2.2539062 11.335938 A 1 1 0 0 0 2 11.998047 A 1 1 0 0 0 2.2050781 12.605469 A 1 1 0 0 0 2.234375 12.642578 L 5.171875 16.560547 A 1 1 0 0 0 5.9980469 17 A 1 1 0 0 0 7 16.001953 A 1 1 0 0 0 6.8027344 15.40625 L 6.8046875 15.404297 L 4.2539062 12.001953 L 6.8046875 8.5996094 L 6.8007812 8.5976562 A 1 1 0 0 0 6.8789062 8.4746094 L 5.5234375 7.1191406 z M 9 11 A 1 1 0 0 0 9 13 A 1 1 0 0 0 9.7773438 11.373047 L 9.6269531 11.222656 A 1 1 0 0 0 9 11 z "
|
||||
style="opacity:0.5;vector-effect:none;fill:#f2f2f2;fill-opacity:1;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;font-variant-east_asian:normal;marker:none" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.0 KiB |
@@ -0,0 +1,4 @@
|
||||
<svg width="24" height="24" version="1.1" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="m6.002 7c-0.34766-9.221e-4 -0.67086 0.17879-0.85352 0.47461l-2.8945 3.8613c-0.16267 0.18228-0.25299 0.4178-0.25391 0.66211-1.558e-4 0.21949 0.071909 0.43294 0.20508 0.60742 0.00947 0.0126 0.01924 0.02497 0.029297 0.03711l2.9375 3.918c0.18564 0.27425 0.495 0.43881 0.82617 0.43945 0.55229 0.0011 1.0009-0.44576 1.002-0.99805-1.36e-4 -0.21459-0.069298-0.42344-0.19727-0.5957l0.00195-2e-3 -2.5508-3.4023 2.5508-3.4023-0.00391-0.00195c0.12866-0.172 0.19851-0.38086 0.19923-0.59566 0.00108-0.55229-0.44576-1.0009-0.99805-1.002zm11.996 0c-0.55228 0.00108-0.99913 0.44967-0.99805 1.002 7.01e-4 0.21481 0.07055 0.42369 0.19922 0.5957l-0.0039 0.00195 2.5508 3.4023-2.5508 3.4023 2e-3 2e-3c-0.12798 0.17224-0.19716 0.38108-0.19732 0.59566 0.0011 0.55229 0.44967 0.99913 1.002 0.99805 0.33117-6.47e-4 0.64054-0.1652 0.82617-0.43945l2.9375-3.918c0.01006-0.01214 0.01983-0.02451 0.0293-0.03711 0.13317-0.17448 0.20523-0.38793 0.20508-0.60742-9.14e-4 -0.24431-0.09123-0.47983-0.25391-0.66211l-2.8945-3.8613c-0.18266-0.29582-0.50585-0.47553-0.85352-0.47461z" fill="#f2f2f2"/>
|
||||
<path d="m9 11c-1.3333 0-1.3333 2 0 2s1.3333-2 0-2zm3 0c-1.3333 0-1.3333 2 0 2s1.3333-2 0-2zm3 0c-1.3333 0-1.3333 2 0 2s1.3333-2 0-2z" fill="#f2f2f2"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.3 KiB |
+13
-3
@@ -28,7 +28,7 @@ NOTIFICATION_IMAGE_SIZE = 48
|
||||
|
||||
|
||||
# Improved animation smoothness and consistent behavior for rapid notifications.
|
||||
def smooth_revealer_animation(revealer: SlideRevealer, duration: int = 250):
|
||||
def smooth_revealer_animation(revealer: SlideRevealer, duration: int = 600):
|
||||
revealer.duration = duration
|
||||
|
||||
|
||||
@@ -207,7 +207,7 @@ class NotificationRevealer(SlideRevealer):
|
||||
super().__init__(
|
||||
child=self.event_box,
|
||||
direction="right",
|
||||
duration=250,
|
||||
duration=600,
|
||||
)
|
||||
|
||||
smooth_revealer_animation(self)
|
||||
@@ -283,6 +283,7 @@ class ModusNoti(Window):
|
||||
self.notifications = Box(
|
||||
v_expand=True,
|
||||
h_expand=True,
|
||||
title="Notification Center",
|
||||
style="margin: 1px 0px 1px 1px;",
|
||||
orientation="v",
|
||||
spacing=5,
|
||||
@@ -317,8 +318,17 @@ class ModusNoti(Window):
|
||||
current_children.insert(0, new_box)
|
||||
self.notifications.children = current_children
|
||||
|
||||
|
||||
# This ensures each notification's container is fully laid out before animation
|
||||
|
||||
if len(current_children) >= 4:
|
||||
# Animate close for the oldest notification if we exceed the limit
|
||||
oldest_notification = current_children[-1]
|
||||
if hasattr(oldest_notification, 'notification'):
|
||||
# Trigger the close animation by closing the underlying notification
|
||||
# This will use the same slide animation as auto-dismiss (left-to-right)
|
||||
oldest_notification.notification.close("expired")
|
||||
current_children.pop()
|
||||
|
||||
def start_animation():
|
||||
if new_box.get_parent(): # Only animate if still in the tree
|
||||
new_box.reveal()
|
||||
|
||||
@@ -15,7 +15,7 @@ class BluetoothIndicator(Box):
|
||||
self.bluetooth = BluetoothClient()
|
||||
self.bt_icon = Svg(
|
||||
name="bt-icon",
|
||||
size=20,
|
||||
size=25,
|
||||
svg_file=get_relative_path(
|
||||
"../../../config/assets/icons/applets/bluetooth-clear.svg"
|
||||
),
|
||||
@@ -211,15 +211,15 @@ class NetworkIndicator(Box):
|
||||
elif primary_device == "wired" and self.network_service.ethernet_device:
|
||||
ethernet = self.network_service.ethernet_device
|
||||
if ethernet.internet == "activated":
|
||||
icon_file = "ethernet.svg"
|
||||
icon_file = "network-wired.svg"
|
||||
tooltip = "Ethernet connected"
|
||||
if hasattr(ethernet, "speed") and ethernet.speed > 0:
|
||||
tooltip += f" ({ethernet.speed} Mbps)"
|
||||
elif ethernet.internet == "activating":
|
||||
icon_file = "wifi-clear.svg"
|
||||
icon_file = "network-wired.svg"
|
||||
tooltip = "Ethernet connecting..."
|
||||
else:
|
||||
icon_file = "wifi-off-clear.svg"
|
||||
icon_file = "network-wired-offline.svg"
|
||||
tooltip = "Ethernet disconnected"
|
||||
|
||||
self.network_icon.set_from_file(
|
||||
|
||||
@@ -63,13 +63,15 @@ class AnimationManager:
|
||||
"""Calculate optimal frame interval based on widget count"""
|
||||
widget_count = len(self._animating_widgets)
|
||||
if widget_count <= 1:
|
||||
return 22 # 45 FPS for single widget
|
||||
elif widget_count <= 3:
|
||||
return 33 # 30 FPS for 2-3 widgets
|
||||
return 16 # 60 FPS
|
||||
elif widget_count <= 2:
|
||||
return 16 # 60 FPS
|
||||
elif widget_count <= 4:
|
||||
return 22 # 45 FPS
|
||||
elif widget_count <= 6:
|
||||
return 50 # 20 FPS for 4-6 widgets
|
||||
return 33 # 30 FPS
|
||||
else:
|
||||
return 67 # 15 FPS for 7+ widgets
|
||||
return 50 # 20 FPS
|
||||
|
||||
def _start_timer(self):
|
||||
interval = self._get_optimal_interval()
|
||||
@@ -166,9 +168,10 @@ class SlideRevealer(Gtk.Overlay):
|
||||
t = min(elapsed / self.duration, 1.0)
|
||||
|
||||
if self._show_animation:
|
||||
eased = 1 - (1 - t) ** 3 # Inline ease_out_cubic
|
||||
# Ease out quadratic (no bounce/overshoot)
|
||||
eased = 1 - (1 - t) ** 2
|
||||
else:
|
||||
eased = t**3 # Ease in cubic for hide animation
|
||||
eased = t**2 # Ease in quadratic for hide animation
|
||||
|
||||
self._pending_position = self._get_position_at_progress_cached(eased)
|
||||
|
||||
|
||||
Reference in new issue
Block a user