Fix RTL text rendering for display names (#4747)

* header display name rtl support

* highlighted post rtl

* move `NON_BREAKING_SPACE` to an external constant

* rtl support in search dropdown

* profile card rtl

* old profile card rtl

* hover card

* wizard list card

* new chat

* account card

* chat header

* clean up notifications

* just force LTR on meta display name
zio/stable
Hailey 2024-07-08 10:06:00 -07:00 committed by GitHub
parent d5503d17de
commit f8a59e10dd
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
13 changed files with 41 additions and 23 deletions

View File

@ -166,7 +166,9 @@ export function NameAndHandle({
return ( return (
<View style={[a.flex_1]}> <View style={[a.flex_1]}>
<Text style={[a.text_md, a.font_bold, a.leading_snug]} numberOfLines={1}> <Text
style={[a.text_md, a.font_bold, a.leading_snug, a.self_start]}
numberOfLines={1}>
{name} {name}
</Text> </Text>
<Text <Text

View File

@ -462,7 +462,8 @@ function Inner({
<Link to={profileURL} label={_(msg`View profile`)} onPress={hide}> <Link to={profileURL} label={_(msg`View profile`)} onPress={hide}>
<View style={[a.pb_sm, a.flex_1]}> <View style={[a.pb_sm, a.flex_1]}>
<Text style={[a.pt_md, a.pb_xs, a.text_lg, a.font_bold]}> <Text
style={[a.pt_md, a.pb_xs, a.text_lg, a.font_bold, a.self_start]}>
{sanitizeDisplayName( {sanitizeDisplayName(
profile.displayName || sanitizeHandle(profile.handle), profile.displayName || sanitizeHandle(profile.handle),
moderation.ui('displayName'), moderation.ui('displayName'),

View File

@ -78,7 +78,13 @@ function WizardListCard({
/> />
<View style={[a.flex_1, a.gap_2xs]}> <View style={[a.flex_1, a.gap_2xs]}>
<Text <Text
style={[a.flex_1, a.font_bold, a.text_md, a.leading_tight]} style={[
a.flex_1,
a.font_bold,
a.text_md,
a.leading_tight,
a.self_start,
]}
numberOfLines={1}> numberOfLines={1}>
{displayName} {displayName}
</Text> </Text>

View File

@ -168,7 +168,12 @@ function HeaderReady({
</View> </View>
<View style={a.flex_1}> <View style={a.flex_1}>
<Text <Text
style={[a.text_md, a.font_bold, web(a.leading_normal)]} style={[
a.text_md,
a.font_bold,
a.self_start,
web(a.leading_normal),
]}
numberOfLines={1}> numberOfLines={1}>
{displayName} {displayName}
</Text> </Text>

View File

@ -395,7 +395,7 @@ function ProfileCard({
/> />
<View style={[a.flex_1, a.gap_2xs]}> <View style={[a.flex_1, a.gap_2xs]}>
<Text <Text
style={[t.atoms.text, a.font_bold, a.leading_tight]} style={[t.atoms.text, a.font_bold, a.leading_tight, a.self_start]}
numberOfLines={1}> numberOfLines={1}>
{displayName} {displayName}
</Text> </Text>

View File

@ -0,0 +1 @@
export const NON_BREAKING_SPACE = '\u00A0'

View File

@ -20,7 +20,7 @@ export function ProfileHeaderDisplayName({
<View pointerEvents="none"> <View pointerEvents="none">
<Text <Text
testID="profileHeaderDisplayName" testID="profileHeaderDisplayName"
style={[t.atoms.text, a.text_4xl, {fontWeight: '500'}]}> style={[t.atoms.text, a.text_4xl, a.self_start, {fontWeight: '500'}]}>
{sanitizeDisplayName( {sanitizeDisplayName(
profile.displayName || sanitizeHandle(profile.handle), profile.displayName || sanitizeHandle(profile.handle),
moderation.ui('displayName'), moderation.ui('displayName'),

View File

@ -58,6 +58,7 @@ import {useNavigation} from '@react-navigation/native'
import {parseTenorGif} from '#/lib/strings/embed-player' import {parseTenorGif} from '#/lib/strings/embed-player'
import {logger} from '#/logger' import {logger} from '#/logger'
import {NavigationProp} from 'lib/routes/types' import {NavigationProp} from 'lib/routes/types'
import {forceLTR} from 'lib/strings/bidi'
import {DM_SERVICE_HEADERS} from 'state/queries/messages/const' import {DM_SERVICE_HEADERS} from 'state/queries/messages/const'
import {useAgent} from 'state/session' import {useAgent} from 'state/session'
import {Button, ButtonText} from '#/components/Button' import {Button, ButtonText} from '#/components/Button'
@ -274,13 +275,15 @@ let FeedItem = ({
showDmButton={item.type === 'starterpack-joined' || isFollowBack} showDmButton={item.type === 'starterpack-joined' || isFollowBack}
/> />
<ExpandedAuthorsList visible={isAuthorsExpanded} authors={authors} /> <ExpandedAuthorsList visible={isAuthorsExpanded} authors={authors} />
<Text style={styles.meta}> <Text style={[styles.meta, a.self_start]}>
<TextLink <TextLink
key={authors[0].href} key={authors[0].href}
style={[pal.text, s.bold]} style={[pal.text, s.bold]}
href={authors[0].href} href={authors[0].href}
text={sanitizeDisplayName( text={forceLTR(
authors[0].profile.displayName || authors[0].profile.handle, sanitizeDisplayName(
authors[0].profile.displayName || authors[0].profile.handle,
),
)} )}
disableMismatchWarning disableMismatchWarning
/> />

View File

@ -281,7 +281,7 @@ let PostThreadItemLoaded = ({
<Link style={s.flex1} href={authorHref} title={authorTitle}> <Link style={s.flex1} href={authorHref} title={authorTitle}>
<Text <Text
type="xl-bold" type="xl-bold"
style={[pal.text]} style={[pal.text, a.self_start]}
numberOfLines={1} numberOfLines={1}
lineHeight={1.2}> lineHeight={1.2}>
{sanitizeDisplayName( {sanitizeDisplayName(

View File

@ -97,7 +97,7 @@ export function ProfileCard({
<View style={styles.layoutContent}> <View style={styles.layoutContent}>
<Text <Text
type="lg" type="lg"
style={[s.bold, pal.text]} style={[s.bold, pal.text, a.self_start]}
numberOfLines={1} numberOfLines={1}
lineHeight={1.2}> lineHeight={1.2}>
{sanitizeDisplayName( {sanitizeDisplayName(

View File

@ -6,6 +6,8 @@ import {useQueryClient} from '@tanstack/react-query'
import {precacheProfile} from '#/state/queries/profile' import {precacheProfile} from '#/state/queries/profile'
import {usePalette} from 'lib/hooks/usePalette' import {usePalette} from 'lib/hooks/usePalette'
import {makeProfileLink} from 'lib/routes/links' 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 {sanitizeDisplayName} from 'lib/strings/display-names'
import {sanitizeHandle} from 'lib/strings/handles' import {sanitizeHandle} from 'lib/strings/handles'
import {niceDate} from 'lib/strings/time' import {niceDate} from 'lib/strings/time'
@ -32,8 +34,6 @@ interface PostMetaOpts {
style?: StyleProp<ViewStyle> style?: StyleProp<ViewStyle>
} }
const NON_BREAKING_SPACE = '\u00A0'
let PostMeta = (opts: PostMetaOpts): React.ReactNode => { let PostMeta = (opts: PostMetaOpts): React.ReactNode => {
const pal = usePalette('default') const pal = usePalette('default')
const displayName = opts.author.displayName || opts.author.handle const displayName = opts.author.displayName || opts.author.handle
@ -70,14 +70,12 @@ let PostMeta = (opts: PostMetaOpts): React.ReactNode => {
style={[pal.text]} style={[pal.text]}
lineHeight={1.2} lineHeight={1.2}
disableMismatchWarning disableMismatchWarning
text={ text={forceLTR(
<> sanitizeDisplayName(
{sanitizeDisplayName( displayName,
displayName, opts.moderation?.ui('displayName'),
opts.moderation?.ui('displayName'), ),
)} )}
</>
}
href={profileLink} href={profileLink}
onBeforePress={onBeforePressAuthor} onBeforePress={onBeforePressAuthor}
/> />

View File

@ -68,6 +68,7 @@ import {navigate, resetToTab} from '#/Navigation'
import {Email2FAToggle} from './Email2FAToggle' import {Email2FAToggle} from './Email2FAToggle'
import {ExportCarDialog} from './ExportCarDialog' import {ExportCarDialog} from './ExportCarDialog'
import hairlineWidth = StyleSheet.hairlineWidth import hairlineWidth = StyleSheet.hairlineWidth
import {atoms as a} from '#/alf'
function SettingsAccountCard({ function SettingsAccountCard({
account, account,
@ -104,7 +105,7 @@ function SettingsAccountCard({
/> />
</View> </View>
<View style={[s.flex1]}> <View style={[s.flex1]}>
<Text type="md-bold" style={pal.text} numberOfLines={1}> <Text type="md-bold" style={[pal.text, a.self_start]} numberOfLines={1}>
{profile?.displayName || account.handle} {profile?.displayName || account.handle}
</Text> </Text>
<Text type="sm" style={pal.textLight} numberOfLines={1}> <Text type="sm" style={pal.textLight} numberOfLines={1}>

View File

@ -30,6 +30,7 @@ import {precacheProfile} from 'state/queries/profile'
import {Link} from '#/view/com/util/Link' import {Link} from '#/view/com/util/Link'
import {UserAvatar} from '#/view/com/util/UserAvatar' import {UserAvatar} from '#/view/com/util/UserAvatar'
import {Text} from 'view/com/util/text/Text' import {Text} from 'view/com/util/text/Text'
import {atoms as a} from '#/alf'
let SearchLinkCard = ({ let SearchLinkCard = ({
label, label,
@ -127,7 +128,7 @@ let SearchProfileCard = ({
<View style={{flex: 1}}> <View style={{flex: 1}}>
<Text <Text
type="lg" type="lg"
style={[s.bold, pal.text]} style={[s.bold, pal.text, a.self_start]}
numberOfLines={1} numberOfLines={1}
lineHeight={1.2}> lineHeight={1.2}>
{sanitizeDisplayName( {sanitizeDisplayName(