{"version":3,"sources":["webpack:///./app/javascript/mastodon/features/getting_started/components/announcements.jsx","webpack:///./app/javascript/mastodon/features/getting_started/containers/announcements_container.js","webpack:///./app/javascript/mastodon/features/home_timeline/components/column_settings.tsx","webpack:///./app/javascript/mastodon/features/home_timeline/components/critical_update_banner.tsx","webpack:///./app/javascript/mastodon/features/home_timeline/components/explore_prompt.tsx","webpack:///./app/javascript/mastodon/features/home_timeline/index.jsx"],"names":["messages","defineMessages","close","id","defaultMessage","previous","next","Content","ImmutablePureComponent","constructor","arguments","setRef","c","this","node","onMentionClick","mention","e","context","router","button","ctrlKey","metaKey","preventDefault","history","push","get","onHashtagClick","hashtag","replace","onStatusClick","status","getIn","handleMouseEnter","_ref","currentTarget","autoPlayGif","emojis","querySelectorAll","i","length","emoji","src","getAttribute","handleMouseLeave","_ref2","componentDidMount","_updateLinks","componentDidUpdate","links","link","classList","contains","add","props","announcement","find","item","href","addEventListener","bind","setAttribute","textContent","previousSibling","text","render","_jsx","className","ref","dangerouslySetInnerHTML","__html","onMouseEnter","onMouseLeave","contextTypes","PropTypes","object","propTypes","ImmutablePropTypes","map","isRequired","Emoji","PureComponent","emojiMap","hovered","unicodeMapping","filename","shortCode","title","_jsx2","draggable","alt","assetHost","Reaction","state","handleClick","reaction","announcementId","addReaction","removeReaction","setState","classNames","active","onClick","style","AnimatedNumber","value","string","func","ReactionsBar","handleEmojiPick","data","native","willEnter","scale","reduceMotion","willLeave","spring","stiffness","damping","reactions","visibleReactions","filter","x","styles","key","toArray","TransitionMotion","items","isEmpty","_ref3","transform","position","size","EmojiPickerDropdown","onPickEmoji","Icon","list","Announcement","unread","selected","startsAt","Date","endsAt","now","hasTimeRange","skipYear","getFullYear","skipEndDate","getDate","getMonth","skipTime","FormattedMessage","FormattedDate","hour12","year","undefined","month","day","hour","minute","intl","bool","Announcements","index","handleChangeIndex","announcements","handleNextClick","handlePrevClick","getDerivedStateFromProps","_markAnnouncementAsRead","dismissAnnouncement","mascot","elephantUIPlane","ReactSwipeableViews","animateHeight","animateTransitions","onChangeIndex","idx","disabled","disableSwiping","reverse","IconButton","formatMessage","icon","injectIntl","customEmojiMap","createSelector","reduce","set","ImmutableMap","connect","dispatch","name","ColumnSettings","settings","useAppSelector","useAppDispatch","onChange","useCallback","checked","changeSetting","SettingToggle","prefix","settingPath","label","CriticalUpdateBanner","ExplorePrompt","DismissableBanner","background","Link","to","show_announcements","hide_announcements","getHomeFeedSpeed","ImmutableList","statusIds","pendingStatusIds","statusMap","statuses","me","take","gap","newest","datetimes","oldest","min","max","homeTooSlow","isLoading","isPartial","speed","HomeTimeline","handlePin","columnId","removeColumn","addColumn","handleMove","dir","moveColumn","handleHeaderClick","column","scrollTop","handleLoadMore","maxId","expandHomeTimeline","handleToggleAnnouncementsClick","stopPropagation","toggleShowAnnouncements","setTimeout","fetchAnnouncements","_checkIfReloadNeeded","prevProps","componentWillUnmount","_stopPolling","wasPartial","polling","setInterval","clearInterval","hasUnread","multiColumn","tooSlow","hasAnnouncements","unreadAnnouncements","showAnnouncements","pinned","signedIn","identity","banners","announcementsButton","type","IconWithBadge","count","criticalUpdatesPending","_jsxs","Column","bindToDocument","children","ColumnHeader","onPin","onMove","extraButton","appendContent","AnnouncementsContainer","StatusListContainer","prepend","alwaysPrepend","trackScroll","scrollKey","onLoadMore","timelineId","emptyMessage","NotSignedInIndicator","Helmet","content"],"mappings":"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","file":"js/features/home_timeline-a687c1609488b37ab9ae.chunk.js","sourcesContent":["import PropTypes from 'prop-types';\nimport { PureComponent } from 'react';\n\nimport { defineMessages, injectIntl, FormattedMessage, FormattedDate } from 'react-intl';\n\nimport classNames from 'classnames';\n\nimport ImmutablePropTypes from 'react-immutable-proptypes';\nimport ImmutablePureComponent from 'react-immutable-pure-component';\n\nimport TransitionMotion from 'react-motion/lib/TransitionMotion';\nimport spring from 'react-motion/lib/spring';\nimport ReactSwipeableViews from 'react-swipeable-views';\n\nimport elephantUIPlane from 'mastodon/../images/elephant_ui_plane.svg';\nimport { AnimatedNumber } from 'mastodon/components/animated_number';\nimport { Icon } from 'mastodon/components/icon';\nimport { IconButton } from 'mastodon/components/icon_button';\nimport EmojiPickerDropdown from 'mastodon/features/compose/containers/emoji_picker_dropdown_container';\nimport unicodeMapping from 'mastodon/features/emoji/emoji_unicode_mapping_light';\nimport { autoPlayGif, reduceMotion, disableSwiping, mascot } from 'mastodon/initial_state';\nimport { assetHost } from 'mastodon/utils/config';\n\nconst messages = defineMessages({\n close: { id: 'lightbox.close', defaultMessage: 'Close' },\n previous: { id: 'lightbox.previous', defaultMessage: 'Previous' },\n next: { id: 'lightbox.next', defaultMessage: 'Next' },\n});\n\nclass Content extends ImmutablePureComponent {\n\n static contextTypes = {\n router: PropTypes.object,\n };\n\n static propTypes = {\n announcement: ImmutablePropTypes.map.isRequired,\n };\n\n setRef = c => {\n this.node = c;\n };\n\n componentDidMount () {\n this._updateLinks();\n }\n\n componentDidUpdate () {\n this._updateLinks();\n }\n\n _updateLinks () {\n const node = this.node;\n\n if (!node) {\n return;\n }\n\n const links = node.querySelectorAll('a');\n\n for (var i = 0; i < links.length; ++i) {\n let link = links[i];\n\n if (link.classList.contains('status-link')) {\n continue;\n }\n\n link.classList.add('status-link');\n\n let mention = this.props.announcement.get('mentions').find(item => link.href === item.get('url'));\n\n if (mention) {\n link.addEventListener('click', this.onMentionClick.bind(this, mention), false);\n link.setAttribute('title', mention.get('acct'));\n } else if (link.textContent[0] === '#' || (link.previousSibling && link.previousSibling.textContent && link.previousSibling.textContent[link.previousSibling.textContent.length - 1] === '#')) {\n link.addEventListener('click', this.onHashtagClick.bind(this, link.text), false);\n } else {\n let status = this.props.announcement.get('statuses').find(item => link.href === item.get('url'));\n if (status) {\n link.addEventListener('click', this.onStatusClick.bind(this, status), false);\n }\n link.setAttribute('title', link.href);\n link.classList.add('unhandled-link');\n }\n\n link.setAttribute('target', '_blank');\n link.setAttribute('rel', 'noopener noreferrer');\n }\n }\n\n onMentionClick = (mention, e) => {\n if (this.context.router && e.button === 0 && !(e.ctrlKey || e.metaKey)) {\n e.preventDefault();\n this.context.router.history.push(`/@${mention.get('acct')}`);\n }\n };\n\n onHashtagClick = (hashtag, e) => {\n hashtag = hashtag.replace(/^#/, '');\n\n if (this.context.router && e.button === 0 && !(e.ctrlKey || e.metaKey)) {\n e.preventDefault();\n this.context.router.history.push(`/tags/${hashtag}`);\n }\n };\n\n onStatusClick = (status, e) => {\n if (this.context.router && e.button === 0 && !(e.ctrlKey || e.metaKey)) {\n e.preventDefault();\n this.context.router.history.push(`/@${status.getIn(['account', 'acct'])}/${status.get('id')}`);\n }\n };\n\n handleMouseEnter = ({ currentTarget }) => {\n if (autoPlayGif) {\n return;\n }\n\n const emojis = currentTarget.querySelectorAll('.custom-emoji');\n\n for (var i = 0; i < emojis.length; i++) {\n let emoji = emojis[i];\n emoji.src = emoji.getAttribute('data-original');\n }\n };\n\n handleMouseLeave = ({ currentTarget }) => {\n if (autoPlayGif) {\n return;\n }\n\n const emojis = currentTarget.querySelectorAll('.custom-emoji');\n\n for (var i = 0; i < emojis.length; i++) {\n let emoji = emojis[i];\n emoji.src = emoji.getAttribute('data-static');\n }\n };\n\n render () {\n const { announcement } = this.props;\n\n return (\n <div\n className='announcements__item__content translate'\n ref={this.setRef}\n dangerouslySetInnerHTML={{ __html: announcement.get('contentHtml') }}\n onMouseEnter={this.handleMouseEnter}\n onMouseLeave={this.handleMouseLeave}\n />\n );\n }\n\n}\n\nclass Emoji extends PureComponent {\n\n static propTypes = {\n emoji: PropTypes.string.isRequired,\n emojiMap: ImmutablePropTypes.map.isRequired,\n hovered: PropTypes.bool.isRequired,\n };\n\n render () {\n const { emoji, emojiMap, hovered } = this.props;\n\n if (unicodeMapping[emoji]) {\n const { filename, shortCode } = unicodeMapping[this.props.emoji];\n const title = shortCode ? `:${shortCode}:` : '';\n\n return (\n <img\n draggable='false'\n className='emojione'\n alt={emoji}\n title={title}\n src={`${assetHost}/emoji/${filename}.svg`}\n />\n );\n } else if (emojiMap.get(emoji)) {\n const filename = (autoPlayGif || hovered) ? emojiMap.getIn([emoji, 'url']) : emojiMap.getIn([emoji, 'static_url']);\n const shortCode = `:${emoji}:`;\n\n return (\n <img\n draggable='false'\n className='emojione custom-emoji'\n alt={shortCode}\n title={shortCode}\n src={filename}\n />\n );\n } else {\n return null;\n }\n }\n\n}\n\nclass Reaction extends ImmutablePureComponent {\n\n static propTypes = {\n announcementId: PropTypes.string.isRequired,\n reaction: ImmutablePropTypes.map.isRequired,\n addReaction: PropTypes.func.isRequired,\n removeReaction: PropTypes.func.isRequired,\n emojiMap: ImmutablePropTypes.map.isRequired,\n style: PropTypes.object,\n };\n\n state = {\n hovered: false,\n };\n\n handleClick = () => {\n const { reaction, announcementId, addReaction, removeReaction } = this.props;\n\n if (reaction.get('me')) {\n removeReaction(announcementId, reaction.get('name'));\n } else {\n addReaction(announcementId, reaction.get('name'));\n }\n };\n\n handleMouseEnter = () => this.setState({ hovered: true });\n\n handleMouseLeave = () => this.setState({ hovered: false });\n\n render () {\n const { reaction } = this.props;\n\n let shortCode = reaction.get('name');\n\n if (unicodeMapping[shortCode]) {\n shortCode = unicodeMapping[shortCode].shortCode;\n }\n\n return (\n <button className={classNames('reactions-bar__item', { active: reaction.get('me') })} onClick={this.handleClick} onMouseEnter={this.handleMouseEnter} onMouseLeave={this.handleMouseLeave} title={`:${shortCode}:`} style={this.props.style}>\n <span className='reactions-bar__item__emoji'><Emoji hovered={this.state.hovered} emoji={reaction.get('name')} emojiMap={this.props.emojiMap} /></span>\n <span className='reactions-bar__item__count'><AnimatedNumber value={reaction.get('count')} /></span>\n </button>\n );\n }\n\n}\n\nclass ReactionsBar extends ImmutablePureComponent {\n\n static propTypes = {\n announcementId: PropTypes.string.isRequired,\n reactions: ImmutablePropTypes.list.isRequired,\n addReaction: PropTypes.func.isRequired,\n removeReaction: PropTypes.func.isRequired,\n emojiMap: ImmutablePropTypes.map.isRequired,\n };\n\n handleEmojiPick = data => {\n const { addReaction, announcementId } = this.props;\n addReaction(announcementId, data.native.replace(/:/g, ''));\n };\n\n willEnter () {\n return { scale: reduceMotion ? 1 : 0 };\n }\n\n willLeave () {\n return { scale: reduceMotion ? 0 : spring(0, { stiffness: 170, damping: 26 }) };\n }\n\n render () {\n const { reactions } = this.props;\n const visibleReactions = reactions.filter(x => x.get('count') > 0);\n\n const styles = visibleReactions.map(reaction => ({\n key: reaction.get('name'),\n data: reaction,\n style: { scale: reduceMotion ? 1 : spring(1, { stiffness: 150, damping: 13 }) },\n })).toArray();\n\n return (\n <TransitionMotion styles={styles} willEnter={this.willEnter} willLeave={this.willLeave}>\n {items => (\n <div className={classNames('reactions-bar', { 'reactions-bar--empty': visibleReactions.isEmpty() })}>\n {items.map(({ key, data, style }) => (\n <Reaction\n key={key}\n reaction={data}\n style={{ transform: `scale(${style.scale})`, position: style.scale < 0.5 ? 'absolute' : 'static' }}\n announcementId={this.props.announcementId}\n addReaction={this.props.addReaction}\n removeReaction={this.props.removeReaction}\n emojiMap={this.props.emojiMap}\n />\n ))}\n\n {visibleReactions.size < 8 && <EmojiPickerDropdown onPickEmoji={this.handleEmojiPick} button={<Icon id='plus' />} />}\n </div>\n )}\n </TransitionMotion>\n );\n }\n\n}\n\nclass Announcement extends ImmutablePureComponent {\n\n static propTypes = {\n announcement: ImmutablePropTypes.map.isRequired,\n emojiMap: ImmutablePropTypes.map.isRequired,\n addReaction: PropTypes.func.isRequired,\n removeReaction: PropTypes.func.isRequired,\n intl: PropTypes.object.isRequired,\n selected: PropTypes.bool,\n };\n\n state = {\n unread: !this.props.announcement.get('read'),\n };\n\n componentDidUpdate () {\n const { selected, announcement } = this.props;\n if (!selected && this.state.unread !== !announcement.get('read')) {\n this.setState({ unread: !announcement.get('read') });\n }\n }\n\n render () {\n const { announcement } = this.props;\n const { unread } = this.state;\n const startsAt = announcement.get('starts_at') && new Date(announcement.get('starts_at'));\n const endsAt = announcement.get('ends_at') && new Date(announcement.get('ends_at'));\n const now = new Date();\n const hasTimeRange = startsAt && endsAt;\n const skipYear = hasTimeRange && startsAt.getFullYear() === endsAt.getFullYear() && endsAt.getFullYear() === now.getFullYear();\n const skipEndDate = hasTimeRange && startsAt.getDate() === endsAt.getDate() && startsAt.getMonth() === endsAt.getMonth() && startsAt.getFullYear() === endsAt.getFullYear();\n const skipTime = announcement.get('all_day');\n\n return (\n <div className='announcements__item'>\n <strong className='announcements__item__range'>\n <FormattedMessage id='announcement.announcement' defaultMessage='Announcement' />\n {hasTimeRange && <span> · <FormattedDate value={startsAt} hour12={false} year={(skipYear || startsAt.getFullYear() === now.getFullYear()) ? undefined : 'numeric'} month='short' day='2-digit' hour={skipTime ? undefined : '2-digit'} minute={skipTime ? undefined : '2-digit'} /> - <FormattedDate value={endsAt} hour12={false} year={(skipYear || endsAt.getFullYear() === now.getFullYear()) ? undefined : 'numeric'} month={skipEndDate ? undefined : 'short'} day={skipEndDate ? undefined : '2-digit'} hour={skipTime ? undefined : '2-digit'} minute={skipTime ? undefined : '2-digit'} /></span>}\n </strong>\n\n <Content announcement={announcement} />\n\n <ReactionsBar\n reactions={announcement.get('reactions')}\n announcementId={announcement.get('id')}\n addReaction={this.props.addReaction}\n removeReaction={this.props.removeReaction}\n emojiMap={this.props.emojiMap}\n />\n\n {unread && <span className='announcements__item__unread' />}\n </div>\n );\n }\n\n}\n\nclass Announcements extends ImmutablePureComponent {\n\n static propTypes = {\n announcements: ImmutablePropTypes.list,\n emojiMap: ImmutablePropTypes.map.isRequired,\n dismissAnnouncement: PropTypes.func.isRequired,\n addReaction: PropTypes.func.isRequired,\n removeReaction: PropTypes.func.isRequired,\n intl: PropTypes.object.isRequired,\n };\n\n state = {\n index: 0,\n };\n\n static getDerivedStateFromProps(props, state) {\n if (props.announcements.size > 0 && state.index >= props.announcements.size) {\n return { index: props.announcements.size - 1 };\n } else {\n return null;\n }\n }\n\n componentDidMount () {\n this._markAnnouncementAsRead();\n }\n\n componentDidUpdate () {\n this._markAnnouncementAsRead();\n }\n\n _markAnnouncementAsRead () {\n const { dismissAnnouncement, announcements } = this.props;\n const { index } = this.state;\n const announcement = announcements.get(announcements.size - 1 - index);\n if (!announcement.get('read')) dismissAnnouncement(announcement.get('id'));\n }\n\n handleChangeIndex = index => {\n this.setState({ index: index % this.props.announcements.size });\n };\n\n handleNextClick = () => {\n this.setState({ index: (this.state.index + 1) % this.props.announcements.size });\n };\n\n handlePrevClick = () => {\n this.setState({ index: (this.props.announcements.size + this.state.index - 1) % this.props.announcements.size });\n };\n\n render () {\n const { announcements, intl } = this.props;\n const { index } = this.state;\n\n if (announcements.isEmpty()) {\n return null;\n }\n\n return (\n <div className='announcements'>\n <img className='announcements__mastodon' alt='' draggable='false' src={mascot || elephantUIPlane} />\n\n <div className='announcements__container'>\n <ReactSwipeableViews animateHeight animateTransitions={!reduceMotion} index={index} onChangeIndex={this.handleChangeIndex}>\n {announcements.map((announcement, idx) => (\n <Announcement\n key={announcement.get('id')}\n announcement={announcement}\n emojiMap={this.props.emojiMap}\n addReaction={this.props.addReaction}\n removeReaction={this.props.removeReaction}\n intl={intl}\n selected={index === idx}\n disabled={disableSwiping}\n />\n )).reverse()}\n </ReactSwipeableViews>\n\n {announcements.size > 1 && (\n <div className='announcements__pagination'>\n <IconButton disabled={announcements.size === 1} title={intl.formatMessage(messages.previous)} icon='chevron-left' onClick={this.handlePrevClick} size={13} />\n <span>{index + 1} / {announcements.size}</span>\n <IconButton disabled={announcements.size === 1} title={intl.formatMessage(messages.next)} icon='chevron-right' onClick={this.handleNextClick} size={13} />\n </div>\n )}\n </div>\n </div>\n );\n }\n\n}\n\nexport default injectIntl(Announcements);\n","import { Map as ImmutableMap } from 'immutable';\nimport { connect } from 'react-redux';\nimport { createSelector } from 'reselect';\n\nimport { addReaction, removeReaction, dismissAnnouncement } from 'mastodon/actions/announcements';\n\nimport Announcements from '../components/announcements';\n\nconst customEmojiMap = createSelector([state => state.get('custom_emojis')], items => items.reduce((map, emoji) => map.set(emoji.get('shortcode'), emoji), ImmutableMap()));\n\nconst mapStateToProps = state => ({\n announcements: state.getIn(['announcements', 'items']),\n emojiMap: customEmojiMap(state),\n});\n\nconst mapDispatchToProps = dispatch => ({\n dismissAnnouncement: id => dispatch(dismissAnnouncement(id)),\n addReaction: (id, name) => dispatch(addReaction(id, name)),\n removeReaction: (id, name) => dispatch(removeReaction(id, name)),\n});\n\nexport default connect(mapStateToProps, mapDispatchToProps)(Announcements);\n","/* eslint-disable @typescript-eslint/no-unsafe-call,\n @typescript-eslint/no-unsafe-return,\n @typescript-eslint/no-unsafe-assignment,\n @typescript-eslint/no-unsafe-member-access\n -- the settings store is not yet typed */\nimport { useCallback } from 'react';\n\nimport { FormattedMessage } from 'react-intl';\n\nimport { useAppSelector, useAppDispatch } from 'mastodon/store';\n\nimport { changeSetting } from '../../../actions/settings';\nimport SettingToggle from '../../notifications/components/setting_toggle';\n\nexport const ColumnSettings: React.FC = () => {\n const settings = useAppSelector((state) => state.settings.get('home'));\n\n const dispatch = useAppDispatch();\n const onChange = useCallback(\n (key: string, checked: boolean) => {\n dispatch(changeSetting(['home', ...key], checked));\n },\n [dispatch],\n );\n\n return (\n <div>\n <span className='column-settings__section'>\n <FormattedMessage\n id='home.column_settings.basic'\n defaultMessage='Basic'\n />\n </span>\n\n <div className='column-settings__row'>\n <SettingToggle\n prefix='home_timeline'\n settings={settings}\n settingPath={['shows', 'reblog']}\n onChange={onChange}\n label={\n <FormattedMessage\n id='home.column_settings.show_reblogs'\n defaultMessage='Show boosts'\n />\n }\n />\n </div>\n\n <div className='column-settings__row'>\n <SettingToggle\n prefix='home_timeline'\n settings={settings}\n settingPath={['shows', 'reply']}\n onChange={onChange}\n label={\n <FormattedMessage\n id='home.column_settings.show_replies'\n defaultMessage='Show replies'\n />\n }\n />\n </div>\n </div>\n );\n};\n","import { FormattedMessage } from 'react-intl';\n\nexport const CriticalUpdateBanner = () => (\n <div className='warning-banner'>\n <div className='warning-banner__message'>\n <h1>\n <FormattedMessage\n id='home.pending_critical_update.title'\n defaultMessage='Critical security update available!'\n />\n </h1>\n <p>\n <FormattedMessage\n id='home.pending_critical_update.body'\n defaultMessage='Please update your Mastodon server as soon as possible!'\n />{' '}\n <a href='/admin/software_updates'>\n <FormattedMessage\n id='home.pending_critical_update.link'\n defaultMessage='See updates'\n />\n </a>\n </p>\n </div>\n </div>\n);\n","import { FormattedMessage } from 'react-intl';\n\nimport { Link } from 'react-router-dom';\n\nimport background from 'mastodon/../images/friends-cropped.png';\nimport { DismissableBanner } from 'mastodon/components/dismissable_banner';\n\nexport const ExplorePrompt = () => (\n <DismissableBanner id='home.explore_prompt'>\n <img\n src={background}\n alt=''\n className='dismissable-banner__background-image'\n />\n\n <h1>\n <FormattedMessage\n id='home.explore_prompt.title'\n defaultMessage='This is your home base within Mastodon.'\n />\n </h1>\n <p>\n <FormattedMessage\n id='home.explore_prompt.body'\n defaultMessage=\"Your home feed will have a mix of posts from the hashtags you've chosen to follow, the people you've chosen to follow, and the posts they boost. If that feels too quiet, you may want to:\"\n />\n </p>\n\n <div className='dismissable-banner__message__wrapper'>\n <div className='dismissable-banner__message__actions'>\n <Link to='/explore' className='button'>\n <FormattedMessage\n id='home.actions.go_to_explore'\n defaultMessage=\"See what's trending\"\n />\n </Link>\n <Link to='/explore/suggestions' className='button button-tertiary'>\n <FormattedMessage\n id='home.actions.go_to_suggestions'\n defaultMessage='Find people to follow'\n />\n </Link>\n </div>\n </div>\n </DismissableBanner>\n);\n","import PropTypes from 'prop-types';\nimport { PureComponent } from 'react';\n\nimport { defineMessages, injectIntl, FormattedMessage } from 'react-intl';\n\nimport classNames from 'classnames';\nimport { Helmet } from 'react-helmet';\n\nimport { List as ImmutableList } from 'immutable';\nimport { connect } from 'react-redux';\nimport { createSelector } from 'reselect';\n\nimport { fetchAnnouncements, toggleShowAnnouncements } from 'mastodon/actions/announcements';\nimport { IconWithBadge } from 'mastodon/components/icon_with_badge';\nimport { NotSignedInIndicator } from 'mastodon/components/not_signed_in_indicator';\nimport AnnouncementsContainer from 'mastodon/features/getting_started/containers/announcements_container';\nimport { me, criticalUpdatesPending } from 'mastodon/initial_state';\n\nimport { addColumn, removeColumn, moveColumn } from '../../actions/columns';\nimport { expandHomeTimeline } from '../../actions/timelines';\nimport Column from '../../components/column';\nimport ColumnHeader from '../../components/column_header';\nimport StatusListContainer from '../ui/containers/status_list_container';\n\nimport { ColumnSettings } from './components/column_settings';\nimport { CriticalUpdateBanner } from './components/critical_update_banner';\nimport { ExplorePrompt } from './components/explore_prompt';\n\nconst messages = defineMessages({\n title: { id: 'column.home', defaultMessage: 'Home' },\n show_announcements: { id: 'home.show_announcements', defaultMessage: 'Show announcements' },\n hide_announcements: { id: 'home.hide_announcements', defaultMessage: 'Hide announcements' },\n});\n\nconst getHomeFeedSpeed = createSelector([\n state => state.getIn(['timelines', 'home', 'items'], ImmutableList()),\n state => state.getIn(['timelines', 'home', 'pendingItems'], ImmutableList()),\n state => state.get('statuses'),\n], (statusIds, pendingStatusIds, statusMap) => {\n const recentStatusIds = pendingStatusIds.size > 0 ? pendingStatusIds : statusIds;\n const statuses = recentStatusIds.filter(id => id !== null).map(id => statusMap.get(id)).filter(status => status?.get('account') !== me).take(20);\n\n if (statuses.isEmpty()) {\n return {\n gap: 0,\n newest: new Date(0),\n };\n }\n\n const datetimes = statuses.map(status => status.get('created_at', 0));\n const oldest = new Date(datetimes.min());\n const newest = new Date(datetimes.max());\n const averageGap = (newest - oldest) / (1000 * (statuses.size + 1)); // Average gap between posts on first page in seconds\n\n return {\n gap: averageGap,\n newest,\n };\n});\n\nconst homeTooSlow = createSelector([\n state => state.getIn(['timelines', 'home', 'isLoading']),\n state => state.getIn(['timelines', 'home', 'isPartial']),\n getHomeFeedSpeed,\n], (isLoading, isPartial, speed) =>\n !isLoading && !isPartial // Only if the home feed has finished loading\n && (\n (speed.gap > (30 * 60) // If the average gap between posts is more than 30 minutes\n || (Date.now() - speed.newest) > (1000 * 3600)) // If the most recent post is from over an hour ago\n )\n);\n\nconst mapStateToProps = state => ({\n hasUnread: state.getIn(['timelines', 'home', 'unread']) > 0,\n isPartial: state.getIn(['timelines', 'home', 'isPartial']),\n hasAnnouncements: !state.getIn(['announcements', 'items']).isEmpty(),\n unreadAnnouncements: state.getIn(['announcements', 'items']).count(item => !item.get('read')),\n showAnnouncements: state.getIn(['announcements', 'show']),\n tooSlow: homeTooSlow(state),\n});\n\nclass HomeTimeline extends PureComponent {\n\n static contextTypes = {\n identity: PropTypes.object,\n };\n\n static propTypes = {\n dispatch: PropTypes.func.isRequired,\n intl: PropTypes.object.isRequired,\n hasUnread: PropTypes.bool,\n isPartial: PropTypes.bool,\n columnId: PropTypes.string,\n multiColumn: PropTypes.bool,\n hasAnnouncements: PropTypes.bool,\n unreadAnnouncements: PropTypes.number,\n showAnnouncements: PropTypes.bool,\n tooSlow: PropTypes.bool,\n };\n\n handlePin = () => {\n const { columnId, dispatch } = this.props;\n\n if (columnId) {\n dispatch(removeColumn(columnId));\n } else {\n dispatch(addColumn('HOME', {}));\n }\n };\n\n handleMove = (dir) => {\n const { columnId, dispatch } = this.props;\n dispatch(moveColumn(columnId, dir));\n };\n\n handleHeaderClick = () => {\n this.column.scrollTop();\n };\n\n setRef = c => {\n this.column = c;\n };\n\n handleLoadMore = maxId => {\n this.props.dispatch(expandHomeTimeline({ maxId }));\n };\n\n componentDidMount () {\n setTimeout(() => this.props.dispatch(fetchAnnouncements()), 700);\n this._checkIfReloadNeeded(false, this.props.isPartial);\n }\n\n componentDidUpdate (prevProps) {\n this._checkIfReloadNeeded(prevProps.isPartial, this.props.isPartial);\n }\n\n componentWillUnmount () {\n this._stopPolling();\n }\n\n _checkIfReloadNeeded (wasPartial, isPartial) {\n const { dispatch } = this.props;\n\n if (wasPartial === isPartial) {\n return;\n } else if (!wasPartial && isPartial) {\n this.polling = setInterval(() => {\n dispatch(expandHomeTimeline());\n }, 3000);\n } else if (wasPartial && !isPartial) {\n this._stopPolling();\n }\n }\n\n _stopPolling () {\n if (this.polling) {\n clearInterval(this.polling);\n this.polling = null;\n }\n }\n\n handleToggleAnnouncementsClick = (e) => {\n e.stopPropagation();\n this.props.dispatch(toggleShowAnnouncements());\n };\n\n render () {\n const { intl, hasUnread, columnId, multiColumn, tooSlow, hasAnnouncements, unreadAnnouncements, showAnnouncements } = this.props;\n const pinned = !!columnId;\n const { signedIn } = this.context.identity;\n const banners = [];\n\n let announcementsButton;\n\n if (hasAnnouncements) {\n announcementsButton = (\n <button\n type='button'\n className={classNames('column-header__button', { 'active': showAnnouncements })}\n title={intl.formatMessage(showAnnouncements ? messages.hide_announcements : messages.show_announcements)}\n aria-label={intl.formatMessage(showAnnouncements ? messages.hide_announcements : messages.show_announcements)}\n onClick={this.handleToggleAnnouncementsClick}\n >\n <IconWithBadge id='bullhorn' count={unreadAnnouncements} />\n </button>\n );\n }\n\n if (criticalUpdatesPending) {\n banners.push(<CriticalUpdateBanner key='critical-update-banner' />);\n }\n\n if (tooSlow) {\n banners.push(<ExplorePrompt key='explore-prompt' />);\n }\n\n return (\n <Column bindToDocument={!multiColumn} ref={this.setRef} label={intl.formatMessage(messages.title)}>\n <ColumnHeader\n icon='home'\n active={hasUnread}\n title={intl.formatMessage(messages.title)}\n onPin={this.handlePin}\n onMove={this.handleMove}\n onClick={this.handleHeaderClick}\n pinned={pinned}\n multiColumn={multiColumn}\n extraButton={announcementsButton}\n appendContent={hasAnnouncements && showAnnouncements && <AnnouncementsContainer />}\n >\n <ColumnSettings />\n </ColumnHeader>\n\n {signedIn ? (\n <StatusListContainer\n prepend={banners}\n alwaysPrepend\n trackScroll={!pinned}\n scrollKey={`home_timeline-${columnId}`}\n onLoadMore={this.handleLoadMore}\n timelineId='home'\n emptyMessage={<FormattedMessage id='empty_column.home' defaultMessage='Your home timeline is empty! Follow more people to fill it up.' />}\n bindToDocument={!multiColumn}\n />\n ) : <NotSignedInIndicator />}\n\n <Helmet>\n <title>{intl.formatMessage(messages.title)}</title>\n <meta name='robots' content='noindex' />\n </Helmet>\n </Column>\n );\n }\n\n}\n\nexport default connect(mapStateToProps)(injectIntl(HomeTimeline));\n"],"sourceRoot":""}