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";
6 CommentNode as CommentNodeI,
13 } from "lemmy-js-client";
14 import { Subscription } from "rxjs";
15 import { i18n } from "../../i18next";
16 import { UserService, WebSocketService } from "../../services";
19 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: Either<CommentNodeI, number>;
34 onReplyCancel?(): any;
37 interface CommentFormState {
40 formId: Option<string>;
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"))
49 ? capitalizeFirstLetter(i18n.t("save"))
50 : capitalizeFirstLetter(i18n.t("reply")),
55 constructor(props: any, context: any) {
56 super(props, context);
58 this.handleCommentSubmit = this.handleCommentSubmit.bind(this);
59 this.handleReplyCancel = this.handleReplyCancel.bind(this);
61 this.state = this.emptyState;
63 this.parseMessage = this.parseMessage.bind(this);
64 this.subscription = wsSubscribe(this.parseMessage);
67 componentWillUnmount() {
68 this.subscription.unsubscribe();
72 let initialContent = this.props.node.match({
74 this.props.edit ? Some(node.comment_view.comment.content) : None,
78 <div className="mb-3">
79 {UserService.Instance.myUserInfo.isSome() ? (
81 initialContent={initialContent}
82 buttonTitle={Some(this.state.buttonTitle)}
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"))}
93 <div className="alert alert-warning" role="alert">
94 <Icon icon="alert-triangle" classes="icon-inline mr-2" />
95 <T i18nKey="must_login" class="d-inline">
97 <Link className="alert-link" to="/login">
107 handleCommentSubmit(msg: { val: string; formId: string }) {
108 let content = msg.val;
109 this.setState({ formId: Some(msg.formId) });
111 this.props.node.match({
113 if (this.props.edit) {
114 let form = new EditComment({
115 content: Some(content),
117 form_id: this.state.formId,
118 comment_id: node.comment_view.comment.id,
119 auth: auth().unwrap(),
121 WebSocketService.Instance.send(wsClient.editComment(form));
123 let form = new CreateComment({
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(),
130 WebSocketService.Instance.send(wsClient.createComment(form));
134 let form = new CreateComment({
136 form_id: this.state.formId,
139 auth: auth().unwrap(),
141 WebSocketService.Instance.send(wsClient.createComment(form));
144 this.setState(this.state);
147 handleReplyCancel() {
148 this.props.onReplyCancel();
151 parseMessage(msg: any) {
152 let op = wsUserOp(msg);
155 // Only do the showing and hiding if logged in
156 if (UserService.Instance.myUserInfo.isSome()) {
158 op == UserOperation.CreateComment ||
159 op == UserOperation.EditComment
161 let data = wsJsonToRes<CommentResponse>(msg, CommentResponse);
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 });
167 // Necessary because it broke tribute for some reason
168 this.setState({ finished: false });