refactor(controlcenter): simplify refresh handling and add cancellation hooks

The changes replace timeout‑based refreshes with animation‑aware callbacks, improving responsiveness and preventing stale pending operations.
This commit is contained in:
sankalp committed 2026-06-24 12:53:30 +05:45
1 parent 3a05e123e7
commit 2d6fd6c84b
3 files changed
+92 -41

No files matched your search

+48 -23
View File
@@ -382,7 +382,6 @@ class BluetoothConnections(Box):
on_clicked=self.toggle_other_devices,
)
self.other_devices = Box(spacing=4, orientation="vertical")
self.other_devices.set_size_request(-1, 150)
self.other_devices_scrolled = AnimatedScrollable(
min_content_size=(303, 0),
@@ -441,6 +440,7 @@ class BluetoothConnections(Box):
def on_hide(self, *_):
"""Called when the widget is hidden (popup closed)"""
self.stop_device_monitoring()
self._cancel_pending_refresh()
if self.other_devices.get_visible():
self.other_devices.set_visible(False)
self.other_devices_scrolled.snap_to_size(0)
@@ -456,25 +456,51 @@ class BluetoothConnections(Box):
def toggle_other_devices(self, *_):
"""Toggle the visibility of other devices section"""
current_state = self.other_devices.get_visible()
self.other_devices.set_visible(not current_state)
self.update_scan_label()
self._cancel_pending_refresh()
if current_state:
self.other_devices.set_visible(False)
self.other_devices_scrolled.snap_to_size(0)
self.update_scan_label()
if (
self.client
and self.client.scanning
and hasattr(self.client, "stop_scan")
):
self.client.stop_scan()
else:
self.other_devices.set_visible(True)
self.update_scan_label()
if (
self.client
and not self.client.scanning
and hasattr(self.client, "scan")
):
self.client.scan()
# Defer refresh until after the height animation completes
GLib.idle_add(self._refresh_after_animation)
if self.client:
if self.other_devices.get_visible():
if not self.client.scanning and hasattr(self.client, "scan"):
GLib.timeout_add(100, self.client.scan)
if hasattr(self, "_refresh_timeout_id") and self._refresh_timeout_id:
GLib.source_remove(self._refresh_timeout_id)
def _cancel_pending_refresh(self):
if hasattr(self, "_anim_finished_handler") and self._anim_finished_handler:
try:
self.other_devices_scrolled.height_animator.disconnect(
self._anim_finished_handler
)
except Exception:
pass
self._anim_finished_handler = None
def _do_refresh():
self.force_device_refresh()
self._refresh_timeout_id = None
return False
self._refresh_timeout_id = GLib.timeout_add(150, _do_refresh)
else:
if self.client.scanning and hasattr(self.client, "stop_scan"):
self.client.stop_scan()
def _refresh_after_animation(self):
if self._destroyed:
return False
anim = self.other_devices_scrolled.height_animator
if anim.playing:
self._anim_finished_handler = anim.connect(
"finished",
lambda *_: self.force_device_refresh() if not self._destroyed else None,
)
else:
self.force_device_refresh()
return False
def open_bluetooth_settings(self, *_):
"""Open Blueman bluetooth manager"""
@@ -650,6 +676,7 @@ class BluetoothConnections(Box):
"""Cleanup when widget is destroyed"""
self._destroyed = True
self.stop_device_monitoring()
self._cancel_pending_refresh()
for sig_id in self._client_signal_ids:
try:
self.client.disconnect(sig_id)
@@ -658,14 +685,12 @@ class BluetoothConnections(Box):
f"[Bluetooth] Failed to disconnect client signal {sig_id}: {e}"
)
self._client_signal_ids.clear()
try:
self.other_devices_revealer.child_revealed = False
except Exception as e:
logger.error(f"[Bluetooth] Failed to hide other devices revealer: {e}")
def close_bluetooth(self):
"""Called when Bluetooth panel is being closed"""
self.other_devices_revealer.child_revealed = False
if self.other_devices.get_visible():
self.other_devices.set_visible(False)
self.other_devices_scrolled.snap_to_size(0)
def setup_pull_to_refresh(self):
"""Setup pull-to-refresh gesture for the scrolled window"""
+36 -16
View File
@@ -342,7 +342,6 @@ class WifiConnections(Box):
on_clicked=self.toggle_other_networks,
)
self.other_networks = Box(spacing=4, orientation="vertical")
self.other_networks.set_size_request(-1, 150)
# Create scrolled window for other networks
self.other_networks_scrolled = AnimatedScrollable(
@@ -388,6 +387,7 @@ class WifiConnections(Box):
def on_hide(self, *_):
"""Called when the widget is hidden (popup closed)"""
self.stop_network_monitoring()
self._cancel_pending_refresh()
if self.other_networks.get_visible():
self.other_networks.set_visible(False)
self.other_networks_scrolled.snap_to_size(0)
@@ -395,20 +395,41 @@ class WifiConnections(Box):
def toggle_other_networks(self, *_):
"""Toggle the visibility of other networks section"""
current_state = self.other_networks.get_visible()
self.other_networks.set_visible(not current_state)
if self.other_networks.get_visible():
self._cancel_pending_refresh()
if current_state:
self.other_networks.set_visible(False)
self.other_networks_scrolled.snap_to_size(0)
else:
self.other_networks.set_visible(True)
if self.wifi_service:
self.wifi_service.scan()
if hasattr(self, "_refresh_timeout_id") and self._refresh_timeout_id:
GLib.source_remove(self._refresh_timeout_id)
# Defer refresh until after the height animation completes
GLib.idle_add(self._refresh_after_animation)
def _do_refresh():
self.force_network_refresh()
self._refresh_timeout_id = None
return False
def _cancel_pending_refresh(self):
if hasattr(self, "_anim_finished_handler") and self._anim_finished_handler:
try:
self.other_networks_scrolled.height_animator.disconnect(
self._anim_finished_handler
)
except Exception:
pass
self._anim_finished_handler = None
self._refresh_timeout_id = GLib.timeout_add(150, _do_refresh)
def _refresh_after_animation(self):
if self._destroyed:
return False
anim = self.other_networks_scrolled.height_animator
if anim.playing:
self._anim_finished_handler = anim.connect(
"finished",
lambda *_: (
self.force_network_refresh() if not self._destroyed else None
),
)
else:
self.force_network_refresh()
return False
def on_network_ready(self, *_):
"""Called when network service is ready"""
@@ -720,6 +741,7 @@ class WifiConnections(Box):
"""Cleanup when widget is destroyed"""
self._destroyed = True
self.stop_network_monitoring()
self._cancel_pending_refresh()
for obj, sig_id in self._signal_ids:
try:
obj.disconnect(sig_id)
@@ -728,11 +750,9 @@ class WifiConnections(Box):
self._signal_ids.clear()
self.wifi_service = None
self.network_service = None
try:
self.other_networks_revealer.child_revealed = False
except Exception as e:
logger.error(f"[WiFi] Failed to hide other networks revealer: {e}")
def close_wifi(self):
"""Called when WiFi panel is being closed"""
self.other_networks_revealer.child_revealed = False
if self.other_networks.get_visible():
self.other_networks.set_visible(False)
self.other_networks_scrolled.snap_to_size(0)
+8 -2
View File
@@ -172,6 +172,9 @@ class Launcher(Window):
self.show_all()
if not self.results:
self.results_scroll.hide()
if trigger_keyword:
# Set flag to track that launcher was opened with a trigger keyword
self.opened_with_trigger = True
@@ -764,7 +767,10 @@ class Launcher(Window):
self.results_box.show_all()
self.results_scroll.show()
if self.results:
self.results_scroll.show()
else:
self.results_scroll.hide()
def _update_input_action_text(self):
"""Update the input field with action text (Spotlight-style)."""
@@ -810,7 +816,7 @@ class Launcher(Window):
child.destroy()
else:
self.results_box.remove(child)
# Keep the results scroll visible even when empty
self.results_scroll.hide()
def _handle_escape_key(self) -> bool:
"""Handle escape key press."""