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