]> Untitled Git - lemmy-ui.git/blobdiff - src/shared/components/community/community.tsx
Use canonical URLs (#1883)
[lemmy-ui.git] / src / shared / components / community / community.tsx
index f2d7ad729a8e492b2944205314ae6e47e88c8dca..b88d6f6100e03843ef387ad60a3c8d524a0b1650 100644 (file)
@@ -1,4 +1,28 @@
-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,
@@ -52,42 +76,16 @@ import {
   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,
-  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";
@@ -100,6 +98,12 @@ import { SiteSidebar } from "../home/site-sidebar";
 import { PostListings } from "../post/post-listings";
 import { CommunityLink } from "./community-link";
 
+type CommunityData = RouteDataResponse<{
+  communityRes: GetCommunityResponse;
+  postsRes: GetPostsResponse;
+  commentsRes: GetCommentsResponse;
+}>;
+
 interface State {
   communityRes: RequestState<GetCommunityResponse>;
   postsRes: RequestState<GetPostsResponse>;
@@ -140,7 +144,7 @@ export class Community extends Component<
   RouteComponentProps<{ name: string }>,
   State
 > {
-  private isoData = setIsoData(this.context);
+  private isoData = setIsoData<CommunityData>(this.context);
   state: State = {
     communityRes: { state: "empty" },
     postsRes: { state: "empty" },
@@ -150,7 +154,7 @@ export class Community extends Component<
     finished: new Map(),
     isIsomorphic: false,
   };
-
+  private readonly mainContentRef: RefObject<HTMLElement>;
   constructor(props: RouteComponentProps<{ name: string }>, context: any) {
     super(props, context);
 
@@ -191,16 +195,17 @@ export class Community extends Component<
     this.handleSavePost = this.handleSavePost.bind(this);
     this.handlePurgePost = this.handlePurgePost.bind(this);
     this.handleFeaturePost = this.handleFeaturePost.bind(this);
-
+    this.mainContentRef = createRef();
     // Only fetch the data if coming from another route
     if (FirstLoadService.isFirstLoad) {
-      const [communityRes, postsRes, commentsRes] = this.isoData.routeData;
+      const { communityRes, commentsRes, postsRes } = this.isoData.routeData;
+
       this.state = {
         ...this.state,
+        isIsomorphic: true,
+        commentsRes,
         communityRes,
         postsRes,
-        commentsRes,
-        isIsomorphic: true,
       };
     }
   }
@@ -223,27 +228,21 @@ export class Community extends Component<
     setupTippy();
   }
 
-  componentWillUnmount() {
-    saveScrollPosition(this.context);
-  }
-
-  static fetchInitialData({
+  static async fetchInitialData({
     client,
     path,
     query: { dataType: urlDataType, page: urlPage, sort: urlSort },
     auth,
   }: InitialFetchRequest<QueryParams<CommunityProps>>): Promise<
-    RequestState<any>
-  >[] {
+    Promise<CommunityData>
+  > {
     const pathSplit = path.split("/");
-    const promises: Promise<RequestState<any>>[] = [];
 
     const communityName = pathSplit[2];
     const communityForm: GetCommunity = {
       name: communityName,
       auth,
     };
-    promises.push(client.getCommunity(communityForm));
 
     const dataType = getDataTypeFromQuery(urlDataType);
 
@@ -251,6 +250,11 @@ export class Community extends Component<
 
     const page = getPageFromString(urlPage);
 
+    let postsResponse: RequestState<GetPostsResponse> = { state: "empty" };
+    let commentsResponse: RequestState<GetCommentsResponse> = {
+      state: "empty",
+    };
+
     if (dataType === DataType.Post) {
       const getPostsForm: GetPosts = {
         community_name: communityName,
@@ -261,8 +265,8 @@ export class Community extends Component<
         saved_only: false,
         auth,
       };
-      promises.push(client.getPosts(getPostsForm));
-      promises.push(Promise.resolve({ state: "empty" }));
+
+      postsResponse = await client.getPosts(getPostsForm);
     } else {
       const getCommentsForm: GetComments = {
         community_name: communityName,
@@ -273,11 +277,15 @@ export class Community extends Component<
         saved_only: false,
         auth,
       };
-      promises.push(Promise.resolve({ state: "empty" }));
-      promises.push(client.getComments(getCommentsForm));
+
+      commentsResponse = await client.getComments(getCommentsForm);
     }
 
-    return promises;
+    return {
+      communityRes: await client.getCommunity(communityForm),
+      commentsRes: commentsResponse,
+      postsRes: postsResponse,
+    };
   }
 
   get documentTitle(): string {
@@ -304,19 +312,23 @@ export class Community extends Component<
             <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
@@ -331,10 +343,10 @@ export class Community extends Component<
                 {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>
           </>
         );
@@ -343,7 +355,9 @@ export class Community extends Component<
   }
 
   render() {
-    return <div className="container-lg">{this.renderCommunity()}</div>;
+    return (
+      <div className="community container-lg">{this.renderCommunity()}</div>
+    );
   }
 
   sidebar(res: GetCommunityResponse) {
@@ -472,7 +486,7 @@ export class Community extends Component<
       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
@@ -496,13 +510,13 @@ export class Community extends Component<
 
     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 && (
@@ -594,7 +608,6 @@ export class Community extends Component<
       });
     }
 
-    restoreScrollPosition(this.context);
     setupTippy();
   }
 
@@ -741,14 +754,14 @@ export class Community extends Component<
   async handleCommentReport(form: CreateCommentReport) {
     const reportRes = await HttpService.client.createCommentReport(form);
     if (reportRes.state == "success") {
-      toast(i18n.t("report_created"));
+      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"));
+      toast(I18NextService.i18n.t("report_created"));
     }
   }
 
@@ -774,7 +787,7 @@ export class Community extends Component<
     const transferCommunityRes = await HttpService.client.transferCommunity(
       form
     );
-    toast(i18n.t("transfer_community"));
+    toast(I18NextService.i18n.t("transfer_community"));
     this.updateCommunityFull(transferCommunityRes);
   }
 
@@ -863,7 +876,7 @@ export class Community extends Component<
 
   purgeItem(purgeRes: RequestState<PurgeItemResponse>) {
     if (purgeRes.state == "success") {
-      toast(i18n.t("purge_success"));
+      toast(I18NextService.i18n.t("purge_success"));
       this.context.router.history.push(`/`);
     }
   }