diff --git a/js/lbry.js b/js/lbry.js
index cca8c6af7..00cbbe626 100644
--- a/js/lbry.js
+++ b/js/lbry.js
@@ -4,6 +4,9 @@ var lbry = {
daemonConnectionString: 'http://localhost:5279/lbryapi',
colors: {
primary: '#155B4A'
+ },
+ defaultClientSettings: {
+ showNsfw: false,
}
};
@@ -90,13 +93,20 @@ lbry.getNewAddress = function(callback) {
lbry.call('get_new_address', {}, callback);
}
-lbry.getSettings = function(callback) {
+lbry.getDaemonSettings = function(callback) {
lbry.call('get_settings', {}, callback);
-};
+}
-lbry.setSettings = function(settings, callback) {
+lbry.setDaemonSettings = function(settings, callback) {
lbry.call('set_settings', settings, callback);
-};
+}
+
+lbry.setDaemonSetting = function(setting, value, callback) {
+ var setSettingsArgs = {};
+ setSettingsArgs[setting] = value;
+ lbry.call('set_settings', setSettingsArgs, callback)
+}
+
lbry.getBalance = function(callback)
{
@@ -208,6 +218,31 @@ lbry.checkNewVersionAvailable = function(callback) {
});
}
+lbry.getClientSettings = function() {
+ var outSettings = {};
+ for (let setting of Object.keys(lbry.defaultClientSettings)) {
+ var localStorageVal = localStorage.getItem('setting_' + setting);
+ outSettings[setting] = (localStorageVal === null ? lbry.defaultClientSettings[setting] : JSON.parse(localStorageVal));
+ }
+ return outSettings;
+}
+
+lbry.getClientSetting = function(setting) {
+ var localStorageVal = localStorage.getItem('setting_' + setting);
+ return (localStorageVal === null ? lbry.defaultClientSettings[setting] : JSON.parse(localStorageVal));
+}
+
+lbry.setClientSettings = function(settings) {
+ for (let setting of Object.keys(settings)) {
+ lbry.setClientSetting(setting, settings[setting]);
+ }
+}
+
+lbry.setClientSetting = function(setting, value) {
+ return localStorage.setItem('setting_' + setting, JSON.stringify(value));
+}
+
+
lbry.reportBug = function(message, callback) {
lbry.call('upload_log', {
name_prefix: 'report',
diff --git a/js/page/discover.js b/js/page/discover.js
index c76b92827..36b3a2e91 100644
--- a/js/page/discover.js
+++ b/js/page/discover.js
@@ -36,12 +36,11 @@ var SearchResults = React.createClass({
render: function() {
var rows = [];
this.props.results.forEach(function(result) {
- if (!result.value.nsfw) {
- rows.push(
-
- );
- }
+ console.log(result);
+ rows.push(
+
+ );
});
return (
{rows}
@@ -77,14 +76,25 @@ var
var SearchResultRow = React.createClass({
getInitialState: function() {
return {
- downloading: false
+ downloading: false,
+ isHovered: false,
}
},
+ handleMouseOver: function() {
+ this.setState({
+ isHovered: true,
+ });
+ },
+ handleMouseOut: function() {
+ this.setState({
+ isHovered: false,
+ });
+ },
render: function() {
+ var obscureNsfw = !lbry.getClientSetting('showNsfw') && this.props.nsfw;
return (
-
-
-
+
+
@@ -101,14 +111,27 @@ var SearchResultRow = React.createClass({
{this.props.description}
+ {
+ !obscureNsfw || !this.state.isHovered ? null :
+
+
+ This content is Not Safe For Work.
+ To view adult content, please change your .
+
+
+ }
);
}
});
-
+var featuredContentItemContainerStyle = {
+ position: 'relative',
+};
var FeaturedContentItem = React.createClass({
+ resolveSearch: false,
+
propTypes: {
name: React.PropTypes.string,
},
@@ -118,31 +141,43 @@ var FeaturedContentItem = React.createClass({
metadata: null,
title: null,
amount: 0.0,
+ overlayShowing: false,
};
},
- componentWillMount: function() {
- lbry.search(this.props.name, (results) => {
+ componentWillUnmount: function() {
+ this.resolveSearch = false;
+ },
+
+ componentDidMount: function() {
+ this.resolveSearch = true;
+
+ lbry.search(this.props.name, function(results) {
var result = results[0];
var metadata = result.value;
- this.setState({
- metadata: metadata,
- amount: result.cost,
- available: result.available,
- title: metadata && metadata.title ? metadata.title : ('lbry://' + this.props.name),
- })
- });
+ if (this.resolveSearch)
+ {
+ this.setState({
+ metadata: metadata,
+ amount: result.cost,
+ available: result.available,
+ title: metadata && metadata.title ? metadata.title : ('lbry://' + this.props.name),
+ });
+ }
+ }.bind(this));
},
render: function() {
- if (this.state.metadata == null) {
- // Still waiting for metadata
+ if (this.state.metadata === null) {
+ // Still waiting for metadata, skip render
return null;
}
- return ;
+ return (
+
+
);
}
});
@@ -182,17 +217,25 @@ var DiscoverPage = React.createClass({
componentDidUpdate: function() {
if (this.props.query != this.state.query)
{
- this.setState({
- searching: true,
- query: this.props.query,
- });
-
- lbry.search(this.props.query, this.searchCallback);
+ this.handleSearchChanged();
}
},
+ handleSearchChanged: function() {
+ this.setState({
+ searching: true,
+ query: this.props.query,
+ });
+
+ lbry.search(this.props.query, this.searchCallback);
+ },
+
componentDidMount: function() {
document.title = "Discover";
+ if (this.props.query !== '') {
+ // Rendering with a query already typed
+ this.handleSearchChanged();
+ }
},
getInitialState: function() {
@@ -204,10 +247,6 @@ var DiscoverPage = React.createClass({
},
searchCallback: function(results) {
- console.log('results:', results)
- console.log('search callback');
- console.log(this.state);
- console.log(this.props);
if (this.state.searching) //could have canceled while results were pending, in which case nothing to do
{
this.setState({
@@ -227,4 +266,4 @@ var DiscoverPage = React.createClass({
);
}
-});
\ No newline at end of file
+});
diff --git a/js/page/settings.js b/js/page/settings.js
index 44fb795c5..8391cc829 100644
--- a/js/page/settings.js
+++ b/js/page/settings.js
@@ -14,64 +14,60 @@ var settingsRadioOptionStyles = {
};
var SettingsPage = React.createClass({
- storeSetting: function(setting, val) {
- var settings = Object.assign({}, this.state.settings);
- settings[setting] = val;
- this.setState({
- 'settings': settings
- });
- lbry.setSettings(settings);
- },
onRunOnStartChange: function (event) {
- this.storeSetting('run_on_startup', event.target.checked);
+ lbry.setDaemonSetting('run_on_startup', event.target.checked);
},
onShareDataChange: function (event) {
- this.storeSetting('upload_log', event.target.checked);
+ lbry.setDaemonSetting('upload_log', event.target.checked);
},
onDownloadDirChange: function(event) {
- this.storeSetting('download_directory', event.target.value);
+ lbry.setDaemonSetting('download_directory', event.target.value);
},
onMaxUploadPrefChange: function(isLimited) {
if (!isLimited) {
- this.storeSetting('max_upload', 0.0);
+ lbry.setDaemonSetting('max_upload', 0.0);
}
this.setState({
isMaxUpload: isLimited
});
},
onMaxUploadFieldChange: function(event) {
- this.storeSetting('max_upload', Number(event.target.value));
+ lbry.setDaemonSetting('max_upload', Number(event.target.value));
},
onMaxDownloadPrefChange: function(isLimited) {
if (!isLimited) {
- this.storeSetting('max_download', 0.0);
+ lbry.setDaemonSetting('max_download', 0.0);
}
this.setState({
isMaxDownload: isLimited
});
},
onMaxDownloadFieldChange: function(event) {
- this.storeSetting('max_download', Number(event.target.value));
+ lbry.setDaemonSetting('max_download', Number(event.target.value));
},
getInitialState: function() {
return {
- settings: null
+ settings: null,
+ showNsfw: lbry.getClientSetting('showNsfw')
}
},
componentDidMount: function() {
document.title = "Settings";
},
componentWillMount: function() {
- lbry.getSettings(function(settings) {
+ lbry.getDaemonSettings(function(settings) {
this.setState({
- settings: settings,
+ daemonSettings: settings,
isMaxUpload: settings.max_upload != 0,
isMaxDownload: settings.max_download != 0
});
}.bind(this));
},
+ onShowNsfwChange: function(event) {
+ lbry.setClientSetting('showNsfw', event.target.checked);
+ },
render: function() {
- if (!this.state.settings) { // If the settings aren't loaded yet, don't render anything.
+ if (!this.state.daemonSettings) {
return null;
}
@@ -80,13 +76,13 @@ var SettingsPage = React.createClass({
+
+ Content
+
+
+
NSFW content may include nudity, intense sexuality, profanity, or other adult content.
+
+
);
}
-});
\ No newline at end of file
+});
diff --git a/scss/_canvas.scss b/scss/_canvas.scss
index 0a9ae7f26..2e8f0cc27 100644
--- a/scss/_canvas.scss
+++ b/scss/_canvas.scss
@@ -157,6 +157,30 @@ $header-icon-size: 1.5em;
box-shadow: $default-box-shadow;
border-radius: 2px;
}
+.card-obscured
+{
+ position: relative;
+}
+.card-obscured .card-content {
+ -webkit-filter: blur($blur-intensity);
+ -moz-filter: blur($blur-intensity);
+ -o-filter: blur($blur-intensity);
+ -ms-filter: blur($blur-intensity);
+ filter: blur($blur-intensity);
+}
+.card-overlay {
+ position: absolute;
+ left: 0px;
+ right: 0px;
+ top: 0px;
+ bottom: 0px;
+ padding: 20px;
+ background-color: rgba(128, 128, 128, 0.8);
+ color: #fff;
+ display: flex;
+ align-items: center;
+ font-weight: 600;
+}
.card-series-submit
{
diff --git a/scss/_global.scss b/scss/_global.scss
index 8bfde1b90..ad5854a36 100644
--- a/scss/_global.scss
+++ b/scss/_global.scss
@@ -21,6 +21,7 @@ $header-height: $spacing-vertical * 2.5;
$default-box-shadow: 0 2px 2px 0 rgba(0,0,0,.14),0 3px 1px -2px rgba(0,0,0,.2),0 1px 5px 0 rgba(0,0,0,.12);
+$blur-intensity: 8px;
@mixin clearfix()
{
diff --git a/scss/_gui.scss b/scss/_gui.scss
index 7f042b433..dc3e19585 100644
--- a/scss/_gui.scss
+++ b/scss/_gui.scss
@@ -17,6 +17,10 @@ section
{
margin-bottom: 0;
}
+ &:only-child {
+ /* If it's an only child, assume it's part of a React layout that will handle the last child condition on its own */
+ margin-bottom: $spacing-vertical;
+ }
}
main h1 {