[build] upgrade eslint to 9.37.0 (#88)

Co-authored-by: tobi <tobi.smethurst@protonmail.com>
Reviewed-on: https://codeberg.org/superseriousbusiness/masto-fe-standalone/pulls/88
Co-authored-by: Zoë Bijl <moiety@noreply.codeberg.org>
Co-committed-by: Zoë Bijl <moiety@noreply.codeberg.org>
This commit is contained in:
Zoë Bijl
2025-10-12 13:42:02 +02:00
committed by tobi
parent 75d7a62693
commit 1ff70886a1
975 changed files with 22196 additions and 21964 deletions
+12 -12
View File
@@ -1,7 +1,7 @@
import { Map as ImmutableMap, fromJS } from 'immutable';
import { Map as ImmutableMap, fromJS } from "immutable";
import { ACCOUNT_REVEAL } from 'mastodon/actions/accounts';
import { ACCOUNT_IMPORT, ACCOUNTS_IMPORT } from 'mastodon/actions/importer';
import { ACCOUNT_REVEAL } from "mastodon/actions/accounts";
import { ACCOUNT_IMPORT, ACCOUNTS_IMPORT } from "mastodon/actions/importer";
const initialState = ImmutableMap();
@@ -12,7 +12,7 @@ const normalizeAccount = (state, account) => {
delete account.following_count;
delete account.statuses_count;
account.hidden = state.getIn([account.id, 'hidden']) === false ? false : account.limited;
account.hidden = state.getIn([account.id, "hidden"]) === false ? false : account.limited;
return state.set(account.id, fromJS(account));
};
@@ -27,13 +27,13 @@ const normalizeAccounts = (state, accounts) => {
export default function accounts(state = initialState, action) {
switch(action.type) {
case ACCOUNT_IMPORT:
return normalizeAccount(state, action.account);
case ACCOUNTS_IMPORT:
return normalizeAccounts(state, action.accounts);
case ACCOUNT_REVEAL:
return state.setIn([action.id, 'hidden'], false);
default:
return state;
case ACCOUNT_IMPORT:
return normalizeAccount(state, action.account);
case ACCOUNTS_IMPORT:
return normalizeAccounts(state, action.accounts);
case ACCOUNT_REVEAL:
return state.setIn([action.id, "hidden"], false);
default:
return state;
}
}
@@ -1,12 +1,12 @@
import { Map as ImmutableMap, fromJS } from 'immutable';
import { Map as ImmutableMap, fromJS } from "immutable";
import { me } from 'mastodon/initial_state';
import { me } from "mastodon/initial_state";
import {
ACCOUNT_FOLLOW_SUCCESS,
ACCOUNT_UNFOLLOW_SUCCESS,
} from '../actions/accounts';
import { ACCOUNT_IMPORT, ACCOUNTS_IMPORT } from '../actions/importer';
} from "../actions/accounts";
import { ACCOUNT_IMPORT, ACCOUNTS_IMPORT } from "../actions/importer";
const normalizeAccount = (state, account) => state.set(account.id, fromJS({
followers_count: account.followers_count,
@@ -23,27 +23,27 @@ const normalizeAccounts = (state, accounts) => {
};
const incrementFollowers = (state, accountId) =>
state.updateIn([accountId, 'followers_count'], num => num + 1)
.updateIn([me, 'following_count'], num => num + 1);
state.updateIn([accountId, "followers_count"], num => num + 1)
.updateIn([me, "following_count"], num => num + 1);
const decrementFollowers = (state, accountId) =>
state.updateIn([accountId, 'followers_count'], num => Math.max(0, num - 1))
.updateIn([me, 'following_count'], num => Math.max(0, num - 1));
state.updateIn([accountId, "followers_count"], num => Math.max(0, num - 1))
.updateIn([me, "following_count"], num => Math.max(0, num - 1));
const initialState = ImmutableMap();
export default function accountsCounters(state = initialState, action) {
switch(action.type) {
case ACCOUNT_IMPORT:
return normalizeAccount(state, action.account);
case ACCOUNTS_IMPORT:
return normalizeAccounts(state, action.accounts);
case ACCOUNT_FOLLOW_SUCCESS:
return action.alreadyFollowing ? state :
incrementFollowers(state, action.relationship.id);
case ACCOUNT_UNFOLLOW_SUCCESS:
return decrementFollowers(state, action.relationship.id);
default:
return state;
case ACCOUNT_IMPORT:
return normalizeAccount(state, action.account);
case ACCOUNTS_IMPORT:
return normalizeAccounts(state, action.accounts);
case ACCOUNT_FOLLOW_SUCCESS:
return action.alreadyFollowing ? state :
incrementFollowers(state, action.relationship.id);
case ACCOUNT_UNFOLLOW_SUCCESS:
return decrementFollowers(state, action.relationship.id);
default:
return state;
}
}
@@ -1,7 +1,7 @@
import { Map as ImmutableMap } from 'immutable';
import { Map as ImmutableMap } from "immutable";
import { ACCOUNT_LOOKUP_FAIL } from '../actions/accounts';
import { ACCOUNT_IMPORT, ACCOUNTS_IMPORT } from '../actions/importer';
import { ACCOUNT_LOOKUP_FAIL } from "../actions/accounts";
import { ACCOUNT_IMPORT, ACCOUNTS_IMPORT } from "../actions/importer";
export const normalizeForLookup = str => str.toLowerCase();
@@ -9,13 +9,13 @@ const initialState = ImmutableMap();
export default function accountsMap(state = initialState, action) {
switch(action.type) {
case ACCOUNT_LOOKUP_FAIL:
return action.error?.response?.status === 404 ? state.set(normalizeForLookup(action.acct), null) : state;
case ACCOUNT_IMPORT:
return state.set(normalizeForLookup(action.account.acct), action.account.id);
case ACCOUNTS_IMPORT:
return state.withMutations(map => action.accounts.forEach(account => map.set(normalizeForLookup(account.acct), account.id)));
default:
return state;
case ACCOUNT_LOOKUP_FAIL:
return action.error?.response?.status === 404 ? state.set(normalizeForLookup(action.acct), null) : state;
case ACCOUNT_IMPORT:
return state.set(normalizeForLookup(action.account.acct), action.account.id);
case ACCOUNTS_IMPORT:
return state.withMutations(map => action.accounts.forEach(account => map.set(normalizeForLookup(account.acct), account.id)));
default:
return state;
}
}
+10 -10
View File
@@ -1,10 +1,10 @@
import { List as ImmutableList } from 'immutable';
import { List as ImmutableList } from "immutable";
import {
ALERT_SHOW,
ALERT_DISMISS,
ALERT_CLEAR,
} from '../actions/alerts';
} from "../actions/alerts";
const initialState = ImmutableList([]);
@@ -18,13 +18,13 @@ const addAlert = (state, alert) =>
export default function alerts(state = initialState, action) {
switch(action.type) {
case ALERT_SHOW:
return addAlert(state, action.alert);
case ALERT_DISMISS:
return state.filterNot(item => item.key === action.alert.key);
case ALERT_CLEAR:
return state.clear();
default:
return state;
case ALERT_SHOW:
return addAlert(state, action.alert);
case ALERT_DISMISS:
return state.filterNot(item => item.key === action.alert.key);
case ALERT_CLEAR:
return state.clear();
default:
return state;
}
}
@@ -1,4 +1,4 @@
import { Map as ImmutableMap, List as ImmutableList, fromJS } from 'immutable';
import { Map as ImmutableMap, List as ImmutableList, fromJS } from "immutable";
import {
ANNOUNCEMENTS_FETCH_REQUEST,
@@ -13,7 +13,7 @@ import {
ANNOUNCEMENTS_TOGGLE_SHOW,
ANNOUNCEMENTS_DELETE,
ANNOUNCEMENTS_DISMISS_SUCCESS,
} from '../actions/announcements';
} from "../actions/announcements";
const initialState = ImmutableMap({
items: ImmutableList(),
@@ -21,10 +21,10 @@ const initialState = ImmutableMap({
show: false,
});
const updateReaction = (state, id, name, updater) => state.update('items', list => list.map(announcement => {
if (announcement.get('id') === id) {
return announcement.update('reactions', reactions => {
const idx = reactions.findIndex(reaction => reaction.get('name') === name);
const updateReaction = (state, id, name, updater) => state.update("items", list => list.map(announcement => {
if (announcement.get("id") === id) {
return announcement.update("reactions", reactions => {
const idx = reactions.findIndex(reaction => reaction.get("name") === name);
if (idx > -1) {
return reactions.update(idx, reaction => updater(reaction));
@@ -37,67 +37,67 @@ const updateReaction = (state, id, name, updater) => state.update('items', list
return announcement;
}));
const updateReactionCount = (state, reaction) => updateReaction(state, reaction.announcement_id, reaction.name, x => x.set('count', reaction.count));
const updateReactionCount = (state, reaction) => updateReaction(state, reaction.announcement_id, reaction.name, x => x.set("count", reaction.count));
const addReaction = (state, id, name) => updateReaction(state, id, name, x => x.set('me', true).update('count', y => y + 1));
const addReaction = (state, id, name) => updateReaction(state, id, name, x => x.set("me", true).update("count", y => y + 1));
const removeReaction = (state, id, name) => updateReaction(state, id, name, x => x.set('me', false).update('count', y => y - 1));
const removeReaction = (state, id, name) => updateReaction(state, id, name, x => x.set("me", false).update("count", y => y - 1));
const sortAnnouncements = list => list.sortBy(x => x.get('starts_at') || x.get('published_at'));
const sortAnnouncements = list => list.sortBy(x => x.get("starts_at") || x.get("published_at"));
const updateAnnouncement = (state, announcement) => {
const idx = state.get('items').findIndex(x => x.get('id') === announcement.get('id'));
const idx = state.get("items").findIndex(x => x.get("id") === announcement.get("id"));
if (idx > -1) {
// Deep merge is used because announcements from the streaming API do not contain
// personalized data about which reactions have been selected by the given user,
// and that is information we want to preserve
return state.update('items', list => sortAnnouncements(list.update(idx, x => x.mergeDeep(announcement))));
return state.update("items", list => sortAnnouncements(list.update(idx, x => x.mergeDeep(announcement))));
}
return state.update('items', list => sortAnnouncements(list.unshift(announcement)));
return state.update("items", list => sortAnnouncements(list.unshift(announcement)));
};
export default function announcementsReducer(state = initialState, action) {
switch(action.type) {
case ANNOUNCEMENTS_TOGGLE_SHOW:
return state.withMutations(map => {
map.set('show', !map.get('show'));
});
case ANNOUNCEMENTS_FETCH_REQUEST:
return state.set('isLoading', true);
case ANNOUNCEMENTS_FETCH_SUCCESS:
return state.withMutations(map => {
const items = fromJS(action.announcements);
case ANNOUNCEMENTS_TOGGLE_SHOW:
return state.withMutations(map => {
map.set("show", !map.get("show"));
});
case ANNOUNCEMENTS_FETCH_REQUEST:
return state.set("isLoading", true);
case ANNOUNCEMENTS_FETCH_SUCCESS:
return state.withMutations(map => {
const items = fromJS(action.announcements);
map.set('items', items);
map.set('isLoading', false);
});
case ANNOUNCEMENTS_FETCH_FAIL:
return state.set('isLoading', false);
case ANNOUNCEMENTS_UPDATE:
return updateAnnouncement(state, fromJS(action.announcement));
case ANNOUNCEMENTS_REACTION_UPDATE:
return updateReactionCount(state, action.reaction);
case ANNOUNCEMENTS_REACTION_ADD_REQUEST:
case ANNOUNCEMENTS_REACTION_REMOVE_FAIL:
return addReaction(state, action.id, action.name);
case ANNOUNCEMENTS_REACTION_REMOVE_REQUEST:
case ANNOUNCEMENTS_REACTION_ADD_FAIL:
return removeReaction(state, action.id, action.name);
case ANNOUNCEMENTS_DISMISS_SUCCESS:
return updateAnnouncement(state, fromJS({ 'id': action.id, 'read': true }));
case ANNOUNCEMENTS_DELETE:
return state.update('items', list => {
const idx = list.findIndex(x => x.get('id') === action.id);
map.set("items", items);
map.set("isLoading", false);
});
case ANNOUNCEMENTS_FETCH_FAIL:
return state.set("isLoading", false);
case ANNOUNCEMENTS_UPDATE:
return updateAnnouncement(state, fromJS(action.announcement));
case ANNOUNCEMENTS_REACTION_UPDATE:
return updateReactionCount(state, action.reaction);
case ANNOUNCEMENTS_REACTION_ADD_REQUEST:
case ANNOUNCEMENTS_REACTION_REMOVE_FAIL:
return addReaction(state, action.id, action.name);
case ANNOUNCEMENTS_REACTION_REMOVE_REQUEST:
case ANNOUNCEMENTS_REACTION_ADD_FAIL:
return removeReaction(state, action.id, action.name);
case ANNOUNCEMENTS_DISMISS_SUCCESS:
return updateAnnouncement(state, fromJS({ "id": action.id, "read": true }));
case ANNOUNCEMENTS_DELETE:
return state.update("items", list => {
const idx = list.findIndex(x => x.get("id") === action.id);
if (idx > -1) {
return list.delete(idx);
}
if (idx > -1) {
return list.delete(idx);
}
return list;
});
default:
return state;
return list;
});
default:
return state;
}
}
+8 -8
View File
@@ -1,8 +1,8 @@
import Immutable from 'immutable';
import Immutable from "immutable";
import {
BLOCKS_INIT_MODAL,
} from '../actions/blocks';
} from "../actions/blocks";
const initialState = Immutable.Map({
new: Immutable.Map({
@@ -12,11 +12,11 @@ const initialState = Immutable.Map({
export default function mutes(state = initialState, action) {
switch (action.type) {
case BLOCKS_INIT_MODAL:
return state.withMutations((state) => {
state.setIn(['new', 'account_id'], action.account.get('id'));
});
default:
return state;
case BLOCKS_INIT_MODAL:
return state.withMutations((state) => {
state.setIn(["new", "account_id"], action.account.get("id"));
});
default:
return state;
}
}
+11 -11
View File
@@ -1,25 +1,25 @@
import Immutable from 'immutable';
import Immutable from "immutable";
import {
BOOSTS_INIT_MODAL,
BOOSTS_CHANGE_PRIVACY,
} from 'mastodon/actions/boosts';
} from "mastodon/actions/boosts";
const initialState = Immutable.Map({
new: Immutable.Map({
privacy: 'public',
privacy: "public",
}),
});
export default function mutes(state = initialState, action) {
switch (action.type) {
case BOOSTS_INIT_MODAL:
return state.withMutations((state) => {
state.setIn(['new', 'privacy'], action.privacy);
});
case BOOSTS_CHANGE_PRIVACY:
return state.setIn(['new', 'privacy'], action.privacy);
default:
return state;
case BOOSTS_INIT_MODAL:
return state.withMutations((state) => {
state.setIn(["new", "privacy"], action.privacy);
});
case BOOSTS_CHANGE_PRIVACY:
return state.setIn(["new", "privacy"], action.privacy);
default:
return state;
}
}
+321 -317
View File
@@ -1,4 +1,4 @@
import { Map as ImmutableMap, List as ImmutableList, OrderedSet as ImmutableOrderedSet, fromJS } from 'immutable';
import { Map as ImmutableMap, List as ImmutableList, OrderedSet as ImmutableOrderedSet, fromJS } from "immutable";
import {
COMPOSE_MOUNT,
@@ -49,22 +49,22 @@ import {
COMPOSE_CHANGE_MEDIA_FOCUS,
COMPOSE_SET_STATUS,
COMPOSE_FOCUS,
} from '../actions/compose';
import { REDRAFT } from '../actions/statuses';
import { STORE_HYDRATE } from '../actions/store';
import { TIMELINE_DELETE } from '../actions/timelines';
import { me } from '../initial_state';
import { unescapeHTML } from '../utils/html';
import { uuid } from '../uuid';
} from "../actions/compose";
import { REDRAFT } from "../actions/statuses";
import { STORE_HYDRATE } from "../actions/store";
import { TIMELINE_DELETE } from "../actions/timelines";
import { me } from "../initial_state";
import { unescapeHTML } from "../utils/html";
import { uuid } from "../uuid";
const initialState = ImmutableMap({
mounted: 0,
sensitive: false,
spoiler: false,
spoiler_text: '',
spoiler_text: "",
privacy: null,
id: null,
text: '',
text: "",
focusDate: null,
caretPosition: null,
preselectDate: null,
@@ -81,15 +81,15 @@ const initialState = ImmutableMap({
poll: null,
suggestion_token: null,
suggestions: ImmutableList(),
default_privacy: 'public',
default_privacy: "public",
default_sensitive: false,
default_language: 'en',
default_language: "en",
resetFileKey: Math.floor((Math.random() * 0x10000)),
idempotencyKey: null,
tagHistory: ImmutableList(),
media_modal: ImmutableMap({
id: null,
description: '',
description: "",
focusX: 0,
focusY: 0,
dirty: false,
@@ -97,7 +97,7 @@ const initialState = ImmutableMap({
});
const initialPoll = ImmutableMap({
options: ImmutableList(['', '']),
options: ImmutableList(["", ""]),
expires_in: 24 * 3600,
multiple: false,
});
@@ -105,60 +105,60 @@ const initialPoll = ImmutableMap({
function statusToTextMentions(state, status) {
let set = ImmutableOrderedSet([]);
if (status.getIn(['account', 'id']) !== me) {
set = set.add(`@${status.getIn(['account', 'acct'])} `);
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('');
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('id', null);
map.set('text', '');
map.set('spoiler', false);
map.set('spoiler_text', '');
map.set('is_submitting', false);
map.set('is_changing_upload', false);
map.set('in_reply_to', null);
map.set('privacy', state.get('default_privacy'));
map.set('sensitive', state.get('default_sensitive'));
map.set('language', state.get('default_language'));
map.update('media_attachments', list => list.clear());
map.set('poll', null);
map.set('idempotencyKey', uuid());
map.set("id", null);
map.set("text", "");
map.set("spoiler", false);
map.set("spoiler_text", "");
map.set("is_submitting", false);
map.set("is_changing_upload", false);
map.set("in_reply_to", null);
map.set("privacy", state.get("default_privacy"));
map.set("sensitive", state.get("default_sensitive"));
map.set("language", state.get("default_language"));
map.update("media_attachments", list => list.clear());
map.set("poll", null);
map.set("idempotencyKey", uuid());
});
}
function appendMedia(state, media, file) {
const prevSize = state.get('media_attachments').size;
const prevSize = state.get("media_attachments").size;
return state.withMutations(map => {
if (media.get('type') === 'image') {
media = media.set('file', file);
if (media.get("type") === "image") {
media = media.set("file", file);
}
map.update('media_attachments', list => list.push(media.set('unattached', true)));
map.set('is_uploading', false);
map.set('is_processing', false);
map.set('resetFileKey', Math.floor((Math.random() * 0x10000)));
map.set('idempotencyKey', uuid());
map.update('pending_media_attachments', n => n - 1);
map.update("media_attachments", list => list.push(media.set("unattached", true)));
map.set("is_uploading", false);
map.set("is_processing", false);
map.set("resetFileKey", Math.floor((Math.random() * 0x10000)));
map.set("idempotencyKey", uuid());
map.update("pending_media_attachments", n => n - 1);
if (prevSize === 0 && (state.get('default_sensitive') || state.get('spoiler'))) {
map.set('sensitive', true);
if (prevSize === 0 && (state.get("default_sensitive") || state.get("spoiler"))) {
map.set("sensitive", true);
}
});
}
function removeMedia(state, mediaId) {
const prevSize = state.get('media_attachments').size;
const prevSize = state.get("media_attachments").size;
return state.withMutations(map => {
map.update('media_attachments', list => list.filterNot(item => item.get('id') === mediaId));
map.set('idempotencyKey', uuid());
map.update("media_attachments", list => list.filterNot(item => item.get("id") === mediaId));
map.set("idempotencyKey", uuid());
if (prevSize === 1) {
map.set('sensitive', false);
map.set("sensitive", false);
}
});
}
@@ -166,29 +166,29 @@ function removeMedia(state, mediaId) {
const insertSuggestion = (state, position, token, completion, path) => {
return state.withMutations(map => {
map.updateIn(path, oldText => `${oldText.slice(0, position)}${completion} ${oldText.slice(position + token.length)}`);
map.set('suggestion_token', null);
map.set('suggestions', ImmutableList());
if (path.length === 1 && path[0] === 'text') {
map.set('focusDate', new Date());
map.set('caretPosition', position + completion.length + 1);
map.set("suggestion_token", null);
map.set("suggestions", ImmutableList());
if (path.length === 1 && path[0] === "text") {
map.set("focusDate", new Date());
map.set("caretPosition", position + completion.length + 1);
}
map.set('idempotencyKey', uuid());
map.set("idempotencyKey", uuid());
});
};
const ignoreSuggestion = (state, position, token, completion, path) => {
return state.withMutations(map => {
map.updateIn(path, oldText => `${oldText.slice(0, position + token.length)} ${oldText.slice(position + token.length)}`);
map.set('suggestion_token', null);
map.set('suggestions', ImmutableList());
map.set('focusDate', new Date());
map.set('caretPosition', position + token.length + 1);
map.set('idempotencyKey', uuid());
map.set("suggestion_token", null);
map.set("suggestions", ImmutableList());
map.set("focusDate", new Date());
map.set("caretPosition", position + token.length + 1);
map.set("idempotencyKey", uuid());
});
};
const sortHashtagsByUse = (state, tags) => {
const personalHistory = state.get('tagHistory').map(tag => tag.toLowerCase());
const personalHistory = state.get("tagHistory").map(tag => tag.toLowerCase());
const tagsWithLowercase = tags.map(t => ({ ...t, lowerName: t.name.toLowerCase() }));
const sorted = tagsWithLowercase.sort((a, b) => {
@@ -208,8 +208,8 @@ const sortHashtagsByUse = (state, tags) => {
};
const insertEmoji = (state, position, emojiData, needsSpace) => {
const oldText = state.get('text');
const emoji = needsSpace ? ' ' + emojiData.native : emojiData.native;
const oldText = state.get("text");
const emoji = needsSpace ? " " + emojiData.native : emojiData.native;
return state.merge({
text: `${oldText.slice(0, position)}${emoji} ${oldText.slice(position)}`,
@@ -220,15 +220,15 @@ const insertEmoji = (state, position, emojiData, needsSpace) => {
};
const privacyPreference = (a, b) => {
const order = ['public', 'unlisted', 'private', 'direct'];
const order = ["public", "unlisted", "private", "direct"];
return order[Math.max(order.indexOf(a), order.indexOf(b), 0)];
};
const hydrate = (state, hydratedState) => {
state = clearAll(state.merge(hydratedState));
if (hydratedState.get('text')) {
state = state.set('text', hydratedState.get('text')).set('focusDate', new Date());
if (hydratedState.get("text")) {
state = state.set("text", hydratedState.get("text")).set("focusDate", new Date());
}
return state;
@@ -237,17 +237,19 @@ const hydrate = (state, hydratedState) => {
const domParser = new DOMParser();
const expandMentions = status => {
const fragment = domParser.parseFromString(status.get('content'), 'text/html').documentElement;
const fragment = domParser.parseFromString(status.get("content"), "text/html").documentElement;
status.get('mentions').forEach(mention => {
fragment.querySelector(`a[href="${mention.get('url')}"]`).textContent = `@${mention.get('acct')}`;
status.get("mentions").forEach(mention => {
fragment.querySelector(`a[href="${mention.get("url")}"]`).textContent = `@${mention.get("acct")}`;
});
return fragment.innerHTML;
};
const expiresInFromExpiresAt = expires_at => {
if (!expires_at) return 24 * 3600;
if (!expires_at) {
return 24 * 3600;
}
const delta = (new Date(expires_at).getTime() - Date.now()) / 1000;
return [300, 1800, 3600, 21600, 86400, 259200, 604800].find(expires_in => expires_in >= delta) || 24 * 3600;
};
@@ -255,8 +257,8 @@ const expiresInFromExpiresAt = expires_at => {
const mergeLocalHashtagResults = (suggestions, prefix, tagHistory) => {
prefix = prefix.toLowerCase();
if (suggestions.length < 4) {
const localTags = tagHistory.filter(tag => tag.toLowerCase().startsWith(prefix) && !suggestions.some(suggestion => suggestion.type === 'hashtag' && suggestion.name.toLowerCase() === tag.toLowerCase()));
return suggestions.concat(localTags.slice(0, 4 - suggestions.length).toJS().map(tag => ({ type: 'hashtag', name: tag })));
const localTags = tagHistory.filter(tag => tag.toLowerCase().startsWith(prefix) && !suggestions.some(suggestion => suggestion.type === "hashtag" && suggestion.name.toLowerCase() === tag.toLowerCase()));
return suggestions.concat(localTags.slice(0, 4 - suggestions.length).toJS().map(tag => ({ type: "hashtag", name: tag })));
} else {
return suggestions;
}
@@ -264,273 +266,275 @@ const mergeLocalHashtagResults = (suggestions, prefix, tagHistory) => {
const normalizeSuggestions = (state, { accounts, emojis, tags, token }) => {
if (accounts) {
return accounts.map(item => ({ id: item.id, type: 'account' }));
return accounts.map(item => ({ id: item.id, type: "account" }));
} else if (emojis) {
return emojis.map(item => ({ ...item, type: 'emoji' }));
return emojis.map(item => ({ ...item, type: "emoji" }));
} else {
return mergeLocalHashtagResults(sortHashtagsByUse(state, tags.map(item => ({ ...item, type: 'hashtag' }))), token.slice(1), state.get('tagHistory'));
return mergeLocalHashtagResults(sortHashtagsByUse(state, tags.map(item => ({ ...item, type: "hashtag" }))), token.slice(1), state.get("tagHistory"));
}
};
const updateSuggestionTags = (state, token) => {
const prefix = token.slice(1);
const suggestions = state.get('suggestions').toJS();
const suggestions = state.get("suggestions").toJS();
return state.merge({
suggestions: ImmutableList(mergeLocalHashtagResults(suggestions, prefix, state.get('tagHistory'))),
suggestions: ImmutableList(mergeLocalHashtagResults(suggestions, prefix, state.get("tagHistory"))),
suggestion_token: token,
});
};
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', state.get('mounted') + 1);
case COMPOSE_UNMOUNT:
return state
.set('mounted', Math.max(state.get('mounted') - 1, 0))
.set('is_composing', false);
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', !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:
if (!state.get('spoiler')) return state;
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('id', null);
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('focusDate', new Date());
map.set('caretPosition', null);
map.set('preselectDate', new Date());
map.set('idempotencyKey', uuid());
map.update('media_attachments', list => list.filter(media => media.get('unattached')));
if (action.status.get('language') && !action.status.has('translation')) {
map.set('language', action.status.get('language'));
} else {
map.set('language', state.get('default_language'));
}
if (action.status.get('spoiler_text').length > 0) {
map.set('spoiler', true);
map.set('spoiler_text', action.status.get('spoiler_text'));
if (map.get('media_attachments').size >= 1) {
map.set('sensitive', true);
}
} else {
map.set('spoiler', false);
map.set('spoiler_text', '');
}
});
case COMPOSE_SUBMIT_REQUEST:
return state.set('is_submitting', true);
case COMPOSE_UPLOAD_CHANGE_REQUEST:
return state.set('is_changing_upload', true);
case COMPOSE_REPLY_CANCEL:
case COMPOSE_RESET:
case COMPOSE_SUBMIT_SUCCESS:
return clearAll(state);
case COMPOSE_SUBMIT_FAIL:
return state.set('is_submitting', false);
case COMPOSE_UPLOAD_CHANGE_FAIL:
return state.set('is_changing_upload', false);
case COMPOSE_UPLOAD_REQUEST:
return state.set('is_uploading', true).update('pending_media_attachments', n => n + 1);
case COMPOSE_UPLOAD_PROCESSING:
return state.set('is_processing', true);
case COMPOSE_UPLOAD_SUCCESS:
return appendMedia(state, fromJS(action.media), action.file);
case COMPOSE_UPLOAD_FAIL:
return state.set('is_uploading', false).set('is_processing', false).update('pending_media_attachments', n => n - 1);
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 THUMBNAIL_UPLOAD_REQUEST:
return state.set('isUploadingThumbnail', true);
case THUMBNAIL_UPLOAD_PROGRESS:
return state.set('thumbnailProgress', Math.round((action.loaded / action.total) * 100));
case THUMBNAIL_UPLOAD_FAIL:
return state.set('isUploadingThumbnail', false);
case THUMBNAIL_UPLOAD_SUCCESS:
return state
.set('isUploadingThumbnail', false)
.update('media_attachments', list => list.map(item => {
if (item.get('id') === action.media.id) {
return fromJS(action.media);
case STORE_HYDRATE:
return hydrate(state, action.state.get("compose"));
case COMPOSE_MOUNT:
return state.set("mounted", state.get("mounted") + 1);
case COMPOSE_UNMOUNT:
return state
.set("mounted", Math.max(state.get("mounted") - 1, 0))
.set("is_composing", false);
case COMPOSE_SENSITIVITY_CHANGE:
return state.withMutations(map => {
if (!state.get("spoiler")) {
map.set("sensitive", !state.get("sensitive"));
}
return item;
map.set("idempotencyKey", uuid());
});
case COMPOSE_SPOILERNESS_CHANGE:
return state.withMutations(map => {
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:
if (!state.get("spoiler")) {
return state;
}
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("id", null);
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("focusDate", new Date());
map.set("caretPosition", null);
map.set("preselectDate", new Date());
map.set("idempotencyKey", uuid());
map.update("media_attachments", list => list.filter(media => media.get("unattached")));
if (action.status.get("language") && !action.status.has("translation")) {
map.set("language", action.status.get("language"));
} else {
map.set("language", state.get("default_language"));
}
if (action.status.get("spoiler_text").length > 0) {
map.set("spoiler", true);
map.set("spoiler_text", action.status.get("spoiler_text"));
if (map.get("media_attachments").size >= 1) {
map.set("sensitive", true);
}
} else {
map.set("spoiler", false);
map.set("spoiler_text", "");
}
});
case COMPOSE_SUBMIT_REQUEST:
return state.set("is_submitting", true);
case COMPOSE_UPLOAD_CHANGE_REQUEST:
return state.set("is_changing_upload", true);
case COMPOSE_REPLY_CANCEL:
case COMPOSE_RESET:
case COMPOSE_SUBMIT_SUCCESS:
return clearAll(state);
case COMPOSE_SUBMIT_FAIL:
return state.set("is_submitting", false);
case COMPOSE_UPLOAD_CHANGE_FAIL:
return state.set("is_changing_upload", false);
case COMPOSE_UPLOAD_REQUEST:
return state.set("is_uploading", true).update("pending_media_attachments", n => n + 1);
case COMPOSE_UPLOAD_PROCESSING:
return state.set("is_processing", true);
case COMPOSE_UPLOAD_SUCCESS:
return appendMedia(state, fromJS(action.media), action.file);
case COMPOSE_UPLOAD_FAIL:
return state.set("is_uploading", false).set("is_processing", false).update("pending_media_attachments", n => n - 1);
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 THUMBNAIL_UPLOAD_REQUEST:
return state.set("isUploadingThumbnail", true);
case THUMBNAIL_UPLOAD_PROGRESS:
return state.set("thumbnailProgress", Math.round((action.loaded / action.total) * 100));
case THUMBNAIL_UPLOAD_FAIL:
return state.set("isUploadingThumbnail", false);
case THUMBNAIL_UPLOAD_SUCCESS:
return state
.set("isUploadingThumbnail", false)
.update("media_attachments", list => list.map(item => {
if (item.get("id") === action.media.id) {
return fromJS(action.media);
}
return item;
}));
case INIT_MEDIA_EDIT_MODAL:
const media = state.get("media_attachments").find(item => item.get("id") === action.id);
return state.set("media_modal", ImmutableMap({
id: action.id,
description: media.get("description") || "",
focusX: media.getIn(["meta", "focus", "x"], 0),
focusY: media.getIn(["meta", "focus", "y"], 0),
dirty: false,
}));
case INIT_MEDIA_EDIT_MODAL:
const media = state.get('media_attachments').find(item => item.get('id') === action.id);
return state.set('media_modal', ImmutableMap({
id: action.id,
description: media.get('description') || '',
focusX: media.getIn(['meta', 'focus', 'x'], 0),
focusY: media.getIn(['meta', 'focus', 'y'], 0),
dirty: false,
}));
case COMPOSE_CHANGE_MEDIA_DESCRIPTION:
return state.setIn(['media_modal', 'description'], action.description).setIn(['media_modal', 'dirty'], true);
case COMPOSE_CHANGE_MEDIA_FOCUS:
return state.setIn(['media_modal', 'focusX'], action.focusX).setIn(['media_modal', 'focusY'], action.focusY).setIn(['media_modal', 'dirty'], true);
case COMPOSE_MENTION:
return state.withMutations(map => {
map.update('text', text => [text.trim(), `@${action.account.get('acct')} `].filter((str) => str.length !== 0).join(' '));
map.set('focusDate', new Date());
map.set('caretPosition', null);
map.set('idempotencyKey', uuid());
});
case COMPOSE_DIRECT:
return state.withMutations(map => {
map.update('text', text => [text.trim(), `@${action.account.get('acct')} `].filter((str) => str.length !== 0).join(' '));
map.set('privacy', 'direct');
map.set('focusDate', new Date());
map.set('caretPosition', null);
map.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(normalizeSuggestions(state, action))).set('suggestion_token', action.token);
case COMPOSE_SUGGESTION_SELECT:
return insertSuggestion(state, action.position, action.token, action.completion, action.path);
case COMPOSE_SUGGESTION_IGNORE:
return ignoreSuggestion(state, action.position, action.token, action.completion, action.path);
case COMPOSE_SUGGESTION_TAGS_UPDATE:
return updateSuggestionTags(state, action.token);
case COMPOSE_TAG_HISTORY_UPDATE:
return state.set('tagHistory', fromJS(action.tags));
case TIMELINE_DELETE:
if (action.id === state.get('in_reply_to')) {
return state.set('in_reply_to', null);
} else if (action.id === state.get('id')) {
return state.set('id', null);
} else {
case COMPOSE_CHANGE_MEDIA_DESCRIPTION:
return state.setIn(["media_modal", "description"], action.description).setIn(["media_modal", "dirty"], true);
case COMPOSE_CHANGE_MEDIA_FOCUS:
return state.setIn(["media_modal", "focusX"], action.focusX).setIn(["media_modal", "focusY"], action.focusY).setIn(["media_modal", "dirty"], true);
case COMPOSE_MENTION:
return state.withMutations(map => {
map.update("text", text => [text.trim(), `@${action.account.get("acct")} `].filter((str) => str.length !== 0).join(" "));
map.set("focusDate", new Date());
map.set("caretPosition", null);
map.set("idempotencyKey", uuid());
});
case COMPOSE_DIRECT:
return state.withMutations(map => {
map.update("text", text => [text.trim(), `@${action.account.get("acct")} `].filter((str) => str.length !== 0).join(" "));
map.set("privacy", "direct");
map.set("focusDate", new Date());
map.set("caretPosition", null);
map.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(normalizeSuggestions(state, action))).set("suggestion_token", action.token);
case COMPOSE_SUGGESTION_SELECT:
return insertSuggestion(state, action.position, action.token, action.completion, action.path);
case COMPOSE_SUGGESTION_IGNORE:
return ignoreSuggestion(state, action.position, action.token, action.completion, action.path);
case COMPOSE_SUGGESTION_TAGS_UPDATE:
return updateSuggestionTags(state, action.token);
case COMPOSE_TAG_HISTORY_UPDATE:
return state.set("tagHistory", fromJS(action.tags));
case TIMELINE_DELETE:
if (action.id === state.get("in_reply_to")) {
return state.set("in_reply_to", null);
} else if (action.id === state.get("id")) {
return state.set("id", null);
} else {
return state;
}
case COMPOSE_EMOJI_INSERT:
return insertEmoji(state, action.position, action.emoji, action.needsSpace);
case COMPOSE_UPLOAD_CHANGE_SUCCESS:
return state
.set("is_changing_upload", false)
.setIn(["media_modal", "dirty"], false)
.update("media_attachments", list => list.map(item => {
if (item.get("id") === action.media.id) {
return fromJS(action.media).set("unattached", !action.attached);
}
return item;
}));
case REDRAFT:
return state.withMutations(map => {
map.set("text", action.raw_text || unescapeHTML(expandMentions(action.status)));
map.set("in_reply_to", action.status.get("in_reply_to_id"));
map.set("privacy", action.status.get("visibility"));
map.set("media_attachments", action.status.get("media_attachments").map((media) => media.set("unattached", true)));
map.set("focusDate", new Date());
map.set("caretPosition", null);
map.set("idempotencyKey", uuid());
map.set("sensitive", action.status.get("sensitive"));
map.set("language", action.status.get("language"));
map.set("id", null);
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", "");
}
if (action.status.get("poll")) {
map.set("poll", ImmutableMap({
options: action.status.getIn(["poll", "options"]).map(x => x.get("title")),
multiple: action.status.getIn(["poll", "multiple"]),
expires_in: expiresInFromExpiresAt(action.status.getIn(["poll", "expires_at"])),
}));
}
});
case COMPOSE_SET_STATUS:
return state.withMutations(map => {
map.set("id", action.status.get("id"));
map.set("text", action.text);
map.set("in_reply_to", action.status.get("in_reply_to_id"));
map.set("privacy", action.status.get("visibility"));
map.set("media_attachments", action.status.get("media_attachments"));
map.set("focusDate", new Date());
map.set("caretPosition", null);
map.set("idempotencyKey", uuid());
map.set("sensitive", action.status.get("sensitive"));
map.set("language", action.status.get("language"));
if (action.spoiler_text.length > 0) {
map.set("spoiler", true);
map.set("spoiler_text", action.spoiler_text);
} else {
map.set("spoiler", false);
map.set("spoiler_text", "");
}
if (action.status.get("poll")) {
map.set("poll", ImmutableMap({
options: action.status.getIn(["poll", "options"]).map(x => x.get("title")),
multiple: action.status.getIn(["poll", "multiple"]),
expires_in: expiresInFromExpiresAt(action.status.getIn(["poll", "expires_at"])),
}));
}
});
case COMPOSE_POLL_ADD:
return state.set("poll", initialPoll);
case COMPOSE_POLL_REMOVE:
return state.set("poll", null);
case COMPOSE_POLL_OPTION_ADD:
return state.updateIn(["poll", "options"], options => options.push(action.title));
case COMPOSE_POLL_OPTION_CHANGE:
return state.setIn(["poll", "options", action.index], action.title);
case COMPOSE_POLL_OPTION_REMOVE:
return state.updateIn(["poll", "options"], options => options.delete(action.index));
case COMPOSE_POLL_SETTINGS_CHANGE:
return state.update("poll", poll => poll.set("expires_in", action.expiresIn).set("multiple", action.isMultiple));
case COMPOSE_LANGUAGE_CHANGE:
return state.set("language", action.language);
case COMPOSE_FOCUS:
return state.set("focusDate", new Date()).update("text", text => text.length > 0 ? text : action.defaultText);
default:
return state;
}
case COMPOSE_EMOJI_INSERT:
return insertEmoji(state, action.position, action.emoji, action.needsSpace);
case COMPOSE_UPLOAD_CHANGE_SUCCESS:
return state
.set('is_changing_upload', false)
.setIn(['media_modal', 'dirty'], false)
.update('media_attachments', list => list.map(item => {
if (item.get('id') === action.media.id) {
return fromJS(action.media).set('unattached', !action.attached);
}
return item;
}));
case REDRAFT:
return state.withMutations(map => {
map.set('text', action.raw_text || unescapeHTML(expandMentions(action.status)));
map.set('in_reply_to', action.status.get('in_reply_to_id'));
map.set('privacy', action.status.get('visibility'));
map.set('media_attachments', action.status.get('media_attachments').map((media) => media.set('unattached', true)));
map.set('focusDate', new Date());
map.set('caretPosition', null);
map.set('idempotencyKey', uuid());
map.set('sensitive', action.status.get('sensitive'));
map.set('language', action.status.get('language'));
map.set('id', null);
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', '');
}
if (action.status.get('poll')) {
map.set('poll', ImmutableMap({
options: action.status.getIn(['poll', 'options']).map(x => x.get('title')),
multiple: action.status.getIn(['poll', 'multiple']),
expires_in: expiresInFromExpiresAt(action.status.getIn(['poll', 'expires_at'])),
}));
}
});
case COMPOSE_SET_STATUS:
return state.withMutations(map => {
map.set('id', action.status.get('id'));
map.set('text', action.text);
map.set('in_reply_to', action.status.get('in_reply_to_id'));
map.set('privacy', action.status.get('visibility'));
map.set('media_attachments', action.status.get('media_attachments'));
map.set('focusDate', new Date());
map.set('caretPosition', null);
map.set('idempotencyKey', uuid());
map.set('sensitive', action.status.get('sensitive'));
map.set('language', action.status.get('language'));
if (action.spoiler_text.length > 0) {
map.set('spoiler', true);
map.set('spoiler_text', action.spoiler_text);
} else {
map.set('spoiler', false);
map.set('spoiler_text', '');
}
if (action.status.get('poll')) {
map.set('poll', ImmutableMap({
options: action.status.getIn(['poll', 'options']).map(x => x.get('title')),
multiple: action.status.getIn(['poll', 'multiple']),
expires_in: expiresInFromExpiresAt(action.status.getIn(['poll', 'expires_at'])),
}));
}
});
case COMPOSE_POLL_ADD:
return state.set('poll', initialPoll);
case COMPOSE_POLL_REMOVE:
return state.set('poll', null);
case COMPOSE_POLL_OPTION_ADD:
return state.updateIn(['poll', 'options'], options => options.push(action.title));
case COMPOSE_POLL_OPTION_CHANGE:
return state.setIn(['poll', 'options', action.index], action.title);
case COMPOSE_POLL_OPTION_REMOVE:
return state.updateIn(['poll', 'options'], options => options.delete(action.index));
case COMPOSE_POLL_SETTINGS_CHANGE:
return state.update('poll', poll => poll.set('expires_in', action.expiresIn).set('multiple', action.isMultiple));
case COMPOSE_LANGUAGE_CHANGE:
return state.set('language', action.language);
case COMPOSE_FOCUS:
return state.set('focusDate', new Date()).update('text', text => text.length > 0 ? text : action.defaultText);
default:
return state;
}
}
+25 -25
View File
@@ -1,12 +1,12 @@
import { Map as ImmutableMap, List as ImmutableList } from 'immutable';
import { Map as ImmutableMap, List as ImmutableList } from "immutable";
import {
ACCOUNT_BLOCK_SUCCESS,
ACCOUNT_MUTE_SUCCESS,
} from '../actions/accounts';
import { CONTEXT_FETCH_SUCCESS } from '../actions/statuses';
import { TIMELINE_DELETE, TIMELINE_UPDATE } from '../actions/timelines';
import { compareId } from '../compare_id';
} from "../actions/accounts";
import { CONTEXT_FETCH_SUCCESS } from "../actions/statuses";
import { TIMELINE_DELETE, TIMELINE_UPDATE } from "../actions/timelines";
import { compareId } from "../compare_id";
const initialState = ImmutableMap({
inReplyTos: ImmutableMap(),
@@ -14,8 +14,8 @@ const initialState = ImmutableMap({
});
const normalizeContext = (immutableState, id, ancestors, descendants) => immutableState.withMutations(state => {
state.update('inReplyTos', immutableAncestors => immutableAncestors.withMutations(inReplyTos => {
state.update('replies', immutableDescendants => immutableDescendants.withMutations(replies => {
state.update("inReplyTos", immutableAncestors => immutableAncestors.withMutations(inReplyTos => {
state.update("replies", immutableDescendants => immutableDescendants.withMutations(replies => {
function addReply({ id, in_reply_to_id }) {
if (in_reply_to_id && !inReplyTos.has(id)) {
@@ -43,8 +43,8 @@ const normalizeContext = (immutableState, id, ancestors, descendants) => immutab
});
const deleteFromContexts = (immutableState, ids) => immutableState.withMutations(state => {
state.update('inReplyTos', immutableAncestors => immutableAncestors.withMutations(inReplyTos => {
state.update('replies', immutableDescendants => immutableDescendants.withMutations(replies => {
state.update("inReplyTos", immutableAncestors => immutableAncestors.withMutations(inReplyTos => {
state.update("replies", immutableDescendants => immutableDescendants.withMutations(replies => {
ids.forEach(id => {
const inReplyToIdOfId = inReplyTos.get(id);
const repliesOfId = replies.get(id);
@@ -68,8 +68,8 @@ const deleteFromContexts = (immutableState, ids) => immutableState.withMutations
const filterContexts = (state, relationship, statuses) => {
const ownedStatusIds = statuses
.filter(status => status.get('account') === relationship.id)
.map(status => status.get('id'));
.filter(status => status.get("account") === relationship.id)
.map(status => status.get("id"));
return deleteFromContexts(state, ownedStatusIds);
};
@@ -77,12 +77,12 @@ const filterContexts = (state, relationship, statuses) => {
const updateContext = (state, status) => {
if (status.in_reply_to_id) {
return state.withMutations(mutable => {
const replies = mutable.getIn(['replies', status.in_reply_to_id], ImmutableList());
const replies = mutable.getIn(["replies", status.in_reply_to_id], ImmutableList());
mutable.setIn(['inReplyTos', status.id], status.in_reply_to_id);
mutable.setIn(["inReplyTos", status.id], status.in_reply_to_id);
if (!replies.includes(status.id)) {
mutable.setIn(['replies', status.in_reply_to_id], replies.push(status.id));
mutable.setIn(["replies", status.in_reply_to_id], replies.push(status.id));
}
});
}
@@ -92,16 +92,16 @@ const updateContext = (state, status) => {
export default function replies(state = initialState, action) {
switch(action.type) {
case ACCOUNT_BLOCK_SUCCESS:
case ACCOUNT_MUTE_SUCCESS:
return filterContexts(state, action.relationship, action.statuses);
case CONTEXT_FETCH_SUCCESS:
return normalizeContext(state, action.id, action.ancestors, action.descendants);
case TIMELINE_DELETE:
return deleteFromContexts(state, [action.id]);
case TIMELINE_UPDATE:
return updateContext(state, action.status);
default:
return state;
case ACCOUNT_BLOCK_SUCCESS:
case ACCOUNT_MUTE_SUCCESS:
return filterContexts(state, action.relationship, action.statuses);
case CONTEXT_FETCH_SUCCESS:
return normalizeContext(state, action.id, action.ancestors, action.descendants);
case TIMELINE_DELETE:
return deleteFromContexts(state, [action.id]);
case TIMELINE_UPDATE:
return updateContext(state, action.status);
default:
return state;
}
}
@@ -1,7 +1,7 @@
import { Map as ImmutableMap, List as ImmutableList } from 'immutable';
import { Map as ImmutableMap, List as ImmutableList } from "immutable";
import { ACCOUNT_BLOCK_SUCCESS, ACCOUNT_MUTE_SUCCESS } from 'mastodon/actions/accounts';
import { DOMAIN_BLOCK_SUCCESS } from 'mastodon/actions/domain_blocks';
import { ACCOUNT_BLOCK_SUCCESS, ACCOUNT_MUTE_SUCCESS } from "mastodon/actions/accounts";
import { DOMAIN_BLOCK_SUCCESS } from "mastodon/actions/domain_blocks";
import {
CONVERSATIONS_MOUNT,
@@ -12,8 +12,8 @@ import {
CONVERSATIONS_UPDATE,
CONVERSATIONS_READ,
CONVERSATIONS_DELETE_SUCCESS,
} from '../actions/conversations';
import { compareId } from '../compare_id';
} from "../actions/conversations";
import { compareId } from "../compare_id";
const initialState = ImmutableMap({
items: ImmutableList(),
@@ -29,8 +29,8 @@ const conversationToMap = item => ImmutableMap({
last_status: item.last_status ? item.last_status.id : null,
});
const updateConversation = (state, item) => state.update('items', list => {
const index = list.findIndex(x => x.get('id') === item.id);
const updateConversation = (state, item) => state.update("items", list => {
const index = list.findIndex(x => x.get("id") === item.id);
const newItem = conversationToMap(item);
if (index === -1) {
@@ -45,9 +45,9 @@ const expandNormalizedConversations = (state, conversations, next, isLoadingRece
return state.withMutations(mutable => {
if (!items.isEmpty()) {
mutable.update('items', list => {
mutable.update("items", list => {
list = list.map(oldItem => {
const newItemIndex = items.findIndex(x => x.get('id') === oldItem.get('id'));
const newItemIndex = items.findIndex(x => x.get("id") === oldItem.get("id"));
if (newItemIndex === -1) {
return oldItem;
@@ -61,7 +61,7 @@ const expandNormalizedConversations = (state, conversations, next, isLoadingRece
list = list.concat(items);
return list.sortBy(x => x.get('last_status'), (a, b) => {
return list.sortBy(x => x.get("last_status"), (a, b) => {
if(a === null || b === null) {
return -1;
}
@@ -72,47 +72,47 @@ const expandNormalizedConversations = (state, conversations, next, isLoadingRece
}
if (!next && !isLoadingRecent) {
mutable.set('hasMore', false);
mutable.set("hasMore", false);
}
mutable.set('isLoading', false);
mutable.set("isLoading", false);
});
};
const filterConversations = (state, accountIds) => {
return state.update('items', list => list.filterNot(item => item.get('accounts').some(accountId => accountIds.includes(accountId))));
return state.update("items", list => list.filterNot(item => item.get("accounts").some(accountId => accountIds.includes(accountId))));
};
export default function conversations(state = initialState, action) {
switch (action.type) {
case CONVERSATIONS_FETCH_REQUEST:
return state.set('isLoading', true);
case CONVERSATIONS_FETCH_FAIL:
return state.set('isLoading', false);
case CONVERSATIONS_FETCH_SUCCESS:
return expandNormalizedConversations(state, action.conversations, action.next, action.isLoadingRecent);
case CONVERSATIONS_UPDATE:
return updateConversation(state, action.conversation);
case CONVERSATIONS_MOUNT:
return state.update('mounted', count => count + 1);
case CONVERSATIONS_UNMOUNT:
return state.update('mounted', count => count - 1);
case CONVERSATIONS_READ:
return state.update('items', list => list.map(item => {
if (item.get('id') === action.id) {
return item.set('unread', false);
}
case CONVERSATIONS_FETCH_REQUEST:
return state.set("isLoading", true);
case CONVERSATIONS_FETCH_FAIL:
return state.set("isLoading", false);
case CONVERSATIONS_FETCH_SUCCESS:
return expandNormalizedConversations(state, action.conversations, action.next, action.isLoadingRecent);
case CONVERSATIONS_UPDATE:
return updateConversation(state, action.conversation);
case CONVERSATIONS_MOUNT:
return state.update("mounted", count => count + 1);
case CONVERSATIONS_UNMOUNT:
return state.update("mounted", count => count - 1);
case CONVERSATIONS_READ:
return state.update("items", list => list.map(item => {
if (item.get("id") === action.id) {
return item.set("unread", false);
}
return item;
}));
case ACCOUNT_BLOCK_SUCCESS:
case ACCOUNT_MUTE_SUCCESS:
return filterConversations(state, [action.relationship.id]);
case DOMAIN_BLOCK_SUCCESS:
return filterConversations(state, action.accounts);
case CONVERSATIONS_DELETE_SUCCESS:
return state.update('items', list => list.filterNot(item => item.get('id') === action.id));
default:
return state;
return item;
}));
case ACCOUNT_BLOCK_SUCCESS:
case ACCOUNT_MUTE_SUCCESS:
return filterConversations(state, [action.relationship.id]);
case DOMAIN_BLOCK_SUCCESS:
return filterConversations(state, action.accounts);
case CONVERSATIONS_DELETE_SUCCESS:
return state.update("items", list => list.filterNot(item => item.get("id") === action.id));
default:
return state;
}
}
@@ -1,15 +1,15 @@
import { List as ImmutableList, fromJS as ConvertToImmutable } from 'immutable';
import { List as ImmutableList, fromJS as ConvertToImmutable } from "immutable";
import { CUSTOM_EMOJIS_FETCH_SUCCESS } from '../actions/custom_emojis';
import { buildCustomEmojis } from '../features/emoji/emoji';
import { search as emojiSearch } from '../features/emoji/emoji_mart_search_light';
import { CUSTOM_EMOJIS_FETCH_SUCCESS } from "../actions/custom_emojis";
import { buildCustomEmojis } from "../features/emoji/emoji";
import { search as emojiSearch } from "../features/emoji/emoji_mart_search_light";
const initialState = ImmutableList([]);
export default function custom_emojis(state = initialState, action) {
if(action.type === CUSTOM_EMOJIS_FETCH_SUCCESS) {
state = ConvertToImmutable(action.custom_emojis);
emojiSearch('', { custom: buildCustomEmojis(state) });
emojiSearch("", { custom: buildCustomEmojis(state) });
}
return state;
@@ -1,10 +1,10 @@
import { Map as ImmutableMap, OrderedSet as ImmutableOrderedSet } from 'immutable';
import { Map as ImmutableMap, OrderedSet as ImmutableOrderedSet } from "immutable";
import {
DOMAIN_BLOCKS_FETCH_SUCCESS,
DOMAIN_BLOCKS_EXPAND_SUCCESS,
DOMAIN_UNBLOCK_SUCCESS,
} from '../actions/domain_blocks';
} from "../actions/domain_blocks";
const initialState = ImmutableMap({
blocks: ImmutableMap({
@@ -14,13 +14,13 @@ const initialState = ImmutableMap({
export default function domainLists(state = initialState, action) {
switch(action.type) {
case DOMAIN_BLOCKS_FETCH_SUCCESS:
return state.setIn(['blocks', 'items'], ImmutableOrderedSet(action.domains)).setIn(['blocks', 'next'], action.next);
case DOMAIN_BLOCKS_EXPAND_SUCCESS:
return state.updateIn(['blocks', 'items'], set => set.union(action.domains)).setIn(['blocks', 'next'], action.next);
case DOMAIN_UNBLOCK_SUCCESS:
return state.updateIn(['blocks', 'items'], set => set.delete(action.domain));
default:
return state;
case DOMAIN_BLOCKS_FETCH_SUCCESS:
return state.setIn(["blocks", "items"], ImmutableOrderedSet(action.domains)).setIn(["blocks", "next"], action.next);
case DOMAIN_BLOCKS_EXPAND_SUCCESS:
return state.updateIn(["blocks", "items"], set => set.union(action.domains)).setIn(["blocks", "next"], action.next);
case DOMAIN_UNBLOCK_SUCCESS:
return state.updateIn(["blocks", "items"], set => set.delete(action.domain));
default:
return state;
}
}
@@ -1,11 +1,11 @@
import { createReducer } from '@reduxjs/toolkit';
import { createReducer } from "@reduxjs/toolkit";
import { closeDropdownMenu, openDropdownMenu } from '../actions/dropdown_menu';
import { closeDropdownMenu, openDropdownMenu } from "../actions/dropdown_menu";
interface DropdownMenuState {
openId: string | null;
keyboard: boolean;
scrollKey: string | null;
openId: string | null,
keyboard: boolean,
scrollKey: string | null,
}
const initialState: DropdownMenuState = {
+11 -11
View File
@@ -1,7 +1,7 @@
import { Map as ImmutableMap, is, fromJS } from 'immutable';
import { Map as ImmutableMap, is, fromJS } from "immutable";
import { FILTERS_FETCH_SUCCESS, FILTERS_CREATE_SUCCESS } from '../actions/filters';
import { FILTERS_IMPORT } from '../actions/importer';
import { FILTERS_FETCH_SUCCESS, FILTERS_CREATE_SUCCESS } from "../actions/filters";
import { FILTERS_IMPORT } from "../actions/importer";
const normalizeFilter = (state, filter) => {
const normalizedFilter = fromJS({
@@ -33,13 +33,13 @@ const normalizeFilters = (state, filters) => {
export default function filters(state = ImmutableMap(), action) {
switch(action.type) {
case FILTERS_CREATE_SUCCESS:
return normalizeFilter(state, action.filter);
case FILTERS_FETCH_SUCCESS:
return normalizeFilters(ImmutableMap(), action.filters);
case FILTERS_IMPORT:
return normalizeFilters(state, action.filters);
default:
return state;
case FILTERS_CREATE_SUCCESS:
return normalizeFilter(state, action.filter);
case FILTERS_FETCH_SUCCESS:
return normalizeFilters(ImmutableMap(), action.filters);
case FILTERS_IMPORT:
return normalizeFilters(state, action.filters);
default:
return state;
}
}
@@ -1,4 +1,4 @@
import { Map as ImmutableMap, List as ImmutableList, fromJS } from 'immutable';
import { Map as ImmutableMap, List as ImmutableList, fromJS } from "immutable";
import {
FOLLOWED_HASHTAGS_FETCH_REQUEST,
@@ -7,7 +7,7 @@ import {
FOLLOWED_HASHTAGS_EXPAND_REQUEST,
FOLLOWED_HASHTAGS_EXPAND_SUCCESS,
FOLLOWED_HASHTAGS_EXPAND_FAIL,
} from 'mastodon/actions/tags';
} from "mastodon/actions/tags";
const initialState = ImmutableMap({
items: ImmutableList(),
@@ -17,27 +17,27 @@ const initialState = ImmutableMap({
export default function followed_tags(state = initialState, action) {
switch(action.type) {
case FOLLOWED_HASHTAGS_FETCH_REQUEST:
return state.set('isLoading', true);
case FOLLOWED_HASHTAGS_FETCH_SUCCESS:
return state.withMutations(map => {
map.set('items', fromJS(action.followed_tags));
map.set('isLoading', false);
map.set('next', action.next);
});
case FOLLOWED_HASHTAGS_FETCH_FAIL:
return state.set('isLoading', false);
case FOLLOWED_HASHTAGS_EXPAND_REQUEST:
return state.set('isLoading', true);
case FOLLOWED_HASHTAGS_EXPAND_SUCCESS:
return state.withMutations(map => {
map.update('items', set => set.concat(fromJS(action.followed_tags)));
map.set('isLoading', false);
map.set('next', action.next);
});
case FOLLOWED_HASHTAGS_EXPAND_FAIL:
return state.set('isLoading', false);
default:
return state;
case FOLLOWED_HASHTAGS_FETCH_REQUEST:
return state.set("isLoading", true);
case FOLLOWED_HASHTAGS_FETCH_SUCCESS:
return state.withMutations(map => {
map.set("items", fromJS(action.followed_tags));
map.set("isLoading", false);
map.set("next", action.next);
});
case FOLLOWED_HASHTAGS_FETCH_FAIL:
return state.set("isLoading", false);
case FOLLOWED_HASHTAGS_EXPAND_REQUEST:
return state.set("isLoading", true);
case FOLLOWED_HASHTAGS_EXPAND_SUCCESS:
return state.withMutations(map => {
map.update("items", set => set.concat(fromJS(action.followed_tags)));
map.set("isLoading", false);
map.set("next", action.next);
});
case FOLLOWED_HASHTAGS_EXPAND_FAIL:
return state.set("isLoading", false);
default:
return state;
}
}
@@ -1,6 +1,6 @@
import { Map as ImmutableMap } from 'immutable';
import { Map as ImmutableMap } from "immutable";
import { HEIGHT_CACHE_SET, HEIGHT_CACHE_CLEAR } from '../actions/height_cache';
import { HEIGHT_CACHE_SET, HEIGHT_CACHE_CLEAR } from "../actions/height_cache";
const initialState = ImmutableMap();
@@ -14,11 +14,11 @@ const clearHeights = () => {
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;
case HEIGHT_CACHE_SET:
return setHeight(state, action.key, action.id, action.height);
case HEIGHT_CACHE_CLEAR:
return clearHeights();
default:
return state;
}
}
+16 -16
View File
@@ -1,6 +1,6 @@
import { Map as ImmutableMap, List as ImmutableList, fromJS } from 'immutable';
import { Map as ImmutableMap, List as ImmutableList, fromJS } from "immutable";
import { HISTORY_FETCH_REQUEST, HISTORY_FETCH_SUCCESS, HISTORY_FETCH_FAIL } from 'mastodon/actions/history';
import { HISTORY_FETCH_REQUEST, HISTORY_FETCH_SUCCESS, HISTORY_FETCH_FAIL } from "mastodon/actions/history";
const initialHistory = ImmutableMap({
loading: false,
@@ -11,19 +11,19 @@ const initialState = ImmutableMap();
export default function history(state = initialState, action) {
switch(action.type) {
case HISTORY_FETCH_REQUEST:
return state.update(action.statusId, initialHistory, history => history.withMutations(map => {
map.set('loading', true);
map.set('items', ImmutableList());
}));
case HISTORY_FETCH_SUCCESS:
return state.update(action.statusId, initialHistory, history => history.withMutations(map => {
map.set('loading', false);
map.set('items', fromJS(action.history.map((x, i) => ({ ...x, account: x.account.id, original: i === 0 })).reverse()));
}));
case HISTORY_FETCH_FAIL:
return state.update(action.statusId, initialHistory, history => history.set('loading', false));
default:
return state;
case HISTORY_FETCH_REQUEST:
return state.update(action.statusId, initialHistory, history => history.withMutations(map => {
map.set("loading", true);
map.set("items", ImmutableList());
}));
case HISTORY_FETCH_SUCCESS:
return state.update(action.statusId, initialHistory, history => history.withMutations(map => {
map.set("loading", false);
map.set("items", fromJS(action.history.map((x, i) => ({ ...x, account: x.account.id, original: i === 0 })).reverse()));
}));
case HISTORY_FETCH_FAIL:
return state.update(action.statusId, initialHistory, history => history.set("loading", false));
default:
return state;
}
}
+44 -44
View File
@@ -1,48 +1,48 @@
import { Record as ImmutableRecord } from 'immutable';
import { Record as ImmutableRecord } from "immutable";
import { loadingBarReducer } from 'react-redux-loading-bar';
import { combineReducers } from 'redux-immutable';
import { loadingBarReducer } from "react-redux-loading-bar";
import { combineReducers } from "redux-immutable";
import accounts from './accounts';
import accounts_counters from './accounts_counters';
import accounts_map from './accounts_map';
import alerts from './alerts';
import announcements from './announcements';
import blocks from './blocks';
import boosts from './boosts';
import compose from './compose';
import contexts from './contexts';
import conversations from './conversations';
import custom_emojis from './custom_emojis';
import domain_lists from './domain_lists';
import { dropdownMenuReducer } from './dropdown_menu';
import filters from './filters';
import followed_tags from './followed_tags';
import height_cache from './height_cache';
import history from './history';
import listAdder from './list_adder';
import listEditor from './list_editor';
import lists from './lists';
import markers from './markers';
import media_attachments from './media_attachments';
import meta from './meta';
import { modalReducer } from './modal';
import mutes from './mutes';
import notifications from './notifications';
import picture_in_picture from './picture_in_picture';
import polls from './polls';
import push_notifications from './push_notifications';
import relationships from './relationships';
import search from './search';
import server from './server';
import settings from './settings';
import status_lists from './status_lists';
import statuses from './statuses';
import suggestions from './suggestions';
import tags from './tags';
import timelines from './timelines';
import trends from './trends';
import user_lists from './user_lists';
import accounts from "./accounts";
import accounts_counters from "./accounts_counters";
import accounts_map from "./accounts_map";
import alerts from "./alerts";
import announcements from "./announcements";
import blocks from "./blocks";
import boosts from "./boosts";
import compose from "./compose";
import contexts from "./contexts";
import conversations from "./conversations";
import custom_emojis from "./custom_emojis";
import domain_lists from "./domain_lists";
import { dropdownMenuReducer } from "./dropdown_menu";
import filters from "./filters";
import followed_tags from "./followed_tags";
import height_cache from "./height_cache";
import history from "./history";
import listAdder from "./list_adder";
import listEditor from "./list_editor";
import lists from "./lists";
import markers from "./markers";
import media_attachments from "./media_attachments";
import meta from "./meta";
import { modalReducer } from "./modal";
import mutes from "./mutes";
import notifications from "./notifications";
import picture_in_picture from "./picture_in_picture";
import polls from "./polls";
import push_notifications from "./push_notifications";
import relationships from "./relationships";
import search from "./search";
import server from "./server";
import settings from "./settings";
import status_lists from "./status_lists";
import statuses from "./statuses";
import suggestions from "./suggestions";
import tags from "./tags";
import timelines from "./timelines";
import trends from "./trends";
import user_lists from "./user_lists";
const reducers = {
announcements,
@@ -102,7 +102,7 @@ const initialRootState = Object.fromEntries(
]),
);
const RootStateRecord = ImmutableRecord(initialRootState, 'RootState');
const RootStateRecord = ImmutableRecord(initialRootState, "RootState");
const rootReducer = combineReducers(reducers, RootStateRecord);
+24 -24
View File
@@ -1,4 +1,4 @@
import { Map as ImmutableMap, List as ImmutableList } from 'immutable';
import { Map as ImmutableMap, List as ImmutableList } from "immutable";
import {
LIST_ADDER_RESET,
@@ -8,7 +8,7 @@ import {
LIST_ADDER_LISTS_FETCH_FAIL,
LIST_EDITOR_ADD_SUCCESS,
LIST_EDITOR_REMOVE_SUCCESS,
} from '../actions/lists';
} from "../actions/lists";
const initialState = ImmutableMap({
accountId: null,
@@ -22,27 +22,27 @@ const initialState = ImmutableMap({
export default function listAdderReducer(state = initialState, action) {
switch(action.type) {
case LIST_ADDER_RESET:
return initialState;
case LIST_ADDER_SETUP:
return state.withMutations(map => {
map.set('accountId', action.account.get('id'));
});
case LIST_ADDER_LISTS_FETCH_REQUEST:
return state.setIn(['lists', 'isLoading'], true);
case LIST_ADDER_LISTS_FETCH_FAIL:
return state.setIn(['lists', 'isLoading'], false);
case LIST_ADDER_LISTS_FETCH_SUCCESS:
return state.update('lists', lists => lists.withMutations(map => {
map.set('isLoading', false);
map.set('loaded', true);
map.set('items', ImmutableList(action.lists.map(item => item.id)));
}));
case LIST_EDITOR_ADD_SUCCESS:
return state.updateIn(['lists', 'items'], list => list.unshift(action.listId));
case LIST_EDITOR_REMOVE_SUCCESS:
return state.updateIn(['lists', 'items'], list => list.filterNot(item => item === action.listId));
default:
return state;
case LIST_ADDER_RESET:
return initialState;
case LIST_ADDER_SETUP:
return state.withMutations(map => {
map.set("accountId", action.account.get("id"));
});
case LIST_ADDER_LISTS_FETCH_REQUEST:
return state.setIn(["lists", "isLoading"], true);
case LIST_ADDER_LISTS_FETCH_FAIL:
return state.setIn(["lists", "isLoading"], false);
case LIST_ADDER_LISTS_FETCH_SUCCESS:
return state.update("lists", lists => lists.withMutations(map => {
map.set("isLoading", false);
map.set("loaded", true);
map.set("items", ImmutableList(action.lists.map(item => item.id)));
}));
case LIST_EDITOR_ADD_SUCCESS:
return state.updateIn(["lists", "items"], list => list.unshift(action.listId));
case LIST_EDITOR_REMOVE_SUCCESS:
return state.updateIn(["lists", "items"], list => list.filterNot(item => item === action.listId));
default:
return state;
}
}
+58 -58
View File
@@ -1,4 +1,4 @@
import { Map as ImmutableMap, List as ImmutableList } from 'immutable';
import { Map as ImmutableMap, List as ImmutableList } from "immutable";
import {
LIST_CREATE_REQUEST,
@@ -18,13 +18,13 @@ import {
LIST_EDITOR_SUGGESTIONS_CHANGE,
LIST_EDITOR_ADD_SUCCESS,
LIST_EDITOR_REMOVE_SUCCESS,
} from '../actions/lists';
} from "../actions/lists";
const initialState = ImmutableMap({
listId: null,
isSubmitting: false,
isChanged: false,
title: '',
title: "",
isExclusive: false,
accounts: ImmutableMap({
@@ -34,66 +34,66 @@ const initialState = ImmutableMap({
}),
suggestions: ImmutableMap({
value: '',
value: "",
items: ImmutableList(),
}),
});
export default function listEditorReducer(state = initialState, action) {
switch(action.type) {
case LIST_EDITOR_RESET:
return initialState;
case LIST_EDITOR_SETUP:
return state.withMutations(map => {
map.set('listId', action.list.get('id'));
map.set('title', action.list.get('title'));
map.set('isExclusive', action.list.get('is_exclusive'));
map.set('isSubmitting', false);
});
case LIST_EDITOR_TITLE_CHANGE:
return state.withMutations(map => {
map.set('title', action.value);
map.set('isChanged', true);
});
case LIST_CREATE_REQUEST:
case LIST_UPDATE_REQUEST:
return state.withMutations(map => {
map.set('isSubmitting', true);
map.set('isChanged', false);
});
case LIST_CREATE_FAIL:
case LIST_UPDATE_FAIL:
return state.set('isSubmitting', false);
case LIST_CREATE_SUCCESS:
case LIST_UPDATE_SUCCESS:
return state.withMutations(map => {
map.set('isSubmitting', false);
map.set('listId', action.list.id);
});
case LIST_ACCOUNTS_FETCH_REQUEST:
return state.setIn(['accounts', 'isLoading'], true);
case LIST_ACCOUNTS_FETCH_FAIL:
return state.setIn(['accounts', 'isLoading'], false);
case LIST_ACCOUNTS_FETCH_SUCCESS:
return state.update('accounts', accounts => accounts.withMutations(map => {
map.set('isLoading', false);
map.set('loaded', true);
map.set('items', ImmutableList(action.accounts.map(item => item.id)));
}));
case LIST_EDITOR_SUGGESTIONS_CHANGE:
return state.setIn(['suggestions', 'value'], action.value);
case LIST_EDITOR_SUGGESTIONS_READY:
return state.setIn(['suggestions', 'items'], ImmutableList(action.accounts.map(item => item.id)));
case LIST_EDITOR_SUGGESTIONS_CLEAR:
return state.update('suggestions', suggestions => suggestions.withMutations(map => {
map.set('items', ImmutableList());
map.set('value', '');
}));
case LIST_EDITOR_ADD_SUCCESS:
return state.updateIn(['accounts', 'items'], list => list.unshift(action.accountId));
case LIST_EDITOR_REMOVE_SUCCESS:
return state.updateIn(['accounts', 'items'], list => list.filterNot(item => item === action.accountId));
default:
return state;
case LIST_EDITOR_RESET:
return initialState;
case LIST_EDITOR_SETUP:
return state.withMutations(map => {
map.set("listId", action.list.get("id"));
map.set("title", action.list.get("title"));
map.set("isExclusive", action.list.get("is_exclusive"));
map.set("isSubmitting", false);
});
case LIST_EDITOR_TITLE_CHANGE:
return state.withMutations(map => {
map.set("title", action.value);
map.set("isChanged", true);
});
case LIST_CREATE_REQUEST:
case LIST_UPDATE_REQUEST:
return state.withMutations(map => {
map.set("isSubmitting", true);
map.set("isChanged", false);
});
case LIST_CREATE_FAIL:
case LIST_UPDATE_FAIL:
return state.set("isSubmitting", false);
case LIST_CREATE_SUCCESS:
case LIST_UPDATE_SUCCESS:
return state.withMutations(map => {
map.set("isSubmitting", false);
map.set("listId", action.list.id);
});
case LIST_ACCOUNTS_FETCH_REQUEST:
return state.setIn(["accounts", "isLoading"], true);
case LIST_ACCOUNTS_FETCH_FAIL:
return state.setIn(["accounts", "isLoading"], false);
case LIST_ACCOUNTS_FETCH_SUCCESS:
return state.update("accounts", accounts => accounts.withMutations(map => {
map.set("isLoading", false);
map.set("loaded", true);
map.set("items", ImmutableList(action.accounts.map(item => item.id)));
}));
case LIST_EDITOR_SUGGESTIONS_CHANGE:
return state.setIn(["suggestions", "value"], action.value);
case LIST_EDITOR_SUGGESTIONS_READY:
return state.setIn(["suggestions", "items"], ImmutableList(action.accounts.map(item => item.id)));
case LIST_EDITOR_SUGGESTIONS_CLEAR:
return state.update("suggestions", suggestions => suggestions.withMutations(map => {
map.set("items", ImmutableList());
map.set("value", "");
}));
case LIST_EDITOR_ADD_SUCCESS:
return state.updateIn(["accounts", "items"], list => list.unshift(action.accountId));
case LIST_EDITOR_REMOVE_SUCCESS:
return state.updateIn(["accounts", "items"], list => list.filterNot(item => item === action.accountId));
default:
return state;
}
}
+13 -13
View File
@@ -1,4 +1,4 @@
import { Map as ImmutableMap, fromJS } from 'immutable';
import { Map as ImmutableMap, fromJS } from "immutable";
import {
LIST_FETCH_SUCCESS,
@@ -7,7 +7,7 @@ import {
LIST_CREATE_SUCCESS,
LIST_UPDATE_SUCCESS,
LIST_DELETE_SUCCESS,
} from '../actions/lists';
} from "../actions/lists";
const initialState = ImmutableMap();
@@ -23,16 +23,16 @@ const normalizeLists = (state, lists) => {
export default function lists(state = initialState, action) {
switch(action.type) {
case LIST_FETCH_SUCCESS:
case LIST_CREATE_SUCCESS:
case LIST_UPDATE_SUCCESS:
return normalizeList(state, action.list);
case LISTS_FETCH_SUCCESS:
return normalizeLists(state, action.lists);
case LIST_DELETE_SUCCESS:
case LIST_FETCH_FAIL:
return state.set(action.id, false);
default:
return state;
case LIST_FETCH_SUCCESS:
case LIST_CREATE_SUCCESS:
case LIST_UPDATE_SUCCESS:
return normalizeList(state, action.list);
case LISTS_FETCH_SUCCESS:
return normalizeLists(state, action.lists);
case LIST_DELETE_SUCCESS:
case LIST_FETCH_FAIL:
return state.set(action.id, false);
default:
return state;
}
}
+14 -14
View File
@@ -1,26 +1,26 @@
import { Map as ImmutableMap } from 'immutable';
import { Map as ImmutableMap } from "immutable";
import {
MARKERS_SUBMIT_SUCCESS,
} from '../actions/markers';
} from "../actions/markers";
const initialState = ImmutableMap({
home: '0',
notifications: '0',
home: "0",
notifications: "0",
});
export default function markers(state = initialState, action) {
switch(action.type) {
case MARKERS_SUBMIT_SUCCESS:
if (action.home) {
state = state.set('home', action.home);
}
if (action.notifications) {
state = state.set('notifications', action.notifications);
}
return state;
default:
return state;
case MARKERS_SUBMIT_SUCCESS:
if (action.home) {
state = state.set("home", action.home);
}
if (action.notifications) {
state = state.set("notifications", action.notifications);
}
return state;
default:
return state;
}
}
@@ -1,6 +1,6 @@
import { Map as ImmutableMap } from 'immutable';
import { Map as ImmutableMap } from "immutable";
import { STORE_HYDRATE } from '../actions/store';
import { STORE_HYDRATE } from "../actions/store";
const initialState = ImmutableMap({
accept_content_types: [],
@@ -8,9 +8,9 @@ const initialState = ImmutableMap({
export default function meta(state = initialState, action) {
switch(action.type) {
case STORE_HYDRATE:
return state.merge(action.state.get('media_attachments'));
default:
return state;
case STORE_HYDRATE:
return state.merge(action.state.get("media_attachments"));
default:
return state;
}
}
+11 -11
View File
@@ -1,23 +1,23 @@
import { Map as ImmutableMap } from 'immutable';
import { Map as ImmutableMap } from "immutable";
import { changeLayout } from 'mastodon/actions/app';
import { STORE_HYDRATE } from 'mastodon/actions/store';
import { layoutFromWindow } from 'mastodon/is_mobile';
import { changeLayout } from "mastodon/actions/app";
import { STORE_HYDRATE } from "mastodon/actions/store";
import { layoutFromWindow } from "mastodon/is_mobile";
const initialState = ImmutableMap({
streaming_api_base_url: null,
access_token: null,
layout: layoutFromWindow(),
permissions: '0',
permissions: "0",
});
export default function meta(state = initialState, action) {
switch(action.type) {
case STORE_HYDRATE:
return state.merge(action.state.get('meta')).set('permissions', action.state.getIn(['role', 'permissions']));
case changeLayout.type:
return state.set('layout', action.payload.layout);
default:
return state;
case STORE_HYDRATE:
return state.merge(action.state.get("meta")).set("permissions", action.state.getIn(["role", "permissions"]));
case changeLayout.type:
return state.set("layout", action.payload.layout);
default:
return state;
}
}
+29 -27
View File
@@ -1,26 +1,26 @@
import { Record as ImmutableRecord, Stack } from 'immutable';
import { Record as ImmutableRecord, Stack } from "immutable";
import type { Reducer } from '@reduxjs/toolkit';
import { type Reducer } from "@reduxjs/toolkit";
import { COMPOSE_UPLOAD_CHANGE_SUCCESS } from '../actions/compose';
import type { ModalType } from '../actions/modal';
import { openModal, closeModal } from '../actions/modal';
import { TIMELINE_DELETE } from '../actions/timelines';
import { COMPOSE_UPLOAD_CHANGE_SUCCESS } from "../actions/compose";
import { type ModalType } from "../actions/modal";
import { openModal, closeModal } from "../actions/modal";
import { TIMELINE_DELETE } from "../actions/timelines";
export type ModalProps = Record<string, unknown>;
interface Modal {
modalType: ModalType;
modalProps: ModalProps;
modalType: ModalType,
modalProps: ModalProps,
}
const Modal = ImmutableRecord<Modal>({
modalType: 'ACTIONS',
modalType: "ACTIONS",
modalProps: ImmutableRecord({})(),
});
interface ModalState {
ignoreFocus: boolean;
stack: Stack<ImmutableRecord<Modal>>;
ignoreFocus: boolean,
stack: Stack<ImmutableRecord<Modal>>,
}
const initialState = ImmutableRecord<ModalState>({
@@ -30,8 +30,8 @@ const initialState = ImmutableRecord<ModalState>({
type State = typeof initialState;
interface PopModalOption {
modalType: ModalType | undefined;
ignoreFocus: boolean;
modalType: ModalType | undefined,
ignoreFocus: boolean,
}
const popModal = (
state: State,
@@ -39,11 +39,11 @@ const popModal = (
): State => {
if (
modalType === undefined ||
modalType === state.get('stack').get(0)?.get('modalType')
modalType === state.get("stack").get(0)?.get("modalType")
) {
return state
.set('ignoreFocus', !!ignoreFocus)
.update('stack', (stack) => stack.shift());
.set("ignoreFocus", ignoreFocus)
.update("stack", (stack) => stack.shift());
} else {
return state;
}
@@ -55,29 +55,31 @@ const pushModal = (
modalProps: ModalProps,
): State => {
return state.withMutations((record) => {
record.set('ignoreFocus', false);
record.update('stack', (stack) =>
record.set("ignoreFocus", false);
record.update("stack", (stack) =>
stack.unshift(Modal({ modalType, modalProps })),
);
});
};
export const modalReducer: Reducer<State> = (state = initialState, action) => {
if (openModal.match(action))
if (openModal.match(action)) {
return pushModal(
state,
action.payload.modalType,
action.payload.modalProps,
);
else if (closeModal.match(action)) return popModal(state, action.payload);
// TODO: type those actions
else if (action.type === COMPOSE_UPLOAD_CHANGE_SUCCESS)
return popModal(state, { modalType: 'FOCAL_POINT', ignoreFocus: false });
else if (action.type === TIMELINE_DELETE)
return state.update('stack', (stack) =>
} else if (closeModal.match(action)) {
return popModal(state, action.payload);
} else if (action.type === COMPOSE_UPLOAD_CHANGE_SUCCESS) {
return popModal(state, { modalType: "FOCAL_POINT", ignoreFocus: false });
} else if (action.type === TIMELINE_DELETE) {
return state.update("stack", (stack) =>
stack.filterNot(
(modal) => modal.get('modalProps').statusId === action.id,
(modal) => modal.get("modalProps").statusId === action.id,
),
);
else return state;
} else {
return state;
}
};
+13 -13
View File
@@ -1,10 +1,10 @@
import Immutable from 'immutable';
import Immutable from "immutable";
import {
MUTES_INIT_MODAL,
MUTES_TOGGLE_HIDE_NOTIFICATIONS,
MUTES_CHANGE_DURATION,
} from '../actions/mutes';
} from "../actions/mutes";
const initialState = Immutable.Map({
new: Immutable.Map({
@@ -16,16 +16,16 @@ const initialState = Immutable.Map({
export default function mutes(state = initialState, action) {
switch (action.type) {
case MUTES_INIT_MODAL:
return state.withMutations((state) => {
state.setIn(['new', 'account'], action.account);
state.setIn(['new', 'notifications'], true);
});
case MUTES_TOGGLE_HIDE_NOTIFICATIONS:
return state.updateIn(['new', 'notifications'], (old) => !old);
case MUTES_CHANGE_DURATION:
return state.setIn(['new', 'duration'], Number(action.duration));
default:
return state;
case MUTES_INIT_MODAL:
return state.withMutations((state) => {
state.setIn(["new", "account"], action.account);
state.setIn(["new", "notifications"], true);
});
case MUTES_TOGGLE_HIDE_NOTIFICATIONS:
return state.updateIn(["new", "notifications"], (old) => !old);
case MUTES_CHANGE_DURATION:
return state.setIn(["new", "duration"], Number(action.duration));
default:
return state;
}
}
+115 -115
View File
@@ -1,20 +1,20 @@
import { fromJS, Map as ImmutableMap, List as ImmutableList } from 'immutable';
import { fromJS, Map as ImmutableMap, List as ImmutableList } from "immutable";
import { DOMAIN_BLOCK_SUCCESS } from 'mastodon/actions/domain_blocks';
import { DOMAIN_BLOCK_SUCCESS } from "mastodon/actions/domain_blocks";
import {
ACCOUNT_BLOCK_SUCCESS,
ACCOUNT_MUTE_SUCCESS,
FOLLOW_REQUEST_AUTHORIZE_SUCCESS,
FOLLOW_REQUEST_REJECT_SUCCESS,
} from '../actions/accounts';
} from "../actions/accounts";
import {
focusApp,
unfocusApp,
} from '../actions/app';
} from "../actions/app";
import {
MARKERS_FETCH_SUCCESS,
} from '../actions/markers';
} from "../actions/markers";
import {
NOTIFICATIONS_UPDATE,
NOTIFICATIONS_EXPAND_SUCCESS,
@@ -29,9 +29,9 @@ import {
NOTIFICATIONS_MARK_AS_READ,
NOTIFICATIONS_SET_BROWSER_SUPPORT,
NOTIFICATIONS_SET_BROWSER_PERMISSION,
} from '../actions/notifications';
import { TIMELINE_DELETE, TIMELINE_DISCONNECT } from '../actions/timelines';
import { compareId } from '../compare_id';
} from "../actions/notifications";
import { TIMELINE_DELETE, TIMELINE_DISCONNECT } from "../actions/timelines";
import { compareId } from "../compare_id";
const initialState = ImmutableMap({
pendingItems: ImmutableList(),
@@ -40,12 +40,12 @@ const initialState = ImmutableMap({
top: false,
mounted: 0,
unread: 0,
lastReadId: '0',
readMarkerId: '0',
lastReadId: "0",
readMarkerId: "0",
isTabVisible: true,
isLoading: 0,
browserSupport: false,
browserPermission: 'default',
browserPermission: "default",
});
const notificationToMap = notification => ImmutableMap({
@@ -58,24 +58,24 @@ const notificationToMap = notification => ImmutableMap({
});
const normalizeNotification = (state, notification, usePendingItems) => {
const top = state.get('top');
const top = state.get("top");
// Under currently unknown conditions, the client may receive duplicates from the server
if (state.get('pendingItems').some((item) => item?.get('id') === notification.id) || state.get('items').some((item) => item?.get('id') === notification.id)) {
if (state.get("pendingItems").some((item) => item?.get("id") === notification.id) || state.get("items").some((item) => item?.get("id") === notification.id)) {
return state;
}
if (usePendingItems || !state.get('pendingItems').isEmpty()) {
return state.update('pendingItems', list => list.unshift(notificationToMap(notification))).update('unread', unread => unread + 1);
if (usePendingItems || !state.get("pendingItems").isEmpty()) {
return state.update("pendingItems", list => list.unshift(notificationToMap(notification))).update("unread", unread => unread + 1);
}
if (shouldCountUnreadNotifications(state)) {
state = state.update('unread', unread => unread + 1);
state = state.update("unread", unread => unread + 1);
} else {
state = state.set('lastReadId', notification.id);
state = state.set("lastReadId", notification.id);
}
return state.update('items', list => {
return state.update("items", list => {
if (top && list.size > 40) {
list = list.take(20);
}
@@ -92,26 +92,26 @@ const expandNormalizedNotifications = (state, notifications, next, isLoadingMore
// - `notifications` may include items that are already included
// - this function can be called either to fill in a gap, or load newer items
const lastReadId = state.get('lastReadId');
const lastReadId = state.get("lastReadId");
const newItems = ImmutableList(notifications.map(notificationToMap));
return state.withMutations(mutable => {
if (!newItems.isEmpty()) {
usePendingItems = isLoadingRecent && (usePendingItems || !mutable.get('pendingItems').isEmpty());
usePendingItems = isLoadingRecent && (usePendingItems || !mutable.get("pendingItems").isEmpty());
mutable.update(usePendingItems ? 'pendingItems' : 'items', oldItems => {
mutable.update(usePendingItems ? "pendingItems" : "items", oldItems => {
// If called to poll *new* notifications, we just need to add them on top without duplicates
if (isLoadingRecent) {
const idsToCheck = oldItems.map(item => item?.get('id')).toSet();
const insertedItems = newItems.filterNot(item => idsToCheck.includes(item.get('id')));
const idsToCheck = oldItems.map(item => item?.get("id")).toSet();
const insertedItems = newItems.filterNot(item => idsToCheck.includes(item.get("id")));
return insertedItems.concat(oldItems);
}
// If called to expand more (presumably older than any known to the WebUI), we just have to
// add them to the bottom without duplicates
if (isLoadingMore) {
const idsToCheck = oldItems.map(item => item?.get('id')).toSet();
const insertedItems = newItems.filterNot(item => idsToCheck.includes(item.get('id')));
const idsToCheck = oldItems.map(item => item?.get("id")).toSet();
const insertedItems = newItems.filterNot(item => idsToCheck.includes(item.get("id")));
return oldItems.concat(insertedItems);
}
@@ -124,14 +124,14 @@ const expandNormalizedNotifications = (state, notifications, next, isLoadingMore
// First, find the furthest (if properly sorted, oldest) item in the notifications that is
// newer than the oldest fetched one, as it's most likely that it delimits the gap.
// Start the gap *after* that item.
const lastIndex = oldItems.findLastIndex(item => item !== null && compareId(item.get('id'), newItems.last().get('id')) >= 0) + 1;
const lastIndex = oldItems.findLastIndex(item => item !== null && compareId(item.get("id"), newItems.last().get("id")) >= 0) + 1;
// Then, try to find the furthest (if properly sorted, oldest) item in the notifications that
// is newer than the most recent fetched one, as it delimits a section comprised of only
// items older or within `newItems` (or that were deleted from the server, so should be removed
// anyway).
// Stop the gap *after* that item.
const firstIndex = oldItems.take(lastIndex).findLastIndex(item => item !== null && compareId(item.get('id'), newItems.first().get('id')) > 0) + 1;
const firstIndex = oldItems.take(lastIndex).findLastIndex(item => item !== null && compareId(item.get("id"), newItems.first().get("id")) > 0) + 1;
// At this point:
// - no `oldItems` after `firstIndex` is newer than any of the `newItems`
@@ -143,9 +143,9 @@ const expandNormalizedNotifications = (state, notifications, next, isLoadingMore
// should be added in the back.
// - to avoid duplicates, `newItems` should be checked the first `firstIndex` items of
// `oldItems`
const idsToCheck = oldItems.take(firstIndex).map(item => item?.get('id')).toSet();
const insertedItems = newItems.filterNot(item => idsToCheck.includes(item.get('id')));
const olderItems = oldItems.slice(firstIndex, lastIndex).filter(item => item !== null && compareId(item.get('id'), newItems.last().get('id')) < 0);
const idsToCheck = oldItems.take(firstIndex).map(item => item?.get("id")).toSet();
const insertedItems = newItems.filterNot(item => idsToCheck.includes(item.get("id")));
const olderItems = oldItems.slice(firstIndex, lastIndex).filter(item => item !== null && compareId(item.get("id"), newItems.last().get("id")) < 0);
return oldItems.take(firstIndex).concat(
insertedItems,
@@ -156,35 +156,35 @@ const expandNormalizedNotifications = (state, notifications, next, isLoadingMore
}
if (!next) {
mutable.set('hasMore', false);
mutable.set("hasMore", false);
}
if (shouldCountUnreadNotifications(state)) {
mutable.set('unread', mutable.get('pendingItems').count(item => item !== null) + mutable.get('items').count(item => item && compareId(item.get('id'), lastReadId) > 0));
mutable.set("unread", mutable.get("pendingItems").count(item => item !== null) + mutable.get("items").count(item => item && compareId(item.get("id"), lastReadId) > 0));
} else {
const mostRecent = newItems.find(item => item !== null);
if (mostRecent && compareId(lastReadId, mostRecent.get('id')) < 0) {
mutable.set('lastReadId', mostRecent.get('id'));
if (mostRecent && compareId(lastReadId, mostRecent.get("id")) < 0) {
mutable.set("lastReadId", mostRecent.get("id"));
}
}
mutable.update('isLoading', (nbLoading) => nbLoading - 1);
mutable.update("isLoading", (nbLoading) => nbLoading - 1);
});
};
const filterNotifications = (state, accountIds, type) => {
const helper = list => list.filterNot(item => item !== null && accountIds.includes(item.get('account')) && (type === undefined || type === item.get('type')));
return state.update('items', helper).update('pendingItems', helper);
const helper = list => list.filterNot(item => item !== null && accountIds.includes(item.get("account")) && (type === undefined || type === item.get("type")));
return state.update("items", helper).update("pendingItems", helper);
};
const clearUnread = (state) => {
state = state.set('unread', state.get('pendingItems').size);
const lastNotification = state.get('items').find(item => item !== null);
return state.set('lastReadId', lastNotification ? lastNotification.get('id') : '0');
state = state.set("unread", state.get("pendingItems").size);
const lastNotification = state.get("items").find(item => item !== null);
return state.set("lastReadId", lastNotification ? lastNotification.get("id") : "0");
};
const updateTop = (state, top) => {
state = state.set('top', top);
state = state.set("top", top);
if (!shouldCountUnreadNotifications(state)) {
state = clearUnread(state);
@@ -194,115 +194,115 @@ const updateTop = (state, top) => {
};
const deleteByStatus = (state, statusId) => {
const lastReadId = state.get('lastReadId');
const lastReadId = state.get("lastReadId");
if (shouldCountUnreadNotifications(state)) {
const deletedUnread = state.get('items').filter(item => item !== null && item.get('status') === statusId && compareId(item.get('id'), lastReadId) > 0);
state = state.update('unread', unread => unread - deletedUnread.size);
const deletedUnread = state.get("items").filter(item => item !== null && item.get("status") === statusId && compareId(item.get("id"), lastReadId) > 0);
state = state.update("unread", unread => unread - deletedUnread.size);
}
const helper = list => list.filterNot(item => item !== null && item.get('status') === statusId);
const deletedUnread = state.get('pendingItems').filter(item => item !== null && item.get('status') === statusId && compareId(item.get('id'), lastReadId) > 0);
state = state.update('unread', unread => unread - deletedUnread.size);
return state.update('items', helper).update('pendingItems', helper);
const helper = list => list.filterNot(item => item !== null && item.get("status") === statusId);
const deletedUnread = state.get("pendingItems").filter(item => item !== null && item.get("status") === statusId && compareId(item.get("id"), lastReadId) > 0);
state = state.update("unread", unread => unread - deletedUnread.size);
return state.update("items", helper).update("pendingItems", helper);
};
const updateMounted = (state) => {
state = state.update('mounted', count => count + 1);
if (!shouldCountUnreadNotifications(state, state.get('mounted') === 1)) {
state = state.set('readMarkerId', state.get('lastReadId'));
state = state.update("mounted", count => count + 1);
if (!shouldCountUnreadNotifications(state, state.get("mounted") === 1)) {
state = state.set("readMarkerId", state.get("lastReadId"));
state = clearUnread(state);
}
return state;
};
const updateVisibility = (state, visibility) => {
state = state.set('isTabVisible', visibility);
state = state.set("isTabVisible", visibility);
if (!shouldCountUnreadNotifications(state)) {
state = state.set('readMarkerId', state.get('lastReadId'));
state = state.set("readMarkerId", state.get("lastReadId"));
state = clearUnread(state);
}
return state;
};
const shouldCountUnreadNotifications = (state, ignoreScroll = false) => {
const isTabVisible = state.get('isTabVisible');
const isOnTop = state.get('top');
const isMounted = state.get('mounted') > 0;
const lastReadId = state.get('lastReadId');
const lastItem = state.get('items').findLast(item => item !== null);
const lastItemReached = !state.get('hasMore') || lastReadId === '0' || (lastItem && compareId(lastItem.get('id'), lastReadId) <= 0);
const isTabVisible = state.get("isTabVisible");
const isOnTop = state.get("top");
const isMounted = state.get("mounted") > 0;
const lastReadId = state.get("lastReadId");
const lastItem = state.get("items").findLast(item => item !== null);
const lastItemReached = !state.get("hasMore") || lastReadId === "0" || (lastItem && compareId(lastItem.get("id"), lastReadId) <= 0);
return !(isTabVisible && (ignoreScroll || isOnTop) && isMounted && lastItemReached);
};
const recountUnread = (state, last_read_id) => {
return state.withMutations(mutable => {
if (compareId(last_read_id, mutable.get('lastReadId')) > 0) {
mutable.set('lastReadId', last_read_id);
if (compareId(last_read_id, mutable.get("lastReadId")) > 0) {
mutable.set("lastReadId", last_read_id);
}
if (compareId(last_read_id, mutable.get('readMarkerId')) > 0) {
mutable.set('readMarkerId', last_read_id);
if (compareId(last_read_id, mutable.get("readMarkerId")) > 0) {
mutable.set("readMarkerId", last_read_id);
}
if (state.get('unread') > 0 || shouldCountUnreadNotifications(state)) {
mutable.set('unread', mutable.get('pendingItems').count(item => item !== null) + mutable.get('items').count(item => item && compareId(item.get('id'), last_read_id) > 0));
if (state.get("unread") > 0 || shouldCountUnreadNotifications(state)) {
mutable.set("unread", mutable.get("pendingItems").count(item => item !== null) + mutable.get("items").count(item => item && compareId(item.get("id"), last_read_id) > 0));
}
});
};
export default function notifications(state = initialState, action) {
switch(action.type) {
case MARKERS_FETCH_SUCCESS:
return action.markers.notifications ? recountUnread(state, action.markers.notifications.last_read_id) : state;
case NOTIFICATIONS_MOUNT:
return updateMounted(state);
case NOTIFICATIONS_UNMOUNT:
return state.update('mounted', count => count - 1);
case focusApp.type:
return updateVisibility(state, true);
case unfocusApp.type:
return updateVisibility(state, false);
case NOTIFICATIONS_LOAD_PENDING:
return state.update('items', list => state.get('pendingItems').concat(list.take(40))).set('pendingItems', ImmutableList()).set('unread', 0);
case NOTIFICATIONS_EXPAND_REQUEST:
return state.update('isLoading', (nbLoading) => nbLoading + 1);
case NOTIFICATIONS_EXPAND_FAIL:
return state.update('isLoading', (nbLoading) => nbLoading - 1);
case NOTIFICATIONS_FILTER_SET:
return state.set('items', ImmutableList()).set('pendingItems', ImmutableList()).set('hasMore', true);
case NOTIFICATIONS_SCROLL_TOP:
return updateTop(state, action.top);
case NOTIFICATIONS_UPDATE:
return normalizeNotification(state, action.notification, action.usePendingItems);
case NOTIFICATIONS_EXPAND_SUCCESS:
return expandNormalizedNotifications(state, action.notifications, action.next, action.isLoadingMore, action.isLoadingRecent, action.usePendingItems);
case ACCOUNT_BLOCK_SUCCESS:
return filterNotifications(state, [action.relationship.id]);
case ACCOUNT_MUTE_SUCCESS:
return action.relationship.muting_notifications ? filterNotifications(state, [action.relationship.id]) : state;
case DOMAIN_BLOCK_SUCCESS:
return filterNotifications(state, action.accounts);
case FOLLOW_REQUEST_AUTHORIZE_SUCCESS:
case FOLLOW_REQUEST_REJECT_SUCCESS:
return filterNotifications(state, [action.id], 'follow_request');
case NOTIFICATIONS_CLEAR:
return state.set('items', ImmutableList()).set('pendingItems', ImmutableList()).set('hasMore', false);
case TIMELINE_DELETE:
return deleteByStatus(state, action.id);
case TIMELINE_DISCONNECT:
return action.timeline === 'home' ?
state.update(action.usePendingItems ? 'pendingItems' : 'items', items => items.first() ? items.unshift(null) : items) :
state;
case NOTIFICATIONS_MARK_AS_READ:
const lastNotification = state.get('items').find(item => item !== null);
return lastNotification ? recountUnread(state, lastNotification.get('id')) : state;
case NOTIFICATIONS_SET_BROWSER_SUPPORT:
return state.set('browserSupport', action.value);
case NOTIFICATIONS_SET_BROWSER_PERMISSION:
return state.set('browserPermission', action.value);
default:
return state;
case MARKERS_FETCH_SUCCESS:
return action.markers.notifications ? recountUnread(state, action.markers.notifications.last_read_id) : state;
case NOTIFICATIONS_MOUNT:
return updateMounted(state);
case NOTIFICATIONS_UNMOUNT:
return state.update("mounted", count => count - 1);
case focusApp.type:
return updateVisibility(state, true);
case unfocusApp.type:
return updateVisibility(state, false);
case NOTIFICATIONS_LOAD_PENDING:
return state.update("items", list => state.get("pendingItems").concat(list.take(40))).set("pendingItems", ImmutableList()).set("unread", 0);
case NOTIFICATIONS_EXPAND_REQUEST:
return state.update("isLoading", (nbLoading) => nbLoading + 1);
case NOTIFICATIONS_EXPAND_FAIL:
return state.update("isLoading", (nbLoading) => nbLoading - 1);
case NOTIFICATIONS_FILTER_SET:
return state.set("items", ImmutableList()).set("pendingItems", ImmutableList()).set("hasMore", true);
case NOTIFICATIONS_SCROLL_TOP:
return updateTop(state, action.top);
case NOTIFICATIONS_UPDATE:
return normalizeNotification(state, action.notification, action.usePendingItems);
case NOTIFICATIONS_EXPAND_SUCCESS:
return expandNormalizedNotifications(state, action.notifications, action.next, action.isLoadingMore, action.isLoadingRecent, action.usePendingItems);
case ACCOUNT_BLOCK_SUCCESS:
return filterNotifications(state, [action.relationship.id]);
case ACCOUNT_MUTE_SUCCESS:
return action.relationship.muting_notifications ? filterNotifications(state, [action.relationship.id]) : state;
case DOMAIN_BLOCK_SUCCESS:
return filterNotifications(state, action.accounts);
case FOLLOW_REQUEST_AUTHORIZE_SUCCESS:
case FOLLOW_REQUEST_REJECT_SUCCESS:
return filterNotifications(state, [action.id], "follow_request");
case NOTIFICATIONS_CLEAR:
return state.set("items", ImmutableList()).set("pendingItems", ImmutableList()).set("hasMore", false);
case TIMELINE_DELETE:
return deleteByStatus(state, action.id);
case TIMELINE_DISCONNECT:
return action.timeline === "home" ?
state.update(action.usePendingItems ? "pendingItems" : "items", items => items.first() ? items.unshift(null) : items) :
state;
case NOTIFICATIONS_MARK_AS_READ:
const lastNotification = state.get("items").find(item => item !== null);
return lastNotification ? recountUnread(state, lastNotification.get("id")) : state;
case NOTIFICATIONS_SET_BROWSER_SUPPORT:
return state.set("browserSupport", action.value);
case NOTIFICATIONS_SET_BROWSER_PERMISSION:
return state.set("browserPermission", action.value);
default:
return state;
}
}
@@ -1,6 +1,6 @@
import { PICTURE_IN_PICTURE_DEPLOY, PICTURE_IN_PICTURE_REMOVE } from 'mastodon/actions/picture_in_picture';
import { PICTURE_IN_PICTURE_DEPLOY, PICTURE_IN_PICTURE_REMOVE } from "mastodon/actions/picture_in_picture";
import { TIMELINE_DELETE } from '../actions/timelines';
import { TIMELINE_DELETE } from "../actions/timelines";
const initialState = {
statusId: null,
@@ -14,13 +14,13 @@ const initialState = {
export default function pictureInPicture(state = initialState, action) {
switch(action.type) {
case PICTURE_IN_PICTURE_DEPLOY:
return { statusId: action.statusId, accountId: action.accountId, type: action.playerType, ...action.props };
case PICTURE_IN_PICTURE_REMOVE:
return { ...initialState };
case TIMELINE_DELETE:
return (state.statusId === action.id) ? { ...initialState } : state;
default:
return state;
case PICTURE_IN_PICTURE_DEPLOY:
return { statusId: action.statusId, accountId: action.accountId, type: action.playerType, ...action.props };
case PICTURE_IN_PICTURE_REMOVE:
return { ...initialState };
case TIMELINE_DELETE:
return (state.statusId === action.id) ? { ...initialState } : state;
default:
return state;
}
}
+15 -15
View File
@@ -1,9 +1,9 @@
import { Map as ImmutableMap, fromJS } from 'immutable';
import { Map as ImmutableMap, fromJS } from "immutable";
import { POLLS_IMPORT } from 'mastodon/actions/importer';
import { POLLS_IMPORT } from "mastodon/actions/importer";
import { normalizePollOptionTranslation } from '../actions/importer/normalizer';
import { STATUS_TRANSLATE_SUCCESS, STATUS_TRANSLATE_UNDO } from '../actions/statuses';
import { normalizePollOptionTranslation } from "../actions/importer/normalizer";
import { STATUS_TRANSLATE_SUCCESS, STATUS_TRANSLATE_UNDO } from "../actions/statuses";
const importPolls = (state, polls) => state.withMutations(map => polls.forEach(poll => map.set(poll.id, fromJS(poll))));
@@ -13,7 +13,7 @@ const statusTranslateSuccess = (state, pollTranslation) => {
const poll = state.get(pollTranslation.id);
pollTranslation.options.forEach((item, index) => {
map.setIn([pollTranslation.id, 'options', index, 'translation'], fromJS(normalizePollOptionTranslation(item, poll)));
map.setIn([pollTranslation.id, "options", index, "translation"], fromJS(normalizePollOptionTranslation(item, poll)));
});
}
});
@@ -21,10 +21,10 @@ const statusTranslateSuccess = (state, pollTranslation) => {
const statusTranslateUndo = (state, id) => {
return state.withMutations(map => {
const options = map.getIn([id, 'options']);
const options = map.getIn([id, "options"]);
if (options) {
options.forEach((item, index) => map.deleteIn([id, 'options', index, 'translation']));
options.forEach((item, index) => map.deleteIn([id, "options", index, "translation"]));
}
});
};
@@ -33,13 +33,13 @@ const initialState = ImmutableMap();
export default function polls(state = initialState, action) {
switch(action.type) {
case POLLS_IMPORT:
return importPolls(state, action.polls);
case STATUS_TRANSLATE_SUCCESS:
return statusTranslateSuccess(state, action.translation.poll);
case STATUS_TRANSLATE_UNDO:
return statusTranslateUndo(state, action.pollId);
default:
return state;
case POLLS_IMPORT:
return importPolls(state, action.polls);
case STATUS_TRANSLATE_SUCCESS:
return statusTranslateSuccess(state, action.translation.poll);
case STATUS_TRANSLATE_UNDO:
return statusTranslateUndo(state, action.pollId);
default:
return state;
}
}
@@ -1,7 +1,7 @@
import Immutable from 'immutable';
import Immutable from "immutable";
import { SET_BROWSER_SUPPORT, SET_SUBSCRIPTION, CLEAR_SUBSCRIPTION, SET_ALERTS } from '../actions/push_notifications';
import { STORE_HYDRATE } from '../actions/store';
import { SET_BROWSER_SUPPORT, SET_SUBSCRIPTION, CLEAR_SUBSCRIPTION, SET_ALERTS } from "../actions/push_notifications";
import { STORE_HYDRATE } from "../actions/store";
const initialState = Immutable.Map({
subscription: null,
@@ -19,36 +19,36 @@ const initialState = Immutable.Map({
export default function push_subscriptions(state = initialState, action) {
switch(action.type) {
case STORE_HYDRATE: {
const push_subscription = action.state.get('push_subscription');
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);
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;
}
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 SET_ALERTS:
return state.setIn(action.path, action.value);
default:
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 SET_ALERTS:
return state.setIn(action.path, action.value);
default:
return state;
}
}
@@ -1,8 +1,8 @@
import { Map as ImmutableMap, fromJS } from 'immutable';
import { Map as ImmutableMap, fromJS } from "immutable";
import {
submitAccountNote,
} from '../actions/account_notes';
} from "../actions/account_notes";
import {
ACCOUNT_FOLLOW_SUCCESS,
ACCOUNT_FOLLOW_REQUEST,
@@ -19,14 +19,14 @@ import {
RELATIONSHIPS_FETCH_SUCCESS,
FOLLOW_REQUEST_AUTHORIZE_SUCCESS,
FOLLOW_REQUEST_REJECT_SUCCESS,
} from '../actions/accounts';
} from "../actions/accounts";
import {
DOMAIN_BLOCK_SUCCESS,
DOMAIN_UNBLOCK_SUCCESS,
} from '../actions/domain_blocks';
} from "../actions/domain_blocks";
import {
NOTIFICATIONS_UPDATE,
} from '../actions/notifications';
} from "../actions/notifications";
const normalizeRelationship = (state, relationship) => state.set(relationship.id, fromJS(relationship));
@@ -42,7 +42,7 @@ const normalizeRelationships = (state, relationships) => {
const setDomainBlocking = (state, accounts, blocking) => {
return state.withMutations(map => {
accounts.forEach(id => {
map.setIn([id, 'domain_blocking'], blocking);
map.setIn([id, "domain_blocking"], blocking);
});
});
};
@@ -51,38 +51,38 @@ const initialState = ImmutableMap();
export default function relationships(state = initialState, action) {
switch(action.type) {
case FOLLOW_REQUEST_AUTHORIZE_SUCCESS:
return state.setIn([action.id, 'followed_by'], true).setIn([action.id, 'requested_by'], false);
case FOLLOW_REQUEST_REJECT_SUCCESS:
return state.setIn([action.id, 'followed_by'], false).setIn([action.id, 'requested_by'], false);
case NOTIFICATIONS_UPDATE:
return action.notification.type === 'follow_request' ? state.setIn([action.notification.account.id, 'requested_by'], true) : state;
case ACCOUNT_FOLLOW_REQUEST:
return state.getIn([action.id, 'following']) ? state : state.setIn([action.id, action.locked ? 'requested' : 'following'], true);
case ACCOUNT_FOLLOW_FAIL:
return state.setIn([action.id, action.locked ? 'requested' : 'following'], false);
case ACCOUNT_UNFOLLOW_REQUEST:
return state.setIn([action.id, 'following'], false);
case ACCOUNT_UNFOLLOW_FAIL:
return state.setIn([action.id, 'following'], true);
case ACCOUNT_FOLLOW_SUCCESS:
case ACCOUNT_UNFOLLOW_SUCCESS:
case ACCOUNT_BLOCK_SUCCESS:
case ACCOUNT_UNBLOCK_SUCCESS:
case ACCOUNT_MUTE_SUCCESS:
case ACCOUNT_UNMUTE_SUCCESS:
case ACCOUNT_PIN_SUCCESS:
case ACCOUNT_UNPIN_SUCCESS:
return normalizeRelationship(state, action.relationship);
case RELATIONSHIPS_FETCH_SUCCESS:
return normalizeRelationships(state, action.relationships);
case submitAccountNote.fulfilled:
return normalizeRelationship(state, action.payload.relationship);
case DOMAIN_BLOCK_SUCCESS:
return setDomainBlocking(state, action.accounts, true);
case DOMAIN_UNBLOCK_SUCCESS:
return setDomainBlocking(state, action.accounts, false);
default:
return state;
case FOLLOW_REQUEST_AUTHORIZE_SUCCESS:
return state.setIn([action.id, "followed_by"], true).setIn([action.id, "requested_by"], false);
case FOLLOW_REQUEST_REJECT_SUCCESS:
return state.setIn([action.id, "followed_by"], false).setIn([action.id, "requested_by"], false);
case NOTIFICATIONS_UPDATE:
return action.notification.type === "follow_request" ? state.setIn([action.notification.account.id, "requested_by"], true) : state;
case ACCOUNT_FOLLOW_REQUEST:
return state.getIn([action.id, "following"]) ? state : state.setIn([action.id, action.locked ? "requested" : "following"], true);
case ACCOUNT_FOLLOW_FAIL:
return state.setIn([action.id, action.locked ? "requested" : "following"], false);
case ACCOUNT_UNFOLLOW_REQUEST:
return state.setIn([action.id, "following"], false);
case ACCOUNT_UNFOLLOW_FAIL:
return state.setIn([action.id, "following"], true);
case ACCOUNT_FOLLOW_SUCCESS:
case ACCOUNT_UNFOLLOW_SUCCESS:
case ACCOUNT_BLOCK_SUCCESS:
case ACCOUNT_UNBLOCK_SUCCESS:
case ACCOUNT_MUTE_SUCCESS:
case ACCOUNT_UNMUTE_SUCCESS:
case ACCOUNT_PIN_SUCCESS:
case ACCOUNT_UNPIN_SUCCESS:
return normalizeRelationship(state, action.relationship);
case RELATIONSHIPS_FETCH_SUCCESS:
return normalizeRelationships(state, action.relationships);
case submitAccountNote.fulfilled:
return normalizeRelationship(state, action.payload.relationship);
case DOMAIN_BLOCK_SUCCESS:
return setDomainBlocking(state, action.accounts, true);
case DOMAIN_UNBLOCK_SUCCESS:
return setDomainBlocking(state, action.accounts, false);
default:
return state;
}
}
+51 -51
View File
@@ -1,10 +1,10 @@
import { Map as ImmutableMap, OrderedSet as ImmutableOrderedSet, fromJS } from 'immutable';
import { Map as ImmutableMap, OrderedSet as ImmutableOrderedSet, fromJS } from "immutable";
import {
COMPOSE_MENTION,
COMPOSE_REPLY,
COMPOSE_DIRECT,
} from '../actions/compose';
} from "../actions/compose";
import {
SEARCH_CHANGE,
SEARCH_CLEAR,
@@ -16,67 +16,67 @@ import {
SEARCH_EXPAND_SUCCESS,
SEARCH_EXPAND_FAIL,
SEARCH_HISTORY_UPDATE,
} from '../actions/search';
} from "../actions/search";
const initialState = ImmutableMap({
value: '',
value: "",
submitted: false,
hidden: false,
results: ImmutableMap(),
isLoading: false,
searchTerm: '',
searchTerm: "",
type: null,
recent: ImmutableOrderedSet(),
});
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);
map.set('searchTerm', '');
map.set('type', null);
});
case SEARCH_SHOW:
return state.set('hidden', false);
case COMPOSE_REPLY:
case COMPOSE_MENTION:
case COMPOSE_DIRECT:
return state.set('hidden', true);
case SEARCH_FETCH_REQUEST:
return state.withMutations(map => {
map.set('isLoading', true);
map.set('submitted', true);
map.set('type', action.searchType);
});
case SEARCH_FETCH_FAIL:
case SEARCH_EXPAND_FAIL:
return state.set('isLoading', false);
case SEARCH_FETCH_SUCCESS:
return state.withMutations(map => {
map.set('results', ImmutableMap({
accounts: ImmutableOrderedSet(action.results.accounts.map(item => item.id)),
statuses: ImmutableOrderedSet(action.results.statuses.map(item => item.id)),
hashtags: ImmutableOrderedSet(fromJS(action.results.hashtags)),
}));
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);
map.set("searchTerm", "");
map.set("type", null);
});
case SEARCH_SHOW:
return state.set("hidden", false);
case COMPOSE_REPLY:
case COMPOSE_MENTION:
case COMPOSE_DIRECT:
return state.set("hidden", true);
case SEARCH_FETCH_REQUEST:
return state.withMutations(map => {
map.set("isLoading", true);
map.set("submitted", true);
map.set("type", action.searchType);
});
case SEARCH_FETCH_FAIL:
case SEARCH_EXPAND_FAIL:
return state.set("isLoading", false);
case SEARCH_FETCH_SUCCESS:
return state.withMutations(map => {
map.set("results", ImmutableMap({
accounts: ImmutableOrderedSet(action.results.accounts.map(item => item.id)),
statuses: ImmutableOrderedSet(action.results.statuses.map(item => item.id)),
hashtags: ImmutableOrderedSet(fromJS(action.results.hashtags)),
}));
map.set('searchTerm', action.searchTerm);
map.set('type', action.searchType);
map.set('isLoading', false);
});
case SEARCH_EXPAND_REQUEST:
return state.set('type', action.searchType).set('isLoading', true);
case SEARCH_EXPAND_SUCCESS:
const results = action.searchType === 'hashtags' ? ImmutableOrderedSet(fromJS(action.results.hashtags)) : action.results[action.searchType].map(item => item.id);
return state.updateIn(['results', action.searchType], list => list.union(results)).set('isLoading', false);
case SEARCH_HISTORY_UPDATE:
return state.set('recent', ImmutableOrderedSet(fromJS(action.recent)));
default:
return state;
map.set("searchTerm", action.searchTerm);
map.set("type", action.searchType);
map.set("isLoading", false);
});
case SEARCH_EXPAND_REQUEST:
return state.set("type", action.searchType).set("isLoading", true);
case SEARCH_EXPAND_SUCCESS:
const results = action.searchType === "hashtags" ? ImmutableOrderedSet(fromJS(action.results.hashtags)) : action.results[action.searchType].map(item => item.id);
return state.updateIn(["results", action.searchType], list => list.union(results)).set("isLoading", false);
case SEARCH_HISTORY_UPDATE:
return state.set("recent", ImmutableOrderedSet(fromJS(action.recent)));
default:
return state;
}
}
+16 -16
View File
@@ -1,4 +1,4 @@
import { Map as ImmutableMap, List as ImmutableList, fromJS } from 'immutable';
import { Map as ImmutableMap, List as ImmutableList, fromJS } from "immutable";
import {
SERVER_FETCH_REQUEST,
@@ -7,7 +7,7 @@ import {
SERVER_DOMAIN_BLOCKS_FETCH_REQUEST,
SERVER_DOMAIN_BLOCKS_FETCH_SUCCESS,
SERVER_DOMAIN_BLOCKS_FETCH_FAIL,
} from 'mastodon/actions/server';
} from "mastodon/actions/server";
const initialState = ImmutableMap({
server: ImmutableMap({
@@ -23,19 +23,19 @@ const initialState = ImmutableMap({
export default function server(state = initialState, action) {
switch (action.type) {
case SERVER_FETCH_REQUEST:
return state.setIn(['server', 'isLoading'], true);
case SERVER_FETCH_SUCCESS:
return state.set('server', fromJS(action.server)).setIn(['server', 'isLoading'], false);
case SERVER_FETCH_FAIL:
return state.setIn(['server', 'isLoading'], false);
case SERVER_DOMAIN_BLOCKS_FETCH_REQUEST:
return state.setIn(['domainBlocks', 'isLoading'], true);
case SERVER_DOMAIN_BLOCKS_FETCH_SUCCESS:
return state.setIn(['domainBlocks', 'items'], fromJS(action.blocks)).setIn(['domainBlocks', 'isLoading'], false).setIn(['domainBlocks', 'isAvailable'], action.isAvailable);
case SERVER_DOMAIN_BLOCKS_FETCH_FAIL:
return state.setIn(['domainBlocks', 'isLoading'], false);
default:
return state;
case SERVER_FETCH_REQUEST:
return state.setIn(["server", "isLoading"], true);
case SERVER_FETCH_SUCCESS:
return state.set("server", fromJS(action.server)).setIn(["server", "isLoading"], false);
case SERVER_FETCH_FAIL:
return state.setIn(["server", "isLoading"], false);
case SERVER_DOMAIN_BLOCKS_FETCH_REQUEST:
return state.setIn(["domainBlocks", "isLoading"], true);
case SERVER_DOMAIN_BLOCKS_FETCH_SUCCESS:
return state.setIn(["domainBlocks", "items"], fromJS(action.blocks)).setIn(["domainBlocks", "isLoading"], false).setIn(["domainBlocks", "isAvailable"], action.isAvailable);
case SERVER_DOMAIN_BLOCKS_FETCH_FAIL:
return state.setIn(["domainBlocks", "isLoading"], false);
default:
return state;
}
}
+67 -67
View File
@@ -1,13 +1,13 @@
import { Map as ImmutableMap, fromJS } from 'immutable';
import { Map as ImmutableMap, fromJS } from "immutable";
import { COLUMN_ADD, COLUMN_REMOVE, COLUMN_MOVE, COLUMN_PARAMS_CHANGE } from '../actions/columns';
import { EMOJI_USE } from '../actions/emojis';
import { LANGUAGE_USE } from '../actions/languages';
import { LIST_DELETE_SUCCESS, LIST_FETCH_FAIL } from '../actions/lists';
import { NOTIFICATIONS_FILTER_SET } from '../actions/notifications';
import { SETTING_CHANGE, SETTING_SAVE } from '../actions/settings';
import { STORE_HYDRATE } from '../actions/store';
import { uuid } from '../uuid';
import { COLUMN_ADD, COLUMN_REMOVE, COLUMN_MOVE, COLUMN_PARAMS_CHANGE } from "../actions/columns";
import { EMOJI_USE } from "../actions/emojis";
import { LANGUAGE_USE } from "../actions/languages";
import { LIST_DELETE_SUCCESS, LIST_FETCH_FAIL } from "../actions/lists";
import { NOTIFICATIONS_FILTER_SET } from "../actions/notifications";
import { SETTING_CHANGE, SETTING_SAVE } from "../actions/settings";
import { STORE_HYDRATE } from "../actions/store";
import { uuid } from "../uuid";
const initialState = ImmutableMap({
saved: true,
@@ -25,7 +25,7 @@ const initialState = ImmutableMap({
}),
regex: ImmutableMap({
body: '',
body: "",
}),
}),
@@ -39,12 +39,12 @@ const initialState = ImmutableMap({
poll: false,
status: false,
update: false,
'admin.sign_up': false,
'admin.report': false,
"admin.sign_up": false,
"admin.report": false,
}),
quickFilter: ImmutableMap({
active: 'all',
active: "all",
show: true,
advanced: false,
}),
@@ -61,8 +61,8 @@ const initialState = ImmutableMap({
poll: true,
status: true,
update: true,
'admin.sign_up': true,
'admin.report': true,
"admin.sign_up": true,
"admin.report": true,
}),
sounds: ImmutableMap({
@@ -74,8 +74,8 @@ const initialState = ImmutableMap({
poll: true,
status: true,
update: true,
'admin.sign_up': true,
'admin.report': true,
"admin.sign_up": true,
"admin.report": true,
}),
}),
@@ -85,34 +85,34 @@ const initialState = ImmutableMap({
community: ImmutableMap({
regex: ImmutableMap({
body: '',
body: "",
}),
}),
public: ImmutableMap({
regex: ImmutableMap({
body: '',
body: "",
}),
}),
direct: ImmutableMap({
regex: ImmutableMap({
body: '',
body: "",
}),
}),
});
const defaultColumns = fromJS([
{ id: 'COMPOSE', uuid: uuid(), params: {} },
{ id: 'HOME', uuid: uuid(), params: {} },
{ id: 'NOTIFICATIONS', uuid: uuid(), params: {} },
{ 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 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 columns = state.get("columns");
const index = columns.findIndex(item => item.get("uuid") === uuid);
const newIndex = index + direction;
let newColumns;
@@ -121,59 +121,59 @@ const moveColumn = (state, uuid, direction) => {
newColumns = newColumns.splice(newIndex, 0, columns.get(index));
return state
.set('columns', newColumns)
.set('saved', false);
.set("columns", newColumns)
.set("saved", false);
};
const changeColumnParams = (state, uuid, path, value) => {
const columns = state.get('columns');
const index = columns.findIndex(item => item.get('uuid') === uuid);
const columns = state.get("columns");
const index = columns.findIndex(item => item.get("uuid") === uuid);
const newColumns = columns.update(index, column => column.updateIn(['params', ...path], () => value));
const newColumns = columns.update(index, column => column.updateIn(["params", ...path], () => value));
return state
.set('columns', newColumns)
.set('saved', false);
.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);
const updateFrequentEmojis = (state, emoji) => state.update("frequentlyUsedEmojis", ImmutableMap(), map => map.update(emoji.id, 0, count => count + 1)).set("saved", false);
const updateFrequentLanguages = (state, language) => state.update('frequentlyUsedLanguages', ImmutableMap(), map => map.update(language, 0, count => count + 1)).set('saved', false);
const updateFrequentLanguages = (state, language) => state.update("frequentlyUsedLanguages", ImmutableMap(), map => map.update(language, 0, count => count + 1)).set("saved", false);
const filterDeadListColumns = (state, listId) => state.update('columns', columns => columns.filterNot(column => column.get('id') === 'LIST' && column.get('params').get('id') === listId));
const filterDeadListColumns = (state, listId) => state.update("columns", columns => columns.filterNot(column => column.get("id") === "LIST" && column.get("params").get("id") === listId));
export default function settings(state = initialState, action) {
switch(action.type) {
case STORE_HYDRATE:
return hydrate(state, action.state.get('settings'));
case NOTIFICATIONS_FILTER_SET:
case SETTING_CHANGE:
return state
.setIn(action.path, 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 COLUMN_PARAMS_CHANGE:
return changeColumnParams(state, action.uuid, action.path, action.value);
case EMOJI_USE:
return updateFrequentEmojis(state, action.emoji);
case LANGUAGE_USE:
return updateFrequentLanguages(state, action.language);
case SETTING_SAVE:
return state.set('saved', true);
case LIST_FETCH_FAIL:
return action.error.response.status === 404 ? filterDeadListColumns(state, action.id) : state;
case LIST_DELETE_SUCCESS:
return filterDeadListColumns(state, action.id);
default:
return state;
case STORE_HYDRATE:
return hydrate(state, action.state.get("settings"));
case NOTIFICATIONS_FILTER_SET:
case SETTING_CHANGE:
return state
.setIn(action.path, 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 COLUMN_PARAMS_CHANGE:
return changeColumnParams(state, action.uuid, action.path, action.value);
case EMOJI_USE:
return updateFrequentEmojis(state, action.emoji);
case LANGUAGE_USE:
return updateFrequentLanguages(state, action.language);
case SETTING_SAVE:
return state.set("saved", true);
case LIST_FETCH_FAIL:
return action.error.response.status === 404 ? filterDeadListColumns(state, action.id) : state;
case LIST_DELETE_SUCCESS:
return filterDeadListColumns(state, action.id);
default:
return state;
}
}
@@ -1,9 +1,9 @@
import { Map as ImmutableMap, OrderedSet as ImmutableOrderedSet } from 'immutable';
import { Map as ImmutableMap, OrderedSet as ImmutableOrderedSet } from "immutable";
import {
ACCOUNT_BLOCK_SUCCESS,
ACCOUNT_MUTE_SUCCESS,
} from '../actions/accounts';
} from "../actions/accounts";
import {
BOOKMARKED_STATUSES_FETCH_REQUEST,
BOOKMARKED_STATUSES_FETCH_SUCCESS,
@@ -11,7 +11,7 @@ import {
BOOKMARKED_STATUSES_EXPAND_REQUEST,
BOOKMARKED_STATUSES_EXPAND_SUCCESS,
BOOKMARKED_STATUSES_EXPAND_FAIL,
} from '../actions/bookmarks';
} from "../actions/bookmarks";
import {
FAVOURITED_STATUSES_FETCH_REQUEST,
FAVOURITED_STATUSES_FETCH_SUCCESS,
@@ -19,7 +19,7 @@ import {
FAVOURITED_STATUSES_EXPAND_REQUEST,
FAVOURITED_STATUSES_EXPAND_SUCCESS,
FAVOURITED_STATUSES_EXPAND_FAIL,
} from '../actions/favourites';
} from "../actions/favourites";
import {
FAVOURITE_SUCCESS,
UNFAVOURITE_SUCCESS,
@@ -27,10 +27,10 @@ import {
UNBOOKMARK_SUCCESS,
PIN_SUCCESS,
UNPIN_SUCCESS,
} from '../actions/interactions';
} from "../actions/interactions";
import {
PINNED_STATUSES_FETCH_SUCCESS,
} from '../actions/pin_statuses';
} from "../actions/pin_statuses";
import {
TRENDS_STATUSES_FETCH_REQUEST,
TRENDS_STATUSES_FETCH_SUCCESS,
@@ -38,7 +38,7 @@ import {
TRENDS_STATUSES_EXPAND_REQUEST,
TRENDS_STATUSES_EXPAND_SUCCESS,
TRENDS_STATUSES_EXPAND_FAIL,
} from '../actions/trends';
} from "../actions/trends";
@@ -67,85 +67,85 @@ const initialState = ImmutableMap({
const normalizeList = (state, listType, statuses, next) => {
return state.update(listType, listMap => listMap.withMutations(map => {
map.set('next', next);
map.set('loaded', true);
map.set('isLoading', false);
map.set('items', ImmutableOrderedSet(statuses.map(item => item.id)));
map.set("next", next);
map.set("loaded", true);
map.set("isLoading", false);
map.set("items", ImmutableOrderedSet(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('isLoading', false);
map.set('items', map.get('items').union(statuses.map(item => item.id)));
map.set("next", next);
map.set("isLoading", false);
map.set("items", map.get("items").union(statuses.map(item => item.id)));
}));
};
const prependOneToList = (state, listType, status) => {
return state.updateIn([listType, 'items'], (list) => {
if (list.includes(status.get('id'))) {
return state.updateIn([listType, "items"], (list) => {
if (list.includes(status.get("id"))) {
return list;
} else {
return ImmutableOrderedSet([status.get('id')]).union(list);
return ImmutableOrderedSet([status.get("id")]).union(list);
}
});
};
const removeOneFromList = (state, listType, status) => {
return state.updateIn([listType, 'items'], (list) => list.delete(status.get('id')));
return state.updateIn([listType, "items"], (list) => list.delete(status.get("id")));
};
export default function statusLists(state = initialState, action) {
switch(action.type) {
case FAVOURITED_STATUSES_FETCH_REQUEST:
case FAVOURITED_STATUSES_EXPAND_REQUEST:
return state.setIn(['favourites', 'isLoading'], true);
case FAVOURITED_STATUSES_FETCH_FAIL:
case FAVOURITED_STATUSES_EXPAND_FAIL:
return state.setIn(['favourites', 'isLoading'], false);
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 BOOKMARKED_STATUSES_FETCH_REQUEST:
case BOOKMARKED_STATUSES_EXPAND_REQUEST:
return state.setIn(['bookmarks', 'isLoading'], true);
case BOOKMARKED_STATUSES_FETCH_FAIL:
case BOOKMARKED_STATUSES_EXPAND_FAIL:
return state.setIn(['bookmarks', 'isLoading'], false);
case BOOKMARKED_STATUSES_FETCH_SUCCESS:
return normalizeList(state, 'bookmarks', action.statuses, action.next);
case BOOKMARKED_STATUSES_EXPAND_SUCCESS:
return appendToList(state, 'bookmarks', action.statuses, action.next);
case TRENDS_STATUSES_FETCH_REQUEST:
case TRENDS_STATUSES_EXPAND_REQUEST:
return state.setIn(['trending', 'isLoading'], true);
case TRENDS_STATUSES_FETCH_FAIL:
case TRENDS_STATUSES_EXPAND_FAIL:
return state.setIn(['trending', 'isLoading'], false);
case TRENDS_STATUSES_FETCH_SUCCESS:
return normalizeList(state, 'trending', action.statuses, action.next);
case TRENDS_STATUSES_EXPAND_SUCCESS:
return appendToList(state, 'trending', action.statuses, action.next);
case FAVOURITE_SUCCESS:
return prependOneToList(state, 'favourites', action.status);
case UNFAVOURITE_SUCCESS:
return removeOneFromList(state, 'favourites', action.status);
case BOOKMARK_SUCCESS:
return prependOneToList(state, 'bookmarks', action.status);
case UNBOOKMARK_SUCCESS:
return removeOneFromList(state, 'bookmarks', 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);
case ACCOUNT_BLOCK_SUCCESS:
case ACCOUNT_MUTE_SUCCESS:
return state.updateIn(['trending', 'items'], ImmutableOrderedSet(), list => list.filterNot(statusId => action.statuses.getIn([statusId, 'account']) === action.relationship.id));
default:
return state;
case FAVOURITED_STATUSES_FETCH_REQUEST:
case FAVOURITED_STATUSES_EXPAND_REQUEST:
return state.setIn(["favourites", "isLoading"], true);
case FAVOURITED_STATUSES_FETCH_FAIL:
case FAVOURITED_STATUSES_EXPAND_FAIL:
return state.setIn(["favourites", "isLoading"], false);
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 BOOKMARKED_STATUSES_FETCH_REQUEST:
case BOOKMARKED_STATUSES_EXPAND_REQUEST:
return state.setIn(["bookmarks", "isLoading"], true);
case BOOKMARKED_STATUSES_FETCH_FAIL:
case BOOKMARKED_STATUSES_EXPAND_FAIL:
return state.setIn(["bookmarks", "isLoading"], false);
case BOOKMARKED_STATUSES_FETCH_SUCCESS:
return normalizeList(state, "bookmarks", action.statuses, action.next);
case BOOKMARKED_STATUSES_EXPAND_SUCCESS:
return appendToList(state, "bookmarks", action.statuses, action.next);
case TRENDS_STATUSES_FETCH_REQUEST:
case TRENDS_STATUSES_EXPAND_REQUEST:
return state.setIn(["trending", "isLoading"], true);
case TRENDS_STATUSES_FETCH_FAIL:
case TRENDS_STATUSES_EXPAND_FAIL:
return state.setIn(["trending", "isLoading"], false);
case TRENDS_STATUSES_FETCH_SUCCESS:
return normalizeList(state, "trending", action.statuses, action.next);
case TRENDS_STATUSES_EXPAND_SUCCESS:
return appendToList(state, "trending", action.statuses, action.next);
case FAVOURITE_SUCCESS:
return prependOneToList(state, "favourites", action.status);
case UNFAVOURITE_SUCCESS:
return removeOneFromList(state, "favourites", action.status);
case BOOKMARK_SUCCESS:
return prependOneToList(state, "bookmarks", action.status);
case UNBOOKMARK_SUCCESS:
return removeOneFromList(state, "bookmarks", 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);
case ACCOUNT_BLOCK_SUCCESS:
case ACCOUNT_MUTE_SUCCESS:
return state.updateIn(["trending", "items"], ImmutableOrderedSet(), list => list.filterNot(statusId => action.statuses.getIn([statusId, "account"]) === action.relationship.id));
default:
return state;
}
}
+72 -72
View File
@@ -1,7 +1,7 @@
import { Map as ImmutableMap, fromJS } from 'immutable';
import { Map as ImmutableMap, fromJS } from "immutable";
import { STATUS_IMPORT, STATUSES_IMPORT } from '../actions/importer';
import { normalizeStatusTranslation } from '../actions/importer/normalizer';
import { STATUS_IMPORT, STATUSES_IMPORT } from "../actions/importer";
import { normalizeStatusTranslation } from "../actions/importer/normalizer";
import {
REBLOG_REQUEST,
REBLOG_FAIL,
@@ -15,7 +15,7 @@ import {
BOOKMARK_FAIL,
UNBOOKMARK_REQUEST,
UNBOOKMARK_FAIL,
} from '../actions/interactions';
} from "../actions/interactions";
import {
STATUS_MUTE_SUCCESS,
STATUS_UNMUTE_SUCCESS,
@@ -26,8 +26,8 @@ import {
STATUS_TRANSLATE_UNDO,
STATUS_FETCH_REQUEST,
STATUS_FETCH_FAIL,
} from '../actions/statuses';
import { TIMELINE_DELETE } from '../actions/timelines';
} from "../actions/statuses";
import { TIMELINE_DELETE } from "../actions/timelines";
const importStatus = (state, status) => state.set(status.id, fromJS(status));
@@ -44,13 +44,13 @@ const deleteStatus = (state, id, references) => {
const statusTranslateSuccess = (state, id, translation) => {
return state.withMutations(map => {
map.setIn([id, 'translation'], fromJS(normalizeStatusTranslation(translation, map.get(id))));
map.setIn([id, "translation"], fromJS(normalizeStatusTranslation(translation, map.get(id))));
const list = map.getIn([id, 'media_attachments']);
const list = map.getIn([id, "media_attachments"]);
if (translation.media_attachments && list) {
translation.media_attachments.forEach(item => {
const index = list.findIndex(i => i.get('id') === item.id);
map.setIn([id, 'media_attachments', index, 'translation'], fromJS({ description: item.description }));
const index = list.findIndex(i => i.get("id") === item.id);
map.setIn([id, "media_attachments", index, "translation"], fromJS({ description: item.description }));
});
}
});
@@ -58,8 +58,8 @@ const statusTranslateSuccess = (state, id, translation) => {
const statusTranslateUndo = (state, id) => {
return state.withMutations(map => {
map.deleteIn([id, 'translation']);
map.getIn([id, 'media_attachments']).forEach((item, index) => map.deleteIn([id, 'media_attachments', index, 'translation']));
map.deleteIn([id, "translation"]);
map.getIn([id, "media_attachments"]).forEach((item, index) => map.deleteIn([id, "media_attachments", index, "translation"]));
});
};
@@ -67,67 +67,67 @@ const initialState = ImmutableMap();
export default function statuses(state = initialState, action) {
switch(action.type) {
case STATUS_FETCH_REQUEST:
return state.setIn([action.id, 'isLoading'], true);
case STATUS_FETCH_FAIL:
return state.delete(action.id);
case STATUS_IMPORT:
return importStatus(state, action.status);
case STATUSES_IMPORT:
return importStatuses(state, action.statuses);
case FAVOURITE_REQUEST:
return state.setIn([action.status.get('id'), 'favourited'], true);
case FAVOURITE_FAIL:
return state.get(action.status.get('id')) === undefined ? state : state.setIn([action.status.get('id'), 'favourited'], false);
case UNFAVOURITE_REQUEST:
return state.setIn([action.status.get('id'), 'favourited'], false);
case UNFAVOURITE_FAIL:
return state.get(action.status.get('id')) === undefined ? state : state.setIn([action.status.get('id'), 'favourited'], true);
case BOOKMARK_REQUEST:
return state.get(action.status.get('id')) === undefined ? state : state.setIn([action.status.get('id'), 'bookmarked'], true);
case BOOKMARK_FAIL:
return state.get(action.status.get('id')) === undefined ? state : state.setIn([action.status.get('id'), 'bookmarked'], false);
case UNBOOKMARK_REQUEST:
return state.get(action.status.get('id')) === undefined ? state : state.setIn([action.status.get('id'), 'bookmarked'], false);
case UNBOOKMARK_FAIL:
return state.get(action.status.get('id')) === undefined ? state : state.setIn([action.status.get('id'), 'bookmarked'], true);
case REBLOG_REQUEST:
return state.setIn([action.status.get('id'), 'reblogged'], true);
case REBLOG_FAIL:
return state.get(action.status.get('id')) === undefined ? state : state.setIn([action.status.get('id'), 'reblogged'], false);
case UNREBLOG_REQUEST:
return state.setIn([action.status.get('id'), 'reblogged'], false);
case UNREBLOG_FAIL:
return state.get(action.status.get('id')) === undefined ? state : state.setIn([action.status.get('id'), 'reblogged'], true);
case STATUS_MUTE_SUCCESS:
return state.setIn([action.id, 'muted'], true);
case STATUS_UNMUTE_SUCCESS:
return state.setIn([action.id, 'muted'], false);
case STATUS_REVEAL:
return state.withMutations(map => {
action.ids.forEach(id => {
if (!(state.get(id) === undefined)) {
map.setIn([id, 'hidden'], false);
}
case STATUS_FETCH_REQUEST:
return state.setIn([action.id, "isLoading"], true);
case STATUS_FETCH_FAIL:
return state.delete(action.id);
case STATUS_IMPORT:
return importStatus(state, action.status);
case STATUSES_IMPORT:
return importStatuses(state, action.statuses);
case FAVOURITE_REQUEST:
return state.setIn([action.status.get("id"), "favourited"], true);
case FAVOURITE_FAIL:
return state.get(action.status.get("id")) === undefined ? state : state.setIn([action.status.get("id"), "favourited"], false);
case UNFAVOURITE_REQUEST:
return state.setIn([action.status.get("id"), "favourited"], false);
case UNFAVOURITE_FAIL:
return state.get(action.status.get("id")) === undefined ? state : state.setIn([action.status.get("id"), "favourited"], true);
case BOOKMARK_REQUEST:
return state.get(action.status.get("id")) === undefined ? state : state.setIn([action.status.get("id"), "bookmarked"], true);
case BOOKMARK_FAIL:
return state.get(action.status.get("id")) === undefined ? state : state.setIn([action.status.get("id"), "bookmarked"], false);
case UNBOOKMARK_REQUEST:
return state.get(action.status.get("id")) === undefined ? state : state.setIn([action.status.get("id"), "bookmarked"], false);
case UNBOOKMARK_FAIL:
return state.get(action.status.get("id")) === undefined ? state : state.setIn([action.status.get("id"), "bookmarked"], true);
case REBLOG_REQUEST:
return state.setIn([action.status.get("id"), "reblogged"], true);
case REBLOG_FAIL:
return state.get(action.status.get("id")) === undefined ? state : state.setIn([action.status.get("id"), "reblogged"], false);
case UNREBLOG_REQUEST:
return state.setIn([action.status.get("id"), "reblogged"], false);
case UNREBLOG_FAIL:
return state.get(action.status.get("id")) === undefined ? state : state.setIn([action.status.get("id"), "reblogged"], true);
case STATUS_MUTE_SUCCESS:
return state.setIn([action.id, "muted"], true);
case STATUS_UNMUTE_SUCCESS:
return state.setIn([action.id, "muted"], false);
case STATUS_REVEAL:
return state.withMutations(map => {
action.ids.forEach(id => {
if (!(state.get(id) === undefined)) {
map.setIn([id, "hidden"], false);
}
});
});
});
case STATUS_HIDE:
return state.withMutations(map => {
action.ids.forEach(id => {
if (!(state.get(id) === undefined)) {
map.setIn([id, 'hidden'], true);
}
case STATUS_HIDE:
return state.withMutations(map => {
action.ids.forEach(id => {
if (!(state.get(id) === undefined)) {
map.setIn([id, "hidden"], true);
}
});
});
});
case STATUS_COLLAPSE:
return state.setIn([action.id, 'collapsed'], action.isCollapsed);
case TIMELINE_DELETE:
return deleteStatus(state, action.id, action.references);
case STATUS_TRANSLATE_SUCCESS:
return statusTranslateSuccess(state, action.id, action.translation);
case STATUS_TRANSLATE_UNDO:
return statusTranslateUndo(state, action.id);
default:
return state;
case STATUS_COLLAPSE:
return state.setIn([action.id, "collapsed"], action.isCollapsed);
case TIMELINE_DELETE:
return deleteStatus(state, action.id, action.references);
case STATUS_TRANSLATE_SUCCESS:
return statusTranslateSuccess(state, action.id, action.translation);
case STATUS_TRANSLATE_UNDO:
return statusTranslateUndo(state, action.id);
default:
return state;
}
}
+22 -22
View File
@@ -1,14 +1,14 @@
import { Map as ImmutableMap, List as ImmutableList, fromJS } from 'immutable';
import { Map as ImmutableMap, List as ImmutableList, fromJS } from "immutable";
import { ACCOUNT_BLOCK_SUCCESS, ACCOUNT_MUTE_SUCCESS } from 'mastodon/actions/accounts';
import { DOMAIN_BLOCK_SUCCESS } from 'mastodon/actions/domain_blocks';
import { ACCOUNT_BLOCK_SUCCESS, ACCOUNT_MUTE_SUCCESS } from "mastodon/actions/accounts";
import { DOMAIN_BLOCK_SUCCESS } from "mastodon/actions/domain_blocks";
import {
SUGGESTIONS_FETCH_REQUEST,
SUGGESTIONS_FETCH_SUCCESS,
SUGGESTIONS_FETCH_FAIL,
SUGGESTIONS_DISMISS,
} from '../actions/suggestions';
} from "../actions/suggestions";
const initialState = ImmutableMap({
@@ -18,23 +18,23 @@ const initialState = ImmutableMap({
export default function suggestionsReducer(state = initialState, action) {
switch(action.type) {
case SUGGESTIONS_FETCH_REQUEST:
return state.set('isLoading', true);
case SUGGESTIONS_FETCH_SUCCESS:
return state.withMutations(map => {
map.set('items', fromJS(action.suggestions.map(x => ({ ...x, account: x.account.id }))));
map.set('isLoading', false);
});
case SUGGESTIONS_FETCH_FAIL:
return state.set('isLoading', false);
case SUGGESTIONS_DISMISS:
return state.update('items', list => list.filterNot(x => x.account === action.id));
case ACCOUNT_BLOCK_SUCCESS:
case ACCOUNT_MUTE_SUCCESS:
return state.update('items', list => list.filterNot(x => x.account === action.relationship.id));
case DOMAIN_BLOCK_SUCCESS:
return state.update('items', list => list.filterNot(x => action.accounts.includes(x.account)));
default:
return state;
case SUGGESTIONS_FETCH_REQUEST:
return state.set("isLoading", true);
case SUGGESTIONS_FETCH_SUCCESS:
return state.withMutations(map => {
map.set("items", fromJS(action.suggestions.map(x => ({ ...x, account: x.account.id }))));
map.set("isLoading", false);
});
case SUGGESTIONS_FETCH_FAIL:
return state.set("isLoading", false);
case SUGGESTIONS_DISMISS:
return state.update("items", list => list.filterNot(x => x.account === action.id));
case ACCOUNT_BLOCK_SUCCESS:
case ACCOUNT_MUTE_SUCCESS:
return state.update("items", list => list.filterNot(x => x.account === action.relationship.id));
case DOMAIN_BLOCK_SUCCESS:
return state.update("items", list => list.filterNot(x => action.accounts.includes(x.account)));
default:
return state;
}
}
+12 -12
View File
@@ -1,4 +1,4 @@
import { Map as ImmutableMap, fromJS } from 'immutable';
import { Map as ImmutableMap, fromJS } from "immutable";
import {
HASHTAG_FETCH_SUCCESS,
@@ -6,21 +6,21 @@ import {
HASHTAG_FOLLOW_FAIL,
HASHTAG_UNFOLLOW_REQUEST,
HASHTAG_UNFOLLOW_FAIL,
} from 'mastodon/actions/tags';
} from "mastodon/actions/tags";
const initialState = ImmutableMap();
export default function tags(state = initialState, action) {
switch(action.type) {
case HASHTAG_FETCH_SUCCESS:
return state.set(action.name, fromJS(action.tag));
case HASHTAG_FOLLOW_REQUEST:
case HASHTAG_UNFOLLOW_FAIL:
return state.setIn([action.name, 'following'], true);
case HASHTAG_FOLLOW_FAIL:
case HASHTAG_UNFOLLOW_REQUEST:
return state.setIn([action.name, 'following'], false);
default:
return state;
case HASHTAG_FETCH_SUCCESS:
return state.set(action.name, fromJS(action.tag));
case HASHTAG_FOLLOW_REQUEST:
case HASHTAG_UNFOLLOW_FAIL:
return state.setIn([action.name, "following"], true);
case HASHTAG_FOLLOW_FAIL:
case HASHTAG_UNFOLLOW_REQUEST:
return state.setIn([action.name, "following"], false);
default:
return state;
}
}
+79 -71
View File
@@ -1,10 +1,10 @@
import { Map as ImmutableMap, List as ImmutableList, OrderedSet as ImmutableOrderedSet, fromJS } from 'immutable';
import { Map as ImmutableMap, List as ImmutableList, OrderedSet as ImmutableOrderedSet, fromJS } from "immutable";
import {
ACCOUNT_BLOCK_SUCCESS,
ACCOUNT_MUTE_SUCCESS,
ACCOUNT_UNFOLLOW_SUCCESS,
} from '../actions/accounts';
} from "../actions/accounts";
import {
TIMELINE_UPDATE,
TIMELINE_DELETE,
@@ -17,8 +17,8 @@ import {
TIMELINE_DISCONNECT,
TIMELINE_LOAD_PENDING,
TIMELINE_MARK_AS_PARTIAL,
} from '../actions/timelines';
import { compareId } from '../compare_id';
} from "../actions/timelines";
import { compareId } from "../compare_id";
const initialState = ImmutableMap();
@@ -41,18 +41,20 @@ const expandNormalizedTimeline = (state, timeline, statuses, next, isPartial, is
// - this function can be called either to fill in a gap, or load newer items
return state.update(timeline, initialTimeline, map => map.withMutations(mMap => {
mMap.set('isLoading', false);
mMap.set('isPartial', isPartial);
mMap.set("isLoading", false);
mMap.set("isPartial", isPartial);
if (!next && !isLoadingRecent) mMap.set('hasMore', false);
if (!next && !isLoadingRecent) {
mMap.set("hasMore", false);
}
if (timeline.endsWith(':pinned')) {
mMap.set('items', statuses.map(status => status.get('id')));
if (timeline.endsWith(":pinned")) {
mMap.set("items", statuses.map(status => status.get("id")));
} else if (!statuses.isEmpty()) {
usePendingItems = isLoadingRecent && (usePendingItems || !mMap.get('pendingItems').isEmpty());
usePendingItems = isLoadingRecent && (usePendingItems || !mMap.get("pendingItems").isEmpty());
mMap.update(usePendingItems ? 'pendingItems' : 'items', ImmutableList(), oldIds => {
const newIds = statuses.map(status => status.get('id'));
mMap.update(usePendingItems ? "pendingItems" : "items", ImmutableList(), oldIds => {
const newIds = statuses.map(status => status.get("id"));
// Now this gets tricky, as we don't necessarily know for sure where the gap to fill is
// and some items in the timeline may not be properly ordered.
@@ -98,19 +100,19 @@ const expandNormalizedTimeline = (state, timeline, statuses, next, isPartial, is
};
const updateTimeline = (state, timeline, status, usePendingItems) => {
const top = state.getIn([timeline, 'top']);
const top = state.getIn([timeline, "top"]);
if (usePendingItems || !state.getIn([timeline, 'pendingItems']).isEmpty()) {
if (state.getIn([timeline, 'pendingItems'], ImmutableList()).includes(status.get('id')) || state.getIn([timeline, 'items'], ImmutableList()).includes(status.get('id'))) {
if (usePendingItems || !state.getIn([timeline, "pendingItems"]).isEmpty()) {
if (state.getIn([timeline, "pendingItems"], ImmutableList()).includes(status.get("id")) || state.getIn([timeline, "items"], ImmutableList()).includes(status.get("id"))) {
return state;
}
return state.update(timeline, initialTimeline, map => map.update('pendingItems', list => list.unshift(status.get('id'))).update('unread', unread => unread + 1));
return state.update(timeline, initialTimeline, map => map.update("pendingItems", list => list.unshift(status.get("id"))).update("unread", unread => unread + 1));
}
const ids = state.getIn([timeline, 'items'], ImmutableList());
const includesId = ids.includes(status.get('id'));
const unread = state.getIn([timeline, 'unread'], 0);
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;
@@ -119,9 +121,13 @@ const updateTimeline = (state, timeline, status, usePendingItems) => {
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);
mMap.set('items', newIds.unshift(status.get('id')));
if (!top) {
mMap.set("unread", unread + 1);
}
if (top && ids.size > 40) {
newIds = newIds.take(20);
}
mMap.set("items", newIds.unshift(status.get("id")));
}));
};
@@ -129,7 +135,7 @@ const deleteStatus = (state, id, references, exclude_account = null) => {
state.keySeq().forEach(timeline => {
if (exclude_account === null || (timeline !== `account:${exclude_account}` && !timeline.startsWith(`account:${exclude_account}:`))) {
const helper = list => list.filterNot(item => item === id);
state = state.updateIn([timeline, 'items'], helper).updateIn([timeline, 'pendingItems'], helper);
state = state.updateIn([timeline, "items"], helper).updateIn([timeline, "pendingItems"], helper);
}
});
@@ -149,79 +155,81 @@ const filterTimelines = (state, relationship, statuses) => {
let references;
statuses.forEach(status => {
if (status.get('account') !== relationship.id) {
if (status.get("account") !== relationship.id) {
return;
}
references = statuses.filter(item => item.get('reblog') === status.get('id')).map(item => item.get('id'));
state = deleteStatus(state, status.get('id'), references, relationship.id);
references = statuses.filter(item => item.get("reblog") === status.get("id")).map(item => item.get("id"));
state = deleteStatus(state, status.get("id"), references, relationship.id);
});
return state;
};
const filterTimeline = (timeline, state, relationship, statuses) => {
const helper = list => list.filterNot(statusId => statuses.getIn([statusId, 'account']) === relationship.id);
return state.updateIn([timeline, 'items'], ImmutableList(), helper).updateIn([timeline, 'pendingItems'], ImmutableList(), helper);
const helper = list => list.filterNot(statusId => statuses.getIn([statusId, "account"]) === relationship.id);
return state.updateIn([timeline, "items"], ImmutableList(), helper).updateIn([timeline, "pendingItems"], ImmutableList(), helper);
};
const updateTop = (state, timeline, top) => {
return state.update(timeline, initialTimeline, map => map.withMutations(mMap => {
if (top) mMap.set('unread', mMap.get('pendingItems').size);
mMap.set('top', top);
if (top) {
mMap.set("unread", mMap.get("pendingItems").size);
}
mMap.set("top", top);
}));
};
const reconnectTimeline = (state, usePendingItems) => {
if (state.get('online')) {
if (state.get("online")) {
return state;
}
return state.withMutations(mMap => {
mMap.update(usePendingItems ? 'pendingItems' : 'items', items => items.first() ? items.unshift(null) : items);
mMap.set('online', true);
mMap.update(usePendingItems ? "pendingItems" : "items", items => items.first() ? items.unshift(null) : items);
mMap.set("online", true);
});
};
export default function timelines(state = initialState, action) {
switch(action.type) {
case TIMELINE_LOAD_PENDING:
return state.update(action.timeline, initialTimeline, map =>
map.update('items', list => map.get('pendingItems').concat(list.take(40))).set('pendingItems', ImmutableList()).set('unread', 0));
case TIMELINE_EXPAND_REQUEST:
return state.update(action.timeline, initialTimeline, map => map.set('isLoading', true));
case TIMELINE_EXPAND_FAIL:
return state.update(action.timeline, initialTimeline, map => map.set('isLoading', false));
case TIMELINE_EXPAND_SUCCESS:
return expandNormalizedTimeline(state, action.timeline, fromJS(action.statuses), action.next, action.partial, action.isLoadingRecent, action.usePendingItems);
case TIMELINE_UPDATE:
return updateTimeline(state, action.timeline, fromJS(action.status), action.usePendingItems);
case TIMELINE_DELETE:
return deleteStatus(state, action.id, action.references, action.reblogOf);
case TIMELINE_CLEAR:
return clearTimeline(state, action.timeline);
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 => reconnectTimeline(map, action.usePendingItems));
case TIMELINE_DISCONNECT:
return state.update(
action.timeline,
initialTimeline,
map => map.set('online', false).update(action.usePendingItems ? 'pendingItems' : 'items', items => items.first() ? items.unshift(null) : items),
);
case TIMELINE_MARK_AS_PARTIAL:
return state.update(
action.timeline,
initialTimeline,
map => map.set('isPartial', true).set('items', ImmutableList()).set('pendingItems', ImmutableList()).set('unread', 0),
);
default:
return state;
case TIMELINE_LOAD_PENDING:
return state.update(action.timeline, initialTimeline, map =>
map.update("items", list => map.get("pendingItems").concat(list.take(40))).set("pendingItems", ImmutableList()).set("unread", 0));
case TIMELINE_EXPAND_REQUEST:
return state.update(action.timeline, initialTimeline, map => map.set("isLoading", true));
case TIMELINE_EXPAND_FAIL:
return state.update(action.timeline, initialTimeline, map => map.set("isLoading", false));
case TIMELINE_EXPAND_SUCCESS:
return expandNormalizedTimeline(state, action.timeline, fromJS(action.statuses), action.next, action.partial, action.isLoadingRecent, action.usePendingItems);
case TIMELINE_UPDATE:
return updateTimeline(state, action.timeline, fromJS(action.status), action.usePendingItems);
case TIMELINE_DELETE:
return deleteStatus(state, action.id, action.references, action.reblogOf);
case TIMELINE_CLEAR:
return clearTimeline(state, action.timeline);
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 => reconnectTimeline(map, action.usePendingItems));
case TIMELINE_DISCONNECT:
return state.update(
action.timeline,
initialTimeline,
map => map.set("online", false).update(action.usePendingItems ? "pendingItems" : "items", items => items.first() ? items.unshift(null) : items),
);
case TIMELINE_MARK_AS_PARTIAL:
return state.update(
action.timeline,
initialTimeline,
map => map.set("isPartial", true).set("items", ImmutableList()).set("pendingItems", ImmutableList()).set("unread", 0),
);
default:
return state;
}
}
+22 -22
View File
@@ -1,4 +1,4 @@
import { Map as ImmutableMap, List as ImmutableList, fromJS } from 'immutable';
import { Map as ImmutableMap, List as ImmutableList, fromJS } from "immutable";
import {
TRENDS_TAGS_FETCH_REQUEST,
@@ -7,7 +7,7 @@ import {
TRENDS_LINKS_FETCH_REQUEST,
TRENDS_LINKS_FETCH_SUCCESS,
TRENDS_LINKS_FETCH_FAIL,
} from 'mastodon/actions/trends';
} from "mastodon/actions/trends";
const initialState = ImmutableMap({
tags: ImmutableMap({
@@ -23,25 +23,25 @@ const initialState = ImmutableMap({
export default function trendsReducer(state = initialState, action) {
switch(action.type) {
case TRENDS_TAGS_FETCH_REQUEST:
return state.setIn(['tags', 'isLoading'], true);
case TRENDS_TAGS_FETCH_SUCCESS:
return state.withMutations(map => {
map.setIn(['tags', 'items'], fromJS(action.trends));
map.setIn(['tags', 'isLoading'], false);
});
case TRENDS_TAGS_FETCH_FAIL:
return state.setIn(['tags', 'isLoading'], false);
case TRENDS_LINKS_FETCH_REQUEST:
return state.setIn(['links', 'isLoading'], true);
case TRENDS_LINKS_FETCH_SUCCESS:
return state.withMutations(map => {
map.setIn(['links', 'items'], fromJS(action.trends));
map.setIn(['links', 'isLoading'], false);
});
case TRENDS_LINKS_FETCH_FAIL:
return state.setIn(['links', 'isLoading'], false);
default:
return state;
case TRENDS_TAGS_FETCH_REQUEST:
return state.setIn(["tags", "isLoading"], true);
case TRENDS_TAGS_FETCH_SUCCESS:
return state.withMutations(map => {
map.setIn(["tags", "items"], fromJS(action.trends));
map.setIn(["tags", "isLoading"], false);
});
case TRENDS_TAGS_FETCH_FAIL:
return state.setIn(["tags", "isLoading"], false);
case TRENDS_LINKS_FETCH_REQUEST:
return state.setIn(["links", "isLoading"], true);
case TRENDS_LINKS_FETCH_SUCCESS:
return state.withMutations(map => {
map.setIn(["links", "items"], fromJS(action.trends));
map.setIn(["links", "isLoading"], false);
});
case TRENDS_LINKS_FETCH_FAIL:
return state.setIn(["links", "isLoading"], false);
default:
return state;
}
}
+104 -104
View File
@@ -1,4 +1,4 @@
import { Map as ImmutableMap, List as ImmutableList, fromJS } from 'immutable';
import { Map as ImmutableMap, List as ImmutableList, fromJS } from "immutable";
import {
DIRECTORY_FETCH_REQUEST,
@@ -7,12 +7,12 @@ import {
DIRECTORY_EXPAND_REQUEST,
DIRECTORY_EXPAND_SUCCESS,
DIRECTORY_EXPAND_FAIL,
} from 'mastodon/actions/directory';
} from "mastodon/actions/directory";
import {
FEATURED_TAGS_FETCH_REQUEST,
FEATURED_TAGS_FETCH_SUCCESS,
FEATURED_TAGS_FETCH_FAIL,
} from 'mastodon/actions/featured_tags';
} from "mastodon/actions/featured_tags";
import {
FOLLOWERS_FETCH_REQUEST,
@@ -35,7 +35,7 @@ import {
FOLLOW_REQUESTS_EXPAND_FAIL,
FOLLOW_REQUEST_AUTHORIZE_SUCCESS,
FOLLOW_REQUEST_REJECT_SUCCESS,
} from '../actions/accounts';
} from "../actions/accounts";
import {
BLOCKS_FETCH_REQUEST,
BLOCKS_FETCH_SUCCESS,
@@ -43,7 +43,7 @@ import {
BLOCKS_EXPAND_REQUEST,
BLOCKS_EXPAND_SUCCESS,
BLOCKS_EXPAND_FAIL,
} from '../actions/blocks';
} from "../actions/blocks";
import {
REBLOGS_FETCH_REQUEST,
REBLOGS_FETCH_SUCCESS,
@@ -57,7 +57,7 @@ import {
FAVOURITES_EXPAND_REQUEST,
FAVOURITES_EXPAND_SUCCESS,
FAVOURITES_EXPAND_FAIL,
} from '../actions/interactions';
} from "../actions/interactions";
import {
MUTES_FETCH_REQUEST,
MUTES_FETCH_SUCCESS,
@@ -65,10 +65,10 @@ import {
MUTES_EXPAND_REQUEST,
MUTES_EXPAND_SUCCESS,
MUTES_EXPAND_FAIL,
} from '../actions/mutes';
} from "../actions/mutes";
import {
NOTIFICATIONS_UPDATE,
} from '../actions/notifications';
} from "../actions/notifications";
@@ -99,12 +99,12 @@ const normalizeList = (state, path, accounts, next) => {
const appendToList = (state, path, accounts, next) => {
return state.updateIn(path, map => {
return map.set('next', next).set('isLoading', false).update('items', list => list.concat(accounts.map(item => item.id)));
return map.set("next", next).set("isLoading", false).update("items", list => list.concat(accounts.map(item => item.id)));
});
};
const normalizeFollowRequest = (state, notification) => {
return state.updateIn(['follow_requests', 'items'], list => {
return state.updateIn(["follow_requests", "items"], list => {
return list.filterNot(item => item === notification.account.id).unshift(notification.account.id);
});
};
@@ -116,105 +116,105 @@ const normalizeFeaturedTag = (featuredTags, accountId) => {
const normalizeFeaturedTags = (state, path, featuredTags, accountId) => {
return state.setIn(path, ImmutableMap({
items: ImmutableList(featuredTags.map(featuredTag => normalizeFeaturedTag(featuredTag, accountId)).sort((a, b) => b.get('statuses_count') - a.get('statuses_count'))),
items: ImmutableList(featuredTags.map(featuredTag => normalizeFeaturedTag(featuredTag, accountId)).sort((a, b) => b.get("statuses_count") - a.get("statuses_count"))),
isLoading: false,
}));
};
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 FOLLOWERS_FETCH_REQUEST:
case FOLLOWERS_EXPAND_REQUEST:
return state.setIn(['followers', action.id, 'isLoading'], true);
case FOLLOWERS_FETCH_FAIL:
case FOLLOWERS_EXPAND_FAIL:
return state.setIn(['followers', action.id, 'isLoading'], false);
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 FOLLOWING_FETCH_REQUEST:
case FOLLOWING_EXPAND_REQUEST:
return state.setIn(['following', action.id, 'isLoading'], true);
case FOLLOWING_FETCH_FAIL:
case FOLLOWING_EXPAND_FAIL:
return state.setIn(['following', action.id, 'isLoading'], false);
case REBLOGS_FETCH_SUCCESS:
return normalizeList(state, ['reblogged_by', action.id], action.accounts, action.next);
case REBLOGS_EXPAND_SUCCESS:
return appendToList(state, ['reblogged_by', action.id], action.accounts, action.next);
case REBLOGS_FETCH_REQUEST:
case REBLOGS_EXPAND_REQUEST:
return state.setIn(['reblogged_by', action.id, 'isLoading'], true);
case REBLOGS_FETCH_FAIL:
case REBLOGS_EXPAND_FAIL:
return state.setIn(['reblogged_by', action.id, 'isLoading'], false);
case FAVOURITES_FETCH_SUCCESS:
return normalizeList(state, ['favourited_by', action.id], action.accounts, action.next);
case FAVOURITES_EXPAND_SUCCESS:
return appendToList(state, ['favourited_by', action.id], action.accounts, action.next);
case FAVOURITES_FETCH_REQUEST:
case FAVOURITES_EXPAND_REQUEST:
return state.setIn(['favourited_by', action.id, 'isLoading'], true);
case FAVOURITES_FETCH_FAIL:
case FAVOURITES_EXPAND_FAIL:
return state.setIn(['favourited_by', action.id, 'isLoading'], false);
case NOTIFICATIONS_UPDATE:
return action.notification.type === 'follow_request' ? normalizeFollowRequest(state, action.notification) : state;
case FOLLOW_REQUESTS_FETCH_SUCCESS:
return normalizeList(state, ['follow_requests'], action.accounts, action.next);
case FOLLOW_REQUESTS_EXPAND_SUCCESS:
return appendToList(state, ['follow_requests'], action.accounts, action.next);
case FOLLOW_REQUESTS_FETCH_REQUEST:
case FOLLOW_REQUESTS_EXPAND_REQUEST:
return state.setIn(['follow_requests', 'isLoading'], true);
case FOLLOW_REQUESTS_FETCH_FAIL:
case FOLLOW_REQUESTS_EXPAND_FAIL:
return state.setIn(['follow_requests', 'isLoading'], false);
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 normalizeList(state, ['blocks'], action.accounts, action.next);
case BLOCKS_EXPAND_SUCCESS:
return appendToList(state, ['blocks'], action.accounts, action.next);
case BLOCKS_FETCH_REQUEST:
case BLOCKS_EXPAND_REQUEST:
return state.setIn(['blocks', 'isLoading'], true);
case BLOCKS_FETCH_FAIL:
case BLOCKS_EXPAND_FAIL:
return state.setIn(['blocks', 'isLoading'], false);
case MUTES_FETCH_SUCCESS:
return normalizeList(state, ['mutes'], action.accounts, action.next);
case MUTES_EXPAND_SUCCESS:
return appendToList(state, ['mutes'], action.accounts, action.next);
case MUTES_FETCH_REQUEST:
case MUTES_EXPAND_REQUEST:
return state.setIn(['mutes', 'isLoading'], true);
case MUTES_FETCH_FAIL:
case MUTES_EXPAND_FAIL:
return state.setIn(['mutes', 'isLoading'], false);
case DIRECTORY_FETCH_SUCCESS:
return normalizeList(state, ['directory'], action.accounts, action.next);
case DIRECTORY_EXPAND_SUCCESS:
return appendToList(state, ['directory'], action.accounts, action.next);
case DIRECTORY_FETCH_REQUEST:
case DIRECTORY_EXPAND_REQUEST:
return state.setIn(['directory', 'isLoading'], true);
case DIRECTORY_FETCH_FAIL:
case DIRECTORY_EXPAND_FAIL:
return state.setIn(['directory', 'isLoading'], false);
case FEATURED_TAGS_FETCH_SUCCESS:
return normalizeFeaturedTags(state, ['featured_tags', action.id], action.tags, action.id);
case FEATURED_TAGS_FETCH_REQUEST:
return state.setIn(['featured_tags', action.id, 'isLoading'], true);
case FEATURED_TAGS_FETCH_FAIL:
return state.setIn(['featured_tags', action.id, 'isLoading'], false);
default:
return state;
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 FOLLOWERS_FETCH_REQUEST:
case FOLLOWERS_EXPAND_REQUEST:
return state.setIn(["followers", action.id, "isLoading"], true);
case FOLLOWERS_FETCH_FAIL:
case FOLLOWERS_EXPAND_FAIL:
return state.setIn(["followers", action.id, "isLoading"], false);
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 FOLLOWING_FETCH_REQUEST:
case FOLLOWING_EXPAND_REQUEST:
return state.setIn(["following", action.id, "isLoading"], true);
case FOLLOWING_FETCH_FAIL:
case FOLLOWING_EXPAND_FAIL:
return state.setIn(["following", action.id, "isLoading"], false);
case REBLOGS_FETCH_SUCCESS:
return normalizeList(state, ["reblogged_by", action.id], action.accounts, action.next);
case REBLOGS_EXPAND_SUCCESS:
return appendToList(state, ["reblogged_by", action.id], action.accounts, action.next);
case REBLOGS_FETCH_REQUEST:
case REBLOGS_EXPAND_REQUEST:
return state.setIn(["reblogged_by", action.id, "isLoading"], true);
case REBLOGS_FETCH_FAIL:
case REBLOGS_EXPAND_FAIL:
return state.setIn(["reblogged_by", action.id, "isLoading"], false);
case FAVOURITES_FETCH_SUCCESS:
return normalizeList(state, ["favourited_by", action.id], action.accounts, action.next);
case FAVOURITES_EXPAND_SUCCESS:
return appendToList(state, ["favourited_by", action.id], action.accounts, action.next);
case FAVOURITES_FETCH_REQUEST:
case FAVOURITES_EXPAND_REQUEST:
return state.setIn(["favourited_by", action.id, "isLoading"], true);
case FAVOURITES_FETCH_FAIL:
case FAVOURITES_EXPAND_FAIL:
return state.setIn(["favourited_by", action.id, "isLoading"], false);
case NOTIFICATIONS_UPDATE:
return action.notification.type === "follow_request" ? normalizeFollowRequest(state, action.notification) : state;
case FOLLOW_REQUESTS_FETCH_SUCCESS:
return normalizeList(state, ["follow_requests"], action.accounts, action.next);
case FOLLOW_REQUESTS_EXPAND_SUCCESS:
return appendToList(state, ["follow_requests"], action.accounts, action.next);
case FOLLOW_REQUESTS_FETCH_REQUEST:
case FOLLOW_REQUESTS_EXPAND_REQUEST:
return state.setIn(["follow_requests", "isLoading"], true);
case FOLLOW_REQUESTS_FETCH_FAIL:
case FOLLOW_REQUESTS_EXPAND_FAIL:
return state.setIn(["follow_requests", "isLoading"], false);
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 normalizeList(state, ["blocks"], action.accounts, action.next);
case BLOCKS_EXPAND_SUCCESS:
return appendToList(state, ["blocks"], action.accounts, action.next);
case BLOCKS_FETCH_REQUEST:
case BLOCKS_EXPAND_REQUEST:
return state.setIn(["blocks", "isLoading"], true);
case BLOCKS_FETCH_FAIL:
case BLOCKS_EXPAND_FAIL:
return state.setIn(["blocks", "isLoading"], false);
case MUTES_FETCH_SUCCESS:
return normalizeList(state, ["mutes"], action.accounts, action.next);
case MUTES_EXPAND_SUCCESS:
return appendToList(state, ["mutes"], action.accounts, action.next);
case MUTES_FETCH_REQUEST:
case MUTES_EXPAND_REQUEST:
return state.setIn(["mutes", "isLoading"], true);
case MUTES_FETCH_FAIL:
case MUTES_EXPAND_FAIL:
return state.setIn(["mutes", "isLoading"], false);
case DIRECTORY_FETCH_SUCCESS:
return normalizeList(state, ["directory"], action.accounts, action.next);
case DIRECTORY_EXPAND_SUCCESS:
return appendToList(state, ["directory"], action.accounts, action.next);
case DIRECTORY_FETCH_REQUEST:
case DIRECTORY_EXPAND_REQUEST:
return state.setIn(["directory", "isLoading"], true);
case DIRECTORY_FETCH_FAIL:
case DIRECTORY_EXPAND_FAIL:
return state.setIn(["directory", "isLoading"], false);
case FEATURED_TAGS_FETCH_SUCCESS:
return normalizeFeaturedTags(state, ["featured_tags", action.id], action.tags, action.id);
case FEATURED_TAGS_FETCH_REQUEST:
return state.setIn(["featured_tags", action.id, "isLoading"], true);
case FEATURED_TAGS_FETCH_FAIL:
return state.setIn(["featured_tags", action.id, "isLoading"], false);
default:
return state;
}
}