]> Untitled Git - lemmy-ui.git/blobdiff - src/shared/components/post.tsx
Remove categories
[lemmy-ui.git] / src / shared / components / post.tsx
index 160dfccd74ba81efb18d0fc13c738f2b3f992e55..b1bd9aaa52608b709621b5859f63361ae3db8d2d 100644 (file)
@@ -1,6 +1,7 @@
-import { Component, linkEvent } from 'inferno';
-import { HtmlTags } from './html-tags';
-import { Subscription } from 'rxjs';
+import { Component, linkEvent } from "inferno";
+import { HtmlTags } from "./html-tags";
+import { Spinner } from "./icon";
+import { Subscription } from "rxjs";
 import {
   UserOperation,
   PostView,
@@ -20,16 +21,14 @@ import {
   SearchResponse,
   GetSiteResponse,
   GetCommunityResponse,
-  ListCategoriesResponse,
-  Category,
-} from 'lemmy-js-client';
+} from "lemmy-js-client";
 import {
   CommentSortType,
   CommentViewType,
   InitialFetchRequest,
   CommentNode as CommentNodeI,
-} from '../interfaces';
-import { WebSocketService, UserService } from '../services';
+} from "../interfaces";
+import { WebSocketService, UserService } from "../services";
 import {
   wsJsonToRes,
   toast,
@@ -50,17 +49,22 @@ import {
   wsClient,
   authField,
   setOptionalAuth,
-} from '../utils';
-import { PostListing } from './post-listing';
-import { Sidebar } from './sidebar';
-import { CommentForm } from './comment-form';
-import { CommentNodes } from './comment-nodes';
-import autosize from 'autosize';
-import { i18n } from '../i18next';
+  saveScrollPosition,
+  restoreScrollPosition,
+  buildCommentsTree,
+  insertCommentIntoTree,
+} from "../utils";
+import { PostListing } from "./post-listing";
+import { Sidebar } from "./sidebar";
+import { CommentForm } from "./comment-form";
+import { CommentNodes } from "./comment-nodes";
+import autosize from "autosize";
+import { i18n } from "../i18next";
 
 interface PostState {
   postRes: GetPostResponse;
   postId: number;
+  commentTree: CommentNodeI[];
   commentId?: number;
   commentSort: CommentSortType;
   commentViewType: CommentViewType;
@@ -68,7 +72,6 @@ interface PostState {
   loading: boolean;
   crossPosts: PostView[];
   siteRes: GetSiteResponse;
-  categories: Category[];
 }
 
 export class Post extends Component<any, PostState> {
@@ -77,6 +80,7 @@ export class Post extends Component<any, PostState> {
   private emptyState: PostState = {
     postRes: null,
     postId: getIdFromProps(this.props),
+    commentTree: [],
     commentId: getCommentIdFromProps(this.props),
     commentSort: CommentSortType.Hot,
     commentViewType: CommentViewType.Tree,
@@ -84,7 +88,6 @@ export class Post extends Component<any, PostState> {
     loading: true,
     crossPosts: [],
     siteRes: this.isoData.site_res,
-    categories: [],
   };
 
   constructor(props: any, context: any) {
@@ -98,15 +101,20 @@ export class Post extends Component<any, PostState> {
     // Only fetch the data if coming from another route
     if (this.isoData.path == this.context.router.route.match.url) {
       this.state.postRes = this.isoData.routeData[0];
-      this.state.categories = this.isoData.routeData[1].categories;
+      this.state.commentTree = buildCommentsTree(
+        this.state.postRes.comments,
+        this.state.commentSort
+      );
       this.state.loading = false;
 
-      if (isBrowser() && this.state.commentId) {
-        this.scrollCommentIntoView();
+      if (isBrowser()) {
+        this.fetchCrossPosts();
+        if (this.state.commentId) {
+          this.scrollCommentIntoView();
+        }
       }
     } else {
       this.fetchPost();
-      WebSocketService.Instance.send(wsClient.listCategories());
     }
   }
 
@@ -118,8 +126,22 @@ export class Post extends Component<any, PostState> {
     WebSocketService.Instance.send(wsClient.getPost(form));
   }
 
+  fetchCrossPosts() {
+    if (this.state.postRes.post_view.post.url) {
+      let form: Search = {
+        q: this.state.postRes.post_view.post.url,
+        type_: SearchType.Url,
+        sort: SortType.TopAll,
+        page: 1,
+        limit: 6,
+        auth: authField(false),
+      };
+      WebSocketService.Instance.send(wsClient.search(form));
+    }
+  }
+
   static fetchInitialData(req: InitialFetchRequest): Promise<any>[] {
-    let pathSplit = req.path.split('/');
+    let pathSplit = req.path.split("/");
     let promises: Promise<any>[] = [];
 
     let id = Number(pathSplit[2]);
@@ -130,7 +152,6 @@ export class Post extends Component<any, PostState> {
     setOptionalAuth(postForm, req.auth);
 
     promises.push(req.client.getPost(postForm));
-    promises.push(req.client.listCategories());
 
     return promises;
   }
@@ -138,16 +159,17 @@ export class Post extends Component<any, PostState> {
   componentWillUnmount() {
     this.subscription.unsubscribe();
     window.isoData.path = undefined;
+    saveScrollPosition(this.context);
   }
 
   componentDidMount() {
     WebSocketService.Instance.send(
       wsClient.postJoin({ post_id: this.state.postId })
     );
-    autosize(document.querySelectorAll('textarea'));
+    autosize(document.querySelectorAll("textarea"));
   }
 
-  componentDidUpdate(_lastProps: any, lastState: PostState, _snapshot: any) {
+  componentDidUpdate(_lastProps: any, lastState: PostState) {
     if (
       this.state.commentId &&
       !this.state.scrolled &&
@@ -172,7 +194,7 @@ export class Post extends Component<any, PostState> {
   scrollCommentIntoView() {
     var elmnt = document.getElementById(`comment-${this.state.commentId}`);
     elmnt.scrollIntoView();
-    elmnt.classList.add('mark');
+    elmnt.classList.add("mark");
     this.state.scrolled = true;
     this.markScrolledAsRead(this.state.commentId);
   }
@@ -194,7 +216,7 @@ export class Post extends Component<any, PostState> {
       UserService.Instance.user.id == parent_user_id
     ) {
       let form: MarkCommentAsRead = {
-        comment_id: found.creator.id,
+        comment_id: found.comment.id,
         read: true,
         auth: authField(),
       };
@@ -228,9 +250,7 @@ export class Post extends Component<any, PostState> {
       <div class="container">
         {this.state.loading ? (
           <h5>
-            <svg class="icon icon-spinner spin">
-              <use xlinkHref="#icon-spinner"></use>
-            </svg>
+            <Spinner />
           </h5>
         ) : (
           <div class="row">
@@ -277,10 +297,10 @@ export class Post extends Component<any, PostState> {
         <div class="btn-group btn-group-toggle flex-wrap mr-3 mb-2">
           <label
             className={`btn btn-outline-secondary pointer ${
-              this.state.commentSort === CommentSortType.Hot && 'active'
+              this.state.commentSort === CommentSortType.Hot && "active"
             }`}
           >
-            {i18n.t('hot')}
+            {i18n.t("hot")}
             <input
               type="radio"
               value={CommentSortType.Hot}
@@ -290,10 +310,10 @@ export class Post extends Component<any, PostState> {
           </label>
           <label
             className={`btn btn-outline-secondary pointer ${
-              this.state.commentSort === CommentSortType.Top && 'active'
+              this.state.commentSort === CommentSortType.Top && "active"
             }`}
           >
-            {i18n.t('top')}
+            {i18n.t("top")}
             <input
               type="radio"
               value={CommentSortType.Top}
@@ -303,10 +323,10 @@ export class Post extends Component<any, PostState> {
           </label>
           <label
             className={`btn btn-outline-secondary pointer ${
-              this.state.commentSort === CommentSortType.New && 'active'
+              this.state.commentSort === CommentSortType.New && "active"
             }`}
           >
-            {i18n.t('new')}
+            {i18n.t("new")}
             <input
               type="radio"
               value={CommentSortType.New}
@@ -316,10 +336,10 @@ export class Post extends Component<any, PostState> {
           </label>
           <label
             className={`btn btn-outline-secondary pointer ${
-              this.state.commentSort === CommentSortType.Old && 'active'
+              this.state.commentSort === CommentSortType.Old && "active"
             }`}
           >
-            {i18n.t('old')}
+            {i18n.t("old")}
             <input
               type="radio"
               value={CommentSortType.Old}
@@ -331,10 +351,10 @@ export class Post extends Component<any, PostState> {
         <div class="btn-group btn-group-toggle flex-wrap mb-2">
           <label
             className={`btn btn-outline-secondary pointer ${
-              this.state.commentViewType === CommentViewType.Chat && 'active'
+              this.state.commentViewType === CommentViewType.Chat && "active"
             }`}
           >
-            {i18n.t('chat')}
+            {i18n.t("chat")}
             <input
               type="radio"
               value={CommentViewType.Chat}
@@ -348,6 +368,7 @@ export class Post extends Component<any, PostState> {
   }
 
   commentsFlat() {
+    // These are already sorted by new
     return (
       <div>
         <CommentNodes
@@ -359,7 +380,6 @@ export class Post extends Component<any, PostState> {
           postCreatorId={this.state.postRes.post_view.creator.id}
           showContext
           enableDownvotes={this.state.siteRes.site_view.site.enable_downvotes}
-          sort={this.state.commentSort}
         />
       </div>
     );
@@ -375,7 +395,6 @@ export class Post extends Component<any, PostState> {
           online={this.state.postRes.online}
           enableNsfw={this.state.siteRes.site_view.site.enable_nsfw}
           showIcon
-          categories={this.state.categories}
         />
       </div>
     );
@@ -384,58 +403,32 @@ export class Post extends Component<any, PostState> {
   handleCommentSortChange(i: Post, event: any) {
     i.state.commentSort = Number(event.target.value);
     i.state.commentViewType = CommentViewType.Tree;
+    i.state.commentTree = buildCommentsTree(
+      i.state.postRes.comments,
+      i.state.commentSort
+    );
     i.setState(i.state);
   }
 
   handleCommentViewTypeChange(i: Post, event: any) {
     i.state.commentViewType = Number(event.target.value);
     i.state.commentSort = CommentSortType.New;
+    i.state.commentTree = buildCommentsTree(
+      i.state.postRes.comments,
+      i.state.commentSort
+    );
     i.setState(i.state);
   }
 
-  buildCommentsTree(): CommentNodeI[] {
-    let map = new Map<number, CommentNodeI>();
-    for (let comment_view of this.state.postRes.comments) {
-      let node: CommentNodeI = {
-        comment_view: comment_view,
-        children: [],
-      };
-      map.set(comment_view.comment.id, { ...node });
-    }
-    let tree: CommentNodeI[] = [];
-    for (let comment_view of this.state.postRes.comments) {
-      let child = map.get(comment_view.comment.id);
-      if (comment_view.comment.parent_id) {
-        let parent_ = map.get(comment_view.comment.parent_id);
-        parent_.children.push(child);
-      } else {
-        tree.push(child);
-      }
-
-      this.setDepth(child);
-    }
-
-    return tree;
-  }
-
-  setDepth(node: CommentNodeI, i: number = 0): void {
-    for (let child of node.children) {
-      child.depth = i;
-      this.setDepth(child, i + 1);
-    }
-  }
-
   commentsTree() {
-    let nodes = this.buildCommentsTree();
     return (
       <div>
         <CommentNodes
-          nodes={nodes}
+          nodes={this.state.commentTree}
           locked={this.state.postRes.post_view.post.locked}
           moderators={this.state.postRes.moderators}
           admins={this.state.siteRes.admins}
           postCreatorId={this.state.postRes.post_view.creator.id}
-          sort={this.state.commentSort}
           enableDownvotes={this.state.siteRes.site_view.site.enable_downvotes}
         />
       </div>
@@ -444,8 +437,9 @@ export class Post extends Component<any, PostState> {
 
   parseMessage(msg: any) {
     let op = wsUserOp(msg);
+    console.log(msg);
     if (msg.error) {
-      toast(i18n.t(msg.error), 'danger');
+      toast(i18n.t(msg.error), "danger");
       return;
     } else if (msg.reconnect) {
       let postId = Number(this.props.match.params.id);
@@ -459,30 +453,27 @@ export class Post extends Component<any, PostState> {
     } else if (op == UserOperation.GetPost) {
       let data = wsJsonToRes<GetPostResponse>(msg).data;
       this.state.postRes = data;
+      this.state.commentTree = buildCommentsTree(
+        this.state.postRes.comments,
+        this.state.commentSort
+      );
       this.state.loading = false;
 
       // Get cross-posts
-      if (this.state.postRes.post_view.post.url) {
-        let form: Search = {
-          q: this.state.postRes.post_view.post.url,
-          type_: SearchType.Url,
-          sort: SortType.TopAll,
-          page: 1,
-          limit: 6,
-          auth: authField(false),
-        };
-        WebSocketService.Instance.send(wsClient.search(form));
-      }
-
+      this.fetchCrossPosts();
       this.setState(this.state);
       setupTippy();
+      restoreScrollPosition(this.context);
     } else if (op == UserOperation.CreateComment) {
       let data = wsJsonToRes<CommentResponse>(msg).data;
 
-      // Necessary since it might be a user reply
+      // Necessary since it might be a user reply, which has the recipients, to avoid double
       if (data.recipient_ids.length == 0) {
         this.state.postRes.comments.unshift(data.comment_view);
+        insertCommentIntoTree(this.state.commentTree, data.comment_view);
+        this.state.postRes.post_view.counts.comments++;
         this.setState(this.state);
+        setupTippy();
       }
     } else if (
       op == UserOperation.EditComment ||
@@ -571,10 +562,6 @@ export class Post extends Component<any, PostState> {
       this.state.postRes.post_view.community = data.community_view.community;
       this.state.postRes.moderators = data.moderators;
       this.setState(this.state);
-    } else if (op == UserOperation.ListCategories) {
-      let data = wsJsonToRes<ListCategoriesResponse>(msg).data;
-      this.state.categories = data.categories;
-      this.setState(this.state);
     }
   }
 }