Skip to content

Commit

Permalink
Add Simple Grub Configuration #176
Browse files Browse the repository at this point in the history
  • Loading branch information
Jean28518 committed Apr 14, 2024
1 parent d0dd9e3 commit e5df963
Show file tree
Hide file tree
Showing 7 changed files with 346 additions and 2 deletions.
2 changes: 1 addition & 1 deletion additional/python/run_multiple_commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,6 @@
env[key] = value

print(f"-- COMMAND: '{command}' ".ljust(96, "-"))
jessentials.run_command(command=command, environment=env, user=user_id)
jessentials.run_command(command=f"bash -c \"{command}\"", environment=env, user=user_id)

print(" FINISHED ".center(96, "-"))
14 changes: 14 additions & 0 deletions lib/content/basic_entries.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
import 'package:linux_assistant/enums/desktops.dart';
import 'package:linux_assistant/enums/distros.dart';
import 'package:linux_assistant/enums/softwareManagers.dart';
import 'package:linux_assistant/layouts/grub_config/grub_config.dart';
import 'package:linux_assistant/layouts/mint_y.dart';
import 'package:linux_assistant/main.dart';
import 'package:linux_assistant/models/action_entry.dart';
Expand Down Expand Up @@ -226,5 +227,18 @@ List<ActionEntry> getBasicEntries(BuildContext context) {
Linux.disableCdromSourceInDebian(context);
},
),
ActionEntry(
name: AppLocalizations.of(context)!.grubConfiguration,
description: AppLocalizations.of(context)!.grubConfigurationDescription,
iconWidget: Icon(Icons.dns, size: 48, color: MintY.currentColor),
handlerFunction: (VoidCallback callback, BuildContext context) {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => GrubConfigPage(),
),
);
},
),
];
}
7 changes: 7 additions & 0 deletions lib/l10n/app_de.arb
Original file line number Diff line number Diff line change
Expand Up @@ -350,6 +350,13 @@
"openSoftwareCenterDescription": "Öffne das Software-Center, um weitere Anwendungen/Apps zu installieren.",
"disableCdromSource": "Deaktiviere CD-ROM-Quelle",
"disableCdromSourceDescription": "Ein Relikt der Debian-Installation. Deaktiviere die CDROM-Quelle, um Fehlermeldungen zu vermeiden.",
"grubConfiguration": "Grub-Konfiguration",
"grubConfigurationDescription": "Konfiguriere den Grub-Bootloader. Dieser Schritt ist nur für fortgeschrittene Benutzer empfohlen.",
"grubVisible": "Bootmenü sichtbar",
"enableBigFont": "Große Schrift aktivieren",
"grubCountdown": "Zeit bis zum automatischen Start (in Sekunden)",
"startLastBootedEntry": "Starte den zuletzt gebooteten Eintrag",
"save": "Speichern",
"@helloWorld": {
"placeholders": {},
"description": "",
Expand Down
7 changes: 7 additions & 0 deletions lib/l10n/app_en.arb
Original file line number Diff line number Diff line change
Expand Up @@ -350,6 +350,13 @@
"openSoftwareCenterDescription": "Open the Software Center to install additional applications/apps.",
"disableCdromSource": "Disable CD-ROM source",
"disableCdromSourceDescription": "A relic of the Debian installation. Disable the CDROM source to avoid error messages.",
"grubConfiguration": "Grub configuration",
"grubConfigurationDescription": "Configure the Grub bootloader. This step is recommended for advanced users only.",
"grubVisible": "Bootmenu visible",
"enableBigFont": "Enable large font",
"grubCountdown": "Time until automatic start (in seconds)",
"startLastBootedEntry": "Start the last booted entry",
"save": "Save",
"@helloWorld": {
"placeholders": {},
"description": "The conventional newborn programmer greeting",
Expand Down
97 changes: 97 additions & 0 deletions lib/layouts/grub_config/grub_config.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
import 'package:flutter/material.dart';
import 'package:linux_assistant/layouts/mint_y.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:linux_assistant/services/linux.dart';
import 'package:linux_assistant/services/main_search_loader.dart';

class GrubConfigPage extends StatelessWidget {
GrubConfigPage({super.key});

final _GrubSettings _grubSettings = _GrubSettings(Linux.getGrubSettings());

@override
Widget build(BuildContext context) {
return MintYPage(
title: AppLocalizations.of(context)!.grubConfiguration,
contentElements: [
MintYCheckboxSetting(
text: AppLocalizations.of(context)!.grubVisible,
value: _grubSettings.grubVisible,
onChanged: (value) {
_grubSettings.grubVisible = value;
},
),
MintYCheckboxSetting(
text: AppLocalizations.of(context)!.enableBigFont,
value: _grubSettings.enableBigFont,
onChanged: (value) {
_grubSettings.enableBigFont = value;
},
),
MintYTextSetting(
text: AppLocalizations.of(context)!.grubCountdown,
textAlign: TextAlign.right,
value: _grubSettings.timeout.toString(),
onChanged: (value) {
int? parsed = int.tryParse(value);
if (parsed == null) {
return;
}
_grubSettings.timeout = parsed;
},
),
MintYCheckboxSetting(
text: AppLocalizations.of(context)!.startLastBootedEntry,
value: _grubSettings.startLastBootedOne,
onChanged: (value) {
_grubSettings.startLastBootedOne = value;
},
),
],
bottom: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
MintYButton(
text:
Text(AppLocalizations.of(context)!.back, style: MintY.heading4),
onPressed: () {
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) => MainSearchLoader(),
),
);
},
),
const SizedBox(width: 10),
MintYButton(
text: Text(AppLocalizations.of(context)!.save,
style: MintY.heading4White),
color: MintY.currentColor,
onPressed: () {
Linux.ensureGrubSettings(
context,
_grubSettings.grubVisible,
_grubSettings.enableBigFont,
_grubSettings.timeout,
_grubSettings.startLastBootedOne);
},
),
],
),
);
}
}

class _GrubSettings {
bool grubVisible = false;
bool enableBigFont = false;
int timeout = 100;
bool startLastBootedOne = false;

_GrubSettings(Map<String, dynamic> settingsMap) {
grubVisible = settingsMap["grubVisible"];
enableBigFont = settingsMap["enableBigFont"];
timeout = settingsMap["timeout"];
startLastBootedOne = settingsMap["startLastBootedOne"];
}
}
109 changes: 109 additions & 0 deletions lib/layouts/mint_y.dart
Original file line number Diff line number Diff line change
Expand Up @@ -908,3 +908,112 @@ class MintYLoadingPage extends StatelessWidget {
);
}
}

class MintYCheckboxSetting extends StatefulWidget {
late String text;
late bool value;

/// Callback function that takes as parameter the new value of the setting
late Function(bool) onChanged;

MintYCheckboxSetting(
{super.key,
required this.text,
required this.value,
required this.onChanged});

@override
State<MintYCheckboxSetting> createState() => _MintYCheckboxSettingState();
}

class _MintYCheckboxSettingState extends State<MintYCheckboxSetting> {
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 100.0, vertical: 8.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
widget.text,
style: Theme.of(context).textTheme.headlineMedium,
),
Checkbox(
value: widget.value,
onChanged: (bool? newValue) {
setState(() {
widget.value = newValue!;
widget.onChanged.call(newValue);
});
},
activeColor: MintY.currentColor,
),
],
),
);
}
}

class MintYTextSetting extends StatefulWidget {
late String text;
late String value;
late TextAlign textAlign;
late Function(String) onChanged;

MintYTextSetting(
{super.key,
required this.text,
required this.value,
required this.textAlign,
required this.onChanged});

@override
State<MintYTextSetting> createState() => _MintYTextSettingState();
}

class _MintYTextSettingState extends State<MintYTextSetting> {
late TextEditingController controller;

@override
void initState() {
super.initState();
controller = TextEditingController(text: widget.value);
}

@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 100.0, vertical: 8.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
widget.text,
style: Theme.of(context).textTheme.headlineMedium,
),
SizedBox(
width: 200,
child: TextField(
controller: controller,
onChanged: (String newValue) {
widget.onChanged.call(newValue);
},
textAlign: widget.textAlign,
decoration: InputDecoration(
border: OutlineInputBorder(
borderSide: BorderSide(color: MintY.currentColor),
),
focusedBorder: OutlineInputBorder(
borderSide: BorderSide(
color: MintY.currentColor,
width: 2,
style: BorderStyle.solid),
),
),
),
),
],
),
);
}
}
112 changes: 111 additions & 1 deletion lib/services/linux.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2647,7 +2647,7 @@ class Linux {
"git clone https://aur.archlinux.org/snapd.git /tmp/snapd; cd /tmp/snapd; makepkg -si --noconfirm;";
commandQueue.add(LinuxCommand(
userId: currentenvironment.currentUserId,
command: "bash -c '$bashCode'",
command: bashCode,
environment: {"PATH": getPATH(), "HOME": getHomeDirectory()},
));
commandQueue.add(LinuxCommand(
Expand Down Expand Up @@ -2776,4 +2776,114 @@ class Linux {
));
}
}

static Map<String, dynamic> getGrubSettings() {
String grubFileContent = File("/etc/default/grub").readAsStringSync();
List<String> lines = grubFileContent.split("\n");
Map<String, String> settingsFileMap = {};
for (String line in lines) {
if (line.contains("=") && !line.trim().startsWith("#")) {
List<String> parts = line.split("=");
settingsFileMap[parts[0]] = parts[1];
}
}

Map<String, dynamic> returnValue = {};
returnValue["grubVisible"] =
settingsFileMap["GRUB_TIMEOUT_STYLE"] == "menu" ||
settingsFileMap["GRUB_TIMEOUT_STYLE"] == null;
returnValue["enableBigFont"] = settingsFileMap["GRUB_GFXMODE"] == "640x480";
if (settingsFileMap["GRUB_TIMEOUT"] == null) {
settingsFileMap["GRUB_TIMEOUT"] = "0";
}
returnValue["timeout"] =
int.tryParse(settingsFileMap["GRUB_TIMEOUT"]!) ?? 0;
returnValue["startLastBootedOne"] =
settingsFileMap["GRUB_DEFAULT"] == "saved";

return returnValue;
}

static void ensureGrubSettings(context, bool grubVisible, bool enableBigFont,
int timeout, bool startLastBootedOne) {
String grub_timeout_style = grubVisible ? "menu" : "hidden";
String grub_timeout = timeout.toString();
String grub_default = startLastBootedOne ? "saved" : "0";
String grub_save_default = startLastBootedOne ? "true" : "false";
String grub_gfxmode = enableBigFont ? "640x480" : "";

if (grub_timeout_style == "menu" && timeout < 1) {
grub_timeout = "1";
}

if (grub_timeout_style == "hidden" && timeout < 0) {
grub_timeout = "0";
}

ensureOptionInConfigFile(
"GRUB_TIMEOUT_STYLE", grub_timeout_style, "/etc/default/grub");
ensureOptionInConfigFile("GRUB_TIMEOUT", grub_timeout, "/etc/default/grub");
ensureOptionInConfigFile("GRUB_DEFAULT", grub_default, "/etc/default/grub");
ensureOptionInConfigFile(
"GRUB_SAVEDEFAULT", grub_save_default, "/etc/default/grub");
ensureOptionInConfigFile("GRUB_GFXMODE", grub_gfxmode, "/etc/default/grub");

if (currentenvironment.distribution != DISTROS.FEDORA) {
commandQueue.add(LinuxCommand(
userId: 0,
command: "/usr/sbin/grub-mkconfig -o /boot/grub/grub.cfg",
));
} else {
commandQueue.add(LinuxCommand(
userId: 0,
command: "/usr/sbin/grub2-mkconfig -o /boot/grub2/grub.cfg",
));
}

Navigator.of(context).push(MaterialPageRoute(
builder: (context) => RunCommandQueue(
title: AppLocalizations.of(context)!.grubConfiguration,
route: MainSearchLoader()),
));
}

/// Used for config files like /etc/default/grub.
///
/// Only adds the commands to the command queue to ensure that the key is set to the value.
/// If the value is empty, the key will be removed from the file.
static void ensureOptionInConfigFile(String key, String value, String path) {
/// Remove the key from the file if the value is empty
if (value.isEmpty) {
commandQueue.add(LinuxCommand(
userId: 0,
command: "sed -i '/$key/d' $path",
));
return;
}

bool settingFound = false;
// Check if the key is already in the file and is not commented out
String fileContent = File(path).readAsStringSync();
List<String> lines = fileContent.split("\n");
for (String line in lines) {
if (line.contains("$key=") && !line.trim().startsWith("#")) {
settingFound = true;
break;
}
}

if (!settingFound) {
// Add the key to the file
commandQueue.add(LinuxCommand(
userId: 0,
command: "echo '$key=$value' >> $path",
));
} else {
// Replace the key in the file
commandQueue.add(LinuxCommand(
userId: 0,
command: "sed -i 's/$key=.*/$key=$value/' $path",
));
}
}
}

0 comments on commit e5df963

Please sign in to comment.