feat(editor): thumbnail images in media panel; Del=ripple, Shift+Del=lift
This commit is contained in:
parent
090452969c
commit
1e9710ce0c
1 changed files with 45 additions and 5 deletions
|
|
@ -183,6 +183,30 @@
|
||||||
}
|
}
|
||||||
.media-asset-item.active .media-asset-meta { color: var(--accent); opacity: 0.7; }
|
.media-asset-item.active .media-asset-meta { color: var(--accent); opacity: 0.7; }
|
||||||
|
|
||||||
|
/* ── Thumbnail wrapper in media panel ──────────────────────── */
|
||||||
|
.media-thumb-wrap {
|
||||||
|
width: 48px;
|
||||||
|
height: 30px;
|
||||||
|
flex-shrink: 0;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
background: var(--bg-surface);
|
||||||
|
border-radius: 2px;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
.media-thumb {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
object-fit: cover;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
.media-thumb-icon {
|
||||||
|
display: none;
|
||||||
|
color: var(--text-tertiary);
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* ── Timeline panel ────────────────────────────────────────── */
|
/* ── Timeline panel ────────────────────────────────────────── */
|
||||||
.timeline-panel {
|
.timeline-panel {
|
||||||
grid-area: timeline-panel;
|
grid-area: timeline-panel;
|
||||||
|
|
@ -394,6 +418,14 @@
|
||||||
<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5"><circle cx="6" cy="10" r="3.5"/><path d="M8.7 7.3L13 3M11.5 3.5l1.5 1.5M13.5 2.5l1 1"/></svg>
|
<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5"><circle cx="6" cy="10" r="3.5"/><path d="M8.7 7.3L13 3M11.5 3.5l1.5 1.5M13.5 2.5l1 1"/></svg>
|
||||||
Tokens
|
Tokens
|
||||||
</a>
|
</a>
|
||||||
|
<a href="containers.html" class="nav-item">
|
||||||
|
<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5"><rect x="1" y="5" width="14" height="9" rx="1"/><path d="M1 5l2-3h10l2 3"/><line x1="5" y1="5" x2="5" y2="14"/><line x1="11" y1="5" x2="11" y2="14"/></svg>
|
||||||
|
Containers
|
||||||
|
</a>
|
||||||
|
<a href="cluster.html" class="nav-item">
|
||||||
|
<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5"><circle cx="8" cy="3" r="2"/><circle cx="3" cy="13" r="2"/><circle cx="13" cy="13" r="2"/><line x1="8" y1="5" x2="8" y2="9"/><line x1="8" y1="9" x2="3" y2="11"/><line x1="8" y1="9" x2="13" y2="11"/></svg>
|
||||||
|
Cluster
|
||||||
|
</a>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
<div class="sidebar-footer">
|
<div class="sidebar-footer">
|
||||||
|
|
@ -564,6 +596,8 @@
|
||||||
<div class="kbd-row"><kbd>Ctrl+Z</kbd><span>Undo</span></div>
|
<div class="kbd-row"><kbd>Ctrl+Z</kbd><span>Undo</span></div>
|
||||||
<div class="kbd-row"><kbd>Ctrl+⇧+Z</kbd><span>Redo</span></div>
|
<div class="kbd-row"><kbd>Ctrl+⇧+Z</kbd><span>Redo</span></div>
|
||||||
<div class="kbd-row"><kbd>Ctrl+S</kbd><span>Save</span></div>
|
<div class="kbd-row"><kbd>Ctrl+S</kbd><span>Save</span></div>
|
||||||
|
<div class="kbd-row"><kbd>Del</kbd><span>Ripple delete</span></div>
|
||||||
|
<div class="kbd-row"><kbd>⇧+Del</kbd><span>Extract (lift)</span></div>
|
||||||
<div class="kbd-row"><kbd>?</kbd><span>This help</span></div>
|
<div class="kbd-row"><kbd>?</kbd><span>This help</span></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -738,7 +772,7 @@ function renderMediaList() {
|
||||||
|
|
||||||
if (assets.length === 0) {
|
if (assets.length === 0) {
|
||||||
list.innerHTML = '<div style="padding:var(--sp-4) var(--sp-3);font-size:var(--text-xs);color:var(--text-tertiary);">' +
|
list.innerHTML = '<div style="padding:var(--sp-4) var(--sp-3);font-size:var(--text-xs);color:var(--text-tertiary);">' +
|
||||||
(query ? 'No clips match "' + esc(query) + '"' : 'No assets in this bin.') + '</div>';
|
(query ? 'No clips match “' + esc(query) + '”' : 'No assets in this bin.') + '</div>';
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -754,11 +788,17 @@ function renderMediaList() {
|
||||||
].filter(Boolean);
|
].filter(Boolean);
|
||||||
const metaStr = metaParts.join(' · ');
|
const metaStr = metaParts.join(' · ');
|
||||||
|
|
||||||
|
// Thumbnail wrapper: img with SVG fallback for assets without a thumbnail yet
|
||||||
el.innerHTML =
|
el.innerHTML =
|
||||||
'<svg viewBox="0 0 14 14" fill="none" stroke="currentColor" stroke-width="1.3" width="12" height="12">' +
|
'<div class="media-thumb-wrap">' +
|
||||||
'<rect x="1" y="3" width="8" height="8" rx="1"/>' +
|
'<img class="media-thumb" src="/api/v1/assets/' + esc(asset.id) + '/thumbnail?redirect=1" ' +
|
||||||
'<path d="M9 6l4-2v6l-4-2"/>' +
|
'alt="" loading="lazy" ' +
|
||||||
'</svg>' +
|
'onerror="this.style.display=\'none\';this.nextElementSibling.style.display=\'block\'">' +
|
||||||
|
'<svg class="media-thumb-icon" viewBox="0 0 14 14" fill="none" stroke="currentColor" stroke-width="1.3" width="12" height="12">' +
|
||||||
|
'<rect x="1" y="3" width="8" height="8" rx="1"/>' +
|
||||||
|
'<path d="M9 6l4-2v6l-4-2"/>' +
|
||||||
|
'</svg>' +
|
||||||
|
'</div>' +
|
||||||
'<div class="media-asset-info">' +
|
'<div class="media-asset-info">' +
|
||||||
'<span class="media-asset-name" title="' + esc(asset.display_name || asset.filename) + '">' +
|
'<span class="media-asset-name" title="' + esc(asset.display_name || asset.filename) + '">' +
|
||||||
esc(asset.display_name || asset.filename) +
|
esc(asset.display_name || asset.filename) +
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue