Merge pull request #198 from glitch-soc/gs-direct-timeline
Direct messages timeline from tootsuite/mastodon#4514main
commit
31814ddda0
@ -0,0 +1,60 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class Api::V1::Timelines::DirectController < Api::BaseController
|
||||||
|
before_action -> { doorkeeper_authorize! :read }, only: [:show]
|
||||||
|
before_action :require_user!, only: [:show]
|
||||||
|
after_action :insert_pagination_headers, unless: -> { @statuses.empty? }
|
||||||
|
|
||||||
|
respond_to :json
|
||||||
|
|
||||||
|
def show
|
||||||
|
@statuses = load_statuses
|
||||||
|
render json: @statuses, each_serializer: REST::StatusSerializer, relationships: StatusRelationshipsPresenter.new(@statuses, current_user&.account_id)
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def load_statuses
|
||||||
|
cached_direct_statuses
|
||||||
|
end
|
||||||
|
|
||||||
|
def cached_direct_statuses
|
||||||
|
cache_collection direct_statuses, Status
|
||||||
|
end
|
||||||
|
|
||||||
|
def direct_statuses
|
||||||
|
direct_timeline_statuses.paginate_by_max_id(
|
||||||
|
limit_param(DEFAULT_STATUSES_LIMIT),
|
||||||
|
params[:max_id],
|
||||||
|
params[:since_id]
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
def direct_timeline_statuses
|
||||||
|
Status.as_direct_timeline(current_account)
|
||||||
|
end
|
||||||
|
|
||||||
|
def insert_pagination_headers
|
||||||
|
set_pagination_headers(next_path, prev_path)
|
||||||
|
end
|
||||||
|
|
||||||
|
def pagination_params(core_params)
|
||||||
|
params.permit(:local, :limit).merge(core_params)
|
||||||
|
end
|
||||||
|
|
||||||
|
def next_path
|
||||||
|
api_v1_timelines_direct_url pagination_params(max_id: pagination_max_id)
|
||||||
|
end
|
||||||
|
|
||||||
|
def prev_path
|
||||||
|
api_v1_timelines_direct_url pagination_params(since_id: pagination_since_id)
|
||||||
|
end
|
||||||
|
|
||||||
|
def pagination_max_id
|
||||||
|
@statuses.last.id
|
||||||
|
end
|
||||||
|
|
||||||
|
def pagination_since_id
|
||||||
|
@statuses.first.id
|
||||||
|
end
|
||||||
|
end
|
@ -0,0 +1,17 @@
|
|||||||
|
import { connect } from 'react-redux';
|
||||||
|
import ColumnSettings from '../../community_timeline/components/column_settings';
|
||||||
|
import { changeSetting } from '../../../actions/settings';
|
||||||
|
|
||||||
|
const mapStateToProps = state => ({
|
||||||
|
settings: state.getIn(['settings', 'direct']),
|
||||||
|
});
|
||||||
|
|
||||||
|
const mapDispatchToProps = dispatch => ({
|
||||||
|
|
||||||
|
onChange (key, checked) {
|
||||||
|
dispatch(changeSetting(['direct', ...key], checked));
|
||||||
|
},
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
export default connect(mapStateToProps, mapDispatchToProps)(ColumnSettings);
|
@ -0,0 +1,107 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { connect } from 'react-redux';
|
||||||
|
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 {
|
||||||
|
refreshDirectTimeline,
|
||||||
|
expandDirectTimeline,
|
||||||
|
} 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 { connectDirectStream } from '../../actions/streaming';
|
||||||
|
|
||||||
|
const messages = defineMessages({
|
||||||
|
title: { id: 'column.direct', defaultMessage: 'Direct messages' },
|
||||||
|
});
|
||||||
|
|
||||||
|
const mapStateToProps = state => ({
|
||||||
|
hasUnread: state.getIn(['timelines', 'direct', 'unread']) > 0,
|
||||||
|
});
|
||||||
|
|
||||||
|
@connect(mapStateToProps)
|
||||||
|
@injectIntl
|
||||||
|
export default class DirectTimeline extends React.PureComponent {
|
||||||
|
|
||||||
|
static propTypes = {
|
||||||
|
dispatch: PropTypes.func.isRequired,
|
||||||
|
columnId: PropTypes.string,
|
||||||
|
intl: PropTypes.object.isRequired,
|
||||||
|
hasUnread: PropTypes.bool,
|
||||||
|
multiColumn: PropTypes.bool,
|
||||||
|
};
|
||||||
|
|
||||||
|
handlePin = () => {
|
||||||
|
const { columnId, dispatch } = this.props;
|
||||||
|
|
||||||
|
if (columnId) {
|
||||||
|
dispatch(removeColumn(columnId));
|
||||||
|
} else {
|
||||||
|
dispatch(addColumn('DIRECT', {}));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
handleMove = (dir) => {
|
||||||
|
const { columnId, dispatch } = this.props;
|
||||||
|
dispatch(moveColumn(columnId, dir));
|
||||||
|
}
|
||||||
|
|
||||||
|
handleHeaderClick = () => {
|
||||||
|
this.column.scrollTop();
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidMount () {
|
||||||
|
const { dispatch } = this.props;
|
||||||
|
|
||||||
|
dispatch(refreshDirectTimeline());
|
||||||
|
this.disconnect = dispatch(connectDirectStream());
|
||||||
|
}
|
||||||
|
|
||||||
|
componentWillUnmount () {
|
||||||
|
if (this.disconnect) {
|
||||||
|
this.disconnect();
|
||||||
|
this.disconnect = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
setRef = c => {
|
||||||
|
this.column = c;
|
||||||
|
}
|
||||||
|
|
||||||
|
handleLoadMore = () => {
|
||||||
|
this.props.dispatch(expandDirectTimeline());
|
||||||
|
}
|
||||||
|
|
||||||
|
render () {
|
||||||
|
const { intl, hasUnread, columnId, multiColumn } = this.props;
|
||||||
|
const pinned = !!columnId;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Column ref={this.setRef}>
|
||||||
|
<ColumnHeader
|
||||||
|
icon='envelope'
|
||||||
|
active={hasUnread}
|
||||||
|
title={intl.formatMessage(messages.title)}
|
||||||
|
onPin={this.handlePin}
|
||||||
|
onMove={this.handleMove}
|
||||||
|
onClick={this.handleHeaderClick}
|
||||||
|
pinned={pinned}
|
||||||
|
multiColumn={multiColumn}
|
||||||
|
>
|
||||||
|
<ColumnSettingsContainer />
|
||||||
|
</ColumnHeader>
|
||||||
|
|
||||||
|
<StatusListContainer
|
||||||
|
trackScroll={!pinned}
|
||||||
|
scrollKey={`direct_timeline-${columnId}`}
|
||||||
|
timelineId='direct'
|
||||||
|
loadMore={this.handleLoadMore}
|
||||||
|
emptyMessage={<FormattedMessage id='empty_column.direct' defaultMessage="You don't have any direct messages yet. When you send or receive one, it will show up here." />}
|
||||||
|
/>
|
||||||
|
</Column>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in new issue