1
0
Fork 0
mirror of https://github.com/jellyfin/jellyfin-web synced 2025-03-30 19:56:21 +00:00

support theme songs in the web client

This commit is contained in:
Luke Pulverenti 2014-04-14 23:54:52 -04:00
parent b8c3e8c777
commit b7235c797f
22 changed files with 603 additions and 272 deletions

View file

@ -80,14 +80,6 @@
$('#hfResultId', popup).val(item.Id);
if (item.ExtractedName) {
$('#fldRememberCorrection', popup).hide();
} else {
$('#fldRememberCorrection', popup).hide();
}
$('#chkRememberEpisodeCorrection', popup).checked(false).checkboxradio('refresh');
var seriesHtml = allSeries.map(function (s) {
return '<option value="' + s.Id + '">' + s.Name + '</option>';
@ -157,8 +149,7 @@
SeriesId: $('#selectSeries', form).val(),
SeasonNumber: $('#txtSeason', form).val(),
EpisodeNumber: $('#txtEpisode', form).val(),
EndingEpisodeNumber: $('#txtEndingEpisode', form).val(),
RememberCorrection: $('#chkRememberEpisodeCorrection', form).checked()
EndingEpisodeNumber: $('#txtEndingEpisode', form).val()
};
ApiClient.performEpisodeOrganization(resultId, options).done(function () {

View file

@ -40,7 +40,7 @@
Dashboard.updateSystemInfo(systemInfo);
$('#appVersionNumber', page).html(systemInfo.Version);
$('#appVersionNumber', page).html('Version ' + systemInfo.Version);
var port = systemInfo.HttpServerPortNumber;
@ -190,17 +190,15 @@
var html = '';
var table = $('.tblConnections', page);
var parentElement = $('.activeDevices', page);
$('.trSession', table).addClass('deadSession');
var deviceId = ApiClient.deviceId();
$('.activeSession', parentElement).addClass('deadSession');
for (var i = 0, length = sessions.length; i < length; i++) {
var connection = sessions[i];
var rowId = 'trSession' + connection.Id;
var rowId = 'session' + connection.Id;
var elem = $('#' + rowId, page);
@ -209,93 +207,184 @@
continue;
}
html += '<tr class="trSession" id="' + rowId + '">';
var nowPlayingItem = connection.NowPlayingItem;
html += '<td class="clientType" style="text-align:center;">';
html += DashboardPage.getClientType(connection);
html += '</td>';
var className = nowPlayingItem ? 'activeSession' : 'notPlayingSession activeSession';
html += '<td>';
html += '<a class="' + className + '" id="' + rowId + '" href="nowplaying.html">';
html += '<div style="max-width:200px;">';
if (deviceId == connection.DeviceId) {
html += connection.DeviceName;
html += '<div class="sessionNowPlayingContent"';
var imgUrl = DashboardPage.getNowPlayingImageUrl(nowPlayingItem);
if (imgUrl) {
html += ' data-src="' + imgUrl + '" style="display:inline-block;background-image:url(\'' + imgUrl + '\');"';
}
html += '></div>';
html += '<div class="sessionNowPlayingInnerContent">';
html += '<div class="sessionAppInfo">';
var clientImage = DashboardPage.getClientImage(connection);
if (clientImage) {
html += clientImage;
}
html += '<div class="sessionAppName" style="display:inline-block;">' + connection.DeviceName;
html += '<br/>' + connection.ApplicationVersion;
html += '</div>';
html += '</div>';
html += '<div class="sessionUserInfo">';
var userImage = DashboardPage.getUserImage(connection);
if (userImage) {
html += '<div class="sessionUserImage" data-src="' + userImage + '">';
html += '<img src="' + userImage + '" />';
} else {
html += '<a href="#" onclick="RemoteControl.showMenu({sessionId:\'' + connection.Id + '\'});">' + connection.DeviceName + '</a>';
html += '<div class="sessionUserImage">';
}
html += '</div>';
html += '<div>' + connection.ApplicationVersion + '</div>';
html += '<div class="username">';
html += '<div class="sessionUserName">';
html += DashboardPage.getUsersHtml(connection);
html += '</div>';
html += '</td>';
var nowPlayingItem = connection.NowPlayingItem;
html += '<td>';
html += '<div class="nowPlayingImage">';
html += DashboardPage.getNowPlayingImage(nowPlayingItem);
html += '</div>';
html += '<div class="clientNowPlayingText">';
html += DashboardPage.getNowPlayingText(connection, nowPlayingItem);
html += '<div class="sessionNowPlayingInfo">';
if (nowPlayingItem) {
html += DashboardPage.getNowPlayingName(connection);
}
html += '</div>';
html += '</td>';
if (nowPlayingItem) {
var value = (100 * connection.NowPlayingPositionTicks) / nowPlayingItem.RunTimeTicks;
html += '</tr>';
html += '<progress class="itemProgressBar" min="0" max="100" value="' + value + '"></progress>';
} else {
html += '<progress class="itemProgressBar" min="0" max="100" style="display:none;"></progress>';
}
html += '</div>';
html += '</a>';
}
table.append(html).trigger('create');
parentElement.append(html).trigger('create');
$('.deadSession', parentElement).remove();
},
getNowPlayingName: function (session) {
var nowPlayingItem = session.NowPlayingItem;
if (!nowPlayingItem) {
return 'Last seen ' + humane_date(session.LastActivityDate);
}
var topText = nowPlayingItem.Name;
if (nowPlayingItem.MediaType == 'Video') {
if (nowPlayingItem.IndexNumber != null) {
topText = nowPlayingItem.IndexNumber + " - " + topText;
}
if (nowPlayingItem.ParentIndexNumber != null) {
topText = nowPlayingItem.ParentIndexNumber + "." + topText;
}
}
var bottomText = '';
if (nowPlayingItem.Artists && nowPlayingItem.Artists.length) {
bottomText = topText;
topText = nowPlayingItem.Artists[0];
}
else if (nowPlayingItem.SeriesName || nowPlayingItem.Album) {
bottomText = topText;
topText = nowPlayingItem.SeriesName || nowPlayingItem.Album;
}
else if (nowPlayingItem.ProductionYear) {
bottomText = nowPlayingItem.ProductionYear;
}
return bottomText ? topText + '<br/>' + bottomText : topText;
$('.deadSession', table).remove();
},
getUsersHtml: function (session) {
var html = '';
var html = [];
if (session.UserId) {
html += '<div>' + session.UserName + '</div>';
html.push(session.UserName);
}
html += session.AdditionalUsers.map(function (currentSession) {
for (var i = 0, length = session.AdditionalUsers.length; i < length; i++) {
return '<div>' + currentSession.UserName + '</div>';
});
html.push(session.AdditionalUsers[i].UserName);
}
return html;
return html.join(', ');
},
getUserImage: function (session) {
if (session.UserId && session.UserPrimaryImageTag) {
return ApiClient.getUserImageUrl(session.UserId, {
tag: session.UserPrimaryImageTag,
height: 24,
type: 'Primary'
});
}
return null;
},
updateSession: function (row, session) {
row.removeClass('deadSession');
$('.username', row).html(DashboardPage.getUsersHtml(session));
var nowPlayingItem = session.NowPlayingItem;
$('.clientNowPlayingText', row).html(DashboardPage.getNowPlayingText(session, nowPlayingItem)).trigger('create');
if (nowPlayingItem) {
row.removeClass('notPlayingSession');
} else {
row.addClass('notPlayingSession');
}
var imageRow = $('.nowPlayingImage', row);
$('.sessionUserName', row).html(DashboardPage.getUsersHtml(session));
var image = $('img', imageRow)[0];
$('.sessionNowPlayingInfo', row).html(DashboardPage.getNowPlayingName(session));
var nowPlayingItemId = nowPlayingItem ? nowPlayingItem.Id : null;
var nowPlayingItemImageTag = nowPlayingItem ? nowPlayingItem.PrimaryImageTag : null;
if (nowPlayingItem && nowPlayingItem.RunTimeTicks) {
if (!image || image.getAttribute('data-itemid') != nowPlayingItemId || image.getAttribute('data-tag') != nowPlayingItemImageTag) {
imageRow.html(DashboardPage.getNowPlayingImage(nowPlayingItem));
var value = (100 * session.NowPlayingPositionTicks) / nowPlayingItem.RunTimeTicks;
$('progress', row).show().val(value);
} else {
$('progress', row).hide();
}
var imgUrl = DashboardPage.getNowPlayingImageUrl(nowPlayingItem) || '';
var imgElem = $('.sessionNowPlayingContent', row)[0];
if (imgUrl != imgElem.getAttribute('data-src')) {
imgElem.style.backgroundImage = imgUrl ? 'url(\'' + imgUrl + '\')' : '';
imgElem.setAttribute('data-src', imgUrl);
}
},
getClientType: function (connection) {
getClientImage: function (connection) {
var clientLowered = connection.Client.toLowerCase();
@ -325,89 +414,81 @@
}
if (clientLowered == "mb-classic") {
return "<img src='css/images/clients/mbc.png' alt='Media Browser Classic' />";
return "<img src='css/images/clients/mbc.png' />";
}
if (clientLowered == "media browser theater") {
return "<img src='css/images/clients/mb.png' alt='Media Browser Theater' />";
return "<img src='css/images/clients/mb.png' />";
}
if (clientLowered == "android") {
return "<img src='css/images/clients/android.png' alt='Android' />";
return "<img src='css/images/clients/android.png' />";
}
if (clientLowered == "roku") {
return "<img src='css/images/clients/roku.jpg' alt='Roku' />";
return "<img src='css/images/clients/roku.jpg' />";
}
if (clientLowered == "ios") {
return "<img src='css/images/clients/ios.png' alt='iOS' />";
return "<img src='css/images/clients/ios.png' />";
}
if (clientLowered == "windows rt") {
return "<img src='css/images/clients/windowsrt.png' alt='Windows RT' />";
return "<img src='css/images/clients/windowsrt.png' />";
}
if (clientLowered == "windows phone") {
return "<img src='css/images/clients/windowsphone.png' alt='Windows Phone' />";
return "<img src='css/images/clients/windowsphone.png' />";
}
if (clientLowered == "dlna") {
return "<img src='css/images/clients/dlna.png' alt='Dlna' />";
return "<img src='css/images/clients/dlna.png' />";
}
if (clientLowered == "mbkinect") {
return "<img src='css/images/clients/mbkinect.png' alt='MB Kinect' />";
return "<img src='css/images/clients/mbkinect.png' />";
}
if (clientLowered == "xbmc") {
return "<img src='css/images/clients/xbmc.png' alt='Xbmc' />";
return "<img src='css/images/clients/xbmc.png' />";
}
if (clientLowered == "chromecast") {
return "<img src='css/images/chromecast/ic_media_route_on_holo_light.png' alt='Chromecast' />";
return "<img src='css/images/chromecast/ic_media_route_on_holo_light.png' />";
}
return connection.Client;
return null;
},
getNowPlayingImage: function (item) {
getNowPlayingImageUrl: function (item) {
if (item && item.BackdropImageTag) {
return ApiClient.getImageUrl(item.BackdropItemId, {
type: "Backdrop",
width: 810,
tag: item.BackdropImageTag
});
}
if (item && item.ThumbImageTag) {
return ApiClient.getImageUrl(item.ThumbItemId, {
type: "Thumb",
width: 810,
tag: item.ThumbImageTag
});
}
if (item && item.PrimaryImageTag) {
var url = ApiClient.getImageUrl(item.Id, {
return ApiClient.getImageUrl(item.PrimaryImageItemId, {
type: "Primary",
height: 100,
width: 810,
tag: item.PrimaryImageTag
});
url += "&xxx=" + new Date().getTime();
return "<img data-itemid='" + item.Id + "' data-tag='" + item.PrimaryImageTag + "' class='clientNowPlayingImage' src='" + url + "' alt='" + item.Name + "' title='" + item.Name + "' />";
}
return "";
},
getNowPlayingText: function (connection, item) {
var html = "";
if (item) {
html += "<div><a href='itemdetails.html?id=" + item.Id + "'>" + item.Name + "</a></div>";
html += "<div>";
if (item.RunTimeTicks) {
html += Dashboard.getDisplayTime(connection.NowPlayingPositionTicks || 0) + " / ";
html += Dashboard.getDisplayTime(item.RunTimeTicks);
}
html += "</div>";
}
return html;
return null;
},
systemUpdateTaskKey: "SystemUpdateTask",

View file

@ -267,8 +267,7 @@
$('#musicVideosCollapsible', page).hide();
}
renderThemeSongs(page, item, user);
renderThemeVideos(page, item, user);
renderThemeMedia(page, item, user);
renderCriticReviews(page, item, 1);
}
@ -906,22 +905,51 @@
$('#criticReviewsContent', page).html(html).trigger('create');
}
function renderThemeMedia(page, item) {
ApiClient.getThemeMedia(Dashboard.getCurrentUserId(), item.Id, true).done(function (result) {
function renderThemeSongs(page, item) {
var themeSongs = result.ThemeSongsResult.OwnerId == item.Id ?
result.ThemeSongsResult.Items :
[];
var themeVideos = result.ThemeVideosResult.OwnerId == item.Id ?
result.ThemeVideosResult.Items :
[];
ApiClient.getThemeSongs(Dashboard.getCurrentUserId(), item.Id).done(function (result) {
if (result.Items.length) {
renderThemeSongs(page, themeSongs);
renderThemeVideos(page, themeVideos);
$('#themeSongsCollapsible', page).show();
$('#themeSongsContent', page).html(LibraryBrowser.getSongTableHtml(result.Items, { showArtist: true, showAlbum: true, showAlbumArtist: true })).trigger('create');
} else {
$('#themeSongsCollapsible', page).hide();
}
$(page).trigger('thememediadownload', [result]);
});
}
function renderThemeSongs(page, items) {
if (items.length) {
$('#themeSongsCollapsible', page).show();
$('#themeSongsContent', page).html(LibraryBrowser.getSongTableHtml(items, { showArtist: true, showAlbum: true, showAlbumArtist: true })).trigger('create');
} else {
$('#themeSongsCollapsible', page).hide();
}
}
function renderThemeVideos(page, items, user) {
if (items.length) {
$('#themeVideosCollapsible', page).show();
$('#themeVideosContent', page).html(getVideosHtml(items, user)).trigger('create');
} else {
$('#themeVideosCollapsible', page).hide();
}
}
function renderMusicVideos(page, item, user) {
ApiClient.getItems(user.Id, {
@ -946,21 +974,6 @@
}
function renderThemeVideos(page, item, user) {
ApiClient.getThemeVideos(user.Id, item.Id).done(function (result) {
if (result.Items.length) {
$('#themeVideosCollapsible', page).show();
$('#themeVideosContent', page).html(getVideosHtml(result.Items, user)).trigger('create');
} else {
$('#themeVideosCollapsible', page).hide();
}
});
}
function renderAdditionalParts(page, item, user) {
ApiClient.getAdditionalVideoParts(user.Id, item.Id).done(function (result) {

View file

@ -16,7 +16,7 @@
html += '<a class="desktopHomeLink" href="index.html"><img src="css/images/mblogoicon.png" /></a>';
html += '<button class="viewMenuRemoteControlButton" onclick="RemoteControl.showMenu();" type="button" data-icon="wireless" data-inline="true" data-iconpos="notext" title="Remote Control">Remote Control</button>';
html += '<a class="viewMenuRemoteControlButton" href="nowplaying.html" data-role="button" data-icon="wireless" data-inline="true" data-iconpos="notext" title="Now Playing">Remote Control</a>';
if (user.Configuration.IsAdministrator) {
html += '<a class="editorMenuLink" href="edititemmetadata.html" data-role="button" data-icon="edit" data-inline="true" data-iconpos="notext" title="Metadata Manager">Metadata Manager</a>';

View file

@ -36,7 +36,8 @@
isLocalPlayer: currentPlayer.isLocalPlayer,
id: currentTargetInfo.id,
deviceName: currentTargetInfo.deviceName,
playableMediaTypes: currentTargetInfo.playableMediaTypes
playableMediaTypes: currentTargetInfo.playableMediaTypes,
supportedCommands: currentTargetInfo.supportedCommands
};
};
@ -355,7 +356,7 @@
var mirror = (!target.isLocalPlayer && target.supportedCommands.indexOf('DisplayContent') != -1) ? 'true' : 'false';
html += '<input type="radio" class="radioSelectPlayerTarget" name="radioSelectPlayerTarget" data-mirror="' + mirror + '" data-mediatypes="' + target.playableMediaTypes.join(',') + '" data-playername="' + target.playerName + '" data-targetid="' + target.id + '" data-targetname="' + target.name + '" id="' + id + '" value="' + target.id + '"' + checkedHtml + '>';
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 + '" id="' + id + '" value="' + target.id + '"' + checkedHtml + '>';
html += '<label for="' + id + '" style="font-weight:normal;">' + target.name;
if (target.appName) {
@ -432,11 +433,13 @@
var targetId = this.getAttribute('data-targetid');
var targetName = this.getAttribute('data-targetname');
var playableMediaTypes = this.getAttribute('data-mediatypes').split(',');
var supportedCommands = this.getAttribute('data-commands').split(',');
MediaController.setActivePlayer(playerName, {
id: targetId,
name: targetName,
playableMediaTypes: playableMediaTypes
playableMediaTypes: playableMediaTypes,
supportedCommands: supportedCommands
});
});

View file

@ -862,9 +862,13 @@
// Can't autoplay in these browsers so we need to use the full controls
if (requiresControls) {
html += '<video class="itemVideo" id="itemVideo" autoplay controls>';
html += '<video class="itemVideo" id="itemVideo" preload="none" autoplay controls>';
} else {
html += '<video class="itemVideo" id="itemVideo" autoplay>';
// Chrome 35 won't play with preload none
html += '<video class="itemVideo" id="itemVideo" preload="metadata" autoplay>';
}
if (!isStatic) {

View file

@ -566,7 +566,7 @@
};
self.displayContent = function (options) {
// Handle it the same as a remote control command
Dashboard.onBrowseCommand({
@ -934,7 +934,7 @@
};
self.isPlaying = function () {
return currentMediaElement;
return currentMediaElement != null;
};
self.getPlayerState = function () {
@ -1121,6 +1121,15 @@
return testableVideoElement.canPlayType('video/webm').replace(/no/, '');
}
self.canAutoPlayAudio = function () {
if ($.browser.android || ($.browser.webkit && !$.browser.chrome)) {
return false;
}
return true;
};
function getAudioElement() {
var elem = $('.mediaPlayerAudio');
@ -1131,7 +1140,7 @@
var html = '';
var requiresControls = $.browser.android || ($.browser.webkit && !$.browser.chrome);
var requiresControls = !self.canAutoPlayAudio();
if (requiresControls) {
html += '<div class="mediaPlayerAudioContainer"><div class="mediaPlayerAudioContainerInner">';;

View file

@ -167,6 +167,28 @@
getNowPlayingBar();
}
var playerInfo = MediaController.getPlayerInfo();
var supportedCommands = playerInfo.supportedCommands;
if (supportedCommands.indexOf('SetVolume') == -1) {
volumeSlider.prop('disabled', 'disabled');
} else {
volumeSlider.prop('disabled', '');
}
if (supportedCommands.indexOf('Mute') == -1) {
muteButton.prop('disabled', 'disabled');
} else {
muteButton.prop('disabled', '');
}
if (supportedCommands.indexOf('Unmute') == -1) {
unmuteButton.prop('disabled', 'disabled');
} else {
unmuteButton.prop('disabled', '');
}
if (state.isMuted) {
muteButton.hide();
@ -190,9 +212,11 @@
}
if (!isVolumeSliderActive) {
volumeSlider.val(state.volumeLevel || 0).slider('refresh');
volumeSlider.val(state.volumeLevel || 0);
}
volumeSlider.slider('refresh');
if (!isPositionSliderActive) {
if (state.canSeek) {

View file

@ -80,7 +80,7 @@
var page = this;
reloadPlaylist(page);
//reloadPlaylist(page);
});

View file

@ -477,7 +477,7 @@ var Dashboard = {
Dashboard.getCurrentUser().done(function (user) {
var html = '<div data-role="panel" data-position="right" data-display="overlay" id="userFlyout" data-position-fixed="true" data-theme="a">';
var html = '<div data-role="panel" data-position="right" data-display="overlay" id="userFlyout" data-position-fixed="true" data-theme="b">';
html += '<h3>';
@ -496,17 +496,24 @@ var Dashboard = {
html += user.Name;
html += '</h3>';
html += '<form>';
html += '<p><label for="chkEnableThemeSongs">Play theme songs</label><input onchange="ThemeSongManager.enabled(this.checked);" type="checkbox" id="chkEnableThemeSongs" data-mini="true" /></a>';
html += '<p><a data-mini="true" data-role="button" href="useredit.html?userId=' + user.Id + '" data-icon="user">Preferences</button></a>';
html += '<p><button data-mini="true" type="button" onclick="Dashboard.logout();" data-icon="lock">Sign Out</button></p>';
html += '</form>';
html += '</div>';
$(document.body).append(html);
$('#userFlyout').panel({}).trigger('create').panel("open").on("panelafterclose", function () {
var elem = $('#userFlyout').panel({}).trigger('create').panel("open").on("panelafterclose", function () {
$(this).off("panelafterclose").remove();
});
$('#chkEnableThemeSongs', elem).checked(ThemeSongManager.enabled()).checkboxradio('refresh');
});
},

View file

@ -0,0 +1,81 @@
(function (document, $) {
var currentOwnerId;
var currentThemeIds = [];
function playThemeSongs(items, ownerId) {
var player = getPlayer();
if (items.length && player.isDefaultPlayer && player.canAutoPlayAudio()) {
// Stop if a theme song from another ownerId
// Leave it alone if anything else (e.g user playing a movie)
if (!currentOwnerId && player.isPlaying()) {
return;
}
currentThemeIds = items.map(function (i) {
return i.Id;
});
currentOwnerId = ownerId;
player.play({
items: items
});
} else {
currentOwnerId = null;
}
}
function onPlayItem(item) {
// User played something manually
if (currentThemeIds.indexOf(item.Id) == -1) {
currentOwnerId = null;
}
}
function enabled(isEnabled) {
var userId = Dashboard.getCurrentUserId();
var key = userId + '-themesongs';
if (isEnabled != null) {
var val = isEnabled ? '1' : '0';
localStorage.setItem(key, val);
return;
}
return localStorage.getItem(key);
}
function getPlayer() {
return MediaController.getCurrentPlayer();
}
$(document).on('thememediadownload', ".libraryPage", function (e, themeMediaResult) {
if (!enabled()) {
return;
}
var ownerId = themeMediaResult.ThemeSongsResult.OwnerId;
if (ownerId != currentOwnerId) {
playThemeSongs(themeMediaResult.ThemeSongsResult.Items, ownerId);
}
});
window.ThemeSongManager = {
enabled: enabled
};
})(document, jQuery);

View file

@ -1,13 +1,29 @@
(function ($, window, document) {
function populateLanguages(select, languages) {
var html = "";
html += "<option value=''></option>";
for (var i = 0, length = languages.length; i < length; i++) {
var culture = languages[i];
html += "<option value='" + culture.ThreeLetterISOLanguageName + "'>" + culture.DisplayName + "</option>";
}
$(select).html(html).selectmenu("refresh");
}
function loadUser(page, user, loggedInUser, allCulturesPromise) {
Dashboard.setPageTitle(user.Name);
allCulturesPromise.done(function (allCultures) {
Dashboard.populateLanguages($('#selectAudioLanguage', page), allCultures);
Dashboard.populateLanguages($('#selectSubtitleLanguage', page), allCultures);
populateLanguages($('#selectAudioLanguage', page), allCultures);
populateLanguages($('#selectSubtitleLanguage', page), allCultures);
$('#selectAudioLanguage', page).val(user.Configuration.AudioLanguagePreference || "").selectmenu("refresh");
$('#selectSubtitleLanguage', page).val(user.Configuration.SubtitleLanguagePreference || "").selectmenu("refresh");