more support for episodes directly in a series folder

This commit is contained in:
Luke Pulverenti 2013-12-03 23:18:50 -05:00
parent b8c8a794f3
commit e38caab270
15 changed files with 217 additions and 65 deletions

View File

@ -66,6 +66,10 @@
border-top: 0;
}
.posterItemText + .posterItemProgress {
padding-top: 0;
}
.posterItemDefaultText {
position: absolute;
top: 30%;

View File

@ -32,7 +32,7 @@
body {
overflow-y: scroll!important;
font-size: 90%;
font-size: 13px;
}
.textlink {

View File

@ -11,6 +11,35 @@
<a href="livetvrecordings.html" class="ui-btn-active">Recordings</a>
<a href="livetvtimers.html">Timers</a>
</div>
<div id="itemBackdrop" class="itemBackdrop noBackdrop">
<div class="itemBackdropContent">
<table class="detailPageContent primaryDetailPageContent">
<tr>
<td style="vertical-align: top; padding: 10px 1em 10px 0;">
<div id="itemImage" class="itemImageContainer"></div>
</td>
<td style="vertical-align: top; padding: 0;">
<p><span class="itemName inlineItemName"></span><span class="itemMiscInfo" style="display: inline;"></span></p>
<p class="itemChannelNumber"></p>
<p style="margin: 2em 0;">
<span class="userDataIcons"></span>
</p>
</td>
</tr>
</table>
</div>
</div>
<div class="ui-body-a" style="text-align: center; padding: .25em 0 .5em;">
<span id="playButtonContainer" style="display: none;">
<button id="btnPlay" type="button" data-icon="play" data-inline="true" data-mini="true">Play</button>
</span>
<span>
<button id="btnRemote" type="button" data-icon="hand-up" data-inline="true" data-mini="true">Remote</button>
</span>
<span id="deleteButtonContainer" style="display: none;">
<button id="btnDelete" type="button" data-icon="delete" data-inline="true" data-mini="true">Delete</button>
</span>
</div>
<div data-role="content">
</div>
</div>

View File

@ -24,7 +24,7 @@
<th class="desktopColumn">Channel</th>
<th>Date</th>
<th>Start</th>
<th class="tabletColumn">End</th>
<th class="tabletColumn">Length</th>
<th class="tabletColumn">Status</th>
</tr>
</thead>

View File

@ -364,14 +364,34 @@
return;
}
var friendly = item.Type == "Audio" ? "song" : item.Type.toLowerCase();
var promise;
ApiClient.getItems(Dashboard.getCurrentUserId(), {
if (item.Type == "Season") {
promise = ApiClient.getSeasons(item.SeriesId, {
userId: Dashboard.getCurrentUserId(),
AdjacentTo: item.Id
});
}
else if (item.Type == "Episode") {
// Use dedicated episodes endpoint
promise = ApiClient.getEpisodes(item.SeriesId, {
seasonId: item.SeasonId,
userId: Dashboard.getCurrentUserId(),
AdjacentTo: item.Id
});
} else {
promise = ApiClient.getItems(Dashboard.getCurrentUserId(), {
AdjacentTo: item.Id,
ParentId: item.ParentId
});
}
}).done(function (result) {
promise.done(function (result) {
for (var i = 0, length = result.Items.length; i < length; i++) {
@ -381,13 +401,15 @@
continue;
}
var friendlyTypeName = item.Type == "Audio" ? "song" : item.Type.toLowerCase();
if (curr.IndexNumber < item.IndexNumber) {
$('.lnkPreviousItem', page).removeClass('hide').attr('href', 'itemdetails.html?id=' + curr.Id).html('← Previous ' + friendly);
$('.lnkPreviousItem', page).removeClass('hide').attr('href', 'itemdetails.html?id=' + curr.Id).html('← Previous ' + friendlyTypeName);
}
else if (curr.IndexNumber > item.IndexNumber) {
$('.lnkNextItem', page).removeClass('hide').attr('href', 'itemdetails.html?id=' + curr.Id).html('Next ' + friendly + ' →');
$('.lnkNextItem', page).removeClass('hide').attr('href', 'itemdetails.html?id=' + curr.Id).html('Next ' + friendlyTypeName + ' →');
}
}
});
@ -518,23 +540,12 @@
}
else if (item.Type == "Season") {
if (item.IndexNumber == null) {
// Use dedicated episodes endpoint
promise = ApiClient.getEpisodes(item.SeriesId, {
seasonId: item.Id,
userId: user.Id
});
} else {
// Use dedicated episodes endpoint
promise = ApiClient.getEpisodes(item.SeriesId, {
season: item.IndexNumber,
userId: user.Id
});
}
}
promise = promise || ApiClient.getItems(Dashboard.getCurrentUserId(), query);

View File

@ -68,7 +68,8 @@
for (var i = 0, length = result.Items.length; i < length; i++) {
urls.push(LibraryBrowser.getImageUrl(result.Items[i], 'Primary', 0, {
width: 160
width: 160,
EnableImageEnhancers: false
}));
}
@ -96,7 +97,8 @@
for (var i = 0, length = result.Items.length; i < length; i++) {
urls.push(LibraryBrowser.getImageUrl(result.Items[i], 'Primary', 0, {
width: 160
width: 160,
EnableImageEnhancers: false
}));
}
@ -124,7 +126,8 @@
for (var i = 0, length = result.Items.length; i < length; i++) {
urls.push(LibraryBrowser.getImageUrl(result.Items[i], 'Primary', 0, {
width: 160
width: 160,
EnableImageEnhancers: false
}));
}
@ -152,7 +155,8 @@
for (var i = 0, length = result.Items.length; i < length; i++) {
urls.push(LibraryBrowser.getImageUrl(result.Items[i], 'Primary', 0, {
width: 160
width: 160,
EnableImageEnhancers: false
}));
}

View File

@ -735,7 +735,7 @@
else if (item.ImageTags && item.ImageTags.Primary) {
height = 300;
width = primaryImageAspectRatio ? parseInt(height * primaryImageAspectRatio) : null;
width = primaryImageAspectRatio ? (height * primaryImageAspectRatio).toFixed(0) : null;
imgUrl = ApiClient.getImageUrl(item.Id, {
type: "Primary",
@ -748,7 +748,7 @@
else if (item.AlbumId && item.AlbumPrimaryImageTag) {
height = 300;
width = primaryImageAspectRatio ? parseInt(height * primaryImageAspectRatio) : null;
width = primaryImageAspectRatio ? (height * primaryImageAspectRatio).toFixed(0) : null;
imgUrl = ApiClient.getImageUrl(item.AlbumId, {
type: "Primary",
@ -1200,7 +1200,7 @@
}
else if (item.ParentIndexNumber && item.Type == "Episode") {
html.push('<a class="detailPageParentLink" href="itemdetails.html?id=' + item.ParentId + '">Season ' + item.ParentIndexNumber + '</a>');
html.push('<a class="detailPageParentLink" href="itemdetails.html?id=' + item.SeasonId + '">Season ' + item.ParentIndexNumber + '</a>');
}
else if (item.Album && item.Type == "Audio" && (item.AlbumId || item.ParentId)) {
html.push('<a class="detailPageParentLink" href="itemdetails.html?id=' + (item.AlbumId || item.ParentId) + '">' + item.Album + '</a>');
@ -2009,20 +2009,31 @@
}
}
var minutes;
if (item.RunTimeTicks && item.Type != "Series") {
if (item.Type == "Audio") {
miscInfo.push(Dashboard.getDisplayTime(item.RunTimeTicks));
} else {
var minutes = item.RunTimeTicks / 600000000;
minutes = item.RunTimeTicks / 600000000;
minutes = minutes || 1;
miscInfo.push(parseInt(minutes) + "min");
miscInfo.push(minutes.toFixed(0) + "min");
}
}
if (item.DurationMs) {
minutes = item.DurationMs / 60000;
minutes = minutes || 1;
miscInfo.push(minutes.toFixed(0) + "min");
}
if (item.OfficialRating && item.Type !== "Season" && item.Type !== "Episode") {
miscInfo.push(item.OfficialRating);
}

View File

@ -1,4 +1,8 @@
function deleteRecording(page, id) {
(function ($, document, apiClient) {
var currentItem;
function deleteRecording() {
Dashboard.confirm("Are you sure you wish to delete this recording?", "Confirm Recording Deletion", function (result) {
@ -6,14 +10,90 @@
Dashboard.showLoadingMsg();
ApiClient.deleteLiveTvRecording(id).done(function () {
ApiClient.deleteLiveTvRecording(currentItem.Id).done(function () {
Dashboard.alert('Recording deleted');
reload(page);
Dashboard.navigate('livetvrecordings.html');
});
}
});
}
}
function renderRecording(page, item) {
currentItem = item;
var name = item.Name;
$('#itemImage', page).html(LibraryBrowser.getDetailImageHtml(item));
Dashboard.setPageTitle(name);
$('.itemName', page).html(name);
$('.itemChannelNumber', page).html(item.Number);
$('.userDataIcons', page).html(LibraryBrowser.getUserDataIconsHtml(item));
$('.itemMiscInfo', page).html(LibraryBrowser.getMiscInfoHtml(item));
if (ApiClient.isWebSocketOpen()) {
var vals = [item.Type, item.Id, item.Name];
vals.push('livetv');
ApiClient.sendWebSocketMessage("Context", vals.join('|'));
}
if (MediaPlayer.canPlay(item)) {
$('#playButtonContainer', page).show();
} else {
$('#playButtonContainer', page).hide();
}
Dashboard.getCurrentUser().done(function (user) {
if (user.Configuration.IsAdministrator && item.LocationType !== "Offline") {
$('#deleteButtonContainer', page).show();
} else {
$('#deleteButtonContainer', page).hide();
}
});
Dashboard.hideLoadingMsg();
}
function reload(page) {
Dashboard.showLoadingMsg();
var id = getParameterByName('id');
apiClient.getLiveTvRecording(id).done(function (result) {
renderRecording(page, result);
});
}
$(document).on('pageinit', "#liveTvRecordingPage", function () {
var page = this;
$('#btnDelete', page).on('click', deleteRecording);
}).on('pagebeforeshow', "#liveTvRecordingPage", function () {
var page = this;
reload(page);
}).on('pagehide', "#liveTvRecordingPage", function () {
currentItem = null;
});
})(jQuery, document, ApiClient);

View File

@ -34,7 +34,13 @@
html += '</td>';
html += '<td>';
html += '<a href="livetvrecording.html?id=' + recording.Id + '">' + recording.Name + '</a>';
html += '<a href="livetvrecording.html?id=' + recording.Id + '">';
html += recording.Name;
if (recording.EpisodeTitle) {
html += "<br/>" + recording.EpisodeTitle;
}
html += '</a>';
html += '</td>';
html += '<td class="desktopColumn">';
@ -57,7 +63,9 @@
html += '<td>' + LiveTvHelpers.getDisplayTime(recording.StartDate) + '</td>';
html += '<td class="tabletColumn">' + LiveTvHelpers.getDisplayTime(recording.EndDate) + '</td>';
var minutes = recording.DurationMs / 60000;
html += '<td class="tabletColumn">' + minutes.toFixed(0) + ' mins</td>';
html += '<td class="tabletColumn">' + (recording.Status || '') + '</td>';

View File

@ -38,7 +38,7 @@
html += '<th class="desktopColumn">Channel</th>';
html += '<th>Date</th>';
html += '<th>Start</th>';
html += '<th class="tabletColumn">End</th>';
html += '<th class="tabletColumn">Length</th>';
html += '<th class="tabletColumn">Status</th>';
html += '<th class="desktopColumn">Recurring</th>';
@ -78,7 +78,9 @@
html += '<td>' + LiveTvHelpers.getDisplayTime(timer.StartDate) + '</td>';
html += '<td class="tabletColumn">' + LiveTvHelpers.getDisplayTime(timer.EndDate) + '</td>';
var minutes = timer.DurationMs / 60000;
html += '<td class="tabletColumn">' + minutes.toFixed(0) + ' mins</td>';
html += '<td class="tabletColumn">' + (timer.Status || '') + '</td>';

View File

@ -102,11 +102,11 @@
hours = 0;
}
hours = parseInt(hours);
hours = hours.toFixed(0);
ticks -= (hours * 36000000000);
var minutes = parseInt(ticks / 600000000);
var minutes = (ticks / 600000000).toFixed(0);
var suffix = "am";

View File

@ -1100,7 +1100,7 @@ var Dashboard = {
var parts = [];
var hours = ticks / ticksPerHour;
hours = parseInt(hours);
hours = hours.toFixed(0);
if (hours) {
parts.push(hours);
@ -1111,7 +1111,7 @@ var Dashboard = {
var ticksPerMinute = 600000000;
var minutes = ticks / ticksPerMinute;
minutes = parseInt(minutes);
minutes = minutes.toFixed(0);
ticks -= (minutes * ticksPerMinute);
@ -1123,7 +1123,7 @@ var Dashboard = {
var ticksPerSecond = 10000000;
var seconds = ticks / ticksPerSecond;
seconds = parseInt(seconds);
seconds = seconds.toFixed(0);
if (seconds < 10) {
seconds = '0' + seconds;

View File

@ -9,7 +9,7 @@
SortBy: "DateCreated",
SortOrder: "Descending",
IncludeItemTypes: "Episode",
Limit: 8,
Limit: 12,
Recursive: true,
Fields: "PrimaryImageAspectRatio,SeriesInfo,UserData",
Filters: "IsUnplayed",
@ -35,7 +35,7 @@
SortOrder: "Descending",
IncludeItemTypes: "Episode",
Filters: "IsResumable",
Limit: 8,
Limit: 4,
Recursive: true,
Fields: "PrimaryImageAspectRatio,SeriesInfo,UserData",
ExcludeLocationTypes: "Virtual"

View File

@ -7,7 +7,9 @@
function getDateFormat(date) {
// yyyyMMddHHmmss
var d = date;
// Convert to UTC
// http://stackoverflow.com/questions/948532/how-do-you-convert-a-javascript-date-to-utc/14610512#14610512
var d = new Date(date.getTime());
return "" + d.getFullYear() + formatDigit(d.getMonth() + 1) + formatDigit(d.getDate()) + formatDigit(d.getHours()) + formatDigit(d.getMinutes()) + formatDigit(d.getSeconds());
}
@ -28,15 +30,15 @@
var missedItemsQuery = $.extend({
IsUnaired: false
}, query);
var yesterday = new Date();
yesterday.setHours(23, 50, 0, 0);
yesterday.setDate(yesterday.getDate() - 1);
missedItemsQuery.MaxPremiereDate = getDateFormat(yesterday);
yesterday.setHours(0, 0, 0, 0);
missedItemsQuery.MinPremiereDate = getDateFormat(yesterday);
var unairedQuery = $.extend({

View File

@ -19,10 +19,6 @@
<table class="ehsContent">
<tr>
<td>
<h1 class="listHeader firstListHeader">Latest Episodes</h1>
<div id="recentlyAddedItems">
</div>
<div id="resumableSection" style="display: none;">
<h1 class="listHeader">Resume</h1>
@ -30,6 +26,11 @@
<div id="resumableItems">
</div>
</div>
<h1 class="listHeader">Latest Episodes</h1>
<div id="recentlyAddedItems">
</div>
</td>
</tr>
</table>