|  |  |  | import classNames from 'classnames'; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import { MouseEvent } from 'react'; | 
					
						
							|  |  |  | import { useSelector } from 'react-redux'; | 
					
						
							|  |  |  | import styled from 'styled-components'; | 
					
						
							|  |  |  | import { useConvoIdFromContext } from '../../../contexts/ConvoIdContext'; | 
					
						
							|  |  |  | import { Data } from '../../../data/data'; | 
					
						
							|  |  |  | import { | 
					
						
							|  |  |  |   useActiveAt, | 
					
						
							|  |  |  |   useConversationPropsById, | 
					
						
							|  |  |  |   useHasUnread, | 
					
						
							|  |  |  |   useIsForcedUnreadWithoutUnreadMsg, | 
					
						
							|  |  |  |   useIsPinned, | 
					
						
							|  |  |  |   useMentionedUs, | 
					
						
							|  |  |  |   useUnreadCount, | 
					
						
							|  |  |  | } from '../../../hooks/useParamSelector'; | 
					
						
							|  |  |  | import { Constants } from '../../../session'; | 
					
						
							|  |  |  | import { | 
					
						
							|  |  |  |   openConversationToSpecificMessage, | 
					
						
							|  |  |  |   openConversationWithMessages, | 
					
						
							|  |  |  | } from '../../../state/ducks/conversations'; | 
					
						
							|  |  |  | import { isSearching } from '../../../state/selectors/search'; | 
					
						
							|  |  |  | import { getIsMessageSection } from '../../../state/selectors/section'; | 
					
						
							|  |  |  | import { Timestamp } from '../../conversation/Timestamp'; | 
					
						
							|  |  |  | import { SessionIcon } from '../../icon'; | 
					
						
							|  |  |  | import { UserItem } from './UserItem'; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const NotificationSettingIcon = () => { | 
					
						
							|  |  |  |   const isMessagesSection = useSelector(getIsMessageSection); | 
					
						
							|  |  |  |   const convoId = useConvoIdFromContext(); | 
					
						
							|  |  |  |   const convoSetting = useConversationPropsById(convoId)?.currentNotificationSetting; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (!isMessagesSection) { | 
					
						
							|  |  |  |     return null; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   switch (convoSetting) { | 
					
						
							|  |  |  |     case 'all': | 
					
						
							|  |  |  |       return null; | 
					
						
							|  |  |  |     case 'disabled': | 
					
						
							|  |  |  |       return ( | 
					
						
							|  |  |  |         <SessionIcon | 
					
						
							|  |  |  |           iconType="mute" | 
					
						
							|  |  |  |           iconColor={'var(--conversation-tab-text-color)'} | 
					
						
							|  |  |  |           iconSize="small" | 
					
						
							|  |  |  |         /> | 
					
						
							|  |  |  |       ); | 
					
						
							|  |  |  |     case 'mentions_only': | 
					
						
							|  |  |  |       return ( | 
					
						
							|  |  |  |         <SessionIcon | 
					
						
							|  |  |  |           iconType="bell" | 
					
						
							|  |  |  |           iconColor={'var(--conversation-tab-text-color)'} | 
					
						
							|  |  |  |           iconSize="small" | 
					
						
							|  |  |  |         /> | 
					
						
							|  |  |  |       ); | 
					
						
							|  |  |  |     default: | 
					
						
							|  |  |  |       return null; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const StyledConversationListItemIconWrapper = styled.div`
 | 
					
						
							|  |  |  |   svg { | 
					
						
							|  |  |  |     margin: 0px 2px; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   display: flex; | 
					
						
							|  |  |  |   flex-direction: row; | 
					
						
							|  |  |  | `;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const PinIcon = () => { | 
					
						
							|  |  |  |   const conversationId = useConvoIdFromContext(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   const isMessagesSection = useSelector(getIsMessageSection); | 
					
						
							|  |  |  |   const isPinned = useIsPinned(conversationId); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return isMessagesSection && isPinned ? ( | 
					
						
							|  |  |  |     <SessionIcon iconType="pin" iconColor={'var(--conversation-tab-text-color)'} iconSize="small" /> | 
					
						
							|  |  |  |   ) : null; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const ListItemIcons = () => { | 
					
						
							|  |  |  |   return ( | 
					
						
							|  |  |  |     <StyledConversationListItemIconWrapper> | 
					
						
							|  |  |  |       <PinIcon /> | 
					
						
							|  |  |  |       <NotificationSettingIcon /> | 
					
						
							|  |  |  |     </StyledConversationListItemIconWrapper> | 
					
						
							|  |  |  |   ); | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const MentionAtSymbol = styled.span`
 | 
					
						
							|  |  |  |   background: var(--unread-messages-alert-background-color); | 
					
						
							|  |  |  |   color: var(--unread-messages-alert-text-color); | 
					
						
							|  |  |  |   text-align: center; | 
					
						
							|  |  |  |   margin-top: 0px; | 
					
						
							|  |  |  |   margin-bottom: 0px; | 
					
						
							|  |  |  |   padding-inline-start: 3px; | 
					
						
							|  |  |  |   padding-inline-end: 3px; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   position: static; | 
					
						
							|  |  |  |   margin-inline-start: 5px; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   font-weight: 700; | 
					
						
							|  |  |  |   font-size: var(--font-size-xs); | 
					
						
							|  |  |  |   letter-spacing: 0.25px; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   height: 16px; | 
					
						
							|  |  |  |   min-width: 16px; | 
					
						
							|  |  |  |   border-radius: 8px; | 
					
						
							|  |  |  |   cursor: pointer; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   :hover { | 
					
						
							|  |  |  |     filter: grayscale(0.7); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | `;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** | 
					
						
							|  |  |  |  * When clicking on the `@` symbol of a conversation, we open the conversation to the first unread message tagging us (with the @pubkey syntax) | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | async function openConvoToLastMention(e: MouseEvent<HTMLSpanElement>, conversationId: string) { | 
					
						
							|  |  |  |   e.stopPropagation(); | 
					
						
							|  |  |  |   e.preventDefault(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // mousedown is invoked sooner than onClick, but for both right and left click
 | 
					
						
							|  |  |  |   if (e.button === 0) { | 
					
						
							|  |  |  |     const oldestMessageUnreadWithMention = | 
					
						
							|  |  |  |       (await Data.getFirstUnreadMessageWithMention(conversationId)) || null; | 
					
						
							|  |  |  |     if (oldestMessageUnreadWithMention) { | 
					
						
							|  |  |  |       await openConversationToSpecificMessage({ | 
					
						
							|  |  |  |         conversationKey: conversationId, | 
					
						
							|  |  |  |         messageIdToNavigateTo: oldestMessageUnreadWithMention, | 
					
						
							|  |  |  |         shouldHighlightMessage: true, | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |       window.log.info('cannot open to latest mention as no unread mention are found'); | 
					
						
							|  |  |  |       await openConversationWithMessages({ | 
					
						
							|  |  |  |         conversationKey: conversationId, | 
					
						
							|  |  |  |         messageId: null, | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const AtSymbol = ({ convoId }: { convoId: string }) => { | 
					
						
							|  |  |  |   const hasMentionedUs = useMentionedUs(convoId); | 
					
						
							|  |  |  |   const hasUnread = useHasUnread(convoId); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return hasMentionedUs && hasUnread ? ( | 
					
						
							|  |  |  |     <MentionAtSymbol | 
					
						
							|  |  |  |       title="Open to latest mention" | 
					
						
							|  |  |  |       // eslint-disable-next-line @typescript-eslint/no-misused-promises
 | 
					
						
							|  |  |  |       onMouseDown={async e => openConvoToLastMention(e, convoId)} | 
					
						
							|  |  |  |     > | 
					
						
							|  |  |  |       @ | 
					
						
							|  |  |  |     </MentionAtSymbol> | 
					
						
							|  |  |  |   ) : null; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const UnreadCount = ({ convoId }: { convoId: string }) => { | 
					
						
							|  |  |  |   const unreadMsgCount = useUnreadCount(convoId); | 
					
						
							|  |  |  |   const forcedUnread = useIsForcedUnreadWithoutUnreadMsg(convoId); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   const unreadWithOverflow = | 
					
						
							|  |  |  |     unreadMsgCount > Constants.CONVERSATION.MAX_CONVO_UNREAD_COUNT | 
					
						
							|  |  |  |       ? `${Constants.CONVERSATION.MAX_CONVO_UNREAD_COUNT}+` | 
					
						
							|  |  |  |       : unreadMsgCount || ' '; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // TODO would be good to merge the style of this with SessionNotificationCount or SessionUnreadCount at some point.
 | 
					
						
							|  |  |  |   return unreadMsgCount > 0 || forcedUnread ? ( | 
					
						
							|  |  |  |     <p className="module-conversation-list-item__unread-count">{unreadWithOverflow}</p> | 
					
						
							|  |  |  |   ) : null; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | export const ConversationListItemHeaderItem = () => { | 
					
						
							|  |  |  |   const conversationId = useConvoIdFromContext(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   const isSearchingMode = useSelector(isSearching); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   const hasUnread = useHasUnread(conversationId); | 
					
						
							|  |  |  |   const activeAt = useActiveAt(conversationId); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return ( | 
					
						
							|  |  |  |     <div className="module-conversation-list-item__header"> | 
					
						
							|  |  |  |       <div | 
					
						
							|  |  |  |         className={classNames( | 
					
						
							|  |  |  |           'module-conversation-list-item__header__name', | 
					
						
							|  |  |  |           hasUnread ? 'module-conversation-list-item__header__name--with-unread' : null | 
					
						
							|  |  |  |         )} | 
					
						
							|  |  |  |       > | 
					
						
							|  |  |  |         <UserItem /> | 
					
						
							|  |  |  |       </div> | 
					
						
							|  |  |  |       <ListItemIcons /> | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       <UnreadCount convoId={conversationId} /> | 
					
						
							|  |  |  |       <AtSymbol convoId={conversationId} /> | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       {!isSearchingMode && ( | 
					
						
							|  |  |  |         <div | 
					
						
							|  |  |  |           className={classNames( | 
					
						
							|  |  |  |             'module-conversation-list-item__header__date', | 
					
						
							|  |  |  |             hasUnread ? 'module-conversation-list-item__header__date--has-unread' : null | 
					
						
							|  |  |  |           )} | 
					
						
							|  |  |  |         > | 
					
						
							|  |  |  |           <Timestamp timestamp={activeAt} isConversationListItem={true} momentFromNow={true} /> | 
					
						
							|  |  |  |         </div> | 
					
						
							|  |  |  |       )} | 
					
						
							|  |  |  |     </div> | 
					
						
							|  |  |  |   ); | 
					
						
							|  |  |  | }; |