always supply SeriesTimerId

This commit is contained in:
Luke Pulverenti 2016-09-19 11:41:35 -04:00
parent ef9ab82058
commit 85a11e81cf
16 changed files with 499 additions and 87 deletions

View File

@ -1421,10 +1421,56 @@ define(['datetime', 'imageLoader', 'connectionManager', 'itemHelper', 'mediaInfo
}
}
function onTimerCreated(programId, newTimerId, itemsContainer) {
var cells = itemsContainer.querySelectorAll('.card[data-id="' + programId + '"]');
for (var i = 0, length = cells.length; i < length; i++) {
var cell = cells[i];
var icon = cell.querySelector('.timerIndicator');
if (!icon) {
var indicatorsElem = ensureIndicators(cell);
indicatorsElem.insertAdjacentHTML('beforeend', '<i class="md-icon timerIndicator indicatorIcon">&#xE061;</i>');
}
cell.setAttribute('data-timerid', newTimerId);
}
}
function onTimerCancelled(id, itemsContainer) {
var cells = itemsContainer.querySelectorAll('.card[data-timerid="' + id + '"]');
for (var i = 0, length = cells.length; i < length; i++) {
var cell = cells[i];
var icon = cell.querySelector('.timerIndicator');
if (icon) {
icon.parentNode.removeChild(icon);
}
cell.removeAttribute('data-timerid');
}
}
function onSeriesTimerCancelled(id, itemsContainer) {
var cells = itemsContainer.querySelectorAll('.card[data-seriestimerid="' + id + '"]');
for (var i = 0, length = cells.length; i < length; i++) {
var cell = cells[i];
var icon = cell.querySelector('.timerIndicator');
if (icon) {
icon.parentNode.removeChild(icon);
}
cell.removeAttribute('data-seriestimerid');
}
}
return {
getCardsHtml: getCardsHtml,
buildCards: buildCards,
onUserDataChanged: onUserDataChanged,
getDefaultColorClass: getDefaultColorClass
getDefaultColorClass: getDefaultColorClass,
onTimerCreated: onTimerCreated,
onTimerCancelled: onTimerCancelled,
onSeriesTimerCancelled: onSeriesTimerCancelled
};
});

View File

@ -183,6 +183,57 @@
});
}
function onTimerCreated(e, apiClient, data) {
var itemsContainer = this;
var programId = data.ProgramId;
// This could be null, not supported by all tv providers
var newTimerId = data.Id;
require(['cardBuilder'], function (cardBuilder) {
cardBuilder.onTimerCreated(programId, newTimerId, itemsContainer);
});
}
function onSeriesTimerCreated(e, apiClient, data) {
var itemsContainer = this;
}
function onTimerCancelled(e, apiClient, data) {
var itemsContainer = this;
var id = data.Id;
require(['cardBuilder'], function (cardBuilder) {
cardBuilder.onTimerCancelled(id, itemsContainer);
});
}
function onSeriesTimerCancelled(e, apiClient, data) {
var itemsContainer = this;
var id = data.Id;
require(['cardBuilder'], function (cardBuilder) {
cardBuilder.onSeriesTimerCancelled(id, itemsContainer);
});
}
function addNotificationEvent(instance, name, handler) {
var localHandler = handler.bind(instance);
events.on(serverNotifications, name, localHandler);
instance[name] = localHandler;
}
function removeNotificationEvent(instance, name) {
var handler = instance[name];
if (handler) {
events.off(serverNotifications, 'UserDataChanged', handler);
instance[name] = null;
}
}
ItemsContainerProtoType.attachedCallback = function () {
this.addEventListener('click', onClick);
@ -203,9 +254,11 @@
itemShortcuts.on(this, getShortcutOptions());
var userDataHandler = onUserDataChanged.bind(this);
events.on(serverNotifications, 'UserDataChanged', userDataHandler);
this.userDataHandler = userDataHandler;
addNotificationEvent(this, 'UserDataChanged', onUserDataChanged);
addNotificationEvent(this, 'TimerCreated', onTimerCreated);
addNotificationEvent(this, 'SeriesTimerCreated', onSeriesTimerCreated);
addNotificationEvent(this, 'TimerCancelled', onTimerCancelled);
addNotificationEvent(this, 'SeriesTimerCancelled', onSeriesTimerCancelled);
};
ItemsContainerProtoType.detachedCallback = function () {
@ -218,11 +271,11 @@
this.removeEventListener('contextmenu', disableEvent);
itemShortcuts.off(this, getShortcutOptions());
var userDataHandler = this.userDataHandler;
if (userDataHandler) {
events.off(serverNotifications, 'UserDataChanged', userDataHandler);
this.userDataHandler = null;
}
removeNotificationEvent(this, 'UserDataChanged');
removeNotificationEvent(this, 'TimerCreated');
removeNotificationEvent(this, 'SeriesTimerCreated');
removeNotificationEvent(this, 'TimerCancelled');
removeNotificationEvent(this, 'SeriesTimerCancelled');
};
document.registerElement('emby-itemscontainer', {

View File

@ -54,6 +54,10 @@
background: rgba(82,181,75, 0.5);
}
.mdl-switch__input.red:checked + .mdl-switch__label + .mdl-switch__track {
background: rgba(204,51,51, 0.5);
}
.mdl-switch__input[disabled] + .mdl-switch__label + .mdl-switch__track {
background: rgba(0,0,0, 0.12);
cursor: auto;
@ -80,6 +84,12 @@
box-shadow: 0 3px 4px 0 rgba(0, 0, 0, 0.14), 0 3px 3px -2px rgba(0, 0, 0, 0.2), 0 1px 8px 0 rgba(0, 0, 0, 0.12);
}
.mdl-switch__input.red:checked + .mdl-switch__label + .mdl-switch__track + .mdl-switch__thumb {
background: rgb(204,51,51);
left: 1.146em;
box-shadow: 0 3px 4px 0 rgba(0, 0, 0, 0.14), 0 3px 3px -2px rgba(0, 0, 0, 0.2), 0 1px 8px 0 rgba(0, 0, 0, 0.12);
}
.mdl-switch__input[disabled] + .mdl-switch__label + .mdl-switch__track + .mdl-switch__thumb {
background: rgb(189,189,189);
cursor: auto;
@ -109,12 +119,19 @@
background-color: rgba(82,181,75, 0.26);
}
.mdl-switch__input.red:checked:focus + .mdl-switch__label + .mdl-switch__track + .mdl-switch__thumb > .mdl-switch__focus-helper {
box-shadow: 0 0 0px 20px rgba(204,51,51, 0.26);
background-color: rgba(204,51,51, 0.26);
}
.mdl-switch__label {
position: relative;
cursor: pointer;
line-height: 1.72em;
margin: 0;
left: 1.52em;
display: inline-flex;
align-items: center;
}
.mdl-switch__input[disabled] .mdl-switch__label {

View File

@ -396,10 +396,10 @@
}
if (program.SeriesTimerId) {
html += '<i class="seriesTimerIcon md-icon programIcon">fiber_smart_record</i>';
html += '<i class="seriesTimerIcon md-icon programIcon">&#xE062;</i>';
}
else if (program.TimerId) {
html += '<i class="timerIcon md-icon programIcon">fiber_manual_record</i>';
html += '<i class="timerIcon md-icon programIcon">&#xE061;</i>';
}
if (addAccent) {
@ -778,7 +778,7 @@
var icon = cell.querySelector('.timerIcon');
if (!icon) {
cell.insertAdjacentHTML('beforeend', '<i class="timerIcon md-icon">fiber_manual_record</i>');
cell.insertAdjacentHTML('beforeend', '<i class="timerIcon md-icon">&#xE061;</i>');
}
if (newTimerId) {

View File

@ -99,10 +99,10 @@ define(['css!./indicators.css', 'material-icons'], function () {
function getTimerIndicator(item) {
if (item.SeriesTimerId) {
return '<i class="md-icon timerIndicator indicatorIcon">fiber_smart_record</i>';
return '<i class="md-icon timerIndicator indicatorIcon">&#xE062;</i>';
}
if (item.TimerId) {
return '<i class="md-icon timerIndicator indicatorIcon">fiber_manual_record</i>';
return '<i class="md-icon timerIndicator indicatorIcon">&#xE061;</i>';
}
return '';

View File

@ -168,7 +168,7 @@ define(['apphost', 'globalize', 'connectionManager', 'itemHelper', 'embyRouter',
}
}
if (item.Type == 'Program' && (!item.TimerId && !item.SeriesTimerId)) {
if (item.Type == 'Program') {
commands.push({
name: Globalize.translate('sharedcomponents#Record'),

View File

@ -0,0 +1,242 @@
define(['globalize', 'connectionManager', 'require', 'loading', 'apphost', 'recordingHelper', 'emby-toggle'], function (globalize, connectionManager, require, loading, appHost, recordingHelper) {
function getRegistration(apiClient, programId, feature) {
loading.show();
return apiClient.getJSON(apiClient.getUrl('LiveTv/Registration', {
ProgramId: programId,
Feature: feature
})).then(function (result) {
loading.hide();
return result;
}, function () {
loading.hide();
return {
TrialVersion: true,
IsValid: true,
IsRegistered: false
};
});
}
function showConvertRecordingsUnlockMessage(context, apiClient) {
apiClient.getPluginSecurityInfo().then(function (regInfo) {
if (regInfo.IsMBSupporter) {
context.querySelector('.convertRecordingsContainer').classList.add('hide');
} else {
context.querySelector('.convertRecordingsContainer').classList.remove('hide');
}
}, function () {
context.querySelector('.convertRecordingsContainer').classList.remove('hide');
});
}
function showSeriesRecordingFields(context, programId, apiClient) {
getRegistration(apiClient, programId, 'seriesrecordings').then(function (regInfo) {
if (regInfo.IsRegistered) {
context.querySelector('.supporterContainer').classList.add('hide');
context.querySelector('.convertRecordingsContainer').classList.add('hide');
} else {
context.querySelector('.supporterContainerText').innerHTML = globalize.translate('sharedcomponents#MessageActiveSubscriptionRequiredSeriesRecordings');
context.querySelector('.supporterContainer').classList.remove('hide');
context.querySelector('.convertRecordingsContainer').classList.add('hide');
}
});
}
function showSingleRecordingFields(context, programId, apiClient) {
getRegistration(apiClient, programId, 'dvr').then(function (regInfo) {
if (regInfo.IsRegistered) {
context.querySelector('.supporterContainer').classList.add('hide');
showConvertRecordingsUnlockMessage(context, apiClient);
} else {
context.querySelector('.supporterContainerText').innerHTML = globalize.translate('sharedcomponents#DvrSubscriptionRequired');
context.querySelector('.supporterContainer').classList.remove('hide');
context.querySelector('.convertRecordingsContainer').classList.add('hide');
}
});
}
function showRecordingFieldsContainer(context, programId, apiClient) {
getRegistration(apiClient, programId, 'dvr').then(function (regInfo) {
if (regInfo.IsRegistered) {
context.querySelector('.recordingFields').classList.remove('hide');
} else {
context.querySelector('.recordingFields').classList.add('hide');
}
});
}
function loadData(parent, program, apiClient) {
if (program.IsSeries) {
parent.querySelector('.chkRecordSeriesContainer').classList.remove('hide');
} else {
parent.querySelector('.chkRecordSeriesContainer').classList.add('hide');
}
parent.querySelector('.chkRecord').checked = program.TimerId != null;
parent.querySelector('.chkRecordSeries').checked = program.SeriesTimerId != null;
if (program.SeriesTimerId != null) {
showSeriesRecordingFields(parent, program.Id, apiClient);
} else {
showSingleRecordingFields(parent, program.Id, apiClient);
}
//var seriesTimerPromise = program.SeriesTimerId ?
// apiClient.getLiveTvSeriesTimer(program.SeriesTimerId) :
// apiClient.getLiveTvProgram(program.Id, apiClient.getCurrentUserId());
//seriesTimerPromise.then(function (seriesTimer) {
//});
}
function fetchData(instance) {
var options = instance.options;
var apiClient = connectionManager.getApiClient(options.serverId);
showRecordingFieldsContainer(options.parent, options.programId, apiClient);
return apiClient.getLiveTvProgram(options.programId, apiClient.getCurrentUserId()).then(function (program) {
instance.TimerId = program.TimerId;
instance.SeriesTimerId = program.SeriesTimerId;
loadData(options.parent, program, apiClient);
});
}
function recordingEditor(options) {
this.options = options;
this.embed();
}
function onSupporterButtonClick() {
if (appHost.supports('externalpremium')) {
shell.openUrl('https://emby.media/premiere');
} else {
}
}
function onRecordChange(e) {
this.changed = true;
var self = this;
var options = this.options;
var apiClient = connectionManager.getApiClient(options.serverId);
var isChecked = e.target.checked;
if (e.target.checked) {
if (!this.TimerId && !this.SeriesTimerId) {
recordingHelper.createRecording(apiClient, options.programId, false).then(function () {
fetchData(self);
});
}
} else {
if (this.TimerId) {
recordingHelper.cancelTimer(apiClient, this.TimerId, true).then(function () {
fetchData(self);
});
}
}
}
function onRecordSeriesChange(e) {
this.changed = true;
var self = this;
var options = this.options;
var apiClient = connectionManager.getApiClient(options.serverId);
var isChecked = e.target.checked;
if (e.target.checked) {
showSeriesRecordingFields(options.parent, options.programId, apiClient);
if (!this.SeriesTimerId) {
var promise = this.TimerId ?
recordingHelper.changeRecordingToSeries(apiClient, this.TimerId, options.programId) :
recordingHelper.createRecording(apiClient, options.programId, true);
promise.then(function () {
fetchData(self);
});
}
} else {
showSingleRecordingFields(options.parent, options.programId, apiClient);
if (this.SeriesTimerId) {
apiClient.cancelLiveTvSeriesTimer(this.SeriesTimerId).then(function () {
fetchData(self);
});
}
}
}
recordingEditor.prototype.embed = function () {
var self = this;
return new Promise(function (resolve, reject) {
require(['text!./recordingfields.template.html'], function (template) {
var options = self.options;
var context = options.parent;
context.innerHTML = globalize.translateDocument(template, 'sharedcomponents');
var supporterButtons = context.querySelectorAll('.btnSupporter');
for (var i = 0, length = supporterButtons.length; i < length; i++) {
if (appHost.supports('externalpremium')) {
supporterButtons[i].classList.remove('hide');
} else {
supporterButtons[i].classList.add('hide');
}
supporterButtons[i].addEventListener('click', onSupporterButtonClick);
}
context.querySelector('.chkRecord').addEventListener('change', onRecordChange.bind(self));
context.querySelector('.chkRecordSeries').addEventListener('change', onRecordSeriesChange.bind(self));
fetchData(self).then(resolve);
});
});
};
recordingEditor.prototype.hasChanged = function () {
return this.changed;
};
return recordingEditor;
});

View File

@ -0,0 +1,27 @@
<div class="convertRecordingsContainer hide" style="text-align: center; padding: 1.25em 1.5em; background: #242424; border-radius: 3px; margin: 1em 0 2em;">
<h1 style="margin: .25em 0 .5em;">${HeaderConvertYourRecordings}</h1>
<div class="fieldDescription">${PromoConvertRecordingsToStreamingFormat}</div>
<br />
<button is="emby-button" type="button" class="raised btnSupporter btnSupporterForConverting button-submit">
<span>${HeaderLearnMore}</span>
</button>
</div>
<div class="supporterContainer hide" style="text-align: center; padding: 1.25em 1.5em; background: #242424; border-radius: 3px; margin: 1em 0 2em;">
<div class="supporterContainerText"></div>
<br />
<button is="emby-button" type="button" class="btnSupporter hide raised button-submit block">
<span>${HeaderBecomeProjectSupporter}</span>
</button>
</div>
<div class="recordingFields hide">
<label class="toggleContainer chkRecordSeriesContainer hide" style="margin-bottom: 1em;">
<input type="checkbox" is="emby-toggle" class="chkRecordSeries red" />
<span>${RecordSeries}</span>
</label>
<label class="toggleContainer">
<input type="checkbox" is="emby-toggle" class="chkRecord red" />
<span>${Record}</span>
</label>
</div>

View File

@ -0,0 +1,67 @@
define(['globalize', 'loading'], function (globalize, loading) {
function changeRecordingToSeries(apiClient, timerId, programId) {
loading.show();
apiClient.getItem(apiClient.getCurrentUserId(), programId).then(function (item) {
if (item.IsSeries) {
// cancel, then create series
cancelTimer(apiClient, timerId, false).then(function () {
apiClient.getNewLiveTvTimerDefaults({ programId: programId }).then(function (timerDefaults) {
apiClient.createLiveTvSeriesTimer(timerDefaults).then(function () {
loading.hide();
sendToast(globalize.translate('sharedcomponents#SeriesRecordingScheduled'));
});
});
});
} else {
// cancel
cancelTimer(apiClient, timerId, true);
}
});
}
function cancelTimer(apiClient, timerId, hideLoading) {
loading.show();
return apiClient.cancelLiveTvTimer(timerId).then(function () {
if (hideLoading) {
loading.hide();
sendToast(globalize.translate('sharedcomponents#RecordingCancelled'));
}
});
}
function createRecording(apiClient, programId, isSeries) {
loading.show();
return apiClient.getNewLiveTvTimerDefaults({ programId: programId }).then(function (item) {
var promise = isSeries ?
apiClient.createLiveTvSeriesTimer(item) :
apiClient.createLiveTvTimer(item);
return promise.then(function () {
loading.hide();
sendToast(globalize.translate('sharedcomponents#RecordingScheduled'));
});
});
}
function sendToast(msg) {
require(['toast'], function (toast) {
toast(msg);
});
}
return {
cancelTimer: cancelTimer,
createRecording: createRecording,
changeRecordingToSeries: changeRecordingToSeries
};
});

View File

@ -1,4 +1,4 @@
define(['playbackManager', 'inputManager', 'connectionManager', 'embyRouter', 'globalize', 'loading', 'dom'], function (playbackManager, inputManager, connectionManager, embyRouter, globalize, loading, dom) {
define(['playbackManager', 'inputManager', 'connectionManager', 'embyRouter', 'globalize', 'loading', 'dom', 'recordingHelper'], function (playbackManager, inputManager, connectionManager, embyRouter, globalize, loading, dom, recordingHelper) {
function playAllFromHere(card, serverId, queue) {
@ -93,11 +93,6 @@ define(['playbackManager', 'inputManager', 'connectionManager', 'embyRouter', 'g
function showProgramDialog(item) {
if (item.TimerId) {
showItem(item);
return;
}
require(['recordingCreator'], function (recordingCreator) {
recordingCreator.show(item.Id, item.ServerId);
@ -338,75 +333,20 @@ define(['playbackManager', 'inputManager', 'connectionManager', 'embyRouter', 'g
if (seriesTimerId && timerId) {
// cancel
cancelTimer(apiClient, timerId, true);
recordingHelper.cancelTimer(apiClient, timerId, true);
} else if (timerId) {
// change to series recording, if possible
// otherwise cancel individual recording
changeRecordingToSeries(apiClient, timerId, id);
recordingHelper.changeRecordingToSeries(apiClient, timerId, id);
} else if (type == 'Program') {
// schedule recording
createRecording(apiClient, id);
recordingHelper.createRecording(apiClient, id);
}
}
function changeRecordingToSeries(apiClient, timerId, programId) {
loading.show();
apiClient.getItem(apiClient.getCurrentUserId(), programId).then(function (item) {
if (item.IsSeries) {
// cancel, then create series
cancelTimer(apiClient, timerId, false).then(function () {
apiClient.getNewLiveTvTimerDefaults({ programId: programId }).then(function (timerDefaults) {
apiClient.createLiveTvSeriesTimer(timerDefaults).then(function () {
loading.hide();
sendToast(globalize.translate('sharedcomponents#SeriesRecordingScheduled'));
});
});
});
} else {
// cancel
cancelTimer(apiClient, timerId, true);
}
});
}
function cancelTimer(apiClient, timerId, hideLoading) {
loading.show();
return apiClient.cancelLiveTvTimer(timerId).then(function () {
if (hideLoading) {
loading.hide();
sendToast(globalize.translate('sharedcomponents#RecordingCancelled'));
}
});
}
function createRecording(apiClient, programId) {
loading.show();
apiClient.getNewLiveTvTimerDefaults({ programId: programId }).then(function (item) {
apiClient.createLiveTvTimer(item).then(function () {
loading.hide();
sendToast(globalize.translate('sharedcomponents#RecordingScheduled'));
});
});
}
function sendToast(msg) {
require(['toast'], function (toast) {
toast(msg);
});
}
function onClick(e) {
var card = dom.parentWithClass(e.target, 'itemAction');

View File

@ -8,7 +8,7 @@
<div class="subtitleList" style="margin-bottom:2em;"></div>
<h1>${SearchForSubtitles}</h1>
<p style="margin: 1.5em 0;" class="originalFile"><span class="originalSubtitleFileLabel dimText"></span><span class="pathValue"></span></p>
<p style="margin: 1.5em 0;" class="originalFile"><span class="originalSubtitleFileLabel secondaryText"></span><span class="pathValue"></span></p>
<form class="subtitleSearchForm" style="max-width: none;">
<div style="display: flex; align-items: center;">

View File

@ -188,6 +188,14 @@ select {
color: #fff;
}
.ui-body-a .secondaryText {
color: #ccc;
}
.ui-body-b .secondaryText {
color: #aaa;
}
div[data-role='page'] {
outline: none;
}

View File

@ -184,8 +184,14 @@
return false;
}
if (MediaPlayer.canPlayNativeHls() && mediaSource.RunTimeTicks) {
return false;
if (MediaPlayer.canPlayNativeHls()) {
// simple playback should use the native support
if (mediaSource.RunTimeTicks) {
return false;
}
//return false;
}
// For now don't do this in edge because we lose some native audio support
@ -193,6 +199,11 @@
return false;
}
// hls.js is only in beta. needs more testing.
if (browser.safari) {
return false;
}
return true;
}

View File

@ -986,8 +986,9 @@
if (browser.msie) {
if (!window.MediaSource || !mediaSource.RunTimeTicks) {
if (window.MediaSource == null || mediaSource.RunTimeTicks == null) {
alert('Playback of this content is not supported in Internet Explorer. For a better experience, please try a modern browser such as Google Chrome, Firefox, Opera, or Microsoft Edge.');
return;
}
}
@ -1021,7 +1022,7 @@
Dashboard.hideLoadingMsg();
streamInfo.url = hlsPlaylistUrl;
onReadyToPlay();
setTimeout(onReadyToPlay, 0);
}, function () {
Dashboard.hideLoadingMsg();

View File

@ -143,9 +143,7 @@ define(['appSettings', 'userSettings', 'appStorage', 'datetime'], function (appS
return true;
}
// viblast can help us here
//return true;
return window.MediaSource;
return window.MediaSource != null;
};
self.changeStream = function (ticks, params) {

View File

@ -1234,6 +1234,8 @@ var AppInfo = {};
define("playlistEditor", [embyWebComponentsBowerPath + "/playlisteditor/playlisteditor"], returnFirstDependency);
define("recordingCreator", [embyWebComponentsBowerPath + "/recordingcreator/recordingcreator"], returnFirstDependency);
define("recordingEditor", [embyWebComponentsBowerPath + "/recordingcreator/recordingeditor"], returnFirstDependency);
define("recordingFields", [embyWebComponentsBowerPath + "/recordingcreator/recordingfields"], returnFirstDependency);
define("recordingHelper", [embyWebComponentsBowerPath + "/recordingcreator/recordinghelper"], returnFirstDependency);
define("subtitleEditor", [embyWebComponentsBowerPath + "/subtitleeditor/subtitleeditor"], returnFirstDependency);
define("itemIdentifier", [embyWebComponentsBowerPath + "/itemidentifier/itemidentifier"], returnFirstDependency);
define("mediaInfo", [embyWebComponentsBowerPath + "/mediainfo/mediainfo"], returnFirstDependency);