Fix reloading recordings failing

This commit is contained in:
Nicolas Mowen 2024-08-12 12:47:25 -06:00
parent 63984c1bc9
commit daa6d7672c
3 changed files with 151 additions and 126 deletions

View File

@ -168,7 +168,10 @@ export default function DynamicVideoPlayer({
useEffect(() => {
if (!controller || !recordings) {
setNoRecording(true);
if (recordings?.length == 0) {
setNoRecording(true);
}
return;
}

View File

@ -101,7 +101,7 @@ export default function Events() {
// review paging
const [beforeTs, setBeforeTs] = useState(Date.now() / 1000);
const [beforeTs, setBeforeTs] = useState(Math.ceil(Date.now() / 1000));
const last24Hours = useMemo(() => {
return { before: beforeTs, after: getHoursAgo(24) };
}, [beforeTs]);
@ -455,5 +455,5 @@ export default function Events() {
function getHoursAgo(hours: number): number {
const now = new Date();
now.setHours(now.getHours() - hours);
return now.getTime() / 1000;
return Math.ceil(now.getTime() / 1000);
}

View File

@ -46,6 +46,7 @@ import { ASPECT_VERTICAL_LAYOUT, ASPECT_WIDE_LAYOUT } from "@/types/record";
import { useResizeObserver } from "@/hooks/resize-observer";
import { cn } from "@/lib/utils";
import { useFullscreen } from "@/hooks/use-fullscreen";
import ActivityIndicator from "@/components/indicators/activity-indicator";
const SEGMENT_DURATION = 30;
@ -107,7 +108,7 @@ export function RecordingView({
return chunk.after <= startTime && chunk.before >= startTime;
}),
);
const currentTimeRange = useMemo(
const currentTimeRange = useMemo<TimeRange | undefined>(
() => chunkedTimeRange[selectedRangeIdx],
[selectedRangeIdx, chunkedTimeRange],
);
@ -171,6 +172,10 @@ export function RecordingView({
);
useEffect(() => {
if (!currentTimeRange) {
return;
}
if (scrubbing || exportRange) {
if (
currentTime > currentTimeRange.before + 60 ||
@ -198,6 +203,10 @@ export function RecordingView({
const manuallySetCurrentTime = useCallback(
(time: number) => {
if (!currentTimeRange) {
return;
}
setCurrentTime(time);
if (currentTimeRange.after <= time && currentTimeRange.before >= time) {
@ -210,6 +219,10 @@ export function RecordingView({
);
useEffect(() => {
if (!currentTimeRange) {
return;
}
if (!scrubbing) {
if (Math.abs(currentTime - playerTime) > 10) {
if (
@ -471,143 +484,152 @@ export function RecordingView({
</div>
</div>
<div
ref={mainLayoutRef}
className={cn(
"flex h-full justify-center overflow-hidden",
isDesktop ? "" : "flex-col gap-2 landscape:flex-row",
)}
>
{currentTimeRange ? (
<div
ref={cameraLayoutRef}
className={cn("flex flex-1 flex-wrap", isDesktop ? "w-[80%]" : "")}
ref={mainLayoutRef}
className={cn(
"flex h-full justify-center overflow-hidden",
isDesktop ? "" : "flex-col gap-2 landscape:flex-row",
)}
>
<div
className={cn(
"flex size-full items-center",
mainCameraAspect == "tall"
? "flex-row justify-evenly"
: "flex-col justify-center gap-2",
)}
ref={cameraLayoutRef}
className={cn("flex flex-1 flex-wrap", isDesktop ? "w-[80%]" : "")}
>
<div
key={mainCamera}
className={cn(
"relative",
isDesktop
? cn(
"flex justify-center px-4",
mainCameraAspect == "tall"
? "h-[50%] md:h-[60%] lg:h-[75%] xl:h-[90%]"
: mainCameraAspect == "wide"
? "w-full"
: "",
)
: cn(
"pt-2 portrait:w-full",
mainCameraAspect == "wide"
? "aspect-wide landscape:w-full"
: "aspect-video landscape:h-[94%] landscape:xl:h-[65%]",
),
"flex size-full items-center",
mainCameraAspect == "tall"
? "flex-row justify-evenly"
: "flex-col justify-center gap-2",
)}
style={{
width: mainCameraStyle ? mainCameraStyle.width : undefined,
aspectRatio: isDesktop
? mainCameraAspect == "tall"
? getCameraAspect(mainCamera)
: undefined
: Math.max(1, getCameraAspect(mainCamera) ?? 0),
}}
>
<DynamicVideoPlayer
className={grow}
camera={mainCamera}
timeRange={currentTimeRange}
cameraPreviews={allPreviews ?? []}
startTimestamp={playbackStart}
hotKeys={exportMode != "select"}
fullscreen={fullscreen}
onTimestampUpdate={(timestamp) => {
setPlayerTime(timestamp);
setCurrentTime(timestamp);
Object.values(previewRefs.current ?? {}).forEach((prev) =>
prev.scrubToTimestamp(Math.floor(timestamp)),
);
}}
onClipEnded={onClipEnded}
onControllerReady={(controller) => {
mainControllerRef.current = controller;
}}
isScrubbing={scrubbing || exportMode == "timeline"}
setFullResolution={setFullResolution}
toggleFullscreen={toggleFullscreen}
containerRef={mainLayoutRef}
/>
</div>
{isDesktop && (
<div
ref={previewRowRef}
key={mainCamera}
className={cn(
"scrollbar-container flex gap-2 overflow-auto",
mainCameraAspect == "tall"
? "h-full w-72 flex-col"
: `h-28 w-full`,
previewRowOverflows ? "" : "items-center justify-center",
"relative",
isDesktop
? cn(
"flex justify-center px-4",
mainCameraAspect == "tall"
? "h-[50%] md:h-[60%] lg:h-[75%] xl:h-[90%]"
: mainCameraAspect == "wide"
? "w-full"
: "",
)
: cn(
"pt-2 portrait:w-full",
mainCameraAspect == "wide"
? "aspect-wide landscape:w-full"
: "aspect-video landscape:h-[94%] landscape:xl:h-[65%]",
),
)}
style={{
width: mainCameraStyle ? mainCameraStyle.width : undefined,
aspectRatio: isDesktop
? mainCameraAspect == "tall"
? getCameraAspect(mainCamera)
: undefined
: Math.max(1, getCameraAspect(mainCamera) ?? 0),
}}
>
<div className="w-2" />
{allCameras.map((cam) => {
if (cam == mainCamera || cam == "birdseye") {
return;
}
return (
<div
key={cam}
className={
mainCameraAspect == "tall" ? "w-full" : "h-full"
}
style={{
aspectRatio: getCameraAspect(cam),
}}
>
<PreviewPlayer
className="size-full"
camera={cam}
timeRange={currentTimeRange}
cameraPreviews={allPreviews ?? []}
startTime={startTime}
isScrubbing={scrubbing}
onControllerReady={(controller) => {
previewRefs.current[cam] = controller;
controller.scrubToTimestamp(startTime);
}}
onClick={() => onSelectCamera(cam)}
/>
</div>
);
})}
<div className="w-2" />
<DynamicVideoPlayer
className={grow}
camera={mainCamera}
timeRange={currentTimeRange}
cameraPreviews={allPreviews ?? []}
startTimestamp={playbackStart}
hotKeys={exportMode != "select"}
fullscreen={fullscreen}
onTimestampUpdate={(timestamp) => {
setPlayerTime(timestamp);
setCurrentTime(timestamp);
Object.values(previewRefs.current ?? {}).forEach((prev) =>
prev.scrubToTimestamp(Math.floor(timestamp)),
);
}}
onClipEnded={onClipEnded}
onControllerReady={(controller) => {
mainControllerRef.current = controller;
}}
isScrubbing={scrubbing || exportMode == "timeline"}
setFullResolution={setFullResolution}
toggleFullscreen={toggleFullscreen}
containerRef={mainLayoutRef}
/>
</div>
)}
{isDesktop && (
<div
ref={previewRowRef}
className={cn(
"scrollbar-container flex gap-2 overflow-auto",
mainCameraAspect == "tall"
? "h-full w-72 flex-col"
: `h-28 w-full`,
previewRowOverflows ? "" : "items-center justify-center",
)}
>
<div className="w-2" />
{allCameras.map((cam) => {
if (cam == mainCamera || cam == "birdseye") {
return;
}
return (
<div
key={cam}
className={
mainCameraAspect == "tall" ? "w-full" : "h-full"
}
style={{
aspectRatio: getCameraAspect(cam),
}}
>
<PreviewPlayer
className="size-full"
camera={cam}
timeRange={currentTimeRange}
cameraPreviews={allPreviews ?? []}
startTime={startTime}
isScrubbing={scrubbing}
onControllerReady={(controller) => {
previewRefs.current[cam] = controller;
controller.scrubToTimestamp(startTime);
}}
onClick={() => onSelectCamera(cam)}
/>
</div>
);
})}
<div className="w-2" />
</div>
)}
</div>
</div>
<Timeline
contentRef={contentRef}
mainCamera={mainCamera}
timelineType={
(exportRange == undefined ? timelineType : "timeline") ??
"timeline"
}
timeRange={timeRange}
mainCameraReviewItems={mainCameraReviewItems}
currentTime={currentTime}
exportRange={exportMode == "timeline" ? exportRange : undefined}
setCurrentTime={setCurrentTime}
manuallySetCurrentTime={manuallySetCurrentTime}
setScrubbing={setScrubbing}
setExportRange={setExportRange}
/>
</div>
) : (
<div className="relative size-full">
<div className="absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2">
No recordings or previews found for this time
</div>
</div>
<Timeline
contentRef={contentRef}
mainCamera={mainCamera}
timelineType={
(exportRange == undefined ? timelineType : "timeline") ?? "timeline"
}
timeRange={timeRange}
mainCameraReviewItems={mainCameraReviewItems}
currentTime={currentTime}
exportRange={exportMode == "timeline" ? exportRange : undefined}
setCurrentTime={setCurrentTime}
manuallySetCurrentTime={manuallySetCurrentTime}
setScrubbing={setScrubbing}
setExportRange={setExportRange}
/>
</div>
)}
</div>
);
}