Skip to content

Commit

Permalink
MOAR
Browse files Browse the repository at this point in the history
  • Loading branch information
aeharding committed Dec 7, 2024
1 parent 7cd270a commit 528f013
Show file tree
Hide file tree
Showing 6 changed files with 99 additions and 4 deletions.
1 change: 1 addition & 0 deletions src/features/icons/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,4 @@ export { default as superscript } from "./svg/superscript.svg";
export { default as subscript } from "./svg/subscript.svg";
export { default as strikethrough } from "./svg/strikethrough.svg";
export { default as trashEllipse } from "./svg/trashEllipse.svg";
export { default as pip } from "./svg/pip.svg";
1 change: 1 addition & 0 deletions src/features/icons/svg/pip.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
38 changes: 38 additions & 0 deletions src/features/media/gallery/GalleryProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ interface IGalleryContext {
}

export const GalleryContext = createContext<IGalleryContext>({
// eslint-disable-next-line no-empty-function
open: async () => {},
close: noop,
});
Expand Down Expand Up @@ -70,6 +71,34 @@ export default function GalleryProvider({ children }: React.PropsWithChildren) {

const videoRef = useRef<HTMLVideoElement>(null);

const [wasPlayingBeforeScrub, setWasPlayingBeforeScrub] = useState(false);

const handleScrubStart = useCallback(() => {
if (videoRef.current) {
setWasPlayingBeforeScrub(!videoRef.current.paused);
videoRef.current.pause();
}
}, []);

const handleScrubEnd = useCallback(() => {
if (videoRef.current && wasPlayingBeforeScrub) {
videoRef.current.play();
}
}, [wasPlayingBeforeScrub]);

useEffect(() => {
const videoElement = videoRef.current;
if (!videoElement) return;

videoElement.addEventListener("scrubstart", handleScrubStart);
videoElement.addEventListener("scrubend", handleScrubEnd);

return () => {
videoElement.removeEventListener("scrubstart", handleScrubStart);
videoElement.removeEventListener("scrubend", handleScrubEnd);
};
}, [handleScrubStart, handleScrubEnd]);

useEffect(() => {
return () => {
lightboxRef.current?.destroy();
Expand Down Expand Up @@ -331,6 +360,14 @@ export default function GalleryProvider({ children }: React.PropsWithChildren) {
});
});

instance.on("verticalDrag", () => {
queueMicrotask(() => {
instance.pswp?.gestures.pswp.element?.classList.remove(
"pswp--ui-visible",
);
});
});

// -----------------------------
// Android back button logic start
const getHistoryState = () => {
Expand Down Expand Up @@ -478,6 +515,7 @@ export default function GalleryProvider({ children }: React.PropsWithChildren) {
controls={false}
progress={false}
volume={false}
allowShowPlayButton={false}
/>,
videoContainer,
)
Expand Down
5 changes: 4 additions & 1 deletion src/features/media/gallery/actions/VideoActions.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,13 @@

.buttons {
display: flex;
justify-content: center;
justify-content: space-between;

opacity: 0.8;
}

.range {
--bar-background: rgba(255, 255, 255, 0.3);
--knob-size: 18px;
--knob-background: #ccc;
}
54 changes: 52 additions & 2 deletions src/features/media/gallery/actions/VideoActions.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { IonButton, IonIcon, IonRange } from "@ionic/react";
import { play } from "ionicons/icons";
import { play, volumeHigh, volumeOff } from "ionicons/icons";
import { pause } from "ionicons/icons";
import React, {
useEffect,
Expand All @@ -8,6 +8,8 @@ import React, {
useState,
} from "react";

import { pip } from "#/features/icons";

import styles from "./VideoActions.module.css";

interface VideoActionsProps {
Expand Down Expand Up @@ -50,6 +52,8 @@ function VideoActions({ videoRef }: VideoActionsProps) {
const [isPlaying, setIsPlaying] = useState(false);
const [progress, setProgress] = useState(0);
const [isDragging, setIsDragging] = useState(false);
const [isMuted, setIsMuted] = useState(false);
const [wasPlayingBeforeScrub, setWasPlayingBeforeScrub] = useState(false);

useEffect(() => {
setupEvent();
Expand All @@ -60,6 +64,7 @@ function VideoActions({ videoRef }: VideoActionsProps) {
useEffect(() => {
if (videoRef.current) {
setIsPlaying(!videoRef.current.paused);
setIsMuted(videoRef.current.muted);
}
}, [videoRef]);

Expand All @@ -68,6 +73,7 @@ function VideoActions({ videoRef }: VideoActionsProps) {
videoRef.current.addEventListener("timeupdate", handleTimeUpdate);
videoRef.current.addEventListener("play", handlePlay);
videoRef.current.addEventListener("pause", handlePause);
videoRef.current.addEventListener("volumechange", handleVolumeChange);
}
}

Expand All @@ -76,6 +82,7 @@ function VideoActions({ videoRef }: VideoActionsProps) {
videoRef.current.removeEventListener("timeupdate", handleTimeUpdate);
videoRef.current.removeEventListener("play", handlePlay);
videoRef.current.removeEventListener("pause", handlePause);
videoRef.current.removeEventListener("volumechange", handleVolumeChange);
}
}

Expand All @@ -95,6 +102,10 @@ function VideoActions({ videoRef }: VideoActionsProps) {
setIsPlaying(false);
}

function handleVolumeChange() {
setIsMuted(videoRef.current?.muted ?? false);
}

function togglePlayPause() {
if (videoRef.current) {
if (isPlaying) {
Expand All @@ -106,11 +117,25 @@ function VideoActions({ videoRef }: VideoActionsProps) {
}
}

function toggleMute() {
if (videoRef.current) {
videoRef.current.muted = !isMuted;
setIsMuted(!isMuted);
}
}

function handleMouseDown() {
if (videoRef.current) {
setWasPlayingBeforeScrub(!videoRef.current.paused);
videoRef.current.pause();
}
setIsDragging(true);
}

function handleMouseUp() {
if (wasPlayingBeforeScrub && videoRef.current) {
videoRef.current.play();
}
setIsDragging(false);
}

Expand All @@ -128,10 +153,17 @@ function VideoActions({ videoRef }: VideoActionsProps) {
}

function handleTouchStart() {
if (videoRef.current) {
setWasPlayingBeforeScrub(!videoRef.current.paused);
videoRef.current.pause();
}
setIsDragging(true);
}

function handleTouchEnd() {
if (wasPlayingBeforeScrub && videoRef.current) {
videoRef.current.play();
}
setIsDragging(false);
}

Expand All @@ -149,14 +181,32 @@ function VideoActions({ videoRef }: VideoActionsProps) {
}
}

function requestPip() {
if (videoRef.current) {
videoRef.current.requestPictureInPicture();
}
}

return (
<div className={styles.container}>
<div className={styles.buttons}>
<IonButton fill="clear" color="dark" onClick={requestPip}>
<IonIcon size="large" slot="icon-only" icon={pip} />
</IonButton>
<div />
<IonButton fill="clear" color="dark" onClick={togglePlayPause}>
<IonIcon
size="large"
slot="icon-only"
icon={isPlaying ? pause : play}
icon={isPlaying || wasPlayingBeforeScrub ? pause : play}
/>
</IonButton>
<div />
<IonButton fill="clear" color="dark" onClick={toggleMute}>
<IonIcon
size="large"
slot="icon-only"
icon={isMuted ? volumeOff : volumeHigh}
/>
</IonButton>
</div>
Expand Down
4 changes: 3 additions & 1 deletion src/features/media/video/Player.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ export interface PlayerProps extends React.HTMLProps<HTMLElement> {
alt?: string;

pauseWhenNotInView?: boolean;
allowShowPlayButton?: boolean;

ref?: React.RefObject<HTMLVideoElement>;
videoRef?: React.RefObject<HTMLVideoElement>;
Expand All @@ -45,6 +46,7 @@ export default function Player({
volume = true,
autoPlay: videoAllowedToAutoplay = true,
pauseWhenNotInView = true,
allowShowPlayButton = true,
ref,
videoRef: _videoRef,
...rest
Expand Down Expand Up @@ -75,7 +77,7 @@ export default function Player({
});
const [progress, setProgress] = useState<number | undefined>(undefined);

const showBigPlayButton = userPaused && !playing;
const showBigPlayButton = userPaused && !playing && allowShowPlayButton;

const setRefs = useCallback(
(node: HTMLVideoElement) => {
Expand Down

0 comments on commit 528f013

Please sign in to comment.