Files
AI-Profile-Router/experiments/acestep15-xl-sft/overrides/user_preferences.js
T

165 lines
6.1 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* User preferences persistence – SAVE side only.
*
* Listens for user changes on Gradio UI controls and persists the current
* values to browser localStorage. Restoration is handled on the Python side
* via ``gr.Blocks.load()`` so Gradio's own Svelte reactivity updates every
* component correctly.
*
* Storage schema:
* key = "acestep.ui.user_preferences"
* value = JSON { _version: 2, audio_format: "flac", … }
*/
(() => {
const STORAGE_KEY = "acestep.ui.user_preferences";
const SCHEMA_VERSION = 2;
const DEBOUNCE_MS = 500;
/**
* Map of preference key → { elemId, type }.
* elemId : the HTML elem_id set in Gradio
* type : "dropdown" | "slider" | "checkbox" | "number"
*/
const PREFS = {
audio_format: { elemId: "acestep-audio-format", type: "dropdown" },
mp3_bitrate: { elemId: "acestep-mp3-bitrate", type: "dropdown" },
mp3_sample_rate: { elemId: "acestep-mp3-sample-rate", type: "dropdown" },
score_scale: { elemId: "acestep-score-scale", type: "slider" },
enable_normalization:{ elemId: "acestep-enable-normalization", type: "checkbox" },
normalization_db: { elemId: "acestep-normalization-db", type: "slider" },
fade_in_duration: { elemId: "acestep-fade-in-duration", type: "slider" },
fade_out_duration: { elemId: "acestep-fade-out-duration", type: "slider" },
latent_shift: { elemId: "acestep-latent-shift", type: "slider" },
latent_rescale: { elemId: "acestep-latent-rescale", type: "slider" },
lm_batch_chunk_size: { elemId: "acestep-lm-batch-chunk-size", type: "number" },
};
let saveTimer = null;
const wiredElements = new WeakSet();
// ── Storage helpers ──────────────────────────────────────────────
const saveAll = (prefs) => {
try {
window.localStorage.setItem(STORAGE_KEY, JSON.stringify(prefs));
} catch (_e) {
// Private browsing or quota exceeded – silently ignore.
}
};
// ── DOM helpers ──────────────────────────────────────────────────
const findInput = (elemId, type) => {
const wrapper = document.getElementById(elemId);
if (!wrapper) return null;
if (type === "dropdown") {
return wrapper.querySelector("input");
}
if (type === "slider") {
return wrapper.querySelector("input[type='range']")
|| wrapper.querySelector("input[type='number']");
}
if (type === "checkbox") {
return wrapper.querySelector("input[type='checkbox']");
}
if (type === "number") {
return wrapper.querySelector("input[type='number']");
}
return null;
};
const readValue = (key) => {
const spec = PREFS[key];
if (!spec) return undefined;
const el = findInput(spec.elemId, spec.type);
if (!el) return undefined;
if (spec.type === "checkbox") return el.checked;
if (spec.type === "slider" || spec.type === "number") {
const v = Number(el.value);
return Number.isFinite(v) ? v : undefined;
}
return el.value || undefined;
};
// ── Save (debounced) ─────────────────────────────────────────────
const scheduleSave = () => {
if (saveTimer !== null) {
clearTimeout(saveTimer);
}
saveTimer = setTimeout(() => {
saveTimer = null;
const prefs = { _version: SCHEMA_VERSION };
for (const key of Object.keys(PREFS)) {
const v = readValue(key);
if (v !== undefined) {
prefs[key] = v;
}
}
saveAll(prefs);
}, DEBOUNCE_MS);
};
// ── Wire listeners (re-entrant – safe to call on re-renders) ─────
const wireListeners = () => {
for (const key of Object.keys(PREFS)) {
const spec = PREFS[key];
const el = findInput(spec.elemId, spec.type);
if (!el || wiredElements.has(el)) continue;
wiredElements.add(el);
el.addEventListener("input", scheduleSave, { passive: true });
el.addEventListener("change", scheduleSave, { passive: true });
}
};
// ── MutationObserver – re-wire after Gradio re-renders ───────────
const startObserver = () => {
const target = document.getElementById("acestep-audio-format")
|| document.body;
const root = target.closest(".gradio-container") || document.body;
let rafPending = false;
new MutationObserver(() => {
if (rafPending) return;
rafPending = true;
requestAnimationFrame(() => {
rafPending = false;
wireListeners();
});
}).observe(root, { childList: true, subtree: true });
};
// ── Boot ─────────────────────────────────────────────────────────
const BOOT_POLL_MS = 200;
const BOOT_TIMEOUT_MS = 10000;
const boot = () => {
const started = Date.now();
const poll = () => {
const probe = document.getElementById(
PREFS.audio_format.elemId
);
if (!probe) {
if (Date.now() - started < BOOT_TIMEOUT_MS) {
setTimeout(poll, BOOT_POLL_MS);
}
return;
}
wireListeners();
startObserver();
};
poll();
};
if (document.readyState === "loading") {
document.addEventListener("DOMContentLoaded", boot, { once: true });
} else {
boot();
}
})();