"Fixed NSFW content showing on filePage"
NSFW content is obscured on show page and gives an overlay to inform the user. Fixes #286 Added one additional format(epub) in lbry.js.
This commit is contained in:
parent
6aad233f66
commit
e3bbb6fcef
12 changed files with 89 additions and 45 deletions
|
@ -1,10 +1,10 @@
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import lbry from "lbry.js";
|
|
||||||
import lbryuri from "lbryuri.js";
|
import lbryuri from "lbryuri.js";
|
||||||
import Link from "component/link";
|
import Link from "component/link";
|
||||||
import { Thumbnail, TruncatedText, Icon } from "component/common";
|
import { TruncatedText, Icon } from "component/common";
|
||||||
import FilePrice from "component/filePrice";
|
import FilePrice from "component/filePrice";
|
||||||
import UriIndicator from "component/uriIndicator";
|
import UriIndicator from "component/uriIndicator";
|
||||||
|
import NsfwOverlay from "component/nsfwOverlay";
|
||||||
|
|
||||||
class FileCard extends React.PureComponent {
|
class FileCard extends React.PureComponent {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
|
@ -97,22 +97,8 @@ class FileCard extends React.PureComponent {
|
||||||
<TruncatedText lines={2}>{description}</TruncatedText>
|
<TruncatedText lines={2}>{description}</TruncatedText>
|
||||||
</div>
|
</div>
|
||||||
</Link>
|
</Link>
|
||||||
{obscureNsfw &&
|
|
||||||
this.state.hovered &&
|
|
||||||
<div className="card-overlay">
|
|
||||||
<p>
|
|
||||||
{__(
|
|
||||||
"This content is Not Safe For Work. To view adult content, please change your"
|
|
||||||
)}
|
|
||||||
{" "}
|
|
||||||
<Link
|
|
||||||
className="button-text"
|
|
||||||
onClick={() => navigate("settings")}
|
|
||||||
label={__("Settings")}
|
|
||||||
/>.
|
|
||||||
</p>
|
|
||||||
</div>}
|
|
||||||
</div>
|
</div>
|
||||||
|
{obscureNsfw && this.state.hovered && <NsfwOverlay />}
|
||||||
</section>
|
</section>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,10 +2,9 @@ import React from "react";
|
||||||
import lbry from "lbry.js";
|
import lbry from "lbry.js";
|
||||||
import lbryuri from "lbryuri.js";
|
import lbryuri from "lbryuri.js";
|
||||||
import Link from "component/link";
|
import Link from "component/link";
|
||||||
import FileActions from "component/fileActions";
|
import { TruncatedText } from "component/common.js";
|
||||||
import { Thumbnail, TruncatedText } from "component/common.js";
|
|
||||||
import FilePrice from "component/filePrice";
|
import FilePrice from "component/filePrice";
|
||||||
import UriIndicator from "component/uriIndicator";
|
import NsfwOverlay from "component/nsfwOverlay";
|
||||||
|
|
||||||
class FileTile extends React.PureComponent {
|
class FileTile extends React.PureComponent {
|
||||||
static SHOW_EMPTY_PUBLISH = "publish";
|
static SHOW_EMPTY_PUBLISH = "publish";
|
||||||
|
@ -124,20 +123,7 @@ class FileTile extends React.PureComponent {
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Link>
|
</Link>
|
||||||
{this.state.showNsfwHelp &&
|
{this.state.showNsfwHelp && <NsfwOverlay />}
|
||||||
<div className="card-overlay">
|
|
||||||
<p>
|
|
||||||
{__(
|
|
||||||
"This content is Not Safe For Work. To view adult content, please change your"
|
|
||||||
)}
|
|
||||||
{" "}
|
|
||||||
<Link
|
|
||||||
className="button-text"
|
|
||||||
onClick={() => navigate("/settings")}
|
|
||||||
label={__("Settings")}
|
|
||||||
/>.
|
|
||||||
</p>
|
|
||||||
</div>}
|
|
||||||
</section>
|
</section>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
10
ui/js/component/nsfwOverlay/index.js
Normal file
10
ui/js/component/nsfwOverlay/index.js
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
import React from "react";
|
||||||
|
import { connect } from "react-redux";
|
||||||
|
import { doNavigate } from "actions/app";
|
||||||
|
import NsfwOverlay from "./view";
|
||||||
|
|
||||||
|
const perform = dispatch => ({
|
||||||
|
navigateSettings: () => dispatch(doNavigate("/settings")),
|
||||||
|
});
|
||||||
|
|
||||||
|
export default connect(null, perform)(NsfwOverlay);
|
22
ui/js/component/nsfwOverlay/view.jsx
Normal file
22
ui/js/component/nsfwOverlay/view.jsx
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
import React from "react";
|
||||||
|
import Link from "component/link";
|
||||||
|
|
||||||
|
const NsfwOverlay = props => {
|
||||||
|
return (
|
||||||
|
<div className="card-overlay">
|
||||||
|
<p>
|
||||||
|
{__(
|
||||||
|
"This content is Not Safe For Work. To view adult content, please change your"
|
||||||
|
)}{" "}
|
||||||
|
{" "}{" "}
|
||||||
|
<Link
|
||||||
|
className="button-text"
|
||||||
|
onClick={() => props.navigateSettings()}
|
||||||
|
label={__("Settings")}
|
||||||
|
/>.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default NsfwOverlay;
|
|
@ -1,6 +1,7 @@
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { connect } from "react-redux";
|
import { connect } from "react-redux";
|
||||||
import { doCloseModal } from "actions/app";
|
import { doCloseModal } from "actions/app";
|
||||||
|
import { doNavigate } from "actions/app";
|
||||||
import { selectCurrentModal } from "selectors/app";
|
import { selectCurrentModal } from "selectors/app";
|
||||||
import { doPurchaseUri, doLoadVideo } from "actions/content";
|
import { doPurchaseUri, doLoadVideo } from "actions/content";
|
||||||
import {
|
import {
|
||||||
|
@ -13,6 +14,7 @@ import {
|
||||||
makeSelectDownloadingForUri,
|
makeSelectDownloadingForUri,
|
||||||
} from "selectors/file_info";
|
} from "selectors/file_info";
|
||||||
import { makeSelectCostInfoForUri } from "selectors/cost_info";
|
import { makeSelectCostInfoForUri } from "selectors/cost_info";
|
||||||
|
import { selectObscureNsfw } from "selectors/app";
|
||||||
import Video from "./view";
|
import Video from "./view";
|
||||||
|
|
||||||
const makeSelect = () => {
|
const makeSelect = () => {
|
||||||
|
@ -27,6 +29,7 @@ const makeSelect = () => {
|
||||||
costInfo: selectCostInfo(state, props),
|
costInfo: selectCostInfo(state, props),
|
||||||
fileInfo: selectFileInfo(state, props),
|
fileInfo: selectFileInfo(state, props),
|
||||||
metadata: selectMetadata(state, props),
|
metadata: selectMetadata(state, props),
|
||||||
|
obscureNsfw: selectObscureNsfw(state),
|
||||||
modal: selectCurrentModal(state),
|
modal: selectCurrentModal(state),
|
||||||
isLoading: selectIsLoading(state, props),
|
isLoading: selectIsLoading(state, props),
|
||||||
isDownloading: selectIsDownloading(state, props),
|
isDownloading: selectIsDownloading(state, props),
|
||||||
|
|
|
@ -3,11 +3,15 @@ import lbry from "lbry";
|
||||||
import VideoPlayer from "./internal/player";
|
import VideoPlayer from "./internal/player";
|
||||||
import VideoPlayButton from "./internal/play-button";
|
import VideoPlayButton from "./internal/play-button";
|
||||||
import LoadingScreen from "./internal/loading-screen";
|
import LoadingScreen from "./internal/loading-screen";
|
||||||
|
import NsfwOverlay from "component/nsfwOverlay";
|
||||||
|
|
||||||
class Video extends React.PureComponent {
|
class Video extends React.PureComponent {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
this.state = { isPlaying: false };
|
this.state = {
|
||||||
|
isPlaying: false,
|
||||||
|
showNsfwHelp: false,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
startPlaying() {
|
startPlaying() {
|
||||||
|
@ -16,6 +20,26 @@ class Video extends React.PureComponent {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
handleMouseOver() {
|
||||||
|
if (
|
||||||
|
this.props.obscureNsfw &&
|
||||||
|
this.props.metadata &&
|
||||||
|
this.props.metadata.nsfw
|
||||||
|
) {
|
||||||
|
this.setState({
|
||||||
|
showNsfwHelp: true,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
handleMouseOut() {
|
||||||
|
if (this.state.showNsfwHelp) {
|
||||||
|
this.setState({
|
||||||
|
showNsfwHelp: false,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const {
|
const {
|
||||||
metadata,
|
metadata,
|
||||||
|
@ -27,6 +51,7 @@ class Video extends React.PureComponent {
|
||||||
const { isPlaying = false } = this.state;
|
const { isPlaying = false } = this.state;
|
||||||
|
|
||||||
const isReadyToPlay = fileInfo && fileInfo.written_bytes > 0;
|
const isReadyToPlay = fileInfo && fileInfo.written_bytes > 0;
|
||||||
|
const obscureNsfw = this.props.obscureNsfw && metadata && metadata.nsfw;
|
||||||
const mediaType = lbry.getMediaType(
|
const mediaType = lbry.getMediaType(
|
||||||
contentType,
|
contentType,
|
||||||
fileInfo && fileInfo.file_name
|
fileInfo && fileInfo.file_name
|
||||||
|
@ -47,6 +72,7 @@ class Video extends React.PureComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
let klasses = [];
|
let klasses = [];
|
||||||
|
klasses.push(obscureNsfw ? "video--obscured " : "");
|
||||||
if (isLoading || isDownloading) klasses.push("video-embedded", "video");
|
if (isLoading || isDownloading) klasses.push("video-embedded", "video");
|
||||||
if (mediaType === "video") {
|
if (mediaType === "video") {
|
||||||
klasses.push("video-embedded", "video");
|
klasses.push("video-embedded", "video");
|
||||||
|
@ -59,7 +85,11 @@ class Video extends React.PureComponent {
|
||||||
const poster = metadata.thumbnail;
|
const poster = metadata.thumbnail;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={klasses.join(" ")}>
|
<div
|
||||||
|
className={klasses.join(" ")}
|
||||||
|
onMouseEnter={this.handleMouseOver.bind(this)}
|
||||||
|
onMouseLeave={this.handleMouseOut.bind(this)}
|
||||||
|
>
|
||||||
{isPlaying &&
|
{isPlaying &&
|
||||||
(!isReadyToPlay
|
(!isReadyToPlay
|
||||||
? <LoadingScreen status={loadStatusMessage} />
|
? <LoadingScreen status={loadStatusMessage} />
|
||||||
|
@ -81,6 +111,7 @@ class Video extends React.PureComponent {
|
||||||
mediaType={mediaType}
|
mediaType={mediaType}
|
||||||
/>
|
/>
|
||||||
</div>}
|
</div>}
|
||||||
|
{this.state.showNsfwHelp && <NsfwOverlay />}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -323,7 +323,9 @@ lbry.getMediaType = function(contentType, fileName) {
|
||||||
return "video";
|
return "video";
|
||||||
} else if (/^mp3|m4a|aac|wav|flac|ogg|opus$/i.test(ext)) {
|
} else if (/^mp3|m4a|aac|wav|flac|ogg|opus$/i.test(ext)) {
|
||||||
return "audio";
|
return "audio";
|
||||||
} else if (/^html|htm|xml|pdf|odf|doc|docx|md|markdown|txt|org$/i.test(ext)) {
|
} else if (
|
||||||
|
/^html|htm|xml|pdf|odf|doc|docx|md|markdown|txt|epub|org$/i.test(ext)
|
||||||
|
) {
|
||||||
return "document";
|
return "document";
|
||||||
} else {
|
} else {
|
||||||
return "unknown";
|
return "unknown";
|
||||||
|
|
|
@ -10,6 +10,7 @@ import {
|
||||||
makeSelectMetadataForUri,
|
makeSelectMetadataForUri,
|
||||||
} from "selectors/claims";
|
} from "selectors/claims";
|
||||||
import { makeSelectCostInfoForUri } from "selectors/cost_info";
|
import { makeSelectCostInfoForUri } from "selectors/cost_info";
|
||||||
|
import { selectObscureNsfw } from "selectors/app";
|
||||||
import FilePage from "./view";
|
import FilePage from "./view";
|
||||||
|
|
||||||
const makeSelect = () => {
|
const makeSelect = () => {
|
||||||
|
@ -24,6 +25,7 @@ const makeSelect = () => {
|
||||||
contentType: selectContentType(state, props),
|
contentType: selectContentType(state, props),
|
||||||
costInfo: selectCostInfo(state, props),
|
costInfo: selectCostInfo(state, props),
|
||||||
metadata: selectMetadata(state, props),
|
metadata: selectMetadata(state, props),
|
||||||
|
obscureNsfw: selectObscureNsfw(state),
|
||||||
fileInfo: selectFileInfo(state, props),
|
fileInfo: selectFileInfo(state, props),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -81,6 +81,7 @@ class FilePage extends React.PureComponent {
|
||||||
const uriIndicator = <UriIndicator uri={uri} />;
|
const uriIndicator = <UriIndicator uri={uri} />;
|
||||||
const mediaType = lbry.getMediaType(contentType);
|
const mediaType = lbry.getMediaType(contentType);
|
||||||
const player = require("render-media");
|
const player = require("render-media");
|
||||||
|
const obscureNsfw = this.props.obscureNsfw && metadata && metadata.nsfw;
|
||||||
const isPlayable =
|
const isPlayable =
|
||||||
Object.values(player.mime).indexOf(contentType) !== -1 ||
|
Object.values(player.mime).indexOf(contentType) !== -1 ||
|
||||||
mediaType === "audio";
|
mediaType === "audio";
|
||||||
|
@ -94,7 +95,7 @@ class FilePage extends React.PureComponent {
|
||||||
? <Thumbnail src={metadata.thumbnail} />
|
? <Thumbnail src={metadata.thumbnail} />
|
||||||
: <Thumbnail />}
|
: <Thumbnail />}
|
||||||
</section>
|
</section>
|
||||||
<section className="card">
|
<section className={"card " + (obscureNsfw ? "card--obscured " : "")}>
|
||||||
<div className="card__inner">
|
<div className="card__inner">
|
||||||
<div className="card__title-identity">
|
<div className="card__title-identity">
|
||||||
{!fileInfo || fileInfo.written_bytes <= 0
|
{!fileInfo || fileInfo.written_bytes <= 0
|
||||||
|
|
|
@ -39,7 +39,7 @@ $box-shadow-focus: 2px 4px 4px 0 rgba(0,0,0,.14),2px 5px 3px -2px rgba(0,0,0,.2)
|
||||||
|
|
||||||
$transition-standard: .225s ease;
|
$transition-standard: .225s ease;
|
||||||
|
|
||||||
$blur-intensity: 8px;
|
$blur-intensity-nsfw: 20px;
|
||||||
|
|
||||||
@mixin clearfix()
|
@mixin clearfix()
|
||||||
{
|
{
|
||||||
|
|
|
@ -17,11 +17,7 @@ $padding-card-horizontal: $spacing-vertical * 2/3;
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
.card--obscured .card__inner {
|
.card--obscured .card__inner {
|
||||||
-webkit-filter: blur($blur-intensity);
|
filter: blur($blur-intensity-nsfw);
|
||||||
-moz-filter: blur($blur-intensity);
|
|
||||||
-o-filter: blur($blur-intensity);
|
|
||||||
-ms-filter: blur($blur-intensity);
|
|
||||||
filter: blur($blur-intensity);
|
|
||||||
}
|
}
|
||||||
.card__title-primary {
|
.card__title-primary {
|
||||||
padding: 0 $padding-card-horizontal;
|
padding: 0 $padding-card-horizontal;
|
||||||
|
|
|
@ -33,6 +33,11 @@ video {
|
||||||
transform: translateY(-50%);
|
transform: translateY(-50%);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.video--obscured .video__cover
|
||||||
|
{
|
||||||
|
position: relative;
|
||||||
|
filter: blur($blur-intensity-nsfw);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
.video__loading-screen {
|
.video__loading-screen {
|
||||||
|
|
Loading…
Reference in a new issue