race condition with search and firebase initializing
This commit is contained in:
@@ -9,7 +9,6 @@ import { NirvanaTheme } from './mui/NirvanaTheme';
|
||||
import { ElectronProvider } from './providers/ElectronProvider';
|
||||
import { AuthProvider } from './providers/AuthProvider';
|
||||
|
||||
import './firebase/connect';
|
||||
import ErrorParent from './providers/ErrorBoundary';
|
||||
|
||||
const root = ReactDOM.createRoot(document.getElementById('root') as HTMLElement);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, { useCallback, useRef } from 'react';
|
||||
import React, { useCallback, useRef, useState } from 'react';
|
||||
|
||||
import {
|
||||
Avatar,
|
||||
@@ -17,21 +17,37 @@ import {
|
||||
import { blueGrey } from '@mui/material/colors';
|
||||
import { FiActivity, FiInbox, FiSearch } from 'react-icons/fi';
|
||||
import NirvanaAvatar from './NirvanaAvatar';
|
||||
import { useKey } from 'react-use';
|
||||
import { useDebounce, useKey } from 'react-use';
|
||||
import { useSnackbar } from 'notistack';
|
||||
import KeyboardShortcutLabel from './KeyboardShortcutLabel';
|
||||
import { searchUsers, User } from '../firebase/firestore';
|
||||
|
||||
const Conversations = () => {
|
||||
const { enqueueSnackbar } = useSnackbar();
|
||||
|
||||
const searchRef = useRef<HTMLInputElement>(null);
|
||||
const [searchVal, setSearchVal] = useState<string>('');
|
||||
|
||||
const onSearch = useCallback(() => {
|
||||
const onSearchFocus = useCallback(() => {
|
||||
enqueueSnackbar('search focused');
|
||||
if (searchRef?.current) searchRef.current.focus();
|
||||
}, []);
|
||||
}, [enqueueSnackbar, searchRef]);
|
||||
|
||||
useKey('Shift', onSearch);
|
||||
const [searchUsersResults, setSearchUsersResults] = useState<User[]>([]);
|
||||
|
||||
useKey('Shift', onSearchFocus);
|
||||
|
||||
const [, cancel] = useDebounce(
|
||||
async () => {
|
||||
if (searchVal) {
|
||||
enqueueSnackbar('searching...', { variant: 'info' });
|
||||
|
||||
setSearchUsersResults(await searchUsers(searchVal));
|
||||
}
|
||||
},
|
||||
500,
|
||||
[searchVal, enqueueSnackbar, setSearchUsersResults],
|
||||
);
|
||||
|
||||
return (
|
||||
<>
|
||||
@@ -51,11 +67,18 @@ const Conversations = () => {
|
||||
>
|
||||
<FiSearch style={{ color: blueGrey[500] }} />
|
||||
|
||||
<Input placeholder={'Find or start a conversation'} inputRef={searchRef} />
|
||||
<Input
|
||||
onChange={(e) => setSearchVal(e.target.value)}
|
||||
value={searchVal}
|
||||
placeholder={'Find or start a conversation'}
|
||||
inputRef={searchRef}
|
||||
/>
|
||||
|
||||
<KeyboardShortcutLabel label="Shift" />
|
||||
</Stack>
|
||||
|
||||
{searchVal && <ListPeople people={searchUsersResults} />}
|
||||
|
||||
<List
|
||||
sx={{
|
||||
pt: 2,
|
||||
@@ -149,4 +172,39 @@ const Conversations = () => {
|
||||
);
|
||||
};
|
||||
|
||||
function ListPeople({ people }: { people: User[] }) {
|
||||
return (
|
||||
<List
|
||||
sx={{
|
||||
pt: 2,
|
||||
}}
|
||||
subheader={
|
||||
<ListSubheader>
|
||||
<FiActivity />
|
||||
<Typography variant="subtitle2"> Priority</Typography>
|
||||
</ListSubheader>
|
||||
}
|
||||
>
|
||||
{people.length === 0 && (
|
||||
<Typography variant="caption">
|
||||
Sorry please try someone else or invite them to nirvana.
|
||||
</Typography>
|
||||
)}
|
||||
|
||||
{people.map((person) => (
|
||||
<ListItem key={`${person.uid}-searchUsers`}>
|
||||
<ListItemButton selected={true}>
|
||||
<ListItemAvatar>
|
||||
<Avatar alt={person.displayName} src={person.photoUrl} />
|
||||
</ListItemAvatar>
|
||||
|
||||
<ListItemText primary={person.displayName} />
|
||||
|
||||
<Typography variant={'caption'}>20 sec</Typography>
|
||||
</ListItemButton>
|
||||
</ListItem>
|
||||
))}
|
||||
</List>
|
||||
);
|
||||
}
|
||||
export default Conversations;
|
||||
|
||||
@@ -12,4 +12,4 @@ export const firebaseApp = initializeApp(devConfig);
|
||||
export const firebaseAuth = getAuth(firebaseApp);
|
||||
|
||||
// Initialize Cloud Firestore and get a reference to the service
|
||||
export const firestore = getFirestore(firebaseApp);
|
||||
export const firestoreDb = getFirestore(firebaseApp);
|
||||
|
||||
@@ -8,9 +8,14 @@ import {
|
||||
QueryDocumentSnapshot,
|
||||
Timestamp,
|
||||
FieldValue,
|
||||
getDoc,
|
||||
query,
|
||||
where,
|
||||
getDocs,
|
||||
} from 'firebase/firestore';
|
||||
|
||||
import { User as FirebaseUser } from 'firebase/auth';
|
||||
import { firestoreDb } from './connect';
|
||||
|
||||
/**
|
||||
* UTILS
|
||||
@@ -20,11 +25,15 @@ const converter = <T>() => ({
|
||||
fromFirestore: (snap: QueryDocumentSnapshot) => snap.data() as T,
|
||||
});
|
||||
|
||||
const dataPoint = <T>(collectionPath: string) =>
|
||||
doc(getFirestore(), collectionPath).withConverter(converter<T>());
|
||||
const docPoint = <T>(collectionPath: string) =>
|
||||
firestoreDb && doc(getFirestore(), collectionPath).withConverter(converter<T>());
|
||||
|
||||
const collectionPoint = <T>(collectionPath: string) =>
|
||||
firestoreDb && collection(getFirestore(), collectionPath).withConverter(converter<T>());
|
||||
|
||||
const db = {
|
||||
user: (userId: string) => dataPoint<User>(`users/${userId}`),
|
||||
users: collectionPoint<User>(`users`),
|
||||
user: (userId: string) => docPoint<User>(`users/${userId}`),
|
||||
};
|
||||
|
||||
export class User {
|
||||
@@ -65,3 +74,31 @@ export const createUser = async (user: FirebaseUser) => {
|
||||
throw new Error('Error creating user');
|
||||
}
|
||||
};
|
||||
|
||||
export const searchUsers = async (searchQuery: string): Promise<User[] | undefined> => {
|
||||
try {
|
||||
const emaildocSearchQuery = query(
|
||||
db.users,
|
||||
where('email', '>=', searchQuery.toUpperCase()),
|
||||
where('email', '<=', searchQuery.toUpperCase() + '\uf8ff'),
|
||||
);
|
||||
|
||||
const nameSearchQuery = query(
|
||||
db.users,
|
||||
where('displayName', '>=', searchQuery.toUpperCase()),
|
||||
where('displayName', '<=', searchQuery.toUpperCase() + '\uf8ff'),
|
||||
);
|
||||
|
||||
const emailquerySnap = await getDocs(emaildocSearchQuery);
|
||||
const namequerySnap = await getDocs(nameSearchQuery);
|
||||
|
||||
return [
|
||||
...emailquerySnap.docs.map((doc) => doc.data()),
|
||||
...namequerySnap.docs.map((doc) => doc.data()),
|
||||
];
|
||||
} catch (e) {
|
||||
console.error('Error: ', e);
|
||||
|
||||
throw new Error('Error');
|
||||
}
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user