Changeset View
Changeset View
Standalone View
Standalone View
native/navigation/community-drawer-content.react.js
// @flow | // @flow | ||||
import { useDrawerStatus } from '@react-navigation/drawer'; | |||||
import { useNavigation } from '@react-navigation/native'; | |||||
import * as React from 'react'; | import * as React from 'react'; | ||||
import { FlatList, Platform } from 'react-native'; | import { FlatList, Platform } from 'react-native'; | ||||
import { SafeAreaView } from 'react-native-safe-area-context'; | import { SafeAreaView } from 'react-native-safe-area-context'; | ||||
import { useSelector } from 'react-redux'; | import { useSelector } from 'react-redux'; | ||||
import { | import { | ||||
fetchPrimaryInviteLinkActionTypes, | |||||
fetchPrimaryInviteLinks, | |||||
} from 'lib/actions/link-actions.js'; | |||||
import { | |||||
childThreadInfos, | childThreadInfos, | ||||
communityThreadSelector, | communityThreadSelector, | ||||
} from 'lib/selectors/thread-selectors.js'; | } from 'lib/selectors/thread-selectors.js'; | ||||
import type { InviteLink } from 'lib/types/link-types'; | |||||
import type { ThreadInfo } from 'lib/types/thread-types'; | |||||
import { | |||||
useDispatchActionPromise, | |||||
useServerCall, | |||||
} from 'lib/utils/action-utils.js'; | |||||
import { | import { | ||||
createRecursiveDrawerItemsData, | createRecursiveDrawerItemsData, | ||||
appendSuffix, | appendSuffix, | ||||
} from 'lib/utils/drawer-utils.react.js'; | } from 'lib/utils/drawer-utils.react.js'; | ||||
import { useResolvedThreadInfos } from 'lib/utils/entity-helpers.js'; | import { useResolvedThreadInfos } from 'lib/utils/entity-helpers.js'; | ||||
import CommunityDrawerItemCommunity from './community-drawer-item-community.react.js'; | import CommunityDrawerItemCommunity from './community-drawer-item-community.react.js'; | ||||
import { ViewInviteLinksModalRouteName } from './route-names.js'; | |||||
import { useNavigateToThread } from '../chat/message-list-types.js'; | import { useNavigateToThread } from '../chat/message-list-types.js'; | ||||
import { useStyles } from '../themes/colors.js'; | import { useStyles } from '../themes/colors.js'; | ||||
const maxDepth = 2; | const maxDepth = 2; | ||||
const safeAreaEdges = Platform.select({ | const safeAreaEdges = Platform.select({ | ||||
ios: ['top'], | ios: ['top'], | ||||
default: ['top', 'bottom'], | default: ['top', 'bottom'], | ||||
}); | }); | ||||
function CommunityDrawerContent(): React.Node { | function CommunityDrawerContent(): React.Node { | ||||
const communities = useSelector(communityThreadSelector); | const communities = useSelector(communityThreadSelector); | ||||
const resolvedCommunities = useResolvedThreadInfos(communities); | const resolvedCommunities = useResolvedThreadInfos(communities); | ||||
const communitiesSuffixed = React.useMemo( | const communitiesSuffixed = React.useMemo( | ||||
() => appendSuffix(resolvedCommunities), | () => appendSuffix(resolvedCommunities), | ||||
[resolvedCommunities], | [resolvedCommunities], | ||||
); | ); | ||||
const styles = useStyles(unboundStyles); | const styles = useStyles(unboundStyles); | ||||
const [inviteLinks, setInviteLinks] = React.useState(null); | |||||
const callFetchPrimaryLinks = useServerCall(fetchPrimaryInviteLinks); | |||||
const dispatchActionPromise = useDispatchActionPromise(); | |||||
const drawerStatus = useDrawerStatus(); | |||||
React.useEffect(() => { | |||||
(async () => { | |||||
if (drawerStatus !== 'open') { | |||||
return; | |||||
} | |||||
const createFetchPrimaryLinksPromise = async () => { | |||||
const response = await callFetchPrimaryLinks(); | |||||
const links = {}; | |||||
for (const link of response.links) { | |||||
links[link.communityID] = link; | |||||
} | |||||
setInviteLinks(links); | |||||
}; | |||||
await dispatchActionPromise( | |||||
fetchPrimaryInviteLinkActionTypes, | |||||
createFetchPrimaryLinksPromise(), | |||||
); | |||||
})(); | |||||
}, [callFetchPrimaryLinks, dispatchActionPromise, drawerStatus]); | |||||
const [openCommunity, setOpenCommunity] = React.useState( | const [openCommunity, setOpenCommunity] = React.useState( | ||||
communitiesSuffixed.length === 1 ? communitiesSuffixed[0].id : null, | communitiesSuffixed.length === 1 ? communitiesSuffixed[0].id : null, | ||||
); | ); | ||||
const navigateToThread = useNavigateToThread(); | const navigateToThread = useNavigateToThread(); | ||||
const childThreadInfosMap = useSelector(childThreadInfos); | const childThreadInfosMap = useSelector(childThreadInfos); | ||||
const setOpenCommunityOrClose = React.useCallback((index: string) => { | const setOpenCommunityOrClose = React.useCallback((index: string) => { | ||||
setOpenCommunity(open => (open === index ? null : index)); | setOpenCommunity(open => (open === index ? null : index)); | ||||
}, []); | }, []); | ||||
const { navigate } = useNavigation(); | |||||
const navigateToInviteLinksView = React.useCallback( | |||||
(community: ThreadInfo, inviteLink: InviteLink) => { | |||||
navigate<'ViewInviteLinksModal'>({ | |||||
name: ViewInviteLinksModalRouteName, | |||||
params: { | |||||
community, | |||||
inviteLink, | |||||
}, | |||||
}); | |||||
}, | |||||
[navigate], | |||||
); | |||||
const renderItem = React.useCallback( | const renderItem = React.useCallback( | ||||
({ item }) => ( | ({ item }) => ( | ||||
<CommunityDrawerItemCommunity | <CommunityDrawerItemCommunity | ||||
key={item.threadInfo.id} | key={item.threadInfo.id} | ||||
itemData={item} | itemData={item} | ||||
toggleExpanded={setOpenCommunityOrClose} | toggleExpanded={setOpenCommunityOrClose} | ||||
expanded={item.threadInfo.id === openCommunity} | expanded={item.threadInfo.id === openCommunity} | ||||
navigateToThread={navigateToThread} | navigateToThread={navigateToThread} | ||||
navigateToInviteLinksView={navigateToInviteLinksView} | |||||
/> | /> | ||||
), | ), | ||||
[navigateToThread, openCommunity, setOpenCommunityOrClose], | [ | ||||
navigateToInviteLinksView, | |||||
navigateToThread, | |||||
openCommunity, | |||||
setOpenCommunityOrClose, | |||||
], | |||||
); | ); | ||||
const labelStylesObj = useStyles(labelUnboundStyles); | const labelStylesObj = useStyles(labelUnboundStyles); | ||||
const labelStyles = React.useMemo( | const labelStyles = React.useMemo( | ||||
() => [ | () => [ | ||||
labelStylesObj.level0Label, | labelStylesObj.level0Label, | ||||
labelStylesObj.level1Label, | labelStylesObj.level1Label, | ||||
labelStylesObj.level2Label, | labelStylesObj.level2Label, | ||||
], | ], | ||||
[labelStylesObj], | [labelStylesObj], | ||||
); | ); | ||||
const drawerItemsData = React.useMemo( | const drawerItemsData = React.useMemo( | ||||
() => | () => | ||||
createRecursiveDrawerItemsData( | createRecursiveDrawerItemsData( | ||||
childThreadInfosMap, | childThreadInfosMap, | ||||
communitiesSuffixed, | communitiesSuffixed, | ||||
labelStyles, | labelStyles, | ||||
maxDepth, | maxDepth, | ||||
inviteLinks, | |||||
), | ), | ||||
[childThreadInfosMap, communitiesSuffixed, labelStyles], | [childThreadInfosMap, communitiesSuffixed, inviteLinks, labelStyles], | ||||
); | ); | ||||
return ( | return ( | ||||
<SafeAreaView style={styles.drawerContent} edges={safeAreaEdges}> | <SafeAreaView style={styles.drawerContent} edges={safeAreaEdges}> | ||||
<FlatList data={drawerItemsData} renderItem={renderItem} /> | <FlatList data={drawerItemsData} renderItem={renderItem} /> | ||||
</SafeAreaView> | </SafeAreaView> | ||||
); | ); | ||||
} | } | ||||
Show All 35 Lines |