Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 | 81x 149x 149x 149x 149x 81x 1578x 1578x 1578x 1578x 1578x 1578x 145x 145x 1578x 4x 4x 4x 4x 4x | import React from "react";
import type { SkipToken } from "@tanstack/react-query";
import { useSuspenseQuery } from "@tanstack/react-query";
import type {
TRPCDecoratedInfiniteQueryProcedure,
TRPCInfiniteQueryKey,
} from "~app/trpc";
import type { SearchParamState } from "~app/utils/navigation";
import { updateSetStateAction } from "~utils/react";
const validateOffset = ({
limit,
offset,
count,
}: {
limit: number;
offset: number;
count: number;
}) => {
const maxOffset = count === 0 ? 0 : (Math.ceil(count / limit) - 1) * limit;
Iif (offset > maxOffset) {
return maxOffset;
}
Iif (offset % limit !== 0) {
return Math.floor(offset / limit) * limit;
}
return offset;
};
export const useCursorPaging = <
K extends TRPCInfiniteQueryKey,
P extends TRPCDecoratedInfiniteQueryProcedure<K> =
TRPCDecoratedInfiniteQueryProcedure<K>,
I extends Exclude<Parameters<P["queryOptions"]>[0], SkipToken> = Exclude<
Parameters<P["queryOptions"]>[0],
SkipToken
>,
>(
procedure: P,
input: Omit<I, "cursor">,
offsetState: SearchParamState<"/_protected/receipts/", "offset">,
) => {
const { limit } = input;
const [offset, setOffset] = offsetState;
const deferredOffset = React.useDeferredValue(offset);
const { data } = useSuspenseQuery(
// This is hacky, but I couldn't manage types here
(
procedure as TRPCDecoratedInfiniteQueryProcedure<"peers.getPaged">
).queryOptions({ ...input, cursor: deferredOffset }),
);
const { count } = data;
React.useEffect(() => {
// This affect helps with invalid navigations / limit changes
const validatedOffset = validateOffset({ offset, limit, count });
Iif (validatedOffset !== offset) {
setOffset(validatedOffset);
}
}, [count, limit, offset, setOffset]);
return {
data: data as P["~types"]["output"],
onPageChange: React.useCallback<
React.Dispatch<React.SetStateAction<number>>
>(
(setStateAction: React.SetStateAction<number>) =>
setOffset((prevOffset) => {
const prevPage = Math.floor(prevOffset / limit) + 1;
const nextPage = updateSetStateAction(setStateAction, prevPage);
const nextOffset = (nextPage - 1) * limit;
return validateOffset({ offset: nextOffset, limit, count });
}),
[setOffset, limit, count],
),
isPending: deferredOffset !== offset,
};
};
|