Skip to content

Commit c4ac9d1

Browse files
authored
fix(network): show live signal strength and classify auth failures (#312)
# Description - [x] Bug fix Stacked on #311, review after it merges. Last PR in the #306 split. Live Wi-Fi signal strength and auth-failure classification. - `_active_ap_signal`, `_signal_map_once`, `_read_connectivity`, `_is_wifi_ap_mode` - `_classify_settings_error`; `_validate_psk` follows NM's own psk rule (length in bytes, SAE exempt) and runs before the old profile is backed up - `_wait_for_connection` stops early when the Wi-Fi device reports FAILED (the StateChanged listener counts it, since NM leaves FAILED too fast for polling to see it) - Connection waits read the Wi-Fi interface's own IP, so an ethernet or VPN primary link can't fake success - `_async_get_network_password` prefills the saved-network password field; saved page shows the static IP/mask - `networkWindow.py` operation-result routing (success/failure/timeout handlers); the hotspot page's activate drops ethernet like the toggle does - `test_network_ui.py`, `test_worker_unit.py`, `test_worker_helpers_unit.py` coverage
1 parent ad25544 commit c4ac9d1

8 files changed

Lines changed: 1245 additions & 493 deletions

File tree

‎BlocksScreen/lib/network/manager.py‎

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ class NetworkManager(QObject):
4343
error_occurred = pyqtSignal(str, str)
4444
reconnect_complete = pyqtSignal()
4545
hotspot_config_updated = pyqtSignal(str, str, str)
46+
network_password_loaded = pyqtSignal(str, str)
4647

4748
def __init__(self, parent: QObject | None = None) -> None:
4849
"""Create the worker, wire all signals"""
@@ -72,6 +73,7 @@ def __init__(self, parent: QObject | None = None) -> None:
7273
self._worker.error_occurred.connect(self.error_occurred)
7374
self._worker.hotspot_info_ready.connect(self._on_hotspot_info_ready)
7475
self._worker.reconnect_complete.connect(self.reconnect_complete)
76+
self._worker.network_password_loaded.connect(self.network_password_loaded)
7577
self._worker.initialized.connect(self._on_worker_initialized)
7678

7779
# Keepalive timer: safety net for any missed D-Bus signals.
@@ -170,9 +172,11 @@ def _on_networks_scanned(self, networks: list) -> None:
170172

171173
@pyqtSlot(list)
172174
def _on_saved_networks_loaded(self, networks: list) -> None:
173-
"""Cache saved profiles, rebuild lowercase lookup map, and re-emit."""
175+
"""Cache saved profiles, rebuild lowercase lookup map, and re-emit if changed."""
174176
if self._shutting_down:
175177
return
178+
if networks == self._cached_saved:
179+
return
176180
self._cached_saved = networks
177181
self._saved_network_map = {n.ssid.lower(): n for n in networks}
178182
self.saved_networks_loaded.emit(networks)
@@ -249,6 +253,10 @@ def update_network( # nosec B107
249253
"""Update the password and/or autoconnect priority for a saved profile."""
250254
self._schedule(self._worker._async_update_network(ssid, password, priority))
251255

256+
def get_network_password(self, ssid: str) -> None:
257+
"""Ask NM for a saved profile's psk; answered by network_password_loaded."""
258+
self._schedule(self._worker._async_get_network_password(ssid))
259+
252260
def set_wifi_enabled(self, enabled: bool) -> None:
253261
"""Enable or disable the Wi-Fi radio."""
254262
self._schedule(self._worker._async_set_wifi_enabled(enabled))

‎BlocksScreen/lib/network/models.py‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -237,7 +237,7 @@ class SavedNetwork:
237237
signal_strength: int = 0
238238
timestamp: int = 0 # Unix time of last successful activation
239239
is_dhcp: bool = True # True = auto (DHCP), False = manual (static IP)
240-
ip_address: str = ""
240+
ip_address: str = "" # static IPv4 config, all empty while on DHCP
241241
netmask: str = ""
242242
gateway: str = ""
243243
dns_servers: tuple[str, ...] = ()

0 commit comments

Comments
 (0)