]> Untitled Git - lemmy-ui.git/blob - src/shared/components/comment-form.tsx
Updating v2 API based on nutomics recommends.
[lemmy-ui.git] / src / shared / components / comment-form.tsx
1 import { Component } from 'inferno';
2 import { Link } from 'inferno-router';
3 import { Subscription } from 'rxjs';
4 import {
5   CreateComment,
6   EditComment,
7   UserOperation,
8   CommentResponse,
9 } from 'lemmy-js-client';
10 import { CommentNode as CommentNodeI } from '../interfaces';
11 import {
12   authField,
13   capitalizeFirstLetter,
14   wsClient,
15   wsJsonToRes,
16   wsSubscribe,
17   wsUserOp,
18 } from '../utils';
19 import { WebSocketService, UserService } from '../services';
20 import { i18n } from '../i18next';
21 import { T } from 'inferno-i18next';
22 import { MarkdownTextArea } from './markdown-textarea';
23
24 interface CommentFormProps {
25   postId?: number;
26   node?: CommentNodeI; // Can either be the parent, or the editable comment
27   edit?: boolean;
28   disabled?: boolean;
29   focus?: boolean;
30   onReplyCancel?(): any;
31 }
32
33 interface CommentFormState {
34   buttonTitle: string;
35   finished: boolean;
36   formId: string;
37 }
38
39 export class CommentForm extends Component<CommentFormProps, CommentFormState> {
40   private subscription: Subscription;
41   private emptyState: CommentFormState = {
42     buttonTitle: !this.props.node
43       ? capitalizeFirstLetter(i18n.t('post'))
44       : this.props.edit
45       ? capitalizeFirstLetter(i18n.t('save'))
46       : capitalizeFirstLetter(i18n.t('reply')),
47     finished: false,
48     formId: null,
49   };
50
51   constructor(props: any, context: any) {
52     super(props, context);
53
54     this.handleCommentSubmit = this.handleCommentSubmit.bind(this);
55     this.handleReplyCancel = this.handleReplyCancel.bind(this);
56
57     this.state = this.emptyState;
58
59     this.parseMessage = this.parseMessage.bind(this);
60     this.subscription = wsSubscribe(this.parseMessage);
61   }
62
63   componentWillUnmount() {
64     this.subscription.unsubscribe();
65   }
66
67   render() {
68     return (
69       <div class="mb-3">
70         {UserService.Instance.user ? (
71           <MarkdownTextArea
72             initialContent={
73               this.props.edit
74                 ? this.props.node.comment_view.comment.content
75                 : null
76             }
77             buttonTitle={this.state.buttonTitle}
78             finished={this.state.finished}
79             replyType={!!this.props.node}
80             focus={this.props.focus}
81             disabled={this.props.disabled}
82             onSubmit={this.handleCommentSubmit}
83             onReplyCancel={this.handleReplyCancel}
84           />
85         ) : (
86           <div class="alert alert-light" role="alert">
87             <svg class="icon icon-inline mr-2">
88               <use xlinkHref="#icon-alert-triangle"></use>
89             </svg>
90             <T i18nKey="must_login" class="d-inline">
91               #
92               <Link className="alert-link" to="/login">
93                 #
94               </Link>
95             </T>
96           </div>
97         )}
98       </div>
99     );
100   }
101
102   handleCommentSubmit(msg: { val: string; formId: string }) {
103     let content = msg.val;
104     this.state.formId = msg.formId;
105
106     let node = this.props.node;
107
108     if (this.props.edit) {
109       let form: EditComment = {
110         content,
111         form_id: this.state.formId,
112         comment_id: node.comment_view.comment.id,
113         auth: authField(),
114       };
115       WebSocketService.Instance.send(wsClient.editComment(form));
116     } else {
117       let form: CreateComment = {
118         content,
119         form_id: this.state.formId,
120         post_id: node ? node.comment_view.post.id : this.props.postId,
121         parent_id: node ? node.comment_view.comment.id : null,
122         auth: authField(),
123       };
124       WebSocketService.Instance.send(wsClient.createComment(form));
125     }
126     this.setState(this.state);
127   }
128
129   handleReplyCancel() {
130     this.props.onReplyCancel();
131   }
132
133   parseMessage(msg: any) {
134     let op = wsUserOp(msg);
135
136     // Only do the showing and hiding if logged in
137     if (UserService.Instance.user) {
138       if (
139         op == UserOperation.CreateComment ||
140         op == UserOperation.EditComment
141       ) {
142         let data = wsJsonToRes<CommentResponse>(msg).data;
143
144         // This only finishes this form, if the randomly generated form_id matches the one received
145         if (this.state.formId == data.form_id) {
146           this.setState({ finished: true });
147
148           // Necessary because it broke tribute for some reason
149           this.setState({ finished: false });
150         }
151       }
152     }
153   }
154 }