Enable room queue controls
This commit is contained in:
@@ -3,7 +3,7 @@
|
||||
import { revalidatePath } from "next/cache";
|
||||
import { normalizeMediaUrl } from "./media";
|
||||
import { prisma } from "./prisma";
|
||||
import { requireCurrentUser } from "./session";
|
||||
import { requireCurrentUser, userIsAdmin } from "./session";
|
||||
import { getAppSettings } from "./settings";
|
||||
|
||||
export async function addMediaToRoom(formData: FormData) {
|
||||
@@ -27,6 +27,8 @@ export async function addMediaToRoom(formData: FormData) {
|
||||
const media = normalizeMediaUrl(sourceUrl);
|
||||
if (!settings.allowedProviders.includes(media.provider)) return;
|
||||
|
||||
const nextPosition = await prisma.mediaSource.count({ where: { roomId: room.id } });
|
||||
|
||||
await prisma.mediaSource.create({
|
||||
data: {
|
||||
roomId: room.id,
|
||||
@@ -34,6 +36,8 @@ export async function addMediaToRoom(formData: FormData) {
|
||||
provider: media.provider,
|
||||
originalUrl: media.originalUrl,
|
||||
playbackUrl: media.playbackUrl,
|
||||
thumbnailUrl: media.thumbnailUrl,
|
||||
queuePosition: nextPosition + 1,
|
||||
title: media.originalUrl
|
||||
}
|
||||
});
|
||||
@@ -54,3 +58,149 @@ export async function addMediaToRoom(formData: FormData) {
|
||||
revalidatePath(`/rooms/${encodeURIComponent(room.slug)}`);
|
||||
revalidatePath("/dashboard");
|
||||
}
|
||||
|
||||
export async function removeMediaFromRoom(formData: FormData) {
|
||||
const { room, media } = await requireMediaManager(formData);
|
||||
if (!room || !media) return;
|
||||
|
||||
await prisma.mediaSource.delete({ where: { id: media.id } });
|
||||
await normalizeQueue(room.id);
|
||||
revalidateRoom(room.slug);
|
||||
}
|
||||
|
||||
export async function moveMediaUp(formData: FormData) {
|
||||
await moveMedia(formData, -1);
|
||||
}
|
||||
|
||||
export async function moveMediaDown(formData: FormData) {
|
||||
await moveMedia(formData, 1);
|
||||
}
|
||||
|
||||
export async function setCurrentMedia(formData: FormData) {
|
||||
const user = await requireCurrentUser();
|
||||
const mediaId = String(formData.get("mediaId") || "");
|
||||
if (!mediaId) return;
|
||||
|
||||
const media = await prisma.mediaSource.findUnique({
|
||||
where: { id: mediaId },
|
||||
include: {
|
||||
room: {
|
||||
select: {
|
||||
id: true,
|
||||
slug: true,
|
||||
ownerId: true,
|
||||
visibility: true,
|
||||
members: { where: { userId: user.id }, select: { canManage: true } }
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (!media || !canUseRoom(user.id, media.room, user)) return;
|
||||
|
||||
await prisma.room.update({
|
||||
where: { id: media.roomId },
|
||||
data: {
|
||||
currentState: {
|
||||
provider: media.provider,
|
||||
originalUrl: media.originalUrl,
|
||||
playbackUrl: media.playbackUrl,
|
||||
mediaSourceId: media.id,
|
||||
updatedBy: user.username,
|
||||
updatedAt: Date.now()
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
revalidateRoom(media.room.slug);
|
||||
}
|
||||
|
||||
async function moveMedia(formData: FormData, direction: -1 | 1) {
|
||||
const { room, media } = await requireMediaManager(formData);
|
||||
if (!room || !media) return;
|
||||
|
||||
const queue = await prisma.mediaSource.findMany({
|
||||
where: { roomId: room.id },
|
||||
orderBy: [{ queuePosition: "asc" }, { createdAt: "asc" }, { id: "asc" }],
|
||||
select: { id: true }
|
||||
});
|
||||
const index = queue.findIndex((item) => item.id === media.id);
|
||||
const target = index + direction;
|
||||
if (index < 0 || target < 0 || target >= queue.length) return;
|
||||
|
||||
const reordered = [...queue];
|
||||
[reordered[index], reordered[target]] = [reordered[target], reordered[index]];
|
||||
await prisma.$transaction(
|
||||
reordered.map((item, itemIndex) =>
|
||||
prisma.mediaSource.update({
|
||||
where: { id: item.id },
|
||||
data: { queuePosition: itemIndex + 1 }
|
||||
})
|
||||
)
|
||||
);
|
||||
|
||||
revalidateRoom(room.slug);
|
||||
}
|
||||
|
||||
async function requireMediaManager(formData: FormData) {
|
||||
const user = await requireCurrentUser();
|
||||
const mediaId = String(formData.get("mediaId") || "");
|
||||
if (!mediaId) return { room: null, media: null };
|
||||
|
||||
const media = await prisma.mediaSource.findUnique({
|
||||
where: { id: mediaId },
|
||||
include: {
|
||||
room: {
|
||||
select: {
|
||||
id: true,
|
||||
slug: true,
|
||||
ownerId: true,
|
||||
visibility: true,
|
||||
members: { where: { userId: user.id }, select: { canManage: true } }
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (!media || !canManageRoom(user.id, media.room, user)) return { room: null, media: null };
|
||||
return { room: media.room, media };
|
||||
}
|
||||
|
||||
function canUseRoom(
|
||||
userId: string,
|
||||
room: { ownerId: string | null; visibility: string; members: Array<{ canManage: boolean }> },
|
||||
user?: Awaited<ReturnType<typeof requireCurrentUser>>
|
||||
) {
|
||||
return room.ownerId === userId || Boolean(user && userIsAdmin(user)) || room.visibility === "PUBLIC" || room.members.length > 0;
|
||||
}
|
||||
|
||||
function canManageRoom(
|
||||
userId: string,
|
||||
room: { ownerId: string | null; members: Array<{ canManage: boolean }> },
|
||||
user?: Awaited<ReturnType<typeof requireCurrentUser>>
|
||||
) {
|
||||
return room.ownerId === userId || Boolean(user && userIsAdmin(user)) || room.members.some((member) => member.canManage);
|
||||
}
|
||||
|
||||
async function normalizeQueue(roomId: string) {
|
||||
const queue = await prisma.mediaSource.findMany({
|
||||
where: { roomId },
|
||||
orderBy: [{ queuePosition: "asc" }, { createdAt: "asc" }, { id: "asc" }],
|
||||
select: { id: true }
|
||||
});
|
||||
if (queue.length === 0) return;
|
||||
await prisma.$transaction(
|
||||
queue.map((item, index) =>
|
||||
prisma.mediaSource.update({
|
||||
where: { id: item.id },
|
||||
data: { queuePosition: index + 1 }
|
||||
})
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
function revalidateRoom(slug: string) {
|
||||
revalidatePath(`/rooms/${encodeURIComponent(slug)}`);
|
||||
revalidatePath("/dashboard");
|
||||
revalidatePath("/rooms");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user