import PropTypes from "prop-types"; import { PureComponent } from "react"; import { FormattedMessage } from "react-intl"; import classnames from "classnames"; import Immutable from "immutable"; import ImmutablePropTypes from "react-immutable-proptypes"; import { Blurhash } from "flavours/glitch/components/blurhash"; import { Icon } from "flavours/glitch/components/icon"; import { decode as decodeIDNA } from "flavours/glitch/utils/idna"; const getHostname = url => { const parser = document.createElement("a"); parser.href = url; return parser.hostname; }; const domParser = new DOMParser(); const addAutoPlay = html => { const document = domParser.parseFromString(html, "text/html").documentElement; const iframe = document.querySelector("iframe"); if (iframe) { if (iframe.src.indexOf("?") !== -1) { iframe.src += "&"; } else { iframe.src += "?"; } iframe.src += "autoplay=1&auto_play=1"; // DOM parser creates html/body elements around original HTML fragment, // so we need to get innerHTML out of the body and not the entire document return document.querySelector("body").innerHTML; } return html; }; export default class Card extends PureComponent { static propTypes = { card: ImmutablePropTypes.map, onOpenMedia: PropTypes.func.isRequired, compact: PropTypes.bool, sensitive: PropTypes.bool, useBlurhash: PropTypes.bool, }; static defaultProps = { compact: false, }; state = { previewLoaded: false, embedded: false, revealed: !this.props.sensitive, }; UNSAFE_componentWillReceiveProps (nextProps) { if (!Immutable.is(this.props.card, nextProps.card)) { this.setState({ embedded: false, previewLoaded: false }); } if (this.props.sensitive !== nextProps.sensitive) { this.setState({ revealed: !nextProps.sensitive }); } } componentDidMount () { window.addEventListener("resize", this.handleResize, { passive: true }); } componentWillUnmount () { window.removeEventListener("resize", this.handleResize); } handlePhotoClick = () => { const { card, onOpenMedia } = this.props; onOpenMedia( Immutable.fromJS([ { type: "image", url: card.get("embed_url"), description: card.get("title"), meta: { original: { width: card.get("width"), height: card.get("height"), }, }, }, ]), 0, ); }; handleEmbedClick = () => { const { card } = this.props; if (card.get("type") === "photo") { this.handlePhotoClick(); } else { this.setState({ embedded: true }); } }; setRef = c => { this.node = c; }; handleImageLoad = () => { this.setState({ previewLoaded: true }); }; handleReveal = e => { e.preventDefault(); e.stopPropagation(); this.setState({ revealed: true }); }; renderVideo () { const { card } = this.props; const content = { __html: addAutoPlay(card.get("html")) }; return (
); } render () { const { card, compact, useBlurhash } = this.props; const { embedded, revealed } = this.state; if (card === null) { return null; } const provider = card.get("provider_name").length === 0 ? decodeIDNA(getHostname(card.get("url"))) : card.get("provider_name"); const horizontal = (!compact && card.get("width") > card.get("height")) || card.get("type") !== "link" || embedded; const interactive = card.get("type") !== "link"; const className = classnames("status-card", { horizontal, compact, interactive }); const title = interactive ? {card.get("title")} : {card.get("title")}; const language = card.get("language") || ""; const description = ({card.get("description")}
} {provider}