Switch to thumbnails and thumbnail creation on the sample grid page until clicked.

This commit is contained in:
Jaret Burkett
2026-07-25 08:40:33 -06:00
parent e00f3791e2
commit efb58c8641
7 changed files with 105 additions and 13 deletions

View File

@@ -45,7 +45,7 @@ export async function GET(request: NextRequest, { params }: { params: { imagePat
// Security check: resolve the path so any `..` segments are collapsed,
// then ensure it's still under an allowed root. (Plain `.includes('..')`
// false-positives on filenames that contain `..` as text, e.g. an ellipsis.)
const resolved = path.resolve(filepath);
let resolved = path.resolve(filepath);
const isAllowed = allowedDirs.some(
allowedDir => resolved === allowedDir || resolved.startsWith(allowedDir + path.sep),
);
@@ -55,6 +55,17 @@ export async function GET(request: NextRequest, { params }: { params: { imagePat
return new NextResponse('Access denied', { status: 403 });
}
// ?thumb=1 serves the pre-generated 300x300 jpg from the sibling .thumbs
// folder (<name>.<ext>.jpg) when it exists; otherwise falls through to
// the full file exactly as before.
if (request.nextUrl.searchParams.has('thumb')) {
const thumbPath = path.join(path.dirname(resolved), '.thumbs', path.basename(resolved) + '.jpg');
const thumbStat = await fs.promises.stat(thumbPath).catch(() => null);
if (thumbStat && thumbStat.isFile()) {
resolved = thumbPath;
}
}
// Bail out early if the client already gave up
if (request.signal.aborted) {
return new NextResponse(null, { status: 499 });

View File

@@ -25,8 +25,12 @@ export async function GET(request: NextRequest, { params }: { params: { jobID: s
return NextResponse.json({ samples: [] });
}
// find all img (png, jpg, jpeg) files in the samples folder
const samples = (await fs.promises.readdir(samplesFolder))
// find all img (png, jpg, jpeg) files in the samples folder. Thumbnails
// live in the hidden .thumbs subfolder (and partial writes in .tmp) — the
// isFile check keeps those directories out even if their names ever match.
const samples = (await fs.promises.readdir(samplesFolder, { withFileTypes: true }))
.filter(entry => entry.isFile())
.map(entry => entry.name)
.filter(file => {
return file.endsWith('.png') || file.endsWith('.jpg') || file.endsWith('.jpeg') || file.endsWith('.webp') || file.endsWith('.mp4') || file.endsWith('mp3') || file.endsWith('wav') || file.endsWith('flac') || file.endsWith('ogg');
})