iOS: запрет масштабирования, версия в подвале, самообновление, строка ввода
Отзыв с 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
This commit is contained in:
+14
-30
@@ -2,7 +2,7 @@
|
||||
//
|
||||
// bare serve запустить http-сервер
|
||||
// bare vapid напечатать пару vapid-ключей
|
||||
// bare version напечатать ревизию сборки
|
||||
// bare version напечатать ревизию и время коммита
|
||||
package main
|
||||
|
||||
import (
|
||||
@@ -16,11 +16,11 @@ import (
|
||||
"net/http"
|
||||
"os"
|
||||
"os/signal"
|
||||
"runtime/debug"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"github.com/xmatic-squad/bare/internal/api"
|
||||
"github.com/xmatic-squad/bare/internal/build"
|
||||
"github.com/xmatic-squad/bare/internal/config"
|
||||
"github.com/xmatic-squad/bare/internal/store"
|
||||
"github.com/xmatic-squad/bare/internal/web"
|
||||
@@ -56,7 +56,7 @@ func usage() {
|
||||
использование:
|
||||
bare serve запустить http-сервер
|
||||
bare vapid напечатать пару vapid-ключей
|
||||
bare version напечатать ревизию сборки
|
||||
bare version напечатать ревизию и время коммита
|
||||
|
||||
настройка — переменные окружения BARE_*, см. docs/deploy.md
|
||||
`)
|
||||
@@ -159,33 +159,17 @@ func vapid() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// version печатает, какой код собран в этот бинарь: короткую ревизию
|
||||
// и время коммита. Время коммита, а не компиляции: штамп момента сборки
|
||||
// делал бы каждую пересборку одного коммита новым файлом, и сверка хеша
|
||||
// со сборкой из тега перестала бы что-либо значить (ADR-022, ADR-065).
|
||||
// Ревизию, которой нет, и время, которого нет, бинарь не выдумывает
|
||||
// (ADR-057).
|
||||
func version() {
|
||||
fmt.Println(revision())
|
||||
}
|
||||
|
||||
// revision — ревизия сборки. У бинаря из изменённого рабочего дерева
|
||||
// к ней дописывается «+dirty»: сверка хеша со сборкой из тега — единственное
|
||||
// смягчение против подмены клиента (docs/threat-model.md), и чистый хеш
|
||||
// коммита у бинаря с чужими правками сводил бы её на нет (ADR-057).
|
||||
func revision() string {
|
||||
info, ok := debug.ReadBuildInfo()
|
||||
if !ok {
|
||||
return "unknown"
|
||||
info := build.Current()
|
||||
line := info.Version()
|
||||
if !info.CommitAt.IsZero() {
|
||||
line += " " + info.CommitAt.UTC().Format(time.RFC3339)
|
||||
}
|
||||
var vcs, modified string
|
||||
for _, s := range info.Settings {
|
||||
switch s.Key {
|
||||
case "vcs.revision":
|
||||
vcs = s.Value
|
||||
case "vcs.modified":
|
||||
modified = s.Value
|
||||
}
|
||||
}
|
||||
if vcs == "" {
|
||||
return "unknown"
|
||||
}
|
||||
if modified == "true" {
|
||||
return vcs + "+dirty"
|
||||
}
|
||||
return vcs
|
||||
fmt.Println(line)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user