Page MenuHomePhorge

D14584.1768610883.diff
No OneTemporary

Size
19 KB
Referenced Files
None
Subscribers
None

D14584.1768610883.diff

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

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)

Event Timeline