Add reference toots view as thread
This commit is contained in:
parent
44a987810b
commit
801d17f34d
6 changed files with 51 additions and 27 deletions
|
@ -44,11 +44,13 @@ class Api::V1::StatusesController < Api::BaseController
|
||||||
|
|
||||||
ancestors_results = @status.in_reply_to_id.nil? ? [] : @status.ancestors(ancestors_limit, current_account)
|
ancestors_results = @status.in_reply_to_id.nil? ? [] : @status.ancestors(ancestors_limit, current_account)
|
||||||
descendants_results = @status.descendants(descendants_limit, current_account, descendants_depth_limit)
|
descendants_results = @status.descendants(descendants_limit, current_account, descendants_depth_limit)
|
||||||
|
references_results = @status.references
|
||||||
loaded_ancestors = cache_collection(ancestors_results, Status)
|
loaded_ancestors = cache_collection(ancestors_results, Status)
|
||||||
loaded_descendants = cache_collection(descendants_results, Status)
|
loaded_descendants = cache_collection(descendants_results, Status)
|
||||||
|
loaded_references = cache_collection(references_results, Status)
|
||||||
|
|
||||||
@context = Context.new(ancestors: loaded_ancestors, descendants: loaded_descendants)
|
@context = Context.new(ancestors: loaded_ancestors, descendants: loaded_descendants, references: loaded_references)
|
||||||
statuses = [@status] + @context.ancestors + @context.descendants
|
statuses = [@status] + @context.ancestors + @context.descendants + @context.references
|
||||||
|
|
||||||
render json: @context, serializer: REST::ContextSerializer, relationships: StatusRelationshipsPresenter.new(statuses, current_user&.account_id)
|
render json: @context, serializer: REST::ContextSerializer, relationships: StatusRelationshipsPresenter.new(statuses, current_user&.account_id)
|
||||||
end
|
end
|
||||||
|
|
|
@ -181,8 +181,8 @@ export function fetchContext(id) {
|
||||||
dispatch(fetchContextRequest(id));
|
dispatch(fetchContextRequest(id));
|
||||||
|
|
||||||
api(getState).get(`/api/v1/statuses/${id}/context`).then(response => {
|
api(getState).get(`/api/v1/statuses/${id}/context`).then(response => {
|
||||||
dispatch(importFetchedStatuses(response.data.ancestors.concat(response.data.descendants)));
|
dispatch(importFetchedStatuses(response.data.ancestors.concat(response.data.descendants).concat(response.data.references)));
|
||||||
dispatch(fetchContextSuccess(id, response.data.ancestors, response.data.descendants));
|
dispatch(fetchContextSuccess(id, response.data.ancestors, response.data.descendants, response.data.references));
|
||||||
|
|
||||||
}).catch(error => {
|
}).catch(error => {
|
||||||
if (error.response && error.response.status === 404) {
|
if (error.response && error.response.status === 404) {
|
||||||
|
@ -201,12 +201,13 @@ export function fetchContextRequest(id) {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function fetchContextSuccess(id, ancestors, descendants) {
|
export function fetchContextSuccess(id, ancestors, descendants, references) {
|
||||||
return {
|
return {
|
||||||
type: CONTEXT_FETCH_SUCCESS,
|
type: CONTEXT_FETCH_SUCCESS,
|
||||||
id,
|
id,
|
||||||
ancestors,
|
ancestors,
|
||||||
descendants,
|
descendants,
|
||||||
|
references,
|
||||||
statuses: ancestors.concat(descendants),
|
statuses: ancestors.concat(descendants),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -89,6 +89,12 @@ const makeMapStateToProps = () => {
|
||||||
const getStatus = makeGetStatus();
|
const getStatus = makeGetStatus();
|
||||||
const getPictureInPicture = makeGetPictureInPicture();
|
const getPictureInPicture = makeGetPictureInPicture();
|
||||||
|
|
||||||
|
const getReferenceIds = createSelector([
|
||||||
|
(state, { id }) => state.getIn(['contexts', 'references', id]),
|
||||||
|
], (references) => {
|
||||||
|
return references;
|
||||||
|
});
|
||||||
|
|
||||||
const getAncestorsIds = createSelector([
|
const getAncestorsIds = createSelector([
|
||||||
(_, { id }) => id,
|
(_, { id }) => id,
|
||||||
state => state.getIn(['contexts', 'inReplyTos']),
|
state => state.getIn(['contexts', 'inReplyTos']),
|
||||||
|
@ -148,10 +154,12 @@ const makeMapStateToProps = () => {
|
||||||
|
|
||||||
let ancestorsIds = Immutable.List();
|
let ancestorsIds = Immutable.List();
|
||||||
let descendantsIds = Immutable.List();
|
let descendantsIds = Immutable.List();
|
||||||
|
let referenceIds = Immutable.List();
|
||||||
|
|
||||||
if (status) {
|
if (status) {
|
||||||
ancestorsIds = getAncestorsIds(state, { id: status.get('in_reply_to_id') });
|
ancestorsIds = getAncestorsIds(state, { id: status.get('in_reply_to_id') });
|
||||||
descendantsIds = getDescendantsIds(state, { id: status.get('id') });
|
descendantsIds = getDescendantsIds(state, { id: status.get('id') });
|
||||||
|
referenceIds = getReferenceIds(state, { id: status.get('id') });
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
@ -159,6 +167,7 @@ const makeMapStateToProps = () => {
|
||||||
status,
|
status,
|
||||||
ancestorsIds,
|
ancestorsIds,
|
||||||
descendantsIds,
|
descendantsIds,
|
||||||
|
referenceIds,
|
||||||
askReplyConfirmation: state.getIn(['compose', 'text']).trim().length !== 0,
|
askReplyConfirmation: state.getIn(['compose', 'text']).trim().length !== 0,
|
||||||
domain: state.getIn(['meta', 'domain']),
|
domain: state.getIn(['meta', 'domain']),
|
||||||
pictureInPicture: getPictureInPicture(state, { id: props.params.statusId }),
|
pictureInPicture: getPictureInPicture(state, { id: props.params.statusId }),
|
||||||
|
@ -201,6 +210,7 @@ class Status extends ImmutablePureComponent {
|
||||||
isLoading: PropTypes.bool,
|
isLoading: PropTypes.bool,
|
||||||
ancestorsIds: ImmutablePropTypes.list,
|
ancestorsIds: ImmutablePropTypes.list,
|
||||||
descendantsIds: ImmutablePropTypes.list,
|
descendantsIds: ImmutablePropTypes.list,
|
||||||
|
referenceIds: ImmutablePropTypes.list,
|
||||||
intl: PropTypes.object.isRequired,
|
intl: PropTypes.object.isRequired,
|
||||||
askReplyConfirmation: PropTypes.bool,
|
askReplyConfirmation: PropTypes.bool,
|
||||||
multiColumn: PropTypes.bool,
|
multiColumn: PropTypes.bool,
|
||||||
|
@ -447,8 +457,8 @@ class Status extends ImmutablePureComponent {
|
||||||
};
|
};
|
||||||
|
|
||||||
handleToggleAll = () => {
|
handleToggleAll = () => {
|
||||||
const { status, ancestorsIds, descendantsIds } = this.props;
|
const { status, ancestorsIds, descendantsIds, referenceIds } = this.props;
|
||||||
const statusIds = [status.get('id')].concat(ancestorsIds.toJS(), descendantsIds.toJS());
|
const statusIds = [status.get('id')].concat(ancestorsIds.toJS(), descendantsIds.toJS(), referenceIds.toJS());
|
||||||
|
|
||||||
if (status.get('hidden')) {
|
if (status.get('hidden')) {
|
||||||
this.props.dispatch(revealStatus(statusIds));
|
this.props.dispatch(revealStatus(statusIds));
|
||||||
|
@ -641,8 +651,8 @@ class Status extends ImmutablePureComponent {
|
||||||
};
|
};
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
let ancestors, descendants;
|
let ancestors, descendants, references;
|
||||||
const { isLoading, status, ancestorsIds, descendantsIds, intl, domain, multiColumn, pictureInPicture } = this.props;
|
const { isLoading, status, ancestorsIds, descendantsIds, referenceIds, intl, domain, multiColumn, pictureInPicture } = this.props;
|
||||||
const { fullscreen } = this.state;
|
const { fullscreen } = this.state;
|
||||||
|
|
||||||
if (isLoading) {
|
if (isLoading) {
|
||||||
|
@ -659,6 +669,10 @@ class Status extends ImmutablePureComponent {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (referenceIds && referenceIds.size > 0) {
|
||||||
|
references = <>{this.renderChildren(referenceIds, true)}</>;
|
||||||
|
}
|
||||||
|
|
||||||
if (ancestorsIds && ancestorsIds.size > 0) {
|
if (ancestorsIds && ancestorsIds.size > 0) {
|
||||||
ancestors = <>{this.renderChildren(ancestorsIds, true)}</>;
|
ancestors = <>{this.renderChildren(ancestorsIds, true)}</>;
|
||||||
}
|
}
|
||||||
|
@ -695,6 +709,7 @@ class Status extends ImmutablePureComponent {
|
||||||
|
|
||||||
<ScrollContainer scrollKey='thread'>
|
<ScrollContainer scrollKey='thread'>
|
||||||
<div className={classNames('scrollable', { fullscreen })} ref={this.setRef}>
|
<div className={classNames('scrollable', { fullscreen })} ref={this.setRef}>
|
||||||
|
{references}
|
||||||
{ancestors}
|
{ancestors}
|
||||||
|
|
||||||
<HotKeys handlers={handlers}>
|
<HotKeys handlers={handlers}>
|
||||||
|
|
|
@ -11,11 +11,13 @@ import { compareId } from '../compare_id';
|
||||||
const initialState = ImmutableMap({
|
const initialState = ImmutableMap({
|
||||||
inReplyTos: ImmutableMap(),
|
inReplyTos: ImmutableMap(),
|
||||||
replies: ImmutableMap(),
|
replies: ImmutableMap(),
|
||||||
|
references: ImmutableMap(),
|
||||||
});
|
});
|
||||||
|
|
||||||
const normalizeContext = (immutableState, id, ancestors, descendants) => immutableState.withMutations(state => {
|
const normalizeContext = (immutableState, id, ancestors, descendants, references) => immutableState.withMutations(state => {
|
||||||
state.update('inReplyTos', immutableAncestors => immutableAncestors.withMutations(inReplyTos => {
|
state.update('inReplyTos', immutableAncestors => immutableAncestors.withMutations(inReplyTos => {
|
||||||
state.update('replies', immutableDescendants => immutableDescendants.withMutations(replies => {
|
state.update('replies', immutableDescendants => immutableDescendants.withMutations(replies => {
|
||||||
|
state.update('references', immutableReferences => immutableReferences.withMutations(referencePosts => {
|
||||||
function addReply({ id, in_reply_to_id }) {
|
function addReply({ id, in_reply_to_id }) {
|
||||||
if (in_reply_to_id && !inReplyTos.has(id)) {
|
if (in_reply_to_id && !inReplyTos.has(id)) {
|
||||||
|
|
||||||
|
@ -38,6 +40,9 @@ const normalizeContext = (immutableState, id, ancestors, descendants) => immutab
|
||||||
}
|
}
|
||||||
|
|
||||||
descendants.forEach(addReply);
|
descendants.forEach(addReply);
|
||||||
|
|
||||||
|
referencePosts.set(id, ImmutableList(references.map((r) => r.id)));
|
||||||
|
}));
|
||||||
}));
|
}));
|
||||||
}));
|
}));
|
||||||
});
|
});
|
||||||
|
@ -96,7 +101,7 @@ export default function replies(state = initialState, action) {
|
||||||
case ACCOUNT_MUTE_SUCCESS:
|
case ACCOUNT_MUTE_SUCCESS:
|
||||||
return filterContexts(state, action.relationship, action.statuses);
|
return filterContexts(state, action.relationship, action.statuses);
|
||||||
case CONTEXT_FETCH_SUCCESS:
|
case CONTEXT_FETCH_SUCCESS:
|
||||||
return normalizeContext(state, action.id, action.ancestors, action.descendants);
|
return normalizeContext(state, action.id, action.ancestors, action.descendants, action.references);
|
||||||
case TIMELINE_DELETE:
|
case TIMELINE_DELETE:
|
||||||
return deleteFromContexts(state, [action.id]);
|
return deleteFromContexts(state, [action.id]);
|
||||||
case TIMELINE_UPDATE:
|
case TIMELINE_UPDATE:
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class Context < ActiveModelSerializers::Model
|
class Context < ActiveModelSerializers::Model
|
||||||
attributes :ancestors, :descendants
|
attributes :ancestors, :descendants, :references
|
||||||
end
|
end
|
||||||
|
|
|
@ -3,4 +3,5 @@
|
||||||
class REST::ContextSerializer < ActiveModel::Serializer
|
class REST::ContextSerializer < ActiveModel::Serializer
|
||||||
has_many :ancestors, serializer: REST::StatusSerializer
|
has_many :ancestors, serializer: REST::StatusSerializer
|
||||||
has_many :descendants, serializer: REST::StatusSerializer
|
has_many :descendants, serializer: REST::StatusSerializer
|
||||||
|
has_many :references, serializer: REST::StatusSerializer
|
||||||
end
|
end
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue