diff --git a/system/ui/widgets/network.py b/system/ui/widgets/network.py index 5b9d05c96e..29d9a499da 100644 --- a/system/ui/widgets/network.py +++ b/system/ui/widgets/network.py @@ -2,11 +2,11 @@ from dataclasses import dataclass from typing import Literal import pyray as rl -from openpilot.system.ui.lib.wifi_manager import NetworkInfo, WifiManagerCallbacks, WifiManagerWrapper from openpilot.system.ui.lib.application import gui_app from openpilot.system.ui.lib.button import gui_button from openpilot.system.ui.lib.label import gui_label from openpilot.system.ui.lib.scroll_panel import GuiScrollPanel +from openpilot.system.ui.lib.wifi_manager import NetworkInfo, WifiManagerCallbacks, WifiManagerWrapper, SecurityType from openpilot.system.ui.widgets.keyboard import Keyboard from openpilot.system.ui.widgets.confirm_dialog import confirm_dialog @@ -14,7 +14,14 @@ NM_DEVICE_STATE_NEED_AUTH = 60 MIN_PASSWORD_LENGTH = 8 MAX_PASSWORD_LENGTH = 64 ITEM_HEIGHT = 160 +ICON_SIZE = 49 +STRENGTH_ICONS = [ + "icons/wifi_strength_low.png", + "icons/wifi_strength_medium.png", + "icons/wifi_strength_high.png", + "icons/wifi_strength_full.png", +] @dataclass class StateIdle: @@ -109,14 +116,14 @@ class WifiManagerUI: rl.end_scissor_mode() def _draw_network_item(self, rect, network: NetworkInfo, clicked: bool): - label_rect = rl.Rectangle(rect.x, rect.y, rect.width - self.btn_width * 2, ITEM_HEIGHT) - state_rect = rl.Rectangle(rect.x + rect.width - self.btn_width * 2 - 150, rect.y, 300, ITEM_HEIGHT) + spacing = 50 + ssid_rect = rl.Rectangle(rect.x, rect.y, rect.width - self.btn_width * 2, ITEM_HEIGHT) + signal_icon_rect = rl.Rectangle(rect.x + rect.width - ICON_SIZE, rect.y + (ITEM_HEIGHT - ICON_SIZE) / 2, ICON_SIZE, ICON_SIZE) + security_icon_rect = rl.Rectangle(signal_icon_rect.x - spacing - ICON_SIZE, rect.y + (ITEM_HEIGHT - ICON_SIZE) / 2, ICON_SIZE, ICON_SIZE) - gui_label(label_rect, network.ssid, 55) + gui_label(ssid_rect, network.ssid, 55) status_text = "" - if network.is_connected: - status_text = "Connected" match self.state: case StateConnecting(network=connecting): if connecting.ssid == network.ssid: @@ -124,26 +131,49 @@ class WifiManagerUI: case StateForgetting(network=forgetting): if forgetting.ssid == network.ssid: status_text = "FORGETTING..." + if status_text: - rl.gui_label(state_rect, status_text) - - # If the network is saved, show the "Forget" button - if network.is_saved: - forget_btn_rect = rl.Rectangle( - rect.x + rect.width - self.btn_width, - rect.y + (ITEM_HEIGHT - 80) / 2, - self.btn_width, - 80, - ) - if isinstance(self.state, StateIdle) and gui_button(forget_btn_rect, "Forget") and clicked: - self.state = StateShowForgetConfirm(network) - - if isinstance(self.state, StateIdle) and rl.check_collision_point_rec(rl.get_mouse_position(), label_rect) and clicked: + status_text_rect = rl.Rectangle(security_icon_rect.x - 410, rect.y, 410, ITEM_HEIGHT) + rl.gui_label(status_text_rect, status_text) + else: + # If the network is saved, show the "Forget" button + if network.is_saved: + forget_btn_rect = rl.Rectangle(security_icon_rect.x - self.btn_width - spacing, + rect.y + (ITEM_HEIGHT - 80) / 2, + self.btn_width, + 80, + ) + if isinstance(self.state, StateIdle) and gui_button(forget_btn_rect, "Forget") and clicked: + self.state = StateShowForgetConfirm(network) + + self._draw_status_icon(security_icon_rect, network) + self._draw_signal_strength_icon(signal_icon_rect, network) + + if isinstance(self.state, StateIdle) and rl.check_collision_point_rec(rl.get_mouse_position(), ssid_rect) and clicked: if not network.is_saved: self.state = StateNeedsAuth(network) else: self.connect_to_network(network) + def _draw_status_icon(self, rect, network: NetworkInfo): + """Draw the status icon based on network's connection state""" + icon_file = "" + if network.is_connected: + icon_file = "icons/checkmark.png" + elif network.security_type == SecurityType.UNSUPPORTED: + icon_file = "icons/circled_slash.png" + else: + icon_file = "icons/lock_closed.png" + + texture = gui_app.texture(icon_file, ICON_SIZE, ICON_SIZE) + icon_rect = rl.Vector2(rect.x, rect.y + (ICON_SIZE - texture.height) / 2) + rl.draw_texture_v(texture, icon_rect, rl.WHITE) + + def _draw_signal_strength_icon(self, rect: rl.Rectangle, network: NetworkInfo): + """Draw the Wi-Fi signal strength icon based on network's signal strength""" + strength_level = max(0, min(3, round(network.strength / 33.0))) + rl.draw_texture_v(gui_app.texture(STRENGTH_ICONS[strength_level], ICON_SIZE, ICON_SIZE), rl.Vector2(rect.x, rect.y), rl.WHITE) + def connect_to_network(self, network: NetworkInfo, password=''): self.state = StateConnecting(network) if network.is_saved and not password: