dragonflight/services/premiere-plugin/index.html

383 lines
18 KiB
HTML
Raw Normal View History

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Wild Dragon MAM</title>
<link rel="stylesheet" href="css/styles.css">
</head>
<body>
<div id="panel-container">
<!-- Connection Form: shown when disconnected (startup) -->
<div id="connection-form" class="connection-bar">
fix(premiere-plugin): v1.0.1 — actually load + connect under CEP 12 End-to-end debugging against a live Premiere Pro 2025 + auth-enabled mam-api surfaced four real bugs that made v1.0.0 install cleanly but never load, plus the missing auth flow. All four are fixed and the panel is verified connected (status dot green, Reconnect button shown, project list populated). - manifest.xml: a comment in the <Resources> block contained "--" (inside "--enable-nodejs"/"--mixed-context"), which is illegal per the XML spec. CEP 12's strict parser logged ERROR XPATH Double hyphen within comment and skipped the panel entirely. Comment rewritten without double hyphens. - manifest.xml: lacked the Version="X.Y" attribute on <ExtensionManifest> and used a non-standard AbstractionLayers/empty <ExtensionList/> structure. CEP rejected it with Unsupported Manifest version '' Manifest rewritten to the standard CSXS 7.0 schema (ExtensionList + DispatchInfoList + RequiredRuntimeList), matching the working AMPP panel template. - main.js: re-declared `const csInterface = new CSInterface()` at top level even though CSInterface.js already declared the same binding. CEP 12 shares script-realm lexical scope across <script> tags, so the second const threw Identifier 'csInterface' has already been declared The throw fired before setupEventListeners(), so the Connect button's click handler was never attached. This is the root cause of the original "clicking Connect does nothing" symptom; everything else was secondary. Removed the duplicate declaration; main.js now uses the binding from CSInterface.js. - No auth support against AUTH_ENABLED=true servers. mam-api supports Bearer tokens (POST /api/v1/tokens), so added: • API token input field (password-masked) next to Server URL • localStorage persistence on every keystroke • window.fetch monkey-patch that injects Authorization: Bearer <token> on every request whose URL starts with the configured server. Signed S3 download URLs are NOT touched. Drive-by fixes that came out of the same debugging pass: - Server URL input listener was 'change' (fires on blur); switched to 'input' so typing-then-clicking-Connect immediately commits. - restoreSettings() now strips trailing slashes from the stored URL so older saved values like 'http://host/' stop producing //api/v1 404s. - CSS selector `input[type="text"].server-url` didn't match the new password input → the token field was unstyled and effectively invisible. Generalized to `input.server-url`; restructured the connection bar into `.connection-controls--stacked` (flex column) of two `.server-input-row` rows so two input fields fit cleanly. - Build scripts now parse ExtensionBundleVersion from both element form (<ExtensionBundleVersion>X</...>) and attribute form (ExtensionBundleVersion="X"), since the manifest rewrite switched schemas. Version bumped 1.0.0 → 1.0.1. New artifacts committed at services/premiere-plugin/build/releases/v1.0.1/ (.exe 2 MB, .zxp 35 KB). v1.0.0 left in place so editors who downloaded it can verify they're on the broken version. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-23 19:24:10 -04:00
<div class="connection-controls connection-controls--stacked">
<div class="server-input-row">
<input
type="text"
id="server-url"
class="server-url"
fix(premiere-plugin): v1.0.1 — actually load + connect under CEP 12 End-to-end debugging against a live Premiere Pro 2025 + auth-enabled mam-api surfaced four real bugs that made v1.0.0 install cleanly but never load, plus the missing auth flow. All four are fixed and the panel is verified connected (status dot green, Reconnect button shown, project list populated). - manifest.xml: a comment in the <Resources> block contained "--" (inside "--enable-nodejs"/"--mixed-context"), which is illegal per the XML spec. CEP 12's strict parser logged ERROR XPATH Double hyphen within comment and skipped the panel entirely. Comment rewritten without double hyphens. - manifest.xml: lacked the Version="X.Y" attribute on <ExtensionManifest> and used a non-standard AbstractionLayers/empty <ExtensionList/> structure. CEP rejected it with Unsupported Manifest version '' Manifest rewritten to the standard CSXS 7.0 schema (ExtensionList + DispatchInfoList + RequiredRuntimeList), matching the working AMPP panel template. - main.js: re-declared `const csInterface = new CSInterface()` at top level even though CSInterface.js already declared the same binding. CEP 12 shares script-realm lexical scope across <script> tags, so the second const threw Identifier 'csInterface' has already been declared The throw fired before setupEventListeners(), so the Connect button's click handler was never attached. This is the root cause of the original "clicking Connect does nothing" symptom; everything else was secondary. Removed the duplicate declaration; main.js now uses the binding from CSInterface.js. - No auth support against AUTH_ENABLED=true servers. mam-api supports Bearer tokens (POST /api/v1/tokens), so added: • API token input field (password-masked) next to Server URL • localStorage persistence on every keystroke • window.fetch monkey-patch that injects Authorization: Bearer <token> on every request whose URL starts with the configured server. Signed S3 download URLs are NOT touched. Drive-by fixes that came out of the same debugging pass: - Server URL input listener was 'change' (fires on blur); switched to 'input' so typing-then-clicking-Connect immediately commits. - restoreSettings() now strips trailing slashes from the stored URL so older saved values like 'http://host/' stop producing //api/v1 404s. - CSS selector `input[type="text"].server-url` didn't match the new password input → the token field was unstyled and effectively invisible. Generalized to `input.server-url`; restructured the connection bar into `.connection-controls--stacked` (flex column) of two `.server-input-row` rows so two input fields fit cleanly. - Build scripts now parse ExtensionBundleVersion from both element form (<ExtensionBundleVersion>X</...>) and attribute form (ExtensionBundleVersion="X"), since the manifest rewrite switched schemas. Version bumped 1.0.0 → 1.0.1. New artifacts committed at services/premiere-plugin/build/releases/v1.0.1/ (.exe 2 MB, .zxp 35 KB). v1.0.0 left in place so editors who downloaded it can verify they're on the broken version. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-23 19:24:10 -04:00
placeholder="http://10.0.0.25:47434"
title="MAM server URL"
>
<div class="status-indicator" id="status-indicator"></div>
</div>
fix(premiere-plugin): v1.0.1 — actually load + connect under CEP 12 End-to-end debugging against a live Premiere Pro 2025 + auth-enabled mam-api surfaced four real bugs that made v1.0.0 install cleanly but never load, plus the missing auth flow. All four are fixed and the panel is verified connected (status dot green, Reconnect button shown, project list populated). - manifest.xml: a comment in the <Resources> block contained "--" (inside "--enable-nodejs"/"--mixed-context"), which is illegal per the XML spec. CEP 12's strict parser logged ERROR XPATH Double hyphen within comment and skipped the panel entirely. Comment rewritten without double hyphens. - manifest.xml: lacked the Version="X.Y" attribute on <ExtensionManifest> and used a non-standard AbstractionLayers/empty <ExtensionList/> structure. CEP rejected it with Unsupported Manifest version '' Manifest rewritten to the standard CSXS 7.0 schema (ExtensionList + DispatchInfoList + RequiredRuntimeList), matching the working AMPP panel template. - main.js: re-declared `const csInterface = new CSInterface()` at top level even though CSInterface.js already declared the same binding. CEP 12 shares script-realm lexical scope across <script> tags, so the second const threw Identifier 'csInterface' has already been declared The throw fired before setupEventListeners(), so the Connect button's click handler was never attached. This is the root cause of the original "clicking Connect does nothing" symptom; everything else was secondary. Removed the duplicate declaration; main.js now uses the binding from CSInterface.js. - No auth support against AUTH_ENABLED=true servers. mam-api supports Bearer tokens (POST /api/v1/tokens), so added: • API token input field (password-masked) next to Server URL • localStorage persistence on every keystroke • window.fetch monkey-patch that injects Authorization: Bearer <token> on every request whose URL starts with the configured server. Signed S3 download URLs are NOT touched. Drive-by fixes that came out of the same debugging pass: - Server URL input listener was 'change' (fires on blur); switched to 'input' so typing-then-clicking-Connect immediately commits. - restoreSettings() now strips trailing slashes from the stored URL so older saved values like 'http://host/' stop producing //api/v1 404s. - CSS selector `input[type="text"].server-url` didn't match the new password input → the token field was unstyled and effectively invisible. Generalized to `input.server-url`; restructured the connection bar into `.connection-controls--stacked` (flex column) of two `.server-input-row` rows so two input fields fit cleanly. - Build scripts now parse ExtensionBundleVersion from both element form (<ExtensionBundleVersion>X</...>) and attribute form (ExtensionBundleVersion="X"), since the manifest rewrite switched schemas. Version bumped 1.0.0 → 1.0.1. New artifacts committed at services/premiere-plugin/build/releases/v1.0.1/ (.exe 2 MB, .zxp 35 KB). v1.0.0 left in place so editors who downloaded it can verify they're on the broken version. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-23 19:24:10 -04:00
<div class="server-input-row">
<input
type="password"
id="api-token"
class="server-url"
placeholder="API token (wd_…)"
title="API token"
fix(premiere-plugin): v1.0.1 — actually load + connect under CEP 12 End-to-end debugging against a live Premiere Pro 2025 + auth-enabled mam-api surfaced four real bugs that made v1.0.0 install cleanly but never load, plus the missing auth flow. All four are fixed and the panel is verified connected (status dot green, Reconnect button shown, project list populated). - manifest.xml: a comment in the <Resources> block contained "--" (inside "--enable-nodejs"/"--mixed-context"), which is illegal per the XML spec. CEP 12's strict parser logged ERROR XPATH Double hyphen within comment and skipped the panel entirely. Comment rewritten without double hyphens. - manifest.xml: lacked the Version="X.Y" attribute on <ExtensionManifest> and used a non-standard AbstractionLayers/empty <ExtensionList/> structure. CEP rejected it with Unsupported Manifest version '' Manifest rewritten to the standard CSXS 7.0 schema (ExtensionList + DispatchInfoList + RequiredRuntimeList), matching the working AMPP panel template. - main.js: re-declared `const csInterface = new CSInterface()` at top level even though CSInterface.js already declared the same binding. CEP 12 shares script-realm lexical scope across <script> tags, so the second const threw Identifier 'csInterface' has already been declared The throw fired before setupEventListeners(), so the Connect button's click handler was never attached. This is the root cause of the original "clicking Connect does nothing" symptom; everything else was secondary. Removed the duplicate declaration; main.js now uses the binding from CSInterface.js. - No auth support against AUTH_ENABLED=true servers. mam-api supports Bearer tokens (POST /api/v1/tokens), so added: • API token input field (password-masked) next to Server URL • localStorage persistence on every keystroke • window.fetch monkey-patch that injects Authorization: Bearer <token> on every request whose URL starts with the configured server. Signed S3 download URLs are NOT touched. Drive-by fixes that came out of the same debugging pass: - Server URL input listener was 'change' (fires on blur); switched to 'input' so typing-then-clicking-Connect immediately commits. - restoreSettings() now strips trailing slashes from the stored URL so older saved values like 'http://host/' stop producing //api/v1 404s. - CSS selector `input[type="text"].server-url` didn't match the new password input → the token field was unstyled and effectively invisible. Generalized to `input.server-url`; restructured the connection bar into `.connection-controls--stacked` (flex column) of two `.server-input-row` rows so two input fields fit cleanly. - Build scripts now parse ExtensionBundleVersion from both element form (<ExtensionBundleVersion>X</...>) and attribute form (ExtensionBundleVersion="X"), since the manifest rewrite switched schemas. Version bumped 1.0.0 → 1.0.1. New artifacts committed at services/premiere-plugin/build/releases/v1.0.1/ (.exe 2 MB, .zxp 35 KB). v1.0.0 left in place so editors who downloaded it can verify they're on the broken version. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-23 19:24:10 -04:00
autocomplete="off"
>
<button id="connect-btn" class="connect-btn btn btn-primary btn-sm">Connect</button>
fix(premiere-plugin): v1.0.1 — actually load + connect under CEP 12 End-to-end debugging against a live Premiere Pro 2025 + auth-enabled mam-api surfaced four real bugs that made v1.0.0 install cleanly but never load, plus the missing auth flow. All four are fixed and the panel is verified connected (status dot green, Reconnect button shown, project list populated). - manifest.xml: a comment in the <Resources> block contained "--" (inside "--enable-nodejs"/"--mixed-context"), which is illegal per the XML spec. CEP 12's strict parser logged ERROR XPATH Double hyphen within comment and skipped the panel entirely. Comment rewritten without double hyphens. - manifest.xml: lacked the Version="X.Y" attribute on <ExtensionManifest> and used a non-standard AbstractionLayers/empty <ExtensionList/> structure. CEP rejected it with Unsupported Manifest version '' Manifest rewritten to the standard CSXS 7.0 schema (ExtensionList + DispatchInfoList + RequiredRuntimeList), matching the working AMPP panel template. - main.js: re-declared `const csInterface = new CSInterface()` at top level even though CSInterface.js already declared the same binding. CEP 12 shares script-realm lexical scope across <script> tags, so the second const threw Identifier 'csInterface' has already been declared The throw fired before setupEventListeners(), so the Connect button's click handler was never attached. This is the root cause of the original "clicking Connect does nothing" symptom; everything else was secondary. Removed the duplicate declaration; main.js now uses the binding from CSInterface.js. - No auth support against AUTH_ENABLED=true servers. mam-api supports Bearer tokens (POST /api/v1/tokens), so added: • API token input field (password-masked) next to Server URL • localStorage persistence on every keystroke • window.fetch monkey-patch that injects Authorization: Bearer <token> on every request whose URL starts with the configured server. Signed S3 download URLs are NOT touched. Drive-by fixes that came out of the same debugging pass: - Server URL input listener was 'change' (fires on blur); switched to 'input' so typing-then-clicking-Connect immediately commits. - restoreSettings() now strips trailing slashes from the stored URL so older saved values like 'http://host/' stop producing //api/v1 404s. - CSS selector `input[type="text"].server-url` didn't match the new password input → the token field was unstyled and effectively invisible. Generalized to `input.server-url`; restructured the connection bar into `.connection-controls--stacked` (flex column) of two `.server-input-row` rows so two input fields fit cleanly. - Build scripts now parse ExtensionBundleVersion from both element form (<ExtensionBundleVersion>X</...>) and attribute form (ExtensionBundleVersion="X"), since the manifest rewrite switched schemas. Version bumped 1.0.0 → 1.0.1. New artifacts committed at services/premiere-plugin/build/releases/v1.0.1/ (.exe 2 MB, .zxp 35 KB). v1.0.0 left in place so editors who downloaded it can verify they're on the broken version. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-23 19:24:10 -04:00
</div>
</div>
</div>
<!-- Connected Bar: compact strip shown only when connected -->
<div id="connected-bar" class="connected-bar hidden">
<div class="connected-bar-status">
<div class="status-indicator connected"></div>
<span id="connected-host" class="connected-host"></span>
</div>
<button id="disconnect-btn" class="btn btn-ghost btn-sm">Disconnect</button>
</div>
feat: server-side filmstrip worker + fix scheduler crash + fix clip freeze Root causes found: 1. Scheduler crashing every 15s: assets table has no error_message column. Fix: remove error_message from UPDATE in scheduler.js (#66 regression). 2. Clip freezing: client-side filmstrip seek loop runs on main thread, seeks same proxy the player is streaming → both stall → freeze. Fix: replace browser seek loop entirely with server-side FFmpeg worker. 3. No dedicated filmstrip worker: filmstrip was never pre-built server-side. Changes: - services/mam-api/src/db/migrations/018-add-filmstrip-s3-key.sql Add filmstrip_s3_key TEXT column to assets table - services/worker/src/workers/filmstrip.js (new) BullMQ worker: downloads proxy, runs FFmpeg fps filter to extract 28 evenly-spaced JPEG frames, base64-encodes them, uploads JSON array to S3 at filmstrips/<assetId>.json, stores key in DB - services/worker/src/workers/thumbnail.js Queue filmstrip job automatically after thumbnail completes - services/worker/src/index.js Register filmstrip worker (concurrency=2), export filmstripQueue singleton, close it on SIGTERM - services/mam-api/src/routes/assets.js - filmstripQueue added - POST /reprocess?type=filmstrip now supported - GET /:id/filmstrip returns signed S3 URL for JSON frames - services/mam-api/src/routes/jobs.js filmstrip queue visible in Jobs UI - services/web-ui/public/screens-asset.jsx Replace browser seek loop with fetch of /assets/:id/filmstrip → fetch S3 JSON → render frames. Zero browser-side video seeking. Right-click and Files tab re-generate via API endpoint.
2026-05-26 12:39:44 -04:00
<!-- Tab Navigation -->
<div class="tab-nav">
<button id="tab-library" class="tab-btn active">
<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M4 19.5A2.5 2.5 0 0 1 6.5 17H20"/>
<path d="M6.5 2H20v20H6.5A2.5 2.5 0 0 1 4 19.5v-15A2.5 2.5 0 0 1 6.5 2z"/>
</svg>
Library
</button>
<button id="tab-growing" class="tab-btn">
<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M23 7l-7 5 7 5V7z"/>
<rect x="1" y="5" width="15" height="14" rx="2" ry="2"/>
</svg>
Growing
<span id="growing-count" class="badge" style="display:none;">0</span>
feat: server-side filmstrip worker + fix scheduler crash + fix clip freeze Root causes found: 1. Scheduler crashing every 15s: assets table has no error_message column. Fix: remove error_message from UPDATE in scheduler.js (#66 regression). 2. Clip freezing: client-side filmstrip seek loop runs on main thread, seeks same proxy the player is streaming → both stall → freeze. Fix: replace browser seek loop entirely with server-side FFmpeg worker. 3. No dedicated filmstrip worker: filmstrip was never pre-built server-side. Changes: - services/mam-api/src/db/migrations/018-add-filmstrip-s3-key.sql Add filmstrip_s3_key TEXT column to assets table - services/worker/src/workers/filmstrip.js (new) BullMQ worker: downloads proxy, runs FFmpeg fps filter to extract 28 evenly-spaced JPEG frames, base64-encodes them, uploads JSON array to S3 at filmstrips/<assetId>.json, stores key in DB - services/worker/src/workers/thumbnail.js Queue filmstrip job automatically after thumbnail completes - services/worker/src/index.js Register filmstrip worker (concurrency=2), export filmstripQueue singleton, close it on SIGTERM - services/mam-api/src/routes/assets.js - filmstripQueue added - POST /reprocess?type=filmstrip now supported - GET /:id/filmstrip returns signed S3 URL for JSON frames - services/mam-api/src/routes/jobs.js filmstrip queue visible in Jobs UI - services/web-ui/public/screens-asset.jsx Replace browser seek loop with fetch of /assets/:id/filmstrip → fetch S3 JSON → render frames. Zero browser-side video seeking. Right-click and Files tab re-generate via API endpoint.
2026-05-26 12:39:44 -04:00
</button>
</div>
<!-- Search and Filter Area -->
<div class="search-filter-area">
<div class="search-bar">
<input
type="text"
id="search-input"
class="search-input"
placeholder="Search assets..."
>
</div>
<div class="filter-controls">
<select id="project-filter" title="Filter by project">
<option value="all">All Projects</option>
</select>
</div>
</div>
<!-- Active Sequence Info Bar -->
<div id="seq-info-bar" class="seq-info-bar hidden">
<span class="seq-info-label chip chip--good"><span class="chip-dot"></span>SEQ</span>
<span id="seq-info-name" class="seq-info-name"></span>
<button id="seq-refresh-btn" class="seq-refresh-btn btn btn-ghost btn-sm" title="Refresh active sequence">&#8635;</button>
</div>
<!-- Main Content Area -->
<div class="content-area">
feat: server-side filmstrip worker + fix scheduler crash + fix clip freeze Root causes found: 1. Scheduler crashing every 15s: assets table has no error_message column. Fix: remove error_message from UPDATE in scheduler.js (#66 regression). 2. Clip freezing: client-side filmstrip seek loop runs on main thread, seeks same proxy the player is streaming → both stall → freeze. Fix: replace browser seek loop entirely with server-side FFmpeg worker. 3. No dedicated filmstrip worker: filmstrip was never pre-built server-side. Changes: - services/mam-api/src/db/migrations/018-add-filmstrip-s3-key.sql Add filmstrip_s3_key TEXT column to assets table - services/worker/src/workers/filmstrip.js (new) BullMQ worker: downloads proxy, runs FFmpeg fps filter to extract 28 evenly-spaced JPEG frames, base64-encodes them, uploads JSON array to S3 at filmstrips/<assetId>.json, stores key in DB - services/worker/src/workers/thumbnail.js Queue filmstrip job automatically after thumbnail completes - services/worker/src/index.js Register filmstrip worker (concurrency=2), export filmstripQueue singleton, close it on SIGTERM - services/mam-api/src/routes/assets.js - filmstripQueue added - POST /reprocess?type=filmstrip now supported - GET /:id/filmstrip returns signed S3 URL for JSON frames - services/mam-api/src/routes/jobs.js filmstrip queue visible in Jobs UI - services/web-ui/public/screens-asset.jsx Replace browser seek loop with fetch of /assets/:id/filmstrip → fetch S3 JSON → render frames. Zero browser-side video seeking. Right-click and Files tab re-generate via API endpoint.
2026-05-26 12:39:44 -04:00
<!-- Library Grid -->
<div class="asset-grid-container" id="library-container">
<div id="asset-grid" class="asset-grid">
<div id="empty-state" class="empty-state">
<div class="empty-state-icon">
<svg width="40" height="40" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5">
<path d="M21 12a9 9 0 11-18 0 9 9 0 0118 0z"/>
<path d="M9 9a3 3 0 116 0m-6 3h6m-3 3h.01"/>
</svg>
</div>
<div class="empty-state-title">No assets</div>
<div class="empty-state-body">Connect to server and load assets</div>
</div>
</div>
</div>
feat: server-side filmstrip worker + fix scheduler crash + fix clip freeze Root causes found: 1. Scheduler crashing every 15s: assets table has no error_message column. Fix: remove error_message from UPDATE in scheduler.js (#66 regression). 2. Clip freezing: client-side filmstrip seek loop runs on main thread, seeks same proxy the player is streaming → both stall → freeze. Fix: replace browser seek loop entirely with server-side FFmpeg worker. 3. No dedicated filmstrip worker: filmstrip was never pre-built server-side. Changes: - services/mam-api/src/db/migrations/018-add-filmstrip-s3-key.sql Add filmstrip_s3_key TEXT column to assets table - services/worker/src/workers/filmstrip.js (new) BullMQ worker: downloads proxy, runs FFmpeg fps filter to extract 28 evenly-spaced JPEG frames, base64-encodes them, uploads JSON array to S3 at filmstrips/<assetId>.json, stores key in DB - services/worker/src/workers/thumbnail.js Queue filmstrip job automatically after thumbnail completes - services/worker/src/index.js Register filmstrip worker (concurrency=2), export filmstripQueue singleton, close it on SIGTERM - services/mam-api/src/routes/assets.js - filmstripQueue added - POST /reprocess?type=filmstrip now supported - GET /:id/filmstrip returns signed S3 URL for JSON frames - services/mam-api/src/routes/jobs.js filmstrip queue visible in Jobs UI - services/web-ui/public/screens-asset.jsx Replace browser seek loop with fetch of /assets/:id/filmstrip → fetch S3 JSON → render frames. Zero browser-side video seeking. Right-click and Files tab re-generate via API endpoint.
2026-05-26 12:39:44 -04:00
<!-- Growing Grid -->
<div class="asset-grid-container hidden" id="growing-container">
<div id="growing-grid" class="asset-grid">
<div id="growing-empty-state" class="empty-state">
<div class="empty-state-icon">
<svg width="40" height="40" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5">
<rect x="2" y="2" width="20" height="20" rx="2.18" ry="2.18"/>
<line x1="7" y1="2" x2="7" y2="22"/>
<line x1="17" y1="2" x2="17" y2="22"/>
<line x1="2" y1="12" x2="22" y2="12"/>
<line x1="2" y1="7" x2="7" y2="7"/>
<line x1="2" y1="17" x2="7" y2="17"/>
<line x1="17" y1="17" x2="22" y2="17"/>
<line x1="17" y1="7" x2="22" y2="7"/>
</svg>
</div>
<div class="empty-state-title">No growing files</div>
<div class="empty-state-body">Active recordings will appear here</div>
</div>
</div>
</div>
<!-- Details Panel -->
<div id="details-panel" class="details-panel hidden">
<div class="details-header">
<span class="details-header-label">Asset Info</span>
</div>
<div class="details-section">
<div class="details-label">Filename</div>
<div id="details-filename" class="details-value truncate-lines-2"></div>
</div>
<div class="divider"></div>
<div class="details-section">
<div class="details-label">Codec</div>
<div id="details-codec" class="details-value"></div>
</div>
<div class="details-section">
<div class="details-label">Resolution</div>
<div id="details-resolution" class="details-value"></div>
</div>
<div class="details-section">
<div class="details-label">Frame Rate</div>
<div id="details-fps" class="details-value"></div>
</div>
<div class="details-section">
<div class="details-label">Duration</div>
<div id="details-duration" class="details-value"></div>
</div>
<div class="details-section">
<div class="details-label">File Size</div>
<div id="details-size" class="details-value"></div>
</div>
<div class="divider"></div>
<div class="details-section">
<div class="details-label">Tags</div>
<div id="details-tags" class="tags-list"></div>
</div>
</div>
</div>
<!-- Progress Indicator -->
<div id="progress-container" class="progress-container">
<div class="progress-label" id="progress-label">Downloading...</div>
<div class="progress-bar">
<div id="progress-fill" class="progress-fill"></div>
</div>
</div>
<!-- Export Panel -- Push Timeline to MAM -->
<div id="export-panel" class="export-panel hidden">
<div class="export-panel-title">Push Timeline to MAM</div>
<input
type="text"
id="export-seq-name"
class="input"
placeholder="Sequence name"
title="Name this sequence will have in the MAM"
>
<select id="export-proj-select" title="Target project in MAM">
<option value="">— Select project —</option>
</select>
<div id="export-clip-info" class="export-clip-info"></div>
<div class="export-panel-actions">
<button id="export-confirm-btn" class="btn btn-primary">Push to MAM</button>
<button id="export-cancel-btn" class="btn btn-secondary">Cancel</button>
</div>
</div>
<!-- Advanced Section: FCP XML Export & Hi-Res Auto-Relink -->
<div class="advanced-section">
<div class="advanced-section-title">Advanced</div>
<div class="advanced-row">
<button id="export-conform-btn" class="btn btn-primary btn-sm" disabled title="Export timeline as FCP XML and start conform job">
<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/>
<polyline points="7 10 12 15 17 10"/>
<line x1="12" y1="15" x2="12" y2="3"/>
</svg>
Export &amp; Conform
</button>
<button id="fetch-relink-btn" class="btn btn-secondary btn-sm" disabled title="Fetch hi-res media for all timeline clips and auto-relink">
<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="11" cy="11" r="8"/>
<line x1="21" y1="21" x2="16.65" y2="16.65"/>
</svg>
Fetch &amp; Relink All
</button>
</div>
</div>
<!-- Action Bar -->
<div class="action-bar">
<div class="action-row">
<button id="import-btn" class="btn btn-primary" disabled title="Download proxy and import into Premiere">Import Proxy</button>
<button id="import-hires-btn" class="btn btn-secondary" disabled title="Download original hi-res and import into Premiere">Hi-Res</button>
</div>
<div class="action-row">
<button id="mount-live-btn" class="btn btn-secondary" disabled title="Open the live file directly from the SMB share">Mount Live</button>
<button id="relink-btn" class="btn btn-secondary" disabled title="Relink the imported clip from proxy to the finalized hi-res original">Relink to Hi-Res</button>
</div>
<div class="action-row">
<button id="import-all-btn" class="btn btn-secondary" title="Import all visible assets as proxy">Import All</button>
<button id="export-timeline-btn" class="btn btn-secondary" title="Push the current Premiere sequence to MAM">Export Timeline &#8593;</button>
</div>
</div>
</div>
<!-- FCP XML Export & Conform Slide Panel -->
<div id="export-conform-overlay" class="slide-overlay"></div>
<div id="export-conform-panel" class="slide-panel">
<div class="slide-panel-header">
<span class="slide-panel-title">Export &amp; Conform</span>
<button id="export-conform-close-btn" class="btn btn-ghost btn-sm" title="Close">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<line x1="18" y1="6" x2="6" y2="18"/>
<line x1="6" y1="6" x2="18" y2="18"/>
</svg>
</button>
</div>
<div class="slide-panel-body">
<!-- Preset Selection -->
<div class="form-group">
<span class="form-label">Preset</span>
<div id="preset-cards" class="preset-grid">
<div class="preset-card selected" data-preset="broadcast">
<div class="preset-card-title">Broadcast</div>
<div class="preset-card-desc">ProRes 422 HQ, 1920x1080, 48kHz</div>
</div>
<div class="preset-card" data-preset="web">
<div class="preset-card-title">Web</div>
<div class="preset-card-desc">H.264, 1920x1080, AAC 320kbps</div>
</div>
<div class="preset-card" data-preset="archive">
<div class="preset-card-title">Archive</div>
<div class="preset-card-desc">ProRes 4444, UHD, 48kHz</div>
</div>
<div class="preset-card" data-preset="custom">
<div class="preset-card-title">Custom</div>
<div class="preset-card-desc">Manual settings</div>
</div>
</div>
</div>
<!-- Codec -->
<div class="form-group">
<span class="form-label">Codec</span>
<select id="conform-codec">
<option value="prores_hq">ProRes 422 HQ</option>
<option value="prores_4444">ProRes 4444</option>
<option value="h264">H.264</option>
<option value="h265">H.265 / HEVC</option>
<option value="dnxhr_hq">DNxHR HQ</option>
</select>
</div>
<!-- Quality -->
<div class="form-group">
<span class="form-label">Quality</span>
<select id="conform-quality">
<option value="high">High</option>
<option value="medium" selected>Medium</option>
<option value="low">Low</option>
<option value="custom">Custom</option>
</select>
</div>
<!-- Resolution -->
<div class="form-group">
<span class="form-label">Resolution</span>
<select id="conform-resolution">
<option value="uhd">UHD (3840x2160)</option>
<option value="1080p" selected>Full HD (1920x1080)</option>
<option value="720p">HD (1280x720)</option>
<option value="source">Source</option>
</select>
</div>
<!-- Audio Preset -->
<div class="form-group">
<span class="form-label">Audio Preset</span>
<select id="conform-audio">
<option value="broadcast">Broadcast (48kHz, 24-bit, PCM)</option>
<option value="web">Web (44.1kHz, AAC 320kbps)</option>
<option value="archive">Archive (96kHz, 24-bit, PCM)</option>
<option value="custom">Custom</option>
</select>
</div>
<!-- Timeline Clip Summary -->
<div class="form-group">
<span class="form-label">Timeline Clips</span>
<div id="conform-clip-info" class="export-clip-info"></div>
</div>
</div>
<div class="slide-panel-footer">
<button id="export-conform-cancel-btn" class="btn btn-secondary">Cancel</button>
<button id="export-conform-start-btn" class="btn btn-primary">Start Conform</button>
</div>
</div>
<!-- Hi-Res Relink Slide Panel -->
<div id="relink-overlay" class="slide-overlay"></div>
<div id="relink-panel" class="slide-panel">
<div class="slide-panel-header">
<span class="slide-panel-title">Fetch &amp; Relink Hi-Res</span>
<button id="relink-close-btn" class="btn btn-ghost btn-sm" title="Close">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<line x1="18" y1="6" x2="6" y2="18"/>
<line x1="6" y1="6" x2="18" y2="18"/>
</svg>
</button>
</div>
<div class="slide-panel-body">
<div class="form-group">
<span class="form-label">Select clips to relink</span>
<span class="form-hint">Clips matched to MAM assets will be listed below. Check the ones you want to upgrade to hi-res.</span>
</div>
<div id="clip-list-container" class="clip-list-container">
<div id="clip-list" class="clip-list">
<!-- populated by JS -->
</div>
</div>
<div id="relink-summary" class="relink-summary hidden">
<div class="relink-summary-icon">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M22 11.08V12a10 10 0 1 1-5.93-9.14"/>
<polyline points="22 4 12 14.01 9 11.01"/>
</svg>
</div>
<div class="relink-summary-text" id="relink-summary-text"></div>
<div class="relink-summary-detail" id="relink-summary-detail"></div>
</div>
</div>
<div class="slide-panel-footer">
<button id="relink-cancel-btn" class="btn btn-secondary">Cancel</button>
<button id="relink-start-btn" class="btn btn-primary" disabled>Start Relink</button>
</div>
</div>
<!-- Adobe CSInterface Library -->
<script src="js/CSInterface.js"></script>
<!-- Main Panel Script -->
<script src="js/main.js"></script>
</body>
</html>