diff --git a/.bumpversion.cfg b/.bumpversion.cfg index 03dae8d5b..d37da8f5b 100644 --- a/.bumpversion.cfg +++ b/.bumpversion.cfg @@ -1,5 +1,5 @@ [bumpversion] -current_version = 0.11.9 +current_version = 0.12.0 commit = True tag = True parse = (?P\d+)\.(?P\d+)\.(?P\d+)((?P[a-z]+)(?P\d+))? diff --git a/.gitignore b/.gitignore index 17a8ad330..022473023 100644 --- a/.gitignore +++ b/.gitignore @@ -16,3 +16,4 @@ dist .#* build/daemon.zip +.vimrc diff --git a/CHANGELOG.md b/CHANGELOG.md index 79ee6f3ae..67dbfd505 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -27,6 +27,28 @@ Web UI version numbers should always match the corresponding version of LBRY App * * +## [0.12.0] - 2017-06-09 + +### Added + * More file types, like audio and documents, can be streamed and/or served from the app + * App is no longer gated. Reward authorization re-written. Added basic flows for new users. + * Videos now have a classy loading spinner + + +### Changed + * All UI strings are now rendered according to gettext standard, in prep for i18n + * Switched to new fee metadata format + + +### Fixed + * If a daemon is running but unresponsive, startup is no longer blocked indefinitely + * Updated deprecated LBRY API call signatures + * App scrolls to the top of the page on navigation + * Download progress works properly for purchased but deleted files + * Publish channels for less than 1 LBC + + + ## [0.11.9] - 2017-06-01 ### Fixed diff --git a/README.md b/README.md index b9196bc28..e446b747a 100644 --- a/README.md +++ b/README.md @@ -48,3 +48,7 @@ to create distributable packages, which is run by calling: This project has currently only been worked on in Linux and macOS. If you are on Windows, you can checkout out the build steps in [appveyor.yml](https://github.com/lbryio/lbry-app/blob/master/.appveyor.yml) and probably figure out something from there. + +## Internationalization + +If you want to help translating the lbry-app, you can copy the en.json file in /app/locales and modify the values while leaving the keys as their original English strings. An example for this would be: `"Skip": "Überspringen",` Translations should automatically show up in options. \ No newline at end of file diff --git a/app/main.js b/app/main.js index 889fa0402..85a0dd3c7 100644 --- a/app/main.js +++ b/app/main.js @@ -21,7 +21,13 @@ const VERSION_CHECK_INTERVAL = 30 * 60 * 1000; const LATEST_RELEASE_API_URL = 'https://api.github.com/repos/lbryio/lbry-app/releases/latest'; -let client = jayson.client.http('http://localhost:5279/lbryapi'); +let client = jayson.client.http({ + host: 'localhost', + port: 5279, + path: '/lbryapi', + timeout: 1000 +}); + // Keep a global reference of the window object, if you don't, the window will // be closed automatically when the JavaScript object is garbage collected. let win; diff --git a/app/package-lock.json b/app/package-lock.json new file mode 100644 index 000000000..a5eec6773 --- /dev/null +++ b/app/package-lock.json @@ -0,0 +1,1470 @@ +{ + "name": "LBRY", + "version": "0.12.0", + "lockfileVersion": 1, + "dependencies": { + "commander": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/commander/-/commander-1.3.2.tgz", + "integrity": "sha1-io8w7GcKb91kr1LxkUuQfXnq1bU=" + }, + "electron-dl": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/electron-dl/-/electron-dl-1.9.0.tgz", + "integrity": "sha1-HzBuMLblkLKWzihP+rFPGlREl8c=" + }, + "es6-promise": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-3.3.1.tgz", + "integrity": "sha1-oIzd6EzNvzTQJ6FFG8kdS80ophM=" + }, + "es6-promisify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-3.0.0.tgz", + "integrity": "sha1-IiJrkpVzF/llJH7f3pKV+D7+voY=" + }, + "eyes": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/eyes/-/eyes-0.1.8.tgz", + "integrity": "sha1-Ys8SAjTGg3hdkCNIqADvPgzCC8A=" + }, + "install": { + "version": "0.8.9", + "resolved": "https://registry.npmjs.org/install/-/install-0.8.9.tgz", + "integrity": "sha1-n0tcDRhR74cunfheT3Fi1OXc2+0=" + }, + "jayson": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/jayson/-/jayson-2.0.3.tgz", + "integrity": "sha1-3XULdOozQfOpj4dbQaNcrx1JSe0=" + }, + "json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" + }, + "jsonparse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.0.0.tgz", + "integrity": "sha1-JiL05mwI4arH7b63YFPJt+EhH3Y=" + }, + "JSONStream": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.0.3.tgz", + "integrity": "sha1-coVEGJQ4t7ndIYQ5JYGGHrq9liE=" + }, + "keypress": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/keypress/-/keypress-0.1.0.tgz", + "integrity": "sha1-SjGI1CkbZrT2XtuZ+AaqmuKTWSo=" + }, + "lodash": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.6.0.tgz", + "integrity": "sha1-Umao9J3Zib5Pn2gbbyoMVShdDZo=" + }, + "npm": { + "version": "4.6.1", + "resolved": "https://registry.npmjs.org/npm/-/npm-4.6.1.tgz", + "integrity": "sha1-+Osa0A3FilUUNjtBylNCgX8L1kY=", + "dependencies": { + "abbrev": { + "version": "1.1.0", + "bundled": true + }, + "ansi-regex": { + "version": "2.1.1", + "bundled": true + }, + "ansicolors": { + "version": "0.3.2", + "bundled": true + }, + "ansistyles": { + "version": "0.1.3", + "bundled": true + }, + "aproba": { + "version": "1.1.1", + "bundled": true + }, + "archy": { + "version": "1.0.0", + "bundled": true + }, + "asap": { + "version": "2.0.5", + "bundled": true + }, + "bluebird": { + "version": "3.5.0", + "bundled": true + }, + "call-limit": { + "version": "1.1.0", + "bundled": true + }, + "chownr": { + "version": "1.0.1", + "bundled": true + }, + "cmd-shim": { + "version": "2.0.2", + "bundled": true + }, + "columnify": { + "version": "1.5.4", + "bundled": true, + "dependencies": { + "wcwidth": { + "version": "1.0.0", + "bundled": true, + "dependencies": { + "defaults": { + "version": "1.0.3", + "bundled": true, + "dependencies": { + "clone": { + "version": "1.0.2", + "bundled": true + } + } + } + } + } + } + }, + "config-chain": { + "version": "1.1.11", + "bundled": true, + "dependencies": { + "proto-list": { + "version": "1.2.4", + "bundled": true + } + } + }, + "debuglog": { + "version": "1.0.1", + "bundled": true + }, + "dezalgo": { + "version": "1.0.3", + "bundled": true + }, + "editor": { + "version": "1.0.0", + "bundled": true + }, + "fs-vacuum": { + "version": "1.2.10", + "bundled": true + }, + "fs-write-stream-atomic": { + "version": "1.0.10", + "bundled": true + }, + "fstream": { + "version": "1.0.11", + "bundled": true + }, + "fstream-npm": { + "version": "1.2.0", + "bundled": true, + "dependencies": { + "fstream-ignore": { + "version": "1.0.5", + "bundled": true, + "dependencies": { + "minimatch": { + "version": "3.0.3", + "bundled": true, + "dependencies": { + "brace-expansion": { + "version": "1.1.6", + "bundled": true, + "dependencies": { + "balanced-match": { + "version": "0.4.2", + "bundled": true + }, + "concat-map": { + "version": "0.0.1", + "bundled": true + } + } + } + } + } + } + } + } + }, + "glob": { + "version": "7.1.1", + "bundled": true, + "dependencies": { + "fs.realpath": { + "version": "1.0.0", + "bundled": true + }, + "minimatch": { + "version": "3.0.3", + "bundled": true, + "dependencies": { + "brace-expansion": { + "version": "1.1.6", + "bundled": true, + "dependencies": { + "balanced-match": { + "version": "0.4.2", + "bundled": true + }, + "concat-map": { + "version": "0.0.1", + "bundled": true + } + } + } + } + }, + "path-is-absolute": { + "version": "1.0.1", + "bundled": true + } + } + }, + "graceful-fs": { + "version": "4.1.11", + "bundled": true + }, + "has-unicode": { + "version": "2.0.1", + "bundled": true + }, + "hosted-git-info": { + "version": "2.4.2", + "bundled": true + }, + "iferr": { + "version": "0.1.5", + "bundled": true + }, + "imurmurhash": { + "version": "0.1.4", + "bundled": true + }, + "inflight": { + "version": "1.0.6", + "bundled": true + }, + "inherits": { + "version": "2.0.3", + "bundled": true + }, + "ini": { + "version": "1.3.4", + "bundled": true + }, + "init-package-json": { + "version": "1.10.1", + "bundled": true, + "dependencies": { + "promzard": { + "version": "0.3.0", + "bundled": true + } + } + }, + "JSONStream": { + "version": "1.3.1", + "bundled": true, + "dependencies": { + "jsonparse": { + "version": "1.3.0", + "bundled": true + }, + "through": { + "version": "2.3.8", + "bundled": true + } + } + }, + "lazy-property": { + "version": "1.0.0", + "bundled": true + }, + "lockfile": { + "version": "1.0.3", + "bundled": true + }, + "lodash._baseindexof": { + "version": "3.1.0", + "bundled": true + }, + "lodash._baseuniq": { + "version": "4.6.0", + "bundled": true, + "dependencies": { + "lodash._createset": { + "version": "4.0.3", + "bundled": true + }, + "lodash._root": { + "version": "3.0.1", + "bundled": true + } + } + }, + "lodash._bindcallback": { + "version": "3.0.1", + "bundled": true + }, + "lodash._cacheindexof": { + "version": "3.0.2", + "bundled": true + }, + "lodash._createcache": { + "version": "3.1.2", + "bundled": true + }, + "lodash._getnative": { + "version": "3.9.1", + "bundled": true + }, + "lodash.clonedeep": { + "version": "4.5.0", + "bundled": true + }, + "lodash.restparam": { + "version": "3.6.1", + "bundled": true + }, + "lodash.union": { + "version": "4.6.0", + "bundled": true + }, + "lodash.uniq": { + "version": "4.5.0", + "bundled": true + }, + "lodash.without": { + "version": "4.4.0", + "bundled": true + }, + "mississippi": { + "version": "1.3.0", + "bundled": true, + "dependencies": { + "concat-stream": { + "version": "1.6.0", + "bundled": true, + "dependencies": { + "typedarray": { + "version": "0.0.6", + "bundled": true + } + } + }, + "duplexify": { + "version": "3.5.0", + "bundled": true, + "dependencies": { + "end-of-stream": { + "version": "1.0.0", + "bundled": true, + "dependencies": { + "once": { + "version": "1.3.3", + "bundled": true + } + } + }, + "stream-shift": { + "version": "1.0.0", + "bundled": true + } + } + }, + "end-of-stream": { + "version": "1.1.0", + "bundled": true, + "dependencies": { + "once": { + "version": "1.3.3", + "bundled": true + } + } + }, + "flush-write-stream": { + "version": "1.0.2", + "bundled": true + }, + "from2": { + "version": "2.3.0", + "bundled": true + }, + "parallel-transform": { + "version": "1.1.0", + "bundled": true, + "dependencies": { + "cyclist": { + "version": "0.2.2", + "bundled": true + } + } + }, + "pump": { + "version": "1.0.2", + "bundled": true + }, + "pumpify": { + "version": "1.3.5", + "bundled": true + }, + "stream-each": { + "version": "1.2.0", + "bundled": true, + "dependencies": { + "stream-shift": { + "version": "1.0.0", + "bundled": true + } + } + }, + "through2": { + "version": "2.0.3", + "bundled": true, + "dependencies": { + "xtend": { + "version": "4.0.1", + "bundled": true + } + } + } + } + }, + "mkdirp": { + "version": "0.5.1", + "bundled": true, + "dependencies": { + "minimist": { + "version": "0.0.8", + "bundled": true + } + } + }, + "move-concurrently": { + "version": "1.0.1", + "bundled": true, + "dependencies": { + "copy-concurrently": { + "version": "1.0.3", + "bundled": true + }, + "run-queue": { + "version": "1.0.3", + "bundled": true + } + } + }, + "node-gyp": { + "version": "3.6.0", + "bundled": true, + "dependencies": { + "minimatch": { + "version": "3.0.3", + "bundled": true, + "dependencies": { + "brace-expansion": { + "version": "1.1.6", + "bundled": true, + "dependencies": { + "balanced-match": { + "version": "0.4.2", + "bundled": true + }, + "concat-map": { + "version": "0.0.1", + "bundled": true + } + } + } + } + }, + "nopt": { + "version": "3.0.6", + "bundled": true + } + } + }, + "nopt": { + "version": "4.0.1", + "bundled": true, + "dependencies": { + "osenv": { + "version": "0.1.4", + "bundled": true, + "dependencies": { + "os-homedir": { + "version": "1.0.2", + "bundled": true + }, + "os-tmpdir": { + "version": "1.0.2", + "bundled": true + } + } + } + } + }, + "normalize-git-url": { + "version": "3.0.2", + "bundled": true + }, + "normalize-package-data": { + "version": "2.3.8", + "bundled": true, + "dependencies": { + "is-builtin-module": { + "version": "1.0.0", + "bundled": true, + "dependencies": { + "builtin-modules": { + "version": "1.1.1", + "bundled": true + } + } + } + } + }, + "npm-cache-filename": { + "version": "1.0.2", + "bundled": true + }, + "npm-install-checks": { + "version": "3.0.0", + "bundled": true + }, + "npm-package-arg": { + "version": "4.2.1", + "bundled": true + }, + "npm-registry-client": { + "version": "8.1.1", + "bundled": true, + "dependencies": { + "concat-stream": { + "version": "1.6.0", + "bundled": true, + "dependencies": { + "typedarray": { + "version": "0.0.6", + "bundled": true + } + } + } + } + }, + "npm-user-validate": { + "version": "0.1.5", + "bundled": true + }, + "npmlog": { + "version": "4.0.2", + "bundled": true, + "dependencies": { + "are-we-there-yet": { + "version": "1.1.4", + "bundled": true, + "dependencies": { + "delegates": { + "version": "1.0.0", + "bundled": true + } + } + }, + "console-control-strings": { + "version": "1.1.0", + "bundled": true + }, + "gauge": { + "version": "2.7.4", + "bundled": true, + "dependencies": { + "object-assign": { + "version": "4.1.1", + "bundled": true + }, + "signal-exit": { + "version": "3.0.2", + "bundled": true + }, + "string-width": { + "version": "1.0.2", + "bundled": true, + "dependencies": { + "code-point-at": { + "version": "1.1.0", + "bundled": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "bundled": true, + "dependencies": { + "number-is-nan": { + "version": "1.0.1", + "bundled": true + } + } + } + } + }, + "wide-align": { + "version": "1.1.0", + "bundled": true + } + } + }, + "set-blocking": { + "version": "2.0.0", + "bundled": true + } + } + }, + "once": { + "version": "1.4.0", + "bundled": true + }, + "opener": { + "version": "1.4.3", + "bundled": true + }, + "osenv": { + "version": "0.1.4", + "bundled": true, + "dependencies": { + "os-homedir": { + "version": "1.0.2", + "bundled": true + }, + "os-tmpdir": { + "version": "1.0.2", + "bundled": true + } + } + }, + "path-is-inside": { + "version": "1.0.2", + "bundled": true + }, + "read": { + "version": "1.0.7", + "bundled": true, + "dependencies": { + "mute-stream": { + "version": "0.0.5", + "bundled": true + } + } + }, + "read-cmd-shim": { + "version": "1.0.1", + "bundled": true + }, + "read-installed": { + "version": "4.0.3", + "bundled": true, + "dependencies": { + "util-extend": { + "version": "1.0.3", + "bundled": true + } + } + }, + "read-package-json": { + "version": "2.0.5", + "bundled": true, + "dependencies": { + "json-parse-helpfulerror": { + "version": "1.0.3", + "bundled": true, + "dependencies": { + "jju": { + "version": "1.3.0", + "bundled": true + } + } + } + } + }, + "read-package-tree": { + "version": "5.1.5", + "bundled": true + }, + "readable-stream": { + "version": "2.2.9", + "bundled": true, + "dependencies": { + "buffer-shims": { + "version": "1.0.0", + "bundled": true + }, + "core-util-is": { + "version": "1.0.2", + "bundled": true + }, + "isarray": { + "version": "1.0.0", + "bundled": true + }, + "process-nextick-args": { + "version": "1.0.7", + "bundled": true + }, + "string_decoder": { + "version": "1.0.0", + "bundled": true + }, + "util-deprecate": { + "version": "1.0.2", + "bundled": true + } + } + }, + "readdir-scoped-modules": { + "version": "1.0.2", + "bundled": true + }, + "realize-package-specifier": { + "version": "3.0.3", + "bundled": true + }, + "request": { + "version": "2.81.0", + "bundled": true, + "dependencies": { + "aws-sign2": { + "version": "0.6.0", + "bundled": true + }, + "aws4": { + "version": "1.6.0", + "bundled": true + }, + "caseless": { + "version": "0.12.0", + "bundled": true + }, + "combined-stream": { + "version": "1.0.5", + "bundled": true, + "dependencies": { + "delayed-stream": { + "version": "1.0.0", + "bundled": true + } + } + }, + "extend": { + "version": "3.0.0", + "bundled": true + }, + "forever-agent": { + "version": "0.6.1", + "bundled": true + }, + "form-data": { + "version": "2.1.2", + "bundled": true, + "dependencies": { + "asynckit": { + "version": "0.4.0", + "bundled": true + } + } + }, + "har-validator": { + "version": "4.2.1", + "bundled": true, + "dependencies": { + "ajv": { + "version": "4.11.4", + "bundled": true, + "dependencies": { + "co": { + "version": "4.6.0", + "bundled": true + }, + "json-stable-stringify": { + "version": "1.0.1", + "bundled": true, + "dependencies": { + "jsonify": { + "version": "0.0.0", + "bundled": true + } + } + } + } + }, + "har-schema": { + "version": "1.0.5", + "bundled": true + } + } + }, + "hawk": { + "version": "3.1.3", + "bundled": true, + "dependencies": { + "boom": { + "version": "2.10.1", + "bundled": true + }, + "cryptiles": { + "version": "2.0.5", + "bundled": true + }, + "hoek": { + "version": "2.16.3", + "bundled": true + }, + "sntp": { + "version": "1.0.9", + "bundled": true + } + } + }, + "http-signature": { + "version": "1.1.1", + "bundled": true, + "dependencies": { + "assert-plus": { + "version": "0.2.0", + "bundled": true + }, + "jsprim": { + "version": "1.3.1", + "bundled": true, + "dependencies": { + "extsprintf": { + "version": "1.0.2", + "bundled": true + }, + "json-schema": { + "version": "0.2.3", + "bundled": true + }, + "verror": { + "version": "1.3.6", + "bundled": true + } + } + }, + "sshpk": { + "version": "1.11.0", + "bundled": true, + "dependencies": { + "asn1": { + "version": "0.2.3", + "bundled": true + }, + "assert-plus": { + "version": "1.0.0", + "bundled": true + }, + "bcrypt-pbkdf": { + "version": "1.0.1", + "bundled": true, + "optional": true + }, + "dashdash": { + "version": "1.14.1", + "bundled": true + }, + "ecc-jsbn": { + "version": "0.1.1", + "bundled": true, + "optional": true + }, + "getpass": { + "version": "0.1.6", + "bundled": true + }, + "jodid25519": { + "version": "1.0.2", + "bundled": true, + "optional": true + }, + "jsbn": { + "version": "0.1.1", + "bundled": true, + "optional": true + }, + "tweetnacl": { + "version": "0.14.5", + "bundled": true, + "optional": true + } + } + } + } + }, + "is-typedarray": { + "version": "1.0.0", + "bundled": true + }, + "isstream": { + "version": "0.1.2", + "bundled": true + }, + "json-stringify-safe": { + "version": "5.0.1", + "bundled": true + }, + "mime-types": { + "version": "2.1.14", + "bundled": true, + "dependencies": { + "mime-db": { + "version": "1.26.0", + "bundled": true + } + } + }, + "oauth-sign": { + "version": "0.8.2", + "bundled": true + }, + "performance-now": { + "version": "0.2.0", + "bundled": true + }, + "qs": { + "version": "6.4.0", + "bundled": true + }, + "safe-buffer": { + "version": "5.0.1", + "bundled": true + }, + "stringstream": { + "version": "0.0.5", + "bundled": true + }, + "tough-cookie": { + "version": "2.3.2", + "bundled": true, + "dependencies": { + "punycode": { + "version": "1.4.1", + "bundled": true + } + } + }, + "tunnel-agent": { + "version": "0.6.0", + "bundled": true + } + } + }, + "retry": { + "version": "0.10.1", + "bundled": true + }, + "rimraf": { + "version": "2.6.1", + "bundled": true + }, + "semver": { + "version": "5.3.0", + "bundled": true + }, + "sha": { + "version": "2.0.1", + "bundled": true + }, + "slide": { + "version": "1.1.6", + "bundled": true + }, + "sorted-object": { + "version": "2.0.1", + "bundled": true + }, + "sorted-union-stream": { + "version": "2.1.3", + "bundled": true, + "dependencies": { + "from2": { + "version": "1.3.0", + "bundled": true, + "dependencies": { + "readable-stream": { + "version": "1.1.14", + "bundled": true, + "dependencies": { + "core-util-is": { + "version": "1.0.2", + "bundled": true + }, + "isarray": { + "version": "0.0.1", + "bundled": true + }, + "string_decoder": { + "version": "0.10.31", + "bundled": true + } + } + } + } + }, + "stream-iterate": { + "version": "1.1.1", + "bundled": true + } + } + }, + "strip-ansi": { + "version": "3.0.1", + "bundled": true + }, + "tar": { + "version": "2.2.1", + "bundled": true, + "dependencies": { + "block-stream": { + "version": "0.0.8", + "bundled": true + } + } + }, + "text-table": { + "version": "0.2.0", + "bundled": true + }, + "uid-number": { + "version": "0.0.6", + "bundled": true + }, + "umask": { + "version": "1.1.0", + "bundled": true + }, + "unique-filename": { + "version": "1.1.0", + "bundled": true, + "dependencies": { + "unique-slug": { + "version": "2.0.0", + "bundled": true + } + } + }, + "unpipe": { + "version": "1.0.0", + "bundled": true + }, + "update-notifier": { + "version": "2.1.0", + "bundled": true, + "dependencies": { + "boxen": { + "version": "1.0.0", + "bundled": true, + "dependencies": { + "ansi-align": { + "version": "1.1.0", + "bundled": true, + "dependencies": { + "string-width": { + "version": "1.0.2", + "bundled": true, + "dependencies": { + "code-point-at": { + "version": "1.1.0", + "bundled": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "bundled": true, + "dependencies": { + "number-is-nan": { + "version": "1.0.1", + "bundled": true + } + } + } + } + } + } + }, + "camelcase": { + "version": "4.0.0", + "bundled": true + }, + "cli-boxes": { + "version": "1.0.0", + "bundled": true + }, + "string-width": { + "version": "2.0.0", + "bundled": true, + "dependencies": { + "is-fullwidth-code-point": { + "version": "2.0.0", + "bundled": true + } + } + }, + "term-size": { + "version": "0.1.1", + "bundled": true, + "dependencies": { + "execa": { + "version": "0.4.0", + "bundled": true, + "dependencies": { + "cross-spawn-async": { + "version": "2.2.5", + "bundled": true, + "dependencies": { + "lru-cache": { + "version": "4.0.2", + "bundled": true, + "dependencies": { + "pseudomap": { + "version": "1.0.2", + "bundled": true + }, + "yallist": { + "version": "2.0.0", + "bundled": true + } + } + } + } + }, + "is-stream": { + "version": "1.1.0", + "bundled": true + }, + "npm-run-path": { + "version": "1.0.0", + "bundled": true + }, + "object-assign": { + "version": "4.1.1", + "bundled": true + }, + "path-key": { + "version": "1.0.0", + "bundled": true + }, + "strip-eof": { + "version": "1.0.0", + "bundled": true + } + } + } + } + }, + "widest-line": { + "version": "1.0.0", + "bundled": true, + "dependencies": { + "string-width": { + "version": "1.0.2", + "bundled": true, + "dependencies": { + "code-point-at": { + "version": "1.1.0", + "bundled": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "bundled": true, + "dependencies": { + "number-is-nan": { + "version": "1.0.1", + "bundled": true + } + } + } + } + } + } + } + } + }, + "chalk": { + "version": "1.1.3", + "bundled": true, + "dependencies": { + "ansi-styles": { + "version": "2.2.1", + "bundled": true + }, + "escape-string-regexp": { + "version": "1.0.5", + "bundled": true + }, + "has-ansi": { + "version": "2.0.0", + "bundled": true + }, + "supports-color": { + "version": "2.0.0", + "bundled": true + } + } + }, + "configstore": { + "version": "3.0.0", + "bundled": true, + "dependencies": { + "dot-prop": { + "version": "4.1.1", + "bundled": true, + "dependencies": { + "is-obj": { + "version": "1.0.1", + "bundled": true + } + } + }, + "unique-string": { + "version": "1.0.0", + "bundled": true, + "dependencies": { + "crypto-random-string": { + "version": "1.0.0", + "bundled": true + } + } + } + } + }, + "is-npm": { + "version": "1.0.0", + "bundled": true + }, + "latest-version": { + "version": "3.0.0", + "bundled": true, + "dependencies": { + "package-json": { + "version": "3.1.0", + "bundled": true, + "dependencies": { + "got": { + "version": "6.7.1", + "bundled": true, + "dependencies": { + "create-error-class": { + "version": "3.0.2", + "bundled": true, + "dependencies": { + "capture-stack-trace": { + "version": "1.0.0", + "bundled": true + } + } + }, + "duplexer3": { + "version": "0.1.4", + "bundled": true + }, + "get-stream": { + "version": "3.0.0", + "bundled": true + }, + "is-redirect": { + "version": "1.0.0", + "bundled": true + }, + "is-retry-allowed": { + "version": "1.1.0", + "bundled": true + }, + "is-stream": { + "version": "1.1.0", + "bundled": true + }, + "lowercase-keys": { + "version": "1.0.0", + "bundled": true + }, + "safe-buffer": { + "version": "5.0.1", + "bundled": true + }, + "timed-out": { + "version": "4.0.1", + "bundled": true + }, + "unzip-response": { + "version": "2.0.1", + "bundled": true + }, + "url-parse-lax": { + "version": "1.0.0", + "bundled": true, + "dependencies": { + "prepend-http": { + "version": "1.0.4", + "bundled": true + } + } + } + } + }, + "registry-auth-token": { + "version": "3.1.0", + "bundled": true, + "dependencies": { + "rc": { + "version": "1.1.7", + "bundled": true, + "dependencies": { + "deep-extend": { + "version": "0.4.1", + "bundled": true + }, + "minimist": { + "version": "1.2.0", + "bundled": true + }, + "strip-json-comments": { + "version": "2.0.1", + "bundled": true + } + } + } + } + }, + "registry-url": { + "version": "3.1.0", + "bundled": true, + "dependencies": { + "rc": { + "version": "1.1.7", + "bundled": true, + "dependencies": { + "deep-extend": { + "version": "0.4.1", + "bundled": true + }, + "minimist": { + "version": "1.2.0", + "bundled": true + }, + "strip-json-comments": { + "version": "2.0.1", + "bundled": true + } + } + } + } + } + } + } + } + }, + "lazy-req": { + "version": "2.0.0", + "bundled": true + }, + "semver-diff": { + "version": "2.1.0", + "bundled": true + }, + "xdg-basedir": { + "version": "3.0.0", + "bundled": true + } + } + }, + "uuid": { + "version": "3.0.1", + "bundled": true + }, + "validate-npm-package-license": { + "version": "3.0.1", + "bundled": true, + "dependencies": { + "spdx-correct": { + "version": "1.0.2", + "bundled": true, + "dependencies": { + "spdx-license-ids": { + "version": "1.2.0", + "bundled": true + } + } + }, + "spdx-expression-parse": { + "version": "1.0.2", + "bundled": true, + "dependencies": { + "spdx-exceptions": { + "version": "1.0.4", + "bundled": true + }, + "spdx-license-ids": { + "version": "1.2.0", + "bundled": true + } + } + } + } + }, + "validate-npm-package-name": { + "version": "3.0.0", + "bundled": true, + "dependencies": { + "builtins": { + "version": "1.0.3", + "bundled": true + } + } + }, + "which": { + "version": "1.2.14", + "bundled": true, + "dependencies": { + "isexe": { + "version": "2.0.0", + "bundled": true + } + } + }, + "wrappy": { + "version": "1.0.2", + "bundled": true + }, + "write-file-atomic": { + "version": "1.3.3", + "bundled": true + } + } + }, + "semver": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz", + "integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8=" + }, + "through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" + }, + "tree-kill": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.1.0.tgz", + "integrity": "sha1-yWPc8DciiS7FnLpWnpQLcZVNFyk=" + } + } +} diff --git a/app/package.json b/app/package.json index 824cb40a6..95261b0c2 100644 --- a/app/package.json +++ b/app/package.json @@ -1,6 +1,6 @@ { "name": "LBRY", - "version": "0.11.9", + "version": "0.12.0", "main": "main.js", "description": "LBRY is a fully decentralized, open-source protocol facilitating the discovery, access, and (sometimes) purchase of data.", "author": { diff --git a/build/DAEMON_URL b/build/DAEMON_URL index 11bffea34..5544239f9 100644 --- a/build/DAEMON_URL +++ b/build/DAEMON_URL @@ -1 +1 @@ -https://github.com/lbryio/lbry/releases/download/v0.10.3/lbrynet-daemon-v0.10.3-OSNAME.zip +https://github.com/lbryio/lbry/releases/download/v0.11.0/lbrynet-daemon-v0.11.0-OSNAME.zip diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 000000000..5f5e82c88 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,1764 @@ +{ + "lockfileVersion": 1, + "dependencies": { + "@types/node": { + "version": "7.0.29", + "resolved": "https://registry.npmjs.org/@types/node/-/node-7.0.29.tgz", + "integrity": "sha512-+8JrLZny/uR+d/jLK9eaV63buRM7X/gNzQk57q76NS4KNKLSKOmxJYFIlwuP2zDvA7wqZj05POPhSd9Z1hYQpQ==", + "dev": true + }, + "7zip-bin": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/7zip-bin/-/7zip-bin-2.1.0.tgz", + "integrity": "sha512-jgBTCcJ0gQedE9o8Jw+H/Gyq//EnQxmVpha7CdprIwzRSC81Uj37inHvPzv6jaZgZwkCcfho52rAaIFBrdbO7w==", + "dev": true + }, + "7zip-bin-linux": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/7zip-bin-linux/-/7zip-bin-linux-1.1.0.tgz", + "integrity": "sha512-BfW7XsUWNV/j723el3gGbiNWdmvLrnTB9VD0BondfCinxCwz4RQ60W4c3UxRpfHn1Q4Cn1o/DxYFmLMgHTEKqg==", + "dev": true, + "optional": true + }, + "7zip-bin-mac": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/7zip-bin-mac/-/7zip-bin-mac-1.0.1.tgz", + "integrity": "sha1-Pmh3i78JJq3GgVlCcHRQXUdVXAI=", + "dev": true, + "optional": true + }, + "7zip-bin-win": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/7zip-bin-win/-/7zip-bin-win-2.1.0.tgz", + "integrity": "sha512-7t8V+cGvZ0xUAuTLH1iDkrl+XVYWxlS3hHCvA6yELTcx2VwgMDNe4FdQlyKJRjO0PExn0sit8wD3PGaPKBpt2A==", + "dev": true, + "optional": true + }, + "ajv": { + "version": "4.11.8", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-4.11.8.tgz", + "integrity": "sha1-gv+wKynmYq5TvcIK8VlHcGc5xTY=", + "dev": true + }, + "ansi-align": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-1.1.0.tgz", + "integrity": "sha1-LwwWWIKXOa3V67FeawxuNCPwFro=", + "dev": true + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "argparse": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.9.tgz", + "integrity": "sha1-c9g7wmP4bpf4zE9rrhsOkKfSLIY=", + "dev": true + }, + "array-find-index": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz", + "integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=", + "dev": true + }, + "asar-electron-builder": { + "version": "0.13.5", + "resolved": "https://registry.npmjs.org/asar-electron-builder/-/asar-electron-builder-0.13.5.tgz", + "integrity": "sha1-TM1NEf18nTs8/8eC/ePe7Z75GvY=", + "dev": true, + "dependencies": { + "minimist": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", + "dev": true + }, + "mkdirp": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "dev": true + } + } + }, + "asn1": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz", + "integrity": "sha1-2sh4dxPJlmhJ/IGAd36+nB3fO4Y=", + "dev": true + }, + "assert-plus": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.2.0.tgz", + "integrity": "sha1-104bh+ev/A24qttwIfP+SBAasjQ=", + "dev": true + }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", + "dev": true + }, + "aws-sign2": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.6.0.tgz", + "integrity": "sha1-FDQt0428yU0OW4fXY81jYSwOeU8=", + "dev": true + }, + "aws4": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.6.0.tgz", + "integrity": "sha1-g+9cqGCysy5KDe7e6MdxudtXRx4=", + "dev": true + }, + "balanced-match": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.4.2.tgz", + "integrity": "sha1-yz8+PHMtwPAe5wtAPzAuYddwmDg=", + "dev": true + }, + "base64-js": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.2.0.tgz", + "integrity": "sha1-o5mS1yNYSBGYK+XikLtqU9hnAPE=", + "dev": true + }, + "bcrypt-pbkdf": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz", + "integrity": "sha1-Y7xdy2EzG5K8Bf1SiVPDNGKgb40=", + "dev": true, + "optional": true + }, + "bluebird": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.0.tgz", + "integrity": "sha1-eRQg1/VR7qKJdFOop3ZT+WYG1nw=", + "dev": true + }, + "bluebird-lst-c": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/bluebird-lst-c/-/bluebird-lst-c-1.0.6.tgz", + "integrity": "sha1-gfiB0T+d9wD2fVd/E0gLwy2Eu6k=", + "dev": true + }, + "boom": { + "version": "2.10.1", + "resolved": "https://registry.npmjs.org/boom/-/boom-2.10.1.tgz", + "integrity": "sha1-OciRjO/1eZ+D+UkqhI9iWt0Mdm8=", + "dev": true + }, + "boxen": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/boxen/-/boxen-0.6.0.tgz", + "integrity": "sha1-g2TUJIrDT/DvGy8r9JpsYM4NgbY=", + "dev": true + }, + "brace-expansion": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.7.tgz", + "integrity": "sha1-Pv/DxQ4ABTH7cg6v+A8K6O8jz1k=", + "dev": true + }, + "builtin-modules": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", + "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=", + "dev": true + }, + "camelcase": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", + "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=", + "dev": true + }, + "camelcase-keys": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz", + "integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=", + "dev": true + }, + "capture-stack-trace": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/capture-stack-trace/-/capture-stack-trace-1.0.0.tgz", + "integrity": "sha1-Sm+gc5nCa7pH8LJJa00PtAjFVQ0=", + "dev": true + }, + "caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true + }, + "chromium-pickle-js": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/chromium-pickle-js/-/chromium-pickle-js-0.2.0.tgz", + "integrity": "sha1-BKEGZywYsIWrd02YPfo+oTjyIgU=", + "dev": true + }, + "ci-info": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-1.0.0.tgz", + "integrity": "sha1-3FKF8rTiUYIWg2gcOBwziPRuxTQ=", + "dev": true + }, + "cli-boxes": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-1.0.0.tgz", + "integrity": "sha1-T6kXw+WclKAEzWH47lCdplFocUM=", + "dev": true + }, + "cliui": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", + "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", + "dev": true + }, + "co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", + "dev": true + }, + "code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", + "dev": true + }, + "color-convert": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-0.5.3.tgz", + "integrity": "sha1-vbbGnOZg+t/+CwAHzER+G59ygr0=", + "dev": true + }, + "combined-stream": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.5.tgz", + "integrity": "sha1-k4NwpXtKUd6ix3wV1cX9+JUWQAk=", + "dev": true + }, + "commander": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.9.0.tgz", + "integrity": "sha1-nJkJQXbhIkDLItbFFGCYQA/g99Q=", + "dev": true + }, + "compare-version": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/compare-version/-/compare-version-0.1.2.tgz", + "integrity": "sha1-AWLsLZNR9d3VmpICy6k1NmpyUIA=", + "dev": true + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "concat-stream": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.0.tgz", + "integrity": "sha1-CqxmL9Ur54lk1VMvaUeE5wEQrPc=", + "dev": true, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "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==", + "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=", + "dev": true + }, + "string_decoder": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.2.tgz", + "integrity": "sha1-sp4fThEl+pehA4K4pTNze3SR4Xk=", + "dev": true + } + } + }, + "configstore": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/configstore/-/configstore-2.1.0.tgz", + "integrity": "sha1-c3o6cDbpiGECqmCZ5HuzOrGroaE=", + "dev": true, + "dependencies": { + "uuid": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-2.0.3.tgz", + "integrity": "sha1-Z+LoY3lyFVMN/zGOW/nc6/1Hsho=", + "dev": true + } + } + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", + "dev": true + }, + "create-error-class": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/create-error-class/-/create-error-class-3.0.2.tgz", + "integrity": "sha1-Br56vvlHo/FKMP1hBnHUAbyot7Y=", + "dev": true + }, + "cryptiles": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-2.0.5.tgz", + "integrity": "sha1-O9/s3GCBR8HGcgL6KR59ylnqo7g=", + "dev": true + }, + "cuint": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/cuint/-/cuint-0.2.2.tgz", + "integrity": "sha1-QICG1AlVDCYxFVYZ6fp7ytw7mRs=", + "dev": true + }, + "currently-unhandled": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz", + "integrity": "sha1-mI3zP+qxke95mmE2nddsF635V+o=", + "dev": true + }, + "dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "dev": true, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "dev": true + } + } + }, + "debug": { + "version": "2.6.8", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.8.tgz", + "integrity": "sha1-5zFTHKLt4n0YgiJCfaF4IdaP9Pw=", + "dev": true + }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "dev": true + }, + "deep-extend": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.4.2.tgz", + "integrity": "sha1-SLaZwn4zS/ifEIkr5DL25MfTSn8=", + "dev": true + }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", + "dev": true + }, + "dot-prop": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-3.0.0.tgz", + "integrity": "sha1-G3CK8JSknJoOfbyteQq6U52sEXc=", + "dev": true + }, + "duplexer2": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", + "integrity": "sha1-ixLauHjA1p4+eJEFFmKjL8a93ME=", + "dev": true, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "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==", + "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=", + "dev": true + }, + "string_decoder": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.2.tgz", + "integrity": "sha1-sp4fThEl+pehA4K4pTNze3SR4Xk=", + "dev": true + } + } + }, + "ecc-jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz", + "integrity": "sha1-D8c6ntXw1Tw4GTOYUj735UN3dQU=", + "dev": true, + "optional": true + }, + "electron": { + "version": "1.6.10", + "resolved": "https://registry.npmjs.org/electron/-/electron-1.6.10.tgz", + "integrity": "sha1-Twuc1ZbjVwC1cSj5iMwdLOZ+VnE=", + "dev": true + }, + "electron-builder": { + "version": "11.7.0", + "resolved": "https://registry.npmjs.org/electron-builder/-/electron-builder-11.7.0.tgz", + "integrity": "sha1-1SkS9uhKxSoGXeGXqS3vkxvZ3CU=", + "dev": true, + "dependencies": { + "electron-download-tf": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/electron-download-tf/-/electron-download-tf-3.1.0.tgz", + "integrity": "sha1-xtYsDgpMY7ZylfV7a2ZRTBO47Y0=", + "dev": true + }, + "fs-extra": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-1.0.0.tgz", + "integrity": "sha1-zTzl9+fLYUWIP8rjGR6Yd/hYeVA=", + "dev": true + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true + }, + "tunnel-agent": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.4.3.tgz", + "integrity": "sha1-Y3PbdpCf5XDgjXNYM2Xtgop07us=", + "dev": true + } + } + }, + "electron-builder-core": { + "version": "11.2.1", + "resolved": "https://registry.npmjs.org/electron-builder-core/-/electron-builder-core-11.2.1.tgz", + "integrity": "sha1-HcqMGhzui1F1C3cIoEkTrv+s+Kg=", + "dev": true + }, + "electron-builder-http": { + "version": "11.5.0", + "resolved": "https://registry.npmjs.org/electron-builder-http/-/electron-builder-http-11.5.0.tgz", + "integrity": "sha1-t3OWY0kDREMp7aO7zQIyFEDgYDg=", + "dev": true, + "dependencies": { + "debug": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.0.tgz", + "integrity": "sha1-vFlryr52F/Edn6FTYe3tVgi4SZs=", + "dev": true + }, + "ms": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.2.tgz", + "integrity": "sha1-riXPJRKziFodldfwN4aNhDESR2U=", + "dev": true + } + } + }, + "electron-builder-util": { + "version": "11.6.1", + "resolved": "https://registry.npmjs.org/electron-builder-util/-/electron-builder-util-11.6.1.tgz", + "integrity": "sha1-D1VvZ6cOTI11GFVp7yp1ZtsBXsw=", + "dev": true, + "dependencies": { + "debug": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.0.tgz", + "integrity": "sha1-vFlryr52F/Edn6FTYe3tVgi4SZs=", + "dev": true + }, + "ms": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.2.tgz", + "integrity": "sha1-riXPJRKziFodldfwN4aNhDESR2U=", + "dev": true + } + } + }, + "electron-debug": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/electron-debug/-/electron-debug-1.1.0.tgz", + "integrity": "sha1-BQqcP5Bv/8JJJRDPisMdDzKleeE=", + "dev": true + }, + "electron-download": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/electron-download/-/electron-download-3.3.0.tgz", + "integrity": "sha1-LP1U1pZsAZxNSa1l++Zcyc3vaMg=", + "dev": true + }, + "electron-is-dev": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/electron-is-dev/-/electron-is-dev-0.1.2.tgz", + "integrity": "sha1-ihBD4ys6HaHD9VPc4oznZCRhZ+M=", + "dev": true + }, + "electron-localshortcut": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/electron-localshortcut/-/electron-localshortcut-0.6.1.tgz", + "integrity": "sha1-xOJow4puQvQN5WGPyQbR7WCPEao=", + "dev": true + }, + "electron-macos-sign": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/electron-macos-sign/-/electron-macos-sign-1.5.0.tgz", + "integrity": "sha1-/jqKy3VbX1aPH+FE6eZs7kQBlEg=", + "dev": true + }, + "error-ex": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.1.tgz", + "integrity": "sha1-+FWobOYa3E6GIcPNoh56dhLDqNw=", + "dev": true + }, + "es6-promise": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.1.0.tgz", + "integrity": "sha1-3aA8qPn4m8WX5omEKSnee6jOvfA=", + "dev": true + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, + "esprima": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-3.1.3.tgz", + "integrity": "sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM=", + "dev": true + }, + "extend": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", + "integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ=", + "dev": true + }, + "extract-zip": { + "version": "1.6.5", + "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-1.6.5.tgz", + "integrity": "sha1-maBnNbbqIOqbcF13ms/8yHz/BEA=", + "dev": true, + "dependencies": { + "debug": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", + "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", + "dev": true + }, + "ms": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", + "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", + "dev": true + } + } + }, + "extsprintf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.0.2.tgz", + "integrity": "sha1-4QgOBljjALBilJkMxw4VAiNf1VA=", + "dev": true + }, + "fd-slicer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.0.1.tgz", + "integrity": "sha1-i1vL2ewyfFBBv5qwI/1nUPEXfmU=", + "dev": true + }, + "filled-array": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/filled-array/-/filled-array-1.1.0.tgz", + "integrity": "sha1-w8T2xmO5I0WamqKZEtLQMfFQf4Q=", + "dev": true + }, + "find-up": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", + "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", + "dev": true + }, + "forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", + "dev": true + }, + "form-data": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.1.4.tgz", + "integrity": "sha1-M8GDrPGTJ27KqYFDpp6Uv+4XUNE=", + "dev": true + }, + "fs-extra": { + "version": "0.30.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-0.30.0.tgz", + "integrity": "sha1-8jP/zAjU2n1DLapEl3aYnbHfk/A=", + "dev": true + }, + "fs-extra-p": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/fs-extra-p/-/fs-extra-p-3.1.0.tgz", + "integrity": "sha1-7d97uNk4XXkBTeyyH0Wx0MV5ANM=", + "dev": true, + "dependencies": { + "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.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "get-caller-file": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.2.tgz", + "integrity": "sha1-9wLmMSfn4jHBYKgMFVSstw1QR+U=", + "dev": true + }, + "get-stdin": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", + "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=", + "dev": true + }, + "getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "dev": true, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "dev": true + } + } + }, + "glob": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "dev": true + }, + "got": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/got/-/got-5.7.1.tgz", + "integrity": "sha1-X4FjWmHkplifGAVp6k44FoClHzU=", + "dev": true, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "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==", + "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=", + "dev": true + }, + "string_decoder": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.2.tgz", + "integrity": "sha1-sp4fThEl+pehA4K4pTNze3SR4Xk=", + "dev": true + } + } + }, + "graceful-fs": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", + "dev": true + }, + "graceful-readlink": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz", + "integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=", + "dev": true + }, + "har-schema": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-1.0.5.tgz", + "integrity": "sha1-0mMTX0MwfALGAq/I/pWXDAFRNp4=", + "dev": true + }, + "har-validator": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-4.2.1.tgz", + "integrity": "sha1-M0gdDxu/9gDdID11gSpqX7oALio=", + "dev": true + }, + "has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", + "dev": true + }, + "hawk": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/hawk/-/hawk-3.1.3.tgz", + "integrity": "sha1-B4REvXwWQLD+VA0sm3PVlnjo4cQ=", + "dev": true + }, + "hoek": { + "version": "2.16.3", + "resolved": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz", + "integrity": "sha1-ILt0A9POo5jpHcRxCo/xuCdKJe0=", + "dev": true + }, + "home-path": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/home-path/-/home-path-1.0.5.tgz", + "integrity": "sha1-eIspgVsS1Tus9XVkhHbm+QQdEz8=", + "dev": true + }, + "hosted-git-info": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.4.2.tgz", + "integrity": "sha1-AHa59GonBQbduq6lZJaJdGBhKmc=", + "dev": true + }, + "http-signature": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.1.1.tgz", + "integrity": "sha1-33LiZwZs0Kxn+3at+OE0qPvPkb8=", + "dev": true + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", + "dev": true + }, + "indent-string": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz", + "integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=", + "dev": true + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + }, + "ini": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.4.tgz", + "integrity": "sha1-BTfLedr1m1mhpRff9wbIbsA5Fi4=", + "dev": true + }, + "invert-kv": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", + "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=", + "dev": true + }, + "is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", + "dev": true + }, + "is-builtin-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz", + "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=", + "dev": true + }, + "is-ci": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-1.0.10.tgz", + "integrity": "sha1-9zkzayYyNlBhqdSCcM1WrjNpMY4=", + "dev": true + }, + "is-finite": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.2.tgz", + "integrity": "sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko=", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "dev": true + }, + "is-npm": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-npm/-/is-npm-1.0.0.tgz", + "integrity": "sha1-8vtjpl5JBbQGyGBydloaTceTufQ=", + "dev": true + }, + "is-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", + "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=", + "dev": true + }, + "is-redirect": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-redirect/-/is-redirect-1.0.0.tgz", + "integrity": "sha1-HQPd7VO9jbDzDCbk+V02/HyH3CQ=", + "dev": true + }, + "is-retry-allowed": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-retry-allowed/-/is-retry-allowed-1.1.0.tgz", + "integrity": "sha1-EaBgVotnM5REAz0BJaYaINVk+zQ=", + "dev": true + }, + "is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", + "dev": true + }, + "is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", + "dev": true + }, + "is-utf8": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", + "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", + "dev": true + }, + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "isbinaryfile": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-3.0.2.tgz", + "integrity": "sha1-Sj6XTsDLqQBNP8bN5yCeppNopiE=", + "dev": true + }, + "isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", + "dev": true + }, + "js-yaml": { + "version": "3.8.4", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.8.4.tgz", + "integrity": "sha1-UgtFZPhlc7qWZir4Woyvp7S1pvY=", + "dev": true + }, + "jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", + "dev": true, + "optional": true + }, + "json-schema": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", + "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=", + "dev": true + }, + "json-stable-stringify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz", + "integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=", + "dev": true + }, + "json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", + "dev": true + }, + "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", + "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=", + "dev": true + }, + "jsprim": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.0.tgz", + "integrity": "sha1-o7h+QCmNjDgFUtjMdiigu5WiKRg=", + "dev": true, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "dev": true + } + } + }, + "klaw": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/klaw/-/klaw-1.3.1.tgz", + "integrity": "sha1-QIhDO0azsbolnXh4XY6W9zugJDk=", + "dev": true + }, + "latest-version": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-2.0.0.tgz", + "integrity": "sha1-VvjWE5YghHuAF/jx9NeOIRMkFos=", + "dev": true + }, + "lazy-req": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/lazy-req/-/lazy-req-1.1.0.tgz", + "integrity": "sha1-va6+rTD42CQDnODOFJ1Nqge6H6w=", + "dev": true + }, + "lcid": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", + "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", + "dev": true + }, + "load-json-file": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", + "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", + "dev": true + }, + "lodash": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.12.0.tgz", + "integrity": "sha1-K9bcRqBA9Z5obJcu0h2T3FkFMlg=", + "dev": true + }, + "loud-rejection": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz", + "integrity": "sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=", + "dev": true + }, + "lowercase-keys": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.0.tgz", + "integrity": "sha1-TjNms55/VFfjXxMkvfb4jQv8cwY=", + "dev": true + }, + "macaddress": { + "version": "0.2.8", + "resolved": "https://registry.npmjs.org/macaddress/-/macaddress-0.2.8.tgz", + "integrity": "sha1-WQTcU3w57G2+/q6QIycTX6hRHxI=", + "dev": true + }, + "map-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", + "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=", + "dev": true + }, + "meow": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz", + "integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=", + "dev": true + }, + "mime": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.3.6.tgz", + "integrity": "sha1-WR2E02U6awtKO5343lqoEI5y5eA=", + "dev": true + }, + "mime-db": { + "version": "1.27.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.27.0.tgz", + "integrity": "sha1-gg9XIpa70g7CXtVeW13oaeVDbrE=", + "dev": true + }, + "mime-types": { + "version": "2.1.15", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.15.tgz", + "integrity": "sha1-pOv1BkCUVpI3uM9wBGd20J/JKu0=", + "dev": true + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true + }, + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + }, + "mkdirp": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.0.tgz", + "integrity": "sha1-HXMHam35hs2TROFecfzAWkyavxI=", + "dev": true, + "dependencies": { + "minimist": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", + "dev": true + } + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "node-emoji": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/node-emoji/-/node-emoji-1.5.1.tgz", + "integrity": "sha1-/ZGOQSdpv4xEgFEjgjOECyr/FqE=", + "dev": true + }, + "node-status-codes": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/node-status-codes/-/node-status-codes-1.0.0.tgz", + "integrity": "sha1-WuVUHQJGRdMqWPzdyc7s6nrjrC8=", + "dev": true + }, + "normalize-package-data": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.3.8.tgz", + "integrity": "sha1-2Bntoqne29H/pWPqQHHZNngilbs=", + "dev": true + }, + "nugget": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/nugget/-/nugget-2.0.1.tgz", + "integrity": "sha1-IBCVpIfhrTYIGzQy+jytpPjQcbA=", + "dev": true + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", + "dev": true + }, + "oauth-sign": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz", + "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=", + "dev": true + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "dev": true + }, + "object-keys": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-0.4.0.tgz", + "integrity": "sha1-KKaq50KN0sOpLz2V8hM13SBOAzY=", + "dev": true + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true + }, + "os-homedir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", + "dev": true + }, + "os-locale": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", + "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", + "dev": true + }, + "os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", + "dev": true + }, + "osenv": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.4.tgz", + "integrity": "sha1-Qv5tWVPfBsgGS+bxdsPQWqqjRkQ=", + "dev": true + }, + "package-json": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/package-json/-/package-json-2.4.0.tgz", + "integrity": "sha1-DRW9Z9HLvduyyiIv8u24a8sxqLs=", + "dev": true + }, + "parse-color": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/parse-color/-/parse-color-1.0.0.tgz", + "integrity": "sha1-e3SLlag/A/FqlPU15S1/PZRlhhk=", + "dev": true + }, + "parse-json": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", + "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", + "dev": true + }, + "path-exists": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", + "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", + "dev": true + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true + }, + "path-type": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", + "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", + "dev": true + }, + "pend": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", + "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=", + "dev": true + }, + "performance-now": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-0.2.0.tgz", + "integrity": "sha1-M+8wxcd9TqIcWlOGnZG1bY8lVeU=", + "dev": true + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + }, + "pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", + "dev": true + }, + "pinkie-promise": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", + "dev": true + }, + "plist": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/plist/-/plist-2.1.0.tgz", + "integrity": "sha1-V8zbeggh3yGDEhejytVOPhRqECU=", + "dev": true + }, + "prepend-http": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-1.0.4.tgz", + "integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=", + "dev": true + }, + "pretty-bytes": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-1.0.4.tgz", + "integrity": "sha1-CiLoIQYJrTVUL4yNXSFZr/B1HIQ=", + "dev": true + }, + "process-nextick-args": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", + "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=", + "dev": true + }, + "progress": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/progress/-/progress-1.1.8.tgz", + "integrity": "sha1-4mDHj2Fhzdmw5WzD4Khd4Xx6V74=", + "dev": true + }, + "progress-stream": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/progress-stream/-/progress-stream-1.2.0.tgz", + "integrity": "sha1-LNPP6jO6OonJwSHsM0er6asSX3c=", + "dev": true + }, + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", + "dev": true + }, + "qs": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.4.0.tgz", + "integrity": "sha1-E+JtKK1rD/qpExLNO/cI7TUecjM=", + "dev": true + }, + "rc": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.1.tgz", + "integrity": "sha1-LgPo5C7kULjLPc5lvhv4l04d/ZU=", + "dev": true + }, + "read-all-stream": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/read-all-stream/-/read-all-stream-3.1.0.tgz", + "integrity": "sha1-NcPhd/IHjveJ7kv6+kNzB06u9Po=", + "dev": true, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "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==", + "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=", + "dev": true + }, + "string_decoder": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.2.tgz", + "integrity": "sha1-sp4fThEl+pehA4K4pTNze3SR4Xk=", + "dev": true + } + } + }, + "read-pkg": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", + "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", + "dev": true + }, + "read-pkg-up": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", + "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", + "dev": true + }, + "readable-stream": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "dev": true + }, + "redent": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz", + "integrity": "sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94=", + "dev": true + }, + "registry-auth-token": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-3.3.1.tgz", + "integrity": "sha1-+w0yie4Nmtosu1KvXf5mywcNMAY=", + "dev": true + }, + "registry-url": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-3.1.0.tgz", + "integrity": "sha1-PU74cPc93h138M+aOBQyRE4XSUI=", + "dev": true + }, + "repeating": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz", + "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=", + "dev": true + }, + "request": { + "version": "2.81.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.81.0.tgz", + "integrity": "sha1-xpKJRqDgbF+Nb4qTM0af/aRimKA=", + "dev": true + }, + "require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", + "dev": true + }, + "require-main-filename": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", + "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=", + "dev": true + }, + "rimraf": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.1.tgz", + "integrity": "sha1-wjOOxkPfeht/5cVPqG9XQopV8z0=", + "dev": true + }, + "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 + }, + "sanitize-filename": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/sanitize-filename/-/sanitize-filename-1.6.1.tgz", + "integrity": "sha1-YS2hyWRz+gLczaktzVtKsWSmdyo=", + "dev": true + }, + "semver": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz", + "integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8=", + "dev": true + }, + "semver-diff": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/semver-diff/-/semver-diff-2.1.0.tgz", + "integrity": "sha1-S7uEN8jTfksM8aaP1ybsbWRdbTY=", + "dev": true + }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", + "dev": true + }, + "signal-exit": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", + "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", + "dev": true + }, + "single-line-log": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/single-line-log/-/single-line-log-1.1.2.tgz", + "integrity": "sha1-wvg/Jzo+GhbtsJlWYdoO1e8DM2Q=", + "dev": true + }, + "slide": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/slide/-/slide-1.1.6.tgz", + "integrity": "sha1-VusCfWW00tzmyy4tMsTUr8nh1wc=", + "dev": true + }, + "sntp": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/sntp/-/sntp-1.0.9.tgz", + "integrity": "sha1-ZUEYTMkK7qbG57NeJlkIJEPGYZg=", + "dev": true + }, + "source-map": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.6.tgz", + "integrity": "sha1-dc449SvwczxafwwRjYEzSiu19BI=", + "dev": true + }, + "source-map-support": { + "version": "0.4.15", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.15.tgz", + "integrity": "sha1-AyAt9lwG0r2MfsI2KhkwVv7407E=", + "dev": true + }, + "spdx-correct": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-1.0.2.tgz", + "integrity": "sha1-SzBz2TP/UfORLwOsVRlJikFQ20A=", + "dev": true + }, + "spdx-expression-parse": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-1.0.4.tgz", + "integrity": "sha1-m98vIOH0DtRH++JzJmGR/O1RYmw=", + "dev": true + }, + "spdx-license-ids": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-1.2.2.tgz", + "integrity": "sha1-yd96NCRZSt5r0RkA1ZZpbcBrrFc=", + "dev": true + }, + "speedometer": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/speedometer/-/speedometer-0.1.4.tgz", + "integrity": "sha1-mHbb0qFp0xFUAtSObqYynIgWpQ0=", + "dev": true + }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", + "dev": true + }, + "sshpk": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.13.1.tgz", + "integrity": "sha1-US322mKHFEMW3EwY/hzx2UBzm+M=", + "dev": true, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "dev": true + } + } + }, + "stat-mode": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/stat-mode/-/stat-mode-0.2.2.tgz", + "integrity": "sha1-5sgLYjEj19gM8TLOU480YokHJQI=", + "dev": true + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true + }, + "string.prototype.codepointat": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/string.prototype.codepointat/-/string.prototype.codepointat-0.2.0.tgz", + "integrity": "sha1-aybpvTr8qnvjtCabUm3huCAArHg=", + "dev": true + }, + "stringstream": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz", + "integrity": "sha1-TkhM1N5aC7vuGORjB3EKioFiGHg=", + "dev": true + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true + }, + "strip-bom": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", + "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", + "dev": true + }, + "strip-indent": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz", + "integrity": "sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=", + "dev": true + }, + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", + "dev": true + }, + "sumchecker": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/sumchecker/-/sumchecker-1.3.1.tgz", + "integrity": "sha1-ebs7RFbdBPGOvbwNcDodHa7FEF0=", + "dev": true + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + }, + "throttleit": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/throttleit/-/throttleit-0.0.2.tgz", + "integrity": "sha1-z+34jmDADdlpe2H90qg0OptoDq8=", + "dev": true + }, + "through2": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/through2/-/through2-0.2.3.tgz", + "integrity": "sha1-6zKE2k6jEbbMis42U3SKUqvyWj8=", + "dev": true + }, + "timed-out": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/timed-out/-/timed-out-3.1.3.tgz", + "integrity": "sha1-lYYL/MXHbCd/j4Mm/Q9bLiDrohc=", + "dev": true + }, + "tough-cookie": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.2.tgz", + "integrity": "sha1-8IH3bkyFcg5sN6X6ztc3FQ2EByo=", + "dev": true + }, + "trim-newlines": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz", + "integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM=", + "dev": true + }, + "truncate-utf8-bytes": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/truncate-utf8-bytes/-/truncate-utf8-bytes-1.0.2.tgz", + "integrity": "sha1-QFkjkJWS1W94pYGENLC3hInKXys=", + "dev": true + }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "dev": true + }, + "tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", + "dev": true, + "optional": true + }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", + "dev": true + }, + "unzip-response": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/unzip-response/-/unzip-response-1.0.2.tgz", + "integrity": "sha1-uYTwh3/AqJwsdzzB73tbIytbBv4=", + "dev": true + }, + "update-notifier": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-1.0.3.tgz", + "integrity": "sha1-j5LFFUgr1oMbfJMBPnD4dVLHz1o=", + "dev": true + }, + "url-parse-lax": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-1.0.0.tgz", + "integrity": "sha1-evjzA2Rem9eaJy56FKxovAYJ2nM=", + "dev": true + }, + "utf8-byte-length": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/utf8-byte-length/-/utf8-byte-length-1.0.4.tgz", + "integrity": "sha1-9F8VDExm7uloGGUFq5P8u4rWv2E=", + "dev": true + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "dev": true + }, + "uuid": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.0.1.tgz", + "integrity": "sha1-ZUS7ot/ajBzxfmKaOjBeK7H+5sE=", + "dev": true + }, + "uuid-1345": { + "version": "0.99.6", + "resolved": "https://registry.npmjs.org/uuid-1345/-/uuid-1345-0.99.6.tgz", + "integrity": "sha1-sScK4BWnchx63sbEbsFpxgmK7UA=", + "dev": true + }, + "validate-npm-package-license": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.1.tgz", + "integrity": "sha1-KAS6vnEq0zeUWaz74kdGqywwP7w=", + "dev": true + }, + "verror": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.3.6.tgz", + "integrity": "sha1-z/XfEpRtKX0rqu+qJoniW+AcAFw=", + "dev": true + }, + "which-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz", + "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=", + "dev": true + }, + "why-did-you-update": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/why-did-you-update/-/why-did-you-update-0.0.8.tgz", + "integrity": "sha1-OJ2X3WwUfh7byfXVRw1E2YXIrjg=", + "dev": true + }, + "widest-line": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-1.0.0.tgz", + "integrity": "sha1-DAnIXCqUaD0Nfq+O4JfVZL8OEFw=", + "dev": true + }, + "wrap-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", + "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", + "dev": true + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + }, + "write-file-atomic": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-1.3.4.tgz", + "integrity": "sha1-+Aek8LHZ6ROuekgRLmzDrxmRtF8=", + "dev": true + }, + "xdg-basedir": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-2.0.0.tgz", + "integrity": "sha1-7byQPMOF/ARSPZZqM1UEtVBNG9I=", + "dev": true + }, + "xmlbuilder": { + "version": "8.2.2", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-8.2.2.tgz", + "integrity": "sha1-aSSGc0ELS6QuGmE2VR0pIjNap3M=", + "dev": true + }, + "xmldom": { + "version": "0.1.27", + "resolved": "https://registry.npmjs.org/xmldom/-/xmldom-0.1.27.tgz", + "integrity": "sha1-1QH5ezvbQDr4757MIFcxh6rawOk=", + "dev": true + }, + "xtend": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-2.1.2.tgz", + "integrity": "sha1-bv7MKk2tjmlixJAbM3znuoe10os=", + "dev": true + }, + "y18n": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", + "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=", + "dev": true + }, + "yargs": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-6.6.0.tgz", + "integrity": "sha1-eC7CHvQDNF+DCoCMo9UTr1YGUgg=", + "dev": true, + "dependencies": { + "camelcase": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", + "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=", + "dev": true + } + } + }, + "yargs-parser": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-4.2.1.tgz", + "integrity": "sha1-KczqwNxPA8bIe0qfIX3RjJ90hxw=", + "dev": true, + "dependencies": { + "camelcase": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", + "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=", + "dev": true + } + } + }, + "yauzl": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.4.1.tgz", + "integrity": "sha1-lSj0QtqxsihOWLQ3m7GU4i4MQAU=", + "dev": true + } + } +} diff --git a/package.json b/package.json index bcdf0aacb..0d7c8eea1 100644 --- a/package.json +++ b/package.json @@ -32,11 +32,15 @@ }, "backgroundColor": "155B4A" }, - "protocols": [{ - "name": "lbry", - "role": "Viewer", - "schemes": ["lbry"] - }], + "protocols": [ + { + "name": "lbry", + "role": "Viewer", + "schemes": [ + "lbry" + ] + } + ], "linux": { "target": "deb", "desktop": { diff --git a/ui/js/actions/app.js b/ui/js/actions/app.js index bf0451c82..8609e1e3d 100644 --- a/ui/js/actions/app.js +++ b/ui/js/actions/app.js @@ -1,5 +1,5 @@ -import * as types from 'constants/action_types' -import lbry from 'lbry' +import * as types from "constants/action_types"; +import lbry from "lbry"; import { selectUpdateUrl, selectUpgradeDownloadPath, @@ -8,36 +8,34 @@ import { selectPageTitle, selectCurrentPage, selectCurrentParams, -} from 'selectors/app' -import { - doSearch, -} from 'actions/search' +} from "selectors/app"; +import { doSearch } from "actions/search"; +import { doFetchDaemonSettings } from "actions/settings"; +import { doAuthenticate } from "actions/user"; +import { doRewardList } from "actions/rewards"; +import { doFileList } from "actions/file_info"; -const {remote, ipcRenderer, shell} = require('electron'); -const path = require('path'); -const app = require('electron').remote.app; -const {download} = remote.require('electron-dl'); -const fs = remote.require('fs'); +const { remote, ipcRenderer, shell } = require("electron"); +const path = require("path"); +const app = require("electron").remote.app; +const { download } = remote.require("electron-dl"); +const fs = remote.require("fs"); -const queryStringFromParams = (params) => { - return Object - .keys(params) - .map(key => `${key}=${params[key]}`) - .join('&') -} +const queryStringFromParams = params => { + return Object.keys(params).map(key => `${key}=${params[key]}`).join("&"); +}; export function doNavigate(path, params = {}) { return function(dispatch, getState) { - let url = path - if (params) - url = `${url}?${queryStringFromParams(params)}` + let url = path; + if (params) url = `${url}?${queryStringFromParams(params)}`; - dispatch(doChangePath(url)) + dispatch(doChangePath(url)); - const state = getState() - const pageTitle = selectPageTitle(state) - dispatch(doHistoryPush(params, pageTitle, url)) - } + const state = getState(); + const pageTitle = selectPageTitle(state); + dispatch(doHistoryPush(params, pageTitle, url)); + }; } export function doChangePath(path) { @@ -46,121 +44,124 @@ export function doChangePath(path) { type: types.CHANGE_PATH, data: { path, - } - }) + }, + }); - const state = getState() - const pageTitle = selectPageTitle(state) - window.document.title = pageTitle - window.scrollTo(0, 0) + const state = getState(); + const pageTitle = selectPageTitle(state); + window.document.title = pageTitle; + window.scrollTo(0, 0); - const currentPage = selectCurrentPage(state) - if (currentPage === 'search') { - const params = selectCurrentParams(state) - dispatch(doSearch(params.query)) + const currentPage = selectCurrentPage(state); + if (currentPage === "search") { + const params = selectCurrentParams(state); + dispatch(doSearch(params.query)); } - } + }; } export function doHistoryBack() { return function(dispatch, getState) { - history.back() - } + history.back(); + }; } export function doHistoryPush(params, title, relativeUrl) { return function(dispatch, getState) { - let pathParts = window.location.pathname.split('/') - pathParts[pathParts.length - 1] = relativeUrl.replace(/^\//, '') - const url = pathParts.join('/') - title += " - LBRY" - history.pushState(params, title, url) - } + let pathParts = window.location.pathname.split("/"); + pathParts[pathParts.length - 1] = relativeUrl.replace(/^\//, ""); + const url = pathParts.join("/"); + title += " - LBRY"; + history.pushState(params, title, url); + }; } export function doOpenModal(modal) { return { type: types.OPEN_MODAL, data: { - modal - } - } + modal, + }, + }; } export function doCloseModal() { return { type: types.CLOSE_MODAL, - } + }; } export function doUpdateDownloadProgress(percent) { return { type: types.UPGRADE_DOWNLOAD_PROGRESSED, data: { - percent: percent - } - } + percent: percent, + }, + }; } export function doSkipUpgrade() { return { - type: types.SKIP_UPGRADE - } + type: types.SKIP_UPGRADE, + }; } export function doStartUpgrade() { return function(dispatch, getState) { - const state = getState() - const upgradeDownloadPath = selectUpgradeDownloadPath(state) + const state = getState(); + const upgradeDownloadPath = selectUpgradeDownloadPath(state); - ipcRenderer.send('upgrade', upgradeDownloadPath) - } + ipcRenderer.send("upgrade", upgradeDownloadPath); + }; } export function doDownloadUpgrade() { return function(dispatch, getState) { - const state = getState() + const state = getState(); // Make a new directory within temp directory so the filename is guaranteed to be available - const dir = fs.mkdtempSync(app.getPath('temp') + require('path').sep); - const upgradeFilename = selectUpgradeFilename(state) + const dir = fs.mkdtempSync(app.getPath("temp") + require("path").sep); + const upgradeFilename = selectUpgradeFilename(state); let options = { - onProgress: (p) => dispatch(doUpdateDownloadProgress(Math.round(p * 100))), + onProgress: p => dispatch(doUpdateDownloadProgress(Math.round(p * 100))), directory: dir, }; - download(remote.getCurrentWindow(), selectUpdateUrl(state), options) - .then(downloadItem => { - /** + download( + remote.getCurrentWindow(), + selectUpdateUrl(state), + options + ).then(downloadItem => { + /** * TODO: get the download path directly from the download object. It should just be * downloadItem.getSavePath(), but the copy on the main process is being garbage collected * too soon. */ - dispatch({ - type: types.UPGRADE_DOWNLOAD_COMPLETED, - data: { - downloadItem, - path: path.join(dir, upgradeFilename) - } - }) + dispatch({ + type: types.UPGRADE_DOWNLOAD_COMPLETED, + data: { + downloadItem, + path: path.join(dir, upgradeFilename), + }, }); + }); dispatch({ - type: types.UPGRADE_DOWNLOAD_STARTED - }) + type: types.UPGRADE_DOWNLOAD_STARTED, + }); dispatch({ type: types.OPEN_MODAL, data: { - modal: 'downloading' - } - }) - } + modal: "downloading", + }, + }); + }; } export function doCancelUpgrade() { return function(dispatch, getState) { - const state = getState() - const upgradeDownloadItem = selectUpgradeDownloadItem(state) + const state = getState(); + const upgradeDownloadItem = selectUpgradeDownloadItem(state); if (upgradeDownloadItem) { /* @@ -171,68 +172,74 @@ export function doCancelUpgrade() { try { upgradeDownloadItem.cancel(); } catch (err) { - console.error(err) + console.error(err); // Do nothing } } - dispatch({ type: types.UPGRADE_CANCELLED }) - } + dispatch({ type: types.UPGRADE_CANCELLED }); + }; } export function doCheckUpgradeAvailable() { return function(dispatch, getState) { - const state = getState() + const state = getState(); - lbry.getAppVersionInfo().then(({remoteVersion, upgradeAvailable}) => { + lbry.getAppVersionInfo().then(({ remoteVersion, upgradeAvailable }) => { if (upgradeAvailable) { dispatch({ type: types.UPDATE_VERSION, data: { version: remoteVersion, - } - }) + }, + }); dispatch({ type: types.OPEN_MODAL, data: { - modal: 'upgrade' - } - }) + modal: "upgrade", + }, + }); } }); - } + }; } export function doAlertError(errorList) { return function(dispatch, getState) { - const state = getState() - console.log('do alert error') - console.log(errorList) + const state = getState(); + console.log("do alert error"); + console.log(errorList); dispatch({ type: types.OPEN_MODAL, data: { - modal: 'error', - extraContent: errorList - } - }) - } + modal: "error", + extraContent: errorList, + }, + }); + }; } export function doDaemonReady() { - return { - type: types.DAEMON_READY - } + return function(dispatch, getState) { + dispatch(doAuthenticate()); + dispatch({ + type: types.DAEMON_READY, + }); + dispatch(doChangePath("/discover")); + dispatch(doFetchDaemonSettings()); + dispatch(doFileList()); + }; } export function doShowSnackBar(data) { return { type: types.SHOW_SNACKBAR, data, - } + }; } export function doRemoveSnackBarSnack() { return { type: types.REMOVE_SNACKBAR_SNACK, - } + }; } diff --git a/ui/js/actions/availability.js b/ui/js/actions/availability.js index 501a2eeda..2c7cbc3cb 100644 --- a/ui/js/actions/availability.js +++ b/ui/js/actions/availability.js @@ -1,29 +1,27 @@ -import * as types from 'constants/action_types' -import lbry from 'lbry' -import { - selectFetchingAvailability -} from 'selectors/availability' +import * as types from "constants/action_types"; +import lbry from "lbry"; +import { selectFetchingAvailability } from "selectors/availability"; export function doFetchAvailability(uri) { return function(dispatch, getState) { - const state = getState() - const alreadyFetching = !!selectFetchingAvailability(state)[uri] + const state = getState(); + const alreadyFetching = !!selectFetchingAvailability(state)[uri]; if (!alreadyFetching) { dispatch({ type: types.FETCH_AVAILABILITY_STARTED, - data: {uri} - }) + data: { uri }, + }); - lbry.get_availability({uri}).then((availability) => { + lbry.get_availability({ uri }).then(availability => { dispatch({ type: types.FETCH_AVAILABILITY_COMPLETED, data: { availability, uri, - } - }) - }) + }, + }); + }); } - } -} \ No newline at end of file + }; +} diff --git a/ui/js/actions/content.js b/ui/js/actions/content.js index a7276abf9..ca174b261 100644 --- a/ui/js/actions/content.js +++ b/ui/js/actions/content.js @@ -1,47 +1,34 @@ -import * as types from 'constants/action_types' -import lbry from 'lbry' -import lbryio from 'lbryio' -import lbryuri from 'lbryuri' -import rewards from 'rewards' -import { - selectBalance, -} from 'selectors/wallet' +import * as types from "constants/action_types"; +import lbry from "lbry"; +import lbryio from "lbryio"; +import lbryuri from "lbryuri"; +import { selectBalance } from "selectors/wallet"; import { selectFileInfoForUri, selectUrisDownloading, -} from 'selectors/file_info' -import { - selectResolvingUris -} from 'selectors/content' -import { - selectCostInfoForUri, -} from 'selectors/cost_info' -import { - selectClaimsByUri, -} from 'selectors/claims' -import { - doOpenModal, -} from 'actions/app' +} from "selectors/file_info"; +import { selectResolvingUris } from "selectors/content"; +import { selectCostInfoForUri } from "selectors/cost_info"; +import { doOpenModal } from "actions/app"; +import { doClaimEligiblePurchaseRewards } from "actions/rewards"; export function doResolveUri(uri) { return function(dispatch, getState) { + uri = lbryuri.normalize(uri); - uri = lbryuri.normalize(uri) - - const state = getState() - const alreadyResolving = selectResolvingUris(state).indexOf(uri) !== -1 + const state = getState(); + const alreadyResolving = selectResolvingUris(state).indexOf(uri) !== -1; if (!alreadyResolving) { dispatch({ type: types.RESOLVE_URI_STARTED, - data: { uri } - }) + data: { uri }, + }); - lbry.resolve({ uri }).then((resolutionInfo) => { - const { - claim, - certificate, - } = resolutionInfo ? resolutionInfo : { claim : null, certificate: null } + lbry.resolve({ uri }).then(resolutionInfo => { + const { claim, certificate } = resolutionInfo + ? resolutionInfo + : { claim: null, certificate: null }; dispatch({ type: types.RESOLVE_URI_COMPLETED, @@ -49,246 +36,252 @@ export function doResolveUri(uri) { uri, claim, certificate, - } - }) - }) + }, + }); + }); } - } + }; } export function doCancelResolveUri(uri) { return function(dispatch, getState) { - lbry.cancelResolve({ uri }) + lbry.cancelResolve({ uri }); dispatch({ type: types.RESOLVE_URI_CANCELED, - data: { uri } - }) - } + data: { uri }, + }); + }; } export function doFetchFeaturedUris() { return function(dispatch, getState) { - const state = getState() + const state = getState(); dispatch({ type: types.FETCH_FEATURED_CONTENT_STARTED, - }) + }); const success = ({ Categories, Uris }) => { + let featuredUris = {}; - let featuredUris = {} - - Categories.forEach((category) => { + Categories.forEach(category => { if (Uris[category] && Uris[category].length) { - featuredUris[category] = Uris[category] + featuredUris[category] = Uris[category]; } - }) + }); dispatch({ type: types.FETCH_FEATURED_CONTENT_COMPLETED, data: { categories: Categories, uris: featuredUris, - } - }) - } + }, + }); + }; const failure = () => { dispatch({ type: types.FETCH_FEATURED_CONTENT_COMPLETED, data: { categories: [], - uris: {} - } - }) - } + uris: {}, + }, + }); + }; - lbryio.call('discover', 'list', { version: "early-access" } ) - .then(success, failure) - } + lbryio + .call("discover", "list", { version: "early-access" }) + .then(success, failure); + }; } export function doUpdateLoadStatus(uri, outpoint) { return function(dispatch, getState) { - const state = getState() + const state = getState(); - lbry.file_list({ - outpoint: outpoint, - full_status: true, - }).then(([fileInfo]) => { - if(!fileInfo || fileInfo.written_bytes == 0) { - // download hasn't started yet - setTimeout(() => { dispatch(doUpdateLoadStatus(uri, outpoint)) }, 250) - } else if (fileInfo.completed) { - // TODO this isn't going to get called if they reload the client before - // the download finished - dispatch({ - type: types.DOWNLOADING_COMPLETED, - data: { - uri, - outpoint, - fileInfo, - } - }) - } else { - // ready to play - const { - total_bytes, - written_bytes, - } = fileInfo - const progress = (written_bytes / total_bytes) * 100 + lbry + .file_list({ + outpoint: outpoint, + full_status: true, + }) + .then(([fileInfo]) => { + if (!fileInfo || fileInfo.written_bytes == 0) { + // download hasn't started yet + setTimeout(() => { + dispatch(doUpdateLoadStatus(uri, outpoint)); + }, 250); + } else if (fileInfo.completed) { + // TODO this isn't going to get called if they reload the client before + // the download finished + dispatch({ + type: types.DOWNLOADING_COMPLETED, + data: { + uri, + outpoint, + fileInfo, + }, + }); + } else { + // ready to play + const { total_bytes, written_bytes } = fileInfo; + const progress = written_bytes / total_bytes * 100; - dispatch({ - type: types.DOWNLOADING_PROGRESSED, - data: { - uri, - outpoint, - fileInfo, - progress, - } - }) - setTimeout(() => { dispatch(doUpdateLoadStatus(uri, outpoint)) }, 250) - } - }) - } + dispatch({ + type: types.DOWNLOADING_PROGRESSED, + data: { + uri, + outpoint, + fileInfo, + progress, + }, + }); + setTimeout(() => { + dispatch(doUpdateLoadStatus(uri, outpoint)); + }, 250); + } + }); + }; } export function doDownloadFile(uri, streamInfo) { return function(dispatch, getState) { - const state = getState() + const state = getState(); - lbry.file_list({ outpoint: streamInfo.outpoint, full_status: true }).then(([fileInfo]) => { - dispatch({ - type: types.DOWNLOADING_STARTED, - data: { - uri, - outpoint: streamInfo.outpoint, - fileInfo, - } + lbry + .file_list({ outpoint: streamInfo.outpoint, full_status: true }) + .then(([fileInfo]) => { + dispatch({ + type: types.DOWNLOADING_STARTED, + data: { + uri, + outpoint: streamInfo.outpoint, + fileInfo, + }, + }); + + dispatch(doUpdateLoadStatus(uri, streamInfo.outpoint)); + }); + + lbryio + .call("file", "view", { + uri: uri, + outpoint: streamInfo.outpoint, + claim_id: streamInfo.claim_id, }) + .catch(() => {}); - dispatch(doUpdateLoadStatus(uri, streamInfo.outpoint)) - }) - - lbryio.call('file', 'view', { - uri: uri, - outpoint: streamInfo.outpoint, - claim_id: streamInfo.claim_id, - }).catch(() => {}) - - rewards.claimEligiblePurchaseRewards() - - } + dispatch(doClaimEligiblePurchaseRewards()); + }; } export function doLoadVideo(uri) { return function(dispatch, getState) { - const state = getState() + const state = getState(); dispatch({ type: types.LOADING_VIDEO_STARTED, data: { - uri - } - }) + uri, + }, + }); lbry.get({ uri }).then(streamInfo => { - const timeout = streamInfo === null || - typeof streamInfo !== 'object' || - streamInfo.error == 'Timeout' + const timeout = + streamInfo === null || + typeof streamInfo !== "object" || + streamInfo.error == "Timeout"; - if(timeout) { + if (timeout) { dispatch({ type: types.LOADING_VIDEO_FAILED, - data: { uri } - }) - dispatch(doOpenModal('timedOut')) + data: { uri }, + }); + dispatch(doOpenModal("timedOut")); } else { - dispatch(doDownloadFile(uri, streamInfo)) + dispatch(doDownloadFile(uri, streamInfo)); } - }) - } + }); + }; } export function doPurchaseUri(uri, purchaseModalName) { return function(dispatch, getState) { - const state = getState() - const balance = selectBalance(state) - const fileInfo = selectFileInfoForUri(state, { uri }) - const downloadingByUri = selectUrisDownloading(state) - const alreadyDownloading = !!downloadingByUri[uri] + const state = getState(); + const balance = selectBalance(state); + const fileInfo = selectFileInfoForUri(state, { uri }); + const downloadingByUri = selectUrisDownloading(state); + const alreadyDownloading = !!downloadingByUri[uri]; // we already fully downloaded the file. if (fileInfo && fileInfo.completed) { // If written_bytes is false that means the user has deleted/moved the // file manually on their file system, so we need to dispatch a // doLoadVideo action to reconstruct the file from the blobs - if (!fileInfo.written_bytes) dispatch(doLoadVideo(uri)) + if (!fileInfo.written_bytes) dispatch(doLoadVideo(uri)); - return Promise.resolve() + return Promise.resolve(); } // we are already downloading the file if (alreadyDownloading) { - return Promise.resolve() + return Promise.resolve(); } - const costInfo = selectCostInfoForUri(state, { uri }) - const { cost } = costInfo + const costInfo = selectCostInfoForUri(state, { uri }); + const { cost } = costInfo; // the file is free or we have partially downloaded it if (cost <= 0.01 || (fileInfo && fileInfo.download_directory)) { - dispatch(doLoadVideo(uri)) - return Promise.resolve() + dispatch(doLoadVideo(uri)); + return Promise.resolve(); } if (cost > balance) { - dispatch(doOpenModal('notEnoughCredits')) + dispatch(doOpenModal("notEnoughCredits")); } else { - dispatch(doOpenModal(purchaseModalName)) + dispatch(doOpenModal(purchaseModalName)); } - return Promise.resolve() - } + return Promise.resolve(); + }; } export function doFetchClaimsByChannel(uri) { return function(dispatch, getState) { dispatch({ type: types.FETCH_CHANNEL_CLAIMS_STARTED, - data: { uri } - }) + data: { uri }, + }); - lbry.resolve({ uri }).then((resolutionInfo) => { - const { - claims_in_channel, - } = resolutionInfo ? resolutionInfo : { claims_in_channel: [] } + lbry.resolve({ uri }).then(resolutionInfo => { + const { claims_in_channel } = resolutionInfo + ? resolutionInfo + : { claims_in_channel: [] }; dispatch({ type: types.FETCH_CHANNEL_CLAIMS_COMPLETED, data: { uri, - claims: claims_in_channel - } - }) - }) - } + claims: claims_in_channel, + }, + }); + }); + }; } export function doFetchClaimListMine() { return function(dispatch, getState) { dispatch({ - type: types.FETCH_CLAIM_LIST_MINE_STARTED - }) + type: types.FETCH_CLAIM_LIST_MINE_STARTED, + }); - - lbry.claim_list_mine().then((claims) => { + lbry.claim_list_mine().then(claims => { dispatch({ type: types.FETCH_CLAIM_LIST_MINE_COMPLETED, data: { - claims - } - }) - }) - } -} \ No newline at end of file + claims, + }, + }); + }); + }; +} diff --git a/ui/js/actions/cost_info.js b/ui/js/actions/cost_info.js index dbad86f33..42025718f 100644 --- a/ui/js/actions/cost_info.js +++ b/ui/js/actions/cost_info.js @@ -1,48 +1,26 @@ - import * as types from 'constants/action_types' -import lbry from 'lbry' -import lbryio from 'lbryio' -import { - doResolveUri -} from 'actions/content' -import { - selectResolvingUris, -} from 'selectors/content' -import { - selectClaimsByUri -} from 'selectors/claims' -import { - selectSettingsIsGenerous -} from 'selectors/settings' +import * as types from "constants/action_types"; +import lbry from "lbry"; +import lbryio from "lbryio"; +import { doResolveUri } from "actions/content"; +import { selectResolvingUris } from "selectors/content"; +import { selectClaimsByUri } from "selectors/claims"; +import { selectSettingsIsGenerous } from "selectors/settings"; export function doFetchCostInfoForUri(uri) { return function(dispatch, getState) { const state = getState(), - claim = selectClaimsByUri(state)[uri], - isResolving = selectResolvingUris(state).indexOf(uri) !== -1, - isGenerous = selectSettingsIsGenerous(state) - - if (claim === null) { //claim doesn't exist, nothing to fetch a cost for - return - } - - if (!claim) { - setTimeout(() => { - dispatch(doFetchCostInfoForUri(uri)) - }, 1000) - if (!isResolving) { - dispatch(doResolveUri(uri)) - } - return - } + claim = selectClaimsByUri(state)[uri], + isGenerous = selectSettingsIsGenerous(state); + if (!claim) return null; function begin() { dispatch({ type: types.FETCH_COST_INFO_STARTED, data: { uri, - } - }) + }, + }); } function resolve(costInfo) { @@ -51,27 +29,26 @@ export function doFetchCostInfoForUri(uri) { data: { uri, costInfo, - } - }) + }, + }); } if (isGenerous && claim) { - let cost + let cost; const fee = claim.value.stream.metadata.fee; - if (fee === undefined ) { - resolve({ cost: 0, includesData: true }) - } else if (fee.currency == 'LBC') { - resolve({ cost: fee.amount, includesData: true }) + if (fee === undefined) { + resolve({ cost: 0, includesData: true }); + } else if (fee.currency == "LBC") { + resolve({ cost: fee.amount, includesData: true }); } else { - begin() - lbryio.getExchangeRates().then(({lbc_usd}) => { - resolve({ cost: fee.amount / lbc_usd, includesData: true }) + begin(); + lbryio.getExchangeRates().then(({ lbc_usd }) => { + resolve({ cost: fee.amount / lbc_usd, includesData: true }); }); } } else { - begin() - lbry.getCostInfo(uri).then(resolve) + begin(); + lbry.getCostInfo(uri).then(resolve); } - } + }; } - diff --git a/ui/js/actions/file_info.js b/ui/js/actions/file_info.js index 44d76885c..d379db625 100644 --- a/ui/js/actions/file_info.js +++ b/ui/js/actions/file_info.js @@ -1,121 +1,113 @@ -import * as types from 'constants/action_types' -import lbry from 'lbry' -import { - doFetchClaimListMine -} from 'actions/content' +import * as types from "constants/action_types"; +import lbry from "lbry"; +import { doFetchClaimListMine } from "actions/content"; import { selectClaimsByUri, selectClaimListMineIsPending, -} from 'selectors/claims' +} from "selectors/claims"; import { selectFileListIsPending, selectAllFileInfos, selectUrisLoading, -} from 'selectors/file_info' -import { - doCloseModal, -} from 'actions/app' +} from "selectors/file_info"; +import { doCloseModal } from "actions/app"; -const { - shell, -} = require('electron') +const { shell } = require("electron"); export function doFetchFileInfo(uri) { return function(dispatch, getState) { - const state = getState() - const claim = selectClaimsByUri(state)[uri] - const outpoint = claim ? `${claim.txid}:${claim.nout}` : null - const alreadyFetching = !!selectUrisLoading(state)[uri] + const state = getState(); + const claim = selectClaimsByUri(state)[uri]; + const outpoint = claim ? `${claim.txid}:${claim.nout}` : null; + const alreadyFetching = !!selectUrisLoading(state)[uri]; if (!alreadyFetching) { dispatch({ type: types.FETCH_FILE_INFO_STARTED, data: { outpoint, - } - }) + }, + }); - lbry.file_list({outpoint: outpoint, full_status: true}).then(fileInfos => { - - dispatch({ - type: types.FETCH_FILE_INFO_COMPLETED, - data: { - outpoint, - fileInfo: fileInfos && fileInfos.length ? fileInfos[0] : null, - } - }) - }) + lbry + .file_list({ outpoint: outpoint, full_status: true }) + .then(fileInfos => { + dispatch({ + type: types.FETCH_FILE_INFO_COMPLETED, + data: { + outpoint, + fileInfo: fileInfos && fileInfos.length ? fileInfos[0] : null, + }, + }); + }); } - } + }; } export function doFileList() { return function(dispatch, getState) { - const state = getState() - const isPending = selectFileListIsPending(state) + const state = getState(); + const isPending = selectFileListIsPending(state); if (!isPending) { dispatch({ type: types.FILE_LIST_STARTED, - }) + }); - lbry.file_list().then((fileInfos) => { + lbry.file_list().then(fileInfos => { dispatch({ type: types.FILE_LIST_COMPLETED, data: { fileInfos, - } - }) - }) + }, + }); + }); } - } + }; } export function doOpenFileInShell(fileInfo) { return function(dispatch, getState) { - shell.openItem(fileInfo.download_path) - } + shell.openItem(fileInfo.download_path); + }; } export function doOpenFileInFolder(fileInfo) { return function(dispatch, getState) { - shell.showItemInFolder(fileInfo.download_path) - } + shell.showItemInFolder(fileInfo.download_path); + }; } export function doDeleteFile(outpoint, deleteFromComputer) { return function(dispatch, getState) { - dispatch({ type: types.FILE_DELETE, data: { - outpoint - } - }) + outpoint, + }, + }); lbry.file_delete({ outpoint: outpoint, delete_target_file: deleteFromComputer, - }) + }); - dispatch(doCloseModal()) - } + dispatch(doCloseModal()); + }; } - export function doFetchFileInfosAndPublishedClaims() { return function(dispatch, getState) { const state = getState(), - isClaimListMinePending = selectClaimListMineIsPending(state), - isFileInfoListPending = selectFileListIsPending(state) + isClaimListMinePending = selectClaimListMineIsPending(state), + isFileInfoListPending = selectFileListIsPending(state); if (isClaimListMinePending === undefined) { - dispatch(doFetchClaimListMine()) + dispatch(doFetchClaimListMine()); } if (isFileInfoListPending === undefined) { - dispatch(doFileList()) + dispatch(doFileList()); } - } + }; } - diff --git a/ui/js/actions/rewards.js b/ui/js/actions/rewards.js index 84f65047f..14a2a8253 100644 --- a/ui/js/actions/rewards.js +++ b/ui/js/actions/rewards.js @@ -1,36 +1,116 @@ -import * as types from 'constants/action_types' -import lbry from 'lbry' -import lbryio from 'lbryio'; -import rewards from 'rewards' +import * as types from "constants/action_types"; +import lbry from "lbry"; +import lbryio from "lbryio"; +import rewards from "rewards"; +import { selectRewards, selectRewardsByType } from "selectors/rewards"; -export function doFetchRewards() { +export function doRewardList() { return function(dispatch, getState) { - const state = getState() + const state = getState(); dispatch({ type: types.FETCH_REWARDS_STARTED, - }) - - lbryio.call('reward', 'list', {}).then(function(userRewards) { - dispatch({ - type: types.FETCH_REWARDS_COMPLETED, - data: { userRewards } - }) }); - } + + lbryio + .call("reward", "list", {}) + .then(userRewards => { + dispatch({ + type: types.FETCH_REWARDS_COMPLETED, + data: { userRewards }, + }); + }) + .catch(() => { + dispatch({ + type: types.FETCH_REWARDS_COMPLETED, + data: { userRewards: [] }, + }); + }); + }; } -export function doClaimReward(rewardType) { +export function doClaimRewardType(rewardType) { return function(dispatch, getState) { - try { - rewards.claimReward(rewards[rewardType]) - dispatch({ - type: types.REWARD_CLAIMED, - data: { - reward: rewards[rewardType] - } - }) - } catch(err) { + const rewardsByType = selectRewardsByType(getState()), + reward = rewardsByType[rewardType]; + + if (reward) { + dispatch(doClaimReward(reward)); } - } + }; +} + +export function doClaimReward(reward, saveError = false) { + return function(dispatch, getState) { + if (reward.transaction_id) { + //already claimed, do nothing + return; + } + + dispatch({ + type: types.CLAIM_REWARD_STARTED, + data: { reward }, + }); + + const success = reward => { + dispatch({ + type: types.CLAIM_REWARD_SUCCESS, + data: { + reward, + }, + }); + }; + + const failure = error => { + dispatch({ + type: types.CLAIM_REWARD_FAILURE, + data: { + reward, + error: saveError ? error : null, + }, + }); + }; + + rewards.claimReward(reward.reward_type).then(success, failure); + }; +} + +export function doClaimEligiblePurchaseRewards() { + return function(dispatch, getState) { + if (!lbryio.enabled || !lbryio.getAccessToken()) { + return; + } + + const rewardsByType = selectRewardsByType(getState()); + + let types = {}; + + types[rewards.TYPE_FIRST_STREAM] = false; + types[rewards.TYPE_FEATURED_DOWNLOAD] = false; + types[rewards.TYPE_MANY_DOWNLOADS] = false; + Object.values(rewardsByType).forEach(reward => { + if (types[reward.reward_type] === false && reward.transaction_id) { + types[reward.reward_type] = true; + } + }); + + let unclaimedType = Object.keys(types).find(type => { + return types[type] === false && type !== rewards.TYPE_FEATURED_DOWNLOAD; //handled below + }); + if (unclaimedType) { + dispatch(doClaimRewardType(unclaimedType)); + } + if (types[rewards.TYPE_FEATURED_DOWNLOAD] === false) { + dispatch(doClaimRewardType(rewards.TYPE_FEATURED_DOWNLOAD)); + } + }; +} + +export function doClaimRewardClearError(reward) { + return function(dispatch, getState) { + dispatch({ + type: types.CLAIM_REWARD_CLEAR_ERROR, + data: { reward }, + }); + }; } diff --git a/ui/js/actions/search.js b/ui/js/actions/search.js index 149aa78ea..ab844df03 100644 --- a/ui/js/actions/search.js +++ b/ui/js/actions/search.js @@ -1,35 +1,28 @@ -import * as types from 'constants/action_types' -import lbryuri from 'lbryuri' -import lighthouse from 'lighthouse' -import { - doResolveUri, -} from 'actions/content' -import { - doNavigate, - doHistoryPush -} from 'actions/app' -import { - selectCurrentPage, -} from 'selectors/app' +import * as types from "constants/action_types"; +import lbryuri from "lbryuri"; +import lighthouse from "lighthouse"; +import { doResolveUri } from "actions/content"; +import { doNavigate, doHistoryPush } from "actions/app"; +import { selectCurrentPage } from "selectors/app"; export function doSearch(query) { return function(dispatch, getState) { - const state = getState() - const page = selectCurrentPage(state) + const state = getState(); + const page = selectCurrentPage(state); if (!query) { return dispatch({ type: types.SEARCH_CANCELLED, - }) + }); } dispatch({ type: types.SEARCH_STARTED, - data: { query } - }) + data: { query }, + }); - if(page != 'search') { - dispatch(doNavigate('search', { query: query })) + if (page != "search") { + dispatch(doNavigate("search", { query: query })); } else { lighthouse.search(query).then(results => { results.forEach(result => { @@ -37,18 +30,18 @@ export function doSearch(query) { channelName: result.channel_name, contentName: result.name, claimId: result.channel_id || result.claim_id, - }) - dispatch(doResolveUri(uri)) - }) + }); + dispatch(doResolveUri(uri)); + }); dispatch({ type: types.SEARCH_COMPLETED, data: { query, results, - } - }) - }) + }, + }); + }); } - } + }; } diff --git a/ui/js/actions/settings.js b/ui/js/actions/settings.js index 41dccd3f2..8268989d8 100644 --- a/ui/js/actions/settings.js +++ b/ui/js/actions/settings.js @@ -1,31 +1,31 @@ -import * as types from 'constants/action_types' -import lbry from 'lbry' +import * as types from "constants/action_types"; +import lbry from "lbry"; export function doFetchDaemonSettings() { return function(dispatch, getState) { - lbry.settings_get().then((settings) => { + lbry.settings_get().then(settings => { dispatch({ type: types.DAEMON_SETTINGS_RECEIVED, data: { - settings - } - }) - }) - } + settings, + }, + }); + }); + }; } export function doSetDaemonSetting(key, value) { return function(dispatch, getState) { let settings = {}; settings[key] = value; - lbry.settings_set(settings).then(settings) - lbry.get_settings().then((settings) => { + lbry.settings_set(settings).then(settings); + lbry.settings_get().then(settings => { dispatch({ type: types.DAEMON_SETTINGS_RECEIVED, data: { - settings - } - }) - }) - } -} \ No newline at end of file + settings, + }, + }); + }); + }; +} diff --git a/ui/js/actions/user.js b/ui/js/actions/user.js new file mode 100644 index 000000000..972e167eb --- /dev/null +++ b/ui/js/actions/user.js @@ -0,0 +1,132 @@ +import * as types from "constants/action_types"; +import lbryio from "lbryio"; +import { setLocal } from "utils"; +import { doRewardList } from "actions/rewards"; +import { selectEmailToVerify } from "selectors/user"; + +export function doAuthenticate() { + return function(dispatch, getState) { + dispatch({ + type: types.AUTHENTICATION_STARTED, + }); + lbryio + .authenticate() + .then(user => { + dispatch({ + type: types.AUTHENTICATION_SUCCESS, + data: { user }, + }); + + dispatch(doRewardList()); //FIXME - where should this happen? + }) + .catch(error => { + dispatch({ + type: types.AUTHENTICATION_FAILURE, + data: { error }, + }); + }); + }; +} + +export function doUserFetch() { + return function(dispatch, getState) { + dispatch({ + type: types.USER_FETCH_STARTED, + }); + lbryio.setCurrentUser( + user => { + dispatch({ + type: types.USER_FETCH_SUCCESS, + data: { user }, + }); + }, + error => { + dispatch({ + type: types.USER_FETCH_FAILURE, + data: { error }, + }); + } + ); + }; +} + +export function doUserEmailNew(email) { + return function(dispatch, getState) { + dispatch({ + type: types.USER_EMAIL_NEW_STARTED, + email: email, + }); + lbryio.call("user_email", "new", { email }, "post").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 }, + }); + } + } + ); + }; +} + +export function doUserEmailDecline() { + return function(dispatch, getState) { + setLocal("user_email_declined", true); + dispatch({ + type: types.USER_EMAIL_DECLINE, + }); + }; +} + +export function doUserEmailVerify(verificationToken) { + return function(dispatch, getState) { + const email = selectEmailToVerify(getState()); + + dispatch({ + type: types.USER_EMAIL_VERIFY_STARTED, + code: verificationToken, + }); + + const failure = error => { + dispatch({ + type: types.USER_EMAIL_VERIFY_FAILURE, + data: { error: error.message }, + }); + }; + + lbryio + .call( + "user_email", + "confirm", + { verification_token: verificationToken, email: email }, + "post" + ) + .then(userEmail => { + if (userEmail.is_verified) { + dispatch({ + type: types.USER_EMAIL_VERIFY_SUCCESS, + data: { email }, + }); + dispatch(doUserFetch()); + } else { + failure(new Error("Your email is still not verified.")); //shouldn't happen? + } + }, failure); + }; +} diff --git a/ui/js/actions/wallet.js b/ui/js/actions/wallet.js index 79b22d8d6..def93cf68 100644 --- a/ui/js/actions/wallet.js +++ b/ui/js/actions/wallet.js @@ -1,125 +1,127 @@ -import * as types from 'constants/action_types' -import lbry from 'lbry' +import * as types from "constants/action_types"; +import lbry from "lbry"; import { selectDraftTransaction, selectDraftTransactionAmount, selectBalance, -} from 'selectors/wallet' -import { - doOpenModal, -} from 'actions/app' +} from "selectors/wallet"; +import { doOpenModal } from "actions/app"; export function doUpdateBalance(balance) { return { type: types.UPDATE_BALANCE, data: { - balance: balance - } - } + balance: balance, + }, + }; } export function doFetchTransactions() { return function(dispatch, getState) { dispatch({ - type: types.FETCH_TRANSACTIONS_STARTED - }) + type: types.FETCH_TRANSACTIONS_STARTED, + }); - lbry.call('get_transaction_history', {}, (results) => { + lbry.call("transaction_list", {}, results => { dispatch({ type: types.FETCH_TRANSACTIONS_COMPLETED, data: { - transactions: results - } - }) - }) - } + transactions: results, + }, + }); + }); + }; } export function doGetNewAddress() { return function(dispatch, getState) { dispatch({ - type: types.GET_NEW_ADDRESS_STARTED - }) + type: types.GET_NEW_ADDRESS_STARTED, + }); lbry.wallet_new_address().then(function(address) { - localStorage.setItem('wallet_address', address); + localStorage.setItem("wallet_address", address); dispatch({ type: types.GET_NEW_ADDRESS_COMPLETED, - data: { address } - }) - }) - } + data: { address }, + }); + }); + }; } export function doCheckAddressIsMine(address) { return function(dispatch, getState) { dispatch({ - type: types.CHECK_ADDRESS_IS_MINE_STARTED - }) + type: types.CHECK_ADDRESS_IS_MINE_STARTED, + }); - lbry.checkAddressIsMine(address, (isMine) => { - if (!isMine) dispatch(doGetNewAddress()) + lbry.checkAddressIsMine(address, isMine => { + if (!isMine) dispatch(doGetNewAddress()); dispatch({ - type: types.CHECK_ADDRESS_IS_MINE_COMPLETED - }) - }) - } + type: types.CHECK_ADDRESS_IS_MINE_COMPLETED, + }); + }); + }; } export function doSendDraftTransaction() { return function(dispatch, getState) { - const state = getState() - const draftTx = selectDraftTransaction(state) - const balance = selectBalance(state) - const amount = selectDraftTransactionAmount(state) + const state = getState(); + const draftTx = selectDraftTransaction(state); + const balance = selectBalance(state); + const amount = selectDraftTransactionAmount(state); if (balance - amount < 1) { - return dispatch(doOpenModal('insufficientBalance')) + return dispatch(doOpenModal("insufficientBalance")); } dispatch({ type: types.SEND_TRANSACTION_STARTED, - }) + }); - const successCallback = (results) => { - if(results === true) { + const successCallback = results => { + if (results === true) { dispatch({ type: types.SEND_TRANSACTION_COMPLETED, - }) - dispatch(doOpenModal('transactionSuccessful')) - } - else { + }); + dispatch(doOpenModal("transactionSuccessful")); + } else { dispatch({ type: types.SEND_TRANSACTION_FAILED, - data: { error: results } - }) - dispatch(doOpenModal('transactionFailed')) + data: { error: results }, + }); + dispatch(doOpenModal("transactionFailed")); } - } + }; - const errorCallback = (error) => { + const errorCallback = error => { dispatch({ type: types.SEND_TRANSACTION_FAILED, - data: { error: error.message } - }) - dispatch(doOpenModal('transactionFailed')) - } + data: { error: error.message }, + }); + dispatch(doOpenModal("transactionFailed")); + }; - lbry.sendToAddress(draftTx.amount, draftTx.address, successCallback, errorCallback); - } + lbry.sendToAddress( + draftTx.amount, + draftTx.address, + successCallback, + errorCallback + ); + }; } export function doSetDraftTransactionAmount(amount) { return { type: types.SET_DRAFT_TRANSACTION_AMOUNT, - data: { amount } - } + data: { amount }, + }; } export function doSetDraftTransactionAddress(address) { return { type: types.SET_DRAFT_TRANSACTION_ADDRESS, - data: { address } - } + data: { address }, + }; } diff --git a/ui/js/app.js b/ui/js/app.js index b354036ba..1f1f32ecd 100644 --- a/ui/js/app.js +++ b/ui/js/app.js @@ -1,18 +1,31 @@ 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 logs = []; const app = { - env: env, - config: config, - store: store, - 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.__; +window.__n = i18n.__n; global.app = app; -module.exports = app; \ No newline at end of file +module.exports = app; diff --git a/ui/js/component/app/index.js b/ui/js/component/app/index.js index 5de84e28f..4c966cb56 100644 --- a/ui/js/component/app/index.js +++ b/ui/js/component/app/index.js @@ -1,26 +1,19 @@ -import React from 'react'; -import { connect } from 'react-redux' +import React from "react"; +import { connect } from "react-redux"; -import { - selectCurrentModal, -} from 'selectors/app' -import { - doCheckUpgradeAvailable, - doAlertError, -} from 'actions/app' -import { - doUpdateBalance, -} from 'actions/wallet' -import App from './view' +import { selectCurrentModal } from "selectors/app"; +import { doCheckUpgradeAvailable, doAlertError } from "actions/app"; +import { doUpdateBalance } from "actions/wallet"; +import App from "./view"; -const select = (state) => ({ +const select = state => ({ modal: selectCurrentModal(state), -}) +}); -const perform = (dispatch) => ({ - alertError: (errorList) => dispatch(doAlertError(errorList)), +const perform = dispatch => ({ + alertError: errorList => dispatch(doAlertError(errorList)), checkUpgradeAvailable: () => dispatch(doCheckUpgradeAvailable()), - updateBalance: (balance) => dispatch(doUpdateBalance(balance)) -}) + updateBalance: balance => dispatch(doUpdateBalance(balance)), +}); -export default connect(select, perform)(App) +export default connect(select, perform)(App); diff --git a/ui/js/component/app/view.jsx b/ui/js/component/app/view.jsx index 1c7ff4eb4..f117c5f2e 100644 --- a/ui/js/component/app/view.jsx +++ b/ui/js/component/app/view.jsx @@ -1,42 +1,44 @@ -import React from 'react' -import Router from 'component/router' -import Header from 'component/header'; -import ErrorModal from 'component/errorModal' -import DownloadingModal from 'component/downloadingModal' -import UpgradeModal from 'component/upgradeModal' -import lbry from 'lbry' -import {Line} from 'rc-progress' +import React from "react"; +import Router from "component/router"; +import Header from "component/header"; +import ErrorModal from "component/errorModal"; +import DownloadingModal from "component/downloadingModal"; +import UpgradeModal from "component/upgradeModal"; +import WelcomeModal from "component/welcomeModal"; +import lbry from "lbry"; +import { Line } from "rc-progress"; -class App extends React.Component { +class App extends React.PureComponent { componentWillMount() { - document.addEventListener('unhandledError', (event) => { + document.addEventListener("unhandledError", event => { this.props.alertError(event.detail); }); if (!this.props.upgradeSkipped) { - this.props.checkUpgradeAvailable() + this.props.checkUpgradeAvailable(); } - lbry.balanceSubscribe((balance) => { - this.props.updateBalance(balance) - }) + lbry.balanceSubscribe(balance => { + this.props.updateBalance(balance); + }); } render() { - const { - modal, - } = this.props + const { modal } = this.props; - return
-
-
- + return ( +
+
+
+ +
+ {modal == "upgrade" && } + {modal == "downloading" && } + {modal == "error" && } + {modal == "welcome" && }
- {modal == 'upgrade' && } - {modal == 'downloading' && } - {modal == 'error' && } -
+ ); } } -export default App +export default App; diff --git a/ui/js/component/auth.js b/ui/js/component/auth.js deleted file mode 100644 index b36ff1902..000000000 --- a/ui/js/component/auth.js +++ /dev/null @@ -1,327 +0,0 @@ -import React from "react"; -import lbry from "../lbry.js"; -import lbryio from "../lbryio.js"; -import Modal from "./modal.js"; -import ModalPage from "./modal-page.js"; -import Link from "component/link" -import {RewardLink} from 'component/reward-link'; -import {FormRow} from "../component/form.js"; -import {CreditAmount, Address} from "../component/common.js"; -import {getLocal, setLocal} from '../utils.js'; -import rewards from '../rewards' - - -class SubmitEmailStage extends React.Component { - constructor(props) { - super(props); - - this.state = { - rewardType: null, - email: '', - submitting: false - }; - } - - handleEmailChanged(event) { - this.setState({ - email: event.target.value, - }); - } - - onEmailSaved(email) { - this.props.setStage("confirm", { email: email }) - } - - handleSubmit(event) { - event.preventDefault(); - - this.setState({ - submitting: true, - }); - lbryio.call('user_email', 'new', {email: this.state.email}, 'post').then(() => { - this.onEmailSaved(this.state.email); - }, (error) => { - if (error.xhr && (error.xhr.status == 409 || error.message == "This email is already in use")) { - this.onEmailSaved(this.state.email); - return; - } else if (this._emailRow) { - this._emailRow.showError(error.message) - } - this.setState({ submitting: false }); - }); - } - - render() { - return ( -
-
{ this.handleSubmit(event) }}> - { this._emailRow = ref }} type="text" label="Email" placeholder="scrwvwls@lbry.io" - name="email" value={this.state.email} - onChange={(event) => { this.handleEmailChanged(event) }} /> -
- { this.handleSubmit(event) }} /> -
- -
- ); - } -} - -class ConfirmEmailStage extends React.Component { - constructor(props) { - super(props); - - this.state = { - rewardType: null, - code: '', - submitting: false, - errorMessage: null, - }; - } - - handleCodeChanged(event) { - this.setState({ - code: event.target.value, - }); - } - - handleSubmit(event) { - event.preventDefault(); - this.setState({ - submitting: true, - }); - - const onSubmitError = (error) => { - if (this._codeRow) { - this._codeRow.showError(error.message) - } - this.setState({ submitting: false }); - }; - - lbryio.call('user_email', 'confirm', {verification_token: this.state.code, email: this.props.email}, 'post').then((userEmail) => { - if (userEmail.is_verified) { - this.props.setStage("welcome") - } else { - onSubmitError(new Error("Your email is still not verified.")) //shouldn't happen? - } - }, onSubmitError); - } - - render() { - return ( -
-
{ this.handleSubmit(event) }}> - { this._codeRow = ref }} type="text" - name="code" placeholder="a94bXXXXXXXXXXXXXX" value={this.state.code} onChange={(event) => { this.handleCodeChanged(event) }} - helper="A verification code is required to access this version."/> -
- { this.handleSubmit(event)}} /> -
-
- No code? { this.props.setStage("nocode")}} label="Click here" />. -
- -
- ); - } -} - -class WelcomeStage extends React.Component { - static propTypes = { - endAuth: React.PropTypes.func, - } - - constructor(props) { - super(props); - - this.state = { - hasReward: false, - rewardAmount: null, - }; - } - - onRewardClaim(reward) { - this.setState({ - hasReward: true, - rewardAmount: reward.amount - }) - } - - render() { - return ( - !this.state.hasReward ? - -
-

Welcome to LBRY.

-

Using LBRY is like dating a centaur. Totally normal up top, and way different underneath.

-

Up top, LBRY is similar to popular media sites.

-

Below, LBRY is controlled by users -- you -- via blockchain and decentralization.

-

Thank you for making content freedom possible! Here's a nickel, kid.

-
- { this.onRewardClaim(event) }} onRewardFailure={() => this.props.setStage(null)} onConfirmed={() => { this.props.setStage(null) }} /> -
-
-
: - { this.props.setStage(null) }}> -
-

About Your Reward

-

You earned a reward of LBRY credits, or LBC.

-

This reward will show in your Wallet momentarily, probably while you are reading this message.

-

LBC is used to compensate creators, to publish, and to have say in how the network works.

-

No need to understand it all just yet! Try watching or downloading something next.

-

Finally, know that LBRY is an early beta and that it earns the name.

-
-
- ); - } -} - -const ErrorStage = (props) => { - return
-

An error was encountered that we cannot continue from.

-

At least we're earning the name beta.

- { props.errorText ?

Message: {props.errorText}

: '' } - { window.location.reload() } } /> -
-} - -const PendingStage = (props) => { - return
-

Preparing for first access

-
-} - - -class CodeRequiredStage extends React.Component { - constructor(props) { - super(props); - - this._balanceSubscribeId = null - - this.state = { - balance: 0, - address: getLocal('wallet_address') - }; - } - - componentWillMount() { - this._balanceSubscribeId = lbry.balanceSubscribe((balance) => { - this.setState({ - balance: balance - }); - }) - - if (!this.state.address) { - lbry.wallet_unused_address().then((address) => { - setLocal('wallet_address', address); - this.setState({ address: address }); - }); - } - } - - componentWillUnmount() { - if (this._balanceSubscribeId) { - lbry.balanceUnsubscribe(this._balanceSubscribeId) - } - } - - render() { - const disabled = this.state.balance < 1; - return ( -
-
-

Access to LBRY is restricted as we build and scale the network.

-

There are two ways in:

-

Own LBRY Credits

-

If you own at least 1 LBC, you can get in right now.

-

{ setLocal('auth_bypassed', true); this.props.setStage(null); }} - disabled={disabled} label="Let Me In" button={ disabled ? "alt" : "primary" } />

-

Your balance is . To increase your balance, send credits to this address:

-

-

If you don't understand how to send credits, then...

-
-
-

Wait For A Code

-

If you provide your email, you'll automatically receive a notification when the system is open.

-

{ this.props.setStage("email"); }} label="Return" />

-
-
- ); - } -} - - -export class AuthOverlay extends React.Component { - constructor(props) { - super(props); - - this._stages = { - pending: PendingStage, - error: ErrorStage, - nocode: CodeRequiredStage, - email: SubmitEmailStage, - confirm: ConfirmEmailStage, - welcome: WelcomeStage - } - - this.state = { - stage: "pending", - stageProps: {} - }; - } - - setStage(stage, stageProps = {}) { - this.setState({ - stage: stage, - stageProps: stageProps - }) - } - - componentWillMount() { - lbryio.authenticate().then((user) => { - if (!user.has_verified_email) { - if (getLocal('auth_bypassed')) { - this.setStage(null) - } else { - this.setStage("email", {}) - } - } else { - lbryio.call('reward', 'list', {}).then((userRewards) => { - userRewards.filter(function(reward) { - return reward.reward_type == rewards.TYPE_NEW_USER && reward.transaction_id; - }).length ? - this.setStage(null) : - this.setStage("welcome") - }); - } - }).catch((err) => { - this.setStage("error", { errorText: err.message }) - document.dispatchEvent(new CustomEvent('unhandledError', { - detail: { - message: err.message, - data: err.stack - } - })); - }) - } - - render() { - if (!this.state.stage) { - return null; - } - const StageContent = this._stages[this.state.stage]; - - if (!StageContent) { - return Unknown authentication step. - } - - return ( - this.state.stage != "welcome" ? - -

LBRY Early Access

- { this.setStage(stage, stageProps) }} /> -
: - { this.setStage(stage, stageProps) }} {...this.state.stageProps} /> - ); - } -} \ No newline at end of file diff --git a/ui/js/component/auth/index.js b/ui/js/component/auth/index.js new file mode 100644 index 000000000..37af9f90f --- /dev/null +++ b/ui/js/component/auth/index.js @@ -0,0 +1,16 @@ +import React from "react"; +import { connect } from "react-redux"; +import { + selectAuthenticationIsPending, + selectEmailToVerify, + selectUserIsVerificationCandidate, +} from "selectors/user"; +import Auth from "./view"; + +const select = state => ({ + isPending: selectAuthenticationIsPending(state), + email: selectEmailToVerify(state), + isVerificationCandidate: selectUserIsVerificationCandidate(state), +}); + +export default connect(select, null)(Auth); diff --git a/ui/js/component/auth/view.jsx b/ui/js/component/auth/view.jsx new file mode 100644 index 000000000..551113ffa --- /dev/null +++ b/ui/js/component/auth/view.jsx @@ -0,0 +1,22 @@ +import React from "react"; +import { BusyMessage } from "component/common"; +import UserEmailNew from "component/userEmailNew"; +import UserEmailVerify from "component/userEmailVerify"; + +export class Auth extends React.PureComponent { + render() { + const { isPending, email, isVerificationCandidate } = this.props; + + if (isPending) { + return ; + } else if (!email) { + return ; + } else if (isVerificationCandidate) { + return ; + } else { + return {__("No further steps.")}; + } + } +} + +export default Auth; diff --git a/ui/js/component/authOverlay/index.jsx b/ui/js/component/authOverlay/index.jsx new file mode 100644 index 000000000..ec7d7ee5a --- /dev/null +++ b/ui/js/component/authOverlay/index.jsx @@ -0,0 +1,24 @@ +import React from "react"; +import * as modal from "constants/modal_types"; +import { connect } from "react-redux"; +import { doUserEmailDecline } from "actions/user"; +import { doOpenModal } from "actions/app"; +import { + selectAuthenticationIsPending, + selectUserHasEmail, + selectUserIsAuthRequested, +} from "selectors/user"; +import AuthOverlay from "./view"; + +const select = state => ({ + hasEmail: selectUserHasEmail(state), + isPending: selectAuthenticationIsPending(state), + isShowing: selectUserIsAuthRequested(state), +}); + +const perform = dispatch => ({ + userEmailDecline: () => dispatch(doUserEmailDecline()), + openWelcomeModal: () => dispatch(doOpenModal(modal.WELCOME)), +}); + +export default connect(select, perform)(AuthOverlay); diff --git a/ui/js/component/authOverlay/view.jsx b/ui/js/component/authOverlay/view.jsx new file mode 100644 index 000000000..0cce29f9b --- /dev/null +++ b/ui/js/component/authOverlay/view.jsx @@ -0,0 +1,83 @@ +import React from "react"; +import lbryio from "lbryio.js"; +import ModalPage from "component/modal-page.js"; +import Auth from "component/auth"; +import Link from "component/link"; + +export class AuthOverlay extends React.PureComponent { + constructor(props) { + super(props); + + this.state = { + showNoEmailConfirm: false, + }; + } + + componentWillReceiveProps(nextProps) { + if (this.props.isShowing && !this.props.isPending && !nextProps.isShowing) { + setTimeout(() => this.props.openWelcomeModal(), 1); + } + } + + onEmailSkipClick() { + this.setState({ showNoEmailConfirm: true }); + } + + onEmailSkipConfirm() { + this.props.userEmailDecline(); + } + + render() { + if (!lbryio.enabled) { + return null; + } + + const { isPending, isShowing, hasEmail } = this.props; + + if (isShowing) { + return ( + +

LBRY Early Access

+ + {isPending + ? "" + :
+ {!hasEmail && this.state.showNoEmailConfirm + ?
+

+ {__( + "If you continue without an email, you will be ineligible to earn free LBC rewards, as well as unable to receive security related communications." + )} +

+ { + this.onEmailSkipConfirm(); + }} + label={__("Continue without email")} + /> +
+ : { + hasEmail + ? this.onEmailSkipConfirm() + : this.onEmailSkipClick(); + }} + label={ + hasEmail ? __("Skip for now") : __("Do I have to?") + } + />} +
} +
+ ); + } + + return null; + } +} + +export default AuthOverlay; diff --git a/ui/js/component/common.js b/ui/js/component/common.js index c11e0d14c..38dbf83fd 100644 --- a/ui/js/component/common.js +++ b/ui/js/component/common.js @@ -1,76 +1,95 @@ -import React from 'react'; -import lbry from '../lbry.js'; +import React from "react"; +import lbry from "../lbry.js"; //component/icon.js -export class Icon extends React.Component { +export class Icon extends React.PureComponent { static propTypes = { icon: React.PropTypes.string.isRequired, className: React.PropTypes.string, fixed: React.PropTypes.bool, - } + }; render() { - const {fixed, className} = this.props; - const spanClassName = ('icon ' + ('fixed' in this.props ? 'icon-fixed-width ' : '') + - this.props.icon + ' ' + (this.props.className || '')); - return + const { fixed, className } = this.props; + const spanClassName = + "icon " + + ("fixed" in this.props ? "icon-fixed-width " : "") + + this.props.icon + + " " + + (this.props.className || ""); + return ; } } -export class TruncatedText extends React.Component { +export class TruncatedText extends React.PureComponent { static propTypes = { lines: React.PropTypes.number, - } + }; static defaultProps = { - lines: null - } + lines: null, + }; render() { - return {this.props.children}; + return ( + + {this.props.children} + + ); } } -export class BusyMessage extends React.Component { +export class BusyMessage extends React.PureComponent { static propTypes = { message: React.PropTypes.string, - } + }; render() { - return {this.props.message} + return ( + {this.props.message} + ); } } -export class CurrencySymbol extends React.Component { +export class CurrencySymbol extends React.PureComponent { render() { return LBC; } } -export class CreditAmount extends React.Component { +export class CreditAmount extends React.PureComponent { static propTypes = { amount: React.PropTypes.number.isRequired, precision: React.PropTypes.number, isEstimate: React.PropTypes.bool, label: React.PropTypes.bool, showFree: React.PropTypes.bool, - look: React.PropTypes.oneOf(['indicator', 'plain']), - } + look: React.PropTypes.oneOf(["indicator", "plain"]), + }; static defaultProps = { precision: 1, label: true, showFree: false, - look: 'indicator', - } + look: "indicator", + }; render() { - const formattedAmount = lbry.formatCredits(this.props.amount, this.props.precision); + const formattedAmount = lbry.formatCredits( + this.props.amount, + this.props.precision + ); let amountText; if (this.props.showFree && parseFloat(formattedAmount) == 0) { - amountText = 'free'; + amountText = __("free"); } else if (this.props.label) { - amountText = formattedAmount + (parseFloat(formattedAmount) == 1 ? ' credit' : ' credits'); + amountText = + formattedAmount + + " " + + (parseFloat(formattedAmount) == 1 ? __("credit") : __("credits")); } else { amountText = formattedAmount; } @@ -80,19 +99,27 @@ export class CreditAmount extends React.Component { {amountText} - { this.props.isEstimate ? * : null } + {this.props.isEstimate + ? + * + + : null} ); } } let addressStyle = { - fontFamily: '"Consolas", "Lucida Console", "Adobe Source Code Pro", monospace', + fontFamily: + '"Consolas", "Lucida Console", "Adobe Source Code Pro", monospace', }; -export class Address extends React.Component { +export class Address extends React.PureComponent { static propTypes = { address: React.PropTypes.string, - } + }; constructor(props) { super(props); @@ -102,16 +129,27 @@ export class Address extends React.Component { render() { return ( - { this._inputElem = input; }} - onFocus={() => { this._inputElem.select(); }} style={addressStyle} readOnly="readonly" value={this.props.address}> + { + this._inputElem = input; + }} + onFocus={() => { + this._inputElem.select(); + }} + style={addressStyle} + readOnly="readonly" + value={this.props.address} + /> ); } } -export class Thumbnail extends React.Component { +export class Thumbnail extends React.PureComponent { static propTypes = { src: React.PropTypes.string, - } + }; handleError() { if (this.state.imageUrl != this._defaultImageUri) { @@ -124,9 +162,9 @@ export class Thumbnail extends React.Component { constructor(props) { super(props); - this._defaultImageUri = lbry.imagePath('default-thumb.svg') - this._maxLoadTime = 10000 - this._isMounted = false + this._defaultImageUri = lbry.imagePath("default-thumb.svg"); + this._maxLoadTime = 10000; + this._isMounted = false; this.state = { imageUri: this.props.src || this._defaultImageUri, @@ -149,9 +187,19 @@ export class Thumbnail extends React.Component { } render() { - const className = this.props.className ? this.props.className : '', - otherProps = Object.assign({}, this.props) + const className = this.props.className ? this.props.className : "", + otherProps = Object.assign({}, this.props); delete otherProps.className; - return { this.handleError() }} {...otherProps} className={className} src={this.state.imageUri} /> + return ( + { + this.handleError(); + }} + {...otherProps} + className={className} + src={this.state.imageUri} + /> + ); } } diff --git a/ui/js/component/downloadingModal/index.jsx b/ui/js/component/downloadingModal/index.jsx index 618f335fb..1902cbd13 100644 --- a/ui/js/component/downloadingModal/index.jsx +++ b/ui/js/component/downloadingModal/index.jsx @@ -1,25 +1,17 @@ -import React from 'react' -import { - connect -} from 'react-redux' -import { - doStartUpgrade, - doCancelUpgrade, -} from 'actions/app' -import { - selectDownloadProgress, - selectDownloadComplete, -} from 'selectors/app' -import DownloadingModal from './view' +import React from "react"; +import { connect } from "react-redux"; +import { doStartUpgrade, doCancelUpgrade } from "actions/app"; +import { selectDownloadProgress, selectDownloadComplete } from "selectors/app"; +import DownloadingModal from "./view"; -const select = (state) => ({ +const select = state => ({ downloadProgress: selectDownloadProgress(state), downloadComplete: selectDownloadComplete(state), -}) +}); -const perform = (dispatch) => ({ +const perform = dispatch => ({ startUpgrade: () => dispatch(doStartUpgrade()), - cancelUpgrade: () => dispatch(doCancelUpgrade()) -}) + cancelUpgrade: () => dispatch(doCancelUpgrade()), +}); -export default connect(select, perform)(DownloadingModal) +export default connect(select, perform)(DownloadingModal); diff --git a/ui/js/component/downloadingModal/view.jsx b/ui/js/component/downloadingModal/view.jsx index dc76fdd4b..0bf612d7f 100644 --- a/ui/js/component/downloadingModal/view.jsx +++ b/ui/js/component/downloadingModal/view.jsx @@ -1,40 +1,62 @@ -import React from 'react' -import { - Modal -} from 'component/modal' -import {Line} from 'rc-progress'; -import Link from 'component/link' +import React from "react"; +import { Modal } from "component/modal"; +import { Line } from "rc-progress"; +import Link from "component/link"; -class DownloadingModal extends React.Component { +class DownloadingModal extends React.PureComponent { render() { const { downloadProgress, downloadComplete, startUpgrade, cancelUpgrade, - } = this.props + } = this.props; return ( - - Downloading Update{downloadProgress ? `: ${downloadProgress}%` : null} - - {downloadComplete ? ( -
-
-

Click "Begin Upgrade" to start the upgrade process.

-

The app will close, and you will be prompted to install the latest version of LBRY.

-

After the install is complete, please reopen the app.

-
- ) : null } + + {__("Downloading Update")} + {downloadProgress ? `: ${downloadProgress}%` : null} + + {downloadComplete + ?
+
+

{__('Click "Begin Upgrade" to start the upgrade process.')}

+

+ {__( + "The app will close, and you will be prompted to install the latest version of LBRY." + )} +

+

+ {__("After the install is complete, please reopen the app.")} +

+
+ : null}
{downloadComplete - ? + ? : null} - +
- ) + ); } } -export default DownloadingModal +export default DownloadingModal; diff --git a/ui/js/component/errorModal/index.jsx b/ui/js/component/errorModal/index.jsx index e4e4bc24b..dadbe3eb5 100644 --- a/ui/js/component/errorModal/index.jsx +++ b/ui/js/component/errorModal/index.jsx @@ -1,23 +1,16 @@ -import React from 'react' -import { - connect -} from 'react-redux' -import { - selectCurrentModal, - selectModalExtraContent, -} from 'selectors/app' -import { - doCloseModal, -} from 'actions/app' -import ErrorModal from './view' +import React from "react"; +import { connect } from "react-redux"; +import { selectCurrentModal, selectModalExtraContent } from "selectors/app"; +import { doCloseModal } from "actions/app"; +import ErrorModal from "./view"; -const select = (state) => ({ +const select = state => ({ modal: selectCurrentModal(state), error: selectModalExtraContent(state), -}) +}); -const perform = (dispatch) => ({ - closeModal: () => dispatch(doCloseModal()) -}) +const perform = dispatch => ({ + closeModal: () => dispatch(doCloseModal()), +}); -export default connect(select, perform)(ErrorModal) +export default connect(select, perform)(ErrorModal); diff --git a/ui/js/component/errorModal/view.jsx b/ui/js/component/errorModal/view.jsx index c494c9cb1..57bfe19dc 100644 --- a/ui/js/component/errorModal/view.jsx +++ b/ui/js/component/errorModal/view.jsx @@ -1,54 +1,63 @@ -import React from 'react' -import lbry from 'lbry' -import { - ExpandableModal -} from 'component/modal' +import React from "react"; +import lbry from "lbry"; +import { ExpandableModal } from "component/modal"; -class ErrorModal extends React.Component { +class ErrorModal extends React.PureComponent { render() { - const { - modal, - closeModal, - error - } = this.props + const { modal, closeModal, error } = this.props; - const errorObj = typeof error === "string" ? { error: error } : error + const errorObj = typeof error === "string" ? { error: error } : error; const error_key_labels = { - connectionString: 'API connection string', - method: 'Method', - params: 'Parameters', - code: 'Error code', - message: 'Error message', - data: 'Error data', - } + connectionString: __("API connection string"), + method: __("Method"), + params: __("Parameters"), + code: __("Error code"), + message: __("Error message"), + data: __("Error data"), + }; - - const errorInfoList = [] + const errorInfoList = []; for (let key of Object.keys(error)) { - let val = typeof error[key] == 'string' ? error[key] : JSON.stringify(error[key]); + let val = typeof error[key] == "string" + ? error[key] + : JSON.stringify(error[key]); let label = error_key_labels[key]; - errorInfoList.push(
  • {label}: {val}
  • ); + errorInfoList.push( +
  • {label}: {val}
  • + ); } - const errorInfo =
      {errorInfoList}
    + const errorInfo = ( +
      {errorInfoList}
    + ); - return( + return ( -

    Error

    +

    {__("Error")}

    -
    -

    We're sorry that LBRY has encountered an error. This has been reported and we will investigate the problem.

    +
    + +
    +

    + {__( + "We're sorry that LBRY has encountered an error. This has been reported and we will investigate the problem." + )} +

    - ) + ); } } -export default ErrorModal +export default ErrorModal; diff --git a/ui/js/component/file-selector.js b/ui/js/component/file-selector.js index 4670f4830..879ea2665 100644 --- a/ui/js/component/file-selector.js +++ b/ui/js/component/file-selector.js @@ -1,16 +1,16 @@ -import React from 'react'; +import React from "react"; -const {remote} = require('electron'); -class FileSelector extends React.Component { +const { remote } = require("electron"); +class FileSelector extends React.PureComponent { static propTypes = { - type: React.PropTypes.oneOf(['file', 'directory']), + type: React.PropTypes.oneOf(["file", "directory"]), initPath: React.PropTypes.string, onFileChosen: React.PropTypes.func, - } + }; static defaultProps = { - type: 'file', - } + type: "file", + }; componentWillMount() { this.setState({ @@ -19,40 +19,46 @@ class FileSelector extends React.Component { } handleButtonClick() { - remote.dialog.showOpenDialog({ - properties: [this.props.type == 'file' ? 'openFile' : 'openDirectory'], - }, (paths) => { - if (!paths) { // User hit cancel, so do nothing - return; - } + remote.dialog.showOpenDialog( + { + properties: [this.props.type == "file" ? "openFile" : "openDirectory"], + }, + paths => { + if (!paths) { + // User hit cancel, so do nothing + return; + } - const path = paths[0]; - this.setState({ - path: path, - }); - if (this.props.onFileChosen) { - this.props.onFileChosen(path); + const path = paths[0]; + this.setState({ + path: path, + }); + if (this.props.onFileChosen) { + this.props.onFileChosen(path); + } } - }); + ); } render() { return (
    - - {' '} + {" "} - {this.state.path ? - this.state.path : - 'No File Chosen'} + {this.state.path ? this.state.path : __("No File Chosen")}
    ); } -}; +} export default FileSelector; diff --git a/ui/js/component/fileActions/index.js b/ui/js/component/fileActions/index.js index 1d8ba6088..3f3e43283 100644 --- a/ui/js/component/fileActions/index.js +++ b/ui/js/component/fileActions/index.js @@ -1,49 +1,30 @@ -import React from 'react' -import { - connect, -} from 'react-redux' -import { - selectPlatform, -} from 'selectors/app' +import React from "react"; +import { connect } from "react-redux"; +import { selectPlatform } from "selectors/app"; import { makeSelectFileInfoForUri, makeSelectDownloadingForUri, makeSelectLoadingForUri, -} from 'selectors/file_info' -import { - makeSelectIsAvailableForUri, -} from 'selectors/availability' -import { - selectCurrentModal, -} from 'selectors/app' -import { - makeSelectCostInfoForUri, -} from 'selectors/cost_info' -import { - doCloseModal, - doOpenModal, - doHistoryBack, -} from 'actions/app' -import { - doFetchAvailability -} from 'actions/availability' +} from "selectors/file_info"; +import { makeSelectIsAvailableForUri } from "selectors/availability"; +import { selectCurrentModal } from "selectors/app"; +import { makeSelectCostInfoForUri } from "selectors/cost_info"; +import { doCloseModal, doOpenModal, doHistoryBack } from "actions/app"; +import { doFetchAvailability } from "actions/availability"; import { doOpenFileInShell, doOpenFileInFolder, doDeleteFile, -} from 'actions/file_info' -import { - doPurchaseUri, - doLoadVideo, -} from 'actions/content' -import FileActions from './view' +} from "actions/file_info"; +import { doPurchaseUri, doLoadVideo } from "actions/content"; +import FileActions from "./view"; const makeSelect = () => { - const selectFileInfoForUri = makeSelectFileInfoForUri() - const selectIsAvailableForUri = makeSelectIsAvailableForUri() - const selectDownloadingForUri = makeSelectDownloadingForUri() - const selectCostInfoForUri = makeSelectCostInfoForUri() - const selectLoadingForUri = makeSelectLoadingForUri() + const selectFileInfoForUri = makeSelectFileInfoForUri(); + const selectIsAvailableForUri = makeSelectIsAvailableForUri(); + const selectDownloadingForUri = makeSelectDownloadingForUri(); + const selectCostInfoForUri = makeSelectCostInfoForUri(); + const selectLoadingForUri = makeSelectLoadingForUri(); const select = (state, props) => ({ fileInfo: selectFileInfoForUri(state, props), @@ -53,23 +34,23 @@ const makeSelect = () => { downloading: selectDownloadingForUri(state, props), costInfo: selectCostInfoForUri(state, props), loading: selectLoadingForUri(state, props), - }) + }); - return select -} + return select; +}; -const perform = (dispatch) => ({ - checkAvailability: (uri) => dispatch(doFetchAvailability(uri)), +const perform = dispatch => ({ + checkAvailability: uri => dispatch(doFetchAvailability(uri)), closeModal: () => dispatch(doCloseModal()), - openInFolder: (fileInfo) => dispatch(doOpenFileInFolder(fileInfo)), - openInShell: (fileInfo) => dispatch(doOpenFileInShell(fileInfo)), + openInFolder: fileInfo => dispatch(doOpenFileInFolder(fileInfo)), + openInShell: fileInfo => dispatch(doOpenFileInShell(fileInfo)), deleteFile: (fileInfo, deleteFromComputer) => { - dispatch(doHistoryBack()) - dispatch(doDeleteFile(fileInfo, deleteFromComputer)) + dispatch(doHistoryBack()); + dispatch(doDeleteFile(fileInfo, deleteFromComputer)); }, - openModal: (modal) => dispatch(doOpenModal(modal)), - startDownload: (uri) => dispatch(doPurchaseUri(uri, 'affirmPurchase')), - loadVideo: (uri) => dispatch(doLoadVideo(uri)), -}) + openModal: modal => dispatch(doOpenModal(modal)), + startDownload: uri => dispatch(doPurchaseUri(uri, "affirmPurchase")), + loadVideo: uri => dispatch(doLoadVideo(uri)), +}); -export default connect(makeSelect, perform)(FileActions) \ No newline at end of file +export default connect(makeSelect, perform)(FileActions); diff --git a/ui/js/component/fileActions/view.jsx b/ui/js/component/fileActions/view.jsx index 8b3d2678b..b78512be9 100644 --- a/ui/js/component/fileActions/view.jsx +++ b/ui/js/component/fileActions/view.jsx @@ -1,33 +1,33 @@ -import React from 'react'; -import {Icon,BusyMessage} from 'component/common'; -import FilePrice from 'component/filePrice' -import {Modal} from 'component/modal'; -import {FormField} from 'component/form'; -import Link from 'component/link'; -import {ToolTip} from 'component/tooltip'; -import {DropDownMenu, DropDownMenuItem} from 'component/menu'; +import React from "react"; +import { Icon, BusyMessage } from "component/common"; +import FilePrice from "component/filePrice"; +import { Modal } from "component/modal"; +import { FormField } from "component/form"; +import Link from "component/link"; +import { ToolTip } from "component/tooltip"; +import { DropDownMenu, DropDownMenuItem } from "component/menu"; -class FileActions extends React.Component { +class FileActions extends React.PureComponent { constructor(props) { - super(props) + super(props); this.state = { forceShowActions: false, deleteChecked: false, - } + }; } componentWillMount() { - this.checkAvailability(this.props.uri) + this.checkAvailability(this.props.uri); } componentWillReceiveProps(nextProps) { - this.checkAvailability(nextProps.uri) + this.checkAvailability(nextProps.uri); } checkAvailability(uri) { if (!this._uri || uri !== this._uri) { this._uri = uri; - this.props.checkAvailability(uri) + this.props.checkAvailability(uri); } } @@ -40,12 +40,12 @@ class FileActions extends React.Component { handleDeleteCheckboxClicked(event) { this.setState({ deleteChecked: event.target.checked, - }) + }); } onAffirmPurchase() { - this.props.closeModal() - this.props.loadVideo(this.props.uri) + this.props.closeModal(); + this.props.loadVideo(this.props.uri); } render() { @@ -64,88 +64,159 @@ class FileActions extends React.Component { startDownload, costInfo, loading, - } = this.props + } = this.props; const deleteChecked = this.state.deleteChecked, - metadata = fileInfo ? fileInfo.metadata : null, - openInFolderMessage = platform.startsWith('Mac') ? 'Open in Finder' : 'Open in Folder', - showMenu = fileInfo && Object.keys(fileInfo).length > 0, - title = metadata ? metadata.title : uri; + metadata = fileInfo ? fileInfo.metadata : null, + openInFolderMessage = platform.startsWith("Mac") + ? __("Open in Finder") + : __("Open in Folder"), + showMenu = fileInfo && Object.keys(fileInfo).length > 0, + title = metadata ? metadata.title : uri; - let content + let content; if (loading || downloading) { + const progress = fileInfo && fileInfo.written_bytes + ? fileInfo.written_bytes / fileInfo.total_bytes * 100 + : 0, + label = fileInfo + ? progress.toFixed(0) + __("% complete") + : __("Connecting..."), + labelWithIcon = ( + + {label} + + ); - const - progress = (fileInfo && fileInfo.written_bytes) ? fileInfo.written_bytes / fileInfo.total_bytes * 100 : 0, - label = fileInfo ? progress.toFixed(0) + '% complete' : 'Connecting...', - labelWithIcon = {label}; - - content =
    -
    {labelWithIcon}
    - {labelWithIcon} -
    - + content = ( +
    +
    + {labelWithIcon} +
    + {labelWithIcon} +
    + ); } else if (!fileInfo && isAvailable === undefined) { - - content = - + content = ; } else if (!fileInfo && !isAvailable && !this.state.forceShowActions) { - - content =
    -
    Content unavailable.
    - - -
    - + content = ( +
    +
    + {__("Content unavailable.")} +
    + + +
    + ); } else if (fileInfo === null && !downloading) { if (!costInfo) { - content = + content = ; } else { - content = { startDownload(uri) } } />; + content = ( + { + startDownload(uri); + }} + /> + ); } - } else if (fileInfo && fileInfo.download_path) { - content = openInShell(fileInfo)} />; + content = ( + openInShell(fileInfo)} + /> + ); } else { - console.log('handle this case of file action props?'); + console.log("handle this case of file action props?"); } return (
    - { content } - { showMenu ? - - openInFolder(fileInfo)} label={openInFolderMessage} /> - openModal('confirmRemove')} label="Remove..." /> - : '' } - - This will purchase {title} for credits. + {content} + {showMenu + ? + openInFolder(fileInfo)} + label={openInFolderMessage} + /> + openModal("confirmRemove")} + label={__("Remove...")} + /> + + : ""} + + {__("This will purchase")} {title} {__("for")} + {" "} + {" "}{__("credits")}. - - You don't have enough LBRY credits to pay for this stream. + + {__("You don't have enough LBRY credits to pay for this stream.")} - - LBRY was unable to download the stream {uri}. + + {__("LBRY was unable to download the stream")} {uri}. - deleteFile(fileInfo.outpoint, deleteChecked)} - onAborted={closeModal}> -

    Are you sure you'd like to remove {title} from LBRY?

    + deleteFile(fileInfo.outpoint, deleteChecked)} + onAborted={closeModal} + > +

    + {__("Are you sure you'd like to remove")} {title} + {" "}{__("from LBRY?")} +

    - +
    ); } } -export default FileActions +export default FileActions; diff --git a/ui/js/component/fileCard/index.js b/ui/js/component/fileCard/index.js index 89ebc5040..dcf1aad5c 100644 --- a/ui/js/component/fileCard/index.js +++ b/ui/js/component/fileCard/index.js @@ -1,34 +1,21 @@ -import React from 'react' -import { - connect -} from 'react-redux' -import { - doNavigate, -} from 'actions/app' -import { - doResolveUri, - doCancelResolveUri, -} from 'actions/content' -import { - selectObscureNsfw, -} from 'selectors/app' +import React from "react"; +import { connect } from "react-redux"; +import { doNavigate } from "actions/app"; +import { doResolveUri, doCancelResolveUri } from "actions/content"; +import { selectObscureNsfw } from "selectors/app"; import { makeSelectClaimForUri, makeSelectMetadataForUri, -} from 'selectors/claims' -import { - makeSelectFileInfoForUri, -} from 'selectors/file_info' -import { - makeSelectIsResolvingForUri, -} from 'selectors/content' -import FileCard from './view' +} from "selectors/claims"; +import { makeSelectFileInfoForUri } from "selectors/file_info"; +import { makeSelectIsResolvingForUri } from "selectors/content"; +import FileCard from "./view"; const makeSelect = () => { - const selectClaimForUri = makeSelectClaimForUri() - const selectFileInfoForUri = makeSelectFileInfoForUri() - const selectMetadataForUri = makeSelectMetadataForUri() - const selectResolvingUri = makeSelectIsResolvingForUri() + const selectClaimForUri = makeSelectClaimForUri(); + const selectFileInfoForUri = makeSelectFileInfoForUri(); + const selectMetadataForUri = makeSelectMetadataForUri(); + const selectResolvingUri = makeSelectIsResolvingForUri(); const select = (state, props) => ({ claim: selectClaimForUri(state, props), @@ -36,15 +23,15 @@ const makeSelect = () => { obscureNsfw: selectObscureNsfw(state), metadata: selectMetadataForUri(state, props), isResolvingUri: selectResolvingUri(state, props), - }) + }); - return select -} + return select; +}; -const perform = (dispatch) => ({ +const perform = dispatch => ({ navigate: (path, params) => dispatch(doNavigate(path, params)), - resolveUri: (uri) => dispatch(doResolveUri(uri)), - cancelResolveUri: (uri) => dispatch(doCancelResolveUri(uri)) -}) + resolveUri: uri => dispatch(doResolveUri(uri)), + cancelResolveUri: uri => dispatch(doCancelResolveUri(uri)), +}); -export default connect(makeSelect, perform)(FileCard) +export default connect(makeSelect, perform)(FileCard); diff --git a/ui/js/component/fileCard/view.jsx b/ui/js/component/fileCard/view.jsx index 918476a53..70b8e8132 100644 --- a/ui/js/component/fileCard/view.jsx +++ b/ui/js/component/fileCard/view.jsx @@ -1,42 +1,33 @@ -import React from 'react'; -import lbry from 'lbry.js'; -import lbryuri from 'lbryuri.js'; -import Link from 'component/link'; -import {Thumbnail, TruncatedText, Icon} from 'component/common'; -import FilePrice from 'component/filePrice' -import UriIndicator from 'component/uriIndicator'; +import React from "react"; +import lbry from "lbry.js"; +import lbryuri from "lbryuri.js"; +import Link from "component/link"; +import { Thumbnail, TruncatedText, Icon } from "component/common"; +import FilePrice from "component/filePrice"; +import UriIndicator from "component/uriIndicator"; -class FileCard extends React.Component { +class FileCard extends React.PureComponent { componentWillMount() { - this.resolve(this.props) + this.resolve(this.props); } componentWillReceiveProps(nextProps) { - this.resolve(nextProps) + this.resolve(nextProps); } resolve(props) { - const { - isResolvingUri, - resolveUri, - claim, - uri, - } = props + const { isResolvingUri, resolveUri, claim, uri } = props; - if(!isResolvingUri && claim === undefined && uri) { - resolveUri(uri) + if (!isResolvingUri && claim === undefined && uri) { + resolveUri(uri); } } componentWillUnmount() { - const { - isResolvingUri, - cancelResolveUri, - uri - } = this.props + const { isResolvingUri, cancelResolveUri, uri } = this.props; if (isResolvingUri) { - cancelResolveUri(uri) + cancelResolveUri(uri); } } @@ -53,56 +44,75 @@ class FileCard extends React.Component { } render() { - - const { - claim, - fileInfo, - metadata, - isResolvingUri, - navigate, - } = this.props + const { claim, fileInfo, metadata, isResolvingUri, navigate } = this.props; const uri = lbryuri.normalize(this.props.uri); - const title = !isResolvingUri && metadata && metadata.title ? metadata.title : uri; + const title = !isResolvingUri && metadata && metadata.title + ? metadata.title + : uri; const obscureNsfw = this.props.obscureNsfw && metadata && metadata.nsfw; - let description = "" + let description = ""; if (isResolvingUri) { - description = "Loading..." + description = __("Loading..."); } else if (metadata && metadata.description) { - description = metadata.description + description = metadata.description; } else if (claim === null) { - description = 'This address contains no content.' + description = __("This address contains no content."); } return ( -
    +
    - navigate('/show', { uri })} className="card__link"> + navigate("/show", { uri })} + className="card__link" + >
    -
    {title}
    +
    + {title} +
    - + - { fileInfo ? {' '} : '' } + {fileInfo + ? {" "} + : ""}
    - {metadata && metadata.thumbnail && -
    - } + {metadata && + metadata.thumbnail && +
    }
    - {description} + {description}
    {obscureNsfw && this.state.hovered - ?
    -

    - This content is Not Safe For Work. - To view adult content, please change your navigate('settings')} label="Settings" />. -

    -
    + ?
    +

    + {__( + "This content is Not Safe For Work. To view adult content, please change your" + )} + {" "} + navigate("settings")} + label={__("Settings")} + />. +

    +
    : null}
    @@ -110,4 +120,4 @@ class FileCard extends React.Component { } } -export default FileCard +export default FileCard; diff --git a/ui/js/component/fileList/index.js b/ui/js/component/fileList/index.js index dd0209b40..966481a30 100644 --- a/ui/js/component/fileList/index.js +++ b/ui/js/component/fileList/index.js @@ -1,13 +1,9 @@ -import React from 'react' -import { - connect -} from 'react-redux' -import FileList from './view' +import React from "react"; +import { connect } from "react-redux"; +import FileList from "./view"; -const select = (state) => ({ -}) +const select = state => ({}); -const perform = (dispatch) => ({ -}) +const perform = dispatch => ({}); -export default connect(select, perform)(FileList) +export default connect(select, perform)(FileList); diff --git a/ui/js/component/fileList/view.jsx b/ui/js/component/fileList/view.jsx index eb3b620b8..664ae97d3 100644 --- a/ui/js/component/fileList/view.jsx +++ b/ui/js/component/fileList/view.jsx @@ -1,20 +1,20 @@ -import React from 'react'; -import lbry from 'lbry.js'; -import lbryuri from 'lbryuri.js'; -import Link from 'component/link'; -import {FormField} from 'component/form.js'; -import FileTile from 'component/fileTile'; -import rewards from 'rewards.js'; -import lbryio from 'lbryio.js'; -import {BusyMessage, Thumbnail} from 'component/common.js'; +import React from "react"; +import lbry from "lbry.js"; +import lbryuri from "lbryuri.js"; +import Link from "component/link"; +import { FormField } from "component/form.js"; +import FileTile from "component/fileTile"; +import rewards from "rewards.js"; +import lbryio from "lbryio.js"; +import { BusyMessage, Thumbnail } from "component/common.js"; -class FileList extends React.Component { +class FileList extends React.PureComponent { constructor(props) { - super(props) + super(props); this.state = { - sortBy: 'date', - } + sortBy: "date", + }; this._sortFunctions = { date: function(fileInfos) { @@ -22,8 +22,12 @@ class FileList extends React.Component { }, title: function(fileInfos) { return fileInfos.slice().sort(function(fileInfo1, fileInfo2) { - const title1 = fileInfo1.metadata ? fileInfo1.metadata.stream.metadata.title.toLowerCase() : fileInfo1.name; - const title2 = fileInfo2.metadata ? fileInfo2.metadata.stream.metadata.title.toLowerCase() : fileInfo2.name; + const title1 = fileInfo1.metadata + ? fileInfo1.metadata.stream.metadata.title.toLowerCase() + : fileInfo1.name; + const title2 = fileInfo2.metadata + ? fileInfo2.metadata.stream.metadata.title.toLowerCase() + : fileInfo2.name; if (title1 < title2) { return -1; } else if (title1 > title2) { @@ -31,63 +35,66 @@ class FileList extends React.Component { } else { return 0; } - }) + }); }, filename: function(fileInfos) { - return fileInfos.slice().sort(function({file_name: fileName1}, {file_name: fileName2}) { - const fileName1Lower = fileName1.toLowerCase(); - const fileName2Lower = fileName2.toLowerCase(); - if (fileName1Lower < fileName2Lower) { - return -1; - } else if (fileName2Lower > fileName1Lower) { - return 1; - } else { - return 0; - } - }) + return fileInfos + .slice() + .sort(function({ file_name: fileName1 }, { file_name: fileName2 }) { + const fileName1Lower = fileName1.toLowerCase(); + const fileName2Lower = fileName2.toLowerCase(); + if (fileName1Lower < fileName2Lower) { + return -1; + } else if (fileName2Lower > fileName1Lower) { + return 1; + } else { + return 0; + } + }); }, - } + }; } handleSortChanged(event) { this.setState({ sortBy: event.target.value, - }) + }); } render() { - const { - handleSortChanged, - fetching, - fileInfos, - } = this.props - const { - sortBy, - } = this.state - const content = [] + const { handleSortChanged, fetching, fileInfos } = this.props; + const { sortBy } = this.state; + const content = []; this._sortFunctions[sortBy](fileInfos).forEach(fileInfo => { const uri = lbryuri.build({ contentName: fileInfo.name, channelName: fileInfo.channel_name, - }) - content.push() - }) + }); + content.push( + + ); + }); return (
    - { fetching && } - - Sort by { ' ' } + {fetching && } + + {__("Sort by")} {" "} - - - + + + {content}
    - ) + ); } } -export default FileList +export default FileList; diff --git a/ui/js/component/fileListSearch/index.js b/ui/js/component/fileListSearch/index.js index ed452052b..8008aaaef 100644 --- a/ui/js/component/fileListSearch/index.js +++ b/ui/js/component/fileListSearch/index.js @@ -1,29 +1,23 @@ -import React from 'react' -import { - connect, -} from 'react-redux' -import { - doSearch, -} from 'actions/search' +import React from "react"; +import { connect } from "react-redux"; +import { doSearch } from "actions/search"; import { selectIsSearching, selectCurrentSearchResults, selectSearchQuery, -} from 'selectors/search' -import { - doNavigate, -} from 'actions/app' -import FileListSearch from './view' +} from "selectors/search"; +import { doNavigate } from "actions/app"; +import FileListSearch from "./view"; -const select = (state) => ({ +const select = state => ({ isSearching: selectIsSearching(state), query: selectSearchQuery(state), - results: selectCurrentSearchResults(state) -}) + results: selectCurrentSearchResults(state), +}); -const perform = (dispatch) => ({ - navigate: (path) => dispatch(doNavigate(path)), - search: (search) => dispatch(doSearch(search)) -}) +const perform = dispatch => ({ + navigate: path => dispatch(doNavigate(path)), + search: search => dispatch(doSearch(search)), +}); -export default connect(select, perform)(FileListSearch) +export default connect(select, perform)(FileListSearch); diff --git a/ui/js/component/fileListSearch/view.jsx b/ui/js/component/fileListSearch/view.jsx index 986d8aa5c..bd8efeb00 100644 --- a/ui/js/component/fileListSearch/view.jsx +++ b/ui/js/component/fileListSearch/view.jsx @@ -1,76 +1,76 @@ -import React from 'react'; -import lbry from 'lbry'; -import lbryio from 'lbryio'; -import lbryuri from 'lbryuri'; -import lighthouse from 'lighthouse'; -import FileTile from 'component/fileTile' -import Link from 'component/link' -import {ToolTip} from 'component/tooltip.js'; -import {BusyMessage} from 'component/common.js'; +import React from "react"; +import lbry from "lbry"; +import lbryio from "lbryio"; +import lbryuri from "lbryuri"; +import lighthouse from "lighthouse"; +import FileTile from "component/fileTile"; +import Link from "component/link"; +import { ToolTip } from "component/tooltip.js"; +import { BusyMessage } from "component/common.js"; -const SearchNoResults = (props) => { - const { - navigate, - query, - } = props +const SearchNoResults = props => { + const { navigate, query } = props; - return
    - - No one has checked anything in for {query} yet. { ' ' } - navigate('/publish')} /> - -
    ; -} + return ( +
    + + {(__("No one has checked anything in for %s yet."), query)} {" "} + navigate("/publish")} /> + +
    + ); +}; -const FileListSearchResults = (props) => { - const { - results, - } = props +const FileListSearchResults = props => { + const { results } = props; const rows = [], seenNames = {}; //fix this when the search API returns claim IDs - for (let {name, claim, claim_id, channel_name, channel_id, txid, nout} of results) { + for (let { + name, + claim, + claim_id, + channel_name, + channel_id, + txid, + nout, + } of results) { const uri = lbryuri.build({ channelName: channel_name, contentName: name, claimId: channel_id || claim_id, }); - rows.push( - - ); + rows.push(); } - return ( -
    {rows}
    - ); -} + return
    {rows}
    ; +}; -class FileListSearch extends React.Component{ +class FileListSearch extends React.PureComponent { componentWillMount() { - this.props.search(this.props.query) + this.props.search(this.props.query); } render() { - const { - isSearching, - results - } = this.props + const { isSearching, results } = this.props; return (
    - {isSearching && !results && - } + {isSearching && + !results && + } - {isSearching && results && - } + {isSearching && + results && + } - {(results && !!results.length) ? - : - } + {results && !!results.length + ? + : }
    - ) + ); } } -export default FileListSearch \ No newline at end of file +export default FileListSearch; diff --git a/ui/js/component/filePrice/index.js b/ui/js/component/filePrice/index.js index 65e870a58..aa8f692aa 100644 --- a/ui/js/component/filePrice/index.js +++ b/ui/js/component/filePrice/index.js @@ -1,31 +1,32 @@ -import React from 'react' -import { - connect, -} from 'react-redux' -import { - doFetchCostInfoForUri, -} from 'actions/cost_info' +import React from "react"; +import { connect } from "react-redux"; +import { doFetchCostInfoForUri } from "actions/cost_info"; import { makeSelectCostInfoForUri, makeSelectFetchingCostInfoForUri, } from 'selectors/cost_info' +import { + makeSelectClaimForUri, +} from 'selectors/claims' import FilePrice from './view' const makeSelect = () => { - const selectCostInfoForUri = makeSelectCostInfoForUri() - const selectFetchingCostInfoForUri = makeSelectFetchingCostInfoForUri() + const selectCostInfoForUri = makeSelectCostInfoForUri(); + const selectFetchingCostInfoForUri = makeSelectFetchingCostInfoForUri(); + const selectClaim = makeSelectClaimForUri(); const select = (state, props) => ({ costInfo: selectCostInfoForUri(state, props), fetching: selectFetchingCostInfoForUri(state, props), - }) + claim: selectClaim(state, props), + }); - return select -} + return select; +}; -const perform = (dispatch) => ({ - fetchCostInfo: (uri) => dispatch(doFetchCostInfoForUri(uri)), +const perform = dispatch => ({ + fetchCostInfo: uri => dispatch(doFetchCostInfoForUri(uri)), // cancelFetchCostInfo: (uri) => dispatch(doCancelFetchCostInfoForUri(uri)) -}) +}); -export default connect(makeSelect, perform)(FilePrice) +export default connect(makeSelect, perform)(FilePrice); diff --git a/ui/js/component/filePrice/view.jsx b/ui/js/component/filePrice/view.jsx index 2a0872492..127bf28b0 100644 --- a/ui/js/component/filePrice/view.jsx +++ b/ui/js/component/filePrice/view.jsx @@ -1,44 +1,43 @@ -import React from 'react' -import { - CreditAmount, -} from 'component/common' +import React from "react"; +import { CreditAmount } from "component/common"; -class FilePrice extends React.Component{ +class FilePrice extends React.PureComponent { componentWillMount() { - this.fetchCost(this.props) + this.fetchCost(this.props); } componentWillReceiveProps(nextProps) { - this.fetchCost(nextProps) + this.fetchCost(nextProps); } fetchCost(props) { - const { - costInfo, - fetchCostInfo, - uri, - fetching, - } = props + const { costInfo, fetchCostInfo, uri, fetching, claim } = props; - if (costInfo === undefined && !fetching) { - fetchCostInfo(uri) + if (costInfo === undefined && !fetching && claim) { + fetchCostInfo(uri); } } render() { - const { - costInfo, - look = 'indicator', - } = this.props + const { costInfo, look = "indicator" } = this.props; - const isEstimate = costInfo ? !costInfo.includesData : null + const isEstimate = costInfo ? !costInfo.includesData : null; if (!costInfo) { - return ???; + return ( + ??? + ); } - return + return ( + + ); } } -export default FilePrice +export default FilePrice; diff --git a/ui/js/component/fileTile/index.js b/ui/js/component/fileTile/index.js index d61e58b64..58a34b13d 100644 --- a/ui/js/component/fileTile/index.js +++ b/ui/js/component/fileTile/index.js @@ -1,33 +1,21 @@ -import React from 'react' -import { - connect -} from 'react-redux' -import { - doNavigate, -} from 'actions/app' -import { - doResolveUri, -} from 'actions/content' +import React from "react"; +import { connect } from "react-redux"; +import { doNavigate } from "actions/app"; +import { doResolveUri } from "actions/content"; import { makeSelectClaimForUri, makeSelectMetadataForUri, -} from 'selectors/claims' -import { - makeSelectFileInfoForUri, -} from 'selectors/file_info' -import { - selectObscureNsfw, -} from 'selectors/app' -import { - makeSelectIsResolvingForUri, -} from 'selectors/content' -import FileTile from './view' +} from "selectors/claims"; +import { makeSelectFileInfoForUri } from "selectors/file_info"; +import { selectObscureNsfw } from "selectors/app"; +import { makeSelectIsResolvingForUri } from "selectors/content"; +import FileTile from "./view"; const makeSelect = () => { - const selectClaimForUri = makeSelectClaimForUri() - const selectFileInfoForUri = makeSelectFileInfoForUri() - const selectMetadataForUri = makeSelectMetadataForUri() - const selectResolvingUri = makeSelectIsResolvingForUri() + const selectClaimForUri = makeSelectClaimForUri(); + const selectFileInfoForUri = makeSelectFileInfoForUri(); + const selectMetadataForUri = makeSelectMetadataForUri(); + const selectResolvingUri = makeSelectIsResolvingForUri(); const select = (state, props) => ({ claim: selectClaimForUri(state, props), @@ -35,14 +23,14 @@ const makeSelect = () => { obscureNsfw: selectObscureNsfw(state), metadata: selectMetadataForUri(state, props), isResolvingUri: selectResolvingUri(state, props), - }) + }); - return select -} + return select; +}; -const perform = (dispatch) => ({ +const perform = dispatch => ({ navigate: (path, params) => dispatch(doNavigate(path, params)), - resolveUri: (uri) => dispatch(doResolveUri(uri)), -}) + resolveUri: uri => dispatch(doResolveUri(uri)), +}); -export default connect(makeSelect, perform)(FileTile) \ No newline at end of file +export default connect(makeSelect, perform)(FileTile); diff --git a/ui/js/component/fileTile/view.jsx b/ui/js/component/fileTile/view.jsx index 250bf6296..27511defd 100644 --- a/ui/js/component/fileTile/view.jsx +++ b/ui/js/component/fileTile/view.jsx @@ -1,38 +1,41 @@ -import React from 'react'; -import lbry from 'lbry.js'; -import lbryuri from 'lbryuri.js'; -import Link from 'component/link'; -import FileActions from 'component/fileActions'; -import {Thumbnail, TruncatedText,} from 'component/common.js'; -import FilePrice from 'component/filePrice' -import UriIndicator from 'component/uriIndicator'; +import React from "react"; +import lbry from "lbry.js"; +import lbryuri from "lbryuri.js"; +import Link from "component/link"; +import FileActions from "component/fileActions"; +import { Thumbnail, TruncatedText } from "component/common.js"; +import FilePrice from "component/filePrice"; +import UriIndicator from "component/uriIndicator"; -class FileTile extends React.Component { - static SHOW_EMPTY_PUBLISH = "publish" - static SHOW_EMPTY_PENDING = "pending" +class FileTile extends React.PureComponent { + static SHOW_EMPTY_PUBLISH = "publish"; + static SHOW_EMPTY_PENDING = "pending"; constructor(props) { - super(props) + super(props); this.state = { showNsfwHelp: false, - } + }; } componentDidMount() { - const { - isResolvingUri, - resolveUri, - claim, - uri, - } = this.props + this.resolve(this.props); + } - if(!isResolvingUri && !claim && uri) { - resolveUri(uri) - } + componentWillReceiveProps(nextProps) { + this.resolve(nextProps); + } + + resolve({ isResolvingUri, claim, uri, resolveUri }) { + if (!isResolvingUri && claim === undefined && uri) resolveUri(uri); } handleMouseOver() { - if (this.props.obscureNsfw && this.props.metadata && this.props.metadata.nsfw) { + if ( + this.props.obscureNsfw && + this.props.metadata && + this.props.metadata.nsfw + ) { this.setState({ showNsfwHelp: true, }); @@ -55,40 +58,61 @@ class FileTile extends React.Component { showEmpty, navigate, hidePrice, - } = this.props + } = this.props; const uri = lbryuri.normalize(this.props.uri); const isClaimed = !!claim; - const isClaimable = lbryuri.isClaimable(uri) - const title = isClaimed && metadata && metadata.title ? metadata.title : uri; + const isClaimable = lbryuri.isClaimable(uri); + const title = isClaimed && metadata && metadata.title + ? metadata.title + : uri; const obscureNsfw = this.props.obscureNsfw && metadata && metadata.nsfw; - let onClick = () => navigate('/show', { uri }) + let onClick = () => navigate("/show", { uri }); - let description = "" + let description = ""; if (isClaimed) { - description = metadata && metadata.description + description = metadata && metadata.description; } else if (isResolvingUri) { - description = "Loading..." + description = __("Loading..."); } else if (showEmpty === FileTile.SHOW_EMPTY_PUBLISH) { - onClick = () => navigate('/publish', { }) - description = - This location is unused. { ' ' } - { isClaimable && Put something here! } - + onClick = () => navigate("/publish", {}); + description = ( + + {__("This location is unused.")} {" "} + {isClaimable && + {__("Put something here!")}} + + ); } else if (showEmpty === FileTile.SHOW_EMPTY_PENDING) { - description = This file is pending confirmation. + description = ( + + {__("This file is pending confirmation.")} + + ); } return ( -
    +
    -
    -
    +
    - { !hidePrice ? : null} + {!hidePrice ? : null}
    {uri}

    {title}

    @@ -101,16 +125,23 @@ class FileTile extends React.Component {
    {this.state.showNsfwHelp - ?
    -

    - This content is Not Safe For Work. - To view adult content, please change your navigate('/settings')} label="Settings" />. -

    -
    + ?
    +

    + {__( + "This content is Not Safe For Work. To view adult content, please change your" + )} + {" "} + navigate("/settings")} + label={__("Settings")} + />. +

    +
    : null}
    ); } } -export default FileTile +export default FileTile; diff --git a/ui/js/component/form.js b/ui/js/component/form.js index 416011df3..7ab78325c 100644 --- a/ui/js/component/form.js +++ b/ui/js/component/form.js @@ -1,27 +1,27 @@ -import React from 'react'; -import FileSelector from './file-selector.js'; -import {Icon} from './common.js'; +import React from "react"; +import FileSelector from "./file-selector.js"; +import { Icon } from "./common.js"; var formFieldCounter = 0, - formFieldFileSelectorTypes = ['file', 'directory'], - formFieldNestedLabelTypes = ['radio', 'checkbox']; + formFieldFileSelectorTypes = ["file", "directory"], + formFieldNestedLabelTypes = ["radio", "checkbox"]; function formFieldId() { - return "form-field-" + (++formFieldCounter); + return "form-field-" + ++formFieldCounter; } -export class FormField extends React.Component { +export class FormField extends React.PureComponent { static propTypes = { type: React.PropTypes.string.isRequired, prefix: React.PropTypes.string, postfix: React.PropTypes.string, - hasError: React.PropTypes.bool - } + hasError: React.PropTypes.bool, + }; constructor(props) { super(props); - this._fieldRequiredText = 'This field is required'; + this._fieldRequiredText = __("This field is required"); this._type = null; this._element = null; @@ -32,15 +32,15 @@ export class FormField extends React.Component { } componentWillMount() { - if (['text', 'number', 'radio', 'checkbox'].includes(this.props.type)) { - this._element = 'input'; + if (["text", "number", "radio", "checkbox"].includes(this.props.type)) { + this._element = "input"; this._type = this.props.type; - } else if (this.props.type == 'text-number') { - this._element = 'input'; - this._type = 'text'; + } else if (this.props.type == "text-number") { + this._element = "input"; + this._type = "text"; } else if (formFieldFileSelectorTypes.includes(this.props.type)) { - this._element = 'input'; - this._type = 'hidden'; + this._element = "input"; + this._type = "hidden"; } else { // Non field, e.g.