client/packages/user/src/context.tsx
Alois 55da8026a7
All checks were successful
/ build-web (push) Successful in 1m12s
/ build-desktop (push) Successful in 11m51s
/ build-mobile (push) Successful in 16m33s
/ release (push) Successful in 23s
(feat): add profile page
(feat): show user online-status
(feat): make markdown input more modular
2026-05-16 14:41:43 +02:00

91 lines
2.2 KiB
TypeScript

import * as React from "react";
import { useTTP } from "@tensamin/ttp";
import { ttp as schemas } from "@tensamin/shared/data";
import type z from "zod";
export type User = z.infer<typeof schemas.get_user_data.response>;
interface contextValue {
get(userId: number): Promise<User>;
}
const UserContext = React.createContext<contextValue | undefined>(undefined);
/**
* Executes UserProvider.
* @param props Parameter props.
* @returns unknown.
*/
export default function UserProvider(props: { children: React.ReactNode }) {
const storageRef = React.useRef<Record<number, User>>({});
const pendingRef = React.useRef<Record<number, Promise<User> | undefined>>(
{},
);
const { send } = useTTP();
/**
* Executes get.
* @param userId Parameter userId.
* @returns Promise<User>.
*/
const get = React.useCallback(
async (userId: number): Promise<User> => {
if (userId == null) {
throw new Error("userId is required");
}
const cachedUser = storageRef.current[userId];
if (cachedUser !== undefined) {
return cachedUser;
}
const pendingUser = pendingRef.current[userId];
if (pendingUser !== undefined) {
return pendingUser;
}
const request = (async () => {
const userData = await send("get_user_data", { user_id: userId });
const user = {
...userData.data,
avatar: userData.data.avatar
? `data:image/webp;base64,${atob(userData.data.avatar)}`
: undefined,
};
storageRef.current[userId] = user;
return user;
})();
pendingRef.current[userId] = request;
try {
return await request;
} finally {
delete pendingRef.current[userId];
}
},
[send],
);
return (
<UserContext.Provider value={{ get }}>
{props.children}
</UserContext.Provider>
);
}
/**
* Executes useUser.
* @param none This function has no parameters.
* @returns contextValue.
*/
export function useUser(): contextValue {
const context = React.useContext(UserContext);
if (!context) {
throw new Error("useUser must be used within a UserProvider");
}
return context;
}