Changeset View
Changeset View
Standalone View
Standalone View
web/chat/chat-thread-list.react.js
// @flow | // @flow | ||||
import invariant from 'invariant'; | import invariant from 'invariant'; | ||||
import _sum from 'lodash/fp/sum.js'; | import _sum from 'lodash/fp/sum.js'; | ||||
import * as React from 'react'; | import * as React from 'react'; | ||||
import AutoSizer from 'react-virtualized-auto-sizer'; | import AutoSizer from 'react-virtualized-auto-sizer'; | ||||
import { VariableSizeList } from 'react-window'; | import { VariableSizeList } from 'react-window'; | ||||
import { useFetchLatestMessages } from 'lib/hooks/message-hooks.js'; | |||||
import { emptyItemText } from 'lib/shared/thread-utils.js'; | import { emptyItemText } from 'lib/shared/thread-utils.js'; | ||||
import ChatThreadListItem from './chat-thread-list-item.react.js'; | import ChatThreadListItem from './chat-thread-list-item.react.js'; | ||||
import css from './chat-thread-list.css'; | import css from './chat-thread-list.css'; | ||||
import { ThreadListContext } from './thread-list-provider.js'; | import { ThreadListContext } from './thread-list-provider.js'; | ||||
import BackgroundIllustration from '../assets/background-illustration.react.js'; | import BackgroundIllustration from '../assets/background-illustration.react.js'; | ||||
import Button from '../components/button.react.js'; | import Button from '../components/button.react.js'; | ||||
import Search from '../components/search.react.js'; | import Search from '../components/search.react.js'; | ||||
import { useSelector } from '../redux/redux-utils.js'; | import { useSelector } from '../redux/redux-utils.js'; | ||||
import { useOnClickNewThread } from '../selectors/thread-selectors.js'; | import { useOnClickNewThread } from '../selectors/thread-selectors.js'; | ||||
const prefetchMessagesThreadThreshold = 5; | |||||
const sizes = { | const sizes = { | ||||
search: 68, | search: 68, | ||||
thread: 81, | thread: 81, | ||||
sidebars: { sidebar: 32, seeMore: 22, spacer: 6 }, | sidebars: { sidebar: 32, seeMore: 22, spacer: 6 }, | ||||
}; | }; | ||||
const getThreadItemSize = item => { | const getThreadItemSize = item => { | ||||
const sidebarHeight = _sum(item.sidebars.map(s => sizes.sidebars[s.type])); | const sidebarHeight = _sum(item.sidebars.map(s => sizes.sidebars[s.type])); | ||||
Show All 33 Lines | () => ( | ||||
onChangeText={setSearchText} | onChangeText={setSearchText} | ||||
searchText={searchText} | searchText={searchText} | ||||
placeholder="Search chats" | placeholder="Search chats" | ||||
/> | /> | ||||
), | ), | ||||
[searchText, setSearchText], | [searchText, setSearchText], | ||||
); | ); | ||||
const { fetchMoreLatestMessages, loadingStatus } = useFetchLatestMessages( | |||||
activeTab === 'Focus', | |||||
inka: Why is this hardcoded? Why cannot messages for 'Background' be fetched here? | |||||
); | |||||
const threadListContainerRef = React.useRef(); | const threadListContainerRef = React.useRef(); | ||||
const threads = React.useMemo( | const threads = React.useMemo( | ||||
() => | () => | ||||
threadList.filter( | threadList.filter( | ||||
item => | item => | ||||
!communityID || | !communityID || | ||||
item.threadInfo.community === communityID || | item.threadInfo.community === communityID || | ||||
item.threadInfo.id === communityID, | item.threadInfo.id === communityID, | ||||
), | ), | ||||
[communityID, threadList], | [communityID, threadList], | ||||
); | ); | ||||
const [currentHeight, setCurrentHeight] = React.useState(0); | |||||
React.useEffect(() => { | |||||
if (loadingStatus === 'loading') { | |||||
return; | |||||
} | |||||
let totalHeight = sizes.search; | |||||
for (const threadItem of threads) { | |||||
totalHeight += getThreadItemSize(threadItem); | |||||
if (totalHeight > currentHeight) { | |||||
return; | |||||
} | |||||
inkaUnsubmitted Not Done Inline ActionsIn the first run totalHeight is sizes.search, so it is greater than currentHeight which is 0. Why do any messages get fetched? inka: In the first run `totalHeight` is `sizes.search`, so it is greater than `currentHeight` which… | |||||
} | |||||
fetchMoreLatestMessages(); | |||||
}, [ | |||||
currentHeight, | |||||
fetchMoreLatestMessages, | |||||
loadingStatus, | |||||
threads, | |||||
threads.length, | |||||
inkaUnsubmitted Not Done Inline ActionsIs this necessary? inka: Is this necessary? | |||||
]); | |||||
React.useEffect(() => { | React.useEffect(() => { | ||||
if (threadListContainerRef.current) { | if (threadListContainerRef.current) { | ||||
threadListContainerRef.current.resetAfterIndex(0, false); | threadListContainerRef.current.resetAfterIndex(0, false); | ||||
} | } | ||||
}, [threads]); | }, [threads]); | ||||
const threadListContainer = React.useMemo(() => { | const threadListContainer = React.useMemo(() => { | ||||
if (isBackground && threads.length === 0) { | if (isBackground && threads.length === 0) { | ||||
Show All 13 Lines | const threadListContainer = React.useMemo(() => { | ||||
const itemSize = index => { | const itemSize = index => { | ||||
if (index === 0) { | if (index === 0) { | ||||
return sizes.search; | return sizes.search; | ||||
} | } | ||||
return getThreadItemSize(items[index]); | return getThreadItemSize(items[index]); | ||||
}; | }; | ||||
const onItemsRendered = ({ visibleStopIndex }) => { | |||||
if ( | |||||
visibleStopIndex >= threads.length - prefetchMessagesThreadThreshold && | |||||
loadingStatus !== 'loading' | |||||
) { | |||||
fetchMoreLatestMessages(); | |||||
} | |||||
}; | |||||
return ( | return ( | ||||
<AutoSizer disableWidth> | <AutoSizer | ||||
disableWidth | |||||
onResize={({ height }) => setCurrentHeight(height)} | |||||
> | |||||
{({ height }) => ( | {({ height }) => ( | ||||
<VariableSizeList | <VariableSizeList | ||||
itemData={items} | itemData={items} | ||||
itemCount={items.length} | itemCount={items.length} | ||||
itemSize={itemSize} | itemSize={itemSize} | ||||
itemKey={itemKey} | itemKey={itemKey} | ||||
height={height} | height={height} | ||||
overscanCount={1} | overscanCount={1} | ||||
onItemsRendered={onItemsRendered} | |||||
ref={threadListContainerRef} | ref={threadListContainerRef} | ||||
> | > | ||||
{renderItem} | {renderItem} | ||||
</VariableSizeList> | </VariableSizeList> | ||||
)} | )} | ||||
</AutoSizer> | </AutoSizer> | ||||
); | ); | ||||
}, [isBackground, search, threads]); | }, [fetchMoreLatestMessages, isBackground, loadingStatus, search, threads]); | ||||
return ( | return ( | ||||
<> | <> | ||||
<div className={css.threadListContainer}>{threadListContainer}</div> | <div className={css.threadListContainer}>{threadListContainer}</div> | ||||
<div className={css.createNewThread}> | <div className={css.createNewThread}> | ||||
<Button | <Button | ||||
variant="filled" | variant="filled" | ||||
disabled={isThreadCreation} | disabled={isThreadCreation} | ||||
Show All 19 Lines |
Why is this hardcoded? Why cannot messages for 'Background' be fetched here?