Changeset View
Changeset View
Standalone View
Standalone View
native/navigation/community-drawer-item.react.js
// @flow | // @flow | ||||
import { useActionSheet } from '@expo/react-native-action-sheet'; | |||||
import * as React from 'react'; | import * as React from 'react'; | ||||
import { View, FlatList, TouchableOpacity } from 'react-native'; | import { View, FlatList, TouchableOpacity } from 'react-native'; | ||||
import { useSafeAreaInsets } from 'react-native-safe-area-context'; | |||||
import type { InviteLink } from 'lib/types/link-types'; | |||||
import type { ThreadInfo } from 'lib/types/thread-types'; | |||||
import type { CommunityDrawerItemData } from 'lib/utils/drawer-utils.react.js'; | import type { CommunityDrawerItemData } from 'lib/utils/drawer-utils.react.js'; | ||||
import { useResolvedThreadInfo } from 'lib/utils/entity-helpers.js'; | import { useResolvedThreadInfo } from 'lib/utils/entity-helpers.js'; | ||||
import { ExpandButton, ExpandButtonDisabled } from './expand-buttons.react.js'; | import { ExpandButton, ExpandButtonDisabled } from './expand-buttons.react.js'; | ||||
import SubchannelsButton from './subchannels-button.react.js'; | import SubchannelsButton from './subchannels-button.react.js'; | ||||
import ThreadAvatar from '../avatars/thread-avatar.react.js'; | import ThreadAvatar from '../avatars/thread-avatar.react.js'; | ||||
import type { MessageListParams } from '../chat/message-list-types.js'; | import type { MessageListParams } from '../chat/message-list-types.js'; | ||||
import { SingleLine } from '../components/single-line.react.js'; | import { SingleLine } from '../components/single-line.react.js'; | ||||
import SWMansionIcon from '../components/swmansion-icon.react.js'; | |||||
import { useStyles } from '../themes/colors.js'; | import { useStyles } from '../themes/colors.js'; | ||||
import type { TextStyle } from '../types/styles.js'; | import type { TextStyle } from '../types/styles.js'; | ||||
import { useShouldRenderAvatars } from '../utils/avatar-utils.js'; | import { useShouldRenderAvatars } from '../utils/avatar-utils.js'; | ||||
export type DrawerItemProps = { | export type DrawerItemProps = { | ||||
+itemData: CommunityDrawerItemData<TextStyle>, | +itemData: CommunityDrawerItemData<TextStyle>, | ||||
+toggleExpanded: (threadID: string) => void, | +toggleExpanded: (threadID: string) => void, | ||||
+expanded: boolean, | +expanded: boolean, | ||||
+navigateToThread: (params: MessageListParams) => void, | +navigateToThread: (params: MessageListParams) => void, | ||||
+navigateToInviteLinksView: ( | |||||
community: ThreadInfo, | |||||
inviteLink: InviteLink, | |||||
) => void, | |||||
}; | }; | ||||
function CommunityDrawerItem(props: DrawerItemProps): React.Node { | function CommunityDrawerItem(props: DrawerItemProps): React.Node { | ||||
const { | const { | ||||
itemData: { threadInfo, itemChildren, labelStyle, hasSubchannelsButton }, | itemData: { | ||||
threadInfo, | |||||
itemChildren, | |||||
labelStyle, | |||||
hasSubchannelsButton, | |||||
inviteLink, | |||||
}, | |||||
navigateToThread, | navigateToThread, | ||||
expanded, | expanded, | ||||
toggleExpanded, | toggleExpanded, | ||||
navigateToInviteLinksView, | |||||
} = props; | } = props; | ||||
const styles = useStyles(unboundStyles); | const styles = useStyles(unboundStyles); | ||||
const renderItem = React.useCallback( | const renderItem = React.useCallback( | ||||
({ item }) => ( | ({ item }) => ( | ||||
<MemoizedCommunityDrawerItemChat | <MemoizedCommunityDrawerItemChat | ||||
key={item.threadInfo.id} | key={item.threadInfo.id} | ||||
itemData={item} | itemData={item} | ||||
navigateToThread={navigateToThread} | navigateToThread={navigateToThread} | ||||
navigateToInviteLinksView={navigateToInviteLinksView} | |||||
/> | /> | ||||
), | ), | ||||
[navigateToThread], | [navigateToInviteLinksView, navigateToThread], | ||||
); | ); | ||||
const children = React.useMemo(() => { | const children = React.useMemo(() => { | ||||
if (!expanded) { | if (!expanded) { | ||||
return null; | return null; | ||||
} | } | ||||
if (hasSubchannelsButton) { | if (hasSubchannelsButton) { | ||||
return ( | return ( | ||||
Show All 38 Lines | const avatar = React.useMemo(() => { | ||||
return ( | return ( | ||||
<View style={styles.avatarContainer}> | <View style={styles.avatarContainer}> | ||||
<ThreadAvatar size="micro" threadInfo={threadInfo} /> | <ThreadAvatar size="micro" threadInfo={threadInfo} /> | ||||
</View> | </View> | ||||
); | ); | ||||
}, [shouldRenderAvatars, styles.avatarContainer, threadInfo]); | }, [shouldRenderAvatars, styles.avatarContainer, threadInfo]); | ||||
const insets = useSafeAreaInsets(); | |||||
const { showActionSheetWithOptions } = useActionSheet(); | |||||
const inviteLinksButton = React.useMemo(() => { | |||||
if (!inviteLink) { | |||||
return null; | |||||
} | |||||
const options = ['Invite Link', 'Cancel']; | |||||
const containerStyle = { | |||||
paddingBottom: insets.bottom, | |||||
}; | |||||
return ( | |||||
<TouchableOpacity | |||||
onPress={() => | |||||
showActionSheetWithOptions( | |||||
{ | |||||
options, | |||||
cancelButtonIndex: 1, | |||||
containerStyle, | |||||
}, | |||||
selectedIndex => { | |||||
if (selectedIndex === 0) { | |||||
navigateToInviteLinksView(threadInfo, inviteLink); | |||||
} | |||||
}, | |||||
) | |||||
} | |||||
> | |||||
<SWMansionIcon | |||||
name="menu-vertical" | |||||
size={22} | |||||
style={styles.inviteLinksButton} | |||||
/> | |||||
</TouchableOpacity> | |||||
); | |||||
}, [ | |||||
insets.bottom, | |||||
inviteLink, | |||||
navigateToInviteLinksView, | |||||
showActionSheetWithOptions, | |||||
styles.inviteLinksButton, | |||||
threadInfo, | |||||
]); | |||||
return ( | return ( | ||||
<View> | <View> | ||||
<View style={styles.threadEntry}> | <View style={styles.threadEntry}> | ||||
{itemExpandButton} | {itemExpandButton} | ||||
<TouchableOpacity | <TouchableOpacity | ||||
onPress={onPress} | onPress={onPress} | ||||
style={styles.textTouchableWrapper} | style={styles.textTouchableWrapper} | ||||
onLongPress={onExpandToggled} | onLongPress={onExpandToggled} | ||||
> | > | ||||
{avatar} | {avatar} | ||||
<SingleLine style={labelStyle}>{uiName}</SingleLine> | <SingleLine style={labelStyle}>{uiName}</SingleLine> | ||||
</TouchableOpacity> | </TouchableOpacity> | ||||
{inviteLinksButton} | |||||
</View> | </View> | ||||
{children} | {children} | ||||
</View> | </View> | ||||
); | ); | ||||
} | } | ||||
const unboundStyles = { | const unboundStyles = { | ||||
avatarContainer: { | avatarContainer: { | ||||
marginRight: 8, | marginRight: 8, | ||||
}, | }, | ||||
chatView: { | chatView: { | ||||
marginLeft: 16, | marginLeft: 16, | ||||
}, | }, | ||||
inviteLinksButton: { | |||||
color: 'drawerItemLabelLevel0', | |||||
}, | |||||
threadEntry: { | threadEntry: { | ||||
flexDirection: 'row', | flexDirection: 'row', | ||||
marginVertical: 6, | marginVertical: 6, | ||||
}, | }, | ||||
textTouchableWrapper: { | textTouchableWrapper: { | ||||
flex: 1, | flex: 1, | ||||
flexDirection: 'row', | flexDirection: 'row', | ||||
alignItems: 'center', | alignItems: 'center', | ||||
}, | }, | ||||
subchannelsButton: { | subchannelsButton: { | ||||
marginLeft: 24, | marginLeft: 24, | ||||
marginBottom: 6, | marginBottom: 6, | ||||
}, | }, | ||||
}; | }; | ||||
export type CommunityDrawerItemChatProps = { | export type CommunityDrawerItemChatProps = { | ||||
+itemData: CommunityDrawerItemData<TextStyle>, | +itemData: CommunityDrawerItemData<TextStyle>, | ||||
+navigateToThread: (params: MessageListParams) => void, | +navigateToThread: (params: MessageListParams) => void, | ||||
+navigateToInviteLinksView: () => void, | |||||
}; | }; | ||||
function CommunityDrawerItemChat( | function CommunityDrawerItemChat( | ||||
props: CommunityDrawerItemChatProps, | props: CommunityDrawerItemChatProps, | ||||
): React.Node { | ): React.Node { | ||||
const [expanded, setExpanded] = React.useState(false); | const [expanded, setExpanded] = React.useState(false); | ||||
const styles = useStyles(unboundStyles); | const styles = useStyles(unboundStyles); | ||||
Show All 21 Lines |