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