|
|
|
@ -17,7 +17,7 @@ import {
|
|
|
|
|
} from 'soapbox/actions/moderation';
|
|
|
|
|
import { getSettings } from 'soapbox/actions/settings';
|
|
|
|
|
import { getSoapboxConfig } from 'soapbox/actions/soapbox';
|
|
|
|
|
import PullToRefresh from 'soapbox/components/pull-to-refresh';
|
|
|
|
|
import ScrollableList from 'soapbox/components/scrollable_list';
|
|
|
|
|
import SubNavigation from 'soapbox/components/sub_navigation';
|
|
|
|
|
import { Column } from 'soapbox/components/ui';
|
|
|
|
|
import PlaceholderStatus from 'soapbox/features/placeholder/components/placeholder_status';
|
|
|
|
@ -642,9 +642,11 @@ class Status extends ImmutablePureComponent<IStatus, IStatusState> {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
render() {
|
|
|
|
|
let ancestors, descendants;
|
|
|
|
|
const { status, ancestorsIds, descendantsIds, intl } = this.props;
|
|
|
|
|
|
|
|
|
|
const hasAncestors = ancestorsIds && ancestorsIds.size > 0;
|
|
|
|
|
const hasDescendants = descendantsIds && descendantsIds.size > 0;
|
|
|
|
|
|
|
|
|
|
if (!status && this.state.isLoaded) {
|
|
|
|
|
// TODO: handle errors other than 404 with `this.state.error?.response?.status`
|
|
|
|
|
return (
|
|
|
|
@ -656,14 +658,6 @@ class Status extends ImmutablePureComponent<IStatus, IStatusState> {
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (ancestorsIds && ancestorsIds.size > 0) {
|
|
|
|
|
ancestors = this.renderChildren(ancestorsIds);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (descendantsIds && descendantsIds.size > 0) {
|
|
|
|
|
descendants = this.renderChildren(descendantsIds);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type HotkeyHandlers = { [key: string]: (keyEvent?: KeyboardEvent) => void };
|
|
|
|
|
|
|
|
|
|
const handlers: HotkeyHandlers = {
|
|
|
|
@ -683,6 +677,76 @@ class Status extends ImmutablePureComponent<IStatus, IStatusState> {
|
|
|
|
|
const username = String(status.getIn(['account', 'acct']));
|
|
|
|
|
const titleMessage = status.visibility === 'direct' ? messages.titleDirect : messages.title;
|
|
|
|
|
|
|
|
|
|
const focusedStatus = (
|
|
|
|
|
<div className={classNames('thread__detailed-status', { 'pb-4': hasDescendants })} key={status.id}>
|
|
|
|
|
<HotKeys handlers={handlers}>
|
|
|
|
|
<div
|
|
|
|
|
ref={this.setStatusRef}
|
|
|
|
|
className={classNames('detailed-status__wrapper')}
|
|
|
|
|
tabIndex={0}
|
|
|
|
|
// FIXME: no "reblogged by" text is added for the screen reader
|
|
|
|
|
aria-label={textForScreenReader(intl, status)}
|
|
|
|
|
>
|
|
|
|
|
{/* @ts-ignore */}
|
|
|
|
|
<DetailedStatus
|
|
|
|
|
status={status}
|
|
|
|
|
onOpenVideo={this.handleOpenVideo}
|
|
|
|
|
onOpenMedia={this.handleOpenMedia}
|
|
|
|
|
onToggleHidden={this.handleToggleHidden}
|
|
|
|
|
showMedia={this.state.showMedia}
|
|
|
|
|
onToggleMediaVisibility={this.handleToggleMediaVisibility}
|
|
|
|
|
/>
|
|
|
|
|
|
|
|
|
|
<hr className='mb-2 dark:border-slate-600' />
|
|
|
|
|
|
|
|
|
|
<ActionBar
|
|
|
|
|
status={status}
|
|
|
|
|
onReply={this.handleReplyClick}
|
|
|
|
|
onFavourite={this.handleFavouriteClick}
|
|
|
|
|
onEmojiReact={this.handleEmojiReactClick}
|
|
|
|
|
onReblog={this.handleReblogClick}
|
|
|
|
|
onQuote={this.handleQuoteClick}
|
|
|
|
|
onDelete={this.handleDeleteClick}
|
|
|
|
|
onDirect={this.handleDirectClick}
|
|
|
|
|
onChat={this.handleChatClick}
|
|
|
|
|
onMention={this.handleMentionClick}
|
|
|
|
|
onMute={this.handleMuteClick}
|
|
|
|
|
onMuteConversation={this.handleConversationMuteClick}
|
|
|
|
|
onBlock={this.handleBlockClick}
|
|
|
|
|
onReport={this.handleReport}
|
|
|
|
|
onPin={this.handlePin}
|
|
|
|
|
onBookmark={this.handleBookmark}
|
|
|
|
|
onEmbed={this.handleEmbed}
|
|
|
|
|
onDeactivateUser={this.handleDeactivateUser}
|
|
|
|
|
onDeleteUser={this.handleDeleteUser}
|
|
|
|
|
onToggleStatusSensitivity={this.handleToggleStatusSensitivity}
|
|
|
|
|
onDeleteStatus={this.handleDeleteStatus}
|
|
|
|
|
allowedEmoji={this.props.allowedEmoji}
|
|
|
|
|
emojiSelectorFocused={this.state.emojiSelectorFocused}
|
|
|
|
|
handleEmojiSelectorExpand={this.handleEmojiSelectorExpand}
|
|
|
|
|
handleEmojiSelectorUnfocus={this.handleEmojiSelectorUnfocus}
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
</HotKeys>
|
|
|
|
|
|
|
|
|
|
{hasDescendants && (
|
|
|
|
|
<hr className='mt-2 dark:border-slate-600' />
|
|
|
|
|
)}
|
|
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
const children: JSX.Element[] = [];
|
|
|
|
|
|
|
|
|
|
if (hasAncestors) {
|
|
|
|
|
children.push(...this.renderChildren(ancestorsIds).toArray());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
children.push(focusedStatus);
|
|
|
|
|
|
|
|
|
|
if (hasDescendants) {
|
|
|
|
|
children.push(...this.renderChildren(descendantsIds).toArray());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
<Column label={intl.formatMessage(titleMessage, { username })} transparent>
|
|
|
|
|
<div className='px-4 pt-4 sm:p-0'>
|
|
|
|
@ -690,70 +754,9 @@ class Status extends ImmutablePureComponent<IStatus, IStatusState> {
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div ref={this.setRef} className='thread'>
|
|
|
|
|
<PullToRefresh onRefresh={this.handleRefresh}>
|
|
|
|
|
{ancestors && (
|
|
|
|
|
<div className='thread__ancestors space-y-4 mb-4'>{ancestors}</div>
|
|
|
|
|
)}
|
|
|
|
|
|
|
|
|
|
<div className='thread__status thread__status--focused'>
|
|
|
|
|
<HotKeys handlers={handlers}>
|
|
|
|
|
<div
|
|
|
|
|
ref={this.setStatusRef}
|
|
|
|
|
className={classNames('detailed-status__wrapper')}
|
|
|
|
|
tabIndex={0}
|
|
|
|
|
// FIXME: no "reblogged by" text is added for the screen reader
|
|
|
|
|
aria-label={textForScreenReader(intl, status)}
|
|
|
|
|
>
|
|
|
|
|
{/* @ts-ignore */}
|
|
|
|
|
<DetailedStatus
|
|
|
|
|
status={status}
|
|
|
|
|
onOpenVideo={this.handleOpenVideo}
|
|
|
|
|
onOpenMedia={this.handleOpenMedia}
|
|
|
|
|
onToggleHidden={this.handleToggleHidden}
|
|
|
|
|
showMedia={this.state.showMedia}
|
|
|
|
|
onToggleMediaVisibility={this.handleToggleMediaVisibility}
|
|
|
|
|
/>
|
|
|
|
|
|
|
|
|
|
<hr className='mb-2 dark:border-slate-600' />
|
|
|
|
|
|
|
|
|
|
<ActionBar
|
|
|
|
|
status={status}
|
|
|
|
|
onReply={this.handleReplyClick}
|
|
|
|
|
onFavourite={this.handleFavouriteClick}
|
|
|
|
|
onEmojiReact={this.handleEmojiReactClick}
|
|
|
|
|
onReblog={this.handleReblogClick}
|
|
|
|
|
onQuote={this.handleQuoteClick}
|
|
|
|
|
onDelete={this.handleDeleteClick}
|
|
|
|
|
onDirect={this.handleDirectClick}
|
|
|
|
|
onChat={this.handleChatClick}
|
|
|
|
|
onMention={this.handleMentionClick}
|
|
|
|
|
onMute={this.handleMuteClick}
|
|
|
|
|
onMuteConversation={this.handleConversationMuteClick}
|
|
|
|
|
onBlock={this.handleBlockClick}
|
|
|
|
|
onReport={this.handleReport}
|
|
|
|
|
onPin={this.handlePin}
|
|
|
|
|
onBookmark={this.handleBookmark}
|
|
|
|
|
onEmbed={this.handleEmbed}
|
|
|
|
|
onDeactivateUser={this.handleDeactivateUser}
|
|
|
|
|
onDeleteUser={this.handleDeleteUser}
|
|
|
|
|
onToggleStatusSensitivity={this.handleToggleStatusSensitivity}
|
|
|
|
|
onDeleteStatus={this.handleDeleteStatus}
|
|
|
|
|
allowedEmoji={this.props.allowedEmoji}
|
|
|
|
|
emojiSelectorFocused={this.state.emojiSelectorFocused}
|
|
|
|
|
handleEmojiSelectorExpand={this.handleEmojiSelectorExpand}
|
|
|
|
|
handleEmojiSelectorUnfocus={this.handleEmojiSelectorUnfocus}
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
</HotKeys>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
{descendants && (
|
|
|
|
|
<>
|
|
|
|
|
<hr className='mt-2 dark:border-slate-600' />
|
|
|
|
|
<div className='thread__descendants space-y-4'>{descendants}</div>
|
|
|
|
|
</>
|
|
|
|
|
)}
|
|
|
|
|
</PullToRefresh>
|
|
|
|
|
<ScrollableList onRefresh={this.handleRefresh}>
|
|
|
|
|
{children}
|
|
|
|
|
</ScrollableList>
|
|
|
|
|
</div>
|
|
|
|
|
</Column>
|
|
|
|
|
);
|
|
|
|
|