feat: add video watch progress tracking with resume functionality

Implements a complete watch progress system that allows users to:
- Save playback position automatically every 5 seconds while watching
- Resume from last position when returning to a video
- Save progress on page leave using sendBeacon for reliability

Also includes:
- Optimized slug generation in projects and workspaces APIs (single query vs loop)
- Added isActive filter to version queries across all video endpoints
- Added pagination support for video and comment queries
- Enhanced database pool management with connection limits and graceful shutdown
- New WatchProgress Prisma model with user-version relations
This commit is contained in:
Yusuf İpek
2026-02-14 15:25:32 +03:00
parent 2888f7de98
commit 88c74d646e
10 changed files with 484 additions and 38 deletions
+24 -15
View File
@@ -11,30 +11,39 @@ export async function GET(request: NextRequest, { params }: RouteParams) {
const session = await auth();
const { videoId } = await params;
// Parse query params
const searchParams = request.nextUrl.searchParams;
const includeComments = searchParams.get('includeComments') === 'true';
const video = await db.video.findUnique({
where: { id: videoId },
include: {
project: true,
versions: {
where: { isActive: true },
orderBy: { versionNumber: 'desc' },
include: {
comments: {
orderBy: { timestamp: 'asc' },
where: { parentId: null },
include: {
author: { select: { id: true, name: true, image: true } },
tag: { select: { id: true, name: true, color: true } },
replies: {
orderBy: { createdAt: 'asc' },
include: {
author: { select: { id: true, name: true, image: true } },
tag: { select: { id: true, name: true, color: true } },
},
take: 1,
...(includeComments ? {
include: {
comments: {
orderBy: { timestamp: 'asc' },
where: { parentId: null },
include: {
author: { select: { id: true, name: true, image: true } },
tag: { select: { id: true, name: true, color: true } },
},
},
_count: { select: { comments: true } },
},
_count: { select: { comments: true } },
},
} : {
select: {
id: true,
thumbnailUrl: true,
duration: true,
versionNumber: true,
_count: { select: { comments: true } },
},
}),
},
},
});