[Glitch] Add media timeline
Port 7403e5d306d36c83bfb80cd900235373186cd51a to glitch-soc
This commit is contained in:
		
							parent
							
								
									74ee5bdf37
								
							
						
					
					
						commit
						1fb4bf87f7
					
				@ -44,10 +44,9 @@ const refreshHomeTimelineAndNotification = (dispatch, done) => {
 | 
			
		||||
  dispatch(expandHomeTimeline({}, () => dispatch(expandNotifications({}, done))));
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export const connectUserStream = () => connectTimelineStream('home', 'user', refreshHomeTimelineAndNotification);
 | 
			
		||||
export const connectCommunityStream = () => connectTimelineStream('community', 'public:local');
 | 
			
		||||
export const connectMediaStream = () => connectTimelineStream('community', 'public:local');
 | 
			
		||||
export const connectPublicStream = () => connectTimelineStream('public', 'public');
 | 
			
		||||
export const connectHashtagStream = (tag) => connectTimelineStream(`hashtag:${tag}`, `hashtag&tag=${tag}`);
 | 
			
		||||
export const connectDirectStream = () => connectTimelineStream('direct', 'direct');
 | 
			
		||||
export const connectListStream = (id) => connectTimelineStream(`list:${id}`, `list&list=${id}`);
 | 
			
		||||
export const connectUserStream      = () => connectTimelineStream('home', 'user', refreshHomeTimelineAndNotification);
 | 
			
		||||
export const connectCommunityStream = ({ onlyMedia } = {}) => connectTimelineStream(`community${onlyMedia ? ':media' : ''}`, `public:local${onlyMedia ? ':media' : ''}`);
 | 
			
		||||
export const connectPublicStream    = ({ onlyMedia } = {}) => connectTimelineStream(`public${onlyMedia ? ':media' : ''}`, `public${onlyMedia ? ':media' : ''}`);
 | 
			
		||||
export const connectHashtagStream   = tag => connectTimelineStream(`hashtag:${tag}`, `hashtag&tag=${tag}`);
 | 
			
		||||
export const connectDirectStream    = () => connectTimelineStream('direct', 'direct');
 | 
			
		||||
export const connectListStream      = id => connectTimelineStream(`list:${id}`, `list&list=${id}`);
 | 
			
		||||
 | 
			
		||||
@ -69,15 +69,15 @@ export function expandTimeline(timelineId, path, params = {}, done = noOp) {
 | 
			
		||||
  };
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export const expandHomeTimeline         = ({ maxId } = {}, done = noOp) => expandTimeline('home', '/api/v1/timelines/home', { max_id: maxId }, done);
 | 
			
		||||
export const expandPublicTimeline       = ({ maxId } = {}, done = noOp) => expandTimeline('public', '/api/v1/timelines/public', { max_id: maxId }, done);
 | 
			
		||||
export const expandCommunityTimeline    = ({ maxId } = {}, done = noOp) => expandTimeline('community', '/api/v1/timelines/public', { local: true, max_id: maxId }, done);
 | 
			
		||||
export const expandDirectTimeline       = ({ maxId } = {}, done = noOp) => expandTimeline('direct', '/api/v1/timelines/direct', { max_id: maxId }, done);
 | 
			
		||||
export const expandAccountTimeline      = (accountId, { maxId, withReplies } = {}) => expandTimeline(`account:${accountId}${withReplies ? ':with_replies' : ''}`, `/api/v1/accounts/${accountId}/statuses`, { exclude_replies: !withReplies, max_id: maxId });
 | 
			
		||||
export const expandHomeTimeline            = ({ maxId } = {}, done = noOp) => expandTimeline('home', '/api/v1/timelines/home', { max_id: maxId }, done);
 | 
			
		||||
export const expandPublicTimeline          = ({ maxId, onlyMedia } = {}, done = noOp) => expandTimeline(`public${onlyMedia ? ':media' : ''}`, '/api/v1/timelines/public', { max_id: maxId, only_media: !!onlyMedia }, done);
 | 
			
		||||
export const expandCommunityTimeline       = ({ maxId, onlyMedia } = {}, done = noOp) => expandTimeline(`community${onlyMedia ? ':media' : ''}`, '/api/v1/timelines/public', { local: true, max_id: maxId, only_media: !!onlyMedia }, done);
 | 
			
		||||
export const expandDirectTimeline          = ({ maxId } = {}, done = noOp) => expandTimeline('direct', '/api/v1/timelines/direct', { max_id: maxId }, done);
 | 
			
		||||
export const expandAccountTimeline         = (accountId, { maxId, withReplies } = {}) => expandTimeline(`account:${accountId}${withReplies ? ':with_replies' : ''}`, `/api/v1/accounts/${accountId}/statuses`, { exclude_replies: !withReplies, max_id: maxId });
 | 
			
		||||
export const expandAccountFeaturedTimeline = accountId => expandTimeline(`account:${accountId}:pinned`, `/api/v1/accounts/${accountId}/statuses`, { pinned: true });
 | 
			
		||||
export const expandAccountMediaTimeline = (accountId, { maxId } = {}) => expandTimeline(`account:${accountId}:media`, `/api/v1/accounts/${accountId}/statuses`, { max_id: maxId, only_media: true });
 | 
			
		||||
export const expandHashtagTimeline      = (hashtag, { maxId } = {}, done = noOp) => expandTimeline(`hashtag:${hashtag}`, `/api/v1/timelines/tag/${hashtag}`, { max_id: maxId }, done);
 | 
			
		||||
export const expandListTimeline         = (id, { maxId } = {}, done = noOp) => expandTimeline(`list:${id}`, `/api/v1/timelines/list/${id}`, { max_id: maxId }, done);
 | 
			
		||||
export const expandAccountMediaTimeline    = (accountId, { maxId } = {}) => expandTimeline(`account:${accountId}:media`, `/api/v1/accounts/${accountId}/statuses`, { max_id: maxId, only_media: true });
 | 
			
		||||
export const expandHashtagTimeline         = (hashtag, { maxId } = {}, done = noOp) => expandTimeline(`hashtag:${hashtag}`, `/api/v1/timelines/tag/${hashtag}`, { max_id: maxId }, done);
 | 
			
		||||
export const expandListTimeline            = (id, { maxId } = {}, done = noOp) => expandTimeline(`list:${id}`, `/api/v1/timelines/list/${id}`, { max_id: maxId }, done);
 | 
			
		||||
 | 
			
		||||
export function expandTimelineRequest(timeline, isLoadingMore) {
 | 
			
		||||
  return {
 | 
			
		||||
 | 
			
		||||
@ -1,12 +1,13 @@
 | 
			
		||||
import React from 'react';
 | 
			
		||||
import { connect } from 'react-redux';
 | 
			
		||||
import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
 | 
			
		||||
import { NavLink } from 'react-router-dom';
 | 
			
		||||
import PropTypes from 'prop-types';
 | 
			
		||||
import StatusListContainer from 'flavours/glitch/features/ui/containers/status_list_container';
 | 
			
		||||
import Column from 'flavours/glitch/components/column';
 | 
			
		||||
import ColumnHeader from 'flavours/glitch/components/column_header';
 | 
			
		||||
import { expandCommunityTimeline } from 'flavours/glitch/actions/timelines';
 | 
			
		||||
import { addColumn, removeColumn, moveColumn } from 'flavours/glitch/actions/columns';
 | 
			
		||||
import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
 | 
			
		||||
import ColumnSettingsContainer from './containers/column_settings_container';
 | 
			
		||||
import { connectCommunityStream } from 'flavours/glitch/actions/streaming';
 | 
			
		||||
 | 
			
		||||
@ -14,20 +15,25 @@ const messages = defineMessages({
 | 
			
		||||
  title: { id: 'column.community', defaultMessage: 'Local timeline' },
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
const mapStateToProps = state => ({
 | 
			
		||||
  hasUnread: state.getIn(['timelines', 'community', 'unread']) > 0,
 | 
			
		||||
const mapStateToProps = (state, { onlyMedia }) => ({
 | 
			
		||||
  hasUnread: state.getIn(['timelines', `community${onlyMedia ? ':media' : ''}`, 'unread']) > 0,
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
@connect(mapStateToProps)
 | 
			
		||||
@injectIntl
 | 
			
		||||
export default class CommunityTimeline extends React.PureComponent {
 | 
			
		||||
 | 
			
		||||
  static defaultProps = {
 | 
			
		||||
    onlyMedia: false,
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  static propTypes = {
 | 
			
		||||
    dispatch: PropTypes.func.isRequired,
 | 
			
		||||
    columnId: PropTypes.string,
 | 
			
		||||
    intl: PropTypes.object.isRequired,
 | 
			
		||||
    hasUnread: PropTypes.bool,
 | 
			
		||||
    multiColumn: PropTypes.bool,
 | 
			
		||||
    onlyMedia: PropTypes.bool,
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  handlePin = () => {
 | 
			
		||||
@ -50,10 +56,10 @@ export default class CommunityTimeline extends React.PureComponent {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  componentDidMount () {
 | 
			
		||||
    const { dispatch } = this.props;
 | 
			
		||||
    const { dispatch, onlyMedia } = this.props;
 | 
			
		||||
 | 
			
		||||
    dispatch(expandCommunityTimeline());
 | 
			
		||||
    this.disconnect = dispatch(connectCommunityStream());
 | 
			
		||||
    dispatch(expandCommunityTimeline({ onlyMedia }));
 | 
			
		||||
    this.disconnect = dispatch(connectCommunityStream({ onlyMedia }));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  componentWillUnmount () {
 | 
			
		||||
@ -68,13 +74,22 @@ export default class CommunityTimeline extends React.PureComponent {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  handleLoadMore = maxId => {
 | 
			
		||||
    this.props.dispatch(expandCommunityTimeline({ maxId }));
 | 
			
		||||
    const { dispatch, onlyMedia } = this.props;
 | 
			
		||||
 | 
			
		||||
    dispatch(expandCommunityTimeline({ maxId, onlyMedia }));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  render () {
 | 
			
		||||
    const { intl, hasUnread, columnId, multiColumn } = this.props;
 | 
			
		||||
    const { intl, hasUnread, columnId, multiColumn, onlyMedia } = this.props;
 | 
			
		||||
    const pinned = !!columnId;
 | 
			
		||||
 | 
			
		||||
    const headline = (
 | 
			
		||||
      <div className='community-timeline__section-headline'>
 | 
			
		||||
        <NavLink exact to='/timelines/public/local' replace><FormattedMessage id='timeline.posts' defaultMessage='Toots' /></NavLink>
 | 
			
		||||
        <NavLink exact to='/timelines/public/local/media' replace><FormattedMessage id='timeline.media' defaultMessage='Media' /></NavLink>
 | 
			
		||||
      </div>
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    return (
 | 
			
		||||
      <Column ref={this.setRef} name='local' label={intl.formatMessage(messages.title)}>
 | 
			
		||||
        <ColumnHeader
 | 
			
		||||
@ -91,9 +106,11 @@ export default class CommunityTimeline extends React.PureComponent {
 | 
			
		||||
        </ColumnHeader>
 | 
			
		||||
 | 
			
		||||
        <StatusListContainer
 | 
			
		||||
          prepend={headline}
 | 
			
		||||
          trackScroll={!pinned}
 | 
			
		||||
          scrollKey={`community_timeline-${columnId}`}
 | 
			
		||||
          timelineId='community'
 | 
			
		||||
          shouldUpdateScroll={this.shouldUpdateScroll}
 | 
			
		||||
          timelineId={`community${onlyMedia ? ':media' : ''}`}
 | 
			
		||||
          onLoadMore={this.handleLoadMore}
 | 
			
		||||
          emptyMessage={<FormattedMessage id='empty_column.community' defaultMessage='The local timeline is empty. Write something publicly to get the ball rolling!' />}
 | 
			
		||||
        />
 | 
			
		||||
 | 
			
		||||
@ -1,12 +1,13 @@
 | 
			
		||||
import React from 'react';
 | 
			
		||||
import { connect } from 'react-redux';
 | 
			
		||||
import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
 | 
			
		||||
import { NavLink } from 'react-router-dom';
 | 
			
		||||
import PropTypes from 'prop-types';
 | 
			
		||||
import StatusListContainer from 'flavours/glitch/features/ui/containers/status_list_container';
 | 
			
		||||
import Column from 'flavours/glitch/components/column';
 | 
			
		||||
import ColumnHeader from 'flavours/glitch/components/column_header';
 | 
			
		||||
import { expandPublicTimeline } from 'flavours/glitch/actions/timelines';
 | 
			
		||||
import { addColumn, removeColumn, moveColumn } from 'flavours/glitch/actions/columns';
 | 
			
		||||
import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
 | 
			
		||||
import ColumnSettingsContainer from './containers/column_settings_container';
 | 
			
		||||
import { connectPublicStream } from 'flavours/glitch/actions/streaming';
 | 
			
		||||
 | 
			
		||||
@ -14,20 +15,25 @@ const messages = defineMessages({
 | 
			
		||||
  title: { id: 'column.public', defaultMessage: 'Federated timeline' },
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
const mapStateToProps = state => ({
 | 
			
		||||
  hasUnread: state.getIn(['timelines', 'public', 'unread']) > 0,
 | 
			
		||||
const mapStateToProps = (state, { onlyMedia }) => ({
 | 
			
		||||
  hasUnread: state.getIn(['timelines', `public${onlyMedia ? ':media' : ''}`, 'unread']) > 0,
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
@connect(mapStateToProps)
 | 
			
		||||
@injectIntl
 | 
			
		||||
export default class PublicTimeline extends React.PureComponent {
 | 
			
		||||
 | 
			
		||||
  static defaultProps = {
 | 
			
		||||
    onlyMedia: false,
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  static propTypes = {
 | 
			
		||||
    dispatch: PropTypes.func.isRequired,
 | 
			
		||||
    intl: PropTypes.object.isRequired,
 | 
			
		||||
    columnId: PropTypes.string,
 | 
			
		||||
    multiColumn: PropTypes.bool,
 | 
			
		||||
    hasUnread: PropTypes.bool,
 | 
			
		||||
    onlyMedia: PropTypes.bool,
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  handlePin = () => {
 | 
			
		||||
@ -50,10 +56,10 @@ export default class PublicTimeline extends React.PureComponent {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  componentDidMount () {
 | 
			
		||||
    const { dispatch } = this.props;
 | 
			
		||||
    const { dispatch, onlyMedia } = this.props;
 | 
			
		||||
 | 
			
		||||
    dispatch(expandPublicTimeline());
 | 
			
		||||
    this.disconnect = dispatch(connectPublicStream());
 | 
			
		||||
    dispatch(expandPublicTimeline({ onlyMedia }));
 | 
			
		||||
    this.disconnect = dispatch(connectPublicStream({ onlyMedia }));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  componentWillUnmount () {
 | 
			
		||||
@ -68,13 +74,22 @@ export default class PublicTimeline extends React.PureComponent {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  handleLoadMore = maxId => {
 | 
			
		||||
    this.props.dispatch(expandPublicTimeline({ maxId }));
 | 
			
		||||
    const { dispatch, onlyMedia } = this.props;
 | 
			
		||||
 | 
			
		||||
    dispatch(expandPublicTimeline({ maxId, onlyMedia }));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  render () {
 | 
			
		||||
    const { intl, columnId, hasUnread, multiColumn } = this.props;
 | 
			
		||||
    const { intl, columnId, hasUnread, multiColumn, onlyMedia } = this.props;
 | 
			
		||||
    const pinned = !!columnId;
 | 
			
		||||
 | 
			
		||||
    const headline = (
 | 
			
		||||
      <div className='public-timeline__section-headline'>
 | 
			
		||||
        <NavLink exact to='/timelines/public' replace><FormattedMessage id='timeline.posts' defaultMessage='Toots' /></NavLink>
 | 
			
		||||
        <NavLink exact to='/timelines/public/media' replace><FormattedMessage id='timeline.media' defaultMessage='Media' /></NavLink>
 | 
			
		||||
      </div>
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    return (
 | 
			
		||||
      <Column ref={this.setRef} name='federated' label={intl.formatMessage(messages.title)}>
 | 
			
		||||
        <ColumnHeader
 | 
			
		||||
@ -91,7 +106,8 @@ export default class PublicTimeline extends React.PureComponent {
 | 
			
		||||
        </ColumnHeader>
 | 
			
		||||
 | 
			
		||||
        <StatusListContainer
 | 
			
		||||
          timelineId='public'
 | 
			
		||||
          prepend={headline}
 | 
			
		||||
          timelineId={`public${onlyMedia ? ':media' : ''}`}
 | 
			
		||||
          onLoadMore={this.handleLoadMore}
 | 
			
		||||
          trackScroll={!pinned}
 | 
			
		||||
          scrollKey={`public_timeline-${columnId}`}
 | 
			
		||||
 | 
			
		||||
@ -467,7 +467,9 @@ export default class UI extends React.Component {
 | 
			
		||||
              <WrappedRoute path='/keyboard-shortcuts' component={KeyboardShortcuts} content={children} />
 | 
			
		||||
              <WrappedRoute path='/timelines/home' component={HomeTimeline} content={children} />
 | 
			
		||||
              <WrappedRoute path='/timelines/public' exact component={PublicTimeline} content={children} />
 | 
			
		||||
              <WrappedRoute path='/timelines/public/media' extract component={PublicTimeline} content={children} componentParams={{ onlyMedia: true }} />
 | 
			
		||||
              <WrappedRoute path='/timelines/public/local' component={CommunityTimeline} content={children} />
 | 
			
		||||
              <WrappedRoute path='/timelines/public/local/media' component={CommunityTimeline} content={children} componentParams={{ onlyMedia: true }} />
 | 
			
		||||
              <WrappedRoute path='/timelines/direct' component={DirectTimeline} content={children} />
 | 
			
		||||
              <WrappedRoute path='/timelines/tag/:id' component={HashtagTimeline} content={children} />
 | 
			
		||||
              <WrappedRoute path='/timelines/list/:id' component={ListTimeline} content={children} />
 | 
			
		||||
 | 
			
		||||
@ -446,6 +446,8 @@
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.notification__filter-bar,
 | 
			
		||||
.community-timeline__section-headline,
 | 
			
		||||
.public-timeline__section-headline,
 | 
			
		||||
.account__section-headline {
 | 
			
		||||
  background: darken($ui-base-color, 4%);
 | 
			
		||||
  border-bottom: 1px solid lighten($ui-base-color, 8%);
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user