You cannot select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
	
	
		
			141 lines
		
	
	
		
			4.4 KiB
		
	
	
	
		
			TypeScript
		
	
			
		
		
	
	
			141 lines
		
	
	
		
			4.4 KiB
		
	
	
	
		
			TypeScript
		
	
| import { isEmpty } from 'lodash';
 | |
| import { useSelector } from 'react-redux';
 | |
| import { AutoSizer, List, ListRowProps } from 'react-virtualized';
 | |
| import styled from 'styled-components';
 | |
| import { SearchResults } from '../search/SearchResults';
 | |
| import { LeftPaneSectionHeader } from './LeftPaneSectionHeader';
 | |
| import { MessageRequestsBanner } from './MessageRequestsBanner';
 | |
| 
 | |
| import { setLeftOverlayMode } from '../../state/ducks/section';
 | |
| import { getLeftPaneConversationIds } from '../../state/selectors/conversations';
 | |
| import { getSearchTerm } from '../../state/selectors/search';
 | |
| import { getLeftOverlayMode } from '../../state/selectors/section';
 | |
| import { assertUnreachable } from '../../types/sqlSharedTypes';
 | |
| import { SessionSearchInput } from '../SessionSearchInput';
 | |
| import { StyledLeftPaneList } from './LeftPaneList';
 | |
| import { ConversationListItem } from './conversation-list-item/ConversationListItem';
 | |
| import { OverlayClosedGroup } from './overlay/OverlayClosedGroup';
 | |
| import { OverlayCommunity } from './overlay/OverlayCommunity';
 | |
| import { OverlayInvite } from './overlay/OverlayInvite';
 | |
| import { OverlayMessage } from './overlay/OverlayMessage';
 | |
| import { OverlayMessageRequest } from './overlay/OverlayMessageRequest';
 | |
| import { OverlayChooseAction } from './overlay/choose-action/OverlayChooseAction';
 | |
| 
 | |
| const StyledLeftPaneContent = styled.div`
 | |
|   display: flex;
 | |
|   flex-direction: column;
 | |
|   flex: 1;
 | |
|   overflow: hidden;
 | |
| `;
 | |
| 
 | |
| const StyledConversationListContent = styled.div`
 | |
|   background: var(--background-primary-color);
 | |
|   overflow-x: hidden;
 | |
|   display: flex;
 | |
|   flex-direction: column;
 | |
|   flex-grow: 1;
 | |
|   transition: none;
 | |
| `;
 | |
| 
 | |
| const ClosableOverlay = () => {
 | |
|   const leftOverlayMode = useSelector(getLeftOverlayMode);
 | |
| 
 | |
|   switch (leftOverlayMode) {
 | |
|     case 'choose-action':
 | |
|       return <OverlayChooseAction />;
 | |
|     case 'open-group':
 | |
|       return <OverlayCommunity />;
 | |
|     case 'closed-group':
 | |
|       return <OverlayClosedGroup />;
 | |
|     case 'message':
 | |
|       return <OverlayMessage />;
 | |
|     case 'message-requests':
 | |
|       return <OverlayMessageRequest />;
 | |
|     case 'invite-a-friend':
 | |
|       return <OverlayInvite />;
 | |
|     case undefined:
 | |
|       return null;
 | |
|     default:
 | |
|       return assertUnreachable(
 | |
|         leftOverlayMode,
 | |
|         `ClosableOverlay: leftOverlayMode case not handled "${leftOverlayMode}"`
 | |
|       );
 | |
|   }
 | |
| };
 | |
| 
 | |
| const ConversationRow = (
 | |
|   { index, key, style }: ListRowProps,
 | |
|   conversationIds: Array<string>
 | |
| ): JSX.Element | null => {
 | |
|   // assume conversations that have been marked unapproved should be filtered out by selector.
 | |
|   if (!conversationIds) {
 | |
|     throw new Error('ConversationRow: Tried to render without conversations');
 | |
|   }
 | |
| 
 | |
|   const conversationId = conversationIds[index];
 | |
|   if (!conversationId) {
 | |
|     throw new Error(
 | |
|       'ConversationRow: conversations selector returned element containing falsy value.'
 | |
|     );
 | |
|   }
 | |
| 
 | |
|   return <ConversationListItem key={key} style={style} conversationId={conversationId} />;
 | |
| };
 | |
| 
 | |
| const ConversationList = () => {
 | |
|   const searchTerm = useSelector(getSearchTerm);
 | |
|   const conversationIds = useSelector(getLeftPaneConversationIds);
 | |
| 
 | |
|   if (!isEmpty(searchTerm)) {
 | |
|     return <SearchResults />;
 | |
|   }
 | |
| 
 | |
|   if (!conversationIds) {
 | |
|     throw new Error(
 | |
|       'ConversationList: must provided conversations if no search results are provided'
 | |
|     );
 | |
|   }
 | |
| 
 | |
|   return (
 | |
|     <StyledLeftPaneList key={`conversation-list-0`}>
 | |
|       <AutoSizer>
 | |
|         {({ height, width }) => (
 | |
|           <List
 | |
|             className="module-left-pane__virtual-list"
 | |
|             height={height}
 | |
|             rowCount={conversationIds.length}
 | |
|             rowHeight={64}
 | |
|             rowRenderer={props => ConversationRow(props, conversationIds)}
 | |
|             width={width}
 | |
|             autoHeight={false}
 | |
|             conversationIds={conversationIds}
 | |
|           />
 | |
|         )}
 | |
|       </AutoSizer>
 | |
|     </StyledLeftPaneList>
 | |
|   );
 | |
| };
 | |
| 
 | |
| export const LeftPaneMessageSection = () => {
 | |
|   const leftOverlayMode = useSelector(getLeftOverlayMode);
 | |
| 
 | |
|   return (
 | |
|     <StyledLeftPaneContent>
 | |
|       <LeftPaneSectionHeader />
 | |
|       {leftOverlayMode ? (
 | |
|         <ClosableOverlay />
 | |
|       ) : (
 | |
|         <StyledConversationListContent>
 | |
|           <SessionSearchInput />
 | |
|           <MessageRequestsBanner
 | |
|             handleOnClick={() => {
 | |
|               window.inboxStore?.dispatch(setLeftOverlayMode('message-requests'));
 | |
|             }}
 | |
|           />
 | |
|           <ConversationList />
 | |
|         </StyledConversationListContent>
 | |
|       )}
 | |
|     </StyledLeftPaneContent>
 | |
|   );
 | |
| };
 |