Handle autoplay for mobile

This commit is contained in:
Nick Mowen 2023-12-13 14:09:07 -07:00
parent 08e9120db5
commit 7e13501787
4 changed files with 46 additions and 8 deletions

View File

@ -22,11 +22,13 @@ import { formatUnixTimestampToDateTime } from "@/utils/dateUtil";
type HistoryCardProps = {
timeline: Card;
relevantPreview?: Preview;
shouldAutoPlay: boolean;
};
export default function HistoryCard({
relevantPreview,
timeline,
shouldAutoPlay,
}: HistoryCardProps) {
const { data: config } = useSWR<FrigateConfig>("config");
@ -41,6 +43,7 @@ export default function HistoryCard({
relevantPreview={relevantPreview}
startTs={Object.values(timeline.entries)[0].timestamp}
eventId={Object.values(timeline.entries)[0].source_id}
shouldAutoPlay={shouldAutoPlay}
/>
<div className="p-2">
<div className="text-sm flex">

View File

@ -11,6 +11,7 @@ type PreviewPlayerProps = {
relevantPreview?: Preview;
startTs: number;
eventId: string;
shouldAutoPlay: boolean;
};
type Preview = {
@ -26,12 +27,13 @@ export default function PreviewThumbnailPlayer({
relevantPreview,
startTs,
eventId,
shouldAutoPlay,
}: PreviewPlayerProps) {
const { data: config } = useSWR("config");
const playerRef = useRef<Player | null>(null);
const apiHost = useApiHost();
const onHover = useCallback(
const onPlayback = useCallback(
(isHovered: Boolean) => {
if (!relevantPreview || !playerRef.current) {
return;
@ -47,6 +49,32 @@ export default function PreviewThumbnailPlayer({
[relevantPreview, startTs]
);
const observer = useRef<IntersectionObserver | null>();
const inViewRef = useCallback(
(node: HTMLElement | null) => {
if (!shouldAutoPlay || observer.current) {
return;
}
try {
observer.current = new IntersectionObserver(
(entries) => {
if (entries[0].isIntersecting) {
onPlayback(true);
} else {
onPlayback(false);
}
},
{ threshold: 1.0 }
);
if (node) observer.current.observe(node);
} catch (e) {
// no op
}
},
[observer, onPlayback]
);
if (!relevantPreview) {
if (isCurrentHour(startTs)) {
return (
@ -56,6 +84,7 @@ export default function PreviewThumbnailPlayer({
>
<img
className={`${getPreviewWidth(camera, config)}`}
loading="lazy"
src={`${apiHost}api/preview/${camera}/${startTs}/thumbnail.jpg`}
/>
</AspectRatio>
@ -69,6 +98,7 @@ export default function PreviewThumbnailPlayer({
>
<img
className="w-[160px]"
loading="lazy"
src={`${apiHost}api/events/${eventId}/thumbnail.jpg`}
/>
</AspectRatio>
@ -77,10 +107,11 @@ export default function PreviewThumbnailPlayer({
return (
<AspectRatio
ref={shouldAutoPlay ? inViewRef : null}
ratio={16 / 9}
className="bg-black flex justify-center items-center"
onMouseEnter={() => onHover(true)}
onMouseLeave={() => onHover(false)}
onMouseEnter={() => onPlayback(true)}
onMouseLeave={() => onPlayback(false)}
>
<div className={`${getPreviewWidth(camera, config)}`}>
<VideoPlayer

View File

@ -44,7 +44,7 @@ export default function VideoPlayer({ children, options, seekOptions = {forward:
videoElement.classList.add('small-player');
videoElement.classList.add('video-js');
videoElement.classList.add('vjs-default-skin');
videoRef.current.appendChild(videoElement);
videoRef.current?.appendChild(videoElement);
const player = playerRef.current = videojs(videoElement, { ...defaultOptions, ...options }, () => {
onReady && onReady(player);

View File

@ -5,11 +5,10 @@ import { FrigateConfig } from "@/types/frigateConfig";
import Heading from "@/components/ui/heading";
import ActivityIndicator from "@/components/ui/activity-indicator";
import HistoryCard from "@/components/card/HistoryCard";
import { ScrollArea, ScrollBar } from "@/components/ui/scroll-area";
import { formatUnixTimestampToDateTime } from "@/utils/dateUtil";
import axios from "axios";
const API_LIMIT = 200;
const API_LIMIT = 100;
function History() {
const { data: config } = useSWR<FrigateConfig>("config");
@ -26,11 +25,15 @@ function History() {
const getKey = useCallback((index: number, prevData: HourlyTimeline) => {
if (index > 0) {
const lastDate = prevData.end;
const pagedParams = { before: lastDate, timezone };
const pagedParams = { before: lastDate, timezone, limit: API_LIMIT };
return ["timeline/hourly", pagedParams];
}
return ["timeline/hourly", { timezone }];
return ["timeline/hourly", { timezone, limit: API_LIMIT }];
}, []);
const shouldAutoPlay = useMemo(() => {
return window.innerWidth < 480;
}, []);
const {
@ -207,6 +210,7 @@ function History() {
<HistoryCard
key={key}
timeline={timeline}
shouldAutoPlay={shouldAutoPlay}
relevantPreview={Object.values(
allPreviews || []
).find(