Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions archinstall/applications/bluetooth.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
from typing import TYPE_CHECKING

from archinstall.lib.output import debug

if TYPE_CHECKING:
from archinstall.lib.installer import Installer


class Bluetooth:
@property
def packages(self) -> list[str]:
return [
'bluez',
'bluez-utils',
]

@property
def services(self) -> list[str]:
return [
'bluetooth.service',
]

def install(self, install_session: 'Installer') -> None:
debug('Installing Bluetooth')
install_session.add_additional_packages(self.packages)
install_session.enable_service(self.services)
2 changes: 0 additions & 2 deletions archinstall/default_profiles/desktops/cinnamon.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,6 @@ def packages(self) -> list[str]:
'system-config-printer',
'gnome-keyring',
'gnome-terminal',
'blueman',
'bluez-utils',
'engrampa',
'gnome-screenshot',
'gvfs-smb',
Expand Down
Empty file.
23 changes: 23 additions & 0 deletions archinstall/lib/applications/application_handler.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
from typing import TYPE_CHECKING

from archinstall.applications.bluetooth import Bluetooth
from archinstall.lib.models.application import ApplicationConfiguration

if TYPE_CHECKING:
from archinstall.lib.installer import Installer


class ApplicationHandler:
def __init__(self) -> None:
pass

def install_applications(
self,
install_session: 'Installer',
app_config: ApplicationConfiguration,
) -> None:
if app_config.bluetooth_config:
Bluetooth().install(install_session)


application_handler = ApplicationHandler()
76 changes: 76 additions & 0 deletions archinstall/lib/applications/application_menu.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
from typing import override

from archinstall.lib.menu.abstract_menu import AbstractSubMenu
from archinstall.lib.models.application import ApplicationConfiguration, BluetoothConfiguration
from archinstall.lib.translationhandler import tr
from archinstall.tui.curses_menu import SelectMenu
from archinstall.tui.menu_item import MenuItem, MenuItemGroup
from archinstall.tui.types import Alignment, Orientation


class ApplicationMenu(AbstractSubMenu[ApplicationConfiguration]):
def __init__(
self,
preset: ApplicationConfiguration | None = None,
):
if preset:
self._app_config = preset
else:
self._app_config = ApplicationConfiguration()

menu_optioons = self._define_menu_options()
self._item_group = MenuItemGroup(menu_optioons, checkmarks=True)

super().__init__(
self._item_group,
config=self._app_config,
allow_reset=True,
)

@override
def run(self, additional_title: str | None = None) -> ApplicationConfiguration:
super().run(additional_title=additional_title)
return self._app_config

def _define_menu_options(self) -> list[MenuItem]:
return [
MenuItem(
text=tr('Bluetooth'),
action=select_bluetooth,
value=self._app_config.bluetooth_config,
preview_action=self._prev_bluetooth,
key='bluetooth_config',
),
]

def _prev_bluetooth(self, item: MenuItem) -> str | None:
if item.value is not None:
bluetooth_config: BluetoothConfiguration = item.value

output = 'Bluetooth: '
output += tr('Enabled') if bluetooth_config.enabled else tr('Disabled')
return output
return None


def select_bluetooth(preset: BluetoothConfiguration | None) -> BluetoothConfiguration | None:
group = MenuItemGroup.yes_no()
group.focus_item = MenuItem.no()

if preset is not None:
group.set_selected_by_value(preset.enabled)

header = tr('Would you like to configure Bluetooth?') + '\n'

result = SelectMenu[bool](
group,
header=header,
alignment=Alignment.CENTER,
columns=2,
orientation=Orientation.HORIZONTAL,
allow_skip=True,
).run()

enabled = result.item() == MenuItem.yes()

return BluetoothConfiguration(enabled)
6 changes: 6 additions & 0 deletions archinstall/lib/args.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
from pydantic.dataclasses import dataclass as p_dataclass

from archinstall.lib.crypt import decrypt
from archinstall.lib.models.application import ApplicationConfiguration
from archinstall.lib.models.audio_configuration import AudioConfiguration
from archinstall.lib.models.bootloader import Bootloader
from archinstall.lib.models.device_model import DiskEncryption, DiskLayoutConfiguration
Expand Down Expand Up @@ -63,6 +64,7 @@ class ArchConfig:
bootloader: Bootloader = field(default=Bootloader.get_default())
uki: bool = False
audio_config: AudioConfiguration | None = None
application_config: ApplicationConfiguration | None = None
hostname: str = 'archlinux'
kernels: list[str] = field(default_factory=lambda: ['linux'])
ntp: bool = True
Expand Down Expand Up @@ -105,6 +107,7 @@ def safe_json(self) -> dict[str, Any]:
'custom_commands': self.custom_commands,
'bootloader': self.bootloader.json(),
'audio_config': self.audio_config.json() if self.audio_config else None,
'app_config': self.application_config.json() if self.application_config else None,
}

if self.locale_config:
Expand Down Expand Up @@ -184,6 +187,9 @@ def from_config(cls, args_config: dict[str, Any]) -> 'ArchConfig':
if audio_config := args_config.get('audio_config', None):
arch_config.audio_config = AudioConfiguration.parse_arg(audio_config)

if app_config := args_config.get('app_config', None):
arch_config.application_config = ApplicationConfiguration.parse_arg(app_config)

if hostname := args_config.get('hostname', ''):
arch_config.hostname = hostname

Expand Down
26 changes: 26 additions & 0 deletions archinstall/lib/global_menu.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,12 @@
from typing import override

from archinstall.lib.disk.disk_menu import DiskLayoutConfigurationMenu
from archinstall.lib.models.application import ApplicationConfiguration
from archinstall.lib.models.device_model import DiskLayoutConfiguration, DiskLayoutType, EncryptionType, FilesystemType, PartitionModification
from archinstall.lib.packages import list_available_packages
from archinstall.tui.menu_item import MenuItem, MenuItemGroup

from .applications.application_menu import ApplicationMenu
from .args import ArchConfig
from .configuration import save_config
from .hardware import SysInfo
Expand Down Expand Up @@ -132,6 +134,13 @@ def _get_menu_options(self) -> list[MenuItem]:
preview_action=self._prev_audio,
key='audio_config',
),
MenuItem(
text=tr('Applications'),
action=self._select_applications,
value=[],
preview_action=self._prev_applications,
key='application_config',
),
MenuItem(
text=tr('Kernels'),
value=['linux'],
Expand Down Expand Up @@ -252,6 +261,10 @@ def _select_archinstall_language(self, preset: Language) -> Language:

return language

def _select_applications(self, preset: ApplicationConfiguration | None) -> ApplicationConfiguration | None:
app_config = ApplicationMenu(preset).run()
return app_config

def _update_lang_text(self) -> None:
"""
The options for the global menu are generated with a static text;
Expand Down Expand Up @@ -291,6 +304,19 @@ def _prev_additional_pkgs(self, item: MenuItem) -> str | None:
return output
return None

def _prev_applications(self, item: MenuItem) -> str | None:
if item.value:
app_config: ApplicationConfiguration = item.value
output = ''

if app_config.bluetooth_config:
output += f'{tr("Bluetooth")}: '
output += tr('Enabled') if app_config.bluetooth_config.enabled else tr('Disabled') + '\n'

return output

return None

def _prev_tz(self, item: MenuItem) -> str | None:
if item.value:
return f'{tr("Timezone")}: {item.value}'
Expand Down
45 changes: 45 additions & 0 deletions archinstall/lib/models/application.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
from dataclasses import dataclass
from typing import NotRequired, TypedDict


class BluetoothConfigSerialization(TypedDict):
enabled: bool


class ApplicationSerialization(TypedDict):
bluetooth_config: NotRequired[BluetoothConfigSerialization]


@dataclass
class BluetoothConfiguration:
enabled: bool

def json(self) -> BluetoothConfigSerialization:
return {'enabled': self.enabled}

@staticmethod
def parse_arg(arg: BluetoothConfigSerialization) -> 'BluetoothConfiguration':
return BluetoothConfiguration(arg['enabled'])


@dataclass
class ApplicationConfiguration:
bluetooth_config: BluetoothConfiguration | None = None

@staticmethod
def parse_arg(args: ApplicationSerialization) -> 'ApplicationConfiguration':
bluetooth_config: BluetoothConfiguration | None = None
if 'bluetooth_config' in args:
bluetooth_config = BluetoothConfiguration.parse_arg(args['bluetooth_config'])

return ApplicationConfiguration(
bluetooth_config=bluetooth_config,
)

def json(self) -> ApplicationSerialization:
config: ApplicationSerialization = {}

if self.bluetooth_config:
config['bluetooth_config'] = self.bluetooth_config.json()

return config
4 changes: 4 additions & 0 deletions archinstall/scripts/guided.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
from pathlib import Path

from archinstall import SysInfo
from archinstall.lib.applications.application_handler import application_handler
from archinstall.lib.args import arch_config_handler
from archinstall.lib.configuration import ConfigurationOutput
from archinstall.lib.disk.filesystem import FilesystemHandler
Expand Down Expand Up @@ -127,6 +128,9 @@ def perform_installation(mountpoint: Path) -> None:
if profile_config := config.profile_config:
profile_handler.install_profile_config(installation, profile_config)

if app_config := config.application_config:
application_handler.install_applications(installation, app_config)

if timezone := config.timezone:
installation.set_timezone(timezone)

Expand Down
5 changes: 5 additions & 0 deletions tests/data/test_config.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
{
"archinstall-language": "English",
"app_config": {
"bluetooth_config": {
"enabled": true
}
},
"audio_config": {
"audio": "pipewire"
},
Expand Down
4 changes: 4 additions & 0 deletions tests/test_args.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
from archinstall.default_profiles.profile import GreeterType
from archinstall.lib.args import ArchConfig, ArchConfigHandler, Arguments
from archinstall.lib.hardware import GfxDriver
from archinstall.lib.models.application import ApplicationConfiguration, BluetoothConfiguration
from archinstall.lib.models.audio_configuration import Audio, AudioConfiguration
from archinstall.lib.models.bootloader import Bootloader
from archinstall.lib.models.device_model import DiskLayoutConfiguration, DiskLayoutType
Expand Down Expand Up @@ -127,6 +128,9 @@ def test_config_file_parsing(

assert arch_config == ArchConfig(
version='3.0.2',
application_config=ApplicationConfiguration(
bluetooth_config=BluetoothConfiguration(enabled=True),
),
locale_config=LocaleConfiguration(
kb_layout='us',
sys_lang='en_US',
Expand Down