Skip to content

Показывает превью сохранённых страниц, по умолчанию выключенные - #6

Open
knyazevs wants to merge 1 commit into
mainfrom
page-previews
Open

Показывает превью сохранённых страниц, по умолчанию выключенные#6
knyazevs wants to merge 1 commit into
mainfrom
page-previews

Conversation

@knyazevs

Copy link
Copy Markdown
Contributor

Карточка-ссылка умеет показать, что её страница говорит о себе — og:title, og:description и og:image.

Кто читает страницу

Сервер, а не браузер. Клиентский вариант потребовал бы <all_urls> в манифесте (долгая проверка в Chrome Web Store на каждом обновлении) и слал бы запрос с адреса пользователя — то есть сообщал бы каждому сайту, что на него сохранена ссылка. Новых хост-разрешений не нужно: api.stramus.space уже в манифесте.

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

Сервер

GET /v1/preview?url=… внутри authenticate(BEARER), устроен как FaviconService:

  • isFetchableHost на каждом хопе редиректа, редиректы вручную, максимум 3;
  • только text/html, только первые 128 КБ, Accept-Encoding: identity (gzip-бомба не должна превращать лимит в нечто большее);
  • кодировка: заголовок → <meta charset>http-equiv → UTF-8, иначе заголовки с windows-1251 приезжают кракозябрами и рисуются как правильные;
  • теги ниже <body> игнорируются, чтобы чужой комментарий на странице не описывал страницу;
  • og:image принимается только по HTTPS и только с публичного хоста — иначе это заведомо сломанная рамка, закэшированная на две недели;
  • 200 / 204 / 503 по образцу иконок; лимит промахов — на аккаунт, а не на адрес.

Кэш preview_cache (миграция 007) — по SHA-256 адреса и без колонки пользователя. Строка favicon_cache называет хост; строка про страницу называла бы страницу, и таблица читалась бы как чужая история посещений.

Картинка не проксируется и не хранится: наружу отдаётся её адрес, карточка наводит на него <img> с no-referrer — ровно как уже сделано для кадров YouTube, и по той же причине (см. комментарий в Thumbs.kt).

Клиент

Локальный кэш — новое хранилище link_previews (миграция схемы 2, рядом с favicons, не синкается). Без него каждая новая вкладка переспрашивала бы всё заново.

Где превью показываются, решает уже существующая настройка «Превью видео», так что «всегда» означает «всегда» для обоих видов карточек:

Превью видео Что происходит
Выключить ничего не показывается и ничего не спрашивается
При наведении попапом; спрашивается одна карточка — та, на которой курсор
Всегда картинка на плитке; спрашивается каждая ссылка открытой коллекции

В режиме «всегда» ссылка без своей картинки носит плитку с фавиконкой на цвете хоста (тот же стабильный хэш, что у буквенных иконок). Сетка, где высокие три карточки из шестидесяти, — это сетка, перестроенная в колонки ради трёх картинок; теперь колоночная раскладка включается, только когда рядом со ссылками действительно лежат заметки или файлы, а фиксированная высота has-cover переехала с .grid.covers на саму карточку.

Выключение настройки стирает кэш — и в памяти, и на диске. installPreviewSource этого специально не делает: он вызывается на каждом старте, а сессия восстанавливается на мгновение позже первого рендера, так что чистка там стирала бы кэш при каждой загрузке. eraseLocalData тоже теперь забирает link_previews.

Проверено

  • 163 теста (:core:jvmTest :server:test), из них 24 новых: разбор og-тегов, кодировки, guard на адрес.
  • Живьём против локального сервера: 401 без токена; github/habr — теги на месте; lib.ru (windows-1251) — кириллица целая; example.com — заголовок из <title>; SVG и 404 — 204; 127.0.0.1, 169.254.169.254, file:///etc/passwd, db.internal — 204 за 5 мс, наружу ничего не ушло; повтор адреса и якорь #… — из кэша, новых строк нет. В базе после всего только хэши, ни одного адреса в открытом виде.
  • Собраны продовые бандлы расширения и веб-приложения.

Документы

privacy.html (en + ru), store/README.md и store/submission.md обновлены: в submission теперь «Three things a reviewer may ask about».

На что посмотреть при ревью

Заглушка на карточке ставится по cardPreviews == INLINE, независимо от «Превью страниц». То есть при «Превью видео: Всегда» без аккаунта обычные ссылки тоже получат цветную плитку. Логика в том, что «Всегда» означает «каждая карточка с картинкой», и дырявая сетка была там и раньше — но это меняет вид уже выпущенной фичи для тех, кто про превью страниц не просил.

🤖 Generated with Claude Code

Карточка-ссылка умеет показать, что её страница говорит о себе — og:title,
og:description и og:image. Читает их сервер, а не браузер: иначе расширению
понадобился бы <all_urls>, а запрос шёл бы с адреса пользователя, сообщая
каждому сайту, что на него сохранена ссылка.

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

Где превью показываются, решает уже существующая настройка «Превью видео», так
что «всегда» означает «всегда» для обоих видов карточек. В этом режиме ссылка
без своей картинки носит плитку с фавиконкой на цвете хоста: сетка, где высокие
три карточки из шестидесяти, — это сетка, перестроенная в колонки ради трёх
картинок. Колоночная раскладка теперь включается, только когда рядом со
ссылками действительно лежат заметки или файлы.

Картинку сервер не проксирует и не хранит — отдаёт только адрес, а карточка
наводит на него <img> с no-referrer, ровно как это уже сделано для кадров
YouTube.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant