X-Git-Url: http://these/git/?a=blobdiff_plain;f=src%2Fshared%2Fcomponents%2Fpost%2Fpost-listing.tsx;h=c92663501e474ecae19526a25c55a2f089e3c3ef;hb=2efe167f6d5f5cb65a2b749ba2fcee0934b247a3;hp=92550589dfb97f83bb6ff544379b24ccece7cbb1;hpb=ffb0ffb255bd5936400d4b66689812ee3d04431a;p=lemmy-ui.git diff --git a/src/shared/components/post/post-listing.tsx b/src/shared/components/post/post-listing.tsx index 9255058..c926635 100644 --- a/src/shared/components/post/post-listing.tsx +++ b/src/shared/components/post/post-listing.tsx @@ -1,4 +1,4 @@ -import { myAuthRequired } from "@utils/app"; +import { myAuth, myAuthRequired } from "@utils/app"; import { canShare, share } from "@utils/browser"; import { getExternalHost, getHttpBase } from "@utils/env"; import { @@ -34,6 +34,7 @@ import { FeaturePost, Language, LockPost, + MarkPostAsRead, PersonView, PostView, PurgePerson, @@ -49,12 +50,13 @@ import { PurgeType, VoteContentType, } from "../../interfaces"; -import { mdNoImages, mdToHtml, mdToHtmlInline } from "../../markdown"; +import { mdToHtml, mdToHtmlInline } from "../../markdown"; import { I18NextService, UserService } from "../../services"; import { setupTippy } from "../../tippy"; import { Icon, PurgeWarning, Spinner } from "../common/icon"; import { MomentTime } from "../common/moment-time"; import { PictrsImage } from "../common/pictrs-image"; +import { UserBadges } from "../common/user-badges"; import { VoteButtons, VoteButtonsCompact } from "../common/vote-buttons"; import { CommunityLink } from "../community/community-link"; import { PersonListing } from "../person/person-listing"; @@ -105,6 +107,9 @@ interface PostListingProps { allLanguages: Language[]; siteLanguages: number[]; showCommunity?: boolean; + /** + * Controls whether to show both the body *and* the metadata preview card + */ showBody?: boolean; hideImage?: boolean; enableDownvotes?: boolean; @@ -126,6 +131,7 @@ interface PostListingProps { onAddModToCommunity(form: AddModToCommunity): void; onAddAdmin(form: AddAdmin): void; onTransferCommunity(form: TransferCommunity): void; + onMarkPostAsRead(form: MarkPostAsRead): void; } export class PostListing extends Component { @@ -167,6 +173,26 @@ export class PostListing extends Component { this.handleEditCancel = this.handleEditCancel.bind(this); } + componentWillReceiveProps(nextProps: PostListingProps) { + 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, + }); + } + } + get postView(): PostView { return this.props.post_view; } @@ -180,7 +206,7 @@ export class PostListing extends Component { <> {this.listing()} {this.state.imageExpanded && !this.props.hideImage && this.img} - {post.url && this.state.showBody && post.embed_title && ( + {this.showBody && post.url && post.embed_title && ( )} {this.showBody && this.body()} @@ -286,16 +312,10 @@ export class PostListing extends Component { const url = post.url; const thumbnail = post.thumbnail_url; - if (url && isImage(url)) { - if (url.includes("pictrs")) { - return url; - } else if (thumbnail) { - return thumbnail; - } else { - return url; - } - } else if (thumbnail) { + if (thumbnail) { return thumbnail; + } else if (url && isImage(url)) { + return url; } else { return undefined; } @@ -308,27 +328,34 @@ export class PostListing extends Component { if (!this.props.hideImage && url && isImage(url) && this.imageSrc) { return ( - {this.imgThumb(this.imageSrc)} - - + + ); } else if (!this.props.hideImage && url && thumbnail && this.imageSrc) { return ( {this.imgThumb(this.imageSrc)} - + ); } else if (url) { @@ -342,6 +369,7 @@ export class PostListing extends Component { data-tippy-content={I18NextService.i18n.t("expand_here")} onClick={linkEvent(this, this.handleImageExpandClick)} aria-label={I18NextService.i18n.t("expand_here")} + target={this.linkTarget} >
@@ -350,7 +378,13 @@ export class PostListing extends Component { ); } else { return ( - +
@@ -363,6 +397,7 @@ export class PostListing extends Component { className="text-body" to={`/post/${post.id}`} title={I18NextService.i18n.t("comments")} + target={this.linkTarget} >
@@ -374,24 +409,16 @@ export class PostListing extends Component { createdLine() { const post_view = this.postView; + return ( - - - {this.creatorIsMod_ && ( - - {I18NextService.i18n.t("mod")} - - )} - {this.creatorIsAdmin_ && ( - - {I18NextService.i18n.t("admin")} - - )} - {post_view.creator.bot_account && ( - - {I18NextService.i18n.t("bot_account").toLowerCase()} - - )} +
+ + {this.props.showCommunity && ( <> {" "} @@ -403,7 +430,7 @@ export class PostListing extends Component { { this.props.allLanguages.find( - lang => lang.id === post_view.post.language_id + lang => lang.id === post_view.post.language_id, )?.name } @@ -413,7 +440,7 @@ export class PostListing extends Component { published={post_view.post.published} updated={post_view.post.updated} /> - +
); } @@ -443,8 +470,8 @@ export class PostListing extends Component { return ( <> -
-
+
{/** - * 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. + * If there is (a) a URL and an embed title, or (b) a post body, and + * we were not told to show the body by the parent component, show the + * MetadataCard/body toggle. */} - {(post.url || (post.body && !this.props.showBody)) && ( - - )} + {!this.props.showBody && + ((post.url && post.embed_title) || post.body) && + this.showPreviewButton()} {post.removed && ( {I18NextService.i18n.t("removed")} )} + {post.deleted && ( { )} + {post.locked && ( { )} + {post.featured_community && ( )} + {post.featured_local && ( { )} + {post.nsfw && ( {I18NextService.i18n.t("nsfw")} @@ -599,7 +607,7 @@ export class PostListing extends Component { {this.commentsButton} {canShare() && (
); } + public get linkTarget(): string { + return UserService.Instance.myUserInfo?.local_user_view.local_user + .open_links_in_new_tab + ? "_blank" + : // _self is the default target on links when the field is not specified + "_self"; + } + get commentsButton() { const post_view = this.postView; const title = I18NextService.i18n.t("number_of_comments", { @@ -707,6 +767,7 @@ export class PostListing extends Component { title={title} to={`/post/${post_view.post.id}?scrollToComments=true`} data-tippy-content={title} + target={this.linkTarget} > {post_view.counts.comments} @@ -724,7 +785,7 @@ export class PostListing extends Component { get unreadCount(): number | undefined { const pv = this.postView; - return pv.unread_comments == pv.counts.comments || pv.unread_comments == 0 + return pv.unread_comments === pv.counts.comments || pv.unread_comments === 0 ? undefined : pv.unread_comments; } @@ -736,7 +797,7 @@ export class PostListing extends Component { : I18NextService.i18n.t("save"); return ( @@ -967,9 +1027,8 @@ export class PostListing extends Component { get modUnbanFromCommunityButton() { return ( @@ -979,20 +1038,15 @@ export class PostListing extends Component { get addModToCommunityButton() { return ( ); @@ -1001,11 +1055,10 @@ export class PostListing extends Component { get modBanButton() { return ( ); } @@ -1013,14 +1066,13 @@ export class PostListing extends Component { get modUnbanButton() { return ( ); @@ -1029,11 +1081,10 @@ export class PostListing extends Component { get purgePersonButton() { return ( ); } @@ -1041,11 +1092,10 @@ export class PostListing extends Component { get purgePostButton() { return ( ); } @@ -1053,20 +1103,31 @@ export class PostListing extends Component { get toggleAdminButton() { return ( ); } + get transferCommunityButton() { + return ( + + ); + } + get modRemoveButton() { const removed = this.postView.post.removed; return ( @@ -1074,116 +1135,28 @@ export class PostListing extends Component { className="btn btn-link btn-sm d-flex align-items-center rounded-0 dropdown-item" onClick={linkEvent( this, - !removed ? this.handleModRemoveShow : this.handleModRemoveSubmit + !removed ? this.handleModRemoveShow : this.handleModRemoveSubmit, )} > {/* TODO: Find an icon for this. */} {this.state.removeLoading ? ( ) : !removed ? ( - I18NextService.i18n.t("remove") + capitalizeFirstLetter(I18NextService.i18n.t("remove_post")) ) : ( - I18NextService.i18n.t("restore") + <> + {capitalizeFirstLetter(I18NextService.i18n.t("restore"))}{" "} + {I18NextService.i18n.t("post")} + )} ); } - /** - * Mod/Admin actions to be taken against the author. - */ - userActionsLine() { - // TODO: make nicer - const post_view = this.postView; - return ( - this.state.showAdvanced && ( -
- {this.canMod_ && ( - <> - {!this.creatorIsMod_ && - (!post_view.creator_banned_from_community ? ( -
  • {this.modBanFromCommunityButton}
  • - ) : ( -
  • {this.modUnbanFromCommunityButton}
  • - ))} - {!post_view.creator_banned_from_community && ( -
  • {this.addModToCommunityButton}
  • - )} - - )} - - {/* Community creators and admins can transfer community to another mod */} - {(amCommunityCreator(post_view.creator.id, this.props.moderators) || - this.canAdmin_) && - this.creatorIsMod_ && - (!this.state.showConfirmTransferCommunity ? ( - - ) : ( - <> - - - - - ))} - {/* Admins can ban from all, and appoint other admins */} - {this.canAdmin_ && ( - <> - {!this.creatorIsAdmin_ && ( - <> - {!isBanned(post_view.creator) - ? this.modBanButton - : this.modUnbanButton} - {this.purgePersonButton} - {this.purgePostButton} - - )} - {!isBanned(post_view.creator) && - post_view.creator.local && - this.toggleAdminButton} - - )} -
    - ) - ); - } - removeAndBanDialogs() { const post = this.postView; const purgeTypeText = - this.state.purgeType == PurgeType.Post + this.state.purgeType === PurgeType.Post ? I18NextService.i18n.t("purge_post") : `${I18NextService.i18n.t("purge")} ${post.creator.name}`; return ( @@ -1207,11 +1180,7 @@ export class PostListing extends Component { value={this.state.removeReason} onInput={linkEvent(this, this.handleModRemoveReasonChange)} /> - )} + {this.state.showConfirmTransferCommunity && ( + <> + + + + + )} {this.state.showBanDialog && (
    @@ -1273,11 +1269,7 @@ export class PostListing extends Component { {/* */} {/*
    */}
    - )} @@ -1357,10 +1341,10 @@ export class PostListing extends Component { const post = this.postView.post; return post.thumbnail_url || (post.url && isImage(post.url)) ? (
    -
    +
    {this.postTitleLine()}
    -
    +
    {/* Post thumbnail */} {!this.state.imageExpanded && this.thumbnail()}
    @@ -1370,6 +1354,21 @@ export class PostListing extends Component { ); } + showPreviewButton() { + return ( + + ); + } + listing() { return ( <> @@ -1383,7 +1382,6 @@ export class PostListing extends Component { {this.mobileThumbnail()} {this.commentsLine(true)} - {this.userActionsLine()} {this.duplicatesLine()} {this.removeAndBanDialogs()}
    @@ -1394,26 +1392,27 @@ export class PostListing extends Component {
    {!this.props.viewOnly && ( - +
    + +
    )} -
    -
    {this.thumbnail()}
    -
    -
    +
    -
    +
    +
    {this.thumbnail()}
    +
    +
    {this.postTitleLine()} {this.createdLine()} {this.commentsLine()} {this.duplicatesLine()} - {this.userActionsLine()} {this.removeAndBanDialogs()}
    @@ -1426,10 +1425,11 @@ export class PostListing extends Component { private get myPost(): boolean { return ( - this.postView.creator.id == + this.postView.creator.id === UserService.Instance.myUserInfo?.local_user_view.person.id ); } + handleEditClick(i: PostListing) { i.setState({ showEdit: true }); } @@ -1553,6 +1553,7 @@ export class PostListing extends Component { post_id: i.postView.post.id, removed: !i.postView.post.removed, auth: myAuthRequired(), + reason: i.state.removeReason, }); } @@ -1624,13 +1625,13 @@ export class PostListing extends Component { handlePurgeSubmit(i: PostListing, event: any) { event.preventDefault(); i.setState({ purgeLoading: true }); - if (i.state.purgeType == PurgeType.Person) { + 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) { + } else if (i.state.purgeType === PurgeType.Post) { i.props.onPurgePost({ post_id: i.postView.post.id, reason: i.state.purgeReason, @@ -1663,7 +1664,7 @@ export class PostListing extends Component { const ban = !i.props.post_view.creator_banned_from_community; // If its an unban, restore all their data - if (ban == false) { + if (ban === false) { i.setState({ removeData: false }); } const person_id = i.props.post_view.creator.id; @@ -1671,7 +1672,7 @@ export class PostListing extends Component { const reason = i.state.banReason; const expires = futureDaysToUnixTime(i.state.banExpireDays); - if (i.state.banType == BanType.Community) { + if (i.state.banType === BanType.Community) { const community_id = i.postView.community.id; i.props.onBanPersonFromCommunity({ community_id, @@ -1742,6 +1743,15 @@ export class PostListing extends Component { event.preventDefault(); i.setState({ imageExpanded: !i.state.imageExpanded }); setupTippy(); + + const auth = myAuth(); + if (auth && !i.props.post_view.read) { + i.props.onMarkPostAsRead({ + post_id: i.props.post_view.post.id, + read: true, + auth: auth, + }); + } } handleViewSource(i: PostListing) { @@ -1791,7 +1801,7 @@ export class PostListing extends Component { this.props.moderators, this.props.admins, undefined, - true + true, ); } @@ -1799,7 +1809,7 @@ export class PostListing extends Component { return canMod( this.postView.creator.id, this.props.moderators, - this.props.admins + this.props.admins, ); }