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