ui: add confirmation circle button (#37586)

* try this

* clean up and use it

* clean up

* simpler

* do this later

* do onboarding & reset

* do setup

* temp

* Revert "temp"

This reverts commit 22fbbf5c813b4915e784b9ee235ed3bde2229048.

* simpler again

* missing size

* fix

* Revert "fix"

This reverts commit 53c4e29e614181029dc8e9a2baea7694957dc8fb.

* nl
This commit is contained in:
Shane Smiskol
2026-03-06 22:38:00 -08:00
committed by GitHub
parent 793f8fee32
commit 0557283e3d
4 changed files with 37 additions and 61 deletions
+12 -30
View File
@@ -14,8 +14,7 @@ from openpilot.system.ui.widgets.label import gui_label
from openpilot.system.ui.lib.multilang import tr
from openpilot.system.version import terms_version, training_version
from openpilot.selfdrive.ui.ui_state import ui_state, device
from openpilot.selfdrive.ui.mici.widgets.button import BigCircleButton
from openpilot.selfdrive.ui.mici.widgets.dialog import BigConfirmationDialog
from openpilot.selfdrive.ui.mici.widgets.dialog import BigConfirmationCircleButton
from openpilot.selfdrive.ui.mici.onroad.driver_state import DriverStateRenderer
from openpilot.selfdrive.ui.mici.onroad.driver_camera_dialog import BaseDriverCameraDialog
@@ -215,25 +214,18 @@ class TrainingGuideRecordFront(NavScroller):
def __init__(self, continue_callback: Callable[[], None]):
super().__init__()
def show_accept_dialog():
def on_accept():
ui_state.params.put_bool_nonblocking("RecordFront", True)
continue_callback()
def on_accept():
ui_state.params.put_bool_nonblocking("RecordFront", True)
continue_callback()
gui_app.push_widget(BigConfirmationDialog("allow data uploading", "icons_mici/setup/driver_monitoring/dm_check.png", on_accept, exit_on_confirm=False))
def on_decline():
ui_state.params.put_bool_nonblocking("RecordFront", False)
continue_callback()
def show_decline_dialog():
def on_decline():
ui_state.params.put_bool_nonblocking("RecordFront", False)
continue_callback()
self._accept_button = BigConfirmationCircleButton("allow data uploading", "icons_mici/setup/driver_monitoring/dm_check.png",
on_accept, exit_on_confirm=False)
gui_app.push_widget(BigConfirmationDialog("no, don't upload", "icons_mici/setup/cancel.png", on_decline, exit_on_confirm=False))
self._accept_button = BigCircleButton("icons_mici/setup/driver_monitoring/dm_check.png")
self._accept_button.set_click_callback(show_accept_dialog)
self._decline_button = BigCircleButton("icons_mici/setup/cancel.png")
self._decline_button.set_click_callback(show_decline_dialog)
self._decline_button = BigConfirmationCircleButton("no, don't upload", "icons_mici/setup/cancel.png", on_decline, exit_on_confirm=False)
self._scroller.add_widgets([
GreyBigButton("driver camera data", "do you want to share video data for training?",
@@ -322,18 +314,8 @@ class TermsPage(Scroller):
def __init__(self, on_accept, on_decline):
super().__init__()
def show_accept_dialog():
gui_app.push_widget(BigConfirmationDialog("accept\nterms", "icons_mici/setup/driver_monitoring/dm_check.png", on_accept))
def show_decline_dialog():
gui_app.push_widget(BigConfirmationDialog("decline &\nuninstall", "icons_mici/setup/cancel.png", on_decline,
red=True, exit_on_confirm=False))
self._accept_button = BigCircleButton("icons_mici/setup/driver_monitoring/dm_check.png")
self._accept_button.set_click_callback(show_accept_dialog)
self._decline_button = BigCircleButton("icons_mici/setup/cancel.png", red=True)
self._decline_button.set_click_callback(show_decline_dialog)
self._accept_button = BigConfirmationCircleButton("accept\nterms", "icons_mici/setup/driver_monitoring/dm_check.png", on_accept)
self._decline_button = BigConfirmationCircleButton("decline &\nuninstall", "icons_mici/setup/cancel.png", on_decline, red=True, exit_on_confirm=False)
self._terms_header = GreyBigButton("terms and\nconditions", "scroll to continue",
gui_app.texture("icons_mici/setup/green_info.png", 64, 64))
+13 -1
View File
@@ -11,7 +11,7 @@ from openpilot.system.ui.lib.wrap_text import wrap_text
from openpilot.system.ui.lib.application import gui_app, FontWeight, MousePos
from openpilot.system.ui.widgets.slider import RedBigSlider, BigSlider
from openpilot.common.filter_simple import FirstOrderFilter
from openpilot.selfdrive.ui.mici.widgets.button import BigButton
from openpilot.selfdrive.ui.mici.widgets.button import BigCircleButton, BigButton
DEBUG = False
@@ -253,3 +253,15 @@ class BigDialogButton(BigButton):
dlg = BigDialog(self.text, self._description)
gui_app.push_widget(dlg)
class BigConfirmationCircleButton(BigCircleButton):
def __init__(self, title: str, icon: str, confirm_callback: Callable[[], None], exit_on_confirm: bool = True,
red: bool = False, icon_size: tuple[int, int] = (64, 53), icon_offset: tuple[int, int] = (0, 0)):
super().__init__(icon, red, icon_size, icon_offset)
def show_confirm_dialog():
gui_app.push_widget(BigConfirmationDialog(title, icon, confirm_callback,
exit_on_confirm=exit_on_confirm, red=red))
self.set_click_callback(show_confirm_dialog)
+8 -20
View File
@@ -11,8 +11,7 @@ from openpilot.system.ui.lib.application import gui_app
from openpilot.system.ui.widgets.scroller import Scroller
from openpilot.system.ui.widgets.nav_widget import NavWidget
from openpilot.system.ui.mici_setup import GreyBigButton, FailedPage
from openpilot.selfdrive.ui.mici.widgets.dialog import BigConfirmationDialog
from openpilot.selfdrive.ui.mici.widgets.button import BigCircleButton
from openpilot.selfdrive.ui.mici.widgets.dialog import BigConfirmationCircleButton
USERDATA = "/dev/disk/by-partlabel/userdata"
TIMEOUT = 3*60
@@ -70,37 +69,26 @@ class Reset(Scroller):
self._resetting_page = ResettingPage()
self._reset_failed_page = ResetFailedPage()
def show_confirm_dialog():
dialog = BigConfirmationDialog("erase\ndevice", "icons_mici/settings/device/uninstall.png", self.start_reset, red=True)
gui_app.push_widget(dialog)
self._reset_button = BigConfirmationCircleButton("erase\ndevice", "icons_mici/settings/device/uninstall.png", self.start_reset, red=True)
self._cancel_button = BigConfirmationCircleButton("normal\nstartup", "icons_mici/settings/device/reboot.png", gui_app.request_close, exit_on_confirm=False)
self._reboot_button = BigConfirmationCircleButton("reboot\ndevice", "icons_mici/settings/device/reboot.png", HARDWARE.reboot, exit_on_confirm=False)
def show_cancel_dialog():
dialog = BigConfirmationDialog("normal\nstartup", "icons_mici/settings/device/reboot.png", gui_app.request_close, exit_on_confirm=False)
gui_app.push_widget(dialog)
def show_reboot_dialog():
dialog = BigConfirmationDialog("reboot\ndevice", "icons_mici/settings/device/reboot.png", HARDWARE.reboot, exit_on_confirm=False)
gui_app.push_widget(dialog)
self._reset_button = BigCircleButton("icons_mici/settings/device/uninstall.png", red=True)
self._reset_button.set_click_callback(show_confirm_dialog)
self._cancel_button = BigCircleButton("icons_mici/settings/device/reboot.png")
self._cancel_button.set_click_callback(show_cancel_dialog)
# show reboot button if in recover mode
self._cancel_button.set_visible(mode != ResetMode.RECOVER)
self._reboot_button.set_visible(mode == ResetMode.RECOVER)
main_card = GreyBigButton("factory reset", "all content and\nsettings will be erased",
gui_app.texture("icons_mici/setup/factory_reset.png", 64, 64))
# cancel button becomes reboot button
if mode == ResetMode.RECOVER:
main_card.set_text("unable to mount\ndata partition")
main_card.set_value("it may be corrupted")
self._cancel_button.set_click_callback(show_reboot_dialog)
self._scroller.add_widgets([
main_card,
self._reset_button,
self._cancel_button,
self._reboot_button,
])
def _do_erase(self):
+4 -10
View File
@@ -28,8 +28,8 @@ from openpilot.system.ui.widgets.scroller import Scroller, NavScroller, ITEM_SPA
from openpilot.system.ui.widgets.slider import LargerSlider
from openpilot.selfdrive.ui.mici.layouts.settings.network import WifiNetworkButton
from openpilot.selfdrive.ui.mici.layouts.settings.network.wifi_ui import WifiUIMici
from openpilot.selfdrive.ui.mici.widgets.dialog import BigInputDialog, BigConfirmationDialog
from openpilot.selfdrive.ui.mici.widgets.button import BigCircleButton, BigButton
from openpilot.selfdrive.ui.mici.widgets.dialog import BigInputDialog, BigConfirmationCircleButton
from openpilot.selfdrive.ui.mici.widgets.button import BigButton
NetworkType = log.DeviceState.NetworkType
@@ -247,13 +247,6 @@ class FailedPage(NavScroller):
super().__init__()
self.set_back_callback(retry_callback)
def show_reboot_dialog():
dialog = BigConfirmationDialog("slide to reboot", "icons_mici/settings/device/reboot.png", HARDWARE.reboot, exit_on_confirm=False)
gui_app.push_widget(dialog)
reboot_button = BigCircleButton("icons_mici/settings/device/reboot.png", red=False, icon_size=(64, 70))
reboot_button.set_click_callback(show_reboot_dialog)
self._reason_card = GreyBigButton("", "")
self._reason_card.set_visible(False)
@@ -261,7 +254,8 @@ class FailedPage(NavScroller):
GreyBigButton(title, description or "swipe down to go\nback and try again",
gui_app.texture(icon, 64, 58)),
self._reason_card,
reboot_button,
BigConfirmationCircleButton("slide to reboot", "icons_mici/settings/device/reboot.png",
HARDWARE.reboot, exit_on_confirm=False, icon_size=(64, 70)),
])
def set_reason(self, reason: str):