mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-14 05:14:54 +00:00
feat(core): simple recovery history ui poc (#5033)
Simple recovery history UI poc. What's missing - [x] e2e All biz logic should be done, excluding complete ui details. - [ ] offline prompt - [ ] history timeline - [ ] page ui https://github.com/toeverything/AFFiNE/assets/584378/fc3f6a48-ff7f-4265-b9f5-9c0087cb2635
This commit is contained in:
@@ -5,12 +5,15 @@ import type {
|
||||
QueryOptions,
|
||||
QueryResponse,
|
||||
QueryVariables,
|
||||
RecursiveMaybeFields,
|
||||
} from '@affine/graphql';
|
||||
import { gqlFetcherFactory } from '@affine/graphql';
|
||||
import { useAsyncCallback } from '@toeverything/hooks/affine-async-hooks';
|
||||
import type { GraphQLError } from 'graphql';
|
||||
import { useMemo } from 'react';
|
||||
import type { Key, SWRConfiguration, SWRResponse } from 'swr';
|
||||
import useSWR from 'swr';
|
||||
import useSWR, { useSWRConfig } from 'swr';
|
||||
import useSWRInfinite from 'swr/infinite';
|
||||
import type {
|
||||
SWRMutationConfiguration,
|
||||
SWRMutationResponse,
|
||||
@@ -86,6 +89,63 @@ export function useQuery<Query extends GraphQLQuery>(
|
||||
);
|
||||
}
|
||||
|
||||
export function useQueryInfinite<Query extends GraphQLQuery>(
|
||||
options: Omit<QueryOptions<Query>, 'variables'> & {
|
||||
getVariables: (
|
||||
pageIndex: number,
|
||||
previousPageData: QueryResponse<Query>
|
||||
) => QueryOptions<Query>['variables'];
|
||||
},
|
||||
config?: Omit<
|
||||
SWRConfiguration<
|
||||
QueryResponse<Query>,
|
||||
GraphQLError | GraphQLError[],
|
||||
typeof fetcher<Query>
|
||||
>,
|
||||
'fetcher'
|
||||
>
|
||||
) {
|
||||
const configWithSuspense: SWRConfiguration = useMemo(
|
||||
() => ({
|
||||
suspense: true,
|
||||
...config,
|
||||
}),
|
||||
[config]
|
||||
);
|
||||
|
||||
const { data, setSize, size, error } = useSWRInfinite<
|
||||
QueryResponse<Query>,
|
||||
GraphQLError | GraphQLError[]
|
||||
>(
|
||||
(pageIndex: number, previousPageData: QueryResponse<Query>) => [
|
||||
'cloud',
|
||||
options.query.id,
|
||||
options.getVariables(pageIndex, previousPageData),
|
||||
],
|
||||
async ([_, __, variables]) => {
|
||||
const params = { ...options, variables } as QueryOptions<Query>;
|
||||
return fetcher(params);
|
||||
},
|
||||
configWithSuspense
|
||||
);
|
||||
|
||||
const loadingMore = size > 0 && data && !data[size - 1];
|
||||
|
||||
// todo: find a generic way to know whether or not there are more items to load
|
||||
const loadMore = useAsyncCallback(async () => {
|
||||
if (loadingMore) {
|
||||
return;
|
||||
}
|
||||
await setSize(size => size + 1);
|
||||
}, [loadingMore, setSize]);
|
||||
return {
|
||||
data,
|
||||
error,
|
||||
loadingMore,
|
||||
loadMore,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* A useSWRMutation wrapper for sending graphql mutations
|
||||
*
|
||||
@@ -138,3 +198,32 @@ export function useMutation(
|
||||
}
|
||||
|
||||
export const gql = fetcher;
|
||||
|
||||
// use this to revalidate all queries that match the filter
|
||||
export const useMutateQueryResource = () => {
|
||||
const { mutate } = useSWRConfig();
|
||||
const revalidateResource = useMemo(
|
||||
() =>
|
||||
<Q extends GraphQLQuery>(
|
||||
query: Q,
|
||||
varsFilter: (
|
||||
vars: RecursiveMaybeFields<QueryVariables<Q>>
|
||||
) => boolean = _vars => true
|
||||
) => {
|
||||
return mutate(key => {
|
||||
const res =
|
||||
Array.isArray(key) &&
|
||||
key[0] === 'cloud' &&
|
||||
key[1] === query.id &&
|
||||
varsFilter(key[2]);
|
||||
if (res) {
|
||||
console.debug('revalidate resource', key);
|
||||
}
|
||||
return res;
|
||||
});
|
||||
},
|
||||
[mutate]
|
||||
);
|
||||
|
||||
return revalidateResource;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user