nice sort of display of priority convos and such
This commit is contained in:
@@ -64,6 +64,10 @@ function useSocketFire() {
|
||||
interface IConversationContext {
|
||||
conversationMap: ConversationMap;
|
||||
|
||||
// sorted conversation lists
|
||||
priorityConversations: MasterConversation[];
|
||||
inboxConversations: MasterConversation[];
|
||||
|
||||
selectedConversation?: MasterConversation;
|
||||
selectConversation?: (conversationId: string, temporaryOverrideSort?: boolean) => Promise<void>;
|
||||
|
||||
@@ -72,6 +76,8 @@ interface IConversationContext {
|
||||
|
||||
const ConversationContext = React.createContext<IConversationContext>({
|
||||
conversationMap: {},
|
||||
priorityConversations: [],
|
||||
inboxConversations: [],
|
||||
});
|
||||
|
||||
export function ConversationProvider({ children }: { children: React.ReactNode }) {
|
||||
@@ -339,6 +345,43 @@ export function ConversationProvider({ children }: { children: React.ReactNode }
|
||||
return tunedConversations;
|
||||
}, [conversationMap, user]);
|
||||
|
||||
const masterConversations = useMemo(() => {
|
||||
const priorityConversations: MasterConversation[] = [];
|
||||
const inboxConversations: MasterConversation[] = [];
|
||||
|
||||
Object.values(conversationMap).forEach((currentMasterConversation) => {
|
||||
const personalConvoMember = currentMasterConversation.members.find(
|
||||
(mem) => mem._id.toString() === user._id.toString(),
|
||||
);
|
||||
if (personalConvoMember && personalConvoMember.memberState === 'priority') {
|
||||
priorityConversations.push(currentMasterConversation);
|
||||
|
||||
return;
|
||||
}
|
||||
inboxConversations.push(currentMasterConversation);
|
||||
});
|
||||
|
||||
// sort each list
|
||||
inboxConversations.sort((a, b) => {
|
||||
if (a.temporaryOverrideSort) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (b.temporaryOverrideSort) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// sort by which ones have new activity for me
|
||||
// then sort by last activity date
|
||||
});
|
||||
|
||||
priorityConversations.sort((a, b) => {
|
||||
return b.createdDate.getTime() - a.createdDate.getTime();
|
||||
});
|
||||
|
||||
return [priorityConversations, inboxConversations];
|
||||
}, [conversationMap, user]);
|
||||
|
||||
if (fetchState.error) {
|
||||
return (
|
||||
<Typography variant={'h6'} color={'danger'}>
|
||||
@@ -354,6 +397,8 @@ export function ConversationProvider({ children }: { children: React.ReactNode }
|
||||
handleStartConversation,
|
||||
selectedConversation,
|
||||
selectConversation,
|
||||
priorityConversations: masterConversations[0],
|
||||
inboxConversations: masterConversations[1],
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
|
||||
@@ -41,7 +41,7 @@ export function ConversationList() {
|
||||
|
||||
const { omniSearch } = useSearch();
|
||||
|
||||
const { conversationMap } = useConversations();
|
||||
const { conversationMap, inboxConversations } = useConversations();
|
||||
|
||||
const rendersCount = useRendersCount();
|
||||
// console.warn('RENDER COUNT | CONVERSATION LIST | ', rendersCount);
|
||||
@@ -51,43 +51,6 @@ export function ConversationList() {
|
||||
omniSearch(SUPPORT_DISPLAY_NAME);
|
||||
}, [omniSearch]);
|
||||
|
||||
const masterConversations = useMemo(() => {
|
||||
const priorityConversations: MasterConversation[] = [];
|
||||
const inboxConversations: MasterConversation[] = [];
|
||||
|
||||
Object.values(conversationMap).forEach((currentMasterConversation) => {
|
||||
const personalConvoMember = currentMasterConversation.members.find(
|
||||
(mem) => mem._id.toString() === user._id.toString(),
|
||||
);
|
||||
if (personalConvoMember && personalConvoMember.memberState === 'priority') {
|
||||
priorityConversations.push(currentMasterConversation);
|
||||
|
||||
return;
|
||||
}
|
||||
inboxConversations.push(currentMasterConversation);
|
||||
});
|
||||
|
||||
// sort each list
|
||||
inboxConversations.sort((a, b) => {
|
||||
if (a.temporaryOverrideSort) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (b.temporaryOverrideSort) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// sort by which ones have new activity for me
|
||||
// then sort by last activity date
|
||||
});
|
||||
|
||||
priorityConversations.sort((a, b) => {
|
||||
return b.createdDate.getTime() - a.createdDate.getTime();
|
||||
});
|
||||
|
||||
return [priorityConversations, inboxConversations];
|
||||
}, [conversationMap, user]);
|
||||
|
||||
if (Object.keys(conversationMap).length === 0) {
|
||||
return (
|
||||
<Stack direction={'column'} alignItems="center">
|
||||
@@ -123,37 +86,6 @@ export function ConversationList() {
|
||||
|
||||
<Divider />
|
||||
|
||||
<List
|
||||
sx={{
|
||||
pt: 2,
|
||||
}}
|
||||
subheader={
|
||||
<ListSubheader>
|
||||
<FiActivity />
|
||||
<Typography variant="subtitle2"> Priority</Typography>
|
||||
</ListSubheader>
|
||||
}
|
||||
>
|
||||
{masterConversations[0].length === 0 && (
|
||||
<Stack direction={'column'} alignItems="center">
|
||||
<Typography align="center" variant="caption">
|
||||
Mark conversations as priority to hear them across the hall.
|
||||
</Typography>
|
||||
</Stack>
|
||||
)}
|
||||
|
||||
{masterConversations[0].map((currentConversation, index) => (
|
||||
<ConversationRow
|
||||
key={`${currentConversation._id.toString()}-priorityConvoList`}
|
||||
conversation={currentConversation}
|
||||
index={index}
|
||||
isPriority={true}
|
||||
/>
|
||||
))}
|
||||
</List>
|
||||
|
||||
<Divider />
|
||||
|
||||
<List
|
||||
sx={{
|
||||
pt: 2,
|
||||
@@ -165,7 +97,7 @@ export function ConversationList() {
|
||||
</ListSubheader>
|
||||
}
|
||||
>
|
||||
{masterConversations[1].map((currentConversation, index) => (
|
||||
{inboxConversations.map((currentConversation, index) => (
|
||||
<ConversationRow
|
||||
key={`${currentConversation._id.toString()}-inboxConvoList`}
|
||||
conversation={currentConversation}
|
||||
|
||||
@@ -39,9 +39,10 @@ import {
|
||||
FiVideoOff,
|
||||
FiX,
|
||||
} from 'react-icons/fi';
|
||||
import React, { useCallback, useState } from 'react';
|
||||
import React, { useCallback, useMemo, useState } from 'react';
|
||||
|
||||
import ConversationLabel from '../subcomponents/ConversationLabel';
|
||||
import { MasterConversation } from '../util/types';
|
||||
import { SUPPORT_DISPLAY_NAME } from '../util/support';
|
||||
import { blueGrey } from '@mui/material/colors';
|
||||
import useAuth from '../providers/AuthProvider';
|
||||
@@ -53,7 +54,7 @@ import useZen from '../providers/ZenProvider';
|
||||
export default function FooterControls() {
|
||||
const { handleFlowState } = useZen();
|
||||
|
||||
const { selectedConversation } = useConversations();
|
||||
const { selectedConversation, priorityConversations } = useConversations();
|
||||
const { user, handleLogout } = useAuth();
|
||||
|
||||
const [openUserSettings, setOpenUserSettings] = useState<boolean>(false);
|
||||
@@ -69,6 +70,18 @@ export default function FooterControls() {
|
||||
setOpenUserSettings(false);
|
||||
}, [setOpenUserSettings]);
|
||||
|
||||
// is there a selected conversation and if so, is it a priority one?
|
||||
const isSelectedConversationPriority = useMemo(() => {
|
||||
const priorityIds =
|
||||
priorityConversations.map((priorityConvo) => priorityConvo._id.toString()) ?? [];
|
||||
|
||||
if (selectedConversation && priorityIds.includes(selectedConversation._id.toString())) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}, [selectedConversation, priorityConversations]);
|
||||
|
||||
return (
|
||||
<Box
|
||||
sx={{
|
||||
@@ -90,93 +103,23 @@ export default function FooterControls() {
|
||||
p: 1,
|
||||
flex: 1,
|
||||
}}
|
||||
spacing={2}
|
||||
>
|
||||
{selectedConversation && (
|
||||
<Stack
|
||||
direction={'column'}
|
||||
spacing={1}
|
||||
sx={{
|
||||
p: 1,
|
||||
borderRadius: 2,
|
||||
bgcolor: blueGrey[300],
|
||||
}}
|
||||
alignItems={'center'}
|
||||
>
|
||||
{/* status */}
|
||||
<Box
|
||||
component={'span'}
|
||||
sx={{
|
||||
bgcolor: (theme) => theme.palette.secondary.main,
|
||||
height: 5,
|
||||
width: 5,
|
||||
borderRadius: 100,
|
||||
}}
|
||||
/>
|
||||
|
||||
<AvatarGroup
|
||||
variant={'rounded'}
|
||||
sx={{
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
'& >:first-child': {
|
||||
marginTop: 0,
|
||||
},
|
||||
'& > *': {
|
||||
marginLeft: '0 !important' as any,
|
||||
marginTop: -2,
|
||||
},
|
||||
}}
|
||||
>
|
||||
{selectedConversation.members?.map((conversationUser, index) => (
|
||||
<Avatar
|
||||
key={`${selectedConversation._id.toString()}-${conversationUser._id.toString()}-convoIcon`}
|
||||
alt={conversationUser?.givenName}
|
||||
src={conversationUser?.picture}
|
||||
sx={{
|
||||
opacity: selectedConversation.tunedInUsers?.includes(
|
||||
conversationUser._id.toString(),
|
||||
)
|
||||
? '100%'
|
||||
: '20%',
|
||||
}}
|
||||
/>
|
||||
))}
|
||||
</AvatarGroup>
|
||||
{priorityConversations.map((masterPriorityConversation) => (
|
||||
<OverlayConversation
|
||||
key={`priorityConversationOverlay-${masterPriorityConversation._id.toString()}`}
|
||||
masterConversation={masterPriorityConversation}
|
||||
isSelected={
|
||||
masterPriorityConversation._id.toString() === selectedConversation?._id.toString()
|
||||
}
|
||||
/>
|
||||
))}
|
||||
|
||||
{selectedConversation && !isSelectedConversationPriority && (
|
||||
<>
|
||||
<Divider orientation="horizontal" flexItem />
|
||||
|
||||
<Tooltip title="Show video!">
|
||||
<IconButton
|
||||
sx={{
|
||||
color: 'white',
|
||||
}}
|
||||
size="small"
|
||||
>
|
||||
<FiVideoOff />
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
|
||||
{/* todo: not speaking mode, speaking mode, locked in mode */}
|
||||
<Tooltip title="Speak or toggle by clicking here!">
|
||||
<IconButton
|
||||
sx={{
|
||||
color: 'white',
|
||||
}}
|
||||
size="small"
|
||||
>
|
||||
<FiSun />
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
|
||||
<IconButton
|
||||
sx={{
|
||||
color: 'GrayText',
|
||||
}}
|
||||
size="small"
|
||||
>
|
||||
<FiX />
|
||||
</IconButton>
|
||||
</Stack>
|
||||
<OverlayConversation masterConversation={selectedConversation} isSelected={true} />
|
||||
</>
|
||||
)}
|
||||
|
||||
<Stack sx={{ mt: 'auto' }} spacing={1} direction={'column'} alignItems={'center'}>
|
||||
@@ -222,6 +165,104 @@ export default function FooterControls() {
|
||||
);
|
||||
}
|
||||
|
||||
function OverlayConversation({
|
||||
masterConversation,
|
||||
isSelected = false,
|
||||
}: {
|
||||
masterConversation: MasterConversation;
|
||||
isSelected?: boolean;
|
||||
}) {
|
||||
return (
|
||||
<Stack
|
||||
direction={'column'}
|
||||
spacing={1}
|
||||
sx={{
|
||||
p: 1,
|
||||
borderRadius: 2,
|
||||
bgcolor: isSelected ? blueGrey[300] : '',
|
||||
}}
|
||||
alignItems={'center'}
|
||||
>
|
||||
{/* status */}
|
||||
<Box
|
||||
component={'span'}
|
||||
sx={{
|
||||
bgcolor: (theme) => theme.palette.secondary.main,
|
||||
height: 5,
|
||||
width: 5,
|
||||
borderRadius: 100,
|
||||
}}
|
||||
/>
|
||||
|
||||
<AvatarGroup
|
||||
variant={'rounded'}
|
||||
sx={{
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
'& >:first-child': {
|
||||
marginTop: 0,
|
||||
},
|
||||
'& > *': {
|
||||
marginLeft: '0 !important' as any,
|
||||
marginTop: -2,
|
||||
},
|
||||
}}
|
||||
>
|
||||
{masterConversation.members?.map((conversationUser, index) => (
|
||||
<Avatar
|
||||
key={`${masterConversation._id.toString()}-${conversationUser._id.toString()}-convoIcon`}
|
||||
alt={conversationUser?.givenName}
|
||||
src={conversationUser?.picture}
|
||||
sx={{
|
||||
opacity: masterConversation.tunedInUsers?.includes(conversationUser._id.toString())
|
||||
? '100%'
|
||||
: '20%',
|
||||
}}
|
||||
/>
|
||||
))}
|
||||
</AvatarGroup>
|
||||
|
||||
{isSelected && (
|
||||
<>
|
||||
<Divider orientation="horizontal" flexItem />
|
||||
|
||||
<Tooltip title="Show video!">
|
||||
<IconButton
|
||||
sx={{
|
||||
color: 'white',
|
||||
}}
|
||||
size="small"
|
||||
>
|
||||
<FiVideoOff />
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
|
||||
{/* todo: not speaking mode, speaking mode, locked in mode */}
|
||||
<Tooltip title="Speak or toggle by clicking here!">
|
||||
<IconButton
|
||||
sx={{
|
||||
color: 'white',
|
||||
}}
|
||||
size="small"
|
||||
>
|
||||
<FiSun />
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
|
||||
<IconButton
|
||||
sx={{
|
||||
color: 'GrayText',
|
||||
}}
|
||||
size="small"
|
||||
>
|
||||
<FiX />
|
||||
</IconButton>
|
||||
</>
|
||||
)}
|
||||
</Stack>
|
||||
);
|
||||
}
|
||||
|
||||
const NO_DEVICE_SELECTION = 'NA';
|
||||
|
||||
function UserSettingsDialog({ open, handleClose }: { handleClose: () => void; open: boolean }) {
|
||||
|
||||
Reference in New Issue
Block a user