All checks were successful
Release / Test backend (push) Successful in 51s
Release / Check ui (push) Successful in 47s
Release / Docker / caddy (push) Successful in 38s
Release / Docker / backend (push) Successful in 2m30s
Release / Docker / runner (push) Successful in 2m38s
Release / Docker / ui (push) Successful in 2m1s
Release / Gitea Release (push) Successful in 41s
- Replace ?? with || when reading font_size so 0 falls back to 1.0 (affects GET /api/settings, layout.server.ts, +layout.svelte) - Remove the explicit 'body.fontSize !== 0' exception in PUT /api/settings validation so 0 is now correctly rejected as an invalid font size - Add add_index helper + idx_chapters_idx_slug_number declaration to scripts/pb-init-v3.sh (idempotent UNIQUE INDEX on chapters_idx)
78 lines
2.9 KiB
TypeScript
78 lines
2.9 KiB
TypeScript
import { json, error } from '@sveltejs/kit';
|
|
import type { RequestHandler } from './$types';
|
|
import { getSettings, saveSettings } from '$lib/server/pocketbase';
|
|
import { log } from '$lib/server/logger';
|
|
|
|
/**
|
|
* GET /api/settings
|
|
* Returns the current user's settings (auto_next, voice, speed, theme, locale, fontFamily, fontSize).
|
|
* Returns defaults if no settings record exists yet.
|
|
*/
|
|
export const GET: RequestHandler = async ({ locals }) => {
|
|
try {
|
|
const settings = await getSettings(locals.sessionId, locals.user?.id);
|
|
return json({
|
|
autoNext: settings?.auto_next ?? false,
|
|
voice: settings?.voice ?? 'af_bella',
|
|
speed: settings?.speed ?? 1.0,
|
|
theme: settings?.theme ?? 'amber',
|
|
locale: settings?.locale ?? 'en',
|
|
fontFamily: settings?.font_family ?? 'system',
|
|
fontSize: settings?.font_size || 1.0
|
|
});
|
|
} catch (e) {
|
|
log.error('settings', 'GET failed', { err: String(e) });
|
|
error(500, 'Failed to load settings');
|
|
}
|
|
};
|
|
|
|
/**
|
|
* PUT /api/settings
|
|
* Body: { autoNext: boolean, voice: string, speed: number, theme?: string, locale?: string, fontFamily?: string, fontSize?: number }
|
|
* Saves user preferences.
|
|
*/
|
|
export const PUT: RequestHandler = async ({ request, locals }) => {
|
|
const body = await request.json().catch(() => null);
|
|
|
|
if (
|
|
!body ||
|
|
typeof body.autoNext !== 'boolean' ||
|
|
typeof body.voice !== 'string' ||
|
|
typeof body.speed !== 'number'
|
|
) {
|
|
error(400, 'Invalid body — expected { autoNext, voice, speed }');
|
|
}
|
|
|
|
// theme is optional — if provided (and non-empty) it must be a known value
|
|
const validThemes = ['amber', 'slate', 'rose', 'light', 'light-slate', 'light-rose'];
|
|
if (body.theme !== undefined && body.theme !== '' && !validThemes.includes(body.theme)) {
|
|
error(400, `Invalid theme — must be one of: ${validThemes.join(', ')}`);
|
|
}
|
|
|
|
// locale is optional — if provided (and non-empty) it must be a known value
|
|
const validLocales = ['en', 'ru', 'id', 'pt', 'fr'];
|
|
if (body.locale !== undefined && body.locale !== '' && !validLocales.includes(body.locale)) {
|
|
error(400, `Invalid locale — must be one of: ${validLocales.join(', ')}`);
|
|
}
|
|
|
|
// fontFamily is optional — if provided (and non-empty) it must be a known value
|
|
const validFontFamilies = ['system', 'serif', 'mono'];
|
|
if (body.fontFamily !== undefined && body.fontFamily !== '' && !validFontFamilies.includes(body.fontFamily)) {
|
|
error(400, `Invalid fontFamily — must be one of: ${validFontFamilies.join(', ')}`);
|
|
}
|
|
|
|
// fontSize is optional — if provided it must be one of the valid steps (0 is not valid)
|
|
const validFontSizes = [0.9, 1.0, 1.15, 1.3];
|
|
if (body.fontSize !== undefined && !validFontSizes.includes(body.fontSize)) {
|
|
error(400, `Invalid fontSize — must be one of: ${validFontSizes.join(', ')}`);
|
|
}
|
|
|
|
try {
|
|
await saveSettings(locals.sessionId, body, locals.user?.id);
|
|
} catch (e) {
|
|
log.error('settings', 'PUT failed', { err: String(e) });
|
|
error(500, 'Failed to save settings');
|
|
}
|
|
return json({ ok: true });
|
|
};
|