users: подписка как список ссылок из бэка (Mihomo URL + clashmi-диплинк) - #116
Merged
Conversation
Колонка «Подписка» открывает попап со списком копируемых ссылок вместо одной
кнопки Mihomo. Каталог ссылок (тайтлы + форматы) живёт на бэке — новый сервис
internal/service/sublinks; фронт ничего не хардкодит, в попапе только тайтл и
кнопка «Копировать» (значение приватное, не показывается).
Форма sub в GET /admin/api/users: {id,url} -> {links:[{title,value}]}.
name clashmi-диплинка = profile title эффективного (кастомного, иначе базового)
конфига пользователя. См. ADR-0008.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Postlog
force-pushed
the
feat/subscription-link-popup
branch
from
June 17, 2026 11:54
599d885 to
00f83e2
Compare
…thooks - Config-вкладка: карточка «Параметры подписки» поднята на первое место (перед proxy-groups). - Убраны остатки githooks: таргет `make hooks` из Makefile и локальный core.hooksPath (каталог .githooks/ был удалён ранее). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Owner
Author
|
Добавлено в этот PR (по ходу ревью-сессии):
Коммит |
Postlog
commented
Jun 17, 2026
По ревью PR #116: - Интерфейсы зависимостей во всех contract.go названы по конкретной зависимости (repo -> <сущность>Repo, service -> <сущность>Service, client -> <сущность>Client) вместо ролевых имён (subLinker/configResolver/mihomoReader/creator/deleter/...). Правило закреплено в AGENTS.md. - sublinks: catalogKinds вычисляется один раз на import-time (var-IIFE вместо вызова функции на каждый запрос). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
postlog-vibecoder
previously approved these changes
Jun 18, 2026
CI линтил закоммиченный ce873ff без этих переводов строк и падал на wsl_v5 (assign под ExprStmt в sub_valid_test; if под несвязанным присваиванием в sublinks.go; два присваивания над if в sublinks_test). Локально не воспроизводилось: format-хук уже добавил их в рабочее дерево, но в коммит они не попали. Коммичу рабочее дерево — оно wsl_v5-чистое. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
make lint больше не зависит от локального golangci-lint (host-сборка под darwin/arm64 расходилась с CI на wsl_v5). Теперь запускает тот же pinned образ golangci/golangci-lint:v2.12.2 на linux/amd64, что и GitHub Actions, — локальный линт байт-в-байт совпадает с CI. DOCKER_CONTEXT в Makefile не зашит (специфика машины) — передаётся при вызове: `DOCKER_CONTEXT=desktop-linux make lint`. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
… нативная арка) ci.yml и deploy.yml больше не используют golangci-lint-action: оба вызывают `make lint`, который гоняет pinned-образ golangci/golangci-lint:v2.12.2 в Docker (версия пиннится в одном месте — Makefile). Платформа не фиксируется -> нативная для хоста (CI amd64 / Apple Silicon arm64); все включённые линтеры арх-независимы на 64-бит, поэтому результат идентичный без эмуляции (максимум скорости). Кэш модулей и build/analysis — в gitignored .lintcache/ (на CI — через actions/cache). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
postlog-vibecoder
approved these changes
Jun 18, 2026
Postlog
pushed a commit
that referenced
this pull request
Jun 18, 2026
Make the admin panel usable on every screen — mini-phones (320px) through ultrawide. Static-only (app.css/app.js/index.html); Go is untouched and the desktop (>=992px) is visually unchanged. - navbar collapses into a hamburger below lg (992px): animated toggle + a full-width collapsible menu; the tabs became <button> (keyboard-operable) with a focus-visible ring; - the Users/Nodes tables turn into data-label cards below 992px (two-up on tablets via CSS-grid; the table returns at >=992px); - the config constructors and rule/group/sub-rule rows stack below 768px; the orphaned delete "x" is right-aligned; - touch targets >=40px and 16px inputs (iOS no-zoom) below 768px; hover popovers (connections, description) open on tap (:focus-within + tabindex); - modals are a flex column that scrolls only the body (header/footer pinned even on a short landscape screen), with a vh fallback before dvh; - the Monaco base-YAML editor no longer traps page scroll on touch; - ultrawide widens the container (>=1600px -> 1320px, >=2200px -> 1560px). Re-applied on top of the English UI (#117) and the subscription-links popup (#116) — the new sublinks modal reuses the generic responsive modal. Verified with headless Chrome / Playwright at 320/360/500/768/850/1024/1280/1600px (no horizontal overflow, no desktop regression). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Postlog
pushed a commit
that referenced
this pull request
Jun 18, 2026
Make the admin panel usable on every screen — mini-phones (320px) through ultrawide. Static-only (app.css/app.js/index.html); Go is untouched and the desktop (>=992px) is visually unchanged. - navbar collapses into a hamburger below lg (992px): animated toggle + a full-width collapsible menu; the tabs became <button> (keyboard-operable) with a focus-visible ring; - the Users/Nodes tables turn into data-label cards below 992px (two-up on tablets via CSS-grid; the table returns at >=992px); - the config constructors and rule/group/sub-rule rows stack below 768px; the orphaned delete "x" is right-aligned; - touch targets >=40px and 16px inputs (iOS no-zoom) below 768px; hover popovers (connections, description) open on tap (:focus-within + tabindex); - modals are a flex column that scrolls only the body (header/footer pinned even on a short landscape screen), with a vh fallback before dvh; - the Monaco base-YAML editor no longer traps page scroll on touch; - ultrawide widens the container (>=1600px -> 1320px, >=2200px -> 1560px). Re-applied on top of the English UI (#117) and the subscription-links popup (#116) — the new sublinks modal reuses the generic responsive modal. Verified with headless Chrome / Playwright at 320/360/500/768/850/1024/1280/1600px (no horizontal overflow, no desktop regression). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Postlog
pushed a commit
that referenced
this pull request
Jun 18, 2026
Make the admin panel usable on every screen — mini-phones (320px) through ultrawide. Static-only (app.css/app.js/index.html); Go is untouched and the desktop (>=992px) is visually unchanged. - navbar collapses into a hamburger below lg (992px): animated toggle + a full-width collapsible menu; the tabs became <button> (keyboard-operable) with a focus-visible ring; - the Users/Nodes tables turn into data-label cards below 992px (two-up on tablets via CSS-grid; the table returns at >=992px); - the config constructors and rule/group/sub-rule rows stack below 768px; the orphaned delete "x" is right-aligned; - touch targets >=40px and 16px inputs (iOS no-zoom) below 768px; hover popovers (connections, description) open on tap (:focus-within + tabindex); - modals are a flex column that scrolls only the body (header/footer pinned even on a short landscape screen), with a vh fallback before dvh; - the Monaco base-YAML editor no longer traps page scroll on touch; - ultrawide widens the container (>=1600px -> 1320px, >=2200px -> 1560px). Re-applied on top of the English UI (#117) and the subscription-links popup (#116) — the new sublinks modal reuses the generic responsive modal. Verified with headless Chrome / Playwright at 320/360/500/768/850/1024/1280/1600px (no horizontal overflow, no desktop regression). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Postlog
pushed a commit
that referenced
this pull request
Jun 19, 2026
Make the admin panel usable on every screen — mini-phones (320px) through ultrawide. Static-only (app.css/app.js/index.html); Go is untouched and the desktop (>=992px) is visually unchanged. - navbar collapses into a hamburger below lg (992px): animated toggle + a full-width collapsible menu; the tabs became <button> (keyboard-operable) with a focus-visible ring; - the Users/Nodes tables turn into data-label cards below 992px (two-up on tablets via CSS-grid; the table returns at >=992px); - the config constructors and rule/group/sub-rule rows stack below 768px; the orphaned delete "x" is right-aligned; - touch targets >=40px and 16px inputs (iOS no-zoom) below 768px; hover popovers (connections, description) open on tap (:focus-within + tabindex); - modals are a flex column that scrolls only the body (header/footer pinned even on a short landscape screen), with a vh fallback before dvh; - the Monaco base-YAML editor no longer traps page scroll on touch; - ultrawide widens the container (>=1600px -> 1320px, >=2200px -> 1560px). Re-applied on top of the English UI (#117) and the subscription-links popup (#116) — the new sublinks modal reuses the generic responsive modal. Verified with headless Chrome / Playwright at 320/360/500/768/850/1024/1280/1600px (no horizontal overflow, no desktop regression). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Что и зачем
Колонка «Подписка» в списке пользователей открывала одну кнопку «Mihomo», копировавшую единственный URL. Конфигов/клиентов становится больше — нужно копировать и сам URL подписки, и диплинк приложения Clashmi (
clashmi://install-config?url=<enc>&name=<title>&overwrite=false), а в будущем и другое.Теперь это попап со списком копируемых ссылок. Главное требование: фронт ничего не хардкодит — состав ссылок и их тайтлы целиком приходят с бэка.
Как сделано
internal/service/sublinks(новый сервис) — владеет упорядоченным каталогом ссылок[]linkSpec{title, kind, build}: для Mihomobuild— сам URL, для Clashmi — формат диплинка. Добавить движок/приложение = одна строка каталога, фронт не меняется.nameclashmi-диплинка = profile title эффективного конфига пользователя (кастомный, иначе базовый). Резолв эффективен: базовый title читается один раз на движок, кастомы — только у кого есть.subвGET /admin/api/users:{id,url}→{links:[{title,value}]}(idфронтом не использовался,urlзаменён списком).sub.linksвербатим.UserSub.Links+ хелперSubURL()(берёт сырой URL по http-схеме, не по тайтлу).Решение и альтернативы — ADR-0008.
Проверка
go build/vet/testзелёные;go vet -tags apitest ./apitest/...ок. Подняли локально с тест-данными: alice/bob →name=Freedom(база), carol →name=Freedom Pro(её кастом) — per-user title резолвится верно.Заметки для ревью
main(без responsive-работы изfeat/responsive-admin).(#PR)в CHANGELOG/ADR проставлю номером после открытия PR.🤖 Generated with Claude Code