1 import { None, Option, Some } from "@sniptt/monads";
2 import { Component, linkEvent } from "inferno";
3 import { T } from "inferno-i18next-dess";
4 import { Prompt } from "inferno-router";
9 PrivateMessageResponse,
14 } from "lemmy-js-client";
15 import { Subscription } from "rxjs";
16 import { i18n } from "../../i18next";
17 import { WebSocketService } from "../../services";
20 capitalizeFirstLetter,
28 import { Icon, Spinner } from "../common/icon";
29 import { MarkdownTextArea } from "../common/markdown-textarea";
30 import { PersonListing } from "../person/person-listing";
32 interface PrivateMessageFormProps {
33 recipient: PersonSafe;
34 privateMessageView: Option<PrivateMessageView>; // If a pm is given, that means this is an edit
36 onCreate?(message: PrivateMessageView): any;
37 onEdit?(message: PrivateMessageView): any;
40 interface PrivateMessageFormState {
41 privateMessageForm: CreatePrivateMessage;
44 showDisclaimer: boolean;
47 export class PrivateMessageForm extends Component<
48 PrivateMessageFormProps,
49 PrivateMessageFormState
51 private subscription: Subscription;
52 private emptyState: PrivateMessageFormState = {
53 privateMessageForm: new CreatePrivateMessage({
55 recipient_id: this.props.recipient.id,
56 auth: auth().unwrap(),
60 showDisclaimer: false,
63 constructor(props: any, context: any) {
64 super(props, context);
66 this.state = this.emptyState;
68 this.handleContentChange = this.handleContentChange.bind(this);
70 this.parseMessage = this.parseMessage.bind(this);
71 this.subscription = wsSubscribe(this.parseMessage);
74 this.props.privateMessageView.match({
76 (this.state.privateMessageForm.content = pm.private_message.content),
85 componentDidUpdate() {
86 if (!this.state.loading && this.state.privateMessageForm.content) {
87 window.onbeforeunload = () => true;
89 window.onbeforeunload = undefined;
93 componentWillUnmount() {
95 this.subscription.unsubscribe();
96 window.onbeforeunload = null;
104 when={!this.state.loading && this.state.privateMessageForm.content}
105 message={i18n.t("block_leaving")}
107 <form onSubmit={linkEvent(this, this.handlePrivateMessageSubmit)}>
108 {this.props.privateMessageView.isNone() && (
109 <div class="form-group row">
110 <label class="col-sm-2 col-form-label">
111 {capitalizeFirstLetter(i18n.t("to"))}
114 <div class="col-sm-10 form-control-plaintext">
115 <PersonListing person={this.props.recipient} />
119 <div class="form-group row">
120 <label class="col-sm-2 col-form-label">
123 class="btn btn-link text-warning d-inline-block"
124 onClick={linkEvent(this, this.handleShowDisclaimer)}
125 data-tippy-content={i18n.t("private_message_disclaimer")}
126 aria-label={i18n.t("private_message_disclaimer")}
128 <Icon icon="alert-triangle" classes="icon-inline" />
131 <div class="col-sm-10">
133 initialContent={Some(this.state.privateMessageForm.content)}
137 onContentChange={this.handleContentChange}
142 {this.state.showDisclaimer && (
143 <div class="form-group row">
144 <div class="offset-sm-2 col-sm-10">
145 <div class="alert alert-danger" role="alert">
146 <T i18nKey="private_message_disclaimer">
151 href="https://element.io/get-started"
160 <div class="form-group row">
161 <div class="offset-sm-2 col-sm-10">
164 class="btn btn-secondary mr-2"
165 disabled={this.state.loading}
167 {this.state.loading ? (
169 ) : this.props.privateMessageView.isSome() ? (
170 capitalizeFirstLetter(i18n.t("save"))
172 capitalizeFirstLetter(i18n.t("send_message"))
175 {this.props.privateMessageView.isSome() && (
178 class="btn btn-secondary"
179 onClick={linkEvent(this, this.handleCancel)}
184 <ul class="d-inline-block float-right list-inline mb-1 text-muted font-weight-bold">
185 <li class="list-inline-item"></li>
194 handlePrivateMessageSubmit(i: PrivateMessageForm, event: any) {
195 event.preventDefault();
196 i.props.privateMessageView.match({
198 let form = new EditPrivateMessage({
199 private_message_id: pm.private_message.id,
200 content: i.state.privateMessageForm.content,
201 auth: auth().unwrap(),
203 WebSocketService.Instance.send(wsClient.editPrivateMessage(form));
205 none: WebSocketService.Instance.send(
206 wsClient.createPrivateMessage(i.state.privateMessageForm)
209 i.state.loading = true;
213 handleContentChange(val: string) {
214 this.state.privateMessageForm.content = val;
215 this.setState(this.state);
218 handleCancel(i: PrivateMessageForm) {
222 handlePreviewToggle(i: PrivateMessageForm, event: any) {
223 event.preventDefault();
224 i.state.previewMode = !i.state.previewMode;
228 handleShowDisclaimer(i: PrivateMessageForm) {
229 i.state.showDisclaimer = !i.state.showDisclaimer;
233 parseMessage(msg: any) {
234 let op = wsUserOp(msg);
237 toast(i18n.t(msg.error), "danger");
238 this.state.loading = false;
239 this.setState(this.state);
242 op == UserOperation.EditPrivateMessage ||
243 op == UserOperation.DeletePrivateMessage ||
244 op == UserOperation.MarkPrivateMessageAsRead
246 let data = wsJsonToRes<PrivateMessageResponse>(
248 PrivateMessageResponse
250 this.state.loading = false;
251 this.props.onEdit(data.private_message_view);
252 } else if (op == UserOperation.CreatePrivateMessage) {
253 let data = wsJsonToRes<PrivateMessageResponse>(
255 PrivateMessageResponse
257 this.state.loading = false;
258 this.props.onCreate(data.private_message_view);
259 this.setState(this.state);