1
0
mirror of https://github.com/tooot-app/app synced 2025-06-05 22:19:13 +02:00
This commit is contained in:
xmflsct
2022-11-29 23:44:11 +01:00
parent 75800598c2
commit de7498b218
75 changed files with 289 additions and 1421 deletions

View File

@ -6,29 +6,19 @@ import { StyleConstants } from '@utils/styles/constants'
import { useTheme } from '@utils/styles/ThemeManager'
import React, { useCallback } from 'react'
import { Pressable, View } from 'react-native'
import analytics from './analytics'
import GracefullyImage from './GracefullyImage'
import CustomText from './Text'
export interface Props {
account: Mastodon.Account
onPress?: () => void
origin?: string
}
const ComponentAccount: React.FC<Props> = ({
account,
onPress: customOnPress,
origin
}) => {
const ComponentAccount: React.FC<Props> = ({ account, onPress: customOnPress }) => {
const { colors } = useTheme()
const navigation =
useNavigation<StackNavigationProp<TabLocalStackParamList>>()
const navigation = useNavigation<StackNavigationProp<TabLocalStackParamList>>()
const onPress = useCallback(() => {
analytics('search_account_press', { page: origin })
navigation.push('Tab-Shared-Account', { account })
}, [])
const onPress = useCallback(() => navigation.push('Tab-Shared-Account', { account }), [])
return (
<Pressable

View File

@ -1,4 +1,3 @@
import analytics from '@components/analytics'
import { displayMessage } from '@components/Message'
import { useRelationshipQuery } from '@utils/queryHooks/relationship'
import {
@ -135,9 +134,6 @@ const contextMenuAccount = ({ actions, type, queryKey, rootQueryKey, id: account
return // For Android
}
if (actions[index].id === 'account-mute') {
analytics('timeline_shared_headeractions_account_mute_press', {
page: queryKey && queryKey[1].page
})
mutation.mutate({
type: 'updateAccountProperty',
queryKey,
@ -149,9 +145,6 @@ const contextMenuAccount = ({ actions, type, queryKey, rootQueryKey, id: account
actions[index].id === 'account-block' ||
(actions[index].id === 'account' && actions[index].actions?.[0].id === 'account-block')
) {
analytics('timeline_shared_headeractions_account_block_press', {
page: queryKey && queryKey[1].page
})
mutation.mutate({
type: 'updateAccountProperty',
queryKey,
@ -163,9 +156,6 @@ const contextMenuAccount = ({ actions, type, queryKey, rootQueryKey, id: account
actions[index].id === 'account-reports' ||
(actions[index].id === 'account' && actions[index].actions?.[0].id === 'account-reports')
) {
analytics('timeline_shared_headeractions_account_reports_press', {
page: queryKey && queryKey[1].page
})
mutation.mutate({
type: 'updateAccountProperty',
queryKey,

View File

@ -1,4 +1,3 @@
import analytics from '@components/analytics'
import { displayMessage } from '@components/Message'
import { QueryKeyTimeline, useTimelineMutation } from '@utils/queryHooks/timeline'
import { getInstanceUrl } from '@utils/slices/instancesSlice'
@ -71,9 +70,6 @@ const contextMenuInstance = ({ actions, status, queryKey, rootQueryKey }: Props)
actions[index].id === 'instance-block' ||
(actions[index].id === 'instance' && actions[index].actions?.[0].id === 'instance-block')
) {
analytics('timeline_shared_headeractions_domain_block_press', {
page: queryKey[1].page
})
Alert.alert(
t('instance.block.alert.title', { instance }),
t('instance.block.alert.message'),
@ -82,9 +78,6 @@ const contextMenuInstance = ({ actions, status, queryKey, rootQueryKey }: Props)
text: t('instance.block.alert.buttons.confirm'),
style: 'destructive',
onPress: () => {
analytics('timeline_shared_headeractions_domain_block_confirm', {
page: queryKey && queryKey[1].page
})
mutation.mutate({
type: 'domainBlock',
queryKey,

View File

@ -1,4 +1,3 @@
import analytics from '@components/analytics'
import { displayMessage } from '@components/Message'
import Clipboard from '@react-native-clipboard/clipboard'
import { useTheme } from '@utils/styles/ThemeManager'
@ -39,7 +38,6 @@ const contextMenuShare = ({ copiableContent, actions, type, url }: Props) => {
return // For Android
}
if (actions[index].id === 'copy') {
analytics('timeline_shared_headeractions_copy_press')
Clipboard.setString(copiableContent?.current.content || '')
displayMessage({
theme,
@ -48,7 +46,6 @@ const contextMenuShare = ({ copiableContent, actions, type, url }: Props) => {
})
}
if (actions[index].id === 'share') {
analytics('timeline_shared_headeractions_share_press')
switch (Platform.OS) {
case 'ios':
Share.share({ url })

View File

@ -1,5 +1,4 @@
import apiInstance from '@api/instance'
import analytics from '@components/analytics'
import { displayMessage } from '@components/Message'
import { useNavigation } from '@react-navigation/native'
import { NativeStackNavigationProp } from '@react-navigation/native-stack'
@ -107,17 +106,11 @@ const contextMenuStatus = ({ actions, status, queryKey, rootQueryKey }: Props) =
return // For Android
}
if (actions[index].id === 'status-delete') {
analytics('timeline_shared_headeractions_status_delete_press', {
page: queryKey && queryKey[1].page
})
Alert.alert(t('status.delete.alert.title'), t('status.delete.alert.message'), [
{
text: t('status.delete.alert.buttons.confirm'),
style: 'destructive',
onPress: async () => {
analytics('timeline_shared_headeractions_status_delete_confirm', {
page: queryKey && queryKey[1].page
})
mutation.mutate({
type: 'deleteItem',
source: 'statuses',
@ -133,17 +126,11 @@ const contextMenuStatus = ({ actions, status, queryKey, rootQueryKey }: Props) =
])
}
if (actions[index].id === 'status-delete-edit') {
analytics('timeline_shared_headeractions_status_deleteedit_press', {
page: queryKey && queryKey[1].page
})
Alert.alert(t('status.deleteEdit.alert.title'), t('status.deleteEdit.alert.message'), [
{
text: t('status.deleteEdit.alert.buttons.confirm'),
style: 'destructive',
onPress: async () => {
analytics('timeline_shared_headeractions_status_deleteedit_confirm', {
page: queryKey && queryKey[1].page
})
let replyToStatus: Mastodon.Status | undefined = undefined
if (status.in_reply_to_id) {
replyToStatus = await apiInstance<Mastodon.Status>({
@ -174,9 +161,6 @@ const contextMenuStatus = ({ actions, status, queryKey, rootQueryKey }: Props) =
])
}
if (actions[index].id === 'status-mute') {
analytics('timeline_shared_headeractions_status_mute_press', {
page: queryKey && queryKey[1].page
})
mutation.mutate({
type: 'updateStatusProperty',
queryKey,
@ -191,9 +175,6 @@ const contextMenuStatus = ({ actions, status, queryKey, rootQueryKey }: Props) =
})
}
if (actions[index].id === 'status-edit') {
analytics('timeline_shared_headeractions_status_edit_press', {
page: queryKey && queryKey[1].page
})
let replyToStatus: Mastodon.Status | undefined = undefined
if (status.in_reply_to_id) {
replyToStatus = await apiInstance<Mastodon.Status>({
@ -224,9 +205,6 @@ const contextMenuStatus = ({ actions, status, queryKey, rootQueryKey }: Props) =
}
if (actions[index].id === 'status-pin') {
// Also note that reblogs cannot be pinned.
analytics('timeline_shared_headeractions_status_pin_press', {
page: queryKey && queryKey[1].page
})
mutation.mutate({
type: 'updateStatusProperty',
queryKey,

View File

@ -5,7 +5,6 @@ import { StyleConstants } from '@utils/styles/constants'
import { useTheme } from '@utils/styles/ThemeManager'
import React, { useCallback } from 'react'
import { Pressable } from 'react-native'
import analytics from './analytics'
import CustomText from './Text'
export interface Props {
@ -24,7 +23,6 @@ const ComponentHashtag: React.FC<Props> = ({
useNavigation<StackNavigationProp<TabLocalStackParamList>>()
const onPress = useCallback(() => {
analytics('search_account_press', { page: origin })
navigation.push('Tab-Shared-Hashtag', { hashtag: hashtag.name })
}, [])

View File

@ -9,18 +9,10 @@ import * as WebBrowser from 'expo-web-browser'
import { debounce } from 'lodash'
import React, { RefObject, useCallback, useMemo, useState } from 'react'
import { Trans, useTranslation } from 'react-i18next'
import {
Alert,
Image,
KeyboardAvoidingView,
Platform,
TextInput,
View
} from 'react-native'
import { Alert, Image, KeyboardAvoidingView, Platform, TextInput, View } from 'react-native'
import { ScrollView } from 'react-native-gesture-handler'
import { useSelector } from 'react-redux'
import { Placeholder } from 'rn-placeholder'
import analytics from './analytics'
import InstanceAuth from './Instance/Auth'
import InstanceInfo from './Instance/Info'
import CustomText from './Text'
@ -65,11 +57,7 @@ const ComponentInstance: React.FC<Props> = ({
const processUpdate = useCallback(() => {
if (domain) {
analytics('instance_login')
if (
instances &&
instances.filter(instance => instance.url === domain).length
) {
if (instances && instances.filter(instance => instance.url === domain).length) {
Alert.alert(t('update.alert.title'), t('update.alert.message'), [
{
text: t('update.alert.buttons.cancel'),
@ -142,9 +130,7 @@ const ComponentInstance: React.FC<Props> = ({
borderBottomWidth: 1,
...StyleConstants.FontStyle.M,
color: colors.primaryDefault,
borderBottomColor: instanceQuery.isError
? colors.red
: colors.border
borderBottomColor: instanceQuery.isError ? colors.red : colors.border
}}
editable={false}
defaultValue='https://'
@ -156,9 +142,7 @@ const ComponentInstance: React.FC<Props> = ({
...StyleConstants.FontStyle.M,
marginRight: StyleConstants.Spacing.M,
color: colors.primaryDefault,
borderBottomColor: instanceQuery.isError
? colors.red
: colors.border
borderBottomColor: instanceQuery.isError ? colors.red : colors.border
}}
onChangeText={onChangeText}
autoCapitalize='none'
@ -166,7 +150,6 @@ const ComponentInstance: React.FC<Props> = ({
keyboardType='url'
textContentType='URL'
onSubmitEditing={({ nativeEvent: { text } }) => {
analytics('instance_textinput_submit', { match: text === domain })
if (
text === domain &&
instanceQuery.isSuccess &&
@ -182,11 +165,7 @@ const ComponentInstance: React.FC<Props> = ({
keyboardAppearance={mode}
{...(scrollViewRef && {
onFocus: () =>
setTimeout(
() =>
scrollViewRef.current?.scrollTo({ y: 0, animated: true }),
150
)
setTimeout(() => scrollViewRef.current?.scrollTo({ y: 0, animated: true }), 150)
})}
autoCorrect={false}
spellCheck={false}
@ -211,27 +190,19 @@ const ComponentInstance: React.FC<Props> = ({
<InstanceInfo
style={{ alignItems: 'flex-start' }}
header={t('server.information.accounts')}
content={
instanceQuery.data?.stats?.user_count?.toString() || undefined
}
content={instanceQuery.data?.stats?.user_count?.toString() || undefined}
potentialWidth={4}
/>
<InstanceInfo
style={{ alignItems: 'center' }}
header={t('server.information.statuses')}
content={
instanceQuery.data?.stats?.status_count?.toString() ||
undefined
}
content={instanceQuery.data?.stats?.status_count?.toString() || undefined}
potentialWidth={4}
/>
<InstanceInfo
style={{ alignItems: 'flex-end' }}
header={t('server.information.domains')}
content={
instanceQuery.data?.stats?.domain_count?.toString() ||
undefined
}
content={instanceQuery.data?.stats?.domain_count?.toString() || undefined}
potentialWidth={4}
/>
</View>
@ -248,17 +219,11 @@ const ComponentInstance: React.FC<Props> = ({
size={StyleConstants.Font.Size.S}
color={colors.secondary}
style={{
marginTop:
(StyleConstants.Font.LineHeight.S -
StyleConstants.Font.Size.S) /
2,
marginTop: (StyleConstants.Font.LineHeight.S - StyleConstants.Font.Size.S) / 2,
marginRight: StyleConstants.Spacing.XS
}}
/>
<CustomText
fontStyle='S'
style={{ flex: 1, color: colors.secondary }}
>
<CustomText fontStyle='S' style={{ flex: 1, color: colors.secondary }}>
{t('server.disclaimer.base')}
</CustomText>
</View>
@ -274,10 +239,7 @@ const ComponentInstance: React.FC<Props> = ({
size={StyleConstants.Font.Size.S}
color={colors.secondary}
style={{
marginTop:
(StyleConstants.Font.LineHeight.S -
StyleConstants.Font.Size.S) /
2,
marginTop: (StyleConstants.Font.LineHeight.S - StyleConstants.Font.Size.S) / 2,
marginRight: StyleConstants.Spacing.XS
}}
/>
@ -292,22 +254,14 @@ const ComponentInstance: React.FC<Props> = ({
<CustomText
accessible
style={{ color: colors.blue }}
onPress={() => {
analytics('view_privacy')
WebBrowser.openBrowserAsync(
'https://tooot.app/privacy-policy'
)
}}
onPress={() => WebBrowser.openBrowserAsync('https://tooot.app/privacy-policy')}
/>,
<CustomText
accessible
style={{ color: colors.blue }}
onPress={() => {
analytics('view_tos')
WebBrowser.openBrowserAsync(
'https://tooot.app/terms-of-service'
)
}}
onPress={() =>
WebBrowser.openBrowserAsync('https://tooot.app/terms-of-service')
}
/>
]}
/>

View File

@ -1,4 +1,3 @@
import analytics from '@components/analytics'
import Icon from '@components/Icon'
import openLink from '@components/openLink'
import ParseEmojis from '@components/Parse/Emojis'
@ -63,7 +62,6 @@ const renderNode = ({
lineHeight: adaptedLineheight
}}
onPress={() => {
analytics('status_hashtag_press')
!disableDetails &&
differentTag &&
navigation.push('Tab-Shared-Hashtag', {
@ -89,7 +87,6 @@ const renderNode = ({
lineHeight: adaptedLineheight
}}
onPress={() => {
analytics('status_mention_press')
accountIndex !== -1 &&
!disableDetails &&
differentAccount &&
@ -118,7 +115,6 @@ const renderNode = ({
lineHeight: adaptedLineheight
}}
onPress={async () => {
analytics('status_link_press')
if (!disableDetails) {
if (shouldBeTag) {
navigation.push('Tab-Shared-Hashtag', {
@ -255,7 +251,6 @@ const ParseHTML = React.memo(
<Pressable
accessibilityLabel={t('HTML.accessibilityHint')}
onPress={() => {
analytics('status_readmore', { totalLines, expanded })
layoutAnimation()
setExpanded(!expanded)
}}

View File

@ -1,11 +1,7 @@
import analytics from '@components/analytics'
import Button from '@components/Button'
import haptics from '@components/haptics'
import { displayMessage } from '@components/Message'
import {
QueryKeyRelationship,
useRelationshipMutation
} from '@utils/queryHooks/relationship'
import { QueryKeyRelationship, useRelationshipMutation } from '@utils/queryHooks/relationship'
import { QueryKeyTimeline } from '@utils/queryHooks/timeline'
import { StyleConstants } from '@utils/styles/constants'
import { useTheme } from '@utils/styles/ThemeManager'
@ -23,17 +19,12 @@ const RelationshipIncoming: React.FC<Props> = ({ id }) => {
const { t } = useTranslation()
const queryKeyRelationship: QueryKeyRelationship = ['Relationship', { id }]
const queryKeyNotification: QueryKeyTimeline = [
'Timeline',
{ page: 'Notifications' }
]
const queryKeyNotification: QueryKeyTimeline = ['Timeline', { page: 'Notifications' }]
const queryClient = useQueryClient()
const mutation = useRelationshipMutation({
onSuccess: res => {
haptics('Success')
queryClient.setQueryData<Mastodon.Relationship[]>(queryKeyRelationship, [
res
])
queryClient.setQueryData<Mastodon.Relationship[]>(queryKeyRelationship, [res])
queryClient.refetchQueries(queryKeyNotification)
},
onError: (err: any, { type }) => {
@ -62,28 +53,26 @@ const RelationshipIncoming: React.FC<Props> = ({ id }) => {
type='icon'
content='X'
loading={mutation.isLoading}
onPress={() => {
analytics('relationship_incoming_press_reject')
onPress={() =>
mutation.mutate({
id,
type: 'incoming',
payload: { action: 'reject' }
})
}}
}
/>
<Button
round
type='icon'
content='Check'
loading={mutation.isLoading}
onPress={() => {
analytics('relationship_incoming_press_authorize')
onPress={() =>
mutation.mutate({
id,
type: 'incoming',
payload: { action: 'authorize' }
})
}}
}
style={styles.approve}
/>
</View>

View File

@ -1,4 +1,3 @@
import analytics from '@components/analytics'
import Button from '@components/Button'
import haptics from '@components/haptics'
import { displayMessage } from '@components/Message'
@ -29,10 +28,7 @@ const RelationshipOutgoing = React.memo(
const mutation = useRelationshipMutation({
onSuccess: (res, { payload: { action } }) => {
haptics('Success')
queryClient.setQueryData<Mastodon.Relationship[]>(
queryKeyRelationship,
[res]
)
queryClient.setQueryData<Mastodon.Relationship[]>(queryKeyRelationship, [res])
if (action === 'block') {
const queryKey: QueryKeyTimeline = ['Timeline', { page: 'Following' }]
queryClient.invalidateQueries(queryKey)
@ -64,17 +60,12 @@ const RelationshipOutgoing = React.memo(
onPress = () => {}
} else {
if (query.data?.blocked_by) {
analytics('relationship_outgoing_blocked_by')
content = t('button.blocked_by')
onPress = () => {
analytics('relationship_outgoing_blocked_by_press')
}
onPress = () => {}
} else {
if (query.data?.blocking) {
analytics('relationship_outgoing_blocking')
content = t('button.blocking')
onPress = () => {
analytics('relationship_outgoing_blocking_press')
mutation.mutate({
id,
type: 'outgoing',
@ -86,10 +77,8 @@ const RelationshipOutgoing = React.memo(
}
} else {
if (query.data?.following) {
analytics('relationship_outgoing_following')
content = t('button.following')
onPress = () => {
analytics('relationship_outgoing_following_press')
mutation.mutate({
id,
type: 'outgoing',
@ -101,10 +90,8 @@ const RelationshipOutgoing = React.memo(
}
} else {
if (query.data?.requested) {
analytics('relationship_outgoing_requested')
content = t('button.requested')
onPress = () => {
analytics('relationship_outgoing_requested_press')
mutation.mutate({
id,
type: 'outgoing',
@ -115,10 +102,8 @@ const RelationshipOutgoing = React.memo(
})
}
} else {
analytics('relationship_outgoing_default')
content = t('button.default')
onPress = () => {
analytics('relationship_outgoing_default_press')
mutation.mutate({
id,
type: 'outgoing',

View File

@ -1,5 +1,4 @@
import apiInstance from '@api/instance'
import analytics from '@components/analytics'
import GracefullyImage from '@components/GracefullyImage'
import { useNavigation } from '@react-navigation/native'
import { StackNavigationProp } from '@react-navigation/stack'
@ -79,7 +78,6 @@ const TimelineConversation = React.memo(
const navigation =
useNavigation<StackNavigationProp<TabLocalStackParamList>>()
const onPress = useCallback(() => {
analytics('timeline_conversation_press')
if (conversation.last_status) {
conversation.unread && mutate()
navigation.push('Tab-Shared-Toot', {

View File

@ -1,4 +1,3 @@
import analytics from '@components/analytics'
import TimelineActioned from '@components/Timeline/Shared/Actioned'
import TimelineActions from '@components/Timeline/Shared/Actions'
import TimelineAttachment from '@components/Timeline/Shared/Attachment'
@ -17,7 +16,7 @@ import { StyleConstants } from '@utils/styles/constants'
import { useTheme } from '@utils/styles/ThemeManager'
import { uniqBy } from 'lodash'
import React, { useRef } from 'react'
import { Platform, Pressable, StyleProp, View, ViewStyle } from 'react-native'
import { Pressable, StyleProp, View, ViewStyle } from 'react-native'
import { useSelector } from 'react-redux'
import TimelineContextMenu from './Shared/ContextMenu'
import TimelineFeedback from './Shared/Feedback'
@ -29,7 +28,6 @@ export interface Props {
item: Mastodon.Status & { _pinned?: boolean } // For account page, internal property
queryKey?: QueryKeyTimeline
rootQueryKey?: QueryKeyTimeline
origin?: string
highlighted?: boolean
disableDetails?: boolean
disableOnPress?: boolean
@ -40,7 +38,6 @@ const TimelineDefault: React.FC<Props> = ({
item,
queryKey,
rootQueryKey,
origin,
highlighted = false,
disableDetails = false,
disableOnPress = false
@ -65,9 +62,6 @@ const TimelineDefault: React.FC<Props> = ({
const onPress = () => {
if (highlighted) return
analytics('timeline_default_press', {
page: queryKey ? queryKey[1].page : origin
})
navigation.push('Tab-Shared-Toot', {
toot: actualStatus,
rootQueryKey: queryKey

View File

@ -1,4 +1,3 @@
import analytics from '@components/analytics'
import Button from '@components/Button'
import Icon from '@components/Icon'
import CustomText from '@components/Text'
@ -27,20 +26,11 @@ const TimelineEmpty = React.memo(
const children = () => {
switch (status) {
case 'loading':
return (
<Circle
size={StyleConstants.Font.Size.L}
color={colors.secondary}
/>
)
return <Circle size={StyleConstants.Font.Size.L} color={colors.secondary} />
case 'error':
return (
<>
<Icon
name='Frown'
size={StyleConstants.Font.Size.L}
color={colors.primaryDefault}
/>
<Icon name='Frown' size={StyleConstants.Font.Size.L} color={colors.primaryDefault} />
<CustomText
fontStyle='M'
style={{
@ -51,14 +41,7 @@ const TimelineEmpty = React.memo(
>
{t('empty.error.message')}
</CustomText>
<Button
type='text'
content={t('empty.error.button')}
onPress={() => {
analytics('timeline_error_press_refetch')
refetch()
}}
/>
<Button type='text' content={t('empty.error.button')} onPress={() => refetch()} />
</>
)
case 'success':

View File

@ -1,4 +1,3 @@
import analytics from '@components/analytics'
import TimelineActioned from '@components/Timeline/Shared/Actioned'
import TimelineActions from '@components/Timeline/Shared/Actions'
import TimelineAttachment from '@components/Timeline/Shared/Attachment'
@ -15,7 +14,7 @@ import { QueryKeyTimeline } from '@utils/queryHooks/timeline'
import { getInstanceAccount } from '@utils/slices/instancesSlice'
import { StyleConstants } from '@utils/styles/constants'
import { useTheme } from '@utils/styles/ThemeManager'
import { isEqual, uniqBy } from 'lodash'
import { uniqBy } from 'lodash'
import React, { useCallback, useRef } from 'react'
import { Platform, Pressable, View } from 'react-native'
import { useSelector } from 'react-redux'
@ -57,7 +56,6 @@ const TimelineNotifications: React.FC<Props> = ({
const actualAccount = notification.status ? notification.status.account : notification.account
const onPress = useCallback(() => {
analytics('timeline_notification_press')
notification.status &&
navigation.push('Tab-Shared-Toot', {
toot: notification.status,

View File

@ -1,4 +1,3 @@
import analytics from '@components/analytics'
import Icon from '@components/Icon'
import { ParseEmojis } from '@components/Parse'
import { useNavigation } from '@react-navigation/native'
@ -6,7 +5,7 @@ import { StackNavigationProp } from '@react-navigation/stack'
import { TabLocalStackParamList } from '@utils/navigation/navigators'
import { StyleConstants } from '@utils/styles/constants'
import { useTheme } from '@utils/styles/ThemeManager'
import React, { useCallback, useMemo } from 'react'
import React from 'react'
import { useTranslation } from 'react-i18next'
import { Pressable, StyleSheet, View } from 'react-native'
@ -20,8 +19,7 @@ const TimelineActioned = React.memo(
({ account, action, notification = false }: Props) => {
const { t } = useTranslation('componentTimeline')
const { colors } = useTheme()
const navigation =
useNavigation<StackNavigationProp<TabLocalStackParamList>>()
const navigation = useNavigation<StackNavigationProp<TabLocalStackParamList>>()
const name = account?.display_name || account?.username
const iconColor = colors.primaryDefault
@ -29,10 +27,7 @@ const TimelineActioned = React.memo(
<ParseEmojis content={content} emojis={account.emojis} size='S' />
)
const onPress = useCallback(() => {
analytics('timeline_shared_actioned_press', { action })
navigation.push('Tab-Shared-Account', { account })
}, [])
const onPress = () => navigation.push('Tab-Shared-Account', { account })
const children = () => {
switch (action) {

View File

@ -1,4 +1,3 @@
import analytics from '@components/analytics'
import Icon from '@components/Icon'
import { displayMessage } from '@components/Message'
import CustomText from '@components/Text'
@ -84,18 +83,16 @@ const TimelineActions: React.FC<Props> = ({
}
})
const onPressReply = useCallback(() => {
analytics('timeline_shared_actions_reply_press', {
page: queryKey[1].page,
count: status.replies_count
})
navigation.navigate('Screen-Compose', {
type: 'reply',
incomingStatus: status,
accts,
queryKey
})
}, [status.replies_count])
const onPressReply = useCallback(
() =>
navigation.navigate('Screen-Compose', {
type: 'reply',
incomingStatus: status,
accts,
queryKey
}),
[status.replies_count]
)
const { showActionSheetWithOptions } = useActionSheet()
const onPressReblog = useCallback(() => {
if (!status.reblogged) {
@ -112,11 +109,6 @@ const TimelineActions: React.FC<Props> = ({
(selectedIndex: number) => {
switch (selectedIndex) {
case 0:
analytics('timeline_shared_actions_reblog_public_press', {
page: queryKey[1].page,
count: status.reblogs_count,
current: status.reblogged
})
mutation.mutate({
type: 'updateStatusProperty',
queryKey,
@ -133,11 +125,6 @@ const TimelineActions: React.FC<Props> = ({
})
break
case 1:
analytics('timeline_shared_actions_reblog_unlisted_press', {
page: queryKey[1].page,
count: status.reblogs_count,
current: status.reblogged
})
mutation.mutate({
type: 'updateStatusProperty',
queryKey,
@ -157,11 +144,6 @@ const TimelineActions: React.FC<Props> = ({
}
)
} else {
analytics('timeline_shared_actions_reblog_press', {
page: queryKey[1].page,
count: status.reblogs_count,
current: status.reblogged
})
mutation.mutate({
type: 'updateStatusProperty',
queryKey,
@ -179,11 +161,6 @@ const TimelineActions: React.FC<Props> = ({
}
}, [status.reblogged, status.reblogs_count])
const onPressFavourite = useCallback(() => {
analytics('timeline_shared_actions_favourite_press', {
page: queryKey[1].page,
count: status.favourites_count,
current: status.favourited
})
mutation.mutate({
type: 'updateStatusProperty',
queryKey,
@ -199,10 +176,6 @@ const TimelineActions: React.FC<Props> = ({
})
}, [status.favourited, status.favourites_count])
const onPressBookmark = useCallback(() => {
analytics('timeline_shared_actions_bookmark_press', {
page: queryKey[1].page,
current: status.bookmarked
})
mutation.mutate({
type: 'updateStatusProperty',
queryKey,

View File

@ -1,4 +1,3 @@
import analytics from '@components/analytics'
import Button from '@components/Button'
import haptics from '@components/haptics'
import AttachmentAudio from '@components/Timeline/Shared/Attachment/Audio'
@ -195,7 +194,6 @@ const TimelineAttachment = React.memo(
content={t('shared.attachment.sensitive.button')}
overlay
onPress={() => {
analytics('timeline_shared_attachment_blurview_press_show')
layoutAnimation()
setSensitiveShown(false)
haptics('Light')
@ -209,7 +207,6 @@ const TimelineAttachment = React.memo(
round
overlay
onPress={() => {
analytics('timeline_shared_attachment_blurview_press_hide')
setSensitiveShown(true)
haptics('Light')
}}

View File

@ -1,4 +1,3 @@
import analytics from '@components/analytics'
import Button from '@components/Button'
import GracefullyImage from '@components/GracefullyImage'
import { Slider } from '@sharcoux/slider'
@ -25,7 +24,6 @@ const AttachmentAudio: React.FC<Props> = ({ total, index, sensitiveShown, audio
const [audioPlaying, setAudioPlaying] = useState(false)
const [audioPosition, setAudioPosition] = useState(0)
const playAudio = useCallback(async () => {
analytics('timeline_shared_attachment_audio_play_press', { id: audio.id })
if (!audioPlayer) {
const { sound } = await Audio.Sound.createAsync(
{ uri: audio.url },
@ -41,7 +39,6 @@ const AttachmentAudio: React.FC<Props> = ({ total, index, sensitiveShown, audio
}
}, [audioPlayer, audioPosition])
const pauseAudio = useCallback(async () => {
analytics('timeline_shared_attachment_audio_pause_press', { id: audio.id })
audioPlayer!.pauseAsync()
setAudioPlaying(false)
}, [audioPlayer])

View File

@ -1,4 +1,3 @@
import analytics from '@components/analytics'
import GracefullyImage from '@components/GracefullyImage'
import { StyleConstants } from '@utils/styles/constants'
import React from 'react'
@ -34,27 +33,17 @@ const AttachmentImage = ({
hidden={sensitiveShown}
uri={{ original: image.preview_url, remote: image.remote_url }}
blurhash={image.blurhash}
onPress={() => {
analytics('timeline_shared_attachment_image_press', {
id: image.id
})
navigateToImagesViewer(image.id)
}}
onPress={() => navigateToImagesViewer(image.id)}
style={{
aspectRatio:
total > 1 ||
!image.meta?.original?.width ||
!image.meta?.original?.height
total > 1 || !image.meta?.original?.width || !image.meta?.original?.height
? attachmentAspectRatio({ total, index })
: image.meta.original.height / image.meta.original.width > 1
? 1
: image.meta.original.width / image.meta.original.height
}}
/>
<AttachmentAltText
sensitiveShown={sensitiveShown}
text={image.description}
/>
<AttachmentAltText sensitiveShown={sensitiveShown} text={image.description} />
</View>
)
}

View File

@ -1,4 +1,3 @@
import analytics from '@components/analytics'
import Button from '@components/Button'
import openLink from '@components/openLink'
import CustomText from '@components/Text'
@ -18,12 +17,7 @@ export interface Props {
attachment: Mastodon.AttachmentUnknown
}
const AttachmentUnsupported: React.FC<Props> = ({
total,
index,
sensitiveShown,
attachment
}) => {
const AttachmentUnsupported: React.FC<Props> = ({ total, index, sensitiveShown, attachment }) => {
const { t } = useTranslation('componentTimeline')
const { colors } = useTheme()
@ -55,9 +49,7 @@ const AttachmentUnsupported: React.FC<Props> = ({
style={{
textAlign: 'center',
marginBottom: StyleConstants.Spacing.S,
color: attachment.blurhash
? colors.backgroundDefault
: colors.primaryDefault
color: attachment.blurhash ? colors.backgroundDefault : colors.primaryDefault
}}
>
{t('shared.attachment.unsupported.text')}
@ -69,17 +61,13 @@ const AttachmentUnsupported: React.FC<Props> = ({
size='S'
overlay
onPress={() => {
analytics('timeline_shared_attachment_unsupported_press')
attachment.remote_url && openLink(attachment.remote_url)
}}
/>
) : null}
</>
) : null}
<AttachmentAltText
sensitiveShown={sensitiveShown}
text={attachment.description}
/>
<AttachmentAltText sensitiveShown={sensitiveShown} text={attachment.description} />
</View>
)
}

View File

@ -5,7 +5,6 @@ import React, { useCallback, useEffect, useRef, useState } from 'react'
import { AppState, AppStateStatus, Pressable, View } from 'react-native'
import { Blurhash } from 'react-native-blurhash'
import attachmentAspectRatio from './aspectRatio'
import analytics from '@components/analytics'
import AttachmentAltText from './AltText'
import { Platform } from 'expo-modules-core'
@ -30,13 +29,6 @@ const AttachmentVideo: React.FC<Props> = ({
const [videoPosition, setVideoPosition] = useState<number>(0)
const [videoResizeMode, setVideoResizeMode] = useState<ResizeMode>(ResizeMode.COVER)
const playOnPress = useCallback(async () => {
analytics('timeline_shared_attachment_video_length', {
length: video.meta?.length
})
analytics('timeline_shared_attachment_vide_play_press', {
id: video.id,
timestamp: Date.now()
})
setVideoLoading(true)
if (!videoLoaded) {
await videoPlayer.current?.loadAsync({ uri: video.url })

View File

@ -1,4 +1,3 @@
import analytics from '@components/analytics'
import GracefullyImage from '@components/GracefullyImage'
import { useNavigation } from '@react-navigation/native'
import { StackNavigationProp } from '@react-navigation/stack'
@ -14,43 +13,37 @@ export interface Props {
highlighted: boolean
}
const TimelineAvatar = React.memo(
({ queryKey, account, highlighted }: Props) => {
const { t } = useTranslation('componentTimeline')
const navigation =
useNavigation<StackNavigationProp<TabLocalStackParamList>>()
// Need to fix go back root
const onPress = useCallback(() => {
analytics('timeline_shared_avatar_press', {
page: queryKey && queryKey[1].page
})
queryKey && navigation.push('Tab-Shared-Account', { account })
}, [])
const TimelineAvatar = React.memo(({ queryKey, account, highlighted }: Props) => {
const { t } = useTranslation('componentTimeline')
const navigation = useNavigation<StackNavigationProp<TabLocalStackParamList>>()
// Need to fix go back root
const onPress = useCallback(() => {
queryKey && navigation.push('Tab-Shared-Account', { account })
}, [])
return (
<GracefullyImage
{...(highlighted && {
accessibilityLabel: t('shared.avatar.accessibilityLabel', {
name: account.display_name
}),
accessibilityHint: t('shared.avatar.accessibilityHint', {
name: account.display_name
})
})}
onPress={onPress}
uri={{ original: account?.avatar, static: account?.avatar_static }}
dimension={{
width: StyleConstants.Avatar.M,
height: StyleConstants.Avatar.M
}}
style={{
borderRadius: StyleConstants.Avatar.M,
overflow: 'hidden',
marginRight: StyleConstants.Spacing.S
}}
/>
)
}
)
return (
<GracefullyImage
{...(highlighted && {
accessibilityLabel: t('shared.avatar.accessibilityLabel', {
name: account.display_name
}),
accessibilityHint: t('shared.avatar.accessibilityHint', {
name: account.display_name
})
})}
onPress={onPress}
uri={{ original: account?.avatar, static: account?.avatar_static }}
dimension={{
width: StyleConstants.Avatar.M,
height: StyleConstants.Avatar.M
}}
style={{
borderRadius: StyleConstants.Avatar.M,
overflow: 'hidden',
marginRight: StyleConstants.Spacing.S
}}
/>
)
})
export default TimelineAvatar

View File

@ -1,5 +1,4 @@
import ComponentAccount from '@components/Account'
import analytics from '@components/analytics'
import GracefullyImage from '@components/GracefullyImage'
import openLink from '@components/openLink'
import CustomText from '@components/Text'
@ -130,10 +129,10 @@ const TimelineCard = React.memo(({ card }: Props) => {
)
}
if (isStatus && foundStatus) {
return <TimelineDefault item={foundStatus} disableDetails disableOnPress origin='card' />
return <TimelineDefault item={foundStatus} disableDetails disableOnPress />
}
if (isAccount && foundAccount) {
return <ComponentAccount account={foundAccount} origin='card' />
return <ComponentAccount account={foundAccount} />
}
return (
<>
@ -193,10 +192,7 @@ const TimelineCard = React.memo(({ card }: Props) => {
overflow: 'hidden',
borderColor: colors.border
}}
onPress={async () => {
analytics('timeline_shared_card_press')
await openLink(card.url, navigation)
}}
onPress={async () => await openLink(card.url, navigation)}
children={cardContent}
/>
)

View File

@ -1,4 +1,3 @@
import analytics from '@components/analytics'
import CustomText from '@components/Text'
import { useNavigation } from '@react-navigation/native'
import { StackNavigationProp } from '@react-navigation/stack'
@ -11,10 +10,7 @@ import { useTranslation } from 'react-i18next'
import { StyleSheet, View } from 'react-native'
export interface Props {
status: Pick<
Mastodon.Status,
'id' | 'edited_at' | 'reblogs_count' | 'favourites_count'
>
status: Pick<Mastodon.Status, 'id' | 'edited_at' | 'reblogs_count' | 'favourites_count'>
highlighted: boolean
}
@ -26,8 +22,7 @@ const TimelineFeedback = React.memo(
const { t } = useTranslation('componentTimeline')
const { colors } = useTheme()
const navigation =
useNavigation<StackNavigationProp<TabLocalStackParamList>>()
const navigation = useNavigation<StackNavigationProp<TabLocalStackParamList>>()
const { data } = useStatusHistory({
id: status.id,
@ -39,28 +34,20 @@ const TimelineFeedback = React.memo(
<View style={{ flexDirection: 'row' }}>
{status.reblogs_count > 0 ? (
<CustomText
accessibilityLabel={t(
'shared.actionsUsers.reblogged_by.accessibilityLabel',
{
count: status.reblogs_count
}
)}
accessibilityHint={t(
'shared.actionsUsers.reblogged_by.accessibilityHint'
)}
accessibilityLabel={t('shared.actionsUsers.reblogged_by.accessibilityLabel', {
count: status.reblogs_count
})}
accessibilityHint={t('shared.actionsUsers.reblogged_by.accessibilityHint')}
accessibilityRole='button'
style={[styles.text, { color: colors.blue }]}
onPress={() => {
analytics('timeline_shared_feedback_press_reblog', {
count: status.reblogs_count
})
onPress={() =>
navigation.push('Tab-Shared-Users', {
reference: 'statuses',
id: status.id,
type: 'reblogged_by',
count: status.reblogs_count
})
}}
}
>
{t('shared.actionsUsers.reblogged_by.text', {
count: status.reblogs_count
@ -69,28 +56,20 @@ const TimelineFeedback = React.memo(
) : null}
{status.favourites_count > 0 ? (
<CustomText
accessibilityLabel={t(
'shared.actionsUsers.favourited_by.accessibilityLabel',
{
count: status.reblogs_count
}
)}
accessibilityHint={t(
'shared.actionsUsers.favourited_by.accessibilityHint'
)}
accessibilityLabel={t('shared.actionsUsers.favourited_by.accessibilityLabel', {
count: status.reblogs_count
})}
accessibilityHint={t('shared.actionsUsers.favourited_by.accessibilityHint')}
accessibilityRole='button'
style={[styles.text, { color: colors.blue }]}
onPress={() => {
analytics('timeline_shared_feedback_press_favourite', {
count: status.favourites_count
})
onPress={() =>
navigation.push('Tab-Shared-Users', {
reference: 'statuses',
id: status.id,
type: 'favourited_by',
count: status.favourites_count
})
}}
}
>
{t('shared.actionsUsers.favourited_by.text', {
count: status.favourites_count
@ -101,23 +80,13 @@ const TimelineFeedback = React.memo(
<View>
{data && data.length > 1 ? (
<CustomText
accessibilityLabel={t(
'shared.actionsUsers.history.accessibilityLabel',
{
count: data.length - 1
}
)}
accessibilityHint={t(
'shared.actionsUsers.history.accessibilityHint'
)}
accessibilityLabel={t('shared.actionsUsers.history.accessibilityLabel', {
count: data.length - 1
})}
accessibilityHint={t('shared.actionsUsers.history.accessibilityHint')}
accessibilityRole='button'
style={[styles.text, { marginRight: 0, color: colors.blue }]}
onPress={() => {
analytics('timeline_shared_feedback_press_history', {
count: data.length - 1
})
navigation.push('Tab-Shared-History', { id: status.id })
}}
onPress={() => navigation.push('Tab-Shared-History', { id: status.id })}
>
{t('shared.actionsUsers.history.text', {
count: data.length - 1

View File

@ -1,15 +1,11 @@
import analytics from '@components/analytics'
import Icon from '@components/Icon'
import { displayMessage } from '@components/Message'
import { ParseEmojis } from '@components/Parse'
import CustomText from '@components/Text'
import {
QueryKeyTimeline,
useTimelineMutation
} from '@utils/queryHooks/timeline'
import { QueryKeyTimeline, useTimelineMutation } from '@utils/queryHooks/timeline'
import { StyleConstants } from '@utils/styles/constants'
import { useTheme } from '@utils/styles/ThemeManager'
import React, { useCallback, useMemo } from 'react'
import React from 'react'
import { useTranslation } from 'react-i18next'
import { Pressable, View } from 'react-native'
import { useQueryClient } from 'react-query'
@ -71,27 +67,6 @@ const HeaderConversation = ({ queryKey, conversation }: Props) => {
}
})
const actionOnPress = useCallback(() => {
analytics('timeline_conversation_delete_press')
mutation.mutate({
type: 'deleteItem',
source: 'conversations',
queryKey,
id: conversation.id
})
}, [])
const actionChildren = useMemo(
() => (
<Icon
name='Trash'
color={colors.secondary}
size={StyleConstants.Font.Size.L}
/>
),
[]
)
return (
<View style={{ flex: 1, flexDirection: 'row' }}>
<View style={{ flex: 3 }}>
@ -116,8 +91,15 @@ const HeaderConversation = ({ queryKey, conversation }: Props) => {
<Pressable
style={{ flex: 1, flexDirection: 'row', justifyContent: 'center' }}
onPress={actionOnPress}
children={actionChildren}
onPress={() =>
mutation.mutate({
type: 'deleteItem',
source: 'conversations',
queryKey,
id: conversation.id
})
}
children={<Icon name='Trash' color={colors.secondary} size={StyleConstants.Font.Size.L} />}
/>
</View>
)

View File

@ -1,4 +1,3 @@
import analytics from '@components/analytics'
import openLink from '@components/openLink'
import CustomText from '@components/Text'
import { StyleConstants } from '@utils/styles/constants'
@ -20,9 +19,6 @@ const HeaderSharedApplication = React.memo(
fontStyle='S'
accessibilityRole='link'
onPress={async () => {
analytics('timeline_shared_header_application_press', {
application
})
application.website && (await openLink(application.website))
}}
style={{

View File

@ -1,4 +1,3 @@
import analytics from '@components/analytics'
import Button from '@components/Button'
import haptics from '@components/haptics'
import Icon from '@components/Icon'
@ -40,9 +39,7 @@ const TimelinePoll: React.FC<Props> = ({
const { colors, theme } = useTheme()
const { t, i18n } = useTranslation('componentTimeline')
const [allOptions, setAllOptions] = useState(
new Array(poll.options.length).fill(false)
)
const [allOptions, setAllOptions] = useState(new Array(poll.options.length).fill(false))
const queryClient = useQueryClient()
const mutation = useTimelineMutation({
@ -86,8 +83,7 @@ const TimelinePoll: React.FC<Props> = ({
return (
<View style={{ marginRight: StyleConstants.Spacing.S }}>
<Button
onPress={() => {
analytics('timeline_shared_vote_vote_press')
onPress={() =>
mutation.mutate({
type: 'updateStatusProperty',
queryKey,
@ -101,7 +97,7 @@ const TimelinePoll: React.FC<Props> = ({
options: allOptions
}
})
}}
}
type='text'
content={t('shared.poll.meta.button.vote')}
loading={mutation.isLoading}
@ -113,8 +109,7 @@ const TimelinePoll: React.FC<Props> = ({
return (
<View style={{ marginRight: StyleConstants.Spacing.S }}>
<Button
onPress={() => {
analytics('timeline_shared_vote_refresh_press')
onPress={() =>
mutation.mutate({
type: 'updateStatusProperty',
queryKey,
@ -127,7 +122,7 @@ const TimelinePoll: React.FC<Props> = ({
type: 'refresh'
}
})
}}
}
type='text'
content={t('shared.poll.meta.button.refresh')}
loading={mutation.isLoading}
@ -136,14 +131,7 @@ const TimelinePoll: React.FC<Props> = ({
)
}
}
}, [
theme,
i18n.language,
poll.expired,
poll.voted,
allOptions,
mutation.isLoading
])
}, [theme, i18n.language, poll.expired, poll.voted, allOptions, mutation.isLoading])
const isSelected = useCallback(
(index: number): string =>
@ -154,20 +142,13 @@ const TimelinePoll: React.FC<Props> = ({
)
const pollBodyDisallow = useMemo(() => {
const maxValue = maxBy(
poll.options,
option => option.votes_count
)?.votes_count
const maxValue = maxBy(poll.options, option => option.votes_count)?.votes_count
return poll.options.map((option, index) => (
<View
key={index}
style={{ flex: 1, paddingVertical: StyleConstants.Spacing.S }}
>
<View key={index} style={{ flex: 1, paddingVertical: StyleConstants.Spacing.S }}>
<View style={{ flex: 1, flexDirection: 'row' }}>
<Icon
style={{
paddingTop:
StyleConstants.Font.LineHeight.M - StyleConstants.Font.Size.M,
paddingTop: StyleConstants.Font.LineHeight.M - StyleConstants.Font.Size.M,
marginRight: StyleConstants.Spacing.S
}}
name={
@ -176,9 +157,7 @@ const TimelinePoll: React.FC<Props> = ({
}` as any
}
size={StyleConstants.Font.Size.M}
color={
poll.own_votes?.includes(index) ? colors.blue : colors.disabled
}
color={poll.own_votes?.includes(index) ? colors.blue : colors.disabled}
/>
<CustomText style={{ flex: 1 }}>
<ParseEmojis content={option.title} emojis={poll.emojis} />
@ -194,11 +173,7 @@ const TimelinePoll: React.FC<Props> = ({
}}
>
{poll.votes_count
? Math.round(
(option.votes_count /
(poll.voters_count || poll.votes_count)) *
100
)
? Math.round((option.votes_count / (poll.voters_count || poll.votes_count)) * 100)
: 0}
%
</CustomText>
@ -213,11 +188,9 @@ const TimelinePoll: React.FC<Props> = ({
marginTop: StyleConstants.Spacing.XS,
marginBottom: StyleConstants.Spacing.S,
width: `${Math.round(
(option.votes_count / (poll.voters_count || poll.votes_count)) *
100
(option.votes_count / (poll.voters_count || poll.votes_count)) * 100
)}%`,
backgroundColor:
option.votes_count === maxValue ? colors.blue : colors.disabled
backgroundColor: option.votes_count === maxValue ? colors.blue : colors.disabled
}}
/>
</View>
@ -229,21 +202,15 @@ const TimelinePoll: React.FC<Props> = ({
key={index}
style={{ flex: 1, paddingVertical: StyleConstants.Spacing.S }}
onPress={() => {
analytics('timeline_shared_vote_option_press')
!allOptions[index] && haptics('Light')
if (poll.multiple) {
setAllOptions(allOptions.map((o, i) => (i === index ? !o : o)))
} else {
{
const otherOptions =
allOptions[index] === false ? false : undefined
const otherOptions = allOptions[index] === false ? false : undefined
setAllOptions(
allOptions.map((o, i) =>
i === index
? !o
: otherOptions !== undefined
? otherOptions
: o
i === index ? !o : otherOptions !== undefined ? otherOptions : o
)
)
}
@ -253,8 +220,7 @@ const TimelinePoll: React.FC<Props> = ({
<View style={{ flex: 1, flexDirection: 'row' }}>
<Icon
style={{
paddingTop:
StyleConstants.Font.LineHeight.M - StyleConstants.Font.Size.M,
paddingTop: StyleConstants.Font.LineHeight.M - StyleConstants.Font.Size.M,
marginRight: StyleConstants.Spacing.S
}}
name={isSelected(index)}
@ -271,13 +237,9 @@ const TimelinePoll: React.FC<Props> = ({
const pollVoteCounts = () => {
if (poll.voters_count !== null) {
return (
t('shared.poll.meta.count.voters', { count: poll.voters_count }) + ' • '
)
return t('shared.poll.meta.count.voters', { count: poll.voters_count }) + ' • '
} else if (poll.votes_count !== null) {
return (
t('shared.poll.meta.count.votes', { count: poll.votes_count }) + ' • '
)
return t('shared.poll.meta.count.votes', { count: poll.votes_count }) + ' • '
}
}
@ -308,10 +270,7 @@ const TimelinePoll: React.FC<Props> = ({
}}
>
{pollButton}
<CustomText
fontStyle='S'
style={{ flexShrink: 1, color: colors.secondary }}
>
<CustomText fontStyle='S' style={{ flexShrink: 1, color: colors.secondary }}>
{pollVoteCounts()}
{pollExpiration()}
</CustomText>

View File

@ -1,4 +1,3 @@
import analytics from '@components/analytics'
import { ParseHTML } from '@components/Parse'
import CustomText from '@components/Text'
import getLanguage from '@helpers/getLanguage'
@ -85,15 +84,9 @@ const TimelineTranslate = React.memo(
onPress={() => {
if (enabled) {
if (!isSuccess) {
analytics('timeline_shared_translate_retry', {
language: detectedLanguage
})
refetch()
}
} else {
analytics('timeline_shared_translate', {
language: detectedLanguage
})
setEnabled(true)
}
}}

View File

@ -1,7 +0,0 @@
import * as Analytics from 'expo-firebase-analytics'
const analytics = (event: string, params?: { [key: string]: any }) => {
Analytics.logEvent(event, params).catch(() => {})
}
export default analytics