v3: added playlist moderation permission
All checks were successful
Build and Publish Docker Image / build-and-push (push) Successful in 43s

This commit is contained in:
khannurien
2026-06-28 06:37:23 +00:00
parent 4fb5caa146
commit 551e29c564
8 changed files with 99 additions and 66 deletions

View File

@@ -25,6 +25,7 @@ import {
deserializePlaylistWithDumps,
} from "../model.ts";
import { playlistUrl } from "../utils/urls.ts";
import { can } from "../utils/permissions.ts";
import { useAuth } from "../hooks/useAuth.ts";
import { useWS } from "../hooks/useWS.ts";
import { relativeTime } from "../utils/relativeTime.ts";
@@ -566,6 +567,8 @@ export function PlaylistDetail() {
const { playlist } = state;
const isOwner = !!user && user.id === playlist.userId;
// Owners edit their own playlists; moderators may edit any (playlist:moderate).
const canEdit = isOwner || can(user, "playlist:moderate");
// Active dumps in playlist order; fading dumps appended so they stay visible
const activeDumps = playlist.dumps.filter((d) => activeDumpIds.has(d.id));
@@ -604,7 +607,7 @@ export function PlaylistDetail() {
isPublic={playlist.isPublic}
/>
)}
{isOwner && (
{canEdit && (
<button
type="button"
className="playlist-edit-btn"
@@ -671,7 +674,7 @@ export function PlaylistDetail() {
: (
<div
className="playlist-dump-list"
onDragOver={isOwner ? (e) => e.preventDefault() : undefined}
onDragOver={canEdit ? (e) => e.preventDefault() : undefined}
>
{visibleDumps.map((dump) => {
const isActive = activeDumpIds.has(dump.id);
@@ -692,16 +695,16 @@ export function PlaylistDetail() {
? " playlist-dump-item--drag-over"
: ""
}`}
draggable={isOwner && isActive}
onDragStart={isOwner && isActive
draggable={canEdit && isActive}
onDragStart={canEdit && isActive
? () => handleDragStart(activeIndex)
: undefined}
onDragOver={isOwner && isActive
onDragOver={canEdit && isActive
? (e) => handleDragOver(e, activeIndex)
: undefined}
onDragEnd={isOwner ? handleDragEnd : undefined}
onDragEnd={canEdit ? handleDragEnd : undefined}
>
{isOwner && isActive && (
{canEdit && isActive && (
<span className="drag-handle" aria-hidden></span>
)}
<DumpCard
@@ -714,7 +717,7 @@ export function PlaylistDetail() {
className={cardCls}
isOwner={!!user && user.id === dump.userId}
/>
{isOwner && (isActive
{canEdit && (isActive
? (
<button
type="button"