From cd49f22d5c373fc7ea0f312fada5fe1a5c748d67 Mon Sep 17 00:00:00 2001 From: Fabio Manganiello Date: Sat, 9 Feb 2019 01:53:14 +0100 Subject: [PATCH] Introduced floating panel with options on element click instead of the double-click-to-play logic on media elements --- platypush/backend/http/static/css/media.css | 24 ++- .../backend/http/static/js/application.js | 33 ++++ platypush/backend/http/static/js/media.js | 151 ++++++++++++------ .../backend/http/templates/plugins/media.html | 20 ++- 4 files changed, 161 insertions(+), 67 deletions(-) diff --git a/platypush/backend/http/static/css/media.css b/platypush/backend/http/static/css/media.css index 03dc3d2d..0a6f6799 100644 --- a/platypush/backend/http/static/css/media.css +++ b/platypush/backend/http/static/css/media.css @@ -77,18 +77,12 @@ form#video-ctrl { 100% { background: #d4ffe3; } } - button.remote[data-panel-toggle="#media-devices-panel"] { + button.remote[data-panel="#media-devices-panel"] { color: #34b868; } - button.selected[data-panel-toggle="#media-devices-panel"] { - box-shadow: inset 0 2px 0 rgba(0,0,0,0.1), - inset 3px 0 0 rgba(0,0,0,0.1), - inset 0 0 2px rgba(0,0,0,0.1), - inset 0 0 0 1px rgba(0,0,0,0.1); - } - -#media-devices-panel { +#media-devices-panel, +#media-item-panel { display: none; position: absolute; padding: 1rem; @@ -112,7 +106,8 @@ form#video-ctrl { right: .5rem; } - #media-devices-panel * > .cast-device { + #media-devices-panel * > .cast-device, + #media-item-panel > .media-item-action { padding: 0.5rem; cursor: pointer; } @@ -128,16 +123,19 @@ form#video-ctrl { } #media-devices-panel * > .cast-device.disabled, - #media-devices-panel * > .refresh-devices.disabled { + #media-devices-panel * > .refresh-devices.disabled, + #media-item-panel > .media-item-action.disabled { cursor: default; color: #999 !important; } - #media-devices-panel * > .cast-device:hover { + #media-devices-panel * > .cast-device:hover, + #media-item-panel > .media-item-action:hover { background-color: #daf8e2 !important; } - #media-devices-panel * > .cast-device-icon { + #media-devices-panel * > .cast-device-icon + #media-item-panel > .media-item-item { color: #666; } diff --git a/platypush/backend/http/static/js/application.js b/platypush/backend/http/static/js/application.js index dc1d58a2..b14a542f 100644 --- a/platypush/backend/http/static/js/application.js +++ b/platypush/backend/http/static/js/application.js @@ -184,16 +184,49 @@ $(document).ready(function() { }); }; + var initPanelOpenBindings = function() { + $('body').on('mouseup touchend', '[data-panel]', function(event) { + var $source = $(event.target); + var $panel = $($source.data('panel')); + setTimeout(() => { + $panel.show(); + }, 200); + }); + }; + + var initPanelCloseBindings = function() { + $('body').on('mouseup touchend', function(event) { + var $source = $(event.target); + if ($source.data('panel') || $source.parents('[data-panel]').length) { + var $panel = $source.data('panel') ? $($source.data('panel')) : + $($source.parents('[data-panel]').data('panel')); + $panel.toggle(); + return; + } + + if (!$source.parents('.panel').length + && !$source.data('panel')) { + $('.panel').filter(':visible').hide(); + } + }); + }; + var initModals = function() { initModalOpenBindings(); initModalCloseBindings(); }; + var initPanels = function() { + initPanelOpenBindings(); + initPanelCloseBindings(); + }; + var init = function() { initWebsocket(); initElements(); initDateTime(); initModals(); + initPanels(); }; window.registerEventListener = registerEventListener; diff --git a/platypush/backend/http/static/js/media.js b/platypush/backend/http/static/js/media.js index e449459a..105342f5 100644 --- a/platypush/backend/http/static/js/media.js +++ b/platypush/backend/http/static/js/media.js @@ -6,12 +6,14 @@ $(document).ready(function() { $ctrlForm = $('#video-ctrl'), $devsPanel = $('#media-devices-panel'), $devsList = $devsPanel.find('.devices-list'), - $devsBtn = $('button[data-panel-toggle="#media-devices-panel"]'), + $devsBtn = $('button[data-panel="#media-devices-panel"]'), $devsBtnIcon = $('#media-devices-panel-icon'), $devsRefreshBtn = $devsPanel.find('.refresh-devices'), $searchBarContainer = $('#media-search-bar-container'), $mediaBtnsContainer = $('#media-btns-container'), - prevVolume = undefined; + $mediaItemPanel = $('#media-item-panel'), + prevVolume = undefined, + selectedResource = undefined; var updateVideoResults = function(videos) { $videoResults.html(''); @@ -19,6 +21,7 @@ $(document).ready(function() { var $videoResult = $('
') .addClass('video-result') .attr('data-url', video['url']) + .attr('data-panel', '#media-item-panel') .html('title' in video ? video['title'] : video['url']); var $icon = getVideoIconByUrl(video['url']); @@ -132,6 +135,67 @@ $(document).ready(function() { }); }; + var play = function(resource) { + return new Promise((resolve, reject) => { + var results = $videoResults.html(); + var onVideoLoading = function() { + $videoResults.text('Loading video...'); + }; + + var onVideoReady = function() { + $videoResults.html(results); + }; + + var requestArgs = { + type: 'request', + action: 'media.play', + args: { resource: resource }, + }; + + var selectedDevice = getSelectedDevice(); + if (selectedDevice.isBrowser) { + onVideoLoading(); + + startStreaming(resource) + .then((url) => { + window.open(url, '_blank'); + resolve(url); + }) + .catch((xhr, status, error) => { + reject(xhr.responseText); + }) + .finally(() => { + onVideoReady(); + }); + + return; + } + + if (selectedDevice.isRemote) { + requestArgs.action = 'media.chromecast.play'; + requestArgs.args.chromecast = selectedDevice.name; + } + + onVideoLoading(); + execute( + requestArgs, + function(response) { + $videoResults.html(results); + resolve(resource); + }, + + function(xhr, status, error) { + onVideoReady(); + reject(xhr.responseText); + } + ); + }); + }; + + var download = function(resource) { + // TODO + }; + var initBindings = function() { $searchForm.on('submit', function(event) { var $input = $(this).find('input[name=video-search-text]'); @@ -221,66 +285,29 @@ $(document).ready(function() { ); }); - $videoResults.on('click touch', '.video-result', function(evt) { - var results = $videoResults.html(); + $videoResults.on('mousedown touchstart', '.video-result', function() { + selectedResource = $(this).data('url'); + }); + + $videoResults.on('mouseup touchend', '.video-result', function(event) { var $item = $(this); - if (!$item.hasClass('selected')) { - $item.siblings().removeClass('selected'); - $item.addClass('selected'); - return false; + var resource = $item.data('url'); + if (resource !== selectedResource) { + return; // Did not really click this item } - var onVideoLoading = function() { - $videoResults.text('Loading video...'); - }; + $item.siblings().removeClass('selected'); + $item.addClass('selected'); - var onVideoReady = function() { - $videoResults.html(results); - }; - - var resource = $item.data('url') - var requestArgs = { - type: 'request', - action: 'media.play', - args: { resource: resource }, - }; - - var selectedDevice = getSelectedDevice(); - if (selectedDevice.isBrowser) { - onVideoLoading(); - - startStreaming(resource) - .then((url) => { window.open(url, '_blank'); }) - .finally(() => { onVideoReady(); }); - - return; - } - - if (selectedDevice.isRemote) { - requestArgs.action = 'media.chromecast.play'; - requestArgs.args.chromecast = selectedDevice.name; - } - - onVideoLoading(); - execute( - requestArgs, - function() { - $videoResults.html(results); - $item.siblings().removeClass('active'); - $item.addClass('active'); - }, - - function() { - onVideoReady(); - } - ); + $mediaItemPanel.css('top', (event.clientY + $(window).scrollTop()) + 'px'); + $mediaItemPanel.css('left', (event.clientX + $(window).scrollLeft()) + 'px'); + $mediaItemPanel.data('resource', resource); }); $devsBtn.on('click touch', function() { $(this).toggleClass('selected'); $devsPanel.css('top', ($(this).position().top + $(this).outerHeight()) + 'px'); $devsPanel.css('left', ($(this).position().left) + 'px'); - $devsPanel.toggle(); return false; }); @@ -318,6 +345,26 @@ $(document).ready(function() { $(this).addClass('disabled'); initRemoteDevices(); }); + + $mediaItemPanel.on('click', '[data-action]', function() { + if ($(this).hasClass('disabled')) { + return; + } + + var action = $(this).data('action'); + var resource = $mediaItemPanel.data('resource'); + if (!resource) { + return; + } + + $mediaItemPanel.hide(); + $mediaItemPanel.find('[data-action]').addClass('disabled'); + + eval(action)($mediaItemPanel.data('resource')) + .finally(() => { + $mediaItemPanel.find('[data-action]').removeClass('disabled'); + }); + }); }; var initRemoteDevices = function() { diff --git a/platypush/backend/http/templates/plugins/media.html b/platypush/backend/http/templates/plugins/media.html index 51ae8bc8..46398d47 100644 --- a/platypush/backend/http/templates/plugins/media.html +++ b/platypush/backend/http/templates/plugins/media.html @@ -17,13 +17,13 @@ - -
+
@@ -98,6 +98,22 @@
+
+
+
+ +
+
Play
+
+ +
+
+ +
+
Download
+
+
+