557 lines
25 KiB
JavaScript
557 lines
25 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;
|
||
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,
|
||
profilePage1: 0,
|
||
profilePage2: 1,
|
||
subnetRules: [],
|
||
profiles: [
|
||
{ name: 'Профиль 1', username: '', password: '', autoSubmit: true, delay: 500 }
|
||
]
|
||
},
|
||
disabledSites: [],
|
||
replaceLogo: true,
|
||
uiVisible: true
|
||
};
|
||
|
||
// Состояние страницы
|
||
let currentProfiles = [];
|
||
let currentSubnetRules = [];
|
||
|
||
// Элементы формы
|
||
const elements = {
|
||
portVideo: document.getElementById('port-video'),
|
||
portScheme: document.getElementById('port-scheme'),
|
||
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'),
|
||
uiVisible: document.getElementById('ui-visible'),
|
||
autologinEnabled: document.getElementById('autologin-enabled'),
|
||
autologinSettings: document.getElementById('autologin-settings'),
|
||
autologinPage1Profile: document.getElementById('autologin-page1-profile'),
|
||
autologinPage2Profile: document.getElementById('autologin-page2-profile'),
|
||
autologinProfilesList: document.getElementById('autologin-profiles-list'),
|
||
autologinAddProfile: document.getElementById('autologin-add-profile'),
|
||
autologinSubnetRules: document.getElementById('autologin-subnet-rules'),
|
||
autologinAddSubnetRule: document.getElementById('autologin-add-subnet-rule'),
|
||
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')
|
||
};
|
||
|
||
// ---- Рендеринг профилей ----
|
||
|
||
function renderProfiles() {
|
||
const container = elements.autologinProfilesList;
|
||
if (!container) return;
|
||
container.innerHTML = '';
|
||
|
||
currentProfiles.forEach((profile, idx) => {
|
||
const card = document.createElement('div');
|
||
card.style.cssText = 'border:1px solid #e2e4ea;border-radius:8px;padding:10px 12px;margin-bottom:8px;background:#fff;';
|
||
|
||
const header = document.createElement('div');
|
||
header.style.cssText = 'display:flex;justify-content:space-between;align-items:center;margin-bottom:8px;';
|
||
|
||
const nameInput = document.createElement('input');
|
||
nameInput.type = 'text';
|
||
nameInput.value = profile.name || '';
|
||
nameInput.placeholder = getStr('options.autologinProfileNamePlaceholder');
|
||
nameInput.style.cssText = 'font-weight:600;border:none;border-bottom:1px solid #ccc;border-radius:0;padding:2px 4px;width:auto;font-size:13px;flex:1;';
|
||
nameInput.addEventListener('input', () => {
|
||
currentProfiles[idx].name = nameInput.value;
|
||
rebuildProfileSelects();
|
||
});
|
||
|
||
const removeBtn = document.createElement('button');
|
||
removeBtn.type = 'button';
|
||
removeBtn.textContent = getStr('options.autologinRemoveProfile');
|
||
removeBtn.title = 'Удалить профиль';
|
||
removeBtn.style.cssText = 'border:none;background:none;color:#e53935;cursor:pointer;font-size:16px;padding:0 4px;margin-left:8px;';
|
||
removeBtn.disabled = currentProfiles.length <= 1;
|
||
removeBtn.addEventListener('click', () => {
|
||
if (currentProfiles.length <= 1) return;
|
||
currentProfiles.splice(idx, 1);
|
||
// Корректируем индексы выбранных профилей
|
||
const p1 = parseInt(elements.autologinPage1Profile.value) || 0;
|
||
const p2 = parseInt(elements.autologinPage2Profile.value) || 0;
|
||
elements.autologinPage1Profile.dataset.value = Math.min(p1, currentProfiles.length - 1);
|
||
elements.autologinPage2Profile.dataset.value = Math.min(p2, currentProfiles.length - 1);
|
||
renderProfiles();
|
||
renderSubnetRules();
|
||
rebuildProfileSelects();
|
||
});
|
||
|
||
header.appendChild(nameInput);
|
||
header.appendChild(removeBtn);
|
||
|
||
const fields = document.createElement('div');
|
||
fields.style.cssText = 'display:grid;grid-template-columns:1fr 1fr;gap:8px;';
|
||
|
||
fields.appendChild(makeField(
|
||
getStr('options.autologinUsernameLabel'),
|
||
'text', profile.username, getStr('options.autologinUsernamePlaceholder'), 'off',
|
||
(v) => { currentProfiles[idx].username = v; }
|
||
));
|
||
const pwdField = makeField(
|
||
getStr('options.autologinPasswordLabel'),
|
||
'text', profile.password, '••••••••', 'off',
|
||
(v) => { currentProfiles[idx].password = v; }
|
||
);
|
||
pwdField.querySelector('input').classList.add('password-field');
|
||
fields.appendChild(pwdField);
|
||
|
||
const autoSubmitWrap = document.createElement('div');
|
||
autoSubmitWrap.style.cssText = 'display:flex;align-items:center;gap:8px;font-size:13px;';
|
||
const cbLabel = document.createElement('label');
|
||
cbLabel.style.cssText = 'display:flex;align-items:center;gap:6px;cursor:pointer;';
|
||
const cb = document.createElement('input');
|
||
cb.type = 'checkbox';
|
||
cb.checked = profile.autoSubmit !== false;
|
||
cb.addEventListener('change', () => { currentProfiles[idx].autoSubmit = cb.checked; });
|
||
cbLabel.appendChild(cb);
|
||
cbLabel.appendChild(document.createTextNode(getStr('options.autologinAutoSubmitLabel')));
|
||
autoSubmitWrap.appendChild(cbLabel);
|
||
|
||
const delayWrap = makeField(
|
||
getStr('options.autologinDelayLabel'),
|
||
'number', profile.delay || 500, '500', 'off',
|
||
(v) => { currentProfiles[idx].delay = parseInt(v) || 500; }
|
||
);
|
||
delayWrap.querySelector('input').min = '0';
|
||
delayWrap.querySelector('input').max = '5000';
|
||
delayWrap.querySelector('input').step = '100';
|
||
|
||
const hint = document.createElement('small');
|
||
hint.className = 'hint';
|
||
hint.style.gridColumn = '1/-1';
|
||
hint.textContent = getStr('options.autologinPasswordHint');
|
||
|
||
fields.appendChild(autoSubmitWrap);
|
||
fields.appendChild(delayWrap);
|
||
fields.appendChild(hint);
|
||
|
||
card.appendChild(header);
|
||
card.appendChild(fields);
|
||
container.appendChild(card);
|
||
});
|
||
}
|
||
|
||
function makeField(label, type, value, placeholder, autocomplete, onChange) {
|
||
const wrap = document.createElement('div');
|
||
const lbl = document.createElement('label');
|
||
lbl.style.cssText = 'font-size:12px;color:#555;display:block;margin-bottom:3px;';
|
||
lbl.textContent = label;
|
||
const inp = document.createElement('input');
|
||
inp.type = type;
|
||
inp.value = value !== undefined ? value : '';
|
||
inp.placeholder = placeholder || '';
|
||
if (autocomplete) inp.autocomplete = autocomplete;
|
||
inp.style.cssText = 'width:100%;padding:5px 8px;border:1px solid #ddd;border-radius:6px;font-size:13px;';
|
||
inp.addEventListener('input', () => onChange(inp.value));
|
||
wrap.appendChild(lbl);
|
||
wrap.appendChild(inp);
|
||
return wrap;
|
||
}
|
||
|
||
function rebuildProfileSelects() {
|
||
const saved1 = parseInt(elements.autologinPage1Profile.value);
|
||
const saved2 = parseInt(elements.autologinPage2Profile.value);
|
||
|
||
[elements.autologinPage1Profile, elements.autologinPage2Profile].forEach((sel, selIdx) => {
|
||
const prev = selIdx === 0 ? (isNaN(saved1) ? 0 : saved1) : (isNaN(saved2) ? 1 : saved2);
|
||
sel.innerHTML = '';
|
||
currentProfiles.forEach((p, idx) => {
|
||
const opt = document.createElement('option');
|
||
opt.value = idx;
|
||
opt.textContent = p.name || `Профиль ${idx + 1}`;
|
||
sel.appendChild(opt);
|
||
});
|
||
sel.value = Math.min(prev, currentProfiles.length - 1);
|
||
});
|
||
|
||
// Тоже обновляем selects в правилах подсетей
|
||
document.querySelectorAll('.subnet-rule-profile-select').forEach((sel) => {
|
||
const prev = parseInt(sel.value);
|
||
sel.innerHTML = '';
|
||
currentProfiles.forEach((p, idx) => {
|
||
const opt = document.createElement('option');
|
||
opt.value = idx;
|
||
opt.textContent = p.name || `Профиль ${idx + 1}`;
|
||
sel.appendChild(opt);
|
||
});
|
||
sel.value = isNaN(prev) ? 0 : Math.min(prev, currentProfiles.length - 1);
|
||
});
|
||
}
|
||
|
||
// ---- Рендеринг правил подсетей ----
|
||
|
||
function renderSubnetRules() {
|
||
const container = elements.autologinSubnetRules;
|
||
if (!container) return;
|
||
container.innerHTML = '';
|
||
|
||
if (currentSubnetRules.length === 0) {
|
||
const empty = document.createElement('p');
|
||
empty.style.cssText = 'font-size:12px;color:#aaa;margin-bottom:4px;';
|
||
empty.textContent = 'Нет правил';
|
||
container.appendChild(empty);
|
||
return;
|
||
}
|
||
|
||
currentSubnetRules.forEach((rule, idx) => {
|
||
const row = document.createElement('div');
|
||
row.style.cssText = 'display:flex;align-items:center;gap:6px;margin-bottom:6px;flex-wrap:wrap;';
|
||
|
||
const subnetInput = document.createElement('input');
|
||
subnetInput.type = 'text';
|
||
subnetInput.value = rule.subnet || '';
|
||
subnetInput.placeholder = getStr('options.autologinSubnetPlaceholder');
|
||
subnetInput.style.cssText = 'width:130px;padding:5px 8px;border:1px solid #ddd;border-radius:6px;font-size:13px;font-family:monospace;';
|
||
subnetInput.addEventListener('input', () => { currentSubnetRules[idx].subnet = subnetInput.value; });
|
||
|
||
const actionSelect = document.createElement('select');
|
||
actionSelect.style.cssText = 'padding:5px 8px;border:1px solid #ddd;border-radius:6px;font-size:13px;';
|
||
const optSkip = document.createElement('option');
|
||
optSkip.value = 'skip';
|
||
optSkip.textContent = getStr('options.autologinSubnetActionSkip');
|
||
const optProfile = document.createElement('option');
|
||
optProfile.value = 'profile';
|
||
optProfile.textContent = getStr('options.autologinSubnetActionProfile');
|
||
actionSelect.appendChild(optSkip);
|
||
actionSelect.appendChild(optProfile);
|
||
actionSelect.value = rule.action || 'skip';
|
||
|
||
const profileSelect = document.createElement('select');
|
||
profileSelect.className = 'subnet-rule-profile-select';
|
||
profileSelect.style.cssText = 'padding:5px 8px;border:1px solid #ddd;border-radius:6px;font-size:13px;';
|
||
currentProfiles.forEach((p, pi) => {
|
||
const opt = document.createElement('option');
|
||
opt.value = pi;
|
||
opt.textContent = p.name || `Профиль ${pi + 1}`;
|
||
profileSelect.appendChild(opt);
|
||
});
|
||
profileSelect.value = rule.profileIndex || 0;
|
||
profileSelect.style.display = rule.action === 'profile' ? '' : 'none';
|
||
|
||
actionSelect.addEventListener('change', () => {
|
||
currentSubnetRules[idx].action = actionSelect.value;
|
||
profileSelect.style.display = actionSelect.value === 'profile' ? '' : 'none';
|
||
});
|
||
profileSelect.addEventListener('change', () => {
|
||
currentSubnetRules[idx].profileIndex = parseInt(profileSelect.value);
|
||
});
|
||
|
||
const removeBtn = document.createElement('button');
|
||
removeBtn.type = 'button';
|
||
removeBtn.textContent = getStr('options.autologinRemoveSubnetRule');
|
||
removeBtn.title = 'Удалить правило';
|
||
removeBtn.style.cssText = 'border:none;background:none;color:#e53935;cursor:pointer;font-size:16px;padding:0 4px;';
|
||
removeBtn.addEventListener('click', () => {
|
||
currentSubnetRules.splice(idx, 1);
|
||
renderSubnetRules();
|
||
});
|
||
|
||
row.appendChild(subnetInput);
|
||
row.appendChild(actionSelect);
|
||
row.appendChild(profileSelect);
|
||
row.appendChild(removeBtn);
|
||
container.appendChild(row);
|
||
});
|
||
}
|
||
|
||
// ---- Загрузка настроек ----
|
||
|
||
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);
|
||
elements.autologinAddProfile.addEventListener('click', () => {
|
||
currentProfiles.push({ name: `Профиль ${currentProfiles.length + 1}`, username: '', password: '', autoSubmit: true, delay: 500 });
|
||
renderProfiles();
|
||
rebuildProfileSelects();
|
||
});
|
||
elements.autologinAddSubnetRule.addEventListener('click', () => {
|
||
currentSubnetRules.push({ subnet: '', action: 'skip', profileIndex: 0 });
|
||
renderSubnetRules();
|
||
});
|
||
|
||
function loadSettings() {
|
||
chrome.storage.sync.get(['config'], (result) => {
|
||
if (chrome.runtime.lastError) {
|
||
showStatus(getStr('options.statusLoadError') + ' ' + chrome.runtime.lastError.message, 'error');
|
||
return;
|
||
}
|
||
|
||
const config = result.config || DEFAULT_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;
|
||
elements.mnemoMode.value = (mnemoMode === 'ip-scheme' ? 'host-scheme' : (mnemoMode === 'skip-on-domain' || mnemoMode === 'default' ? 'host-port' : (mnemoMode || 'host-port')));
|
||
elements.mnemoSkipOnDomain.checked = config.mnemo?.skipOnDomain === true || mnemoMode === 'skip-on-domain';
|
||
elements.mnemoAddSchemeButton.checked = config.mnemo?.addSchemeButton !== false;
|
||
elements.mnemoAddVideoButton.checked = config.mnemo?.addVideoButton !== false;
|
||
|
||
// Внешний вид
|
||
elements.replaceLogo.checked = config.replaceLogo !== false;
|
||
elements.uiVisible.checked = config.uiVisible !== false;
|
||
|
||
// Автологин — загружаем профили (с миграцией старого формата)
|
||
const al = config.autologin || {};
|
||
if (Array.isArray(al.profiles) && al.profiles.length > 0) {
|
||
currentProfiles = al.profiles.map(p => ({ ...p }));
|
||
} else if (al.username || al.password) {
|
||
// Миграция старого формата
|
||
currentProfiles = [
|
||
{ name: 'Профиль 1', username: al.username || '', password: al.password || '', autoSubmit: al.autoSubmit !== false, delay: al.delay || 500 }
|
||
];
|
||
if (al.username2 || al.password2) {
|
||
currentProfiles.push({ name: 'Профиль 2', username: al.username2 || '', password: al.password2 || '', autoSubmit: true, delay: 500 });
|
||
}
|
||
} else {
|
||
currentProfiles = [{ name: 'Профиль 1', username: '', password: '', autoSubmit: true, delay: 500 }];
|
||
}
|
||
|
||
currentSubnetRules = Array.isArray(al.subnetRules) ? al.subnetRules.map(r => ({ ...r })) : [];
|
||
|
||
elements.autologinEnabled.checked = al.enabled || false;
|
||
|
||
renderProfiles();
|
||
renderSubnetRules();
|
||
rebuildProfileSelects();
|
||
|
||
// Выставляем выбранные профили
|
||
const p1 = typeof al.profilePage1 === 'number' ? al.profilePage1 : 0;
|
||
const p2 = typeof al.profilePage2 === 'number' ? al.profilePage2 : Math.min(1, currentProfiles.length - 1);
|
||
elements.autologinPage1Profile.value = Math.min(p1, currentProfiles.length - 1);
|
||
elements.autologinPage2Profile.value = Math.min(p2, currentProfiles.length - 1);
|
||
|
||
// Отладка
|
||
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;
|
||
|
||
toggleDebugModules();
|
||
toggleRedirectDelay();
|
||
toggleAutologinSettings();
|
||
});
|
||
}
|
||
|
||
// ---- Сохранение настроек ----
|
||
|
||
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 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: parseInt(elements.redirectDelay.value) || 500
|
||
},
|
||
mnemo: {
|
||
mode: elements.mnemoMode.value,
|
||
skipOnDomain: elements.mnemoSkipOnDomain.checked,
|
||
addVideoButton: elements.mnemoAddVideoButton.checked,
|
||
addSchemeButton: elements.mnemoAddSchemeButton.checked
|
||
},
|
||
replaceLogo: elements.replaceLogo.checked,
|
||
uiVisible: elements.uiVisible.checked,
|
||
autologin: {
|
||
enabled: elements.autologinEnabled.checked,
|
||
profilePage1: parseInt(elements.autologinPage1Profile.value) || 0,
|
||
profilePage2: parseInt(elements.autologinPage2Profile.value) || 0,
|
||
profiles: currentProfiles.map(p => ({ ...p })),
|
||
subnetRules: currentSubnetRules.map(r => ({ ...r }))
|
||
}
|
||
};
|
||
|
||
chrome.storage.sync.get(['config'], (prev) => {
|
||
if (prev.config && Array.isArray(prev.config.disabledSites)) {
|
||
config.disabledSites = prev.config.disabledSites;
|
||
} else {
|
||
config.disabledSites = [];
|
||
}
|
||
|
||
chrome.storage.sync.set({ config }, () => {
|
||
if (chrome.runtime.lastError) {
|
||
showStatus(getStr('options.statusSaveError') + ' ' + chrome.runtime.lastError.message, 'error');
|
||
return;
|
||
}
|
||
showStatus(getStr('options.statusSaveOk'), 'success');
|
||
chrome.tabs.query({}, (tabs) => {
|
||
tabs.forEach(tab => {
|
||
chrome.tabs.sendMessage(tab.id, { type: 'CONFIG_UPDATED', config }).catch(() => {});
|
||
});
|
||
});
|
||
});
|
||
});
|
||
}
|
||
|
||
// ---- Сброс настроек ----
|
||
|
||
function resetSettings() {
|
||
if (!confirm(getStr('options.confirmReset'))) return;
|
||
|
||
currentProfiles = DEFAULT_CONFIG.autologin.profiles.map(p => ({ ...p }));
|
||
currentSubnetRules = [];
|
||
|
||
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.uiVisible.checked = DEFAULT_CONFIG.uiVisible !== false;
|
||
elements.autologinEnabled.checked = DEFAULT_CONFIG.autologin.enabled;
|
||
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;
|
||
|
||
renderProfiles();
|
||
renderSubnetRules();
|
||
rebuildProfileSelects();
|
||
|
||
chrome.storage.sync.set({ config: DEFAULT_CONFIG }, () => {
|
||
showStatus(getStr('options.statusResetDone'), 'success');
|
||
toggleDebugModules();
|
||
toggleRedirectDelay();
|
||
toggleAutologinSettings();
|
||
});
|
||
}
|
||
|
||
// ---- Вспомогательные функции ----
|
||
|
||
function toggleDebugModules() {
|
||
if (elements.debugEnabled.checked) {
|
||
elements.debugModules.classList.add('expanded');
|
||
} else {
|
||
elements.debugModules.classList.remove('expanded');
|
||
}
|
||
}
|
||
|
||
function toggleRedirectDelay() {
|
||
elements.redirectDelayContainer.style.display = elements.novncRedirect.checked ? 'block' : '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');
|
||
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, ''); });
|