{"version":3,"sources":["webpack:///app/javascript/opt/mastodon/app/javascript/flavours/glitch/features/account_gallery/components/media_item.tsx","webpack:///app/javascript/opt/mastodon/app/javascript/flavours/glitch/features/account_gallery/index.tsx"],"names":["MediaItem","_ref","attachment","onOpenMedia","account","useAppSelector","state","accounts","get","getIn","visible","setVisible","useState","displayMedia","loaded","setLoaded","handleImageLoad","useCallback","handleMouseEnter","e","target","HTMLVideoElement","play","handleMouseLeave","pause","currentTime","handleClick","button","ctrlKey","metaKey","preventDefault","status","description","previewUrl","fullUrl","avatarUrl","avatar_static","lang","blurhash","statusUrl","type","thumbnail","badges","length","push","_jsx","AltTextBadge","_jsxs","_Fragment","children","src","alt","title","onLoad","className","Icon","id","icon","HeadphonesIcon","x","y","style","objectPosition","includes","duration","onMouseEnter","onMouseLeave","onLoadedData","autoPlay","autoPlayGif","playsInline","loop","muted","MovieIcon","formatTime","Math","floor","VisibilityOffIcon","Blurhash","hash","classNames","dummy","useBlurhash","href","onClick","rel","messages","defineMessages","profile","defaultMessage","getAccountGallery","createSelector","accountId","timelines","ImmutableList","statuses","statusIds","items","forEach","statusId","concat","map","media","set","RemoteHint","acct","url","domain","split","undefined","TimelineHint","message","FormattedMessage","label","values","AccountGallery","_ref2","_attachments$last","multiColumn","intl","useIntl","useParams","dispatch","useAppDispatch","accounts_map","normalizeForLookup","attachments","isLoading","hasMore","blockedBy","relationships","suspended","isAccount","remote","username","hidden","getAccountHidden","maxId","last","useEffect","lookupAccount","fetchAccount","expandAccountMediaTimeline","handleLoadMore","handleOpenMedia","openModal","modalType","modalProps","options","index","findIndex","BundleColumnError","errorType","emptyMessage","LimitedAccountHint","isEmpty","forceEmptyState","Column","iconComponent","PersonIcon","heading","formatMessage","alwaysShowBackButton","ScrollableList","prepend","AccountHeader","hideTabs","alwaysPrepend","append","scrollKey","onLoadMore","bindToDocument"],"mappings":"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","file":"js/flavours/glitch/async/account_gallery-22991a9e51fe2204776a.chunk.js","sourcesContent":["import { useState, useCallback } from 'react';\n\nimport classNames from 'classnames';\n\nimport HeadphonesIcon from '@/material-icons/400-24px/headphones-fill.svg?react';\nimport MovieIcon from '@/material-icons/400-24px/movie-fill.svg?react';\nimport VisibilityOffIcon from '@/material-icons/400-24px/visibility_off.svg?react';\nimport { AltTextBadge } from 'flavours/glitch/components/alt_text_badge';\nimport { Blurhash } from 'flavours/glitch/components/blurhash';\nimport { Icon } from 'flavours/glitch/components/icon';\nimport { formatTime } from 'flavours/glitch/features/video';\nimport {\n  autoPlayGif,\n  displayMedia,\n  useBlurhash,\n} from 'flavours/glitch/initial_state';\nimport type { Status, MediaAttachment } from 'flavours/glitch/models/status';\nimport { useAppSelector } from 'flavours/glitch/store';\n\nexport const MediaItem: React.FC<{\n  attachment: MediaAttachment;\n  onOpenMedia: (arg0: MediaAttachment) => void;\n}> = ({ attachment, onOpenMedia }) => {\n  const account = useAppSelector((state) =>\n    state.accounts.get(attachment.getIn(['status', 'account']) as string),\n  );\n  const [visible, setVisible] = useState(\n    (displayMedia !== 'hide_all' &&\n      !attachment.getIn(['status', 'sensitive'])) ||\n      displayMedia === 'show_all',\n  );\n  const [loaded, setLoaded] = useState(false);\n\n  const handleImageLoad = useCallback(() => {\n    setLoaded(true);\n  }, [setLoaded]);\n\n  const handleMouseEnter = useCallback(\n    (e: React.MouseEvent<HTMLVideoElement>) => {\n      if (e.target instanceof HTMLVideoElement) {\n        void e.target.play();\n      }\n    },\n    [],\n  );\n\n  const handleMouseLeave = useCallback(\n    (e: React.MouseEvent<HTMLVideoElement>) => {\n      if (e.target instanceof HTMLVideoElement) {\n        e.target.pause();\n        e.target.currentTime = 0;\n      }\n    },\n    [],\n  );\n\n  const handleClick = useCallback(\n    (e: React.MouseEvent<HTMLAnchorElement>) => {\n      if (e.button === 0 && !(e.ctrlKey || e.metaKey)) {\n        e.preventDefault();\n\n        if (visible) {\n          onOpenMedia(attachment);\n        } else {\n          setVisible(true);\n        }\n      }\n    },\n    [attachment, visible, onOpenMedia, setVisible],\n  );\n\n  const status = attachment.get('status') as Status;\n  const description = (attachment.getIn(['translation', 'description']) ||\n    attachment.get('description')) as string | undefined;\n  const previewUrl = attachment.get('preview_url') as string;\n  const fullUrl = attachment.get('url') as string;\n  const avatarUrl = account?.avatar_static;\n  const lang = status.get('language') as string;\n  const blurhash = attachment.get('blurhash') as string;\n  const statusUrl = status.get('url') as string;\n  const type = attachment.get('type') as string;\n\n  let thumbnail;\n\n  const badges = [];\n\n  if (description && description.length > 0) {\n    badges.push(<AltTextBadge key='alt' description={description} />);\n  }\n\n  if (!visible) {\n    thumbnail = (\n      <div className='media-gallery__item__overlay'>\n        <Icon id='eye-slash' icon={VisibilityOffIcon} />\n      </div>\n    );\n  } else if (type === 'audio') {\n    thumbnail = (\n      <>\n        <img\n          src={previewUrl || avatarUrl}\n          alt={description}\n          title={description}\n          lang={lang}\n          onLoad={handleImageLoad}\n        />\n\n        <div className='media-gallery__item__overlay media-gallery__item__overlay--corner'>\n          <Icon id='music' icon={HeadphonesIcon} />\n        </div>\n      </>\n    );\n  } else if (type === 'image') {\n    const focusX = (attachment.getIn(['meta', 'focus', 'x']) || 0) as number;\n    const focusY = (attachment.getIn(['meta', 'focus', 'y']) || 0) as number;\n    const x = (focusX / 2 + 0.5) * 100;\n    const y = (focusY / -2 + 0.5) * 100;\n\n    thumbnail = (\n      <img\n        src={previewUrl}\n        alt={description}\n        title={description}\n        lang={lang}\n        style={{ objectPosition: `${x}% ${y}%` }}\n        onLoad={handleImageLoad}\n      />\n    );\n  } else if (['video', 'gifv'].includes(type)) {\n    const duration = attachment.getIn([\n      'meta',\n      'original',\n      'duration',\n    ]) as number;\n\n    thumbnail = (\n      <div className='media-gallery__gifv'>\n        <video\n          className='media-gallery__item-gifv-thumbnail'\n          aria-label={description}\n          title={description}\n          lang={lang}\n          src={fullUrl}\n          onMouseEnter={handleMouseEnter}\n          onMouseLeave={handleMouseLeave}\n          onLoadedData={handleImageLoad}\n          autoPlay={autoPlayGif}\n          playsInline\n          loop\n          muted\n        />\n\n        {type === 'video' && (\n          <div className='media-gallery__item__overlay media-gallery__item__overlay--corner'>\n            <Icon id='play' icon={MovieIcon} />\n          </div>\n        )}\n      </div>\n    );\n\n    if (type === 'gifv') {\n      badges.push(\n        <span\n          key='gif'\n          className='media-gallery__alt__label media-gallery__alt__label--non-interactive'\n        >\n          GIF\n        </span>,\n      );\n    } else {\n      badges.push(\n        <span\n          key='video'\n          className='media-gallery__alt__label media-gallery__alt__label--non-interactive'\n        >\n          {formatTime(Math.floor(duration))}\n        </span>,\n      );\n    }\n  }\n\n  return (\n    <div className='media-gallery__item media-gallery__item--square'>\n      <Blurhash\n        hash={blurhash}\n        className={classNames('media-gallery__preview', {\n          'media-gallery__preview--hidden': visible && loaded,\n        })}\n        dummy={!useBlurhash}\n      />\n\n      <a\n        className='media-gallery__item-thumbnail'\n        href={statusUrl}\n        onClick={handleClick}\n        target='_blank'\n        rel='noopener noreferrer'\n      >\n        {thumbnail}\n      </a>\n\n      {badges.length > 0 && (\n        <div className='media-gallery__item__badges'>{badges}</div>\n      )}\n    </div>\n  );\n};\n","import { useEffect, useCallback } from 'react';\n\nimport { FormattedMessage, useIntl, defineMessages } from 'react-intl';\n\nimport { useParams } from 'react-router-dom';\n\nimport { createSelector } from '@reduxjs/toolkit';\nimport type { Map as ImmutableMap } from 'immutable';\nimport { List as ImmutableList } from 'immutable';\n\nimport PersonIcon from '@/material-icons/400-24px/person.svg?react';\nimport { lookupAccount, fetchAccount } from 'flavours/glitch/actions/accounts';\nimport { openModal } from 'flavours/glitch/actions/modal';\nimport { expandAccountMediaTimeline } from 'flavours/glitch/actions/timelines';\nimport ScrollableList from 'flavours/glitch/components/scrollable_list';\nimport { TimelineHint } from 'flavours/glitch/components/timeline_hint';\nimport { AccountHeader } from 'flavours/glitch/features/account_timeline/components/account_header';\nimport { LimitedAccountHint } from 'flavours/glitch/features/account_timeline/components/limited_account_hint';\nimport BundleColumnError from 'flavours/glitch/features/ui/components/bundle_column_error';\nimport Column from 'flavours/glitch/features/ui/components/column';\nimport type { MediaAttachment } from 'flavours/glitch/models/media_attachment';\nimport { normalizeForLookup } from 'flavours/glitch/reducers/accounts_map';\nimport { getAccountHidden } from 'flavours/glitch/selectors/accounts';\nimport type { RootState } from 'flavours/glitch/store';\nimport { useAppSelector, useAppDispatch } from 'flavours/glitch/store';\n\nimport { MediaItem } from './components/media_item';\n\nconst messages = defineMessages({\n  profile: { id: 'column_header.profile', defaultMessage: 'Profile' },\n});\n\nconst getAccountGallery = createSelector(\n  [\n    (state: RootState, accountId: string) =>\n      (state.timelines as ImmutableMap<string, unknown>).getIn(\n        [`account:${accountId}:media`, 'items'],\n        ImmutableList(),\n      ) as ImmutableList<string>,\n    (state: RootState) => state.statuses,\n  ],\n  (statusIds, statuses) => {\n    let items = ImmutableList<MediaAttachment>();\n\n    statusIds.forEach((statusId) => {\n      const status = statuses.get(statusId) as\n        | ImmutableMap<string, unknown>\n        | undefined;\n\n      if (status) {\n        items = items.concat(\n          (\n            status.get('media_attachments') as ImmutableList<MediaAttachment>\n          ).map((media) => media.set('status', status)),\n        );\n      }\n    });\n\n    return items;\n  },\n);\n\ninterface Params {\n  acct?: string;\n  id?: string;\n}\n\nconst RemoteHint: React.FC<{\n  accountId: string;\n}> = ({ accountId }) => {\n  const account = useAppSelector((state) => state.accounts.get(accountId));\n  const acct = account?.acct;\n  const url = account?.url;\n  const domain = acct ? acct.split('@')[1] : undefined;\n\n  if (!url) {\n    return null;\n  }\n\n  return (\n    <TimelineHint\n      url={url}\n      message={\n        <FormattedMessage\n          id='hints.profiles.posts_may_be_missing'\n          defaultMessage='Some posts from this profile may be missing.'\n        />\n      }\n      label={\n        <FormattedMessage\n          id='hints.profiles.see_more_posts'\n          defaultMessage='See more posts on {domain}'\n          values={{ domain: <strong>{domain}</strong> }}\n        />\n      }\n    />\n  );\n};\n\nexport const AccountGallery: React.FC<{\n  multiColumn: boolean;\n}> = ({ multiColumn }) => {\n  const intl = useIntl();\n  const { acct, id } = useParams<Params>();\n  const dispatch = useAppDispatch();\n  const accountId = useAppSelector(\n    (state) =>\n      id ??\n      (state.accounts_map.get(normalizeForLookup(acct)) as string | undefined),\n  );\n  const attachments = useAppSelector((state) =>\n    accountId\n      ? getAccountGallery(state, accountId)\n      : ImmutableList<MediaAttachment>(),\n  );\n  const isLoading = useAppSelector((state) =>\n    (state.timelines as ImmutableMap<string, unknown>).getIn([\n      `account:${accountId}:media`,\n      'isLoading',\n    ]),\n  );\n  const hasMore = useAppSelector((state) =>\n    (state.timelines as ImmutableMap<string, unknown>).getIn([\n      `account:${accountId}:media`,\n      'hasMore',\n    ]),\n  );\n  const account = useAppSelector((state) =>\n    accountId ? state.accounts.get(accountId) : undefined,\n  );\n  const blockedBy = useAppSelector(\n    (state) =>\n      state.relationships.getIn([accountId, 'blocked_by'], false) as boolean,\n  );\n  const suspended = useAppSelector(\n    (state) => state.accounts.getIn([accountId, 'suspended'], false) as boolean,\n  );\n  const isAccount = !!account;\n  const remote = account?.acct !== account?.username;\n  const hidden = useAppSelector((state) =>\n    accountId ? getAccountHidden(state, accountId) : false,\n  );\n  const maxId = attachments.last()?.getIn(['status', 'id']) as\n    | string\n    | undefined;\n\n  useEffect(() => {\n    if (!accountId) {\n      dispatch(lookupAccount(acct));\n    }\n  }, [dispatch, accountId, acct]);\n\n  useEffect(() => {\n    if (accountId && !isAccount) {\n      dispatch(fetchAccount(accountId));\n    }\n\n    if (accountId && isAccount) {\n      void dispatch(expandAccountMediaTimeline(accountId));\n    }\n  }, [dispatch, accountId, isAccount]);\n\n  const handleLoadMore = useCallback(() => {\n    if (maxId) {\n      void dispatch(expandAccountMediaTimeline(accountId, { maxId }));\n    }\n  }, [dispatch, accountId, maxId]);\n\n  const handleOpenMedia = useCallback(\n    (attachment: MediaAttachment) => {\n      const statusId = attachment.getIn(['status', 'id']);\n      const lang = attachment.getIn(['status', 'language']);\n\n      if (attachment.get('type') === 'video') {\n        dispatch(\n          openModal({\n            modalType: 'VIDEO',\n            modalProps: {\n              media: attachment,\n              statusId,\n              lang,\n              options: { autoPlay: true },\n            },\n          }),\n        );\n      } else if (attachment.get('type') === 'audio') {\n        dispatch(\n          openModal({\n            modalType: 'AUDIO',\n            modalProps: {\n              media: attachment,\n              statusId,\n              lang,\n              options: { autoPlay: true },\n            },\n          }),\n        );\n      } else {\n        const media = attachment.getIn([\n          'status',\n          'media_attachments',\n        ]) as ImmutableList<MediaAttachment>;\n        const index = media.findIndex(\n          (x) => x.get('id') === attachment.get('id'),\n        );\n\n        dispatch(\n          openModal({\n            modalType: 'MEDIA',\n            modalProps: { media, index, statusId, lang },\n          }),\n        );\n      }\n    },\n    [dispatch],\n  );\n\n  if (accountId && !isAccount) {\n    return <BundleColumnError multiColumn={multiColumn} errorType='routing' />;\n  }\n\n  let emptyMessage;\n\n  if (accountId) {\n    if (suspended) {\n      emptyMessage = (\n        <FormattedMessage\n          id='empty_column.account_suspended'\n          defaultMessage='Account suspended'\n        />\n      );\n    } else if (hidden) {\n      emptyMessage = <LimitedAccountHint accountId={accountId} />;\n    } else if (blockedBy) {\n      emptyMessage = (\n        <FormattedMessage\n          id='empty_column.account_unavailable'\n          defaultMessage='Profile unavailable'\n        />\n      );\n    } else if (remote && attachments.isEmpty()) {\n      emptyMessage = <RemoteHint accountId={accountId} />;\n    } else {\n      emptyMessage = (\n        <FormattedMessage\n          id='empty_column.account_timeline'\n          defaultMessage='No posts found'\n        />\n      );\n    }\n  }\n\n  const forceEmptyState = suspended || blockedBy || hidden;\n\n  return (\n    <Column\n      icon='user-circle'\n      iconComponent={PersonIcon}\n      heading={intl.formatMessage(messages.profile)}\n      alwaysShowBackButton\n    >\n      <ScrollableList\n        className='account-gallery__container'\n        prepend={\n          accountId && (\n            <AccountHeader accountId={accountId} hideTabs={forceEmptyState} />\n          )\n        }\n        alwaysPrepend\n        append={remote && accountId && <RemoteHint accountId={accountId} />}\n        scrollKey='account_gallery'\n        isLoading={isLoading}\n        hasMore={!forceEmptyState && hasMore}\n        onLoadMore={handleLoadMore}\n        emptyMessage={emptyMessage}\n        bindToDocument={!multiColumn}\n      >\n        {attachments.map((attachment) => (\n          <MediaItem\n            key={attachment.get('id') as string}\n            attachment={attachment}\n            onOpenMedia={handleOpenMedia}\n          />\n        ))}\n      </ScrollableList>\n    </Column>\n  );\n};\n\n// eslint-disable-next-line import/no-default-export\nexport default AccountGallery;\n"],"sourceRoot":""}