diff --git a/services/premiere-plugin-uxp/index.html b/services/premiere-plugin-uxp/index.html
index ee19824..3601298 100644
--- a/services/premiere-plugin-uxp/index.html
+++ b/services/premiere-plugin-uxp/index.html
@@ -77,6 +77,9 @@
+
diff --git a/services/premiere-plugin-uxp/src/main.js b/services/premiere-plugin-uxp/src/main.js
index 46d980d..71862bf 100644
--- a/services/premiere-plugin-uxp/src/main.js
+++ b/services/premiere-plugin-uxp/src/main.js
@@ -28,6 +28,29 @@
});
}
+ // Asset layout toggle: compact list (default) vs thumbnail grid. Persisted
+ // in localStorage when available (UXP host permitting), else session-only.
+ const GRID_ICON = '';
+ const LIST_ICON = '';
+ let _viewMode = null;
+ function getViewMode() {
+ if (_viewMode) return _viewMode;
+ try { _viewMode = localStorage.getItem('df_view_mode'); } catch (e) {}
+ return _viewMode || 'list';
+ }
+ function applyViewMode(mode) {
+ _viewMode = mode === 'grid' ? 'grid' : 'list';
+ try { localStorage.setItem('df_view_mode', _viewMode); } catch (e) {}
+ const isList = _viewMode === 'list';
+ document.querySelectorAll('.asset-grid').forEach(g => g.classList.toggle('list-view', isList));
+ const btn = $('view-toggle-btn');
+ if (btn) {
+ // Show the icon for the layout a click switches TO.
+ btn.innerHTML = isList ? GRID_ICON : LIST_ICON;
+ btn.setAttribute('data-tip', isList ? 'Grid view' : 'List view');
+ }
+ }
+
function syncConnectBtn() {
$('connect-btn').disabled = !$('server-url').value.trim() || !$('api-token').value.trim();
}
@@ -96,6 +119,11 @@
$('tab-library').addEventListener('click', () => Library.switchTab('library'));
$('tab-growing').addEventListener('click', () => Library.switchTab('growing'));
+ const vt = $('view-toggle-btn');
+ if (vt) vt.addEventListener('click', () => {
+ applyViewMode(getViewMode() === 'list' ? 'grid' : 'list');
+ });
+
let searchTimer;
$('search-input').addEventListener('input', e => {
clearTimeout(searchTimer);
@@ -488,6 +516,7 @@
function init() {
enableDivDisabled();
+ applyViewMode(getViewMode());
wireConnectPane(); wireLibraryPane();
wireExportPanel(); wireConformPanel(); wireRelinkPanel();
showVersion();
diff --git a/services/premiere-plugin-uxp/src/tooltip.js b/services/premiere-plugin-uxp/src/tooltip.js
index da66091..c198797 100644
--- a/services/premiere-plugin-uxp/src/tooltip.js
+++ b/services/premiere-plugin-uxp/src/tooltip.js
@@ -26,6 +26,10 @@
const r = el.getBoundingClientRect();
const t = tip.getBoundingClientRect();
+ // position:absolute on a body-level node is offset from the document
+ // origin; add scroll offset (0 in practice, body doesn't scroll) for safety.
+ const sx = window.pageXOffset || document.documentElement.scrollLeft || 0;
+ const sy = window.pageYOffset || document.documentElement.scrollTop || 0;
const gap = 7;
const pos = el.getAttribute('data-tip-pos') || 'down';
let x, y;
@@ -42,11 +46,12 @@
x = r.left + (r.width - t.width) / 2; y = r.bottom + gap;
}
- const vw = window.innerWidth, vh = window.innerHeight;
+ const vw = window.innerWidth || document.documentElement.clientWidth || 99999;
+ const vh = window.innerHeight || document.documentElement.clientHeight || 99999;
x = Math.max(4, Math.min(x, vw - t.width - 4));
y = Math.max(4, Math.min(y, vh - t.height - 4));
- tip.style.left = x + 'px';
- tip.style.top = y + 'px';
+ tip.style.left = (x + sx) + 'px';
+ tip.style.top = (y + sy) + 'px';
tip.style.opacity = '1';
}
diff --git a/services/premiere-plugin-uxp/styles.css b/services/premiere-plugin-uxp/styles.css
index ce4ecf1..43b3a2a 100644
--- a/services/premiere-plugin-uxp/styles.css
+++ b/services/premiere-plugin-uxp/styles.css
@@ -454,6 +454,38 @@ input[type="search"]::-webkit-search-cancel-button { display: none; }
.status-ready { background: var(--success); color: #06120d; }
.status-error { background: var(--danger); color: #fff; }
+/* ── compact list view (toolbar toggle) ─────────────────────────── */
+.asset-grid.list-view { gap: 2px; padding: 6px 8px; }
+.asset-grid.list-view .asset-card {
+ flex: 1 1 100%;
+ max-width: 100%;
+ flex-direction: row;
+ align-items: center;
+ gap: 9px;
+ padding: 3px 8px 3px 3px;
+ border-radius: 6px;
+}
+.asset-grid.list-view .asset-thumb,
+.asset-grid.list-view .asset-thumb-placeholder {
+ width: 50px;
+ height: 28px;
+ border-radius: 4px;
+}
+.asset-grid.list-view .asset-thumb-placeholder { font-size: 0; }
+.asset-grid.list-view .asset-info {
+ order: 1;
+ flex: 1 1 auto;
+ min-width: 0;
+ padding: 0;
+ gap: 1px;
+}
+.asset-grid.list-view .asset-status {
+ order: 2;
+ position: static;
+ margin-left: auto;
+ flex-shrink: 0;
+}
+
/* ── action dock ────────────────────────────────────────────────── */
.dock {
flex-shrink: 0;
@@ -606,8 +638,11 @@ input[type="search"]::-webkit-search-cancel-button { display: none; }
/* ── hover tooltip bubble (driven by src/tooltip.js) ────────────── */
.tip-bubble {
- position: fixed;
- z-index: 100;
+ /* UXP's engine does not reliably support position:fixed; absolute on a
+ body-level node maps to the same coords because the panel body never
+ scrolls (only .asset-grid scrolls internally). */
+ position: absolute;
+ z-index: 1000;
display: none;
pointer-events: none;
white-space: nowrap;