no more lock!

pull/36063/head
Shane Smiskol 2 days ago
parent 0c6974db12
commit 8c1abd96a2
  1. 25
      system/ui/lib/wifi_manager.py
  2. 75
      system/ui/widgets/network.py

@ -136,10 +136,9 @@ class WifiManager:
self._callback_queue: list[Callable] = []
# Callbacks
# TODO: implement a callback queue to avoid blocking UI thread
self._need_auth: Callable[[str], None] | None = None
self._activated: Callable[[], None] | None = None
self._forgotten: Callable[[str], None] | None = None
self._forgotten: Callable[[], None] | None = None
self._networks_updated: Callable[[list[Network]], None] | None = None
self._disconnected: Callable[[], None] | None = None
@ -155,7 +154,7 @@ class WifiManager:
def set_callbacks(self, need_auth: Callable[[str], None],
activated: Callable[[], None] | None,
forgotten: Callable[[str], None],
forgotten: Callable[[], None],
networks_updated: Callable[[list[Network]], None],
disconnected: Callable[[], None]):
self._need_auth = need_auth
@ -164,11 +163,14 @@ class WifiManager:
self._networks_updated = networks_updated
self._disconnected = disconnected
def _enqueue_callback(self, cb: Callable, *args):
self._callback_queue.append(lambda: cb(*args))
def process_callbacks(self):
for cb in self._callback_queue:
print('calling wifi cb', cb.__name__)
# Call from UI thread to run any pending callbacks
to_run, self._callback_queue = self._callback_queue, []
for cb in to_run:
cb()
self._callback_queue.clear()
def set_active(self, active: bool):
self._active = active
@ -213,19 +215,20 @@ class WifiManager:
print('hi')
if self._need_auth is not None:
print('wifi need auth', self._connecting_to_ssid)
self._callback_queue.append(lambda ssid=self._connecting_to_ssid: self._need_auth(ssid))
# self._callback_queue.append(lambda cb=self._need_auth, ssid=self._connecting_to_ssid: cb(ssid))
self._enqueue_callback(self._need_auth, self._connecting_to_ssid)
self._connecting_to_ssid = ""
elif new_state == NMDeviceState.ACTIVATED:
if self._activated is not None:
self._update_networks()
self._callback_queue.append(self._activated)
self._enqueue_callback(self._activated)
self._connecting_to_ssid = ""
elif new_state == NMDeviceState.DISCONNECTED and change_reason != NM_DEVICE_STATE_REASON_NEW_ACTIVATION:
self._connecting_to_ssid = ""
if self._disconnected is not None:
self._callback_queue.append(self._disconnected)
self._enqueue_callback(self._disconnected)
def _network_scanner(self):
self._wait_for_wifi_device()
@ -333,7 +336,7 @@ class WifiManager:
if self._forgotten is not None:
self._update_networks()
self._callback_queue.append(lambda: self._forgotten(ssid))
self._enqueue_callback(self._forgotten)
if block:
worker()
@ -409,7 +412,7 @@ class WifiManager:
self._networks = networks
if self._networks_updated is not None:
self._callback_queue.append(lambda: self._networks_updated(self._networks))
self._enqueue_callback(self._networks_updated, self._networks)
def __del__(self):
self.stop()

@ -1,6 +1,5 @@
from enum import IntEnum
from functools import partial
from threading import Lock
from typing import cast
import pyray as rl
@ -50,7 +49,6 @@ class WifiManagerUI(Widget):
self._networks: list[Network] = []
self._networks_buttons: dict[str, Button] = {}
self._forget_networks_buttons: dict[str, Button] = {}
self._lock = Lock()
self._confirm_dialog = ConfirmDialog("", "Forget", "Cancel")
self.wifi_manager.set_callbacks(need_auth=self._on_need_auth,
@ -73,21 +71,20 @@ class WifiManagerUI(Widget):
def _render(self, rect: rl.Rectangle):
self.wifi_manager.process_callbacks()
with self._lock:
if not self._networks:
gui_label(rect, "Scanning Wi-Fi networks...", 72, alignment=rl.GuiTextAlignment.TEXT_ALIGN_CENTER)
return
if self.state == UIState.NEEDS_AUTH and self._state_network:
self.keyboard.set_title("Wrong password" if self._password_retry else "Enter password", f"for {self._state_network.ssid}")
self.keyboard.reset()
gui_app.set_modal_overlay(self.keyboard, lambda result: self._on_password_entered(cast(Network, self._state_network), result))
elif self.state == UIState.SHOW_FORGET_CONFIRM and self._state_network:
self._confirm_dialog.set_text(f'Forget Wi-Fi Network "{self._state_network.ssid}"?')
self._confirm_dialog.reset()
gui_app.set_modal_overlay(self._confirm_dialog, callback=lambda result: self.on_forgot_confirm_finished(self._state_network, result))
else:
self._draw_network_list(rect)
if not self._networks:
gui_label(rect, "Scanning Wi-Fi networks...", 72, alignment=rl.GuiTextAlignment.TEXT_ALIGN_CENTER)
return
if self.state == UIState.NEEDS_AUTH and self._state_network:
self.keyboard.set_title("Wrong password" if self._password_retry else "Enter password", f"for {self._state_network.ssid}")
self.keyboard.reset()
gui_app.set_modal_overlay(self.keyboard, lambda result: self._on_password_entered(cast(Network, self._state_network), result))
elif self.state == UIState.SHOW_FORGET_CONFIRM and self._state_network:
self._confirm_dialog.set_text(f'Forget Wi-Fi Network "{self._state_network.ssid}"?')
self._confirm_dialog.reset()
gui_app.set_modal_overlay(self._confirm_dialog, callback=lambda result: self.on_forgot_confirm_finished(self._state_network, result))
else:
self._draw_network_list(rect)
def _on_password_entered(self, network: Network, result: int):
if result == 1:
@ -213,37 +210,35 @@ class WifiManagerUI(Widget):
self.wifi_manager.forget_connection(network.ssid)
def _on_network_updated(self, networks: list[Network]):
with self._lock:
self._networks = networks
for n in self._networks:
self._networks_buttons[n.ssid] = Button(n.ssid, partial(self._networks_buttons_callback, n), font_size=55, text_alignment=TextAlignment.LEFT,
button_style=ButtonStyle.NO_EFFECT)
self._forget_networks_buttons[n.ssid] = Button("Forget", partial(self._forget_networks_buttons_callback, n), button_style=ButtonStyle.FORGET_WIFI,
font_size=45)
print('networks updated', [n.ssid for n in networks])
self._networks = networks
for n in self._networks:
self._networks_buttons[n.ssid] = Button(n.ssid, partial(self._networks_buttons_callback, n), font_size=55, text_alignment=TextAlignment.LEFT,
button_style=ButtonStyle.NO_EFFECT)
self._forget_networks_buttons[n.ssid] = Button("Forget", partial(self._forget_networks_buttons_callback, n), button_style=ButtonStyle.FORGET_WIFI,
font_size=45)
def _on_need_auth(self, ssid):
print('need auth for', ssid)
with self._lock:
network = next((n for n in self._networks if n.ssid == ssid), None)
if network:
self.state = UIState.NEEDS_AUTH
self._state_network = network
self._password_retry = True
network = next((n for n in self._networks if n.ssid == ssid), None)
if network:
self.state = UIState.NEEDS_AUTH
self._state_network = network
self._password_retry = True
def _on_activated(self):
with self._lock:
if self.state == UIState.CONNECTING:
self.state = UIState.IDLE
print('_on_activated')
if self.state == UIState.CONNECTING:
self.state = UIState.IDLE
def _on_forgotten(self, ssid):
with self._lock:
if self.state == UIState.FORGETTING:
self.state = UIState.IDLE
def _on_forgotten(self):
print('_on_forgotten')
if self.state == UIState.FORGETTING:
self.state = UIState.IDLE
def _on_disconnected(self):
with self._lock:
if self.state == UIState.CONNECTING:
self.state = UIState.IDLE
if self.state == UIState.CONNECTING:
self.state = UIState.IDLE
def main():

Loading…
Cancel
Save