mirror of
https://github.com/block/buzz.git
synced 2026-11-13 21:01:53 +00:00
108 lines
2.8 KiB
TypeScript
108 lines
2.8 KiB
TypeScript
import { useEffect } from "react";
|
|
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
|
|
|
|
import {
|
|
getProfile,
|
|
searchUsers,
|
|
getUserProfile,
|
|
getUsersBatch,
|
|
updateProfile,
|
|
} from "@/shared/api/tauri";
|
|
import type {
|
|
Profile,
|
|
UpdateProfileInput,
|
|
UserSearchResult,
|
|
UsersBatchResponse,
|
|
} from "@/shared/api/types";
|
|
|
|
export const profileQueryKey = ["profile"] as const;
|
|
|
|
export function useProfileQuery(enabled = true) {
|
|
return useQuery({
|
|
enabled,
|
|
queryKey: profileQueryKey,
|
|
queryFn: getProfile,
|
|
staleTime: 30_000,
|
|
});
|
|
}
|
|
|
|
export function useUserProfileQuery(pubkey?: string) {
|
|
return useQuery({
|
|
enabled: typeof pubkey === "string" && pubkey.length > 0,
|
|
queryKey: ["user-profile", pubkey?.toLowerCase() ?? ""],
|
|
queryFn: () => getUserProfile(pubkey),
|
|
staleTime: 60_000,
|
|
});
|
|
}
|
|
|
|
export function useUsersBatchQuery(
|
|
pubkeys: string[],
|
|
options?: {
|
|
enabled?: boolean;
|
|
},
|
|
) {
|
|
const queryClient = useQueryClient();
|
|
const normalizedPubkeys = [
|
|
...new Set(pubkeys.map((pubkey) => pubkey.toLowerCase())),
|
|
]
|
|
.filter((pubkey) => pubkey.length > 0)
|
|
.sort();
|
|
const enabled = (options?.enabled ?? true) && normalizedPubkeys.length > 0;
|
|
|
|
const query = useQuery<UsersBatchResponse>({
|
|
enabled,
|
|
queryKey: ["users-batch", ...normalizedPubkeys],
|
|
queryFn: () => getUsersBatch(normalizedPubkeys),
|
|
staleTime: 60_000,
|
|
gcTime: 5 * 60 * 1_000,
|
|
});
|
|
|
|
// Seed individual "user-profile" cache entries so avatar clicks are instant
|
|
// cache hits instead of fresh network requests.
|
|
useEffect(() => {
|
|
const profiles = query.data?.profiles;
|
|
if (!profiles) return;
|
|
for (const [pubkey, summary] of Object.entries(profiles)) {
|
|
queryClient.setQueryData<Profile>(
|
|
["user-profile", pubkey],
|
|
(existing) => existing ?? { pubkey, about: null, ...summary },
|
|
);
|
|
}
|
|
}, [query.data, queryClient]);
|
|
|
|
return query;
|
|
}
|
|
|
|
export function useUserSearchQuery(
|
|
query: string,
|
|
options?: {
|
|
enabled?: boolean;
|
|
limit?: number;
|
|
},
|
|
) {
|
|
const normalizedQuery = query.trim().toLowerCase();
|
|
const enabled = (options?.enabled ?? true) && normalizedQuery.length > 0;
|
|
|
|
return useQuery<UserSearchResult[]>({
|
|
enabled,
|
|
queryKey: ["user-search", normalizedQuery, options?.limit ?? 8],
|
|
queryFn: () => searchUsers(normalizedQuery, options?.limit ?? 8),
|
|
staleTime: 30_000,
|
|
gcTime: 5 * 60 * 1_000,
|
|
});
|
|
}
|
|
|
|
export function useUpdateProfileMutation() {
|
|
const queryClient = useQueryClient();
|
|
|
|
return useMutation({
|
|
mutationFn: (input: UpdateProfileInput) => updateProfile(input),
|
|
onSuccess: (profile: Profile) => {
|
|
queryClient.setQueryData(profileQueryKey, profile);
|
|
},
|
|
onSettled: async () => {
|
|
await queryClient.invalidateQueries({ queryKey: profileQueryKey });
|
|
},
|
|
});
|
|
}
|