mirror of
https://github.com/jellyfin/jellyfin-web
synced 2025-03-30 19:56:21 +00:00
Merge branch 'dev' of https://github.com/MediaBrowser/MediaBrowser into dev
This commit is contained in:
commit
bb77192e8c
21 changed files with 404 additions and 151 deletions
|
@ -275,10 +275,6 @@
|
|||
|
||||
@media all and (min-width: 540px) {
|
||||
|
||||
.portraitCard {
|
||||
width: 25%;
|
||||
}
|
||||
|
||||
.smallBackdropCard {
|
||||
width: 33.3%;
|
||||
}
|
||||
|
@ -287,6 +283,12 @@
|
|||
|
||||
@media all and (min-width: 640px) {
|
||||
|
||||
.portraitCard {
|
||||
width: 25%;
|
||||
}
|
||||
}
|
||||
|
||||
@media all and (min-width: 700px) {
|
||||
.backdropCard {
|
||||
width: 33.3%;
|
||||
}
|
||||
|
@ -296,7 +298,6 @@
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
@media all and (min-width: 800px) {
|
||||
|
||||
.squareCard {
|
||||
|
@ -319,10 +320,6 @@
|
|||
width: 20%;
|
||||
}
|
||||
|
||||
.backdropCard {
|
||||
width: 25%;
|
||||
}
|
||||
|
||||
.smallBackdropCard {
|
||||
width: 20%;
|
||||
}
|
||||
|
@ -331,6 +328,10 @@
|
|||
|
||||
@media all and (min-width: 1200px) {
|
||||
|
||||
.backdropCard {
|
||||
width: 25%;
|
||||
}
|
||||
|
||||
.squareCard {
|
||||
width: 16.666666666666666666666666666667%;
|
||||
}
|
||||
|
@ -483,15 +484,6 @@
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
@media all and (min-width: 600px) {
|
||||
|
||||
.detailPageSquareCard {
|
||||
width: 20%;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** homePageSmallBackdropCard */
|
||||
.homePageSmallBackdropCard .cardPadder {
|
||||
padding-bottom: 56.25%;
|
||||
|
|
|
@ -384,7 +384,7 @@ span.itemCommunityRating:not(:empty) + .userDataIcons {
|
|||
|
||||
.noBackdrop {
|
||||
height: auto;
|
||||
margin: 2.5em 0 0;
|
||||
margin: 3em 0 0;
|
||||
}
|
||||
|
||||
.noBackdrop .itemBackdropContent {
|
||||
|
@ -633,7 +633,7 @@ span.itemCommunityRating:not(:empty) + .userDataIcons {
|
|||
|
||||
.detailSection {
|
||||
vertical-align: top;
|
||||
margin-bottom: 2em;
|
||||
margin-bottom: 2.5em;
|
||||
}
|
||||
|
||||
.detailCollapsibleSection:not(.hide) + .detailCollapsibleSection {
|
||||
|
@ -664,7 +664,7 @@ span.itemCommunityRating:not(:empty) + .userDataIcons {
|
|||
}
|
||||
|
||||
.detailSectionHeader, .detailSectionHeader h3 {
|
||||
font-size: 16px;
|
||||
font-size: 17px;
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
|
@ -754,13 +754,37 @@ span.itemCommunityRating:not(:empty) + .userDataIcons {
|
|||
|
||||
@media all and (max-width: 800px) {
|
||||
|
||||
.editorMenuLink {
|
||||
display: none;
|
||||
.itemBackdrop:not(.noBackdrop) {
|
||||
height: 500px;
|
||||
}
|
||||
}
|
||||
|
||||
@media all and (max-height: 800px), (max-width: 700px) {
|
||||
|
||||
.itemBackdrop:not(.noBackdrop) {
|
||||
height: 400px;
|
||||
}
|
||||
}
|
||||
|
||||
@media all and (max-height: 700px) {
|
||||
|
||||
.itemBackdrop:not(.noBackdrop) {
|
||||
height: 340px;
|
||||
}
|
||||
}
|
||||
|
||||
@media all and (max-height: 600px), (max-width: 600px) {
|
||||
|
||||
.itemBackdrop:not(.noBackdrop) {
|
||||
height: 280px;
|
||||
}
|
||||
}
|
||||
|
||||
@media all and (max-width: 800px) {
|
||||
|
||||
.editorMenuLink {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.itemDetailImage {
|
||||
max-height: 240px;
|
||||
|
|
|
@ -8,10 +8,14 @@
|
|||
|
||||
.libraryMenuDivider {
|
||||
height: 1px;
|
||||
background: #333;
|
||||
background: #282828;
|
||||
margin: .5em 0;
|
||||
}
|
||||
|
||||
.headerBackButton {
|
||||
padding-right: 0 !important;
|
||||
}
|
||||
|
||||
.viewMenuBar, .barsMenuButton, .libraryMenuButtonText, .btnCast {
|
||||
height: 50px;
|
||||
}
|
||||
|
@ -50,7 +54,6 @@
|
|||
}
|
||||
|
||||
.headerButtonLeft {
|
||||
float: left;
|
||||
padding: 0 15px;
|
||||
}
|
||||
|
||||
|
@ -176,23 +179,23 @@
|
|||
vertical-align: top;
|
||||
}
|
||||
|
||||
.librarySidebarLinks a {
|
||||
font-weight: 300 !important;
|
||||
.librarySidebarLinks {
|
||||
margin-left: -1em;
|
||||
margin-right: -1em;
|
||||
margin-top: -1em;
|
||||
padding-top: 0;
|
||||
}
|
||||
|
||||
.librarySidebarLinks a {
|
||||
font-weight: 300 !important;
|
||||
padding: .7em 20px .7em 0;
|
||||
}
|
||||
|
||||
.librarySidebarLinks a:hover {
|
||||
background-color: #38c !important;
|
||||
color: #fff !important;
|
||||
}
|
||||
|
||||
.homeViewMenu {
|
||||
background-image: url(images/mblogoicon.png) !important;
|
||||
background-size: 39px 26px !important;
|
||||
background-position: 13px center !important;
|
||||
padding-left: 66px !important;
|
||||
background-repeat: no-repeat !important;
|
||||
}
|
||||
|
||||
.viewMenuSecondary {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
|
@ -210,7 +213,7 @@
|
|||
}
|
||||
|
||||
.ui-panel.ui-body-b {
|
||||
background-color: #222;
|
||||
background-color: #161616;
|
||||
}
|
||||
|
||||
.libraryViewNav .ui-btn-active {
|
||||
|
|
|
@ -130,8 +130,8 @@
|
|||
}
|
||||
|
||||
/* Hack for safari because it doesn't allow clickable content over the video surface. */
|
||||
.itemVideo { (;top: 9%!important;height: 91% !important;); }
|
||||
.itemVideo { [;top: 9%!important;height: 91% !important;]; }
|
||||
/*.itemVideo { (;top: 9%!important;height: 91% !important;); }
|
||||
.itemVideo { [;top: 9%!important;height: 91% !important;]; }*/
|
||||
|
||||
#mediaPlayer .ui-slider-track, .nowPlayingBar .ui-slider-track, .nowPlayingPage .ui-slider-track {
|
||||
border-color: #2ad !important;
|
||||
|
|
|
@ -156,6 +156,12 @@ h1 a:hover {
|
|||
display: none;
|
||||
}
|
||||
|
||||
.ui-slider-track.ui-mini .ui-slider-handle {
|
||||
height: 18px;
|
||||
width: 18px;
|
||||
margin: -10px 0 0 -10px;
|
||||
}
|
||||
|
||||
.largePanel {
|
||||
width: 270px;
|
||||
}
|
||||
|
@ -382,6 +388,7 @@ h1 .imageLink {
|
|||
font-size: 17px;
|
||||
width: 66px;
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.ui-page-theme-a .sidebarLinkIcon {
|
||||
|
|
|
@ -110,6 +110,12 @@
|
|||
<a href="gamestudios.html">${TabStudios}</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="itemTabs channelTabs" style="display: none;">
|
||||
<div class="libraryViewNav scopedLibraryViewNav">
|
||||
<a href="channelslatest.html">${TabLatest}</a>
|
||||
<a href="channels.html" class="ui-btn-active">${TabChannels}</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="channelHeader" style="display: none;"></div>
|
||||
|
||||
|
|
|
@ -121,6 +121,35 @@
|
|||
</select>
|
||||
</div>
|
||||
<br />
|
||||
<div>
|
||||
<label for="selectMaxChromecastBitrate">${LabelMaxChromecastBitrate}</label>
|
||||
<select id="selectMaxChromecastBitrate" data-mini="true">
|
||||
<option value="30000000">30Mbps</option>
|
||||
<option value="25000000">25Mbps</option>
|
||||
<option value="20000000">20Mbps</option>
|
||||
<option value="15000000">15Mbps</option>
|
||||
<option value="12000000">12Mbps</option>
|
||||
<option value="11000000">11Mbps</option>
|
||||
<option value="10000000">10Mbps</option>
|
||||
<option value="9000000">9Mbps</option>
|
||||
<option value="8000000">8Mbps</option>
|
||||
<option value="7000000">7Mbps</option>
|
||||
<option value="6000000">6Mbps</option>
|
||||
<option value="5000000">5Mbps</option>
|
||||
<option value="4000000">4Mbps</option>
|
||||
<option value="3000000">3Mbps</option>
|
||||
<option value="2500000">2.5Mbps</option>
|
||||
<option value="2000000">2Mbps</option>
|
||||
<option value="1500000">1.5Mbps</option>
|
||||
<option value="1000000">1Mbps</option>
|
||||
<option value="720000">720kbps</option>
|
||||
<option value="420000">420kbps</option>
|
||||
<option value="400000">400kbps</option>
|
||||
<option value="320000">320kbps</option>
|
||||
<option value="192000">192kbps</option>
|
||||
</select>
|
||||
</div>
|
||||
<br />
|
||||
<div>
|
||||
<label for="selectThemeSong">${LabelEnableThemeSongs}</label>
|
||||
<select id="selectThemeSong" data-mini="true">
|
||||
|
|
|
@ -336,8 +336,7 @@
|
|||
|
||||
var player = this;
|
||||
|
||||
var bitrateSetting = AppSettings.maxStreamingBitrate();
|
||||
bitrateSetting = Math.min(bitrateSetting, 10000000);
|
||||
var bitrateSetting = AppSettings.maxChromecastBitrate();
|
||||
|
||||
var receiverName = null;
|
||||
|
||||
|
|
|
@ -155,49 +155,49 @@
|
|||
if (item.MovieCount) {
|
||||
|
||||
html += '<input type="radio" name="ibnItems" id="radioMovies" class="context-movies" value="on">';
|
||||
html += '<label for="radioMovies">'+Globalize.translate('TabMovies')+'</label>';
|
||||
html += '<label for="radioMovies">' + Globalize.translate('TabMovies') + '</label>';
|
||||
}
|
||||
|
||||
if (item.SeriesCount) {
|
||||
|
||||
html += '<input type="radio" name="ibnItems" id="radioShows" class="context-tv" value="on">';
|
||||
html += '<label for="radioShows">'+Globalize.translate('TabSeries')+'</label>';
|
||||
html += '<label for="radioShows">' + Globalize.translate('TabSeries') + '</label>';
|
||||
}
|
||||
|
||||
if (item.EpisodeCount) {
|
||||
|
||||
html += '<input type="radio" name="ibnItems" id="radioEpisodes" class="context-tv" value="on">';
|
||||
html += '<label for="radioEpisodes">'+Globalize.translate('TabEpisodes')+'</label>';
|
||||
html += '<label for="radioEpisodes">' + Globalize.translate('TabEpisodes') + '</label>';
|
||||
}
|
||||
|
||||
if (item.TrailerCount) {
|
||||
|
||||
html += '<input type="radio" name="ibnItems" id="radioTrailers" class="context-movies" value="on">';
|
||||
html += '<label for="radioTrailers">'+Globalize.translate('TabTrailers')+'</label>';
|
||||
html += '<label for="radioTrailers">' + Globalize.translate('TabTrailers') + '</label>';
|
||||
}
|
||||
|
||||
if (item.GameCount) {
|
||||
|
||||
html += '<input type="radio" name="ibnItems" id="radioGames" class="context-games" value="on">';
|
||||
html += '<label for="radioGames">'+Globalize.translate('TabGames')+'</label>';
|
||||
html += '<label for="radioGames">' + Globalize.translate('TabGames') + '</label>';
|
||||
}
|
||||
|
||||
if (item.AlbumCount) {
|
||||
|
||||
html += '<input type="radio" name="ibnItems" id="radioAlbums" class="context-music" value="on">';
|
||||
html += '<label for="radioAlbums">'+Globalize.translate('TabAlbums')+'</label>';
|
||||
html += '<label for="radioAlbums">' + Globalize.translate('TabAlbums') + '</label>';
|
||||
}
|
||||
|
||||
if (item.SongCount) {
|
||||
|
||||
html += '<input type="radio" name="ibnItems" id="radioSongs" class="context-music" value="on">';
|
||||
html += '<label for="radioSongs">'+Globalize.translate('TabSongs')+'</label>';
|
||||
html += '<label for="radioSongs">' + Globalize.translate('TabSongs') + '</label>';
|
||||
}
|
||||
|
||||
if (item.MusicVideoCount) {
|
||||
|
||||
html += '<input type="radio" name="ibnItems" id="radioMusicVideos" class="context-music" value="on">';
|
||||
html += '<label for="radioMusicVideos">'+Globalize.translate('TabMusicVideos')+'</label>';
|
||||
html += '<label for="radioMusicVideos">' + Globalize.translate('TabMusicVideos') + '</label>';
|
||||
}
|
||||
|
||||
html += '</fieldset>';
|
||||
|
@ -385,7 +385,7 @@
|
|||
}
|
||||
}
|
||||
|
||||
function getItemsFunction(options) {
|
||||
function getQuery(options) {
|
||||
|
||||
var query = {
|
||||
|
||||
|
@ -407,6 +407,13 @@
|
|||
|
||||
addCurrentItemToQuery(query);
|
||||
|
||||
return query;
|
||||
}
|
||||
|
||||
function getItemsFunction(options) {
|
||||
|
||||
var query = getQuery(options);
|
||||
|
||||
return function (index, limit, fields) {
|
||||
|
||||
query.StartIndex = index;
|
||||
|
@ -424,27 +431,10 @@
|
|||
Dashboard.showLoadingMsg();
|
||||
|
||||
_childrenItemsFunction = getItemsFunction(options);
|
||||
var query = {
|
||||
|
||||
SortBy: "SortName",
|
||||
SortOrder: "Ascending",
|
||||
IncludeItemTypes: "",
|
||||
Recursive: true,
|
||||
Fields: "AudioInfo,SeriesInfo,ParentId,PrimaryImageAspectRatio,SyncInfo",
|
||||
Limit: LibraryBrowser.getDefaultPageSize(),
|
||||
StartIndex: 0,
|
||||
CollapseBoxSetItems: false
|
||||
};
|
||||
var query = getQuery(options);
|
||||
|
||||
query = $.extend(query, options || {});
|
||||
|
||||
if (query.IncludeItemTypes == "Audio") {
|
||||
query.SortBy = "AlbumArtist,Album,SortName";
|
||||
}
|
||||
|
||||
addCurrentItemToQuery(query);
|
||||
|
||||
ApiClient.getItems(Dashboard.getCurrentUserId(), query).done(function (result) {
|
||||
getItemsFunction(options)(options.StartIndex, options.Limit, options.Fields).done(function (result) {
|
||||
|
||||
var html = '';
|
||||
|
||||
|
|
|
@ -282,6 +282,9 @@
|
|||
$('.lnkMovies', page).addClass('ui-btn-active');
|
||||
}
|
||||
}
|
||||
else if (context == 'channels') {
|
||||
elem = $('.channelTabs', page).show();
|
||||
}
|
||||
else if (item.Type == "MusicAlbum") {
|
||||
$('#albumTabs', page).show();
|
||||
}
|
||||
|
@ -627,6 +630,7 @@
|
|||
promise = ApiClient.getSimilarTrailers(item.Id, options);
|
||||
}
|
||||
else if (item.Type == "MusicAlbum") {
|
||||
options.limit = 4;
|
||||
promise = ApiClient.getSimilarAlbums(item.Id, options);
|
||||
}
|
||||
else if (item.Type == "Series") {
|
||||
|
@ -1314,7 +1318,7 @@
|
|||
if (stream.ChannelLayout) {
|
||||
attributes.push(createAttribute(Globalize.translate('MediaInfoLayout'), stream.ChannelLayout));
|
||||
}
|
||||
else if (stream.Channels) {
|
||||
if (stream.Channels) {
|
||||
attributes.push(createAttribute(Globalize.translate('MediaInfoChannels'), stream.Channels + ' ch'));
|
||||
}
|
||||
|
||||
|
|
|
@ -4,6 +4,10 @@
|
|||
|
||||
var html = '<div class="viewMenuBar ui-bar-b">';
|
||||
|
||||
if ($.browser.safari && $.browser.mobile && window.navigator.standalone) {
|
||||
html += '<a data-rel="back" data-role="none" href="#" class="headerButton headerButtonLeft headerBackButton"><div class="fa fa-arrow-circle-o-left"></div></a>';
|
||||
}
|
||||
|
||||
html += '<button type="button" data-role="none" title="Menu" class="headerButton dashboardMenuButton barsMenuButton headerButtonLeft">';
|
||||
html += '<div class="barMenuInner fa fa-bars">';
|
||||
html += '</div>';
|
||||
|
@ -46,7 +50,7 @@
|
|||
var url = user.imageUrl;
|
||||
|
||||
if (user.supportsImageParams) {
|
||||
url += "&height=" + userButtonHeight;
|
||||
url += "&height=" + (userButtonHeight * Math.max(devicePixelRatio || 1, 2));
|
||||
}
|
||||
|
||||
html += '<img src="' + url + '" style="border-radius: 1000px; height:' + userButtonHeight + 'px;" />';
|
||||
|
@ -68,10 +72,25 @@
|
|||
$('.viewMenuBar').trigger('create');
|
||||
|
||||
$(document).trigger('headercreated');
|
||||
bindMenuEvents();
|
||||
}
|
||||
|
||||
function bindMenuEvents() {
|
||||
|
||||
if ($.browser.mobile) {
|
||||
|
||||
$('.libraryMenuButton').on('mousedown', function () {
|
||||
showLibraryMenu(false);
|
||||
});
|
||||
$('.dashboardMenuButton').on('mousedown', function () {
|
||||
showDashboardMenu(false);
|
||||
});
|
||||
|
||||
} else {
|
||||
$('.libraryMenuButton').createHoverTouch().on('hovertouch', showLibraryMenu);
|
||||
$('.dashboardMenuButton').createHoverTouch().on('hovertouch', showDashboardMenu);
|
||||
}
|
||||
}
|
||||
|
||||
function getItemHref(item, context) {
|
||||
|
||||
|
@ -102,7 +121,9 @@
|
|||
var page = $.mobile.activePage;
|
||||
var panel;
|
||||
|
||||
panel = getLibraryMenu();
|
||||
ConnectionManager.user().done(function (user) {
|
||||
|
||||
panel = getLibraryMenu(user);
|
||||
updateLibraryNavLinks(page);
|
||||
|
||||
$(panel).panel('toggle').off('mouseleave.librarymenu').on('mouseleave.librarymenu', function () {
|
||||
|
@ -110,6 +131,7 @@
|
|||
$(this).panel("close");
|
||||
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function showDashboardMenu() {
|
||||
|
@ -229,13 +251,42 @@
|
|||
|
||||
html += '<div data-role="panel" id="libraryPanel" class="libraryPanel" data-position="left" data-display="overlay" data-position-fixed="true" data-theme="b">';
|
||||
|
||||
html += '<div class="sidebarLinks librarySidebarLinks" style="margin-top: 0;margin-left: -1em;margin-right: -1em;">';
|
||||
html += '<div class="sidebarLinks librarySidebarLinks">';
|
||||
|
||||
//var userHref = user.localUser && user.localUser.Policy.EnableUserPreferenceAccess ?
|
||||
// 'mypreferencesdisplay.html?userId=' + user.localUser.Id :
|
||||
// (user.localUser ? 'index.html' : '#');
|
||||
|
||||
//var paddingLeft = user.imageUrl ? 'padding-left:.7em;' : '';
|
||||
//html += '<a style="margin-top:0;' + paddingLeft + 'display:block;color:#fff;text-decoration:none;font-size:16px;font-weight:400!important;background: #000;" href="' + userHref + '">';
|
||||
|
||||
//var imgWidth = 44;
|
||||
|
||||
//if (user.imageUrl) {
|
||||
// var url = user.imageUrl;
|
||||
|
||||
// if (user.supportsImageParams) {
|
||||
// url += "&width=" + (imgWidth * Math.max(devicePixelRatio || 1, 2));
|
||||
// }
|
||||
|
||||
// html += '<img style="max-width:' + imgWidth + 'px;vertical-align:middle;margin-right:.8em;border-radius: 50px;" src="' + url + '" />';
|
||||
//} else {
|
||||
// html += '<span class="fa fa-user sidebarLinkIcon"></span>';
|
||||
//}
|
||||
|
||||
//html += user.name;
|
||||
//html += '</a>';
|
||||
|
||||
var homeHref = ConnectionManager.currentApiClient() ? 'index.html' : 'selectserver.html';
|
||||
|
||||
html += '<a class="lnkMediaFolder sidebarLink homeViewMenu" href="' + homeHref + '">' + Globalize.translate('ButtonHome') + '</a>';
|
||||
html += '<a class="lnkMediaFolder sidebarLink" style="margin-top:.5em;padding-left:1em;display:block;color:#fff;text-decoration:none;" href="' + homeHref + '">';
|
||||
|
||||
html += '<div class="libraryMenuDivider"></div>';
|
||||
html += '<img style="max-width:36px;vertical-align:middle;margin-right:1em;" src="css/images/mblogoicon.png" />';
|
||||
|
||||
html += Globalize.translate('ButtonHome');
|
||||
html += '</a>';
|
||||
|
||||
html += '<div class="libraryMenuDivider" style="margin-top:0;"></div>';
|
||||
|
||||
html += getViewsHtml();
|
||||
html += '</div>';
|
||||
|
|
|
@ -69,9 +69,6 @@
|
|||
|
||||
ApiClient.reportPlaybackStopped(stopInfo);
|
||||
|
||||
}).on('positionchange.mediacontroller', function (e, state) {
|
||||
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -931,6 +931,31 @@
|
|||
|
||||
var streamInfo = self.createStreamInfo('Video', item, mediaSource, startPosition);
|
||||
|
||||
// Huge hack alert. Safari doesn't seem to like if the segments aren't available right away when playback starts
|
||||
// This will start the transcoding process before actually feeding the video url into the player
|
||||
if ($.browser.safari && !mediaSource.RunTimeTicks) {
|
||||
|
||||
Dashboard.showLoadingMsg();
|
||||
|
||||
ApiClient.ajax({
|
||||
type: 'GET',
|
||||
url: streamInfo.url.replace('master.m3u8', 'live.m3u8')
|
||||
}).always(function () {
|
||||
|
||||
Dashboard.hideLoadingMsg();
|
||||
|
||||
}).done(function () {
|
||||
self.playVideoInternal(item, mediaSource, startPosition, streamInfo);
|
||||
});
|
||||
|
||||
} else {
|
||||
self.playVideoInternal(item, mediaSource, startPosition, streamInfo);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
self.playVideoInternal = function (item, mediaSource, startPosition, streamInfo) {
|
||||
|
||||
var videoUrl = streamInfo.url;
|
||||
var contentType = streamInfo.contentType;
|
||||
var startPositionInSeekParam = streamInfo.startPositionInSeekParam;
|
||||
|
@ -941,6 +966,31 @@
|
|||
return s.Type == 'Subtitle';
|
||||
});
|
||||
|
||||
// Get Video Poster (Code from librarybrowser.js)
|
||||
var screenWidth = Math.max(screen.height, screen.width);
|
||||
var posterCode = '';
|
||||
|
||||
if (item.BackdropImageTags && item.BackdropImageTags.length) {
|
||||
|
||||
posterCode = ' poster="' + ApiClient.getScaledImageUrl(item.Id, {
|
||||
type: "Backdrop",
|
||||
index: 0,
|
||||
maxWidth: screenWidth,
|
||||
tag: item.BackdropImageTags[0]
|
||||
}) + '"';
|
||||
|
||||
}
|
||||
else if (item.ParentBackdropItemId && item.ParentBackdropImageTags && item.ParentBackdropImageTags.length) {
|
||||
|
||||
posterCode = ' poster="' + ApiClient.getScaledImageUrl(item.ParentBackdropItemId, {
|
||||
type: 'Backdrop',
|
||||
index: 0,
|
||||
maxWidth: screenWidth,
|
||||
tag: item.ParentBackdropImageTags[0]
|
||||
}) + '"';
|
||||
|
||||
}
|
||||
|
||||
//======================================================================================>
|
||||
|
||||
// Create video player
|
||||
|
@ -950,11 +1000,12 @@
|
|||
|
||||
// Can't autoplay in these browsers so we need to use the full controls
|
||||
if (requiresNativeControls) {
|
||||
html += '<video class="itemVideo" id="itemVideo" preload="none" autoplay="autoplay" crossorigin="anonymous" controls="controls">';
|
||||
} else {
|
||||
html += '<video class="itemVideo" id="itemVideo" preload="metadata" autoplay="autoplay" crossorigin="anonymous" controls="controls"' + posterCode + '>';
|
||||
}
|
||||
else {
|
||||
|
||||
// Chrome 35 won't play with preload none
|
||||
html += '<video class="itemVideo" id="itemVideo" preload="metadata" crossorigin="anonymous" autoplay>';
|
||||
html += '<video class="itemVideo" id="itemVideo" preload="metadata" crossorigin="anonymous" autoplay' + posterCode + '>';
|
||||
}
|
||||
|
||||
html += '<source type="' + contentType + '" src="' + videoUrl + '" />';
|
||||
|
@ -1142,7 +1193,10 @@
|
|||
|
||||
$('body').addClass('bodyWithPopupOpen');
|
||||
|
||||
return video[0];
|
||||
self.currentMediaElement = video[0];
|
||||
self.currentDurationTicks = self.currentMediaSource.RunTimeTicks;
|
||||
|
||||
self.updateNowPlayingInfo(item);
|
||||
};
|
||||
|
||||
self.updatePlaylistUi = function () {
|
||||
|
|
|
@ -208,13 +208,22 @@
|
|||
profile.ContainerProfiles = [];
|
||||
|
||||
var audioConditions = [];
|
||||
if ($.browser.msie) {
|
||||
audioConditions.push({
|
||||
var videoAudioAacConditions = [];
|
||||
var videoAudioMp3Conditions = [];
|
||||
|
||||
var maxAudioChannels = $.browser.msie || $.browser.safari ?
|
||||
'2' :
|
||||
'6';
|
||||
|
||||
var channelCondition = {
|
||||
Condition: 'LessThanEqual',
|
||||
Property: 'AudioChannels',
|
||||
Value: '2'
|
||||
});
|
||||
}
|
||||
Value: maxAudioChannels
|
||||
};
|
||||
|
||||
audioConditions.push(channelCondition);
|
||||
videoAudioAacConditions.push(channelCondition);
|
||||
videoAudioMp3Conditions.push(channelCondition);
|
||||
|
||||
profile.CodecProfiles = [];
|
||||
profile.CodecProfiles.push({
|
||||
|
@ -222,21 +231,36 @@
|
|||
Conditions: audioConditions
|
||||
});
|
||||
|
||||
if (videoAudioMp3Conditions.length) {
|
||||
profile.CodecProfiles.push({
|
||||
Type: 'VideoAudio',
|
||||
Conditions: audioConditions
|
||||
Codec: 'mp3',
|
||||
Conditions: videoAudioMp3Conditions
|
||||
});
|
||||
}
|
||||
|
||||
videoAudioAacConditions.push({
|
||||
Condition: 'NotEquals',
|
||||
Property: 'AudioProfile',
|
||||
Value: 'LC'
|
||||
});
|
||||
|
||||
videoAudioAacConditions.push({
|
||||
Condition: 'NotEquals',
|
||||
Property: 'AudioProfile',
|
||||
Value: 'HE-AAC'
|
||||
});
|
||||
|
||||
profile.CodecProfiles.push({
|
||||
Type: 'VideoAudio',
|
||||
Codec: 'aac',
|
||||
Conditions: videoAudioAacConditions
|
||||
});
|
||||
|
||||
profile.CodecProfiles.push({
|
||||
Type: 'Video',
|
||||
Codec: 'h264',
|
||||
Conditions: [
|
||||
{
|
||||
Condition: 'Equals',
|
||||
Property: 'IsCabac',
|
||||
Value: 'true',
|
||||
IsRequired: false
|
||||
},
|
||||
{
|
||||
Condition: 'NotEquals',
|
||||
Property: 'IsAnamorphic',
|
||||
|
@ -355,36 +379,6 @@
|
|||
return false;
|
||||
};
|
||||
|
||||
self.getVideoTranscodingExtension = function (currentSrc) {
|
||||
|
||||
if (currentSrc) {
|
||||
return self.getCurrentMediaExtension(currentSrc);
|
||||
}
|
||||
|
||||
// safari
|
||||
if (self.canPlayHls()) {
|
||||
return '.m3u8';
|
||||
}
|
||||
|
||||
// Chrome, Firefox or IE with plugin installed
|
||||
// For some reason in chrome pausing mp4 is causing the video to fail.
|
||||
// So for now it will have to prioritize webm
|
||||
if (self.canPlayWebm()) {
|
||||
|
||||
if ($.browser.msie) {
|
||||
return '.webm';
|
||||
}
|
||||
if ($.browser.chrome) {
|
||||
return '.webm';
|
||||
}
|
||||
|
||||
// Firefox suddenly having trouble with our webm
|
||||
return '.webm';
|
||||
}
|
||||
|
||||
return '.mp4';
|
||||
};
|
||||
|
||||
self.changeStream = function (ticks, params) {
|
||||
|
||||
var element = self.currentMediaElement;
|
||||
|
@ -871,10 +865,7 @@
|
|||
|
||||
if (item.MediaType === "Video") {
|
||||
|
||||
self.currentMediaElement = self.playVideo(item, self.currentMediaSource, startPosition);
|
||||
self.currentDurationTicks = self.currentMediaSource.RunTimeTicks;
|
||||
|
||||
self.updateNowPlayingInfo(item);
|
||||
self.playVideo(item, self.currentMediaSource, startPosition);
|
||||
|
||||
} else if (item.MediaType === "Audio") {
|
||||
|
||||
|
|
|
@ -400,7 +400,7 @@
|
|||
// The button is created dynamically
|
||||
$(page).on('click', '.btnNewCollection', function () {
|
||||
|
||||
showCollectionPanel(page, []);
|
||||
showCollectionPanel([]);
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
var screenWidth = $(window).width();
|
||||
|
||||
return screenWidth >= 1920 ? 9 : 8;
|
||||
return screenWidth >= 1920 ? 9 : (screenWidth >= 1200 ? 12 : (screenWidth >= 1000 ? 10 : 8));
|
||||
}
|
||||
|
||||
function loadLatest(page, parentId) {
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
var externalPlayers = JSON.parse(store.getItem('externalplayers') || '[]');
|
||||
|
||||
$('#selectMaxBitrate', page).val(AppSettings.maxStreamingBitrate()).selectmenu("refresh");
|
||||
$('#selectMaxChromecastBitrate', page).val(AppSettings.maxChromecastBitrate()).selectmenu("refresh");
|
||||
|
||||
$('.chkExternalPlayer', page).each(function () {
|
||||
|
||||
|
@ -66,6 +67,7 @@
|
|||
store.setItem('externalplayers', JSON.stringify(externalPlayers));
|
||||
|
||||
AppSettings.maxStreamingBitrate($('#selectMaxBitrate', page).val());
|
||||
AppSettings.maxChromecastBitrate($('#selectMaxChromecastBitrate', page).val());
|
||||
|
||||
var userId = getParameterByName('userId') || Dashboard.getCurrentUserId();
|
||||
|
||||
|
@ -122,6 +124,14 @@
|
|||
}
|
||||
|
||||
return parseInt(store.getItem('preferredVideoBitrate') || '') || 1500000;
|
||||
},
|
||||
maxChromecastBitrate: function (val) {
|
||||
|
||||
if (val != null) {
|
||||
store.setItem('chromecastBitrate', val);
|
||||
}
|
||||
|
||||
return parseInt(store.getItem('chromecastBitrate') || '') || 3000000;
|
||||
}
|
||||
|
||||
};
|
||||
|
|
|
@ -40,6 +40,8 @@
|
|||
|
||||
updateFilterControls(page);
|
||||
|
||||
var defaultAction = query.MediaTypes == 'Photo' ? 'photoslideshow' : null;
|
||||
|
||||
// Poster
|
||||
html = LibraryBrowser.getPosterViewHtml({
|
||||
items: result.Items,
|
||||
|
@ -47,7 +49,8 @@
|
|||
context: getParameterByName('context') || 'photos',
|
||||
showTitle: false,
|
||||
centerText: true,
|
||||
lazy: true
|
||||
lazy: true,
|
||||
defaultAction: defaultAction
|
||||
});
|
||||
|
||||
var elem = $('#items', page).html(html).lazyChildren();
|
||||
|
@ -134,6 +137,50 @@
|
|||
query.ParentId = getParameterByName('parentId') || LibraryMenu.getTopParentId();
|
||||
}
|
||||
|
||||
function startSlideshow(page, index) {
|
||||
|
||||
index += (query.StartIndex || 0);
|
||||
|
||||
var userId = Dashboard.getCurrentUserId();
|
||||
|
||||
var localQuery = $.extend({}, query);
|
||||
localQuery.StartIndex = 0;
|
||||
localQuery.Limit = null;
|
||||
localQuery.MediaTypes = "Photo";
|
||||
localQuery.Recursive = true;
|
||||
localQuery.Filters = "IsNotFolder";
|
||||
|
||||
ApiClient.getItems(userId, localQuery).done(function (result) {
|
||||
|
||||
showSlideshow(page, result.Items, index);
|
||||
});
|
||||
}
|
||||
|
||||
function showSlideshow(page, items, index) {
|
||||
|
||||
var slideshowItems = items.map(function (item) {
|
||||
|
||||
var imgUrl = ApiClient.getScaledImageUrl(item.Id, {
|
||||
|
||||
tag: item.ImageTags.Primary,
|
||||
type: 'Primary'
|
||||
|
||||
});
|
||||
|
||||
return {
|
||||
title: item.Name,
|
||||
href: imgUrl
|
||||
};
|
||||
});
|
||||
|
||||
index = Math.max(index || 0, 0);
|
||||
|
||||
$.swipebox(slideshowItems, {
|
||||
initialIndexOnArray: index,
|
||||
hideBarsDelay: 30000
|
||||
});
|
||||
}
|
||||
|
||||
$(document).on('pageinit', "#photosPage", function () {
|
||||
|
||||
var page = this;
|
||||
|
@ -197,6 +244,10 @@
|
|||
reloadItems(page);
|
||||
});
|
||||
|
||||
$('.itemsContainer', page).on('photoslideshow', function (e, index) {
|
||||
startSlideshow(page, index);
|
||||
});
|
||||
|
||||
}).on('pagebeforeshow', "#photosPage", function () {
|
||||
|
||||
var page = this;
|
||||
|
|
|
@ -577,14 +577,16 @@ var Dashboard = {
|
|||
|
||||
html += '<h3>';
|
||||
|
||||
var imgWidth = 48;
|
||||
|
||||
if (user.imageUrl) {
|
||||
var url = user.imageUrl;
|
||||
|
||||
if (user.supportsImageParams) {
|
||||
url += "&width=" + 28;
|
||||
url += "&width=" + (imgWidth * Math.max(devicePixelRatio || 1, 2));
|
||||
}
|
||||
|
||||
html += '<img style="max-width:28px;vertical-align:middle;margin-right:5px;" src="' + url + '" />';
|
||||
html += '<img style="max-width:' + imgWidth + 'px;vertical-align:middle;margin-right:.5em;border-radius: 50px;" src="' + url + '" />';
|
||||
}
|
||||
html += user.name;
|
||||
html += '</h3>';
|
||||
|
@ -1385,6 +1387,27 @@ var Dashboard = {
|
|||
|
||||
if (window.ApiClient) {
|
||||
Dashboard.importCss(ApiClient.getUrl('Branding/Css'));
|
||||
|
||||
ApiClient.getDefaultImageQuality = function (imageType) {
|
||||
|
||||
var quality = 90;
|
||||
var isBackdrop = imageType.toLowerCase() == 'backdrop';
|
||||
|
||||
if (isBackdrop) {
|
||||
quality -= 10;
|
||||
}
|
||||
|
||||
if ($.browser.safari && $.browser.mobile) {
|
||||
|
||||
quality -= 10;
|
||||
|
||||
if (isBackdrop) {
|
||||
quality -= 10;
|
||||
}
|
||||
}
|
||||
|
||||
return quality;
|
||||
};
|
||||
}
|
||||
|
||||
})();
|
||||
|
|
30
dashboard-ui/thirdparty/apiclient/apiclient.js
vendored
30
dashboard-ui/thirdparty/apiclient/apiclient.js
vendored
|
@ -54,6 +54,25 @@
|
|||
return serverInfo;
|
||||
};
|
||||
|
||||
var currentUser;
|
||||
/**
|
||||
* Gets or sets the current user id.
|
||||
*/
|
||||
self.getCurrentUser = function () {
|
||||
|
||||
if (currentUser != null) {
|
||||
|
||||
var deferred = DeferredBuilder.Deferred();
|
||||
deferred.resolveWith(null, [currentUser]);
|
||||
return deferred.promise();
|
||||
}
|
||||
|
||||
return self.getUser(self.getCurrentUserId()).done(function (user) {
|
||||
|
||||
currentUser = user;
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Gets or sets the current user id.
|
||||
*/
|
||||
|
@ -69,6 +88,7 @@
|
|||
self.setCurrentUserId = function (userId, token) {
|
||||
|
||||
currentUserId = userId;
|
||||
currentUser = null;
|
||||
accessToken = token;
|
||||
};
|
||||
|
||||
|
@ -2305,6 +2325,10 @@
|
|||
});
|
||||
};
|
||||
|
||||
self.getDefaultImageQuality = function (imageType) {
|
||||
return imageType.toLowerCase() == 'backdrop' ? 80 : 90;
|
||||
};
|
||||
|
||||
function normalizeImageOptions(options) {
|
||||
|
||||
var ratio = devicePixelRatio || 1;
|
||||
|
@ -2329,7 +2353,7 @@
|
|||
}
|
||||
}
|
||||
|
||||
options.quality = options.quality || (options.type.toLowerCase() == 'backdrop' ? 80 : 90);
|
||||
options.quality = options.quality || self.getDefaultImageQuality(options.type);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -2350,9 +2374,7 @@
|
|||
throw new Error("null userId");
|
||||
}
|
||||
|
||||
options = options || {
|
||||
|
||||
};
|
||||
options = options || {};
|
||||
|
||||
var url = "Users/" + userId + "/Images/" + options.type;
|
||||
|
||||
|
|
|
@ -433,7 +433,7 @@
|
|||
|
||||
var apiClient = self.currentApiClient();
|
||||
if (apiClient && apiClient.getCurrentUserId()) {
|
||||
apiClient.getUser(apiClient.getCurrentUserId()).done(function (u) {
|
||||
apiClient.getCurrentUser().done(function (u) {
|
||||
localUser = u;
|
||||
}).always(onLocalUserDone);
|
||||
} else {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue