1
0
mirror of https://github.com/tooot-app/app synced 2025-06-05 22:19:13 +02:00
This commit is contained in:
Zhiyuan Zheng
2021-05-30 23:39:07 +02:00
parent 8aa84f7568
commit a023ad58f1
9 changed files with 164 additions and 3 deletions

View File

@ -10,14 +10,16 @@ import TimelinePoll from '@components/Timeline/Shared/Poll'
import { useNavigation } from '@react-navigation/native'
import { StackNavigationProp } from '@react-navigation/stack'
import { QueryKeyTimeline } from '@utils/queryHooks/timeline'
import { getInstanceAccount } from '@utils/slices/instancesSlice'
import { getInstance, getInstanceAccount } from '@utils/slices/instancesSlice'
import { StyleConstants } from '@utils/styles/constants'
import { useTheme } from '@utils/styles/ThemeManager'
import htmlparser2 from 'htmlparser2-without-node-native'
import { uniqBy } from 'lodash'
import React, { useCallback } from 'react'
import { Pressable, StyleSheet, View } from 'react-native'
import { useSelector } from 'react-redux'
import TimelineActionsUsers from './Shared/ActionsUsers'
import TimelineFiltered, { shouldFilter } from './Shared/Filtered'
import TimelineFullConversation from './Shared/FullConversation'
import TimelineTranslate from './Shared/Translate'
@ -49,6 +51,16 @@ const TimelineDefault: React.FC<Props> = ({
let actualStatus = item.reblog ? item.reblog : item
const ownAccount = actualStatus.account.id === instanceAccount?.id
if (
!highlighted &&
queryKey &&
shouldFilter({ status: actualStatus, queryKey })
) {
return <TimelineFiltered />
}
const onPress = useCallback(() => {
analytics('timeline_default_press', {
page: queryKey ? queryKey[1].page : origin
@ -118,7 +130,7 @@ const TimelineDefault: React.FC<Props> = ({
statusId={actualStatus.id}
poll={actualStatus.poll}
reblog={item.reblog ? true : false}
sameAccount={actualStatus.account.id === instanceAccount?.id}
sameAccount={ownAccount}
/>
) : null}
{!disableDetails &&

View File

@ -17,6 +17,7 @@ import { uniqBy } from 'lodash'
import React, { useCallback } from 'react'
import { Pressable, StyleSheet, View } from 'react-native'
import { useSelector } from 'react-redux'
import TimelineFiltered, { shouldFilter } from './Shared/Filtered'
import TimelineFullConversation from './Shared/FullConversation'
export interface Props {
@ -30,6 +31,13 @@ const TimelineNotifications: React.FC<Props> = ({
queryKey,
highlighted = false
}) => {
if (
notification.status &&
shouldFilter({ status: notification.status, queryKey })
) {
return <TimelineFiltered />
}
const { theme } = useTheme()
const instanceAccount = useSelector(
getInstanceAccount,
@ -38,6 +46,7 @@ const TimelineNotifications: React.FC<Props> = ({
const navigation = useNavigation<
StackNavigationProp<Nav.TabLocalStackParamList>
>()
const actualAccount = notification.status
? notification.status.account
: notification.account

View File

@ -0,0 +1,105 @@
import { store } from '@root/store'
import { QueryKeyTimeline } from '@utils/queryHooks/timeline'
import { getInstance, getInstanceAccount } from '@utils/slices/instancesSlice'
import { StyleConstants } from '@utils/styles/constants'
import { useTheme } from '@utils/styles/ThemeManager'
import htmlparser2 from 'htmlparser2-without-node-native'
import React from 'react'
import { useTranslation } from 'react-i18next'
import { Text, View } from 'react-native'
const TimelineFiltered = React.memo(
() => {
const { theme } = useTheme()
const { t } = useTranslation('componentTimeline')
return (
<View style={{ backgroundColor: theme.backgroundDefault }}>
<Text
style={{
...StyleConstants.FontStyle.S,
color: theme.secondary,
textAlign: 'center',
paddingVertical: StyleConstants.Spacing.S,
paddingLeft: StyleConstants.Avatar.M + StyleConstants.Spacing.S
}}
>
{t('shared.filtered')}
</Text>
</View>
)
},
() => true
)
export const shouldFilter = ({
status,
queryKey
}: {
status: Mastodon.Status
queryKey: QueryKeyTimeline
}) => {
const instance = getInstance(store.getState())
const ownAccount =
getInstanceAccount(store.getState())?.id === status.account.id
let shouldFilter = false
if (queryKey && !ownAccount) {
const parser = new htmlparser2.Parser({
ontext (text: string) {
const checkFilter = (filter: Mastodon.Filter) => {
switch (filter.whole_word) {
case true:
if (new RegExp('\\b' + filter.phrase + '\\b').test(text)) {
shouldFilter = true
}
break
case false:
if (new RegExp(filter.phrase).test(text)) {
shouldFilter = true
}
break
}
}
instance?.filters.forEach(filter => {
if (filter.expires_at) {
if (new Date().getTime() > new Date(filter.expires_at).getTime()) {
return
}
}
switch (queryKey[1].page) {
case 'Following':
case 'Local':
case 'List':
case 'Account_Default':
if (filter.context.includes('home')) {
checkFilter(filter)
}
break
case 'Notifications':
if (filter.context.includes('notifications')) {
checkFilter(filter)
}
break
case 'LocalPublic':
if (filter.context.includes('public')) {
checkFilter(filter)
}
break
case 'Toot':
if (filter.context.includes('thread')) {
checkFilter(filter)
}
}
})
}
})
parser.write(status.content)
parser.end()
}
return shouldFilter
}
export default TimelineFiltered