From 48f5cebc80975388f83ba61c3d6c7b620124969d Mon Sep 17 00:00:00 2001 From: Paul Frazee Date: Mon, 4 Dec 2023 17:58:45 -0800 Subject: [PATCH] Update feeds on post created (#2085) --- src/state/events.ts | 8 ++++++ src/state/queries/post-feed.ts | 2 +- src/view/com/composer/Composer.tsx | 45 +++++++++++++++++++++--------- src/view/com/posts/Feed.tsx | 25 +++++++++++++++++ 4 files changed, 66 insertions(+), 14 deletions(-) diff --git a/src/state/events.ts b/src/state/events.ts index 5441aafe..f8586082 100644 --- a/src/state/events.ts +++ b/src/state/events.ts @@ -36,3 +36,11 @@ export function listenSessionDropped(fn: () => void): UnlistenFn { emitter.on('session-dropped', fn) return () => emitter.off('session-dropped', fn) } + +export function emitPostCreated() { + emitter.emit('post-created') +} +export function listenPostCreated(fn: () => void): UnlistenFn { + emitter.on('post-created', fn) + return () => emitter.off('post-created', fn) +} diff --git a/src/state/queries/post-feed.ts b/src/state/queries/post-feed.ts index 7589aa34..36e06cfa 100644 --- a/src/state/queries/post-feed.ts +++ b/src/state/queries/post-feed.ts @@ -248,7 +248,7 @@ export function findPostInQueryData( export function* findAllPostsInQueryData( queryClient: QueryClient, uri: string, -): Generator { +): Generator { const queryDatas = queryClient.getQueriesData< InfiniteData >({ diff --git a/src/view/com/composer/Composer.tsx b/src/view/com/composer/Composer.tsx index 7336f3b9..d8af6d0c 100644 --- a/src/view/com/composer/Composer.tsx +++ b/src/view/com/composer/Composer.tsx @@ -14,7 +14,7 @@ import { import {useSafeAreaInsets} from 'react-native-safe-area-context' import LinearGradient from 'react-native-linear-gradient' import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome' -import {RichText} from '@atproto/api' +import {AppBskyFeedGetPosts, RichText} from '@atproto/api' import {useAnalytics} from 'lib/analytics/analytics' import {useIsKeyboardVisible} from 'lib/hooks/useIsKeyboardVisible' import {ExternalEmbed} from './ExternalEmbed' @@ -59,6 +59,8 @@ import { import {useSession, getAgent} from '#/state/session' import {useProfileQuery} from '#/state/queries/profile' import {useComposerControls} from '#/state/shell/composer' +import {until} from '#/lib/async/until' +import {emitPostCreated} from '#/state/events' type Props = ComposerOpts export const ComposePost = observer(function ComposePost({ @@ -208,17 +210,20 @@ export const ComposePost = observer(function ComposePost({ setIsProcessing(true) + let postUri try { - await apilib.post(getAgent(), { - rawText: richtext.text, - replyTo: replyTo?.uri, - images: gallery.images, - quote, - extLink, - labels, - onStateChange: setProcessingState, - langs: toPostLanguages(langPrefs.postLanguage), - }) + postUri = ( + await apilib.post(getAgent(), { + rawText: richtext.text, + replyTo: replyTo?.uri, + images: gallery.images, + quote, + extLink, + labels, + onStateChange: setProcessingState, + langs: toPostLanguages(langPrefs.postLanguage), + }) + ).uri } catch (e: any) { if (extLink) { setExtLink({ @@ -236,8 +241,10 @@ export const ComposePost = observer(function ComposePost({ }) if (replyTo && replyTo.uri) track('Post:Reply') } - if (!replyTo) { - // TODO onPostCreated + if (postUri && !replyTo) { + whenAppViewReady(postUri).then(() => { + emitPostCreated() + }) } setLangPrefs.savePostLanguageToHistory() onPost?.() @@ -533,3 +540,15 @@ const styles = StyleSheet.create({ borderTopWidth: 1, }, }) + +async function whenAppViewReady(uri: string) { + await until( + 5, // 5 tries + 1e3, // 1s delay between tries + (res: AppBskyFeedGetPosts.Response) => !!res.data.posts[0], + () => + getAgent().getPosts({ + uris: [uri], + }), + ) +} diff --git a/src/view/com/posts/Feed.tsx b/src/view/com/posts/Feed.tsx index ed00561b..5da04e38 100644 --- a/src/view/com/posts/Feed.tsx +++ b/src/view/com/posts/Feed.tsx @@ -8,6 +8,7 @@ import { View, ViewStyle, } from 'react-native' +import {useQueryClient} from '@tanstack/react-query' import {FlatList} from '../util/Views' import {PostFeedLoadingPlaceholder} from '../util/LoadingPlaceholder' import {FeedErrorMessage} from './FeedErrorMessage' @@ -20,6 +21,7 @@ import {useAnimatedScrollHandler} from '#/lib/hooks/useAnimatedScrollHandler_FIX import {useTheme} from 'lib/ThemeContext' import {logger} from '#/logger' import { + RQKEY, FeedDescriptor, FeedParams, usePostFeedQuery, @@ -27,6 +29,8 @@ import { } from '#/state/queries/post-feed' import {useModerationOpts} from '#/state/queries/preferences' import {isWeb} from '#/platform/detection' +import {listenPostCreated} from '#/state/events' +import {useSession} from '#/state/session' const LOADING_ITEM = {_reactKey: '__loading__'} const EMPTY_FEED_ITEM = {_reactKey: '__empty__'} @@ -73,6 +77,8 @@ let Feed = ({ const pal = usePalette('default') const theme = useTheme() const {track} = useAnalytics() + const queryClient = useQueryClient() + const {currentAccount} = useSession() const [isPTRing, setIsPTRing] = React.useState(false) const checkForNewRef = React.useRef<(() => void) | null>(null) @@ -104,6 +110,25 @@ let Feed = ({ } }, [feed, data, isFetching, onHasNew, enabled]) + const myDid = currentAccount?.did || '' + const onPostCreated = React.useCallback(() => { + // NOTE + // only invalidate if there's 1 page + // more than 1 page can trigger some UI freakouts on iOS and android + // -prf + if ( + data?.pages.length === 1 && + (feed === 'following' || + feed === 'home' || + feed === `author|${myDid}|posts_no_replies`) + ) { + queryClient.invalidateQueries({queryKey: RQKEY(feed)}) + } + }, [queryClient, feed, data, myDid]) + React.useEffect(() => { + return listenPostCreated(onPostCreated) + }, [onPostCreated]) + React.useEffect(() => { // we store the interval handler in a ref to avoid needless // reassignments of the interval