diff --git a/native/chat/chat-thread-list-item.react.js b/native/chat/chat-thread-list-item.react.js
index 70c9660d1..587fb1359 100644
--- a/native/chat/chat-thread-list-item.react.js
+++ b/native/chat/chat-thread-list-item.react.js
@@ -1,221 +1,234 @@
// @flow
import * as React from 'react';
import { Text, View } from 'react-native';
import type { ChatThreadItem } from 'lib/selectors/chat-selectors.js';
import type { ThreadInfo } from 'lib/types/thread-types.js';
import type { UserInfo } from 'lib/types/user-types.js';
import { shortAbsoluteDate } from 'lib/utils/date-utils.js';
import { useResolvedThreadInfo } from 'lib/utils/entity-helpers.js';
import ChatThreadListSeeMoreSidebars from './chat-thread-list-see-more-sidebars.react.js';
import ChatThreadListSidebar from './chat-thread-list-sidebar.react.js';
import MessagePreview from './message-preview.react.js';
import SwipeableThread from './swipeable-thread.react.js';
import ThreadAvatar from '../avatars/thread-avatar.react.js';
import Button from '../components/button.react.js';
import SingleLine from '../components/single-line.react.js';
import ThreadAncestorsLabel from '../components/thread-ancestors-label.react.js';
import UnreadDot from '../components/unread-dot.react.js';
import { useColors, useStyles } from '../themes/colors.js';
type Props = {
+data: ChatThreadItem,
+onPressItem: (
threadInfo: ThreadInfo,
pendingPersonalThreadUserInfo?: UserInfo,
) => void,
+onPressSeeMoreSidebars: (threadInfo: ThreadInfo) => void,
+onSwipeableWillOpen: (threadInfo: ThreadInfo) => void,
+currentlyOpenedSwipeableId: string,
};
function ChatThreadListItem({
data,
onPressItem,
onPressSeeMoreSidebars,
onSwipeableWillOpen,
currentlyOpenedSwipeableId,
}: Props): React.Node {
const styles = useStyles(unboundStyles);
const colors = useColors();
const lastMessage = React.useMemo(() => {
const mostRecentMessageInfo = data.mostRecentMessageInfo;
if (!mostRecentMessageInfo) {
return (
No messages
);
}
return (
);
}, [data.mostRecentMessageInfo, data.threadInfo, styles]);
const numOfSidebarsWithExtendedArrow =
data.sidebars.filter(sidebarItem => sidebarItem.type === 'sidebar').length -
1;
- const sidebars = data.sidebars.map((sidebarItem, index) => {
- if (sidebarItem.type === 'sidebar') {
- const { type, ...sidebarInfo } = sidebarItem;
- return (
-
- );
- } else if (sidebarItem.type === 'seeMore') {
- return (
-
- );
- } else {
- return ;
- }
- });
+ const sidebars = React.useMemo(
+ () =>
+ data.sidebars.map((sidebarItem, index) => {
+ if (sidebarItem.type === 'sidebar') {
+ const { type, ...sidebarInfo } = sidebarItem;
+ return (
+
+ );
+ } else if (sidebarItem.type === 'seeMore') {
+ return (
+
+ );
+ } else {
+ return ;
+ }
+ }),
+ [
+ currentlyOpenedSwipeableId,
+ data.sidebars,
+ data.threadInfo,
+ numOfSidebarsWithExtendedArrow,
+ onPressItem,
+ onPressSeeMoreSidebars,
+ onSwipeableWillOpen,
+ styles.spacer,
+ ],
+ );
const onPress = React.useCallback(() => {
onPressItem(data.threadInfo, data.pendingPersonalThreadUserInfo);
}, [onPressItem, data.threadInfo, data.pendingPersonalThreadUserInfo]);
const threadNameStyle = React.useMemo(() => {
if (!data.threadInfo.currentUser.unread) {
return styles.threadName;
}
return [styles.threadName, styles.unreadThreadName];
}, [
data.threadInfo.currentUser.unread,
styles.threadName,
styles.unreadThreadName,
]);
const lastActivity = shortAbsoluteDate(data.lastUpdatedTime);
const lastActivityStyle = React.useMemo(() => {
if (!data.threadInfo.currentUser.unread) {
return styles.lastActivity;
}
return [styles.lastActivity, styles.unreadLastActivity];
}, [
data.threadInfo.currentUser.unread,
styles.lastActivity,
styles.unreadLastActivity,
]);
const resolvedThreadInfo = useResolvedThreadInfo(data.threadInfo);
return (
<>
{sidebars}
>
);
}
const chatThreadListItemHeight = 70;
const spacerHeight = 6;
const unboundStyles = {
container: {
height: chatThreadListItemHeight,
justifyContent: 'center',
backgroundColor: 'listBackground',
},
content: {
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'center',
},
avatarContainer: {
marginLeft: 6,
marginBottom: 12,
},
threadDetails: {
paddingLeft: 12,
paddingRight: 18,
justifyContent: 'center',
flex: 1,
marginTop: 5,
},
lastActivity: {
color: 'listForegroundTertiaryLabel',
fontSize: 14,
marginLeft: 10,
},
unreadLastActivity: {
color: 'listForegroundLabel',
fontWeight: 'bold',
},
noMessages: {
color: 'listForegroundTertiaryLabel',
flex: 1,
fontSize: 14,
fontStyle: 'italic',
},
row: {
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'center',
},
threadName: {
color: 'listForegroundSecondaryLabel',
flex: 1,
fontSize: 21,
},
unreadThreadName: {
color: 'listForegroundLabel',
fontWeight: '500',
},
spacer: {
height: spacerHeight,
},
};
export { ChatThreadListItem, chatThreadListItemHeight, spacerHeight };
diff --git a/native/chat/chat-thread-list-sidebar.react.js b/native/chat/chat-thread-list-sidebar.react.js
index 646531d83..04db62007 100644
--- a/native/chat/chat-thread-list-sidebar.react.js
+++ b/native/chat/chat-thread-list-sidebar.react.js
@@ -1,151 +1,158 @@
// @flow
import * as React from 'react';
import { View } from 'react-native';
import type { ThreadInfo, SidebarInfo } from 'lib/types/thread-types.js';
import { SidebarItem, sidebarHeight } from './sidebar-item.react.js';
import SwipeableThread from './swipeable-thread.react.js';
import Button from '../components/button.react.js';
import UnreadDot from '../components/unread-dot.react.js';
import { useColors, useStyles } from '../themes/colors.js';
import ExtendedArrow from '../vectors/arrow-extended.react.js';
import Arrow from '../vectors/arrow.react.js';
type Props = {
+sidebarInfo: SidebarInfo,
+onPressItem: (threadInfo: ThreadInfo) => void,
+onSwipeableWillOpen: (threadInfo: ThreadInfo) => void,
+currentlyOpenedSwipeableId: string,
+extendArrow: boolean,
};
function ChatThreadListSidebar(props: Props): React.Node {
const colors = useColors();
const styles = useStyles(unboundStyles);
const {
sidebarInfo,
onSwipeableWillOpen,
currentlyOpenedSwipeableId,
onPressItem,
extendArrow = false,
} = props;
const { threadInfo } = sidebarInfo;
const onPress = React.useCallback(
() => onPressItem(threadInfo),
[threadInfo, onPressItem],
);
const arrow = React.useMemo(() => {
if (extendArrow) {
return (
);
}
return (
);
}, [extendArrow, styles.arrow, styles.extendedArrow]);
const unreadIndicator = React.useMemo(
() => (
),
[
sidebarInfo.threadInfo.currentUser.unread,
styles.unreadIndicatorContainer,
],
);
+ const sidebarItem = React.useMemo(
+ () => ,
+ [sidebarInfo],
+ );
+
const swipeableThread = React.useMemo(
() => (
-
+ {sidebarItem}
),
[
currentlyOpenedSwipeableId,
onSwipeableWillOpen,
- sidebarInfo,
+ sidebarInfo.mostRecentNonLocalMessage,
+ sidebarInfo.threadInfo,
+ sidebarItem,
styles.swipeableThreadContainer,
],
);
const chatThreadListSidebar = React.useMemo(
() => (
),
[
arrow,
colors.listIosHighlightUnderlay,
onPress,
styles.sidebar,
swipeableThread,
unreadIndicator,
],
);
return chatThreadListSidebar;
}
const unboundStyles = {
arrow: {
left: 28,
position: 'absolute',
top: -12,
},
extendedArrow: {
left: 28,
position: 'absolute',
top: -6,
},
sidebar: {
alignItems: 'center',
flexDirection: 'row',
width: '100%',
height: sidebarHeight,
paddingLeft: 6,
paddingRight: 18,
backgroundColor: 'listBackground',
},
swipeableThreadContainer: {
flex: 1,
height: '100%',
},
unreadIndicatorContainer: {
alignItems: 'center',
flexDirection: 'row',
justifyContent: 'flex-start',
paddingLeft: 6,
width: 56,
},
};
export default ChatThreadListSidebar;