From 53a724ae27278c628a428a85cb7dfa98a6db8a2c Mon Sep 17 00:00:00 2001 From: Void Date: Fri, 13 Nov 2026 21:45:00 +0000 Subject: [PATCH 1/2] Files desk cut 1 under Matrix authority: folders by album title path, share into the current folder Albums titled a/b/c group into folders in AlbumView; ShareSet prefixes the current folder onto the album title it sends. No wire change. Co-Authored-By: Claude Sonnet 5.5 --- src/app/features/albums/AlbumView.tsx | 60 +++++++-- src/app/features/albums/ShareSet.tsx | 10 +- src/app/features/albums/albumFolders.test.ts | 129 +++++++++++++++++++ src/app/features/albums/albumFolders.ts | 73 +++++++++++ 4 files changed, 257 insertions(+), 15 deletions(-) create mode 100644 src/app/features/albums/albumFolders.test.ts create mode 100644 src/app/features/albums/albumFolders.ts diff --git a/src/app/features/albums/AlbumView.tsx b/src/app/features/albums/AlbumView.tsx index b670ee2b..20c1e27c 100644 --- a/src/app/features/albums/AlbumView.tsx +++ b/src/app/features/albums/AlbumView.tsx @@ -15,6 +15,7 @@ import { getBlobSafeMimeType } from '../../utils/mimeTypes'; import { timeDayMonYear } from '../../utils/time'; import { getMemberDisplayName } from '../../utils/room'; import { Album, AlbumFile } from './buildAlbums'; +import { folderOf, listFolder, pathLabel } from './albumFolders'; import { FileReadBy } from './FileReadBy'; import { ShareSet, useShareEnabled } from './ShareSet'; import { useAlbums } from './useAlbums'; @@ -91,6 +92,7 @@ export function AlbumView({ room, onTimeline }: AlbumViewProps) { const { loading, error, albums } = useAlbums(room); const [dateFormat] = useSetting(settingsAtom, 'dateFormatString'); const [openId, setOpenId] = useState(); + const [path, setPath] = useState([]); const open: Album | undefined = albums.find((a) => a.id === openId); const authorOf = (a: Album) => getMemberDisplayName(room, a.author) ?? a.author; const encrypted = room.hasEncryptionStateEvent(); @@ -103,8 +105,17 @@ export function AlbumView({ room, onTimeline }: AlbumViewProps) { const images = open.files.length > 0 && open.files.every((f) => f.kind === 'image'); body = ( <> - {open.title} @@ -122,14 +133,41 @@ export function AlbumView({ room, onTimeline }: AlbumViewProps) { body = This zone is encrypted, so its albums cannot be listed here.; else if (albums.length === 0) body = No albums yet.; else { - body = albums.map((a) => ( - - )); + const here = listFolder(albums, path); + body = ( + <> + {path.length > 0 && ( + + )} + {path.length > 0 && {pathLabel(path)}} + {here.folders.map((f) => ( + + ))} + {here.albums.map(({ album: a, leaf }) => ( + + ))} + {here.folders.length === 0 && here.albums.length === 0 && Nothing here.} + + ); } return ( @@ -139,7 +177,7 @@ export function AlbumView({ room, onTimeline }: AlbumViewProps) { {/* Stays mounted while an album is open, so a running send keeps its progress. */} {canShare && ( )}