Prevent reboot dialog enter reentry
This commit is contained in:
@@ -25,6 +25,7 @@ Control은 라즈베리파이/리눅스 호스트의 팬과 시스템 상태를
|
||||
- WakeLock 버튼으로 대시보드 화면 꺼짐 방지
|
||||
- Reboot 버튼으로 2단계 확인 후 시스템 재부팅 요청
|
||||
- 기본 브라우저 alert/confirm/prompt 대신 대시보드 디자인에 맞춘 custom dialog 사용
|
||||
- custom dialog는 Enter/Escape 키 입력을 자체 처리하며, Reboot 확인 흐름은 중복 실행을 차단
|
||||
- Translate 버튼으로 `en`, `ko` UI 언어 토글. 버튼 표시는 상태 suffix 없이 고정
|
||||
- Theme 버튼으로 `dark`, `light` UI 테마 토글. 버튼 표시는 상태 suffix 없이 고정
|
||||
|
||||
@@ -150,7 +151,7 @@ control-wifi-observe.service
|
||||
6. `control-wifi-observe.timer`는 사용자 접속과 무관하게 10초마다 5G 관측 세션을 갱신합니다.
|
||||
7. Push 등록은 권한 요청과 구독 저장이 끝나면 즉시 상태를 갱신합니다.
|
||||
8. WakeLock 버튼은 활성 상태를 초록색 버튼으로 표시합니다.
|
||||
9. Reboot 버튼은 `재부팅` 단어 입력과 관리자 암호 재입력을 모두 통과한 뒤 서버 API로 재부팅을 요청합니다.
|
||||
9. Reboot 버튼은 `재부팅` 단어 입력과 관리자 암호 재입력을 모두 통과한 뒤 서버 API로 재부팅을 요청합니다. 확인 단어 입력창에서 Enter를 눌러도 같은 Reboot 흐름이 다시 열리지 않도록 키 이벤트 기본 동작과 중복 실행을 차단합니다.
|
||||
10. Translate 버튼은 최초 접속 시 디바이스 언어를 기본값으로 사용하고, 변경값은 `localStorage`의 `controlLang`에 저장합니다. 라벨은 `Translate` 또는 `번역`으로만 표시합니다.
|
||||
11. Theme 버튼은 기본값 `dark`로 시작하고, 변경값은 `localStorage`의 `controlTheme`에 저장합니다. 라벨은 `Theme` 또는 `테마`로만 표시합니다.
|
||||
12. 시스템 상태는 `vcgencmd get_throttled`를 읽어 현재 저전압 여부와 부팅 후 이력, 최근 감지 시각, 현재/최근 지속시간을 표시합니다.
|
||||
|
||||
+18
-3
@@ -66,6 +66,7 @@
|
||||
wsReconnectTimer: null,
|
||||
wsReconnectDelay: 1000,
|
||||
pushDevicesLastRefresh: 0,
|
||||
rebootRequesting: false,
|
||||
lang: 'en',
|
||||
theme: 'dark',
|
||||
};
|
||||
@@ -513,8 +514,17 @@
|
||||
if (event.target === layer) onCancel();
|
||||
};
|
||||
const onKeydown = event => {
|
||||
if (event.key === 'Escape') onCancel();
|
||||
if (event.key === 'Enter' && (document.activeElement === input || !needsInput)) onOk();
|
||||
if (event.key === 'Escape') {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
onCancel();
|
||||
return;
|
||||
}
|
||||
if (event.key === 'Enter' && (document.activeElement === input || !needsInput)) {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
onOk();
|
||||
}
|
||||
};
|
||||
|
||||
els.customDialogTitle.textContent = options.title || t('dialogConfirm');
|
||||
@@ -1576,6 +1586,10 @@
|
||||
}
|
||||
|
||||
async function requestReboot() {
|
||||
if (state.rebootRequesting) return;
|
||||
state.rebootRequesting = true;
|
||||
|
||||
try {
|
||||
const phrase = await window.customPrompt(t('rebootPrompt'), {
|
||||
title: t('rebootTitle'),
|
||||
okText: t('next'),
|
||||
@@ -1603,7 +1617,6 @@
|
||||
|
||||
if (password === null) return;
|
||||
|
||||
try {
|
||||
els.rebootBtn.disabled = true;
|
||||
notice(t('rebootSending'), 'info');
|
||||
await api('reboot', {
|
||||
@@ -1621,6 +1634,8 @@
|
||||
title: t('rebootFailed'),
|
||||
danger: true,
|
||||
});
|
||||
} finally {
|
||||
state.rebootRequesting = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -319,7 +319,7 @@ html[data-theme="light"] .btn.secondary{background:#d9e2ef;color:#172033}html[da
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script src="/assets/app.js?v=20260607_prefs1"></script>
|
||||
<script src="/assets/app.js?v=20260617_reboot_enter1"></script>
|
||||
<script src="/assets/wakelock.js?v=20260607_prefs1"></script>
|
||||
<script src="/push_subscribe.js?v=20260607_prefs1"></script>
|
||||
<?php endif; ?>
|
||||
|
||||
Reference in New Issue
Block a user