1 import { Component, linkEvent } from 'inferno';
2 import { Link } from 'inferno-router';
4 PrivateMessage as PrivateMessageI,
5 EditPrivateMessageForm,
6 } from '../interfaces';
7 import { WebSocketService, UserService } from '../services';
10 pictshareAvatarThumbnail,
14 import { MomentTime } from './moment-time';
15 import { PrivateMessageForm } from './private-message-form';
16 import { i18n } from '../i18next';
18 interface PrivateMessageState {
25 interface PrivateMessageProps {
26 privateMessage: PrivateMessageI;
29 export class PrivateMessage extends Component<
33 private emptyState: PrivateMessageState = {
40 constructor(props: any, context: any) {
41 super(props, context);
43 this.state = this.emptyState;
44 this.handleReplyCancel = this.handleReplyCancel.bind(this);
45 this.handlePrivateMessageCreate = this.handlePrivateMessageCreate.bind(
48 this.handlePrivateMessageEdit = this.handlePrivateMessageEdit.bind(this);
52 return UserService.Instance.user.id == this.props.privateMessage.creator_id;
56 let message = this.props.privateMessage;
58 <div class="border-top border-light">
60 <ul class="list-inline mb-0 text-muted small">
61 {/* TODO refactor this */}
62 <li className="list-inline-item">
63 {this.mine ? i18n.t('to') : i18n.t('from')}
65 <li className="list-inline-item">
67 className="text-body font-weight-bold"
70 ? `/u/${message.recipient_name}`
71 : `/u/${message.creator_name}`
75 ? message.recipient_avatar
76 : message.creator_avatar) &&
81 src={pictshareAvatarThumbnail(
83 ? message.recipient_avatar
84 : message.creator_avatar
86 class="rounded-circle mr-1"
90 {this.mine ? message.recipient_name : message.creator_name}
94 <li className="list-inline-item">
96 <MomentTime data={message} />
99 <li className="list-inline-item">
101 className="pointer text-monospace"
102 onClick={linkEvent(this, this.handleMessageCollapse)}
104 {this.state.collapsed ? (
105 <svg class="icon icon-inline">
106 <use xlinkHref="#icon-plus-square"></use>
109 <svg class="icon icon-inline">
110 <use xlinkHref="#icon-minus-square"></use>
116 {this.state.showEdit && (
118 privateMessage={message}
119 onEdit={this.handlePrivateMessageEdit}
120 onCancel={this.handleReplyCancel}
123 {!this.state.showEdit && !this.state.collapsed && (
125 {this.state.viewSource ? (
126 <pre>{this.messageUnlessRemoved}</pre>
130 dangerouslySetInnerHTML={mdToHtml(this.messageUnlessRemoved)}
133 <ul class="list-inline mb-0 text-muted font-weight-bold">
136 <li className="list-inline-item">
138 class="btn btn-link btn-sm btn-animate text-muted"
139 onClick={linkEvent(this, this.handleMarkRead)}
142 ? i18n.t('mark_as_unread')
143 : i18n.t('mark_as_read')
147 class={`icon icon-inline ${
148 message.read && 'text-success'
151 <use xlinkHref="#icon-check"></use>
155 <li className="list-inline-item">
157 class="btn btn-link btn-sm btn-animate text-muted"
158 onClick={linkEvent(this, this.handleReplyClick)}
159 data-tippy-content={i18n.t('reply')}
161 <svg class="icon icon-inline">
162 <use xlinkHref="#icon-reply1"></use>
170 <li className="list-inline-item">
172 class="btn btn-link btn-sm btn-animate text-muted"
173 onClick={linkEvent(this, this.handleEditClick)}
174 data-tippy-content={i18n.t('edit')}
176 <svg class="icon icon-inline">
177 <use xlinkHref="#icon-edit"></use>
181 <li className="list-inline-item">
183 class="btn btn-link btn-sm btn-animate text-muted"
184 onClick={linkEvent(this, this.handleDeleteClick)}
192 class={`icon icon-inline ${
193 message.deleted && 'text-danger'
196 <use xlinkHref="#icon-trash"></use>
202 <li className="list-inline-item">
204 class="btn btn-link btn-sm btn-animate text-muted"
205 onClick={linkEvent(this, this.handleViewSource)}
206 data-tippy-content={i18n.t('view_source')}
209 class={`icon icon-inline ${
210 this.state.viewSource && 'text-success'
213 <use xlinkHref="#icon-file-text"></use>
221 {this.state.showReply && (
224 recipient_id: this.props.privateMessage.creator_id,
226 onCreate={this.handlePrivateMessageCreate}
229 {/* A collapsed clearfix */}
230 {this.state.collapsed && <div class="row col-12"></div>}
235 get messageUnlessRemoved(): string {
236 let message = this.props.privateMessage;
237 return message.deleted ? `*${i18n.t('deleted')}*` : message.content;
240 handleReplyClick(i: PrivateMessage) {
241 i.state.showReply = true;
245 handleEditClick(i: PrivateMessage) {
246 i.state.showEdit = true;
250 handleDeleteClick(i: PrivateMessage) {
251 let form: EditPrivateMessageForm = {
252 edit_id: i.props.privateMessage.id,
253 deleted: !i.props.privateMessage.deleted,
255 WebSocketService.Instance.editPrivateMessage(form);
258 handleReplyCancel() {
259 this.state.showReply = false;
260 this.state.showEdit = false;
261 this.setState(this.state);
264 handleMarkRead(i: PrivateMessage) {
265 let form: EditPrivateMessageForm = {
266 edit_id: i.props.privateMessage.id,
267 read: !i.props.privateMessage.read,
269 WebSocketService.Instance.editPrivateMessage(form);
272 handleMessageCollapse(i: PrivateMessage) {
273 i.state.collapsed = !i.state.collapsed;
277 handleViewSource(i: PrivateMessage) {
278 i.state.viewSource = !i.state.viewSource;
282 handlePrivateMessageEdit() {
283 this.state.showEdit = false;
284 this.setState(this.state);
287 handlePrivateMessageCreate() {
288 this.state.showReply = false;
289 this.setState(this.state);
290 toast(i18n.t('message_sent'));