From ac9738d358ae253cbbf1b7249f2acf23ae83ba28 Mon Sep 17 00:00:00 2001 From: xmflsct Date: Sun, 1 Jan 2023 13:39:48 +0100 Subject: [PATCH 1/7] Remove flat list in compose view --- src/screens/Compose/Root/Actions.tsx | 3 + src/screens/Compose/Root/Suggestion.tsx | 53 --------- src/screens/Compose/Root/Suggestions.tsx | 135 +++++++++++++++++++++++ src/screens/Compose/Root/index.tsx | 73 ++---------- 4 files changed, 149 insertions(+), 115 deletions(-) delete mode 100644 src/screens/Compose/Root/Suggestion.tsx create mode 100644 src/screens/Compose/Root/Suggestions.tsx diff --git a/src/screens/Compose/Root/Actions.tsx b/src/screens/Compose/Root/Actions.tsx index 773683db..b9ef7459 100644 --- a/src/screens/Compose/Root/Actions.tsx +++ b/src/screens/Compose/Root/Actions.tsx @@ -141,6 +141,9 @@ const ComposeActions: React.FC = () => { = ({ item }) => { - const { composeState, composeDispatch } = useContext(ComposeContext) - - useEffect(() => { - if (composeState.text.raw.length === 0) { - composeDispatch({ type: 'tag', payload: undefined }) - } - }, [composeState.text.raw.length]) - - const onPress = () => { - const focusedInput = composeState.textInputFocus.current - const updatedText = (): string => { - const main = item.acct ? `@${item.acct}` : `#${item.name}` - const textInput = composeState.textInputFocus.current - if (composeState.tag) { - const contentFront = composeState[textInput].raw.slice(0, composeState.tag.index) - const contentRear = composeState[textInput].raw.slice(composeState.tag.lastIndex) - - const spaceFront = - composeState[textInput].raw.length === 0 || /\s/g.test(contentFront.slice(-1)) ? '' : ' ' - const spaceRear = /\s/g.test(contentRear[0]) ? '' : ' ' - - return [contentFront, spaceFront, main, spaceRear, contentRear].join('') - } else { - return composeState[textInput].raw - } - } - formatText({ - textInput: focusedInput, - composeDispatch, - content: updatedText(), - disableDebounce: true - }) - haptics('Light') - } - - return item.acct ? ( - - ) : ( - - ) -} - -export default ComposeRootSuggestion diff --git a/src/screens/Compose/Root/Suggestions.tsx b/src/screens/Compose/Root/Suggestions.tsx new file mode 100644 index 00000000..b1ae64e9 --- /dev/null +++ b/src/screens/Compose/Root/Suggestions.tsx @@ -0,0 +1,135 @@ +import ComponentAccount from '@components/Account' +import haptics from '@components/haptics' +import ComponentHashtag from '@components/Hashtag' +import Icon from '@components/Icon' +import ComponentSeparator from '@components/Separator' +import { useSearchQuery } from '@utils/queryHooks/search' +import { StyleConstants } from '@utils/styles/constants' +import { useTheme } from '@utils/styles/ThemeManager' +import React, { Fragment, useContext, useEffect } from 'react' +import { View } from 'react-native' +import { Circle } from 'react-native-animated-spinkit' +import ComposeContext from '../utils/createContext' +import { formatText } from '../utils/processText' + +const ComposeRootSuggestions: React.FC = () => { + const { composeState, composeDispatch } = useContext(ComposeContext) + + const { colors } = useTheme() + + useEffect(() => { + if (composeState.text.raw.length === 0) { + composeDispatch({ type: 'tag', payload: undefined }) + } + }, [composeState.text.raw.length]) + + const mapSchemaToType = () => { + if (composeState.tag) { + switch (composeState.tag?.schema) { + case '@': + return 'accounts' + case '#': + return 'hashtags' + } + } else { + return undefined + } + } + const { isFetching, data, refetch } = useSearchQuery({ + type: mapSchemaToType(), + term: composeState.tag?.raw.substring(1), + limit: 10, + options: { enabled: false } + }) + useEffect(() => { + if ( + (composeState.tag?.schema === '@' || composeState.tag?.schema === '#') && + composeState.tag?.raw + ) { + refetch() + } + }, [composeState.tag]) + + const onPress = (content: string) => { + const focusedInput = composeState.textInputFocus.current + const updatedText = (): string => { + const textInput = composeState.textInputFocus.current + if (composeState.tag) { + const contentFront = composeState[textInput].raw.slice(0, composeState.tag.index) + const contentRear = composeState[textInput].raw.slice(composeState.tag.lastIndex) + + const spaceFront = + contentFront.length === 0 || + composeState[textInput].raw.length === 0 || + /\s/g.test(contentFront.slice(-1)) + ? '' + : ' ' + const spaceRear = /\s/g.test(contentRear[0]) ? '' : ' ' + + return [contentFront, spaceFront, content, spaceRear, contentRear].join('') + } else { + return composeState[textInput].raw + } + } + formatText({ + textInput: focusedInput, + composeDispatch, + content: updatedText(), + disableDebounce: true + }) + haptics('Light') + } + + const main = () => { + if (composeState.tag) { + switch (composeState.tag?.schema) { + case '@': + return ( + + {data?.accounts?.map(account => ( + + onPress(`@${account.acct}`) }} + children={ + + } + /> + + + ))} + + ) + case '#': + return ( + + {data?.hashtags?.map(hashtag => ( + + onPress(`#${hashtag.name}`)} /> + + + ))} + + ) + } + } + } + + return isFetching ? ( + + + + ) : ( + <>{main()} + ) +} + +export default ComposeRootSuggestions diff --git a/src/screens/Compose/Root/index.tsx b/src/screens/Compose/Root/index.tsx index 1a42f7df..dc459320 100644 --- a/src/screens/Compose/Root/index.tsx +++ b/src/screens/Compose/Root/index.tsx @@ -1,21 +1,13 @@ -import ComponentSeparator from '@components/Separator' -import { useSearchQuery } from '@utils/queryHooks/search' -import { StyleConstants } from '@utils/styles/constants' -import { useTheme } from '@utils/styles/ThemeManager' -import React, { useContext, useEffect, useRef } from 'react' -import { AccessibilityInfo, findNodeHandle, FlatList, View } from 'react-native' -import { Circle } from 'react-native-animated-spinkit' +import React, { useEffect, useRef } from 'react' +import { AccessibilityInfo, findNodeHandle, ScrollView, View } from 'react-native' import ComposePosting from '../Posting' -import ComposeContext from '../utils/createContext' import ComposeActions from './Actions' import ComposeDrafts from './Drafts' import ComposeRootFooter from './Footer' import ComposeRootHeader from './Header' -import ComposeRootSuggestion from './Suggestion' +import ComposeRootSuggestion from './Suggestions' const ComposeRoot = () => { - const { colors } = useTheme() - const accessibleRefDrafts = useRef(null) const accessibleRefAttachments = useRef(null) @@ -24,60 +16,17 @@ const ComposeRoot = () => { tagDrafts && AccessibilityInfo.setAccessibilityFocus(tagDrafts) }, [accessibleRefDrafts.current]) - const { composeState } = useContext(ComposeContext) - - const mapSchemaToType = () => { - if (composeState.tag) { - switch (composeState.tag?.schema) { - case '@': - return 'accounts' - case '#': - return 'hashtags' - } - } else { - return undefined - } - } - const { isFetching, data, refetch } = useSearchQuery({ - type: mapSchemaToType(), - term: composeState.tag?.raw.substring(1), - options: { enabled: false } - }) - - useEffect(() => { - if ( - (composeState.tag?.schema === '@' || composeState.tag?.schema === '#') && - composeState.tag?.raw - ) { - refetch() - } - }, [composeState.tag]) - return ( - - } - ListEmptyComponent={ - isFetching ? ( - - - - ) : null - } - keyboardShouldPersistTaps='always' - ListHeaderComponent={ComposeRootHeader} - ListFooterComponent={ - - } - ItemSeparatorComponent={ComponentSeparator} - // @ts-ignore - data={data ? data[mapSchemaToType()] : undefined} - keyExtractor={() => Math.random().toString()} - /> - + <> + + + + + - + + ) } From ced71d66111899d6846a85fdfe5cc071983cb5f4 Mon Sep 17 00:00:00 2001 From: xmflsct Date: Sun, 1 Jan 2023 16:44:55 +0100 Subject: [PATCH 2/7] Reply working for #638 --- src/@types/mastodon.d.ts | 4 ++++ src/screens/Compose/index.tsx | 19 +++++++++++++++++++ src/screens/Compose/utils/reducer.ts | 15 +++++---------- src/screens/Compose/utils/types.d.ts | 4 ++++ src/screens/Tabs/Shared/Toot.tsx | 17 ++++++++++------- src/utils/queryHooks/timeline.ts | 1 + src/utils/styles/ThemeManager.tsx | 2 +- 7 files changed, 44 insertions(+), 18 deletions(-) diff --git a/src/@types/mastodon.d.ts b/src/@types/mastodon.d.ts index d2a83751..ca936344 100644 --- a/src/@types/mastodon.d.ts +++ b/src/@types/mastodon.d.ts @@ -552,6 +552,10 @@ declare namespace Mastodon { language?: string text?: string filtered?: FilterResult[] + + // Internal + _level?: number + _remote?: boolean } type StatusHistory = { diff --git a/src/screens/Compose/index.tsx b/src/screens/Compose/index.tsx index 96020750..346e9650 100644 --- a/src/screens/Compose/index.tsx +++ b/src/screens/Compose/index.tsx @@ -7,9 +7,11 @@ import ComposeRoot from '@screens/Compose/Root' import { formatText } from '@screens/Compose/utils/processText' import { useQueryClient } from '@tanstack/react-query' import { handleError } from '@utils/api/helpers' +import apiInstance from '@utils/api/instance' import { RootStackScreenProps } from '@utils/navigation/navigators' import { useInstanceQuery } from '@utils/queryHooks/instance' import { usePreferencesQuery } from '@utils/queryHooks/preferences' +import { SearchResult } from '@utils/queryHooks/search' import { useTimelineMutation } from '@utils/queryHooks/timeline' import { getAccountStorage, @@ -155,6 +157,23 @@ const ScreenCompose: React.FC> = ({ content: params.accts.map(acct => `@${acct}`).join(' ') + ' ', disableDebounce: true }) + apiInstance({ + version: 'v2', + method: 'get', + url: 'search', + params: { + q: params.incomingStatus.uri, + type: 'statuses', + limit: 1, + resolve: true + } + }) + .then(res => { + if (res.body.statuses[0]?.uri === params.incomingStatus.uri) { + composeDispatch({ type: 'updateReply', payload: res.body.statuses[0] }) + } + }) + .catch(() => {}) break case 'conversation': formatText({ diff --git a/src/screens/Compose/utils/reducer.ts b/src/screens/Compose/utils/reducer.ts index 2440d14b..94d409df 100644 --- a/src/screens/Compose/utils/reducer.ts +++ b/src/screens/Compose/utils/reducer.ts @@ -1,9 +1,6 @@ import { ComposeAction, ComposeState } from './types' -const composeReducer = ( - state: ComposeState, - action: ComposeAction -): ComposeState => { +const composeReducer = (state: ComposeState, action: ComposeAction): ComposeState => { switch (action.type) { case 'loadDraft': const draft = action.payload @@ -67,9 +64,7 @@ const composeReducer = ( ...state, attachments: { ...state.attachments, - uploads: state.attachments.uploads.filter( - upload => upload.local?.hash !== action.payload - ) + uploads: state.attachments.uploads.filter(upload => upload.local?.hash !== action.payload) } } case 'attachment/delete': @@ -77,9 +72,7 @@ const composeReducer = ( ...state, attachments: { ...state.attachments, - uploads: state.attachments.uploads.filter( - upload => upload.remote?.id !== action.payload - ) + uploads: state.attachments.uploads.filter(upload => upload.remote?.id !== action.payload) } } case 'attachment/edit': @@ -101,6 +94,8 @@ const composeReducer = ( ...state, textInputFocus: { ...state.textInputFocus, ...action.payload } } + case 'updateReply': + return { ...state, replyToStatus: action.payload } case 'removeReply': return { ...state, replyToStatus: undefined } default: diff --git a/src/screens/Compose/utils/types.d.ts b/src/screens/Compose/utils/types.d.ts index e30267f6..20198ece 100644 --- a/src/screens/Compose/utils/types.d.ts +++ b/src/screens/Compose/utils/types.d.ts @@ -126,6 +126,10 @@ export type ComposeAction = type: 'textInputFocus' payload: Partial } + | { + type: 'updateReply' + payload: Mastodon.Status + } | { type: 'removeReply' } diff --git a/src/screens/Tabs/Shared/Toot.tsx b/src/screens/Tabs/Shared/Toot.tsx index fef8f609..39bcd73b 100644 --- a/src/screens/Tabs/Shared/Toot.tsx +++ b/src/screens/Tabs/Shared/Toot.tsx @@ -9,6 +9,7 @@ import apiGeneral from '@utils/api/general' import apiInstance from '@utils/api/instance' import { getHost } from '@utils/helpers/urlMatcher' import { TabSharedStackScreenProps } from '@utils/navigation/navigators' +import { QueryKeyTimeline } from '@utils/queryHooks/timeline' import { StyleConstants } from '@utils/styles/constants' import { useTheme } from '@utils/styles/ThemeManager' import React, { useEffect, useRef, useState } from 'react' @@ -56,12 +57,14 @@ const TabSharedToot: React.FC> = ({ const flRef = useRef(null) const scrolled = useRef(false) - const finalData = useRef<(Mastodon.Status & { _level?: number; _remote?: boolean })[]>([ - { ...toot, _level: 0, _remote: false } - ]) + const finalData = useRef([{ ...toot, _level: 0, _remote: false }]) const highlightIndex = useRef(0) + const queryKey: { [key: string]: QueryKeyTimeline } = { + local: ['Timeline', { page: 'Toot', toot: toot.id, remote: false }], + remote: ['Timeline', { page: 'Toot', toot: toot.id, remote: true }] + } const queryLocal = useQuery( - ['Timeline', { page: 'Toot', toot: toot.id, remote: false }], + queryKey.local, async () => { const context = await apiInstance<{ ancestors: Mastodon.Status[] @@ -129,7 +132,7 @@ const TabSharedToot: React.FC> = ({ } ) useQuery( - ['Timeline', { page: 'Toot', toot: toot.id, remote: true }], + queryKey.remote, async () => { let context: | { @@ -196,7 +199,7 @@ const TabSharedToot: React.FC> = ({ if (finalData.current?.length < data.pages[0].body.length) { finalData.current = data.pages[0].body.map(remote => { const localMatch = finalData.current?.find(local => local.uri === remote.uri) - return localMatch ? { ...localMatch, _remote: false } : { ...remote, _remote: true } + return localMatch || { ...remote, _remote: true } }) setHasRemoteContent(true) } @@ -299,7 +302,7 @@ const TabSharedToot: React.FC> = ({ > ({ export const useTheme = () => useContext(ManageThemeContext) -const useColorSchemeDelay = (delay = 50) => { +const useColorSchemeDelay = (delay = 250) => { const [colorScheme, setColorScheme] = React.useState(Appearance.getColorScheme()) const onColorSchemeChange = React.useCallback( throttle( From 56d1090ca9c566855dfd344ed23e5e4162967526 Mon Sep 17 00:00:00 2001 From: xmflsct Date: Sun, 1 Jan 2023 17:20:35 +0100 Subject: [PATCH 3/7] Actions working for #638 --- src/components/Timeline/Shared/Actions.tsx | 5 +++++ src/screens/Compose/index.tsx | 21 ++++----------------- src/screens/Tabs/Shared/Toot.tsx | 11 ++++++++--- src/utils/queryHooks/search.ts | 15 +++++++++++++++ src/utils/queryHooks/timeline.ts | 17 +++++++++++++---- 5 files changed, 45 insertions(+), 24 deletions(-) diff --git a/src/components/Timeline/Shared/Actions.tsx b/src/components/Timeline/Shared/Actions.tsx index 503bd97a..33cb0f4d 100644 --- a/src/components/Timeline/Shared/Actions.tsx +++ b/src/components/Timeline/Shared/Actions.tsx @@ -113,6 +113,7 @@ const TimelineActions: React.FC = () => { rootQueryKey, id: status.id, isReblog: !!reblogStatus, + fetchRemoteURI: status._remote ? status.uri : undefined, payload: { property: 'reblogged', currentValue: status.reblogged, @@ -129,6 +130,7 @@ const TimelineActions: React.FC = () => { rootQueryKey, id: status.id, isReblog: !!reblogStatus, + fetchRemoteURI: status._remote ? status.uri : undefined, payload: { property: 'reblogged', currentValue: status.reblogged, @@ -148,6 +150,7 @@ const TimelineActions: React.FC = () => { rootQueryKey, id: status.id, isReblog: !!reblogStatus, + fetchRemoteURI: status._remote ? status.uri : undefined, payload: { property: 'reblogged', currentValue: status.reblogged, @@ -165,6 +168,7 @@ const TimelineActions: React.FC = () => { rootQueryKey, id: status.id, isReblog: !!reblogStatus, + fetchRemoteURI: status._remote ? status.uri : undefined, payload: { property: 'favourited', currentValue: status.favourited, @@ -180,6 +184,7 @@ const TimelineActions: React.FC = () => { rootQueryKey, id: status.id, isReblog: !!reblogStatus, + fetchRemoteURI: status._remote ? status.uri : undefined, payload: { property: 'bookmarked', currentValue: status.bookmarked, diff --git a/src/screens/Compose/index.tsx b/src/screens/Compose/index.tsx index 346e9650..f832afbf 100644 --- a/src/screens/Compose/index.tsx +++ b/src/screens/Compose/index.tsx @@ -7,11 +7,10 @@ import ComposeRoot from '@screens/Compose/Root' import { formatText } from '@screens/Compose/utils/processText' import { useQueryClient } from '@tanstack/react-query' import { handleError } from '@utils/api/helpers' -import apiInstance from '@utils/api/instance' import { RootStackScreenProps } from '@utils/navigation/navigators' import { useInstanceQuery } from '@utils/queryHooks/instance' import { usePreferencesQuery } from '@utils/queryHooks/preferences' -import { SearchResult } from '@utils/queryHooks/search' +import { searchFetchToot, SearchResult } from '@utils/queryHooks/search' import { useTimelineMutation } from '@utils/queryHooks/timeline' import { getAccountStorage, @@ -157,23 +156,11 @@ const ScreenCompose: React.FC> = ({ content: params.accts.map(acct => `@${acct}`).join(' ') + ' ', disableDebounce: true }) - apiInstance({ - version: 'v2', - method: 'get', - url: 'search', - params: { - q: params.incomingStatus.uri, - type: 'statuses', - limit: 1, - resolve: true + searchFetchToot(params.incomingStatus.uri).then(status => { + if (status?.uri === params.incomingStatus.uri) { + composeDispatch({ type: 'updateReply', payload: status }) } }) - .then(res => { - if (res.body.statuses[0]?.uri === params.incomingStatus.uri) { - composeDispatch({ type: 'updateReply', payload: res.body.statuses[0] }) - } - }) - .catch(() => {}) break case 'conversation': formatText({ diff --git a/src/screens/Tabs/Shared/Toot.tsx b/src/screens/Tabs/Shared/Toot.tsx index 39bcd73b..f1932749 100644 --- a/src/screens/Tabs/Shared/Toot.tsx +++ b/src/screens/Tabs/Shared/Toot.tsx @@ -59,7 +59,7 @@ const TabSharedToot: React.FC> = ({ const finalData = useRef([{ ...toot, _level: 0, _remote: false }]) const highlightIndex = useRef(0) - const queryKey: { [key: string]: QueryKeyTimeline } = { + const queryKey: { local: QueryKeyTimeline; remote: QueryKeyTimeline } = { local: ['Timeline', { page: 'Toot', toot: toot.id, remote: false }], remote: ['Timeline', { page: 'Toot', toot: toot.id, remote: true }] } @@ -199,7 +199,12 @@ const TabSharedToot: React.FC> = ({ if (finalData.current?.length < data.pages[0].body.length) { finalData.current = data.pages[0].body.map(remote => { const localMatch = finalData.current?.find(local => local.uri === remote.uri) - return localMatch || { ...remote, _remote: true } + if (localMatch) { + return localMatch + } else { + remote._remote = true + return remote + } }) setHasRemoteContent(true) } @@ -302,7 +307,7 @@ const TabSharedToot: React.FC> = ({ > ({ return useQuery(queryKey, queryFunction, options) } +export const searchFetchToot = (uri: Mastodon.Status['uri']): Promise => + apiInstance({ + version: 'v2', + method: 'get', + url: 'search', + params: { + q: uri, + type: 'statuses', + limit: 1, + resolve: true + } + }) + .then(res => res.body.statuses[0]) + .catch(() => {}) + export { useSearchQuery } diff --git a/src/utils/queryHooks/timeline.ts b/src/utils/queryHooks/timeline.ts index 9708b75f..e848b8e9 100644 --- a/src/utils/queryHooks/timeline.ts +++ b/src/utils/queryHooks/timeline.ts @@ -4,9 +4,7 @@ import { QueryFunctionContext, useInfiniteQuery, UseInfiniteQueryOptions, - useMutation, - useQuery, - UseQueryOptions + useMutation } from '@tanstack/react-query' import { PagedResponse } from '@utils/api/helpers' import apiInstance from '@utils/api/instance' @@ -15,6 +13,7 @@ import queryClient from '@utils/queryHooks' import { getAccountStorage } from '@utils/storage/actions' import { AxiosError } from 'axios' import { uniqBy } from 'lodash' +import { searchFetchToot } from './search' import deleteItem from './timeline/deleteItem' import editItem from './timeline/editItem' import updateStatusProperty from './timeline/updateStatusProperty' @@ -251,6 +250,7 @@ export type MutationVarsTimelineUpdateStatusProperty = { rootQueryKey?: QueryKeyTimeline id: Mastodon.Status['id'] | Mastodon.Poll['id'] isReblog?: boolean + fetchRemoteURI?: Mastodon.Status['uri'] payload: | { property: 'bookmarked' | 'muted' | 'pinned' @@ -344,13 +344,22 @@ const mutationFunction = async (params: MutationVarsTimeline) => { ...(params.payload.type === 'vote' && { body: formData }) }) default: + let tootId = params.id + if (params.fetchRemoteURI) { + const fetched = await searchFetchToot(params.fetchRemoteURI) + if (fetched) { + tootId = fetched.id + } else { + return Promise.reject() + } + } const body = new FormData() if (params.payload.property === 'reblogged') { body.append('visibility', params.payload.visibility) } return apiInstance({ method: 'post', - url: `statuses/${params.id}/${params.payload.currentValue ? 'un' : ''}${ + url: `statuses/${tootId}/${params.payload.currentValue ? 'un' : ''}${ MapPropertyToUrl[params.payload.property] }`, ...(params.payload.property === 'reblogged' && { body }) From 2705b4b80463a81113f41dcc5bd1fd97e3cecd53 Mon Sep 17 00:00:00 2001 From: xmflsct Date: Sun, 1 Jan 2023 18:37:05 +0100 Subject: [PATCH 4/7] Simplify update toot logic --- src/components/Timeline/Default.tsx | 5 +- src/components/Timeline/Notifications.tsx | 1 + src/components/Timeline/Shared/Actioned.tsx | 5 +- src/components/Timeline/Shared/Actions.tsx | 57 +++------ src/components/Timeline/Shared/Context.tsx | 1 - src/components/Timeline/Shared/Poll.tsx | 53 +++----- src/components/contextMenu/status.ts | 14 +-- src/utils/queryHooks/timeline.ts | 60 ++++----- .../timeline/update/conversation.ts | 34 ----- .../timeline/update/notification.ts | 31 ----- .../queryHooks/timeline/update/status.ts | 46 ------- .../timeline/updateStatusProperty.ts | 117 +++++++----------- 12 files changed, 114 insertions(+), 310 deletions(-) delete mode 100644 src/utils/queryHooks/timeline/update/conversation.ts delete mode 100644 src/utils/queryHooks/timeline/update/notification.ts delete mode 100644 src/utils/queryHooks/timeline/update/status.ts diff --git a/src/components/Timeline/Default.tsx b/src/components/Timeline/Default.tsx index ae264a35..48725b8a 100644 --- a/src/components/Timeline/Default.tsx +++ b/src/components/Timeline/Default.tsx @@ -87,9 +87,9 @@ const TimelineDefault: React.FC = ({ const main = () => ( <> {item.reblog ? ( - + ) : item._pinned ? ( - + ) : null} = ({ queryKey, rootQueryKey, status, - reblogStatus: item.reblog ? item : undefined, ownAccount, spoilerHidden, rawContent, diff --git a/src/components/Timeline/Notifications.tsx b/src/components/Timeline/Notifications.tsx index f82332f4..75b7b030 100644 --- a/src/components/Timeline/Notifications.tsx +++ b/src/components/Timeline/Notifications.tsx @@ -61,6 +61,7 @@ const TimelineNotifications: React.FC = ({ notification, queryKey }) => { action={notification.type} isNotification account={notification.account} + rootStatus={notification.status} /> ) : null} diff --git a/src/components/Timeline/Shared/Actioned.tsx b/src/components/Timeline/Shared/Actioned.tsx index 8e73de69..62b9e29c 100644 --- a/src/components/Timeline/Shared/Actioned.tsx +++ b/src/components/Timeline/Shared/Actioned.tsx @@ -14,11 +14,12 @@ export interface Props { action: Mastodon.Notification['type'] | 'reblog' | 'pinned' isNotification?: boolean account?: Mastodon.Account // For notification + rootStatus?: Mastodon.Status } const TimelineActioned: React.FC = ({ action, isNotification, ...rest }) => { - const { status, reblogStatus } = useContext(StatusContext) - const account = rest.account || (reblogStatus ? reblogStatus.account : status?.account) + const { status } = useContext(StatusContext) + const account = rest.account || (rest.rootStatus || status)?.account if (!account) return null const { t } = useTranslation('componentTimeline') diff --git a/src/components/Timeline/Shared/Actions.tsx b/src/components/Timeline/Shared/Actions.tsx index 33cb0f4d..7df190f0 100644 --- a/src/components/Timeline/Shared/Actions.tsx +++ b/src/components/Timeline/Shared/Actions.tsx @@ -22,7 +22,7 @@ import { Pressable, StyleSheet, View } from 'react-native' import StatusContext from './Context' const TimelineActions: React.FC = () => { - const { queryKey, rootQueryKey, status, reblogStatus, ownAccount, highlighted, disableDetails } = + const { queryKey, rootQueryKey, status, ownAccount, highlighted, disableDetails } = useContext(StatusContext) if (!queryKey || !status || disableDetails) return null @@ -38,16 +38,16 @@ const TimelineActions: React.FC = () => { const theParams = params as MutationVarsTimelineUpdateStatusProperty if ( // Un-bookmark from bookmarks page - (queryKey[1].page === 'Bookmarks' && theParams.payload.property === 'bookmarked') || + (queryKey[1].page === 'Bookmarks' && theParams.payload.type === 'bookmarked') || // Un-favourite from favourites page - (queryKey[1].page === 'Favourites' && theParams.payload.property === 'favourited') + (queryKey[1].page === 'Favourites' && theParams.payload.type === 'favourited') ) { queryClient.invalidateQueries(queryKey) - } else if (theParams.payload.property === 'favourited') { + } else if (theParams.payload.type === 'favourited') { // When favourited, update favourited page const tempQueryKey: QueryKeyTimeline = ['Timeline', { page: 'Favourites' }] queryClient.invalidateQueries(tempQueryKey) - } else if (theParams.payload.property === 'bookmarked') { + } else if (theParams.payload.type === 'bookmarked') { // When bookmarked, update bookmark page const tempQueryKey: QueryKeyTimeline = ['Timeline', { page: 'Bookmarks' }] queryClient.invalidateQueries(tempQueryKey) @@ -60,7 +60,7 @@ const TimelineActions: React.FC = () => { type: 'error', message: t('common:message.error.message', { function: t( - `componentTimeline:shared.actions.${correctParam.payload.property}.function` as any + `componentTimeline:shared.actions.${correctParam.payload.type}.function` as any ) }), ...(err.status && @@ -111,14 +111,9 @@ const TimelineActions: React.FC = () => { type: 'updateStatusProperty', queryKey, rootQueryKey, - id: status.id, - isReblog: !!reblogStatus, - fetchRemoteURI: status._remote ? status.uri : undefined, + status, payload: { - property: 'reblogged', - currentValue: status.reblogged, - propertyCount: 'reblogs_count', - countValue: status.reblogs_count, + type: 'reblogged', visibility: 'public' } }) @@ -128,14 +123,9 @@ const TimelineActions: React.FC = () => { type: 'updateStatusProperty', queryKey, rootQueryKey, - id: status.id, - isReblog: !!reblogStatus, - fetchRemoteURI: status._remote ? status.uri : undefined, + status, payload: { - property: 'reblogged', - currentValue: status.reblogged, - propertyCount: 'reblogs_count', - countValue: status.reblogs_count, + type: 'reblogged', visibility: 'unlisted' } }) @@ -148,14 +138,9 @@ const TimelineActions: React.FC = () => { type: 'updateStatusProperty', queryKey, rootQueryKey, - id: status.id, - isReblog: !!reblogStatus, - fetchRemoteURI: status._remote ? status.uri : undefined, + status, payload: { - property: 'reblogged', - currentValue: status.reblogged, - propertyCount: 'reblogs_count', - countValue: status.reblogs_count, + type: 'reblogged', visibility: 'public' } }) @@ -166,14 +151,9 @@ const TimelineActions: React.FC = () => { type: 'updateStatusProperty', queryKey, rootQueryKey, - id: status.id, - isReblog: !!reblogStatus, - fetchRemoteURI: status._remote ? status.uri : undefined, + status, payload: { - property: 'favourited', - currentValue: status.favourited, - propertyCount: 'favourites_count', - countValue: status.favourites_count + type: 'favourited' } }) } @@ -182,14 +162,9 @@ const TimelineActions: React.FC = () => { type: 'updateStatusProperty', queryKey, rootQueryKey, - id: status.id, - isReblog: !!reblogStatus, - fetchRemoteURI: status._remote ? status.uri : undefined, + status, payload: { - property: 'bookmarked', - currentValue: status.bookmarked, - propertyCount: undefined, - countValue: undefined + type: 'bookmarked' } }) } diff --git a/src/components/Timeline/Shared/Context.tsx b/src/components/Timeline/Shared/Context.tsx index ea689fc2..cc23fb8c 100644 --- a/src/components/Timeline/Shared/Context.tsx +++ b/src/components/Timeline/Shared/Context.tsx @@ -9,7 +9,6 @@ type StatusContextType = { status?: Mastodon.Status - reblogStatus?: Mastodon.Status // When it is a reblog, pass the root status ownAccount?: boolean spoilerHidden?: boolean rawContent?: React.MutableRefObject // When highlighted, for translate, edit history diff --git a/src/components/Timeline/Shared/Poll.tsx b/src/components/Timeline/Shared/Poll.tsx index 7e5f1f3a..d2de4b53 100644 --- a/src/components/Timeline/Shared/Poll.tsx +++ b/src/components/Timeline/Shared/Poll.tsx @@ -20,15 +20,8 @@ import { Pressable, View } from 'react-native' import StatusContext from './Context' const TimelinePoll: React.FC = () => { - const { - queryKey, - rootQueryKey, - status, - reblogStatus, - ownAccount, - spoilerHidden, - disableDetails - } = useContext(StatusContext) + const { queryKey, rootQueryKey, status, ownAccount, spoilerHidden, disableDetails } = + useContext(StatusContext) if (!queryKey || !status || !status.poll) return null const poll = status.poll @@ -45,10 +38,9 @@ const TimelinePoll: React.FC = () => { rootQueryKey && queryClient.cancelQueries(rootQueryKey) haptics('Success') - switch (theParams.payload.property) { + switch (theParams.payload.type) { case 'poll': - theParams.payload.data = body as unknown as Mastodon.Poll - updateStatusProperty(theParams) + updateStatusProperty({ ...theParams, poll: body as unknown as Mastodon.Poll }) break } }, @@ -84,12 +76,10 @@ const TimelinePoll: React.FC = () => { type: 'updateStatusProperty', queryKey, rootQueryKey, - id: status.id, - isReblog: !!reblogStatus, + status, payload: { - property: 'poll', - id: poll.id, - type: 'vote', + type: 'poll', + action: 'vote', options: allOptions } }) @@ -110,12 +100,10 @@ const TimelinePoll: React.FC = () => { type: 'updateStatusProperty', queryKey, rootQueryKey, - id: status.id, - isReblog: !!reblogStatus, + status, payload: { - property: 'poll', - id: poll.id, - type: 'refresh' + type: 'poll', + action: 'refresh' } }) } @@ -230,13 +218,9 @@ const TimelinePoll: React.FC = () => { const pollVoteCounts = () => { if (poll.voters_count !== null) { - return ( - t('componentTimeline:shared.poll.meta.count.voters', { count: poll.voters_count }) + ' • ' - ) + return t('componentTimeline:shared.poll.meta.count.voters', { count: poll.voters_count }) } else if (poll.votes_count !== null) { - return ( - t('componentTimeline:shared.poll.meta.count.votes', { count: poll.votes_count }) + ' • ' - ) + return t('componentTimeline:shared.poll.meta.count.votes', { count: poll.votes_count }) } } @@ -246,11 +230,14 @@ const TimelinePoll: React.FC = () => { } else { if (poll.expires_at) { return ( - ]} - /> + <> + {' • '} + ]} + /> + ) } } diff --git a/src/components/contextMenu/status.ts b/src/components/contextMenu/status.ts index 33b149e7..b36a7042 100644 --- a/src/components/contextMenu/status.ts +++ b/src/components/contextMenu/status.ts @@ -35,7 +35,7 @@ const menuStatus = ({ onMutate: true, onError: (err: any, params, oldData) => { const theFunction = (params as MutationVarsTimelineUpdateStatusProperty).payload - ? (params as MutationVarsTimelineUpdateStatusProperty).payload.property + ? (params as MutationVarsTimelineUpdateStatusProperty).payload.type : 'delete' displayMessage({ theme, @@ -195,10 +195,9 @@ const menuStatus = ({ type: 'updateStatusProperty', queryKey, rootQueryKey, - id: status.id, + status, payload: { - property: 'muted', - currentValue: status.muted + type: 'muted' } }), disabled: false, @@ -220,12 +219,9 @@ const menuStatus = ({ type: 'updateStatusProperty', queryKey, rootQueryKey, - id: status.id, + status, payload: { - property: 'pinned', - currentValue: status.pinned, - propertyCount: undefined, - countValue: undefined + type: 'pinned' } }), disabled: false, diff --git a/src/utils/queryHooks/timeline.ts b/src/utils/queryHooks/timeline.ts index e848b8e9..be798429 100644 --- a/src/utils/queryHooks/timeline.ts +++ b/src/utils/queryHooks/timeline.ts @@ -248,35 +248,23 @@ export type MutationVarsTimelineUpdateStatusProperty = { type: 'updateStatusProperty' queryKey: QueryKeyTimeline rootQueryKey?: QueryKeyTimeline - id: Mastodon.Status['id'] | Mastodon.Poll['id'] - isReblog?: boolean - fetchRemoteURI?: Mastodon.Status['uri'] + status: Mastodon.Status payload: | { - property: 'bookmarked' | 'muted' | 'pinned' - currentValue: boolean - propertyCount?: undefined - countValue?: undefined + type: 'bookmarked' | 'muted' | 'pinned' | 'favourited' } | { - property: 'favourited' - currentValue: boolean - propertyCount: 'favourites_count' | 'reblogs_count' - countValue: number - } - | { - property: 'reblogged' - currentValue: boolean - propertyCount: 'favourites_count' | 'reblogs_count' - countValue: number + type: 'reblogged' visibility: 'public' | 'unlisted' } | { - property: 'poll' - id: Mastodon.Poll['id'] - type: 'vote' | 'refresh' - options?: boolean[] - data?: Mastodon.Poll + type: 'poll' + action: 'vote' + options: boolean[] + } + | { + type: 'poll' + action: 'refresh' } } @@ -325,10 +313,10 @@ export type MutationVarsTimeline = const mutationFunction = async (params: MutationVarsTimeline) => { switch (params.type) { case 'updateStatusProperty': - switch (params.payload.property) { + switch (params.payload.type) { case 'poll': const formData = new FormData() - params.payload.type === 'vote' && + params.payload.action === 'vote' && params.payload.options?.forEach((option, index) => { if (option) { formData.append('choices[]', index.toString()) @@ -336,17 +324,17 @@ const mutationFunction = async (params: MutationVarsTimeline) => { }) return apiInstance({ - method: params.payload.type === 'vote' ? 'post' : 'get', + method: params.payload.action === 'vote' ? 'post' : 'get', url: - params.payload.type === 'vote' - ? `polls/${params.payload.id}/votes` - : `polls/${params.payload.id}`, - ...(params.payload.type === 'vote' && { body: formData }) + params.payload.action === 'vote' + ? `polls/${params.status.poll?.id}/votes` + : `polls/${params.status.poll?.id}`, + ...(params.payload.action === 'vote' && { body: formData }) }) default: - let tootId = params.id - if (params.fetchRemoteURI) { - const fetched = await searchFetchToot(params.fetchRemoteURI) + let tootId = params.status.id + if (params.status._remote) { + const fetched = await searchFetchToot(params.status.uri) if (fetched) { tootId = fetched.id } else { @@ -354,15 +342,15 @@ const mutationFunction = async (params: MutationVarsTimeline) => { } } const body = new FormData() - if (params.payload.property === 'reblogged') { + if (params.payload.type === 'reblogged') { body.append('visibility', params.payload.visibility) } return apiInstance({ method: 'post', - url: `statuses/${tootId}/${params.payload.currentValue ? 'un' : ''}${ - MapPropertyToUrl[params.payload.property] + url: `statuses/${tootId}/${params.status[params.payload.type] ? '' : 'un'}${ + MapPropertyToUrl[params.payload.type] }`, - ...(params.payload.property === 'reblogged' && { body }) + ...(params.payload.type === 'reblogged' && { body }) }) } case 'updateAccountProperty': diff --git a/src/utils/queryHooks/timeline/update/conversation.ts b/src/utils/queryHooks/timeline/update/conversation.ts deleted file mode 100644 index 9211bd4a..00000000 --- a/src/utils/queryHooks/timeline/update/conversation.ts +++ /dev/null @@ -1,34 +0,0 @@ -import { MutationVarsTimelineUpdateStatusProperty } from '@utils/queryHooks/timeline' - -const updateConversation = ({ - item, - payload -}: { - item: Mastodon.Conversation - payload: MutationVarsTimelineUpdateStatusProperty['payload'] -}) => { - switch (payload.property) { - case 'poll': - if (item.last_status) { - item.last_status[payload.property] = payload.data - } - return item - default: - if (item.last_status) { - item.last_status[payload.property] = - typeof payload.currentValue === 'boolean' - ? !payload.currentValue - : true - if (payload.propertyCount) { - if (typeof payload.currentValue === 'boolean' && payload.currentValue) { - item.last_status[payload.propertyCount] = payload.countValue - 1 - } else { - item.last_status[payload.propertyCount] = payload.countValue + 1 - } - } - } - return item - } -} - -export default updateConversation diff --git a/src/utils/queryHooks/timeline/update/notification.ts b/src/utils/queryHooks/timeline/update/notification.ts deleted file mode 100644 index 1d652e77..00000000 --- a/src/utils/queryHooks/timeline/update/notification.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { MutationVarsTimelineUpdateStatusProperty } from '@utils/queryHooks/timeline' - -const updateNotification = ({ - item, - payload -}: { - item: Mastodon.Notification - payload: MutationVarsTimelineUpdateStatusProperty['payload'] -}) => { - switch (payload.property) { - case 'poll': - return item - default: - if (item.status) { - item.status[payload.property] = - typeof payload.currentValue === 'boolean' - ? !payload.currentValue - : true - if (payload.propertyCount) { - if (typeof payload.currentValue === 'boolean' && payload.currentValue) { - item.status[payload.propertyCount] = payload.countValue - 1 - } else { - item.status[payload.propertyCount] = payload.countValue + 1 - } - } - } - return item - } -} - -export default updateNotification diff --git a/src/utils/queryHooks/timeline/update/status.ts b/src/utils/queryHooks/timeline/update/status.ts deleted file mode 100644 index c6b0b5f4..00000000 --- a/src/utils/queryHooks/timeline/update/status.ts +++ /dev/null @@ -1,46 +0,0 @@ -import { MutationVarsTimelineUpdateStatusProperty } from '@utils/queryHooks/timeline' - -const updateStatus = ({ - item, - isReblog, - payload -}: { - item: Mastodon.Status - isReblog?: boolean - payload: MutationVarsTimelineUpdateStatusProperty['payload'] -}) => { - switch (payload.property) { - case 'poll': - if (isReblog) { - item.reblog!.poll = payload.data - } else { - item.poll = payload.data - } - break - default: - if (isReblog) { - item.reblog![payload.property] = - typeof payload.currentValue === 'boolean' ? !payload.currentValue : true - if (payload.propertyCount) { - if (typeof payload.currentValue === 'boolean' && payload.currentValue) { - item.reblog![payload.propertyCount] = payload.countValue - 1 - } else { - item.reblog![payload.propertyCount] = payload.countValue + 1 - } - } - } else { - item[payload.property] = - typeof payload.currentValue === 'boolean' ? !payload.currentValue : true - if (payload.propertyCount) { - if (typeof payload.currentValue === 'boolean' && payload.currentValue) { - item[payload.propertyCount] = payload.countValue - 1 - } else { - item[payload.propertyCount] = payload.countValue + 1 - } - } - } - return item - } -} - -export default updateStatus diff --git a/src/utils/queryHooks/timeline/updateStatusProperty.ts b/src/utils/queryHooks/timeline/updateStatusProperty.ts index fab61536..da0b9ee4 100644 --- a/src/utils/queryHooks/timeline/updateStatusProperty.ts +++ b/src/utils/queryHooks/timeline/updateStatusProperty.ts @@ -1,103 +1,72 @@ import { InfiniteData } from '@tanstack/react-query' import queryClient from '@utils/queryHooks' import { MutationVarsTimelineUpdateStatusProperty, TimelineData } from '../timeline' -import updateConversation from './update/conversation' -import updateNotification from './update/notification' -import updateStatus from './update/status' const updateStatusProperty = ({ queryKey, rootQueryKey, - id, - isReblog, - payload -}: MutationVarsTimelineUpdateStatusProperty) => { - queryClient.setQueryData | undefined>(queryKey, old => { - if (old) { - let foundToot = false - old.pages = old.pages.map(page => { - // Skip rest of the pages if any toot is found - if (foundToot) { - return page - } else { - if (typeof (page.body as Mastodon.Conversation[])[0].unread === 'boolean') { - const items = page.body as Mastodon.Conversation[] - const tootIndex = items.findIndex(({ last_status }) => last_status?.id === id) - if (tootIndex >= 0) { - foundToot = true - updateConversation({ item: items[tootIndex], payload }) - } - return page - } else if (typeof (page.body as Mastodon.Notification[])[0].type === 'string') { - const items = page.body as Mastodon.Notification[] - const tootIndex = items.findIndex(({ status }) => status?.id === id) - if (tootIndex >= 0) { - foundToot = true - updateNotification({ item: items[tootIndex], payload }) - } - } else { - const items = page.body as Mastodon.Status[] - const tootIndex = isReblog - ? items.findIndex(({ reblog }) => reblog?.id === id) - : items.findIndex(toot => toot.id === id) - // if favourites page and notifications page, remove the item instead - if (tootIndex >= 0) { - foundToot = true - updateStatus({ item: items[tootIndex], isReblog, payload }) - } - } + status, + payload, + poll +}: MutationVarsTimelineUpdateStatusProperty & { poll?: Mastodon.Poll }) => { + for (const key of [queryKey, rootQueryKey]) { + if (!key) continue - return page - } - }) - } - - return old - }) - - rootQueryKey && - queryClient.setQueryData | undefined>(rootQueryKey, old => { + queryClient.setQueryData | undefined>(key, old => { if (old) { - let foundToot = false + let foundToot: Mastodon.Status | undefined = undefined old.pages = old.pages.map(page => { - // Skip rest of the pages if any toot is found if (foundToot) { return page } else { if (typeof (page.body as Mastodon.Conversation[])[0].unread === 'boolean') { - const items = page.body as Mastodon.Conversation[] - const tootIndex = items.findIndex(({ last_status }) => last_status?.id === id) - if (tootIndex >= 0) { - foundToot = true - updateConversation({ item: items[tootIndex], payload }) - } + foundToot = (page.body as Mastodon.Conversation[]).find( + ({ last_status }) => last_status?.id === status.id + )?.last_status return page } else if (typeof (page.body as Mastodon.Notification[])[0].type === 'string') { - const items = page.body as Mastodon.Notification[] - const tootIndex = items.findIndex(({ status }) => status?.id === id) - if (tootIndex >= 0) { - foundToot = true - updateNotification({ item: items[tootIndex], payload }) - } + foundToot = (page.body as Mastodon.Notification[]).find( + no => no.status?.id === status.id + )?.status } else { - const items = page.body as Mastodon.Status[] - const tootIndex = isReblog - ? items.findIndex(({ reblog }) => reblog?.id === id) - : items.findIndex(toot => toot.id === id) - // if favourites page and notifications page, remove the item instead - if (tootIndex >= 0) { - foundToot = true - updateStatus({ item: items[tootIndex], isReblog, payload }) - } + foundToot = (page.body as Mastodon.Status[]).find(toot => toot.id === status.id) } return page } }) + + if (foundToot) { + enum MapPropertyToCount { + favourited = 'favourites_count', + reblogged = 'reblogs_count' + } + + switch (payload.type) { + case 'poll': + status.poll = poll + break + default: + status[payload.type] = + typeof status[payload.type] === 'boolean' ? !status[payload.type] : true + switch (payload.type) { + case 'favourited': + case 'reblogged': + if (typeof status[payload.type] === 'boolean' && status[payload.type]) { + status[MapPropertyToCount[payload.type]]-- + } else { + status[MapPropertyToCount[payload.type]]++ + } + break + } + break + } + } } return old }) + } } export default updateStatusProperty From f3e1741629566200a2959a1706b740ef6a66d706 Mon Sep 17 00:00:00 2001 From: xmflsct Date: Sun, 1 Jan 2023 18:48:32 +0100 Subject: [PATCH 5/7] Update updateStatusProperty.ts --- .../queryHooks/timeline/updateStatusProperty.ts | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/utils/queryHooks/timeline/updateStatusProperty.ts b/src/utils/queryHooks/timeline/updateStatusProperty.ts index da0b9ee4..a942360a 100644 --- a/src/utils/queryHooks/timeline/updateStatusProperty.ts +++ b/src/utils/queryHooks/timeline/updateStatusProperty.ts @@ -20,16 +20,20 @@ const updateStatusProperty = ({ return page } else { if (typeof (page.body as Mastodon.Conversation[])[0].unread === 'boolean') { - foundToot = (page.body as Mastodon.Conversation[]).find( - ({ last_status }) => last_status?.id === status.id + 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 return page } else if (typeof (page.body as Mastodon.Notification[])[0].type === 'string') { - foundToot = (page.body as Mastodon.Notification[]).find( - no => no.status?.id === status.id + 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.id === status.id) + foundToot = (page.body as Mastodon.Status[]).find(toot => + toot.reblog ? toot.reblog.id === status.id : toot.id === status.id + ) } return page From 62df29a4795f9a05e069df6830f915c02148b9c4 Mon Sep 17 00:00:00 2001 From: xmflsct Date: Sun, 1 Jan 2023 18:54:42 +0100 Subject: [PATCH 6/7] Update status.ts --- src/components/contextMenu/status.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/components/contextMenu/status.ts b/src/components/contextMenu/status.ts index b36a7042..30cd24c0 100644 --- a/src/components/contextMenu/status.ts +++ b/src/components/contextMenu/status.ts @@ -202,7 +202,7 @@ const menuStatus = ({ }), disabled: false, destructive: false, - hidden: !ownAccount && !status.mentions?.filter(mention => mention.id === accountId).length + hidden: !ownAccount }, title: t('componentContextMenu:status.mute.action', { defaultValue: 'false', @@ -224,9 +224,9 @@ const menuStatus = ({ type: 'pinned' } }), - disabled: false, + disabled: status.visibility !== 'public' && status.visibility !== 'unlisted', destructive: false, - hidden: !ownAccount || (status.visibility !== 'public' && status.visibility !== 'unlisted') + hidden: !ownAccount }, title: t('componentContextMenu:status.pin.action', { defaultValue: 'false', From 6dafbc96af74ba98808337b0b5a5bec96feb0286 Mon Sep 17 00:00:00 2001 From: xmflsct Date: Mon, 2 Jan 2023 02:08:12 +0100 Subject: [PATCH 7/7] Account actions working for #638 --- src/@types/i18next.d.ts | 2 - src/components/Parse/HTML.tsx | 5 +- src/components/Timeline/Shared/Actioned.tsx | 3 +- .../Timeline/Shared/Attachment/AltText.tsx | 9 +- src/components/Timeline/Shared/Avatar.tsx | 3 +- src/components/Timeline/Shared/Content.tsx | 2 +- .../Timeline/Shared/HeaderShared/Replies.tsx | 7 +- src/components/contextMenu/account.ts | 48 +++++--- src/i18n/ca/index.ts | 1 - src/i18n/ca/screens/actions.json | 7 -- src/i18n/cs/screens/actions.json | 7 -- src/i18n/de/index.ts | 1 - src/i18n/de/screens/actions.json | 7 -- src/i18n/en/components/timeline.json | 3 +- src/i18n/en/index.ts | 1 - src/i18n/en/screens/actions.json | 7 -- src/i18n/en/screens/tabs.json | 6 +- src/i18n/es/index.ts | 1 - src/i18n/es/screens/actions.json | 7 -- src/i18n/fr/index.ts | 1 - src/i18n/fr/screens/actions.json | 7 -- src/i18n/it/index.ts | 1 - src/i18n/it/screens/actions.json | 7 -- src/i18n/ja/index.ts | 1 - src/i18n/ja/screens/actions.json | 7 -- src/i18n/ko/index.ts | 1 - src/i18n/ko/screens/actions.json | 7 -- src/i18n/nl/index.ts | 1 - src/i18n/nl/screens/actions.json | 7 -- src/i18n/pl/screens/actions.json | 7 -- src/i18n/pt_BR/index.ts | 1 - src/i18n/pt_BR/screens/actions.json | 7 -- src/i18n/ru/screens/actions.json | 7 -- src/i18n/sv/index.ts | 1 - src/i18n/sv/screens/actions.json | 7 -- src/i18n/uk/index.ts | 1 - src/i18n/uk/screens/actions.json | 7 -- src/i18n/vi/index.ts | 1 - src/i18n/vi/screens/actions.json | 7 -- src/i18n/zh-Hans/index.ts | 1 - src/i18n/zh-Hans/screens/actions.json | 7 -- src/i18n/zh-Hant/index.ts | 1 - src/i18n/zh-Hant/screens/actions.json | 7 -- src/screens/Actions.tsx | 112 ------------------ src/screens/Actions/AltText.tsx | 42 ------- src/screens/Tabs/Me/Root/MyInfo.tsx | 10 +- src/screens/Tabs/Me/Root/index.tsx | 14 +-- .../Tabs/Shared/Account/Attachments.tsx | 40 +++---- src/screens/Tabs/Shared/Account/Context.tsx | 9 ++ src/screens/Tabs/Shared/Account/Header.tsx | 9 +- .../Tabs/Shared/Account/Information.tsx | 22 ++-- .../Shared/Account/Information/Account.tsx | 19 ++- .../Shared/Account/Information/Actions.tsx | 14 +-- .../Shared/Account/Information/Avatar.tsx | 12 +- .../Shared/Account/Information/Created.tsx | 12 +- .../Shared/Account/Information/Fields.tsx | 12 +- .../Tabs/Shared/Account/Information/Name.tsx | 9 +- .../Tabs/Shared/Account/Information/Note.tsx | 12 +- .../Tabs/Shared/Account/Information/Stats.tsx | 12 +- src/screens/Tabs/Shared/Account/Nav.tsx | 8 +- src/screens/Tabs/Shared/Account/index.tsx | 35 +++--- .../Shared/Account/utils/createContext.ts | 10 -- .../Tabs/Shared/Account/utils/initialState.ts | 9 -- .../Tabs/Shared/Account/utils/reducer.ts | 19 --- .../Tabs/Shared/Account/utils/types.d.ts | 22 ---- src/screens/Tabs/Shared/Attachments.tsx | 2 +- src/screens/Tabs/Shared/Report.tsx | 17 ++- src/screens/Tabs/Shared/Toot.tsx | 92 ++++---------- src/screens/index.tsx | 10 -- src/utils/navigation/navigators.ts | 11 +- src/utils/queryHooks/account.ts | 37 +++++- src/utils/queryHooks/relationship.ts | 15 ++- src/utils/queryHooks/timeline.ts | 12 +- 73 files changed, 262 insertions(+), 626 deletions(-) delete mode 100644 src/i18n/ca/screens/actions.json delete mode 100644 src/i18n/cs/screens/actions.json delete mode 100644 src/i18n/de/screens/actions.json delete mode 100644 src/i18n/en/screens/actions.json delete mode 100644 src/i18n/es/screens/actions.json delete mode 100644 src/i18n/fr/screens/actions.json delete mode 100644 src/i18n/it/screens/actions.json delete mode 100644 src/i18n/ja/screens/actions.json delete mode 100644 src/i18n/ko/screens/actions.json delete mode 100644 src/i18n/nl/screens/actions.json delete mode 100644 src/i18n/pl/screens/actions.json delete mode 100644 src/i18n/pt_BR/screens/actions.json delete mode 100644 src/i18n/ru/screens/actions.json delete mode 100644 src/i18n/sv/screens/actions.json delete mode 100644 src/i18n/uk/screens/actions.json delete mode 100644 src/i18n/vi/screens/actions.json delete mode 100644 src/i18n/zh-Hans/screens/actions.json delete mode 100644 src/i18n/zh-Hant/screens/actions.json delete mode 100644 src/screens/Actions.tsx delete mode 100644 src/screens/Actions/AltText.tsx create mode 100644 src/screens/Tabs/Shared/Account/Context.tsx delete mode 100644 src/screens/Tabs/Shared/Account/utils/createContext.ts delete mode 100644 src/screens/Tabs/Shared/Account/utils/initialState.ts delete mode 100644 src/screens/Tabs/Shared/Account/utils/reducer.ts delete mode 100644 src/screens/Tabs/Shared/Account/utils/types.d.ts diff --git a/src/@types/i18next.d.ts b/src/@types/i18next.d.ts index 0eebc410..ebce9f85 100644 --- a/src/@types/i18next.d.ts +++ b/src/@types/i18next.d.ts @@ -4,7 +4,6 @@ import common from '../i18n/en/common.json' import screens from '../i18n/en/screens.json' import screenAccountSelection from '../i18n/en/screens/accountSelection.json' -import screenActions from '../i18n/en/screens/actions.json' import screenAnnouncements from '../i18n/en/screens/announcements.json' import screenCompose from '../i18n/en/screens/compose.json' import screenImageViewer from '../i18n/en/screens/imageViewer.json' @@ -26,7 +25,6 @@ declare module 'i18next' { screens: typeof screens screenAccountSelection: typeof screenAccountSelection - screenActions: typeof screenActions screenAnnouncements: typeof screenAnnouncements screenCompose: typeof screenCompose screenImageViewer: typeof screenImageViewer diff --git a/src/components/Parse/HTML.tsx b/src/components/Parse/HTML.tsx index 246f839a..18bdd497 100644 --- a/src/components/Parse/HTML.tsx +++ b/src/components/Parse/HTML.tsx @@ -168,7 +168,10 @@ const ParseHTML: React.FC = ({ matchedMention && !disableDetails && !sameAccount && - navigation.push('Tab-Shared-Account', { account: matchedMention }) + navigation.push('Tab-Shared-Account', { + account: matchedMention, + isRemote: status?._remote + }) } children={node.children.map(unwrapNode).join('')} /> diff --git a/src/components/Timeline/Shared/Actioned.tsx b/src/components/Timeline/Shared/Actioned.tsx index 62b9e29c..d6446a31 100644 --- a/src/components/Timeline/Shared/Actioned.tsx +++ b/src/components/Timeline/Shared/Actioned.tsx @@ -37,7 +37,8 @@ const TimelineActioned: React.FC = ({ action, isNotification, ...rest }) /> ) - const onPress = () => navigation.push('Tab-Shared-Account', { account }) + const onPress = () => + navigation.push('Tab-Shared-Account', { account, isRemote: status?._remote }) const children = () => { switch (action) { diff --git a/src/components/Timeline/Shared/Attachment/AltText.tsx b/src/components/Timeline/Shared/Attachment/AltText.tsx index ce1bf2a6..bd108545 100644 --- a/src/components/Timeline/Shared/Attachment/AltText.tsx +++ b/src/components/Timeline/Shared/Attachment/AltText.tsx @@ -1,8 +1,7 @@ import Button from '@components/Button' -import { useNavigation } from '@react-navigation/native' -import { StackNavigationProp } from '@react-navigation/stack' -import { RootStackParamList } from '@utils/navigation/navigators' import { StyleConstants } from '@utils/styles/constants' +import { useTranslation } from 'react-i18next' +import { Alert } from 'react-native' export interface Props { sensitiveShown: boolean @@ -14,7 +13,7 @@ const AttachmentAltText: React.FC = ({ sensitiveShown, text }) => { return null } - const navigation = useNavigation>() + const { t } = useTranslation('componentTimeline') return !sensitiveShown ? (