parent
c1794e6f83
commit
2017bf970f
2 changed files with 133 additions and 0 deletions
@ -0,0 +1,127 @@ |
||||
import pyray as rl |
||||
import requests |
||||
import threading |
||||
import copy |
||||
from enum import Enum |
||||
|
||||
from openpilot.common.params import Params |
||||
from openpilot.system.ui.lib.application import gui_app, DialogResult, FontWeight |
||||
from openpilot.system.ui.lib.button import gui_button, ButtonStyle |
||||
from openpilot.system.ui.lib.list_view import ( |
||||
ItemAction, |
||||
ListItem, |
||||
BUTTON_HEIGHT, |
||||
BUTTON_BORDER_RADIUS, |
||||
BUTTON_FONT_SIZE, |
||||
BUTTON_WIDTH, |
||||
) |
||||
from openpilot.system.ui.lib.text_measure import measure_text_cached |
||||
from openpilot.system.ui.widgets.confirm_dialog import alert_dialog |
||||
from openpilot.system.ui.widgets.keyboard import Keyboard |
||||
|
||||
|
||||
class SshKeyActionState(Enum): |
||||
LOADING = "LOADING" |
||||
ADD = "ADD" |
||||
REMOVE = "REMOVE" |
||||
|
||||
|
||||
class SshKeyAction(ItemAction): |
||||
HTTP_TIMEOUT = 15 # seconds |
||||
MAX_WIDTH = 500 |
||||
|
||||
def __init__(self): |
||||
super().__init__(self.MAX_WIDTH, True) |
||||
|
||||
self._keyboard = Keyboard() |
||||
self._params = Params() |
||||
self._error_message: str = "" |
||||
self._text_font = gui_app.font(FontWeight.MEDIUM) |
||||
|
||||
self._refresh_state() |
||||
|
||||
def _refresh_state(self): |
||||
self._username = self._params.get("GithubUsername", "") |
||||
self._state = SshKeyActionState.REMOVE if self._params.get("GithubSshKeys") else SshKeyActionState.ADD |
||||
|
||||
def _render(self, rect: rl.Rectangle) -> bool: |
||||
# Show error dialog if there's an error |
||||
if self._error_message: |
||||
message = copy.copy(self._error_message) |
||||
gui_app.set_modal_overlay(lambda: alert_dialog(message)) |
||||
self._username = "" |
||||
self._error_message = "" |
||||
|
||||
# Draw username if exists |
||||
if self._username: |
||||
text_size = measure_text_cached(self._text_font, self._username, BUTTON_FONT_SIZE) |
||||
rl.draw_text_ex( |
||||
self._text_font, |
||||
self._username, |
||||
(rect.x + rect.width - BUTTON_WIDTH - text_size.x - 30, rect.y + (rect.height - text_size.y) / 2), |
||||
BUTTON_FONT_SIZE, |
||||
1.0, |
||||
rl.WHITE, |
||||
) |
||||
|
||||
# Draw button |
||||
if gui_button( |
||||
rl.Rectangle( |
||||
rect.x + rect.width - BUTTON_WIDTH, rect.y + (rect.height - BUTTON_HEIGHT) / 2, BUTTON_WIDTH, BUTTON_HEIGHT |
||||
), |
||||
self._state.value, |
||||
is_enabled=self._state != SshKeyActionState.LOADING, |
||||
border_radius=BUTTON_BORDER_RADIUS, |
||||
font_size=BUTTON_FONT_SIZE, |
||||
button_style=ButtonStyle.LIST_ACTION, |
||||
): |
||||
self._handle_button_click() |
||||
return True |
||||
return False |
||||
|
||||
def _handle_button_click(self): |
||||
if self._state == SshKeyActionState.ADD: |
||||
self._keyboard.clear() |
||||
self._keyboard.set_title("Enter your GitHub username") |
||||
gui_app.set_modal_overlay(self._keyboard, callback=self._on_username_submit) |
||||
elif self._state == SshKeyActionState.REMOVE: |
||||
self._params.remove("GithubUsername") |
||||
self._params.remove("GithubSshKeys") |
||||
self._refresh_state() |
||||
|
||||
def _on_username_submit(self, result: DialogResult): |
||||
if result != DialogResult.CONFIRM: |
||||
return |
||||
|
||||
username = self._keyboard.text.strip() |
||||
if not username: |
||||
return |
||||
|
||||
self._state = SshKeyActionState.LOADING |
||||
threading.Thread(target=lambda: self._fetch_ssh_key(username), daemon=True).start() |
||||
|
||||
def _fetch_ssh_key(self, username: str): |
||||
try: |
||||
url = f"https://github.com/{username}.keys" |
||||
response = requests.get(url, timeout=self.HTTP_TIMEOUT) |
||||
response.raise_for_status() |
||||
keys = response.text.strip() |
||||
if not keys: |
||||
raise requests.exceptions.HTTPError("No SSH keys found") |
||||
|
||||
# Success - save keys |
||||
self._params.put("GithubUsername", username) |
||||
self._params.put("GithubSshKeys", keys) |
||||
self._state = SshKeyActionState.REMOVE |
||||
self._username = username |
||||
|
||||
except requests.exceptions.Timeout: |
||||
self._error_message = "Request timed out" |
||||
self._state = SshKeyActionState.ADD |
||||
except Exception: |
||||
self._error_message = f"No SSH keys found for user '{username}'" |
||||
self._state = SshKeyActionState.ADD |
||||
|
||||
|
||||
def ssh_key_item(title: str, description: str): |
||||
return ListItem(title=title, description=description, action_item=SshKeyAction()) |
Loading…
Reference in new issue