-import { Component, linkEvent } from "inferno";
+import {
+ commentsToFlatNodes,
+ communityRSSUrl,
+ editComment,
+ editPost,
+ editWith,
+ enableDownvotes,
+ enableNsfw,
+ getCommentParentId,
+ getDataTypeString,
+ myAuth,
+ postToCommentSortType,
+ setIsoData,
+ showLocal,
+ updateCommunityBlock,
+ updatePersonBlock,
+} from "@utils/app";
+import {
+ getPageFromString,
+ getQueryParams,
+ getQueryString,
+} from "@utils/helpers";
+import type { QueryParams } from "@utils/types";
+import { RouteDataResponse } from "@utils/types";
+import { Component, RefObject, createRef, linkEvent } from "inferno";
import { RouteComponentProps } from "inferno-router/dist/Route";
import {
AddAdmin,
LockPost,
MarkCommentReplyAsRead,
MarkPersonMentionAsRead,
+ MarkPostAsRead,
PostResponse,
PurgeComment,
PurgeCommunity,
SortType,
TransferCommunity,
} from "lemmy-js-client";
-import { i18n } from "../../i18next";
+import { fetchLimit, relTags } from "../../config";
import {
CommentViewType,
DataType,
InitialFetchRequest,
} from "../../interfaces";
-import { UserService } from "../../services";
-import { FirstLoadService } from "../../services/FirstLoadService";
+import { FirstLoadService, I18NextService, UserService } from "../../services";
import { HttpService, RequestState } from "../../services/HttpService";
-import {
- QueryParams,
- RouteDataResponse,
- commentsToFlatNodes,
- communityRSSUrl,
- editComment,
- editPost,
- editWith,
- enableDownvotes,
- enableNsfw,
- fetchLimit,
- getCommentParentId,
- getDataTypeString,
- getPageFromString,
- getQueryParams,
- getQueryString,
- myAuth,
- postToCommentSortType,
- relTags,
- restoreScrollPosition,
- saveScrollPosition,
- setIsoData,
- setupTippy,
- showLocal,
- toast,
- updateCommunityBlock,
- updatePersonBlock,
-} from "../../utils";
+import { setupTippy } from "../../tippy";
+import { toast } from "../../toast";
import { CommentNodes } from "../comment/comment-nodes";
import { BannerIconHeader } from "../common/banner-icon-header";
import { DataTypeSelect } from "../common/data-type-select";
finished: new Map(),
isIsomorphic: false,
};
-
+ private readonly mainContentRef: RefObject<HTMLElement>;
constructor(props: RouteComponentProps<{ name: string }>, context: any) {
super(props, context);
this.handleSavePost = this.handleSavePost.bind(this);
this.handlePurgePost = this.handlePurgePost.bind(this);
this.handleFeaturePost = this.handleFeaturePost.bind(this);
-
+ this.handleMarkPostAsRead = this.handleMarkPostAsRead.bind(this);
+ this.mainContentRef = createRef();
// Only fetch the data if coming from another route
if (FirstLoadService.isFirstLoad) {
const { communityRes, commentsRes, postsRes } = this.isoData.routeData;
setupTippy();
}
- componentWillUnmount() {
- saveScrollPosition(this.context);
- }
-
static async fetchInitialData({
client,
path,
get documentTitle(): string {
const cRes = this.state.communityRes;
- return cRes.state == "success"
+ return cRes.state === "success"
? `${cRes.data.community_view.community.title} - ${this.isoData.site_res.site_view.site.name}`
: "";
}
<HtmlTags
title={this.documentTitle}
path={this.context.router.route.match.url}
+ canonicalPath={res.community_view.community.actor_id}
description={res.community_view.community.description}
image={res.community_view.community.icon}
/>
<div className="row">
- <div className="col-12 col-md-8">
+ <main
+ className="col-12 col-md-8 col-lg-9"
+ ref={this.mainContentRef}
+ >
{this.communityInfo(res)}
<div className="d-block d-md-none">
<button
- className="btn btn-secondary d-inline-block mb-2 mr-3"
+ className="btn btn-secondary d-inline-block mb-2 me-3"
onClick={linkEvent(this, this.handleShowSidebarMobile)}
>
- {i18n.t("sidebar")}{" "}
+ {I18NextService.i18n.t("sidebar")}{" "}
<Icon
icon={
this.state.showSidebarMobile
{this.selects(res)}
{this.listings(res)}
<Paginator page={page} onChange={this.handlePageChange} />
- </div>
- <div className="d-none d-md-block col-md-4">
+ </main>
+ <aside className="d-none d-md-block col-md-4 col-lg-3">
{this.sidebar(res)}
- </div>
+ </aside>
</div>
</>
);
}
render() {
- return <div className="container-lg">{this.renderCommunity()}</div>;
+ return (
+ <div className="community container-lg">{this.renderCommunity()}</div>
+ );
}
sidebar(res: GetCommunityResponse) {
onAddAdmin={this.handleAddAdmin}
onTransferCommunity={this.handleTransferCommunity}
onFeaturePost={this.handleFeaturePost}
+ onMarkPostAsRead={this.handleMarkPostAsRead}
/>
);
}
nodes={commentsToFlatNodes(this.state.commentsRes.data.comments)}
viewType={CommentViewType.Flat}
finished={this.state.finished}
- noIndent
+ isTopLevel
showContext
enableDownvotes={enableDownvotes(site_res)}
moderators={communityRes.moderators}
community && (
<div className="mb-2">
<BannerIconHeader banner={community.banner} icon={community.icon} />
- <h5 className="mb-0 overflow-wrap-anywhere">{community.title}</h5>
+ <h1 className="h4 mb-0 overflow-wrap-anywhere">{community.title}</h1>
<CommunityLink
community={community}
realLink
return (
<div className="mb-3">
- <span className="mr-3">
+ <span className="me-3">
<DataTypeSelect
type_={dataType}
onChange={this.handleDataTypeChange}
/>
</span>
- <span className="mr-2">
+ <span className="me-2">
<SortSelect sort={sort} onChange={this.handleSortChange} />
</span>
{communityRss && (
};
this.props.history.push(
- `/c/${this.props.match.params.name}${getQueryString(queryParams)}`
+ `/c/${this.props.match.params.name}${getQueryString(queryParams)}`,
);
await this.fetchData();
});
}
- restoreScrollPosition(this.context);
setupTippy();
}
this.updateCommunity(followCommunityRes);
// Update myUserInfo
- if (followCommunityRes.state == "success") {
+ if (followCommunityRes.state === "success") {
const communityId = followCommunityRes.data.community_view.community.id;
const mui = UserService.Instance.myUserInfo;
if (mui) {
- mui.follows = mui.follows.filter(i => i.community.id != communityId);
+ mui.follows = mui.follows.filter(i => i.community.id !== communityId);
}
}
}
async handleBlockCommunity(form: BlockCommunity) {
const blockCommunityRes = await HttpService.client.blockCommunity(form);
- if (blockCommunityRes.state == "success") {
+ if (blockCommunityRes.state === "success") {
updateCommunityBlock(blockCommunityRes.data);
this.setState(s => {
- if (s.communityRes.state == "success") {
+ if (s.communityRes.state === "success") {
s.communityRes.data.community_view.blocked =
blockCommunityRes.data.blocked;
}
async handleBlockPerson(form: BlockPerson) {
const blockPersonRes = await HttpService.client.blockPerson(form);
- if (blockPersonRes.state == "success") {
+ if (blockPersonRes.state === "success") {
updatePersonBlock(blockPersonRes.data);
}
}
async handleCommentReport(form: CreateCommentReport) {
const reportRes = await HttpService.client.createCommentReport(form);
- if (reportRes.state == "success") {
- toast(i18n.t("report_created"));
+ if (reportRes.state === "success") {
+ toast(I18NextService.i18n.t("report_created"));
}
}
async handlePostReport(form: CreatePostReport) {
const reportRes = await HttpService.client.createPostReport(form);
- if (reportRes.state == "success") {
- toast(i18n.t("report_created"));
+ if (reportRes.state === "success") {
+ toast(I18NextService.i18n.t("report_created"));
}
}
async handleAddAdmin(form: AddAdmin) {
const addAdminRes = await HttpService.client.addAdmin(form);
- if (addAdminRes.state == "success") {
+ if (addAdminRes.state === "success") {
this.setState(s => ((s.siteRes.admins = addAdminRes.data.admins), s));
}
}
async handleTransferCommunity(form: TransferCommunity) {
const transferCommunityRes = await HttpService.client.transferCommunity(
- form
+ form,
);
- toast(i18n.t("transfer_community"));
+ toast(I18NextService.i18n.t("transfer_community"));
this.updateCommunityFull(transferCommunityRes);
}
await HttpService.client.markPersonMentionAsRead(form);
}
+ async handleMarkPostAsRead(form: MarkPostAsRead) {
+ const res = await HttpService.client.markPostAsRead(form);
+ this.findAndUpdatePost(res);
+ }
+
async handleBanFromCommunity(form: BanFromCommunity) {
const banRes = await HttpService.client.banFromCommunity(form);
this.updateBanFromCommunity(banRes);
updateBanFromCommunity(banRes: RequestState<BanFromCommunityResponse>) {
// Maybe not necessary
- if (banRes.state == "success") {
+ if (banRes.state === "success") {
this.setState(s => {
- if (s.postsRes.state == "success") {
+ if (s.postsRes.state === "success") {
s.postsRes.data.posts
- .filter(c => c.creator.id == banRes.data.person_view.person.id)
+ .filter(c => c.creator.id === banRes.data.person_view.person.id)
.forEach(
- c => (c.creator_banned_from_community = banRes.data.banned)
+ c => (c.creator_banned_from_community = banRes.data.banned),
);
}
- if (s.commentsRes.state == "success") {
+ if (s.commentsRes.state === "success") {
s.commentsRes.data.comments
- .filter(c => c.creator.id == banRes.data.person_view.person.id)
+ .filter(c => c.creator.id === banRes.data.person_view.person.id)
.forEach(
- c => (c.creator_banned_from_community = banRes.data.banned)
+ c => (c.creator_banned_from_community = banRes.data.banned),
);
}
return s;
updateBan(banRes: RequestState<BanPersonResponse>) {
// Maybe not necessary
- if (banRes.state == "success") {
+ if (banRes.state === "success") {
this.setState(s => {
- if (s.postsRes.state == "success") {
+ if (s.postsRes.state === "success") {
s.postsRes.data.posts
- .filter(c => c.creator.id == banRes.data.person_view.person.id)
+ .filter(c => c.creator.id === banRes.data.person_view.person.id)
.forEach(c => (c.creator.banned = banRes.data.banned));
}
- if (s.commentsRes.state == "success") {
+ if (s.commentsRes.state === "success") {
s.commentsRes.data.comments
- .filter(c => c.creator.id == banRes.data.person_view.person.id)
+ .filter(c => c.creator.id === banRes.data.person_view.person.id)
.forEach(c => (c.creator.banned = banRes.data.banned));
}
return s;
updateCommunity(res: RequestState<CommunityResponse>) {
this.setState(s => {
- if (s.communityRes.state == "success" && res.state == "success") {
+ if (s.communityRes.state === "success" && res.state === "success") {
s.communityRes.data.community_view = res.data.community_view;
s.communityRes.data.discussion_languages =
res.data.discussion_languages;
updateCommunityFull(res: RequestState<GetCommunityResponse>) {
this.setState(s => {
- if (s.communityRes.state == "success" && res.state == "success") {
+ if (s.communityRes.state === "success" && res.state === "success") {
s.communityRes.data.community_view = res.data.community_view;
s.communityRes.data.moderators = res.data.moderators;
}
}
purgeItem(purgeRes: RequestState<PurgeItemResponse>) {
- if (purgeRes.state == "success") {
- toast(i18n.t("purge_success"));
+ if (purgeRes.state === "success") {
+ toast(I18NextService.i18n.t("purge_success"));
this.context.router.history.push(`/`);
}
}
findAndUpdateComment(res: RequestState<CommentResponse>) {
this.setState(s => {
- if (s.commentsRes.state == "success" && res.state == "success") {
+ if (s.commentsRes.state === "success" && res.state === "success") {
s.commentsRes.data.comments = editComment(
res.data.comment_view,
- s.commentsRes.data.comments
+ s.commentsRes.data.comments,
);
s.finished.set(res.data.comment_view.comment.id, true);
}
createAndUpdateComments(res: RequestState<CommentResponse>) {
this.setState(s => {
- if (s.commentsRes.state == "success" && res.state == "success") {
+ if (s.commentsRes.state === "success" && res.state === "success") {
s.commentsRes.data.comments.unshift(res.data.comment_view);
// Set finished for the parent
s.finished.set(
getCommentParentId(res.data.comment_view.comment) ?? 0,
- true
+ true,
);
}
return s;
findAndUpdateCommentReply(res: RequestState<CommentReplyResponse>) {
this.setState(s => {
- if (s.commentsRes.state == "success" && res.state == "success") {
+ if (s.commentsRes.state === "success" && res.state === "success") {
s.commentsRes.data.comments = editWith(
res.data.comment_reply_view,
- s.commentsRes.data.comments
+ s.commentsRes.data.comments,
);
}
return s;
findAndUpdatePost(res: RequestState<PostResponse>) {
this.setState(s => {
- if (s.postsRes.state == "success" && res.state == "success") {
+ if (s.postsRes.state === "success" && res.state === "success") {
s.postsRes.data.posts = editPost(
res.data.post_view,
- s.postsRes.data.posts
+ s.postsRes.data.posts,
);
}
return s;
updateModerators(res: RequestState<AddModToCommunityResponse>) {
// Update the moderators
this.setState(s => {
- if (s.communityRes.state == "success" && res.state == "success") {
+ if (s.communityRes.state === "success" && res.state === "success") {
s.communityRes.data.moderators = res.data.moderators;
}
return s;