2023-06-23 03:48:53 +00:00
|
|
|
import { myAuthRequired } from "@utils/app";
|
2023-06-20 14:17:16 +00:00
|
|
|
import { canShare, share } from "@utils/browser";
|
2023-06-22 13:02:48 +00:00
|
|
|
import { getExternalHost, getHttpBase } from "@utils/env";
|
2023-06-22 12:58:51 +00:00
|
|
|
import {
|
|
|
|
capitalizeFirstLetter,
|
|
|
|
futureDaysToUnixTime,
|
|
|
|
hostname,
|
|
|
|
} from "@utils/helpers";
|
2023-06-21 22:28:24 +00:00
|
|
|
import { isImage, isVideo } from "@utils/media";
|
2023-06-20 14:17:16 +00:00
|
|
|
import {
|
|
|
|
amAdmin,
|
|
|
|
amCommunityCreator,
|
|
|
|
amMod,
|
|
|
|
canAdmin,
|
|
|
|
canMod,
|
|
|
|
isAdmin,
|
|
|
|
isBanned,
|
|
|
|
isMod,
|
|
|
|
} from "@utils/roles";
|
2022-01-12 00:53:23 +00:00
|
|
|
import classNames from "classnames";
|
2021-02-22 02:39:04 +00:00
|
|
|
import { Component, linkEvent } from "inferno";
|
|
|
|
import { Link } from "inferno-router";
|
2020-09-06 16:15:25 +00:00
|
|
|
import {
|
2021-07-17 20:42:55 +00:00
|
|
|
AddAdmin,
|
|
|
|
AddModToCommunity,
|
|
|
|
BanFromCommunity,
|
|
|
|
BanPerson,
|
2021-08-20 02:56:18 +00:00
|
|
|
BlockPerson,
|
2021-07-17 20:42:55 +00:00
|
|
|
CommunityModeratorView,
|
2020-12-24 01:58:27 +00:00
|
|
|
CreatePostLike,
|
2021-09-28 10:38:59 +00:00
|
|
|
CreatePostReport,
|
2020-12-24 01:58:27 +00:00
|
|
|
DeletePost,
|
2023-06-14 12:20:40 +00:00
|
|
|
EditPost,
|
2022-12-14 15:03:18 +00:00
|
|
|
FeaturePost,
|
2022-09-22 15:14:58 +00:00
|
|
|
Language,
|
2020-12-24 01:58:27 +00:00
|
|
|
LockPost,
|
2023-05-11 18:32:32 +00:00
|
|
|
PersonView,
|
2021-07-17 20:42:55 +00:00
|
|
|
PostView,
|
2022-06-23 19:44:05 +00:00
|
|
|
PurgePerson,
|
|
|
|
PurgePost,
|
2021-07-17 20:42:55 +00:00
|
|
|
RemovePost,
|
|
|
|
SavePost,
|
2020-12-24 01:58:27 +00:00
|
|
|
TransferCommunity,
|
2021-02-22 02:39:04 +00:00
|
|
|
} from "lemmy-js-client";
|
2023-06-21 22:28:24 +00:00
|
|
|
import { relTags } from "../../config";
|
2023-06-23 03:48:53 +00:00
|
|
|
import { BanType, PostFormParams, PurgeType } from "../../interfaces";
|
2023-06-21 22:28:24 +00:00
|
|
|
import { mdNoImages, mdToHtml, mdToHtmlInline } from "../../markdown";
|
2023-06-22 00:54:35 +00:00
|
|
|
import { I18NextService, UserService } from "../../services";
|
2023-06-21 22:28:24 +00:00
|
|
|
import { setupTippy } from "../../tippy";
|
2022-06-23 19:44:05 +00:00
|
|
|
import { Icon, PurgeWarning, Spinner } from "../common/icon";
|
2021-07-17 20:42:55 +00:00
|
|
|
import { MomentTime } from "../common/moment-time";
|
|
|
|
import { PictrsImage } from "../common/pictrs-image";
|
2023-06-22 17:36:38 +00:00
|
|
|
import { VoteButtons, VoteButtonsCompact } from "../common/vote-buttons";
|
2021-07-17 20:42:55 +00:00
|
|
|
import { CommunityLink } from "../community/community-link";
|
|
|
|
import { PersonListing } from "../person/person-listing";
|
2021-08-19 15:24:13 +00:00
|
|
|
import { MetadataCard } from "./metadata-card";
|
2021-07-17 20:42:55 +00:00
|
|
|
import { PostForm } from "./post-form";
|
2020-09-06 16:15:25 +00:00
|
|
|
|
|
|
|
interface PostListingState {
|
|
|
|
showEdit: boolean;
|
|
|
|
showRemoveDialog: boolean;
|
2022-06-23 19:44:05 +00:00
|
|
|
showPurgeDialog: boolean;
|
2023-01-04 16:56:24 +00:00
|
|
|
purgeReason?: string;
|
|
|
|
purgeType?: PurgeType;
|
2022-06-23 19:44:05 +00:00
|
|
|
purgeLoading: boolean;
|
2023-01-04 16:56:24 +00:00
|
|
|
removeReason?: string;
|
2020-09-06 16:15:25 +00:00
|
|
|
showBanDialog: boolean;
|
2023-01-04 16:56:24 +00:00
|
|
|
banReason?: string;
|
|
|
|
banExpireDays?: number;
|
|
|
|
banType?: BanType;
|
|
|
|
removeData?: boolean;
|
2020-09-06 16:15:25 +00:00
|
|
|
showConfirmTransferSite: boolean;
|
|
|
|
showConfirmTransferCommunity: boolean;
|
|
|
|
imageExpanded: boolean;
|
|
|
|
viewSource: boolean;
|
|
|
|
showAdvanced: boolean;
|
2020-09-26 16:18:49 +00:00
|
|
|
showMoreMobile: boolean;
|
2021-03-25 16:44:16 +00:00
|
|
|
showBody: boolean;
|
2021-09-28 10:38:59 +00:00
|
|
|
showReportDialog: boolean;
|
2023-01-04 16:56:24 +00:00
|
|
|
reportReason?: string;
|
2023-06-14 12:20:40 +00:00
|
|
|
reportLoading: boolean;
|
|
|
|
blockLoading: boolean;
|
|
|
|
lockLoading: boolean;
|
|
|
|
deleteLoading: boolean;
|
|
|
|
removeLoading: boolean;
|
|
|
|
saveLoading: boolean;
|
|
|
|
featureCommunityLoading: boolean;
|
|
|
|
featureLocalLoading: boolean;
|
|
|
|
banLoading: boolean;
|
|
|
|
addModLoading: boolean;
|
|
|
|
addAdminLoading: boolean;
|
|
|
|
transferLoading: boolean;
|
2020-09-06 16:15:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
interface PostListingProps {
|
2020-12-24 01:58:27 +00:00
|
|
|
post_view: PostView;
|
2023-06-14 12:20:40 +00:00
|
|
|
crossPosts?: PostView[];
|
2023-01-04 16:56:24 +00:00
|
|
|
moderators?: CommunityModeratorView[];
|
2023-05-11 18:32:32 +00:00
|
|
|
admins?: PersonView[];
|
2022-09-22 15:14:58 +00:00
|
|
|
allLanguages: Language[];
|
2022-12-19 15:57:29 +00:00
|
|
|
siteLanguages: number[];
|
2020-09-06 16:15:25 +00:00
|
|
|
showCommunity?: boolean;
|
|
|
|
showBody?: boolean;
|
2022-11-18 02:11:30 +00:00
|
|
|
hideImage?: boolean;
|
2022-06-21 21:42:29 +00:00
|
|
|
enableDownvotes?: boolean;
|
|
|
|
enableNsfw?: boolean;
|
2022-02-02 14:56:43 +00:00
|
|
|
viewOnly?: boolean;
|
2023-06-14 12:20:40 +00:00
|
|
|
onPostEdit(form: EditPost): void;
|
|
|
|
onPostVote(form: CreatePostLike): void;
|
|
|
|
onPostReport(form: CreatePostReport): void;
|
|
|
|
onBlockPerson(form: BlockPerson): void;
|
|
|
|
onLockPost(form: LockPost): void;
|
|
|
|
onDeletePost(form: DeletePost): void;
|
|
|
|
onRemovePost(form: RemovePost): void;
|
|
|
|
onSavePost(form: SavePost): void;
|
|
|
|
onFeaturePost(form: FeaturePost): void;
|
|
|
|
onPurgePerson(form: PurgePerson): void;
|
|
|
|
onPurgePost(form: PurgePost): void;
|
|
|
|
onBanPersonFromCommunity(form: BanFromCommunity): void;
|
|
|
|
onBanPerson(form: BanPerson): void;
|
|
|
|
onAddModToCommunity(form: AddModToCommunity): void;
|
|
|
|
onAddAdmin(form: AddAdmin): void;
|
|
|
|
onTransferCommunity(form: TransferCommunity): void;
|
2020-09-06 16:15:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
export class PostListing extends Component<PostListingProps, PostListingState> {
|
2023-01-04 16:56:24 +00:00
|
|
|
state: PostListingState = {
|
2020-09-06 16:15:25 +00:00
|
|
|
showEdit: false,
|
|
|
|
showRemoveDialog: false,
|
2022-06-23 19:44:05 +00:00
|
|
|
showPurgeDialog: false,
|
|
|
|
purgeType: PurgeType.Person,
|
2020-09-06 16:15:25 +00:00
|
|
|
showBanDialog: false,
|
|
|
|
banType: BanType.Community,
|
2022-04-15 21:22:39 +00:00
|
|
|
removeData: false,
|
2020-09-06 16:15:25 +00:00
|
|
|
showConfirmTransferSite: false,
|
|
|
|
showConfirmTransferCommunity: false,
|
|
|
|
imageExpanded: false,
|
|
|
|
viewSource: false,
|
|
|
|
showAdvanced: false,
|
2020-09-26 16:18:49 +00:00
|
|
|
showMoreMobile: false,
|
2021-03-25 16:44:16 +00:00
|
|
|
showBody: false,
|
2021-09-28 10:38:59 +00:00
|
|
|
showReportDialog: false,
|
2023-06-14 12:20:40 +00:00
|
|
|
purgeLoading: false,
|
|
|
|
reportLoading: false,
|
|
|
|
blockLoading: false,
|
|
|
|
lockLoading: false,
|
|
|
|
deleteLoading: false,
|
|
|
|
removeLoading: false,
|
|
|
|
saveLoading: false,
|
|
|
|
featureCommunityLoading: false,
|
|
|
|
featureLocalLoading: false,
|
|
|
|
banLoading: false,
|
|
|
|
addModLoading: false,
|
|
|
|
addAdminLoading: false,
|
|
|
|
transferLoading: false,
|
2020-09-06 16:15:25 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
constructor(props: any, context: any) {
|
|
|
|
super(props, context);
|
|
|
|
|
|
|
|
this.handleEditPost = this.handleEditPost.bind(this);
|
|
|
|
this.handleEditCancel = this.handleEditCancel.bind(this);
|
|
|
|
}
|
|
|
|
|
|
|
|
componentWillReceiveProps(nextProps: PostListingProps) {
|
2023-06-14 12:20:40 +00:00
|
|
|
if (this.props !== nextProps) {
|
|
|
|
this.setState({
|
|
|
|
purgeLoading: false,
|
|
|
|
reportLoading: false,
|
|
|
|
blockLoading: false,
|
|
|
|
lockLoading: false,
|
|
|
|
deleteLoading: false,
|
|
|
|
removeLoading: false,
|
|
|
|
saveLoading: false,
|
|
|
|
featureCommunityLoading: false,
|
|
|
|
featureLocalLoading: false,
|
|
|
|
banLoading: false,
|
|
|
|
addModLoading: false,
|
|
|
|
addAdminLoading: false,
|
|
|
|
transferLoading: false,
|
|
|
|
imageExpanded: false,
|
|
|
|
});
|
2020-09-06 16:15:25 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-06-14 12:20:40 +00:00
|
|
|
get postView(): PostView {
|
|
|
|
return this.props.post_view;
|
|
|
|
}
|
|
|
|
|
2020-09-06 16:15:25 +00:00
|
|
|
render() {
|
2023-06-14 12:20:40 +00:00
|
|
|
const post = this.postView.post;
|
2023-04-15 14:47:10 +00:00
|
|
|
|
2020-09-06 16:15:25 +00:00
|
|
|
return (
|
2023-06-19 01:36:27 +00:00
|
|
|
<div className="post-listing mt-2">
|
2020-09-06 16:15:25 +00:00
|
|
|
{!this.state.showEdit ? (
|
|
|
|
<>
|
|
|
|
{this.listing()}
|
2022-11-18 02:11:30 +00:00
|
|
|
{this.state.imageExpanded && !this.props.hideImage && this.img}
|
2023-06-14 12:20:40 +00:00
|
|
|
{post.url && this.state.showBody && post.embed_title && (
|
2023-01-04 16:56:24 +00:00
|
|
|
<MetadataCard post={post} />
|
|
|
|
)}
|
2022-06-21 21:42:29 +00:00
|
|
|
{this.showBody && this.body()}
|
2020-09-06 16:15:25 +00:00
|
|
|
</>
|
|
|
|
) : (
|
2023-06-14 12:20:40 +00:00
|
|
|
<PostForm
|
|
|
|
post_view={this.postView}
|
|
|
|
crossPosts={this.props.crossPosts}
|
|
|
|
onEdit={this.handleEditPost}
|
|
|
|
onCancel={this.handleEditCancel}
|
|
|
|
enableNsfw={this.props.enableNsfw}
|
|
|
|
enableDownvotes={this.props.enableDownvotes}
|
|
|
|
allLanguages={this.props.allLanguages}
|
|
|
|
siteLanguages={this.props.siteLanguages}
|
|
|
|
/>
|
2020-09-06 16:15:25 +00:00
|
|
|
)}
|
|
|
|
</div>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
body() {
|
2023-06-14 12:20:40 +00:00
|
|
|
const body = this.postView.post.body;
|
2023-01-04 16:56:24 +00:00
|
|
|
return body ? (
|
2023-06-16 20:27:41 +00:00
|
|
|
<article id="postContent" className="col-12 card my-2 p-2">
|
2023-01-04 16:56:24 +00:00
|
|
|
{this.state.viewSource ? (
|
|
|
|
<pre>{body}</pre>
|
|
|
|
) : (
|
|
|
|
<div className="md-div" dangerouslySetInnerHTML={mdToHtml(body)} />
|
|
|
|
)}
|
2023-06-16 20:27:41 +00:00
|
|
|
</article>
|
2023-01-04 16:56:24 +00:00
|
|
|
) : (
|
|
|
|
<></>
|
|
|
|
);
|
2020-09-06 16:15:25 +00:00
|
|
|
}
|
|
|
|
|
2022-01-12 00:53:23 +00:00
|
|
|
get img() {
|
2023-06-22 18:45:09 +00:00
|
|
|
if (this.imageSrc) {
|
|
|
|
return (
|
|
|
|
<>
|
|
|
|
<div className="offset-sm-3 my-2 d-none d-sm-block">
|
|
|
|
<a href={this.imageSrc} className="d-inline-block">
|
|
|
|
<PictrsImage src={this.imageSrc} />
|
|
|
|
</a>
|
|
|
|
</div>
|
|
|
|
<div className="my-2 d-block d-sm-none">
|
|
|
|
<a
|
|
|
|
className="d-inline-block"
|
|
|
|
onClick={linkEvent(this, this.handleImageExpandClick)}
|
|
|
|
>
|
|
|
|
<PictrsImage src={this.imageSrc} />
|
|
|
|
</a>
|
|
|
|
</div>
|
|
|
|
</>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
const { post } = this.postView;
|
|
|
|
const { url } = post;
|
|
|
|
|
|
|
|
if (url && isVideo(url)) {
|
|
|
|
return (
|
|
|
|
<div className="embed-responsive mt-3">
|
|
|
|
<video muted controls className="embed-responsive-item col-12">
|
|
|
|
<source src={url} type="video/mp4" />
|
|
|
|
</video>
|
2023-01-04 16:56:24 +00:00
|
|
|
</div>
|
2023-06-22 18:45:09 +00:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
return <></>;
|
2022-01-12 00:53:23 +00:00
|
|
|
}
|
|
|
|
|
2020-09-06 16:15:25 +00:00
|
|
|
imgThumb(src: string) {
|
2023-06-14 12:20:40 +00:00
|
|
|
const post_view = this.postView;
|
2020-09-06 16:15:25 +00:00
|
|
|
return (
|
2020-10-14 19:36:37 +00:00
|
|
|
<PictrsImage
|
2020-09-06 16:15:25 +00:00
|
|
|
src={src}
|
2020-10-14 19:36:37 +00:00
|
|
|
thumbnail
|
2021-02-06 20:20:41 +00:00
|
|
|
alt=""
|
2020-12-24 01:58:27 +00:00
|
|
|
nsfw={post_view.post.nsfw || post_view.community.nsfw}
|
2020-09-06 16:15:25 +00:00
|
|
|
/>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2023-01-04 16:56:24 +00:00
|
|
|
get imageSrc(): string | undefined {
|
2023-06-14 12:20:40 +00:00
|
|
|
const post = this.postView.post;
|
2023-06-05 21:31:12 +00:00
|
|
|
const url = post.url;
|
|
|
|
const thumbnail = post.thumbnail_url;
|
2022-06-21 21:42:29 +00:00
|
|
|
|
2023-01-04 16:56:24 +00:00
|
|
|
if (url && isImage(url)) {
|
|
|
|
if (url.includes("pictrs")) {
|
2022-06-21 21:42:29 +00:00
|
|
|
return url;
|
2023-01-04 16:56:24 +00:00
|
|
|
} else if (thumbnail) {
|
2022-06-21 21:42:29 +00:00
|
|
|
return thumbnail;
|
2020-09-06 16:15:25 +00:00
|
|
|
} else {
|
2022-06-21 21:42:29 +00:00
|
|
|
return url;
|
2020-09-06 16:15:25 +00:00
|
|
|
}
|
2023-01-04 16:56:24 +00:00
|
|
|
} else if (thumbnail) {
|
2022-06-21 21:42:29 +00:00
|
|
|
return thumbnail;
|
2020-09-09 00:48:17 +00:00
|
|
|
} else {
|
2023-01-04 16:56:24 +00:00
|
|
|
return undefined;
|
2020-09-06 16:15:25 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
thumbnail() {
|
2023-06-14 12:20:40 +00:00
|
|
|
const post = this.postView.post;
|
2023-06-05 21:31:12 +00:00
|
|
|
const url = post.url;
|
|
|
|
const thumbnail = post.thumbnail_url;
|
2020-09-06 16:15:25 +00:00
|
|
|
|
2023-01-04 16:56:24 +00:00
|
|
|
if (!this.props.hideImage && url && isImage(url) && this.imageSrc) {
|
2020-09-06 16:15:25 +00:00
|
|
|
return (
|
2021-09-19 20:29:03 +00:00
|
|
|
<a
|
2023-01-04 16:56:24 +00:00
|
|
|
href={this.imageSrc}
|
2022-09-22 15:03:35 +00:00
|
|
|
className="text-body d-inline-block position-relative mb-2"
|
2023-06-22 00:54:35 +00:00
|
|
|
data-tippy-content={I18NextService.i18n.t("expand_here")}
|
2020-09-06 16:15:25 +00:00
|
|
|
onClick={linkEvent(this, this.handleImageExpandClick)}
|
2023-06-22 00:54:35 +00:00
|
|
|
aria-label={I18NextService.i18n.t("expand_here")}
|
2020-09-06 16:15:25 +00:00
|
|
|
>
|
2023-01-04 16:56:24 +00:00
|
|
|
{this.imgThumb(this.imageSrc)}
|
2021-02-11 20:35:27 +00:00
|
|
|
<Icon icon="image" classes="mini-overlay" />
|
2021-09-19 20:29:03 +00:00
|
|
|
</a>
|
2020-09-06 16:15:25 +00:00
|
|
|
);
|
2023-01-04 16:56:24 +00:00
|
|
|
} else if (!this.props.hideImage && url && thumbnail && this.imageSrc) {
|
2020-09-06 16:15:25 +00:00
|
|
|
return (
|
|
|
|
<a
|
2022-09-22 15:03:35 +00:00
|
|
|
className="text-body d-inline-block position-relative mb-2"
|
2023-01-04 16:56:24 +00:00
|
|
|
href={url}
|
2022-02-24 15:31:44 +00:00
|
|
|
rel={relTags}
|
2023-01-04 16:56:24 +00:00
|
|
|
title={url}
|
2020-09-06 16:15:25 +00:00
|
|
|
>
|
2023-01-04 16:56:24 +00:00
|
|
|
{this.imgThumb(this.imageSrc)}
|
2021-02-11 20:35:27 +00:00
|
|
|
<Icon icon="external-link" classes="mini-overlay" />
|
2020-09-06 16:15:25 +00:00
|
|
|
</a>
|
|
|
|
);
|
2023-01-04 16:56:24 +00:00
|
|
|
} else if (url) {
|
|
|
|
if (!this.props.hideImage && isVideo(url)) {
|
2020-09-06 16:15:25 +00:00
|
|
|
return (
|
2023-06-22 18:45:09 +00:00
|
|
|
<a
|
|
|
|
className="text-body"
|
|
|
|
href={url}
|
|
|
|
title={url}
|
|
|
|
rel={relTags}
|
|
|
|
data-tippy-content={I18NextService.i18n.t("expand_here")}
|
|
|
|
onClick={linkEvent(this, this.handleImageExpandClick)}
|
|
|
|
aria-label={I18NextService.i18n.t("expand_here")}
|
|
|
|
>
|
|
|
|
<div className="thumbnail rounded bg-light d-flex justify-content-center">
|
|
|
|
<Icon icon="play" classes="d-flex align-items-center" />
|
|
|
|
</div>
|
|
|
|
</a>
|
2020-09-06 16:15:25 +00:00
|
|
|
);
|
|
|
|
} else {
|
|
|
|
return (
|
2023-01-04 16:56:24 +00:00
|
|
|
<a className="text-body" href={url} title={url} rel={relTags}>
|
2022-09-22 15:03:35 +00:00
|
|
|
<div className="thumbnail rounded bg-light d-flex justify-content-center">
|
2021-02-11 20:35:27 +00:00
|
|
|
<Icon icon="external-link" classes="d-flex align-items-center" />
|
2020-09-06 16:15:25 +00:00
|
|
|
</div>
|
|
|
|
</a>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
return (
|
|
|
|
<Link
|
|
|
|
className="text-body"
|
|
|
|
to={`/post/${post.id}`}
|
2023-06-22 00:54:35 +00:00
|
|
|
title={I18NextService.i18n.t("comments")}
|
2020-09-06 16:15:25 +00:00
|
|
|
>
|
2022-09-22 15:03:35 +00:00
|
|
|
<div className="thumbnail rounded bg-light d-flex justify-content-center">
|
2021-02-11 20:35:27 +00:00
|
|
|
<Icon icon="message-square" classes="d-flex align-items-center" />
|
2020-09-06 16:15:25 +00:00
|
|
|
</div>
|
|
|
|
</Link>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
createdLine() {
|
2023-06-14 12:20:40 +00:00
|
|
|
const post_view = this.postView;
|
2020-09-06 16:15:25 +00:00
|
|
|
return (
|
2023-06-21 23:40:24 +00:00
|
|
|
<span className="small">
|
|
|
|
<PersonListing person={post_view.creator} />
|
|
|
|
{this.creatorIsMod_ && (
|
2023-06-22 21:37:10 +00:00
|
|
|
<span className="mx-1 badge text-bg-light">
|
|
|
|
{I18NextService.i18n.t("mod")}
|
|
|
|
</span>
|
2023-06-21 23:40:24 +00:00
|
|
|
)}
|
|
|
|
{this.creatorIsAdmin_ && (
|
2023-06-22 21:37:10 +00:00
|
|
|
<span className="mx-1 badge text-bg-light">
|
|
|
|
{I18NextService.i18n.t("admin")}
|
|
|
|
</span>
|
2023-06-21 23:40:24 +00:00
|
|
|
)}
|
|
|
|
{post_view.creator.bot_account && (
|
|
|
|
<span className="mx-1 badge text-bg-light">
|
2023-06-22 21:37:10 +00:00
|
|
|
{I18NextService.i18n.t("bot_account").toLowerCase()}
|
2023-06-21 23:40:24 +00:00
|
|
|
</span>
|
|
|
|
)}
|
|
|
|
{this.props.showCommunity && (
|
|
|
|
<>
|
|
|
|
{" "}
|
2023-06-22 21:37:10 +00:00
|
|
|
{I18NextService.i18n.t("to")}{" "}
|
|
|
|
<CommunityLink community={post_view.community} />
|
2023-06-21 23:40:24 +00:00
|
|
|
</>
|
|
|
|
)}
|
2023-05-24 10:22:24 +00:00
|
|
|
{post_view.post.language_id !== 0 && (
|
2023-06-20 12:01:29 +00:00
|
|
|
<span className="mx-1 badge text-bg-light">
|
2023-05-23 20:16:54 +00:00
|
|
|
{
|
|
|
|
this.props.allLanguages.find(
|
|
|
|
lang => lang.id === post_view.post.language_id
|
|
|
|
)?.name
|
|
|
|
}
|
|
|
|
</span>
|
2023-06-21 23:40:24 +00:00
|
|
|
)}{" "}
|
|
|
|
•{" "}
|
|
|
|
<MomentTime
|
|
|
|
published={post_view.post.published}
|
|
|
|
updated={post_view.post.updated}
|
|
|
|
/>
|
|
|
|
</span>
|
2020-09-06 16:15:25 +00:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2022-11-19 04:39:32 +00:00
|
|
|
get postLink() {
|
2023-06-14 12:20:40 +00:00
|
|
|
const post = this.postView.post;
|
2022-11-19 04:39:32 +00:00
|
|
|
return (
|
|
|
|
<Link
|
2023-06-18 04:41:47 +00:00
|
|
|
className={`d-inline ${
|
2022-12-14 15:03:18 +00:00
|
|
|
!post.featured_community && !post.featured_local
|
|
|
|
? "text-body"
|
|
|
|
: "text-primary"
|
2023-02-21 20:53:15 +00:00
|
|
|
}`}
|
2022-11-19 04:39:32 +00:00
|
|
|
to={`/post/${post.id}`}
|
2023-06-22 00:54:35 +00:00
|
|
|
title={I18NextService.i18n.t("comments")}
|
2022-11-19 04:39:32 +00:00
|
|
|
>
|
2023-06-18 04:41:47 +00:00
|
|
|
<span
|
|
|
|
className="d-inline"
|
2023-02-21 20:53:15 +00:00
|
|
|
dangerouslySetInnerHTML={mdToHtmlInline(post.name)}
|
|
|
|
/>
|
2022-11-19 04:39:32 +00:00
|
|
|
</Link>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2020-09-06 16:15:25 +00:00
|
|
|
postTitleLine() {
|
2023-06-14 12:20:40 +00:00
|
|
|
const post = this.postView.post;
|
2023-06-05 21:31:12 +00:00
|
|
|
const url = post.url;
|
2023-01-04 16:56:24 +00:00
|
|
|
|
2020-09-06 16:15:25 +00:00
|
|
|
return (
|
2023-06-19 15:26:29 +00:00
|
|
|
<>
|
|
|
|
<div className="post-title overflow-hidden">
|
|
|
|
<h5 className="d-inline">
|
|
|
|
{url && this.props.showBody ? (
|
|
|
|
<a
|
|
|
|
className={
|
|
|
|
!post.featured_community && !post.featured_local
|
|
|
|
? "text-body"
|
|
|
|
: "text-primary"
|
|
|
|
}
|
|
|
|
href={url}
|
|
|
|
title={url}
|
|
|
|
rel={relTags}
|
|
|
|
dangerouslySetInnerHTML={mdToHtmlInline(post.name)}
|
|
|
|
></a>
|
|
|
|
) : (
|
|
|
|
this.postLink
|
|
|
|
)}
|
|
|
|
</h5>
|
|
|
|
{(url && isImage(url)) ||
|
|
|
|
(post.thumbnail_url && (
|
|
|
|
<button
|
2023-06-20 04:35:50 +00:00
|
|
|
className="btn btn-sm text-monospace text-muted d-inline-block"
|
2023-06-22 00:54:35 +00:00
|
|
|
data-tippy-content={I18NextService.i18n.t("expand_here")}
|
2023-06-19 15:26:29 +00:00
|
|
|
onClick={linkEvent(this, this.handleImageExpandClick)}
|
|
|
|
>
|
|
|
|
<Icon
|
|
|
|
icon={
|
|
|
|
!this.state.imageExpanded ? "plus-square" : "minus-square"
|
|
|
|
}
|
|
|
|
classes="icon-inline"
|
|
|
|
/>
|
|
|
|
</button>
|
|
|
|
))}
|
|
|
|
{post.removed && (
|
2023-06-20 12:01:29 +00:00
|
|
|
<small className="ms-2 badge text-bg-secondary">
|
2023-06-22 00:54:35 +00:00
|
|
|
{I18NextService.i18n.t("removed")}
|
2023-06-19 15:26:29 +00:00
|
|
|
</small>
|
2022-01-12 00:53:23 +00:00
|
|
|
)}
|
2023-06-19 15:26:29 +00:00
|
|
|
{post.deleted && (
|
|
|
|
<small
|
2023-06-20 12:01:29 +00:00
|
|
|
className="unselectable pointer ms-2 text-muted font-italic"
|
2023-06-22 00:54:35 +00:00
|
|
|
data-tippy-content={I18NextService.i18n.t("deleted")}
|
2023-06-17 16:32:12 +00:00
|
|
|
>
|
2023-06-19 15:26:29 +00:00
|
|
|
<Icon icon="trash" classes="icon-inline text-danger" />
|
|
|
|
</small>
|
|
|
|
)}
|
|
|
|
{post.locked && (
|
|
|
|
<small
|
2023-06-20 12:01:29 +00:00
|
|
|
className="unselectable pointer ms-2 text-muted font-italic"
|
2023-06-22 00:54:35 +00:00
|
|
|
data-tippy-content={I18NextService.i18n.t("locked")}
|
2023-06-19 15:26:29 +00:00
|
|
|
>
|
|
|
|
<Icon icon="lock" classes="icon-inline text-danger" />
|
|
|
|
</small>
|
|
|
|
)}
|
|
|
|
{post.featured_community && (
|
|
|
|
<small
|
2023-06-20 12:01:29 +00:00
|
|
|
className="unselectable pointer ms-2 text-muted font-italic"
|
2023-06-22 00:54:35 +00:00
|
|
|
data-tippy-content={I18NextService.i18n.t(
|
|
|
|
"featured_in_community"
|
|
|
|
)}
|
|
|
|
aria-label={I18NextService.i18n.t("featured_in_community")}
|
2023-06-19 15:26:29 +00:00
|
|
|
>
|
|
|
|
<Icon icon="pin" classes="icon-inline text-primary" />
|
|
|
|
</small>
|
|
|
|
)}
|
|
|
|
{post.featured_local && (
|
|
|
|
<small
|
2023-06-20 12:01:29 +00:00
|
|
|
className="unselectable pointer ms-2 text-muted font-italic"
|
2023-06-22 00:54:35 +00:00
|
|
|
data-tippy-content={I18NextService.i18n.t("featured_in_local")}
|
|
|
|
aria-label={I18NextService.i18n.t("featured_in_local")}
|
2023-06-19 15:26:29 +00:00
|
|
|
>
|
|
|
|
<Icon icon="pin" classes="icon-inline text-secondary" />
|
|
|
|
</small>
|
|
|
|
)}
|
|
|
|
{post.nsfw && (
|
2023-06-20 12:01:29 +00:00
|
|
|
<small className="ms-2 badge text-bg-danger">
|
2023-06-22 00:54:35 +00:00
|
|
|
{I18NextService.i18n.t("nsfw")}
|
2023-06-19 15:26:29 +00:00
|
|
|
</small>
|
|
|
|
)}
|
|
|
|
</div>
|
|
|
|
{url && this.urlLine()}
|
|
|
|
</>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
urlLine() {
|
|
|
|
const post = this.postView.post;
|
|
|
|
const url = post.url;
|
|
|
|
|
|
|
|
return (
|
|
|
|
<p className="d-flex text-muted align-items-center gap-1 small m-0">
|
|
|
|
{url && !(hostname(url) === getExternalHost()) && (
|
|
|
|
<a
|
|
|
|
className="text-muted font-italic"
|
|
|
|
href={url}
|
|
|
|
title={url}
|
|
|
|
rel={relTags}
|
2023-06-17 16:32:12 +00:00
|
|
|
>
|
2023-06-19 15:26:29 +00:00
|
|
|
{hostname(url)}
|
|
|
|
</a>
|
2023-06-17 16:32:12 +00:00
|
|
|
)}
|
2023-06-19 15:26:29 +00:00
|
|
|
</p>
|
2020-09-06 16:15:25 +00:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
duplicatesLine() {
|
2023-06-14 12:20:40 +00:00
|
|
|
const dupes = this.props.crossPosts;
|
2023-01-04 16:56:24 +00:00
|
|
|
return dupes && dupes.length > 0 ? (
|
|
|
|
<ul className="list-inline mb-1 small text-muted">
|
|
|
|
<>
|
2023-06-22 00:54:35 +00:00
|
|
|
<li className="list-inline-item me-2">
|
|
|
|
{I18NextService.i18n.t("cross_posted_to")}
|
|
|
|
</li>
|
2023-01-04 16:56:24 +00:00
|
|
|
{dupes.map(pv => (
|
2023-06-20 12:01:29 +00:00
|
|
|
<li key={pv.post.id} className="list-inline-item me-2">
|
2023-01-04 16:56:24 +00:00
|
|
|
<Link to={`/post/${pv.post.id}`}>
|
|
|
|
{pv.community.local
|
|
|
|
? pv.community.name
|
|
|
|
: `${pv.community.name}@${hostname(pv.community.actor_id)}`}
|
|
|
|
</Link>
|
|
|
|
</li>
|
|
|
|
))}
|
|
|
|
</>
|
|
|
|
</ul>
|
|
|
|
) : (
|
|
|
|
<></>
|
|
|
|
);
|
2020-09-06 16:15:25 +00:00
|
|
|
}
|
|
|
|
|
2022-01-12 00:53:23 +00:00
|
|
|
commentsLine(mobile = false) {
|
2023-06-14 12:20:40 +00:00
|
|
|
const post = this.postView.post;
|
2023-05-21 18:17:56 +00:00
|
|
|
|
2022-01-12 00:53:23 +00:00
|
|
|
return (
|
2023-06-20 04:35:50 +00:00
|
|
|
<div className="d-flex align-items-center justify-content-start flex-wrap text-muted">
|
2022-01-12 00:53:23 +00:00
|
|
|
{this.commentsButton}
|
2023-05-21 18:17:56 +00:00
|
|
|
{canShare() && (
|
|
|
|
<button
|
2023-06-20 04:35:50 +00:00
|
|
|
className="btn btn-sm btn-animate text-muted py-0"
|
2023-05-21 18:17:56 +00:00
|
|
|
onClick={linkEvent(this, this.handleShare)}
|
|
|
|
type="button"
|
|
|
|
>
|
|
|
|
<Icon icon="share" inline />
|
|
|
|
</button>
|
|
|
|
)}
|
2022-02-17 18:28:43 +00:00
|
|
|
{!post.local && (
|
|
|
|
<a
|
2023-06-20 04:35:50 +00:00
|
|
|
className="btn btn-sm btn-animate text-muted py-0"
|
2023-06-22 00:54:35 +00:00
|
|
|
title={I18NextService.i18n.t("link")}
|
2022-02-17 18:28:43 +00:00
|
|
|
href={post.ap_id}
|
|
|
|
>
|
|
|
|
<Icon icon="fedilink" inline />
|
|
|
|
</a>
|
|
|
|
)}
|
2023-06-22 17:36:38 +00:00
|
|
|
{mobile && !this.props.viewOnly && (
|
|
|
|
<VoteButtonsCompact
|
2023-06-23 03:48:53 +00:00
|
|
|
id={this.postView.post.id}
|
|
|
|
onVote={this.props.onPostVote}
|
2023-06-22 17:36:38 +00:00
|
|
|
enableDownvotes={this.props.enableDownvotes}
|
|
|
|
counts={this.postView.counts}
|
|
|
|
my_vote={this.postView.my_vote}
|
|
|
|
/>
|
|
|
|
)}
|
2023-01-04 16:56:24 +00:00
|
|
|
{UserService.Instance.myUserInfo &&
|
2022-02-02 14:56:43 +00:00
|
|
|
!this.props.viewOnly &&
|
2023-06-17 22:17:22 +00:00
|
|
|
this.postActions()}
|
2022-01-12 00:53:23 +00:00
|
|
|
</div>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2023-06-19 15:26:29 +00:00
|
|
|
showPreviewButton() {
|
|
|
|
const post_view = this.postView;
|
|
|
|
const body = post_view.post.body;
|
|
|
|
|
2023-06-17 22:03:12 +00:00
|
|
|
return (
|
2023-06-19 15:26:29 +00:00
|
|
|
<button
|
2023-06-20 04:35:50 +00:00
|
|
|
className="btn btn-sm btn-animate text-muted py-0"
|
2023-06-19 15:26:29 +00:00
|
|
|
data-tippy-content={body && mdNoImages.render(body)}
|
|
|
|
data-tippy-allowHtml={true}
|
|
|
|
onClick={linkEvent(this, this.handleShowBody)}
|
|
|
|
>
|
|
|
|
<Icon
|
|
|
|
icon="book-open"
|
2023-06-20 12:01:29 +00:00
|
|
|
classes={classNames("icon-inline me-1", {
|
2023-06-19 15:26:29 +00:00
|
|
|
"text-success": this.state.showBody,
|
|
|
|
})}
|
|
|
|
/>
|
|
|
|
</button>
|
2023-06-17 22:03:12 +00:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2023-06-17 22:17:22 +00:00
|
|
|
postActions() {
|
2022-01-12 00:53:23 +00:00
|
|
|
// Possible enhancement: Priority+ pattern instead of just hard coding which get hidden behind the show more button.
|
|
|
|
// Possible enhancement: Make each button a component.
|
2023-06-14 12:20:40 +00:00
|
|
|
const post_view = this.postView;
|
2023-06-19 15:26:29 +00:00
|
|
|
const post = post_view.post;
|
|
|
|
|
2020-09-06 16:15:25 +00:00
|
|
|
return (
|
2022-01-12 00:53:23 +00:00
|
|
|
<>
|
|
|
|
{this.saveButton}
|
2023-06-22 21:32:24 +00:00
|
|
|
{this.crossPostButton}
|
2023-06-17 22:03:12 +00:00
|
|
|
|
2023-06-19 15:26:29 +00:00
|
|
|
{/**
|
|
|
|
* If there is a URL, or if the post has a body and we were told not to
|
|
|
|
* show the body, show the MetadataCard/body toggle.
|
|
|
|
*/}
|
|
|
|
{(post.url || (post.body && !this.props.showBody)) &&
|
|
|
|
this.showPreviewButton()}
|
|
|
|
|
2023-06-17 22:03:12 +00:00
|
|
|
{this.showBody && post_view.post.body && this.viewSourceButton}
|
|
|
|
|
2023-06-19 19:56:55 +00:00
|
|
|
<div className="dropdown">
|
|
|
|
<button
|
2023-06-20 04:35:50 +00:00
|
|
|
className="btn btn-sm btn-animate text-muted py-0 dropdown-toggle"
|
2023-06-19 19:56:55 +00:00
|
|
|
onClick={linkEvent(this, this.handleShowAdvanced)}
|
2023-06-22 00:54:35 +00:00
|
|
|
data-tippy-content={I18NextService.i18n.t("more")}
|
2023-06-19 19:56:55 +00:00
|
|
|
data-bs-toggle="dropdown"
|
|
|
|
aria-expanded="false"
|
|
|
|
aria-controls="advancedButtonsDropdown"
|
2023-06-22 00:54:35 +00:00
|
|
|
aria-label={I18NextService.i18n.t("more")}
|
2023-06-19 19:56:55 +00:00
|
|
|
>
|
|
|
|
<Icon icon="more-vertical" inline />
|
|
|
|
</button>
|
|
|
|
|
|
|
|
<ul className="dropdown-menu" id="advancedButtonsDropdown">
|
|
|
|
{!this.myPost ? (
|
|
|
|
<>
|
|
|
|
<li>{this.reportButton}</li>
|
|
|
|
<li>{this.blockButton}</li>
|
|
|
|
</>
|
|
|
|
) : (
|
|
|
|
<>
|
|
|
|
<li>{this.editButton}</li>
|
|
|
|
<li>{this.deleteButton}</li>
|
|
|
|
</>
|
|
|
|
)}
|
|
|
|
|
|
|
|
{/* Any mod can do these, not limited to hierarchy*/}
|
|
|
|
{(amMod(this.props.moderators) || amAdmin()) && (
|
|
|
|
<>
|
|
|
|
<li>
|
|
|
|
<hr className="dropdown-divider" />
|
|
|
|
</li>
|
|
|
|
<li>{this.lockButton}</li>
|
|
|
|
{this.featureButtons}
|
|
|
|
</>
|
|
|
|
)}
|
|
|
|
|
|
|
|
{(this.canMod_ || this.canAdmin_) && (
|
|
|
|
<li>{this.modRemoveButton}</li>
|
|
|
|
)}
|
|
|
|
</ul>
|
|
|
|
</div>
|
2022-01-12 00:53:23 +00:00
|
|
|
</>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
get commentsButton() {
|
2023-06-14 12:20:40 +00:00
|
|
|
const post_view = this.postView;
|
2023-06-22 00:54:35 +00:00
|
|
|
const title = I18NextService.i18n.t("number_of_comments", {
|
2023-06-20 23:53:55 +00:00
|
|
|
count: Number(post_view.counts.comments),
|
|
|
|
formattedCount: Number(post_view.counts.comments),
|
|
|
|
});
|
|
|
|
|
2022-01-12 00:53:23 +00:00
|
|
|
return (
|
2023-06-12 08:30:37 +00:00
|
|
|
<Link
|
2023-06-20 23:53:55 +00:00
|
|
|
className="btn btn-link btn-sm text-muted ps-0"
|
|
|
|
title={title}
|
2023-06-12 08:30:37 +00:00
|
|
|
to={`/post/${post_view.post.id}?scrollToComments=true`}
|
2023-06-20 23:53:55 +00:00
|
|
|
data-tippy-content={title}
|
2023-06-12 08:30:37 +00:00
|
|
|
>
|
2023-06-21 23:40:24 +00:00
|
|
|
<Icon icon="message-square" classes="me-1" inline />
|
|
|
|
{post_view.counts.comments}
|
2023-06-12 08:30:37 +00:00
|
|
|
{this.unreadCount && (
|
2023-06-21 19:02:23 +00:00
|
|
|
<span className="text-muted fst-italic">
|
2023-06-22 00:54:35 +00:00
|
|
|
({this.unreadCount} {I18NextService.i18n.t("new")})
|
2022-09-27 19:42:24 +00:00
|
|
|
</span>
|
2023-06-12 08:30:37 +00:00
|
|
|
)}
|
|
|
|
</Link>
|
2022-01-12 00:53:23 +00:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2023-05-15 19:53:29 +00:00
|
|
|
get unreadCount(): number | undefined {
|
2023-06-14 12:20:40 +00:00
|
|
|
const pv = this.postView;
|
2023-05-15 19:53:29 +00:00
|
|
|
return pv.unread_comments == pv.counts.comments || pv.unread_comments == 0
|
2023-01-04 16:56:24 +00:00
|
|
|
? undefined
|
|
|
|
: pv.unread_comments;
|
2022-09-27 19:42:24 +00:00
|
|
|
}
|
|
|
|
|
2022-01-12 00:53:23 +00:00
|
|
|
get saveButton() {
|
2023-06-14 12:20:40 +00:00
|
|
|
const saved = this.postView.saved;
|
2023-06-22 00:54:35 +00:00
|
|
|
const label = saved
|
|
|
|
? I18NextService.i18n.t("unsave")
|
|
|
|
: I18NextService.i18n.t("save");
|
2022-01-12 00:53:23 +00:00
|
|
|
return (
|
|
|
|
<button
|
2023-06-20 04:35:50 +00:00
|
|
|
className="btn btn-sm btn-animate text-muted py-0"
|
2022-01-12 00:53:23 +00:00
|
|
|
onClick={linkEvent(this, this.handleSavePostClick)}
|
|
|
|
data-tippy-content={label}
|
|
|
|
aria-label={label}
|
|
|
|
>
|
2023-06-14 12:20:40 +00:00
|
|
|
{this.state.saveLoading ? (
|
|
|
|
<Spinner />
|
|
|
|
) : (
|
|
|
|
<Icon
|
|
|
|
icon="star"
|
|
|
|
classes={classNames({ "text-warning": saved })}
|
|
|
|
inline
|
|
|
|
/>
|
|
|
|
)}
|
2022-01-12 00:53:23 +00:00
|
|
|
</button>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
get crossPostButton() {
|
|
|
|
return (
|
|
|
|
<Link
|
2023-06-22 21:32:24 +00:00
|
|
|
className="btn btn-sm btn-animate text-muted py-0"
|
2023-04-15 14:47:10 +00:00
|
|
|
to={{
|
|
|
|
/* Empty string properties are required to satisfy type*/
|
|
|
|
pathname: "/create_post",
|
|
|
|
state: { ...this.crossPostParams },
|
|
|
|
hash: "",
|
|
|
|
key: "",
|
|
|
|
search: "",
|
|
|
|
}}
|
2023-06-22 00:54:35 +00:00
|
|
|
title={I18NextService.i18n.t("cross_post")}
|
|
|
|
data-tippy-content={I18NextService.i18n.t("cross_post")}
|
|
|
|
aria-label={I18NextService.i18n.t("cross_post")}
|
2022-01-12 00:53:23 +00:00
|
|
|
>
|
2023-06-22 21:30:48 +00:00
|
|
|
<Icon icon="copy" inline />
|
2022-01-12 00:53:23 +00:00
|
|
|
</Link>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
get reportButton() {
|
|
|
|
return (
|
|
|
|
<button
|
2023-06-18 01:09:43 +00:00
|
|
|
className="btn btn-link btn-sm d-flex align-items-center rounded-0 dropdown-item"
|
2022-01-12 00:53:23 +00:00
|
|
|
onClick={linkEvent(this, this.handleShowReportDialog)}
|
2023-06-22 00:54:35 +00:00
|
|
|
aria-label={I18NextService.i18n.t("show_report_dialog")}
|
2022-01-12 00:53:23 +00:00
|
|
|
>
|
2023-06-20 12:01:29 +00:00
|
|
|
<Icon classes="me-1" icon="flag" inline />
|
2023-06-22 00:54:35 +00:00
|
|
|
{I18NextService.i18n.t("create_report")}
|
2022-01-12 00:53:23 +00:00
|
|
|
</button>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
get blockButton() {
|
|
|
|
return (
|
|
|
|
<button
|
2023-06-18 01:09:43 +00:00
|
|
|
className="btn btn-link btn-sm d-flex align-items-center rounded-0 dropdown-item"
|
2023-06-14 12:20:40 +00:00
|
|
|
onClick={linkEvent(this, this.handleBlockPersonClick)}
|
2023-06-22 00:54:35 +00:00
|
|
|
aria-label={I18NextService.i18n.t("block_user")}
|
2022-01-12 00:53:23 +00:00
|
|
|
>
|
2023-06-18 20:02:55 +00:00
|
|
|
{this.state.blockLoading ? (
|
|
|
|
<Spinner />
|
|
|
|
) : (
|
2023-06-20 12:01:29 +00:00
|
|
|
<Icon classes="me-1" icon="slash" inline />
|
2023-06-18 20:02:55 +00:00
|
|
|
)}
|
2023-06-22 00:54:35 +00:00
|
|
|
{I18NextService.i18n.t("block_user")}
|
2022-01-12 00:53:23 +00:00
|
|
|
</button>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
get editButton() {
|
|
|
|
return (
|
|
|
|
<button
|
2023-06-18 01:09:43 +00:00
|
|
|
className="btn btn-link btn-sm d-flex align-items-center rounded-0 dropdown-item"
|
2022-01-12 00:53:23 +00:00
|
|
|
onClick={linkEvent(this, this.handleEditClick)}
|
2023-06-22 00:54:35 +00:00
|
|
|
aria-label={I18NextService.i18n.t("edit")}
|
2022-01-12 00:53:23 +00:00
|
|
|
>
|
2023-06-20 12:01:29 +00:00
|
|
|
<Icon classes="me-1" icon="edit" inline />
|
2023-06-22 00:54:35 +00:00
|
|
|
{I18NextService.i18n.t("edit")}
|
2022-01-12 00:53:23 +00:00
|
|
|
</button>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
get deleteButton() {
|
2023-06-14 12:20:40 +00:00
|
|
|
const deleted = this.postView.post.deleted;
|
2023-06-22 00:54:35 +00:00
|
|
|
const label = !deleted
|
|
|
|
? I18NextService.i18n.t("delete")
|
|
|
|
: I18NextService.i18n.t("restore");
|
2022-01-12 00:53:23 +00:00
|
|
|
return (
|
|
|
|
<button
|
2023-06-18 01:09:43 +00:00
|
|
|
className="btn btn-link btn-sm d-flex align-items-center rounded-0 dropdown-item"
|
2022-01-12 00:53:23 +00:00
|
|
|
onClick={linkEvent(this, this.handleDeleteClick)}
|
|
|
|
>
|
2023-06-14 12:20:40 +00:00
|
|
|
{this.state.deleteLoading ? (
|
|
|
|
<Spinner />
|
|
|
|
) : (
|
2023-06-17 22:03:12 +00:00
|
|
|
<>
|
|
|
|
<Icon
|
|
|
|
icon="trash"
|
2023-06-20 12:01:29 +00:00
|
|
|
classes={classNames("me-1", { "text-danger": deleted })}
|
2023-06-17 22:03:12 +00:00
|
|
|
inline
|
|
|
|
/>
|
2023-06-17 22:28:35 +00:00
|
|
|
{label}
|
2023-06-17 22:03:12 +00:00
|
|
|
</>
|
2023-06-14 12:20:40 +00:00
|
|
|
)}
|
2022-01-12 00:53:23 +00:00
|
|
|
</button>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
get viewSourceButton() {
|
|
|
|
return (
|
|
|
|
<button
|
2023-06-20 04:35:50 +00:00
|
|
|
className="btn btn-sm btn-animate text-muted py-0"
|
2022-01-12 00:53:23 +00:00
|
|
|
onClick={linkEvent(this, this.handleViewSource)}
|
2023-06-22 00:54:35 +00:00
|
|
|
data-tippy-content={I18NextService.i18n.t("view_source")}
|
|
|
|
aria-label={I18NextService.i18n.t("view_source")}
|
2022-01-12 00:53:23 +00:00
|
|
|
>
|
|
|
|
<Icon
|
|
|
|
icon="file-text"
|
|
|
|
classes={classNames({ "text-success": this.state.viewSource })}
|
|
|
|
inline
|
|
|
|
/>
|
|
|
|
</button>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
get lockButton() {
|
2023-06-14 12:20:40 +00:00
|
|
|
const locked = this.postView.post.locked;
|
2023-06-22 00:54:35 +00:00
|
|
|
const label = locked
|
|
|
|
? I18NextService.i18n.t("unlock")
|
|
|
|
: I18NextService.i18n.t("lock");
|
2022-01-12 00:53:23 +00:00
|
|
|
return (
|
|
|
|
<button
|
2023-06-18 01:09:43 +00:00
|
|
|
className="btn btn-link btn-sm d-flex align-items-center rounded-0 dropdown-item"
|
2022-01-12 00:53:23 +00:00
|
|
|
onClick={linkEvent(this, this.handleModLock)}
|
|
|
|
aria-label={label}
|
|
|
|
>
|
2023-06-14 12:20:40 +00:00
|
|
|
{this.state.lockLoading ? (
|
|
|
|
<Spinner />
|
|
|
|
) : (
|
2023-06-17 22:03:12 +00:00
|
|
|
<>
|
|
|
|
<Icon
|
|
|
|
icon="lock"
|
2023-06-20 12:01:29 +00:00
|
|
|
classes={classNames("me-1", { "text-danger": locked })}
|
2023-06-17 22:03:12 +00:00
|
|
|
inline
|
|
|
|
/>
|
2023-06-22 12:58:51 +00:00
|
|
|
{capitalizeFirstLetter(label)}
|
2023-06-17 22:03:12 +00:00
|
|
|
</>
|
2023-06-14 12:20:40 +00:00
|
|
|
)}
|
2022-01-12 00:53:23 +00:00
|
|
|
</button>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2023-06-17 22:03:12 +00:00
|
|
|
get featureButtons() {
|
2023-06-14 12:20:40 +00:00
|
|
|
const featuredCommunity = this.postView.post.featured_community;
|
2023-02-21 20:53:51 +00:00
|
|
|
const labelCommunity = featuredCommunity
|
2023-06-22 00:54:35 +00:00
|
|
|
? I18NextService.i18n.t("unfeature_from_community")
|
|
|
|
: I18NextService.i18n.t("feature_in_community");
|
2022-12-14 15:03:18 +00:00
|
|
|
|
2023-06-14 12:20:40 +00:00
|
|
|
const featuredLocal = this.postView.post.featured_local;
|
2023-02-21 20:53:51 +00:00
|
|
|
const labelLocal = featuredLocal
|
2023-06-22 00:54:35 +00:00
|
|
|
? I18NextService.i18n.t("unfeature_from_local")
|
|
|
|
: I18NextService.i18n.t("feature_in_local");
|
2022-01-12 00:53:23 +00:00
|
|
|
return (
|
2023-06-17 22:03:12 +00:00
|
|
|
<>
|
|
|
|
<li>
|
2022-12-14 15:03:18 +00:00
|
|
|
<button
|
2023-06-18 01:09:43 +00:00
|
|
|
className="btn btn-link btn-sm d-flex align-items-center rounded-0 dropdown-item"
|
2023-06-17 22:03:12 +00:00
|
|
|
onClick={linkEvent(this, this.handleModFeaturePostCommunity)}
|
|
|
|
data-tippy-content={labelCommunity}
|
|
|
|
aria-label={labelCommunity}
|
2022-12-14 15:03:18 +00:00
|
|
|
>
|
2023-06-17 22:03:12 +00:00
|
|
|
{this.state.featureCommunityLoading ? (
|
2023-06-14 12:20:40 +00:00
|
|
|
<Spinner />
|
|
|
|
) : (
|
2023-06-17 22:03:12 +00:00
|
|
|
<>
|
2023-06-14 12:20:40 +00:00
|
|
|
<Icon
|
|
|
|
icon="pin"
|
2023-06-20 12:01:29 +00:00
|
|
|
classes={classNames("me-1", {
|
2023-06-17 22:03:12 +00:00
|
|
|
"text-success": featuredCommunity,
|
|
|
|
})}
|
2023-06-14 12:20:40 +00:00
|
|
|
inline
|
|
|
|
/>
|
2023-06-22 00:54:35 +00:00
|
|
|
{I18NextService.i18n.t("community")}
|
2023-06-17 22:03:12 +00:00
|
|
|
</>
|
2023-06-14 12:20:40 +00:00
|
|
|
)}
|
2022-12-14 15:03:18 +00:00
|
|
|
</button>
|
2023-06-17 22:03:12 +00:00
|
|
|
</li>
|
|
|
|
<li>
|
|
|
|
{amAdmin() && (
|
|
|
|
<button
|
2023-06-18 01:09:43 +00:00
|
|
|
className="btn btn-link btn-sm d-flex align-items-center rounded-0 dropdown-item"
|
2023-06-17 22:03:12 +00:00
|
|
|
onClick={linkEvent(this, this.handleModFeaturePostLocal)}
|
|
|
|
data-tippy-content={labelLocal}
|
|
|
|
aria-label={labelLocal}
|
|
|
|
>
|
|
|
|
{this.state.featureLocalLoading ? (
|
|
|
|
<Spinner />
|
|
|
|
) : (
|
|
|
|
<>
|
|
|
|
<Icon
|
|
|
|
icon="pin"
|
2023-06-20 12:01:29 +00:00
|
|
|
classes={classNames("me-1", {
|
2023-06-17 22:03:12 +00:00
|
|
|
"text-success": featuredLocal,
|
|
|
|
})}
|
|
|
|
inline
|
|
|
|
/>
|
2023-06-22 00:54:35 +00:00
|
|
|
{I18NextService.i18n.t("local")}
|
2023-06-17 22:03:12 +00:00
|
|
|
</>
|
|
|
|
)}
|
|
|
|
</button>
|
|
|
|
)}
|
|
|
|
</li>
|
|
|
|
</>
|
2022-01-12 00:53:23 +00:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
get modRemoveButton() {
|
2023-06-14 12:20:40 +00:00
|
|
|
const removed = this.postView.post.removed;
|
2022-01-12 00:53:23 +00:00
|
|
|
return (
|
|
|
|
<button
|
2023-06-18 01:09:43 +00:00
|
|
|
className="btn btn-link btn-sm d-flex align-items-center rounded-0 dropdown-item"
|
2022-01-12 00:53:23 +00:00
|
|
|
onClick={linkEvent(
|
|
|
|
this,
|
|
|
|
!removed ? this.handleModRemoveShow : this.handleModRemoveSubmit
|
|
|
|
)}
|
|
|
|
>
|
|
|
|
{/* TODO: Find an icon for this. */}
|
2023-06-14 12:20:40 +00:00
|
|
|
{this.state.removeLoading ? (
|
|
|
|
<Spinner />
|
|
|
|
) : !removed ? (
|
2023-06-22 00:54:35 +00:00
|
|
|
I18NextService.i18n.t("remove")
|
2023-06-14 12:20:40 +00:00
|
|
|
) : (
|
2023-06-22 00:54:35 +00:00
|
|
|
I18NextService.i18n.t("restore")
|
2023-06-14 12:20:40 +00:00
|
|
|
)}
|
2022-01-12 00:53:23 +00:00
|
|
|
</button>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Mod/Admin actions to be taken against the author.
|
|
|
|
*/
|
|
|
|
userActionsLine() {
|
|
|
|
// TODO: make nicer
|
2023-06-14 12:20:40 +00:00
|
|
|
const post_view = this.postView;
|
2022-01-12 00:53:23 +00:00
|
|
|
return (
|
|
|
|
this.state.showAdvanced && (
|
2023-06-21 23:40:24 +00:00
|
|
|
<div className="mt-3">
|
2022-06-21 21:42:29 +00:00
|
|
|
{this.canMod_ && (
|
2022-01-12 00:53:23 +00:00
|
|
|
<>
|
2022-06-21 21:42:29 +00:00
|
|
|
{!this.creatorIsMod_ &&
|
2022-01-12 00:53:23 +00:00
|
|
|
(!post_view.creator_banned_from_community ? (
|
2021-09-28 10:38:59 +00:00
|
|
|
<button
|
2022-09-22 15:03:35 +00:00
|
|
|
className="btn btn-link btn-animate text-muted py-0"
|
2022-01-12 00:53:23 +00:00
|
|
|
onClick={linkEvent(
|
|
|
|
this,
|
|
|
|
this.handleModBanFromCommunityShow
|
|
|
|
)}
|
2023-06-22 00:54:35 +00:00
|
|
|
aria-label={I18NextService.i18n.t("ban_from_community")}
|
2021-09-28 10:38:59 +00:00
|
|
|
>
|
2023-06-22 00:54:35 +00:00
|
|
|
{I18NextService.i18n.t("ban_from_community")}
|
2021-09-28 10:38:59 +00:00
|
|
|
</button>
|
2022-01-12 00:53:23 +00:00
|
|
|
) : (
|
2021-09-28 10:38:59 +00:00
|
|
|
<button
|
2022-09-22 15:03:35 +00:00
|
|
|
className="btn btn-link btn-animate text-muted py-0"
|
2022-01-12 00:53:23 +00:00
|
|
|
onClick={linkEvent(
|
|
|
|
this,
|
|
|
|
this.handleModBanFromCommunitySubmit
|
|
|
|
)}
|
2023-06-22 00:54:35 +00:00
|
|
|
aria-label={I18NextService.i18n.t("unban")}
|
2021-09-28 10:38:59 +00:00
|
|
|
>
|
2023-06-22 00:54:35 +00:00
|
|
|
{this.state.banLoading ? (
|
|
|
|
<Spinner />
|
|
|
|
) : (
|
|
|
|
I18NextService.i18n.t("unban")
|
|
|
|
)}
|
2021-09-28 10:38:59 +00:00
|
|
|
</button>
|
2022-01-12 00:53:23 +00:00
|
|
|
))}
|
|
|
|
{!post_view.creator_banned_from_community && (
|
|
|
|
<button
|
2022-09-22 15:03:35 +00:00
|
|
|
className="btn btn-link btn-animate text-muted py-0"
|
2022-01-12 00:53:23 +00:00
|
|
|
onClick={linkEvent(this, this.handleAddModToCommunity)}
|
|
|
|
aria-label={
|
2022-06-21 21:42:29 +00:00
|
|
|
this.creatorIsMod_
|
2023-06-22 00:54:35 +00:00
|
|
|
? I18NextService.i18n.t("remove_as_mod")
|
|
|
|
: I18NextService.i18n.t("appoint_as_mod")
|
2022-01-12 00:53:23 +00:00
|
|
|
}
|
|
|
|
>
|
2023-06-14 12:20:40 +00:00
|
|
|
{this.state.addModLoading ? (
|
|
|
|
<Spinner />
|
|
|
|
) : this.creatorIsMod_ ? (
|
2023-06-22 00:54:35 +00:00
|
|
|
I18NextService.i18n.t("remove_as_mod")
|
2023-06-14 12:20:40 +00:00
|
|
|
) : (
|
2023-06-22 00:54:35 +00:00
|
|
|
I18NextService.i18n.t("appoint_as_mod")
|
2023-06-14 12:20:40 +00:00
|
|
|
)}
|
2022-01-12 00:53:23 +00:00
|
|
|
</button>
|
2021-08-20 02:56:18 +00:00
|
|
|
)}
|
2020-09-26 16:18:49 +00:00
|
|
|
</>
|
|
|
|
)}
|
2022-01-12 00:53:23 +00:00
|
|
|
{/* Community creators and admins can transfer community to another mod */}
|
2023-01-04 16:56:24 +00:00
|
|
|
{(amCommunityCreator(post_view.creator.id, this.props.moderators) ||
|
2022-06-21 21:42:29 +00:00
|
|
|
this.canAdmin_) &&
|
|
|
|
this.creatorIsMod_ &&
|
2022-01-12 00:53:23 +00:00
|
|
|
(!this.state.showConfirmTransferCommunity ? (
|
2020-09-26 16:18:49 +00:00
|
|
|
<button
|
2022-09-22 15:03:35 +00:00
|
|
|
className="btn btn-link btn-animate text-muted py-0"
|
2022-01-12 00:53:23 +00:00
|
|
|
onClick={linkEvent(
|
|
|
|
this,
|
|
|
|
this.handleShowConfirmTransferCommunity
|
|
|
|
)}
|
2023-06-22 00:54:35 +00:00
|
|
|
aria-label={I18NextService.i18n.t("transfer_community")}
|
2020-09-26 16:18:49 +00:00
|
|
|
>
|
2023-06-22 00:54:35 +00:00
|
|
|
{I18NextService.i18n.t("transfer_community")}
|
2020-09-26 16:18:49 +00:00
|
|
|
</button>
|
2022-01-12 00:53:23 +00:00
|
|
|
) : (
|
|
|
|
<>
|
2020-09-26 16:18:49 +00:00
|
|
|
<button
|
2023-06-20 12:01:29 +00:00
|
|
|
className="d-inline-block me-1 btn btn-link btn-animate text-muted py-0"
|
2023-06-22 00:54:35 +00:00
|
|
|
aria-label={I18NextService.i18n.t("are_you_sure")}
|
2020-09-26 16:18:49 +00:00
|
|
|
>
|
2023-06-22 00:54:35 +00:00
|
|
|
{I18NextService.i18n.t("are_you_sure")}
|
2020-09-26 16:18:49 +00:00
|
|
|
</button>
|
2022-01-12 00:53:23 +00:00
|
|
|
<button
|
2023-06-20 12:01:29 +00:00
|
|
|
className="btn btn-link btn-animate text-muted py-0 d-inline-block me-1"
|
2023-06-22 00:54:35 +00:00
|
|
|
aria-label={I18NextService.i18n.t("yes")}
|
2022-01-12 00:53:23 +00:00
|
|
|
onClick={linkEvent(this, this.handleTransferCommunity)}
|
|
|
|
>
|
2023-06-22 00:54:35 +00:00
|
|
|
{this.state.transferLoading ? (
|
|
|
|
<Spinner />
|
|
|
|
) : (
|
|
|
|
I18NextService.i18n.t("yes")
|
|
|
|
)}
|
2022-01-12 00:53:23 +00:00
|
|
|
</button>
|
|
|
|
<button
|
2022-09-22 15:03:35 +00:00
|
|
|
className="btn btn-link btn-animate text-muted py-0 d-inline-block"
|
2022-01-12 00:53:23 +00:00
|
|
|
onClick={linkEvent(
|
|
|
|
this,
|
|
|
|
this.handleCancelShowConfirmTransferCommunity
|
2021-03-25 16:44:16 +00:00
|
|
|
)}
|
2023-06-22 00:54:35 +00:00
|
|
|
aria-label={I18NextService.i18n.t("no")}
|
2022-01-12 00:53:23 +00:00
|
|
|
>
|
2023-06-22 00:54:35 +00:00
|
|
|
{I18NextService.i18n.t("no")}
|
2022-01-12 00:53:23 +00:00
|
|
|
</button>
|
|
|
|
</>
|
|
|
|
))}
|
|
|
|
{/* Admins can ban from all, and appoint other admins */}
|
2022-06-21 21:42:29 +00:00
|
|
|
{this.canAdmin_ && (
|
2022-01-12 00:53:23 +00:00
|
|
|
<>
|
2022-06-23 19:44:05 +00:00
|
|
|
{!this.creatorIsAdmin_ && (
|
|
|
|
<>
|
|
|
|
{!isBanned(post_view.creator) ? (
|
|
|
|
<button
|
2022-09-22 15:03:35 +00:00
|
|
|
className="btn btn-link btn-animate text-muted py-0"
|
2022-06-23 19:44:05 +00:00
|
|
|
onClick={linkEvent(this, this.handleModBanShow)}
|
2023-06-22 00:54:35 +00:00
|
|
|
aria-label={I18NextService.i18n.t("ban_from_site")}
|
2022-06-23 19:44:05 +00:00
|
|
|
>
|
2023-06-22 00:54:35 +00:00
|
|
|
{I18NextService.i18n.t("ban_from_site")}
|
2022-06-23 19:44:05 +00:00
|
|
|
</button>
|
|
|
|
) : (
|
|
|
|
<button
|
2022-09-22 15:03:35 +00:00
|
|
|
className="btn btn-link btn-animate text-muted py-0"
|
2022-06-23 19:44:05 +00:00
|
|
|
onClick={linkEvent(this, this.handleModBanSubmit)}
|
2023-06-22 00:54:35 +00:00
|
|
|
aria-label={I18NextService.i18n.t("unban_from_site")}
|
2022-06-23 19:44:05 +00:00
|
|
|
>
|
2023-06-14 12:20:40 +00:00
|
|
|
{this.state.banLoading ? (
|
|
|
|
<Spinner />
|
|
|
|
) : (
|
2023-06-22 00:54:35 +00:00
|
|
|
I18NextService.i18n.t("unban_from_site")
|
2023-06-14 12:20:40 +00:00
|
|
|
)}
|
2022-06-23 19:44:05 +00:00
|
|
|
</button>
|
|
|
|
)}
|
2020-10-13 20:12:40 +00:00
|
|
|
<button
|
2022-09-22 15:03:35 +00:00
|
|
|
className="btn btn-link btn-animate text-muted py-0"
|
2022-06-23 19:44:05 +00:00
|
|
|
onClick={linkEvent(this, this.handlePurgePersonShow)}
|
2023-06-22 00:54:35 +00:00
|
|
|
aria-label={I18NextService.i18n.t("purge_user")}
|
2020-09-26 16:18:49 +00:00
|
|
|
>
|
2023-06-22 00:54:35 +00:00
|
|
|
{I18NextService.i18n.t("purge_user")}
|
2020-10-13 20:12:40 +00:00
|
|
|
</button>
|
|
|
|
<button
|
2022-09-22 15:03:35 +00:00
|
|
|
className="btn btn-link btn-animate text-muted py-0"
|
2022-06-23 19:44:05 +00:00
|
|
|
onClick={linkEvent(this, this.handlePurgePostShow)}
|
2023-06-22 00:54:35 +00:00
|
|
|
aria-label={I18NextService.i18n.t("purge_post")}
|
2020-09-26 16:18:49 +00:00
|
|
|
>
|
2023-06-22 00:54:35 +00:00
|
|
|
{I18NextService.i18n.t("purge_post")}
|
2020-10-13 20:12:40 +00:00
|
|
|
</button>
|
2022-06-23 19:44:05 +00:00
|
|
|
</>
|
|
|
|
)}
|
2022-01-12 00:53:23 +00:00
|
|
|
{!isBanned(post_view.creator) && post_view.creator.local && (
|
|
|
|
<button
|
2022-09-22 15:03:35 +00:00
|
|
|
className="btn btn-link btn-animate text-muted py-0"
|
2022-01-12 00:53:23 +00:00
|
|
|
onClick={linkEvent(this, this.handleAddAdmin)}
|
|
|
|
aria-label={
|
2022-06-21 21:42:29 +00:00
|
|
|
this.creatorIsAdmin_
|
2023-06-22 00:54:35 +00:00
|
|
|
? I18NextService.i18n.t("remove_as_admin")
|
|
|
|
: I18NextService.i18n.t("appoint_as_admin")
|
2022-01-12 00:53:23 +00:00
|
|
|
}
|
|
|
|
>
|
2023-06-14 12:20:40 +00:00
|
|
|
{this.state.addAdminLoading ? (
|
|
|
|
<Spinner />
|
|
|
|
) : this.creatorIsAdmin_ ? (
|
2023-06-22 00:54:35 +00:00
|
|
|
I18NextService.i18n.t("remove_as_admin")
|
2023-06-14 12:20:40 +00:00
|
|
|
) : (
|
2023-06-22 00:54:35 +00:00
|
|
|
I18NextService.i18n.t("appoint_as_admin")
|
2023-06-14 12:20:40 +00:00
|
|
|
)}
|
2022-01-12 00:53:23 +00:00
|
|
|
</button>
|
|
|
|
)}
|
2020-09-26 16:18:49 +00:00
|
|
|
</>
|
|
|
|
)}
|
2023-06-21 23:40:24 +00:00
|
|
|
</div>
|
2020-09-26 16:18:49 +00:00
|
|
|
)
|
2020-09-06 16:15:25 +00:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
removeAndBanDialogs() {
|
2023-06-14 12:20:40 +00:00
|
|
|
const post = this.postView;
|
2023-06-05 21:31:12 +00:00
|
|
|
const purgeTypeText =
|
2023-01-04 16:56:24 +00:00
|
|
|
this.state.purgeType == PurgeType.Post
|
2023-06-22 00:54:35 +00:00
|
|
|
? I18NextService.i18n.t("purge_post")
|
|
|
|
: `${I18NextService.i18n.t("purge")} ${post.creator.name}`;
|
2020-09-06 16:15:25 +00:00
|
|
|
return (
|
|
|
|
<>
|
|
|
|
{this.state.showRemoveDialog && (
|
|
|
|
<form
|
2022-09-22 15:03:35 +00:00
|
|
|
className="form-inline"
|
2020-09-06 16:15:25 +00:00
|
|
|
onSubmit={linkEvent(this, this.handleModRemoveSubmit)}
|
|
|
|
>
|
2023-06-20 12:01:29 +00:00
|
|
|
<label
|
|
|
|
className="visually-hidden"
|
|
|
|
htmlFor="post-listing-remove-reason"
|
|
|
|
>
|
2023-06-22 00:54:35 +00:00
|
|
|
{I18NextService.i18n.t("reason")}
|
2021-02-09 16:21:24 +00:00
|
|
|
</label>
|
2020-09-06 16:15:25 +00:00
|
|
|
<input
|
|
|
|
type="text"
|
2021-02-09 16:21:24 +00:00
|
|
|
id="post-listing-remove-reason"
|
2023-06-20 12:01:29 +00:00
|
|
|
className="form-control me-2"
|
2023-06-22 00:54:35 +00:00
|
|
|
placeholder={I18NextService.i18n.t("reason")}
|
2023-01-04 16:56:24 +00:00
|
|
|
value={this.state.removeReason}
|
2020-09-06 16:15:25 +00:00
|
|
|
onInput={linkEvent(this, this.handleModRemoveReasonChange)}
|
|
|
|
/>
|
2021-02-09 16:21:24 +00:00
|
|
|
<button
|
|
|
|
type="submit"
|
2022-09-22 15:03:35 +00:00
|
|
|
className="btn btn-secondary"
|
2023-06-22 00:54:35 +00:00
|
|
|
aria-label={I18NextService.i18n.t("remove_post")}
|
2021-02-09 16:21:24 +00:00
|
|
|
>
|
2023-06-22 00:54:35 +00:00
|
|
|
{this.state.removeLoading ? (
|
|
|
|
<Spinner />
|
|
|
|
) : (
|
|
|
|
I18NextService.i18n.t("remove_post")
|
|
|
|
)}
|
2020-09-06 16:15:25 +00:00
|
|
|
</button>
|
|
|
|
</form>
|
|
|
|
)}
|
|
|
|
{this.state.showBanDialog && (
|
|
|
|
<form onSubmit={linkEvent(this, this.handleModBanBothSubmit)}>
|
2023-06-20 12:01:29 +00:00
|
|
|
<div className="mb-3 row col-12">
|
2022-09-22 15:03:35 +00:00
|
|
|
<label
|
|
|
|
className="col-form-label"
|
|
|
|
htmlFor="post-listing-ban-reason"
|
|
|
|
>
|
2023-06-22 00:54:35 +00:00
|
|
|
{I18NextService.i18n.t("reason")}
|
2020-09-06 16:15:25 +00:00
|
|
|
</label>
|
|
|
|
<input
|
|
|
|
type="text"
|
2021-02-09 16:21:24 +00:00
|
|
|
id="post-listing-ban-reason"
|
2023-06-20 12:01:29 +00:00
|
|
|
className="form-control me-2"
|
2023-06-22 00:54:35 +00:00
|
|
|
placeholder={I18NextService.i18n.t("reason")}
|
2023-01-04 16:56:24 +00:00
|
|
|
value={this.state.banReason}
|
2020-09-06 16:15:25 +00:00
|
|
|
onInput={linkEvent(this, this.handleModBanReasonChange)}
|
|
|
|
/>
|
2022-09-22 15:03:35 +00:00
|
|
|
<label className="col-form-label" htmlFor={`mod-ban-expires`}>
|
2023-06-22 00:54:35 +00:00
|
|
|
{I18NextService.i18n.t("expires")}
|
2022-01-09 17:53:11 +00:00
|
|
|
</label>
|
|
|
|
<input
|
|
|
|
type="number"
|
|
|
|
id={`mod-ban-expires`}
|
2023-06-20 12:01:29 +00:00
|
|
|
className="form-control me-2"
|
2023-06-22 00:54:35 +00:00
|
|
|
placeholder={I18NextService.i18n.t("number_of_days")}
|
2023-01-04 16:56:24 +00:00
|
|
|
value={this.state.banExpireDays}
|
2022-01-09 17:53:11 +00:00
|
|
|
onInput={linkEvent(this, this.handleModBanExpireDaysChange)}
|
|
|
|
/>
|
2023-06-20 12:01:29 +00:00
|
|
|
<div className="input-group mb-3">
|
2022-09-22 15:03:35 +00:00
|
|
|
<div className="form-check">
|
2020-09-06 16:15:25 +00:00
|
|
|
<input
|
2022-09-22 15:03:35 +00:00
|
|
|
className="form-check-input"
|
2020-09-06 16:15:25 +00:00
|
|
|
id="mod-ban-remove-data"
|
|
|
|
type="checkbox"
|
|
|
|
checked={this.state.removeData}
|
|
|
|
onChange={linkEvent(this, this.handleModRemoveDataChange)}
|
|
|
|
/>
|
2021-08-17 21:46:27 +00:00
|
|
|
<label
|
2022-09-22 15:03:35 +00:00
|
|
|
className="form-check-label"
|
2021-08-17 21:46:27 +00:00
|
|
|
htmlFor="mod-ban-remove-data"
|
2023-06-22 00:54:35 +00:00
|
|
|
title={I18NextService.i18n.t("remove_content_more")}
|
2021-08-17 21:46:27 +00:00
|
|
|
>
|
2023-06-22 00:54:35 +00:00
|
|
|
{I18NextService.i18n.t("remove_content")}
|
2020-09-06 16:15:25 +00:00
|
|
|
</label>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
{/* TODO hold off on expires until later */}
|
2023-06-20 12:01:29 +00:00
|
|
|
{/* <div class="mb-3 row"> */}
|
2020-09-06 16:15:25 +00:00
|
|
|
{/* <label class="col-form-label">Expires</label> */}
|
2023-06-22 00:54:35 +00:00
|
|
|
{/* <input type="date" class="form-control me-2" placeholder={I18NextService.i18n.t('expires')} value={this.state.banExpires} onInput={linkEvent(this, this.handleModBanExpiresChange)} /> */}
|
2020-09-06 16:15:25 +00:00
|
|
|
{/* </div> */}
|
2023-06-20 12:01:29 +00:00
|
|
|
<div className="mb-3 row">
|
2021-02-09 16:21:24 +00:00
|
|
|
<button
|
|
|
|
type="submit"
|
2022-09-22 15:03:35 +00:00
|
|
|
className="btn btn-secondary"
|
2023-06-22 00:54:35 +00:00
|
|
|
aria-label={I18NextService.i18n.t("ban")}
|
2021-02-09 16:21:24 +00:00
|
|
|
>
|
2023-06-14 12:20:40 +00:00
|
|
|
{this.state.banLoading ? (
|
|
|
|
<Spinner />
|
|
|
|
) : (
|
|
|
|
<span>
|
2023-06-22 00:54:35 +00:00
|
|
|
{I18NextService.i18n.t("ban")} {post.creator.name}
|
2023-06-14 12:20:40 +00:00
|
|
|
</span>
|
|
|
|
)}
|
2020-09-06 16:15:25 +00:00
|
|
|
</button>
|
|
|
|
</div>
|
|
|
|
</form>
|
|
|
|
)}
|
2021-09-28 10:38:59 +00:00
|
|
|
{this.state.showReportDialog && (
|
|
|
|
<form
|
2022-09-22 15:03:35 +00:00
|
|
|
className="form-inline"
|
2021-09-28 10:38:59 +00:00
|
|
|
onSubmit={linkEvent(this, this.handleReportSubmit)}
|
|
|
|
>
|
2023-06-20 12:01:29 +00:00
|
|
|
<label className="visually-hidden" htmlFor="post-report-reason">
|
2023-06-22 00:54:35 +00:00
|
|
|
{I18NextService.i18n.t("reason")}
|
2021-09-28 10:38:59 +00:00
|
|
|
</label>
|
|
|
|
<input
|
|
|
|
type="text"
|
|
|
|
id="post-report-reason"
|
2023-06-20 12:01:29 +00:00
|
|
|
className="form-control me-2"
|
2023-06-22 00:54:35 +00:00
|
|
|
placeholder={I18NextService.i18n.t("reason")}
|
2021-09-28 10:38:59 +00:00
|
|
|
required
|
2023-01-04 16:56:24 +00:00
|
|
|
value={this.state.reportReason}
|
2021-09-28 10:38:59 +00:00
|
|
|
onInput={linkEvent(this, this.handleReportReasonChange)}
|
|
|
|
/>
|
|
|
|
<button
|
|
|
|
type="submit"
|
2022-09-22 15:03:35 +00:00
|
|
|
className="btn btn-secondary"
|
2023-06-22 00:54:35 +00:00
|
|
|
aria-label={I18NextService.i18n.t("create_report")}
|
2021-09-28 10:38:59 +00:00
|
|
|
>
|
2023-06-22 00:54:35 +00:00
|
|
|
{this.state.reportLoading ? (
|
|
|
|
<Spinner />
|
|
|
|
) : (
|
|
|
|
I18NextService.i18n.t("create_report")
|
|
|
|
)}
|
2021-09-28 10:38:59 +00:00
|
|
|
</button>
|
|
|
|
</form>
|
|
|
|
)}
|
2022-06-23 19:44:05 +00:00
|
|
|
{this.state.showPurgeDialog && (
|
|
|
|
<form
|
2022-09-22 15:03:35 +00:00
|
|
|
className="form-inline"
|
2022-06-23 19:44:05 +00:00
|
|
|
onSubmit={linkEvent(this, this.handlePurgeSubmit)}
|
|
|
|
>
|
|
|
|
<PurgeWarning />
|
2023-06-20 12:01:29 +00:00
|
|
|
<label className="visually-hidden" htmlFor="purge-reason">
|
2023-06-22 00:54:35 +00:00
|
|
|
{I18NextService.i18n.t("reason")}
|
2022-06-23 19:44:05 +00:00
|
|
|
</label>
|
|
|
|
<input
|
|
|
|
type="text"
|
|
|
|
id="purge-reason"
|
2023-06-20 12:01:29 +00:00
|
|
|
className="form-control me-2"
|
2023-06-22 00:54:35 +00:00
|
|
|
placeholder={I18NextService.i18n.t("reason")}
|
2023-01-04 16:56:24 +00:00
|
|
|
value={this.state.purgeReason}
|
2022-06-23 19:44:05 +00:00
|
|
|
onInput={linkEvent(this, this.handlePurgeReasonChange)}
|
|
|
|
/>
|
|
|
|
{this.state.purgeLoading ? (
|
|
|
|
<Spinner />
|
|
|
|
) : (
|
|
|
|
<button
|
|
|
|
type="submit"
|
2022-09-22 15:03:35 +00:00
|
|
|
className="btn btn-secondary"
|
2022-06-23 19:44:05 +00:00
|
|
|
aria-label={purgeTypeText}
|
|
|
|
>
|
2023-06-14 12:20:40 +00:00
|
|
|
{this.state.purgeLoading ? <Spinner /> : { purgeTypeText }}
|
2022-06-23 19:44:05 +00:00
|
|
|
</button>
|
|
|
|
)}
|
|
|
|
</form>
|
|
|
|
)}
|
2020-09-06 16:15:25 +00:00
|
|
|
</>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
mobileThumbnail() {
|
2023-06-14 12:20:40 +00:00
|
|
|
const post = this.postView.post;
|
2023-01-04 16:56:24 +00:00
|
|
|
return post.thumbnail_url || (post.url && isImage(post.url)) ? (
|
2022-09-22 15:03:35 +00:00
|
|
|
<div className="row">
|
2021-02-22 02:39:04 +00:00
|
|
|
<div className={`${this.state.imageExpanded ? "col-12" : "col-8"}`}>
|
2020-09-06 16:15:25 +00:00
|
|
|
{this.postTitleLine()}
|
|
|
|
</div>
|
2022-09-22 15:03:35 +00:00
|
|
|
<div className="col-4">
|
2023-06-22 17:36:38 +00:00
|
|
|
{/* Post thumbnail */}
|
2020-09-06 16:15:25 +00:00
|
|
|
{!this.state.imageExpanded && this.thumbnail()}
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
) : (
|
|
|
|
this.postTitleLine()
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2023-06-21 23:40:24 +00:00
|
|
|
showBodyPreview() {
|
2023-06-15 17:21:42 +00:00
|
|
|
const { body, id } = this.postView.post;
|
|
|
|
|
2023-01-04 16:56:24 +00:00
|
|
|
return !this.showBody && body ? (
|
2023-06-21 23:40:24 +00:00
|
|
|
<Link className="text-body mt-2 d-block" to={`/post/${id}`}>
|
2023-06-15 17:21:42 +00:00
|
|
|
<div className="md-div mb-1 preview-lines">{body}</div>
|
|
|
|
</Link>
|
2023-01-04 16:56:24 +00:00
|
|
|
) : (
|
|
|
|
<></>
|
2020-09-06 16:15:25 +00:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
listing() {
|
|
|
|
return (
|
|
|
|
<>
|
|
|
|
{/* The mobile view*/}
|
2022-09-22 15:03:35 +00:00
|
|
|
<div className="d-block d-sm-none">
|
2023-06-16 20:27:41 +00:00
|
|
|
<article className="row post-container">
|
2022-09-22 15:03:35 +00:00
|
|
|
<div className="col-12">
|
2020-09-06 16:15:25 +00:00
|
|
|
{this.createdLine()}
|
|
|
|
|
|
|
|
{/* If it has a thumbnail, do a right aligned thumbnail */}
|
|
|
|
{this.mobileThumbnail()}
|
|
|
|
|
2023-06-22 21:30:48 +00:00
|
|
|
{/* Show a preview of the post body */}
|
2023-06-21 23:40:24 +00:00
|
|
|
{this.showBodyPreview()}
|
2023-06-22 21:30:48 +00:00
|
|
|
|
|
|
|
{this.commentsLine(true)}
|
2022-01-12 00:53:23 +00:00
|
|
|
{this.userActionsLine()}
|
2020-09-06 16:15:25 +00:00
|
|
|
{this.duplicatesLine()}
|
|
|
|
{this.removeAndBanDialogs()}
|
|
|
|
</div>
|
2023-06-16 20:27:41 +00:00
|
|
|
</article>
|
2020-09-06 16:15:25 +00:00
|
|
|
</div>
|
|
|
|
|
|
|
|
{/* The larger view*/}
|
2022-09-22 15:03:35 +00:00
|
|
|
<div className="d-none d-sm-block">
|
2023-06-16 20:27:41 +00:00
|
|
|
<article className="row post-container">
|
2023-06-22 17:36:38 +00:00
|
|
|
{!this.props.viewOnly && (
|
|
|
|
<VoteButtons
|
2023-06-23 03:48:53 +00:00
|
|
|
id={this.postView.post.id}
|
|
|
|
onVote={this.props.onPostVote}
|
2023-06-22 17:36:38 +00:00
|
|
|
enableDownvotes={this.props.enableDownvotes}
|
|
|
|
counts={this.postView.counts}
|
|
|
|
my_vote={this.postView.my_vote}
|
|
|
|
/>
|
|
|
|
)}
|
2023-06-20 12:01:29 +00:00
|
|
|
<div className="col-sm-2 pe-0 post-media">
|
2022-09-22 15:03:35 +00:00
|
|
|
<div className="">{this.thumbnail()}</div>
|
2022-01-12 00:53:23 +00:00
|
|
|
</div>
|
2022-09-22 15:03:35 +00:00
|
|
|
<div className="col-12 col-sm-9">
|
|
|
|
<div className="row">
|
2020-09-06 16:15:25 +00:00
|
|
|
<div className="col-12">
|
|
|
|
{this.postTitleLine()}
|
|
|
|
{this.createdLine()}
|
2023-06-21 23:40:24 +00:00
|
|
|
{this.showBodyPreview()}
|
2020-09-06 16:15:25 +00:00
|
|
|
{this.commentsLine()}
|
|
|
|
{this.duplicatesLine()}
|
2022-01-12 00:53:23 +00:00
|
|
|
{this.userActionsLine()}
|
2020-09-06 16:15:25 +00:00
|
|
|
{this.removeAndBanDialogs()}
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
2023-06-16 20:27:41 +00:00
|
|
|
</article>
|
2020-09-06 16:15:25 +00:00
|
|
|
</div>
|
|
|
|
</>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
private get myPost(): boolean {
|
2023-01-04 16:56:24 +00:00
|
|
|
return (
|
2023-06-14 12:20:40 +00:00
|
|
|
this.postView.creator.id ==
|
2023-01-04 16:56:24 +00:00
|
|
|
UserService.Instance.myUserInfo?.local_user_view.person.id
|
|
|
|
);
|
2020-09-06 16:15:25 +00:00
|
|
|
}
|
|
|
|
handleEditClick(i: PostListing) {
|
2022-09-22 15:03:35 +00:00
|
|
|
i.setState({ showEdit: true });
|
2020-09-06 16:15:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
handleEditCancel() {
|
2022-09-22 15:03:35 +00:00
|
|
|
this.setState({ showEdit: false });
|
2020-09-06 16:15:25 +00:00
|
|
|
}
|
|
|
|
|
2023-06-12 14:05:36 +00:00
|
|
|
// The actual editing is done in the receive for post
|
2023-06-14 12:20:40 +00:00
|
|
|
handleEditPost(form: EditPost) {
|
2022-09-22 15:03:35 +00:00
|
|
|
this.setState({ showEdit: false });
|
2023-06-14 12:20:40 +00:00
|
|
|
this.props.onPostEdit(form);
|
2020-09-06 16:15:25 +00:00
|
|
|
}
|
|
|
|
|
2023-05-21 18:17:56 +00:00
|
|
|
handleShare(i: PostListing) {
|
|
|
|
const { name, body, id } = i.props.post_view.post;
|
|
|
|
share({
|
|
|
|
title: name,
|
|
|
|
text: body?.slice(0, 50),
|
|
|
|
url: `${getHttpBase()}/post/${id}`,
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2021-09-28 10:38:59 +00:00
|
|
|
handleShowReportDialog(i: PostListing) {
|
2022-09-22 15:03:35 +00:00
|
|
|
i.setState({ showReportDialog: !i.state.showReportDialog });
|
2021-09-28 10:38:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
handleReportReasonChange(i: PostListing, event: any) {
|
2023-01-04 16:56:24 +00:00
|
|
|
i.setState({ reportReason: event.target.value });
|
2021-09-28 10:38:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
handleReportSubmit(i: PostListing, event: any) {
|
|
|
|
event.preventDefault();
|
2023-06-14 12:20:40 +00:00
|
|
|
i.setState({ reportLoading: true });
|
|
|
|
i.props.onPostReport({
|
|
|
|
post_id: i.postView.post.id,
|
|
|
|
reason: i.state.reportReason ?? "",
|
|
|
|
auth: myAuthRequired(),
|
|
|
|
});
|
2021-09-28 10:38:59 +00:00
|
|
|
}
|
|
|
|
|
2023-06-14 12:20:40 +00:00
|
|
|
handleBlockPersonClick(i: PostListing) {
|
|
|
|
i.setState({ blockLoading: true });
|
|
|
|
i.props.onBlockPerson({
|
|
|
|
person_id: i.postView.creator.id,
|
|
|
|
block: true,
|
|
|
|
auth: myAuthRequired(),
|
|
|
|
});
|
2021-08-20 02:56:18 +00:00
|
|
|
}
|
|
|
|
|
2020-09-06 16:15:25 +00:00
|
|
|
handleDeleteClick(i: PostListing) {
|
2023-06-14 12:20:40 +00:00
|
|
|
i.setState({ deleteLoading: true });
|
|
|
|
i.props.onDeletePost({
|
|
|
|
post_id: i.postView.post.id,
|
|
|
|
deleted: !i.postView.post.deleted,
|
|
|
|
auth: myAuthRequired(),
|
|
|
|
});
|
2020-09-06 16:15:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
handleSavePostClick(i: PostListing) {
|
2023-06-14 12:20:40 +00:00
|
|
|
i.setState({ saveLoading: true });
|
|
|
|
i.props.onSavePost({
|
|
|
|
post_id: i.postView.post.id,
|
|
|
|
save: !i.postView.saved,
|
|
|
|
auth: myAuthRequired(),
|
|
|
|
});
|
2020-09-06 16:15:25 +00:00
|
|
|
}
|
|
|
|
|
2023-04-15 14:47:10 +00:00
|
|
|
get crossPostParams(): PostFormParams {
|
|
|
|
const queryParams: PostFormParams = {};
|
2023-06-14 12:20:40 +00:00
|
|
|
const { name, url } = this.postView.post;
|
2020-09-06 16:15:25 +00:00
|
|
|
|
2023-04-15 14:47:10 +00:00
|
|
|
queryParams.name = name;
|
|
|
|
|
|
|
|
if (url) {
|
|
|
|
queryParams.url = url;
|
2020-09-06 16:15:25 +00:00
|
|
|
}
|
2023-04-15 14:47:10 +00:00
|
|
|
|
|
|
|
const crossPostBody = this.crossPostBody();
|
2023-01-04 16:56:24 +00:00
|
|
|
if (crossPostBody) {
|
2023-04-15 14:47:10 +00:00
|
|
|
queryParams.body = crossPostBody;
|
2020-09-06 16:15:25 +00:00
|
|
|
}
|
2023-04-15 14:47:10 +00:00
|
|
|
|
|
|
|
return queryParams;
|
2020-09-06 16:15:25 +00:00
|
|
|
}
|
|
|
|
|
2023-01-04 16:56:24 +00:00
|
|
|
crossPostBody(): string | undefined {
|
2023-06-14 12:20:40 +00:00
|
|
|
const post = this.postView.post;
|
2023-06-05 21:31:12 +00:00
|
|
|
const body = post.body;
|
2023-01-04 16:56:24 +00:00
|
|
|
|
|
|
|
return body
|
2023-06-22 00:54:35 +00:00
|
|
|
? `${I18NextService.i18n.t("cross_posted_from")} ${
|
|
|
|
post.ap_id
|
|
|
|
}\n\n${body.replace(/^/gm, "> ")}`
|
2023-01-04 16:56:24 +00:00
|
|
|
: undefined;
|
2021-03-25 17:28:47 +00:00
|
|
|
}
|
|
|
|
|
2021-03-25 16:44:16 +00:00
|
|
|
get showBody(): boolean {
|
|
|
|
return this.props.showBody || this.state.showBody;
|
|
|
|
}
|
|
|
|
|
2020-09-06 16:15:25 +00:00
|
|
|
handleModRemoveShow(i: PostListing) {
|
2022-09-22 15:03:35 +00:00
|
|
|
i.setState({
|
|
|
|
showRemoveDialog: !i.state.showRemoveDialog,
|
|
|
|
showBanDialog: false,
|
|
|
|
});
|
2020-09-06 16:15:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
handleModRemoveReasonChange(i: PostListing, event: any) {
|
2023-01-04 16:56:24 +00:00
|
|
|
i.setState({ removeReason: event.target.value });
|
2020-09-06 16:15:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
handleModRemoveDataChange(i: PostListing, event: any) {
|
2022-09-22 15:03:35 +00:00
|
|
|
i.setState({ removeData: event.target.checked });
|
2020-09-06 16:15:25 +00:00
|
|
|
}
|
|
|
|
|
2021-01-26 17:21:10 +00:00
|
|
|
handleModRemoveSubmit(i: PostListing, event: any) {
|
2020-09-06 16:15:25 +00:00
|
|
|
event.preventDefault();
|
2023-06-14 12:20:40 +00:00
|
|
|
i.setState({ removeLoading: true });
|
|
|
|
i.props.onRemovePost({
|
|
|
|
post_id: i.postView.post.id,
|
|
|
|
removed: !i.postView.post.removed,
|
|
|
|
auth: myAuthRequired(),
|
|
|
|
});
|
2020-09-06 16:15:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
handleModLock(i: PostListing) {
|
2023-06-14 12:20:40 +00:00
|
|
|
i.setState({ lockLoading: true });
|
|
|
|
i.props.onLockPost({
|
|
|
|
post_id: i.postView.post.id,
|
|
|
|
locked: !i.postView.post.locked,
|
|
|
|
auth: myAuthRequired(),
|
|
|
|
});
|
2020-09-06 16:15:25 +00:00
|
|
|
}
|
|
|
|
|
2023-02-21 20:53:51 +00:00
|
|
|
handleModFeaturePostLocal(i: PostListing) {
|
2023-06-14 12:20:40 +00:00
|
|
|
i.setState({ featureLocalLoading: true });
|
|
|
|
i.props.onFeaturePost({
|
|
|
|
post_id: i.postView.post.id,
|
|
|
|
featured: !i.postView.post.featured_local,
|
|
|
|
feature_type: "Local",
|
|
|
|
auth: myAuthRequired(),
|
|
|
|
});
|
2023-02-21 20:53:51 +00:00
|
|
|
}
|
2023-01-04 16:56:24 +00:00
|
|
|
|
2023-02-21 20:53:51 +00:00
|
|
|
handleModFeaturePostCommunity(i: PostListing) {
|
2023-06-14 12:20:40 +00:00
|
|
|
i.setState({ featureCommunityLoading: true });
|
|
|
|
i.props.onFeaturePost({
|
|
|
|
post_id: i.postView.post.id,
|
|
|
|
featured: !i.postView.post.featured_community,
|
|
|
|
feature_type: "Community",
|
|
|
|
auth: myAuthRequired(),
|
|
|
|
});
|
2020-09-06 16:15:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
handleModBanFromCommunityShow(i: PostListing) {
|
2022-09-22 15:03:35 +00:00
|
|
|
i.setState({
|
|
|
|
showBanDialog: true,
|
|
|
|
banType: BanType.Community,
|
|
|
|
showRemoveDialog: false,
|
|
|
|
});
|
2020-09-06 16:15:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
handleModBanShow(i: PostListing) {
|
2022-09-22 15:03:35 +00:00
|
|
|
i.setState({
|
|
|
|
showBanDialog: true,
|
|
|
|
banType: BanType.Site,
|
|
|
|
showRemoveDialog: false,
|
|
|
|
});
|
2020-09-06 16:15:25 +00:00
|
|
|
}
|
|
|
|
|
2022-06-23 19:44:05 +00:00
|
|
|
handlePurgePersonShow(i: PostListing) {
|
2022-09-22 15:03:35 +00:00
|
|
|
i.setState({
|
|
|
|
showPurgeDialog: true,
|
|
|
|
purgeType: PurgeType.Person,
|
|
|
|
showRemoveDialog: false,
|
|
|
|
});
|
2022-06-23 19:44:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
handlePurgePostShow(i: PostListing) {
|
2022-09-22 15:03:35 +00:00
|
|
|
i.setState({
|
|
|
|
showPurgeDialog: true,
|
|
|
|
purgeType: PurgeType.Post,
|
|
|
|
showRemoveDialog: false,
|
|
|
|
});
|
2022-06-23 19:44:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
handlePurgeReasonChange(i: PostListing, event: any) {
|
2023-01-04 16:56:24 +00:00
|
|
|
i.setState({ purgeReason: event.target.value });
|
2022-06-23 19:44:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
handlePurgeSubmit(i: PostListing, event: any) {
|
|
|
|
event.preventDefault();
|
2023-06-14 12:20:40 +00:00
|
|
|
i.setState({ purgeLoading: true });
|
|
|
|
if (i.state.purgeType == PurgeType.Person) {
|
|
|
|
i.props.onPurgePerson({
|
|
|
|
person_id: i.postView.creator.id,
|
|
|
|
reason: i.state.purgeReason,
|
|
|
|
auth: myAuthRequired(),
|
|
|
|
});
|
|
|
|
} else if (i.state.purgeType == PurgeType.Post) {
|
|
|
|
i.props.onPurgePost({
|
|
|
|
post_id: i.postView.post.id,
|
|
|
|
reason: i.state.purgeReason,
|
|
|
|
auth: myAuthRequired(),
|
|
|
|
});
|
2023-01-04 16:56:24 +00:00
|
|
|
}
|
2022-06-23 19:44:05 +00:00
|
|
|
}
|
|
|
|
|
2020-09-06 16:15:25 +00:00
|
|
|
handleModBanReasonChange(i: PostListing, event: any) {
|
2023-01-04 16:56:24 +00:00
|
|
|
i.setState({ banReason: event.target.value });
|
2020-09-06 16:15:25 +00:00
|
|
|
}
|
|
|
|
|
2022-01-09 17:53:11 +00:00
|
|
|
handleModBanExpireDaysChange(i: PostListing, event: any) {
|
2023-01-04 16:56:24 +00:00
|
|
|
i.setState({ banExpireDays: event.target.value });
|
2020-09-06 16:15:25 +00:00
|
|
|
}
|
|
|
|
|
2023-06-14 12:20:40 +00:00
|
|
|
handleModBanFromCommunitySubmit(i: PostListing, event: any) {
|
2022-09-22 15:03:35 +00:00
|
|
|
i.setState({ banType: BanType.Community });
|
2023-06-14 12:20:40 +00:00
|
|
|
i.handleModBanBothSubmit(i, event);
|
2020-09-06 16:15:25 +00:00
|
|
|
}
|
|
|
|
|
2023-06-14 12:20:40 +00:00
|
|
|
handleModBanSubmit(i: PostListing, event: any) {
|
2022-09-22 15:03:35 +00:00
|
|
|
i.setState({ banType: BanType.Site });
|
2023-06-14 12:20:40 +00:00
|
|
|
i.handleModBanBothSubmit(i, event);
|
|
|
|
}
|
|
|
|
|
|
|
|
handleModBanBothSubmit(i: PostListing, event: any) {
|
|
|
|
event.preventDefault();
|
|
|
|
i.setState({ banLoading: true });
|
2020-09-06 16:15:25 +00:00
|
|
|
|
2023-06-14 12:20:40 +00:00
|
|
|
const ban = !i.props.post_view.creator_banned_from_community;
|
|
|
|
// If its an unban, restore all their data
|
|
|
|
if (ban == false) {
|
|
|
|
i.setState({ removeData: false });
|
|
|
|
}
|
|
|
|
const person_id = i.props.post_view.creator.id;
|
|
|
|
const remove_data = i.state.removeData;
|
|
|
|
const reason = i.state.banReason;
|
|
|
|
const expires = futureDaysToUnixTime(i.state.banExpireDays);
|
|
|
|
|
|
|
|
if (i.state.banType == BanType.Community) {
|
|
|
|
const community_id = i.postView.community.id;
|
|
|
|
i.props.onBanPersonFromCommunity({
|
|
|
|
community_id,
|
|
|
|
person_id,
|
|
|
|
ban,
|
|
|
|
remove_data,
|
|
|
|
reason,
|
|
|
|
expires,
|
|
|
|
auth: myAuthRequired(),
|
|
|
|
});
|
|
|
|
} else {
|
|
|
|
i.props.onBanPerson({
|
|
|
|
person_id,
|
|
|
|
ban,
|
|
|
|
remove_data,
|
|
|
|
reason,
|
|
|
|
expires,
|
|
|
|
auth: myAuthRequired(),
|
|
|
|
});
|
2023-01-04 16:56:24 +00:00
|
|
|
}
|
2020-09-06 16:15:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
handleAddModToCommunity(i: PostListing) {
|
2023-06-14 12:20:40 +00:00
|
|
|
i.setState({ addModLoading: true });
|
|
|
|
i.props.onAddModToCommunity({
|
|
|
|
community_id: i.postView.community.id,
|
|
|
|
person_id: i.postView.creator.id,
|
|
|
|
added: !i.creatorIsMod_,
|
|
|
|
auth: myAuthRequired(),
|
|
|
|
});
|
2020-09-06 16:15:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
handleAddAdmin(i: PostListing) {
|
2023-06-14 12:20:40 +00:00
|
|
|
i.setState({ addAdminLoading: true });
|
|
|
|
i.props.onAddAdmin({
|
|
|
|
person_id: i.postView.creator.id,
|
|
|
|
added: !i.creatorIsAdmin_,
|
|
|
|
auth: myAuthRequired(),
|
|
|
|
});
|
2020-09-06 16:15:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
handleShowConfirmTransferCommunity(i: PostListing) {
|
2022-09-22 15:03:35 +00:00
|
|
|
i.setState({ showConfirmTransferCommunity: true });
|
2020-09-06 16:15:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
handleCancelShowConfirmTransferCommunity(i: PostListing) {
|
2022-09-22 15:03:35 +00:00
|
|
|
i.setState({ showConfirmTransferCommunity: false });
|
2020-09-06 16:15:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
handleTransferCommunity(i: PostListing) {
|
2023-06-14 12:20:40 +00:00
|
|
|
i.setState({ transferLoading: true });
|
|
|
|
i.props.onTransferCommunity({
|
|
|
|
community_id: i.postView.community.id,
|
|
|
|
person_id: i.postView.creator.id,
|
|
|
|
auth: myAuthRequired(),
|
|
|
|
});
|
2020-09-06 16:15:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
handleShowConfirmTransferSite(i: PostListing) {
|
2022-09-22 15:03:35 +00:00
|
|
|
i.setState({ showConfirmTransferSite: true });
|
2020-09-06 16:15:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
handleCancelShowConfirmTransferSite(i: PostListing) {
|
2022-09-22 15:03:35 +00:00
|
|
|
i.setState({ showConfirmTransferSite: false });
|
2020-09-06 16:15:25 +00:00
|
|
|
}
|
|
|
|
|
2021-09-19 20:29:03 +00:00
|
|
|
handleImageExpandClick(i: PostListing, event: any) {
|
|
|
|
event.preventDefault();
|
2022-09-22 15:03:35 +00:00
|
|
|
i.setState({ imageExpanded: !i.state.imageExpanded });
|
2022-01-12 00:53:23 +00:00
|
|
|
setupTippy();
|
2020-09-06 16:15:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
handleViewSource(i: PostListing) {
|
2022-09-22 15:03:35 +00:00
|
|
|
i.setState({ viewSource: !i.state.viewSource });
|
2020-09-06 16:15:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
handleShowAdvanced(i: PostListing) {
|
2022-09-22 15:03:35 +00:00
|
|
|
i.setState({ showAdvanced: !i.state.showAdvanced });
|
2020-09-06 16:15:25 +00:00
|
|
|
setupTippy();
|
|
|
|
}
|
|
|
|
|
2020-09-26 16:18:49 +00:00
|
|
|
handleShowMoreMobile(i: PostListing) {
|
2022-09-22 15:03:35 +00:00
|
|
|
i.setState({
|
|
|
|
showMoreMobile: !i.state.showMoreMobile,
|
|
|
|
showAdvanced: !i.state.showAdvanced,
|
|
|
|
});
|
2020-09-26 16:18:49 +00:00
|
|
|
setupTippy();
|
|
|
|
}
|
|
|
|
|
2021-03-25 16:44:16 +00:00
|
|
|
handleShowBody(i: PostListing) {
|
2022-09-22 15:03:35 +00:00
|
|
|
i.setState({ showBody: !i.state.showBody });
|
2021-03-25 16:44:16 +00:00
|
|
|
setupTippy();
|
|
|
|
}
|
|
|
|
|
2020-09-06 16:15:25 +00:00
|
|
|
get pointsTippy(): string {
|
2023-06-22 00:54:35 +00:00
|
|
|
const points = I18NextService.i18n.t("number_of_points", {
|
2023-06-14 12:20:40 +00:00
|
|
|
count: Number(this.postView.counts.score),
|
|
|
|
formattedCount: Number(this.postView.counts.score),
|
2020-09-06 16:15:25 +00:00
|
|
|
});
|
|
|
|
|
2023-06-22 00:54:35 +00:00
|
|
|
const upvotes = I18NextService.i18n.t("number_of_upvotes", {
|
2023-06-14 12:20:40 +00:00
|
|
|
count: Number(this.postView.counts.upvotes),
|
|
|
|
formattedCount: Number(this.postView.counts.upvotes),
|
2020-09-06 16:15:25 +00:00
|
|
|
});
|
|
|
|
|
2023-06-22 00:54:35 +00:00
|
|
|
const downvotes = I18NextService.i18n.t("number_of_downvotes", {
|
2023-06-14 12:20:40 +00:00
|
|
|
count: Number(this.postView.counts.downvotes),
|
|
|
|
formattedCount: Number(this.postView.counts.downvotes),
|
2020-09-06 16:15:25 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
return `${points} • ${upvotes} • ${downvotes}`;
|
|
|
|
}
|
2022-06-21 21:42:29 +00:00
|
|
|
|
|
|
|
get canModOnSelf_(): boolean {
|
|
|
|
return canMod(
|
2023-06-14 12:20:40 +00:00
|
|
|
this.postView.creator.id,
|
2022-06-21 21:42:29 +00:00
|
|
|
this.props.moderators,
|
|
|
|
this.props.admins,
|
|
|
|
undefined,
|
|
|
|
true
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
get canMod_(): boolean {
|
|
|
|
return canMod(
|
2023-06-14 12:20:40 +00:00
|
|
|
this.postView.creator.id,
|
2022-06-21 21:42:29 +00:00
|
|
|
this.props.moderators,
|
2023-01-04 16:56:24 +00:00
|
|
|
this.props.admins
|
2022-06-21 21:42:29 +00:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
get canAdmin_(): boolean {
|
2023-06-14 12:20:40 +00:00
|
|
|
return canAdmin(this.postView.creator.id, this.props.admins);
|
2022-06-21 21:42:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
get creatorIsMod_(): boolean {
|
2023-06-14 12:20:40 +00:00
|
|
|
return isMod(this.postView.creator.id, this.props.moderators);
|
2022-06-21 21:42:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
get creatorIsAdmin_(): boolean {
|
2023-06-14 12:20:40 +00:00
|
|
|
return isAdmin(this.postView.creator.id, this.props.admins);
|
2022-06-21 21:42:29 +00:00
|
|
|
}
|
2020-09-06 16:15:25 +00:00
|
|
|
}
|