diff --git a/server/static/auto.js b/server/static/auto.js index 2a46ad7..a90707d 100644 --- a/server/static/auto.js +++ b/server/static/auto.js @@ -244,7 +244,7 @@ function renderCutPanel(box,panelId,data,opts){ /* ── 컷별 선택 ── 카드는 '어느 컷 소속'인지가 배치를 정한다. selCut[hlId][idx] = 컷 인덱스. sel[hlId] 는 항상 컷 순서로 정렬해 둔다 (업로드 순서 = 배치 순서라서). */ -const selCut={}; +let selCut={}; function sortSel(hlId){ const m=selCut[hlId]||{}; sel[hlId].sort((a,b)=>(m[a]??999)-(m[b]??999)); @@ -732,10 +732,30 @@ function updatePrepStep(ev){ if(ev.detail){const d=el.querySelector(".sdetail");d.hidden=false;d.textContent=ev.detail;}} } +/* ── 검토는 한 번에 하나 ── + byIdx/sel/selCut 는 탭(auto/yt/paste) 구분 없는 전역 상태다. 세 result 핸들러가 + 전부 byIdx={} 로 전역 리셋하면서 sel/selCut 은 자기 키만 건드리면, 다른 탭이 + 그려둔 카드가 방금 리셋된 byIdx/sel 을 참조해 "엉뚱한 댓글을 가리킴"·"ID n 사용중" + 오표시·클릭 시 TypeError(toggle()의 list.indexOf, sel[hlId]가 undefined)가 난다. + → 새 결과가 오면 sel/selCut 도 전역 리셋하고, 다른 탭의 검토 DOM·빌드 버튼까지 + 지워 클릭 경로 자체를 없앤다. */ +const PANEL_DOM={auto:{review:"#autoReview",build:"#autoBuild"}, + yt:{review:"#ytReview",build:"#ytBuild"}, + paste:{review:"#pasteReview",build:"#pasteBuild"}}; +function clearOtherPanels(exceptId){ + for(const id in PANEL_DOM){ + if(id===exceptId) continue; + const d=PANEL_DOM[id]; + const r=$(d.review); if(r) r.innerHTML=""; + const b=$(d.build); if(b) b.style.display="none"; + } +} + /* ── 2차 검토 화면 — 지금까지와 같은 ID별 탭 + renderCutPanel(컷별 댓글 섹션). ── 준비(prepare)를 마친 ID만 온다 — 실패한 ID는 경고 로그로만 알린다(탭 자체가 없음). */ function onPrepareResult(ev){ P=ev;byIdx={};sel={};selCut={};curId=null; + clearOtherPanels("auto"); (ev.comments||[]).forEach(c=>{byIdx[c.idx]=c;}); (ev.warnings||[]).forEach(w=>prepLog("⚠️ "+w)); const R=$("#autoReview");R.innerHTML=""; @@ -978,7 +998,9 @@ function ytFail(m){ytLog("⚠️ "+m);ytDone();} (channel 은 유튜브에서 자동인식됐을 수 있음) 여기서 입력칸에 반영해 보여준다 — 사용자가 여기서 또 고치면 그 값이 생성(ytBuildAll)에 그대로 실린다. */ function onYtResult(ev){ - byIdx={};(ev.comments||[]).forEach(c=>{byIdx[c.idx]=c;}); + byIdx={};sel={};selCut={};curId=null; // 검토는 한 번에 하나 — 다른 탭 선택 상태까지 전부 리셋 + clearOtherPanels("yt"); + (ev.comments||[]).forEach(c=>{byIdx[c.idx]=c;}); (ev.warnings||[]).forEach(w=>ytLog("⚠️ "+w)); if(ev.title_top!=null) $("#yttop").value=ev.title_top; if(ev.title_main!=null) $("#ytmain").value=ev.title_main; @@ -1136,7 +1158,9 @@ function pasteFail(m){pasteLog("⚠️ "+m);pasteDone();} expandAllCuts·refreshSel 이 전부 "#hlbox-"+panelId 로 찾으므로 id를 정확히 맞춰야 한다 (yt 탭의 #hlbox-yt 와 동일한 방식). */ function onPasteResult(ev){ - byIdx={};(ev.comments||[]).forEach(c=>{byIdx[c.idx]=c;}); + byIdx={};sel={};selCut={};curId=null; // 검토는 한 번에 하나 — 다른 탭 선택 상태까지 전부 리셋 + clearOtherPanels("paste"); + (ev.comments||[]).forEach(c=>{byIdx[c.idx]=c;}); (ev.warnings||[]).forEach(w=>pasteLog("⚠️ "+w)); PASTE_HL={id:"paste",need:ev.need,cuts:ev.cuts,paste:{cuts:ev.cutRanges}}; sel["paste"]=[];selCut["paste"]={};