Spaces:
Running
Running
Commit ·
a99ebea
1
Parent(s): 077bd66
Remove session usage tracker (couldn't reflect cross-session quota)
Browse files- index.html +0 -83
index.html
CHANGED
|
@@ -215,46 +215,6 @@ body {
|
|
| 215 |
.voice-card:hover .delete-voice { opacity: 1; }
|
| 216 |
.voice-card .delete-voice:hover { color: var(--danger); background: rgba(239,68,68,0.1); }
|
| 217 |
|
| 218 |
-
/* ── Usage tracker ── */
|
| 219 |
-
.usage-tracker {
|
| 220 |
-
padding: 12px;
|
| 221 |
-
margin: 0 12px 12px;
|
| 222 |
-
background: var(--surface2);
|
| 223 |
-
border: 1px solid var(--border);
|
| 224 |
-
border-radius: 10px;
|
| 225 |
-
}
|
| 226 |
-
|
| 227 |
-
.usage-header {
|
| 228 |
-
display: flex;
|
| 229 |
-
align-items: center;
|
| 230 |
-
justify-content: space-between;
|
| 231 |
-
margin-bottom: 8px;
|
| 232 |
-
}
|
| 233 |
-
|
| 234 |
-
.usage-label { font-size: 11px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.5px; color: var(--text-muted); }
|
| 235 |
-
.usage-value { font-size: 11px; color: var(--text-secondary); font-variant-numeric: tabular-nums; }
|
| 236 |
-
|
| 237 |
-
.usage-bar {
|
| 238 |
-
width: 100%;
|
| 239 |
-
height: 4px;
|
| 240 |
-
background: var(--surface3);
|
| 241 |
-
border-radius: 2px;
|
| 242 |
-
overflow: hidden;
|
| 243 |
-
margin-bottom: 6px;
|
| 244 |
-
}
|
| 245 |
-
|
| 246 |
-
.usage-fill {
|
| 247 |
-
height: 100%;
|
| 248 |
-
background: var(--accent);
|
| 249 |
-
border-radius: 2px;
|
| 250 |
-
transition: width 0.5s ease;
|
| 251 |
-
}
|
| 252 |
-
|
| 253 |
-
.usage-fill.warning { background: var(--warning); }
|
| 254 |
-
.usage-fill.danger { background: var(--danger); }
|
| 255 |
-
|
| 256 |
-
.usage-sub { font-size: 10px; color: var(--text-muted); }
|
| 257 |
-
|
| 258 |
/* ── Content ── */
|
| 259 |
.content {
|
| 260 |
overflow-y: auto;
|
|
@@ -877,15 +837,6 @@ pre {
|
|
| 877 |
</button>
|
| 878 |
</div>
|
| 879 |
|
| 880 |
-
<!-- Usage Tracker -->
|
| 881 |
-
<div class="usage-tracker" id="usage-tracker">
|
| 882 |
-
<div class="usage-header">
|
| 883 |
-
<span class="usage-label">Session Usage</span>
|
| 884 |
-
<span class="usage-value" id="usage-value">0s used</span>
|
| 885 |
-
</div>
|
| 886 |
-
<div class="usage-bar"><div class="usage-fill" id="usage-fill" style="width:0%"></div></div>
|
| 887 |
-
<div class="usage-sub" id="usage-sub">Estimated from generation durations</div>
|
| 888 |
-
</div>
|
| 889 |
</div>
|
| 890 |
|
| 891 |
<div class="content">
|
|
@@ -1457,9 +1408,6 @@ import { oauthLoginUrl, oauthHandleRedirectIfPresent } from "https://esm.sh/@hug
|
|
| 1457 |
|
| 1458 |
const OMNIVOICE_BASE = "https://k2-fsa-omnivoice.hf.space/gradio_api";
|
| 1459 |
const COLORS = ["#7c3aed","#ec4899","#f59e0b","#22c55e","#3b82f6","#ef4444","#06b6d4","#8b5cf6"];
|
| 1460 |
-
const QUOTA_FREE = 240;
|
| 1461 |
-
const QUOTA_PRO = 1500;
|
| 1462 |
-
|
| 1463 |
let accessToken = null;
|
| 1464 |
let userInfo = null;
|
| 1465 |
let isPro = false;
|
|
@@ -1467,7 +1415,6 @@ let selectedVoice = null;
|
|
| 1467 |
let resultAudioUrl = null;
|
| 1468 |
let modalFileData = null;
|
| 1469 |
let history = JSON.parse(localStorage.getItem("zl_history") || "[]");
|
| 1470 |
-
let sessionUsage = parseFloat(sessionStorage.getItem("zl_usage") || "0");
|
| 1471 |
|
| 1472 |
// ── IndexedDB ──
|
| 1473 |
|
|
@@ -1657,28 +1604,6 @@ document.addEventListener("click", () => {
|
|
| 1657 |
document.getElementById("voice-picker")?.classList.remove("visible");
|
| 1658 |
});
|
| 1659 |
|
| 1660 |
-
// ── Usage Tracker ──
|
| 1661 |
-
|
| 1662 |
-
function updateUsageTracker(addSeconds) {
|
| 1663 |
-
if (addSeconds) {
|
| 1664 |
-
sessionUsage += addSeconds;
|
| 1665 |
-
sessionStorage.setItem("zl_usage", sessionUsage.toString());
|
| 1666 |
-
}
|
| 1667 |
-
const quota = isPro ? QUOTA_PRO : QUOTA_FREE;
|
| 1668 |
-
const pct = Math.min((sessionUsage / quota) * 100, 100);
|
| 1669 |
-
const fill = document.getElementById("usage-fill");
|
| 1670 |
-
fill.style.width = `${pct}%`;
|
| 1671 |
-
fill.className = "usage-fill" + (pct > 80 ? " danger" : pct > 50 ? " warning" : "");
|
| 1672 |
-
|
| 1673 |
-
const mins = Math.floor(sessionUsage / 60);
|
| 1674 |
-
const secs = Math.round(sessionUsage % 60);
|
| 1675 |
-
document.getElementById("usage-value").textContent = mins > 0 ? `${mins}m ${secs}s` : `${secs}s`;
|
| 1676 |
-
|
| 1677 |
-
const quotaMins = Math.round(quota / 60);
|
| 1678 |
-
const tier = isPro ? "Pro" : "Free";
|
| 1679 |
-
document.getElementById("usage-sub").textContent = `~${Math.round(sessionUsage)}s of ${quotaMins}m ${tier} daily quota (est.)`;
|
| 1680 |
-
}
|
| 1681 |
-
|
| 1682 |
// ── Smart Error CTAs ──
|
| 1683 |
|
| 1684 |
function showStatusWithCTA(errorMsg) {
|
|
@@ -2034,7 +1959,6 @@ window.generateDesign = async function() {
|
|
| 2034 |
result.classList.add("visible");
|
| 2035 |
showDesignStatus("success", `Generated in ${dur.toFixed(1)}s`);
|
| 2036 |
addToHistory(text, "Voice Design", dur, designAudioUrl);
|
| 2037 |
-
updateUsageTracker(dur * 0.5);
|
| 2038 |
} else {
|
| 2039 |
const errMsg = data.output?.error || "Generation failed";
|
| 2040 |
showDesignStatusWithCTA(errMsg);
|
|
@@ -2220,7 +2144,6 @@ window.transcribe = async function() {
|
|
| 2220 |
document.getElementById("transcribe-text").textContent = transcript;
|
| 2221 |
result.style.display = "block";
|
| 2222 |
showTranscribeStatus("success", `Transcribed in ${data.output.duration?.toFixed(1)}s`);
|
| 2223 |
-
updateUsageTracker(data.output.duration * 0.5);
|
| 2224 |
} else {
|
| 2225 |
showTranscribeStatusWithCTA(data.output?.error || "Transcription failed");
|
| 2226 |
}
|
|
@@ -2343,7 +2266,6 @@ function showApp() {
|
|
| 2343 |
renderPresets();
|
| 2344 |
renderVoicesPage();
|
| 2345 |
renderHistory();
|
| 2346 |
-
updateUsageTracker();
|
| 2347 |
}
|
| 2348 |
|
| 2349 |
// ── Pages ──
|
|
@@ -2981,7 +2903,6 @@ window.voiceChange = async function() {
|
|
| 2981 |
document.getElementById("vc-player-meta").textContent = `${vcSource.name} → ${vcTarget.name} · ${duration.toFixed(1)}s`;
|
| 2982 |
result.classList.add("visible");
|
| 2983 |
showStatusOn("vc-status", "success", `Converted in ${duration.toFixed(1)}s`);
|
| 2984 |
-
updateUsageTracker(duration * 0.5);
|
| 2985 |
} catch (err) {
|
| 2986 |
showStatusCtaOn("vc-status", err.message);
|
| 2987 |
} finally {
|
|
@@ -3040,7 +2961,6 @@ window.voiceIsolate = async function() {
|
|
| 3040 |
document.getElementById("iso-player-meta").textContent = `${isoFile.name} · ${duration.toFixed(1)}s`;
|
| 3041 |
result.classList.add("visible");
|
| 3042 |
showStatusOn("iso-status", "success", `Done in ${duration.toFixed(1)}s`);
|
| 3043 |
-
updateUsageTracker(duration * 0.5);
|
| 3044 |
} catch (err) {
|
| 3045 |
showStatusCtaOn("iso-status", err.message);
|
| 3046 |
} finally {
|
|
@@ -3094,7 +3014,6 @@ window.soundEffect = async function() {
|
|
| 3094 |
document.getElementById("sfx-player-meta").textContent = `${sfxDuration.value}s · ${duration.toFixed(1)}s gen`;
|
| 3095 |
result.classList.add("visible");
|
| 3096 |
showStatusOn("sfx-status", "success", `Generated in ${duration.toFixed(1)}s`);
|
| 3097 |
-
updateUsageTracker(duration * 0.5);
|
| 3098 |
} catch (err) {
|
| 3099 |
showStatusCtaOn("sfx-status", err.message);
|
| 3100 |
} finally {
|
|
@@ -3211,8 +3130,6 @@ window.generate = async function() {
|
|
| 3211 |
result.classList.add("visible");
|
| 3212 |
showStatus("success", `Generated in ${dur.toFixed(1)}s`);
|
| 3213 |
addToHistory(text, selectedVoice.name, dur, resultAudioUrl);
|
| 3214 |
-
// Estimate GPU usage (~50% of wall time based on our measurements)
|
| 3215 |
-
updateUsageTracker(dur * 0.5);
|
| 3216 |
} else {
|
| 3217 |
const errMsg = data.output?.error || "Generation failed";
|
| 3218 |
showStatusWithCTA(errMsg);
|
|
|
|
| 215 |
.voice-card:hover .delete-voice { opacity: 1; }
|
| 216 |
.voice-card .delete-voice:hover { color: var(--danger); background: rgba(239,68,68,0.1); }
|
| 217 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 218 |
/* ── Content ── */
|
| 219 |
.content {
|
| 220 |
overflow-y: auto;
|
|
|
|
| 837 |
</button>
|
| 838 |
</div>
|
| 839 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 840 |
</div>
|
| 841 |
|
| 842 |
<div class="content">
|
|
|
|
| 1408 |
|
| 1409 |
const OMNIVOICE_BASE = "https://k2-fsa-omnivoice.hf.space/gradio_api";
|
| 1410 |
const COLORS = ["#7c3aed","#ec4899","#f59e0b","#22c55e","#3b82f6","#ef4444","#06b6d4","#8b5cf6"];
|
|
|
|
|
|
|
|
|
|
| 1411 |
let accessToken = null;
|
| 1412 |
let userInfo = null;
|
| 1413 |
let isPro = false;
|
|
|
|
| 1415 |
let resultAudioUrl = null;
|
| 1416 |
let modalFileData = null;
|
| 1417 |
let history = JSON.parse(localStorage.getItem("zl_history") || "[]");
|
|
|
|
| 1418 |
|
| 1419 |
// ── IndexedDB ──
|
| 1420 |
|
|
|
|
| 1604 |
document.getElementById("voice-picker")?.classList.remove("visible");
|
| 1605 |
});
|
| 1606 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1607 |
// ── Smart Error CTAs ──
|
| 1608 |
|
| 1609 |
function showStatusWithCTA(errorMsg) {
|
|
|
|
| 1959 |
result.classList.add("visible");
|
| 1960 |
showDesignStatus("success", `Generated in ${dur.toFixed(1)}s`);
|
| 1961 |
addToHistory(text, "Voice Design", dur, designAudioUrl);
|
|
|
|
| 1962 |
} else {
|
| 1963 |
const errMsg = data.output?.error || "Generation failed";
|
| 1964 |
showDesignStatusWithCTA(errMsg);
|
|
|
|
| 2144 |
document.getElementById("transcribe-text").textContent = transcript;
|
| 2145 |
result.style.display = "block";
|
| 2146 |
showTranscribeStatus("success", `Transcribed in ${data.output.duration?.toFixed(1)}s`);
|
|
|
|
| 2147 |
} else {
|
| 2148 |
showTranscribeStatusWithCTA(data.output?.error || "Transcription failed");
|
| 2149 |
}
|
|
|
|
| 2266 |
renderPresets();
|
| 2267 |
renderVoicesPage();
|
| 2268 |
renderHistory();
|
|
|
|
| 2269 |
}
|
| 2270 |
|
| 2271 |
// ── Pages ──
|
|
|
|
| 2903 |
document.getElementById("vc-player-meta").textContent = `${vcSource.name} → ${vcTarget.name} · ${duration.toFixed(1)}s`;
|
| 2904 |
result.classList.add("visible");
|
| 2905 |
showStatusOn("vc-status", "success", `Converted in ${duration.toFixed(1)}s`);
|
|
|
|
| 2906 |
} catch (err) {
|
| 2907 |
showStatusCtaOn("vc-status", err.message);
|
| 2908 |
} finally {
|
|
|
|
| 2961 |
document.getElementById("iso-player-meta").textContent = `${isoFile.name} · ${duration.toFixed(1)}s`;
|
| 2962 |
result.classList.add("visible");
|
| 2963 |
showStatusOn("iso-status", "success", `Done in ${duration.toFixed(1)}s`);
|
|
|
|
| 2964 |
} catch (err) {
|
| 2965 |
showStatusCtaOn("iso-status", err.message);
|
| 2966 |
} finally {
|
|
|
|
| 3014 |
document.getElementById("sfx-player-meta").textContent = `${sfxDuration.value}s · ${duration.toFixed(1)}s gen`;
|
| 3015 |
result.classList.add("visible");
|
| 3016 |
showStatusOn("sfx-status", "success", `Generated in ${duration.toFixed(1)}s`);
|
|
|
|
| 3017 |
} catch (err) {
|
| 3018 |
showStatusCtaOn("sfx-status", err.message);
|
| 3019 |
} finally {
|
|
|
|
| 3130 |
result.classList.add("visible");
|
| 3131 |
showStatus("success", `Generated in ${dur.toFixed(1)}s`);
|
| 3132 |
addToHistory(text, selectedVoice.name, dur, resultAudioUrl);
|
|
|
|
|
|
|
| 3133 |
} else {
|
| 3134 |
const errMsg = data.output?.error || "Generation failed";
|
| 3135 |
showStatusWithCTA(errMsg);
|