diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md
index 85eb40a..8edf86f 100644
--- a/docs/CHANGELOG.md
+++ b/docs/CHANGELOG.md
@@ -4,6 +4,12 @@ All notable changes to the KoalaSync browser extension and relay server.
---
+## Unreleased
+
+### Added
+- **Extension: Editable Hide-Clutter list** — Adds a validated, deduplicated domain editor in Settings, prefilled with the shipped blacklist, with a defaults reset and per-device persistence in `chrome.storage.local`.
+- **Extension: Independent default audio boost** — Adds a configurable `0–20 dB` output gain in half-decibel steps. The boost works with or without the compressor and applies live to the selected video tab.
+
## [v3.0.2] — 2026-07-31
This release adds three focused chat improvements: encrypted quick-reaction emojis,
diff --git a/docs/ROADMAP.md b/docs/ROADMAP.md
index a9744a2..5cd8aba 100644
--- a/docs/ROADMAP.md
+++ b/docs/ROADMAP.md
@@ -30,24 +30,6 @@
*Prioritized for upcoming phases.*
-### Customizable Hide-Clutter Tab List
-
-- **Priority:** P2
-- **Category:** UX / Personalization
-- **Background:** The Hide Clutter tabs feature already has a blacklist. Users should be
- able to extend that list with tabs they frequently keep open but never want included.
-- **Planned behavior:** Provide a custom editable list, prefilled with the existing
- blacklist, so users can add and manage their own entries.
-
-### Default Audio Boost
-
-- **Priority:** P2
-- **Category:** Audio / Playback
-- **Background:** Extend the audio settings with a configurable default boost that raises
- the level by a chosen amount in dB.
-- **Planned behavior:** Apply the default gain in addition to the existing compressor,
- with the boost controlled independently in the audio settings.
-
### Invite link with target URL for auto-redirect
- **Priority:** P2
diff --git a/extension/audio-options.css b/extension/audio-options.css
index 8c3be91..9030c19 100644
--- a/extension/audio-options.css
+++ b/extension/audio-options.css
@@ -107,6 +107,14 @@ h2 {
font-size: 16px;
}
+.section-copy {
+ max-width: 560px;
+ margin: 6px 0 0;
+ color: var(--text-muted);
+ font-size: 12px;
+ line-height: 1.5;
+}
+
.panel {
background: var(--card);
border: 1px solid var(--border);
diff --git a/extension/audio-options.html b/extension/audio-options.html
index 86181c8..5eea660 100644
--- a/extension/audio-options.html
+++ b/extension/audio-options.html
@@ -23,6 +23,23 @@
+
+
+
+
Default Boost
+
Raises video volume independently of the compressor. Set 0 dB to disable.
+
+
+
+
+
+
+
+ dB
+
+
+
+
Compressor
diff --git a/extension/audio-options.js b/extension/audio-options.js
index 5342377..d850b56 100644
--- a/extension/audio-options.js
+++ b/extension/audio-options.js
@@ -10,12 +10,14 @@ const PRESETS = {
const DEFAULT_AUDIO_SETTINGS = {
enabled: false,
+ boostDb: 0,
compressor: {
enabled: false,
preset: 'recommended',
customParams: { ...PRESETS.custom }
}
};
+const BOOST_DB_LIMITS = { min: 0, max: 20 };
const PARAM_LIMITS = {
threshold: { min: -60, max: 0 },
knee: { min: 0, max: 40 },
@@ -26,9 +28,11 @@ const PARAM_LIMITS = {
const elements = {
audioEnabled: document.getElementById('audioEnabled'),
+ boostRange: document.getElementById('boostRange'),
+ boostNumber: document.getElementById('boostNumber'),
compressorEnabled: document.getElementById('compressorEnabled'),
presetInputs: Array.from(document.querySelectorAll('input[name="preset"]')),
- controlRows: Array.from(document.querySelectorAll('.control-row')),
+ controlRows: Array.from(document.querySelectorAll('.control-row[data-param]')),
backLink: document.getElementById('backLink')
};
@@ -41,12 +45,20 @@ function cloneDefaultSettings() {
let currentSettings = cloneDefaultSettings();
+function normalizeBoostDb(value) {
+ const parsed = Number(value);
+ if (!Number.isFinite(parsed)) return DEFAULT_AUDIO_SETTINGS.boostDb;
+ const clamped = Math.min(BOOST_DB_LIMITS.max, Math.max(BOOST_DB_LIMITS.min, parsed));
+ return Math.round(clamped * 2) / 2;
+}
+
function mergeAudioSettings(settings = {}) {
const safeSettings = settings && typeof settings === 'object' ? settings : {};
const defaults = cloneDefaultSettings();
return {
...defaults,
...safeSettings,
+ boostDb: normalizeBoostDb(safeSettings.boostDb),
compressor: {
...defaults.compressor,
...(safeSettings.compressor || {}),
@@ -61,10 +73,18 @@ function mergeAudioSettings(settings = {}) {
function debounceSave() {
if (saveTimer) clearTimeout(saveTimer);
saveTimer = setTimeout(() => {
+ saveTimer = null;
chrome.storage.local.set({ audioSettings: currentSettings });
}, 40);
}
+async function flushPendingSave() {
+ if (!saveTimer) return;
+ clearTimeout(saveTimer);
+ saveTimer = null;
+ await chrome.storage.local.set({ audioSettings: currentSettings });
+}
+
function getParamValue(param, value, isMsInput = false) {
const parsed = Number(value);
const candidate = Number.isFinite(parsed)
@@ -84,6 +104,9 @@ function formatNumber(value, param, isMsInput = false) {
function render() {
isRendering = true;
elements.audioEnabled.checked = currentSettings.enabled === true;
+ const boostDb = normalizeBoostDb(currentSettings.boostDb);
+ elements.boostRange.value = boostDb;
+ elements.boostNumber.value = boostDb;
elements.compressorEnabled.checked = currentSettings.compressor.enabled === true;
const selectedPreset = currentSettings.compressor.preset || 'recommended';
@@ -106,6 +129,17 @@ function render() {
isRendering = false;
}
+function setBoostDb(value) {
+ currentSettings.boostDb = normalizeBoostDb(value);
+ if (currentSettings.boostDb > 0) {
+ currentSettings.enabled = true;
+ } else if (!currentSettings.compressor.enabled) {
+ currentSettings.enabled = false;
+ }
+ render();
+ debounceSave();
+}
+
function setPreset(preset) {
currentSettings.compressor.preset = preset;
if (preset === 'custom') {
@@ -138,16 +172,27 @@ async function init() {
elements.audioEnabled.addEventListener('change', () => {
currentSettings.enabled = elements.audioEnabled.checked;
- if (currentSettings.enabled && !currentSettings.compressor.enabled) {
+ if (currentSettings.enabled && !currentSettings.compressor.enabled && currentSettings.boostDb === 0) {
currentSettings.compressor.enabled = true;
}
render();
debounceSave();
});
+[elements.boostRange, elements.boostNumber].forEach(input => {
+ input.addEventListener('input', () => {
+ if (isRendering) return;
+ setBoostDb(input.value);
+ });
+});
+
elements.compressorEnabled.addEventListener('change', () => {
currentSettings.compressor.enabled = elements.compressorEnabled.checked;
- if (currentSettings.compressor.enabled) currentSettings.enabled = true;
+ if (currentSettings.compressor.enabled) {
+ currentSettings.enabled = true;
+ } else if (currentSettings.boostDb === 0) {
+ currentSettings.enabled = false;
+ }
render();
debounceSave();
});
@@ -181,12 +226,17 @@ chrome.storage.onChanged.addListener((changes, area) => {
});
if (elements.backLink) {
- elements.backLink.addEventListener('click', (e) => {
+ elements.backLink.addEventListener('click', async (e) => {
e.preventDefault();
+ await flushPendingSave();
window.close();
});
}
+window.addEventListener('pagehide', () => {
+ flushPendingSave().catch(() => {});
+});
+
init().catch(err => {
console.error('[AudioOptions] Failed to initialize:', err);
});
diff --git a/extension/background.js b/extension/background.js
index c945667..3d3d99d 100644
--- a/extension/background.js
+++ b/extension/background.js
@@ -465,7 +465,7 @@ function emitEpisodeLobbyForCurrentPrivacy() {
const LEGACY_SYNC_KEYS = [
'serverUrl', 'useCustomServer', 'roomId', 'password', 'chatKey',
'chatEnabled', 'chatNotifications', 'chatPosition', 'chatSize', 'chatStartMode', 'chatReactionDisplay', 'username',
- 'filterNoise', 'autoSyncNextEpisode', 'forceSyncMode',
+ 'filterNoise', 'customBlacklistDomains', 'autoSyncNextEpisode', 'forceSyncMode',
'browserNotifications', 'autoCopyInvite', 'locale', 'audioSettings',
'titlePrivacyMode', 'sendTabTitle', 'mediaTitlePrivacyMode'
];
diff --git a/extension/content.js b/extension/content.js
index fbe7147..8e8bdd9 100644
--- a/extension/content.js
+++ b/extension/content.js
@@ -250,6 +250,11 @@
if (area === 'local' && changes.autoSyncNextEpisode) {
_autoSyncEnabled = changes.autoSyncNextEpisode.newValue !== false;
}
+ if (area === 'local' && changes.audioSettings) {
+ _audioSettings = mergeAudioSettings(changes.audioSettings.newValue);
+ const video = findVideo();
+ if (video && _audioProcessingAllowed) applyAudioSettings(video, _audioSettings);
+ }
}
chrome.storage.onChanged.addListener(handleStorageChanged);
@@ -605,24 +610,32 @@
smooth: { threshold: -30, ratio: 1.5, attack: 0.030, release: 0.250, knee: 20 },
custom: { threshold: -24, ratio: 12, attack: 0.003, release: 0.250, knee: 30 }
};
- const DEFAULT_AUDIO_SETTINGS = {
- enabled: false,
- compressor: {
+ const DEFAULT_AUDIO_SETTINGS = {
+ enabled: false,
+ boostDb: 0,
+ compressor: {
enabled: false,
preset: 'recommended',
customParams: { ...AUDIO_PRESETS.custom }
}
};
let audioCtx = null;
- let audioChains = new WeakMap();
- let currentAudioVideo = null;
+ let audioChains = new WeakMap();
+ let currentAudioVideo = null;
+
+ function normalizeBoostDb(value) {
+ const parsed = Number(value);
+ if (!Number.isFinite(parsed)) return DEFAULT_AUDIO_SETTINGS.boostDb;
+ return Math.min(20, Math.max(0, Math.round(parsed * 2) / 2));
+ }
function mergeAudioSettings(settings = {}) {
const safeSettings = settings && typeof settings === 'object' ? settings : {};
- return {
- ...DEFAULT_AUDIO_SETTINGS,
- ...safeSettings,
- compressor: {
+ return {
+ ...DEFAULT_AUDIO_SETTINGS,
+ ...safeSettings,
+ boostDb: normalizeBoostDb(safeSettings.boostDb),
+ compressor: {
...DEFAULT_AUDIO_SETTINGS.compressor,
...(safeSettings.compressor || {}),
customParams: {
@@ -665,21 +678,31 @@
if (!ctx) return null;
try {
- const src = ctx.createMediaElementSource(videoEl);
- const compressor = ctx.createDynamicsCompressor();
- const dryGain = ctx.createGain();
- const compGain = ctx.createGain();
-
- src.connect(dryGain);
- dryGain.connect(ctx.destination);
- src.connect(compressor);
- compressor.connect(compGain);
- compGain.connect(ctx.destination);
-
- dryGain.gain.value = 1;
- compGain.gain.value = 0;
-
- const chain = { compressor, dryGain, compGain, active: false };
+ const src = ctx.createMediaElementSource(videoEl);
+ const compressor = ctx.createDynamicsCompressor();
+ const dryGain = ctx.createGain();
+ const compGain = ctx.createGain();
+ const outputGain = ctx.createGain();
+ const limiter = ctx.createDynamicsCompressor();
+
+ src.connect(dryGain);
+ dryGain.connect(outputGain);
+ src.connect(compressor);
+ compressor.connect(compGain);
+ compGain.connect(outputGain);
+ outputGain.connect(limiter);
+ limiter.connect(ctx.destination);
+
+ dryGain.gain.value = 1;
+ compGain.gain.value = 0;
+ outputGain.gain.value = 1;
+ limiter.threshold.value = 0;
+ limiter.knee.value = 0;
+ limiter.ratio.value = 20;
+ limiter.attack.value = 0;
+ limiter.release.value = 0.1;
+
+ const chain = { compressor, dryGain, compGain, outputGain, limiter, active: false, signature: '' };
audioChains.set(videoEl, chain);
currentAudioVideo = videoEl;
return chain;
@@ -699,46 +722,59 @@
function applyAudioBypass(videoEl) {
const chain = audioChains.get(videoEl);
if (!chain || !chain.active) return;
- const t = chain.dryGain.context.currentTime;
- rampGain(chain.dryGain, 1, t);
- rampGain(chain.compGain, 0, t);
- chain.active = false;
- reportLog('Audio compressor disabled', 'info');
+ const t = chain.dryGain.context.currentTime;
+ rampGain(chain.dryGain, 1, t);
+ rampGain(chain.compGain, 0, t);
+ rampGain(chain.outputGain, 1, t);
+ chain.limiter.threshold.setValueAtTime(0, t);
+ chain.active = false;
+ chain.signature = '';
+ reportLog('Audio processing disabled', 'info');
}
function bypassCurrentAudioProcessing() {
if (currentAudioVideo) applyAudioBypass(currentAudioVideo);
}
- function applyAudioSettings(videoEl, settings) {
- const mergedSettings = mergeAudioSettings(settings);
- if (!mergedSettings.enabled || !mergedSettings.compressor?.enabled) {
- applyAudioBypass(videoEl);
- return;
- }
+ function applyAudioSettings(videoEl, settings) {
+ const mergedSettings = mergeAudioSettings(settings);
+ const compressorEnabled = mergedSettings.compressor?.enabled === true;
+ const boostDb = normalizeBoostDb(mergedSettings.boostDb);
+ if (!mergedSettings.enabled || (!compressorEnabled && boostDb === 0)) {
+ applyAudioBypass(videoEl);
+ return;
+ }
const chain = setupAudioChain(videoEl);
if (!chain) return;
- const cSettings = mergedSettings.compressor;
- const params = cSettings.preset === 'custom'
- ? cSettings.customParams
- : AUDIO_PRESETS[cSettings.preset] || AUDIO_PRESETS.recommended;
-
- chain.compressor.threshold.value = params.threshold ?? -24;
- chain.compressor.knee.value = params.knee ?? 15;
- chain.compressor.ratio.value = params.ratio ?? 8;
- chain.compressor.attack.value = params.attack ?? 0.010;
- chain.compressor.release.value = params.release ?? 0.300;
-
- if (!chain.active) {
- const t = chain.dryGain.context.currentTime;
- rampGain(chain.dryGain, 0, t);
- rampGain(chain.compGain, 1, t);
- chain.active = true;
- reportLog('Audio compressor enabled', 'info');
- }
- }
+ if (compressorEnabled) {
+ const cSettings = mergedSettings.compressor;
+ const params = cSettings.preset === 'custom'
+ ? cSettings.customParams
+ : AUDIO_PRESETS[cSettings.preset] || AUDIO_PRESETS.recommended;
+
+ chain.compressor.threshold.value = params.threshold ?? -24;
+ chain.compressor.knee.value = params.knee ?? 15;
+ chain.compressor.ratio.value = params.ratio ?? 8;
+ chain.compressor.attack.value = params.attack ?? 0.010;
+ chain.compressor.release.value = params.release ?? 0.300;
+ }
+
+ const t = chain.dryGain.context.currentTime;
+ rampGain(chain.dryGain, compressorEnabled ? 0 : 1, t);
+ rampGain(chain.compGain, compressorEnabled ? 1 : 0, t);
+ rampGain(chain.outputGain, Math.pow(10, boostDb / 20), t);
+ chain.limiter.threshold.setValueAtTime(boostDb > 0 ? -1 : 0, t);
+
+ const signature = `${compressorEnabled ? 'compressor' : 'dry'}:${boostDb}`;
+ if (chain.signature !== signature) {
+ const boostLabel = boostDb > 0 ? ` + ${boostDb} dB boost` : '';
+ reportLog(`Audio processing enabled (${compressorEnabled ? 'compressor' : 'boost only'}${boostLabel})`, 'info');
+ }
+ chain.signature = signature;
+ chain.active = true;
+ }
// --- Episode Auto-Sync: Detection ---
function getMediaTitle() {
diff --git a/extension/locales/de.json b/extension/locales/de.json
index 94a3131..26cf419 100644
--- a/extension/locales/de.json
+++ b/extension/locales/de.json
@@ -96,6 +96,15 @@
"PLACEHOLDER_USERNAME": "Anonymer Koala",
"LABEL_HIDE_CLUTTER": "Aufgeräumte Tab-Liste",
"LABEL_HIDE_CLUTTER_TOOLTIP": "Filtert Nicht-Video-Tabs und irrelevante Domains heraus, um die Liste sauber zu halten",
+ "BLACKLIST_EDIT": "Liste bearbeiten",
+ "BLACKLIST_EDITOR_LABEL": "Ausgeblendete Domains",
+ "BLACKLIST_EDITOR_HELP": "Eine Domain pro Zeile. URLs werden auf ihren Hostnamen reduziert. Speicherung nur auf diesem Gerät.",
+ "BLACKLIST_RESET": "Standards wiederherstellen",
+ "BLACKLIST_SAVE": "Liste speichern",
+ "BLACKLIST_STATUS_INVALID": "Nicht gespeichert. Bitte diese Einträge prüfen: {domains}",
+ "BLACKLIST_STATUS_LIMIT": "Nicht gespeichert. Die Liste unterstützt höchstens {max} Domains.",
+ "BLACKLIST_STATUS_SAVED": "{count} ausgeblendete Domains auf diesem Gerät gespeichert.",
+ "BLACKLIST_STATUS_DEFAULTS": "Standard-Domainliste wiederhergestellt.",
"LABEL_AUTO_SYNC_NEXT": "Nächste Episode auto-syncen",
"LABEL_AUTO_SYNC_NEXT_TOOLTIP": "Pausiert automatisch und wartet auf alle Teilnehmer bei Episodenwechsel, startet dann synchron.",
"LABEL_AUTO_COPY_INVITE": "Einladungslink auto-kopieren",
@@ -215,6 +224,9 @@
"AUDIO_BACK": "← Zurück",
"AUDIO_PAGE_TITLE": "Audio-Einstellungen",
"AUDIO_MASTER_TOGGLE": "Audio-Verarbeitung",
+ "AUDIO_DEFAULT_BOOST": "Standard-Verstärkung",
+ "AUDIO_DEFAULT_BOOST_HELP": "Erhöht die Videolautstärke unabhängig vom Kompressor. 0 dB deaktiviert die Verstärkung.",
+ "AUDIO_PARAM_BOOST": "Verstärkung",
"AUDIO_COMPRESSOR": "Kompressor",
"AUDIO_COMPRESSOR_ENABLE": "Aktiviert",
"AUDIO_PRESET": "Preset",
diff --git a/extension/locales/en.json b/extension/locales/en.json
index dcd5e7b..38ea622 100644
--- a/extension/locales/en.json
+++ b/extension/locales/en.json
@@ -96,6 +96,15 @@
"PLACEHOLDER_USERNAME": "Anonymous Koala",
"LABEL_HIDE_CLUTTER": "Hide Clutter Tabs",
"LABEL_HIDE_CLUTTER_TOOLTIP": "Filters out non-video tabs and unrelated domains to keep the list clean",
+ "BLACKLIST_EDIT": "Edit list",
+ "BLACKLIST_EDITOR_LABEL": "Hidden domains",
+ "BLACKLIST_EDITOR_HELP": "One domain per line. URLs are reduced to their hostname. Stored only on this device.",
+ "BLACKLIST_RESET": "Restore defaults",
+ "BLACKLIST_SAVE": "Save list",
+ "BLACKLIST_STATUS_INVALID": "Not saved. Check these entries: {domains}",
+ "BLACKLIST_STATUS_LIMIT": "Not saved. The list supports at most {max} domains.",
+ "BLACKLIST_STATUS_SAVED": "Saved {count} hidden domains on this device.",
+ "BLACKLIST_STATUS_DEFAULTS": "Default domain list restored.",
"LABEL_AUTO_SYNC_NEXT": "Auto-Sync Next Episode",
"LABEL_AUTO_SYNC_NEXT_TOOLTIP": "Pauses automatically and waits for all peers when an episode changes, then sync-starts together.",
"LABEL_AUTO_COPY_INVITE": "Auto-Copy Invite Link",
@@ -215,6 +224,9 @@
"AUDIO_BACK": "← Back",
"AUDIO_PAGE_TITLE": "Audio Settings",
"AUDIO_MASTER_TOGGLE": "Audio Processing",
+ "AUDIO_DEFAULT_BOOST": "Default Boost",
+ "AUDIO_DEFAULT_BOOST_HELP": "Raises video volume independently of the compressor. Set 0 dB to disable.",
+ "AUDIO_PARAM_BOOST": "Boost",
"AUDIO_COMPRESSOR": "Compressor",
"AUDIO_COMPRESSOR_ENABLE": "Enabled",
"AUDIO_PRESET": "Preset",
diff --git a/extension/locales/es.json b/extension/locales/es.json
index c42aedb..d92ec2e 100644
--- a/extension/locales/es.json
+++ b/extension/locales/es.json
@@ -96,6 +96,15 @@
"PLACEHOLDER_USERNAME": "Koala anónimo",
"LABEL_HIDE_CLUTTER": "Ocultar pestañas sin video",
"LABEL_HIDE_CLUTTER_TOOLTIP": "Filtra pestañas que no son de video y dominios no relacionados para mantener limpia la lista",
+ "BLACKLIST_EDIT": "Editar lista",
+ "BLACKLIST_EDITOR_LABEL": "Dominios ocultos",
+ "BLACKLIST_EDITOR_HELP": "Un dominio por línea. Las URL se reducen a su nombre de host. Se guarda solo en este dispositivo.",
+ "BLACKLIST_RESET": "Restaurar valores predeterminados",
+ "BLACKLIST_SAVE": "Guardar lista",
+ "BLACKLIST_STATUS_INVALID": "No se guardó. Revisa estas entradas: {domains}",
+ "BLACKLIST_STATUS_LIMIT": "No se guardó. La lista admite como máximo {max} dominios.",
+ "BLACKLIST_STATUS_SAVED": "Se guardaron {count} dominios ocultos en este dispositivo.",
+ "BLACKLIST_STATUS_DEFAULTS": "Se restauró la lista de dominios predeterminada.",
"LABEL_AUTO_SYNC_NEXT": "Sincro auto del siguiente episodio",
"LABEL_AUTO_SYNC_NEXT_TOOLTIP": "Pausa automáticamente y espera a todos al cambiar de episodio, luego inicia de forma sincrónica.",
"LABEL_AUTO_COPY_INVITE": "Auto-copiar enlace",
@@ -215,6 +224,9 @@
"AUDIO_BACK": "← Volver",
"AUDIO_PAGE_TITLE": "Configuración de audio",
"AUDIO_MASTER_TOGGLE": "Procesamiento de audio",
+ "AUDIO_DEFAULT_BOOST": "Amplificación predeterminada",
+ "AUDIO_DEFAULT_BOOST_HELP": "Aumenta el volumen del video independientemente del compresor. Usa 0 dB para desactivarla.",
+ "AUDIO_PARAM_BOOST": "Amplificación",
"AUDIO_COMPRESSOR": "Compresor",
"AUDIO_COMPRESSOR_ENABLE": "Activado",
"AUDIO_PRESET": "Preajuste",
diff --git a/extension/locales/fr.json b/extension/locales/fr.json
index 83533a3..b6477c5 100644
--- a/extension/locales/fr.json
+++ b/extension/locales/fr.json
@@ -96,6 +96,15 @@
"PLACEHOLDER_USERNAME": "Koala anonyme",
"LABEL_HIDE_CLUTTER": "Liste d'onglets épurée",
"LABEL_HIDE_CLUTTER_TOOLTIP": "Filtre les onglets non-vidéo et les domaines non pertinents pour garder la liste propre",
+ "BLACKLIST_EDIT": "Modifier la liste",
+ "BLACKLIST_EDITOR_LABEL": "Domaines masqués",
+ "BLACKLIST_EDITOR_HELP": "Un domaine par ligne. Les URL sont réduites à leur nom d’hôte. Stockage uniquement sur cet appareil.",
+ "BLACKLIST_RESET": "Restaurer les valeurs par défaut",
+ "BLACKLIST_SAVE": "Enregistrer la liste",
+ "BLACKLIST_STATUS_INVALID": "Non enregistré. Vérifiez ces entrées : {domains}",
+ "BLACKLIST_STATUS_LIMIT": "Non enregistré. La liste accepte au maximum {max} domaines.",
+ "BLACKLIST_STATUS_SAVED": "{count} domaines masqués enregistrés sur cet appareil.",
+ "BLACKLIST_STATUS_DEFAULTS": "Liste de domaines par défaut restaurée.",
"LABEL_AUTO_SYNC_NEXT": "Synchro auto l'épisode suivant",
"LABEL_AUTO_SYNC_NEXT_TOOLTIP": "Met en pause et attend tous les membres lors d'un changement d'épisode, puis démarre de manière synchrone.",
"LABEL_AUTO_COPY_INVITE": "Copie auto du lien",
@@ -215,6 +224,9 @@
"AUDIO_BACK": "← Retour",
"AUDIO_PAGE_TITLE": "Paramètres audio",
"AUDIO_MASTER_TOGGLE": "Traitement audio",
+ "AUDIO_DEFAULT_BOOST": "Amplification par défaut",
+ "AUDIO_DEFAULT_BOOST_HELP": "Augmente le volume vidéo indépendamment du compresseur. Réglez sur 0 dB pour désactiver.",
+ "AUDIO_PARAM_BOOST": "Amplification",
"AUDIO_COMPRESSOR": "Compresseur",
"AUDIO_COMPRESSOR_ENABLE": "Activé",
"AUDIO_PRESET": "Préréglage",
diff --git a/extension/locales/it.json b/extension/locales/it.json
index 8a3c1e5..d4efd0a 100644
--- a/extension/locales/it.json
+++ b/extension/locales/it.json
@@ -96,6 +96,15 @@
"PLACEHOLDER_USERNAME": "Koala Anonimo",
"LABEL_HIDE_CLUTTER": "Nascondi schede senza video",
"LABEL_HIDE_CLUTTER_TOOLTIP": "Mantiene pulito l'elenco filtrando le schede non pertinenti",
+ "BLACKLIST_EDIT": "Modifica elenco",
+ "BLACKLIST_EDITOR_LABEL": "Domini nascosti",
+ "BLACKLIST_EDITOR_HELP": "Un dominio per riga. Gli URL vengono ridotti al nome host. Salvato solo su questo dispositivo.",
+ "BLACKLIST_RESET": "Ripristina predefiniti",
+ "BLACKLIST_SAVE": "Salva elenco",
+ "BLACKLIST_STATUS_INVALID": "Non salvato. Controlla queste voci: {domains}",
+ "BLACKLIST_STATUS_LIMIT": "Non salvato. L'elenco supporta al massimo {max} domini.",
+ "BLACKLIST_STATUS_SAVED": "Salvati {count} domini nascosti su questo dispositivo.",
+ "BLACKLIST_STATUS_DEFAULTS": "Elenco domini predefinito ripristinato.",
"LABEL_AUTO_SYNC_NEXT": "Sincro auto prossimo episodio",
"LABEL_AUTO_SYNC_NEXT_TOOLTIP": "Attende tutti i partecipanti prima di avviare il prossimo episodio.",
"LABEL_AUTO_COPY_INVITE": "Copia automatica invito",
@@ -215,6 +224,9 @@
"AUDIO_BACK": "← Indietro",
"AUDIO_PAGE_TITLE": "Impostazioni Audio",
"AUDIO_MASTER_TOGGLE": "Elaborazione Audio",
+ "AUDIO_DEFAULT_BOOST": "Amplificazione predefinita",
+ "AUDIO_DEFAULT_BOOST_HELP": "Aumenta il volume del video indipendentemente dal compressore. Imposta 0 dB per disattivare.",
+ "AUDIO_PARAM_BOOST": "Amplificazione",
"AUDIO_COMPRESSOR": "Compressore",
"AUDIO_COMPRESSOR_ENABLE": "Attivo",
"AUDIO_PRESET": "Preimpostazione",
diff --git a/extension/locales/ja.json b/extension/locales/ja.json
index 383657c..a3e41b2 100644
--- a/extension/locales/ja.json
+++ b/extension/locales/ja.json
@@ -96,6 +96,15 @@
"PLACEHOLDER_USERNAME": "匿名コアラ",
"LABEL_HIDE_CLUTTER": "不要なタブを非表示",
"LABEL_HIDE_CLUTTER_TOOLTIP": "リストをすっきりさせるため、ビデオのないタブや無関係なドメインをフィルタリングします",
+ "BLACKLIST_EDIT": "リストを編集",
+ "BLACKLIST_EDITOR_LABEL": "非表示ドメイン",
+ "BLACKLIST_EDITOR_HELP": "1行に1つのドメインを入力します。URLはホスト名に変換され、この端末にのみ保存されます。",
+ "BLACKLIST_RESET": "既定値に戻す",
+ "BLACKLIST_SAVE": "リストを保存",
+ "BLACKLIST_STATUS_INVALID": "保存されませんでした。次の項目を確認してください: {domains}",
+ "BLACKLIST_STATUS_LIMIT": "保存されませんでした。リストは最大{max}ドメインまでです。",
+ "BLACKLIST_STATUS_SAVED": "この端末に{count}件の非表示ドメインを保存しました。",
+ "BLACKLIST_STATUS_DEFAULTS": "既定のドメインリストを復元しました。",
"LABEL_AUTO_SYNC_NEXT": "次のエピソードを自動同期",
"LABEL_AUTO_SYNC_NEXT_TOOLTIP": "エピソード変更時に自動的に一時停止して全員を待ち、準備ができたら同時に再生を開始します。",
"LABEL_AUTO_COPY_INVITE": "招待リンク自動コピー",
@@ -215,6 +224,9 @@
"AUDIO_BACK": "← 戻る",
"AUDIO_PAGE_TITLE": "オーディオ設定",
"AUDIO_MASTER_TOGGLE": "オーディオ処理",
+ "AUDIO_DEFAULT_BOOST": "デフォルトブースト",
+ "AUDIO_DEFAULT_BOOST_HELP": "コンプレッサーとは独立して動画音量を上げます。無効にするには0 dBに設定します。",
+ "AUDIO_PARAM_BOOST": "ブースト",
"AUDIO_COMPRESSOR": "コンプレッサー",
"AUDIO_COMPRESSOR_ENABLE": "有効",
"AUDIO_PRESET": "プリセット",
diff --git a/extension/locales/ko.json b/extension/locales/ko.json
index ee7c353..2bc7c27 100644
--- a/extension/locales/ko.json
+++ b/extension/locales/ko.json
@@ -96,6 +96,15 @@
"PLACEHOLDER_USERNAME": "익명의 코알라",
"LABEL_HIDE_CLUTTER": "복잡한 탭 숨기기",
"LABEL_HIDE_CLUTTER_TOOLTIP": "목록을 깔끔하게 유지하기 위해 비디오가 없는 탭과 관련 없는 도메인을 필터링합니다",
+ "BLACKLIST_EDIT": "목록 편집",
+ "BLACKLIST_EDITOR_LABEL": "숨긴 도메인",
+ "BLACKLIST_EDITOR_HELP": "한 줄에 도메인 하나를 입력하세요. URL은 호스트 이름으로 변환되며 이 기기에만 저장됩니다.",
+ "BLACKLIST_RESET": "기본값 복원",
+ "BLACKLIST_SAVE": "목록 저장",
+ "BLACKLIST_STATUS_INVALID": "저장되지 않았습니다. 다음 항목을 확인하세요: {domains}",
+ "BLACKLIST_STATUS_LIMIT": "저장되지 않았습니다. 목록은 최대 {max}개 도메인을 지원합니다.",
+ "BLACKLIST_STATUS_SAVED": "이 기기에 숨긴 도메인 {count}개를 저장했습니다.",
+ "BLACKLIST_STATUS_DEFAULTS": "기본 도메인 목록을 복원했습니다.",
"LABEL_AUTO_SYNC_NEXT": "다음 에피소드 자동 동기화",
"LABEL_AUTO_SYNC_NEXT_TOOLTIP": "에피소드가 변경되면 자동으로 일시정지하고 모든 참여자를 기다린 후 함께 동기화하여 시작합니다.",
"LABEL_AUTO_COPY_INVITE": "초대 링크 자동 복사",
@@ -215,6 +224,9 @@
"AUDIO_BACK": "← 뒤로",
"AUDIO_PAGE_TITLE": "오디오 설정",
"AUDIO_MASTER_TOGGLE": "오디오 처리",
+ "AUDIO_DEFAULT_BOOST": "기본 부스트",
+ "AUDIO_DEFAULT_BOOST_HELP": "컴프레서와 별도로 동영상 볼륨을 높입니다. 끄려면 0 dB로 설정하세요.",
+ "AUDIO_PARAM_BOOST": "부스트",
"AUDIO_COMPRESSOR": "컴프레서",
"AUDIO_COMPRESSOR_ENABLE": "활성화",
"AUDIO_PRESET": "프리셋",
diff --git a/extension/locales/nl.json b/extension/locales/nl.json
index bb56eac..9f8d9ad 100644
--- a/extension/locales/nl.json
+++ b/extension/locales/nl.json
@@ -96,6 +96,15 @@
"PLACEHOLDER_USERNAME": "Anonieme Koala",
"LABEL_HIDE_CLUTTER": "Overbodige tabbladen verbergen",
"LABEL_HIDE_CLUTTER_TOOLTIP": "Filtert tabbladen zonder video's en niet-gerelateerde domeinen om de lijst schoon te houden",
+ "BLACKLIST_EDIT": "Lijst bewerken",
+ "BLACKLIST_EDITOR_LABEL": "Verborgen domeinen",
+ "BLACKLIST_EDITOR_HELP": "Eén domein per regel. URL's worden teruggebracht tot hun hostnaam. Alleen opgeslagen op dit apparaat.",
+ "BLACKLIST_RESET": "Standaardwaarden herstellen",
+ "BLACKLIST_SAVE": "Lijst opslaan",
+ "BLACKLIST_STATUS_INVALID": "Niet opgeslagen. Controleer deze items: {domains}",
+ "BLACKLIST_STATUS_LIMIT": "Niet opgeslagen. De lijst ondersteunt maximaal {max} domeinen.",
+ "BLACKLIST_STATUS_SAVED": "{count} verborgen domeinen opgeslagen op dit apparaat.",
+ "BLACKLIST_STATUS_DEFAULTS": "Standaard domeinlijst hersteld.",
"LABEL_AUTO_SYNC_NEXT": "Volgende aflevering automatisch syncen",
"LABEL_AUTO_SYNC_NEXT_TOOLTIP": "Pauzeert automatisch en wacht op alle deelnemers wanneer een aflevering verandert, en start dan gezamenlijk gesynchroniseerd.",
"LABEL_AUTO_COPY_INVITE": "Uitnodigingslink automatisch kopiëren",
@@ -215,6 +224,9 @@
"AUDIO_BACK": "← Terug",
"AUDIO_PAGE_TITLE": "Audio-instellingen",
"AUDIO_MASTER_TOGGLE": "Audioverwerking",
+ "AUDIO_DEFAULT_BOOST": "Standaardversterking",
+ "AUDIO_DEFAULT_BOOST_HELP": "Verhoogt het videovolume onafhankelijk van de compressor. Stel in op 0 dB om uit te schakelen.",
+ "AUDIO_PARAM_BOOST": "Versterking",
"AUDIO_COMPRESSOR": "Compressor",
"AUDIO_COMPRESSOR_ENABLE": "Ingeschakeld",
"AUDIO_PRESET": "Voorinstelling",
diff --git a/extension/locales/pl.json b/extension/locales/pl.json
index b1148ef..a0c8d03 100644
--- a/extension/locales/pl.json
+++ b/extension/locales/pl.json
@@ -96,6 +96,15 @@
"PLACEHOLDER_USERNAME": "Anonimowy Koala",
"LABEL_HIDE_CLUTTER": "Ukryj zbędne karty",
"LABEL_HIDE_CLUTTER_TOOLTIP": "Filtruje karty bez wideo i niepowiązane domeny, aby zachować porządek",
+ "BLACKLIST_EDIT": "Edytuj listę",
+ "BLACKLIST_EDITOR_LABEL": "Ukryte domeny",
+ "BLACKLIST_EDITOR_HELP": "Jedna domena w wierszu. Adresy URL są skracane do nazwy hosta. Zapis tylko na tym urządzeniu.",
+ "BLACKLIST_RESET": "Przywróć domyślne",
+ "BLACKLIST_SAVE": "Zapisz listę",
+ "BLACKLIST_STATUS_INVALID": "Nie zapisano. Sprawdź te wpisy: {domains}",
+ "BLACKLIST_STATUS_LIMIT": "Nie zapisano. Lista obsługuje maksymalnie {max} domen.",
+ "BLACKLIST_STATUS_SAVED": "Zapisano {count} ukrytych domen na tym urządzeniu.",
+ "BLACKLIST_STATUS_DEFAULTS": "Przywrócono domyślną listę domen.",
"LABEL_AUTO_SYNC_NEXT": "Auto-sync następnego odcinka",
"LABEL_AUTO_SYNC_NEXT_TOOLTIP": "Automatycznie wstrzymuje i czeka na wszystkich uczestników po zmianie odcinka, a następnie uruchamia się wspólnie.",
"LABEL_AUTO_COPY_INVITE": "Auto-kopiowanie zaproszenia",
@@ -215,6 +224,9 @@
"AUDIO_BACK": "← Wstecz",
"AUDIO_PAGE_TITLE": "Ustawienia dźwięku",
"AUDIO_MASTER_TOGGLE": "Przetwarzanie dźwięku",
+ "AUDIO_DEFAULT_BOOST": "Domyślne wzmocnienie",
+ "AUDIO_DEFAULT_BOOST_HELP": "Zwiększa głośność wideo niezależnie od kompresora. Ustaw 0 dB, aby wyłączyć.",
+ "AUDIO_PARAM_BOOST": "Wzmocnienie",
"AUDIO_COMPRESSOR": "Kompresor",
"AUDIO_COMPRESSOR_ENABLE": "Włączony",
"AUDIO_PRESET": "Preset",
diff --git a/extension/locales/pt-BR.json b/extension/locales/pt-BR.json
index 0220416..20c492c 100644
--- a/extension/locales/pt-BR.json
+++ b/extension/locales/pt-BR.json
@@ -96,6 +96,15 @@
"PLACEHOLDER_USERNAME": "Coala anônimo",
"LABEL_HIDE_CLUTTER": "Ocultar abas sem vídeo",
"LABEL_HIDE_CLUTTER_TOOLTIP": "Filtra abas não relacionadas para manter a lista limpa",
+ "BLACKLIST_EDIT": "Editar lista",
+ "BLACKLIST_EDITOR_LABEL": "Domínios ocultos",
+ "BLACKLIST_EDITOR_HELP": "Um domínio por linha. URLs são reduzidas ao nome do host. Salvo somente neste dispositivo.",
+ "BLACKLIST_RESET": "Restaurar padrões",
+ "BLACKLIST_SAVE": "Salvar lista",
+ "BLACKLIST_STATUS_INVALID": "Não foi salvo. Verifique estas entradas: {domains}",
+ "BLACKLIST_STATUS_LIMIT": "Não foi salvo. A lista aceita no máximo {max} domínios.",
+ "BLACKLIST_STATUS_SAVED": "{count} domínios ocultos salvos neste dispositivo.",
+ "BLACKLIST_STATUS_DEFAULTS": "Lista de domínios padrão restaurada.",
"LABEL_AUTO_SYNC_NEXT": "Sincro auto do próximo episódio",
"LABEL_AUTO_SYNC_NEXT_TOOLTIP": "Pausa automaticamente e aguarda todos ao mudar de episódio.",
"LABEL_AUTO_COPY_INVITE": "Auto-copiar link de convite",
@@ -215,6 +224,9 @@
"AUDIO_BACK": "← Voltar",
"AUDIO_PAGE_TITLE": "Configurações de áudio",
"AUDIO_MASTER_TOGGLE": "Processamento de áudio",
+ "AUDIO_DEFAULT_BOOST": "Ganho padrão",
+ "AUDIO_DEFAULT_BOOST_HELP": "Aumenta o volume do vídeo independentemente do compressor. Use 0 dB para desativar.",
+ "AUDIO_PARAM_BOOST": "Ganho",
"AUDIO_COMPRESSOR": "Compressor",
"AUDIO_COMPRESSOR_ENABLE": "Ativado",
"AUDIO_PRESET": "Predefinição",
diff --git a/extension/locales/pt.json b/extension/locales/pt.json
index 710c2c4..0791ceb 100644
--- a/extension/locales/pt.json
+++ b/extension/locales/pt.json
@@ -96,6 +96,15 @@
"PLACEHOLDER_USERNAME": "Coala Anónimo",
"LABEL_HIDE_CLUTTER": "Ocultar separadores sem vídeo",
"LABEL_HIDE_CLUTTER_TOOLTIP": "Filtra separadores não relacionados para manter a lista limpa",
+ "BLACKLIST_EDIT": "Editar lista",
+ "BLACKLIST_EDITOR_LABEL": "Domínios ocultos",
+ "BLACKLIST_EDITOR_HELP": "Um domínio por linha. Os URL são reduzidos ao nome do anfitrião. Guardado apenas neste dispositivo.",
+ "BLACKLIST_RESET": "Repor predefinições",
+ "BLACKLIST_SAVE": "Guardar lista",
+ "BLACKLIST_STATUS_INVALID": "Não foi guardado. Verifique estas entradas: {domains}",
+ "BLACKLIST_STATUS_LIMIT": "Não foi guardado. A lista suporta no máximo {max} domínios.",
+ "BLACKLIST_STATUS_SAVED": "{count} domínios ocultos guardados neste dispositivo.",
+ "BLACKLIST_STATUS_DEFAULTS": "Lista de domínios predefinida restaurada.",
"LABEL_AUTO_SYNC_NEXT": "Sincro Auto do Próximo Episódio",
"LABEL_AUTO_SYNC_NEXT_TOOLTIP": "Pausa automaticamente e aguarda por todos ao mudar de episódio.",
"LABEL_AUTO_COPY_INVITE": "Copiar Convite Automaticamente",
@@ -215,6 +224,9 @@
"AUDIO_BACK": "← Voltar",
"AUDIO_PAGE_TITLE": "Configurações de Áudio",
"AUDIO_MASTER_TOGGLE": "Processamento de Áudio",
+ "AUDIO_DEFAULT_BOOST": "Ganho predefinido",
+ "AUDIO_DEFAULT_BOOST_HELP": "Aumenta o volume do vídeo independentemente do compressor. Defina 0 dB para desativar.",
+ "AUDIO_PARAM_BOOST": "Ganho",
"AUDIO_COMPRESSOR": "Compressor",
"AUDIO_COMPRESSOR_ENABLE": "Ativado",
"AUDIO_PRESET": "Predefinição",
diff --git a/extension/locales/ru.json b/extension/locales/ru.json
index 3bb12b8..0ac0afa 100644
--- a/extension/locales/ru.json
+++ b/extension/locales/ru.json
@@ -96,6 +96,15 @@
"PLACEHOLDER_USERNAME": "Анонимный Коала",
"LABEL_HIDE_CLUTTER": "Чистый список вкладок",
"LABEL_HIDE_CLUTTER_TOOLTIP": "Скрывает вкладки без видео и несвязанные домены для порядка",
+ "BLACKLIST_EDIT": "Изменить список",
+ "BLACKLIST_EDITOR_LABEL": "Скрытые домены",
+ "BLACKLIST_EDITOR_HELP": "Один домен в строке. URL сокращаются до имени хоста. Хранится только на этом устройстве.",
+ "BLACKLIST_RESET": "Восстановить значения по умолчанию",
+ "BLACKLIST_SAVE": "Сохранить список",
+ "BLACKLIST_STATUS_INVALID": "Не сохранено. Проверьте записи: {domains}",
+ "BLACKLIST_STATUS_LIMIT": "Не сохранено. Список поддерживает не более {max} доменов.",
+ "BLACKLIST_STATUS_SAVED": "На этом устройстве сохранено скрытых доменов: {count}.",
+ "BLACKLIST_STATUS_DEFAULTS": "Список доменов по умолчанию восстановлен.",
"LABEL_AUTO_SYNC_NEXT": "Автосинхрон следующей серии",
"LABEL_AUTO_SYNC_NEXT_TOOLTIP": "Автоматически ставит на паузу и ждет всех при смене серии, затем запускает видео синхронно.",
"LABEL_AUTO_COPY_INVITE": "Автокопирование ссылки",
@@ -215,6 +224,9 @@
"AUDIO_BACK": "← Назад",
"AUDIO_PAGE_TITLE": "Настройки звука",
"AUDIO_MASTER_TOGGLE": "Обработка звука",
+ "AUDIO_DEFAULT_BOOST": "Усиление по умолчанию",
+ "AUDIO_DEFAULT_BOOST_HELP": "Увеличивает громкость видео независимо от компрессора. Установите 0 дБ для отключения.",
+ "AUDIO_PARAM_BOOST": "Усиление",
"AUDIO_COMPRESSOR": "Компрессор",
"AUDIO_COMPRESSOR_ENABLE": "Включено",
"AUDIO_PRESET": "Пресет",
diff --git a/extension/locales/tr.json b/extension/locales/tr.json
index 0f32aca..5e6dca1 100644
--- a/extension/locales/tr.json
+++ b/extension/locales/tr.json
@@ -96,6 +96,15 @@
"PLACEHOLDER_USERNAME": "Anonim Koala",
"LABEL_HIDE_CLUTTER": "Gereksiz Sekmeleri Gizle",
"LABEL_HIDE_CLUTTER_TOOLTIP": "Listeyi temiz tutmak için video olmayan sekmeleri ve alakasız alan adlarını filtreler",
+ "BLACKLIST_EDIT": "Listeyi düzenle",
+ "BLACKLIST_EDITOR_LABEL": "Gizli alan adları",
+ "BLACKLIST_EDITOR_HELP": "Her satıra bir alan adı. URL'ler ana makine adına indirgenir. Yalnızca bu cihazda saklanır.",
+ "BLACKLIST_RESET": "Varsayılanları geri yükle",
+ "BLACKLIST_SAVE": "Listeyi kaydet",
+ "BLACKLIST_STATUS_INVALID": "Kaydedilmedi. Şu girdileri kontrol edin: {domains}",
+ "BLACKLIST_STATUS_LIMIT": "Kaydedilmedi. Liste en fazla {max} alan adını destekler.",
+ "BLACKLIST_STATUS_SAVED": "Bu cihazda {count} gizli alan adı kaydedildi.",
+ "BLACKLIST_STATUS_DEFAULTS": "Varsayılan alan adı listesi geri yüklendi.",
"LABEL_AUTO_SYNC_NEXT": "Sonraki Bölümü Otomatik Eşitle",
"LABEL_AUTO_SYNC_NEXT_TOOLTIP": "Bir bölüm değiştiğinde otomatik olarak duraklatılır ve tüm bağlantıların hazır olmasını bekler, ardından birlikte senkronize olarak başlar.",
"LABEL_AUTO_COPY_INVITE": "Davet Linkini Otomatik Kopyala",
@@ -215,6 +224,9 @@
"AUDIO_BACK": "← Geri",
"AUDIO_PAGE_TITLE": "Ses ayarları",
"AUDIO_MASTER_TOGGLE": "Ses işleme",
+ "AUDIO_DEFAULT_BOOST": "Varsayılan ses artışı",
+ "AUDIO_DEFAULT_BOOST_HELP": "Video sesini kompresörden bağımsız olarak artırır. Devre dışı bırakmak için 0 dB ayarlayın.",
+ "AUDIO_PARAM_BOOST": "Ses artışı",
"AUDIO_COMPRESSOR": "Kompresör",
"AUDIO_COMPRESSOR_ENABLE": "Etkin",
"AUDIO_PRESET": "Ön ayar",
diff --git a/extension/locales/uk.json b/extension/locales/uk.json
index 2c5a918..af6b633 100644
--- a/extension/locales/uk.json
+++ b/extension/locales/uk.json
@@ -96,6 +96,15 @@
"PLACEHOLDER_USERNAME": "Анонімна коала",
"LABEL_HIDE_CLUTTER": "Приховати безладні вкладки",
"LABEL_HIDE_CLUTTER_TOOLTIP": "Відфільтровує вкладки, не пов’язані з відео, і непов’язані домени, щоб зберегти список чистим",
+ "BLACKLIST_EDIT": "Редагувати список",
+ "BLACKLIST_EDITOR_LABEL": "Приховані домени",
+ "BLACKLIST_EDITOR_HELP": "Один домен у рядку. URL скорочуються до імені хоста. Зберігається лише на цьому пристрої.",
+ "BLACKLIST_RESET": "Відновити типові значення",
+ "BLACKLIST_SAVE": "Зберегти список",
+ "BLACKLIST_STATUS_INVALID": "Не збережено. Перевірте записи: {domains}",
+ "BLACKLIST_STATUS_LIMIT": "Не збережено. Список підтримує щонайбільше {max} доменів.",
+ "BLACKLIST_STATUS_SAVED": "На цьому пристрої збережено прихованих доменів: {count}.",
+ "BLACKLIST_STATUS_DEFAULTS": "Типовий список доменів відновлено.",
"LABEL_AUTO_SYNC_NEXT": "Автоматична синхронізація наступного епізоду",
"LABEL_AUTO_SYNC_NEXT_TOOLTIP": "Автоматично призупиняється та чекає на всіх однорангових пристроїв, коли епізод зміниться, а потім синхронізація починається разом.",
"LABEL_AUTO_COPY_INVITE": "Автоматичне копіювання посилання для запрошення",
@@ -215,6 +224,9 @@
"AUDIO_BACK": "← Назад",
"AUDIO_PAGE_TITLE": "Параметри звуку",
"AUDIO_MASTER_TOGGLE": "Обробка аудіо",
+ "AUDIO_DEFAULT_BOOST": "Типове підсилення",
+ "AUDIO_DEFAULT_BOOST_HELP": "Збільшує гучність відео незалежно від компресора. Установіть 0 дБ, щоб вимкнути.",
+ "AUDIO_PARAM_BOOST": "Підсилення",
"AUDIO_COMPRESSOR": "Компресор",
"AUDIO_COMPRESSOR_ENABLE": "Увімкнено",
"AUDIO_PRESET": "Попереднє налаштування",
diff --git a/extension/locales/zh.json b/extension/locales/zh.json
index c76220f..4508a91 100644
--- a/extension/locales/zh.json
+++ b/extension/locales/zh.json
@@ -96,6 +96,15 @@
"PLACEHOLDER_USERNAME": "无名考拉",
"LABEL_HIDE_CLUTTER": "隐藏杂乱标签",
"LABEL_HIDE_CLUTTER_TOOLTIP": "过滤掉非视频选项卡和不相关的域以保持列表干净",
+ "BLACKLIST_EDIT": "编辑列表",
+ "BLACKLIST_EDITOR_LABEL": "隐藏的域名",
+ "BLACKLIST_EDITOR_HELP": "每行一个域名。URL 会转换为主机名,并且仅保存在此设备上。",
+ "BLACKLIST_RESET": "恢复默认值",
+ "BLACKLIST_SAVE": "保存列表",
+ "BLACKLIST_STATUS_INVALID": "未保存。请检查这些条目:{domains}",
+ "BLACKLIST_STATUS_LIMIT": "未保存。列表最多支持 {max} 个域名。",
+ "BLACKLIST_STATUS_SAVED": "已在此设备上保存 {count} 个隐藏域名。",
+ "BLACKLIST_STATUS_DEFAULTS": "已恢复默认域名列表。",
"LABEL_AUTO_SYNC_NEXT": "自动同步下一集",
"LABEL_AUTO_SYNC_NEXT_TOOLTIP": "当情节发生变化时,自动暂停并等待所有对等点,然后一起开始同步。",
"LABEL_AUTO_COPY_INVITE": "自动复制邀请链接",
@@ -215,6 +224,9 @@
"AUDIO_BACK": "← 返回",
"AUDIO_PAGE_TITLE": "音频设置",
"AUDIO_MASTER_TOGGLE": "音频处理",
+ "AUDIO_DEFAULT_BOOST": "默认增益",
+ "AUDIO_DEFAULT_BOOST_HELP": "独立于压缩器提高视频音量。设置为 0 dB 可关闭。",
+ "AUDIO_PARAM_BOOST": "增益",
"AUDIO_COMPRESSOR": "压缩器",
"AUDIO_COMPRESSOR_ENABLE": "启用",
"AUDIO_PRESET": "预设",
diff --git a/extension/popup.html b/extension/popup.html
index e816202..9ade1ea 100644
--- a/extension/popup.html
+++ b/extension/popup.html
@@ -1215,6 +1215,68 @@
line-height: 1.45;
text-align: left;
}
+ .settings-inline-actions {
+ width: 154px;
+ display: flex;
+ align-items: center;
+ justify-content: flex-end;
+ gap: 8px;
+ }
+ .settings-inline-actions .settings-action {
+ min-width: 0;
+ }
+ .settings-editor {
+ margin: 0 0 10px;
+ padding: 12px;
+ border: 1px solid var(--border-soft);
+ border-radius: 10px;
+ background: var(--surface-deep);
+ }
+ .settings-editor > label {
+ display: block;
+ margin: 0 0 4px;
+ color: var(--text);
+ font-size: 12px;
+ font-weight: 700;
+ }
+ .settings-editor textarea {
+ box-sizing: border-box;
+ width: 100%;
+ min-height: 150px;
+ margin: 10px 0;
+ padding: 10px;
+ resize: vertical;
+ border: 1px solid var(--border-strong);
+ border-radius: 9px;
+ background: var(--bg);
+ color: var(--text);
+ font: 11px/1.45 ui-monospace, SFMono-Regular, Consolas, monospace;
+ }
+ .settings-editor-actions {
+ display: flex;
+ gap: 8px;
+ }
+ .settings-editor-actions button {
+ flex: 1;
+ min-height: 36px;
+ margin: 0;
+ padding: 8px;
+ font-size: 11px;
+ }
+ .settings-editor-status {
+ margin: 8px 0 0;
+ font-size: 10px;
+ line-height: 1.4;
+ }
+ .settings-editor-status:empty {
+ display: none;
+ }
+ .settings-editor-status[data-state="success"] {
+ color: var(--accent);
+ }
+ .settings-editor-status[data-state="error"] {
+ color: var(--error);
+ }
[data-chat-setting] {
transition: opacity 0.2s;
}
@@ -1693,10 +1755,23 @@
-
+
+
+
+
+
+
+
+
One domain per line. URLs are reduced to their hostname. Stored only on this device.