Image/video border + tweaks (#5324)
* Image/video border (#5253) * Update AutoSizedImage.tsx * Update AutoSizedImage.tsx * Update Gallery.tsx * Update ExternalLinkEmbed.tsx * Update MediaPreview.tsx * Update UserAvatar.tsx * Update ExternalLinkEmbed.tsx * Update ExternalPlayerEmbed.tsx * Update ExternalGifEmbed.tsx * Update GifEmbed.tsx * Update ExternalGifEmbed.tsx * Update GifEmbed.tsx * Update UserAvatar.tsx * Update ExternalPlayerEmbed.tsx * Update ExternalPlayerEmbed.tsx * video * Update QuoteEmbed.tsx * Tweaks, abstract components --------- Co-authored-by: Minseo Lee <itoupluk427@gmail.com>zio/dev^2
parent
c7231537f1
commit
b3381da1c1
|
@ -0,0 +1,11 @@
|
|||
import React from 'react'
|
||||
import {View} from 'react-native'
|
||||
|
||||
import {atoms as a, ViewStyleProp} from '#/alf'
|
||||
|
||||
export function Fill({
|
||||
children,
|
||||
style,
|
||||
}: {children?: React.ReactNode} & ViewStyleProp) {
|
||||
return <View style={[a.absolute, a.inset_0, style]}>{children}</View>
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
import React from 'react'
|
||||
|
||||
import {atoms as a, useTheme, ViewStyleProp} from '#/alf'
|
||||
import {Fill} from '#/components/Fill'
|
||||
|
||||
/**
|
||||
* Applies and thin border within a bounding box. Used to contrast media from
|
||||
* bg of the container.
|
||||
*/
|
||||
export function MediaInsetBorder({
|
||||
children,
|
||||
style,
|
||||
opaque,
|
||||
}: {
|
||||
children?: React.ReactNode
|
||||
/**
|
||||
* Used where this border needs to match adjacent borders, such as in
|
||||
* external link previews
|
||||
*/
|
||||
opaque?: boolean
|
||||
} & ViewStyleProp) {
|
||||
const t = useTheme()
|
||||
const isLight = t.name === 'light'
|
||||
return (
|
||||
<Fill
|
||||
style={[
|
||||
a.rounded_sm,
|
||||
a.border,
|
||||
opaque
|
||||
? [t.atoms.border_contrast_low]
|
||||
: [
|
||||
isLight
|
||||
? t.atoms.border_contrast_low
|
||||
: t.atoms.border_contrast_high,
|
||||
{opacity: 0.6},
|
||||
],
|
||||
style,
|
||||
]}>
|
||||
{children}
|
||||
</Fill>
|
||||
)
|
||||
}
|
|
@ -11,6 +11,7 @@ import {Trans} from '@lingui/macro'
|
|||
|
||||
import {parseTenorGif} from '#/lib/strings/embed-player'
|
||||
import {atoms as a, useTheme} from '#/alf'
|
||||
import {MediaInsetBorder} from '#/components/MediaInsetBorder'
|
||||
import {Text} from '#/components/Typography'
|
||||
import {PlayButtonIcon} from '#/components/video/PlayButtonIcon'
|
||||
|
||||
|
@ -104,6 +105,7 @@ export function ImageItem({
|
|||
accessibilityHint={alt}
|
||||
accessibilityLabel=""
|
||||
/>
|
||||
<MediaInsetBorder style={[a.rounded_xs]} />
|
||||
{children}
|
||||
</View>
|
||||
)
|
||||
|
|
|
@ -19,7 +19,7 @@ import {colors} from 'lib/styles'
|
|||
import {isAndroid, isNative, isWeb} from 'platform/detection'
|
||||
import {precacheProfile} from 'state/queries/profile'
|
||||
import {HighPriorityImage} from 'view/com/util/images/Image'
|
||||
import {tokens, useTheme} from '#/alf'
|
||||
import {atoms as a, tokens, useTheme} from '#/alf'
|
||||
import {
|
||||
Camera_Filled_Stroke2_Corner0_Rounded as CameraFilled,
|
||||
Camera_Stroke2_Corner0_Rounded as Camera,
|
||||
|
@ -27,6 +27,7 @@ import {
|
|||
import {StreamingLive_Stroke2_Corner0_Rounded as Library} from '#/components/icons/StreamingLive'
|
||||
import {Trash_Stroke2_Corner0_Rounded as Trash} from '#/components/icons/Trash'
|
||||
import {Link} from '#/components/Link'
|
||||
import {MediaInsetBorder} from '#/components/MediaInsetBorder'
|
||||
import * as Menu from '#/components/Menu'
|
||||
import {ProfileHoverCard} from '#/components/ProfileHoverCard'
|
||||
import {openCamera, openCropper, openPicker} from '../../../lib/media/picker'
|
||||
|
@ -240,6 +241,7 @@ let UserAvatar = ({
|
|||
onLoad={onLoad}
|
||||
/>
|
||||
)}
|
||||
<MediaInsetBorder style={[a.rounded_full]} />
|
||||
{alert}
|
||||
</View>
|
||||
) : (
|
||||
|
|
|
@ -11,6 +11,7 @@ import {isNative} from '#/platform/detection'
|
|||
import {useLargeAltBadgeEnabled} from '#/state/preferences/large-alt-badge'
|
||||
import {atoms as a, useBreakpoints, useTheme} from '#/alf'
|
||||
import {ArrowsDiagonalOut_Stroke2_Corner0_Rounded as Fullscreen} from '#/components/icons/ArrowsDiagonal'
|
||||
import {MediaInsetBorder} from '#/components/MediaInsetBorder'
|
||||
import {Text} from '#/components/Typography'
|
||||
|
||||
export function useImageAspectRatio({
|
||||
|
@ -140,6 +141,7 @@ export function AutoSizedImage({
|
|||
accessibilityLabel={image.alt}
|
||||
accessibilityHint=""
|
||||
/>
|
||||
<MediaInsetBorder />
|
||||
|
||||
{(hasAlt || isCropped) && !hideBadge ? (
|
||||
<View
|
||||
|
|
|
@ -8,6 +8,7 @@ import {useLingui} from '@lingui/react'
|
|||
import {useLargeAltBadgeEnabled} from '#/state/preferences/large-alt-badge'
|
||||
import {PostEmbedViewContext} from '#/view/com/util/post-embeds/types'
|
||||
import {atoms as a, useTheme} from '#/alf'
|
||||
import {MediaInsetBorder} from '#/components/MediaInsetBorder'
|
||||
import {Text} from '#/components/Typography'
|
||||
|
||||
type EventFunction = (index: number) => void
|
||||
|
@ -46,7 +47,7 @@ export const GalleryItem: FC<GalleryItemProps> = ({
|
|||
onLongPress={onLongPress ? () => onLongPress(index) : undefined}
|
||||
style={[
|
||||
a.flex_1,
|
||||
a.rounded_xs,
|
||||
a.rounded_sm,
|
||||
a.overflow_hidden,
|
||||
t.atoms.bg_contrast_25,
|
||||
imageStyle,
|
||||
|
@ -62,6 +63,7 @@ export const GalleryItem: FC<GalleryItemProps> = ({
|
|||
accessibilityHint=""
|
||||
accessibilityIgnoresInvertColors
|
||||
/>
|
||||
<MediaInsetBorder />
|
||||
</Pressable>
|
||||
{hasAlt && !hideBadges ? (
|
||||
<View
|
||||
|
|
|
@ -5,19 +5,21 @@ import {
|
|||
LayoutChangeEvent,
|
||||
Pressable,
|
||||
StyleSheet,
|
||||
View,
|
||||
} from 'react-native'
|
||||
import {Image, ImageLoadEventData} from 'expo-image'
|
||||
import {AppBskyEmbedExternal} from '@atproto/api'
|
||||
import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome'
|
||||
import {msg} from '@lingui/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
|
||||
import {EmbedPlayerParams, getGifDims} from '#/lib/strings/embed-player'
|
||||
import {isIOS, isNative, isWeb} from '#/platform/detection'
|
||||
import {useExternalEmbedsPrefs} from '#/state/preferences'
|
||||
import {atoms as a, useTheme} from '#/alf'
|
||||
import {useDialogControl} from '#/components/Dialog'
|
||||
import {EmbedConsentDialog} from '#/components/dialogs/EmbedConsent'
|
||||
import {Fill} from '#/components/Fill'
|
||||
import {MediaInsetBorder} from '#/components/MediaInsetBorder'
|
||||
import {PlayButtonIcon} from '#/components/video/PlayButtonIcon'
|
||||
|
||||
export function ExternalGifEmbed({
|
||||
link,
|
||||
|
@ -26,6 +28,7 @@ export function ExternalGifEmbed({
|
|||
link: AppBskyEmbedExternal.ViewExternal
|
||||
params: EmbedPlayerParams
|
||||
}) {
|
||||
const t = useTheme()
|
||||
const externalEmbedsPrefs = useExternalEmbedsPrefs()
|
||||
|
||||
const {_} = useLingui()
|
||||
|
@ -113,26 +116,19 @@ export function ExternalGifEmbed({
|
|||
<Pressable
|
||||
style={[
|
||||
{height: imageDims.height},
|
||||
styles.topRadius,
|
||||
styles.gifContainer,
|
||||
a.rounded_sm,
|
||||
a.overflow_hidden,
|
||||
{
|
||||
borderBottomLeftRadius: 0,
|
||||
borderBottomRightRadius: 0,
|
||||
},
|
||||
]}
|
||||
onPress={onPlayPress}
|
||||
onLayout={onLayout}
|
||||
accessibilityRole="button"
|
||||
accessibilityHint={_(msg`Plays the GIF`)}
|
||||
accessibilityLabel={_(msg`Play ${link.title}`)}>
|
||||
{(!isPrefetched || !isAnimating) && ( // If we have not loaded or are not animating, show the overlay
|
||||
<View style={[styles.layer, styles.overlayLayer]}>
|
||||
<View style={[styles.overlayContainer, styles.topRadius]}>
|
||||
{!isAnimating || !isPlayerActive ? ( // Play button when not animating or not active
|
||||
<FontAwesomeIcon icon="play" size={42} color="white" />
|
||||
) : (
|
||||
// Activity indicator while gif loads
|
||||
<ActivityIndicator size="large" color="white" />
|
||||
)}
|
||||
</View>
|
||||
</View>
|
||||
)}
|
||||
<Image
|
||||
source={{
|
||||
uri:
|
||||
|
@ -150,6 +146,35 @@ export function ExternalGifEmbed({
|
|||
accessibilityHint={link.title}
|
||||
cachePolicy={isIOS ? 'disk' : 'memory-disk'} // cant control playback with memory-disk on ios
|
||||
/>
|
||||
|
||||
{(!isPrefetched || !isAnimating) && (
|
||||
<Fill style={[a.align_center, a.justify_center]}>
|
||||
<Fill
|
||||
style={[
|
||||
t.name === 'light' ? t.atoms.bg_contrast_975 : t.atoms.bg,
|
||||
{
|
||||
opacity: 0.3,
|
||||
},
|
||||
]}
|
||||
/>
|
||||
|
||||
{!isAnimating || !isPlayerActive ? ( // Play button when not animating or not active
|
||||
<PlayButtonIcon />
|
||||
) : (
|
||||
// Activity indicator while gif loads
|
||||
<ActivityIndicator size="large" color="white" />
|
||||
)}
|
||||
</Fill>
|
||||
)}
|
||||
<MediaInsetBorder
|
||||
opaque
|
||||
style={[
|
||||
{
|
||||
borderBottomLeftRadius: 0,
|
||||
borderBottomRightRadius: 0,
|
||||
},
|
||||
]}
|
||||
/>
|
||||
</Pressable>
|
||||
</>
|
||||
)
|
||||
|
@ -171,7 +196,6 @@ const styles = StyleSheet.create({
|
|||
flex: 1,
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
backgroundColor: 'rgba(0,0,0,0.5)',
|
||||
},
|
||||
overlayLayer: {
|
||||
zIndex: 2,
|
||||
|
|
|
@ -21,6 +21,7 @@ import {ExternalGifEmbed} from 'view/com/util/post-embeds/ExternalGifEmbed'
|
|||
import {ExternalPlayer} from 'view/com/util/post-embeds/ExternalPlayerEmbed'
|
||||
import {GifEmbed} from 'view/com/util/post-embeds/GifEmbed'
|
||||
import {atoms as a, useTheme} from '#/alf'
|
||||
import {MediaInsetBorder} from '#/components/MediaInsetBorder'
|
||||
import {Text} from '../text/Text'
|
||||
|
||||
export const ExternalLinkEmbed = ({
|
||||
|
@ -36,6 +37,7 @@ export const ExternalLinkEmbed = ({
|
|||
}) => {
|
||||
const {_} = useLingui()
|
||||
const pal = usePalette('default')
|
||||
const t = useTheme()
|
||||
const {isMobile} = useWebMediaQueries()
|
||||
const externalEmbedPrefs = useExternalEmbedsPrefs()
|
||||
|
||||
|
@ -60,19 +62,30 @@ export const ExternalLinkEmbed = ({
|
|||
<View style={[a.flex_col, a.rounded_sm, a.overflow_hidden]}>
|
||||
<LinkWrapper link={link} onOpen={onOpen} style={style}>
|
||||
{imageUri && !embedPlayerParams ? (
|
||||
<Image
|
||||
style={{
|
||||
aspectRatio: 1.91,
|
||||
borderTopRightRadius: 6,
|
||||
borderTopLeftRadius: 6,
|
||||
}}
|
||||
source={{uri: imageUri}}
|
||||
accessibilityIgnoresInvertColors
|
||||
accessibilityLabel={starterPackParsed ? link.title : undefined}
|
||||
accessibilityHint={
|
||||
starterPackParsed ? _(msg`Navigate to starter pack`) : undefined
|
||||
}
|
||||
/>
|
||||
<View>
|
||||
<Image
|
||||
style={{
|
||||
aspectRatio: 1.91,
|
||||
borderTopRightRadius: 8,
|
||||
borderTopLeftRadius: 8,
|
||||
}}
|
||||
source={{uri: imageUri}}
|
||||
accessibilityIgnoresInvertColors
|
||||
accessibilityLabel={starterPackParsed ? link.title : undefined}
|
||||
accessibilityHint={
|
||||
starterPackParsed ? _(msg`Navigate to starter pack`) : undefined
|
||||
}
|
||||
/>
|
||||
<MediaInsetBorder
|
||||
opaque
|
||||
style={[
|
||||
{
|
||||
borderBottomLeftRadius: 0,
|
||||
borderBottomRightRadius: 0,
|
||||
},
|
||||
]}
|
||||
/>
|
||||
</View>
|
||||
) : undefined}
|
||||
{embedPlayerParams?.isGif ? (
|
||||
<ExternalGifEmbed link={link} params={embedPlayerParams} />
|
||||
|
@ -81,11 +94,18 @@ export const ExternalLinkEmbed = ({
|
|||
) : undefined}
|
||||
<View
|
||||
style={[
|
||||
a.border_b,
|
||||
a.border_l,
|
||||
a.border_r,
|
||||
a.flex_1,
|
||||
a.py_sm,
|
||||
t.atoms.border_contrast_low,
|
||||
{
|
||||
borderBottomRightRadius: 8,
|
||||
borderBottomLeftRadius: 8,
|
||||
paddingHorizontal: isMobile ? 10 : 14,
|
||||
},
|
||||
!imageUri && !embedPlayerParams && [a.border, a.rounded_sm],
|
||||
]}>
|
||||
<Text
|
||||
type="sm"
|
||||
|
@ -124,8 +144,6 @@ function LinkWrapper({
|
|||
style?: StyleProp<ViewStyle>
|
||||
children: React.ReactNode
|
||||
}) {
|
||||
const t = useTheme()
|
||||
|
||||
const onShareExternal = useCallback(() => {
|
||||
if (link.uri && isNative) {
|
||||
shareUrl(link.uri)
|
||||
|
@ -137,14 +155,7 @@ function LinkWrapper({
|
|||
asAnchor
|
||||
anchorNoUnderline
|
||||
href={link.uri}
|
||||
style={[
|
||||
a.flex_1,
|
||||
a.border,
|
||||
a.rounded_sm,
|
||||
t.atoms.border_contrast_medium,
|
||||
style,
|
||||
]}
|
||||
hoverStyle={t.atoms.border_contrast_high}
|
||||
style={[a.flex_1, a.rounded_sm, style]}
|
||||
onBeforePress={onOpen}
|
||||
onLongPress={onShareExternal}>
|
||||
{children}
|
||||
|
|
|
@ -25,9 +25,11 @@ import {NavigationProp} from '#/lib/routes/types'
|
|||
import {EmbedPlayerParams, getPlayerAspect} from '#/lib/strings/embed-player'
|
||||
import {isNative} from '#/platform/detection'
|
||||
import {useExternalEmbedsPrefs} from '#/state/preferences'
|
||||
import {atoms as a} from '#/alf'
|
||||
import {atoms as a, useTheme} from '#/alf'
|
||||
import {useDialogControl} from '#/components/Dialog'
|
||||
import {EmbedConsentDialog} from '#/components/dialogs/EmbedConsent'
|
||||
import {Fill} from '#/components/Fill'
|
||||
import {MediaInsetBorder} from '#/components/MediaInsetBorder'
|
||||
import {PlayButtonIcon} from '#/components/video/PlayButtonIcon'
|
||||
import {EventStopper} from '../EventStopper'
|
||||
|
||||
|
@ -106,6 +108,16 @@ function Player({
|
|||
style={styles.webview}
|
||||
setSupportMultipleWindows={false} // Prevent any redirects from opening a new window (ads)
|
||||
/>
|
||||
|
||||
<MediaInsetBorder
|
||||
opaque
|
||||
style={[
|
||||
{
|
||||
borderBottomLeftRadius: 0,
|
||||
borderBottomRightRadius: 0,
|
||||
},
|
||||
]}
|
||||
/>
|
||||
</EventStopper>
|
||||
)
|
||||
}
|
||||
|
@ -118,6 +130,7 @@ export function ExternalPlayer({
|
|||
link: AppBskyEmbedExternal.ViewExternal
|
||||
params: EmbedPlayerParams
|
||||
}) {
|
||||
const t = useTheme()
|
||||
const navigation = useNavigation<NavigationProp>()
|
||||
const insets = useSafeAreaInsets()
|
||||
const windowDims = useWindowDimensions()
|
||||
|
@ -211,13 +224,38 @@ export function ExternalPlayer({
|
|||
onAccept={onAcceptConsent}
|
||||
/>
|
||||
|
||||
<Animated.View ref={viewRef} collapsable={false} style={[aspect]}>
|
||||
<Animated.View
|
||||
ref={viewRef}
|
||||
collapsable={false}
|
||||
style={[aspect, a.rounded_sm]}>
|
||||
{link.thumb && (!isPlayerActive || isLoading) && (
|
||||
<Image
|
||||
style={[a.flex_1, styles.topRadius]}
|
||||
source={{uri: link.thumb}}
|
||||
accessibilityIgnoresInvertColors
|
||||
/>
|
||||
<>
|
||||
<Image
|
||||
style={[a.flex_1, styles.topRadius]}
|
||||
source={{uri: link.thumb}}
|
||||
accessibilityIgnoresInvertColors
|
||||
/>
|
||||
<Fill
|
||||
style={[
|
||||
a.rounded_sm,
|
||||
t.name === 'light' ? t.atoms.bg_contrast_975 : t.atoms.bg,
|
||||
{
|
||||
borderBottomLeftRadius: 0,
|
||||
borderBottomRightRadius: 0,
|
||||
opacity: 0.3,
|
||||
},
|
||||
]}
|
||||
/>
|
||||
<MediaInsetBorder
|
||||
opaque
|
||||
style={[
|
||||
{
|
||||
borderBottomLeftRadius: 0,
|
||||
borderBottomRightRadius: 0,
|
||||
},
|
||||
]}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
<PlaceholderOverlay
|
||||
isLoading={isLoading}
|
||||
|
@ -236,14 +274,13 @@ export function ExternalPlayer({
|
|||
|
||||
const styles = StyleSheet.create({
|
||||
topRadius: {
|
||||
borderTopLeftRadius: 6,
|
||||
borderTopRightRadius: 6,
|
||||
borderTopLeftRadius: 8,
|
||||
borderTopRightRadius: 8,
|
||||
},
|
||||
overlayContainer: {
|
||||
flex: 1,
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
backgroundColor: 'rgba(0,0,0,0.5)',
|
||||
},
|
||||
overlayLayer: {
|
||||
zIndex: 2,
|
||||
|
@ -252,6 +289,8 @@ const styles = StyleSheet.create({
|
|||
zIndex: 3,
|
||||
},
|
||||
webview: {
|
||||
borderTopRightRadius: 8,
|
||||
borderTopLeftRadius: 8,
|
||||
backgroundColor: 'transparent',
|
||||
},
|
||||
gifContainer: {
|
||||
|
|
|
@ -18,7 +18,9 @@ import {useLargeAltBadgeEnabled} from '#/state/preferences/large-alt-badge'
|
|||
import {EmbedPlayerParams} from 'lib/strings/embed-player'
|
||||
import {useAutoplayDisabled} from 'state/preferences'
|
||||
import {atoms as a, useTheme} from '#/alf'
|
||||
import {Fill} from '#/components/Fill'
|
||||
import {Loader} from '#/components/Loader'
|
||||
import {MediaInsetBorder} from '#/components/MediaInsetBorder'
|
||||
import * as Prompt from '#/components/Prompt'
|
||||
import {Text} from '#/components/Typography'
|
||||
import {PlayButtonIcon} from '#/components/video/PlayButtonIcon'
|
||||
|
@ -56,8 +58,6 @@ function PlaybackControls({
|
|||
zIndex: 2,
|
||||
backgroundColor: !isLoaded
|
||||
? t.atoms.bg_contrast_25.backgroundColor
|
||||
: !isPlaying
|
||||
? 'rgba(0, 0, 0, 0.3)'
|
||||
: undefined,
|
||||
},
|
||||
]}
|
||||
|
@ -86,6 +86,7 @@ export function GifEmbed({
|
|||
hideAlt?: boolean
|
||||
style?: StyleProp<ViewStyle>
|
||||
}) {
|
||||
const t = useTheme()
|
||||
const {_} = useLingui()
|
||||
const autoplayDisabled = useAutoplayDisabled()
|
||||
|
||||
|
@ -138,6 +139,17 @@ export function GifEmbed({
|
|||
accessibilityHint={_(msg`Animated GIF`)}
|
||||
accessibilityLabel={parsedAlt.alt}
|
||||
/>
|
||||
{!playerState.isPlaying && (
|
||||
<Fill
|
||||
style={[
|
||||
t.name === 'light' ? t.atoms.bg_contrast_975 : t.atoms.bg,
|
||||
{
|
||||
opacity: 0.3,
|
||||
},
|
||||
]}
|
||||
/>
|
||||
)}
|
||||
<MediaInsetBorder />
|
||||
{!hideAlt && parsedAlt.isPreferred && <AltText text={parsedAlt.alt} />}
|
||||
</View>
|
||||
</View>
|
||||
|
|
|
@ -33,7 +33,7 @@ import {InfoCircleIcon} from 'lib/icons'
|
|||
import {makeProfileLink} from 'lib/routes/links'
|
||||
import {precacheProfile} from 'state/queries/profile'
|
||||
import {ComposerOptsQuote} from 'state/shell/composer'
|
||||
import {atoms as a} from '#/alf'
|
||||
import {atoms as a, useTheme} from '#/alf'
|
||||
import {RichText} from '#/components/RichText'
|
||||
import {ContentHider} from '../../../../components/moderation/ContentHider'
|
||||
import {PostAlerts} from '../../../../components/moderation/PostAlerts'
|
||||
|
@ -56,6 +56,7 @@ export function MaybeQuoteEmbed({
|
|||
allowNestedQuotes?: boolean
|
||||
viewContext?: QuoteEmbedViewContext
|
||||
}) {
|
||||
const t = useTheme()
|
||||
const pal = usePalette('default')
|
||||
const {currentAccount} = useSession()
|
||||
if (
|
||||
|
@ -75,7 +76,8 @@ export function MaybeQuoteEmbed({
|
|||
)
|
||||
} else if (AppBskyEmbedRecord.isViewBlocked(embed.record)) {
|
||||
return (
|
||||
<View style={[styles.errorContainer, pal.borderDark]}>
|
||||
<View
|
||||
style={[styles.errorContainer, a.border, t.atoms.border_contrast_low]}>
|
||||
<InfoCircleIcon size={18} style={pal.text} />
|
||||
<Text type="lg" style={pal.text}>
|
||||
<Trans>Blocked</Trans>
|
||||
|
@ -84,7 +86,8 @@ export function MaybeQuoteEmbed({
|
|||
)
|
||||
} else if (AppBskyEmbedRecord.isViewNotFound(embed.record)) {
|
||||
return (
|
||||
<View style={[styles.errorContainer, pal.borderDark]}>
|
||||
<View
|
||||
style={[styles.errorContainer, a.border, t.atoms.border_contrast_low]}>
|
||||
<InfoCircleIcon size={18} style={pal.text} />
|
||||
<Text type="lg" style={pal.text}>
|
||||
<Trans>Deleted</Trans>
|
||||
|
@ -96,7 +99,8 @@ export function MaybeQuoteEmbed({
|
|||
? embed.record.uri.includes(currentAccount.did)
|
||||
: false
|
||||
return (
|
||||
<View style={[styles.errorContainer, pal.borderDark]}>
|
||||
<View
|
||||
style={[styles.errorContainer, a.border, t.atoms.border_contrast_low]}>
|
||||
<InfoCircleIcon size={18} style={pal.text} />
|
||||
<Text type="lg" style={pal.text}>
|
||||
{isViewerOwner ? (
|
||||
|
@ -169,6 +173,7 @@ export function QuoteEmbed({
|
|||
allowNestedQuotes?: boolean
|
||||
viewContext?: QuoteEmbedViewContext
|
||||
}) {
|
||||
const t = useTheme()
|
||||
const queryClient = useQueryClient()
|
||||
const pal = usePalette('default')
|
||||
const itemUrip = new AtUri(quote.uri)
|
||||
|
@ -214,7 +219,7 @@ export function QuoteEmbed({
|
|||
return (
|
||||
<ContentHider
|
||||
modui={moderation?.ui('contentList')}
|
||||
style={[styles.container, pal.borderDark, style]}
|
||||
style={[styles.container, a.border, t.atoms.border_contrast_low, style]}
|
||||
childContainerStyle={[a.pt_sm]}>
|
||||
<Link
|
||||
hoverStyle={{borderColor: pal.colors.borderLinkHover}}
|
||||
|
|
|
@ -13,6 +13,7 @@ import {useActiveVideoNative} from 'view/com/util/post-embeds/ActiveVideoNativeC
|
|||
import {atoms as a, useTheme} from '#/alf'
|
||||
import {Mute_Stroke2_Corner0_Rounded as MuteIcon} from '#/components/icons/Mute'
|
||||
import {SpeakerVolumeFull_Stroke2_Corner0_Rounded as UnmuteIcon} from '#/components/icons/Speaker'
|
||||
import {MediaInsetBorder} from '#/components/MediaInsetBorder'
|
||||
import {
|
||||
AudioCategory,
|
||||
PlatformInfo,
|
||||
|
@ -84,6 +85,7 @@ export function VideoEmbedInnerNative({
|
|||
isMuted={isMuted}
|
||||
timeRemaining={timeRemaining}
|
||||
/>
|
||||
<MediaInsetBorder />
|
||||
</View>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ import {AppBskyEmbedVideo} from '@atproto/api'
|
|||
import Hls from 'hls.js'
|
||||
|
||||
import {atoms as a} from '#/alf'
|
||||
import {MediaInsetBorder} from '#/components/MediaInsetBorder'
|
||||
import {Controls} from './VideoWebControls'
|
||||
|
||||
export function VideoEmbedInnerWeb({
|
||||
|
@ -119,6 +120,7 @@ export function VideoEmbedInnerWeb({
|
|||
fullscreenRef={containerRef}
|
||||
hasSubtitleTrack={hasSubtitleTrack}
|
||||
/>
|
||||
<MediaInsetBorder />
|
||||
</div>
|
||||
</View>
|
||||
)
|
||||
|
|
Loading…
Reference in New Issue