11 KiB
Карта: Уведомления (forbion, мобильная веб-версия)
Снято 2026-07-12. Метод по mail/078: структура берётся ИЗ КОДА
(апстрим nextcloud/notifications, компоненты NotificationsApp.vue / NotificationItem.vue /
ActionButton.vue / IconNotification.vue; на forbion версия 5.0.0-dev.0 — компоненты стабильны
между версиями), живой мобильный web forbion (вьюпорт 390px, аккаунт cloude, строго read-only
по mail/073) — для визуальной сверки размещения и порядка. Живой аккаунт cloude на момент съёмки
имел пустую ленту (empty-state), поэтому структура элемента уведомления и действий снята с кода,
а не с экрана. Пишущих кнопок («Скрыть», «Скрыть все», action-кнопки) НЕ нажимал — dismiss и
выполнение действий это записи (DELETE / произвольный HTTP-метод), а аккаунт реальный рабочий.
Уведомления — НЕ отдельное приложение (нет пункта в шторке приложений и своего URL-роута), а
глобальный дропдаун-лента в шапке (компонент NotificationsApp, монтируется в #notifications).
Вход
В мобильной вёрстке forbion иконка-триггер (колокольчик) живёт в шторке приложений, а не на плавающей нижней панели. Путь:
- Нижняя панель шелла →
≡(«три полоски»,#open-header-menu-mobile) открывает шторкуapp-menu--mobile. - В шторке — слот
#mobile-header-notifications(классf7-mobile-menu-control-slot,mobile-bottom-slot--overlay) с кнопкой-колокольчиком (.notifications-button,aria-label="Уведомления",aria-expanded). - Нижняя плавающая панель (общая, зона лида, для ориентира):
</>(сайдбар-навигация,#mobile-header-left-sidebar-button) · конверт → Почта (/apps/mail/) · «карточки» → Задачи (/apps/tasks/) · камера → Конференции (/apps/spreed/) ·≡→ шторка приложений.
Триггер (колокольчик) — IconNotification
Вид: иконка «колокол». Индикатор состояния (showDot):
- точка-бейдж показывается, когда
notifications.length !== 0или когда браузерные разрешения ещё не запрошены (webNotificationsGranted === null); - значок-предупреждение (
showWarning) — когда push-уведомления задросселированы политикой честного использования (hasThrottledPushNotifications). Действие: тап → раскрывает дропдаун-ленту (aria-expandedfalse→true), эмит@opened → onOpen(подгрузка/пометка ленты активной). Повторный тап или клик вне (кроме.popover) — закрывает.
Экран: Лента уведомлений (дропдаун NcHeaderMenu, класс header-menu)
Контейнер .notification-container внутри .header-menu__content. Тайтл шапки в мобильной
теме — «Уведомления» (.tooltip-header--notifications). Два взаимоисключающих состояния:
Состояние A — есть уведомления (notifications.length > 0)
Тело: список <ul class="notification-wrapper"> из элементов NotificationItem (см. ниже),
сверху вниз, новые (notificationId > lastOpenMaxId) помечены классом notification--new.
Если push задросселирован — первым нештатным элементом идёт баннер «Push notifications might be
unreliable» (fairUsePolicy, key=-2016).
Низ: блок .dismiss-all — кнопка «Скрыть все уведомления» (tertiary, во всю ширину,
иконка «×»). ⚠️ Пишущая: onDismissAll → DELETE /ocs/v2.php/apps/notifications/api/v2/notifications.
Состояние B — пусто (empty-state NcEmptyContent) — наблюдалось у cloude
Три варианта текста (computed emptyContentMessage):
webNotificationsGranted === null→ «Запрос разрешений для показа уведомлений в браузере» (именно это видел уcloude— иконка колоколаbell-outline-icon);- задросселированы push → заголовок = subject fairUsePolicy + описание + кнопка «Contact
Nextcloud GmbH ↗» (внешняя ссылка), иконка
icon-alert-outline; - иначе → «Нет уведомлений» (
No notifications). При переходе списка из >0 в 0 на ~5 сек показывается анимация inbox-zero (галочка + конфетти), затем обычный колокол.
Элемент: NotificationItem (<li class="notification">, из кода)
data-атрибуты: data-id, data-timestamp, data-object-type, data-app.
Шапка элемента (.notification-heading):
- время (
NcDateTime, формат «время + длинная дата»,.notification-time) — если есть timestamp; - кнопка «Скрыть» (
.notification-dismiss-button, tertiary, иконка «×»,aria-label="Dismiss"). ⚠️ Пишущая:onDismissNotification→DELETE …/api/v2/notifications/{id}, затем@remove(убрать из ленты). Субъект (заголовок), три варианта рендера: - если
externalLink→<a target=_blank>классfull-subject-link external, текст «{subject} ↗»; - иначе если есть
link(useLink) →<a>на этот линк; - иначе — просто блок
.notification-subjectбез ссылки. Внутри: опциональная иконка (img.notification-icon); если естьsubjectRich— богатый рендерNcRichTextс параметрами (см. Parameters ниже), иначе простой.subjectс текстом subject. Сообщение (.notification-message, если естьmessage): богатый (messageRich+ autolink) или простой текст; длинное сворачивается (.message-container.collapsed+ градиент.notification-overflow), тап по сообщению — разворот (onClickMessage). Действия (.notification-actions): - если
notification.actions[]непусто — рядActionButtonпо каждому action; - иначе, если есть
externalLink— одна primary-кнопка «Contact Nextcloud GmbH ↗».
Элемент: ActionButton (кнопка действия уведомления)
Поля action (из API): label, link, type, primary.
type === 'WEB'(isWebLink) илиprimary→ кнопка primary; для WEB это прямойhref(ссылка).- прочие типы (GET/POST/DELETE/PUT) → кнопка secondary.
Клик (
onClickAction): эмитnotifications:action:execute(приложение может отменить,cancelAction); для WEB — просто переход по ссылке; иначе ⚠️ пишущий вызовaxios({ method: action.type, url: action.link }), при успехе —@remove(уходит из ленты) + эмитnotifications:action:executed. Ошибка → тост «Failed to perform action». Пример типового уведомления с действиями — приглашение в Talk-беседу: subject + действия «Присоединиться»/«Отклонить» и т.п. (состав задаёт серверное приложение-источник).
Параметры rich-subject/message (Components/Parameters/)
NcRichText подставляет типизированные плейсхолдеры:
UserParameter— пользователь (аватар + имя, кликабельно);FileParameter— файл (иконка + имя, ссылка на файл);DefaultParameter— прочие (просто текст).расхождение:в нативном клиенте (NotificationsRepository/NotificationsSheet) сейчас берётся только плоскийsubject/message(API v2), rich-параметры и иконка app не разворачиваются — это мой бэклог (см. представление mail/070).
API (из кода, все через OCS apps/notifications/api/v2/notifications)
GET …/notifications— лента (в нативе уже есть,NotificationsRepository.load, limit=50);DELETE …/notifications/{id}— скрыть одно (в нативе естьdismiss);DELETE …/notifications— скрыть все (в нативе НЕТ — бэклог «отметить/скрыть все»);{action.type} {action.link}— выполнить действие уведомления (в нативе действий НЕТ — бэклог). Обновление ленты — по ETag (lastETag) и, если доступен, через notify_push (@nextcloud/notify_push).
Стили (тема forbion)
Отдельного _mobile-notifications.css в теме нет: на вебе лента — дроп в шапке
(css/components/_header.css), мобильное размещение колокольчика — слот
#mobile-header-notifications в header__mobile-bottom/шторке (тема
css/pages/pages-mobile/_mobile-common.css). Для нативной ленты держим общий карточный стиль
модулей (_mobile-common.css + токены designsystem) — согласовано с лидом (mail/070).
Открытые вопросы / сверить, когда лента будет непустой
- (?) Как именно выглядит
notification--newв мобильной теме (подсветка/полоса) — на пустом аккаунте не увидеть; сверить на аккаунте с уведомлениями. - (?) Точный порядок и подписи action-кнопок для реальных источников (Talk-приглашение, дедлайны Deck/Календаря) — снять живьём, когда появятся уведомления.
- (?) Сворачивание длинного message в мобильной ширине 390px (высота
.message-container).