Mobile recordings redesign (#10711)

* Only show back button text on desktop

* Add mobile camera drawer to separate component

* Use bottom sheet for export on mobile

* Add intermediary mobile bottom sheet

* fix filter

* Fix mobile layout jumping

* Fix desktop vertical camera view

* Fix horizontal camera list

* Add overlay instead of using same button for timeline exports

* Don't use native hls for now

* Fix export bottom sheet

* Fix scrolling

* Simplify checks

* Adjust hls compat approach

* Fix events shadow

* Make corners consistent

* Make corners consistent

* fix max drawer height

* Use separate buttons for export control

* Add icons

* Fix list views

* Fix new items to review

* bottom padding on bottom sheets

* bottom padding on bottom sheets
This commit is contained in:
Nicolas Mowen
2024-03-27 17:03:05 -06:00
committed by GitHub
parent 559e6910c4
commit 4e800e19ff
11 changed files with 890 additions and 348 deletions

View File

@@ -88,29 +88,36 @@ export default function HlsVideoPlayer({
const [controlsOpen, setControlsOpen] = useState(false);
return (
<div
className={`relative ${visible ? "visible" : "hidden"}`}
onMouseOver={
isDesktop
? () => {
setControls(true);
}
: undefined
}
onMouseOut={
isDesktop
? () => {
setControls(controlsOpen);
}
: undefined
}
onClick={isDesktop ? undefined : () => setControls(!controls)}
>
<TransformWrapper minScale={1.0}>
<TransformComponent>
<TransformWrapper minScale={1.0}>
<div
className={`relative w-full ${className ?? ""} ${visible ? "visible" : "hidden"}`}
onMouseOver={
isDesktop
? () => {
setControls(true);
}
: undefined
}
onMouseOut={
isDesktop
? () => {
setControls(controlsOpen);
}
: undefined
}
onClick={isDesktop ? undefined : () => setControls(!controls)}
>
<TransformComponent
wrapperStyle={{
width: "100%",
}}
contentStyle={{
width: "100%",
}}
>
<video
ref={videoRef}
className={`${className ?? ""} bg-black rounded-2xl ${loadedMetadata ? "" : "invisible"}`}
className={`size-full bg-black rounded-2xl ${loadedMetadata ? "" : "invisible"}`}
preload="auto"
autoPlay
controls={false}
@@ -149,46 +156,47 @@ export default function HlsVideoPlayer({
unsupportedErrorCodes.includes(e.target.error.code) &&
videoRef.current
) {
setLoadedMetadata(false);
setUseHlsCompat(true);
}
}}
/>
</TransformComponent>
</TransformWrapper>
<VideoControls
className="absolute bottom-5 left-1/2 -translate-x-1/2"
video={videoRef.current}
isPlaying={isPlaying}
show={controls}
controlsOpen={controlsOpen}
setControlsOpen={setControlsOpen}
playbackRate={videoRef.current?.playbackRate ?? 1}
hotKeys={hotKeys}
onPlayPause={(play) => {
if (!videoRef.current) {
return;
}
<VideoControls
className="absolute bottom-5 left-1/2 -translate-x-1/2"
video={videoRef.current}
isPlaying={isPlaying}
show={controls}
controlsOpen={controlsOpen}
setControlsOpen={setControlsOpen}
playbackRate={videoRef.current?.playbackRate ?? 1}
hotKeys={hotKeys}
onPlayPause={(play) => {
if (!videoRef.current) {
return;
}
if (play) {
videoRef.current.play();
} else {
videoRef.current.pause();
}
}}
onSeek={(diff) => {
const currentTime = videoRef.current?.currentTime;
if (play) {
videoRef.current.play();
} else {
videoRef.current.pause();
}
}}
onSeek={(diff) => {
const currentTime = videoRef.current?.currentTime;
if (!videoRef.current || !currentTime) {
return;
}
if (!videoRef.current || !currentTime) {
return;
}
videoRef.current.currentTime = Math.max(0, currentTime + diff);
}}
onSetPlaybackRate={(rate) =>
videoRef.current ? (videoRef.current.playbackRate = rate) : null
}
/>
{children}
</div>
videoRef.current.currentTime = Math.max(0, currentTime + diff);
}}
onSetPlaybackRate={(rate) =>
videoRef.current ? (videoRef.current.playbackRate = rate) : null
}
/>
{children}
</div>
</TransformWrapper>
);
}

View File

@@ -9,6 +9,7 @@ import PreviewPlayer, { PreviewController } from "../PreviewPlayer";
import { DynamicVideoController } from "./DynamicVideoController";
import HlsVideoPlayer from "../HlsVideoPlayer";
import { TimeRange, Timeline } from "@/types/timeline";
import { isDesktop } from "react-device-detect";
/**
* Dynamically switches between video playback and scrubbing preview player.
@@ -54,7 +55,7 @@ export default function DynamicVideoPlayer({
if (aspectRatio > 2) {
return "";
} else if (aspectRatio < 16 / 9) {
return "aspect-tall";
return isDesktop ? "" : "aspect-tall";
} else {
return "aspect-video";
}
@@ -168,9 +169,9 @@ export default function DynamicVideoPlayer({
}, [controller, recordings]);
return (
<div className={`relative ${className ?? ""}`}>
<div className={`w-full relative ${className ?? ""}`}>
<HlsVideoPlayer
className={`w-full ${grow ?? ""}`}
className={isDesktop ? `w-full ${grow}` : "max-h-[50dvh]"}
videoRef={playerRef}
visible={!(isScrubbing || isLoading)}
currentSource={source}
@@ -194,7 +195,7 @@ export default function DynamicVideoPlayer({
)}
</HlsVideoPlayer>
<PreviewPlayer
className={`${isScrubbing || isLoading ? "visible" : "hidden"} ${grow}`}
className={`${isScrubbing || isLoading ? "visible" : "hidden"} ${isDesktop ? `w-full ${grow}` : "max-h-[50dvh]"}`}
camera={camera}
timeRange={timeRange}
cameraPreviews={cameraPreviews}