Отзыв с iPhone после первого живого прогона. Масштабирование запрещено (ADR-066): viewport как в соседнем sixlines плюс viewport-fit=cover, мета-теги установленного приложения, touch-action против двойного тапа и страховка на JS — гашение жестов iOS, потому что мета-строку Safari вправе проигнорировать. Размеры шрифтов не тронуты: 14 px из брифа остаются, поднимать поля до 16 px владелец отклонил. Цена — доступность для тех, кому зум нужен — записана в ADR и в ui.md честно. Версия в подвале (ADR-065, 067): GET /api/config отдаёт короткую ревизию и время коммита. Именно коммита, а не сборки: штамп компиляции в бинаре means каждая пересборка даёт новый хеш, и обещание ADR-022 «бинарь собирается из тега байт в байт» перестаёт проверяться. Самообновление PWA (ADR-068, 070): в режиме приложения на iPhone перезагрузки нет, и старая версия жила бы вечно. Проверка при возврате в приложение, включение ждущей оболочки, перезагрузка — но не тогда, когда в строке набран текст. Замок от петли сравнивает версию оболочки, а не считает перезагрузки: счётчик отменял саму фичу, долгоживущая вкладка переставала обновляться. Замерено: было 30, 60, 120, 240 секунд между релизами, стало ровно 30. Строка ввода — редактируемый блок (ADR-069): iOS рисует над клавиатурой полосу со стрелками и «готово» для полей формы, и убрать её со страницы нельзя. Для contenteditable не рисует. Режим plaintext-only с проверкой, что он применился, и запасным путём с разбором вставки: невалидное значение атрибута в части браузеров делает блок нередактируемым вовсе. Чтение и запись только через textContent, innerHTML в клиенте по-прежнему нет. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015DbCjVfTFq4ZFG8juD45YJ
3.5 KiB
ADR-072: Отложенное обновление возвращается по таймеру
Уточняет ADR-068: поводов вернуться к отложенному было два, и оба мимо самого частого случая.
Контекст
Обновление ждёт, пока в полях вкладки набранное: перезагрузка унесла бы его. Вернуться к отложенному могли только событие input и возвращение в приложение.
Строка ввода пустеет и без того, и без другого. Отправка сообщения чистит блок присваиванием — события input это не порождает. Экран, с которого ушли, выбывает из документа вместе со своим полем — тем более.
Замер: во вкладке с черновиком соседняя вкладка включила новый выпуск, контроллёр сменился, перезагрузка отложена. Enter отправляет сообщение, поле пусто, вкладка на виду — за полторы минуты перезагрузки нет, оболочка прежняя. Один цикл смены видимости — перезагрузка через две секунды. То есть после самого обычного действия, «написал и отправил», приложение остаётся на старой оболочке до следующего возвращения в него, хотя платить за обновление уже нечем. Ради этого случая ADR-068 и написан.
Решение
- Отложенное набранным возвращается само, по таймеру: полминуты, тем же таймером, которым возвращается отложенное паузой между перезагрузками (ADR-070). Поля пусты — обновление идёт дальше; набранное на месте — таймер заводится снова.
- Таймер заводится только тогда, когда обновление уже ждёт: оболочка сменилась или установленная версия ждёт включения. Иначе проверка полей крутилась бы вхолостую всю жизнь вкладки.
- Событие
inputостаётся: опустевшее поле оно замечает сразу, а таймер — не позже чем через полминуты.
Следствия
- Отправленное сообщение больше не держит вкладку на старой оболочке: обновление доезжает в течение полуминуты после того, как поле опустело.
- Уход с экрана — то же самое: поле пропадает вместе с экраном, и заметить это иначе нечем.
- Пока обновление ждёт, а в полях набранное, вкладка раз в полминуты обходит свои поля. Это дешевле, чем протокол между экранами и обновлением.
- Записано в
docs/ui.md, «Сеть и состояния».