mirror of
https://github.com/yusufipk/OpenFrame.git
synced 2026-09-11 17:46:06 +00:00
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:
@@ -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>
|
||||
);
|
||||
}
|
||||
@@ -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>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user