1 import { Component, linkEvent } from "inferno";
2 import { T } from "inferno-i18next-dess";
7 PrivateMessageResponse,
12 } from "lemmy-js-client";
13 import { Subscription } from "rxjs";
14 import { i18n } from "../../i18next";
15 import { WebSocketService } from "../../services";
17 capitalizeFirstLetter,
26 import { Icon, Spinner } from "../common/icon";
27 import { MarkdownTextArea } from "../common/markdown-textarea";
28 import NavigationPrompt from "../common/navigation-prompt";
29 import { PersonListing } from "../person/person-listing";
31 interface PrivateMessageFormProps {
33 privateMessageView?: PrivateMessageView; // If a pm is given, that means this is an edit
35 onCreate?(message: PrivateMessageView): any;
36 onEdit?(message: PrivateMessageView): any;
39 interface PrivateMessageFormState {
43 showDisclaimer: boolean;
46 export class PrivateMessageForm extends Component<
47 PrivateMessageFormProps,
48 PrivateMessageFormState
50 private subscription?: Subscription;
51 state: PrivateMessageFormState = {
54 showDisclaimer: false,
57 constructor(props: any, context: any) {
58 super(props, context);
60 this.handleContentChange = this.handleContentChange.bind(this);
62 this.parseMessage = this.parseMessage.bind(this);
63 this.subscription = wsSubscribe(this.parseMessage);
66 if (this.props.privateMessageView) {
68 this.props.privateMessageView.private_message.content;
76 componentDidUpdate() {
77 if (!this.state.loading && this.state.content) {
78 window.onbeforeunload = () => true;
80 window.onbeforeunload = null;
84 componentWillUnmount() {
86 this.subscription?.unsubscribe();
87 window.onbeforeunload = null;
94 <NavigationPrompt when={!this.state.loading && !!this.state.content} />
95 <form onSubmit={linkEvent(this, this.handlePrivateMessageSubmit)}>
96 {!this.props.privateMessageView && (
97 <div className="form-group row">
98 <label className="col-sm-2 col-form-label">
99 {capitalizeFirstLetter(i18n.t("to"))}
102 <div className="col-sm-10 form-control-plaintext">
103 <PersonListing person={this.props.recipient} />
107 <div className="form-group row">
108 <label className="col-sm-2 col-form-label">
111 className="btn btn-link text-warning d-inline-block"
112 onClick={linkEvent(this, this.handleShowDisclaimer)}
113 data-tippy-content={i18n.t("private_message_disclaimer")}
114 aria-label={i18n.t("private_message_disclaimer")}
116 <Icon icon="alert-triangle" classes="icon-inline" />
119 <div className="col-sm-10">
121 initialContent={this.state.content}
122 onContentChange={this.handleContentChange}
129 {this.state.showDisclaimer && (
130 <div className="form-group row">
131 <div className="offset-sm-2 col-sm-10">
132 <div className="alert alert-danger" role="alert">
133 <T i18nKey="private_message_disclaimer">
136 className="alert-link"
138 href="https://element.io/get-started"
147 <div className="form-group row">
148 <div className="offset-sm-2 col-sm-10">
151 className="btn btn-secondary mr-2"
152 disabled={this.state.loading}
154 {this.state.loading ? (
156 ) : this.props.privateMessageView ? (
157 capitalizeFirstLetter(i18n.t("save"))
159 capitalizeFirstLetter(i18n.t("send_message"))
162 {this.props.privateMessageView && (
165 className="btn btn-secondary"
166 onClick={linkEvent(this, this.handleCancel)}
171 <ul className="d-inline-block float-right list-inline mb-1 text-muted font-weight-bold">
172 <li className="list-inline-item"></li>
181 handlePrivateMessageSubmit(i: PrivateMessageForm, event: any) {
182 event.preventDefault();
183 const pm = i.props.privateMessageView;
184 const auth = myAuth();
185 const content = i.state.content;
186 if (auth && content) {
188 const form: EditPrivateMessage = {
189 private_message_id: pm.private_message.id,
193 WebSocketService.Instance.send(wsClient.editPrivateMessage(form));
195 const form: CreatePrivateMessage = {
197 recipient_id: i.props.recipient.id,
200 WebSocketService.Instance.send(wsClient.createPrivateMessage(form));
202 i.setState({ loading: true });
206 handleContentChange(val: string) {
207 this.setState({ content: val });
210 handleCancel(i: PrivateMessageForm) {
211 i.props.onCancel?.();
214 handlePreviewToggle(i: PrivateMessageForm, event: any) {
215 event.preventDefault();
216 i.setState({ previewMode: !i.state.previewMode });
219 handleShowDisclaimer(i: PrivateMessageForm) {
220 i.setState({ showDisclaimer: !i.state.showDisclaimer });
223 parseMessage(msg: any) {
224 const op = wsUserOp(msg);
227 toast(i18n.t(msg.error), "danger");
228 this.setState({ loading: false });
231 op == UserOperation.EditPrivateMessage ||
232 op == UserOperation.DeletePrivateMessage ||
233 op == UserOperation.MarkPrivateMessageAsRead
235 const data = wsJsonToRes<PrivateMessageResponse>(msg);
236 this.setState({ loading: false });
237 this.props.onEdit?.(data.private_message_view);
238 } else if (op == UserOperation.CreatePrivateMessage) {
239 const data = wsJsonToRes<PrivateMessageResponse>(msg);
240 this.props.onCreate?.(data.private_message_view);