caps_enhancer/js/options.js
2026-03-23 14:02:46 +03:00

396 lines
16 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// ==================== СКРИПТ СТРАНИЦЫ НАСТРОЕК ====================
function getStr(path) {
const o = window.CAPS_STRINGS || {};
const val = path.split('.').reduce((acc, k) => acc && acc[k], o);
return (val !== undefined && val !== null) ? val : path;
}
function applyOptionsStrings() {
document.querySelectorAll('[data-i18n]').forEach((node) => {
const key = node.getAttribute('data-i18n');
const text = getStr(key);
if (text === '') {
node.style.display = 'none';
} else if (text) {
node.textContent = text;
}
});
document.querySelectorAll('[data-i18n-placeholder]').forEach((node) => {
const key = node.getAttribute('data-i18n-placeholder');
const text = getStr(key);
if (text !== undefined && text !== null) node.placeholder = text;
});
const pageTitle = getStr('options.pageTitle');
if (pageTitle) document.title = pageTitle;
// Версия — из manifest.json (единый источник)
const versionEl = document.getElementById('app-version');
if (versionEl && typeof chrome !== 'undefined' && chrome.runtime && chrome.runtime.getManifest) {
const manifest = chrome.runtime.getManifest();
if (manifest && manifest.version) versionEl.textContent = manifest.version;
}
}
// Значения по умолчанию
const DEFAULT_CONFIG = {
debug: {
enabled: true,
modules: {
core: true,
video: true,
mnemo: true,
close: true,
content: true,
novnc: true,
autologin: true
}
},
ports: {
video: '5000',
scheme: '8080'
},
novnc: {
mode: 'button',
redirectDelay: 500
},
mnemo: {
mode: 'host-port',
skipOnDomain: false,
addVideoButton: true,
addSchemeButton: true
},
autologin: {
enabled: false,
username: '',
password: '',
autoSubmit: true,
delay: 500
},
disabledSites: [],
replaceLogo: true
};
// Элементы формы
const elements = {
// Порты
portVideo: document.getElementById('port-video'),
portScheme: document.getElementById('port-scheme'),
// noVNC (страница экрана)
novncRedirect: document.getElementById('novnc-redirect'),
redirectDelay: document.getElementById('redirect-delay'),
redirectDelayContainer: document.getElementById('redirect-delay-container'),
// Мнемосхема
mnemoMode: document.getElementById('mnemo-mode'),
mnemoSkipOnDomain: document.getElementById('mnemo-skip-on-domain'),
mnemoAddSchemeButton: document.getElementById('mnemo-add-scheme-button'),
mnemoAddVideoButton: document.getElementById('mnemo-add-video-button'),
// Замена логотипа
replaceLogo: document.getElementById('replace-logo'),
// Автологин
autologinEnabled: document.getElementById('autologin-enabled'),
autologinSettings: document.getElementById('autologin-settings'),
autologinUsername: document.getElementById('autologin-username'),
autologinPassword: document.getElementById('autologin-password'),
autologinAutoSubmit: document.getElementById('autologin-autosubmit'),
autologinDelay: document.getElementById('autologin-delay'),
// Отладка
debugEnabled: document.getElementById('debug-enabled'),
debugModules: document.getElementById('debug-modules'),
debugCore: document.getElementById('debug-core'),
debugVideo: document.getElementById('debug-video'),
debugMnemo: document.getElementById('debug-mnemo'),
debugClose: document.getElementById('debug-close'),
debugContent: document.getElementById('debug-content'),
debugNovnc: document.getElementById('debug-novnc'),
debugAutologin: document.getElementById('debug-autologin'),
// Кнопки
saveBtn: document.getElementById('save-btn'),
resetBtn: document.getElementById('reset-btn'),
// Статус
status: document.getElementById('status')
};
// Загрузка настроек при открытии страницы (сначала подставляем строки из strings.js)
document.addEventListener('DOMContentLoaded', () => {
applyOptionsStrings();
loadSettings();
});
// Обработчики событий
elements.saveBtn.addEventListener('click', saveSettings);
elements.resetBtn.addEventListener('click', resetSettings);
elements.debugEnabled.addEventListener('change', toggleDebugModules);
elements.novncRedirect.addEventListener('change', toggleRedirectDelay);
elements.autologinEnabled.addEventListener('change', toggleAutologinSettings);
// Загрузка сохранённых настроек
function loadSettings() {
console.log('Загрузка настроек...');
chrome.storage.sync.get(['config'], (result) => {
if (chrome.runtime.lastError) {
console.error('Ошибка загрузки:', chrome.runtime.lastError);
showStatus(getStr('options.statusLoadError') + ' ' + chrome.runtime.lastError.message, 'error');
return;
}
const config = result.config || DEFAULT_CONFIG;
console.log('Настройки получены из storage:', result);
console.log('Используемая конфигурация:', config);
// Порты
elements.portVideo.value = config.ports?.video || DEFAULT_CONFIG.ports.video;
elements.portScheme.value = config.ports?.scheme || DEFAULT_CONFIG.ports.scheme;
// noVNC
elements.novncRedirect.checked = (config.novnc?.mode || DEFAULT_CONFIG.novnc.mode) === 'redirect';
elements.redirectDelay.value = config.novnc?.redirectDelay || DEFAULT_CONFIG.novnc.redirectDelay;
// Мнемосхема
const mnemoMode = config.mnemo?.mode;
const mnemoSkip = config.mnemo?.skipOnDomain === true || mnemoMode === 'skip-on-domain';
elements.mnemoMode.value = (mnemoMode === 'ip-scheme' ? 'host-scheme' : (mnemoMode === 'skip-on-domain' || mnemoMode === 'default' ? 'host-port' : (mnemoMode || 'host-port')));
elements.mnemoSkipOnDomain.checked = mnemoSkip;
elements.mnemoAddSchemeButton.checked = config.mnemo?.addSchemeButton !== false;
elements.mnemoAddVideoButton.checked = config.mnemo?.addVideoButton !== false;
// Замена логотипа
elements.replaceLogo.checked = config.replaceLogo !== false;
// Автологин
elements.autologinEnabled.checked = config.autologin?.enabled || false;
elements.autologinUsername.value = config.autologin?.username || '';
elements.autologinPassword.value = config.autologin?.password || '';
elements.autologinAutoSubmit.checked = config.autologin?.autoSubmit !== false;
elements.autologinDelay.value = config.autologin?.delay || DEFAULT_CONFIG.autologin.delay;
// Отладка
elements.debugEnabled.checked = config.debug?.enabled !== false;
elements.debugCore.checked = config.debug?.modules?.core !== false;
elements.debugVideo.checked = config.debug?.modules?.video !== false;
elements.debugMnemo.checked = config.debug?.modules?.mnemo !== false;
elements.debugClose.checked = config.debug?.modules?.close !== false;
elements.debugContent.checked = config.debug?.modules?.content !== false;
elements.debugNovnc.checked = config.debug?.modules?.novnc !== false;
elements.debugAutologin.checked = config.debug?.modules?.autologin !== false;
// Обновляем UI
toggleDebugModules();
toggleRedirectDelay();
toggleAutologinSettings();
console.log('✅ Настройки загружены успешно');
});
}
// Сохранение настроек
function saveSettings() {
// Валидация портов
const portVideo = elements.portVideo.value.trim();
const portScheme = elements.portScheme.value.trim();
if (!portVideo || isNaN(portVideo) || portVideo < 1 || portVideo > 65535) {
showStatus(getStr('options.errorPortVideo'), 'error');
return;
}
if (!portScheme || isNaN(portScheme) || portScheme < 1 || portScheme > 65535) {
showStatus(getStr('options.errorPortScheme'), 'error');
return;
}
const redirectDelay = parseInt(elements.redirectDelay.value) || 500;
const autologinDelay = parseInt(elements.autologinDelay.value) || 500;
// Собираем конфигурацию
const config = {
debug: {
enabled: elements.debugEnabled.checked,
modules: {
core: elements.debugCore.checked,
video: elements.debugVideo.checked,
mnemo: elements.debugMnemo.checked,
close: elements.debugClose.checked,
content: elements.debugContent.checked,
novnc: elements.debugNovnc.checked,
autologin: elements.debugAutologin.checked
}
},
ports: {
video: portVideo,
scheme: portScheme
},
novnc: {
mode: elements.novncRedirect.checked ? 'redirect' : 'button',
redirectDelay: redirectDelay
},
mnemo: {
mode: elements.mnemoMode.value,
skipOnDomain: elements.mnemoSkipOnDomain.checked,
addVideoButton: elements.mnemoAddVideoButton.checked,
addSchemeButton: elements.mnemoAddSchemeButton.checked
},
replaceLogo: elements.replaceLogo.checked,
autologin: {
enabled: elements.autologinEnabled.checked,
username: elements.autologinUsername.value.trim(),
password: elements.autologinPassword.value,
autoSubmit: elements.autologinAutoSubmit.checked,
delay: autologinDelay
}
};
// Сохраняем список отключённых сайтов из текущего storage
chrome.storage.sync.get(['config'], (prev) => {
if (prev.config && Array.isArray(prev.config.disabledSites)) {
config.disabledSites = prev.config.disabledSites;
} else {
config.disabledSites = [];
}
// Сохраняем в chrome.storage
chrome.storage.sync.set({ config }, () => {
if (chrome.runtime.lastError) {
console.error('Ошибка сохранения:', chrome.runtime.lastError);
showStatus(getStr('options.statusSaveError') + ' ' + chrome.runtime.lastError.message, 'error');
return;
}
console.log('Настройки сохранены:', config);
showStatus(getStr('options.statusSaveOk'), 'success');
// Отправляем сообщение всем вкладкам для обновления конфига
chrome.tabs.query({}, (tabs) => {
tabs.forEach(tab => {
chrome.tabs.sendMessage(tab.id, {
type: 'CONFIG_UPDATED',
config: config
}, (response) => {
// Игнорируем ошибки для вкладок, где нет content script
if (chrome.runtime.lastError) {
// Это нормально, не все вкладки имеют content script
}
});
});
});
});
});
}
// Сброс настроек к значениям по умолчанию
function resetSettings() {
if (!confirm(getStr('options.confirmReset'))) {
return;
}
// Устанавливаем значения по умолчанию
elements.portVideo.value = DEFAULT_CONFIG.ports.video;
elements.portScheme.value = DEFAULT_CONFIG.ports.scheme;
elements.novncRedirect.checked = DEFAULT_CONFIG.novnc.mode === 'redirect';
elements.redirectDelay.value = DEFAULT_CONFIG.novnc.redirectDelay;
elements.mnemoMode.value = DEFAULT_CONFIG.mnemo.mode;
elements.mnemoSkipOnDomain.checked = DEFAULT_CONFIG.mnemo.skipOnDomain;
elements.mnemoAddSchemeButton.checked = DEFAULT_CONFIG.mnemo.addSchemeButton;
elements.mnemoAddVideoButton.checked = DEFAULT_CONFIG.mnemo.addVideoButton;
elements.replaceLogo.checked = DEFAULT_CONFIG.replaceLogo !== false;
elements.autologinEnabled.checked = DEFAULT_CONFIG.autologin.enabled;
elements.autologinUsername.value = DEFAULT_CONFIG.autologin.username;
elements.autologinPassword.value = DEFAULT_CONFIG.autologin.password;
elements.autologinAutoSubmit.checked = DEFAULT_CONFIG.autologin.autoSubmit;
elements.autologinDelay.value = DEFAULT_CONFIG.autologin.delay;
elements.debugEnabled.checked = DEFAULT_CONFIG.debug.enabled;
elements.debugCore.checked = DEFAULT_CONFIG.debug.modules.core;
elements.debugVideo.checked = DEFAULT_CONFIG.debug.modules.video;
elements.debugMnemo.checked = DEFAULT_CONFIG.debug.modules.mnemo;
elements.debugClose.checked = DEFAULT_CONFIG.debug.modules.close;
elements.debugContent.checked = DEFAULT_CONFIG.debug.modules.content;
elements.debugNovnc.checked = DEFAULT_CONFIG.debug.modules.novnc;
elements.debugAutologin.checked = DEFAULT_CONFIG.debug.modules.autologin;
// Сохраняем
chrome.storage.sync.set({ config: DEFAULT_CONFIG }, () => {
console.log('Настройки сброшены к значениям по умолчанию');
showStatus(getStr('options.statusResetDone'), 'success');
toggleDebugModules();
toggleRedirectDelay();
toggleAutologinSettings();
});
}
// Показать/скрыть модули отладки (при загрузке без .expanded блок изначально скрыт)
function toggleDebugModules() {
if (elements.debugEnabled.checked) {
elements.debugModules.classList.add('expanded');
} else {
elements.debugModules.classList.remove('expanded');
}
}
// Показать/скрыть поле задержки переадресации
function toggleRedirectDelay() {
if (elements.novncRedirect.checked) {
elements.redirectDelayContainer.style.display = 'block';
} else {
elements.redirectDelayContainer.style.display = 'none';
}
}
// Показать/скрыть настройки автологина
function toggleAutologinSettings() {
if (elements.autologinEnabled.checked) {
elements.autologinSettings.classList.remove('disabled');
} else {
elements.autologinSettings.classList.add('disabled');
}
}
// Показать статус сообщение
function showStatus(message, type = 'success') {
elements.status.textContent = message;
elements.status.className = `status ${type}`;
elements.status.classList.remove('hidden');
// Автоматически скрыть через 5 секунд
setTimeout(() => {
elements.status.classList.add('hidden');
}, 5000);
}
// Валидация при вводе (только цифры для портов)
elements.portVideo.addEventListener('input', (e) => {
e.target.value = e.target.value.replace(/[^0-9]/g, '');
});
elements.portScheme.addEventListener('input', (e) => {
e.target.value = e.target.value.replace(/[^0-9]/g, '');
});
// Тестирование chrome.storage при загрузке страницы
console.log('=== Проверка chrome.storage API ===');
console.log('chrome.storage доступен:', typeof chrome.storage !== 'undefined');
console.log('chrome.storage.sync доступен:', typeof chrome.storage?.sync !== 'undefined');
// Тестовое сохранение и чтение
if (typeof chrome.storage !== 'undefined' && chrome.storage.sync) {
chrome.storage.sync.set({ test: 'test_value' }, () => {
if (chrome.runtime.lastError) {
console.error('❌ Тест сохранения FAILED:', chrome.runtime.lastError);
} else {
console.log('✅ Тест сохранения OK');
chrome.storage.sync.get(['test'], (result) => {
if (chrome.runtime.lastError) {
console.error('❌ Тест чтения FAILED:', chrome.runtime.lastError);
} else {
console.log('✅ Тест чтения OK:', result);
}
});
}
});
} else {
console.error('❌ chrome.storage.sync недоступен!');
}