1 import { None, Some } from "@sniptt/monads/build";
2 import { Component, linkEvent } from "inferno";
5 MarkPrivateMessageAsRead,
8 } from "lemmy-js-client";
9 import { i18n } from "../../i18next";
10 import { UserService, WebSocketService } from "../../services";
11 import { auth, mdToHtml, 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 {
24 interface PrivateMessageProps {
25 private_message_view: PrivateMessageView;
28 export class PrivateMessage extends Component<
32 private emptyState: PrivateMessageState = {
39 constructor(props: any, context: any) {
40 super(props, context);
42 this.state = this.emptyState;
43 this.handleReplyCancel = this.handleReplyCancel.bind(this);
44 this.handlePrivateMessageCreate =
45 this.handlePrivateMessageCreate.bind(this);
46 this.handlePrivateMessageEdit = this.handlePrivateMessageEdit.bind(this);
50 return UserService.Instance.myUserInfo
53 m.local_user_view.person.id ==
54 this.props.private_message_view.creator.id
60 let message_view = this.props.private_message_view;
61 let otherPerson: PersonSafe = this.mine
62 ? message_view.recipient
63 : message_view.creator;
66 <div class="border-top border-light">
68 <ul class="list-inline mb-0 text-muted small">
69 {/* TODO refactor this */}
70 <li className="list-inline-item">
71 {this.mine ? i18n.t("to") : i18n.t("from")}
73 <li className="list-inline-item">
74 <PersonListing person={otherPerson} />
76 <li className="list-inline-item">
79 published={message_view.private_message.published}
80 updated={message_view.private_message.updated}
84 <li className="list-inline-item">
87 className="pointer text-monospace"
88 onClick={linkEvent(this, this.handleMessageCollapse)}
90 {this.state.collapsed ? (
91 <Icon icon="plus-square" classes="icon-inline" />
93 <Icon icon="minus-square" classes="icon-inline" />
98 {this.state.showEdit && (
100 recipient={otherPerson}
101 privateMessageView={Some(message_view)}
102 onEdit={this.handlePrivateMessageEdit}
103 onCreate={this.handlePrivateMessageCreate}
104 onCancel={this.handleReplyCancel}
107 {!this.state.showEdit && !this.state.collapsed && (
109 {this.state.viewSource ? (
110 <pre>{this.messageUnlessRemoved}</pre>
114 dangerouslySetInnerHTML={mdToHtml(this.messageUnlessRemoved)}
117 <ul class="list-inline mb-0 text-muted font-weight-bold">
120 <li className="list-inline-item">
122 class="btn btn-link btn-animate text-muted"
123 onClick={linkEvent(this, this.handleMarkRead)}
125 message_view.private_message.read
126 ? i18n.t("mark_as_unread")
127 : i18n.t("mark_as_read")
130 message_view.private_message.read
131 ? i18n.t("mark_as_unread")
132 : i18n.t("mark_as_read")
137 classes={`icon-inline ${
138 message_view.private_message.read && "text-success"
143 <li className="list-inline-item">
145 class="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 class="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 class="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 class="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.showReply && (
214 recipient={otherPerson}
215 privateMessageView={None}
216 onCreate={this.handlePrivateMessageCreate}
219 {/* A collapsed clearfix */}
220 {this.state.collapsed && <div class="row col-12"></div>}
225 get messageUnlessRemoved(): string {
226 let message = this.props.private_message_view.private_message;
227 return message.deleted ? `*${i18n.t("deleted")}*` : message.content;
230 handleReplyClick(i: PrivateMessage) {
231 i.state.showReply = true;
235 handleEditClick(i: PrivateMessage) {
236 i.state.showEdit = true;
240 handleDeleteClick(i: PrivateMessage) {
241 let form = new DeletePrivateMessage({
242 private_message_id: i.props.private_message_view.private_message.id,
243 deleted: !i.props.private_message_view.private_message.deleted,
244 auth: auth().unwrap(),
246 WebSocketService.Instance.send(wsClient.deletePrivateMessage(form));
249 handleReplyCancel() {
250 this.state.showReply = false;
251 this.state.showEdit = false;
252 this.setState(this.state);
255 handleMarkRead(i: PrivateMessage) {
256 let form = new MarkPrivateMessageAsRead({
257 private_message_id: i.props.private_message_view.private_message.id,
258 read: !i.props.private_message_view.private_message.read,
259 auth: auth().unwrap(),
261 WebSocketService.Instance.send(wsClient.markPrivateMessageAsRead(form));
264 handleMessageCollapse(i: PrivateMessage) {
265 i.state.collapsed = !i.state.collapsed;
269 handleViewSource(i: PrivateMessage) {
270 i.state.viewSource = !i.state.viewSource;
274 handlePrivateMessageEdit() {
275 this.state.showEdit = false;
276 this.setState(this.state);
279 handlePrivateMessageCreate(message: PrivateMessageView) {
280 UserService.Instance.myUserInfo.match({
282 if (message.creator.id == mui.local_user_view.person.id) {
283 this.state.showReply = false;
284 this.setState(this.state);
285 toast(i18n.t("message_sent"));