Page MenuHomePhabricator

D9515.id32151.diff
No OneTemporary

D9515.id32151.diff

diff --git a/lib/hooks/ens-cache.js b/lib/hooks/ens-cache.js
--- a/lib/hooks/ens-cache.js
+++ b/lib/hooks/ens-cache.js
@@ -6,11 +6,19 @@
import { ENSCacheContext } from '../components/ens-cache-provider.react.js';
import { getETHAddressForUserInfo } from '../shared/account-utils.js';
import { stringForUser } from '../shared/user-utils.js';
+import { getENSNames } from '../utils/ens-helpers.js';
type BaseUserInfo = { +username?: ?string, ... };
-function useENSNames<T: ?BaseUserInfo>(users: $ReadOnlyArray<T>): T[] {
+export type UseENSNamesOptions = {
+ +allAtOnce?: ?boolean,
+};
+function useENSNames<T: ?BaseUserInfo>(
+ users: $ReadOnlyArray<T>,
+ options?: ?UseENSNamesOptions,
+): T[] {
const cacheContext = React.useContext(ENSCacheContext);
const { ensCache } = cacheContext;
+ const allAtOnce = options?.allAtOnce ?? false;
const cachedInfo = React.useMemo(
() =>
@@ -43,7 +51,8 @@
if (!ensCache) {
return;
}
- const needFetch = cachedInfo
+
+ const needFetchUsers: $ReadOnlyArray<{ +username: string }> = cachedInfo
.map(user => {
if (!user) {
return null;
@@ -52,20 +61,39 @@
if (cachedResult || !ethAddress || fetchedAddresses.has(ethAddress)) {
return null;
}
- return ethAddress;
+ return { username: ethAddress };
})
.filter(Boolean);
- if (needFetch.length === 0) {
+ if (needFetchUsers.length === 0) {
return;
}
+
+ const needFetchAddresses = needFetchUsers.map(({ username }) => username);
setFetchedAddresses(oldFetchedAddresses => {
const newFetchedAddresses = new Set(oldFetchedAddresses);
- for (const ethAddress of needFetch) {
+ for (const ethAddress of needFetchAddresses) {
newFetchedAddresses.add(ethAddress);
}
return newFetchedAddresses;
});
- for (const ethAddress of needFetch) {
+
+ if (allAtOnce) {
+ (async () => {
+ const withENSNames = await getENSNames(ensCache, needFetchUsers);
+ setENSNames(oldENSNames => {
+ const newENSNames = new Map(oldENSNames);
+ for (let i = 0; i < withENSNames.length; i++) {
+ const ethAddress = needFetchAddresses[i];
+ const result = withENSNames[i].username;
+ newENSNames.set(ethAddress, result);
+ }
+ return newENSNames;
+ });
+ })();
+ return;
+ }
+
+ for (const ethAddress of needFetchAddresses) {
(async () => {
const result = await ensCache.getNameForAddress(ethAddress);
if (!result) {
@@ -78,7 +106,7 @@
});
})();
}
- }, [cachedInfo, fetchedAddresses, ensCache]);
+ }, [cachedInfo, fetchedAddresses, ensCache, allAtOnce]);
return React.useMemo(
() =>
diff --git a/lib/selectors/nav-selectors.js b/lib/selectors/nav-selectors.js
--- a/lib/selectors/nav-selectors.js
+++ b/lib/selectors/nav-selectors.js
@@ -3,7 +3,7 @@
import * as React from 'react';
import { createSelector } from 'reselect';
-import { ENSCacheContext } from '../components/ens-cache-provider.react.js';
+import { useENSNames } from '../hooks/ens-cache.js';
import SearchIndex from '../shared/search-index.js';
import { memberHasAdminPowers } from '../shared/thread-utils.js';
import type { Platform } from '../types/device-types.js';
@@ -16,7 +16,6 @@
import type { BaseAppState } from '../types/redux-types.js';
import type { RawThreadInfo, ThreadInfo } from '../types/thread-types.js';
import { getConfig } from '../utils/config.js';
-import { getENSNames } from '../utils/ens-helpers.js';
import { values } from '../utils/objects.js';
import { useSelector } from '../utils/redux-utils.js';
@@ -72,6 +71,12 @@
},
);
+// Without allAtOnce, useThreadSearchIndex is very expensive. useENSNames would
+// trigger its recalculation for each ENS name as it streams in, but we would
+// prefer to trigger its recaculation just once for every update of the
+// underlying Redux data.
+const useENSNamesOptions = { allAtOnce: true };
+
function useThreadSearchIndex(
threadInfos: $ReadOnlyArray<RawThreadInfo | ThreadInfo>,
): SearchIndex {
@@ -101,34 +106,18 @@
return [...allMembersOfAllThreads.values()];
}, [threadInfos, userInfos, viewerID]);
- const cacheContext = React.useContext(ENSCacheContext);
- const { ensCache } = cacheContext;
-
- // We avoid using useENSNames here because the SearchIndex memo below is very
- // expensive. useENSNames would trigger its recalculation for each ENS name as
- // it streams in, but we would prefer to trigger its recaculation just once
- // for every update of the underlying Redux data.
- const [nonViewerMembersWithENSNames, setNonViewerMembersWithENSNames] =
- React.useState();
- React.useEffect(() => {
- if (!ensCache) {
- return;
- }
- (async () => {
- const withENSNames = await getENSNames(ensCache, nonViewerMembers);
- setNonViewerMembersWithENSNames(withENSNames);
- })();
- }, [ensCache, nonViewerMembers]);
+ const nonViewerMembersWithENSNames = useENSNames(
+ nonViewerMembers,
+ useENSNamesOptions,
+ );
- const resolvedNonViewerMembers =
- nonViewerMembersWithENSNames ?? nonViewerMembers;
const memberMap = React.useMemo(() => {
const result = new Map();
- for (const userInfo of resolvedNonViewerMembers) {
+ for (const userInfo of nonViewerMembersWithENSNames) {
result.set(userInfo.id, userInfo);
}
return result;
- }, [resolvedNonViewerMembers]);
+ }, [nonViewerMembersWithENSNames]);
return React.useMemo(() => {
const searchIndex = new SearchIndex();

File Metadata

Mime Type
text/plain
Expires
Wed, Nov 27, 2:57 PM (20 h, 16 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
2590738
Default Alt Text
D9515.id32151.diff (5 KB)

Event Timeline