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