Skip to content

Commit 6a82fcc

Browse files
authored
Merge pull request #613 from subquery/fix/update-exist-project
feat: update system
2 parents 85a735a + e27b55b commit 6a82fcc

File tree

1 file changed

+63
-76
lines changed

1 file changed

+63
-76
lines changed

src/hooks/useLocalProjects.ts

Lines changed: 63 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,17 @@ import { useProjectMetadata } from '@containers';
66
import { ProjectFieldsFragment, ProjectsOrderBy } from '@subql/network-query';
77
import { useGetProjectsLazyQuery } from '@subql/react-hooks';
88
import { notEmpty } from '@utils';
9-
import { filterSuccessPromoiseSettledResult } from '@utils';
109
import { makeCacheKey } from '@utils/limitation';
1110
import { waitForSomething } from '@utils/waitForSomething';
12-
import { useInterval, useMount } from 'ahooks';
11+
import { useMount } from 'ahooks';
1312
import localforage from 'localforage';
1413
import { uniqWith } from 'lodash-es';
14+
import { cloneDeep } from 'lodash-es';
1515

1616
const cacheKey = makeCacheKey('localProjectWithMetadata');
1717

18+
type ProjectWithMetadata = { description: string; versionDescription: string; name: string } & ProjectFieldsFragment;
19+
1820
export const useLocalProjects = () => {
1921
// this hooks want to do these things:
2022
// 1. Get all projects order by order
@@ -35,66 +37,80 @@ export const useLocalProjects = () => {
3537
});
3638
const { getMetadataFromCid } = useProjectMetadata();
3739

38-
const projects = useRef<
39-
({ description: string; versionDescription: string; name: string } & ProjectFieldsFragment)[]
40-
>([]);
40+
const projects = useRef<ProjectWithMetadata[]>([]);
4141

42-
const fetchAllProjects = async (length = 0) => {
43-
try {
44-
loading.current = true;
42+
const fetchAllProjects = async (cachedProjects?: ProjectWithMetadata[], withLoading = true) => {
43+
const innerFetch: (fetchedProjects: ProjectWithMetadata[]) => Promise<ProjectWithMetadata[]> = async (
44+
fetchedProjects,
45+
) => {
46+
let tempProjects = cloneDeep(fetchedProjects) || [];
4547

46-
const res = await getProjects({
47-
variables: {
48-
offset: length,
49-
orderBy: [ProjectsOrderBy.ID_ASC],
50-
ids: [],
51-
},
52-
defaultOptions: {
53-
fetchPolicy: 'network-only',
54-
},
55-
});
56-
57-
if (res.data?.projects?.nodes) {
58-
const nonEmptyProjects = res.data.projects?.nodes.filter(notEmpty);
59-
const allMetadata = await Promise.allSettled(nonEmptyProjects.map((i) => getMetadataFromCid(i.metadata)));
60-
const projectsWithMetadata = nonEmptyProjects.map((project, index) => {
61-
const rawMetadata = allMetadata[index];
62-
const metadata =
63-
rawMetadata.status === 'fulfilled'
64-
? rawMetadata.value
65-
: { name: '', description: '', versionDescription: '' };
66-
return {
67-
...project,
68-
...metadata,
69-
};
70-
});
71-
const mergered = uniqWith([...projects.current, ...projectsWithMetadata], (x, y) => x.id === y.id);
72-
projects.current = mergered;
73-
await localforage.setItem(cacheKey, mergered);
74-
if (mergered.length >= res.data.projects.totalCount) {
75-
loading.current = false;
76-
return;
48+
try {
49+
if (withLoading) {
50+
loading.current = true;
7751
}
7852

79-
window.requestIdleCallback(() => fetchAllProjects(mergered.length));
53+
const res = await getProjects({
54+
variables: {
55+
offset: tempProjects.length,
56+
orderBy: [ProjectsOrderBy.ID_ASC],
57+
ids: [],
58+
},
59+
defaultOptions: {
60+
fetchPolicy: 'network-only',
61+
},
62+
});
63+
64+
if (res.data?.projects?.nodes) {
65+
const nonEmptyProjects = res.data.projects?.nodes.filter(notEmpty);
66+
const allMetadata = await Promise.allSettled(nonEmptyProjects.map((i) => getMetadataFromCid(i.metadata)));
67+
const projectsWithMetadata = nonEmptyProjects.map((project, index) => {
68+
const rawMetadata = allMetadata[index];
69+
const metadata =
70+
rawMetadata.status === 'fulfilled'
71+
? rawMetadata.value
72+
: { name: '', description: '', versionDescription: '' };
73+
return {
74+
...project,
75+
...metadata,
76+
};
77+
});
78+
const mergered = uniqWith([...tempProjects, ...projectsWithMetadata], (x, y) => x.id === y.id);
79+
tempProjects = mergered;
80+
if (mergered.length >= res.data.projects.totalCount) {
81+
loading.current = false;
82+
return tempProjects;
83+
}
84+
85+
return await innerFetch(tempProjects);
86+
}
87+
} catch (e) {
88+
setError(e);
89+
loading.current = false;
90+
return tempProjects;
8091
}
81-
} catch (e) {
82-
setError(e);
83-
loading.current = false;
84-
}
92+
93+
return tempProjects;
94+
};
95+
96+
const res = await innerFetch(cachedProjects || []);
97+
98+
projects.current = res;
99+
await localforage.setItem(cacheKey, res);
85100
};
86101

87102
const init = async () => {
88103
// When first estiblish the local cache. We need to fetch all of it.
89104
// See fetchAllProject. It's a low-priority(requestsIdleCallback) fetch
90-
// if there have cache, just add & update metadata.
105+
// if there have cache, use cache first, and then fetch from initial to update.
91106
const cached = await localforage.getItem<
92107
({ description: string; versionDescription: string; name: string } & ProjectFieldsFragment)[]
93108
>(cacheKey);
94-
95109
if (cached) {
96110
projects.current = cached;
97-
fetchAllProjects(cached.length);
111+
await fetchAllProjects(cached);
112+
// update for next search
113+
window.requestIdleCallback(() => fetchAllProjects([], false));
98114
return;
99115
}
100116
fetchAllProjects();
@@ -119,39 +135,10 @@ export const useLocalProjects = () => {
119135
};
120136
};
121137

122-
const updateExistMetadata = async () => {
123-
await waitForSomething({ func: () => !loading.current });
124-
// IPFS can be cache. So fetch all of it would ok.
125-
const allMetadata = await Promise.allSettled(
126-
projects.current.map(async (i) => {
127-
const data = await getMetadataFromCid(i.metadata);
128-
return {
129-
[i.id]: data,
130-
};
131-
}),
132-
);
133-
const successData = allMetadata.filter(filterSuccessPromoiseSettledResult);
134-
135-
const newProjectsData = projects.current.map((i) => {
136-
const find = successData.find((x) => x.value[i.id]);
137-
return {
138-
...i,
139-
...find,
140-
};
141-
});
142-
await localforage.setItem(cacheKey, newProjectsData);
143-
144-
projects.current = newProjectsData;
145-
};
146-
147138
useMount(() => {
148139
window.requestIdleCallback(() => init());
149140
});
150141

151-
useInterval(() => {
152-
window.requestIdleCallback(() => updateExistMetadata());
153-
}, 60000);
154-
155142
return {
156143
loading,
157144
error,

0 commit comments

Comments
 (0)