pl-fe: Complete migration of settings store
Signed-off-by: marcin mikołajczak <git@mkljczk.pl>
This commit is contained in:
parent
e4615b70f7
commit
97d1ce2f47
12 changed files with 51 additions and 110 deletions
|
@ -294,14 +294,14 @@ const scrollTopNotifications = (top: boolean) =>
|
|||
|
||||
const setFilter = (filterType: FilterType, abort?: boolean) =>
|
||||
(dispatch: AppDispatch) => {
|
||||
const activeFilter = useSettingsStore.getState().settings.notifications.quickFilter.active as FilterType;
|
||||
const settingsStore = useSettingsStore.getState();
|
||||
const activeFilter = settingsStore.settings.notifications.quickFilter.active as FilterType;
|
||||
|
||||
dispatch({
|
||||
type: NOTIFICATIONS_FILTER_SET,
|
||||
path: ['notifications', 'quickFilter', 'active'],
|
||||
value: filterType,
|
||||
});
|
||||
settingsStore.changeSetting(['notifications', 'quickFilter', 'active'], filterType);
|
||||
|
||||
dispatch({ type: NOTIFICATIONS_FILTER_SET });
|
||||
dispatch(expandNotifications(undefined, undefined, abort));
|
||||
|
||||
if (activeFilter !== filterType) dispatch(saveSettings());
|
||||
};
|
||||
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
import { useSettingsStore } from 'pl-fe/stores/settings';
|
||||
|
||||
import { getClient } from '../api';
|
||||
|
||||
import { fetchRelationships } from './accounts';
|
||||
|
@ -88,9 +90,10 @@ const setFilter = (value: string, filterType: SearchFilter) =>
|
|||
(dispatch: AppDispatch) => {
|
||||
dispatch(submitSearch(value, filterType));
|
||||
|
||||
useSettingsStore.getState().changeSetting(['search', 'filter'], filterType);
|
||||
|
||||
return dispatch({
|
||||
type: SEARCH_FILTER_SET,
|
||||
path: ['search', 'filter'],
|
||||
value: filterType,
|
||||
});
|
||||
};
|
||||
|
|
|
@ -11,8 +11,6 @@ import { isLoggedIn } from 'pl-fe/utils/auth';
|
|||
|
||||
import type { AppDispatch, RootState } from 'pl-fe/store';
|
||||
|
||||
const SETTING_CHANGE = 'SETTING_CHANGE' as const;
|
||||
|
||||
const FE_NAME = 'pl_fe';
|
||||
|
||||
const getAccount = makeGetAccount();
|
||||
|
@ -129,33 +127,9 @@ const saveSuccessMessage = defineMessage({ id: 'settings.save.success', defaultM
|
|||
// }),
|
||||
// });
|
||||
|
||||
interface SettingChangeAction {
|
||||
type: typeof SETTING_CHANGE;
|
||||
path: string[];
|
||||
value: any;
|
||||
}
|
||||
|
||||
const changeSettingImmediate = (path: string[], value: any, opts?: SettingOpts) =>
|
||||
(dispatch: AppDispatch) => {
|
||||
const action: SettingChangeAction = {
|
||||
type: SETTING_CHANGE,
|
||||
path,
|
||||
value,
|
||||
};
|
||||
|
||||
dispatch(action);
|
||||
dispatch(saveSettings(opts));
|
||||
};
|
||||
|
||||
const changeSetting = (path: string[], value: any, opts?: SettingOpts) =>
|
||||
(dispatch: AppDispatch) => {
|
||||
const action: SettingChangeAction = {
|
||||
type: SETTING_CHANGE,
|
||||
path,
|
||||
value,
|
||||
};
|
||||
|
||||
dispatch(action);
|
||||
useSettingsStore.getState().changeSetting(path, value);
|
||||
return dispatch(saveSettings(opts));
|
||||
};
|
||||
|
||||
|
@ -214,16 +188,10 @@ const getLocale = (fallback = 'en') => {
|
|||
return Object.keys(messages).includes(localeWithVariant) ? localeWithVariant : Object.keys(messages).includes(locale) ? locale : fallback;
|
||||
};
|
||||
|
||||
type SettingsAction =
|
||||
| SettingChangeAction
|
||||
|
||||
export {
|
||||
SETTING_CHANGE,
|
||||
FE_NAME,
|
||||
changeSettingImmediate,
|
||||
changeSetting,
|
||||
saveSettings,
|
||||
updateSettingsStore,
|
||||
getLocale,
|
||||
type SettingsAction,
|
||||
};
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import React, { useState } from 'react';
|
||||
import { FormattedMessage, defineMessages, useIntl } from 'react-intl';
|
||||
|
||||
import { changeSettingImmediate } from 'pl-fe/actions/settings';
|
||||
import { changeSetting } from 'pl-fe/actions/settings';
|
||||
import { Column, Button, Form, FormActions, FormGroup, Input, Text } from 'pl-fe/components/ui';
|
||||
import { useAppDispatch } from 'pl-fe/hooks';
|
||||
import toast from 'pl-fe/toast';
|
||||
|
@ -26,7 +26,7 @@ const DevelopersChallenge = () => {
|
|||
|
||||
const handleSubmit = () => {
|
||||
if (answer === 'fe-pl') {
|
||||
dispatch(changeSettingImmediate(['isDeveloper'], true));
|
||||
dispatch(changeSetting(['isDeveloper'], true));
|
||||
toast.success(intl.formatMessage(messages.success));
|
||||
} else {
|
||||
toast.error(intl.formatMessage(messages.fail));
|
||||
|
|
|
@ -2,7 +2,7 @@ import React from 'react';
|
|||
import { FormattedMessage, defineMessages, useIntl } from 'react-intl';
|
||||
import { Link, useHistory } from 'react-router-dom';
|
||||
|
||||
import { changeSettingImmediate } from 'pl-fe/actions/settings';
|
||||
import { changeSetting } from 'pl-fe/actions/settings';
|
||||
import { Column, Text } from 'pl-fe/components/ui';
|
||||
import SvgIcon from 'pl-fe/components/ui/icon/svg-icon';
|
||||
import { useAppDispatch } from 'pl-fe/hooks';
|
||||
|
@ -38,7 +38,7 @@ const Developers: React.FC = () => {
|
|||
const leaveDevelopers = (e: React.MouseEvent<HTMLButtonElement>) => {
|
||||
e.preventDefault();
|
||||
|
||||
dispatch(changeSettingImmediate(['isDeveloper'], false));
|
||||
dispatch(changeSetting(['isDeveloper'], false));
|
||||
toast.success(intl.formatMessage(messages.leave));
|
||||
history.push('/');
|
||||
};
|
||||
|
|
|
@ -22,8 +22,8 @@ const STATUS_TYPE_ICONS: Record<string, string> = {
|
|||
direct: require('@tabler/icons/outline/mail.svg'),
|
||||
private: require('@tabler/icons/outline/lock.svg'),
|
||||
mutuals_only: require('@tabler/icons/outline/users-group.svg'),
|
||||
local: require('@tabler/icons/outline/affiliate.svg'),
|
||||
list: require('@tabler/icons/outline/list.svg'),
|
||||
local: require('@tabler/icons/outline/affiliate.svg'),
|
||||
list: require('@tabler/icons/outline/list.svg'),
|
||||
};
|
||||
|
||||
const StatusTypeIcon: React.FC<IStatusTypeIcon> = ({ status }) => {
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
* globals: do things through the console.
|
||||
* This feature is for developers.
|
||||
*/
|
||||
import { changeSettingImmediate } from 'pl-fe/actions/settings';
|
||||
import { changeSetting } from 'pl-fe/actions/settings';
|
||||
|
||||
import type { Store } from 'pl-fe/store';
|
||||
|
||||
|
@ -14,7 +14,7 @@ const createGlobals = (store: Store) => {
|
|||
if (![true, false].includes(bool)) {
|
||||
throw `Invalid option ${bool}. Must be true or false.`;
|
||||
}
|
||||
store.dispatch(changeSettingImmediate(['isDeveloper'], bool) as any);
|
||||
store.dispatch(changeSetting(['isDeveloper'], bool) as any);
|
||||
return bool;
|
||||
},
|
||||
};
|
||||
|
|
|
@ -62,7 +62,7 @@ import {
|
|||
} from '../actions/compose';
|
||||
import { EVENT_COMPOSE_CANCEL, EVENT_FORM_SET, type EventsAction } from '../actions/events';
|
||||
import { ME_FETCH_SUCCESS, ME_PATCH_SUCCESS, MeAction } from '../actions/me';
|
||||
import { SETTING_CHANGE, FE_NAME, SettingsAction } from '../actions/settings';
|
||||
import { FE_NAME } from '../actions/settings';
|
||||
import { TIMELINE_DELETE, TimelineAction } from '../actions/timelines';
|
||||
import { unescapeHTML } from '../utils/html';
|
||||
|
||||
|
@ -263,17 +263,17 @@ const importAccount = (compose: Compose, account: CredentialAccount) => {
|
|||
});
|
||||
};
|
||||
|
||||
const updateSetting = (compose: Compose, path: string[], value: string) => {
|
||||
const pathString = path.join(',');
|
||||
switch (pathString) {
|
||||
case 'defaultPrivacy':
|
||||
return compose.set('privacy', value);
|
||||
case 'defaultContentType':
|
||||
return compose.set('content_type', value);
|
||||
default:
|
||||
return compose;
|
||||
}
|
||||
};
|
||||
// const updateSetting = (compose: Compose, path: string[], value: string) => {
|
||||
// const pathString = path.join(',');
|
||||
// switch (pathString) {
|
||||
// case 'defaultPrivacy':
|
||||
// return compose.set('privacy', value);
|
||||
// case 'defaultContentType':
|
||||
// return compose.set('content_type', value);
|
||||
// default:
|
||||
// return compose;
|
||||
// }
|
||||
// };
|
||||
|
||||
const updateCompose = (state: State, key: string, updater: (compose: Compose) => Compose) =>
|
||||
state.update(key, state.get('default')!, updater);
|
||||
|
@ -282,7 +282,7 @@ const initialState: State = ImmutableMap({
|
|||
default: ReducerCompose({ idempotencyKey: crypto.randomUUID(), resetFileKey: getResetFileKey() }),
|
||||
});
|
||||
|
||||
const compose = (state = initialState, action: ComposeAction | EventsAction | MeAction | SettingsAction | TimelineAction) => {
|
||||
const compose = (state = initialState, action: ComposeAction | EventsAction | MeAction | TimelineAction) => {
|
||||
switch (action.type) {
|
||||
case COMPOSE_TYPE_CHANGE:
|
||||
return updateCompose(state, action.composeId, compose => compose.withMutations(map => {
|
||||
|
@ -544,8 +544,8 @@ const compose = (state = initialState, action: ComposeAction | EventsAction | Me
|
|||
case ME_FETCH_SUCCESS:
|
||||
case ME_PATCH_SUCCESS:
|
||||
return updateCompose(state, 'default', compose => importAccount(compose, action.me));
|
||||
case SETTING_CHANGE:
|
||||
return updateCompose(state, 'default', compose => updateSetting(compose, action.path, action.value));
|
||||
// case SETTING_CHANGE:
|
||||
// return updateCompose(state, 'default', compose => updateSetting(compose, action.path, action.value));
|
||||
case COMPOSE_EDITOR_STATE_SET:
|
||||
return updateCompose(state, action.composeId, compose => compose
|
||||
.setIn(!compose.modified_language || compose.modified_language === compose.language ? ['editorState'] : ['editorStateMap', compose.modified_language], action.editorState as string)
|
||||
|
|
|
@ -37,7 +37,6 @@ import push_notifications from './push-notifications';
|
|||
import scheduled_statuses from './scheduled-statuses';
|
||||
import search from './search';
|
||||
import security from './security';
|
||||
// import settings from './settings';
|
||||
import status_lists from './status-lists';
|
||||
import statuses from './statuses';
|
||||
import suggestions from './suggestions';
|
||||
|
@ -81,7 +80,6 @@ const reducers = {
|
|||
scheduled_statuses,
|
||||
search,
|
||||
security,
|
||||
// settings,
|
||||
status_lists,
|
||||
statuses,
|
||||
suggestions,
|
||||
|
|
|
@ -1,11 +0,0 @@
|
|||
import { Map as ImmutableMap } from 'immutable';
|
||||
|
||||
import reducer from './settings';
|
||||
|
||||
describe('settings reducer', () => {
|
||||
it('should return the initial state', () => {
|
||||
expect(reducer(undefined, {} as any)).toEqual(ImmutableMap({
|
||||
saved: true,
|
||||
}));
|
||||
});
|
||||
});
|
|
@ -1,34 +0,0 @@
|
|||
import { produce } from 'immer';
|
||||
import { AnyAction } from 'redux';
|
||||
|
||||
import { settingsSchema, type Settings } from 'pl-fe/schemas/pl-fe/settings';
|
||||
|
||||
import { NOTIFICATIONS_FILTER_SET } from '../actions/notifications';
|
||||
import { SEARCH_FILTER_SET } from '../actions/search';
|
||||
import { SETTING_CHANGE } from '../actions/settings';
|
||||
|
||||
type State = Partial<Settings>;
|
||||
|
||||
// Default settings are in action/settings.js
|
||||
//
|
||||
// Settings should be accessed with `getSettings(getState()).getIn(...)`
|
||||
// instead of directly from the state.
|
||||
const settings = (
|
||||
state: State = settingsSchema.partial().parse({}),
|
||||
action: AnyAction,
|
||||
): State => {
|
||||
switch (action.type) {
|
||||
case NOTIFICATIONS_FILTER_SET:
|
||||
case SEARCH_FILTER_SET:
|
||||
case SETTING_CHANGE:
|
||||
return produce(state, draft => {
|
||||
// @ts-ignore
|
||||
draft[action.path] = action.value;
|
||||
draft.saved = false;
|
||||
});
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
};
|
||||
|
||||
export { settings as default };
|
|
@ -17,10 +17,21 @@ type State = {
|
|||
loadDefaultSettings: (settings: APIEntity) => void;
|
||||
loadUserSettings: (settings: APIEntity) => void;
|
||||
userSettingsSaving: () => void;
|
||||
changeSetting: (path: string[], value: any) => void;
|
||||
rememberEmojiUse: (emoji: Emoji) => void;
|
||||
rememberLanguageUse: (language: string) => void;
|
||||
}
|
||||
|
||||
const changeSetting = (object: APIEntity, path: string[], value: any) => {
|
||||
if (path.length === 1) {
|
||||
object[path[0]] = value;
|
||||
return;
|
||||
}
|
||||
|
||||
if (typeof object[path[0]] !== 'object') object[path[0]] = {};
|
||||
return changeSetting(object[path[0]], path.slice(1), value);
|
||||
};
|
||||
|
||||
const mergeSettings = (state: State) => state.settings = { ...state.defaultSettings, ...state.userSettings };
|
||||
|
||||
const useSettingsStore = create<State>((set) => ({
|
||||
|
@ -49,6 +60,12 @@ const useSettingsStore = create<State>((set) => ({
|
|||
mergeSettings(state);
|
||||
})),
|
||||
|
||||
changeSetting: (path: string[], value: any) => set(produce((state: State) => {
|
||||
changeSetting(state.userSettings, path, value);
|
||||
|
||||
mergeSettings(state);
|
||||
})),
|
||||
|
||||
rememberEmojiUse: (emoji: Emoji) => set(produce((state: State) => {
|
||||
const settings = state.userSettings;
|
||||
if (!settings.frequentlyUsedEmojis) settings.frequentlyUsedEmojis = {};
|
||||
|
|
Loading…
Reference in a new issue