diff --git a/installer-rp/renderer.js b/installer-rp/renderer.js index 5e789cb..4cb0bdc 100644 --- a/installer-rp/renderer.js +++ b/installer-rp/renderer.js @@ -226,8 +226,12 @@ function renderAgreementWithKinds(KINDS) { // 새 약관 페이지는 화면 맨 위에서부터 보이도록 스크롤을 올린다. if (pageHost) pageHost.scrollTop = 0 + // 약관 본문이 정상 로드된 뒤에만 동의를 허용한다. 로드 실패 상태에서는 + // 스크롤을 해도 동의 체크가 켜지지 않는다("무조건 약관을 읽도록"). + var termLoaded = false + function markReadable() { - if (!accept.disabled) return + if (!termLoaded || !accept.disabled) return accept.disabled = false hint.textContent = '' } @@ -257,6 +261,7 @@ function renderAgreementWithKinds(KINDS) { }) function afterLoad() { + termLoaded = true body.scrollTop = 0 if (accepted[k.id]) { accept.disabled = false @@ -270,15 +275,31 @@ function renderAgreementWithKinds(KINDS) { }, 0) } - if (cache[k.id]) { - body.innerHTML = cache[k.id] - afterLoad() - } else { + // 약관 본문 로드 실패: 동의 불가 상태를 유지하고 다시 시도만 허용한다. + function showLoadError(message) { + termLoaded = false + accept.disabled = true + accept.checked = false + accepted[k.id] = false + nextBtn.disabled = true + hint.textContent = tt('agreement.readToBottom') + body.innerHTML = + '
' + escapeHtml(tt('agreement.loadFailed', { message: message || '' })) + '
' + + '' + var retry = section.querySelector('#agRetry') + if (retry) retry.addEventListener('click', loadTerm) + } + + function loadTerm() { + if (cache[k.id]) { + body.innerHTML = cache[k.id] + afterLoad() + return + } body.textContent = tt('agreement.loading') api.getTerm(k.id).then(function (res) { if (!res.ok) { - body.innerHTML = '' + escapeHtml(tt('agreement.loadFailed', { message: res.message || '' })) + '
' - markReadable() + showLoadError(res.message || '') return } var html = renderTermsMarkdown(res.content || '') @@ -286,10 +307,11 @@ function renderAgreementWithKinds(KINDS) { body.innerHTML = html afterLoad() }).catch(function (err) { - body.innerHTML = '' + escapeHtml(tt('agreement.loadFailed', { message: err.message })) + '
' - markReadable() + showLoadError(err && err.message ? err.message : '') }) } + + loadTerm() } renderCurrent() diff --git a/installer/renderer.js b/installer/renderer.js index 6da0a9a..eb56145 100644 --- a/installer/renderer.js +++ b/installer/renderer.js @@ -266,8 +266,12 @@ function renderAgreementWithKinds(KINDS) { // 새 약관 페이지는 화면 맨 위에서부터 보이도록 스크롤을 올린다. if (pageHost) pageHost.scrollTop = 0 + // 약관 본문이 정상 로드된 뒤에만 동의를 허용한다. 로드 실패 상태에서는 + // 스크롤을 해도 동의 체크가 켜지지 않는다("무조건 약관을 읽도록"). + var termLoaded = false + function markReadable() { - if (!accept.disabled) return + if (!termLoaded || !accept.disabled) return accept.disabled = false hint.textContent = '' } @@ -298,6 +302,7 @@ function renderAgreementWithKinds(KINDS) { }) function afterLoad() { + termLoaded = true body.scrollTop = 0 // 이미 동의했던 약관으로 되돌아온 경우: 체크/다음 활성화 유지. if (accepted[k.id]) { @@ -313,15 +318,31 @@ function renderAgreementWithKinds(KINDS) { }, 0) } - if (cache[k.id]) { - body.innerHTML = cache[k.id] - afterLoad() - } else { + // 약관 본문 로드 실패: 동의 불가 상태를 유지하고 다시 시도만 허용한다. + function showLoadError(message) { + termLoaded = false + accept.disabled = true + accept.checked = false + accepted[k.id] = false + nextBtn.disabled = true + hint.textContent = tt('agreement.readToBottom') + body.innerHTML = + '' + tt('agreement.loadFailed', { message: message || '' }) + '
' + + '' + var retry = section.querySelector('#agRetry') + if (retry) retry.addEventListener('click', loadTerm) + } + + function loadTerm() { + if (cache[k.id]) { + body.innerHTML = cache[k.id] + afterLoad() + return + } body.textContent = tt('agreement.loading') installerApi.getTerm(k.id).then(function (res) { if (!res.ok) { - body.innerHTML = '' + tt('agreement.loadFailed', { message: res.message || '' }) + '
' - markReadable() + showLoadError(res.message || '') return } var html = renderTermsMarkdown(res.content || '') @@ -329,10 +350,11 @@ function renderAgreementWithKinds(KINDS) { body.innerHTML = html afterLoad() }).catch(function (err) { - body.innerHTML = '' + tt('agreement.loadFailed', { message: err.message }) + '
' - markReadable() + showLoadError(err && err.message ? err.message : '') }) } + + loadTerm() } renderCurrent() diff --git a/package.json b/package.json index cc30d96..a70ce44 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "minecraft-music-quiz-installer", - "version": "0.4.1", + "version": "0.4.2", "description": "마인크래프트 음악퀴즈 간편설치기 + 관리 사이트", "main": "dist/installer/main.js", "scripts": {