nicolium: migrate pending statuses store

Signed-off-by: nicole mikołajczyk <git@mkljczk.pl>
This commit is contained in:
nicole mikołajczyk
2026-02-23 14:26:56 +01:00
parent 1972ec4810
commit 76ec516b2d
6 changed files with 73 additions and 74 deletions

View File

@ -1,6 +1,7 @@
import { queryClient } from '@/queries/client';
import { scheduledStatusesQueryOptions } from '@/queries/statuses/scheduled-statuses';
import { useModalsStore } from '@/stores/modals';
import { usePendingStatusesStore } from '@/stores/pending-statuses';
import { useSettingsStore } from '@/stores/settings';
import { isLoggedIn } from '@/utils/auth';
import { shouldHaveCard } from '@/utils/status';
@ -50,7 +51,8 @@ const createStatus =
redacting = false,
) =>
(dispatch: AppDispatch, getState: () => RootState) => {
if (!params.preview)
if (!params.preview) {
usePendingStatusesStore.getState().actions.importStatus(params, idempotencyKey);
dispatch<StatusesAction>({
type: STATUS_CREATE_REQUEST,
params,
@ -58,6 +60,7 @@ const createStatus =
editing: !!editedId,
redacting,
});
}
const client = getClient(getState());
@ -116,6 +119,7 @@ const createStatus =
return status;
})
.catch((error) => {
usePendingStatusesStore.getState().actions.deleteStatus(idempotencyKey);
dispatch<StatusesAction>({
type: STATUS_CREATE_FAIL,
error,
@ -195,6 +199,7 @@ const deleteStatus =
: getClient(state).statuses.deleteStatus(statusId)
)
.then((response) => {
usePendingStatusesStore.getState().actions.deleteStatus(statusId);
dispatch<StatusesAction>({ type: STATUS_DELETE_SUCCESS, statusId });
dispatch(deleteFromTimelines(statusId));

View File

@ -1,4 +1,5 @@
import { getLocale } from '@/actions/settings';
import { usePendingStatusesStore } from '@/stores/pending-statuses';
import { useSettingsStore } from '@/stores/settings';
import { shouldFilter } from '@/utils/timelines';
@ -39,7 +40,8 @@ const processTimelineUpdate =
(timeline: string, status: BaseStatus) => (dispatch: AppDispatch, getState: () => RootState) => {
const me = getState().me;
const ownStatus = status.account?.id === me;
const hasPendingStatuses = !!getState().pending_statuses.length;
const hasPendingStatuses = Object.keys(usePendingStatusesStore.getState().statuses).length > 0;
const columnSettings = useSettingsStore.getState().settings.timelines[timeline];
const shouldSkipQueue = shouldFilter(

View File

@ -11,6 +11,7 @@ import PlaceholderCard from '@/features/placeholder/components/placeholder-card'
import PlaceholderMediaGallery from '@/features/placeholder/components/placeholder-media-gallery';
import QuotedStatus from '@/features/status/containers/quoted-status-container';
import { useAppSelector } from '@/hooks/use-app-selector';
import { usePendingStatus } from '@/stores/pending-statuses';
import { buildStatus } from '../util/pending-status-builder';
@ -48,8 +49,9 @@ const PendingStatus: React.FC<IPendingStatus> = ({
muted,
variant = 'rounded',
}) => {
const pendingStatus = usePendingStatus(idempotencyKey);
const status = useAppSelector((state) => {
const pendingStatus = state.pending_statuses[idempotencyKey];
return pendingStatus ? buildStatus(state, pendingStatus, idempotencyKey) : null;
});

View File

@ -15,7 +15,6 @@ import instance from './instance';
import me from './me';
import meta from './meta';
import notifications from './notifications';
import pending_statuses from './pending-statuses';
import push_notifications from './push-notifications';
import statuses from './statuses';
import timelines from './timelines';
@ -33,7 +32,6 @@ const reducers = {
me,
meta,
notifications,
pending_statuses,
push_notifications,
statuses,
timelines,

View File

@ -1,69 +0,0 @@
import { create } from 'mutative';
import { CreateStatusParams } from 'pl-api';
import {
STATUS_CREATE_FAIL,
STATUS_CREATE_REQUEST,
STATUS_CREATE_SUCCESS,
type StatusesAction,
} from '@/actions/statuses';
import type { StatusVisibility } from '@/normalizers/status';
interface PendingStatus {
content_type: string;
in_reply_to_id: string | null;
media_ids: Array<string> | null;
quote_id: string | null;
poll: Exclude<CreateStatusParams['poll'], undefined> | null;
sensitive: boolean;
spoiler_text: string;
status: string;
to: Array<string> | null;
visibility: StatusVisibility;
}
const newPendingStatus = (props: Partial<PendingStatus> = {}): PendingStatus => ({
content_type: '',
in_reply_to_id: null,
media_ids: null,
quote_id: null,
poll: null,
sensitive: false,
spoiler_text: '',
status: '',
to: null,
visibility: 'public',
...props,
});
type State = Record<string, PendingStatus>;
const initialState: State = {};
const importStatus = (state: State, params: Record<string, any>, idempotencyKey: string) => {
state[idempotencyKey] = newPendingStatus(params);
};
const deleteStatus = (state: State, idempotencyKey: string) => {
delete state[idempotencyKey];
};
const pending_statuses = (state = initialState, action: StatusesAction): State => {
switch (action.type) {
case STATUS_CREATE_REQUEST:
if (action.editing) return state;
return create(state, (draft) => {
importStatus(draft, action.params, action.idempotencyKey);
});
case STATUS_CREATE_FAIL:
case STATUS_CREATE_SUCCESS:
return create(state, (draft) => {
deleteStatus(draft, action.idempotencyKey);
});
default:
return state;
}
};
export { type PendingStatus, pending_statuses as default };

View File

@ -0,0 +1,61 @@
import { CreateStatusParams } from 'pl-api';
import { create } from 'zustand';
import { mutative } from 'zustand-mutative';
import type { StatusVisibility } from '@/normalizers/status';
interface PendingStatus {
content_type: string;
in_reply_to_id: string | null;
media_ids: Array<string> | null;
quote_id: string | null;
poll: Exclude<CreateStatusParams['poll'], undefined> | null;
sensitive: boolean;
spoiler_text: string;
status: string;
to: Array<string> | null;
visibility: StatusVisibility;
}
type State = {
statuses: Record<string, PendingStatus>;
actions: {
importStatus: (params: Partial<CreateStatusParams>, idempotencyKey: string) => void;
deleteStatus: (idempotencyKey: string) => void;
};
};
const usePendingStatusesStore = create<State>()(
mutative((set) => ({
statuses: {},
actions: {
importStatus: (params, idempotencyKey) => {
set((state: State) => {
state.statuses[idempotencyKey] = {
content_type: '',
in_reply_to_id: null,
media_ids: null,
quote_id: null,
poll: null,
sensitive: false,
spoiler_text: '',
status: '',
to: null,
visibility: 'public',
...params,
};
});
},
deleteStatus: (idempotencyKey) => {
set((state: State) => {
delete state.statuses[idempotencyKey];
});
},
},
})),
);
const usePendingStatus = (id: string) => usePendingStatusesStore((state) => state.statuses[id]);
const usePendingStatusesActions = () => usePendingStatusesStore((state) => state.actions);
export { usePendingStatusesStore, usePendingStatus, usePendingStatusesActions };