feat: implement comment tagging system with CRUD operations

- Removed Telegram setup instructions from settings page.
- Enhanced video and version comment APIs to include tag information.
- Added new CommentTag model in Prisma schema for managing tags.
- Created API routes for managing tags (GET, POST, PATCH, DELETE).
- Updated WatchPage to support tag selection and display.
- Introduced keyboard shortcuts modal for improved user experience.
- Added tag selection dropdown in comment input area.
This commit is contained in:
Yusuf İpek
2026-02-07 14:46:17 +03:00
parent 88dcf9514c
commit 5856c42181
12 changed files with 1098 additions and 111 deletions
+92
View File
@@ -0,0 +1,92 @@
'use client';
import {
Dialog,
DialogContent,
DialogHeader,
DialogTitle,
} from '@/components/ui/dialog';
interface ShortcutItem {
keys: string[];
description: string;
}
interface ShortcutGroup {
title: string;
shortcuts: ShortcutItem[];
}
const shortcutGroups: ShortcutGroup[] = [
{
title: 'Playback',
shortcuts: [
{ keys: ['Space', 'K'], description: 'Play / Pause' },
{ keys: ['M'], description: 'Mute / Unmute' },
],
},
{
title: 'Seeking',
shortcuts: [
{ keys: ['←'], description: 'Seek back 5s' },
{ keys: ['→'], description: 'Seek forward 5s' },
{ keys: ['J'], description: 'Seek back 10s' },
{ keys: ['L'], description: 'Seek forward 10s' },
],
},
{
title: 'Speed',
shortcuts: [
{ keys: ['↑'], description: 'Increase speed' },
{ keys: ['↓'], description: 'Decrease speed' },
{ keys: ['⇧', '>'], description: 'Increase speed' },
{ keys: ['⇧', '<'], description: 'Decrease speed' },
],
},
];
interface KeyboardShortcutsModalProps {
open: boolean;
onOpenChange: (open: boolean) => void;
}
export function KeyboardShortcutsModal({ open, onOpenChange }: KeyboardShortcutsModalProps) {
return (
<Dialog open={open} onOpenChange={onOpenChange}>
<DialogContent className="sm:max-w-md">
<DialogHeader>
<DialogTitle className="text-base">Keyboard Shortcuts</DialogTitle>
</DialogHeader>
<div className="space-y-5 mt-1">
{shortcutGroups.map((group) => (
<div key={group.title}>
<h4 className="text-xs font-medium text-muted-foreground uppercase tracking-wider mb-2.5">
{group.title}
</h4>
<div className="space-y-1.5">
{group.shortcuts.map((shortcut, i) => (
<div
key={i}
className="flex items-center justify-between py-1.5 px-2 rounded-md hover:bg-muted/50 transition-colors"
>
<span className="text-sm">{shortcut.description}</span>
<div className="flex items-center gap-1">
{shortcut.keys.map((key, j) => (
<kbd
key={j}
className="inline-flex h-6 min-w-6 items-center justify-center rounded border border-border bg-muted px-1.5 font-mono text-xs text-muted-foreground"
>
{key}
</kbd>
))}
</div>
</div>
))}
</div>
</div>
))}
</div>
</DialogContent>
</Dialog>
);
}
+10 -1
View File
@@ -1,5 +1,6 @@
'use client';
import { useState } from 'react';
import Link from 'next/link';
import { usePathname } from 'next/navigation';
import {
@@ -10,7 +11,8 @@ import {
Settings,
LogOut,
User,
Menu
Menu,
Keyboard
} from 'lucide-react';
import { Button } from '@/components/ui/button';
import {
@@ -23,6 +25,7 @@ import {
import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar';
import { Sheet, SheetContent, SheetTrigger } from '@/components/ui/sheet';
import { ThemeToggle } from '@/components/theme-toggle';
import { KeyboardShortcutsModal } from '@/components/keyboard-shortcuts-modal';
import { cn } from '@/lib/utils';
interface NavItem {
@@ -46,6 +49,7 @@ interface HeaderProps {
export function Header({ user }: HeaderProps) {
const pathname = usePathname();
const [shortcutsOpen, setShortcutsOpen] = useState(false);
return (
<header className="sticky top-0 z-50 w-full border-b bg-background/95 backdrop-blur supports-[backdrop-filter]:bg-background/60">
@@ -151,6 +155,10 @@ export function Header({ user }: HeaderProps) {
Settings
</Link>
</DropdownMenuItem>
<DropdownMenuItem onClick={() => setShortcutsOpen(true)}>
<Keyboard className="h-4 w-4 mr-2" />
Shortcuts
</DropdownMenuItem>
<DropdownMenuSeparator />
<DropdownMenuItem asChild>
<Link href="/signout">
@@ -170,6 +178,7 @@ export function Header({ user }: HeaderProps) {
)}
</div>
</div>
<KeyboardShortcutsModal open={shortcutsOpen} onOpenChange={setShortcutsOpen} />
</header>
);
}