Added support for openai api tts.
This commit is contained in:
+273
-25
@@ -35,7 +35,8 @@ class OptionsUIModule extends BaseModule {
|
||||
'showReloadNotice',
|
||||
'toggle',
|
||||
'setupEventListeners',
|
||||
'saveCurrentSettings'
|
||||
'saveCurrentSettings',
|
||||
'setupApiUrlFields'
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -85,6 +86,9 @@ class OptionsUIModule extends BaseModule {
|
||||
// Apply settings
|
||||
this.applySettings();
|
||||
|
||||
// Setup API URLs with default values if needed
|
||||
this.setupApiUrlFields();
|
||||
|
||||
console.log('Options UI: Initialization complete');
|
||||
}, 1000); // 1 second delay
|
||||
});
|
||||
@@ -266,6 +270,127 @@ class OptionsUIModule extends BaseModule {
|
||||
|
||||
ttsSection.appendChild(ttsVoiceContainer);
|
||||
|
||||
// API TTS Provider Settings (ElevenLabs and OpenAI)
|
||||
// Container for API settings that will be shown/hidden based on selected TTS system
|
||||
const apiSettingsContainer = document.createElement('div');
|
||||
apiSettingsContainer.id = 'api-tts-settings';
|
||||
apiSettingsContainer.className = 'api-settings-container';
|
||||
apiSettingsContainer.style.display = 'none';
|
||||
|
||||
// ElevenLabs API Key
|
||||
const elevenLabsApiKeyContainer = document.createElement('div');
|
||||
elevenLabsApiKeyContainer.className = 'options-row elevenlabs-setting';
|
||||
elevenLabsApiKeyContainer.dataset.provider = 'elevenlabs';
|
||||
|
||||
const elevenLabsApiKeyLabel = document.createElement('label');
|
||||
elevenLabsApiKeyLabel.textContent = 'ElevenLabs API Key:';
|
||||
elevenLabsApiKeyContainer.appendChild(elevenLabsApiKeyLabel);
|
||||
|
||||
const elevenLabsApiKey = document.createElement('input');
|
||||
elevenLabsApiKey.type = 'password';
|
||||
elevenLabsApiKey.id = 'elevenlabs-api-key';
|
||||
elevenLabsApiKey.placeholder = 'Enter your ElevenLabs API key';
|
||||
elevenLabsApiKey.addEventListener('change', (e) => {
|
||||
const persistenceManager = this.getModule('persistence-manager');
|
||||
if (persistenceManager) {
|
||||
persistenceManager.updatePreference('tts', 'elevenlabs_api_key', e.target.value);
|
||||
|
||||
// Notify TTS system that API key has changed
|
||||
document.dispatchEvent(new CustomEvent('tts:api:keyChanged', {
|
||||
detail: { provider: 'elevenlabs', key: e.target.value }
|
||||
}));
|
||||
}
|
||||
});
|
||||
elevenLabsApiKeyContainer.appendChild(elevenLabsApiKey);
|
||||
|
||||
apiSettingsContainer.appendChild(elevenLabsApiKeyContainer);
|
||||
|
||||
// ElevenLabs API Base URL
|
||||
const elevenLabsApiUrlContainer = document.createElement('div');
|
||||
elevenLabsApiUrlContainer.className = 'options-row elevenlabs-setting';
|
||||
elevenLabsApiUrlContainer.dataset.provider = 'elevenlabs';
|
||||
|
||||
const elevenLabsApiUrlLabel = document.createElement('label');
|
||||
elevenLabsApiUrlLabel.textContent = 'ElevenLabs API URL:';
|
||||
elevenLabsApiUrlContainer.appendChild(elevenLabsApiUrlLabel);
|
||||
|
||||
const elevenLabsApiUrl = document.createElement('input');
|
||||
elevenLabsApiUrl.type = 'text';
|
||||
elevenLabsApiUrl.id = 'elevenlabs-api-url';
|
||||
elevenLabsApiUrl.placeholder = 'https://api.elevenlabs.io/v1';
|
||||
elevenLabsApiUrl.addEventListener('change', (e) => {
|
||||
const persistenceManager = this.getModule('persistence-manager');
|
||||
if (persistenceManager) {
|
||||
persistenceManager.updatePreference('tts', 'elevenlabs_api_base_url', e.target.value);
|
||||
|
||||
// Notify TTS system that API URL has changed
|
||||
document.dispatchEvent(new CustomEvent('tts:api:urlChanged', {
|
||||
detail: { provider: 'elevenlabs', url: e.target.value }
|
||||
}));
|
||||
}
|
||||
});
|
||||
elevenLabsApiUrlContainer.appendChild(elevenLabsApiUrl);
|
||||
|
||||
apiSettingsContainer.appendChild(elevenLabsApiUrlContainer);
|
||||
|
||||
// OpenAI API Key
|
||||
const openaiApiKeyContainer = document.createElement('div');
|
||||
openaiApiKeyContainer.className = 'options-row openai-setting';
|
||||
openaiApiKeyContainer.dataset.provider = 'openai';
|
||||
|
||||
const openaiApiKeyLabel = document.createElement('label');
|
||||
openaiApiKeyLabel.textContent = 'OpenAI API Key:';
|
||||
openaiApiKeyContainer.appendChild(openaiApiKeyLabel);
|
||||
|
||||
const openaiApiKey = document.createElement('input');
|
||||
openaiApiKey.type = 'password';
|
||||
openaiApiKey.id = 'openai-api-key';
|
||||
openaiApiKey.placeholder = 'Enter your OpenAI API key';
|
||||
openaiApiKey.addEventListener('change', (e) => {
|
||||
const persistenceManager = this.getModule('persistence-manager');
|
||||
if (persistenceManager) {
|
||||
persistenceManager.updatePreference('tts', 'openai_api_key', e.target.value);
|
||||
|
||||
// Notify TTS system that API key has changed
|
||||
document.dispatchEvent(new CustomEvent('tts:api:keyChanged', {
|
||||
detail: { provider: 'openai', key: e.target.value }
|
||||
}));
|
||||
}
|
||||
});
|
||||
openaiApiKeyContainer.appendChild(openaiApiKey);
|
||||
|
||||
apiSettingsContainer.appendChild(openaiApiKeyContainer);
|
||||
|
||||
// OpenAI API Base URL
|
||||
const openaiApiUrlContainer = document.createElement('div');
|
||||
openaiApiUrlContainer.className = 'options-row openai-setting';
|
||||
openaiApiUrlContainer.dataset.provider = 'openai';
|
||||
|
||||
const openaiApiUrlLabel = document.createElement('label');
|
||||
openaiApiUrlLabel.textContent = 'OpenAI API URL:';
|
||||
openaiApiUrlContainer.appendChild(openaiApiUrlLabel);
|
||||
|
||||
const openaiApiUrl = document.createElement('input');
|
||||
openaiApiUrl.type = 'text';
|
||||
openaiApiUrl.id = 'openai-api-url';
|
||||
openaiApiUrl.placeholder = 'https://api.openai.com/v1';
|
||||
openaiApiUrl.addEventListener('change', (e) => {
|
||||
const persistenceManager = this.getModule('persistence-manager');
|
||||
if (persistenceManager) {
|
||||
persistenceManager.updatePreference('tts', 'openai_api_base_url', e.target.value);
|
||||
|
||||
// Notify TTS system that API URL has changed
|
||||
document.dispatchEvent(new CustomEvent('tts:api:urlChanged', {
|
||||
detail: { provider: 'openai', url: e.target.value }
|
||||
}));
|
||||
}
|
||||
});
|
||||
openaiApiUrlContainer.appendChild(openaiApiUrl);
|
||||
|
||||
apiSettingsContainer.appendChild(openaiApiUrlContainer);
|
||||
|
||||
ttsSection.appendChild(apiSettingsContainer);
|
||||
|
||||
// Speed controls
|
||||
const speedContainer = document.createElement('div');
|
||||
speedContainer.className = 'options-row';
|
||||
@@ -494,7 +619,12 @@ class OptionsUIModule extends BaseModule {
|
||||
effectsVolume,
|
||||
reloadNotice,
|
||||
speechRate: speedSlider,
|
||||
ttsSpeechToggle
|
||||
ttsSpeechToggle,
|
||||
apiSettingsContainer,
|
||||
elevenLabsApiKey,
|
||||
elevenLabsApiUrl,
|
||||
openaiApiKey,
|
||||
openaiApiUrl
|
||||
};
|
||||
}
|
||||
|
||||
@@ -542,41 +672,78 @@ class OptionsUIModule extends BaseModule {
|
||||
// Clear existing options
|
||||
this.elements.ttsSystem.innerHTML = '';
|
||||
|
||||
// Add "None" option first
|
||||
// Add 'None' option
|
||||
const noneOption = document.createElement('option');
|
||||
noneOption.value = 'none';
|
||||
noneOption.textContent = 'None (Disable TTS)';
|
||||
noneOption.textContent = 'None';
|
||||
this.elements.ttsSystem.appendChild(noneOption);
|
||||
|
||||
// Get available handlers
|
||||
// Get available TTS handlers
|
||||
const handlers = ttsFactory.getAvailableHandlers();
|
||||
console.log('Options UI: Available TTS handlers:', handlers.map(h => h.id).join(', '));
|
||||
|
||||
// Add all registered handlers
|
||||
for (const id in handlers) {
|
||||
// Add options for each handler
|
||||
for (const handler of handlers) {
|
||||
const option = document.createElement('option');
|
||||
option.value = id;
|
||||
option.textContent = this.getTtsSystemName(id);
|
||||
option.value = handler.id;
|
||||
option.textContent = this.getTtsSystemName(handler.id);
|
||||
this.elements.ttsSystem.appendChild(option);
|
||||
}
|
||||
|
||||
// If no handlers available, add a disabled option
|
||||
if (this.elements.ttsSystem.options.length === 1) {
|
||||
const option = document.createElement('option');
|
||||
option.value = '';
|
||||
option.textContent = 'No TTS systems available';
|
||||
option.disabled = true;
|
||||
this.elements.ttsSystem.appendChild(option);
|
||||
}
|
||||
// Set the current active handler
|
||||
const activeHandler = ttsFactory.getActiveHandler();
|
||||
console.log('Options UI: Active TTS handler:', activeHandler ? (activeHandler.getId ? activeHandler.getId() : activeHandler.id) : 'none');
|
||||
|
||||
// Set the current provider value in the dropdown
|
||||
if (this.persistenceManager) {
|
||||
const provider = this.persistenceManager.getPreference('tts', 'provider');
|
||||
if (provider) {
|
||||
const option = Array.from(this.elements.ttsSystem.options).find(opt => opt.value === provider);
|
||||
if (option) {
|
||||
this.elements.ttsSystem.value = provider;
|
||||
}
|
||||
if (activeHandler) {
|
||||
if (typeof activeHandler.getId === 'function') {
|
||||
// Use getId() if available
|
||||
this.elements.ttsSystem.value = activeHandler.getId();
|
||||
} else if (activeHandler.id) {
|
||||
// Otherwise try to use the id property
|
||||
this.elements.ttsSystem.value = activeHandler.id;
|
||||
} else {
|
||||
// If no id is available, default to 'none'
|
||||
this.elements.ttsSystem.value = 'none';
|
||||
console.warn('Options UI: Active TTS handler has no ID');
|
||||
}
|
||||
} else {
|
||||
this.elements.ttsSystem.value = 'none';
|
||||
}
|
||||
|
||||
// Show/hide API settings based on selected TTS system
|
||||
this.updateApiSettingsVisibility();
|
||||
|
||||
// Add change event to show/hide API settings
|
||||
this.elements.ttsSystem.addEventListener('change', () => {
|
||||
this.updateApiSettingsVisibility();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Update visibility of API settings based on selected TTS system
|
||||
*/
|
||||
updateApiSettingsVisibility() {
|
||||
if (!this.elements || !this.elements.apiSettingsContainer) return;
|
||||
|
||||
const selectedProvider = this.elements.ttsSystem.value;
|
||||
|
||||
// Show/hide API settings container based on whether an API provider is selected
|
||||
if (selectedProvider === 'elevenlabs' || selectedProvider === 'openai') {
|
||||
this.elements.apiSettingsContainer.style.display = 'block';
|
||||
|
||||
// Show/hide provider-specific settings
|
||||
const elevenLabsSettings = document.querySelectorAll('.elevenlabs-setting');
|
||||
const openaiSettings = document.querySelectorAll('.openai-setting');
|
||||
|
||||
elevenLabsSettings.forEach(element => {
|
||||
element.style.display = selectedProvider === 'elevenlabs' ? 'flex' : 'none';
|
||||
});
|
||||
|
||||
openaiSettings.forEach(element => {
|
||||
element.style.display = selectedProvider === 'openai' ? 'flex' : 'none';
|
||||
});
|
||||
} else {
|
||||
this.elements.apiSettingsContainer.style.display = 'none';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -761,6 +928,26 @@ class OptionsUIModule extends BaseModule {
|
||||
if (this.elements.ttsSpeechToggle) {
|
||||
this.elements.ttsSpeechToggle.checked = prefs.tts.enabled;
|
||||
}
|
||||
|
||||
// ElevenLabs API Key
|
||||
if (this.elements.elevenLabsApiKey) {
|
||||
this.elements.elevenLabsApiKey.value = prefs.tts.elevenlabs_api_key;
|
||||
}
|
||||
|
||||
// ElevenLabs API Base URL
|
||||
if (this.elements.elevenLabsApiUrl) {
|
||||
this.elements.elevenLabsApiUrl.value = prefs.tts.elevenlabs_api_base_url;
|
||||
}
|
||||
|
||||
// OpenAI API Key
|
||||
if (this.elements.openaiApiKey) {
|
||||
this.elements.openaiApiKey.value = prefs.tts.openai_api_key;
|
||||
}
|
||||
|
||||
// OpenAI API Base URL
|
||||
if (this.elements.openaiApiUrl) {
|
||||
this.elements.openaiApiUrl.value = prefs.tts.openai_api_base_url;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -873,6 +1060,22 @@ class OptionsUIModule extends BaseModule {
|
||||
// Save text speed setting
|
||||
const textSpeed = parseInt(this.elements.textSpeed.value);
|
||||
this.persistenceManager.updatePreference('animation', 'speed', textSpeed);
|
||||
|
||||
// Save ElevenLabs API Key
|
||||
const elevenLabsApiKey = this.elements.elevenLabsApiKey.value;
|
||||
this.persistenceManager.updatePreference('tts', 'elevenlabs_api_key', elevenLabsApiKey);
|
||||
|
||||
// Save ElevenLabs API Base URL
|
||||
const elevenLabsApiUrl = this.elements.elevenLabsApiUrl.value;
|
||||
this.persistenceManager.updatePreference('tts', 'elevenlabs_api_base_url', elevenLabsApiUrl);
|
||||
|
||||
// Save OpenAI API Key
|
||||
const openaiApiKey = this.elements.openaiApiKey.value;
|
||||
this.persistenceManager.updatePreference('tts', 'openai_api_key', openaiApiKey);
|
||||
|
||||
// Save OpenAI API Base URL
|
||||
const openaiApiUrl = this.elements.openaiApiUrl.value;
|
||||
this.persistenceManager.updatePreference('tts', 'openai_api_base_url', openaiApiUrl);
|
||||
}
|
||||
|
||||
setupEventListeners() {
|
||||
@@ -944,6 +1147,51 @@ class OptionsUIModule extends BaseModule {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
setupApiUrlFields() {
|
||||
if (!this.elements) return;
|
||||
|
||||
const persistenceManager = this.getModule('persistence-manager');
|
||||
if (!persistenceManager) return;
|
||||
|
||||
// Set up ElevenLabs API URL
|
||||
if (this.elements.elevenLabsApiUrl) {
|
||||
const savedUrl = persistenceManager.getPreference('tts', 'elevenlabs_api_url');
|
||||
if (!savedUrl) {
|
||||
const defaultUrl = 'https://api.elevenlabs.io/v1';
|
||||
console.log('Options UI: Setting default ElevenLabs API URL:', defaultUrl);
|
||||
this.elements.elevenLabsApiUrl.value = defaultUrl;
|
||||
persistenceManager.updatePreference('tts', 'elevenlabs_api_url', defaultUrl);
|
||||
|
||||
// Also dispatch the change event to notify the handler
|
||||
window.dispatchEvent(new CustomEvent('tts:api:urlChanged', {
|
||||
detail: {
|
||||
provider: 'elevenlabs',
|
||||
url: defaultUrl
|
||||
}
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
// Set up OpenAI API URL
|
||||
if (this.elements.openaiApiUrl) {
|
||||
const savedUrl = persistenceManager.getPreference('tts', 'openai_api_url');
|
||||
if (!savedUrl) {
|
||||
const defaultUrl = 'https://api.openai.com/v1';
|
||||
console.log('Options UI: Setting default OpenAI API URL:', defaultUrl);
|
||||
this.elements.openaiApiUrl.value = defaultUrl;
|
||||
persistenceManager.updatePreference('tts', 'openai_api_url', defaultUrl);
|
||||
|
||||
// Also dispatch the change event to notify the handler
|
||||
window.dispatchEvent(new CustomEvent('tts:api:urlChanged', {
|
||||
detail: {
|
||||
provider: 'openai',
|
||||
url: defaultUrl
|
||||
}
|
||||
}));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Create the singleton instance
|
||||
|
||||
Reference in New Issue
Block a user