caps_enhancer/CLAUDE.md

98 lines
6.7 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# CAPS Enhancer — Chrome Extension
Chrome-расширение (Manifest V3) для улучшения интерфейса CAPS/UTP: навигационные кнопки, автологин, замена логотипа, редирект noVNC.
## Архитектура
```
caps_enhancer-1/
├── manifest.json # MV3, update URL, content scripts on <all_urls>
├── js/
│ ├── background.js # Service worker: проверка обновлений (chrome.alarms)
│ ├── content.js # Инициализация: роутинг по типу страницы
│ ├── popup.js # Popup: быстрые переключатели
│ ├── options.js # Страница настроек: загрузка/сохранение конфига
│ └── strings.js # Все строки UI (русский)
├── modules/
│ ├── core.js # CONFIG, утилиты, loadConfig(), updateConfig()
│ ├── mnemoschema.js # Кнопки «Мнемосхема» и «Лещ» на главной странице
│ ├── video-window.js # Кнопка с IP или «Лещ» в заголовке видео-окна
│ ├── novnc-redirect.js # Редирект или кнопка на noVNC-странице
│ ├── auto-login.js # Автологин с профилями и правилами подсетей
│ └── close-handler.js # ESC закрывает видео-окна и карточки
├── options.html / popup.html
├── css/options.css / popup.css
└── server/ # Деплой: .crx, nginx.conf, .reg, update.xml
```
## Конфигурация (core.js CONFIG)
Хранится в `chrome.storage.sync` под ключом `config`. Структура:
```javascript
{
debug: { enabled, modules: { core, video, mnemo, close, content, novnc, autologin } },
ports: { video: '5000', scheme: '8080' },
videoWindow: {
ipButtonMode: 'button' // 'button' — кнопка «🔗 IP:порт», 'clickable-title' — кнопка «Лещ»
},
novnc: { mode: 'button'|'redirect', redirectDelay: 500 },
mnemo: { mode: 'host-port'|'host-scheme', skipOnDomain, addVideoButton, addSchemeButton },
autologin: { enabled, profilePage1, profilePage2, subnetRules, profiles },
disabledSites: [],
replaceLogo: true,
uiVisible: true
}
```
При добавлении нового поля конфига: обновить `CONFIG` в `core.js`, `updateConfig()` в `core.js`, `DEFAULT_CONFIG` в `options.js`, добавить элемент в `options.html`, загрузку/сохранение в `options.js`, строки в `strings.js`.
## Типы страниц (core.checkPageType)
| Тип | Признаки |
|-----|---------|
| `isMainPage` | логотип CleverPark + noscript-маркер |
| `isVideoPage` | noscript-маркер, нет логотипа |
| `isNoVNCPage` | noscript "You need to enable JavaScript" + один из признаков ниже |
**Признаки noVNC (второй критерий):**
- `div[class*="app_AppWindow__"]` — старый тип страницы (CSS-модульный класс React-компонента)
- `document.title` содержит `"Платёжный терминал"` — новый тип страницы (присутствует в HTML сразу при загрузке, до инициализации React)
**Важно:** не использовать DOM-элементы, которые появляются после загрузки React (например `div#app.App`, `div.multi-find-menu-container`) — они не существуют в момент первой проверки, что приводит к неверному определению типа страницы.
## Модуль video-window.js
Добавляет ссылку на IP устройства в заголовок видео-окна. Два режима (настройка `videoWindow.ipButtonMode`):
- **`button`** (по умолчанию): кнопка `🔗 IP:5000` после `<p>` в заголовке. Tooltip не задан.
- **`clickable-title`**: кнопка **«Лещ»** с тем же стилем и тем же переходом. При наведении — нативный tooltip с полным URL (`button.title`).
Оба режима используют `core.createStyledButton()` — одинаковая стилизация. IP извлекается из src видео-элемента `img[src*=":8888/screen"][src*="/getVideo/"]` через regex `/\/getVideo\/http:\/\/([^\/:?#]+)(?::(\d+))?/i`.
## Модуль novnc-redirect.js
Два режима (`novnc.mode`):
- **`redirect`**: автоматический переход на `http://<host>:<videoPort>`. Редирект происходит если текущий порт **не равен** целевому (не жёсткая привязка к порту 80).
- **`button`**: фиксированная кнопка в правом верхнем углу. После добавления следит за удалением через `MutationObserver` (15 сек) и добавляет кнопку снова — защита от React-рендеринга, который может очищать body.
Важно: у кнопки задан `dataset.capsUiDisplay = 'inline-block'`, чтобы `applyVisibility` не сбрасывала её display в `''`.
## Видимость UI (Shift+F1)
- `data-caps-ui="true"` — элементы расширения (скрываются при `uiVisible=false`)
- `data-caps-ui-display` — исходное значение `display`, восстанавливается при `uiVisible=true`; **обязательно задавать** при создании кнопок с нестандартным display
- `data-caps-original="true"` — оригинальные элементы (скрываются при `uiVisible=true`)
- Логотип меняет `src` вместо `display`
## Паттерны
- Каждый модуль — IIFE, расширяет `window.VideoIPRedirect`
- Общие утилиты: `core.createStyledButton()`, `core.debugLog()`, `core.retryWithBackoff()`
- Конфиг обновляется через `chrome.runtime.onMessage``CONFIG_UPDATED`
- Строки: все тексты UI только в `js/strings.js`, доступ через `getStr('options.key')`
## Деплой
См. [DEPLOY.md](DEPLOY.md). Кратко: упаковать `.crx` → загрузить на сервер → обновить `update.xml` с новой версией → версия в `manifest.json`.