diff --git a/lib/actions/entry-actions.js b/lib/actions/entry-actions.js --- a/lib/actions/entry-actions.js +++ b/lib/actions/entry-actions.js @@ -5,7 +5,7 @@ sortCalendarQueryPerKeyserver, } from '../keyserver-conn/keyserver-call-utils.js'; import type { CallKeyserverEndpoint } from '../keyserver-conn/keyserver-conn-types.js'; -import { localIDPrefix } from '../shared/message-utils.js'; +import { getNextLocalID } from '../shared/message-utils.js'; import type { RawEntryInfo, CalendarQuery, @@ -127,13 +127,13 @@ const createLocalEntryActionType = 'CREATE_LOCAL_ENTRY'; function createLocalEntry( threadID: string, - localID: number, dateString: string, creatorID: string, ): RawEntryInfo { const date = dateFromString(dateString); + const localID = getNextLocalID(); const newEntryInfo: RawEntryInfo = { - localID: `${localIDPrefix}${localID}`, + localID, threadID, text: '', year: date.getFullYear(), diff --git a/lib/shared/message-utils.js b/lib/shared/message-utils.js --- a/lib/shared/message-utils.js +++ b/lib/shared/message-utils.js @@ -4,6 +4,7 @@ import _maxBy from 'lodash/fp/maxBy.js'; import _orderBy from 'lodash/fp/orderBy.js'; import * as React from 'react'; +import uuid from 'uuid'; import { codeBlockRegex, type ParserRules } from './markdown.js'; import type { CreationSideEffectsFunc } from './messages/message-spec.js'; @@ -654,8 +655,8 @@ return ET`assigned ${affectedUsers} the "${roleName}" role`; } -function useNextLocalID(): string { - const nextLocalID = useSelector(state => state.nextLocalID); +function getNextLocalID(): string { + const nextLocalID = uuid.v4(); return `${localIDPrefix}${nextLocalID}`; } @@ -744,7 +745,7 @@ getPinnedContentFromMessage, modifyItemForResultScreen, constructChangeRoleEntityText, - useNextLocalID, + getNextLocalID, isInvalidSidebarSource, isInvalidPinSource, isInvalidPinSourceForThread, diff --git a/native/calendar/thread-picker-modal.react.js b/native/calendar/thread-picker-modal.react.js --- a/native/calendar/thread-picker-modal.react.js +++ b/native/calendar/thread-picker-modal.react.js @@ -40,7 +40,6 @@ const viewerID = useSelector( state => state.currentUserInfo && state.currentUserInfo.id, ); - const nextLocalID = useSelector(state => state.nextLocalID); const dispatch = useDispatch(); const rootNavigatorContext = React.useContext(RootNavigatorContext); @@ -53,10 +52,10 @@ rootNavigatorContext.setKeyboardHandlingEnabled(false); dispatch({ type: createLocalEntryActionType, - payload: createLocalEntry(threadID, nextLocalID, dateString, viewerID), + payload: createLocalEntry(threadID, dateString, viewerID), }); }, - [rootNavigatorContext, dispatch, viewerID, nextLocalID, dateString], + [rootNavigatorContext, dispatch, viewerID, dateString], ); React.useEffect( 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 @@ -53,7 +53,7 @@ type MessagePreviewResult, trimMessage, useMessagePreview, - useNextLocalID, + getNextLocalID, } from 'lib/shared/message-utils.js'; import SentencePrefixSearchIndex from 'lib/shared/sentence-prefix-search-index.js'; import { @@ -284,7 +284,6 @@ +joinThreadLoadingStatus: LoadingStatus, +threadCreationInProgress: boolean, +calendarQuery: () => CalendarQuery, - +nextLocalID: string, +userInfos: UserInfos, +colors: Colors, +styles: $ReadOnly, @@ -973,7 +972,7 @@ return; } - const localID = this.props.nextLocalID; + const localID = getNextLocalID(); const creatorID = this.props.viewerID; invariant(creatorID, 'should have viewer ID in order to send a message'); invariant( @@ -1243,7 +1242,6 @@ navContext, }), ); - const nextLocalID = useNextLocalID(); const userInfos = useSelector(state => state.userStore.userInfos); const styles = useStyles(unboundStyles); @@ -1340,7 +1338,6 @@ joinThreadLoadingStatus={joinThreadLoadingStatus} threadCreationInProgress={threadCreationInProgress} calendarQuery={calendarQuery} - nextLocalID={nextLocalID} userInfos={userInfos} colors={colors} styles={styles} diff --git a/native/chat/inline-engagement.react.js b/native/chat/inline-engagement.react.js --- a/native/chat/inline-engagement.react.js +++ b/native/chat/inline-engagement.react.js @@ -11,7 +11,6 @@ import type { ReactionInfo } from 'lib/selectors/chat-selectors.js'; import { getInlineEngagementSidebarText } from 'lib/shared/inline-engagement-utils.js'; -import { useNextLocalID } from 'lib/shared/message-utils.js'; import type { MessageInfo } from 'lib/types/message-types.js'; import type { ThreadInfo } from 'lib/types/minimally-encoded-thread-permissions-types.js'; @@ -246,11 +245,8 @@ repliesText, ]); - const localID = useNextLocalID(); - const sendReaction = useSendReaction( messageInfo.id, - localID, threadInfo.id, reactions, ); diff --git a/native/chat/multimedia-message-tooltip-button.react.js b/native/chat/multimedia-message-tooltip-button.react.js --- a/native/chat/multimedia-message-tooltip-button.react.js +++ b/native/chat/multimedia-message-tooltip-button.react.js @@ -3,7 +3,6 @@ import * as React from 'react'; import Animated from 'react-native-reanimated'; -import { useNextLocalID } from 'lib/shared/message-utils.js'; import { useViewerAlreadySelectedMessageReactions, useCanCreateReactionFromMessage, @@ -102,7 +101,6 @@ ); const { messageInfo, threadInfo, reactions } = item; - const localID = useNextLocalID(); const canCreateReactionFromMessage = useCanCreateReactionFromMessage( threadInfo, @@ -111,7 +109,6 @@ const sendReaction = useSendReaction( messageInfo.id, - localID, threadInfo.id, reactions, ); diff --git a/native/chat/reaction-message-utils.js b/native/chat/reaction-message-utils.js --- a/native/chat/reaction-message-utils.js +++ b/native/chat/reaction-message-utils.js @@ -8,6 +8,7 @@ sendReactionMessageActionTypes, } from 'lib/actions/message-actions.js'; import type { ReactionInfo } from 'lib/selectors/chat-selectors.js'; +import { getNextLocalID } from 'lib/shared/message-utils.js'; import { messageTypes } from 'lib/types/message-types-enum.js'; import type { RawReactionMessageInfo } from 'lib/types/messages/reaction.js'; import { cloneError } from 'lib/utils/errors.js'; @@ -22,7 +23,6 @@ function useSendReaction( messageID: ?string, - localID: string, threadID: string, reactions: ReactionInfo, ): (reaction: string) => mixed { @@ -39,6 +39,8 @@ return; } + const localID = getNextLocalID(); + invariant(viewerID, 'viewerID should be set'); const viewerReacted = reactions[reaction] @@ -102,7 +104,6 @@ viewerID, reactions, threadID, - localID, dispatchActionPromise, callSendReactionMessage, ], diff --git a/native/chat/robotext-message-tooltip-button.react.js b/native/chat/robotext-message-tooltip-button.react.js --- a/native/chat/robotext-message-tooltip-button.react.js +++ b/native/chat/robotext-message-tooltip-button.react.js @@ -3,7 +3,6 @@ import * as React from 'react'; import Animated from 'react-native-reanimated'; -import { useNextLocalID } from 'lib/shared/message-utils.js'; import { useViewerAlreadySelectedMessageReactions, useCanCreateReactionFromMessage, @@ -85,7 +84,6 @@ }, [initialCoordinates, isOpeningSidebar, item, progress, windowWidth]); const { messageInfo, threadInfo, reactions } = item; - const localID = useNextLocalID(); const canCreateReactionFromMessage = useCanCreateReactionFromMessage( threadInfo, @@ -94,7 +92,6 @@ const sendReaction = useSendReaction( messageInfo.id, - localID, threadInfo.id, reactions, ); diff --git a/native/chat/text-message-tooltip-button.react.js b/native/chat/text-message-tooltip-button.react.js --- a/native/chat/text-message-tooltip-button.react.js +++ b/native/chat/text-message-tooltip-button.react.js @@ -3,7 +3,6 @@ import * as React from 'react'; import Animated from 'react-native-reanimated'; -import { useNextLocalID } from 'lib/shared/message-utils.js'; import { useViewerAlreadySelectedMessageReactions, useCanCreateReactionFromMessage, @@ -99,7 +98,6 @@ }, [initialCoordinates, isOpeningSidebar, item, progress, windowWidth]); const { messageInfo, threadInfo, reactions } = item; - const localID = useNextLocalID(); const canCreateReactionFromMessage = useCanCreateReactionFromMessage( threadInfo, @@ -108,7 +106,6 @@ const sendReaction = useSendReaction( messageInfo.id, - localID, threadInfo.id, reactions, ); 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 @@ -42,7 +42,7 @@ import { createMediaMessageInfo, useMessageCreationSideEffectsFunc, - useNextLocalID, + getNextLocalID, } from 'lib/shared/message-utils.js'; import type { CreationSideEffectsFunc } from 'lib/shared/messages/message-spec.js'; import { @@ -137,7 +137,6 @@ type Props = { ...BaseProps, +viewerID: ?string, - +nextLocalID: string, +messageStoreMessages: { +[id: string]: RawMessageInfo }, +ongoingMessageCreation: boolean, +hasWiFi: boolean, @@ -612,7 +611,7 @@ threadInfo: ThreadInfo, ) => { this.sendCallbacks.forEach(callback => callback()); - const localMessageID = this.props.nextLocalID; + const localMessageID = getNextLocalID(); void this.startThreadCreation(threadInfo); if (threadIsPendingSidebar(threadInfo.id)) { @@ -1718,7 +1717,6 @@ const viewerID = useSelector( state => state.currentUserInfo && state.currentUserInfo.id, ); - const nextLocalID = useNextLocalID(); const messageStoreMessages = useSelector( state => state.messageStore.messages, ); @@ -1747,7 +1745,6 @@ , +viewerID: ?string, +loggedIn: boolean, - +nextLocalID: number, +dispatch: Dispatch, +pushModal: PushModal, +popModal: () => void, @@ -200,12 +199,7 @@ invariant(viewerID, 'should have viewerID in order to create thread'); this.props.dispatch({ type: createLocalEntryActionType, - payload: createLocalEntry( - threadID, - this.props.nextLocalID, - this.props.dayString, - viewerID, - ), + payload: createLocalEntry(threadID, this.props.dayString, viewerID), }); }; @@ -236,7 +230,6 @@ state => !!(state.currentUserInfo && !state.currentUserInfo.anonymous && true), ); - const nextLocalID = useSelector(state => state.nextLocalID); const dispatch = useDispatch(); const { pushModal, popModal } = useModalContext(); @@ -246,7 +239,6 @@ onScreenThreadInfos={onScreenThreadInfos} viewerID={viewerID} loggedIn={loggedIn} - nextLocalID={nextLocalID} dispatch={dispatch} pushModal={pushModal} popModal={popModal} diff --git a/web/chat/chat-input-bar.react.js b/web/chat/chat-input-bar.react.js --- a/web/chat/chat-input-bar.react.js +++ b/web/chat/chat-input-bar.react.js @@ -24,7 +24,7 @@ useMentionTypeaheadUserSuggestions, useUserMentionsCandidates, } from 'lib/shared/mention-utils.js'; -import { localIDPrefix, trimMessage } from 'lib/shared/message-utils.js'; +import { trimMessage, getNextLocalID } from 'lib/shared/message-utils.js'; import { checkIfDefaultMembersAreVoiced, threadActualMembers, @@ -75,7 +75,6 @@ +joinThreadLoadingStatus: LoadingStatus, +threadCreationInProgress: boolean, +calendarQuery: () => CalendarQuery, - +nextLocalID: number, +isThreadActive: boolean, +userInfos: UserInfos, +dispatchActionPromise: DispatchActionPromise, @@ -480,25 +479,19 @@ }; send() { - let { nextLocalID } = this.props; - const text = trimMessage(this.props.inputState.draft); if (text) { - this.dispatchTextMessageAction(text, nextLocalID); - nextLocalID++; + this.dispatchTextMessageAction(text); } if (this.props.inputState.pendingUploads.length > 0) { - this.props.inputState.createMultimediaMessage( - nextLocalID, - this.props.threadInfo, - ); + this.props.inputState.createMultimediaMessage(this.props.threadInfo); } } - dispatchTextMessageAction(text: string, nextLocalID: number) { + dispatchTextMessageAction(text: string) { this.props.inputState.setDraft(''); - const localID = `${localIDPrefix}${nextLocalID}`; + const localID = getNextLocalID(); const creatorID = this.props.viewerID; invariant(creatorID, 'should have viewer ID in order to send a message'); @@ -572,7 +565,6 @@ const viewerID = useSelector( state => state.currentUserInfo && state.currentUserInfo.id, ); - const nextLocalID = useSelector(state => state.nextLocalID); const isThreadActive = useSelector( state => props.threadInfo.id === state.navInfo.activeChatThreadID, ); @@ -671,7 +663,6 @@ joinThreadLoadingStatus={joinThreadLoadingStatus} threadCreationInProgress={threadCreationInProgress} calendarQuery={calendarQuery} - nextLocalID={nextLocalID} isThreadActive={isThreadActive} userInfos={userInfos} dispatchActionPromise={dispatchActionPromise} diff --git a/web/chat/reaction-message-utils.js b/web/chat/reaction-message-utils.js --- a/web/chat/reaction-message-utils.js +++ b/web/chat/reaction-message-utils.js @@ -9,6 +9,7 @@ } from 'lib/actions/message-actions.js'; import { useModalContext } from 'lib/components/modal-provider.react.js'; import type { ReactionInfo } from 'lib/selectors/chat-selectors'; +import { getNextLocalID } from 'lib/shared/message-utils.js'; import { messageTypes } from 'lib/types/message-types-enum.js'; import type { RawReactionMessageInfo } from 'lib/types/messages/reaction.js'; import type { CallSingleKeyserverEndpointResultInfoInterface } from 'lib/utils/call-single-keyserver-endpoint.js'; @@ -25,7 +26,6 @@ function useSendReaction( messageID: ?string, - localID: string, threadID: string, reactions: ReactionInfo, ): (reaction: string) => mixed { @@ -44,6 +44,8 @@ return; } + const localID = getNextLocalID(); + invariant(viewerID, 'viewerID should be set'); const viewerReacted = reactions[reaction] @@ -108,7 +110,6 @@ viewerID, reactions, threadID, - localID, dispatchActionPromise, callSendReactionMessage, pushModal, diff --git a/web/chat/reaction-pill.react.js b/web/chat/reaction-pill.react.js --- a/web/chat/reaction-pill.react.js +++ b/web/chat/reaction-pill.react.js @@ -4,7 +4,6 @@ import * as React from 'react'; import type { ReactionInfo } from 'lib/selectors/chat-selectors.js'; -import { useNextLocalID } from 'lib/shared/message-utils.js'; import { useSendReaction } from './reaction-message-utils.js'; import css from './reaction-pill.css'; @@ -26,8 +25,7 @@ function ReactionPill(props: Props): React.Node { const { reaction, messageID, threadID, reactions } = props; - const localID = useNextLocalID(); - const sendReaction = useSendReaction(messageID, localID, threadID, reactions); + const sendReaction = useSendReaction(messageID, threadID, reactions); const onClickReaction = React.useCallback( (event: SyntheticEvent) => { diff --git a/web/input/input-state-container.react.js b/web/input/input-state-container.react.js --- a/web/input/input-state-container.react.js +++ b/web/input/input-state-container.react.js @@ -47,6 +47,7 @@ createMediaMessageInfo, localIDPrefix, useMessageCreationSideEffectsFunc, + getNextLocalID, } from 'lib/shared/message-utils.js'; import type { CreationSideEffectsFunc } from 'lib/shared/messages/message-spec.js'; import { @@ -642,10 +643,8 @@ parentThreadInfo: ?ThreadInfo, ) => this.sendTextMessage(messageInfo, threadInfo, parentThreadInfo), - createMultimediaMessage: ( - localID: number, - threadInfo: ThreadInfo, - ) => this.createMultimediaMessage(localID, threadInfo), + createMultimediaMessage: (threadInfo: ThreadInfo) => + this.createMultimediaMessage(threadInfo), setDraft: (newDraft: string) => this.setDraft(threadID, newDraft), setTextCursorPosition: (newPosition: number) => this.setTextCursorPosition(threadID, newPosition), @@ -1395,10 +1394,10 @@ // Creates a MultimediaMessage from the unassigned pending uploads, // if there are any - createMultimediaMessage(localID: number, threadInfo: ThreadInfo) { + createMultimediaMessage(threadInfo: ThreadInfo) { this.props.sendCallbacks.forEach(callback => callback()); - const localMessageID = `${localIDPrefix}${localID}`; + const localMessageID = getNextLocalID(); void this.startThreadCreation(threadInfo); if (threadIsPendingSidebar(threadInfo.id)) { diff --git a/web/input/input-state.js b/web/input/input-state.js --- a/web/input/input-state.js +++ b/web/input/input-state.js @@ -72,7 +72,7 @@ threadInfo: ThreadInfo, parentThreadInfo: ?ThreadInfo, ) => mixed, - +createMultimediaMessage: (localID: number, threadInfo: ThreadInfo) => void, + +createMultimediaMessage: (threadInfo: ThreadInfo) => void, +setDraft: (draft: string) => void, +setTextCursorPosition: (newPosition: number) => void, +messageHasUploadFailure: (localMessageID: string) => boolean, diff --git a/web/tooltips/message-tooltip.react.js b/web/tooltips/message-tooltip.react.js --- a/web/tooltips/message-tooltip.react.js +++ b/web/tooltips/message-tooltip.react.js @@ -6,7 +6,6 @@ import * as React from 'react'; import type { ChatMessageInfoItem } from 'lib/selectors/chat-selectors.js'; -import { useNextLocalID } from 'lib/shared/message-utils.js'; import type { ThreadInfo } from 'lib/types/minimally-encoded-thread-permissions-types.js'; import css from './message-tooltip.css'; @@ -170,11 +169,8 @@ }; }, [emojiKeyboardPosition]); - const localID = useNextLocalID(); - const sendReaction = useSendReaction( messageInfo.id, - localID, threadInfo.id, reactions, );