add top bar and improve ui feel

This commit is contained in:
Jelle van Snik 2023-01-10 00:27:04 +01:00
parent 024325f640
commit 351b35ef98
6 changed files with 52 additions and 11 deletions

View File

@ -5,8 +5,11 @@ import { PauseControl } from "./controls/PauseControl";
import { ProgressControl } from "./controls/ProgressControl";
import { TimeControl } from "./controls/TimeControl";
import { VolumeControl } from "./controls/VolumeControl";
import { VideoPlayerHeader } from "./parts/VideoPlayerHeader";
import { VideoPlayer, VideoPlayerProps } from "./VideoPlayer";
// TODO animate items away when hidden
export function DecoratedVideoPlayer(props: VideoPlayerProps) {
return (
<VideoPlayer autoPlay={props.autoPlay}>
@ -14,9 +17,9 @@ export function DecoratedVideoPlayer(props: VideoPlayerProps) {
<div className="absolute inset-0 flex items-center justify-center">
<LoadingControl />
</div>
<div className="pointer-events-auto absolute inset-x-0 bottom-0 mb-4 flex flex-col px-6">
<div className="pointer-events-auto absolute inset-x-0 bottom-0 flex flex-col px-4 pb-2">
<ProgressControl />
<div className="flex items-center">
<div className="flex items-center px-2">
<PauseControl />
<VolumeControl className="mr-2" />
<TimeControl />
@ -24,6 +27,9 @@ export function DecoratedVideoPlayer(props: VideoPlayerProps) {
<FullscreenControl />
</div>
</div>
<div className="pointer-events-auto absolute inset-x-0 top-0 flex flex-col py-6 px-8 pb-2">
<VideoPlayerHeader title="Spiderman: Coming House" />
</div>
</BackdropControl>
{props.children}
</VideoPlayer>

View File

@ -5,6 +5,8 @@ interface BackdropControlProps {
children?: React.ReactNode;
}
// TODO add double click to toggle fullscreen
export function BackdropControl(props: BackdropControlProps) {
const { videoState } = useVideoPlayerState();
const [moved, setMoved] = useState(false);
@ -50,12 +52,12 @@ export function BackdropControl(props: BackdropControlProps) {
}`}
/>
<div
className={`pointer-events-none absolute inset-x-0 bottom-0 h-[30%] bg-gradient-to-t from-black to-transparent opacity-75 transition-opacity duration-200 ${
className={`pointer-events-none absolute inset-x-0 bottom-0 h-[20%] bg-gradient-to-t from-black to-transparent transition-opacity duration-200 ${
!showUI ? "!opacity-0" : ""
}`}
/>
<div
className={`pointer-events-none absolute inset-x-0 top-0 h-[30%] bg-gradient-to-b from-black to-transparent opacity-75 transition-opacity duration-200 ${
className={`pointer-events-none absolute inset-x-0 top-0 h-[20%] bg-gradient-to-b from-black to-transparent transition-opacity duration-200 ${
!showUI ? "!opacity-0" : ""
}`}
/>

View File

@ -44,13 +44,13 @@ export function ProgressControl() {
}`}
>
<div
className="absolute inset-y-0 left-0 flex items-center justify-end rounded-full bg-gray-300 bg-opacity-50"
className="absolute inset-y-0 left-0 flex items-center justify-end rounded-full bg-gray-300 bg-opacity-20"
style={{
width: bufferProgress,
}}
/>
<div
className="absolute inset-y-0 left-0 flex items-center justify-end rounded-full bg-bink-500"
className="absolute inset-y-0 left-0 flex items-center justify-end rounded-full bg-bink-600"
style={{
width: watchProgress,
}}

View File

@ -60,12 +60,12 @@ export function VolumeControl(props: Props) {
</div>
<div
className={`-ml-2 w-0 overflow-hidden transition-[width,opacity] duration-300 ease-in ${
hoveredOnce ? "!w-20 opacity-100" : "w-4 opacity-0"
hoveredOnce ? "!w-24 opacity-100" : "w-4 opacity-0"
}`}
>
<div
ref={ref}
className="flex h-10 w-16 items-center px-2"
className="flex h-10 w-20 items-center px-2"
onMouseDown={dragMouseDown}
>
<div className="relative h-1 flex-1 rounded-full bg-gray-500 bg-opacity-50">

View File

@ -0,0 +1,28 @@
import { Icon, Icons } from "@/components/Icon";
import { BrandPill } from "@/components/layout/BrandPill";
interface VideoPlayerHeaderProps {
title: string;
onClick?: () => void;
}
export function VideoPlayerHeader(props: VideoPlayerHeaderProps) {
return (
<div className="flex items-center">
<div className="flex flex-1 items-center">
<p className="flex items-center">
<span
onClick={props.onClick}
className="flex cursor-pointer items-center py-1 text-white opacity-50 transition-opacity hover:opacity-100"
>
<Icon className="mr-2" icon={Icons.ARROW_LEFT} />
<span>Back to home</span>
</span>
<span className="mx-4 h-6 w-[1.5px] rotate-[30deg] bg-white opacity-50" />
<span className="text-white">{props.title}</span>
</p>
</div>
<BrandPill />
</div>
);
}

View File

@ -5,13 +5,18 @@ import { useCallback, useState } from "react";
// test videos: https://gist.github.com/jsturgis/3b19447b304616f18657
// TODO video todos:
// - make pretty
// - improve seekables
// - improve seekables (if possible)
// - error handling
// - middle pause button
// - double click backdrop to toggle fullscreen
// - make volume bar collapse when hovering away from left control section
// - animate UI when showing/hiding
// - shortcuts when player is active
// - save volume in localstorage so persists between page reloads
// - improve pausing while seeking/buffering
// - volume control flashes old value when updating
// - progress control flashes old value when updating
// - captions
// - backdrop better click handling
// - IOS support: (no volume, fullscreen video element instead of wrapper)
// - IpadOS support: (fullscreen video wrapper should work, see (lookmovie.io) )
// - HLS support: feature detection otherwise use HLS.js