mirror of
https://github.com/jellyfin/jellyfin-web
synced 2025-03-30 19:56:21 +00:00
update player selection dialog
This commit is contained in:
parent
f0f5c26a2c
commit
c80c66b498
10 changed files with 258 additions and 296 deletions
|
@ -705,7 +705,8 @@
|
|||
"SetAudioStreamIndex",
|
||||
"SetSubtitleStreamIndex",
|
||||
"DisplayContent",
|
||||
"SetRepeatMode"]
|
||||
"SetRepeatMode",
|
||||
"EndSession"]
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -778,6 +779,11 @@
|
|||
});
|
||||
};
|
||||
|
||||
self.endSession = function () {
|
||||
|
||||
castPlayer.stopApp();
|
||||
};
|
||||
|
||||
self.volumeUp = function () {
|
||||
|
||||
castPlayer.sendMessage({
|
||||
|
|
|
@ -68,10 +68,13 @@
|
|||
renderDetails(page, item, context);
|
||||
|
||||
var hasBackdrop = LibraryBrowser.renderDetailPageBackdrop(page, item);
|
||||
//$('#itemBackdrop', page).addClass('noBackdrop').css('background-image', 'none');
|
||||
//Backdrops.setBackdrops(page, [item]);
|
||||
|
||||
// For these types, make the backdrop a little smaller so that the items are more quickly accessible
|
||||
if (item.Type == "Season" || item.Type == "MusicArtist" || item.Type == "MusicAlbum" || item.Type == "Series" || item.Type == "Playlist" || item.Type == "BoxSet") {
|
||||
if (item.Type == 'MusicArtist' || item.Type == "MusicAlbum" || item.Type == "Playlist" || item.Type == "BoxSet" || item.Type == "Audio") {
|
||||
$('#itemBackdrop', page).addClass('noBackdrop').css('background-image', 'none');
|
||||
Backdrops.setBackdrops(page, [item]);
|
||||
}
|
||||
else if (item.Type == "Season" || item.Type == "Series") {
|
||||
page.querySelector('#itemBackdrop').classList.add('smallBackdrop');
|
||||
} else {
|
||||
page.querySelector('#itemBackdrop').classList.remove('smallBackdrop');
|
||||
|
@ -411,7 +414,7 @@
|
|||
var topOverview = page.querySelector('.topOverview');
|
||||
var bottomOverview = page.querySelector('.bottomOverview');
|
||||
|
||||
var seasonOnBottom = screen.availHeight < 600 || screen.availWidth < 600;
|
||||
var seasonOnBottom = screen.availHeight < 800 || screen.availWidth < 600;
|
||||
|
||||
if (item.Type == 'MusicAlbum' || item.Type == 'MusicArtist' || (item.Type == 'Season' && seasonOnBottom) || (item.Type == 'Series' && seasonOnBottom)) {
|
||||
LibraryBrowser.renderOverview([bottomOverview], item);
|
||||
|
@ -647,14 +650,20 @@
|
|||
return;
|
||||
}
|
||||
|
||||
var shape = item.Type == "MusicAlbum" || item.Type == "MusicArtist" ? "detailPageSquare" : "detailPagePortrait";
|
||||
var screenWidth = $(window).width();
|
||||
var screenHeight = $(window).height();
|
||||
|
||||
var options = {
|
||||
userId: Dashboard.getCurrentUserId(),
|
||||
limit: screenWidth > 800 ? 5 : 4,
|
||||
limit: screenWidth > 800 && shape == "detailPagePortrait" ? 5 : 4,
|
||||
fields: "PrimaryImageAspectRatio,UserData,SyncInfo"
|
||||
};
|
||||
|
||||
if (screenWidth >= 800 && screenHeight >= 1000) {
|
||||
options.limit *= 2;
|
||||
}
|
||||
|
||||
ApiClient.getSimilarItems(item.Id, options).done(function (result) {
|
||||
|
||||
if (!result.Items.length) {
|
||||
|
@ -669,7 +678,7 @@
|
|||
|
||||
var html = LibraryBrowser.getPosterViewHtml({
|
||||
items: result.Items,
|
||||
shape: item.Type == "MusicAlbum" || item.Type == "MusicArtist" ? "detailPageSquare" : "detailPagePortrait",
|
||||
shape: shape,
|
||||
showParentTitle: item.Type == "MusicAlbum",
|
||||
centerText: true,
|
||||
showTitle: item.Type == "MusicAlbum" || item.Type == "Game" || item.Type == "MusicArtist",
|
||||
|
|
|
@ -64,119 +64,110 @@
|
|||
});
|
||||
}
|
||||
|
||||
function getTargetsHtml(targets) {
|
||||
function showPlayerSelection() {
|
||||
|
||||
var playerInfo = MediaController.getPlayerInfo();
|
||||
|
||||
var html = '';
|
||||
html += '<form>';
|
||||
|
||||
html += '<h3>' + Globalize.translate('HeaderSelectPlayer') + '</h3>';
|
||||
html += '<fieldset data-role="controlgroup" data-mini="true">';
|
||||
|
||||
var checkedHtml;
|
||||
|
||||
for (var i = 0, length = targets.length; i < length; i++) {
|
||||
|
||||
var target = targets[i];
|
||||
|
||||
var id = 'radioPlayerTarget' + i;
|
||||
|
||||
var isChecked = target.id == playerInfo.id;
|
||||
checkedHtml = isChecked ? ' checked="checked"' : '';
|
||||
|
||||
var mirror = (!target.isLocalPlayer && target.supportedCommands.indexOf('DisplayContent') != -1) ? 'true' : 'false';
|
||||
|
||||
html += '<input type="radio" class="radioSelectPlayerTarget" name="radioSelectPlayerTarget" data-mirror="' + mirror + '" data-commands="' + target.supportedCommands.join(',') + '" data-mediatypes="' + target.playableMediaTypes.join(',') + '" data-playername="' + target.playerName + '" data-targetid="' + target.id + '" data-targetname="' + target.name + '" data-devicename="' + (target.deviceName || '') + '" id="' + id + '" value="' + target.id + '"' + checkedHtml + '>';
|
||||
html += '<label for="' + id + '" style="font-weight:normal;">' + target.name;
|
||||
|
||||
if (target.appName && target.appName != target.name) {
|
||||
html += '<br/><span>' + target.appName + '</span>';
|
||||
}
|
||||
|
||||
html += '</label>';
|
||||
if (!playerInfo.isLocalPlayer) {
|
||||
showActivePlayerMenu(playerInfo);
|
||||
return;
|
||||
}
|
||||
|
||||
html += '</fieldset>';
|
||||
Dashboard.showModalLoadingMsg();
|
||||
|
||||
html += '<p class="fieldDescription">' + Globalize.translate('LabelAllPlaysSentToPlayer') + '</p>';
|
||||
MediaController.getTargets().done(function (targets) {
|
||||
|
||||
checkedHtml = MediaController.enableDisplayMirroring() ? ' checked="checked"' : '';
|
||||
var menuItems = targets.map(function (t) {
|
||||
|
||||
html += '<div style="margin-top:1.5em;" class="fldMirrorMode"><label for="chkEnableMirrorMode">' + Globalize.translate('OptionEnableDisplayMirroring') + '</label><input type="checkbox" class="chkEnableMirrorMode" id="chkEnableMirrorMode" data-mini="true"' + checkedHtml + ' /></div>';
|
||||
var name = t.name;
|
||||
|
||||
html += '</form>';
|
||||
if (t.appName && t.appName != t.name) {
|
||||
name += " - " + t.appName;
|
||||
}
|
||||
|
||||
return html;
|
||||
return {
|
||||
name: name,
|
||||
id: t.id,
|
||||
ironIcon: 'tablet-android'
|
||||
};
|
||||
|
||||
});
|
||||
|
||||
require(['actionsheet'], function () {
|
||||
|
||||
Dashboard.hideModalLoadingMsg();
|
||||
|
||||
ActionSheetElement.show({
|
||||
title: Globalize.translate('HeaderSelectPlayer'),
|
||||
items: menuItems,
|
||||
callback: function (id) {
|
||||
|
||||
var target = targets.filter(function (t) {
|
||||
return t.id == id;
|
||||
})[0];
|
||||
|
||||
MediaController.trySetActivePlayer(target.playerName, target);
|
||||
|
||||
mirrorIfEnabled();
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function showPlayerSelection() {
|
||||
function showActivePlayerMenu(playerInfo) {
|
||||
|
||||
var promise = MediaController.getTargets();
|
||||
var id = 'dlg' + new Date().getTime();
|
||||
var html = '';
|
||||
|
||||
var html = '<div data-role="panel" data-position="right" data-display="overlay" data-position-fixed="true" id="playerSelectionPanel" data-theme="a">';
|
||||
var style = "";
|
||||
|
||||
html += '<div class="players"></div>';
|
||||
html += '<paper-dialog id="' + id + '" entry-animation="fade-in-animation" exit-animation="fade-out-animation" with-backdrop style="' + style + '">';
|
||||
|
||||
html += '<br/>';
|
||||
html += '<p><a href="nowplaying.html" class="clearLink"><paper-button raised class="block"><iron-icon icon="tablet-android"></iron-icon><span>' + Globalize.translate('ButtonRemoteControl') + '</span></paper-button></a></p>';
|
||||
html += '<h2>';
|
||||
html += (playerInfo.deviceName || playerInfo.name);
|
||||
html += '</h2>';
|
||||
|
||||
html += '<div style="padding:0 2em;">';
|
||||
|
||||
if (playerInfo.supportedCommands.indexOf('DisplayContent') != -1) {
|
||||
|
||||
html += '<div>';
|
||||
var checkedHtml = MediaController.enableDisplayMirroring() ? ' checked' : '';
|
||||
html += '<paper-checkbox class="chkMirror"' + checkedHtml + '>' + Globalize.translate('OptionEnableDisplayMirroring') + '</paper-checkbox>';
|
||||
html += '</div>';
|
||||
}
|
||||
|
||||
html += '</div>';
|
||||
|
||||
html += '<div class="buttons">';
|
||||
html += '<paper-button onclick="Dashboard.navigate(\'nowplaying.html\');" dialog-dismiss>' + Globalize.translate('ButtonRemoteControl') + '</paper-button>';
|
||||
html += '<paper-button dialog-dismiss onclick="MediaController.disconnectFromPlayer();">' + Globalize.translate('ButtonDisconnect') + '</paper-button>';
|
||||
html += '<paper-button dialog-dismiss>' + Globalize.translate('ButtonCancel') + '</paper-button>';
|
||||
html += '</div>';
|
||||
|
||||
html += '</paper-dialog>';
|
||||
|
||||
$(document.body).append(html);
|
||||
|
||||
require(['jqmicons']);
|
||||
setTimeout(function () {
|
||||
|
||||
var elem = $('#playerSelectionPanel').panel({}).trigger('create').panel("open").on("panelclose", function () {
|
||||
var dlg = document.getElementById(id);
|
||||
|
||||
$(this).off("panelclose").remove();
|
||||
});
|
||||
$('.chkMirror', dlg).on('change', onMirrorChange);
|
||||
|
||||
promise.done(function (targets) {
|
||||
|
||||
$('.players', elem).html(getTargetsHtml(targets)).trigger('create');
|
||||
|
||||
$('.chkEnableMirrorMode', elem).on('change', function () {
|
||||
MediaController.enableDisplayMirroring(this.checked);
|
||||
dlg.open();
|
||||
|
||||
// Has to be assigned a z-index after the call to .open()
|
||||
$(dlg).on('iron-overlay-closed', function () {
|
||||
$(this).remove();
|
||||
});
|
||||
|
||||
$('.radioSelectPlayerTarget', elem).off('change').on('change', function () {
|
||||
}, 100);
|
||||
}
|
||||
|
||||
var supportsMirror = this.getAttribute('data-mirror') == 'true';
|
||||
|
||||
if (supportsMirror) {
|
||||
$('.fldMirrorMode', elem).show();
|
||||
} else {
|
||||
$('.fldMirrorMode', elem).hide();
|
||||
}
|
||||
|
||||
var playerName = this.getAttribute('data-playername');
|
||||
var targetId = this.getAttribute('data-targetid');
|
||||
var targetName = this.getAttribute('data-targetname');
|
||||
var deviceName = this.getAttribute('data-deviceName');
|
||||
var playableMediaTypes = this.getAttribute('data-mediatypes').split(',');
|
||||
var supportedCommands = this.getAttribute('data-commands').split(',');
|
||||
|
||||
MediaController.trySetActivePlayer(playerName, {
|
||||
id: targetId,
|
||||
name: targetName,
|
||||
playableMediaTypes: playableMediaTypes,
|
||||
supportedCommands: supportedCommands,
|
||||
deviceName: deviceName
|
||||
|
||||
});
|
||||
|
||||
mirrorIfEnabled();
|
||||
|
||||
});
|
||||
|
||||
if ($('.radioSelectPlayerTarget:checked', elem)[0].getAttribute('data-mirror') == 'true') {
|
||||
$('.fldMirrorMode', elem).show();
|
||||
} else {
|
||||
$('.fldMirrorMode', elem).hide();
|
||||
}
|
||||
});
|
||||
function onMirrorChange() {
|
||||
MediaController.enableDisplayMirroring(this.checked);
|
||||
}
|
||||
|
||||
function bindKeys(controller) {
|
||||
|
@ -369,6 +360,36 @@
|
|||
}
|
||||
};
|
||||
|
||||
self.disconnectFromPlayer = function () {
|
||||
|
||||
var playerInfo = self.getPlayerInfo();
|
||||
|
||||
if (playerInfo.supportedCommands.indexOf('EndSession') != -1) {
|
||||
|
||||
var options = {
|
||||
callback: function (result) {
|
||||
|
||||
if (result == 0) {
|
||||
MediaController.getCurrentPlayer().endSession();
|
||||
}
|
||||
|
||||
if (result != 2) {
|
||||
self.setDefaultPlayerActive();
|
||||
}
|
||||
},
|
||||
message: Globalize.translate('ConfirmEndPlayerSession'),
|
||||
title: Globalize.translate('HeaderDisconnectFromPlayer'),
|
||||
buttons: [Globalize.translate('ButtonYes'), Globalize.translate('ButtonNo'), Globalize.translate('ButtonCancel')]
|
||||
};
|
||||
|
||||
Dashboard.dialog(options);
|
||||
|
||||
} else {
|
||||
|
||||
self.setDefaultPlayerActive();
|
||||
}
|
||||
};
|
||||
|
||||
self.getPlayers = function () {
|
||||
return players;
|
||||
};
|
||||
|
|
|
@ -20,7 +20,6 @@ $.support.cors = true;
|
|||
$(document).one('click', WebNotifications.requestPermission);
|
||||
|
||||
var Dashboard = {
|
||||
|
||||
jQueryMobileInit: function () {
|
||||
|
||||
// Page
|
||||
|
@ -96,7 +95,7 @@ var Dashboard = {
|
|||
var url = getWindowUrl().toLowerCase();
|
||||
|
||||
return url.indexOf('mediabrowser.tv') != -1 ||
|
||||
url.indexOf('emby.media') != -1;
|
||||
url.indexOf('emby.media') != -1;
|
||||
},
|
||||
|
||||
isRunningInCordova: function () {
|
||||
|
@ -244,8 +243,7 @@ var Dashboard = {
|
|||
|
||||
if (document.createStyleSheet) {
|
||||
document.createStyleSheet(url);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
var link = document.createElement('link');
|
||||
link.setAttribute('rel', 'stylesheet');
|
||||
link.setAttribute('type', 'text/css');
|
||||
|
@ -599,6 +597,75 @@ var Dashboard = {
|
|||
}
|
||||
},
|
||||
|
||||
dialog: function (options) {
|
||||
|
||||
var title = options.title;
|
||||
var message = options.message;
|
||||
var buttons = options.buttons;
|
||||
var callback = options.callback;
|
||||
|
||||
// Cordova
|
||||
if (navigator.notification && navigator.notification.confirm && message.indexOf('<') == -1) {
|
||||
|
||||
navigator.notification.confirm(message, function (index) {
|
||||
|
||||
callback(index);
|
||||
|
||||
}, title, buttons.join(','));
|
||||
|
||||
} else {
|
||||
Dashboard.dialogInternal(message, title, buttons, callback);
|
||||
}
|
||||
},
|
||||
|
||||
dialogInternal: function (message, title, buttons, callback) {
|
||||
|
||||
var id = 'paperdlg' + new Date().getTime();
|
||||
|
||||
var html = '<paper-dialog id="' + id + '" role="alertdialog" entry-animation="fade-in-animation" exit-animation="fade-out-animation" with-backdrop>';
|
||||
html += '<h2>' + title + '</h2>';
|
||||
html += '<div>' + message + '</div>';
|
||||
html += '<div class="buttons">';
|
||||
|
||||
var index = 0;
|
||||
html += buttons.map(function (b) {
|
||||
|
||||
var dataIndex = ' data-index="' + index + '"';
|
||||
index++;
|
||||
return '<paper-button class="dialogButton"' + dataIndex + ' dialog-dismiss>' + b + '</paper-button>';
|
||||
|
||||
}).join('');
|
||||
|
||||
html += '</div>';
|
||||
html += '</paper-dialog>';
|
||||
|
||||
$(document.body).append(html);
|
||||
|
||||
// This timeout is obviously messy but it's unclear how to determine when the webcomponent is ready for use
|
||||
// element onload never fires
|
||||
setTimeout(function () {
|
||||
|
||||
var dlg = document.getElementById(id);
|
||||
|
||||
$('.dialogButton', dlg).on('click', function () {
|
||||
|
||||
if (callback) {
|
||||
callback(parseInt(this.getAttribute('data-index')));
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
// Has to be assigned a z-index after the call to .open()
|
||||
$(dlg).on('iron-overlay-closed', function (e) {
|
||||
|
||||
this.parentNode.removeChild(this);
|
||||
});
|
||||
|
||||
dlg.open();
|
||||
|
||||
}, 300);
|
||||
},
|
||||
|
||||
confirm: function (message, title, callback) {
|
||||
|
||||
// Cordova
|
||||
|
@ -619,46 +686,43 @@ var Dashboard = {
|
|||
|
||||
confirmInternal: function (message, title, showCancel, callback) {
|
||||
|
||||
require(['paperbuttonstyle'], function () {
|
||||
var id = 'paperdlg' + new Date().getTime();
|
||||
|
||||
var id = 'paperdlg' + new Date().getTime();
|
||||
var html = '<paper-dialog id="' + id + '" role="alertdialog" entry-animation="fade-in-animation" exit-animation="fade-out-animation" with-backdrop>';
|
||||
html += '<h2>' + title + '</h2>';
|
||||
html += '<div>' + message + '</div>';
|
||||
html += '<div class="buttons">';
|
||||
|
||||
var html = '<paper-dialog id="' + id + '" role="alertdialog" entry-animation="fade-in-animation" exit-animation="fade-out-animation" with-backdrop>';
|
||||
html += '<h2>' + title + '</h2>';
|
||||
html += '<div>' + message + '</div>';
|
||||
html += '<div class="buttons">';
|
||||
html += '<paper-button class="btnConfirm" dialog-confirm autofocus>' + Globalize.translate('ButtonOk') + '</paper-button>';
|
||||
|
||||
if (showCancel) {
|
||||
html += '<paper-button dialog-dismiss>' + Globalize.translate('ButtonCancel') + '</paper-button>';
|
||||
}
|
||||
if (showCancel) {
|
||||
html += '<paper-button dialog-dismiss>' + Globalize.translate('ButtonCancel') + '</paper-button>';
|
||||
}
|
||||
|
||||
html += '<paper-button class="btnConfirm" dialog-confirm autofocus>' + Globalize.translate('ButtonOk') + '</paper-button>';
|
||||
html += '</div>';
|
||||
html += '</paper-dialog>';
|
||||
|
||||
html += '</div>';
|
||||
html += '</paper-dialog>';
|
||||
$(document.body).append(html);
|
||||
|
||||
$(document.body).append(html);
|
||||
// This timeout is obviously messy but it's unclear how to determine when the webcomponent is ready for use
|
||||
// element onload never fires
|
||||
setTimeout(function () {
|
||||
|
||||
// This timeout is obviously messy but it's unclear how to determine when the webcomponent is ready for use
|
||||
// element onload never fires
|
||||
setTimeout(function () {
|
||||
var dlg = document.getElementById(id);
|
||||
|
||||
var dlg = document.getElementById(id);
|
||||
// Has to be assigned a z-index after the call to .open()
|
||||
$(dlg).on('iron-overlay-closed', function (e) {
|
||||
var confirmed = this.closingReason.confirmed;
|
||||
this.parentNode.removeChild(this);
|
||||
|
||||
// Has to be assigned a z-index after the call to .open()
|
||||
$(dlg).on('iron-overlay-closed', function (e) {
|
||||
var confirmed = this.closingReason.confirmed;
|
||||
this.parentNode.removeChild(this);
|
||||
if (callback) {
|
||||
callback(confirmed);
|
||||
}
|
||||
});
|
||||
|
||||
if (callback) {
|
||||
callback(confirmed);
|
||||
}
|
||||
});
|
||||
dlg.open();
|
||||
|
||||
dlg.open();
|
||||
|
||||
}, 300);
|
||||
});
|
||||
}, 300);
|
||||
},
|
||||
|
||||
refreshSystemInfoFromServer: function () {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue