fix: null-safe loadSettings() — prevent crash on missing elements (v1.12.17)
loadSettings() was crashing with "Cannot set properties of null" because many settings input elements were moved out of their original sections during the Library restructure. All bare .value assignments are now routed through a local sv() helper that silently skips absent elements. This was also blocking My Voices from rendering on page load. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
373aee8423
commit
7e265f3e30
@ -9,6 +9,13 @@ Follows [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) · versioned wi
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
## [1.12.17] — 2026-06-28
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
- **Settings load crash** — `loadSettings()` used direct `.value` assignments on elements that no longer exist after the Library restructure; all now use null-safe `sv()` helper so a missing element is silently skipped instead of throwing. This was also preventing My Voices from loading on page start.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## [1.12.16] — 2026-06-28
|
## [1.12.16] — 2026-06-28
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|||||||
@ -26,7 +26,7 @@
|
|||||||
|
|
||||||
<!-- ── Core styles (local — no CDN dependency for first paint) ────────── -->
|
<!-- ── Core styles (local — no CDN dependency for first paint) ────────── -->
|
||||||
<link rel="stylesheet" href="/static/vendor/mdi/materialdesignicons.min.css">
|
<link rel="stylesheet" href="/static/vendor/mdi/materialdesignicons.min.css">
|
||||||
<link rel="stylesheet" href="/static/style.css?v=1.12.16">
|
<link rel="stylesheet" href="/static/style.css?v=1.12.17">
|
||||||
|
|
||||||
|
|
||||||
<!-- ── Flag icons — non-blocking (loaded async, icons appear after JS) ── -->
|
<!-- ── Flag icons — non-blocking (loaded async, icons appear after JS) ── -->
|
||||||
@ -336,7 +336,7 @@
|
|||||||
<script src="/static/vendor/wavesurfer-regions.min.js"></script>
|
<script src="/static/vendor/wavesurfer-regions.min.js"></script>
|
||||||
|
|
||||||
<!-- loader.js: fetches sections → loads JS modules → removes skeleton -->
|
<!-- loader.js: fetches sections → loads JS modules → removes skeleton -->
|
||||||
<script src="/static/loader.js?v=1.12.16"></script>
|
<script src="/static/loader.js?v=1.12.17"></script>
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@ -399,16 +399,17 @@ function enhanceSettingsHelp(root = document) {
|
|||||||
|
|
||||||
async function loadSettings() {
|
async function loadSettings() {
|
||||||
const s = await fetch('/api/settings').then(r => r.json());
|
const s = await fetch('/api/settings').then(r => r.json());
|
||||||
$('s-whisper-url').value = s.whisper_url || '';
|
const sv = (id, val) => { const el = $(id); if (el) el.value = val; };
|
||||||
$('s-whisper-key').value = s.whisper_api_key || '';
|
sv('s-whisper-url', s.whisper_url || '');
|
||||||
$('s-tts-url').value = s.tts_url || '';
|
sv('s-whisper-key', s.whisper_api_key || '');
|
||||||
$('s-faster-whisper-url').value = s.faster_whisper_url || '';
|
sv('s-tts-url', s.tts_url || '');
|
||||||
$('s-whisper-cpp-url').value = s.whisper_cpp_url || '';
|
sv('s-faster-whisper-url', s.faster_whisper_url || '');
|
||||||
$('s-groq-api-key').value = s.groq_api_key || '';
|
sv('s-whisper-cpp-url', s.whisper_cpp_url || '');
|
||||||
$('s-kokoro-url').value = s.kokoro_url || '';
|
sv('s-groq-api-key', s.groq_api_key || '');
|
||||||
$('s-vibevoice-url').value = s.vibevoice_url || '';
|
sv('s-kokoro-url', s.kokoro_url || '');
|
||||||
$('s-xtts-url').value = s.xtts_url || '';
|
sv('s-vibevoice-url', s.vibevoice_url || '');
|
||||||
const llmUrlEl = $('s-llm-url'); if (llmUrlEl) llmUrlEl.value = s.llm_url || '';
|
sv('s-xtts-url', s.xtts_url || '');
|
||||||
|
sv('s-llm-url', s.llm_url || '');
|
||||||
_appSettings = s;
|
_appSettings = s;
|
||||||
|
|
||||||
// Restore engine URL inputs from server (overrides localStorage fallback)
|
// Restore engine URL inputs from server (overrides localStorage fallback)
|
||||||
@ -437,32 +438,31 @@ async function loadSettings() {
|
|||||||
if (refineInp && s.refine_llm_url) refineInp.value = s.refine_llm_url;
|
if (refineInp && s.refine_llm_url) refineInp.value = s.refine_llm_url;
|
||||||
const convInp = $('conv-llm-url');
|
const convInp = $('conv-llm-url');
|
||||||
if (convInp && s.conv_llm_url) convInp.value = s.conv_llm_url;
|
if (convInp && s.conv_llm_url) convInp.value = s.conv_llm_url;
|
||||||
$('s-tts-stream-url').value = s.tts_stream_url || '';
|
sv('s-tts-stream-url', s.tts_stream_url || '');
|
||||||
$('s-customvoice-url').value = s.customvoice_url || 'http://host.docker.internal:8022';
|
sv('s-customvoice-url', s.customvoice_url || 'http://host.docker.internal:8022');
|
||||||
$('s-nvidia-router-url').value = s.nvidia_router_url || 'http://host.docker.internal:8090';
|
sv('s-nvidia-router-url', s.nvidia_router_url || 'http://host.docker.internal:8090');
|
||||||
$('s-nvidia-tts-url').value = s.nvidia_tts_url || 'http://host.docker.internal:8091';
|
sv('s-nvidia-tts-url', s.nvidia_tts_url || 'http://host.docker.internal:8091');
|
||||||
$('s-nvidia-asr-url').value = s.nvidia_asr_url || 'http://host.docker.internal:8092';
|
sv('s-nvidia-asr-url', s.nvidia_asr_url || 'http://host.docker.internal:8092');
|
||||||
$('s-nvidia-zeroshot-url').value = s.nvidia_zeroshot_url || s.nvidia_clone_url || 'http://host.docker.internal:8093';
|
sv('s-nvidia-zeroshot-url', s.nvidia_zeroshot_url || s.nvidia_clone_url || 'http://host.docker.internal:8093');
|
||||||
$('s-nvidia-flow-url').value = s.nvidia_flow_url || 'http://host.docker.internal:8094';
|
sv('s-nvidia-flow-url', s.nvidia_flow_url || 'http://host.docker.internal:8094');
|
||||||
$('s-tts-stream-mode').value = s.tts_stream_mode || 'auto';
|
sv('s-tts-stream-mode', s.tts_stream_mode || 'auto');
|
||||||
$('s-tts-key').value = s.tts_api_key || '';
|
sv('s-tts-key', s.tts_api_key || '');
|
||||||
$('s-tts-backend').value = s.tts_backend || 'openai';
|
sv('s-tts-backend', s.tts_backend || 'openai');
|
||||||
const defaultTtsParams = {temperature:0.1, top_p:0.8, seed:0};
|
const defaultTtsParams = {temperature:0.1, top_p:0.8, seed:0};
|
||||||
const byBackend = s.tts_extra_params_by_backend || {};
|
const byBackend = s.tts_extra_params_by_backend || {};
|
||||||
$('s-tts-extra-voice-clone').value = JSON.stringify(byBackend.voice_clone || s.tts_extra_params || defaultTtsParams, null, 2);
|
sv('s-tts-extra-voice-clone', JSON.stringify(byBackend.voice_clone || s.tts_extra_params || defaultTtsParams, null, 2));
|
||||||
$('s-tts-extra-streaming').value = JSON.stringify(byBackend.streaming || s.tts_extra_params || defaultTtsParams, null, 2);
|
sv('s-tts-extra-streaming', JSON.stringify(byBackend.streaming || s.tts_extra_params || defaultTtsParams, null, 2));
|
||||||
$('s-tts-extra-customvoice').value = JSON.stringify(byBackend.customvoice || s.tts_extra_params || defaultTtsParams, null, 2);
|
sv('s-tts-extra-customvoice', JSON.stringify(byBackend.customvoice || s.tts_extra_params || defaultTtsParams, null, 2));
|
||||||
$('s-tts-extra-voice-design').value = JSON.stringify(byBackend.voice_design || s.tts_extra_params || defaultTtsParams, null, 2);
|
sv('s-tts-extra-voice-design', JSON.stringify(byBackend.voice_design || s.tts_extra_params || defaultTtsParams, null, 2));
|
||||||
$('s-tts-extra-nvidia-magpie').value = JSON.stringify(byBackend.nvidia_magpie || {}, null, 2);
|
sv('s-tts-extra-nvidia-magpie', JSON.stringify(byBackend.nvidia_magpie || {}, null, 2));
|
||||||
$('s-tts-extra-nvidia-zeroshot').value = JSON.stringify(byBackend.nvidia_zeroshot || {}, null, 2);
|
sv('s-tts-extra-nvidia-zeroshot',JSON.stringify(byBackend.nvidia_zeroshot|| {}, null, 2));
|
||||||
$('s-tts-extra-nvidia-flow').value = JSON.stringify(byBackend.nvidia_flow || {}, null, 2);
|
sv('s-tts-extra-nvidia-flow', JSON.stringify(byBackend.nvidia_flow || {}, null, 2));
|
||||||
$('s-tts-extra-kokoro').value = JSON.stringify(byBackend.kokoro || {}, null, 2);
|
sv('s-tts-extra-kokoro', JSON.stringify(byBackend.kokoro || {}, null, 2));
|
||||||
const vibevoiceExtraEl = $('s-tts-extra-vibevoice');
|
sv('s-tts-extra-vibevoice', JSON.stringify(byBackend.vibevoice || {}, null, 2));
|
||||||
if (vibevoiceExtraEl) vibevoiceExtraEl.value = JSON.stringify(byBackend.vibevoice || {}, null, 2);
|
sv('s-voice-design-url', s.voice_design_url || 'http://host.docker.internal:8021');
|
||||||
$('s-voice-design-url').value = s.voice_design_url || 'http://host.docker.internal:8021';
|
sv('s-vd-key', s.voice_design_api_key || '');
|
||||||
$('s-vd-key').value = s.voice_design_api_key || '';
|
sv('s-voices-scan-dir', s.voices_scan_dir || '');
|
||||||
$('s-voices-scan-dir').value = s.voices_scan_dir || '';
|
sv('s-output-dir', s.output_dir || '');
|
||||||
$('s-output-dir').value = s.output_dir || '';
|
|
||||||
const seedFinderDirEl = $('s-seed-finder-dir');
|
const seedFinderDirEl = $('s-seed-finder-dir');
|
||||||
if (seedFinderDirEl) seedFinderDirEl.value = s.seed_finder_dir || '';
|
if (seedFinderDirEl) seedFinderDirEl.value = s.seed_finder_dir || '';
|
||||||
const ptDirEl = $('s-pt-dir');
|
const ptDirEl = $('s-pt-dir');
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user