diff --git a/src/pages/commonFeed/hooks/useCommonData/index.ts b/src/pages/commonFeed/hooks/useCommonData/index.ts index c2a84ee823..20e5efdbba 100644 --- a/src/pages/commonFeed/hooks/useCommonData/index.ts +++ b/src/pages/commonFeed/hooks/useCommonData/index.ts @@ -47,12 +47,13 @@ export const useCommonData = (userId?: string): Return => { (async () => { try { const [common, governance, sharedFeedItem] = await Promise.all([ - CommonService.getCommonById(commonId), - GovernanceService.getGovernanceByCommonId(commonId), + CommonService.getCommonById(commonId, true), + GovernanceService.getGovernanceByCommonId(commonId, true), sharedFeedItemId ? CommonFeedService.getCommonFeedItemById( commonId, sharedFeedItemId, + true, ) : null, ]); @@ -69,10 +70,10 @@ export const useCommonData = (userId?: string): Return => { const { rootCommonId } = common; const [parentCommons, subCommons, rootCommonGovernance] = await Promise.all([ - CommonService.getAllParentCommonsForCommon(common), - CommonService.getCommonsByDirectParentIds([common.id]), + CommonService.getAllParentCommonsForCommon(common, true), + CommonService.getCommonsByDirectParentId(common.id, true), rootCommonId - ? GovernanceService.getGovernanceByCommonId(rootCommonId) + ? GovernanceService.getGovernanceByCommonId(rootCommonId, true) : null, ]); const rootCommon = await getRootCommon( diff --git a/src/services/Common.ts b/src/services/Common.ts index 50bd9192f5..4ba3541c9a 100644 --- a/src/services/Common.ts +++ b/src/services/Common.ts @@ -17,7 +17,6 @@ import { SubCollections, } from "@/shared/models"; import { - convertObjectDatesToFirestoreTimestamps, emptyFunction, firestoreDataConverter, transformFirebaseDataList, @@ -30,16 +29,25 @@ const converter = firestoreDataConverter(); const commonMemberConverter = firestoreDataConverter(); class CommonService { - public getCommonById = async (commonId: string): Promise => { - const common = await firebase + public getCommonById = async ( + commonId: string, + cached = false, + ): Promise => { + const snapshot = await firebase .firestore() .collection(Collection.Daos) .where("id", "==", commonId) .where("state", "==", CommonState.ACTIVE) - .get(); - const data = transformFirebaseDataList(common); + .withConverter(converter) + .get({ source: cached ? "cache" : "default" }); + const commons = snapshot.docs.map((doc) => doc.data()); + const common = commons[0] || null; + + if (cached && !common) { + return this.getCommonById(commonId); + } - return data[0] ? convertObjectDatesToFirestoreTimestamps(data[0]) : null; + return common; }; public getCachedCommonById = async ( @@ -93,6 +101,26 @@ class CommonService { .reduce((acc, items) => [...acc, ...items], []); }; + public getCommonsByDirectParentId = async ( + parentCommonId: string, + cached = false, + ): Promise => { + const snapshot = await firebase + .firestore() + .collection(Collection.Daos) + .where("state", "==", CommonState.ACTIVE) + .where("directParent.commonId", "==", parentCommonId) + .withConverter(converter) + .get({ source: cached ? "cache" : "default" }); + const commons = snapshot.docs.map((doc) => doc.data()); + + if (cached && commons.length === 0) { + return this.getCommonsByDirectParentId(parentCommonId); + } + + return commons; + }; + public getCommonsByDirectParentIds = async ( ids: string[], ): Promise => { @@ -249,10 +277,11 @@ class CommonService { // Fetch all parent commons. Order: from root parent common to lowest ones public getAllParentCommonsForCommon = async ( commonToCheck: Pick | string, + cached = false, ): Promise => { const common = typeof commonToCheck === "string" - ? await this.getCommonById(commonToCheck) + ? await this.getCommonById(commonToCheck, cached) : commonToCheck; if (!common || common.directParent === null) { @@ -263,7 +292,7 @@ class CommonService { let nextCommonId = common.directParent.commonId; while (nextCommonId) { - const common = await this.getCommonById(nextCommonId); + const common = await this.getCommonById(nextCommonId, cached); if (common) { finalCommons = [common, ...finalCommons]; diff --git a/src/services/CommonFeed.ts b/src/services/CommonFeed.ts index f9920217aa..7ab52352fb 100644 --- a/src/services/CommonFeed.ts +++ b/src/services/CommonFeed.ts @@ -25,7 +25,7 @@ import { convertToTimestamp, firestoreDataConverter, } from "@/shared/utils"; -import firebase from "@/shared/utils/firebase"; +import firebase, { isFirestoreCacheError } from "@/shared/utils/firebase"; import Api, { CancelToken } from "./Api"; const converter = firestoreDataConverter(); @@ -42,12 +42,21 @@ class CommonFeedService { public getCommonFeedItemById = async ( commonId: string, commonFeedId: string, + cached = false, ): Promise => { - const snapshot = await this.getCommonFeedSubCollection(commonId) - .doc(commonFeedId) - .get(); + try { + const snapshot = await this.getCommonFeedSubCollection(commonId) + .doc(commonFeedId) + .get({ source: cached ? "cache" : "default" }); - return snapshot?.data() || null; + return snapshot?.data() || null; + } catch (error) { + if (cached && isFirestoreCacheError(error)) { + return this.getCommonFeedItemById(commonId, commonFeedId); + } else { + throw error; + } + } }; public getCommonFeedItemWithSnapshot = async ( diff --git a/src/services/Governance.ts b/src/services/Governance.ts index 3a1784db95..eb94536183 100644 --- a/src/services/Governance.ts +++ b/src/services/Governance.ts @@ -13,12 +13,20 @@ const converter = firestoreDataConverter(); class GovernanceService { public getGovernanceByCommonId = async ( commonId: string, + cached = false, ): Promise => { - const governanceList = await governanceCollection + const snapshot = await governanceCollection .where("commonId", "==", commonId) - .get(); + .withConverter(converter) + .get({ source: cached ? "cache" : "default" }); + const governanceList = snapshot.docs.map((doc) => doc.data()); + const governance = governanceList[0] || null; - return transformFirebaseDataList(governanceList)[0] || null; + if (cached && !governance) { + return this.getGovernanceByCommonId(commonId); + } + + return governance; }; public getGovernanceListByCommonIds = async ( diff --git a/src/shared/hooks/useCases/useFullCommonData/index.ts b/src/shared/hooks/useCases/useFullCommonData/index.ts index 20a85949cb..0e6133a3f9 100644 --- a/src/shared/hooks/useCases/useFullCommonData/index.ts +++ b/src/shared/hooks/useCases/useFullCommonData/index.ts @@ -26,7 +26,7 @@ export const getRootCommon = async ( return initialRootCommon; } - return CommonService.getCommonById(rootCommonId); + return CommonService.getCommonById(rootCommonId, true); }; export const useFullCommonData = (): Return => { diff --git a/src/shared/utils/firebase.tsx b/src/shared/utils/firebase.tsx index 57d0f0f0e7..783c5e5cd3 100644 --- a/src/shared/utils/firebase.tsx +++ b/src/shared/utils/firebase.tsx @@ -32,8 +32,11 @@ if (REACT_APP_ENV === Environment.Local) { }); } -export const isFirebaseError = (error: any): error is FirebaseError => { - return error && error.code && error.code.startsWith("auth/"); -}; +export const isFirebaseError = (error: any): error is FirebaseError => + (error && error.code && error.code.startsWith("auth/")) || + error.name === "FirebaseError"; + +export const isFirestoreCacheError = (error: any): boolean => + isFirebaseError(error) && error.code === "unavailable"; export default firebase;