From a70c4d1bf217f4a651757ddccbc4dbf9d13de093 Mon Sep 17 00:00:00 2001 From: Alberto Miranda Date: Wed, 22 Mar 2017 09:42:17 -0300 Subject: [PATCH 1/9] Working on watch-folder MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Added chokidar to watch for folder changes; added folder-watcher; passing state to delayedInit on main; added default values for new preferences; added “Auto add torrents” preference with its checkbox and path selector; TODO: start/stop watching on preference change, start watching on init, add dialog when trying to enable preference without a torrents folder. --- package.json | 1 + src/main/folder-watcher.js | 54 ++++++++++++++++++++++++++ src/main/index.js | 12 ++++-- src/renderer/lib/state.js | 4 +- src/renderer/pages/preferences-page.js | 54 ++++++++++++++++++++++++++ 5 files changed, 121 insertions(+), 4 deletions(-) create mode 100644 src/main/folder-watcher.js diff --git a/package.json b/package.json index 90be982642..fc30abe0ff 100644 --- a/package.json +++ b/package.json @@ -17,6 +17,7 @@ "auto-launch": "^4.0.1", "bitfield": "^1.0.2", "capture-frame": "^1.0.0", + "chokidar": "^1.6.1", "chromecasts": "^1.8.0", "cp-file": "^4.0.1", "create-torrent": "^3.24.5", diff --git a/src/main/folder-watcher.js b/src/main/folder-watcher.js new file mode 100644 index 0000000000..9e0a4ad796 --- /dev/null +++ b/src/main/folder-watcher.js @@ -0,0 +1,54 @@ +const chokidar = require('chokidar') +const log = require('./log') + +class FolderWatcher { + constructor ({window, state}) { + this.window = window + this.state = state + this.torrentsFolderPath + } + + init () { + const torrentsFolderPath = this.state.saved.prefs.torrentsFolderPath + this.torrentsFolderPath = torrentsFolderPath + if (!torrentsFolderPath) return + + const glob = `${torrentsFolderPath}/**/*.torrent` + log('Folder Watcher: watching: ', glob) + + const options = {ignoreInitial: true} + this.watcher = chokidar.watch(glob, options) + this.watcher + .on('add', (path) => { + log('-- torrent added: ', path) + this.window.dispatch('addTorrent', path) + }) + } + + start (torrentsFolderPath) { + // Stop watching previous folder before + // start watching a new one. + if (this.torrentsFolderPath) { + this.stop() + } + + const glob = `${torrentsFolderPath}/**/*.torrent` + log('Folder Watcher: watching: ', glob) + + const options = {ignoreInitial: true} + this.watcher = chokidar.watch(glob, options) + this.watcher + .on('add', (path) => { + log('-- torrent added: ', path) + this.window.dispatch('addTorrent', path) + }) + } + + stop () { + if (!this.watcher) return + this.watcher.close() + } +} + + +module.exports = FolderWatcher diff --git a/src/main/index.js b/src/main/index.js index 3828697738..c99a4c31ae 100644 --- a/src/main/index.js +++ b/src/main/index.js @@ -72,13 +72,16 @@ function init () { if (err) throw err isReady = true + const state = results.state - windows.main.init(results.state, {hidden: hidden}) + windows.main.init(state, {hidden: hidden}) windows.webtorrent.init() menu.init() // To keep app startup fast, some code is delayed. - setTimeout(delayedInit, config.DELAYED_INIT) + setTimeout(() => { + delayedInit(state) + }, config.DELAYED_INIT) // Report uncaught exceptions process.on('uncaughtException', (err) => { @@ -121,16 +124,19 @@ function init () { }) } -function delayedInit () { +function delayedInit (state) { if (app.isQuitting) return const announcement = require('./announcement') const dock = require('./dock') const updater = require('./updater') + const FolderWatcher = require('./folder-watcher') + const folderWatcher = new FolderWatcher({window: windows.main, state}) announcement.init() dock.init() updater.init() + folderWatcher.init() if (process.platform === 'win32') { const userTasks = require('./user-tasks') diff --git a/src/renderer/lib/state.js b/src/renderer/lib/state.js index 6a909d9629..68c85bb00d 100644 --- a/src/renderer/lib/state.js +++ b/src/renderer/lib/state.js @@ -121,7 +121,9 @@ function setupStateSaved (cb) { isFileHandler: false, openExternalPlayer: false, externalPlayerPath: null, - startup: false + startup: false, + autoAddTorrents: false, + torrentsFolderPath: '' }, torrents: config.DEFAULT_TORRENTS.map(createTorrentObject), torrentsToResume: [], diff --git a/src/renderer/pages/preferences-page.js b/src/renderer/pages/preferences-page.js index bf7291413c..f5c4b8d16c 100644 --- a/src/renderer/pages/preferences-page.js +++ b/src/renderer/pages/preferences-page.js @@ -108,6 +108,56 @@ class PreferencesPage extends React.Component { dispatch('updatePreferences', 'externalPlayerPath', filePath) } + autoAddTorrentsCheckbox () { + return ( + + {this.handleAutoAddTorrentsChange(e, value)}} + /> + + ) + } + + handleAutoAddTorrentsChange (e, isChecked) { + const torrentsFolderPath = this.props.state.unsaved.prefs.torrentsFolderPath + if (isChecked && !torrentsFolderPath) { + alert('Select a torrents folder first.') + e.preventDefault() + return + } + + dispatch('updatePreferences', 'autoAddTorrents', isChecked) + } + + torrentsFolderPathSelector () { + const torrentsFolderPath = this.props.state.unsaved.prefs.torrentsFolderPath + + const value = torrentsFolderPath || 'Path to be watched.' + const description = 'Torrent files saved to this folder will be automatically added to the list.' + + return ( + +

{description}

+ +
+ ) + } + + handletorrentsFolderPathChange (filePath) { + dispatch('updatePreferences', 'torrentsFolderPath', filePath) + } + setDefaultAppButton () { const isFileHandler = this.props.state.unsaved.prefs.isFileHandler if (isFileHandler) { @@ -174,6 +224,10 @@ class PreferencesPage extends React.Component { {this.setDefaultAppButton()} + + {this.autoAddTorrentsCheckbox()} + {this.torrentsFolderPathSelector()} + {this.setStartupSection()} ) From a6c53d06d2923ebe480f6ef52304e6ea3053cd89 Mon Sep 17 00:00:00 2001 From: Alberto Miranda Date: Wed, 22 Mar 2017 22:27:03 -0300 Subject: [PATCH 2/9] fixed styling issues --- src/main/folder-watcher.js | 1 - src/renderer/pages/preferences-page.js | 6 +++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/main/folder-watcher.js b/src/main/folder-watcher.js index 9e0a4ad796..7bde2b7ceb 100644 --- a/src/main/folder-watcher.js +++ b/src/main/folder-watcher.js @@ -50,5 +50,4 @@ class FolderWatcher { } } - module.exports = FolderWatcher diff --git a/src/renderer/pages/preferences-page.js b/src/renderer/pages/preferences-page.js index f5c4b8d16c..c6553f91db 100644 --- a/src/renderer/pages/preferences-page.js +++ b/src/renderer/pages/preferences-page.js @@ -115,7 +115,7 @@ class PreferencesPage extends React.Component { className='control' checked={this.props.state.unsaved.prefs.autoAddTorrents} label={'Enable'} - onCheck={(e, value) => {this.handleAutoAddTorrentsChange(e, value)}} + onCheck={(e, value) => { this.handleAutoAddTorrentsChange(e, value) }} /> ) @@ -124,7 +124,7 @@ class PreferencesPage extends React.Component { handleAutoAddTorrentsChange (e, isChecked) { const torrentsFolderPath = this.props.state.unsaved.prefs.torrentsFolderPath if (isChecked && !torrentsFolderPath) { - alert('Select a torrents folder first.') + alert('Select a torrents folder first.') // eslint-disable-line e.preventDefault() return } @@ -136,7 +136,7 @@ class PreferencesPage extends React.Component { const torrentsFolderPath = this.props.state.unsaved.prefs.torrentsFolderPath const value = torrentsFolderPath || 'Path to be watched.' - const description = 'Torrent files saved to this folder will be automatically added to the list.' + const description = 'Torrent files saved to this folder will be automatically added.' return ( From 7f817241edbba286ad9c9313bfcee30d9f050e26 Mon Sep 17 00:00:00 2001 From: Alberto Miranda Date: Wed, 22 Mar 2017 23:21:07 -0300 Subject: [PATCH 3/9] added start / stop events; starting / stopping folder watcher. --- src/main/folder-watcher.js | 35 +++++++++++--------------- src/main/index.js | 6 ++++- src/main/ipc.js | 21 +++++++++++++++- src/renderer/main.js | 6 +++++ src/renderer/pages/preferences-page.js | 7 ++++++ 5 files changed, 53 insertions(+), 22 deletions(-) diff --git a/src/main/folder-watcher.js b/src/main/folder-watcher.js index 7bde2b7ceb..7692ec8bf1 100644 --- a/src/main/folder-watcher.js +++ b/src/main/folder-watcher.js @@ -6,31 +6,22 @@ class FolderWatcher { this.window = window this.state = state this.torrentsFolderPath + this.watching = false } - init () { - const torrentsFolderPath = this.state.saved.prefs.torrentsFolderPath - this.torrentsFolderPath = torrentsFolderPath - if (!torrentsFolderPath) return - - const glob = `${torrentsFolderPath}/**/*.torrent` - log('Folder Watcher: watching: ', glob) - - const options = {ignoreInitial: true} - this.watcher = chokidar.watch(glob, options) - this.watcher - .on('add', (path) => { - log('-- torrent added: ', path) - this.window.dispatch('addTorrent', path) - }) + isEnabled () { + return this.state.saved.prefs.autoAddTorrents } - start (torrentsFolderPath) { + start () { + log('--- FOLDER WATCHER --> START') // Stop watching previous folder before // start watching a new one. - if (this.torrentsFolderPath) { - this.stop() - } + if (this.watching) this.stop() + + const torrentsFolderPath = this.state.saved.prefs.torrentsFolderPath + this.torrentsFolderPath = torrentsFolderPath + if (!torrentsFolderPath) return const glob = `${torrentsFolderPath}/**/*.torrent` log('Folder Watcher: watching: ', glob) @@ -42,11 +33,15 @@ class FolderWatcher { log('-- torrent added: ', path) this.window.dispatch('addTorrent', path) }) + + this.watching = true } stop () { - if (!this.watcher) return + log('--- FOLDER WATCHER --> STOP') + if (!this.watching) return this.watcher.close() + this.watching = false } } diff --git a/src/main/index.js b/src/main/index.js index c99a4c31ae..ea38a84227 100644 --- a/src/main/index.js +++ b/src/main/index.js @@ -136,7 +136,11 @@ function delayedInit (state) { announcement.init() dock.init() updater.init() - folderWatcher.init() + + ipc.setModule('folderWatcher', folderWatcher) + if (folderWatcher.isEnabled()) { + folderWatcher.start() + } if (process.platform === 'win32') { const userTasks = require('./user-tasks') diff --git a/src/main/ipc.js b/src/main/ipc.js index e61106264e..432a480f63 100644 --- a/src/main/ipc.js +++ b/src/main/ipc.js @@ -1,5 +1,6 @@ module.exports = { - init + init, + setModule } const electron = require('electron') @@ -13,6 +14,14 @@ const windows = require('./windows') // Messages from the main process, to be sent once the WebTorrent process starts const messageQueueMainToWebTorrent = [] +// Will hold modules injected from the app that will be used on fired +// IPC events. +const modules = {} + +function setModule (name, module) { + modules[name] = module +} + function init () { const ipc = electron.ipcMain @@ -106,6 +115,16 @@ function init () { thumbar.onPlayerPause() }) + ipc.on('startFolderWatcher', function () { + log('--- Torrent Watcher started') + modules['folderWatcher'].start() + }) + + ipc.on('stopFolderWatcher', function () { + log('--- Torrent Watcher stop') + modules['folderWatcher'].stop() + }) + /** * Shell */ diff --git a/src/renderer/main.js b/src/renderer/main.js index 7acb24f59d..1fc431dff3 100644 --- a/src/renderer/main.js +++ b/src/renderer/main.js @@ -111,6 +111,10 @@ function onState (err, _state) { update: createGetter(() => { const UpdateController = require('./controllers/update-controller') return new UpdateController(state) + }), + folderWatcher: createGetter(() => { + const FolderWatcherController = require('./controllers/folder-watcher-controller') + return new FolderWatcherController() }) } @@ -296,6 +300,8 @@ const dispatchHandlers = { 'preferences': () => controllers.prefs().show(), 'updatePreferences': (key, value) => controllers.prefs().update(key, value), 'checkDownloadPath': checkDownloadPath, + 'startFolderWatcher': () => controllers.folderWatcher().start(), + 'stopFolderWatcher': () => controllers.folderWatcher().stop(), // Update (check for new versions on Linux, where there's no auto updater) 'updateAvailable': (version) => controllers.update().updateAvailable(version), diff --git a/src/renderer/pages/preferences-page.js b/src/renderer/pages/preferences-page.js index c6553f91db..05c2ecfe19 100644 --- a/src/renderer/pages/preferences-page.js +++ b/src/renderer/pages/preferences-page.js @@ -130,6 +130,13 @@ class PreferencesPage extends React.Component { } dispatch('updatePreferences', 'autoAddTorrents', isChecked) + + if (isChecked) { + dispatch('startFolderWatcher', null) + return + } + + dispatch('stopFolderWatcher', null) } torrentsFolderPathSelector () { From 4a8ab6e1f6dfb5e84c7e6ed2bbe3285cc40f25fd Mon Sep 17 00:00:00 2001 From: Alberto Miranda Date: Thu, 23 Mar 2017 07:00:45 -0300 Subject: [PATCH 4/9] fixed styling issue --- src/main/folder-watcher.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/folder-watcher.js b/src/main/folder-watcher.js index 7692ec8bf1..d5e81f226b 100644 --- a/src/main/folder-watcher.js +++ b/src/main/folder-watcher.js @@ -5,7 +5,7 @@ class FolderWatcher { constructor ({window, state}) { this.window = window this.state = state - this.torrentsFolderPath + this.torrentsFolderPath = null this.watching = false } From 996a81ddaa65b6933fed30b163a79eefa69987a7 Mon Sep 17 00:00:00 2001 From: Alberto Miranda Date: Thu, 23 Mar 2017 07:14:27 -0300 Subject: [PATCH 5/9] added folder-watcher-controller --- .../controllers/folder-watcher-controller.js | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 src/renderer/controllers/folder-watcher-controller.js diff --git a/src/renderer/controllers/folder-watcher-controller.js b/src/renderer/controllers/folder-watcher-controller.js new file mode 100644 index 0000000000..1454dba117 --- /dev/null +++ b/src/renderer/controllers/folder-watcher-controller.js @@ -0,0 +1,13 @@ +const {ipcRenderer} = require('electron') + +module.exports = class FolderWatcherController { + start () { + console.log('-- IPC: start folder watcher') + ipcRenderer.send('startFolderWatcher') + } + + stop () { + console.log('-- IPC: stop folder watcher') + ipcRenderer.send('stopFolderWatcher') + } +} From 2ad3f6d6e2d73a1fcc09bc67fd97e6a2c8712765 Mon Sep 17 00:00:00 2001 From: Alberto Miranda Date: Fri, 24 Mar 2017 12:54:28 -0300 Subject: [PATCH 6/9] Removed extra logging. --- src/main/folder-watcher.js | 6 +++--- src/main/ipc.js | 18 +++++++++++++++--- 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/src/main/folder-watcher.js b/src/main/folder-watcher.js index d5e81f226b..ccf867a3c1 100644 --- a/src/main/folder-watcher.js +++ b/src/main/folder-watcher.js @@ -1,3 +1,4 @@ +const ipc = require('electron').ipcMain const chokidar = require('chokidar') const log = require('./log') @@ -14,7 +15,6 @@ class FolderWatcher { } start () { - log('--- FOLDER WATCHER --> START') // Stop watching previous folder before // start watching a new one. if (this.watching) this.stop() @@ -30,7 +30,7 @@ class FolderWatcher { this.watcher = chokidar.watch(glob, options) this.watcher .on('add', (path) => { - log('-- torrent added: ', path) + log('Folder Watcher: added torrent: ', path) this.window.dispatch('addTorrent', path) }) @@ -38,7 +38,7 @@ class FolderWatcher { } stop () { - log('--- FOLDER WATCHER --> STOP') + log('Folder Watcher: stop.') if (!this.watching) return this.watcher.close() this.watching = false diff --git a/src/main/ipc.js b/src/main/ipc.js index 432a480f63..4c0a3d4252 100644 --- a/src/main/ipc.js +++ b/src/main/ipc.js @@ -67,7 +67,7 @@ function init () { }) /** - * Events + * Player Events */ ipc.on('onPlayerOpen', function () { @@ -115,13 +115,25 @@ function init () { thumbar.onPlayerPause() }) + /** + * Folder Watcher Events + */ + ipc.on('startFolderWatcher', function () { - log('--- Torrent Watcher started') + if (!modules['folderWatcher']) { + log('IPC ERR: folderWatcher module is not defined.') + return + } + modules['folderWatcher'].start() }) ipc.on('stopFolderWatcher', function () { - log('--- Torrent Watcher stop') + if (!modules['folderWatcher']) { + log('IPC ERR: folderWatcher module is not defined.') + return + } + modules['folderWatcher'].stop() }) From 23eef1a0585e2787d214d8592dd4dc6d50eec1b9 Mon Sep 17 00:00:00 2001 From: Alberto Miranda Date: Fri, 24 Mar 2017 12:55:10 -0300 Subject: [PATCH 7/9] Removed unused module from folderWatcher. --- src/main/folder-watcher.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/folder-watcher.js b/src/main/folder-watcher.js index ccf867a3c1..b8421d0a50 100644 --- a/src/main/folder-watcher.js +++ b/src/main/folder-watcher.js @@ -1,4 +1,3 @@ -const ipc = require('electron').ipcMain const chokidar = require('chokidar') const log = require('./log') From 6e67cae49407884d8f57ccc370e370a005b44355 Mon Sep 17 00:00:00 2001 From: Alberto Miranda Date: Sun, 26 Mar 2017 11:04:05 -0300 Subject: [PATCH 8/9] Wait for .torrent files to finish downloading. --- src/main/folder-watcher.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/main/folder-watcher.js b/src/main/folder-watcher.js index b8421d0a50..d628d35b4b 100644 --- a/src/main/folder-watcher.js +++ b/src/main/folder-watcher.js @@ -25,7 +25,10 @@ class FolderWatcher { const glob = `${torrentsFolderPath}/**/*.torrent` log('Folder Watcher: watching: ', glob) - const options = {ignoreInitial: true} + const options = { + ignoreInitial: true, + awaitWriteFinish: true + } this.watcher = chokidar.watch(glob, options) this.watcher .on('add', (path) => { From b02d6f3cdba34fc1fa5969ed9f0e02cf1302c80f Mon Sep 17 00:00:00 2001 From: Alberto Miranda Date: Sun, 2 Apr 2017 19:37:13 -0300 Subject: [PATCH 9/9] Preferences update MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Renamed “Downloads” section to “Folders”; watch folder preference moved under “Folders”; updated texts for watch folder preference. --- src/renderer/pages/preferences-page.js | 20 +++++++------------- 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/src/renderer/pages/preferences-page.js b/src/renderer/pages/preferences-page.js index 05c2ecfe19..76097109c7 100644 --- a/src/renderer/pages/preferences-page.js +++ b/src/renderer/pages/preferences-page.js @@ -114,7 +114,7 @@ class PreferencesPage extends React.Component { { this.handleAutoAddTorrentsChange(e, value) }} /> @@ -142,20 +142,16 @@ class PreferencesPage extends React.Component { torrentsFolderPathSelector () { const torrentsFolderPath = this.props.state.unsaved.prefs.torrentsFolderPath - const value = torrentsFolderPath || 'Path to be watched.' - const description = 'Torrent files saved to this folder will be automatically added.' - return ( -

{description}

) @@ -220,8 +216,10 @@ class PreferencesPage extends React.Component { } return (
- + {this.downloadPathSelector()} + {this.autoAddTorrentsCheckbox()} + {this.torrentsFolderPathSelector()} {this.openExternalPlayerCheckbox()} @@ -231,10 +229,6 @@ class PreferencesPage extends React.Component { {this.setDefaultAppButton()} - - {this.autoAddTorrentsCheckbox()} - {this.torrentsFolderPathSelector()} - {this.setStartupSection()}
)