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