mirror of
https://github.com/jellyfin/jellyfin-web
synced 2025-03-30 19:56:21 +00:00
the beginnings of remote control
This commit is contained in:
parent
57fed6b0ad
commit
5bb0338772
7 changed files with 246 additions and 34 deletions
37
ApiClient.js
37
ApiClient.js
|
@ -2589,7 +2589,6 @@ MediaBrowser.ApiClient = function ($, navigator, JSON, WebSocket, setTimeout) {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reports a user has stopped playing an item
|
* Reports a user has stopped playing an item
|
||||||
* @param {String} userId
|
* @param {String} userId
|
||||||
|
@ -2629,6 +2628,42 @@ MediaBrowser.ApiClient = function ($, navigator, JSON, WebSocket, setTimeout) {
|
||||||
url: url
|
url: url
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
self.sendBrowseCommand = function (sessionId, options) {
|
||||||
|
|
||||||
|
if (!sessionId) {
|
||||||
|
throw new Error("null sessionId");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!options) {
|
||||||
|
throw new Error("null options");
|
||||||
|
}
|
||||||
|
|
||||||
|
var url = self.getUrl("Sessions/" + sessionId + "/Viewing", options);
|
||||||
|
|
||||||
|
return self.ajax({
|
||||||
|
type: "POST",
|
||||||
|
url: url
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
self.sendPlayCommand = function (sessionId, options) {
|
||||||
|
|
||||||
|
if (!sessionId) {
|
||||||
|
throw new Error("null sessionId");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!options) {
|
||||||
|
throw new Error("null options");
|
||||||
|
}
|
||||||
|
|
||||||
|
var url = self.getUrl("Sessions/" + sessionId + "/Playing", options);
|
||||||
|
|
||||||
|
return self.ajax({
|
||||||
|
type: "POST",
|
||||||
|
url: url
|
||||||
|
});
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
}(jQuery, navigator, window.JSON, window.WebSocket, setTimeout);
|
}(jQuery, navigator, window.JSON, window.WebSocket, setTimeout);
|
||||||
|
|
|
@ -127,6 +127,17 @@
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="ui-body-a" style="text-align: center; padding: .25em 0 .5em;">
|
||||||
|
<span id="playButtonContainer" style="display: none;">
|
||||||
|
<button id="btnPlay" type="button" data-icon="play" data-inline="true" data-mini="true">Play</button>
|
||||||
|
</span>
|
||||||
|
<span>
|
||||||
|
<button id="btnRemote" type="button" data-icon="hand-up" data-inline="true" data-mini="true">Remote Control</button>
|
||||||
|
</span>
|
||||||
|
<span id="editButtonContainer" style="display: none;">
|
||||||
|
<button id="btnEdit" type="button" data-icon="pencil" data-inline="true" data-mini="true">Edit</button>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
<div data-role="content">
|
<div data-role="content">
|
||||||
|
|
||||||
<div class="detailPageContent">
|
<div class="detailPageContent">
|
||||||
|
|
|
@ -127,7 +127,7 @@
|
||||||
<button id="btnPlay" type="button" data-icon="play" data-inline="true" data-mini="true">Play</button>
|
<button id="btnPlay" type="button" data-icon="play" data-inline="true" data-mini="true">Play</button>
|
||||||
</span>
|
</span>
|
||||||
<span>
|
<span>
|
||||||
<button id="btnRemote" type="button" data-icon="hand-up" data-inline="true" data-mini="true">Remote</button>
|
<button id="btnRemote" type="button" data-icon="hand-up" data-inline="true" data-mini="true">Remote Control</button>
|
||||||
</span>
|
</span>
|
||||||
<span id="editButtonContainer" style="display: none;">
|
<span id="editButtonContainer" style="display: none;">
|
||||||
<button id="btnEdit" type="button" data-icon="pencil" data-inline="true" data-mini="true">Edit</button>
|
<button id="btnEdit" type="button" data-icon="pencil" data-inline="true" data-mini="true">Edit</button>
|
||||||
|
|
|
@ -464,7 +464,16 @@
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
$(document).on('pageshow', "#itemByNameDetailPage", function () {
|
$(document).on('pageinit', "#itemByNameDetailPage", function () {
|
||||||
|
|
||||||
|
var page = this;
|
||||||
|
|
||||||
|
$('#btnRemote', page).on('click', function () {
|
||||||
|
|
||||||
|
RemoteControl.showMenu(page, currentItem);
|
||||||
|
});
|
||||||
|
|
||||||
|
}).on('pageshow', "#itemByNameDetailPage", function () {
|
||||||
|
|
||||||
var page = this;
|
var page = this;
|
||||||
|
|
||||||
|
|
|
@ -511,6 +511,12 @@
|
||||||
level: 3
|
level: 3
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
var ogvVideoUrl = ApiClient.getUrl('Videos/' + item.Id + '/stream.ogv', $.extend({}, baseParams, {
|
||||||
|
videoCodec: 'theora',
|
||||||
|
audioCodec: 'Vorbis'
|
||||||
|
}));
|
||||||
|
|
||||||
|
|
||||||
var html = '';
|
var html = '';
|
||||||
|
|
||||||
// HLS must be at the top for safari
|
// HLS must be at the top for safari
|
||||||
|
@ -518,15 +524,16 @@
|
||||||
|
|
||||||
// Can't autoplay in these browsers so we need to use the full controls
|
// Can't autoplay in these browsers so we need to use the full controls
|
||||||
if ($.browser.msie || $.browser.android || $.browser.iphone || $.browser.ipad) {
|
if ($.browser.msie || $.browser.android || $.browser.iphone || $.browser.ipad) {
|
||||||
html += '<video class="itemVideo" autoplay controls preload="auto">';
|
html += '<video class="itemVideo" autoplay controls preload="none">';
|
||||||
} else {
|
} else {
|
||||||
html += '<video class="itemVideo" autoplay preload="auto">';
|
html += '<video class="itemVideo" autoplay preload="none">';
|
||||||
}
|
}
|
||||||
|
|
||||||
html += '<source type="application/x-mpegURL" src="' + hlsVideoUrl + '" />';
|
html += '<source type="application/x-mpegURL" src="' + hlsVideoUrl + '" />';
|
||||||
html += '<source type="video/mp2t" src="' + tsVideoUrl + '" />';
|
html += '<source type="video/mp2t" src="' + tsVideoUrl + '" />';
|
||||||
html += '<source type="video/webm" src="' + webmVideoUrl + '" />';
|
html += '<source type="video/webm" src="' + webmVideoUrl + '" />';
|
||||||
html += '<source type="video/mp4" src="' + mp4VideoUrl + '" />';
|
html += '<source type="video/mp4" src="' + mp4VideoUrl + '" />';
|
||||||
|
html += '<source type="video/ogg" src="' + ogvVideoUrl + '" />';
|
||||||
html += '</video';
|
html += '</video';
|
||||||
|
|
||||||
var nowPlayingBar = $('#nowPlayingBar').show();
|
var nowPlayingBar = $('#nowPlayingBar').show();
|
||||||
|
|
|
@ -1,12 +1,6 @@
|
||||||
(function (window, document, $) {
|
(function (window, document, $) {
|
||||||
|
|
||||||
function remoteControl() {
|
function showMenu(page, item, context, sessionsPromise, usersPromise) {
|
||||||
|
|
||||||
var self = this;
|
|
||||||
|
|
||||||
self.showMenu = function (page, item) {
|
|
||||||
|
|
||||||
$('#confirmFlyout').popup("close").remove();
|
|
||||||
|
|
||||||
var html = '<div data-role="popup" id="remoteControlFlyout">';
|
var html = '<div data-role="popup" id="remoteControlFlyout">';
|
||||||
|
|
||||||
|
@ -16,22 +10,178 @@
|
||||||
|
|
||||||
html += '<div data-role="content" class="ui-corner-bottom ui-content">';
|
html += '<div data-role="content" class="ui-corner-bottom ui-content">';
|
||||||
|
|
||||||
html += '<div style="padding: 1em;margin: 0;">test';
|
html += '<form id="sendToForm"><div class="sessionsPopupContent">';
|
||||||
html += '</div>';
|
|
||||||
|
|
||||||
html += '<p><button type="button" data-icon="ok" onclick="$(\'#confirmFlyout\')[0].confirm=true;$(\'#confirmFlyout\').popup(\'close\');" data-theme="b" data-mini="true" data-inline="true">Ok</button>';
|
html += '<div class="circle"></div><div class="circle1"></div>';
|
||||||
html += '<button type="button" data-icon="delete" onclick="$(\'#confirmFlyout\').popup(\'close\');" data-theme="a" data-mini="true" data-inline="true">Cancel</button></p>';
|
|
||||||
|
|
||||||
html += '</div>';
|
html += '</div>';
|
||||||
|
|
||||||
|
html += '<p style="text-align:center;margin:0;"><button type="submit" data-icon="ok" data-theme="b" data-mini="true" data-inline="true">Ok</button>';
|
||||||
|
html += '<button type="button" data-icon="delete" onclick="$(\'#remoteControlFlyout\').popup(\'close\');" data-theme="a" data-mini="true" data-inline="true">Cancel</button></p>';
|
||||||
|
|
||||||
|
html += '</form></div>';
|
||||||
|
|
||||||
html += '</div>';
|
html += '</div>';
|
||||||
|
|
||||||
$(document.body).append(html);
|
$(document.body).append(html);
|
||||||
|
|
||||||
$('#remoteControlFlyout').popup({ history: false }).trigger('create').popup("open").on("popupafterclose", function () {
|
var popup = $('#remoteControlFlyout').popup({ history: false }).trigger('create').popup("open").on("popupafterclose", function () {
|
||||||
|
|
||||||
$(this).off("popupafterclose").remove();
|
$(this).off("popupafterclose").remove();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
$('#sendToForm', popup).on('submit', function () {
|
||||||
|
|
||||||
|
var checkboxes = $('.chkClient', popup);
|
||||||
|
|
||||||
|
if (!checkboxes.length) {
|
||||||
|
$('#remoteControlFlyout').popup("close");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
checkboxes = $('.chkClient:checked', popup);
|
||||||
|
|
||||||
|
if (!checkboxes.length) {
|
||||||
|
Dashboard.alert('Please select a device to control.');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
var sessionIds = [];
|
||||||
|
|
||||||
|
checkboxes.parents('.trSession').each(function () {
|
||||||
|
|
||||||
|
sessionIds.push(this.getAttribute('data-sessionid'));
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
var command = $('#selectCommand', popup).val();
|
||||||
|
|
||||||
|
var promise;
|
||||||
|
|
||||||
|
if (command == "Browse") {
|
||||||
|
promise = ApiClient.sendBrowseCommand(sessionIds[0], {
|
||||||
|
|
||||||
|
ItemId: item.Id,
|
||||||
|
ItemName: item.Name,
|
||||||
|
ItemType: item.Type,
|
||||||
|
Context: context
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else if (command == "Play") {
|
||||||
|
promise = ApiClient.sendPlayCommand(sessionIds[0], {
|
||||||
|
|
||||||
|
ItemIds: [item.Id].join(','),
|
||||||
|
PlayCommand: 'PlayNow'
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
promise.done(function () {
|
||||||
|
|
||||||
|
$('#remoteControlFlyout').popup("close");
|
||||||
|
});
|
||||||
|
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
|
||||||
|
var elem = $('.sessionsPopupContent');
|
||||||
|
|
||||||
|
$.when(sessionsPromise, usersPromise).done(function (response1, response2) {
|
||||||
|
|
||||||
|
var deviceId = ApiClient.deviceId();
|
||||||
|
|
||||||
|
var sessions = response1[0].filter(function (s) {
|
||||||
|
return s.DeviceId != deviceId;
|
||||||
|
});
|
||||||
|
|
||||||
|
renderSessions(sessions, response2[0], elem);
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function renderSessions(sessions, users, elem) {
|
||||||
|
|
||||||
|
if (!sessions.length) {
|
||||||
|
elem.html('<p>There are currently no available media browser sessions to control.</p>');
|
||||||
|
$('#remoteControlFlyout').popup("reposition", {});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var html = '';
|
||||||
|
|
||||||
|
html += '<p style="margin-top:0;">';
|
||||||
|
html += '<label for="selectCommand">Select Command</label>';
|
||||||
|
html += '<select id="selectCommand" data-mini="true">';
|
||||||
|
html += '<option value="Browse">Browse To</label>';
|
||||||
|
html += '<option value="Play">Play</label>';
|
||||||
|
html += '</select>';
|
||||||
|
html += '</p>';
|
||||||
|
|
||||||
|
html += '<p style="margin: 1.5em 0;">Send To Device</p>';
|
||||||
|
|
||||||
|
html += '<div>';
|
||||||
|
|
||||||
|
html += '<table data-role="table" data-mode="reflow" class="ui-responsive table-stroke">';
|
||||||
|
|
||||||
|
html += '<thead><tr>';
|
||||||
|
html += '<th></th>';
|
||||||
|
html += '<th>Client</th>';
|
||||||
|
html += '<th>Device</th>';
|
||||||
|
html += '<th>User</th>';
|
||||||
|
html += '</tr></thead>';
|
||||||
|
|
||||||
|
html += '<tbody>';
|
||||||
|
|
||||||
|
for (var i = 0, length = sessions.length; i < length; i++) {
|
||||||
|
|
||||||
|
var session = sessions[i];
|
||||||
|
|
||||||
|
html += '<tr class="trSession" data-sessionid="' + session.Id + '">';
|
||||||
|
|
||||||
|
html += '<td class="checkboxCell"></td>';
|
||||||
|
html += '<td>' + session.Client + '</td>';
|
||||||
|
html += '<td>' + session.DeviceName + '</td>';
|
||||||
|
|
||||||
|
html += '<td>';
|
||||||
|
|
||||||
|
var user = null;
|
||||||
|
|
||||||
|
if (session.UserId) {
|
||||||
|
|
||||||
|
user = users.filter(function (u) {
|
||||||
|
return u.Id == session.UserId;
|
||||||
|
})[0];
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
html += user ? user.Name : ' ';
|
||||||
|
|
||||||
|
html += '</td>';
|
||||||
|
|
||||||
|
html += '</tr>';
|
||||||
|
}
|
||||||
|
|
||||||
|
html += '</tbody>';
|
||||||
|
|
||||||
|
html += '</table>';
|
||||||
|
|
||||||
|
html += '<br/>';
|
||||||
|
html += '</div>';
|
||||||
|
|
||||||
|
elem.html(html).trigger('create');
|
||||||
|
|
||||||
|
$('.checkboxCell', elem).html('<input type="radio" class="chkClient" name="chkClient" />');
|
||||||
|
|
||||||
|
$('#remoteControlFlyout').popup("reposition", {});
|
||||||
|
}
|
||||||
|
|
||||||
|
function remoteControl() {
|
||||||
|
|
||||||
|
var self = this;
|
||||||
|
|
||||||
|
self.showMenu = function (page, item, context) {
|
||||||
|
showMenu(page, item, context, ApiClient.getSessions({ SupportsRemoteControl: true }), ApiClient.getUsers());
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<packages>
|
<packages>
|
||||||
<package id="MediaBrowser.ApiClient.Javascript" version="3.0.120" targetFramework="net45" />
|
<package id="MediaBrowser.ApiClient.Javascript" version="3.0.122" targetFramework="net45" />
|
||||||
<package id="ServiceStack.Common" version="3.9.46" targetFramework="net45" />
|
<package id="ServiceStack.Common" version="3.9.46" targetFramework="net45" />
|
||||||
<package id="ServiceStack.Text" version="3.9.45" targetFramework="net45" />
|
<package id="ServiceStack.Text" version="3.9.45" targetFramework="net45" />
|
||||||
</packages>
|
</packages>
|
Loading…
Add table
Add a link
Reference in a new issue