diff --git a/platypush/backend/http/media/handlers/__init__.py b/platypush/backend/http/media/handlers/__init__.py index 717fbb3c..8c1f05e8 100644 --- a/platypush/backend/http/media/handlers/__init__.py +++ b/platypush/backend/http/media/handlers/__init__.py @@ -1,8 +1,5 @@ import logging -from .file import FileHandler - - class MediaHandler: """ Abstract class to manage media handlers that can be streamed over the HTTP @@ -63,6 +60,8 @@ class MediaHandler: yield (attr, getattr(self, attr)) +from .file import FileHandler + __all__ = ['MediaHandler', 'FileHandler'] diff --git a/platypush/backend/http/static/js/plugins/media/handlers/file.js b/platypush/backend/http/static/js/plugins/media/handlers/file.js index 0275ddb4..6d71ce23 100644 --- a/platypush/backend/http/static/js/plugins/media/handlers/file.js +++ b/platypush/backend/http/static/js/plugins/media/handlers/file.js @@ -38,6 +38,17 @@ MediaHandlers.file = Vue.extend({ }, methods: { + matchesUrl: function(url) { + return !!url.match('^(file://)?/'); + }, + + getMetadata: function(url) { + return { + url: url, + title: url.split('/').pop(), + }; + }, + play: function(item) { this.bus.$emit('play', item); }, @@ -53,3 +64,22 @@ MediaHandlers.file = Vue.extend({ }, }); +MediaHandlers.generic = MediaHandlers.file.extend({ + props: { + bus: { type: Object }, + iconClass: { + type: String, + default: 'fa fa-globe', + }, + }, + + methods: { + getMetadata: function(url) { + return { + url: url, + title: url, + }; + }, + }, +}); + diff --git a/platypush/backend/http/static/js/plugins/media/handlers/torrent.js b/platypush/backend/http/static/js/plugins/media/handlers/torrent.js index d5211bff..490fe029 100644 --- a/platypush/backend/http/static/js/plugins/media/handlers/torrent.js +++ b/platypush/backend/http/static/js/plugins/media/handlers/torrent.js @@ -32,6 +32,19 @@ MediaHandlers.torrent = Vue.extend({ }, methods: { + matchesUrl: function(url) { + return !!( + url.match('^magnet:?') || + url.match('^https?://.*\.torrent$') || + url.match('^(file://)?/.*\.torrent$') + ); + }, + + getMetadata: function(url) { + // TODO + return {}; + }, + play: function(item) { }, diff --git a/platypush/backend/http/static/js/plugins/media/handlers/youtube.js b/platypush/backend/http/static/js/plugins/media/handlers/youtube.js index 1b527053..99925ba8 100644 --- a/platypush/backend/http/static/js/plugins/media/handlers/youtube.js +++ b/platypush/backend/http/static/js/plugins/media/handlers/youtube.js @@ -32,6 +32,15 @@ MediaHandlers.youtube = Vue.extend({ }, methods: { + matchesUrl: function(url) { + return !!(url.match('^https?://(www\.)?youtube.com/') || url.match('^https?://youtu.be/')); + }, + + getMetadata: function(url) { + // TODO + return {}; + }, + play: function(item) { }, diff --git a/platypush/backend/http/static/js/plugins/media/index.js b/platypush/backend/http/static/js/plugins/media/index.js index 4745c90c..97753eda 100644 --- a/platypush/backend/http/static/js/plugins/media/index.js +++ b/platypush/backend/http/static/js/plugins/media/index.js @@ -60,13 +60,29 @@ Vue.component('media', { }, onResultsReady: function(results) { - this.loading.results = false; + for (const result of results) { + if (result.type && MediaHandlers[result.type]) { + result.handler = MediaHandlers[result.type]; + } else { + result.type = 'generic'; + result.handler = MediaHandlers.generic; - for (var i=0; i < results.length; i++) { - results[i].handler = MediaHandlers[results[i].type]; + for (const [handlerType, handler] of Object.entries(MediaHandlers)) { + if (handler.matchesUrl && handler.matchesUrl(result.url)) { + result.type = handlerType; + result.handler = handler; + break; + } + } + } + + Object.entries(result.handler.getMetadata(result.url)).forEach(entry => { + Vue.set(result, entry[0], entry[1]); + }); } this.results = results; + this.loading.results = false; }, play: async function(item) { diff --git a/platypush/backend/http/static/js/plugins/media/players/browser.js b/platypush/backend/http/static/js/plugins/media/players/browser.js index 0ceb18b0..fd8bd3ff 100644 --- a/platypush/backend/http/static/js/plugins/media/players/browser.js +++ b/platypush/backend/http/static/js/plugins/media/players/browser.js @@ -21,7 +21,7 @@ MediaPlayers.browser = Vue.extend({ iconClass: { type: String, - default: 'fa fa-laptop', + default: 'fa fa-browser', }, }, diff --git a/platypush/backend/http/static/js/plugins/media/search.js b/platypush/backend/http/static/js/plugins/media/search.js index 09262bf3..15520f40 100644 --- a/platypush/backend/http/static/js/plugins/media/search.js +++ b/platypush/backend/http/static/js/plugins/media/search.js @@ -19,10 +19,31 @@ Vue.component('media-search', { }, methods: { - search: async function(event) { - const types = Object.entries(this.types).filter(t => t[1]).map(t => t[0]); - var results = []; + isUrl: function(query) { + const match = query.match('^([^:]+)://'); + if (match) { + let protocol = match[1]; + if (protocol === 'https') + protocol = 'http'; + return protocol; + } + }, + + search: async function(event) { + const types = Object.entries(this.types).filter(t => t[0] !== 'generic' && t[1]).map(t => t[0]); + const protocol = this.isUrl(this.query); + + if (protocol) { + this.bus.$emit('results-ready', [{ + type: protocol, + url: this.query, + }]); + + return; + } + + var results = []; this.searching = true; this.bus.$emit('results-loading'); diff --git a/platypush/backend/http/templates/plugins/media/search.html b/platypush/backend/http/templates/plugins/media/search.html index 887bfaae..bb1f4495 100644 --- a/platypush/backend/http/templates/plugins/media/search.html +++ b/platypush/backend/http/templates/plugins/media/search.html @@ -10,7 +10,7 @@ + :disabled="searching" placeholder="Search query or media URL">