Merge remote-tracking branch 'origin/master' into help-version-section

This commit is contained in:
Jeremy Kauffman 2016-08-26 18:11:28 -04:00
commit d46fed313f
12 changed files with 231 additions and 93 deletions

9
dist/img/default-thumb.svg vendored Normal file
View file

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="480" height="288">
<rect fill="#09f911" width="96" height="288"/>
<rect fill="#029d74" width="96" height="288" x="96"/>
<rect fill="#e35bd8" width="96" height="288" x="192"/>
<rect fill="#4156c5" width="96" height="288" x="288"/>
<rect fill="#635688" width="96" height="288" x="384"/>
<text font-size="32" fill="white" font-family="Bitstream Vera Sans" x="388.1" y="269.3">+<tspan font-size="48">C0</tspan></text>
</svg>

After

Width:  |  Height:  |  Size: 507 B

View file

@ -31,7 +31,7 @@ var App = React.createClass({
}
var message = 'The version of LBRY you\'re using is not up to date.\n\n' +
'Choose "OK" to download the latest version."';
'Choose "OK" to download the latest version.';
lbry.getVersionInfo(function(versionInfo) {
if (versionInfo.os_system == 'Darwin') {

View file

@ -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',

View file

@ -36,12 +36,11 @@ var SearchResults = React.createClass({
render: function() {
var rows = [];
this.props.results.forEach(function(result) {
if (!result.value.nsfw) {
console.log(result);
rows.push(
<SearchResultRow key={result.name} name={result.name} title={result.value.title} imgUrl={result.value.thumbnail}
description={result.value.description} cost={result.cost} />
description={result.value.description} cost={result.cost} nsfw={result.value.nsfw} />
);
}
});
return (
<div>{rows}</div>
@ -77,16 +76,27 @@ 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 (
<section className="card">
<div className="row-fluid" style={searchRowStyle}>
<section className={ 'card ' + (obscureNsfw ? 'card-obscured' : '') } onMouseEnter={this.handleMouseOver} onMouseLeave={this.handleMouseOut}>
<div className="row-fluid card-content" style={searchRowStyle}>
<div className="span3">
<img src={this.props.imgUrl} alt={'Photo for ' + (this.props.title || this.props.name)} style={searchRowImgStyle} />
<img src={this.props.imgUrl || '/img/default-thumb.svg'} alt={'Photo for ' + (this.props.title || this.props.name)} style={searchRowImgStyle} />
</div>
<div className="span9">
<span style={searchRowCostStyle}>
@ -101,14 +111,27 @@ var SearchResultRow = React.createClass({
<p style={searchRowDescriptionStyle}>{this.props.description}</p>
</div>
</div>
{
!obscureNsfw || !this.state.isHovered ? null :
<div className='card-overlay'>
<p>
This content is Not Safe For Work.
To view adult content, please change your <Link href="?settings" label="Settings" />.
</p>
</div>
}
</section>
);
}
});
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;
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 <SearchResultRow name={this.props.name} title={this.state.title} imgUrl={this.state.metadata.thumbnail}
description={this.state.metadata.description} cost={this.state.amount}
available={this.state.available} />;
return (<div style={featuredContentItemContainerStyle}>
<SearchResultRow name={this.props.name} title={this.state.title} imgUrl={this.state.metadata.thumbnail || '/img/default-thumb.svg'}
description={this.state.metadata.description} cost={this.state.amount} nsfw={this.state.metadata.nsfw}
available={this.state.available} />
</div>);
}
});
@ -160,16 +195,19 @@ var FeaturedContent = React.createClass({
<h3>Featured Content</h3>
<FeaturedContentItem name="what" />
<FeaturedContentItem name="itsadisaster" />
<FeaturedContentItem name="keynesvhayek" />
<FeaturedContentItem name="meetlbry1" />
<FeaturedContentItem name="coloradobridge" />
<FeaturedContentItem name="samhyde2070" />
<FeaturedContentItem name="LendersDen" />
</div>
<div className="span6">
<h3>Community Content <ToolTipLink style={featuredContentLegendStyle} label="What's this?"
tooltip='Community Content is a public space where anyone can share content with the rest of the LBRY community. Bid on the names "one," "two," "three" and "four" to put your content here!' /></h3>
tooltip='Community Content is a public space where anyone can share content with the rest of the LBRY community. Bid on the names "one," "two," "three," "four" and "five" to put your content here!' /></h3>
<FeaturedContentItem name="one" />
<FeaturedContentItem name="two" />
<FeaturedContentItem name="three" />
<FeaturedContentItem name="four" />
<FeaturedContentItem name="five" />
</div>
</div>
);
@ -182,17 +220,25 @@ var DiscoverPage = React.createClass({
componentDidUpdate: function() {
if (this.props.query != this.state.query)
{
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 +250,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({

View file

@ -64,6 +64,7 @@ var HelpPage = React.createClass({
: <p>Your copy of LBRY is up to date.</p>
}
<table className="table-standard">
<tbody>
<tr>
<th>lbrynet (data)</th>
<td>{ver.lbrynet_version}</td>
@ -76,6 +77,7 @@ var HelpPage = React.createClass({
<th>Platform</th>
<td>{platform}</td>
</tr>
</tbody>
</table>
</section>
}

View file

@ -57,6 +57,7 @@ var moreButtonColumnStyle = {
},
artStyle = {
maxHeight: '100px',
maxWidth: '100%',
display: 'block',
marginLeft: 'auto',
marginRight: 'auto',
@ -97,7 +98,7 @@ var MyFilesRow = React.createClass({
<section className="card">
<div className="row-fluid">
<div className="span3">
{this.props.imgUrl ? <img src={this.props.imgUrl} alt={'Photo for ' + this.props.title} style={artStyle} /> : null}
<img src={this.props.imgUrl || '/img/default-thumb.svg'} alt={'Photo for ' + this.props.title} style={artStyle} />
</div>
<div className="span8">
<h3>{this.props.pending ? this.props.title : <a href={'/?show=' + this.props.lbryUri}>{this.props.title}</a>}</h3>

View file

@ -41,7 +41,16 @@ var PublishPage = React.createClass({
return;
}
var metadata = {ver: '0.0.2'};
if (this.state.nameIsMine) {
// Pre-populate with existing metadata
var metadata = Object.assign({}, this.state.claimMetadata);
if (this.refs.file.getValue() !== '') {
delete metadata.sources;
}
} else {
var metadata = {};
}
metadata['ver'] = '0.0.2';
for (let metaField of ['title', 'author', 'description', 'thumbnail', 'license', 'license_url', 'language', 'nsfw']) {
var value = this.refs['meta_' + metaField].getValue();
if (value !== '') {
@ -71,9 +80,7 @@ var PublishPage = React.createClass({
metadata: metadata,
};
if (this.refs.file.getValue() === '') {
publishArgs.metadata.sources = this.state.claimMetadata.sources;
} else {
if (this.refs.file.getValue() !== '') {
publishArgs.file_path = this._tempFilePath;
}

View file

@ -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({
<section className="card">
<h3>Run on Startup</h3>
<label style={settingsCheckBoxOptionStyles}>
<input type="checkbox" onChange={this.onRunOnStartChange} defaultChecked={this.state.settings.run_on_startup} /> Run LBRY automatically when I start my computer
<input type="checkbox" onChange={this.onRunOnStartChange} defaultChecked={this.state.daemonSettings.run_on_startup} /> Run LBRY automatically when I start my computer
</label>
</section>
<section className="card">
<h3>Download Directory</h3>
<div className="help">Where would you like the files you download from LBRY to be saved?</div>
<input style={downloadDirectoryFieldStyles} type="text" name="download_directory" defaultValue={this.state.settings.download_directory} onChange={this.onDownloadDirChange}/>
<input style={downloadDirectoryFieldStyles} type="text" name="download_directory" defaultValue={this.state.daemonSettings.download_directory} onChange={this.onDownloadDirChange}/>
</section>
<section className="card">
<h3>Bandwidth Limits</h3>
@ -97,7 +93,7 @@ var SettingsPage = React.createClass({
</label>
<label style={settingsRadioOptionStyles}>
<input type="radio" name="max_upload_pref" onChange={this.onMaxUploadPrefChange.bind(this, true)} defaultChecked={this.state.isMaxUpload}/> { this.state.isMaxUpload ? 'Up to' : 'Choose limit...' }
<span className={ this.state.isMaxUpload ? '' : 'hidden'}> <input type="number" min="0" step=".5" defaultValue={this.state.settings.max_upload} style={settingsNumberFieldStyles} onChange={this.onMaxUploadFieldChange}/> MB/s</span>
<span className={ this.state.isMaxUpload ? '' : 'hidden'}> <input type="number" min="0" step=".5" defaultValue={this.state.daemonSettings.max_upload} style={settingsNumberFieldStyles} onChange={this.onMaxUploadFieldChange}/> MB/s</span>
</label>
</div>
<div className="form-row">
@ -107,14 +103,26 @@ var SettingsPage = React.createClass({
</label>
<label style={settingsRadioOptionStyles}>
<input type="radio" name="max_download_pref" onChange={this.onMaxDownloadPrefChange.bind(this, true)} defaultChecked={this.state.isMaxDownload}/> { this.state.isMaxDownload ? 'Up to' : 'Choose limit...' }
<span className={ this.state.isMaxDownload ? '' : 'hidden'}> <input type="number" min="0" step=".5" defaultValue={this.state.settings.max_download} style={settingsNumberFieldStyles} onChange={this.onMaxDownloadFieldChange}/> MB/s</span>
<span className={ this.state.isMaxDownload ? '' : 'hidden'}> <input type="number" min="0" step=".5" defaultValue={this.state.daemonSettings.max_download} style={settingsNumberFieldStyles} onChange={this.onMaxDownloadFieldChange}/> MB/s</span>
</label>
</div>
</section>
<section className="card">
<h3>Content</h3>
<div className="form-row">
<label style={settingsCheckBoxOptionStyles}>
<input type="checkbox" onChange={this.onShowNsfwChange} defaultChecked={this.state.showNsfw} /> Show NSFW Content
</label>
<div className="help">
NSFW content may include nudity, intense sexuality, profanity, or other adult content.
By displaying NSFW content, you are affirming you are of legal age to view mature content in your country or jurisdiction.
</div>
</div>
</section>
<section className="card">
<h3>Share Diagnostic Data</h3>
<label style={settingsCheckBoxOptionStyles}>
<input type="checkbox" onChange={this.onShareDataChange} defaultChecked={this.state.settings.upload_log} /> Help make LBRY better by contributing diagnostic data about my usage
<input type="checkbox" onChange={this.onShareDataChange} defaultChecked={this.state.daemonSettings.upload_log} /> Help make LBRY better by contributing diagnostic data about my usage
</label>
</section>
</main>

View file

@ -12,6 +12,7 @@ var FormatItem = React.createClass({
claimInfo: React.PropTypes.object,
amount: React.PropTypes.number,
name: React.PropTypes.string,
available: React.PropTypes.bool,
},
render: function() {
@ -24,12 +25,13 @@ var FormatItem = React.createClass({
var license = claimInfo.license;
var fileContentType = claimInfo['content-type'];
var available = this.props.available;
var amount = this.props.amount || 0.0;
return (
<div className="row-fluid">
<div className="span4">
<img src={thumbnail} alt={'Photo for ' + title} style={formatItemImgStyle} />
<img src={thumbnail || '/img/default-thumb.svg'} alt={'Photo for ' + title} style={formatItemImgStyle} />
</div>
<div className="span8">
<p>{description}</p>
@ -40,7 +42,7 @@ var FormatItem = React.createClass({
<td>Content-Type</td><td>{fileContentType}</td>
</tr>
<tr>
<td>Cost</td><td><CreditAmount amount={amount} isEstimate={true}/></td>
<td>Cost</td><td><CreditAmount amount={amount} isEstimate={!available}/></td>
</tr>
<tr>
<td>Author</td><td>{author}</td>
@ -69,6 +71,7 @@ var FormatsSection = React.createClass({
claimInfo: React.PropTypes.object,
amount: React.PropTypes.number,
name: React.PropTypes.string,
available: React.PropTypes.bool,
},
render: function() {
var name = this.props.name;
@ -90,7 +93,7 @@ var FormatsSection = React.createClass({
{/* In future, anticipate multiple formats, just a guess at what it could look like
// var formats = this.props.claimInfo.formats
// return (<tbody>{formats.map(function(format,i){ */}
<FormatItem claimInfo={format} amount={this.props.amount} />
<FormatItem claimInfo={format} amount={this.props.amount} name={this.props.name} available={this.props.available} />
{/* })}</tbody>); */}
</div>);
}
@ -113,7 +116,8 @@ var DetailPage = React.createClass({
lbry.search(this.props.name, (results) => {
var result = results[0];
this.setState({
amount: result.amount,
amount: result.cost,
available: result.available,
claimInfo: result.value,
searching: false,
});
@ -126,13 +130,14 @@ var DetailPage = React.createClass({
}
var name = this.props.name;
var available = this.state.available;
var claimInfo = this.state.claimInfo;
var amount = this.state.amount;
return (
<main>
<section className="card">
<FormatsSection name={name} claimInfo={claimInfo} amount={amount} />
<FormatsSection name={name} claimInfo={claimInfo} amount={amount} available={available} />
</section>
</main>);
}

View file

@ -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
{

View file

@ -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()
{

View file

@ -13,6 +13,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 {