Spaces:
Running on CPU Upgrade
Running on CPU Upgrade
Sync from GitHub via hub-sync
Browse files
src/app/[org]/[dataset]/[episode]/episode-viewer.tsx
CHANGED
|
@@ -1,13 +1,6 @@
|
|
| 1 |
"use client";
|
| 2 |
|
| 3 |
-
import {
|
| 4 |
-
useState,
|
| 5 |
-
useEffect,
|
| 6 |
-
useRef,
|
| 7 |
-
lazy,
|
| 8 |
-
Suspense,
|
| 9 |
-
useCallback,
|
| 10 |
-
} from "react";
|
| 11 |
import { useRouter, useSearchParams } from "next/navigation";
|
| 12 |
import { postParentMessageWithParams } from "@/utils/postParentMessage";
|
| 13 |
import { SimpleVideosPlayer } from "@/components/simple-videos-player";
|
|
@@ -470,33 +463,52 @@ function EpisodeViewerInner({
|
|
| 470 |
});
|
| 471 |
}, []);
|
| 472 |
|
| 473 |
-
|
| 474 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 475 |
const { key } = e;
|
|
|
|
| 476 |
|
| 477 |
if (key === " ") {
|
| 478 |
e.preventDefault();
|
| 479 |
-
if (activeTab === "urdf") {
|
| 480 |
urdfPlayToggleRef.current?.();
|
| 481 |
} else {
|
| 482 |
setIsPlaying((prev: boolean) => !prev);
|
| 483 |
}
|
| 484 |
} else if (key === "ArrowDown" || key === "ArrowUp") {
|
| 485 |
e.preventDefault();
|
| 486 |
-
if (activeTab === "urdf") {
|
| 487 |
const nextEp =
|
| 488 |
-
key === "ArrowDown" ? urdfEpisode + 1 : urdfEpisode - 1;
|
| 489 |
-
const lowest = episodes[0];
|
| 490 |
-
const highest = episodes[episodes.length - 1];
|
| 491 |
if (nextEp >= lowest && nextEp <= highest) {
|
| 492 |
setUrdfEpisode(nextEp);
|
| 493 |
urdfChangerRef.current?.(nextEp);
|
| 494 |
}
|
| 495 |
} else {
|
| 496 |
const nextEpisodeId =
|
| 497 |
-
key === "ArrowDown" ? episodeId + 1 : episodeId - 1;
|
| 498 |
-
const lowestEpisodeId = episodes[0];
|
| 499 |
-
const highestEpisodeId = episodes[episodes.length - 1];
|
| 500 |
if (
|
| 501 |
nextEpisodeId >= lowestEpisodeId &&
|
| 502 |
nextEpisodeId <= highestEpisodeId
|
|
@@ -505,24 +517,12 @@ function EpisodeViewerInner({
|
|
| 505 |
}
|
| 506 |
}
|
| 507 |
}
|
| 508 |
-
},
|
| 509 |
-
[activeTab, episodeId, episodes, router, setIsPlaying, urdfEpisode],
|
| 510 |
-
);
|
| 511 |
-
|
| 512 |
-
// Initialize based on URL time parameter
|
| 513 |
-
useEffect(() => {
|
| 514 |
-
// Initialize page based on current episode
|
| 515 |
-
const episodeIndex = episodes.indexOf(episodeId);
|
| 516 |
-
if (episodeIndex !== -1) {
|
| 517 |
-
setCurrentPage(Math.floor(episodeIndex / pageSize) + 1);
|
| 518 |
-
}
|
| 519 |
-
|
| 520 |
-
// Add keyboard event listener
|
| 521 |
-
window.addEventListener("keydown", handleKeyDown);
|
| 522 |
-
return () => {
|
| 523 |
-
window.removeEventListener("keydown", handleKeyDown);
|
| 524 |
};
|
| 525 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 526 |
|
| 527 |
// Pagination functions
|
| 528 |
const nextPage = () => {
|
|
|
|
| 1 |
"use client";
|
| 2 |
|
| 3 |
+
import { useState, useEffect, useRef, lazy, Suspense } from "react";
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 4 |
import { useRouter, useSearchParams } from "next/navigation";
|
| 5 |
import { postParentMessageWithParams } from "@/utils/postParentMessage";
|
| 6 |
import { SimpleVideosPlayer } from "@/components/simple-videos-player";
|
|
|
|
| 463 |
});
|
| 464 |
}, []);
|
| 465 |
|
| 466 |
+
// Initialize page based on the current episode. Splitting this out from
|
| 467 |
+
// the keyboard listener effect lets the listener attach exactly once.
|
| 468 |
+
useEffect(() => {
|
| 469 |
+
const episodeIndex = episodes.indexOf(episodeId);
|
| 470 |
+
if (episodeIndex !== -1) {
|
| 471 |
+
setCurrentPage(Math.floor(episodeIndex / pageSize) + 1);
|
| 472 |
+
}
|
| 473 |
+
}, [episodes, episodeId, pageSize]);
|
| 474 |
+
|
| 475 |
+
// Mirror the values the keydown handler needs into a ref. Without this,
|
| 476 |
+
// `useCallback` would produce a new handler whenever `activeTab` /
|
| 477 |
+
// `episodeId` / `urdfEpisode` changed, and the keydown effect would
|
| 478 |
+
// detach + reattach the listener each time. Now the listener attaches
|
| 479 |
+
// once and reads the latest state via the ref.
|
| 480 |
+
// Vercel rule: advanced-event-handler-refs.
|
| 481 |
+
const keyStateRef = useRef({ activeTab, episodeId, episodes, urdfEpisode });
|
| 482 |
+
keyStateRef.current = { activeTab, episodeId, episodes, urdfEpisode };
|
| 483 |
+
|
| 484 |
+
useEffect(() => {
|
| 485 |
+
const onKeyDown = (e: KeyboardEvent) => {
|
| 486 |
const { key } = e;
|
| 487 |
+
const s = keyStateRef.current;
|
| 488 |
|
| 489 |
if (key === " ") {
|
| 490 |
e.preventDefault();
|
| 491 |
+
if (s.activeTab === "urdf") {
|
| 492 |
urdfPlayToggleRef.current?.();
|
| 493 |
} else {
|
| 494 |
setIsPlaying((prev: boolean) => !prev);
|
| 495 |
}
|
| 496 |
} else if (key === "ArrowDown" || key === "ArrowUp") {
|
| 497 |
e.preventDefault();
|
| 498 |
+
if (s.activeTab === "urdf") {
|
| 499 |
const nextEp =
|
| 500 |
+
key === "ArrowDown" ? s.urdfEpisode + 1 : s.urdfEpisode - 1;
|
| 501 |
+
const lowest = s.episodes[0];
|
| 502 |
+
const highest = s.episodes[s.episodes.length - 1];
|
| 503 |
if (nextEp >= lowest && nextEp <= highest) {
|
| 504 |
setUrdfEpisode(nextEp);
|
| 505 |
urdfChangerRef.current?.(nextEp);
|
| 506 |
}
|
| 507 |
} else {
|
| 508 |
const nextEpisodeId =
|
| 509 |
+
key === "ArrowDown" ? s.episodeId + 1 : s.episodeId - 1;
|
| 510 |
+
const lowestEpisodeId = s.episodes[0];
|
| 511 |
+
const highestEpisodeId = s.episodes[s.episodes.length - 1];
|
| 512 |
if (
|
| 513 |
nextEpisodeId >= lowestEpisodeId &&
|
| 514 |
nextEpisodeId <= highestEpisodeId
|
|
|
|
| 517 |
}
|
| 518 |
}
|
| 519 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 520 |
};
|
| 521 |
+
|
| 522 |
+
window.addEventListener("keydown", onKeyDown);
|
| 523 |
+
return () => window.removeEventListener("keydown", onKeyDown);
|
| 524 |
+
// router / setIsPlaying are stable; the rest is read via keyStateRef.
|
| 525 |
+
}, [router, setIsPlaying]);
|
| 526 |
|
| 527 |
// Pagination functions
|
| 528 |
const nextPage = () => {
|