From 1a50e697ceaaf93e81965cb49d195a7735fa10ed Mon Sep 17 00:00:00 2001 From: Sean Yesmunt Date: Wed, 29 Apr 2020 16:50:06 -0400 Subject: [PATCH] embed functionality inside markdown posts --- .../fileViewerEmbeddedTitle/view.jsx | 27 ---- .../common/form-components/form-field.jsx | 2 +- .../common/markdown-preview-internal.jsx | 121 --------------- ui/component/common/markdown-preview.jsx | 144 +++++++++++++++++- ui/component/embedPlayButton/index.js | 19 +++ ui/component/embedPlayButton/view.jsx | 60 ++++++++ ui/component/fileRenderFloating/index.js | 9 +- ui/component/fileRenderFloating/view.jsx | 16 +- .../fileViewerEmbeddedTitle/index.js | 0 ui/component/fileViewerEmbeddedTitle/view.jsx | 38 +++++ ui/component/viewers/videoViewer/view.jsx | 2 +- ui/constants/action_types.js | 1 + ui/redux/actions/content.js | 34 +++-- ui/redux/reducers/content.js | 6 + ui/redux/selectors/content.js | 17 ++- ui/scss/component/_embed-player.scss | 17 +++ ui/scss/component/_file-render.scss | 4 + ui/scss/component/_markdown-preview.scss | 12 -- 18 files changed, 343 insertions(+), 186 deletions(-) delete mode 100644 lbrytv/component/fileViewerEmbeddedTitle/view.jsx delete mode 100644 ui/component/common/markdown-preview-internal.jsx create mode 100644 ui/component/embedPlayButton/index.js create mode 100644 ui/component/embedPlayButton/view.jsx rename {lbrytv => ui}/component/fileViewerEmbeddedTitle/index.js (100%) create mode 100644 ui/component/fileViewerEmbeddedTitle/view.jsx diff --git a/lbrytv/component/fileViewerEmbeddedTitle/view.jsx b/lbrytv/component/fileViewerEmbeddedTitle/view.jsx deleted file mode 100644 index de09393da..000000000 --- a/lbrytv/component/fileViewerEmbeddedTitle/view.jsx +++ /dev/null @@ -1,27 +0,0 @@ -// @flow -import React from 'react'; -import Button from 'component/button'; -import { formatLbryUrlForWeb } from 'util/url'; -import { withRouter } from 'react-router'; -import { URL } from 'config'; -import * as ICONS from 'constants/icons'; - -type Props = { - uri: string, - title: ?string, -}; - -function fileViewerEmbeddedTitle(props: Props) { - const { uri, title } = props; - - const lbrytvLink = `${URL}${formatLbryUrlForWeb(uri)}?src=embed`; - - return ( -
-
- ); -} - -export default withRouter(fileViewerEmbeddedTitle); diff --git a/ui/component/common/form-components/form-field.jsx b/ui/component/common/form-components/form-field.jsx index 3c4b963b0..8a481201d 100644 --- a/ui/component/common/form-components/form-field.jsx +++ b/ui/component/common/form-components/form-field.jsx @@ -3,7 +3,7 @@ import type { ElementRef, Node } from 'react'; import React from 'react'; import ReactDOMServer from 'react-dom/server'; import SimpleMDE from 'react-simplemde-editor'; -import MarkdownPreview from 'component/common/markdown-preview-internal'; +import MarkdownPreview from 'component/common/markdown-preview'; import { openEditorMenu, stopContextMenu } from 'util/context-menu'; import { MAX_CHARACTERS_IN_COMMENT as defaultTextAreaLimit } from 'constants/comments'; import 'easymde/dist/easymde.min.css'; diff --git a/ui/component/common/markdown-preview-internal.jsx b/ui/component/common/markdown-preview-internal.jsx deleted file mode 100644 index b2d3e9a99..000000000 --- a/ui/component/common/markdown-preview-internal.jsx +++ /dev/null @@ -1,121 +0,0 @@ -// @flow -import * as React from 'react'; -import remark from 'remark'; -import remarkAttr from 'remark-attr'; -import remarkStrip from 'strip-markdown'; -import remarkEmoji from 'remark-emoji'; -import reactRenderer from 'remark-react'; -import ExternalLink from 'component/externalLink'; -import defaultSchema from 'hast-util-sanitize/lib/github.json'; -import { formatedLinks, inlineLinks } from 'util/remark-lbry'; -import { Link } from 'react-router-dom'; -import { formatLbryUrlForWeb } from 'util/url'; - -type SimpleTextProps = { - children?: React.Node, -}; - -type SimpleLinkProps = { - href?: string, - title?: string, - children?: React.Node, -}; - -type MarkdownProps = { - strip?: boolean, - content: ?string, - promptLinks?: boolean, -}; - -const SimpleText = (props: SimpleTextProps) => { - return {props.children}; -}; - -const SimpleLink = (props: SimpleLinkProps) => { - const { title, children } = props; - let { href } = props; - if (IS_WEB && href && href.startsWith('lbry://')) { - href = formatLbryUrlForWeb(href); - // using Link after formatLbryUrl to handle "/" vs "#/" - // for web and desktop scenarios respectively - return ( - { - e.stopPropagation(); - }} - > - {children} - - ); - } - return ( - - {children} - - ); -}; - -// Use github sanitation schema -const schema = { ...defaultSchema }; - -// Extend sanitation schema to support lbry protocol -schema.protocols.href.push('lbry'); -schema.attributes.a.push('embed'); - -const MarkdownPreview = (props: MarkdownProps) => { - const { content, strip, promptLinks } = props; - - const remarkOptions: Object = { - sanitize: schema, - fragment: React.Fragment, - remarkReactComponents: { - a: promptLinks ? ExternalLink : SimpleLink, - // Workaraund of remarkOptions.Fragment - div: React.Fragment, - }, - }; - - const remarkAttrOpts = { - scope: 'extended', - elements: ['link'], - extend: { link: ['embed'] }, - defaultValue: true, - }; - - // Strip all content and just render text - if (strip) { - // Remove new lines and extra space - remarkOptions.remarkReactComponents.p = SimpleText; - return ( - - { - remark() - .use(remarkStrip) - .use(reactRenderer, remarkOptions) - .processSync(content).contents - } - - ); - } - - return ( -
- { - remark() - .use(remarkAttr, remarkAttrOpts) - // Remark plugins for lbry urls - // Note: The order is important - .use(formatedLinks) - .use(inlineLinks) - // Emojis - .use(remarkEmoji) - .use(reactRenderer, remarkOptions) - .processSync(content).contents - } -
- ); -}; - -export default MarkdownPreview; diff --git a/ui/component/common/markdown-preview.jsx b/ui/component/common/markdown-preview.jsx index 3064b472c..bfbdd3169 100644 --- a/ui/component/common/markdown-preview.jsx +++ b/ui/component/common/markdown-preview.jsx @@ -1,8 +1,144 @@ -import React, { Suspense } from 'react'; -import MarkDownPreview from './markdown-preview-internal'; +// @flow +import * as React from 'react'; +import remark from 'remark'; +import remarkAttr from 'remark-attr'; +import remarkStrip from 'strip-markdown'; +import remarkEmoji from 'remark-emoji'; +import reactRenderer from 'remark-react'; +import ExternalLink from 'component/externalLink'; +import defaultSchema from 'hast-util-sanitize/lib/github.json'; +import { formatedLinks, inlineLinks } from 'util/remark-lbry'; +import { Link } from 'react-router-dom'; +import { formatLbryUrlForWeb } from 'util/url'; +import EmbedPlayButton from 'component/embedPlayButton'; -const MarkdownPreview = props => { - return ; +type SimpleTextProps = { + children?: React.Node, +}; + +type SimpleLinkProps = { + href?: string, + title?: string, + children?: React.Node, +}; + +type MarkdownProps = { + strip?: boolean, + content: ?string, + promptLinks?: boolean, +}; + +const SimpleText = (props: SimpleTextProps) => { + return {props.children}; +}; + +const SimpleLink = (props: SimpleLinkProps) => { + const { title, children } = props; + const { href } = props; + + if (!href) { + return children || null; + } + + if (!href.startsWith('lbry://')) { + return ( + + {children} + + ); + } + + const [uri, search] = href.split('?'); + const urlParams = new URLSearchParams(search); + const embed = urlParams.get('embed'); + + if (embed) { + return ; + } + + const webLink = formatLbryUrlForWeb(uri); + // using Link after formatLbryUrl to handle "/" vs "#/" + // for web and desktop scenarios respectively + + return ( + { + e.stopPropagation(); + }} + > + {children} + + ); +}; + +// Use github sanitation schema +const schema = { ...defaultSchema }; + +// Extend sanitation schema to support lbry protocol +schema.protocols.href.push('lbry'); +schema.attributes.a.push('embed'); + +const REPLACE_REGEX = /(