Moves DraftAttachments into redux

This commit is contained in:
Josh Perez 2021-09-24 16:02:30 -04:00 committed by Josh Perez
parent f81f61af4e
commit 1c3c971cf4
20 changed files with 818 additions and 444 deletions

View file

@ -3,6 +3,8 @@
import { ThunkAction } from 'redux-thunk';
import * as log from '../../logging/log';
import { NoopActionType } from './noop';
import { StateType as RootStateType } from '../reducer';
import { AttachmentType } from '../../types/Attachment';
import { MessageAttributesType } from '../../model-types.d';
@ -12,6 +14,13 @@ import {
REMOVE_PREVIEW as REMOVE_LINK_PREVIEW,
RemoveLinkPreviewActionType,
} from './linkPreviews';
import { writeDraftAttachment } from '../../util/writeDraftAttachment';
import { replaceIndex } from '../../util/replaceIndex';
import { resolveAttachmentOnDisk } from '../../util/resolveAttachmentOnDisk';
import {
handleAttachmentsProcessing,
HandleAttachmentsProcessingArgsType,
} from '../../util/handleAttachmentsProcessing';
// State
@ -25,12 +34,18 @@ export type ComposerStateType = {
// Actions
const ADD_PENDING_ATTACHMENT = 'composer/ADD_PENDING_ATTACHMENT';
const REPLACE_ATTACHMENTS = 'composer/REPLACE_ATTACHMENTS';
const RESET_COMPOSER = 'composer/RESET_COMPOSER';
const SET_HIGH_QUALITY_SETTING = 'composer/SET_HIGH_QUALITY_SETTING';
const SET_LINK_PREVIEW_RESULT = 'composer/SET_LINK_PREVIEW_RESULT';
const SET_QUOTED_MESSAGE = 'composer/SET_QUOTED_MESSAGE';
type AddPendingAttachmentActionType = {
type: typeof ADD_PENDING_ATTACHMENT;
payload: AttachmentType;
};
type ReplaceAttachmentsActionType = {
type: typeof REPLACE_ATTACHMENTS;
payload: ReadonlyArray<AttachmentType>;
@ -59,16 +74,21 @@ type SetQuotedMessageActionType = {
};
type ComposerActionType =
| AddPendingAttachmentActionType
| RemoveLinkPreviewActionType
| ReplaceAttachmentsActionType
| ResetComposerActionType
| SetHighQualitySettingActionType
| SetLinkPreviewResultActionType
| RemoveLinkPreviewActionType
| SetQuotedMessageActionType;
// Action Creators
export const actions = {
addAttachment,
addPendingAttachment,
processAttachments,
removeAttachment,
replaceAttachments,
resetComposer,
setLinkPreviewResult,
@ -76,9 +96,137 @@ export const actions = {
setQuotedMessage,
};
// Not cool that we have to pull from ConversationModel here
// but if the current selected conversation isn't the one that we're operating
// on then we won't be able to grab attachments from state so we resort to the
// next in-memory store.
function getAttachmentsFromConversationModel(
conversationId: string
): Array<AttachmentType> {
const conversation = window.ConversationController.get(conversationId);
return conversation?.get('draftAttachments') || [];
}
function addAttachment(
conversationId: string,
attachment: AttachmentType
): ThunkAction<void, RootStateType, unknown, ReplaceAttachmentsActionType> {
return async (dispatch, getState) => {
const isSelectedConversation =
getState().conversations.selectedConversationId === conversationId;
const draftAttachments = isSelectedConversation
? getState().composer.attachments
: getAttachmentsFromConversationModel(conversationId);
const hasDraftAttachmentPending = draftAttachments.some(
draftAttachment =>
draftAttachment.pending && draftAttachment.path === attachment.path
);
// User has canceled the draft so we don't need to continue processing
if (!hasDraftAttachmentPending) {
return;
}
const onDisk = await writeDraftAttachment(attachment);
// Remove any pending attachments that were transcoding
const index = draftAttachments.findIndex(
draftAttachment => draftAttachment.path === attachment.path
);
let nextAttachments = draftAttachments;
if (index < 0) {
log.warn(
`addAttachment: Failed to find pending attachment with path ${attachment.path}`
);
nextAttachments = [...draftAttachments, onDisk];
} else {
nextAttachments = replaceIndex(draftAttachments, index, onDisk);
}
replaceAttachments(conversationId, nextAttachments)(
dispatch,
getState,
null
);
const conversation = window.ConversationController.get(conversationId);
if (conversation) {
conversation.attributes.draftAttachments = nextAttachments;
window.Signal.Data.updateConversation(conversation.attributes);
}
};
}
function addPendingAttachment(
conversationId: string,
pendingAttachment: AttachmentType
): ThunkAction<void, RootStateType, unknown, ReplaceAttachmentsActionType> {
return (dispatch, getState) => {
const isSelectedConversation =
getState().conversations.selectedConversationId === conversationId;
const draftAttachments = isSelectedConversation
? getState().composer.attachments
: getAttachmentsFromConversationModel(conversationId);
const nextAttachments = [...draftAttachments, pendingAttachment];
dispatch({
type: REPLACE_ATTACHMENTS,
payload: nextAttachments,
});
const conversation = window.ConversationController.get(conversationId);
if (conversation) {
conversation.attributes.draftAttachments = nextAttachments;
window.Signal.Data.updateConversation(conversation.attributes);
}
};
}
function processAttachments(
options: HandleAttachmentsProcessingArgsType
): ThunkAction<void, RootStateType, unknown, NoopActionType> {
return async dispatch => {
await handleAttachmentsProcessing(options);
dispatch({
type: 'NOOP',
payload: null,
});
};
}
function removeAttachment(
conversationId: string,
filePath: string
): ThunkAction<void, RootStateType, unknown, ReplaceAttachmentsActionType> {
return (dispatch, getState) => {
const { attachments } = getState().composer;
const nextAttachments = attachments.filter(
attachment => attachment.path !== filePath
);
const conversation = window.ConversationController.get(conversationId);
if (conversation) {
conversation.attributes.draftAttachments = nextAttachments;
conversation.attributes.draftChanged = true;
window.Signal.Data.updateConversation(conversation.attributes);
}
replaceAttachments(conversationId, nextAttachments)(
dispatch,
getState,
null
);
};
}
function replaceAttachments(
conversationId: string,
payload: ReadonlyArray<AttachmentType>
attachments: ReadonlyArray<AttachmentType>
): ThunkAction<void, RootStateType, unknown, ReplaceAttachmentsActionType> {
return (dispatch, getState) => {
// If the call came from a conversation we are no longer in we do not
@ -89,7 +237,7 @@ function replaceAttachments(
dispatch({
type: REPLACE_ATTACHMENTS,
payload,
payload: attachments.map(resolveAttachmentOnDisk),
});
};
}
@ -189,5 +337,12 @@ export function reducer(
});
}
if (action.type === ADD_PENDING_ATTACHMENT) {
return {
...state,
attachments: [...state.attachments, action.payload],
};
}
return state;
}

View file

@ -78,6 +78,7 @@ const mapStateToProps = (state: StateType, props: ExternalProps) => {
return {
// Base
conversationId: id,
i18n: getIntl(state),
// AttachmentsList
draftAttachments,