diff options
Diffstat (limited to 'src/view/com/util')
-rw-r--r-- | src/view/com/util/PostMeta.tsx | 44 | ||||
-rw-r--r-- | src/view/com/util/UserInfoText.tsx | 31 | ||||
-rw-r--r-- | src/view/com/util/post-embeds/ExternalLinkEmbed.tsx | 27 | ||||
-rw-r--r-- | src/view/com/util/text/Text.tsx | 50 | ||||
-rw-r--r-- | src/view/com/util/text/ThemedText.tsx | 80 |
5 files changed, 97 insertions, 135 deletions
diff --git a/src/view/com/util/PostMeta.tsx b/src/view/com/util/PostMeta.tsx index 3bd350bf3..f2d717e96 100644 --- a/src/view/com/util/PostMeta.tsx +++ b/src/view/com/util/PostMeta.tsx @@ -4,16 +4,16 @@ import {AppBskyActorDefs, ModerationDecision, ModerationUI} from '@atproto/api' import {useLingui} from '@lingui/react' import {useQueryClient} from '@tanstack/react-query' +import {usePalette} from '#/lib/hooks/usePalette' +import {makeProfileLink} from '#/lib/routes/links' +import {forceLTR} from '#/lib/strings/bidi' +import {NON_BREAKING_SPACE} from '#/lib/strings/constants' +import {sanitizeDisplayName} from '#/lib/strings/display-names' +import {sanitizeHandle} from '#/lib/strings/handles' +import {niceDate} from '#/lib/strings/time' +import {TypographyVariant} from '#/lib/ThemeContext' +import {isAndroid} from '#/platform/detection' import {precacheProfile} from '#/state/queries/profile' -import {usePalette} from 'lib/hooks/usePalette' -import {makeProfileLink} from 'lib/routes/links' -import {forceLTR} from 'lib/strings/bidi' -import {NON_BREAKING_SPACE} from 'lib/strings/constants' -import {sanitizeDisplayName} from 'lib/strings/display-names' -import {sanitizeHandle} from 'lib/strings/handles' -import {niceDate} from 'lib/strings/time' -import {TypographyVariant} from 'lib/ThemeContext' -import {isAndroid} from 'platform/detection' import {ProfileHoverCard} from '#/components/ProfileHoverCard' import {TextLinkOnWebOnly} from './Link' import {Text} from './text/Text' @@ -73,12 +73,20 @@ let PostMeta = (opts: PostMetaOpts): React.ReactNode => { style={[pal.text]} lineHeight={1.2} disableMismatchWarning - text={forceLTR( - sanitizeDisplayName( - displayName, - opts.moderation?.ui('displayName'), - ), - )} + text={ + <Text + type={opts.displayNameType || 'lg-bold'} + emoji + style={[pal.text]} + lineHeight={1.2}> + {forceLTR( + sanitizeDisplayName( + displayName, + opts.moderation?.ui('displayName'), + ), + )} + </Text> + } href={profileLink} onBeforePress={onBeforePressAuthor} /> @@ -86,7 +94,11 @@ let PostMeta = (opts: PostMetaOpts): React.ReactNode => { type="md" disableMismatchWarning style={[pal.textLight, {flexShrink: 4}]} - text={NON_BREAKING_SPACE + sanitizeHandle(handle, '@')} + text={ + <Text emoji style={[pal.textLight, {flexShrink: 4}]}> + {NON_BREAKING_SPACE + sanitizeHandle(handle, '@')} + </Text> + } href={profileLink} onBeforePress={onBeforePressAuthor} anchorNoUnderline diff --git a/src/view/com/util/UserInfoText.tsx b/src/view/com/util/UserInfoText.tsx index 9cb9997f6..8a444d590 100644 --- a/src/view/com/util/UserInfoText.tsx +++ b/src/view/com/util/UserInfoText.tsx @@ -1,15 +1,16 @@ import React from 'react' -import {AppBskyActorGetProfile as GetProfile} from '@atproto/api' import {StyleProp, StyleSheet, TextStyle} from 'react-native' +import {AppBskyActorGetProfile as GetProfile} from '@atproto/api' + +import {makeProfileLink} from '#/lib/routes/links' +import {sanitizeDisplayName} from '#/lib/strings/display-names' +import {sanitizeHandle} from '#/lib/strings/handles' +import {TypographyVariant} from '#/lib/ThemeContext' +import {STALE} from '#/state/queries' +import {useProfileQuery} from '#/state/queries/profile' import {TextLinkOnWebOnly} from './Link' -import {Text} from './text/Text' import {LoadingPlaceholder} from './LoadingPlaceholder' -import {TypographyVariant} from 'lib/ThemeContext' -import {sanitizeDisplayName} from 'lib/strings/display-names' -import {sanitizeHandle} from 'lib/strings/handles' -import {makeProfileLink} from 'lib/routes/links' -import {useProfileQuery} from '#/state/queries/profile' -import {STALE} from '#/state/queries' +import {Text} from './text/Text' export function UserInfoText({ type = 'md', @@ -50,11 +51,15 @@ export function UserInfoText({ lineHeight={1.2} numberOfLines={1} href={makeProfileLink(profile)} - text={`${prefix || ''}${sanitizeDisplayName( - typeof profile[attr] === 'string' && profile[attr] - ? (profile[attr] as string) - : sanitizeHandle(profile.handle), - )}`} + text={ + <Text emoji type={type} style={style} lineHeight={1.2}> + {`${prefix || ''}${sanitizeDisplayName( + typeof profile[attr] === 'string' && profile[attr] + ? (profile[attr] as string) + : sanitizeHandle(profile.handle), + )}`} + </Text> + } /> ) } else { diff --git a/src/view/com/util/post-embeds/ExternalLinkEmbed.tsx b/src/view/com/util/post-embeds/ExternalLinkEmbed.tsx index 54e1eb4d5..98332c33b 100644 --- a/src/view/com/util/post-embeds/ExternalLinkEmbed.tsx +++ b/src/view/com/util/post-embeds/ExternalLinkEmbed.tsx @@ -5,21 +5,21 @@ import {AppBskyEmbedExternal} from '@atproto/api' import {msg} from '@lingui/macro' import {useLingui} from '@lingui/react' -import {usePalette} from 'lib/hooks/usePalette' -import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries' -import {shareUrl} from 'lib/sharing' -import {parseEmbedPlayerFromUrl} from 'lib/strings/embed-player' +import {usePalette} from '#/lib/hooks/usePalette' +import {useWebMediaQueries} from '#/lib/hooks/useWebMediaQueries' +import {shareUrl} from '#/lib/sharing' +import {parseEmbedPlayerFromUrl} from '#/lib/strings/embed-player' import { getStarterPackOgCard, parseStarterPackUri, -} from 'lib/strings/starter-pack' -import {toNiceDomain} from 'lib/strings/url-helpers' -import {isNative} from 'platform/detection' -import {useExternalEmbedsPrefs} from 'state/preferences' -import {Link} from 'view/com/util/Link' -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' +} from '#/lib/strings/starter-pack' +import {toNiceDomain} from '#/lib/strings/url-helpers' +import {isNative} from '#/platform/detection' +import {useExternalEmbedsPrefs} from '#/state/preferences' +import {Link} from '#/view/com/util/Link' +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' @@ -115,12 +115,13 @@ export const ExternalLinkEmbed = ({ </Text> {!embedPlayerParams?.isGif && !embedPlayerParams?.dimensions && ( - <Text type="lg-bold" numberOfLines={3} style={[pal.text]}> + <Text emoji type="lg-bold" numberOfLines={3} style={[pal.text]}> {link.title || link.uri} </Text> )} {link.description ? ( <Text + emoji type="md" numberOfLines={link.thumb ? 2 : 4} style={[pal.text, a.mt_xs]}> diff --git a/src/view/com/util/text/Text.tsx b/src/view/com/util/text/Text.tsx index 52a45b0e2..3d885480c 100644 --- a/src/view/com/util/text/Text.tsx +++ b/src/view/com/util/text/Text.tsx @@ -2,27 +2,40 @@ import React from 'react' import {StyleSheet, Text as RNText, TextProps} from 'react-native' import {UITextView} from 'react-native-uitextview' -import {lh, s} from 'lib/styles' -import {TypographyVariant, useTheme} from 'lib/ThemeContext' -import {isIOS, isWeb} from 'platform/detection' +import {lh, s} from '#/lib/styles' +import {TypographyVariant, useTheme} from '#/lib/ThemeContext' +import {logger} from '#/logger' +import {isIOS} from '#/platform/detection' import {applyFonts, useAlf} from '#/alf' +import { + childHasEmoji, + childIsString, + renderChildrenWithEmoji, + StringChild, +} from '#/components/Typography' +import {IS_DEV} from '#/env' -export type CustomTextProps = TextProps & { +export type CustomTextProps = Omit<TextProps, 'children'> & { type?: TypographyVariant lineHeight?: number title?: string dataSet?: Record<string, string | number> selectable?: boolean -} - -const fontFamilyStyle = { - fontFamily: - '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Liberation Sans", Helvetica, Arial, sans-serif', -} +} & ( + | { + emoji: true + children: StringChild + } + | { + emoji?: false + children: TextProps['children'] + } + ) export function Text({ type = 'md', children, + emoji, lineHeight, style, title, @@ -35,6 +48,18 @@ export function Text({ const lineHeightStyle = lineHeight ? lh(theme, type, lineHeight) : undefined const {fonts} = useAlf() + if (IS_DEV) { + if (!emoji && childHasEmoji(children)) { + logger.warn( + `Text: emoji detected but emoji not enabled: "${children}"\n\nPlease add <Text emoji />'`, + ) + } + + if (emoji && !childIsString(children)) { + logger.error('Text: when <Text emoji />, children can only be strings.') + } + } + if (selectable && isIOS) { const flattened = StyleSheet.flatten([ s.black, @@ -58,7 +83,7 @@ export function Text({ selectable={selectable} uiTextView {...props}> - {children} + {isIOS && emoji ? renderChildrenWithEmoji(children) : children} </UITextView> ) } @@ -66,7 +91,6 @@ export function Text({ const flattened = StyleSheet.flatten([ s.black, typography, - isWeb && fontFamilyStyle, lineHeightStyle, style, ]) @@ -87,7 +111,7 @@ export function Text({ dataSet={Object.assign({tooltip: title}, dataSet || {})} selectable={selectable} {...props}> - {children} + {isIOS && emoji ? renderChildrenWithEmoji(children) : children} </RNText> ) } diff --git a/src/view/com/util/text/ThemedText.tsx b/src/view/com/util/text/ThemedText.tsx deleted file mode 100644 index 2844d273c..000000000 --- a/src/view/com/util/text/ThemedText.tsx +++ /dev/null @@ -1,80 +0,0 @@ -import React from 'react' -import {CustomTextProps, Text} from './Text' -import {usePalette} from 'lib/hooks/usePalette' -import {addStyle} from 'lib/styles' - -export type ThemedTextProps = CustomTextProps & { - fg?: 'default' | 'light' | 'error' | 'inverted' | 'inverted-light' - bg?: 'default' | 'light' | 'error' | 'inverted' | 'inverted-light' - border?: 'default' | 'dark' | 'error' | 'inverted' | 'inverted-dark' - lineHeight?: number -} - -export function ThemedText({ - fg, - bg, - border, - style, - children, - ...props -}: React.PropsWithChildren<ThemedTextProps>) { - const pal = usePalette('default') - const palInverted = usePalette('inverted') - const palError = usePalette('error') - switch (fg) { - case 'default': - style = addStyle(style, pal.text) - break - case 'light': - style = addStyle(style, pal.textLight) - break - case 'error': - style = addStyle(style, {color: palError.colors.background}) - break - case 'inverted': - style = addStyle(style, palInverted.text) - break - case 'inverted-light': - style = addStyle(style, palInverted.textLight) - break - } - switch (bg) { - case 'default': - style = addStyle(style, pal.view) - break - case 'light': - style = addStyle(style, pal.viewLight) - break - case 'error': - style = addStyle(style, palError.view) - break - case 'inverted': - style = addStyle(style, palInverted.view) - break - case 'inverted-light': - style = addStyle(style, palInverted.viewLight) - break - } - switch (border) { - case 'default': - style = addStyle(style, pal.border) - break - case 'dark': - style = addStyle(style, pal.borderDark) - break - case 'error': - style = addStyle(style, palError.border) - break - case 'inverted': - style = addStyle(style, palInverted.border) - break - case 'inverted-dark': - style = addStyle(style, palInverted.borderDark) - break - } - return ( - <Text style={style} {...props}> - {children} - </Text> - ) -} |