From 8354f9c144e9215945908f7c0a32a3104c1d98ab Mon Sep 17 00:00:00 2001 From: Ruud Date: Sat, 30 Jun 2012 15:09:27 +0200 Subject: [PATCH 01/11] Only notify once on update. fix #515 --- couchpotato/core/_base/updater/main.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/couchpotato/core/_base/updater/main.py b/couchpotato/core/_base/updater/main.py index bc7f869a..f148b4bd 100644 --- a/couchpotato/core/_base/updater/main.py +++ b/couchpotato/core/_base/updater/main.py @@ -20,6 +20,8 @@ log = CPLog(__name__) class Updater(Plugin): + available_notified = False + def __init__(self): if Env.get('desktop'): @@ -69,8 +71,9 @@ class Updater(Plugin): return if self.updater.check(): - if self.conf('notification') and not self.conf('automatic'): + if not self.available_notified and self.conf('notification') and not self.conf('automatic'): fireEvent('updater.available', message = 'A new update is available', data = self.updater.info()) + self.available_notified = True return True return False From cdb6dfe70cfd9398177454991bd6f471da3f06d8 Mon Sep 17 00:00:00 2001 From: Ruud Date: Sat, 30 Jun 2012 15:30:58 +0200 Subject: [PATCH 02/11] Always do votecount as int. fix #513 --- couchpotato/core/providers/movie/imdbapi/main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/couchpotato/core/providers/movie/imdbapi/main.py b/couchpotato/core/providers/movie/imdbapi/main.py index ad3f78ff..daf8b369 100644 --- a/couchpotato/core/providers/movie/imdbapi/main.py +++ b/couchpotato/core/providers/movie/imdbapi/main.py @@ -89,7 +89,7 @@ class IMDBAPI(MovieProvider): 'poster': [movie.get('Poster', '')] if movie.get('Poster') and len(movie.get('Poster', '')) > 4 else [], }, 'rating': { - 'imdb': (tryFloat(movie.get('imdbRating', 0)), tryInt(movie.get('imdbVotes', ''))), + 'imdb': (tryFloat(movie.get('imdbRating', 0)), tryInt(movie.get('imdbVotes', '').replace(',', ''))), #'rotten': (tryFloat(movie.get('tomatoRating', 0)), tryInt(movie.get('tomatoReviews', 0))), }, 'imdb': str(movie.get('imdbID', '')), From 89d3b9b72afc598ee03deaebd99fb0060b156b10 Mon Sep 17 00:00:00 2001 From: Ruud Date: Sat, 30 Jun 2012 15:42:58 +0200 Subject: [PATCH 03/11] Log plex error. closes #512 --- couchpotato/core/notifications/plex/main.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/couchpotato/core/notifications/plex/main.py b/couchpotato/core/notifications/plex/main.py index ce0dc1a8..23fd39df 100644 --- a/couchpotato/core/notifications/plex/main.py +++ b/couchpotato/core/notifications/plex/main.py @@ -46,10 +46,13 @@ class Plex(Notification): def notify(self, message = '', data = {}, listener = None): if self.isDisabled(): return - for host in [x.strip() + ':3000' for x in self.conf('host').split(",")]: - self.send({'command': 'ExecBuiltIn', 'parameter': 'Notification(CouchPotato, %s)' % message}, host) + hosts = [x.strip() + ':3000' for x in self.conf('host').split(",")] + successful = 0 + for host in hosts: + if self.send({'command': 'ExecBuiltIn', 'parameter': 'Notification(CouchPotato, %s)' % message}, host): + successful += 1 - return True + return successful == len(hosts) def send(self, command, host): @@ -60,7 +63,7 @@ class Plex(Notification): try: self.urlopen(url, headers = headers, show_error = False) except: - log.error("Couldn't sent command to Plex") + log.error("Couldn't sent command to Plex: %s", traceback.format_exc()) return False log.info('Plex notification to %s successful.', host) From 0fc5c42aba56954f79fd25b04e100fc58d3b9b71 Mon Sep 17 00:00:00 2001 From: Ruud Date: Sat, 30 Jun 2012 19:03:53 +0200 Subject: [PATCH 04/11] Give error when datadir in appdir --- couchpotato/core/_base/_core/main.py | 7 +++++++ couchpotato/core/_base/updater/main.py | 7 +++++++ 2 files changed, 14 insertions(+) diff --git a/couchpotato/core/_base/_core/main.py b/couchpotato/core/_base/_core/main.py index bac1efed..2e5bc843 100644 --- a/couchpotato/core/_base/_core/main.py +++ b/couchpotato/core/_base/_core/main.py @@ -43,6 +43,7 @@ class Core(Plugin): addEvent('app.base_url', self.createBaseUrl) addEvent('app.api_url', self.createApiUrl) addEvent('app.version', self.version) + addEvent('app.load', self.checkDataDir) addEvent('setting.save.core.password', self.md5Password) addEvent('setting.save.core.api_key', self.checkApikey) @@ -54,6 +55,12 @@ class Core(Plugin): def checkApikey(self, value): return value if value and len(value) > 3 else uuid4().hex + def checkDataDir(self): + if Env.get('app_dir') in Env.get('data_dir'): + log.error('You should NOT use your CouchPotato directory to save your settings in. Files will get overwritten or be deleted.') + + return True + def available(self): return jsonified({ 'succes': True diff --git a/couchpotato/core/_base/updater/main.py b/couchpotato/core/_base/updater/main.py index f148b4bd..3717b90e 100644 --- a/couchpotato/core/_base/updater/main.py +++ b/couchpotato/core/_base/updater/main.py @@ -305,6 +305,13 @@ class SourceUpdater(BaseUpdater): except Exception, e: log.error('Failed overwriting file: %s', e) + if Env.get('app_dir') not in Env.get('data_dir'): + for still_exists in existing_files: + try: + os.remove(still_exists) + except: + log.error('Failed removing non-used file: %s', traceback.format_exc()) + def removeDir(self, path): try: From 3b441d2942b200e7d7123c64de818783be92917b Mon Sep 17 00:00:00 2001 From: Ruud Date: Sat, 30 Jun 2012 19:58:53 +0200 Subject: [PATCH 05/11] Encode html entities in log --- couchpotato/core/plugins/log/static/log.js | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/couchpotato/core/plugins/log/static/log.js b/couchpotato/core/plugins/log/static/log.js index 7a91d4cf..0e276b58 100644 --- a/couchpotato/core/plugins/log/static/log.js +++ b/couchpotato/core/plugins/log/static/log.js @@ -78,15 +78,16 @@ Page.Log = new Class({ addColors: function(text){ var self = this; - var text = new Element('div', { - 'html': text - }).get('text') - - text = text.replace(/\u001b\[31m/gi, '') - text = text.replace(/\u001b\[36m/gi, '') - text = text.replace(/\u001b\[33m/gi, '') - text = text.replace(/\u001b\[0m\n/gi, '') - text = text.replace(/\u001b\[0m/gi, '') + text = text + .replace(/&/g, '&') + .replace(//g, '>') + .replace(/"/g, '"') + .replace(/\u001b\[31m/gi, '') + .replace(/\u001b\[36m/gi, '') + .replace(/\u001b\[33m/gi, '') + .replace(/\u001b\[0m\n/gi, '') + .replace(/\u001b\[0m/gi, '') return '' + text + ''; } From cf3041c848ba02e124d3cc5636e809881777f0fc Mon Sep 17 00:00:00 2001 From: Ruud Date: Sat, 30 Jun 2012 21:25:36 +0200 Subject: [PATCH 06/11] Simple growl-like notifications --- couchpotato/core/notifications/core/main.py | 9 +++-- .../notifications/core/static/notification.js | 31 +++++++++++++-- couchpotato/core/plugins/movie/main.py | 4 +- .../core/plugins/movie/static/movie.js | 11 ++++-- couchpotato/core/plugins/searcher/main.py | 2 +- couchpotato/static/style/main.css | 38 ++++++++++++++++++- 6 files changed, 80 insertions(+), 15 deletions(-) diff --git a/couchpotato/core/notifications/core/main.py b/couchpotato/core/notifications/core/main.py index a37a6667..e0af50de 100644 --- a/couchpotato/core/notifications/core/main.py +++ b/couchpotato/core/notifications/core/main.py @@ -136,23 +136,24 @@ class CoreNotifier(Notification): #db.close() return True - def frontend(self, type = 'notification', data = {}): + def frontend(self, type = 'notification', data = {}, message = None): self.m_lock.acquire() - message = { + notification = { 'message_id': str(uuid.uuid4()), 'time': time.time(), 'type': type, 'data': data, + 'message': message, } - self.messages.append(message) + self.messages.append(notification) while len(self.listeners) > 0 and not self.shuttingDown(): try: listener, last_id = self.listeners.pop() listener({ 'success': True, - 'result': [message], + 'result': [notification], }) except: break diff --git a/couchpotato/core/notifications/core/static/notification.js b/couchpotato/core/notifications/core/static/notification.js index 8e6a52b8..d3811d4d 100644 --- a/couchpotato/core/notifications/core/static/notification.js +++ b/couchpotato/core/notifications/core/static/notification.js @@ -126,11 +126,12 @@ var NotificationBase = new Class({ processData: function(json){ var self = this; - // Process data if(json){ Array.each(json.result, function(result){ - App.fireEvent(result.type, result) + App.fireEvent(result.type, result); + if(result.message && result.read === undefined) + self.showMessage(result.message); }) if(json.result.length > 0) @@ -140,7 +141,31 @@ var NotificationBase = new Class({ // Restart poll self.startPoll() }, - + + showMessage: function(message){ + var self = this; + + if(!self.message_container) + self.message_container = new Element('div.messages').inject(document.body); + + var new_message = new Element('div.message', { + 'text': message + }).inject(self.message_container); + + setTimeout(function(){ + new_message.addClass('show') + }, 10); + + setTimeout(function(){ + new_message.addClass('hide') + setTimeout(function(){ + new_message.destroy(); + }, 1000); + }, 4000); + + }, + + // Notification setting tests addTestButtons: function(){ var self = this; diff --git a/couchpotato/core/plugins/movie/main.py b/couchpotato/core/plugins/movie/main.py index 3a7a7361..ab23a18c 100644 --- a/couchpotato/core/plugins/movie/main.py +++ b/couchpotato/core/plugins/movie/main.py @@ -240,7 +240,6 @@ class MoviePlugin(Plugin): db = get_session() for id in getParam('id').split(','): - fireEvent('notify.frontend', type = 'movie.busy.%s' % id, data = True) movie = db.query(Movie).filter_by(id = id).first() if movie: @@ -250,6 +249,7 @@ class MoviePlugin(Plugin): for title in movie.library.titles: if title.default: default_title = title.title + fireEvent('notify.frontend', type = 'movie.busy.%s' % id, data = True, message = 'Updating "%s"' % default_title) fireEventAsync('library.update', identifier = movie.library.identifier, default_title = default_title, force = True, on_complete = self.createOnComplete(id)) @@ -342,7 +342,7 @@ class MoviePlugin(Plugin): onComplete() if added: - fireEvent('notify.frontend', type = 'movie.added', data = movie_dict) + fireEvent('notify.frontend', type = 'movie.added', data = movie_dict, message = 'Successfully added "%s" to your wanted list.' % params.get('title', '')) #db.close() return movie_dict diff --git a/couchpotato/core/plugins/movie/static/movie.js b/couchpotato/core/plugins/movie/static/movie.js index b7849e6a..d71eb648 100644 --- a/couchpotato/core/plugins/movie/static/movie.js +++ b/couchpotato/core/plugins/movie/static/movie.js @@ -17,10 +17,13 @@ var Movie = new Class({ self.parent(self, options); App.addEvent('movie.update.'+data.id, self.update.bind(self)); - App.addEvent('movie.busy.'+data.id, function(notification){ - if(notification.data) - self.busy(true) - }); + + ['movie.busy', 'searcher.started'].each(function(listener){ + App.addEvent(listener+'.'+data.id, function(notification){ + if(notification.data) + self.busy(true) + }); + }) }, busy: function(set_busy){ diff --git a/couchpotato/core/plugins/searcher/main.py b/couchpotato/core/plugins/searcher/main.py index ce8deeb5..18e89320 100644 --- a/couchpotato/core/plugins/searcher/main.py +++ b/couchpotato/core/plugins/searcher/main.py @@ -84,7 +84,7 @@ class Searcher(Plugin): if not default_title: return - fireEvent('notify.frontend', type = 'searcher.started.%s' % movie['id'], data = True) + fireEvent('notify.frontend', type = 'searcher.started.%s' % movie['id'], data = True, message = 'Searching for "%s"' % default_title) ret = False for quality_type in movie['profile']['types']: diff --git a/couchpotato/static/style/main.css b/couchpotato/static/style/main.css index dd792b87..8524534a 100644 --- a/couchpotato/static/style/main.css +++ b/couchpotato/static/style/main.css @@ -601,4 +601,40 @@ body > .spinner, .mask{ } .more_menu .wrapper li a:hover { background: rgba(0,0,0,0.05); - } \ No newline at end of file + } + +.messages { + position: fixed; + right: 0; + bottom: 0; + padding: 2px; + width: 240px; + z-index: 2; +} + + .messages .message { + text-align: center; + border-radius: 2px; + margin: 2px 0 0 0; + height: 0; + overflow: hidden; + position: relative; + transition: all .4s cubic-bezier(0.9,0,0.1,1); + font-size: 12px; + box-shadow: 0 1px 1px rgba(0,0,0,0.35), inset 0 1px 0px rgba(255,255,255,0.20); + background-image: linear-gradient( + 270deg, + #5b9bd1 0%, + #406db8 100% + ); + } + .messages .message.show { + height: auto; + padding: 3px 5px; + min-height: 10px; + max-height: 400px; + } + .messages .message.hide { + right: -240px; + opacity: 0; + } \ No newline at end of file From c87a84e66827e64af7da7e8e9582d7de761595cd Mon Sep 17 00:00:00 2001 From: Ruud Date: Sat, 30 Jun 2012 22:06:53 +0200 Subject: [PATCH 07/11] Styling cleanup --- .../static/scripts/library/prefix_free.js | 72 +++++++++++++------ couchpotato/static/style/main.css | 43 +++-------- couchpotato/static/style/page/settings.css | 47 +++--------- couchpotato/templates/_desktop.html | 2 - 4 files changed, 68 insertions(+), 96 deletions(-) diff --git a/couchpotato/static/scripts/library/prefix_free.js b/couchpotato/static/scripts/library/prefix_free.js index 4876187b..a918d048 100644 --- a/couchpotato/static/scripts/library/prefix_free.js +++ b/couchpotato/static/scripts/library/prefix_free.js @@ -1,5 +1,5 @@ /** - * StyleFix 1.0.2 + * StyleFix 1.0.3 * @author Lea Verou * MIT license */ @@ -52,8 +52,10 @@ var self = window.StyleFix = { }); // behavior URLs shoudn’t be converted (Issue #19) - css = css.replace(RegExp('\\b(behavior:\\s*?url\\(\'?"?)' + base, 'gi'), '$1'); - } + // base should be escaped before added to RegExp (Issue #81) + var escaped_base = base.replace(/([\\\^\$*+[\]?{}.=!:(|)])/g,"\\$1"); + css = css.replace(RegExp('\\b(behavior:\\s*?url\\(\'?"?)' + escaped_base, 'gi'), '$1'); + } var style = document.createElement('style'); style.textContent = css; @@ -63,6 +65,8 @@ var self = window.StyleFix = { parent.insertBefore(style, link); parent.removeChild(link); + + style.media = link.media; // Duplicate is intentional. See issue #31 } }; @@ -84,6 +88,9 @@ var self = window.StyleFix = { }, styleElement: function(style) { + if (style.hasAttribute('data-noprefix')) { + return; + } var disabled = style.disabled; style.textContent = self.fix(style.textContent, true, style); @@ -150,7 +157,7 @@ function $(expr, con) { })(); /** - * PrefixFree 1.0.5 + * PrefixFree 1.0.6 * @author Lea Verou * MIT license */ @@ -160,36 +167,39 @@ if(!window.StyleFix || !window.getComputedStyle) { return; } +// Private helper +function fix(what, before, after, replacement, css) { + what = self[what]; + + if(what.length) { + var regex = RegExp(before + '(' + what.join('|') + ')' + after, 'gi'); + + css = css.replace(regex, replacement); + } + + return css; +} + var self = window.PrefixFree = { prefixCSS: function(css, raw) { var prefix = self.prefix; - function fix(what, before, after, replacement) { - what = self[what]; - - if(what.length) { - var regex = RegExp(before + '(' + what.join('|') + ')' + after, 'gi'); - - css = css.replace(regex, replacement); - } - } - - fix('functions', '(\\s|:|,)', '\\s*\\(', '$1' + prefix + '$2('); - fix('keywords', '(\\s|:)', '(\\s|;|\\}|$)', '$1' + prefix + '$2$3'); - fix('properties', '(^|\\{|\\s|;)', '\\s*:', '$1' + prefix + '$2:'); + css = fix('functions', '(\\s|:|,)', '\\s*\\(', '$1' + prefix + '$2(', css); + css = fix('keywords', '(\\s|:)', '(\\s|;|\\}|$)', '$1' + prefix + '$2$3', css); + css = fix('properties', '(^|\\{|\\s|;)', '\\s*:', '$1' + prefix + '$2:', css); // Prefix properties *inside* values (issue #8) if (self.properties.length) { var regex = RegExp('\\b(' + self.properties.join('|') + ')(?!:)', 'gi'); - fix('valueProperties', '\\b', ':(.+?);', function($0) { + css = fix('valueProperties', '\\b', ':(.+?);', function($0) { return $0.replace(regex, prefix + "$1") - }); + }, css); } if(raw) { - fix('selectors', '', '\\b', self.prefixSelector); - fix('atrules', '@', '\\b', '@' + prefix + '$1'); + css = fix('selectors', '', '\\b', self.prefixSelector, css); + css = fix('atrules', '@', '\\b', '@' + prefix + '$1', css); } // Fix double prefixing @@ -198,11 +208,25 @@ var self = window.PrefixFree = { return css; }, - // Warning: prefixXXX functions prefix no matter what, even if the XXX is supported prefix-less + property: function(property) { + return (self.properties.indexOf(property)? self.prefix : '') + property; + }, + + value: function(value, property) { + value = fix('functions', '(^|\\s|,)', '\\s*\\(', '$1' + self.prefix + '$2(', value); + value = fix('keywords', '(^|\\s)', '(\\s|$)', '$1' + self.prefix + '$2$3', value); + + // TODO properties inside values + + return value; + }, + + // Warning: Prefixes no matter what, even if the selector is supported prefix-less prefixSelector: function(selector) { return selector.replace(/^:{1,2}/, function($0) { return $0 + self.prefix }) }, + // Warning: Prefixes no matter what, even if the property is supported prefix-less prefixProperty: function(property, camelCase) { var prefixed = self.prefix + property; @@ -334,7 +358,9 @@ var keywords = { 'zoom-out': 'cursor', 'box': 'display', 'flexbox': 'display', - 'inline-flexbox': 'display' + 'inline-flexbox': 'display', + 'flex': 'display', + 'inline-flex': 'display' }; self.functions = []; diff --git a/couchpotato/static/style/main.css b/couchpotato/static/style/main.css index 8524534a..4f4475ac 100644 --- a/couchpotato/static/style/main.css +++ b/couchpotato/static/style/main.css @@ -21,9 +21,9 @@ body { } * { - -moz-box-sizing: border-box; - -webkit-box-sizing: border-box; - box-sizing: border-box; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; } pre { @@ -267,10 +267,9 @@ body > .spinner, .mask{ font-size: 8px; margin: -5px 0 0 15px; box-shadow: inset 0 1px 0 rgba(255,255,255,.6), 0 0 3px rgba(0,0,0,.7); - background: -webkit-gradient(linear, left bottom, left top, from(rgba(255,255,255,.3)), to(rgba(255,255,255,.1))); - background: -moz-linear-gradient(center bottom, rgba(255,255,255,.3) 0%, rgba(255,255,255,.1) 100%); background-color: #1b79b8; text-shadow: none; + background-image: linear-gradient(0deg, rgba(255,255,255,.3) 0%, rgba(255,255,255,.1) 100%); } .header .notification_menu .wrapper { @@ -354,16 +353,8 @@ body > .spinner, .mask{ border-radius:30px; box-shadow: 0 1px 1px rgba(0,0,0,0.35), inset 0 1px 0px rgba(255,255,255,0.20); - - background: url('../images/sprite.png') no-repeat 94% -53px, -webkit-gradient( - linear, - left bottom, - left top, - color-stop(0, #406db8), - color-stop(1, #5b9bd1) - ); - background: url('../images/sprite.png') no-repeat 94% -53px, -moz-linear-gradient( - center top, + background: url('../images/sprite.png') no-repeat 94% -53px, linear-gradient( + 270deg, #5b9bd1 0%, #406db8 100% ); @@ -448,15 +439,8 @@ body > .spinner, .mask{ border: 1px solid #252930; box-shadow: inset 0 1px 0px rgba(255,255,255,0.20), 0 0 3px rgba(0,0,0, 0.2); background: rgb(55,62,74); - background-image: -webkit-gradient( - linear, - left bottom, - left top, - color-stop(0, rgb(55,62,74)), - color-stop(1, rgb(73,83,98)) - ); - background-image: -moz-linear-gradient( - center bottom, + background-image: linear-gradient( + 90deg, rgb(55,62,74) 0%, rgb(73,83,98) 100% ); @@ -544,15 +528,8 @@ body > .spinner, .mask{ text-align: center; color: #000; text-shadow: none; - background-image: -webkit-gradient( - linear, - left bottom, - right top, - color-stop(0, rgb(200,200,200)), - color-stop(1, rgb(255,255,255)) - ); - background-image: -moz-linear-gradient( - left bottom, + background-image: linear-gradient( + 45deg, rgb(200,200,200) 0%, rgb(255,255,255) 100% ); diff --git a/couchpotato/static/style/page/settings.css b/couchpotato/static/style/page/settings.css index e814ddfd..b7fbaabf 100644 --- a/couchpotato/static/style/page/settings.css +++ b/couchpotato/static/style/page/settings.css @@ -16,17 +16,9 @@ padding: 40px 0; margin: 0; min-height: 470px; - - background-image: -webkit-gradient( - linear, - right top, - 40% 4%, - color-stop(0, rgba(0,0,0, 0.3)), - color-stop(1, rgba(0,0,0, 0)) - ); - background-image: -moz-linear-gradient( - 10% 0% 16deg, - rgba(0,0,0,0) 0%, + background-image: linear-gradient( + 20deg, + rgba(0,0,0,0) 50%, rgba(0,0,0,0.3) 100% ); } @@ -364,30 +356,16 @@ border-radius: 2px; } .page .tag_input > ul:hover > li.choice { - background: -webkit-gradient( - linear, - left bottom, - left top, - color-stop(0, rgba(255,255,255,0.1)), - color-stop(1, rgba(255,255,255,0.3)) - ); - background: -moz-linear-gradient( - center top, + background: linear-gradient( + 270deg, rgba(255,255,255,0.3) 0%, rgba(255,255,255,0.1) 100% ); } .page .tag_input > ul > li.choice:hover, .page .tag_input > ul > li.choice.selected { - background: -webkit-gradient( - linear, - left bottom, - left top, - color-stop(0, #406db8), - color-stop(1, #5b9bd1) - ); - background: -moz-linear-gradient( - center top, + background: linear-gradient( + 270deg, #5b9bd1 0%, #406db8 100% ); @@ -425,15 +403,8 @@ margin: -9px 0 0 -16px; border-radius: 30px 30px 0 0; cursor: pointer; - background: url('../../images/icon.delete.png') no-repeat center 2px, -webkit-gradient( - linear, - left bottom, - left top, - color-stop(0, #5b9bd1), - color-stop(1, #5b9bd1) - ); - background: url('../../images/icon.delete.png') no-repeat center 2px, -moz-linear-gradient( - center top, + background: url('../../images/icon.delete.png') no-repeat center 2px, -webkit-linear-gradient( + 270deg, #5b9bd1 0%, #5b9bd1 100% ); diff --git a/couchpotato/templates/_desktop.html b/couchpotato/templates/_desktop.html index f66e3b4c..0c228dca 100644 --- a/couchpotato/templates/_desktop.html +++ b/couchpotato/templates/_desktop.html @@ -10,9 +10,7 @@ - {% if not env.get('dev') %} - {% endif %} From 6c8b6a749f5fd88dd961b93a60164d6e6e235fbd Mon Sep 17 00:00:00 2001 From: Ruud Date: Sat, 30 Jun 2012 22:32:19 +0200 Subject: [PATCH 08/11] Message didn't animate in Firefox --- couchpotato/static/style/main.css | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/couchpotato/static/style/main.css b/couchpotato/static/style/main.css index 4f4475ac..d86fbbd6 100644 --- a/couchpotato/static/style/main.css +++ b/couchpotato/static/style/main.css @@ -581,12 +581,15 @@ body > .spinner, .mask{ } .messages { - position: fixed; + position: absolute; right: 0; bottom: 0; padding: 2px; width: 240px; z-index: 2; + overflow: hidden; + font-size: 14px; + font-weight: bold; } .messages .message { @@ -595,23 +598,27 @@ body > .spinner, .mask{ margin: 2px 0 0 0; height: 0; overflow: hidden; - position: relative; - transition: all .4s cubic-bezier(0.9,0,0.1,1); - font-size: 12px; + transition: all .6s cubic-bezier(0.9,0,0.1,1); box-shadow: 0 1px 1px rgba(0,0,0,0.35), inset 0 1px 0px rgba(255,255,255,0.20); background-image: linear-gradient( 270deg, #5b9bd1 0%, #406db8 100% ); + width: 100%; + padding: 0 5px; + visibility: hidden; + max-height: 0; } .messages .message.show { + visibility: visible; height: auto; - padding: 3px 5px; - min-height: 10px; - max-height: 400px; + padding-top: 3px; + padding-bottom: 3px; + min-height: 1px; + max-height: 400px; } .messages .message.hide { - right: -240px; + margin-left: 240px; opacity: 0; } \ No newline at end of file From c274867571b32fcfbaef04bd3869c175148dbd7e Mon Sep 17 00:00:00 2001 From: Ruud Date: Sun, 1 Jul 2012 00:43:34 +0200 Subject: [PATCH 09/11] Use settings datadir again. fix #518 --- CouchPotato.py | 3 +-- couchpotato/runner.py | 19 +++++++++++++------ 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/CouchPotato.py b/CouchPotato.py index 1c16275e..21b208a2 100755 --- a/CouchPotato.py +++ b/CouchPotato.py @@ -37,10 +37,9 @@ class Loader(object): # Create data dir if needed if self.options.data_dir: self.data_dir = self.options.data_dir - else: self.data_dir = os.path.expanduser(Env.setting('data_dir')) - + if self.data_dir == '': self.data_dir = getDataDir() diff --git a/couchpotato/runner.py b/couchpotato/runner.py index 5f838c71..31a8ce32 100644 --- a/couchpotato/runner.py +++ b/couchpotato/runner.py @@ -20,14 +20,12 @@ import warnings def getOptions(base_path, args): - data_dir = getDataDir() - # Options parser = ArgumentParser(prog = 'CouchPotato.py') - parser.add_argument('--config_file', default = os.path.join(data_dir, 'settings.conf'), - dest = 'config_file', help = 'Absolute or ~/ path of the settings file (default ./_data/settings.conf)') - parser.add_argument('--data_dir', default = data_dir, + parser.add_argument('--data_dir', dest = 'data_dir', help = 'Absolute or ~/ path of the data dir') + parser.add_argument('--config_file', + dest = 'config_file', help = 'Absolute or ~/ path of the settings file (default DATA_DIR/settings.conf)') parser.add_argument('--debug', action = 'store_true', dest = 'debug', help = 'Debug mode') parser.add_argument('--console_log', action = 'store_true', @@ -36,12 +34,21 @@ def getOptions(base_path, args): dest = 'quiet', help = 'No console logging') parser.add_argument('--daemon', action = 'store_true', dest = 'daemon', help = 'Daemonize the app') - parser.add_argument('--pid_file', default = os.path.join(data_dir, 'couchpotato.pid'), + parser.add_argument('--pid_file', dest = 'pid_file', help = 'Path to pidfile needed for daemon') options = parser.parse_args(args) + data_dir = os.path.expanduser(options.data_dir if options.data_dir else getDataDir()) + + if not options.config_file: + options.config_file = os.path.join(data_dir, 'settings.conf') + + if not options.pid_file: + options.pid_file = os.path.join(data_dir, 'couchpotato.pid') + options.config_file = os.path.expanduser(options.config_file) + options.pid_file = os.path.expanduser(options.pid_file) return options From f15351aa73ccac33747fedd85b264bf6b41dc203 Mon Sep 17 00:00:00 2001 From: Ruud Date: Sun, 1 Jul 2012 00:48:44 +0200 Subject: [PATCH 10/11] Not restarting after update --- couchpotato/core/_base/_core/main.py | 5 ++++- couchpotato/core/_base/updater/main.py | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/couchpotato/core/_base/_core/main.py b/couchpotato/core/_base/_core/main.py index 2e5bc843..58bd1d19 100644 --- a/couchpotato/core/_base/_core/main.py +++ b/couchpotato/core/_base/_core/main.py @@ -18,7 +18,10 @@ log = CPLog(__name__) class Core(Plugin): - ignore_restart = ['Core.restart', 'Core.shutdown', 'Updater.check'] + ignore_restart = [ + 'Core.restart', 'Core.shutdown', + 'Updater.check', 'Updater.autoUpdate', + ] shutdown_started = False def __init__(self): diff --git a/couchpotato/core/_base/updater/main.py b/couchpotato/core/_base/updater/main.py index 3717b90e..1ecb6b40 100644 --- a/couchpotato/core/_base/updater/main.py +++ b/couchpotato/core/_base/updater/main.py @@ -66,6 +66,10 @@ class Updater(Plugin): fireEventAsync('app.restart') + return True + + return False + def check(self): if self.isDisabled(): return @@ -171,7 +175,6 @@ class GitUpdater(BaseUpdater): self.repo.saveStash() log.info('Updating to latest version') - info = self.info() self.repo.pull() # Delete leftover .pyc files From 6162ea9f429536fa6de1e56bb4674740f5a4a615 Mon Sep 17 00:00:00 2001 From: Ruud Date: Sun, 1 Jul 2012 00:49:07 +0200 Subject: [PATCH 11/11] Give feedback if no update --- .../core/_base/updater/static/updater.js | 6 ++++-- .../notifications/core/static/notification.js | 17 +++++++++-------- couchpotato/static/scripts/couchpotato.js | 2 +- 3 files changed, 14 insertions(+), 11 deletions(-) diff --git a/couchpotato/core/_base/updater/static/updater.js b/couchpotato/core/_base/updater/static/updater.js index fe0a632c..df6cf351 100644 --- a/couchpotato/core/_base/updater/static/updater.js +++ b/couchpotato/core/_base/updater/static/updater.js @@ -22,8 +22,10 @@ var UpdaterBase = new Class({ if(json.update_available) self.doUpdate(); - else - App.unBlockPage() + else { + App.unBlockPage(); + App.fireEvent('message', 'No updates available'); + } } }) diff --git a/couchpotato/core/notifications/core/static/notification.js b/couchpotato/core/notifications/core/static/notification.js index d3811d4d..595a39ed 100644 --- a/couchpotato/core/notifications/core/static/notification.js +++ b/couchpotato/core/notifications/core/static/notification.js @@ -11,6 +11,7 @@ var NotificationBase = new Class({ App.addEvent('unload', self.stopPoll.bind(self)); App.addEvent('reload', self.startInterval.bind(self, [true])); App.addEvent('notification', self.notify.bind(self)); + App.addEvent('message', self.showMessage.bind(self)); // Add test buttons to settings page App.addEvent('load', self.addTestButtons.bind(self)); @@ -86,7 +87,7 @@ var NotificationBase = new Class({ startInterval: function(force){ var self = this; - + if(self.stopped && !force){ self.stopped = false; return; @@ -141,30 +142,30 @@ var NotificationBase = new Class({ // Restart poll self.startPoll() }, - + showMessage: function(message){ var self = this; - + if(!self.message_container) self.message_container = new Element('div.messages').inject(document.body); - + var new_message = new Element('div.message', { 'text': message }).inject(self.message_container); - + setTimeout(function(){ new_message.addClass('show') }, 10); - + setTimeout(function(){ new_message.addClass('hide') setTimeout(function(){ new_message.destroy(); }, 1000); }, 4000); - + }, - + // Notification setting tests addTestButtons: function(){ var self = this; diff --git a/couchpotato/static/scripts/couchpotato.js b/couchpotato/static/scripts/couchpotato.js index 9a15bbab..c0860a99 100644 --- a/couchpotato/static/scripts/couchpotato.js +++ b/couchpotato/static/scripts/couchpotato.js @@ -80,7 +80,7 @@ var CouchPotato = new Class({ } }), new Element('a', { - 'text': 'Check for updates', + 'text': 'Update to latest', 'events': { 'click': self.checkForUpdate.bind(self, null) }