]> Untitled Git - lemmy-ui.git/blob - src/shared/components/post/post-listings.tsx
merge
[lemmy-ui.git] / src / shared / components / post / post-listings.tsx
1 import { None, Some } from "@sniptt/monads";
2 import { Component } from "inferno";
3 import { T } from "inferno-i18next-dess";
4 import { Link } from "inferno-router";
5 import { PostView } from "lemmy-js-client";
6 import { i18n } from "../../i18next";
7 import { PostListing } from "./post-listing";
8
9 interface PostListingsProps {
10   posts: PostView[];
11   showCommunity?: boolean;
12   removeDuplicates?: boolean;
13   enableDownvotes: boolean;
14   enableNsfw: boolean;
15 }
16
17 export class PostListings extends Component<PostListingsProps, any> {
18   duplicatesMap = new Map<number, PostView[]>();
19
20   constructor(props: any, context: any) {
21     super(props, context);
22   }
23
24   get posts() {
25     return this.props.removeDuplicates
26       ? this.removeDuplicates()
27       : this.props.posts;
28   }
29
30   render() {
31     return (
32       <div>
33         {this.posts.length > 0 ? (
34           this.posts.map(post_view => (
35             <>
36               <PostListing
37                 post_view={post_view}
38                 duplicates={Some(this.duplicatesMap.get(post_view.post.id))}
39                 moderators={None}
40                 admins={None}
41                 showCommunity={this.props.showCommunity}
42                 enableDownvotes={this.props.enableDownvotes}
43                 enableNsfw={this.props.enableNsfw}
44               />
45               <hr class="my-3" />
46             </>
47           ))
48         ) : (
49           <>
50             <div>{i18n.t("no_posts")}</div>
51             {this.props.showCommunity && (
52               <T i18nKey="subscribe_to_communities">
53                 #<Link to="/communities">#</Link>
54               </T>
55             )}
56           </>
57         )}
58       </div>
59     );
60   }
61
62   removeDuplicates(): PostView[] {
63     // Must use a spread to clone the props, because splice will fail below otherwise.
64     let posts = [...this.props.posts];
65
66     // A map from post url to list of posts (dupes)
67     let urlMap = new Map<string, PostView[]>();
68
69     // Loop over the posts, find ones with same urls
70     for (let pv of posts) {
71       !pv.post.deleted &&
72         !pv.post.removed &&
73         !pv.community.deleted &&
74         !pv.community.removed &&
75         pv.post.url.match({
76           some: url => {
77             if (!urlMap.get(url)) {
78               urlMap.set(url, [pv]);
79             } else {
80               urlMap.get(url).push(pv);
81             }
82           },
83           none: void 0,
84         });
85     }
86
87     // Sort by oldest
88     // Remove the ones that have no length
89     for (let e of urlMap.entries()) {
90       if (e[1].length == 1) {
91         urlMap.delete(e[0]);
92       } else {
93         e[1].sort((a, b) => a.post.published.localeCompare(b.post.published));
94       }
95     }
96
97     for (let i = 0; i < posts.length; i++) {
98       let pv = posts[i];
99       pv.post.url.match({
100         some: url => {
101           let found = urlMap.get(url);
102           if (found) {
103             // If its the oldest, add
104             if (pv.post.id == found[0].post.id) {
105               this.duplicatesMap.set(pv.post.id, found.slice(1));
106             }
107             // Otherwise, delete it
108             else {
109               posts.splice(i--, 1);
110             }
111           }
112         },
113         none: void 0,
114       });
115     }
116
117     return posts;
118   }
119 }