Концепції, цінність і типові сценарії
Концепції, цінність і типові сценарії
Preparing Ring content
Preparing Ring content
Preparing Ring content
Використовуйте вкладки Founder / Developer на бічній панелі документації, щоб відфільтрувати цю сторінку. Завантаження проходять через RingFileBase; байти публічної галереї — через Ring CDN /files/{uuid}.
Ring File Cabinet — персональний файловий менеджер для клонів Ring: вкладені папки (максимальна глибина 3), робочий простір для комп’ютера з трьома колонками, ACL owner / trustee (trustee = лише перегляд і завантаження), робочий стіл shared-with-me для кожного subscriber+, приватне упорядкування галереї та lightbox /{username}/img для елементів із visibility=public.
| Поверхня | Хто | Поведінка |
|---|---|---|
/file-cabinet | Auth; member+ | Власний менеджер — FileCabinetWrapper → FileCabinetDesktop. Нечлени бачать MemberUpgradeGate (той самий патерн, що й для add-entity). |
/profile/cabinet | — | Перенаправляє на /file-cabinet (ROUTES.PROFILE_CABINET — псевдонім FILE_CABINET). |
/profile/shared | subscriber+ | Повноцінний drag-and-drop робочий стіл довірених поширень. Користувачі лише з рівнем subscriber також бачать CTA оновлення membersUpgrade → membership із returnTo=/profile/shared. |
/profile/gallery | Auth; member+ | Упорядковування зображень/відео → private | unlisted | public (MemberUpgradeGate для нечленів). |
/{username}/img | Public | Lightbox для елементів із visibility=public. |
/{username}/player | Public | Mood player (перейменовано з /songs; старого редиректу немає). Приватне керування залишається на /profile/songs. |
Права ACL надаються одразу (без прийняття запрошення). Максимальний розмір завантаження — 25MB через getCabinetStorageConfig(). Публікації використовують окрему модель співавторів — це не ACL File Cabinet.
Власний File Cabinet (/file-cabinet) і керування галереєю (/profile/gallery) потребують привілеїв member (hasMemberPrivileges + MemberUpgradeGate). Усі subscriber (і рівні вище) відкривають /profile/shared для довірених поширень — вони не отримують власний робочий стіл або поверхню завантаження, доки не оновляться до member.
Учасникам потрібне місце для документів, сканів і медіа, яке не перетворюється на хаос вкладень у чаті й не є сховищем Admin Wiki. File Cabinet — це персональне сховище з довіреними переглядачами, спільна скринька для співпрацівників і публічне обличчя-галерея — корисно для маркетплейсів, сервісних кілець і будь-якого клону, де довіра включає «покажи свою роботу».
Учасники відкривають /file-cabinet — завантаження, папки, trustees через ContactPicker, розгортане дерево + рейка параметрів. Нечлени потрапляють на гейт оновлення membership.
Кожен subscriber+ використовує /profile/shared для довірених поширень (робочий стіл перегляду/завантаження). CTA оновлення в рейці веде до membership для отримання власного менеджера.
Залежність: завантаження кабінету проходять через file() / RingBaseAdapter і getCabinetStorageConfig.
Залежність: елементи публічної галереї використовують стабільний CDN /files/{uuid} (+ похідні _v_*).
Наступний крок: публічні поверхні /img, /player і /games розташовані під /{username}.
Див. також: публічна доступність /games — споріднена поверхня профілю (не ACL File Cabinet).
Використовуйте вкладки Founder / Developer на бічній панелі документації, щоб відфільтрувати цю сторінку. Завантаження проходять через RingFileBase; байти публічної галереї — через Ring CDN /files/{uuid}.
Ring File Cabinet — персональний файловий менеджер для клонів Ring: вкладені папки (максимальна глибина 3), робочий простір для комп’ютера з трьома колонками, ACL owner / trustee (trustee = лише перегляд і завантаження), робочий стіл shared-with-me для кожного subscriber+, приватне упорядкування галереї та lightbox /{username}/img для елементів із visibility=public.
| Поверхня | Хто | Поведінка |
|---|---|---|
/file-cabinet | Auth; member+ | Власний менеджер — FileCabinetWrapper → FileCabinetDesktop. Нечлени бачать MemberUpgradeGate (той самий патерн, що й для add-entity). |
/profile/cabinet | — | Перенаправляє на /file-cabinet (ROUTES.PROFILE_CABINET — псевдонім FILE_CABINET). |
/profile/shared | subscriber+ | Повноцінний drag-and-drop робочий стіл довірених поширень. Користувачі лише з рівнем subscriber також бачать CTA оновлення membersUpgrade → membership із returnTo=/profile/shared. |
/profile/gallery | Auth; member+ | Упорядковування зображень/відео → private | unlisted | public (MemberUpgradeGate для нечленів). |
/{username}/img | Public | Lightbox для елементів із visibility=public. |
/{username}/player | Public | Mood player (перейменовано з /songs; старого редиректу немає). Приватне керування залишається на /profile/songs. |
Права ACL надаються одразу (без прийняття запрошення). Максимальний розмір завантаження — 25MB через getCabinetStorageConfig(). Публікації використовують окрему модель співавторів — це не ACL File Cabinet.
Власний File Cabinet (/file-cabinet) і керування галереєю (/profile/gallery) потребують привілеїв member (hasMemberPrivileges + MemberUpgradeGate). Усі subscriber (і рівні вище) відкривають /profile/shared для довірених поширень — вони не отримують власний робочий стіл або поверхню завантаження, доки не оновляться до member.
Учасникам потрібне місце для документів, сканів і медіа, яке не перетворюється на хаос вкладень у чаті й не є сховищем Admin Wiki. File Cabinet — це персональне сховище з довіреними переглядачами, спільна скринька для співпрацівників і публічне обличчя-галерея — корисно для маркетплейсів, сервісних кілець і будь-якого клону, де довіра включає «покажи свою роботу».
Учасники відкривають /file-cabinet — завантаження, папки, trustees через ContactPicker, розгортане дерево + рейка параметрів. Нечлени потрапляють на гейт оновлення membership.
Кожен subscriber+ використовує /profile/shared для довірених поширень (робочий стіл перегляду/завантаження). CTA оновлення в рейці веде до membership для отримання власного менеджера.
Залежність: завантаження кабінету проходять через file() / RingBaseAdapter і getCabinetStorageConfig.
Залежність: елементи публічної галереї використовують стабільний CDN /files/{uuid} (+ похідні _v_*).
Наступний крок: публічні поверхні /img, /player і /games розташовані під /{username}.
Див. також: публічна доступність /games — споріднена поверхня профілю (не ACL File Cabinet).
Використовуйте вкладки Founder / Developer на бічній панелі документації, щоб відфільтрувати цю сторінку. Завантаження проходять через RingFileBase; байти публічної галереї — через Ring CDN /files/{uuid}.
Ring File Cabinet — персональний файловий менеджер для клонів Ring: вкладені папки (максимальна глибина 3), робочий простір для комп’ютера з трьома колонками, ACL owner / trustee (trustee = лише перегляд і завантаження), робочий стіл shared-with-me для кожного subscriber+, приватне упорядкування галереї та lightbox /{username}/img для елементів із visibility=public.
| Поверхня | Хто | Поведінка |
|---|---|---|
/file-cabinet | Auth; member+ | Власний менеджер — FileCabinetWrapper → FileCabinetDesktop. Нечлени бачать MemberUpgradeGate (той самий патерн, що й для add-entity). |
/profile/cabinet | — | Перенаправляє на /file-cabinet (ROUTES.PROFILE_CABINET — псевдонім FILE_CABINET). |
/profile/shared | subscriber+ | Повноцінний drag-and-drop робочий стіл довірених поширень. Користувачі лише з рівнем subscriber також бачать CTA оновлення membersUpgrade → membership із returnTo=/profile/shared. |
/profile/gallery | Auth; member+ | Упорядковування зображень/відео → private | unlisted | public (MemberUpgradeGate для нечленів). |
/{username}/img | Public | Lightbox для елементів із visibility=public. |
/{username}/player | Public | Mood player (перейменовано з /songs; старого редиректу немає). Приватне керування залишається на /profile/songs. |
Права ACL надаються одразу (без прийняття запрошення). Максимальний розмір завантаження — 25MB через getCabinetStorageConfig(). Публікації використовують окрему модель співавторів — це не ACL File Cabinet.
Власний File Cabinet (/file-cabinet) і керування галереєю (/profile/gallery) потребують привілеїв member (hasMemberPrivileges + MemberUpgradeGate). Усі subscriber (і рівні вище) відкривають /profile/shared для довірених поширень — вони не отримують власний робочий стіл або поверхню завантаження, доки не оновляться до member.
Учасникам потрібне місце для документів, сканів і медіа, яке не перетворюється на хаос вкладень у чаті й не є сховищем Admin Wiki. File Cabinet — це персональне сховище з довіреними переглядачами, спільна скринька для співпрацівників і публічне обличчя-галерея — корисно для маркетплейсів, сервісних кілець і будь-якого клону, де довіра включає «покажи свою роботу».
Учасники відкривають /file-cabinet — завантаження, папки, trustees через ContactPicker, розгортане дерево + рейка параметрів. Нечлени потрапляють на гейт оновлення membership.
Кожен subscriber+ використовує /profile/shared для довірених поширень (робочий стіл перегляду/завантаження). CTA оновлення в рейці веде до membership для отримання власного менеджера.
Залежність: завантаження кабінету проходять через file() / RingBaseAdapter і getCabinetStorageConfig.
Залежність: елементи публічної галереї використовують стабільний CDN /files/{uuid} (+ похідні _v_*).
Наступний крок: публічні поверхні /img, /player і /games розташовані під /{username}.
Див. також: публічна доступність /games — споріднена поверхня профілю (не ACL File Cabinet).
Упорядковуйте на /profile/gallery (member+); публічні елементи з’являються на /{username}/img через URL CDN.
/file-cabinet; ділиться папкою з trustee (лише перегляд/завантаження, права надаються одразу).research-{runId}.md і зображення з цитатами в store/[storename]/[product-slug]/alt (глибина ≤3). Продавці відкривають ці зображення на панелі деталей → Image chat / Video chat, щоб покращити або оживити їх, а потім зберігають сусідній файл поруч із джерелом./profile/shared, упорядковує довірені файли на своєму робочому столі й завантажує їх — без власного кабінету.public → відвідувачі відкривають /{username}/img.FsModal показує живий рядок Trustees (або «конфіденційно») і Make confidential, щоб відкликати всіх trustee.042_file_cabinet.sql (таблиці file_cabinet_*) і образ застосунку містить UI File Cabinet.NEXT_PUBLIC_STORAGE_PROVIDER=ring_filebase (або еквівалент), RINGBASE_API_URL, RINGBASE_PUBLIC_URL, RINGBASE_API_TOKEN — див. RingFileBase./file-cabinet → Share trustees → другий користувач (subscriber+) бачить елемент на /profile/shared./file-cabinet показує гейт оновлення; /profile/shared далі працює для спільних файлів; рейка показує «Members get their own file manager».public → відкрийте /{username}/img./files/{fileId}.Actions (listOwnCabinetAction, upload, own desktop) |
requireMember() |
Actions (listSharedCabinetAction, shared desktop) | requireSubscriber(); scope: 'own' усе одно потребує member |
FileCabinetWrapper — тонка клієнтська межа (components/wrappers/file-cabinet-wrapper.tsx), яка рендерить FileCabinetDesktop. Оболонка з трьома колонками (RingRightRailLayout + центральна панель Davinci) живе всередині компонента desktop.
| Частина | Роль |
|---|---|
| Центральна панель | Хлібні крихти + New folder / Upload (праворуч) + робочий простір іконок (без картки desktop з рамкою) |
| Права рейка | Заголовок → розгортане дерево лише папок → параметри (DavinciGlassPanel, title = видиме ім’я файлу) → інформаційна панель без прокручування |
| Дерево | Розгортання +/−; вибраний каталог використовує повністю заокруглену (rounded-[99px]) активну поверхню; стан розгортання у treeExpandedIds документа desktop |
| Іконки desktop | SSOT видимого імені у icons[].meta.filename (перейменування перезаписує; історії немає); іконки зображень використовують sync_thumb через download ?variant= |
| Порожня папка | Контрол видалення лише коли папка не має дочірніх елементів |
| Trustees | Рядок параметрів + Share FsModal (живі Trustees / конфіденційно, вбудований ContactPicker, Make confidential під час очищення trustee) |
| Завантаження | Skeleton фіксованої висоти для рядка trustees, метаданих і прев’ю зображення (без стрибка макета) |
| Оновлення shared | Лише subscriber + scope === 'shared' → CTA t('membersUpgrade') → /membership?returnTo=/profile/shared |
| Image / Video chat | Панель деталей (file-cabinet-detail-panel.tsx) на файлах зображень → GenerativeMediaEditorFsModal (scope="cabinet") |
| Збереження поруч | saveGeneratedMediaToDesktopAction під parentId джерела як {base}-enhanced-{ts}.{ext} або {base}-enlive-{ts}.{ext} |
Коли продавці запускають Research для товару, features/store/lib/product-cabinet-media.ts забезпечує три вкладені каталоги в кабінеті власника-продавця (концептуальний корінь files/ + MAX_FOLDER_DEPTH = 3):
store/[storename]/[product-slug]/alt
Артефакти: research-{runId}.md плюс завантажені зображення research-{runId}-N.{ext} (SSRF-перевірка HTTP(S) fetch → RingBase → createFileNode). Увімкнення галереї storefront залишається у формі товару (Use in gallery) — див. Multi-Vendor Store. Pipeline: cabinet.genmedia.sibling_save у scripts/PIPELINES.md.
| Шлях | Роль |
|---|---|
features/file-cabinet/service.ts | server-only CRUD, ACL (включно з обходом предків для успадкованих trustee), desktop, gallery |
features/file-cabinet/acl.ts | owner | trustee (legacy editor → trustee) |
features/file-cabinet/constants.ts | FILE_CABINET_DESKTOP_CHANNEL, FILE_CABINET_DOWNLOAD_PATH, MAX_FOLDER_DEPTH = 3 |
features/file-cabinet/desktop-filename.ts | Допоміжні засоби видимого імені файлу |
features/file-cabinet/media-urls.ts | Допоміжні засоби same-origin URL завантаження (?variant=) |
features/file-cabinet/components/* | Desktop, дерево, параметри, деталі (Image/Video chat), FsModal поширення/перейменування, skeleton, gallery, public img |
app/_actions/file-cabinet.ts | Server Actions + рольові гейти + saveGeneratedMediaToDesktopAction |
features/store/lib/product-cabinet-media.ts | Store research → writer store/…/alt (SSRF-safe) |
app/api/file-cabinet/download/route.ts | Перевірка ACL → потік байтів (inline=1, необов’язковий variant= для thumb/webp) |
lib/storage/storage-config.ts | getCabinetStorageConfig() — 25MB + allowlist MIME |
components/file-tree/tree-helpers.ts | Спільні помічники дерева (адаптери Admin Wiki) |
data/migrations/042_file_cabinet.sql | Схема (+ дзеркало в data/schema.sql) |
| Роль | Можливості |
|---|---|
owner | Повний CRUD, встановлення trustee через ContactPicker (setCabinetTrusteesAction) |
trustee | Перегляд / список / завантаження; макет shared desktop; не може змінювати або завантажувати |
Права одразу записуються в file_cabinet_acl — потоку прийняття запрошення немає. Під час переліку ACL для рейки параметрів виконується обхід предків, тому поширення папки відображаються і на вкладених файлах.
Таблиці (id + data JSONB): file_cabinet_nodes, file_cabinet_acl, file_cabinet_desktop, file_cabinet_gallery_items.
Документ desktop зберігає позиції іконок і treeExpandedIds для дерева папок лише з розгортанням/згортанням. Кеш макета для кожної папки зберігає позиції після перетягування під час переходу вкладеними папками.
Передавайте id документа як createDoc(collection, data, { id }). Якщо покласти id лише всередину data, PostgreSQLAdapter може розійтися з data.id, згенерувавши інший generateId().
Завантаження в кабінет використовують file().upload(...) з access: 'private', derivativesProfile: 'gallery' для зображень і перевірками MIME/розміру з getCabinetStorageConfig() (зображення, PDF, Office, text/csv/md, zip, а також video/mp4 / video/webm).
Публічні елементи галереї зберігають CDN URL із завантаження (storageUrl). У поточному шляху RingBaseAdapter немає підписаних URL HMAC/TTL — доставка має вигляд {RINGBASE_PUBLIC_URL}/files/{fileId} (+ похідні _v_*). Приватні завантаження використовують ACL-проксі (/api/file-cabinet/download) із Content-Disposition з node.name / desktop meta.filename. У прямому CDN /files/{uuid} досі немає Content-Disposition — див. backlog.
saveDesktop публікує дані в персональний tunnel учасника:
Клієнт слухає через useTunnelChannel у file-cabinet-desktop.tsx.
Переконайтеся, що 042_file_cabinet.sql (і паритет schema.sql) застосовано до БД клону. Нові інсталяції отримують таблиці з data/schema.sql.
Зверніться до RingFileBase: NEXT_PUBLIC_STORAGE_PROVIDER=ring_filebase, RINGBASE_API_URL, RINGBASE_PUBLIC_URL, RINGBASE_API_TOKEN.
Віддавайте перевагу app/_actions/file-cabinet.ts із клієнтського UI — не обходьте ACL-помічники в service.ts. Власний список/завантаження потребує member; shared desktop потребує subscriber+; getDesktop / saveDesktop для scope: 'own' також потребують привілеїв member.
app/[locale]/[username]/img/page.tsx завантажує listPublicGalleryByOwner(ownerId) і рендерить PublicProfileImgGallery. Відображаються лише елементи з visibility=public.
| Константа | Шлях |
|---|---|
ROUTES.FILE_CABINET | /file-cabinet (канонічний власний менеджер) |
ROUTES.PROFILE_CABINET | /file-cabinet (застарілий псевдонім; /profile/cabinet перенаправляє) |
ROUTES.PROFILE_SHARED | /profile/shared |
ROUTES.PROFILE_GALLERY | /profile/gallery |
ROUTES.PUBLIC_PROFILE_IMG(username) | /{username}/img |
ROUTES.PUBLIC_PROFILE_PLAYER(username) | /{username}/player |
Керування приватним mood-player залишається на /profile/songs (ROUTES.PROFILE_SONGS). Peer /games — споріднена поверхня public profile, а не сховище File Cabinet.
Той самий процес: member gate для /file-cabinet проти shared desktop для subscriber+.
Упорядковуйте на /profile/gallery (member+); публічні елементи з’являються на /{username}/img через URL CDN.
/file-cabinet; ділиться папкою з trustee (лише перегляд/завантаження, права надаються одразу).research-{runId}.md і зображення з цитатами в store/[storename]/[product-slug]/alt (глибина ≤3). Продавці відкривають ці зображення на панелі деталей → Image chat / Video chat, щоб покращити або оживити їх, а потім зберігають сусідній файл поруч із джерелом./profile/shared, упорядковує довірені файли на своєму робочому столі й завантажує їх — без власного кабінету.public → відвідувачі відкривають /{username}/img.FsModal показує живий рядок Trustees (або «конфіденційно») і Make confidential, щоб відкликати всіх trustee.042_file_cabinet.sql (таблиці file_cabinet_*) і образ застосунку містить UI File Cabinet.NEXT_PUBLIC_STORAGE_PROVIDER=ring_filebase (або еквівалент), RINGBASE_API_URL, RINGBASE_PUBLIC_URL, RINGBASE_API_TOKEN — див. RingFileBase./file-cabinet → Share trustees → другий користувач (subscriber+) бачить елемент на /profile/shared./file-cabinet показує гейт оновлення; /profile/shared далі працює для спільних файлів; рейка показує «Members get their own file manager».public → відкрийте /{username}/img./files/{fileId}.Actions (listOwnCabinetAction, upload, own desktop) |
requireMember() |
Actions (listSharedCabinetAction, shared desktop) | requireSubscriber(); scope: 'own' усе одно потребує member |
FileCabinetWrapper — тонка клієнтська межа (components/wrappers/file-cabinet-wrapper.tsx), яка рендерить FileCabinetDesktop. Оболонка з трьома колонками (RingRightRailLayout + центральна панель Davinci) живе всередині компонента desktop.
| Частина | Роль |
|---|---|
| Центральна панель | Хлібні крихти + New folder / Upload (праворуч) + робочий простір іконок (без картки desktop з рамкою) |
| Права рейка | Заголовок → розгортане дерево лише папок → параметри (DavinciGlassPanel, title = видиме ім’я файлу) → інформаційна панель без прокручування |
| Дерево | Розгортання +/−; вибраний каталог використовує повністю заокруглену (rounded-[99px]) активну поверхню; стан розгортання у treeExpandedIds документа desktop |
| Іконки desktop | SSOT видимого імені у icons[].meta.filename (перейменування перезаписує; історії немає); іконки зображень використовують sync_thumb через download ?variant= |
| Порожня папка | Контрол видалення лише коли папка не має дочірніх елементів |
| Trustees | Рядок параметрів + Share FsModal (живі Trustees / конфіденційно, вбудований ContactPicker, Make confidential під час очищення trustee) |
| Завантаження | Skeleton фіксованої висоти для рядка trustees, метаданих і прев’ю зображення (без стрибка макета) |
| Оновлення shared | Лише subscriber + scope === 'shared' → CTA t('membersUpgrade') → /membership?returnTo=/profile/shared |
| Image / Video chat | Панель деталей (file-cabinet-detail-panel.tsx) на файлах зображень → GenerativeMediaEditorFsModal (scope="cabinet") |
| Збереження поруч | saveGeneratedMediaToDesktopAction під parentId джерела як {base}-enhanced-{ts}.{ext} або {base}-enlive-{ts}.{ext} |
Коли продавці запускають Research для товару, features/store/lib/product-cabinet-media.ts забезпечує три вкладені каталоги в кабінеті власника-продавця (концептуальний корінь files/ + MAX_FOLDER_DEPTH = 3):
store/[storename]/[product-slug]/alt
Артефакти: research-{runId}.md плюс завантажені зображення research-{runId}-N.{ext} (SSRF-перевірка HTTP(S) fetch → RingBase → createFileNode). Увімкнення галереї storefront залишається у формі товару (Use in gallery) — див. Multi-Vendor Store. Pipeline: cabinet.genmedia.sibling_save у scripts/PIPELINES.md.
| Шлях | Роль |
|---|---|
features/file-cabinet/service.ts | server-only CRUD, ACL (включно з обходом предків для успадкованих trustee), desktop, gallery |
features/file-cabinet/acl.ts | owner | trustee (legacy editor → trustee) |
features/file-cabinet/constants.ts | FILE_CABINET_DESKTOP_CHANNEL, FILE_CABINET_DOWNLOAD_PATH, MAX_FOLDER_DEPTH = 3 |
features/file-cabinet/desktop-filename.ts | Допоміжні засоби видимого імені файлу |
features/file-cabinet/media-urls.ts | Допоміжні засоби same-origin URL завантаження (?variant=) |
features/file-cabinet/components/* | Desktop, дерево, параметри, деталі (Image/Video chat), FsModal поширення/перейменування, skeleton, gallery, public img |
app/_actions/file-cabinet.ts | Server Actions + рольові гейти + saveGeneratedMediaToDesktopAction |
features/store/lib/product-cabinet-media.ts | Store research → writer store/…/alt (SSRF-safe) |
app/api/file-cabinet/download/route.ts | Перевірка ACL → потік байтів (inline=1, необов’язковий variant= для thumb/webp) |
lib/storage/storage-config.ts | getCabinetStorageConfig() — 25MB + allowlist MIME |
components/file-tree/tree-helpers.ts | Спільні помічники дерева (адаптери Admin Wiki) |
data/migrations/042_file_cabinet.sql | Схема (+ дзеркало в data/schema.sql) |
| Роль | Можливості |
|---|---|
owner | Повний CRUD, встановлення trustee через ContactPicker (setCabinetTrusteesAction) |
trustee | Перегляд / список / завантаження; макет shared desktop; не може змінювати або завантажувати |
Права одразу записуються в file_cabinet_acl — потоку прийняття запрошення немає. Під час переліку ACL для рейки параметрів виконується обхід предків, тому поширення папки відображаються і на вкладених файлах.
Таблиці (id + data JSONB): file_cabinet_nodes, file_cabinet_acl, file_cabinet_desktop, file_cabinet_gallery_items.
Документ desktop зберігає позиції іконок і treeExpandedIds для дерева папок лише з розгортанням/згортанням. Кеш макета для кожної папки зберігає позиції після перетягування під час переходу вкладеними папками.
Передавайте id документа як createDoc(collection, data, { id }). Якщо покласти id лише всередину data, PostgreSQLAdapter може розійтися з data.id, згенерувавши інший generateId().
Завантаження в кабінет використовують file().upload(...) з access: 'private', derivativesProfile: 'gallery' для зображень і перевірками MIME/розміру з getCabinetStorageConfig() (зображення, PDF, Office, text/csv/md, zip, а також video/mp4 / video/webm).
Публічні елементи галереї зберігають CDN URL із завантаження (storageUrl). У поточному шляху RingBaseAdapter немає підписаних URL HMAC/TTL — доставка має вигляд {RINGBASE_PUBLIC_URL}/files/{fileId} (+ похідні _v_*). Приватні завантаження використовують ACL-проксі (/api/file-cabinet/download) із Content-Disposition з node.name / desktop meta.filename. У прямому CDN /files/{uuid} досі немає Content-Disposition — див. backlog.
saveDesktop публікує дані в персональний tunnel учасника:
Клієнт слухає через useTunnelChannel у file-cabinet-desktop.tsx.
Переконайтеся, що 042_file_cabinet.sql (і паритет schema.sql) застосовано до БД клону. Нові інсталяції отримують таблиці з data/schema.sql.
Зверніться до RingFileBase: NEXT_PUBLIC_STORAGE_PROVIDER=ring_filebase, RINGBASE_API_URL, RINGBASE_PUBLIC_URL, RINGBASE_API_TOKEN.
Віддавайте перевагу app/_actions/file-cabinet.ts із клієнтського UI — не обходьте ACL-помічники в service.ts. Власний список/завантаження потребує member; shared desktop потребує subscriber+; getDesktop / saveDesktop для scope: 'own' також потребують привілеїв member.
app/[locale]/[username]/img/page.tsx завантажує listPublicGalleryByOwner(ownerId) і рендерить PublicProfileImgGallery. Відображаються лише елементи з visibility=public.
| Константа | Шлях |
|---|---|
ROUTES.FILE_CABINET | /file-cabinet (канонічний власний менеджер) |
ROUTES.PROFILE_CABINET | /file-cabinet (застарілий псевдонім; /profile/cabinet перенаправляє) |
ROUTES.PROFILE_SHARED | /profile/shared |
ROUTES.PROFILE_GALLERY | /profile/gallery |
ROUTES.PUBLIC_PROFILE_IMG(username) | /{username}/img |
ROUTES.PUBLIC_PROFILE_PLAYER(username) | /{username}/player |
Керування приватним mood-player залишається на /profile/songs (ROUTES.PROFILE_SONGS). Peer /games — споріднена поверхня public profile, а не сховище File Cabinet.
Той самий процес: member gate для /file-cabinet проти shared desktop для subscriber+.
Упорядковуйте на /profile/gallery (member+); публічні елементи з’являються на /{username}/img через URL CDN.
/file-cabinet; ділиться папкою з trustee (лише перегляд/завантаження, права надаються одразу).research-{runId}.md і зображення з цитатами в store/[storename]/[product-slug]/alt (глибина ≤3). Продавці відкривають ці зображення на панелі деталей → Image chat / Video chat, щоб покращити або оживити їх, а потім зберігають сусідній файл поруч із джерелом./profile/shared, упорядковує довірені файли на своєму робочому столі й завантажує їх — без власного кабінету.public → відвідувачі відкривають /{username}/img.FsModal показує живий рядок Trustees (або «конфіденційно») і Make confidential, щоб відкликати всіх trustee.042_file_cabinet.sql (таблиці file_cabinet_*) і образ застосунку містить UI File Cabinet.NEXT_PUBLIC_STORAGE_PROVIDER=ring_filebase (або еквівалент), RINGBASE_API_URL, RINGBASE_PUBLIC_URL, RINGBASE_API_TOKEN — див. RingFileBase./file-cabinet → Share trustees → другий користувач (subscriber+) бачить елемент на /profile/shared./file-cabinet показує гейт оновлення; /profile/shared далі працює для спільних файлів; рейка показує «Members get their own file manager».public → відкрийте /{username}/img./files/{fileId}.Actions (listOwnCabinetAction, upload, own desktop) |
requireMember() |
Actions (listSharedCabinetAction, shared desktop) | requireSubscriber(); scope: 'own' усе одно потребує member |
FileCabinetWrapper — тонка клієнтська межа (components/wrappers/file-cabinet-wrapper.tsx), яка рендерить FileCabinetDesktop. Оболонка з трьома колонками (RingRightRailLayout + центральна панель Davinci) живе всередині компонента desktop.
| Частина | Роль |
|---|---|
| Центральна панель | Хлібні крихти + New folder / Upload (праворуч) + робочий простір іконок (без картки desktop з рамкою) |
| Права рейка | Заголовок → розгортане дерево лише папок → параметри (DavinciGlassPanel, title = видиме ім’я файлу) → інформаційна панель без прокручування |
| Дерево | Розгортання +/−; вибраний каталог використовує повністю заокруглену (rounded-[99px]) активну поверхню; стан розгортання у treeExpandedIds документа desktop |
| Іконки desktop | SSOT видимого імені у icons[].meta.filename (перейменування перезаписує; історії немає); іконки зображень використовують sync_thumb через download ?variant= |
| Порожня папка | Контрол видалення лише коли папка не має дочірніх елементів |
| Trustees | Рядок параметрів + Share FsModal (живі Trustees / конфіденційно, вбудований ContactPicker, Make confidential під час очищення trustee) |
| Завантаження | Skeleton фіксованої висоти для рядка trustees, метаданих і прев’ю зображення (без стрибка макета) |
| Оновлення shared | Лише subscriber + scope === 'shared' → CTA t('membersUpgrade') → /membership?returnTo=/profile/shared |
| Image / Video chat | Панель деталей (file-cabinet-detail-panel.tsx) на файлах зображень → GenerativeMediaEditorFsModal (scope="cabinet") |
| Збереження поруч | saveGeneratedMediaToDesktopAction під parentId джерела як {base}-enhanced-{ts}.{ext} або {base}-enlive-{ts}.{ext} |
Коли продавці запускають Research для товару, features/store/lib/product-cabinet-media.ts забезпечує три вкладені каталоги в кабінеті власника-продавця (концептуальний корінь files/ + MAX_FOLDER_DEPTH = 3):
store/[storename]/[product-slug]/alt
Артефакти: research-{runId}.md плюс завантажені зображення research-{runId}-N.{ext} (SSRF-перевірка HTTP(S) fetch → RingBase → createFileNode). Увімкнення галереї storefront залишається у формі товару (Use in gallery) — див. Multi-Vendor Store. Pipeline: cabinet.genmedia.sibling_save у scripts/PIPELINES.md.
| Шлях | Роль |
|---|---|
features/file-cabinet/service.ts | server-only CRUD, ACL (включно з обходом предків для успадкованих trustee), desktop, gallery |
features/file-cabinet/acl.ts | owner | trustee (legacy editor → trustee) |
features/file-cabinet/constants.ts | FILE_CABINET_DESKTOP_CHANNEL, FILE_CABINET_DOWNLOAD_PATH, MAX_FOLDER_DEPTH = 3 |
features/file-cabinet/desktop-filename.ts | Допоміжні засоби видимого імені файлу |
features/file-cabinet/media-urls.ts | Допоміжні засоби same-origin URL завантаження (?variant=) |
features/file-cabinet/components/* | Desktop, дерево, параметри, деталі (Image/Video chat), FsModal поширення/перейменування, skeleton, gallery, public img |
app/_actions/file-cabinet.ts | Server Actions + рольові гейти + saveGeneratedMediaToDesktopAction |
features/store/lib/product-cabinet-media.ts | Store research → writer store/…/alt (SSRF-safe) |
app/api/file-cabinet/download/route.ts | Перевірка ACL → потік байтів (inline=1, необов’язковий variant= для thumb/webp) |
lib/storage/storage-config.ts | getCabinetStorageConfig() — 25MB + allowlist MIME |
components/file-tree/tree-helpers.ts | Спільні помічники дерева (адаптери Admin Wiki) |
data/migrations/042_file_cabinet.sql | Схема (+ дзеркало в data/schema.sql) |
| Роль | Можливості |
|---|---|
owner | Повний CRUD, встановлення trustee через ContactPicker (setCabinetTrusteesAction) |
trustee | Перегляд / список / завантаження; макет shared desktop; не може змінювати або завантажувати |
Права одразу записуються в file_cabinet_acl — потоку прийняття запрошення немає. Під час переліку ACL для рейки параметрів виконується обхід предків, тому поширення папки відображаються і на вкладених файлах.
Таблиці (id + data JSONB): file_cabinet_nodes, file_cabinet_acl, file_cabinet_desktop, file_cabinet_gallery_items.
Документ desktop зберігає позиції іконок і treeExpandedIds для дерева папок лише з розгортанням/згортанням. Кеш макета для кожної папки зберігає позиції після перетягування під час переходу вкладеними папками.
Передавайте id документа як createDoc(collection, data, { id }). Якщо покласти id лише всередину data, PostgreSQLAdapter може розійтися з data.id, згенерувавши інший generateId().
Завантаження в кабінет використовують file().upload(...) з access: 'private', derivativesProfile: 'gallery' для зображень і перевірками MIME/розміру з getCabinetStorageConfig() (зображення, PDF, Office, text/csv/md, zip, а також video/mp4 / video/webm).
Публічні елементи галереї зберігають CDN URL із завантаження (storageUrl). У поточному шляху RingBaseAdapter немає підписаних URL HMAC/TTL — доставка має вигляд {RINGBASE_PUBLIC_URL}/files/{fileId} (+ похідні _v_*). Приватні завантаження використовують ACL-проксі (/api/file-cabinet/download) із Content-Disposition з node.name / desktop meta.filename. У прямому CDN /files/{uuid} досі немає Content-Disposition — див. backlog.
saveDesktop публікує дані в персональний tunnel учасника:
Клієнт слухає через useTunnelChannel у file-cabinet-desktop.tsx.
Переконайтеся, що 042_file_cabinet.sql (і паритет schema.sql) застосовано до БД клону. Нові інсталяції отримують таблиці з data/schema.sql.
Зверніться до RingFileBase: NEXT_PUBLIC_STORAGE_PROVIDER=ring_filebase, RINGBASE_API_URL, RINGBASE_PUBLIC_URL, RINGBASE_API_TOKEN.
Віддавайте перевагу app/_actions/file-cabinet.ts із клієнтського UI — не обходьте ACL-помічники в service.ts. Власний список/завантаження потребує member; shared desktop потребує subscriber+; getDesktop / saveDesktop для scope: 'own' також потребують привілеїв member.
app/[locale]/[username]/img/page.tsx завантажує listPublicGalleryByOwner(ownerId) і рендерить PublicProfileImgGallery. Відображаються лише елементи з visibility=public.
| Константа | Шлях |
|---|---|
ROUTES.FILE_CABINET | /file-cabinet (канонічний власний менеджер) |
ROUTES.PROFILE_CABINET | /file-cabinet (застарілий псевдонім; /profile/cabinet перенаправляє) |
ROUTES.PROFILE_SHARED | /profile/shared |
ROUTES.PROFILE_GALLERY | /profile/gallery |
ROUTES.PUBLIC_PROFILE_IMG(username) | /{username}/img |
ROUTES.PUBLIC_PROFILE_PLAYER(username) | /{username}/player |
Керування приватним mood-player залишається на /profile/songs (ROUTES.PROFILE_SONGS). Peer /games — споріднена поверхня public profile, а не сховище File Cabinet.
Той самий процес: member gate для /file-cabinet проти shared desktop для subscriber+.