import autosize from "autosize"; import { Component, linkEvent } from "inferno"; import { Prompt } from "inferno-router"; import { CreatePost, EditPost, Language, PostResponse, PostView, Search, SearchResponse, UserOperation, wsJsonToRes, wsUserOp, } from "lemmy-js-client"; import { Subscription } from "rxjs"; import { i18n } from "../../i18next"; import { PostFormParams } from "../../interfaces"; import { UserService, WebSocketService } from "../../services"; import { Choice, archiveTodayUrl, capitalizeFirstLetter, communityToChoice, debounce, fetchCommunities, getIdFromString, getSiteMetadata, ghostArchiveUrl, isImage, myAuth, pictrsDeleteToast, relTags, setupTippy, toast, trendingFetchLimit, uploadImage, validTitle, validURL, webArchiveUrl, wsClient, wsSubscribe, } from "../../utils"; import { Icon, Spinner } from "../common/icon"; import { LanguageSelect } from "../common/language-select"; import { MarkdownTextArea } from "../common/markdown-textarea"; import { SearchableSelect } from "../common/searchable-select"; import { PostListings } from "./post-listings"; const MAX_POST_TITLE_LENGTH = 200; interface PostFormProps { post_view?: PostView; // If a post is given, that means this is an edit allLanguages: Language[]; siteLanguages: number[]; params?: PostFormParams; onCancel?(): any; onCreate?(post: PostView): any; onEdit?(post: PostView): any; enableNsfw?: boolean; enableDownvotes?: boolean; selectedCommunityChoice?: Choice; onSelectCommunity?: (choice: Choice) => void; } interface PostFormState { form: { name?: string; url?: string; body?: string; nsfw?: boolean; language_id?: number; community_id?: number; honeypot?: string; }; suggestedTitle?: string; suggestedPosts?: PostView[]; crossPosts?: PostView[]; loading: boolean; imageLoading: boolean; communitySearchLoading: boolean; communitySearchOptions: Choice[]; previewMode: boolean; } export class PostForm extends Component { private subscription?: Subscription; state: PostFormState = { form: {}, loading: false, imageLoading: false, communitySearchLoading: false, previewMode: false, communitySearchOptions: [], }; constructor(props: PostFormProps, context: any) { super(props, context); this.fetchSimilarPosts = debounce(this.fetchSimilarPosts.bind(this)); this.fetchPageTitle = debounce(this.fetchPageTitle.bind(this)); this.handlePostBodyChange = this.handlePostBodyChange.bind(this); this.handleLanguageChange = this.handleLanguageChange.bind(this); this.handleCommunitySelect = this.handleCommunitySelect.bind(this); this.parseMessage = this.parseMessage.bind(this); this.subscription = wsSubscribe(this.parseMessage); // Means its an edit const pv = this.props.post_view; if (pv) { this.state = { ...this.state, form: { body: pv.post.body, name: pv.post.name, community_id: pv.community.id, url: pv.post.url, nsfw: pv.post.nsfw, language_id: pv.post.language_id, }, }; } const selectedCommunityChoice = this.props.selectedCommunityChoice; if (selectedCommunityChoice) { this.state = { ...this.state, form: { ...this.state.form, community_id: getIdFromString(selectedCommunityChoice.value), }, communitySearchOptions: [selectedCommunityChoice], }; } const params = this.props.params; if (params) { this.state = { ...this.state, form: { ...this.state.form, ...params, }, }; } } componentDidMount() { setupTippy(); const textarea: any = document.getElementById("post-title"); if (textarea) { autosize(textarea); } } componentDidUpdate() { if ( !this.state.loading && (this.state.form.name || this.state.form.url || this.state.form.body) ) { window.onbeforeunload = () => true; } else { window.onbeforeunload = null; } } componentWillUnmount() { this.subscription?.unsubscribe(); /* this.choices && this.choices.destroy(); */ window.onbeforeunload = null; } static getDerivedStateFromProps( { selectedCommunityChoice }: PostFormProps, { form, ...restState }: PostFormState ) { return { ...restState, form: { ...form, community_id: getIdFromString(selectedCommunityChoice?.value), }, }; } render() { let firstLang = this.state.form.language_id; let selectedLangs = firstLang ? Array.of(firstLang) : undefined; let url = this.state.form.url; return (
{this.state.suggestedTitle && (
{i18n.t("copy_suggested_title", { title: "" })}{" "} {this.state.suggestedTitle}
)} {url && validURL(url) && ( )} {this.state.imageLoading && } {url && isImage(url) && ( )} {this.state.crossPosts && this.state.crossPosts.length > 0 && ( <>
{i18n.t("cross_posts")}
)}