import { None, Option, Some } from "@sniptt/monads"; import autosize from "autosize"; import { Component, linkEvent } from "inferno"; import { Prompt } from "inferno-router"; import { CommunityView, CreatePost, EditPost, ListingType, PostResponse, PostView, Search, SearchResponse, SearchType, SortType, toUndefined, UserOperation, wsJsonToRes, wsUserOp, } from "lemmy-js-client"; import { Subscription } from "rxjs"; import { pictrsUri } from "../../env"; import { i18n } from "../../i18next"; import { PostFormParams } from "../../interfaces"; import { UserService, WebSocketService } from "../../services"; import { archiveTodayUrl, auth, capitalizeFirstLetter, choicesConfig, communitySelectName, communityToChoice, debounce, fetchCommunities, getSiteMetadata, ghostArchiveUrl, isBrowser, isImage, pictrsDeleteToast, relTags, setupTippy, toast, trendingFetchLimit, validTitle, validURL, webArchiveUrl, wsClient, wsSubscribe, } from "../../utils"; import { Icon, Spinner } from "../common/icon"; import { MarkdownTextArea } from "../common/markdown-textarea"; import { PostListings } from "./post-listings"; var Choices: any; if (isBrowser()) { Choices = require("choices.js"); } const MAX_POST_TITLE_LENGTH = 200; interface PostFormProps { post_view: Option; // If a post is given, that means this is an edit communities: Option; params: Option; onCancel?(): any; onCreate?(post: PostView): any; onEdit?(post: PostView): any; enableNsfw?: boolean; enableDownvotes?: boolean; } interface PostFormState { postForm: CreatePost; suggestedTitle: Option; suggestedPosts: Option; crossPosts: Option; loading: boolean; imageLoading: boolean; previewMode: boolean; } export class PostForm extends Component { private subscription: Subscription; private choices: any; private emptyState: PostFormState = { postForm: new CreatePost({ community_id: undefined, name: undefined, nsfw: Some(false), url: None, body: None, honeypot: None, auth: undefined, }), loading: false, imageLoading: false, previewMode: false, suggestedTitle: None, suggestedPosts: None, crossPosts: None, }; constructor(props: any, 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.state = this.emptyState; // Means its an edit this.props.post_view.match({ some: pv => (this.state.postForm = new CreatePost({ body: pv.post.body, name: pv.post.name, community_id: pv.community.id, url: pv.post.url, nsfw: Some(pv.post.nsfw), honeypot: None, auth: auth().unwrap(), })), none: void 0, }); this.props.params.match({ some: params => { this.state.postForm.name = toUndefined(params.name); this.state.postForm.url = params.url; this.state.postForm.body = params.body; }, none: void 0, }); this.parseMessage = this.parseMessage.bind(this); this.subscription = wsSubscribe(this.parseMessage); } componentDidMount() { setupTippy(); this.setupCommunities(); let textarea: any = document.getElementById("post-title"); if (textarea) { autosize(textarea); } } componentDidUpdate() { if ( !this.state.loading && (this.state.postForm.name || this.state.postForm.url.isSome() || this.state.postForm.body.isSome()) ) { window.onbeforeunload = () => true; } else { window.onbeforeunload = undefined; } } componentWillUnmount() { this.subscription.unsubscribe(); /* this.choices && this.choices.destroy(); */ window.onbeforeunload = null; } render() { return (
{this.state.suggestedTitle.match({ some: title => (
{i18n.t("copy_suggested_title", { title: "" })} {title}
), none: <>, })} {this.state.postForm.url.match({ some: url => validURL(url) && ( ), none: <>, })} {this.state.imageLoading && } {this.state.postForm.url.match({ some: url => isImage(url) && , none: <>, })} {this.state.crossPosts.match({ some: xPosts => xPosts.length > 0 && ( <>
{i18n.t("cross_posts")}
), none: <>, })}