All files / app/features/messages/groupchats GroupChatListItem.tsx

0% Statements 0/31
0% Branches 0/22
0% Functions 0/3
0% Lines 0/30

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124                                                                                                                                                                                                                                                       
import {
  ListItem,
  ListItemAvatar,
  ListItemProps,
  ListItemText,
} from "@material-ui/core";
import { makeStyles } from "@material-ui/core/styles";
import { Skeleton } from "@material-ui/lab";
import Avatar from "components/Avatar";
import { MuteIcon } from "components/Icons";
import { useAuthContext } from "features/auth/AuthProvider";
import {
  controlMessage,
  groupChatTitleText,
  isControlMessage,
  messageTargetId,
} from "features/messages/utils";
import useUsers from "features/userQueries/useUsers";
import { useTranslation } from "i18n";
import { MESSAGES } from "i18n/namespaces";
import { GroupChat } from "proto/conversations_pb";
import React from "react";
import { firstName } from "utils/names";
 
const useStyles = makeStyles((theme) => ({
  titlePadding: { marginInlineEnd: theme.spacing(1) },
  muteIcon: { verticalAlign: "middle" },
  unread: { fontWeight: "bold" },
}));
 
export interface GroupChatListItemProps extends ListItemProps {
  groupChat: GroupChat.AsObject;
}
 
export default function GroupChatListItem({
  groupChat,
  className,
}: GroupChatListItemProps) {
  const { t } = useTranslation(MESSAGES);
  const classes = useStyles();
  const currentUserId = useAuthContext().authState.userId!;
  const latestMessageAuthorId = groupChat.latestMessage?.authorUserId;
  const isUnreadClass =
    groupChat.lastSeenMessageId !== groupChat.latestMessage?.messageId
      ? classes.unread
      : "";
 
  //It is possible the last message is sent by someone who has left
  //so include it just in case
  const groupChatMembersQuery = useUsers([
    ...groupChat.memberUserIdsList,
    latestMessageAuthorId,
  ]);
 
  //the avatar is of the latest message author (if it's not the logged in user),
  //otherwise any user that's not the logged in user, otherwise logged in user
  const avatarUserId =
    latestMessageAuthorId !== null && latestMessageAuthorId !== currentUserId
      ? latestMessageAuthorId
      : groupChat.memberUserIdsList.find((id) => id !== currentUserId) ??
        currentUserId;
  //title is the chat title, or all the member's names except current user joined together
  const title = groupChatTitleText(
    groupChat,
    groupChatMembersQuery,
    currentUserId
  );
  //text is the control message text or message text
  let text = "";
  const authorName = firstName(
    groupChatMembersQuery.data?.get(groupChat.latestMessage?.authorUserId)?.name
  );
  if (groupChat.latestMessage && isControlMessage(groupChat.latestMessage)) {
    const targetName = firstName(
      groupChatMembersQuery.data?.get(messageTargetId(groupChat.latestMessage))
        ?.name
    );
    text = controlMessage({
      user: authorName,
      target_user: targetName,
      t,
      message: groupChat.latestMessage,
    });
  } else {
    text = `${authorName}: ${groupChat.latestMessage?.text?.text || ""}`;
  }
 
  return (
    <ListItem button className={className}>
      <ListItemAvatar>
        {groupChatMembersQuery.isLoading ? (
          <Skeleton />
        ) : (
          <Avatar
            user={groupChatMembersQuery.data?.get(avatarUserId)}
            isProfileLink={false}
          />
        )}
      </ListItemAvatar>
      {
        //When we want more than primary and secondary (host Request status, etc)
        //They can also take react nodes. But change typography component using props
      }
      <ListItemText
        primary={
          groupChatMembersQuery.isLoading ? (
            <Skeleton />
          ) : (
            <>
              <span className={classes.titlePadding}>{title}</span>
              {groupChat.muteInfo?.muted && (
                <MuteIcon className={classes.muteIcon} />
              )}
            </>
          )
        }
        secondary={groupChatMembersQuery.isLoading ? <Skeleton /> : text}
        primaryTypographyProps={{ noWrap: true, className: isUnreadClass }}
        secondaryTypographyProps={{ noWrap: true, className: isUnreadClass }}
      />
    </ListItem>
  );
}