Add player controls and configurable profiles
All checks were successful
Release Dry Run / release-dry-run (push) Successful in 1m34s
Build / build (push) Successful in 11m47s
Template Compliance / compliance (push) Successful in 5s

This commit is contained in:
MrSphay
2026-05-15 21:36:22 +02:00
parent 9fbd79c7ef
commit 7a5cc2f64b
27 changed files with 592 additions and 56 deletions

47
src/lib/settings.ts Normal file
View File

@@ -0,0 +1,47 @@
import { prisma } from "./prisma";
export type AppSettings = {
instanceName: string;
instanceDescription: string;
registrationMode: "OPEN" | "INVITE_ONLY" | "DISABLED";
defaultRoomVisibility: "PUBLIC" | "FRIENDS" | "EXPLICIT" | "ROLE_RESTRICTED";
allowedProviders: string[];
maxAvatarUploadMb: number;
};
const defaults: AppSettings = {
instanceName: "WatchLink",
instanceDescription: "Persistent shared watch rooms for friends and teams.",
registrationMode: "OPEN",
defaultRoomVisibility: "FRIENDS",
allowedProviders: ["YOUTUBE", "TWITCH", "DIRECT"],
maxAvatarUploadMb: 2
};
export async function getAppSettings(): Promise<AppSettings> {
const rows = await prisma.appSetting.findMany();
const values = new Map(rows.map((row) => [row.key, row.value]));
const registrationMode = parseChoice(values.get("registrationMode"), ["OPEN", "INVITE_ONLY", "DISABLED"], defaults.registrationMode);
const defaultRoomVisibility = parseChoice(
values.get("defaultRoomVisibility"),
["PUBLIC", "FRIENDS", "EXPLICIT", "ROLE_RESTRICTED"],
defaults.defaultRoomVisibility
);
const maxAvatarUploadMb = Number(values.get("maxAvatarUploadMb") || defaults.maxAvatarUploadMb);
return {
instanceName: values.get("instanceName") || defaults.instanceName,
instanceDescription: values.get("instanceDescription") || defaults.instanceDescription,
registrationMode,
defaultRoomVisibility,
allowedProviders: (values.get("allowedProviders") || defaults.allowedProviders.join(","))
.split(",")
.map((item) => item.trim())
.filter(Boolean),
maxAvatarUploadMb: Number.isFinite(maxAvatarUploadMb) && maxAvatarUploadMb > 0 ? maxAvatarUploadMb : defaults.maxAvatarUploadMb
};
}
function parseChoice<T extends string>(value: string | undefined, allowed: T[], fallback: T): T {
return allowed.includes(value as T) ? (value as T) : fallback;
}