Compare commits

...

4 Commits

Author SHA1 Message Date
Hördle Bot
56461fe0bb Bump version to 0.1.6.31 2025-12-07 13:17:03 +01:00
Hördle Bot
989654f62e Fix: Waveform-Editor verwendet jetzt API-Route statt statischen Pfad
- WaveformEditor verwendet /api/audio/... statt /uploads/...
- Gleicher Pfad wie beim Abspielen aus der Liste
- Behebt Problem, dass neu hochgeladene Dateien nicht im Waveform-Editor bearbeitbar waren
2025-12-07 13:16:32 +01:00
Hördle Bot
bf9fbe37c0 Bump version to 0.1.6.30 2025-12-07 13:04:23 +01:00
Hördle Bot
c83dc7a5e5 Fix: Cache-Control-Header für Waveform-Editor API-Route hinzugefügt
- API-Route sendet jetzt explizite No-Cache-Header
- Frontend-Fetch verwendet cache: 'no-store'
- Behebt Problem, dass neu hochgeladene Dateien erst nach Container-Neustart bearbeitbar waren
2025-12-07 13:03:43 +01:00
4 changed files with 39 additions and 6 deletions

View File

@@ -1,9 +1,14 @@
import { NextRequest, NextResponse } from 'next/server'; import { NextRequest, NextResponse } from 'next/server';
import { PrismaClient } from '@prisma/client'; import { PrismaClient } from '@prisma/client';
import { requireStaffAuth } from '@/lib/auth'; import { requireStaffAuth } from '@/lib/auth';
import { access } from 'fs/promises';
import path from 'path';
const prisma = new PrismaClient(); const prisma = new PrismaClient();
// Mark route as dynamic to prevent caching
export const dynamic = 'force-dynamic';
export async function GET( export async function GET(
request: NextRequest, request: NextRequest,
{ params }: { params: Promise<{ id: string }> } { params }: { params: Promise<{ id: string }> }
@@ -52,13 +57,40 @@ export async function GET(
return NextResponse.json({ error: 'Special not found' }, { status: 404 }); return NextResponse.json({ error: 'Special not found' }, { status: 404 });
} }
// Filtere Songs ohne vollständige Song-Daten (song, song.filename) // Filtere Songs ohne vollständige Song-Daten und prüfe Datei-Existenz
// Dies verhindert Fehler im Frontend, wenn Songs gelöscht wurden oder Daten fehlen // Dies verhindert Fehler im Frontend, wenn Songs gelöscht wurden, Daten fehlen
const filteredSongs = special.songs.filter(ss => ss.song && ss.song.filename); // oder Dateien noch nicht im Container verfügbar sind (Volume Mount Delay)
const uploadsDir = path.join(process.cwd(), 'public/uploads');
const filteredSongs = await Promise.all(
special.songs
.filter(ss => ss.song && ss.song.filename)
.map(async (ss) => {
const filePath = path.join(uploadsDir, ss.song.filename);
try {
// Prüfe ob Datei existiert und zugänglich ist
await access(filePath);
return ss;
} catch (error) {
// Datei existiert nicht oder ist nicht zugänglich
console.warn(`[API] Song file not available: ${ss.song.filename} (may be syncing)`);
return null;
}
})
);
// Entferne null-Werte (Songs ohne verfügbare Dateien)
const availableSongs = filteredSongs.filter((ss): ss is typeof special.songs[0] => ss !== null);
return NextResponse.json({ return NextResponse.json({
...special, ...special,
songs: filteredSongs, songs: availableSongs,
}, {
headers: {
'Cache-Control': 'no-store, no-cache, must-revalidate, proxy-revalidate',
'Pragma': 'no-cache',
'Expires': '0',
},
}); });
} }

View File

@@ -32,6 +32,7 @@ export default function CuratorSpecialEditorPage() {
} }
const res = await fetch(`/api/curator/specials/${specialId}`, { const res = await fetch(`/api/curator/specials/${specialId}`, {
headers: getCuratorAuthHeaders(), headers: getCuratorAuthHeaders(),
cache: 'no-store',
}); });
if (res.status === 403) { if (res.status === 403) {
setError(t('specialForbidden')); setError(t('specialForbidden'));

View File

@@ -184,7 +184,7 @@ export default function CurateSpecialEditor({
</button> </button>
</div> </div>
<WaveformEditor <WaveformEditor
audioUrl={`/uploads/${selectedSpecialSong.song.filename}`} audioUrl={`/api/audio/${selectedSpecialSong.song.filename}`}
startTime={pendingStartTime ?? selectedSpecialSong.startTime} startTime={pendingStartTime ?? selectedSpecialSong.startTime}
duration={totalDuration} duration={totalDuration}
unlockSteps={unlockSteps} unlockSteps={unlockSteps}

View File

@@ -1,6 +1,6 @@
{ {
"name": "hoerdle", "name": "hoerdle",
"version": "0.1.6.29", "version": "0.1.6.31",
"private": true, "private": true,
"scripts": { "scripts": {
"dev": "next dev", "dev": "next dev",