From 1964f74f19643c0127caaafafc24a3e2aaf1076f Mon Sep 17 00:00:00 2001
From: Fabio Manganiello <blacklight86@gmail.com>
Date: Sat, 22 Jun 2019 19:05:17 +0200
Subject: [PATCH] New media webplugin WIP

---
 .../backend/http/media/handlers/__init__.py   |  5 ++--
 .../static/js/plugins/media/handlers/file.js  | 30 +++++++++++++++++++
 .../js/plugins/media/handlers/torrent.js      | 13 ++++++++
 .../js/plugins/media/handlers/youtube.js      |  9 ++++++
 .../http/static/js/plugins/media/index.js     | 22 ++++++++++++--
 .../js/plugins/media/players/browser.js       |  2 +-
 .../http/static/js/plugins/media/search.js    | 27 +++++++++++++++--
 .../http/templates/plugins/media/search.html  |  2 +-
 8 files changed, 99 insertions(+), 11 deletions(-)

diff --git a/platypush/backend/http/media/handlers/__init__.py b/platypush/backend/http/media/handlers/__init__.py
index 717fbb3ce..8c1f05e83 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 0275ddb41..6d71ce231 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 d5211bff9..490fe0299 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 1b5270533..99925ba8f 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 4745c90cf..97753eda5 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 0ceb18b04..fd8bd3ff3 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 09262bf3f..15520f40c 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 887bfaae9..bb1f44958 100644
--- a/platypush/backend/http/templates/plugins/media/search.html
+++ b/platypush/backend/http/templates/plugins/media/search.html
@@ -10,7 +10,7 @@
             </button>
 
             <input type="text" name="query" v-model.lazy.trim="query"
-                   :disabled="searching" placeholder="Search query or video URL">
+                   :disabled="searching" placeholder="Search query or media URL">
 
             <button type="submit" :disabled="searching" title="Search">
                 <i class="fa fa-search"></i>