diff --git a/README.md b/README.md index 0b34d45..8a9b391 100644 --- a/README.md +++ b/README.md @@ -64,6 +64,11 @@ cd /opt/amnezia-admin && chmod +x scripts/install.sh && sudo SKIP_DOWNLOAD=1 bas | `AWG_PROFILES` | _(нет)_ | Несколько инстансов; см. примеры в репозитории PRO | | `COMMUNITY_UPGRADE_URL` | Страница подписки PRO на Boosty (зашита в код по умолчанию) | Переопределите, если смените уровень подписки | | `COMMUNITY_UPGRADE_PITCH` | _(текст по умолчанию в коде)_ | Текст под заголовком базовой версии | +| `PANEL_FOOTER_DONATE_URL` | Как **`COMMUNITY_UPGRADE_URL`** | Ссылка «донат» в **шапке и подвале** веб‑панели (**не** добавляется на nginx‑лендинг пользователей). | +| `PANEL_FOOTER_TELEGRAM_URL` | `https://t.me/lot_andrey` | Ссылка Telegram‑спонсора / канала (там же: только панель). | +| `PANEL_FOOTER_DONATE_LABEL` | `Поддержать проект` | Текст якоря доната | +| `PANEL_FOOTER_TELEGRAM_LABEL` | `Telegram‑канал спонсора` | Текст якоря Telegram | +| `PANEL_FOOTER_PROMO_SUBTITLE` | _(строка по умолчанию в коде)_ | Поясняющий текст в верхней полосе панели | | `SKIP_LANDING` | `0` | `1` — без лендинга на порту 80 | | `ALLOW_COMMUNITY_GITHUB_ACTIVATION` | `0` | `1` — в редакции community показывать ввод GitHub-токена и запускать приватный `install.sh` (доступ к репо с Contents Read / repo; **высокая чувствительность**, см. раздел безопасности) | | `COMMUNITY_PRIVATE_INSTALL_SCRIPT_URL` | `https://raw.githubusercontent.com/andrey271192/amnezia_web-pro/main/scripts/install.sh` | Сырой URL `scripts/install.sh` в **вашем** приватном репозитории PRO | diff --git a/package.json b/package.json index 97df75b..3e1859a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "amnezia-admin", - "version": "1.2.19", + "version": "1.2.20", "private": true, "description": "amnezia_web — базовая панель AmneziaWG (FREE: просмотр и удаление клиентов; полная версия — PRO).", "license": "MIT", diff --git a/public/app.js b/public/app.js index 71985ff..b4378dc 100644 --- a/public/app.js +++ b/public/app.js @@ -147,6 +147,62 @@ function fmtBytesRu(n) { return `${Math.round(x / (1024 * 102.4)) / 10} MiB`; } +/** Ссылки доната и Telegram‑спонсора: шапка + подвал панели (`GET /api/panel/footer`). */ +function wirePanelPromoAnchor(el, url, label) { + const u = typeof url === "string" ? url.trim() : ""; + const lb = typeof label === "string" ? label.trim() : ""; + if (!el || !u || !lb) { + if (el) { + el.classList.add("hidden"); + el.removeAttribute("href"); + el.textContent = ""; + } + return false; + } + el.href = u; + el.textContent = lb; + el.classList.remove("hidden"); + return true; +} + +async function hydratePanelPromoFooter() { + const strip = document.getElementById("panel-promo-strip"); + const sub = document.getElementById("panel-promo-subtitle"); + const aDonTop = document.getElementById("panel-strip-donate"); + const sepTop = document.getElementById("panel-strip-sep"); + const aTgTop = document.getElementById("panel-strip-telegram"); + const gap1 = document.getElementById("footer-promo-gap1"); + const aDonF = document.getElementById("footer-promo-donate"); + const sepMid = document.getElementById("footer-promo-sep-mid"); + const aTgF = document.getElementById("footer-promo-telegram"); + + try { + const r = await fetch("/api/panel/footer", { credentials: "same-origin" }); + if (!r.ok) return; + const j = await r.json().catch(() => null); + if (!j || typeof j !== "object") return; + + const subtitle = typeof j.promoSubtitle === "string" ? j.promoSubtitle.trim() : ""; + if (sub) sub.textContent = subtitle; + + const okD = wirePanelPromoAnchor(aDonTop, j.donateUrl, j.donateLabel); + const okT = wirePanelPromoAnchor(aTgTop, j.telegramUrl, j.telegramLabel); + if (sepTop) sepTop.classList.toggle("hidden", !(okD && okT)); + + wirePanelPromoAnchor(aDonF, j.donateUrl, j.donateLabel); + wirePanelPromoAnchor(aTgF, j.telegramUrl, j.telegramLabel); + + const footerD = aDonF && !aDonF.classList.contains("hidden"); + const footerT = aTgF && !aTgF.classList.contains("hidden"); + if (gap1) gap1.classList.toggle("hidden", !(footerD || footerT)); + if (sepMid) sepMid.classList.toggle("hidden", !(footerD && footerT)); + + if (strip && (okD || okT)) strip.classList.remove("hidden"); + } catch { + /* офлайн или сбой — блок остаётся скрытым */ + } +} + function ensureEditionBannerInstallLogPanel() { if (!editionBanner) return null; let wrap = editionBanner.querySelector(".edition-banner-install-log"); @@ -1603,4 +1659,5 @@ async function boot() { } } +void hydratePanelPromoFooter(); boot(); diff --git a/public/index.html b/public/index.html index 292d14a..b3c6557 100644 --- a/public/index.html +++ b/public/index.html @@ -7,9 +7,20 @@ - +
+ + - +