installer: auto-run port check on 3-5 and auto-install on 4-2

3-5 포트포워딩 점검에 진입하면 즉시 점검을 시작하고, 버튼은 "재점검"으로 다시 돌릴 수 있게 한다. 4-2 클라이언트 설치도 진입과 동시에 자동 실행되어 사용자가 따로 버튼을 누를 필요가 없다.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
2026-05-13 00:58:24 +09:00
parent d630c90862
commit c2fb7d03a6

View File

@@ -431,32 +431,46 @@ function renderSubStep35(host, back, done) {
'<h3>3-5. 포트포워딩 점검</h3>' + '<h3>3-5. 포트포워딩 점검</h3>' +
'<p class="formMessage">서버의 외부 접근 가능 여부를 확인합니다. UPnP를 시도해도 안 되면 직접 포트포워딩을 안내합니다.</p>' + '<p class="formMessage">서버의 외부 접근 가능 여부를 확인합니다. UPnP를 시도해도 안 되면 직접 포트포워딩을 안내합니다.</p>' +
'<div class="fieldset"><label>포트 <input id="port" type="text" value="25565" /></label></div>' + '<div class="fieldset"><label>포트 <input id="port" type="text" value="25565" /></label></div>' +
'<button class="secondaryBtn" id="run">검사 시작</button>' + '<button class="secondaryBtn" id="run">재점검</button>' +
'<div class="formMessage" id="resultMsg"></div>' + '<div class="formMessage" id="resultMsg"></div>' +
'<div class="actionRow"><button class="secondaryBtn" id="back">이전</button><button class="primaryBtn" id="next" disabled>다음</button></div>' '<div class="actionRow"><button class="secondaryBtn" id="back">이전</button><button class="primaryBtn" id="next" disabled>다음</button></div>'
var resultMsg = host.querySelector('#resultMsg') var resultMsg = host.querySelector('#resultMsg')
var nextBtn = host.querySelector('#next') var nextBtn = host.querySelector('#next')
if (state.serverInstall.portStatus) nextBtn.disabled = false var runBtn = host.querySelector('#run')
host.querySelector('#back').addEventListener('click', back) host.querySelector('#back').addEventListener('click', back)
host.querySelector('#run').addEventListener('click', async function () {
var port = Number(host.querySelector('#port').value) || 25565 async function runCheck() {
runBtn.disabled = true
resultMsg.classList.remove('success', 'warn', 'error')
resultMsg.textContent = '확인 중...' resultMsg.textContent = '확인 중...'
var result = await installerApi.checkPortForward(port) var port = Number(host.querySelector('#port').value) || 25565
state.serverInstall.portStatus = result try {
if (result.status === 'preForwarded') { var result = await installerApi.checkPortForward(port)
resultMsg.innerHTML = '이미 외부 접속 가능: ' + result.externalIp + ':' + result.port state.serverInstall.portStatus = result
resultMsg.classList.add('success') if (result.status === 'preForwarded') {
} else if (result.status === 'upnpOk') { resultMsg.innerHTML = '이미 외부 접속 가능: ' + result.externalIp + ':' + result.port
resultMsg.innerHTML = 'UPnP로 자동 개방 완료: ' + result.externalIp + ':' + result.port resultMsg.classList.add('success')
resultMsg.classList.add('success') } else if (result.status === 'upnpOk') {
} else { resultMsg.innerHTML = 'UPnP로 자동 개방 완료: ' + result.externalIp + ':' + result.port
resultMsg.innerHTML = (result.message || '직접 포트포워딩을 해주세요.') + resultMsg.classList.add('success')
'<br><small>외부 IP: ' + (result.externalIp || '확인 불가') + ', 포트: ' + result.port + '</small>' } else {
resultMsg.classList.add('warn') resultMsg.innerHTML = (result.message || '직접 포트포워딩을 해주세요.') +
'<br><small>외부 IP: ' + (result.externalIp || '확인 불가') + ', 포트: ' + result.port + '</small>'
resultMsg.classList.add('warn')
}
nextBtn.disabled = false
} catch (err) {
resultMsg.textContent = '점검 실패: ' + (err && err.message ? err.message : err)
resultMsg.classList.add('error')
} finally {
runBtn.disabled = false
} }
nextBtn.disabled = false }
})
runBtn.addEventListener('click', runCheck)
nextBtn.addEventListener('click', done) nextBtn.addEventListener('click', done)
// 페이지 진입 즉시 자동 점검
runCheck()
} }
function renderStep4() { function renderStep4() {
@@ -537,18 +551,23 @@ function renderSubStep42(host, back, done) {
host.innerHTML = host.innerHTML =
'<h3>4-2. 모드/리소스팩 다운로드 및 launcher_profiles 갱신</h3>' + '<h3>4-2. 모드/리소스팩 다운로드 및 launcher_profiles 갱신</h3>' +
'<p class="formMessage">%appdata%\\.mc_custom 에 모드와 리소스팩을 설치하고, launcher_profiles.json에 프로필을 등록합니다.</p>' + '<p class="formMessage">%appdata%\\.mc_custom 에 모드와 리소스팩을 설치하고, launcher_profiles.json에 프로필을 등록합니다.</p>' +
'<button class="primaryBtn" id="run">설치 시작</button>' + '<div class="formMessage" id="msg">설치 중...</div>' +
'<div class="formMessage" id="msg"></div>' +
'<div class="actionRow"><button class="secondaryBtn" id="back">이전</button><button class="primaryBtn" id="next" disabled>다음</button></div>' '<div class="actionRow"><button class="secondaryBtn" id="back">이전</button><button class="primaryBtn" id="next" disabled>다음</button></div>'
var runBtn = host.querySelector('#run')
var msg = host.querySelector('#msg') var msg = host.querySelector('#msg')
var nextBtn = host.querySelector('#next') var nextBtn = host.querySelector('#next')
if (state.client.clientInstalled) nextBtn.disabled = false
host.querySelector('#back').addEventListener('click', back) host.querySelector('#back').addEventListener('click', back)
runBtn.addEventListener('click', async function () { nextBtn.addEventListener('click', done)
runBtn.disabled = true
msg.textContent = '설치 중...' // 이미 설치됐다면 다시 돌리지 않음
msg.classList.remove('error', 'success') if (state.client.clientInstalled) {
msg.textContent = '클라이언트 설치 완료.'
msg.classList.add('success')
nextBtn.disabled = false
return
}
// 페이지 진입 즉시 자동 설치
;(async function () {
try { try {
await installerApi.installClient({ await installerApi.installClient({
packKey: state.selectedPackKey, packKey: state.selectedPackKey,
@@ -559,12 +578,10 @@ function renderSubStep42(host, back, done) {
state.client.clientInstalled = true state.client.clientInstalled = true
nextBtn.disabled = false nextBtn.disabled = false
} catch (err) { } catch (err) {
msg.textContent = '설치 실패: ' + err.message msg.textContent = '설치 실패: ' + (err && err.message ? err.message : err)
msg.classList.add('error') msg.classList.add('error')
runBtn.disabled = false
} }
}) })()
nextBtn.addEventListener('click', done)
} }
function renderSubStep43(host, back, done) { function renderSubStep43(host, back, done) {