import { isFulfilled } from '@reduxjs/toolkit'; import type { Reducer } from '@reduxjs/toolkit'; import { Map as ImmutableMap } from 'immutable'; import type { ApiRelationshipJSON } from 'mastodon/api_types/relationships'; import type { Account } from 'mastodon/models/account'; import { createRelationship } from 'mastodon/models/relationship'; import type { Relationship } from 'mastodon/models/relationship'; import { submitAccountNote } from '../actions/account_notes'; import { followAccountSuccess, unfollowAccountSuccess, authorizeFollowRequestSuccess, rejectFollowRequestSuccess, followAccountRequest, followAccountFail, unfollowAccountRequest, unfollowAccountFail, blockAccountSuccess, unblockAccountSuccess, muteAccountSuccess, unmuteAccountSuccess, pinAccountSuccess, unpinAccountSuccess, fetchRelationshipsSuccess, } from '../actions/accounts_typed'; import { blockDomainSuccess, unblockDomainSuccess, } from '../actions/domain_blocks_typed'; import { notificationsUpdate } from '../actions/notifications_typed'; const initialState = ImmutableMap<string, Relationship>(); type State = typeof initialState; const normalizeRelationship = ( state: State, relationship: ApiRelationshipJSON, ) => state.set(relationship.id, createRelationship(relationship)); const normalizeRelationships = ( state: State, relationships: ApiRelationshipJSON[], ) => { relationships.forEach((relationship) => { state = normalizeRelationship(state, relationship); }); return state; }; const setDomainBlocking = ( state: State, accounts: Account[], blocking: boolean, ) => { return state.withMutations((map) => { accounts.forEach((id) => { map.setIn([id, 'domain_blocking'], blocking); }); }); }; export const relationshipsReducer: Reducer<State> = ( state = initialState, action, ) => { if (authorizeFollowRequestSuccess.match(action)) return state .setIn([action.payload.id, 'followed_by'], true) .setIn([action.payload.id, 'requested_by'], false); else if (rejectFollowRequestSuccess.match(action)) return state .setIn([action.payload.id, 'followed_by'], false) .setIn([action.payload.id, 'requested_by'], false); else if (notificationsUpdate.match(action)) return action.payload.notification.type === 'follow_request' ? state.setIn( [action.payload.notification.account.id, 'requested_by'], true, ) : state; else if (followAccountRequest.match(action)) return state.getIn([action.payload.id, 'following']) ? state : state.setIn( [ action.payload.id, action.payload.locked ? 'requested' : 'following', ], true, ); else if (followAccountFail.match(action)) return state.setIn( [action.payload.id, action.payload.locked ? 'requested' : 'following'], false, ); else if (unfollowAccountRequest.match(action)) return state.setIn([action.payload.id, 'following'], false); else if (unfollowAccountFail.match(action)) return state.setIn([action.payload.id, 'following'], true); else if ( followAccountSuccess.match(action) || unfollowAccountSuccess.match(action) || blockAccountSuccess.match(action) || unblockAccountSuccess.match(action) || muteAccountSuccess.match(action) || unmuteAccountSuccess.match(action) || pinAccountSuccess.match(action) || unpinAccountSuccess.match(action) || isFulfilled(submitAccountNote)(action) ) return normalizeRelationship(state, action.payload.relationship); else if (fetchRelationshipsSuccess.match(action)) return normalizeRelationships(state, action.payload.relationships); else if (blockDomainSuccess.match(action)) return setDomainBlocking(state, action.payload.accounts, true); else if (unblockDomainSuccess.match(action)) return setDomainBlocking(state, action.payload.accounts, false); else return state; };