- Express + EJS + express-session stack (auth/navbar ported from minecraft_launcher)
- Public: main folder list, folder video grid, internal popup player (/player/:videoId)
- Admin (/op): login, folder CRUD with right-click context menu + add-folder modal
- Admin folder: video grid with right-click edit/rename/delete, "영상 추가" -> editor
- Video editor: drag-drop upload, file picker, YouTube URL probe (ETA + 5분 경고),
background yt-dlp download with progress polling, navbar title edit, trim controls,
save runs ffmpeg trim (original preserved)
- Filesystem storage under data/folders/<name>/<videoId>/{meta.json, original.<ext>, edited.<ext>}
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
52 lines
1.8 KiB
JavaScript
52 lines
1.8 KiB
JavaScript
(function () {
|
|
var overlay = document.getElementById('playerOverlay')
|
|
var closeBtn = document.getElementById('playerClose')
|
|
var video = document.getElementById('playerVideo')
|
|
var titleEl = document.getElementById('playerTitle')
|
|
|
|
function openPlayer(videoId, title) {
|
|
// 스펙: /player/:videoId 로 이동한 것처럼 동작하면서 내부 팝업으로 띄운다.
|
|
// pushState 로 URL 만 바꿔, 새로고침/직접접근 시 player.ejs 가 응답한다.
|
|
history.pushState({ player: true, videoId: videoId }, '', '/player/' + encodeURIComponent(videoId))
|
|
titleEl.textContent = title || ''
|
|
video.src = '/api/video/' + encodeURIComponent(videoId) + '/file'
|
|
overlay.hidden = false
|
|
video.play().catch(function () { /* 자동재생 막힘 무시 */ })
|
|
}
|
|
|
|
function closePlayer() {
|
|
overlay.hidden = true
|
|
video.pause()
|
|
video.removeAttribute('src')
|
|
video.load()
|
|
// 폴더 페이지로 되돌리기
|
|
if (history.state && history.state.player) {
|
|
history.back()
|
|
}
|
|
}
|
|
|
|
document.querySelectorAll('.videoCard').forEach(function (card) {
|
|
card.addEventListener('click', function () {
|
|
var id = card.getAttribute('data-video-id')
|
|
var title = card.querySelector('.videoTitle')
|
|
openPlayer(id, title ? title.textContent : '')
|
|
})
|
|
})
|
|
|
|
if (closeBtn) closeBtn.addEventListener('click', closePlayer)
|
|
if (overlay) overlay.addEventListener('click', function (e) {
|
|
if (e.target === overlay) closePlayer()
|
|
})
|
|
window.addEventListener('popstate', function () {
|
|
if (!overlay.hidden) {
|
|
overlay.hidden = true
|
|
video.pause()
|
|
video.removeAttribute('src')
|
|
video.load()
|
|
}
|
|
})
|
|
document.addEventListener('keydown', function (e) {
|
|
if (e.key === 'Escape' && !overlay.hidden) closePlayer()
|
|
})
|
|
})()
|