Create new AltBadgeWithDialog component and match other badge styles
This commit is contained in:
@@ -0,0 +1,93 @@
|
|||||||
|
import {Pressable} from 'react-native'
|
||||||
|
import {Trans, useLingui} from '@lingui/react/macro'
|
||||||
|
|
||||||
|
import {HITSLOP_20} from '#/lib/constants'
|
||||||
|
import {useLargeAltBadgeEnabled} from '#/state/preferences/large-alt-badge'
|
||||||
|
import {atoms as a, useTheme} from '#/alf'
|
||||||
|
import * as Prompt from '#/components/Prompt'
|
||||||
|
import {Text} from '#/components/Typography'
|
||||||
|
|
||||||
|
const positionStyles = {
|
||||||
|
'top-left': {
|
||||||
|
top: a.p_xs.padding,
|
||||||
|
left: a.p_xs.padding,
|
||||||
|
},
|
||||||
|
'top-right': {
|
||||||
|
top: a.p_xs.padding,
|
||||||
|
right: a.p_xs.padding,
|
||||||
|
},
|
||||||
|
'bottom-left': {
|
||||||
|
bottom: a.p_xs.padding,
|
||||||
|
left: a.p_xs.padding,
|
||||||
|
},
|
||||||
|
'bottom-right': {
|
||||||
|
bottom: a.p_xs.padding,
|
||||||
|
right: a.p_xs.padding,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
export function AltBadgeWithDialog({
|
||||||
|
text,
|
||||||
|
position,
|
||||||
|
}: {
|
||||||
|
text: string
|
||||||
|
position?: 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right'
|
||||||
|
}) {
|
||||||
|
const t = useTheme()
|
||||||
|
const {t: l} = useLingui()
|
||||||
|
const large = useLargeAltBadgeEnabled()
|
||||||
|
const control = Prompt.usePromptControl()
|
||||||
|
|
||||||
|
const pos = position ? [a.absolute, positionStyles[position]] : {}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Pressable
|
||||||
|
testID="altBadgeWithDialogButton"
|
||||||
|
accessibilityRole="button"
|
||||||
|
accessibilityLabel={l`Show alt text`}
|
||||||
|
accessibilityHint=""
|
||||||
|
hitSlop={HITSLOP_20}
|
||||||
|
onPress={control.open}
|
||||||
|
style={s => [
|
||||||
|
a.justify_center,
|
||||||
|
a.rounded_sm,
|
||||||
|
a.p_xs,
|
||||||
|
a.z_10,
|
||||||
|
t.atoms.bg_contrast_25,
|
||||||
|
large && {
|
||||||
|
padding: 6,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
opacity: 0.8,
|
||||||
|
},
|
||||||
|
pos,
|
||||||
|
s.hovered || s.pressed
|
||||||
|
? [
|
||||||
|
{
|
||||||
|
opacity: 1,
|
||||||
|
},
|
||||||
|
]
|
||||||
|
: [],
|
||||||
|
]}>
|
||||||
|
<Text
|
||||||
|
accessible={false}
|
||||||
|
style={[a.font_bold, large ? a.text_xs : {fontSize: 8}]}>
|
||||||
|
<Trans>ALT</Trans>
|
||||||
|
</Text>
|
||||||
|
</Pressable>
|
||||||
|
|
||||||
|
<Prompt.Outer control={control}>
|
||||||
|
<Prompt.Content>
|
||||||
|
<Prompt.TitleText>
|
||||||
|
<Trans>Alt Text</Trans>
|
||||||
|
</Prompt.TitleText>
|
||||||
|
<Prompt.DescriptionText selectable>{text}</Prompt.DescriptionText>
|
||||||
|
</Prompt.Content>
|
||||||
|
<Prompt.Actions>
|
||||||
|
<Prompt.Cancel cta={l`Close`} />
|
||||||
|
</Prompt.Actions>
|
||||||
|
</Prompt.Outer>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -1,18 +1,13 @@
|
|||||||
import {
|
import {ActivityIndicator, View} from 'react-native'
|
||||||
ActivityIndicator,
|
|
||||||
StyleSheet,
|
|
||||||
TouchableOpacity,
|
|
||||||
View,
|
|
||||||
} from 'react-native'
|
|
||||||
import {msg} from '@lingui/core/macro'
|
import {msg} from '@lingui/core/macro'
|
||||||
import {useLingui} from '@lingui/react'
|
import {useLingui} from '@lingui/react'
|
||||||
import {Trans} from '@lingui/react/macro'
|
import {Trans} from '@lingui/react/macro'
|
||||||
|
|
||||||
import {HITSLOP_20} from '#/lib/constants'
|
import {useLargeAltBadgeEnabled} from '#/state/preferences/large-alt-badge'
|
||||||
import {atoms as a, useTheme} from '#/alf'
|
import {atoms as a, useTheme} from '#/alf'
|
||||||
|
import {AltBadgeWithDialog} from '#/components/AltBadgeWithDialog'
|
||||||
import {Button} from '#/components/Button'
|
import {Button} from '#/components/Button'
|
||||||
import {Fill} from '#/components/Fill'
|
import {Fill} from '#/components/Fill'
|
||||||
import * as Prompt from '#/components/Prompt'
|
|
||||||
import {Text} from '#/components/Typography'
|
import {Text} from '#/components/Typography'
|
||||||
import {PlayButtonIcon} from '#/components/video/PlayButtonIcon'
|
import {PlayButtonIcon} from '#/components/video/PlayButtonIcon'
|
||||||
|
|
||||||
@@ -29,6 +24,7 @@ export function GifPresentationControls({
|
|||||||
}) {
|
}) {
|
||||||
const {_} = useLingui()
|
const {_} = useLingui()
|
||||||
const t = useTheme()
|
const t = useTheme()
|
||||||
|
const largeBadge = useLargeAltBadgeEnabled()
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@@ -64,74 +60,41 @@ export function GifPresentationControls({
|
|||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
<View style={styles.gifBadgeContainer}>
|
<View
|
||||||
<Text style={[{color: 'white'}, a.font_bold, a.text_xs]}>
|
style={[
|
||||||
|
a.absolute,
|
||||||
|
a.flex_row,
|
||||||
|
a.z_10,
|
||||||
|
{
|
||||||
|
bottom: a.p_xs.padding,
|
||||||
|
right: a.p_xs.padding,
|
||||||
|
gap: 3,
|
||||||
|
},
|
||||||
|
largeBadge && {
|
||||||
|
gap: 4,
|
||||||
|
},
|
||||||
|
]}>
|
||||||
|
<View
|
||||||
|
accessible={false}
|
||||||
|
style={[
|
||||||
|
a.justify_center,
|
||||||
|
a.rounded_sm,
|
||||||
|
a.p_xs,
|
||||||
|
a.z_10,
|
||||||
|
t.atoms.bg_contrast_25,
|
||||||
|
largeBadge && {
|
||||||
|
padding: 6,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
opacity: 0.8,
|
||||||
|
},
|
||||||
|
]}>
|
||||||
|
<Text style={[a.font_bold, largeBadge ? a.text_xs : {fontSize: 8}]}>
|
||||||
<Trans>GIF</Trans>
|
<Trans>GIF</Trans>
|
||||||
</Text>
|
</Text>
|
||||||
</View>
|
</View>
|
||||||
{altText && <AltBadge text={altText} />}
|
{altText && <AltBadgeWithDialog text={altText} />}
|
||||||
|
</View>
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function AltBadge({text}: {text: string}) {
|
|
||||||
const control = Prompt.usePromptControl()
|
|
||||||
const {_} = useLingui()
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<TouchableOpacity
|
|
||||||
testID="altTextButton"
|
|
||||||
accessibilityRole="button"
|
|
||||||
accessibilityLabel={_(msg`Show alt text`)}
|
|
||||||
accessibilityHint=""
|
|
||||||
hitSlop={HITSLOP_20}
|
|
||||||
onPress={control.open}
|
|
||||||
style={styles.altBadgeContainer}>
|
|
||||||
<Text
|
|
||||||
style={[{color: 'white'}, a.font_bold, a.text_xs]}
|
|
||||||
accessible={false}>
|
|
||||||
<Trans>ALT</Trans>
|
|
||||||
</Text>
|
|
||||||
</TouchableOpacity>
|
|
||||||
<Prompt.Outer control={control}>
|
|
||||||
<Prompt.Content>
|
|
||||||
<Prompt.TitleText>
|
|
||||||
<Trans>Alt Text</Trans>
|
|
||||||
</Prompt.TitleText>
|
|
||||||
<Prompt.DescriptionText selectable>{text}</Prompt.DescriptionText>
|
|
||||||
</Prompt.Content>
|
|
||||||
<Prompt.Actions>
|
|
||||||
<Prompt.Action
|
|
||||||
onPress={() => control.close()}
|
|
||||||
cta={_(msg`Close`)}
|
|
||||||
color="secondary"
|
|
||||||
/>
|
|
||||||
</Prompt.Actions>
|
|
||||||
</Prompt.Outer>
|
|
||||||
</>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
|
||||||
gifBadgeContainer: {
|
|
||||||
backgroundColor: 'rgba(0, 0, 0, 0.75)',
|
|
||||||
borderRadius: 6,
|
|
||||||
paddingHorizontal: 4,
|
|
||||||
paddingVertical: 3,
|
|
||||||
position: 'absolute',
|
|
||||||
left: 6,
|
|
||||||
bottom: 6,
|
|
||||||
zIndex: 2,
|
|
||||||
},
|
|
||||||
altBadgeContainer: {
|
|
||||||
backgroundColor: 'rgba(0, 0, 0, 0.75)',
|
|
||||||
borderRadius: 6,
|
|
||||||
paddingHorizontal: 4,
|
|
||||||
paddingVertical: 3,
|
|
||||||
position: 'absolute',
|
|
||||||
right: 6,
|
|
||||||
top: 6,
|
|
||||||
zIndex: 2,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import {useLingui} from '@lingui/react'
|
|||||||
import {HITSLOP_30} from '#/lib/constants'
|
import {HITSLOP_30} from '#/lib/constants'
|
||||||
import {useAutoplayDisabled} from '#/state/preferences'
|
import {useAutoplayDisabled} from '#/state/preferences'
|
||||||
import {atoms as a, useTheme} from '#/alf'
|
import {atoms as a, useTheme} from '#/alf'
|
||||||
|
import {AltBadgeWithDialog} from '#/components/AltBadgeWithDialog'
|
||||||
import {useIsWithinMessage} from '#/components/dms/MessageContext'
|
import {useIsWithinMessage} from '#/components/dms/MessageContext'
|
||||||
import {Mute_Stroke2_Corner0_Rounded as MuteIcon} from '#/components/icons/Mute'
|
import {Mute_Stroke2_Corner0_Rounded as MuteIcon} from '#/components/icons/Mute'
|
||||||
import {Pause_Filled_Corner0_Rounded as PauseIcon} from '#/components/icons/Pause'
|
import {Pause_Filled_Corner0_Rounded as PauseIcon} from '#/components/icons/Pause'
|
||||||
@@ -16,7 +17,7 @@ import {SpeakerVolumeFull_Stroke2_Corner0_Rounded as UnmuteIcon} from '#/compone
|
|||||||
import {KeepAwake} from '#/components/KeepAwake'
|
import {KeepAwake} from '#/components/KeepAwake'
|
||||||
import {MediaInsetBorder} from '#/components/MediaInsetBorder'
|
import {MediaInsetBorder} from '#/components/MediaInsetBorder'
|
||||||
import {useVideoMuteState} from '#/components/Post/Embed/VideoEmbed/VideoVolumeContext'
|
import {useVideoMuteState} from '#/components/Post/Embed/VideoEmbed/VideoVolumeContext'
|
||||||
import {AltBadge, GifPresentationControls} from '../GifPresentationControls'
|
import {GifPresentationControls} from '../GifPresentationControls'
|
||||||
import {TimeIndicator} from './TimeIndicator'
|
import {TimeIndicator} from './TimeIndicator'
|
||||||
|
|
||||||
export function VideoEmbedInnerNative({
|
export function VideoEmbedInnerNative({
|
||||||
@@ -112,7 +113,9 @@ export function VideoEmbedInnerNative({
|
|||||||
timeRemaining={timeRemaining}
|
timeRemaining={timeRemaining}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{!isGif && embed.alt && <AltBadge text={embed.alt} />}
|
{!isGif && embed.alt && (
|
||||||
|
<AltBadgeWithDialog text={embed.alt} position="top-right" />
|
||||||
|
)}
|
||||||
<MediaInsetBorder />
|
<MediaInsetBorder />
|
||||||
<KeepAwake enabled={isPlaying} />
|
<KeepAwake enabled={isPlaying} />
|
||||||
</View>
|
</View>
|
||||||
|
|||||||
@@ -7,8 +7,8 @@ import type * as HlsTypes from 'hls.js'
|
|||||||
|
|
||||||
import {useNonReactiveCallback} from '#/lib/hooks/useNonReactiveCallback'
|
import {useNonReactiveCallback} from '#/lib/hooks/useNonReactiveCallback'
|
||||||
import {atoms as a} from '#/alf'
|
import {atoms as a} from '#/alf'
|
||||||
|
import {AltBadgeWithDialog} from '#/components/AltBadgeWithDialog'
|
||||||
import {useFullscreen} from '#/components/hooks/useFullscreen'
|
import {useFullscreen} from '#/components/hooks/useFullscreen'
|
||||||
import {AltBadge} from '../GifPresentationControls'
|
|
||||||
import * as BandwidthEstimate from './bandwidth-estimate'
|
import * as BandwidthEstimate from './bandwidth-estimate'
|
||||||
import {Controls} from './web-controls/VideoControls'
|
import {Controls} from './web-controls/VideoControls'
|
||||||
|
|
||||||
@@ -80,7 +80,9 @@ export function VideoEmbedInnerWeb({
|
|||||||
</figcaption>
|
</figcaption>
|
||||||
)}
|
)}
|
||||||
</figure>
|
</figure>
|
||||||
{!isFullscreen && embed.alt && <AltBadge text={embed.alt} />}
|
{!isFullscreen && embed.alt && (
|
||||||
|
<AltBadgeWithDialog text={embed.alt} position="top-right" />
|
||||||
|
)}
|
||||||
<Controls
|
<Controls
|
||||||
videoRef={videoRef}
|
videoRef={videoRef}
|
||||||
hlsRef={hlsRef}
|
hlsRef={hlsRef}
|
||||||
|
|||||||
Reference in New Issue
Block a user