Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F33263305
D14584.1768610883.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Size
19 KB
Referenced Files
None
Subscribers
None
D14584.1768610883.diff
View Options
diff --git a/lib/actions/user-actions.js b/lib/actions/user-actions.js
--- a/lib/actions/user-actions.js
+++ b/lib/actions/user-actions.js
@@ -1470,10 +1470,11 @@
const client = React.useContext(IdentityClientContext);
const identityClient = client?.identityClient;
invariant(identityClient, 'Identity client should be set');
- return async () => {
- const supported = await identityClient.versionSupported();
+ const { versionSupported } = identityClient;
+ return React.useCallback(async () => {
+ const supported = await versionSupported();
return { supported };
- };
+ }, [versionSupported]);
}
const restoreUserActionTypes = Object.freeze({
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
@@ -139,9 +139,10 @@
function useStringForUser(
user: ?{ +username?: ?string, +isViewer?: ?boolean, ... },
): ?string {
- const toFetch = user?.isViewer ? null : user;
// stringForUser ignores username is isViewer, so we skip the ENS fetch
- const [result] = useENSNames([toFetch]);
+ const toFetch = user?.isViewer ? null : user;
+ const usersObjArr = React.useMemo(() => [toFetch], [toFetch]);
+ const [result] = useENSNames(usersObjArr);
if (user?.isViewer) {
return stringForUser(user);
} else if (result) {
diff --git a/lib/shared/user-utils.js b/lib/shared/user-utils.js
--- a/lib/shared/user-utils.js
+++ b/lib/shared/user-utils.js
@@ -1,5 +1,7 @@
// @flow
+import * as React from 'react';
+
import { roleIsAdminRole } from './thread-utils.js';
import { useENSNames } from '../hooks/ens-cache.js';
import type {
@@ -41,7 +43,8 @@
member.role ? roleIsAdminRole(roles[member.role]) : false,
);
const adminUserInfo = admin ? userInfos[admin.id] : undefined;
- const [adminUserInfoWithENSName] = useENSNames([adminUserInfo]);
+ const adminUserInfos = React.useMemo(() => [adminUserInfo], [adminUserInfo]);
+ const [adminUserInfoWithENSName] = useENSNames(adminUserInfos);
return adminUserInfoWithENSName;
}
diff --git a/lib/utils/role-utils.js b/lib/utils/role-utils.js
--- a/lib/utils/role-utils.js
+++ b/lib/utils/role-utils.js
@@ -56,24 +56,30 @@
community ? threadInfoSelector(state)[community] : null,
);
const topMostThreadInfo = communityThreadInfo || threadInfo;
- const roleMap = new Map<string, ?RoleInfo>();
- if (topMostThreadInfo.type === threadTypes.GENESIS) {
- memberInfos.forEach(memberInfo =>
+ return React.useMemo(() => {
+ const roleMap = new Map<string, ?RoleInfo>();
+
+ if (topMostThreadInfo.type === threadTypes.GENESIS) {
+ memberInfos.forEach(memberInfo =>
+ roleMap.set(
+ memberInfo.id,
+ memberInfo.role ? threadInfo.roles[memberInfo.role] : null,
+ ),
+ );
+ return roleMap;
+ }
+
+ const { members: memberInfosFromTopMostThreadInfo, roles } =
+ topMostThreadInfo;
+ memberInfosFromTopMostThreadInfo.forEach(memberInfo => {
roleMap.set(
memberInfo.id,
- memberInfo.role ? threadInfo.roles[memberInfo.role] : null,
- ),
- );
+ memberInfo.role ? roles[memberInfo.role] : null,
+ );
+ });
return roleMap;
- }
-
- const { members: memberInfosFromTopMostThreadInfo, roles } =
- topMostThreadInfo;
- memberInfosFromTopMostThreadInfo.forEach(memberInfo => {
- roleMap.set(memberInfo.id, memberInfo.role ? roles[memberInfo.role] : null);
- });
- return roleMap;
+ }, [topMostThreadInfo, threadInfo, memberInfos]);
}
function useMembersGroupedByRole(
diff --git a/native/account/registration/username-selection.react.js b/native/account/registration/username-selection.react.js
--- a/native/account/registration/username-selection.react.js
+++ b/native/account/registration/username-selection.react.js
@@ -118,26 +118,33 @@
}
const styles = useStyles(unboundStyles);
+ const errorNumberStyle = React.useMemo(
+ () => [styles.errorText, styles.listItemNumber],
+ [styles.errorText, styles.listItemNumber],
+ );
+ const errorTextStyle = React.useMemo(
+ () => [styles.errorText, styles.listItemContent],
+ [styles.errorText, styles.listItemContent],
+ );
+
let errorText;
if (usernameError === 'username_invalid') {
errorText = (
<>
<Text style={styles.errorText}>Usernames must:</Text>
<View style={styles.listItem}>
- <Text style={[styles.errorText, styles.listItemNumber]}>{'1. '}</Text>
- <Text style={[styles.errorText, styles.listItemContent]}>
- Be at least one character long.
- </Text>
+ <Text style={errorNumberStyle}>{'1. '}</Text>
+ <Text style={errorTextStyle}>Be at least one character long.</Text>
</View>
<View style={styles.listItem}>
- <Text style={[styles.errorText, styles.listItemNumber]}>{'2. '}</Text>
- <Text style={[styles.errorText, styles.listItemContent]}>
+ <Text style={errorNumberStyle}>{'2. '}</Text>
+ <Text style={errorTextStyle}>
Start with either a letter or a number.
</Text>
</View>
<View style={styles.listItem}>
- <Text style={[styles.errorText, styles.listItemNumber]}>{'3. '}</Text>
- <Text style={[styles.errorText, styles.listItemContent]}>
+ <Text style={errorNumberStyle}>{'3. '}</Text>
+ <Text style={errorTextStyle}>
Contain only letters, numbers, or the characters “-” and “_”.
</Text>
</View>
diff --git a/native/account/terms-and-privacy-modal.react.js b/native/account/terms-and-privacy-modal.react.js
--- a/native/account/terms-and-privacy-modal.react.js
+++ b/native/account/terms-and-privacy-modal.react.js
@@ -41,6 +41,8 @@
policyAcknowledgmentActionTypes,
);
+const safeAreaEdges = ['top', 'bottom'];
+
function TermsAndPrivacyModal(props: Props): React.Node {
const loadingStatus = useSelector(loadingStatusSelector);
const [acknowledgmentError, setAcknowledgmentError] = React.useState('');
@@ -89,7 +91,6 @@
};
}, [onBackPress]);
- const safeAreaEdges = ['top', 'bottom'];
return (
<Modal
disableClosing={true}
diff --git a/native/calendar/loading-indicator.react.js b/native/calendar/loading-indicator.react.js
--- a/native/calendar/loading-indicator.react.js
+++ b/native/calendar/loading-indicator.react.js
@@ -12,11 +12,14 @@
+canUseRed: boolean,
};
function LoadingIndicator(props: Props): React.Node {
- if (props.loadingStatus === 'error') {
- const colorStyle = props.canUseRed
+ const errorStyle = React.useMemo(() => {
+ const errorColorStyle = props.canUseRed
? { color: 'red' }
: { color: props.color };
- return <Icon name="x-circle" style={[styles.errorIcon, colorStyle]} />;
+ return [styles.errorIcon, errorColorStyle];
+ }, [props.canUseRed, props.color]);
+ if (props.loadingStatus === 'error') {
+ return <Icon name="x-circle" style={errorStyle} />;
} else if (props.loadingStatus === 'loading') {
return <ActivityIndicator size="small" color={props.color} />;
} else {
diff --git a/native/chat/chat-input-bar.react.js b/native/chat/chat-input-bar.react.js
--- a/native/chat/chat-input-bar.react.js
+++ b/native/chat/chat-input-bar.react.js
@@ -987,6 +987,15 @@
prevEditedMessage.current = editedMessage;
}, [blockNavigation, messageEditingContext?.editState.editedMessage]);
+ const currentlyEditMode = isEditMode();
+ const expandoButtonsViewStyle: Array<ViewStyle> = React.useMemo(() => {
+ const combined = [styles.innerExpandoButtons];
+ if (currentlyEditMode) {
+ combined.push({ display: 'none' });
+ }
+ return combined;
+ }, [styles.innerExpandoButtons, currentlyEditMode]);
+
const renderInput = () => {
const expandoButton = (
<TouchableOpacity
@@ -1004,12 +1013,6 @@
</TouchableOpacity>
);
const threadColor = `#${threadInfo.color}`;
- const expandoButtonsViewStyle: Array<ViewStyle> = [
- styles.innerExpandoButtons,
- ];
- if (isEditMode()) {
- expandoButtonsViewStyle.push({ display: 'none' });
- }
return (
<TouchableWithoutFeedback onPress={dismissKeyboard}>
<View style={styles.inputContainer}>
@@ -1079,6 +1082,10 @@
const isMember = viewerIsMember(threadInfo);
let joinButton = null;
const threadColor = `#${threadInfo.color}`;
+ const joinButtonStyle = React.useMemo(
+ () => [styles.joinButton, { backgroundColor: threadColor }],
+ [styles.joinButton, threadColor],
+ );
if (!isMember && currentUserCanJoin && !threadCreationInProgress) {
let buttonContent;
@@ -1106,7 +1113,7 @@
<Button
onPress={onPressJoin}
iosActiveOpacity={0.85}
- style={[styles.joinButton, { backgroundColor: threadColor }]}
+ style={joinButtonStyle}
>
{buttonContent}
</Button>
@@ -1163,6 +1170,11 @@
<KeyboardInputHost textInputRef={textInputRef.current} />
);
+ const editingLabelStyle = React.useMemo(
+ () => [{ color: threadColor }, styles.editingLabel],
+ [threadColor, styles.editingLabel],
+ );
+
let editedMessage;
if (isEditMode() && editedMessagePreview) {
const { message } = editedMessagePreview;
@@ -1174,9 +1186,7 @@
>
<View style={styles.editViewContent}>
<TouchableOpacity onPress={scrollToEditedMessage} activeOpacity={0.4}>
- <Text style={[{ color: threadColor }, styles.editingLabel]}>
- Editing message
- </Text>
+ <Text style={editingLabelStyle}>Editing message</Text>
<SingleLine style={styles.editingMessagePreview}>
{message.text}
</SingleLine>
diff --git a/native/chat/inner-robotext-message.react.js b/native/chat/inner-robotext-message.react.js
--- a/native/chat/inner-robotext-message.react.js
+++ b/native/chat/inner-robotext-message.react.js
@@ -144,7 +144,10 @@
}
function ColorEntity(props: { +color: string }) {
- const colorStyle = { color: props.color };
+ const colorStyle = React.useMemo(
+ () => ({ color: props.color }),
+ [props.color],
+ );
return <Text style={colorStyle}>{props.color}</Text>;
}
diff --git a/native/chat/robotext-message.react.js b/native/chat/robotext-message.react.js
--- a/native/chat/robotext-message.react.js
+++ b/native/chat/robotext-message.react.js
@@ -220,12 +220,14 @@
return { opacity: contentAndHeaderOpacity.value };
});
- const viewStyle: { height?: number } = {};
- if (!__DEV__) {
- // We don't force view height in dev mode because we
- // want to measure it in Message to see if it's correct
- viewStyle.height = item.contentHeight;
- }
+ const viewStyle: { height?: number } = React.useMemo(() => {
+ if (__DEV__) {
+ // We don't force view height in dev mode because we
+ // want to measure it in Message to see if it's correct
+ return {};
+ }
+ return { height: item.contentHeight };
+ }, [item.contentHeight]);
return (
<View {...viewProps}>
diff --git a/native/chat/settings/thread-settings-edit-relationship.react.js b/native/chat/settings/thread-settings-edit-relationship.react.js
--- a/native/chat/settings/thread-settings-edit-relationship.react.js
+++ b/native/chat/settings/thread-settings-edit-relationship.react.js
@@ -44,7 +44,11 @@
});
invariant(otherUserInfoFromRedux, 'Other user info should be specified');
- const [otherUserInfo] = useENSNames([otherUserInfoFromRedux]);
+ const ensNames = React.useMemo(
+ () => [otherUserInfoFromRedux],
+ [otherUserInfoFromRedux],
+ );
+ const [otherUserInfo] = useENSNames(ensNames);
const updateRelationships = useUpdateRelationships();
const updateRelationship = React.useCallback(
diff --git a/native/profile/user-relationship-tooltip-modal.react.js b/native/profile/user-relationship-tooltip-modal.react.js
--- a/native/profile/user-relationship-tooltip-modal.react.js
+++ b/native/profile/user-relationship-tooltip-modal.react.js
@@ -35,17 +35,18 @@
...UserRelationshipTooltipModalParams,
+action: Action,
};
-function useRelationshipAction(input: OnRemoveUserProps) {
+function useRelationshipAction({
+ relativeUserInfo,
+ action,
+}: OnRemoveUserProps) {
const updateRelationships = useUpdateRelationships();
const dispatchActionPromise = useDispatchActionPromise();
- const userText = stringForUser(input.relativeUserInfo);
+ const userText = stringForUser(relativeUserInfo);
return React.useCallback(() => {
const callRemoveRelationships = async () => {
try {
- return await updateRelationships(input.action, [
- input.relativeUserInfo.id,
- ]);
+ return await updateRelationships(action, [relativeUserInfo.id]);
} catch (e) {
Alert.alert(
unknownErrorAlertDetails.title,
@@ -59,25 +60,25 @@
}
};
const onConfirmRemoveUser = () => {
- const customKeyName = `${updateRelationshipsActionTypes.started}:${input.relativeUserInfo.id}`;
+ const customKeyName = `${updateRelationshipsActionTypes.started}:${relativeUserInfo.id}`;
void dispatchActionPromise(
updateRelationshipsActionTypes,
callRemoveRelationships(),
{ customKeyName },
);
};
- const action = {
+ const actionStr = {
unfriend: 'removal',
block: 'block',
unblock: 'unblock',
- }[input.action];
+ }[action];
const message = {
unfriend: `remove ${userText} from friends?`,
block: `block ${userText}`,
unblock: `unblock ${userText}?`,
- }[input.action];
+ }[action];
Alert.alert(
- `Confirm ${action}`,
+ `Confirm ${actionStr}`,
`Are you sure you want to ${message}`,
[
{ text: 'Cancel', style: 'cancel' },
@@ -85,7 +86,13 @@
],
{ cancelable: true },
);
- }, [updateRelationships, dispatchActionPromise, userText, input]);
+ }, [
+ updateRelationships,
+ dispatchActionPromise,
+ userText,
+ relativeUserInfo,
+ action,
+ ]);
}
function TooltipMenu(
diff --git a/web/chat/chat-input-text-area.react.js b/web/chat/chat-input-text-area.react.js
--- a/web/chat/chat-input-text-area.react.js
+++ b/web/chat/chat-input-text-area.react.js
@@ -75,28 +75,26 @@
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [currentText]);
- const onKeyDown = (event: SyntheticKeyboardEvent<HTMLTextAreaElement>) => {
- if (event.key === 'Escape') {
- event.preventDefault();
- if (!escape) {
- return;
+ const onKeyDown = React.useCallback(
+ (event: SyntheticKeyboardEvent<HTMLTextAreaElement>) => {
+ if (event.key === 'Escape') {
+ event.preventDefault();
+ escape?.();
+ } else if (event.key === 'Enter' && !event.shiftKey) {
+ event.preventDefault();
+ send?.();
}
- escape();
- } else if (event.key === 'Enter' && !event.shiftKey) {
- event.preventDefault();
- if (!send) {
- return;
- }
- send();
- }
- };
+ },
+ [escape, send],
+ );
- const onChangeMessageText = (
- event: SyntheticEvent<HTMLTextAreaElement>,
- ) => {
- setCurrentText(event.currentTarget.value);
- updateHeight();
- };
+ const onChangeMessageText = React.useCallback(
+ (event: SyntheticEvent<HTMLTextAreaElement>) => {
+ setCurrentText(event.currentTarget.value);
+ updateHeight();
+ },
+ [setCurrentText, updateHeight],
+ );
return (
<div className={css.inputBarTextInput}>
diff --git a/web/chat/edit-text-message.react.js b/web/chat/edit-text-message.react.js
--- a/web/chat/edit-text-message.react.js
+++ b/web/chat/edit-text-message.react.js
@@ -2,7 +2,6 @@
import classNames from 'classnames';
import * as React from 'react';
-import { useCallback } from 'react';
import { XCircle as XCircleIcon } from 'react-feather';
import type { ComposableChatMessageInfoItem } from 'lib/selectors/chat-selectors.js';
@@ -29,6 +28,7 @@
};
const bottomRowStyle = { height: editBoxBottomRowHeight };
+const buttonClassNames = [css.saveButton, css.smallButton];
function EditTextMessage(props: Props): React.Node {
const { background, threadInfo, item } = props;
@@ -47,10 +47,7 @@
[threadColor],
);
- const isMessageEmpty = React.useMemo(
- () => trimMessage(editedMessageDraft) === '',
- [editedMessageDraft],
- );
+ const isMessageEmpty = trimMessage(editedMessageDraft) === '';
const isMessageEdited = React.useMemo(() => {
const { messageInfo } = item;
@@ -64,7 +61,7 @@
return trimmedDraft !== messageInfo.text;
}, [editState, editedMessageDraft, item]);
- const checkAndEdit = async () => {
+ const checkAndEdit = React.useCallback(async () => {
const { id: messageInfoID } = item.messageInfo;
if (isMessageEmpty) {
return;
@@ -73,18 +70,26 @@
clearEditModal();
return;
}
- if (!messageInfoID || !editState?.editedMessageDraft) {
+ if (!messageInfoID || !editedMessageDraft) {
return;
}
try {
- await editMessage(messageInfoID, editState.editedMessageDraft);
+ await editMessage(messageInfoID, editedMessageDraft);
clearEditModal();
} catch (e) {
setError(true);
}
- };
-
- const updateDimensions = useCallback(() => {
+ }, [
+ item.messageInfo,
+ isMessageEmpty,
+ isMessageEdited,
+ editedMessageDraft,
+ editMessage,
+ clearEditModal,
+ setError,
+ ]);
+
+ const updateDimensions = React.useCallback(() => {
if (!myRef.current || !background) {
return;
}
@@ -156,7 +161,7 @@
{editFailed}
<div className={css.buttons}>
<Button
- className={[css.saveButton, css.smallButton]}
+ className={buttonClassNames}
variant="filled"
buttonColor={saveButtonColor}
onClick={checkAndEdit}
diff --git a/web/modals/history/history-revision.react.js b/web/modals/history/history-revision.react.js
--- a/web/modals/history/history-revision.react.js
+++ b/web/modals/history/history-revision.react.js
@@ -44,7 +44,11 @@
const authorUserInfo = useSelector(
state => state.userStore.userInfos[authorID],
);
- const [authorWithENSName] = useENSNames([authorUserInfo]);
+ const authorUserInfos = React.useMemo(
+ () => [authorUserInfo],
+ [authorUserInfo],
+ );
+ const [authorWithENSName] = useENSNames(authorUserInfos);
const author = authorWithENSName?.username ? (
<span className={css.entryUsername}>{authorWithENSName.username}</span>
diff --git a/web/modals/threads/members/member.react.js b/web/modals/threads/members/member.react.js
--- a/web/modals/threads/members/member.react.js
+++ b/web/modals/threads/members/member.react.js
@@ -38,7 +38,8 @@
const { pushModal } = useModalContext();
const userName = stringForUser(memberInfo);
- const roles = useRolesFromCommunityThreadInfo(threadInfo, [memberInfo]);
+ const memberInfos = React.useMemo(() => [memberInfo], [memberInfo]);
+ const roles = useRolesFromCommunityThreadInfo(threadInfo, memberInfos);
const roleName = roles.get(memberInfo.id)?.name;
const onMenuChange = React.useCallback(
diff --git a/web/modals/threads/settings/thread-settings-relationship-tab.react.js b/web/modals/threads/settings/thread-settings-relationship-tab.react.js
--- a/web/modals/threads/settings/thread-settings-relationship-tab.react.js
+++ b/web/modals/threads/settings/thread-settings-relationship-tab.react.js
@@ -18,7 +18,8 @@
function ThreadSettingsRelationshipTab(props: Props): React.Node {
const { relationshipButtons, otherUserInfo, setErrorMessage } = props;
- const [otherUserInfoWithENSName] = useENSNames([otherUserInfo]);
+ const userInfos = React.useMemo(() => [otherUserInfo], [otherUserInfo]);
+ const [otherUserInfoWithENSName] = useENSNames(userInfos);
const buttons = React.useMemo(
() =>
relationshipButtons.map(action => (
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sat, Jan 17, 12:48 AM (5 h, 31 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
5946604
Default Alt Text
D14584.1768610883.diff (19 KB)
Attached To
Mode
D14584: [lib][native][web] Add some memoization
Attached
Detach File
Event Timeline
Log In to Comment