import { useRef, useLayoutEffect, useEffect, useState } from 'react' type Props = { id: string, width: number, height: number, style?: CSSProperties } import type { CSSProperties, FC } from 'react' export default ((props: Props) => { const { id, width, height, style = { } } = props const iframeRef = useRef (null) const [screenWidth, setScreenWidth] = useState () const [screenHeight, setScreenHeight] = useState () const [landscape, setLandscape] = useState (false) const [fullScreen, setFullScreen] = useState (false) const src = `https://embed.nicovideo.jp/watch/${id}?persistence=1&oldScript=1&referer=&from=0&allowProgrammaticFullScreen=1`; const styleFullScreen: CSSProperties = fullScreen ? { top: 0, left: landscape ? 0 : '100%', position: 'fixed', width: screenWidth, height: screenHeight, zIndex: 2147483647, maxWidth: 'none', transformOrigin: '0% 0%', transform: landscape ? 'none' : 'rotate(90deg)', WebkitTransformOrigin: '0% 0%', WebkitTransform: landscape ? 'none' : 'rotate(90deg)' } : {}; const margedStyle = { border: 'none', maxWidth: '100%', ...style, ...styleFullScreen } useEffect (() => { const onMessage = (event: MessageEvent) => { if (!(iframeRef.current) || (event.source !== iframeRef.current.contentWindow)) return if (event.data.eventName === 'enterProgrammaticFullScreen') setFullScreen (true) else if (event.data.eventName === 'exitProgrammaticFullScreen') setFullScreen (false) } addEventListener ('message', onMessage) return () => removeEventListener ('message', onMessage) }, []) useLayoutEffect(() => { if (!(fullScreen)) return const initialScrollX = scrollX const initialScrollY = scrollY let timer: NodeJS.Timeout let ended = false const pollingResize = () => { if (ended) return const landscape = innerWidth >= innerHeight const windowWidth = `${landscape ? innerWidth : innerHeight}px` const windowHeight = `${landscape ? innerHeight : innerWidth}px` setLandscape (landscape) setScreenWidth (windowWidth) setScreenHeight (windowHeight) timer = setTimeout (startPollingResize, 200) } const startPollingResize = () => { if (requestAnimationFrame) requestAnimationFrame (pollingResize) else pollingResize () } startPollingResize () return () => { clearTimeout (timer) ended = true scrollTo (initialScrollX, initialScrollY) } }, [fullScreen]) useEffect (() => { if (!(fullScreen)) return scrollTo (0, 0) }, [screenWidth, screenHeight, fullScreen]) return (