diff --git a/src/actions/compose.ts b/src/actions/compose.ts index 0fd8784f8..bd37943ef 100644 --- a/src/actions/compose.ts +++ b/src/actions/compose.ts @@ -23,6 +23,7 @@ import type { Account as BaseAccount, BackendVersion, CreateStatusParams, Group, import type { AutoSuggestion } from 'soapbox/components/autosuggest-input'; import type { Emoji } from 'soapbox/features/emoji'; import type { Account, Status } from 'soapbox/normalizers'; +import type { ReducerStatus } from 'soapbox/reducers/statuses'; import type { AppDispatch, RootState } from 'soapbox/store'; import type { History } from 'soapbox/types/history'; @@ -110,8 +111,8 @@ const messages = defineMessages({ interface ComposeSetStatusAction { type: typeof COMPOSE_SET_STATUS; composeId: string; - status: Pick; - poll?: Poll; + status: Pick; + poll?: Poll | null; rawText: string; explicitAddressing: boolean; spoilerText?: string; @@ -122,7 +123,7 @@ interface ComposeSetStatusAction { editorState?: string | null; } -const setComposeToStatus = (status: ComposeSetStatusAction['status'], poll: Poll, rawText: string, spoilerText?: string, contentType?: string | false, withRedraft?: boolean, draftId?: string, editorState?: string | null) => +const setComposeToStatus = (status: ComposeSetStatusAction['status'], poll: Poll | null, rawText: string, spoilerText?: string, contentType?: string | false, withRedraft?: boolean, draftId?: string, editorState?: string | null) => (dispatch: AppDispatch, getState: () => RootState) => { const client = getClient(getState); const { createStatusExplicitAddressing: explicitAddressing, version: v } = client.features; @@ -154,7 +155,7 @@ const changeCompose = (composeId: string, text: string) => ({ interface ComposeReplyAction { type: typeof COMPOSE_REPLY; composeId: string; - status: Pick; + status: Pick; account: Pick; explicitAddressing: boolean; preserveSpoilers: boolean; @@ -196,7 +197,7 @@ const cancelReplyCompose = () => ({ interface ComposeQuoteAction { type: typeof COMPOSE_QUOTE; composeId: string; - status: Pick; + status: Pick; account: Pick | undefined; explicitAddressing: boolean; } diff --git a/src/api/hooks/accounts/useAccountList.ts b/src/api/hooks/accounts/useAccountList.ts index da0eab19b..af567f611 100644 --- a/src/api/hooks/accounts/useAccountList.ts +++ b/src/api/hooks/accounts/useAccountList.ts @@ -1,4 +1,4 @@ -import { accountSchema, type Account as BaseAccount } from 'pl-api'; +import { accountSchema, mutedAccountSchema, type Account as BaseAccount } from 'pl-api'; import { Entities } from 'soapbox/entity-store/entities'; import { useEntities } from 'soapbox/entity-store/hooks'; @@ -17,7 +17,7 @@ const useAccountList = (listKey: string[], entityFn: EntityFn, opts: useAc const { entities, ...rest } = useEntities( [Entities.ACCOUNTS, ...listKey], entityFn, - { schema: accountSchema, enabled: opts.enabled, transform: normalizeAccount }, + { schema: listKey[0] === 'mutes' ? mutedAccountSchema : accountSchema, enabled: opts.enabled, transform: normalizeAccount }, ); const { relationships } = useRelationships( diff --git a/src/api/hooks/groups/useDemoteGroupMember.ts b/src/api/hooks/groups/useDemoteGroupMember.ts index ee6aa9eb4..3b2d8fb97 100644 --- a/src/api/hooks/groups/useDemoteGroupMember.ts +++ b/src/api/hooks/groups/useDemoteGroupMember.ts @@ -1,9 +1,10 @@ -import { groupMemberSchema, type Group, type GroupMember, type GroupRole } from 'pl-api'; +import { groupMemberSchema, type Group, type GroupMember as GroupMember, type GroupRole } from 'pl-api'; import { z } from 'zod'; import { Entities } from 'soapbox/entity-store/entities'; import { useCreateEntity } from 'soapbox/entity-store/hooks'; import { useClient } from 'soapbox/hooks'; +import { normalizeGroupMember } from 'soapbox/normalizers/group-member'; const useDemoteGroupMember = (group: Pick, groupMember: Pick) => { const client = useClient(); @@ -11,7 +12,7 @@ const useDemoteGroupMember = (group: Pick, groupMember: Pick client.experimental.groups.demoteGroupUsers(group.id, account_ids, role), - { schema: z.array(groupMemberSchema).transform((arr) => arr[0]) }, + { schema: z.array(groupMemberSchema).transform((arr) => arr[0]), transform: normalizeGroupMember }, ); return createEntity; diff --git a/src/api/hooks/groups/useGroupMembers.ts b/src/api/hooks/groups/useGroupMembers.ts index d95c870f9..669e63c92 100644 --- a/src/api/hooks/groups/useGroupMembers.ts +++ b/src/api/hooks/groups/useGroupMembers.ts @@ -3,6 +3,7 @@ import { groupMemberSchema, type GroupMember, type GroupRoles } from 'pl-api'; import { Entities } from 'soapbox/entity-store/entities'; import { useEntities } from 'soapbox/entity-store/hooks'; import { useClient } from 'soapbox/hooks'; +import { normalizeGroupMember } from 'soapbox/normalizers/group-member'; const useGroupMembers = (groupId: string, role: GroupRoles) => { const client = useClient(); @@ -10,7 +11,7 @@ const useGroupMembers = (groupId: string, role: GroupRoles) => { const { entities, ...result } = useEntities( [Entities.GROUP_MEMBERSHIPS, groupId, role], () => client.experimental.groups.getGroupMemberships(groupId, role), - { schema: groupMemberSchema }, + { schema: groupMemberSchema, transform: normalizeGroupMember }, ); return { diff --git a/src/api/hooks/groups/useGroups.ts b/src/api/hooks/groups/useGroups.ts index 0ff89bcdb..97d9ed0a9 100644 --- a/src/api/hooks/groups/useGroups.ts +++ b/src/api/hooks/groups/useGroups.ts @@ -1,10 +1,10 @@ -import { groupSchema, type Group } from 'pl-api'; +import { groupSchema, type Group as BaseGroup } from 'pl-api'; import { Entities } from 'soapbox/entity-store/entities'; import { useEntities } from 'soapbox/entity-store/hooks'; import { useClient } from 'soapbox/hooks'; import { useFeatures } from 'soapbox/hooks/useFeatures'; -import { normalizeGroup } from 'soapbox/normalizers'; +import { normalizeGroup, type Group } from 'soapbox/normalizers'; import { useGroupRelationships } from './useGroupRelationships'; @@ -12,7 +12,7 @@ const useGroups = () => { const client = useClient(); const features = useFeatures(); - const { entities, ...result } = useEntities( + const { entities, ...result } = useEntities( [Entities.GROUPS, 'search', ''], () => client.experimental.groups.getGroups(), { enabled: features.groups, schema: groupSchema, transform: normalizeGroup }, diff --git a/src/api/hooks/groups/usePromoteGroupMember.ts b/src/api/hooks/groups/usePromoteGroupMember.ts index a9cdcac6d..a48ddae07 100644 --- a/src/api/hooks/groups/usePromoteGroupMember.ts +++ b/src/api/hooks/groups/usePromoteGroupMember.ts @@ -4,6 +4,7 @@ import { z } from 'zod'; import { Entities } from 'soapbox/entity-store/entities'; import { useCreateEntity } from 'soapbox/entity-store/hooks'; import { useClient } from 'soapbox/hooks'; +import { normalizeGroupMember } from 'soapbox/normalizers/group-member'; import type { Group, GroupMember, GroupRole } from 'pl-api'; @@ -13,7 +14,7 @@ const usePromoteGroupMember = (group: Pick, groupMember: Pick client.experimental.groups.promoteGroupUsers(group.id, account_ids, role), - { schema: z.array(groupMemberSchema).transform((arr) => arr[0]) }, + { schema: z.array(groupMemberSchema).transform((arr) => arr[0]), transform: normalizeGroupMember }, ); return createEntity; diff --git a/src/components/event-preview.tsx b/src/components/event-preview.tsx index 09ab8e849..5be64de05 100644 --- a/src/components/event-preview.tsx +++ b/src/components/event-preview.tsx @@ -10,7 +10,7 @@ import Icon from './icon'; import { Button, HStack, Stack, Text } from './ui'; import VerificationBadge from './verification-badge'; -import type { Status as StatusEntity } from 'soapbox/types/entities'; +import type { Status as StatusEntity } from 'soapbox/normalizers'; const messages = defineMessages({ eventBanner: { id: 'event.banner', defaultMessage: 'Event banner' }, diff --git a/src/components/preview-card.tsx b/src/components/preview-card.tsx index d25507901..9a53ec7f1 100644 --- a/src/components/preview-card.tsx +++ b/src/components/preview-card.tsx @@ -1,5 +1,5 @@ import clsx from 'clsx'; -import { type MediaAttachment, mediaAttachmentSchema } from 'pl-api'; +import { type MediaAttachment, type PreviewCard as CardEntity, mediaAttachmentSchema } from 'pl-api'; import React, { useState, useEffect } from 'react'; import Blurhash from 'soapbox/components/blurhash'; @@ -7,8 +7,6 @@ import { HStack, Stack, Text, Icon } from 'soapbox/components/ui'; import { addAutoPlay } from 'soapbox/utils/media'; import { getTextDirection } from 'soapbox/utils/rtl'; -import type { Card as CardEntity } from 'soapbox/types/entities'; - /** Props for `PreviewCard`. */ interface IPreviewCard { card: CardEntity; diff --git a/src/components/quoted-status.tsx b/src/components/quoted-status.tsx index d537cae0c..9c27edcf3 100644 --- a/src/components/quoted-status.tsx +++ b/src/components/quoted-status.tsx @@ -14,7 +14,7 @@ import StatusContent from './status-content'; import StatusReplyMentions from './status-reply-mentions'; import SensitiveContentOverlay from './statuses/sensitive-content-overlay'; -import type { Status as StatusEntity } from 'soapbox/types/entities'; +import type { ReducerStatus as StatusEntity } from 'soapbox/reducers/statuses'; const messages = defineMessages({ cancel: { id: 'reply_indicator.cancel', defaultMessage: 'Cancel' }, diff --git a/src/components/sidebar-menu.tsx b/src/components/sidebar-menu.tsx index f9e819fea..be37bbf84 100644 --- a/src/components/sidebar-menu.tsx +++ b/src/components/sidebar-menu.tsx @@ -15,7 +15,7 @@ import { useAppDispatch, useAppSelector, useFeatures, useInstance } from 'soapbo import { makeGetOtherAccounts } from 'soapbox/selectors'; import type { List as ImmutableList } from 'immutable'; -import type { Account as AccountEntity } from 'soapbox/types/entities'; +import type { Account as AccountEntity } from 'soapbox/normalizers'; const messages = defineMessages({ profile: { id: 'account.profile', defaultMessage: 'Profile' }, @@ -336,7 +336,7 @@ const SidebarMenu: React.FC = (): JSX.Element | null => { /> )} - {account.staff && ( + {(account.is_admin || account.is_moderator) && ( = (props) => { const [minHeight, setMinHeight] = useState(208); - const actualStatus = getActualStatus(status); + const actualStatus = getActualStatus(status); const isReblog = status.reblog && typeof status.reblog === 'object'; const statusUrl = `/@${actualStatus.account.acct}/posts/${actualStatus.id}`; const group = actualStatus.group; diff --git a/src/entity-store/hooks/useCreateEntity.ts b/src/entity-store/hooks/useCreateEntity.ts index f90d1f5ab..ecb687f7f 100644 --- a/src/entity-store/hooks/useCreateEntity.ts +++ b/src/entity-store/hooks/useCreateEntity.ts @@ -28,7 +28,7 @@ const useCreateEntity = = {}, + callbacks: EntityCallbacks = {}, ): Promise => { const result = await setPromise(entityFn(data)); const schema = opts.schema || z.custom(); @@ -39,7 +39,7 @@ const useCreateEntity = void; @@ -68,7 +66,7 @@ const AccountGallery = () => { if (attachment.type === 'video') { dispatch(openModal('VIDEO', { media: attachment, status: attachment.status, account: attachment.account })); } else { - const media = (attachment.status as Status).media_attachments; + const media = attachment.status.media_attachments; const index = media.findIndex((x) => x.id === attachment.id); dispatch(openModal('MEDIA', { media, index, status: attachment.status })); diff --git a/src/features/admin/components/report-status.tsx b/src/features/admin/components/report-status.tsx index 373bf972d..a39a191bf 100644 --- a/src/features/admin/components/report-status.tsx +++ b/src/features/admin/components/report-status.tsx @@ -8,7 +8,8 @@ import StatusMedia from 'soapbox/components/status-media'; import { HStack, Stack } from 'soapbox/components/ui'; import { useAppDispatch } from 'soapbox/hooks'; -import type { AdminReport, Status } from 'soapbox/types/entities'; +import type { Status } from 'soapbox/normalizers'; +import type { AdminReport } from 'soapbox/types/entities'; const messages = defineMessages({ viewStatus: { id: 'admin.reports.actions.view_status', defaultMessage: 'View post' }, diff --git a/src/features/compose/components/reply-mentions.tsx b/src/features/compose/components/reply-mentions.tsx index 3731ce8ca..a3ccf6a98 100644 --- a/src/features/compose/components/reply-mentions.tsx +++ b/src/features/compose/components/reply-mentions.tsx @@ -5,7 +5,7 @@ import { openModal } from 'soapbox/actions/modals'; import { useAppDispatch, useAppSelector, useCompose, useFeatures } from 'soapbox/hooks'; import { makeGetStatus } from 'soapbox/selectors'; -import type { Status as StatusEntity } from 'soapbox/types/entities'; +import type { Status as StatusEntity } from 'soapbox/normalizers'; interface IReplyMentions { composeId: string; diff --git a/src/features/draft-statuses/components/draft-status-action-bar.tsx b/src/features/draft-statuses/components/draft-status-action-bar.tsx index 14454a1cf..0ec6367b1 100644 --- a/src/features/draft-statuses/components/draft-status-action-bar.tsx +++ b/src/features/draft-statuses/components/draft-status-action-bar.tsx @@ -46,7 +46,7 @@ const DraftStatusActionBar: React.FC = ({ source, status }; const handleEditClick = () => { - dispatch(setComposeToStatus(status, source.text, source.spoiler_text, source.content_type, false, source.draft_id, source.editorState)); + dispatch(setComposeToStatus(status, status.poll, source.text, source.spoiler_text, source.content_type, false, source.draft_id, source.editorState)); dispatch(openModal('COMPOSE')); }; diff --git a/src/features/draft-statuses/components/draft-status.tsx b/src/features/draft-statuses/components/draft-status.tsx index 7af417d82..2cdd90296 100644 --- a/src/features/draft-statuses/components/draft-status.tsx +++ b/src/features/draft-statuses/components/draft-status.tsx @@ -15,8 +15,8 @@ import { buildStatus } from '../builder'; import DraftStatusActionBar from './draft-status-action-bar'; +import type { Status as StatusEntity } from 'soapbox/normalizers'; import type { DraftStatus as DraftStatusType } from 'soapbox/reducers/draft-statuses'; -import type { Status as StatusEntity } from 'soapbox/types/entities'; interface IDraftStatus { draftStatus: DraftStatusType; diff --git a/src/features/event/event-information.tsx b/src/features/event/event-information.tsx index af72c8838..93636f80b 100644 --- a/src/features/event/event-information.tsx +++ b/src/features/event/event-information.tsx @@ -12,7 +12,7 @@ import QuotedStatus from 'soapbox/features/status/containers/quoted-status-conta import { useAppDispatch, useAppSelector, useSoapboxConfig } from 'soapbox/hooks'; import { makeGetStatus } from 'soapbox/selectors'; -import type { Status as StatusEntity } from 'soapbox/types/entities'; +import type { Status as StatusEntity } from 'soapbox/normalizers'; type RouteParams = { statusId: string }; diff --git a/src/features/group/group-gallery.tsx b/src/features/group/group-gallery.tsx index e23722aee..4f2bb2adb 100644 --- a/src/features/group/group-gallery.tsx +++ b/src/features/group/group-gallery.tsx @@ -10,8 +10,8 @@ import { useAppDispatch } from 'soapbox/hooks'; import MediaItem from '../account-gallery/components/media-item'; +import type { Status } from 'soapbox/normalizers'; import type { AccountGalleryAttachment } from 'soapbox/selectors'; -import type { Status } from 'soapbox/types/entities'; interface IGroupGallery { params: { groupId: string }; diff --git a/src/features/lists/index.tsx b/src/features/lists/index.tsx index fe935aeb0..f45d7bb79 100644 --- a/src/features/lists/index.tsx +++ b/src/features/lists/index.tsx @@ -9,6 +9,7 @@ import { useAppDispatch, useAppSelector } from 'soapbox/hooks'; import NewListForm from './components/new-list-form'; +import type { List as ListEntity } from 'pl-api'; import type { RootState } from 'soapbox/store'; const messages = defineMessages({ @@ -21,7 +22,7 @@ const getOrderedLists = createSelector([(state: RootState) => state.lists], list return lists; } - return lists.toList().filter((item) => !!item).sort((a, b) => a.title.localeCompare(b.title)); + return lists.toList().filter((item): item is ListEntity => !!item).sort((a, b) => a.title.localeCompare(b.title)); }); const Lists: React.FC = () => { diff --git a/src/features/notifications/components/notification.tsx b/src/features/notifications/components/notification.tsx index 544f690b1..5fc8d81df 100644 --- a/src/features/notifications/components/notification.tsx +++ b/src/features/notifications/components/notification.tsx @@ -16,11 +16,10 @@ import { useAppDispatch, useAppSelector, useInstance } from 'soapbox/hooks'; import { makeGetNotification } from 'soapbox/selectors'; import { NotificationType } from 'soapbox/utils/notification'; -import type { Account, Notification as BaseNotification } from 'pl-api'; +import type { Notification as BaseNotification } from 'pl-api'; import type { ScrollPosition } from 'soapbox/components/status'; -import type { Notification as NotificationEntity } from 'soapbox/normalizers'; +import type { Account, Notification as NotificationEntity, Status as StatusEntity } from 'soapbox/normalizers'; import type { MinifiedNotification } from 'soapbox/reducers/notifications'; -import type { Status as StatusEntity } from 'soapbox/types/entities'; const notificationForScreenReader = (intl: IntlShape, message: string, timestamp: string) => { const output = [message]; @@ -290,7 +289,7 @@ const Notification: React.FC = (props) => { } else if (icons[type]) { return ( ); diff --git a/src/features/scheduled-statuses/components/scheduled-status-action-bar.tsx b/src/features/scheduled-statuses/components/scheduled-status-action-bar.tsx index 5ca1e0789..de9169ec3 100644 --- a/src/features/scheduled-statuses/components/scheduled-status-action-bar.tsx +++ b/src/features/scheduled-statuses/components/scheduled-status-action-bar.tsx @@ -7,7 +7,7 @@ import { getSettings } from 'soapbox/actions/settings'; import { Button, HStack } from 'soapbox/components/ui'; import { useAppDispatch } from 'soapbox/hooks'; -import type { Status as StatusEntity } from 'soapbox/types/entities'; +import type { Status as StatusEntity } from 'soapbox/normalizers'; const messages = defineMessages({ cancel: { id: 'scheduled_status.cancel', defaultMessage: 'Cancel' }, diff --git a/src/features/security/mfa-form.tsx b/src/features/security/mfa-form.tsx index a1b488da6..5d2f1f314 100644 --- a/src/features/security/mfa-form.tsx +++ b/src/features/security/mfa-form.tsx @@ -34,11 +34,11 @@ const MfaForm: React.FC = () => { setDisplayOtpForm(true); }; - const mfa = useAppSelector((state) => state.security.get('mfa')); + const mfa = useAppSelector((state) => state.security.mfa); return ( - {mfa.getIn(['settings', 'totp']) ? ( + {mfa.settings.totp ? ( ) : ( diff --git a/src/features/status/components/detailed-status.tsx b/src/features/status/components/detailed-status.tsx index e61353642..0d2a233cc 100644 --- a/src/features/status/components/detailed-status.tsx +++ b/src/features/status/components/detailed-status.tsx @@ -16,7 +16,7 @@ import { getActualStatus } from 'soapbox/utils/status'; import StatusInteractionBar from './status-interaction-bar'; -import type { Status as StatusEntity } from 'soapbox/types/entities'; +import type { Status as StatusEntity } from 'soapbox/normalizers'; interface IDetailedStatus { status: StatusEntity; @@ -81,7 +81,7 @@ const DetailedStatus: React.FC = ({ } }; - const actualStatus = getActualStatus(status); + const actualStatus = getActualStatus(status); if (!actualStatus) return null; const { account } = actualStatus; if (!account || typeof account !== 'object') return null; diff --git a/src/features/status/components/status-interaction-bar.tsx b/src/features/status/components/status-interaction-bar.tsx index c43feb8e7..f53a329ea 100644 --- a/src/features/status/components/status-interaction-bar.tsx +++ b/src/features/status/components/status-interaction-bar.tsx @@ -8,7 +8,7 @@ import { HStack, Text, Emoji } from 'soapbox/components/ui'; import { useAppSelector, useSoapboxConfig, useFeatures, useAppDispatch } from 'soapbox/hooks'; import { reduceEmoji } from 'soapbox/utils/emoji-reacts'; -import type { Status } from 'soapbox/types/entities'; +import type { Status } from 'soapbox/normalizers'; interface IStatusInteractionBar { status: Status; diff --git a/src/features/status/components/thread.tsx b/src/features/status/components/thread.tsx index c36218b2a..49bcc667f 100644 --- a/src/features/status/components/thread.tsx +++ b/src/features/status/components/thread.tsx @@ -25,7 +25,7 @@ import { textForScreenReader } from 'soapbox/utils/status'; import DetailedStatus from './detailed-status'; import ThreadStatus from './thread-status'; -import type { Account, Status } from 'soapbox/types/entities'; +import type { Account, Status } from 'soapbox/normalizers'; const getAncestorsIds = createSelector([ (_: RootState, statusId: string | undefined) => statusId, diff --git a/src/features/ui/components/modals/boost-modal.tsx b/src/features/ui/components/modals/boost-modal.tsx index 2281dc1c4..127713317 100644 --- a/src/features/ui/components/modals/boost-modal.tsx +++ b/src/features/ui/components/modals/boost-modal.tsx @@ -5,7 +5,7 @@ import Icon from 'soapbox/components/icon'; import { Modal, Stack, Text } from 'soapbox/components/ui'; import ReplyIndicator from 'soapbox/features/compose/components/reply-indicator'; -import type { Status as StatusEntity } from 'soapbox/types/entities'; +import type { Status as StatusEntity } from 'soapbox/normalizers'; const messages = defineMessages({ cancel_reblog: { id: 'status.cancel_reblog_private', defaultMessage: 'Un-repost' }, @@ -14,7 +14,7 @@ const messages = defineMessages({ interface IBoostModal { status: StatusEntity; - onReblog: (status: StatusEntity) => void; + onReblog: (status: Pick) => void; onClose: () => void; } diff --git a/src/features/ui/components/modals/media-modal.tsx b/src/features/ui/components/modals/media-modal.tsx index 9c103d49c..2894d8a0a 100644 --- a/src/features/ui/components/modals/media-modal.tsx +++ b/src/features/ui/components/modals/media-modal.tsx @@ -20,7 +20,7 @@ import { makeGetStatus } from 'soapbox/selectors'; import ImageLoader from '../image-loader'; import type { MediaAttachment } from 'pl-api'; -import type { Status } from 'soapbox/types/entities'; +import type { Status } from 'soapbox/normalizers'; const messages = defineMessages({ close: { id: 'lightbox.close', defaultMessage: 'Close' }, diff --git a/src/features/ui/components/modals/select-bookmark-folder-modal.tsx b/src/features/ui/components/modals/select-bookmark-folder-modal.tsx index 7ab95cfdc..82fb462d9 100644 --- a/src/features/ui/components/modals/select-bookmark-folder-modal.tsx +++ b/src/features/ui/components/modals/select-bookmark-folder-modal.tsx @@ -9,7 +9,7 @@ import NewFolderForm from 'soapbox/features/bookmark-folders/components/new-fold import { useAppDispatch, useAppSelector } from 'soapbox/hooks'; import { makeGetStatus } from 'soapbox/selectors'; -import type { Status as StatusEntity } from 'soapbox/types/entities'; +import type { Status as StatusEntity } from 'soapbox/normalizers'; interface ISelectBookmarkFolderModal { statusId: string; diff --git a/src/features/ui/components/modals/video-modal.tsx b/src/features/ui/components/modals/video-modal.tsx index 02b009c5e..1efc8c62f 100644 --- a/src/features/ui/components/modals/video-modal.tsx +++ b/src/features/ui/components/modals/video-modal.tsx @@ -5,7 +5,7 @@ import { useHistory } from 'react-router-dom'; import Video from 'soapbox/features/video'; import type { MediaAttachment } from 'pl-api'; -import type { Status, Account } from 'soapbox/types/entities'; +import type { Account, Status } from 'soapbox/normalizers'; interface IVideoModal { media: MediaAttachment; diff --git a/src/features/ui/components/pending-status.tsx b/src/features/ui/components/pending-status.tsx index a18990923..96939a104 100644 --- a/src/features/ui/components/pending-status.tsx +++ b/src/features/ui/components/pending-status.tsx @@ -14,7 +14,7 @@ import { buildStatus } from '../util/pending-status-builder'; import PollPreview from './poll-preview'; -import type { Status as StatusEntity } from 'soapbox/types/entities'; +import type { Status as StatusEntity } from 'soapbox/normalizers'; const shouldHaveCard = (pendingStatus: StatusEntity) => Boolean(pendingStatus.content.match(/https?:\/\/\S*/)); @@ -47,7 +47,7 @@ const PendingStatus: React.FC = ({ idempotencyKey, className, mu const status = useAppSelector((state) => { const pendingStatus = state.pending_statuses.get(idempotencyKey); return pendingStatus ? buildStatus(state, pendingStatus, idempotencyKey) : null; - }) as StatusEntity | null; + }); if (!status) return null; if (!status.account) return null; @@ -89,7 +89,7 @@ const PendingStatus: React.FC = ({ idempotencyKey, className, mu {status.poll && } - {status.quote && } + {status.quote && } diff --git a/src/features/ui/components/profile-dropdown.tsx b/src/features/ui/components/profile-dropdown.tsx index d8d989949..8078d7d86 100644 --- a/src/features/ui/components/profile-dropdown.tsx +++ b/src/features/ui/components/profile-dropdown.tsx @@ -13,7 +13,7 @@ import { makeGetAccount } from 'soapbox/selectors'; import ThemeToggle from './theme-toggle'; -import type { Account as AccountEntity } from 'soapbox/types/entities'; +import type { Account as AccountEntity } from 'soapbox/normalizers'; const messages = defineMessages({ add: { id: 'profile_dropdown.add_account', defaultMessage: 'Add an existing account' }, diff --git a/src/features/ui/components/subscription-button.tsx b/src/features/ui/components/subscription-button.tsx index e8f974429..882f835a2 100644 --- a/src/features/ui/components/subscription-button.tsx +++ b/src/features/ui/components/subscription-button.tsx @@ -6,7 +6,7 @@ import { IconButton } from 'soapbox/components/ui'; import { useFeatures } from 'soapbox/hooks'; import toast from 'soapbox/toast'; -import type { Account as AccountEntity } from 'soapbox/types/entities'; +import type { Account as AccountEntity } from 'soapbox/normalizers'; const messages = defineMessages({ subscribe: { id: 'account.subscribe', defaultMessage: 'Subscribe to notifications from @{name}' }, diff --git a/src/features/ui/components/who-to-follow-panel.tsx b/src/features/ui/components/who-to-follow-panel.tsx index 56ab2c739..182e09cb4 100644 --- a/src/features/ui/components/who-to-follow-panel.tsx +++ b/src/features/ui/components/who-to-follow-panel.tsx @@ -7,7 +7,7 @@ import AccountContainer from 'soapbox/containers/account-container'; import PlaceholderSidebarSuggestions from 'soapbox/features/placeholder/components/placeholder-sidebar-suggestions'; import { useDismissSuggestion, useSuggestions } from 'soapbox/queries/suggestions'; -import type { Account as AccountEntity } from 'soapbox/types/entities'; +import type { Account as AccountEntity } from 'soapbox/normalizers'; const messages = defineMessages({ dismissSuggestion: { id: 'suggestions.dismiss', defaultMessage: 'Dismiss suggestion' }, diff --git a/src/features/ui/util/pending-status-builder.ts b/src/features/ui/util/pending-status-builder.ts index 2a35a930d..3fa1e8b8b 100644 --- a/src/features/ui/util/pending-status-builder.ts +++ b/src/features/ui/util/pending-status-builder.ts @@ -41,7 +41,7 @@ const buildStatus = (state: RootState, pendingStatus: PendingStatus, idempotency media_attachments: (pendingStatus.media_ids || ImmutableList()).map((id: string) => ({ id })), mentions: buildMentions(pendingStatus), poll: buildPoll(pendingStatus), - quote: pendingStatus.quote_id, + quote: pendingStatus.quote_id ? state.statuses.get(pendingStatus.quote_id) : null, sensitive: pendingStatus.sensitive, visibility: pendingStatus.visibility, }; diff --git a/src/normalizers/account.ts b/src/normalizers/account.ts index e574d9dfb..ed8e945be 100644 --- a/src/normalizers/account.ts +++ b/src/normalizers/account.ts @@ -37,6 +37,7 @@ const normalizeAccount = (account: BaseAccount) => { const emojiMap = makeEmojiMap(account.emojis); return { + mute_expires_at: null, ...account, avatar: account.avatar || account.avatar_static || missingAvatar, avatar_static: account.avatar_static || account.avatar || missingAvatar, diff --git a/src/normalizers/admin-account.ts b/src/normalizers/admin-account.ts index b62a16e8d..0e0675a31 100644 --- a/src/normalizers/admin-account.ts +++ b/src/normalizers/admin-account.ts @@ -9,7 +9,8 @@ import { fromJS, } from 'immutable'; -import type { Account, EmbeddedEntity } from 'soapbox/types/entities'; +import type { Account } from 'soapbox/normalizers'; +import type { EmbeddedEntity } from 'soapbox/types/entities'; const AdminAccountRecord = ImmutableRecord({ account: null as EmbeddedEntity, diff --git a/src/normalizers/admin-report.ts b/src/normalizers/admin-report.ts index b5bf5e444..4cf0a40fa 100644 --- a/src/normalizers/admin-report.ts +++ b/src/normalizers/admin-report.ts @@ -9,7 +9,8 @@ import { fromJS, } from 'immutable'; -import type { Account, EmbeddedEntity, Status } from 'soapbox/types/entities'; +import type { Account, Status } from 'soapbox/normalizers'; +import type { EmbeddedEntity } from 'soapbox/types/entities'; const AdminReportRecord = ImmutableRecord({ account: null as EmbeddedEntity, diff --git a/src/reducers/compose.ts b/src/reducers/compose.ts index 8e70194a6..543aa07ed 100644 --- a/src/reducers/compose.ts +++ b/src/reducers/compose.ts @@ -331,7 +331,7 @@ const compose = (state = initialState, action: ComposeAction | EventsAction | Me ? statusToMentionsArray(action.status, action.account, action.rebloggedBy) : ImmutableOrderedSet(); - map.set('group_id', action.status.group?.id as string); + map.set('group_id', typeof action.status.group === 'string' ? action.status.group : action.status.group?.id || null); map.set('in_reply_to', action.status.id); map.set('to', to); map.set('parent_reblogged_by', action.rebloggedBy?.id || null); @@ -371,7 +371,7 @@ const compose = (state = initialState, action: ComposeAction | EventsAction | Me map.set('spoiler_text', ''); if (action.status.visibility === 'group') { - map.set('group_id', action.status.group?.id as string); + map.set('group_id', typeof action.status.group === 'string' ? action.status.group : action.status.group?.id || null); map.set('privacy', 'group'); } })); @@ -474,8 +474,8 @@ const compose = (state = initialState, action: ComposeAction | EventsAction | Me map.set('caretPosition', null); map.set('idempotencyKey', uuid()); map.set('content_type', action.contentType || 'text/plain'); - map.set('quote', action.status.quote?.id as string); - map.set('group_id', action.status.group?.id as string); + map.set('quote', typeof action.status.quote === 'string' ? action.status.quote : action.status.quote?.id || null); + map.set('group_id', typeof action.status.group === 'string' ? action.status.group : action.status.group?.id || null); if (action.v?.software === PLEROMA && action.withRedraft && hasIntegerMediaIds(action.status)) { map.set('media_attachments', ImmutableList());