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)
|
||||
descendants_results = @status.descendants(descendants_limit, current_account, descendants_depth_limit)
|
||||
references_results = @status.references
|
||||
loaded_ancestors = cache_collection(ancestors_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)
|
||||
statuses = [@status] + @context.ancestors + @context.descendants
|
||||
@context = Context.new(ancestors: loaded_ancestors, descendants: loaded_descendants, references: loaded_references)
|
||||
statuses = [@status] + @context.ancestors + @context.descendants + @context.references
|
||||
|
||||
render json: @context, serializer: REST::ContextSerializer, relationships: StatusRelationshipsPresenter.new(statuses, current_user&.account_id)
|
||||
end
|
||||
|
|
|
@ -181,8 +181,8 @@ export function fetchContext(id) {
|
|||
dispatch(fetchContextRequest(id));
|
||||
|
||||
api(getState).get(`/api/v1/statuses/${id}/context`).then(response => {
|
||||
dispatch(importFetchedStatuses(response.data.ancestors.concat(response.data.descendants)));
|
||||
dispatch(fetchContextSuccess(id, response.data.ancestors, 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, response.data.references));
|
||||
|
||||
}).catch(error => {
|
||||
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 {
|
||||
type: CONTEXT_FETCH_SUCCESS,
|
||||
id,
|
||||
ancestors,
|
||||
descendants,
|
||||
references,
|
||||
statuses: ancestors.concat(descendants),
|
||||
};
|
||||
}
|
||||
|
|
|
@ -89,6 +89,12 @@ const makeMapStateToProps = () => {
|
|||
const getStatus = makeGetStatus();
|
||||
const getPictureInPicture = makeGetPictureInPicture();
|
||||
|
||||
const getReferenceIds = createSelector([
|
||||
(state, { id }) => state.getIn(['contexts', 'references', id]),
|
||||
], (references) => {
|
||||
return references;
|
||||
});
|
||||
|
||||
const getAncestorsIds = createSelector([
|
||||
(_, { id }) => id,
|
||||
state => state.getIn(['contexts', 'inReplyTos']),
|
||||
|
@ -148,10 +154,12 @@ const makeMapStateToProps = () => {
|
|||
|
||||
let ancestorsIds = Immutable.List();
|
||||
let descendantsIds = Immutable.List();
|
||||
let referenceIds = Immutable.List();
|
||||
|
||||
if (status) {
|
||||
ancestorsIds = getAncestorsIds(state, { id: status.get('in_reply_to_id') });
|
||||
descendantsIds = getDescendantsIds(state, { id: status.get('id') });
|
||||
referenceIds = getReferenceIds(state, { id: status.get('id') });
|
||||
}
|
||||
|
||||
return {
|
||||
|
@ -159,6 +167,7 @@ const makeMapStateToProps = () => {
|
|||
status,
|
||||
ancestorsIds,
|
||||
descendantsIds,
|
||||
referenceIds,
|
||||
askReplyConfirmation: state.getIn(['compose', 'text']).trim().length !== 0,
|
||||
domain: state.getIn(['meta', 'domain']),
|
||||
pictureInPicture: getPictureInPicture(state, { id: props.params.statusId }),
|
||||
|
@ -201,6 +210,7 @@ class Status extends ImmutablePureComponent {
|
|||
isLoading: PropTypes.bool,
|
||||
ancestorsIds: ImmutablePropTypes.list,
|
||||
descendantsIds: ImmutablePropTypes.list,
|
||||
referenceIds: ImmutablePropTypes.list,
|
||||
intl: PropTypes.object.isRequired,
|
||||
askReplyConfirmation: PropTypes.bool,
|
||||
multiColumn: PropTypes.bool,
|
||||
|
@ -447,8 +457,8 @@ class Status extends ImmutablePureComponent {
|
|||
};
|
||||
|
||||
handleToggleAll = () => {
|
||||
const { status, ancestorsIds, descendantsIds } = this.props;
|
||||
const statusIds = [status.get('id')].concat(ancestorsIds.toJS(), descendantsIds.toJS());
|
||||
const { status, ancestorsIds, descendantsIds, referenceIds } = this.props;
|
||||
const statusIds = [status.get('id')].concat(ancestorsIds.toJS(), descendantsIds.toJS(), referenceIds.toJS());
|
||||
|
||||
if (status.get('hidden')) {
|
||||
this.props.dispatch(revealStatus(statusIds));
|
||||
|
@ -641,8 +651,8 @@ class Status extends ImmutablePureComponent {
|
|||
};
|
||||
|
||||
render () {
|
||||
let ancestors, descendants;
|
||||
const { isLoading, status, ancestorsIds, descendantsIds, intl, domain, multiColumn, pictureInPicture } = this.props;
|
||||
let ancestors, descendants, references;
|
||||
const { isLoading, status, ancestorsIds, descendantsIds, referenceIds, intl, domain, multiColumn, pictureInPicture } = this.props;
|
||||
const { fullscreen } = this.state;
|
||||
|
||||
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) {
|
||||
ancestors = <>{this.renderChildren(ancestorsIds, true)}</>;
|
||||
}
|
||||
|
@ -695,6 +709,7 @@ class Status extends ImmutablePureComponent {
|
|||
|
||||
<ScrollContainer scrollKey='thread'>
|
||||
<div className={classNames('scrollable', { fullscreen })} ref={this.setRef}>
|
||||
{references}
|
||||
{ancestors}
|
||||
|
||||
<HotKeys handlers={handlers}>
|
||||
|
|
|
@ -11,33 +11,38 @@ import { compareId } from '../compare_id';
|
|||
const initialState = ImmutableMap({
|
||||
inReplyTos: 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('replies', immutableDescendants => immutableDescendants.withMutations(replies => {
|
||||
function addReply({ id, in_reply_to_id }) {
|
||||
if (in_reply_to_id && !inReplyTos.has(id)) {
|
||||
state.update('references', immutableReferences => immutableReferences.withMutations(referencePosts => {
|
||||
function addReply({ id, in_reply_to_id }) {
|
||||
if (in_reply_to_id && !inReplyTos.has(id)) {
|
||||
|
||||
replies.update(in_reply_to_id, ImmutableList(), siblings => {
|
||||
const index = siblings.findLastIndex(sibling => compareId(sibling, id) < 0);
|
||||
return siblings.insert(index + 1, id);
|
||||
});
|
||||
replies.update(in_reply_to_id, ImmutableList(), siblings => {
|
||||
const index = siblings.findLastIndex(sibling => compareId(sibling, id) < 0);
|
||||
return siblings.insert(index + 1, id);
|
||||
});
|
||||
|
||||
inReplyTos.set(id, in_reply_to_id);
|
||||
inReplyTos.set(id, in_reply_to_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// We know in_reply_to_id of statuses but `id` itself.
|
||||
// So we assume that the status of the id replies to last ancestors.
|
||||
// We know in_reply_to_id of statuses but `id` itself.
|
||||
// So we assume that the status of the id replies to last ancestors.
|
||||
|
||||
ancestors.forEach(addReply);
|
||||
ancestors.forEach(addReply);
|
||||
|
||||
if (ancestors[0]) {
|
||||
addReply({ id, in_reply_to_id: ancestors[ancestors.length - 1].id });
|
||||
}
|
||||
if (ancestors[0]) {
|
||||
addReply({ id, in_reply_to_id: ancestors[ancestors.length - 1].id });
|
||||
}
|
||||
|
||||
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:
|
||||
return filterContexts(state, action.relationship, action.statuses);
|
||||
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:
|
||||
return deleteFromContexts(state, [action.id]);
|
||||
case TIMELINE_UPDATE:
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class Context < ActiveModelSerializers::Model
|
||||
attributes :ancestors, :descendants
|
||||
attributes :ancestors, :descendants, :references
|
||||
end
|
||||
|
|
|
@ -3,4 +3,5 @@
|
|||
class REST::ContextSerializer < ActiveModel::Serializer
|
||||
has_many :ancestors, serializer: REST::StatusSerializer
|
||||
has_many :descendants, serializer: REST::StatusSerializer
|
||||
has_many :references, serializer: REST::StatusSerializer
|
||||
end
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue