80 lines
No EOL
2.4 KiB
TypeScript
80 lines
No EOL
2.4 KiB
TypeScript
import { Typography, styled } from '@mui/material';
|
|
import React from 'react';
|
|
import { Document, makeThumbnailUrl } from '../../accessor/document';
|
|
import {ComicReader} from './comic';
|
|
import {VideoReader} from './video'
|
|
|
|
export interface PagePresenterProp{
|
|
doc:Document,
|
|
className?:string
|
|
}
|
|
interface PagePresenter{
|
|
(prop:PagePresenterProp):JSX.Element
|
|
}
|
|
|
|
export const getPresenter = (content:Document):PagePresenter => {
|
|
switch (content.content_type) {
|
|
case "comic":
|
|
return ComicReader;
|
|
case "video":
|
|
return VideoReader;
|
|
}
|
|
return ()=><Typography variant='h2'>Not implemented reader</Typography>;
|
|
}
|
|
const BackgroundDiv = styled("div")({
|
|
height: '400px',
|
|
width:'300px',
|
|
backgroundColor:"#272733",
|
|
display:"flex",
|
|
alignItems:"center",
|
|
justifyContent:"center"}
|
|
);
|
|
|
|
|
|
import { useRef, useState, useEffect } from 'react';
|
|
import "./thumbnail.css"
|
|
|
|
export function useIsElementInViewport<T extends HTMLElement>(options?: IntersectionObserverInit) {
|
|
const elementRef = useRef<T>(null);
|
|
const [isVisible, setIsVisible] = useState(false);
|
|
|
|
const callback = (entries: IntersectionObserverEntry[]) => {
|
|
const [entry] = entries;
|
|
setIsVisible(entry.isIntersecting);
|
|
};
|
|
|
|
useEffect(() => {
|
|
const observer = new IntersectionObserver(callback, options);
|
|
elementRef.current && observer.observe(elementRef.current);
|
|
return () => observer.disconnect();
|
|
}, [elementRef, options]);
|
|
|
|
return { elementRef, isVisible };
|
|
};
|
|
|
|
export function ThumbnailContainer(props:{
|
|
content:Document,
|
|
className?:string,
|
|
}){
|
|
const {elementRef, isVisible} = useIsElementInViewport<HTMLDivElement>({});
|
|
const [loaded, setLoaded] = useState(false);
|
|
useEffect(()=>{
|
|
if(isVisible){
|
|
setLoaded(true);
|
|
}
|
|
},[isVisible])
|
|
const style = {
|
|
maxHeight: '400px',
|
|
maxWidth: 'min(400px, 100vw)',
|
|
};
|
|
const thumbnailurl = makeThumbnailUrl(props.content);
|
|
if(props.content.content_type === "video"){
|
|
return (<video src={thumbnailurl} muted autoPlay loop className={props.className} style={style}></video>)
|
|
}
|
|
else return (<BackgroundDiv ref={elementRef}>
|
|
{loaded && <img src={thumbnailurl}
|
|
className={props.className + " thumbnail_img"}
|
|
|
|
loading="lazy"></img>}
|
|
</BackgroundDiv>)
|
|
} |