import PropTypes from 'prop-types'; import { useRef, useCallback, useEffect } from 'react'; import { useIntl, defineMessages, FormattedMessage } from 'react-intl'; import { Helmet } from 'react-helmet'; import { NavLink } from 'react-router-dom'; import PublicIcon from '@material-symbols/svg-600/outlined/public.svg?react'; import { addColumn } from 'mastodon/actions/columns'; import { changeSetting } from 'mastodon/actions/settings'; import { connectPublicStream, connectCommunityStream } from 'mastodon/actions/streaming'; import { expandPublicTimeline, expandCommunityTimeline } from 'mastodon/actions/timelines'; import { DismissableBanner } from 'mastodon/components/dismissable_banner'; import initialState, { domain } from 'mastodon/initial_state'; import { useAppDispatch, useAppSelector } from 'mastodon/store'; import Column from '../../components/column'; import ColumnHeader from '../../components/column_header'; import SettingToggle from '../notifications/components/setting_toggle'; import StatusListContainer from '../ui/containers/status_list_container'; const messages = defineMessages({ title: { id: 'column.firehose', defaultMessage: 'Live feeds' }, }); // TODO: use a proper React context later on const useIdentity = () => ({ signedIn: !!initialState.meta.me, accountId: initialState.meta.me, disabledAccountId: initialState.meta.disabled_account_id, accessToken: initialState.meta.access_token, permissions: initialState.role ? initialState.role.permissions : 0, }); const ColumnSettings = () => { const dispatch = useAppDispatch(); const settings = useAppSelector((state) => state.getIn(['settings', 'firehose'])); const onChange = useCallback( (key, checked) => dispatch(changeSetting(['firehose', ...key], checked)), [dispatch], ); return (
} />
); }; const Firehose = ({ feedType, multiColumn }) => { const dispatch = useAppDispatch(); const intl = useIntl(); const { signedIn } = useIdentity(); const columnRef = useRef(null); const onlyMedia = useAppSelector((state) => state.getIn(['settings', 'firehose', 'onlyMedia'], false)); const hasUnread = useAppSelector((state) => state.getIn(['timelines', `${feedType}${onlyMedia ? ':media' : ''}`, 'unread'], 0) > 0); const handlePin = useCallback( () => { switch(feedType) { case 'community': dispatch(addColumn('COMMUNITY', { other: { onlyMedia } })); break; case 'public': dispatch(addColumn('PUBLIC', { other: { onlyMedia } })); break; case 'public:remote': dispatch(addColumn('REMOTE', { other: { onlyMedia, onlyRemote: true } })); break; } }, [dispatch, onlyMedia, feedType], ); const handleLoadMore = useCallback( (maxId) => { switch(feedType) { case 'community': dispatch(expandCommunityTimeline({ maxId, onlyMedia })); break; case 'public': dispatch(expandPublicTimeline({ maxId, onlyMedia })); break; case 'public:remote': dispatch(expandPublicTimeline({ maxId, onlyMedia, onlyRemote: true })); break; } }, [dispatch, onlyMedia, feedType], ); const handleHeaderClick = useCallback(() => columnRef.current?.scrollTop(), []); useEffect(() => { let disconnect; switch(feedType) { case 'community': dispatch(expandCommunityTimeline({ onlyMedia })); if (signedIn) { disconnect = dispatch(connectCommunityStream({ onlyMedia })); } break; case 'public': dispatch(expandPublicTimeline({ onlyMedia })); if (signedIn) { disconnect = dispatch(connectPublicStream({ onlyMedia })); } break; case 'public:remote': dispatch(expandPublicTimeline({ onlyMedia, onlyRemote: true })); if (signedIn) { disconnect = dispatch(connectPublicStream({ onlyMedia, onlyRemote: true })); } break; } return () => disconnect?.(); }, [dispatch, signedIn, feedType, onlyMedia]); const prependBanner = feedType === 'community' ? ( ) : ( ); const emptyMessage = feedType === 'community' ? ( ) : ( ); return (
{intl.formatMessage(messages.title)}
); }; Firehose.propTypes = { multiColumn: PropTypes.bool, feedType: PropTypes.string, }; export default Firehose;