diff --git a/ios/Podfile b/ios/Podfile index ce23340c..26c6ceef 100644 --- a/ios/Podfile +++ b/ios/Podfile @@ -19,7 +19,7 @@ target 'tooot' do :path => config[:reactNativePath], :hermes_enabled => true, :fabric_enabled => flags[:fabric_enabled], - :flipper_configuration => FlipperConfiguration.disabled, + :flipper_configuration => FlipperConfiguration.enabled(["Debug"], { 'Flipper' => '0.159.0' }), # An absolute path to your application root. :app_path => "#{Pod::Config.instance.installation_root}/.." ) diff --git a/ios/Podfile.lock b/ios/Podfile.lock index ca759e9e..e16f5cfe 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -1,5 +1,6 @@ PODS: - boost (1.76.0) + - CocoaAsyncSocket (7.6.5) - DoubleConversion (1.1.6) - EXApplication (5.0.1): - ExpoModulesCore @@ -52,6 +53,66 @@ PODS: - React-Core (= 0.70.6) - React-jsi (= 0.70.6) - ReactCommon/turbomodule/core (= 0.70.6) + - Flipper (0.159.0): + - Flipper-Folly (~> 2.6) + - Flipper-Boost-iOSX (1.76.0.1.11) + - Flipper-DoubleConversion (3.2.0.1) + - Flipper-Fmt (7.1.7) + - Flipper-Folly (2.6.10): + - Flipper-Boost-iOSX + - Flipper-DoubleConversion + - Flipper-Fmt (= 7.1.7) + - Flipper-Glog + - libevent (~> 2.1.12) + - OpenSSL-Universal (= 1.1.1100) + - Flipper-Glog (0.5.0.5) + - Flipper-PeerTalk (0.0.4) + - Flipper-RSocket (1.4.3): + - Flipper-Folly (~> 2.6) + - FlipperKit (0.159.0): + - FlipperKit/Core (= 0.159.0) + - FlipperKit/Core (0.159.0): + - Flipper (~> 0.159.0) + - FlipperKit/CppBridge + - FlipperKit/FBCxxFollyDynamicConvert + - FlipperKit/FBDefines + - FlipperKit/FKPortForwarding + - SocketRocket (~> 0.6.0) + - FlipperKit/CppBridge (0.159.0): + - Flipper (~> 0.159.0) + - FlipperKit/FBCxxFollyDynamicConvert (0.159.0): + - Flipper-Folly (~> 2.6) + - FlipperKit/FBDefines (0.159.0) + - FlipperKit/FKPortForwarding (0.159.0): + - CocoaAsyncSocket (~> 7.6) + - Flipper-PeerTalk (~> 0.0.4) + - FlipperKit/FlipperKitHighlightOverlay (0.159.0) + - FlipperKit/FlipperKitLayoutHelpers (0.159.0): + - FlipperKit/Core + - FlipperKit/FlipperKitHighlightOverlay + - FlipperKit/FlipperKitLayoutTextSearchable + - FlipperKit/FlipperKitLayoutIOSDescriptors (0.159.0): + - FlipperKit/Core + - FlipperKit/FlipperKitHighlightOverlay + - FlipperKit/FlipperKitLayoutHelpers + - YogaKit (~> 1.18) + - FlipperKit/FlipperKitLayoutPlugin (0.159.0): + - FlipperKit/Core + - FlipperKit/FlipperKitHighlightOverlay + - FlipperKit/FlipperKitLayoutHelpers + - FlipperKit/FlipperKitLayoutIOSDescriptors + - FlipperKit/FlipperKitLayoutTextSearchable + - YogaKit (~> 1.18) + - FlipperKit/FlipperKitLayoutTextSearchable (0.159.0) + - FlipperKit/FlipperKitNetworkPlugin (0.159.0): + - FlipperKit/Core + - FlipperKit/FlipperKitReactPlugin (0.159.0): + - FlipperKit/Core + - FlipperKit/FlipperKitUserDefaultsPlugin (0.159.0): + - FlipperKit/Core + - FlipperKit/SKIOSNetworkPlugin (0.159.0): + - FlipperKit/Core + - FlipperKit/FlipperKitNetworkPlugin - fmt (6.2.1) - glog (0.3.5) - hermes-engine (0.70.6) @@ -68,6 +129,7 @@ PODS: - MMKV (1.2.14): - MMKVCore (~> 1.2.14) - MMKVCore (1.2.14) + - OpenSSL-Universal (1.1.1100) - RCT-Folly (2021.07.22.00): - boost - DoubleConversion @@ -300,6 +362,8 @@ PODS: - React-Core - react-native-cameraroll (5.2.0): - React-Core + - react-native-flipper (0.176.1): + - React-Core - react-native-image-picker (4.10.3): - React-Core - react-native-ios-context-menu (1.15.1): @@ -446,8 +510,11 @@ PODS: - libwebp (~> 1.0) - SDWebImage/Core (~> 5.13) - Sentry/HybridSDK (7.31.3) + - SocketRocket (0.6.0) - Swime (3.0.6) - Yoga (1.14.0) + - YogaKit (1.18.1): + - Yoga (~> 1.14) DEPENDENCIES: - boost (from `../node_modules/react-native/third-party-podspecs/boost.podspec`) @@ -474,9 +541,31 @@ DEPENDENCIES: - EXVideoThumbnails (from `../node_modules/expo-video-thumbnails/ios`) - FBLazyVector (from `../node_modules/react-native/Libraries/FBLazyVector`) - FBReactNativeSpec (from `../node_modules/react-native/React/FBReactNativeSpec`) + - Flipper (= 0.159.0) + - Flipper-Boost-iOSX (= 1.76.0.1.11) + - Flipper-DoubleConversion (= 3.2.0.1) + - Flipper-Fmt (= 7.1.7) + - Flipper-Folly (= 2.6.10) + - Flipper-Glog (= 0.5.0.5) + - Flipper-PeerTalk (= 0.0.4) + - Flipper-RSocket (= 1.4.3) + - FlipperKit (= 0.159.0) + - FlipperKit/Core (= 0.159.0) + - FlipperKit/CppBridge (= 0.159.0) + - FlipperKit/FBCxxFollyDynamicConvert (= 0.159.0) + - FlipperKit/FBDefines (= 0.159.0) + - FlipperKit/FKPortForwarding (= 0.159.0) + - FlipperKit/FlipperKitHighlightOverlay (= 0.159.0) + - FlipperKit/FlipperKitLayoutPlugin (= 0.159.0) + - FlipperKit/FlipperKitLayoutTextSearchable (= 0.159.0) + - FlipperKit/FlipperKitNetworkPlugin (= 0.159.0) + - FlipperKit/FlipperKitReactPlugin (= 0.159.0) + - FlipperKit/FlipperKitUserDefaultsPlugin (= 0.159.0) + - FlipperKit/SKIOSNetworkPlugin (= 0.159.0) - glog (from `../node_modules/react-native/third-party-podspecs/glog.podspec`) - hermes-engine (from `../node_modules/react-native/sdks/hermes/hermes-engine.podspec`) - libevent (~> 2.1.12) + - OpenSSL-Universal (= 1.1.1100) - RCT-Folly (from `../node_modules/react-native/third-party-podspecs/RCT-Folly.podspec`) - RCTRequired (from `../node_modules/react-native/Libraries/RCTRequired`) - RCTTypeSafety (from `../node_modules/react-native/Libraries/TypeSafety`) @@ -485,6 +574,7 @@ DEPENDENCIES: - React-callinvoker (from `../node_modules/react-native/ReactCommon/callinvoker`) - React-Codegen (from `build/generated/ios`) - React-Core (from `../node_modules/react-native/`) + - React-Core/DevSupport (from `../node_modules/react-native/`) - React-Core/RCTWebSocket (from `../node_modules/react-native/`) - React-CoreModules (from `../node_modules/react-native/React/CoreModules`) - React-cxxreact (from `../node_modules/react-native/ReactCommon/cxxreact`) @@ -496,6 +586,7 @@ DEPENDENCIES: - "react-native-blur (from `../node_modules/@react-native-community/blur`)" - react-native-blurhash (from `../node_modules/react-native-blurhash`) - "react-native-cameraroll (from `../node_modules/@react-native-camera-roll/camera-roll`)" + - react-native-flipper (from `../node_modules/react-native-flipper`) - react-native-image-picker (from `../node_modules/react-native-image-picker`) - react-native-ios-context-menu (from `../node_modules/react-native-ios-context-menu`) - react-native-language-detection (from `../node_modules/react-native-language-detection`) @@ -531,15 +622,28 @@ DEPENDENCIES: SPEC REPOS: trunk: + - CocoaAsyncSocket + - Flipper + - Flipper-Boost-iOSX + - Flipper-DoubleConversion + - Flipper-Fmt + - Flipper-Folly + - Flipper-Glog + - Flipper-PeerTalk + - Flipper-RSocket + - FlipperKit - fmt - libevent - libwebp - MMKV - MMKVCore + - OpenSSL-Universal - SDWebImage - SDWebImageWebPCoder - Sentry + - SocketRocket - Swime + - YogaKit EXTERNAL SOURCES: boost: @@ -630,6 +734,8 @@ EXTERNAL SOURCES: :path: "../node_modules/react-native-blurhash" react-native-cameraroll: :path: "../node_modules/@react-native-camera-roll/camera-roll" + react-native-flipper: + :path: "../node_modules/react-native-flipper" react-native-image-picker: :path: "../node_modules/react-native-image-picker" react-native-ios-context-menu: @@ -697,6 +803,7 @@ EXTERNAL SOURCES: SPEC CHECKSUMS: boost: a7c83b31436843459a1961bfd74b96033dc77234 + CocoaAsyncSocket: 065fd1e645c7abab64f7a6a2007a48038fdc6a99 DoubleConversion: 5189b271737e1565bdce30deb4a08d647e3f5f54 EXApplication: 034b1c40a8e9fe1bff76a1e511ee90dff64ad834 EXAV: 9a45d37772c5329294c054a041dcc39931fc5032 @@ -720,6 +827,15 @@ SPEC CHECKSUMS: EXVideoThumbnails: 8b3e48f3716679dd0cbf949217a31eab5c555799 FBLazyVector: 48289402952f4f7a4e235de70a9a590aa0b79ef4 FBReactNativeSpec: dd1186fd05255e3457baa2f4ca65e94c2cd1e3ac + Flipper: dbc210f7008265335b812b2a5a1122b0300e5b64 + Flipper-Boost-iOSX: fd1e2b8cbef7e662a122412d7ac5f5bea715403c + Flipper-DoubleConversion: 2dc99b02f658daf147069aad9dbd29d8feb06d30 + Flipper-Fmt: 60cbdd92fc254826e61d669a5d87ef7015396a9b + Flipper-Folly: 584845625005ff068a6ebf41f857f468decd26b3 + Flipper-Glog: 70c50ce58ddaf67dc35180db05f191692570f446 + Flipper-PeerTalk: 116d8f857dc6ef55c7a5a75ea3ceaafe878aadc9 + Flipper-RSocket: d9d9ade67cbecf6ac10730304bf5607266dd2541 + FlipperKit: 57a0368f6a0416609fafe827f6a957ec3eff7cdc fmt: ff9d55029c625d3757ed641535fd4a75fedc7ce9 glog: 04b94705f318337d7ead9e6d17c019bd9b1f6b1b hermes-engine: 2af7b7a59128f250adfd86f15aa1d5a2ecd39995 @@ -727,6 +843,7 @@ SPEC CHECKSUMS: libwebp: f62cb61d0a484ba548448a4bd52aabf150ff6eef MMKV: 9c4663aa7ca255d478ff10f2f5cb7d17c1651ccd MMKVCore: 89f5c8a66bba2dcd551779dea4d412eeec8ff5bb + OpenSSL-Universal: ebc357f1e6bc71fa463ccb2fe676756aff50e88c RCT-Folly: 0080d0a6ebf2577475bda044aa59e2ca1f909cda RCTRequired: e1866f61af7049eb3d8e08e8b133abd38bc1ca7a RCTTypeSafety: 27c2ac1b00609a432ced1ae701247593f07f901e @@ -745,6 +862,7 @@ SPEC CHECKSUMS: react-native-blur: 50c9feabacbc5f49b61337ebc32192c6be7ec3c3 react-native-blurhash: add4df9a937b4e021a24bc67a0714f13e0bd40b7 react-native-cameraroll: 0ff04cc4e0ff5f19a94ff4313e5c8bc4503cd86d + react-native-flipper: 7e4b1c3fe1a2eecbe7304e5ff6b89231b3ec61dc react-native-image-picker: 60f4246eb5bb7187fc15638a8c1f13abd3820695 react-native-ios-context-menu: b170594b4448c0cd10c79e13432216bac99de1ac react-native-language-detection: f414937fa715108ab50a6269a3de0bcb95e4ceb0 @@ -779,9 +897,11 @@ SPEC CHECKSUMS: SDWebImage: b9a731e1d6307f44ca703b3976d18c24ca561e84 SDWebImageWebPCoder: 18503de6621dd2c420d680e33d46bf8e1d5169b0 Sentry: 08884c523575ec0f6690d94ed3ccb0246a1600bf + SocketRocket: fccef3f9c5cedea1353a9ef6ada904fde10d6608 Swime: d7b2c277503b6cea317774aedc2dce05613f8b0b Yoga: 99caf8d5ab45e9d637ee6e0174ec16fbbb01bcfc + YogaKit: f782866e155069a2cca2517aafea43200b01fd5a -PODFILE CHECKSUM: 05bf71d31ba782dfda5a6b47d38e98a6f6bc079a +PODFILE CHECKSUM: acb35c48d65adb321b72c9eb6ca2fb964ed29a55 COCOAPODS: 1.11.3 diff --git a/ios/tooot.xcodeproj/project.pbxproj b/ios/tooot.xcodeproj/project.pbxproj index 908f700c..a4925e4c 100644 --- a/ios/tooot.xcodeproj/project.pbxproj +++ b/ios/tooot.xcodeproj/project.pbxproj @@ -382,10 +382,16 @@ ); inputPaths = ( "${PODS_ROOT}/Target Support Files/Pods-tooot/Pods-tooot-frameworks.sh", + "${PODS_XCFRAMEWORKS_BUILD_DIR}/Flipper-DoubleConversion/double-conversion.framework/double-conversion", + "${PODS_XCFRAMEWORKS_BUILD_DIR}/Flipper-Glog/glog.framework/glog", + "${PODS_XCFRAMEWORKS_BUILD_DIR}/OpenSSL-Universal/OpenSSL.framework/OpenSSL", "${PODS_XCFRAMEWORKS_BUILD_DIR}/hermes-engine/hermes.framework/hermes", ); name = "[CP] Embed Pods Frameworks"; outputPaths = ( + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/double-conversion.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/glog.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/OpenSSL.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/hermes.framework", ); runOnlyForDeploymentPostprocessing = 0; diff --git a/package.json b/package.json index 7a10ad07..cbbae056 100644 --- a/package.json +++ b/package.json @@ -110,6 +110,8 @@ "chalk": "^4.1.2", "dotenv": "^16.0.3", "react-native-clean-project": "^4.0.1", + "react-native-flipper": "^0.176.1", + "react-query-native-devtools": "^4.0.0", "typescript": "^4.9.4" }, "packageManager": "yarn@3.3.1", diff --git a/src/@types/mastodon.d.ts b/src/@types/mastodon.d.ts index ca936344..d7a3b1c4 100644 --- a/src/@types/mastodon.d.ts +++ b/src/@types/mastodon.d.ts @@ -31,6 +31,9 @@ declare namespace Mastodon { source?: Source suspended?: boolean role?: Role + + // Internal + _remote?: boolean } type Announcement = { @@ -389,6 +392,9 @@ declare namespace Mastodon { username: string acct: string url: string + + // Internal + _remote?: boolean } type Notification = diff --git a/src/components/Account.tsx b/src/components/Account.tsx index 7153973a..bd43dff1 100644 --- a/src/components/Account.tsx +++ b/src/components/Account.tsx @@ -11,7 +11,7 @@ import Icon from './Icon' import CustomText from './Text' export interface Props { - account: Partial & Pick + account: Partial & Pick props?: PressableProps } diff --git a/src/components/Parse/HTML.tsx b/src/components/Parse/HTML.tsx index 18bdd497..246f839a 100644 --- a/src/components/Parse/HTML.tsx +++ b/src/components/Parse/HTML.tsx @@ -168,10 +168,7 @@ const ParseHTML: React.FC = ({ matchedMention && !disableDetails && !sameAccount && - navigation.push('Tab-Shared-Account', { - account: matchedMention, - isRemote: status?._remote - }) + navigation.push('Tab-Shared-Account', { account: matchedMention }) } children={node.children.map(unwrapNode).join('')} /> diff --git a/src/components/Timeline/Default.tsx b/src/components/Timeline/Default.tsx index 48725b8a..89d60d9d 100644 --- a/src/components/Timeline/Default.tsx +++ b/src/components/Timeline/Default.tsx @@ -37,7 +37,6 @@ export interface Props { disableDetails?: boolean disableOnPress?: boolean isConversation?: boolean - isRemote?: boolean } // When the poll is long @@ -48,8 +47,7 @@ const TimelineDefault: React.FC = ({ highlighted = false, disableDetails = false, disableOnPress = false, - isConversation = false, - isRemote = false + isConversation = false }) => { const status = item.reblog ? item.reblog : item const rawContent = useRef([]) @@ -177,7 +175,7 @@ const TimelineDefault: React.FC = ({ disableDetails, disableOnPress, isConversation, - isRemote + isRemote: item._remote }} > {disableOnPress ? ( diff --git a/src/components/Timeline/Shared/Actioned.tsx b/src/components/Timeline/Shared/Actioned.tsx index d6446a31..bd2cbcec 100644 --- a/src/components/Timeline/Shared/Actioned.tsx +++ b/src/components/Timeline/Shared/Actioned.tsx @@ -38,7 +38,7 @@ const TimelineActioned: React.FC = ({ action, isNotification, ...rest }) ) const onPress = () => - navigation.push('Tab-Shared-Account', { account, isRemote: status?._remote }) + navigation.push('Tab-Shared-Account', { account }) const children = () => { switch (action) { diff --git a/src/components/Timeline/Shared/Actions.tsx b/src/components/Timeline/Shared/Actions.tsx index 7df190f0..73314cc4 100644 --- a/src/components/Timeline/Shared/Actions.tsx +++ b/src/components/Timeline/Shared/Actions.tsx @@ -114,7 +114,8 @@ const TimelineActions: React.FC = () => { status, payload: { type: 'reblogged', - visibility: 'public' + visibility: 'public', + to: true } }) break @@ -126,7 +127,8 @@ const TimelineActions: React.FC = () => { status, payload: { type: 'reblogged', - visibility: 'unlisted' + visibility: 'unlisted', + to: true } }) break @@ -141,7 +143,8 @@ const TimelineActions: React.FC = () => { status, payload: { type: 'reblogged', - visibility: 'public' + visibility: 'public', + to: false } }) } @@ -153,7 +156,8 @@ const TimelineActions: React.FC = () => { rootQueryKey, status, payload: { - type: 'favourited' + type: 'favourited', + to: !status.favourited } }) } @@ -164,7 +168,8 @@ const TimelineActions: React.FC = () => { rootQueryKey, status, payload: { - type: 'bookmarked' + type: 'bookmarked', + to: !status.bookmarked } }) } diff --git a/src/components/Timeline/Shared/Avatar.tsx b/src/components/Timeline/Shared/Avatar.tsx index 7fed7071..b1f6a57c 100644 --- a/src/components/Timeline/Shared/Avatar.tsx +++ b/src/components/Timeline/Shared/Avatar.tsx @@ -32,7 +32,7 @@ const TimelineAvatar: React.FC = ({ account }) => { })} onPress={() => !disableOnPress && - navigation.push('Tab-Shared-Account', { account: actualAccount, isRemote: status?._remote }) + navigation.push('Tab-Shared-Account', { account: actualAccount }) } uri={{ original: actualAccount.avatar, static: actualAccount.avatar_static }} dimension={ diff --git a/src/components/Timeline/Shared/Card.tsx b/src/components/Timeline/Shared/Card.tsx index 8155e109..d9bf2600 100644 --- a/src/components/Timeline/Shared/Card.tsx +++ b/src/components/Timeline/Shared/Card.tsx @@ -86,7 +86,8 @@ const TimelineCard: React.FC = () => { }, []) const accountQuery = useAccountQuery({ - id: isAccount?.style === 'default' ? isAccount.id : '', + account: + isAccount?.style === 'default' ? { id: isAccount.id, url: status.card.url } : undefined, options: { enabled: false } }) useEffect(() => { diff --git a/src/components/contextMenu/account.ts b/src/components/contextMenu/account.ts index ed017d6d..6e859872 100644 --- a/src/components/contextMenu/account.ts +++ b/src/components/contextMenu/account.ts @@ -30,7 +30,7 @@ const menuAccount = ({ }: { type: 'status' | 'account' // Where the action is coming from openChange: boolean - account?: Partial & Pick + account?: Partial & Pick status?: Mastodon.Status queryKey?: QueryKeyTimeline rootQueryKey?: QueryKeyTimeline @@ -47,10 +47,7 @@ const menuAccount = ({ setEnabled(true) } }, [openChange, enabled]) - const { data: fetchedAccount } = useAccountQuery({ - remoteUrl: account?.url, - options: { enabled: !!status?._remote && enabled } - }) + const { data: fetchedAccount } = useAccountQuery({ account, options: { enabled } }) const actualAccount = status?._remote ? fetchedAccount : account const { data, isFetched } = useRelationshipQuery({ id: actualAccount?.id, diff --git a/src/components/contextMenu/status.ts b/src/components/contextMenu/status.ts index 30cd24c0..caed4a62 100644 --- a/src/components/contextMenu/status.ts +++ b/src/components/contextMenu/status.ts @@ -197,7 +197,8 @@ const menuStatus = ({ rootQueryKey, status, payload: { - type: 'muted' + type: 'muted', + to: !status.muted } }), disabled: false, @@ -221,7 +222,8 @@ const menuStatus = ({ rootQueryKey, status, payload: { - type: 'pinned' + type: 'pinned', + to: !status.pinned } }), disabled: status.visibility !== 'public' && status.visibility !== 'unlisted', diff --git a/src/screens/Tabs/Shared/Account/index.tsx b/src/screens/Tabs/Shared/Account/index.tsx index 8d27ee31..7f0c74b2 100644 --- a/src/screens/Tabs/Shared/Account/index.tsx +++ b/src/screens/Tabs/Shared/Account/index.tsx @@ -24,15 +24,30 @@ import AccountNav from './Nav' const TabSharedAccount: React.FC> = ({ navigation, route: { - params: { account, isRemote } + params: { account } } }) => { const { t } = useTranslation('screenTabs') const { colors, mode } = useTheme() const { data, dataUpdatedAt } = useAccountQuery({ - id: account.id, - ...(isRemote && { remoteUrl: account.url }) + account, + options: { + onSuccess: a => { + if (account._remote) { + setQueryKey([ + queryKey[0], + { + ...queryKey[1], + page: 'Account', + id: a.id, + exclude_reblogs: true, + only_media: false + } + ]) + } + } + } }) const mShare = menuShare({ type: 'account', url: data?.url }) @@ -87,7 +102,12 @@ const TabSharedAccount: React.FC const queryClient = useQueryClient() const [queryKey, setQueryKey] = useState([ 'Timeline', - { page: 'Account', id: data?.id, exclude_reblogs: true, only_media: false } + { + page: 'Account', + id: account._remote ? data?.id : account.id, + exclude_reblogs: true, + only_media: false + } ]) const page = queryKey[1] @@ -174,7 +194,7 @@ const TabSharedAccount: React.FC , onScroll: ({ nativeEvent }) => (scrollY.value = nativeEvent.contentOffset.y), diff --git a/src/screens/Tabs/Shared/Toot.tsx b/src/screens/Tabs/Shared/Toot.tsx index d95bb8a1..29887ac5 100644 --- a/src/screens/Tabs/Shared/Toot.tsx +++ b/src/screens/Tabs/Shared/Toot.tsx @@ -9,6 +9,7 @@ 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 { getAccountStorage } from '@utils/storage/actions' import { StyleConstants } from '@utils/styles/constants' import { useTheme } from '@utils/styles/ThemeManager' import React, { useEffect, useRef, useState } from 'react' @@ -65,8 +66,8 @@ const TabSharedToot: React.FC> = ({ const flRef = useRef(null) const scrolled = useRef(false) - const finalData = useRef([ - { ...toot, _level: 0, _remote: toot._remote } + const finalData = useRef<(Mastodon.Status & { key?: string })[]>([ + { ...toot, _level: 0, key: 'cached' } ]) const highlightIndex = useRef(0) const queryKey: { local: QueryKeyTimeline; remote: QueryKeyTimeline } = { @@ -86,7 +87,7 @@ const TabSharedToot: React.FC> = ({ const statuses: (Mastodon.Status & { _level?: number })[] = [ ...context.body.ancestors, - toot, + { ...toot }, ...context.body.descendants ] @@ -115,8 +116,7 @@ const TabSharedToot: React.FC> = ({ return } - if (finalData.current.length < data.pages[0].body.length) { - // if the remote has been loaded first + if (finalData.current[0].key === 'cached') { finalData.current = data.pages[0].body if (!scrolled.current) { @@ -178,7 +178,7 @@ const TabSharedToot: React.FC> = ({ const statuses: (Mastodon.Status & { _level?: number })[] = [ ...context.ancestors, - toot, + { ...toot }, ...context.descendants ] @@ -198,7 +198,9 @@ const TabSharedToot: React.FC> = ({ return { pages: [{ body: statuses }] } }, { - enabled: toot.account.acct !== toot.account.username, // When on the same instance, these two values are the same + enabled: + ['public', 'unlisted'].includes(toot.visibility) && + getHost(toot.uri) !== getAccountStorage.string('auth.domain'), staleTime: 0, refetchOnMount: true, onSuccess: data => { @@ -211,12 +213,25 @@ const TabSharedToot: React.FC> = ({ finalData.current = data.pages[0].body.map(remote => { const localMatch = finalData.current.find(local => local.uri === remote.uri) if (localMatch) { + delete localMatch.key return localMatch } else { remote._remote = true + + remote.account._remote = true + remote.mentions = remote.mentions.map(mention => ({ ...mention, _remote: true })) + if (remote.reblog) { + remote.reblog.account._remote = true + remote.reblog.mentions = remote.mentions.map(mention => ({ + ...mention, + _remote: true + })) + } + return remote } }) + setHasRemoteContent(true) } @@ -274,9 +289,8 @@ const TabSharedToot: React.FC> = ({ item={item} queryKey={item._remote ? queryKey.remote : queryKey.local} rootQueryKey={rootQueryKey} - highlighted={toot.id === item.id} - isConversation={toot.id !== item.id} - isRemote={item._remote} + highlighted={toot.id === item.id || item.id === 'cached'} + isConversation={toot.id !== item.id && item.id !== 'cached'} /> {curr > 1 || next > 1 ? [...new Array(curr)].map((_, i) => { diff --git a/src/utils/navigation/navigators.ts b/src/utils/navigation/navigators.ts index 0c5cd275..748a2bb2 100644 --- a/src/utils/navigation/navigators.ts +++ b/src/utils/navigation/navigators.ts @@ -84,8 +84,7 @@ export type ScreenTabsScreenProps = Bo export type TabSharedStackParamList = { 'Tab-Shared-Account': { - account: Partial & Pick - isRemote?: boolean + account: Pick } 'Tab-Shared-Account-In-Lists': { account: Pick @@ -99,7 +98,7 @@ export type TabSharedStackParamList = { detectedLanguage: string } 'Tab-Shared-Report': { - account: Partial & Pick + account: Pick status?: Pick } 'Tab-Shared-Search': undefined diff --git a/src/utils/queryHooks/account.ts b/src/utils/queryHooks/account.ts index 88ddf89d..fc859649 100644 --- a/src/utils/queryHooks/account.ts +++ b/src/utils/queryHooks/account.ts @@ -3,21 +3,24 @@ import apiInstance from '@utils/api/instance' import { AxiosError } from 'axios' import { SearchResult } from './search' -export type QueryKeyAccount = ['Account', { id?: Mastodon.Account['id']; remoteUrl?: string }] +export type QueryKeyAccount = [ + 'Account', + Pick | undefined +] const accountQueryFunction = async ({ queryKey }: QueryFunctionContext) => { - const { id, remoteUrl } = queryKey[1] - if (!id && !remoteUrl) return Promise.reject() + const key = queryKey[1] + if (!key) return Promise.reject() - let matchedId = id + let matchedId = key.id - if (remoteUrl) { + if (key._remote) { await apiInstance({ version: 'v2', method: 'get', url: 'search', params: { - q: remoteUrl, + q: key.url, type: 'accounts', limit: 1, resolve: true @@ -25,7 +28,7 @@ const accountQueryFunction = async ({ queryKey }: QueryFunctionContext { const account = res.body.accounts[0] - if (account.url !== remoteUrl) { + if (account.url !== key.url) { return Promise.reject() } else { matchedId = account.id @@ -44,11 +47,23 @@ const accountQueryFunction = async ({ queryKey }: QueryFunctionContext }) => { - const queryKey: QueryKeyAccount = ['Account', { ...queryKeyParams }] - return useQuery(queryKey, accountQueryFunction, { ...options }) + const queryKey: QueryKeyAccount = [ + 'Account', + queryKeyParams.account + ? { + id: queryKeyParams.account.id, + url: queryKeyParams.account.url, + _remote: queryKeyParams.account._remote + } + : undefined + ] + return useQuery(queryKey, accountQueryFunction, { + ...options, + enabled: (queryKeyParams.account?._remote ? !!queryKeyParams.account : true) && options?.enabled + }) } /* ----- */ diff --git a/src/utils/queryHooks/index.ts b/src/utils/queryHooks/index.ts index cba87dbe..f75117ac 100644 --- a/src/utils/queryHooks/index.ts +++ b/src/utils/queryHooks/index.ts @@ -18,4 +18,9 @@ const queryClient = new QueryClient({ } }) +// @ts-ignore +import('react-query-native-devtools').then(({ addPlugin }) => { + addPlugin({ queryClient }) +}) + export default queryClient diff --git a/src/utils/queryHooks/search.ts b/src/utils/queryHooks/search.ts index d35aa0ae..704ae695 100644 --- a/src/utils/queryHooks/search.ts +++ b/src/utils/queryHooks/search.ts @@ -20,7 +20,7 @@ export type SearchResult = { const queryFunction = async ({ queryKey }: QueryFunctionContext) => { const { type, term, limit = 20 } = queryKey[1] if (!term?.length) { - return Promise.reject() + return Promise.reject('Empty search term') } const res = await apiInstance({ version: 'v2', @@ -59,6 +59,6 @@ export const searchFetchToot = (uri: Mastodon.Status['uri']): Promise res.body.statuses[0]) - .catch(() => {}) + .catch(err => console.warn(err)) export { useSearchQuery } diff --git a/src/utils/queryHooks/tags.ts b/src/utils/queryHooks/tags.ts index a4c09651..0058fc8f 100644 --- a/src/utils/queryHooks/tags.ts +++ b/src/utils/queryHooks/tags.ts @@ -37,11 +37,11 @@ const useFollowedTagsQuery = ( }) }, { - enabled: canFollowTags, staleTime: Infinity, cacheTime: Infinity, ...params?.options, ...infinitePageParams, + enabled: canFollowTags && params?.options?.enabled, onSuccess: data => { setAccountStorage([ { diff --git a/src/utils/queryHooks/timeline.ts b/src/utils/queryHooks/timeline.ts index 28bc352f..a294cc3b 100644 --- a/src/utils/queryHooks/timeline.ts +++ b/src/utils/queryHooks/timeline.ts @@ -131,7 +131,7 @@ const queryFunction = async ({ queryKey, pageParam }: QueryFunctionContext { if (fetched) { tootId = fetched.id } else { - return Promise.reject() + return Promise.reject('Fetching for remote toot failed') } } const body = new FormData() @@ -349,7 +355,7 @@ const mutationFunction = async (params: MutationVarsTimeline) => { } return apiInstance({ method: 'post', - url: `statuses/${tootId}/${params.status[params.payload.type] ? '' : 'un'}${ + url: `statuses/${tootId}/${params.payload.to ? '' : 'un'}${ MapPropertyToUrl[params.payload.type] }`, ...(params.payload.type === 'reblogged' && { body }) diff --git a/src/utils/queryHooks/timeline/updateStatusProperty.ts b/src/utils/queryHooks/timeline/updateStatusProperty.ts index a942360a..86fc60e4 100644 --- a/src/utils/queryHooks/timeline/updateStatusProperty.ts +++ b/src/utils/queryHooks/timeline/updateStatusProperty.ts @@ -9,10 +9,11 @@ const updateStatusProperty = ({ payload, poll }: MutationVarsTimelineUpdateStatusProperty & { poll?: Mastodon.Poll }) => { - for (const key of [queryKey, rootQueryKey]) { + for (const key of [queryKey]) { if (!key) continue queryClient.setQueryData | undefined>(key, old => { + console.log('key', key) if (old) { let foundToot: Mastodon.Status | undefined = undefined old.pages = old.pages.map(page => { @@ -25,7 +26,6 @@ const updateStatusProperty = ({ ? 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?.reblog ? no.status.reblog.id === status.id : no.status?.id === status.id @@ -41,6 +41,8 @@ const updateStatusProperty = ({ }) if (foundToot) { + const toot = foundToot as Mastodon.Status + console.log('updating', toot.id) enum MapPropertyToCount { favourited = 'favourites_count', reblogged = 'reblogs_count' @@ -48,18 +50,19 @@ const updateStatusProperty = ({ switch (payload.type) { case 'poll': - status.poll = poll + toot.poll = poll break default: - status[payload.type] = - typeof status[payload.type] === 'boolean' ? !status[payload.type] : true + console.log('11', toot[payload.type]) + toot[payload.type] = payload.to + console.log('22', toot[payload.type]) switch (payload.type) { case 'favourited': case 'reblogged': - if (typeof status[payload.type] === 'boolean' && status[payload.type]) { - status[MapPropertyToCount[payload.type]]-- + if (payload.to) { + toot[MapPropertyToCount[payload.type]]++ } else { - status[MapPropertyToCount[payload.type]]++ + toot[MapPropertyToCount[payload.type]]-- } break } diff --git a/src/utils/storage/actions.ts b/src/utils/storage/actions.ts index a1191c59..ef7048bc 100644 --- a/src/utils/storage/actions.ts +++ b/src/utils/storage/actions.ts @@ -212,7 +212,7 @@ export const generateAccountKey = ({ export const setAccount = async (account: string) => { storage.account = new MMKV({ id: account }) setGlobalStorage('account.active', account) - await queryClient.resetQueries() + queryClient.clear() } export const removeAccount = async (account: string) => { diff --git a/yarn.lock b/yarn.lock index 3489d785..12534d10 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5987,6 +5987,13 @@ __metadata: languageName: node linkType: hard +"flatted@npm:^3.2.4": + version: 3.2.7 + resolution: "flatted@npm:3.2.7" + checksum: 427633049d55bdb80201c68f7eb1cbd533e03eac541f97d3aecab8c5526f12a20ccecaeede08b57503e772c769e7f8680b37e8d482d1e5f8d7e2194687f9ea35 + languageName: node + linkType: hard + "flow-parser@npm:0.*": version: 0.196.3 resolution: "flow-parser@npm:0.196.3" @@ -9509,6 +9516,16 @@ __metadata: languageName: node linkType: hard +"react-native-flipper@npm:^0.176.1": + version: 0.176.1 + resolution: "react-native-flipper@npm:0.176.1" + peerDependencies: + react: ^16.8.0 || ^17.0.0 || ^18.0.0 + react-native: ">0.62.0" + checksum: f8ba597190baaed791a73d474ab8c2410048025f6bf8b1e49b5b64b71f08453d50fa118113a4c37e5fd8bb1c7700f8afe84671afeab6ad912a5f0c4da41a35be + languageName: node + linkType: hard + "react-native-gesture-handler@npm:~2.8.0": version: 2.8.0 resolution: "react-native-gesture-handler@npm:2.8.0" @@ -9742,6 +9759,18 @@ __metadata: languageName: node linkType: hard +"react-query-native-devtools@npm:^4.0.0": + version: 4.0.0 + resolution: "react-query-native-devtools@npm:4.0.0" + dependencies: + flatted: ^3.2.4 + peerDependencies: + react-native-flipper: ^0.127.0 + react-query: ^3.34.6 + checksum: 7da16b14a59ac19805c315a25ab2c090cc277afe22aee412a743eda5296f282a91c0b35a269d015fbf27781e9c8b65c1a642a6fd5fc258a9318821a27c6da652 + languageName: node + linkType: hard + "react-redux@npm:^8.0.5": version: 8.0.5 resolution: "react-redux@npm:8.0.5" @@ -11272,6 +11301,7 @@ __metadata: react-native-fast-image: ^8.6.3 react-native-feather: ^1.1.2 react-native-flash-message: ^0.3.1 + react-native-flipper: ^0.176.1 react-native-gesture-handler: ~2.8.0 react-native-image-picker: ^4.10.3 react-native-ios-context-menu: ^1.15.1 @@ -11286,6 +11316,7 @@ __metadata: react-native-svg: ^13.6.0 react-native-swipe-list-view: ^3.2.9 react-native-tab-view: ^3.3.4 + react-query-native-devtools: ^4.0.0 react-redux: ^8.0.5 rn-placeholder: ^3.0.3 typescript: ^4.9.4