pl-fe: migrations off immutable

Signed-off-by: marcin mikołajczak <git@mkljczk.pl>
This commit is contained in:
marcin mikołajczak 2024-11-10 00:22:03 +01:00
parent 9f51735099
commit 7b405ef1d0
16 changed files with 81 additions and 74 deletions

View file

@ -59,7 +59,7 @@ const LIST_ADDER_LISTS_FETCH_FAIL = 'LIST_ADDER_LISTS_FETCH_FAIL' as const;
const fetchList = (listId: string) => (dispatch: AppDispatch, getState: () => RootState) => {
if (!isLoggedIn(getState)) return;
if (getState().lists.get(listId)) {
if (getState().lists[listId]) {
return;
}
@ -124,7 +124,7 @@ const submitListEditor = (shouldReset?: boolean) => (dispatch: AppDispatch, getS
const setupListEditor = (listId: string) => (dispatch: AppDispatch, getState: () => RootState) => {
dispatch({
type: LIST_EDITOR_SETUP,
list: getState().lists.get(String(listId)),
list: getState().lists[listId],
});
dispatch(fetchListAccounts(listId));

View file

@ -44,7 +44,7 @@ const unsubscribe = ({ registration, subscription }: {
const sendSubscriptionToBackend = (subscription: PushSubscription, me: Me) =>
(dispatch: AppDispatch, getState: () => RootState) => {
const alerts = getState().push_notifications.alerts.toJS() as Record<string, boolean>;
const alerts = getState().push_notifications.alerts;
const params = { subscription, data: { alerts } };
if (me) {
@ -138,7 +138,7 @@ const register = () =>
const saveSettings = () =>
(dispatch: AppDispatch, getState: () => RootState) => {
const state = getState().push_notifications;
const alerts = state.alerts.toJS();
const alerts = state.alerts;
const data = { alerts };
const me = getState().me;

View file

@ -98,7 +98,7 @@ const SidebarMenu: React.FC = (): JSX.Element | null => {
const { settings } = useSettingsStore();
const followRequestsCount = useAppSelector((state) => state.user_lists.follow_requests.items.length);
const interactionRequestsCount = useInteractionRequestsCount().data || 0;
const scheduledStatusCount = useAppSelector((state) => state.scheduled_statuses.size);
const scheduledStatusCount = useAppSelector((state) => Object.keys(state.scheduled_statuses).length);
const draftCount = useAppSelector((state) => Object.keys(state.draft_statuses).length);
// const dashboardCount = useAppSelector((state) => state.admin.openReports.count() + state.admin.awaitingApproval.count());
const [sidebarVisible, setSidebarVisible] = useState(isSidebarOpen);

View file

@ -51,7 +51,7 @@ const SidebarNavigation = () => {
const followRequestsCount = useAppSelector((state) => state.user_lists.follow_requests.items.length);
const interactionRequestsCount = useInteractionRequestsCount().data || 0;
const dashboardCount = useAppSelector((state) => state.admin.openReports.length + state.admin.awaitingApproval.length);
const scheduledStatusCount = useAppSelector((state) => state.scheduled_statuses.size);
const scheduledStatusCount = useAppSelector((state) => Object.keys(state.scheduled_statuses).length);
const draftCount = useAppSelector((state) => Object.keys(state.draft_statuses).length);
const restrictUnauth = instance.pleroma.metadata.restrict_unauthenticated;

View file

@ -78,10 +78,10 @@ const getItems = (features: Features, lists: ReturnType<typeof getOrderedLists>,
text: intl.formatMessage(messages.local_short),
meta: intl.formatMessage(messages.local_long),
} : undefined,
features.addressableLists && !lists.isEmpty() ? {
features.addressableLists && Object.keys(lists).length ? {
icon: require('@tabler/icons/outline/list.svg'),
value: '',
items: lists.toArray().map((list) => ({
items: Object.values(lists).map((list) => ({
icon: require('@tabler/icons/outline/list.svg'),
value: `list:${list.id}`,
text: list.title,

View file

@ -34,7 +34,7 @@ const ListTimeline: React.FC = () => {
const isMobile = useIsMobile();
const { openModal } = useModalsStore();
const list = useAppSelector((state) => state.lists.get(id));
const list = useAppSelector((state) => state.lists[id]);
useListStream(id);

View file

@ -28,7 +28,7 @@ const getOrderedLists = createSelector([(state: RootState) => state.lists], list
return lists;
}
return lists.toList().filter((item): item is ListEntity => !!item).sort((a, b) => a.title.localeCompare(b.title));
return Object.values(lists).filter((item): item is ListEntity => !!item).sort((a, b) => a.title.localeCompare(b.title));
});
const Lists: React.FC = () => {
@ -56,7 +56,7 @@ const Lists: React.FC = () => {
<Stack space={4}>
<NewListForm />
{lists.isEmpty() ? (
{!Object.keys(lists).length ? (
<Card variant='rounded' size='lg'>
{emptyMessage}
</Card>

View file

@ -20,7 +20,7 @@ interface IScheduledStatus {
const ScheduledStatus: React.FC<IScheduledStatus> = ({ statusId, ...other }) => {
const status = useAppSelector((state) => {
const scheduledStatus = state.scheduled_statuses.get(statusId);
const scheduledStatus = state.scheduled_statuses[statusId];
if (!scheduledStatus) return null;
return buildStatus(state, scheduledStatus);
});

View file

@ -20,7 +20,7 @@ const List: React.FC<IList> = ({ listId }) => {
const intl = useIntl();
const dispatch = useAppDispatch();
const list = useAppSelector((state) => state.lists.get(listId));
const list = useAppSelector((state) => state.lists[listId]);
const added = useAppSelector((state) => state.listAdder.lists.items.includes(listId));
const onRemove = () => dispatch(removeFromListAdder(listId));

View file

@ -61,7 +61,7 @@ const ListAdderModal: React.FC<BaseModalProps & ListAdderModalProps> = ({ accoun
<CardTitle title={intl.formatMessage(messages.subheading)} />
</CardHeader>
<div>
{listIds.map(ListId => <List key={ListId} listId={ListId} />)}
{listIds.map(listId => <List key={listId} listId={listId} />)}
</div>
</Modal>
);

View file

@ -1,18 +1,14 @@
import { List as ImmutableList } from 'immutable';
import { FILTERS_FETCH_SUCCESS } from '../actions/filters';
import type { Filter } from 'pl-api';
import type { AnyAction } from 'redux';
type State = ImmutableList<Filter>;
type State = Array<Filter>;
const importFilters = (_state: State, filters: Array<Filter>): State => ImmutableList(filters);
const filters = (state: State = ImmutableList(), action: AnyAction): State => {
const filters = (state: State = [], action: AnyAction): State => {
switch (action.type) {
case FILTERS_FETCH_SUCCESS:
return importFilters(state, action.filters);
return action.filters;
default:
return state;
}

View file

@ -1,4 +1,3 @@
import { Map as ImmutableMap } from 'immutable';
import { create } from 'mutative';
import { type Instance, instanceSchema, PleromaConfig } from 'pl-api';
import * as v from 'valibot';
@ -20,11 +19,11 @@ const preloadImport = (state: State, action: Record<string, any>, path: string)
return instance ? v.parse(instanceSchema, instance) : state;
};
const getConfigValue = (instanceConfig: ImmutableMap<string, any>, key: string) => {
const getConfigValue = (instanceConfig: Array<any>, key: string) => {
const v = instanceConfig
.find(value => value.getIn(['tuple', 0]) === key);
.find(value => value?.tuple?.[0] === key);
return v ? v.getIn(['tuple', 1]) : undefined;
return v ? v?.tuple?.[1] : undefined;
};
const importConfigs = (state: State, configs: PleromaConfig['configs']) => {

View file

@ -1,4 +1,4 @@
import { Map as ImmutableMap } from 'immutable';
import { create } from 'mutative';
import {
LIST_FETCH_SUCCESS,
@ -12,18 +12,16 @@ import {
import type { List } from 'pl-api';
import type { AnyAction } from 'redux';
type State = ImmutableMap<string, List | false>;
type State = Record<string, List | false>;
const initialState: State = ImmutableMap();
const initialState: State = {};
const importList = (state: State, list: List) => state.set(list.id, list);
const importList = (state: State, list: List) => {
state[list.id] = list;
};
const importLists = (state: State, lists: Array<List>) => {
lists.forEach(list => {
state = importList(state, list);
});
return state;
lists.forEach(list => importList(state, list));
};
const lists = (state: State = initialState, action: AnyAction) => {
@ -31,12 +29,18 @@ const lists = (state: State = initialState, action: AnyAction) => {
case LIST_FETCH_SUCCESS:
case LIST_CREATE_SUCCESS:
case LIST_UPDATE_SUCCESS:
return importList(state, action.list);
return create(state, (draft) => {
importList(draft, action.list);
});
case LISTS_FETCH_SUCCESS:
return importLists(state, action.lists);
return create(state, (draft) => {
importLists(draft, action.lists);
});
case LIST_DELETE_SUCCESS:
case LIST_FETCH_FAIL:
return state.set(action.listId, false);
return create(state, (draft) => {
draft[action.listId] = false;
});
default:
return state;
}

View file

@ -1,44 +1,52 @@
import { Map as ImmutableMap, Record as ImmutableRecord } from 'immutable';
import { create } from 'mutative';
import { SET_BROWSER_SUPPORT, SET_SUBSCRIPTION, CLEAR_SUBSCRIPTION } from '../actions/push-notifications';
import type { SetterAction } from 'pl-fe/actions/push-notifications/setter';
const SubscriptionRecord = ImmutableRecord({
id: '',
endpoint: '',
});
interface Subscription {
id: string;
endpoint: string;
}
const ReducerRecord = ImmutableRecord({
subscription: null as Subscription | null,
alerts: ImmutableMap<string, boolean>({
interface State {
subscription: Subscription | null;
alerts: Record<string, boolean>;
isSubscribed: boolean;
browserSupport: boolean;
}
const initialState: State = {
subscription: null,
alerts: {
follow: true,
follow_request: true,
favourite: true,
reblog: true,
mention: true,
poll: true,
}),
},
isSubscribed: false,
browserSupport: false,
});
};
type Subscription = ReturnType<typeof SubscriptionRecord>;
const push_subscriptions = (state = ReducerRecord(), action: SetterAction) => {
const push_subscriptions = (state = initialState, action: SetterAction): State => {
switch (action.type) {
case SET_SUBSCRIPTION:
return state
.set('subscription', SubscriptionRecord({
return create(state, (draft) => {
draft.subscription = {
id: action.subscription.id,
endpoint: action.subscription.endpoint,
}))
.set('alerts', ImmutableMap(action.subscription.alerts))
.set('isSubscribed', true);
};
draft.alerts = action.subscription.alerts;
draft.isSubscribed = true;
});
case SET_BROWSER_SUPPORT:
return state.set('browserSupport', action.value);
return create(state, (draft) => {
draft.browserSupport = action.value;
});
case CLEAR_SUBSCRIPTION:
return ReducerRecord();
return initialState;
default:
return state;
}

View file

@ -1,4 +1,4 @@
import { Map as ImmutableMap } from 'immutable';
import { create } from 'mutative';
import { STATUS_IMPORT, STATUSES_IMPORT, type ImporterAction } from 'pl-fe/actions/importer';
import {
@ -11,31 +11,34 @@ import { STATUS_CREATE_SUCCESS } from 'pl-fe/actions/statuses';
import type { Status, ScheduledStatus } from 'pl-api';
import type { AnyAction } from 'redux';
type State = ImmutableMap<string, ScheduledStatus>;
type State = Record<string, ScheduledStatus>;
const initialState: State = ImmutableMap();
const initialState: State = {};
const importStatus = (state: State, status: Status | ScheduledStatus) => {
if (!status.scheduled_at) return state;
return state.set(status.id, status);
state[status.id] = status;
};
const importStatuses = (state: State, statuses: Array<Status | ScheduledStatus>) =>
state.withMutations(mutable => statuses.forEach(status => importStatus(mutable, status)));
const importStatuses = (state: State, statuses: Array<Status | ScheduledStatus>) => {
statuses.forEach(status => importStatus(state, status));
};
const deleteStatus = (state: State, statusId: string) => state.delete(statusId);
const deleteStatus = (state: State, statusId: string) => {
delete state[statusId];
};
const scheduled_statuses = (state: State = initialState, action: AnyAction | ImporterAction) => {
switch (action.type) {
case STATUS_IMPORT:
case STATUS_CREATE_SUCCESS:
return importStatus(state, action.status);
return create(state, (draft) => importStatus(draft, action.status));
case STATUSES_IMPORT:
case SCHEDULED_STATUSES_FETCH_SUCCESS:
return importStatuses(state, action.statuses);
return create(state, (draft) => importStatuses(draft, action.statuses));
case SCHEDULED_STATUS_CANCEL_REQUEST:
case SCHEDULED_STATUS_CANCEL_SUCCESS:
return deleteStatus(state, action.statusId);
return create(state, (draft) => deleteStatus(draft, action.statusId));
default:
return state;
}

View file

@ -1,7 +1,4 @@
import {
List as ImmutableList,
OrderedSet as ImmutableOrderedSet,
} from 'immutable';
import { OrderedSet as ImmutableOrderedSet } from 'immutable';
import { createSelector } from 'reselect';
// import { getLocale } from 'pl-fe/actions/settings';
@ -80,8 +77,8 @@ const getFilters = (state: RootState, query: FilterContext) =>
const escapeRegExp = (string: string) =>
string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string
const regexFromFilters = (filters: ImmutableList<Filter>) => {
if (filters.size === 0) return null;
const regexFromFilters = (filters: Array<Filter>) => {
if (filters.length === 0) return null;
return new RegExp(filters.map(filter =>
filter.keywords.map(keyword => {
@ -102,7 +99,7 @@ const regexFromFilters = (filters: ImmutableList<Filter>) => {
).join('|'), 'i');
};
const checkFiltered = (index: string, filters: ImmutableList<Filter>) =>
const checkFiltered = (index: string, filters: Array<Filter>) =>
filters.reduce((result: Array<string>, filter) =>
result.concat(filter.keywords.reduce((result: Array<string>, keyword) => {
let expr = escapeRegExp(keyword.keyword);