From 715087918614a1cbbb915c8d8e5d82bdce4349cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?nicole=20miko=C5=82ajczyk?= Date: Fri, 27 Feb 2026 00:02:43 +0100 Subject: [PATCH] nicolium: types 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/moderation.tsx | 6 ++-- packages/pl-fe/src/actions/timelines.ts | 2 +- .../pl-fe/src/components/event-preview.tsx | 7 +++-- .../pl-fe/src/components/status-content.tsx | 6 ++-- .../pl-fe/src/components/status-media.tsx | 14 +++------ .../pl-fe/src/components/translate-button.tsx | 6 ++-- .../containers/preview-compose-container.tsx | 17 ++-------- .../src/features/draft-statuses/builder.tsx | 19 ++++++------ .../components/draft-status-action-bar.tsx | 7 ++++- .../components/draft-status.tsx | 7 +++-- .../event/components/event-header.tsx | 12 ++++--- .../components/scheduled-status.tsx | 10 +++--- .../status/components/detailed-status.tsx | 5 +-- .../components/status-interaction-bar.tsx | 7 +++-- .../features/ui/components/pending-status.tsx | 15 ++++----- .../ui/util/pending-status-builder.ts | 13 -------- .../pl-fe/src/hooks/use-account-gallery.ts | 2 +- .../src/modals/compare-history-modal.tsx | 6 ++-- .../notifications/use-notifications.ts | 9 ++---- .../pl-fe/src/queries/statuses/use-poll.ts | 5 ++- packages/pl-fe/src/reducers/timelines.ts | 4 +-- packages/pl-fe/src/stores/compose.ts | 31 ++++++++++--------- packages/pl-fe/src/styles/new/panels.scss | 2 +- packages/pl-fe/src/utils/status.ts | 6 ++-- 24 files changed, 106 insertions(+), 112 deletions(-) diff --git a/packages/pl-fe/src/actions/moderation.tsx b/packages/pl-fe/src/actions/moderation.tsx index 2a50aee89..a95395bc0 100644 --- a/packages/pl-fe/src/actions/moderation.tsx +++ b/packages/pl-fe/src/actions/moderation.tsx @@ -185,7 +185,8 @@ const toggleStatusSensitivityModal = (intl: IntlShape, statusId: string, sensitive: boolean, afterConfirm = () => {}) => (dispatch: AppDispatch, getState: () => RootState) => { const state = getState(); - const acct = state.statuses[statusId].account.acct; + const statusAccount = selectAccount(state.statuses[statusId].account_id); + const acct = statusAccount?.acct; useModalsStore.getState().actions.openModal('CONFIRM', { heading: intl.formatMessage( @@ -217,7 +218,8 @@ const deleteStatusModal = (intl: IntlShape, statusId: string, afterConfirm = () => {}) => (dispatch: AppDispatch, getState: () => RootState) => { const state = getState(); - const acct = state.statuses[statusId].account.acct; + const statusAccount = selectAccount(state.statuses[statusId].account_id); + const acct = statusAccount?.acct; useModalsStore.getState().actions.openModal('CONFIRM', { heading: intl.formatMessage(messages.deleteStatusHeading), diff --git a/packages/pl-fe/src/actions/timelines.ts b/packages/pl-fe/src/actions/timelines.ts index 24a86020c..67cbf06a1 100644 --- a/packages/pl-fe/src/actions/timelines.ts +++ b/packages/pl-fe/src/actions/timelines.ts @@ -127,7 +127,7 @@ interface TimelineDeleteAction { const deleteFromTimelines = (statusId: string) => (dispatch: AppDispatch, getState: () => RootState) => { - const accountId = getState().statuses[statusId]?.account?.id; + const accountId = getState().statuses[statusId]?.account_id; const references: Array<[string, string]> = Object.entries(getState().statuses) .filter(([key, status]) => [key, status.reblog_id === statusId]) .map(([key, status]) => [key, status.account_id]); diff --git a/packages/pl-fe/src/components/event-preview.tsx b/packages/pl-fe/src/components/event-preview.tsx index da380216a..34833b20f 100644 --- a/packages/pl-fe/src/components/event-preview.tsx +++ b/packages/pl-fe/src/components/event-preview.tsx @@ -12,6 +12,7 @@ import Emojify from '@/features/emoji/emojify'; import EventActionButton from '@/features/event/components/event-action-button'; import EventDate from '@/features/event/components/event-date'; import { useAppSelector } from '@/hooks/use-app-selector'; +import { useAccount } from '@/queries/accounts/use-account'; import type { NormalizedStatus as StatusEntity } from '@/reducers/statuses'; @@ -26,7 +27,7 @@ const messages = defineMessages({ }); interface IEventPreview { - status: Pick; + status: Pick; className?: string; hideAction?: boolean; floatingAction?: boolean; @@ -41,10 +42,12 @@ const EventPreview: React.FC = ({ const intl = useIntl(); const me = useAppSelector((state) => state.me); + const { data: account } = useAccount(status.account_id); - const account = status.account; const event = status.event!; + if (!account) return null; + const banner = event.banner; const action = diff --git a/packages/pl-fe/src/components/status-content.tsx b/packages/pl-fe/src/components/status-content.tsx index 878156e6d..603769fc1 100644 --- a/packages/pl-fe/src/components/status-content.tsx +++ b/packages/pl-fe/src/components/status-content.tsx @@ -7,6 +7,7 @@ import Stack from '@/components/ui/stack'; import Emojify from '@/features/emoji/emojify'; import QuotedStatus from '@/features/status/containers/quoted-status-container'; import { useFrontendConfig } from '@/hooks/use-frontend-config'; +import { useAccount } from '@/queries/accounts/use-account'; import { useLocalStatusTranslation } from '@/queries/statuses/use-local-status-translation'; import { useStatusTranslation } from '@/queries/statuses/use-status-translation'; import { useSettings } from '@/stores/settings'; @@ -79,6 +80,7 @@ const StatusContent: React.FC = React.memo( }) => { const { urlPrivacy, displaySpoilers, renderMfm } = useSettings(); const { greentext } = useFrontendConfig(); + const { data: account } = useAccount(status.account_id); const [collapsed, setCollapsed] = useState(null); const [onlyEmoji, setOnlyEmoji] = useState(false); @@ -172,11 +174,11 @@ const StatusContent: React.FC = React.memo( redirectUrls: urlPrivacy.redirectLinksMode !== 'off', displayTargetHost: urlPrivacy.displayTargetHost, greentext, - speakAsCat: status.account.speak_as_cat, + speakAsCat: account?.speak_as_cat, }, true, ); - }, [content, renderMfm]); + }, [content, renderMfm, account?.speak_as_cat]); const spoilerText = status.spoiler_text_map && statusMeta.currentLanguage diff --git a/packages/pl-fe/src/components/status-media.tsx b/packages/pl-fe/src/components/status-media.tsx index 07c391758..4f05c2401 100644 --- a/packages/pl-fe/src/components/status-media.tsx +++ b/packages/pl-fe/src/components/status-media.tsx @@ -4,6 +4,7 @@ import AttachmentThumbs from '@/components/attachment-thumbs'; import PreviewCard from '@/components/preview-card'; import PlaceholderCard from '@/features/placeholder/components/placeholder-card'; import { MediaGallery, Video, Audio } from '@/features/ui/util/async-components'; +import { useAccount } from '@/queries/accounts/use-account'; import { useModalsActions } from '@/stores/modals'; import { useSettings } from '@/stores/settings'; @@ -17,7 +18,7 @@ interface IStatusMedia { status: Pick< Status, | 'id' - | 'account' + | 'account_id' | 'card' | 'expectsCard' | 'filtered' @@ -36,6 +37,7 @@ interface IStatusMedia { const StatusMedia: React.FC = ({ status, muted = false, onClick }) => { const { openModal } = useModalsActions(); const { displayMedia } = useSettings(); + const { data: account } = useAccount(status.account_id); const [visible] = useMediaVisible(status, displayMedia); @@ -97,7 +99,7 @@ const StatusMedia: React.FC = ({ status, muted = false, onClick }) poster={ attachment.preview_url !== attachment.url ? attachment.preview_url - : status.account.avatar_static + : account?.avatar_static } backgroundColor={attachment.meta.colors?.background} foregroundColor={attachment.meta.colors?.foreground} @@ -128,13 +130,7 @@ const StatusMedia: React.FC = ({ status, muted = false, onClick }) if (media) { return ( // eslint-disable-next-line jsx-a11y/no-static-element-interactions -
{ - e.stopPropagation(); - }} - > - {media} -
+
e.stopPropagation()}>{media}
); } else { return null; diff --git a/packages/pl-fe/src/components/translate-button.tsx b/packages/pl-fe/src/components/translate-button.tsx index 13cbddafc..0edacff87 100644 --- a/packages/pl-fe/src/components/translate-button.tsx +++ b/packages/pl-fe/src/components/translate-button.tsx @@ -7,6 +7,7 @@ import Text from '@/components/ui/text'; import { useAppSelector } from '@/hooks/use-app-selector'; import { useFeatures } from '@/hooks/use-features'; import { useInstance } from '@/hooks/use-instance'; +import { selectAccount } from '@/queries/accounts/selectors'; import { useTranslationLanguages } from '@/queries/instance/use-translation-languages'; import { useLocalStatusTranslation } from '@/queries/statuses/use-local-status-translation'; import { useStatusTranslation } from '@/queries/statuses/use-status-translation'; @@ -40,7 +41,8 @@ const canRemoteTranslate = ( if (!isLoggedIn && !allowUnauthenticated) return false; - if (!status.account.local && !allowRemote) return false; + const statusAccount = selectAccount(status.account_id); + if (statusAccount && !statusAccount.local && !allowRemote) return false; if (!supportedLanguages[status.language]?.includes(locale)) return false; @@ -68,7 +70,7 @@ const localTranslationAvailability = async ( }; interface ITranslateButton { - status: Pick; + status: Pick; } const TranslateButton: React.FC = ({ status }) => { diff --git a/packages/pl-fe/src/features/compose/containers/preview-compose-container.tsx b/packages/pl-fe/src/features/compose/containers/preview-compose-container.tsx index 94b3db9b1..6d3b88767 100644 --- a/packages/pl-fe/src/features/compose/containers/preview-compose-container.tsx +++ b/packages/pl-fe/src/features/compose/containers/preview-compose-container.tsx @@ -1,4 +1,4 @@ -import React, { useMemo } from 'react'; +import React from 'react'; import { defineMessages, FormattedMessage, useIntl } from 'react-intl'; import EventPreview from '@/components/event-preview'; @@ -14,7 +14,6 @@ import IconButton from '@/components/ui/icon-button'; import Stack from '@/components/ui/stack'; import Text from '@/components/ui/text'; import AccountContainer from '@/containers/account-container'; -import { useOwnAccount } from '@/hooks/use-own-account'; import { useCompose, useComposeActions } from '@/stores/compose'; import type { NormalizedStatus as Status } from '@/reducers/statuses'; @@ -34,7 +33,6 @@ interface IQuotedStatusContainer { const PreviewComposeContainer: React.FC = ({ composeId }) => { const { updateCompose } = useComposeActions(); const intl = useIntl(); - const { data: ownAccount } = useOwnAccount(); const previewedStatus = useCompose(composeId).preview as unknown as Status; @@ -44,16 +42,7 @@ const PreviewComposeContainer: React.FC = ({ composeId } }); }; - const status = useMemo( - () => - previewedStatus - ? { - ...previewedStatus, - account: previewedStatus.account || ownAccount, - } - : null, - [previewedStatus, ownAccount], - ); + const status = previewedStatus ?? null; if (!status) { return null; @@ -80,7 +69,7 @@ const PreviewComposeContainer: React.FC = ({ composeId } /> { - if (draftStatus.poll?.options) { - return { - ...draftStatus.poll, - id: `${draftStatus.draft_id}-poll`, - options: draftStatus.poll.options.map((title: string) => ({ title })).toArray(), - }; +const buildPoll = (draftPoll: DraftStatus['poll']) => { + if (draftPoll?.options) { + return v.parse(pollSchema, { + ...draftPoll, + id: 'poll', + options: draftPoll.options.map((title: string) => ({ title })).toArray(), + }); } else { return null; } @@ -29,7 +29,6 @@ const buildStatus = (account: Account, draftStatus: DraftStatus) => { group: draftStatus.group_id, in_reply_to_id: draftStatus.in_reply_to, media_attachments: draftStatus.media_attachments, - poll: buildPoll(draftStatus), quote_id: draftStatus.quote, sensitive: draftStatus.sensitive, spoiler_text: draftStatus.spoiler_text, @@ -41,4 +40,4 @@ const buildStatus = (account: Account, draftStatus: DraftStatus) => { return normalizeStatus(status); }; -export { buildStatus }; +export { buildStatus, buildPoll }; diff --git a/packages/pl-fe/src/features/draft-statuses/components/draft-status-action-bar.tsx b/packages/pl-fe/src/features/draft-statuses/components/draft-status-action-bar.tsx index e7eab912b..869e87f67 100644 --- a/packages/pl-fe/src/features/draft-statuses/components/draft-status-action-bar.tsx +++ b/packages/pl-fe/src/features/draft-statuses/components/draft-status-action-bar.tsx @@ -5,6 +5,8 @@ import { fetchStatus } from '@/actions/statuses'; import Button from '@/components/ui/button'; import HStack from '@/components/ui/hstack'; import { useAppDispatch } from '@/hooks/use-app-dispatch'; +import { queryClient } from '@/queries/client'; +import { queryKeys } from '@/queries/keys'; import { useCancelDraftStatus } from '@/queries/statuses/use-draft-statuses'; import { useComposeActions } from '@/stores/compose'; import { useModalsActions } from '@/stores/modals'; @@ -55,7 +57,10 @@ const DraftStatusActionBar: React.FC = ({ source, status const handleEditClick = () => { if (status.in_reply_to_id) dispatch(fetchStatus(status.in_reply_to_id)); - setComposeToStatus(status, status.poll, source, false, source.draft_id, source.editorState); + const poll = status.poll_id + ? queryClient.getQueryData(queryKeys.statuses.polls.show(status.poll_id)) + : undefined; + setComposeToStatus(status, poll, source, false, source.draft_id, source.editorState); openModal('COMPOSE'); }; diff --git a/packages/pl-fe/src/features/draft-statuses/components/draft-status.tsx b/packages/pl-fe/src/features/draft-statuses/components/draft-status.tsx index 31a752800..89bd40f80 100644 --- a/packages/pl-fe/src/features/draft-statuses/components/draft-status.tsx +++ b/packages/pl-fe/src/features/draft-statuses/components/draft-status.tsx @@ -13,7 +13,7 @@ import QuotedStatus from '@/features/status/containers/quoted-status-container'; import PollPreview from '@/features/ui/components/poll-preview'; import { useOwnAccount } from '@/hooks/use-own-account'; -import { buildStatus } from '../builder'; +import { buildPoll, buildStatus } from '../builder'; import DraftStatusActionBar from './draft-status-action-bar'; @@ -29,10 +29,11 @@ const DraftStatus: React.FC = ({ draftStatus, ...other }) => { if (!ownAccount || !draftStatus) return null; const status = buildStatus(ownAccount, draftStatus); + const poll = draftStatus.poll ? buildPoll(draftStatus.poll) : null; if (!status) return null; - const account = status.account; + const account = ownAccount; let quote; @@ -82,7 +83,7 @@ const DraftStatus: React.FC = ({ draftStatus, ...other }) => { {quote} - {status.poll && } + {poll && } 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 0ee4d00a2..f1ef25d10 100644 --- a/packages/pl-fe/src/features/event/components/event-header.tsx +++ b/packages/pl-fe/src/features/event/components/event-header.tsx @@ -19,6 +19,7 @@ import Emojify from '@/features/emoji/emojify'; import { useAppDispatch } from '@/hooks/use-app-dispatch'; import { useFeatures } from '@/hooks/use-features'; import { useOwnAccount } from '@/hooks/use-own-account'; +import { useAccount } from '@/queries/accounts/use-account'; import { useChats } from '@/queries/chats'; import { useBookmarkStatus, @@ -94,7 +95,7 @@ interface IEventHeader { status?: Pick< Status, | 'id' - | 'account' + | 'account_id' | 'bookmarked' | 'event' | 'group_id' @@ -121,6 +122,7 @@ const EventHeader: React.FC = ({ status }) => { const features = useFeatures(); const { boostModal } = useSettings(); const { data: ownAccount } = useOwnAccount(); + const { data: account } = useAccount(status?.account_id!); const isStaff = ownAccount ? (ownAccount.is_admin ?? ownAccount.is_moderator) : false; const isAdmin = ownAccount ? ownAccount.is_admin : false; @@ -131,7 +133,7 @@ const EventHeader: React.FC = ({ status }) => { const { mutate: pinStatus } = usePinStatus(status?.id!); const { mutate: unpinStatus } = useUnpinStatus(status?.id!); - if (!status || !status.event) { + if (!status || !status.event || !account) { return ( <>
@@ -142,11 +144,11 @@ const EventHeader: React.FC = ({ status }) => { ); } - - const account = status.account; const event = status.event; const banner = event.banner; + if (!account) return null; + const username = account.username; const handleHeaderClick: React.MouseEventHandler = (e) => { @@ -365,7 +367,7 @@ const EventHeader: React.FC = ({ status }) => { icon: require('@phosphor-icons/core/regular/at.svg'), }); - if (status.account.accepts_chat_messages === true) { + if (account.accepts_chat_messages === true) { menu.push({ text: intl.formatMessage(messages.chat, { name: username }), action: handleChatClick, diff --git a/packages/pl-fe/src/features/scheduled-statuses/components/scheduled-status.tsx b/packages/pl-fe/src/features/scheduled-statuses/components/scheduled-status.tsx index abc765687..b0af51eb7 100644 --- a/packages/pl-fe/src/features/scheduled-statuses/components/scheduled-status.tsx +++ b/packages/pl-fe/src/features/scheduled-statuses/components/scheduled-status.tsx @@ -7,6 +7,7 @@ import StatusContent from '@/components/status-content'; import StatusReplyMentions from '@/components/status-reply-mentions'; import HStack from '@/components/ui/hstack'; import Stack from '@/components/ui/stack'; +import { buildPoll } from '@/features/draft-statuses/builder'; import PollPreview from '@/features/ui/components/poll-preview'; import { useOwnAccount } from '@/hooks/use-own-account'; @@ -26,11 +27,10 @@ const ScheduledStatus: React.FC = ({ scheduledStatus, ...other if (!ownAccount) return null; const status = buildStatus(ownAccount, scheduledStatus); + const poll = scheduledStatus.params.poll ? buildPoll(scheduledStatus.params.poll) : null; if (!status) return null; - const account = status.account; - return (
= ({ scheduledStatus, ...other
} @@ -63,7 +63,7 @@ const ScheduledStatus: React.FC = ({ scheduledStatus, ...other {status.media_attachments.length > 0 && } - {status.poll && } + {poll && }
diff --git a/packages/pl-fe/src/features/status/components/detailed-status.tsx b/packages/pl-fe/src/features/status/components/detailed-status.tsx index d2988d819..7629f98f0 100644 --- a/packages/pl-fe/src/features/status/components/detailed-status.tsx +++ b/packages/pl-fe/src/features/status/components/detailed-status.tsx @@ -14,6 +14,7 @@ import Icon from '@/components/ui/icon'; import Stack from '@/components/ui/stack'; import Text from '@/components/ui/text'; import Emojify from '@/features/emoji/emojify'; +import { useAccount } from '@/queries/accounts/use-account'; import { useGroupQuery } from '@/queries/groups/use-group'; import StatusInteractionBar from './status-interaction-bar'; @@ -41,6 +42,7 @@ const DetailedStatus: React.FC = ({ const node = useRef(null); const { data: group } = useGroupQuery(status.group_id ?? undefined); + const { data: account } = useAccount(status.account_id); const handleOpenCompareHistoryModal = () => { onOpenCompareHistoryModal(status); @@ -93,8 +95,7 @@ const DetailedStatus: React.FC = ({ const actualStatus = status?.reblog || status; if (!actualStatus) return null; - const { account } = actualStatus; - if (!account || typeof account !== 'object') return null; + if (!account) return null; return (
diff --git a/packages/pl-fe/src/features/status/components/status-interaction-bar.tsx b/packages/pl-fe/src/features/status/components/status-interaction-bar.tsx index 1c720dd12..ae88c7ebc 100644 --- a/packages/pl-fe/src/features/status/components/status-interaction-bar.tsx +++ b/packages/pl-fe/src/features/status/components/status-interaction-bar.tsx @@ -7,6 +7,7 @@ import AnimatedNumber from '@/components/animated-number'; import HStack from '@/components/ui/hstack'; import Text from '@/components/ui/text'; import { useFeatures } from '@/hooks/use-features'; +import { useAccount } from '@/queries/accounts/use-account'; import { useModalsActions } from '@/stores/modals'; import type { NormalizedStatus as Status } from '@/reducers/statuses'; @@ -15,7 +16,7 @@ interface IStatusInteractionBar { status: Pick< Status, | 'id' - | 'account' + | 'account_id' | 'dislikes_count' | 'favourited' | 'favourites_count' @@ -29,7 +30,7 @@ const StatusInteractionBar: React.FC = ({ }): React.JSX.Element | null => { const { openModal } = useModalsActions(); const features = useFeatures(); - const { account } = status; + const { data: account } = useAccount(status.account_id); if (!account || typeof account !== 'object') return null; @@ -74,7 +75,7 @@ const StatusInteractionBar: React.FC = ({ = ({ status }) => { if (status.media_attachments && status.media_attachments.length) { return ; - } else if (!status.quote && shouldHaveCard(status)) { + } else if (!status.quote_id && shouldHaveCard(status)) { return ; } else { return null; @@ -57,10 +58,10 @@ const PendingStatus: React.FC = ({ : null; }); - if (!status) return null; - if (!status.account) return null; + const { data: poll } = usePollQuery(status?.poll_id ?? ''); - const account = status.account; + if (!status) return null; + if (!ownAccount) return null; return (
@@ -75,8 +76,8 @@ const PendingStatus: React.FC = ({
= ({ - {status.poll && } + {poll && } {status.quote_id && } diff --git a/packages/pl-fe/src/features/ui/util/pending-status-builder.ts b/packages/pl-fe/src/features/ui/util/pending-status-builder.ts index 95a616695..3c4e54988 100644 --- a/packages/pl-fe/src/features/ui/util/pending-status-builder.ts +++ b/packages/pl-fe/src/features/ui/util/pending-status-builder.ts @@ -1,4 +1,3 @@ -import { create } from 'mutative'; import { statusSchema, type Account } from 'pl-api'; import * as v from 'valibot'; @@ -15,17 +14,6 @@ const buildMentions = (pendingStatus: PendingStatus) => { } }; -const buildPoll = (pendingStatus: PendingStatus) => { - if (pendingStatus.poll?.options) { - return create(pendingStatus.poll, (draft) => { - // @ts-expect-error - draft.options = draft.options.map((title) => ({ title })); - }); - } else { - return null; - } -}; - const buildStatus = ( account: Account, state: RootState, @@ -42,7 +30,6 @@ const buildStatus = ( in_reply_to_id: inReplyToId, media_attachments: (pendingStatus.media_ids ?? []).map((id: string) => ({ id })), mentions: buildMentions(pendingStatus), - poll: buildPoll(pendingStatus), quote: pendingStatus.quote_id ? state.statuses[pendingStatus.quote_id] : null, sensitive: pendingStatus.sensitive, visibility: pendingStatus.visibility, diff --git a/packages/pl-fe/src/hooks/use-account-gallery.ts b/packages/pl-fe/src/hooks/use-account-gallery.ts index 3b809ba10..7c471c9f1 100644 --- a/packages/pl-fe/src/hooks/use-account-gallery.ts +++ b/packages/pl-fe/src/hooks/use-account-gallery.ts @@ -33,7 +33,7 @@ const getGallery = createSelector( sensitive: status.sensitive, visibility: status.visibility, status_id: statusId, - account_id: status.account.id, + account_id: status.account_id, })), ); }, []), diff --git a/packages/pl-fe/src/modals/compare-history-modal.tsx b/packages/pl-fe/src/modals/compare-history-modal.tsx index 54a84f163..5c3d5007d 100644 --- a/packages/pl-fe/src/modals/compare-history-modal.tsx +++ b/packages/pl-fe/src/modals/compare-history-modal.tsx @@ -10,6 +10,7 @@ import Stack from '@/components/ui/stack'; import Text from '@/components/ui/text'; import Emojify from '@/features/emoji/emojify'; import { useAppSelector } from '@/hooks/use-app-selector'; +import { useAccount } from '@/queries/accounts/use-account'; import { useStatusHistory } from '@/queries/statuses/use-status-history'; import type { BaseModalProps } from '@/features/ui/components/modal-root'; @@ -25,6 +26,7 @@ const CompareHistoryModal: React.FC = const { data: versions, isLoading } = useStatusHistory(statusId); const status = useAppSelector((state) => state.statuses[statusId]); + const { data: statusAccount } = useAccount(status?.account_id ?? ''); const onClickClose = () => { onClose('COMPARE_HISTORY'); @@ -44,7 +46,7 @@ const CompareHistoryModal: React.FC = mentions={status?.mentions} hasQuote={!!status?.quote_id} emojis={version.emojis} - speakAsCat={status.account.speak_as_cat} + speakAsCat={statusAccount?.speak_as_cat} /> ); @@ -81,7 +83,7 @@ const CompareHistoryModal: React.FC = diff --git a/packages/pl-fe/src/queries/notifications/use-notifications.ts b/packages/pl-fe/src/queries/notifications/use-notifications.ts index 3306e9019..f9340b181 100644 --- a/packages/pl-fe/src/queries/notifications/use-notifications.ts +++ b/packages/pl-fe/src/queries/notifications/use-notifications.ts @@ -5,10 +5,7 @@ import { useCallback, useEffect } from 'react'; import { useIntl } from 'react-intl'; import { importEntities } from '@/actions/importer'; -import { - getNotificationStatus, - notificationMessages, -} from '@/features/notifications/components/notification'; +import { notificationMessages } from '@/features/notifications/components/notification'; import { useAppDispatch } from '@/hooks/use-app-dispatch'; import { useAppSelector } from '@/hooks/use-app-selector'; import { useClient } from '@/hooks/use-client'; @@ -150,7 +147,7 @@ const useProcessStreamNotification = () => { if (notification.type === 'chat_mention') return; const playSound = sounds[notification.type]; - const status = getNotificationStatus(notification); + const status = 'status' in notification ? notification.status : null; let filtered: boolean | null = false; @@ -166,7 +163,7 @@ const useProcessStreamNotification = () => { if (!filtered && isNotificationsEnabled) { const targetName = notification.type === 'move' ? notification.target.acct : ''; - const isReblog = status?.reblog_id ? 1 : 0; + const isReblog = status?.reblog ? 1 : 0; const title = intl.formatMessage(notificationMessages[notification.type], { name: notification.account.display_name, diff --git a/packages/pl-fe/src/queries/statuses/use-poll.ts b/packages/pl-fe/src/queries/statuses/use-poll.ts index 047377f5d..9a2fd3385 100644 --- a/packages/pl-fe/src/queries/statuses/use-poll.ts +++ b/packages/pl-fe/src/queries/statuses/use-poll.ts @@ -4,14 +4,13 @@ import { useClient } from '@/hooks/use-client'; import { queryKeys } from '../keys'; -import type { Poll } from 'pl-api'; - const usePollQuery = (pollId: string) => { const client = useClient(); - return useQuery({ + return useQuery({ queryKey: queryKeys.statuses.polls.show(pollId), queryFn: () => client.polls.getPoll(pollId), + enabled: !!pollId, }); }; diff --git a/packages/pl-fe/src/reducers/timelines.ts b/packages/pl-fe/src/reducers/timelines.ts index 93dec5ff5..9e0882012 100644 --- a/packages/pl-fe/src/reducers/timelines.ts +++ b/packages/pl-fe/src/reducers/timelines.ts @@ -223,7 +223,7 @@ const isReblogOf = (reblog: Pick, status: Pick>, + statuses: Record>, status: Pick, ): Array<[string]> => Object.values(statuses) @@ -239,7 +239,7 @@ const buildReferencesTo = ( const filterTimelines = ( state: State, relationship: Relationship, - statuses: Record>, + statuses: Record>, ) => { for (const statusId in statuses) { const status = statuses[statusId]; diff --git a/packages/pl-fe/src/stores/compose.ts b/packages/pl-fe/src/stores/compose.ts index c623248cc..6a82c6c5a 100644 --- a/packages/pl-fe/src/stores/compose.ts +++ b/packages/pl-fe/src/stores/compose.ts @@ -209,36 +209,38 @@ const newPoll = (params: Partial = {}): ComposePoll => ({ }); const statusToTextMentions = ( - status: Pick, + status: Pick, account: Pick, ) => { - const author = status.account.acct; + const statusAccount = selectAccount(status.account_id); + const author = statusAccount?.acct; const mentions = status.mentions.map((m) => m.acct); - return [...new Set([author, ...mentions].filter((acct) => acct !== account.acct))] + return [...new Set([author, ...mentions].filter((acct) => acct && acct !== account.acct))] .map((m) => `@${m} `) .join(''); }; const statusToMentionsArray = ( - status: Pick, + status: Pick, account: Pick, rebloggedBy?: Pick, ) => { - const author = status.account.acct; + const statusAccount = selectAccount(status.account_id); + const author = statusAccount?.acct; const mentions = status.mentions.map((m) => m.acct); return [ ...new Set( [author, ...(rebloggedBy ? [rebloggedBy.acct] : []), ...mentions].filter( - (acct) => acct !== account.acct, + (acct): acct is string => !!acct && acct !== account.acct, ), ), ]; }; const statusToMentionsAccountIdsArray = ( - status: Pick, + status: Pick, account: Pick, parentRebloggedBy?: string | null, ) => { @@ -246,7 +248,7 @@ const statusToMentionsAccountIdsArray = ( return [ ...new Set( - [status.account.id, ...(parentRebloggedBy ? [parentRebloggedBy] : []), ...mentions].filter( + [status.account_id, ...(parentRebloggedBy ? [parentRebloggedBy] : []), ...mentions].filter( (id) => id !== account.id, ), ), @@ -307,7 +309,7 @@ interface ComposeActions { status: Pick< Status, | 'id' - | 'account' + | 'account_id' | 'content' | 'group_id' | 'in_reply_to_id' @@ -330,7 +332,7 @@ interface ComposeActions { status: Pick< Status, | 'id' - | 'account' + | 'account_id' | 'group_id' | 'list_id' | 'local_only' @@ -342,7 +344,7 @@ interface ComposeActions { approvalRequired?: boolean, ) => void; quoteCompose: ( - status: Pick, + status: Pick, approvalRequired?: boolean, ) => void; mentionCompose: (account: Pick) => void; @@ -351,7 +353,7 @@ interface ComposeActions { openComposeWithText: (composeId: string, text?: string) => void; eventDiscussionCompose: ( composeId: string, - status: Pick, + status: Pick, ) => void; resetCompose: (composeId?: string) => void; selectComposeSuggestion: ( @@ -423,7 +425,7 @@ const useComposeStore = create()( const compose = state.composers['compose-modal']; const mentions = explicitAddressing - ? getExplicitMentions(status.account.id, status) + ? getExplicitMentions(status.account_id, status) : []; if (!withRedraft && !draftId) { compose.editedId = status.id; @@ -526,7 +528,8 @@ const useComposeStore = create()( } const compose = draft.composers['compose-modal']; - const author = status.account.acct; + const statusAccount = selectAccount(status.account_id); + const author = statusAccount?.acct ?? ''; compose.quoteId = status.id; compose.to = [author]; diff --git a/packages/pl-fe/src/styles/new/panels.scss b/packages/pl-fe/src/styles/new/panels.scss index 1b43703d1..2a9a9a917 100644 --- a/packages/pl-fe/src/styles/new/panels.scss +++ b/packages/pl-fe/src/styles/new/panels.scss @@ -7,4 +7,4 @@ @include mixins.text($theme: success); line-height: 1; } -} \ No newline at end of file +} diff --git a/packages/pl-fe/src/utils/status.ts b/packages/pl-fe/src/utils/status.ts index 80fe574fa..f5c49991e 100644 --- a/packages/pl-fe/src/utils/status.ts +++ b/packages/pl-fe/src/utils/status.ts @@ -1,3 +1,5 @@ +import { selectAccount } from '@/queries/accounts/selectors'; + import type { NormalizedStatus as Status } from '@/reducers/statuses'; import type { IntlShape } from 'react-intl'; @@ -21,10 +23,10 @@ const shouldHaveCard = (status: Pick): boolean => /** Sanitize status text for use with screen readers. */ const textForScreenReader = ( intl: IntlShape, - status: Pick, + status: Pick, rebloggedByText?: string, ): string => { - const { account } = status; + const account = selectAccount(status.account_id); if (!account || typeof account !== 'object') return ''; const displayName = account.display_name;