mirror of
https://github.com/blakeblackshear/frigate.git
synced 2026-04-05 22:57:40 +03:00
Preserve scrub zoom state while addressing maintainer feedback
This commit is contained in:
parent
9eb0a89de0
commit
2e48fa47ac
@ -68,7 +68,7 @@ export default function HlsVideoPlayer({
|
|||||||
videoClassName,
|
videoClassName,
|
||||||
containerRef,
|
containerRef,
|
||||||
visible,
|
visible,
|
||||||
showControls = visible,
|
showControls = true,
|
||||||
currentSource,
|
currentSource,
|
||||||
hotKeys,
|
hotKeys,
|
||||||
supportsFullscreen,
|
supportsFullscreen,
|
||||||
@ -290,7 +290,7 @@ export default function HlsVideoPlayer({
|
|||||||
)}
|
)}
|
||||||
video={videoRef.current}
|
video={videoRef.current}
|
||||||
isPlaying={isPlaying}
|
isPlaying={isPlaying}
|
||||||
show={showControls && (controls || controlsOpen)}
|
show={visible && showControls && (controls || controlsOpen)}
|
||||||
muted={muted}
|
muted={muted}
|
||||||
volume={volume}
|
volume={volume}
|
||||||
features={{
|
features={{
|
||||||
@ -395,9 +395,8 @@ export default function HlsVideoPlayer({
|
|||||||
<video
|
<video
|
||||||
ref={videoRef}
|
ref={videoRef}
|
||||||
className={cn(
|
className={cn(
|
||||||
"size-full rounded-lg bg-black md:rounded-2xl",
|
"size-full cursor-pointer rounded-lg bg-black md:rounded-2xl",
|
||||||
loadedMetadata ? "" : "invisible",
|
loadedMetadata ? "" : "invisible",
|
||||||
"cursor-pointer",
|
|
||||||
videoClassName,
|
videoClassName,
|
||||||
)}
|
)}
|
||||||
preload="auto"
|
preload="auto"
|
||||||
|
|||||||
@ -282,12 +282,9 @@ export default function DynamicVideoPlayer({
|
|||||||
);
|
);
|
||||||
|
|
||||||
const showPreview = isScrubbing || isLoading;
|
const showPreview = isScrubbing || isLoading;
|
||||||
const previewPlayer = (
|
const renderPreviewPlayer = (previewClassName: string) => (
|
||||||
<PreviewPlayer
|
<PreviewPlayer
|
||||||
className={cn(
|
className={previewClassName}
|
||||||
source ? "pointer-events-none absolute inset-0 z-20" : className,
|
|
||||||
showPreview ? "visible" : "invisible",
|
|
||||||
)}
|
|
||||||
camera={camera}
|
camera={camera}
|
||||||
timeRange={timeRange}
|
timeRange={timeRange}
|
||||||
cameraPreviews={cameraPreviews}
|
cameraPreviews={cameraPreviews}
|
||||||
@ -298,6 +295,12 @@ export default function DynamicVideoPlayer({
|
|||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
const previewOverlay = renderPreviewPlayer(
|
||||||
|
cn(
|
||||||
|
"pointer-events-none absolute inset-0 z-20",
|
||||||
|
showPreview ? "visible" : "invisible",
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@ -306,6 +309,8 @@ export default function DynamicVideoPlayer({
|
|||||||
videoRef={playerRef}
|
videoRef={playerRef}
|
||||||
videoClassName={videoClassName}
|
videoClassName={videoClassName}
|
||||||
containerRef={containerRef}
|
containerRef={containerRef}
|
||||||
|
// Keep transform wrapper mounted while scrubbing/loading
|
||||||
|
// so zoom and pan position are preserved.
|
||||||
visible={true}
|
visible={true}
|
||||||
showControls={!isScrubbing && !isLoading}
|
showControls={!isScrubbing && !isLoading}
|
||||||
currentSource={source}
|
currentSource={source}
|
||||||
@ -346,12 +351,13 @@ export default function DynamicVideoPlayer({
|
|||||||
transformedOverlay={
|
transformedOverlay={
|
||||||
<>
|
<>
|
||||||
{transformedOverlay}
|
{transformedOverlay}
|
||||||
{previewPlayer}
|
{previewOverlay}
|
||||||
</>
|
</>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{!source && previewPlayer}
|
{!source &&
|
||||||
|
renderPreviewPlayer(cn(className, showPreview ? "visible" : "hidden"))}
|
||||||
{!isScrubbing && (isLoading || isBuffering) && !noRecording && (
|
{!isScrubbing && (isLoading || isBuffering) && !noRecording && (
|
||||||
<ActivityIndicator className="absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2" />
|
<ActivityIndicator className="absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2" />
|
||||||
)}
|
)}
|
||||||
|
|||||||
@ -374,7 +374,6 @@ export function RecordingView({
|
|||||||
const {
|
const {
|
||||||
cameraSectionStyle,
|
cameraSectionStyle,
|
||||||
isDraggingMobileSplit,
|
isDraggingMobileSplit,
|
||||||
isMobilePortraitStacked,
|
|
||||||
onHandlePointerDown,
|
onHandlePointerDown,
|
||||||
usePortraitSplitLayout,
|
usePortraitSplitLayout,
|
||||||
} = useMobileVideoSplit({
|
} = useMobileVideoSplit({
|
||||||
@ -778,7 +777,7 @@ export function RecordingView({
|
|||||||
? "min-w-0 px-4"
|
? "min-w-0 px-4"
|
||||||
: cn(
|
: cn(
|
||||||
"portrait:flex-shrink-0 portrait:flex-grow-0 portrait:basis-auto",
|
"portrait:flex-shrink-0 portrait:flex-grow-0 portrait:basis-auto",
|
||||||
isMobilePortraitStacked
|
usePortraitSplitLayout
|
||||||
? "portrait:flex-none"
|
? "portrait:flex-none"
|
||||||
: "portrait:max-h-[50dvh]",
|
: "portrait:max-h-[50dvh]",
|
||||||
),
|
),
|
||||||
@ -922,7 +921,7 @@ export function RecordingView({
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{isMobilePortraitStacked && !fullscreen && (
|
{usePortraitSplitLayout && (
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
aria-label={t("recordings.resizeSplit")}
|
aria-label={t("recordings.resizeSplit")}
|
||||||
|
|||||||
@ -23,7 +23,6 @@ type UseMobileVideoSplitProps = {
|
|||||||
type UseMobileVideoSplitReturn = {
|
type UseMobileVideoSplitReturn = {
|
||||||
cameraSectionStyle: CSSProperties | undefined;
|
cameraSectionStyle: CSSProperties | undefined;
|
||||||
isDraggingMobileSplit: boolean;
|
isDraggingMobileSplit: boolean;
|
||||||
isMobilePortraitStacked: boolean;
|
|
||||||
onHandlePointerDown: (event: PointerEvent<HTMLButtonElement>) => void;
|
onHandlePointerDown: (event: PointerEvent<HTMLButtonElement>) => void;
|
||||||
usePortraitSplitLayout: boolean;
|
usePortraitSplitLayout: boolean;
|
||||||
};
|
};
|
||||||
@ -40,11 +39,10 @@ export function useMobileVideoSplit({
|
|||||||
const [{ width: mainLayoutWidth, height: mainLayoutHeight }] =
|
const [{ width: mainLayoutWidth, height: mainLayoutHeight }] =
|
||||||
useResizeObserver(mainLayoutRef);
|
useResizeObserver(mainLayoutRef);
|
||||||
|
|
||||||
const isMobilePortraitStacked = useMemo(
|
const usePortraitSplitLayout = useMemo(
|
||||||
() => !isDesktop && mainLayoutHeight > mainLayoutWidth,
|
() => !isDesktop && !fullscreen && mainLayoutHeight > mainLayoutWidth,
|
||||||
[mainLayoutHeight, mainLayoutWidth],
|
[fullscreen, mainLayoutHeight, mainLayoutWidth],
|
||||||
);
|
);
|
||||||
const usePortraitSplitLayout = isMobilePortraitStacked && !fullscreen;
|
|
||||||
const mobileVideoSplitSafe = useMemo(
|
const mobileVideoSplitSafe = useMemo(
|
||||||
() =>
|
() =>
|
||||||
Math.min(
|
Math.min(
|
||||||
@ -59,7 +57,7 @@ export function useMobileVideoSplit({
|
|||||||
|
|
||||||
const updateMobileSplitFromClientY = useCallback(
|
const updateMobileSplitFromClientY = useCallback(
|
||||||
(clientY: number) => {
|
(clientY: number) => {
|
||||||
if (!mainLayoutRef.current || !isMobilePortraitStacked) {
|
if (!mainLayoutRef.current || !usePortraitSplitLayout) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -75,12 +73,12 @@ export function useMobileVideoSplit({
|
|||||||
);
|
);
|
||||||
setMobileVideoSplit(clampedSplit);
|
setMobileVideoSplit(clampedSplit);
|
||||||
},
|
},
|
||||||
[isMobilePortraitStacked, mainLayoutRef, setMobileVideoSplit],
|
[usePortraitSplitLayout, mainLayoutRef, setMobileVideoSplit],
|
||||||
);
|
);
|
||||||
|
|
||||||
const onHandlePointerDown = useCallback(
|
const onHandlePointerDown = useCallback(
|
||||||
(event: PointerEvent<HTMLButtonElement>) => {
|
(event: PointerEvent<HTMLButtonElement>) => {
|
||||||
if (!isMobilePortraitStacked) {
|
if (!usePortraitSplitLayout) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -88,7 +86,7 @@ export function useMobileVideoSplit({
|
|||||||
setIsDraggingMobileSplit(true);
|
setIsDraggingMobileSplit(true);
|
||||||
updateMobileSplitFromClientY(event.clientY);
|
updateMobileSplitFromClientY(event.clientY);
|
||||||
},
|
},
|
||||||
[isMobilePortraitStacked, updateMobileSplitFromClientY],
|
[usePortraitSplitLayout, updateMobileSplitFromClientY],
|
||||||
);
|
);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -117,16 +115,15 @@ export function useMobileVideoSplit({
|
|||||||
|
|
||||||
const cameraSectionStyle = useMemo(
|
const cameraSectionStyle = useMemo(
|
||||||
() =>
|
() =>
|
||||||
isMobilePortraitStacked
|
usePortraitSplitLayout
|
||||||
? { height: `${Math.round(mobileVideoSplitSafe * 100)}%` }
|
? { height: `${Math.round(mobileVideoSplitSafe * 100)}%` }
|
||||||
: undefined,
|
: undefined,
|
||||||
[isMobilePortraitStacked, mobileVideoSplitSafe],
|
[usePortraitSplitLayout, mobileVideoSplitSafe],
|
||||||
);
|
);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
cameraSectionStyle,
|
cameraSectionStyle,
|
||||||
isDraggingMobileSplit,
|
isDraggingMobileSplit,
|
||||||
isMobilePortraitStacked,
|
|
||||||
onHandlePointerDown,
|
onHandlePointerDown,
|
||||||
usePortraitSplitLayout,
|
usePortraitSplitLayout,
|
||||||
};
|
};
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user