pl-fe: migrate pin/unpin

Signed-off-by: nicole mikołajczyk <git@mkljczk.pl>
This commit is contained in:
nicole mikołajczyk
2025-06-26 11:30:33 +02:00
parent 6faf7f48a3
commit 3f1d044880
5 changed files with 55 additions and 67 deletions

View File

@ -1,12 +1,3 @@
import { isLoggedIn } from 'pl-fe/utils/auth';
import { getClient } from '../api';
import { importEntities } from './importer';
import type { Status } from 'pl-api';
import type { AppDispatch, RootState } from 'pl-fe/store';
const REBLOG_REQUEST = 'REBLOG_REQUEST' as const;
const REBLOG_FAIL = 'REBLOG_FAIL' as const;
@ -81,53 +72,17 @@ interface UndislikeRequest {
statusId: string;
}
const pin = (status: Pick<Status, 'id'>, accountId: string) =>
(dispatch: AppDispatch, getState: () => RootState) => {
if (!isLoggedIn(getState)) return;
interface PinSuccess {
type: typeof PIN_SUCCESS;
statusId: string;
accountId: string;
}
return getClient(getState()).statuses.pinStatus(status.id).then(response => {
dispatch(importEntities({ statuses: [response] }));
dispatch(pinSuccess(response, accountId));
}).catch(error => {
});
};
const pinSuccess = (status: Status, accountId: string) => ({
type: PIN_SUCCESS,
status,
statusId: status.id,
accountId,
});
const unpin = (status: Pick<Status, 'id'>, accountId: string) =>
(dispatch: AppDispatch, getState: () => RootState) => {
if (!isLoggedIn(getState)) return;
return getClient(getState()).statuses.unpinStatus(status.id).then(response => {
dispatch(importEntities({ statuses: [response] }));
dispatch(unpinSuccess(response, accountId));
});
};
const togglePin = (status: Pick<Status, 'id' | 'pinned'>) =>
(dispatch: AppDispatch, getState: () => RootState) => {
const accountId = getState().me;
if (!accountId) return;
if (status.pinned) {
dispatch(unpin(status, accountId));
} else {
dispatch(pin(status, accountId));
}
};
const unpinSuccess = (status: Status, accountId: string) => ({
type: UNPIN_SUCCESS,
status,
statusId: status.id,
accountId,
});
interface UnpinSuccess {
type: typeof UNPIN_SUCCESS;
statusId: string;
accountId: string;
}
type InteractionsAction =
| ReblogRequest
@ -140,8 +95,8 @@ type InteractionsAction =
| DislikeRequest
| DislikeFail
| UndislikeRequest
| ReturnType<typeof pinSuccess>
| ReturnType<typeof unpinSuccess>
| PinSuccess
| UnpinSuccess
export {
REBLOG_REQUEST,
@ -156,6 +111,5 @@ export {
UNDISLIKE_REQUEST,
PIN_SUCCESS,
UNPIN_SUCCESS,
togglePin,
type InteractionsAction,
};

View File

@ -6,7 +6,6 @@ import { useHistory, useRouteMatch } from 'react-router-dom';
import { blockAccount } from 'pl-fe/actions/accounts';
import { directCompose, mentionCompose, quoteCompose, replyCompose } from 'pl-fe/actions/compose';
import { emojiReact, unEmojiReact } from 'pl-fe/actions/emoji-reacts';
import { togglePin } from 'pl-fe/actions/interactions';
import { deleteStatusModal, toggleStatusSensitivityModal } from 'pl-fe/actions/moderation';
import { initReport, ReportableEntities } from 'pl-fe/actions/reports';
import { changeSetting } from 'pl-fe/actions/settings';
@ -30,7 +29,7 @@ import { useChats } from 'pl-fe/queries/chats';
import { useBlockGroupUserMutation } from 'pl-fe/queries/groups/use-group-blocks';
import { useCustomEmojis } from 'pl-fe/queries/instance/use-custom-emojis';
import { useTranslationLanguages } from 'pl-fe/queries/instance/use-translation-languages';
import { useBookmarkStatus, useDislikeStatus, useFavouriteStatus, useReblogStatus, useUnbookmarkStatus, useUndislikeStatus, useUnfavouriteStatus, useUnreblogStatus } from 'pl-fe/queries/statuses/use-status-interactions';
import { useBookmarkStatus, useDislikeStatus, useFavouriteStatus, usePinStatus, useReblogStatus, useUnbookmarkStatus, useUndislikeStatus, useUnfavouriteStatus, useUnpinStatus, useUnreblogStatus } from 'pl-fe/queries/statuses/use-status-interactions';
import { useModalsStore } from 'pl-fe/stores/modals';
import { useStatusMetaStore } from 'pl-fe/stores/status-meta';
import toast from 'pl-fe/toast';
@ -624,6 +623,8 @@ const MenuButton: React.FC<IMenuButton> = ({
const { getOrCreateChatByAccountId } = useChats();
const { mutate: bookmarkStatus } = useBookmarkStatus(status.id);
const { mutate: unbookmarkStatus } = useUnbookmarkStatus(status.id);
const { mutate: pinStatus } = usePinStatus(status?.id!);
const { mutate: unpinStatus } = useUnpinStatus(status?.id!);
const { groupRelationship } = useGroupRelationship(status.group_id || undefined);
const features = useFeatures();
@ -693,7 +694,8 @@ const MenuButton: React.FC<IMenuButton> = ({
};
const handlePinClick: React.EventHandler<React.MouseEvent> = (e) => {
dispatch(togglePin(status));
if (status.pinned) unpinStatus();
else pinStatus();
};
const handleReblogClick = (e: React.MouseEvent | React.KeyboardEvent, visibility?: string) => {

View File

@ -5,7 +5,6 @@ import { Link, useHistory } from 'react-router-dom';
import { blockAccount } from 'pl-fe/actions/accounts';
import { directCompose, mentionCompose, quoteCompose } from 'pl-fe/actions/compose';
import { fetchEventIcs } from 'pl-fe/actions/events';
import { togglePin } from 'pl-fe/actions/interactions';
import { deleteStatusModal, toggleStatusSensitivityModal } from 'pl-fe/actions/moderation';
import { initReport, ReportableEntities } from 'pl-fe/actions/reports';
import { deleteStatus } from 'pl-fe/actions/statuses';
@ -24,7 +23,7 @@ import { useFeatures } from 'pl-fe/hooks/use-features';
import { useOwnAccount } from 'pl-fe/hooks/use-own-account';
import { useSettings } from 'pl-fe/hooks/use-settings';
import { useChats } from 'pl-fe/queries/chats';
import { useBookmarkStatus, useReblogStatus, useUnbookmarkStatus, useUnreblogStatus } from 'pl-fe/queries/statuses/use-status-interactions';
import { useBookmarkStatus, usePinStatus, useReblogStatus, useUnbookmarkStatus, useUnpinStatus, useUnreblogStatus } from 'pl-fe/queries/statuses/use-status-interactions';
import { useModalsStore } from 'pl-fe/stores/modals';
import copy from 'pl-fe/utils/copy';
import { download } from 'pl-fe/utils/download';
@ -94,6 +93,8 @@ const EventHeader: React.FC<IEventHeader> = ({ status }) => {
const { mutate: unreblogStatus } = useUnreblogStatus(status?.id!);
const { mutate: bookmarkStatus } = useBookmarkStatus(status?.id!);
const { mutate: unbookmarkStatus } = useUnbookmarkStatus(status?.id!);
const { mutate: pinStatus } = usePinStatus(status?.id!);
const { mutate: unpinStatus } = useUnpinStatus(status?.id!);
if (!status || !status.event) {
return (
@ -154,7 +155,8 @@ const EventHeader: React.FC<IEventHeader> = ({ status }) => {
};
const handlePinClick = () => {
dispatch(togglePin(status));
if (status.pinned) unpinStatus();
else pinStatus();
};
const handleDeleteClick = () => {

View File

@ -2,6 +2,7 @@ import { InfiniteData, useMutation, useQuery, useQueryClient } from '@tanstack/r
import { defineMessages } from 'react-intl';
import { importEntities } from 'pl-fe/actions/importer';
import { PIN_SUCCESS, UNPIN_SUCCESS, type InteractionsAction } from 'pl-fe/actions/interactions';
import { useAppDispatch } from 'pl-fe/hooks/use-app-dispatch';
import { useClient } from 'pl-fe/hooks/use-client';
import { useFeatures } from 'pl-fe/hooks/use-features';
@ -11,7 +12,6 @@ import { useModalsStore } from 'pl-fe/stores/modals';
import toast, { IToastOptions } from 'pl-fe/toast';
import type { PaginatedResponse } from 'pl-api';
import type { InteractionsAction } from 'pl-fe/actions/interactions';
const messages = defineMessages({
bookmarkAdded: { id: 'status.bookmarked', defaultMessage: 'Bookmark added.' },
@ -237,6 +237,34 @@ const useUnbookmarkStatus = (statusId: string) => {
});
};
const usePinStatus = (statusId: string) => {
const client = useClient();
const dispatch = useAppDispatch();
return useMutation({
mutationKey: ['statuses', 'pin', statusId],
mutationFn: () => client.statuses.pinStatus(statusId),
onSuccess: (status) => {
dispatch(importEntities({ statuses: [status] }));
dispatch<InteractionsAction>({ type: PIN_SUCCESS, statusId: status.id, accountId: status.account.id });
},
});
};
const useUnpinStatus = (statusId: string) => {
const client = useClient();
const dispatch = useAppDispatch();
return useMutation({
mutationKey: ['statuses', 'unpin', statusId],
mutationFn: () => client.statuses.unpinStatus(statusId),
onSuccess: (status) => {
dispatch(importEntities({ statuses: [status] }));
dispatch<InteractionsAction>({ type: UNPIN_SUCCESS, statusId: status.id, accountId: status.account.id });
},
});
};
export {
useStatusDislikes,
useStatusFavourites,
@ -250,4 +278,6 @@ export {
useUnreblogStatus,
useBookmarkStatus,
useUnbookmarkStatus,
usePinStatus,
useUnpinStatus,
};

View File

@ -113,9 +113,9 @@ const statusLists = (state = initialState, action: FavouritesAction | Interactio
case PINNED_STATUSES_FETCH_SUCCESS:
return create(state, draft => normalizeList(draft, 'pins', action.statuses, action.next));
case PIN_SUCCESS:
return create(state, draft => prependOneToList(draft, 'pins', action.status));
return create(state, draft => prependOneToList(draft, 'pins', action.statusId));
case UNPIN_SUCCESS:
return create(state, draft => removeOneFromList(draft, 'pins', action.status));
return create(state, draft => removeOneFromList(draft, 'pins', action.statusId));
default:
return state;
}