]> Untitled Git - lemmy-ui.git/blob - src/shared/components/comment/comment-form.tsx
Using auto-generated types from ts-rs. (#1003)
[lemmy-ui.git] / src / shared / components / comment / comment-form.tsx
1 import { Component } from "inferno";
2 import { T } from "inferno-i18next-dess";
3 import { Link } from "inferno-router";
4 import {
5   CommentResponse,
6   CreateComment,
7   EditComment,
8   Language,
9   UserOperation,
10   wsJsonToRes,
11   wsUserOp,
12 } from "lemmy-js-client";
13 import { Subscription } from "rxjs";
14 import { CommentNodeI } from "shared/interfaces";
15 import { i18n } from "../../i18next";
16 import { UserService, WebSocketService } from "../../services";
17 import {
18   capitalizeFirstLetter,
19   myAuth,
20   myFirstDiscussionLanguageId,
21   wsClient,
22   wsSubscribe,
23 } from "../../utils";
24 import { Icon } from "../common/icon";
25 import { MarkdownTextArea } from "../common/markdown-textarea";
26
27 interface CommentFormProps {
28   /**
29    * Can either be the parent, or the editable comment. The right side is a postId.
30    */
31   node: CommentNodeI | number;
32   edit?: boolean;
33   disabled?: boolean;
34   focus?: boolean;
35   onReplyCancel?(): any;
36   allLanguages: Language[];
37   siteLanguages: number[];
38 }
39
40 interface CommentFormState {
41   buttonTitle: string;
42   finished: boolean;
43   formId?: string;
44 }
45
46 export class CommentForm extends Component<CommentFormProps, CommentFormState> {
47   private subscription?: Subscription;
48   state: CommentFormState = {
49     buttonTitle:
50       typeof this.props.node === "number"
51         ? capitalizeFirstLetter(i18n.t("post"))
52         : this.props.edit
53         ? capitalizeFirstLetter(i18n.t("save"))
54         : capitalizeFirstLetter(i18n.t("reply")),
55     finished: false,
56   };
57
58   constructor(props: any, context: any) {
59     super(props, context);
60
61     this.handleCommentSubmit = this.handleCommentSubmit.bind(this);
62     this.handleReplyCancel = this.handleReplyCancel.bind(this);
63
64     this.parseMessage = this.parseMessage.bind(this);
65     this.subscription = wsSubscribe(this.parseMessage);
66   }
67
68   componentWillUnmount() {
69     this.subscription?.unsubscribe();
70   }
71
72   render() {
73     let initialContent =
74       typeof this.props.node !== "number"
75         ? this.props.edit
76           ? this.props.node.comment_view.comment.content
77           : undefined
78         : undefined;
79
80     let selectedLang =
81       typeof this.props.node !== "number"
82         ? this.props.node.comment_view.comment.language_id
83         : myFirstDiscussionLanguageId(
84             this.props.allLanguages,
85             this.props.siteLanguages,
86             UserService.Instance.myUserInfo
87           );
88
89     return (
90       <div className="mb-3">
91         {UserService.Instance.myUserInfo ? (
92           <MarkdownTextArea
93             initialContent={initialContent}
94             initialLanguageId={selectedLang}
95             showLanguage
96             buttonTitle={this.state.buttonTitle}
97             finished={this.state.finished}
98             replyType={typeof this.props.node !== "number"}
99             focus={this.props.focus}
100             disabled={this.props.disabled}
101             onSubmit={this.handleCommentSubmit}
102             onReplyCancel={this.handleReplyCancel}
103             placeholder={i18n.t("comment_here")}
104             allLanguages={this.props.allLanguages}
105             siteLanguages={this.props.siteLanguages}
106           />
107         ) : (
108           <div className="alert alert-warning" role="alert">
109             <Icon icon="alert-triangle" classes="icon-inline mr-2" />
110             <T i18nKey="must_login" class="d-inline">
111               #
112               <Link className="alert-link" to="/login">
113                 #
114               </Link>
115             </T>
116           </div>
117         )}
118       </div>
119     );
120   }
121
122   handleCommentSubmit(msg: {
123     val: string;
124     formId: string;
125     languageId?: number;
126   }) {
127     let content = msg.val;
128     let language_id = msg.languageId;
129     let node = this.props.node;
130
131     this.setState({ formId: msg.formId });
132
133     let auth = myAuth();
134     if (auth) {
135       if (typeof node === "number") {
136         let postId = node;
137         let form: CreateComment = {
138           content,
139           form_id: this.state.formId,
140           post_id: postId,
141           language_id,
142           auth,
143         };
144         WebSocketService.Instance.send(wsClient.createComment(form));
145       } else {
146         if (this.props.edit) {
147           let form: EditComment = {
148             content,
149             form_id: this.state.formId,
150             comment_id: node.comment_view.comment.id,
151             language_id,
152             auth,
153           };
154           WebSocketService.Instance.send(wsClient.editComment(form));
155         } else {
156           let form: CreateComment = {
157             content,
158             form_id: this.state.formId,
159             post_id: node.comment_view.post.id,
160             parent_id: node.comment_view.comment.id,
161             language_id,
162             auth,
163           };
164           WebSocketService.Instance.send(wsClient.createComment(form));
165         }
166       }
167     }
168   }
169
170   handleReplyCancel() {
171     this.props.onReplyCancel?.();
172   }
173
174   parseMessage(msg: any) {
175     let op = wsUserOp(msg);
176     console.log(msg);
177
178     // Only do the showing and hiding if logged in
179     if (UserService.Instance.myUserInfo) {
180       if (
181         op == UserOperation.CreateComment ||
182         op == UserOperation.EditComment
183       ) {
184         let data = wsJsonToRes<CommentResponse>(msg);
185
186         // This only finishes this form, if the randomly generated form_id matches the one received
187         if (this.state.formId && this.state.formId == data.form_id) {
188           this.setState({ finished: true });
189
190           // Necessary because it broke tribute for some reason
191           this.setState({ finished: false });
192         }
193       }
194     }
195   }
196 }