diff --git a/dist/addon.xml b/dist/addon.xml index e97bbcc..5fc310b 100755 --- a/dist/addon.xml +++ b/dist/addon.xml @@ -1,7 +1,7 @@ diff --git a/dist/changelog.txt b/dist/changelog.txt index 9489da6..33138c3 100755 --- a/dist/changelog.txt +++ b/dist/changelog.txt @@ -1,3 +1,17 @@ +Version 0.3.9 +- changed search trigger to only respond to input change #39 - thanks to kopf +- Strip [color] text from labels #33 - thanks to thorstenhirsch +- Fix for iOS bug in footer #40 - thanks to joshjowen +- Add iOS icon #47 - thanks to joshjowen +- Add Android icon +- Fixed bug where movies reloaded complete list when you get to the end #35 +- Improved now playing meta info in footer +- Fixed LiveTV now playing information #38 +- Added duration and direct download link to movie view +- Added duration and direct download link to tv episode view, moved plot into overview tab +- Fixed bug with closing the remote (having to click button twice) + + Version 0.3.8 - Fixed ability to delete a custom playlist song - Refactored player state and added some improvements to stream playback diff --git a/dist/chorus.js b/dist/chorus.js index fe034a6..118f42c 100644 --- a/dist/chorus.js +++ b/dist/chorus.js @@ -15983,8 +15983,10 @@ app.Router = Backbone.Router.extend({ // fetch results app.cached.movieCollection.fetch({"fullRange": fullRange, "success": function(collection){ + // if fully loaded, we don't want a next button + collection.showNext = !app.cached.movieCollection.fullyLoaded; + // get the view of results - collection.showNext = true; app.cached.movieListView = new app.MovieListView({model: collection}); if(isNewPage === true || app.moviePageNum === 0 || append !== true){ // Replace content // @@ -17566,9 +17568,39 @@ app.ui = { app.ui.timerStart(); } + }, + - } + /** + * Create a sub-title string for a given model + */ + getModelMeta: function(model){ + + // need a model or type to continue + if(model === undefined || model.type === undefined){ + return ''; + } + // meta depends on type + meta = ''; + switch(model.type){ + case 'song': + meta = app.helpers.parseArtistsArray(model); + break; + case 'movie': + meta = model.year; + break; + case 'episode': + meta = model.showtitle + ' (S' + model.season + ' E' + model.episode + ')'; + break; + case 'channel': + meta = model.title; + break; + } + + // return the meta + return meta; + } @@ -17756,7 +17788,7 @@ app.PvrChannel = Backbone.Model.extend({ app.Movie = Backbone.Model.extend({ initialize:function () {}, - defaults: {movieid: 1, thumbnail: '', fanart: '', year: '', url: '#movies', 'thumbsup': false, 'libraryId': 1}, + defaults: {movieid: 1, thumbnail: '', fanart: '', year: '', url: '#movies', 'thumbsup': false, 'libraryId': 1, runtime: 0}, sync: function(method, model, options) { if (method === "read") { @@ -17782,7 +17814,7 @@ app.Movie = Backbone.Model.extend({ app.TVShow = Backbone.Model.extend({ initialize:function () {}, - defaults: {'tvshowid': '', 'label': '', 'watchedepisodes': '', 'genre': '', 'year': '', 'cast': [], 'rating': 0, url: '#tv', 'episodeid': ''}, + defaults: {'tvshowid': '', 'label': '', 'watchedepisodes': '', 'genre': '', 'year': '', 'cast': [], 'rating': 0, url: '#tv', 'episodeid': '', runtime: 0}, sync: function(method, model, options) { if (method === "read") { @@ -22188,13 +22220,10 @@ app.MovieCollection = Backbone.Collection.extend({ sync: function(method, model, options) { if (method === "read") { - // Get a paginated var self = this, fullRange = (typeof options.fullRange != 'undefined' && options.fullRange === true); - - // load up a full cache for pagination app.cached.moviesPage = new app.MovieAllCollection(); app.cached.moviesPage.fetch({"success": function(model){ @@ -22203,7 +22232,8 @@ app.MovieCollection = Backbone.Collection.extend({ // return pagination from cache if exists var cache = self.cachedPagination(app.moviePageNum, fullRange); if(cache !== false){ - options.success(cache); + self.fullyLoaded = (cache >= app.stores.allMovies.length); + options.success(cache); return; } @@ -22232,28 +22262,21 @@ app.MovieCollection = Backbone.Collection.extend({ }); } - // if models less than ipp then must be the end - if(data.models.length > app.itemsPerPage){ - self.fullyLoaded = true; - } + // if models less than ipp or we have a complete collection then must be the end + self.fullyLoaded = (data.models.length < app.itemsPerPage || data.models.length >= app.stores.allMovies.length); + // return callback options.success(data.models); return data.models; }}); - - - }}); - //return this - } }, - /** * Returns a set of results if in cache or false if a lookup is required * @param pageNum @@ -25474,8 +25497,11 @@ app.MovieListView = Backbone.View.extend({ }, nextPage: function(e){ - var $el = $('.next-page').last(); - app.pager.nextPage($el, 'movie'); + // Do not run if we have no next button (sometime sneaks past even if button not rendered somehow?) + if(this.model.showNext !== undefined && this.model.showNext === true){ + var $el = $('.next-page').last(); + app.pager.nextPage($el, 'movie'); + } }, @@ -25679,9 +25705,14 @@ app.MovieView = Backbone.View.extend({ model.thumbsup = app.playlists.isThumbsUp('movie', model.movieid); model.watched = app.VideoController.watchedStatus(model); - //main detail + // main detail this.$el.html(this.template(model)); + // populate download link + app.AudioController.downloadFile(model.file, function(url){ + $('.download-link', this.$el).attr('href', url); + }); + // backstretch _.defer(function(){ var $fart = $('#fanart-background',self.$el), @@ -26299,7 +26330,7 @@ app.playerStateView = Backbone.View.extend({ * @returns {boolean} */ isUrl: function(str){ - return (str.lastIndexOf("http://", 0) === 0) || (str.lastIndexOf("https://", 0) === 0); + return str !== undefined && ((str.lastIndexOf("http://", 0) === 0) || (str.lastIndexOf("https://", 0) === 0)); }, @@ -26353,7 +26384,7 @@ app.playerStateView = Backbone.View.extend({ cur = 0, dur = 0, // playlist stuff - meta = app.helpers.parseArtistsArray(data.item), + meta = app.ui.getModelMeta(data.item), $playlistActive = $('.playlist .playing-row'); //set playlist meta and playing row @@ -27584,7 +27615,7 @@ app.searchView = Backbone.View.extend({ var keyDelay = 200, self = this; // set and clear timeout to leave a gap - $('#search').keyup(function (e) { + $('#search').on('input', function (e) { // e.preventDefault(); clearTimeout(app.cached.keyupTimeout); // doesn't matter if it's 0 app.cached.keyupTimeout = setTimeout(function(){ @@ -27664,8 +27695,8 @@ app.searchView = Backbone.View.extend({ // toggle remote remoteControl: function(e){ + e.preventDefault(); if(app.helpers.arg(0) == 'remote'){ - e.preventDefault(); // same as using the back button window.history.back(); } else { @@ -28486,6 +28517,11 @@ app.TvshowView = Backbone.View.extend({ //main detail this.$el.html(this.template(model)); + // populate download link + app.AudioController.downloadFile(model.file, function(url){ + $('.download-link', this.$el).attr('href', url); + }); + // backstretch _.defer(function(){ var $fart = $('#fanart-background',this.$el), diff --git a/dist/chorus.min.js b/dist/chorus.min.js index 875a134..b43c68f 100644 --- a/dist/chorus.min.js +++ b/dist/chorus.min.js @@ -1,18 +1,18 @@ -/*! chorus by Jeremy Graham - built on 05-05-2014 */ +/*! chorus by Jeremy Graham - built on 18-05-2014 */ !function(a,b){"object"==typeof module&&"object"==typeof module.exports?module.exports=a.document?b(a,!0):function(a){if(!a.document)throw new Error("jQuery requires a window with a document");return b(a)}:b(a)}("undefined"!=typeof window?window:this,function(a,b){function c(a){var b=a.length,c=eb.type(a);return"function"===c||eb.isWindow(a)?!1:1===a.nodeType&&b?!0:"array"===c||0===b||"number"==typeof b&&b>0&&b-1 in a}function d(a,b,c){if(eb.isFunction(b))return eb.grep(a,function(a,d){return!!b.call(a,d,a)!==c});if(b.nodeType)return eb.grep(a,function(a){return a===b!==c});if("string"==typeof b){if(mb.test(b))return eb.filter(b,a,c);b=eb.filter(b,a)}return eb.grep(a,function(a){return eb.inArray(a,b)>=0!==c})}function e(a,b){do a=a[b];while(a&&1!==a.nodeType);return a}function f(a){var b=ub[a]={};return eb.each(a.match(tb)||[],function(a,c){b[c]=!0}),b}function g(){ob.addEventListener?(ob.removeEventListener("DOMContentLoaded",h,!1),a.removeEventListener("load",h,!1)):(ob.detachEvent("onreadystatechange",h),a.detachEvent("onload",h))}function h(){(ob.addEventListener||"load"===event.type||"complete"===ob.readyState)&&(g(),eb.ready())}function i(a,b,c){if(void 0===c&&1===a.nodeType){var d="data-"+b.replace(zb,"-$1").toLowerCase();if(c=a.getAttribute(d),"string"==typeof c){try{c="true"===c?!0:"false"===c?!1:"null"===c?null:+c+""===c?+c:yb.test(c)?eb.parseJSON(c):c}catch(e){}eb.data(a,b,c)}else c=void 0}return c}function j(a){var b;for(b in a)if(("data"!==b||!eb.isEmptyObject(a[b]))&&"toJSON"!==b)return!1;return!0}function k(a,b,c,d){if(eb.acceptData(a)){var e,f,g=eb.expando,h=a.nodeType,i=h?eb.cache:a,j=h?a[g]:a[g]&&g;if(j&&i[j]&&(d||i[j].data)||void 0!==c||"string"!=typeof b)return j||(j=h?a[g]=W.pop()||eb.guid++:g),i[j]||(i[j]=h?{}:{toJSON:eb.noop}),("object"==typeof b||"function"==typeof b)&&(d?i[j]=eb.extend(i[j],b):i[j].data=eb.extend(i[j].data,b)),f=i[j],d||(f.data||(f.data={}),f=f.data),void 0!==c&&(f[eb.camelCase(b)]=c),"string"==typeof b?(e=f[b],null==e&&(e=f[eb.camelCase(b)])):e=f,e}}function l(a,b,c){if(eb.acceptData(a)){var d,e,f=a.nodeType,g=f?eb.cache:a,h=f?a[eb.expando]:eb.expando;if(g[h]){if(b&&(d=c?g[h]:g[h].data)){eb.isArray(b)?b=b.concat(eb.map(b,eb.camelCase)):b in d?b=[b]:(b=eb.camelCase(b),b=b in d?[b]:b.split(" ")),e=b.length;for(;e--;)delete d[b[e]];if(c?!j(d):!eb.isEmptyObject(d))return}(c||(delete g[h].data,j(g[h])))&&(f?eb.cleanData([a],!0):cb.deleteExpando||g!=g.window?delete g[h]:g[h]=null)}}}function m(){return!0}function n(){return!1}function o(){try{return ob.activeElement}catch(a){}}function p(a){var b=Kb.split("|"),c=a.createDocumentFragment();if(c.createElement)for(;b.length;)c.createElement(b.pop());return c}function q(a,b){var c,d,e=0,f=typeof a.getElementsByTagName!==xb?a.getElementsByTagName(b||"*"):typeof a.querySelectorAll!==xb?a.querySelectorAll(b||"*"):void 0;if(!f)for(f=[],c=a.childNodes||a;null!=(d=c[e]);e++)!b||eb.nodeName(d,b)?f.push(d):eb.merge(f,q(d,b));return void 0===b||b&&eb.nodeName(a,b)?eb.merge([a],f):f}function r(a){Eb.test(a.type)&&(a.defaultChecked=a.checked)}function s(a,b){return eb.nodeName(a,"table")&&eb.nodeName(11!==b.nodeType?b:b.firstChild,"tr")?a.getElementsByTagName("tbody")[0]||a.appendChild(a.ownerDocument.createElement("tbody")):a}function t(a){return a.type=(null!==eb.find.attr(a,"type"))+"/"+a.type,a}function u(a){var b=Vb.exec(a.type);return b?a.type=b[1]:a.removeAttribute("type"),a}function v(a,b){for(var c,d=0;null!=(c=a[d]);d++)eb._data(c,"globalEval",!b||eb._data(b[d],"globalEval"))}function w(a,b){if(1===b.nodeType&&eb.hasData(a)){var c,d,e,f=eb._data(a),g=eb._data(b,f),h=f.events;if(h){delete g.handle,g.events={};for(c in h)for(d=0,e=h[c].length;e>d;d++)eb.event.add(b,c,h[c][d])}g.data&&(g.data=eb.extend({},g.data))}}function x(a,b){var c,d,e;if(1===b.nodeType){if(c=b.nodeName.toLowerCase(),!cb.noCloneEvent&&b[eb.expando]){e=eb._data(b);for(d in e.events)eb.removeEvent(b,d,e.handle);b.removeAttribute(eb.expando)}"script"===c&&b.text!==a.text?(t(b).text=a.text,u(b)):"object"===c?(b.parentNode&&(b.outerHTML=a.outerHTML),cb.html5Clone&&a.innerHTML&&!eb.trim(b.innerHTML)&&(b.innerHTML=a.innerHTML)):"input"===c&&Eb.test(a.type)?(b.defaultChecked=b.checked=a.checked,b.value!==a.value&&(b.value=a.value)):"option"===c?b.defaultSelected=b.selected=a.defaultSelected:("input"===c||"textarea"===c)&&(b.defaultValue=a.defaultValue)}}function y(b,c){var d,e=eb(c.createElement(b)).appendTo(c.body),f=a.getDefaultComputedStyle&&(d=a.getDefaultComputedStyle(e[0]))?d.display:eb.css(e[0],"display");return e.detach(),f}function z(a){var b=ob,c=_b[a];return c||(c=y(a,b),"none"!==c&&c||($b=($b||eb("