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

Believe #638 can be closed now!

This commit is contained in:
xmflsct
2023-01-04 22:39:29 +01:00
parent 62a6594f91
commit 06324ee51a
34 changed files with 278 additions and 346 deletions

View File

@ -1,10 +1,19 @@
import { BottomTabScreenProps } from '@react-navigation/bottom-tabs'
import { NavigatorScreenParams } from '@react-navigation/native'
import { NavigatorScreenParams, useNavigationState } from '@react-navigation/native'
import { NativeStackScreenProps } from '@react-navigation/native-stack'
import { StackNavigationProp } from '@react-navigation/stack'
import { ComposeState } from '@screens/Compose/utils/types'
import { QueryKeyTimeline } from '@utils/queryHooks/timeline'
export const useNavState = () =>
useNavigationState(state =>
state.routes.map(
route => (route.params as { queryKey?: QueryKeyTimeline } | undefined)?.queryKey
)
)
.filter(key => key?.[0] === 'Timeline')
.reverse()
export type RootStackParamList = {
'Screen-Tabs': NavigatorScreenParams<ScreenTabsStackParamList>
'Screen-Announcements': { showAll: boolean }
@ -13,20 +22,19 @@ export type RootStackParamList = {
type: 'edit'
incomingStatus: Mastodon.Status
replyToStatus?: Mastodon.Status
queryKey?: QueryKeyTimeline
rootQueryKey?: QueryKeyTimeline
navigationState: (QueryKeyTimeline | undefined)[]
}
| {
type: 'deleteEdit'
incomingStatus: Mastodon.Status
replyToStatus?: Mastodon.Status
queryKey?: QueryKeyTimeline
navigationState: (QueryKeyTimeline | undefined)[]
}
| {
type: 'reply'
incomingStatus: Mastodon.Status
accts: Mastodon.Account['acct'][]
queryKey?: QueryKeyTimeline
navigationState: (QueryKeyTimeline | undefined)[]
}
| {
type: 'conversation'
@ -85,27 +93,18 @@ export type ScreenTabsScreenProps<T extends keyof ScreenTabsStackParamList> = Bo
export type TabSharedStackParamList = {
'Tab-Shared-Account': {
account: Pick<Mastodon.Account, 'id' | 'username' | 'acct' | 'url' | '_remote'>
queryKey?: QueryKeyTimeline
}
'Tab-Shared-Account-In-Lists': {
account: Pick<Mastodon.Account, 'id' | 'username'>
}
'Tab-Shared-Attachments': { account: Mastodon.Account }
'Tab-Shared-Hashtag': {
hashtag: Mastodon.Tag['name']
}
'Tab-Shared-History': {
status: Mastodon.Status
detectedLanguage: string
}
'Tab-Shared-Account-In-Lists': { account: Pick<Mastodon.Account, 'id' | 'username'> }
'Tab-Shared-Attachments': { account: Mastodon.Account; queryKey?: QueryKeyTimeline }
'Tab-Shared-Hashtag': { hashtag: Mastodon.Tag['name']; queryKey?: QueryKeyTimeline }
'Tab-Shared-History': { status: Mastodon.Status; detectedLanguage: string }
'Tab-Shared-Report': {
account: Pick<Mastodon.Account, 'id' | 'acct' | 'username' | 'url'>
status?: Pick<Mastodon.Status, 'id' | '_remote' | 'uri'>
}
'Tab-Shared-Search': undefined
'Tab-Shared-Toot': {
toot: Mastodon.Status
rootQueryKey?: QueryKeyTimeline
}
'Tab-Shared-Toot': { toot: Mastodon.Status; queryKey?: QueryKeyTimeline }
'Tab-Shared-Users':
| {
reference: 'accounts'
@ -124,15 +123,15 @@ export type TabSharedStackScreenProps<T extends keyof TabSharedStackParamList> =
NativeStackScreenProps<TabSharedStackParamList, T>
export type TabLocalStackParamList = {
'Tab-Local-Root': undefined
'Tab-Local-Root': { queryKey?: QueryKeyTimeline }
} & TabSharedStackParamList
export type TabPublicStackParamList = {
'Tab-Public-Root': undefined
'Tab-Public-Root': { queryKey?: QueryKeyTimeline }
} & TabSharedStackParamList
export type TabNotificationsStackParamList = {
'Tab-Notifications-Root': undefined
'Tab-Notifications-Root': { queryKey?: QueryKeyTimeline }
'Tab-Notifications-Filters': undefined
} & TabSharedStackParamList
export type TabNotificationsStackScreenProps<T extends keyof TabNotificationsStackParamList> =
@ -140,11 +139,11 @@ export type TabNotificationsStackScreenProps<T extends keyof TabNotificationsSta
export type TabMeStackParamList = {
'Tab-Me-Root': undefined
'Tab-Me-Bookmarks': undefined
'Tab-Me-Conversations': undefined
'Tab-Me-Favourites': undefined
'Tab-Me-Bookmarks': { queryKey?: QueryKeyTimeline }
'Tab-Me-Conversations': { queryKey?: QueryKeyTimeline }
'Tab-Me-Favourites': { queryKey?: QueryKeyTimeline }
'Tab-Me-FollowedTags': undefined
'Tab-Me-List': Mastodon.List
'Tab-Me-List': { list: Mastodon.List; queryKey?: QueryKeyTimeline }
'Tab-Me-List-Accounts': Omit<Mastodon.List, 'replies_policy'>
'Tab-Me-List-Edit':
| {

View File

@ -4,9 +4,7 @@ import navigationRef from '@utils/navigation/navigationRef'
const pushUseNavigate = (id?: Mastodon.Notification['id']) => {
navigationRef.navigate('Screen-Tabs', {
screen: 'Tab-Notifications',
params: {
screen: 'Tab-Notifications-Root'
}
params: { screen: 'Tab-Notifications-Root', params: {} }
})
if (!id) {

View File

@ -9,13 +9,13 @@ import {
import { PagedResponse } from '@utils/api/helpers'
import apiInstance from '@utils/api/instance'
import { featureCheck } from '@utils/helpers/featureCheck'
import { useNavState } from '@utils/navigation/navigators'
import { queryClient } from '@utils/queryHooks'
import { getAccountStorage } 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'
import updateStatusProperty from './timeline/updateStatusProperty'
export type QueryKeyTimeline = [
@ -248,8 +248,6 @@ enum MapPropertyToUrl {
export type MutationVarsTimelineUpdateStatusProperty = {
// This is status in general, including "status" inside conversation and notification
type: 'updateStatusProperty'
queryKey: QueryKeyTimeline
rootQueryKey?: QueryKeyTimeline
status: Mastodon.Status
payload:
| {
@ -279,7 +277,6 @@ export type MutationVarsTimelineUpdateStatusProperty = {
export type MutationVarsTimelineUpdateAccountProperty = {
// This is status in general, including "status" inside conversation and notification
type: 'updateAccountProperty'
queryKey?: QueryKeyTimeline
id: Mastodon.Account['id']
payload: {
property: 'mute' | 'block' | 'reports'
@ -287,34 +284,22 @@ export type MutationVarsTimelineUpdateAccountProperty = {
}
}
export type MutationVarsTimelineEditItem = {
// This is for editing status
type: 'editItem'
queryKey?: QueryKeyTimeline
rootQueryKey?: QueryKeyTimeline
status: Mastodon.Status
}
export type MutationVarsTimelineDeleteItem = {
// This is for deleting status and conversation
type: 'deleteItem'
source: 'statuses' | 'conversations'
queryKey?: QueryKeyTimeline
rootQueryKey?: QueryKeyTimeline
id: Mastodon.Status['id']
}
export type MutationVarsTimelineDomainBlock = {
// This is for deleting status and conversation
type: 'domainBlock'
queryKey: QueryKeyTimeline
domain: string
}
export type MutationVarsTimeline =
| MutationVarsTimelineUpdateStatusProperty
| MutationVarsTimelineUpdateAccountProperty
| MutationVarsTimelineEditItem
| MutationVarsTimelineDeleteItem
| MutationVarsTimelineDomainBlock
@ -380,8 +365,6 @@ const mutationFunction = async (params: MutationVarsTimeline) => {
}
})
}
case 'editItem':
return { body: params.status }
case 'deleteItem':
return apiInstance<Mastodon.Conversation>({
method: 'delete',
@ -415,6 +398,8 @@ const useTimelineMutation = ({
onSettled?: MutationOptionsTimeline['onSettled']
onSuccess?: MutationOptionsTimeline['onSuccess']
}) => {
const navigationState = useNavState()
return useMutation<
{ body: Mastodon.Conversation | Mastodon.Notification | Mastodon.Status },
AxiosError,
@ -425,19 +410,16 @@ const useTimelineMutation = ({
onSuccess,
...(onMutate && {
onMutate: params => {
queryClient.cancelQueries(params.queryKey)
const oldData = params.queryKey && queryClient.getQueryData(params.queryKey)
queryClient.cancelQueries(navigationState[0])
const oldData = navigationState[0] && queryClient.getQueryData(navigationState[0])
haptics('Light')
switch (params.type) {
case 'updateStatusProperty':
updateStatusProperty(params)
break
case 'editItem':
editItem(params)
updateStatusProperty(params, navigationState)
break
case 'deleteItem':
deleteItem(params)
deleteItem(params, navigationState)
break
}
return oldData

View File

@ -1,29 +1,31 @@
import { InfiniteData } from '@tanstack/react-query'
import { queryClient } from '@utils/queryHooks'
import { MutationVarsTimelineDeleteItem } from '../timeline'
import { MutationVarsTimelineDeleteItem, QueryKeyTimeline, TimelineData } from '../timeline'
const deleteItem = ({ queryKey, rootQueryKey, id }: MutationVarsTimelineDeleteItem) => {
queryKey &&
queryClient.setQueryData<InfiniteData<any> | undefined>(queryKey, old => {
const deleteItem = (
{ id }: MutationVarsTimelineDeleteItem,
navigationState: (QueryKeyTimeline | undefined)[]
) => {
for (const key of navigationState) {
if (!key) continue
queryClient.setQueryData<InfiniteData<TimelineData> | undefined>(key, old => {
if (old) {
let foundToot: boolean = false
old.pages = old.pages.map(page => {
page.body = page.body.filter((item: Mastodon.Status) => item.id !== id)
if (foundToot) return page
page.body = (page.body as Mastodon.Status[]).filter(
(item: Mastodon.Status) => item.id !== id
)
return page
})
return old
}
})
rootQueryKey &&
queryClient.setQueryData<InfiniteData<any> | undefined>(rootQueryKey, old => {
if (old) {
old.pages = old.pages.map(page => {
page.body = page.body.filter((item: Mastodon.Status) => item.id !== id)
return page
})
return old
}
return old
})
}
}
export default deleteItem

View File

@ -1,39 +0,0 @@
import { InfiniteData } from '@tanstack/react-query'
import { queryClient } from '@utils/queryHooks'
import { MutationVarsTimelineEditItem } from '../timeline'
const editItem = ({ queryKey, rootQueryKey, status }: MutationVarsTimelineEditItem) => {
queryKey &&
queryClient.setQueryData<InfiniteData<any> | undefined>(queryKey, old => {
if (old) {
old.pages = old.pages.map(page => {
page.body = page.body.map((item: Mastodon.Status) => {
if (item.id === status.id) {
item = status
}
return item
})
return page
})
return old
}
})
rootQueryKey &&
queryClient.setQueryData<InfiniteData<any> | undefined>(rootQueryKey, old => {
if (old) {
old.pages = old.pages.map(page => {
page.body = page.body.map((item: Mastodon.Status) => {
if (item.id === status.id) {
item = status
}
return item
})
return page
})
return old
}
})
}
export default editItem

View File

@ -1,72 +1,78 @@
import { InfiniteData } from '@tanstack/react-query'
import { queryClient } from '@utils/queryHooks'
import { MutationVarsTimelineUpdateStatusProperty, TimelineData } from '../timeline'
import {
MutationVarsTimelineUpdateStatusProperty,
QueryKeyTimeline,
TimelineData
} from '../timeline'
const updateStatusProperty = ({
queryKey,
rootQueryKey,
status,
payload,
poll
}: MutationVarsTimelineUpdateStatusProperty & { poll?: Mastodon.Poll }) => {
for (const key of [queryKey, rootQueryKey]) {
const updateStatusProperty = (
{ status, payload, poll }: MutationVarsTimelineUpdateStatusProperty & { poll?: Mastodon.Poll },
navigationState: (QueryKeyTimeline | undefined)[]
) => {
const update = (to?: Mastodon.Status): boolean => {
if (!to) return false
enum MapPropertyToCount {
favourited = 'favourites_count',
reblogged = 'reblogs_count'
}
switch (payload.type) {
case 'poll':
to.poll = poll
return true
default:
to[payload.type] = payload.to
switch (payload.type) {
case 'favourited':
case 'reblogged':
if (payload.to) {
to[MapPropertyToCount[payload.type]]++
} else {
to[MapPropertyToCount[payload.type]]--
}
break
}
return true
}
}
for (const key of navigationState) {
if (!key) continue
queryClient.setQueryData<InfiniteData<TimelineData> | undefined>(key, old => {
if (old) {
let foundToot: Mastodon.Status | undefined = undefined
let updated: boolean = false
old.pages = old.pages.map(page => {
if (foundToot) {
return page
} else {
if (typeof (page.body as Mastodon.Conversation[])[0].unread === 'boolean') {
foundToot = (page.body as Mastodon.Conversation[]).find(({ last_status }) =>
last_status?.reblog
? last_status.reblog.id === status.id
: last_status?.id === status.id
)?.last_status
} else if (typeof (page.body as Mastodon.Notification[])[0].type === 'string') {
foundToot = (page.body as Mastodon.Notification[]).find(no =>
no.status?.reblog ? no.status.reblog.id === status.id : no.status?.id === status.id
)?.status
} else {
foundToot = (page.body as Mastodon.Status[]).find(toot =>
toot.reblog ? toot.reblog.id === status.id : toot.id === status.id
)
}
if (updated) return page
return page
}
})
if (foundToot) {
const toot = foundToot as Mastodon.Status
enum MapPropertyToCount {
favourited = 'favourites_count',
reblogged = 'reblogs_count'
}
switch (payload.type) {
case 'poll':
toot.poll = poll
break
default:
toot[payload.type] = payload.to
switch (payload.type) {
case 'favourited':
case 'reblogged':
if (payload.to) {
toot[MapPropertyToCount[payload.type]]++
} else {
toot[MapPropertyToCount[payload.type]]--
}
break
if (typeof (page.body as Mastodon.Conversation[])[0].unread === 'boolean') {
;(page.body as Mastodon.Conversation[]).forEach(({ last_status }) => {
if (last_status?.reblog?.id === status.id) {
updated = update(last_status.reblog)
} else if (last_status?.id === status.id) {
updated = update(last_status)
}
break
})
} else if (typeof (page.body as Mastodon.Notification[])[0].type === 'string') {
;(page.body as Mastodon.Notification[]).forEach(no => {
if (no.status?.reblog?.id === status.id) {
updated = update(no.status.reblog)
} else if (no.status?.id === status.id) {
updated = update(no.status)
}
})
} else {
;(page.body as Mastodon.Status[]).forEach(toot => {
if (toot.reblog?.id === status.id) {
updated = update(toot.reblog)
} else if (toot.id === status.id) {
updated = update(toot)
}
})
}
}
return page
})
}
return old
})
}

View File

@ -5,8 +5,8 @@ export const dev = () => {
if (__DEV__) {
log('log', 'dev', 'loading tools')
// @ts-ignore
import('react-query-native-devtools').then(({ addPlugin }) => {
addPlugin({ queryClient })
})
// import('react-query-native-devtools').then(({ addPlugin }) => {
// addPlugin({ queryClient })
// })
}
}