bastodon/app/javascript/mastodon/reducers/relationships.ts

123 lines
3.9 KiB
TypeScript

import { Map as ImmutableMap } from 'immutable';
import { isFulfilled } from '@reduxjs/toolkit';
import type { Reducer } from 'redux';
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;
};