M app/javascript/flavours/glitch/components/status.jsx => app/javascript/flavours/glitch/components/status.jsx +17 -4
@@ 67,6 67,9 @@ class Status extends ImmutablePureComponent {
id: PropTypes.string,
status: ImmutablePropTypes.map,
account: ImmutablePropTypes.map,
+ previousId: PropTypes.string,
+ nextInReplyToId: PropTypes.string,
+ rootId: PropTypes.string,
onReply: PropTypes.func,
onFavourite: PropTypes.func,
onReblog: PropTypes.func,
@@ 518,6 521,9 @@ class Status extends ImmutablePureComponent {
unread,
featured,
pictureInPicture,
+ previousId,
+ nextInReplyToId,
+ rootId,
...other
} = this.props;
const { isCollapsed, forceFilter } = this.state;
@@ 561,6 567,8 @@ class Status extends ImmutablePureComponent {
openMedia: this.handleHotkeyOpenMedia,
};
+ let prepend, rebloggedByText;
+
if (hidden) {
return (
<HotKeys handlers={handlers}>
@@ 572,7 580,11 @@ class Status extends ImmutablePureComponent {
);
}
+ const connectUp = previousId && previousId === status.get('in_reply_to_id');
+ const connectToRoot = rootId && rootId === status.get('in_reply_to_id');
+ const connectReply = nextInReplyToId && nextInReplyToId === status.get('id');
const matchedFilters = status.get('matched_filters');
+
if (this.state.forceFilter === undefined ? matchedFilters : this.state.forceFilter) {
const minHandlers = this.props.muted ? {} : {
moveUp: this.handleHotkeyMoveUp,
@@ 726,8 738,6 @@ class Status extends ImmutablePureComponent {
'data-status-by': `@${status.getIn(['account', 'acct'])}`,
};
- let prepend;
-
if (this.props.prepend && account) {
const notifKind = {
favourite: 'favourited',
@@ 748,8 758,6 @@ class Status extends ImmutablePureComponent {
);
}
- let rebloggedByText;
-
if (this.props.prepend === 'reblog') {
rebloggedByText = intl.formatMessage({ id: 'status.reblogged_by', defaultMessage: '{name} boosted' }, { name: account.get('acct') });
}
@@ 758,6 766,8 @@ class Status extends ImmutablePureComponent {
collapsed: isCollapsed,
'has-background': isCollapsed && background,
'status__wrapper-reply': !!status.get('in_reply_to_id'),
+ 'status--in-thread': !!rootId,
+ 'status--first-in-thread': previousId && (!connectUp || connectToRoot),
unread,
muted,
}, 'focusable');
@@ 774,6 784,9 @@ class Status extends ImmutablePureComponent {
aria-label={textForScreenReader(intl, status, rebloggedByText, !status.get('hidden'))}
>
{!muted && prepend}
+
+ {(connectReply || connectUp || connectToRoot) && <div className={classNames('status__line', { 'status__line--full': connectReply, 'status__line--first': !status.get('in_reply_to_id') && !connectToRoot })} />}
+
<header className='status__info'>
<span>
{muted && prepend}
M app/javascript/flavours/glitch/containers/status_container.js => app/javascript/flavours/glitch/containers/status_container.js +1 -0
@@ 83,6 83,7 @@ const makeMapStateToProps = () => {
return {
containerId: props.containerId || props.id, // Should match reblogStatus's id for reblogs
status: status,
+ nextInReplyToId: props.nextId ? state.getIn(['statuses', props.nextId, 'in_reply_to_id']) : null,
account: account || props.account,
settings: state.get('local_settings'),
prepend: prepend || props.prepend,
M app/javascript/flavours/glitch/features/status/index.jsx => app/javascript/flavours/glitch/features/status/index.jsx +8 -3
@@ 559,8 559,10 @@ class Status extends ImmutablePureComponent {
this.column.scrollTop();
};
- renderChildren (list) {
- return list.map(id => (
+ renderChildren (list, ancestors) {
+ const { params: { statusId } } = this.props;
+
+ return list.map((id, i) => (
<StatusContainer
key={id}
id={id}
@@ 568,6 570,9 @@ class Status extends ImmutablePureComponent {
onMoveUp={this.handleMoveUp}
onMoveDown={this.handleMoveDown}
contextType='thread'
+ previousId={i > 0 && list.get(i - 1)}
+ nextId={list.get(i + 1) || (ancestors && statusId)}
+ rootId={statusId}
/>
));
}
@@ 628,7 633,7 @@ class Status extends ImmutablePureComponent {
const isExpanded = settings.getIn(['content_warnings', 'shared_state']) ? !status.get('hidden') : this.state.isExpanded;
if (ancestorsIds && ancestorsIds.size > 0) {
- ancestors = <>{this.renderChildren(ancestorsIds)}</>;
+ ancestors = <>{this.renderChildren(ancestorsIds, true)}</>;
}
if (descendantsIds && descendantsIds.size > 0) {
M app/javascript/flavours/glitch/styles/components/status.scss => app/javascript/flavours/glitch/styles/components/status.scss +50 -0
@@ 554,6 554,7 @@
.detailed-status {
background: lighten($ui-base-color, 4%);
padding: 14px 10px;
+ border-top: 1px solid lighten($ui-base-color, 8%);
&--flex {
display: flex;
@@ 690,6 691,7 @@ a.status__display-name,
margin-inline-end: 10px;
height: 48px;
width: 48px;
+ box-shadow: 0 0 0 2px $ui-base-color;
}
.muted {
@@ 1029,6 1031,54 @@ a.status-card.compact:hover {
pointer-events: none;
}
}
+
+ &--in-thread {
+ border-bottom: 0;
+
+ .status__content,
+ .status__action-bar {
+ margin-left: 46px + 10px;
+ width: calc(100% - (46px + 10px));
+ }
+ }
+
+ &--first-in-thread {
+ border-top: 1px solid lighten($ui-base-color, 8%);
+ }
+
+ &__line {
+ height: 16px - 4px;
+ border-inline-start: 2px solid lighten($ui-base-color, 8%);
+ width: 0;
+ position: absolute;
+ top: 0;
+ inset-inline-start: 16px + ((46px - 2px) / 2);
+
+ &--full {
+ top: 0;
+ height: 100%;
+
+ &::before {
+ content: '';
+ display: block;
+ position: absolute;
+ top: 16px - 4px;
+ height: 46px + 4px + 4px;
+ width: 2px;
+ background: $ui-base-color;
+ inset-inline-start: -2px;
+ }
+ }
+
+ &--first {
+ top: 16px + 46px + 4px;
+ height: calc(100% - (16px + 46px + 4px));
+
+ &::before {
+ display: none;
+ }
+ }
+ }
}
.picture-in-picture {