上映会改修 (#302) #357
@@ -1,11 +1,11 @@
|
|||||||
import { forwardRef,
|
import { forwardRef,
|
||||||
useCallback,
|
useCallback,
|
||||||
useEffect,
|
useEffect,
|
||||||
useImperativeHandle,
|
useImperativeHandle,
|
||||||
useLayoutEffect,
|
useLayoutEffect,
|
||||||
useMemo,
|
useMemo,
|
||||||
useRef,
|
useRef,
|
||||||
useState } from 'react'
|
useState } from 'react'
|
||||||
|
|
||||||
import type { CSSProperties, ForwardedRef } from 'react'
|
import type { CSSProperties, ForwardedRef } from 'react'
|
||||||
|
|
||||||
@@ -15,19 +15,19 @@ type NiconicoPlayerMessage =
|
|||||||
| { eventName: 'enterProgrammaticFullScreen' }
|
| { eventName: 'enterProgrammaticFullScreen' }
|
||||||
| { eventName: 'exitProgrammaticFullScreen' }
|
| { eventName: 'exitProgrammaticFullScreen' }
|
||||||
| { eventName: 'loadComplete'
|
| { eventName: 'loadComplete'
|
||||||
playerId?: string
|
playerId?: string
|
||||||
data: { videoInfo: NiconicoVideoInfo } }
|
data: { videoInfo: NiconicoVideoInfo } }
|
||||||
| { eventName: 'playerMetadataChange'
|
| { eventName: 'playerMetadataChange'
|
||||||
playerId?: string
|
playerId?: string
|
||||||
data: NiconicoMetadata }
|
data: NiconicoMetadata }
|
||||||
| { eventName: 'playerStatusChange' | 'statusChange'
|
| { eventName: 'playerStatusChange' | 'statusChange'
|
||||||
playerId?: string
|
playerId?: string
|
||||||
data?: unknown }
|
data?: unknown }
|
||||||
| { eventName: 'error'
|
| { eventName: 'error'
|
||||||
playerId?: string
|
playerId?: string
|
||||||
data?: unknown
|
data?: unknown
|
||||||
code?: string
|
code?: string
|
||||||
message?: string }
|
message?: string }
|
||||||
|
|
||||||
type NiconicoCommand =
|
type NiconicoCommand =
|
||||||
| { eventName: 'play'; sourceConnectorType: 1; playerId: string }
|
| { eventName: 'play'; sourceConnectorType: 1; playerId: string }
|
||||||
@@ -53,13 +53,13 @@ type Props = {
|
|||||||
|
|
||||||
|
|
||||||
export default forwardRef ((props: Props, ref: ForwardedRef<NiconicoViewerHandle>) => {
|
export default forwardRef ((props: Props, ref: ForwardedRef<NiconicoViewerHandle>) => {
|
||||||
const { id, width, height, style = { }, onLoadComplete, onMetadataChange, onError } = props
|
const { id, width, height, style = { }, onLoadComplete, onMetadataChange, onError } = props
|
||||||
|
|
||||||
const iframeRef = useRef<HTMLIFrameElement> (null)
|
const iframeRef = useRef<HTMLIFrameElement> (null)
|
||||||
const loadCompleteTimerRef = useRef<ReturnType<typeof setTimeout> | null> (null)
|
const loadCompleteTimerRef = useRef<ReturnType<typeof setTimeout> | null> (null)
|
||||||
const playerId = useMemo (
|
const playerId = useMemo (
|
||||||
() => `nico-${ id }-${ Math.random ().toString (36).slice (2) }`,
|
() => `nico-${ id }-${ Math.random ().toString (36).slice (2) }`,
|
||||||
[id])
|
[id])
|
||||||
|
|
||||||
const [screenWidth, setScreenWidth] = useState<CSSProperties['width']> ()
|
const [screenWidth, setScreenWidth] = useState<CSSProperties['width']> ()
|
||||||
const [screenHeight, setScreenHeight] = useState<CSSProperties['height']> ()
|
const [screenHeight, setScreenHeight] = useState<CSSProperties['height']> ()
|
||||||
@@ -79,38 +79,38 @@ export default forwardRef ((props: Props, ref: ForwardedRef<NiconicoViewerHandle
|
|||||||
const styleFullScreen: CSSProperties =
|
const styleFullScreen: CSSProperties =
|
||||||
fullScreen
|
fullScreen
|
||||||
? { top: 0,
|
? { top: 0,
|
||||||
left: landscape ? 0 : '100%',
|
left: landscape ? 0 : '100%',
|
||||||
position: 'fixed',
|
position: 'fixed',
|
||||||
width: screenWidth,
|
width: screenWidth,
|
||||||
height: screenHeight,
|
height: screenHeight,
|
||||||
zIndex: 2_147_483_647,
|
zIndex: 2_147_483_647,
|
||||||
maxWidth: 'none',
|
maxWidth: 'none',
|
||||||
transformOrigin: '0% 0%',
|
transformOrigin: '0% 0%',
|
||||||
transform: landscape ? 'none' : 'rotate(90deg)',
|
transform: landscape ? 'none' : 'rotate(90deg)',
|
||||||
WebkitTransformOrigin: '0% 0%',
|
WebkitTransformOrigin: '0% 0%',
|
||||||
WebkitTransform: landscape ? 'none' : 'rotate(90deg)' }
|
WebkitTransform: landscape ? 'none' : 'rotate(90deg)' }
|
||||||
: { }
|
: { }
|
||||||
|
|
||||||
const margedStyle: CSSProperties =
|
const margedStyle: CSSProperties =
|
||||||
{ border: 'none', maxWidth: '100%', ...style, ...styleFullScreen }
|
{ border: 'none', maxWidth: '100%', ...style, ...styleFullScreen }
|
||||||
|
|
||||||
const clearLoadCompleteTimer = useCallback (() => {
|
const clearLoadCompleteTimer = useCallback (() => {
|
||||||
if (!(loadCompleteTimerRef.current))
|
if (!(loadCompleteTimerRef.current))
|
||||||
return
|
return
|
||||||
|
|
||||||
clearTimeout (loadCompleteTimerRef.current)
|
clearTimeout (loadCompleteTimerRef.current)
|
||||||
loadCompleteTimerRef.current = null
|
loadCompleteTimerRef.current = null
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
const startLoadCompleteTimer = useCallback (() => {
|
const startLoadCompleteTimer = useCallback (() => {
|
||||||
clearLoadCompleteTimer ()
|
clearLoadCompleteTimer ()
|
||||||
loadCompleteTimerRef.current = setTimeout (() => {
|
loadCompleteTimerRef.current = setTimeout (() => {
|
||||||
onError?.({
|
onError?.({
|
||||||
eventName: 'loadCompleteTimeout',
|
eventName: 'loadCompleteTimeout',
|
||||||
reason: 'niconico video length was not reported by embed',
|
reason: 'niconico video length was not reported by embed',
|
||||||
})
|
})
|
||||||
}, LOAD_COMPLETE_TIMEOUT_MS)
|
}, LOAD_COMPLETE_TIMEOUT_MS)
|
||||||
}, [clearLoadCompleteTimer, onError])
|
}, [clearLoadCompleteTimer, onError])
|
||||||
|
|
||||||
const postToPlayer = useCallback ((message: NiconicoCommand) => {
|
const postToPlayer = useCallback ((message: NiconicoCommand) => {
|
||||||
const win = iframeRef.current?.contentWindow
|
const win = iframeRef.current?.contentWindow
|
||||||
@@ -165,21 +165,21 @@ export default forwardRef ((props: Props, ref: ForwardedRef<NiconicoViewerHandle
|
|||||||
useEffect (() => {
|
useEffect (() => {
|
||||||
const onMessage = (event: MessageEvent<NiconicoPlayerMessage>) => {
|
const onMessage = (event: MessageEvent<NiconicoPlayerMessage>) => {
|
||||||
if (!(iframeRef.current)
|
if (!(iframeRef.current)
|
||||||
|| (event.source !== iframeRef.current.contentWindow)
|
|| (event.source !== iframeRef.current.contentWindow)
|
||||||
|| (event.origin !== EMBED_ORIGIN))
|
|| (event.origin !== EMBED_ORIGIN))
|
||||||
return
|
return
|
||||||
|
|
||||||
const data = event.data
|
const data = event.data
|
||||||
|
|
||||||
if (!(data)
|
if (!(data)
|
||||||
|| typeof data !== 'object'
|
|| typeof data !== 'object'
|
||||||
|| !('eventName' in data))
|
|| !('eventName' in data))
|
||||||
return
|
return
|
||||||
|
|
||||||
if (('playerId' in data)
|
if (('playerId' in data)
|
||||||
&& data.playerId
|
&& data.playerId
|
||||||
&& data.playerId !== playerId)
|
&& data.playerId !== playerId)
|
||||||
return
|
return
|
||||||
|
|
||||||
if (data.eventName === 'enterProgrammaticFullScreen')
|
if (data.eventName === 'enterProgrammaticFullScreen')
|
||||||
{
|
{
|
||||||
@@ -193,12 +193,12 @@ export default forwardRef ((props: Props, ref: ForwardedRef<NiconicoViewerHandle
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data.eventName === 'loadComplete')
|
if (data.eventName === 'loadComplete')
|
||||||
{
|
{
|
||||||
clearLoadCompleteTimer ()
|
clearLoadCompleteTimer ()
|
||||||
onLoadComplete?.(data.data.videoInfo)
|
onLoadComplete?.(data.data.videoInfo)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data.eventName === 'playerMetadataChange')
|
if (data.eventName === 'playerMetadataChange')
|
||||||
{
|
{
|
||||||
@@ -206,20 +206,20 @@ export default forwardRef ((props: Props, ref: ForwardedRef<NiconicoViewerHandle
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data.eventName === 'error')
|
if (data.eventName === 'error')
|
||||||
{
|
{
|
||||||
clearLoadCompleteTimer ()
|
clearLoadCompleteTimer ()
|
||||||
console.error ('niconico player error:', data)
|
console.error ('niconico player error:', data)
|
||||||
onError?.(data)
|
onError?.(data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
addEventListener ('message', onMessage)
|
addEventListener ('message', onMessage)
|
||||||
|
|
||||||
return () => removeEventListener ('message', onMessage)
|
return () => removeEventListener ('message', onMessage)
|
||||||
}, [clearLoadCompleteTimer, onError, onLoadComplete, onMetadataChange, playerId])
|
}, [clearLoadCompleteTimer, onError, onLoadComplete, onMetadataChange, playerId])
|
||||||
|
|
||||||
useEffect (() => clearLoadCompleteTimer, [clearLoadCompleteTimer])
|
useEffect (() => clearLoadCompleteTimer, [clearLoadCompleteTimer])
|
||||||
|
|
||||||
useLayoutEffect (() => {
|
useLayoutEffect (() => {
|
||||||
if (!(fullScreen))
|
if (!(fullScreen))
|
||||||
@@ -232,7 +232,7 @@ export default forwardRef ((props: Props, ref: ForwardedRef<NiconicoViewerHandle
|
|||||||
|
|
||||||
const pollingResize = () => {
|
const pollingResize = () => {
|
||||||
if (ended)
|
if (ended)
|
||||||
return
|
return
|
||||||
|
|
||||||
const isLandscape = innerWidth >= innerHeight
|
const isLandscape = innerWidth >= innerHeight
|
||||||
const windowWidth = `${ isLandscape ? innerWidth : innerHeight }px`
|
const windowWidth = `${ isLandscape ? innerWidth : innerHeight }px`
|
||||||
@@ -246,9 +246,9 @@ export default forwardRef ((props: Props, ref: ForwardedRef<NiconicoViewerHandle
|
|||||||
|
|
||||||
const startPollingResize = () => {
|
const startPollingResize = () => {
|
||||||
if (requestAnimationFrame)
|
if (requestAnimationFrame)
|
||||||
requestAnimationFrame (pollingResize)
|
requestAnimationFrame (pollingResize)
|
||||||
else
|
else
|
||||||
pollingResize ()
|
pollingResize ()
|
||||||
}
|
}
|
||||||
|
|
||||||
startPollingResize ()
|
startPollingResize ()
|
||||||
|
|||||||
新しい課題から参照
ユーザをブロックする