mirror of
https://github.com/LemmyNet/lemmy-ui.git
synced 2024-11-22 14:45:20 +00:00
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:
parent
e48590b9d6
commit
c1722a0b6b
|
@ -1 +1 @@
|
||||||
Subproject commit b0dab329ce23cfaec4a3a034ea2fee210888922e
|
Subproject commit a94ef775f3f923067b48c1719cda206dbcf1a9e5
|
|
@ -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>
|
||||||
|
|
71
src/shared/components/common/post-hidden-select.tsx
Normal file
71
src/shared/components/common/post-hidden-select.tsx
Normal 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>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -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);
|
||||||
|
|
|
@ -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") {
|
||||||
|
|
|
@ -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" />
|
||||||
</>
|
</>
|
||||||
|
|
|
@ -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 () => {}}
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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" />}
|
||||||
</>
|
</>
|
||||||
|
|
|
@ -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")}:{" "}
|
||||||
|
|
|
@ -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") {
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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,
|
||||||
};
|
};
|
||||||
|
|
3
src/shared/utils/types/string-boolean.ts
Normal file
3
src/shared/utils/types/string-boolean.ts
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
type StringBoolean = "true" | "false";
|
||||||
|
|
||||||
|
export default StringBoolean;
|
Loading…
Reference in a new issue