import autosize from "autosize"; import { NoOptionI18nKeys } from "i18next"; import { Component, linkEvent } from "inferno"; import { Language } from "lemmy-js-client"; import { i18n } from "../../i18next"; import { HttpService, UserService } from "../../services"; import { concurrentImageUpload, customEmojisLookup, markdownFieldCharacterLimit, markdownHelpUrl, maxUploadImages, mdToHtml, numToSI, pictrsDeleteToast, randomStr, relTags, setupTippy, setupTribute, toast, } from "../../utils"; import { isBrowser } from "../../utils/browser/is-browser"; import { EmojiPicker } from "./emoji-picker"; import { Icon, Spinner } from "./icon"; import { LanguageSelect } from "./language-select"; import NavigationPrompt from "./navigation-prompt"; import ProgressBar from "./progress-bar"; 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): void; onReplyCancel?(): void; onSubmit?(content: string, formId: string, languageId?: number): void; allLanguages: Language[]; // TODO should probably be nullable siteLanguages: number[]; // TODO same } interface ImageUploadStatus { total: number; uploaded: number; } interface MarkdownTextAreaState { content?: string; languageId?: number; previewMode: boolean; imageUploadStatus?: ImageUploadStatus; loading: boolean; submitted: 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, submitted: false, }; constructor(props: any, context: any) { super(props, context); this.handleLanguageChange = this.handleLanguageChange.bind(this); if (isBrowser()) { this.tribute = setupTribute(); } } componentDidMount() { const 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(); } } componentWillReceiveProps(nextProps: MarkdownTextAreaProps) { if (nextProps.finished) { this.setState({ previewMode: false, imageUploadStatus: undefined, loading: false, content: undefined, }); if (this.props.replyType) { this.props.onReplyCancel?.(); } const textarea: any = document.getElementById(this.id); const form: any = document.getElementById(this.formId); form.reset(); setTimeout(() => autosize.update(textarea), 10); } } render() { const languageId = this.state.languageId; // TODO add these prompts back in at some point // return (