import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'; import { useClient } from 'hooks/useClient'; const KEY = ['soulseek', 'favorites'] as const; const EMPTY: string[] = []; /** * The owner's favourited Soulseek peers, backed by the officer-slskd sidecar's own `/_officer/favorites` * route (slskd has no favourites API — Officer owns that data). One shared react-query cache, so every * star in the workspace reflects the same state; toggling is optimistic and rolls back on failure. */ export function useSoulseekFavorites() { const { get, post, delete: del } = useClient(); const qc = useQueryClient(); const { data } = useQuery({ queryKey: KEY, queryFn: () => get('/soulseek/_officer/favorites'), staleTime: 60_000, }); const mutation = useMutation({ mutationFn: ({ on, username }: { on: boolean; username: string }) => on ? post('/soulseek/_officer/favorites', { username }) : del(`/soulseek/_officer/favorites?username=${encodeURIComponent(username)}`), onMutate: async ({ on, username }) => { await qc.cancelQueries({ queryKey: KEY }); const prev = qc.getQueryData(KEY) ?? EMPTY; const next = on ? [...prev, username].sort((a, b) => a.localeCompare(b)) : prev.filter((u) => u !== username); qc.setQueryData(KEY, next); return { prev }; }, onError: (_err, _vars, ctx) => { if (ctx?.prev) qc.setQueryData(KEY, ctx.prev); }, }); const favorites = data ?? EMPTY; const isFavorite = (username: string) => favorites.includes(username); const toggle = (username: string) => { if (!username) return; mutation.mutate({ on: !isFavorite(username), username }); }; return { favorites, isFavorite, toggle }; }