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 ( - -
-
+
+
{'Photo
@@ -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({

Run on Startup

Download Directory

Where would you like the files you download from LBRY to be saved?
- +

Bandwidth Limits

@@ -97,7 +93,7 @@ var SettingsPage = React.createClass({
@@ -107,17 +103,26 @@ var SettingsPage = React.createClass({
+
+

Content

+
+ +
NSFW content may include nudity, intense sexuality, profanity, or other adult content.
+
+

Share Diagnostic Data

); } -}); \ 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 {