gif content filtering and safari fixes
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import {ViewProps} from 'react-native'
|
||||
import {type ViewProps} from 'react-native'
|
||||
|
||||
export interface GifViewStateChangeEvent {
|
||||
nativeEvent: {
|
||||
@@ -10,6 +10,12 @@ export interface GifViewStateChangeEvent {
|
||||
export interface GifViewProps extends ViewProps {
|
||||
autoplay?: boolean
|
||||
source?: string
|
||||
/**
|
||||
* Web-only ordered list of `<source>` tags rendered inside `<video>`. The
|
||||
* browser uses `canPlayType` to pick the first one it supports. Ignored on
|
||||
* native (which uses `source` directly).
|
||||
*/
|
||||
sources?: ReadonlyArray<{src: string; type: string}>
|
||||
placeholderSource?: string
|
||||
onPlayerStateChange?: (event: GifViewStateChangeEvent) => void
|
||||
}
|
||||
|
||||
@@ -1,17 +1,20 @@
|
||||
import * as React from 'react'
|
||||
import {createRef, PureComponent, type RefObject} from 'react'
|
||||
import {StyleSheet} from 'react-native'
|
||||
|
||||
import {GifViewProps} from './GifView.types'
|
||||
import {type GifViewProps} from './GifView.types'
|
||||
|
||||
export class GifView extends React.PureComponent<GifViewProps> {
|
||||
private readonly videoPlayerRef: React.RefObject<HTMLMediaElement> =
|
||||
React.createRef()
|
||||
export class GifView extends PureComponent<GifViewProps> {
|
||||
private readonly videoPlayerRef: RefObject<HTMLMediaElement> = createRef()
|
||||
private isLoaded = false
|
||||
|
||||
constructor(props: GifViewProps | Readonly<GifViewProps>) {
|
||||
super(props)
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
document.addEventListener('visibilitychange', this.onVisibilityChange)
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps: Readonly<GifViewProps>) {
|
||||
if (prevProps.autoplay !== this.props.autoplay) {
|
||||
if (this.props.autoplay) {
|
||||
@@ -22,10 +25,28 @@ export class GifView extends React.PureComponent<GifViewProps> {
|
||||
}
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
document.removeEventListener('visibilitychange', this.onVisibilityChange)
|
||||
}
|
||||
|
||||
static async prefetchAsync(_: string[]): Promise<void> {
|
||||
console.warn('prefetchAsync is not supported on web')
|
||||
}
|
||||
|
||||
// Safari pauses backgrounded `<video>` elements when the tab becomes
|
||||
// inactive and does not resume them automatically when the tab is shown
|
||||
// again, leaving GIFs frozen on a still frame. Resume playback when the
|
||||
// page becomes visible if the consumer expects autoplay.
|
||||
private onVisibilityChange = () => {
|
||||
if (
|
||||
document.visibilityState === 'visible' &&
|
||||
this.props.autoplay &&
|
||||
this.videoPlayerRef.current?.paused
|
||||
) {
|
||||
void this.playAsync()
|
||||
}
|
||||
}
|
||||
|
||||
private firePlayerStateChangeEvent = () => {
|
||||
this.props.onPlayerStateChange?.({
|
||||
nativeEvent: {
|
||||
@@ -62,21 +83,29 @@ export class GifView extends React.PureComponent<GifViewProps> {
|
||||
}
|
||||
|
||||
render() {
|
||||
const {sources, source, autoplay, accessibilityLabel, style} = this.props
|
||||
const useSources = sources && sources.length > 0
|
||||
|
||||
return (
|
||||
<video
|
||||
src={this.props.source}
|
||||
autoPlay={this.props.autoplay ? 'autoplay' : undefined}
|
||||
preload={this.props.autoplay ? 'auto' : undefined}
|
||||
// When `<source>` children are present, omit `src` so the browser
|
||||
// walks the source list and picks via canPlayType.
|
||||
src={useSources ? undefined : source}
|
||||
autoPlay={autoplay ? 'autoplay' : undefined}
|
||||
preload={autoplay ? 'auto' : undefined}
|
||||
playsInline={true}
|
||||
loop="loop"
|
||||
muted="muted"
|
||||
style={StyleSheet.flatten(this.props.style)}
|
||||
style={StyleSheet.flatten(style)}
|
||||
onCanPlay={this.onLoad}
|
||||
onPlay={this.firePlayerStateChangeEvent}
|
||||
onPause={this.firePlayerStateChangeEvent}
|
||||
aria-label={this.props.accessibilityLabel}
|
||||
ref={this.videoPlayerRef}
|
||||
/>
|
||||
aria-label={accessibilityLabel}
|
||||
ref={this.videoPlayerRef}>
|
||||
{useSources
|
||||
? sources.map(s => <source key={s.src} src={s.src} type={s.type} />)
|
||||
: null}
|
||||
</video>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user