]> Untitled Git - lemmy-ui.git/blob - src/shared/components/post/post-listings.tsx
fix submodule error
[lemmy-ui.git] / src / shared / components / post / post-listings.tsx
1 import { Component } from "inferno";
2 import { T } from "inferno-i18next-dess";
3 import { Link } from "inferno-router";
4 import {
5   AddAdmin,
6   AddModToCommunity,
7   BanFromCommunity,
8   BanPerson,
9   BlockPerson,
10   CreatePostLike,
11   CreatePostReport,
12   DeletePost,
13   EditPost,
14   FeaturePost,
15   Language,
16   LockPost,
17   MarkPostAsRead,
18   PostView,
19   PurgePerson,
20   PurgePost,
21   RemovePost,
22   SavePost,
23   TransferCommunity,
24 } from "lemmy-js-client";
25 import { I18NextService } from "../../services";
26 import { PostListing } from "./post-listing";
27
28 interface PostListingsProps {
29   posts: PostView[];
30   allLanguages: Language[];
31   siteLanguages: number[];
32   showCommunity?: boolean;
33   removeDuplicates?: boolean;
34   enableDownvotes?: boolean;
35   enableNsfw?: boolean;
36   viewOnly?: boolean;
37   onPostEdit(form: EditPost): void;
38   onPostVote(form: CreatePostLike): void;
39   onPostReport(form: CreatePostReport): void;
40   onBlockPerson(form: BlockPerson): void;
41   onLockPost(form: LockPost): void;
42   onDeletePost(form: DeletePost): void;
43   onRemovePost(form: RemovePost): void;
44   onSavePost(form: SavePost): void;
45   onFeaturePost(form: FeaturePost): void;
46   onPurgePerson(form: PurgePerson): void;
47   onPurgePost(form: PurgePost): void;
48   onBanPersonFromCommunity(form: BanFromCommunity): void;
49   onBanPerson(form: BanPerson): void;
50   onAddModToCommunity(form: AddModToCommunity): void;
51   onAddAdmin(form: AddAdmin): void;
52   onTransferCommunity(form: TransferCommunity): void;
53   onMarkPostAsRead(form: MarkPostAsRead): void;
54 }
55
56 export class PostListings extends Component<PostListingsProps, any> {
57   duplicatesMap = new Map<number, PostView[]>();
58
59   constructor(props: any, context: any) {
60     super(props, context);
61   }
62
63   get posts() {
64     return this.props.removeDuplicates
65       ? this.removeDuplicates()
66       : this.props.posts;
67   }
68
69   render() {
70     return (
71       <div className="post-listings">
72         {this.posts.length > 0 ? (
73           this.posts.map((post_view, idx) => (
74             <>
75               <PostListing
76                 post_view={post_view}
77                 crossPosts={this.duplicatesMap.get(post_view.post.id)}
78                 showCommunity={this.props.showCommunity}
79                 enableDownvotes={this.props.enableDownvotes}
80                 enableNsfw={this.props.enableNsfw}
81                 viewOnly={this.props.viewOnly}
82                 allLanguages={this.props.allLanguages}
83                 siteLanguages={this.props.siteLanguages}
84                 onPostEdit={this.props.onPostEdit}
85                 onPostVote={this.props.onPostVote}
86                 onPostReport={this.props.onPostReport}
87                 onBlockPerson={this.props.onBlockPerson}
88                 onLockPost={this.props.onLockPost}
89                 onDeletePost={this.props.onDeletePost}
90                 onRemovePost={this.props.onRemovePost}
91                 onSavePost={this.props.onSavePost}
92                 onFeaturePost={this.props.onFeaturePost}
93                 onPurgePerson={this.props.onPurgePerson}
94                 onPurgePost={this.props.onPurgePost}
95                 onBanPersonFromCommunity={this.props.onBanPersonFromCommunity}
96                 onBanPerson={this.props.onBanPerson}
97                 onAddModToCommunity={this.props.onAddModToCommunity}
98                 onAddAdmin={this.props.onAddAdmin}
99                 onTransferCommunity={this.props.onTransferCommunity}
100                 onMarkPostAsRead={this.props.onMarkPostAsRead}
101               />
102               {idx + 1 !== this.posts.length && <hr className="my-3" />}
103             </>
104           ))
105         ) : (
106           <>
107             <div>{I18NextService.i18n.t("no_posts")}</div>
108             {this.props.showCommunity && (
109               <T i18nKey="subscribe_to_communities">
110                 #<Link to="/communities">#</Link>
111               </T>
112             )}
113           </>
114         )}
115       </div>
116     );
117   }
118
119   removeDuplicates(): PostView[] {
120     // Must use a spread to clone the props, because splice will fail below otherwise.
121     const posts = [...this.props.posts].filter(empty => empty);
122
123     // A map from post url to list of posts (dupes)
124     const urlMap = new Map<string, PostView[]>();
125
126     // Loop over the posts, find ones with same urls
127     for (const pv of posts) {
128       const url = pv.post.url;
129       if (
130         !pv.post.deleted &&
131         !pv.post.removed &&
132         !pv.community.deleted &&
133         !pv.community.removed &&
134         url
135       ) {
136         if (!urlMap.get(url)) {
137           urlMap.set(url, [pv]);
138         } else {
139           urlMap.get(url)?.push(pv);
140         }
141       }
142     }
143
144     // Sort by oldest
145     // Remove the ones that have no length
146     for (const e of urlMap.entries()) {
147       if (e[1].length === 1) {
148         urlMap.delete(e[0]);
149       } else {
150         e[1].sort((a, b) => a.post.published.localeCompare(b.post.published));
151       }
152     }
153
154     for (let i = 0; i < posts.length; i++) {
155       const pv = posts[i];
156       const url = pv.post.url;
157       if (url) {
158         const found = urlMap.get(url);
159         if (found) {
160           // If its the oldest, add
161           if (pv.post.id === found[0].post.id) {
162             this.duplicatesMap.set(pv.post.id, found.slice(1));
163           }
164           // Otherwise, delete it
165           else {
166             posts.splice(i--, 1);
167           }
168         }
169       }
170     }
171
172     return posts;
173   }
174 }