diff --git a/native/navigation/community-drawer-content.react.js b/native/navigation/community-drawer-content.react.js
index 824f5ea31..985d557f3 100644
--- a/native/navigation/community-drawer-content.react.js
+++ b/native/navigation/community-drawer-content.react.js
@@ -1,190 +1,199 @@
// @flow
import * as React from 'react';
import { FlatList, Platform } from 'react-native';
import { SafeAreaView } from 'react-native-safe-area-context';
import { useSelector } from 'react-redux';
import {
childThreadInfos,
communityThreadSelector,
} from 'lib/selectors/thread-selectors';
import { threadIsChannel } from 'lib/shared/thread-utils';
-import { type ThreadInfo, communitySubthreads } from 'lib/types/thread-types';
+import {
+ type ThreadInfo,
+ type ResolvedThreadInfo,
+ communitySubthreads,
+} from 'lib/types/thread-types';
+import { useResolvedThreadInfos } from 'lib/utils/entity-helpers';
import { useNavigateToThread } from '../chat/message-list-types';
import { useStyles } from '../themes/colors';
import type { TextStyle } from '../types/styles';
import CommunityDrawerItemCommunity from './community-drawer-item-community.react';
const maxDepth = 2;
const safeAreaEdges = Platform.select({
ios: ['top'],
default: ['top', 'bottom'],
});
function CommunityDrawerContent(): React.Node {
const communities = useSelector(communityThreadSelector);
- const communitiesSuffixed = React.useMemo(() => appendSuffix(communities), [
- communities,
- ]);
+ const resolvedCommunities = useResolvedThreadInfos(communities);
+ const communitiesSuffixed = React.useMemo(
+ () => appendSuffix(resolvedCommunities),
+ [resolvedCommunities],
+ );
const styles = useStyles(unboundStyles);
const [openCommunity, setOpenCommunity] = React.useState(
communitiesSuffixed.length === 1 ? communitiesSuffixed[0].id : null,
);
const navigateToThread = useNavigateToThread();
const childThreadInfosMap = useSelector(childThreadInfos);
const setOpenCommunityOrClose = React.useCallback((index: string) => {
setOpenCommunity(open => (open === index ? null : index));
}, []);
const renderItem = React.useCallback(
({ item }) => {
const itemData = {
threadInfo: item.threadInfo,
itemChildren: item.itemChildren,
labelStyle: item.labelStyle,
hasSubchannelsButton: item.subchannelsButton,
};
return (
);
},
[navigateToThread, openCommunity, setOpenCommunityOrClose],
);
const labelStylesObj = useStyles(labelUnboundStyles);
const labelStyles = React.useMemo(
() => [
labelStylesObj.level0Label,
labelStylesObj.level1Label,
labelStylesObj.level2Label,
],
[labelStylesObj],
);
const drawerItemsData = React.useMemo(
() =>
createRecursiveDrawerItemsData(
childThreadInfosMap,
communitiesSuffixed,
labelStyles,
),
[childThreadInfosMap, communitiesSuffixed, labelStyles],
);
return (
);
}
function createRecursiveDrawerItemsData(
childThreadInfosMap: { +[id: string]: $ReadOnlyArray },
- communities: $ReadOnlyArray,
+ communities: $ReadOnlyArray,
labelStyles: $ReadOnlyArray,
) {
const result = communities.map(community => ({
key: community.id,
threadInfo: community,
itemChildren: [],
labelStyle: labelStyles[0],
subchannelsButton: false,
}));
let queue = result.map(item => [item, 0]);
for (let i = 0; i < queue.length; i++) {
const [item, lvl] = queue[i];
const itemChildThreadInfos = childThreadInfosMap[item.threadInfo.id] ?? [];
if (lvl < maxDepth) {
item.itemChildren = itemChildThreadInfos
.filter(childItem => communitySubthreads.includes(childItem.type))
.map(childItem => ({
threadInfo: childItem,
itemChildren: [],
labelStyle: labelStyles[Math.min(lvl + 1, labelStyles.length - 1)],
hasSubchannelsButton:
lvl + 1 === maxDepth &&
threadHasSubchannels(childItem, childThreadInfosMap),
}));
queue = queue.concat(
item.itemChildren.map(childItem => [childItem, lvl + 1]),
);
}
}
return result;
}
function threadHasSubchannels(
threadInfo: ThreadInfo,
childThreadInfosMap: { +[id: string]: $ReadOnlyArray },
) {
if (!childThreadInfosMap[threadInfo.id]?.length) {
return false;
}
return childThreadInfosMap[threadInfo.id].some(thread =>
threadIsChannel(thread),
);
}
-function appendSuffix(chats: $ReadOnlyArray): ThreadInfo[] {
+function appendSuffix(
+ chats: $ReadOnlyArray,
+): ResolvedThreadInfo[] {
const result = [];
const names = new Map();
for (const chat of chats) {
let name = chat.uiName;
const numberOfOccurrences = names.get(name);
names.set(name, (numberOfOccurrences ?? 0) + 1);
if (numberOfOccurrences) {
name = `${name} (${numberOfOccurrences.toString()})`;
}
result.push({ ...chat, uiName: name });
}
return result;
}
const unboundStyles = {
drawerContent: {
flex: 1,
paddingRight: 8,
paddingTop: 8,
backgroundColor: 'drawerBackground',
},
};
const labelUnboundStyles = {
level0Label: {
color: 'drawerItemLabelLevel0',
fontSize: 16,
lineHeight: 24,
fontWeight: '500',
},
level1Label: {
color: 'drawerItemLabelLevel1',
fontSize: 14,
lineHeight: 22,
fontWeight: '500',
},
level2Label: {
color: 'drawerItemLabelLevel2',
fontSize: 14,
lineHeight: 22,
fontWeight: '400',
},
};
const MemoizedCommunityDrawerContent: React.ComponentType<{}> = React.memo(
CommunityDrawerContent,
);
export default MemoizedCommunityDrawerContent;
diff --git a/native/navigation/community-drawer-item.react.js b/native/navigation/community-drawer-item.react.js
index cb0b78b0e..7c5cebb6c 100644
--- a/native/navigation/community-drawer-item.react.js
+++ b/native/navigation/community-drawer-item.react.js
@@ -1,153 +1,155 @@
// @flow
import * as React from 'react';
import { View, FlatList, TouchableOpacity } from 'react-native';
import type { ThreadInfo } from 'lib/types/thread-types';
+import { useResolvedThreadInfo } from 'lib/utils/entity-helpers';
import type { MessageListParams } from '../chat/message-list-types';
import { SingleLine } from '../components/single-line.react';
import { useStyles } from '../themes/colors';
import type { TextStyle } from '../types/styles';
import { ExpandButton, ExpandButtonDisabled } from './expand-buttons.react';
import SubchannelsButton from './subchannels-button.react';
export type CommunityDrawerItemData = {
+threadInfo: ThreadInfo,
+itemChildren?: $ReadOnlyArray,
+labelStyle: TextStyle,
+hasSubchannelsButton: boolean,
};
export type DrawerItemProps = {
+itemData: CommunityDrawerItemData,
+toggleExpanded: (threadID: string) => void,
+expanded: boolean,
+navigateToThread: (params: MessageListParams) => void,
};
function CommunityDrawerItem(props: DrawerItemProps): React.Node {
const {
itemData: { threadInfo, itemChildren, labelStyle, hasSubchannelsButton },
navigateToThread,
expanded,
toggleExpanded,
} = props;
const styles = useStyles(unboundStyles);
const renderItem = React.useCallback(
({ item }) => (
),
[navigateToThread],
);
const children = React.useMemo(() => {
if (!expanded) {
return null;
}
if (hasSubchannelsButton) {
return (
);
}
return ;
}, [
expanded,
itemChildren,
renderItem,
hasSubchannelsButton,
styles.subchannelsButton,
threadInfo,
]);
const onExpandToggled = React.useCallback(() => {
toggleExpanded(threadInfo.id);
}, [toggleExpanded, threadInfo.id]);
const itemExpandButton = React.useMemo(() => {
if (!itemChildren?.length && !hasSubchannelsButton) {
return ;
}
return ;
}, [itemChildren?.length, hasSubchannelsButton, onExpandToggled, expanded]);
const onPress = React.useCallback(() => {
navigateToThread({ threadInfo });
}, [navigateToThread, threadInfo]);
+ const { uiName } = useResolvedThreadInfo(threadInfo);
return (
{itemExpandButton}
- {threadInfo.uiName}
+ {uiName}
{children}
);
}
const unboundStyles = {
chatView: {
marginLeft: 16,
},
threadEntry: {
flexDirection: 'row',
marginVertical: 6,
},
textTouchableWrapper: {
flex: 1,
},
subchannelsButton: {
marginLeft: 24,
marginBottom: 6,
},
};
export type CommunityDrawerItemChatProps = {
+itemData: CommunityDrawerItemData,
+navigateToThread: (params: MessageListParams) => void,
};
function CommunityDrawerItemChat(
props: CommunityDrawerItemChatProps,
): React.Node {
const [expanded, setExpanded] = React.useState(false);
const styles = useStyles(unboundStyles);
const toggleExpanded = React.useCallback(() => {
setExpanded(isExpanded => !isExpanded);
}, []);
return (
);
}
const MemoizedCommunityDrawerItemChat: React.ComponentType = React.memo(
CommunityDrawerItemChat,
);
const MemoizedCommunityDrawerItem: React.ComponentType = React.memo(
CommunityDrawerItem,
);
export default MemoizedCommunityDrawerItem;