]> Untitled Git - lemmy.git/blob - ui/src/components/private-message.tsx
Adding private messaging, and matrix user ids.
[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   EditPrivateMessageForm,
6 } from '../interfaces';
7 import { WebSocketService, UserService } from '../services';
8 import { mdToHtml, pictshareAvatarThumbnail, showAvatars } from '../utils';
9 import { MomentTime } from './moment-time';
10 import { PrivateMessageForm } from './private-message-form';
11 import { i18n } from '../i18next';
12 import { T } from 'inferno-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 UserService.Instance.user.id == this.props.privateMessage.creator_id;
49   }
50
51   render() {
52     let message = this.props.privateMessage;
53     return (
54       <div class="mb-2">
55         <div>
56           <ul class="list-inline mb-0 text-muted small">
57             <li className="list-inline-item">
58               {this.mine ? i18n.t('to') : i18n.t('from')}
59             </li>
60             <li className="list-inline-item">
61               <Link
62                 className="text-info"
63                 to={
64                   this.mine
65                     ? `/u/${message.recipient_name}`
66                     : `/u/${message.creator_name}`
67                 }
68               >
69                 {(this.mine
70                   ? message.recipient_avatar
71                   : message.creator_avatar) &&
72                   showAvatars() && (
73                     <img
74                       height="32"
75                       width="32"
76                       src={pictshareAvatarThumbnail(
77                         this.mine
78                           ? message.recipient_avatar
79                           : message.creator_avatar
80                       )}
81                       class="rounded-circle mr-1"
82                     />
83                   )}
84                 <span>
85                   {this.mine ? message.recipient_name : message.creator_name}
86                 </span>
87               </Link>
88             </li>
89             <li className="list-inline-item">
90               <span>
91                 <MomentTime data={message} />
92               </span>
93             </li>
94             <li className="list-inline-item">
95               <div
96                 className="pointer text-monospace"
97                 onClick={linkEvent(this, this.handleMessageCollapse)}
98               >
99                 {this.state.collapsed ? '[+]' : '[-]'}
100               </div>
101             </li>
102           </ul>
103           {this.state.showEdit && (
104             <PrivateMessageForm
105               privateMessage={message}
106               onEdit={this.handlePrivateMessageEdit}
107               onCancel={this.handleReplyCancel}
108             />
109           )}
110           {!this.state.showEdit && !this.state.collapsed && (
111             <div>
112               {this.state.viewSource ? (
113                 <pre>{this.messageUnlessRemoved}</pre>
114               ) : (
115                 <div
116                   className="md-div"
117                   dangerouslySetInnerHTML={mdToHtml(this.messageUnlessRemoved)}
118                 />
119               )}
120               <ul class="list-inline mb-1 text-muted small font-weight-bold">
121                 {!this.mine && (
122                   <>
123                     <li className="list-inline-item">
124                       <span
125                         class="pointer"
126                         onClick={linkEvent(this, this.handleMarkRead)}
127                       >
128                         {message.read
129                           ? i18n.t('mark_as_unread')
130                           : i18n.t('mark_as_read')}
131                       </span>
132                     </li>
133                     <li className="list-inline-item">
134                       <span
135                         class="pointer"
136                         onClick={linkEvent(this, this.handleReplyClick)}
137                       >
138                         <T i18nKey="reply">#</T>
139                       </span>
140                     </li>
141                   </>
142                 )}
143                 {this.mine && (
144                   <>
145                     <li className="list-inline-item">
146                       <span
147                         class="pointer"
148                         onClick={linkEvent(this, this.handleEditClick)}
149                       >
150                         <T i18nKey="edit">#</T>
151                       </span>
152                     </li>
153                     <li className="list-inline-item">
154                       <span
155                         class="pointer"
156                         onClick={linkEvent(this, this.handleDeleteClick)}
157                       >
158                         {!message.deleted
159                           ? i18n.t('delete')
160                           : i18n.t('restore')}
161                       </span>
162                     </li>
163                   </>
164                 )}
165                 <li className="list-inline-item">•</li>
166                 <li className="list-inline-item">
167                   <span
168                     className="pointer"
169                     onClick={linkEvent(this, this.handleViewSource)}
170                   >
171                     <T i18nKey="view_source">#</T>
172                   </span>
173                 </li>
174               </ul>
175             </div>
176           )}
177         </div>
178         {this.state.showReply && (
179           <PrivateMessageForm
180             params={{
181               recipient_id: this.props.privateMessage.creator_id,
182             }}
183             onCreate={this.handlePrivateMessageCreate}
184           />
185         )}
186         {/* A collapsed clearfix */}
187         {this.state.collapsed && <div class="row col-12"></div>}
188       </div>
189     );
190   }
191
192   get messageUnlessRemoved(): string {
193     let message = this.props.privateMessage;
194     return message.deleted ? `*${i18n.t('deleted')}*` : message.content;
195   }
196
197   handleReplyClick(i: PrivateMessage) {
198     i.state.showReply = true;
199     i.setState(i.state);
200   }
201
202   handleEditClick(i: PrivateMessage) {
203     i.state.showEdit = true;
204     i.setState(i.state);
205   }
206
207   handleDeleteClick(i: PrivateMessage) {
208     let form: EditPrivateMessageForm = {
209       edit_id: i.props.privateMessage.id,
210       deleted: !i.props.privateMessage.deleted,
211     };
212     WebSocketService.Instance.editPrivateMessage(form);
213   }
214
215   handleReplyCancel() {
216     this.state.showReply = false;
217     this.state.showEdit = false;
218     this.setState(this.state);
219   }
220
221   handleMarkRead(i: PrivateMessage) {
222     let form: EditPrivateMessageForm = {
223       edit_id: i.props.privateMessage.id,
224       read: !i.props.privateMessage.read,
225     };
226     WebSocketService.Instance.editPrivateMessage(form);
227   }
228
229   handleMessageCollapse(i: PrivateMessage) {
230     i.state.collapsed = !i.state.collapsed;
231     i.setState(i.state);
232   }
233
234   handleViewSource(i: PrivateMessage) {
235     i.state.viewSource = !i.state.viewSource;
236     i.setState(i.state);
237   }
238
239   handlePrivateMessageEdit() {
240     this.state.showEdit = false;
241     this.setState(this.state);
242   }
243
244   handlePrivateMessageCreate() {
245     this.state.showReply = false;
246     this.setState(this.state);
247     alert(i18n.t('message_sent'));
248   }
249 }