Fix typos and improve comments in ZapretManager_LuCI.sh
This commit is contained in:
1 parent
d8468bd153
commit
74b0045a3f
1 file changed
+2
-68
+2
-68
@@ -1,5 +1,5 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
# Zapret Manager by Stressozz LuCI installer — самодостаточный скрипт (все файлы зашиты внутри).
|
# Zapret Manager by StressOzz LuCI installer — самодостаточный скрипт (все файлы зашиты внутри).
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
GREEN="\033[1;32m"; CYAN="\033[1;36m"; YELLOW="\033[1;33m"; MAGENTA="\033[1;35m"; BLUE="\033[0;34m"; NC="\033[0m"; DGRAY="\033[38;5;244m"
|
GREEN="\033[1;32m"; CYAN="\033[1;36m"; YELLOW="\033[1;33m"; MAGENTA="\033[1;35m"; BLUE="\033[0;34m"; NC="\033[0m"; DGRAY="\033[38;5;244m"
|
||||||
@@ -1480,12 +1480,6 @@ tg_status() {
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
[ -f "$TG_SECRET_MT_FILE" ] && secret_mt=$(grep '^SECRET=' "$TG_SECRET_MT_FILE" | cut -d= -f2)
|
[ -f "$TG_SECRET_MT_FILE" ] && secret_mt=$(grep '^SECRET=' "$TG_SECRET_MT_FILE" | cut -d= -f2)
|
||||||
# Ключ Rust-прокси. Оригинальный консольный скрипт никогда не писал его в
|
|
||||||
# отдельный файл — он всегда встроен прямо в команду запуска init.d-скрипта
|
|
||||||
# (--secret <hex>). Если установка была сделана через SSH оригинальным
|
|
||||||
# скриптом (а не через эту панель), нашего файла $TG_SECRET_RS_FILE попросту
|
|
||||||
# не существует — поэтому читаем ключ из самого init.d-скрипта, это работает
|
|
||||||
# независимо от того, чем ставили: нашей панелью или оригинальным SSH-скриптом.
|
|
||||||
if [ -f "$TG_INIT_RS" ]; then
|
if [ -f "$TG_INIT_RS" ]; then
|
||||||
secret_rs=$(sed -n 's/.*--secret[[:space:]]*\([0-9a-fA-F]\{32\}\).*/\1/p' "$TG_INIT_RS" | head -n1)
|
secret_rs=$(sed -n 's/.*--secret[[:space:]]*\([0-9a-fA-F]\{32\}\).*/\1/p' "$TG_INIT_RS" | head -n1)
|
||||||
fi
|
fi
|
||||||
@@ -2034,21 +2028,13 @@ var callDohInstall = rpc.declare({ object: 'zapret-manager', method: 'doh_instal
|
|||||||
var callDohRemove = rpc.declare({ object: 'zapret-manager', method: 'doh_remove', expect: {} });
|
var callDohRemove = rpc.declare({ object: 'zapret-manager', method: 'doh_remove', expect: {} });
|
||||||
var callDohSet = rpc.declare({ object: 'zapret-manager', method: 'doh_set', params: ['provider'], expect: {} });
|
var callDohSet = rpc.declare({ object: 'zapret-manager', method: 'doh_set', params: ['provider'], expect: {} });
|
||||||
|
|
||||||
// Некоторые прошивки (например FriendlyWrt) переписывают тему LuCI целиком
|
|
||||||
// и не объявляют переменную --background-color-medium вообще — тогда наш
|
|
||||||
// var(--background-color-medium, #fff) молча берёт запасное значение #fff,
|
|
||||||
// и карточки становятся белыми посреди тёмной страницы. Если же переменная
|
|
||||||
// объявлена (как на ванильной OpenWrt) — она уже работает правильно сама,
|
|
||||||
// трогать вообще ничего не нужно.
|
|
||||||
function detectMissingThemeVar() {
|
function detectMissingThemeVar() {
|
||||||
if (document.documentElement.hasAttribute('data-zm-theme-checked')) return;
|
if (document.documentElement.hasAttribute('data-zm-theme-checked')) return;
|
||||||
document.documentElement.setAttribute('data-zm-theme-checked', '1');
|
document.documentElement.setAttribute('data-zm-theme-checked', '1');
|
||||||
try {
|
try {
|
||||||
var declared = getComputedStyle(document.documentElement).getPropertyValue('--background-color-medium').trim();
|
var declared = getComputedStyle(document.documentElement).getPropertyValue('--background-color-medium').trim();
|
||||||
if (declared) return; // тема сама её объявляет — ничего не делаем, это уже рабочий случай
|
if (declared) return;
|
||||||
|
|
||||||
// переменная не объявлена этой темой — определяем реальный цвет фона
|
|
||||||
// страницы и, если он тёмный, включаем свой запасной тёмный вид
|
|
||||||
var el = document.body, bg = '', hops = 0;
|
var el = document.body, bg = '', hops = 0;
|
||||||
while (el && hops < 6) {
|
while (el && hops < 6) {
|
||||||
var c = getComputedStyle(el).backgroundColor;
|
var c = getComputedStyle(el).backgroundColor;
|
||||||
@@ -2081,9 +2067,6 @@ function badge(ok, textOk, textBad) {
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Раскрашивает построчный вывод (==> сообщения) для читаемости: стрелки —
|
|
||||||
// голубым, обычные шаги — жёлтым, успешные/готово — зелёным, ошибки — красным,
|
|
||||||
// !! предупреждения — оранжевым; необработанный вывод команд — приглушённым серым.
|
|
||||||
function renderLog(logEl, text) {
|
function renderLog(logEl, text) {
|
||||||
logEl.innerHTML = '';
|
logEl.innerHTML = '';
|
||||||
var lines = (text || '').split('\n');
|
var lines = (text || '').split('\n');
|
||||||
@@ -2129,11 +2112,6 @@ function pollJob(job, logEl, onDone, onTick) {
|
|||||||
onDone(st.rc === '0');
|
onDone(st.rc === '0');
|
||||||
}
|
}
|
||||||
}).catch(function() {
|
}).catch(function() {
|
||||||
// Одиночная неудача опроса (роутер занят распаковкой/установкой —
|
|
||||||
// временная заминка) не должна навсегда останавливать поллинг:
|
|
||||||
// сама операция на роутере продолжает идти в фоне независимо от
|
|
||||||
// того, отвечает ли сейчас веб-интерфейс. Останавливаемся только
|
|
||||||
// после нескольких подряд неудач и явно предупреждаем.
|
|
||||||
failCount++;
|
failCount++;
|
||||||
if (failCount >= 8) {
|
if (failCount >= 8) {
|
||||||
clearInterval(timer);
|
clearInterval(timer);
|
||||||
@@ -2149,11 +2127,6 @@ function refreshBanner(message) {
|
|||||||
E('button', {
|
E('button', {
|
||||||
'class': 'cbi-button cbi-button-positive',
|
'class': 'cbi-button cbi-button-positive',
|
||||||
'click': function() {
|
'click': function() {
|
||||||
// Разрываем сессию в фоне, затем перезагружаем ИМЕННО текущую
|
|
||||||
// страницу (а не отдельный URL logout) — LuCI при недействительной
|
|
||||||
// сессии сама показывает форму входа прямо на этом адресе и после
|
|
||||||
// успешного входа возвращает сюда же (штатное поведение при
|
|
||||||
// истечении сессии, тут просто используем его напрямую).
|
|
||||||
fetch(L.url('admin/logout'), { credentials: 'same-origin' }).catch(function() {}).then(function() {
|
fetch(L.url('admin/logout'), { credentials: 'same-origin' }).catch(function() {}).then(function() {
|
||||||
location.reload();
|
location.reload();
|
||||||
});
|
});
|
||||||
@@ -2162,7 +2135,6 @@ function refreshBanner(message) {
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---------- собственные всплывающие уведомления (не системные LuCI) ----------
|
|
||||||
|
|
||||||
function toastContainer() {
|
function toastContainer() {
|
||||||
var c = document.getElementById('zm-toast-container');
|
var c = document.getElementById('zm-toast-container');
|
||||||
@@ -3266,10 +3238,6 @@ cat > '/www/luci-static/resources/view/zapret-manager/style.css' << 'ZM_INSTALLE
|
|||||||
transition: box-shadow .15s;
|
transition: box-shadow .15s;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Запасной тёмный вид — включается через JS ТОЛЬКО если тема прошивки не
|
|
||||||
объявляет переменную --background-color-medium сама (тогда выше сработал
|
|
||||||
бы статичный светлый запасной #fff даже на тёмной странице). Если тема
|
|
||||||
объявляет переменную — этот блок вообще не применяется, ничего не меняется. */
|
|
||||||
html.zm-theme-dark .zm-card {
|
html.zm-theme-dark .zm-card {
|
||||||
background: #1c2128;
|
background: #1c2128;
|
||||||
border-color: rgba(255,255,255,.10);
|
border-color: rgba(255,255,255,.10);
|
||||||
@@ -3279,8 +3247,6 @@ html.zm-theme-dark .zm-card {
|
|||||||
|
|
||||||
.zm-card h3 { margin: 0 0 12px 0; font-size: 15px; font-weight: 600; display: flex; align-items: center; gap: 8px; }
|
.zm-card h3 { margin: 0 0 12px 0; font-size: 15px; font-weight: 600; display: flex; align-items: center; gap: 8px; }
|
||||||
|
|
||||||
/* Строка "подпись: значение" — подпись и значение стоят РЯДОМ (умеренный
|
|
||||||
отступ), а не растянуты в разные концы широкой карточки. */
|
|
||||||
.zm-row { display: flex; align-items: center; gap: 12px; margin: 7px 0; font-size: 13px; flex-wrap: wrap; }
|
.zm-row { display: flex; align-items: center; gap: 12px; margin: 7px 0; font-size: 13px; flex-wrap: wrap; }
|
||||||
.zm-row .zm-label { opacity: .65; flex-shrink: 0; }
|
.zm-row .zm-label { opacity: .65; flex-shrink: 0; }
|
||||||
.zm-row > span:last-child { overflow-wrap: anywhere; }
|
.zm-row > span:last-child { overflow-wrap: anywhere; }
|
||||||
@@ -3300,8 +3266,6 @@ html.zm-theme-dark .zm-card {
|
|||||||
.zm-actions { display: flex; gap: 12px; flex-wrap: wrap; align-items: center; margin: 14px 0; }
|
.zm-actions { display: flex; gap: 12px; flex-wrap: wrap; align-items: center; margin: 14px 0; }
|
||||||
.zm-actions .cbi-button { margin: 0; }
|
.zm-actions .cbi-button { margin: 0; }
|
||||||
|
|
||||||
/* Плитки: flex вместо grid — компактные "чипы" по контенту, а не растянутые
|
|
||||||
на всю колонку, аккуратно переносятся на новую строку. */
|
|
||||||
.zm-grid { display: flex; flex-wrap: wrap; gap: 9px; }
|
.zm-grid { display: flex; flex-wrap: wrap; gap: 9px; }
|
||||||
|
|
||||||
.zm-tile {
|
.zm-tile {
|
||||||
@@ -3319,10 +3283,6 @@ html.zm-theme-dark .zm-card {
|
|||||||
transition: border-color .15s, background .15s, transform .1s;
|
transition: border-color .15s, background .15s, transform .1s;
|
||||||
background: var(--background-color-low, #fafafa);
|
background: var(--background-color-low, #fafafa);
|
||||||
}
|
}
|
||||||
/* Только для нейтрального состояния плитки — активные (.zm-active) и
|
|
||||||
выключенные (.zm-tile-off) уже раскрашены полупрозрачным зелёным/красным
|
|
||||||
поверх фона и одинаково хорошо читаются что на светлом, что на тёмном
|
|
||||||
фоне, поэтому их сюда специально не включаем. */
|
|
||||||
html.zm-theme-dark .zm-tile:not(.zm-active):not(.zm-tile-off) {
|
html.zm-theme-dark .zm-tile:not(.zm-active):not(.zm-tile-off) {
|
||||||
background: #22272e;
|
background: #22272e;
|
||||||
border-color: rgba(255,255,255,.12);
|
border-color: rgba(255,255,255,.12);
|
||||||
@@ -3335,8 +3295,6 @@ html.zm-theme-dark .zm-tile:not(.zm-active):not(.zm-tile-off) {
|
|||||||
}
|
}
|
||||||
.zm-tile.zm-active::before { content: "✓ "; }
|
.zm-tile.zm-active::before { content: "✓ "; }
|
||||||
|
|
||||||
/* Отдельное состояние для "выключено/не исключено" (например, Исключения IP) —
|
|
||||||
красным с крестиком, отличное от обычного нейтрального "не активно". */
|
|
||||||
.zm-tile.zm-tile-off {
|
.zm-tile.zm-tile-off {
|
||||||
border-color: rgba(207,34,46,.35); background: rgba(207,34,46,.08);
|
border-color: rgba(207,34,46,.35); background: rgba(207,34,46,.08);
|
||||||
color: #cf222e; font-weight: 600;
|
color: #cf222e; font-weight: 600;
|
||||||
@@ -3346,10 +3304,6 @@ html.zm-theme-dark .zm-tile:not(.zm-active):not(.zm-tile-off) {
|
|||||||
.zm-tile.zm-tile-pending { opacity: .55; border-style: dashed; cursor: not-allowed; }
|
.zm-tile.zm-tile-pending { opacity: .55; border-style: dashed; cursor: not-allowed; }
|
||||||
.zm-tile.zm-tile-pending:hover { border-color: rgba(0,0,0,.1); transform: none; }
|
.zm-tile.zm-tile-pending:hover { border-color: rgba(0,0,0,.1); transform: none; }
|
||||||
|
|
||||||
/* Живой вывод действий (установка/тест/и т.д.) — большая, ясно видимая
|
|
||||||
консоль вместо мелкой полоски: крупнее шрифт, больше высоты, чёткая рамка.
|
|
||||||
white-space: pre-wrap — длинные строки (URL и т.п.) переносятся ВНИЗ,
|
|
||||||
а не вылезают вправо за пределы карточки. */
|
|
||||||
.zm-log {
|
.zm-log {
|
||||||
background: #0d1117; color: #e6edf3;
|
background: #0d1117; color: #e6edf3;
|
||||||
font-family: ui-monospace, "SF Mono", "Cascadia Code", Consolas, "Liberation Mono", monospace;
|
font-family: ui-monospace, "SF Mono", "Cascadia Code", Consolas, "Liberation Mono", monospace;
|
||||||
@@ -3365,7 +3319,6 @@ html.zm-theme-dark .zm-tile:not(.zm-active):not(.zm-tile-off) {
|
|||||||
.zm-log.zm-show { display: block; }
|
.zm-log.zm-show { display: block; }
|
||||||
.zm-log:empty::before { content: "Ожидание вывода..."; opacity: .4; }
|
.zm-log:empty::before { content: "Ожидание вывода..."; opacity: .4; }
|
||||||
|
|
||||||
/* Раскраска построчного вывода (==> сообщения) для читаемости. */
|
|
||||||
.zm-log-arrow { color: #56d4dd; font-weight: 700; }
|
.zm-log-arrow { color: #56d4dd; font-weight: 700; }
|
||||||
.zm-log-msg-info { color: #e3c04a; }
|
.zm-log-msg-info { color: #e3c04a; }
|
||||||
.zm-log-msg-ok { color: #3fb950; font-weight: 600; }
|
.zm-log-msg-ok { color: #3fb950; font-weight: 600; }
|
||||||
@@ -3375,8 +3328,6 @@ html.zm-theme-dark .zm-tile:not(.zm-active):not(.zm-tile-off) {
|
|||||||
|
|
||||||
.zm-hint { font-size: 12px; opacity: .65; margin-top: 6px; line-height: 1.5; overflow-wrap: break-word; }
|
.zm-hint { font-size: 12px; opacity: .65; margin-top: 6px; line-height: 1.5; overflow-wrap: break-word; }
|
||||||
|
|
||||||
/* Уведомление о необходимости обновить страницу LuCI после установки/удаления
|
|
||||||
пакетов, добавляющих собственные меню (luci-app-*). */
|
|
||||||
.zm-refresh-banner {
|
.zm-refresh-banner {
|
||||||
display: flex; align-items: center; justify-content: space-between; gap: 14px;
|
display: flex; align-items: center; justify-content: space-between; gap: 14px;
|
||||||
background: rgba(191,135,0,.12); border: 2px solid rgba(191,135,0,.35);
|
background: rgba(191,135,0,.12); border: 2px solid rgba(191,135,0,.35);
|
||||||
@@ -3385,8 +3336,6 @@ html.zm-theme-dark .zm-tile:not(.zm-active):not(.zm-tile-off) {
|
|||||||
}
|
}
|
||||||
.zm-refresh-banner button { flex-shrink: 0; }
|
.zm-refresh-banner button { flex-shrink: 0; }
|
||||||
|
|
||||||
/* Собственные всплывающие уведомления — вместо системных баннеров LuCI.
|
|
||||||
Сделаны крупными и заметными по запросу (увеличены повторно). */
|
|
||||||
#zm-toast-container {
|
#zm-toast-container {
|
||||||
position: fixed; top: 20px; right: 20px; z-index: 10000;
|
position: fixed; top: 20px; right: 20px; z-index: 10000;
|
||||||
display: flex; flex-direction: column; gap: 14px;
|
display: flex; flex-direction: column; gap: 14px;
|
||||||
@@ -3411,8 +3360,6 @@ html.zm-theme-dark .zm-tile:not(.zm-active):not(.zm-tile-off) {
|
|||||||
.zm-toast-warning .zm-toast-icon { color: #e3b341; }
|
.zm-toast-warning .zm-toast-icon { color: #e3b341; }
|
||||||
.zm-toast-text { overflow-wrap: anywhere; }
|
.zm-toast-text { overflow-wrap: anywhere; }
|
||||||
|
|
||||||
/* Крупная плитка со ссылкой для вставки в Telegram (tg://proxy / tg://socks) —
|
|
||||||
отдельно от узких карточек статуса, чтобы длинная ссылка помещалась целиком. */
|
|
||||||
.zm-tg-link-card {
|
.zm-tg-link-card {
|
||||||
background: rgba(26,127,55,.06);
|
background: rgba(26,127,55,.06);
|
||||||
border: 1px solid rgba(26,127,55,.25);
|
border: 1px solid rgba(26,127,55,.25);
|
||||||
@@ -3433,8 +3380,6 @@ html.zm-theme-dark .zm-tile:not(.zm-active):not(.zm-tile-off) {
|
|||||||
.zm-tg-link-row { display: flex; align-items: flex-start; gap: 10px; }
|
.zm-tg-link-row { display: flex; align-items: flex-start; gap: 10px; }
|
||||||
.zm-tg-link-row .zm-tg-link-box { flex: 1 1 auto; }
|
.zm-tg-link-row .zm-tg-link-box { flex: 1 1 auto; }
|
||||||
|
|
||||||
/* Заметный индикатор "что сейчас используется/применено" на страницах
|
|
||||||
стратегий/DoH/hosts/fake. */
|
|
||||||
.zm-current-banner {
|
.zm-current-banner {
|
||||||
display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
|
display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
|
||||||
background: rgba(26,127,55,.07); border: 1px solid rgba(26,127,55,.22);
|
background: rgba(26,127,55,.07); border: 1px solid rgba(26,127,55,.22);
|
||||||
@@ -3445,12 +3390,6 @@ html.zm-theme-dark .zm-tile:not(.zm-active):not(.zm-tile-off) {
|
|||||||
background: rgba(110,118,129,.08); border-color: rgba(110,118,129,.2);
|
background: rgba(110,118,129,.08); border-color: rgba(110,118,129,.2);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Наши страницы не используют UCI-формы LuCI (никакие uci.set/save не
|
|
||||||
вызываются) — стандартная панель "Save & Apply / Save / Reset" здесь
|
|
||||||
ничего не делает и только сбивает с толку. Скрываем её, пока наш CSS
|
|
||||||
загружен (то есть только на страницах Zapret Manager — при переходе на
|
|
||||||
любую другую страницу LuCI загружается заново без нашего style.css, и
|
|
||||||
панель снова появится там, где она реально нужна). */
|
|
||||||
.cbi-page-actions { display: none !important; }
|
.cbi-page-actions { display: none !important; }
|
||||||
ZM_INSTALLER_EOF
|
ZM_INSTALLER_EOF
|
||||||
|
|
||||||
@@ -3691,9 +3630,6 @@ function copyToClipboard(text) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function fallbackCopy(text) {
|
function fallbackCopy(text) {
|
||||||
// LuCI обычно открыт по обычному http:// (не https), а Clipboard API работает
|
|
||||||
// только в защищённом контексте — используем старый, но надёжный способ через
|
|
||||||
// скрытое текстовое поле + document.execCommand('copy'), он работает и по http.
|
|
||||||
var ta = document.createElement('textarea');
|
var ta = document.createElement('textarea');
|
||||||
ta.value = text;
|
ta.value = text;
|
||||||
ta.setAttribute('readonly', '');
|
ta.setAttribute('readonly', '');
|
||||||
@@ -3778,8 +3714,6 @@ return view.extend({
|
|||||||
'class': 'cbi-button cbi-button-remove',
|
'class': 'cbi-button cbi-button-remove',
|
||||||
'click': function() { doAction(v.id, 'remove'); }
|
'click': function() { doAction(v.id, 'remove'); }
|
||||||
}, 'Удалить'));
|
}, 'Удалить'));
|
||||||
// "Обновить" показываем только если реально есть более новая версия —
|
|
||||||
// иначе кнопка вводит в заблуждение, будто обновляться есть на что.
|
|
||||||
if (st.version && st.latest && st.version !== st.latest) {
|
if (st.version && st.latest && st.version !== st.latest) {
|
||||||
actions.push(E('button', {
|
actions.push(E('button', {
|
||||||
'class': 'cbi-button',
|
'class': 'cbi-button',
|
||||||
|
|||||||
Reference in new issue
Block a user