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