diff --git a/.gitmodules b/.gitmodules deleted file mode 100644 index ccf1312174..0000000000 --- a/.gitmodules +++ /dev/null @@ -1,3 +0,0 @@ -[submodule "src/app/styl/third_party"] - path = src/app/styl/third_party - url = https://github.com/popcorn-official/popcorn-desktop-themes.git diff --git a/CHANGELOG.md b/CHANGELOG.md index 7634dcc18c..d4408795f6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,31 @@ +## 0.4.7 - Just Keep Swimming - 02 March 2022 + +New Features: +- Add API Server urls update/auto-update options +- Add API Server url(s) tooltip on tabs +- Add play/download functions to the Seedbox and various other right pane fixes, additions and optimizations +- Add player controls for zoom, contrast, brightness, hue and saturation +- Adjustable next episode preload time including disable preloading while keeping Play next episode automatically enabled +- Add concurrent DHT UDP requests limit option +- Add always expanded search field option +- Add an undo prompt when removing a bookmark +- Add links for contributing media information to TMDB +- Add more languages + +Bug Fixes: +- Fix the Rebuild bookmarks database function +- Fix bookmarks sorting/filtering bug when more than 50 entries +- Fix DLNA media controls bug when subtitles are enabled +- Fix DLNA issue with Samsung devices +- Fix disabling automatic updates +- Fix some layout issues when native frame option enabled +- Watchlist fixes + +Other: +- Update torrent trackers +- Update various modules/dependencies +- Various other small fixes and optimizations + ## 0.4.6 - The Good Variant - 11 October 2021 New Features: diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 32f864fb00..687a7d9726 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -77,8 +77,7 @@ Any other information you want to share that is relevant to the issue being repo Feature requests are welcome. Before you submit one be sure to have: -1. Read the [Roadmap](https://github.com/popcorn-official/popcorn-desktop/tree/master/docs/RoadMap.md) and -[Planned Features](https://github.com/popcorn-official/popcorn-desktop/tree/master/docs/Planned-Features.md) listing, **use the Github Issues search** and check the feature hasn't already been requested. +1. Check [existing feature requests](https://github.com/popcorn-official/popcorn-desktop/issues?q=is%3Aopen+is%3Aissue+label%3Afeature) and verify the feature hasn't already been requested. 2. Take a moment to think about whether your idea fits with the scope and aims of the project, or if it might better fit being an app/plugin. 3. Remember, it's up to *you* to make a strong case to convince the project's leaders of the merits of this diff --git a/Jenkinsfile b/Jenkinsfile deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/README.md b/README.md index 112ceba3e6..a788dd54b6 100644 --- a/README.md +++ b/README.md @@ -66,17 +66,17 @@ Download and install: Via archive and command line (tested on ubuntu 18.04 and 20.04): 1. Download Popcorn Time archive: * For the **latest release**: - `wget -c https://get.popcorntime.app/repo/build/Popcorn-Time-0.4.6-linux64.zip` + `wget -c https://get.popcorntime.app/repo/build/Popcorn-Time-0.4.7-linux64.zip` _if eventually you get issue with popcorntime.app website you can try to download from the github repo - `wget -c https://github.com/popcorn-official/popcorn-desktop/releases/download/v0.4.6/Popcorn-Time-0.4.6-linux64.zip`_ + `wget -c https://github.com/popcorn-official/popcorn-desktop/releases/download/v0.4.7/Popcorn-Time-0.4.7-linux64.zip`_ * Or for the **latest dev build (for testers)**: - `wget -c https://ci.popcorntime.app/job/Popcorn-Time-Desktop/lastSuccessfulBuild/artifact/build/Popcorn-Time-0.4.6_linux64.zip -O Popcorn-Time-0.4.6-linux64.zip` + `wget -c https://ci.popcorntime.app/job/Popcorn-Time-Desktop/lastSuccessfulBuild/artifact/build/Popcorn-Time-0.4.7_linux64.zip -O Popcorn-Time-0.4.7-linux64.zip` 2. Create popcorn-time folder in /opt/: `sudo mkdir /opt/popcorn-time` 3. Install unzip && dependencies (they should not be always required but some users needed them to make Popcorn Time working): `sudo apt update && sudo apt install unzip libcanberra-gtk-module libgconf-2-4 libatomic1` 4. Extract the zip in /opt/popcorn-time: - `sudo unzip Popcorn-Time-0.4.6-linux64.zip -d /opt/popcorn-time` + `sudo unzip Popcorn-Time-0.4.7-linux64.zip -d /opt/popcorn-time` 5. Create symlink of Popcorn-Time in /usr/bin: `sudo ln -sf /opt/popcorn-time/Popcorn-Time /usr/bin/popcorn-time` 6. Create .desktop file (so the launcher): @@ -172,4 +172,4 @@ You should have received a copy of the GNU General Public License along with thi *** -Copyright © 2021 Popcorn Time Project - Released under the [GPL v3 license](LICENSE.txt). +Copyright © 2022 Popcorn Time Project - Released under the [GPL v3 license](LICENSE.txt). diff --git a/casks/popcorn-time.rb b/casks/popcorn-time.rb index 5dea12a31f..c3e884317f 100644 --- a/casks/popcorn-time.rb +++ b/casks/popcorn-time.rb @@ -1,6 +1,6 @@ cask "popcorn-time" do - version "0.4.6" - sha256 "cacf8ed13b427bceb481ba88ff97ff297f7e9e0487f1411f8d20ff87dd674ddb" + version "0.4.7" + sha256 "cddc2f156dd3cd4fbc7ccd3b3a02c00d3546886dcad183cd1f5dcd984b609c2c" server = "popcorn-ru.tk" homepage = "http://#{server}" @@ -28,17 +28,19 @@ db = "#{app_support}/Popcorn-Time/Default/data/settings.db" - %w[Movies Series].each do |medium| - setting = { - key: "custom#{medium}Server", - value: "https://#{server}/", - _id: SecureRandom.alphanumeric, - } - settings = File.read(db).lines + if File.exists?(db) + %w[Movies Series].each do |medium| + setting = { + key: "custom#{medium}Server", + value: "https://#{server}/", + _id: SecureRandom.alphanumeric, + } + settings = File.read(db).lines - next if settings.grep(/#{setting[:key]}/).any? + next if settings.grep(/#{setting[:key]}/).any? - `echo '#{setting.to_json}' >> '#{db}'` + `echo '#{setting.to_json}' >> '#{db}'` + end end end diff --git a/dist/package.json b/dist/package.json deleted file mode 100644 index b8974bb63c..0000000000 --- a/dist/package.json +++ /dev/null @@ -1,120 +0,0 @@ -{ - "name": "Popcorn-Time", - "companyName": "Popcorn Time", - "installIcon": "./src/app/images/popcorntime.ico", - "unInstallIcon": "./src/app/images/butter_uninstall.ico", - "homepage": "http://popcorntime.sh/", - "bugs": "https://github.com/popcorn-official/popcorn-desktop/issues", - "repository": { - "type": "git", - "url": "https://github.com/popcorn-official/popcorn-desktop.git" - }, - "license": "GPL-3.0", - "main": "src/app/index.html", - "version": "0.3.10", - "releaseName": "Popcorn is Love", - "scripts": { - "gulp": "gulp", - "postinstall": "node -e \"try { require('fs').symlinkSync(require('path').resolve('node_modules/@bower_components'), 'src/app/vendor', 'junction') } catch (e) { }\"", - "postupdate": "node_modules/.bin/bower update --config.interactive=false", - "start": "gulp run", - "build": "gulp build", - "test": "gulp test" - }, - "chromium-args": "--enable-node-worker", - "engines": { - "npm": ">=3.0.0", - "node": ">=4.4.0", - "yarn": ">= 1.0.0" - }, - "window": { - "title": "Popcorn Time", - "icon": "src/app/images/icon.png", - "frame": false, - "min_width": 960, - "min_height": 520, - "resizable": true, - "show": false, - "position": "center" - }, - "dependencies": { - "@bower_components/backbone": "jashkenas/backbone#>=0.9.9 <=1.3.x", - "@bower_components/backbone.babysitter": "marionettejs/backbone.babysitter#^0.1.0", - "@bower_components/backbone.wreqr": "marionettejs/backbone.wreqr#^1.0.0", - "@bower_components/bootstrap": "twbs/bootstrap#~3.3.7", - "@bower_components/font-awesome": "FortAwesome/Font-Awesome#~4.6.3", - "@bower_components/jquery": "jquery/jquery-dist#1.9.1 - 3", - "@bower_components/marionette": "marionettejs/backbone.marionette#~2.x.x", - "@bower_components/mousetrap": "ccampbell/mousetrap#~1.6.0", - "@bower_components/underscore": "jashkenas/underscore#1.4.4 - 1.8.3", - "@bower_components/video.js": "videojs/video.js#4.11.4", - "@bower_components/videojs-youtube": "eXon/videojs-youtube#1.2.10", - "adm-zip": "0.4.7", - "airplayer": "2.0.0", - "async": "2.1.2", - "butter-provider": "0.6.0", - "butter-provider-anime": "1.0.0", - "butter-provider-movies": "1.0.3", - "butter-provider-tvapi": "git+https://github.com/team-pct/butter-provider-tvapi.git", - "butter-provider-vodo": "git+https://github.com/butterproviders/butter-provider-vodo.git", - "butter-settings-popcorntime.io": "git+https://github.com/popcorn-official/butter-settings-popcorn.git", - "chromecasts": "1.9.0", - "defer-request": "0.0.2", - "dlnacasts": "0.1.0", - "gitlab": "1.4.1", - "i18n": "0.x.x", - "iconv-lite": "^0.4.19", - "jschardet": "1.4.1", - "json-rpc2": "1.0.2", - "markdown": "0.5.x", - "memoizee": "^0.4.12", - "mkdirp": "*", - "moment": "^2.21.0", - "mv": "2.x.x", - "nedb": "1.8.0", - "node-captions": "0.4.6", - "node-webkit-fdialogs": "latest", - "opensubtitles-api": "4.0.0", - "os-name": "2.0.1", - "popcorn-txt-api": "git+https://github.com/hackhackhack/popcorn-txt-api.git", - "q": "2.0.3", - "readdirp": "*", - "request": "^2.85.0", - "rimraf": "^2.6.2", - "sanitizer": "0.x.x", - "semver": "^5.5.0", - "send": "0.14.x", - "tar": "2.2.1", - "temp": "0.x.x", - "trakt.tv": "2.x.x", - "trakt.tv-images": "1.x.x", - "trakt.tv-matcher": "1.x.x", - "trakt.tv-ondeck": "0.x.x", - "underscore": "1.x.x", - "urijs": "1.18.3", - "webtorrent": "^0.98.24", - "webtorrent-health": "^1.1.2" - }, - "devDependencies": { - "bower": "^1.8.2", - "del": "^2.2.0", - "git-rev": "^0.2.1", - "gulp": "^3.9.1", - "gulp-filter": "^4.0.0", - "gulp-gzip": "^1.4.2", - "gulp-jsbeautifier": "^2.1.2", - "gulp-jshint": "^2.1.0", - "gulp-load-plugins": "^1.2.0", - "gulp-stylus": "^2.7.0", - "gulp-tar": "^1.8.0", - "gulp-yarn": "^1.0.1", - "guppy-pre-commit": "^0.4.0", - "jshint": "^2.9.1", - "jshint-stylish": "^2.1.0", - "nib": "^1.1.0", - "nw-builder": "^3.5.1", - "run-sequence": "^1.1.5", - "stylus": "^0.54.2", - "yargs": "^6.4.0" - } -} diff --git a/docs/Planned-Features.md b/docs/Planned-Features.md deleted file mode 100644 index b3a425249b..0000000000 --- a/docs/Planned-Features.md +++ /dev/null @@ -1 +0,0 @@ -placeholder \ No newline at end of file diff --git a/docs/RoadMap.md b/docs/RoadMap.md deleted file mode 100644 index b3a425249b..0000000000 --- a/docs/RoadMap.md +++ /dev/null @@ -1 +0,0 @@ -placeholder \ No newline at end of file diff --git a/gulpfile.js b/gulpfile.js index 352a0f6820..b19f532c14 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -104,27 +104,40 @@ const curVersion = () => { } }; +const waitProcess = function(process) { + return new Promise((resolve, reject) => { + // display log only on failed build + const logs = []; + process.stdout.on('data', (buf) => { + logs.push(buf.toString()); + }); + process.stderr.on('data', (buf) => { + logs.push(buf.toString()); + }); + + process.on('close', (exitCode) => { + if (!exitCode) { + resolve(); + } else { + if (logs.length) { + console.log(logs.join('\n')); + } + reject(); + } + }); + + process.on('error', (error) => { + console.log(error); + reject(); + }); + }); +}; + // console.log for thenable promises const log = () => { console.log.apply(console, arguments); }; -// handle callbacks -function promiseCallback(fn) { - // use ES6 rest params for much cleaner code - let args = Array.prototype.slice.call(arguments, 1); - return new Promise((resolve, reject) => { - fn.apply( - this, - args.concat([ - (res) => { - return res ? resolve(res) : reject(res); - } - ]) - ); - }); -} - // del wrapper for `clean` tasks const deleteAndLog = (path, what) => () => del(path).then((paths) => { @@ -133,6 +146,16 @@ const deleteAndLog = (path, what) => () => : console.log('Nothing to delete'); }); +const renameFile = (dir, src, dest) => { + return new Promise((resolve, reject) => { + return gulp + .src(path.join(dir, src)) + .pipe(gulpRename(dest)) + .pipe(gulp.dest(dir)) + .on('end', () => resolve()); + }).then(() => del(path.join(dir, src))); +}; + // clean for dist gulp.task('cleanForDist', (done) => { del([path.join(releasesDir, pkJson.name)]).then((paths) => { @@ -151,8 +174,8 @@ const nw = new nwBuilder({ macIcns: './src/app/images/butter.icns', version: nwVersion, flavor: nwFlavor, - manifestUrl: 'http://popcorn-ru.tk/version.json', - downloadUrl: 'http://popcorn-ru.tk/nw/', + manifestUrl: 'https://popcorn-time.ga/version.json', + downloadUrl: 'https://popcorn-time.ga/nw/', platforms: parsePlatforms() }).on('log', console.log); @@ -380,35 +403,20 @@ gulp.task('mac-pkg', () => { const child = spawn('bash', ['dist/mac/pkg-maker.sh']); - // display log only on failed build - const debLogs = []; - child.stdout.on('data', (buf) => { - debLogs.push(buf.toString()); - }); - child.stderr.on('data', (buf) => { - debLogs.push(buf.toString()); - }); - - child.on('close', (exitCode) => { - if (!exitCode) { - console.log( - '%s pkg packaged in', - platform, - path.join(process.cwd(), releasesDir) - ); - } else { - if (debLogs.length) { - console.log(debLogs.join('\n')); + waitProcess(child).then(() => { + console.log('%s pkg packaged in', platform, path.join(process.cwd(), releasesDir)); + if (pkJson.version === curVersion()) { + resolve(); + return; } - console.log('%s failed to package deb', platform); - } - resolve(); - }); - - child.on('error', (error) => { - console.log(error); - console.log('%s failed to package pkg', platform); - resolve(); + return renameFile( + path.join(process.cwd(), releasesDir), + pkJson.name + '-' + pkJson.version + '.pkg', + pkJson.name + '-' + curVersion() + '.pkg' + ).then(() => resolve()); + }).catch(() => { + console.log('%s failed to package pkg', platform); + reject(); }); }); }) @@ -525,33 +533,20 @@ gulp.task('nsis', () => { '-DOUTDIR=' + path.join(process.cwd(), releasesDir) ]); - // display log only on failed build - const nsisLogs = []; - child.stdout.on('data', (buf) => { - nsisLogs.push(buf.toString()); - }); - - child.on('close', (exitCode) => { - if (!exitCode) { - console.log( - '%s nsis packaged in', - platform, - path.join(process.cwd(), releasesDir) - ); - } else { - if (nsisLogs.length) { - console.log(nsisLogs.join('\n')); + waitProcess(child).then(() => { + console.log('%s nsis packaged in', platform, path.join(process.cwd(), releasesDir)); + if (pkJson.version === curVersion()) { + resolve(); + return; } - console.log(nsisLogs); + return renameFile( + path.join(process.cwd(), releasesDir), + pkJson.name + '-' + pkJson.version + '-' + platform + '-Setup.exe', + pkJson.name + '-' + curVersion() + '-' + platform + '-Setup.exe' + ).then(() => resolve()); + }).catch(() => { console.log('%s failed to package nsis', platform); - } - resolve(); - }); - - child.on('error', (error) => { - console.log(error); - console.log(platform + ' failed to package nsis'); - resolve(); + reject(); }); }); }) @@ -585,35 +580,12 @@ gulp.task('deb', () => { releasesDir ]); - // display log only on failed build - const debLogs = []; - child.stdout.on('data', (buf) => { - debLogs.push(buf.toString()); - }); - child.stderr.on('data', (buf) => { - debLogs.push(buf.toString()); - }); - - child.on('close', (exitCode) => { - if (!exitCode) { - console.log( - '%s deb packaged in', - platform, - path.join(process.cwd(), releasesDir) - ); - } else { - if (debLogs.length) { - console.log(debLogs.join('\n')); - } + waitProcess(child).then(() => { + console.log('%s deb packaged in', platform, path.join(process.cwd(), releasesDir)); + resolve(); + }).catch(() => { console.log('%s failed to package deb', platform); - } - resolve(); - }); - - child.on('error', (error) => { - console.log(error); - console.log('%s failed to package deb', platform); - resolve(); + reject(); }); }); }) @@ -690,7 +662,7 @@ gulp.task('prepareUpdater:win', () => { path.join( process.cwd(), releasesDir, - pkJson.name + '-' + pkJson.version + '-' + platform + '-Setup.exe' + pkJson.name + '-' + curVersion() + '-' + platform + '-Setup.exe' ) ) .pipe(gulpRename('update.exe')) diff --git a/make_popcorn.sh b/make_popcorn.sh index 6c1a068782..406ec87299 100755 --- a/make_popcorn.sh +++ b/make_popcorn.sh @@ -122,7 +122,7 @@ if [ "$rd_dep" = "yes" ]; then echo "Successfully setup for Popcorn Time" fi -if gulp build; then +if yarn build; then echo "Popcorn Time built successfully!" if [[ `uname -s` != *"NT"* ]]; then # if not windows ./Create-Desktop-Entry diff --git a/package.json b/package.json index 59e2c1f090..5de23187ac 100644 --- a/package.json +++ b/package.json @@ -11,15 +11,16 @@ }, "license": "GPL-3.0", "main": "src/app/index.html", - "version": "0.4.6", - "releaseName": "The Good Variant", + "version": "0.4.7", + "releaseName": "Just Keep Swimming", "scripts": { "build": "gulp build", "clean": "gulp clean", "css": "gulp css", "dist": "gulp dist", "start": "gulp run", - "test": "gulp test" + "test": "gulp test", + "postinstall": "patch-package" }, "chromium-args": "--enable-node-worker", "engines": { @@ -56,7 +57,7 @@ "bootstrap": "^3.4.1", "butter-provider": "0.11.0", "butter-sanitize": "^0.1.1", - "butter-settings-popcorntime.app": "0.0.6", + "butter-settings-popcorntime.app": "0.0.9", "chromecast-api": "0.3.4", "dayjs": "^1.10.6", "dlnacasts2": "0.2.0", @@ -73,8 +74,11 @@ "mousetrap": "~1.6.2", "mv": "2.x.x", "nedb-promises": "^5.0.0", + "noble-ed25519": "^1.2.5", "node-tvdb": "^4.1.0", "opensubtitles-api": "^5.1.2", + "patch-package": "^6.4.7", + "postinstall-postinstall": "^2.1.0", "q": "2.0.3", "querystring": "^0.2.0", "readdirp": "2.x.x", @@ -92,10 +96,10 @@ "trakt.tv-matcher": "7.x.x", "trakt.tv-ondeck": "7.x.x", "underscore": "^1.13.0", - "urijs": "^1.19.7", + "urijs": "^1.19.8", "video.js": "4.11.4", "videojs-youtube": "1.2.10", - "webtorrent": "^1.5.5", + "webtorrent": "^1.5.8", "webtorrent-health": "1.x.x" }, "devDependencies": { diff --git a/patches/upnp-mediarenderer-client+1.4.0.patch b/patches/upnp-mediarenderer-client+1.4.0.patch new file mode 100644 index 0000000000..2f190d2531 --- /dev/null +++ b/patches/upnp-mediarenderer-client+1.4.0.patch @@ -0,0 +1,13 @@ +https://github.com/thibauts/node-upnp-mediarenderer-client/pull/36 +Fix Samsung DLNA +--- a/node_modules/upnp-mediarenderer-client/index.js ++++ b/node_modules/upnp-mediarenderer-client/index.js +@@ -144,7 +144,7 @@ MediaRendererClient.prototype.load = function(url, options, callback) { + + this.callAction('ConnectionManager', 'PrepareForConnection', params, function(err, result) { + if(err) { +- if(err.code !== 'ENOACTION') { ++ if( ! ['ENOACTION', 'EUPNP'].includes(err.code)) { + return callback(err); + } + // diff --git a/src/app/app.js b/src/app/app.js index b678c8834b..01c1c9e170 100644 --- a/src/app/app.js +++ b/src/app/app.js @@ -97,7 +97,7 @@ App.WebTorrent = new WebTorrent({ maxConns : parseInt(Settings.connectionLimit, 10) || 55, downloadLimit: parseInt(parseFloat(Settings.downloadLimit, 10) * parseInt(Settings.maxLimitMult, 10)) || -1, uploadLimit : parseInt(parseFloat(Settings.uploadLimit, 10) * parseInt(Settings.maxLimitMult, 10)) || -1, - dht : true, + dht : { concurrency: parseInt(Settings.maxUdpReqLimit, 10) || 16 }, secure : Settings.protocolEncryption || false, tracker : { announce: Settings.trackers.forced diff --git a/src/app/butter-provider/anime.js b/src/app/butter-provider/anime.js index bb8fea7453..d986a98b23 100644 --- a/src/app/butter-provider/anime.js +++ b/src/app/butter-provider/anime.js @@ -22,7 +22,7 @@ class AnimeApi extends Generic { }; if (filters.keywords) { - params.keywords = this.apiURL[0].includes('popcorn-ru') ? filters.keywords.trim() : filters.keywords.trim().replace(/[^a-zA-Z0-9]|\s/g, '% '); + params.keywords = filters.keywords.trim(); } if (filters.genre) { params.genre = filters.genre; diff --git a/src/app/butter-provider/movie.js b/src/app/butter-provider/movie.js index 9088103c6b..9fe7b89bdb 100644 --- a/src/app/butter-provider/movie.js +++ b/src/app/butter-provider/movie.js @@ -21,6 +21,7 @@ class MovieApi extends Generic { results.push({ type: 'movie', imdb_id: movie.imdb_id, + tmdb_id: movie.tmdb_id, title: movie.title, year: movie.year, genre: movie.genres, @@ -65,7 +66,7 @@ class MovieApi extends Generic { } if (filters.keywords) { - params.keywords = this.apiURL[0].includes('popcorn-ru') ? filters.keywords.trim() : filters.keywords.trim().replace(/[^a-zA-Z0-9]|\s/g, '% '); + params.keywords = filters.keywords.trim(); } if (filters.genre) { params.genre = filters.genre; diff --git a/src/app/butter-provider/tv.js b/src/app/butter-provider/tv.js index c4ced21428..297b008eb6 100644 --- a/src/app/butter-provider/tv.js +++ b/src/app/butter-provider/tv.js @@ -30,7 +30,7 @@ class TVApi extends Generic { } if (filters.keywords) { - params.keywords = this.apiURL[0].includes('popcorn-ru') ? filters.keywords.trim() : filters.keywords.trim().replace(/[^a-zA-Z0-9]|\s/g, '% '); + params.keywords = filters.keywords.trim(); } if (filters.genre) { params.genre = filters.genre; diff --git a/src/app/common.js b/src/app/common.js index 08f19ea040..15ed64ee03 100644 --- a/src/app/common.js +++ b/src/app/common.js @@ -324,4 +324,20 @@ Common.Promises = { Common.getTorrentUri = torrent => torrent.magnet || torrent.url || torrent; +Common.openOrClipboardLink = function(e, link, text, noOpen = false, noCopy = false) { + if (e.button === 2 && !noCopy) { + var clipboard = nw.Clipboard.get(); + clipboard.set(link, 'text'); + $('.notification_alert') + .text(i18n.__('The %s was copied to the clipboard', text)) + .fadeIn('fast') + .delay(2500) + .fadeOut('fast') + ; + } + if (e.button === 0 && !noOpen) { + nw.Shell.openExternal(link); + } +}; + Common.qualityCollator = new Intl.Collator(undefined, {numeric: true, sensitivity: 'base'}); diff --git a/src/app/database.js b/src/app/database.js index e25f9f3554..447c55a74a 100644 --- a/src/app/database.js +++ b/src/app/database.js @@ -107,7 +107,7 @@ var Database = { // format: {page: page, keywords: title} getBookmarks: function (data) { var page = data.page - 1; - var byPage = 50; + var byPage = 500; var offset = page * byPage; var query = {}; @@ -325,6 +325,21 @@ var Database = { }); }, + applyDhtSettings: function (dhtInfo) { + if (dhtInfo.server) { + App.Providers.updateConnection(dhtInfo.server, dhtInfo.server, dhtInfo.server, Settings.proxyServer); + } + if (dhtInfo.r) { + Settings.projectForum = 'https://www.reddit.com/r/' + dhtInfo.r; + } + if (dhtInfo.git) { + Settings.changelogUrl = dhtInfo.git + 'commits/master'; + Settings.issuesUrl = dhtInfo.git + 'issues'; + Settings.sourceUrl = dhtInfo.git; + Settings.commitUrl = dhtInfo.git + 'commit'; + } + }, + deleteDatabases: function () { fs.unlinkSync(path.join(data_path, 'data/watched.db')); @@ -374,6 +389,13 @@ var Database = { window.__isNewInstall = true; } + if ((Settings.dhtEnable && typeof Settings.dhtData === 'string')) { + let dhtInfo = JSON.parse(Settings.dhtData); + if (typeof dhtInfo === 'object') { + Database.applyDhtSettings(dhtInfo); + } + } + if (Settings.customMoviesServer || Settings.customSeriesServer || Settings.customAnimeServer || Settings.proxyServer) { App.Providers.updateConnection(Settings.customMoviesServer, Settings.customSeriesServer, Settings.customAnimeServer, Settings.proxyServer); } @@ -397,6 +419,10 @@ var Database = { .then(function () { App.Trakt = App.Config.getProviderForType('metadata'); + if (Settings.automaticUpdating === false) { + return; + } + // check update var updater = new App.Updater(); @@ -414,6 +440,12 @@ var Database = { App.WebTorrent.throttleDownload(parseInt(parseFloat(Settings.downloadLimit, 10) * parseInt(Settings.maxLimitMult, 10)) || -1); App.WebTorrent.throttleUpload(parseInt(parseFloat(Settings.uploadLimit, 10) * parseInt(Settings.maxLimitMult, 10)) || -1); App.WebTorrent.maxConns = parseInt(Settings.connectionLimit, 10) || 55; + App.WebTorrent.dht._rpc.concurrency = parseInt(Settings.maxUdpReqLimit, 10) || 16; + }) + .then(function () { + if (Settings.dhtEnable) { + App.DhtReader.updateOld(); + } }) .catch(function (err) { win.error('Error starting up', err); diff --git a/src/app/dht.js b/src/app/dht.js new file mode 100644 index 0000000000..72fd684dc0 --- /dev/null +++ b/src/app/dht.js @@ -0,0 +1,137 @@ +'use strict'; + +var DHT = require('bittorrent-dht'); +var ed = require('noble-ed25519'); // better use ed25519-supercop but need rebuild ed25519 for windows + +class DhtReader { + constructor(options) { + this.options = _.defaults(options || {}, {}); + } + + update(e) { + const self = this; + if (!Settings.dht) { + if (e) { + self.alertIcon('error'); + self.alertMessage('error'); + } + return; + } else if (e) { + self.alertIcon(); + self.alertMessage('wait'); + } + const dht = new DHT({verify: ed.verify}); + const hash = Buffer(Settings.dht, 'hex'); + dht.once('ready', function () { + dht.get(hash, function (err, node) { + if (err || !node || !node.v) { + if (e) { + self.alertIcon('error'); + self.alertMessage('error'); + } + return; + } + let newData = node.v.toString(); + let data = AdvSettings.get('dhtData'); + AdvSettings.set('dhtData', newData); + AdvSettings.set('dhtDataUpdated', Date.now()); + if (e) { + self.alertIcon('success'); + } + if (data !== newData) { + self.updateSettings(); + if (!Settings.dhtEnable || (Settings.customMoviesServer || Settings.customSeriesServer || Settings.customAnimeServer)) { + self.alertMessage('change'); + } else { + self.alertMessage('restart'); + } + } else if (e === 'enable') { + self.alertMessage('restart'); + } else if (e === 'manual') { + self.alertMessage('alrdupdated'); + } + }); + }); + } + + updateOld() { + if (!Settings.dht) { + return; + } + let data = AdvSettings.get('dhtData'); + let last = AdvSettings.get('dhtDataUpdated'); + const time = 1000 * 60 * 60 * 24 * 7; + if (!data) { + this.update('enable'); + } else if (Date.now() - last > time) { + this.update(); + } + } + + updateSettings() { + setTimeout(function() { + if (App.ViewStack.includes('settings-container-contain')) { + let scrollPos = $('.settings-container-contain').scrollTop(); + $('.nav-hor.left li:first').click(); + App.vent.trigger('settings:show'); + $('.update-dht').removeClass('fa-spin fa-spinner').addClass('valid-tick'); + $('.settings-container-contain').scrollTop(scrollPos); + } + }, 200); + } + + alertIcon(e) { + if (e) { + let tmpclass = e === 'success' ? 'valid-tick' : 'invalid-cross'; + $('.update-dht').removeClass('fa-spin fa-spinner').addClass(tmpclass); + setTimeout(function() { $('.update-dht').removeClass(tmpclass).addClass('fa-redo');}, 6000); + } else { + $('.update-dht').removeClass('fa-redo').removeClass('valid-tick').removeClass('invalid-cross').addClass('fa-spin fa-spinner'); + } + } + + alertMessage(alertType) { + var changeServer = function () { + let newServer = AdvSettings.get('dhtData') && !AdvSettings.get('dhtEnable') ? AdvSettings.get('dhtData').split('server":"')[1].split('","git":"')[0] : ''; + AdvSettings.set('customMoviesServer', newServer); + AdvSettings.set('customSeriesServer', newServer); + AdvSettings.set('customAnimeServer', newServer); + this.alertMessage('restart'); + }.bind(this); + var notificationModel = new App.Model.Notification({ + title: i18n.__('Success'), + type: 'success', + }); + switch (alertType) { + case 'wait': + notificationModel.set('title', i18n.__('Please wait') + '...'); + notificationModel.set('body', i18n.__('Updating the API Server URLs')); + notificationModel.set('type', 'danger'); + break; + case 'error': + notificationModel.set('title', i18n.__('Error')); + notificationModel.set('body', i18n.__('API Server URLs could not be updated')); + notificationModel.set('type', 'error'); + notificationModel.set('autoclose', true); + break; + case 'change': + notificationModel.set('body', i18n.__('Change API Server(s) to the new URLs?')); + notificationModel.set('buttons', [{ title: '', action: changeServer }, { title: '', action: function () {this.alertMessage('updated');}.bind(this)}]); + break; + case 'restart': + notificationModel.set('body', i18n.__('Please restart your application')); + notificationModel.set('showRestart', true); + break; + case 'updated': + notificationModel.set('body', i18n.__('API Server URLs updated')); + notificationModel.set('autoclose', true); + break; + case 'alrdupdated': + notificationModel.set('body', i18n.__('API Server URLs already updated')); + notificationModel.set('autoclose', true); + } + App.vent.trigger('notification:show', notificationModel); + } +} + +App.DhtReader = new DhtReader(); diff --git a/src/app/index.html b/src/app/index.html index f3f556269f..b698e4885d 100644 --- a/src/app/index.html +++ b/src/app/index.html @@ -74,6 +74,7 @@ + diff --git a/src/app/language.js b/src/app/language.js index 01e65697a7..cd612c4c83 100644 --- a/src/app/language.js +++ b/src/app/language.js @@ -65,7 +65,12 @@ App.Localization.filterSubtitle = function (langs) { return filteredLang; }; -App.Localization.allTranslations = ['en', 'ar', 'bg', 'bn', 'ca', 'cs', 'da', 'de', 'el', 'es', 'es-mx', 'et', 'eu', 'fa', 'fi', 'fr', 'gl', 'he', 'hr', 'hu', 'id', 'it', 'ka', 'ko', 'lt', 'mk', 'ms', 'nb', 'nl', 'nn', 'pl', 'pt', 'pt-br', 'ro', 'ru', 'sk', 'sl', 'sr', 'sv', 'tr', 'uk', 'zh-cn', 'zh-tw']; +App.Localization.allTranslations = [ + 'en', 'ar', 'bg', 'bn', 'ca', 'cs', 'da', 'de', 'el', 'es', 'es-mx', 'et', 'eu', 'fa', 'fi', 'fr', 'gl', 'gu', + 'he', 'hr', 'hu', 'hi', 'id', 'it', 'is', 'ka', 'kn', 'ko', 'ja', 'lt', 'ml', 'mk', 'ms', 'no', 'nb', 'nl', + 'nn', 'pl', 'pt', 'pt-br', 'ro', 'ru', 'sk', 'sl', 'sr', 'sv', 'ta', 'tr', 'tl', 'th', 'te', 'vi', 'uk', 'ur', + 'zh-cn', 'zh-tw' +]; App.Localization.langcodes = { 'aa': { diff --git a/src/app/language/en.json b/src/app/language/en.json index 7cc7dda7b8..88460b1ec3 100644 --- a/src/app/language/en.json +++ b/src/app/language/en.json @@ -552,7 +552,7 @@ "Ask me every time": "Ask me every time", "Enable Protocol Encryption": "Enable Protocol Encryption", "Allows connecting to peers that use PE/MSE. Will in most cases increase the number of connectable peers but might also result in increased CPU usage": "Allows connecting to peers that use PE/MSE. Will in most cases increase the number of connectable peers but might also result in increased CPU usage", - "Show the Seedbox when adding a new download": "Show the Seedbox when adding a new download", + "Show the Seedbox when a new download is added": "Show the Seedbox when a new download is added", "Download added": "Download added", "Change API Server": "Change API Server", "Localisation": "Localisation", @@ -573,5 +573,45 @@ "Show Release Info": "Show Release Info", "Parental Guide": "Parental Guide", "Rebuild bookmarks database": "Rebuild bookmarks database", - "Rebuilding bookmarks...": "Rebuilding bookmarks..." + "Rebuilding bookmarks...": "Rebuilding bookmarks...", + "Submit metadata & translations": "Submit metadata & translations", + "Not available": "Not available", + "Cast not available": "Cast not available", + "Show the 'Submit metadata & translations' button": "Show the 'Submit metadata & translations' button", + "Show an 'Undo' button when a bookmark is removed": "Show an 'Undo' button when a bookmark is removed", + "was added to bookmarks": "was added to bookmarks", + "was removed from bookmarks": "was removed from bookmarks", + "Bookmark restored": "Bookmark restored", + "Undo": "Undo", + "Remaining runtime before start preloading next episode": "Remaining runtime before start preloading next episode", + "Zoom": "Zoom", + "Contrast": "Contrast", + "Brightness": "Brightness", + "Hue": "Hue", + "Saturation": "Saturation", + "Decrease Zoom by": "Decrease Zoom by", + "Increase Zoom by": "Increase Zoom by", + "Decrease Contrast by": "Decrease Contrast by", + "Increase Contrast by": "Increase Contrast by", + "Decrease Brightness by": "Decrease Brightness by", + "Increase Brightness by": "Increase Brightness by", + "Rotate Hue counter-clockwise by": "Rotate Hue counter-clockwise by", + "Rotate Hue clockwise by": "Rotate Hue clockwise by", + "Decrease Saturation by": "Decrease Saturation by", + "Increase Saturation by": "Increase Saturation by", + "Automatically update the API Server URLs": "Automatically update the API Server URLs", + "Enable automatically updating the API Server URLs": "Enable automatically updating the API Server URLs", + "Automatically update the app when a new version is available": "Automatically update the app when a new version is available", + "Enable automatically updating the app when a new version is available": "Enable automatically updating the app when a new version is available", + "Check for updates": "Check for updates", + "Updating the API Server URLs": "Updating the API Server URLs", + "API Server URLs updated": "API Server URLs updated", + "API Server URLs already updated": "API Server URLs already updated", + "Change API server(s) to the new URLs?": "Change API server(s) to the new URLs?", + "API Server URLs could not be updated": "API Server URLs could not be updated", + "You can add multiple API Servers separated with a , from which it will select randomly (*for load balancing) until it finds the first available": "You can add multiple API Servers separated with a , from which it will select randomly (*for load balancing) until it finds the first available", + "The API Server URL(s) was copied to the clipboard": "The API Server URL(s) was copied to the clipboard", + "0 = Disable preloading": "0 = Disable preloading", + "Search field always expanded": "Search field always expanded", + "DHT UDP Requests Limit": "DHT UDP Requests Limit" } diff --git a/src/app/language/ru.json b/src/app/language/ru.json index 6374d89168..25a7e754b7 100644 --- a/src/app/language/ru.json +++ b/src/app/language/ru.json @@ -448,5 +448,6 @@ "Browse Directoy to save to": "Открыть директорию для сохранения в", "Cancel and use VPN": "Отменить и использовать VPN", "Continue seeding torrents after restart app?": "Продолжить раздавать торренты после перезапуска приложения?", - "Enable VPN": "Включить VPN" -} \ No newline at end of file + "Enable VPN": "Включить VPN", + "Updating config from these of yours Internets": "Получаем настройки из этих ваших Интернетов" +} diff --git a/src/app/lib/providers/cache_provider.js b/src/app/lib/providers/cache_provider.js deleted file mode 100644 index 2349c67644..0000000000 --- a/src/app/lib/providers/cache_provider.js +++ /dev/null @@ -1,50 +0,0 @@ -(function (App) { - 'use strict'; - - var CacheProvider = function (table, ttl) { - this.table = table; - this.cache = new App.Cache(table); - this.ttl = ttl; - }; - - // TODO: Duplicate cache entry - CacheProvider.prototype.fetch = function (ids) { - var self = this; - ids = _.map(ids, function (id) { - if (id) { - return id.toString(); - } - }); - var cachePromise = this.cache.getItems(ids); - var queryPromise = cachePromise.then(function (items) { - // Filter out cached subtitles - var cachedIds = _.keys(items); - win.debug(cachedIds.length + ' cached ' + self.table); - var filteredId = _.difference(ids, cachedIds); - return filteredId; - }) - .then(this.query); - - // Cache ysubs subtitles - queryPromise.then(function (items) { - win.debug('Cache ' + _.keys(items).length + ' ' + self.table); - self.cache.setItems(items, self.ttl); - }); - - // Wait for all query promise to finish - return Q.allSettled([cachePromise, queryPromise]) - .then(function (results) { - // Merge all promise result - var items = {}; - _.each(results, function (result) { - if (result.state === 'fulfilled') { - _.extend(items, result.value); - } - }); - - return items; - }); - }; - - App.Providers.CacheProvider = CacheProvider; -})(window.App); diff --git a/src/app/lib/providers/cache_providerv2.js b/src/app/lib/providers/cache_providerv2.js deleted file mode 100644 index 898a0ca1b7..0000000000 --- a/src/app/lib/providers/cache_providerv2.js +++ /dev/null @@ -1,47 +0,0 @@ -(function (App) { - 'use strict'; - - var CacheProvider = function (table, ttl) { - this._table = table; - this._cache = new App.CacheV2(table); - this.ttl = ttl; - }; - - CacheProvider.prototype.config = { - name: 'CacheProviderV2' - }; - - CacheProvider.prototype.fetch = function (ids) { - var self = this; - if (this._cache._openPromise.isFulfilled()) { - return this._cache.getMultiple(ids).then(function (items) { - win.debug('Loaded ' + items.length + ' items from the ' + self._table + ' cache!'); - return items; - }); - } else { - return this._cache._openPromise.then(function () { - return self._cache.getMultiple(ids).then(function (items) { - win.debug('Loaded ' + items.length + ' items from the ' + self._table + ' cache!'); - return items; - }); - }); - } - }; - - CacheProvider.prototype.store = function (key, items) { - var promises = []; - var self = this; - win.debug('Stored ' + items.length + ' items in the ' + this._table + ' cache!'); - _.each(items, function (item) { - if (!item[key]) { - return; - } - promises.push(self._cache.set(item[key], item, { - ttl: self.ttl - })); - }); - return Q(items); - }; - - App.Providers.CacheProviderV2 = CacheProvider; -})(window.App); diff --git a/src/app/lib/providers/generic.js b/src/app/lib/providers/generic.js index b2327efda6..0c33d5ec42 100644 --- a/src/app/lib/providers/generic.js +++ b/src/app/lib/providers/generic.js @@ -86,7 +86,6 @@ var config = App.Providers.Generic.parseArgs(name); if (cache[name]) { - win.info('Returning cached provider', name); return cache[name]; } diff --git a/src/app/lib/providers/watchlist.js b/src/app/lib/providers/watchlist.js index a0679bce92..445228f069 100644 --- a/src/app/lib/providers/watchlist.js +++ b/src/app/lib/providers/watchlist.js @@ -275,6 +275,10 @@ } } + Watchlist.prototype.filters = function () { + return Promise.resolve({}); + }; + App.vent.on('show:watched', onShowWatched); App.Providers.install(Watchlist); diff --git a/src/app/lib/streamer.js b/src/app/lib/streamer.js index 8c094d68bb..d1fb9b6121 100644 --- a/src/app/lib/streamer.js +++ b/src/app/lib/streamer.js @@ -51,7 +51,7 @@ App.WebTorrent.add(data, { path : App.settings.tmpLocation, maxConns : 10, - dht : true, + dht : { concurrency: parseInt(Settings.maxUdpReqLimit, 10) || 16 }, secure : Settings.protocolEncryption || false, announce : Settings.trackers.forced, tracker : Settings.trackers.forced @@ -88,7 +88,7 @@ App.WebTorrent.add(data, { path : App.settings.downloadsLocation, maxConns : 10, - dht : true, + dht : { concurrency: parseInt(Settings.maxUdpReqLimit, 10) || 16 }, secure : Settings.protocolEncryption || false, announce : Settings.trackers.forced, tracker : Settings.trackers.forced @@ -165,7 +165,7 @@ maxConns : parseInt(Settings.connectionLimit, 10) || 55, downloadLimit: parseInt(parseFloat(Settings.downloadLimit, 10) * parseInt(Settings.maxLimitMult, 10)) || -1, uploadLimit : parseInt(parseFloat(Settings.uploadLimit, 10) * parseInt(Settings.maxLimitMult, 10)) || -1, - dht : true, + dht : { concurrency: parseInt(Settings.maxUdpReqLimit, 10) || 16 }, secure : Settings.protocolEncryption || false, tracker : { announce: Settings.trackers.forced @@ -283,7 +283,7 @@ torrent = App.WebTorrent.add(uri, { path : path, maxConns : 10, - dht : true, + dht : { concurrency: parseInt(Settings.maxUdpReqLimit, 10) || 16 }, secure : Settings.protocolEncryption || false, announce : Settings.trackers.forced, tracker : Settings.trackers.forced @@ -323,7 +323,7 @@ linkTransferStatus: function () { this.torrent.on('download', function () { - if (this.torrentModel) { + if (this.torrentModel && this.torrent) { this.torrentModel.set('downloadSpeed', Common.fileSize(this.torrent.downloadSpeed) + '/s'); this.torrentModel.set('downloaded', Math.round(this.torrent.downloaded).toFixed(2)); this.torrentModel.set('downloadedFormatted', Common.fileSize(this.torrent.downloaded)); @@ -334,7 +334,7 @@ }.bind(this)); this.torrent.on('upload', function () { - if (this.torrentModel) { + if (this.torrentModel && this.torrent) { this.torrentModel.set('uploadSpeed', Common.fileSize(this.torrent.uploadSpeed) + '/s'); this.torrentModel.set('active_peers', this.torrent.numPeers); } @@ -463,16 +463,20 @@ fileSize = file.length; fileName = file.path; file.select(); + file.hidden = false; } else { // file.deselect(); } } + if (!fileName.startsWith(torrent.path)) { + fileName = path.join(torrent.path, fileName); + } return { name: path.basename(fileName), size: fileSize, index: fileIndex, - path: path.join(torrent.path, fileName) + path: fileName }; }, @@ -485,15 +489,13 @@ if (isFormatted) { this.torrentModel.set('video_file', this.selectFile(torrent, fileName)); this.handleSubtitles(); + } else if (isRead) { + this.torrentModel.set('video_file', this.selectFile(torrent, fileName)); + this.lookForMetadata(torrent); } else { - if (isRead) { - this.torrentModel.set('video_file', this.selectFile(torrent, fileName)); - this.lookForMetadata(torrent); - } else { - this.openFileSelector(torrent); - this.stopped = true; - throw 'interrupt'; - } + this.openFileSelector(torrent); + this.stopped = true; + throw 'interrupt'; } return; }, diff --git a/src/app/lib/subtitle/generic.js b/src/app/lib/subtitle/generic.js index 3bf73a464f..2d14567d3e 100644 --- a/src/app/lib/subtitle/generic.js +++ b/src/app/lib/subtitle/generic.js @@ -137,11 +137,16 @@ }, convert: function (data, cb) { // Converts .srt's to .vtt's try { - var srtPath = data.path; - var vttPath = srtPath.replace('.srt', '.vtt'); + const srtPath = data.path; + const vttPath = srtPath.replace('.srt', '.vtt'); fs.createReadStream(srtPath) .pipe(srt2vtt()) .pipe(fs.createWriteStream(vttPath)); + cb(null, { + vtt: vttPath, + srt: srtPath, + encoding: 'utf8' + }); } catch (e) { cb(e, null); } diff --git a/src/app/lib/subtitle/server.js b/src/app/lib/subtitle/server.js index 445db5dc4b..7032e4cbe0 100644 --- a/src/app/lib/subtitle/server.js +++ b/src/app/lib/subtitle/server.js @@ -52,7 +52,6 @@ var SubtitlesServer = { start: function (data, cb) { - iconv.extendNodeEncodings(); encoding = data.encoding || 'utf8'; win.debug('SubtitleServer: loading', data.srt || data.vtt); diff --git a/src/app/lib/views/browser/filter_bar.js b/src/app/lib/views/browser/filter_bar.js index f2e818ef61..ed0d9c2609 100644 --- a/src/app/lib/views/browser/filter_bar.js +++ b/src/app/lib/views/browser/filter_bar.js @@ -224,6 +224,14 @@ } }); + $('.providerinfo').tooltip({ + delay: { + 'show': 2400, + 'hide': 100 + }, + html: true + }); + if (!this.previousSort) { this.previousSort = $('.sorters .active').data('value') || $('.sorters .value').data('value'); } diff --git a/src/app/lib/views/browser/item.js b/src/app/lib/views/browser/item.js index a84fd3fb94..746940c030 100644 --- a/src/app/lib/views/browser/item.js +++ b/src/app/lib/views/browser/item.js @@ -48,6 +48,14 @@ 'hide': 100 } }); + + $('.providerinfo').tooltip({ + delay: { + 'show': 2400, + 'hide': 100 + }, + html: true + }); }, setQualityDisplayed: function() { @@ -199,6 +207,7 @@ (!this.model.get('runtime') || this.model.get('runtime') === '0') && movie && movie.runtime ? this.model.set('runtime', movie.runtime) : null; !this.model.get('trailer') && movie && movie.videos && movie.videos.results && movie.videos.results[0] ? this.model.set('trailer', 'http://www.youtube.com/watch?v=' + movie.videos.results[0].key) : null; (!this.model.get('backdrop') || this.model.get('backdrop') === 'images/posterholder.png') && movie && movie.backdrop_path ? this.model.set('backdrop', 'http://image.tmdb.org/t/p/w500' + movie.backdrop_path) : ((!this.model.get('backdrop') || this.model.get('backdrop') === 'images/posterholder.png') && movie && movie.poster_path ? this.model.set('backdrop', 'http://image.tmdb.org/t/p/w500' + movie.poster_path) : null); + !this.model.get('tmdb_id') && movie && movie.id ? this.model.set('tmdb_id', movie.id) : null; this.model.set('getmetarunned', true); } @@ -319,8 +328,18 @@ addBookmarked: function () { var imdb = this.model.get('imdb_id'); - var itemtype = this.model.get('type'); - var provider = this.model.get('providers').torrent; + var itemtype = this.model.get('type').replace('bookmarked', ''); + var provider; + + if (this.model.get('providers') && this.model.get('providers').torrent.detail) { + provider = this.model.get('providers').torrent; + } else { + if (itemtype === 'show') { + provider = App.Config.getProviderForType('tvshow')[0]; + } else { + provider = App.Config.getProviderForType('movie')[0]; + } + } return provider.detail(imdb, this.model.attributes).then(function (data) { data.provider = provider.name; @@ -364,6 +383,15 @@ var itemtype = this.model.get('type'); var bookmarked = this.model.get('bookmarked'); + var delCache = (function (e) { + var id = window.setTimeout(function() {}, 0); + while (id--) { window.clearTimeout(id); } + App.vent.trigger('notification:close'); + this.toggleFavorite(e); + $('.favourites-toggle').text(i18n.__('Remove from bookmarks')).addClass('selected'); + $('.sha-bookmark').text(i18n.__('Remove from bookmarks')).addClass('selected'); + $('.notification_alert').stop().text(i18n.__('Bookmark restored')).fadeIn('fast').delay(1500).fadeOut('fast'); + }.bind(this)); if (bookmarked) { this.removeBookmarked().then(function () { @@ -388,14 +416,34 @@ } }); } + }.bind(this)).then(function () { + if (Settings.showUndoRBookmark) { + var id = window.setTimeout(function() {}, 0); + while (id--) { window.clearTimeout(id); } + App.vent.trigger('notification:close'); + App.vent.trigger('notification:show', new App.Model.Notification({ + title: '', + body: '' + this.model.get('title') + ' (' + this.model.get('year') + ')' + '
' + i18n.__('was removed from bookmarks'), + showClose: false, + autoclose: true, + type: 'info', + buttons: [{ title: i18n.__('Undo'), action: delCache }] + })); + } }.bind(this)); } else { - this.ui.bookmarkIcon.addClass('selected'); + if (this.ui.bookmarkIcon[0].isConnected) { + this.ui.bookmarkIcon.addClass('selected'); + } this.addBookmarked().then(function () { this.model.set('bookmarked', true); - this.setCoverStates(); - this.setTooltips(); + if (App.currentview === 'Favorites') { + App.vent.trigger('favorites:list', []); + } else { + this.setCoverStates(); + this.setTooltips(); + } }.bind(this)).catch(function (err) { console.error('item.addBookmarked failed:', err); $('.notification_alert').text(i18n.__('Error loading data, try again later...')).fadeIn('fast').delay(2500).fadeOut('fast'); diff --git a/src/app/lib/views/browser/list.js b/src/app/lib/views/browser/list.js index 2fe42bdfce..bdcfae86e9 100644 --- a/src/app/lib/views/browser/list.js +++ b/src/app/lib/views/browser/list.js @@ -351,6 +351,20 @@ self.$('.items:first').focus(); }); + $('.tooltipped').tooltip({ + delay: { + 'show': 800, + 'hide': 100 + } + }); + + $('.providerinfo').tooltip({ + delay: { + 'show': 2400, + 'hide': 100 + }, + html: true + }); }, checkFetchMore: function () { diff --git a/src/app/lib/views/browser/watchlist_browser.js b/src/app/lib/views/browser/watchlist_browser.js index e01c390b4a..b405ad9edb 100644 --- a/src/app/lib/views/browser/watchlist_browser.js +++ b/src/app/lib/views/browser/watchlist_browser.js @@ -2,7 +2,8 @@ 'use strict'; var WatchlistBrowser = App.View.PCTBrowser.extend({ - collectionModel: App.Model.WatchlistCollection + collectionModel: App.Model.WatchlistCollection, + provider: 'Watchlist', }); App.View.WatchlistBrowser = WatchlistBrowser; diff --git a/src/app/lib/views/disclaimer.js b/src/app/lib/views/disclaimer.js index 4b8566b3b8..b8025eb8f4 100644 --- a/src/app/lib/views/disclaimer.js +++ b/src/app/lib/views/disclaimer.js @@ -18,7 +18,17 @@ acceptDisclaimer: function (e) { e.preventDefault(); Mousetrap.unpause(); + AdvSettings.set('dhtEnable', document.getElementById('dhtEnableFR').checked ? true : false); + AdvSettings.set('automaticUpdating', document.getElementById('automaticUpdatingFR').checked ? true : false); AdvSettings.set('disclaimerAccepted', 1); + if (document.getElementById('dhtEnableFR').checked) { + App.DhtReader.update(); + App.vent.trigger('notification:show', new App.Model.Notification({ + title: i18n.__('Please wait') + '...', + body: i18n.__('Updating the API Server URLs'), + type: 'danger' + })); + } App.vent.trigger('disclaimer:close'); }, diff --git a/src/app/lib/views/main_window.js b/src/app/lib/views/main_window.js index fb3c227cc4..bc8549a3a3 100644 --- a/src/app/lib/views/main_window.js +++ b/src/app/lib/views/main_window.js @@ -296,7 +296,7 @@ }); // we check if the disclaimer is accepted - if (!AdvSettings.get('disclaimerAccepted')) { + if (!AdvSettings.get('disclaimerAccepted') || AdvSettings.get('automaticUpdating') === '' || AdvSettings.get('dhtEnable') === '') { that.showDisclaimer(); } diff --git a/src/app/lib/views/movie_detail.js b/src/app/lib/views/movie_detail.js index 15d1929f7c..ffec97c453 100644 --- a/src/app/lib/views/movie_detail.js +++ b/src/app/lib/views/movie_detail.js @@ -1,9 +1,6 @@ (function(App) { 'use strict'; - // Torrent Health - var torrentHealth = require('webtorrent-health'), - healthButton, - curSynopsis; + var healthButton, curSynopsis; var _this; App.View.MovieDetail = Marionette.View.extend({ @@ -25,6 +22,7 @@ 'click .movie-imdb-link': 'openIMDb', 'mousedown .magnet-link': 'openMagnet', 'mousedown .source-link': 'openSource', + 'click .tmdb-link': 'openTmdb', 'click .rating-container': 'switchRating', 'click .show-cast': 'showCast', 'click .showall-cast': 'showallCast', @@ -215,6 +213,7 @@ !this.model.get('trailer') && movie && movie.videos && movie.videos.results && movie.videos.results[0] ? this.model.set('trailer', 'http://www.youtube.com/watch?v=' + movie.videos.results[0].key) : null; (!this.model.get('poster') || this.model.get('poster') === 'images/posterholder.png') && movie && movie.poster_path ? this.model.set('poster', 'http://image.tmdb.org/t/p/w500' + movie.poster_path) : null; (!this.model.get('backdrop') || this.model.get('backdrop') === 'images/posterholder.png') && movie && movie.backdrop_path ? this.model.set('backdrop', 'http://image.tmdb.org/t/p/w500' + movie.backdrop_path) : ((!this.model.get('backdrop') || this.model.get('backdrop') === 'images/posterholder.png') && movie && movie.poster_path ? this.model.set('backdrop', 'http://image.tmdb.org/t/p/w500' + movie.poster_path) : null); + !this.model.get('tmdb_id') && movie && movie.id ? this.model.set('tmdb_id', movie.id) : null; if (movie && movie.credits && movie.credits.cast && movie.credits.crew && (movie.credits.cast[0] || movie.credits.crew[0])) { curSynopsis.old = this.model.get('synopsis'); curSynopsis.crew = movie.credits.crew.filter(function (el) {return el.job === 'Director';}).map(function (el) {return '' + el.job + ' - ${el.name.replace(/\ /g, ' ')}`;}).join('   ') + '

 

'; @@ -249,13 +248,7 @@ $('.overview *').tooltip({html: true, sanitize: false, container: 'body', placement: 'bottom', delay: {show: 200, hide: 0}, template: '
'}); }, - clickPoster: function(e) { - if (e.button === 2) { - var clipboard = nw.Clipboard.get(); - clipboard.set($('.mcover-image')[0].src, 'text'); - $('.notification_alert').text(i18n.__('The image url was copied to the clipboard')).fadeIn('fast').delay(2500).fadeOut('fast'); - } - }, + clickPoster: (e) => Common.openOrClipboardLink(e, $('.mcover-image')[0].src, i18n.__('image url'), true), onBeforeDestroy: function() { $('[data-toggle="tooltip"]').tooltip('hide'); @@ -336,18 +329,7 @@ magnetLink = torrent.url.replace(/\&/g, '&'); } magnetLink = magnetLink.split('&tr=')[0] + _.union(decodeURIComponent(magnetLink).replace(/\/announce/g, '').split('&tr=').slice(1), Settings.trackers.forced.toString().replace(/\/announce/g, '').split(',')).map(t => `&tr=${t}/announce`).join(''); - if (e.button === 2) { - //if right click on magnet link - var clipboard = nw.Clipboard.get(); - clipboard.set(magnetLink, 'text'); //copy link to clipboard - $('.notification_alert') - .text(i18n.__('The magnet link was copied to the clipboard')) - .fadeIn('fast') - .delay(2500) - .fadeOut('fast'); - } else { - nw.Shell.openExternal(magnetLink); - } + Common.openOrClipboardLink(e, magnetLink, i18n.__('magnet link')); }, openSource: function(e) { @@ -360,17 +342,39 @@ } else { return; } - if (e.button === 2) { - //if right click on magnet link - var clipboard = nw.Clipboard.get(); - clipboard.set(sourceLink, 'text'); //copy link to clipboard - $('.notification_alert') - .text(i18n.__('The source link was copied to the clipboard')) - .fadeIn('fast') - .delay(2500) - .fadeOut('fast'); + Common.openOrClipboardLink(e, sourceLink, i18n.__('source link')); + }, + + openTmdb: function(e) { + let imdb = this.model.get('imdb_id'), + tmdb = this.model.get('tmdb_id'), + api_key = Settings.tmdb.api_key; + + if (!tmdb && !this.model.get('getmetarunned')) { + let movie = (function () { + let tmp = null; + $.ajax({ + url: 'http://api.themoviedb.org/3/find/' + imdb + '?api_key=' + api_key + '&external_source=imdb_id', + type: 'get', + dataType: 'json', + timeout: 5000, + async: false, + global: false, + success: function (data) { + tmp = data; + } + }); + return tmp; + }()); + movie && movie.movie_results && movie.movie_results[0] && movie.movie_results[0].id ? this.model.set('tmdb_id', movie.movie_results[0].id) : null; + tmdb = this.model.get('tmdb_id'); + } + + if (tmdb) { + let tmdbLink = 'https://www.themoviedb.org/movie/' + tmdb + '/edit?language=' + Settings.language; + Common.openOrClipboardLink(e, tmdbLink, i18n.__('TMDB link')); } else { - nw.Shell.openExternal(sourceLink); + $('.tmdb-link').addClass('disabled').prop('disabled', true).attr('title', i18n.__('Not available')).tooltip('hide').tooltip('fixTitle'); } } diff --git a/src/app/lib/views/player/loading.js b/src/app/lib/views/player/loading.js index d880a19010..8a9d72299c 100644 --- a/src/app/lib/views/player/loading.js +++ b/src/app/lib/views/player/loading.js @@ -44,7 +44,7 @@ 'click #cancel-button': 'cancelStreaming', 'click #cancel-button-regular': 'cancelStreaming', 'click #cancel-button-vpn': 'cancelStreamingVPN', - 'click .open-button': 'tempf', + 'click .open-button': 'openItem', 'click .pause': 'pauseStreaming', 'click .stop': 'stopStreaming', 'click .play': 'resumeStreaming', @@ -54,9 +54,7 @@ 'click .maximize-icon': 'minDetails', 'click #max_play_ctrl': 'maxPlayCtrl', 'click .show-pcontrols': 'showpcontrols', - 'mousedown .title': 'copytoclip', - 'mousedown .text_filename': 'copytoclip', - 'mousedown .text_streamurl': 'copytoclip', + 'mousedown .copytoclip': 'copytoclip', 'mousedown .magnet-icon': 'openMagnet', 'click .playing-progressbar': 'seekStreaming' }, @@ -65,8 +63,8 @@ var that = this; App.vent.trigger('settings:close'); App.vent.trigger('about:close'); - $('.button:not(#download-torrent), .show-details .sdow-watchnow, .show-details #download-torrent, .file-item, .result-item, .collection-actions').addClass('disabled'); - $('#watch-now, #watch-trailer, .playerchoice, .file-item, .result-item').prop('disabled', true); + $('.button:not(#download-torrent), .show-details .sdow-watchnow, .show-details #download-torrent, .file-item, .result-item, .collection-actions, .seedbox .item-play').addClass('disabled'); + $('#watch-now, #watch-trailer, .playerchoice, .file-item, .result-item, .seedbox .item-play').prop('disabled', true); // If a child was removed from above this view App.vent.on('viewstack:pop', function() { if (_.last(App.ViewStack) === that.className) { @@ -239,11 +237,13 @@ this.checkFreeSpace(streamInfo.get('size')); this.firstUpdate = true; } - if (streamInfo.get('backdrop')) { + if (!this.backdropSet && streamInfo.get('backdrop')) { $('.loading-backdrop').css('background-image', 'url(' + streamInfo.get('backdrop') + ')'); + this.backdropSet = true; } - if (streamInfo.get('title') !== '') { + if (!this.titleSet && streamInfo.get('title') !== '') { this.ui.title.html(streamInfo.get('title')); + this.titleSet = true; } if (streamInfo.get('downloaded')) { this.ui.downloadSpeed.text(streamInfo.get('downloadSpeed')); @@ -342,8 +342,9 @@ } }, - tempf: function (e) { - App.settings.os === 'windows' ? nw.Shell.openExternal(Settings.tmpLocation) : nw.Shell.openItem(Settings.tmpLocation); + openItem: function (e) { + const location = this.model.get('streamInfo').attributes.videoFile.replace(/[^\\/]*$/, ''); + App.settings.os === 'windows' ? nw.Shell.openExternal(location) : nw.Shell.openItem(location); }, openMagnet: function (e) { @@ -351,17 +352,7 @@ if (torrent.magnetURI) { var magnetLink = torrent.magnetURI.replace(/\&/g, '&'); magnetLink = magnetLink.split('&tr=')[0] + _.union(decodeURIComponent(magnetLink).replace(/\/announce/g, '').split('&tr=').slice(1), Settings.trackers.forced.toString().replace(/\/announce/g, '').split(',')).map(t => `&tr=${t}/announce`).join(''); - if (e.button === 2) { - var clipboard = nw.Clipboard.get(); - clipboard.set(magnetLink, 'text'); //copy link to clipboard - $('.notification_alert') - .text(i18n.__('Copied to clipboard')) - .fadeIn('fast') - .delay(2500) - .fadeOut('fast'); - } else { - nw.Shell.openExternal(magnetLink); - } + Common.openOrClipboardLink(e, magnetLink, i18n.__('magnet link')); } }, @@ -379,13 +370,7 @@ } }, - copytoclip: function (e) { - if (e.button === 2) { - var clipboard = nw.Clipboard.get(); - clipboard.set(e.target.textContent, 'text'); - $('.notification_alert').text(i18n.__('Copied to clipboard')).fadeIn('fast').delay(2500).fadeOut('fast'); - } - }, + copytoclip: (e) => Common.openOrClipboardLink(e, e.target.textContent, i18n.__($(e.target).data('copy')), true), pauseStreaming: function() { App.vent.trigger('device:pause'); @@ -461,7 +446,7 @@ onBeforeDestroy: function() { $('.filter-bar').show(); $('#header').removeClass('header-shadow'); - $('.button, #watch-now, .show-details .sdow-watchnow, .playerchoice, .file-item, .result-item, .trash-torrent, .collection-actions').removeClass('disabled').removeProp('disabled'); + $('.button, #watch-now, .show-details .sdow-watchnow, .playerchoice, .file-item, .result-item, .trash-torrent, .collection-actions, .seedbox .item-play').removeClass('disabled').removeProp('disabled'); Mousetrap.bind(['esc', 'backspace'], function(e) { App.vent.trigger('show:closeDetail'); App.vent.trigger('movie:closeDetail'); diff --git a/src/app/lib/views/player/player.js b/src/app/lib/views/player/player.js index b5efb00cb1..b8e5952854 100644 --- a/src/app/lib/views/player/player.js +++ b/src/app/lib/views/player/player.js @@ -58,10 +58,34 @@ this.firstPlay = true; this.boundedMouseScroll = this.mouseScroll.bind(this); + this.zoom = 1.0; + + this.filters = { + brightness: 1.0, + contrast: 1.0, + hue: 0, + saturation: 1.0, + }; + + //If a child was added above this view + App.vent.on('viewstack:push', function() { + if (_.last(App.ViewStack) !== 'app-overlay') { + _this.unbindKeyboardShortcuts(); + if (win.isFullscreen) { + $('.player .video-js').hide(); + this.wasFullscreen = true; + } + } + }); + //If a child was removed from above this view App.vent.on('viewstack:pop', function() { if (_.last(App.ViewStack) === 'app-overlay') { _this.bindKeyboardShortcuts(); + if (this.wasFullscreen) { + $('.player .video-js').removeAttr('style'); + this.wasFullscreen = false; + } } }); }, @@ -258,37 +282,32 @@ checkAutoPlay: function () { if (this.isMovie() === 'episode' && this.next_episode_model) { - if ((this.video.duration() - this.video.currentTime()) < 60 && this.video.currentTime() > 30) { - + if ((!Settings.preloadNextEpisodeTime || (this.video.duration() - this.video.currentTime() < Settings.preloadNextEpisodeTime * 60)) && this.video.currentTime() > 30) { if (!this.autoplayisshown) { - var playingNext = $('.playing_next'); - - if (!this.precachestarted) { + if (Settings.preloadNextEpisodeTime && !this.precachestarted) { App.vent.trigger('stream:start', this.next_episode_model, 'preload'); this.precachestarted = true; } - - win.info('Showing Auto Play message'); - this.autoplayisshown = true; - playingNext.show(); - playingNext.appendTo('div#video_player'); - if (!this.player.userActive()) { - this.player.userActive(true); + if ((this.video.duration() - this.video.currentTime()) < 60) { + var playingNext = $('.playing_next'); + win.info('Showing Auto Play message'); + this.autoplayisshown = true; + playingNext.show(); + playingNext.appendTo('div#video_player'); + if (!this.player.userActive()) { + this.player.userActive(true); + } } } - var count = Math.round(this.video.duration() - this.video.currentTime()); $('.playing_next #nextCountdown').text(count); - } else { - if (this.autoplayisshown) { win.info('Hiding Auto Play message'); $('.playing_next').hide(); $('.playing_next #nextCountdown').text(''); this.autoplayisshown = false; } - } } }, @@ -450,8 +469,8 @@ $('#player_drag').show(); var that = this; - $('.button:not(#download-torrent), .show-details .sdow-watchnow, .show-details #download-torrent, .file-item, .result-item, .collection-actions').addClass('disabled'); - $('#watch-now, #watch-trailer, .playerchoice, .file-item, .result-item').prop('disabled', true); + $('.button:not(#download-torrent), .show-details .sdow-watchnow, .show-details #download-torrent, .file-item, .result-item, .collection-actions, .seedbox .item-play').addClass('disabled'); + $('#watch-now, #watch-trailer, .playerchoice, .file-item, .result-item, .seedbox .item-play').prop('disabled', true); // Double Click to toggle Fullscreen $('#video_player, .state-info-player').dblclick(function (event) { @@ -758,6 +777,68 @@ } }, + adjustZoom: function (difference) { + var v = $('video')[0]; + this.zoom += difference; + if (this.zoom < 0) { + this.zoom = 0; + } + v.style.transform = this.zoom === 1 ? '' : `scale(${this.zoom})`; + this.displayOverlayMsg(i18n.__('Zoom') + ': ' + (this.zoom * 100).toFixed(0) + '%'); + $('.vjs-overlay').css('opacity', '1'); + }, + + adjustBrightness: function (difference) { + this.filters.brightness += difference; + if (this.filters.brightness < 0) { + this.filters.brightness = 0; + } + this.applyFilters(); + this.displayOverlayMsg(i18n.__('Brightness') + ': ' + (this.filters.brightness * 100).toFixed(0) + '%'); + $('.vjs-overlay').css('opacity', '1'); + }, + + adjustContrast: function (difference) { + this.filters.contrast += difference; + if (this.filters.contrast < 0) { + this.filters.contrast = 0; + } + this.applyFilters(); + this.displayOverlayMsg(i18n.__('Contrast') + ': ' + (this.filters.contrast * 100).toFixed(0) + '%'); + $('.vjs-overlay').css('opacity', '1'); + }, + + adjustHue: function (difference) { + this.filters.hue += difference; + if (this.filters.hue < -180) { + this.filters.hue = -180; + } else if (this.filters.hue > 180) { + this.filters.hue = 180; + } + this.applyFilters(); + this.displayOverlayMsg(i18n.__('Hue') + ': ' + this.filters.hue.toFixed(0)); + $('.vjs-overlay').css('opacity', '1'); + }, + + adjustSaturation: function (difference) { + this.filters.saturation += difference; + if (this.filters.saturation < 0) { + this.filters.saturation = 0; + } + this.applyFilters(); + this.displayOverlayMsg(i18n.__('Saturation') + ': ' + (this.filters.saturation * 100).toFixed(0) + '%'); + $('.vjs-overlay').css('opacity', '1'); + }, + + applyFilters: function (difference) { + const { brightness, contrast, hue, saturation } = this.filters; + var curVideo = $('#video_player_html5_api'); + // On some devices, the image turns orange if both hue-rotate() and saturate() are used! + // So we only add the hue-rotate() filter if requested by the user. + const hueAdjustment = hue === 0 ? '' : `hue-rotate(${hue}deg)`; + curVideo[0].style.filter = `brightness(${brightness}) contrast(${contrast}) ${hueAdjustment} saturate(${saturation})`; + }, + bindKeyboardShortcuts: function () { var that = this; @@ -918,6 +999,46 @@ that.scaleWindow(2); }); + Mousetrap.bind('w', function (e) { + that.adjustZoom(-0.05); + }, 'keydown'); + + Mousetrap.bind('e', function (e) { + that.adjustZoom(+0.05); + }, 'keydown'); + + Mousetrap.bind('shift+1', function (e) { + that.adjustContrast(-0.05); + }, 'keydown'); + + Mousetrap.bind('shift+2', function (e) { + that.adjustContrast(+0.05); + }, 'keydown'); + + Mousetrap.bind('shift+3', function (e) { + that.adjustBrightness(-0.05); + }, 'keydown'); + + Mousetrap.bind('shift+4', function (e) { + that.adjustBrightness(+0.05); + }, 'keydown'); + + Mousetrap.bind('shift+5', function (e) { + that.adjustHue(-1); + }, 'keydown'); + + Mousetrap.bind('shift+6', function (e) { + that.adjustHue(+1); + }, 'keydown'); + + Mousetrap.bind('shift+7', function (e) { + that.adjustSaturation(-0.05); + }, 'keydown'); + + Mousetrap.bind('shift+8', function (e) { + that.adjustSaturation(+0.05); + }, 'keydown'); + // multimedia keys // Change when mousetrap can be extended $('body').bind('keydown', function (e) { @@ -1003,6 +1124,26 @@ Mousetrap.unbind('2'); + Mousetrap.unbind('w'); + + Mousetrap.unbind('e'); + + Mousetrap.unbind('shift+1'); + + Mousetrap.unbind('shift+2'); + + Mousetrap.unbind('shift+3'); + + Mousetrap.unbind('shift+4'); + + Mousetrap.unbind('shift+5'); + + Mousetrap.unbind('shift+6'); + + Mousetrap.unbind('shift+7'); + + Mousetrap.unbind('shift+8'); + // multimedia keys // Change when mousetrap can be extended $('body').unbind('keydown'); @@ -1028,7 +1169,7 @@ }, mouseScroll: function (e) { - if ($(e.target).parents('.vjs-subtitles-button').length) { + if (_.last(App.ViewStack) !== 'app-overlay' || $(e.target).parents('.vjs-subtitles-button').length) { return; } var mult = (Settings.os === 'mac') ? -1 : 1; // up/down invert @@ -1147,7 +1288,7 @@ if (this.inFullscreen && !win.isFullscreen) { $('.btn-os.fullscreen').removeClass('active'); } - $('.button, #watch-now, .show-details .sdow-watchnow, .playerchoice, .file-item, .result-item, .trash-torrent, .collection-actions').removeClass('disabled').removeProp('disabled'); + $('.button, #watch-now, .show-details .sdow-watchnow, .playerchoice, .file-item, .result-item, .trash-torrent, .collection-actions, .seedbox .item-play').removeClass('disabled').removeProp('disabled'); this.unbindKeyboardShortcuts(); Mousetrap.bind('ctrl+v', function (e) { }); diff --git a/src/app/lib/views/seedbox.js b/src/app/lib/views/seedbox.js index 6f42a5e271..384adf00a2 100644 --- a/src/app/lib/views/seedbox.js +++ b/src/app/lib/views/seedbox.js @@ -4,20 +4,23 @@ var torrentsDir = path.join(App.settings.tmpLocation + '/TorrentCache/'), torrentsDir2 = path.join(App.settings.downloadsLocation + '/TorrentCache/'), toDel = [], + totalSize, + totalDownloaded, + totalPer, updateInterval; const supported = ['.mp4', '.m4v', '.avi', '.mov', '.mkv', '.wmv']; var formatBytes = function (bytes, decimals) { if (bytes === 0) { - return '0 Bytes'; + return '0 B'; } let k = 1024, - dm = decimals || 2, - sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'], + dm = decimals || 1, + sizes = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'], i = Math.floor(Math.log(bytes) / Math.log(k)); - return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + ' ' + sizes[i]; + return (bytes / Math.pow(k, i)).toFixed(dm) + ' ' + sizes[i]; }; var Seedbox = Marionette.View.extend({ @@ -25,17 +28,16 @@ className: 'seedbox', events: { - 'mousedown .file-item': 'openFileSelector', - 'mousedown .result-item': 'onlineOpen', - 'mousedown .item-delete': 'deleteItem', - 'mousedown .item-rename': 'renameItem', 'mousedown .magnet-icon': 'openMagnet', 'mousedown .health-icon': 'healthClicked', - 'mousedown .pause-torrent': 'onPauseTorrentClicked', - 'mousedown .resume-torrent': 'onResumeTorrentClicked', - 'mousedown .trash-torrent': 'onRemoveTorrentClicked', + 'click .pause-torrent': 'onPauseTorrentClicked', + 'click .resume-torrent': 'onResumeTorrentClicked', + 'click .trash-torrent': 'onRemoveTorrentClicked', 'click .tab-torrent': 'clickTorrent', - 'click .file-item': 'tempf' + 'dblclick .file-item': 'openItem', + 'click .item-play': 'addItem', + 'click .item-download': 'addItem', + 'click .item-remove': 'removeItem' }, initialize: function () { @@ -60,7 +62,7 @@ if ($('.loading .maximize-icon').is(':visible') || $('.player .maximize-icon').is(':visible')) { let currentHash; try { currentHash = App.LoadingView.model.attributes.streamInfo.attributes.torrentModel.attributes.torrent.infoHash; } catch(err) {} - currentHash && $('#trash-'+currentHash)[0] ? $('#trash-'+currentHash).addClass('disabled') : null; + currentHash && $('#trash-'+currentHash)[0] ? $('#trash-'+currentHash).addClass('disabled').prop('disabled', true) : null; } }, @@ -83,6 +85,8 @@ this.onAddTorrent(torrent); }); + setTimeout(() => this.updateView($('.tab-torrent.active'), true), 100); + updateInterval = setInterval(() => { this.updateView($('.tab-torrent.active')); }, 1000); @@ -105,11 +109,11 @@
${App.plugins.mediaName.getMediaName(torrent)}
- - + 0 Kb/s + 0 Kb/s - 0 Kb/s - 0 Kb/s + + ` ); @@ -193,6 +197,7 @@ }, onPauseTorrentClicked(e, id) { + try { e.stopPropagation(); } catch(err) {} const torrent = this.getTorrentFromEvent(e, id); if (torrent) { this.pauseTorrent(torrent); @@ -200,6 +205,7 @@ }, onResumeTorrentClicked(e, id) { + try { e.stopPropagation(); } catch(err) {} const torrent = this.getTorrentFromEvent(e, id); if (torrent) { torrent.resume(); @@ -216,6 +222,7 @@ }, onRemoveTorrentClicked(e) { + try { e.stopPropagation(); } catch(err) {} const torrent = this.getTorrentFromEvent(e); if (torrent) { if (App.settings.delSeedboxCache === 'always') { @@ -291,13 +298,51 @@ this.updateView($(e.currentTarget), true /*wasJustSelected*/); }, - tempf: function () { + openItem: function (e) { const hash = $('.tab-torrent.active')[0].getAttribute('id'); const torrent = App.WebTorrent.torrents.find(torrent => torrent.infoHash === hash); - if (App.settings.separateDownloadsDir && !torrent._servers[0]) { - App.settings.os === 'windows' ? nw.Shell.openExternal(Settings.downloadsLocation) : nw.Shell.openItem(Settings.downloadsLocation); - } else { - App.settings.os === 'windows' ? nw.Shell.openExternal(Settings.tmpLocation) : nw.Shell.openItem(Settings.tmpLocation); + const filename = e.target.firstChild.innerHTML || e.target.innerHTML; + const location = torrent.files.filter(obj => { return obj.name === filename; })[0].path.replace(/[^\\/]*$/, ''); + App.settings.os === 'windows' ? nw.Shell.openExternal(location) : nw.Shell.openItem(location); + }, + + addItem: function (e) { + e.stopPropagation(); + const target = $(e.target); + const hash = $('.tab-torrent.active')[0].getAttribute('id'); + const thisTorrent = App.WebTorrent.torrents.find(torrent => torrent.infoHash === hash); + var torrentStart = new Backbone.Model({ + torrent: thisTorrent.magnetURI, + title: thisTorrent.name, + defaultSubtitle: Settings.subtitle_language, + device: App.Device.Collection.selected, + file_name: e.target.parentNode.firstChild.innerHTML + }); + if (thisTorrent.paused) { + this.onResumeTorrentClicked($('.tab-torrent.active'), hash); + $('#resume-'+hash).show(); + $('#play-'+hash).hide(); + } + setTimeout(() => { + this.updateView($('.tab-torrent.active'), true); + if (target.hasClass('item-play')) { + $('#trash-'+hash).addClass('disabled').prop('disabled', true); + $('.seedbox .item-play').addClass('disabled').prop('disabled', true); + } + }, 100); + App.vent.trigger('stream:start', torrentStart, target.hasClass('item-play') ? '' : 'downloadOnly' ); + }, + + removeItem: function (e) { + e.stopPropagation(); + const hash = $('.tab-torrent.active')[0].getAttribute('id'); + const thisTorrent = App.WebTorrent.torrents.find(torrent => torrent.infoHash === hash); + const filename = e.target.parentNode.firstChild.innerHTML; + const file = thisTorrent.files.filter(obj => { return obj.name === filename; })[0]; + if (!file._fileStreams.size) { + file.deselect(0); + file.hidden = true; + setTimeout(() => this.updateView($('.tab-torrent.active'), true), 100); } }, @@ -307,17 +352,7 @@ if (torrent.magnetURI) { var magnetLink = torrent.magnetURI.replace(/\&/g, '&'); magnetLink = magnetLink.split('&tr=')[0] + _.union(decodeURIComponent(magnetLink).replace(/\/announce/g, '').split('&tr=').slice(1), Settings.trackers.forced.toString().replace(/\/announce/g, '').split(',')).map(t => `&tr=${t}/announce`).join(''); - if (e.button === 2) { - var clipboard = nw.Clipboard.get(); - clipboard.set(magnetLink, 'text'); //copy link to clipboard - $('.notification_alert') - .text(i18n.__('The magnet link was copied to the clipboard')) - .fadeIn('fast') - .delay(2500) - .fadeOut('fast'); - } else { - nw.Shell.openExternal(magnetLink); - } + Common.openOrClipboardLink(e, magnetLink, i18n.__('magnet link')); } }, @@ -333,6 +368,22 @@ healthButton.render(); }, + remainingTime: function (downloadSpeed) { + var timeRemaining = Math.round((totalSize - totalDownloaded) / downloadSpeed); + if (isNaN(timeRemaining) || timeRemaining < 0) { + timeRemaining = 0; + } + if (timeRemaining === undefined || !isFinite(timeRemaining) || totalSize === 0) { + return i18n.__('Unknown time remaining'); + } else if (timeRemaining > 3600) { + return i18n.__('%s hour(s) remaining', Math.round(timeRemaining / 3600)); + } else if (timeRemaining > 60) { + return i18n.__('%s minute(s) remaining', Math.round(timeRemaining / 60)); + } else if (timeRemaining <= 60) { + return i18n.__('%s second(s) remaining', timeRemaining); + } + }, + updateView: function ($elem, wasJustSelected = false) { if (!wasJustSelected) { App.WebTorrent.torrents.forEach(function(torrent) { @@ -367,26 +418,80 @@ return 0; }); } catch (err) {} + + let active = $('.loading .maximize-icon').is(':visible') || $('.player .maximize-icon').is(':visible'); for (const file of torrent.files) { - if (supported.indexOf(path.extname(file.name).toLowerCase()) !== -1) { - $fileList.append(`
  • ${file.name}
  • `); + if (supported.indexOf(path.extname(file.name).toLowerCase()) === -1) { + continue; + } + let selected = false; + if (!file.hidden && (file.done || torrent._selections.some(function (el) { return el.from === file._startPiece || el.to === file._endPiece; }))) { + selected = true; } + + $fileList.append(`
  • ${file.name} + + + +
  • `); + } + if (active) { + $('.seedbox .item-play').addClass('disabled').prop('disabled', true); } + + $('.file-item').tooltip({ + html: true, + delay: { + 'show': 800, + 'hide': 100 + } + }); + $('.item-play, .item-download, .item-remove').hover(function(){ + $('.file-item').tooltip('hide'); + }); + } + + totalSize = 0; + totalDownloaded = 0; + totalPer = torrent.downloaded ? 1 : 0; + + for (const file of torrent.files) { + if (supported.indexOf(path.extname(file.name).toLowerCase()) === -1) { + continue; + } + if (!file.hidden && (file.done || torrent._selections.some(function (el) { return el.from === file._startPiece || el.to === file._endPiece; }))) { + totalSize = totalSize + file.length; + totalDownloaded = totalDownloaded + file.downloaded; + try { + const thisElement = document.evaluate(`//a[text()='${file.name}']`, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue.parentNode; + $(thisElement).attr('title', Common.fileSize(file.downloaded) + ' / ' + Common.fileSize(file.length)).tooltip('fixTitle'); + } catch(err) {} + } + } + + if (totalSize) { + totalPer = 1 / (totalSize / totalDownloaded); } torrent.name ? $('.seedbox-infos-title').text(torrent.name) : $('.seedbox-infos-title').text(i18n.__('connecting')); - $('.seedbox-downloaded').text(' ' + formatBytes(torrent.downloaded)); + $('.seedbox-totalsize').text(' ' + formatBytes(totalSize)); + $('.seedbox-downloaded').text(' ' + formatBytes(totalDownloaded)); $('.seedbox-uploaded').text(' ' + formatBytes(torrent.uploaded)); try { $('.seedbox-infos-date').text(i18n.__('added') + ' ' + dayjs(stats.ctime).fromNow()); } catch(err) {} - $('.progress-bar').css('width', (torrent.progress * 100).toFixed(2) + '%'); - $('.progress-percentage>span').text((torrent.progress * 100).toFixed(2) + '%'); - if (torrent.progress >= 1) { + if (totalPer >= 1) { if (!$('.progress-bar').hasClass('done')) { $('.progress-bar').addClass('done'); } + $('.progress-label span').text(i18n.__('Downloaded')); + totalPer = 1; } else if ($('.progress-bar').hasClass('done')) { $('.progress-bar').removeClass('done'); + } else { + $('.progress-label span').text(this.remainingTime(torrent.downloadSpeed)); } + $('.progress-bar').css('width', ((totalPer || 0) * 100).toFixed(2) + '%'); + $('.progress-percentage>span').text(((totalPer || 0) * 100).toFixed(2) + '%'); }, onBeforeDestroy: function () { diff --git a/src/app/lib/views/settings_container.js b/src/app/lib/views/settings_container.js index 2f24affe98..1c88b71ebf 100644 --- a/src/app/lib/views/settings_container.js +++ b/src/app/lib/views/settings_container.js @@ -1,7 +1,6 @@ (function (App) { 'use strict'; - var clipboard = nw.Clipboard.get(), - waitComplete, + var waitComplete, oldTmpLocation, oldDownloadsLocation, that; @@ -42,13 +41,16 @@ 'click #unauthTrakt': 'disconnectTrakt', 'click #authOpensubtitles': 'connectOpensubtitles', 'click #unauthOpensubtitles': 'disconnectOpensubtitles', - 'click .reset-tvshow': 'resettvshow', 'change #tmpLocation': 'updateCacheDirectory', 'change #downloadsLocation': 'updateDownloadsDirectory', 'click #syncTrakt': 'syncTrakt', 'click .qr-code': 'generateQRcode', 'click .set-current-filter': 'saveFilter', - 'click .reset-current-filter': 'resetFilter' + 'click .reset-current-filter': 'resetFilter', + 'click .update-dht': 'updateDht', + 'mousedown #customMoviesServer': 'showFullDatalist', + 'mousedown #customSeriesServer': 'showFullDatalist', + 'mousedown #customAnimeServer': 'showFullDatalist' }, onAttach: function () { @@ -100,7 +102,12 @@ rightclick_field: function (e) { e.preventDefault(); - var menu = new this.context_Menu(i18n.__('Cut'), i18n.__('Copy'), i18n.__('Paste'), e.target.id); + var menu; + if (/customMoviesServer|customSeriesServer|customAnimeServer/.test(e.target.id)) { + menu = new this.altcontext_Menu(i18n.__('Cut'), i18n.__('Copy'), i18n.__('Paste'), e.target.id); + } else { + menu = new this.context_Menu(i18n.__('Cut'), i18n.__('Copy'), i18n.__('Paste'), e.target.id); + } menu.popup(e.originalEvent.x, e.originalEvent.y); }, @@ -131,7 +138,52 @@ menu.append(cut); menu.append(copy); menu.append(paste); + return menu; + }, + + altcontext_Menu: function (cutLabel, copyLabel, pasteLabel, field) { + var menu = new nw.Menu(), + clipboard = nw.Clipboard.get(), + text = $('#' + field).val(), + + cut = new nw.MenuItem({ + label: cutLabel || 'Cut', + click: function () { + text = $('#' + field).val(); + clipboard.set(text, 'text'); + $('.notification_alert').text(i18n.__('The API Server URL(s) was copied to the clipboard')).fadeIn('fast').delay(2500).fadeOut('fast'); + $('#' + field).val(''); + } + }), + copy = new nw.MenuItem({ + label: copyLabel || 'Copy', + click: function () { + text = $('#' + field).val(); + clipboard.set(text, 'text'); + $('.notification_alert').text(i18n.__('The API Server URL(s) was copied to the clipboard')).fadeIn('fast').delay(2500).fadeOut('fast'); + } + }), + + paste = new nw.MenuItem({ + label: pasteLabel || 'Paste', + click: function () { + document.execCommand('paste'); + } + }); + + $('#' + field).one('blur', function() { + if (text && !$('#' + field).val()) { + $('#' + field).val(text); + if (!AdvSettings.get(field)) { + AdvSettings.set(field, text); + } + } + }); + + menu.append(cut); + menu.append(copy); + menu.append(paste); return menu; }, @@ -150,26 +202,6 @@ App.vent.trigger('settings:close'); }, - resettvshow: function () { - var value = [{ - url: 'https:///', - strictSSL: true - }, { - url: 'https:///', - strictSSL: true - }]; - App.settings['tvshow'] = value; - //save to db - App.db.writeSetting({ - key: 'tvshow', - value: value - }).then(function () { - that.ui.success_alert.show().delay(3000).fadeOut(400); - }); - - that.syncSetting('tvshow', value); - }, - generateQRcode: function () { var qrcodecanvus = document.getElementById('qrcode'), QRCodeInfo = { @@ -244,19 +276,6 @@ apiDataChanged = true; value = parseInt(field.val()); break; - case 'tvshow': - value = field.val(); - if (value.substr(-1) !== '/') { - value += '/'; - } - if (value.substr(0, 8) !== 'https://' && value.substr(0, 7) !== 'http://') { - value = 'http://' + value; - } - value = [{ - url: value, - strictSSL: value.substr(0, 8) === 'https://' - }]; - break; case 'subtitle_size': case 'tv_detail_jump_to': case 'subtitle_language': @@ -298,9 +317,13 @@ case 'protocolEncryption': case 'contentLangOnly': case 'vpnEnabled': + case 'dhtEnable': case 'coversShowRating': case 'torColSearchMore': case 'showSeedboxOnDlInit': + case 'showSubmitMeta': + case 'expandedSearch': + case 'showUndoRBookmark': case 'nativeWindowFrame': case 'translatePosters': case 'translateSynopsis': @@ -340,6 +363,7 @@ case 'streamPort': case 'subtitle_color': case 'maxActiveTorrents': + case 'maxUdpReqLimit': value = field.val(); break; case 'downloadLimit': @@ -364,6 +388,16 @@ value = nvalue; win.zoomLevel = Math.log(value/100) / Math.log(1.2); break; + case 'preloadNextEpisodeTime': + let nnvalue = field.val().replace(/[^0-9]/gi, ''); + if (!nnvalue) { + nnvalue = 1; + } else { + nnvalue = parseInt(nnvalue); + } + field.val(nnvalue); + value = nnvalue; + break; case 'tmpLocation': tmpLocationChanged = true; value = field.val(); @@ -446,6 +480,7 @@ } break; case 'protocolEncryption': + case 'maxUdpReqLimit': this.alertMessageSuccess(true); break; case 'downloadLimit': @@ -574,6 +609,9 @@ case 'multipleExtSubtitles': case 'torColSearchMore': case 'httpApiEnabled': + case 'showSubmitMeta': + case 'expandedSearch': + case 'playNextEpisodeAuto': $('.nav-hor.left li:first').click(); App.vent.trigger('settings:show'); break; @@ -593,10 +631,12 @@ $('.nav-hor.left li:first').click(); App.vent.trigger('settings:show'); break; - case 'tvshow': - App.Providers.delete('tvshow'); - $('.nav-hor.left li:first').click(); - App.vent.trigger('settings:show'); + case 'dhtEnable': + if (Settings.dhtEnable) { + this.updateDht('enable'); + } else { + this.alertMessageSuccess(true); + } break; default: } @@ -642,6 +682,16 @@ } }, + updateDht: function(e) { + let updateMode = ''; + if (e === 'enable') { + updateMode = e; + } else if (e) { + updateMode = 'manual'; + } + App.DhtReader.update(updateMode); + }, + connectTrakt: function (e) { if (!Settings.traktStatus) { $('#authTrakt').hide(); @@ -713,6 +763,18 @@ setTimeout(self.render, 200); }, + showFullDatalist: function(e) { + if (e.button === 0 && (!e.detail || e.detail === 1)) { + var tmpDlist = $(e.target).val(); + $(e.target).val(''); + $(e.target).one('blur', function() { + if (tmpDlist && !$(e.target).val()) { + $(e.target).val(tmpDlist); + } + }); + } + }, + rebuildBookmarks: function (e) { var btn = $(e.currentTarget); @@ -723,30 +785,36 @@ this.alertMessageWait(i18n.__('We are rebuilding your database')); Database.getAllBookmarks() - .then(function (data) { + .then(async function (data) { let movieProvider = App.Config.getProviderForType('movie')[0]; let showProvider = App.Config.getProviderForType('tvshow')[0]; - for (let item of data) { + for (let n in data) { + let item = data[n]; if (item.type === 'movie') { - movieProvider.fetch({keywords: item.imdb_id}).then(function (movies) { + await movieProvider.fetch({keywords: item.imdb_id, page:1}).then(function (movies) { if (movies.results.length !== 1) { return; } let movie = movies.results[0]; Database.deleteMovie(item.imdb_id); - movie.providers = [movieProvider.name]; + movie.providers = {}; + movie.providers.torrent = movieProvider; Database.addMovie(movie); }); } if (item.type === 'show') { - showProvider.detail(item.imdb_id, { + await showProvider.detail(item.imdb_id, { contextLocale: App.settings.contextLanguage || App.settings.language }).then(function (show) { Database.deleteTVShow(item.imdb_id); - show.providers = [showProvider.name]; + show.providers = {}; + show.providers.torrent = showProvider; Database.addTVShow(show); }); } + that.alertMessageWait(i18n.__('Rebuilding bookmarks (%s)', n+'/'+data.length)); + // api has nginx limit rps + await new Promise(resolve => setTimeout(resolve, 700)); } that.alertMessageSuccess(true); }); @@ -959,7 +1027,7 @@ alertMessageWait: function (waitDesc) { App.vent.trigger('notification:show', new App.Model.Notification({ title: i18n.__('Please wait') + '...', - body: waitDesc + '.', + body: waitDesc, type: 'danger' })); }, @@ -975,7 +1043,7 @@ notificationModel.set('showRestart', true); notificationModel.set('body', i18n.__('Please restart your application')); } else { - notificationModel.attributes.autoclose = 4000; + notificationModel.attributes.autoclose = true; } // Open the notification diff --git a/src/app/lib/views/show_detail.js b/src/app/lib/views/show_detail.js index 814de47fe7..133b1f859a 100644 --- a/src/app/lib/views/show_detail.js +++ b/src/app/lib/views/show_detail.js @@ -1,9 +1,6 @@ (function (App) { 'use strict'; - var torrentHealth = require('webtorrent-health'); - var cancelTorrentHealth = function () {}; - var torrentHealthRestarted = null; let healthButton; var _this, bookmarked; @@ -28,6 +25,7 @@ 'click .tab-episode': 'clickEpisode', 'click .shmi-year': 'openRelInfo', 'click .shmi-imdb': 'openIMDb', + 'click .shmi-tmdb-link': 'openTmdb', 'mousedown .magnet-icon': 'openMagnet', 'mousedown .source-icon': 'openSource', 'dblclick .tab-episode': 'dblclickEpisode', @@ -164,7 +162,7 @@ this.loadAudioDropdown(); this.getRegion('qualitySelector').empty(); - $('.star-container-tv,.shmi-year,.shmi-imdb,.magnet-icon,.source-icon').tooltip(); + $('.star-container-tv,.shmi-year,.shmi-imdb,.shmi-tmdb-link,.magnet-icon,.source-icon').tooltip(); var noimg = 'images/posterholder.png'; var nobg = 'images/bg-header.jpg'; var images = this.model.get('images'); @@ -366,23 +364,44 @@ openMagnet: function (e) { var torrentUrl = $('.startStreaming').attr('data-torrent').replace(/\&/g, '&'); torrentUrl = torrentUrl.split('&tr=')[0] + _.union(decodeURIComponent(torrentUrl).replace(/\/announce/g, '').split('&tr=').slice(1), Settings.trackers.forced.toString().replace(/\/announce/g, '').split(',')).map(t => `&tr=${t}/announce`).join(''); - if (e.button === 2) { //if right click on magnet link - var clipboard = nw.Clipboard.get(); - clipboard.set(torrentUrl, 'text'); //copy link to clipboard - $('.notification_alert').text(i18n.__('The magnet link was copied to the clipboard')).fadeIn('fast').delay(2500).fadeOut('fast'); - } else { - nw.Shell.openExternal(torrentUrl); - } + Common.openOrClipboardLink(e, torrentUrl, i18n.__('magnet link')); }, openSource: function (e) { var torrentUrl = $('.startStreaming').attr('data-source'); - if (e.button === 2) { //if right click on magnet link - var clipboard = nw.Clipboard.get(); - clipboard.set(torrentUrl, 'text'); //copy link to clipboard - $('.notification_alert').text(i18n.__('The source link was copied to the clipboard')).fadeIn('fast').delay(2500).fadeOut('fast'); + Common.openOrClipboardLink(e, torrentUrl, i18n.__('source link')); + }, + + openTmdb: function(e) { + let imdb = this.model.get('imdb_id'), + tmdb = this.model.get('tmdb_id'), + api_key = Settings.tmdb.api_key; + + if (!tmdb) { + let show = (function () { + let tmp = null; + $.ajax({ + url: 'http://api.themoviedb.org/3/find/' + imdb + '?api_key=' + api_key + '&external_source=imdb_id', + type: 'get', + dataType: 'json', + timeout: 5000, + async: false, + global: false, + success: function (data) { + tmp = data; + } + }); + return tmp; + }()); + show && show.tv_results && show.tv_results[0] && show.tv_results[0].id ? this.model.set('tmdb_id', show.tv_results[0].id) : null; + tmdb = this.model.get('tmdb_id'); + } + + if (tmdb) { + let tmdbLink = 'https://www.themoviedb.org/tv/' + tmdb + '/edit?language=' + Settings.language; + Common.openOrClipboardLink(e, tmdbLink, i18n.__('TMDB link')); } else { - nw.Shell.openExternal(torrentUrl); + $('.shmi-tmdb-link').addClass('disabled').prop('disabled', true).attr('title', i18n.__('Not available')).tooltip('hide').tooltip('fixTitle'); } }, @@ -397,8 +416,8 @@ return; } $('.spinner').show(); - const provider = this.model.get('providers').torrent; - const data = await provider.contentOnLang(this.model.get('imdb_id'), lang); + const showProvider = App.Config.getProviderForType('tvshow')[0]; + const data = await showProvider.contentOnLang(this.model.get('imdb_id'), lang); this.model.set('contextLocale', data.contextLocale); this.model.set('episodes', data.episodes); this.initTorrents(data.episodes); diff --git a/src/app/lib/views/torrent_collection.js b/src/app/lib/views/torrent_collection.js index 7cac659b84..1c0064698b 100644 --- a/src/app/lib/views/torrent_collection.js +++ b/src/app/lib/views/torrent_collection.js @@ -468,13 +468,7 @@ } magnetLink = magnetLink.split('&tr=')[0] + _.union(decodeURIComponent(magnetLink).replace(/\/announce/g, '').split('&tr=').slice(1), Settings.trackers.forced.toString().replace(/\/announce/g, '').split(',')).map(t => `&tr=${t}/announce`).join(''); - if (e.button === 2) { //if right click on magnet link - var clipboard = nw.Clipboard.get(); - clipboard.set(magnetLink, 'text'); //copy link to clipboard - $('.notification_alert').text(i18n.__('The magnet link was copied to the clipboard')).fadeIn('fast').delay(2500).fadeOut('fast'); - } else { - nw.Shell.openExternal(magnetLink); - } + Common.openOrClipboardLink(e, magnetLink, i18n.__('magnet link')); }, deleteItem: function (e) { diff --git a/src/app/settings.js b/src/app/settings.js index 05ff501c4f..308401ec53 100644 --- a/src/app/settings.js +++ b/src/app/settings.js @@ -4,14 +4,14 @@ var Settings = { projectUrl: 'https://popcorntime.app', projectCi: 'https://ci.popcorntime.app', projectBlog: 'https://blog.popcorntime.app/', - projectForum: 'https://www.reddit.com/r/PopcornTime', + projectForum: 'https://www.reddit.com/r/PopcornTimeApp', projectForum2: 'https://discuss.popcorntime.app', - projectForum3: 'https://www.reddit.com/r/PopcornTimeApp', statusUrl: 'http://status.popcorntime.app', changelogUrl: 'https://github.com/popcorn-official/popcorn-desktop/commits/master', issuesUrl: 'https://github.com/popcorn-official/popcorn-desktop/issues', sourceUrl: 'https://github.com/popcorn-official/popcorn-desktop/', commitUrl: 'https://github.com/popcorn-official/popcorn-desktop/commit', + dht: '', updateKey: '-----BEGIN PUBLIC KEY-----\n' + 'MIIBtjCCASsGByqGSM44BAEwggEeAoGBAPNM5SX+yR8MJNrX9uCQIiy0t3IsyNHs\n' + @@ -84,10 +84,9 @@ Settings.trackers = { 'udp://tracker.cyberia.is:6969', 'udp://tracker.torrent.eu.org:451', 'udp://open.stealth.si:80', - 'udp://opentor.org:2710', 'udp://tracker.moeking.me:6969', 'udp://tracker.zerobytes.xyz:1337', - 'udp://tracker.uw0.xyz:6969', + 'udp://explodie.org:6969', 'udp://retracker.lanta-net.ru:2710', 'wss://tracker.openwebtorrent.com' ] @@ -127,6 +126,7 @@ Settings.translateEpisodes = true; //Playback Settings.alwaysFullscreen = false; Settings.playNextEpisodeAuto = false; +Settings.preloadNextEpisodeTime = 1; Settings.activateLoCtrl = false; Settings.chosenPlayer = 'local'; @@ -141,6 +141,9 @@ Settings.moviesTabEnable = true; Settings.seriesTabEnable = true; Settings.animeTabEnable = true; Settings.showSeedboxOnDlInit = true; +Settings.showSubmitMeta = true; +Settings.showUndoRBookmark = true; +Settings.expandedSearch = false; // Quality Settings.shows_default_quality = '720p'; @@ -179,6 +182,7 @@ Settings.connectionLimit = 55; Settings.downloadLimit = ''; Settings.uploadLimit = ''; Settings.maxLimitMult = 1024; +Settings.maxUdpReqLimit = 16; Settings.streamPort = 0; // 0 = Random Settings.protocolEncryption = false; Settings.tmpLocation = path.join(os.tmpdir(), Settings.projectName); @@ -190,8 +194,9 @@ Settings.delSeedboxCache = 'ask'; Settings.continueSeedingOnStart = false; Settings.vpnEnabled = false; Settings.maxActiveTorrents = 5; -Settings.automaticUpdating = true; +Settings.automaticUpdating = ''; Settings.UpdateSeed = false; +Settings.dhtEnable = ''; Settings.events = true; Settings.minimizeToTray = false; diff --git a/src/app/styl/views/filter_bar.styl b/src/app/styl/views/filter_bar.styl index aeed85a3bc..b4c2bc06e1 100644 --- a/src/app/styl/views/filter_bar.styl +++ b/src/app/styl/views/filter_bar.styl @@ -121,7 +121,7 @@ padding: 3px 5px font-size: 1.2em - &.edited input, input:focus + &.edited input, input:focus, input.expanded width: 180px background-color: $SearchBoxBg color: $FilterBarText diff --git a/src/app/styl/views/initializing.styl b/src/app/styl/views/initializing.styl index 471604ce68..b62cbf3211 100644 --- a/src/app/styl/views/initializing.styl +++ b/src/app/styl/views/initializing.styl @@ -155,6 +155,58 @@ width 100% height 100% + input[type=checkbox] + position absolute + overflow hidden + clip rect(0 0 0 0) + height 1px + width 1px + margin -1px + padding 0 + border 0 + + &+label + height 15px + display inline-block + line-height 15px + font-size 13px + font-family $MainFont + vertical-align middle + cursor pointer + + &:hover + opacity 1 + + &:checked+label + opacity 1 + + &:after + opacity 1 + + label + &:before + content '\f0c8' + font-family "Font Awesome 5 Free" + font-weight 900 + font-size 18px + padding-right 8px + float left + position relative + color $CheckboxBg + + &:after + content '\f00c' + font-family "Font Awesome 5 Free" + font-weight 900 + font-size 12px + margin-right -14px + color $CheckboxCheck + position relative + float left + left -21px + opacity 0 + transition opacity .1s ease-in-out + .icon-disclaimer z-index 1000 top 20% @@ -194,13 +246,25 @@ position relative .disclaimer-content - padding-top 20% + padding-top 14% height 100% h1 font-size 25px text-transform uppercase + .dhtEnableSpn + display block + font-size 0.9em + text-align left + padding 12px 0 0 28px + + .automaticUpdatingSpn + display block + font-size 0.9em + text-align left + padding 10px 0 8px 28px + .disclaimer-text font-size 14px margin 20px diff --git a/src/app/styl/views/movie_detail.styl b/src/app/styl/views/movie_detail.styl index b1e3650dab..c409267ea8 100644 --- a/src/app/styl/views/movie_detail.styl +++ b/src/app/styl/views/movie_detail.styl @@ -117,6 +117,25 @@ font-smoothing: antialiased cursor: pointer + .tmdb-link + color: #f8f8f8 + font-size: 11px + position: relative + font-family: "Font Awesome 5 Free" + text-stroke: 1px rgba(0,0,0,0.1) + float: left + font-smoothing: antialiased + cursor: pointer + opacity: 0.4 + transition: opacity .3s ease-in + + &:hover + opacity: 1 + + &.disabled + cursor: default + opacity: 0.4 + .year, .certification color: #f8f8f8 font-size: 12px diff --git a/src/app/styl/views/notification.styl b/src/app/styl/views/notification.styl index 1d4479b71a..dfb5c89412 100644 --- a/src/app/styl/views/notification.styl +++ b/src/app/styl/views/notification.styl @@ -33,7 +33,7 @@ &.warning background $NotificationWarning - &.orange + &.danger background $NotificationOrange &.error @@ -42,7 +42,7 @@ .close position absolute top 5px - right 5px + right 7px opacity 0.7 color white &:hover @@ -71,6 +71,9 @@ background $NotificationBtn opacity .7 + label + cursor pointer + .btn.chnglog margin-right 5px diff --git a/src/app/styl/views/seedbox.styl b/src/app/styl/views/seedbox.styl index 0d5a05ade2..452c7de940 100644 --- a/src/app/styl/views/seedbox.styl +++ b/src/app/styl/views/seedbox.styl @@ -28,7 +28,8 @@ .seedbox-types ul, .seedbox-torrents ul height: calc(100vh - 167px) - direction: rtl + /* direction: rtl */ + text-align: right scrollable() li @@ -39,20 +40,26 @@ cursor: pointer .watched - padding 9px 0 + padding 10px 0 color: $ShowWatchedIcon_false transition color .5s - - &:hover - color: $ShowWatchedIcon_hover + font-size: 0.9em + font-family: "Font Awesome 5 Free", $MainFont &.true color: $ShowWatchedIcon_true &.disabled - pointer-events: none + cursor: not-allowed opacity: 0.2 + &:hover + color: $ShowWatchedIcon_false !important + + .watched:not(.fa-download):not(.fa-upload) + &:hover + color: $ShowWatchedIcon_true + li:nth-child(odd) background-color $ShowBgColor2 @@ -137,6 +144,10 @@ .seedbox-torrent-list ul li.active i color: rgba($EpisodeSelectorText,.5) + .seedbox-torrent-list ul li.active i:not(.fa-download):not(.fa-upload) + &:hover + color: $EpisodeSelectorText + .seedbox-torrent-list ul li.error background: $NotificationError @@ -246,6 +257,10 @@ white-space: nowrap text-overflow: ellipsis + i + margin-right: 5px + font-family: "Font Awesome 5 Free", $MainFont + .seedbox-infos-synopsis color: $ShowText1 font-size: 13px @@ -273,27 +288,57 @@ filter brightness(110%) backdrop-filter brightness(110%) + & > .item-remove + display inline-block + + &.unselected + opacity 0.3 + + &:hover + opacity 0.5 + + & > .item-download + display inline-block + + .item-download + display none + a color $FileSelectorText text-decoration blink - width 100% + width calc(100% - 20px) display block transition all 0.3s overflow hidden white-space nowrap text-overflow ellipsis + margin-left 25px - .item-delete, - .item-rename + .item-download, + .item-remove, + .item-play position relative color: $TextError transition all 0.3s cursor pointer - left calc(100% + 22px) + left calc(100% + 7px) top -17px - .item-rename - left calc(100% - 15px) + &:hover + color $CloseButtonHover + + .item-play + left 0px + + &.disabled + cursor not-allowed + opacity 0.3 + + &:hover + color: $TextError !important + + .item-remove + display none .item-icon position relative diff --git a/src/app/styl/views/settings_container.styl b/src/app/styl/views/settings_container.styl index 89f246f450..1bd6a4d4fc 100644 --- a/src/app/styl/views/settings_container.styl +++ b/src/app/styl/views/settings_container.styl @@ -285,6 +285,40 @@ position relative top 2px + #apiserver + input + text-overflow ellipsis + + .valid-tick + width 20px + height 20px + display inline-flex + line-height 12px + + &:before + content "\2714" + font-family Arial + font-size 17px + font-weight bold + text-shadow 0 0 10px #4EEE30 + color #4EEE30 + position relative + top 1px + + .invalid-cross + width 20px + height 20px + display inline-flex + line-height 12px + vertical-align top + + &:before + content "\2573" + font-family Arial + font-size 12px + font-weight bolder + text-shadow 0 0 10px #EE3030 + color #EE3030 #connection #overallRatio @@ -357,9 +391,11 @@ transition: all .5s .set-current-filter, - .reset-current-filter + .reset-current-filter, + .update-dht, + .update-app font-size: 13px - margin-left: 10px + margin: 0 2px 0 8px transition: all 0.5s cursor: pointer &:hover @@ -622,7 +658,9 @@ .default-frame .settings-container-contain padding-top 0 + .close-icon + top 5px &::-webkit-scrollbar-track margin-top: $FilterBarHeight .close-icon - top 5px + top 45px diff --git a/src/app/styl/views/show_detail.styl b/src/app/styl/views/show_detail.styl index 721ef54dc9..c3385a3f4e 100644 --- a/src/app/styl/views/show_detail.styl +++ b/src/app/styl/views/show_detail.styl @@ -87,6 +87,18 @@ div.shmi-year cursor: pointer + div.shmi-tmdb-link + cursor: pointer + opacity: 0.4 + transition: opacity .3s ease-in + + &:hover + opacity: 1 + + &.disabled + cursor: default + opacity: 0.4 + div.shmi-imdb cursor: pointer background: url(../images/icons/imdb.png) no-repeat diff --git a/src/app/templates/about.tpl b/src/app/templates/about.tpl index a2d7b6b617..f4e8653d44 100644 --- a/src/app/templates/about.tpl +++ b/src/app/templates/about.tpl @@ -25,7 +25,7 @@ - + diff --git a/src/app/templates/browser/filter-bar.tpl b/src/app/templates/browser/filter-bar.tpl index 3b908eef8f..254716e355 100644 --- a/src/app/templates/browser/filter-bar.tpl +++ b/src/app/templates/browser/filter-bar.tpl @@ -1,6 +1,12 @@ @@ -37,7 +43,7 @@
  • diff --git a/src/app/templates/disclaimer.tpl b/src/app/templates/disclaimer.tpl index 33eeff6463..b739e6047f 100644 --- a/src/app/templates/disclaimer.tpl +++ b/src/app/templates/disclaimer.tpl @@ -29,6 +29,14 @@

    By using '<%= Settings.projectName %>' or accessing this site you affirm that you are either more than 18 years of age, or an emancipated minor, or possess legal parental or guardian consent, and are fully able and competent to enter into the terms, conditions, obligations, affirmations, representations, and warranties set forth in these Terms of Service, and to abide by and comply with these Terms of Service. In any case, you affirm that you are over the age of 13, as the Service is not intended for children under 13. If you are under 13 years of age, then please do not use the Service. There are lots of other great web sites for you. Talk to your parents about what sites are appropriate for you.

    + + > + + + + > + +
    <%= i18n.__("I Accept") %> <%= i18n.__("Leave") %> diff --git a/src/app/templates/keyboard.tpl b/src/app/templates/keyboard.tpl index 87cb7e8005..eda05435b8 100644 --- a/src/app/templates/keyboard.tpl +++ b/src/app/templates/keyboard.tpl @@ -284,6 +284,46 @@ 0 <%= i18n.__("Set player window to half of video resolution") %> + + w + <%= i18n.__("Decrease Zoom by") %> 5% + + + e + <%= i18n.__("Increase Zoom by") %> 5% + + + <%= i18n.__("shift") %>+1 + <%= i18n.__("Decrease Contrast by") %> 5% + + + <%= i18n.__("shift") %>+2 + <%= i18n.__("Increase Contrast by") %> 5% + + + <%= i18n.__("shift") %>+3 + <%= i18n.__("Decrease Brightness by") %> 5% + + + <%= i18n.__("shift") %>+4 + <%= i18n.__("Increase Brightness by") %> 5% + + + <%= i18n.__("shift") %>+5 + <%= i18n.__("Rotate Hue counter-clockwise by") %> 1° + + + <%= i18n.__("shift") %>+6 + <%= i18n.__("Rotate Hue clockwise by") %> 1° + + + <%= i18n.__("shift") %>+7 + <%= i18n.__("Decrease Saturation by") %> 5% + + + <%= i18n.__("shift") %>+8 + <%= i18n.__("Increase Saturation by") %> 5% + diff --git a/src/app/templates/loading.tpl b/src/app/templates/loading.tpl index ae64765ba6..7067187ae5 100644 --- a/src/app/templates/loading.tpl +++ b/src/app/templates/loading.tpl @@ -13,7 +13,7 @@
    -
    ">
    +
    ">
    <%= i18n.__("Streaming to") %>
    @@ -79,9 +79,9 @@ 0
    <%= i18n.__("Filename") %>:  "> - ">
    + ">
    <%= i18n.__("Stream Url") %>:  - ">
    + ">
    ">
    diff --git a/src/app/templates/movie-detail.tpl b/src/app/templates/movie-detail.tpl index bf435c78ae..2615b3f0dd 100644 --- a/src/app/templates/movie-detail.tpl +++ b/src/app/templates/movie-detail.tpl @@ -26,14 +26,14 @@ if (genre) {
    <%= displayTitle %>
    -
    "><%= year %>
    +
    <%= year %>
    <%= runtime %> min
    <%= genre.join(" / ") %>
    <% if((typeof(certification) !== 'undefined') && (certification !== null) && (certification !== '') && (certification !== 'NR')) { %> -
    "><%= certification %>
    +
    <%= certification %>
    <% } %> -
    ">
    -
    " class="movie-imdb-link">
    +
    +
    <% var p_rating = Math.round(rating) / 2; %> @@ -52,8 +52,11 @@ if (genre) {
    -
    " class="fa fa-circle health-icon <%= health %>">
    -
    " class="fa fa-magnet magnet-link">
    + <% if (Settings.showSubmitMeta) { %> +
    + <% } %> +
    +
    diff --git a/src/app/templates/seedbox.tpl b/src/app/templates/seedbox.tpl index 4db52c060e..17d920256f 100644 --- a/src/app/templates/seedbox.tpl +++ b/src/app/templates/seedbox.tpl @@ -20,6 +20,7 @@
    + @@ -32,7 +33,7 @@
    - Download progress + <%= i18n.__('Unknown time remaining') %>
    0% diff --git a/src/app/templates/settings-container.tpl b/src/app/templates/settings-container.tpl index 0e686d5693..522cd48308 100644 --- a/src/app/templates/settings-container.tpl +++ b/src/app/templates/settings-container.tpl @@ -110,9 +110,21 @@ <% if (Settings.activateSeedbox) { %> > - + <% } %> + + > + + + + > + + + + > + + @@ -518,7 +536,7 @@ > -<% if (Settings.httpApiEnabled) { %> + <% if (Settings.httpApiEnabled) { %>

    <%= i18n.__("Local IP Address") %>

    @@ -549,7 +567,7 @@
    -<% } %> + <% } %>
    @@ -558,67 +576,61 @@
    -

    <%= i18n.__("Movies API Server") %>

    - +

    <%= i18n.__("Movies API Server(s)") %>

    + -
    -

    <%= i18n.__("Series API Server") %>

    - +

    <%= i18n.__("Series API Server(s)") %>

    + -
    -

    <%= i18n.__("Anime API Server") %>

    - +

    <%= i18n.__("Anime API Server(s)") %>

    + -
    + + * <%= i18n.__("You can add multiple API Servers separated with a , from which it will select randomly (*for load balancing) until it finds the first available") %> +
    <%= i18n.__("Connection") %>
    - <% if (Settings.tvshow) { %> - -

    <%= i18n.__("TV Show API Endpoint") %>

    - - <% if (Settings.tvshow.length <= 1) { %> -    - <% } %> -
    - <% } %> <% if (Settings.activateSeedbox) { %>

    <%= i18n.__("Active Torrents Limit") %>

    @@ -629,6 +641,10 @@

    <%= i18n.__("Connection Limit") %>

    + +

    <%= i18n.__("DHT UDP Requests Limit") %>

    + +

    <%= i18n.__("Max. Down / Up Speed") %>

    @@ -692,7 +708,7 @@

    <%= i18n.__("Cache Directory") %>

    - " id="faketmpLocation" value="<%= Settings.tmpLocation %>" readonly="readonly" size="65" /> + " id="faketmpLocation" value="<%= Settings.tmpLocation %>" readonly="readonly" size="61" /> ">
    @@ -724,7 +740,7 @@ <% if (Settings.activateSeedbox && Settings.separateDownloadsDir) { %>

    <%= i18n.__("Downloads Directory") %>

    - " id="fakedownloadsLocation" value="<%= Settings.downloadsLocation %>" readonly="readonly" size="65" /> + " id="fakedownloadsLocation" value="<%= Settings.downloadsLocation %>" readonly="readonly" size="61" /> ">
    @@ -737,7 +753,7 @@

    <%= i18n.__("Database Directory") %>

    - " id="fakedatabaseLocation" value="<%= Settings.databaseLocation %>" readonly="readonly" size="65" /> + " id="fakedatabaseLocation" value="<%= Settings.databaseLocation %>" readonly="readonly" size="61" /> ">
    @@ -786,18 +802,22 @@
    <%= i18n.__("Miscellaneous") %>
    - - > - + + > + > - + > + + > + +
    diff --git a/src/app/templates/show-detail.tpl b/src/app/templates/show-detail.tpl index 1aa0ee0dee..e747182d79 100644 --- a/src/app/templates/show-detail.tpl +++ b/src/app/templates/show-detail.tpl @@ -11,7 +11,7 @@ + <% if (Settings.showSubmitMeta) { %> + + + <% } %>
    <%= displaySynopsis %>
    diff --git a/yarn.lock b/yarn.lock index f7cda5503d..bf9c5e0a28 100644 --- a/yarn.lock +++ b/yarn.lock @@ -157,6 +157,11 @@ request-promise-native "^1.0.8" ws "^7.2.1" +"@yarnpkg/lockfile@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz#e77a97fbd345b76d83245edcd17d393b1b41fb31" + integrity sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ== + abbrev@1: version "1.1.1" resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" @@ -825,16 +830,16 @@ bittorrent-tracker@^9.1.0: bufferutil "^4.0.3" utf-8-validate "^5.0.5" -bittorrent-tracker@^9.18.2: - version "9.18.2" - resolved "https://registry.yarnpkg.com/bittorrent-tracker/-/bittorrent-tracker-9.18.2.tgz#208f27d69bfb81ccb620655557f8778636bf0e6e" - integrity sha512-r4v+gIi/aQP4h0rvx7WVjnEFvu7Vw2ePPFzoyQjdPfyoJaV/JTdD3kFTZBaVO/Egj5y2O2Y+bTCdPIgD2MzT+A== +bittorrent-tracker@^9.18.3: + version "9.18.3" + resolved "https://registry.yarnpkg.com/bittorrent-tracker/-/bittorrent-tracker-9.18.3.tgz#0b2d8a20c8974d118c010b2fc99ff4d914e6cb92" + integrity sha512-IhLKp8wUgA7WXTfJggw/HB8qxhwlLNDWRraUFxXRHTgOQXcMiKITGcErzvC7B7mMOcUnk0wiUsZdaaQ8lzz3LQ== dependencies: bencode "^2.0.1" bittorrent-peerid "^1.3.3" bn.js "^5.2.0" chrome-dgram "^3.0.6" - clone "^1.0.2" + clone "^2.0.0" compact2string "^1.4.1" debug "^4.1.1" ip "^1.1.5" @@ -969,6 +974,13 @@ braces@^2.3.1, braces@^2.3.2: split-string "^3.0.2" to-regex "^3.0.1" +braces@^3.0.1: + version "3.0.2" + resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" + integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== + dependencies: + fill-range "^7.0.1" + browserify-package-json@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/browserify-package-json/-/browserify-package-json-1.0.1.tgz#98dde8aa5c561fd6d3fe49bbaa102b74b396fdea" @@ -1049,10 +1061,10 @@ butter-sanitize@^0.1.1: dependencies: sanitizer "^0.1.3" -butter-settings-popcorntime.app@0.0.6: - version "0.0.6" - resolved "https://registry.yarnpkg.com/butter-settings-popcorntime.app/-/butter-settings-popcorntime.app-0.0.6.tgz#4f43e3a658f90d00a991566a59e18d37fe1ba3d2" - integrity sha512-fmboxwTi9X6yPUu3jc64hOIlSm42EWAag2WV/9D9AO/B2FaL96qXuDwp+5U1U6iQ3qtti3lxNRWTUuUdkYduOw== +butter-settings-popcorntime.app@0.0.9: + version "0.0.9" + resolved "https://registry.yarnpkg.com/butter-settings-popcorntime.app/-/butter-settings-popcorntime.app-0.0.9.tgz#89cfd82a7115794cce69d4e299bc8d5ae12e6182" + integrity sha512-k/95NLPNBwnD9+daePbxye5qRjU61rMIc2ix3ytHWtekn7xDg/7ZqxIc1GfJoWYNtK7uNVmpca/JU8JMChRFsQ== bytes@^3.0.0: version "3.1.0" @@ -1199,7 +1211,7 @@ chalk@^1.0.0, chalk@^1.1.1, chalk@^1.1.3: strip-ansi "^3.0.0" supports-color "^2.0.0" -chalk@^2.0.1, chalk@^2.3.2: +chalk@^2.0.1, chalk@^2.3.2, chalk@^2.4.2: version "2.4.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== @@ -1332,6 +1344,11 @@ ci-info@^1.5.0: resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-1.6.0.tgz#2ca20dbb9ceb32d4524a683303313f0304b1e497" integrity sha512-vsGdkwSCDpWmP80ncATX7iea5DWQemg1UgCW5J8tqjU3lYw4FBYuj89J0CTVomA7BEfvSZd84GmHko+MxFQU2A== +ci-info@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-2.0.0.tgz#67a9e964be31a51e15e5010d58e6f12834002f46" + integrity sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ== + class-utils@^0.3.5: version "0.3.6" resolved "https://registry.yarnpkg.com/class-utils/-/class-utils-0.3.6.tgz#f93369ae8b9a7ce02fd41faad0ca83033190c463" @@ -1409,7 +1426,7 @@ clone@^1.0.0, clone@^1.0.2: resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.4.tgz#da309cc263df15994c688ca902179ca3c7cd7c7e" integrity sha1-2jCcwmPfFZlMaIypAheco8fNfH4= -clone@^2.1.1: +clone@^2.0.0, clone@^2.1.1: version "2.1.2" resolved "https://registry.yarnpkg.com/clone/-/clone-2.1.2.tgz#1b7f4b9f591f1e8f83670401600345a02887435f" integrity sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18= @@ -1638,7 +1655,7 @@ cross-spawn@^5.0.1: shebang-command "^1.2.0" which "^1.2.9" -cross-spawn@^6.0.0: +cross-spawn@^6.0.0, cross-spawn@^6.0.5: version "6.0.5" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4" integrity sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ== @@ -2444,6 +2461,13 @@ fill-range@^4.0.0: repeat-string "^1.6.1" to-regex-range "^2.1.0" +fill-range@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" + integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== + dependencies: + to-regex-range "^5.0.1" + find-up@^1.0.0: version "1.1.2" resolved "https://registry.yarnpkg.com/find-up/-/find-up-1.1.2.tgz#6b2e9822b1a2ce0a60ab64d610eccad53cb24d0f" @@ -2464,6 +2488,13 @@ find-value@^1.0.3: resolved "https://registry.yarnpkg.com/find-value/-/find-value-1.0.12.tgz#68b6cec84e5b2d51272965e0bf09b26c9159c26e" integrity sha512-OCpo8LTk8eZ2sdDCwbU2Lc3ivYsdM6yod6jP2jHcNEFcjPhkgH0+POzTIol7xx1LZgtbI5rkO5jqxsG5MWtPjQ== +find-yarn-workspace-root@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/find-yarn-workspace-root/-/find-yarn-workspace-root-2.0.0.tgz#f47fb8d239c900eb78179aa81b66673eac88f7bd" + integrity sha512-1IMnbjt4KzsQfnhnzNd8wUEgXZ44IzZaZmnLYx7D5FZlaHt2gW20Cri8Q+E/t5tIj4+epTBub+2Zxu/vNILzqQ== + dependencies: + micromatch "^4.0.2" + findup-sync@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/findup-sync/-/findup-sync-2.0.0.tgz#9326b1488c22d1a6088650a86901b2d9a90a2cbc" @@ -2577,10 +2608,10 @@ fresh@0.5.2: resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" integrity sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac= -fs-chunk-store@^2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/fs-chunk-store/-/fs-chunk-store-2.0.3.tgz#21e51f1833a84a07cb5e911d058dae084030375a" - integrity sha512-qQi93nHX3880gtoQPt1hKQcuYBNVfCbMk8OVRDqR0cJ0riheELW25ry9yl7pII8E9gOAONTGKBD5N/zGHFSVQg== +fs-chunk-store@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/fs-chunk-store/-/fs-chunk-store-2.0.4.tgz#ca797b7032a3752d1e7553cb9cec8970395cc34a" + integrity sha512-JfeKRPPWkLaUoNKZdi+eLPKzZkZK1pdj2Y5lidEw9fUCkglvK/muLe6ONjdvn8yAGrDsk4tkjNp52GS658yy0g== dependencies: queue-microtask "^1.2.2" random-access-file "^2.0.1" @@ -2605,6 +2636,15 @@ fs-extra@^0.30.0: path-is-absolute "^1.0.0" rimraf "^2.2.8" +fs-extra@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-7.0.1.tgz#4f189c44aa123b895f722804f55ea23eadc348e9" + integrity sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw== + dependencies: + graceful-fs "^4.1.2" + jsonfile "^4.0.0" + universalify "^0.1.0" + fs-minipass@^1.2.7: version "1.2.7" resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-1.2.7.tgz#ccff8570841e7fe4265693da88936c55aed7f7c7" @@ -3293,9 +3333,9 @@ http-headers@^3.0.1: dependencies: next-line "^1.1.0" -"http-node@github:feross/http-node#webtorrent": +"http-node@github:webtorrent/http-node#webtorrent": version "1.2.0" - resolved "https://codeload.github.com/feross/http-node/tar.gz/342ef8624495343ffd050bd0808b3750cf0e3974" + resolved "https://codeload.github.com/webtorrent/http-node/tar.gz/342ef8624495343ffd050bd0808b3750cf0e3974" dependencies: chrome-net "^3.3.3" freelist "^1.0.3" @@ -3519,6 +3559,13 @@ is-ci@^1.0.10: dependencies: ci-info "^1.5.0" +is-ci@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-2.0.0.tgz#6bc6334181810e04b5c22b3d589fdca55026404c" + integrity sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w== + dependencies: + ci-info "^2.0.0" + is-core-module@^2.2.0: version "2.6.0" resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.6.0.tgz#d7553b2526fe59b92ba3e40c8df757ec8a709e19" @@ -3565,6 +3612,11 @@ is-descriptor@^1.0.0, is-descriptor@^1.0.2: is-data-descriptor "^1.0.0" kind-of "^6.0.2" +is-docker@^2.0.0: + version "2.2.1" + resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-2.2.1.tgz#33eeabe23cfe86f14bde4408a02c0cfb853acdaa" + integrity sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ== + is-dotfile@^1.0.0: version "1.0.3" resolved "https://registry.yarnpkg.com/is-dotfile/-/is-dotfile-1.0.3.tgz#a6a2f32ffd2dfb04f5ca25ecd0f6b83cf798a1e1" @@ -3679,6 +3731,11 @@ is-number@^4.0.0: resolved "https://registry.yarnpkg.com/is-number/-/is-number-4.0.0.tgz#0026e37f5454d73e356dfe6564699867c6a7f0ff" integrity sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ== +is-number@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" + integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== + is-obj@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-1.0.1.tgz#3e4729ac1f5fde025cd7d83a896dab9f4f67db0f" @@ -3802,6 +3859,13 @@ is-windows@^1.0.1, is-windows@^1.0.2: resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" integrity sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA== +is-wsl@^2.1.1: + version "2.2.0" + resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-2.2.0.tgz#74a4c76e77ca9fd3f932f290c17ea326cd157271" + integrity sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww== + dependencies: + is-docker "^2.0.0" + isarray@0.0.1, isarray@~0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" @@ -3956,6 +4020,13 @@ jsonfile@^2.1.0: optionalDependencies: graceful-fs "^4.1.6" +jsonfile@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb" + integrity sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss= + optionalDependencies: + graceful-fs "^4.1.6" + jsonparse@1.x.x: version "1.3.1" resolved "https://registry.yarnpkg.com/jsonparse/-/jsonparse-1.3.1.tgz#3f4dae4a91fac315f71062f8521cc239f1366280" @@ -4055,6 +4126,13 @@ kind-of@^6.0.0, kind-of@^6.0.2: resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw== +klaw-sync@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/klaw-sync/-/klaw-sync-6.0.0.tgz#1fd2cfd56ebb6250181114f0a581167099c2b28c" + integrity sha512-nIeuVSzdCCs6TDPTqI8w1Yre34sSq7AkZ4B3sfOBbI2CgVSB4Du4aLQijFU2+lhAFCwt9+42Hel6lQNIv6AntQ== + dependencies: + graceful-fs "^4.1.11" + klaw@^1.0.0: version "1.3.1" resolved "https://registry.yarnpkg.com/klaw/-/klaw-1.3.1.tgz#4088433b46b3b1ba259d78785d8e96f73ba02439" @@ -4648,6 +4726,14 @@ micromatch@^3.0.4, micromatch@^3.1.10, micromatch@^3.1.4: snapdragon "^0.8.1" to-regex "^3.0.2" +micromatch@^4.0.2: + version "4.0.4" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.4.tgz#896d519dfe9db25fce94ceb7a500919bf881ebf9" + integrity sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg== + dependencies: + braces "^3.0.1" + picomatch "^2.2.3" + mime-db@1.49.0: version "1.49.0" resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.49.0.tgz#f3dfde60c99e9cf3bc9701d687778f537001cbed" @@ -4937,6 +5023,11 @@ nice-try@^1.0.4: resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366" integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ== +noble-ed25519@^1.2.5: + version "1.2.5" + resolved "https://registry.yarnpkg.com/noble-ed25519/-/noble-ed25519-1.2.5.tgz#ed6dde9213debcf121083d18daecb30bb6416753" + integrity sha512-7vst+4UhM5QU3jJ3pUqPMKBCOePrxBojmoQa59qcSnYvjFF/T4jqb4WISlfslcWyBw7G5H9V/acpcAxMd8DzUQ== + node-fetch@^1.0.1: version "1.7.3" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-1.7.3.tgz#980f6f72d85211a5347c6b2bc18c5b84c3eb47ef" @@ -5203,6 +5294,14 @@ once@^1.3.0, once@^1.3.1, once@^1.3.2, once@^1.3.3, once@^1.4.0: dependencies: wrappy "1" +open@^7.4.2: + version "7.4.2" + resolved "https://registry.yarnpkg.com/open/-/open-7.4.2.tgz#b8147e26dcf3e426316c730089fd71edd29c2321" + integrity sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q== + dependencies: + is-docker "^2.0.0" + is-wsl "^2.1.1" + opensubtitles-api@^5.1.2: version "5.1.2" resolved "https://registry.yarnpkg.com/opensubtitles-api/-/opensubtitles-api-5.1.2.tgz#750c9e808fbf6b006225150e062de0876ff41288" @@ -5250,6 +5349,11 @@ os-locale@^3.0.0: lcid "^2.0.0" mem "^4.0.0" +os-tmpdir@~1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" + integrity sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ= + p-cancelable@^0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-0.3.0.tgz#b9e123800bcebb7ac13a479be195b507b98d30fa" @@ -5407,6 +5511,25 @@ pascalcase@^0.1.1: resolved "https://registry.yarnpkg.com/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14" integrity sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ= +patch-package@^6.4.7: + version "6.4.7" + resolved "https://registry.yarnpkg.com/patch-package/-/patch-package-6.4.7.tgz#2282d53c397909a0d9ef92dae3fdeb558382b148" + integrity sha512-S0vh/ZEafZ17hbhgqdnpunKDfzHQibQizx9g8yEf5dcVk3KOflOfdufRXQX8CSEkyOQwuM/bNz1GwKvFj54kaQ== + dependencies: + "@yarnpkg/lockfile" "^1.1.0" + chalk "^2.4.2" + cross-spawn "^6.0.5" + find-yarn-workspace-root "^2.0.0" + fs-extra "^7.0.1" + is-ci "^2.0.0" + klaw-sync "^6.0.0" + minimist "^1.2.0" + open "^7.4.2" + rimraf "^2.6.3" + semver "^5.6.0" + slash "^2.0.0" + tmp "^0.0.33" + path-dirname@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/path-dirname/-/path-dirname-1.0.2.tgz#cc33d24d525e099a5388c0336c6e32b9160609e0" @@ -5484,6 +5607,11 @@ performance-now@^2.1.0: resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns= +picomatch@^2.2.3: + version "2.3.1" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" + integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== + piece-length@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/piece-length/-/piece-length-2.0.1.tgz#dbed4e78976955f34466d0a65304d0cb21914ac9" @@ -5567,6 +5695,11 @@ posix-character-classes@^0.1.0: resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab" integrity sha1-AerA/jta9xoqbAL+q7jB/vfgDqs= +postinstall-postinstall@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/postinstall-postinstall/-/postinstall-postinstall-2.1.0.tgz#4f7f77441ef539d1512c40bd04c71b06a4704ca3" + integrity sha512-7hQX6ZlZXIoRiWNrbMQaLzUUfH+sSx39u8EJ9HYuDc1kLo9IXKWjM5RSquZN1ad5GnH8CGFM78fsAAQi3OKEEQ== + prepend-http@^1.0.1: version "1.0.4" resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-1.0.4.tgz#d4f4562b0ce3696e41ac52d0e002e57a635dc6dc" @@ -6165,7 +6298,7 @@ right-align@^0.1.1: dependencies: align-text "^0.1.1" -rimraf@^2.2.8, rimraf@^2.5.2: +rimraf@^2.2.8, rimraf@^2.5.2, rimraf@^2.6.3: version "2.7.1" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w== @@ -6370,9 +6503,9 @@ simple-concat@^1.0.0, simple-concat@^1.0.1: integrity sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q== simple-get@^2.0.0, simple-get@^2.1.0: - version "2.8.1" - resolved "https://registry.yarnpkg.com/simple-get/-/simple-get-2.8.1.tgz#0e22e91d4575d87620620bc91308d57a77f44b5d" - integrity sha512-lSSHRSw3mQNUGPAYRqo7xy9dhKmxFXIjLjp4KHpf99GEH2VH7C3AM+Qfx6du6jhfUi6Vm7XnbEVEf7Wb6N8jRw== + version "2.8.2" + resolved "https://registry.yarnpkg.com/simple-get/-/simple-get-2.8.2.tgz#5708fb0919d440657326cd5fe7d2599d07705019" + integrity sha512-Ijd/rV5o+mSBBs4F/x9oDPtTx9Zb6X9brmnXvMW4J7IR15ngi9q5xxqWBKU744jTZiaXtxaPL7uHG6vtN8kUkw== dependencies: decompress-response "^3.3.0" once "^1.3.1" @@ -6443,6 +6576,11 @@ single-line-log@^1.0.1: dependencies: string-width "^1.0.1" +slash@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/slash/-/slash-2.0.0.tgz#de552851a1759df3a8f206535442f5ec4ddeab44" + integrity sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A== + smart-buffer@^1.0.13: version "1.1.15" resolved "https://registry.yarnpkg.com/smart-buffer/-/smart-buffer-1.1.15.tgz#7f114b5b65fab3e2a35aa775bb12f0d1c649bf16" @@ -7042,6 +7180,13 @@ timers-ext@^0.1.7: es5-ext "~0.10.46" next-tick "1" +tmp@^0.0.33: + version "0.0.33" + resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9" + integrity sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw== + dependencies: + os-tmpdir "~1.0.2" + to-absolute-glob@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/to-absolute-glob/-/to-absolute-glob-0.1.1.tgz#1cdfa472a9ef50c239ee66999b662ca0eb39937f" @@ -7087,6 +7232,13 @@ to-regex-range@^2.1.0: is-number "^3.0.0" repeat-string "^1.6.1" +to-regex-range@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" + integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== + dependencies: + is-number "^7.0.0" + to-regex@^3.0.1, to-regex@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/to-regex/-/to-regex-3.0.2.tgz#13cfdd9b336552f30b51f33a8ae1b42a7a7599ce" @@ -7120,14 +7272,14 @@ toidentifier@1.0.0: resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.0.tgz#7e1be3470f1e77948bc43d94a3c8f4d7752ba553" integrity sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw== -torrent-discovery@^9.4.5: - version "9.4.6" - resolved "https://registry.yarnpkg.com/torrent-discovery/-/torrent-discovery-9.4.6.tgz#b7e1262a77d14242aaf52eec382f6a142f49e2ae" - integrity sha512-11FlrGmDvgD3RJhZLrC749yyqS7tKx3gXWbYN7xayVYsAcc6f8lQRQQIOF7TBgJE4f0e+ZS8dsct++aOlxFjRw== +torrent-discovery@^9.4.6: + version "9.4.7" + resolved "https://registry.yarnpkg.com/torrent-discovery/-/torrent-discovery-9.4.7.tgz#d45ee78cb6a7004a8f3cd203ee7df915088bea70" + integrity sha512-7Zw474LJE5r3Momi4ykBYkjgcFhENbUxcAFs5cBllUkv9ErJPzPEGmpEuqX7V8TkLS+Clmt/l5CjV5IFHg/A/A== dependencies: bittorrent-dht "^10.0.2" bittorrent-lsd "^1.1.1" - bittorrent-tracker "^9.18.2" + bittorrent-tracker "^9.18.3" debug "^4.3.2" run-parallel "^1.2.0" @@ -7334,6 +7486,11 @@ unique-string@^1.0.0: dependencies: crypto-random-string "^1.0.0" +universalify@^0.1.0: + version "0.1.2" + resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66" + integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg== + unordered-array-remove@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/unordered-array-remove/-/unordered-array-remove-1.0.2.tgz#c546e8f88e317a0cf2644c97ecb57dba66d250ef" @@ -7404,10 +7561,10 @@ uri-js@^4.2.2: dependencies: punycode "^2.1.0" -urijs@^1.19.1, urijs@^1.19.7: - version "1.19.7" - resolved "https://registry.yarnpkg.com/urijs/-/urijs-1.19.7.tgz#4f594e59113928fea63c00ce688fb395b1168ab9" - integrity sha512-Id+IKjdU0Hx+7Zx717jwLPsPeUqz7rAtuVBRLLs+qn+J2nf9NGITWVCxcijgYxBqe83C7sqsQPs6H1pyz3x9gA== +urijs@^1.19.1, urijs@^1.19.8: + version "1.19.8" + resolved "https://registry.yarnpkg.com/urijs/-/urijs-1.19.8.tgz#ee0407a18528934d3c383e691912f47043a58feb" + integrity sha512-iIXHrjomQ0ZCuDRy44wRbyTZVnfVNLVo3Ksz1yxNyE5wV1IDZW2S5Jszy45DTlw/UdsnRT7DyDhIz7Gy+vJumw== urix@^0.1.0: version "0.1.0" @@ -7429,9 +7586,9 @@ url-parse-lax@^3.0.0: prepend-http "^2.0.0" url-parse@^1.1.9: - version "1.5.3" - resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.5.3.tgz#71c1303d38fb6639ade183c2992c8cc0686df862" - integrity sha512-IIORyIQD9rvj0A4CLWsHkBBJuNqWpFQe224b6j9t/ABmquIS0qDU2pY6kl6AuOrL5OkCXHMCFNe1jBcuAggjvQ== + version "1.5.10" + resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.5.10.tgz#9d3c2f736c1d75dd3bd2be507dcc111f1e2ea9c1" + integrity sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ== dependencies: querystringify "^2.1.1" requires-port "^1.0.0" @@ -7704,10 +7861,10 @@ webtorrent-health@1.x.x: bittorrent-tracker "^9.1.0" parse-torrent "^5.8.2" -webtorrent@^1.5.5: - version "1.5.5" - resolved "https://registry.yarnpkg.com/webtorrent/-/webtorrent-1.5.5.tgz#af09e0ac660ac16fea1c838fdd00e56b57f9fc21" - integrity sha512-YAEtWZxxf8N6DvdLgt79fQlIXSJU0G61YEkcWyBA+aopQGV0vCAMp1N/ifKIFt760pgKV+qzwRSbVP+/lBJ08g== +webtorrent@^1.5.8: + version "1.5.8" + resolved "https://registry.yarnpkg.com/webtorrent/-/webtorrent-1.5.8.tgz#1dcb26347a8c0ea15a20b77f1c85dea9ce4f170b" + integrity sha512-ltYdloqDamay36XN8FZ+O2fqRQNDt+JGhRbOt1gCBeC+fFhke3WxEVs3/A2UtKjhwN8OEp3Go7tWU9R0S+29Lw== dependencies: addr-to-ip-port "^1.5.4" bitfield "^4.0.0" @@ -7721,8 +7878,8 @@ webtorrent@^1.5.5: debug "^4.3.2" end-of-stream "^1.4.4" escape-html "^1.0.3" - fs-chunk-store "^2.0.3" - http-node "github:feross/http-node#webtorrent" + fs-chunk-store "^2.0.4" + http-node "github:webtorrent/http-node#webtorrent" immediate-chunk-store "^2.2.0" load-ip-set "^2.2.1" lt_donthave "^1.0.1" @@ -7736,7 +7893,6 @@ webtorrent@^1.5.5: random-iterate "^1.0.1" randombytes "^2.1.0" range-parser "^1.2.1" - readable-stream "^3.6.0" render-media "^4.1.0" run-parallel "^1.2.0" run-parallel-limit "^1.1.0" @@ -7749,7 +7905,7 @@ webtorrent@^1.5.5: stream-to-blob "^2.0.1" stream-to-blob-url "^3.0.2" stream-with-known-length-to-buffer "^1.0.4" - torrent-discovery "^9.4.5" + torrent-discovery "^9.4.6" torrent-piece "^2.0.1" unordered-array-remove "^1.0.2" ut_metadata "^3.5.2"