396 lines
16 KiB
JavaScript
396 lines
16 KiB
JavaScript
// ==================== СКРИПТ СТРАНИЦЫ НАСТРОЕК ====================
|
||
|
||
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 недоступен!');
|
||
}
|