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