]> Untitled Git - lemmy.git/commitdiff
Live post and comment resorting. Fixes #522
authorDessalines <tyhou13@gmx.com>
Sun, 9 Feb 2020 16:44:24 +0000 (11:44 -0500)
committerDessalines <tyhou13@gmx.com>
Sun, 9 Feb 2020 16:44:24 +0000 (11:44 -0500)
- Moving sorting to utils.

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

index a67b1c351896fb27c3f33276ddc5cc9b6d37eba8..0e51106398d57f9d946f522a494095d3ec4a1ae0 100644 (file)
@@ -15,6 +15,8 @@ import {
   TransferCommunityForm,
   TransferSiteForm,
   BanType,
+  CommentSortType,
+  SortType,
 } from '../interfaces';
 import { WebSocketService, UserService } from '../services';
 import {
@@ -61,6 +63,8 @@ interface CommentNodeProps {
   // TODO is this necessary, can't I get it from the node itself?
   postCreatorId?: number;
   showCommunity?: boolean;
+  sort?: CommentSortType;
+  sortType?: SortType;
 }
 
 export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
@@ -630,6 +634,8 @@ 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}
           />
         )}
         {/* A collapsed clearfix */}
index fb700cc4098bef5f480f56a5399c1fc689df7958..b15da5208954739d1e82c131c8f19b596024916d 100644 (file)
@@ -3,7 +3,10 @@ import {
   CommentNode as CommentNodeI,
   CommunityUser,
   UserView,
+  CommentSortType,
+  SortType,
 } from '../interfaces';
+import { commentSort, commentSortSortType } from '../utils';
 import { CommentNode } from './comment-node';
 
 interface CommentNodesState {}
@@ -18,6 +21,8 @@ interface CommentNodesProps {
   locked?: boolean;
   markable?: boolean;
   showCommunity?: boolean;
+  sort?: CommentSortType;
+  sortType?: SortType;
 }
 
 export class CommentNodes extends Component<
@@ -31,7 +36,7 @@ export class CommentNodes extends Component<
   render() {
     return (
       <div className="comments">
-        {this.props.nodes.map(node => (
+        {this.sorter().map(node => (
           <CommentNode
             node={node}
             noIndent={this.props.noIndent}
@@ -42,9 +47,21 @@ export class CommentNodes extends Component<
             postCreatorId={this.props.postCreatorId}
             markable={this.props.markable}
             showCommunity={this.props.showCommunity}
+            sort={this.props.sort}
+            sortType={this.props.sortType}
           />
         ))}
       </div>
     );
   }
+
+  sorter(): Array<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 32392ca1ddc3d9697f0e77c5c0de0f4bb6146a9f..e28c99bc7d7f2a82b0185d0d78155934736ec2aa 100644 (file)
@@ -178,9 +178,17 @@ export class Community extends Component<any, State> {
 
   listings() {
     return this.state.dataType == DataType.Post ? (
-      <PostListings posts={this.state.posts} removeDuplicates />
+      <PostListings
+        posts={this.state.posts}
+        removeDuplicates
+        sort={this.state.sort}
+      />
     ) : (
-      <CommentNodes nodes={commentsToFlatNodes(this.state.comments)} noIndent />
+      <CommentNodes
+        nodes={commentsToFlatNodes(this.state.comments)}
+        noIndent
+        sortType={this.state.sort}
+      />
     );
   }
 
index 99b1618de4b007efccc7f25e17cd1d979494bff8..c8e132f7a4d0c5f503dfa41a213348f5a9091aec 100644 (file)
@@ -51,6 +51,7 @@ import {
   createPostLikeFindRes,
   editPostFindRes,
   commentsToFlatNodes,
+  commentSortSortType,
 } from '../utils';
 import { i18n } from '../i18next';
 import { T } from 'inferno-i18next';
@@ -404,12 +405,18 @@ export class Main extends Component<any, MainState> {
 
   listings() {
     return this.state.dataType == DataType.Post ? (
-      <PostListings posts={this.state.posts} showCommunity removeDuplicates />
+      <PostListings
+        posts={this.state.posts}
+        showCommunity
+        removeDuplicates
+        sort={this.state.sort}
+      />
     ) : (
       <CommentNodes
         nodes={commentsToFlatNodes(this.state.comments)}
         noIndent
         showCommunity
+        sortType={this.state.sort}
       />
     );
   }
index 005c4fe03ce669ca7c32394efcdd7b768a8c741e..d61f624d425beeb29b8b6e7a391b9bbf05d648dd 100644 (file)
@@ -1,6 +1,7 @@
 import { Component } from 'inferno';
 import { Link } from 'inferno-router';
-import { Post } from '../interfaces';
+import { Post, SortType } from '../interfaces';
+import { postSort } from '../utils';
 import { PostListing } from './post-listing';
 import { i18n } from '../i18next';
 import { T } from 'inferno-i18next';
@@ -9,6 +10,7 @@ interface PostListingsProps {
   posts: Array<Post>;
   showCommunity?: boolean;
   removeDuplicates?: boolean;
+  sort?: SortType;
 }
 
 export class PostListings extends Component<PostListingsProps, any> {
@@ -20,10 +22,7 @@ export class PostListings extends Component<PostListingsProps, any> {
     return (
       <div>
         {this.props.posts.length > 0 ? (
-          (this.props.removeDuplicates
-            ? this.removeDuplicates(this.props.posts)
-            : this.props.posts
-          ).map(post => (
+          this.outer().map(post => (
             <>
               <PostListing
                 post={post}
@@ -47,6 +46,19 @@ export class PostListings extends Component<PostListingsProps, any> {
     );
   }
 
+  outer(): Array<Post> {
+    let out = this.props.posts;
+    if (this.props.removeDuplicates) {
+      out = this.removeDuplicates(out);
+    }
+
+    if (this.props.sort !== undefined) {
+      postSort(out, this.props.sort);
+    }
+
+    return out;
+  }
+
   removeDuplicates(posts: Array<Post>): Array<Post> {
     // A map from post url to list of posts (dupes)
     let urlMap = new Map<string, Array<Post>>();
index 1f2e40ba6be506d0c8b40fcc8bcea8ad837ed21b..b5b1fce364f2198f76f3275621d779fb83bcc2b3 100644 (file)
@@ -31,7 +31,6 @@ import {
 import { WebSocketService, UserService } from '../services';
 import {
   wsJsonToRes,
-  hotRank,
   toast,
   editCommentRes,
   saveCommentRes,
@@ -314,48 +313,9 @@ export class Post extends Component<any, PostState> {
       }
     }
 
-    this.sortTree(tree);
-
     return tree;
   }
 
-  sortTree(tree: Array<CommentNodeI>) {
-    // First, put removed and deleted comments at the bottom, then do your other sorts
-    if (this.state.commentSort == CommentSortType.Top) {
-      tree.sort(
-        (a, b) =>
-          +a.comment.removed - +b.comment.removed ||
-          +a.comment.deleted - +b.comment.deleted ||
-          b.comment.score - a.comment.score
-      );
-    } else if (this.state.commentSort == CommentSortType.New) {
-      tree.sort(
-        (a, b) =>
-          +a.comment.removed - +b.comment.removed ||
-          +a.comment.deleted - +b.comment.deleted ||
-          b.comment.published.localeCompare(a.comment.published)
-      );
-    } else if (this.state.commentSort == CommentSortType.Old) {
-      tree.sort(
-        (a, b) =>
-          +a.comment.removed - +b.comment.removed ||
-          +a.comment.deleted - +b.comment.deleted ||
-          a.comment.published.localeCompare(b.comment.published)
-      );
-    } else if (this.state.commentSort == CommentSortType.Hot) {
-      tree.sort(
-        (a, b) =>
-          +a.comment.removed - +b.comment.removed ||
-          +a.comment.deleted - +b.comment.deleted ||
-          hotRank(b.comment) - hotRank(a.comment)
-      );
-    }
-
-    for (let node of tree) {
-      this.sortTree(node.children);
-    }
-  }
-
   commentsTree() {
     let nodes = this.buildCommentsTree();
     return (
@@ -366,6 +326,7 @@ export class Post extends Component<any, PostState> {
           moderators={this.state.moderators}
           admins={this.state.admins}
           postCreatorId={this.state.post.creator_id}
+          sort={this.state.commentSort}
         />
       </div>
     );
index 8cdc02f0470b58dfd593a1ea3392affba546d30e..929877fc7fa9262ad6e30a5751639cc099c7471f 100644 (file)
@@ -20,6 +20,7 @@ import {
   PrivateMessage,
   User,
   SortType,
+  CommentSortType,
   ListingType,
   DataType,
   SearchType,
@@ -93,15 +94,22 @@ md.renderer.rules.emoji = function(token, idx) {
   return twemoji.parse(token[idx].content);
 };
 
-export function hotRank(comment: Comment): number {
-  // Rank = ScaleFactor * sign(Score) * log(1 + abs(Score)) / (Time + 2)^Gravity
+export function hotRankComment(comment: Comment): number {
+  return hotRank(comment.score, comment.published);
+}
+
+export function hotRankPost(post: Post): number {
+  return hotRank(post.score, post.newest_activity_time);
+}
 
-  let date: Date = new Date(comment.published + 'Z'); // Add Z to convert from UTC date
+export function hotRank(score: number, timeStr: string): number {
+  // Rank = ScaleFactor * sign(Score) * log(1 + abs(Score)) / (Time + 2)^Gravity
+  let date: Date = new Date(timeStr + 'Z'); // Add Z to convert from UTC date
   let now: Date = new Date();
   let hoursElapsed: number = (now.getTime() - date.getTime()) / 36e5;
 
   let rank =
-    (10000 * Math.log10(Math.max(1, 3 + comment.score))) /
+    (10000 * Math.log10(Math.max(1, 3 + score))) /
     Math.pow(hoursElapsed + 2, 1.8);
 
   // console.log(`Comment: ${comment.content}\nRank: ${rank}\nScore: ${comment.score}\nHours: ${hoursElapsed}`);
@@ -639,3 +647,95 @@ export function commentsToFlatNodes(
   }
   return nodes;
 }
+
+export function commentSort(tree: Array<CommentNode>, sort: CommentSortType) {
+  // First, put removed and deleted comments at the bottom, then do your other sorts
+  if (sort == CommentSortType.Top) {
+    tree.sort(
+      (a, b) =>
+        +a.comment.removed - +b.comment.removed ||
+        +a.comment.deleted - +b.comment.deleted ||
+        b.comment.score - a.comment.score
+    );
+  } else if (sort == CommentSortType.New) {
+    tree.sort(
+      (a, b) =>
+        +a.comment.removed - +b.comment.removed ||
+        +a.comment.deleted - +b.comment.deleted ||
+        b.comment.published.localeCompare(a.comment.published)
+    );
+  } else if (sort == CommentSortType.Old) {
+    tree.sort(
+      (a, b) =>
+        +a.comment.removed - +b.comment.removed ||
+        +a.comment.deleted - +b.comment.deleted ||
+        a.comment.published.localeCompare(b.comment.published)
+    );
+  } else if (sort == CommentSortType.Hot) {
+    tree.sort(
+      (a, b) =>
+        +a.comment.removed - +b.comment.removed ||
+        +a.comment.deleted - +b.comment.deleted ||
+        hotRankComment(b.comment) - hotRankComment(a.comment)
+    );
+  }
+
+  // Go through the children recursively
+  for (let node of tree) {
+    if (node.children) {
+      commentSort(node.children, sort);
+    }
+  }
+}
+
+export function commentSortSortType(tree: Array<CommentNode>, sort: SortType) {
+  commentSort(tree, convertCommentSortType(sort));
+}
+
+function convertCommentSortType(sort: SortType): CommentSortType {
+  if (
+    sort == SortType.TopAll ||
+    sort == SortType.TopDay ||
+    sort == SortType.TopWeek ||
+    sort == SortType.TopMonth ||
+    sort == SortType.TopYear
+  ) {
+    return CommentSortType.Top;
+  } else if (sort == SortType.New) {
+    return CommentSortType.New;
+  } else if (sort == SortType.Hot) {
+    return CommentSortType.Hot;
+  } else {
+    return CommentSortType.Hot;
+  }
+}
+
+export function postSort(posts: Array<Post>, sort: SortType) {
+  // 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.removed - +b.removed || +a.deleted - +b.deleted || b.score - a.score
+    );
+  } else if (sort == SortType.New) {
+    posts.sort(
+      (a, b) =>
+        +a.removed - +b.removed ||
+        +a.deleted - +b.deleted ||
+        b.published.localeCompare(a.published)
+    );
+  } else if (sort == SortType.Hot) {
+    posts.sort(
+      (a, b) =>
+        +a.removed - +b.removed ||
+        +a.deleted - +b.deleted ||
+        hotRankPost(b) - hotRankPost(a)
+    );
+  }
+}