This commit is contained in:
xmflsct 2022-12-31 12:56:10 +01:00
parent f0734e52e7
commit 65e9f41a3b
6 changed files with 93 additions and 78 deletions

View File

@ -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<Props> = ({
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<Props> = ({
return ''
}
}
const startingOfText = useRef<boolean>(false)
const openingMentions = useRef<boolean>(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 (
<ParseEmojis
key={index}
content={node.data.replace(new RegExp(/^\s+/), '')}
content={content}
emojis={status?.emojis || emojis}
size={size}
adaptiveSize={adaptiveSize}
@ -108,6 +119,7 @@ const ParseHTML: React.FC<Props> = ({
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<Props> = ({
)
if (
matchedMention &&
!startingOfText.current &&
excludeMentions?.current.find(eM => eM.id === matchedMention.id)
) {
return null
@ -165,6 +176,7 @@ const ParseHTML: React.FC<Props> = ({
}
}
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<Props> = ({
}
}
}}
children={content !== href ? content : showFullLink ? href : content}
children={content}
/>
)
break

View File

@ -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<any>()
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 ? (
<CustomText
fontStyle='S'
style={{
marginLeft: StyleConstants.Spacing.S,
flexDirection: 'row',
color: colors.secondary
}}
style={{ flex: 1, marginLeft: StyleConstants.Spacing.S, color: colors.secondary }}
numberOfLines={1}
>
<>
{t('shared.header.shared.replies')}
{excludeMentions.current.map((mention, index) => (
<Fragment key={index}>
{' '}
<CustomText
style={{ color: colors.blue, paddingLeft: StyleConstants.Spacing.S }}
children={`@${mention.username}`}
onPress={() => navigation.push('Tab-Shared-Account', { account: mention })}
/>
</Fragment>
))}
</>
<Trans
ns='componentTimeline'
i18nKey='shared.header.shared.replies'
components={[
<>
{excludeMentions.current.map((mention, index) => (
<Fragment key={index}>
{index > 0 ? t('common:separator') : null}
<CustomText
style={{ color: colors.blue, paddingLeft: StyleConstants.Spacing.S }}
children={`@${mention.username}`}
onPress={() => navigation.push('Tab-Shared-Account', { account: mention })}
/>
</Fragment>
))}
</>
]}
/>
</CustomText>
) : null
}

View File

@ -122,7 +122,7 @@
"muted": {
"accessibilityLabel": "Toot muted"
},
"replies": "Replies",
"replies": "Replies <0 />",
"visibility": {
"direct": {
"accessibilityLabel": "Toot is a direct message"

View File

@ -83,7 +83,10 @@ const Root: React.FC<NativeStackScreenProps<TabPublicStackParamList, 'Tab-Public
swipeEnabled
renderScene={renderScene}
renderTabBar={() => 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 }}
/>

View File

@ -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<Props> = ({ account, myInfo }) => {
const { colors } = useTheme()
return (
<View style={[styles.fields, { borderTopColor: colors.border }]}>
<View
style={{
borderTopWidth: StyleSheet.hairlineWidth,
marginBottom: StyleConstants.Spacing.M,
borderTopColor: colors.border
}}
>
{account.fields.map((field, index) => (
<View key={index} style={[styles.field, { borderBottomColor: colors.border }]}>
<View style={[styles.fieldLeft, { borderRightColor: colors.border }]}>
<View
key={index}
style={[
{
flex: 1,
flexDirection: 'row',
borderBottomWidth: StyleSheet.hairlineWidth,
paddingTop: StyleConstants.Spacing.S,
paddingBottom: StyleConstants.Spacing.S,
borderBottomColor: colors.border
},
field.verified_at ? { backgroundColor: 'rgba(0, 255, 0, 0.035)' } : undefined
]}
>
<View
style={{
flex: 1,
flexDirection: 'row',
alignItems: 'center',
borderRightWidth: 1,
paddingLeft: StyleConstants.Spacing.S,
paddingRight: StyleConstants.Spacing.S,
borderRightColor: colors.border
}}
>
<ParseHTML
content={field.name}
size={'S'}
@ -30,16 +58,15 @@ const AccountInformationFields: React.FC<Props> = ({ account, myInfo }) => {
numberOfLines={5}
selectable
/>
{field.verified_at ? (
<Icon
name='CheckCircle'
size={StyleConstants.Font.Size.M}
color={colors.primaryDefault}
style={styles.fieldCheck}
/>
) : null}
</View>
<View style={styles.fieldRight}>
<View
style={{
flex: 2,
justifyContent: 'center',
paddingLeft: StyleConstants.Spacing.S,
paddingRight: StyleConstants.Spacing.S
}}
>
<ParseHTML
content={field.value}
size={'S'}
@ -55,33 +82,4 @@ const AccountInformationFields: React.FC<Props> = ({ 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

View File

@ -65,6 +65,8 @@ const TabSharedToot: React.FC<TabSharedStackScreenProps<'Tab-Shared-Toot'>> = ({
})
const heights = useRef<(number | undefined)[]>([])
const MAX_LEVEL = 10
const ARC = StyleConstants.Avatar.XS / 4
return (
<FlatList
@ -73,9 +75,6 @@ const TabSharedToot: React.FC<TabSharedStackScreenProps<'Tab-Shared-Toot'>> = ({
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<TabSharedStackScreenProps<'Tab-Shared-Toot'>> = ({
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<TabSharedStackScreenProps<'Tab-Shared-Toot'>> = ({
<>
<ComponentSeparator
extraMarginLeft={
toot.id === leadingItem.id
leadingItem.id === toot.id
? 0
: StyleConstants.Avatar.XS +
StyleConstants.Spacing.S +
Math.max(0, leadingItem._level - 1) * 8
Math.min(Math.max(0, leadingItem._level - 1), MAX_LEVEL) *
StyleConstants.Spacing.S
}
/>
{leadingItem._level > 1