diff --git a/lib/reducers/draft-reducer.js b/lib/reducers/draft-reducer.js new file mode 100644 index 000000000..bf74165c9 --- /dev/null +++ b/lib/reducers/draft-reducer.js @@ -0,0 +1,91 @@ +// @flow + +import { + moveDraftActionType, + setDraftStoreDrafts, + updateDraftActionType, +} from '../actions/draft-actions'; +import { + deleteAccountActionTypes, + logOutActionTypes, +} from '../actions/user-actions'; +import type { DraftStore, DraftStoreOperation } from '../types/draft-types'; +import type { BaseAction } from '../types/redux-types'; +import { setNewSessionActionType } from '../utils/action-utils'; + +type ReduceDraftStoreResult = { + +draftStoreOperations: $ReadOnlyArray, + +draftStore: DraftStore, +}; + +function reduceDraftStore( + draftStore: DraftStore, + action: BaseAction, +): ReduceDraftStoreResult { + if ( + action.type === logOutActionTypes.success || + action.type === deleteAccountActionTypes.success || + (action.type === setNewSessionActionType && + action.payload.sessionChange.cookieInvalidated) + ) { + return { + draftStoreOperations: [{ type: 'remove_all' }], + draftStore: { drafts: {} }, + }; + } else if (action.type === updateDraftActionType) { + const { key, text } = action.payload; + + const draftStoreOperations = [ + { + type: 'update', + payload: { key, text }, + }, + ]; + return { + draftStoreOperations, + draftStore: { + ...draftStore, + drafts: { + ...draftStore.drafts, + [key]: text, + }, + }, + }; + } else if (action.type === moveDraftActionType) { + const { oldKey, newKey } = action.payload; + + const draftStoreOperations = [ + { + type: 'move', + payload: { oldKey, newKey }, + }, + ]; + + const { [oldKey]: text, ...draftsWithoutOldKey } = draftStore.drafts; + return { + draftStoreOperations, + draftStore: { + ...draftStore, + drafts: { + ...draftsWithoutOldKey, + [newKey]: text, + }, + }, + }; + } else if (action.type === setDraftStoreDrafts) { + const drafts = {}; + for (const dbDraftInfo of action.payload) { + drafts[dbDraftInfo.key] = dbDraftInfo.text; + } + return { + draftStoreOperations: [], + draftStore: { + ...draftStore, + drafts: drafts, + }, + }; + } + return { draftStore, draftStoreOperations: [] }; +} + +export { reduceDraftStore }; diff --git a/lib/reducers/master-reducer.js b/lib/reducers/master-reducer.js index f88f011fa..093670a9a 100644 --- a/lib/reducers/master-reducer.js +++ b/lib/reducers/master-reducer.js @@ -1,107 +1,115 @@ // @flow import { registerActionTypes, logInActionTypes } from '../actions/user-actions'; import type { BaseNavInfo } from '../types/nav-types'; import type { BaseAppState, BaseAction } from '../types/redux-types'; import { fullStateSyncActionType, incrementalStateSyncActionType, } from '../types/socket-types'; import type { StoreOperations } from '../types/store-ops-types'; import reduceCalendarFilters from './calendar-filters-reducer'; import reduceConnectionInfo from './connection-reducer'; import reduceDataLoaded from './data-loaded-reducer'; +import { reduceDraftStore } from './draft-reducer'; import reduceEnabledApps from './enabled-apps-reducer'; import { reduceEntryInfos } from './entry-reducer'; import reduceLifecycleState from './lifecycle-state-reducer'; import { reduceLoadingStatuses } from './loading-reducer'; import reduceNextLocalID from './local-id-reducer'; import { reduceMessageStore } from './message-reducer'; import reduceBaseNavInfo from './nav-reducer'; import reduceReportStore from './report-store-reducer'; import { reduceThreadInfos } from './thread-reducer'; import reduceUpdatesCurrentAsOf from './updates-reducer'; import reduceURLPrefix from './url-prefix-reducer'; import { reduceCurrentUserInfo, reduceUserInfos } from './user-reducer'; export default function baseReducer>( state: T, action: BaseAction, ): { state: T, storeOperations: StoreOperations } { const { threadStore, newThreadInconsistencies, threadStoreOperations, } = reduceThreadInfos(state.threadStore, action); const { threadInfos } = threadStore; const [entryStore, newEntryInconsistencies] = reduceEntryInfos( state.entryStore, action, threadInfos, ); const newInconsistencies = [ ...newEntryInconsistencies, ...newThreadInconsistencies, ]; // Only allow checkpoints to increase if we are connected // or if the action is a STATE_SYNC const { messageStoreOperations, messageStore: reducedMessageStore, } = reduceMessageStore(state.messageStore, action, threadInfos); let messageStore = reducedMessageStore; let updatesCurrentAsOf = reduceUpdatesCurrentAsOf( state.updatesCurrentAsOf, action, ); const connection = reduceConnectionInfo(state.connection, action); if ( connection.status !== 'connected' && action.type !== incrementalStateSyncActionType && action.type !== fullStateSyncActionType && action.type !== registerActionTypes.success && action.type !== logInActionTypes.success ) { if (messageStore.currentAsOf !== state.messageStore.currentAsOf) { messageStore = { ...messageStore, currentAsOf: state.messageStore.currentAsOf, }; } if (updatesCurrentAsOf !== state.updatesCurrentAsOf) { updatesCurrentAsOf = state.updatesCurrentAsOf; } } + const { draftStore, draftStoreOperations } = reduceDraftStore( + state.draftStore, + action, + ); + return { state: { ...state, navInfo: reduceBaseNavInfo(state.navInfo, action), + draftStore, entryStore, loadingStatuses: reduceLoadingStatuses(state.loadingStatuses, action), currentUserInfo: reduceCurrentUserInfo(state.currentUserInfo, action), threadStore, userStore: reduceUserInfos(state.userStore, action), messageStore, updatesCurrentAsOf, urlPrefix: reduceURLPrefix(state.urlPrefix, action), calendarFilters: reduceCalendarFilters(state.calendarFilters, action), connection, lifecycleState: reduceLifecycleState(state.lifecycleState, action), enabledApps: reduceEnabledApps(state.enabledApps, action), reportStore: reduceReportStore( state.reportStore, action, newInconsistencies, ), nextLocalID: reduceNextLocalID(state.nextLocalID, action), dataLoaded: reduceDataLoaded(state.dataLoaded, action), }, storeOperations: { + draftStoreOperations, threadStoreOperations, messageStoreOperations, }, }; } diff --git a/lib/types/store-ops-types.js b/lib/types/store-ops-types.js index 3839aeaf4..f4db0b449 100644 --- a/lib/types/store-ops-types.js +++ b/lib/types/store-ops-types.js @@ -1,8 +1,11 @@ // @flow + +import type { DraftStoreOperation } from './draft-types'; import type { MessageStoreOperation } from './message-types'; import type { ThreadStoreOperation } from './thread-types'; export type StoreOperations = { + +draftStoreOperations: $ReadOnlyArray, +threadStoreOperations: $ReadOnlyArray, +messageStoreOperations: $ReadOnlyArray, };