초기 커밋: DefVideo 소스 등록

abcVideo 플레이어 소스 (client / server / shared / pythonsource / docs / .claude).
.gitignore 적용으로 node_modules·storage·samplevideo·미디어 등 대용량 일괄 제외.
103 files, ~964K.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-16 03:20:27 +00:00
commit 82662d417d
103 changed files with 17213 additions and 0 deletions

View File

@@ -0,0 +1,61 @@
import { useEffect, useCallback } from 'react';
import { useAnnotationStore } from '../store/annotationStore';
import type { Annotation, CreateAnnotationInput, UpdateAnnotationInput } from '@abcvideo/shared';
export function useAnnotations(videoId: string | null) {
const { annotations, setAnnotations, addAnnotation, updateAnnotation, removeAnnotation } =
useAnnotationStore();
useEffect(() => {
if (!videoId) { setAnnotations([]); return; }
fetch(`/api/annotations/${videoId}`)
.then((r) => r.json())
.then((data: Annotation[]) => setAnnotations(data))
.catch(console.error);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [videoId]);
const create = useCallback(
async (input: Omit<CreateAnnotationInput, 'videoId'>) => {
if (!videoId) return;
const res = await fetch(`/api/annotations/${videoId}`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ ...input, videoId }),
});
const annotation: Annotation = await res.json();
addAnnotation(annotation);
return annotation;
},
// eslint-disable-next-line react-hooks/exhaustive-deps
[videoId]
);
const update = useCallback(
async (id: string, input: UpdateAnnotationInput) => {
if (!videoId) return;
const res = await fetch(`/api/annotations/${videoId}/${id}`, {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(input),
});
const annotation: Annotation = await res.json();
updateAnnotation(id, annotation);
return annotation;
},
// eslint-disable-next-line react-hooks/exhaustive-deps
[videoId]
);
const remove = useCallback(
async (id: string) => {
if (!videoId) return;
await fetch(`/api/annotations/${videoId}/${id}`, { method: 'DELETE' });
removeAnnotation(id);
},
// eslint-disable-next-line react-hooks/exhaustive-deps
[videoId]
);
return { annotations, create, update, remove };
}