]> Untitled Git - lemmy-ui.git/blob - src/shared/components/private_message/private-message.tsx
Fixing nav-link
[lemmy-ui.git] / src / shared / components / private_message / private-message.tsx
1 import { Component, linkEvent } from "inferno";
2 import {
3   DeletePrivateMessage,
4   MarkPrivateMessageAsRead,
5   PersonSafe,
6   PrivateMessageView,
7 } from "lemmy-js-client";
8 import { i18n } from "../../i18next";
9 import { UserService, WebSocketService } from "../../services";
10 import { authField, mdToHtml, toast, wsClient } from "../../utils";
11 import { Icon } from "../common/icon";
12 import { MomentTime } from "../common/moment-time";
13 import { PersonListing } from "../person/person-listing";
14 import { PrivateMessageForm } from "./private-message-form";
15
16 interface PrivateMessageState {
17   showReply: boolean;
18   showEdit: boolean;
19   collapsed: boolean;
20   viewSource: boolean;
21 }
22
23 interface PrivateMessageProps {
24   private_message_view: PrivateMessageView;
25 }
26
27 export class PrivateMessage extends Component<
28   PrivateMessageProps,
29   PrivateMessageState
30 > {
31   private emptyState: PrivateMessageState = {
32     showReply: false,
33     showEdit: false,
34     collapsed: false,
35     viewSource: false,
36   };
37
38   constructor(props: any, context: any) {
39     super(props, context);
40
41     this.state = this.emptyState;
42     this.handleReplyCancel = this.handleReplyCancel.bind(this);
43     this.handlePrivateMessageCreate =
44       this.handlePrivateMessageCreate.bind(this);
45     this.handlePrivateMessageEdit = this.handlePrivateMessageEdit.bind(this);
46   }
47
48   get mine(): boolean {
49     return (
50       UserService.Instance.myUserInfo &&
51       UserService.Instance.myUserInfo.local_user_view.person.id ==
52         this.props.private_message_view.creator.id
53     );
54   }
55
56   render() {
57     let message_view = this.props.private_message_view;
58     // TODO check this again
59     let otherPerson: PersonSafe = this.mine
60       ? message_view.recipient
61       : message_view.creator;
62
63     return (
64       <div class="border-top border-light">
65         <div>
66           <ul class="list-inline mb-0 text-muted small">
67             {/* TODO refactor this */}
68             <li className="list-inline-item">
69               {this.mine ? i18n.t("to") : i18n.t("from")}
70             </li>
71             <li className="list-inline-item">
72               <PersonListing person={otherPerson} />
73             </li>
74             <li className="list-inline-item">
75               <span>
76                 <MomentTime data={message_view.private_message} />
77               </span>
78             </li>
79             <li className="list-inline-item">
80               <div
81                 role="button"
82                 className="pointer text-monospace"
83                 onClick={linkEvent(this, this.handleMessageCollapse)}
84               >
85                 {this.state.collapsed ? (
86                   <Icon icon="plus-square" classes="icon-inline" />
87                 ) : (
88                   <Icon icon="minus-square" classes="icon-inline" />
89                 )}
90               </div>
91             </li>
92           </ul>
93           {this.state.showEdit && (
94             <PrivateMessageForm
95               recipient={otherPerson}
96               privateMessage={message_view}
97               onEdit={this.handlePrivateMessageEdit}
98               onCreate={this.handlePrivateMessageCreate}
99               onCancel={this.handleReplyCancel}
100             />
101           )}
102           {!this.state.showEdit && !this.state.collapsed && (
103             <div>
104               {this.state.viewSource ? (
105                 <pre>{this.messageUnlessRemoved}</pre>
106               ) : (
107                 <div
108                   className="md-div"
109                   dangerouslySetInnerHTML={mdToHtml(this.messageUnlessRemoved)}
110                 />
111               )}
112               <ul class="list-inline mb-0 text-muted font-weight-bold">
113                 {!this.mine && (
114                   <>
115                     <li className="list-inline-item">
116                       <button
117                         class="btn btn-link btn-animate text-muted"
118                         onClick={linkEvent(this, this.handleMarkRead)}
119                         data-tippy-content={
120                           message_view.private_message.read
121                             ? i18n.t("mark_as_unread")
122                             : i18n.t("mark_as_read")
123                         }
124                         aria-label={
125                           message_view.private_message.read
126                             ? i18n.t("mark_as_unread")
127                             : i18n.t("mark_as_read")
128                         }
129                       >
130                         <Icon
131                           icon="check"
132                           classes={`icon-inline ${
133                             message_view.private_message.read && "text-success"
134                           }`}
135                         />
136                       </button>
137                     </li>
138                     <li className="list-inline-item">
139                       <button
140                         class="btn btn-link btn-animate text-muted"
141                         onClick={linkEvent(this, this.handleReplyClick)}
142                         data-tippy-content={i18n.t("reply")}
143                         aria-label={i18n.t("reply")}
144                       >
145                         <Icon icon="reply1" classes="icon-inline" />
146                       </button>
147                     </li>
148                   </>
149                 )}
150                 {this.mine && (
151                   <>
152                     <li className="list-inline-item">
153                       <button
154                         class="btn btn-link btn-animate text-muted"
155                         onClick={linkEvent(this, this.handleEditClick)}
156                         data-tippy-content={i18n.t("edit")}
157                         aria-label={i18n.t("edit")}
158                       >
159                         <Icon icon="edit" classes="icon-inline" />
160                       </button>
161                     </li>
162                     <li className="list-inline-item">
163                       <button
164                         class="btn btn-link btn-animate text-muted"
165                         onClick={linkEvent(this, this.handleDeleteClick)}
166                         data-tippy-content={
167                           !message_view.private_message.deleted
168                             ? i18n.t("delete")
169                             : i18n.t("restore")
170                         }
171                         aria-label={
172                           !message_view.private_message.deleted
173                             ? i18n.t("delete")
174                             : i18n.t("restore")
175                         }
176                       >
177                         <Icon
178                           icon="trash"
179                           classes={`icon-inline ${
180                             message_view.private_message.deleted &&
181                             "text-danger"
182                           }`}
183                         />
184                       </button>
185                     </li>
186                   </>
187                 )}
188                 <li className="list-inline-item">
189                   <button
190                     class="btn btn-link btn-animate text-muted"
191                     onClick={linkEvent(this, this.handleViewSource)}
192                     data-tippy-content={i18n.t("view_source")}
193                     aria-label={i18n.t("view_source")}
194                   >
195                     <Icon
196                       icon="file-text"
197                       classes={`icon-inline ${
198                         this.state.viewSource && "text-success"
199                       }`}
200                     />
201                   </button>
202                 </li>
203               </ul>
204             </div>
205           )}
206         </div>
207         {this.state.showReply && (
208           <PrivateMessageForm
209             recipient={otherPerson}
210             onCreate={this.handlePrivateMessageCreate}
211           />
212         )}
213         {/* A collapsed clearfix */}
214         {this.state.collapsed && <div class="row col-12"></div>}
215       </div>
216     );
217   }
218
219   get messageUnlessRemoved(): string {
220     let message = this.props.private_message_view.private_message;
221     return message.deleted ? `*${i18n.t("deleted")}*` : message.content;
222   }
223
224   handleReplyClick(i: PrivateMessage) {
225     i.state.showReply = true;
226     i.setState(i.state);
227   }
228
229   handleEditClick(i: PrivateMessage) {
230     i.state.showEdit = true;
231     i.setState(i.state);
232   }
233
234   handleDeleteClick(i: PrivateMessage) {
235     let form: DeletePrivateMessage = {
236       private_message_id: i.props.private_message_view.private_message.id,
237       deleted: !i.props.private_message_view.private_message.deleted,
238       auth: authField(),
239     };
240     WebSocketService.Instance.send(wsClient.deletePrivateMessage(form));
241   }
242
243   handleReplyCancel() {
244     this.state.showReply = false;
245     this.state.showEdit = false;
246     this.setState(this.state);
247   }
248
249   handleMarkRead(i: PrivateMessage) {
250     let form: MarkPrivateMessageAsRead = {
251       private_message_id: i.props.private_message_view.private_message.id,
252       read: !i.props.private_message_view.private_message.read,
253       auth: authField(),
254     };
255     WebSocketService.Instance.send(wsClient.markPrivateMessageAsRead(form));
256   }
257
258   handleMessageCollapse(i: PrivateMessage) {
259     i.state.collapsed = !i.state.collapsed;
260     i.setState(i.state);
261   }
262
263   handleViewSource(i: PrivateMessage) {
264     i.state.viewSource = !i.state.viewSource;
265     i.setState(i.state);
266   }
267
268   handlePrivateMessageEdit() {
269     this.state.showEdit = false;
270     this.setState(this.state);
271   }
272
273   handlePrivateMessageCreate(message: PrivateMessageView) {
274     if (
275       UserService.Instance.myUserInfo &&
276       message.creator.id ==
277         UserService.Instance.myUserInfo.local_user_view.person.id
278     ) {
279       this.state.showReply = false;
280       this.setState(this.state);
281       toast(i18n.t("message_sent"));
282     }
283   }
284 }