From 129578cb3a5b1e309ef8acec8cf1a681e7f1e987 Mon Sep 17 00:00:00 2001 From: vibe-bot Date: Fri, 8 Aug 2025 14:05:44 +0200 Subject: [PATCH] =?UTF-8?q?feat(recent):=20Tab=20'Neu'=20(letzte=2010=20Up?= =?UTF-8?q?loads)=20+=20-Badge=20f=C3=BCr=20letzte=205;=20API=20markiert?= =?UTF-8?q?=20isRecent=20via=20mtime?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- server/src/index.ts | 30 +++++++++++++++++++++++++++--- web/src/App.tsx | 17 ++++++++++++++++- web/src/types.ts | 1 + 3 files changed, 44 insertions(+), 4 deletions(-) diff --git a/server/src/index.ts b/server/src/index.ts index 2911839..04f089d 100644 --- a/server/src/index.ts +++ b/server/src/index.ts @@ -248,16 +248,40 @@ app.get('/api/sounds', (req: Request, res: Response) => { } const allItems = [...rootFiles, ...folderItems].sort((a, b) => a.name.localeCompare(b.name)); + + // Zeitstempel für Neu-Logik + type ItemWithTime = { fileName: string; name: string; folder: string; relativePath: string; mtimeMs: number }; + const allWithTime: ItemWithTime[] = [...allItems].map((it) => { + const stat = fs.statSync(path.join(SOUNDS_DIR, it.relativePath)); + return { ...it, mtimeMs: stat.mtimeMs }; + }); + const sortedByNewest = [...allWithTime].sort((a, b) => b.mtimeMs - a.mtimeMs); + const recentTop10 = sortedByNewest.slice(0, 10); + const recentTop5Set = new Set(recentTop10.slice(0, 5).map((x) => x.relativePath)); let itemsByFolder = allItems; if (folderFilter !== '__all__') { - itemsByFolder = allItems.filter((it) => (folderFilter === '' ? it.folder === '' : it.folder === folderFilter)); + if (folderFilter === '__recent__') { + itemsByFolder = recentTop10.map(({ fileName, name, folder, relativePath }) => ({ fileName, name, folder, relativePath })); + } else { + itemsByFolder = allItems.filter((it) => (folderFilter === '' ? it.folder === '' : it.folder === folderFilter)); + } } const filteredItems = itemsByFolder.filter((s) => (q ? s.name.toLowerCase().includes(q) : true)); const total = allItems.length; - const foldersOut = [{ key: '__all__', name: 'Alle', count: total }, ...folders]; + const recentCount = Math.min(10, total); + const foldersOut = [ + { key: '__all__', name: 'Alle', count: total }, + { key: '__recent__', name: 'Neu', count: recentCount }, + ...folders + ]; + // isRecent-Flag für UI (Top 5 der neuesten) + const withRecentFlag = filteredItems.map((it) => ({ + ...it, + isRecent: recentTop5Set.has(it.relativePath ?? it.fileName) + })); - res.json({ items: filteredItems, total, folders: foldersOut }); + res.json({ items: withRecentFlag, total, folders: foldersOut }); }); app.get('/api/channels', (_req: Request, res: Response) => { diff --git a/web/src/App.tsx b/web/src/App.tsx index 149e964..5b4bc3c 100644 --- a/web/src/App.tsx +++ b/web/src/App.tsx @@ -164,6 +164,21 @@ export default function App() { > Favoriten ({favCount}) + {/* Neueste 10 */} + {folders.map((f) => (