Merge remote-tracking branch 'upstream/master'

This commit is contained in:
Mayesters 2017-06-21 20:31:12 +02:00
commit 85464fb3cb
40 changed files with 1077 additions and 699 deletions

View file

@ -1,5 +1,5 @@
[bumpversion]
current_version = 0.12.2rc3
current_version = 0.12.2rc5
commit = True
tag = True
parse = (?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)((?P<release>[a-z]+)(?P<candidate>\d+))?
@ -18,5 +18,9 @@ values =
[bumpversion:file:app/package.json]
[bumpversion:file:app/package-lock.json]
[bumpversion:file:ui/package.json]
[bumpversion:file:ui/package-lock.json]

13
.gitignore vendored
View file

@ -1,6 +1,13 @@
node_modules
LBRY-darwin-x64
dist
/node_modules
/LBRY-darwin-x64
/dist
/ui/dist/css/*
/ui/dist/js/*
!/ui/dist/js/mediaelement
/ui/node_modules
/ui/.sass-cache
/app/dist
/app/node_modules

View file

@ -1,20 +1,7 @@
matrix:
include:
- os: osx
# Use generic language for osx
# python 2.7 is broken on osx on travis, so follow we have to specify the installation ourselves
# https://github.com/travis-ci/travis-ci/issues/2312#issuecomment-195620855
language: generic
osx_image: xcode7.3
os: linux
dist: xenial
install:
- wget https://www.python.org/ftp/python/2.7.13/python-2.7.13-macosx10.6.pkg
- sudo installer -pkg python-2.7.13-macosx10.6.pkg -target /
- pip install -U pip
- pip install pyinstaller
- wget https://nodejs.org/dist/v6.9.4/node-v6.9.4.pkg
- sudo installer -pkg node-v6.9.4.pkg -target /
- sudo npm install electron-packager -g
- ./build.sh
- electron-packager --electron-version=1.4.14 --overwrite electron LBRY
- rvm install 2.3.1
- rvm use 2.3.1 && gem install danger --version '~> 4.0' && danger
# - FULL_BUILD=true ./build.sh

View file

@ -9,15 +9,19 @@ Web UI version numbers should always match the corresponding version of LBRY App
## [Unreleased]
### Added
* State is persisted through app close and re-open, resulting in faster opens
* Support webm, ogg, m4v, and a few others
* Translations added to build process
### Changed
* Upgraded to lbry daemon 0.13, including updating API signatures
* Channels resolve much faster
* Resolve is no longer cancelled on navigate
* Updated API and authentication used by rewards process
### Fixed
* Fix help menu force reloading whole app
* Show page updates correctly when navigating from show page to another show page
* URI handling navigates to correct page if app is closed
### Deprecated
*

23
app/package-lock.json generated
View file

@ -1,6 +1,6 @@
{
"name": "LBRY",
"version": "0.12.0",
"version": "0.12.2rc5",
"lockfileVersion": 1,
"dependencies": {
"commander": {
@ -155,7 +155,8 @@
},
"dezalgo": {
"version": "1.0.3",
"bundled": true
"resolved": "https://registry.npmjs.org/dezalgo/-/dezalgo-1.0.3.tgz",
"integrity": "sha1-f3Qt4Gb8dIvI24IFad3c5Jvw1FY="
},
"editor": {
"version": "1.0.0",
@ -525,7 +526,8 @@
},
"normalize-git-url": {
"version": "3.0.2",
"bundled": true
"resolved": "https://registry.npmjs.org/normalize-git-url/-/normalize-git-url-3.0.2.tgz",
"integrity": "sha1-jl8Uvgva7bc+ByADEKpBbCc1D8Q="
},
"normalize-package-data": {
"version": "2.3.8",
@ -549,7 +551,8 @@
},
"npm-install-checks": {
"version": "3.0.0",
"bundled": true
"resolved": "https://registry.npmjs.org/npm-install-checks/-/npm-install-checks-3.0.0.tgz",
"integrity": "sha1-1K7N/VGlPjcjt7L5Oy7ijjB7wNc="
},
"npm-package-arg": {
"version": "4.2.1",
@ -717,7 +720,8 @@
},
"core-util-is": {
"version": "1.0.2",
"bundled": true
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
"integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac="
},
"isarray": {
"version": "1.0.0",
@ -743,7 +747,8 @@
},
"realize-package-specifier": {
"version": "3.0.3",
"bundled": true
"resolved": "https://registry.npmjs.org/realize-package-specifier/-/realize-package-specifier-3.0.3.tgz",
"integrity": "sha1-0N74gpUrjeP2frpekRmWYScfQfQ="
},
"request": {
"version": "2.81.0",
@ -1064,7 +1069,8 @@
"dependencies": {
"unique-slug": {
"version": "2.0.0",
"bundled": true
"resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.0.tgz",
"integrity": "sha1-22Z258fMBimHj/GWCXx4hVrp9Ks="
}
}
},
@ -1420,7 +1426,8 @@
},
"spdx-license-ids": {
"version": "1.2.0",
"bundled": true
"resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-1.2.0.tgz",
"integrity": "sha1-tUndD2Pct0Whfi6joHQC4OMy0eI="
}
}
}

View file

@ -1,6 +1,6 @@
{
"name": "LBRY",
"version": "0.12.2rc3",
"version": "0.12.2rc5",
"main": "main.js",
"description": "LBRY is a fully decentralized, open-source protocol facilitating the discovery, access, and (sometimes) purchase of data.",
"author": {

View file

@ -1 +1 @@
https://github.com/lbryio/lbry/releases/download/v0.13.1rc1/lbrynet-daemon-v0.13.1rc1-OSNAME.zip
https://github.com/lbryio/lbry/releases/download/v0.13.1/lbrynet-daemon-v0.13.1-OSNAME.zip

View file

@ -13,6 +13,13 @@ cd ..
# build ui
cd ui
npm install
# necessary to ensure native Node modules (e.g. keytar) are built against the correct version of Node)
# yes, it needs to be run twice. it fails the first time, not sure why
node_modules\.bin\electron-rebuild
node_modules\.bin\electron-rebuild
node extractLocals.js
node_modules\.bin\node-sass --output dist\css --sourcemap=none scss\
node_modules\.bin\webpack
Copy-Item dist ..\app\ -recurse

View file

@ -45,6 +45,13 @@ if [ "$FULL_BUILD" == "true" ]; then
python "$BUILD_DIR/set_version.py"
fi
libsecret="libsecret-1-dev"
if $LINUX && [ -z "$(dpkg-query --show --showformat='${Status}\n' "$libsecret" 2>/dev/null | grep "install ok installed")" ]; then
# this is needed for keytar, which does secure password/token management
sudo apt-get install --no-install-recommends -y "$libsecret"
fi
[ -d "$ROOT/dist" ] && rm -rf "$ROOT/dist"
mkdir -p "$ROOT/dist"
[ -d "$ROOT/app/dist" ] && rm -rf "$ROOT/app/dist"
@ -61,6 +68,16 @@ npm install
(
cd "$ROOT/ui"
npm install
# necessary to ensure native Node modules (e.g. keytar) are built against the correct version of Node)
# yes, it needs to be run twice. it fails the first time, not sure why
set +e
# DEBUG=electron-rebuild node_modules/.bin/electron-rebuild .
node_modules/.bin/electron-rebuild "$ROOT/ui"
set -e
node_modules/.bin/electron-rebuild "$ROOT/ui"
node extractLocals.js
node_modules/.bin/node-sass --output dist/css --sourcemap=none scss/
node_modules/.bin/webpack
cp -r dist/* "$ROOT/app/dist/"

6
package-lock.json generated
View file

@ -1,12 +1,6 @@
{
"lockfileVersion": 1,
"dependencies": {
"@types/node": {
"version": "7.0.31",
"resolved": "https://registry.npmjs.org/@types/node/-/node-7.0.31.tgz",
"integrity": "sha512-+KrE1LDddn97ip+gXZAnzNQ0pupKH/6tcKwTpo96BDVNpzmhIKGHug0Wd3H0dN4WEqYB1tXYI5m2mZuIZNI8tg==",
"dev": true
},
"7zip-bin": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/7zip-bin/-/7zip-bin-2.1.0.tgz",

7
ui/.gitignore vendored
View file

@ -1,7 +0,0 @@
dist/css/*
dist/js/*
!dist/js/mediaelement
node_modules
.sass-cache
.idea
.DS_Store

View file

@ -1,35 +0,0 @@
language: node_js
node_js: 5
# note that travis still builds PRs so that covers
# other branches
branches:
only:
- master
- development
install:
- rvm install 2.3.1
- npm install
script:
- rvm use 2.3.1 && gem install danger --version '~> 4.0' && danger
- mkdir -p dist/css dist/js
- node_modules/.bin/node-sass scss/all.scss dist/css/all.css
- node_modules/.bin/webpack
- mkdir upload
- cd dist; zip -r ../upload/dist.zip *; cd -
- .travis/echo_sha.sh > upload/data.json
deploy:
provider: s3
access_key_id:
secure: "LjqvQ2MQj8fbumcnIKZC5wa03s3SIAnaLdOrmi7uRcltKIMko20QluRlpXipmYLdDRBg9sZrGgHJzN2QMZBk29XDsPhnFTG5Mhnaf9Ycxac2dy6FABtarNXjEOSH6Vv+Z96W8NkNTly7Okgyg0lXylTi1rLm/JxW14z+SrDPBOVPx5i4Wemd/y4Qx/5Oy611jaZIC4tExL+KWLCfX6tCgg1iE1vnJ22DAjNVlUOmZrLpuhuz/d/4mgkjtZvHAENDPmTItoN6WXxWPspMuaBaSMsj5OuhXqfro8BygbalWfUN7bSMvCqvO+irC6PBeZ4ntq675fS6g9Xb0vzZ6KnNck40PdHXdZRb4wvseqphCL4Xy9cLgUfND3GhxDtStJlqpMeaCg5Yjd9JknQjfCteObLqVeHyjIbWUNsQlyyQcgrVdAQRQiImG+do5qWQXC/02YqxffGJxW/6iQUC/TqC6vNoTKbMSVlccHExt9wnoooZ8D7MT7oN4BCk8bw+G/momH03hGoI0xffcVM9mN+y4z3/BbDX+bn/H5J2cmGWVFZHcOcbY+ehsTmdcqmm+KeePIpKmP6bD7waSUp+czXMgAgfjlWKuzmOFVxvlTo/rLzj5NlIH35RtIKOoVjU8kHzYI1aWAKIHNTHHrUJp4aVYeYGw5y2oejaHnO0ltmVoog="
secret_access_key:
secure: "cAWUhKK+2//JBmV2ohcLs3WTDgDWAMK2RxDrwTqUBEeOdAHMRnEVR++a7fzEL+2dcYi939ZaynNXS5JFJANdjIEKmSWDtvyszyl5MWH0xERZtD0K0xs9bNXS8Un6UrTxhaatmQmqx0KokdUmdH5iqB02BBCKLuwGEjMcUVbadXkp+F8Pd4EXmDPbYHQ2eNo87FzQ7dCQ+GOyQBDNM1Orq+hOKiqJOzB9sDWKShsMTeq5Hyb1oji3cAxTyi6niJ/M/46NokLrPT0xrJLxy+sw5k2106SJXyofJsW1UVOsa5Nxx/suJTv2D0E6d7Ei1XYNnkAbDltu1m9wMq2xqLyoxfdvcC7bxr/NcUZ+DTCKcsM5oa8CiL/y+sOpB8ia0CjO3WBebIUWQAhyswQb312rYsbfQXscb5TnheS+wo4Z1MLse7fSm6jzZRZwqGi27GxC7SFWkSkBwHgaQ8tA7mzsdi6DFmz/KrnwgzqzFRkGg9d0RNXVfUN09p0GJr9drVS1DscVYWGhhD1eDKAIEaEd89u0vKF83zLk73UuNVZA38kkERtLwv7Yr1rRdftL3/gt6fMiW//JQB9sRWV0fDfiWbV2vaki6c/0s6moX00UBuZq21FEpx8puylUOwkXNlQK6TH/bw41ikrRMO156njokYOwLgQaebI/Mb0Cwi32gOU="
bucket: lbry-ui
skip_cleanup: true
upload-dir: ${TRAVIS_BRANCH}
local_dir: upload
on:
all_branches: true

View file

@ -1,7 +0,0 @@
#!/bin/bash
# this is a script instead of a line in the travis.yml
# getting the quoting on this correctly inside the yaml is
# unreadable and difficult
echo '{"sha": "'${TRAVIS_COMMIT}'"}'

View file

@ -1 +0,0 @@
See https://github.com/lbryio/lbry/blob/master/LICENSE

48
ui/extractLocals.js Normal file
View file

@ -0,0 +1,48 @@
var extract = require("i18n-extract");
const fs = require("fs");
var dir = __dirname + "/../app/dist/locales";
var path = dir + "/en.json";
if (!fs.existsSync(dir)) {
fs.mkdirSync(dir);
}
fs.writeFile(path, "{}", "utf8", function(err) {
if (err) {
return console.log(err);
}
var enLocale = require(path);
const keys = extract.extractFromFiles(["js/**/*.{js,jsx}"], {
marker: "__",
});
let reports = [];
reports = reports.concat(extract.findMissing(enLocale, keys));
if (reports.length > 0) {
fs.readFile(path, "utf8", function readFileCallback(err, data) {
if (err) {
console.log(err);
} else {
localeObj = JSON.parse(data);
for (var i = 0; i < reports.length; i++) {
// no need to care for other types than MISSING because starting file will always be empty
if (reports[i].type === "MISSING") {
localeObj[reports[i].key] = reports[i].key;
}
}
var json = JSON.stringify(localeObj, null, "\t"); //convert it back to json-string
fs.writeFile(path, json, "utf8", function callback(err) {
if (err) {
throw err;
}
console.log("Extracted all strings!");
});
}
});
}
});

View file

@ -225,7 +225,6 @@ export function doDaemonReady() {
dispatch({
type: types.DAEMON_READY,
});
dispatch(doChangePath("/discover"));
dispatch(doFetchDaemonSettings());
dispatch(doFileList());
};

View file

@ -33,20 +33,20 @@ export function doUserFetch() {
dispatch({
type: types.USER_FETCH_STARTED,
});
lbryio.setCurrentUser(
user => {
lbryio
.getCurrentUser()
.then(user => {
dispatch({
type: types.USER_FETCH_SUCCESS,
data: { user },
});
},
error => {
})
.catch(error => {
dispatch({
type: types.USER_FETCH_FAILURE,
data: { error },
});
}
);
});
};
}
@ -56,32 +56,37 @@ export function doUserEmailNew(email) {
type: types.USER_EMAIL_NEW_STARTED,
email: email,
});
lbryio.call("user_email", "new", { email }, "post").then(
() => {
lbryio
.call(
"user_email",
"new",
{ email: email, send_verification_email: true },
"post"
)
.catch(error => {
if (error.xhr && error.xhr.status == 409) {
return lbryio.call(
"user_email",
"resend_token",
{ email: email, only_if_expired: true },
"post"
);
}
throw error;
})
.then(() => {
dispatch({
type: types.USER_EMAIL_NEW_SUCCESS,
data: { email },
});
dispatch(doUserFetch());
},
error => {
if (
error.xhr &&
(error.xhr.status == 409 ||
error.message == "This email is already in use")
) {
dispatch({
type: types.USER_EMAIL_NEW_EXISTS,
data: { email },
});
} else {
dispatch({
type: types.USER_EMAIL_NEW_FAILURE,
data: { error: error.message },
});
}
}
);
})
.catch(error => {
dispatch({
type: types.USER_EMAIL_NEW_FAILURE,
data: { error: error.message },
});
});
};
}

View file

@ -1,27 +1,27 @@
import store from 'store.js';
import lbry from './lbry.js';
import store from "store.js";
import lbry from "./lbry.js";
const env = ENV;
const config = require(`./config/${env}`);
const language = lbry.getClientSetting('language')
? lbry.getClientSetting('language')
: 'en';
const i18n = require('y18n')({
directory: 'app/locales',
updateFiles: false,
locale: language
const language = lbry.getClientSetting("language")
? lbry.getClientSetting("language")
: "en";
const i18n = require("y18n")({
directory: "app/locales",
updateFiles: false,
locale: language,
});
const logs = [];
const app = {
env: env,
config: config,
store: store,
i18n: i18n,
logs: logs,
log: function(message) {
console.log(message);
logs.push(message);
}
env: env,
config: config,
store: store,
i18n: i18n,
logs: logs,
log: function(message) {
console.log(message);
logs.push(message);
},
};
window.__ = i18n.__;

View file

@ -4,11 +4,9 @@ import { doFetchCostInfoForUri } from "actions/cost_info";
import {
makeSelectCostInfoForUri,
makeSelectFetchingCostInfoForUri,
} from 'selectors/cost_info'
import {
makeSelectClaimForUri,
} from 'selectors/claims'
import FilePrice from './view'
} from "selectors/cost_info";
import { makeSelectClaimForUri } from "selectors/claims";
import FilePrice from "./view";
const makeSelect = () => {
const selectCostInfoForUri = makeSelectCostInfoForUri();

View file

@ -21,7 +21,7 @@ const RewardLink = props => {
: <Link
button={button ? button : "alt"}
disabled={isPending}
label={isPending ? "Claiming..." : "Claim Reward"}
label={isPending ? __("Claiming...") : __("Claim Reward")}
onClick={() => {
claimReward(reward);
}}

View file

@ -34,7 +34,7 @@ class UserEmailVerify extends React.PureComponent {
>
<FormRow
type="text"
label="Verification Code"
label={__("Verification Code")}
placeholder="a94bXXXXXXXXXXXXXX"
name="code"
value={this.state.code}
@ -46,14 +46,15 @@ class UserEmailVerify extends React.PureComponent {
{/* render help separately so it always shows */}
<div className="form-field__helper">
<p>
Email <Link href="mailto:help@lbry.io" label="help@lbry.io" /> if
you did not receive or are having trouble with your code.
{__("Email")}{" "}
<Link href="mailto:help@lbry.io" label="help@lbry.io" />{" "}
{__("if you did not receive or are having trouble with your code.")}
</p>
</div>
<div className="form-row-submit form-row-submit--with-footer">
<Link
button="primary"
label="Verify"
label={__("Verify")}
disabled={this.state.submitting}
onClick={event => {
this.handleSubmit(event);

View file

@ -23,7 +23,7 @@ const WalletSend = props => {
<div className="card__content">
<FormRow
label={__("Amount")}
postfix="LBC"
postfix={__("LBC")}
step="0.01"
type="number"
placeholder="1.23"

View file

@ -11,18 +11,21 @@ class WelcomeModal extends React.PureComponent {
return !hasClaimed
? <Modal type="custom" isOpen={true} contentLabel="Welcome to LBRY">
<section>
<h3 className="modal__header">Welcome to LBRY.</h3>
<h3 className="modal__header">{__("Welcome to LBRY.")}</h3>
<p>
Using LBRY is like dating a centaur. Totally normal up top, and
{" "}<em>way different</em> underneath.
{__(
"Using LBRY is like dating a centaur. Totally normal up top, and"
)}
{" "}<em>{__("way different")}</em> {__("underneath.")}
</p>
<p>Up top, LBRY is similar to popular media sites.</p>
<p>{__("Up top, LBRY is similar to popular media sites.")}</p>
<p>
Below, LBRY is controlled by users -- you -- via blockchain and
decentralization.
{__(
"Below, LBRY is controlled by users -- you -- via blockchain and decentralization."
)}
</p>
<p>
Thank you for making content freedom possible!
{__("Thank you for making content freedom possible!")}
{" "}{isRewardApproved ? __("Here's a nickel, kid.") : ""}
</p>
<div className="text-center">
@ -31,7 +34,7 @@ class WelcomeModal extends React.PureComponent {
: <Link
button="primary"
onClick={closeModal}
label="Continue"
label={__("Continue")}
/>}
</div>
</section>
@ -40,32 +43,35 @@ class WelcomeModal extends React.PureComponent {
type="alert"
overlayClassName="modal-overlay modal-overlay--clear"
isOpen={true}
contentLabel="Welcome to LBRY"
contentLabel={__("Welcome to LBRY")}
onConfirmed={closeModal}
>
<section>
<h3 className="modal__header">About Your Reward</h3>
<h3 className="modal__header">{__("About Your Reward")}</h3>
<p>
You earned a reward of
{__("You earned a reward of")}
{" "}<CreditAmount amount={reward.reward_amount} label={false} />
{" "}LBRY
credits, or <em>LBC</em>.
{" "}{__("LBRY credits, or")} <em>{__("LBC")}</em>.
</p>
<p>
This reward will show in your Wallet momentarily, probably while
you are reading this message.
{__(
"This reward will show in your Wallet momentarily, probably while you are reading this message."
)}
</p>
<p>
LBC is used to compensate creators, to publish, and to have say in
how the network works.
{__(
"LBC is used to compensate creators, to publish, and to have say in how the network works."
)}
</p>
<p>
No need to understand it all just yet! Try watching or downloading
something next.
{__(
"No need to understand it all just yet! Try watching or downloading something next."
)}
</p>
<p>
Finally, know that LBRY is an early beta and that it earns the
name.
{__(
"Finally, know that LBRY is an early beta and that it earns the name."
)}
</p>
</section>
</Modal>;

View file

@ -1,87 +1,87 @@
const jsonrpc = {};
jsonrpc.call = function(
connectionString,
method,
params,
callback,
errorCallback,
connectFailedCallback,
timeout
connectionString,
method,
params,
callback,
errorCallback,
connectFailedCallback,
timeout
) {
var xhr = new XMLHttpRequest();
if (typeof connectFailedCallback !== 'undefined') {
if (timeout) {
xhr.timeout = timeout;
}
var xhr = new XMLHttpRequest();
if (typeof connectFailedCallback !== "undefined") {
if (timeout) {
xhr.timeout = timeout;
}
xhr.addEventListener('error', function(e) {
connectFailedCallback(e);
});
xhr.addEventListener('timeout', function() {
connectFailedCallback(
new Error(__('XMLHttpRequest connection timed out'))
);
});
}
xhr.addEventListener('load', function() {
var response = JSON.parse(xhr.responseText);
xhr.addEventListener("error", function(e) {
connectFailedCallback(e);
});
xhr.addEventListener("timeout", function() {
connectFailedCallback(
new Error(__("XMLHttpRequest connection timed out"))
);
});
}
xhr.addEventListener("load", function() {
var response = JSON.parse(xhr.responseText);
if (response.error) {
if (errorCallback) {
errorCallback(response.error);
} else {
var errorEvent = new CustomEvent('unhandledError', {
detail: {
connectionString: connectionString,
method: method,
params: params,
code: response.error.code,
message: response.error.message,
data: response.error.data
}
});
document.dispatchEvent(errorEvent);
}
} else if (callback) {
callback(response.result);
}
});
if (response.error) {
if (errorCallback) {
errorCallback(response.error);
} else {
var errorEvent = new CustomEvent("unhandledError", {
detail: {
connectionString: connectionString,
method: method,
params: params,
code: response.error.code,
message: response.error.message,
data: response.error.data,
},
});
document.dispatchEvent(errorEvent);
}
} else if (callback) {
callback(response.result);
}
});
if (connectFailedCallback) {
xhr.addEventListener('error', function(event) {
connectFailedCallback(event);
});
} else {
xhr.addEventListener('error', function(event) {
var errorEvent = new CustomEvent('unhandledError', {
detail: {
connectionString: connectionString,
method: method,
params: params,
code: xhr.status,
message: __('Connection to API server failed')
}
});
document.dispatchEvent(errorEvent);
});
}
if (connectFailedCallback) {
xhr.addEventListener("error", function(event) {
connectFailedCallback(event);
});
} else {
xhr.addEventListener("error", function(event) {
var errorEvent = new CustomEvent("unhandledError", {
detail: {
connectionString: connectionString,
method: method,
params: params,
code: xhr.status,
message: __("Connection to API server failed"),
},
});
document.dispatchEvent(errorEvent);
});
}
const counter = parseInt(sessionStorage.getItem('JSONRPCCounter') || 0);
const counter = parseInt(sessionStorage.getItem("JSONRPCCounter") || 0);
xhr.open('POST', connectionString, true);
xhr.send(
JSON.stringify({
jsonrpc: '2.0',
method: method,
params: params,
id: counter
})
);
xhr.open("POST", connectionString, true);
xhr.send(
JSON.stringify({
jsonrpc: "2.0",
method: method,
params: params,
id: counter,
})
);
sessionStorage.setItem('JSONRPCCounter', counter + 1);
sessionStorage.setItem("JSONRPCCounter", counter + 1);
return xhr;
return xhr;
};
export default jsonrpc;

View file

@ -319,11 +319,11 @@ lbry.getMediaType = function(contentType, fileName) {
}
var ext = fileName.substr(dotIndex + 1);
if (/^mp4|mov|m4v|flv|f4v$/i.test(ext)) {
if (/^mp4|m4v|mov|webm|flv|f4v|ogv$/i.test(ext)) {
return "video";
} else if (/^mp3|m4a|aac|wav|flac|ogg$/i.test(ext)) {
} else if (/^mp3|m4a|aac|wav|flac|ogg|opus$/i.test(ext)) {
return "audio";
} else if (/^html|htm|pdf|odf|doc|docx|md|markdown|txt$/i.test(ext)) {
} else if (/^html|htm|xml|pdf|odf|doc|docx|md|markdown|txt|org$/i.test(ext)) {
return "document";
} else {
return "unknown";
@ -417,7 +417,7 @@ lbry.file_list = function(params = {}) {
return;
}
}
apiCall(
"file_list",
params,
@ -458,7 +458,6 @@ lbry.claim_list_mine = function(params = {}) {
});
};
lbry._resolveXhrs = {};
lbry.resolve = function(params = {}) {
return new Promise((resolve, reject) => {

View file

@ -1,21 +1,21 @@
import { getSession, setSession, setLocal } from "./utils.js";
import lbry from "./lbry.js";
const querystring = require("querystring");
const keytar = require("keytar");
const lbryio = {
_accessToken: getSession("accessToken"),
_authenticationPromise: null,
enabled: true,
_authenticationPromise: null,
_exchangePromise: null,
_exchangeLastFetched: null,
};
const CONNECTION_STRING = process.env.LBRY_APP_API_URL
? process.env.LBRY_APP_API_URL.replace(/\/*$/, "/") // exactly one slash at the end
: "https://api.lbry.io/";
const EXCHANGE_RATE_TIMEOUT = 20 * 60 * 1000;
lbryio._exchangePromise = null;
lbryio._exchangeLastFetched = null;
lbryio.getExchangeRates = function() {
if (
!lbryio._exchangeLastFetched ||
@ -60,7 +60,7 @@ lbryio.call = function(resource, action, params = {}, method = "get") {
if (!response.success) {
if (reject) {
let error = new Error(response.error);
const error = new Error(response.error);
error.xhr = xhr;
reject(error);
} else {
@ -81,54 +81,54 @@ lbryio.call = function(resource, action, params = {}, method = "get") {
}
});
// For social media auth:
//const accessToken = localStorage.getItem('accessToken');
//const fullParams = {...params, ... accessToken ? {access_token: accessToken} : {}};
lbryio
.getAuthToken()
.then(token => {
const fullParams = { auth_token: token, ...params };
// Temp app ID based auth:
const fullParams = { app_id: lbryio.getAccessToken(), ...params };
if (method == "get") {
xhr.open(
"get",
CONNECTION_STRING +
resource +
"/" +
action +
"?" +
querystring.stringify(fullParams),
true
);
xhr.send();
} else if (method == "post") {
xhr.open("post", CONNECTION_STRING + resource + "/" + action, true);
xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
xhr.send(querystring.stringify(fullParams));
} else {
reject(new Error(__("Invalid method")));
}
if (method == "get") {
xhr.open(
"get",
CONNECTION_STRING +
resource +
"/" +
action +
"?" +
querystring.stringify(fullParams),
true
);
xhr.send();
} else if (method == "post") {
xhr.open("post", CONNECTION_STRING + resource + "/" + action, true);
xhr.setRequestHeader(
"Content-type",
"application/x-www-form-urlencoded"
);
xhr.send(querystring.stringify(fullParams));
} else {
reject(new Error(__("Invalid method")));
}
})
.catch(reject);
});
};
lbryio.getAccessToken = () => {
const token = getSession("accessToken");
return token ? token.toString().trim() : token;
lbryio.getAuthToken = () => {
return keytar.getPassword("LBRY", "auth_token").then(token => {
return token ? token.toString().trim() : null;
});
};
lbryio.setAccessToken = token => {
setSession("accessToken", token ? token.toString().trim() : token);
lbryio.setAuthToken = token => {
return keytar.setPassword(
"LBRY",
"auth_token",
token ? token.toString().trim() : null
);
};
lbryio.setCurrentUser = (resolve, reject) => {
lbryio
.call("user", "me")
.then(data => {
resolve(data);
})
.catch(function(err) {
lbryio.setAccessToken(null);
reject(err);
});
lbryio.getCurrentUser = () => {
return lbryio.call("user", "me");
};
lbryio.authenticate = function() {
@ -144,48 +144,69 @@ lbryio.authenticate = function() {
});
});
}
if (lbryio._authenticationPromise === null) {
lbryio._authenticationPromise = new Promise((resolve, reject) => {
lbry
.status()
.then(response => {
let installation_id = response.installation_id;
if (!lbryio.getAccessToken()) {
lbryio
.call(
"user",
"new",
{
language: "en",
app_id: installation_id,
},
"post"
)
.then(function(responseData) {
if (!responseData.id) {
reject(
new Error("Received invalid authentication response.")
);
}
lbryio.setAccessToken(installation_id);
lbryio.setCurrentUser(resolve, reject);
})
.catch(function(error) {
/*
until we have better error code format, assume all errors are duplicate application id
if we're wrong, this will be caught by later attempts to make a valid call
*/
lbryio.setAccessToken(installation_id);
lbryio.setCurrentUser(resolve, reject);
});
} else {
lbryio.setCurrentUser(resolve, reject);
lbryio
.getAuthToken()
.then(token => {
if (!token || token.length > 60) {
return false;
}
// check that token works
return lbryio
.getCurrentUser()
.then(() => {
return true;
})
.catch(() => {
return false;
});
})
.catch(reject);
.then(isTokenValid => {
if (isTokenValid) {
return;
}
let app_id;
return lbry
.status()
.then(status => {
// first try swapping
app_id = status.installation_id;
return lbryio.call(
"user",
"token_swap",
{ auth_token: "", app_id: app_id },
"post"
);
})
.catch(err => {
if (err.xhr.status == 403) {
// cannot swap. either app_id doesn't exist, or app_id already swapped. pretend its the former and create a new user. if we get another error, then its the latter
return lbryio.call(
"user",
"new",
{ auth_token: "", language: "en", app_id: app_id },
"post"
);
}
throw err;
})
.then(response => {
if (!response.auth_token) {
throw new Error(__("auth_token is missing from response"));
}
return lbryio.setAuthToken(response.auth_token);
});
})
.then(lbryio.getCurrentUser())
.then(resolve, reject);
});
}
return lbryio._authenticationPromise;
};

View file

@ -26,125 +26,125 @@ const lbryuri = {};
* - channelName (string, if present): Channel name without @
*/
lbryuri.parse = function(uri, requireProto = false) {
// Break into components. Empty sub-matches are converted to null
const componentsRegex = new RegExp(
'^((?:lbry://)?)' + // protocol
'([^:$#/]*)' + // name (stops at the first separator or end)
'([:$#]?)([^/]*)' + // modifier separator, modifier (stops at the first path separator or end)
'(/?)(.*)' // path separator, path
);
const [proto, name, modSep, modVal, pathSep, path] = componentsRegex
.exec(uri)
.slice(1)
.map(match => match || null);
// Break into components. Empty sub-matches are converted to null
const componentsRegex = new RegExp(
"^((?:lbry://)?)" + // protocol
"([^:$#/]*)" + // name (stops at the first separator or end)
"([:$#]?)([^/]*)" + // modifier separator, modifier (stops at the first path separator or end)
"(/?)(.*)" // path separator, path
);
const [proto, name, modSep, modVal, pathSep, path] = componentsRegex
.exec(uri)
.slice(1)
.map(match => match || null);
let contentName;
let contentName;
// Validate protocol
if (requireProto && !proto) {
throw new Error(__('LBRY URIs must include a protocol prefix (lbry://).'));
}
// Validate protocol
if (requireProto && !proto) {
throw new Error(__("LBRY URIs must include a protocol prefix (lbry://)."));
}
// Validate and process name
if (!name) {
throw new Error(__('URI does not include name.'));
}
// Validate and process name
if (!name) {
throw new Error(__("URI does not include name."));
}
const isChannel = name.startsWith('@');
const channelName = isChannel ? name.slice(1) : name;
const isChannel = name.startsWith("@");
const channelName = isChannel ? name.slice(1) : name;
if (isChannel) {
if (!channelName) {
throw new Error(__('No channel name after @.'));
}
if (isChannel) {
if (!channelName) {
throw new Error(__("No channel name after @."));
}
if (channelName.length < CHANNEL_NAME_MIN_LEN) {
throw new Error(
__(
`Channel names must be at least %s characters.`,
CHANNEL_NAME_MIN_LEN
)
);
}
if (channelName.length < CHANNEL_NAME_MIN_LEN) {
throw new Error(
__(
`Channel names must be at least %s characters.`,
CHANNEL_NAME_MIN_LEN
)
);
}
contentName = path;
}
contentName = path;
}
const nameBadChars = (channelName || name).match(/[^A-Za-z0-9-]/g);
if (nameBadChars) {
throw new Error(
__(
`Invalid character %s in name: %s.`,
nameBadChars.length == 1 ? '' : 's',
nameBadChars.join(', ')
)
);
}
const nameBadChars = (channelName || name).match(/[^A-Za-z0-9-]/g);
if (nameBadChars) {
throw new Error(
__(
`Invalid character %s in name: %s.`,
nameBadChars.length == 1 ? "" : "s",
nameBadChars.join(", ")
)
);
}
// Validate and process modifier (claim ID, bid position or claim sequence)
let claimId, claimSequence, bidPosition;
if (modSep) {
if (!modVal) {
throw new Error(__(`No modifier provided after separator %s.`, modSep));
}
// Validate and process modifier (claim ID, bid position or claim sequence)
let claimId, claimSequence, bidPosition;
if (modSep) {
if (!modVal) {
throw new Error(__(`No modifier provided after separator %s.`, modSep));
}
if (modSep == '#') {
claimId = modVal;
} else if (modSep == ':') {
claimSequence = modVal;
} else if (modSep == '$') {
bidPosition = modVal;
}
}
if (modSep == "#") {
claimId = modVal;
} else if (modSep == ":") {
claimSequence = modVal;
} else if (modSep == "$") {
bidPosition = modVal;
}
}
if (
claimId &&
(claimId.length > CLAIM_ID_MAX_LEN || !claimId.match(/^[0-9a-f]+$/))
) {
throw new Error(__(`Invalid claim ID %s.`, claimId));
}
if (
claimId &&
(claimId.length > CLAIM_ID_MAX_LEN || !claimId.match(/^[0-9a-f]+$/))
) {
throw new Error(__(`Invalid claim ID %s.`, claimId));
}
if (claimSequence && !claimSequence.match(/^-?[1-9][0-9]*$/)) {
throw new Error(__('Claim sequence must be a number.'));
}
if (claimSequence && !claimSequence.match(/^-?[1-9][0-9]*$/)) {
throw new Error(__("Claim sequence must be a number."));
}
if (bidPosition && !bidPosition.match(/^-?[1-9][0-9]*$/)) {
throw new Error(__('Bid position must be a number.'));
}
if (bidPosition && !bidPosition.match(/^-?[1-9][0-9]*$/)) {
throw new Error(__("Bid position must be a number."));
}
// Validate and process path
if (path) {
if (!isChannel) {
throw new Error(__('Only channel URIs may have a path.'));
}
// Validate and process path
if (path) {
if (!isChannel) {
throw new Error(__("Only channel URIs may have a path."));
}
const pathBadChars = path.match(/[^A-Za-z0-9-]/g);
if (pathBadChars) {
throw new Error(
__(
`Invalid character %s in path: %s`,
count == 1 ? '' : 's',
nameBadChars.join(', ')
)
);
}
const pathBadChars = path.match(/[^A-Za-z0-9-]/g);
if (pathBadChars) {
throw new Error(
__(
`Invalid character %s in path: %s`,
count == 1 ? "" : "s",
nameBadChars.join(", ")
)
);
}
contentName = path;
} else if (pathSep) {
throw new Error(__('No path provided after /'));
}
contentName = path;
} else if (pathSep) {
throw new Error(__("No path provided after /"));
}
return {
name,
path,
isChannel,
...(contentName ? { contentName } : {}),
...(channelName ? { channelName } : {}),
...(claimSequence ? { claimSequence: parseInt(claimSequence) } : {}),
...(bidPosition ? { bidPosition: parseInt(bidPosition) } : {}),
...(claimId ? { claimId } : {}),
...(path ? { path } : {})
};
return {
name,
path,
isChannel,
...(contentName ? { contentName } : {}),
...(channelName ? { channelName } : {}),
...(claimSequence ? { claimSequence: parseInt(claimSequence) } : {}),
...(bidPosition ? { bidPosition: parseInt(bidPosition) } : {}),
...(claimId ? { claimId } : {}),
...(path ? { path } : {}),
};
};
/**
@ -153,96 +153,96 @@ lbryuri.parse = function(uri, requireProto = false) {
* The channelName key will accept names with or without the @ prefix.
*/
lbryuri.build = function(uriObj, includeProto = true, allowExtraProps = false) {
let {
name,
claimId,
claimSequence,
bidPosition,
path,
contentName,
channelName
} = uriObj;
let {
name,
claimId,
claimSequence,
bidPosition,
path,
contentName,
channelName,
} = uriObj;
if (channelName) {
const channelNameFormatted = channelName.startsWith('@')
? channelName
: '@' + channelName;
if (!name) {
name = channelNameFormatted;
} else if (name !== channelNameFormatted) {
throw new Error(
__(
'Received a channel content URI, but name and channelName do not match. "name" represents the value in the name position of the URI (lbry://name...), which for channel content will be the channel name. In most cases, to construct a channel URI you should just pass channelName and contentName.'
)
);
}
}
if (channelName) {
const channelNameFormatted = channelName.startsWith("@")
? channelName
: "@" + channelName;
if (!name) {
name = channelNameFormatted;
} else if (name !== channelNameFormatted) {
throw new Error(
__(
'Received a channel content URI, but name and channelName do not match. "name" represents the value in the name position of the URI (lbry://name...), which for channel content will be the channel name. In most cases, to construct a channel URI you should just pass channelName and contentName.'
)
);
}
}
if (contentName) {
if (!name) {
name = contentName;
} else if (!path) {
path = contentName;
}
if (path && path !== contentName) {
throw new Error(
__(
'Path and contentName do not match. Only one is required; most likely you wanted contentName.'
)
);
}
}
if (contentName) {
if (!name) {
name = contentName;
} else if (!path) {
path = contentName;
}
if (path && path !== contentName) {
throw new Error(
__(
"Path and contentName do not match. Only one is required; most likely you wanted contentName."
)
);
}
}
return (
(includeProto ? 'lbry://' : '') +
name +
(claimId ? `#${claimId}` : '') +
(claimSequence ? `:${claimSequence}` : '') +
(bidPosition ? `\$${bidPosition}` : '') +
(path ? `/${path}` : '')
);
return (
(includeProto ? "lbry://" : "") +
name +
(claimId ? `#${claimId}` : "") +
(claimSequence ? `:${claimSequence}` : "") +
(bidPosition ? `\$${bidPosition}` : "") +
(path ? `/${path}` : "")
);
};
/* Takes a parseable LBRY URI and converts it to standard, canonical format (currently this just
* consists of adding the lbry:// prefix if needed) */
lbryuri.normalize = function(uri) {
const { name, path, bidPosition, claimSequence, claimId } = lbryuri.parse(
uri
);
return lbryuri.build({ name, path, claimSequence, bidPosition, claimId });
const { name, path, bidPosition, claimSequence, claimId } = lbryuri.parse(
uri
);
return lbryuri.build({ name, path, claimSequence, bidPosition, claimId });
};
lbryuri.isValid = function(uri) {
let parts;
try {
parts = lbryuri.parse(lbryuri.normalize(uri));
} catch (error) {
return false;
}
return parts && parts.name;
let parts;
try {
parts = lbryuri.parse(lbryuri.normalize(uri));
} catch (error) {
return false;
}
return parts && parts.name;
};
lbryuri.isValidName = function(name, checkCase = true) {
const regexp = new RegExp('^[a-z0-9-]+$', checkCase ? '' : 'i');
return regexp.test(name);
const regexp = new RegExp("^[a-z0-9-]+$", checkCase ? "" : "i");
return regexp.test(name);
};
lbryuri.isClaimable = function(uri) {
let parts;
try {
parts = lbryuri.parse(lbryuri.normalize(uri));
} catch (error) {
return false;
}
return (
parts &&
parts.name &&
!parts.claimId &&
!parts.bidPosition &&
!parts.claimSequence &&
!parts.isChannel &&
!parts.path
);
let parts;
try {
parts = lbryuri.parse(lbryuri.normalize(uri));
} catch (error) {
return false;
}
return (
parts &&
parts.name &&
!parts.claimId &&
!parts.bidPosition &&
!parts.claimSequence &&
!parts.isChannel &&
!parts.path
);
};
window.lbryuri = lbryuri;

View file

@ -1,84 +1,84 @@
import lbry from './lbry.js';
import jsonrpc from './jsonrpc.js';
import lbry from "./lbry.js";
import jsonrpc from "./jsonrpc.js";
const queryTimeout = 3000;
const maxQueryTries = 2;
const defaultServers = [
'http://lighthouse7.lbry.io:50005',
'http://lighthouse8.lbry.io:50005',
'http://lighthouse9.lbry.io:50005'
"http://lighthouse7.lbry.io:50005",
"http://lighthouse8.lbry.io:50005",
"http://lighthouse9.lbry.io:50005",
];
const path = '/';
const path = "/";
let server = null;
let connectTryNum = 0;
function getServers() {
return lbry.getClientSetting('useCustomLighthouseServers')
? lbry.getClientSetting('customLighthouseServers')
: defaultServers;
return lbry.getClientSetting("useCustomLighthouseServers")
? lbry.getClientSetting("customLighthouseServers")
: defaultServers;
}
function call(method, params, callback, errorCallback) {
if (connectTryNum >= maxQueryTries) {
errorCallback(
new Error(
__(
`Could not connect to Lighthouse server. Last server attempted: %s`,
server
)
)
);
return;
}
if (connectTryNum >= maxQueryTries) {
errorCallback(
new Error(
__(
`Could not connect to Lighthouse server. Last server attempted: %s`,
server
)
)
);
return;
}
/**
/**
* Set the Lighthouse server if it hasn't been set yet, if the current server is not in current
* set of servers (most likely because of a settings change), or we're re-trying after a failed
* query.
*/
if (!server || !getServers().includes(server) || connectTryNum > 0) {
// If there's a current server, filter it out so we get a new one
const newServerChoices = server
? getServers().filter(s => s != server)
: getServers();
server =
newServerChoices[
Math.round(Math.random() * (newServerChoices.length - 1))
];
}
if (!server || !getServers().includes(server) || connectTryNum > 0) {
// If there's a current server, filter it out so we get a new one
const newServerChoices = server
? getServers().filter(s => s != server)
: getServers();
server =
newServerChoices[
Math.round(Math.random() * (newServerChoices.length - 1))
];
}
jsonrpc.call(
server + path,
method,
params,
response => {
connectTryNum = 0;
callback(response);
},
error => {
connectTryNum = 0;
errorCallback(error);
},
() => {
connectTryNum++;
call(method, params, callback, errorCallback);
},
queryTimeout
);
jsonrpc.call(
server + path,
method,
params,
response => {
connectTryNum = 0;
callback(response);
},
error => {
connectTryNum = 0;
errorCallback(error);
},
() => {
connectTryNum++;
call(method, params, callback, errorCallback);
},
queryTimeout
);
}
const lighthouse = new Proxy(
{},
{
get: function(target, name) {
return function(...params) {
return new Promise((resolve, reject) => {
call(name, params, resolve, reject);
});
};
}
}
{},
{
get: function(target, name) {
return function(...params) {
return new Promise((resolve, reject) => {
call(name, params, resolve, reject);
});
};
},
}
);
export default lighthouse;

View file

@ -5,11 +5,6 @@ import FileCard from "component/fileCard";
import { BusyMessage } from "component/common.js";
import ToolTip from "component/tooltip.js";
const communityCategoryToolTipText =
"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!';
const FeaturedCategory = props => {
const { category, names } = props;
@ -21,7 +16,9 @@ const FeaturedCategory = props => {
category.match(/^community/i) &&
<ToolTip
label={__("What's this?")}
body={__(communityCategoryToolTipText)}
body={__(
'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!'
)}
className="tooltip--header"
/>}
</h3>

View file

@ -15,7 +15,8 @@ const perform = dispatch => ({
back: () => dispatch(doHistoryBack()),
navigate: path => dispatch(doNavigate(path)),
fetchClaimListMine: () => dispatch(doFetchClaimListMine()),
claimFirstChannelReward: () => dispatch(doClaimRewardType(rewards.TYPE_FIRST_CHANNEL)),
claimFirstChannelReward: () =>
dispatch(doClaimRewardType(rewards.TYPE_FIRST_CHANNEL)),
});
export default connect(select, perform)(PublishPage);

View file

@ -433,17 +433,26 @@ class PublishPage extends React.PureComponent {
"You have already used this URL. Publishing to it again will update your previous publish."
);
} else if (this.state.topClaimValue) {
return (
<span>
{__n(
'A deposit of at least "%s" credit is required to win "%s". However, you can still get a permanent URL for any amount.',
'A deposit of at least "%s" credits is required to win "%s". However, you can still get a permanent URL for any amount.',
this.state.topClaimValue /*pluralization param*/,
this.state.topClaimValue,
this.state.name /*regular params*/
)}
</span>
);
if (this.state.topClaimValue === 1) {
return (
<span>
{__(
'A deposit of at least one credit is required to win "%s". However, you can still get a permanent URL for any amount.',
this.state.name
)}
</span>
);
} else {
return (
<span>
{__(
'A deposit of at least "%s" credits is required to win "%s". However, you can still get a permanent URL for any amount.',
this.state.topClaimValue,
this.state.name
)}
</span>
);
}
} else {
return "";
}
@ -752,7 +761,7 @@ class PublishPage extends React.PureComponent {
/>
<FormRow
label={__("Deposit")}
postfix="LBC"
postfix={__("LBC")}
step="0.01"
min="0"
type="number"

View file

@ -20,7 +20,7 @@ const RewardTile = props => {
</div>
<div className="card__actions">
{claimed
? <span><Icon icon="icon-check" /> Reward claimed.</span>
? <span><Icon icon="icon-check" /> {__("Reward claimed.")}</span>
: <RewardLink reward_type={reward.reward_type} />}
</div>
<div className="card__content">{reward.reward_description}</div>
@ -59,14 +59,14 @@ const RewardsPage = props => {
<div className="empty">
<p>{__("You are not eligible to claim rewards.")}</p>
<p>
To become eligible, email
{" "}<Link href="mailto:help@lbry.io" label="help@lbry.io" /> with a
link to a public social media profile.
{__("To become eligible, email")}
{" "}<Link href="mailto:help@lbry.io" label="help@lbry.io" />{" "}
{__("with a link to a public social media profile.")}
</p>
</div>
);
} else if (fetching) {
content = <BusyMessage message="Fetching rewards" />;
content = <BusyMessage message={__("Fetching rewards")} />;
} else if (rewards.length > 0) {
content = rewards.map(reward =>
<RewardTile key={reward.reward_type} reward={reward} />

View file

@ -68,8 +68,7 @@ export const selectUserIsVerificationCandidate = createSelector(
selectUserIsRewardApproved,
selectEmailToVerify,
selectUser,
(isEligible, isApproved, emailToVerify, user) =>
(isEligible && !isApproved) || (emailToVerify && user && !user.has_email)
(isEligible, isApproved, emailToVerify, user) => emailToVerify && user
);
export const selectUserIsAuthRequested = createSelector(

View file

@ -3,15 +3,15 @@
* is not set yet.
*/
export function getLocal(key, fallback = undefined) {
const itemRaw = localStorage.getItem(key);
return itemRaw === null ? fallback : JSON.parse(itemRaw);
const itemRaw = localStorage.getItem(key);
return itemRaw === null ? fallback : JSON.parse(itemRaw);
}
/**
* Thin wrapper around localStorage.setItem(). Converts value to JSON.
*/
export function setLocal(key, value) {
localStorage.setItem(key, JSON.stringify(value));
localStorage.setItem(key, JSON.stringify(value));
}
/**
@ -19,13 +19,13 @@ export function setLocal(key, value) {
* is not set yet.
*/
export function getSession(key, fallback = undefined) {
const itemRaw = sessionStorage.getItem(key);
return itemRaw === null ? fallback : JSON.parse(itemRaw);
const itemRaw = sessionStorage.getItem(key);
return itemRaw === null ? fallback : JSON.parse(itemRaw);
}
/**
* Thin wrapper around localStorage.setItem(). Converts value to JSON.
*/
export function setSession(key, value) {
sessionStorage.setItem(key, JSON.stringify(value));
sessionStorage.setItem(key, JSON.stringify(value));
}

488
ui/package-lock.json generated
View file

@ -1,6 +1,6 @@
{
"name": "lbry-web-ui",
"version": "0.12.0",
"version": "0.12.2rc5",
"lockfileVersion": 1,
"dependencies": {
"abbrev": {
@ -97,6 +97,12 @@
"integrity": "sha1-vgiVmQl7dKXJxKhKDNvNtivYeu8=",
"dev": true
},
"any-promise": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz",
"integrity": "sha1-q8av7tzqUugJzcA3au0845Y10X8=",
"dev": true
},
"anymatch": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/anymatch/-/anymatch-1.3.0.tgz",
@ -140,9 +146,9 @@
"integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E="
},
"array-flatten": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
"integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=",
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-2.1.1.tgz",
"integrity": "sha1-Qmu52oQJDBg42BLIFQryCoMx4pY=",
"dev": true
},
"array-union": {
@ -661,9 +667,9 @@
"integrity": "sha1-cK+ySNVmDl0Y+BHZHIMDtUE0oY4="
},
"babylon": {
"version": "6.17.3",
"resolved": "https://registry.npmjs.org/babylon/-/babylon-6.17.3.tgz",
"integrity": "sha512-mq0x3HCAGGmQyZXviOVe5TRsw37Ijy3D43jCqt/9WVf+onx2dUgW3PosnqCbScAFhRO9DGs8nxoMzU0iiosMqQ=="
"version": "6.17.4",
"resolved": "https://registry.npmjs.org/babylon/-/babylon-6.17.4.tgz",
"integrity": "sha512-kChlV+0SXkjE0vUn9OZ7pBMWRFd8uq3mZe8x1K6jhuNcAFAtEnjchFAqB+dYEXKyd+JpT6eppRR78QAr5gTsUw=="
},
"balanced-match": {
"version": "1.0.0",
@ -715,9 +721,15 @@
"integrity": "sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo="
},
"bn.js": {
"version": "4.11.6",
"resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.6.tgz",
"integrity": "sha1-UzRK2xRhehP26N0s4okF0cC6MhU=",
"version": "4.11.7",
"resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.7.tgz",
"integrity": "sha512-LxFiV5mefv0ley0SzqkOPR1bC4EbpPx8LkOz5vMe/Yi15t5hzwgO/G+tc7wOtL4PZTYjwHu8JnEiSLumuSjSfA==",
"dev": true
},
"bonjour": {
"version": "3.5.0",
"resolved": "https://registry.npmjs.org/bonjour/-/bonjour-3.5.0.tgz",
"integrity": "sha1-jokKGD2O6aI5OzhExpGkK897yfU=",
"dev": true
},
"boom": {
@ -783,6 +795,12 @@
"integrity": "sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg=",
"dev": true
},
"buffer-indexof": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/buffer-indexof/-/buffer-indexof-1.1.0.tgz",
"integrity": "sha1-9U9kfE9OJSKLqmVqLlfkPV8nCYI=",
"dev": true
},
"buffer-xor": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz",
@ -874,22 +892,30 @@
"dev": true
},
"cli-cursor": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-1.0.2.tgz",
"integrity": "sha1-ZNo/fValRBLll5S9Ytw1KV6PKYc=",
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz",
"integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=",
"dev": true
},
"cli-spinners": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-0.1.2.tgz",
"integrity": "sha1-u3ZNiOGF+54eaiofGXcjGPYF4xw=",
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-1.0.0.tgz",
"integrity": "sha1-75h+09SDkaw9q5GAtAanQhgNbmo=",
"dev": true
},
"cli-table": {
"version": "0.3.1",
"resolved": "https://registry.npmjs.org/cli-table/-/cli-table-0.3.1.tgz",
"integrity": "sha1-9TsFJmqLGguTSz0IIebi3FkUriM=",
"dev": true
"dev": true,
"dependencies": {
"colors": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/colors/-/colors-1.0.3.tgz",
"integrity": "sha1-BDP0TYCWgP3rYO0mDxsMJi6CpAs=",
"dev": true
}
}
},
"cli-truncate": {
"version": "0.2.1",
@ -931,9 +957,9 @@
"integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c="
},
"colors": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/colors/-/colors-1.0.3.tgz",
"integrity": "sha1-BDP0TYCWgP3rYO0mDxsMJi6CpAs=",
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/colors/-/colors-1.1.2.tgz",
"integrity": "sha1-FopHAXVran9RoSzgyXv6KMCE7WM=",
"dev": true
},
"combined-stream": {
@ -1090,9 +1116,9 @@
"dev": true
},
"create-react-class": {
"version": "15.5.4",
"resolved": "https://registry.npmjs.org/create-react-class/-/create-react-class-15.5.4.tgz",
"integrity": "sha1-GIh1yxXi++TKWVtvQ+sOSh8A/lA="
"version": "15.6.0",
"resolved": "https://registry.npmjs.org/create-react-class/-/create-react-class-15.6.0.tgz",
"integrity": "sha1-q0SEl8JlZuHilBPogyB9V8/nvtQ="
},
"cross-spawn": {
"version": "3.0.1",
@ -1166,6 +1192,12 @@
"resolved": "https://registry.npmjs.org/deep-diff/-/deep-diff-0.3.8.tgz",
"integrity": "sha1-wB3mPvsO7JeYgB1Ax+Da4ltYLIQ="
},
"deep-equal": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.0.1.tgz",
"integrity": "sha1-9dJgKStmDghO/0zbyfCK0yR0SLU=",
"dev": true
},
"deep-is": {
"version": "0.1.3",
"resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz",
@ -1229,6 +1261,24 @@
"integrity": "sha1-tYNXOScM/ias9jIJn97SoH8gnl4=",
"dev": true
},
"dns-equal": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/dns-equal/-/dns-equal-1.0.0.tgz",
"integrity": "sha1-s55/HabrCnW6nBcySzR1PEfgZU0=",
"dev": true
},
"dns-packet": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-1.1.1.tgz",
"integrity": "sha1-I2nUUDivBF84mOb6VoYq7T9AKWw=",
"dev": true
},
"dns-txt": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/dns-txt/-/dns-txt-2.0.2.tgz",
"integrity": "sha1-uR2Ab10nGI5Ks+fRB9iBocxGQrY=",
"dev": true
},
"doctrine": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.0.0.tgz",
@ -1253,6 +1303,12 @@
"integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=",
"dev": true
},
"electron-rebuild": {
"version": "1.5.11",
"resolved": "https://registry.npmjs.org/electron-rebuild/-/electron-rebuild-1.5.11.tgz",
"integrity": "sha1-bqZg3rVGpRbn76qBzVmF1WZPJFw=",
"dev": true
},
"elegant-spinner": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/elegant-spinner/-/elegant-spinner-1.0.1.tgz",
@ -1418,9 +1474,9 @@
"dev": true
},
"eslint-loader": {
"version": "1.7.1",
"resolved": "https://registry.npmjs.org/eslint-loader/-/eslint-loader-1.7.1.tgz",
"integrity": "sha1-ULFY3WJy3O+5fphCVIN/gaWALOA=",
"version": "1.8.0",
"resolved": "https://registry.npmjs.org/eslint-loader/-/eslint-loader-1.8.0.tgz",
"integrity": "sha512-+d9me9y9t+/k1pY5hsorY685H3yYoQT0t5pZT1TGB7L46VOoLv8+3uKHvkjpUx1aCTjeacbj4yz4s5/LcGolpg==",
"dev": true,
"dependencies": {
"loader-utils": {
@ -1552,18 +1608,10 @@
"dev": true
},
"esrecurse": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.1.0.tgz",
"integrity": "sha1-RxO2U2rffyrE8yfVWed1a/9kgiA=",
"dev": true,
"dependencies": {
"estraverse": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.1.1.tgz",
"integrity": "sha1-9srKcokzqFDvkGYdDheYK6RxEaI=",
"dev": true
}
}
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.0.tgz",
"integrity": "sha1-+pVo2Y04I/mkHZHpAtyrnqblsWM=",
"dev": true
},
"estraverse": {
"version": "4.2.0",
@ -1653,6 +1701,12 @@
"integrity": "sha1-urZdDwOqgMNYQIly/HAPkWlEtmI=",
"dev": true,
"dependencies": {
"array-flatten": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
"integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=",
"dev": true
},
"debug": {
"version": "2.6.7",
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.7.tgz",
@ -1813,6 +1867,18 @@
"resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz",
"integrity": "sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8="
},
"fs-extra": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-2.1.2.tgz",
"integrity": "sha1-BGxwFjzvmq1GsOSn+kZ/si1x3jU=",
"dev": true
},
"fs-promise": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/fs-promise/-/fs-promise-2.0.3.tgz",
"integrity": "sha1-9k5PhUvPaJqovdy6JokW2z20aFQ=",
"dev": true
},
"fs-readdir-recursive": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/fs-readdir-recursive/-/fs-readdir-recursive-1.0.0.tgz",
@ -2427,6 +2493,12 @@
}
}
},
"gettext-parser": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/gettext-parser/-/gettext-parser-1.2.2.tgz",
"integrity": "sha1-HvDadcHnWa4wicc++k0Z5AKYdI4=",
"dev": true
},
"glob": {
"version": "7.1.2",
"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz",
@ -2519,9 +2591,9 @@
"dev": true
},
"hash.js": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.0.3.tgz",
"integrity": "sha1-EzL/ABVsCg/92CNgE9B7d6BFFXM=",
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.1.tgz",
"integrity": "sha512-I2TYCUjYQMmqmRMCp6jKMC5bvdXxGIZ/heITRR/0F1u0OP920ImEj/cXt3WgcTKBnNYGn7enxUzdai3db829JA==",
"dev": true
},
"hawk": {
@ -2630,6 +2702,12 @@
}
}
},
"i18n-extract": {
"version": "0.4.4",
"resolved": "https://registry.npmjs.org/i18n-extract/-/i18n-extract-0.4.4.tgz",
"integrity": "sha1-/VyDA4mv91WNrLh1bpPv1lNIHV8=",
"dev": true
},
"iconv-lite": {
"version": "0.4.18",
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.18.tgz",
@ -2693,6 +2771,32 @@
"version": "0.12.0",
"resolved": "https://registry.npmjs.org/inquirer/-/inquirer-0.12.0.tgz",
"integrity": "sha1-HvK/1jUE3wvHV4X/+MLEHfEvB34=",
"dev": true,
"dependencies": {
"cli-cursor": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-1.0.2.tgz",
"integrity": "sha1-ZNo/fValRBLll5S9Ytw1KV6PKYc=",
"dev": true
},
"onetime": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz",
"integrity": "sha1-ofeDj4MUxRbwXs78vEzP4EtO14k=",
"dev": true
},
"restore-cursor": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-1.0.1.tgz",
"integrity": "sha1-NGYfRohjJ/7SmRR5FSJS35LapUE=",
"dev": true
}
}
},
"internal-ip": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/internal-ip/-/internal-ip-1.2.0.tgz",
"integrity": "sha1-rp+/k7mEh4eF1QqN4bNWlWBYz1w=",
"dev": true
},
"interpret": {
@ -2711,6 +2815,12 @@
"resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz",
"integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY="
},
"ip": {
"version": "1.1.5",
"resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz",
"integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=",
"dev": true
},
"ipaddr.js": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.3.0.tgz",
@ -2976,6 +3086,12 @@
"resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz",
"integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE="
},
"jsonfile": {
"version": "2.4.0",
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz",
"integrity": "sha1-NzaitCi4e72gzIO1P6PWM6NcKug=",
"dev": true
},
"jsonify": {
"version": "0.0.0",
"resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz",
@ -3017,6 +3133,18 @@
"integrity": "sha1-OGchPo3Xm/Ho8jAMDPwe+xgsDfE=",
"dev": true
},
"keytar": {
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/keytar/-/keytar-4.0.3.tgz",
"integrity": "sha1-RaNnQsHPzQchDSbRuUKOKXh5vPw=",
"dependencies": {
"nan": {
"version": "2.5.1",
"resolved": "https://registry.npmjs.org/nan/-/nan-2.5.1.tgz",
"integrity": "sha1-1bAWkSUzJql6K77p5hxV2NYDUeI="
}
}
},
"kind-of": {
"version": "3.2.2",
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
@ -3054,7 +3182,39 @@
"version": "0.12.0",
"resolved": "https://registry.npmjs.org/listr/-/listr-0.12.0.tgz",
"integrity": "sha1-a84sD1YD+klYDqF81qAMwOX6RRo=",
"dev": true
"dev": true,
"dependencies": {
"cli-cursor": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-1.0.2.tgz",
"integrity": "sha1-ZNo/fValRBLll5S9Ytw1KV6PKYc=",
"dev": true
},
"cli-spinners": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-0.1.2.tgz",
"integrity": "sha1-u3ZNiOGF+54eaiofGXcjGPYF4xw=",
"dev": true
},
"onetime": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz",
"integrity": "sha1-ofeDj4MUxRbwXs78vEzP4EtO14k=",
"dev": true
},
"ora": {
"version": "0.2.3",
"resolved": "https://registry.npmjs.org/ora/-/ora-0.2.3.tgz",
"integrity": "sha1-N1J9Igrc1Tw5tzVx11QVbV22V6Q=",
"dev": true
},
"restore-cursor": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-1.0.1.tgz",
"integrity": "sha1-NGYfRohjJ/7SmRR5FSJS35LapUE=",
"dev": true
}
}
},
"listr-silent-renderer": {
"version": "1.1.1",
@ -3080,7 +3240,27 @@
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/listr-verbose-renderer/-/listr-verbose-renderer-0.4.0.tgz",
"integrity": "sha1-RNwBuww0oDxXIVTU0Izemx3FYg8=",
"dev": true
"dev": true,
"dependencies": {
"cli-cursor": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-1.0.2.tgz",
"integrity": "sha1-ZNo/fValRBLll5S9Ytw1KV6PKYc=",
"dev": true
},
"onetime": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz",
"integrity": "sha1-ofeDj4MUxRbwXs78vEzP4EtO14k=",
"dev": true
},
"restore-cursor": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-1.0.1.tgz",
"integrity": "sha1-NGYfRohjJ/7SmRR5FSJS35LapUE=",
"dev": true
}
}
},
"load-json-file": {
"version": "1.1.0",
@ -3262,7 +3442,27 @@
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/log-update/-/log-update-1.0.2.tgz",
"integrity": "sha1-GZKfZMQJPS0ucHWh2tivWcKWuNE=",
"dev": true
"dev": true,
"dependencies": {
"cli-cursor": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-1.0.2.tgz",
"integrity": "sha1-ZNo/fValRBLll5S9Ytw1KV6PKYc=",
"dev": true
},
"onetime": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz",
"integrity": "sha1-ofeDj4MUxRbwXs78vEzP4EtO14k=",
"dev": true
},
"restore-cursor": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-1.0.1.tgz",
"integrity": "sha1-NGYfRohjJ/7SmRR5FSJS35LapUE=",
"dev": true
}
}
},
"longest": {
"version": "1.0.1",
@ -3375,6 +3575,12 @@
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.15.tgz",
"integrity": "sha1-pOv1BkCUVpI3uM9wBGd20J/JKu0="
},
"mimic-fn": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.1.0.tgz",
"integrity": "sha1-5md4PZLonb00KBi1IwudYqZyrRg=",
"dev": true
},
"minimalistic-assert": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.0.tgz",
@ -3417,6 +3623,18 @@
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
},
"multicast-dns": {
"version": "6.1.1",
"resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-6.1.1.tgz",
"integrity": "sha1-bn3oalcIcqsXBYrepxYLvsqBTd4=",
"dev": true
},
"multicast-dns-service-types": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/multicast-dns-service-types/-/multicast-dns-service-types-1.1.0.tgz",
"integrity": "sha1-iZ8R2WhuXgXLkbNdXw5jt3PPyQE=",
"dev": true
},
"multistream": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/multistream/-/multistream-2.1.0.tgz",
@ -3428,6 +3646,12 @@
"integrity": "sha1-j7+rsKmKJT0xhDMfno3rc3L6xsA=",
"dev": true
},
"mz": {
"version": "2.6.0",
"resolved": "https://registry.npmjs.org/mz/-/mz-2.6.0.tgz",
"integrity": "sha1-yLhSHZWN8KTydoAl22nHGe5O8c4=",
"dev": true
},
"nan": {
"version": "2.6.2",
"resolved": "https://registry.npmjs.org/nan/-/nan-2.6.2.tgz",
@ -3450,6 +3674,12 @@
"resolved": "https://registry.npmjs.org/next-event/-/next-event-1.0.0.tgz",
"integrity": "sha1-53eKzeLlWALgrRh5w5z2917aYdg="
},
"node-abi": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/node-abi/-/node-abi-2.0.3.tgz",
"integrity": "sha1-DKZ+XmZ7jhNDVJyhcVOoFdC7/ao=",
"dev": true
},
"node-emoji": {
"version": "1.5.1",
"resolved": "https://registry.npmjs.org/node-emoji/-/node-emoji-1.5.1.tgz",
@ -3461,6 +3691,12 @@
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-1.7.1.tgz",
"integrity": "sha512-j8XsFGCLw79vWXkZtMSmmLaOk9z5SQ9bV/tkbZVCqvgwzrjAGq66igobLofHtF63NvMTp2WjytpsNTGKa+XRIQ=="
},
"node-forge": {
"version": "0.6.33",
"resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.6.33.tgz",
"integrity": "sha1-RjgRh59XPUUVWtap9D3ClujoXrw=",
"dev": true
},
"node-gyp": {
"version": "3.6.2",
"resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-3.6.2.tgz",
@ -3480,6 +3716,12 @@
}
}
},
"node-loader": {
"version": "0.6.0",
"resolved": "https://registry.npmjs.org/node-loader/-/node-loader-0.6.0.tgz",
"integrity": "sha1-x5fvUQle1YWZArFX9jhPY2HgWug=",
"dev": true
},
"node-notifier": {
"version": "4.6.1",
"resolved": "https://registry.npmjs.org/node-notifier/-/node-notifier-4.6.1.tgz",
@ -3604,9 +3846,9 @@
"integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E="
},
"onetime": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz",
"integrity": "sha1-ofeDj4MUxRbwXs78vEzP4EtO14k=",
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz",
"integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=",
"dev": true
},
"opn": {
@ -3636,9 +3878,9 @@
"dev": true
},
"ora": {
"version": "0.2.3",
"resolved": "https://registry.npmjs.org/ora/-/ora-0.2.3.tgz",
"integrity": "sha1-N1J9Igrc1Tw5tzVx11QVbV22V6Q=",
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/ora/-/ora-1.3.0.tgz",
"integrity": "sha1-gAeN0rkqk0r2ajrXKluRBpTt5Ro=",
"dev": true
},
"original": {
@ -3881,9 +4123,9 @@
"dev": true
},
"promise": {
"version": "7.1.1",
"resolved": "https://registry.npmjs.org/promise/-/promise-7.1.1.tgz",
"integrity": "sha1-SJZUxpJha4qlWwck+oCbt9tJxb8="
"version": "7.3.1",
"resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz",
"integrity": "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg=="
},
"prop-types": {
"version": "15.5.10",
@ -3974,15 +4216,7 @@
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.0.5.tgz",
"integrity": "sha512-8T7Zn1AhMsQ/HI1SjcCfT/t4ii3eAqco3yOcSzS4mozsOz69lHLsoMXmF9nZgnFanYscnSlUSgs8uZyKzpE6kg==",
"dev": true,
"dependencies": {
"safe-buffer": {
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.0.tgz",
"integrity": "sha512-aSLEDudu6OoRr/2rU609gRmnYboRLxgDG1z9o2Q0os7236FwvcqIOO8r8U5JUEwivZOhDaKlFO4SbPTJYyBEyQ==",
"dev": true
}
}
"dev": true
},
"range-parser": {
"version": "1.2.0",
@ -4001,19 +4235,24 @@
"integrity": "sha1-0xzLFJmuIjwNIdFIVlCqSg03TOA="
},
"react": {
"version": "15.6.0",
"resolved": "https://registry.npmjs.org/react/-/react-15.6.0.tgz",
"integrity": "sha1-wjKZtI4w7TAlCM6J4aAskZ+Ca84="
"version": "15.6.1",
"resolved": "https://registry.npmjs.org/react/-/react-15.6.1.tgz",
"integrity": "sha1-uqhDTsZ4C96ZfNw4C3nNM7ljk98="
},
"react-dom": {
"version": "15.6.0",
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-15.6.0.tgz",
"integrity": "sha1-i8I8sMgOcGNVt2yp+M5Hz3vfttE="
"version": "15.6.1",
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-15.6.1.tgz",
"integrity": "sha1-LLDtQZEDjlPCCes6eaI+Kkz5lHA="
},
"react-dom-factories": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/react-dom-factories/-/react-dom-factories-1.0.0.tgz",
"integrity": "sha1-9DwF5QUbME8zJRYY1byFmynka20="
},
"react-modal": {
"version": "1.9.4",
"resolved": "https://registry.npmjs.org/react-modal/-/react-modal-1.9.4.tgz",
"integrity": "sha512-ourtHswaEA/KyeI20AsCOSWTC23WF3z0b1C3qzQtA5UhBOdwQ2sEK2OPJGN8u7iFGJ83etmk605aeF/i4tGVEQ=="
"version": "1.9.7",
"resolved": "https://registry.npmjs.org/react-modal/-/react-modal-1.9.7.tgz",
"integrity": "sha512-oZNqI0ZnPD7NnfObrCMz2hxHTAw5oEuhZJ+gnyFNIQB2rR8h1YbLQTfhms1mtSJigb0J23OOWElHjXYYaKO+wg=="
},
"react-redux": {
"version": "5.0.5",
@ -4031,9 +4270,9 @@
"integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI="
},
"readable-stream": {
"version": "2.2.11",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.2.11.tgz",
"integrity": "sha512-h+8+r3MKEhkiVrwdKL8aWs1oc1VvBu33ueshOvS26RsZQ3Amhx/oO3TKe4lApSV9ueY6as8EAh7mtuFjdlhg9Q=="
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.0.tgz",
"integrity": "sha512-c7KMXGd4b48nN3OJ1U9qOsn6pXNzf6kLd3kdZCkg2sxAcoiufInqF0XckwEnlrcwuaYwonlNK8GQUIOC/WC7sg=="
},
"readdirp": {
"version": "2.1.0",
@ -4084,9 +4323,9 @@
}
},
"redux": {
"version": "3.6.0",
"resolved": "https://registry.npmjs.org/redux/-/redux-3.6.0.tgz",
"integrity": "sha1-iHwrPQub2G7KK+cFccJ2VMGeGI0="
"version": "3.7.0",
"resolved": "https://registry.npmjs.org/redux/-/redux-3.7.0.tgz",
"integrity": "sha512-GHjaOkEQtQnnuLoYPFkRKHIqs1i1tdTlisu/xUHfk2juzCobSy4STxs4Lz5bPkc07Owb6BeGKx/r76c9IVTkOw=="
},
"redux-action-buffer": {
"version": "1.1.0",
@ -4236,9 +4475,9 @@
"dev": true
},
"restore-cursor": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-1.0.1.tgz",
"integrity": "sha1-NGYfRohjJ/7SmRR5FSJS35LapUE=",
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz",
"integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=",
"dev": true
},
"right-align": {
@ -4271,15 +4510,15 @@
"dev": true
},
"rxjs": {
"version": "5.4.0",
"resolved": "https://registry.npmjs.org/rxjs/-/rxjs-5.4.0.tgz",
"integrity": "sha1-p9sUqxV/nXqsalbmVeejhg05vyY=",
"version": "5.4.1",
"resolved": "https://registry.npmjs.org/rxjs/-/rxjs-5.4.1.tgz",
"integrity": "sha1-ti91fyeURdJloYpY+wpw3JDpFiY=",
"dev": true
},
"safe-buffer": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.0.1.tgz",
"integrity": "sha1-0mPKVGls2KMGtcplUekt5XkY++c="
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.0.tgz",
"integrity": "sha512-aSLEDudu6OoRr/2rU609gRmnYboRLxgDG1z9o2Q0os7236FwvcqIOO8r8U5JUEwivZOhDaKlFO4SbPTJYyBEyQ=="
},
"sass-graph": {
"version": "2.2.4",
@ -4304,6 +4543,12 @@
"integrity": "sha1-Yl2GWPhlr0Psliv8N2o3NZpJlMo=",
"dev": true
},
"selfsigned": {
"version": "1.9.1",
"resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-1.9.1.tgz",
"integrity": "sha1-zdpEktcNSGVw+HxlVGAjVY4d+lo=",
"dev": true
},
"semver": {
"version": "5.3.0",
"resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz",
@ -4451,6 +4696,12 @@
"resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.15.tgz",
"integrity": "sha1-AyAt9lwG0r2MfsI2KhkwVv7407E="
},
"spawn-rx": {
"version": "2.0.11",
"resolved": "https://registry.npmjs.org/spawn-rx/-/spawn-rx-2.0.11.tgz",
"integrity": "sha1-ZUUa1lZigB2up1VJgyp4LeAEjb8=",
"dev": true
},
"spdx-correct": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-1.0.2.tgz",
@ -4539,7 +4790,14 @@
"string_decoder": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.2.tgz",
"integrity": "sha1-sp4fThEl+pehA4K4pTNze3SR4Xk="
"integrity": "sha1-sp4fThEl+pehA4K4pTNze3SR4Xk=",
"dependencies": {
"safe-buffer": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.0.1.tgz",
"integrity": "sha1-0mPKVGls2KMGtcplUekt5XkY++c="
}
}
},
"string-width": {
"version": "1.0.2",
@ -4631,6 +4889,18 @@
"integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=",
"dev": true
},
"thenify": {
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.0.tgz",
"integrity": "sha1-5p44obq+lpsBCCB5eLn2K4hgSDk=",
"dev": true
},
"thenify-all": {
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz",
"integrity": "sha1-GhkY1ALY/D+Y+/I02wvMjMEOlyY=",
"dev": true
},
"through": {
"version": "2.3.8",
"resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
@ -4658,6 +4928,12 @@
}
}
},
"thunky": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/thunky/-/thunky-0.1.0.tgz",
"integrity": "sha1-vzAUaCTituZ7Dy16Ssi+smkIaE4=",
"dev": true
},
"timers-browserify": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.2.tgz",
@ -4848,9 +5124,9 @@
"dev": true
},
"uuid": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.0.1.tgz",
"integrity": "sha1-ZUS7ot/ajBzxfmKaOjBeK7H+5sE="
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.1.0.tgz",
"integrity": "sha512-DIWtzUkw04M4k3bf1IcpS2tngXEL26YUD2M0tMDUpnUrz2hgzUBlD55a4FjdLGPvfHxS6uluGWvaVEqgBcVa+g=="
},
"v8flags": {
"version": "2.1.1",
@ -4961,9 +5237,9 @@
"dev": true
},
"webpack-dev-server": {
"version": "2.4.5",
"resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-2.4.5.tgz",
"integrity": "sha1-MThM6BE2vhCAtLTN4OubkOVO5s8=",
"version": "2.5.0",
"resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-2.5.0.tgz",
"integrity": "sha1-TTanKLA7iyr6SO0wJCiEfOooQK0=",
"dev": true,
"dependencies": {
"camelcase": {
@ -4972,6 +5248,32 @@
"integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=",
"dev": true
},
"del": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/del/-/del-3.0.0.tgz",
"integrity": "sha1-U+z2mf/LyzljdpGrE7rxYIGXZuU=",
"dev": true
},
"globby": {
"version": "6.1.0",
"resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz",
"integrity": "sha1-9abXDoOV4hyFj7BInWTfAkJNUGw=",
"dev": true,
"dependencies": {
"pify": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
"integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=",
"dev": true
}
}
},
"pify": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz",
"integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=",
"dev": true
},
"supports-color": {
"version": "3.2.3",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz",

View file

@ -1,12 +1,13 @@
{
"name": "lbry-web-ui",
"version": "0.12.2rc3",
"version": "0.12.2rc5",
"description": "LBRY UI",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"dev": "webpack-dev-server --devtool eval --progress --colors --inline",
"precommit": "lint-staged",
"prettier": "prettier --trailing-comma es5 --write js/**/*.{js,jsx}"
"prettier": "prettier --trailing-comma es5 --write js/**/*.{js,jsx}",
"extract-langs": "node extractLocals.js"
},
"keywords": [
"lbry"
@ -15,11 +16,11 @@
"name": "LBRY Inc.",
"email": "hello@lbry.io"
},
"license": "SEE LICENSE IN LICENSE.md",
"license": "MIT",
"bugs": {
"url": "https://github.com/lbryio/lbry-app/issues"
},
"homepage": "https://github.com/lbryio/lbry-app#readme",
"homepage": "https://github.com/lbryio/lbry-app",
"dependencies": {
"babel-cli": "^6.11.4",
"babel-preset-es2015": "^6.13.2",
@ -27,6 +28,7 @@
"from2": "^2.3.0",
"jshashes": "^1.0.6",
"localforage": "^1.5.0",
"keytar": "^4.0.3",
"node-sass": "^3.8.0",
"rc-progress": "^2.0.6",
"react": "^15.4.0",
@ -53,6 +55,7 @@
"babel-preset-es2015": "^6.18.0",
"babel-preset-react": "^6.16.0",
"babel-preset-stage-2": "^6.18.0",
"electron-rebuild": "^1.5.11",
"eslint": "^3.10.2",
"eslint-config-airbnb": "^13.0.0",
"eslint-loader": "^1.6.1",
@ -60,8 +63,10 @@
"eslint-plugin-jsx-a11y": "^2.2.3",
"eslint-plugin-react": "^6.7.1",
"husky": "^0.13.4",
"i18n-extract": "^0.4.4",
"json-loader": "^0.5.4",
"lint-staged": "^3.6.0",
"node-loader": "^0.6.0",
"node-sass": "^3.13.0",
"prettier": "^1.4.2",
"webpack": "^2.6.1",

View file

@ -7,16 +7,19 @@ set -euo pipefail
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
mkdir -p $DIR/dist/css
mkdir -p $DIR/dist/js
(
cd "$DIR"
mkdir -p $DIR/dist/css
mkdir -p $DIR/dist/js
if [ ! -d "$DIR/node_modules" ]; then
echo "Installing NPM modules"
npm install
fi
if [ ! -d "$DIR/node_modules" ]; then
echo "Installing NPM modules"
npm install
fi
# run sass once without --watch to force update. then run with --watch to keep watching
$DIR/node_modules/.bin/node-sass --output $DIR/../app/dist/css --sourcemap=none $DIR/scss/
$DIR/node_modules/.bin/node-sass --output $DIR/../app/dist/css --sourcemap=none --watch $DIR/scss/ &
# run sass once without --watch to force update. then run with --watch to keep watching
node_modules/.bin/node-sass --output $DIR/../app/dist/css --sourcemap=none $DIR/scss/
node_modules/.bin/node-sass --output $DIR/../app/dist/css --sourcemap=none --watch $DIR/scss/ &
node_modules/.bin/webpack --config webpack.dev.config.js --progress --colors --watch
node_modules/.bin/webpack --config webpack.dev.config.js --progress --colors --watch
)

View file

@ -33,6 +33,10 @@ module.exports = {
// define an include so we check just the files we need
include: PATHS.app
},
{
test: /\.node$/,
use: ["node-loader"]
},
{
test: /\.css$/,
use: ["style-loader", "css-loader"]

View file

@ -41,6 +41,10 @@ module.exports = {
// define an include so we check just the files we need
include: PATHS.app
},
{
test: /\.node$/,
use: ["node-loader"]
},
{
test: /\.css$/,
use: ["style-loader", "css-loader"]