Show install summary when configuration is valid (#4475)

* Show install summary when configuration is valid

Previously the Install menu preview was empty when everything was valid,
leaving the user with no "ready" signal. Now show "Ready to install"
plus a two-column summary of the current configuration.

- New _install_summary() composes an aligned key/value table with rows
  for disks+FS+LUKS, bootloader, kernel, profile, greeter, package
  count, network, locale and timezone. Column width adapts to the
  longest translated label so translations keep the alignment.
- Rows whose underlying config is not set are skipped rather than
  rendered as empty.
- base.pot / uk base.po: add new msgids for summary labels.

* Move install summary into ConfigurationOutput

The summary helper that renders the install preview's two-column
configuration overview lived in GlobalMenu. Move it to
ConfigurationOutput.as_summary() so it sits alongside the JSON
output methods that share the same role. The preview now syncs
menu state to ArchConfig and delegates rendering.
This commit is contained in:
Softer 2026-04-28 12:22:01 +03:00 committed by GitHub
parent 8cc35f41d8
commit 08cba236f6
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 102 additions and 2 deletions

View File

@ -10,6 +10,8 @@ from archinstall.lib.args import ArchConfig
from archinstall.lib.crypt import encrypt from archinstall.lib.crypt import encrypt
from archinstall.lib.menu.helpers import Confirmation, Selection from archinstall.lib.menu.helpers import Confirmation, Selection
from archinstall.lib.menu.util import get_password, prompt_dir from archinstall.lib.menu.util import get_password, prompt_dir
from archinstall.lib.models.bootloader import Bootloader
from archinstall.lib.models.network import NetworkConfiguration
from archinstall.lib.output import debug, logger, warn from archinstall.lib.output import debug, logger, warn
from archinstall.lib.translationhandler import tr from archinstall.lib.translationhandler import tr
from archinstall.tui.ui.menu_item import MenuItem, MenuItemGroup from archinstall.tui.ui.menu_item import MenuItem, MenuItemGroup
@ -58,6 +60,70 @@ class ConfigurationOutput:
debug(' -- Chosen configuration --') debug(' -- Chosen configuration --')
debug(self.user_config_to_json()) debug(self.user_config_to_json())
def as_summary(self) -> str:
"""
Render a concise two-column summary of the current configuration.
The left column holds section labels, the right column holds values.
Column width adapts to the longest translated label so translations
do not break the alignment. Rows whose underlying config is not set
are skipped.
Returns an empty string if nothing meaningful to show.
"""
rows: list[tuple[str, str]] = []
disk_config = self._config.disk_config
if disk_config and disk_config.device_modifications:
disk_parts: list[str] = []
for mod in disk_config.device_modifications:
path = str(mod.device_path)
root_part = mod.get_root_partition()
flags: list[str] = []
if root_part and root_part.fs_type:
flags.append(root_part.fs_type.value)
if disk_config.disk_encryption:
flags.append(tr('LUKS'))
disk_parts.append(f'{path} ({" + ".join(flags)})' if flags else path)
rows.append((tr('Disks'), ', '.join(disk_parts)))
bl_config = self._config.bootloader_config
if bl_config and bl_config.bootloader != Bootloader.NO_BOOTLOADER:
rows.append((tr('Bootloader'), bl_config.bootloader.value))
kernels = self._config.kernels
if kernels:
rows.append((tr('Kernel'), ', '.join(kernels)))
profile_config = self._config.profile_config
if profile_config and profile_config.profile:
names = profile_config.profile.current_selection_names()
rows.append((tr('Profile'), ', '.join(names) if names else profile_config.profile.name))
if profile_config.greeter:
rows.append((tr('Greeter'), profile_config.greeter.value))
packages = self._config.packages
if packages:
rows.append((tr('Packages'), str(len(packages))))
net_config = self._config.network_config
if isinstance(net_config, NetworkConfiguration):
rows.append((tr('Network'), net_config.type.display_msg()))
locale_config = self._config.locale_config
if locale_config:
rows.append((tr('Locale'), locale_config.sys_lang))
tz = self._config.timezone
if tz:
rows.append((tr('Timezone'), tz))
if not rows:
return ''
label_width = max(len(label) for label, _ in rows) + 2
return '\n'.join(f'{label:<{label_width}}{value}' for label, value in rows)
async def confirm_config(self) -> bool: async def confirm_config(self) -> bool:
header = f'{tr("The specified configuration will be applied")}. ' header = f'{tr("The specified configuration will be applied")}. '
header += tr('Would you like to continue?') + '\n' header += tr('Would you like to continue?') + '\n'

View File

@ -6,7 +6,7 @@ from archinstall.lib.args import ArchConfig
from archinstall.lib.authentication.authentication_menu import AuthenticationMenu from archinstall.lib.authentication.authentication_menu import AuthenticationMenu
from archinstall.lib.bootloader.bootloader_menu import BootloaderMenu from archinstall.lib.bootloader.bootloader_menu import BootloaderMenu
from archinstall.lib.bootloader.utils import validate_bootloader_layout from archinstall.lib.bootloader.utils import validate_bootloader_layout
from archinstall.lib.configuration import save_config from archinstall.lib.configuration import ConfigurationOutput, save_config
from archinstall.lib.disk.disk_menu import DiskLayoutConfigurationMenu from archinstall.lib.disk.disk_menu import DiskLayoutConfigurationMenu
from archinstall.lib.general.general_menu import select_hostname, select_ntp, select_timezone from archinstall.lib.general.general_menu import select_hostname, select_ntp, select_timezone
from archinstall.lib.general.system_menu import select_kernel, select_swap from archinstall.lib.general.system_menu import select_kernel, select_swap
@ -504,7 +504,11 @@ class GlobalMenu(AbstractMenu[None]):
if error := self._validate_bootloader(): if error := self._validate_bootloader():
return tr(f'Invalid configuration: {error}') return tr(f'Invalid configuration: {error}')
return None self.sync_all_to_config()
summary = ConfigurationOutput(self._arch_config).as_summary()
if summary:
return f'{tr("Ready to install")}\n\n{summary}'
return tr('Ready to install')
def _prev_profile(self, item: MenuItem) -> str | None: def _prev_profile(self, item: MenuItem) -> str | None:
profile_config: ProfileConfiguration | None = item.value profile_config: ProfileConfiguration | None = item.value

View File

@ -1248,6 +1248,21 @@ msgstr ""
msgid "Invalid configuration: {error}" msgid "Invalid configuration: {error}"
msgstr "" msgstr ""
msgid "Ready to install"
msgstr ""
msgid "Disks"
msgstr ""
msgid "Packages"
msgstr ""
msgid "Network"
msgstr ""
msgid "Locale"
msgstr ""
msgid "Type" msgid "Type"
msgstr "" msgstr ""

View File

@ -1222,6 +1222,21 @@ msgstr "Модель"
msgid "Invalid configuration: {error}" msgid "Invalid configuration: {error}"
msgstr "Неправильна конфігурація: {error}" msgstr "Неправильна конфігурація: {error}"
msgid "Ready to install"
msgstr "Готово до встановлення"
msgid "Disks"
msgstr "Диски"
msgid "Packages"
msgstr "Пакети"
msgid "Network"
msgstr "Мережа"
msgid "Locale"
msgstr "Локаль"
msgid "Type" msgid "Type"
msgstr "Тип" msgstr "Тип"