Changeset View
Changeset View
Standalone View
Standalone View
web/input/input-state-container.react.js
Show First 20 Lines • Show All 112 Lines • ▼ Show 20 Lines | type Props = { | ||||
+registerSendCallback: (() => mixed) => void, | +registerSendCallback: (() => mixed) => void, | ||||
+unregisterSendCallback: (() => mixed) => void, | +unregisterSendCallback: (() => mixed) => void, | ||||
}; | }; | ||||
type State = { | type State = { | ||||
+pendingUploads: { | +pendingUploads: { | ||||
[threadID: string]: { [localUploadID: string]: PendingMultimediaUpload }, | [threadID: string]: { [localUploadID: string]: PendingMultimediaUpload }, | ||||
}, | }, | ||||
+drafts: { [threadID: string]: string }, | +drafts: { [threadID: string]: string }, | ||||
+textCursorPositions: { [threadID: string]: number }, | |||||
}; | }; | ||||
class InputStateContainer extends React.PureComponent<Props, State> { | class InputStateContainer extends React.PureComponent<Props, State> { | ||||
state: State = { | state: State = { | ||||
pendingUploads: {}, | pendingUploads: {}, | ||||
drafts: {}, | drafts: {}, | ||||
textCursorPositions: {}, | |||||
}; | }; | ||||
replyCallbacks: Array<(message: string) => void> = []; | replyCallbacks: Array<(message: string) => void> = []; | ||||
pendingThreadCreations = new Map<string, Promise<string>>(); | pendingThreadCreations = new Map<string, Promise<string>>(); | ||||
static reassignToRealizedThreads<T>( | static reassignToRealizedThreads<T>( | ||||
state: { +[threadID: string]: T }, | state: { +[threadID: string]: T }, | ||||
props: Props, | props: Props, | ||||
): ?{ [threadID: string]: T } { | ): ?{ [threadID: string]: T } { | ||||
Show All 14 Lines | static getDerivedStateFromProps(props: Props, state: State) { | ||||
const drafts = InputStateContainer.reassignToRealizedThreads( | const drafts = InputStateContainer.reassignToRealizedThreads( | ||||
state.drafts, | state.drafts, | ||||
props, | props, | ||||
); | ); | ||||
const pendingUploads = InputStateContainer.reassignToRealizedThreads( | const pendingUploads = InputStateContainer.reassignToRealizedThreads( | ||||
state.pendingUploads, | state.pendingUploads, | ||||
props, | props, | ||||
); | ); | ||||
const textCursorPositions = InputStateContainer.reassignToRealizedThreads( | |||||
state.textCursorPositions, | |||||
props, | |||||
); | |||||
if (!drafts && !pendingUploads) { | if (!drafts && !pendingUploads && !textCursorPositions) { | ||||
return null; | return null; | ||||
} | } | ||||
const stateUpdate = {}; | const stateUpdate = {}; | ||||
if (drafts) { | if (drafts) { | ||||
stateUpdate.drafts = drafts; | stateUpdate.drafts = drafts; | ||||
} | } | ||||
if (pendingUploads) { | if (pendingUploads) { | ||||
stateUpdate.pendingUploads = pendingUploads; | stateUpdate.pendingUploads = pendingUploads; | ||||
} | } | ||||
if (textCursorPositions) { | |||||
stateUpdate.textCursorPositions = textCursorPositions; | |||||
} | |||||
return stateUpdate; | return stateUpdate; | ||||
} | } | ||||
static completedMessageIDs(state: State) { | static completedMessageIDs(state: State) { | ||||
const completed = new Map(); | const completed = new Map(); | ||||
for (const threadID in state.pendingUploads) { | for (const threadID in state.pendingUploads) { | ||||
const pendingUploads = state.pendingUploads[threadID]; | const pendingUploads = state.pendingUploads[threadID]; | ||||
for (const localUploadID in pendingUploads) { | for (const localUploadID in pendingUploads) { | ||||
▲ Show 20 Lines • Show All 270 Lines • ▼ Show 20 Lines | async startThreadCreation(threadInfo: ThreadInfo): Promise<string> { | ||||
} | } | ||||
return threadCreationPromise; | return threadCreationPromise; | ||||
} | } | ||||
inputStateSelector = _memoize((threadID: string) => | inputStateSelector = _memoize((threadID: string) => | ||||
createSelector( | createSelector( | ||||
(state: State) => state.pendingUploads[threadID], | (state: State) => state.pendingUploads[threadID], | ||||
(state: State) => state.drafts[threadID], | (state: State) => state.drafts[threadID], | ||||
(state: State) => state.textCursorPositions[threadID], | |||||
( | ( | ||||
pendingUploads: ?{ [localUploadID: string]: PendingMultimediaUpload }, | pendingUploads: ?{ [localUploadID: string]: PendingMultimediaUpload }, | ||||
draft: ?string, | draft: ?string, | ||||
textCursorPosition: ?number, | |||||
) => { | ) => { | ||||
let threadPendingUploads = []; | let threadPendingUploads = []; | ||||
const assignedUploads = {}; | const assignedUploads = {}; | ||||
if (pendingUploads) { | if (pendingUploads) { | ||||
const [uploadsWithMessageIDs, uploadsWithoutMessageIDs] = _partition( | const [uploadsWithMessageIDs, uploadsWithoutMessageIDs] = _partition( | ||||
'messageID', | 'messageID', | ||||
)(pendingUploads); | )(pendingUploads); | ||||
threadPendingUploads = _sortBy('localID')(uploadsWithoutMessageIDs); | threadPendingUploads = _sortBy('localID')(uploadsWithoutMessageIDs); | ||||
const threadAssignedUploads = _groupBy('messageID')( | const threadAssignedUploads = _groupBy('messageID')( | ||||
uploadsWithMessageIDs, | uploadsWithMessageIDs, | ||||
); | ); | ||||
for (const messageID in threadAssignedUploads) { | for (const messageID in threadAssignedUploads) { | ||||
// lodash libdefs don't return $ReadOnlyArray | // lodash libdefs don't return $ReadOnlyArray | ||||
assignedUploads[messageID] = [...threadAssignedUploads[messageID]]; | assignedUploads[messageID] = [...threadAssignedUploads[messageID]]; | ||||
} | } | ||||
} | } | ||||
return { | return { | ||||
pendingUploads: threadPendingUploads, | pendingUploads: threadPendingUploads, | ||||
assignedUploads, | assignedUploads, | ||||
draft: draft ? draft : '', | draft: draft ?? '', | ||||
textCursorPosition: textCursorPosition ?? 0, | |||||
appendFiles: (files: $ReadOnlyArray<File>) => | appendFiles: (files: $ReadOnlyArray<File>) => | ||||
this.appendFiles(threadID, files), | this.appendFiles(threadID, files), | ||||
cancelPendingUpload: (localUploadID: string) => | cancelPendingUpload: (localUploadID: string) => | ||||
this.cancelPendingUpload(threadID, localUploadID), | this.cancelPendingUpload(threadID, localUploadID), | ||||
sendTextMessage: ( | sendTextMessage: ( | ||||
messageInfo: RawTextMessageInfo, | messageInfo: RawTextMessageInfo, | ||||
threadInfo: ThreadInfo, | threadInfo: ThreadInfo, | ||||
) => this.sendTextMessage(messageInfo, threadInfo), | ) => this.sendTextMessage(messageInfo, threadInfo), | ||||
createMultimediaMessage: (localID: number, threadInfo: ThreadInfo) => | createMultimediaMessage: (localID: number, threadInfo: ThreadInfo) => | ||||
this.createMultimediaMessage(localID, threadInfo), | this.createMultimediaMessage(localID, threadInfo), | ||||
setDraft: (newDraft: string) => this.setDraft(threadID, newDraft), | setDraft: (newDraft: string) => this.setDraft(threadID, newDraft), | ||||
setTextCursorPosition: (newPosition: number) => | |||||
this.setTextCursorPosition(threadID, newPosition), | |||||
messageHasUploadFailure: (localMessageID: string) => | messageHasUploadFailure: (localMessageID: string) => | ||||
this.messageHasUploadFailure(assignedUploads[localMessageID]), | this.messageHasUploadFailure(assignedUploads[localMessageID]), | ||||
retryMultimediaMessage: ( | retryMultimediaMessage: ( | ||||
localMessageID: string, | localMessageID: string, | ||||
threadInfo: ThreadInfo, | threadInfo: ThreadInfo, | ||||
) => | ) => | ||||
this.retryMultimediaMessage( | this.retryMultimediaMessage( | ||||
localMessageID, | localMessageID, | ||||
▲ Show 20 Lines • Show All 565 Lines • ▼ Show 20 Lines | this.setState(prevState => { | ||||
drafts: { | drafts: { | ||||
...prevState.drafts, | ...prevState.drafts, | ||||
[newThreadID]: draft, | [newThreadID]: draft, | ||||
}, | }, | ||||
}; | }; | ||||
}); | }); | ||||
} | } | ||||
setTextCursorPosition(threadID: string, newPosition: number) { | |||||
this.setState(prevState => { | |||||
const newThreadID = this.getRealizedOrPendingThreadID(threadID); | |||||
return { | |||||
textCursorPositions: { | |||||
...prevState.textCursorPositions, | |||||
[newThreadID]: newPosition, | |||||
}, | |||||
}; | |||||
}); | |||||
} | |||||
setProgress( | setProgress( | ||||
threadID: string, | threadID: string, | ||||
localUploadID: string, | localUploadID: string, | ||||
progressPercent: number, | progressPercent: number, | ||||
) { | ) { | ||||
this.setState(prevState => { | this.setState(prevState => { | ||||
const newThreadID = this.getRealizedOrPendingThreadID(threadID); | const newThreadID = this.getRealizedOrPendingThreadID(threadID); | ||||
const pendingUploads = prevState.pendingUploads[newThreadID]; | const pendingUploads = prevState.pendingUploads[newThreadID]; | ||||
▲ Show 20 Lines • Show All 221 Lines • Show Last 20 Lines |