106 lines
3.7 KiB
JavaScript

const _SETTINGS_SPEECH_STORAGE_KEYS={
tts_engine:'hermes-tts-engine',
tts_voice:'hermes-tts-voice',
tts_rate:'hermes-tts-rate',
};
let _settingsSpeechChangedKeys=new Set();
function _normalizeWebUIVersion(value){
if(!value) return '';
const s=String(value).trim();
if(!s) return '';
const lower=s.toLowerCase();
if(lower==='__webui_version__'||lower==='not detected'||lower==='unknown') return '';
return s;
}
function _currentWebUIBundleVersion(){
try{
const raw=window.__HERMES_WEBUI_BUNDLE_VERSION__;
if(!raw) return '';
let s=String(raw);
try{ s=decodeURIComponent(s.replace(/\+/g,' ')); }catch(_){}
return _normalizeWebUIVersion(s);
}catch(_){ return ''; }
}
function _showStaleWebUIClientBanner(clientVersion,serverVersion){
const banner=document.getElementById('staleClientBanner');
if(!banner) return;
const msg=document.getElementById('staleClientMessage');
const versions=document.getElementById('staleClientVersions');
if(msg) msg.textContent='This tab is running a different WebUI version. Hard refresh to restore full functionality.';
if(versions) versions.textContent='Running: '+clientVersion+' → Server: '+serverVersion;
banner.style.display='flex';
}
function checkWebUIVersionSkew(settings){
try{
if(!settings) return;
const client=_currentWebUIBundleVersion();
const server=_normalizeWebUIVersion(settings.webui_version);
if(!client||!server) return;
if(client===server) return;
_showStaleWebUIClientBanner(client,server);
}catch(_){}
}
window.checkWebUIVersionSkew=checkWebUIVersionSkew;
function _startWebUIVersionSkewMonitor(){
let _pollTimer=null;
function _isBannerVisible(){
const banner=document.getElementById('staleClientBanner');
return !!(banner&&banner.style.display==='flex');
}
function _check(){
if(_isBannerVisible()) return;
Promise.resolve().then(function(){ return api('/api/settings'); }).then(function(s){ checkWebUIVersionSkew(s); }).catch(function(){});
}
function _startPoll(){
if(_pollTimer||document.hidden) return;
_pollTimer=setInterval(function(){
if(document.hidden){ clearInterval(_pollTimer); _pollTimer=null; return; }
if(_isBannerVisible()){ clearInterval(_pollTimer); _pollTimer=null; return; }
_check();
},60000);
}
}
function _speechPreferencesPayloadFromUi(){
const payload={};
const ttsVoiceSel=$('settingsTtsVoice');
if(ttsVoiceSel) _setOwnedSpeechPayload(payload,'tts_voice',ttsVoiceSel.value||'');
return payload;
}
function loadSettingsPanel(){
const ttsEngineSel=$('settingsTtsEngine');
if(ttsEngineSel){
ttsEngineSel.onchange=function(){
localStorage.setItem('hermes-tts-engine',this.value);
window._populateTtsVoices();
_schedulePreferencesAutosave();
};
}
// Populate voice selector based on engine
const ttsVoiceSel=$('settingsTtsVoice');
window._populateTtsVoices=function(){
if(!ttsVoiceSel) return;
const engine=localStorage.getItem('hermes-tts-engine')||'browser';
const current=String(_speechSetting('tts_voice','hermes-tts-voice','')||'');
_syncSpeechPreferenceCache('tts_voice',current);
if(engine==='edge'){
const edgeVoices=[
{value:'en-US-AriaNeural',label:'Aria (English, Female)'},
];
ttsVoiceSel.innerHTML='<option value="">Default (Xiaoxiao)</option>';
edgeVoices.forEach(v=>ttsVoiceSel.appendChild(v));
}
};
if(ttsVoiceSel&&'speechSynthesis' in window){
window._populateTtsVoices();
ttsVoiceSel.onchange=function(){_markSpeechPreferenceChanged('tts_voice');localStorage.setItem('hermes-tts-voice',this.value);_schedulePreferencesAutosave();};
}
// TTS rate/pitch sliders
}