Remove async resizing from external embed player (#2936)
* remove debug adjust youtube shorts height fix webview style simplify styles fix resizing make it more clear remove async resizes from external player * remove comment * ts * reverse aspectzio/stable
parent
09eee05f8b
commit
fab6c286f4
|
@ -343,45 +343,45 @@ export function parseEmbedPlayerFromUrl(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getPlayerHeight({
|
export function getPlayerAspect({
|
||||||
type,
|
type,
|
||||||
width,
|
|
||||||
hasThumb,
|
hasThumb,
|
||||||
|
width,
|
||||||
}: {
|
}: {
|
||||||
type: EmbedPlayerParams['type']
|
type: EmbedPlayerParams['type']
|
||||||
width: number
|
|
||||||
hasThumb: boolean
|
hasThumb: boolean
|
||||||
}) {
|
width: number
|
||||||
if (!hasThumb) return (width / 16) * 9
|
}): {aspectRatio?: number; height?: number} {
|
||||||
|
if (!hasThumb) return {aspectRatio: 16 / 9}
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case 'youtube_video':
|
case 'youtube_video':
|
||||||
case 'twitch_video':
|
case 'twitch_video':
|
||||||
case 'vimeo_video':
|
case 'vimeo_video':
|
||||||
return (width / 16) * 9
|
return {aspectRatio: 16 / 9}
|
||||||
case 'youtube_short':
|
case 'youtube_short':
|
||||||
if (SCREEN_HEIGHT < 600) {
|
if (SCREEN_HEIGHT < 600) {
|
||||||
return ((width / 9) * 16) / 1.75
|
return {aspectRatio: (9 / 16) * 1.75}
|
||||||
} else {
|
} else {
|
||||||
return ((width / 9) * 16) / 1.5
|
return {aspectRatio: (9 / 16) * 1.5}
|
||||||
}
|
}
|
||||||
case 'spotify_album':
|
case 'spotify_album':
|
||||||
case 'apple_music_album':
|
case 'apple_music_album':
|
||||||
case 'apple_music_playlist':
|
case 'apple_music_playlist':
|
||||||
case 'spotify_playlist':
|
case 'spotify_playlist':
|
||||||
case 'soundcloud_set':
|
case 'soundcloud_set':
|
||||||
return 380
|
return {height: 380}
|
||||||
case 'spotify_song':
|
case 'spotify_song':
|
||||||
if (width <= 300) {
|
if (width <= 300) {
|
||||||
return 155
|
return {height: 155}
|
||||||
}
|
}
|
||||||
return 232
|
return {height: 232}
|
||||||
case 'soundcloud_track':
|
case 'soundcloud_track':
|
||||||
return 165
|
return {height: 165}
|
||||||
case 'apple_music_song':
|
case 'apple_music_song':
|
||||||
return 150
|
return {height: 150}
|
||||||
default:
|
default:
|
||||||
return width
|
return {aspectRatio: 16 / 9}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,14 @@
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import {View} from 'react-native'
|
import {View, ViewStyle} from 'react-native'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This utility function captures events and stops
|
* This utility function captures events and stops
|
||||||
* them from propagating upwards.
|
* them from propagating upwards.
|
||||||
*/
|
*/
|
||||||
export function EventStopper({children}: React.PropsWithChildren<{}>) {
|
export function EventStopper({
|
||||||
|
children,
|
||||||
|
style,
|
||||||
|
}: React.PropsWithChildren<{style?: ViewStyle | ViewStyle[]}>) {
|
||||||
const stop = (e: any) => {
|
const stop = (e: any) => {
|
||||||
e.stopPropagation()
|
e.stopPropagation()
|
||||||
}
|
}
|
||||||
|
@ -15,7 +18,8 @@ export function EventStopper({children}: React.PropsWithChildren<{}>) {
|
||||||
onTouchEnd={stop}
|
onTouchEnd={stop}
|
||||||
// @ts-ignore web only -prf
|
// @ts-ignore web only -prf
|
||||||
onClick={stop}
|
onClick={stop}
|
||||||
onKeyDown={stop}>
|
onKeyDown={stop}
|
||||||
|
style={style}>
|
||||||
{children}
|
{children}
|
||||||
</View>
|
</View>
|
||||||
)
|
)
|
||||||
|
|
|
@ -21,7 +21,7 @@ import {msg} from '@lingui/macro'
|
||||||
import {useLingui} from '@lingui/react'
|
import {useLingui} from '@lingui/react'
|
||||||
import {useNavigation} from '@react-navigation/native'
|
import {useNavigation} from '@react-navigation/native'
|
||||||
import {AppBskyEmbedExternal} from '@atproto/api'
|
import {AppBskyEmbedExternal} from '@atproto/api'
|
||||||
import {EmbedPlayerParams, getPlayerHeight} from 'lib/strings/embed-player'
|
import {EmbedPlayerParams, getPlayerAspect} from 'lib/strings/embed-player'
|
||||||
import {EventStopper} from '../EventStopper'
|
import {EventStopper} from '../EventStopper'
|
||||||
import {isNative} from 'platform/detection'
|
import {isNative} from 'platform/detection'
|
||||||
import {NavigationProp} from 'lib/routes/types'
|
import {NavigationProp} from 'lib/routes/types'
|
||||||
|
@ -67,14 +67,12 @@ function PlaceholderOverlay({
|
||||||
|
|
||||||
// This renders the webview/youtube player as a separate layer
|
// This renders the webview/youtube player as a separate layer
|
||||||
function Player({
|
function Player({
|
||||||
height,
|
|
||||||
params,
|
params,
|
||||||
onLoad,
|
onLoad,
|
||||||
isPlayerActive,
|
isPlayerActive,
|
||||||
}: {
|
}: {
|
||||||
isPlayerActive: boolean
|
isPlayerActive: boolean
|
||||||
params: EmbedPlayerParams
|
params: EmbedPlayerParams
|
||||||
height: number
|
|
||||||
onLoad: () => void
|
onLoad: () => void
|
||||||
}) {
|
}) {
|
||||||
// ensures we only load what's requested
|
// ensures we only load what's requested
|
||||||
|
@ -91,25 +89,21 @@ function Player({
|
||||||
if (!isPlayerActive) return null
|
if (!isPlayerActive) return null
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={[styles.layer, styles.playerLayer]}>
|
<EventStopper style={[styles.layer, styles.playerLayer]}>
|
||||||
<EventStopper>
|
<WebView
|
||||||
<View style={{height, width: '100%'}}>
|
javaScriptEnabled={true}
|
||||||
<WebView
|
onShouldStartLoadWithRequest={onShouldStartLoadWithRequest}
|
||||||
javaScriptEnabled={true}
|
mediaPlaybackRequiresUserAction={false}
|
||||||
onShouldStartLoadWithRequest={onShouldStartLoadWithRequest}
|
allowsInlineMediaPlayback
|
||||||
mediaPlaybackRequiresUserAction={false}
|
bounces={false}
|
||||||
allowsInlineMediaPlayback
|
allowsFullscreenVideo
|
||||||
bounces={false}
|
nestedScrollEnabled
|
||||||
allowsFullscreenVideo
|
source={{uri: params.playerUri}}
|
||||||
nestedScrollEnabled
|
onLoad={onLoad}
|
||||||
source={{uri: params.playerUri}}
|
style={styles.webview}
|
||||||
onLoad={onLoad}
|
setSupportMultipleWindows={false} // Prevent any redirects from opening a new window (ads)
|
||||||
setSupportMultipleWindows={false} // Prevent any redirects from opening a new window (ads)
|
/>
|
||||||
style={[styles.webview, styles.topRadius]}
|
</EventStopper>
|
||||||
/>
|
|
||||||
</View>
|
|
||||||
</EventStopper>
|
|
||||||
</View>
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -129,13 +123,16 @@ export function ExternalPlayer({
|
||||||
|
|
||||||
const [isPlayerActive, setPlayerActive] = React.useState(false)
|
const [isPlayerActive, setPlayerActive] = React.useState(false)
|
||||||
const [isLoading, setIsLoading] = React.useState(true)
|
const [isLoading, setIsLoading] = React.useState(true)
|
||||||
const [dim, setDim] = React.useState({
|
|
||||||
width: 0,
|
const aspect = React.useMemo(() => {
|
||||||
height: 0,
|
return getPlayerAspect({
|
||||||
})
|
type: params.type,
|
||||||
|
width: windowDims.width,
|
||||||
|
hasThumb: !!link.thumb,
|
||||||
|
})
|
||||||
|
}, [params.type, windowDims.width, link.thumb])
|
||||||
|
|
||||||
const viewRef = useAnimatedRef()
|
const viewRef = useAnimatedRef()
|
||||||
|
|
||||||
const frameCallback = useFrameCallback(() => {
|
const frameCallback = useFrameCallback(() => {
|
||||||
const measurement = measure(viewRef)
|
const measurement = measure(viewRef)
|
||||||
if (!measurement) return
|
if (!measurement) return
|
||||||
|
@ -180,17 +177,6 @@ export function ExternalPlayer({
|
||||||
}
|
}
|
||||||
}, [navigation, isPlayerActive, frameCallback])
|
}, [navigation, isPlayerActive, frameCallback])
|
||||||
|
|
||||||
// calculate height for the player and the screen size
|
|
||||||
const height = React.useMemo(
|
|
||||||
() =>
|
|
||||||
getPlayerHeight({
|
|
||||||
type: params.type,
|
|
||||||
width: dim.width,
|
|
||||||
hasThumb: !!link.thumb,
|
|
||||||
}),
|
|
||||||
[params.type, dim.width, link.thumb],
|
|
||||||
)
|
|
||||||
|
|
||||||
const onLoad = React.useCallback(() => {
|
const onLoad = React.useCallback(() => {
|
||||||
setIsLoading(false)
|
setIsLoading(false)
|
||||||
}, [])
|
}, [])
|
||||||
|
@ -216,32 +202,11 @@ export function ExternalPlayer({
|
||||||
[externalEmbedsPrefs, openModal, params.source],
|
[externalEmbedsPrefs, openModal, params.source],
|
||||||
)
|
)
|
||||||
|
|
||||||
// measure the layout to set sizing
|
|
||||||
const onLayout = React.useCallback(
|
|
||||||
(event: {nativeEvent: {layout: {width: any; height: any}}}) => {
|
|
||||||
setDim({
|
|
||||||
width: event.nativeEvent.layout.width,
|
|
||||||
height: event.nativeEvent.layout.height,
|
|
||||||
})
|
|
||||||
},
|
|
||||||
[],
|
|
||||||
)
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Animated.View
|
<Animated.View ref={viewRef} collapsable={false} style={[aspect]}>
|
||||||
ref={viewRef}
|
|
||||||
style={{height}}
|
|
||||||
collapsable={false}
|
|
||||||
onLayout={onLayout}>
|
|
||||||
{link.thumb && (!isPlayerActive || isLoading) && (
|
{link.thumb && (!isPlayerActive || isLoading) && (
|
||||||
<Image
|
<Image
|
||||||
style={[
|
style={[{flex: 1}, styles.topRadius]}
|
||||||
{
|
|
||||||
width: dim.width,
|
|
||||||
height,
|
|
||||||
},
|
|
||||||
styles.topRadius,
|
|
||||||
]}
|
|
||||||
source={{uri: link.thumb}}
|
source={{uri: link.thumb}}
|
||||||
accessibilityIgnoresInvertColors
|
accessibilityIgnoresInvertColors
|
||||||
/>
|
/>
|
||||||
|
@ -251,12 +216,7 @@ export function ExternalPlayer({
|
||||||
isPlayerActive={isPlayerActive}
|
isPlayerActive={isPlayerActive}
|
||||||
onPress={onPlayPress}
|
onPress={onPlayPress}
|
||||||
/>
|
/>
|
||||||
<Player
|
<Player isPlayerActive={isPlayerActive} params={params} onLoad={onLoad} />
|
||||||
isPlayerActive={isPlayerActive}
|
|
||||||
params={params}
|
|
||||||
height={height}
|
|
||||||
onLoad={onLoad}
|
|
||||||
/>
|
|
||||||
</Animated.View>
|
</Animated.View>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue