1
0
mirror of https://github.com/tooot-app/app synced 2025-06-05 22:19:13 +02:00

Continue refine remote logic #638

This commit is contained in:
xmflsct
2023-01-03 23:57:23 +01:00
parent b067b9bdb1
commit 0bcd0c1725
46 changed files with 548 additions and 531 deletions

View File

@ -3,9 +3,10 @@ import GracefullyImage from '@components/GracefullyImage'
import openLink from '@components/openLink'
import CustomText from '@components/Text'
import { useNavigation } from '@react-navigation/native'
import { matchAccount, matchStatus } from '@utils/helpers/urlMatcher'
import { StackNavigationProp } from '@react-navigation/stack'
import { urlMatcher } from '@utils/helpers/urlMatcher'
import { TabLocalStackParamList } from '@utils/navigation/navigators'
import { useAccountQuery } from '@utils/queryHooks/account'
import { useSearchQuery } from '@utils/queryHooks/search'
import { useStatusQuery } from '@utils/queryHooks/status'
import { StyleConstants } from '@utils/styles/constants'
import { useTheme } from '@utils/styles/ThemeManager'
@ -20,97 +21,44 @@ const TimelineCard: React.FC = () => {
if (!status || !status.card) return null
const { colors } = useTheme()
const navigation = useNavigation()
const navigation = useNavigation<StackNavigationProp<TabLocalStackParamList>>()
const [loading, setLoading] = useState(false)
const isStatus = matchStatus(status.card.url)
const match = urlMatcher(status.card.url)
const [foundStatus, setFoundStatus] = useState<Mastodon.Status>()
const isAccount = matchAccount(status.card.url)
const [foundAccount, setFoundAccount] = useState<Mastodon.Account>()
const searchQuery = useSearchQuery({
type: (() => {
if (isStatus) return 'statuses'
if (isAccount) return 'accounts'
})(),
term: (() => {
if (isStatus) {
if (isStatus.sameInstance) {
return
} else {
return status.card.url
}
}
if (isAccount) {
if (isAccount.sameInstance) {
if (isAccount.style === 'default') {
return
} else {
return isAccount.username
}
} else {
return status.card.url
}
}
})(),
limit: 1,
options: { enabled: false }
})
const statusQuery = useStatusQuery({
id: isStatus?.id || '',
status: match?.status ? { ...match.status, uri: status.card.url } : undefined,
options: { enabled: false }
})
useEffect(() => {
if (isStatus) {
if (match?.status) {
setLoading(true)
if (isStatus.sameInstance) {
statusQuery
.refetch()
.then(res => {
res.data && setFoundStatus(res.data)
setLoading(false)
})
.catch(() => setLoading(false))
} else {
searchQuery
.refetch()
.then(res => {
const status = (res.data as any)?.statuses?.[0]
status && setFoundStatus(status)
setLoading(false)
})
.catch(() => setLoading(false))
}
statusQuery
.refetch()
.then(res => {
res.data && setFoundStatus(res.data)
setLoading(false)
})
.catch(() => setLoading(false))
}
}, [])
const accountQuery = useAccountQuery({
account:
isAccount?.style === 'default' ? { id: isAccount.id, url: status.card.url } : undefined,
account: match?.account ? { ...match?.account, url: status.card.url } : undefined,
options: { enabled: false }
})
useEffect(() => {
if (isAccount) {
if (match?.account) {
setLoading(true)
if (isAccount.sameInstance && isAccount.style === 'default') {
accountQuery
.refetch()
.then(res => {
res.data && setFoundAccount(res.data)
setLoading(false)
})
.catch(() => setLoading(false))
} else {
searchQuery
.refetch()
.then(res => {
const account = (res.data as any)?.accounts?.[0]
account && setFoundAccount(account)
setLoading(false)
})
.catch(() => setLoading(false))
}
accountQuery
.refetch()
.then(res => {
res.data && setFoundAccount(res.data)
setLoading(false)
})
.catch(() => setLoading(false))
}
}, [])
@ -129,10 +77,10 @@ const TimelineCard: React.FC = () => {
</View>
)
}
if (isStatus && foundStatus) {
if (match?.status && foundStatus) {
return <TimelineDefault item={foundStatus} disableDetails disableOnPress />
}
if (isAccount && foundAccount) {
if (match?.account && foundAccount) {
return <ComponentAccount account={foundAccount} />
}
return (
@ -198,7 +146,18 @@ const TimelineCard: React.FC = () => {
overflow: 'hidden',
borderColor: colors.border
}}
onPress={async () => status.card && (await openLink(status.card.url, navigation))}
onPress={async () => {
if (match?.status && foundStatus) {
navigation.push('Tab-Shared-Toot', { toot: foundStatus })
return
}
if (match?.account && foundAccount) {
navigation.push('Tab-Shared-Account', { account: foundAccount })
return
}
status.card?.url && (await openLink(status.card.url, navigation))
}}
children={cardContent()}
/>
)

View File

@ -19,7 +19,7 @@ const TimelineFeedback = () => {
const navigation = useNavigation<StackNavigationProp<TabLocalStackParamList>>()
const { data } = useStatusHistory({
id: status.id,
status,
options: { enabled: status.edited_at !== undefined }
})
@ -82,7 +82,7 @@ const TimelineFeedback = () => {
style={[styles.text, { marginRight: 0, color: colors.blue }]}
onPress={() =>
navigation.push('Tab-Shared-History', {
id: status.id,
status,
detectedLanguage: detectedLanguage?.current || status.language || ''
})
}

View File

@ -1,6 +1,6 @@
import CustomText from '@components/Text'
import queryClient from '@utils/queryHooks'
import removeHTML from '@utils/helpers/removeHTML'
import { queryClient } from '@utils/queryHooks'
import { QueryKeyFilters } from '@utils/queryHooks/filters'
import { QueryKeyTimeline } from '@utils/queryHooks/timeline'
import { StyleConstants } from '@utils/styles/constants'

View File

@ -73,13 +73,8 @@ const HeaderConversation = ({ conversation }: Props) => {
marginBottom: StyleConstants.Spacing.S
}}
>
{conversation.last_status?.created_at ? (
<HeaderSharedCreated
created_at={conversation.last_status?.created_at}
edited_at={conversation.last_status?.edited_at}
/>
) : null}
<HeaderSharedMuted muted={conversation.last_status?.muted} />
{conversation.last_status?.created_at ? <HeaderSharedCreated /> : null}
<HeaderSharedMuted />
</View>
</View>

View File

@ -17,7 +17,7 @@ import HeaderSharedReplies from './HeaderShared/Replies'
import HeaderSharedVisibility from './HeaderShared/Visibility'
const TimelineHeaderDefault: React.FC = () => {
const { queryKey, rootQueryKey, status, highlighted, disableDetails, rawContent, isRemote } =
const { queryKey, rootQueryKey, status, disableDetails, rawContent, isRemote } =
useContext(StatusContext)
if (!status) return null
@ -66,15 +66,11 @@ const TimelineHeaderDefault: React.FC = () => {
style={{ marginRight: StyleConstants.Spacing.S }}
/>
) : null}
<HeaderSharedCreated
created_at={status.created_at}
edited_at={status.edited_at}
highlighted={highlighted}
/>
<HeaderSharedVisibility visibility={status.visibility} />
<HeaderSharedMuted muted={status.muted} />
<HeaderSharedCreated />
<HeaderSharedVisibility />
<HeaderSharedMuted />
<HeaderSharedReplies />
<HeaderSharedApplication application={status.application} />
<HeaderSharedApplication />
</View>
</View>

View File

@ -146,15 +146,10 @@ const TimelineHeaderNotification: React.FC<Props> = ({ notification }) => {
marginBottom: StyleConstants.Spacing.S
}}
>
<HeaderSharedCreated
created_at={notification.status?.created_at || notification.created_at}
edited_at={notification.status?.edited_at}
/>
{notification.status?.visibility ? (
<HeaderSharedVisibility visibility={notification.status.visibility} />
) : null}
<HeaderSharedMuted muted={notification.status?.muted} />
<HeaderSharedApplication application={notification.status?.application} />
<HeaderSharedCreated />
{notification.status?.visibility ? <HeaderSharedVisibility /> : null}
<HeaderSharedMuted />
<HeaderSharedApplication />
</View>
</View>

View File

@ -2,32 +2,31 @@ import openLink from '@components/openLink'
import CustomText from '@components/Text'
import { StyleConstants } from '@utils/styles/constants'
import { useTheme } from '@utils/styles/ThemeManager'
import React from 'react'
import React, { useContext } from 'react'
import { useTranslation } from 'react-i18next'
import StatusContext from '../Context'
export interface Props {
application?: Mastodon.Application
}
const HeaderSharedApplication: React.FC<Props> = ({ application }) => {
const HeaderSharedApplication: React.FC = () => {
const { status } = useContext(StatusContext)
const { colors } = useTheme()
const { t } = useTranslation('componentTimeline')
return application && application.name !== 'Web' ? (
return status?.application?.name && status.application.name !== 'Web' ? (
<CustomText
fontStyle='S'
accessibilityRole='link'
onPress={async () => {
application.website && (await openLink(application.website))
status.application?.website && (await openLink(status.application.website))
}}
style={{
flex: 1,
marginLeft: StyleConstants.Spacing.S,
color: colors.secondary
}}
numberOfLines={1}
>
{t('shared.header.shared.application', {
application: application.name
application: status.application.name
})}
</CustomText>
) : null

View File

@ -3,21 +3,23 @@ import RelativeTime from '@components/RelativeTime'
import CustomText from '@components/Text'
import { StyleConstants } from '@utils/styles/constants'
import { useTheme } from '@utils/styles/ThemeManager'
import React from 'react'
import React, { useContext } from 'react'
import { useTranslation } from 'react-i18next'
import { FormattedDate } from 'react-intl'
import StatusContext from '../Context'
export interface Props {
created_at: Mastodon.Status['created_at'] | number
edited_at?: Mastodon.Status['edited_at']
highlighted?: boolean
created_at?: Mastodon.Status['created_at'] | number
}
const HeaderSharedCreated: React.FC<Props> = ({ created_at, edited_at, highlighted = false }) => {
const HeaderSharedCreated: React.FC<Props> = ({ created_at }) => {
const { status, highlighted } = useContext(StatusContext)
const { t } = useTranslation('componentTimeline')
const { colors } = useTheme()
const actualTime = edited_at || created_at
if (!status) return null
const actualTime = created_at || status.edited_at || status.created_at
return (
<>
@ -30,7 +32,7 @@ const HeaderSharedCreated: React.FC<Props> = ({ created_at, edited_at, highlight
<RelativeTime time={actualTime} />
)}
</CustomText>
{edited_at ? (
{status.edited_at && !highlighted ? (
<Icon
accessibilityLabel={t('shared.header.shared.edited.accessibilityLabel')}
name='Edit'

View File

@ -1,18 +1,16 @@
import Icon from '@components/Icon'
import { StyleConstants } from '@utils/styles/constants'
import { useTheme } from '@utils/styles/ThemeManager'
import React from 'react'
import React, { useContext } from 'react'
import { useTranslation } from 'react-i18next'
import StatusContext from '../Context'
export interface Props {
muted?: Mastodon.Status['muted']
}
const HeaderSharedMuted: React.FC<Props> = ({ muted }) => {
const HeaderSharedMuted: React.FC = () => {
const { status } = useContext(StatusContext)
const { t } = useTranslation('componentTimeline')
const { colors } = useTheme()
return muted ? (
return status?.muted ? (
<Icon
accessibilityLabel={t('shared.header.shared.muted.accessibilityLabel')}
name='VolumeX'

View File

@ -1,19 +1,17 @@
import Icon from '@components/Icon'
import { StyleConstants } from '@utils/styles/constants'
import { useTheme } from '@utils/styles/ThemeManager'
import React from 'react'
import React, { useContext } from 'react'
import { useTranslation } from 'react-i18next'
import { StyleSheet } from 'react-native'
import StatusContext from '../Context'
export interface Props {
visibility: Mastodon.Status['visibility']
}
const HeaderSharedVisibility: React.FC<Props> = ({ visibility }) => {
const HeaderSharedVisibility: React.FC = () => {
const { status } = useContext(StatusContext)
const { t } = useTranslation('componentTimeline')
const { colors } = useTheme()
switch (visibility) {
switch (status?.visibility) {
case 'unlisted':
return (
<Icon