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,
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 class="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.state.formId = Some(msg.formId);
111 this.props.node.match({
113 if (this.props.edit) {
114 let form = new EditComment({
116 form_id: this.state.formId,
117 comment_id: node.comment_view.comment.id,
118 auth: auth().unwrap(),
120 WebSocketService.Instance.send(wsClient.editComment(form));
122 let form = new CreateComment({
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(),
129 WebSocketService.Instance.send(wsClient.createComment(form));
133 let form = new CreateComment({
135 form_id: this.state.formId,
138 auth: auth().unwrap(),
140 WebSocketService.Instance.send(wsClient.createComment(form));
143 this.setState(this.state);
146 handleReplyCancel() {
147 this.props.onReplyCancel();
150 parseMessage(msg: any) {
151 let op = wsUserOp(msg);
154 // Only do the showing and hiding if logged in
155 if (UserService.Instance.myUserInfo.isSome()) {
157 op == UserOperation.CreateComment ||
158 op == UserOperation.EditComment
160 let data = wsJsonToRes<CommentResponse>(msg, CommentResponse);
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 });
166 // Necessary because it broke tribute for some reason
167 this.setState({ finished: false });