lemmy-ui/src/shared/components/private-message-form.tsx

249 lines
7.2 KiB
TypeScript
Raw Normal View History

2021-02-22 02:39:04 +00:00
import { Component, linkEvent } from "inferno";
import { Prompt } from "inferno-router";
import { Subscription } from "rxjs";
import {
2020-12-24 01:58:27 +00:00
CreatePrivateMessage,
EditPrivateMessage,
PrivateMessageView,
PrivateMessageResponse,
2020-12-24 01:58:27 +00:00
UserSafe,
UserOperation,
2021-02-22 02:39:04 +00:00
} from "lemmy-js-client";
import { WebSocketService } from "../services";
import {
capitalizeFirstLetter,
wsJsonToRes,
toast,
setupTippy,
2020-09-08 18:44:55 +00:00
wsSubscribe,
isBrowser,
2020-12-24 01:58:27 +00:00
wsUserOp,
wsClient,
authField,
2021-02-22 02:39:04 +00:00
} from "../utils";
import { UserListing } from "./user-listing";
import { MarkdownTextArea } from "./markdown-textarea";
import { Icon, Spinner } from "./icon";
import { i18n } from "../i18next";
import { T } from "inferno-i18next";
interface PrivateMessageFormProps {
2020-12-24 01:58:27 +00:00
recipient: UserSafe;
privateMessage?: PrivateMessageView; // If a pm is given, that means this is an edit
onCancel?(): any;
2020-12-24 01:58:27 +00:00
onCreate?(message: PrivateMessageView): any;
onEdit?(message: PrivateMessageView): any;
}
interface PrivateMessageFormState {
2020-12-24 01:58:27 +00:00
privateMessageForm: CreatePrivateMessage;
loading: boolean;
previewMode: boolean;
showDisclaimer: boolean;
}
export class PrivateMessageForm extends Component<
PrivateMessageFormProps,
PrivateMessageFormState
> {
private subscription: Subscription;
private emptyState: PrivateMessageFormState = {
privateMessageForm: {
content: null,
2020-09-08 18:44:55 +00:00
recipient_id: this.props.recipient.id,
auth: authField(),
},
loading: false,
previewMode: false,
showDisclaimer: false,
};
constructor(props: any, context: any) {
super(props, context);
this.state = this.emptyState;
this.handleContentChange = this.handleContentChange.bind(this);
2020-09-08 18:44:55 +00:00
this.parseMessage = this.parseMessage.bind(this);
this.subscription = wsSubscribe(this.parseMessage);
2020-12-24 01:58:27 +00:00
// Its an edit
if (this.props.privateMessage) {
2020-12-24 01:58:27 +00:00
this.state.privateMessageForm.content = this.props.privateMessage.private_message.content;
}
}
componentDidMount() {
setupTippy();
}
componentDidUpdate() {
if (!this.state.loading && this.state.privateMessageForm.content) {
window.onbeforeunload = () => true;
} else {
window.onbeforeunload = undefined;
}
}
componentWillUnmount() {
2020-09-08 18:44:55 +00:00
if (isBrowser()) {
this.subscription.unsubscribe();
window.onbeforeunload = null;
}
}
render() {
return (
<div>
<Prompt
when={!this.state.loading && this.state.privateMessageForm.content}
2021-02-22 02:39:04 +00:00
message={i18n.t("block_leaving")}
/>
<form onSubmit={linkEvent(this, this.handlePrivateMessageSubmit)}>
{!this.props.privateMessage && (
<div class="form-group row">
<label class="col-sm-2 col-form-label">
2021-02-22 02:39:04 +00:00
{capitalizeFirstLetter(i18n.t("to"))}
</label>
2020-09-08 18:44:55 +00:00
<div class="col-sm-10 form-control-plaintext">
2020-12-24 01:58:27 +00:00
<UserListing user={this.props.recipient} />
2020-09-08 18:44:55 +00:00
</div>
</div>
)}
<div class="form-group row">
<label class="col-sm-2 col-form-label">
2021-02-22 02:39:04 +00:00
{i18n.t("message")}
<span
onClick={linkEvent(this, this.handleShowDisclaimer)}
role="button"
class="ml-2 pointer text-danger"
2021-03-01 21:23:25 +00:00
data-tippy-content={i18n.t("private_message_disclaimer")}
aria-label={i18n.t("private_message_disclaimer")}
>
2021-02-11 20:35:27 +00:00
<Icon icon="alert-triangle" classes="icon-inline" />
</span>
</label>
<div class="col-sm-10">
<MarkdownTextArea
initialContent={this.state.privateMessageForm.content}
onContentChange={this.handleContentChange}
/>
</div>
</div>
{this.state.showDisclaimer && (
<div class="form-group row">
<div class="offset-sm-2 col-sm-10">
<div class="alert alert-danger" role="alert">
<T i18nKey="private_message_disclaimer">
#
<a
class="alert-link"
rel="noopener"
href="https://element.io/get-started"
>
#
</a>
</T>
</div>
</div>
</div>
)}
<div class="form-group row">
<div class="offset-sm-2 col-sm-10">
<button
type="submit"
class="btn btn-secondary mr-2"
disabled={this.state.loading}
>
{this.state.loading ? (
2021-02-11 20:35:27 +00:00
<Spinner />
) : this.props.privateMessage ? (
2021-02-22 02:39:04 +00:00
capitalizeFirstLetter(i18n.t("save"))
) : (
2021-02-22 02:39:04 +00:00
capitalizeFirstLetter(i18n.t("send_message"))
)}
</button>
{this.props.privateMessage && (
<button
type="button"
class="btn btn-secondary"
onClick={linkEvent(this, this.handleCancel)}
>
2021-02-22 02:39:04 +00:00
{i18n.t("cancel")}
</button>
)}
<ul class="d-inline-block float-right list-inline mb-1 text-muted font-weight-bold">
<li class="list-inline-item"></li>
</ul>
</div>
</div>
</form>
</div>
);
}
handlePrivateMessageSubmit(i: PrivateMessageForm, event: any) {
event.preventDefault();
if (i.props.privateMessage) {
2020-12-24 01:58:27 +00:00
let form: EditPrivateMessage = {
private_message_id: i.props.privateMessage.private_message.id,
content: i.state.privateMessageForm.content,
auth: authField(),
};
WebSocketService.Instance.send(wsClient.editPrivateMessage(form));
} else {
WebSocketService.Instance.send(
wsClient.createPrivateMessage(i.state.privateMessageForm)
);
}
i.state.loading = true;
i.setState(i.state);
}
handleContentChange(val: string) {
this.state.privateMessageForm.content = val;
this.setState(this.state);
}
handleCancel(i: PrivateMessageForm) {
i.props.onCancel();
}
handlePreviewToggle(i: PrivateMessageForm, event: any) {
event.preventDefault();
i.state.previewMode = !i.state.previewMode;
i.setState(i.state);
}
handleShowDisclaimer(i: PrivateMessageForm) {
i.state.showDisclaimer = !i.state.showDisclaimer;
i.setState(i.state);
}
2020-12-24 01:58:27 +00:00
parseMessage(msg: any) {
let op = wsUserOp(msg);
if (msg.error) {
2021-02-22 02:39:04 +00:00
toast(i18n.t(msg.error), "danger");
this.state.loading = false;
this.setState(this.state);
return;
} else if (
2020-12-24 01:58:27 +00:00
op == UserOperation.EditPrivateMessage ||
op == UserOperation.DeletePrivateMessage ||
op == UserOperation.MarkPrivateMessageAsRead
) {
2020-12-24 01:58:27 +00:00
let data = wsJsonToRes<PrivateMessageResponse>(msg).data;
this.state.loading = false;
2020-12-24 01:58:27 +00:00
this.props.onEdit(data.private_message_view);
} else if (op == UserOperation.CreatePrivateMessage) {
let data = wsJsonToRes<PrivateMessageResponse>(msg).data;
this.state.loading = false;
2020-12-24 01:58:27 +00:00
this.props.onCreate(data.private_message_view);
this.setState(this.state);
}
}
}