diff --git a/lib/reducers/community-reducer.js b/lib/reducers/community-reducer.js --- a/lib/reducers/community-reducer.js +++ b/lib/reducers/community-reducer.js @@ -6,12 +6,14 @@ fetchCommunityInfosActionTypes, createOrUpdateFarcasterChannelTagActionTypes, deleteFarcasterChannelTagActionTypes, + fetchAllCommunityInfosWithNamesActionTypes, } from '../actions/community-actions.js'; import { communityStoreOpsHandlers, type CommunityStoreOperation, type ReplaceCommunityOperation, } from '../ops/community-store-ops.js'; +import { viewerIsMember } from '../shared/thread-utils.js'; import type { CommunityStore } from '../types/community-types.js'; import type { BaseAction } from '../types/redux-types'; @@ -37,6 +39,27 @@ }; }); + return { + communityStore: processStoreOps(state, replaceOperations), + communityStoreOperations: replaceOperations, + }; + } else if ( + action.type === fetchAllCommunityInfosWithNamesActionTypes.success + ) { + const replaceOperations = action.payload.allCommunityInfosWithNames + .filter(community => viewerIsMember(community.threadInfo)) + .map(community => { + const { id, threadInfo, communityName, ...communityInfo } = community; + + return { + type: 'replace_community', + payload: { + id, + communityInfo, + }, + }; + }); + return { communityStore: processStoreOps(state, replaceOperations), communityStoreOperations: replaceOperations, diff --git a/native/navigation/community-drawer-content.react.js b/native/navigation/community-drawer-content.react.js --- a/native/navigation/community-drawer-content.react.js +++ b/native/navigation/community-drawer-content.react.js @@ -7,15 +7,20 @@ import { SafeAreaView } from 'react-native-safe-area-context'; import { - fetchCommunityInfosActionTypes, - useFetchCommunityInfos, + fetchAllCommunityInfosWithNamesActionTypes, + fetchAllCommunityInfosWithNames, } from 'lib/actions/community-actions.js'; import { fetchPrimaryInviteLinkActionTypes, useFetchPrimaryInviteLinks, } from 'lib/actions/link-actions.js'; import { useChildThreadInfosMap } from 'lib/hooks/thread-hooks.js'; +import { useLegacyAshoatKeyserverCall } from 'lib/keyserver-conn/legacy-keyserver-call.js'; import { communityThreadSelector } from 'lib/selectors/thread-selectors.js'; +import type { + ClientCommunityInfoWithCommunityName, + ClientFetchAllCommunityInfosWithNamesResponse, +} from 'lib/types/community-types.js'; import { threadTypeIsCommunityRoot } from 'lib/types/thread-types-enum.js'; import { createRecursiveDrawerItemsData, @@ -25,11 +30,15 @@ import { useDispatchActionPromise } from 'lib/utils/redux-promise-utils.js'; import CommunityDrawerItem from './community-drawer-item.react.js'; -import { CommunityCreationRouteName } from './route-names.js'; +import { + CommunityCreationRouteName, + CommunityJoinerModalRouteName, +} from './route-names.js'; import { useNavigateToThread } from '../chat/message-list-types.js'; import SWMansionIcon from '../components/swmansion-icon.react.js'; import { useSelector } from '../redux/redux-utils.js'; import { useStyles } from '../themes/colors.js'; +import Alert from '../utils/alert.js'; import { flattenDrawerItemsData, filterOutThreadAndDescendantIDs, @@ -49,10 +58,16 @@ const styles = useStyles(unboundStyles); const callFetchPrimaryLinks = useFetchPrimaryInviteLinks(); - const fetchCommunityInfos = useFetchCommunityInfos(); const dispatchActionPromise = useDispatchActionPromise(); const drawerStatus = useDrawerStatus(); + const getAllCommunityInfosWithNames = useLegacyAshoatKeyserverCall( + fetchAllCommunityInfosWithNames, + ); + const getAllCommunityInfosWithNamesPromiseRef = + React.useRef>(null); + const [fetchedCommunitiesWithNames, setFetchedCommunitiesWithNames] = + React.useState>(null); React.useEffect(() => { if (drawerStatus !== 'open') { return; @@ -61,15 +76,23 @@ fetchPrimaryInviteLinkActionTypes, callFetchPrimaryLinks(), ); + const getAllCommunityInfosWithNamesPromise = + getAllCommunityInfosWithNames(); + getAllCommunityInfosWithNamesPromiseRef.current = + getAllCommunityInfosWithNamesPromise; void dispatchActionPromise( - fetchCommunityInfosActionTypes, - fetchCommunityInfos(), + fetchAllCommunityInfosWithNamesActionTypes, + getAllCommunityInfosWithNamesPromise, ); + void (async () => { + const response = await getAllCommunityInfosWithNamesPromise; + setFetchedCommunitiesWithNames(response.allCommunityInfosWithNames); + })(); }, [ callFetchPrimaryLinks, dispatchActionPromise, drawerStatus, - fetchCommunityInfos, + getAllCommunityInfosWithNames, ]); const [expanded, setExpanded] = React.useState>(() => { @@ -169,10 +192,40 @@ ); + const onPressExploreCommunities = React.useCallback(async () => { + if (fetchedCommunitiesWithNames) { + navigate<'CommunityJoinerModal'>({ + name: CommunityJoinerModalRouteName, + params: { communities: fetchedCommunitiesWithNames }, + }); + return; + } + if (getAllCommunityInfosWithNamesPromiseRef.current) { + try { + const response = await getAllCommunityInfosWithNamesPromiseRef.current; + navigate<'CommunityJoinerModal'>({ + name: CommunityJoinerModalRouteName, + params: { communities: response.allCommunityInfosWithNames }, + }); + return; + } catch (error) { + // Handle error silently; fallback to showing the alert below + } + } + Alert.alert( + 'Couldn’t load communities', + 'Uhh... try again?', + [{ text: 'OK' }], + { + cancelable: false, + }, + ); + }, [fetchedCommunitiesWithNames, navigate]); + let exploreCommunitiesButton; if (__DEV__) { exploreCommunitiesButton = ( - +