Forking glitch theme
This commit is contained in:
@@ -1,135 +0,0 @@
|
||||
import {
|
||||
ACCOUNT_FETCH_SUCCESS,
|
||||
FOLLOWERS_FETCH_SUCCESS,
|
||||
FOLLOWERS_EXPAND_SUCCESS,
|
||||
FOLLOWING_FETCH_SUCCESS,
|
||||
FOLLOWING_EXPAND_SUCCESS,
|
||||
FOLLOW_REQUESTS_FETCH_SUCCESS,
|
||||
FOLLOW_REQUESTS_EXPAND_SUCCESS,
|
||||
} from '../actions/accounts';
|
||||
import {
|
||||
BLOCKS_FETCH_SUCCESS,
|
||||
BLOCKS_EXPAND_SUCCESS,
|
||||
} from '../actions/blocks';
|
||||
import {
|
||||
MUTES_FETCH_SUCCESS,
|
||||
MUTES_EXPAND_SUCCESS,
|
||||
} from '../actions/mutes';
|
||||
import { COMPOSE_SUGGESTIONS_READY } from '../actions/compose';
|
||||
import {
|
||||
REBLOG_SUCCESS,
|
||||
UNREBLOG_SUCCESS,
|
||||
FAVOURITE_SUCCESS,
|
||||
UNFAVOURITE_SUCCESS,
|
||||
REBLOGS_FETCH_SUCCESS,
|
||||
FAVOURITES_FETCH_SUCCESS,
|
||||
} from '../actions/interactions';
|
||||
import {
|
||||
TIMELINE_REFRESH_SUCCESS,
|
||||
TIMELINE_UPDATE,
|
||||
TIMELINE_EXPAND_SUCCESS,
|
||||
} from '../actions/timelines';
|
||||
import {
|
||||
STATUS_FETCH_SUCCESS,
|
||||
CONTEXT_FETCH_SUCCESS,
|
||||
} from '../actions/statuses';
|
||||
import { SEARCH_FETCH_SUCCESS } from '../actions/search';
|
||||
import {
|
||||
NOTIFICATIONS_UPDATE,
|
||||
NOTIFICATIONS_REFRESH_SUCCESS,
|
||||
NOTIFICATIONS_EXPAND_SUCCESS,
|
||||
} from '../actions/notifications';
|
||||
import {
|
||||
FAVOURITED_STATUSES_FETCH_SUCCESS,
|
||||
FAVOURITED_STATUSES_EXPAND_SUCCESS,
|
||||
} from '../actions/favourites';
|
||||
import { STORE_HYDRATE } from '../actions/store';
|
||||
import emojify from '../features/emoji/emoji';
|
||||
import { Map as ImmutableMap, fromJS } from 'immutable';
|
||||
import escapeTextContentForBrowser from 'escape-html';
|
||||
|
||||
const normalizeAccount = (state, account) => {
|
||||
account = { ...account };
|
||||
|
||||
delete account.followers_count;
|
||||
delete account.following_count;
|
||||
delete account.statuses_count;
|
||||
|
||||
const displayName = account.display_name.length === 0 ? account.username : account.display_name;
|
||||
account.display_name_html = emojify(escapeTextContentForBrowser(displayName));
|
||||
account.note_emojified = emojify(account.note);
|
||||
|
||||
return state.set(account.id, fromJS(account));
|
||||
};
|
||||
|
||||
const normalizeAccounts = (state, accounts) => {
|
||||
accounts.forEach(account => {
|
||||
state = normalizeAccount(state, account);
|
||||
});
|
||||
|
||||
return state;
|
||||
};
|
||||
|
||||
const normalizeAccountFromStatus = (state, status) => {
|
||||
state = normalizeAccount(state, status.account);
|
||||
|
||||
if (status.reblog && status.reblog.account) {
|
||||
state = normalizeAccount(state, status.reblog.account);
|
||||
}
|
||||
|
||||
return state;
|
||||
};
|
||||
|
||||
const normalizeAccountsFromStatuses = (state, statuses) => {
|
||||
statuses.forEach(status => {
|
||||
state = normalizeAccountFromStatus(state, status);
|
||||
});
|
||||
|
||||
return state;
|
||||
};
|
||||
|
||||
const initialState = ImmutableMap();
|
||||
|
||||
export default function accounts(state = initialState, action) {
|
||||
switch(action.type) {
|
||||
case STORE_HYDRATE:
|
||||
return state.merge(action.state.get('accounts'));
|
||||
case ACCOUNT_FETCH_SUCCESS:
|
||||
case NOTIFICATIONS_UPDATE:
|
||||
return normalizeAccount(state, action.account);
|
||||
case FOLLOWERS_FETCH_SUCCESS:
|
||||
case FOLLOWERS_EXPAND_SUCCESS:
|
||||
case FOLLOWING_FETCH_SUCCESS:
|
||||
case FOLLOWING_EXPAND_SUCCESS:
|
||||
case REBLOGS_FETCH_SUCCESS:
|
||||
case FAVOURITES_FETCH_SUCCESS:
|
||||
case COMPOSE_SUGGESTIONS_READY:
|
||||
case FOLLOW_REQUESTS_FETCH_SUCCESS:
|
||||
case FOLLOW_REQUESTS_EXPAND_SUCCESS:
|
||||
case BLOCKS_FETCH_SUCCESS:
|
||||
case BLOCKS_EXPAND_SUCCESS:
|
||||
case MUTES_FETCH_SUCCESS:
|
||||
case MUTES_EXPAND_SUCCESS:
|
||||
return action.accounts ? normalizeAccounts(state, action.accounts) : state;
|
||||
case NOTIFICATIONS_REFRESH_SUCCESS:
|
||||
case NOTIFICATIONS_EXPAND_SUCCESS:
|
||||
case SEARCH_FETCH_SUCCESS:
|
||||
return normalizeAccountsFromStatuses(normalizeAccounts(state, action.accounts), action.statuses);
|
||||
case TIMELINE_REFRESH_SUCCESS:
|
||||
case TIMELINE_EXPAND_SUCCESS:
|
||||
case CONTEXT_FETCH_SUCCESS:
|
||||
case FAVOURITED_STATUSES_FETCH_SUCCESS:
|
||||
case FAVOURITED_STATUSES_EXPAND_SUCCESS:
|
||||
return normalizeAccountsFromStatuses(state, action.statuses);
|
||||
case REBLOG_SUCCESS:
|
||||
case FAVOURITE_SUCCESS:
|
||||
case UNREBLOG_SUCCESS:
|
||||
case UNFAVOURITE_SUCCESS:
|
||||
return normalizeAccountFromStatus(state, action.response);
|
||||
case TIMELINE_UPDATE:
|
||||
case STATUS_FETCH_SUCCESS:
|
||||
return normalizeAccountFromStatus(state, action.status);
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
};
|
@@ -1,136 +0,0 @@
|
||||
import {
|
||||
ACCOUNT_FETCH_SUCCESS,
|
||||
FOLLOWERS_FETCH_SUCCESS,
|
||||
FOLLOWERS_EXPAND_SUCCESS,
|
||||
FOLLOWING_FETCH_SUCCESS,
|
||||
FOLLOWING_EXPAND_SUCCESS,
|
||||
FOLLOW_REQUESTS_FETCH_SUCCESS,
|
||||
FOLLOW_REQUESTS_EXPAND_SUCCESS,
|
||||
ACCOUNT_FOLLOW_SUCCESS,
|
||||
ACCOUNT_UNFOLLOW_SUCCESS,
|
||||
} from '../actions/accounts';
|
||||
import {
|
||||
BLOCKS_FETCH_SUCCESS,
|
||||
BLOCKS_EXPAND_SUCCESS,
|
||||
} from '../actions/blocks';
|
||||
import {
|
||||
MUTES_FETCH_SUCCESS,
|
||||
MUTES_EXPAND_SUCCESS,
|
||||
} from '../actions/mutes';
|
||||
import { COMPOSE_SUGGESTIONS_READY } from '../actions/compose';
|
||||
import {
|
||||
REBLOG_SUCCESS,
|
||||
UNREBLOG_SUCCESS,
|
||||
FAVOURITE_SUCCESS,
|
||||
UNFAVOURITE_SUCCESS,
|
||||
REBLOGS_FETCH_SUCCESS,
|
||||
FAVOURITES_FETCH_SUCCESS,
|
||||
} from '../actions/interactions';
|
||||
import {
|
||||
TIMELINE_REFRESH_SUCCESS,
|
||||
TIMELINE_UPDATE,
|
||||
TIMELINE_EXPAND_SUCCESS,
|
||||
} from '../actions/timelines';
|
||||
import {
|
||||
STATUS_FETCH_SUCCESS,
|
||||
CONTEXT_FETCH_SUCCESS,
|
||||
} from '../actions/statuses';
|
||||
import { SEARCH_FETCH_SUCCESS } from '../actions/search';
|
||||
import {
|
||||
NOTIFICATIONS_UPDATE,
|
||||
NOTIFICATIONS_REFRESH_SUCCESS,
|
||||
NOTIFICATIONS_EXPAND_SUCCESS,
|
||||
} from '../actions/notifications';
|
||||
import {
|
||||
FAVOURITED_STATUSES_FETCH_SUCCESS,
|
||||
FAVOURITED_STATUSES_EXPAND_SUCCESS,
|
||||
} from '../actions/favourites';
|
||||
import { STORE_HYDRATE } from '../actions/store';
|
||||
import { Map as ImmutableMap, fromJS } from 'immutable';
|
||||
|
||||
const normalizeAccount = (state, account) => state.set(account.id, fromJS({
|
||||
followers_count: account.followers_count,
|
||||
following_count: account.following_count,
|
||||
statuses_count: account.statuses_count,
|
||||
}));
|
||||
|
||||
const normalizeAccounts = (state, accounts) => {
|
||||
accounts.forEach(account => {
|
||||
state = normalizeAccount(state, account);
|
||||
});
|
||||
|
||||
return state;
|
||||
};
|
||||
|
||||
const normalizeAccountFromStatus = (state, status) => {
|
||||
state = normalizeAccount(state, status.account);
|
||||
|
||||
if (status.reblog && status.reblog.account) {
|
||||
state = normalizeAccount(state, status.reblog.account);
|
||||
}
|
||||
|
||||
return state;
|
||||
};
|
||||
|
||||
const normalizeAccountsFromStatuses = (state, statuses) => {
|
||||
statuses.forEach(status => {
|
||||
state = normalizeAccountFromStatus(state, status);
|
||||
});
|
||||
|
||||
return state;
|
||||
};
|
||||
|
||||
const initialState = ImmutableMap();
|
||||
|
||||
export default function accountsCounters(state = initialState, action) {
|
||||
switch(action.type) {
|
||||
case STORE_HYDRATE:
|
||||
return state.merge(action.state.get('accounts').map(item => fromJS({
|
||||
followers_count: item.get('followers_count'),
|
||||
following_count: item.get('following_count'),
|
||||
statuses_count: item.get('statuses_count'),
|
||||
})));
|
||||
case ACCOUNT_FETCH_SUCCESS:
|
||||
case NOTIFICATIONS_UPDATE:
|
||||
return normalizeAccount(state, action.account);
|
||||
case FOLLOWERS_FETCH_SUCCESS:
|
||||
case FOLLOWERS_EXPAND_SUCCESS:
|
||||
case FOLLOWING_FETCH_SUCCESS:
|
||||
case FOLLOWING_EXPAND_SUCCESS:
|
||||
case REBLOGS_FETCH_SUCCESS:
|
||||
case FAVOURITES_FETCH_SUCCESS:
|
||||
case COMPOSE_SUGGESTIONS_READY:
|
||||
case FOLLOW_REQUESTS_FETCH_SUCCESS:
|
||||
case FOLLOW_REQUESTS_EXPAND_SUCCESS:
|
||||
case BLOCKS_FETCH_SUCCESS:
|
||||
case BLOCKS_EXPAND_SUCCESS:
|
||||
case MUTES_FETCH_SUCCESS:
|
||||
case MUTES_EXPAND_SUCCESS:
|
||||
return action.accounts ? normalizeAccounts(state, action.accounts) : state;
|
||||
case NOTIFICATIONS_REFRESH_SUCCESS:
|
||||
case NOTIFICATIONS_EXPAND_SUCCESS:
|
||||
case SEARCH_FETCH_SUCCESS:
|
||||
return normalizeAccountsFromStatuses(normalizeAccounts(state, action.accounts), action.statuses);
|
||||
case TIMELINE_REFRESH_SUCCESS:
|
||||
case TIMELINE_EXPAND_SUCCESS:
|
||||
case CONTEXT_FETCH_SUCCESS:
|
||||
case FAVOURITED_STATUSES_FETCH_SUCCESS:
|
||||
case FAVOURITED_STATUSES_EXPAND_SUCCESS:
|
||||
return normalizeAccountsFromStatuses(state, action.statuses);
|
||||
case REBLOG_SUCCESS:
|
||||
case FAVOURITE_SUCCESS:
|
||||
case UNREBLOG_SUCCESS:
|
||||
case UNFAVOURITE_SUCCESS:
|
||||
return normalizeAccountFromStatus(state, action.response);
|
||||
case TIMELINE_UPDATE:
|
||||
case STATUS_FETCH_SUCCESS:
|
||||
return normalizeAccountFromStatus(state, action.status);
|
||||
case ACCOUNT_FOLLOW_SUCCESS:
|
||||
if (action.alreadyFollowing) { return state; }
|
||||
return state.updateIn([action.relationship.id, 'followers_count'], num => num + 1);
|
||||
case ACCOUNT_UNFOLLOW_SUCCESS:
|
||||
return state.updateIn([action.relationship.id, 'followers_count'], num => Math.max(0, num - 1));
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
};
|
@@ -1,25 +0,0 @@
|
||||
import {
|
||||
ALERT_SHOW,
|
||||
ALERT_DISMISS,
|
||||
ALERT_CLEAR,
|
||||
} from '../actions/alerts';
|
||||
import { Map as ImmutableMap, List as ImmutableList } from 'immutable';
|
||||
|
||||
const initialState = ImmutableList([]);
|
||||
|
||||
export default function alerts(state = initialState, action) {
|
||||
switch(action.type) {
|
||||
case ALERT_SHOW:
|
||||
return state.push(ImmutableMap({
|
||||
key: state.size > 0 ? state.last().get('key') + 1 : 0,
|
||||
title: action.title,
|
||||
message: action.message,
|
||||
}));
|
||||
case ALERT_DISMISS:
|
||||
return state.filterNot(item => item.get('key') === action.alert.key);
|
||||
case ALERT_CLEAR:
|
||||
return state.clear();
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
};
|
@@ -1,14 +0,0 @@
|
||||
import { STATUS_CARD_FETCH_SUCCESS } from '../actions/cards';
|
||||
|
||||
import { Map as ImmutableMap, fromJS } from 'immutable';
|
||||
|
||||
const initialState = ImmutableMap();
|
||||
|
||||
export default function cards(state = initialState, action) {
|
||||
switch(action.type) {
|
||||
case STATUS_CARD_FETCH_SUCCESS:
|
||||
return state.set(action.id, fromJS(action.card));
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
};
|
@@ -1,307 +0,0 @@
|
||||
import {
|
||||
COMPOSE_MOUNT,
|
||||
COMPOSE_UNMOUNT,
|
||||
COMPOSE_CHANGE,
|
||||
COMPOSE_REPLY,
|
||||
COMPOSE_REPLY_CANCEL,
|
||||
COMPOSE_MENTION,
|
||||
COMPOSE_SUBMIT_REQUEST,
|
||||
COMPOSE_SUBMIT_SUCCESS,
|
||||
COMPOSE_SUBMIT_FAIL,
|
||||
COMPOSE_UPLOAD_REQUEST,
|
||||
COMPOSE_UPLOAD_SUCCESS,
|
||||
COMPOSE_UPLOAD_FAIL,
|
||||
COMPOSE_UPLOAD_UNDO,
|
||||
COMPOSE_UPLOAD_PROGRESS,
|
||||
COMPOSE_SUGGESTIONS_CLEAR,
|
||||
COMPOSE_SUGGESTIONS_READY,
|
||||
COMPOSE_SUGGESTION_SELECT,
|
||||
COMPOSE_ADVANCED_OPTIONS_CHANGE,
|
||||
COMPOSE_SENSITIVITY_CHANGE,
|
||||
COMPOSE_SPOILERNESS_CHANGE,
|
||||
COMPOSE_SPOILER_TEXT_CHANGE,
|
||||
COMPOSE_VISIBILITY_CHANGE,
|
||||
COMPOSE_COMPOSING_CHANGE,
|
||||
COMPOSE_EMOJI_INSERT,
|
||||
COMPOSE_UPLOAD_CHANGE_REQUEST,
|
||||
COMPOSE_UPLOAD_CHANGE_SUCCESS,
|
||||
COMPOSE_UPLOAD_CHANGE_FAIL,
|
||||
COMPOSE_DOODLE_SET,
|
||||
COMPOSE_RESET,
|
||||
} from '../actions/compose';
|
||||
import { TIMELINE_DELETE } from '../actions/timelines';
|
||||
import { STORE_HYDRATE } from '../actions/store';
|
||||
import { Map as ImmutableMap, List as ImmutableList, OrderedSet as ImmutableOrderedSet, fromJS } from 'immutable';
|
||||
import uuid from '../uuid';
|
||||
import { me } from '../initial_state';
|
||||
|
||||
const initialState = ImmutableMap({
|
||||
mounted: false,
|
||||
advanced_options: ImmutableMap({
|
||||
do_not_federate: false,
|
||||
}),
|
||||
sensitive: false,
|
||||
spoiler: false,
|
||||
spoiler_text: '',
|
||||
privacy: null,
|
||||
text: '',
|
||||
focusDate: null,
|
||||
preselectDate: null,
|
||||
in_reply_to: null,
|
||||
is_composing: false,
|
||||
is_submitting: false,
|
||||
is_uploading: false,
|
||||
progress: 0,
|
||||
media_attachments: ImmutableList(),
|
||||
suggestion_token: null,
|
||||
suggestions: ImmutableList(),
|
||||
default_advanced_options: ImmutableMap({
|
||||
do_not_federate: false,
|
||||
}),
|
||||
default_privacy: 'public',
|
||||
default_sensitive: false,
|
||||
resetFileKey: Math.floor((Math.random() * 0x10000)),
|
||||
idempotencyKey: null,
|
||||
doodle: ImmutableMap({
|
||||
fg: 'rgb( 0, 0, 0)',
|
||||
bg: 'rgb(255, 255, 255)',
|
||||
swapped: false,
|
||||
mode: 'draw',
|
||||
size: 'normal',
|
||||
weight: 2,
|
||||
opacity: 1,
|
||||
adaptiveStroke: true,
|
||||
smoothing: false,
|
||||
}),
|
||||
});
|
||||
|
||||
function statusToTextMentions(state, status) {
|
||||
let set = ImmutableOrderedSet([]);
|
||||
|
||||
if (status.getIn(['account', 'id']) !== me) {
|
||||
set = set.add(`@${status.getIn(['account', 'acct'])} `);
|
||||
}
|
||||
|
||||
return set.union(status.get('mentions').filterNot(mention => mention.get('id') === me).map(mention => `@${mention.get('acct')} `)).join('');
|
||||
};
|
||||
|
||||
function clearAll(state) {
|
||||
return state.withMutations(map => {
|
||||
map.set('text', '');
|
||||
map.set('spoiler', false);
|
||||
map.set('spoiler_text', '');
|
||||
map.set('is_submitting', false);
|
||||
map.set('in_reply_to', null);
|
||||
map.set('advanced_options', state.get('default_advanced_options'));
|
||||
map.set('privacy', state.get('default_privacy'));
|
||||
map.set('sensitive', false);
|
||||
map.update('media_attachments', list => list.clear());
|
||||
map.set('idempotencyKey', uuid());
|
||||
});
|
||||
};
|
||||
|
||||
function appendMedia(state, media) {
|
||||
const prevSize = state.get('media_attachments').size;
|
||||
|
||||
return state.withMutations(map => {
|
||||
map.update('media_attachments', list => list.push(media));
|
||||
map.set('is_uploading', false);
|
||||
map.set('resetFileKey', Math.floor((Math.random() * 0x10000)));
|
||||
map.update('text', oldText => `${oldText.trim()} ${media.get('text_url')}`);
|
||||
map.set('focusDate', new Date());
|
||||
map.set('idempotencyKey', uuid());
|
||||
|
||||
if (prevSize === 0 && (state.get('default_sensitive') || state.get('spoiler'))) {
|
||||
map.set('sensitive', true);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
function removeMedia(state, mediaId) {
|
||||
const media = state.get('media_attachments').find(item => item.get('id') === mediaId);
|
||||
const prevSize = state.get('media_attachments').size;
|
||||
|
||||
return state.withMutations(map => {
|
||||
map.update('media_attachments', list => list.filterNot(item => item.get('id') === mediaId));
|
||||
map.update('text', text => text.replace(media.get('text_url'), '').trim());
|
||||
map.set('idempotencyKey', uuid());
|
||||
|
||||
if (prevSize === 1) {
|
||||
map.set('sensitive', false);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const insertSuggestion = (state, position, token, completion) => {
|
||||
return state.withMutations(map => {
|
||||
map.update('text', oldText => `${oldText.slice(0, position)}${completion}\u200B${oldText.slice(position + token.length)}`);
|
||||
map.set('suggestion_token', null);
|
||||
map.update('suggestions', ImmutableList(), list => list.clear());
|
||||
map.set('focusDate', new Date());
|
||||
map.set('idempotencyKey', uuid());
|
||||
});
|
||||
};
|
||||
|
||||
const insertEmoji = (state, position, emojiData) => {
|
||||
const emoji = emojiData.native;
|
||||
|
||||
return state.withMutations(map => {
|
||||
map.update('text', oldText => `${oldText.slice(0, position)}${emoji}\u200B${oldText.slice(position)}`);
|
||||
map.set('focusDate', new Date());
|
||||
map.set('idempotencyKey', uuid());
|
||||
});
|
||||
};
|
||||
|
||||
const privacyPreference = (a, b) => {
|
||||
if (a === 'direct' || b === 'direct') {
|
||||
return 'direct';
|
||||
} else if (a === 'private' || b === 'private') {
|
||||
return 'private';
|
||||
} else if (a === 'unlisted' || b === 'unlisted') {
|
||||
return 'unlisted';
|
||||
} else {
|
||||
return 'public';
|
||||
}
|
||||
};
|
||||
|
||||
const hydrate = (state, hydratedState) => {
|
||||
state = clearAll(state.merge(hydratedState));
|
||||
|
||||
if (hydratedState.has('text')) {
|
||||
state = state.set('text', hydratedState.get('text'));
|
||||
}
|
||||
|
||||
return state;
|
||||
};
|
||||
|
||||
export default function compose(state = initialState, action) {
|
||||
switch(action.type) {
|
||||
case STORE_HYDRATE:
|
||||
return hydrate(state, action.state.get('compose'));
|
||||
case COMPOSE_MOUNT:
|
||||
return state.set('mounted', true);
|
||||
case COMPOSE_UNMOUNT:
|
||||
return state
|
||||
.set('mounted', false)
|
||||
.set('is_composing', false);
|
||||
case COMPOSE_ADVANCED_OPTIONS_CHANGE:
|
||||
return state
|
||||
.set('advanced_options',
|
||||
state.get('advanced_options').set(action.option, !state.getIn(['advanced_options', action.option])))
|
||||
.set('idempotencyKey', uuid());
|
||||
case COMPOSE_SENSITIVITY_CHANGE:
|
||||
return state.withMutations(map => {
|
||||
if (!state.get('spoiler')) {
|
||||
map.set('sensitive', !state.get('sensitive'));
|
||||
}
|
||||
|
||||
map.set('idempotencyKey', uuid());
|
||||
});
|
||||
case COMPOSE_SPOILERNESS_CHANGE:
|
||||
return state.withMutations(map => {
|
||||
map.set('spoiler_text', '');
|
||||
map.set('spoiler', !state.get('spoiler'));
|
||||
map.set('idempotencyKey', uuid());
|
||||
|
||||
if (!state.get('sensitive') && state.get('media_attachments').size >= 1) {
|
||||
map.set('sensitive', true);
|
||||
}
|
||||
});
|
||||
case COMPOSE_SPOILER_TEXT_CHANGE:
|
||||
return state
|
||||
.set('spoiler_text', action.text)
|
||||
.set('idempotencyKey', uuid());
|
||||
case COMPOSE_VISIBILITY_CHANGE:
|
||||
return state
|
||||
.set('privacy', action.value)
|
||||
.set('idempotencyKey', uuid());
|
||||
case COMPOSE_CHANGE:
|
||||
return state
|
||||
.set('text', action.text)
|
||||
.set('idempotencyKey', uuid());
|
||||
case COMPOSE_COMPOSING_CHANGE:
|
||||
return state.set('is_composing', action.value);
|
||||
case COMPOSE_REPLY:
|
||||
return state.withMutations(map => {
|
||||
map.set('in_reply_to', action.status.get('id'));
|
||||
map.set('text', statusToTextMentions(state, action.status));
|
||||
map.set('privacy', privacyPreference(action.status.get('visibility'), state.get('default_privacy')));
|
||||
map.set('advanced_options', new ImmutableMap({
|
||||
do_not_federate: /👁\ufe0f?<\/p>$/.test(action.status.get('content')),
|
||||
}));
|
||||
map.set('focusDate', new Date());
|
||||
map.set('preselectDate', new Date());
|
||||
map.set('idempotencyKey', uuid());
|
||||
|
||||
if (action.status.get('spoiler_text').length > 0) {
|
||||
map.set('spoiler', true);
|
||||
map.set('spoiler_text', action.status.get('spoiler_text'));
|
||||
} else {
|
||||
map.set('spoiler', false);
|
||||
map.set('spoiler_text', '');
|
||||
}
|
||||
});
|
||||
case COMPOSE_REPLY_CANCEL:
|
||||
case COMPOSE_RESET:
|
||||
return state.withMutations(map => {
|
||||
map.set('in_reply_to', null);
|
||||
map.set('text', '');
|
||||
map.set('spoiler', false);
|
||||
map.set('spoiler_text', '');
|
||||
map.set('privacy', state.get('default_privacy'));
|
||||
map.set('advanced_options', state.get('default_advanced_options'));
|
||||
map.set('idempotencyKey', uuid());
|
||||
});
|
||||
case COMPOSE_SUBMIT_REQUEST:
|
||||
case COMPOSE_UPLOAD_CHANGE_REQUEST:
|
||||
return state.set('is_submitting', true);
|
||||
case COMPOSE_SUBMIT_SUCCESS:
|
||||
return clearAll(state);
|
||||
case COMPOSE_SUBMIT_FAIL:
|
||||
case COMPOSE_UPLOAD_CHANGE_FAIL:
|
||||
return state.set('is_submitting', false);
|
||||
case COMPOSE_UPLOAD_REQUEST:
|
||||
return state.set('is_uploading', true);
|
||||
case COMPOSE_UPLOAD_SUCCESS:
|
||||
return appendMedia(state, fromJS(action.media));
|
||||
case COMPOSE_UPLOAD_FAIL:
|
||||
return state.set('is_uploading', false);
|
||||
case COMPOSE_UPLOAD_UNDO:
|
||||
return removeMedia(state, action.media_id);
|
||||
case COMPOSE_UPLOAD_PROGRESS:
|
||||
return state.set('progress', Math.round((action.loaded / action.total) * 100));
|
||||
case COMPOSE_MENTION:
|
||||
return state
|
||||
.update('text', text => `${text}@${action.account.get('acct')} `)
|
||||
.set('focusDate', new Date())
|
||||
.set('idempotencyKey', uuid());
|
||||
case COMPOSE_SUGGESTIONS_CLEAR:
|
||||
return state.update('suggestions', ImmutableList(), list => list.clear()).set('suggestion_token', null);
|
||||
case COMPOSE_SUGGESTIONS_READY:
|
||||
return state.set('suggestions', ImmutableList(action.accounts ? action.accounts.map(item => item.id) : action.emojis)).set('suggestion_token', action.token);
|
||||
case COMPOSE_SUGGESTION_SELECT:
|
||||
return insertSuggestion(state, action.position, action.token, action.completion);
|
||||
case TIMELINE_DELETE:
|
||||
if (action.id === state.get('in_reply_to')) {
|
||||
return state.set('in_reply_to', null);
|
||||
} else {
|
||||
return state;
|
||||
}
|
||||
case COMPOSE_EMOJI_INSERT:
|
||||
return insertEmoji(state, action.position, action.emoji);
|
||||
case COMPOSE_UPLOAD_CHANGE_SUCCESS:
|
||||
return state
|
||||
.set('is_submitting', false)
|
||||
.update('media_attachments', list => list.map(item => {
|
||||
if (item.get('id') === action.media.id) {
|
||||
return item.set('description', action.media.description);
|
||||
}
|
||||
|
||||
return item;
|
||||
}));
|
||||
case COMPOSE_DOODLE_SET:
|
||||
return state.mergeIn(['doodle'], action.options);
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
};
|
@@ -1,61 +0,0 @@
|
||||
import { CONTEXT_FETCH_SUCCESS } from '../actions/statuses';
|
||||
import { TIMELINE_DELETE, TIMELINE_CONTEXT_UPDATE } from '../actions/timelines';
|
||||
import { Map as ImmutableMap, List as ImmutableList } from 'immutable';
|
||||
|
||||
const initialState = ImmutableMap({
|
||||
ancestors: ImmutableMap(),
|
||||
descendants: ImmutableMap(),
|
||||
});
|
||||
|
||||
const normalizeContext = (state, id, ancestors, descendants) => {
|
||||
const ancestorsIds = ImmutableList(ancestors.map(ancestor => ancestor.id));
|
||||
const descendantsIds = ImmutableList(descendants.map(descendant => descendant.id));
|
||||
|
||||
return state.withMutations(map => {
|
||||
map.setIn(['ancestors', id], ancestorsIds);
|
||||
map.setIn(['descendants', id], descendantsIds);
|
||||
});
|
||||
};
|
||||
|
||||
const deleteFromContexts = (state, id) => {
|
||||
state.getIn(['descendants', id], ImmutableList()).forEach(descendantId => {
|
||||
state = state.updateIn(['ancestors', descendantId], ImmutableList(), list => list.filterNot(itemId => itemId === id));
|
||||
});
|
||||
|
||||
state.getIn(['ancestors', id], ImmutableList()).forEach(ancestorId => {
|
||||
state = state.updateIn(['descendants', ancestorId], ImmutableList(), list => list.filterNot(itemId => itemId === id));
|
||||
});
|
||||
|
||||
state = state.deleteIn(['descendants', id]).deleteIn(['ancestors', id]);
|
||||
|
||||
return state;
|
||||
};
|
||||
|
||||
const updateContext = (state, status, references) => {
|
||||
return state.update('descendants', map => {
|
||||
references.forEach(parentId => {
|
||||
map = map.update(parentId, ImmutableList(), list => {
|
||||
if (list.includes(status.id)) {
|
||||
return list;
|
||||
}
|
||||
|
||||
return list.push(status.id);
|
||||
});
|
||||
});
|
||||
|
||||
return map;
|
||||
});
|
||||
};
|
||||
|
||||
export default function contexts(state = initialState, action) {
|
||||
switch(action.type) {
|
||||
case CONTEXT_FETCH_SUCCESS:
|
||||
return normalizeContext(state, action.id, action.ancestors, action.descendants);
|
||||
case TIMELINE_DELETE:
|
||||
return deleteFromContexts(state, action.id);
|
||||
case TIMELINE_CONTEXT_UPDATE:
|
||||
return updateContext(state, action.status, action.references);
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
};
|
@@ -1,16 +0,0 @@
|
||||
import { List as ImmutableList } from 'immutable';
|
||||
import { STORE_HYDRATE } from '../actions/store';
|
||||
import { search as emojiSearch } from '../features/emoji/emoji_mart_search_light';
|
||||
import { buildCustomEmojis } from '../features/emoji/emoji';
|
||||
|
||||
const initialState = ImmutableList();
|
||||
|
||||
export default function custom_emojis(state = initialState, action) {
|
||||
switch(action.type) {
|
||||
case STORE_HYDRATE:
|
||||
emojiSearch('', { custom: buildCustomEmojis(action.state.get('custom_emojis', [])) });
|
||||
return action.state.get('custom_emojis');
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
};
|
@@ -1,23 +0,0 @@
|
||||
import { Map as ImmutableMap } from 'immutable';
|
||||
import { HEIGHT_CACHE_SET, HEIGHT_CACHE_CLEAR } from '../actions/height_cache';
|
||||
|
||||
const initialState = ImmutableMap();
|
||||
|
||||
const setHeight = (state, key, id, height) => {
|
||||
return state.update(key, ImmutableMap(), map => map.set(id, height));
|
||||
};
|
||||
|
||||
const clearHeights = () => {
|
||||
return ImmutableMap();
|
||||
};
|
||||
|
||||
export default function statuses(state = initialState, action) {
|
||||
switch(action.type) {
|
||||
case HEIGHT_CACHE_SET:
|
||||
return setHeight(state, action.key, action.id, action.height);
|
||||
case HEIGHT_CACHE_CLEAR:
|
||||
return clearHeights();
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
};
|
@@ -1,54 +0,0 @@
|
||||
import { combineReducers } from 'redux-immutable';
|
||||
import timelines from './timelines';
|
||||
import meta from './meta';
|
||||
import alerts from './alerts';
|
||||
import { loadingBarReducer } from 'react-redux-loading-bar';
|
||||
import modal from './modal';
|
||||
import user_lists from './user_lists';
|
||||
import accounts from './accounts';
|
||||
import accounts_counters from './accounts_counters';
|
||||
import statuses from './statuses';
|
||||
import relationships from './relationships';
|
||||
import settings from './settings';
|
||||
import local_settings from '../../glitch/reducers/local_settings';
|
||||
import push_notifications from './push_notifications';
|
||||
import status_lists from './status_lists';
|
||||
import cards from './cards';
|
||||
import mutes from './mutes';
|
||||
import reports from './reports';
|
||||
import contexts from './contexts';
|
||||
import compose from './compose';
|
||||
import search from './search';
|
||||
import media_attachments from './media_attachments';
|
||||
import notifications from './notifications';
|
||||
import height_cache from './height_cache';
|
||||
import custom_emojis from './custom_emojis';
|
||||
|
||||
const reducers = {
|
||||
timelines,
|
||||
meta,
|
||||
alerts,
|
||||
loadingBar: loadingBarReducer,
|
||||
modal,
|
||||
user_lists,
|
||||
status_lists,
|
||||
accounts,
|
||||
accounts_counters,
|
||||
statuses,
|
||||
relationships,
|
||||
settings,
|
||||
local_settings,
|
||||
push_notifications,
|
||||
cards,
|
||||
mutes,
|
||||
reports,
|
||||
contexts,
|
||||
compose,
|
||||
search,
|
||||
media_attachments,
|
||||
notifications,
|
||||
height_cache,
|
||||
custom_emojis,
|
||||
};
|
||||
|
||||
export default combineReducers(reducers);
|
@@ -1,15 +0,0 @@
|
||||
import { STORE_HYDRATE } from '../actions/store';
|
||||
import { Map as ImmutableMap } from 'immutable';
|
||||
|
||||
const initialState = ImmutableMap({
|
||||
accept_content_types: [],
|
||||
});
|
||||
|
||||
export default function meta(state = initialState, action) {
|
||||
switch(action.type) {
|
||||
case STORE_HYDRATE:
|
||||
return state.merge(action.state.get('media_attachments'));
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
};
|
@@ -1,16 +0,0 @@
|
||||
import { STORE_HYDRATE } from '../actions/store';
|
||||
import { Map as ImmutableMap } from 'immutable';
|
||||
|
||||
const initialState = ImmutableMap({
|
||||
streaming_api_base_url: null,
|
||||
access_token: null,
|
||||
});
|
||||
|
||||
export default function meta(state = initialState, action) {
|
||||
switch(action.type) {
|
||||
case STORE_HYDRATE:
|
||||
return state.merge(action.state.get('meta'));
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
};
|
@@ -1,17 +0,0 @@
|
||||
import { MODAL_OPEN, MODAL_CLOSE } from '../actions/modal';
|
||||
|
||||
const initialState = {
|
||||
modalType: null,
|
||||
modalProps: {},
|
||||
};
|
||||
|
||||
export default function modal(state = initialState, action) {
|
||||
switch(action.type) {
|
||||
case MODAL_OPEN:
|
||||
return { modalType: action.modalType, modalProps: action.modalProps };
|
||||
case MODAL_CLOSE:
|
||||
return initialState;
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
};
|
@@ -1,29 +0,0 @@
|
||||
import Immutable from 'immutable';
|
||||
|
||||
import {
|
||||
MUTES_INIT_MODAL,
|
||||
MUTES_TOGGLE_HIDE_NOTIFICATIONS,
|
||||
} from '../actions/mutes';
|
||||
|
||||
const initialState = Immutable.Map({
|
||||
new: Immutable.Map({
|
||||
isSubmitting: false,
|
||||
account: null,
|
||||
notifications: true,
|
||||
}),
|
||||
});
|
||||
|
||||
export default function mutes(state = initialState, action) {
|
||||
switch (action.type) {
|
||||
case MUTES_INIT_MODAL:
|
||||
return state.withMutations((state) => {
|
||||
state.setIn(['new', 'isSubmitting'], false);
|
||||
state.setIn(['new', 'account'], action.account);
|
||||
state.setIn(['new', 'notifications'], true);
|
||||
});
|
||||
case MUTES_TOGGLE_HIDE_NOTIFICATIONS:
|
||||
return state.updateIn(['new', 'notifications'], (old) => !old);
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
}
|
@@ -1,191 +0,0 @@
|
||||
import {
|
||||
NOTIFICATIONS_UPDATE,
|
||||
NOTIFICATIONS_REFRESH_SUCCESS,
|
||||
NOTIFICATIONS_EXPAND_SUCCESS,
|
||||
NOTIFICATIONS_REFRESH_REQUEST,
|
||||
NOTIFICATIONS_EXPAND_REQUEST,
|
||||
NOTIFICATIONS_REFRESH_FAIL,
|
||||
NOTIFICATIONS_EXPAND_FAIL,
|
||||
NOTIFICATIONS_CLEAR,
|
||||
NOTIFICATIONS_SCROLL_TOP,
|
||||
NOTIFICATIONS_DELETE_MARKED_REQUEST,
|
||||
NOTIFICATIONS_DELETE_MARKED_SUCCESS,
|
||||
NOTIFICATION_MARK_FOR_DELETE,
|
||||
NOTIFICATIONS_DELETE_MARKED_FAIL,
|
||||
NOTIFICATIONS_ENTER_CLEARING_MODE,
|
||||
NOTIFICATIONS_MARK_ALL_FOR_DELETE,
|
||||
} from '../actions/notifications';
|
||||
import {
|
||||
ACCOUNT_BLOCK_SUCCESS,
|
||||
ACCOUNT_MUTE_SUCCESS,
|
||||
} from '../actions/accounts';
|
||||
import { TIMELINE_DELETE } from '../actions/timelines';
|
||||
import { Map as ImmutableMap, List as ImmutableList } from 'immutable';
|
||||
|
||||
const initialState = ImmutableMap({
|
||||
items: ImmutableList(),
|
||||
next: null,
|
||||
top: true,
|
||||
unread: 0,
|
||||
loaded: false,
|
||||
isLoading: true,
|
||||
cleaningMode: false,
|
||||
// notification removal mark of new notifs loaded whilst cleaningMode is true.
|
||||
markNewForDelete: false,
|
||||
});
|
||||
|
||||
const notificationToMap = (state, notification) => ImmutableMap({
|
||||
id: notification.id,
|
||||
type: notification.type,
|
||||
account: notification.account.id,
|
||||
markedForDelete: state.get('markNewForDelete'),
|
||||
status: notification.status ? notification.status.id : null,
|
||||
});
|
||||
|
||||
const normalizeNotification = (state, notification) => {
|
||||
const top = state.get('top');
|
||||
|
||||
if (!top) {
|
||||
state = state.update('unread', unread => unread + 1);
|
||||
}
|
||||
|
||||
return state.update('items', list => {
|
||||
if (top && list.size > 40) {
|
||||
list = list.take(20);
|
||||
}
|
||||
|
||||
return list.unshift(notificationToMap(state, notification));
|
||||
});
|
||||
};
|
||||
|
||||
const normalizeNotifications = (state, notifications, next) => {
|
||||
let items = ImmutableList();
|
||||
const loaded = state.get('loaded');
|
||||
|
||||
notifications.forEach((n, i) => {
|
||||
items = items.set(i, notificationToMap(state, n));
|
||||
});
|
||||
|
||||
if (state.get('next') === null) {
|
||||
state = state.set('next', next);
|
||||
}
|
||||
|
||||
return state
|
||||
.update('items', list => loaded ? items.concat(list) : list.concat(items))
|
||||
.set('loaded', true)
|
||||
.set('isLoading', false);
|
||||
};
|
||||
|
||||
const appendNormalizedNotifications = (state, notifications, next) => {
|
||||
let items = ImmutableList();
|
||||
|
||||
notifications.forEach((n, i) => {
|
||||
items = items.set(i, notificationToMap(state, n));
|
||||
});
|
||||
|
||||
return state
|
||||
.update('items', list => list.concat(items))
|
||||
.set('next', next)
|
||||
.set('isLoading', false);
|
||||
};
|
||||
|
||||
const filterNotifications = (state, relationship) => {
|
||||
return state.update('items', list => list.filterNot(item => item.get('account') === relationship.id));
|
||||
};
|
||||
|
||||
const updateTop = (state, top) => {
|
||||
if (top) {
|
||||
state = state.set('unread', 0);
|
||||
}
|
||||
|
||||
return state.set('top', top);
|
||||
};
|
||||
|
||||
const deleteByStatus = (state, statusId) => {
|
||||
return state.update('items', list => list.filterNot(item => item.get('status') === statusId));
|
||||
};
|
||||
|
||||
const markForDelete = (state, notificationId, yes) => {
|
||||
return state.update('items', list => list.map(item => {
|
||||
if(item.get('id') === notificationId) {
|
||||
return item.set('markedForDelete', yes);
|
||||
} else {
|
||||
return item;
|
||||
}
|
||||
}));
|
||||
};
|
||||
|
||||
const markAllForDelete = (state, yes) => {
|
||||
return state.update('items', list => list.map(item => {
|
||||
if(yes !== null) {
|
||||
return item.set('markedForDelete', yes);
|
||||
} else {
|
||||
return item.set('markedForDelete', !item.get('markedForDelete'));
|
||||
}
|
||||
}));
|
||||
};
|
||||
|
||||
const unmarkAllForDelete = (state) => {
|
||||
return state.update('items', list => list.map(item => item.set('markedForDelete', false)));
|
||||
};
|
||||
|
||||
const deleteMarkedNotifs = (state) => {
|
||||
return state.update('items', list => list.filterNot(item => item.get('markedForDelete')));
|
||||
};
|
||||
|
||||
export default function notifications(state = initialState, action) {
|
||||
let st;
|
||||
|
||||
switch(action.type) {
|
||||
case NOTIFICATIONS_REFRESH_REQUEST:
|
||||
case NOTIFICATIONS_EXPAND_REQUEST:
|
||||
case NOTIFICATIONS_DELETE_MARKED_REQUEST:
|
||||
return state.set('isLoading', true);
|
||||
case NOTIFICATIONS_DELETE_MARKED_FAIL:
|
||||
case NOTIFICATIONS_REFRESH_FAIL:
|
||||
case NOTIFICATIONS_EXPAND_FAIL:
|
||||
return state.set('isLoading', false);
|
||||
case NOTIFICATIONS_SCROLL_TOP:
|
||||
return updateTop(state, action.top);
|
||||
case NOTIFICATIONS_UPDATE:
|
||||
return normalizeNotification(state, action.notification);
|
||||
case NOTIFICATIONS_REFRESH_SUCCESS:
|
||||
return normalizeNotifications(state, action.notifications, action.next);
|
||||
case NOTIFICATIONS_EXPAND_SUCCESS:
|
||||
return appendNormalizedNotifications(state, action.notifications, action.next);
|
||||
case ACCOUNT_BLOCK_SUCCESS:
|
||||
case ACCOUNT_MUTE_SUCCESS:
|
||||
return filterNotifications(state, action.relationship);
|
||||
case NOTIFICATIONS_CLEAR:
|
||||
return state.set('items', ImmutableList()).set('next', null);
|
||||
case TIMELINE_DELETE:
|
||||
return deleteByStatus(state, action.id);
|
||||
|
||||
case NOTIFICATION_MARK_FOR_DELETE:
|
||||
return markForDelete(state, action.id, action.yes);
|
||||
|
||||
case NOTIFICATIONS_DELETE_MARKED_SUCCESS:
|
||||
return deleteMarkedNotifs(state).set('isLoading', false);
|
||||
|
||||
case NOTIFICATIONS_ENTER_CLEARING_MODE:
|
||||
st = state.set('cleaningMode', action.yes);
|
||||
if (!action.yes) {
|
||||
return unmarkAllForDelete(st).set('markNewForDelete', false);
|
||||
} else {
|
||||
return st;
|
||||
}
|
||||
|
||||
case NOTIFICATIONS_MARK_ALL_FOR_DELETE:
|
||||
st = state;
|
||||
if (action.yes === null) {
|
||||
// Toggle - this is a bit confusing, as it toggles the all-none mode
|
||||
//st = st.set('markNewForDelete', !st.get('markNewForDelete'));
|
||||
} else {
|
||||
st = st.set('markNewForDelete', action.yes);
|
||||
}
|
||||
return markAllForDelete(st, action.yes);
|
||||
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
};
|
@@ -1,51 +0,0 @@
|
||||
import { STORE_HYDRATE } from '../actions/store';
|
||||
import { SET_BROWSER_SUPPORT, SET_SUBSCRIPTION, CLEAR_SUBSCRIPTION, ALERTS_CHANGE } from '../actions/push_notifications';
|
||||
import Immutable from 'immutable';
|
||||
|
||||
const initialState = Immutable.Map({
|
||||
subscription: null,
|
||||
alerts: new Immutable.Map({
|
||||
follow: false,
|
||||
favourite: false,
|
||||
reblog: false,
|
||||
mention: false,
|
||||
}),
|
||||
isSubscribed: false,
|
||||
browserSupport: false,
|
||||
});
|
||||
|
||||
export default function push_subscriptions(state = initialState, action) {
|
||||
switch(action.type) {
|
||||
case STORE_HYDRATE: {
|
||||
const push_subscription = action.state.get('push_subscription');
|
||||
|
||||
if (push_subscription) {
|
||||
return state
|
||||
.set('subscription', new Immutable.Map({
|
||||
id: push_subscription.get('id'),
|
||||
endpoint: push_subscription.get('endpoint'),
|
||||
}))
|
||||
.set('alerts', push_subscription.get('alerts') || initialState.get('alerts'))
|
||||
.set('isSubscribed', true);
|
||||
}
|
||||
|
||||
return state;
|
||||
}
|
||||
case SET_SUBSCRIPTION:
|
||||
return state
|
||||
.set('subscription', new Immutable.Map({
|
||||
id: action.subscription.id,
|
||||
endpoint: action.subscription.endpoint,
|
||||
}))
|
||||
.set('alerts', new Immutable.Map(action.subscription.alerts))
|
||||
.set('isSubscribed', true);
|
||||
case SET_BROWSER_SUPPORT:
|
||||
return state.set('browserSupport', action.value);
|
||||
case CLEAR_SUBSCRIPTION:
|
||||
return initialState;
|
||||
case ALERTS_CHANGE:
|
||||
return state.setIn(action.key, action.value);
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
};
|
@@ -1,46 +0,0 @@
|
||||
import {
|
||||
ACCOUNT_FOLLOW_SUCCESS,
|
||||
ACCOUNT_UNFOLLOW_SUCCESS,
|
||||
ACCOUNT_BLOCK_SUCCESS,
|
||||
ACCOUNT_UNBLOCK_SUCCESS,
|
||||
ACCOUNT_MUTE_SUCCESS,
|
||||
ACCOUNT_UNMUTE_SUCCESS,
|
||||
RELATIONSHIPS_FETCH_SUCCESS,
|
||||
} from '../actions/accounts';
|
||||
import {
|
||||
DOMAIN_BLOCK_SUCCESS,
|
||||
DOMAIN_UNBLOCK_SUCCESS,
|
||||
} from '../actions/domain_blocks';
|
||||
import { Map as ImmutableMap, fromJS } from 'immutable';
|
||||
|
||||
const normalizeRelationship = (state, relationship) => state.set(relationship.id, fromJS(relationship));
|
||||
|
||||
const normalizeRelationships = (state, relationships) => {
|
||||
relationships.forEach(relationship => {
|
||||
state = normalizeRelationship(state, relationship);
|
||||
});
|
||||
|
||||
return state;
|
||||
};
|
||||
|
||||
const initialState = ImmutableMap();
|
||||
|
||||
export default function relationships(state = initialState, action) {
|
||||
switch(action.type) {
|
||||
case ACCOUNT_FOLLOW_SUCCESS:
|
||||
case ACCOUNT_UNFOLLOW_SUCCESS:
|
||||
case ACCOUNT_BLOCK_SUCCESS:
|
||||
case ACCOUNT_UNBLOCK_SUCCESS:
|
||||
case ACCOUNT_MUTE_SUCCESS:
|
||||
case ACCOUNT_UNMUTE_SUCCESS:
|
||||
return normalizeRelationship(state, action.relationship);
|
||||
case RELATIONSHIPS_FETCH_SUCCESS:
|
||||
return normalizeRelationships(state, action.relationships);
|
||||
case DOMAIN_BLOCK_SUCCESS:
|
||||
return state.setIn([action.accountId, 'domain_blocking'], true);
|
||||
case DOMAIN_UNBLOCK_SUCCESS:
|
||||
return state.setIn([action.accountId, 'domain_blocking'], false);
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
};
|
@@ -1,60 +0,0 @@
|
||||
import {
|
||||
REPORT_INIT,
|
||||
REPORT_SUBMIT_REQUEST,
|
||||
REPORT_SUBMIT_SUCCESS,
|
||||
REPORT_SUBMIT_FAIL,
|
||||
REPORT_CANCEL,
|
||||
REPORT_STATUS_TOGGLE,
|
||||
REPORT_COMMENT_CHANGE,
|
||||
} from '../actions/reports';
|
||||
import { Map as ImmutableMap, Set as ImmutableSet } from 'immutable';
|
||||
|
||||
const initialState = ImmutableMap({
|
||||
new: ImmutableMap({
|
||||
isSubmitting: false,
|
||||
account_id: null,
|
||||
status_ids: ImmutableSet(),
|
||||
comment: '',
|
||||
}),
|
||||
});
|
||||
|
||||
export default function reports(state = initialState, action) {
|
||||
switch(action.type) {
|
||||
case REPORT_INIT:
|
||||
return state.withMutations(map => {
|
||||
map.setIn(['new', 'isSubmitting'], false);
|
||||
map.setIn(['new', 'account_id'], action.account.get('id'));
|
||||
|
||||
if (state.getIn(['new', 'account_id']) !== action.account.get('id')) {
|
||||
map.setIn(['new', 'status_ids'], action.status ? ImmutableSet([action.status.getIn(['reblog', 'id'], action.status.get('id'))]) : ImmutableSet());
|
||||
map.setIn(['new', 'comment'], '');
|
||||
} else if (action.status) {
|
||||
map.updateIn(['new', 'status_ids'], ImmutableSet(), set => set.add(action.status.getIn(['reblog', 'id'], action.status.get('id'))));
|
||||
}
|
||||
});
|
||||
case REPORT_STATUS_TOGGLE:
|
||||
return state.updateIn(['new', 'status_ids'], ImmutableSet(), set => {
|
||||
if (action.checked) {
|
||||
return set.add(action.statusId);
|
||||
}
|
||||
|
||||
return set.remove(action.statusId);
|
||||
});
|
||||
case REPORT_COMMENT_CHANGE:
|
||||
return state.setIn(['new', 'comment'], action.comment);
|
||||
case REPORT_SUBMIT_REQUEST:
|
||||
return state.setIn(['new', 'isSubmitting'], true);
|
||||
case REPORT_SUBMIT_FAIL:
|
||||
return state.setIn(['new', 'isSubmitting'], false);
|
||||
case REPORT_CANCEL:
|
||||
case REPORT_SUBMIT_SUCCESS:
|
||||
return state.withMutations(map => {
|
||||
map.setIn(['new', 'account_id'], null);
|
||||
map.setIn(['new', 'status_ids'], ImmutableSet());
|
||||
map.setIn(['new', 'comment'], '');
|
||||
map.setIn(['new', 'isSubmitting'], false);
|
||||
});
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
};
|
@@ -1,42 +0,0 @@
|
||||
import {
|
||||
SEARCH_CHANGE,
|
||||
SEARCH_CLEAR,
|
||||
SEARCH_FETCH_SUCCESS,
|
||||
SEARCH_SHOW,
|
||||
} from '../actions/search';
|
||||
import { COMPOSE_MENTION, COMPOSE_REPLY } from '../actions/compose';
|
||||
import { Map as ImmutableMap, List as ImmutableList } from 'immutable';
|
||||
|
||||
const initialState = ImmutableMap({
|
||||
value: '',
|
||||
submitted: false,
|
||||
hidden: false,
|
||||
results: ImmutableMap(),
|
||||
});
|
||||
|
||||
export default function search(state = initialState, action) {
|
||||
switch(action.type) {
|
||||
case SEARCH_CHANGE:
|
||||
return state.set('value', action.value);
|
||||
case SEARCH_CLEAR:
|
||||
return state.withMutations(map => {
|
||||
map.set('value', '');
|
||||
map.set('results', ImmutableMap());
|
||||
map.set('submitted', false);
|
||||
map.set('hidden', false);
|
||||
});
|
||||
case SEARCH_SHOW:
|
||||
return state.set('hidden', false);
|
||||
case COMPOSE_REPLY:
|
||||
case COMPOSE_MENTION:
|
||||
return state.set('hidden', true);
|
||||
case SEARCH_FETCH_SUCCESS:
|
||||
return state.set('results', ImmutableMap({
|
||||
accounts: ImmutableList(action.results.accounts.map(item => item.id)),
|
||||
statuses: ImmutableList(action.results.statuses.map(item => item.id)),
|
||||
hashtags: ImmutableList(action.results.hashtags),
|
||||
})).set('submitted', true);
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
};
|
@@ -1,119 +0,0 @@
|
||||
import { SETTING_CHANGE, SETTING_SAVE } from '../actions/settings';
|
||||
import { COLUMN_ADD, COLUMN_REMOVE, COLUMN_MOVE } from '../actions/columns';
|
||||
import { STORE_HYDRATE } from '../actions/store';
|
||||
import { EMOJI_USE } from '../actions/emojis';
|
||||
import { Map as ImmutableMap, fromJS } from 'immutable';
|
||||
import uuid from '../uuid';
|
||||
|
||||
const initialState = ImmutableMap({
|
||||
saved: true,
|
||||
|
||||
onboarded: false,
|
||||
layout: 'auto',
|
||||
|
||||
skinTone: 1,
|
||||
|
||||
home: ImmutableMap({
|
||||
shows: ImmutableMap({
|
||||
reblog: true,
|
||||
reply: true,
|
||||
}),
|
||||
|
||||
regex: ImmutableMap({
|
||||
body: '',
|
||||
}),
|
||||
}),
|
||||
|
||||
notifications: ImmutableMap({
|
||||
alerts: ImmutableMap({
|
||||
follow: true,
|
||||
favourite: true,
|
||||
reblog: true,
|
||||
mention: true,
|
||||
}),
|
||||
|
||||
shows: ImmutableMap({
|
||||
follow: true,
|
||||
favourite: true,
|
||||
reblog: true,
|
||||
mention: true,
|
||||
}),
|
||||
|
||||
sounds: ImmutableMap({
|
||||
follow: true,
|
||||
favourite: true,
|
||||
reblog: true,
|
||||
mention: true,
|
||||
}),
|
||||
}),
|
||||
|
||||
community: ImmutableMap({
|
||||
regex: ImmutableMap({
|
||||
body: '',
|
||||
}),
|
||||
}),
|
||||
|
||||
public: ImmutableMap({
|
||||
regex: ImmutableMap({
|
||||
body: '',
|
||||
}),
|
||||
}),
|
||||
|
||||
direct: ImmutableMap({
|
||||
regex: ImmutableMap({
|
||||
body: '',
|
||||
}),
|
||||
}),
|
||||
});
|
||||
|
||||
const defaultColumns = fromJS([
|
||||
{ id: 'COMPOSE', uuid: uuid(), params: {} },
|
||||
{ id: 'HOME', uuid: uuid(), params: {} },
|
||||
{ id: 'NOTIFICATIONS', uuid: uuid(), params: {} },
|
||||
]);
|
||||
|
||||
const hydrate = (state, settings) => state.mergeDeep(settings).update('columns', (val = defaultColumns) => val);
|
||||
|
||||
const moveColumn = (state, uuid, direction) => {
|
||||
const columns = state.get('columns');
|
||||
const index = columns.findIndex(item => item.get('uuid') === uuid);
|
||||
const newIndex = index + direction;
|
||||
|
||||
let newColumns;
|
||||
|
||||
newColumns = columns.splice(index, 1);
|
||||
newColumns = newColumns.splice(newIndex, 0, columns.get(index));
|
||||
|
||||
return state
|
||||
.set('columns', newColumns)
|
||||
.set('saved', false);
|
||||
};
|
||||
|
||||
const updateFrequentEmojis = (state, emoji) => state.update('frequentlyUsedEmojis', ImmutableMap(), map => map.update(emoji.id, 0, count => count + 1)).set('saved', false);
|
||||
|
||||
export default function settings(state = initialState, action) {
|
||||
switch(action.type) {
|
||||
case STORE_HYDRATE:
|
||||
return hydrate(state, action.state.get('settings'));
|
||||
case SETTING_CHANGE:
|
||||
return state
|
||||
.setIn(action.key, action.value)
|
||||
.set('saved', false);
|
||||
case COLUMN_ADD:
|
||||
return state
|
||||
.update('columns', list => list.push(fromJS({ id: action.id, uuid: uuid(), params: action.params })))
|
||||
.set('saved', false);
|
||||
case COLUMN_REMOVE:
|
||||
return state
|
||||
.update('columns', list => list.filterNot(item => item.get('uuid') === action.uuid))
|
||||
.set('saved', false);
|
||||
case COLUMN_MOVE:
|
||||
return moveColumn(state, action.uuid, action.direction);
|
||||
case EMOJI_USE:
|
||||
return updateFrequentEmojis(state, action.emoji);
|
||||
case SETTING_SAVE:
|
||||
return state.set('saved', true);
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
};
|
@@ -1,75 +0,0 @@
|
||||
import {
|
||||
FAVOURITED_STATUSES_FETCH_SUCCESS,
|
||||
FAVOURITED_STATUSES_EXPAND_SUCCESS,
|
||||
} from '../actions/favourites';
|
||||
import {
|
||||
PINNED_STATUSES_FETCH_SUCCESS,
|
||||
} from '../actions/pin_statuses';
|
||||
import { Map as ImmutableMap, List as ImmutableList } from 'immutable';
|
||||
import {
|
||||
FAVOURITE_SUCCESS,
|
||||
UNFAVOURITE_SUCCESS,
|
||||
PIN_SUCCESS,
|
||||
UNPIN_SUCCESS,
|
||||
} from '../actions/interactions';
|
||||
|
||||
const initialState = ImmutableMap({
|
||||
favourites: ImmutableMap({
|
||||
next: null,
|
||||
loaded: false,
|
||||
items: ImmutableList(),
|
||||
}),
|
||||
pins: ImmutableMap({
|
||||
next: null,
|
||||
loaded: false,
|
||||
items: ImmutableList(),
|
||||
}),
|
||||
});
|
||||
|
||||
const normalizeList = (state, listType, statuses, next) => {
|
||||
return state.update(listType, listMap => listMap.withMutations(map => {
|
||||
map.set('next', next);
|
||||
map.set('loaded', true);
|
||||
map.set('items', ImmutableList(statuses.map(item => item.id)));
|
||||
}));
|
||||
};
|
||||
|
||||
const appendToList = (state, listType, statuses, next) => {
|
||||
return state.update(listType, listMap => listMap.withMutations(map => {
|
||||
map.set('next', next);
|
||||
map.set('items', map.get('items').concat(statuses.map(item => item.id)));
|
||||
}));
|
||||
};
|
||||
|
||||
const prependOneToList = (state, listType, status) => {
|
||||
return state.update(listType, listMap => listMap.withMutations(map => {
|
||||
map.set('items', map.get('items').unshift(status.get('id')));
|
||||
}));
|
||||
};
|
||||
|
||||
const removeOneFromList = (state, listType, status) => {
|
||||
return state.update(listType, listMap => listMap.withMutations(map => {
|
||||
map.set('items', map.get('items').filter(item => item !== status.get('id')));
|
||||
}));
|
||||
};
|
||||
|
||||
export default function statusLists(state = initialState, action) {
|
||||
switch(action.type) {
|
||||
case FAVOURITED_STATUSES_FETCH_SUCCESS:
|
||||
return normalizeList(state, 'favourites', action.statuses, action.next);
|
||||
case FAVOURITED_STATUSES_EXPAND_SUCCESS:
|
||||
return appendToList(state, 'favourites', action.statuses, action.next);
|
||||
case FAVOURITE_SUCCESS:
|
||||
return prependOneToList(state, 'favourites', action.status);
|
||||
case UNFAVOURITE_SUCCESS:
|
||||
return removeOneFromList(state, 'favourites', action.status);
|
||||
case PINNED_STATUSES_FETCH_SUCCESS:
|
||||
return normalizeList(state, 'pins', action.statuses, action.next);
|
||||
case PIN_SUCCESS:
|
||||
return prependOneToList(state, 'pins', action.status);
|
||||
case UNPIN_SUCCESS:
|
||||
return removeOneFromList(state, 'pins', action.status);
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
};
|
@@ -1,148 +0,0 @@
|
||||
import {
|
||||
REBLOG_REQUEST,
|
||||
REBLOG_SUCCESS,
|
||||
REBLOG_FAIL,
|
||||
UNREBLOG_SUCCESS,
|
||||
FAVOURITE_REQUEST,
|
||||
FAVOURITE_SUCCESS,
|
||||
FAVOURITE_FAIL,
|
||||
UNFAVOURITE_SUCCESS,
|
||||
PIN_SUCCESS,
|
||||
UNPIN_SUCCESS,
|
||||
} from '../actions/interactions';
|
||||
import {
|
||||
STATUS_FETCH_SUCCESS,
|
||||
CONTEXT_FETCH_SUCCESS,
|
||||
STATUS_MUTE_SUCCESS,
|
||||
STATUS_UNMUTE_SUCCESS,
|
||||
} from '../actions/statuses';
|
||||
import {
|
||||
TIMELINE_REFRESH_SUCCESS,
|
||||
TIMELINE_UPDATE,
|
||||
TIMELINE_DELETE,
|
||||
TIMELINE_EXPAND_SUCCESS,
|
||||
} from '../actions/timelines';
|
||||
import {
|
||||
ACCOUNT_BLOCK_SUCCESS,
|
||||
ACCOUNT_MUTE_SUCCESS,
|
||||
} from '../actions/accounts';
|
||||
import {
|
||||
NOTIFICATIONS_UPDATE,
|
||||
NOTIFICATIONS_REFRESH_SUCCESS,
|
||||
NOTIFICATIONS_EXPAND_SUCCESS,
|
||||
} from '../actions/notifications';
|
||||
import {
|
||||
FAVOURITED_STATUSES_FETCH_SUCCESS,
|
||||
FAVOURITED_STATUSES_EXPAND_SUCCESS,
|
||||
} from '../actions/favourites';
|
||||
import {
|
||||
PINNED_STATUSES_FETCH_SUCCESS,
|
||||
} from '../actions/pin_statuses';
|
||||
import { SEARCH_FETCH_SUCCESS } from '../actions/search';
|
||||
import emojify from '../features/emoji/emoji';
|
||||
import { Map as ImmutableMap, fromJS } from 'immutable';
|
||||
import escapeTextContentForBrowser from 'escape-html';
|
||||
|
||||
const domParser = new DOMParser();
|
||||
|
||||
const normalizeStatus = (state, status) => {
|
||||
if (!status) {
|
||||
return state;
|
||||
}
|
||||
|
||||
const normalStatus = { ...status };
|
||||
normalStatus.account = status.account.id;
|
||||
|
||||
if (status.reblog && status.reblog.id) {
|
||||
state = normalizeStatus(state, status.reblog);
|
||||
normalStatus.reblog = status.reblog.id;
|
||||
}
|
||||
|
||||
const searchContent = [status.spoiler_text, status.content].join('\n\n').replace(/<br \/>/g, '\n').replace(/<\/p><p>/g, '\n\n');
|
||||
|
||||
const emojiMap = normalStatus.emojis.reduce((obj, emoji) => {
|
||||
obj[`:${emoji.shortcode}:`] = emoji;
|
||||
return obj;
|
||||
}, {});
|
||||
|
||||
normalStatus.search_index = domParser.parseFromString(searchContent, 'text/html').documentElement.textContent;
|
||||
normalStatus.contentHtml = emojify(normalStatus.content, emojiMap);
|
||||
normalStatus.spoilerHtml = emojify(escapeTextContentForBrowser(normalStatus.spoiler_text || ''), emojiMap);
|
||||
|
||||
return state.update(status.id, ImmutableMap(), map => map.mergeDeep(fromJS(normalStatus)));
|
||||
};
|
||||
|
||||
const normalizeStatuses = (state, statuses) => {
|
||||
statuses.forEach(status => {
|
||||
state = normalizeStatus(state, status);
|
||||
});
|
||||
|
||||
return state;
|
||||
};
|
||||
|
||||
const deleteStatus = (state, id, references) => {
|
||||
references.forEach(ref => {
|
||||
state = deleteStatus(state, ref[0], []);
|
||||
});
|
||||
|
||||
return state.delete(id);
|
||||
};
|
||||
|
||||
const filterStatuses = (state, relationship) => {
|
||||
state.forEach(status => {
|
||||
if (status.get('account') !== relationship.id) {
|
||||
return;
|
||||
}
|
||||
|
||||
state = deleteStatus(state, status.get('id'), state.filter(item => item.get('reblog') === status.get('id')));
|
||||
});
|
||||
|
||||
return state;
|
||||
};
|
||||
|
||||
const initialState = ImmutableMap();
|
||||
|
||||
export default function statuses(state = initialState, action) {
|
||||
switch(action.type) {
|
||||
case TIMELINE_UPDATE:
|
||||
case STATUS_FETCH_SUCCESS:
|
||||
case NOTIFICATIONS_UPDATE:
|
||||
return normalizeStatus(state, action.status);
|
||||
case REBLOG_SUCCESS:
|
||||
case UNREBLOG_SUCCESS:
|
||||
case FAVOURITE_SUCCESS:
|
||||
case UNFAVOURITE_SUCCESS:
|
||||
case PIN_SUCCESS:
|
||||
case UNPIN_SUCCESS:
|
||||
return normalizeStatus(state, action.response);
|
||||
case FAVOURITE_REQUEST:
|
||||
return state.setIn([action.status.get('id'), 'favourited'], true);
|
||||
case FAVOURITE_FAIL:
|
||||
return state.setIn([action.status.get('id'), 'favourited'], false);
|
||||
case REBLOG_REQUEST:
|
||||
return state.setIn([action.status.get('id'), 'reblogged'], true);
|
||||
case REBLOG_FAIL:
|
||||
return state.setIn([action.status.get('id'), 'reblogged'], false);
|
||||
case STATUS_MUTE_SUCCESS:
|
||||
return state.setIn([action.id, 'muted'], true);
|
||||
case STATUS_UNMUTE_SUCCESS:
|
||||
return state.setIn([action.id, 'muted'], false);
|
||||
case TIMELINE_REFRESH_SUCCESS:
|
||||
case TIMELINE_EXPAND_SUCCESS:
|
||||
case CONTEXT_FETCH_SUCCESS:
|
||||
case NOTIFICATIONS_REFRESH_SUCCESS:
|
||||
case NOTIFICATIONS_EXPAND_SUCCESS:
|
||||
case FAVOURITED_STATUSES_FETCH_SUCCESS:
|
||||
case FAVOURITED_STATUSES_EXPAND_SUCCESS:
|
||||
case PINNED_STATUSES_FETCH_SUCCESS:
|
||||
case SEARCH_FETCH_SUCCESS:
|
||||
return normalizeStatuses(state, action.statuses);
|
||||
case TIMELINE_DELETE:
|
||||
return deleteStatus(state, action.id, action.references);
|
||||
case ACCOUNT_BLOCK_SUCCESS:
|
||||
case ACCOUNT_MUTE_SUCCESS:
|
||||
return filterStatuses(state, action.relationship);
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
};
|
@@ -1,149 +0,0 @@
|
||||
import {
|
||||
TIMELINE_REFRESH_REQUEST,
|
||||
TIMELINE_REFRESH_SUCCESS,
|
||||
TIMELINE_REFRESH_FAIL,
|
||||
TIMELINE_UPDATE,
|
||||
TIMELINE_DELETE,
|
||||
TIMELINE_EXPAND_SUCCESS,
|
||||
TIMELINE_EXPAND_REQUEST,
|
||||
TIMELINE_EXPAND_FAIL,
|
||||
TIMELINE_SCROLL_TOP,
|
||||
TIMELINE_CONNECT,
|
||||
TIMELINE_DISCONNECT,
|
||||
} from '../actions/timelines';
|
||||
import {
|
||||
ACCOUNT_BLOCK_SUCCESS,
|
||||
ACCOUNT_MUTE_SUCCESS,
|
||||
ACCOUNT_UNFOLLOW_SUCCESS,
|
||||
} from '../actions/accounts';
|
||||
import { Map as ImmutableMap, List as ImmutableList, fromJS } from 'immutable';
|
||||
|
||||
const initialState = ImmutableMap();
|
||||
|
||||
const initialTimeline = ImmutableMap({
|
||||
unread: 0,
|
||||
online: false,
|
||||
top: true,
|
||||
loaded: false,
|
||||
isLoading: false,
|
||||
next: false,
|
||||
items: ImmutableList(),
|
||||
});
|
||||
|
||||
const normalizeTimeline = (state, timeline, statuses, next) => {
|
||||
const oldIds = state.getIn([timeline, 'items'], ImmutableList());
|
||||
const ids = ImmutableList(statuses.map(status => status.get('id'))).filter(newId => !oldIds.includes(newId));
|
||||
const wasLoaded = state.getIn([timeline, 'loaded']);
|
||||
const hadNext = state.getIn([timeline, 'next']);
|
||||
|
||||
return state.update(timeline, initialTimeline, map => map.withMutations(mMap => {
|
||||
mMap.set('loaded', true);
|
||||
mMap.set('isLoading', false);
|
||||
if (!hadNext) mMap.set('next', next);
|
||||
mMap.set('items', wasLoaded ? ids.concat(oldIds) : ids);
|
||||
}));
|
||||
};
|
||||
|
||||
const appendNormalizedTimeline = (state, timeline, statuses, next) => {
|
||||
const oldIds = state.getIn([timeline, 'items'], ImmutableList());
|
||||
const ids = ImmutableList(statuses.map(status => status.get('id'))).filter(newId => !oldIds.includes(newId));
|
||||
|
||||
return state.update(timeline, initialTimeline, map => map.withMutations(mMap => {
|
||||
mMap.set('isLoading', false);
|
||||
mMap.set('next', next);
|
||||
mMap.set('items', oldIds.concat(ids));
|
||||
}));
|
||||
};
|
||||
|
||||
const updateTimeline = (state, timeline, status, references) => {
|
||||
const top = state.getIn([timeline, 'top']);
|
||||
const ids = state.getIn([timeline, 'items'], ImmutableList());
|
||||
const includesId = ids.includes(status.get('id'));
|
||||
const unread = state.getIn([timeline, 'unread'], 0);
|
||||
|
||||
if (includesId) {
|
||||
return state;
|
||||
}
|
||||
|
||||
let newIds = ids;
|
||||
|
||||
return state.update(timeline, initialTimeline, map => map.withMutations(mMap => {
|
||||
if (!top) mMap.set('unread', unread + 1);
|
||||
if (top && ids.size > 40) newIds = newIds.take(20);
|
||||
if (status.getIn(['reblog', 'id'], null) !== null) newIds = newIds.filterNot(item => references.includes(item));
|
||||
mMap.set('items', newIds.unshift(status.get('id')));
|
||||
}));
|
||||
};
|
||||
|
||||
const deleteStatus = (state, id, accountId, references) => {
|
||||
state.keySeq().forEach(timeline => {
|
||||
state = state.updateIn([timeline, 'items'], list => list.filterNot(item => item === id));
|
||||
});
|
||||
|
||||
// Remove reblogs of deleted status
|
||||
references.forEach(ref => {
|
||||
state = deleteStatus(state, ref[0], ref[1], []);
|
||||
});
|
||||
|
||||
return state;
|
||||
};
|
||||
|
||||
const filterTimelines = (state, relationship, statuses) => {
|
||||
let references;
|
||||
|
||||
statuses.forEach(status => {
|
||||
if (status.get('account') !== relationship.id) {
|
||||
return;
|
||||
}
|
||||
|
||||
references = statuses.filter(item => item.get('reblog') === status.get('id')).map(item => [item.get('id'), item.get('account')]);
|
||||
state = deleteStatus(state, status.get('id'), status.get('account'), references);
|
||||
});
|
||||
|
||||
return state;
|
||||
};
|
||||
|
||||
const filterTimeline = (timeline, state, relationship, statuses) =>
|
||||
state.updateIn([timeline, 'items'], ImmutableList(), list =>
|
||||
list.filterNot(statusId =>
|
||||
statuses.getIn([statusId, 'account']) === relationship.id
|
||||
));
|
||||
|
||||
const updateTop = (state, timeline, top) => {
|
||||
return state.update(timeline, initialTimeline, map => map.withMutations(mMap => {
|
||||
if (top) mMap.set('unread', 0);
|
||||
mMap.set('top', top);
|
||||
}));
|
||||
};
|
||||
|
||||
export default function timelines(state = initialState, action) {
|
||||
switch(action.type) {
|
||||
case TIMELINE_REFRESH_REQUEST:
|
||||
case TIMELINE_EXPAND_REQUEST:
|
||||
return state.update(action.timeline, initialTimeline, map => map.set('isLoading', true));
|
||||
case TIMELINE_REFRESH_FAIL:
|
||||
case TIMELINE_EXPAND_FAIL:
|
||||
return state.update(action.timeline, initialTimeline, map => map.set('isLoading', false));
|
||||
case TIMELINE_REFRESH_SUCCESS:
|
||||
return normalizeTimeline(state, action.timeline, fromJS(action.statuses), action.next);
|
||||
case TIMELINE_EXPAND_SUCCESS:
|
||||
return appendNormalizedTimeline(state, action.timeline, fromJS(action.statuses), action.next);
|
||||
case TIMELINE_UPDATE:
|
||||
return updateTimeline(state, action.timeline, fromJS(action.status), action.references);
|
||||
case TIMELINE_DELETE:
|
||||
return deleteStatus(state, action.id, action.accountId, action.references, action.reblogOf);
|
||||
case ACCOUNT_BLOCK_SUCCESS:
|
||||
case ACCOUNT_MUTE_SUCCESS:
|
||||
return filterTimelines(state, action.relationship, action.statuses);
|
||||
case ACCOUNT_UNFOLLOW_SUCCESS:
|
||||
return filterTimeline('home', state, action.relationship, action.statuses);
|
||||
case TIMELINE_SCROLL_TOP:
|
||||
return updateTop(state, action.timeline, action.top);
|
||||
case TIMELINE_CONNECT:
|
||||
return state.update(action.timeline, initialTimeline, map => map.set('online', true));
|
||||
case TIMELINE_DISCONNECT:
|
||||
return state.update(action.timeline, initialTimeline, map => map.set('online', false));
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
};
|
@@ -1,80 +0,0 @@
|
||||
import {
|
||||
FOLLOWERS_FETCH_SUCCESS,
|
||||
FOLLOWERS_EXPAND_SUCCESS,
|
||||
FOLLOWING_FETCH_SUCCESS,
|
||||
FOLLOWING_EXPAND_SUCCESS,
|
||||
FOLLOW_REQUESTS_FETCH_SUCCESS,
|
||||
FOLLOW_REQUESTS_EXPAND_SUCCESS,
|
||||
FOLLOW_REQUEST_AUTHORIZE_SUCCESS,
|
||||
FOLLOW_REQUEST_REJECT_SUCCESS,
|
||||
} from '../actions/accounts';
|
||||
import {
|
||||
REBLOGS_FETCH_SUCCESS,
|
||||
FAVOURITES_FETCH_SUCCESS,
|
||||
} from '../actions/interactions';
|
||||
import {
|
||||
BLOCKS_FETCH_SUCCESS,
|
||||
BLOCKS_EXPAND_SUCCESS,
|
||||
} from '../actions/blocks';
|
||||
import {
|
||||
MUTES_FETCH_SUCCESS,
|
||||
MUTES_EXPAND_SUCCESS,
|
||||
} from '../actions/mutes';
|
||||
import { Map as ImmutableMap, List as ImmutableList } from 'immutable';
|
||||
|
||||
const initialState = ImmutableMap({
|
||||
followers: ImmutableMap(),
|
||||
following: ImmutableMap(),
|
||||
reblogged_by: ImmutableMap(),
|
||||
favourited_by: ImmutableMap(),
|
||||
follow_requests: ImmutableMap(),
|
||||
blocks: ImmutableMap(),
|
||||
mutes: ImmutableMap(),
|
||||
});
|
||||
|
||||
const normalizeList = (state, type, id, accounts, next) => {
|
||||
return state.setIn([type, id], ImmutableMap({
|
||||
next,
|
||||
items: ImmutableList(accounts.map(item => item.id)),
|
||||
}));
|
||||
};
|
||||
|
||||
const appendToList = (state, type, id, accounts, next) => {
|
||||
return state.updateIn([type, id], map => {
|
||||
return map.set('next', next).update('items', list => list.concat(accounts.map(item => item.id)));
|
||||
});
|
||||
};
|
||||
|
||||
export default function userLists(state = initialState, action) {
|
||||
switch(action.type) {
|
||||
case FOLLOWERS_FETCH_SUCCESS:
|
||||
return normalizeList(state, 'followers', action.id, action.accounts, action.next);
|
||||
case FOLLOWERS_EXPAND_SUCCESS:
|
||||
return appendToList(state, 'followers', action.id, action.accounts, action.next);
|
||||
case FOLLOWING_FETCH_SUCCESS:
|
||||
return normalizeList(state, 'following', action.id, action.accounts, action.next);
|
||||
case FOLLOWING_EXPAND_SUCCESS:
|
||||
return appendToList(state, 'following', action.id, action.accounts, action.next);
|
||||
case REBLOGS_FETCH_SUCCESS:
|
||||
return state.setIn(['reblogged_by', action.id], ImmutableList(action.accounts.map(item => item.id)));
|
||||
case FAVOURITES_FETCH_SUCCESS:
|
||||
return state.setIn(['favourited_by', action.id], ImmutableList(action.accounts.map(item => item.id)));
|
||||
case FOLLOW_REQUESTS_FETCH_SUCCESS:
|
||||
return state.setIn(['follow_requests', 'items'], ImmutableList(action.accounts.map(item => item.id))).setIn(['follow_requests', 'next'], action.next);
|
||||
case FOLLOW_REQUESTS_EXPAND_SUCCESS:
|
||||
return state.updateIn(['follow_requests', 'items'], list => list.concat(action.accounts.map(item => item.id))).setIn(['follow_requests', 'next'], action.next);
|
||||
case FOLLOW_REQUEST_AUTHORIZE_SUCCESS:
|
||||
case FOLLOW_REQUEST_REJECT_SUCCESS:
|
||||
return state.updateIn(['follow_requests', 'items'], list => list.filterNot(item => item === action.id));
|
||||
case BLOCKS_FETCH_SUCCESS:
|
||||
return state.setIn(['blocks', 'items'], ImmutableList(action.accounts.map(item => item.id))).setIn(['blocks', 'next'], action.next);
|
||||
case BLOCKS_EXPAND_SUCCESS:
|
||||
return state.updateIn(['blocks', 'items'], list => list.concat(action.accounts.map(item => item.id))).setIn(['blocks', 'next'], action.next);
|
||||
case MUTES_FETCH_SUCCESS:
|
||||
return state.setIn(['mutes', 'items'], ImmutableList(action.accounts.map(item => item.id))).setIn(['mutes', 'next'], action.next);
|
||||
case MUTES_EXPAND_SUCCESS:
|
||||
return state.updateIn(['mutes', 'items'], list => list.concat(action.accounts.map(item => item.id))).setIn(['mutes', 'next'], action.next);
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
};
|
Reference in New Issue
Block a user