]> Untitled Git - lemmy-ui.git/blob - src/shared/components/comment/comment-form.tsx
Comment Tree paging (#726)
[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,
116             form_id: this.state.formId,
117             comment_id: node.comment_view.comment.id,
118             auth: auth().unwrap(),
119           });
120           WebSocketService.Instance.send(wsClient.editComment(form));
121         } else {
122           let form = new CreateComment({
123             content,
124             form_id: this.state.formId,
125             post_id: node.comment_view.post.id,
126             parent_id: Some(node.comment_view.comment.id),
127             auth: auth().unwrap(),
128           });
129           WebSocketService.Instance.send(wsClient.createComment(form));
130         }
131       },
132       right: postId => {
133         let form = new CreateComment({
134           content,
135           form_id: this.state.formId,
136           post_id: postId,
137           parent_id: None,
138           auth: auth().unwrap(),
139         });
140         WebSocketService.Instance.send(wsClient.createComment(form));
141       },
142     });
143     this.setState(this.state);
144   }
145
146   handleReplyCancel() {
147     this.props.onReplyCancel();
148   }
149
150   parseMessage(msg: any) {
151     let op = wsUserOp(msg);
152     console.log(msg);
153
154     // Only do the showing and hiding if logged in
155     if (UserService.Instance.myUserInfo.isSome()) {
156       if (
157         op == UserOperation.CreateComment ||
158         op == UserOperation.EditComment
159       ) {
160         let data = wsJsonToRes<CommentResponse>(msg, CommentResponse);
161
162         // This only finishes this form, if the randomly generated form_id matches the one received
163         if (this.state.formId.unwrapOr("") == data.form_id.unwrapOr("")) {
164           this.setState({ finished: true });
165
166           // Necessary because it broke tribute for some reason
167           this.setState({ finished: false });
168         }
169       }
170     }
171   }
172 }