Add hide post UI (#2408)

* Add hide post UI

* Add toggle to home and community feeds to show hidden posts

* Add i18n (and add lockfile to prettier ignore)

* Change show hidden style

* Tippy
This commit is contained in:
SleeplessOne1917 2024-04-12 13:43:09 +00:00 committed by GitHub
parent e48590b9d6
commit c1722a0b6b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
14 changed files with 242 additions and 14 deletions

@ -1 +1 @@
Subproject commit b0dab329ce23cfaec4a3a034ea2fee210888922e Subproject commit a94ef775f3f923067b48c1719cda206dbcf1a9e5

View file

@ -54,6 +54,7 @@ export type ContentPostProps = {
onLock: () => Promise<void>; onLock: () => Promise<void>;
onFeatureLocal: () => Promise<void>; onFeatureLocal: () => Promise<void>;
onFeatureCommunity: () => Promise<void>; onFeatureCommunity: () => Promise<void>;
onHidePost: () => Promise<void>;
} & ContentActionDropdownPropsBase; } & ContentActionDropdownPropsBase;
type ContentActionDropdownProps = ContentCommentProps | ContentPostProps; type ContentActionDropdownProps = ContentCommentProps | ContentPostProps;
@ -178,6 +179,17 @@ export default class ContentActionDropdown extends Component<
</button> </button>
<ul className="dropdown-menu" id={dropdownId}> <ul className="dropdown-menu" id={dropdownId}>
{type === "post" && (
<li>
<ActionButton
icon={this.props.postView.hidden ? "eye" : "eye-slash"}
label={I18NextService.i18n.t(
this.props.postView.hidden ? "unhide_post" : "hide_post",
)}
onClick={this.props.onHidePost}
/>
</li>
)}
{this.amCreator ? ( {this.amCreator ? (
<> <>
<li> <li>

View file

@ -0,0 +1,71 @@
import { StringBoolean } from "@utils/types";
import classNames from "classnames";
import { Icon } from "./icon";
import { tippyMixin } from "../mixins/tippy-mixin";
import { Component, linkEvent } from "inferno";
import { I18NextService } from "../../services/I18NextService";
// Need to disable this rule because ESLint flat out lies about labels not
// having an associated control in this component
/* eslint-disable jsx-a11y/label-has-associated-control */
interface PostHiddenSelectProps {
showHidden?: StringBoolean;
onShowHiddenChange: (hidden?: StringBoolean) => void;
}
function handleShowHiddenChange(i: PostHiddenSelect, event: any) {
i.props.onShowHiddenChange(event.target.value);
}
@tippyMixin
export default class PostHiddenSelect extends Component<
PostHiddenSelectProps,
never
> {
render() {
const { showHidden } = this.props;
return (
<div
className="show-hidden-select btn-group btn-group-toggle flex-wrap"
role="group"
>
<label
htmlFor="show-hidden"
className={classNames("pointer btn btn-outline-secondary", {
active: showHidden === "true",
})}
data-tippy-content={I18NextService.i18n.t("show_hidden_posts")}
>
<Icon icon="eye" inline />
<input
id="show-hidden"
type="radio"
className="btn-check"
value="true"
checked={showHidden === "true"}
onChange={linkEvent(this, handleShowHiddenChange)}
/>
</label>
<label
htmlFor="hide-hidden"
className={classNames("pointer btn btn-outline-secondary", {
active: showHidden !== "true",
})}
data-tippy-content={I18NextService.i18n.t("hide_hidden_posts")}
>
<Icon icon="eye-slash" inline />
<input
id="hide-hidden"
type="radio"
className="btn-check"
value="false"
checked={showHidden !== "true"}
onChange={linkEvent(this, handleShowHiddenChange)}
/>
</label>
</div>
);
}
}

View file

@ -20,7 +20,7 @@ import {
resourcesSettled, resourcesSettled,
} from "@utils/helpers"; } from "@utils/helpers";
import { scrollMixin } from "../mixins/scroll-mixin"; import { scrollMixin } from "../mixins/scroll-mixin";
import type { QueryParams } from "@utils/types"; import type { QueryParams, StringBoolean } from "@utils/types";
import { RouteDataResponse } from "@utils/types"; import { RouteDataResponse } from "@utils/types";
import { Component, RefObject, createRef, linkEvent } from "inferno"; import { Component, RefObject, createRef, linkEvent } from "inferno";
import { RouteComponentProps } from "inferno-router/dist/Route"; import { RouteComponentProps } from "inferno-router/dist/Route";
@ -59,6 +59,7 @@ import {
GetPosts, GetPosts,
GetPostsResponse, GetPostsResponse,
GetSiteResponse, GetSiteResponse,
HidePost,
LemmyHttp, LemmyHttp,
LockPost, LockPost,
MarkCommentReplyAsRead, MarkCommentReplyAsRead,
@ -111,6 +112,7 @@ import {
} from "../common/loading-skeleton"; } from "../common/loading-skeleton";
import { Sidebar } from "./sidebar"; import { Sidebar } from "./sidebar";
import { IRoutePropsWithFetch } from "../../routes"; import { IRoutePropsWithFetch } from "../../routes";
import PostHiddenSelect from "../common/post-hidden-select";
type CommunityData = RouteDataResponse<{ type CommunityData = RouteDataResponse<{
communityRes: GetCommunityResponse; communityRes: GetCommunityResponse;
@ -132,6 +134,7 @@ interface CommunityProps {
dataType: DataType; dataType: DataType;
sort: SortType; sort: SortType;
pageCursor?: PaginationCursor; pageCursor?: PaginationCursor;
showHidden?: StringBoolean;
} }
type Fallbacks = { sort: SortType }; type Fallbacks = { sort: SortType };
@ -148,6 +151,7 @@ export function getCommunityQueryParams(
dataType: getDataTypeFromQuery, dataType: getDataTypeFromQuery,
pageCursor: (cursor?: string) => cursor, pageCursor: (cursor?: string) => cursor,
sort: getSortTypeFromQuery, sort: getSortTypeFromQuery,
showHidden: (include?: StringBoolean) => include,
}, },
source, source,
{ {
@ -242,6 +246,9 @@ export class Community extends Component<CommunityRouteProps, State> {
this.handleSavePost = this.handleSavePost.bind(this); this.handleSavePost = this.handleSavePost.bind(this);
this.handlePurgePost = this.handlePurgePost.bind(this); this.handlePurgePost = this.handlePurgePost.bind(this);
this.handleFeaturePost = this.handleFeaturePost.bind(this); this.handleFeaturePost = this.handleFeaturePost.bind(this);
this.handleHidePost = this.handleHidePost.bind(this);
this.handleShowHiddenChange = this.handleShowHiddenChange.bind(this);
this.mainContentRef = createRef(); this.mainContentRef = createRef();
// Only fetch the data if coming from another route // Only fetch the data if coming from another route
if (FirstLoadService.isFirstLoad) { if (FirstLoadService.isFirstLoad) {
@ -274,7 +281,7 @@ export class Community extends Component<CommunityRouteProps, State> {
static async fetchInitialData({ static async fetchInitialData({
headers, headers,
query: { dataType, pageCursor, sort }, query: { dataType, pageCursor, sort, showHidden },
match: { match: {
params: { name: communityName }, params: { name: communityName },
}, },
@ -303,6 +310,7 @@ export class Community extends Component<CommunityRouteProps, State> {
sort, sort,
type_: "All", type_: "All",
saved_only: false, saved_only: false,
show_hidden: showHidden === "true",
}; };
postsFetch = client.getPosts(getPostsForm); postsFetch = client.getPosts(getPostsForm);
@ -481,6 +489,7 @@ export class Community extends Component<CommunityRouteProps, State> {
onTransferCommunity={this.handleTransferCommunity} onTransferCommunity={this.handleTransferCommunity}
onFeaturePost={this.handleFeaturePost} onFeaturePost={this.handleFeaturePost}
onMarkPostAsRead={async () => {}} onMarkPostAsRead={async () => {}}
onHidePost={this.handleHidePost}
/> />
); );
} }
@ -560,10 +569,7 @@ export class Community extends Component<CommunityRouteProps, State> {
} }
selects(res: GetCommunityResponse) { selects(res: GetCommunityResponse) {
// let communityRss = this.state.communityRes.map(r => const { dataType, sort, showHidden } = this.props;
// communityRSSUrl(r.community_view.community.actor_id, this.state.sort)
// );
const { dataType, sort } = this.props;
const communityRss = res const communityRss = res
? communityRSSUrl(res.community_view.community.actor_id, sort) ? communityRSSUrl(res.community_view.community.actor_id, sort)
: undefined; : undefined;
@ -576,6 +582,14 @@ export class Community extends Component<CommunityRouteProps, State> {
onChange={this.handleDataTypeChange} onChange={this.handleDataTypeChange}
/> />
</span> </span>
{dataType === DataType.Post && UserService.Instance.myUserInfo && (
<span className="me-3">
<PostHiddenSelect
showHidden={showHidden}
onShowHiddenChange={this.handleShowHiddenChange}
/>
</span>
)}
<span className="me-2"> <span className="me-2">
<SortSelect sort={sort} onChange={this.handleSortChange} /> <SortSelect sort={sort} onChange={this.handleSortChange} />
</span> </span>
@ -611,19 +625,36 @@ export class Community extends Component<CommunityRouteProps, State> {
this.updateUrl({ dataType, pageCursor: undefined }); this.updateUrl({ dataType, pageCursor: undefined });
} }
handleShowHiddenChange(show?: StringBoolean) {
this.updateUrl({
showHidden: show,
pageCursor: undefined,
});
}
handleShowSidebarMobile(i: Community) { handleShowSidebarMobile(i: Community) {
i.setState(({ showSidebarMobile }) => ({ i.setState(({ showSidebarMobile }) => ({
showSidebarMobile: !showSidebarMobile, showSidebarMobile: !showSidebarMobile,
})); }));
} }
async updateUrl({ dataType, pageCursor, sort }: Partial<CommunityProps>) { async updateUrl({
const { dataType: urlDataType, sort: urlSort } = this.props; dataType,
pageCursor,
sort,
showHidden,
}: Partial<CommunityProps>) {
const {
dataType: urlDataType,
sort: urlSort,
showHidden: urlShowHidden,
} = this.props;
const queryParams: QueryParams<CommunityProps> = { const queryParams: QueryParams<CommunityProps> = {
dataType: getDataTypeString(dataType ?? urlDataType), dataType: getDataTypeString(dataType ?? urlDataType),
pageCursor: pageCursor, pageCursor: pageCursor,
sort: sort ?? urlSort, sort: sort ?? urlSort,
showHidden: showHidden ?? urlShowHidden,
}; };
this.props.history.push( this.props.history.push(
@ -634,7 +665,7 @@ export class Community extends Component<CommunityRouteProps, State> {
} }
async fetchData() { async fetchData() {
const { dataType, pageCursor, sort } = this.props; const { dataType, pageCursor, sort, showHidden } = this.props;
const { name } = this.props.match.params; const { name } = this.props.match.params;
if (dataType === DataType.Post) { if (dataType === DataType.Post) {
@ -647,6 +678,7 @@ export class Community extends Component<CommunityRouteProps, State> {
type_: "All", type_: "All",
community_name: name, community_name: name,
saved_only: false, saved_only: false,
show_hidden: showHidden === "true",
}), }),
}); });
} else { } else {
@ -824,6 +856,26 @@ export class Community extends Component<CommunityRouteProps, State> {
this.findAndUpdatePost(lockRes); this.findAndUpdatePost(lockRes);
} }
async handleHidePost(form: HidePost) {
const hideRes = await HttpService.client.hidePost(form);
if (hideRes.state === "success") {
this.setState(prev => {
if (prev.postsRes.state === "success") {
for (const post of prev.postsRes.data.posts.filter(p =>
form.post_ids.some(id => id === p.post.id),
)) {
post.hidden = form.hide;
}
}
return prev;
});
toast(I18NextService.i18n.t(form.hide ? "post_hidden" : "post_unhidden"));
}
}
async handleDistinguishComment(form: DistinguishComment) { async handleDistinguishComment(form: DistinguishComment) {
const distinguishRes = await HttpService.client.distinguishComment(form); const distinguishRes = await HttpService.client.distinguishComment(form);
this.findAndUpdateComment(distinguishRes); this.findAndUpdateComment(distinguishRes);

View file

@ -21,7 +21,7 @@ import {
} from "@utils/helpers"; } from "@utils/helpers";
import { scrollMixin } from "../mixins/scroll-mixin"; import { scrollMixin } from "../mixins/scroll-mixin";
import { canCreateCommunity } from "@utils/roles"; import { canCreateCommunity } from "@utils/roles";
import type { QueryParams } from "@utils/types"; import type { QueryParams, StringBoolean } from "@utils/types";
import { RouteDataResponse } from "@utils/types"; import { RouteDataResponse } from "@utils/types";
import { NoOptionI18nKeys } from "i18next"; import { NoOptionI18nKeys } from "i18next";
import { Component, MouseEventHandler, linkEvent } from "inferno"; import { Component, MouseEventHandler, linkEvent } from "inferno";
@ -54,6 +54,7 @@ import {
GetPosts, GetPosts,
GetPostsResponse, GetPostsResponse,
GetSiteResponse, GetSiteResponse,
HidePost,
LemmyHttp, LemmyHttp,
ListCommunities, ListCommunities,
ListCommunitiesResponse, ListCommunitiesResponse,
@ -109,6 +110,7 @@ import {
} from "../common/loading-skeleton"; } from "../common/loading-skeleton";
import { RouteComponentProps } from "inferno-router/dist/Route"; import { RouteComponentProps } from "inferno-router/dist/Route";
import { IRoutePropsWithFetch } from "../../routes"; import { IRoutePropsWithFetch } from "../../routes";
import PostHiddenSelect from "../common/post-hidden-select";
import { snapToTop } from "@utils/browser"; import { snapToTop } from "@utils/browser";
interface HomeState { interface HomeState {
@ -130,6 +132,7 @@ interface HomeProps {
dataType: DataType; dataType: DataType;
sort: SortType; sort: SortType;
pageCursor?: PaginationCursor; pageCursor?: PaginationCursor;
showHidden?: StringBoolean;
} }
type HomeData = RouteDataResponse<{ type HomeData = RouteDataResponse<{
@ -206,6 +209,7 @@ export function getHomeQueryParams(
listingType: getListingTypeFromQuery, listingType: getListingTypeFromQuery,
pageCursor: (cursor?: string) => cursor, pageCursor: (cursor?: string) => cursor,
dataType: getDataTypeFromQuery, dataType: getDataTypeFromQuery,
showHidden: (include?: StringBoolean) => include,
}, },
source, source,
{ {
@ -287,6 +291,7 @@ export class Home extends Component<HomeRouteProps, HomeState> {
this.handleSortChange = this.handleSortChange.bind(this); this.handleSortChange = this.handleSortChange.bind(this);
this.handleListingTypeChange = this.handleListingTypeChange.bind(this); this.handleListingTypeChange = this.handleListingTypeChange.bind(this);
this.handleDataTypeChange = this.handleDataTypeChange.bind(this); this.handleDataTypeChange = this.handleDataTypeChange.bind(this);
this.handleShowHiddenChange = this.handleShowHiddenChange.bind(this);
this.handlePageNext = this.handlePageNext.bind(this); this.handlePageNext = this.handlePageNext.bind(this);
this.handlePagePrev = this.handlePagePrev.bind(this); this.handlePagePrev = this.handlePagePrev.bind(this);
@ -317,6 +322,7 @@ export class Home extends Component<HomeRouteProps, HomeState> {
this.handleSavePost = this.handleSavePost.bind(this); this.handleSavePost = this.handleSavePost.bind(this);
this.handlePurgePost = this.handlePurgePost.bind(this); this.handlePurgePost = this.handlePurgePost.bind(this);
this.handleFeaturePost = this.handleFeaturePost.bind(this); this.handleFeaturePost = this.handleFeaturePost.bind(this);
this.handleHidePost = this.handleHidePost.bind(this);
// Only fetch the data if coming from another route // Only fetch the data if coming from another route
if (FirstLoadService.isFirstLoad) { if (FirstLoadService.isFirstLoad) {
@ -349,7 +355,7 @@ export class Home extends Component<HomeRouteProps, HomeState> {
} }
static async fetchInitialData({ static async fetchInitialData({
query: { listingType, dataType, sort, pageCursor }, query: { listingType, dataType, sort, pageCursor, showHidden },
headers, headers,
}: InitialFetchRequest<HomePathProps, HomeProps>): Promise<HomeData> { }: InitialFetchRequest<HomePathProps, HomeProps>): Promise<HomeData> {
const client = wrapClient( const client = wrapClient(
@ -368,6 +374,7 @@ export class Home extends Component<HomeRouteProps, HomeState> {
limit: fetchLimit, limit: fetchLimit,
sort, sort,
saved_only: false, saved_only: false,
show_hidden: showHidden === "true",
}; };
postsFetch = client.getPosts(getPostsForm); postsFetch = client.getPosts(getPostsForm);
@ -658,11 +665,13 @@ export class Home extends Component<HomeRouteProps, HomeState> {
listingType, listingType,
pageCursor, pageCursor,
sort, sort,
showHidden,
}: Partial<HomeProps>) { }: Partial<HomeProps>) {
const { const {
dataType: urlDataType, dataType: urlDataType,
listingType: urlListingType, listingType: urlListingType,
sort: urlSort, sort: urlSort,
showHidden: urlShowHidden,
} = this.props; } = this.props;
const queryParams: QueryParams<HomeProps> = { const queryParams: QueryParams<HomeProps> = {
@ -670,6 +679,7 @@ export class Home extends Component<HomeRouteProps, HomeState> {
listingType: listingType ?? urlListingType, listingType: listingType ?? urlListingType,
pageCursor: pageCursor, pageCursor: pageCursor,
sort: sort ?? urlSort, sort: sort ?? urlSort,
showHidden: showHidden ?? urlShowHidden,
}; };
this.props.history.push({ this.props.history.push({
@ -739,6 +749,7 @@ export class Home extends Component<HomeRouteProps, HomeState> {
onTransferCommunity={this.handleTransferCommunity} onTransferCommunity={this.handleTransferCommunity}
onFeaturePost={this.handleFeaturePost} onFeaturePost={this.handleFeaturePost}
onMarkPostAsRead={async () => {}} onMarkPostAsRead={async () => {}}
onHidePost={this.handleHidePost}
/> />
); );
} }
@ -786,7 +797,7 @@ export class Home extends Component<HomeRouteProps, HomeState> {
} }
get selects() { get selects() {
const { listingType, dataType, sort } = this.props; const { listingType, dataType, sort, showHidden } = this.props;
return ( return (
<div className="row align-items-center mb-3 g-3"> <div className="row align-items-center mb-3 g-3">
@ -796,6 +807,14 @@ export class Home extends Component<HomeRouteProps, HomeState> {
onChange={this.handleDataTypeChange} onChange={this.handleDataTypeChange}
/> />
</div> </div>
{dataType === DataType.Post && UserService.Instance.myUserInfo && (
<div className="col-auto">
<PostHiddenSelect
showHidden={showHidden}
onShowHiddenChange={this.handleShowHiddenChange}
/>
</div>
)}
<div className="col-auto"> <div className="col-auto">
<ListingTypeSelect <ListingTypeSelect
type_={ type_={
@ -833,7 +852,7 @@ export class Home extends Component<HomeRouteProps, HomeState> {
} }
async fetchData() { async fetchData() {
const { dataType, pageCursor, listingType, sort } = this.props; const { dataType, pageCursor, listingType, sort, showHidden } = this.props;
if (dataType === DataType.Post) { if (dataType === DataType.Post) {
this.setState({ postsRes: LOADING_REQUEST }); this.setState({ postsRes: LOADING_REQUEST });
@ -844,6 +863,7 @@ export class Home extends Component<HomeRouteProps, HomeState> {
sort, sort,
saved_only: false, saved_only: false,
type_: listingType, type_: listingType,
show_hidden: showHidden === "true",
}), }),
}); });
} else { } else {
@ -899,6 +919,14 @@ export class Home extends Component<HomeRouteProps, HomeState> {
this.updateUrl({ dataType: val, pageCursor: undefined }); this.updateUrl({ dataType: val, pageCursor: undefined });
} }
handleShowHiddenChange(show?: StringBoolean) {
console.log(`Got ${show}`);
this.updateUrl({
showHidden: show,
pageCursor: undefined,
});
}
async handleAddModToCommunity(form: AddModToCommunity) { async handleAddModToCommunity(form: AddModToCommunity) {
// TODO not sure what to do here // TODO not sure what to do here
await HttpService.client.addModToCommunity(form); await HttpService.client.addModToCommunity(form);
@ -1049,6 +1077,26 @@ export class Home extends Component<HomeRouteProps, HomeState> {
this.updateBan(banRes); this.updateBan(banRes);
} }
async handleHidePost(form: HidePost) {
const hideRes = await HttpService.client.hidePost(form);
if (hideRes.state === "success") {
this.setState(prev => {
if (prev.postsRes.state === "success") {
for (const post of prev.postsRes.data.posts.filter(p =>
form.post_ids.some(id => id === p.post.id),
)) {
post.hidden = form.hide;
}
}
return prev;
});
toast(I18NextService.i18n.t(form.hide ? "post_hidden" : "post_unhidden"));
}
}
updateBanFromCommunity(banRes: RequestState<BanFromCommunityResponse>) { updateBanFromCommunity(banRes: RequestState<BanFromCommunityResponse>) {
// Maybe not necessary // Maybe not necessary
if (banRes.state === "success") { if (banRes.state === "success") {

View file

@ -210,6 +210,7 @@ export class PersonDetails extends Component<PersonDetailsProps, any> {
onAddAdmin={this.props.onAddAdmin} onAddAdmin={this.props.onAddAdmin}
onTransferCommunity={this.props.onTransferCommunity} onTransferCommunity={this.props.onTransferCommunity}
onMarkPostAsRead={this.props.onMarkPostAsRead} onMarkPostAsRead={this.props.onMarkPostAsRead}
onHidePost={async () => {}}
/> />
); );
} }
@ -322,6 +323,7 @@ export class PersonDetails extends Component<PersonDetailsProps, any> {
onAddAdmin={this.props.onAddAdmin} onAddAdmin={this.props.onAddAdmin}
onTransferCommunity={this.props.onTransferCommunity} onTransferCommunity={this.props.onTransferCommunity}
onMarkPostAsRead={this.props.onMarkPostAsRead} onMarkPostAsRead={this.props.onMarkPostAsRead}
onHidePost={async () => {}}
/> />
<hr className="my-3" /> <hr className="my-3" />
</> </>

View file

@ -475,6 +475,7 @@ export class PostForm extends Component<PostFormProps, PostFormState> {
onAddAdmin={async () => {}} onAddAdmin={async () => {}}
onTransferCommunity={async () => {}} onTransferCommunity={async () => {}}
onMarkPostAsRead={async () => {}} onMarkPostAsRead={async () => {}}
onHidePost={async () => {}}
/> />
</> </>
)} )}
@ -688,6 +689,7 @@ export class PostForm extends Component<PostFormProps, PostFormState> {
onAddAdmin={async () => {}} onAddAdmin={async () => {}}
onTransferCommunity={async () => {}} onTransferCommunity={async () => {}}
onMarkPostAsRead={async () => {}} onMarkPostAsRead={async () => {}}
onHidePost={async () => {}}
/> />
</> </>
) )

View file

@ -19,6 +19,7 @@ import {
DeletePost, DeletePost,
EditPost, EditPost,
FeaturePost, FeaturePost,
HidePost,
Language, Language,
LockPost, LockPost,
MarkPostAsRead, MarkPostAsRead,
@ -91,6 +92,7 @@ interface PostListingProps {
onAddAdmin(form: AddAdmin): Promise<void>; onAddAdmin(form: AddAdmin): Promise<void>;
onTransferCommunity(form: TransferCommunity): Promise<void>; onTransferCommunity(form: TransferCommunity): Promise<void>;
onMarkPostAsRead(form: MarkPostAsRead): void; onMarkPostAsRead(form: MarkPostAsRead): void;
onHidePost(form: HidePost): Promise<void>;
onScrollIntoCommentsClick?(e: MouseEvent): void; onScrollIntoCommentsClick?(e: MouseEvent): void;
} }
@ -126,6 +128,7 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
this.handleModBanFromSite = this.handleModBanFromSite.bind(this); this.handleModBanFromSite = this.handleModBanFromSite.bind(this);
this.handlePurgePerson = this.handlePurgePerson.bind(this); this.handlePurgePerson = this.handlePurgePerson.bind(this);
this.handlePurgePost = this.handlePurgePost.bind(this); this.handlePurgePost = this.handlePurgePost.bind(this);
this.handleHidePost = this.handleHidePost.bind(this);
} }
componentDidMount(): void { componentDidMount(): void {
@ -611,6 +614,7 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
onPurgeUser={this.handlePurgePerson} onPurgeUser={this.handlePurgePerson}
onPurgeContent={this.handlePurgePost} onPurgeContent={this.handlePurgePost}
onAppointAdmin={this.handleAppointAdmin} onAppointAdmin={this.handleAppointAdmin}
onHidePost={this.handleHidePost}
/> />
)} )}
</div> </div>
@ -907,6 +911,13 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
}); });
} }
handleHidePost() {
return this.props.onHidePost({
hide: !this.postView.hidden,
post_ids: [this.postView.post.id],
});
}
handleModBanFromCommunity({ handleModBanFromCommunity({
daysUntilExpires, daysUntilExpires,
reason, reason,

View file

@ -12,6 +12,7 @@ import {
DeletePost, DeletePost,
EditPost, EditPost,
FeaturePost, FeaturePost,
HidePost,
Language, Language,
LockPost, LockPost,
MarkPostAsRead, MarkPostAsRead,
@ -53,6 +54,7 @@ interface PostListingsProps {
onAddAdmin(form: AddAdmin): Promise<void>; onAddAdmin(form: AddAdmin): Promise<void>;
onTransferCommunity(form: TransferCommunity): Promise<void>; onTransferCommunity(form: TransferCommunity): Promise<void>;
onMarkPostAsRead(form: MarkPostAsRead): Promise<void>; onMarkPostAsRead(form: MarkPostAsRead): Promise<void>;
onHidePost(form: HidePost): Promise<void>;
} }
export class PostListings extends Component<PostListingsProps, any> { export class PostListings extends Component<PostListingsProps, any> {
@ -100,6 +102,7 @@ export class PostListings extends Component<PostListingsProps, any> {
onAddAdmin={this.props.onAddAdmin} onAddAdmin={this.props.onAddAdmin}
onTransferCommunity={this.props.onTransferCommunity} onTransferCommunity={this.props.onTransferCommunity}
onMarkPostAsRead={this.props.onMarkPostAsRead} onMarkPostAsRead={this.props.onMarkPostAsRead}
onHidePost={this.props.onHidePost}
/> />
{idx + 1 !== this.posts.length && <hr className="my-3" />} {idx + 1 !== this.posts.length && <hr className="my-3" />}
</> </>

View file

@ -94,6 +94,7 @@ export class PostReport extends Component<PostReportProps, PostReportState> {
onAddAdmin={async () => {}} onAddAdmin={async () => {}}
onTransferCommunity={async () => {}} onTransferCommunity={async () => {}}
onMarkPostAsRead={async () => {}} onMarkPostAsRead={async () => {}}
onHidePost={async () => {}}
/> />
<div> <div>
{I18NextService.i18n.t("reporter")}:{" "} {I18NextService.i18n.t("reporter")}:{" "}

View file

@ -61,6 +61,7 @@ import {
GetPost, GetPost,
GetPostResponse, GetPostResponse,
GetSiteResponse, GetSiteResponse,
HidePost,
LemmyHttp, LemmyHttp,
LockPost, LockPost,
MarkCommentReplyAsRead, MarkCommentReplyAsRead,
@ -195,6 +196,7 @@ export class Post extends Component<PostRouteProps, PostState> {
this.handleSavePost = this.handleSavePost.bind(this); this.handleSavePost = this.handleSavePost.bind(this);
this.handlePurgePost = this.handlePurgePost.bind(this); this.handlePurgePost = this.handlePurgePost.bind(this);
this.handleFeaturePost = this.handleFeaturePost.bind(this); this.handleFeaturePost = this.handleFeaturePost.bind(this);
this.handleHidePost = this.handleHidePost.bind(this);
this.handleScrollIntoCommentsClick = this.handleScrollIntoCommentsClick =
this.handleScrollIntoCommentsClick.bind(this); this.handleScrollIntoCommentsClick.bind(this);
@ -405,6 +407,7 @@ export class Post extends Component<PostRouteProps, PostState> {
onTransferCommunity={this.handleTransferCommunity} onTransferCommunity={this.handleTransferCommunity}
onFeaturePost={this.handleFeaturePost} onFeaturePost={this.handleFeaturePost}
onMarkPostAsRead={() => {}} onMarkPostAsRead={() => {}}
onHidePost={this.handleHidePost}
onScrollIntoCommentsClick={this.handleScrollIntoCommentsClick} onScrollIntoCommentsClick={this.handleScrollIntoCommentsClick}
/> />
<div ref={this.state.commentSectionRef} className="mb-2" /> <div ref={this.state.commentSectionRef} className="mb-2" />
@ -1044,6 +1047,22 @@ export class Post extends Component<PostRouteProps, PostState> {
} }
} }
async handleHidePost(form: HidePost) {
const hideRes = await HttpService.client.hidePost(form);
if (hideRes.state === "success") {
this.setState(s => {
if (s.postRes.state === "success") {
s.postRes.data.post_view.hidden = form.hide;
}
return s;
});
toast(I18NextService.i18n.t(form.hide ? "post_hidden" : "post_unhidden"));
}
}
updateBanFromCommunity(banRes: RequestState<BanFromCommunityResponse>) { updateBanFromCommunity(banRes: RequestState<BanFromCommunityResponse>) {
// Maybe not necessary // Maybe not necessary
if (banRes.state === "success") { if (banRes.state === "success") {

View file

@ -741,6 +741,7 @@ export class Search extends Component<SearchRouteProps, SearchState> {
onAddAdmin={async () => {}} onAddAdmin={async () => {}}
onTransferCommunity={async () => {}} onTransferCommunity={async () => {}}
onMarkPostAsRead={async () => {}} onMarkPostAsRead={async () => {}}
onHidePost={async () => {}}
/> />
)} )}
{i.type_ === "comments" && ( {i.type_ === "comments" && (
@ -892,6 +893,7 @@ export class Search extends Component<SearchRouteProps, SearchState> {
onAddAdmin={async () => {}} onAddAdmin={async () => {}}
onTransferCommunity={async () => {}} onTransferCommunity={async () => {}}
onMarkPostAsRead={() => {}} onMarkPostAsRead={() => {}}
onHidePost={async () => {}}
/> />
</div> </div>
</div> </div>

View file

@ -7,6 +7,7 @@ import { RouteDataResponse } from "./route-data-response";
import { ThemeColor } from "./theme-color"; import { ThemeColor } from "./theme-color";
import WithComment from "./with-comment"; import WithComment from "./with-comment";
import CrossPostParams from "./cross-post-params"; import CrossPostParams from "./cross-post-params";
import StringBoolean from "./string-boolean";
export { export {
Choice, Choice,
@ -18,4 +19,5 @@ export {
ThemeColor, ThemeColor,
WithComment, WithComment,
CrossPostParams, CrossPostParams,
StringBoolean,
}; };

View file

@ -0,0 +1,3 @@
type StringBoolean = "true" | "false";
export default StringBoolean;