Commit Graph

11 Commits

Author SHA1 Message Date
Claude (owner)
066ae6b112 feat(thumbnails): generate and serve video thumbnails for folder cards
ffmpeg로 영상 첫 프레임을 즉석 추출해 thumb.jpg로 캐시하고
공개/관리자 폴더 카드에서 실제 썸네일을 표시한다. ffmpeg가 없거나
생성 불가하면 404로 떨어져 ▶ placeholder로 폴백한다.

Co-Authored-By: Claude Opus 4 <noreply@anthropic.com>
2026-06-02 00:41:06 +09:00
Claude (owner)
0e39836c1f feat(folders): allow videos in top-level folders too
1단계 폴더에도 영상을 직접 추가할 수 있게 한다 (하위 폴더와 혼합 가능).
플레이리스트 추가는 기존대로 2단계 폴더 한정.

- op.ts: editor/upload/youtube start 의 parentId===null 차단 제거
  (playlist probe/start/new 차단은 유지)
- op/folder.ejs: 1단계에서 "하위 폴더 추가"+"영상 추가" 동시 노출,
  서브폴더 그리드와 영상 그리드를 함께 표시
- folder.ejs(public): 1단계에서 하위 폴더 + 영상 함께 표시
- README: 폴더 구조/버튼 설명 갱신

Co-Authored-By: Claude Opus 4 <noreply@anthropic.com>
2026-06-01 22:12:37 +09:00
Claude (owner)
31c754a3ad feat(playlist): import UI with drag reorder + random/sequential ID toggle (STEP 5)
Adds /op/folder/:top/:sub/playlist/new page that lets the operator paste a
YouTube playlist URL, probe entries via yt-dlp, reorder them by drag, edit
title/ID per row, and choose between random IDs or zero-padded sequential
IDs before registering all jobs in one batch.
2026-06-01 00:15:39 +09:00
Claude (owner)
55ce30733b feat(videos): inline ID edit with live availability check
영상 편집 페이지에 영상 ID 입력란을 추가했다. 입력 시 250ms 디바운스로
/op/videos/idAvailable 를 호출해 중복/형식을 실시간 확인하고, 변경
버튼으로 /op/videos/:id/changeId 를 호출한 뒤 새 ID 의 편집 페이지로
location.replace 한다. 공유 주소 복사 버튼도 함께 노출한다.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-31 23:51:18 +09:00
Claude
3089af1ad8 fix(folders): enforce videos-only at depth 2 (P1 review fix)
- routes/op.ts: editor / upload / youtube-start reject when folder.parentId === null
- op/folder.ejs: at depth 1 show only "하위 폴더 추가"; at depth 2 show
  "영상 추가" + "플레이리스트 추가". Video grid and sub-folder modal
  rendered conditionally.
- folder.ejs (public): at depth 1 render only sub-folder grid; at depth 2
  render only video grid.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-31 23:43:24 +09:00
Claude
c5faa8808c feat(folders): nested folder tree (max depth 2) + id-based mutations
- new storeDb.ts: DB+FS layer (folders w/ parent_id, videos w/ global id)
- depth cap: sub-folder cannot have children (enforced in createFolder)
- video id: editable anytime (changeVideoId), uniqueness via PK
- routes:
  - public /folder/:topName[/:subName], /video/:topName[/:subName]/:videoId
  - admin /op/folder/:topName[/:subName], id-based /op/folders/:id/*
    and /op/videos/:id/* (rename/changeId/delete/save + idAvailable check)
- views: breadcrumb + subFolder grid; 플레이리스트 추가 button shows at 2단계
- client JS: id-based mutation endpoints, share URL data attribute,
  in-site player pushes share URL to address bar
- store.ts slimmed to Account + readAccounts (FS layer moved to storeDb)
- pickIntId accepts numeric JSON bodies

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-31 23:36:02 +09:00
51bf813ccc feat(folder): right-click "영상 주소 복사" on public and admin
- 공개 폴더(/folder/:name): 새 ctxMenu + public-folder.js 로 우클릭 메뉴 신설
  ("영상 주소 복사" 만 포함). 좌클릭 재생 기능은 그대로 유지.
- 관리자 폴더(/op/folder/:name): 기존 ctxMenu 에 "영상 주소 복사" 항목과
  folder.js 에 copyUrl 핸들러 추가.
- 양쪽 모두 navigator.clipboard.writeText(origin + "/player/" + id) 사용,
  실패하면 hidden textarea + execCommand("copy") fallback, 그것도 실패하면
  window.prompt 으로 직접 복사 안내. 성공 시 flashToast 로 피드백.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-15 18:42:49 +09:00
e77c18a83e feat(op/folder): click video card to open inline player
관리자 폴더 화면에서도 영상 카드를 좌클릭하면 공개 폴더와 동일한
내부 팝업 플레이어로 재생되도록 함. 우클릭 컨텍스트 메뉴 (수정/이름
변경/삭제) 는 그대로 유지.

- 카드에 data-video-id 추가해 기존 player.js 가 인식하게 함
- 페이지에 playerOverlay HTML 과 player.js 스크립트 포함
- window.__SITE__.folder 도 함께 노출해 player.js 의 가정 충족

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-15 18:39:50 +09:00
f587dce5ce feat(editor): timeline scrubber with draggable trim handles
영상편집기에 lossless-cut 류 트림 타임라인 추가. 숫자 입력만 있던 기존 UI 를
시각적 재생바 + 좌/우 드래그 핸들 + 플레이헤드로 교체.

- 좌/우 파란 핸들을 끌어 in/out 점 설정 (pointer events 기반, 터치 지원)
- 흰색 플레이헤드가 영상 재생 위치 따라감
- 타임라인 빈 공간 클릭 → 그 지점으로 시킹
- "[ 시작점" / "끝점 ]" 버튼으로 현재 시점 마크
- "선택 재생" 으로 선택구간만 미리보기, "초기화" 로 전체 선택 복원
- 기존 숫자 입력은 보조 입력으로 유지하고 상태와 양방향 동기화

저장 페이로드는 그대로 (startSec/endSec). 서버측 ffmpeg 트림 로직 변경 없음.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-15 18:31:07 +09:00
3f4bcf52d0 fix: escape JSON in <script>; popup player picks edited if available
P1: views were emitting <%- JSON.stringify(...) %> directly inside <script>
tags. A video title like "</script><script>alert(1)</script>" would break
out of the script and inject HTML. Added res.locals.jsonForScript() that
escapes <, >, &, U+2028, U+2029 before output and switched all three
templates (op/editor.ejs, op/folder.ejs, folder.ejs) to use it.

P2: The internal popup player in /folder/:name always hit
/api/video/:id/file which returned the original. Made the file endpoint
default to the edited variant when present and only fall back to original
when ?edited=0 is given. Editor page passes ?edited=0 explicitly so the
operator always re-trims from the original. Standalone /player/:id no
longer needs the ?edited=1 hint.

Verified: rendered editor HTML escapes </script> payloads to \u003c/script,
default file endpoint serves edited.mp4 while ?edited=0 serves original.mp4.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-15 16:49:03 +09:00
0db04cf5cd feat: implement video site per README spec
- 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>
2026-05-15 16:42:00 +09:00