diff --git a/src/components/attachment-thumbs.tsx b/src/components/attachment-thumbs.tsx index 4829b7688..2b4aadf75 100644 --- a/src/components/attachment-thumbs.tsx +++ b/src/components/attachment-thumbs.tsx @@ -3,12 +3,10 @@ import { Suspense } from 'react'; import { openModal } from 'soapbox/actions/modals.ts'; import { MediaGallery } from 'soapbox/features/ui/util/async-components.ts'; import { useAppDispatch } from 'soapbox/hooks/useAppDispatch.ts'; - -import type { List as ImmutableList } from 'immutable'; -import type { Attachment } from 'soapbox/types/entities.ts'; +import { Attachment } from 'soapbox/schemas/index.ts'; interface IAttachmentThumbs { - media: ImmutableList; + media: readonly Attachment[]; onClick?(): void; sensitive?: boolean; } @@ -18,7 +16,7 @@ const AttachmentThumbs = (props: IAttachmentThumbs) => { const dispatch = useAppDispatch(); const fallback =
; - const onOpenMedia = (media: ImmutableList, index: number) => dispatch(openModal('MEDIA', { media, index })); + const onOpenMedia = (media: readonly Attachment[], index: number) => dispatch(openModal('MEDIA', { media, index })); return (
diff --git a/src/components/dropdown-menu/dropdown-menu.tsx b/src/components/dropdown-menu/dropdown-menu.tsx index 161d92307..84af570bb 100644 --- a/src/components/dropdown-menu/dropdown-menu.tsx +++ b/src/components/dropdown-menu/dropdown-menu.tsx @@ -9,13 +9,12 @@ import { closeDropdownMenu as closeDropdownMenuRedux, openDropdownMenu } from 's import { closeModal, openModal } from 'soapbox/actions/modals.ts'; import IconButton from 'soapbox/components/ui/icon-button.tsx'; import Portal from 'soapbox/components/ui/portal.tsx'; +import { Entities, EntityTypes } from 'soapbox/entity-store/entities.ts'; import { useAppDispatch } from 'soapbox/hooks/useAppDispatch.ts'; import { userTouching } from 'soapbox/is-mobile.ts'; import DropdownMenuItem, { MenuItem } from './dropdown-menu-item.tsx'; -import type { Status } from 'soapbox/types/entities.ts'; - export type Menu = Array; interface IDropdownMenu { @@ -28,7 +27,7 @@ interface IDropdownMenu { onShiftClick?: React.EventHandler; placement?: Placement; src?: string; - status?: Status; + status?: EntityTypes[Entities.STATUSES]; title?: string; } diff --git a/src/components/media-gallery.tsx b/src/components/media-gallery.tsx index 085d95e61..9b59bab2d 100644 --- a/src/components/media-gallery.tsx +++ b/src/components/media-gallery.tsx @@ -8,7 +8,7 @@ import StillImage from 'soapbox/components/still-image.tsx'; import { MIMETYPE_ICONS } from 'soapbox/components/upload.tsx'; import { useSettings } from 'soapbox/hooks/useSettings.ts'; import { useSoapboxConfig } from 'soapbox/hooks/useSoapboxConfig.ts'; -import { Attachment } from 'soapbox/types/entities.ts'; +import { Attachment } from 'soapbox/schemas/index.ts'; import { truncateFilename } from 'soapbox/utils/media.ts'; import { isIOS } from '../is-mobile.ts'; @@ -16,8 +16,6 @@ import { isPanoramic, isPortrait, isNonConformingRatio, minimumAspectRatio, maxi import SvgIcon from './ui/svg-icon.tsx'; -import type { List as ImmutableList } from 'immutable'; - // const Gameboy = lazy(() => import('./gameboy')); const ATTACHMENT_LIMIT = 4; @@ -46,7 +44,8 @@ const withinLimits = (aspectRatio: number) => { }; const shouldLetterbox = (attachment: Attachment): boolean => { - const aspectRatio = attachment.getIn(['meta', 'original', 'aspect']) as number | undefined; + const aspectRatio = 'meta' in attachment && 'original' in attachment.meta && (attachment)?.meta?.original?.aspect; + if (!aspectRatio) return true; return !withinLimits(aspectRatio); @@ -159,7 +158,7 @@ const Item: React.FC = ({ const attachmentIcon = ( ); @@ -291,9 +290,9 @@ const Item: React.FC = ({ export interface IMediaGallery { sensitive?: boolean; - media: ImmutableList; + media: readonly Attachment[]; height?: number; - onOpenMedia: (media: ImmutableList, index: number) => void; + onOpenMedia: (media: readonly Attachment[], index: number) => void; defaultWidth?: number; cacheWidth?: (width: number) => void; visible?: boolean; @@ -323,7 +322,7 @@ const MediaGallery: React.FC = (props) => { const getSizeDataSingle = (): SizeData => { const w = width || defaultWidth; - const aspectRatio = media.getIn([0, 'meta', 'original', 'aspect']) as number | undefined; + const aspectRatio = 'meta' in media[0] && 'original' in media[0].meta && (media[0])?.meta?.original?.aspect; const getHeight = () => { if (!aspectRatio) return w * 9 / 16; @@ -349,7 +348,9 @@ const MediaGallery: React.FC = (props) => { let itemsDimensions: Dimensions[] = []; const ratios = Array(size).fill(null).map((_, i) => - media.getIn([i, 'meta', 'original', 'aspect']) as number, + 'meta' in media[i] && 'original' in media[i].meta && typeof media[i].meta?.original?.aspect === 'number' + ? media[i].meta.original.aspect + : undefined as unknown as number, // NOTE: the old logic returned undefined anyways, and the implementation of the functions below call 'isNaN', such as the 'isPortrait' function ); const [ar1, ar2, ar3, ar4] = ratios; @@ -547,9 +548,9 @@ const MediaGallery: React.FC = (props) => { }; }; - const sizeData: SizeData = getSizeData(media.size); + const sizeData: SizeData = getSizeData(media.length); - const children = media.take(ATTACHMENT_LIMIT).map((attachment, i) => ( + const children = media.slice(0, ATTACHMENT_LIMIT).map((attachment, i) => ( = (props) => { visible={!!props.visible} dimensions={sizeData.itemsDimensions[i]} last={i === ATTACHMENT_LIMIT - 1} - total={media.size} + total={media.length} compact={compact} /> )); diff --git a/src/components/preview-card.tsx b/src/components/preview-card.tsx index c9f70c981..3e8282396 100644 --- a/src/components/preview-card.tsx +++ b/src/components/preview-card.tsx @@ -3,7 +3,6 @@ import linkIcon from '@tabler/icons/outline/link.svg'; import playerPlayIcon from '@tabler/icons/outline/player-play.svg'; import zoomInIcon from '@tabler/icons/outline/zoom-in.svg'; import clsx from 'clsx'; -import { List as ImmutableList } from 'immutable'; import { useState, useEffect, useRef } from 'react'; import Blurhash from 'soapbox/components/blurhash.tsx'; @@ -12,17 +11,18 @@ import Stack from 'soapbox/components/ui/stack.tsx'; import SvgIcon from 'soapbox/components/ui/svg-icon.tsx'; import Text from 'soapbox/components/ui/text.tsx'; import { normalizeAttachment } from 'soapbox/normalizers/index.ts'; +import { Attachment } from 'soapbox/schemas/index.ts'; import { addAutoPlay } from 'soapbox/utils/media.ts'; import { getTextDirection } from 'soapbox/utils/rtl.ts'; -import type { Card as CardEntity, Attachment } from 'soapbox/types/entities.ts'; +import type { Card as CardEntity } from 'soapbox/types/entities.ts'; /** Props for `PreviewCard`. */ interface IPreviewCard { card: CardEntity; maxTitle?: number; maxDescription?: number; - onOpenMedia: (attachments: ImmutableList, index: number) => void; + onOpenMedia: (attachments: readonly Attachment[], index: number) => void; compact?: boolean; defaultWidth?: number; cacheWidth?: (width: number) => void; @@ -73,9 +73,9 @@ const PreviewCard: React.FC = ({ height: card.height, }, }, - }); + }).toJS(); - onOpenMedia(ImmutableList([attachment]), 0); + onOpenMedia([{ ...attachment, blurhash: attachment.blurhash === undefined ? null : attachment.blurhash } as Attachment], 0); }; const handleEmbedClick: React.MouseEventHandler = (e) => { diff --git a/src/components/pure-status.tsx b/src/components/pure-status.tsx index 51e40d0f6..7135c690d 100644 --- a/src/components/pure-status.tsx +++ b/src/components/pure-status.tsx @@ -2,11 +2,10 @@ import circlesIcon from '@tabler/icons/outline/circles.svg'; import pinnedIcon from '@tabler/icons/outline/pinned.svg'; import repeatIcon from '@tabler/icons/outline/repeat.svg'; import clsx from 'clsx'; -import { useCallback, useEffect, useRef, useState } from 'react'; +import { useEffect, useRef, useState } from 'react'; import { useIntl, FormattedMessage, defineMessages } from 'react-intl'; import { Link, useHistory } from 'react-router-dom'; -import { importFetchedStatuses } from 'soapbox/actions/importer/index.ts'; import { openModal } from 'soapbox/actions/modals.ts'; import { unfilterStatus } from 'soapbox/actions/statuses.ts'; import PureEventPreview from 'soapbox/components/pure-event-preview.tsx'; @@ -23,14 +22,14 @@ import { EntityTypes, Entities } from 'soapbox/entity-store/entities.ts'; import QuotedStatus from 'soapbox/features/status/containers/quoted-status-container.tsx'; import { HotKeys } from 'soapbox/features/ui/components/hotkeys.tsx'; import { useAppDispatch } from 'soapbox/hooks/useAppDispatch.ts'; -import { useAppSelector } from 'soapbox/hooks/useAppSelector.ts'; import { useFavourite } from 'soapbox/hooks/useFavourite.ts'; import { useMentionCompose } from 'soapbox/hooks/useMentionCompose.ts'; import { useReblog } from 'soapbox/hooks/useReblog.ts'; import { useReplyCompose } from 'soapbox/hooks/useReplyCompose.ts'; import { useSettings } from 'soapbox/hooks/useSettings.ts'; import { useStatusHidden } from 'soapbox/hooks/useStatusHidden.ts'; -import { makeGetStatus } from 'soapbox/selectors/index.ts'; +import { normalizeStatus } from 'soapbox/normalizers/index.ts'; +import { Status } from 'soapbox/types/entities.ts'; import { emojifyText } from 'soapbox/utils/emojify.tsx'; import { defaultMediaVisibility, textForScreenReader, getActualStatus } from 'soapbox/utils/status.ts'; @@ -127,16 +126,7 @@ const PureStatus: React.FC = (props) => { } }, [overlay.current]); - // TODO: remove this code, it will be removed once all components in this file are pure. - useEffect(() => { - dispatch(importFetchedStatuses([status])); - }, []); - const getStatus = useCallback(makeGetStatus(), []); - const statusImmutable = useAppSelector(state => getStatus(state, { id: status.id })); - if (!statusImmutable) { - return null; - } - // END TODO + const statusImmutable = normalizeStatus(status) as Status; // TODO: remove this line, it will be removed once all components in this file are pure. const handleToggleMediaVisibility = (): void => { setShowMedia(!showMedia); @@ -486,7 +476,7 @@ const PureStatus: React.FC = (props) => { {(quote || actualStatus.card || actualStatus.media_attachments.length > 0) && ( = ({ status, onCancel, compose }) => {status.media_attachments.size > 0 && ( = ({ /> )} - + = ({ }) => { const dispatch = useAppDispatch(); - const size = status.media_attachments.size; - const firstAttachment = status.media_attachments.first(); + const size = status.media_attachments.length; + const firstAttachment = status.media_attachments[0]; let media: JSX.Element | null = null; @@ -52,7 +51,7 @@ const StatusMedia: React.FC = ({ return
; }; - const openMedia = (media: ImmutableList, index: number) => { + const openMedia = (media: readonly Attachment[], index: number) => { dispatch(openModal('MEDIA', { media, status, index })); }; @@ -72,10 +71,10 @@ const StatusMedia: React.FC = ({ diff --git a/src/components/status.tsx b/src/components/status.tsx index dc36ae974..1b189d5d1 100644 --- a/src/components/status.tsx +++ b/src/components/status.tsx @@ -16,6 +16,7 @@ import Icon from 'soapbox/components/ui/icon.tsx'; import Stack from 'soapbox/components/ui/stack.tsx'; import Text from 'soapbox/components/ui/text.tsx'; import AccountContainer from 'soapbox/containers/account-container.tsx'; +import { Entities, EntityTypes } from 'soapbox/entity-store/entities.ts'; import QuotedStatus from 'soapbox/features/status/containers/quoted-status-container.tsx'; import { HotKeys } from 'soapbox/features/ui/components/hotkeys.tsx'; import { useAppDispatch } from 'soapbox/hooks/useAppDispatch.ts'; @@ -465,7 +466,7 @@ const Status: React.FC = (props) => { {(quote || actualStatus.card || actualStatus.media_attachments.size > 0) && ( = ({ status }) => { - +
diff --git a/src/features/chats/components/chat-message.tsx b/src/features/chats/components/chat-message.tsx index 22204041d..5d5c26190 100644 --- a/src/features/chats/components/chat-message.tsx +++ b/src/features/chats/components/chat-message.tsx @@ -23,6 +23,7 @@ import { useAppSelector } from 'soapbox/hooks/useAppSelector.ts'; import { useFeatures } from 'soapbox/hooks/useFeatures.ts'; import { ChatKeys, IChat, useChatActions } from 'soapbox/queries/chats.ts'; import { queryClient } from 'soapbox/queries/client.ts'; +import { Attachment } from 'soapbox/schemas/index.ts'; import { htmlToPlaintext } from 'soapbox/utils/html.ts'; import { isOnlyEmoji as _isOnlyEmoji } from 'soapbox/utils/only-emoji.ts'; @@ -112,7 +113,7 @@ const ChatMessage = (props: IChatMessage) => { 'rounded-br-sm': isMyMessage && content, 'rounded-bl-sm': !isMyMessage && content, })} - media={chatMessage.media_attachments} + media={chatMessage.media_attachments.toJS() as unknown as Attachment[]} onOpenMedia={onOpenMedia} visible /> diff --git a/src/features/compose/components/reply-indicator.tsx b/src/features/compose/components/reply-indicator.tsx index 5570ec7cc..7d12ae738 100644 --- a/src/features/compose/components/reply-indicator.tsx +++ b/src/features/compose/components/reply-indicator.tsx @@ -5,13 +5,12 @@ import AttachmentThumbs from 'soapbox/components/attachment-thumbs.tsx'; import Markup from 'soapbox/components/markup.tsx'; import Stack from 'soapbox/components/ui/stack.tsx'; import AccountContainer from 'soapbox/containers/account-container.tsx'; +import { Entities, EntityTypes } from 'soapbox/entity-store/entities.ts'; import { getTextDirection } from 'soapbox/utils/rtl.ts'; -import type { Status } from 'soapbox/types/entities.ts'; - interface IReplyIndicator { className?: string; - status?: Status; + status?: EntityTypes[Entities.STATUSES]; onCancel?: () => void; hideActions: boolean; } @@ -50,12 +49,12 @@ const ReplyIndicator: React.FC = ({ className, status, hideActi className='break-words' size='sm' direction={getTextDirection(status.search_index)} - emojis={status?.emojis?.toJS() ?? status.emojis} // Use toJS() if status.emojis is immutable; otherwise, fallback to plain status.emojis - mentions={status.mentions.toJS()} + emojis={status.emojis} + mentions={status.mentions} html={{ __html: status.content }} /> - {status.media_attachments.size > 0 && ( + {status.media_attachments.length > 0 && ( { const editing = !!state.compose.get(composeId)?.id; return { - status: getStatus(state, { id: statusId }) as Status, + status: (getStatus(state, { id: statusId }) as Status)?.toJS() as EntityTypes[Entities.STATUSES], hideActions: editing, }; }; diff --git a/src/features/event/event-information.tsx b/src/features/event/event-information.tsx index 0b01c27dd..9d64356a4 100644 --- a/src/features/event/event-information.tsx +++ b/src/features/event/event-information.tsx @@ -15,6 +15,7 @@ import HStack from 'soapbox/components/ui/hstack.tsx'; import Icon from 'soapbox/components/ui/icon.tsx'; import Stack from 'soapbox/components/ui/stack.tsx'; import Text from 'soapbox/components/ui/text.tsx'; +import { Entities, EntityTypes } from 'soapbox/entity-store/entities.ts'; import QuotedStatus from 'soapbox/features/status/containers/quoted-status-container.tsx'; import { useAppDispatch } from 'soapbox/hooks/useAppDispatch.ts'; import { useAppSelector } from 'soapbox/hooks/useAppSelector.ts'; @@ -208,7 +209,7 @@ const EventInformation: React.FC = ({ params }) => { )} diff --git a/src/features/report/components/status-check-box.tsx b/src/features/report/components/status-check-box.tsx index 149a5b352..29c63ee3f 100644 --- a/src/features/report/components/status-check-box.tsx +++ b/src/features/report/components/status-check-box.tsx @@ -7,6 +7,7 @@ import Toggle from 'soapbox/components/ui/toggle.tsx'; import { MediaGallery, Video, Audio } from 'soapbox/features/ui/util/async-components.ts'; import { useAppDispatch } from 'soapbox/hooks/useAppDispatch.ts'; import { useAppSelector } from 'soapbox/hooks/useAppSelector.ts'; +import { Attachment } from 'soapbox/schemas/index.ts'; interface IStatusCheckBox { id: string; @@ -62,7 +63,7 @@ const StatusCheckBox: React.FC = ({ id, disabled }) => { } else { media = ( {}} diff --git a/src/features/scheduled-statuses/components/scheduled-status.tsx b/src/features/scheduled-statuses/components/scheduled-status.tsx index ea45ef9aa..137f85ce8 100644 --- a/src/features/scheduled-statuses/components/scheduled-status.tsx +++ b/src/features/scheduled-statuses/components/scheduled-status.tsx @@ -8,6 +8,7 @@ import HStack from 'soapbox/components/ui/hstack.tsx'; import Stack from 'soapbox/components/ui/stack.tsx'; import PollPreview from 'soapbox/features/ui/components/poll-preview.tsx'; import { useAppSelector } from 'soapbox/hooks/useAppSelector.ts'; +import { Attachment } from 'soapbox/schemas/index.ts'; import { buildStatus } from '../builder.tsx'; @@ -55,7 +56,7 @@ const ScheduledStatus: React.FC = ({ statusId, ...other }) => {status.media_attachments.size > 0 && ( )} diff --git a/src/features/status/components/detailed-status.tsx b/src/features/status/components/detailed-status.tsx index 39bf23c7f..2f0c82053 100644 --- a/src/features/status/components/detailed-status.tsx +++ b/src/features/status/components/detailed-status.tsx @@ -16,6 +16,7 @@ import HStack from 'soapbox/components/ui/hstack.tsx'; import Icon from 'soapbox/components/ui/icon.tsx'; import Stack from 'soapbox/components/ui/stack.tsx'; import Text from 'soapbox/components/ui/text.tsx'; +import { Entities, EntityTypes } from 'soapbox/entity-store/entities.ts'; import QuotedStatus from 'soapbox/features/status/containers/quoted-status-container.tsx'; import { getActualStatus } from 'soapbox/utils/status.ts'; @@ -162,7 +163,7 @@ const DetailedStatus: React.FC = ({ {(withMedia && (quote || actualStatus.card || actualStatus.media_attachments.size > 0)) && ( diff --git a/src/features/ui/components/modals/actions-modal.tsx b/src/features/ui/components/modals/actions-modal.tsx index 6641298b6..9aacd9b3e 100644 --- a/src/features/ui/components/modals/actions-modal.tsx +++ b/src/features/ui/components/modals/actions-modal.tsx @@ -4,15 +4,15 @@ import { spring } from 'react-motion'; import HStack from 'soapbox/components/ui/hstack.tsx'; import SvgIcon from 'soapbox/components/ui/svg-icon.tsx'; +import { Entities, EntityTypes } from 'soapbox/entity-store/entities.ts'; import ReplyIndicator from 'soapbox/features/compose/components/reply-indicator.tsx'; import Motion from '../../util/optional-motion.tsx'; import type { Menu, MenuItem } from 'soapbox/components/dropdown-menu/index.ts'; -import type { Status as StatusEntity } from 'soapbox/types/entities.ts'; interface IActionsModal { - status: StatusEntity; + status: EntityTypes[Entities.STATUSES]; actions: Menu; onClick: () => void; onClose: () => void; diff --git a/src/features/ui/components/modals/boost-modal.tsx b/src/features/ui/components/modals/boost-modal.tsx index 425e8580a..afe841a3c 100644 --- a/src/features/ui/components/modals/boost-modal.tsx +++ b/src/features/ui/components/modals/boost-modal.tsx @@ -5,6 +5,7 @@ import Icon from 'soapbox/components/icon.tsx'; import Modal from 'soapbox/components/ui/modal.tsx'; import Stack from 'soapbox/components/ui/stack.tsx'; import Text from 'soapbox/components/ui/text.tsx'; +import { Entities, EntityTypes } from 'soapbox/entity-store/entities.ts'; import ReplyIndicator from 'soapbox/features/compose/components/reply-indicator.tsx'; import type { Status as StatusEntity } from 'soapbox/types/entities.ts'; @@ -37,7 +38,7 @@ const BoostModal: React.FC = ({ status, onReblog, onClose }) => { confirmationText={intl.formatMessage(buttonText)} > - + {/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */} diff --git a/src/features/ui/components/modals/compare-history-modal.tsx b/src/features/ui/components/modals/compare-history-modal.tsx index 313de9291..133359516 100644 --- a/src/features/ui/components/modals/compare-history-modal.tsx +++ b/src/features/ui/components/modals/compare-history-modal.tsx @@ -12,6 +12,7 @@ import Stack from 'soapbox/components/ui/stack.tsx'; import Text from 'soapbox/components/ui/text.tsx'; import { useAppDispatch } from 'soapbox/hooks/useAppDispatch.ts'; import { useAppSelector } from 'soapbox/hooks/useAppSelector.ts'; +import { Attachment } from 'soapbox/schemas/index.ts'; import { emojifyText } from 'soapbox/utils/emojify.tsx'; import type { StatusEdit as StatusEditEntity } from 'soapbox/types/entities.ts'; @@ -81,7 +82,7 @@ const CompareHistoryModal: React.FC = ({ onClose, statusId )} {version.media_attachments.size > 0 && ( - + )} diff --git a/src/features/ui/components/modals/media-modal.tsx b/src/features/ui/components/modals/media-modal.tsx index 2faa1de1d..59c3a6763 100644 --- a/src/features/ui/components/modals/media-modal.tsx +++ b/src/features/ui/components/modals/media-modal.tsx @@ -19,20 +19,20 @@ import HStack from 'soapbox/components/ui/hstack.tsx'; import IconButton from 'soapbox/components/ui/icon-button.tsx'; import Icon from 'soapbox/components/ui/icon.tsx'; import Stack from 'soapbox/components/ui/stack.tsx'; +import { Entities, EntityTypes } from 'soapbox/entity-store/entities.ts'; import Audio from 'soapbox/features/audio/index.tsx'; import PlaceholderStatus from 'soapbox/features/placeholder/components/placeholder-status.tsx'; import Thread from 'soapbox/features/status/components/thread.tsx'; import Video from 'soapbox/features/video/index.tsx'; import { useAppDispatch } from 'soapbox/hooks/useAppDispatch.ts'; -import { useAppSelector } from 'soapbox/hooks/useAppSelector.ts'; import { userTouching } from 'soapbox/is-mobile.ts'; -import { makeGetStatus } from 'soapbox/selectors/index.ts'; +import { normalizeStatus } from 'soapbox/normalizers/index.ts'; +import { Attachment } from 'soapbox/schemas/index.ts'; +import { Status } from 'soapbox/types/entities.ts'; +import { getActualStatus } from 'soapbox/utils/status.ts'; import ImageLoader from '../image-loader.tsx'; -import type { List as ImmutableList } from 'immutable'; -import type { Attachment, Status } from 'soapbox/types/entities.ts'; - const messages = defineMessages({ close: { id: 'lightbox.close', defaultMessage: 'Close' }, expand: { id: 'lightbox.expand', defaultMessage: 'Expand' }, @@ -55,8 +55,8 @@ const containerStyle: React.CSSProperties = { }; interface IMediaModal { - media: ImmutableList; - status?: Status; + media: readonly Attachment[]; + status?: EntityTypes[Entities.STATUSES]; index: number; time?: number; onClose(): void; @@ -74,8 +74,7 @@ const MediaModal: React.FC = (props) => { const history = useHistory(); const intl = useIntl(); - const getStatus = useCallback(makeGetStatus(), []); - const actualStatus = useAppSelector((state) => getStatus(state, { id: status?.id as string })); + const actualStatus = status ? getActualStatus(status) : undefined; const [isLoaded, setIsLoaded] = useState(!!status); const [next, setNext] = useState(); @@ -83,11 +82,11 @@ const MediaModal: React.FC = (props) => { const [navigationHidden, setNavigationHidden] = useState(false); const [isFullScreen, setIsFullScreen] = useState(!status); - const hasMultipleImages = media.size > 1; + const hasMultipleImages = media.length > 1; - const handleSwipe = (index: number) => setIndex(index % media.size); - const handleNextClick = () => setIndex((getIndex() + 1) % media.size); - const handlePrevClick = () => setIndex((media.size + getIndex() - 1) % media.size); + const handleSwipe = (index: number) => setIndex(index % media.length); + const handleNextClick = () => setIndex((getIndex() + 1) % media.length); + const handlePrevClick = () => setIndex((media.length + getIndex() - 1) % media.length); const navigationHiddenClassName = navigationHidden ? 'pointer-events-none opacity-0' : ''; @@ -107,7 +106,7 @@ const MediaModal: React.FC = (props) => { }; const handleDownload = () => { - const mediaItem = hasMultipleImages ? media.get(index as number) : media.get(0); + const mediaItem = hasMultipleImages ? media[index as number] : media[0]; window.open(mediaItem?.url); }; @@ -126,8 +125,8 @@ const MediaModal: React.FC = (props) => { }; const content = media.map((attachment, i) => { - const width = (attachment.meta.getIn(['original', 'width']) || undefined) as number | undefined; - const height = (attachment.meta.getIn(['original', 'height']) || undefined) as number | undefined; + const width = 'meta' in attachment && 'original' in attachment.meta ? (attachment)?.meta?.original?.width : undefined; + const height = 'meta' in attachment && 'original' in attachment.meta ? (attachment)?.meta?.original?.height : undefined; const link = (status && ( @@ -151,7 +150,7 @@ const MediaModal: React.FC = (props) => { return (