터치 디스플레이 설정 관리 추가
This commit is contained in:
+149
-2
@@ -199,6 +199,25 @@
|
||||
settingsSaveFailed: 'settings save failed',
|
||||
settingsResetConfirm: 'Reset all Control settings to defaults?',
|
||||
settingsDefault: 'default',
|
||||
touchDisplaySettings: 'Touch Display',
|
||||
touchDisplayStatus: 'Status',
|
||||
touchDisplayDetected: 'Detected',
|
||||
touchDisplayConnected: 'Connected',
|
||||
touchDisplayMode: 'Mode',
|
||||
touchDisplayFramebuffer: 'Framebuffer',
|
||||
touchDisplayOverlay: 'Manual overlay',
|
||||
touchDisplayAutoDetect: 'Auto detect',
|
||||
touchDisplayEnabled: 'LCD output',
|
||||
touchInputEnabled: 'Touch input',
|
||||
touchRotation: 'Console rotation',
|
||||
touchInvx: 'Invert X',
|
||||
touchInvy: 'Invert Y',
|
||||
touchSwapxy: 'Swap X/Y',
|
||||
touchSizeX: 'Touch X size',
|
||||
touchSizeY: 'Touch Y size',
|
||||
touchDisplaySave: 'Save display boot settings',
|
||||
touchDisplaySaved: 'Display settings saved. Reboot is required.',
|
||||
touchDisplayNoChange: 'Display settings already match.',
|
||||
rebootButton: 'Reboot',
|
||||
dialogAlert: 'Alert',
|
||||
dialogConfirm: 'Confirm',
|
||||
@@ -351,6 +370,25 @@
|
||||
settingsSaveFailed: '설정 저장 실패',
|
||||
settingsResetConfirm: 'Control 설정을 모두 기본값으로 되돌릴까요?',
|
||||
settingsDefault: '기본값',
|
||||
touchDisplaySettings: '터치 디스플레이',
|
||||
touchDisplayStatus: '상태',
|
||||
touchDisplayDetected: '인식',
|
||||
touchDisplayConnected: '연결',
|
||||
touchDisplayMode: '모드',
|
||||
touchDisplayFramebuffer: '프레임버퍼',
|
||||
touchDisplayOverlay: '수동 overlay',
|
||||
touchDisplayAutoDetect: '자동 감지',
|
||||
touchDisplayEnabled: 'LCD 출력',
|
||||
touchInputEnabled: '터치 입력',
|
||||
touchRotation: '콘솔 회전',
|
||||
touchInvx: '터치 X 반전',
|
||||
touchInvy: '터치 Y 반전',
|
||||
touchSwapxy: '터치 X/Y 교환',
|
||||
touchSizeX: '터치 X 크기',
|
||||
touchSizeY: '터치 Y 크기',
|
||||
touchDisplaySave: '디스플레이 부팅 설정 저장',
|
||||
touchDisplaySaved: '디스플레이 설정을 저장했습니다. 재부팅이 필요합니다.',
|
||||
touchDisplayNoChange: '디스플레이 설정이 이미 동일합니다.',
|
||||
rebootButton: '재부팅',
|
||||
dialogAlert: '알림',
|
||||
dialogConfirm: '확인',
|
||||
@@ -645,6 +683,85 @@
|
||||
return `setting-${String(key).replace(/[^A-Za-z0-9_-]/g, '-')}`;
|
||||
}
|
||||
|
||||
function displayDomId(key) {
|
||||
return `touch-display-${String(key).replace(/[^A-Za-z0-9_-]/g, '-')}`;
|
||||
}
|
||||
|
||||
function boolLabel(value) {
|
||||
return value ? 'ON' : 'OFF';
|
||||
}
|
||||
|
||||
function renderTouchDisplaySettings(display) {
|
||||
if (!display || !display.config) return '';
|
||||
const config = display.config || {};
|
||||
const statusRows = [
|
||||
[t('touchDisplayDetected'), boolLabel(!!display.detected)],
|
||||
[t('touchDisplayConnected'), `${display.status || 'unknown'} / ${display.enabled_state || 'unknown'} / ${display.dpms || 'unknown'}`],
|
||||
[t('touchDisplayMode'), display.current_mode || '-'],
|
||||
[t('touchDisplayFramebuffer'), display.framebuffer || '-'],
|
||||
[t('touchDisplayAutoDetect'), boolLabel(!!config.display_auto_detect)],
|
||||
[t('touchDisplayOverlay'), boolLabel(!!config.manual_overlay)],
|
||||
];
|
||||
const checkboxField = (key, label, checked) => {
|
||||
const id = escapeHtml(displayDomId(key));
|
||||
return `
|
||||
<div class="settings-field">
|
||||
<span class="settings-label"><span>${escapeHtml(label)}</span><span></span></span>
|
||||
<span class="settings-control">
|
||||
<span class="settings-toggle">
|
||||
<input id="${id}" data-display-key="${escapeHtml(key)}" type="checkbox" value="1" autocomplete="off" ${checked ? 'checked' : ''}>
|
||||
<span class="settings-toggle-on">켜기</span>
|
||||
<span class="settings-toggle-off">끄기</span>
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
`;
|
||||
};
|
||||
const numberField = (key, label, value, min, max, step = 1) => `
|
||||
<div class="settings-field">
|
||||
<span class="settings-label"><span>${escapeHtml(label)}</span><span></span></span>
|
||||
<span class="settings-control">
|
||||
<input id="${escapeHtml(displayDomId(key))}" data-display-key="${escapeHtml(key)}" type="number" min="${min}" max="${max}" step="${step}" autocomplete="off" value="${escapeHtml(value)}">
|
||||
</span>
|
||||
</div>
|
||||
`;
|
||||
|
||||
return `
|
||||
<section class="settings-group touch-display-settings">
|
||||
<h4>${escapeHtml(t('touchDisplaySettings'))}</h4>
|
||||
<div class="touch-display-status">
|
||||
${statusRows.map(([key, value]) => `
|
||||
<div><span>${escapeHtml(key)}</span><strong>${escapeHtml(value)}</strong></div>
|
||||
`).join('')}
|
||||
</div>
|
||||
<div class="settings-grid">
|
||||
<div class="settings-field">
|
||||
<span class="settings-label"><span>${escapeHtml(t('touchRotation'))}</span><span>deg</span></span>
|
||||
<span class="settings-control">
|
||||
<select data-display-key="rotation" class="settings-select" autocomplete="off">
|
||||
${[0, 90, 180, 270].map(value => `
|
||||
<option value="${value}" ${Number(config.rotation || 0) === value ? 'selected' : ''}>${value}</option>
|
||||
`).join('')}
|
||||
</select>
|
||||
</span>
|
||||
</div>
|
||||
${checkboxField('manual_overlay', t('touchDisplayOverlay'), !!config.manual_overlay)}
|
||||
${checkboxField('display_enabled', t('touchDisplayEnabled'), !!config.display_enabled)}
|
||||
${checkboxField('touch_enabled', t('touchInputEnabled'), !!config.touch_enabled)}
|
||||
${checkboxField('touch_invx', t('touchInvx'), !!config.touch_invx)}
|
||||
${checkboxField('touch_invy', t('touchInvy'), !!config.touch_invy)}
|
||||
${checkboxField('touch_swapxy', t('touchSwapxy'), !!config.touch_swapxy)}
|
||||
${numberField('touch_sizex', t('touchSizeX'), config.touch_sizex || 800, 100, 4096)}
|
||||
${numberField('touch_sizey', t('touchSizeY'), config.touch_sizey || 480, 100, 4096)}
|
||||
</div>
|
||||
<div class="settings-inline-actions">
|
||||
<button id="touchDisplaySave" class="btn" type="button">${escapeHtml(t('touchDisplaySave'))}</button>
|
||||
<span class="settings-note">/boot/firmware/config.txt, /boot/firmware/cmdline.txt</span>
|
||||
</div>
|
||||
</section>
|
||||
`;
|
||||
}
|
||||
|
||||
function renderSettings(payload = state.settingsPayload, options = {}) {
|
||||
if (!els.settingsBody || !payload) return;
|
||||
if (state.settingsOpen && state.settingsDirty && !options.force) return;
|
||||
@@ -718,7 +835,7 @@
|
||||
return item.default ?? '';
|
||||
};
|
||||
|
||||
els.settingsBody.innerHTML = Object.entries(byGroup).map(([group, items]) => `
|
||||
els.settingsBody.innerHTML = renderTouchDisplaySettings(payload.touch_display) + Object.entries(byGroup).map(([group, items]) => `
|
||||
<section class="settings-group">
|
||||
<h4>${escapeHtml(groups[group] || group)}</h4>
|
||||
<div class="settings-grid">
|
||||
@@ -737,7 +854,7 @@
|
||||
</div>
|
||||
</section>
|
||||
`).join('');
|
||||
els.settingsBody.querySelectorAll('[data-setting-key]').forEach(input => {
|
||||
els.settingsBody.querySelectorAll('[data-setting-key],[data-display-key]').forEach(input => {
|
||||
input.addEventListener('input', () => {
|
||||
state.settingsDirty = true;
|
||||
});
|
||||
@@ -757,6 +874,7 @@
|
||||
input.dispatchEvent(new Event('change'));
|
||||
});
|
||||
});
|
||||
$('#touchDisplaySave', els.settingsBody)?.addEventListener('click', saveTouchDisplaySettings);
|
||||
}
|
||||
|
||||
function settingByKey(key, fallback = null) {
|
||||
@@ -797,6 +915,35 @@
|
||||
return values;
|
||||
}
|
||||
|
||||
function currentTouchDisplayFormValues() {
|
||||
const values = {};
|
||||
els.settingsBody?.querySelectorAll('[data-display-key]').forEach(input => {
|
||||
values[input.dataset.displayKey] = input.type === 'checkbox'
|
||||
? (input.checked ? '1' : '0')
|
||||
: input.value;
|
||||
});
|
||||
return values;
|
||||
}
|
||||
|
||||
async function saveTouchDisplaySettings() {
|
||||
if (!await window.customConfirm('디스플레이 부팅 설정을 저장할까요? 저장 후 재부팅해야 적용됩니다.', { title: t('touchDisplaySettings') })) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const data = await api('touch_display_save', {
|
||||
display: JSON.stringify(currentTouchDisplayFormValues()),
|
||||
});
|
||||
state.settingsDirty = false;
|
||||
render(data);
|
||||
renderSettings(data.settings, { force: true });
|
||||
const changed = data.touch_display_save?.changed || [];
|
||||
notice(changed.length ? t('touchDisplaySaved') : t('touchDisplayNoChange'), 'success');
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
notice(e.message || t('settingsSaveFailed'), 'error');
|
||||
}
|
||||
}
|
||||
|
||||
async function saveSettings() {
|
||||
try {
|
||||
const data = await api('settings_save', {
|
||||
|
||||
Reference in New Issue
Block a user