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