Polish mobile and web experience

This commit is contained in:
2026-08-17 00:18:55 -04:00
parent 6c74436092
commit 9929d7321d
28 changed files with 835 additions and 688 deletions
+34
View File
@@ -0,0 +1,34 @@
import { useCallback, useState } from "react";
import { RefreshControl, type RefreshControlProps } from "react-native";
type PullToRefreshProps = Omit<RefreshControlProps, "onRefresh" | "refreshing"> & {
onRefresh: () => Promise<unknown> | unknown;
};
/**
* Keeps the native refresh indicator tied to an actual pull gesture.
* Query `isRefetching` also covers background polling and invalidations, which
* can repeatedly move an offscreen iOS scroll view when used as `refreshing`.
*/
export function PullToRefresh({ onRefresh, ...props }: PullToRefreshProps) {
const [refreshing, setRefreshing] = useState(false);
const handleRefresh = useCallback(async () => {
if (refreshing) return;
setRefreshing(true);
try {
await onRefresh();
} finally {
setRefreshing(false);
}
}, [onRefresh, refreshing]);
return (
<RefreshControl
{...props}
refreshing={refreshing}
onRefresh={() => void handleRefresh()}
/>
);
}