Wip: bookmark categories

This commit is contained in:
KMY 2023-08-26 10:26:45 +09:00
parent 020e50d0c5
commit f6bdd9b6de
13 changed files with 866 additions and 1 deletions

View file

@ -0,0 +1,71 @@
import { Map as ImmutableMap, fromJS, OrderedSet as ImmutableOrderedSet } from 'immutable';
import {
BOOKMARK_CATEGORY_FETCH_SUCCESS,
BOOKMARK_CATEGORY_FETCH_FAIL,
BOOKMARK_CATEGORIES_FETCH_SUCCESS,
BOOKMARK_CATEGORY_CREATE_SUCCESS,
BOOKMARK_CATEGORY_UPDATE_SUCCESS,
BOOKMARK_CATEGORY_DELETE_SUCCESS,
BOOKMARK_CATEGORY_STATUSES_FETCH_REQUEST,
BOOKMARK_CATEGORY_STATUSES_FETCH_SUCCESS,
BOOKMARK_CATEGORY_STATUSES_FETCH_FAIL,
BOOKMARK_CATEGORY_STATUSES_EXPAND_REQUEST,
BOOKMARK_CATEGORY_STATUSES_EXPAND_SUCCESS,
BOOKMARK_CATEGORY_STATUSES_EXPAND_FAIL,
} from '../actions/bookmark_categories';
const initialState = ImmutableMap();
const normalizeBookmarkCategory = (state, category) => state.set(category.id, fromJS(category));
const normalizeBookmarkCategories = (state, bookmarkCategories) => {
bookmarkCategories.forEach(bookmarkCategory => {
state = normalizeBookmarkCategory(state, bookmarkCategory);
});
return state;
};
const normalizeBookmarkCategoryStatuses = (state, bookmaryCategoryId, statuses, next) => {
return state.updateIn([bookmaryCategoryId, 'items'], 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)));
}));
};
const appendToBookmarkCategoryStatuses = (state, bookmarkCategoryId, statuses, next) => {
return state.updateIn([bookmarkCategoryId, 'items'], listMap => listMap.withMutations(map => {
map.set('next', next);
map.set('isLoading', false);
map.set('items', map.get('items').union(statuses.map(item => item.id)));
}));
};
export default function bookmarkCategories(state = initialState, action) {
switch(action.type) {
case BOOKMARK_CATEGORY_FETCH_SUCCESS:
case BOOKMARK_CATEGORY_CREATE_SUCCESS:
case BOOKMARK_CATEGORY_UPDATE_SUCCESS:
return normalizeBookmarkCategory(state, action.bookmarkCategory);
case BOOKMARK_CATEGORIES_FETCH_SUCCESS:
return normalizeBookmarkCategories(state, action.bookmarkCategories);
case BOOKMARK_CATEGORY_DELETE_SUCCESS:
case BOOKMARK_CATEGORY_FETCH_FAIL:
return state.set(action.id, false);
case BOOKMARK_CATEGORY_STATUSES_FETCH_REQUEST:
case BOOKMARK_CATEGORY_STATUSES_EXPAND_REQUEST:
return state.setIn([action.id, 'isLoading'], true);
case BOOKMARK_CATEGORY_STATUSES_FETCH_FAIL:
case BOOKMARK_CATEGORY_STATUSES_EXPAND_FAIL:
return state.setIn([action.id, 'isLoading'], false);
case BOOKMARK_CATEGORY_STATUSES_FETCH_SUCCESS:
return normalizeBookmarkCategoryStatuses(state, action.id, action.statuses, action.next);
case BOOKMARK_CATEGORY_STATUSES_EXPAND_SUCCESS:
return appendToBookmarkCategoryStatuses(state, action.id, action.statuses, action.next);
default:
return state;
}
}

View file

@ -0,0 +1,74 @@
import { Map as ImmutableMap, List as ImmutableList } from 'immutable';
import {
BOOKMARK_CATEGORY_CREATE_REQUEST,
BOOKMARK_CATEGORY_CREATE_FAIL,
BOOKMARK_CATEGORY_CREATE_SUCCESS,
BOOKMARK_CATEGORY_UPDATE_REQUEST,
BOOKMARK_CATEGORY_UPDATE_FAIL,
BOOKMARK_CATEGORY_UPDATE_SUCCESS,
BOOKMARK_CATEGORY_EDITOR_RESET,
BOOKMARK_CATEGORY_EDITOR_SETUP,
BOOKMARK_CATEGORY_EDITOR_TITLE_CHANGE,
BOOKMARK_CATEGORY_EDITOR_ADD_SUCCESS,
BOOKMARK_CATEGORY_EDITOR_REMOVE_SUCCESS,
} from '../actions/bookmark_categories';
const initialState = ImmutableMap({
bookmaryCategoryId: null,
isSubmitting: false,
isChanged: false,
title: '',
isExclusive: false,
statuses: ImmutableMap({
items: ImmutableList(),
loaded: false,
isLoading: false,
}),
suggestions: ImmutableMap({
value: '',
items: ImmutableList(),
}),
});
export default function bookmaryCategoryEditorReducer(state = initialState, action) {
switch(action.type) {
case BOOKMARK_CATEGORY_EDITOR_RESET:
return initialState;
case BOOKMARK_CATEGORY_EDITOR_SETUP:
return state.withMutations(map => {
map.set('bookmaryCategoryId', action.bookmaryCategory.get('id'));
map.set('title', action.bookmaryCategory.get('title'));
map.set('isExclusive', action.bookmaryCategory.get('is_exclusive'));
map.set('isSubmitting', false);
});
case BOOKMARK_CATEGORY_EDITOR_TITLE_CHANGE:
return state.withMutations(map => {
map.set('title', action.value);
map.set('isChanged', true);
});
case BOOKMARK_CATEGORY_CREATE_REQUEST:
case BOOKMARK_CATEGORY_UPDATE_REQUEST:
return state.withMutations(map => {
map.set('isSubmitting', true);
map.set('isChanged', false);
});
case BOOKMARK_CATEGORY_CREATE_FAIL:
case BOOKMARK_CATEGORY_UPDATE_FAIL:
return state.set('isSubmitting', false);
case BOOKMARK_CATEGORY_CREATE_SUCCESS:
case BOOKMARK_CATEGORY_UPDATE_SUCCESS:
return state.withMutations(map => {
map.set('isSubmitting', false);
map.set('bookmaryCategoryId', action.bookmaryCategory.id);
});
case BOOKMARK_CATEGORY_EDITOR_ADD_SUCCESS:
return state.updateIn(['accounts', 'items'], bookmaryCategory => bookmaryCategory.unshift(action.accountId));
case BOOKMARK_CATEGORY_EDITOR_REMOVE_SUCCESS:
return state.updateIn(['accounts', 'items'], bookmaryCategory => bookmaryCategory.filterNot(item => item === action.accountId));
default:
return state;
}
}

View file

@ -12,6 +12,8 @@ import antennaAdder from './antenna_adder';
import antennaEditor from './antenna_editor';
import antennas from './antennas';
import blocks from './blocks';
import bookmark_categories from './bookmark_categories';
import bookmarkCategoryEditor from './bookmark_category_editor';
import boosts from './boosts';
import circleAdder from './circle_adder';
import circleEditor from './circle_editor';
@ -89,6 +91,8 @@ const reducers = {
circles,
circleEditor,
circleAdder,
bookmark_categories,
bookmarkCategoryEditor,
filters,
conversations,
suggestions,

View file

@ -1,5 +1,8 @@
import { Map as ImmutableMap, fromJS } from 'immutable';
import { ANTENNA_DELETE_SUCCESS, ANTENNA_FETCH_FAIL } from 'mastodon/actions/antennas';
import { CIRCLE_DELETE_SUCCESS, CIRCLE_FETCH_FAIL } from 'mastodon/actions/circles';
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';
@ -142,6 +145,10 @@ const updateFrequentLanguages = (state, language) => state.update('frequentlyUse
const filterDeadListColumns = (state, listId) => state.update('columns', columns => columns.filterNot(column => column.get('id') === 'LIST' && column.get('params').get('id') === listId));
const filterDeadAntennaColumns = (state, antennaId) => state.update('columns', columns => columns.filterNot(column => column.get('id') === 'ANTENNA' && column.get('params').get('id') === antennaId));
const filterDeadCircleColumns = (state, circleId) => state.update('columns', columns => columns.filterNot(column => column.get('id') === 'CIRCLE' && column.get('params').get('id') === circleId));
export default function settings(state = initialState, action) {
switch(action.type) {
case STORE_HYDRATE:
@ -173,6 +180,14 @@ export default function settings(state = initialState, action) {
return action.error.response.status === 404 ? filterDeadListColumns(state, action.id) : state;
case LIST_DELETE_SUCCESS:
return filterDeadListColumns(state, action.id);
case ANTENNA_FETCH_FAIL:
return action.error.response.status === 404 ? filterDeadAntennaColumns(state, action.id) : state;
case ANTENNA_DELETE_SUCCESS:
return filterDeadAntennaColumns(state, action.id);
case CIRCLE_FETCH_FAIL:
return action.error.response.status === 404 ? filterDeadCircleColumns(state, action.id) : state;
case CIRCLE_DELETE_SUCCESS:
return filterDeadCircleColumns(state, action.id);
default:
return state;
}