[TV] Moved imdb and refresh components to new "episode.actions.js", implemented episode "release" action
This commit is contained in:
+450
@@ -0,0 +1,450 @@
|
||||
var EpisodeAction = new Class({
|
||||
|
||||
Implements: [Options],
|
||||
|
||||
class_name: 'action icon2',
|
||||
|
||||
initialize: function(episode, options){
|
||||
var self = this;
|
||||
self.setOptions(options);
|
||||
|
||||
self.show = episode.show;
|
||||
self.episode = episode;
|
||||
|
||||
self.create();
|
||||
if(self.el)
|
||||
self.el.addClass(self.class_name)
|
||||
},
|
||||
|
||||
create: function(){},
|
||||
|
||||
disable: function(){
|
||||
if(this.el)
|
||||
this.el.addClass('disable')
|
||||
},
|
||||
|
||||
enable: function(){
|
||||
if(this.el)
|
||||
this.el.removeClass('disable')
|
||||
},
|
||||
|
||||
getTitle: function(){
|
||||
var self = this;
|
||||
|
||||
try {
|
||||
return self.show.getTitle();
|
||||
}
|
||||
catch(e){
|
||||
try {
|
||||
return self.show.original_title ? self.show.original_title : self.show.titles[0];
|
||||
}
|
||||
catch(e){
|
||||
return 'Unknown';
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
get: function(key){
|
||||
var self = this;
|
||||
try {
|
||||
return self.show.get(key)
|
||||
}
|
||||
catch(e){
|
||||
return self.show[key]
|
||||
}
|
||||
},
|
||||
|
||||
createMask: function(){
|
||||
var self = this;
|
||||
self.mask = new Element('div.mask', {
|
||||
'styles': {
|
||||
'z-index': '1'
|
||||
}
|
||||
}).inject(self.show, 'top').fade('hide');
|
||||
},
|
||||
|
||||
toElement: function(){
|
||||
return this.el || null
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
var EA = {};
|
||||
|
||||
EA.IMDB = new Class({
|
||||
|
||||
Extends: EpisodeAction,
|
||||
id: null,
|
||||
|
||||
create: function(){
|
||||
var self = this;
|
||||
|
||||
self.id = self.show.getIdentifier ? self.show.getIdentifier() : self.get('imdb');
|
||||
|
||||
self.el = new Element('a.imdb', {
|
||||
'title': 'Go to the IMDB page of ' + self.getTitle(),
|
||||
'href': 'http://www.imdb.com/title/'+self.id+'/',
|
||||
'target': '_blank'
|
||||
});
|
||||
|
||||
if(!self.id) self.disable();
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
EA.Release = new Class({
|
||||
|
||||
Extends: EpisodeAction,
|
||||
|
||||
create: function(){
|
||||
var self = this;
|
||||
|
||||
self.el = new Element('a.releases.download', {
|
||||
'title': 'Show the releases that are available for ' + self.getTitle(),
|
||||
'events': {
|
||||
'click': self.open.bind(self)
|
||||
}
|
||||
});
|
||||
|
||||
if(!self.episode.data.releases || self.episode.data.releases.length == 0)
|
||||
self.el.hide();
|
||||
else
|
||||
self.showHelper();
|
||||
|
||||
App.on('show.searcher.ended', function(notification){
|
||||
if(self.show.data._id != notification.data._id) return;
|
||||
|
||||
self.releases = null;
|
||||
if(self.options_container){
|
||||
self.options_container.destroy();
|
||||
self.options_container = null;
|
||||
}
|
||||
});
|
||||
|
||||
},
|
||||
|
||||
open: function(e){
|
||||
var self = this;
|
||||
if(e)
|
||||
(e).preventDefault();
|
||||
|
||||
self.createReleases();
|
||||
|
||||
},
|
||||
|
||||
createReleases: function(){
|
||||
var self = this;
|
||||
|
||||
if(!self.releases_container){
|
||||
self.releases_container = new Element('div.releases.table').inject(self.episode.el);
|
||||
|
||||
// Header
|
||||
new Element('div.item.head').adopt(
|
||||
new Element('span.name', {'text': 'Release name'}),
|
||||
new Element('span.status', {'text': 'Status'}),
|
||||
new Element('span.quality', {'text': 'Quality'}),
|
||||
new Element('span.size', {'text': 'Size'}),
|
||||
new Element('span.age', {'text': 'Age'}),
|
||||
new Element('span.score', {'text': 'Score'}),
|
||||
new Element('span.provider', {'text': 'Provider'})
|
||||
).inject(self.releases_container);
|
||||
|
||||
if(self.episode.data.releases)
|
||||
self.episode.data.releases.each(function(release){
|
||||
|
||||
var quality = Quality.getQuality(release.quality) || {},
|
||||
info = release.info || {},
|
||||
provider = self.get(release, 'provider') + (info['provider_extra'] ? self.get(release, 'provider_extra') : '');
|
||||
|
||||
var release_name = self.get(release, 'name');
|
||||
if(release.files && release.files.length > 0){
|
||||
try {
|
||||
var movie_file = release.files.filter(function(file){
|
||||
var type = File.Type.get(file.type_id);
|
||||
return type && type.identifier == 'movie'
|
||||
}).pick();
|
||||
release_name = movie_file.path.split(Api.getOption('path_sep')).getLast();
|
||||
}
|
||||
catch(e){}
|
||||
}
|
||||
|
||||
// Create release
|
||||
release['el'] = new Element('div', {
|
||||
'class': 'item '+release.status,
|
||||
'id': 'release_'+release._id
|
||||
}).adopt(
|
||||
new Element('span.name', {'text': release_name, 'title': release_name}),
|
||||
new Element('span.status', {'text': release.status, 'class': 'release_status '+release.status}),
|
||||
new Element('span.quality', {'text': quality.label + (release.is_3d ? ' 3D' : '') || 'n/a'}),
|
||||
new Element('span.size', {'text': info['size'] ? Math.floor(self.get(release, 'size')) : 'n/a'}),
|
||||
new Element('span.age', {'text': self.get(release, 'age')}),
|
||||
new Element('span.score', {'text': self.get(release, 'score')}),
|
||||
new Element('span.provider', { 'text': provider, 'title': provider }),
|
||||
info['detail_url'] ? new Element('a.info.icon2', {
|
||||
'href': info['detail_url'],
|
||||
'target': '_blank'
|
||||
}) : new Element('a'),
|
||||
new Element('a.download.icon2', {
|
||||
'events': {
|
||||
'click': function(e){
|
||||
(e).preventDefault();
|
||||
if(!this.hasClass('completed'))
|
||||
self.download(release);
|
||||
}
|
||||
}
|
||||
}),
|
||||
new Element('a.delete.icon2', {
|
||||
'events': {
|
||||
'click': function(e){
|
||||
(e).preventDefault();
|
||||
self.ignore(release);
|
||||
}
|
||||
}
|
||||
})
|
||||
).inject(self.releases_container);
|
||||
|
||||
if(release.status == 'ignored' || release.status == 'failed' || release.status == 'snatched'){
|
||||
if(!self.last_release || (self.last_release && self.last_release.status != 'snatched' && release.status == 'snatched'))
|
||||
self.last_release = release;
|
||||
}
|
||||
else if(!self.next_release && release.status == 'available'){
|
||||
self.next_release = release;
|
||||
}
|
||||
|
||||
var update_handle = function(notification) {
|
||||
if(notification.data._id != release._id) return;
|
||||
|
||||
var q = self.show.quality.getElement('.q_' + release.quality),
|
||||
new_status = notification.data.status;
|
||||
|
||||
release.el.set('class', 'item ' + new_status);
|
||||
|
||||
var status_el = release.el.getElement('.release_status');
|
||||
status_el.set('class', 'release_status ' + new_status);
|
||||
status_el.set('text', new_status);
|
||||
|
||||
if(!q && (new_status == 'snatched' || new_status == 'seeding' || new_status == 'done'))
|
||||
q = self.addQuality(release.quality_id);
|
||||
|
||||
if(q && !q.hasClass(new_status)) {
|
||||
q.removeClass(release.status).addClass(new_status);
|
||||
q.set('title', q.get('title').replace(release.status, new_status));
|
||||
}
|
||||
};
|
||||
|
||||
App.on('release.update_status', update_handle);
|
||||
|
||||
});
|
||||
|
||||
if(self.last_release)
|
||||
self.releases_container.getElements('#release_'+self.last_release._id).addClass('last_release');
|
||||
|
||||
if(self.next_release)
|
||||
self.releases_container.getElements('#release_'+self.next_release._id).addClass('next_release');
|
||||
|
||||
if(self.next_release || (self.last_release && ['ignored', 'failed'].indexOf(self.last_release.status) === false)){
|
||||
|
||||
self.trynext_container = new Element('div.buttons.try_container').inject(self.releases_container, 'top');
|
||||
|
||||
var nr = self.next_release,
|
||||
lr = self.last_release;
|
||||
|
||||
self.trynext_container.adopt(
|
||||
new Element('span.or', {
|
||||
'text': 'If anything went wrong, download'
|
||||
}),
|
||||
lr ? new Element('a.button.orange', {
|
||||
'text': 'the same release again',
|
||||
'events': {
|
||||
'click': function(){
|
||||
self.download(lr);
|
||||
}
|
||||
}
|
||||
}) : null,
|
||||
nr && lr ? new Element('span.or', {
|
||||
'text': ','
|
||||
}) : null,
|
||||
nr ? [new Element('a.button.green', {
|
||||
'text': lr ? 'another release' : 'the best release',
|
||||
'events': {
|
||||
'click': function(){
|
||||
self.download(nr);
|
||||
}
|
||||
}
|
||||
}),
|
||||
new Element('span.or', {
|
||||
'text': 'or pick one below'
|
||||
})] : null
|
||||
)
|
||||
}
|
||||
|
||||
self.last_release = null;
|
||||
self.next_release = null;
|
||||
|
||||
self.episode.el.addEvent('outerClick', function(){
|
||||
console.log('outerClick');
|
||||
|
||||
self.releases_container.removeClass('expanded');
|
||||
});
|
||||
}
|
||||
|
||||
self.releases_container.addClass('expanded');
|
||||
|
||||
},
|
||||
|
||||
showHelper: function(e){
|
||||
var self = this;
|
||||
if(e)
|
||||
(e).preventDefault();
|
||||
|
||||
var has_available = false,
|
||||
has_snatched = false;
|
||||
|
||||
if(self.episode.data.releases)
|
||||
self.episode.data.releases.each(function(release){
|
||||
if(has_available && has_snatched) return;
|
||||
|
||||
if(['snatched', 'downloaded', 'seeding'].contains(release.status))
|
||||
has_snatched = true;
|
||||
|
||||
if(['available'].contains(release.status))
|
||||
has_available = true;
|
||||
|
||||
});
|
||||
|
||||
if(has_available || has_snatched){
|
||||
|
||||
self.trynext_container = new Element('div.buttons.trynext').inject(self.show.info_container);
|
||||
|
||||
self.trynext_container.adopt(
|
||||
has_available ? [new Element('a.icon2.readd', {
|
||||
'text': has_snatched ? 'Download another release' : 'Download the best release',
|
||||
'events': {
|
||||
'click': self.tryNextRelease.bind(self)
|
||||
}
|
||||
}),
|
||||
new Element('a.icon2.download', {
|
||||
'text': 'pick one yourself',
|
||||
'events': {
|
||||
'click': function(){
|
||||
self.show.quality.fireEvent('click');
|
||||
}
|
||||
}
|
||||
})] : null,
|
||||
new Element('a.icon2.completed', {
|
||||
'text': 'mark this movie done',
|
||||
'events': {
|
||||
'click': self.markMovieDone.bind(self)
|
||||
}
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
get: function(release, type){
|
||||
return (release.info && release.info[type] !== undefined) ? release.info[type] : 'n/a'
|
||||
},
|
||||
|
||||
download: function(release){
|
||||
var self = this;
|
||||
|
||||
var release_el = self.releases_container.getElement('#release_'+release._id),
|
||||
icon = release_el.getElement('.download.icon2');
|
||||
|
||||
if(icon)
|
||||
icon.addClass('icon spinner').removeClass('download');
|
||||
|
||||
Api.request('release.manual_download', {
|
||||
'data': {
|
||||
'id': release._id
|
||||
},
|
||||
'onComplete': function(json){
|
||||
if(icon)
|
||||
icon.removeClass('icon spinner');
|
||||
|
||||
if(json.success){
|
||||
if(icon)
|
||||
icon.addClass('completed');
|
||||
release_el.getElement('.release_status').set('text', 'snatched');
|
||||
}
|
||||
else
|
||||
if(icon)
|
||||
icon.addClass('attention').set('title', 'Something went wrong when downloading, please check logs.');
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
ignore: function(release){
|
||||
|
||||
Api.request('release.ignore', {
|
||||
'data': {
|
||||
'id': release._id
|
||||
}
|
||||
})
|
||||
|
||||
},
|
||||
|
||||
markMovieDone: function(){
|
||||
var self = this;
|
||||
|
||||
Api.request('media.delete', {
|
||||
'data': {
|
||||
'id': self.show.get('_id'),
|
||||
'delete_from': 'wanted'
|
||||
},
|
||||
'onComplete': function(){
|
||||
var movie = $(self.show);
|
||||
movie.set('tween', {
|
||||
'duration': 300,
|
||||
'onComplete': function(){
|
||||
self.show.destroy()
|
||||
}
|
||||
});
|
||||
movie.tween('height', 0);
|
||||
}
|
||||
});
|
||||
|
||||
},
|
||||
|
||||
tryNextRelease: function(){
|
||||
var self = this;
|
||||
|
||||
Api.request('movie.searcher.try_next', {
|
||||
'data': {
|
||||
'media_id': self.show.get('_id')
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
EA.Refresh = new Class({
|
||||
|
||||
Extends: EpisodeAction,
|
||||
|
||||
create: function(){
|
||||
var self = this;
|
||||
|
||||
self.el = new Element('a.refresh', {
|
||||
'title': 'Refresh the movie info and do a forced search',
|
||||
'events': {
|
||||
'click': self.doRefresh.bind(self)
|
||||
}
|
||||
});
|
||||
|
||||
},
|
||||
|
||||
doRefresh: function(e){
|
||||
var self = this;
|
||||
(e).preventDefault();
|
||||
|
||||
Api.request('media.refresh', {
|
||||
'data': {
|
||||
'id': self.show.get('_id')
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
});
|
||||
@@ -4,16 +4,19 @@ var Episode = new Class({
|
||||
|
||||
action: {},
|
||||
|
||||
initialize: function(show, data){
|
||||
initialize: function(show, options, data){
|
||||
var self = this;
|
||||
self.setOptions(options);
|
||||
|
||||
self.show = show;
|
||||
self.options = options;
|
||||
self.data = data;
|
||||
|
||||
self.profile = self.show.profile;
|
||||
|
||||
self.el = new Element('div.item.data');
|
||||
self.el_actions = new Element('div.episode-actions');
|
||||
self.el = new Element('div.item').adopt(
|
||||
self.detail = new Element('div.item.data')
|
||||
);
|
||||
|
||||
self.create();
|
||||
},
|
||||
@@ -21,35 +24,17 @@ var Episode = new Class({
|
||||
create: function(){
|
||||
var self = this;
|
||||
|
||||
self.el.set('id', 'episode_'+self.data._id);
|
||||
self.detail.set('id', 'episode_'+self.data._id);
|
||||
|
||||
self.el.adopt(
|
||||
self.detail.adopt(
|
||||
new Element('span.episode', {'text': (self.data.info.number || 0)}),
|
||||
new Element('span.name', {'text': self.getTitle()}),
|
||||
new Element('span.firstaired', {'text': self.data.info.firstaired}),
|
||||
|
||||
self.quality = new Element('span.quality')
|
||||
self.quality = new Element('span.quality'),
|
||||
self.actions = new Element('div.episode-actions')
|
||||
);
|
||||
|
||||
self.el_actions.inject(self.el);
|
||||
|
||||
// imdb
|
||||
if(self.data.identifiers && self.data.identifiers.imdb) {
|
||||
new Element('a.imdb.icon2', {
|
||||
'title': 'Go to the IMDB page of ' + self.show.getTitle(),
|
||||
'href': 'http://www.imdb.com/title/' + self.data.identifiers.imdb + '/',
|
||||
'target': '_blank'
|
||||
}).inject(self.el_actions);
|
||||
}
|
||||
|
||||
// refresh
|
||||
new Element('a.refresh.icon2', {
|
||||
'title': 'Refresh the episode info and do a forced search',
|
||||
'events': {
|
||||
'click': self.doRefresh.bind(self)
|
||||
}
|
||||
}).inject(self.el_actions);
|
||||
|
||||
// Add profile
|
||||
if(self.profile.data) {
|
||||
self.profile.getTypes().each(function(type){
|
||||
@@ -64,6 +49,12 @@ var Episode = new Class({
|
||||
|
||||
// Add releases
|
||||
self.updateReleases();
|
||||
|
||||
Object.each(self.options.actions, function(action, key){
|
||||
self.action[key.toLowerCase()] = action = new self.options.actions[key](self);
|
||||
if(action.el)
|
||||
self.actions.adopt(action)
|
||||
});
|
||||
},
|
||||
|
||||
updateReleases: function(){
|
||||
@@ -111,13 +102,18 @@ var Episode = new Class({
|
||||
return title;
|
||||
},
|
||||
|
||||
doRefresh: function(e) {
|
||||
getIdentifier: function(){
|
||||
var self = this;
|
||||
|
||||
Api.request('media.refresh', {
|
||||
'data': {
|
||||
'id': self.data._id
|
||||
}
|
||||
});
|
||||
try {
|
||||
return self.get('identifiers').imdb;
|
||||
}
|
||||
catch (e){ }
|
||||
|
||||
return self.get('imdb');
|
||||
},
|
||||
|
||||
get: function(attr){
|
||||
return this.data[attr] || this.data.info[attr]
|
||||
}
|
||||
});
|
||||
@@ -682,25 +682,47 @@
|
||||
}
|
||||
.shows .list .episodes .item {
|
||||
position: relative;
|
||||
width: auto;
|
||||
width: 100%;
|
||||
height: auto;
|
||||
padding: 0;
|
||||
|
||||
text-align: left;
|
||||
|
||||
transition: all .6s cubic-bezier(0.9,0,0.1,1);
|
||||
}
|
||||
|
||||
.shows .list .episodes .item span.episode {
|
||||
.shows .list .episodes .item.data span.episode {
|
||||
width: 40px;
|
||||
padding: 0 10px;
|
||||
}
|
||||
|
||||
.shows .list .episodes .item span.name {
|
||||
.shows .list .episodes .item.data span.name {
|
||||
width: 280px;
|
||||
}
|
||||
|
||||
.shows .list .episodes .item span.firstaired {
|
||||
.shows .list .episodes .item.data span.firstaired {
|
||||
width: 80px;
|
||||
}
|
||||
|
||||
.shows .list .show .episodes .episode-actions {
|
||||
.shows .list .episodes .item.data span.quality {
|
||||
bottom: auto;
|
||||
}
|
||||
|
||||
.shows .list .episodes .releases.table {
|
||||
display: none;
|
||||
width: 100%;
|
||||
height: auto;
|
||||
|
||||
padding: 0;
|
||||
|
||||
background: rgba(0,0,0,.2);
|
||||
}
|
||||
|
||||
.shows .list .episodes .releases.table.expanded {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.shows .list .episodes .episode-actions {
|
||||
position: absolute;
|
||||
width: auto;
|
||||
right: 0;
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
var Episodes = new Class({
|
||||
initialize: function(show) {
|
||||
initialize: function(show, options) {
|
||||
var self = this;
|
||||
|
||||
self.show = show;
|
||||
self.options = options;
|
||||
},
|
||||
|
||||
open: function(){
|
||||
@@ -65,7 +66,7 @@ var Episodes = new Class({
|
||||
|
||||
createEpisode: function(episode){
|
||||
var self = this,
|
||||
e = new Episode(self.show, episode);
|
||||
e = new Episode(self.show, self.options, episode);
|
||||
|
||||
$(e).inject(self.episodes_container);
|
||||
},
|
||||
|
||||
@@ -13,7 +13,9 @@ var Show = new Class({
|
||||
|
||||
self.el = new Element('div.show');
|
||||
|
||||
self.episodes = new Episodes(self);
|
||||
self.episodes = new Episodes(self, {
|
||||
'actions': [EA.IMDB, EA.Release, EA.Refresh]
|
||||
});
|
||||
|
||||
self.profile = Quality.getProfile(data.profile_id) || {};
|
||||
self.category = CategoryList.getCategory(data.category_id) || {};
|
||||
|
||||
Reference in New Issue
Block a user