nice search and quick dial right there

This commit is contained in:
talksik
2022-06-11 13:50:36 -05:00
parent a1ffe5249c
commit 643b547bd0
4 changed files with 175 additions and 35 deletions
@@ -1,9 +1,10 @@
import { ConversationMap, MasterConversation } from '../util/types';
import React, { useCallback, useContext, useState } from 'react';
import Conversation from '@nirvana/core/models/conversation.model';
import { ConversationMap } from '../util/types';
import User from '@nirvana/core/models/user.model';
import useAuth from './AuthProvider';
import useConversations from './ConversationProvider';
import { useDebounce } from 'react-use';
import { userSearch } from '../api/NirvanaApi';
@@ -12,7 +13,7 @@ interface ISearchContext {
omniSearch?: (searchQuery: string) => void;
searchConversations?: (searchQuery: string) => void;
conversationResults: Conversation[];
conversationResults: MasterConversation[];
userResults: User[];
isSearching: boolean;
@@ -31,12 +32,12 @@ const SearchContext = React.createContext<ISearchContext>({
export function SearchProvider({ children }: { children: React.ReactNode }) {
const { user } = useAuth();
// const { conversationMap } = useConversations();
const { conversationMap } = useConversations();
const [searchQuery, setSearchQuery] = useState<string>('');
const [userResults, setUserResultsResults] = useState<User[]>([]);
const [conversationResults, setConversationResultsResults] = useState<Conversation[]>([]);
const [conversationResults, setConversationResultsResults] = useState<MasterConversation[]>([]);
const [isSearching, setIsSearching] = useState<boolean>(false);
// debounce user search and any other async ones
@@ -71,39 +72,39 @@ export function SearchProvider({ children }: { children: React.ReactNode }) {
*/
const searchRelevantConversations = useCallback(
async (searchQuery: string): Promise<Conversation[]> => {
const relevantConversations: Conversation[] = [];
async (searchQuery: string): Promise<MasterConversation[]> => {
const relevantConversations: MasterConversation[] = [];
// Object.values(conversationMap).forEach((conversation) => {
// for (const cachedConversationUser of conversation.userCache) {
// if (
// cachedConversationUser.email
// .toLocaleLowerCase()
// .includes(searchQuery.toLocaleLowerCase())
// ) {
// relevantConversations.push(conversation);
// return;
// }
Object.values(conversationMap).forEach((conversation) => {
for (const cachedConversationUser of conversation.members) {
if (
cachedConversationUser.email
.toLocaleLowerCase()
.includes(searchQuery.toLocaleLowerCase())
) {
relevantConversations.push(conversation);
return;
}
// if (
// cachedConversationUser.displayName
// .toLocaleLowerCase()
// .includes(searchQuery.toLocaleLowerCase())
// ) {
// relevantConversations.push(conversation);
// return;
// }
// }
if (
cachedConversationUser.name
.toLocaleLowerCase()
.includes(searchQuery.toLocaleLowerCase())
) {
relevantConversations.push(conversation);
return;
}
}
// if (conversation.name?.toLocaleLowerCase().includes(searchQuery.toLocaleLowerCase())) {
// relevantConversations.push(conversation);
// return;
// }
// });
if (conversation.name?.toLocaleLowerCase().includes(searchQuery.toLocaleLowerCase())) {
relevantConversations.push(conversation);
return;
}
});
return relevantConversations;
},
[],
[conversationMap],
);
const omniSearch = useCallback(
@@ -106,9 +106,11 @@ export function ConversationList() {
export function ConversationRow({
conversation,
index,
onClick,
}: {
conversation: MasterConversation;
index?: number;
onClick?: () => void;
}) {
const { user } = useAuth();
@@ -126,8 +128,12 @@ export function ConversationRow({
}, [index]);
const handleSelectConversation = useCallback(() => {
if (onClick) {
onClick();
}
selectConversation(conversation._id.toString(), false);
}, [conversation, selectConversation]);
}, [conversation, selectConversation, onClick]);
useKeyPressEvent(`${keyboardShortcut?.toString()}`, handleSelectConversation);
@@ -0,0 +1,131 @@
import {
Avatar,
List,
ListItem,
ListItemAvatar,
ListItemButton,
ListItemSecondaryAction,
ListItemText,
ListSubheader,
Tooltip,
Typography,
} from '@mui/material';
import React, { useCallback } from 'react';
import Conversation from '@nirvana/core/models/conversation.model';
import { ConversationRow } from './ConversationList';
import { FiZap } from 'react-icons/fi';
import User from '@nirvana/core/models/user.model';
import useConversations from '../providers/ConversationProvider';
import useSearch from '../providers/SearchProvider';
import useTerminal from './Terminal';
export default function OmniSearchResults() {
const { handleStartConversation } = useConversations();
const { userResults: people, conversationResults: conversations, clearSearch } = useSearch();
const handleQuickDial = useCallback(
async (otherUser: User) => {
const succeededDialed = await handleStartConversation([otherUser]);
if (succeededDialed) {
clearSearch();
}
},
[handleStartConversation, clearSearch],
);
return (
<>
<List
sx={{
pt: 2,
}}
subheader={
<ListSubheader
sx={{
display: 'flex',
justifyContent: 'center',
}}
>
<Typography align={'center'} variant="subtitle2">
People
</Typography>
</ListSubheader>
}
>
<ListItem
sx={{
display: 'flex',
justifyContent: 'center',
}}
>
{people.length === 0 && (
<Typography align="center" variant="caption">
{`Can't find someone? Invite them!`}
</Typography>
)}
</ListItem>
{people.map((person) => (
<Tooltip key={`${person._id.toString()}-searchUsers`} title={'quick dial'}>
<ListItem>
<ListItemButton onClick={() => handleQuickDial(person)}>
<ListItemAvatar>
<Avatar alt={person.givenName} src={person.picture} />
</ListItemAvatar>
<ListItemText primary={person.name} secondary={person.email} />
<ListItemSecondaryAction sx={{ color: 'GrayText' }}>
<FiZap />
</ListItemSecondaryAction>
</ListItemButton>
</ListItem>
</Tooltip>
))}
</List>
<List
sx={{
pt: 2,
}}
subheader={
<ListSubheader
sx={{
display: 'flex',
justifyContent: 'center',
}}
>
<Typography align={'center'} variant="subtitle2">
Conversations
</Typography>
</ListSubheader>
}
>
<ListItem
sx={{
display: 'flex',
justifyContent: 'center',
}}
>
{conversations.length === 0 && (
<Typography align="center" variant="caption">
{`Can't find a conversation? Just create one!`}
</Typography>
)}
</ListItem>
{conversations.map((conversation) => (
<Tooltip
key={`tooltip-${conversation._id.toString()}-searchConversations`}
title={'continue conversation'}
>
<ConversationRow conversation={conversation} onClick={clearSearch} />
</Tooltip>
))}
</List>
</>
);
}
+5 -3
View File
@@ -4,13 +4,17 @@ import { ConversationList } from './ConversationList';
import MainPanel from './MainPanel';
import Navbar from './Navbar';
import NewConversationDialog from './NewConversationDialog';
import OmniSearchResults from './OmniSearchResults';
import React from 'react';
import { blueGrey } from '@mui/material/colors';
import useRouter from '../providers/RouterProvider';
import useSearch from '../providers/SearchProvider';
export default function Terminal() {
const { page } = useRouter();
const { searchQuery } = useSearch();
return (
<Container
maxWidth={false}
@@ -36,9 +40,7 @@ export default function Terminal() {
>
<Navbar />
<Box sx={{ p: 2 }}>
<ConversationList />
</Box>
<Box sx={{ p: 2 }}>{searchQuery ? <OmniSearchResults /> : <ConversationList />}</Box>
</Grid>
<Grid