diff --git a/app/soapbox/actions/importer/index.js b/app/soapbox/actions/importer/index.js index 7955d53e9..6db16b88d 100644 --- a/app/soapbox/actions/importer/index.js +++ b/app/soapbox/actions/importer/index.js @@ -26,8 +26,8 @@ export function importAccounts(accounts) { return { type: ACCOUNTS_IMPORT, accounts }; } -export function importStatus(status) { - return { type: STATUS_IMPORT, status }; +export function importStatus(status, idempotencyKey) { + return { type: STATUS_IMPORT, status, idempotencyKey }; } export function importStatuses(statuses) { @@ -60,8 +60,27 @@ export function importFetchedAccounts(accounts) { return importAccounts(normalAccounts); } -export function importFetchedStatus(status) { - return importFetchedStatuses([status]); +export function importFetchedStatus(status, idempotencyKey) { + return (dispatch, getState) => { + // Skip broken statuses + if (isBroken(status)) return; + + const normalOldStatus = getState().getIn(['statuses', status.id]); + const expandSpoilers = getSettings(getState()).get('expandSpoilers'); + + const normalizedStatus = normalizeStatus(status, normalOldStatus, expandSpoilers); + + dispatch(importStatus(normalizedStatus, idempotencyKey)); + dispatch(importFetchedAccount(status.account)); + + if (status.reblog && status.reblog.id) { + dispatch(importFetchedStatus(status.reblog)); + } + + if (status.poll && status.poll.id) { + dispatch(importFetchedPoll(status.poll)); + } + }; } // Sometimes Pleroma can return an empty account, diff --git a/app/soapbox/actions/statuses.js b/app/soapbox/actions/statuses.js index cdfc16d94..eadcd59f5 100644 --- a/app/soapbox/actions/statuses.js +++ b/app/soapbox/actions/statuses.js @@ -48,7 +48,7 @@ export function createStatus(params, idempotencyKey) { return api(getState).post('/api/v1/statuses', params, { headers: { 'Idempotency-Key': idempotencyKey }, }).then(({ data: status }) => { - dispatch(importFetchedStatus(status)); + dispatch(importFetchedStatus(status, idempotencyKey)); dispatch({ type: STATUS_CREATE_SUCCESS, status, params, idempotencyKey }); return status; }).catch(error => { diff --git a/app/soapbox/actions/timelines.js b/app/soapbox/actions/timelines.js index 6f93d74f0..5ef4ae733 100644 --- a/app/soapbox/actions/timelines.js +++ b/app/soapbox/actions/timelines.js @@ -29,8 +29,6 @@ export function processTimelineUpdate(timeline, status, accept) { const columnSettings = getSettings(getState()).get(timeline, ImmutableMap()); const shouldSkipQueue = shouldFilter(fromJS(status), columnSettings); - dispatch(importFetchedStatus(status)); - if (ownStatus && hasPendingStatuses) { // WebSockets push statuses without the Idempotency-Key, // so if we have pending statuses, don't import it from here. @@ -38,6 +36,8 @@ export function processTimelineUpdate(timeline, status, accept) { return; } + dispatch(importFetchedStatus(status)); + if (shouldSkipQueue) { dispatch(updateTimeline(timeline, status.id, accept)); } else { diff --git a/app/soapbox/reducers/contexts.js b/app/soapbox/reducers/contexts.js index 5c3448522..54ae70bd8 100644 --- a/app/soapbox/reducers/contexts.js +++ b/app/soapbox/reducers/contexts.js @@ -16,7 +16,8 @@ const initialState = ImmutableMap({ replies: ImmutableMap(), }); -const importStatus = (state, { id, in_reply_to_id }) => { +const importStatus = (state, status, idempotencyKey) => { + const { id, in_reply_to_id } = status; if (!in_reply_to_id) return state; return state.withMutations(state => { @@ -25,6 +26,10 @@ const importStatus = (state, { id, in_reply_to_id }) => { state.updateIn(['replies', in_reply_to_id], ImmutableOrderedSet(), ids => { return ids.add(id).sort(); }); + + if (idempotencyKey) { + deletePendingStatus(state, status, idempotencyKey); + } }); }; @@ -129,7 +134,7 @@ export default function replies(state = initialState, action) { case STATUS_CREATE_SUCCESS: return deletePendingStatus(state, action.status, action.idempotencyKey); case STATUS_IMPORT: - return importStatus(state, action.status); + return importStatus(state, action.status, action.idempotencyKey); case STATUSES_IMPORT: return importStatuses(state, action.statuses); default: