Disable video previews in Comments and Post if author is below a certain level.

This commit is contained in:
infinite-persistence 2021-03-09 17:33:42 +08:00 committed by Sean Yesmunt
parent 9192828505
commit 0d850742f5
9 changed files with 61 additions and 15 deletions

View file

@ -30,6 +30,7 @@ YRBL_SAD_IMG_URL=https://cdn.lbryplayer.xyz/api/v3/streams/free/yrbl-sad/c2d9649
ENABLE_COMMENT_REACTIONS=true ENABLE_COMMENT_REACTIONS=true
ENABLE_FILE_REACTIONS=false ENABLE_FILE_REACTIONS=false
ENABLE_CREATOR_REACTIONS=false ENABLE_CREATOR_REACTIONS=false
CHANNEL_STAKED_LEVEL_VIDEO_COMMENTS=4
# OG # OG
OG_TITLE_SUFFIX=| lbry.tv OG_TITLE_SUFFIX=| lbry.tv

View file

@ -35,6 +35,7 @@ const config = {
ENABLE_COMMENT_REACTIONS: process.env.ENABLE_COMMENT_REACTIONS === 'true', ENABLE_COMMENT_REACTIONS: process.env.ENABLE_COMMENT_REACTIONS === 'true',
ENABLE_FILE_REACTIONS: process.env.ENABLE_FILE_REACTIONS === 'true', ENABLE_FILE_REACTIONS: process.env.ENABLE_FILE_REACTIONS === 'true',
ENABLE_CREATOR_REACTIONS: process.env.ENABLE_CREATOR_REACTIONS === 'true', ENABLE_CREATOR_REACTIONS: process.env.ENABLE_CREATOR_REACTIONS === 'true',
CHANNEL_STAKED_LEVEL_VIDEO_COMMENTS: process.env.CHANNEL_STAKED_LEVEL_VIDEO_COMMENTS,
SIMPLE_SITE: process.env.SIMPLE_SITE === 'true', SIMPLE_SITE: process.env.SIMPLE_SITE === 'true',
SHOW_ADS: process.env.SHOW_ADS === 'true', SHOW_ADS: process.env.SHOW_ADS === 'true',
PINNED_URI_1: process.env.PINNED_URI_1, PINNED_URI_1: process.env.PINNED_URI_1,

View file

@ -1,5 +1,5 @@
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { makeSelectThumbnailForUri, selectMyChannelClaims } from 'lbry-redux'; import { makeSelectStakedLevelForChannelUri, makeSelectThumbnailForUri, selectMyChannelClaims } from 'lbry-redux';
import { doCommentUpdate } from 'redux/actions/comments'; import { doCommentUpdate } from 'redux/actions/comments';
import { makeSelectChannelIsMuted } from 'redux/selectors/blocked'; import { makeSelectChannelIsMuted } from 'redux/selectors/blocked';
import { doToast } from 'redux/actions/notifications'; import { doToast } from 'redux/actions/notifications';
@ -18,6 +18,7 @@ const select = (state, props) => ({
activeChannelClaim: selectActiveChannelClaim(state), activeChannelClaim: selectActiveChannelClaim(state),
myChannels: selectMyChannelClaims(state), myChannels: selectMyChannelClaims(state),
playingUri: selectPlayingUri(state), playingUri: selectPlayingUri(state),
stakedLevel: makeSelectStakedLevelForChannelUri(props.authorUri)(state),
}); });
const perform = (dispatch) => ({ const perform = (dispatch) => ({

View file

@ -49,6 +49,7 @@ type Props = {
commentIdentityChannel: any, commentIdentityChannel: any,
activeChannelClaim: ?ChannelClaim, activeChannelClaim: ?ChannelClaim,
playingUri: ?PlayingUri, playingUri: ?PlayingUri,
stakedLevel: number,
}; };
const LENGTH_TO_COLLAPSE = 300; const LENGTH_TO_COLLAPSE = 300;
@ -75,6 +76,7 @@ function Comment(props: Props) {
isPinned, isPinned,
othersReacts, othersReacts,
playingUri, playingUri,
stakedLevel,
} = props; } = props;
const { const {
push, push,
@ -254,10 +256,20 @@ function Comment(props: Props) {
</div> </div>
) : editedMessage.length >= LENGTH_TO_COLLAPSE ? ( ) : editedMessage.length >= LENGTH_TO_COLLAPSE ? (
<Expandable> <Expandable>
<MarkdownPreview content={message} promptLinks parentCommentId={commentId} /> <MarkdownPreview
content={message}
promptLinks
parentCommentId={commentId}
stakedLevel={stakedLevel}
/>
</Expandable> </Expandable>
) : ( ) : (
<MarkdownPreview content={message} promptLinks parentCommentId={commentId} /> <MarkdownPreview
content={message}
promptLinks
parentCommentId={commentId}
stakedLevel={stakedLevel}
/>
)} )}
</div> </div>

View file

@ -13,6 +13,7 @@ import defaultSchema from 'hast-util-sanitize/lib/github.json';
import { formatedLinks, inlineLinks } from 'util/remark-lbry'; import { formatedLinks, inlineLinks } from 'util/remark-lbry';
import { formattedTimestamp, inlineTimestamp } from 'util/remark-timestamp'; import { formattedTimestamp, inlineTimestamp } from 'util/remark-timestamp';
import ZoomableImage from 'component/zoomableImage'; import ZoomableImage from 'component/zoomableImage';
import { CHANNEL_STAKED_LEVEL_VIDEO_COMMENTS } from 'config';
type SimpleTextProps = { type SimpleTextProps = {
children?: React.Node, children?: React.Node,
@ -32,6 +33,7 @@ type MarkdownProps = {
className?: string, className?: string,
parentCommentId?: string, parentCommentId?: string,
isMarkdownPost?: boolean, isMarkdownPost?: boolean,
stakedLevel?: number,
}; };
// **************************************************************************** // ****************************************************************************
@ -93,7 +95,7 @@ const REPLACE_REGEX = /(<iframe\s+src=["'])(.*?(?=))(["']\s*><\/iframe>)/g;
// **************************************************************************** // ****************************************************************************
const MarkdownPreview = (props: MarkdownProps) => { const MarkdownPreview = (props: MarkdownProps) => {
const { content, strip, simpleLinks, noDataStore, className, parentCommentId, isMarkdownPost } = props; const { content, strip, simpleLinks, noDataStore, className, parentCommentId, isMarkdownPost, stakedLevel } = props;
const strippedContent = content const strippedContent = content
? content.replace(REPLACE_REGEX, (iframeHtml, y, iframeSrc) => { ? content.replace(REPLACE_REGEX, (iframeHtml, y, iframeSrc) => {
// Let the browser try to create an iframe to see if the markup is valid // Let the browser try to create an iframe to see if the markup is valid
@ -119,12 +121,13 @@ const MarkdownPreview = (props: MarkdownProps) => {
remarkReactComponents: { remarkReactComponents: {
a: noDataStore a: noDataStore
? SimpleLink ? SimpleLink
: linkProps => ( : (linkProps) => (
<MarkdownLink <MarkdownLink
{...linkProps} {...linkProps}
parentCommentId={parentCommentId} parentCommentId={parentCommentId}
isMarkdownPost={isMarkdownPost} isMarkdownPost={isMarkdownPost}
simpleLinks={simpleLinks} simpleLinks={simpleLinks}
allowPreview={stakedLevel && stakedLevel >= CHANNEL_STAKED_LEVEL_VIDEO_COMMENTS}
/> />
), ),
// Workaraund of remarkOptions.Fragment // Workaraund of remarkOptions.Fragment

View file

@ -6,6 +6,8 @@ import {
makeSelectDownloadPathForUri, makeSelectDownloadPathForUri,
makeSelectStreamingUrlForUri, makeSelectStreamingUrlForUri,
SETTINGS, SETTINGS,
makeSelectStakedLevelForChannelUri,
makeSelectChannelForClaimUri,
} from 'lbry-redux'; } from 'lbry-redux';
import { makeSelectClientSetting } from 'redux/selectors/settings'; import { makeSelectClientSetting } from 'redux/selectors/settings';
import { makeSelectFileRenderModeForUri, makeSelectFileExtensionForUri } from 'redux/selectors/content'; import { makeSelectFileRenderModeForUri, makeSelectFileExtensionForUri } from 'redux/selectors/content';
@ -13,9 +15,11 @@ import FileRender from './view';
const select = (state, props) => { const select = (state, props) => {
const autoplay = props.embedded ? false : makeSelectClientSetting(SETTINGS.AUTOPLAY)(state); const autoplay = props.embedded ? false : makeSelectClientSetting(SETTINGS.AUTOPLAY)(state);
const channelUri = makeSelectChannelForClaimUri(props.uri)(state);
return { return {
currentTheme: makeSelectClientSetting(SETTINGS.THEME)(state), currentTheme: makeSelectClientSetting(SETTINGS.THEME)(state),
claim: makeSelectClaimForUri(props.uri)(state), claim: makeSelectClaimForUri(props.uri)(state),
stakedLevel: makeSelectStakedLevelForChannelUri(channelUri)(state),
thumbnail: makeSelectThumbnailForUri(props.uri)(state), thumbnail: makeSelectThumbnailForUri(props.uri)(state),
contentType: makeSelectContentTypeForUri(props.uri)(state), contentType: makeSelectContentTypeForUri(props.uri)(state),
downloadPath: makeSelectDownloadPathForUri(props.uri)(state), downloadPath: makeSelectDownloadPathForUri(props.uri)(state),

View file

@ -35,6 +35,7 @@ type Props = {
thumbnail: string, thumbnail: string,
desktopPlayStartTime?: number, desktopPlayStartTime?: number,
className?: string, className?: string,
stakedLevel?: number,
}; };
class FileRender extends React.PureComponent<Props> { class FileRender extends React.PureComponent<Props> {
@ -78,6 +79,7 @@ class FileRender extends React.PureComponent<Props> {
uri, uri,
renderMode, renderMode,
desktopPlayStartTime, desktopPlayStartTime,
stakedLevel,
} = this.props; } = this.props;
const source = streamingUrl; const source = streamingUrl;
@ -110,6 +112,7 @@ class FileRender extends React.PureComponent<Props> {
}} }}
renderMode={renderMode} renderMode={renderMode}
theme={currentTheme} theme={currentTheme}
stakedLevel={stakedLevel}
/> />
); );
case RENDER_MODES.DOCX: case RENDER_MODES.DOCX:

View file

@ -1,5 +1,5 @@
// @flow // @flow
import { KNOWN_APP_DOMAINS } from 'config'; import { KNOWN_APP_DOMAINS, SIMPLE_SITE } from 'config';
import * as ICONS from 'constants/icons'; import * as ICONS from 'constants/icons';
import * as React from 'react'; import * as React from 'react';
import { isURIValid } from 'lbry-redux'; import { isURIValid } from 'lbry-redux';
@ -10,6 +10,7 @@ type Props = {
href: string, href: string,
title?: string, title?: string,
embed?: boolean, embed?: boolean,
allowPreview?: boolean,
children: React.Node, children: React.Node,
parentCommentId?: string, parentCommentId?: string,
isMarkdownPost?: boolean, isMarkdownPost?: boolean,
@ -17,7 +18,16 @@ type Props = {
}; };
function MarkdownLink(props: Props) { function MarkdownLink(props: Props) {
const { children, href, title, embed = false, parentCommentId, isMarkdownPost, simpleLinks = false } = props; const {
children,
href,
title,
embed = false,
allowPreview = false,
parentCommentId,
isMarkdownPost,
simpleLinks = false,
} = props;
let decodedUri; let decodedUri;
try { try {
@ -33,6 +43,7 @@ function MarkdownLink(props: Props) {
// Regex for url protocol // Regex for url protocol
const protocolRegex = new RegExp('^(https?|lbry|mailto)+:', 'i'); const protocolRegex = new RegExp('^(https?|lbry|mailto)+:', 'i');
const protocol = href ? protocolRegex.exec(href) : null; const protocol = href ? protocolRegex.exec(href) : null;
const isLbryLink = href.startsWith('lbry://');
let linkUrlObject; let linkUrlObject;
try { try {
@ -62,6 +73,10 @@ function MarkdownLink(props: Props) {
} }
} }
// Return timestamp link if it starts with '?t=' (only possible from remark-timestamp).
// Return plain text if no valid url.
// Return external link if protocol is http or https.
// Return local link if protocol is lbry uri.
if (href.startsWith('?t=')) { if (href.startsWith('?t=')) {
// Video timestamp markers // Video timestamp markers
element = ( element = (
@ -80,10 +95,7 @@ function MarkdownLink(props: Props) {
/> />
); );
} else if (!simpleLinks && ((protocol && protocol[0] === 'lbry:' && isURIValid(decodedUri)) || lbryUrlFromLink)) { } else if (!simpleLinks && ((protocol && protocol[0] === 'lbry:' && isURIValid(decodedUri)) || lbryUrlFromLink)) {
// Return plain text if no valid url element = allowPreview ? (
// Return external link if protocol is http or https
// Return local link if protocol is lbry uri
element = (
<ClaimLink <ClaimLink
uri={lbryUrlFromLink || decodedUri} uri={lbryUrlFromLink || decodedUri}
autoEmbed={embed} autoEmbed={embed}
@ -92,13 +104,21 @@ function MarkdownLink(props: Props) {
> >
{children} {children}
</ClaimLink> </ClaimLink>
) : (
<Button
button="link"
iconRight={isLbryLink ? undefined : ICONS.EXTERNAL}
title={SIMPLE_SITE ? __("This channel isn't staking enough LBRY Credits for link previews.") : children}
label={children}
className="button--external-link"
navigate={isLbryLink ? href : undefined}
href={isLbryLink ? undefined : href}
/>
); );
} else if ( } else if (
simpleLinks || simpleLinks ||
(protocol && (protocol[0] === 'http:' || protocol[0] === 'https:' || protocol[0] === 'mailto:')) (protocol && (protocol[0] === 'http:' || protocol[0] === 'https:' || protocol[0] === 'mailto:'))
) { ) {
const isLbryLink = href.startsWith('lbry://');
element = ( element = (
<Button <Button
button="link" button="link"

View file

@ -15,6 +15,7 @@ type Props = {
stream: string, stream: string,
contentType: string, contentType: string,
}, },
stakedLevel?: number,
}; };
type State = { type State = {
@ -75,11 +76,11 @@ class DocumentViewer extends React.PureComponent<Props, State> {
renderDocument() { renderDocument() {
const { content } = this.state; const { content } = this.state;
const { source, theme, renderMode } = this.props; const { source, theme, renderMode, stakedLevel } = this.props;
const { contentType } = source; const { contentType } = source;
return renderMode === RENDER_MODES.MARKDOWN ? ( return renderMode === RENDER_MODES.MARKDOWN ? (
<MarkdownPreview content={content} isMarkdownPost promptLinks /> <MarkdownPreview content={content} isMarkdownPost promptLinks stakedLevel={stakedLevel} />
) : ( ) : (
<CodeViewer value={content} contentType={contentType} theme={theme} /> <CodeViewer value={content} contentType={contentType} theme={theme} />
); );