From 4d839631a4ea649542fd9a150ceff8106d47e050 Mon Sep 17 00:00:00 2001 From: CooperWang0912 Date: Thu, 23 Jul 2026 13:05:16 +0800 Subject: [PATCH] Wrapper for Instant Update and Color Change --- archinstall/lib/global_menu.py | 58 ++++++++++++++++++++++------------ 1 file changed, 38 insertions(+), 20 deletions(-) diff --git a/archinstall/lib/global_menu.py b/archinstall/lib/global_menu.py index 663a32c8..5ac0fe78 100644 --- a/archinstall/lib/global_menu.py +++ b/archinstall/lib/global_menu.py @@ -1,4 +1,5 @@ -from typing import override +import inspect +from typing import Any, Callable, override from archinstall.default_profiles.profile import GreeterType from archinstall.lib.applications.application_menu import ApplicationMenu @@ -50,7 +51,7 @@ class GlobalMenu(AbstractMenu[None]): self._skip_boot = skip_boot self._advanced = advanced self._uefi = SysInfo.has_uefi() - menu_options = self._get_menu_options() + menu_options = self._get_menu_options(wrap_actions=True) self._item_group = MenuItemGroup( menu_options, @@ -65,8 +66,8 @@ class GlobalMenu(AbstractMenu[None]): """ Returns a rich-formatted status prefix icon depending on item state: - [✓] (Green) for configured items - - [!] (Yellow) for missing mandatory or required items - - [•] (Dim) for unconfigured optional items + - [!] (Red) for missing mandatory or required items + - [•] (Yellow) for unconfigured optional items """ if item.read_only or item.key in (SpecialMenuKey.SAVE.value, SpecialMenuKey.INSTALL.value, SpecialMenuKey.ABORT.value): return "" @@ -79,20 +80,22 @@ class GlobalMenu(AbstractMenu[None]): ) if is_auth_valid: return "[bold green][✓][/bold green] " - return "[bold yellow][!][/bold yellow] " + return "[bold red][!][/bold red] " + # Standard mandatory or configured item check if item.has_value(): return "[bold green][✓][/bold green] " elif item.mandatory: - return "[bold yellow][!][/bold yellow] " + return "[bold red][!][/bold red] " else: - return "[dim white][•][/dim white] " + return "[bold yellow][•][/bold yellow] " def _update_item_labels(self) -> None: """ Re-applies translated titles and status prefixes to all active menu items. """ - new_options = {o.key: o.text for o in self._get_menu_options() if o.key is not None} + raw_options = self._get_menu_options(wrap_actions=False) + new_options = {o.key: o.text for o in raw_options if o.key is not None} for item in self._item_group.items: if item.key in new_options: @@ -100,7 +103,26 @@ class GlobalMenu(AbstractMenu[None]): prefix = self._get_status_prefix(item) item.text = f"{prefix}{base_title}" - def _get_menu_options(self) -> list[MenuItem]: + def _wrap_action(self, key: str, action: Callable) -> Callable: + async def wrapper(*args, **kwargs) -> Any: + if inspect.iscoroutinefunction(action): + result = await action(*args, **kwargs) + else: + result = action(*args, **kwargs) + if inspect.isawaitable(result): + result = await result + + item = self._item_group.find_by_key(key) + if item: + item.value = result + + self._update_item_labels() + + return result + + return wrapper + + def _get_menu_options(self, wrap_actions: bool = True) -> list[MenuItem]: menu_options = [ MenuItem( text=tr('Archinstall language'), @@ -231,6 +253,11 @@ class GlobalMenu(AbstractMenu[None]): ), ] + if wrap_actions: + for item in menu_options: + if item.key and item.action: + item.action = self._wrap_action(item.key, item.action) + return menu_options async def _safe_config(self) -> None: @@ -305,12 +332,10 @@ class GlobalMenu(AbstractMenu[None]): async def _select_applications(self, preset: ApplicationConfiguration | None) -> ApplicationConfiguration | None: app_config = await ApplicationMenu(preset).show() - self._update_item_labels() return app_config async def _select_authentication(self, preset: AuthenticationConfiguration | None) -> AuthenticationConfiguration | None: auth_config = await AuthenticationMenu(preset).show() - self._update_item_labels() return auth_config def _update_lang_text(self) -> None: @@ -322,7 +347,6 @@ class GlobalMenu(AbstractMenu[None]): async def _locale_selection(self, preset: LocaleConfiguration) -> LocaleConfiguration | None: locale_config = await LocaleMenu(preset).show() - self._update_item_labels() return locale_config def _prev_locale(self, item: MenuItem) -> str | None: @@ -457,9 +481,7 @@ class GlobalMenu(AbstractMenu[None]): return None async def _pacman_configuration(self, preset: PacmanConfiguration) -> PacmanConfiguration | None: - res = await PacmanMenu(preset, advanced=self._advanced).show() - self._update_item_labels() - return res + return await PacmanMenu(preset, advanced=self._advanced).show() def _prev_pacman_config(self, item: MenuItem) -> str | None: if not item.value: @@ -600,7 +622,6 @@ class GlobalMenu(AbstractMenu[None]): preset: DiskLayoutConfiguration | None = None, ) -> DiskLayoutConfiguration | None: disk_config = await DiskLayoutConfigurationMenu(preset).show() - self._update_item_labels() return disk_config async def _select_bootloader_config( @@ -611,14 +632,12 @@ class GlobalMenu(AbstractMenu[None]): preset = BootloaderConfiguration.get_default(self._uefi, self._skip_boot) bootloader_config = await BootloaderMenu(preset, self._uefi, self._skip_boot).show() - self._update_item_labels() return bootloader_config async def _select_profile(self, current_profile: ProfileConfiguration | None) -> ProfileConfiguration | None: from archinstall.lib.profile.profile_menu import ProfileMenu profile_config = await ProfileMenu(preset=current_profile).show() - self._update_item_labels() return profile_config async def _select_additional_packages(self, preset: list[str]) -> list[str]: @@ -632,7 +651,7 @@ class GlobalMenu(AbstractMenu[None]): preset, repositories=repositories, ) - self._update_item_labels() + return packages async def _mirror_configuration(self, preset: MirrorConfiguration | None = None) -> MirrorConfiguration | None: @@ -650,7 +669,6 @@ class GlobalMenu(AbstractMenu[None]): pacman_config.enable(mirror_configuration.optional_repositories) pacman_config.apply() - self._update_item_labels() return mirror_configuration def _prev_mirror_config(self, item: MenuItem) -> str | None: