mirror of
https://github.com/sussy-code/smov.git
synced 2024-12-21 14:47:41 +01:00
mobile safe video sizes
This commit is contained in:
parent
20685577ab
commit
a077417761
5 changed files with 22 additions and 44 deletions
|
@ -90,7 +90,7 @@ export function DecoratedVideoPlayer(
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
ref={bottom}
|
ref={bottom}
|
||||||
className="pointer-events-auto absolute inset-x-0 bottom-0 flex flex-col px-4 pb-2"
|
className="pointer-events-auto absolute inset-x-0 bottom-0 flex flex-col px-4 pb-2 [margin-bottom:env(safe-area-inset-bottom)]"
|
||||||
>
|
>
|
||||||
<ProgressControl />
|
<ProgressControl />
|
||||||
<div className="flex items-center">
|
<div className="flex items-center">
|
||||||
|
|
|
@ -1,33 +1,7 @@
|
||||||
import { Icon, Icons } from "@/components/Icon";
|
import { Icons } from "@/components/Icon";
|
||||||
import { VideoPlayerIconButton } from "../parts/VideoPlayerIconButton";
|
import { VideoPlayerIconButton } from "../parts/VideoPlayerIconButton";
|
||||||
import { useVideoPlayerState } from "../VideoContext";
|
import { useVideoPlayerState } from "../VideoContext";
|
||||||
|
|
||||||
function durationExceedsHour(secs: number): boolean {
|
|
||||||
return secs > 60 * 60;
|
|
||||||
}
|
|
||||||
|
|
||||||
function formatSeconds(secs: number, showHours = false): string {
|
|
||||||
if (Number.isNaN(secs)) {
|
|
||||||
if (showHours) return "0:00:00";
|
|
||||||
return "0:00";
|
|
||||||
}
|
|
||||||
|
|
||||||
let time = secs;
|
|
||||||
const seconds = Math.floor(time % 60);
|
|
||||||
|
|
||||||
time /= 60;
|
|
||||||
const minutes = Math.floor(time % 60);
|
|
||||||
|
|
||||||
time /= 60;
|
|
||||||
const hours = Math.floor(time);
|
|
||||||
|
|
||||||
const paddedSecs = seconds.toString().padStart(2, "0");
|
|
||||||
const paddedMins = minutes.toString().padStart(2, "0");
|
|
||||||
|
|
||||||
if (!showHours) return [minutes, paddedSecs].join(":");
|
|
||||||
return [hours, paddedMins, paddedSecs].join(":");
|
|
||||||
}
|
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
className?: string;
|
className?: string;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,9 @@ import React, { RefObject, useCallback, useEffect, useState } from "react";
|
||||||
|
|
||||||
type ActivityEvent =
|
type ActivityEvent =
|
||||||
| React.MouseEvent<HTMLElement>
|
| React.MouseEvent<HTMLElement>
|
||||||
| React.TouchEvent<HTMLElement>;
|
| React.TouchEvent<HTMLElement>
|
||||||
|
| MouseEvent
|
||||||
|
| TouchEvent;
|
||||||
|
|
||||||
export function makePercentageString(num: number) {
|
export function makePercentageString(num: number) {
|
||||||
return `${num.toFixed(2)}%`;
|
return `${num.toFixed(2)}%`;
|
||||||
|
@ -13,15 +15,13 @@ export function makePercentage(num: number) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function isClickEvent(
|
function isClickEvent(
|
||||||
evt: React.MouseEvent<HTMLElement> | React.TouchEvent<HTMLElement>
|
evt: ActivityEvent
|
||||||
): evt is React.MouseEvent<HTMLElement> {
|
): evt is React.MouseEvent<HTMLElement> | MouseEvent {
|
||||||
return evt.type === "mousedown";
|
return evt.type === "mousedown" || evt.type === "mouseup";
|
||||||
}
|
}
|
||||||
|
|
||||||
const getEventX = (
|
const getEventX = (evt: ActivityEvent) => {
|
||||||
evt: React.MouseEvent<HTMLElement> | React.TouchEvent<HTMLElement>
|
return isClickEvent(evt) ? evt.pageX : evt.changedTouches[0].pageX;
|
||||||
) => {
|
|
||||||
return isClickEvent(evt) ? evt.pageX : evt.touches[0].pageX;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export function useProgressBar(
|
export function useProgressBar(
|
||||||
|
@ -33,15 +33,15 @@ export function useProgressBar(
|
||||||
const [progress, setProgress] = useState<number>(0);
|
const [progress, setProgress] = useState<number>(0);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
function mouseMove(ev: MouseEvent) {
|
function mouseMove(ev: ActivityEvent) {
|
||||||
if (!mouseDown || !barRef.current) return;
|
if (!mouseDown || !barRef.current) return;
|
||||||
const rect = barRef.current.getBoundingClientRect();
|
const rect = barRef.current.getBoundingClientRect();
|
||||||
const pos = (ev.pageX - rect.left) / barRef.current.offsetWidth;
|
const pos = (getEventX(ev) - rect.left) / barRef.current.offsetWidth;
|
||||||
setProgress(pos * 100);
|
setProgress(pos * 100);
|
||||||
if (commitImmediately) commit(pos);
|
if (commitImmediately) commit(pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
function mouseUp(ev: MouseEvent | TouchEvent) {
|
function mouseUp(ev: ActivityEvent) {
|
||||||
if (!mouseDown) return;
|
if (!mouseDown) return;
|
||||||
setMouseDown(false);
|
setMouseDown(false);
|
||||||
document.body.removeAttribute("data-no-select");
|
document.body.removeAttribute("data-no-select");
|
||||||
|
@ -53,17 +53,20 @@ export function useProgressBar(
|
||||||
}
|
}
|
||||||
|
|
||||||
document.addEventListener("mousemove", mouseMove);
|
document.addEventListener("mousemove", mouseMove);
|
||||||
|
document.addEventListener("touchmove", mouseMove);
|
||||||
document.addEventListener("mouseup", mouseUp);
|
document.addEventListener("mouseup", mouseUp);
|
||||||
document.addEventListener("touchend", mouseUp);
|
document.addEventListener("touchend", mouseUp);
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
document.removeEventListener("mousemove", mouseMove);
|
document.removeEventListener("mousemove", mouseMove);
|
||||||
|
document.removeEventListener("touchmove", mouseMove);
|
||||||
document.removeEventListener("mouseup", mouseUp);
|
document.removeEventListener("mouseup", mouseUp);
|
||||||
|
document.removeEventListener("touchend", mouseUp);
|
||||||
};
|
};
|
||||||
}, [mouseDown, barRef, commit, commitImmediately]);
|
}, [mouseDown, barRef, commit, commitImmediately]);
|
||||||
|
|
||||||
const dragMouseDown = useCallback(
|
const dragMouseDown = useCallback(
|
||||||
(ev: React.MouseEvent<HTMLElement> | React.TouchEvent<HTMLElement>) => {
|
(ev: ActivityEvent) => {
|
||||||
setMouseDown(true);
|
setMouseDown(true);
|
||||||
document.body.setAttribute("data-no-select", "true");
|
document.body.setAttribute("data-no-select", "true");
|
||||||
|
|
||||||
|
|
|
@ -4,12 +4,15 @@
|
||||||
|
|
||||||
html,
|
html,
|
||||||
body {
|
body {
|
||||||
@apply bg-denim-100 text-denim-700 font-open-sans min-h-screen overflow-x-hidden;
|
@apply bg-denim-100 text-denim-700 font-open-sans overflow-x-hidden;
|
||||||
|
min-height: 100vh;
|
||||||
|
min-height: 100dvh;
|
||||||
}
|
}
|
||||||
|
|
||||||
#root {
|
#root {
|
||||||
padding: 0.05px;
|
padding: 0.05px;
|
||||||
min-height: 100vh;
|
min-height: 100vh;
|
||||||
|
min-height: 100dvh;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -105,10 +105,8 @@ export function MediaViewPlayer(props: MediaViewPlayerProps) {
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, [props.stream]);
|
}, [props.stream]);
|
||||||
|
|
||||||
// TODO show episode title
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="h-screen w-screen">
|
<div className="h-[100dvh] w-screen">
|
||||||
<Helmet>
|
<Helmet>
|
||||||
<title>{props.meta.meta.title}</title>
|
<title>{props.meta.meta.title}</title>
|
||||||
</Helmet>
|
</Helmet>
|
||||||
|
|
Loading…
Reference in a new issue