caching relevant users for my disposal and starting to render content
This commit is contained in:
@@ -1,24 +1,15 @@
|
|||||||
import Conversation from "@nirvana/common/models/conversation";
|
import Conversation from "@nirvana/common/models/conversation";
|
||||||
import { Avatar } from "antd";
|
import { Avatar } from "antd";
|
||||||
import { FaWalking } from "react-icons/fa";
|
import { FaWalking } from "react-icons/fa";
|
||||||
|
import { MasterAvatarGroupWithUserFetch } from "../UserDetails/MasterAvatarGroup";
|
||||||
|
|
||||||
export default function LiveRoom(props: { conversation: Conversation }) {
|
export default function LiveRoom(props: { conversation: Conversation }) {
|
||||||
return (
|
return (
|
||||||
<span className="group relative flex flex-row items-center bg-slate-50 rounded-lg border p-5 animate-pulse">
|
<span className="group relative flex flex-row items-center bg-slate-50 rounded-lg border p-5 animate-pulse">
|
||||||
<Avatar.Group
|
<MasterAvatarGroupWithUserFetch
|
||||||
maxCount={3}
|
listOfUserIds={props.conversation.membersInLiveRoom}
|
||||||
size={{ xs: 1000 }}
|
showCurrUser={true}
|
||||||
maxStyle={{ color: "#f56a00", backgroundColor: "#fde3cf" }}
|
/>
|
||||||
>
|
|
||||||
<Avatar
|
|
||||||
src="https://joeschmoe.io/api/v1/random"
|
|
||||||
style={{ backgroundColor: "cyan" }}
|
|
||||||
/>
|
|
||||||
<Avatar src="https://joeschmoe.io/api/v1/100" />
|
|
||||||
<Avatar src="https://joeschmoe.io/api/v1/2" />
|
|
||||||
<Avatar src="https://joeschmoe.io/api/v1/10" />
|
|
||||||
<Avatar src="https://joeschmoe.io/api/v1/8" />
|
|
||||||
</Avatar.Group>
|
|
||||||
|
|
||||||
<span className="text-md font-semibold ml-2 mr-10">Engineering</span>
|
<span className="text-md font-semibold ml-2 mr-10">Engineering</span>
|
||||||
|
|
||||||
|
|||||||
@@ -3,9 +3,15 @@ import { useAuth } from "../../contexts/authContext";
|
|||||||
import { useRecoilValue, useRecoilState } from "recoil";
|
import { useRecoilValue, useRecoilState } from "recoil";
|
||||||
import { allRelevantContactsAtom } from "../../recoil/main";
|
import { allRelevantContactsAtom } from "../../recoil/main";
|
||||||
import { userService } from "@nirvana/common/services";
|
import { userService } from "@nirvana/common/services";
|
||||||
|
import { Avatar } from "antd";
|
||||||
|
|
||||||
export default function MasterAvatarGroup(props: { listOfUsers: User[] }) {
|
const AVATAR_SHAPE = "square";
|
||||||
const contactsMap = useRecoilValue(allRelevantContactsAtom);
|
|
||||||
|
export default function MasterAvatarGroup(props: {
|
||||||
|
listOfUsers: User[];
|
||||||
|
showCurrUser?: boolean;
|
||||||
|
}) {
|
||||||
|
const { currUser } = useAuth();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Requirements:
|
* Requirements:
|
||||||
@@ -15,46 +21,100 @@ export default function MasterAvatarGroup(props: { listOfUsers: User[] }) {
|
|||||||
* if 6 more 'other' people, then show 3 and then one circle saying how many more there are
|
* if 6 more 'other' people, then show 3 and then one circle saying how many more there are
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const { currUser } = useAuth();
|
let finalistUsers: User[] = props.listOfUsers;
|
||||||
|
|
||||||
const listOfOtherUsers = props.listOfUsers.filter(
|
if (!props.showCurrUser) {
|
||||||
(lUser) => lUser.id != currUser!.uid
|
finalistUsers = props.listOfUsers.filter(
|
||||||
);
|
(lUser) => lUser.id != currUser!.uid
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// these are the finalists, so now show all of them depending on the number
|
||||||
|
if (finalistUsers?.length == 1) {
|
||||||
|
return (
|
||||||
|
<Avatar
|
||||||
|
key={finalistUsers[0].id}
|
||||||
|
src={finalistUsers[0].avatarUrl}
|
||||||
|
shape={AVATAR_SHAPE}
|
||||||
|
size={"large"}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (finalistUsers?.length == 2) {
|
||||||
|
return (
|
||||||
|
<span className="flex flex-row items-center w-[4rem] relative">
|
||||||
|
<span className="absolute left-0">
|
||||||
|
<Avatar
|
||||||
|
key={finalistUsers[0].id}
|
||||||
|
src={finalistUsers[0].avatarUrl}
|
||||||
|
shape={AVATAR_SHAPE}
|
||||||
|
size={"default"}
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
|
<span className="absolute right-0">
|
||||||
|
<Avatar
|
||||||
|
key={finalistUsers[1].id}
|
||||||
|
src={finalistUsers[1].avatarUrl}
|
||||||
|
shape={AVATAR_SHAPE}
|
||||||
|
size={"default"}
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<span>
|
<Avatar.Group
|
||||||
{listOfOtherUsers.map((oUser) => (
|
maxCount={2}
|
||||||
<img key={oUser.id} src={oUser.avatarUrl} />
|
size="default"
|
||||||
|
maxStyle={{
|
||||||
|
color: "rgb(203 213 225)",
|
||||||
|
fontSize: "10px",
|
||||||
|
backgroundColor: "rgb(248 250 252)",
|
||||||
|
borderRadius: 0,
|
||||||
|
}}
|
||||||
|
className="bg-slate-50 text-slate-300"
|
||||||
|
>
|
||||||
|
{finalistUsers.map((oUser) => (
|
||||||
|
<Avatar
|
||||||
|
key={oUser.id}
|
||||||
|
src={oUser.avatarUrl}
|
||||||
|
shape={AVATAR_SHAPE}
|
||||||
|
size={"default"}
|
||||||
|
/>
|
||||||
))}
|
))}
|
||||||
</span>
|
</Avatar.Group>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function MasterAvatarGroupWithUserFetch(props: {
|
export function MasterAvatarGroupWithUserFetch(props: {
|
||||||
listOfUserIds: string[];
|
listOfUserIds: string[];
|
||||||
|
showCurrUser?: boolean;
|
||||||
}) {
|
}) {
|
||||||
const [contactsMap, setContactsMap] = useRecoilState(allRelevantContactsAtom);
|
const relContactsMap = useRecoilValue(allRelevantContactsAtom);
|
||||||
|
|
||||||
const { currUser } = useAuth();
|
const { currUser } = useAuth();
|
||||||
|
|
||||||
const listOfOtherUsers = props.listOfUserIds.filter(
|
let listOfOtherUsers: string[] = [] as string[];
|
||||||
(lUser) => lUser != currUser!.uid
|
if (props.showCurrUser) {
|
||||||
);
|
listOfOtherUsers = props.listOfUserIds;
|
||||||
|
} else {
|
||||||
|
listOfOtherUsers = props.listOfUserIds.filter(
|
||||||
|
(lUser) => lUser != currUser!.uid
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
const resultUsers: User[] = [] as User[];
|
const resultUsers: User[] = [] as User[];
|
||||||
|
|
||||||
listOfOtherUsers.forEach(async (oUser) => {
|
console.log(listOfOtherUsers);
|
||||||
if (contactsMap.has(oUser) && contactsMap.get(oUser) instanceof User) {
|
listOfOtherUsers.forEach((oUser) => {
|
||||||
resultUsers.push(contactsMap.get(oUser)!);
|
if (relContactsMap.has(oUser)) {
|
||||||
} else {
|
resultUsers.push(relContactsMap.get(oUser)!);
|
||||||
// otherwise, fetch document from firestore and then set the cache
|
|
||||||
const retrievedUser = await userService.getUser(oUser);
|
|
||||||
|
|
||||||
if (retrievedUser) {
|
|
||||||
setContactsMap(new Map(contactsMap.set(oUser, retrievedUser)));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
return <MasterAvatarGroup listOfUsers={resultUsers} />;
|
console.log("fetched users for frontend: ", resultUsers);
|
||||||
|
|
||||||
|
return <MasterAvatarGroup listOfUsers={resultUsers} {...props} />;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,15 +15,18 @@ import {
|
|||||||
} from "firebase/firestore";
|
} from "firebase/firestore";
|
||||||
import { useEffect } from "react";
|
import { useEffect } from "react";
|
||||||
import toast from "react-hot-toast";
|
import toast from "react-hot-toast";
|
||||||
import { useRecoilState } from "recoil";
|
import { useRecoilState, useSetRecoilState } from "recoil";
|
||||||
import { useAuth } from "../contexts/authContext";
|
import { useAuth } from "../contexts/authContext";
|
||||||
import {
|
import {
|
||||||
|
allRelevantContactsAtom,
|
||||||
allRelevantConversationsAtom,
|
allRelevantConversationsAtom,
|
||||||
allUsersConversationsAtom,
|
allUsersConversationsAtom,
|
||||||
|
cachedRelevantContactsSelector,
|
||||||
nirvanaUserDataAtom,
|
nirvanaUserDataAtom,
|
||||||
} from "./main";
|
} from "./main";
|
||||||
|
|
||||||
import { firestoreDb as db } from "../services/firebaseService";
|
import { firestoreDb as db } from "../services/firebaseService";
|
||||||
|
import { userService } from "@nirvana/common/services";
|
||||||
|
|
||||||
export default function MainRecoilDataHandler() {
|
export default function MainRecoilDataHandler() {
|
||||||
const { currUser } = useAuth();
|
const { currUser } = useAuth();
|
||||||
@@ -34,6 +37,8 @@ export default function MainRecoilDataHandler() {
|
|||||||
allRelevantConversationsAtom
|
allRelevantConversationsAtom
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const [relContacts, setRelContacts] = useRecoilState(allRelevantContactsAtom);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const unsubs: Unsubscribe[] = [] as Unsubscribe[];
|
const unsubs: Unsubscribe[] = [] as Unsubscribe[];
|
||||||
|
|
||||||
@@ -120,6 +125,40 @@ export default function MainRecoilDataHandler() {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// build user's cache
|
||||||
|
let allUsersToCache: string[] = [] as string[];
|
||||||
|
|
||||||
|
arrayConvos.forEach((currconvo) => {
|
||||||
|
allUsersToCache = [...allUsersToCache, ...currconvo.activeMembers];
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log(
|
||||||
|
"going to try caching a bunch of users...maybe some duplicates",
|
||||||
|
allUsersToCache
|
||||||
|
);
|
||||||
|
|
||||||
|
// if this userId is in the contacts map, then cool
|
||||||
|
// otherwise fetch with userService
|
||||||
|
|
||||||
|
allUsersToCache.map(async (oUser) => {
|
||||||
|
if (
|
||||||
|
relContacts.has(oUser) &&
|
||||||
|
relContacts.get(oUser) instanceof User
|
||||||
|
) {
|
||||||
|
// do nothing
|
||||||
|
|
||||||
|
console.log("user already cached, no need to re-cache");
|
||||||
|
} else {
|
||||||
|
// otherwise, fetch document from firestore and then set the cache
|
||||||
|
const retrievedUser = await userService.getUser(oUser);
|
||||||
|
console.log("fetching user to add to cache");
|
||||||
|
|
||||||
|
if (retrievedUser) {
|
||||||
|
setRelContacts(new Map(relContacts.set(oUser, retrievedUser)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// add to the main convos atom, by modifying the current map
|
// add to the main convos atom, by modifying the current map
|
||||||
setRelevantConvos((prevConvosMap) => {
|
setRelevantConvos((prevConvosMap) => {
|
||||||
const newMap = new Map(prevConvosMap);
|
const newMap = new Map(prevConvosMap);
|
||||||
|
|||||||
@@ -5,8 +5,9 @@ import Conversation, {
|
|||||||
Link,
|
Link,
|
||||||
} from "@nirvana/common/models/conversation";
|
} from "@nirvana/common/models/conversation";
|
||||||
import { User as NirvanaUser } from "@nirvana/common/models/user";
|
import { User as NirvanaUser } from "@nirvana/common/models/user";
|
||||||
|
import { userService } from "@nirvana/common/services";
|
||||||
|
|
||||||
import { atom, selector, selectorFamily } from "recoil";
|
import { atom, DefaultValue, selector, selectorFamily } from "recoil";
|
||||||
|
|
||||||
export enum RecoilActions {
|
export enum RecoilActions {
|
||||||
TEST = "TEST",
|
TEST = "TEST",
|
||||||
@@ -110,11 +111,18 @@ export const allRelevantContactsAtom = atom<Map<string, NirvanaUser>>({
|
|||||||
|
|
||||||
// todo: useful selector where a component can pass in a list of users
|
// todo: useful selector where a component can pass in a list of users
|
||||||
// and return their full information
|
// and return their full information
|
||||||
export const cachedRelevantContactsSelector = selector<NirvanaUser[]>({
|
export const cachedRelevantContactsSelector = selector<string[]>({
|
||||||
key: RecoilActions.RELEVANT_CONTACTS_SELECTOR_CACHE,
|
key: RecoilActions.RELEVANT_CONTACTS_SELECTOR_CACHE,
|
||||||
get: async ({ get }) => {
|
get: async ({ get }) => {
|
||||||
const currContacts: Map<string, NirvanaUser> = get(allRelevantContactsAtom);
|
|
||||||
return [];
|
return [];
|
||||||
},
|
},
|
||||||
// selector set (pass in a user and build cache if somethings not in the cache already)
|
// selector set (pass in a user and build cache if somethings not in the cache already)
|
||||||
|
set: async ({ set, get }, listUserIdsToCache: string[]) => {
|
||||||
|
if (listUserIdsToCache instanceof DefaultValue) {
|
||||||
|
// set(newUserToCache)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const contactsMap = get(allRelevantContactsAtom);
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user