@@ -65,7 +65,7 @@ $csrf_token = $var['csrf_token'] ?? '';
6565 <dl>
6666 <dt class="help-label">_(PCIe ACS Override)_ _(details)_:</dt>
6767 <dd>
68- <select id="acs-dropdown" onchange="updateConfig()" style="width: auto;">
68+ <select id="acs-dropdown" onchange="updateConfig('acs-dropdown' )" style="width: auto;">
6969 <option value="">_(Disabled)_</option>
7070 <option value="downstream">_(Downstream)_</option>
7171 <option value="multifunction">_(Multi-function)_</option>
@@ -86,7 +86,7 @@ $csrf_token = $var['csrf_token'] ?? '';
8686 <dl>
8787 <dt class="help-label">_(VFIO Allow Unsafe Interrupts)_ _(details)_:</dt>
8888 <dd>
89- <input type="checkbox" id="vfio-toggle" class="switch narrow" onchange="updateConfig()">
89+ <input type="checkbox" id="vfio-toggle" class="switch narrow" onchange="updateConfig('vfio-toggle' )">
9090 <br>
9191 <span class="parameter-code">vfio_iommu_type1.allow_unsafe_interrupts=1</span>
9292 <blockquote class="inline_help">
@@ -665,10 +665,29 @@ function bootParamsTabFocus() {
665665}
666666
667667// Update configuration preview
668- function updateConfig() {
668+ function ensureApplyTogglesEnabled(labels) {
669+ if (!Array.isArray(labels) || labels.length === 0) {
670+ return;
671+ }
672+
673+ $('.boot-entry-apply-toggle').each(function() {
674+ const toggle = $(this);
675+ const label = toggle.attr('data-label');
676+
677+ if (labels.indexOf(label) !== -1 && !toggle.prop('checked')) {
678+ toggle.switchButton('option', 'checked', true);
679+ }
680+ });
681+ }
682+
683+ function updateConfig(changedFieldId) {
669684 // Handle mutual exclusivity for sysfb_blacklist toggle
670685 handleFramebufferMutualExclusivity();
671686
687+ if (changedFieldId === 'acs-dropdown' || changedFieldId === 'vfio-toggle') {
688+ ensureApplyTogglesEnabled(['Unraid OS', 'Unraid OS GUI Mode']);
689+ }
690+
672691 markFormModified();
673692 updatePreview();
674693}
@@ -1044,7 +1063,7 @@ function updatePreview() {
10441063 if (bootloaderType === 'grub') {
10451064 html = '<span style="color: var(--text-color, #333);">linux /bzimage</span> ';
10461065 } else {
1047- html = '<span style="color: var(--text-color, #333);">append initrd=/bzroot </span> ';
1066+ html = '<span style="color: var(--text-color, #333);">append ' + getPreviewSyslinuxInitrd() + ' </span> ';
10481067 }
10491068
10501069 // Add all proposed parameters in bright green with bold weight for visibility
@@ -1203,11 +1222,47 @@ function stripSystemParams(line) {
12031222 return indent + rest;
12041223}
12051224
1225+ function normalizeDisplayLineForComparison(line) {
1226+ if (!line) return '';
1227+ return stripSystemParams(line).trim().replace(/\s+/g, ' ');
1228+ }
1229+
1230+ function getSyslinuxInitrdForEntryLabel(label) {
1231+ return /GUI Mode|GUI Safe Mode/i.test(label || '') ? 'initrd=/bzroot,/bzroot-gui' : 'initrd=/bzroot';
1232+ }
1233+
1234+ function getPreviewSyslinuxInitrd() {
1235+ const appliedLabels = [];
1236+ $('.boot-entry-apply-toggle:checked').each(function() {
1237+ appliedLabels.push($(this).attr('data-label') || '');
1238+ });
1239+
1240+ if (appliedLabels.length > 0 && appliedLabels.every(function(label) {
1241+ return /GUI Mode|GUI Safe Mode/i.test(label);
1242+ })) {
1243+ return 'initrd=/bzroot,/bzroot-gui';
1244+ }
1245+
1246+ return 'initrd=/bzroot';
1247+ }
1248+
1249+ function getSelectedDefaultEntryLabel() {
1250+ const selected = $('input[name="default-boot"]:checked').attr('data-label');
1251+ return selected || '';
1252+ }
1253+
12061254/**
12071255 * Helper function to create boot entry content with optional diff display
12081256 */
12091257function createEntryContent(entry, showApply) {
12101258 const content = $('<pre>').addClass('boot-entry-content');
1259+ const selectedDefaultLabel = getSelectedDefaultEntryLabel();
1260+ const shouldShowMenuDefault = bootloaderType === 'syslinux'
1261+ ? (selectedDefaultLabel ? entry.label === selectedDefaultLabel : entry.isDefault)
1262+ : entry.isDefault;
1263+ const originalHasMenuDefault = bootloaderType === 'syslinux' && entry.lines.some(function(entryLine) {
1264+ return entryLine.trim() === 'menu default';
1265+ });
12111266
12121267 // Find the line index to update (append for syslinux, linux for GRUB)
12131268 let appendLineIndex = -1;
@@ -1227,6 +1282,25 @@ function createEntryContent(entry, showApply) {
12271282 // Build the content
12281283 let contentHtml = '';
12291284 entry.lines.forEach((line, idx) => {
1285+ const trimmed = line.trim();
1286+
1287+ if (bootloaderType === 'syslinux' && trimmed.startsWith('label ')) {
1288+ contentHtml += stripSystemParams(line) + '\n';
1289+ if (shouldShowMenuDefault && !originalHasMenuDefault) {
1290+ contentHtml += '<span class="diff-line-added"> menu default</span>\n';
1291+ }
1292+ return;
1293+ }
1294+
1295+ if (bootloaderType === 'syslinux' && trimmed === 'menu default') {
1296+ if (shouldShowMenuDefault) {
1297+ contentHtml += stripSystemParams(line) + '\n';
1298+ } else {
1299+ contentHtml += '<span class="diff-line-removed">' + stripSystemParams(line) + '</span>\n';
1300+ }
1301+ return;
1302+ }
1303+
12301304 if (idx === appendLineIndex && showApply) {
12311305 // Show diff: removed line (original) and added line (with parameters)
12321306 const originalAppend = stripSystemParams(line);
@@ -1257,10 +1331,12 @@ function createEntryContent(entry, showApply) {
12571331 const args = mergedArgs.length > 0 ? ' ' + mergedArgs.join(' ') : '';
12581332 newAppend = indent + cmd + ' ' + kernel + args;
12591333 } else {
1260- newAppend = ' append initrd=/bzroot' + (proposedParams.length > 0 ? ' ' + proposedParams.join(' ') : '');
1334+ const indentMatch = line.match(/^(\s*)append\b/);
1335+ const indent = indentMatch ? indentMatch[1] : ' ';
1336+ newAppend = indent + 'append ' + getSyslinuxInitrdForEntryLabel(entry.label) + (proposedParams.length > 0 ? ' ' + proposedParams.join(' ') : '');
12611337 }
12621338 const newAppendDisplay = stripSystemParams(newAppend);
1263- if (originalAppend === newAppendDisplay) {
1339+ if (normalizeDisplayLineForComparison( originalAppend) === normalizeDisplayLineForComparison( newAppendDisplay) ) {
12641340 contentHtml += originalAppend + '\n';
12651341 } else {
12661342 contentHtml += '<span class="diff-line-removed">' + originalAppend + '</span>\n';
@@ -1302,6 +1378,28 @@ function updateAllAppliedEntryDiffs() {
13021378 });
13031379}
13041380
1381+ function updateDefaultEntryDisplay() {
1382+ const selectedDefaultLabel = getSelectedDefaultEntryLabel();
1383+
1384+ $('.boot-entry').each(function() {
1385+ const entryDiv = $(this);
1386+ const entry = entryDiv.data('entry');
1387+ if (!entry) return;
1388+
1389+ const toggle = entryDiv.find('.boot-entry-apply-toggle');
1390+ if (toggle.length > 0 && selectedDefaultLabel && entry.label === selectedDefaultLabel && !toggle.prop('checked')) {
1391+ toggle.switchButton('option', 'checked', true);
1392+ }
1393+
1394+ entryDiv.toggleClass('default', !!selectedDefaultLabel && entry.label === selectedDefaultLabel);
1395+
1396+ const showApply = toggle.length > 0 && toggle.prop('checked');
1397+ updateEntryDiff(entryDiv, entry, showApply);
1398+ });
1399+
1400+ updatePreview();
1401+ }
1402+
13051403/**
13061404 * Render menu view from parsed configuration
13071405 */
@@ -1443,6 +1541,7 @@ function renderMenuView(parsed) {
14431541 .prop('checked', entry.isDefault)
14441542 .on('change', function() {
14451543 markFormModified();
1544+ updateDefaultEntryDisplay();
14461545 });
14471546 header.append(radio);
14481547 }
0 commit comments