mirror of https://github.com/tooot-app/app
Improve account page
This commit is contained in:
parent
71e0c88cc2
commit
120641b95e
|
@ -173,6 +173,10 @@ const ComponentInstance: React.FC<Props> = ({
|
|||
lists: { shown: false },
|
||||
announcements: { shown: false, unread: 0 }
|
||||
},
|
||||
page_account_timeline: {
|
||||
excludeBoosts: true,
|
||||
excludeReplies: true
|
||||
},
|
||||
drafts: [],
|
||||
emojis_frequent: []
|
||||
}
|
||||
|
|
|
@ -34,9 +34,8 @@ const AccountAttachments: React.FC<Props> = ({ remote_id, remote_domain }) => {
|
|||
|
||||
const { data } = useTimelineQuery({
|
||||
page: 'Account',
|
||||
type: 'attachments',
|
||||
id: account?.id,
|
||||
exclude_reblogs: false,
|
||||
only_media: true,
|
||||
...(remote_id && remote_domain && { remote_id, remote_domain }),
|
||||
options: { enabled: !!account?.id || (!!remote_id && !!remote_domain) }
|
||||
})
|
||||
|
@ -53,6 +52,7 @@ const AccountAttachments: React.FC<Props> = ({ remote_id, remote_domain }) => {
|
|||
flex: 1,
|
||||
height: width + StyleConstants.Spacing.Global.PagePadding * 2,
|
||||
paddingVertical: StyleConstants.Spacing.Global.PagePadding,
|
||||
paddingRight: StyleConstants.Spacing.Global.PagePadding,
|
||||
borderTopWidth: 1,
|
||||
borderTopColor: colors.border
|
||||
}}
|
||||
|
@ -70,7 +70,7 @@ const AccountAttachments: React.FC<Props> = ({ remote_id, remote_domain }) => {
|
|||
children={
|
||||
<View
|
||||
style={{
|
||||
marginHorizontal: StyleConstants.Spacing.Global.PagePadding,
|
||||
marginLeft: StyleConstants.Spacing.Global.PagePadding,
|
||||
backgroundColor: colors.backgroundOverlayInvert,
|
||||
width: width,
|
||||
height: width,
|
||||
|
@ -110,7 +110,11 @@ const AccountAttachments: React.FC<Props> = ({ remote_id, remote_domain }) => {
|
|||
blurhash: item.media_attachments[0]?.blurhash
|
||||
}}
|
||||
dimension={{ width, height: width }}
|
||||
style={{ marginLeft: StyleConstants.Spacing.Global.PagePadding }}
|
||||
style={{
|
||||
marginLeft: StyleConstants.Spacing.Global.PagePadding,
|
||||
borderRadius: StyleConstants.BorderRadius / 2,
|
||||
overflow: 'hidden'
|
||||
}}
|
||||
onPress={() => navigation.push('Tab-Shared-Toot', { toot: item })}
|
||||
dim
|
||||
/>
|
||||
|
|
|
@ -9,11 +9,12 @@ const AccountHeader: React.FC = () => {
|
|||
const { account } = useContext(AccountContext)
|
||||
|
||||
const topInset = useSafeAreaInsets().top
|
||||
const height = Dimensions.get('window').width / 3 + topInset
|
||||
|
||||
return (
|
||||
<GracefullyImage
|
||||
sources={{ default: { uri: account?.header }, static: { uri: account?.header_static } }}
|
||||
style={{ height: Dimensions.get('window').width / 3 + topInset }}
|
||||
style={{ height }}
|
||||
onPress={() => {
|
||||
if (account) {
|
||||
Image.getSize(account.header, (width, height) =>
|
||||
|
|
|
@ -19,7 +19,8 @@ const AccountInformationFields: React.FC = () => {
|
|||
style={{
|
||||
borderTopWidth: StyleSheet.hairlineWidth,
|
||||
marginBottom: StyleConstants.Spacing.M,
|
||||
borderTopColor: colors.border
|
||||
borderTopColor: colors.border,
|
||||
marginHorizontal: -StyleConstants.Spacing.Global.PagePadding
|
||||
}}
|
||||
>
|
||||
{account.fields.map((field, index) => (
|
||||
|
|
|
@ -23,25 +23,6 @@ const AccountInformationStats: React.FC = () => {
|
|||
|
||||
return (
|
||||
<View style={[styles.stats, { flexDirection: 'row' }]}>
|
||||
{account ? (
|
||||
<CustomText
|
||||
style={[styles.stat, { color: colors.primaryDefault }]}
|
||||
children={t('shared.account.summary.statuses_count', {
|
||||
count: account.statuses_count || 0
|
||||
})}
|
||||
onPress={() => {
|
||||
pageMe && account && navigation.push('Tab-Shared-Account', { account })
|
||||
}}
|
||||
/>
|
||||
) : (
|
||||
<PlaceholderLine
|
||||
width={StyleConstants.Font.Size.S * 1.25}
|
||||
height={StyleConstants.Font.LineHeight.S}
|
||||
color={colors.shimmerDefault}
|
||||
noMargin
|
||||
style={{ borderRadius: 0 }}
|
||||
/>
|
||||
)}
|
||||
{account ? (
|
||||
<CustomText
|
||||
style={[styles.stat, { color: colors.primaryDefault, textAlign: 'right' }]}
|
||||
|
@ -95,13 +76,8 @@ const AccountInformationStats: React.FC = () => {
|
|||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
stats: {
|
||||
flex: 1,
|
||||
justifyContent: 'space-between'
|
||||
},
|
||||
stat: {
|
||||
...StyleConstants.FontStyle.S
|
||||
}
|
||||
stats: { flex: 1, gap: StyleConstants.Spacing.L },
|
||||
stat: { ...StyleConstants.FontStyle.S }
|
||||
})
|
||||
|
||||
export default AccountInformationStats
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
import GracefullyImage from '@components/GracefullyImage'
|
||||
import { ParseEmojis } from '@components/Parse'
|
||||
import CustomText from '@components/Text'
|
||||
import { StyleConstants } from '@utils/styles/constants'
|
||||
import { useTheme } from '@utils/styles/ThemeManager'
|
||||
import React, { useContext } from 'react'
|
||||
import { Dimensions, StyleSheet, View } from 'react-native'
|
||||
import { StyleSheet, View } from 'react-native'
|
||||
import Animated, { Extrapolate, interpolate, useAnimatedStyle } from 'react-native-reanimated'
|
||||
import { useSafeAreaInsets } from 'react-native-safe-area-context'
|
||||
import AccountContext from './Context'
|
||||
|
@ -18,23 +19,11 @@ const AccountNav: React.FC<Props> = ({ scrollY }) => {
|
|||
const { colors } = useTheme()
|
||||
const headerHeight = useSafeAreaInsets().top + 44
|
||||
|
||||
const nameY =
|
||||
Dimensions.get('window').width / 3 +
|
||||
StyleConstants.Avatar.L -
|
||||
StyleConstants.Spacing.Global.PagePadding * 2 +
|
||||
StyleConstants.Spacing.M -
|
||||
headerHeight
|
||||
|
||||
const styleOpacity = useAnimatedStyle(() => {
|
||||
return {
|
||||
opacity: interpolate(scrollY.value, [0, 200], [0, 1], Extrapolate.CLAMP)
|
||||
}
|
||||
})
|
||||
const styleMarginTop = useAnimatedStyle(() => {
|
||||
return {
|
||||
marginTop: interpolate(scrollY.value, [nameY, nameY + 20], [50, 0], Extrapolate.CLAMP)
|
||||
}
|
||||
})
|
||||
|
||||
return (
|
||||
<Animated.View
|
||||
|
@ -53,20 +42,32 @@ const AccountNav: React.FC<Props> = ({ scrollY }) => {
|
|||
flex: 1,
|
||||
alignItems: 'center',
|
||||
overflow: 'hidden',
|
||||
marginTop: useSafeAreaInsets().top + (44 - StyleConstants.Font.Size.L) / 2
|
||||
marginTop: useSafeAreaInsets().top + StyleConstants.Font.Size.L / 2
|
||||
}}
|
||||
>
|
||||
<Animated.View style={[{ flexDirection: 'row' }, styleMarginTop]}>
|
||||
<View
|
||||
style={{ flexDirection: 'row', alignItems: 'center', gap: StyleConstants.Spacing.XS }}
|
||||
>
|
||||
{account ? (
|
||||
<CustomText numberOfLines={1}>
|
||||
<ParseEmojis
|
||||
content={account.display_name || account.username}
|
||||
emojis={account.emojis}
|
||||
fontBold
|
||||
<>
|
||||
<GracefullyImage
|
||||
sources={{ default: { uri: account.avatar_static } }}
|
||||
dimension={{
|
||||
width: StyleConstants.Font.Size.L,
|
||||
height: StyleConstants.Font.Size.L
|
||||
}}
|
||||
style={{ borderRadius: 99, overflow: 'hidden' }}
|
||||
/>
|
||||
</CustomText>
|
||||
<CustomText numberOfLines={1}>
|
||||
<ParseEmojis
|
||||
content={account.display_name || account.username}
|
||||
emojis={account.emojis}
|
||||
fontBold
|
||||
/>
|
||||
</CustomText>
|
||||
</>
|
||||
) : null}
|
||||
</Animated.View>
|
||||
</View>
|
||||
</View>
|
||||
</Animated.View>
|
||||
)
|
||||
|
|
|
@ -1,20 +1,20 @@
|
|||
import menuAccount from '@components/contextMenu/account'
|
||||
import menuShare from '@components/contextMenu/share'
|
||||
import { HeaderLeft, HeaderRight } from '@components/Header'
|
||||
import Icon from '@components/Icon'
|
||||
import CustomText from '@components/Text'
|
||||
import Timeline from '@components/Timeline'
|
||||
import TimelineDefault from '@components/Timeline/Default'
|
||||
import SegmentedControl from '@react-native-segmented-control/segmented-control'
|
||||
import { useQueryClient } from '@tanstack/react-query'
|
||||
import { TabSharedStackScreenProps } from '@utils/navigation/navigators'
|
||||
import { queryClient } from '@utils/queryHooks'
|
||||
import { useAccountQuery } from '@utils/queryHooks/account'
|
||||
import { useRelationshipQuery } from '@utils/queryHooks/relationship'
|
||||
import { QueryKeyTimeline } from '@utils/queryHooks/timeline'
|
||||
import { useAccountStorage } from '@utils/storage/actions'
|
||||
import { StyleConstants } from '@utils/styles/constants'
|
||||
import { useTheme } from '@utils/styles/ThemeManager'
|
||||
import React, { Fragment, useEffect, useMemo, useState } from 'react'
|
||||
import React, { Fragment, useEffect, useMemo } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { Platform, Text, View } from 'react-native'
|
||||
import { Platform, Pressable, Text, View } from 'react-native'
|
||||
import { useSharedValue } from 'react-native-reanimated'
|
||||
import * as DropdownMenu from 'zeego/dropdown-menu'
|
||||
import AccountAttachments from './Attachments'
|
||||
|
@ -29,7 +29,7 @@ const TabSharedAccount: React.FC<TabSharedStackScreenProps<'Tab-Shared-Account'>
|
|||
params: { account }
|
||||
}
|
||||
}) => {
|
||||
const { t } = useTranslation('screenTabs')
|
||||
const { t } = useTranslation(['common', 'screenTabs'])
|
||||
const { colors, mode } = useTheme()
|
||||
|
||||
const { data, dataUpdatedAt, isFetched } = useAccountQuery({
|
||||
|
@ -46,18 +46,15 @@ const TabSharedAccount: React.FC<TabSharedStackScreenProps<'Tab-Shared-Account'>
|
|||
id: data?.id,
|
||||
options: { enabled: account._remote ? isFetched : true }
|
||||
})
|
||||
|
||||
const queryClient = useQueryClient()
|
||||
const [queryKey, setQueryKey] = useState<QueryKeyTimeline>([
|
||||
const queryKeyDefault: QueryKeyTimeline = [
|
||||
'Timeline',
|
||||
{
|
||||
page: 'Account',
|
||||
type: 'default',
|
||||
id: data?.id,
|
||||
exclude_reblogs: true,
|
||||
only_media: false,
|
||||
...(account._remote && { remote_id: account.id, remote_domain: account._remote })
|
||||
}
|
||||
])
|
||||
]
|
||||
|
||||
const mShare = menuShare({ type: 'account', url: data?.url })
|
||||
const mAccount = menuAccount({ type: 'account', openChange: true, account: data })
|
||||
|
@ -72,10 +69,10 @@ const TabSharedAccount: React.FC<TabSharedStackScreenProps<'Tab-Shared-Account'>
|
|||
<DropdownMenu.Root>
|
||||
<DropdownMenu.Trigger>
|
||||
<HeaderRight
|
||||
accessibilityLabel={t('shared.account.actions.accessibilityLabel', {
|
||||
accessibilityLabel={t('screenTabs:shared.account.actions.accessibilityLabel', {
|
||||
user: account.acct
|
||||
})}
|
||||
accessibilityHint={t('shared.account.actions.accessibilityHint')}
|
||||
accessibilityHint={t('screenTabs:shared.account.actions.accessibilityHint')}
|
||||
content='more-horizontal'
|
||||
onPress={() => {}}
|
||||
background
|
||||
|
@ -150,15 +147,10 @@ const TabSharedAccount: React.FC<TabSharedStackScreenProps<'Tab-Shared-Account'>
|
|||
}
|
||||
})
|
||||
}, [mAccount])
|
||||
useEffect(() => {
|
||||
navigation.setParams({ queryKey })
|
||||
}, [queryKey[1]])
|
||||
|
||||
const scrollY = useSharedValue(0)
|
||||
|
||||
const page = queryKey[1]
|
||||
|
||||
const [segment, setSegment] = useState<number>(0)
|
||||
const [timelineSettings, setTimelineSettings] = useAccountStorage.object('page_account_timeline')
|
||||
const ListHeaderComponent = useMemo(() => {
|
||||
return (
|
||||
<>
|
||||
|
@ -170,45 +162,97 @@ const TabSharedAccount: React.FC<TabSharedStackScreenProps<'Tab-Shared-Account'>
|
|||
/>
|
||||
</View>
|
||||
{!data?.suspended ? (
|
||||
// @ts-ignore
|
||||
<SegmentedControl
|
||||
appearance={mode}
|
||||
values={[t('shared.account.toots.default'), t('shared.account.toots.all')]}
|
||||
selectedIndex={segment}
|
||||
onChange={({ nativeEvent }: any) => {
|
||||
setSegment(nativeEvent.selectedSegmentIndex)
|
||||
switch (nativeEvent.selectedSegmentIndex) {
|
||||
case 0:
|
||||
setQueryKey([
|
||||
queryKey[0],
|
||||
{
|
||||
...page,
|
||||
page: 'Account',
|
||||
id: data?.id,
|
||||
exclude_reblogs: true,
|
||||
only_media: false
|
||||
}
|
||||
])
|
||||
break
|
||||
case 1:
|
||||
setQueryKey([
|
||||
queryKey[0],
|
||||
{
|
||||
...page,
|
||||
page: 'Account',
|
||||
id: data?.id,
|
||||
exclude_reblogs: false,
|
||||
only_media: false
|
||||
}
|
||||
])
|
||||
break
|
||||
}
|
||||
}}
|
||||
style={{
|
||||
marginTop: StyleConstants.Spacing.M,
|
||||
marginHorizontal: StyleConstants.Spacing.Global.PagePadding
|
||||
}}
|
||||
/>
|
||||
<DropdownMenu.Root>
|
||||
<DropdownMenu.Trigger>
|
||||
<Pressable
|
||||
style={{
|
||||
flex: 1,
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'space-between',
|
||||
gap: StyleConstants.Spacing.XS,
|
||||
paddingVertical: StyleConstants.Spacing.S,
|
||||
paddingHorizontal: StyleConstants.Spacing.Global.PagePadding
|
||||
}}
|
||||
>
|
||||
<View style={{ flex: 1 }} />
|
||||
<View
|
||||
style={{ flex: 1 }}
|
||||
children={
|
||||
<CustomText
|
||||
style={{ color: colors.secondary, alignSelf: 'center' }}
|
||||
children={t('screenTabs:shared.account.summary.statuses_count', {
|
||||
count: data?.statuses_count || 0
|
||||
})}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
<View
|
||||
style={{
|
||||
flex: 1,
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'flex-end'
|
||||
}}
|
||||
>
|
||||
<Icon name='filter' color={colors.secondary} size={StyleConstants.Font.Size.M} />
|
||||
</View>
|
||||
</Pressable>
|
||||
</DropdownMenu.Trigger>
|
||||
|
||||
<DropdownMenu.Content>
|
||||
<DropdownMenu.Group>
|
||||
<DropdownMenu.CheckboxItem
|
||||
key='showBoosts'
|
||||
value={
|
||||
(
|
||||
typeof timelineSettings?.excludeBoosts === 'boolean'
|
||||
? timelineSettings.excludeBoosts
|
||||
: true
|
||||
)
|
||||
? 'off'
|
||||
: 'on'
|
||||
}
|
||||
onValueChange={() => {
|
||||
setTimelineSettings({
|
||||
...timelineSettings,
|
||||
excludeBoosts: !timelineSettings?.excludeBoosts
|
||||
})
|
||||
queryClient.refetchQueries(queryKeyDefault)
|
||||
}}
|
||||
>
|
||||
<DropdownMenu.ItemIndicator />
|
||||
<DropdownMenu.ItemTitle
|
||||
children={t('screenTabs:tabs.local.options.showBoosts')}
|
||||
/>
|
||||
</DropdownMenu.CheckboxItem>
|
||||
<DropdownMenu.CheckboxItem
|
||||
key='showReplies'
|
||||
value={
|
||||
(
|
||||
typeof timelineSettings?.excludeReplies === 'boolean'
|
||||
? timelineSettings.excludeReplies
|
||||
: true
|
||||
)
|
||||
? 'off'
|
||||
: 'on'
|
||||
}
|
||||
onValueChange={() => {
|
||||
setTimelineSettings({
|
||||
...timelineSettings,
|
||||
excludeReplies: !timelineSettings?.excludeReplies
|
||||
})
|
||||
queryClient.refetchQueries(queryKeyDefault)
|
||||
}}
|
||||
>
|
||||
<DropdownMenu.ItemTitle
|
||||
children={t('screenTabs:tabs.local.options.showReplies')}
|
||||
/>
|
||||
<DropdownMenu.ItemIndicator />
|
||||
</DropdownMenu.CheckboxItem>
|
||||
</DropdownMenu.Group>
|
||||
</DropdownMenu.Content>
|
||||
</DropdownMenu.Root>
|
||||
) : null}
|
||||
{data?.suspended ? (
|
||||
<View
|
||||
|
@ -226,13 +270,13 @@ const TabSharedAccount: React.FC<TabSharedStackScreenProps<'Tab-Shared-Account'>
|
|||
textAlign: 'center'
|
||||
}}
|
||||
>
|
||||
{t('shared.account.suspended')}
|
||||
{t('screenTabs:shared.account.suspended')}
|
||||
</Text>
|
||||
</View>
|
||||
) : null}
|
||||
</>
|
||||
)
|
||||
}, [segment, dataUpdatedAt, mode])
|
||||
}, [timelineSettings, dataUpdatedAt, mode])
|
||||
|
||||
const [domain] = useAccountStorage.string('auth.account.domain')
|
||||
|
||||
|
@ -252,16 +296,14 @@ const TabSharedAccount: React.FC<TabSharedStackScreenProps<'Tab-Shared-Account'>
|
|||
ListHeaderComponent
|
||||
) : (
|
||||
<Timeline
|
||||
queryKey={queryKey}
|
||||
queryKey={queryKeyDefault}
|
||||
disableRefresh
|
||||
customProps={{
|
||||
keyboardShouldPersistTaps: 'always',
|
||||
renderItem: ({ item }) => <TimelineDefault item={item} queryKey={queryKey} />,
|
||||
onScroll: ({ nativeEvent }) => (scrollY.value = nativeEvent.contentOffset.y),
|
||||
ListHeaderComponent,
|
||||
maintainVisibleContentPosition: undefined,
|
||||
onRefresh: () => queryClient.refetchQueries(queryKey),
|
||||
refreshing: false
|
||||
refreshing: false,
|
||||
onRefresh: () => queryClient.refetchQueries(queryKeyDefault)
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
|
|
|
@ -46,7 +46,12 @@ const TabSharedAttachments: React.FC<TabSharedStackScreenProps<'Tab-Shared-Attac
|
|||
|
||||
const queryKey: QueryKeyTimeline = [
|
||||
'Timeline',
|
||||
{ page: 'Account', id: account.id, exclude_reblogs: true, only_media: true }
|
||||
{
|
||||
page: 'Account',
|
||||
type: 'attachments',
|
||||
id: account.id,
|
||||
...(account._remote && { remote_id: account.id, remote_domain: account._remote })
|
||||
}
|
||||
]
|
||||
|
||||
return <Timeline queryKey={queryKey} />
|
||||
|
|
|
@ -15,7 +15,6 @@ import { useNavState } from '@utils/navigation/navigators'
|
|||
import { queryClient } from '@utils/queryHooks'
|
||||
import { getAccountStorage, setAccountStorage } from '@utils/storage/actions'
|
||||
import { AxiosError } from 'axios'
|
||||
import { uniqBy } from 'lodash'
|
||||
import { searchLocalStatus } from './search'
|
||||
import deleteItem from './timeline/deleteItem'
|
||||
import editItem from './timeline/editItem'
|
||||
|
@ -43,10 +42,9 @@ export type QueryKeyTimeline = [
|
|||
}
|
||||
| {
|
||||
page: 'Account'
|
||||
type: 'default' | 'attachments'
|
||||
id?: Mastodon.Account['id']
|
||||
exclude_reblogs: boolean
|
||||
only_media: boolean
|
||||
// remote info
|
||||
// remote
|
||||
remote_id?: Mastodon.Account['id']
|
||||
remote_domain?: string
|
||||
}
|
||||
|
@ -163,139 +161,82 @@ export const queryFunctionTimeline = async ({
|
|||
})
|
||||
|
||||
case 'Account':
|
||||
const reject = Promise.reject('Timeline query account id not provided')
|
||||
if (!page.id) return Promise.reject('Timeline account missing id')
|
||||
|
||||
if (page.only_media) {
|
||||
let res
|
||||
if (page.remote_domain && page.remote_id) {
|
||||
res = await apiGeneral<Mastodon.Status[]>({
|
||||
method: 'get',
|
||||
domain: page.remote_domain,
|
||||
url: `api/v1/accounts/${page.remote_id}/statuses`,
|
||||
params: {
|
||||
only_media: true,
|
||||
...params
|
||||
}
|
||||
})
|
||||
.then(res => ({
|
||||
...res,
|
||||
body: res.body.map(status => appendRemote.status(status, page.remote_domain!))
|
||||
}))
|
||||
.catch(() => {})
|
||||
}
|
||||
if (!res && page.id) {
|
||||
res = await apiInstance<Mastodon.Status[]>({
|
||||
method: 'get',
|
||||
url: `accounts/${page.id}/statuses`,
|
||||
params: {
|
||||
only_media: true,
|
||||
...params
|
||||
}
|
||||
})
|
||||
}
|
||||
return res || reject
|
||||
} else if (page.exclude_reblogs) {
|
||||
if (pageParam && pageParam.hasOwnProperty('max_id')) {
|
||||
let res
|
||||
if (page.remote_domain && page.remote_id) {
|
||||
res = await apiGeneral<Mastodon.Status[]>({
|
||||
method: 'get',
|
||||
domain: page.remote_domain,
|
||||
url: `api/v1/accounts/${page.remote_id}/statuses`,
|
||||
params: {
|
||||
exclude_replies: true,
|
||||
...params
|
||||
}
|
||||
})
|
||||
.then(res => ({
|
||||
...res,
|
||||
body: res.body.map(status => appendRemote.status(status, page.remote_domain!))
|
||||
}))
|
||||
.catch(() => {})
|
||||
let typeParams
|
||||
switch (page.type) {
|
||||
case 'default':
|
||||
const filters = getAccountStorage.object('page_account_timeline')
|
||||
typeParams = {
|
||||
exclude_reblogs:
|
||||
typeof filters?.excludeBoosts === 'boolean' ? filters.excludeBoosts : true,
|
||||
exclude_replies:
|
||||
typeof filters?.excludeReplies === 'boolean' ? filters.excludeReplies : true
|
||||
}
|
||||
if (!res && page.id) {
|
||||
res = await apiInstance<Mastodon.Status[]>({
|
||||
method: 'get',
|
||||
url: `accounts/${page.id}/statuses`,
|
||||
params: {
|
||||
exclude_replies: true,
|
||||
...params
|
||||
}
|
||||
})
|
||||
}
|
||||
return res || reject
|
||||
} else {
|
||||
let res
|
||||
if (page.remote_domain && page.remote_id) {
|
||||
res = await apiGeneral<Mastodon.Status[]>({
|
||||
method: 'get',
|
||||
domain: page.remote_domain,
|
||||
url: `api/v1/accounts/${page.remote_id}/statuses`,
|
||||
params: { exclude_replies: true }
|
||||
})
|
||||
.then(res => ({
|
||||
...res,
|
||||
body: res.body.map(status => appendRemote.status(status, page.remote_domain!))
|
||||
}))
|
||||
.catch(() => {})
|
||||
}
|
||||
if (!res && page.id) {
|
||||
const resPinned = await apiInstance<(Mastodon.Status & { _pinned: boolean })[]>({
|
||||
method: 'get',
|
||||
url: `accounts/${page.id}/statuses`,
|
||||
params: { pinned: true }
|
||||
}).then(res => ({
|
||||
...res,
|
||||
body: res.body.map(status => {
|
||||
status._pinned = true
|
||||
return status
|
||||
})
|
||||
}))
|
||||
const resDefault = await apiInstance<Mastodon.Status[]>({
|
||||
method: 'get',
|
||||
url: `accounts/${page.id}/statuses`,
|
||||
params: { exclude_replies: true }
|
||||
})
|
||||
return {
|
||||
body: uniqBy([...resPinned.body, ...resDefault.body], 'id'),
|
||||
links: resDefault.links
|
||||
}
|
||||
}
|
||||
return res || reject
|
||||
}
|
||||
} else {
|
||||
let res
|
||||
if (page.remote_domain && page.remote_id) {
|
||||
res = await apiGeneral<Mastodon.Status[]>({
|
||||
method: 'get',
|
||||
domain: page.remote_domain,
|
||||
url: `api/v1/accounts/${page.remote_id}/statuses`,
|
||||
params: {
|
||||
...params,
|
||||
exclude_replies: false,
|
||||
only_media: false
|
||||
}
|
||||
})
|
||||
.then(res => ({
|
||||
...res,
|
||||
body: res.body.map(status => appendRemote.status(status, page.remote_domain!))
|
||||
}))
|
||||
.catch(() => {})
|
||||
}
|
||||
if (!res && page.id) {
|
||||
res = await apiInstance<Mastodon.Status[]>({
|
||||
method: 'get',
|
||||
url: `accounts/${page.id}/statuses`,
|
||||
params: {
|
||||
...params,
|
||||
exclude_replies: false,
|
||||
only_media: false
|
||||
}
|
||||
})
|
||||
}
|
||||
return res || reject
|
||||
break
|
||||
case 'attachments':
|
||||
typeParams = { only_media: true, exclude_reblogs: true }
|
||||
break
|
||||
}
|
||||
|
||||
let pinned
|
||||
if (page.type === 'default' && !params.hasOwnProperty('max_id')) {
|
||||
if (page.remote_domain && page.remote_id) {
|
||||
pinned = await apiGeneral<Mastodon.Status[]>({
|
||||
method: 'get',
|
||||
domain: page.remote_domain,
|
||||
url: `api/v1/accounts/${page.remote_id}/statuses`,
|
||||
params: { pinned: true }
|
||||
})
|
||||
.then(res => ({
|
||||
...res,
|
||||
body: res.body.map(status => appendRemote.status(status, page.remote_domain!))
|
||||
}))
|
||||
.catch(() => {})
|
||||
}
|
||||
if (!pinned) {
|
||||
pinned = await apiInstance<Mastodon.Status[]>({
|
||||
method: 'get',
|
||||
url: `accounts/${page.id}/statuses`,
|
||||
params: { pinned: true }
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
let res
|
||||
if (page.remote_domain && page.remote_id) {
|
||||
res = await apiGeneral<Mastodon.Status[]>({
|
||||
method: 'get',
|
||||
domain: page.remote_domain,
|
||||
url: `api/v1/accounts/${page.remote_id}/statuses`,
|
||||
params: {
|
||||
...typeParams,
|
||||
...params
|
||||
}
|
||||
})
|
||||
.then(res => ({
|
||||
...res,
|
||||
body: res.body.map(status => appendRemote.status(status, page.remote_domain!))
|
||||
}))
|
||||
.catch(() => {})
|
||||
}
|
||||
if (!res) {
|
||||
res = await apiInstance<Mastodon.Status[]>({
|
||||
method: 'get',
|
||||
url: `accounts/${page.id}/statuses`,
|
||||
params: {
|
||||
...typeParams,
|
||||
...params
|
||||
}
|
||||
})
|
||||
}
|
||||
return pinned
|
||||
? {
|
||||
body: [...pinned.body.map(status => ({ ...status, _pinned: true })), ...res.body],
|
||||
links: res.links
|
||||
}
|
||||
: res
|
||||
|
||||
case 'Hashtag':
|
||||
return apiInstance<Mastodon.Status[]>({
|
||||
method: 'get',
|
||||
|
|
|
@ -53,6 +53,10 @@ export type AccountV0 = {
|
|||
unread: number
|
||||
}
|
||||
}
|
||||
page_account_timeline: {
|
||||
excludeBoosts: boolean
|
||||
excludeReplies: boolean
|
||||
}
|
||||
drafts: ComposeStateDraft[]
|
||||
emojis_frequent: {
|
||||
emoji: Pick<Mastodon.Emoji, 'url' | 'shortcode' | 'static_url'>
|
||||
|
|
Loading…
Reference in New Issue