tests i can't run locally for now

Signed-off-by: marcin mikolajczak <git@mkljczk.pl>
Signed-off-by: marcin mikołajczak <git@mkljczk.pl>
This commit is contained in:
marcin mikolajczak 2022-09-14 22:05:40 +02:00 committed by marcin mikołajczak
parent 6cce0a0291
commit b38e5ec8e3
13 changed files with 571 additions and 531 deletions

View File

@ -2,6 +2,7 @@ import { Map as ImmutableMap, OrderedSet as ImmutableOrderedSet } from 'immutabl
import { mockStore, rootState } from 'soapbox/jest/test-helpers'; import { mockStore, rootState } from 'soapbox/jest/test-helpers';
import { InstanceRecord } from 'soapbox/normalizers'; import { InstanceRecord } from 'soapbox/normalizers';
import { ReducerCompose } from 'soapbox/reducers/compose';
import { uploadCompose, submitCompose } from '../compose'; import { uploadCompose, submitCompose } from '../compose';
import { STATUS_CREATE_REQUEST } from '../statuses'; import { STATUS_CREATE_REQUEST } from '../statuses';
@ -26,7 +27,8 @@ describe('uploadCompose()', () => {
const state = rootState const state = rootState
.set('me', '1234') .set('me', '1234')
.set('instance', instance); .set('instance', instance)
.setIn(['compose', 'home'], ReducerCompose());
store = mockStore(state); store = mockStore(state);
files = [{ files = [{
@ -43,7 +45,7 @@ describe('uploadCompose()', () => {
} as unknown as IntlShape; } as unknown as IntlShape;
const expectedActions = [ const expectedActions = [
{ type: 'COMPOSE_UPLOAD_REQUEST', skipLoading: true }, { type: 'COMPOSE_UPLOAD_REQUEST', id: 'home', skipLoading: true },
{ {
type: 'ALERT_SHOW', type: 'ALERT_SHOW',
message: 'Image exceeds the current file size limit (10 Bytes)', message: 'Image exceeds the current file size limit (10 Bytes)',
@ -51,10 +53,10 @@ describe('uploadCompose()', () => {
actionLink: undefined, actionLink: undefined,
severity: 'error', severity: 'error',
}, },
{ type: 'COMPOSE_UPLOAD_FAIL', error: true, skipLoading: true }, { type: 'COMPOSE_UPLOAD_FAIL', id: 'home', error: true, skipLoading: true },
]; ];
await store.dispatch(uploadCompose(files, mockIntl)); await store.dispatch(uploadCompose('home', files, mockIntl));
const actions = store.getActions(); const actions = store.getActions();
expect(actions).toEqual(expectedActions); expect(actions).toEqual(expectedActions);
@ -78,7 +80,8 @@ describe('uploadCompose()', () => {
const state = rootState const state = rootState
.set('me', '1234') .set('me', '1234')
.set('instance', instance); .set('instance', instance)
.setIn(['compose', 'home'], ReducerCompose());
store = mockStore(state); store = mockStore(state);
files = [{ files = [{
@ -95,7 +98,7 @@ describe('uploadCompose()', () => {
} as unknown as IntlShape; } as unknown as IntlShape;
const expectedActions = [ const expectedActions = [
{ type: 'COMPOSE_UPLOAD_REQUEST', skipLoading: true }, { type: 'COMPOSE_UPLOAD_REQUEST', id: 'home', skipLoading: true },
{ {
type: 'ALERT_SHOW', type: 'ALERT_SHOW',
message: 'Video exceeds the current file size limit (10 Bytes)', message: 'Video exceeds the current file size limit (10 Bytes)',
@ -103,10 +106,10 @@ describe('uploadCompose()', () => {
actionLink: undefined, actionLink: undefined,
severity: 'error', severity: 'error',
}, },
{ type: 'COMPOSE_UPLOAD_FAIL', error: true, skipLoading: true }, { type: 'COMPOSE_UPLOAD_FAIL', id: 'home', error: true, skipLoading: true },
]; ];
await store.dispatch(uploadCompose(files, mockIntl)); await store.dispatch(uploadCompose('home', files, mockIntl));
const actions = store.getActions(); const actions = store.getActions();
expect(actions).toEqual(expectedActions); expect(actions).toEqual(expectedActions);
@ -118,10 +121,10 @@ describe('submitCompose()', () => {
it('inserts mentions from text', async() => { it('inserts mentions from text', async() => {
const state = rootState const state = rootState
.set('me', '123') .set('me', '123')
.setIn(['compose', 'text'], '@alex hello @mkljczk@pl.fediverse.pl @gg@汉语/漢語.com alex@alexgleason.me'); .setIn(['compose', 'home'], ReducerCompose({ text: '@alex hello @mkljczk@pl.fediverse.pl @gg@汉语/漢語.com alex@alexgleason.me' }));
const store = mockStore(state); const store = mockStore(state);
await store.dispatch(submitCompose()); await store.dispatch(submitCompose('home'));
const actions = store.getActions(); const actions = store.getActions();
const statusCreateRequest = actions.find(action => action.type === STATUS_CREATE_REQUEST); const statusCreateRequest = actions.find(action => action.type === STATUS_CREATE_REQUEST);

View File

@ -121,6 +121,7 @@ describe('deleteStatus()', () => {
version: '0.0.0', version: '0.0.0',
}, },
withRedraft: true, withRedraft: true,
id: 'compose-modal',
}, },
{ type: 'MODAL_OPEN', modalType: 'COMPOSE', modalProps: undefined }, { type: 'MODAL_OPEN', modalType: 'COMPOSE', modalProps: undefined },
]; ];

View File

@ -105,6 +105,7 @@ const setComposeToStatus = (status: Status, rawText: string, spoilerText?: strin
dispatch({ dispatch({
type: COMPOSE_SET_STATUS, type: COMPOSE_SET_STATUS,
id: 'compose-modal',
status, status,
rawText, rawText,
explicitAddressing, explicitAddressing,
@ -129,6 +130,7 @@ const replyCompose = (status: Status) =>
dispatch({ dispatch({
type: COMPOSE_REPLY, type: COMPOSE_REPLY,
id: 'compose-modal',
status: status, status: status,
account: state.accounts.get(state.me), account: state.accounts.get(state.me),
explicitAddressing, explicitAddressing,
@ -139,6 +141,7 @@ const replyCompose = (status: Status) =>
const cancelReplyCompose = () => ({ const cancelReplyCompose = () => ({
type: COMPOSE_REPLY_CANCEL, type: COMPOSE_REPLY_CANCEL,
id: 'compose-modal',
}); });
const quoteCompose = (status: Status) => const quoteCompose = (status: Status) =>
@ -149,6 +152,7 @@ const quoteCompose = (status: Status) =>
dispatch({ dispatch({
type: COMPOSE_QUOTE, type: COMPOSE_QUOTE,
id: 'compose-modal',
status: status, status: status,
account: state.accounts.get(state.me), account: state.accounts.get(state.me),
explicitAddressing, explicitAddressing,
@ -159,16 +163,19 @@ const quoteCompose = (status: Status) =>
const cancelQuoteCompose = () => ({ const cancelQuoteCompose = () => ({
type: COMPOSE_QUOTE_CANCEL, type: COMPOSE_QUOTE_CANCEL,
id: 'compose-modal',
}); });
const resetCompose = () => ({ const resetCompose = (composeId = 'compose-modal') => ({
type: COMPOSE_RESET, type: COMPOSE_RESET,
id: composeId,
}); });
const mentionCompose = (account: Account) => const mentionCompose = (account: Account) =>
(dispatch: AppDispatch) => { (dispatch: AppDispatch) => {
dispatch({ dispatch({
type: COMPOSE_MENTION, type: COMPOSE_MENTION,
id: 'compose-modal',
account: account, account: account,
}); });
@ -179,6 +186,7 @@ const directCompose = (account: Account) =>
(dispatch: AppDispatch) => { (dispatch: AppDispatch) => {
dispatch({ dispatch({
type: COMPOSE_DIRECT, type: COMPOSE_DIRECT,
id: 'compose-modal',
account: account, account: account,
}); });
@ -191,6 +199,7 @@ const directComposeById = (accountId: string) =>
dispatch({ dispatch({
type: COMPOSE_DIRECT, type: COMPOSE_DIRECT,
id: 'compose-modal',
account: account, account: account,
}); });
@ -323,7 +332,7 @@ const uploadCompose = (composeId: string, files: FileList, intl: IntlShape) =>
return; return;
} }
dispatch(uploadComposeRequest()); dispatch(uploadComposeRequest(composeId));
Array.from(files).forEach(async(f, i) => { Array.from(files).forEach(async(f, i) => {
if (media.size + i > attachmentLimit - 1) return; if (media.size + i > attachmentLimit - 1) return;
@ -336,18 +345,18 @@ const uploadCompose = (composeId: string, files: FileList, intl: IntlShape) =>
const limit = formatBytes(maxImageSize); const limit = formatBytes(maxImageSize);
const message = intl.formatMessage(messages.exceededImageSizeLimit, { limit }); const message = intl.formatMessage(messages.exceededImageSizeLimit, { limit });
dispatch(snackbar.error(message)); dispatch(snackbar.error(message));
dispatch(uploadComposeFail(true)); dispatch(uploadComposeFail(composeId, true));
return; return;
} else if (isVideo && maxVideoSize && (f.size > maxVideoSize)) { } else if (isVideo && maxVideoSize && (f.size > maxVideoSize)) {
const limit = formatBytes(maxVideoSize); const limit = formatBytes(maxVideoSize);
const message = intl.formatMessage(messages.exceededVideoSizeLimit, { limit }); const message = intl.formatMessage(messages.exceededVideoSizeLimit, { limit });
dispatch(snackbar.error(message)); dispatch(snackbar.error(message));
dispatch(uploadComposeFail(true)); dispatch(uploadComposeFail(composeId, true));
return; return;
} else if (isVideo && maxVideoDuration && (videoDurationInSeconds > maxVideoDuration)) { } else if (isVideo && maxVideoDuration && (videoDurationInSeconds > maxVideoDuration)) {
const message = intl.formatMessage(messages.exceededVideoDurationLimit, { limit: maxVideoDuration }); const message = intl.formatMessage(messages.exceededVideoDurationLimit, { limit: maxVideoDuration });
dispatch(snackbar.error(message)); dispatch(snackbar.error(message));
dispatch(uploadComposeFail(true)); dispatch(uploadComposeFail(composeId, true));
return; return;
} }
@ -361,7 +370,7 @@ const uploadCompose = (composeId: string, files: FileList, intl: IntlShape) =>
const onUploadProgress = ({ loaded }: any) => { const onUploadProgress = ({ loaded }: any) => {
progress[i] = loaded; progress[i] = loaded;
dispatch(uploadComposeProgress(progress.reduce((a, v) => a + v, 0), total)); dispatch(uploadComposeProgress(composeId, progress.reduce((a, v) => a + v, 0), total));
}; };
return dispatch(uploadMedia(data, onUploadProgress)) return dispatch(uploadMedia(data, onUploadProgress))
@ -369,98 +378,107 @@ const uploadCompose = (composeId: string, files: FileList, intl: IntlShape) =>
// If server-side processing of the media attachment has not completed yet, // If server-side processing of the media attachment has not completed yet,
// poll the server until it is, before showing the media attachment as uploaded // poll the server until it is, before showing the media attachment as uploaded
if (status === 200) { if (status === 200) {
dispatch(uploadComposeSuccess(data, f)); dispatch(uploadComposeSuccess(composeId, data, f));
} else if (status === 202) { } else if (status === 202) {
const poll = () => { const poll = () => {
dispatch(fetchMedia(data.id)).then(({ status, data }) => { dispatch(fetchMedia(data.id)).then(({ status, data }) => {
if (status === 200) { if (status === 200) {
dispatch(uploadComposeSuccess(data, f)); dispatch(uploadComposeSuccess(composeId, data, f));
} else if (status === 206) { } else if (status === 206) {
setTimeout(() => poll(), 1000); setTimeout(() => poll(), 1000);
} }
}).catch(error => dispatch(uploadComposeFail(error))); }).catch(error => dispatch(uploadComposeFail(composeId, error)));
}; };
poll(); poll();
} }
}); });
}).catch(error => dispatch(uploadComposeFail(error))); }).catch(error => dispatch(uploadComposeFail(composeId, error)));
/* eslint-enable no-loop-func */ /* eslint-enable no-loop-func */
}); });
}; };
const changeUploadCompose = (id: string, params: Record<string, any>) => const changeUploadCompose = (composeId: string, id: string, params: Record<string, any>) =>
(dispatch: AppDispatch, getState: () => RootState) => { (dispatch: AppDispatch, getState: () => RootState) => {
if (!isLoggedIn(getState)) return; if (!isLoggedIn(getState)) return;
dispatch(changeUploadComposeRequest()); dispatch(changeUploadComposeRequest(composeId));
dispatch(updateMedia(id, params)).then(response => { dispatch(updateMedia(id, params)).then(response => {
dispatch(changeUploadComposeSuccess(response.data)); dispatch(changeUploadComposeSuccess(composeId, response.data));
}).catch(error => { }).catch(error => {
dispatch(changeUploadComposeFail(id, error)); dispatch(changeUploadComposeFail(composeId, id, error));
}); });
}; };
const changeUploadComposeRequest = () => ({ const changeUploadComposeRequest = (composeId: string) => ({
type: COMPOSE_UPLOAD_CHANGE_REQUEST, type: COMPOSE_UPLOAD_CHANGE_REQUEST,
id: composeId,
skipLoading: true, skipLoading: true,
}); });
const changeUploadComposeSuccess = (media: APIEntity) => ({ const changeUploadComposeSuccess = (composeId: string, media: APIEntity) => ({
type: COMPOSE_UPLOAD_CHANGE_SUCCESS, type: COMPOSE_UPLOAD_CHANGE_SUCCESS,
id: composeId,
media: media, media: media,
skipLoading: true, skipLoading: true,
}); });
const changeUploadComposeFail = (id: string, error: AxiosError) => ({ const changeUploadComposeFail = (composeId: string, id: string, error: AxiosError) => ({
type: COMPOSE_UPLOAD_CHANGE_FAIL, type: COMPOSE_UPLOAD_CHANGE_FAIL,
composeId,
id, id,
error: error, error: error,
skipLoading: true, skipLoading: true,
}); });
const uploadComposeRequest = () => ({ const uploadComposeRequest = (composeId: string) => ({
type: COMPOSE_UPLOAD_REQUEST, type: COMPOSE_UPLOAD_REQUEST,
id: composeId,
skipLoading: true, skipLoading: true,
}); });
const uploadComposeProgress = (loaded: number, total: number) => ({ const uploadComposeProgress = (composeId: string, loaded: number, total: number) => ({
type: COMPOSE_UPLOAD_PROGRESS, type: COMPOSE_UPLOAD_PROGRESS,
id: composeId,
loaded: loaded, loaded: loaded,
total: total, total: total,
}); });
const uploadComposeSuccess = (media: APIEntity, file: File) => ({ const uploadComposeSuccess = (composeId: string, media: APIEntity, file: File) => ({
type: COMPOSE_UPLOAD_SUCCESS, type: COMPOSE_UPLOAD_SUCCESS,
id: composeId,
media: media, media: media,
file, file,
skipLoading: true, skipLoading: true,
}); });
const uploadComposeFail = (error: AxiosError | true) => ({ const uploadComposeFail = (composeId: string, error: AxiosError | true) => ({
type: COMPOSE_UPLOAD_FAIL, type: COMPOSE_UPLOAD_FAIL,
id: composeId,
error: error, error: error,
skipLoading: true, skipLoading: true,
}); });
const undoUploadCompose = (media_id: string) => ({ const undoUploadCompose = (composeId: string, media_id: string) => ({
type: COMPOSE_UPLOAD_UNDO, type: COMPOSE_UPLOAD_UNDO,
id: composeId,
media_id: media_id, media_id: media_id,
}); });
const clearComposeSuggestions = () => { const clearComposeSuggestions = (composeId: string) => {
if (cancelFetchComposeSuggestionsAccounts) { if (cancelFetchComposeSuggestionsAccounts) {
cancelFetchComposeSuggestionsAccounts(); cancelFetchComposeSuggestionsAccounts();
} }
return { return {
type: COMPOSE_SUGGESTIONS_CLEAR, type: COMPOSE_SUGGESTIONS_CLEAR,
id: composeId,
}; };
}; };
const fetchComposeSuggestionsAccounts = throttle((dispatch, getState, token) => { const fetchComposeSuggestionsAccounts = throttle((dispatch, getState, composeId, token) => {
if (cancelFetchComposeSuggestionsAccounts) { if (cancelFetchComposeSuggestionsAccounts) {
cancelFetchComposeSuggestionsAccounts(); cancelFetchComposeSuggestionsAccounts(composeId);
} }
api(getState).get('/api/v1/accounts/search', { api(getState).get('/api/v1/accounts/search', {
cancelToken: new CancelToken(cancel => { cancelToken: new CancelToken(cancel => {
@ -473,7 +491,7 @@ const fetchComposeSuggestionsAccounts = throttle((dispatch, getState, token) =>
}, },
}).then(response => { }).then(response => {
dispatch(importFetchedAccounts(response.data)); dispatch(importFetchedAccounts(response.data));
dispatch(readyComposeSuggestionsAccounts(token, response.data)); dispatch(readyComposeSuggestionsAccounts(composeId, token, response.data));
}).catch(error => { }).catch(error => {
if (!isCancel(error)) { if (!isCancel(error)) {
dispatch(showAlertForError(error)); dispatch(showAlertForError(error));
@ -481,46 +499,48 @@ const fetchComposeSuggestionsAccounts = throttle((dispatch, getState, token) =>
}); });
}, 200, { leading: true, trailing: true }); }, 200, { leading: true, trailing: true });
const fetchComposeSuggestionsEmojis = (dispatch: AppDispatch, getState: () => RootState, token: string) => { const fetchComposeSuggestionsEmojis = (dispatch: AppDispatch, getState: () => RootState, composeId: string, token: string) => {
const results = emojiSearch(token.replace(':', ''), { maxResults: 5 } as any); const results = emojiSearch(token.replace(':', ''), { maxResults: 5 } as any);
dispatch(readyComposeSuggestionsEmojis(token, results)); dispatch(readyComposeSuggestionsEmojis(composeId, token, results));
}; };
const fetchComposeSuggestionsTags = (dispatch: AppDispatch, getState: () => RootState, token: string) => { const fetchComposeSuggestionsTags = (dispatch: AppDispatch, getState: () => RootState, composeId: string, token: string) => {
const state = getState(); const state = getState();
const currentTrends = state.trends.items; const currentTrends = state.trends.items;
dispatch(updateSuggestionTags(token, currentTrends)); dispatch(updateSuggestionTags(composeId, token, currentTrends));
}; };
const fetchComposeSuggestions = (token: string) => const fetchComposeSuggestions = (composeId: string, token: string) =>
(dispatch: AppDispatch, getState: () => RootState) => { (dispatch: AppDispatch, getState: () => RootState) => {
switch (token[0]) { switch (token[0]) {
case ':': case ':':
fetchComposeSuggestionsEmojis(dispatch, getState, token); fetchComposeSuggestionsEmojis(dispatch, getState, composeId, token);
break; break;
case '#': case '#':
fetchComposeSuggestionsTags(dispatch, getState, token); fetchComposeSuggestionsTags(dispatch, getState, composeId, token);
break; break;
default: default:
fetchComposeSuggestionsAccounts(dispatch, getState, token); fetchComposeSuggestionsAccounts(dispatch, getState, composeId, token);
break; break;
} }
}; };
const readyComposeSuggestionsEmojis = (token: string, emojis: Emoji[]) => ({ const readyComposeSuggestionsEmojis = (composeId: string, token: string, emojis: Emoji[]) => ({
type: COMPOSE_SUGGESTIONS_READY, type: COMPOSE_SUGGESTIONS_READY,
id: composeId,
token, token,
emojis, emojis,
}); });
const readyComposeSuggestionsAccounts = (token: string, accounts: APIEntity[]) => ({ const readyComposeSuggestionsAccounts = (composeId: string, token: string, accounts: APIEntity[]) => ({
type: COMPOSE_SUGGESTIONS_READY, type: COMPOSE_SUGGESTIONS_READY,
id: composeId,
token, token,
accounts, accounts,
}); });
const selectComposeSuggestion = (position: number, token: string | null, suggestion: AutoSuggestion, path: Array<string | number>) => const selectComposeSuggestion = (composeId: string, position: number, token: string | null, suggestion: AutoSuggestion, path: Array<string | number>) =>
(dispatch: AppDispatch, getState: () => RootState) => { (dispatch: AppDispatch, getState: () => RootState) => {
let completion, startPosition; let completion, startPosition;
@ -539,6 +559,7 @@ const selectComposeSuggestion = (position: number, token: string | null, suggest
dispatch({ dispatch({
type: COMPOSE_SUGGESTION_SELECT, type: COMPOSE_SUGGESTION_SELECT,
id: composeId,
position: startPosition, position: startPosition,
token, token,
completion, completion,
@ -546,14 +567,16 @@ const selectComposeSuggestion = (position: number, token: string | null, suggest
}); });
}; };
const updateSuggestionTags = (token: string, currentTrends: ImmutableList<Tag>) => ({ const updateSuggestionTags = (composeId: string, token: string, currentTrends: ImmutableList<Tag>) => ({
type: COMPOSE_SUGGESTION_TAGS_UPDATE, type: COMPOSE_SUGGESTION_TAGS_UPDATE,
id: composeId,
token, token,
currentTrends, currentTrends,
}); });
const updateTagHistory = (tags: string[]) => ({ const updateTagHistory = (composeId: string, tags: string[]) => ({
type: COMPOSE_TAG_HISTORY_UPDATE, type: COMPOSE_TAG_HISTORY_UPDATE,
id: composeId,
tags, tags,
}); });
@ -572,7 +595,7 @@ const insertIntoTagHistory = (composeId: string, recognizedTags: APIEntity[], te
const newHistory = names.slice(0, 1000); const newHistory = names.slice(0, 1000);
tagHistory.set(me as string, newHistory); tagHistory.set(me as string, newHistory);
dispatch(updateTagHistory(newHistory)); dispatch(updateTagHistory(composeId, newHistory));
}; };
const changeComposeSensitivity = (composeId: string) => ({ const changeComposeSensitivity = (composeId: string) => ({
@ -665,29 +688,31 @@ const changePollSettings = (composeId: string, expiresIn?: string | number, isMu
const openComposeWithText = (composeId: string, text = '') => const openComposeWithText = (composeId: string, text = '') =>
(dispatch: AppDispatch) => { (dispatch: AppDispatch) => {
dispatch(resetCompose()); dispatch(resetCompose(composeId));
dispatch(openModal('COMPOSE')); dispatch(openModal('COMPOSE'));
dispatch(changeCompose(composeId, text)); dispatch(changeCompose(composeId, text));
}; };
const addToMentions = (accountId: string) => const addToMentions = (composeId: string, accountId: string) =>
(dispatch: AppDispatch, getState: () => RootState) => { (dispatch: AppDispatch, getState: () => RootState) => {
const state = getState(); const state = getState();
const acct = state.accounts.get(accountId)!.acct; const acct = state.accounts.get(accountId)!.acct;
return dispatch({ return dispatch({
type: COMPOSE_ADD_TO_MENTIONS, type: COMPOSE_ADD_TO_MENTIONS,
id: composeId,
account: acct, account: acct,
}); });
}; };
const removeFromMentions = (accountId: string) => const removeFromMentions = (composeId: string, accountId: string) =>
(dispatch: AppDispatch, getState: () => RootState) => { (dispatch: AppDispatch, getState: () => RootState) => {
const state = getState(); const state = getState();
const acct = state.accounts.get(accountId)!.acct; const acct = state.accounts.get(accountId)!.acct;
return dispatch({ return dispatch({
type: COMPOSE_REMOVE_FROM_MENTIONS, type: COMPOSE_REMOVE_FROM_MENTIONS,
id: composeId,
account: acct, account: acct,
}); });
}; };

View File

@ -149,19 +149,19 @@ const ComposeForm: React.FC<IComposeForm> = ({ id, shouldCondense, autoFocus, cl
}; };
const onSuggestionsClearRequested = () => { const onSuggestionsClearRequested = () => {
dispatch(clearComposeSuggestions()); dispatch(clearComposeSuggestions(id));
}; };
const onSuggestionsFetchRequested = (token: string | number) => { const onSuggestionsFetchRequested = (token: string | number) => {
dispatch(fetchComposeSuggestions(token as string)); dispatch(fetchComposeSuggestions(id, token as string));
}; };
const onSuggestionSelected = (tokenStart: number, token: string | null, value: string | undefined) => { const onSuggestionSelected = (tokenStart: number, token: string | null, value: string | undefined) => {
if (value) dispatch(selectComposeSuggestion(tokenStart, token, value, ['text'])); if (value) dispatch(selectComposeSuggestion(id, tokenStart, token, value, ['text']));
}; };
const onSpoilerSuggestionSelected = (tokenStart: number, token: string | null, value: AutoSuggestion) => { const onSpoilerSuggestionSelected = (tokenStart: number, token: string | null, value: AutoSuggestion) => {
dispatch(selectComposeSuggestion(tokenStart, token, value, ['spoiler_text'])); dispatch(selectComposeSuggestion(id, tokenStart, token, value, ['spoiler_text']));
}; };
const handleChangeSpoilerText: React.ChangeEventHandler<HTMLInputElement> = (e) => { const handleChangeSpoilerText: React.ChangeEventHandler<HTMLInputElement> = (e) => {

View File

@ -115,7 +115,6 @@ const EmojiPickerDropdown: React.FC<IEmojiPickerDropdown> = ({ onPickEmoji, butt
}; };
const handlePickEmoji = (emoji: EmojiType) => { const handlePickEmoji = (emoji: EmojiType) => {
console.log(emoji);
// eslint-disable-next-line react-hooks/rules-of-hooks // eslint-disable-next-line react-hooks/rules-of-hooks
dispatch(useEmoji(emoji)); dispatch(useEmoji(emoji));

View File

@ -61,13 +61,13 @@ const Option: React.FC<IOption> = ({
} }
}; };
const onSuggestionsClearRequested = () => dispatch(clearComposeSuggestions()); const onSuggestionsClearRequested = () => dispatch(clearComposeSuggestions(composeId));
const onSuggestionsFetchRequested = (token: string) => dispatch(fetchComposeSuggestions(token)); const onSuggestionsFetchRequested = (token: string) => dispatch(fetchComposeSuggestions(composeId, token));
const onSuggestionSelected = (tokenStart: number, token: string | null, value: AutoSuggestion) => { const onSuggestionSelected = (tokenStart: number, token: string | null, value: AutoSuggestion) => {
if (token && typeof token === 'string') { if (token && typeof token === 'string') {
dispatch(selectComposeSuggestion(tokenStart, token, value, ['poll', 'options', index])); dispatch(selectComposeSuggestion(composeId, tokenStart, token, value, ['poll', 'options', index]));
} }
}; };

View File

@ -22,8 +22,8 @@ const ScheduleButton: React.FC<IScheduleButton> = ({ composeId, disabled }) => {
const compose = useCompose(composeId); const compose = useCompose(composeId);
const active = compose.schedule; const active = !!compose.schedule;
const unavailable = compose.id; const unavailable = !!compose.id;
const handleClick = () => { const handleClick = () => {
if (active) { if (active) {

View File

@ -91,7 +91,7 @@ const Upload: React.FC<IUpload> = ({ composeId, id }) => {
const handleUndoClick: React.MouseEventHandler = e => { const handleUndoClick: React.MouseEventHandler = e => {
e.stopPropagation(); e.stopPropagation();
dispatch(undoUploadCompose(media.id)); dispatch(undoUploadCompose(composeId, media.id));
}; };
const handleInputChange: React.ChangeEventHandler<HTMLTextAreaElement> = e => { const handleInputChange: React.ChangeEventHandler<HTMLTextAreaElement> = e => {
@ -119,7 +119,7 @@ const Upload: React.FC<IUpload> = ({ composeId, id }) => {
setDirtyDescription(null); setDirtyDescription(null);
if (dirtyDescription !== null) { if (dirtyDescription !== null) {
dispatch(changeUploadCompose(media.id, { dirtyDescription })); dispatch(changeUploadCompose(composeId, media.id, { dirtyDescription }));
} }
}; };

View File

@ -9,7 +9,7 @@ import type { AppDispatch, RootState } from 'soapbox/store';
const mapStateToProps = (state: RootState, { composeId }: { composeId: string }) => ({ const mapStateToProps = (state: RootState, { composeId }: { composeId: string }) => ({
disabled: state.compose.get(composeId)?.is_uploading, disabled: state.compose.get(composeId)?.is_uploading,
resetFileKey: state.compose.get(composeId)?.resetFileKey, resetFileKey: state.compose.get(composeId)?.resetFileKey!,
}); });
const mapDispatchToProps = (dispatch: AppDispatch, { composeId }: { composeId: string }) => ({ const mapDispatchToProps = (dispatch: AppDispatch, { composeId }: { composeId: string }) => ({

View File

@ -26,11 +26,13 @@ const Account: React.FC<IAccount> = ({ composeId, accountId, author }) => {
const intl = useIntl(); const intl = useIntl();
const dispatch = useAppDispatch(); const dispatch = useAppDispatch();
const account = useAppSelector((state) => getAccount(state, accountId)); const compose = useCompose(composeId);
const added = !!account && useCompose(composeId).to?.includes(account.acct);
const onRemove = () => dispatch(removeFromMentions(accountId)); const account = useAppSelector((state) => getAccount(state, accountId));
const onAdd = () => dispatch(addToMentions(accountId)); const added = !!account && compose.to?.includes(account.acct);
const onRemove = () => dispatch(removeFromMentions(composeId, accountId));
const onAdd = () => dispatch(addToMentions(composeId, accountId));
useEffect(() => { useEffect(() => {
if (accountId && !account) { if (accountId && !account) {

View File

@ -1,499 +1,510 @@
// import { List as ImmutableList, Record as ImmutableRecord, fromJS } from 'immutable'; import { List as ImmutableList, Record as ImmutableRecord, fromJS } from 'immutable';
// import * as actions from 'soapbox/actions/compose'; import * as actions from 'soapbox/actions/compose';
// import { ME_FETCH_SUCCESS, ME_PATCH_SUCCESS } from 'soapbox/actions/me'; import { ME_FETCH_SUCCESS, ME_PATCH_SUCCESS } from 'soapbox/actions/me';
// import { SETTING_CHANGE } from 'soapbox/actions/settings'; import { SETTING_CHANGE } from 'soapbox/actions/settings';
// import { TIMELINE_DELETE } from 'soapbox/actions/timelines'; import { TIMELINE_DELETE } from 'soapbox/actions/timelines';
// import { TagRecord } from 'soapbox/normalizers'; import { TagRecord } from 'soapbox/normalizers';
// import { normalizeStatus } from 'soapbox/normalizers/status'; import { normalizeStatus } from 'soapbox/normalizers/status';
// import reducer, { ReducerRecord } from '../compose'; import reducer, { initialState, ReducerCompose } from '../compose';
// describe('compose reducer', () => { describe('compose reducer', () => {
// it('returns the initial state by default', () => { it('returns the initial state by default', () => {
// const state = reducer(undefined, {} as any); const state = reducer(undefined, {} as any);
// expect(state.toJS()).toMatchObject({ expect(state.toJS()).toMatchObject({
// mounted: 0, default: {
// sensitive: false, sensitive: false,
// spoiler: false, spoiler: false,
// spoiler_text: '', spoiler_text: '',
// privacy: 'public', privacy: 'public',
// text: '', text: '',
// focusDate: null, focusDate: null,
// caretPosition: null, caretPosition: null,
// in_reply_to: null, in_reply_to: null,
// is_composing: false, is_composing: false,
// is_submitting: false, is_submitting: false,
// is_changing_upload: false, is_changing_upload: false,
// is_uploading: false, is_uploading: false,
// progress: 0, progress: 0,
// media_attachments: [], media_attachments: [],
// poll: null, poll: null,
// suggestion_token: null, suggestion_token: null,
// suggestions: [], suggestions: [],
// default_privacy: 'public', default_privacy: 'public',
// default_sensitive: false, default_sensitive: false,
// tagHistory: [], tagHistory: [],
// content_type: 'text/plain', content_type: 'text/plain',
// }); },
// expect(state.get('idempotencyKey').length === 36); });
// }); expect(state.get('default')!.idempotencyKey.length === 36);
});
// describe('COMPOSE_SET_STATUS', () => { describe('COMPOSE_SET_STATUS', () => {
// it('strips Pleroma integer attachments', () => { it('strips Pleroma integer attachments', () => {
// const action = { const action = {
// type: actions.COMPOSE_SET_STATUS, type: actions.COMPOSE_SET_STATUS,
// status: normalizeStatus(fromJS(require('soapbox/__fixtures__/pleroma-status-deleted.json'))), id: 'compose-modal',
// v: { software: 'Pleroma' }, status: normalizeStatus(fromJS(require('soapbox/__fixtures__/pleroma-status-deleted.json'))),
// withRedraft: true, v: { software: 'Pleroma' },
// }; withRedraft: true,
};
// const result = reducer(undefined, action); const result = reducer(undefined, action);
// expect(result.get('media_attachments').isEmpty()).toBe(true); expect(result.get('compose-modal')!.media_attachments.isEmpty()).toBe(true);
// }); });
// it('leaves non-Pleroma integer attachments alone', () => { it('leaves non-Pleroma integer attachments alone', () => {
// const action = { const action = {
// type: actions.COMPOSE_SET_STATUS, type: actions.COMPOSE_SET_STATUS,
// status: normalizeStatus(fromJS(require('soapbox/__fixtures__/pleroma-status-deleted.json'))), id: 'compose-modal',
// }; status: normalizeStatus(fromJS(require('soapbox/__fixtures__/pleroma-status-deleted.json'))),
};
// const result = reducer(undefined, action); const result = reducer(undefined, action);
// expect(result.getIn(['media_attachments', 0, 'id'])).toEqual('508107650'); expect(result.get('compose-modal')!.media_attachments.getIn([0, 'id'])).toEqual('508107650');
// }); });
// it('sets the id when editing a post', () => { it('sets the id when editing a post', () => {
// const action = { const action = {
// withRedraft: false, id: 'compose-modal',
// type: actions.COMPOSE_SET_STATUS, withRedraft: false,
// status: normalizeStatus(fromJS(require('soapbox/__fixtures__/pleroma-status-deleted.json'))), type: actions.COMPOSE_SET_STATUS,
// }; status: normalizeStatus(fromJS(require('soapbox/__fixtures__/pleroma-status-deleted.json'))),
};
// const result = reducer(undefined, action); const result = reducer(undefined, action);
// expect(result.get('id')).toEqual('AHU2RrX0wdcwzCYjFQ'); expect(result.get('compose-modal')!.id).toEqual('AHU2RrX0wdcwzCYjFQ');
// }); });
// it('does not set the id when redrafting a post', () => { it('does not set the id when redrafting a post', () => {
// const action = { const action = {
// withRedraft: true, id: 'compose-modal',
// type: actions.COMPOSE_SET_STATUS, withRedraft: true,
// status: normalizeStatus(fromJS(require('soapbox/__fixtures__/pleroma-status-deleted.json'))), type: actions.COMPOSE_SET_STATUS,
// }; status: normalizeStatus(fromJS(require('soapbox/__fixtures__/pleroma-status-deleted.json'))),
};
// const result = reducer(undefined, action); const result = reducer(undefined, action);
// expect(result.get('id')).toEqual(null); expect(result.get('compose-modal')!.id).toEqual(null);
// }); });
// }); });
// it('uses \'public\' scope as default', () => { it('uses \'public\' scope as default', () => {
// const action = { const action = {
// type: actions.COMPOSE_REPLY, type: actions.COMPOSE_REPLY,
// status: ImmutableRecord({})(), status: ImmutableRecord({})(),
// account: ImmutableRecord({})(), account: ImmutableRecord({})(),
// }; };
// expect(reducer(undefined, action).toJS()).toMatchObject({ privacy: 'public' }); expect(reducer(undefined, action).toJS()['compose-modal']).toMatchObject({ privacy: 'public' });
// }); });
// it('uses \'direct\' scope when replying to a DM', () => { it('uses \'direct\' scope when replying to a DM', () => {
// const state = ReducerRecord({ default_privacy: 'public' }); const state = initialState.set('default', ReducerCompose({ default_privacy: 'public' }));
// const action = { const action = {
// type: actions.COMPOSE_REPLY, type: actions.COMPOSE_REPLY,
// status: ImmutableRecord({ visibility: 'direct' })(), status: ImmutableRecord({ visibility: 'direct' })(),
// account: ImmutableRecord({})(), account: ImmutableRecord({})(),
// }; };
// expect(reducer(state as any, action).toJS()).toMatchObject({ privacy: 'direct' }); expect(reducer(state as any, action).toJS()['compose-modal']).toMatchObject({ privacy: 'direct' });
// }); });
// it('uses \'private\' scope when replying to a private post', () => { it('uses \'private\' scope when replying to a private post', () => {
// const state = ReducerRecord({ default_privacy: 'public' }); const state = initialState.set('default', ReducerCompose({ default_privacy: 'public' }));
// const action = { const action = {
// type: actions.COMPOSE_REPLY, type: actions.COMPOSE_REPLY,
// status: ImmutableRecord({ visibility: 'private' })(), status: ImmutableRecord({ visibility: 'private' })(),
// account: ImmutableRecord({})(), account: ImmutableRecord({})(),
// }; };
// expect(reducer(state as any, action).toJS()).toMatchObject({ privacy: 'private' }); expect(reducer(state as any, action).toJS()['compose-modal']).toMatchObject({ privacy: 'private' });
// }); });
// it('uses \'unlisted\' scope when replying to an unlisted post', () => { it('uses \'unlisted\' scope when replying to an unlisted post', () => {
// const state = ReducerRecord({ default_privacy: 'public' }); const state = initialState.set('default', ReducerCompose({ default_privacy: 'public' }));
// const action = { const action = {
// type: actions.COMPOSE_REPLY, type: actions.COMPOSE_REPLY,
// status: ImmutableRecord({ visibility: 'unlisted' })(), status: ImmutableRecord({ visibility: 'unlisted' })(),
// account: ImmutableRecord({})(), account: ImmutableRecord({})(),
// }; };
// expect(reducer(state, action).toJS()).toMatchObject({ privacy: 'unlisted' }); expect(reducer(state, action).toJS()['compose-modal']).toMatchObject({ privacy: 'unlisted' });
// }); });
// it('uses \'private\' scope when set as preference and replying to a public post', () => { it('uses \'private\' scope when set as preference and replying to a public post', () => {
// const state = ReducerRecord({ default_privacy: 'private' }); const state = initialState.set('default', ReducerCompose({ default_privacy: 'private' }));
// const action = { const action = {
// type: actions.COMPOSE_REPLY, type: actions.COMPOSE_REPLY,
// status: ImmutableRecord({ visibility: 'public' })(), status: ImmutableRecord({ visibility: 'public' })(),
// account: ImmutableRecord({})(), account: ImmutableRecord({})(),
// }; };
// expect(reducer(state, action).toJS()).toMatchObject({ privacy: 'private' }); expect(reducer(state, action).toJS()['compose-modal']).toMatchObject({ privacy: 'private' });
// }); });
// it('uses \'unlisted\' scope when set as preference and replying to a public post', () => { it('uses \'unlisted\' scope when set as preference and replying to a public post', () => {
// const state = ReducerRecord({ default_privacy: 'unlisted' }); const state = initialState.set('default', ReducerCompose({ default_privacy: 'unlisted' }));
// const action = { const action = {
// type: actions.COMPOSE_REPLY, type: actions.COMPOSE_REPLY,
// status: ImmutableRecord({ visibility: 'public' })(), status: ImmutableRecord({ visibility: 'public' })(),
// account: ImmutableRecord({})(), account: ImmutableRecord({})(),
// }; };
// expect(reducer(state, action).toJS()).toMatchObject({ privacy: 'unlisted' }); expect(reducer(state, action).toJS()['compose-modal']).toMatchObject({ privacy: 'unlisted' });
// }); });
// it('sets preferred scope on user login', () => { it('sets preferred scope on user login', () => {
// const state = ReducerRecord({ default_privacy: 'public' }); const state = initialState.set('default', ReducerCompose({ default_privacy: 'public' }));
// const action = { const action = {
// type: ME_FETCH_SUCCESS, type: ME_FETCH_SUCCESS,
// me: { pleroma: { settings_store: { soapbox_fe: { defaultPrivacy: 'unlisted' } } } }, me: { pleroma: { settings_store: { soapbox_fe: { defaultPrivacy: 'unlisted' } } } },
// }; };
// expect(reducer(state, action).toJS()).toMatchObject({ expect(reducer(state, action).toJS().default).toMatchObject({
// default_privacy: 'unlisted', default_privacy: 'unlisted',
// privacy: 'unlisted', privacy: 'unlisted',
// }); });
// }); });
// it('sets preferred scope on settings change', () => { it('sets preferred scope on settings change', () => {
// const state = ReducerRecord({ default_privacy: 'public' }); const state = initialState.set('default', ReducerCompose({ default_privacy: 'public' }));
// const action = { const action = {
// type: SETTING_CHANGE, type: SETTING_CHANGE,
// path: ['defaultPrivacy'], path: ['defaultPrivacy'],
// value: 'unlisted', value: 'unlisted',
// }; };
// expect(reducer(state, action).toJS()).toMatchObject({ expect(reducer(state, action).toJS().default).toMatchObject({
// default_privacy: 'unlisted', default_privacy: 'unlisted',
// privacy: 'unlisted', privacy: 'unlisted',
// }); });
// }); });
// it('sets default scope on settings save (but retains current scope)', () => { it('sets default scope on settings save (but retains current scope)', () => {
// const state = ReducerRecord({ default_privacy: 'public', privacy: 'public' }); const state = initialState.set('default', ReducerCompose({ default_privacy: 'public', privacy: 'public' }));
// const action = { const action = {
// type: ME_PATCH_SUCCESS, type: ME_PATCH_SUCCESS,
// me: { pleroma: { settings_store: { soapbox_fe: { defaultPrivacy: 'unlisted' } } } }, me: { pleroma: { settings_store: { soapbox_fe: { defaultPrivacy: 'unlisted' } } } },
// }; };
// expect(reducer(state, action).toJS()).toMatchObject({ expect(reducer(state, action).toJS().default).toMatchObject({
// default_privacy: 'unlisted', default_privacy: 'unlisted',
// privacy: 'public', privacy: 'public',
// }); });
// }); });
// it('should handle COMPOSE_MOUNT', () => { it('should handle COMPOSE_SENSITIVITY_CHANGE on Mark Sensitive click, don\'t toggle if spoiler active', () => {
// const state = ReducerRecord({ mounted: 1 }); const state = initialState.set('home', ReducerCompose({ spoiler: true, sensitive: true, idempotencyKey: '' }));
// const action = { const action = {
// type: actions.COMPOSE_MOUNT, type: actions.COMPOSE_SENSITIVITY_CHANGE,
// }; id: 'home',
// expect(reducer(state, action).toJS()).toMatchObject({ };
// mounted: 2, expect(reducer(state, action).toJS().home).toMatchObject({
// }); sensitive: true,
// }); });
});
// it('should handle COMPOSE_UNMOUNT', () => { it('should handle COMPOSE_SENSITIVITY_CHANGE on Mark Sensitive click, toggle if spoiler inactive', () => {
// const state = ReducerRecord({ mounted: 1 }); const state = initialState.set('home', ReducerCompose({ spoiler: false, sensitive: true }));
// const action = { const action = {
// type: actions.COMPOSE_UNMOUNT, type: actions.COMPOSE_SENSITIVITY_CHANGE,
// }; id: 'home',
// expect(reducer(state, action).toJS()).toMatchObject({ };
// mounted: 0, expect(reducer(state, action).toJS().home).toMatchObject({
// }); sensitive: false,
// }); });
});
// it('should handle COMPOSE_SENSITIVITY_CHANGE on Mark Sensitive click, don\'t toggle if spoiler active', () => { it('should handle COMPOSE_SPOILERNESS_CHANGE on CW button click', () => {
// const state = ReducerRecord({ spoiler: true, sensitive: true, idempotencyKey: '' }); const state = initialState.set('home', ReducerCompose({ spoiler_text: 'spoiler text', spoiler: true, media_attachments: ImmutableList() }));
// const action = { const action = {
// type: actions.COMPOSE_SENSITIVITY_CHANGE, type: actions.COMPOSE_SPOILERNESS_CHANGE,
// }; id: 'home',
// expect(reducer(state, action).toJS()).toMatchObject({ };
// sensitive: true, expect(reducer(state, action).toJS().home).toMatchObject({
// }); spoiler: false,
// }); spoiler_text: '',
});
});
// it('should handle COMPOSE_SENSITIVITY_CHANGE on Mark Sensitive click, toggle if spoiler inactive', () => { it('should handle COMPOSE_SPOILER_TEXT_CHANGE', () => {
// const state = ReducerRecord({ spoiler: false, sensitive: true }); const state = initialState.set('home', ReducerCompose({ spoiler_text: 'prevtext' }));
// const action = { const action = {
// type: actions.COMPOSE_SENSITIVITY_CHANGE, type: actions.COMPOSE_SPOILER_TEXT_CHANGE,
// }; id: 'home',
// expect(reducer(state, action).toJS()).toMatchObject({ text: 'nexttext',
// sensitive: false, };
// }); expect(reducer(state, action).toJS().home).toMatchObject({
// }); spoiler_text: 'nexttext',
});
});
// it('should handle COMPOSE_SPOILERNESS_CHANGE on CW button click', () => { it('should handle COMPOSE_VISIBILITY_CHANGE', () => {
// const state = ReducerRecord({ spoiler_text: 'spoiler text', spoiler: true, media_attachments: ImmutableList() }); const state = initialState.set('home', ReducerCompose({ privacy: 'public' }));
// const action = { const action = {
// type: actions.COMPOSE_SPOILERNESS_CHANGE, type: actions.COMPOSE_VISIBILITY_CHANGE,
// }; id: 'home',
// expect(reducer(state, action).toJS()).toMatchObject({ value: 'direct',
// spoiler: false, };
// spoiler_text: '', expect(reducer(state, action).toJS().home).toMatchObject({
// }); privacy: 'direct',
// }); });
});
// it('should handle COMPOSE_SPOILER_TEXT_CHANGE', () => { describe('COMPOSE_CHANGE', () => {
// const state = ReducerRecord({ spoiler_text: 'prevtext' }); it('should handle text changing', () => {
// const action = { const state = initialState.set('home', ReducerCompose({ text: 'prevtext' }));
// type: actions.COMPOSE_SPOILER_TEXT_CHANGE, const action = {
// text: 'nexttext', type: actions.COMPOSE_CHANGE,
// }; id: 'home',
// expect(reducer(state, action).toJS()).toMatchObject({ text: 'nexttext',
// spoiler_text: 'nexttext', };
// }); expect(reducer(state, action).toJS().home).toMatchObject({
// }); text: 'nexttext',
});
});
});
// it('should handle COMPOSE_VISIBILITY_CHANGE', () => { it('should handle COMPOSE_COMPOSING_CHANGE', () => {
// const state = ReducerRecord({ privacy: 'public' }); const state = initialState.set('home', ReducerCompose({ is_composing: true }));
// const action = { const action = {
// type: actions.COMPOSE_VISIBILITY_CHANGE, type: actions.COMPOSE_COMPOSING_CHANGE,
// value: 'direct', id: 'home',
// }; value: false,
// expect(reducer(state, action).toJS()).toMatchObject({ };
// privacy: 'direct', expect(reducer(state, action).toJS().home).toMatchObject({
// }); is_composing: false,
// }); });
});
// describe('COMPOSE_CHANGE', () => { it('should handle COMPOSE_SUBMIT_REQUEST', () => {
// it('should handle text changing', () => { const state = initialState.set('home', ReducerCompose({ is_submitting: false }));
// const state = ReducerRecord({ text: 'prevtext' }); const action = {
// const action = { type: actions.COMPOSE_SUBMIT_REQUEST,
// type: actions.COMPOSE_CHANGE, id: 'home',
// text: 'nexttext', };
// }; expect(reducer(state, action).toJS().home).toMatchObject({
// expect(reducer(state, action).toJS()).toMatchObject({ is_submitting: true,
// text: 'nexttext', });
// }); });
// });
// });
// it('should handle COMPOSE_COMPOSING_CHANGE', () => { it('should handle COMPOSE_UPLOAD_CHANGE_REQUEST', () => {
// const state = ReducerRecord({ is_composing: true }); const state = initialState.set('home', ReducerCompose({ is_changing_upload: false }));
// const action = { const action = {
// type: actions.COMPOSE_COMPOSING_CHANGE, type: actions.COMPOSE_UPLOAD_CHANGE_REQUEST,
// value: false, id: 'home',
// }; };
// expect(reducer(state, action).toJS()).toMatchObject({ expect(reducer(state, action).toJS().home).toMatchObject({
// is_composing: false, is_changing_upload: true,
// }); });
// }); });
// it('should handle COMPOSE_SUBMIT_REQUEST', () => { it('should handle COMPOSE_SUBMIT_SUCCESS', () => {
// const state = ReducerRecord({ is_submitting: false }); const state = initialState.set('home', ReducerCompose({ default_privacy: 'public', privacy: 'private' }));
// const action = { const action = {
// type: actions.COMPOSE_SUBMIT_REQUEST, type: actions.COMPOSE_SUBMIT_SUCCESS,
// }; id: 'home',
// expect(reducer(state, action).toJS()).toMatchObject({ };
// is_submitting: true, expect(reducer(state, action).toJS().home).toMatchObject({
// }); privacy: 'public',
// }); });
});
// it('should handle COMPOSE_UPLOAD_CHANGE_REQUEST', () => { it('should handle COMPOSE_SUBMIT_FAIL', () => {
// const state = ReducerRecord({ is_changing_upload: false }); const state = initialState.set('home', ReducerCompose({ is_submitting: true }));
// const action = { const action = {
// type: actions.COMPOSE_UPLOAD_CHANGE_REQUEST, type: actions.COMPOSE_SUBMIT_FAIL,
// }; id: 'home',
// expect(reducer(state, action).toJS()).toMatchObject({ };
// is_changing_upload: true, expect(reducer(state, action).toJS().home).toMatchObject({
// }); is_submitting: false,
// }); });
});
// it('should handle COMPOSE_SUBMIT_SUCCESS', () => { it('should handle COMPOSE_UPLOAD_CHANGE_FAIL', () => {
// const state = ReducerRecord({ default_privacy: 'public', privacy: 'private' }); const state = initialState.set('home', ReducerCompose({ is_changing_upload: true }));
// const action = { const action = {
// type: actions.COMPOSE_SUBMIT_SUCCESS, type: actions.COMPOSE_UPLOAD_CHANGE_FAIL,
// }; composeId: 'home',
// expect(reducer(state, action).toJS()).toMatchObject({ };
// privacy: 'public', expect(reducer(state, action).toJS().home).toMatchObject({
// }); is_changing_upload: false,
// }); });
});
// it('should handle COMPOSE_SUBMIT_FAIL', () => { it('should handle COMPOSE_UPLOAD_REQUEST', () => {
// const state = ReducerRecord({ is_submitting: true }); const state = initialState.set('home', ReducerCompose({ is_uploading: false }));
// const action = { const action = {
// type: actions.COMPOSE_SUBMIT_FAIL, type: actions.COMPOSE_UPLOAD_REQUEST,
// }; id: 'home',
// expect(reducer(state, action).toJS()).toMatchObject({ };
// is_submitting: false, expect(reducer(state, action).toJS().home).toMatchObject({
// }); is_uploading: true,
// }); });
});
// it('should handle COMPOSE_UPLOAD_CHANGE_FAIL', () => { it('should handle COMPOSE_UPLOAD_SUCCESS', () => {
// const state = ReducerRecord({ is_changing_upload: true }); const state = initialState.set('home', ReducerCompose({ media_attachments: ImmutableList() }));
// const action = { const media = [
// type: actions.COMPOSE_UPLOAD_CHANGE_FAIL, {
// }; description: null,
// expect(reducer(state, action).toJS()).toMatchObject({ id: '1375732379',
// is_changing_upload: false, pleroma: {
// }); mime_type: 'image/jpeg',
// }); },
preview_url: 'https://media.gleasonator.com/media_attachments/files/000/853/856/original/7035d67937053e1d.jpg',
remote_url: 'https://media.gleasonator.com/media_attachments/files/000/853/856/original/7035d67937053e1d.jpg',
text_url: 'https://media.gleasonator.com/media_attachments/files/000/853/856/original/7035d67937053e1d.jpg',
type: 'image',
url: 'https://media.gleasonator.com/media_attachments/files/000/853/856/original/7035d67937053e1d.jpg',
},
];
const action = {
type: actions.COMPOSE_UPLOAD_SUCCESS,
id: 'home',
media: media,
skipLoading: true,
};
expect(reducer(state, action).toJS().home).toMatchObject({
is_uploading: false,
});
});
// it('should handle COMPOSE_UPLOAD_REQUEST', () => { it('should handle COMPOSE_UPLOAD_FAIL', () => {
// const state = ReducerRecord({ is_uploading: false }); const state = initialState.set('home', ReducerCompose({ is_uploading: true }));
// const action = { const action = {
// type: actions.COMPOSE_UPLOAD_REQUEST, type: actions.COMPOSE_UPLOAD_FAIL,
// }; id: 'home',
// expect(reducer(state, action).toJS()).toMatchObject({ };
// is_uploading: true, expect(reducer(state, action).toJS().home).toMatchObject({
// }); is_uploading: false,
// }); });
});
// it('should handle COMPOSE_UPLOAD_SUCCESS', () => { it('should handle COMPOSE_UPLOAD_PROGRESS', () => {
// const state = ReducerRecord({ media_attachments: ImmutableList() }); const state = initialState.set('home', ReducerCompose({ progress: 0 }));
// const media = [ const action = {
// { type: actions.COMPOSE_UPLOAD_PROGRESS,
// description: null, id: 'home',
// id: '1375732379', loaded: 10,
// pleroma: { total: 15,
// mime_type: 'image/jpeg', };
// }, expect(reducer(state, action).toJS().home).toMatchObject({
// preview_url: 'https://media.gleasonator.com/media_attachments/files/000/853/856/original/7035d67937053e1d.jpg', progress: 67,
// remote_url: 'https://media.gleasonator.com/media_attachments/files/000/853/856/original/7035d67937053e1d.jpg', });
// text_url: 'https://media.gleasonator.com/media_attachments/files/000/853/856/original/7035d67937053e1d.jpg', });
// type: 'image',
// url: 'https://media.gleasonator.com/media_attachments/files/000/853/856/original/7035d67937053e1d.jpg',
// },
// ];
// const action = {
// type: actions.COMPOSE_UPLOAD_SUCCESS,
// media: media,
// skipLoading: true,
// };
// expect(reducer(state, action).toJS()).toMatchObject({
// is_uploading: false,
// });
// });
// it('should handle COMPOSE_UPLOAD_FAIL', () => { it('should handle COMPOSE_SUGGESTIONS_CLEAR', () => {
// const state = ReducerRecord({ is_uploading: true }); const state = initialState.set('home', ReducerCompose());
// const action = { const action = {
// type: actions.COMPOSE_UPLOAD_FAIL, type: actions.COMPOSE_SUGGESTIONS_CLEAR,
// }; id: 'home',
// expect(reducer(state, action).toJS()).toMatchObject({ suggestions: [],
// is_uploading: false, suggestion_token: 'aiekdns3',
// }); };
// }); expect(reducer(state, action).toJS().home).toMatchObject({
suggestion_token: null,
});
});
// it('should handle COMPOSE_UPLOAD_PROGRESS', () => { it('should handle COMPOSE_SUGGESTION_TAGS_UPDATE', () => {
// const state = ReducerRecord({ progress: 0 }); const state = initialState.set('home', ReducerCompose({ tagHistory: ImmutableList([ 'hashtag' ]) }));
// const action = { const action = {
// type: actions.COMPOSE_UPLOAD_PROGRESS, type: actions.COMPOSE_SUGGESTION_TAGS_UPDATE,
// loaded: 10, id: 'home',
// total: 15, token: 'aaadken3',
// }; currentTrends: ImmutableList([
// expect(reducer(state, action).toJS()).toMatchObject({ TagRecord({ name: 'hashtag' }),
// progress: 67, ]),
// }); };
// }); expect(reducer(state, action).toJS().home).toMatchObject({
suggestion_token: 'aaadken3',
suggestions: [],
tagHistory: [ 'hashtag' ],
});
});
// it('should handle COMPOSE_SUGGESTIONS_CLEAR', () => { it('should handle COMPOSE_TAG_HISTORY_UPDATE', () => {
// const action = { const action = {
// type: actions.COMPOSE_SUGGESTIONS_CLEAR, type: actions.COMPOSE_TAG_HISTORY_UPDATE,
// suggestions: [], id: 'home',
// suggestion_token: 'aiekdns3', tags: [ 'hashtag', 'hashtag2'],
// }; };
// expect(reducer(undefined, action).toJS()).toMatchObject({ expect(reducer(undefined, action).toJS().home).toMatchObject({
// suggestion_token: null, tagHistory: [ 'hashtag', 'hashtag2' ],
// }); });
// }); });
// it('should handle COMPOSE_SUGGESTION_TAGS_UPDATE', () => { it('should handle TIMELINE_DELETE - delete status from timeline', () => {
// const state = ReducerRecord({ tagHistory: ImmutableList([ 'hashtag' ]) }); const state = initialState.set('compose-modal', ReducerCompose({ in_reply_to: '9wk6pmImMrZjgrK7iC' }));
// const action = { const action = {
// type: actions.COMPOSE_SUGGESTION_TAGS_UPDATE, type: TIMELINE_DELETE,
// token: 'aaadken3', id: '9wk6pmImMrZjgrK7iC',
// currentTrends: ImmutableList([ };
// TagRecord({ name: 'hashtag' }), expect(reducer(state, action).toJS()['compose-modal']).toMatchObject({
// ]), in_reply_to: null,
// }; });
// expect(reducer(state, action).toJS()).toMatchObject({ });
// suggestion_token: 'aaadken3',
// suggestions: [],
// tagHistory: [ 'hashtag' ],
// });
// });
// it('should handle COMPOSE_TAG_HISTORY_UPDATE', () => { it('should handle COMPOSE_POLL_ADD', () => {
// const action = { const state = initialState.set('home', ReducerCompose({ poll: null }));
// type: actions.COMPOSE_TAG_HISTORY_UPDATE, const initialPoll = Object({
// tags: [ 'hashtag', 'hashtag2'], options: [
// }; '',
// expect(reducer(undefined, action).toJS()).toMatchObject({ '',
// tagHistory: [ 'hashtag', 'hashtag2' ], ],
// }); expires_in: 86400,
// }); multiple: false,
});
const action = {
type: actions.COMPOSE_POLL_ADD,
id: 'home',
};
expect(reducer(state, action).toJS().home).toMatchObject({
poll: initialPoll,
});
});
// it('should handle TIMELINE_DELETE - delete status from timeline', () => { it('should handle COMPOSE_POLL_REMOVE', () => {
// const state = ReducerRecord({ in_reply_to: '9wk6pmImMrZjgrK7iC' }); const state = initialState.set('home', ReducerCompose());
// const action = { const action = {
// type: TIMELINE_DELETE, type: actions.COMPOSE_POLL_REMOVE,
// id: '9wk6pmImMrZjgrK7iC', id: 'home',
// }; };
// expect(reducer(state, action).toJS()).toMatchObject({ expect(reducer(state, action).toJS().home).toMatchObject({
// in_reply_to: null, poll: null,
// }); });
// }); });
// it('should handle COMPOSE_POLL_ADD', () => { it('should handle COMPOSE_POLL_OPTION_CHANGE', () => {
// const state = ReducerRecord({ poll: null }); const initialPoll = Object({
// const initialPoll = Object({ options: [
// options: [ 'option 1',
// '', 'option 2',
// '', ],
// ], expires_in: 86400,
// expires_in: 86400, multiple: false,
// multiple: false, });
// }); const state = initialState.set('home', ReducerCompose({ poll: initialPoll }));
// const action = { const action = {
// type: actions.COMPOSE_POLL_ADD, type: actions.COMPOSE_POLL_OPTION_CHANGE,
// }; id: 'home',
// expect(reducer(state, action).toJS()).toMatchObject({ index: 0,
// poll: initialPoll, title: 'change option',
// }); };
// }); const updatedPoll = Object({
options: [
'change option',
'option 2',
],
expires_in: 86400,
multiple: false,
});
expect(reducer(state, action).toJS().home).toMatchObject({
poll: updatedPoll,
});
});
// it('should handle COMPOSE_POLL_REMOVE', () => { it('sets the post content-type', () => {
// const action = { const state = initialState.set('home', ReducerCompose());
// type: actions.COMPOSE_POLL_REMOVE, const action = {
// }; type: actions.COMPOSE_TYPE_CHANGE,
// expect(reducer(undefined, action).toJS()).toMatchObject({ id: 'home',
// poll: null, value: 'text/plain',
// }); };
// }); expect(reducer(state, action).toJS().home).toMatchObject({ content_type: 'text/plain' });
});
// it('should handle COMPOSE_POLL_OPTION_CHANGE', () => { });
// const initialPoll = Object({
// options: [
// 'option 1',
// 'option 2',
// ],
// expires_in: 86400,
// multiple: false,
// });
// const state = ReducerRecord({ poll: initialPoll });
// const action = {
// type: actions.COMPOSE_POLL_OPTION_CHANGE,
// index: 0,
// title: 'change option',
// };
// const updatedPoll = Object({
// options: [
// 'change option',
// 'option 2',
// ],
// expires_in: 86400,
// multiple: false,
// });
// expect(reducer(state, action).toJS()).toMatchObject({
// poll: updatedPoll,
// });
// });
// it('sets the post content-type', () => {
// const action = {
// type: actions.COMPOSE_TYPE_CHANGE,
// value: 'text/plain',
// };
// expect(reducer(undefined, action).toJS()).toMatchObject({ content_type: 'text/plain' });
// });
// });

View File

@ -278,7 +278,7 @@ const updateSetting = (compose: Compose, path: string[], value: string) => {
const updateCompose = (state: State, key: string, updater: (compose: Compose) => Compose) => const updateCompose = (state: State, key: string, updater: (compose: Compose) => Compose) =>
state.update(key, state.get('default')!, updater); state.update(key, state.get('default')!, updater);
const initialState: State = ImmutableMap({ export const initialState: State = ImmutableMap({
default: ReducerCompose({ idempotencyKey: uuid(), resetFileKey: getResetFileKey() }), default: ReducerCompose({ idempotencyKey: uuid(), resetFileKey: getResetFileKey() }),
}); });
@ -361,11 +361,11 @@ export default function compose(state = initialState, action: AnyAction) {
case COMPOSE_QUOTE_CANCEL: case COMPOSE_QUOTE_CANCEL:
case COMPOSE_RESET: case COMPOSE_RESET:
case COMPOSE_SUBMIT_SUCCESS: case COMPOSE_SUBMIT_SUCCESS:
return state.get('default')!.set('idempotencyKey', uuid()); return updateCompose(state, action.id, () => state.get('default')!.set('idempotencyKey', uuid()));
case COMPOSE_SUBMIT_FAIL: case COMPOSE_SUBMIT_FAIL:
return updateCompose(state, action.id, compose => compose.set('is_submitting', false)); return updateCompose(state, action.id, compose => compose.set('is_submitting', false));
case COMPOSE_UPLOAD_CHANGE_FAIL: case COMPOSE_UPLOAD_CHANGE_FAIL:
return updateCompose(state, action.id, compose => compose.set('is_changing_upload', false)); return updateCompose(state, action.composeId, compose => compose.set('is_changing_upload', false));
case COMPOSE_UPLOAD_REQUEST: case COMPOSE_UPLOAD_REQUEST:
return updateCompose(state, action.id, compose => compose.set('is_uploading', true)); return updateCompose(state, action.id, compose => compose.set('is_uploading', true));
case COMPOSE_UPLOAD_SUCCESS: case COMPOSE_UPLOAD_SUCCESS:
@ -392,7 +392,7 @@ export default function compose(state = initialState, action: AnyAction) {
map.set('idempotencyKey', uuid()); map.set('idempotencyKey', uuid());
})); }));
case COMPOSE_SUGGESTIONS_CLEAR: case COMPOSE_SUGGESTIONS_CLEAR:
return updateCompose(state, action.id, compose => compose.update('suggestions', list => list.clear()).set('suggestion_token', null)); return updateCompose(state, action.id, compose => compose.update('suggestions', list => list?.clear()).set('suggestion_token', null));
case COMPOSE_SUGGESTIONS_READY: case COMPOSE_SUGGESTIONS_READY:
return updateCompose(state, action.id, compose => compose.set('suggestions', ImmutableList(action.accounts ? action.accounts.map((item: APIEntity) => item.id) : action.emojis)).set('suggestion_token', action.token)); return updateCompose(state, action.id, compose => compose.set('suggestions', ImmutableList(action.accounts ? action.accounts.map((item: APIEntity) => item.id) : action.emojis)).set('suggestion_token', action.token));
case COMPOSE_SUGGESTION_SELECT: case COMPOSE_SUGGESTION_SELECT:
@ -402,7 +402,7 @@ export default function compose(state = initialState, action: AnyAction) {
case COMPOSE_TAG_HISTORY_UPDATE: case COMPOSE_TAG_HISTORY_UPDATE:
return updateCompose(state, action.id, compose => compose.set('tagHistory', ImmutableList(fromJS(action.tags)) as ImmutableList<string>)); return updateCompose(state, action.id, compose => compose.set('tagHistory', ImmutableList(fromJS(action.tags)) as ImmutableList<string>));
case TIMELINE_DELETE: case TIMELINE_DELETE:
return updateCompose(state, action.id, compose => { return updateCompose(state, 'compose-modal', compose => {
if (action.id === compose.in_reply_to) { if (action.id === compose.in_reply_to) {
return compose.set('in_reply_to', null); return compose.set('in_reply_to', null);
} if (action.id === compose.quote) { } if (action.id === compose.quote) {

View File

@ -157,7 +157,6 @@ const rootReducer: typeof appReducer = (state, action) => {
case AUTH_LOGGED_OUT: case AUTH_LOGGED_OUT:
return appReducer(logOut(state), action); return appReducer(logOut(state), action);
default: default:
console.log(action.type);
return appReducer(state, action); return appReducer(state, action);
} }
}; };