88from openpilot .system .ui .widgets import Widget , DialogResult
99from openpilot .system .ui .widgets .confirm_dialog import ConfirmDialog
1010from openpilot .system .ui .widgets .list_view import button_item , text_item , ListItem
11+ from openpilot .system .ui .widgets .option_dialog import MultiOptionDialog
1112from openpilot .system .ui .widgets .scroller import Scroller
1213
1314# TODO: remove this. updater fails to respond on startup if time is not correct
@@ -52,6 +53,9 @@ def __init__(self):
5253 self ._install_btn = button_item (tr ("Install Update" ), tr ("INSTALL" ), callback = self ._on_install_update )
5354 self ._install_btn .set_visible (False )
5455
56+ self ._select_branch_dialog : MultiOptionDialog | None = None
57+ self ._target_branch_btn = button_item (tr ("Target Branch" ), tr ("SELECT" ), callback = self ._on_select_branch )
58+
5559 # Track waiting-for-updater transition to avoid brief re-enable while still idle
5660 self ._waiting_for_updater = False
5761 self ._waiting_start_ts : float = 0.0
@@ -65,8 +69,7 @@ def _init_items(self):
6569 self ._version_item ,
6670 self ._download_btn ,
6771 self ._install_btn ,
68- # TODO: implement branch switching
69- # button_item("Target Branch", "SELECT", callback=self._on_select_branch),
72+ self ._target_branch_btn ,
7073 button_item ("Uninstall" , tr ("UNINSTALL" ), callback = self ._on_uninstall ),
7174 ]
7275 return items
@@ -87,6 +90,8 @@ def _update_state(self):
8790 self ._version_item .action_item .set_text (current_desc )
8891 self ._version_item .set_description (current_release_notes )
8992
93+ self ._target_branch_btn .action_item .set_value (ui_state .params .get ("UpdaterTargetBranch" ) or "" )
94+
9095 # Update download button visibility and state
9196 self ._download_btn .set_visible (ui_state .is_offroad ())
9297
@@ -163,4 +168,24 @@ def _on_install_update(self):
163168 self ._install_btn .action_item .set_enabled (False )
164169 ui_state .params .put_bool ("DoReboot" , True )
165170
166- def _on_select_branch (self ): pass
171+ def _on_select_branch (self ):
172+ current_branch = ui_state .params .get ("GitBranch" )
173+ available_branches = (ui_state .params .get ("UpdaterAvailableBranches" ) or "" ).split ("," )
174+ available_branches = [branch .strip () for branch in available_branches if branch .strip ()]
175+ priority_branches = [current_branch , "devel-staging" , "devel" , "nightly" , "nightly-dev" , "master" ]
176+ for branch in priority_branches :
177+ if branch in available_branches :
178+ available_branches .remove (branch )
179+ available_branches .insert (0 , branch )
180+
181+ self ._select_branch_dialog = MultiOptionDialog (tr ("Select a branch" ), available_branches , current = current_branch )
182+ gui_app .set_modal_overlay (self ._select_branch_dialog , callback = self ._handle_branch_selection )
183+
184+ def _handle_branch_selection (self , result : int ):
185+ if result == 1 and self ._select_branch_dialog :
186+ selected = self ._select_branch_dialog .selection
187+ self ._target_branch_btn .action_item .set_value (selected )
188+ ui_state .params .put ("UpdaterTargetBranch" , selected )
189+ os .system ("pkill -SIGHUP -f system.updated.updated" )
190+
191+ self ._select_branch_dialog = None
0 commit comments