feat(premiere-plugin-uxp): v2.0.0 — UXP port replacing CEP for import
CEP `csInterface.evalScript` callback is broken in Premiere Pro 26.0.x —
nothing called from the panel ever returns, so importFiles deadlocks. Adobe's
path forward is UXP. This is the minimum viable port that restores the
Import Proxy / Import Hi-Res workflow.
Scope (v2.0.0):
- Connect to a Dragonflight server (URL + Bearer token; persisted)
- Asset library (search, refresh, grid with thumbnails)
- Import Proxy via streamed download → Project.importFiles
- Import Hi-Res via presigned S3 URL → Project.importFiles
Layout:
manifest.json UXP v5, host=premierepro, minVersion=26.0.0
index.html Panel shell
styles.css Mirrors web UI dark tokens
src/ui.js DOM helpers, toast, progress, formatting
src/api.js HTTP client (Bearer; manual redirect-follow drops auth
when hopping to a different host per UXP security policy)
src/library.js Asset grid render + selection
src/import-flow.js Streaming download (fs.createWriteStream) +
premierepro.Project.importFiles into rootBin
src/main.js Bootstrap, event wiring
build/pack.mjs Packs into .ccx; installs via UnifiedPluginInstallerAgent
Coexists with services/premiere-plugin/ (CEP) — keeps the CEP panel for any
features that still work there while running v2.0.0 for import. Future v2.x
will add live preview, conform, timeline export, settings.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-28 00:19:28 -04:00
|
|
|
// Asset library rendering. Calls API.listAssets, renders a grid into
|
|
|
|
|
// #asset-grid, tracks the selected asset for the action buttons.
|
|
|
|
|
|
|
|
|
|
(function () {
|
|
|
|
|
const Library = {};
|
|
|
|
|
Library.state = { assets: [], selectedId: null };
|
|
|
|
|
|
|
|
|
|
Library.render = function () {
|
|
|
|
|
const grid = UI.$('#asset-grid');
|
|
|
|
|
grid.innerHTML = '';
|
|
|
|
|
if (!Library.state.assets.length) {
|
|
|
|
|
const e = document.createElement('div');
|
|
|
|
|
e.className = 'empty muted';
|
|
|
|
|
e.textContent = 'No assets';
|
|
|
|
|
grid.appendChild(e);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
for (const a of Library.state.assets) {
|
|
|
|
|
grid.appendChild(makeCard(a));
|
|
|
|
|
}
|
|
|
|
|
Library.syncActions();
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
function makeCard(asset) {
|
|
|
|
|
const card = document.createElement('div');
|
|
|
|
|
card.className = 'asset-card';
|
|
|
|
|
if (asset.id === Library.state.selectedId) card.classList.add('selected');
|
|
|
|
|
card.dataset.assetId = asset.id;
|
|
|
|
|
|
|
|
|
|
const thumbKey = asset.thumbnail_s3_key || asset.thumbnail || null;
|
|
|
|
|
const thumbUrl = thumbKey
|
|
|
|
|
? `${API.state.serverUrl}/api/v1/assets/${asset.id}/thumbnail?redirect=1`
|
|
|
|
|
: null;
|
|
|
|
|
|
|
|
|
|
if (thumbUrl) {
|
|
|
|
|
const img = document.createElement('img');
|
|
|
|
|
img.className = 'asset-thumb';
|
|
|
|
|
img.alt = asset.display_name || asset.filename || asset.id;
|
|
|
|
|
// UXP fetch supports cross-origin images; the redirect=1 query on
|
|
|
|
|
// /thumbnail tells the server to 302 to the presigned S3 URL.
|
|
|
|
|
img.src = thumbUrl;
|
|
|
|
|
img.onerror = () => { img.replaceWith(placeholder()); };
|
|
|
|
|
card.appendChild(img);
|
|
|
|
|
} else {
|
|
|
|
|
card.appendChild(placeholder());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const name = document.createElement('div');
|
|
|
|
|
name.className = 'asset-name';
|
|
|
|
|
name.textContent = asset.display_name || asset.filename || asset.id;
|
|
|
|
|
card.appendChild(name);
|
|
|
|
|
|
|
|
|
|
card.addEventListener('click', () => Library.select(asset.id));
|
|
|
|
|
return card;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function placeholder() {
|
|
|
|
|
const p = document.createElement('div');
|
|
|
|
|
p.className = 'asset-thumb-placeholder';
|
|
|
|
|
p.textContent = 'no preview';
|
|
|
|
|
return p;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Library.select = function (id) {
|
|
|
|
|
Library.state.selectedId = id;
|
|
|
|
|
Library.render();
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
Library.selectedAsset = function () {
|
|
|
|
|
return Library.state.assets.find(a => a.id === Library.state.selectedId) || null;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
Library.syncActions = function () {
|
|
|
|
|
const sel = Library.selectedAsset();
|
|
|
|
|
const info = UI.$('#selected-info');
|
|
|
|
|
if (sel) {
|
|
|
|
|
info.textContent = (sel.display_name || sel.filename || sel.id)
|
|
|
|
|
+ (sel.file_size ? ' · ' + UI.formatBytes(Number(sel.file_size)) : '');
|
|
|
|
|
info.classList.remove('muted');
|
|
|
|
|
} else {
|
|
|
|
|
info.textContent = 'No asset selected';
|
|
|
|
|
info.classList.add('muted');
|
|
|
|
|
}
|
|
|
|
|
UI.$('#import-proxy-btn').disabled = !sel;
|
|
|
|
|
UI.$('#import-hires-btn').disabled = !sel || !sel.original_s3_key;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
Library.refresh = async function (query) {
|
|
|
|
|
const grid = UI.$('#asset-grid');
|
|
|
|
|
grid.innerHTML = '<div class="empty muted">Loading…</div>';
|
|
|
|
|
try {
|
|
|
|
|
const data = await API.listAssets(query);
|
|
|
|
|
Library.state.assets = (data && (data.assets || data.rows)) || [];
|
|
|
|
|
Library.render();
|
2026-05-28 00:35:04 -04:00
|
|
|
// Surface count via toast so we can tell empty-grid (zero) from
|
|
|
|
|
// CSS-broken-grid (cards exist but invisible) at a glance.
|
|
|
|
|
if (UI.toast) UI.toast('Loaded ' + Library.state.assets.length + ' assets (total ' + (data.total || '?') + ')', 'ok');
|
feat(premiere-plugin-uxp): v2.0.0 — UXP port replacing CEP for import
CEP `csInterface.evalScript` callback is broken in Premiere Pro 26.0.x —
nothing called from the panel ever returns, so importFiles deadlocks. Adobe's
path forward is UXP. This is the minimum viable port that restores the
Import Proxy / Import Hi-Res workflow.
Scope (v2.0.0):
- Connect to a Dragonflight server (URL + Bearer token; persisted)
- Asset library (search, refresh, grid with thumbnails)
- Import Proxy via streamed download → Project.importFiles
- Import Hi-Res via presigned S3 URL → Project.importFiles
Layout:
manifest.json UXP v5, host=premierepro, minVersion=26.0.0
index.html Panel shell
styles.css Mirrors web UI dark tokens
src/ui.js DOM helpers, toast, progress, formatting
src/api.js HTTP client (Bearer; manual redirect-follow drops auth
when hopping to a different host per UXP security policy)
src/library.js Asset grid render + selection
src/import-flow.js Streaming download (fs.createWriteStream) +
premierepro.Project.importFiles into rootBin
src/main.js Bootstrap, event wiring
build/pack.mjs Packs into .ccx; installs via UnifiedPluginInstallerAgent
Coexists with services/premiere-plugin/ (CEP) — keeps the CEP panel for any
features that still work there while running v2.0.0 for import. Future v2.x
will add live preview, conform, timeline export, settings.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-28 00:19:28 -04:00
|
|
|
} catch (e) {
|
|
|
|
|
grid.innerHTML = '';
|
|
|
|
|
const err = document.createElement('div');
|
|
|
|
|
err.className = 'empty muted';
|
|
|
|
|
err.textContent = 'Error loading assets: ' + e.message;
|
|
|
|
|
grid.appendChild(err);
|
2026-05-28 00:35:04 -04:00
|
|
|
if (UI.toast) UI.toast('Asset load failed: ' + e.message, 'error');
|
feat(premiere-plugin-uxp): v2.0.0 — UXP port replacing CEP for import
CEP `csInterface.evalScript` callback is broken in Premiere Pro 26.0.x —
nothing called from the panel ever returns, so importFiles deadlocks. Adobe's
path forward is UXP. This is the minimum viable port that restores the
Import Proxy / Import Hi-Res workflow.
Scope (v2.0.0):
- Connect to a Dragonflight server (URL + Bearer token; persisted)
- Asset library (search, refresh, grid with thumbnails)
- Import Proxy via streamed download → Project.importFiles
- Import Hi-Res via presigned S3 URL → Project.importFiles
Layout:
manifest.json UXP v5, host=premierepro, minVersion=26.0.0
index.html Panel shell
styles.css Mirrors web UI dark tokens
src/ui.js DOM helpers, toast, progress, formatting
src/api.js HTTP client (Bearer; manual redirect-follow drops auth
when hopping to a different host per UXP security policy)
src/library.js Asset grid render + selection
src/import-flow.js Streaming download (fs.createWriteStream) +
premierepro.Project.importFiles into rootBin
src/main.js Bootstrap, event wiring
build/pack.mjs Packs into .ccx; installs via UnifiedPluginInstallerAgent
Coexists with services/premiere-plugin/ (CEP) — keeps the CEP panel for any
features that still work there while running v2.0.0 for import. Future v2.x
will add live preview, conform, timeline export, settings.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-28 00:19:28 -04:00
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
window.Library = Library;
|
|
|
|
|
})();
|