Comments and posts no longer live-sorted. Fixes #51
authorDessalines <tyhou13@gmx.com>
Mon, 8 Feb 2021 04:23:31 +0000 (23:23 -0500)
committerDessalines <tyhou13@gmx.com>
Mon, 8 Feb 2021 04:23:31 +0000 (23:23 -0500)
- Only changing the view or sort, or reloading the page will resort.
- New comments by default added to the top, and left unsorted.

src/shared/components/comment-node.tsx
src/shared/components/comment-nodes.tsx
src/shared/components/community.tsx
src/shared/components/main.tsx
src/shared/components/post-listings.tsx
src/shared/components/post.tsx
src/shared/utils.ts

index 26eeaf0a874a978899d2cd4bf0c6bdd0741ed6e0..bf57a59d831d4a1d90a66de18f994e1d737716bd 100644 (file)
@@ -15,15 +15,10 @@ import {
   AddAdmin,
   TransferCommunity,
   TransferSite,
-  SortType,
   CommentView,
   UserMentionView,
 } from 'lemmy-js-client';
-import {
-  CommentSortType,
-  CommentNode as CommentNodeI,
-  BanType,
-} from '../interfaces';
+import { CommentNode as CommentNodeI, BanType } from '../interfaces';
 import { WebSocketService, UserService } from '../services';
 import {
   mdToHtml,
@@ -82,8 +77,6 @@ interface CommentNodeProps {
   // TODO is this necessary, can't I get it from the node itself?
   postCreatorId?: number;
   showCommunity?: boolean;
-  sort?: CommentSortType;
-  sortType?: SortType;
   enableDownvotes: boolean;
 }
 
@@ -745,8 +738,6 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
             moderators={this.props.moderators}
             admins={this.props.admins}
             postCreatorId={this.props.postCreatorId}
-            sort={this.props.sort}
-            sortType={this.props.sortType}
             enableDownvotes={this.props.enableDownvotes}
           />
         )}
index 90a7783a15e2541b120d8f3c900e6c6c35bca01c..327c9a47bb323fe30155a54434a62f8348e7c968 100644 (file)
@@ -1,11 +1,6 @@
 import { Component } from 'inferno';
-import { CommentSortType, CommentNode as CommentNodeI } from '../interfaces';
-import {
-  CommunityModeratorView,
-  UserViewSafe,
-  SortType,
-} from 'lemmy-js-client';
-import { commentSort, commentSortSortType } from '../utils';
+import { CommentNode as CommentNodeI } from '../interfaces';
+import { CommunityModeratorView, UserViewSafe } from 'lemmy-js-client';
 import { CommentNode } from './comment-node';
 
 interface CommentNodesState {}
@@ -22,8 +17,6 @@ interface CommentNodesProps {
   markable?: boolean;
   showContext?: boolean;
   showCommunity?: boolean;
-  sort?: CommentSortType;
-  sortType?: SortType;
   enableDownvotes: boolean;
 }
 
@@ -38,7 +31,7 @@ export class CommentNodes extends Component<
   render() {
     return (
       <div className="comments">
-        {this.sorter().map(node => (
+        {this.props.nodes.map(node => (
           <CommentNode
             key={node.comment_view.comment.id}
             node={node}
@@ -52,22 +45,10 @@ export class CommentNodes extends Component<
             markable={this.props.markable}
             showContext={this.props.showContext}
             showCommunity={this.props.showCommunity}
-            sort={this.props.sort}
-            sortType={this.props.sortType}
             enableDownvotes={this.props.enableDownvotes}
           />
         ))}
       </div>
     );
   }
-
-  sorter(): CommentNodeI[] {
-    if (this.props.sort !== undefined) {
-      commentSort(this.props.nodes, this.props.sort);
-    } else if (this.props.sortType !== undefined) {
-      commentSortSortType(this.props.nodes, this.props.sortType);
-    }
-
-    return this.props.nodes;
-  }
 }
index 4c4e6d1bcbe2e4ae471c4c92c3063b92ee474bd3..2865a25239958d06b95dec3ba41ed8c7fdd171fe 100644 (file)
@@ -291,7 +291,6 @@ export class Community extends Component<any, State> {
         <PostListings
           posts={this.state.posts}
           removeDuplicates
-          sort={this.state.sort}
           enableDownvotes={site.enable_downvotes}
           enableNsfw={site.enable_nsfw}
         />
@@ -306,7 +305,6 @@ export class Community extends Component<any, State> {
       <CommentNodes
         nodes={commentsToFlatNodes(this.state.comments)}
         noIndent
-        sortType={this.state.sort}
         showContext
         enableDownvotes={site.enable_downvotes}
       />
index 28795b560b41009b559edd4a237c95d491758eb6..2d4b7d7824b7ac08517774e15c73b18d5c51aac7 100644 (file)
@@ -561,7 +561,6 @@ export class Main extends Component<any, MainState> {
         posts={this.state.posts}
         showCommunity
         removeDuplicates
-        sort={this.state.sort}
         enableDownvotes={site.enable_downvotes}
         enableNsfw={site.enable_nsfw}
       />
@@ -570,7 +569,6 @@ export class Main extends Component<any, MainState> {
         nodes={commentsToFlatNodes(this.state.comments)}
         noIndent
         showCommunity
-        sortType={this.state.sort}
         showContext
         enableDownvotes={site.enable_downvotes}
       />
index a7e069372c37959d6ef579341ee102781693b57e..07803627ac072361b21cb019be832a2017f97b26 100644 (file)
@@ -1,7 +1,6 @@
 import { Component } from 'inferno';
 import { Link } from 'inferno-router';
-import { PostView, SortType } from 'lemmy-js-client';
-import { postSort } from '../utils';
+import { PostView } from 'lemmy-js-client';
 import { PostListing } from './post-listing';
 import { i18n } from '../i18next';
 import { T } from 'inferno-i18next';
@@ -10,7 +9,6 @@ interface PostListingsProps {
   posts: PostView[];
   showCommunity?: boolean;
   removeDuplicates?: boolean;
-  sort?: SortType;
   enableDownvotes: boolean;
   enableNsfw: boolean;
 }
@@ -58,10 +56,6 @@ export class PostListings extends Component<PostListingsProps, any> {
       out = this.removeDuplicates(out);
     }
 
-    if (this.props.sort !== undefined) {
-      postSort(out, this.props.sort, this.props.showCommunity == undefined);
-    }
-
     return out;
   }
 
index 2e6d31e889605017adcab68228a986f0935fd9bd..6db6104a6b4f25e68865e6b1eb6365a835098ea1 100644 (file)
@@ -52,6 +52,8 @@ import {
   setOptionalAuth,
   saveScrollPosition,
   restoreScrollPosition,
+  buildCommentsTree,
+  insertCommentIntoTree,
 } from '../utils';
 import { PostListing } from './post-listing';
 import { Sidebar } from './sidebar';
@@ -63,6 +65,7 @@ import { i18n } from '../i18next';
 interface PostState {
   postRes: GetPostResponse;
   postId: number;
+  commentTree: CommentNodeI[];
   commentId?: number;
   commentSort: CommentSortType;
   commentViewType: CommentViewType;
@@ -79,6 +82,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,
@@ -100,6 +104,10 @@ 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.commentTree = buildCommentsTree(
+        this.state.postRes.comments,
+        this.state.commentSort
+      );
       this.state.categories = this.isoData.routeData[1].categories;
       this.state.loading = false;
 
@@ -368,6 +376,7 @@ export class Post extends Component<any, PostState> {
   }
 
   commentsFlat() {
+    // These are already sorted by new
     return (
       <div>
         <CommentNodes
@@ -379,7 +388,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>
     );
@@ -404,58 +412,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>
@@ -480,6 +462,10 @@ 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
@@ -493,6 +479,7 @@ export class Post extends Component<any, PostState> {
       // 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();
index 33f9ff1928a5901d8c7ed7ba39eadbd2607d772b..2f4414283814f667474a17133c376fdc5ae77e54 100644 (file)
@@ -942,7 +942,7 @@ export function commentsToFlatNodes(comments: CommentView[]): CommentNodeI[] {
   return nodes;
 }
 
-export function commentSort(tree: CommentNodeI[], sort: CommentSortType) {
+function commentSort(tree: CommentNodeI[], sort: CommentSortType) {
   // First, put removed and deleted comments at the bottom, then do your other sorts
   if (sort == CommentSortType.Top) {
     tree.sort(
@@ -1008,53 +1008,82 @@ function convertCommentSortType(sort: SortType): CommentSortType {
   }
 }
 
-export function postSort(
-  posts: PostView[],
-  sort: SortType,
-  communityType: boolean
-) {
-  // First, put removed and deleted comments at the bottom, then do your other sorts
-  if (
-    sort == SortType.TopAll ||
-    sort == SortType.TopDay ||
-    sort == SortType.TopWeek ||
-    sort == SortType.TopMonth ||
-    sort == SortType.TopYear
-  ) {
-    posts.sort(
-      (a, b) =>
-        +a.post.removed - +b.post.removed ||
-        +a.post.deleted - +b.post.deleted ||
-        (communityType && +b.post.stickied - +a.post.stickied) ||
-        b.counts.score - a.counts.score
-    );
-  } else if (sort == SortType.New) {
-    posts.sort(
-      (a, b) =>
-        +a.post.removed - +b.post.removed ||
-        +a.post.deleted - +b.post.deleted ||
-        (communityType && +b.post.stickied - +a.post.stickied) ||
-        b.post.published.localeCompare(a.post.published)
-    );
-  } else if (sort == SortType.Hot) {
-    posts.sort(
-      (a, b) =>
-        +a.post.removed - +b.post.removed ||
-        +a.post.deleted - +b.post.deleted ||
-        (communityType && +b.post.stickied - +a.post.stickied) ||
-        hotRankPost(b) - hotRankPost(a)
-    );
-  } else if (sort == SortType.Active) {
-    posts.sort(
-      (a, b) =>
-        +a.post.removed - +b.post.removed ||
-        +a.post.deleted - +b.post.deleted ||
-        (communityType && +b.post.stickied - +a.post.stickied) ||
-        hotRankActivePost(b) - hotRankActivePost(a)
-    );
+export function buildCommentsTree(
+  comments: CommentView[],
+  commentSortType: CommentSortType
+): CommentNodeI[] {
+  let map = new Map<number, CommentNodeI>();
+  for (let comment_view of comments) {
+    let node: CommentNodeI = {
+      comment_view: comment_view,
+      children: [],
+    };
+    map.set(comment_view.comment.id, { ...node });
+  }
+  let tree: CommentNodeI[] = [];
+  for (let comment_view of 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);
+    }
+
+    setDepth(child);
+  }
+
+  commentSort(tree, commentSortType);
+
+  return tree;
+}
+
+function setDepth(node: CommentNodeI, i: number = 0) {
+  for (let child of node.children) {
+    child.depth = i;
+    setDepth(child, i + 1);
+  }
+}
+
+export function insertCommentIntoTree(tree: CommentNodeI[], cv: CommentView) {
+  // Building a fake node to be used for later
+  let node: CommentNodeI = {
+    comment_view: cv,
+    children: [],
+    depth: 0,
+  };
+
+  if (cv.comment.parent_id) {
+    let parentComment = searchCommentTree(tree, cv.comment.parent_id);
+    if (parentComment) {
+      node.depth = parentComment.depth + 1;
+      parentComment.children.unshift(node);
+    }
+  } else {
+    tree.unshift(node);
   }
 }
 
+export function searchCommentTree(
+  tree: CommentNodeI[],
+  id: number
+): CommentNodeI {
+  for (let node of tree) {
+    if (node.comment_view.comment.id === id) {
+      return node;
+    }
+
+    for (const child of node.children) {
+      const res = searchCommentTree([child], id);
+
+      if (res) {
+        return res;
+      }
+    }
+  }
+  return null;
+}
+
 export const colorList: string[] = [
   hsl(0),
   hsl(100),
@@ -1068,10 +1097,6 @@ function hsl(num: number) {
   return `hsla(${num}, 35%, 50%, 1)`;
 }
 
-// function randomHsl() {
-//   return `hsla(${Math.random() * 360}, 100%, 50%, 1)`;
-// }
-
 export function previewLines(
   text: string,
   maxChars: number = 300,