Change media info display (#386)
* Add btn more media info * Add event listener * change class and add close btn * Add style * Add event listener display * hide btn * remove media info form itemdetail page * Add media templete * cleanup unused stayle * Add to context menu * cleanup * cleanup * fix * add todo to file path info * allow admin and user to view the media info * Add to strings * Remove media info menu from book and music * Remove splitVersions function * Readd splitVersions function on item deatil page * Remove unused elements * double quotes & removing newlines * minor style changes * fix format and path info on itemdetails page * update
This commit is contained in:
parent
c46f577f08
commit
5fda5a8738
7 changed files with 251 additions and 196 deletions
164
src/components/itemMediaInfo/itemMediaInfo.js
Normal file
164
src/components/itemMediaInfo/itemMediaInfo.js
Normal file
|
@ -0,0 +1,164 @@
|
|||
define(["dialogHelper", "require", "layoutManager", "globalize", "userSettings", "connectionManager", "loading", "focusManager", "dom", "apphost", "emby-select", "listViewStyle", "paper-icon-button-light", "css!./../formdialog", "material-icons", "emby-button", "flexStyles"], function (dialogHelper, require, layoutManager, globalize, userSettings, connectionManager, loading, focusManager, dom, appHost) {
|
||||
"use strict";
|
||||
|
||||
function setMediaInfo(user, page, item) {
|
||||
var html = item.MediaSources.map(function (version) {
|
||||
return getMediaSourceHtml(user, item, version);
|
||||
}).join('<div style="border-top:1px solid #444;margin: 1em 0;"></div>');
|
||||
if (item.MediaSources.length > 1) {
|
||||
html = "<br/>" + html;
|
||||
}
|
||||
var mediaInfoContent = page.querySelector("#mediaInfoContent");
|
||||
mediaInfoContent.innerHTML = html;
|
||||
}
|
||||
|
||||
function getMediaSourceHtml(user, item, version) {
|
||||
var html = "";
|
||||
if (version.Name) {
|
||||
html += '<div><h2 class="mediaInfoStreamType">' + version.Name + "</h2></div>";
|
||||
}
|
||||
if (version.Container) {
|
||||
html += createAttribute(globalize.translate("MediaInfoContainer"), version.Container) + "<br/>";
|
||||
}
|
||||
if (version.Formats && version.Formats.length) {
|
||||
html += createAttribute(globalize.translate("MediaInfoFormat"), version.Formats.join(",")) + "<br/>";
|
||||
}
|
||||
if (version.Path && user && user.Policy.IsAdministrator) {
|
||||
html += createAttribute(globalize.translate("MediaInfoPath"), version.Path) + "<br/>";
|
||||
}
|
||||
if (version.Size && user && user.Policy.IsAdministrator) {
|
||||
var size = (version.Size / (1024 * 1024)).toFixed(0) + " MB";
|
||||
html += createAttribute(globalize.translate("MediaInfoSize"), size) + "<br/>";
|
||||
}
|
||||
for (var i = 0, length = version.MediaStreams.length; i < length; i++) {
|
||||
var stream = version.MediaStreams[i];
|
||||
if (stream.Type === "Data") {
|
||||
continue;
|
||||
}
|
||||
html += '<div class="mediaInfoStream">';
|
||||
var displayType = globalize.translate("MediaInfoStreamType" + stream.Type);
|
||||
html += '<h2 class="mediaInfoStreamType">' + displayType + "</h2>";
|
||||
var attributes = [];
|
||||
if (stream.DisplayTitle) {
|
||||
attributes.push(createAttribute("Title", stream.DisplayTitle));
|
||||
}
|
||||
if (stream.Language && stream.Type !== "Video") {
|
||||
attributes.push(createAttribute(globalize.translate("MediaInfoLanguage"), stream.Language));
|
||||
}
|
||||
if (stream.Codec) {
|
||||
attributes.push(createAttribute(globalize.translate("MediaInfoCodec"), stream.Codec.toUpperCase()));
|
||||
}
|
||||
if (stream.CodecTag) {
|
||||
attributes.push(createAttribute(globalize.translate("MediaInfoCodecTag"), stream.CodecTag));
|
||||
}
|
||||
if (stream.IsAVC != null) {
|
||||
attributes.push(createAttribute("AVC", (stream.IsAVC ? "Yes" : "No")));
|
||||
}
|
||||
if (stream.Profile) {
|
||||
attributes.push(createAttribute(globalize.translate("MediaInfoProfile"), stream.Profile));
|
||||
}
|
||||
if (stream.Level) {
|
||||
attributes.push(createAttribute(globalize.translate("MediaInfoLevel"), stream.Level));
|
||||
}
|
||||
if (stream.Width || stream.Height) {
|
||||
attributes.push(createAttribute(globalize.translate("MediaInfoResolution"), stream.Width + "x" + stream.Height));
|
||||
}
|
||||
if (stream.AspectRatio && stream.Codec !== "mjpeg") {
|
||||
attributes.push(createAttribute(globalize.translate("MediaInfoAspectRatio"), stream.AspectRatio));
|
||||
}
|
||||
if (stream.Type === "Video") {
|
||||
if (stream.IsAnamorphic != null) {
|
||||
attributes.push(createAttribute(globalize.translate("MediaInfoAnamorphic"), (stream.IsAnamorphic ? "Yes" : "No")));
|
||||
}
|
||||
attributes.push(createAttribute(globalize.translate("MediaInfoInterlaced"), (stream.IsInterlaced ? "Yes" : "No")));
|
||||
}
|
||||
if (stream.AverageFrameRate || stream.RealFrameRate) {
|
||||
attributes.push(createAttribute(globalize.translate("MediaInfoFramerate"), (stream.AverageFrameRate || stream.RealFrameRate)));
|
||||
}
|
||||
if (stream.ChannelLayout) {
|
||||
attributes.push(createAttribute(globalize.translate("MediaInfoLayout"), stream.ChannelLayout));
|
||||
}
|
||||
if (stream.Channels) {
|
||||
attributes.push(createAttribute(globalize.translate("MediaInfoChannels"), stream.Channels + " ch"));
|
||||
}
|
||||
if (stream.BitRate && stream.Codec !== "mjpeg") {
|
||||
attributes.push(createAttribute(globalize.translate("MediaInfoBitrate"), (parseInt(stream.BitRate / 1000)) + " kbps"));
|
||||
}
|
||||
if (stream.SampleRate) {
|
||||
attributes.push(createAttribute(globalize.translate("MediaInfoSampleRate"), stream.SampleRate + " Hz"));
|
||||
}
|
||||
if (stream.BitDepth) {
|
||||
attributes.push(createAttribute(globalize.translate("MediaInfoBitDepth"), stream.BitDepth + " bit"));
|
||||
}
|
||||
if (stream.PixelFormat) {
|
||||
attributes.push(createAttribute(globalize.translate("MediaInfoPixelFormat"), stream.PixelFormat));
|
||||
}
|
||||
if (stream.RefFrames) {
|
||||
attributes.push(createAttribute(globalize.translate("MediaInfoRefFrames"), stream.RefFrames));
|
||||
}
|
||||
if (stream.NalLengthSize) {
|
||||
attributes.push(createAttribute("NAL", stream.NalLengthSize));
|
||||
}
|
||||
if (stream.Type !== "Video") {
|
||||
attributes.push(createAttribute(globalize.translate("MediaInfoDefault"), (stream.IsDefault ? "Yes" : "No")));
|
||||
}
|
||||
if (stream.Type === "Subtitle") {
|
||||
attributes.push(createAttribute(globalize.translate("MediaInfoForced"), (stream.IsForced ? "Yes" : "No")));
|
||||
attributes.push(createAttribute(globalize.translate("MediaInfoExternal"), (stream.IsExternal ? "Yes" : "No")));
|
||||
}
|
||||
if (stream.Type === "Video" && version.Timestamp) {
|
||||
attributes.push(createAttribute(globalize.translate("MediaInfoTimestamp"), version.Timestamp));
|
||||
}
|
||||
html += attributes.join("<br/>");
|
||||
html += "</div>";
|
||||
}
|
||||
return html;
|
||||
}
|
||||
|
||||
function createAttribute(label, value) {
|
||||
return '<span class="mediaInfoLabel">' + label + '</span><span class="mediaInfoAttribute">' + value + "</span>"
|
||||
}
|
||||
|
||||
function showMediaInfoMore(itemId, serverId, template) {
|
||||
var apiClient = connectionManager.getApiClient(serverId);
|
||||
return apiClient.getItem(apiClient.getCurrentUserId(), itemId).then(function (item) {
|
||||
var dialogOptions = {
|
||||
size: "small",
|
||||
removeOnClose: true,
|
||||
scrollY: false
|
||||
};
|
||||
if (layoutManager.tv) {
|
||||
dialogOptions.size = "fullscreen";
|
||||
}
|
||||
var dlg = dialogHelper.createDialog(dialogOptions);
|
||||
dlg.classList.add("formDialog");
|
||||
var html = "";
|
||||
html += globalize.translateDocument(template, "core");
|
||||
dlg.innerHTML = html;
|
||||
if (layoutManager.tv) {
|
||||
scrollHelper.centerFocus.on(dlg.querySelector(".formDialogContent"), false);
|
||||
}
|
||||
dialogHelper.open(dlg);
|
||||
dlg.querySelector(".btnCancel").addEventListener("click", function (e) {
|
||||
dialogHelper.close(dlg);
|
||||
});
|
||||
apiClient.getCurrentUser().then(function (user) {
|
||||
setMediaInfo(user, dlg, item);
|
||||
});
|
||||
loading.hide();
|
||||
});
|
||||
}
|
||||
|
||||
function showMediaInfo(itemId, serverId) {
|
||||
loading.show();
|
||||
return new Promise(function (resolve, reject) {
|
||||
require(["text!./itemMediaInfo.template.html"], function (template) {
|
||||
showMediaInfoMore(itemId, serverId, template).then(resolve, reject);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
show: showMediaInfo
|
||||
};
|
||||
});
|
12
src/components/itemMediaInfo/itemMediaInfo.template.html
Normal file
12
src/components/itemMediaInfo/itemMediaInfo.template.html
Normal file
|
@ -0,0 +1,12 @@
|
|||
<div class="formDialogHeader">
|
||||
<button is="paper-icon-button-light" class="btnCancel autoSize" tabindex="-1"><i class="md-icon"></i></button>
|
||||
<h3 class="formDialogHeaderTitle">
|
||||
${HeaderMediaInfo}
|
||||
</h3>
|
||||
</div>
|
||||
|
||||
<div class="formDialogContent smoothScrollY">
|
||||
<div class="dialogContentInner" style="padding: 1em">
|
||||
<div id="mediaInfoContent" class="mediaInfoContent"></div>
|
||||
</div>
|
||||
</div>
|
|
@ -2,23 +2,19 @@ define(['apphost', 'globalize', 'connectionManager', 'itemHelper', 'appRouter',
|
|||
'use strict';
|
||||
|
||||
function getCommands(options) {
|
||||
|
||||
var item = options.item;
|
||||
|
||||
var canPlay = playbackManager.canPlay(item);
|
||||
|
||||
var commands = [];
|
||||
var restrictOptions = (browser.operaTv || browser.web0s) && !user.Policy.IsAdministrator;
|
||||
|
||||
var user = options.user;
|
||||
|
||||
var restrictOptions = (browser.operaTv || browser.web0s) && !user.Policy.IsAdministrator;
|
||||
var commands = [];
|
||||
|
||||
if (canPlay && item.MediaType !== 'Photo') {
|
||||
if (options.play !== false) {
|
||||
commands.push({
|
||||
name: globalize.translate('Play'),
|
||||
id: 'resume'
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
if (options.playAllFromHere && item.Type !== 'Program' && item.Type !== 'TvChannel') {
|
||||
|
@ -30,7 +26,6 @@ define(['apphost', 'globalize', 'connectionManager', 'itemHelper', 'appRouter',
|
|||
}
|
||||
|
||||
if (playbackManager.canQueue(item)) {
|
||||
|
||||
if (options.queue !== false) {
|
||||
commands.push({
|
||||
name: globalize.translate('AddToPlayQueue'),
|
||||
|
@ -143,20 +138,16 @@ define(['apphost', 'globalize', 'connectionManager', 'itemHelper', 'appRouter',
|
|||
|
||||
var canEdit = itemHelper.canEdit(user, item);
|
||||
if (canEdit) {
|
||||
|
||||
if (options.edit !== false && item.Type !== 'SeriesTimer') {
|
||||
|
||||
var text = (item.Type === 'Timer' || item.Type === 'SeriesTimer') ? globalize.translate('Edit') : globalize.translate('EditMetadata');
|
||||
|
||||
commands.push({
|
||||
name: text,
|
||||
commands.push({
|
||||
name: text,
|
||||
id: 'edit'
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (itemHelper.canEditImages(user, item)) {
|
||||
|
||||
if (options.editImages !== false) {
|
||||
commands.push({
|
||||
name: globalize.translate('EditImages'),
|
||||
|
@ -166,7 +157,6 @@ define(['apphost', 'globalize', 'connectionManager', 'itemHelper', 'appRouter',
|
|||
}
|
||||
|
||||
if (canEdit) {
|
||||
|
||||
if (item.MediaType === 'Video' && item.Type !== 'TvChannel' && item.Type !== 'Program' && item.LocationType !== 'Virtual' && !(item.Type === 'Recording' && item.Status !== 'Completed')) {
|
||||
if (options.editSubtitles !== false) {
|
||||
commands.push({
|
||||
|
@ -186,8 +176,16 @@ define(['apphost', 'globalize', 'connectionManager', 'itemHelper', 'appRouter',
|
|||
}
|
||||
}
|
||||
|
||||
if (item.Type === 'Program' && options.record !== false) {
|
||||
if (item.MediaSources) {
|
||||
if (options.moremediainfo !== false) {
|
||||
commands.push({
|
||||
name: globalize.translate('MoreMediaInfo'),
|
||||
id: 'moremediainfo'
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (item.Type === 'Program' && options.record !== false) {
|
||||
if (item.TimerId) {
|
||||
commands.push({
|
||||
name: Globalize.translate('ManageRecording'),
|
||||
|
@ -197,7 +195,6 @@ define(['apphost', 'globalize', 'connectionManager', 'itemHelper', 'appRouter',
|
|||
}
|
||||
|
||||
if (item.Type === 'Program' && options.record !== false) {
|
||||
|
||||
if (!item.TimerId) {
|
||||
commands.push({
|
||||
name: Globalize.translate('Record'),
|
||||
|
@ -265,7 +262,6 @@ define(['apphost', 'globalize', 'connectionManager', 'itemHelper', 'appRouter',
|
|||
}
|
||||
|
||||
function getResolveFunction(resolve, id, changed, deleted) {
|
||||
|
||||
return function () {
|
||||
resolve({
|
||||
command: id,
|
||||
|
@ -273,146 +269,108 @@ define(['apphost', 'globalize', 'connectionManager', 'itemHelper', 'appRouter',
|
|||
deleted: deleted
|
||||
});
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
function executeCommand(item, id, options) {
|
||||
|
||||
var itemId = item.Id;
|
||||
var serverId = item.ServerId;
|
||||
var apiClient = connectionManager.getApiClient(serverId);
|
||||
|
||||
return new Promise(function (resolve, reject) {
|
||||
|
||||
switch (id) {
|
||||
|
||||
case 'addtocollection':
|
||||
{
|
||||
require(['collectionEditor'], function (collectionEditor) {
|
||||
|
||||
new collectionEditor().show({
|
||||
require(['collectionEditor'], function (collectionEditor) {
|
||||
new collectionEditor().show({
|
||||
items: [itemId],
|
||||
serverId: serverId
|
||||
|
||||
}).then(getResolveFunction(resolve, id, true), getResolveFunction(resolve, id));
|
||||
}).then(getResolveFunction(resolve, id, true), getResolveFunction(resolve, id));
|
||||
});
|
||||
break;
|
||||
}
|
||||
case 'addtoplaylist':
|
||||
{
|
||||
require(['playlistEditor'], function (playlistEditor) {
|
||||
|
||||
new playlistEditor().show({
|
||||
require(['playlistEditor'], function (playlistEditor) {
|
||||
new playlistEditor().show({
|
||||
items: [itemId],
|
||||
serverId: serverId
|
||||
|
||||
}).then(getResolveFunction(resolve, id, true), getResolveFunction(resolve, id));
|
||||
}).then(getResolveFunction(resolve, id, true), getResolveFunction(resolve, id));
|
||||
});
|
||||
break;
|
||||
}
|
||||
case 'download':
|
||||
{
|
||||
require(['fileDownloader'], function (fileDownloader) {
|
||||
require(['fileDownloader'], function (fileDownloader) {
|
||||
var downloadHref = apiClient.getItemDownloadUrl(itemId);
|
||||
fileDownloader.download([{
|
||||
url: downloadHref,
|
||||
itemId: itemId,
|
||||
serverId: serverId
|
||||
}]);
|
||||
getResolveFunction(getResolveFunction(resolve, id), id)();
|
||||
fileDownloader.download([{
|
||||
url: downloadHref,
|
||||
itemId: itemId,
|
||||
serverId: serverId
|
||||
}]);
|
||||
getResolveFunction(getResolveFunction(resolve, id), id)();
|
||||
});
|
||||
break;
|
||||
}
|
||||
case 'editsubtitles':
|
||||
{
|
||||
require(['subtitleEditor'], function (subtitleEditor) {
|
||||
|
||||
subtitleEditor.show(itemId, serverId).then(getResolveFunction(resolve, id, true), getResolveFunction(resolve, id));
|
||||
require(['subtitleEditor'], function (subtitleEditor) {
|
||||
subtitleEditor.show(itemId, serverId).then(getResolveFunction(resolve, id, true), getResolveFunction(resolve, id));
|
||||
});
|
||||
break;
|
||||
}
|
||||
case 'edit':
|
||||
{
|
||||
editItem(apiClient, item).then(getResolveFunction(resolve, id, true), getResolveFunction(resolve, id));
|
||||
editItem(apiClient, item).then(getResolveFunction(resolve, id, true), getResolveFunction(resolve, id));
|
||||
break;
|
||||
}
|
||||
case 'editimages':
|
||||
{
|
||||
require(['imageEditor'], function (imageEditor) {
|
||||
|
||||
require(['imageEditor'], function (imageEditor) {
|
||||
imageEditor.show({
|
||||
itemId: itemId,
|
||||
serverId: serverId
|
||||
|
||||
}).then(getResolveFunction(resolve, id, true), getResolveFunction(resolve, id));
|
||||
}).then(getResolveFunction(resolve, id, true), getResolveFunction(resolve, id));
|
||||
});
|
||||
break;
|
||||
}
|
||||
case 'identify':
|
||||
{
|
||||
require(['itemIdentifier'], function (itemIdentifier) {
|
||||
|
||||
itemIdentifier.show(itemId, serverId).then(getResolveFunction(resolve, id, true), getResolveFunction(resolve, id));
|
||||
require(['itemIdentifier'], function (itemIdentifier) {
|
||||
itemIdentifier.show(itemId, serverId).then(getResolveFunction(resolve, id, true), getResolveFunction(resolve, id));
|
||||
});
|
||||
break;
|
||||
case 'moremediainfo':
|
||||
require(['itemMediaInfo'], function (itemMediaInfo) {
|
||||
itemMediaInfo.show(itemId, serverId).then(getResolveFunction(resolve, id, true), getResolveFunction(resolve, id));
|
||||
});
|
||||
break;
|
||||
}
|
||||
case 'refresh':
|
||||
{
|
||||
refresh(apiClient, item);
|
||||
getResolveFunction(resolve, id)();
|
||||
refresh(apiClient, item);
|
||||
getResolveFunction(resolve, id)();
|
||||
break;
|
||||
}
|
||||
case 'open':
|
||||
{
|
||||
appRouter.showItem(item);
|
||||
getResolveFunction(resolve, id)();
|
||||
appRouter.showItem(item);
|
||||
getResolveFunction(resolve, id)();
|
||||
break;
|
||||
}
|
||||
case 'play':
|
||||
{
|
||||
play(item, false);
|
||||
getResolveFunction(resolve, id)();
|
||||
play(item, false);
|
||||
getResolveFunction(resolve, id)();
|
||||
break;
|
||||
}
|
||||
case 'resume':
|
||||
{
|
||||
play(item, true);
|
||||
getResolveFunction(resolve, id)();
|
||||
play(item, true);
|
||||
getResolveFunction(resolve, id)();
|
||||
break;
|
||||
}
|
||||
case 'queue':
|
||||
{
|
||||
play(item, false, true);
|
||||
getResolveFunction(resolve, id)();
|
||||
play(item, false, true);
|
||||
getResolveFunction(resolve, id)();
|
||||
break;
|
||||
}
|
||||
case 'queuenext':
|
||||
{
|
||||
play(item, false, true, true);
|
||||
getResolveFunction(resolve, id)();
|
||||
play(item, false, true, true);
|
||||
getResolveFunction(resolve, id)();
|
||||
break;
|
||||
}
|
||||
case 'record':
|
||||
require(['recordingCreator'], function (recordingCreator) {
|
||||
recordingCreator.show(itemId, serverId).then(getResolveFunction(resolve, id, true), getResolveFunction(resolve, id));
|
||||
});
|
||||
break;
|
||||
case 'shuffle':
|
||||
{
|
||||
playbackManager.shuffle(item);
|
||||
getResolveFunction(resolve, id)();
|
||||
playbackManager.shuffle(item);
|
||||
getResolveFunction(resolve, id)();
|
||||
break;
|
||||
}
|
||||
case 'instantmix':
|
||||
{
|
||||
playbackManager.instantMix(item);
|
||||
getResolveFunction(resolve, id)();
|
||||
playbackManager.instantMix(item);
|
||||
getResolveFunction(resolve, id)();
|
||||
break;
|
||||
}
|
||||
case 'delete':
|
||||
{
|
||||
deleteItem(apiClient, item).then(getResolveFunction(resolve, id, true, true), getResolveFunction(resolve, id));
|
||||
deleteItem(apiClient, item).then(getResolveFunction(resolve, id, true, true), getResolveFunction(resolve, id));
|
||||
break;
|
||||
}
|
||||
case 'share':
|
||||
navigator.share({
|
||||
title: item.Name,
|
||||
|
@ -432,10 +390,8 @@ define(['apphost', 'globalize', 'connectionManager', 'itemHelper', 'appRouter',
|
|||
getResolveFunction(resolve, id)();
|
||||
break;
|
||||
case 'queueallfromhere':
|
||||
{
|
||||
getResolveFunction(resolve, id)();
|
||||
break;
|
||||
}
|
||||
case 'removefromplaylist':
|
||||
apiClient.ajax({
|
||||
url: apiClient.getUrl('Playlists/' + options.playlistId + '/Items', {
|
||||
|
@ -471,11 +427,8 @@ define(['apphost', 'globalize', 'connectionManager', 'itemHelper', 'appRouter',
|
|||
}
|
||||
|
||||
function deleteTimer(apiClient, item, resolve, command) {
|
||||
|
||||
require(['recordingHelper'], function (recordingHelper) {
|
||||
|
||||
var timerId = item.TimerId || item.Id;
|
||||
|
||||
recordingHelper.cancelTimerWithConfirmation(timerId, item.ServerId).then(function () {
|
||||
getResolveFunction(resolve, command, true)();
|
||||
});
|
||||
|
@ -483,9 +436,7 @@ define(['apphost', 'globalize', 'connectionManager', 'itemHelper', 'appRouter',
|
|||
}
|
||||
|
||||
function deleteSeriesTimer(apiClient, item, resolve, command) {
|
||||
|
||||
require(['recordingHelper'], function (recordingHelper) {
|
||||
|
||||
recordingHelper.cancelSeriesTimerWithConfirmation(item.Id, item.ServerId).then(function () {
|
||||
getResolveFunction(resolve, command, true)();
|
||||
});
|
||||
|
@ -493,7 +444,6 @@ define(['apphost', 'globalize', 'connectionManager', 'itemHelper', 'appRouter',
|
|||
}
|
||||
|
||||
function play(item, resume, queue, queueNext) {
|
||||
|
||||
var method = queue ? (queueNext ? 'queueNext' : 'queue') : 'play';
|
||||
|
||||
var startPosition = 0;
|
||||
|
@ -503,37 +453,32 @@ define(['apphost', 'globalize', 'connectionManager', 'itemHelper', 'appRouter',
|
|||
|
||||
if (item.Type === 'Program') {
|
||||
playbackManager[method]({
|
||||
ids: [item.ChannelId],
|
||||
startPositionTicks: startPosition,
|
||||
serverId: item.ServerId
|
||||
ids: [item.ChannelId],
|
||||
startPositionTicks: startPosition,
|
||||
serverId: item.ServerId
|
||||
});
|
||||
} else {
|
||||
playbackManager[method]({
|
||||
items: [item],
|
||||
startPositionTicks: startPosition
|
||||
items: [item],
|
||||
startPositionTicks: startPosition
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function editItem(apiClient, item) {
|
||||
|
||||
return new Promise(function (resolve, reject) {
|
||||
|
||||
var serverId = apiClient.serverInfo().Id;
|
||||
|
||||
if (item.Type === 'Timer') {
|
||||
require(['recordingEditor'], function (recordingEditor) {
|
||||
|
||||
recordingEditor.show(item.Id, serverId).then(resolve, reject);
|
||||
});
|
||||
} else if (item.Type === 'SeriesTimer') {
|
||||
require(['seriesRecordingEditor'], function (recordingEditor) {
|
||||
|
||||
recordingEditor.show(item.Id, serverId).then(resolve, reject);
|
||||
});
|
||||
} else {
|
||||
require(['metadataEditor'], function (metadataEditor) {
|
||||
|
||||
metadataEditor.show(item.Id, serverId).then(resolve, reject);
|
||||
});
|
||||
}
|
||||
|
@ -541,28 +486,19 @@ define(['apphost', 'globalize', 'connectionManager', 'itemHelper', 'appRouter',
|
|||
}
|
||||
|
||||
function deleteItem(apiClient, item) {
|
||||
|
||||
return new Promise(function (resolve, reject) {
|
||||
|
||||
require(['deleteHelper'], function (deleteHelper) {
|
||||
|
||||
deleteHelper.deleteItem({
|
||||
|
||||
item: item,
|
||||
navigate: false
|
||||
|
||||
}).then(function () {
|
||||
|
||||
resolve(true);
|
||||
|
||||
}, reject);
|
||||
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function refresh(apiClient, item) {
|
||||
|
||||
require(['refreshDialog'], function (refreshDialog) {
|
||||
new refreshDialog({
|
||||
itemIds: [item.Id],
|
||||
|
@ -573,20 +509,15 @@ define(['apphost', 'globalize', 'connectionManager', 'itemHelper', 'appRouter',
|
|||
}
|
||||
|
||||
function show(options) {
|
||||
|
||||
var commands = getCommands(options);
|
||||
|
||||
if (!commands.length) {
|
||||
return Promise.reject();
|
||||
}
|
||||
|
||||
return actionsheet.show({
|
||||
|
||||
items: commands,
|
||||
positionTo: options.positionTo,
|
||||
|
||||
resolveOnClick: ['share']
|
||||
|
||||
}).then(function (id) {
|
||||
return executeCommand(options.item, id, options);
|
||||
});
|
||||
|
@ -596,4 +527,4 @@ define(['apphost', 'globalize', 'connectionManager', 'itemHelper', 'appRouter',
|
|||
getCommands: getCommands,
|
||||
show: show
|
||||
};
|
||||
});
|
||||
});
|
||||
|
|
|
@ -301,7 +301,7 @@ define(["loading", "appRouter", "layoutManager", "connectionManager", "cardBuild
|
|||
var groupedVersions = (item.MediaSources || []).filter(function(g) {
|
||||
return "Grouping" == g.Type
|
||||
});
|
||||
user.Policy.IsAdministrator && groupedVersions.length ? page.querySelector(".splitVersionContainer").classList.remove("hide") : page.querySelector(".splitVersionContainer").classList.add("hide"), itemContextMenu.getCommands(getContextMenuOptions(item, user)).length ? hideAll(page, "btnMoreCommands", !0) : hideAll(page, "btnMoreCommands");
|
||||
user.Policy.IsAdministrator && groupedVersions.length ? page.querySelector(".btnSplitVersions").classList.remove("hide") : page.querySelector(".btnSplitVersions").classList.add("hide"), itemContextMenu.getCommands(getContextMenuOptions(item, user)).length ? hideAll(page, "btnMoreCommands", !0) : hideAll(page, "btnMoreCommands");
|
||||
var itemBirthday = page.querySelector("#itemBirthday");
|
||||
if ("Person" == item.Type && item.PremiereDate) try {
|
||||
var birthday = datetime.parseISO8601Date(item.PremiereDate, !0).toDateString();
|
||||
|
@ -474,7 +474,7 @@ define(["loading", "appRouter", "layoutManager", "connectionManager", "cardBuild
|
|||
}
|
||||
|
||||
function setInitialCollapsibleState(page, item, apiClient, context, user) {
|
||||
page.querySelector(".collectionItems").innerHTML = "", "Playlist" == item.Type ? (page.querySelector("#childrenCollapsible").classList.remove("hide"), renderPlaylistItems(page, item, user)) : "Studio" == item.Type || "Person" == item.Type || "Genre" == item.Type || "MusicGenre" == item.Type || "MusicArtist" == item.Type ? (page.querySelector("#childrenCollapsible").classList.remove("hide"), renderItemsByName(page, item, user)) : item.IsFolder ? ("BoxSet" == item.Type && page.querySelector("#childrenCollapsible").classList.add("hide"), renderChildren(page, item)) : page.querySelector("#childrenCollapsible").classList.add("hide"), "Series" == item.Type && renderSeriesSchedule(page, item, user), "Series" == item.Type ? renderNextUp(page, item, user) : page.querySelector(".nextUpSection").classList.add("hide"), item.MediaSources && item.MediaSources.length && (null == item.EnableMediaSourceDisplay ? "Channel" !== item.SourceType : item.EnableMediaSourceDisplay) ? renderMediaSources(page, user, item) : page.querySelector(".audioVideoMediaInfo").classList.add("hide"), renderScenes(page, item), item.SpecialFeatureCount && 0 != item.SpecialFeatureCount && "Series" != item.Type ? (page.querySelector("#specialsCollapsible").classList.remove("hide"), renderSpecials(page, item, user, 6)) : page.querySelector("#specialsCollapsible").classList.add("hide"), renderCast(page, item, context, enableScrollX() ? null : 12), item.PartCount && item.PartCount > 1 ? (page.querySelector("#additionalPartsCollapsible").classList.remove("hide"), renderAdditionalParts(page, item, user)) : page.querySelector("#additionalPartsCollapsible").classList.add("hide"), "MusicAlbum" == item.Type ? renderMusicVideos(page, item, user) : page.querySelector("#musicVideosCollapsible").classList.add("hide")
|
||||
page.querySelector(".collectionItems").innerHTML = "", "Playlist" == item.Type ? (page.querySelector("#childrenCollapsible").classList.remove("hide"), renderPlaylistItems(page, item, user)) : "Studio" == item.Type || "Person" == item.Type || "Genre" == item.Type || "MusicGenre" == item.Type || "MusicArtist" == item.Type ? (page.querySelector("#childrenCollapsible").classList.remove("hide"), renderItemsByName(page, item, user)) : item.IsFolder ? ("BoxSet" == item.Type && page.querySelector("#childrenCollapsible").classList.add("hide"), renderChildren(page, item)) : page.querySelector("#childrenCollapsible").classList.add("hide"), "Series" == item.Type && renderSeriesSchedule(page, item, user), "Series" == item.Type ? renderNextUp(page, item, user) : page.querySelector(".nextUpSection").classList.add("hide"), renderScenes(page, item), item.SpecialFeatureCount && 0 != item.SpecialFeatureCount && "Series" != item.Type ? (page.querySelector("#specialsCollapsible").classList.remove("hide"), renderSpecials(page, item, user, 6)) : page.querySelector("#specialsCollapsible").classList.add("hide"), renderCast(page, item, context, enableScrollX() ? null : 12), item.PartCount && item.PartCount > 1 ? (page.querySelector("#additionalPartsCollapsible").classList.remove("hide"), renderAdditionalParts(page, item, user)) : page.querySelector("#additionalPartsCollapsible").classList.add("hide"), "MusicAlbum" == item.Type ? renderMusicVideos(page, item, user) : page.querySelector("#musicVideosCollapsible").classList.add("hide")
|
||||
}
|
||||
|
||||
function renderOverview(elems, item) {
|
||||
|
@ -671,8 +671,8 @@ define(["loading", "appRouter", "layoutManager", "connectionManager", "cardBuild
|
|||
if ("Series" != item.Type) return void seriesAirTime.classList.add("hide");
|
||||
var html = "";
|
||||
if (item.AirDays && item.AirDays.length && (html += 7 == item.AirDays.length ? "daily" : item.AirDays.map(function(a) {
|
||||
return a + "s"
|
||||
}).join(",")), item.AirTime && (html += " at " + item.AirTime), item.Studios.length)
|
||||
return a + "s"
|
||||
}).join(",")), item.AirTime && (html += " at " + item.AirTime), item.Studios.length)
|
||||
if (isStatic) html += " on " + item.Studios[0].Name;
|
||||
else {
|
||||
var context = inferContext(item),
|
||||
|
@ -976,54 +976,6 @@ define(["loading", "appRouter", "layoutManager", "connectionManager", "cardBuild
|
|||
} else page.querySelector("#scenesCollapsible").classList.add("hide")
|
||||
}
|
||||
|
||||
function renderMediaSources(page, user, item) {
|
||||
var html = item.MediaSources.map(function(v) {
|
||||
return getMediaSourceHtml(user, item, v)
|
||||
}).join('<div style="border-top:1px solid #444;margin: 1em 0;"></div>');
|
||||
item.MediaSources.length > 1 && (html = "<br/>" + html), page.querySelector("#mediaInfoContent").innerHTML = html, html ? page.querySelector(".audioVideoMediaInfo").classList.remove("hide") : page.querySelector(".audioVideoMediaInfo").classList.add("hide")
|
||||
}
|
||||
|
||||
function getMediaSourceHtml(user, item, version) {
|
||||
var html = "";
|
||||
version.Name && item.MediaSources.length > 1 && (html += '<div><span class="mediaInfoAttribute">' + version.Name + "</span></div><br/>");
|
||||
for (var i = 0, length = version.MediaStreams.length; i < length; i++) {
|
||||
var stream = version.MediaStreams[i];
|
||||
if ("Data" != stream.Type) {
|
||||
html += '<div class="mediaInfoStream">';
|
||||
html += '<h3 class="mediaInfoStreamType">';
|
||||
switch (stream.Type) {
|
||||
case 'Audio':
|
||||
html += globalize.translate("MediaInfoStreamTypeAudio");
|
||||
break;
|
||||
case 'Subtitle':
|
||||
html += globalize.translate("MediaInfoStreamTypeSubtitle");
|
||||
break;
|
||||
case 'Video':
|
||||
html += globalize.translate("MediaInfoStreamTypeVideo");
|
||||
break;
|
||||
case 'Data':
|
||||
html += globalize.translate("MediaInfoStreamTypeData");
|
||||
break;
|
||||
case 'EmbeddedImage':
|
||||
html += globalize.translate("MediaInfoStreamTypeEmbeddedImage");
|
||||
break;
|
||||
}
|
||||
html += "</h3>";
|
||||
var attributes = [];
|
||||
stream.DisplayTitle && attributes.push(createAttribute("Title", stream.DisplayTitle)), stream.Language && "Video" != stream.Type && attributes.push(createAttribute(globalize.translate("MediaInfoLanguage"), stream.Language)), stream.Codec && attributes.push(createAttribute(globalize.translate("MediaInfoCodec"), stream.Codec.toUpperCase())), stream.CodecTag && attributes.push(createAttribute(globalize.translate("MediaInfoCodecTag"), stream.CodecTag)), null != stream.IsAVC && attributes.push(createAttribute("AVC", stream.IsAVC ? "Yes" : "No")), stream.Profile && attributes.push(createAttribute(globalize.translate("MediaInfoProfile"), stream.Profile)), stream.Level && attributes.push(createAttribute(globalize.translate("MediaInfoLevel"), stream.Level)), (stream.Width || stream.Height) && attributes.push(createAttribute(globalize.translate("MediaInfoResolution"), stream.Width + "x" + stream.Height)), stream.AspectRatio && "mjpeg" != stream.Codec && attributes.push(createAttribute(globalize.translate("MediaInfoAspectRatio"), stream.AspectRatio)), "Video" == stream.Type && (null != stream.IsAnamorphic && attributes.push(createAttribute(globalize.translate("MediaInfoAnamorphic"), stream.IsAnamorphic ? "Yes" : "No")), attributes.push(createAttribute(globalize.translate("MediaInfoInterlaced"), stream.IsInterlaced ? "Yes" : "No"))), (stream.AverageFrameRate || stream.RealFrameRate) && attributes.push(createAttribute(globalize.translate("MediaInfoFramerate"), stream.AverageFrameRate || stream.RealFrameRate)), stream.ChannelLayout && attributes.push(createAttribute(globalize.translate("MediaInfoLayout"), stream.ChannelLayout)), stream.Channels && attributes.push(createAttribute(globalize.translate("MediaInfoChannels"), stream.Channels + " ch")), stream.BitRate && "mjpeg" != stream.Codec && attributes.push(createAttribute(globalize.translate("MediaInfoBitrate"), parseInt(stream.BitRate / 1e3) + " kbps")), stream.SampleRate && attributes.push(createAttribute(globalize.translate("MediaInfoSampleRate"), stream.SampleRate + " Hz")), stream.VideoRange && "SDR" !== stream.VideoRange && attributes.push(createAttribute(globalize.translate("VideoRange"), stream.VideoRange)), stream.ColorPrimaries && attributes.push(createAttribute(globalize.translate("ColorPrimaries"), stream.ColorPrimaries)), stream.ColorSpace && attributes.push(createAttribute(globalize.translate("ColorSpace"), stream.ColorSpace)), stream.ColorTransfer && attributes.push(createAttribute(globalize.translate("ColorTransfer"), stream.ColorTransfer)), stream.BitDepth && attributes.push(createAttribute(globalize.translate("MediaInfoBitDepth"), stream.BitDepth + " bit")), stream.PixelFormat && attributes.push(createAttribute(globalize.translate("MediaInfoPixelFormat"), stream.PixelFormat)), stream.RefFrames && attributes.push(createAttribute(globalize.translate("MediaInfoRefFrames"), stream.RefFrames)), stream.NalLengthSize && attributes.push(createAttribute("NAL", stream.NalLengthSize)), "Video" != stream.Type && attributes.push(createAttribute(globalize.translate("MediaInfoDefault"), stream.IsDefault ? "Yes" : "No")), "Subtitle" == stream.Type && (attributes.push(createAttribute(globalize.translate("MediaInfoForced"), stream.IsForced ? "Yes" : "No")), attributes.push(createAttribute(globalize.translate("MediaInfoExternal"), stream.IsExternal ? "Yes" : "No"))), "Video" == stream.Type && version.Timestamp && attributes.push(createAttribute(globalize.translate("MediaInfoTimestamp"), version.Timestamp)), html += attributes.join("<br/>"), html += "</div>"
|
||||
}
|
||||
}
|
||||
if (version.Container && (html += '<div><span class="mediaInfoLabel">' + globalize.translate("MediaInfoContainer") + '</span><span class="mediaInfoAttribute">' + version.Container + "</span></div>"), version.Formats && version.Formats.length, version.Path && "Http" != version.Protocol && user && user.Policy.IsAdministrator && (html += '<div><span class="mediaInfoLabel">' + globalize.translate("MediaInfoPath") + '</span><span class="mediaInfoAttribute">' + version.Path + "</span></div>"), version.Size) {
|
||||
var size = (version.Size / 1048576).toFixed(0);
|
||||
html += '<div><span class="mediaInfoLabel">' + globalize.translate("MediaInfoSize") + '</span><span class="mediaInfoAttribute">' + size + " MB</span></div>"
|
||||
}
|
||||
return html
|
||||
}
|
||||
|
||||
function createAttribute(label, value) {
|
||||
return '<span class="mediaInfoLabel">' + label + '</span><span class="mediaInfoAttribute">' + value + "</span>"
|
||||
}
|
||||
|
||||
function getVideosHtml(items, user, limit, moreButtonClass) {
|
||||
var html = cardBuilder.getCardsHtml({
|
||||
items: items,
|
||||
|
@ -1064,7 +1016,7 @@ define(["loading", "appRouter", "layoutManager", "connectionManager", "cardBuild
|
|||
|
||||
function itemDetailPage() {
|
||||
var self = this;
|
||||
self.setInitialCollapsibleState = setInitialCollapsibleState, self.renderDetails = renderDetails, self.renderCast = renderCast, self.renderMediaSources = renderMediaSources
|
||||
self.setInitialCollapsibleState = setInitialCollapsibleState, self.renderDetails = renderDetails, self.renderCast = renderCast
|
||||
}
|
||||
|
||||
function bindAll(view, selector, eventName, fn) {
|
||||
|
|
|
@ -170,6 +170,10 @@
|
|||
<i class="md-icon"></i>
|
||||
</button>
|
||||
|
||||
<button is="emby-button" type="button" class="fab btnSplitVersions hide detailButton">
|
||||
<i class="md-icon"></i>
|
||||
</button>
|
||||
|
||||
<button is="emby-button" type="button" class="button-flat btnMoreCommands hide detailButton-mobile">
|
||||
<div class="detailButton-mobile-content">
|
||||
<i class="md-icon detailButton-mobile-icon"></i>
|
||||
|
@ -303,15 +307,5 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="verticalSection detailVerticalSection audioVideoMediaInfo hide">
|
||||
<h2 class="sectionTitle padded-left" style="margin-bottom:0;">${HeaderMediaInfo}</h2>
|
||||
<div class="padded-left padded-right">
|
||||
<div class="splitVersionContainer" style="border-bottom: 1px solid #444; padding: 1em 0;">
|
||||
<button is="emby-button" type="button" class="raised btnSplitVersions subdued">${ButtonSplitVersionsApart}</button>
|
||||
</div>
|
||||
<div id="mediaInfoContent" class="mediaInfoContent"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -765,6 +765,7 @@ var AppInfo = {};
|
|||
define("subtitleEditor", [componentsPath + "/subtitleeditor/subtitleeditor"], returnFirstDependency);
|
||||
define("subtitleSync", [componentsPath + "/subtitlesync/subtitlesync"], returnFirstDependency);
|
||||
define("itemIdentifier", [componentsPath + "/itemidentifier/itemidentifier"], returnFirstDependency);
|
||||
define("itemMediaInfo", [componentsPath + "/itemMediaInfo/itemMediaInfo"], returnFirstDependency);
|
||||
define("mediaInfo", [componentsPath + "/mediainfo/mediainfo"], returnFirstDependency);
|
||||
define("itemContextMenu", [componentsPath + "/itemcontextmenu"], returnFirstDependency);
|
||||
define("imageEditor", [componentsPath + "/imageeditor/imageeditor"], returnFirstDependency);
|
||||
|
|
|
@ -989,6 +989,7 @@
|
|||
"Monday": "Monday",
|
||||
"MoreFromValue": "More from {0}",
|
||||
"MoreUsersCanBeAddedLater": "More users can be added later from within the dashboard.",
|
||||
"MoreMediaInfo": "Media Info",
|
||||
"MoveLeft": "Move left",
|
||||
"MoveRight": "Move right",
|
||||
"MovieLibraryHelp": "Review the {0}Jellyfin movie naming guide{1}.",
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue