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>
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
(function () {
|
||||
var ctxMenu = document.getElementById('ctxMenu')
|
||||
if (!ctxMenu) return
|
||||
var targetId = null
|
||||
var targetShareUrl = null
|
||||
|
||||
function showCtx(x, y) {
|
||||
ctxMenu.style.left = x + 'px'
|
||||
@@ -13,7 +13,7 @@
|
||||
document.querySelectorAll('.videoCard').forEach(function (card) {
|
||||
card.addEventListener('contextmenu', function (e) {
|
||||
e.preventDefault()
|
||||
targetId = card.getAttribute('data-video-id') || card.getAttribute('data-id')
|
||||
targetShareUrl = card.getAttribute('data-share-url')
|
||||
showCtx(e.clientX, e.clientY)
|
||||
})
|
||||
})
|
||||
@@ -27,22 +27,19 @@
|
||||
var btn = e.target.closest('button')
|
||||
if (!btn) return
|
||||
var action = btn.getAttribute('data-action')
|
||||
if (action === 'copyUrl' && targetId) {
|
||||
copyVideoUrl(targetId)
|
||||
if (action === 'copyUrl' && targetShareUrl) {
|
||||
copyUrl(location.origin + targetShareUrl)
|
||||
}
|
||||
hideCtx()
|
||||
})
|
||||
|
||||
function copyVideoUrl(id) {
|
||||
var url = location.origin + '/file/video/' + encodeURIComponent(id)
|
||||
function copyUrl(text) {
|
||||
if (navigator.clipboard && navigator.clipboard.writeText) {
|
||||
navigator.clipboard.writeText(url).then(function () {
|
||||
navigator.clipboard.writeText(text).then(function () {
|
||||
flashToast('주소가 복사되었습니다.')
|
||||
}, function () {
|
||||
fallbackCopy(url)
|
||||
})
|
||||
}, function () { fallbackCopy(text) })
|
||||
} else {
|
||||
fallbackCopy(url)
|
||||
fallbackCopy(text)
|
||||
}
|
||||
}
|
||||
function fallbackCopy(text) {
|
||||
|
||||
Reference in New Issue
Block a user