From 7b01b7c3bf4f17a40236987a88ccc33a5360c7f6 Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Mon, 24 Apr 2023 08:07:03 +0200 Subject: [PATCH] [Glitch] Add lines to threads in web UI Port 290e4aba3167b282c9ee1e966c840a490b7c818b to glitch-soc Signed-off-by: Claire --- .../flavours/glitch/components/status.jsx | 21 ++++++-- .../glitch/containers/status_container.js | 1 + .../flavours/glitch/features/status/index.jsx | 11 ++-- .../glitch/styles/components/status.scss | 50 +++++++++++++++++++ 4 files changed, 76 insertions(+), 7 deletions(-) diff --git a/app/javascript/flavours/glitch/components/status.jsx b/app/javascript/flavours/glitch/components/status.jsx index fbb610823a..9dd503584e 100644 --- a/app/javascript/flavours/glitch/components/status.jsx +++ b/app/javascript/flavours/glitch/components/status.jsx @@ -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 ( @@ -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) &&
} +
{muted && prepend} diff --git a/app/javascript/flavours/glitch/containers/status_container.js b/app/javascript/flavours/glitch/containers/status_container.js index 9873725e49..d05005e3bb 100644 --- a/app/javascript/flavours/glitch/containers/status_container.js +++ b/app/javascript/flavours/glitch/containers/status_container.js @@ -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, diff --git a/app/javascript/flavours/glitch/features/status/index.jsx b/app/javascript/flavours/glitch/features/status/index.jsx index 5d1160039b..f0cf3f4595 100644 --- a/app/javascript/flavours/glitch/features/status/index.jsx +++ b/app/javascript/flavours/glitch/features/status/index.jsx @@ -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) => ( 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) { diff --git a/app/javascript/flavours/glitch/styles/components/status.scss b/app/javascript/flavours/glitch/styles/components/status.scss index eb74e10825..56f323ea90 100644 --- a/app/javascript/flavours/glitch/styles/components/status.scss +++ b/app/javascript/flavours/glitch/styles/components/status.scss @@ -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 {