]> Untitled Git - lemmy-ui.git/blob - src/shared/components/private_message/private-message-form.tsx
681a954495c6c4322165c3c7a3921c8269d430f4
[lemmy-ui.git] / src / shared / components / private_message / private-message-form.tsx
1 import { Component, InfernoNode, linkEvent } from "inferno";
2 import { T } from "inferno-i18next-dess";
3 import {
4   CreatePrivateMessage,
5   EditPrivateMessage,
6   Person,
7   PrivateMessageView,
8 } from "lemmy-js-client";
9 import { i18n } from "../../i18next";
10 import {
11   capitalizeFirstLetter,
12   myAuthRequired,
13   relTags,
14   setupTippy,
15 } from "../../utils";
16 import { Icon, Spinner } from "../common/icon";
17 import { MarkdownTextArea } from "../common/markdown-textarea";
18 import NavigationPrompt from "../common/navigation-prompt";
19 import { PersonListing } from "../person/person-listing";
20
21 interface PrivateMessageFormProps {
22   recipient: Person;
23   privateMessageView?: PrivateMessageView; // If a pm is given, that means this is an edit
24   onCancel?(): any;
25   onCreate?(form: CreatePrivateMessage): void;
26   onEdit?(form: EditPrivateMessage): void;
27 }
28
29 interface PrivateMessageFormState {
30   content?: string;
31   loading: boolean;
32   previewMode: boolean;
33   showDisclaimer: boolean;
34   submitted: boolean;
35 }
36
37 export class PrivateMessageForm extends Component<
38   PrivateMessageFormProps,
39   PrivateMessageFormState
40 > {
41   state: PrivateMessageFormState = {
42     loading: false,
43     previewMode: false,
44     showDisclaimer: false,
45     content: this.props.privateMessageView
46       ? this.props.privateMessageView.private_message.content
47       : undefined,
48     submitted: false,
49   };
50
51   constructor(props: any, context: any) {
52     super(props, context);
53
54     this.handleContentChange = this.handleContentChange.bind(this);
55   }
56
57   componentDidMount() {
58     setupTippy();
59   }
60
61   componentWillReceiveProps(
62     nextProps: Readonly<{ children?: InfernoNode } & PrivateMessageFormProps>
63   ): void {
64     if (this.props != nextProps) {
65       this.setState({ loading: false, content: undefined, previewMode: false });
66     }
67   }
68   // TODO
69   // <Prompt
70   //   when={!this.state.loading && this.state.content}
71   //   message={i18n.t("block_leaving")}
72   // />
73
74   render() {
75     return (
76       <form onSubmit={linkEvent(this, this.handlePrivateMessageSubmit)}>
77         <NavigationPrompt
78           when={
79             !this.state.loading && !!this.state.content && !this.state.submitted
80           }
81         />
82         {!this.props.privateMessageView && (
83           <div className="mb-3 row">
84             <label className="col-sm-2 col-form-label">
85               {capitalizeFirstLetter(i18n.t("to"))}
86             </label>
87
88             <div className="col-sm-10 form-control-plaintext">
89               <PersonListing person={this.props.recipient} />
90             </div>
91           </div>
92         )}
93         <div className="mb-3 row">
94           <label className="col-sm-2 col-form-label">
95             {i18n.t("message")}
96             <button
97               className="btn btn-link text-warning d-inline-block"
98               onClick={linkEvent(this, this.handleShowDisclaimer)}
99               data-tippy-content={i18n.t("private_message_disclaimer")}
100               aria-label={i18n.t("private_message_disclaimer")}
101             >
102               <Icon icon="alert-triangle" classes="icon-inline" />
103             </button>
104           </label>
105           <div className="col-sm-10">
106             <MarkdownTextArea
107               initialContent={this.state.content}
108               onContentChange={this.handleContentChange}
109               allLanguages={[]}
110               siteLanguages={[]}
111               hideNavigationWarnings
112             />
113           </div>
114         </div>
115
116         {this.state.showDisclaimer && (
117           <div className="mb-3 row">
118             <div className="offset-sm-2 col-sm-10">
119               <div className="alert alert-danger" role="alert">
120                 <T i18nKey="private_message_disclaimer">
121                   #
122                   <a
123                     className="alert-link"
124                     rel={relTags}
125                     href="https://element.io/get-started"
126                   >
127                     #
128                   </a>
129                 </T>
130               </div>
131             </div>
132           </div>
133         )}
134         <div className="mb-3 row">
135           <div className="offset-sm-2 col-sm-10">
136             <button
137               type="submit"
138               className="btn btn-secondary me-2"
139               disabled={this.state.loading}
140             >
141               {this.state.loading ? (
142                 <Spinner />
143               ) : this.props.privateMessageView ? (
144                 capitalizeFirstLetter(i18n.t("save"))
145               ) : (
146                 capitalizeFirstLetter(i18n.t("send_message"))
147               )}
148             </button>
149             {this.props.privateMessageView && (
150               <button
151                 type="button"
152                 className="btn btn-secondary"
153                 onClick={linkEvent(this, this.handleCancel)}
154               >
155                 {i18n.t("cancel")}
156               </button>
157             )}
158             <ul className="d-inline-block float-right list-inline mb-1 text-muted font-weight-bold">
159               <li className="list-inline-item"></li>
160             </ul>
161           </div>
162         </div>
163       </form>
164     );
165   }
166
167   handlePrivateMessageSubmit(i: PrivateMessageForm, event: any) {
168     event.preventDefault();
169     i.setState({ loading: true, submitted: true });
170     const pm = i.props.privateMessageView;
171     const auth = myAuthRequired();
172     const content = i.state.content ?? "";
173     if (pm) {
174       i.props.onEdit?.({
175         private_message_id: pm.private_message.id,
176         content,
177         auth,
178       });
179     } else {
180       i.props.onCreate?.({
181         content,
182         recipient_id: i.props.recipient.id,
183         auth,
184       });
185     }
186   }
187
188   handleContentChange(val: string) {
189     this.setState({ content: val });
190   }
191
192   handleCancel(i: PrivateMessageForm) {
193     i.props.onCancel?.();
194   }
195
196   handlePreviewToggle(i: PrivateMessageForm, event: any) {
197     event.preventDefault();
198     i.setState({ previewMode: !i.state.previewMode });
199   }
200
201   handleShowDisclaimer(i: PrivateMessageForm) {
202     i.setState({ showDisclaimer: !i.state.showDisclaimer });
203   }
204 }