1 import { Component, linkEvent } from "inferno";
3 CreatePrivateMessageReport,
5 MarkPrivateMessageAsRead,
8 } from "lemmy-js-client";
9 import { i18n } from "../../i18next";
10 import { UserService, WebSocketService } from "../../services";
11 import { mdToHtml, myAuth, toast, wsClient } from "../../utils";
12 import { Icon } from "../common/icon";
13 import { MomentTime } from "../common/moment-time";
14 import { PersonListing } from "../person/person-listing";
15 import { PrivateMessageForm } from "./private-message-form";
17 interface PrivateMessageState {
22 showReportDialog: boolean;
23 reportReason?: string;
26 interface PrivateMessageProps {
27 private_message_view: PrivateMessageView;
30 export class PrivateMessage extends Component<
34 state: PrivateMessageState = {
39 showReportDialog: false,
42 constructor(props: any, context: any) {
43 super(props, context);
45 this.handleReplyCancel = this.handleReplyCancel.bind(this);
46 this.handlePrivateMessageCreate =
47 this.handlePrivateMessageCreate.bind(this);
48 this.handlePrivateMessageEdit = this.handlePrivateMessageEdit.bind(this);
53 UserService.Instance.myUserInfo?.local_user_view.person.id ==
54 this.props.private_message_view.creator.id
59 let message_view = this.props.private_message_view;
60 let otherPerson: Person = this.mine
61 ? message_view.recipient
62 : message_view.creator;
65 <div className="border-top border-light">
67 <ul className="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")}
72 <li className="list-inline-item">
73 <PersonListing person={otherPerson} />
75 <li className="list-inline-item">
78 published={message_view.private_message.published}
79 updated={message_view.private_message.updated}
83 <li className="list-inline-item">
86 className="pointer text-monospace"
87 onClick={linkEvent(this, this.handleMessageCollapse)}
89 {this.state.collapsed ? (
90 <Icon icon="plus-square" classes="icon-inline" />
92 <Icon icon="minus-square" classes="icon-inline" />
97 {this.state.showEdit && (
99 recipient={otherPerson}
100 privateMessageView={message_view}
101 onEdit={this.handlePrivateMessageEdit}
102 onCreate={this.handlePrivateMessageCreate}
103 onCancel={this.handleReplyCancel}
106 {!this.state.showEdit && !this.state.collapsed && (
108 {this.state.viewSource ? (
109 <pre>{this.messageUnlessRemoved}</pre>
113 dangerouslySetInnerHTML={mdToHtml(this.messageUnlessRemoved)}
116 <ul className="list-inline mb-0 text-muted font-weight-bold">
119 <li className="list-inline-item">
121 className="btn btn-link btn-animate text-muted"
122 onClick={linkEvent(this, this.handleMarkRead)}
124 message_view.private_message.read
125 ? i18n.t("mark_as_unread")
126 : i18n.t("mark_as_read")
129 message_view.private_message.read
130 ? i18n.t("mark_as_unread")
131 : i18n.t("mark_as_read")
136 classes={`icon-inline ${
137 message_view.private_message.read && "text-success"
142 <li className="list-inline-item">{this.reportButton}</li>
143 <li className="list-inline-item">
145 className="btn btn-link btn-animate text-muted"
146 onClick={linkEvent(this, this.handleReplyClick)}
147 data-tippy-content={i18n.t("reply")}
148 aria-label={i18n.t("reply")}
150 <Icon icon="reply1" classes="icon-inline" />
157 <li className="list-inline-item">
159 className="btn btn-link btn-animate text-muted"
160 onClick={linkEvent(this, this.handleEditClick)}
161 data-tippy-content={i18n.t("edit")}
162 aria-label={i18n.t("edit")}
164 <Icon icon="edit" classes="icon-inline" />
167 <li className="list-inline-item">
169 className="btn btn-link btn-animate text-muted"
170 onClick={linkEvent(this, this.handleDeleteClick)}
172 !message_view.private_message.deleted
177 !message_view.private_message.deleted
184 classes={`icon-inline ${
185 message_view.private_message.deleted &&
193 <li className="list-inline-item">
195 className="btn btn-link btn-animate text-muted"
196 onClick={linkEvent(this, this.handleViewSource)}
197 data-tippy-content={i18n.t("view_source")}
198 aria-label={i18n.t("view_source")}
202 classes={`icon-inline ${
203 this.state.viewSource && "text-success"
212 {this.state.showReportDialog && (
214 className="form-inline"
215 onSubmit={linkEvent(this, this.handleReportSubmit)}
217 <label className="sr-only" htmlFor="pm-report-reason">
222 id="pm-report-reason"
223 className="form-control mr-2"
224 placeholder={i18n.t("reason")}
226 value={this.state.reportReason}
227 onInput={linkEvent(this, this.handleReportReasonChange)}
231 className="btn btn-secondary"
232 aria-label={i18n.t("create_report")}
234 {i18n.t("create_report")}
238 {this.state.showReply && (
240 recipient={otherPerson}
241 onCreate={this.handlePrivateMessageCreate}
244 {/* A collapsed clearfix */}
245 {this.state.collapsed && <div className="row col-12"></div>}
253 className="btn btn-link btn-animate text-muted py-0"
254 onClick={linkEvent(this, this.handleShowReportDialog)}
255 data-tippy-content={i18n.t("show_report_dialog")}
256 aria-label={i18n.t("show_report_dialog")}
258 <Icon icon="flag" inline />
263 get messageUnlessRemoved(): string {
264 let message = this.props.private_message_view.private_message;
265 return message.deleted ? `*${i18n.t("deleted")}*` : message.content;
268 handleReplyClick(i: PrivateMessage) {
269 i.setState({ showReply: true });
272 handleEditClick(i: PrivateMessage) {
273 i.setState({ showEdit: true });
277 handleDeleteClick(i: PrivateMessage) {
280 let form: DeletePrivateMessage = {
281 private_message_id: i.props.private_message_view.private_message.id,
282 deleted: !i.props.private_message_view.private_message.deleted,
285 WebSocketService.Instance.send(wsClient.deletePrivateMessage(form));
289 handleReplyCancel() {
290 this.setState({ showReply: false, showEdit: false });
293 handleMarkRead(i: PrivateMessage) {
296 let form: MarkPrivateMessageAsRead = {
297 private_message_id: i.props.private_message_view.private_message.id,
298 read: !i.props.private_message_view.private_message.read,
301 WebSocketService.Instance.send(wsClient.markPrivateMessageAsRead(form));
305 handleMessageCollapse(i: PrivateMessage) {
306 i.setState({ collapsed: !i.state.collapsed });
309 handleViewSource(i: PrivateMessage) {
310 i.setState({ viewSource: !i.state.viewSource });
313 handleShowReportDialog(i: PrivateMessage) {
314 i.setState({ showReportDialog: !i.state.showReportDialog });
317 handleReportReasonChange(i: PrivateMessage, event: any) {
318 i.setState({ reportReason: event.target.value });
321 handleReportSubmit(i: PrivateMessage, event: any) {
322 event.preventDefault();
324 let reason = i.state.reportReason;
325 if (auth && reason) {
326 let form: CreatePrivateMessageReport = {
327 private_message_id: i.props.private_message_view.private_message.id,
331 WebSocketService.Instance.send(wsClient.createPrivateMessageReport(form));
333 i.setState({ showReportDialog: false });
337 handlePrivateMessageEdit() {
338 this.setState({ showEdit: false });
341 handlePrivateMessageCreate(message: PrivateMessageView) {
343 message.creator.id ==
344 UserService.Instance.myUserInfo?.local_user_view.person.id
346 this.setState({ showReply: false });
347 toast(i18n.t("message_sent"));