1 import { Component } from "inferno";
2 import { T } from "inferno-i18next-dess";
3 import { Link } from "inferno-router";
12 } from "lemmy-js-client";
13 import { Subscription } from "rxjs";
14 import { i18n } from "../../i18next";
15 import { CommentNodeI } from "../../interfaces";
16 import { UserService, WebSocketService } from "../../services";
18 capitalizeFirstLetter,
23 import { Icon } from "../common/icon";
24 import { MarkdownTextArea } from "../common/markdown-textarea";
26 interface CommentFormProps {
28 * Can either be the parent, or the editable comment. The right side is a postId.
30 node: CommentNodeI | number;
34 onReplyCancel?(): any;
35 allLanguages: Language[];
36 siteLanguages: number[];
39 interface CommentFormState {
45 export class CommentForm extends Component<CommentFormProps, CommentFormState> {
46 private subscription?: Subscription;
47 state: CommentFormState = {
49 typeof this.props.node === "number"
50 ? capitalizeFirstLetter(i18n.t("post"))
52 ? capitalizeFirstLetter(i18n.t("save"))
53 : capitalizeFirstLetter(i18n.t("reply")),
57 constructor(props: any, context: any) {
58 super(props, context);
60 this.handleCommentSubmit = this.handleCommentSubmit.bind(this);
61 this.handleReplyCancel = this.handleReplyCancel.bind(this);
63 this.parseMessage = this.parseMessage.bind(this);
64 this.subscription = wsSubscribe(this.parseMessage);
67 componentWillUnmount() {
68 this.subscription?.unsubscribe();
72 const initialContent =
73 typeof this.props.node !== "number"
75 ? this.props.node.comment_view.comment.content
80 <div className="mb-3">
81 {UserService.Instance.myUserInfo ? (
83 initialContent={initialContent}
85 buttonTitle={this.state.buttonTitle}
86 finished={this.state.finished}
87 replyType={typeof this.props.node !== "number"}
88 focus={this.props.focus}
89 disabled={this.props.disabled}
90 onSubmit={this.handleCommentSubmit}
91 onReplyCancel={this.handleReplyCancel}
92 placeholder={i18n.t("comment_here")}
93 allLanguages={this.props.allLanguages}
94 siteLanguages={this.props.siteLanguages}
97 <div className="alert alert-warning" role="alert">
98 <Icon icon="alert-triangle" classes="icon-inline mr-2" />
99 <T i18nKey="must_login" class="d-inline">
101 <Link className="alert-link" to="/login">
111 handleCommentSubmit(msg: {
116 const content = msg.val;
117 const language_id = msg.languageId;
118 const node = this.props.node;
120 this.setState({ formId: msg.formId });
122 const auth = myAuth();
124 if (typeof node === "number") {
126 const form: CreateComment = {
128 form_id: this.state.formId,
133 WebSocketService.Instance.send(wsClient.createComment(form));
135 if (this.props.edit) {
136 const form: EditComment = {
138 form_id: this.state.formId,
139 comment_id: node.comment_view.comment.id,
143 WebSocketService.Instance.send(wsClient.editComment(form));
145 const form: CreateComment = {
147 form_id: this.state.formId,
148 post_id: node.comment_view.post.id,
149 parent_id: node.comment_view.comment.id,
153 WebSocketService.Instance.send(wsClient.createComment(form));
159 handleReplyCancel() {
160 this.props.onReplyCancel?.();
163 parseMessage(msg: any) {
164 const op = wsUserOp(msg);
167 // Only do the showing and hiding if logged in
168 if (UserService.Instance.myUserInfo) {
170 op == UserOperation.CreateComment ||
171 op == UserOperation.EditComment
173 const data = wsJsonToRes<CommentResponse>(msg);
175 // This only finishes this form, if the randomly generated form_id matches the one received
176 if (this.state.formId && this.state.formId == data.form_id) {
177 this.setState({ finished: true });
179 // Necessary because it broke tribute for some reason
180 this.setState({ finished: false });