diff --git a/src/components/Parse/HTML.tsx b/src/components/Parse/HTML.tsx index 4ff3436f..246f839a 100644 --- a/src/components/Parse/HTML.tsx +++ b/src/components/Parse/HTML.tsx @@ -15,7 +15,7 @@ import { ElementType, parseDocument } from 'htmlparser2' import i18next from 'i18next' import React, { useContext, useRef, useState } from 'react' import { useTranslation } from 'react-i18next' -import { Platform, Pressable, Text, TextStyleIOS, View } from 'react-native' +import { Platform, Pressable, Text, View } from 'react-native' export interface Props { content: string @@ -78,8 +78,8 @@ const ParseHTML: React.FC = ({ return node.data case ElementType.Tag: if (node.name === 'span') { - if (node.attribs.class?.includes('invisible')) return '' - if (node.attribs.class?.includes('ellipsis')) + if (node.attribs.class?.includes('invisible') && !showFullLink) return '' + if (node.attribs.class?.includes('ellipsis') && !showFullLink) return node.children.map(child => unwrapNode(child)).join('') + '...' } return node.children.map(child => unwrapNode(child)).join('') @@ -87,15 +87,26 @@ const ParseHTML: React.FC = ({ return '' } } - const startingOfText = useRef(false) + const openingMentions = useRef(true) const renderNode = (node: ChildNode, index: number) => { switch (node.type) { case ElementType.Text: - node.data.trim().length && (startingOfText.current = true) // Removing empty spaces appeared between tags and mentions + let content: string = node.data + if (openingMentions.current) { + if (node.data.trim().length) { + openingMentions.current = false // Removing empty spaces appeared between tags and mentions + content = excludeMentions?.current.length + ? node.data.replace(new RegExp(/^\s+/), '') + : node.data + } else { + content = node.data.trim() + } + } + return ( = ({ const href = node.attribs.href if (classes) { if (classes.includes('hashtag')) { + openingMentions.current = false const tag = href.match(new RegExp(/\/tags?\/(.*)/, 'i'))?.[1].toLowerCase() const paramsHashtag = (params as { hashtag: Mastodon.Tag['name'] } | undefined) ?.hashtag @@ -142,7 +154,6 @@ const ParseHTML: React.FC = ({ ) if ( matchedMention && - !startingOfText.current && excludeMentions?.current.find(eM => eM.id === matchedMention.id) ) { return null @@ -165,6 +176,7 @@ const ParseHTML: React.FC = ({ } } + openingMentions.current = false const content = node.children.map(child => unwrapNode(child)).join('') const shouldBeTag = status?.tags?.find(tag => `#${tag.name}` === content) return ( @@ -182,7 +194,7 @@ const ParseHTML: React.FC = ({ } } }} - children={content !== href ? content : showFullLink ? href : content} + children={content} /> ) break diff --git a/src/components/Timeline/Shared/HeaderShared/Replies.tsx b/src/components/Timeline/Shared/HeaderShared/Replies.tsx index ff48e5f2..7dab01bd 100644 --- a/src/components/Timeline/Shared/HeaderShared/Replies.tsx +++ b/src/components/Timeline/Shared/HeaderShared/Replies.tsx @@ -3,7 +3,7 @@ import { useNavigation } from '@react-navigation/native' import { StyleConstants } from '@utils/styles/constants' import { useTheme } from '@utils/styles/ThemeManager' import React, { Fragment, useContext } from 'react' -import { useTranslation } from 'react-i18next' +import { Trans, useTranslation } from 'react-i18next' import StatusContext from '../Context' const HeaderSharedReplies: React.FC = () => { @@ -11,7 +11,7 @@ const HeaderSharedReplies: React.FC = () => { if (!isConversation) return null const navigation = useNavigation() - const { t } = useTranslation('componentTimeline') + const { t } = useTranslation(['common', 'componentTimeline']) const { colors } = useTheme() const mentionsBeginning = rawContent?.current?.[0] @@ -26,25 +26,27 @@ const HeaderSharedReplies: React.FC = () => { return excludeMentions?.current.length ? ( - <> - {t('shared.header.shared.replies')} - {excludeMentions.current.map((mention, index) => ( - - {' '} - navigation.push('Tab-Shared-Account', { account: mention })} - /> - - ))} - + + {excludeMentions.current.map((mention, index) => ( + + {index > 0 ? t('common:separator') : null} + navigation.push('Tab-Shared-Account', { account: mention })} + /> + + ))} + + ]} + /> ) : null } diff --git a/src/i18n/en/components/timeline.json b/src/i18n/en/components/timeline.json index 362cbe3e..77492cad 100644 --- a/src/i18n/en/components/timeline.json +++ b/src/i18n/en/components/timeline.json @@ -122,7 +122,7 @@ "muted": { "accessibilityLabel": "Toot muted" }, - "replies": "Replies", + "replies": "Replies <0 />", "visibility": { "direct": { "accessibilityLabel": "Toot is a direct message" diff --git a/src/screens/Tabs/Public/Root.tsx b/src/screens/Tabs/Public/Root.tsx index ac7c11e0..613e818b 100644 --- a/src/screens/Tabs/Public/Root.tsx +++ b/src/screens/Tabs/Public/Root.tsx @@ -83,7 +83,10 @@ const Root: React.FC null} - onIndexChange={index => setSegment(index)} + onIndexChange={index => { + setSegment(index) + setGlobalStorage('app.prev_public_segment', segments[index]) + }} navigationState={{ index: segment, routes }} initialLayout={{ width: Dimensions.get('window').width }} /> diff --git a/src/screens/Tabs/Shared/Account/Information/Fields.tsx b/src/screens/Tabs/Shared/Account/Information/Fields.tsx index f5c083df..824739a5 100644 --- a/src/screens/Tabs/Shared/Account/Information/Fields.tsx +++ b/src/screens/Tabs/Shared/Account/Information/Fields.tsx @@ -1,4 +1,3 @@ -import Icon from '@components/Icon' import { ParseHTML } from '@components/Parse' import { StyleConstants } from '@utils/styles/constants' import { useTheme } from '@utils/styles/ThemeManager' @@ -18,10 +17,39 @@ const AccountInformationFields: React.FC = ({ account, myInfo }) => { const { colors } = useTheme() return ( - + {account.fields.map((field, index) => ( - - + + = ({ account, myInfo }) => { numberOfLines={5} selectable /> - {field.verified_at ? ( - - ) : null} - + = ({ account, myInfo }) => { ) } -const styles = StyleSheet.create({ - fields: { - borderTopWidth: StyleSheet.hairlineWidth, - marginBottom: StyleConstants.Spacing.M - }, - field: { - flex: 1, - flexDirection: 'row', - borderBottomWidth: StyleSheet.hairlineWidth, - paddingTop: StyleConstants.Spacing.S, - paddingBottom: StyleConstants.Spacing.S - }, - fieldLeft: { - flex: 1, - flexDirection: 'row', - alignItems: 'center', - borderRightWidth: 1, - paddingLeft: StyleConstants.Spacing.S, - paddingRight: StyleConstants.Spacing.S - }, - fieldCheck: { marginLeft: StyleConstants.Spacing.XS }, - fieldRight: { - flex: 2, - justifyContent: 'center', - paddingLeft: StyleConstants.Spacing.S, - paddingRight: StyleConstants.Spacing.S - } -}) - export default AccountInformationFields diff --git a/src/screens/Tabs/Shared/Toot.tsx b/src/screens/Tabs/Shared/Toot.tsx index 8b0149cf..5d11abe6 100644 --- a/src/screens/Tabs/Shared/Toot.tsx +++ b/src/screens/Tabs/Shared/Toot.tsx @@ -65,6 +65,8 @@ const TabSharedToot: React.FC> = ({ }) const heights = useRef<(number | undefined)[]>([]) + const MAX_LEVEL = 10 + const ARC = StyleConstants.Avatar.XS / 4 return ( > = ({ windowSize={7} data={data?.body} renderItem={({ item, index }) => { - const MAX_LEVEL = 10 - const ARC = StyleConstants.Avatar.XS / 4 - const prev = data?.body[index - 1]?._level || 0 const curr = item._level const next = data?.body[index + 1]?._level || 0 @@ -85,7 +84,7 @@ const TabSharedToot: React.FC> = ({ style={{ paddingLeft: index > (data?.highlightIndex || 0) - ? Math.min(item._level, MAX_LEVEL) * StyleConstants.Spacing.S + ? Math.min(item._level - 1, MAX_LEVEL) * StyleConstants.Spacing.S : undefined }} onLayout={({ @@ -206,11 +205,12 @@ const TabSharedToot: React.FC> = ({ <> {leadingItem._level > 1