mirror of
https://git.sanhost.net/sanasol/hytale-f2p.git
synced 2026-02-26 14:51:48 -03:00
v2.4.1: Replace raw wrapper script editor with structured config UI
Replace the raw textarea script editor with a structured form for Java wrapper configuration. Users now manage two lists (JVM flags to strip, args to inject with server/always condition) instead of editing bash/batch scripts directly. Scripts are generated at launch time from the structured config. Includes collapsible script preview for power users.
This commit is contained in:
@@ -569,6 +569,7 @@ async function loadAllSettings() {
|
||||
await loadLauncherHwAccel();
|
||||
await loadGpuPreference();
|
||||
await loadVersionBranch();
|
||||
await loadWrapperConfigUI();
|
||||
}
|
||||
|
||||
|
||||
@@ -1254,3 +1255,235 @@ async function loadVersionBranch() {
|
||||
return 'release';
|
||||
}
|
||||
}
|
||||
|
||||
// === Java Wrapper Configuration UI ===
|
||||
|
||||
let _wrapperConfig = null;
|
||||
let _wrapperPreviewOpen = false;
|
||||
|
||||
async function loadWrapperConfigUI() {
|
||||
try {
|
||||
if (!window.electronAPI || !window.electronAPI.loadWrapperConfig) return;
|
||||
|
||||
_wrapperConfig = await window.electronAPI.loadWrapperConfig();
|
||||
renderStripFlagsList();
|
||||
renderInjectArgsList();
|
||||
setupWrapperEventListeners();
|
||||
} catch (error) {
|
||||
console.error('Error loading wrapper config UI:', error);
|
||||
}
|
||||
}
|
||||
|
||||
function renderStripFlagsList() {
|
||||
const container = document.getElementById('wrapperStripFlagsList');
|
||||
if (!container || !_wrapperConfig) return;
|
||||
|
||||
if (_wrapperConfig.stripFlags.length === 0) {
|
||||
container.innerHTML = '<div class="wrapper-items-empty">No flags configured</div>';
|
||||
return;
|
||||
}
|
||||
|
||||
container.innerHTML = '';
|
||||
_wrapperConfig.stripFlags.forEach((flag, index) => {
|
||||
const item = document.createElement('div');
|
||||
item.className = 'wrapper-item';
|
||||
item.innerHTML = `
|
||||
<span class="wrapper-item-text">${escapeHtml(flag)}</span>
|
||||
<button class="wrapper-item-delete" data-index="${index}" title="Remove">
|
||||
<i class="fas fa-trash-alt"></i>
|
||||
</button>
|
||||
`;
|
||||
item.querySelector('.wrapper-item-delete').addEventListener('click', () => removeStripFlag(index));
|
||||
container.appendChild(item);
|
||||
});
|
||||
}
|
||||
|
||||
function renderInjectArgsList() {
|
||||
const container = document.getElementById('wrapperInjectArgsList');
|
||||
if (!container || !_wrapperConfig) return;
|
||||
|
||||
if (_wrapperConfig.injectArgs.length === 0) {
|
||||
container.innerHTML = '<div class="wrapper-items-empty">No arguments configured</div>';
|
||||
return;
|
||||
}
|
||||
|
||||
container.innerHTML = '';
|
||||
_wrapperConfig.injectArgs.forEach((entry, index) => {
|
||||
const item = document.createElement('div');
|
||||
item.className = 'wrapper-item';
|
||||
|
||||
const serverLabel = window.i18n ? window.i18n.t('settings.wrapperConditionServer') : 'Server Only';
|
||||
const alwaysLabel = window.i18n ? window.i18n.t('settings.wrapperConditionAlways') : 'Always';
|
||||
|
||||
item.innerHTML = `
|
||||
<span class="wrapper-item-text">${escapeHtml(entry.arg)}</span>
|
||||
<div class="wrapper-item-condition">
|
||||
<select data-index="${index}">
|
||||
<option value="server"${entry.condition === 'server' ? ' selected' : ''}>${serverLabel}</option>
|
||||
<option value="always"${entry.condition === 'always' ? ' selected' : ''}>${alwaysLabel}</option>
|
||||
</select>
|
||||
</div>
|
||||
<button class="wrapper-item-delete" data-index="${index}" title="Remove">
|
||||
<i class="fas fa-trash-alt"></i>
|
||||
</button>
|
||||
`;
|
||||
item.querySelector('select').addEventListener('change', (e) => updateArgCondition(index, e.target.value));
|
||||
item.querySelector('.wrapper-item-delete').addEventListener('click', () => removeInjectArg(index));
|
||||
container.appendChild(item);
|
||||
});
|
||||
}
|
||||
|
||||
async function addStripFlag() {
|
||||
const input = document.getElementById('wrapperAddFlagInput');
|
||||
if (!input || !_wrapperConfig) return;
|
||||
|
||||
const flag = input.value.trim();
|
||||
if (!flag) return;
|
||||
|
||||
if (_wrapperConfig.stripFlags.includes(flag)) {
|
||||
const msg = window.i18n ? window.i18n.t('notifications.wrapperFlagExists') : 'This flag is already in the list';
|
||||
showNotification(msg, 'error');
|
||||
return;
|
||||
}
|
||||
|
||||
_wrapperConfig.stripFlags.push(flag);
|
||||
input.value = '';
|
||||
renderStripFlagsList();
|
||||
await saveWrapperConfigToBackend();
|
||||
await updateWrapperPreview();
|
||||
}
|
||||
|
||||
async function removeStripFlag(index) {
|
||||
if (!_wrapperConfig) return;
|
||||
_wrapperConfig.stripFlags.splice(index, 1);
|
||||
renderStripFlagsList();
|
||||
await saveWrapperConfigToBackend();
|
||||
await updateWrapperPreview();
|
||||
}
|
||||
|
||||
async function addInjectArg() {
|
||||
const input = document.getElementById('wrapperAddArgInput');
|
||||
const condSelect = document.getElementById('wrapperAddArgCondition');
|
||||
if (!input || !condSelect || !_wrapperConfig) return;
|
||||
|
||||
const arg = input.value.trim();
|
||||
if (!arg) return;
|
||||
|
||||
const exists = _wrapperConfig.injectArgs.some(e => e.arg === arg);
|
||||
if (exists) {
|
||||
const msg = window.i18n ? window.i18n.t('notifications.wrapperArgExists') : 'This argument is already in the list';
|
||||
showNotification(msg, 'error');
|
||||
return;
|
||||
}
|
||||
|
||||
_wrapperConfig.injectArgs.push({ arg, condition: condSelect.value });
|
||||
input.value = '';
|
||||
renderInjectArgsList();
|
||||
await saveWrapperConfigToBackend();
|
||||
await updateWrapperPreview();
|
||||
}
|
||||
|
||||
async function removeInjectArg(index) {
|
||||
if (!_wrapperConfig) return;
|
||||
_wrapperConfig.injectArgs.splice(index, 1);
|
||||
renderInjectArgsList();
|
||||
await saveWrapperConfigToBackend();
|
||||
await updateWrapperPreview();
|
||||
}
|
||||
|
||||
async function updateArgCondition(index, condition) {
|
||||
if (!_wrapperConfig || !_wrapperConfig.injectArgs[index]) return;
|
||||
_wrapperConfig.injectArgs[index].condition = condition;
|
||||
await saveWrapperConfigToBackend();
|
||||
await updateWrapperPreview();
|
||||
}
|
||||
|
||||
async function saveWrapperConfigToBackend() {
|
||||
try {
|
||||
const result = await window.electronAPI.saveWrapperConfig(_wrapperConfig);
|
||||
if (!result || !result.success) {
|
||||
throw new Error(result?.error || 'Save failed');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error saving wrapper config:', error);
|
||||
const msg = window.i18n ? window.i18n.t('notifications.wrapperConfigSaveFailed') : 'Failed to save wrapper configuration';
|
||||
showNotification(msg, 'error');
|
||||
}
|
||||
}
|
||||
|
||||
function setupWrapperEventListeners() {
|
||||
const addFlagBtn = document.getElementById('wrapperAddFlagBtn');
|
||||
const addFlagInput = document.getElementById('wrapperAddFlagInput');
|
||||
const addArgBtn = document.getElementById('wrapperAddArgBtn');
|
||||
const addArgInput = document.getElementById('wrapperAddArgInput');
|
||||
const restoreBtn = document.getElementById('wrapperRestoreDefaultsBtn');
|
||||
const previewToggle = document.getElementById('wrapperPreviewToggle');
|
||||
|
||||
if (addFlagBtn) addFlagBtn.addEventListener('click', addStripFlag);
|
||||
if (addFlagInput) addFlagInput.addEventListener('keydown', (e) => { if (e.key === 'Enter') addStripFlag(); });
|
||||
if (addArgBtn) addArgBtn.addEventListener('click', addInjectArg);
|
||||
if (addArgInput) addArgInput.addEventListener('keydown', (e) => { if (e.key === 'Enter') addInjectArg(); });
|
||||
|
||||
if (restoreBtn) {
|
||||
restoreBtn.addEventListener('click', () => {
|
||||
const message = window.i18n ? window.i18n.t('confirm.resetWrapperMessage') : 'Are you sure you want to restore defaults? Your custom changes will be lost.';
|
||||
const title = window.i18n ? window.i18n.t('confirm.resetWrapperTitle') : 'Restore Defaults';
|
||||
|
||||
showCustomConfirm(message, title, async () => {
|
||||
try {
|
||||
const result = await window.electronAPI.resetWrapperConfig();
|
||||
if (result && result.success) {
|
||||
_wrapperConfig = result.config;
|
||||
renderStripFlagsList();
|
||||
renderInjectArgsList();
|
||||
await updateWrapperPreview();
|
||||
const msg = window.i18n ? window.i18n.t('notifications.wrapperConfigReset') : 'Wrapper configuration restored to defaults';
|
||||
showNotification(msg, 'success');
|
||||
} else {
|
||||
throw new Error(result?.error || 'Reset failed');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error resetting wrapper config:', error);
|
||||
const msg = window.i18n ? window.i18n.t('notifications.wrapperConfigResetFailed') : 'Failed to restore wrapper configuration';
|
||||
showNotification(msg, 'error');
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
if (previewToggle) {
|
||||
previewToggle.addEventListener('click', toggleWrapperPreview);
|
||||
}
|
||||
}
|
||||
|
||||
async function toggleWrapperPreview() {
|
||||
const container = document.getElementById('wrapperPreviewContainer');
|
||||
const chevron = document.getElementById('wrapperPreviewChevron');
|
||||
if (!container) return;
|
||||
|
||||
_wrapperPreviewOpen = !_wrapperPreviewOpen;
|
||||
|
||||
if (_wrapperPreviewOpen) {
|
||||
container.style.display = 'block';
|
||||
if (chevron) chevron.classList.add('expanded');
|
||||
await updateWrapperPreview();
|
||||
} else {
|
||||
container.style.display = 'none';
|
||||
if (chevron) chevron.classList.remove('expanded');
|
||||
}
|
||||
}
|
||||
|
||||
async function updateWrapperPreview() {
|
||||
if (!_wrapperPreviewOpen || !_wrapperConfig) return;
|
||||
|
||||
const previewEl = document.getElementById('wrapperPreviewContent');
|
||||
if (!previewEl) return;
|
||||
|
||||
try {
|
||||
const platform = await window.electronAPI.getCurrentPlatform();
|
||||
const script = await window.electronAPI.previewWrapperScript(_wrapperConfig, platform);
|
||||
previewEl.textContent = script;
|
||||
} catch (error) {
|
||||
previewEl.textContent = 'Error generating preview: ' + error.message;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user