diff --git a/README.md b/README.md index 7d829eb033..6381be0846 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,7 @@ Want to report a bug, request a feature, contribute to or translate Butter? Chec If you're comfortable getting up and running from a `git clone`, this method is for you. -After you clone the GitHub repository, you will need to build a number of assets using grunt. +After you clone the GitHub repository, you will need to build a number of assets using gulp. The [master](https://github.com/butterproject/butter-desktop) branch which contains the latest release. @@ -41,7 +41,7 @@ Keep track of Butter development and community activity. * Join in discussions on the [Butter Forum](https://www.reddit.com/r/ButterProject) * Connect with us on IRC at `#butterproject` on freenode ([web access](http://webchat.freenode.net/?channels=butterproject)) -##Screenshots +## Screenshots ![Butter](https://cloud.githubusercontent.com/assets/8317250/10714437/b1e1dc8c-7b32-11e5-9c25-d9fbd5b2f3bd.png) ![Debugging Butter](https://cloud.githubusercontent.com/assets/8317250/10714430/add70234-7b32-11e5-9be7-1de539d865ba.png) diff --git a/gulpfile.js b/gulpfile.js index 66768afb97..24056a06b4 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -62,7 +62,7 @@ const parsePlatforms = () => { // returns an array of paths with the node_modules to include in builds const parseReqDeps = () => { return new Promise((resolve, reject) => { - exec('npm ls --production=true --parseable=true', (error, stdout, stderr) => { + exec('npm ls --production=true --parseable=true', {maxBuffer: 1024 * 500}, (error, stdout, stderr) => { if (error || stderr) { reject(error || stderr); } else { diff --git a/package.json b/package.json index afbfc28ba4..c6f62bf218 100644 --- a/package.json +++ b/package.json @@ -35,7 +35,7 @@ }, "chromium-args": "--enable-node-worker", "dependencies": { - "butter-provider": "git+https://github.com/butterproviders/butter-provider", + "butter-provider": "0.6.0", "butter-provider-ccc": "git+https://github.com/butterproviders/butter-provider-ccc", "butter-provider-youtube": "git+https://github.com/butterproviders/butter-provider-youtube", "butter-provider-vodo": "git+https://github.com/butterproviders/butter-provider-vodo", @@ -45,7 +45,7 @@ "async": "2.x.x", "bonjour": "^3.5.0", "chromecasts": "1.9.0", - "defer-request": "0.0.2", + "defer-request": "0.0.3", "dlnacasts": "0.1.0", "i18n": "0.x.x", "iconv-lite": "0.x.x", @@ -67,15 +67,15 @@ "rimraf": "2.x.x", "sanitizer": "0.x.x", "semver": "5.x.x", - "send": "0.14.1", + "send": "0.14.2", "strike-api": "0.2.0", "tar": "2.2.1", "temp": "0.x.x", "webtorrent-health": "1.x.x", - "trakt.tv": "2.x.x", - "trakt.tv-ondeck": "0.x.x", - "trakt.tv-matcher": "1.x.x", - "trakt.tv-images": "1.x.x", + "trakt.tv": "5.0.1", + "trakt.tv-ondeck": "5.0.1", + "trakt.tv-matcher": "5.0.0", + "trakt.tv-images": "5.0.0", "underscore": "1.x.x", "urijs": "1.x.x", "webtorrent": "^0.98.0" diff --git a/src/app/app.js b/src/app/app.js index 1ef2c3bc6c..26d91cde11 100644 --- a/src/app/app.js +++ b/src/app/app.js @@ -100,6 +100,7 @@ App.addInitializer(function (options) { var width = parseInt(localStorage.width ? localStorage.width : Settings.defaultWidth); var height = parseInt(localStorage.height ? localStorage.height : Settings.defaultHeight); + var isMaximized = Boolean(parseInt(localStorage.isMaximized)); var x = parseInt(localStorage.posX ? localStorage.posX : -1); var y = parseInt(localStorage.posY ? localStorage.posY : -1); @@ -128,8 +129,13 @@ App.addInitializer(function (options) { } win.zoomLevel = zoom; - win.resizeTo(width, height); - win.moveTo(x, y); + + if (isMaximized) { + win.maximize(); + } else { + win.resizeTo(width, height); + win.moveTo(x, y); + } }); var initTemplates = function () { @@ -152,7 +158,9 @@ var initApp = function () { var mainWindow = new App.View.MainWindow(); // -m argument to open minimized to tray - if (nw.App.fullArgv.indexOf('-m') === -1) { + var isStartMinimized = nw.App.fullArgv.indexOf('-m') !== -1; + + if (!isStartMinimized) { win.show(); } @@ -213,35 +221,6 @@ var delCache = function () { win.close(true); }; -win.on('resize', function (width, height) { - localStorage.width = Math.round(width); - localStorage.height = Math.round(height); -}); - -win.on('move', function (x, y) { - localStorage.posX = Math.round(x); - localStorage.posY = Math.round(y); -}); - -win.on('enter-fullscreen', function () { - App.vent.trigger('window:focus'); -}); - -// Wipe the tmpFolder when closing the app (this frees up disk space) -win.on('close', function () { - if (App.settings.deleteTmpOnClose) { - deleteFolder(App.settings.tmpLocation); - } - if (fs.existsSync(path.join(data_path, 'logs.txt'))) { - fs.unlinkSync(path.join(data_path, 'logs.txt')); - } - try { - delCache(); - } catch (e) { - win.close(true); - } -}); - String.prototype.capitalize = function () { return this.charAt(0).toUpperCase() + this.slice(1); }; @@ -656,6 +635,60 @@ if (nw.App.fullArgv.indexOf('-f') !== -1) { win.enterFullscreen(); } +// nwjs window events +win.on('focus', function () { //hack to make it somehow work + win.setAlwaysOnTop(true); + win.setAlwaysOnTop(Settings.alwaysOnTop); +}); + +win.on('resize', function (width, height) { + localStorage.width = Math.round(width); + localStorage.height = Math.round(height); +}); + +win.on('move', function (x, y) { + localStorage.posX = Math.round(x); + localStorage.posY = Math.round(y); +}); + +win.on('enter-fullscreen', function () { + win.focus(); +}); + +win.on('minimize', function () { + if (Settings.minimizeToTray) { + minimizeToTray(); + } +}); + +win.on('maximize', function () { + localStorage.isMaximized = 1; + $('.os-max').addClass('os-is-max'); +}); + +win.on('restore', function () { + if (Boolean(parseInt(localStorage.isMaximized))) { + localStorage.isMaximized = 0; + } + + $('.os-max').removeClass('os-is-max'); +}); + +// Wipe the tmpFolder when closing the app (this frees up disk space) +win.on('close', function () { + if (App.settings.deleteTmpOnClose) { + deleteFolder(App.settings.tmpLocation); + } + if (fs.existsSync(path.join(data_path, 'logs.txt'))) { + fs.unlinkSync(path.join(data_path, 'logs.txt')); + } + try { + delCache(); + } catch (e) { + win.close(true); + } +}); + nw.App.on('open', function (cmd) { var file; if (os.platform() === 'win32') { @@ -682,19 +715,6 @@ nw.App.on('open', function (cmd) { } }); -win.on('minimize', function () { - if (Settings.minimizeToTray) { - minimizeToTray(); - } -}); - -// When win.focus() doesn't do it's job right, play dirty. -App.vent.on('window:focus', function () { - win.setAlwaysOnTop(true); - win.focus(); - win.setAlwaysOnTop(Settings.alwaysOnTop); -}); - // On uncaught exceptions, log to console. process.on('uncaughtException', function (err) { try { diff --git a/src/app/images/icons/topbar_sprite_win.png b/src/app/images/icons/topbar_sprite_win.png index cec88dfc9f..dec4891930 100644 Binary files a/src/app/images/icons/topbar_sprite_win.png and b/src/app/images/icons/topbar_sprite_win.png differ diff --git a/src/app/lib/providers/opensubtitles.js b/src/app/lib/providers/opensubtitles.js index 5f596824c3..6d155485ac 100644 --- a/src/app/lib/providers/opensubtitles.js +++ b/src/app/lib/providers/opensubtitles.js @@ -7,7 +7,8 @@ openSRT = new OS({ useragent: Settings.opensubtitles.useragent + ' v' + (Settings.version || 1), username: Settings.opensubtitlesUsername, - password: Settings.opensubtitlesPassword + password: Settings.opensubtitlesPassword, + ssl: true }); }; diff --git a/src/app/lib/providers/trakttv.js b/src/app/lib/providers/trakttv.js index 2ce8df95b4..4daf8a5cfb 100644 --- a/src/app/lib/providers/trakttv.js +++ b/src/app/lib/providers/trakttv.js @@ -5,7 +5,11 @@ this.client = new Trakt({ client_id: Settings.trakttv.client_id, client_secret: Settings.trakttv.client_secret, - plugins: ['ondeck', 'matcher', 'images'], + plugins: { + ondeck: require('trakt.tv-ondeck'), + matcher: require('trakt.tv-matcher'), + images: require('trakt.tv-images') + }, options: { images: { smallerImages: true, diff --git a/src/app/lib/vendor/videojshooks.js b/src/app/lib/vendor/videojshooks.js index 42712ec6ed..986fec4392 100644 --- a/src/app/lib/vendor/videojshooks.js +++ b/src/app/lib/vendor/videojshooks.js @@ -284,6 +284,8 @@ vjs.TextTrack.prototype.load = function () { .replace(/(- |==|sync).*[\s\S].*[\s\S].*[\s\S].*[\s\S].*\.(com|org|net|edu)/ig, '') // various teams .replace(/[^0-9][\s\S][^0-9\W].*[\s\S].*[\s\S].*opensubtitles.*/ig, ''); // opensubs "contact us" ads + strings = Common.sanitize(strings); // xss-style attacks + strings = strings.replace(/--\>\;/g, '-->'); // restore srt format callback(strings); }; diff --git a/src/app/lib/views/browser/item.js b/src/app/lib/views/browser/item.js index 477af06e35..f03d939393 100644 --- a/src/app/lib/views/browser/item.js +++ b/src/app/lib/views/browser/item.js @@ -18,6 +18,7 @@ ui: { covers: '.cover-imgs', + defaultCover: '.cover', bookmarkIcon: '.actions-favorites', watchedIcon: '.actions-watched' }, @@ -135,7 +136,7 @@ var posterCache = new Image(); posterCache.src = poster; - this.ui.covers.append(``); + this.ui.covers.append(`
`); posterCache.onload = function () { posterCache.onload = () => {}; @@ -149,11 +150,14 @@ posterCache.src = c.toDataURL(); } - this.ui.covers.children(-1).attr('src', posterCache.src).addClass('fadein'); + this.ui.covers.children(-1).css('background-image', 'url('+posterCache.src+')').addClass('fadein').delay(600).queue(_ => { + this.ui.defaultCover.addClass('empty'); + }); }.bind(this); posterCache.onerror = function (e) { this.ui.covers.empty(); + this.ui.defaultCover.removeClass('empty'); }.bind(this); }, diff --git a/src/app/lib/views/browser/list.js b/src/app/lib/views/browser/list.js index abe98c6883..d7d51b83ac 100644 --- a/src/app/lib/views/browser/list.js +++ b/src/app/lib/views/browser/list.js @@ -262,9 +262,9 @@ onLoaded: function () { App.vent.trigger('list:loaded'); - this.checkEmpty(); var self = this; - this.addloadmore(); + + this.completerow(); if (typeof (this.ui.spinner) === 'object') { this.ui.spinner.hide(); @@ -298,23 +298,34 @@ } }, + completerow: function () { + var elms = this.addloadmore(); + elms += this.addghosts(); + + $('.ghost, #load-more-item').remove(); + $('.items').append(elms); + + this.showloadmore(); + }, + + addghosts: function () { + return ''.repeat(10); + }, + addloadmore: function () { - var self = this; + return '