mirror of
https://github.com/tooot-app/app
synced 2025-06-05 22:19:13 +02:00
Update translations
This commit is contained in:
@ -1,4 +1,4 @@
|
||||
import React, { useRef } from 'react'
|
||||
import React from 'react'
|
||||
import { Dimensions, Modal, StyleSheet, View } from 'react-native'
|
||||
import { useSafeAreaInsets } from 'react-native-safe-area-context'
|
||||
import { useTheme } from '@utils/styles/ThemeManager'
|
||||
|
@ -12,6 +12,7 @@ import {
|
||||
} from '@utils/slices/instancesSlice'
|
||||
import { StyleConstants } from '@utils/styles/constants'
|
||||
import { useTheme } from '@utils/styles/ThemeManager'
|
||||
import * as Linking from 'expo-linking'
|
||||
import { debounce } from 'lodash'
|
||||
import React, { useCallback, useEffect, useMemo, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
@ -36,7 +37,7 @@ const ComponentInstance: React.FC<Props> = ({
|
||||
const navigation = useNavigation()
|
||||
const dispatch = useDispatch()
|
||||
const queryClient = useQueryClient()
|
||||
const { t } = useTranslation('meRoot')
|
||||
const { t } = useTranslation('componentInstance')
|
||||
const { theme } = useTheme()
|
||||
const [instanceDomain, setInstanceDomain] = useState<string | undefined>()
|
||||
const [appData, setApplicationData] = useState<InstanceLocal['appData']>()
|
||||
@ -92,13 +93,14 @@ const ComponentInstance: React.FC<Props> = ({
|
||||
.length
|
||||
) {
|
||||
Alert.alert(
|
||||
'域名已存在',
|
||||
'可以登录同个域名的另外一个账户,现有账户🈚️用',
|
||||
t('update.local.alert.title'),
|
||||
t('update.local.alert.message'),
|
||||
[
|
||||
{ text: '取消', style: 'cancel' },
|
||||
{ text: t('update.local.alert.buttons.cancel'), style: 'cancel' },
|
||||
{
|
||||
text: '继续',
|
||||
text: t('update.local.alert.buttons.continue'),
|
||||
onPress: () => {
|
||||
setApplicationData(undefined)
|
||||
applicationQuery.refetch()
|
||||
}
|
||||
}
|
||||
@ -116,8 +118,8 @@ const ComponentInstance: React.FC<Props> = ({
|
||||
]
|
||||
dispatch(remoteUpdate(instanceDomain))
|
||||
queryClient.resetQueries(queryKey)
|
||||
toast({ type: 'success', message: '重置成功' })
|
||||
navigation.navigate('Screen-Public', { screen: 'Screen-Public-Root' })
|
||||
toast({ type: 'success', message: t('update.remote.succeed') })
|
||||
navigation.goBack()
|
||||
break
|
||||
}
|
||||
}
|
||||
@ -143,9 +145,9 @@ const ComponentInstance: React.FC<Props> = ({
|
||||
const buttonContent = useMemo(() => {
|
||||
switch (type) {
|
||||
case 'local':
|
||||
return t('content.login.button')
|
||||
return t('server.button.local')
|
||||
case 'remote':
|
||||
return '登记'
|
||||
return t('server.button.remote')
|
||||
}
|
||||
}, [])
|
||||
|
||||
@ -176,7 +178,7 @@ const ComponentInstance: React.FC<Props> = ({
|
||||
keyboardType='url'
|
||||
textContentType='URL'
|
||||
onSubmitEditing={onSubmitEditing}
|
||||
placeholder={t('content.login.server.placeholder')}
|
||||
placeholder={t('server.textInput.placeholder')}
|
||||
placeholderTextColor={theme.secondary}
|
||||
returnKeyType='go'
|
||||
/>
|
||||
@ -191,21 +193,21 @@ const ComponentInstance: React.FC<Props> = ({
|
||||
<View>
|
||||
<InstanceInfo
|
||||
visible={instanceQuery.data?.title !== undefined}
|
||||
header='实例名称'
|
||||
header={t('server.information.name')}
|
||||
content={instanceQuery.data?.title || undefined}
|
||||
potentialWidth={10}
|
||||
/>
|
||||
<InstanceInfo
|
||||
visible={instanceQuery.data?.short_description !== undefined}
|
||||
header='实例介绍'
|
||||
header={t('server.information.description.heading')}
|
||||
content={instanceQuery.data?.short_description || undefined}
|
||||
potentialLines={5}
|
||||
/>
|
||||
<View style={styles.instanceStats}>
|
||||
<InstanceInfo
|
||||
style={{ alignItems: 'flex-start' }}
|
||||
visible={instanceQuery.data?.stats?.user_count !== null}
|
||||
header='用户总数'
|
||||
visible={instanceQuery.data?.stats?.user_count === null}
|
||||
header={t('server.information.accounts')}
|
||||
content={
|
||||
instanceQuery.data?.stats?.user_count?.toString() || undefined
|
||||
}
|
||||
@ -213,8 +215,8 @@ const ComponentInstance: React.FC<Props> = ({
|
||||
/>
|
||||
<InstanceInfo
|
||||
style={{ alignItems: 'center' }}
|
||||
visible={instanceQuery.data?.stats?.status_count !== null}
|
||||
header='嘟嘟总数'
|
||||
visible={instanceQuery.data?.stats?.status_count === null}
|
||||
header={t('server.information.statuses')}
|
||||
content={
|
||||
instanceQuery.data?.stats?.status_count?.toString() || undefined
|
||||
}
|
||||
@ -222,22 +224,31 @@ const ComponentInstance: React.FC<Props> = ({
|
||||
/>
|
||||
<InstanceInfo
|
||||
style={{ alignItems: 'flex-end' }}
|
||||
visible={instanceQuery.data?.stats?.domain_count !== null}
|
||||
header='嘟嘟总数'
|
||||
visible={instanceQuery.data?.stats?.domain_count === null}
|
||||
header={t('server.information.domains')}
|
||||
content={
|
||||
instanceQuery.data?.stats?.domain_count?.toString() || undefined
|
||||
}
|
||||
potentialWidth={4}
|
||||
/>
|
||||
</View>
|
||||
<Text style={[styles.disclaimer, { color: theme.secondary }]}>
|
||||
<View style={styles.disclaimer}>
|
||||
<Icon
|
||||
name='Lock'
|
||||
size={StyleConstants.Font.Size.M}
|
||||
size={StyleConstants.Font.Size.S}
|
||||
color={theme.secondary}
|
||||
/>{' '}
|
||||
本站不留存任何信息
|
||||
</Text>
|
||||
style={styles.disclaimerIcon}
|
||||
/>
|
||||
<Text
|
||||
style={[styles.disclaimerText, { color: theme.secondary }]}
|
||||
onPress={() => Linking.openURL('https://tooot.app/privacy')}
|
||||
>
|
||||
{t('server.disclaimer')}
|
||||
<Text style={{ color: theme.blue }}>
|
||||
https://tooot.app/privacy
|
||||
</Text>
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
|
||||
@ -275,9 +286,18 @@ const styles = StyleSheet.create({
|
||||
flexDirection: 'row'
|
||||
},
|
||||
disclaimer: {
|
||||
...StyleConstants.FontStyle.S,
|
||||
flexDirection: 'row',
|
||||
marginHorizontal: StyleConstants.Spacing.Global.PagePadding,
|
||||
marginVertical: StyleConstants.Spacing.M
|
||||
},
|
||||
disclaimerIcon: {
|
||||
marginTop:
|
||||
(StyleConstants.Font.LineHeight.S - StyleConstants.Font.Size.S) / 2,
|
||||
marginRight: StyleConstants.Spacing.XS
|
||||
},
|
||||
disclaimerText: {
|
||||
flex: 1,
|
||||
...StyleConstants.FontStyle.S
|
||||
}
|
||||
})
|
||||
|
||||
|
@ -3,6 +3,7 @@ import { StyleConstants } from '@utils/styles/constants'
|
||||
import { useTheme } from '@utils/styles/ThemeManager'
|
||||
import { LinearGradient } from 'expo-linear-gradient'
|
||||
import React from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { Dimensions, StyleSheet, Text, View, ViewStyle } from 'react-native'
|
||||
import { createShimmerPlaceholder } from 'react-native-shimmer-placeholder'
|
||||
|
||||
@ -24,6 +25,7 @@ const InstanceInfo = React.memo(
|
||||
potentialWidth,
|
||||
potentialLines = 1
|
||||
}: Props) => {
|
||||
const { t } = useTranslation('componentInstance')
|
||||
const { theme } = useTheme()
|
||||
const ShimmerPlaceholder = createShimmerPlaceholder(LinearGradient)
|
||||
|
||||
@ -40,14 +42,18 @@ const InstanceInfo = React.memo(
|
||||
StyleConstants.Spacing.Global.PagePadding * 4
|
||||
}
|
||||
height={StyleConstants.Font.LineHeight.M * potentialLines}
|
||||
shimmerColors={[theme.shimmerDefault, theme.shimmerHighlight, theme.shimmerDefault]}
|
||||
shimmerColors={[
|
||||
theme.shimmerDefault,
|
||||
theme.shimmerHighlight,
|
||||
theme.shimmerDefault
|
||||
]}
|
||||
>
|
||||
{content ? (
|
||||
<ParseHTML
|
||||
content={content}
|
||||
size={'M'}
|
||||
numberOfLines={5}
|
||||
expandHint='介绍'
|
||||
expandHint={t('server.information.description.expandHint')}
|
||||
/>
|
||||
) : null}
|
||||
</ShimmerPlaceholder>
|
||||
|
@ -19,7 +19,7 @@ export interface Props {
|
||||
switchDisabled?: boolean
|
||||
switchOnValueChange?: () => void
|
||||
|
||||
iconBack?: 'ChevronRight' | 'Check'
|
||||
iconBack?: 'ChevronRight' | 'ExternalLink'
|
||||
iconBackColor?: ColorDefinitions
|
||||
|
||||
loading?: boolean
|
||||
|
@ -1,8 +1,8 @@
|
||||
import { StyleConstants } from '@utils/styles/constants'
|
||||
import { useTheme } from '@utils/styles/ThemeManager'
|
||||
import React from 'react'
|
||||
import { StyleSheet, Text } from 'react-native'
|
||||
import { Image } from 'react-native-expo-image-cache'
|
||||
import { useTheme } from '@utils/styles/ThemeManager'
|
||||
import { StyleConstants } from '@utils/styles/constants'
|
||||
|
||||
const regexEmoji = new RegExp(/(:[A-Za-z0-9_]+:)/)
|
||||
|
||||
|
@ -7,6 +7,7 @@ import layoutAnimation from '@utils/styles/layoutAnimation'
|
||||
import { useTheme } from '@utils/styles/ThemeManager'
|
||||
import { LinearGradient } from 'expo-linear-gradient'
|
||||
import React, { useCallback, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { Pressable, Text, View } from 'react-native'
|
||||
import HTMLView from 'react-native-htmlview'
|
||||
|
||||
@ -191,6 +192,7 @@ const ParseHTML: React.FC<Props> = ({
|
||||
}, [])
|
||||
const rootComponent = useCallback(
|
||||
({ children }) => {
|
||||
const { t } = useTranslation('componentParse')
|
||||
const lineHeight = StyleConstants.Font.LineHeight[size]
|
||||
|
||||
const [expandAllow, setExpandAllow] = useState(false)
|
||||
@ -249,7 +251,9 @@ const ParseHTML: React.FC<Props> = ({
|
||||
color: theme.primary
|
||||
}}
|
||||
>
|
||||
{`${expanded ? '折叠' : '展开'}${expandHint}`}
|
||||
{expanded
|
||||
? t('HTML.expanded.true', { hint: expandHint })
|
||||
: t('HTML.expanded.false', { hint: expandHint })}
|
||||
</Text>
|
||||
</LinearGradient>
|
||||
</Pressable>
|
||||
|
@ -16,7 +16,7 @@ export interface Props {
|
||||
|
||||
const RelationshipOutgoing = React.memo(
|
||||
({ id }: Props) => {
|
||||
const { t } = useTranslation()
|
||||
const { t } = useTranslation('componentRelationship')
|
||||
|
||||
const query = useRelationshipQuery({ id })
|
||||
|
||||
@ -30,12 +30,12 @@ const RelationshipOutgoing = React.memo(
|
||||
[res]
|
||||
)
|
||||
},
|
||||
onError: (err: any, { type }) => {
|
||||
onError: (err: any, { payload: { action } }) => {
|
||||
haptics('Error')
|
||||
toast({
|
||||
type: 'error',
|
||||
message: t('common:toastMessage.error.message', {
|
||||
function: t(`relationship:${type}.function`)
|
||||
function: t(`button.${action}.function`)
|
||||
}),
|
||||
...(err.status &&
|
||||
typeof err.status === 'number' &&
|
||||
@ -52,15 +52,15 @@ const RelationshipOutgoing = React.memo(
|
||||
let onPress: () => void
|
||||
|
||||
if (query.isError) {
|
||||
content = t('relationship:button.error')
|
||||
content = t('button.error')
|
||||
onPress = () => {}
|
||||
} else {
|
||||
if (query.data?.blocked_by) {
|
||||
content = t('relationship:button.blocked_by')
|
||||
content = t('button.blocked_by')
|
||||
onPress = () => null
|
||||
} else {
|
||||
if (query.data?.blocking) {
|
||||
content = t('relationship:button.blocking')
|
||||
content = t('button.blocking')
|
||||
onPress = () =>
|
||||
mutation.mutate({
|
||||
id,
|
||||
@ -72,7 +72,7 @@ const RelationshipOutgoing = React.memo(
|
||||
})
|
||||
} else {
|
||||
if (query.data?.following) {
|
||||
content = t('relationship:button.following')
|
||||
content = t('button.following')
|
||||
onPress = () =>
|
||||
mutation.mutate({
|
||||
id,
|
||||
@ -84,7 +84,7 @@ const RelationshipOutgoing = React.memo(
|
||||
})
|
||||
} else {
|
||||
if (query.data?.requested) {
|
||||
content = t('relationship:button.requested')
|
||||
content = t('button.requested')
|
||||
onPress = () =>
|
||||
mutation.mutate({
|
||||
id,
|
||||
@ -95,7 +95,7 @@ const RelationshipOutgoing = React.memo(
|
||||
}
|
||||
})
|
||||
} else {
|
||||
content = t('relationship:button.default')
|
||||
content = t('button.default')
|
||||
onPress = () =>
|
||||
mutation.mutate({
|
||||
id,
|
||||
|
@ -10,7 +10,7 @@ export interface Props {
|
||||
}
|
||||
|
||||
const RelativeTime: React.FC<Props> = ({ date }) => {
|
||||
const { t } = useTranslation('relativeTime')
|
||||
const { t } = useTranslation('componentRelativeTime')
|
||||
|
||||
return (
|
||||
<TimeAgo
|
||||
|
@ -15,7 +15,7 @@ export interface Props {
|
||||
|
||||
const TimelineEmpty: React.FC<Props> = ({ status, refetch }) => {
|
||||
const { mode, theme } = useTheme()
|
||||
const { t, i18n } = useTranslation('timeline')
|
||||
const { t, i18n } = useTranslation('componentTimeline')
|
||||
|
||||
const children = useMemo(() => {
|
||||
switch (status) {
|
||||
|
@ -20,7 +20,7 @@ const TimelineEnd: React.FC<Props> = ({ hasNextPage }) => {
|
||||
) : (
|
||||
<Text style={[styles.text, { color: theme.secondary }]}>
|
||||
<Trans
|
||||
i18nKey='timeline:shared.end.message'
|
||||
i18nKey='componentTimeline:end.message'
|
||||
components={[
|
||||
<Icon
|
||||
name='Coffee'
|
||||
|
@ -4,11 +4,13 @@ import { StyleConstants } from '@root/utils/styles/constants'
|
||||
import { useTheme } from '@root/utils/styles/ThemeManager'
|
||||
import { updatePublicRemoteNotice } from '@utils/slices/contextsSlice'
|
||||
import React from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { StyleSheet, Text, View } from 'react-native'
|
||||
import { useDispatch } from 'react-redux'
|
||||
|
||||
const TimelineHeader = React.memo(
|
||||
() => {
|
||||
const { t } = useTranslation('componentTimeline')
|
||||
const dispatch = useDispatch()
|
||||
const navigation = useNavigation()
|
||||
const { theme } = useTheme()
|
||||
@ -16,7 +18,7 @@ const TimelineHeader = React.memo(
|
||||
return (
|
||||
<View style={[styles.base, { borderColor: theme.border }]}>
|
||||
<Text style={[styles.text, { color: theme.primary }]}>
|
||||
一大堆文字一大堆文字一大堆文字一大堆文字一大堆文字一大堆文字一大堆文字一大堆文字一大堆文字一大堆文字一大堆文字一大堆文字一大堆文字一大堆文字一大堆文字一大堆文字一大堆文字一大堆文字{' '}
|
||||
{t('header.explanation')}
|
||||
<Text
|
||||
style={{ color: theme.blue }}
|
||||
onPress={() => {
|
||||
@ -27,7 +29,7 @@ const TimelineHeader = React.memo(
|
||||
})
|
||||
}}
|
||||
>
|
||||
前往设置{' '}
|
||||
{t('header.button')}
|
||||
<Icon
|
||||
name='ArrowRight'
|
||||
size={StyleConstants.Font.Size.S}
|
||||
|
@ -18,7 +18,7 @@ const TimelineActioned: React.FC<Props> = ({
|
||||
action,
|
||||
notification = false
|
||||
}) => {
|
||||
const { t } = useTranslation('timeline')
|
||||
const { t } = useTranslation('componentTimeline')
|
||||
const { theme } = useTheme()
|
||||
const navigation = useNavigation()
|
||||
const name = account.display_name || account.username
|
||||
|
@ -11,14 +11,7 @@ import { StyleConstants } from '@utils/styles/constants'
|
||||
import { useTheme } from '@utils/styles/ThemeManager'
|
||||
import React, { useCallback, useMemo } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import {
|
||||
Platform,
|
||||
Pressable,
|
||||
Share,
|
||||
StyleSheet,
|
||||
Text,
|
||||
View
|
||||
} from 'react-native'
|
||||
import { Pressable, StyleSheet, Text, View } from 'react-native'
|
||||
import { useQueryClient } from 'react-query'
|
||||
|
||||
export interface Props {
|
||||
@ -29,7 +22,7 @@ export interface Props {
|
||||
|
||||
const TimelineActions: React.FC<Props> = ({ queryKey, status, reblog }) => {
|
||||
const navigation = useNavigation()
|
||||
const { t } = useTranslation()
|
||||
const { t } = useTranslation('componentTimeline')
|
||||
const { theme } = useTheme()
|
||||
const iconColor = theme.secondary
|
||||
const iconColorAction = (state: boolean) =>
|
||||
@ -84,7 +77,7 @@ const TimelineActions: React.FC<Props> = ({ queryKey, status, reblog }) => {
|
||||
type: 'error',
|
||||
message: t('common:toastMessage.error.message', {
|
||||
function: t(
|
||||
`timeline:shared.actions.${correctParam.payload.property}.function`
|
||||
`shared.actions.${correctParam.payload.property}.function`
|
||||
)
|
||||
}),
|
||||
...(err.status &&
|
||||
@ -95,7 +88,7 @@ const TimelineActions: React.FC<Props> = ({ queryKey, status, reblog }) => {
|
||||
description: err.data.error
|
||||
})
|
||||
})
|
||||
queryClient.setQueryData(queryKey, oldData)
|
||||
queryClient.invalidateQueries(queryKey)
|
||||
}
|
||||
})
|
||||
|
||||
@ -150,18 +143,6 @@ const TimelineActions: React.FC<Props> = ({ queryKey, status, reblog }) => {
|
||||
}),
|
||||
[status.bookmarked]
|
||||
)
|
||||
const onPressShare = useCallback(() => {
|
||||
switch (Platform.OS) {
|
||||
case 'ios':
|
||||
return Share.share({
|
||||
url: status.uri
|
||||
})
|
||||
case 'android':
|
||||
return Share.share({
|
||||
message: status.uri
|
||||
})
|
||||
}
|
||||
}, [])
|
||||
|
||||
const childrenReply = useMemo(
|
||||
() => (
|
||||
@ -220,12 +201,6 @@ const TimelineActions: React.FC<Props> = ({ queryKey, status, reblog }) => {
|
||||
),
|
||||
[status.bookmarked]
|
||||
)
|
||||
const childrenShare = useMemo(
|
||||
() => (
|
||||
<Icon name='Share2' color={iconColor} size={StyleConstants.Font.Size.L} />
|
||||
),
|
||||
[]
|
||||
)
|
||||
|
||||
return (
|
||||
<>
|
||||
@ -256,12 +231,6 @@ const TimelineActions: React.FC<Props> = ({ queryKey, status, reblog }) => {
|
||||
onPress={onPressBookmark}
|
||||
children={childrenBookmark}
|
||||
/>
|
||||
|
||||
<Pressable
|
||||
style={styles.action}
|
||||
onPress={onPressShare}
|
||||
children={childrenShare}
|
||||
/>
|
||||
</View>
|
||||
</>
|
||||
)
|
||||
@ -269,16 +238,13 @@ const TimelineActions: React.FC<Props> = ({ queryKey, status, reblog }) => {
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
actions: {
|
||||
width: '100%',
|
||||
flex: 1,
|
||||
flexDirection: 'row',
|
||||
marginTop: StyleConstants.Spacing.S
|
||||
},
|
||||
action: {
|
||||
width: '20%',
|
||||
flex: 1,
|
||||
flexDirection: 'row',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
paddingVertical: StyleConstants.Spacing.S
|
||||
}
|
||||
})
|
||||
|
@ -17,7 +17,7 @@ export interface Props {
|
||||
}
|
||||
|
||||
const TimelineAttachment: React.FC<Props> = ({ status }) => {
|
||||
const { t } = useTranslation('timeline')
|
||||
const { t } = useTranslation('componentTimeline')
|
||||
|
||||
const [sensitiveShown, setSensitiveShown] = useState(status.sensitive)
|
||||
const onPressBlurView = useCallback(() => {
|
||||
|
@ -22,7 +22,7 @@ const AttachmentUnsupported: React.FC<Props> = ({
|
||||
sensitiveShown,
|
||||
attachment
|
||||
}) => {
|
||||
const { t } = useTranslation('timeline')
|
||||
const { t } = useTranslation('componentTimeline')
|
||||
const { theme } = useTheme()
|
||||
|
||||
return (
|
||||
|
@ -17,7 +17,7 @@ const TimelineContent: React.FC<Props> = ({
|
||||
highlighted = false,
|
||||
disableDetails = false
|
||||
}) => {
|
||||
const { t } = useTranslation('timeline')
|
||||
const { t } = useTranslation('componentTimeline')
|
||||
|
||||
return (
|
||||
<>
|
||||
|
@ -20,30 +20,29 @@ const HeaderActionsAccount: React.FC<Props> = ({
|
||||
account,
|
||||
setBottomSheetVisible
|
||||
}) => {
|
||||
const { t } = useTranslation()
|
||||
const { t } = useTranslation('componentTimeline')
|
||||
|
||||
const queryClient = useQueryClient()
|
||||
const mutateion = useTimelineMutation({
|
||||
queryClient,
|
||||
onSuccess: (_, { type }) => {
|
||||
onSuccess: (_, { payload: { property } }) => {
|
||||
haptics('Success')
|
||||
toast({
|
||||
type: 'success',
|
||||
message: t('common:toastMessage.success.message', {
|
||||
function: t(
|
||||
`timeline:shared.header.default.actions.account.${type}.function`,
|
||||
{ acct: account.acct }
|
||||
)
|
||||
function: t(`shared.header.actions.account.${property}.function`, {
|
||||
acct: account.acct
|
||||
})
|
||||
})
|
||||
})
|
||||
},
|
||||
onError: (err: any, { type }) => {
|
||||
onError: (err: any, { payload: { property } }) => {
|
||||
haptics('Error')
|
||||
toast({
|
||||
type: 'error',
|
||||
message: t('common:toastMessage.error.message', {
|
||||
function: t(
|
||||
`timeline:shared.header.default.actions.account.${type}.function`,
|
||||
`shared.header.actions.account.${property}.function`,
|
||||
{ acct: account.acct }
|
||||
)
|
||||
}),
|
||||
@ -64,7 +63,7 @@ const HeaderActionsAccount: React.FC<Props> = ({
|
||||
return (
|
||||
<MenuContainer>
|
||||
<MenuHeader
|
||||
heading={t('timeline:shared.header.default.actions.account.heading')}
|
||||
heading={t('shared.header.actions.account.heading')}
|
||||
/>
|
||||
<MenuRow
|
||||
onPress={() => {
|
||||
@ -77,7 +76,7 @@ const HeaderActionsAccount: React.FC<Props> = ({
|
||||
})
|
||||
}}
|
||||
iconFront='EyeOff'
|
||||
title={t('timeline:shared.header.default.actions.account.mute.button', {
|
||||
title={t('shared.header.actions.account.mute.button', {
|
||||
acct: account.acct
|
||||
})}
|
||||
/>
|
||||
@ -93,7 +92,7 @@ const HeaderActionsAccount: React.FC<Props> = ({
|
||||
}}
|
||||
iconFront='XCircle'
|
||||
title={t(
|
||||
'timeline:shared.header.default.actions.account.block.button',
|
||||
'shared.header.actions.account.block.button',
|
||||
{
|
||||
acct: account.acct
|
||||
}
|
||||
@ -111,7 +110,7 @@ const HeaderActionsAccount: React.FC<Props> = ({
|
||||
}}
|
||||
iconFront='Flag'
|
||||
title={t(
|
||||
'timeline:shared.header.default.actions.account.report.button',
|
||||
'shared.header.actions.account.reports.button',
|
||||
{
|
||||
acct: account.acct
|
||||
}
|
@ -22,7 +22,7 @@ const HeaderActionsDomain: React.FC<Props> = ({
|
||||
domain,
|
||||
setBottomSheetVisible
|
||||
}) => {
|
||||
const { t } = useTranslation()
|
||||
const { t } = useTranslation('componentTimeline')
|
||||
const queryClient = useQueryClient()
|
||||
const mutation = useTimelineMutation({
|
||||
queryClient,
|
||||
@ -30,9 +30,7 @@ const HeaderActionsDomain: React.FC<Props> = ({
|
||||
toast({
|
||||
type: 'success',
|
||||
message: t('common:toastMessage.success.message', {
|
||||
function: t(
|
||||
`timeline:shared.header.default.actions.domain.block.function`
|
||||
)
|
||||
function: t(`shared.header.actions.domain.block.function`)
|
||||
})
|
||||
})
|
||||
queryClient.invalidateQueries(queryKey)
|
||||
@ -41,20 +39,19 @@ const HeaderActionsDomain: React.FC<Props> = ({
|
||||
|
||||
return (
|
||||
<MenuContainer>
|
||||
<MenuHeader
|
||||
heading={t(`timeline:shared.header.default.actions.domain.heading`)}
|
||||
/>
|
||||
<MenuHeader heading={t(`shared.header.actions.domain.heading`)} />
|
||||
<MenuRow
|
||||
onPress={() => {
|
||||
Alert.alert(
|
||||
t('timeline:shared.header.default.actions.domain.alert.title'),
|
||||
t('timeline:shared.header.default.actions.domain.alert.message'),
|
||||
t('shared.header.actions.domain.alert.title', { domain }),
|
||||
t('shared.header.actions.domain.alert.message'),
|
||||
[
|
||||
{ text: t('common:buttons.cancel'), style: 'cancel' },
|
||||
{
|
||||
text: t(
|
||||
'timeline:shared.header.default.actions.domain.alert.confirm'
|
||||
),
|
||||
text: t('shared.header.actions.domain.alert.buttons.cancel'),
|
||||
style: 'cancel'
|
||||
},
|
||||
{
|
||||
text: t('shared.header.actions.domain.alert.buttons.confirm'),
|
||||
style: 'destructive',
|
||||
onPress: () => {
|
||||
setBottomSheetVisible(false)
|
||||
@ -69,7 +66,7 @@ const HeaderActionsDomain: React.FC<Props> = ({
|
||||
)
|
||||
}}
|
||||
iconFront='CloudOff'
|
||||
title={t(`timeline:shared.header.default.actions.domain.block.button`, {
|
||||
title={t(`shared.header.actions.domain.block.button`, {
|
||||
domain
|
||||
})}
|
||||
/>
|
@ -7,17 +7,20 @@ import { useTheme } from '@utils/styles/ThemeManager'
|
||||
import React, { useCallback, useMemo, useState } from 'react'
|
||||
import { Pressable, StyleSheet } from 'react-native'
|
||||
import { useSelector } from 'react-redux'
|
||||
import HeaderActionsAccount from './ActionsAccount'
|
||||
import HeaderActionsDomain from './ActionsDomain'
|
||||
import HeaderActionsStatus from './ActionsStatus'
|
||||
import HeaderActionsAccount from './Account'
|
||||
import HeaderActionsDomain from './Domain'
|
||||
import HeaderActionsShare from './Share'
|
||||
import HeaderActionsStatus from './Status'
|
||||
|
||||
export interface Props {
|
||||
queryKey: QueryKeyTimeline
|
||||
status: Mastodon.Status
|
||||
url?: string
|
||||
type?: 'status' | 'account'
|
||||
}
|
||||
|
||||
const HeaderActions = React.memo(
|
||||
({ queryKey, status }: Props) => {
|
||||
({ queryKey, status, url, type }: Props) => {
|
||||
const { theme } = useTheme()
|
||||
|
||||
const localAccount = useSelector(getLocalAccount)
|
||||
@ -73,6 +76,14 @@ const HeaderActions = React.memo(
|
||||
setBottomSheetVisible={setBottomSheetVisible}
|
||||
/>
|
||||
)}
|
||||
|
||||
{url && type ? (
|
||||
<HeaderActionsShare
|
||||
url={url}
|
||||
type={type}
|
||||
setBottomSheetVisible={setBottomSheetVisible}
|
||||
/>
|
||||
) : null}
|
||||
</BottomSheet>
|
||||
)}
|
||||
</>
|
||||
|
@ -0,0 +1,52 @@
|
||||
import MenuContainer from '@components/Menu/Container'
|
||||
import MenuHeader from '@components/Menu/Header'
|
||||
import MenuRow from '@components/Menu/Row'
|
||||
import { toast } from '@components/toast'
|
||||
import {
|
||||
QueryKeyTimeline,
|
||||
useTimelineMutation
|
||||
} from '@utils/queryHooks/timeline'
|
||||
import React from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { Platform, Share } from 'react-native'
|
||||
|
||||
export interface Props {
|
||||
type: 'status' | 'account'
|
||||
url: string
|
||||
setBottomSheetVisible: React.Dispatch<React.SetStateAction<boolean>>
|
||||
}
|
||||
|
||||
const HeaderActionsShare: React.FC<Props> = ({
|
||||
type,
|
||||
url,
|
||||
setBottomSheetVisible
|
||||
}) => {
|
||||
const { t } = useTranslation('componentTimeline')
|
||||
|
||||
return (
|
||||
<MenuContainer>
|
||||
<MenuHeader heading={t(`shared.header.actions.share.${type}.heading`)} />
|
||||
<MenuRow
|
||||
iconFront='Share2'
|
||||
title={t(`shared.header.actions.share.${type}.button`)}
|
||||
onPress={async () => {
|
||||
switch (Platform.OS) {
|
||||
case 'ios':
|
||||
await Share.share({
|
||||
url
|
||||
})
|
||||
break
|
||||
case 'android':
|
||||
await Share.share({
|
||||
message: url
|
||||
})
|
||||
break
|
||||
}
|
||||
setBottomSheetVisible(false)
|
||||
}}
|
||||
/>
|
||||
</MenuContainer>
|
||||
)
|
||||
}
|
||||
|
||||
export default HeaderActionsShare
|
@ -23,7 +23,7 @@ const HeaderActionsStatus: React.FC<Props> = ({
|
||||
setBottomSheetVisible
|
||||
}) => {
|
||||
const navigation = useNavigation()
|
||||
const { t } = useTranslation()
|
||||
const { t } = useTranslation('componentTimeline')
|
||||
|
||||
const queryClient = useQueryClient()
|
||||
const mutation = useTimelineMutation({
|
||||
@ -38,7 +38,7 @@ const HeaderActionsStatus: React.FC<Props> = ({
|
||||
type: 'error',
|
||||
message: t('common:toastMessage.error.message', {
|
||||
function: t(
|
||||
`timeline:shared.header.default.actions.status.${theFunction}.function`
|
||||
`shared.header.actions.status.${theFunction}.function`
|
||||
)
|
||||
}),
|
||||
...(err.status &&
|
||||
@ -56,7 +56,7 @@ const HeaderActionsStatus: React.FC<Props> = ({
|
||||
return (
|
||||
<MenuContainer>
|
||||
<MenuHeader
|
||||
heading={t('timeline:shared.header.default.actions.status.heading')}
|
||||
heading={t('shared.header.actions.status.heading')}
|
||||
/>
|
||||
<MenuRow
|
||||
onPress={() => {
|
||||
@ -69,20 +69,20 @@ const HeaderActionsStatus: React.FC<Props> = ({
|
||||
})
|
||||
}}
|
||||
iconFront='Trash'
|
||||
title={t('timeline:shared.header.default.actions.status.delete.button')}
|
||||
title={t('shared.header.actions.status.delete.button')}
|
||||
/>
|
||||
<MenuRow
|
||||
onPress={() => {
|
||||
Alert.alert(
|
||||
t('timeline:shared.header.default.actions.status.edit.alert.title'),
|
||||
t('shared.header.actions.status.edit.alert.title'),
|
||||
t(
|
||||
'timeline:shared.header.default.actions.status.edit.alert.message'
|
||||
'shared.header.actions.status.edit.alert.message'
|
||||
),
|
||||
[
|
||||
{ text: t('common:buttons.cancel'), style: 'cancel' },
|
||||
{ text: t('shared.header.actions.status.edit.alert.buttons.cancel'), style: 'cancel' },
|
||||
{
|
||||
text: t(
|
||||
'timeline:shared.header.default.actions.status.edit.alert.confirm'
|
||||
'shared.header.actions.status.edit.alert.buttons.confirm'
|
||||
),
|
||||
style: 'destructive',
|
||||
onPress: async () => {
|
||||
@ -105,8 +105,8 @@ const HeaderActionsStatus: React.FC<Props> = ({
|
||||
]
|
||||
)
|
||||
}}
|
||||
iconFront='Trash'
|
||||
title={t('timeline:shared.header.default.actions.status.edit.button')}
|
||||
iconFront='Edit'
|
||||
title={t('shared.header.actions.status.edit.button')}
|
||||
/>
|
||||
<MenuRow
|
||||
onPress={() => {
|
||||
@ -122,10 +122,10 @@ const HeaderActionsStatus: React.FC<Props> = ({
|
||||
title={
|
||||
status.muted
|
||||
? t(
|
||||
'timeline:shared.header.default.actions.status.mute.button.negative'
|
||||
'shared.header.actions.status.mute.button.negative'
|
||||
)
|
||||
: t(
|
||||
'timeline:shared.header.default.actions.status.mute.button.positive'
|
||||
'shared.header.actions.status.mute.button.positive'
|
||||
)
|
||||
}
|
||||
/>
|
||||
@ -145,10 +145,10 @@ const HeaderActionsStatus: React.FC<Props> = ({
|
||||
title={
|
||||
status.pinned
|
||||
? t(
|
||||
'timeline:shared.header.default.actions.status.pin.button.negative'
|
||||
'shared.header.actions.status.pin.button.negative'
|
||||
)
|
||||
: t(
|
||||
'timeline:shared.header.default.actions.status.pin.button.positive'
|
||||
'shared.header.actions.status.pin.button.positive'
|
||||
)
|
||||
}
|
||||
/>
|
@ -21,7 +21,7 @@ export interface Props {
|
||||
}
|
||||
|
||||
const HeaderConversation: React.FC<Props> = ({ queryKey, conversation }) => {
|
||||
const { t } = useTranslation()
|
||||
const { t } = useTranslation('componentTimeline')
|
||||
|
||||
const queryClient = useQueryClient()
|
||||
const mutation = useTimelineMutation({
|
||||
@ -32,7 +32,7 @@ const HeaderConversation: React.FC<Props> = ({ queryKey, conversation }) => {
|
||||
toast({
|
||||
type: 'error',
|
||||
message: t('common:toastMessage.error.message', {
|
||||
function: t(`timeline:shared.header.conversation.delete.function`)
|
||||
function: t(`shared.header.conversation.delete.function`)
|
||||
}),
|
||||
...(err.status &&
|
||||
typeof err.status === 'number' &&
|
||||
|
@ -27,7 +27,14 @@ const TimelineHeaderDefault: React.FC<Props> = ({ queryKey, status }) => {
|
||||
</View>
|
||||
</View>
|
||||
|
||||
{queryKey ? <HeaderActions queryKey={queryKey} status={status} /> : null}
|
||||
{queryKey ? (
|
||||
<HeaderActions
|
||||
queryKey={queryKey}
|
||||
status={status}
|
||||
url={status.url || status.uri}
|
||||
type='status'
|
||||
/>
|
||||
) : null}
|
||||
</View>
|
||||
)
|
||||
}
|
||||
|
@ -11,7 +11,7 @@ export interface Props {
|
||||
|
||||
const HeaderSharedApplication: React.FC<Props> = ({ application }) => {
|
||||
const { theme } = useTheme()
|
||||
const { t } = useTranslation('timeline')
|
||||
const { t } = useTranslation('componentTimeline')
|
||||
|
||||
return application && application.name !== 'Web' ? (
|
||||
<Text
|
||||
|
@ -2,7 +2,6 @@ import RelativeTime from '@components/RelativeTime'
|
||||
import { StyleConstants } from '@utils/styles/constants'
|
||||
import { useTheme } from '@utils/styles/ThemeManager'
|
||||
import React from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { StyleSheet, Text } from 'react-native'
|
||||
|
||||
export interface Props {
|
||||
@ -11,7 +10,6 @@ export interface Props {
|
||||
|
||||
const HeaderSharedCreated: React.FC<Props> = ({ created_at }) => {
|
||||
const { theme } = useTheme()
|
||||
const { i18n } = useTranslation()
|
||||
|
||||
return (
|
||||
<Text style={[styles.created_at, { color: theme.secondary }]}>
|
||||
|
@ -5,6 +5,7 @@ import { ParseEmojis } from '@components/Parse'
|
||||
import RelativeTime from '@components/RelativeTime'
|
||||
import { toast } from '@components/toast'
|
||||
import {
|
||||
MutationVarsTimelineUpdateStatusProperty,
|
||||
QueryKeyTimeline,
|
||||
useTimelineMutation
|
||||
} from '@utils/queryHooks/timeline'
|
||||
@ -32,7 +33,7 @@ const TimelinePoll: React.FC<Props> = ({
|
||||
sameAccount
|
||||
}) => {
|
||||
const { mode, theme } = useTheme()
|
||||
const { t } = useTranslation('timeline')
|
||||
const { t } = useTranslation('componentTimeline')
|
||||
|
||||
const [allOptions, setAllOptions] = useState(
|
||||
new Array(poll.options.length).fill(false)
|
||||
@ -42,19 +43,21 @@ const TimelinePoll: React.FC<Props> = ({
|
||||
const mutation = useTimelineMutation({
|
||||
queryClient,
|
||||
onSuccess: true,
|
||||
onError: (err: any) => {
|
||||
onError: (err: any, params) => {
|
||||
const theParams = params as MutationVarsTimelineUpdateStatusProperty
|
||||
haptics('Error')
|
||||
toast({
|
||||
type: 'error',
|
||||
message: '投票错误',
|
||||
message: t('common:toastMessage.error.message', {
|
||||
function: t(`shared.poll.meta.button.${theParams.payload.type}`)
|
||||
}),
|
||||
...(err.status &&
|
||||
typeof err.status === 'number' &&
|
||||
err.data &&
|
||||
err.data.error &&
|
||||
typeof err.data.error === 'string' && {
|
||||
description: err.data.error
|
||||
}),
|
||||
autoHide: false
|
||||
})
|
||||
})
|
||||
queryClient.invalidateQueries(queryKey)
|
||||
}
|
||||
|
@ -1,5 +1,4 @@
|
||||
import * as Analytics from 'expo-firebase-analytics'
|
||||
import * as Sentry from 'sentry-expo'
|
||||
|
||||
const analytics = (event: string, params?: { [key: string]: string }) => {
|
||||
Analytics.logEvent(event, params).catch(
|
||||
|
Reference in New Issue
Block a user