80 lines
2.6 KiB
TypeScript
80 lines
2.6 KiB
TypeScript
import { useSyncExternalStore } from "react";
|
|
import { useMutation, useQueryClient } from "@tanstack/react-query";
|
|
import { followUser, unfollowUser, buildCSRFHeaders } from "./ash_rpc";
|
|
|
|
// ── useIsDesktop ──────────────────────────────────────────────────────────────
|
|
// Returns true when viewport is wider than 960px. Reacts to resize.
|
|
|
|
const DESKTOP_MQ =
|
|
typeof window !== "undefined"
|
|
? window.matchMedia("(min-width: 961px)")
|
|
: null;
|
|
|
|
function subscribe(cb: () => void) {
|
|
DESKTOP_MQ?.addEventListener("change", cb);
|
|
return () => DESKTOP_MQ?.removeEventListener("change", cb);
|
|
}
|
|
|
|
export function useIsDesktop(): boolean {
|
|
return useSyncExternalStore(
|
|
subscribe,
|
|
() => DESKTOP_MQ?.matches ?? true,
|
|
() => true,
|
|
);
|
|
}
|
|
|
|
// ── useFollowUser ─────────────────────────────────────────────────────────────
|
|
|
|
export function useFollowUser(targetUserId: string) {
|
|
const qc = useQueryClient();
|
|
|
|
const followMutation = useMutation({
|
|
mutationFn: async () => {
|
|
const res = await followUser({
|
|
input: { followingId: targetUserId },
|
|
headers: buildCSRFHeaders(),
|
|
});
|
|
if (!res.success) {
|
|
const message =
|
|
"errors" in res && Array.isArray(res.errors)
|
|
? (res.errors[0] as any)?.message
|
|
: "Follow failed";
|
|
throw new Error(message);
|
|
}
|
|
return res;
|
|
},
|
|
onSuccess: () => {
|
|
qc.invalidateQueries({ queryKey: ["users"] });
|
|
qc.invalidateQueries({ queryKey: ["user", targetUserId] });
|
|
},
|
|
});
|
|
|
|
const unfollowMutation = useMutation({
|
|
mutationFn: async () => {
|
|
const res = await unfollowUser({
|
|
input: { followingId: targetUserId },
|
|
headers: buildCSRFHeaders(),
|
|
});
|
|
if (!res.success) {
|
|
const message =
|
|
"errors" in res && Array.isArray(res.errors)
|
|
? (res.errors[0] as any)?.message
|
|
: "Unfollow failed";
|
|
throw new Error(message);
|
|
}
|
|
return res;
|
|
},
|
|
onSuccess: () => {
|
|
qc.invalidateQueries({ queryKey: ["users"] });
|
|
qc.invalidateQueries({ queryKey: ["user", targetUserId] });
|
|
},
|
|
});
|
|
|
|
return {
|
|
follow: () => followMutation.mutate(),
|
|
unfollow: () => unfollowMutation.mutate(),
|
|
isPending: followMutation.isPending || unfollowMutation.isPending,
|
|
error: followMutation.error || unfollowMutation.error,
|
|
};
|
|
}
|