import autosize from "autosize"; import { Component, linkEvent } from "inferno"; import { Prompt } from "inferno-router"; import { Language } from "lemmy-js-client"; import { pictrsUri } from "../../env"; import { i18n } from "../../i18next"; import { UserService } from "../../services"; import { isBrowser, markdownFieldCharacterLimit, markdownHelpUrl, mdToHtml, pictrsDeleteToast, randomStr, relTags, setupTippy, setupTribute, toast, } from "../../utils"; import { Icon, Spinner } from "./icon"; import { LanguageSelect } from "./language-select"; interface MarkdownTextAreaProps { initialContent?: string; initialLanguageId?: number; placeholder?: string; buttonTitle?: string; maxLength?: number; replyType?: boolean; focus?: boolean; disabled?: boolean; finished?: boolean; showLanguage?: boolean; hideNavigationWarnings?: boolean; onContentChange?(val: string): any; onReplyCancel?(): any; onSubmit?(msg: { val?: string; formId: string; languageId?: number }): any; allLanguages: Language[]; // TODO should probably be nullable siteLanguages: number[]; // TODO same } interface MarkdownTextAreaState { content?: string; languageId?: number; previewMode: boolean; loading: boolean; imageLoading: boolean; } export class MarkdownTextArea extends Component< MarkdownTextAreaProps, MarkdownTextAreaState > { private id = `comment-textarea-${randomStr()}`; private formId = `comment-form-${randomStr()}`; private tribute: any; state: MarkdownTextAreaState = { content: this.props.initialContent, languageId: this.props.initialLanguageId, previewMode: false, loading: false, imageLoading: false, }; constructor(props: any, context: any) { super(props, context); this.handleLanguageChange = this.handleLanguageChange.bind(this); if (isBrowser()) { this.tribute = setupTribute(); } } componentDidMount() { let textarea: any = document.getElementById(this.id); if (textarea) { autosize(textarea); this.tribute.attach(textarea); textarea.addEventListener("tribute-replaced", () => { this.setState({ content: textarea.value }); autosize.update(textarea); }); this.quoteInsert(); if (this.props.focus) { textarea.focus(); } // TODO this is slow for some reason setupTippy(); } } componentDidUpdate() { if (!this.props.hideNavigationWarnings && this.state.content) { window.onbeforeunload = () => true; } else { window.onbeforeunload = null; } } componentWillReceiveProps(nextProps: MarkdownTextAreaProps) { if (nextProps.finished) { this.setState({ previewMode: false, loading: false, content: undefined }); if (this.props.replyType) { this.props.onReplyCancel?.(); } let textarea: any = document.getElementById(this.id); let form: any = document.getElementById(this.formId); form.reset(); setTimeout(() => autosize.update(textarea), 10); } } componentWillUnmount() { window.onbeforeunload = null; } render() { let languageId = this.state.languageId; return (