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