Add ink integration UI and media playback

This commit is contained in:
2026-05-15 21:23:46 +02:00
parent 44dc64f830
commit f2e786d5bc
89 changed files with 6561 additions and 556 deletions
+41 -20
View File
@@ -46,9 +46,30 @@ class OptionsUIModule extends BaseModule {
'dispatchApiChangeEvent',
'getPreference',
'updatePreference',
'updateUIText',
'renderProviderStatuses'
]);
}
t(key, params = {}) {
const localization = this.getModule('localization');
return localization?.translate?.(key, params) || key;
}
updateUIText() {
if (!this.modal) return;
const wasOpen = this.modal.style.display === 'flex';
this.modal.remove();
this.modal = null;
this.elements = {};
this.createModal();
this.setupPreferenceBindings();
this.populateTtsSystems();
this.populateLanguages();
this.populateVoices();
this.renderProviderStatuses();
if (wasOpen) this.show();
}
/**
* Dispatches an API change event
@@ -135,7 +156,7 @@ class OptionsUIModule extends BaseModule {
header.className = 'modal-header';
const title = document.createElement('h2');
title.textContent = 'Options';
title.textContent = this.t('options.title');
header.appendChild(title);
const closeButton = document.createElement('span');
@@ -156,7 +177,7 @@ class OptionsUIModule extends BaseModule {
appSettingsSection.className = 'options-section';
const appSettingsTitle = document.createElement('h3');
appSettingsTitle.textContent = 'Application Settings';
appSettingsTitle.textContent = this.t('options.applicationSettings');
appSettingsSection.appendChild(appSettingsTitle);
// Language
@@ -164,7 +185,7 @@ class OptionsUIModule extends BaseModule {
languageContainer.className = 'option-item';
const languageLabel = document.createElement('label');
languageLabel.textContent = 'Language:';
languageLabel.textContent = this.t('options.language') + ':';
languageContainer.appendChild(languageLabel);
this.elements.language = createUIElement('select', {
@@ -178,7 +199,7 @@ class OptionsUIModule extends BaseModule {
speedContainer.className = 'option-item';
const speedLabel = document.createElement('label');
speedLabel.textContent = 'Speed:';
speedLabel.textContent = this.t('options.speed') + ':';
speedContainer.appendChild(speedLabel);
const speedValue = document.createElement('span');
@@ -210,7 +231,7 @@ class OptionsUIModule extends BaseModule {
ttsSection.className = 'options-section';
const ttsTitle = document.createElement('h3');
ttsTitle.textContent = 'Text-to-Speech';
ttsTitle.textContent = this.t('options.speech');
ttsSection.appendChild(ttsTitle);
// TTS Enable
@@ -218,7 +239,7 @@ class OptionsUIModule extends BaseModule {
ttsEnableContainer.className = 'option-item';
const ttsEnableLabel = document.createElement('label');
ttsEnableLabel.textContent = 'Enable TTS:';
ttsEnableLabel.textContent = this.t('options.enableSpeech') + ':';
ttsEnableContainer.appendChild(ttsEnableLabel);
this.elements.ttsEnabled = createUIElement('input', {
@@ -233,7 +254,7 @@ class OptionsUIModule extends BaseModule {
ttsSystemContainer.className = 'option-item';
const ttsSystemLabel = document.createElement('label');
ttsSystemLabel.textContent = 'TTS System:';
ttsSystemLabel.textContent = this.t('options.provider') + ':';
ttsSystemContainer.appendChild(ttsSystemLabel);
this.elements.ttsSystem = createUIElement('select', {
@@ -252,7 +273,7 @@ class OptionsUIModule extends BaseModule {
ttsVoiceContainer.className = 'option-item';
const ttsVoiceLabel = document.createElement('label');
ttsVoiceLabel.textContent = 'Voice:';
ttsVoiceLabel.textContent = this.t('options.voice') + ':';
ttsVoiceContainer.appendChild(ttsVoiceLabel);
this.elements.ttsVoice = createUIElement('select', {
@@ -272,7 +293,7 @@ class OptionsUIModule extends BaseModule {
audioSection.className = 'options-section';
const audioTitle = document.createElement('h3');
audioTitle.textContent = 'Audio';
audioTitle.textContent = this.t('options.audio');
audioSection.appendChild(audioTitle);
// Master Volume
@@ -280,7 +301,7 @@ class OptionsUIModule extends BaseModule {
masterVolumeContainer.className = 'option-item';
const masterVolumeLabel = document.createElement('label');
masterVolumeLabel.textContent = 'Master Volume:';
masterVolumeLabel.textContent = this.t('options.masterVolume') + ':';
masterVolumeContainer.appendChild(masterVolumeLabel);
const masterVolumeValue = document.createElement('span');
@@ -310,7 +331,7 @@ class OptionsUIModule extends BaseModule {
ttsVolumeContainer.className = 'option-item';
const ttsVolumeLabel = document.createElement('label');
ttsVolumeLabel.textContent = 'Speech Volume:';
ttsVolumeLabel.textContent = this.t('options.speechVolume') + ':';
ttsVolumeContainer.appendChild(ttsVolumeLabel);
const ttsVolumeValue = document.createElement('span');
@@ -340,7 +361,7 @@ class OptionsUIModule extends BaseModule {
musicVolumeContainer.className = 'option-item';
const musicVolumeLabel = document.createElement('label');
musicVolumeLabel.textContent = 'Music Volume:';
musicVolumeLabel.textContent = this.t('options.musicVolume') + ':';
musicVolumeContainer.appendChild(musicVolumeLabel);
const musicVolumeValue = document.createElement('span');
@@ -370,7 +391,7 @@ class OptionsUIModule extends BaseModule {
sfxVolumeContainer.className = 'option-item';
const sfxVolumeLabel = document.createElement('label');
sfxVolumeLabel.textContent = 'Sound Effects Volume:';
sfxVolumeLabel.textContent = this.t('options.sfxVolume') + ':';
sfxVolumeContainer.appendChild(sfxVolumeLabel);
const sfxVolumeValue = document.createElement('span');
@@ -404,7 +425,7 @@ class OptionsUIModule extends BaseModule {
footer.className = 'modal-footer';
const closeModalButton = document.createElement('button');
closeModalButton.textContent = 'Close';
closeModalButton.textContent = this.t('options.close');
closeModalButton.onclick = () => this.hide();
footer.appendChild(closeModalButton);
@@ -432,7 +453,7 @@ class OptionsUIModule extends BaseModule {
elevenLabsSettings.style.display = 'none';
const elevenLabsTitle = document.createElement('h3');
elevenLabsTitle.textContent = 'ElevenLabs API Settings';
elevenLabsTitle.textContent = this.t('options.elevenLabsSettings');
elevenLabsSettings.appendChild(elevenLabsTitle);
// ElevenLabs API Key
@@ -440,7 +461,7 @@ class OptionsUIModule extends BaseModule {
elevenLabsApiKeyContainer.className = 'option-item';
const elevenLabsApiKeyLabel = document.createElement('label');
elevenLabsApiKeyLabel.textContent = 'API Key:';
elevenLabsApiKeyLabel.textContent = this.t('options.apiKey') + ':';
elevenLabsApiKeyContainer.appendChild(elevenLabsApiKeyLabel);
this.elements.elevenLabsApiKey = createUIElement('input', {
@@ -455,7 +476,7 @@ class OptionsUIModule extends BaseModule {
elevenLabsApiUrlContainer.className = 'option-item';
const elevenLabsApiUrlLabel = document.createElement('label');
elevenLabsApiUrlLabel.textContent = 'API URL:';
elevenLabsApiUrlLabel.textContent = this.t('options.apiUrl') + ':';
elevenLabsApiUrlContainer.appendChild(elevenLabsApiUrlLabel);
this.elements.elevenLabsApiUrl = createUIElement('input', {
@@ -471,7 +492,7 @@ class OptionsUIModule extends BaseModule {
openaiSettings.style.display = 'none';
const openaiTitle = document.createElement('h3');
openaiTitle.textContent = 'OpenAI API Settings';
openaiTitle.textContent = this.t('options.openAiSettings');
openaiSettings.appendChild(openaiTitle);
// OpenAI API Key
@@ -479,7 +500,7 @@ class OptionsUIModule extends BaseModule {
openaiApiKeyContainer.className = 'option-item';
const openaiApiKeyLabel = document.createElement('label');
openaiApiKeyLabel.textContent = 'API Key:';
openaiApiKeyLabel.textContent = this.t('options.apiKey') + ':';
openaiApiKeyContainer.appendChild(openaiApiKeyLabel);
this.elements.openaiApiKey = createUIElement('input', {
@@ -494,7 +515,7 @@ class OptionsUIModule extends BaseModule {
openaiApiUrlContainer.className = 'option-item';
const openaiApiUrlLabel = document.createElement('label');
openaiApiUrlLabel.textContent = 'API URL:';
openaiApiUrlLabel.textContent = this.t('options.apiUrl') + ':';
openaiApiUrlContainer.appendChild(openaiApiUrlLabel);
this.elements.openaiApiUrl = createUIElement('input', {