]> Untitled Git - lemmy-ui.git/blob - src/shared/components/comment/comment-form.tsx
Merge branch 'fix/notif_new_fetch_bug' of https://github.com/ernestwisniewski/lemmy...
[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   UserOperation,
11   wsJsonToRes,
12   wsUserOp,
13 } from "lemmy-js-client";
14 import { Subscription } from "rxjs";
15 import { i18n } from "../../i18next";
16 import { UserService, WebSocketService } from "../../services";
17 import {
18   auth,
19   capitalizeFirstLetter,
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: Either<CommentNodeI, number>;
31   edit?: boolean;
32   disabled?: boolean;
33   focus?: boolean;
34   onReplyCancel?(): any;
35 }
36
37 interface CommentFormState {
38   buttonTitle: string;
39   finished: boolean;
40   formId: Option<string>;
41 }
42
43 export class CommentForm extends Component<CommentFormProps, CommentFormState> {
44   private subscription: Subscription;
45   private emptyState: CommentFormState = {
46     buttonTitle: this.props.node.isRight()
47       ? capitalizeFirstLetter(i18n.t("post"))
48       : this.props.edit
49       ? capitalizeFirstLetter(i18n.t("save"))
50       : capitalizeFirstLetter(i18n.t("reply")),
51     finished: false,
52     formId: None,
53   };
54
55   constructor(props: any, context: any) {
56     super(props, context);
57
58     this.handleCommentSubmit = this.handleCommentSubmit.bind(this);
59     this.handleReplyCancel = this.handleReplyCancel.bind(this);
60
61     this.state = this.emptyState;
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 = this.props.node.match({
73       left: node =>
74         this.props.edit ? Some(node.comment_view.comment.content) : None,
75       right: () => None,
76     });
77     return (
78       <div class="mb-3">
79         {UserService.Instance.myUserInfo.isSome() ? (
80           <MarkdownTextArea
81             initialContent={initialContent}
82             buttonTitle={Some(this.state.buttonTitle)}
83             maxLength={None}
84             finished={this.state.finished}
85             replyType={this.props.node.isLeft()}
86             focus={this.props.focus}
87             disabled={this.props.disabled}
88             onSubmit={this.handleCommentSubmit}
89             onReplyCancel={this.handleReplyCancel}
90             placeholder={Some(i18n.t("comment_here"))}
91           />
92         ) : (
93           <div class="alert alert-warning" role="alert">
94             <Icon icon="alert-triangle" classes="icon-inline mr-2" />
95             <T i18nKey="must_login" class="d-inline">
96               #
97               <Link className="alert-link" to="/login">
98                 #
99               </Link>
100             </T>
101           </div>
102         )}
103       </div>
104     );
105   }
106
107   handleCommentSubmit(msg: { val: string; formId: string }) {
108     let content = msg.val;
109     this.state.formId = Some(msg.formId);
110
111     this.props.node.match({
112       left: node => {
113         if (this.props.edit) {
114           let form = new EditComment({
115             content: Some(content),
116             distinguished: None,
117             form_id: this.state.formId,
118             comment_id: node.comment_view.comment.id,
119             auth: auth().unwrap(),
120           });
121           WebSocketService.Instance.send(wsClient.editComment(form));
122         } else {
123           let form = new CreateComment({
124             content,
125             form_id: this.state.formId,
126             post_id: node.comment_view.post.id,
127             parent_id: Some(node.comment_view.comment.id),
128             auth: auth().unwrap(),
129           });
130           WebSocketService.Instance.send(wsClient.createComment(form));
131         }
132       },
133       right: postId => {
134         let form = new CreateComment({
135           content,
136           form_id: this.state.formId,
137           post_id: postId,
138           parent_id: None,
139           auth: auth().unwrap(),
140         });
141         WebSocketService.Instance.send(wsClient.createComment(form));
142       },
143     });
144     this.setState(this.state);
145   }
146
147   handleReplyCancel() {
148     this.props.onReplyCancel();
149   }
150
151   parseMessage(msg: any) {
152     let op = wsUserOp(msg);
153     console.log(msg);
154
155     // Only do the showing and hiding if logged in
156     if (UserService.Instance.myUserInfo.isSome()) {
157       if (
158         op == UserOperation.CreateComment ||
159         op == UserOperation.EditComment
160       ) {
161         let data = wsJsonToRes<CommentResponse>(msg, CommentResponse);
162
163         // This only finishes this form, if the randomly generated form_id matches the one received
164         if (this.state.formId.unwrapOr("") == data.form_id.unwrapOr("")) {
165           this.setState({ finished: true });
166
167           // Necessary because it broke tribute for some reason
168           this.setState({ finished: false });
169         }
170       }
171     }
172   }
173 }