Add media timeline (#6631)
This commit is contained in:
		
				
					committed by
					
						
						Eugen Rochko
					
				
			
			
				
	
			
			
			
						parent
						
							05f8c375a2
						
					
				
				
					commit
					7403e5d306
				
			@@ -41,9 +41,8 @@ const refreshHomeTimelineAndNotification = (dispatch, 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 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}`);
 | 
			
		||||
export const connectListStream      = id => connectTimelineStream(`list:${id}`, `list&list=${id}`);
 | 
			
		||||
 
 | 
			
		||||
@@ -94,8 +94,8 @@ 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 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 });
 | 
			
		||||
 
 | 
			
		||||
@@ -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 '../ui/containers/status_list_container';
 | 
			
		||||
import Column from '../../components/column';
 | 
			
		||||
import ColumnHeader from '../../components/column_header';
 | 
			
		||||
import { expandCommunityTimeline } from '../../actions/timelines';
 | 
			
		||||
import { addColumn, removeColumn, moveColumn } from '../../actions/columns';
 | 
			
		||||
import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
 | 
			
		||||
import ColumnSettingsContainer from './containers/column_settings_container';
 | 
			
		||||
import { connectCommunityStream } from '../../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}>
 | 
			
		||||
        <ColumnHeader
 | 
			
		||||
@@ -91,9 +106,10 @@ export default class CommunityTimeline extends React.PureComponent {
 | 
			
		||||
        </ColumnHeader>
 | 
			
		||||
 | 
			
		||||
        <StatusListContainer
 | 
			
		||||
          prepend={headline}
 | 
			
		||||
          trackScroll={!pinned}
 | 
			
		||||
          scrollKey={`community_timeline-${columnId}`}
 | 
			
		||||
          timelineId='community'
 | 
			
		||||
          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 '../ui/containers/status_list_container';
 | 
			
		||||
import Column from '../../components/column';
 | 
			
		||||
import ColumnHeader from '../../components/column_header';
 | 
			
		||||
import { expandPublicTimeline } from '../../actions/timelines';
 | 
			
		||||
import { addColumn, removeColumn, moveColumn } from '../../actions/columns';
 | 
			
		||||
import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
 | 
			
		||||
import ColumnSettingsContainer from './containers/column_settings_container';
 | 
			
		||||
import { connectPublicStream } from '../../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}>
 | 
			
		||||
        <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}`}
 | 
			
		||||
 
 | 
			
		||||
@@ -141,7 +141,9 @@ class SwitchingColumnsArea extends React.PureComponent {
 | 
			
		||||
          <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} />
 | 
			
		||||
 
 | 
			
		||||
@@ -280,6 +280,8 @@
 | 
			
		||||
  "tabs_bar.local_timeline": "المحلي",
 | 
			
		||||
  "tabs_bar.notifications": "الإخطارات",
 | 
			
		||||
  "tabs_bar.search": "البحث",
 | 
			
		||||
  "timeline.media": "Media",
 | 
			
		||||
  "timeline.posts": "Toots",
 | 
			
		||||
  "ui.beforeunload": "سوف تفقد مسودتك إن تركت ماستدون.",
 | 
			
		||||
  "upload_area.title": "إسحب ثم أفلت للرفع",
 | 
			
		||||
  "upload_button.label": "إضافة وسائط",
 | 
			
		||||
 
 | 
			
		||||
@@ -280,6 +280,8 @@
 | 
			
		||||
  "tabs_bar.local_timeline": "Local",
 | 
			
		||||
  "tabs_bar.notifications": "Известия",
 | 
			
		||||
  "tabs_bar.search": "Search",
 | 
			
		||||
  "timeline.media": "Media",
 | 
			
		||||
  "timeline.posts": "Toots",
 | 
			
		||||
  "ui.beforeunload": "Your draft will be lost if you leave Mastodon.",
 | 
			
		||||
  "upload_area.title": "Drag & drop to upload",
 | 
			
		||||
  "upload_button.label": "Добави медия",
 | 
			
		||||
 
 | 
			
		||||
@@ -280,6 +280,8 @@
 | 
			
		||||
  "tabs_bar.local_timeline": "Local",
 | 
			
		||||
  "tabs_bar.notifications": "Notificacions",
 | 
			
		||||
  "tabs_bar.search": "Cerca",
 | 
			
		||||
  "timeline.media": "Media",
 | 
			
		||||
  "timeline.posts": "Toots",
 | 
			
		||||
  "ui.beforeunload": "El vostre esborrany es perdrà si sortiu de Mastodon.",
 | 
			
		||||
  "upload_area.title": "Arrossega i deixa anar per carregar",
 | 
			
		||||
  "upload_button.label": "Afegir multimèdia",
 | 
			
		||||
 
 | 
			
		||||
@@ -280,6 +280,8 @@
 | 
			
		||||
  "tabs_bar.local_timeline": "Lucale",
 | 
			
		||||
  "tabs_bar.notifications": "Nutificazione",
 | 
			
		||||
  "tabs_bar.search": "Cercà",
 | 
			
		||||
  "timeline.media": "Media",
 | 
			
		||||
  "timeline.posts": "Toots",
 | 
			
		||||
  "ui.beforeunload": "A bruttacopia sarà persa s'ellu hè chjosu Mastodon.",
 | 
			
		||||
  "upload_area.title": "Drag & drop per caricà un fugliale",
 | 
			
		||||
  "upload_button.label": "Aghjunghje un media",
 | 
			
		||||
 
 | 
			
		||||
@@ -280,6 +280,8 @@
 | 
			
		||||
  "tabs_bar.local_timeline": "Lokal",
 | 
			
		||||
  "tabs_bar.notifications": "Mitteilungen",
 | 
			
		||||
  "tabs_bar.search": "Suchen",
 | 
			
		||||
  "timeline.media": "Media",
 | 
			
		||||
  "timeline.posts": "Toots",
 | 
			
		||||
  "ui.beforeunload": "Dein Entwurf geht verloren, wenn du Mastodon verlässt.",
 | 
			
		||||
  "upload_area.title": "Zum Hochladen hereinziehen",
 | 
			
		||||
  "upload_button.label": "Mediendatei hinzufügen",
 | 
			
		||||
 
 | 
			
		||||
@@ -596,6 +596,14 @@
 | 
			
		||||
        "defaultMessage": "Local timeline",
 | 
			
		||||
        "id": "column.community"
 | 
			
		||||
      },
 | 
			
		||||
      {
 | 
			
		||||
        "defaultMessage": "Toots",
 | 
			
		||||
        "id": "timeline.posts"
 | 
			
		||||
      },
 | 
			
		||||
      {
 | 
			
		||||
        "defaultMessage": "Media",
 | 
			
		||||
        "id": "timeline.media"
 | 
			
		||||
      },
 | 
			
		||||
      {
 | 
			
		||||
        "defaultMessage": "The local timeline is empty. Write something publicly to get the ball rolling!",
 | 
			
		||||
        "id": "empty_column.community"
 | 
			
		||||
@@ -1393,6 +1401,14 @@
 | 
			
		||||
        "defaultMessage": "Federated timeline",
 | 
			
		||||
        "id": "column.public"
 | 
			
		||||
      },
 | 
			
		||||
      {
 | 
			
		||||
        "defaultMessage": "Toots",
 | 
			
		||||
        "id": "timeline.posts"
 | 
			
		||||
      },
 | 
			
		||||
      {
 | 
			
		||||
        "defaultMessage": "Media",
 | 
			
		||||
        "id": "timeline.media"
 | 
			
		||||
      },
 | 
			
		||||
      {
 | 
			
		||||
        "defaultMessage": "There is nothing here! Write something publicly, or manually follow users from other instances to fill it up",
 | 
			
		||||
        "id": "empty_column.public"
 | 
			
		||||
 
 | 
			
		||||
@@ -280,6 +280,8 @@
 | 
			
		||||
  "tabs_bar.local_timeline": "Local",
 | 
			
		||||
  "tabs_bar.notifications": "Notifications",
 | 
			
		||||
  "tabs_bar.search": "Search",
 | 
			
		||||
  "timeline.media": "Media",
 | 
			
		||||
  "timeline.posts": "Toots",
 | 
			
		||||
  "ui.beforeunload": "Your draft will be lost if you leave Mastodon.",
 | 
			
		||||
  "upload_area.title": "Drag & drop to upload",
 | 
			
		||||
  "upload_button.label": "Add media",
 | 
			
		||||
 
 | 
			
		||||
@@ -280,6 +280,8 @@
 | 
			
		||||
  "tabs_bar.local_timeline": "Local",
 | 
			
		||||
  "tabs_bar.notifications": "Notifications",
 | 
			
		||||
  "tabs_bar.search": "Search",
 | 
			
		||||
  "timeline.media": "Media",
 | 
			
		||||
  "timeline.posts": "Toots",
 | 
			
		||||
  "ui.beforeunload": "Your draft will be lost if you leave Mastodon.",
 | 
			
		||||
  "upload_area.title": "Drag & drop to upload",
 | 
			
		||||
  "upload_button.label": "Add media",
 | 
			
		||||
 
 | 
			
		||||
@@ -280,6 +280,8 @@
 | 
			
		||||
  "tabs_bar.local_timeline": "Loka tempolinio",
 | 
			
		||||
  "tabs_bar.notifications": "Sciigoj",
 | 
			
		||||
  "tabs_bar.search": "Serĉi",
 | 
			
		||||
  "timeline.media": "Media",
 | 
			
		||||
  "timeline.posts": "Toots",
 | 
			
		||||
  "ui.beforeunload": "Via malneto perdiĝos se vi eliras de Mastodon.",
 | 
			
		||||
  "upload_area.title": "Altreni kaj lasi por alŝuti",
 | 
			
		||||
  "upload_button.label": "Aldoni aŭdovidaĵon",
 | 
			
		||||
 
 | 
			
		||||
@@ -280,6 +280,8 @@
 | 
			
		||||
  "tabs_bar.local_timeline": "Local",
 | 
			
		||||
  "tabs_bar.notifications": "Notificaciones",
 | 
			
		||||
  "tabs_bar.search": "Search",
 | 
			
		||||
  "timeline.media": "Media",
 | 
			
		||||
  "timeline.posts": "Toots",
 | 
			
		||||
  "ui.beforeunload": "Tu borrador se perderá si sales de Mastodon.",
 | 
			
		||||
  "upload_area.title": "Arrastra y suelta para subir",
 | 
			
		||||
  "upload_button.label": "Subir multimedia",
 | 
			
		||||
 
 | 
			
		||||
@@ -280,6 +280,8 @@
 | 
			
		||||
  "tabs_bar.local_timeline": "Local",
 | 
			
		||||
  "tabs_bar.notifications": "Notifications",
 | 
			
		||||
  "tabs_bar.search": "Search",
 | 
			
		||||
  "timeline.media": "Media",
 | 
			
		||||
  "timeline.posts": "Toots",
 | 
			
		||||
  "ui.beforeunload": "Your draft will be lost if you leave Mastodon.",
 | 
			
		||||
  "upload_area.title": "Drag & drop to upload",
 | 
			
		||||
  "upload_button.label": "Add media",
 | 
			
		||||
 
 | 
			
		||||
@@ -280,6 +280,8 @@
 | 
			
		||||
  "tabs_bar.local_timeline": "محلی",
 | 
			
		||||
  "tabs_bar.notifications": "اعلانها",
 | 
			
		||||
  "tabs_bar.search": "Search",
 | 
			
		||||
  "timeline.media": "Media",
 | 
			
		||||
  "timeline.posts": "Toots",
 | 
			
		||||
  "ui.beforeunload": "اگر از ماستدون خارج شوید پیشنویس شما پاک خواهد شد.",
 | 
			
		||||
  "upload_area.title": "برای بارگذاری به اینجا بکشید",
 | 
			
		||||
  "upload_button.label": "افزودن تصویر",
 | 
			
		||||
 
 | 
			
		||||
@@ -280,6 +280,8 @@
 | 
			
		||||
  "tabs_bar.local_timeline": "Paikallinen",
 | 
			
		||||
  "tabs_bar.notifications": "Ilmoitukset",
 | 
			
		||||
  "tabs_bar.search": "Hae",
 | 
			
		||||
  "timeline.media": "Media",
 | 
			
		||||
  "timeline.posts": "Toots",
 | 
			
		||||
  "ui.beforeunload": "Luonnos häviää, jos poistut Mastodonista.",
 | 
			
		||||
  "upload_area.title": "Lataa raahaamalla ja pudottamalla tähän",
 | 
			
		||||
  "upload_button.label": "Lisää mediaa",
 | 
			
		||||
 
 | 
			
		||||
@@ -280,6 +280,8 @@
 | 
			
		||||
  "tabs_bar.local_timeline": "Fil public local",
 | 
			
		||||
  "tabs_bar.notifications": "Notifications",
 | 
			
		||||
  "tabs_bar.search": "Chercher",
 | 
			
		||||
  "timeline.media": "Media",
 | 
			
		||||
  "timeline.posts": "Toots",
 | 
			
		||||
  "ui.beforeunload": "Votre brouillon sera perdu si vous quittez Mastodon.",
 | 
			
		||||
  "upload_area.title": "Glissez et déposez pour envoyer",
 | 
			
		||||
  "upload_button.label": "Joindre un média",
 | 
			
		||||
 
 | 
			
		||||
@@ -280,6 +280,8 @@
 | 
			
		||||
  "tabs_bar.local_timeline": "Local",
 | 
			
		||||
  "tabs_bar.notifications": "Notificacións",
 | 
			
		||||
  "tabs_bar.search": "Buscar",
 | 
			
		||||
  "timeline.media": "Media",
 | 
			
		||||
  "timeline.posts": "Toots",
 | 
			
		||||
  "ui.beforeunload": "O borrador perderase se sae de Mastodon.",
 | 
			
		||||
  "upload_area.title": "Arrastre e solte para subir",
 | 
			
		||||
  "upload_button.label": "Engadir medios",
 | 
			
		||||
 
 | 
			
		||||
@@ -280,6 +280,8 @@
 | 
			
		||||
  "tabs_bar.local_timeline": "ציר זמן מקומי",
 | 
			
		||||
  "tabs_bar.notifications": "התראות",
 | 
			
		||||
  "tabs_bar.search": "Search",
 | 
			
		||||
  "timeline.media": "Media",
 | 
			
		||||
  "timeline.posts": "Toots",
 | 
			
		||||
  "ui.beforeunload": "הטיוטא תאבד אם תעזבו את מסטודון.",
 | 
			
		||||
  "upload_area.title": "ניתן להעלות על ידי Drag & drop",
 | 
			
		||||
  "upload_button.label": "הוספת מדיה",
 | 
			
		||||
 
 | 
			
		||||
@@ -280,6 +280,8 @@
 | 
			
		||||
  "tabs_bar.local_timeline": "Lokalno",
 | 
			
		||||
  "tabs_bar.notifications": "Notifikacije",
 | 
			
		||||
  "tabs_bar.search": "Search",
 | 
			
		||||
  "timeline.media": "Media",
 | 
			
		||||
  "timeline.posts": "Toots",
 | 
			
		||||
  "ui.beforeunload": "Your draft will be lost if you leave Mastodon.",
 | 
			
		||||
  "upload_area.title": "Povuci i spusti kako bi uploadao",
 | 
			
		||||
  "upload_button.label": "Dodaj media",
 | 
			
		||||
 
 | 
			
		||||
@@ -280,6 +280,8 @@
 | 
			
		||||
  "tabs_bar.local_timeline": "Local",
 | 
			
		||||
  "tabs_bar.notifications": "Értesítések",
 | 
			
		||||
  "tabs_bar.search": "Search",
 | 
			
		||||
  "timeline.media": "Media",
 | 
			
		||||
  "timeline.posts": "Toots",
 | 
			
		||||
  "ui.beforeunload": "A piszkozata el fog vesztődni ha elhagyja Mastodon-t.",
 | 
			
		||||
  "upload_area.title": "Húzza ide a feltöltéshez",
 | 
			
		||||
  "upload_button.label": "Média hozzáadása",
 | 
			
		||||
 
 | 
			
		||||
@@ -280,6 +280,8 @@
 | 
			
		||||
  "tabs_bar.local_timeline": "Տեղական",
 | 
			
		||||
  "tabs_bar.notifications": "Ծանուցումներ",
 | 
			
		||||
  "tabs_bar.search": "Search",
 | 
			
		||||
  "timeline.media": "Media",
 | 
			
		||||
  "timeline.posts": "Toots",
 | 
			
		||||
  "ui.beforeunload": "Քո սեւագիրը կկորի, եթե լքես Մաստոդոնը։",
 | 
			
		||||
  "upload_area.title": "Քաշիր ու նետիր՝ վերբեռնելու համար",
 | 
			
		||||
  "upload_button.label": "Ավելացնել մեդիա",
 | 
			
		||||
 
 | 
			
		||||
@@ -280,6 +280,8 @@
 | 
			
		||||
  "tabs_bar.local_timeline": "Lokal",
 | 
			
		||||
  "tabs_bar.notifications": "Notifikasi",
 | 
			
		||||
  "tabs_bar.search": "Search",
 | 
			
		||||
  "timeline.media": "Media",
 | 
			
		||||
  "timeline.posts": "Toots",
 | 
			
		||||
  "ui.beforeunload": "Naskah anda akan hilang jika anda keluar dari Mastodon.",
 | 
			
		||||
  "upload_area.title": "Seret & lepaskan untuk mengunggah",
 | 
			
		||||
  "upload_button.label": "Tambahkan media",
 | 
			
		||||
 
 | 
			
		||||
@@ -280,6 +280,8 @@
 | 
			
		||||
  "tabs_bar.local_timeline": "Lokala",
 | 
			
		||||
  "tabs_bar.notifications": "Savigi",
 | 
			
		||||
  "tabs_bar.search": "Search",
 | 
			
		||||
  "timeline.media": "Media",
 | 
			
		||||
  "timeline.posts": "Toots",
 | 
			
		||||
  "ui.beforeunload": "Your draft will be lost if you leave Mastodon.",
 | 
			
		||||
  "upload_area.title": "Tranar faligar por kargar",
 | 
			
		||||
  "upload_button.label": "Adjuntar kontenajo",
 | 
			
		||||
 
 | 
			
		||||
@@ -280,6 +280,8 @@
 | 
			
		||||
  "tabs_bar.local_timeline": "Locale",
 | 
			
		||||
  "tabs_bar.notifications": "Notifiche",
 | 
			
		||||
  "tabs_bar.search": "Cerca",
 | 
			
		||||
  "timeline.media": "Media",
 | 
			
		||||
  "timeline.posts": "Toots",
 | 
			
		||||
  "ui.beforeunload": "La bozza andrà persa se esci da Mastodon.",
 | 
			
		||||
  "upload_area.title": "Trascina per caricare",
 | 
			
		||||
  "upload_button.label": "Aggiungi file multimediale",
 | 
			
		||||
 
 | 
			
		||||
@@ -280,6 +280,8 @@
 | 
			
		||||
  "tabs_bar.local_timeline": "ローカル",
 | 
			
		||||
  "tabs_bar.notifications": "通知",
 | 
			
		||||
  "tabs_bar.search": "検索",
 | 
			
		||||
  "timeline.media": "Media",
 | 
			
		||||
  "timeline.posts": "Toots",
 | 
			
		||||
  "ui.beforeunload": "Mastodonから離れると送信前の投稿は失われます。",
 | 
			
		||||
  "upload_area.title": "ドラッグ&ドロップでアップロード",
 | 
			
		||||
  "upload_button.label": "メディアを追加",
 | 
			
		||||
 
 | 
			
		||||
@@ -280,6 +280,8 @@
 | 
			
		||||
  "tabs_bar.local_timeline": "로컬",
 | 
			
		||||
  "tabs_bar.notifications": "알림",
 | 
			
		||||
  "tabs_bar.search": "검색",
 | 
			
		||||
  "timeline.media": "Media",
 | 
			
		||||
  "timeline.posts": "Toots",
 | 
			
		||||
  "ui.beforeunload": "지금 나가면 저장되지 않은 항목을 잃게 됩니다.",
 | 
			
		||||
  "upload_area.title": "드래그 & 드롭으로 업로드",
 | 
			
		||||
  "upload_button.label": "미디어 추가",
 | 
			
		||||
 
 | 
			
		||||
@@ -280,6 +280,8 @@
 | 
			
		||||
  "tabs_bar.local_timeline": "Lokaal",
 | 
			
		||||
  "tabs_bar.notifications": "Meldingen",
 | 
			
		||||
  "tabs_bar.search": "Zoeken",
 | 
			
		||||
  "timeline.media": "Media",
 | 
			
		||||
  "timeline.posts": "Toots",
 | 
			
		||||
  "ui.beforeunload": "Je concept zal verloren gaan als je Mastodon verlaat.",
 | 
			
		||||
  "upload_area.title": "Hierin slepen om te uploaden",
 | 
			
		||||
  "upload_button.label": "Media toevoegen",
 | 
			
		||||
 
 | 
			
		||||
@@ -280,6 +280,8 @@
 | 
			
		||||
  "tabs_bar.local_timeline": "Lokal",
 | 
			
		||||
  "tabs_bar.notifications": "Varslinger",
 | 
			
		||||
  "tabs_bar.search": "Search",
 | 
			
		||||
  "timeline.media": "Media",
 | 
			
		||||
  "timeline.posts": "Toots",
 | 
			
		||||
  "ui.beforeunload": "Din kladd vil bli forkastet om du forlater Mastodon.",
 | 
			
		||||
  "upload_area.title": "Dra og slipp for å laste opp",
 | 
			
		||||
  "upload_button.label": "Legg til media",
 | 
			
		||||
 
 | 
			
		||||
@@ -280,6 +280,8 @@
 | 
			
		||||
  "tabs_bar.local_timeline": "Flux public local",
 | 
			
		||||
  "tabs_bar.notifications": "Notificacions",
 | 
			
		||||
  "tabs_bar.search": "Recèrcas",
 | 
			
		||||
  "timeline.media": "Media",
 | 
			
		||||
  "timeline.posts": "Toots",
 | 
			
		||||
  "ui.beforeunload": "Vòstre brolhon serà perdut se quitatz Mastodon.",
 | 
			
		||||
  "upload_area.title": "Lisatz e depausatz per mandar",
 | 
			
		||||
  "upload_button.label": "Ajustar un mèdia",
 | 
			
		||||
 
 | 
			
		||||
@@ -280,6 +280,8 @@
 | 
			
		||||
  "tabs_bar.local_timeline": "Lokalne",
 | 
			
		||||
  "tabs_bar.notifications": "Powiadomienia",
 | 
			
		||||
  "tabs_bar.search": "Szukaj",
 | 
			
		||||
  "timeline.media": "Media",
 | 
			
		||||
  "timeline.posts": "Toots",
 | 
			
		||||
  "ui.beforeunload": "Utracisz tworzony wpis, jeżeli opuścisz Mastodona.",
 | 
			
		||||
  "upload_area.title": "Przeciągnij i upuść aby wysłać",
 | 
			
		||||
  "upload_button.label": "Dodaj zawartość multimedialną",
 | 
			
		||||
 
 | 
			
		||||
@@ -280,6 +280,8 @@
 | 
			
		||||
  "tabs_bar.local_timeline": "Local",
 | 
			
		||||
  "tabs_bar.notifications": "Notificações",
 | 
			
		||||
  "tabs_bar.search": "Buscar",
 | 
			
		||||
  "timeline.media": "Media",
 | 
			
		||||
  "timeline.posts": "Toots",
 | 
			
		||||
  "ui.beforeunload": "Seu rascunho será perdido se você sair do Mastodon.",
 | 
			
		||||
  "upload_area.title": "Arraste e solte para enviar",
 | 
			
		||||
  "upload_button.label": "Adicionar mídia",
 | 
			
		||||
 
 | 
			
		||||
@@ -280,6 +280,8 @@
 | 
			
		||||
  "tabs_bar.local_timeline": "Local",
 | 
			
		||||
  "tabs_bar.notifications": "Notificações",
 | 
			
		||||
  "tabs_bar.search": "Search",
 | 
			
		||||
  "timeline.media": "Media",
 | 
			
		||||
  "timeline.posts": "Toots",
 | 
			
		||||
  "ui.beforeunload": "O teu rascunho vai ser perdido se abandonares o Mastodon.",
 | 
			
		||||
  "upload_area.title": "Arraste e solte para enviar",
 | 
			
		||||
  "upload_button.label": "Adicionar media",
 | 
			
		||||
 
 | 
			
		||||
@@ -280,6 +280,8 @@
 | 
			
		||||
  "tabs_bar.local_timeline": "Локальная",
 | 
			
		||||
  "tabs_bar.notifications": "Уведомления",
 | 
			
		||||
  "tabs_bar.search": "Поиск",
 | 
			
		||||
  "timeline.media": "Media",
 | 
			
		||||
  "timeline.posts": "Toots",
 | 
			
		||||
  "ui.beforeunload": "Ваш черновик будет утерян, если вы покинете Mastodon.",
 | 
			
		||||
  "upload_area.title": "Перетащите сюда, чтобы загрузить",
 | 
			
		||||
  "upload_button.label": "Добавить медиаконтент",
 | 
			
		||||
 
 | 
			
		||||
@@ -280,6 +280,8 @@
 | 
			
		||||
  "tabs_bar.local_timeline": "Lokálna",
 | 
			
		||||
  "tabs_bar.notifications": "Notifikácie",
 | 
			
		||||
  "tabs_bar.search": "Hľadaj",
 | 
			
		||||
  "timeline.media": "Media",
 | 
			
		||||
  "timeline.posts": "Toots",
 | 
			
		||||
  "ui.beforeunload": "Čo máte rozpísané sa stratí, ak opustíte Mastodon.",
 | 
			
		||||
  "upload_area.title": "Ťahaj a pusti pre nahratie",
 | 
			
		||||
  "upload_button.label": "Pridať médiá",
 | 
			
		||||
 
 | 
			
		||||
@@ -280,6 +280,8 @@
 | 
			
		||||
  "tabs_bar.local_timeline": "Lokalno",
 | 
			
		||||
  "tabs_bar.notifications": "Obvestila",
 | 
			
		||||
  "tabs_bar.search": "Poišči",
 | 
			
		||||
  "timeline.media": "Media",
 | 
			
		||||
  "timeline.posts": "Toots",
 | 
			
		||||
  "ui.beforeunload": "Vaš osnutek bo izgubljen, če zapustite Mastodona.",
 | 
			
		||||
  "upload_area.title": "Povlecite in spustite za pošiljanje",
 | 
			
		||||
  "upload_button.label": "Dodaj medij",
 | 
			
		||||
 
 | 
			
		||||
@@ -280,6 +280,8 @@
 | 
			
		||||
  "tabs_bar.local_timeline": "Lokalno",
 | 
			
		||||
  "tabs_bar.notifications": "Obaveštenja",
 | 
			
		||||
  "tabs_bar.search": "Search",
 | 
			
		||||
  "timeline.media": "Media",
 | 
			
		||||
  "timeline.posts": "Toots",
 | 
			
		||||
  "ui.beforeunload": "Ako napustite Mastodont, izgubićete napisani nacrt.",
 | 
			
		||||
  "upload_area.title": "Prevucite ovde da otpremite",
 | 
			
		||||
  "upload_button.label": "Dodaj multimediju",
 | 
			
		||||
 
 | 
			
		||||
@@ -280,6 +280,8 @@
 | 
			
		||||
  "tabs_bar.local_timeline": "Локално",
 | 
			
		||||
  "tabs_bar.notifications": "Обавештења",
 | 
			
		||||
  "tabs_bar.search": "Search",
 | 
			
		||||
  "timeline.media": "Media",
 | 
			
		||||
  "timeline.posts": "Toots",
 | 
			
		||||
  "ui.beforeunload": "Ако напустите Мастодонт, изгубићете написани нацрт.",
 | 
			
		||||
  "upload_area.title": "Превуците овде да отпремите",
 | 
			
		||||
  "upload_button.label": "Додај мултимедију",
 | 
			
		||||
 
 | 
			
		||||
@@ -280,6 +280,8 @@
 | 
			
		||||
  "tabs_bar.local_timeline": "Lokal",
 | 
			
		||||
  "tabs_bar.notifications": "Meddelanden",
 | 
			
		||||
  "tabs_bar.search": "Sök",
 | 
			
		||||
  "timeline.media": "Media",
 | 
			
		||||
  "timeline.posts": "Toots",
 | 
			
		||||
  "ui.beforeunload": "Ditt utkast kommer att förloras om du lämnar Mastodon.",
 | 
			
		||||
  "upload_area.title": "Dra & släpp för att ladda upp",
 | 
			
		||||
  "upload_button.label": "Lägg till media",
 | 
			
		||||
 
 | 
			
		||||
@@ -280,6 +280,8 @@
 | 
			
		||||
  "tabs_bar.local_timeline": "Local",
 | 
			
		||||
  "tabs_bar.notifications": "Notifications",
 | 
			
		||||
  "tabs_bar.search": "Search",
 | 
			
		||||
  "timeline.media": "Media",
 | 
			
		||||
  "timeline.posts": "Toots",
 | 
			
		||||
  "ui.beforeunload": "Your draft will be lost if you leave Mastodon.",
 | 
			
		||||
  "upload_area.title": "Drag & drop to upload",
 | 
			
		||||
  "upload_button.label": "Add media",
 | 
			
		||||
 
 | 
			
		||||
@@ -280,6 +280,8 @@
 | 
			
		||||
  "tabs_bar.local_timeline": "Local",
 | 
			
		||||
  "tabs_bar.notifications": "Notifications",
 | 
			
		||||
  "tabs_bar.search": "Search",
 | 
			
		||||
  "timeline.media": "Media",
 | 
			
		||||
  "timeline.posts": "Toots",
 | 
			
		||||
  "ui.beforeunload": "Your draft will be lost if you leave Mastodon.",
 | 
			
		||||
  "upload_area.title": "Drag & drop to upload",
 | 
			
		||||
  "upload_button.label": "Add media",
 | 
			
		||||
 
 | 
			
		||||
@@ -280,6 +280,8 @@
 | 
			
		||||
  "tabs_bar.local_timeline": "Yerel",
 | 
			
		||||
  "tabs_bar.notifications": "Bildirimler",
 | 
			
		||||
  "tabs_bar.search": "Search",
 | 
			
		||||
  "timeline.media": "Media",
 | 
			
		||||
  "timeline.posts": "Toots",
 | 
			
		||||
  "ui.beforeunload": "Your draft will be lost if you leave Mastodon.",
 | 
			
		||||
  "upload_area.title": "Upload için sürükle bırak yapınız",
 | 
			
		||||
  "upload_button.label": "Görsel ekle",
 | 
			
		||||
 
 | 
			
		||||
@@ -280,6 +280,8 @@
 | 
			
		||||
  "tabs_bar.local_timeline": "Локальна",
 | 
			
		||||
  "tabs_bar.notifications": "Сповіщення",
 | 
			
		||||
  "tabs_bar.search": "Search",
 | 
			
		||||
  "timeline.media": "Media",
 | 
			
		||||
  "timeline.posts": "Toots",
 | 
			
		||||
  "ui.beforeunload": "Your draft will be lost if you leave Mastodon.",
 | 
			
		||||
  "upload_area.title": "Перетягніть сюди, щоб завантажити",
 | 
			
		||||
  "upload_button.label": "Додати медіаконтент",
 | 
			
		||||
 
 | 
			
		||||
@@ -280,6 +280,8 @@
 | 
			
		||||
  "tabs_bar.local_timeline": "本站",
 | 
			
		||||
  "tabs_bar.notifications": "通知",
 | 
			
		||||
  "tabs_bar.search": "Search",
 | 
			
		||||
  "timeline.media": "Media",
 | 
			
		||||
  "timeline.posts": "Toots",
 | 
			
		||||
  "ui.beforeunload": "如果你现在离开 Mastodon,你的草稿内容将会被丢弃。",
 | 
			
		||||
  "upload_area.title": "将文件拖放到此处开始上传",
 | 
			
		||||
  "upload_button.label": "上传媒体文件",
 | 
			
		||||
 
 | 
			
		||||
@@ -280,6 +280,8 @@
 | 
			
		||||
  "tabs_bar.local_timeline": "本站",
 | 
			
		||||
  "tabs_bar.notifications": "通知",
 | 
			
		||||
  "tabs_bar.search": "搜尋",
 | 
			
		||||
  "timeline.media": "Media",
 | 
			
		||||
  "timeline.posts": "Toots",
 | 
			
		||||
  "ui.beforeunload": "如果你現在離開 Mastodon,你的草稿內容將會被丟棄。",
 | 
			
		||||
  "upload_area.title": "將檔案拖放至此上載",
 | 
			
		||||
  "upload_button.label": "上載媒體檔案",
 | 
			
		||||
 
 | 
			
		||||
@@ -280,6 +280,8 @@
 | 
			
		||||
  "tabs_bar.local_timeline": "本地",
 | 
			
		||||
  "tabs_bar.notifications": "通知",
 | 
			
		||||
  "tabs_bar.search": "Search",
 | 
			
		||||
  "timeline.media": "Media",
 | 
			
		||||
  "timeline.posts": "Toots",
 | 
			
		||||
  "ui.beforeunload": "如果離開 Mastodon,你的草稿將會不見。",
 | 
			
		||||
  "upload_area.title": "拖放來上傳",
 | 
			
		||||
  "upload_button.label": "增加媒體",
 | 
			
		||||
 
 | 
			
		||||
@@ -4737,6 +4737,8 @@ a.status-card {
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.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%);
 | 
			
		||||
 
 | 
			
		||||
@@ -81,6 +81,11 @@ class BatchedRemoveStatusService < BaseService
 | 
			
		||||
      redis.publish('timeline:public', payload)
 | 
			
		||||
      redis.publish('timeline:public:local', payload) if status.local?
 | 
			
		||||
 | 
			
		||||
      if status.media_attachments.exists?
 | 
			
		||||
        redis.publish('timeline:public:media', payload)
 | 
			
		||||
        redis.publish('timeline:public:local:media', payload) if status.local?
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      @tags[status.id].each do |hashtag|
 | 
			
		||||
        redis.publish("timeline:hashtag:#{hashtag}", payload)
 | 
			
		||||
        redis.publish("timeline:hashtag:#{hashtag}:local", payload) if status.local?
 | 
			
		||||
 
 | 
			
		||||
@@ -25,6 +25,7 @@ class FanOutOnWriteService < BaseService
 | 
			
		||||
    return if status.reply? && status.in_reply_to_account_id != status.account_id
 | 
			
		||||
 | 
			
		||||
    deliver_to_public(status)
 | 
			
		||||
    deliver_to_media(status) if status.media_attachments.exists?
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  private
 | 
			
		||||
@@ -85,6 +86,13 @@ class FanOutOnWriteService < BaseService
 | 
			
		||||
    Redis.current.publish('timeline:public:local', @payload) if status.local?
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def deliver_to_media(status)
 | 
			
		||||
    Rails.logger.debug "Delivering status #{status.id} to media timeline"
 | 
			
		||||
 | 
			
		||||
    Redis.current.publish('timeline:public:media', @payload)
 | 
			
		||||
    Redis.current.publish('timeline:public:local:media', @payload) if status.local?
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def deliver_to_direct_timelines(status)
 | 
			
		||||
    Rails.logger.debug "Delivering status #{status.id} to direct timelines"
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -20,6 +20,7 @@ class RemoveStatusService < BaseService
 | 
			
		||||
    remove_reblogs
 | 
			
		||||
    remove_from_hashtags
 | 
			
		||||
    remove_from_public
 | 
			
		||||
    remove_from_media if status.media_attachments.exists?
 | 
			
		||||
    remove_from_direct if status.direct_visibility?
 | 
			
		||||
 | 
			
		||||
    @status.destroy!
 | 
			
		||||
@@ -131,6 +132,13 @@ class RemoveStatusService < BaseService
 | 
			
		||||
    Redis.current.publish('timeline:public:local', @payload) if @status.local?
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def remove_from_media
 | 
			
		||||
    return unless @status.public_visibility?
 | 
			
		||||
 | 
			
		||||
    Redis.current.publish('timeline:public:media', @payload)
 | 
			
		||||
    Redis.current.publish('timeline:public:local:media', @payload) if @status.local?
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def remove_from_direct
 | 
			
		||||
    @mentions.each do |mention|
 | 
			
		||||
      Redis.current.publish("timeline:direct:#{mention.account.id}", @payload) if mention.account.local?
 | 
			
		||||
 
 | 
			
		||||
@@ -241,7 +241,9 @@ const startWorker = (workerId) => {
 | 
			
		||||
 | 
			
		||||
  const PUBLIC_STREAMS = [
 | 
			
		||||
    'public',
 | 
			
		||||
    'public:media',
 | 
			
		||||
    'public:local',
 | 
			
		||||
    'public:local:media',
 | 
			
		||||
    'hashtag',
 | 
			
		||||
    'hashtag:local',
 | 
			
		||||
  ];
 | 
			
		||||
@@ -459,11 +461,17 @@ const startWorker = (workerId) => {
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  app.get('/api/v1/streaming/public', (req, res) => {
 | 
			
		||||
    streamFrom('timeline:public', req, streamToHttp(req, res), streamHttpEnd(req), true);
 | 
			
		||||
    const onlyMedia = req.query.only_media === '1' || req.query.only_media === 'true';
 | 
			
		||||
    const channel   = onlyMedia ? 'timeline:public:media' : 'timeline:public';
 | 
			
		||||
 | 
			
		||||
    streamFrom(channel, req, streamToHttp(req, res), streamHttpEnd(req), true);
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  app.get('/api/v1/streaming/public/local', (req, res) => {
 | 
			
		||||
    streamFrom('timeline:public:local', req, streamToHttp(req, res), streamHttpEnd(req), true);
 | 
			
		||||
    const onlyMedia = req.query.only_media === '1' || req.query.only_media === 'true';
 | 
			
		||||
    const channel   = onlyMedia ? 'timeline:public:local:media' : 'timeline:public:local';
 | 
			
		||||
 | 
			
		||||
    streamFrom(channel, req, streamToHttp(req, res), streamHttpEnd(req), true);
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  app.get('/api/v1/streaming/direct', (req, res) => {
 | 
			
		||||
@@ -521,6 +529,12 @@ const startWorker = (workerId) => {
 | 
			
		||||
    case 'public:local':
 | 
			
		||||
      streamFrom('timeline:public:local', req, streamToWs(req, ws), streamWsEnd(req, ws), true);
 | 
			
		||||
      break;
 | 
			
		||||
    case 'public:media':
 | 
			
		||||
      streamFrom('timeline:public:media', req, streamToWs(req, ws), streamWsEnd(req, ws), true);
 | 
			
		||||
      break;
 | 
			
		||||
    case 'public:local:media':
 | 
			
		||||
      streamFrom('timeline:public:local:media', req, streamToWs(req, ws), streamWsEnd(req, ws), true);
 | 
			
		||||
      break;
 | 
			
		||||
    case 'direct':
 | 
			
		||||
      streamFrom(`timeline:direct:${req.accountId}`, req, streamToWs(req, ws), streamWsEnd(req, ws), true);
 | 
			
		||||
      break;
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user