diff --git a/lib/components/report-handler.react.js b/lib/components/report-handler.react.js --- a/lib/components/report-handler.react.js +++ b/lib/components/report-handler.react.js @@ -78,8 +78,8 @@ } } -const ConnectedReportHandler: React.ComponentType = - React.memo(function ConnectedReportHandler(props) { +const ConnectedReportHandler: React.ComponentType = React.memo( + function ConnectedReportHandler(props) { const queuedReports = useSelector(queuedReportsSelector); const dispatchActionPromise = useDispatchActionPromise(); const callSendReports = useSendReports(); @@ -92,6 +92,7 @@ sendReports={callSendReports} /> ); - }); + }, +); export default ConnectedReportHandler; diff --git a/lib/components/thread-draft-updater.react.js b/lib/components/thread-draft-updater.react.js --- a/lib/components/thread-draft-updater.react.js +++ b/lib/components/thread-draft-updater.react.js @@ -9,7 +9,7 @@ import type { AppState } from '../types/redux-types.js'; import { useSelector, useDispatch } from '../utils/redux-utils.js'; -const ThreadDraftUpdater: React.ComponentType<{}> = React.memo<{}>( +const ThreadDraftUpdater: React.ComponentType<{}> = React.memo( function ThreadDraftUpdater() { const pendingToRealizedThreadIDs = useSelector((state: AppState) => pendingToRealizedThreadIDsSelector(state.threadStore.threadInfos), diff --git a/lib/keyserver-conn/keyserver-connection-handler.js b/lib/keyserver-conn/keyserver-connection-handler.js --- a/lib/keyserver-conn/keyserver-connection-handler.js +++ b/lib/keyserver-conn/keyserver-connection-handler.js @@ -282,7 +282,7 @@ return ; } -const Handler: React.ComponentType = React.memo( +const Handler: React.ComponentType = React.memo( KeyserverConnectionHandler, ); diff --git a/lib/shared/transforms/keyserver-store-transform.js b/lib/shared/transforms/keyserver-store-transform.js --- a/lib/shared/transforms/keyserver-store-transform.js +++ b/lib/shared/transforms/keyserver-store-transform.js @@ -7,10 +7,7 @@ KeyserverInfo, KeyserverStore, } from '../../types/keyserver-types.js'; -import { - type ConnectionInfo, - defaultConnectionInfo, -} from '../../types/socket-types.js'; +import { defaultConnectionInfo } from '../../types/socket-types.js'; export type PersistedKeyserverInfo = Omit< KeyserverInfo, diff --git a/lib/socket/api-request-handler.react.js b/lib/socket/api-request-handler.react.js --- a/lib/socket/api-request-handler.react.js +++ b/lib/socket/api-request-handler.react.js @@ -104,8 +104,8 @@ }; } -const ConnectedAPIRequestHandler: React.ComponentType = - React.memo(function ConnectedAPIRequestHandler(props) { +const ConnectedAPIRequestHandler: React.ComponentType = React.memo( + function ConnectedAPIRequestHandler(props) { const connection = useSelector(connectionSelector(props.keyserverID)); invariant(connection, 'keyserver missing from keyserverStore'); const { registerActiveSocket } = useCallKeyserverEndpointContext(); @@ -116,6 +116,7 @@ registerActiveSocket={registerActiveSocket} /> ); - }); + }, +); export default ConnectedAPIRequestHandler; diff --git a/lib/socket/calendar-query-handler.react.js b/lib/socket/calendar-query-handler.react.js --- a/lib/socket/calendar-query-handler.react.js +++ b/lib/socket/calendar-query-handler.react.js @@ -128,7 +128,7 @@ } const ConnectedCalendarQueryHandler: React.ComponentType = - React.memo(function ConnectedCalendarQueryHandler(props) { + React.memo(function ConnectedCalendarQueryHandler(props) { const { currentCalendarQuery, keyserverID } = props; const keyserverInfo = useSelector( state => state.keyserverStore.keyserverInfos[keyserverID], diff --git a/lib/socket/request-response-handler.react.js b/lib/socket/request-response-handler.react.js --- a/lib/socket/request-response-handler.react.js +++ b/lib/socket/request-response-handler.react.js @@ -139,7 +139,7 @@ } const ConnectedRequestResponseHandler: React.ComponentType = - React.memo(function ConnectedRequestResponseHandler(props) { + React.memo(function ConnectedRequestResponseHandler(props) { const connection = useSelector(connectionSelector(props.keyserverID)); invariant(connection, 'keyserver missing from keyserverStore'); diff --git a/native/account/log-in-panel.react.js b/native/account/log-in-panel.react.js --- a/native/account/log-in-panel.react.js +++ b/native/account/log-in-panel.react.js @@ -348,8 +348,8 @@ const olmSessionInitializationDataLoadingStatusSelector = createLoadingStatusSelector(getOlmSessionInitializationDataActionTypes); -const ConnectedLogInPanel: React.ComponentType = - React.memo(function ConnectedLogInPanel(props: BaseProps) { +const ConnectedLogInPanel: React.ComponentType = React.memo( + function ConnectedLogInPanel(props: BaseProps) { const loadingStatus = useSelector( olmSessionInitializationDataLoadingStatusSelector, ); @@ -363,6 +363,7 @@ identityPasswordLogIn={callIdentityPasswordLogIn} /> ); - }); + }, +); export default ConnectedLogInPanel; diff --git a/native/account/logged-out-modal.react.js b/native/account/logged-out-modal.react.js --- a/native/account/logged-out-modal.react.js +++ b/native/account/logged-out-modal.react.js @@ -605,6 +605,6 @@ } const MemoizedLoggedOutModal: React.ComponentType = - React.memo(LoggedOutModal); + React.memo(LoggedOutModal); export default MemoizedLoggedOutModal; diff --git a/native/account/registration/registration-text-input.react.js b/native/account/registration/registration-text-input.react.js --- a/native/account/registration/registration-text-input.react.js +++ b/native/account/registration/registration-text-input.react.js @@ -99,7 +99,7 @@ const MemoizedRegistrationTextInput: typeof RegistrationTextInput = React.memo< Props, - React.ElementRef, + React.RefSetter>, >(RegistrationTextInput); export default MemoizedRegistrationTextInput; diff --git a/native/account/registration/siwe-backup-message-creation.react.js b/native/account/registration/siwe-backup-message-creation.react.js --- a/native/account/registration/siwe-backup-message-creation.react.js +++ b/native/account/registration/siwe-backup-message-creation.react.js @@ -39,99 +39,97 @@ }; const CreateSIWEBackupMessageBase: React.ComponentType = - React.memo( - function CreateSIWEBackupMessageBase( - props: CreateSIWEBackupMessageBaseProps, - ): React.Node { - const styles = useStyles(unboundStyles); - const { onSuccessfulWalletSignature, onExistingWalletSignature, onSkip } = - props; + React.memo(function CreateSIWEBackupMessageBase( + props: CreateSIWEBackupMessageBaseProps, + ): React.Node { + const styles = useStyles(unboundStyles); + const { onSuccessfulWalletSignature, onExistingWalletSignature, onSkip } = + props; - const { - panelState, - onPanelClosed, - onPanelClosing, - openPanel, - siwePanelSetLoading, - } = useSIWEPanelState(); + const { + panelState, + onPanelClosed, + onPanelClosing, + openPanel, + siwePanelSetLoading, + } = useSIWEPanelState(); - let siwePanel; - if (panelState !== 'closed') { - siwePanel = ( - - ); - } - - const newSignatureButtonText = onExistingWalletSignature - ? 'Encrypt with new signature' - : 'Encrypt with Ethereum signature'; - const defaultNewSignatureButtonVariant = onExistingWalletSignature - ? 'outline' - : 'enabled'; - const newSignatureButtonVariant = - panelState === 'opening' ? 'loading' : defaultNewSignatureButtonVariant; + let siwePanel; + if (panelState !== 'closed') { + siwePanel = ( + + ); + } - let useExistingSignatureButton; - if (onExistingWalletSignature) { - useExistingSignatureButton = ( - - ); - } + const newSignatureButtonText = onExistingWalletSignature + ? 'Encrypt with new signature' + : 'Encrypt with Ethereum signature'; + const defaultNewSignatureButtonVariant = onExistingWalletSignature + ? 'outline' + : 'enabled'; + const newSignatureButtonVariant = + panelState === 'opening' ? 'loading' : defaultNewSignatureButtonVariant; - let onSkipButton; - if (onSkip) { - onSkipButton = ( - - ); - } + let useExistingSignatureButton; + if (onExistingWalletSignature) { + useExistingSignatureButton = ( + + ); + } - return ( - <> - - - Encrypting your Comm backup - - To make sure we can’t see your data, Comm encrypts your backup - using a signature from your wallet. - - - This signature is private and never leaves your device, unlike - the prior signature, which is public. - - - This signature ensures that you can always recover your data as - long as you still control your wallet. - - - - - - - {useExistingSignatureButton} - - {onSkipButton} - - - {siwePanel} - + let onSkipButton; + if (onSkip) { + onSkipButton = ( + ); - }, - ); + } + + return ( + <> + + + Encrypting your Comm backup + + To make sure we can’t see your data, Comm encrypts your backup + using a signature from your wallet. + + + This signature is private and never leaves your device, unlike the + prior signature, which is public. + + + This signature ensures that you can always recover your data as + long as you still control your wallet. + + + + + + + {useExistingSignatureButton} + + {onSkipButton} + + + {siwePanel} + + ); + }); export type CreateSIWEBackupMessageParams = { +userSelections: { diff --git a/native/calendar/calendar-screen.react.js b/native/calendar/calendar-screen.react.js --- a/native/calendar/calendar-screen.react.js +++ b/native/calendar/calendar-screen.react.js @@ -1077,8 +1077,8 @@ ThreadPickerModalRouteName, ); -const ConnectedCalendarScreen: React.ComponentType = - React.memo(function ConnectedCalendarScreen(props: BaseProps) { +const ConnectedCalendarScreen: React.ComponentType = React.memo( + function ConnectedCalendarScreen(props: BaseProps) { const navContext = React.useContext(NavContext); const calendarActive = activeTabSelector(navContext) || activeThreadPickerSelector(navContext); @@ -1115,6 +1115,7 @@ updateCalendarQuery={callUpdateCalendarQuery} /> ); - }); + }, +); export default ConnectedCalendarScreen; diff --git a/native/calendar/entry.react.js b/native/calendar/entry.react.js --- a/native/calendar/entry.react.js +++ b/native/calendar/entry.react.js @@ -809,7 +809,7 @@ ThreadPickerModalRouteName, ); -const Entry: React.ComponentType = React.memo( +const Entry: React.ComponentType = React.memo( function ConnectedEntry(props: BaseProps) { const navContext = React.useContext(NavContext); const threadPickerActive = activeThreadPickerSelector(navContext); diff --git a/native/calendar/section-footer.react.js b/native/calendar/section-footer.react.js --- a/native/calendar/section-footer.react.js +++ b/native/calendar/section-footer.react.js @@ -71,12 +71,13 @@ }; } -const ConnectedSectionFooter: React.ComponentType = - React.memo(function ConnectedSectionFooter(props: BaseProps) { +const ConnectedSectionFooter: React.ComponentType = React.memo( + function ConnectedSectionFooter(props: BaseProps) { const styles = useStyles(unboundStyles); const colors = useColors(); return ; - }); + }, +); export default ConnectedSectionFooter; diff --git a/native/chat/chat-context-provider.react.js b/native/chat/chat-context-provider.react.js --- a/native/chat/chat-context-provider.react.js +++ b/native/chat/chat-context-provider.react.js @@ -168,6 +168,6 @@ } const MemoizedChatContextProvider: React.ComponentType = - React.memo(ChatContextProvider); + React.memo(ChatContextProvider); export default MemoizedChatContextProvider; diff --git a/native/chat/chat-header.react.js b/native/chat/chat-header.react.js --- a/native/chat/chat-header.react.js +++ b/native/chat/chat-header.react.js @@ -10,11 +10,12 @@ const activeTabSelector = createActiveTabSelector(ChatRouteName); -const ChatHeader: React.ComponentType = - React.memo(function ChatHeader(props: StackHeaderProps) { +const ChatHeader: React.ComponentType = React.memo( + function ChatHeader(props: StackHeaderProps) { const navContext = React.useContext(NavContext); const activeTab = activeTabSelector(navContext); return
; - }); + }, +); export default ChatHeader; 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 @@ -1225,9 +1225,7 @@ +route: NavigationRoute<'MessageList'>, }; const ConnectedChatInputBar: React.ComponentType = - React.memo(function ConnectedChatInputBar( - props: ChatInputBarProps, - ) { + React.memo(function ConnectedChatInputBar(props: ChatInputBarProps) { const { navigation, route, ...restProps } = props; const keyboardState = React.useContext(KeyboardContext); diff --git a/native/chat/chat-item-height-measurer.react.js b/native/chat/chat-item-height-measurer.react.js --- a/native/chat/chat-item-height-measurer.react.js +++ b/native/chat/chat-item-height-measurer.react.js @@ -262,7 +262,8 @@ ); } -const MemoizedChatItemHeightMeasurer: React.ComponentType = - React.memo(ChatItemHeightMeasurer); +const MemoizedChatItemHeightMeasurer: React.ComponentType = React.memo( + ChatItemHeightMeasurer, +); export default MemoizedChatItemHeightMeasurer; diff --git a/native/chat/chat-list.react.js b/native/chat/chat-list.react.js --- a/native/chat/chat-list.react.js +++ b/native/chat/chat-list.react.js @@ -334,7 +334,7 @@ }, }); -const ConnectedChatList: React.ComponentType = React.memo( +const ConnectedChatList: React.ComponentType = React.memo( function ConnectedChatList(props: BaseProps) { const keyboardState = React.useContext(KeyboardContext); const inputState = React.useContext(InputStateContext); diff --git a/native/chat/compose-subchannel.react.js b/native/chat/compose-subchannel.react.js --- a/native/chat/compose-subchannel.react.js +++ b/native/chat/compose-subchannel.react.js @@ -369,6 +369,6 @@ }; const MemoizedComposeSubchannel: React.ComponentType = - React.memo(ComposeSubchannel); + React.memo(ComposeSubchannel); export default MemoizedComposeSubchannel; diff --git a/native/chat/compose-thread-button.react.js b/native/chat/compose-thread-button.react.js --- a/native/chat/compose-thread-button.react.js +++ b/native/chat/compose-thread-button.react.js @@ -56,6 +56,6 @@ }); const MemoizedComposeThreadButton: React.ComponentType = - React.memo(ComposeThreadButton); + React.memo(ComposeThreadButton); export default MemoizedComposeThreadButton; diff --git a/native/chat/composed-message.react.js b/native/chat/composed-message.react.js --- a/native/chat/composed-message.react.js +++ b/native/chat/composed-message.react.js @@ -48,7 +48,7 @@ +children: React.Node, }; -const ConnectedComposedMessage: React.ComponentType = React.memo( +const ConnectedComposedMessage: React.ComponentType = React.memo( function ConnectedComposedMessage(props: Props) { const composedMessageMaxWidth = useComposedMessageMaxWidth(); const colors = useColors(); diff --git a/native/chat/failed-send.react.js b/native/chat/failed-send.react.js --- a/native/chat/failed-send.react.js +++ b/native/chat/failed-send.react.js @@ -152,8 +152,8 @@ }; } -const ConnectedFailedSend: React.ComponentType = - React.memo(function ConnectedFailedSend(props: BaseProps) { +const ConnectedFailedSend: React.ComponentType = React.memo( + function ConnectedFailedSend(props: BaseProps) { const id = messageID(props.item.messageInfo); const rawMessageInfo = useSelector(state => { const message = state.messageStore.messages[id]; @@ -175,6 +175,7 @@ parentThreadInfo={parentThreadInfo} /> ); - }); + }, +); export { ConnectedFailedSend as FailedSend, failedSendHeight }; 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 @@ -174,7 +174,7 @@ }; const MemoizedInnerRobotextMessage: React.ComponentType = - React.memo(InnerRobotextMessage); + React.memo(InnerRobotextMessage); export { dummyNodeForRobotextMessageHeightMeasurement, diff --git a/native/chat/message-editing-context-provider.react.js b/native/chat/message-editing-context-provider.react.js --- a/native/chat/message-editing-context-provider.react.js +++ b/native/chat/message-editing-context-provider.react.js @@ -74,6 +74,6 @@ } const MemoizedMessageEditingContextProvider: React.ComponentType = - React.memo(MessageEditingContextProvider); + React.memo(MessageEditingContextProvider); export default MemoizedMessageEditingContextProvider; diff --git a/native/chat/message-list-container.react.js b/native/chat/message-list-container.react.js --- a/native/chat/message-list-container.react.js +++ b/native/chat/message-list-container.react.js @@ -247,9 +247,7 @@ } const ConnectedMessageListContainer: React.ComponentType = - React.memo(function ConnectedMessageListContainer( - props: BaseProps, - ) { + React.memo(function ConnectedMessageListContainer(props: BaseProps) { const [usernameInputText, setUsernameInputText] = React.useState(''); const [userInfoInputArray, setUserInfoInputArray] = React.useState< $ReadOnlyArray, diff --git a/native/chat/message-list-header-title.react.js b/native/chat/message-list-header-title.react.js --- a/native/chat/message-list-header-title.react.js +++ b/native/chat/message-list-header-title.react.js @@ -88,9 +88,7 @@ } const ConnectedMessageListHeaderTitle: React.ComponentType = - React.memo(function ConnectedMessageListHeaderTitle( - props: BaseProps, - ) { + React.memo(function ConnectedMessageListHeaderTitle(props: BaseProps) { const styles = useStyles(unboundStyles); const { uiName } = useResolvedThreadInfo(props.threadInfo); diff --git a/native/chat/message-list-thread-search.react.js b/native/chat/message-list-thread-search.react.js --- a/native/chat/message-list-thread-search.react.js +++ b/native/chat/message-list-thread-search.react.js @@ -29,7 +29,7 @@ returnKeyType: 'go', }; -const MessageListThreadSearch: React.ComponentType = React.memo( +const MessageListThreadSearch: React.ComponentType = React.memo( function MessageListThreadSearch({ usernameInputText, updateUsernameInput, diff --git a/native/chat/message-list.react.js b/native/chat/message-list.react.js --- a/native/chat/message-list.react.js +++ b/native/chat/message-list.react.js @@ -289,8 +289,8 @@ }; } -const ConnectedMessageList: React.ComponentType = - React.memo(function ConnectedMessageList(props: BaseProps) { +const ConnectedMessageList: React.ComponentType = React.memo( + function ConnectedMessageList(props: BaseProps) { const keyboardState = React.useContext(KeyboardContext); const overlayContext = React.useContext(OverlayContext); @@ -321,6 +321,7 @@ fetchMessages={fetchMessages} /> ); - }); + }, +); export default ConnectedMessageList; diff --git a/native/chat/multimedia-message-multimedia.react.js b/native/chat/multimedia-message-multimedia.react.js --- a/native/chat/multimedia-message-multimedia.react.js +++ b/native/chat/multimedia-message-multimedia.react.js @@ -50,8 +50,8 @@ }, }); -const MultimediaMessageMultimedia: React.ComponentType = - React.memo(function MultimediaMessageMultimedia(props: Props) { +const MultimediaMessageMultimedia: React.ComponentType = React.memo( + function MultimediaMessageMultimedia(props: Props) { const keyboardState = React.useContext(KeyboardContext); const overlayContext = React.useContext(OverlayContext); invariant( @@ -167,6 +167,7 @@ ); - }); + }, +); export default MultimediaMessageMultimedia; diff --git a/native/chat/multimedia-message.react.js b/native/chat/multimedia-message.react.js --- a/native/chat/multimedia-message.react.js +++ b/native/chat/multimedia-message.react.js @@ -241,8 +241,8 @@ } } -const ConnectedMultimediaMessage: React.ComponentType = - React.memo(function ConnectedMultimediaMessage(props: BaseProps) { +const ConnectedMultimediaMessage: React.ComponentType = React.memo( + function ConnectedMultimediaMessage(props: BaseProps) { const navigation = useNavigation(); const route = useRoute(); const overlayContext = React.useContext(OverlayContext); @@ -272,6 +272,7 @@ canDeleteMessage={canDeleteMessage} /> ); - }); + }, +); export default ConnectedMultimediaMessage; diff --git a/native/chat/relationship-prompt.react.js b/native/chat/relationship-prompt.react.js --- a/native/chat/relationship-prompt.react.js +++ b/native/chat/relationship-prompt.react.js @@ -19,7 +19,7 @@ +threadInfo: ThreadInfo, }; -const RelationshipPrompt: React.ComponentType = React.memo( +const RelationshipPrompt: React.ComponentType = React.memo( function RelationshipPrompt({ pendingPersonalThreadUserInfo, threadInfo, diff --git a/native/chat/settings/add-users-modal.react.js b/native/chat/settings/add-users-modal.react.js --- a/native/chat/settings/add-users-modal.react.js +++ b/native/chat/settings/add-users-modal.react.js @@ -289,6 +289,6 @@ }; const MemoizedAddUsersModal: React.ComponentType = - React.memo(AddUsersModal); + React.memo(AddUsersModal); export default MemoizedAddUsersModal; diff --git a/native/chat/settings/color-selector-modal.react.js b/native/chat/settings/color-selector-modal.react.js --- a/native/chat/settings/color-selector-modal.react.js +++ b/native/chat/settings/color-selector-modal.react.js @@ -172,8 +172,8 @@ ); } -const ConnectedColorSelectorModal: React.ComponentType = - React.memo(function ConnectedColorSelectorModal(props: BaseProps) { +const ConnectedColorSelectorModal: React.ComponentType = React.memo( + function ConnectedColorSelectorModal(props: BaseProps) { const styles = useStyles(unboundStyles); const colors = useColors(); const windowWidth = useSelector(state => state.dimensions.width); @@ -191,6 +191,7 @@ changeThreadSettings={callChangeThreadSettings} /> ); - }); + }, +); export default ConnectedColorSelectorModal; diff --git a/native/chat/settings/compose-subchannel-modal.react.js b/native/chat/settings/compose-subchannel-modal.react.js --- a/native/chat/settings/compose-subchannel-modal.react.js +++ b/native/chat/settings/compose-subchannel-modal.react.js @@ -138,9 +138,7 @@ } const ConnectedComposeSubchannelModal: React.ComponentType = - React.memo(function ConnectedComposeSubchannelModal( - props: BaseProps, - ) { + React.memo(function ConnectedComposeSubchannelModal(props: BaseProps) { const styles = useStyles(unboundStyles); const colors = useColors(); diff --git a/native/chat/settings/delete-thread.react.js b/native/chat/settings/delete-thread.react.js --- a/native/chat/settings/delete-thread.react.js +++ b/native/chat/settings/delete-thread.react.js @@ -232,8 +232,8 @@ deleteThreadActionTypes, ); -const ConnectedDeleteThread: React.ComponentType = - React.memo(function ConnectedDeleteThread(props: BaseProps) { +const ConnectedDeleteThread: React.ComponentType = React.memo( + function ConnectedDeleteThread(props: BaseProps) { const threadID = props.route.params.threadInfo.id; const reduxThreadInfo = useSelector( state => threadInfoSelector(state)[threadID], @@ -279,6 +279,7 @@ navDispatch={navDispatch} /> ); - }); + }, +); export default ConnectedDeleteThread; diff --git a/native/chat/settings/thread-settings-avatar.react.js b/native/chat/settings/thread-settings-avatar.react.js --- a/native/chat/settings/thread-settings-avatar.react.js +++ b/native/chat/settings/thread-settings-avatar.react.js @@ -34,6 +34,6 @@ }; const MemoizedThreadSettingsAvatar: React.ComponentType = - React.memo(ThreadSettingsAvatar); + React.memo(ThreadSettingsAvatar); export default MemoizedThreadSettingsAvatar; diff --git a/native/chat/settings/thread-settings-color.react.js b/native/chat/settings/thread-settings-color.react.js --- a/native/chat/settings/thread-settings-color.react.js +++ b/native/chat/settings/thread-settings-color.react.js @@ -99,10 +99,8 @@ }; } -const ConnectedThreadSettingsColor: React.ComponentType = - React.memo(function ConnectedThreadSettingsColor( - props: BaseProps, - ) { +const ConnectedThreadSettingsColor: React.ComponentType = React.memo( + function ConnectedThreadSettingsColor(props: BaseProps) { const threadID = props.threadInfo.id; const loadingStatus = useSelector( createLoadingStatusSelector( @@ -120,6 +118,7 @@ styles={styles} /> ); - }); + }, +); export default ConnectedThreadSettingsColor; diff --git a/native/chat/settings/thread-settings-description.react.js b/native/chat/settings/thread-settings-description.react.js --- a/native/chat/settings/thread-settings-description.react.js +++ b/native/chat/settings/thread-settings-description.react.js @@ -291,9 +291,7 @@ } const ConnectedThreadSettingsDescription: React.ComponentType = - React.memo(function ConnectedThreadSettingsDescription( - props: BaseProps, - ) { + React.memo(function ConnectedThreadSettingsDescription(props: BaseProps) { const threadID = props.threadInfo.id; const loadingStatus = useSelector( createLoadingStatusSelector( 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 @@ -32,8 +32,8 @@ +relationshipButton: RelationshipButton, }; -const ThreadSettingsEditRelationship: React.ComponentType = - React.memo(function ThreadSettingsEditRelationship(props: Props) { +const ThreadSettingsEditRelationship: React.ComponentType = React.memo( + function ThreadSettingsEditRelationship(props: Props) { const otherUserInfoFromRedux = useSelector(state => { const currentUserID = state.currentUserInfo?.id; const otherUserID = getSingleOtherUser(props.threadInfo, currentUserID); @@ -109,7 +109,8 @@ ); - }); + }, +); const unboundStyles = { button: { diff --git a/native/chat/settings/thread-settings-leave-thread.react.js b/native/chat/settings/thread-settings-leave-thread.react.js --- a/native/chat/settings/thread-settings-leave-thread.react.js +++ b/native/chat/settings/thread-settings-leave-thread.react.js @@ -135,9 +135,7 @@ } const ConnectedThreadSettingsLeaveThread: React.ComponentType = - React.memo(function ConnectedThreadSettingsLeaveThread( - props: BaseProps, - ) { + React.memo(function ConnectedThreadSettingsLeaveThread(props: BaseProps) { const threadID = props.threadInfo.id; const loadingStatus = useSelector( createLoadingStatusSelector( diff --git a/native/chat/settings/thread-settings-member.react.js b/native/chat/settings/thread-settings-member.react.js --- a/native/chat/settings/thread-settings-member.react.js +++ b/native/chat/settings/thread-settings-member.react.js @@ -242,9 +242,7 @@ } const ConnectedThreadSettingsMember: React.ComponentType = - React.memo(function ConnectedThreadSettingsMember( - props: BaseProps, - ) { + React.memo(function ConnectedThreadSettingsMember(props: BaseProps) { const memberID = props.memberInfo.id; const removeUserLoadingStatus = useSelector(state => createLoadingStatusSelector( diff --git a/native/chat/settings/thread-settings-name.react.js b/native/chat/settings/thread-settings-name.react.js --- a/native/chat/settings/thread-settings-name.react.js +++ b/native/chat/settings/thread-settings-name.react.js @@ -215,8 +215,8 @@ }; } -const ConnectedThreadSettingsName: React.ComponentType = - React.memo(function ConnectedThreadSettingsName(props: BaseProps) { +const ConnectedThreadSettingsName: React.ComponentType = React.memo( + function ConnectedThreadSettingsName(props: BaseProps) { const styles = useStyles(unboundStyles); const colors = useColors(); @@ -241,6 +241,7 @@ changeThreadSettings={callChangeThreadSettings} /> ); - }); + }, +); export default ConnectedThreadSettingsName; diff --git a/native/chat/settings/thread-settings-parent.react.js b/native/chat/settings/thread-settings-parent.react.js --- a/native/chat/settings/thread-settings-parent.react.js +++ b/native/chat/settings/thread-settings-parent.react.js @@ -110,6 +110,6 @@ }; const ConnectedThreadSettingsParent: React.ComponentType = - React.memo(ThreadSettingsParent); + React.memo(ThreadSettingsParent); export default ConnectedThreadSettingsParent; diff --git a/native/chat/settings/thread-settings-promote-sidebar.react.js b/native/chat/settings/thread-settings-promote-sidebar.react.js --- a/native/chat/settings/thread-settings-promote-sidebar.react.js +++ b/native/chat/settings/thread-settings-promote-sidebar.react.js @@ -95,9 +95,7 @@ }; const ConnectedThreadSettingsPromoteSidebar: React.ComponentType = - React.memo(function ConnectedThreadSettingsPromoteSidebar( - props: BaseProps, - ) { + React.memo(function ConnectedThreadSettingsPromoteSidebar(props: BaseProps) { const { threadInfo } = props; const colors = useColors(); const styles = useStyles(unboundStyles); diff --git a/native/chat/settings/thread-settings-push-notifs.react.js b/native/chat/settings/thread-settings-push-notifs.react.js --- a/native/chat/settings/thread-settings-push-notifs.react.js +++ b/native/chat/settings/thread-settings-push-notifs.react.js @@ -140,9 +140,7 @@ } const ConnectedThreadSettingsPushNotifs: React.ComponentType = - React.memo(function ConnectedThreadSettingsPushNotifs( - props: BaseProps, - ) { + React.memo(function ConnectedThreadSettingsPushNotifs(props: BaseProps) { const keyserverID = extractKeyserverIDFromIDOptional(props.threadInfo.id); const deviceToken = useSelector(state => { if (!keyserverID) { diff --git a/native/chat/settings/thread-settings.react.js b/native/chat/settings/thread-settings.react.js --- a/native/chat/settings/thread-settings.react.js +++ b/native/chat/settings/thread-settings.react.js @@ -1150,8 +1150,8 @@ return false; }; -const ConnectedThreadSettings: React.ComponentType = - React.memo(function ConnectedThreadSettings(props: BaseProps) { +const ConnectedThreadSettings: React.ComponentType = React.memo( + function ConnectedThreadSettings(props: BaseProps) { const userInfos = useSelector(state => state.userStore.userInfos); const viewerID = useSelector( state => state.currentUserInfo && state.currentUserInfo.id, @@ -1346,6 +1346,7 @@ inviteLinkExists={!!inviteLink} /> ); - }); + }, +); export default ConnectedThreadSettings; diff --git a/native/chat/text-message.react.js b/native/chat/text-message.react.js --- a/native/chat/text-message.react.js +++ b/native/chat/text-message.react.js @@ -257,8 +257,8 @@ }; } -const ConnectedTextMessage: React.ComponentType = - React.memo(function ConnectedTextMessage(props: BaseProps) { +const ConnectedTextMessage: React.ComponentType = React.memo( + function ConnectedTextMessage(props: BaseProps) { const overlayContext = React.useContext(OverlayContext); const chatContext = React.useContext(ChatContext); const markdownContext = React.useContext(MarkdownContext); @@ -318,6 +318,7 @@ canDeleteMessage={canDeleteMessage} /> ); - }); + }, +); export { ConnectedTextMessage as TextMessage }; diff --git a/native/chat/thread-screen-pruner.react.js b/native/chat/thread-screen-pruner.react.js --- a/native/chat/thread-screen-pruner.react.js +++ b/native/chat/thread-screen-pruner.react.js @@ -22,7 +22,7 @@ import type { AppState } from '../redux/state-types.js'; import Alert from '../utils/alert.js'; -const ThreadScreenPruner: React.ComponentType<{}> = React.memo<{}>( +const ThreadScreenPruner: React.ComponentType<{}> = React.memo( function ThreadScreenPruner() { const rawThreadInfos = useSelector( (state: AppState) => state.threadStore.threadInfos, diff --git a/native/chat/thread-settings-button.react.js b/native/chat/thread-settings-button.react.js --- a/native/chat/thread-settings-button.react.js +++ b/native/chat/thread-settings-button.react.js @@ -50,9 +50,7 @@ } const ConnectedThreadSettingsButton: React.ComponentType = - React.memo(function ConnectedThreadSettingsButton( - props: BaseProps, - ) { + React.memo(function ConnectedThreadSettingsButton(props: BaseProps) { const styles = useStyles(unboundStyles); return ; diff --git a/native/chat/thread-settings-header-title.react.js b/native/chat/thread-settings-header-title.react.js --- a/native/chat/thread-settings-header-title.react.js +++ b/native/chat/thread-settings-header-title.react.js @@ -19,6 +19,6 @@ } const MemoizedThreadSettingsHeaderTitle: React.ComponentType = - React.memo(ThreadSettingsHeaderTitle); + React.memo(ThreadSettingsHeaderTitle); export default MemoizedThreadSettingsHeaderTitle; diff --git a/native/components/community-list-item.react.js b/native/components/community-list-item.react.js --- a/native/components/community-list-item.react.js +++ b/native/components/community-list-item.react.js @@ -191,7 +191,7 @@ } const MemoizedCommunityListItem: React.ComponentType = - React.memo(CommunityListItem); + React.memo(CommunityListItem); const unboundStyles = { activityIndicatorContainer: { diff --git a/native/components/full-screen-view-modal.react.js b/native/components/full-screen-view-modal.react.js --- a/native/components/full-screen-view-modal.react.js +++ b/native/components/full-screen-view-modal.react.js @@ -877,6 +877,6 @@ }); const MemoizedFullScreenViewModal: React.ComponentType = - React.memo(FullScreenViewModal); + React.memo(FullScreenViewModal); export default MemoizedFullScreenViewModal; diff --git a/native/components/keyboard-avoiding-view.react.js b/native/components/keyboard-avoiding-view.react.js --- a/native/components/keyboard-avoiding-view.react.js +++ b/native/components/keyboard-avoiding-view.react.js @@ -29,13 +29,14 @@ +behavior: 'height' | 'position' | 'padding', +contentContainerStyle?: ?ViewStyle, }; -const KeyboardAvoidingView: React.ComponentType = - React.memo(function KeyboardAvoidingView(props: BaseProps) { +const KeyboardAvoidingView: React.ComponentType = React.memo( + function KeyboardAvoidingView(props: BaseProps) { const keyboardState = React.useContext(KeyboardContext); return ( ); - }); + }, +); type Props = { ...BaseProps, diff --git a/native/components/link-button.react.js b/native/components/link-button.react.js --- a/native/components/link-button.react.js +++ b/native/components/link-button.react.js @@ -49,11 +49,12 @@ } } -const ConnectedLinkButton: React.ComponentType = - React.memo(function ConnectedLinkButton(props: BaseProps) { +const ConnectedLinkButton: React.ComponentType = React.memo( + function ConnectedLinkButton(props: BaseProps) { const styles = useStyles(unboundStyles); return ; - }); + }, +); export default ConnectedLinkButton; diff --git a/native/components/search.react.js b/native/components/search.react.js --- a/native/components/search.react.js +++ b/native/components/search.react.js @@ -144,7 +144,7 @@ const MemoizedSearch: SearchComponentType = React.memo< Props, - React.ElementRef, + React.RefSetter>, >(Search); export default MemoizedSearch; diff --git a/native/components/selectable-text-input.react.ios.js b/native/components/selectable-text-input.react.ios.js --- a/native/components/selectable-text-input.react.ios.js +++ b/native/components/selectable-text-input.react.ios.js @@ -137,7 +137,7 @@ ); const MemoizedSelectableTextInput: MemoizedSelectableTextInputComponent = - React.memo( + React.memo>( SelectableTextInput, ); diff --git a/native/components/selectable-text-input.react.js b/native/components/selectable-text-input.react.js --- a/native/components/selectable-text-input.react.js +++ b/native/components/selectable-text-input.react.js @@ -82,7 +82,7 @@ ); const MemoizedSelectableTextInput: MemoizedSelectableTextInputComponent = - React.memo( + React.memo>( SelectableTextInput, ); diff --git a/native/components/thread-list-thread.react.js b/native/components/thread-list-thread.react.js --- a/native/components/thread-list-thread.react.js +++ b/native/components/thread-list-thread.react.js @@ -69,8 +69,8 @@ }; } -const ConnectedThreadListThread: React.ComponentType = - React.memo(function ConnectedThreadListThread(props: BaseProps) { +const ConnectedThreadListThread: React.ComponentType = React.memo( + function ConnectedThreadListThread(props: BaseProps) { const { threadInfo, ...rest } = props; const styles = useStyles(unboundStyles); const colors = useColors(); @@ -84,6 +84,7 @@ colors={colors} /> ); - }); + }, +); export default ConnectedThreadListThread; diff --git a/native/components/thread-list.react.js b/native/components/thread-list.react.js --- a/native/components/thread-list.react.js +++ b/native/components/thread-list.react.js @@ -144,14 +144,15 @@ }; } -const ConnectedThreadList: React.ComponentType = - React.memo(function ConnectedThreadList(props: BaseProps) { +const ConnectedThreadList: React.ComponentType = React.memo( + function ConnectedThreadList(props: BaseProps) { const styles = useStyles(unboundStyles); const indicatorStyle = useIndicatorStyle(); return ( ); - }); + }, +); export default ConnectedThreadList; diff --git a/native/components/user-list-user.react.js b/native/components/user-list-user.react.js --- a/native/components/user-list-user.react.js +++ b/native/components/user-list-user.react.js @@ -88,11 +88,12 @@ }; } -const ConnectedUserListUser: React.ComponentType = - React.memo(function ConnectedUserListUser(props: BaseProps) { +const ConnectedUserListUser: React.ComponentType = React.memo( + function ConnectedUserListUser(props: BaseProps) { const colors = useColors(); const styles = useStyles(unboundStyles); return ; - }); + }, +); export { ConnectedUserListUser as UserListUser, getUserListItemHeight }; diff --git a/native/components/user-list.react.js b/native/components/user-list.react.js --- a/native/components/user-list.react.js +++ b/native/components/user-list.react.js @@ -68,7 +68,7 @@ }; } -const ConnectedUserList: React.ComponentType = React.memo( +const ConnectedUserList: React.ComponentType = React.memo( function ConnectedUserList(props: BaseProps) { const indicatorStyle = useIndicatorStyle(); return ; diff --git a/native/crash.react.js b/native/crash.react.js --- a/native/crash.react.js +++ b/native/crash.react.js @@ -281,7 +281,7 @@ }, }); -const ConnectedCrash: React.ComponentType = React.memo( +const ConnectedCrash: React.ComponentType = React.memo( function ConnectedCrash(props: BaseProps) { const dispatchActionPromise = useDispatchActionPromise(); const callLogOut = useLogOut(); diff --git a/native/input/input-state-container.react.js b/native/input/input-state-container.react.js --- a/native/input/input-state-container.react.js +++ b/native/input/input-state-container.react.js @@ -1656,10 +1656,8 @@ sendTextMessageActionTypes, ); -const ConnectedInputStateContainer: React.ComponentType = - React.memo(function ConnectedInputStateContainer( - props: BaseProps, - ) { +const ConnectedInputStateContainer: React.ComponentType = React.memo( + function ConnectedInputStateContainer(props: BaseProps) { const viewerID = useSelector( state => state.currentUserInfo && state.currentUserInfo.id, ); @@ -1707,6 +1705,7 @@ invalidTokenLogOut={callInvalidTokenLogOut} /> ); - }); + }, +); export default ConnectedInputStateContainer; diff --git a/native/keyboard/keyboard-input-host.react.js b/native/keyboard/keyboard-input-host.react.js --- a/native/keyboard/keyboard-input-host.react.js +++ b/native/keyboard/keyboard-input-host.react.js @@ -100,8 +100,8 @@ }; } -const ConnectedKeyboardInputHost: React.ComponentType = - React.memo(function ConnectedKeyboardInputHost(props: BaseProps) { +const ConnectedKeyboardInputHost: React.ComponentType = React.memo( + function ConnectedKeyboardInputHost(props: BaseProps) { const inputState = React.useContext(InputStateContext); const keyboardState = React.useContext(KeyboardContext); invariant(keyboardState, 'keyboardState should be initialized'); @@ -118,6 +118,7 @@ inputState={inputState} /> ); - }); + }, +); export default ConnectedKeyboardInputHost; diff --git a/native/lifecycle/lifecycle-handler.react.js b/native/lifecycle/lifecycle-handler.react.js --- a/native/lifecycle/lifecycle-handler.react.js +++ b/native/lifecycle/lifecycle-handler.react.js @@ -10,7 +10,7 @@ import { appBecameInactive } from '../redux/redux-setup.js'; import { useSelector } from '../redux/redux-utils.js'; -const LifecycleHandler: React.ComponentType<{}> = React.memo<{}>( +const LifecycleHandler: React.ComponentType<{}> = React.memo( function LifecycleHandler() { const dispatch = useDispatch(); diff --git a/native/media/camera-modal.react.js b/native/media/camera-modal.react.js --- a/native/media/camera-modal.react.js +++ b/native/media/camera-modal.react.js @@ -259,662 +259,655 @@ }, }); -const CameraModal: React.ComponentType = React.memo( - function CameraModal(props: Props) { - const deviceCameraInfo = useSelector(state => state.deviceCameraInfo); - const deviceOrientation = useSelector(state => state.deviceOrientation); - const foreground = useIsAppForegrounded(); - const overlayContext = React.useContext(OverlayContext); - const dispatch = useDispatch(); - - const { navigation, handlePhotoCapture } = props; - - const isActive = !overlayContext || !overlayContext.isDismissing; - - React.useEffect(() => { - if (isActive) { - Orientation.unlockAllOrientations(); - } else { - Orientation.lockToPortrait(); - } - }, [isActive]); - - React.useEffect(() => { - return () => { - Orientation.lockToPortrait(); - }; - }, []); - - const [flashMode, setFlashMode] = React.useState('off'); - - const changeFlashMode = React.useCallback(() => { - setFlashMode(prevFlashMode => { - if (prevFlashMode === 'on') { - return 'off'; - } else if (prevFlashMode === 'off') { - return 'auto'; - } - return 'on'; - }); - }, []); - - const [useFrontCamera, setUseFrontCamera] = React.useState( - deviceCameraInfo.defaultUseFrontCamera, - ); - - const switchCamera = React.useCallback(() => { - setUseFrontCamera(prevUseFrontCamera => !prevUseFrontCamera); - }, []); +const CameraModal: React.ComponentType = React.memo(function CameraModal( + props: Props, +) { + const deviceCameraInfo = useSelector(state => state.deviceCameraInfo); + const deviceOrientation = useSelector(state => state.deviceOrientation); + const foreground = useIsAppForegrounded(); + const overlayContext = React.useContext(OverlayContext); + const dispatch = useDispatch(); + + const { navigation, handlePhotoCapture } = props; + + const isActive = !overlayContext || !overlayContext.isDismissing; + + React.useEffect(() => { + if (isActive) { + Orientation.unlockAllOrientations(); + } else { + Orientation.lockToPortrait(); + } + }, [isActive]); - const [hasCamerasOnBothSides, setHasCamerasOnBothSides] = React.useState( - deviceCameraInfo.hasCamerasOnBothSides, - ); + React.useEffect(() => { + return () => { + Orientation.lockToPortrait(); + }; + }, []); - const cameraIDsFetched = React.useRef(false); + const [flashMode, setFlashMode] = React.useState('off'); - const fetchCameraIDs = React.useCallback(async () => { - if (cameraIDsFetched.current) { - return; - } - cameraIDsFetched.current = true; - - const deviceCameras = Camera.getAvailableCameraDevices(); - - let hasFront = false, - hasBack = false, - i = 0; - while ((!hasFront || !hasBack) && i < deviceCameras.length) { - const deviceCamera = deviceCameras[i]; - if (deviceCamera.position === 'front') { - hasFront = true; - } else if (deviceCamera.position === 'back') { - hasBack = true; - } - i++; + const changeFlashMode = React.useCallback(() => { + setFlashMode(prevFlashMode => { + if (prevFlashMode === 'on') { + return 'off'; + } else if (prevFlashMode === 'off') { + return 'auto'; } + return 'on'; + }); + }, []); - const nextHasCamerasOnBothSides = hasFront && hasBack; - const defaultUseFrontCamera = !hasBack && hasFront; - if (nextHasCamerasOnBothSides !== hasCamerasOnBothSides) { - setHasCamerasOnBothSides(nextHasCamerasOnBothSides); - } - const { - hasCamerasOnBothSides: oldHasCamerasOnBothSides, - defaultUseFrontCamera: oldDefaultUseFrontCamera, - } = deviceCameraInfo; - if ( - nextHasCamerasOnBothSides !== oldHasCamerasOnBothSides || - defaultUseFrontCamera !== oldDefaultUseFrontCamera - ) { - dispatch({ - type: updateDeviceCameraInfoActionType, - payload: { - hasCamerasOnBothSides: nextHasCamerasOnBothSides, - defaultUseFrontCamera, - }, - }); - } - }, [deviceCameraInfo, dispatch, hasCamerasOnBothSides]); + const [useFrontCamera, setUseFrontCamera] = React.useState( + deviceCameraInfo.defaultUseFrontCamera, + ); - const cameraRef = React.useRef(); + const switchCamera = React.useCallback(() => { + setUseFrontCamera(prevUseFrontCamera => !prevUseFrontCamera); + }, []); - const focusOnPoint = React.useCallback( - ([inputX, inputY]: [number, number]) => { - const camera = cameraRef.current; - invariant(camera, 'camera ref should be set'); - void camera.focus({ x: inputX, y: inputY }); - }, - [], - ); + const [hasCamerasOnBothSides, setHasCamerasOnBothSides] = React.useState( + deviceCameraInfo.hasCamerasOnBothSides, + ); - const [stagingMode, setStagingMode] = React.useState(false); - const [pendingPhotoCapture, setPendingPhotoCapture] = - React.useState(); + const cameraIDsFetched = React.useRef(false); - const takePhoto = React.useCallback(async () => { - const camera = cameraRef.current; - invariant(camera, 'camera ref should be set'); - setStagingMode(true); + const fetchCameraIDs = React.useCallback(async () => { + if (cameraIDsFetched.current) { + return; + } + cameraIDsFetched.current = true; + + const deviceCameras = Camera.getAvailableCameraDevices(); + + let hasFront = false, + hasBack = false, + i = 0; + while ((!hasFront || !hasBack) && i < deviceCameras.length) { + const deviceCamera = deviceCameras[i]; + if (deviceCamera.position === 'front') { + hasFront = true; + } else if (deviceCamera.position === 'back') { + hasBack = true; + } + i++; + } - const startTime = Date.now(); - const photoPromise = camera.takePhoto({ - flash: flashMode, + const nextHasCamerasOnBothSides = hasFront && hasBack; + const defaultUseFrontCamera = !hasBack && hasFront; + if (nextHasCamerasOnBothSides !== hasCamerasOnBothSides) { + setHasCamerasOnBothSides(nextHasCamerasOnBothSides); + } + const { + hasCamerasOnBothSides: oldHasCamerasOnBothSides, + defaultUseFrontCamera: oldDefaultUseFrontCamera, + } = deviceCameraInfo; + if ( + nextHasCamerasOnBothSides !== oldHasCamerasOnBothSides || + defaultUseFrontCamera !== oldDefaultUseFrontCamera + ) { + dispatch({ + type: updateDeviceCameraInfoActionType, + payload: { + hasCamerasOnBothSides: nextHasCamerasOnBothSides, + defaultUseFrontCamera, + }, }); + } + }, [deviceCameraInfo, dispatch, hasCamerasOnBothSides]); - const { path: uri, width, height } = await photoPromise; + const cameraRef = React.useRef(); - const filename = filenameFromPathOrURI(uri); - invariant( - filename, - `unable to parse filename out of react-native-vision-camera URI ${uri}`, - ); + const focusOnPoint = React.useCallback( + ([inputX, inputY]: [number, number]) => { + const camera = cameraRef.current; + invariant(camera, 'camera ref should be set'); + void camera.focus({ x: inputX, y: inputY }); + }, + [], + ); + + const [stagingMode, setStagingMode] = React.useState(false); + const [pendingPhotoCapture, setPendingPhotoCapture] = + React.useState(); + + const takePhoto = React.useCallback(async () => { + const camera = cameraRef.current; + invariant(camera, 'camera ref should be set'); + setStagingMode(true); + + const startTime = Date.now(); + const photoPromise = camera.takePhoto({ + flash: flashMode, + }); - const now = Date.now(); - const nextPendingPhotoCapture = { - step: 'photo_capture', - // If you want to consume this file (e.g. for displaying it in an component), you might have to add the file:// prefix. - // https://react-native-vision-camera.com/docs/api/interfaces/PhotoFile#path - uri: uri.startsWith('file://') ? uri : 'file://' + uri, - dimensions: { width, height }, - filename, - time: now - startTime, - captureTime: now, - selectTime: 0, - sendTime: 0, - retries: 0, - }; - setPendingPhotoCapture(nextPendingPhotoCapture); - }, [flashMode]); - - const close = React.useCallback(() => { - if (overlayContext && navigation.goBackOnce) { - navigation.goBackOnce(); - } else { - navigation.goBack(); - } - }, [navigation, overlayContext]); + const { path: uri, width, height } = await photoPromise; - const sendPhoto = React.useCallback(async () => { - if (!pendingPhotoCapture) { - return; - } + const filename = filenameFromPathOrURI(uri); + invariant( + filename, + `unable to parse filename out of react-native-vision-camera URI ${uri}`, + ); - const now = Date.now(); - const capture = { - ...pendingPhotoCapture, - selectTime: now, - sendTime: now, - }; + const now = Date.now(); + const nextPendingPhotoCapture = { + step: 'photo_capture', + // If you want to consume this file (e.g. for displaying it in an component), you might have to add the file:// prefix. + // https://react-native-vision-camera.com/docs/api/interfaces/PhotoFile#path + uri: uri.startsWith('file://') ? uri : 'file://' + uri, + dimensions: { width, height }, + filename, + time: now - startTime, + captureTime: now, + selectTime: 0, + sendTime: 0, + retries: 0, + }; + setPendingPhotoCapture(nextPendingPhotoCapture); + }, [flashMode]); + + const close = React.useCallback(() => { + if (overlayContext && navigation.goBackOnce) { + navigation.goBackOnce(); + } else { + navigation.goBack(); + } + }, [navigation, overlayContext]); - close(); - handlePhotoCapture(capture); - }, [close, handlePhotoCapture, pendingPhotoCapture]); - - const clearPendingImage = React.useCallback(() => { - invariant(cameraRef.current, 'camera ref should be set'); - setStagingMode(false); - setPendingPhotoCapture(); - }, []); - - const closeButtonRef = React.useRef>(); - const closeButtonDimensions = useSharedValue({ - x: -1, - y: -1, - width: 0, - height: 0, - }); + const sendPhoto = React.useCallback(async () => { + if (!pendingPhotoCapture) { + return; + } - const photoButtonRef = React.useRef>(); - const photoButtonDimensions = useSharedValue({ - x: -1, - y: -1, - width: 0, - height: 0, - }); + const now = Date.now(); + const capture = { + ...pendingPhotoCapture, + selectTime: now, + sendTime: now, + }; - const switchCameraButtonRef = - React.useRef>(); - const switchCameraButtonDimensions = useSharedValue({ - x: -1, - y: -1, - width: 0, - height: 0, + close(); + handlePhotoCapture(capture); + }, [close, handlePhotoCapture, pendingPhotoCapture]); + + const clearPendingImage = React.useCallback(() => { + invariant(cameraRef.current, 'camera ref should be set'); + setStagingMode(false); + setPendingPhotoCapture(); + }, []); + + const closeButtonRef = React.useRef>(); + const closeButtonDimensions = useSharedValue({ + x: -1, + y: -1, + width: 0, + height: 0, + }); + + const photoButtonRef = React.useRef>(); + const photoButtonDimensions = useSharedValue({ + x: -1, + y: -1, + width: 0, + height: 0, + }); + + const switchCameraButtonRef = React.useRef>(); + const switchCameraButtonDimensions = useSharedValue({ + x: -1, + y: -1, + width: 0, + height: 0, + }); + + const flashButtonRef = React.useRef>(); + const flashButtonDimensions = useSharedValue({ + x: -1, + y: -1, + width: 0, + height: 0, + }); + + const onCloseButtonLayout = React.useCallback(() => { + if (!closeButtonRef.current) { + return; + } + closeButtonRef.current.measure((x, y, width, height, pageX, pageY) => { + closeButtonDimensions.value = { x: pageX, y: pageY, width, height }; }); + }, [closeButtonDimensions]); - const flashButtonRef = React.useRef>(); - const flashButtonDimensions = useSharedValue({ - x: -1, - y: -1, - width: 0, - height: 0, + const onPhotoButtonLayout = React.useCallback(() => { + if (!photoButtonRef.current) { + return; + } + photoButtonRef.current.measure((x, y, width, height, pageX, pageY) => { + photoButtonDimensions.value = { x: pageX, y: pageY, width, height }; }); + }, [photoButtonDimensions]); - const onCloseButtonLayout = React.useCallback(() => { - if (!closeButtonRef.current) { - return; - } - closeButtonRef.current.measure((x, y, width, height, pageX, pageY) => { - closeButtonDimensions.value = { x: pageX, y: pageY, width, height }; - }); - }, [closeButtonDimensions]); - - const onPhotoButtonLayout = React.useCallback(() => { - if (!photoButtonRef.current) { - return; - } - photoButtonRef.current.measure((x, y, width, height, pageX, pageY) => { - photoButtonDimensions.value = { x: pageX, y: pageY, width, height }; - }); - }, [photoButtonDimensions]); - - const onSwitchCameraButtonLayout = React.useCallback(() => { - if (!switchCameraButtonRef.current) { - return; - } - switchCameraButtonRef.current.measure( - (x, y, width, height, pageX, pageY) => { - switchCameraButtonDimensions.value = { - x: pageX, - y: pageY, - width, - height, - }; - }, - ); - }, [switchCameraButtonDimensions]); - - React.useEffect(() => { - if (!hasCamerasOnBothSides) { + const onSwitchCameraButtonLayout = React.useCallback(() => { + if (!switchCameraButtonRef.current) { + return; + } + switchCameraButtonRef.current.measure( + (x, y, width, height, pageX, pageY) => { switchCameraButtonDimensions.value = { - x: -1, - y: -1, - width: 0, - height: 0, + x: pageX, + y: pageY, + width, + height, }; - } - }, [hasCamerasOnBothSides, switchCameraButtonDimensions]); + }, + ); + }, [switchCameraButtonDimensions]); + + React.useEffect(() => { + if (!hasCamerasOnBothSides) { + switchCameraButtonDimensions.value = { + x: -1, + y: -1, + width: 0, + height: 0, + }; + } + }, [hasCamerasOnBothSides, switchCameraButtonDimensions]); - const onFlashButtonLayout = React.useCallback(() => { - if (!flashButtonRef.current) { - return; - } - flashButtonRef.current.measure((x, y, width, height, pageX, pageY) => { - flashButtonDimensions.value = { x: pageX, y: pageY, width, height }; - }); - }, [flashButtonDimensions]); - - const insets = useSafeAreaInsets(); - - const outsideButtons = React.useCallback( - (x: number, y: number) => { - 'worklet'; - const isOutsideButton = (dim: Dimensions) => { - return ( - x < dim.x || - x > dim.x + dim.width || - y + insets.top < dim.y || - y + insets.top > dim.y + dim.height - ); - }; - const isOutsideCloseButton = isOutsideButton( - closeButtonDimensions.value, - ); - const isOutsidePhotoButton = isOutsideButton( - photoButtonDimensions.value, - ); - const isOutsideSwitchCameraButton = isOutsideButton( - switchCameraButtonDimensions.value, - ); - const isOutsideFlashButton = isOutsideButton( - flashButtonDimensions.value, - ); + const onFlashButtonLayout = React.useCallback(() => { + if (!flashButtonRef.current) { + return; + } + flashButtonRef.current.measure((x, y, width, height, pageX, pageY) => { + flashButtonDimensions.value = { x: pageX, y: pageY, width, height }; + }); + }, [flashButtonDimensions]); + const insets = useSafeAreaInsets(); + + const outsideButtons = React.useCallback( + (x: number, y: number) => { + 'worklet'; + const isOutsideButton = (dim: Dimensions) => { return ( - isOutsideCloseButton && - isOutsidePhotoButton && - isOutsideSwitchCameraButton && - isOutsideFlashButton + x < dim.x || + x > dim.x + dim.width || + y + insets.top < dim.y || + y + insets.top > dim.y + dim.height ); - }, - [ - closeButtonDimensions.value, - flashButtonDimensions.value, - insets.top, - photoButtonDimensions.value, + }; + const isOutsideCloseButton = isOutsideButton(closeButtonDimensions.value); + const isOutsidePhotoButton = isOutsideButton(photoButtonDimensions.value); + const isOutsideSwitchCameraButton = isOutsideButton( switchCameraButtonDimensions.value, - ], - ); - - const focusIndicatorScale = useSharedValue(0.75); - const focusIndicatorPosition = useSharedValue({ x: 0, y: 0 }); - const focusIndicatorOpacity = useSharedValue(0); - const numScaleLoops = useSharedValue(0); + ); + const isOutsideFlashButton = isOutsideButton(flashButtonDimensions.value); - const startFocusAnimation = React.useCallback( - (x: number, y: number) => { - 'worklet'; - focusIndicatorPosition.value = { x, y }; - focusIndicatorOpacity.value = 1; + return ( + isOutsideCloseButton && + isOutsidePhotoButton && + isOutsideSwitchCameraButton && + isOutsideFlashButton + ); + }, + [ + closeButtonDimensions.value, + flashButtonDimensions.value, + insets.top, + photoButtonDimensions.value, + switchCameraButtonDimensions.value, + ], + ); + + const focusIndicatorScale = useSharedValue(0.75); + const focusIndicatorPosition = useSharedValue({ x: 0, y: 0 }); + const focusIndicatorOpacity = useSharedValue(0); + const numScaleLoops = useSharedValue(0); + + const startFocusAnimation = React.useCallback( + (x: number, y: number) => { + 'worklet'; + focusIndicatorPosition.value = { x, y }; + focusIndicatorOpacity.value = 1; + numScaleLoops.value = 0; + focusIndicatorScale.value = 0.75; + focusIndicatorScale.value = withSpring(1, indicatorSpringConfig); + }, + [ + focusIndicatorOpacity, + focusIndicatorPosition, + focusIndicatorScale, + numScaleLoops, + ], + ); + + useAnimatedReaction( + () => focusIndicatorScale.value, + (prevScale, currScale) => { + if (prevScale <= 1.2 && currScale > 1.2) { + numScaleLoops.value++; + } + if (numScaleLoops.value > 1) { numScaleLoops.value = 0; - focusIndicatorScale.value = 0.75; - focusIndicatorScale.value = withSpring(1, indicatorSpringConfig); - }, - [ - focusIndicatorOpacity, - focusIndicatorPosition, - focusIndicatorScale, - numScaleLoops, + focusIndicatorScale.value = withDelay( + 400, + withTiming(0, indicatorTimingConfig), + ); + focusIndicatorOpacity.value = withDelay( + 400, + withTiming(0, indicatorTimingConfig), + ); + } + }, + ); + + const cancelFocusAnimation = React.useCallback(() => { + cancelAnimation(focusIndicatorScale); + cancelAnimation(focusIndicatorOpacity); + focusIndicatorOpacity.value = 0; + }, [focusIndicatorOpacity, focusIndicatorScale]); + + const focusIndicatorAnimatedStyle = useAnimatedStyle( + () => ({ + opacity: focusIndicatorOpacity.value, + transform: [ + { translateX: focusIndicatorPosition.value.x }, + { translateY: focusIndicatorPosition.value.y }, + { scale: focusIndicatorScale.value }, ], - ); + }), + [], + ); - useAnimatedReaction( - () => focusIndicatorScale.value, - (prevScale, currScale) => { - if (prevScale <= 1.2 && currScale > 1.2) { - numScaleLoops.value++; - } - if (numScaleLoops.value > 1) { - numScaleLoops.value = 0; - focusIndicatorScale.value = withDelay( - 400, - withTiming(0, indicatorTimingConfig), - ); - focusIndicatorOpacity.value = withDelay( - 400, - withTiming(0, indicatorTimingConfig), - ); - } - }, - ); + const focusIndicatorStyle = React.useMemo( + () => [styles.focusIndicator, focusIndicatorAnimatedStyle], + [focusIndicatorAnimatedStyle], + ); - const cancelFocusAnimation = React.useCallback(() => { - cancelAnimation(focusIndicatorScale); - cancelAnimation(focusIndicatorOpacity); - focusIndicatorOpacity.value = 0; - }, [focusIndicatorOpacity, focusIndicatorScale]); - - const focusIndicatorAnimatedStyle = useAnimatedStyle( - () => ({ - opacity: focusIndicatorOpacity.value, - transform: [ - { translateX: focusIndicatorPosition.value.x }, - { translateY: focusIndicatorPosition.value.y }, - { scale: focusIndicatorScale.value }, - ], - }), - [], - ); + const zoomBase = useSharedValue(1); + const currentZoom = useSharedValue(1); - const focusIndicatorStyle = React.useMemo( - () => [styles.focusIndicator, focusIndicatorAnimatedStyle], - [focusIndicatorAnimatedStyle], - ); + const animatedProps = useAnimatedProps( + () => ({ zoom: currentZoom.value }), + [currentZoom], + ); - const zoomBase = useSharedValue(1); - const currentZoom = useSharedValue(1); - - const animatedProps = useAnimatedProps( - () => ({ zoom: currentZoom.value }), - [currentZoom], - ); - - const onPinchUpdate = React.useCallback( - (pinchScale: number) => { - 'worklet'; - currentZoom.value = clamp(zoomBase.value * pinchScale, 1, 8); - }, - [currentZoom, zoomBase.value], - ); - - const onPinchEnd = React.useCallback(() => { + const onPinchUpdate = React.useCallback( + (pinchScale: number) => { 'worklet'; - zoomBase.value = currentZoom.value; - }, [currentZoom, zoomBase]); - - const gesture = React.useMemo(() => { - const pinchGesture = Gesture.Pinch() - .onUpdate(({ scale }) => onPinchUpdate(scale)) - .onEnd(() => onPinchEnd()); - const tapGesture = Gesture.Tap().onStart(({ x, y }) => { - if (outsideButtons(x, y)) { - runOnJS(focusOnPoint)([x, y]); - startFocusAnimation(x, y); - } - }); - return Gesture.Exclusive(pinchGesture, tapGesture); - }, [ - focusOnPoint, - onPinchEnd, - onPinchUpdate, - outsideButtons, - startFocusAnimation, - ]); - - const stagingModeProgress = useSharedValue(0); - - const overlayAnimatedStyle = useAnimatedStyle(() => { - const overlayOpacity = interpolate( - stagingModeProgress.value, - [0, 0.01, 1], - [0, 0.5, 0], - Extrapolate.CLAMP, - ); - return { - opacity: overlayOpacity, - }; + currentZoom.value = clamp(zoomBase.value * pinchScale, 1, 8); + }, + [currentZoom, zoomBase.value], + ); + + const onPinchEnd = React.useCallback(() => { + 'worklet'; + zoomBase.value = currentZoom.value; + }, [currentZoom, zoomBase]); + + const gesture = React.useMemo(() => { + const pinchGesture = Gesture.Pinch() + .onUpdate(({ scale }) => onPinchUpdate(scale)) + .onEnd(() => onPinchEnd()); + const tapGesture = Gesture.Tap().onStart(({ x, y }) => { + if (outsideButtons(x, y)) { + runOnJS(focusOnPoint)([x, y]); + startFocusAnimation(x, y); + } }); - - const overlayStyle = React.useMemo( - () => [styles.overlay, overlayAnimatedStyle], - [overlayAnimatedStyle], + return Gesture.Exclusive(pinchGesture, tapGesture); + }, [ + focusOnPoint, + onPinchEnd, + onPinchUpdate, + outsideButtons, + startFocusAnimation, + ]); + + const stagingModeProgress = useSharedValue(0); + + const overlayAnimatedStyle = useAnimatedStyle(() => { + const overlayOpacity = interpolate( + stagingModeProgress.value, + [0, 0.01, 1], + [0, 0.5, 0], + Extrapolate.CLAMP, ); + return { + opacity: overlayOpacity, + }; + }); - const sendButtonProgress = React.useRef(new Animated.Value(0)); + const overlayStyle = React.useMemo( + () => [styles.overlay, overlayAnimatedStyle], + [overlayAnimatedStyle], + ); - const sendButtonStyle = React.useMemo(() => { - const sendButtonScale = sendButtonProgress.current.interpolate({ - inputRange: [0, 1], - outputRange: ([1.1, 1]: number[]), // Flow... - }); - return { - opacity: sendButtonProgress.current, - transform: [{ scale: sendButtonScale }], - }; - }, []); + const sendButtonProgress = React.useRef(new Animated.Value(0)); - const prevDeviceOrientation = React.useRef(); - React.useEffect(() => { - if (deviceOrientation !== prevDeviceOrientation.current) { - cancelFocusAnimation(); - } - prevDeviceOrientation.current = deviceOrientation; - }, [cancelFocusAnimation, deviceOrientation]); - - const prevStagingMode = React.useRef(false); - React.useEffect(() => { - if (stagingMode && !prevStagingMode.current) { - cancelFocusAnimation(); - stagingModeProgress.value = withTiming(1, stagingModeAnimationConfig); - } else if (!stagingMode && prevStagingMode.current) { - stagingModeProgress.value = 0; - } - prevStagingMode.current = stagingMode; - }, [cancelFocusAnimation, stagingMode, stagingModeProgress]); - - const prevPendingPhotoCapture = React.useRef(); - React.useEffect(() => { - if (pendingPhotoCapture && !prevPendingPhotoCapture.current) { - Animated.timing(sendButtonProgress.current, { - ...sendButtonAnimationConfig, - toValue: 1, - }).start(); - } else if (!pendingPhotoCapture && prevPendingPhotoCapture.current) { - void cleanUpPendingPhotoCapture(prevPendingPhotoCapture.current); - sendButtonProgress.current.setValue(0); - } - prevPendingPhotoCapture.current = pendingPhotoCapture; - }, [pendingPhotoCapture]); - - const containerAnimatedStyle = useAnimatedStyle( - () => ({ - opacity: overlayContext?.position?.value, - }), - [overlayContext], - ); + const sendButtonStyle = React.useMemo(() => { + const sendButtonScale = sendButtonProgress.current.interpolate({ + inputRange: [0, 1], + outputRange: ([1.1, 1]: number[]), // Flow... + }); + return { + opacity: sendButtonProgress.current, + transform: [{ scale: sendButtonScale }], + }; + }, []); - const containerStyle = React.useMemo(() => { - if (!overlayContext) { - return styles.container; - } - return [styles.container, containerAnimatedStyle]; - }, [containerAnimatedStyle, overlayContext]); + const prevDeviceOrientation = React.useRef(); + React.useEffect(() => { + if (deviceOrientation !== prevDeviceOrientation.current) { + cancelFocusAnimation(); + } + prevDeviceOrientation.current = deviceOrientation; + }, [cancelFocusAnimation, deviceOrientation]); + + const prevStagingMode = React.useRef(false); + React.useEffect(() => { + if (stagingMode && !prevStagingMode.current) { + cancelFocusAnimation(); + stagingModeProgress.value = withTiming(1, stagingModeAnimationConfig); + } else if (!stagingMode && prevStagingMode.current) { + stagingModeProgress.value = 0; + } + prevStagingMode.current = stagingMode; + }, [cancelFocusAnimation, stagingMode, stagingModeProgress]); + + const prevPendingPhotoCapture = React.useRef(); + React.useEffect(() => { + if (pendingPhotoCapture && !prevPendingPhotoCapture.current) { + Animated.timing(sendButtonProgress.current, { + ...sendButtonAnimationConfig, + toValue: 1, + }).start(); + } else if (!pendingPhotoCapture && prevPendingPhotoCapture.current) { + void cleanUpPendingPhotoCapture(prevPendingPhotoCapture.current); + sendButtonProgress.current.setValue(0); + } + prevPendingPhotoCapture.current = pendingPhotoCapture; + }, [pendingPhotoCapture]); + + const containerAnimatedStyle = useAnimatedStyle( + () => ({ + opacity: overlayContext?.position?.value, + }), + [overlayContext], + ); + + const containerStyle = React.useMemo(() => { + if (!overlayContext) { + return styles.container; + } + return [styles.container, containerAnimatedStyle]; + }, [containerAnimatedStyle, overlayContext]); - const { hasPermission, requestPermission } = useCameraPermission(); + const { hasPermission, requestPermission } = useCameraPermission(); - React.useEffect(() => { - if (foreground && !hasPermission) { - void requestPermission(); - } - }, [foreground, hasPermission, requestPermission]); + React.useEffect(() => { + if (foreground && !hasPermission) { + void requestPermission(); + } + }, [foreground, hasPermission, requestPermission]); - const renderCamera = (): React.Node => { - if (cameraRef.current) { - void fetchCameraIDs(); - } - if (stagingMode) { - return renderStagingView(); - } + const renderCamera = (): React.Node => { + if (cameraRef.current) { + void fetchCameraIDs(); + } + if (stagingMode) { + return renderStagingView(); + } - return ( - + return ( + + + {renderCameraContent()} + + × + + + + ); + }; + + const renderStagingView = (): React.Node => { + let image = null; + if (pendingPhotoCapture) { + const imageSource = { uri: pendingPhotoCapture.uri }; + image = ; + } else { + image = ; + } + + return ( + <> + {image} + - {renderCameraContent()} - × + + + + ); + }; + + const renderCameraContent = (): React.Node => { + if (!hasPermission) { + return ( + + + {'don’t have permission :('} + + ); - }; + } - const renderStagingView = (): React.Node => { - let image = null; - if (pendingPhotoCapture) { - const imageSource = { uri: pendingPhotoCapture.uri }; - image = ; - } else { - image = ; - } + let switchCameraButton = null; + if (hasCamerasOnBothSides) { + switchCameraButton = ( + + + + ); + } - return ( + let flashIcon; + if (flashMode === 'on') { + flashIcon = ; + } else if (flashMode === 'off') { + flashIcon = ; + } else { + flashIcon = ( <> - {image} - - - - - - - - + + A ); - }; - - const renderCameraContent = (): React.Node => { - if (!hasPermission) { - return ( - - - {'don’t have permission :('} - - - ); - } + } - let switchCameraButton = null; - if (hasCamerasOnBothSides) { - switchCameraButton = ( + return ( + + + - + {flashIcon} - ); - } - - let flashIcon; - if (flashMode === 'on') { - flashIcon = ; - } else if (flashMode === 'off') { - flashIcon = ; - } else { - flashIcon = ( - <> - - A - - ); - } - - return ( - - - + - {flashIcon} + - - - - - {switchCameraButton} - - - - ); - }; - - const statusBar = isActive ? + + ); + }; + const statusBar = isActive ?