fix(astal-menu): refresh Bluetooth list on device connection changes

The device rows already render a "Disconnect" button when a device is connected,
but the list only rebuilt on adapter-level notify::devices / notify::is-powered —
not on per-device state changes. So a device connected (via the menu or elsewhere)
while the menu was open kept its "Connect" button and offered no way to disconnect.
Hook each device's notify::connected/connecting/paired (once each) to refresh the
list, so a connected device flips to "Disconnect".

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XUWCXM4KhjRkwheaA3X7bP
feat/astal-menu
Amir Alexander Abdelbaki 2026-07-06 00:17:35 +02:00
parent 5cd880c388
commit e79d427c2a
1 changed files with 13 additions and 0 deletions

View File

@ -44,6 +44,7 @@ class _BluetoothView(Gtk.Box):
self.full = full
self.bt = ctx.services.bluetooth
self._recorded: set[str] = set()
self._hooked: set[str] = set() # devices whose state signals we've wired
self.append(self._build_header())
@ -121,11 +122,23 @@ class _BluetoothView(Gtk.Box):
if not self.full:
devices = [d for d in devices if d.get_connected() or d.get_paired()][:4]
for dev in devices:
self._hook_device(dev)
self._list.append(self._device_row(dev))
if self.full and self.ctx.feature("history", True):
self._list.append(self._history_section())
def _hook_device(self, dev) -> None:
# Rebuild the list when a device's connection state changes, so a freshly
# connected device flips its button to "Disconnect" (adapter-level
# notify::devices doesn't fire for per-device state changes). Hook once each.
key = dev.get_address() or ""
if key in self._hooked:
return
self._hooked.add(key)
for sig in ("notify::connected", "notify::connecting", "notify::paired"):
dev.connect(sig, lambda *_a: self._refresh())
def _device_row(self, dev) -> Gtk.Widget:
row = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=10)
row.add_css_class("bt-row")