181 lines
8.1 KiB
HTML
181 lines
8.1 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="en">
|
||
<head>
|
||
<meta charset="UTF-8" />
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||
<title>Speechify</title>
|
||
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
||
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap" rel="stylesheet" />
|
||
<link rel="stylesheet" href="/static/style.css" />
|
||
</head>
|
||
<body>
|
||
<div class="app">
|
||
|
||
<!-- Top Bar -->
|
||
<header class="topbar">
|
||
<div class="topbar-left">
|
||
<div class="logo">
|
||
<svg width="30" height="30" viewBox="0 0 30 30" fill="none">
|
||
<rect width="30" height="30" rx="9" fill="#7c3aed"/>
|
||
<polygon points="11,8 23,15 11,22" fill="white"/>
|
||
</svg>
|
||
<span>Speechify</span>
|
||
</div>
|
||
</div>
|
||
<div class="topbar-right">
|
||
<button class="btn-icon" id="btn-sidebar-toggle" title="Toggle Input Panel">
|
||
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round">
|
||
<rect x="3" y="3" width="18" height="18" rx="2"/>
|
||
<line x1="9" y1="3" x2="9" y2="21"/>
|
||
</svg>
|
||
</button>
|
||
<button class="btn-icon" id="btn-settings-toggle" title="Voice Settings">
|
||
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round">
|
||
<circle cx="12" cy="12" r="3"/>
|
||
<path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1-2.83 2.83l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-4 0v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83-2.83l.06-.06A1.65 1.65 0 0 0 4.68 15a1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1 0-4h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 2.83-2.83l.06.06A1.65 1.65 0 0 0 9 4.68a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 4 0v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 2.83l-.06.06A1.65 1.65 0 0 0 19.4 9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1z"/>
|
||
</svg>
|
||
</button>
|
||
</div>
|
||
</header>
|
||
|
||
<div class="main-layout">
|
||
|
||
<!-- Left Sidebar: Input -->
|
||
<aside class="sidebar-left" id="sidebar-left">
|
||
<div class="sidebar-header"><h3>Add Content</h3></div>
|
||
|
||
<div class="tabs">
|
||
<button class="tab active" data-tab="text">Text</button>
|
||
<button class="tab" data-tab="pdf">PDF</button>
|
||
<button class="tab" data-tab="url">URL</button>
|
||
</div>
|
||
|
||
<!-- Text Tab -->
|
||
<div class="tab-content active" id="tab-text">
|
||
<textarea id="text-input" placeholder="Paste your text here..."></textarea>
|
||
<button class="btn-primary" id="btn-load-text">Load Text</button>
|
||
</div>
|
||
|
||
<!-- PDF Tab -->
|
||
<div class="tab-content" id="tab-pdf">
|
||
<div class="upload-area" id="upload-area">
|
||
<svg width="44" height="44" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round">
|
||
<path d="M14 2H6a2 2 0 00-2 2v16a2 2 0 002 2h12a2 2 0 002-2V8z"/>
|
||
<polyline points="14 2 14 8 20 8"/>
|
||
<line x1="12" y1="18" x2="12" y2="12"/>
|
||
<line x1="9" y1="15" x2="15" y2="15"/>
|
||
</svg>
|
||
<p>Drop PDF here or<br><strong>click to upload</strong></p>
|
||
<input type="file" id="pdf-input" accept=".pdf" hidden />
|
||
</div>
|
||
<div id="pdf-status" class="status-text"></div>
|
||
</div>
|
||
|
||
<!-- URL Tab -->
|
||
<div class="tab-content" id="tab-url">
|
||
<input type="url" id="url-input" class="text-field" placeholder="https://example.com/article" />
|
||
<button class="btn-primary" id="btn-load-url">Fetch Article</button>
|
||
<div id="url-status" class="status-text"></div>
|
||
</div>
|
||
</aside>
|
||
|
||
<!-- Main Content -->
|
||
<main class="content-area" id="content-area">
|
||
<div id="document-header" class="document-header" style="display:none">
|
||
<h1 class="document-title" id="document-title"></h1>
|
||
<p class="document-meta" id="document-meta"></p>
|
||
</div>
|
||
<div class="text-viewer" id="text-viewer">
|
||
<div class="empty-state">
|
||
<svg width="60" height="60" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1">
|
||
<path d="M14 2H6a2 2 0 00-2 2v16a2 2 0 002 2h12a2 2 0 002-2V8z"/>
|
||
<polyline points="14 2 14 8 20 8"/>
|
||
<line x1="16" y1="13" x2="8" y2="13"/>
|
||
<line x1="16" y1="17" x2="8" y2="17"/>
|
||
</svg>
|
||
<p>Load a document to get started</p>
|
||
<span>Paste text, upload a PDF, or enter a URL</span>
|
||
</div>
|
||
</div>
|
||
</main>
|
||
|
||
<!-- Right Sidebar: Voice Settings -->
|
||
<aside class="sidebar-right" id="sidebar-right">
|
||
<div class="sidebar-header"><h3>Voice Settings</h3></div>
|
||
|
||
<div class="setting-group">
|
||
<label class="setting-label">TTS Model</label>
|
||
<select id="model-select" class="select"></select>
|
||
</div>
|
||
|
||
<div class="setting-group">
|
||
<label class="setting-label">Voice</label>
|
||
<select id="voice-select" class="select"></select>
|
||
</div>
|
||
|
||
<div class="setting-group">
|
||
<label class="setting-label">Speed — <span id="speed-label">1x</span></label>
|
||
<input type="range" id="speed-slider" min="0.5" max="3" step="0.25" value="1" class="slider" />
|
||
<div class="speed-presets">
|
||
<button class="speed-btn" data-speed="0.75">0.75×</button>
|
||
<button class="speed-btn active" data-speed="1">1×</button>
|
||
<button class="speed-btn" data-speed="1.25">1.25×</button>
|
||
<button class="speed-btn" data-speed="1.5">1.5×</button>
|
||
<button class="speed-btn" data-speed="2">2×</button>
|
||
<button class="speed-btn" data-speed="3">3×</button>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="setting-group">
|
||
<label class="setting-label">Font Size</label>
|
||
<div class="font-size-row">
|
||
<button class="btn-sz" id="font-decrease">A−</button>
|
||
<span id="font-size-label">18px</span>
|
||
<button class="btn-sz" id="font-increase">A+</button>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="setting-group">
|
||
<button class="btn-secondary" id="btn-preview">▶ Preview Voice</button>
|
||
</div>
|
||
</aside>
|
||
|
||
</div><!-- /main-layout -->
|
||
|
||
<!-- Player Bar -->
|
||
<div class="player-bar">
|
||
<div class="player-left">
|
||
<p class="now-playing" id="now-playing">No document loaded</p>
|
||
</div>
|
||
<div class="player-center">
|
||
<button class="ctrl-btn" id="btn-prev" title="Previous sentence (←)">
|
||
<svg width="20" height="20" viewBox="0 0 24 24" fill="currentColor"><path d="M6 6h2v12H6zm3.5 6 8.5 6V6z"/></svg>
|
||
</button>
|
||
<button class="play-btn" id="btn-play" title="Play / Pause (Space)">
|
||
<svg class="icon-play" width="26" height="26" viewBox="0 0 24 24" fill="currentColor"><path d="M8 5v14l11-7z"/></svg>
|
||
<svg class="icon-pause" width="26" height="26" viewBox="0 0 24 24" fill="currentColor" style="display:none"><path d="M6 19h4V5H6v14zm8-14v14h4V5h-4z"/></svg>
|
||
</button>
|
||
<button class="ctrl-btn" id="btn-next" title="Next sentence (→)">
|
||
<svg width="20" height="20" viewBox="0 0 24 24" fill="currentColor"><path d="M6 18l8.5-6L6 6v12zm2.5-6 5.5 4V8l-5.5 4zM16 6h2v12h-2z"/></svg>
|
||
</button>
|
||
</div>
|
||
<div class="player-right">
|
||
<span class="progress-text"><span id="cur-sent">0</span> / <span id="tot-sent">0</span></span>
|
||
<div class="progress-track" id="progress-track">
|
||
<div class="progress-fill" id="progress-fill"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
</div><!-- /app -->
|
||
|
||
<!-- Loading overlay -->
|
||
<div class="loading-overlay" id="loading-overlay">
|
||
<div class="spinner"></div>
|
||
<p id="loading-text">Loading…</p>
|
||
</div>
|
||
|
||
<script src="/static/app.js"></script>
|
||
</body>
|
||
</html>
|