dragonflight/services/premiere-plugin-uxp/src/main.js
Claude f1a3d6a24a fix(premiere-plugin-uxp): v2.0.1 — replace unsupported CSS + surface load count
The v2.0.0 grid stayed empty in Premiere 26 because UXP's CSS engine
doesn't support `grid-template-columns: repeat(auto-fill, minmax(...))`
or `aspect-ratio`. Cards rendered with 0 height and the flex column
collapsed, so the actions row stuck to the top of the pane.

Switch to flex-wrap with fixed-width (140px) cards and explicit 80px
thumb heights — both work in UXP's stripped CSS.

Also fix the /auth/me response shape — it returns the user fields
directly, not wrapped in `{ user: ... }`. Header now shows
"display_name @ host" instead of falling back to bare host.

Add a toast on each library load reporting "Loaded N assets (total M)"
so we can tell empty-grid (zero assets) from CSS-broken-grid (cards
exist but invisible) at a glance.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-28 00:35:04 -04:00

103 lines
3.6 KiB
JavaScript

// Panel bootstrap. Wires DOM events to API / Library / Import handlers and
// restores the connection from localStorage on mount.
(function () {
// Avoid running twice if UXP reloads the panel.
if (window.__df_uxp_started) return;
window.__df_uxp_started = true;
function syncConnectBtn() {
const u = UI.$('#server-url').value.trim();
const t = UI.$('#api-token').value.trim();
UI.$('#connect-btn').disabled = !u || !t;
}
async function tryConnect(serverUrl, apiToken) {
UI.setStatus('#connect-status', 'Connecting…', 'muted');
try {
const me = await API.connect(serverUrl, apiToken);
// /auth/me returns the user fields directly (no `user:` wrapper).
const who = (me && (me.display_name || me.username)) || serverUrl;
UI.$('#connected-host').textContent = who + (who === serverUrl ? '' : ' @ ' + serverUrl);
UI.setStatus('#connect-status', '', 'muted');
UI.showPane('library');
await Library.refresh('');
} catch (e) {
API.state.connected = false;
UI.setStatus('#connect-status', 'Connect failed: ' + e.message, 'error');
UI.showPane('connect');
}
}
function wireConnectPane() {
UI.$('#server-url').value = API.state.serverUrl;
UI.$('#api-token').value = API.state.apiToken;
syncConnectBtn();
['input', 'change'].forEach(ev => {
UI.$('#server-url').addEventListener(ev, syncConnectBtn);
UI.$('#api-token').addEventListener(ev, syncConnectBtn);
});
UI.$('#connect-btn').addEventListener('click', async () => {
const u = UI.$('#server-url').value.trim();
const t = UI.$('#api-token').value.trim();
await tryConnect(u, t);
});
}
function wireLibraryPane() {
UI.$('#disconnect-btn').addEventListener('click', () => {
API.disconnect();
UI.$('#server-url').value = '';
UI.$('#api-token').value = '';
syncConnectBtn();
UI.showPane('connect');
UI.setStatus('#connect-status', 'Disconnected.', 'muted');
});
let searchTimer = null;
UI.$('#search-input').addEventListener('input', (e) => {
clearTimeout(searchTimer);
const q = e.target.value;
searchTimer = setTimeout(() => Library.refresh(q), 250);
});
UI.$('#refresh-btn').addEventListener('click', () => Library.refresh(UI.$('#search-input').value));
UI.$('#import-proxy-btn').addEventListener('click', async () => {
const a = Library.selectedAsset();
if (!a) return;
UI.$('#import-proxy-btn').disabled = true;
UI.$('#import-hires-btn').disabled = true;
try { await Import.proxy(a); }
catch (e) { UI.hideProgress(); UI.toast('Proxy import failed: ' + e.message, 'error'); }
finally { Library.syncActions(); }
});
UI.$('#import-hires-btn').addEventListener('click', async () => {
const a = Library.selectedAsset();
if (!a) return;
UI.$('#import-proxy-btn').disabled = true;
UI.$('#import-hires-btn').disabled = true;
try { await Import.hires(a); }
catch (e) { UI.hideProgress(); UI.toast('Hi-res import failed: ' + e.message, 'error'); }
finally { Library.syncActions(); }
});
}
function init() {
wireConnectPane();
wireLibraryPane();
// If we have stored creds, try to reconnect silently. On failure fall
// back to the connect pane so the user can retype.
if (API.state.serverUrl && API.state.apiToken) {
tryConnect(API.state.serverUrl, API.state.apiToken);
} else {
UI.showPane('connect');
}
}
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', init);
} else {
init();
}
})();