9.0 KiB
Diff: Уведомления (Notifications) — итерация 1 (2026-07-13)
Ff_app: 63.6% (done 14 / open 8, n-a 1) · Fd_app: 0.0% (Roborazzi-сверка в работе) · автор b-mob-notify
Итерация 1b (2026-07-13): P1-лента закрыта лидом (
a30627a) + P1-push unregister закрыт (клиентcc7ad71+ вызов в logout255c962). Ff 45.5% → 63.6%.
Сверка веб (
nextcloud/notifications 5.0.0-dev.0+ тема forbion, mail/078) ↔ натив (реализован в app-shell). Лента УЖЕ работает:NotificationsSheet(app/AppSheets.kt) +F7NotificationRow(core/designsystem) +NotificationsRepository(core/network, API v2).[done]= есть в коде натива;Fd=0%— вёрстка на устройстве/визуально ещё не сверялась. Карта-источник:notifications.md(из кода + живая сверка forbion, Browser 1/cloude, read-only; лентаcloude= 3 уведомленияfirstrunwizard).NB зона: лента в
app/AppSheets.kt+core/*(зона лида) — P1-функционал он закрыл сам (mail/113). Моё: core/push (retry+unregister — done) и Fd (Roborazzi-строка уведомления вcore/designsystem/src/test+ веб-эталон 360 CSS-px) — по разрешению лида (mail/112б).feature/notifications— после приёмочного гейта (mail/112б).
Метки: [Ф|Д] (функционал/дизайн) · [open|done|n-a].
Экран 1. Триггер (колокольчик) — Ff n-a (зона лида)
Колокольчик-вход живёт в шелле (нижняя шторка, слот #mobile-header-notifications) — зона
b-dev-mobile (shell.md), не считаю в свой Ff.
Ф (1, n-a 1):
- [Ф][n-a] иконка-триггер + раскрытие ленты — шелл (лид). Индикатор непрочитанных (точка
showDot/ warninghasThrottledPushNotifications) — если понадобится, отдельным пингом лиду.
Экран 2. Лента (дропдаун/шит) — Ff 71.4% · Fd 0%
Ф (8, done 5, open 2, n-a 1):
- [Ф][done] загрузка списка (
NotificationsRepository.load, OCS API v2,limit=50) - [Ф][done] пустое состояние «Нет уведомлений» (иконка
nof-not-icon.svg+ текст) —items.isEmpty() - [Ф][done] состояние загрузки (спиннер
CircularProgressIndicator) - [Ф][done] состояние ошибки (текст
error) - [Ф][done] «Скрыть все уведомления» (
dismissAll()→DELETE …/api/v2/notifications) — лидa30627a(заголовок ленты + кнопка + оптимистичное скрытие) - [Ф][open] баннер fairUsePolicy при throttled push («Push notifications might be unreliable») — P3
- [Ф][open] авто-обновление ленты: сейчас только push-триггер (
refreshRequest), ETag/поллинга (lastETag/notify_push) НЕТ — P2 - [Ф][n-a] пустой вариант «Запрос разрешений браузера» (
webNotificationsGranted===null) — n-a: веб-концепт web-push; натив на FCM, разрешение POST_NOTIFICATIONS запрашивается системно
Д (5, open 5): [Д][open] вёрстка ленты по теме/токенам · [Д][open] высота/скролл шита · [Д][open] пустое состояние (вид иконки/текста) · [Д][open] состояние загрузки/ошибки · [Д][open] анимация inbox-zero (галочка+конфетти при переходе >0→0) — P3
Экран 3. Элемент уведомления (F7NotificationRow ↔ NotificationItem) — Ff 58.3% · Fd 0%
Ф (12, done 7, open 5):
- [Ф][done] относительное время (
formatNotificationRelativeTime) — совпадает с forbion («N минут назад») - [Ф][done] кнопка «Скрыть» (× →
dismissNotification→DELETE …/notifications/{id}) - [Ф][done] иконка app (
resolveNotificationIcon+AsyncImageс auth-хедером) - [Ф][done] subject (плоский текст)
- [Ф][done] message (плоский текст, если есть)
- [Ф][done] переход по тапу (
onNotificationClick→openAppLink(notification.link)) - [Ф][done] action-кнопки уведомления (
actions[]→F7NotificationActionUi, FlowRow) — лидa30627a(primary=заливка, прочие=контур); закрывает Talk-приглашения и т.п. - [Ф][open]
subjectRich(NcRichText+ User/File-параметры) — только плоский subject — P2 - [Ф][open]
messageRich(rich + autolink) — только плоский message — P2 - [Ф][open]
externalLink(вариант «↗», target=_blank + primary-кнопка «Contact…») — не отличается от обычной ссылки — P3 - [Ф][open] сворачивание длинного message (
.collapsed+ разворот по тапу) — нет — P3 - [Ф][open] подсветка нового
notification--new— нет — P3
Д (4, open 4): [Д][open] компоновка строки (время+× сверху, иконка+subject/message) ·
[Д][open] вёрстка по теме (карточный стиль _mobile-common.css + токены) · [Д][open] иконки/аватар ·
[Д][open] типографика subject(SemiBold)/message/время
Экран 4. Кнопка действия (F7NotificationActionUi ↔ ActionButton) — Ff 66.7% · Fd 0%
Реализовано лидом (a30627a): парсинг actions[] (parseActions, type→uppercase, default GET,
primary), рендер F7NotificationActionUi, выполнение executeAction.
Ф (3, done 2, open 1):
- [Ф][done] primary/контур по флагу
primary(F7NotificationActionUi.primary) — рендер FlowRow. (нюанс упстрима: тамisWebLink||primary→primary; в нативе только флагprimary— визуально сойдётся, разберём в Fd, не Ф-дыра) - [Ф][done] выполнение действия (
executeAction: POST/PUT/DELETE, иначе GET, по абсолютномуaction.link+OCS-APIRequest) + оптимистичное скрытие уведомления после - [Ф][open] WEB-действие как прямая ссылка/открытие в браузере —
executeActionдля типаWEBуходит вelse→GET(упстрим: WEB = открытьlinkв браузере, а не HTTP-GET). Пограничный случай, но семантика иная — P3. (сообщу лиду, если встретится WEB-action живьём)
Вне карты-экрана: core/push (моя зона, отдельный бэклог)
Не входит в Ff ленты (нет веб-экрана-аналога), но моя зона и уже зафиксировано в представлении (mail/070). Держу как отдельный трек:
- [Ф][done] unregister при logout — ЗАКРЫТО. Контракт f7push (mail/110). Клиент
F7PushRegistrar.unregisterBlocking(cc7ad71, compile+detekt green) + вызов вMainViewModel.logout()best-effort на IO рядом с ревокацией (лид255c962, mail/112а). P1-push. - [Ф][done] retry/бэкофф в
F7PushRegistrar.registerBlocking(3 попытки, бэкофф 1с/3с, повтор на 0/5xx/408/429, стоп на 2xx/4xx) — коммитa6bda89, compile+detekt green (P2-push) - [Ф][n-a] серверные хвосты FCM (чистка 403 SenderId mismatch, старые
f7cloud-apk) — ячейка A, через integrator-b (mail/064) — вне натива
Сводка
- Ff = 63.6% (done 14 / open 8; n-a 3 не в счёте: web-permission-empty, триггер-шелл, серверный FCM).
- P1 — ЗАКРЫТ: «Скрыть все» + action-кнопки + парсинг
actions(лидa30627a); unregister-push (клиентcc7ad71+ вызов255c962); retry регистрации (a6bda89). - P2 (осталось): rich subject/message, авто-обновление ETag.
- P3 (осталось): fairUsePolicy-баннер, external-«↗», WEB-action как ссылка, сворачивание
message,
notification--new, inbox-zero. - Fd=0% → в работе автономно: Roborazzi-скрин
F7NotificationRowвcore/designsystem/src/test(w360dp) + веб-эталон 360 CSS-px (пустое состояние, без данныхcloude) — по mail/111/112б.