mirror of
https://github.com/yusufipk/OpenFrame.git
synced 2026-09-12 01:46:08 +00:00
refactor: Optimize comment deletion handling with optimistic UI updates
This commit is contained in:
@@ -1132,9 +1132,9 @@ export default function VideoPage() {
|
|||||||
// Delete a comment
|
// Delete a comment
|
||||||
const handleDeleteComment = useCallback(async (commentId: string) => {
|
const handleDeleteComment = useCallback(async (commentId: string) => {
|
||||||
setDeletingCommentId(commentId);
|
setDeletingCommentId(commentId);
|
||||||
try {
|
|
||||||
const res = await fetch(`/api/comments/${commentId}`, { method: 'DELETE' });
|
// Optimistically remove from UI
|
||||||
if (res.ok) {
|
const previousVideo = video;
|
||||||
setVideo((prev) => {
|
setVideo((prev) => {
|
||||||
if (!prev) return prev;
|
if (!prev) return prev;
|
||||||
return {
|
return {
|
||||||
@@ -1154,19 +1154,32 @@ export default function VideoPage() {
|
|||||||
),
|
),
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
try {
|
||||||
|
const res = await fetch(`/api/comments/${commentId}`, { method: 'DELETE' });
|
||||||
|
if (!res.ok) {
|
||||||
|
setVideo(previousVideo);
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error('Failed to delete comment:', err);
|
console.error('Failed to delete comment:', err);
|
||||||
|
setVideo(previousVideo);
|
||||||
} finally {
|
} finally {
|
||||||
setDeletingCommentId(null);
|
setDeletingCommentId(null);
|
||||||
}
|
}
|
||||||
}, [activeVersionId]);
|
}, [activeVersionId, video]);
|
||||||
|
|
||||||
// Poll for new comments every 10 seconds
|
// Poll for new comments every 10 seconds
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!activeVersion) return;
|
if (!activeVersion) return;
|
||||||
const interval = setInterval(async () => {
|
const interval = setInterval(async () => {
|
||||||
try {
|
try {
|
||||||
|
const hasPendingComments = activeVersion.comments.some(
|
||||||
|
(c) => c.id.startsWith('temp-')
|
||||||
|
) || activeVersion.comments.some(
|
||||||
|
(c) => c.replies.some((r) => r.id.startsWith('temp-'))
|
||||||
|
);
|
||||||
|
if (hasPendingComments) return;
|
||||||
|
|
||||||
const res = await fetch(`/api/projects/${projectId}/videos/${videoId}`);
|
const res = await fetch(`/api/projects/${projectId}/videos/${videoId}`);
|
||||||
if (res.ok) {
|
if (res.ok) {
|
||||||
const data = await res.json();
|
const data = await res.json();
|
||||||
|
|||||||
@@ -1085,9 +1085,9 @@ export default function WatchPage() {
|
|||||||
// Delete a comment
|
// Delete a comment
|
||||||
const handleDeleteComment = useCallback(async (commentId: string) => {
|
const handleDeleteComment = useCallback(async (commentId: string) => {
|
||||||
setDeletingCommentId(commentId);
|
setDeletingCommentId(commentId);
|
||||||
try {
|
|
||||||
const res = await fetch(`/api/comments/${commentId}`, { method: 'DELETE' });
|
// Optimistically remove from UI
|
||||||
if (res.ok) {
|
const previousVideo = video;
|
||||||
setVideo((prev) => {
|
setVideo((prev) => {
|
||||||
if (!prev) return prev;
|
if (!prev) return prev;
|
||||||
return {
|
return {
|
||||||
@@ -1107,19 +1107,33 @@ export default function WatchPage() {
|
|||||||
),
|
),
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
try {
|
||||||
|
const res = await fetch(`/api/comments/${commentId}`, { method: 'DELETE' });
|
||||||
|
if (!res.ok) {
|
||||||
|
setVideo(previousVideo);
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error('Failed to delete comment:', err);
|
console.error('Failed to delete comment:', err);
|
||||||
|
setVideo(previousVideo);
|
||||||
} finally {
|
} finally {
|
||||||
setDeletingCommentId(null);
|
setDeletingCommentId(null);
|
||||||
}
|
}
|
||||||
}, [activeVersionId]);
|
}, [activeVersionId, video]);
|
||||||
|
|
||||||
// Poll for new comments every 10 seconds
|
// Poll for new comments every 10 seconds
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!video) return;
|
if (!video) return;
|
||||||
const interval = setInterval(async () => {
|
const interval = setInterval(async () => {
|
||||||
try {
|
try {
|
||||||
|
const activeVersion = video.versions.find((v) => v.id === activeVersionId);
|
||||||
|
const hasPendingComments = activeVersion?.comments.some(
|
||||||
|
(c) => c.id.startsWith('temp-')
|
||||||
|
) || activeVersion?.comments.some(
|
||||||
|
(c) => c.replies.some((r) => r.id.startsWith('temp-'))
|
||||||
|
);
|
||||||
|
if (hasPendingComments) return;
|
||||||
|
|
||||||
const res = await fetch(`/api/watch/${videoId}`);
|
const res = await fetch(`/api/watch/${videoId}`);
|
||||||
if (res.ok) {
|
if (res.ok) {
|
||||||
const data = await res.json();
|
const data = await res.json();
|
||||||
@@ -1128,7 +1142,7 @@ export default function WatchPage() {
|
|||||||
} catch { /* silent */ }
|
} catch { /* silent */ }
|
||||||
}, 10000);
|
}, 10000);
|
||||||
return () => clearInterval(interval);
|
return () => clearInterval(interval);
|
||||||
}, [video, videoId]);
|
}, [video, videoId, activeVersionId]);
|
||||||
|
|
||||||
const getEmbedUrl = (version: Version) => {
|
const getEmbedUrl = (version: Version) => {
|
||||||
if (version.providerId === 'youtube') {
|
if (version.providerId === 'youtube') {
|
||||||
|
|||||||
Reference in New Issue
Block a user