Compare commits
14 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9d3e26f15a | ||
|
|
8a95895254 | ||
|
|
5d71f9e9c6 | ||
|
|
5d410457ce | ||
|
|
c6cd21b8ff | ||
|
|
2235b2fa82 | ||
|
|
65e0b5d6e7 | ||
|
|
ea64411570 | ||
|
|
9348c61a84 | ||
|
|
d9aa3822ee | ||
|
|
e86bd26800 | ||
|
|
6d8cec17de | ||
|
|
572f084570 | ||
|
|
4a3ca5459d |
11
CHANGELOG.md
11
CHANGELOG.md
@@ -1,5 +1,16 @@
|
|||||||
# WebTorrent Desktop Version History
|
# WebTorrent Desktop Version History
|
||||||
|
|
||||||
|
## v0.7.1 - 2016-06-02
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- Change "Step Forward" keyboard shortcut to `Alt+Left`
|
||||||
|
- Change "Step Backward" keyboard shortcut to to `Alt+Right`
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- First time startup bug -- invalid torrent/poster paths
|
||||||
|
|
||||||
## v0.7.0 - 2016-06-02
|
## v0.7.0 - 2016-06-02
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|||||||
@@ -2,7 +2,5 @@
|
|||||||
|
|
||||||
var config = require('../config')
|
var config = require('../config')
|
||||||
var open = require('open')
|
var open = require('open')
|
||||||
var path = require('path')
|
|
||||||
|
|
||||||
var configPath = path.join(config.CONFIG_PATH, 'config.json')
|
open(config.CONFIG_PATH)
|
||||||
open(configPath)
|
|
||||||
|
|||||||
50
config.js
50
config.js
@@ -24,11 +24,39 @@ module.exports = {
|
|||||||
CRASH_REPORT_URL: 'https://webtorrent.io/desktop/crash-report',
|
CRASH_REPORT_URL: 'https://webtorrent.io/desktop/crash-report',
|
||||||
|
|
||||||
CONFIG_PATH: getConfigPath(),
|
CONFIG_PATH: getConfigPath(),
|
||||||
CONFIG_POSTER_PATH: path.join(getConfigPath(), 'Posters'),
|
|
||||||
CONFIG_TORRENT_PATH: path.join(getConfigPath(), 'Torrents'),
|
DEFAULT_TORRENTS: [
|
||||||
|
{
|
||||||
|
name: 'Big Buck Bunny',
|
||||||
|
posterFileName: 'bigBuckBunny.jpg',
|
||||||
|
torrentFileName: 'bigBuckBunny.torrent'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Cosmos Laundromat (Preview)',
|
||||||
|
posterFileName: 'cosmosLaundromat.jpg',
|
||||||
|
torrentFileName: 'cosmosLaundromat.torrent'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Sintel',
|
||||||
|
posterFileName: 'sintel.jpg',
|
||||||
|
torrentFileName: 'sintel.torrent'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Tears of Steel',
|
||||||
|
posterFileName: 'tearsOfSteel.jpg',
|
||||||
|
torrentFileName: 'tearsOfSteel.torrent'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'The WIRED CD - Rip. Sample. Mash. Share.',
|
||||||
|
posterFileName: 'wiredCd.jpg',
|
||||||
|
torrentFileName: 'wiredCd.torrent'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
|
||||||
DELAYED_INIT: 3000 /* 3 seconds */,
|
DELAYED_INIT: 3000 /* 3 seconds */,
|
||||||
|
|
||||||
|
DEFAULT_DOWNLOAD_PATH: getDefaultDownloadPath(),
|
||||||
|
|
||||||
GITHUB_URL: 'https://github.com/feross/webtorrent-desktop',
|
GITHUB_URL: 'https://github.com/feross/webtorrent-desktop',
|
||||||
GITHUB_URL_ISSUES: 'https://github.com/feross/webtorrent-desktop/issues',
|
GITHUB_URL_ISSUES: 'https://github.com/feross/webtorrent-desktop/issues',
|
||||||
GITHUB_URL_RAW: 'https://raw.githubusercontent.com/feross/webtorrent-desktop/master',
|
GITHUB_URL_RAW: 'https://raw.githubusercontent.com/feross/webtorrent-desktop/master',
|
||||||
@@ -38,8 +66,10 @@ module.exports = {
|
|||||||
IS_PORTABLE: isPortable(),
|
IS_PORTABLE: isPortable(),
|
||||||
IS_PRODUCTION: isProduction(),
|
IS_PRODUCTION: isProduction(),
|
||||||
|
|
||||||
|
POSTER_PATH: path.join(getConfigPath(), 'Posters'),
|
||||||
ROOT_PATH: __dirname,
|
ROOT_PATH: __dirname,
|
||||||
STATIC_PATH: path.join(__dirname, 'static'),
|
STATIC_PATH: path.join(__dirname, 'static'),
|
||||||
|
TORRENT_PATH: path.join(getConfigPath(), 'Torrents'),
|
||||||
|
|
||||||
WINDOW_ABOUT: 'file://' + path.join(__dirname, 'renderer', 'about.html'),
|
WINDOW_ABOUT: 'file://' + path.join(__dirname, 'renderer', 'about.html'),
|
||||||
WINDOW_MAIN: 'file://' + path.join(__dirname, 'renderer', 'main.html'),
|
WINDOW_MAIN: 'file://' + path.join(__dirname, 'renderer', 'main.html'),
|
||||||
@@ -57,6 +87,22 @@ function getConfigPath () {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getDefaultDownloadPath () {
|
||||||
|
if (!process || !process.type) {
|
||||||
|
return ''
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isPortable()) {
|
||||||
|
return path.join(getConfigPath(), 'Downloads')
|
||||||
|
}
|
||||||
|
|
||||||
|
var electron = require('electron')
|
||||||
|
|
||||||
|
return process.type === 'renderer'
|
||||||
|
? electron.remote.app.getPath('downloads')
|
||||||
|
: electron.app.getPath('downloads')
|
||||||
|
}
|
||||||
|
|
||||||
function isPortable () {
|
function isPortable () {
|
||||||
try {
|
try {
|
||||||
return process.platform === 'win32' && isProduction() && !!fs.statSync(PORTABLE_PATH)
|
return process.platform === 'win32' && isProduction() && !!fs.statSync(PORTABLE_PATH)
|
||||||
|
|||||||
@@ -217,13 +217,17 @@ function getMenuTemplate () {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'Step Forward',
|
label: 'Step Forward',
|
||||||
accelerator: 'CmdOrCtrl+Alt+Right',
|
accelerator: process.platform === 'darwin'
|
||||||
|
? 'CmdOrCtrl+Alt+Right'
|
||||||
|
: 'Alt+Right',
|
||||||
click: () => windows.main.dispatch('skip', 1),
|
click: () => windows.main.dispatch('skip', 1),
|
||||||
enabled: false
|
enabled: false
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'Step Backward',
|
label: 'Step Backward',
|
||||||
accelerator: 'CmdOrCtrl+Alt+Left',
|
accelerator: process.platform === 'darwin'
|
||||||
|
? 'CmdOrCtrl+Alt+Left'
|
||||||
|
: 'Alt+Left',
|
||||||
click: () => windows.main.dispatch('skip', -1),
|
click: () => windows.main.dispatch('skip', -1),
|
||||||
enabled: false
|
enabled: false
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ function init () {
|
|||||||
resizable: false,
|
resizable: false,
|
||||||
show: false,
|
show: false,
|
||||||
skipTaskbar: true,
|
skipTaskbar: true,
|
||||||
|
title: 'About ' + config.APP_WINDOW_TITLE,
|
||||||
useContentSize: true,
|
useContentSize: true,
|
||||||
width: 300
|
width: 300
|
||||||
})
|
})
|
||||||
@@ -31,7 +32,7 @@ function init () {
|
|||||||
// No menu on the About window
|
// No menu on the About window
|
||||||
win.setMenu(null)
|
win.setMenu(null)
|
||||||
|
|
||||||
win.webContents.on('did-finish-load', function () {
|
win.webContents.once('did-finish-load', function () {
|
||||||
win.show()
|
win.show()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "webtorrent-desktop",
|
"name": "webtorrent-desktop",
|
||||||
"description": "WebTorrent, the streaming torrent client. For OS X, Windows, and Linux.",
|
"description": "WebTorrent, the streaming torrent client. For OS X, Windows, and Linux.",
|
||||||
"version": "0.7.0",
|
"version": "0.7.2",
|
||||||
"author": {
|
"author": {
|
||||||
"name": "WebTorrent, LLC",
|
"name": "WebTorrent, LLC",
|
||||||
"email": "feross@feross.org",
|
"email": "feross@feross.org",
|
||||||
@@ -30,6 +30,7 @@
|
|||||||
"main-loop": "^3.2.0",
|
"main-loop": "^3.2.0",
|
||||||
"musicmetadata": "^2.0.2",
|
"musicmetadata": "^2.0.2",
|
||||||
"network-address": "^1.1.0",
|
"network-address": "^1.1.0",
|
||||||
|
"parse-torrent": "^5.7.3",
|
||||||
"prettier-bytes": "^1.0.1",
|
"prettier-bytes": "^1.0.1",
|
||||||
"run-parallel": "^1.1.6",
|
"run-parallel": "^1.1.6",
|
||||||
"semver": "^5.1.0",
|
"semver": "^5.1.0",
|
||||||
|
|||||||
@@ -18,44 +18,41 @@ function run (state) {
|
|||||||
var version = state.saved.version
|
var version = state.saved.version
|
||||||
|
|
||||||
if (semver.lt(version, '0.7.0')) {
|
if (semver.lt(version, '0.7.0')) {
|
||||||
migrate_0_7_0(state)
|
migrate_0_7_0(state.saved)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Future migrations...
|
if (semver.lt(version, '0.7.2')) {
|
||||||
// if (semver.lt(version, '0.8.0')) {
|
migrate_0_7_2(state.saved)
|
||||||
// migrate_0_8_0(state)
|
}
|
||||||
// }
|
|
||||||
|
|
||||||
// Config is now on the new version
|
// Config is now on the new version
|
||||||
state.saved.version = config.APP_VERSION
|
state.saved.version = config.APP_VERSION
|
||||||
}
|
}
|
||||||
|
|
||||||
function migrate_0_7_0 (state) {
|
function migrate_0_7_0 (saved) {
|
||||||
console.log('migrate to 0.7.0')
|
console.log('migrate to 0.7.0')
|
||||||
|
|
||||||
var fs = require('fs-extra')
|
var fs = require('fs-extra')
|
||||||
var path = require('path')
|
var path = require('path')
|
||||||
|
|
||||||
state.saved.torrents.forEach(function (ts) {
|
saved.torrents.forEach(function (ts) {
|
||||||
var infoHash = ts.infoHash
|
var infoHash = ts.infoHash
|
||||||
|
|
||||||
// Replace torrentPath with torrentFileName
|
// Replace torrentPath with torrentFileName
|
||||||
|
// There are a number of cases to handle here:
|
||||||
|
// * Originally we used absolute paths
|
||||||
|
// * Then, relative paths for the default torrents, eg '../static/sintel.torrent'
|
||||||
|
// * Then, paths computed at runtime for default torrents, eg 'sintel.torrent'
|
||||||
|
// * Finally, now we're getting rid of torrentPath altogether
|
||||||
var src, dst
|
var src, dst
|
||||||
if (ts.torrentPath) {
|
if (ts.torrentPath) {
|
||||||
// There are a number of cases to handle here:
|
|
||||||
// * Originally we used absolute paths
|
|
||||||
// * Then, relative paths for the default torrents, eg '../static/sintel.torrent'
|
|
||||||
// * Then, paths computed at runtime for default torrents, eg 'sintel.torrent'
|
|
||||||
// * Finally, now we're getting rid of torrentPath altogether
|
|
||||||
console.log('replacing torrentPath %s', ts.torrentPath)
|
console.log('replacing torrentPath %s', ts.torrentPath)
|
||||||
if (path.isAbsolute(ts.torrentPath)) {
|
if (path.isAbsolute(ts.torrentPath) || ts.torrentPath.startsWith('..')) {
|
||||||
src = ts.torrentPath
|
|
||||||
} else if (ts.torrentPath.startsWith('..')) {
|
|
||||||
src = ts.torrentPath
|
src = ts.torrentPath
|
||||||
} else {
|
} else {
|
||||||
src = path.join(config.STATIC_PATH, ts.torrentPath)
|
src = path.join(config.STATIC_PATH, ts.torrentPath)
|
||||||
}
|
}
|
||||||
dst = path.join(config.CONFIG_TORRENT_PATH, infoHash + '.torrent')
|
dst = path.join(config.TORRENT_PATH, infoHash + '.torrent')
|
||||||
// Synchronous FS calls aren't ideal, but probably OK in a migration
|
// Synchronous FS calls aren't ideal, but probably OK in a migration
|
||||||
// that only runs once
|
// that only runs once
|
||||||
if (src !== dst) fs.copySync(src, dst)
|
if (src !== dst) fs.copySync(src, dst)
|
||||||
@@ -71,7 +68,7 @@ function migrate_0_7_0 (state) {
|
|||||||
src = path.isAbsolute(ts.posterURL)
|
src = path.isAbsolute(ts.posterURL)
|
||||||
? ts.posterURL
|
? ts.posterURL
|
||||||
: path.join(config.STATIC_PATH, ts.posterURL)
|
: path.join(config.STATIC_PATH, ts.posterURL)
|
||||||
dst = path.join(config.CONFIG_POSTER_PATH, infoHash + extension)
|
dst = path.join(config.POSTER_PATH, infoHash + extension)
|
||||||
// Synchronous FS calls aren't ideal, but probably OK in a migration
|
// Synchronous FS calls aren't ideal, but probably OK in a migration
|
||||||
// that only runs once
|
// that only runs once
|
||||||
if (src !== dst) fs.copySync(src, dst)
|
if (src !== dst) fs.copySync(src, dst)
|
||||||
@@ -88,3 +85,11 @@ function migrate_0_7_0 (state) {
|
|||||||
delete ts.fileModtimes
|
delete ts.fileModtimes
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function migrate_0_7_2 (saved) {
|
||||||
|
if (!saved.prefs) {
|
||||||
|
saved.prefs = {
|
||||||
|
downloadPath: config.DEFAULT_DOWNLOAD_PATH
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,18 +1,20 @@
|
|||||||
var electron = require('electron')
|
|
||||||
var path = require('path')
|
|
||||||
|
|
||||||
var remote = electron.remote
|
|
||||||
|
|
||||||
var config = require('../../config')
|
|
||||||
var LocationHistory = require('./location-history')
|
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
getInitialState,
|
|
||||||
getDefaultPlayState,
|
getDefaultPlayState,
|
||||||
getDefaultSavedState
|
load,
|
||||||
|
save
|
||||||
}
|
}
|
||||||
|
|
||||||
function getInitialState () {
|
var appConfig = require('application-config')('WebTorrent')
|
||||||
|
var path = require('path')
|
||||||
|
|
||||||
|
var config = require('../../config')
|
||||||
|
var migrations = require('./migrations')
|
||||||
|
|
||||||
|
appConfig.filePath = path.join(config.CONFIG_PATH, 'config.json')
|
||||||
|
|
||||||
|
function getDefaultState () {
|
||||||
|
var LocationHistory = require('./location-history')
|
||||||
|
|
||||||
return {
|
return {
|
||||||
/*
|
/*
|
||||||
* Temporary state disappears once the program exits.
|
* Temporary state disappears once the program exits.
|
||||||
@@ -91,185 +93,58 @@ function getDefaultPlayState () {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* If the saved state file doesn't exist yet, here's what we use instead */
|
/* If the saved state file doesn't exist yet, here's what we use instead */
|
||||||
function getDefaultSavedState () {
|
function setupSavedState (cb) {
|
||||||
return {
|
var fs = require('fs-extra')
|
||||||
version: config.APP_VERSION, /* make sure we can upgrade gracefully later */
|
var parseTorrent = require('parse-torrent')
|
||||||
torrents: [
|
var parallel = require('run-parallel')
|
||||||
{
|
|
||||||
status: 'paused',
|
var saved = {
|
||||||
infoHash: '88594aaacbde40ef3e2510c47374ec0aa396c08e',
|
|
||||||
magnetURI: 'magnet:?xt=urn:btih:88594aaacbde40ef3e2510c47374ec0aa396c08e&dn=bbb_sunflower_1080p_30fps_normal.mp4&tr=udp%3A%2F%2Ftracker.openbittorrent.com%3A80%2Fannounce&tr=udp%3A%2F%2Ftracker.publicbt.com%3A80%2Fannounce&tr=wss%3A%2F%2Ftracker.btorrent.xyz&tr=wss%3A%2F%2Ftracker.fastcast.nz&tr=wss%3A%2F%2Ftracker.openwebtorrent.com&tr=wss%3A%2F%2Ftracker.webtorrent.io&ws=http%3A%2F%2Fdistribution.bbb3d.renderfarming.net%2Fvideo%2Fmp4%2Fbbb_sunflower_1080p_30fps_normal.mp4',
|
|
||||||
displayName: 'Big Buck Bunny',
|
|
||||||
posterURL: 'bigBuckBunny.jpg',
|
|
||||||
torrentPath: 'bigBuckBunny.torrent',
|
|
||||||
files: [
|
|
||||||
{
|
|
||||||
length: 276134947,
|
|
||||||
name: 'bbb_sunflower_1080p_30fps_normal.mp4'
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
status: 'paused',
|
|
||||||
infoHash: '6a9759bffd5c0af65319979fb7832189f4f3c35d',
|
|
||||||
magnetURI: 'magnet:?xt=urn:btih:6a9759bffd5c0af65319979fb7832189f4f3c35d&dn=sintel.mp4&tr=udp%3A%2F%2Fexodus.desync.com%3A6969&tr=udp%3A%2F%2Ftracker.coppersurfer.tk%3A6969&tr=udp%3A%2F%2Ftracker.internetwarriors.net%3A1337&tr=udp%3A%2F%2Ftracker.leechers-paradise.org%3A6969&tr=udp%3A%2F%2Ftracker.openbittorrent.com%3A80&tr=wss%3A%2F%2Ftracker.btorrent.xyz&tr=wss%3A%2F%2Ftracker.fastcast.nz&tr=wss%3A%2F%2Ftracker.openwebtorrent.com&tr=wss%3A%2F%2Ftracker.webtorrent.io&ws=https%3A%2F%2Fwebtorrent.io%2Ftorrents%2Fsintel-1024-surround.mp4',
|
|
||||||
displayName: 'Sintel',
|
|
||||||
posterURL: 'sintel.jpg',
|
|
||||||
torrentPath: 'sintel.torrent',
|
|
||||||
files: [
|
|
||||||
{
|
|
||||||
length: 129241752,
|
|
||||||
name: 'sintel.mp4'
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
status: 'paused',
|
|
||||||
infoHash: '02767050e0be2fd4db9a2ad6c12416ac806ed6ed',
|
|
||||||
magnetURI: 'magnet:?xt=urn:btih:02767050e0be2fd4db9a2ad6c12416ac806ed6ed&dn=tears_of_steel_1080p.webm&tr=wss%3A%2F%2Ftracker.btorrent.xyz&tr=wss%3A%2F%2Ftracker.fastcast.nz&tr=wss%3A%2F%2Ftracker.openwebtorrent.com&tr=wss%3A%2F%2Ftracker.webtorrent.io',
|
|
||||||
displayName: 'Tears of Steel',
|
|
||||||
posterURL: 'tearsOfSteel.jpg',
|
|
||||||
torrentPath: 'tearsOfSteel.torrent',
|
|
||||||
files: [
|
|
||||||
{
|
|
||||||
length: 571346576,
|
|
||||||
name: 'tears_of_steel_1080p.webm'
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
status: 'paused',
|
|
||||||
infoHash: '6a02592d2bbc069628cd5ed8a54f88ee06ac0ba5',
|
|
||||||
magnetURI: 'magnet:?xt=urn:btih:6a02592d2bbc069628cd5ed8a54f88ee06ac0ba5&dn=CosmosLaundromatFirstCycle&tr=http%3A%2F%2Fbt1.archive.org%3A6969%2Fannounce&tr=http%3A%2F%2Fbt2.archive.org%3A6969%2Fannounce&tr=wss%3A%2F%2Ftracker.btorrent.xyz&tr=wss%3A%2F%2Ftracker.fastcast.nz&tr=wss%3A%2F%2Ftracker.openwebtorrent.com&tr=wss%3A%2F%2Ftracker.webtorrent.io&ws=http%3A%2F%2Fia601508.us.archive.org%2F14%2Fitems%2F&ws=http%3A%2F%2Fia801508.us.archive.org%2F14%2Fitems%2F&ws=https%3A%2F%2Farchive.org%2Fdownload%2F',
|
|
||||||
displayName: 'Cosmos Laundromat (Preview)',
|
|
||||||
posterURL: 'cosmosLaundromat.jpg',
|
|
||||||
torrentPath: 'cosmosLaundromat.torrent',
|
|
||||||
files: [
|
|
||||||
{
|
|
||||||
length: 223580,
|
|
||||||
name: 'Cosmos Laundromat - First Cycle (1080p).gif'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
length: 220087570,
|
|
||||||
name: 'Cosmos Laundromat - First Cycle (1080p).mp4'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
length: 56832560,
|
|
||||||
name: 'Cosmos Laundromat - First Cycle (1080p).ogv'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
length: 3949,
|
|
||||||
name: 'CosmosLaundromat-FirstCycle1080p.en.srt'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
length: 3907,
|
|
||||||
name: 'CosmosLaundromat-FirstCycle1080p.es.srt'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
length: 4119,
|
|
||||||
name: 'CosmosLaundromat-FirstCycle1080p.fr.srt'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
length: 3941,
|
|
||||||
name: 'CosmosLaundromat-FirstCycle1080p.it.srt'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
length: 11264,
|
|
||||||
name: 'CosmosLaundromatFirstCycle_meta.sqlite'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
length: 1204,
|
|
||||||
name: 'CosmosLaundromatFirstCycle_meta.xml'
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
status: 'paused',
|
|
||||||
infoHash: '3ba219a8634bf7bae3d848192b2da75ae995589d',
|
|
||||||
magnetURI: 'magnet:?xt=urn:btih:3ba219a8634bf7bae3d848192b2da75ae995589d&dn=The+WIRED+CD+-+Rip.+Sample.+Mash.+Share.&tr=udp%3A%2F%2Fexodus.desync.com%3A6969&tr=udp%3A%2F%2Ftracker.coppersurfer.tk%3A6969&tr=udp%3A%2F%2Ftracker.internetwarriors.net%3A1337&tr=udp%3A%2F%2Ftracker.leechers-paradise.org%3A6969&tr=udp%3A%2F%2Ftracker.openbittorrent.com%3A80&tr=wss%3A%2F%2Ftracker.btorrent.xyz&tr=wss%3A%2F%2Ftracker.fastcast.nz&tr=wss%3A%2F%2Ftracker.openwebtorrent.com&tr=wss%3A%2F%2Ftracker.webtorrent.io&ws=https%3A%2F%2Fwebtorrent.io%2Ftorrents%2F',
|
|
||||||
displayName: 'The WIRED CD - Rip. Sample. Mash. Share.',
|
|
||||||
posterURL: 'wired-cd.jpg',
|
|
||||||
torrentPath: 'wired-cd.torrent',
|
|
||||||
files: [
|
|
||||||
{
|
|
||||||
length: 1964275,
|
|
||||||
name: '01 - Beastie Boys - Now Get Busy.mp3'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
length: 3610523,
|
|
||||||
name: '02 - David Byrne - My Fair Lady.mp3'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
length: 2759377,
|
|
||||||
name: '03 - Zap Mama - Wadidyusay.mp3'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
length: 5816537,
|
|
||||||
name: '04 - My Morning Jacket - One Big Holiday.mp3'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
length: 2106421,
|
|
||||||
name: '05 - Spoon - Revenge!.mp3'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
length: 3347550,
|
|
||||||
name: '06 - Gilberto Gil - Oslodum.mp3'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
length: 2107577,
|
|
||||||
name: '07 - Dan The Automator - Relaxation Spa Treatment.mp3'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
length: 3108130,
|
|
||||||
name: '08 - Thievery Corporation - Dc 3000.mp3'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
length: 3051528,
|
|
||||||
name: '09 - Le Tigre - Fake French.mp3'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
length: 3270259,
|
|
||||||
name: '10 - Paul Westerberg - Looking Up In Heaven.mp3'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
length: 3263528,
|
|
||||||
name: '11 - Chuck D - No Meaning No (feat. Fine Arts Militia).mp3'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
length: 6380952,
|
|
||||||
name: '12 - The Rapture - Sister Saviour (Blackstrobe Remix).mp3'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
length: 6550396,
|
|
||||||
name: '13 - Cornelius - Wataridori 2.mp3'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
length: 3034692,
|
|
||||||
name: '14 - DJ Danger Mouse - What U Sittin\' On (feat. Jemini, Cee Lo And Tha Alkaholiks).mp3'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
length: 3854611,
|
|
||||||
name: '15 - DJ Dolores - Oslodum 2004.mp3'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
length: 1762120,
|
|
||||||
name: '16 - Matmos - Action At A Distance.mp3'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
length: 4071,
|
|
||||||
name: 'README.md'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
length: 78163,
|
|
||||||
name: 'poster.jpg'
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
prefs: {
|
prefs: {
|
||||||
downloadPath: config.IS_PORTABLE
|
downloadPath: config.DEFAULT_DOWNLOAD_PATH
|
||||||
? path.join(config.CONFIG_PATH, 'Downloads')
|
},
|
||||||
: remote.app.getPath('downloads')
|
torrents: config.DEFAULT_TORRENTS.map(createTorrentObject),
|
||||||
|
version: config.APP_VERSION /* make sure we can upgrade gracefully later */
|
||||||
|
}
|
||||||
|
|
||||||
|
var tasks = []
|
||||||
|
|
||||||
|
config.DEFAULT_TORRENTS.map(function (t, i) {
|
||||||
|
var infoHash = saved.torrents[i].infoHash
|
||||||
|
tasks.push(function (cb) {
|
||||||
|
fs.copy(
|
||||||
|
path.join(config.STATIC_PATH, t.posterFileName),
|
||||||
|
path.join(config.POSTER_PATH, infoHash + path.extname(t.posterFileName)),
|
||||||
|
cb
|
||||||
|
)
|
||||||
|
})
|
||||||
|
tasks.push(function (cb) {
|
||||||
|
fs.copy(
|
||||||
|
path.join(config.STATIC_PATH, t.torrentFileName),
|
||||||
|
path.join(config.TORRENT_PATH, infoHash + '.torrent'),
|
||||||
|
cb
|
||||||
|
)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
parallel(tasks, function (err) {
|
||||||
|
if (err) return cb(err)
|
||||||
|
cb(null, saved)
|
||||||
|
})
|
||||||
|
|
||||||
|
function createTorrentObject (t) {
|
||||||
|
var torrent = fs.readFileSync(path.join(config.STATIC_PATH, t.torrentFileName))
|
||||||
|
var parsedTorrent = parseTorrent(torrent)
|
||||||
|
|
||||||
|
return {
|
||||||
|
status: 'paused',
|
||||||
|
infoHash: parsedTorrent.infoHash,
|
||||||
|
name: t.name,
|
||||||
|
displayName: t.name,
|
||||||
|
posterFileName: parsedTorrent.infoHash + path.extname(t.posterFileName),
|
||||||
|
torrentFileName: parsedTorrent.infoHash + '.torrent',
|
||||||
|
magnetURI: parseTorrent.toMagnetURI(parsedTorrent),
|
||||||
|
files: parsedTorrent.files,
|
||||||
|
selections: parsedTorrent.files.map((x) => true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -284,3 +159,57 @@ function getPlayingFileSummary () {
|
|||||||
if (!torrentSummary) return null
|
if (!torrentSummary) return null
|
||||||
return torrentSummary.files[this.playing.fileIndex]
|
return torrentSummary.files[this.playing.fileIndex]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function load (cb) {
|
||||||
|
var state = getDefaultState()
|
||||||
|
|
||||||
|
appConfig.read(function (err, saved) {
|
||||||
|
if (err || !saved.version) {
|
||||||
|
console.log('Missing config file: Creating new one')
|
||||||
|
setupSavedState(onSaved)
|
||||||
|
} else {
|
||||||
|
onSaved(null, saved)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
function onSaved (err, saved) {
|
||||||
|
if (err) return cb(err)
|
||||||
|
state.saved = saved
|
||||||
|
migrations.run(state)
|
||||||
|
cb(null, state)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write state.saved to the JSON state file
|
||||||
|
function save (state, cb) {
|
||||||
|
console.log('Saving state to ' + appConfig.filePath)
|
||||||
|
|
||||||
|
var electron = require('electron')
|
||||||
|
|
||||||
|
// Clean up, so that we're not saving any pending state
|
||||||
|
var copy = Object.assign({}, state.saved)
|
||||||
|
// Remove torrents pending addition to the list, where we haven't finished
|
||||||
|
// reading the torrent file or file(s) to seed & don't have an infohash
|
||||||
|
copy.torrents = copy.torrents
|
||||||
|
.filter((x) => x.infoHash)
|
||||||
|
.map(function (x) {
|
||||||
|
var torrent = {}
|
||||||
|
for (var key in x) {
|
||||||
|
if (key === 'progress' || key === 'torrentKey') {
|
||||||
|
continue // Don't save progress info or key for the webtorrent process
|
||||||
|
}
|
||||||
|
if (key === 'playStatus') {
|
||||||
|
continue // Don't save whether a torrent is playing / pending
|
||||||
|
}
|
||||||
|
torrent[key] = x[key]
|
||||||
|
}
|
||||||
|
return torrent
|
||||||
|
})
|
||||||
|
|
||||||
|
appConfig.write(copy, function (err) {
|
||||||
|
if (err) console.error(err)
|
||||||
|
|
||||||
|
// TODO: this doesn't belong here
|
||||||
|
electron.ipcRenderer.send('savedState')
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|||||||
@@ -10,14 +10,14 @@ var config = require('../../config')
|
|||||||
// Returns an absolute path to the torrent file, or null if unavailable
|
// Returns an absolute path to the torrent file, or null if unavailable
|
||||||
function getTorrentPath (torrentSummary) {
|
function getTorrentPath (torrentSummary) {
|
||||||
if (!torrentSummary || !torrentSummary.torrentFileName) return null
|
if (!torrentSummary || !torrentSummary.torrentFileName) return null
|
||||||
return path.join(config.CONFIG_TORRENT_PATH, torrentSummary.torrentFileName)
|
return path.join(config.TORRENT_PATH, torrentSummary.torrentFileName)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Expects a torrentSummary
|
// Expects a torrentSummary
|
||||||
// Returns an absolute path to the poster image, or null if unavailable
|
// Returns an absolute path to the poster image, or null if unavailable
|
||||||
function getPosterPath (torrentSummary) {
|
function getPosterPath (torrentSummary) {
|
||||||
if (!torrentSummary || !torrentSummary.posterFileName) return null
|
if (!torrentSummary || !torrentSummary.posterFileName) return null
|
||||||
var posterPath = path.join(config.CONFIG_POSTER_PATH, torrentSummary.posterFileName)
|
var posterPath = path.join(config.POSTER_PATH, torrentSummary.posterFileName)
|
||||||
// Work around a Chrome bug (reproduced in vanilla Chrome, not just Electron):
|
// Work around a Chrome bug (reproduced in vanilla Chrome, not just Electron):
|
||||||
// Backslashes in URLS in CSS cause bizarre string encoding issues
|
// Backslashes in URLS in CSS cause bizarre string encoding issues
|
||||||
return posterPath.replace(/\\/g, '/')
|
return posterPath.replace(/\\/g, '/')
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ console.time('init')
|
|||||||
var crashReporter = require('../crash-reporter')
|
var crashReporter = require('../crash-reporter')
|
||||||
crashReporter.init()
|
crashReporter.init()
|
||||||
|
|
||||||
var appConfig = require('application-config')('WebTorrent')
|
|
||||||
var dragDrop = require('drag-drop')
|
var dragDrop = require('drag-drop')
|
||||||
var electron = require('electron')
|
var electron = require('electron')
|
||||||
var fs = require('fs-extra')
|
var fs = require('fs-extra')
|
||||||
@@ -18,46 +17,30 @@ var patch = require('virtual-dom/patch')
|
|||||||
var App = require('./views/app')
|
var App = require('./views/app')
|
||||||
var config = require('../config')
|
var config = require('../config')
|
||||||
var errors = require('./lib/errors')
|
var errors = require('./lib/errors')
|
||||||
var migrations = require('./lib/migrations')
|
|
||||||
var sound = require('./lib/sound')
|
var sound = require('./lib/sound')
|
||||||
var State = require('./lib/state')
|
var State = require('./lib/state')
|
||||||
var TorrentPlayer = require('./lib/torrent-player')
|
var TorrentPlayer = require('./lib/torrent-player')
|
||||||
var TorrentSummary = require('./lib/torrent-summary')
|
var TorrentSummary = require('./lib/torrent-summary')
|
||||||
|
|
||||||
var {setDispatch} = require('./lib/dispatcher')
|
var {setDispatch} = require('./lib/dispatcher')
|
||||||
setDispatch(dispatch)
|
|
||||||
|
|
||||||
appConfig.filePath = path.join(config.CONFIG_PATH, 'config.json')
|
|
||||||
|
|
||||||
// This dependency is the slowest-loading, so we lazy load it
|
|
||||||
var Cast = null
|
|
||||||
|
|
||||||
var vdomLoop
|
|
||||||
|
|
||||||
var state = State.getInitialState()
|
|
||||||
state.location.go({ url: 'home' }) // Add first page to location history
|
|
||||||
|
|
||||||
// Electron apps have two processes: a main process (node) runs first and starts
|
// Electron apps have two processes: a main process (node) runs first and starts
|
||||||
// a renderer process (essentially a Chrome window). We're in the renderer process,
|
// a renderer process (essentially a Chrome window). We're in the renderer process,
|
||||||
// and this IPC channel receives from and sends messages to the main process
|
// and this IPC channel receives from and sends messages to the main process
|
||||||
var ipcRenderer = electron.ipcRenderer
|
var ipcRenderer = electron.ipcRenderer
|
||||||
|
|
||||||
// All state lives in state.js. `state.saved` is read from and written to a file.
|
var state, vdomLoop
|
||||||
// All other state is ephemeral. First we load state.saved then initialize the app.
|
|
||||||
loadState(init)
|
|
||||||
|
|
||||||
function loadState (cb) {
|
// This dependency is the slowest-loading, so we lazy load it
|
||||||
appConfig.read(function (err, data) {
|
var Cast = null
|
||||||
if (err) console.error(err)
|
|
||||||
|
|
||||||
// populate defaults if they're not there
|
init()
|
||||||
state.saved = Object.assign({}, State.getDefaultSavedState(), data)
|
|
||||||
state.saved.torrents.forEach(function (torrentSummary) {
|
|
||||||
if (torrentSummary.displayName) torrentSummary.name = torrentSummary.displayName
|
|
||||||
})
|
|
||||||
|
|
||||||
if (cb) cb()
|
function init () {
|
||||||
})
|
// All state lives in state.js. `state.saved` is read from and written to a file.
|
||||||
|
// All other state is ephemeral. First we load state.saved then initialize the app.
|
||||||
|
State.load(onState)
|
||||||
|
|
||||||
|
setDispatch(dispatch)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -65,9 +48,12 @@ function loadState (cb) {
|
|||||||
* Connects to the torrent networks, sets up the UI and OS integrations like
|
* Connects to the torrent networks, sets up the UI and OS integrations like
|
||||||
* the dock icon and drag+drop.
|
* the dock icon and drag+drop.
|
||||||
*/
|
*/
|
||||||
function init () {
|
function onState (err, _state) {
|
||||||
// Clean up the freshly-loaded config file, which may be from an older version
|
if (err) return onError(err)
|
||||||
migrations.run(state)
|
state = _state
|
||||||
|
|
||||||
|
// Add first page to location history
|
||||||
|
state.location.go({ url: 'home' })
|
||||||
|
|
||||||
// Restart everything we were torrenting last time the app ran
|
// Restart everything we were torrenting last time the app ran
|
||||||
resumeTorrents()
|
resumeTorrents()
|
||||||
@@ -328,7 +314,7 @@ function dispatch (action, ...args) {
|
|||||||
saveStateThrottled()
|
saveStateThrottled()
|
||||||
}
|
}
|
||||||
if (action === 'saveState') {
|
if (action === 'saveState') {
|
||||||
saveState()
|
State.save(state)
|
||||||
}
|
}
|
||||||
if (action === 'setTitle') {
|
if (action === 'setTitle') {
|
||||||
state.window.title = args[0] /* title */
|
state.window.title = args[0] /* title */
|
||||||
@@ -512,7 +498,8 @@ function updatePreferences (property, value) {
|
|||||||
// All unsaved prefs take effect atomically, and are saved to config.json
|
// All unsaved prefs take effect atomically, and are saved to config.json
|
||||||
function savePreferences () {
|
function savePreferences () {
|
||||||
state.saved.prefs = Object.assign(state.saved.prefs || {}, state.unsaved.prefs)
|
state.saved.prefs = Object.assign(state.saved.prefs || {}, state.unsaved.prefs)
|
||||||
saveState()
|
State.save(state)
|
||||||
|
update()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Don't write state.saved to file more than once a second
|
// Don't write state.saved to file more than once a second
|
||||||
@@ -520,43 +507,11 @@ function saveStateThrottled () {
|
|||||||
if (state.saveStateTimeout) return
|
if (state.saveStateTimeout) return
|
||||||
state.saveStateTimeout = setTimeout(function () {
|
state.saveStateTimeout = setTimeout(function () {
|
||||||
delete state.saveStateTimeout
|
delete state.saveStateTimeout
|
||||||
saveState()
|
State.save(state)
|
||||||
|
update()
|
||||||
}, 1000)
|
}, 1000)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write state.saved to the JSON state file
|
|
||||||
function saveState () {
|
|
||||||
console.log('saving state to ' + appConfig.filePath)
|
|
||||||
|
|
||||||
// Clean up, so that we're not saving any pending state
|
|
||||||
var copy = Object.assign({}, state.saved)
|
|
||||||
// Remove torrents pending addition to the list, where we haven't finished
|
|
||||||
// reading the torrent file or file(s) to seed & don't have an infohash
|
|
||||||
copy.torrents = copy.torrents
|
|
||||||
.filter((x) => x.infoHash)
|
|
||||||
.map(function (x) {
|
|
||||||
var torrent = {}
|
|
||||||
for (var key in x) {
|
|
||||||
if (key === 'progress' || key === 'torrentKey') {
|
|
||||||
continue // Don't save progress info or key for the webtorrent process
|
|
||||||
}
|
|
||||||
if (key === 'playStatus') {
|
|
||||||
continue // Don't save whether a torrent is playing / pending
|
|
||||||
}
|
|
||||||
torrent[key] = x[key]
|
|
||||||
}
|
|
||||||
return torrent
|
|
||||||
})
|
|
||||||
|
|
||||||
appConfig.write(copy, function (err) {
|
|
||||||
if (err) console.error(err)
|
|
||||||
ipcRenderer.send('savedState')
|
|
||||||
})
|
|
||||||
|
|
||||||
// Update right away, don't wait for the state to save
|
|
||||||
update()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Called when the user adds files (.torrent, files to seed, subtitles) to the app
|
// Called when the user adds files (.torrent, files to seed, subtitles) to the app
|
||||||
// via any method (drag-drop, drag to app icon, command line)
|
// via any method (drag-drop, drag to app icon, command line)
|
||||||
function onOpen (files) {
|
function onOpen (files) {
|
||||||
|
|||||||
@@ -218,7 +218,8 @@ function TorrentList (state) {
|
|||||||
// Show a single torrentSummary file in the details view for a single torrent
|
// Show a single torrentSummary file in the details view for a single torrent
|
||||||
function renderFileRow (torrentSummary, file, index) {
|
function renderFileRow (torrentSummary, file, index) {
|
||||||
// First, find out how much of the file we've downloaded
|
// First, find out how much of the file we've downloaded
|
||||||
var isSelected = torrentSummary.selections[index] // Are we even torrenting it?
|
// Are we even torrenting it?
|
||||||
|
var isSelected = torrentSummary.selections && torrentSummary.selections[index]
|
||||||
var isDone = false // Are we finished torrenting it?
|
var isDone = false // Are we finished torrenting it?
|
||||||
var progress = ''
|
var progress = ''
|
||||||
if (torrentSummary.progress && torrentSummary.progress.files) {
|
if (torrentSummary.progress && torrentSummary.progress.files) {
|
||||||
|
|||||||
@@ -173,7 +173,7 @@ function saveTorrentFile (torrentKey) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Otherwise, save the .torrent file, under the app config folder
|
// Otherwise, save the .torrent file, under the app config folder
|
||||||
fs.mkdir(config.CONFIG_TORRENT_PATH, function (_) {
|
fs.mkdir(config.TORRENT_PATH, function (_) {
|
||||||
fs.writeFile(torrentPath, torrent.torrentFile, function (err) {
|
fs.writeFile(torrentPath, torrent.torrentFile, function (err) {
|
||||||
if (err) return console.log('error saving torrent file %s: %o', torrentPath, err)
|
if (err) return console.log('error saving torrent file %s: %o', torrentPath, err)
|
||||||
console.log('saved torrent file %s', torrentPath)
|
console.log('saved torrent file %s', torrentPath)
|
||||||
@@ -186,7 +186,7 @@ function saveTorrentFile (torrentKey) {
|
|||||||
// Checks whether we've already resolved a given infohash to a torrent file
|
// Checks whether we've already resolved a given infohash to a torrent file
|
||||||
// Calls back with (torrentPath, exists). Logs, does not call back on error
|
// Calls back with (torrentPath, exists). Logs, does not call back on error
|
||||||
function checkIfTorrentFileExists (infoHash, cb) {
|
function checkIfTorrentFileExists (infoHash, cb) {
|
||||||
var torrentPath = path.join(config.CONFIG_TORRENT_PATH, infoHash + '.torrent')
|
var torrentPath = path.join(config.TORRENT_PATH, infoHash + '.torrent')
|
||||||
fs.exists(torrentPath, function (exists) {
|
fs.exists(torrentPath, function (exists) {
|
||||||
cb(torrentPath, exists)
|
cb(torrentPath, exists)
|
||||||
})
|
})
|
||||||
@@ -199,10 +199,10 @@ function generateTorrentPoster (torrentKey) {
|
|||||||
torrentPoster(torrent, function (err, buf, extension) {
|
torrentPoster(torrent, function (err, buf, extension) {
|
||||||
if (err) return console.log('error generating poster: %o', err)
|
if (err) return console.log('error generating poster: %o', err)
|
||||||
// save it for next time
|
// save it for next time
|
||||||
fs.mkdirp(config.CONFIG_POSTER_PATH, function (err) {
|
fs.mkdirp(config.POSTER_PATH, function (err) {
|
||||||
if (err) return console.log('error creating poster dir: %o', err)
|
if (err) return console.log('error creating poster dir: %o', err)
|
||||||
var posterFileName = torrent.infoHash + extension
|
var posterFileName = torrent.infoHash + extension
|
||||||
var posterFilePath = path.join(config.CONFIG_POSTER_PATH, posterFileName)
|
var posterFilePath = path.join(config.POSTER_PATH, posterFileName)
|
||||||
fs.writeFile(posterFilePath, buf, function (err) {
|
fs.writeFile(posterFilePath, buf, function (err) {
|
||||||
if (err) return console.log('error saving poster: %o', err)
|
if (err) return console.log('error saving poster: %o', err)
|
||||||
// show the poster
|
// show the poster
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 76 KiB After Width: | Height: | Size: 76 KiB |
Reference in New Issue
Block a user