From 06b35abcb1910bf54564e7be00aa7e6fd305d4e8 Mon Sep 17 00:00:00 2001 From: claude-bot Date: Mon, 18 May 2026 00:00:29 +0900 Subject: [PATCH] installer: split host/participant choice into its own tab MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Previously the multi-mode role pick appeared as a sub-section that expanded inline under the single/multi cards. Per request, separate it into a dedicated page reached by pressing Next on the mode tab. - renderStep2 now only handles mode selection (single/multi). Next routes single → step4 directly, multi → renderStep2Role. - New renderStep2Role shows the host/participant cards on its own page with back to renderStep2. Next routes host → step3, participant → step4. - backToPrevStep in step4 and the back from sub31 in step3 updated so the role tab is the correct intermediate landing for multi flows. Co-Authored-By: Claude Opus 4.7 --- installer/renderer.js | 88 +++++++++++++++++++++++++------------------ 1 file changed, 51 insertions(+), 37 deletions(-) diff --git a/installer/renderer.js b/installer/renderer.js index 460e27e..87c25f3 100644 --- a/installer/renderer.js +++ b/installer/renderer.js @@ -159,19 +159,10 @@ function renderStep2() { '' + '' + '' + - '' + '
' pageHost.appendChild(section) var nextBtn = section.querySelector('#next') var modeButtons = section.querySelectorAll('[data-mode]') - var roleSection = section.querySelector('#roleSection') - var roleButtons = section.querySelectorAll('[data-role]') function applyMode(mode) { state.mode = mode @@ -179,18 +170,50 @@ function renderStep2() { if (btn.getAttribute('data-mode') === mode) btn.classList.add('selected') else btn.classList.remove('selected') }) - if (mode === 'multi') { - roleSection.hidden = false - // 역할이 이미 골라져 있으면 그대로, 아니면 사용자가 골라야 next 활성화. - nextBtn.disabled = !state.role - } else { - roleSection.hidden = true - state.role = null - roleButtons.forEach(function (btn) { btn.classList.remove('selected') }) - nextBtn.disabled = false - } + nextBtn.disabled = false + // 모드가 바뀌면 이전에 골랐던 역할은 의미가 없어진다. 멀티→싱글 전환 시 잔존하던 + // role 이 다음 단계 분기에 영향 주지 않도록 명시적으로 초기화. + if (mode !== 'multi') state.role = null } + modeButtons.forEach(function (btn) { + btn.addEventListener('click', function () { + applyMode(btn.getAttribute('data-mode')) + }) + }) + + if (state.mode === 'single' || state.mode === 'multi') { + applyMode(state.mode) + } + + nextBtn.addEventListener('click', function () { + if (!state.mode) return + state.stepDone[2] = true + // 멀티는 호스트/참가자 선택 탭을 거친다. 싱글은 곧장 클라이언트(step4) 로. + if (state.mode === 'multi') renderStep2Role() + else renderStep4() + }) + section.querySelector('#back').addEventListener('click', renderStep1) +} + +function renderStep2Role() { + // 스텝 인디케이터는 여전히 2 단계 안쪽이다 — 호스트/참가자 선택은 모드 선택의 + // 하위 결정이기 때문. 별도 탭으로 분리해서 한 화면에 한 결정만 보이도록 한다. + setActiveStep(2) + clearPage() + var section = document.createElement('section') + section.className = 'page' + section.innerHTML = + '

' + tt('step2.roleHeading') + '

' + + '
' + + '' + + '' + + '
' + + '
' + pageHost.appendChild(section) + var nextBtn = section.querySelector('#next') + var roleButtons = section.querySelectorAll('[data-role]') + function applyRole(role) { state.role = role roleButtons.forEach(function (btn) { @@ -200,32 +223,21 @@ function renderStep2() { nextBtn.disabled = false } - modeButtons.forEach(function (btn) { - btn.addEventListener('click', function () { - applyMode(btn.getAttribute('data-mode')) - }) - }) roleButtons.forEach(function (btn) { btn.addEventListener('click', function () { applyRole(btn.getAttribute('data-role')) }) }) - if (state.mode === 'single' || state.mode === 'multi') { - applyMode(state.mode) - if (state.mode === 'multi' && state.role) applyRole(state.role) - } + if (state.role === 'host' || state.role === 'participant') applyRole(state.role) nextBtn.addEventListener('click', function () { - if (!state.mode) return - if (state.mode === 'multi' && !state.role) return - state.stepDone[2] = true - // 멀티+호스트 만 서버 설치(step3) 를 거친다. - // 싱글, 멀티+참가자 는 곧장 클라이언트(step4) 로. - if (state.mode === 'multi' && state.role === 'host') renderStep3() + if (!state.role) return + // 호스트는 서버 설치(step3) 부터, 참가자는 클라이언트(step4) 로 바로. + if (state.role === 'host') renderStep3() else renderStep4() }) - section.querySelector('#back').addEventListener('click', renderStep1) + section.querySelector('#back').addEventListener('click', renderStep2) } function renderStep3() { @@ -239,7 +251,8 @@ function renderStep3() { pageHost.appendChild(section) var subHost = section.querySelector('#subHost') - function show31() { subHost.innerHTML = ''; renderSubStep31(subHost, renderStep2, show32) } + // step3 는 멀티+호스트 만 진입하므로 sub31 의 back 은 역할 선택 탭으로. + function show31() { subHost.innerHTML = ''; renderSubStep31(subHost, renderStep2Role, show32) } function show32() { subHost.innerHTML = ''; renderSubStep32(subHost, show31, show33) } function show33() { subHost.innerHTML = ''; renderSubStep33(subHost, show32, show34) } function show34() { subHost.innerHTML = ''; renderSubStep34(subHost, show33, show35) } @@ -629,9 +642,10 @@ function renderStep4() { state.client.installPlatform = platformType !== 'vanilla' // 멀티+호스트 만 step3 (서버 설치) 를 거쳤으므로 거기로 돌아간다. - // 싱글 / 멀티+참가자 는 step2 로 되돌아간다. + // 멀티+참가자 는 직전 화면이 역할 선택 탭이므로 거기로, 싱글은 모드 탭으로. function backToPrevStep() { if (state.mode === 'multi' && state.role === 'host') renderStep3() + else if (state.mode === 'multi') renderStep2Role() else renderStep2() }