(function () { var op = window.__OP__ || { folderId: null, folderPath: [], isSubFolder: false } var folderPathEnc = (op.folderPath || []).map(encodeURIComponent).join('/') // ── 영상 컨텍스트 메뉴 ─────────────────────────────────────────────── var videoCtxMenu = document.getElementById('ctxMenu') var videoTargetId = null var videoTargetTitle = null var videoTargetShareUrl = null function showVideoCtx(x, y) { videoCtxMenu.style.left = x + 'px' videoCtxMenu.style.top = y + 'px' videoCtxMenu.hidden = false } function hideVideoCtx() { videoCtxMenu.hidden = true } document.querySelectorAll('.adminVideo').forEach(function (card) { card.addEventListener('contextmenu', function (e) { e.preventDefault() videoTargetId = card.getAttribute('data-id') videoTargetTitle = card.getAttribute('data-title') videoTargetShareUrl = card.getAttribute('data-share-url') showVideoCtx(e.clientX, e.clientY) }) }) videoCtxMenu.addEventListener('click', function (e) { var btn = e.target.closest('button') if (!btn || !videoTargetId) return var action = btn.getAttribute('data-action') if (action === 'edit') { location.href = '/op/folder/' + folderPathEnc + '/video/editor?id=' + encodeURIComponent(videoTargetId) } else if (action === 'copyUrl') { copyUrl(location.origin + videoTargetShareUrl) } else if (action === 'rename') { var t = window.prompt('새 영상 제목', videoTargetTitle) if (t && t !== videoTargetTitle) { fetch('/op/videos/' + encodeURIComponent(videoTargetId) + '/rename', { method: 'POST', headers: { 'content-type': 'application/json' }, body: JSON.stringify({ title: t }) }).then(function (r) { return r.json() }).then(function (j) { if (j.ok) location.reload() else alert(j.message || '이름 변경 실패') }) } } else if (action === 'changeId') { var newId = window.prompt('새 영상 ID (영문/숫자/_/-, 1~64자)', videoTargetId) if (newId && newId !== videoTargetId) { fetch('/op/videos/' + encodeURIComponent(videoTargetId) + '/changeId', { method: 'POST', headers: { 'content-type': 'application/json' }, body: JSON.stringify({ newId: newId }) }).then(function (r) { return r.json() }).then(function (j) { if (j.ok) location.reload() else alert(j.message || 'ID 변경 실패') }) } } else if (action === 'delete') { if (window.confirm('"' + videoTargetTitle + '" 영상을 정말 삭제할까요?')) { fetch('/op/videos/' + encodeURIComponent(videoTargetId) + '/delete', { method: 'POST' }).then(function (r) { return r.json() }).then(function (j) { if (j.ok) location.reload() else alert(j.message || '삭제 실패') }) } } hideVideoCtx() }) // ── 하위 폴더 컨텍스트 메뉴 (rename / delete) ──────────────────────── var folderCtxMenu = document.getElementById('folderCtxMenu') var folderTargetId = null var folderTargetName = null function showFolderCtx(x, y) { folderCtxMenu.style.left = x + 'px' folderCtxMenu.style.top = y + 'px' folderCtxMenu.hidden = false } function hideFolderCtx() { folderCtxMenu.hidden = true } document.querySelectorAll('#subFolderGrid .adminFolder').forEach(function (card) { card.addEventListener('contextmenu', function (e) { e.preventDefault() folderTargetId = card.getAttribute('data-folder-id') folderTargetName = card.getAttribute('data-name') showFolderCtx(e.clientX, e.clientY) }) }) if (folderCtxMenu) { folderCtxMenu.addEventListener('click', function (e) { var btn = e.target.closest('button') if (!btn || !folderTargetId) return var action = btn.getAttribute('data-action') if (action === 'rename') { var newName = window.prompt('새 폴더 이름', folderTargetName) if (newName && newName !== folderTargetName) { fetch('/op/folders/' + encodeURIComponent(folderTargetId) + '/rename', { method: 'POST', headers: { 'content-type': 'application/json' }, body: JSON.stringify({ newName: newName }) }).then(function (r) { return r.json() }).then(function (j) { if (j.ok) location.reload() else alert(j.message || '이름 변경 실패') }) } } else if (action === 'delete') { if (window.confirm('"' + folderTargetName + '" 폴더를 정말 삭제할까요? 안의 영상이 모두 사라집니다.')) { fetch('/op/folders/' + encodeURIComponent(folderTargetId) + '/delete', { method: 'POST' }).then(function (r) { return r.json() }).then(function (j) { if (j.ok) location.reload() else alert(j.message || '삭제 실패') }) } } hideFolderCtx() }) } document.addEventListener('click', function (e) { if (videoCtxMenu && !videoCtxMenu.contains(e.target)) hideVideoCtx() if (folderCtxMenu && !folderCtxMenu.contains(e.target)) hideFolderCtx() }) // ── 하위 폴더 추가 모달 ────────────────────────────────────────────── var addSubBtn = document.getElementById('addSubFolderBtn') if (addSubBtn) { var subModal = document.getElementById('addSubFolderModal') var subInput = document.getElementById('addSubFolderInput') var subCancel = document.getElementById('addSubFolderCancel') var subConfirm = document.getElementById('addSubFolderConfirm') function openSubModal() { subModal.hidden = false; subInput.value = '' setTimeout(function () { subInput.focus() }, 0) } function closeSubModal() { subModal.hidden = true } addSubBtn.addEventListener('click', openSubModal) subCancel.addEventListener('click', closeSubModal) subModal.addEventListener('click', function (e) { if (e.target === subModal) closeSubModal() }) subInput.addEventListener('keydown', function (e) { if (e.key === 'Enter') subConfirm.click() }) subConfirm.addEventListener('click', function () { var name = subInput.value.trim() if (!name) return fetch('/op/folders', { method: 'POST', headers: { 'content-type': 'application/json' }, body: JSON.stringify({ name: name, parentId: op.folderId }) }).then(function (r) { return r.json() }).then(function (j) { if (j.ok) location.reload() else alert(j.message || '폴더 생성 실패') }) }) } // ── 유틸 ────────────────────────────────────────────────────────── function copyUrl(text) { if (navigator.clipboard && navigator.clipboard.writeText) { navigator.clipboard.writeText(text).then(function () { flashToast('주소가 복사되었습니다.') }, function () { fallbackCopy(text) }) } else { fallbackCopy(text) } } function fallbackCopy(text) { try { var ta = document.createElement('textarea') ta.value = text ta.style.position = 'fixed' ta.style.left = '-9999px' document.body.appendChild(ta) ta.focus(); ta.select() var ok = document.execCommand && document.execCommand('copy') document.body.removeChild(ta) if (ok) flashToast('주소가 복사되었습니다.') else window.prompt('주소를 복사하세요:', text) } catch (e) { window.prompt('주소를 복사하세요:', text) } } function flashToast(msg) { var el = document.createElement('div') el.className = 'flashToast' el.textContent = msg document.body.appendChild(el) requestAnimationFrame(function () { el.classList.add('show') }) setTimeout(function () { el.classList.remove('show') setTimeout(function () { el.parentNode && el.parentNode.removeChild(el) }, 200) }, 1500) } })()