From 3f1d04488029d43bbef5c7346f940b424e07c9ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?nicole=20miko=C5=82ajczyk?= Date: Thu, 26 Jun 2025 11:30:33 +0200 Subject: [PATCH] pl-fe: migrate pin/unpin MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: nicole mikołajczyk --- packages/pl-fe/src/actions/interactions.ts | 70 ++++--------------- .../src/components/status-action-bar.tsx | 8 ++- .../event/components/event-header.tsx | 8 ++- .../statuses/use-status-interactions.ts | 32 ++++++++- packages/pl-fe/src/reducers/status-lists.ts | 4 +- 5 files changed, 55 insertions(+), 67 deletions(-) diff --git a/packages/pl-fe/src/actions/interactions.ts b/packages/pl-fe/src/actions/interactions.ts index 10a3934d1..a8e330617 100644 --- a/packages/pl-fe/src/actions/interactions.ts +++ b/packages/pl-fe/src/actions/interactions.ts @@ -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, 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, 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) => - (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 - | ReturnType + | PinSuccess + | UnpinSuccess export { REBLOG_REQUEST, @@ -156,6 +111,5 @@ export { UNDISLIKE_REQUEST, PIN_SUCCESS, UNPIN_SUCCESS, - togglePin, type InteractionsAction, }; diff --git a/packages/pl-fe/src/components/status-action-bar.tsx b/packages/pl-fe/src/components/status-action-bar.tsx index 425ede0dc..a16ff6f77 100644 --- a/packages/pl-fe/src/components/status-action-bar.tsx +++ b/packages/pl-fe/src/components/status-action-bar.tsx @@ -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 = ({ 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 = ({ }; const handlePinClick: React.EventHandler = (e) => { - dispatch(togglePin(status)); + if (status.pinned) unpinStatus(); + else pinStatus(); }; const handleReblogClick = (e: React.MouseEvent | React.KeyboardEvent, visibility?: string) => { diff --git a/packages/pl-fe/src/features/event/components/event-header.tsx b/packages/pl-fe/src/features/event/components/event-header.tsx index 6fa80983f..25cb56f09 100644 --- a/packages/pl-fe/src/features/event/components/event-header.tsx +++ b/packages/pl-fe/src/features/event/components/event-header.tsx @@ -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 = ({ 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 = ({ status }) => { }; const handlePinClick = () => { - dispatch(togglePin(status)); + if (status.pinned) unpinStatus(); + else pinStatus(); }; const handleDeleteClick = () => { diff --git a/packages/pl-fe/src/queries/statuses/use-status-interactions.ts b/packages/pl-fe/src/queries/statuses/use-status-interactions.ts index 762491502..940c04f0e 100644 --- a/packages/pl-fe/src/queries/statuses/use-status-interactions.ts +++ b/packages/pl-fe/src/queries/statuses/use-status-interactions.ts @@ -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({ 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({ type: UNPIN_SUCCESS, statusId: status.id, accountId: status.account.id }); + }, + }); +}; + export { useStatusDislikes, useStatusFavourites, @@ -250,4 +278,6 @@ export { useUnreblogStatus, useBookmarkStatus, useUnbookmarkStatus, + usePinStatus, + useUnpinStatus, }; diff --git a/packages/pl-fe/src/reducers/status-lists.ts b/packages/pl-fe/src/reducers/status-lists.ts index 85adc9bce..55b6bec4b 100644 --- a/packages/pl-fe/src/reducers/status-lists.ts +++ b/packages/pl-fe/src/reducers/status-lists.ts @@ -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; }