Shared media renderer
src/components/common_stack_components/media/ · (UI-компонент) — єдина точка відображення image, video, audio, voice та звичайних файлів у card, inline і fullscreen-контекстах.
Суть
Shared media renderer уніфікує вигляд, loading/error states, playback, fullscreen-навігацію та поведінку звичайних файлів. Feature отримує дані, перевіряє права і перетворює власну модель на AppMediaItem; renderer не виконує бізнес-запитів, upload, moderation або видалення.
Публічні точки інтеграції:
MediaRenderer— показує один нормалізований media item;MediaPreview— fullscreen-галерея над переданою колекцією;getFileType— визначає media kind із declared type, MIME type, filename або URL;createLocalMediaPreviewUrl— готує preview для локального файла до upload.
Use cases
Renderer використовують для вкладень повідомлень, листів, тікетів і коментарів, media libraries і pickers, документів та досягнень у картках, аватарів TU і fullscreen-перегляду колекцій.
Нові feature не повинні створювати власні image/video/audio/file viewers, якщо потрібна поведінка вже підтримується shared renderer.
Межі відповідальності
| Shared renderer | Feature-споживач |
|---|---|
| Вибір renderer за media kind. | Отримання, кешування та оновлення даних. |
| Card, inline і fullscreen presentation. | Мапінг backend-моделі в AppMediaItem. |
| Loading, unavailable і decode-ready states. | Вибір original та preview URL потрібної якості. |
| Playback, seek, mute і час. | Склад, порядок і фільтрація fullscreen-колекції. |
| Навігація та закриття fullscreen. | Перевірка прав і фактичне видалення. |
| File open/download. | Upload, moderation, selection та feature overlays. |
Контракт AppMediaItem
| Поле | Обов’язковість | Значення |
|---|---|---|
id | так | Стабільний string ID у межах колекції. |
kind | так | image, video, audio, voice або file. |
src | так | Original image, actual video/audio/voice або URL файла. |
previewSrc | ні | Полегшене image preview або video poster. |
name / filename | ні | Назва вкладення; використовується для alt/title і file card. |
mimeType | ні | Додаткова підказка для визначення типу. |
size | ні | Розмір у байтах; показується для file в inline і fullscreen. |
url | ні | Legacy fallback для file; нові адаптери використовують src. |
id має залишатися однаковим у card і fullscreen-колекції, інакше initialId не відкриє потрібний елемент.
Визначення типу
getFileType використовує доступні підказки в такому порядку:
- явний declared type:
photo/image,video,voice,audio; - MIME prefix;
- розширення filename або URL;
- невідомий формат стає
file.
Declared type voice навмисно відрізняється від audio, щоб voice message мав власне представлення.
Варіанти відображення
| Variant | Призначення | Поведінка |
|---|---|---|
card | Grid, picker, компактний attachment list. | Показує полегшене preview без preload важкого media stream; клік може делегувати відкриття fullscreen. |
inline | Media всередині сторінки з локальним playback. | Video/audio/voice відтворюються на місці; image/video використовують задану геометрію. |
fullscreen | Один активний item у MediaPreview. | Показує original/playable source, розширені controls і file action. |
Image та video підтримують preset або комбінацію size/aspect ratio/fit. Зовнішній grid, gap, selection, badges і moderation controls залишаються відповідальністю feature.
Original і preview URL
Якщо джерело дає кілька рівнів якості:
| URL | Використання |
|---|---|
previewUrl | Мале card preview. |
mediumUrl | Великий inline preview або video poster. |
url | Original image, playable media або файл. |
Адаптер передає original у src, а потрібний полегшений рівень — у previewSrc. Fullscreen використовує src.
Для image renderer може один раз перейти з недоступного previewSrc на src. У великих grid feature має уникати масового fallback на originals, якщо це створює надмірне мережеве навантаження.
Поведінка за типом
Image
Card та inline резервують media slot до завершення декодування. Під час завантаження показується loader; після помилки обох доступних джерел — unavailable state. Fullscreen показує original у межах viewport.
Video
Card використовує poster і не завантажує actual video для playback. Inline та fullscreen мають спільні play, mute і seek controls. За відсутності poster показується video placeholder.
Audio і voice
Card не preload-ить stream. Inline і fullscreen мають play, seek, current time та duration. Зміна item скидає playback state.
File
File card показує filename та extension. Inline і fullscreen додатково показують розмір, якщо він відомий.
Одна file action завжди запускає завантаження з початковим filename. PDF, TXT/MD і code-файли додатково відкриваються в новій вкладці для браузерного перегляду. Word, document, spreadsheet, presentation, archive та невідомі формати лише завантажуються.
Якщо file host дозволяє frontend-запит, renderer використовує тимчасовий локальний URL. Якщо запит заблоковано CORS або завершується помилкою, застосовується початковий URL.
Fullscreen preview
MediaPreview рендериться поверх сторінки та отримує готовий масив дозволених items. Feature передає initialId або initialIndex, щоб відкрити натиснутий елемент.
Керування:
Escape, close button або клік по overlay закривають preview;ArrowLeft/ArrowRightі кнопки навігації переходять між items;- counter показує позицію у переданій колекції;
- delete action з’являється тільки коли feature передала
onDelete; - під час async delete повторна дія блокується;
- якщо колекція спорожніла, preview закривається.
Renderer не підтверджує видалення і не визначає permissions — це робить feature.
Локальні файли до upload
createLocalMediaPreviewUrl готує browser preview:
- image отримує зменшене локальне preview;
- video отримує image frame;
- для audio, voice і file helper не створює окремого visual preview.
Feature окремо створює основний локальний source для draft. Вона володіє всіма створеними URL і повинна звільнити їх після видалення draft, завершення upload або демонтування форми.
Loading та error states
- visual media не показується до готовності preview/original;
- video poster не перекриває вже готове video;
- audio/voice/file мають власний unavailable state;
- media error завершує loading state;
- global loader застосовує feature лише для бізнес-операцій, які блокують цілий сценарій.
Правила інтеграції
- Нормалізувати backend record у стабільний
AppMediaItem. - Передати playable/original/download URL у
src. - Передати card або inline preview у
previewSrc. - Вибрати variant за поведінкою, а не лише за розміром.
- Для fullscreen зберігати selected ID/index і передавати всю дозволену колекцію.
- Тримати permissions, upload, delete confirmation, selection і filters у feature.
- Для локальних файлів очищати створені browser URL.
Поточні інтеграції
- E-mail media;
- Hiring Media Gallery;
- hiring workspace і картка кандидата;
- tickets;
- Golden workspace v2 message/mail/e-mail attachments і media pickers;
- operator card documents, passport scans, comments і achievements;
- operator TU views.
Legacy media implementations ще існують. Їх можна мігрувати лише після звірки data contract, permissions і поточного user flow.
Зв’язки
- Hiring library: media-gallery.
- E-mail library: email-media.
- Hiring workspace: operators-applicants-workspace.
- Tickets: tickets.
- Family workspace: workspace.