8 Commits

Author SHA1 Message Date
grendervill 8814fe7cf4 release: glchat 0.1.1
Версия — в одном месте: файл VERSION в корне, из него её берут Makefile,
deploy/install.sh (IMAGE_TAG) и desktop-обёртка (tauri.conf.json, Cargo.toml).

Публикация обновлений (scripts/desktop-release.sh):
- манифесты прошлых релизов удаляются: оставшийся <старая версия>.json
  перекрывал новый релиз — обёртка спрашивает манифест своей версии и видела
  «обновлений нет»;
- mktemp-каталог раскладки получает 755, каталоги на инстансе
  нормализуются: rsync -a переносил режим 0700 на корень каталога обновлений,
  и приложение не могло читать манифесты (404 при живых файлах);
- --remote работает без TTY и без sudo, если каталог обновлений записываем;
  опции ssh — в GLCHAT_SSH_OPTS;
- предупреждение при публикации версии старше уже опубликованной.

Сервер: HEAD /updates/... (chi не выводит его из GET) — размер и тип артефакта
без скачивания; тест TestUpdatesAnswersHead.

Приёмка на живом канале: 0.1.0 → 0.1.1 на стенде (скачивание, проверка
подписи, установка, перезапуск), /Applications/glchat.app = 0.1.1.
2026-09-26 20:14:25 +03:00
grendervill e7c9c93443 docs(desktop): приёмка автообновления, .dmg в песочнице и открытые пункты
- `--update-now` в таблице аргументов и в разделе «Автообновление»: что делает,
  как запускать, что подпись проверяется так же, пример записей в журнале;
- «Локальная проверка «поверх старой версии»»: пошаговый рецепт прогона
  0.1.0 → 0.1.1 на локальном сервере инстанса и три грабли — http-эндпоинт
  требует временного `dangerousInsecureTransportProtocol`, путь приложения не
  должен содержать символических ссылок (`/tmp` → `/private/tmp`), в headless
  нужен `--update-now`;
- `.dmg`: точные команды — обычным терминалом (`make desktop-build`, с
  оформлением окна) и без графической сессии (`bundle_dmg.sh --sandbox-safe`,
  проверено: образ монтируется, `hdiutil verify` — VALID);
- «Что не сделано»: автообновление end-to-end проверено локально, открытым
  остаётся публикация реального релиза; добавлено наблюдение, что `open --args`
  из песочницы агента аргументы не доставляет (проверено на macOS 27).
2026-09-26 18:12:42 +03:00
grendervill b53cf9d6e7 feat(desktop): тихая установка обновления по флагу --update-now
Установка обновления всегда спрашивала согласие диалогом, поэтому сквозная
проверка «поверх старой версии» не автоматизировалась (в headless-прогоне
кликнуть некому), а на управляемых машинах обновление ставит оператор, а не
пользователь. С флагом `--update-now` обёртка проверяет обновление сразу при
старте (не через 30 секунд) и ставит найденное без диалога, после чего
перезапускается; при отсутствии обновления работает как обычно.

По умолчанию флаг выключен — трей, страница настроек и фоновая проверка
по-прежнему спрашивают согласие. Подпись артефакта проверяется в обоих
режимах: флаг убирает вопрос, но не проверку. Ход тихого обновления виден в
журнале, а в строку запуска добавлена версия сборки — иначе после перезапуска
не понять, какая версия работает.

Решение — D-077, приёмка — desktop/README.md («Локальная проверка»).
2026-09-26 18:12:35 +03:00
grendervill 19d2501ab0 docs(desktop): замеры ресурсов на финальной сборке
Числа в README приведены к сборке, которая поставляется: холодный старт
773–898 мс (процесс 74–78 мс + страница 696–821 мс), RSS 254 МБ
(обёртка 117 + WebKit 137), в трее 256 МБ, физический след 106 МБ.
Прошлый прогон (708–740 мс, 252 МБ) снят с бинарника до правки выхода из трея —
расхождение в пределах разброса, но в документации должны стоять числа
отгружаемой сборки.
2026-09-22 23:21:52 +03:00
grendervill 4d39002a1f docs(desktop): манифест обновлений, поведение при клике по уведомлению, замеры и открытые пункты
README обёртки приведён в соответствие с кодом:

- раздел «Автообновление»: раскладка каталога `UPDATES_DIR`, публикация релиза
  (`make desktop-release`, `make desktop-release-upload HOST=…`), зачем нужен
  `latest.json`, проверка через curl и лог обёртки; отдельно отмечено, что
  владельцу внешнего прокси добавлять ничего не нужно;
- раздел «Уведомления и переход в канал»: реализованное поведение по активации
  приложения и честное ограничение (ОС не сообщает, что активация вызвана
  кликом по уведомлению);
- раздел «Ресурсы и холодный старт»: замеры 708–740 мс и 252 МБ RSS, как
  повторить (`scripts/desktop-perf.py`);
- «Что осталось оператору»: точные команды для `.dmg`
  (`make desktop-build` из обычного терминала), подписи Developer ID и
  нотаризации (`APPLE_*`, `stapler validate`, `spctl`), сборки и подписи
  Windows/Linux, требования к ключу обновлений; отдельно — поведение на Wayland
  (нативная тряска окна не работает, остаётся CSS).
2026-09-22 23:17:48 +03:00
grendervill 72c5189e8f feat(desktop): переход в комнату по уведомлению, выход без потери правок, Ctrl/Cmd+K
Три пункта спецификации клиента (docs/client-tauri.md §5), которые оставались
открытыми в обёртке:

- **Клик по уведомлению → переход в канал.** У `tauri-plugin-notification` на
  desktop нет колбэка действия, поэтому реализовано лучшее доступное поведение:
  уведомление, показанное при неактивном окне, запоминается, и когда приложение
  активируется в течение 10 секунд (окно получило фокус или macOS прислала
  `RunEvent::Reopen`), окно поднимается и открывается комната из уведомления —
  `glchat://guild/<id>/channel/<id>`, для личной беседы `glchat://dm/<id>`.
  Идентификаторы проверяются (только цифры), чтобы из текста уведомления нельзя
  было собрать произвольный deep link. Ограничение: ОС не сообщает, что
  активация вызвана именно кликом, поэтому переход сработает и при обычном
  возврате в приложение в эти 10 секунд — это описано в desktop/README.md;

- **Выход при несохранённых изменениях.** Клиент сообщает о правках командой
  `desktop_set_dirty`; закрытие окна и пункт «Выход» в трее перехватываются
  (`window::request_close_confirmation`), окно best-effort покачивается
  (`Window::set_position`, на Wayland молча пропускается), а решение принимает
  пользователь в диалоге клиента «Сохранить / Выйти без сохранения»; закрывает
  приложение команда `desktop_close_window`. Раньше выход из трея терял правки
  молча;

- **Ctrl/Cmd+K.** Комбинация регистрируется глобально (`shortcuts.rs`) и при
  неактивном окне поднимает окно и просит клиент открыть палитру команд
  (`WebMessage::OpenPalette`); повторы комбинаций с настраиваемыми шорткатами
  отсекаются по разобранной комбинации, иначе вторая регистрация падала бы.

Заодно: `updates.rs` получил тест, который разбирает манифест релиза типом
самого `tauri-plugin-updater` (`RemoteRelease`) — он ловит расхождение формата
(например, дату не в RFC 3339), из-за которого обновление молча не приходило бы.
Проверки: `make desktop-check` (fmt, clippy, 10 тестов).
2026-09-22 23:17:27 +03:00
grendervill a7b4e3318e build(desktop): цели make, README и устойчивость обёртки к правам на логи
- Makefile: `desktop-check`, `desktop-build` (с ключом подписи обновлений,
  без ключа — сборка без артефактов обновления) и `desktop-run`; кэши
  cargo и npm держатся в .cache/, как у остальных инструментов проекта.
- desktop/README.md: сборка, запуск, аргументы командной строки, настройки,
  deep links и открытые пункты Фазы 6.
- bundle.targets = all: бандлы по умолчанию для текущей ОС (macOS: .app/.dmg).
- Логирование подключается в setup и больше не роняет приложение, если
  каталог логов недоступен на запись (песочница, домашний каталог только
  для чтения).
- Разбор аргументов вынесен в Cli::from_args и покрыт тестами
  (--instance, --minimized, --settings, --autostart on|off).
- cargo fmt по модулям обёртки.
2026-09-22 21:55:19 +03:00
grendervill cffcec72b8 feat(desktop): обёртка Tauri 2 вокруг веб-клиента
Первый инкремент Фазы 6 (docs/client-tauri.md): окно с тем же веб-клиентом
(по умолчанию https://gl.mhspx.su, адрес настраивается), трей с меню и
индикатором непрочитанных, нативные уведомления, глобальный push-to-talk и
переключение микрофона/deafen, автозапуск, single-instance, сохранение
геометрии окна, deep links glchat://…, автообновление по подписанному
манифесту.

Связь страницы с обёрткой — через платформенный адаптер
(web/src/lib/platform.ts) и минимальный типизированный набор команд;
в веб-клиенте появились системные уведомления об упоминаниях и личных
сообщениях и переключатель в настройках.

В web/src/stores/gateway.ts вместе с вызовом уведомления лежат правки по
дефектам realtime (READY и сессии) из параллельной волны: файл коммитится
целиком по договорённости с координатором.
2026-09-22 21:46:01 +03:00