Gif panel for VideoViewer
This commit is contained in:
parent
793f051925
commit
c0d9622bec
|
@ -8,5 +8,10 @@
|
|||
"size": "Size",
|
||||
"untitled": "-",
|
||||
"download": "Download File",
|
||||
"source": "View Original"
|
||||
"source": "View Original",
|
||||
"gif": {
|
||||
"alt": "Animated GIF image of the video",
|
||||
"load": "Loading GIF image...",
|
||||
"loadError": "Sorry, we could not open this image!"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,17 +1,20 @@
|
|||
import React, { useContext, useRef, useLayoutEffect, useMemo } from "react";
|
||||
import React, { useContext, useRef, useLayoutEffect, useMemo, useCallback } from "react";
|
||||
import { VideoViewerProps, VideoViewerClassNameContract } from "./VideoViewer.props";
|
||||
import { DesignSystem } from "@microsoft/fast-components-styles-msft";
|
||||
import manageJss, { ComponentStyles } from "@microsoft/fast-jss-manager-react";
|
||||
import { headerHeight } from "../../../_DesignSystem";
|
||||
import { headerHeight, TabViewer, toast } from "../../../_DesignSystem";
|
||||
import { ThumbnailContext, ssrContainer } from "../ThumbnailViewer/ThumbnailViewer";
|
||||
import { SidebarData } from "../FVSidebar/FVSidebarContext";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { TabPanel } from "../../../_DesignSystem/Tabs/TabViewer/TabViewer.props";
|
||||
import tabEventEmitter from "../../../_DesignSystem/Tabs/TabEvents";
|
||||
|
||||
const styles: ComponentStyles<VideoViewerClassNameContract, DesignSystem> = {
|
||||
videoViewer: {
|
||||
position: "absolute",
|
||||
top: "64px",
|
||||
transition: "width .15s",
|
||||
"& video": {
|
||||
"& video, & img": {
|
||||
width: "100%",
|
||||
height: "100%",
|
||||
objectFit: "scale-down",
|
||||
|
@ -42,6 +45,7 @@ const VideoViewer: React.ComponentType<VideoViewerProps> = ({
|
|||
viewportWidth: originalViewportWidth,
|
||||
viewportHeight,
|
||||
} = useContext(ThumbnailContext);
|
||||
const { t } = useTranslation("fileview");
|
||||
|
||||
// Sidebar data for viewport calculations
|
||||
const { debouncedSidebarPos } = useContext(SidebarData);
|
||||
|
@ -55,6 +59,11 @@ const VideoViewer: React.ComponentType<VideoViewerProps> = ({
|
|||
*/
|
||||
const videoRef = useRef<HTMLVideoElement>(null);
|
||||
|
||||
/**
|
||||
* React.ref of the gif container
|
||||
*/
|
||||
const imgRef = useRef<HTMLImageElement>(null);
|
||||
|
||||
/**
|
||||
* Listen to the finishing of the thumbnail animation.
|
||||
* Load the high-res image afterwards and hide the thumbnail.
|
||||
|
@ -89,6 +98,54 @@ const VideoViewer: React.ComponentType<VideoViewerProps> = ({
|
|||
setThumbnailVisibility,
|
||||
]);
|
||||
|
||||
const onGifAppear = useCallback(() => {
|
||||
const imgEl = imgRef.current;
|
||||
if (imgEl && !imgEl.src) {
|
||||
let toastScheduler: number = null;
|
||||
let toastId: React.ReactText = null;
|
||||
|
||||
const removeListeners = () => {
|
||||
imgEl.onerror = () => {};
|
||||
imgEl.onload = () => {};
|
||||
};
|
||||
|
||||
const removeScheduledToast = () => {
|
||||
clearTimeout(toastScheduler);
|
||||
if (toastId) toast.dismiss(toastId);
|
||||
return true;
|
||||
};
|
||||
|
||||
imgEl.onerror = () => {
|
||||
removeScheduledToast();
|
||||
imgEl.style.display = "none";
|
||||
toast.error(t("gif.loadError"), "", { autoClose: 10000 });
|
||||
tabEventEmitter.emit("video-gif-update", "video");
|
||||
removeListeners();
|
||||
imgEl.src = "";
|
||||
};
|
||||
|
||||
imgEl.onload = () => removeScheduledToast() && removeListeners();
|
||||
|
||||
toastScheduler = setTimeout(() => {
|
||||
toastId = toast.info(t("gif.load"), "", { progress: 0 });
|
||||
}, 500) as any;
|
||||
|
||||
imgEl.src = `${window.location.origin}/${id}.gif`;
|
||||
}
|
||||
}, [id, t]);
|
||||
|
||||
const tabContentItems: TabPanel[] = useMemo(
|
||||
() => [
|
||||
{ id: "video", children: <video muted autoPlay loop ref={videoRef} /> },
|
||||
{
|
||||
id: "gif",
|
||||
children: <img alt={t("gif.alt")} ref={imgRef} />,
|
||||
onLoad: onGifAppear,
|
||||
},
|
||||
],
|
||||
[onGifAppear, t]
|
||||
);
|
||||
|
||||
return (
|
||||
<div
|
||||
className={managedClasses.videoViewer}
|
||||
|
@ -99,7 +156,7 @@ const VideoViewer: React.ComponentType<VideoViewerProps> = ({
|
|||
height: viewportHeight,
|
||||
}}
|
||||
>
|
||||
<video muted autoPlay loop ref={videoRef} />
|
||||
<TabViewer id="video-gif" items={tabContentItems} />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue