diff --git a/src/core/constants.js b/src/core/constants.js new file mode 100644 index 0000000..58b58d3 --- /dev/null +++ b/src/core/constants.js @@ -0,0 +1,49 @@ +/** + * constants — Centralized configuration constants + * + * Extracted from AppShell.js to avoid hardcoding provider lists + * and accepted file types directly in HTML templates. + * + * Add new TTS providers here — the settings UI will reflect them + * automatically without touching the shell template. + */ + +/** + * TTS provider options shown in the settings dropdown. + * @type {Array<{id: string, label: string}>} + */ +export const TTS_PROVIDERS = [ + { id: 'supertonic', label: 'Supertonic (Free)' }, + { id: 'groq', label: 'Groq Orpheus' }, + { id: 'hume', label: 'Hume EVI' }, +]; + +/** + * Accepted file types for the transcript panel upload input. + * Includes documents, images, code, and 3D model formats. + * @type {string} + */ +export const TRANSCRIPT_UPLOAD_ACCEPT = [ + 'image/*', + '.pdf', '.docx', '.xlsx', '.pptx', + '.txt', '.md', '.json', '.csv', + '.html', '.js', '.py', '.ts', '.css', + '.glb', '.gltf', '.obj', '.fbx', '.stl', + '.3ds', '.dae', '.ply', '.usdz', '.blend', + '.mtl', '.hdr', '.exr', +].join(','); + +/** + * Sandbox permissions for the canvas iframe. + * @type {string} + */ +export const CANVAS_SANDBOX_PERMISSIONS = [ + 'allow-same-origin', + 'allow-scripts', + 'allow-popups', + 'allow-popups-to-escape-sandbox', + 'allow-forms', + 'allow-top-navigation-by-user-activation', + 'allow-downloads', + 'allow-pointer-lock', +].join(' '); diff --git a/src/ui/AppShell.js b/src/ui/AppShell.js index 3369767..7cabfd6 100644 --- a/src/ui/AppShell.js +++ b/src/ui/AppShell.js @@ -8,15 +8,25 @@ * import { inject } from './ui/AppShell.js'; * inject(); // must be first, before DOM queries */ +import { TTS_PROVIDERS, TRANSCRIPT_UPLOAD_ACCEPT, CANVAS_SANDBOX_PERMISSIONS } from '../core/constants.js'; + export function inject() { - document.body.insertAdjacentHTML('afterbegin', SHELL_HTML); + document.body.insertAdjacentHTML('afterbegin', buildShellHTML()); // Activity chip style — light grey on dark grey, no backdrop-filter const chipStyle = document.createElement('style'); chipStyle.textContent = `.agent-activity-chip{background:var(--bg-elevated)!important;border:1px solid rgba(180,190,210,0.3)!important;color:var(--text-primary)!important;backdrop-filter:none!important;box-shadow:0 2px 12px rgba(0,0,0,0.6),inset 0 1px 0 rgba(255,255,255,0.07)!important;overflow:hidden!important;}`; document.head.appendChild(chipStyle); } -const SHELL_HTML = ` +/** Build TTS provider ` + ).join('\n '); +} + +function buildShellHTML() { +return ` @@ -63,7 +73,7 @@ const SHELL_HTML = ` id="canvas-iframe" src="about:blank" data-canvas-src="" - sandbox="allow-same-origin allow-scripts allow-popups allow-popups-to-escape-sandbox allow-forms allow-top-navigation-by-user-activation allow-downloads allow-pointer-lock" + sandbox="${CANVAS_SANDBOX_PERMISSIONS}" style="width: 100vw; height: 100vh; border: none; display: block; touch-action: manipulation;" allow="autoplay; fullscreen; microphone; camera; pointer-lock"> @@ -108,7 +118,7 @@ const SHELL_HTML = ` `; +}