mirror of
https://github.com/jellyfin/jellyfin-web
synced 2025-03-30 19:56:21 +00:00
Merge branch 'master' into unavailable-yt-video-trailer-bug-fix
This commit is contained in:
commit
05bec3e16b
158 changed files with 3875 additions and 5955 deletions
|
@ -40,13 +40,13 @@ module.exports = {
|
|||
'no-multi-spaces': ['error'],
|
||||
'no-multiple-empty-lines': ['error', { 'max': 1 }],
|
||||
'no-trailing-spaces': ['error'],
|
||||
'no-unused-expressions': ['error', { 'allowShortCircuit': true, 'allowTernary': true, 'allowTaggedTemplates': true }],
|
||||
'no-unused-vars': ['error', { 'vars': 'all', 'args': 'none', 'ignoreRestSiblings': true }],
|
||||
'@babel/no-unused-expressions': ['error', { 'allowShortCircuit': true, 'allowTernary': true, 'allowTaggedTemplates': true }],
|
||||
//'no-unused-vars': ['error', { 'vars': 'all', 'args': 'none', 'ignoreRestSiblings': true }],
|
||||
'one-var': ['error', 'never'],
|
||||
'padded-blocks': ['error', 'never'],
|
||||
//'prefer-const': ['error', {'destructuring': 'all'}],
|
||||
'quotes': ['error', 'single', { 'avoidEscape': true, 'allowTemplateLiterals': false }],
|
||||
'semi': ['error'],
|
||||
'@babel/semi': ['error'],
|
||||
'space-before-blocks': ['error'],
|
||||
'space-infix-ops': 'error',
|
||||
'yoda': 'error'
|
||||
|
@ -106,6 +106,7 @@ module.exports = {
|
|||
// TODO: Fix warnings and remove these rules
|
||||
'no-redeclare': ['off'],
|
||||
'no-useless-escape': ['off'],
|
||||
'no-unused-vars': ['off'],
|
||||
// TODO: Remove after ES6 migration is complete
|
||||
'import/no-unresolved': ['off']
|
||||
},
|
||||
|
|
10
package.json
10
package.json
|
@ -20,7 +20,7 @@
|
|||
"css-loader": "^4.2.1",
|
||||
"cssnano": "^4.1.10",
|
||||
"del": "^5.1.0",
|
||||
"eslint": "^7.6.0",
|
||||
"eslint": "^7.7.0",
|
||||
"eslint-plugin-compat": "^3.5.1",
|
||||
"eslint-plugin-eslint-comments": "^3.2.0",
|
||||
"eslint-plugin-import": "^2.21.2",
|
||||
|
@ -96,6 +96,7 @@
|
|||
"src/components/alphaPicker/alphaPicker.js",
|
||||
"src/components/appFooter/appFooter.js",
|
||||
"src/components/apphost.js",
|
||||
"src/components/appRouter.js",
|
||||
"src/components/autoFocuser.js",
|
||||
"src/components/backdrop/backdrop.js",
|
||||
"src/components/cardbuilder/cardBuilder.js",
|
||||
|
@ -144,6 +145,7 @@
|
|||
"src/components/multiSelect/multiSelect.js",
|
||||
"src/components/notifications/notifications.js",
|
||||
"src/components/nowPlayingBar/nowPlayingBar.js",
|
||||
"src/components/packageManager.js",
|
||||
"src/components/playback/brightnessosd.js",
|
||||
"src/components/playback/mediasession.js",
|
||||
"src/components/playback/nowplayinghelper.js",
|
||||
|
@ -159,16 +161,21 @@
|
|||
"src/components/playerstats/playerstats.js",
|
||||
"src/components/playlisteditor/playlisteditor.js",
|
||||
"src/components/playmenu.js",
|
||||
"src/components/pluginManager.js",
|
||||
"src/components/prompt/prompt.js",
|
||||
"src/components/recordingcreator/recordingbutton.js",
|
||||
"src/components/recordingcreator/recordingcreator.js",
|
||||
"src/components/recordingcreator/seriesrecordingeditor.js",
|
||||
"src/components/recordingcreator/recordinghelper.js",
|
||||
"src/components/refreshdialog/refreshdialog.js",
|
||||
"src/components/recordingcreator/recordingeditor.js",
|
||||
"src/components/recordingcreator/recordingfields.js",
|
||||
"src/components/qualityOptions.js",
|
||||
"src/components/remotecontrol/remotecontrol.js",
|
||||
"src/components/sanatizefilename.js",
|
||||
"src/components/scrollManager.js",
|
||||
"src/plugins/experimentalWarnings/plugin.js",
|
||||
"src/plugins/sessionPlayer/plugin.js",
|
||||
"src/plugins/htmlAudioPlayer/plugin.js",
|
||||
"src/plugins/chromecastPlayer/plugin.js",
|
||||
"src/components/slideshow/slideshow.js",
|
||||
|
@ -318,6 +325,7 @@
|
|||
"src/scripts/alphanumericshortcuts.js",
|
||||
"src/scripts/autoBackdrops.js",
|
||||
"src/scripts/browser.js",
|
||||
"src/scripts/clientUtils.js",
|
||||
"src/scripts/datetime.js",
|
||||
"src/scripts/deleteHelper.js",
|
||||
"src/scripts/dfnshelper.js",
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<div class="formDialogHeader">
|
||||
<button is="paper-icon-button-light" class="btnCancel autoSize" title="${LabelPrevious}" tabindex="-1">
|
||||
<button is="paper-icon-button-light" class="btnCancel autoSize" title="${Previous}" tabindex="-1">
|
||||
<span class="material-icons arrow_back" aria-hidden="true"></span>
|
||||
</button>
|
||||
<h3 class="formDialogHeaderTitle">
|
||||
|
@ -12,13 +12,13 @@
|
|||
|
||||
<div class="selectContainer">
|
||||
<select is="emby-select" id="selectDay" label="${LabelAccessDay}">
|
||||
<option value="Sunday">${OptionSunday}</option>
|
||||
<option value="Monday">${OptionMonday}</option>
|
||||
<option value="Tuesday">${OptionTuesday}</option>
|
||||
<option value="Wednesday">${OptionWednesday}</option>
|
||||
<option value="Thursday">${OptionThursday}</option>
|
||||
<option value="Friday">${OptionFriday}</option>
|
||||
<option value="Saturday">${OptionSaturday}</option>
|
||||
<option value="Sunday">${Sunday}</option>
|
||||
<option value="Monday">${Monday}</option>
|
||||
<option value="Tuesday">${Tuesday}</option>
|
||||
<option value="Wednesday">${Wednesday}</option>
|
||||
<option value="Thursday">${Thursday}</option>
|
||||
<option value="Friday">${Friday}</option>
|
||||
<option value="Saturday">${Saturday}</option>
|
||||
<option value="Everyday">${OptionEveryday}</option>
|
||||
<option value="Weekday">${OptionWeekdays}</option>
|
||||
<option value="Weekend">${OptionWeekends}</option>
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1117,7 +1117,7 @@ import 'programStyles';
|
|||
function importRefreshIndicator() {
|
||||
if (!refreshIndicatorLoaded) {
|
||||
refreshIndicatorLoaded = true;
|
||||
/* eslint-disable-next-line no-unused-expressions */
|
||||
/* eslint-disable-next-line @babel/no-unused-expressions */
|
||||
import('emby-itemrefreshindicator');
|
||||
}
|
||||
}
|
||||
|
@ -1449,7 +1449,7 @@ import 'programStyles';
|
|||
const userData = item.UserData || {};
|
||||
|
||||
if (itemHelper.canMarkPlayed(item)) {
|
||||
/* eslint-disable-next-line no-unused-expressions */
|
||||
/* eslint-disable-next-line @babel/no-unused-expressions */
|
||||
import('emby-playstatebutton');
|
||||
html += '<button is="emby-playstatebutton" type="button" data-action="none" class="' + btnCssClass + '" data-id="' + item.Id + '" data-serverid="' + item.ServerId + '" data-itemtype="' + item.Type + '" data-played="' + (userData.Played) + '"><span class="material-icons cardOverlayButtonIcon cardOverlayButtonIcon-hover check"></span></button>';
|
||||
}
|
||||
|
@ -1457,7 +1457,7 @@ import 'programStyles';
|
|||
if (itemHelper.canRate(item)) {
|
||||
const likes = userData.Likes == null ? '' : userData.Likes;
|
||||
|
||||
/* eslint-disable-next-line no-unused-expressions */
|
||||
/* eslint-disable-next-line @babel/no-unused-expressions */
|
||||
import('emby-ratingbutton');
|
||||
html += '<button is="emby-ratingbutton" type="button" data-action="none" class="' + btnCssClass + '" data-id="' + item.Id + '" data-serverid="' + item.ServerId + '" data-itemtype="' + item.Type + '" data-likes="' + likes + '" data-isfavorite="' + (userData.IsFavorite) + '"><span class="material-icons cardOverlayButtonIcon cardOverlayButtonIcon-hover favorite"></span></button>';
|
||||
}
|
||||
|
|
|
@ -19,11 +19,11 @@ export default class channelMapper {
|
|||
connectionManager.getApiClient(options.serverId).ajax({
|
||||
type: 'POST',
|
||||
url: ApiClient.getUrl('LiveTv/ChannelMappings'),
|
||||
data: {
|
||||
data: JSON.stringify({
|
||||
providerId: providerId,
|
||||
tunerChannelId: channelId,
|
||||
providerChannelId: providerChannelId
|
||||
},
|
||||
}),
|
||||
dataType: 'json'
|
||||
}).then(mapping => {
|
||||
const listItem = dom.parentWithClass(button, 'listItem');
|
||||
|
@ -93,7 +93,7 @@ export default class channelMapper {
|
|||
html += '<div class="formDialogContent smoothScrollY">';
|
||||
html += '<div class="dialogContentInner dialog-content-centered">';
|
||||
html += '<form style="margin:auto;">';
|
||||
html += `<h1>${globalize.translate('HeaderChannels')}</h1>`;
|
||||
html += `<h1>${globalize.translate('Channels')}</h1>`;
|
||||
html += '<div class="channels paperList">';
|
||||
html += '</div>';
|
||||
html += '</form>';
|
||||
|
|
|
@ -375,7 +375,7 @@ import 'scrollStyles';
|
|||
dlg.setAttribute('data-lockscroll', 'true');
|
||||
}
|
||||
|
||||
if (options.enableHistory !== false && appRouter.enableNativeHistory()) {
|
||||
if (options.enableHistory !== false) {
|
||||
dlg.setAttribute('data-history', 'true');
|
||||
}
|
||||
|
||||
|
|
|
@ -125,7 +125,7 @@ import 'emby-button';
|
|||
html += `<input is="emby-input" id="txtDirectoryPickerPath" type="text" required="required" ${readOnlyAttribute} label="${globalize.translate(labelKey)}"/>`;
|
||||
html += '</div>';
|
||||
if (!readOnlyAttribute) {
|
||||
html += `<button type="button" is="paper-icon-button-light" class="btnRefreshDirectories emby-input-iconbutton" title="${globalize.translate('ButtonRefresh')}"><span class="material-icons search"></span></button>`;
|
||||
html += `<button type="button" is="paper-icon-button-light" class="btnRefreshDirectories emby-input-iconbutton" title="${globalize.translate('Refresh')}"><span class="material-icons search"></span></button>`;
|
||||
}
|
||||
html += '</div>';
|
||||
if (!readOnlyAttribute) {
|
||||
|
@ -166,10 +166,10 @@ import 'emby-button';
|
|||
return apiClient.ajax({
|
||||
type: 'POST',
|
||||
url: apiClient.getUrl('Environment/ValidatePath'),
|
||||
data: {
|
||||
data: JSON.stringify({
|
||||
ValidateWriteable: validateWriteable,
|
||||
Path: path
|
||||
}
|
||||
})
|
||||
}).catch(response => {
|
||||
if (response) {
|
||||
if (response.status === 404) {
|
||||
|
|
|
@ -162,7 +162,7 @@
|
|||
<div class="checkboxContainer checkboxContainer-withDescription fldBackdrops hide">
|
||||
<label>
|
||||
<input type="checkbox" is="emby-checkbox" id="chkBackdrops" />
|
||||
<span>${EnableBackdrops}</span>
|
||||
<span>${Backdrops}</span>
|
||||
</label>
|
||||
<div class="fieldDescription checkboxFieldDescription">${EnableBackdropsHelp}</div>
|
||||
</div>
|
||||
|
@ -170,7 +170,7 @@
|
|||
<div class="checkboxContainer checkboxContainer-withDescription fldThemeSong hide">
|
||||
<label>
|
||||
<input type="checkbox" is="emby-checkbox" id="chkThemeSong" />
|
||||
<span>${EnableThemeSongs}</span>
|
||||
<span>${ThemeSongs}</span>
|
||||
</label>
|
||||
<div class="fieldDescription checkboxFieldDescription">${EnableThemeSongsHelp}</div>
|
||||
</div>
|
||||
|
@ -178,7 +178,7 @@
|
|||
<div class="checkboxContainer checkboxContainer-withDescription fldThemeVideo hide">
|
||||
<label>
|
||||
<input type="checkbox" is="emby-checkbox" id="chkThemeVideo" />
|
||||
<span>${EnableThemeVideos}</span>
|
||||
<span>${ThemeVideos}</span>
|
||||
</label>
|
||||
<div class="fieldDescription checkboxFieldDescription">${EnableThemeVideosHelp}</div>
|
||||
</div>
|
||||
|
|
|
@ -90,7 +90,7 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div is="emby-collapse" title="${HeaderGenres}" class="genreFilters hide">
|
||||
<div is="emby-collapse" title="${Genres}" class="genreFilters hide">
|
||||
<div class="collapseContent filterOptions">
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<div class="formDialogHeader">
|
||||
<button is="paper-icon-button-light" class="btnCancel autoSize" title="${LabelPrevious}" tabindex="-1">
|
||||
<button is="paper-icon-button-light" class="btnCancel autoSize" title="${Previous}" tabindex="-1">
|
||||
<span class="material-icons arrow_back" aria-hidden="true"></span>
|
||||
</button>
|
||||
<h3 class="formDialogHeaderTitle">
|
||||
|
|
|
@ -547,7 +547,7 @@ function Guide(options) {
|
|||
} else if (program.IsPremiere && options.showPremiereIndicator) {
|
||||
indicatorHtml = '<span class="premiereTvProgram guideProgramIndicator">' + globalize.translate('Premiere') + '</span>';
|
||||
} else if (program.IsSeries && !program.IsRepeat && options.showNewIndicator) {
|
||||
indicatorHtml = '<span class="newTvProgram guideProgramIndicator">' + globalize.translate('AttributeNew') + '</span>';
|
||||
indicatorHtml = '<span class="newTvProgram guideProgramIndicator">' + globalize.translate('New') + '</span>';
|
||||
} else if (program.IsSeries && program.IsRepeat && options.showRepeatIndicator) {
|
||||
indicatorHtml = '<span class="repeatTvProgram guideProgramIndicator">' + globalize.translate('Repeat') + '</span>';
|
||||
}
|
||||
|
|
|
@ -29,10 +29,10 @@
|
|||
</div>
|
||||
|
||||
<div class="guideOptions hide">
|
||||
<button is="paper-icon-button-light" type="button" class="btnPreviousPage" title="${LabelPrevious}">
|
||||
<button is="paper-icon-button-light" type="button" class="btnPreviousPage" title="${Previous}">
|
||||
<span class="material-icons arrow_back" aria-hidden="true"></span>
|
||||
</button>
|
||||
<button is="paper-icon-button-light" type="button" class="btnNextPage" title="${LabelNext}">
|
||||
<button is="paper-icon-button-light" type="button" class="btnNextPage" title="${Next}">
|
||||
<span class="material-icons arrow_forward" aria-hidden="true"></span>
|
||||
</button>
|
||||
</div>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<form style="margin:0 auto;">
|
||||
<div class="verticalSection verticalSection-extrabottompadding">
|
||||
<h2 class="sectionTitle">${HeaderHome}</h2>
|
||||
<h2 class="sectionTitle">${Home}</h2>
|
||||
|
||||
<div class="selectContainer hide selectTVHomeScreenContainer">
|
||||
<select is="emby-select" class="selectTVHomeScreen" label="${LabelTVHomeScreen}">
|
||||
|
@ -25,7 +25,7 @@
|
|||
<option value="resume">${HeaderContinueWatching}</option>
|
||||
<option value="resumeaudio">${HeaderContinueListening}</option>
|
||||
<option value="latestmedia">${HeaderLatestMedia}</option>
|
||||
<option value="nextup">${HeaderNextUp}</option>
|
||||
<option value="nextup">${NextUp}</option>
|
||||
<option value="livetv">${LiveTV}</option>
|
||||
<option value="none">${None}</option>
|
||||
</select>
|
||||
|
@ -38,7 +38,7 @@
|
|||
<option value="resume">${HeaderContinueWatching}</option>
|
||||
<option value="resumeaudio">${HeaderContinueListening}</option>
|
||||
<option value="latestmedia">${HeaderLatestMedia}</option>
|
||||
<option value="nextup">${HeaderNextUp}</option>
|
||||
<option value="nextup">${NextUp}</option>
|
||||
<option value="livetv">${LiveTV}</option>
|
||||
<option value="none">${None}</option>
|
||||
</select>
|
||||
|
@ -51,7 +51,7 @@
|
|||
<option value="resume">${HeaderContinueWatching}</option>
|
||||
<option value="resumeaudio">${HeaderContinueListening}</option>
|
||||
<option value="latestmedia">${HeaderLatestMedia}</option>
|
||||
<option value="nextup">${HeaderNextUp}</option>
|
||||
<option value="nextup">${NextUp}</option>
|
||||
<option value="livetv">${LiveTV}</option>
|
||||
<option value="none">${None}</option>
|
||||
</select>
|
||||
|
@ -64,7 +64,7 @@
|
|||
<option value="resume">${HeaderContinueWatching}</option>
|
||||
<option value="resumeaudio">${HeaderContinueListening}</option>
|
||||
<option value="latestmedia">${HeaderLatestMedia}</option>
|
||||
<option value="nextup">${HeaderNextUp}</option>
|
||||
<option value="nextup">${NextUp}</option>
|
||||
<option value="livetv">${LiveTV}</option>
|
||||
<option value="none">${None}</option>
|
||||
</select>
|
||||
|
@ -77,7 +77,7 @@
|
|||
<option value="resume">${HeaderContinueWatching}</option>
|
||||
<option value="resumeaudio">${HeaderContinueListening}</option>
|
||||
<option value="latestmedia">${HeaderLatestMedia}</option>
|
||||
<option value="nextup">${HeaderNextUp}</option>
|
||||
<option value="nextup">${NextUp}</option>
|
||||
<option value="livetv">${LiveTV}</option>
|
||||
<option value="none">${None}</option>
|
||||
</select>
|
||||
|
@ -90,7 +90,7 @@
|
|||
<option value="resume">${HeaderContinueWatching}</option>
|
||||
<option value="resumeaudio">${HeaderContinueListening}</option>
|
||||
<option value="latestmedia">${HeaderLatestMedia}</option>
|
||||
<option value="nextup">${HeaderNextUp}</option>
|
||||
<option value="nextup">${NextUp}</option>
|
||||
<option value="livetv">${LiveTV}</option>
|
||||
<option value="none">${None}</option>
|
||||
</select>
|
||||
|
@ -103,7 +103,7 @@
|
|||
<option value="resume">${HeaderContinueWatching}</option>
|
||||
<option value="resumeaudio">${HeaderContinueListening}</option>
|
||||
<option value="latestmedia">${HeaderLatestMedia}</option>
|
||||
<option value="nextup">${HeaderNextUp}</option>
|
||||
<option value="nextup">${NextUp}</option>
|
||||
<option value="livetv">${LiveTV}</option>
|
||||
<option value="none">${None}</option>
|
||||
</select>
|
||||
|
|
|
@ -696,12 +696,12 @@ import 'css!./homesections';
|
|||
serverId: apiClient.serverId()
|
||||
}) + '" class="button-flat button-flat-mini sectionTitleTextButton">';
|
||||
html += '<h2 class="sectionTitle sectionTitle-cards">';
|
||||
html += globalize.translate('HeaderNextUp');
|
||||
html += globalize.translate('NextUp');
|
||||
html += '</h2>';
|
||||
html += '<span class="material-icons chevron_right"></span>';
|
||||
html += '</a>';
|
||||
} else {
|
||||
html += '<h2 class="sectionTitle sectionTitle-cards">' + globalize.translate('HeaderNextUp') + '</h2>';
|
||||
html += '<h2 class="sectionTitle sectionTitle-cards">' + globalize.translate('NextUp') + '</h2>';
|
||||
}
|
||||
html += '</div>';
|
||||
|
||||
|
|
|
@ -8,7 +8,6 @@ import browser from 'browser';
|
|||
import actionsheet from 'actionsheet';
|
||||
|
||||
/* eslint-disable indent */
|
||||
|
||||
export function getCommands(options) {
|
||||
const item = options.item;
|
||||
const user = options.user;
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<button is="paper-icon-button-light" class="btnCancel autoSize" tabindex="-1">
|
||||
<span class="material-icons arrow_back"></span>
|
||||
</button>
|
||||
<h3 class="formDialogHeaderTitle">${HeaderMediaInfo}</h3>
|
||||
<h3 class="formDialogHeaderTitle">${MoreMediaInfo}</h3>
|
||||
</div>
|
||||
|
||||
<div class="formDialogContent smoothScrollY">
|
||||
|
|
|
@ -75,9 +75,9 @@ import 'emby-input';
|
|||
html += '</h3>';
|
||||
html += '</div>';
|
||||
if (i > 0) {
|
||||
html += `<button type="button" is="paper-icon-button-light" title="${globalize.translate('ButtonUp')}" class="btnSortableMoveUp btnSortable" data-pluginindex="${i}"><span class="material-icons keyboard_arrow_up"></span></button>`;
|
||||
html += `<button type="button" is="paper-icon-button-light" title="${globalize.translate('Up')}" class="btnSortableMoveUp btnSortable" data-pluginindex="${i}"><span class="material-icons keyboard_arrow_up"></span></button>`;
|
||||
} else if (plugins.length > 1) {
|
||||
html += `<button type="button" is="paper-icon-button-light" title="${globalize.translate('ButtonDown')}" class="btnSortableMoveDown btnSortable" data-pluginindex="${i}"><span class="material-icons keyboard_arrow_down"></span></button>`;
|
||||
html += `<button type="button" is="paper-icon-button-light" title="${globalize.translate('Down')}" class="btnSortableMoveDown btnSortable" data-pluginindex="${i}"><span class="material-icons keyboard_arrow_down"></span></button>`;
|
||||
}
|
||||
html += '</div>';
|
||||
}
|
||||
|
@ -131,9 +131,9 @@ import 'emby-input';
|
|||
html += '</h3>';
|
||||
html += '</div>';
|
||||
if (index > 0) {
|
||||
html += '<button type="button" is="paper-icon-button-light" title="' + globalize.translate('ButtonUp') + '" class="btnSortableMoveUp btnSortable" data-pluginindex="' + index + '"><span class="material-icons keyboard_arrow_up"></span></button>';
|
||||
html += '<button type="button" is="paper-icon-button-light" title="' + globalize.translate('Up') + '" class="btnSortableMoveUp btnSortable" data-pluginindex="' + index + '"><span class="material-icons keyboard_arrow_up"></span></button>';
|
||||
} else if (plugins.length > 1) {
|
||||
html += '<button type="button" is="paper-icon-button-light" title="' + globalize.translate('ButtonDown') + '" class="btnSortableMoveDown btnSortable" data-pluginindex="' + index + '"><span class="material-icons keyboard_arrow_down"></span></button>';
|
||||
html += '<button type="button" is="paper-icon-button-light" title="' + globalize.translate('Down') + '" class="btnSortableMoveDown btnSortable" data-pluginindex="' + index + '"><span class="material-icons keyboard_arrow_down"></span></button>';
|
||||
}
|
||||
html += '</div>';
|
||||
});
|
||||
|
@ -197,9 +197,9 @@ import 'emby-input';
|
|||
html += '</h3>';
|
||||
html += '</div>';
|
||||
if (i > 0) {
|
||||
html += `<button type="button" is="paper-icon-button-light" title="${globalize.translate('ButtonUp')}" class="btnSortableMoveUp btnSortable" data-pluginindex="${i}"><span class="material-icons keyboard_arrow_up"></span></button>`;
|
||||
html += `<button type="button" is="paper-icon-button-light" title="${globalize.translate('Up')}" class="btnSortableMoveUp btnSortable" data-pluginindex="${i}"><span class="material-icons keyboard_arrow_up"></span></button>`;
|
||||
} else if (plugins.length > 1) {
|
||||
html += `<button type="button" is="paper-icon-button-light" title="${globalize.translate('ButtonDown')}" class="btnSortableMoveDown btnSortable" data-pluginindex="${i}"><span class="material-icons keyboard_arrow_down"></span></button>`;
|
||||
html += `<button type="button" is="paper-icon-button-light" title="${globalize.translate('Down')}" class="btnSortableMoveDown btnSortable" data-pluginindex="${i}"><span class="material-icons keyboard_arrow_down"></span></button>`;
|
||||
}
|
||||
html += '</div>';
|
||||
}
|
||||
|
@ -236,9 +236,9 @@ import 'emby-input';
|
|||
html += '</h3>';
|
||||
html += '</div>';
|
||||
if (i > 0) {
|
||||
html += '<button type="button" is="paper-icon-button-light" title="' + globalize.translate('ButtonUp') + '" class="btnSortableMoveUp btnSortable" data-pluginindex="' + i + '"><span class="material-icons keyboard_arrow_up"></span></button>';
|
||||
html += '<button type="button" is="paper-icon-button-light" title="' + globalize.translate('Up') + '" class="btnSortableMoveUp btnSortable" data-pluginindex="' + i + '"><span class="material-icons keyboard_arrow_up"></span></button>';
|
||||
} else if (plugins.length > 1) {
|
||||
html += '<button type="button" is="paper-icon-button-light" title="' + globalize.translate('ButtonDown') + '" class="btnSortableMoveDown btnSortable" data-pluginindex="' + i + '"><span class="material-icons keyboard_arrow_down"></span></button>';
|
||||
html += '<button type="button" is="paper-icon-button-light" title="' + globalize.translate('Down') + '" class="btnSortableMoveDown btnSortable" data-pluginindex="' + i + '"><span class="material-icons keyboard_arrow_down"></span></button>';
|
||||
}
|
||||
html += '</div>';
|
||||
}
|
||||
|
@ -291,13 +291,13 @@ import 'emby-input';
|
|||
const btnSortable = elem.querySelector('.btnSortable');
|
||||
const inner = btnSortable.querySelector('.material-icons');
|
||||
if (elem.previousSibling) {
|
||||
btnSortable.title = globalize.translate('ButtonUp');
|
||||
btnSortable.title = globalize.translate('Up');
|
||||
btnSortable.classList.add('btnSortableMoveUp');
|
||||
btnSortable.classList.remove('btnSortableMoveDown');
|
||||
inner.classList.remove('keyboard_arrow_down');
|
||||
inner.classList.add('keyboard_arrow_up');
|
||||
} else {
|
||||
btnSortable.title = globalize.translate('ButtonDown');
|
||||
btnSortable.title = globalize.translate('Down');
|
||||
btnSortable.classList.remove('btnSortableMoveUp');
|
||||
btnSortable.classList.add('btnSortableMoveDown');
|
||||
inner.classList.remove('keyboard_arrow_up');
|
||||
|
|
|
@ -88,7 +88,7 @@
|
|||
<div class="checkboxContainer checkboxContainer-withDescription hide chkImportMissingEpisodesContainer advanced">
|
||||
<label>
|
||||
<input is="emby-checkbox" type="checkbox" id="chkImportMissingEpisodes" />
|
||||
<span>${LabelDisplayMissingEpisodesWithinSeasons}</span>
|
||||
<span>${DisplayMissingEpisodesWithinSeasons}</span>
|
||||
</label>
|
||||
<div class="fieldDescription checkboxFieldDescription">${ImportMissingEpisodesHelp}</div>
|
||||
</div>
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
|
||||
<div class="folders">
|
||||
<div style="display: flex; align-items: center;">
|
||||
<h1 style="margin: .5em 0;">${HeadersFolders}</h1>
|
||||
<h1 style="margin: .5em 0;">${Folders}</h1>
|
||||
<button is="emby-button" type="button" class="fab btnAddFolder submit" style="margin-left:1em;" title="${Add}">
|
||||
<span class="material-icons add"></span>
|
||||
</button>
|
||||
|
|
|
@ -76,7 +76,7 @@ import 'flexStyles';
|
|||
confirm({
|
||||
title: globalize.translate('HeaderRemoveMediaLocation'),
|
||||
text: globalize.translate('MessageConfirmRemoveMediaLocation'),
|
||||
confirmText: globalize.translate('ButtonDelete'),
|
||||
confirmText: globalize.translate('Delete'),
|
||||
primary: 'delete'
|
||||
}).then(() => {
|
||||
const refreshAfterChange = currentOptions.refresh;
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
|
||||
<div class="folders hide">
|
||||
<div style="display: flex; align-items: center;">
|
||||
<h1 style="margin: .5em 0;">${HeadersFolders}</h1>
|
||||
<h1 style="margin: .5em 0;">${Folders}</h1>
|
||||
<button is="emby-button" type="button" class="fab btnAddFolder submit" style="margin-left:1em;" title="${Add}">
|
||||
<span class="material-icons add"></span>
|
||||
</button>
|
||||
|
|
|
@ -9,7 +9,6 @@ import 'programStyles';
|
|||
import 'emby-button';
|
||||
|
||||
/* eslint-disable indent */
|
||||
|
||||
function getTimerIndicator(item) {
|
||||
let status;
|
||||
|
||||
|
@ -208,7 +207,7 @@ import 'emby-button';
|
|||
});
|
||||
} else if (item.IsSeries && !item.IsRepeat) {
|
||||
miscInfo.push({
|
||||
html: `<div class="mediaInfoProgramAttribute mediaInfoItem newTvProgram">${globalize.translate('AttributeNew')}</div>`
|
||||
html: `<div class="mediaInfoProgramAttribute mediaInfoItem newTvProgram">${globalize.translate('New')}</div>`
|
||||
});
|
||||
} else if (item.IsSeries && item.IsRepeat) {
|
||||
miscInfo.push({
|
||||
|
|
|
@ -198,7 +198,7 @@ import 'css!./multiSelect';
|
|||
|
||||
if (user.Policy.EnableContentDownloading && appHost.supports('filedownload')) {
|
||||
menuItems.push({
|
||||
name: globalize.translate('ButtonDownload'),
|
||||
name: globalize.translate('Download'),
|
||||
id: 'download',
|
||||
icon: 'file_download'
|
||||
});
|
||||
|
|
|
@ -1,134 +1,140 @@
|
|||
define(['appSettings', 'pluginManager'], function (appSettings, pluginManager) {
|
||||
'use strict';
|
||||
import appSettings from 'appSettings';
|
||||
import pluginManager from 'pluginManager';
|
||||
/* eslint-disable indent */
|
||||
|
||||
var settingsKey = 'installedpackages1';
|
||||
class PackageManager {
|
||||
#packagesList = [];
|
||||
#settingsKey = 'installedpackages1';
|
||||
|
||||
function addPackage(packageManager, pkg) {
|
||||
packageManager.packagesList = packageManager.packagesList.filter(function (p) {
|
||||
return p.name !== pkg.name;
|
||||
});
|
||||
init() {
|
||||
console.groupCollapsed('loading packages');
|
||||
var manifestUrls = JSON.parse(appSettings.get(this.#settingsKey) || '[]');
|
||||
|
||||
packageManager.packagesList.push(pkg);
|
||||
}
|
||||
return Promise.all(manifestUrls.map((url) => {
|
||||
return this.loadPackage(url);
|
||||
}))
|
||||
.then(() => {
|
||||
console.debug('finished loading packages');
|
||||
return Promise.resolve();
|
||||
})
|
||||
.catch(() => {
|
||||
return Promise.resolve();
|
||||
}).finally(() => {
|
||||
console.groupEnd('loading packages');
|
||||
});
|
||||
}
|
||||
|
||||
function removeUrl(url) {
|
||||
var manifestUrls = JSON.parse(appSettings.get(settingsKey) || '[]');
|
||||
get packages() {
|
||||
return this.#packagesList.slice(0);
|
||||
}
|
||||
|
||||
manifestUrls = manifestUrls.filter(function (i) {
|
||||
return i !== url;
|
||||
});
|
||||
install(url) {
|
||||
return this.loadPackage(url, true).then((pkg) => {
|
||||
var manifestUrls = JSON.parse(appSettings.get(this.#settingsKey) || '[]');
|
||||
|
||||
appSettings.set(settingsKey, JSON.stringify(manifestUrls));
|
||||
}
|
||||
|
||||
function loadPackage(packageManager, url, throwError) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
var xhr = new XMLHttpRequest();
|
||||
var originalUrl = url;
|
||||
url += url.indexOf('?') === -1 ? '?' : '&';
|
||||
url += 't=' + new Date().getTime();
|
||||
|
||||
xhr.open('GET', url, true);
|
||||
|
||||
var onError = function () {
|
||||
if (throwError === true) {
|
||||
reject();
|
||||
} else {
|
||||
removeUrl(originalUrl);
|
||||
resolve();
|
||||
if (!manifestUrls.includes(url)) {
|
||||
manifestUrls.push(url);
|
||||
appSettings.set(this.#settingsKey, JSON.stringify(manifestUrls));
|
||||
}
|
||||
};
|
||||
|
||||
xhr.onload = function (e) {
|
||||
if (this.status < 400) {
|
||||
var pkg = JSON.parse(this.response);
|
||||
pkg.url = originalUrl;
|
||||
return pkg;
|
||||
});
|
||||
}
|
||||
|
||||
addPackage(packageManager, pkg);
|
||||
uninstall(name) {
|
||||
var pkg = this.#packagesList.filter((p) => {
|
||||
return p.name === name;
|
||||
})[0];
|
||||
|
||||
var plugins = pkg.plugins || [];
|
||||
if (pkg.plugin) {
|
||||
plugins.push(pkg.plugin);
|
||||
}
|
||||
var promises = plugins.map(function (pluginUrl) {
|
||||
return pluginManager.loadPlugin(packageManager.mapPath(pkg, pluginUrl));
|
||||
});
|
||||
Promise.all(promises).then(resolve, resolve);
|
||||
} else {
|
||||
onError();
|
||||
}
|
||||
};
|
||||
if (pkg) {
|
||||
this.#packagesList = this.#packagesList.filter((p) => {
|
||||
return p.name !== name;
|
||||
});
|
||||
|
||||
xhr.onerror = onError;
|
||||
|
||||
xhr.send();
|
||||
});
|
||||
}
|
||||
|
||||
function PackageManager() {
|
||||
this.packagesList = [];
|
||||
}
|
||||
|
||||
PackageManager.prototype.init = function () {
|
||||
var manifestUrls = JSON.parse(appSettings.get(settingsKey) || '[]');
|
||||
|
||||
var instance = this;
|
||||
return Promise.all(manifestUrls.map(function (u) {
|
||||
return loadPackage(instance, u);
|
||||
})).then(function () {
|
||||
return Promise.resolve();
|
||||
}, function () {
|
||||
return Promise.resolve();
|
||||
});
|
||||
};
|
||||
|
||||
PackageManager.prototype.packages = function () {
|
||||
return this.packagesList.slice(0);
|
||||
};
|
||||
|
||||
PackageManager.prototype.install = function (url) {
|
||||
return loadPackage(this, url, true).then(function (pkg) {
|
||||
var manifestUrls = JSON.parse(appSettings.get(settingsKey) || '[]');
|
||||
|
||||
if (manifestUrls.indexOf(url) === -1) {
|
||||
manifestUrls.push(url);
|
||||
appSettings.set(settingsKey, JSON.stringify(manifestUrls));
|
||||
this.removeUrl(pkg.url);
|
||||
}
|
||||
|
||||
return pkg;
|
||||
});
|
||||
};
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
PackageManager.prototype.uninstall = function (name) {
|
||||
var pkg = this.packagesList.filter(function (p) {
|
||||
return p.name === name;
|
||||
})[0];
|
||||
mapPath(pkg, pluginUrl) {
|
||||
var urlLower = pluginUrl.toLowerCase();
|
||||
if (urlLower.startsWith('http:') || urlLower.startsWith('https:') || urlLower.startsWith('file:')) {
|
||||
return pluginUrl;
|
||||
}
|
||||
|
||||
if (pkg) {
|
||||
this.packagesList = this.packagesList.filter(function (p) {
|
||||
return p.name !== name;
|
||||
var packageUrl = pkg.url;
|
||||
packageUrl = packageUrl.substring(0, packageUrl.lastIndexOf('/'));
|
||||
|
||||
packageUrl += '/';
|
||||
packageUrl += pluginUrl;
|
||||
|
||||
return packageUrl;
|
||||
}
|
||||
|
||||
addPackage(pkg) {
|
||||
this.#packagesList = this.#packagesList.filter((p) => {
|
||||
return p.name !== pkg.name;
|
||||
});
|
||||
|
||||
removeUrl(pkg.url);
|
||||
this.#packagesList.push(pkg);
|
||||
}
|
||||
|
||||
return Promise.resolve();
|
||||
};
|
||||
removeUrl(url) {
|
||||
var manifestUrls = JSON.parse(appSettings.get(this.#settingsKey) || '[]');
|
||||
|
||||
PackageManager.prototype.mapPath = function (pkg, pluginUrl) {
|
||||
var urlLower = pluginUrl.toLowerCase();
|
||||
if (urlLower.indexOf('http:') === 0 || urlLower.indexOf('https:') === 0 || urlLower.indexOf('file:') === 0) {
|
||||
return pluginUrl;
|
||||
manifestUrls = manifestUrls.filter((i) => {
|
||||
return i !== url;
|
||||
});
|
||||
|
||||
appSettings.set(this.#settingsKey, JSON.stringify(manifestUrls));
|
||||
}
|
||||
|
||||
var packageUrl = pkg.url;
|
||||
packageUrl = packageUrl.substring(0, packageUrl.lastIndexOf('/'));
|
||||
loadPackage(url, throwError = false) {
|
||||
return new Promise((resolve, reject) => {
|
||||
var xhr = new XMLHttpRequest();
|
||||
var originalUrl = url;
|
||||
url += url.indexOf('?') === -1 ? '?' : '&';
|
||||
url += 't=' + new Date().getTime();
|
||||
|
||||
packageUrl += '/';
|
||||
packageUrl += pluginUrl;
|
||||
xhr.open('GET', url, true);
|
||||
|
||||
return packageUrl;
|
||||
};
|
||||
var onError = () => {
|
||||
if (throwError === true) {
|
||||
reject();
|
||||
} else {
|
||||
this.removeUrl(originalUrl);
|
||||
resolve();
|
||||
}
|
||||
};
|
||||
|
||||
return new PackageManager();
|
||||
});
|
||||
xhr.onload = () => {
|
||||
if (this.status < 400) {
|
||||
var pkg = JSON.parse(this.response);
|
||||
pkg.url = originalUrl;
|
||||
|
||||
this.addPackage(pkg);
|
||||
|
||||
var plugins = pkg.plugins || [];
|
||||
if (pkg.plugin) {
|
||||
plugins.push(pkg.plugin);
|
||||
}
|
||||
var promises = plugins.map((pluginUrl) => {
|
||||
return pluginManager.loadPlugin(this.mapPath(pkg, pluginUrl));
|
||||
});
|
||||
Promise.all(promises).then(resolve, resolve);
|
||||
} else {
|
||||
onError();
|
||||
}
|
||||
};
|
||||
|
||||
xhr.onerror = onError;
|
||||
|
||||
xhr.send();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/* eslint-enable indent */
|
||||
|
||||
export default new PackageManager();
|
||||
|
|
|
@ -1112,6 +1112,52 @@ class PlaybackManager {
|
|||
}
|
||||
};
|
||||
|
||||
self.increasePlaybackRate = function (player) {
|
||||
player = player || self._currentPlayer;
|
||||
if (player) {
|
||||
let current = self.getPlaybackRate(player);
|
||||
let supported = self.getSupportedPlaybackRates(player);
|
||||
|
||||
let index = -1;
|
||||
for (let i = 0, length = supported.length; i < length; i++) {
|
||||
if (supported[i].id === current) {
|
||||
index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
index = Math.min(index + 1, supported.length - 1);
|
||||
self.setPlaybackRate(supported[index].id, player);
|
||||
}
|
||||
};
|
||||
|
||||
self.decreasePlaybackRate = function (player) {
|
||||
player = player || self._currentPlayer;
|
||||
if (player) {
|
||||
let current = self.getPlaybackRate(player);
|
||||
let supported = self.getSupportedPlaybackRates(player);
|
||||
|
||||
let index = -1;
|
||||
for (let i = 0, length = supported.length; i < length; i++) {
|
||||
if (supported[i].id === current) {
|
||||
index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
index = Math.max(index - 1, 0);
|
||||
self.setPlaybackRate(supported[index].id, player);
|
||||
}
|
||||
};
|
||||
|
||||
self.getSupportedPlaybackRates = function (player) {
|
||||
player = player || self._currentPlayer;
|
||||
if (player && player.getSupportedPlaybackRates) {
|
||||
return player.getSupportedPlaybackRates();
|
||||
}
|
||||
return [];
|
||||
};
|
||||
|
||||
let brightnessOsdLoaded;
|
||||
self.setBrightness = function (val, player) {
|
||||
player = player || self._currentPlayer;
|
||||
|
@ -1416,8 +1462,8 @@ class PlaybackManager {
|
|||
|
||||
self.toggleFullscreen = function (player) {
|
||||
player = player || self._currentPlayer;
|
||||
if (!player.isLocalPlayer || player.toggleFulscreen) {
|
||||
return player.toggleFulscreen();
|
||||
if (!player.isLocalPlayer || player.toggleFullscreen) {
|
||||
return player.toggleFullscreen();
|
||||
}
|
||||
|
||||
if (screenfull.isEnabled) {
|
||||
|
@ -3697,6 +3743,9 @@ class PlaybackManager {
|
|||
case 'SetAspectRatio':
|
||||
this.setAspectRatio(cmd.Arguments.AspectRatio, player);
|
||||
break;
|
||||
case 'PlaybackRate':
|
||||
this.setPlaybackRate(cmd.Arguments.PlaybackRate, player);
|
||||
break;
|
||||
case 'SetBrightness':
|
||||
this.setBrightness(cmd.Arguments.Brightness, player);
|
||||
break;
|
||||
|
|
|
@ -149,6 +149,28 @@ function showAspectRatioMenu(player, btn) {
|
|||
});
|
||||
}
|
||||
|
||||
function showPlaybackRateMenu(player, btn) {
|
||||
// each has a name and id
|
||||
const currentId = playbackManager.getPlaybackRate(player);
|
||||
const menuItems = playbackManager.getSupportedPlaybackRates(player).map(i => ({
|
||||
id: i.id,
|
||||
name: i.name,
|
||||
selected: i.id === currentId
|
||||
}));
|
||||
|
||||
return actionsheet.show({
|
||||
items: menuItems,
|
||||
positionTo: btn
|
||||
}).then(function (id) {
|
||||
if (id) {
|
||||
playbackManager.setPlaybackRate(id, player);
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
return Promise.reject();
|
||||
});
|
||||
}
|
||||
|
||||
function showWithUser(options, player, user) {
|
||||
var supportedCommands = playbackManager.getSupportedCommands(player);
|
||||
|
||||
|
@ -166,6 +188,17 @@ function showWithUser(options, player, user) {
|
|||
});
|
||||
}
|
||||
|
||||
if (supportedCommands.indexOf('PlaybackRate') !== -1) {
|
||||
const currentPlaybackRateId = playbackManager.getPlaybackRate(player);
|
||||
const currentPlaybackRate = playbackManager.getSupportedPlaybackRates(player).filter(i => i.id === currentPlaybackRateId)[0];
|
||||
|
||||
menuItems.push({
|
||||
name: globalize.translate('PlaybackRate'),
|
||||
id: 'playbackrate',
|
||||
asideText: currentPlaybackRate ? currentPlaybackRate.name : null
|
||||
});
|
||||
}
|
||||
|
||||
if (user && user.Policy.EnableVideoPlaybackTranscoding) {
|
||||
var secondaryQualityText = getQualitySecondaryText(player);
|
||||
|
||||
|
@ -230,6 +263,8 @@ function handleSelectedOption(id, options, player) {
|
|||
return showQualityMenu(player, options.positionTo);
|
||||
case 'aspectratio':
|
||||
return showAspectRatioMenu(player, options.positionTo);
|
||||
case 'playbackrate':
|
||||
return showPlaybackRateMenu(player, options.positionTo);
|
||||
case 'repeatmode':
|
||||
return showRepeatModeMenu(player, options.positionTo);
|
||||
case 'stats':
|
||||
|
|
|
@ -1,37 +1,38 @@
|
|||
define(['events', 'globalize'], function (events, globalize) {
|
||||
'use strict';
|
||||
import events from 'events';
|
||||
import globalize from 'globalize';
|
||||
/* eslint-disable indent */
|
||||
|
||||
// TODO: replace with each plugin version
|
||||
var cacheParam = new Date().getTime();
|
||||
|
||||
function loadStrings(plugin) {
|
||||
var strings = plugin.getTranslations ? plugin.getTranslations() : [];
|
||||
return globalize.loadStrings({
|
||||
name: plugin.id || plugin.packageName,
|
||||
strings: strings
|
||||
});
|
||||
}
|
||||
class PluginManager {
|
||||
pluginsList = [];
|
||||
|
||||
function definePluginRoute(pluginManager, route, plugin) {
|
||||
route.contentPath = pluginManager.mapPath(plugin, route.path);
|
||||
route.path = pluginManager.mapRoute(plugin, route);
|
||||
get plugins() {
|
||||
return this.pluginsList;
|
||||
}
|
||||
|
||||
Emby.App.defineRoute(route, plugin.id);
|
||||
}
|
||||
#loadStrings(plugin) {
|
||||
var strings = plugin.getTranslations ? plugin.getTranslations() : [];
|
||||
return globalize.loadStrings({
|
||||
name: plugin.id || plugin.packageName,
|
||||
strings: strings
|
||||
});
|
||||
}
|
||||
|
||||
function PluginManager() {
|
||||
this.pluginsList = [];
|
||||
}
|
||||
#definePluginRoute(route, plugin) {
|
||||
route.contentPath = this.mapPath(plugin, route.path);
|
||||
route.path = this.#mapRoute(plugin, route);
|
||||
|
||||
PluginManager.prototype.loadPlugin = function(pluginSpec) {
|
||||
var instance = this;
|
||||
Emby.App.defineRoute(route, plugin.id);
|
||||
}
|
||||
|
||||
function registerPlugin(plugin) {
|
||||
instance.register(plugin);
|
||||
#registerPlugin(plugin) {
|
||||
this.#register(plugin);
|
||||
|
||||
if (plugin.getRoutes) {
|
||||
plugin.getRoutes().forEach(function (route) {
|
||||
definePluginRoute(instance, route, plugin);
|
||||
plugin.getRoutes().forEach((route) => {
|
||||
this.#definePluginRoute(route, plugin);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -40,7 +41,7 @@ define(['events', 'globalize'], function (events, globalize) {
|
|||
return Promise.resolve(plugin);
|
||||
} else {
|
||||
return new Promise((resolve, reject) => {
|
||||
loadStrings(plugin)
|
||||
this.#loadStrings(plugin)
|
||||
.then(function () {
|
||||
resolve(plugin);
|
||||
})
|
||||
|
@ -49,103 +50,102 @@ define(['events', 'globalize'], function (events, globalize) {
|
|||
}
|
||||
}
|
||||
|
||||
if (typeof pluginSpec === 'string') {
|
||||
console.debug('Loading plugin (via deprecated requirejs method): ' + pluginSpec);
|
||||
loadPlugin(pluginSpec) {
|
||||
if (typeof pluginSpec === 'string') {
|
||||
console.debug('Loading plugin (via deprecated requirejs method): ' + pluginSpec);
|
||||
|
||||
return new Promise(function (resolve, reject) {
|
||||
require([pluginSpec], (pluginFactory) => {
|
||||
var plugin = pluginFactory.default ? new pluginFactory.default() : new pluginFactory();
|
||||
return new Promise((resolve, reject) => {
|
||||
require([pluginSpec], (pluginFactory) => {
|
||||
var plugin = pluginFactory.default ? new pluginFactory.default() : new pluginFactory();
|
||||
|
||||
// See if it's already installed
|
||||
var existing = instance.pluginsList.filter(function (p) {
|
||||
return p.id === plugin.id;
|
||||
})[0];
|
||||
// See if it's already installed
|
||||
var existing = this.pluginsList.filter(function (p) {
|
||||
return p.id === plugin.id;
|
||||
})[0];
|
||||
|
||||
if (existing) {
|
||||
resolve(pluginSpec);
|
||||
}
|
||||
if (existing) {
|
||||
resolve(pluginSpec);
|
||||
}
|
||||
|
||||
plugin.installUrl = pluginSpec;
|
||||
plugin.installUrl = pluginSpec;
|
||||
|
||||
var separatorIndex = Math.max(pluginSpec.lastIndexOf('/'), pluginSpec.lastIndexOf('\\'));
|
||||
plugin.baseUrl = pluginSpec.substring(0, separatorIndex);
|
||||
var separatorIndex = Math.max(pluginSpec.lastIndexOf('/'), pluginSpec.lastIndexOf('\\'));
|
||||
plugin.baseUrl = pluginSpec.substring(0, separatorIndex);
|
||||
|
||||
var paths = {};
|
||||
paths[plugin.id] = plugin.baseUrl;
|
||||
var paths = {};
|
||||
paths[plugin.id] = plugin.baseUrl;
|
||||
|
||||
requirejs.config({
|
||||
waitSeconds: 0,
|
||||
paths: paths
|
||||
requirejs.config({
|
||||
waitSeconds: 0,
|
||||
paths: paths
|
||||
});
|
||||
|
||||
this.#registerPlugin(plugin).then(resolve).catch(reject);
|
||||
});
|
||||
|
||||
registerPlugin(plugin).then(resolve).catch(reject);
|
||||
});
|
||||
} else if (pluginSpec.then) {
|
||||
return pluginSpec.then(pluginBuilder => {
|
||||
return pluginBuilder();
|
||||
}).then((plugin) => {
|
||||
console.debug(`Plugin loaded: ${plugin.id}`);
|
||||
return this.#registerPlugin(plugin);
|
||||
});
|
||||
} else {
|
||||
const err = new TypeError('Plugins have to be a Promise that resolves to a plugin builder function or a RequireJS url (deprecated)');
|
||||
console.error(err);
|
||||
return Promise.reject(err);
|
||||
}
|
||||
}
|
||||
|
||||
// In lieu of automatic discovery, plugins will register dynamic objects
|
||||
// Each object will have the following properties:
|
||||
// name
|
||||
// type (skin, screensaver, etc)
|
||||
#register(obj) {
|
||||
this.pluginsList.push(obj);
|
||||
events.trigger(this, 'registered', [obj]);
|
||||
}
|
||||
|
||||
ofType(type) {
|
||||
return this.pluginsList.filter((o) => {
|
||||
return o.type === type;
|
||||
});
|
||||
} else if (pluginSpec.then) {
|
||||
return pluginSpec.then(pluginBuilder => {
|
||||
return pluginBuilder();
|
||||
}).then(plugin => {
|
||||
console.debug(`Plugin loaded: ${plugin.id}`);
|
||||
return registerPlugin(plugin);
|
||||
});
|
||||
} else {
|
||||
const err = new Error('Plugins have to be a Promise that resolves to a plugin builder function or a requirejs urls (deprecated)');
|
||||
console.error(err);
|
||||
return Promise.reject(err);
|
||||
}
|
||||
};
|
||||
|
||||
// In lieu of automatic discovery, plugins will register dynamic objects
|
||||
// Each object will have the following properties:
|
||||
// name
|
||||
// type (skin, screensaver, etc)
|
||||
PluginManager.prototype.register = function (obj) {
|
||||
this.pluginsList.push(obj);
|
||||
events.trigger(this, 'registered', [obj]);
|
||||
};
|
||||
|
||||
PluginManager.prototype.ofType = function (type) {
|
||||
return this.pluginsList.filter(function (o) {
|
||||
return o.type === type;
|
||||
});
|
||||
};
|
||||
|
||||
PluginManager.prototype.plugins = function () {
|
||||
return this.pluginsList;
|
||||
};
|
||||
|
||||
PluginManager.prototype.mapRoute = function (plugin, route) {
|
||||
if (typeof plugin === 'string') {
|
||||
plugin = this.pluginsList.filter(function (p) {
|
||||
return (p.id || p.packageName) === plugin;
|
||||
})[0];
|
||||
}
|
||||
|
||||
route = route.path || route;
|
||||
#mapRoute(plugin, route) {
|
||||
if (typeof plugin === 'string') {
|
||||
plugin = this.pluginsList.filter((p) => {
|
||||
return (p.id || p.packageName) === plugin;
|
||||
})[0];
|
||||
}
|
||||
|
||||
if (route.toLowerCase().indexOf('http') === 0) {
|
||||
return route;
|
||||
route = route.path || route;
|
||||
|
||||
if (route.toLowerCase().startsWith('http')) {
|
||||
return route;
|
||||
}
|
||||
|
||||
return '/plugins/' + plugin.id + '/' + route;
|
||||
}
|
||||
|
||||
return '/plugins/' + plugin.id + '/' + route;
|
||||
};
|
||||
mapPath(plugin, path, addCacheParam) {
|
||||
if (typeof plugin === 'string') {
|
||||
plugin = this.pluginsList.filter((p) => {
|
||||
return (p.id || p.packageName) === plugin;
|
||||
})[0];
|
||||
}
|
||||
|
||||
PluginManager.prototype.mapPath = function (plugin, path, addCacheParam) {
|
||||
if (typeof plugin === 'string') {
|
||||
plugin = this.pluginsList.filter(function (p) {
|
||||
return (p.id || p.packageName) === plugin;
|
||||
})[0];
|
||||
var url = plugin.baseUrl + '/' + path;
|
||||
|
||||
if (addCacheParam) {
|
||||
url += url.includes('?') ? '&' : '?';
|
||||
url += 'v=' + cacheParam;
|
||||
}
|
||||
|
||||
return url;
|
||||
}
|
||||
}
|
||||
|
||||
var url = plugin.baseUrl + '/' + path;
|
||||
/* eslint-enable indent */
|
||||
|
||||
if (addCacheParam) {
|
||||
url += url.indexOf('?') === -1 ? '?' : '&';
|
||||
url += 'v=' + cacheParam;
|
||||
}
|
||||
|
||||
return url;
|
||||
};
|
||||
|
||||
return new PluginManager();
|
||||
});
|
||||
export default new PluginManager();
|
||||
|
|
|
@ -118,7 +118,7 @@ function reload(context, programId, serverId, refreshRecordingStateOnly) {
|
|||
|
||||
function executeCloseAction(action, programId, serverId) {
|
||||
if (action === 'play') {
|
||||
import('playbackManager').then(({default: playbackManager}) => {
|
||||
import('playbackManager').then(({ default: playbackManager }) => {
|
||||
const apiClient = connectionManager.getApiClient(serverId);
|
||||
|
||||
apiClient.getLiveTvProgram(programId, apiClient.getCurrentUserId()).then(function (item) {
|
||||
|
@ -138,7 +138,7 @@ function showEditor(itemId, serverId) {
|
|||
|
||||
loading.show();
|
||||
|
||||
import('text!./recordingcreator.template.html').then(({default: template}) => {
|
||||
import('text!./recordingcreator.template.html').then(({ default: template }) => {
|
||||
const dialogOptions = {
|
||||
removeOnClose: true,
|
||||
scrollY: false
|
||||
|
|
|
@ -1,151 +1,155 @@
|
|||
define(['dialogHelper', 'globalize', 'layoutManager', 'mediaInfo', 'apphost', 'connectionManager', 'require', 'loading', 'scrollHelper', 'imageLoader', 'scrollStyles', 'emby-button', 'emby-collapse', 'emby-input', 'paper-icon-button-light', 'css!./../formdialog', 'css!./recordingcreator', 'material-icons', 'flexStyles'], function (dialogHelper, globalize, layoutManager, mediaInfo, appHost, connectionManager, require, loading, scrollHelper, imageLoader) {
|
||||
'use strict';
|
||||
import dialogHelper from 'dialogHelper';
|
||||
import globalize from 'globalize';
|
||||
import layoutManager from 'layoutManager';
|
||||
import connectionManager from 'connectionManager';
|
||||
import loading from 'loading';
|
||||
import scrollHelper from 'scrollHelper';
|
||||
import 'scrollStyles';
|
||||
import 'emby-button';
|
||||
import 'emby-collapse';
|
||||
import 'emby-input';
|
||||
import 'paper-icon-button-light';
|
||||
import 'css!./../formdialog';
|
||||
import 'css!./recordingcreator';
|
||||
import 'material-icons';
|
||||
import 'flexStyles';
|
||||
|
||||
scrollHelper = scrollHelper.default || scrollHelper;
|
||||
loading = loading.default || loading;
|
||||
layoutManager = layoutManager.default || layoutManager;
|
||||
let currentDialog;
|
||||
let recordingDeleted = false;
|
||||
let currentItemId;
|
||||
let currentServerId;
|
||||
let currentResolve;
|
||||
|
||||
var currentDialog;
|
||||
var recordingDeleted = false;
|
||||
var currentItemId;
|
||||
var currentServerId;
|
||||
var currentResolve;
|
||||
function deleteTimer(apiClient, timerId) {
|
||||
return import('recordingHelper').then(({ default: recordingHelper }) => {
|
||||
recordingHelper.cancelTimerWithConfirmation(timerId, apiClient.serverId());
|
||||
});
|
||||
}
|
||||
|
||||
function deleteTimer(apiClient, timerId) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
require(['recordingHelper'], function (recordingHelper) {
|
||||
recordingHelper = recordingHelper.default || recordingHelper;
|
||||
function renderTimer(context, item, apiClient) {
|
||||
context.querySelector('#txtPrePaddingMinutes').value = item.PrePaddingSeconds / 60;
|
||||
context.querySelector('#txtPostPaddingMinutes').value = item.PostPaddingSeconds / 60;
|
||||
|
||||
recordingHelper.cancelTimerWithConfirmation(timerId, apiClient.serverId()).then(resolve, reject);
|
||||
});
|
||||
loading.hide();
|
||||
}
|
||||
|
||||
function closeDialog(isDeleted) {
|
||||
recordingDeleted = isDeleted;
|
||||
dialogHelper.close(currentDialog);
|
||||
}
|
||||
|
||||
function onSubmit(e) {
|
||||
const form = this;
|
||||
|
||||
const apiClient = connectionManager.getApiClient(currentServerId);
|
||||
|
||||
apiClient.getLiveTvTimer(currentItemId).then(function (item) {
|
||||
item.PrePaddingSeconds = form.querySelector('#txtPrePaddingMinutes').value * 60;
|
||||
item.PostPaddingSeconds = form.querySelector('#txtPostPaddingMinutes').value * 60;
|
||||
apiClient.updateLiveTvTimer(item).then(currentResolve);
|
||||
});
|
||||
|
||||
e.preventDefault();
|
||||
|
||||
// Disable default form submission
|
||||
return false;
|
||||
}
|
||||
|
||||
function init(context) {
|
||||
context.querySelector('.btnCancel').addEventListener('click', function () {
|
||||
closeDialog(false);
|
||||
});
|
||||
|
||||
context.querySelector('.btnCancelRecording').addEventListener('click', function () {
|
||||
const apiClient = connectionManager.getApiClient(currentServerId);
|
||||
|
||||
deleteTimer(apiClient, currentItemId).then(function () {
|
||||
closeDialog(true);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
function renderTimer(context, item, apiClient) {
|
||||
context.querySelector('#txtPrePaddingMinutes').value = item.PrePaddingSeconds / 60;
|
||||
context.querySelector('#txtPostPaddingMinutes').value = item.PostPaddingSeconds / 60;
|
||||
context.querySelector('form').addEventListener('submit', onSubmit);
|
||||
}
|
||||
|
||||
function reload(context, id) {
|
||||
loading.show();
|
||||
currentItemId = id;
|
||||
|
||||
const apiClient = connectionManager.getApiClient(currentServerId);
|
||||
apiClient.getLiveTvTimer(id).then(function (result) {
|
||||
renderTimer(context, result, apiClient);
|
||||
loading.hide();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function closeDialog(isDeleted) {
|
||||
recordingDeleted = isDeleted;
|
||||
|
||||
dialogHelper.close(currentDialog);
|
||||
}
|
||||
|
||||
function onSubmit(e) {
|
||||
var form = this;
|
||||
|
||||
var apiClient = connectionManager.getApiClient(currentServerId);
|
||||
|
||||
apiClient.getLiveTvTimer(currentItemId).then(function (item) {
|
||||
item.PrePaddingSeconds = form.querySelector('#txtPrePaddingMinutes').value * 60;
|
||||
item.PostPaddingSeconds = form.querySelector('#txtPostPaddingMinutes').value * 60;
|
||||
apiClient.updateLiveTvTimer(item).then(currentResolve);
|
||||
});
|
||||
|
||||
e.preventDefault();
|
||||
|
||||
// Disable default form submission
|
||||
return false;
|
||||
}
|
||||
|
||||
function init(context) {
|
||||
context.querySelector('.btnCancel').addEventListener('click', function () {
|
||||
closeDialog(false);
|
||||
});
|
||||
|
||||
context.querySelector('.btnCancelRecording').addEventListener('click', function () {
|
||||
var apiClient = connectionManager.getApiClient(currentServerId);
|
||||
deleteTimer(apiClient, currentItemId).then(function () {
|
||||
closeDialog(true);
|
||||
});
|
||||
});
|
||||
|
||||
context.querySelector('form').addEventListener('submit', onSubmit);
|
||||
}
|
||||
|
||||
function reload(context, id) {
|
||||
function showEditor(itemId, serverId, options) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
recordingDeleted = false;
|
||||
currentServerId = serverId;
|
||||
loading.show();
|
||||
currentItemId = id;
|
||||
options = options || {};
|
||||
currentResolve = resolve;
|
||||
|
||||
var apiClient = connectionManager.getApiClient(currentServerId);
|
||||
apiClient.getLiveTvTimer(id).then(function (result) {
|
||||
renderTimer(context, result, apiClient);
|
||||
loading.hide();
|
||||
});
|
||||
}
|
||||
import('text!./recordingeditor.template.html').then(({default: template}) => {
|
||||
const dialogOptions = {
|
||||
removeOnClose: true,
|
||||
scrollY: false
|
||||
};
|
||||
|
||||
function showEditor(itemId, serverId, options) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
recordingDeleted = false;
|
||||
currentServerId = serverId;
|
||||
loading.show();
|
||||
options = options || {};
|
||||
currentResolve = resolve;
|
||||
if (layoutManager.tv) {
|
||||
dialogOptions.size = 'fullscreen';
|
||||
}
|
||||
|
||||
require(['text!./recordingeditor.template.html'], function (template) {
|
||||
var dialogOptions = {
|
||||
removeOnClose: true,
|
||||
scrollY: false
|
||||
};
|
||||
const dlg = dialogHelper.createDialog(dialogOptions);
|
||||
|
||||
if (layoutManager.tv) {
|
||||
dialogOptions.size = 'fullscreen';
|
||||
dlg.classList.add('formDialog');
|
||||
dlg.classList.add('recordingDialog');
|
||||
|
||||
if (!layoutManager.tv) {
|
||||
dlg.style['min-width'] = '20%';
|
||||
dlg.classList.add('dialog-fullscreen-lowres');
|
||||
}
|
||||
|
||||
let html = '';
|
||||
|
||||
html += globalize.translateHtml(template, 'core');
|
||||
|
||||
dlg.innerHTML = html;
|
||||
|
||||
if (options.enableCancel === false) {
|
||||
dlg.querySelector('.formDialogFooter').classList.add('hide');
|
||||
}
|
||||
|
||||
currentDialog = dlg;
|
||||
|
||||
dlg.addEventListener('closing', function () {
|
||||
if (!recordingDeleted) {
|
||||
dlg.querySelector('.btnSubmit').click();
|
||||
}
|
||||
|
||||
var dlg = dialogHelper.createDialog(dialogOptions);
|
||||
|
||||
dlg.classList.add('formDialog');
|
||||
dlg.classList.add('recordingDialog');
|
||||
|
||||
if (!layoutManager.tv) {
|
||||
dlg.style['min-width'] = '20%';
|
||||
dlg.classList.add('dialog-fullscreen-lowres');
|
||||
}
|
||||
|
||||
var html = '';
|
||||
|
||||
html += globalize.translateHtml(template, 'core');
|
||||
|
||||
dlg.innerHTML = html;
|
||||
|
||||
if (options.enableCancel === false) {
|
||||
dlg.querySelector('.formDialogFooter').classList.add('hide');
|
||||
}
|
||||
|
||||
currentDialog = dlg;
|
||||
|
||||
dlg.addEventListener('closing', function () {
|
||||
if (!recordingDeleted) {
|
||||
dlg.querySelector('.btnSubmit').click();
|
||||
}
|
||||
});
|
||||
|
||||
dlg.addEventListener('close', function () {
|
||||
if (recordingDeleted) {
|
||||
resolve({
|
||||
updated: true,
|
||||
deleted: true
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
if (layoutManager.tv) {
|
||||
scrollHelper.centerFocus.on(dlg.querySelector('.formDialogContent'), false);
|
||||
}
|
||||
|
||||
init(dlg);
|
||||
|
||||
reload(dlg, itemId);
|
||||
|
||||
dialogHelper.open(dlg);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
show: showEditor
|
||||
};
|
||||
});
|
||||
dlg.addEventListener('close', function () {
|
||||
if (recordingDeleted) {
|
||||
resolve({
|
||||
updated: true,
|
||||
deleted: true
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
if (layoutManager.tv) {
|
||||
scrollHelper.centerFocus.on(dlg.querySelector('.formDialogContent'), false);
|
||||
}
|
||||
|
||||
init(dlg);
|
||||
|
||||
reload(dlg, itemId);
|
||||
|
||||
dialogHelper.open(dlg);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
export default {
|
||||
show: showEditor
|
||||
};
|
||||
|
|
|
@ -1,223 +1,126 @@
|
|||
define(['globalize', 'connectionManager', 'serverNotifications', 'require', 'loading', 'apphost', 'dom', 'recordingHelper', 'events', 'paper-icon-button-light', 'emby-button', 'css!./recordingfields', 'flexStyles'], function (globalize, connectionManager, serverNotifications, require, loading, appHost, dom, recordingHelper, events) {
|
||||
'use strict';
|
||||
import globalize from 'globalize';
|
||||
import connectionManager from 'connectionManager';
|
||||
import serverNotifications from 'serverNotifications';
|
||||
import loading from 'loading';
|
||||
import dom from 'dom';
|
||||
import recordingHelper from 'recordingHelper';
|
||||
import events from 'events';
|
||||
import 'paper-icon-button-light';
|
||||
import 'emby-button';
|
||||
import 'css!./recordingfields';
|
||||
import 'flexStyles';
|
||||
|
||||
serverNotifications = serverNotifications.default || serverNotifications;
|
||||
recordingHelper = recordingHelper.default || recordingHelper;
|
||||
loading = loading.default || loading;
|
||||
/*eslint prefer-const: "error"*/
|
||||
|
||||
function loadData(parent, program, apiClient) {
|
||||
if (program.IsSeries) {
|
||||
parent.querySelector('.recordSeriesContainer').classList.remove('hide');
|
||||
function loadData(parent, program, apiClient) {
|
||||
if (program.IsSeries) {
|
||||
parent.querySelector('.recordSeriesContainer').classList.remove('hide');
|
||||
} else {
|
||||
parent.querySelector('.recordSeriesContainer').classList.add('hide');
|
||||
}
|
||||
|
||||
if (program.SeriesTimerId) {
|
||||
parent.querySelector('.btnManageSeriesRecording').classList.remove('hide');
|
||||
parent.querySelector('.seriesRecordingButton .recordingIcon').classList.add('recordingIcon-active');
|
||||
parent.querySelector('.seriesRecordingButton .buttonText').innerHTML = globalize.translate('CancelSeries');
|
||||
} else {
|
||||
parent.querySelector('.btnManageSeriesRecording').classList.add('hide');
|
||||
parent.querySelector('.seriesRecordingButton .recordingIcon').classList.remove('recordingIcon-active');
|
||||
parent.querySelector('.seriesRecordingButton .buttonText').innerHTML = globalize.translate('RecordSeries');
|
||||
}
|
||||
|
||||
if (program.TimerId && program.Status !== 'Cancelled') {
|
||||
parent.querySelector('.btnManageRecording').classList.remove('hide');
|
||||
parent.querySelector('.singleRecordingButton .recordingIcon').classList.add('recordingIcon-active');
|
||||
if (program.Status === 'InProgress') {
|
||||
parent.querySelector('.singleRecordingButton .buttonText').innerHTML = globalize.translate('StopRecording');
|
||||
} else {
|
||||
parent.querySelector('.recordSeriesContainer').classList.add('hide');
|
||||
parent.querySelector('.singleRecordingButton .buttonText').innerHTML = globalize.translate('DoNotRecord');
|
||||
}
|
||||
} else {
|
||||
parent.querySelector('.btnManageRecording').classList.add('hide');
|
||||
parent.querySelector('.singleRecordingButton .recordingIcon').classList.remove('recordingIcon-active');
|
||||
parent.querySelector('.singleRecordingButton .buttonText').innerHTML = globalize.translate('Record');
|
||||
}
|
||||
}
|
||||
|
||||
if (program.SeriesTimerId) {
|
||||
parent.querySelector('.btnManageSeriesRecording').classList.remove('hide');
|
||||
parent.querySelector('.seriesRecordingButton .recordingIcon').classList.add('recordingIcon-active');
|
||||
parent.querySelector('.seriesRecordingButton .buttonText').innerHTML = globalize.translate('CancelSeries');
|
||||
} else {
|
||||
parent.querySelector('.btnManageSeriesRecording').classList.add('hide');
|
||||
parent.querySelector('.seriesRecordingButton .recordingIcon').classList.remove('recordingIcon-active');
|
||||
parent.querySelector('.seriesRecordingButton .buttonText').innerHTML = globalize.translate('RecordSeries');
|
||||
function fetchData(instance) {
|
||||
const options = instance.options;
|
||||
const apiClient = connectionManager.getApiClient(options.serverId);
|
||||
|
||||
options.parent.querySelector('.recordingFields').classList.remove('hide');
|
||||
return apiClient.getLiveTvProgram(options.programId, apiClient.getCurrentUserId()).then(function (program) {
|
||||
instance.TimerId = program.TimerId;
|
||||
instance.Status = program.Status;
|
||||
instance.SeriesTimerId = program.SeriesTimerId;
|
||||
loadData(options.parent, program, apiClient);
|
||||
});
|
||||
}
|
||||
|
||||
function onTimerChangedExternally(e, apiClient, data) {
|
||||
const options = this.options;
|
||||
let refresh = false;
|
||||
|
||||
if (data.Id) {
|
||||
if (this.TimerId === data.Id) {
|
||||
refresh = true;
|
||||
}
|
||||
|
||||
if (program.TimerId && program.Status !== 'Cancelled') {
|
||||
parent.querySelector('.btnManageRecording').classList.remove('hide');
|
||||
parent.querySelector('.singleRecordingButton .recordingIcon').classList.add('recordingIcon-active');
|
||||
if (program.Status === 'InProgress') {
|
||||
parent.querySelector('.singleRecordingButton .buttonText').innerHTML = globalize.translate('StopRecording');
|
||||
} else {
|
||||
parent.querySelector('.singleRecordingButton .buttonText').innerHTML = globalize.translate('DoNotRecord');
|
||||
}
|
||||
} else {
|
||||
parent.querySelector('.btnManageRecording').classList.add('hide');
|
||||
parent.querySelector('.singleRecordingButton .recordingIcon').classList.remove('recordingIcon-active');
|
||||
parent.querySelector('.singleRecordingButton .buttonText').innerHTML = globalize.translate('Record');
|
||||
}
|
||||
if (data.ProgramId && options) {
|
||||
if (options.programId === data.ProgramId) {
|
||||
refresh = true;
|
||||
}
|
||||
}
|
||||
|
||||
function fetchData(instance) {
|
||||
var options = instance.options;
|
||||
var apiClient = connectionManager.getApiClient(options.serverId);
|
||||
|
||||
options.parent.querySelector('.recordingFields').classList.remove('hide');
|
||||
return apiClient.getLiveTvProgram(options.programId, apiClient.getCurrentUserId()).then(function (program) {
|
||||
instance.TimerId = program.TimerId;
|
||||
instance.Status = program.Status;
|
||||
instance.SeriesTimerId = program.SeriesTimerId;
|
||||
loadData(options.parent, program, apiClient);
|
||||
});
|
||||
if (refresh) {
|
||||
this.refresh();
|
||||
}
|
||||
}
|
||||
|
||||
function onTimerChangedExternally(e, apiClient, data) {
|
||||
var options = this.options;
|
||||
var refresh = false;
|
||||
function onSeriesTimerChangedExternally(e, apiClient, data) {
|
||||
const options = this.options;
|
||||
let refresh = false;
|
||||
|
||||
if (data.Id) {
|
||||
if (this.TimerId === data.Id) {
|
||||
refresh = true;
|
||||
}
|
||||
if (data.Id) {
|
||||
if (this.SeriesTimerId === data.Id) {
|
||||
refresh = true;
|
||||
}
|
||||
if (data.ProgramId && options) {
|
||||
if (options.programId === data.ProgramId) {
|
||||
refresh = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (refresh) {
|
||||
this.refresh();
|
||||
}
|
||||
if (data.ProgramId && options) {
|
||||
if (options.programId === data.ProgramId) {
|
||||
refresh = true;
|
||||
}
|
||||
}
|
||||
|
||||
function onSeriesTimerChangedExternally(e, apiClient, data) {
|
||||
var options = this.options;
|
||||
var refresh = false;
|
||||
|
||||
if (data.Id) {
|
||||
if (this.SeriesTimerId === data.Id) {
|
||||
refresh = true;
|
||||
}
|
||||
}
|
||||
if (data.ProgramId && options) {
|
||||
if (options.programId === data.ProgramId) {
|
||||
refresh = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (refresh) {
|
||||
this.refresh();
|
||||
}
|
||||
if (refresh) {
|
||||
this.refresh();
|
||||
}
|
||||
}
|
||||
|
||||
function RecordingEditor(options) {
|
||||
class RecordingEditor {
|
||||
constructor(options) {
|
||||
this.options = options;
|
||||
this.embed();
|
||||
|
||||
var timerChangedHandler = onTimerChangedExternally.bind(this);
|
||||
const timerChangedHandler = onTimerChangedExternally.bind(this);
|
||||
this.timerChangedHandler = timerChangedHandler;
|
||||
|
||||
events.on(serverNotifications, 'TimerCreated', timerChangedHandler);
|
||||
events.on(serverNotifications, 'TimerCancelled', timerChangedHandler);
|
||||
|
||||
var seriesTimerChangedHandler = onSeriesTimerChangedExternally.bind(this);
|
||||
const seriesTimerChangedHandler = onSeriesTimerChangedExternally.bind(this);
|
||||
this.seriesTimerChangedHandler = seriesTimerChangedHandler;
|
||||
|
||||
events.on(serverNotifications, 'SeriesTimerCreated', seriesTimerChangedHandler);
|
||||
events.on(serverNotifications, 'SeriesTimerCancelled', seriesTimerChangedHandler);
|
||||
}
|
||||
|
||||
function onManageRecordingClick(e) {
|
||||
var options = this.options;
|
||||
if (!this.TimerId || this.Status === 'Cancelled') {
|
||||
return;
|
||||
}
|
||||
|
||||
var self = this;
|
||||
require(['recordingEditor'], function (recordingEditor) {
|
||||
recordingEditor.show(self.TimerId, options.serverId, {
|
||||
enableCancel: false
|
||||
}).then(function () {
|
||||
self.changed = true;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function onManageSeriesRecordingClick(e) {
|
||||
var options = this.options;
|
||||
|
||||
if (!this.SeriesTimerId) {
|
||||
return;
|
||||
}
|
||||
|
||||
var self = this;
|
||||
|
||||
require(['seriesRecordingEditor'], function (seriesRecordingEditor) {
|
||||
seriesRecordingEditor.show(self.SeriesTimerId, options.serverId, {
|
||||
|
||||
enableCancel: false
|
||||
|
||||
}).then(function () {
|
||||
self.changed = true;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function onRecordChange(e) {
|
||||
this.changed = true;
|
||||
|
||||
var self = this;
|
||||
var options = this.options;
|
||||
var apiClient = connectionManager.getApiClient(options.serverId);
|
||||
|
||||
var button = dom.parentWithTag(e.target, 'BUTTON');
|
||||
var isChecked = !button.querySelector('.material-icons').classList.contains('recordingIcon-active');
|
||||
|
||||
var hasEnabledTimer = this.TimerId && this.Status !== 'Cancelled';
|
||||
|
||||
if (isChecked) {
|
||||
if (!hasEnabledTimer) {
|
||||
loading.show();
|
||||
recordingHelper.createRecording(apiClient, options.programId, false).then(function () {
|
||||
events.trigger(self, 'recordingchanged');
|
||||
fetchData(self);
|
||||
loading.hide();
|
||||
});
|
||||
}
|
||||
} else {
|
||||
if (hasEnabledTimer) {
|
||||
loading.show();
|
||||
recordingHelper.cancelTimer(apiClient, this.TimerId, true).then(function () {
|
||||
events.trigger(self, 'recordingchanged');
|
||||
fetchData(self);
|
||||
loading.hide();
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function sendToast(msg) {
|
||||
require(['toast'], function (toast) {
|
||||
toast(msg);
|
||||
});
|
||||
}
|
||||
|
||||
function onRecordSeriesChange(e) {
|
||||
this.changed = true;
|
||||
|
||||
var self = this;
|
||||
var options = this.options;
|
||||
var apiClient = connectionManager.getApiClient(options.serverId);
|
||||
|
||||
var button = dom.parentWithTag(e.target, 'BUTTON');
|
||||
var isChecked = !button.querySelector('.material-icons').classList.contains('recordingIcon-active');
|
||||
|
||||
if (isChecked) {
|
||||
options.parent.querySelector('.recordSeriesContainer').classList.remove('hide');
|
||||
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 {
|
||||
if (this.SeriesTimerId) {
|
||||
apiClient.cancelLiveTvSeriesTimer(this.SeriesTimerId).then(function () {
|
||||
sendToast(globalize.translate('RecordingCancelled'));
|
||||
fetchData(self);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RecordingEditor.prototype.embed = function () {
|
||||
var self = this;
|
||||
embed() {
|
||||
const self = this;
|
||||
return new Promise(function (resolve, reject) {
|
||||
require(['text!./recordingfields.template.html'], function (template) {
|
||||
var options = self.options;
|
||||
var context = options.parent;
|
||||
import('text!./recordingfields.template.html').then(({default: template}) => {
|
||||
const options = self.options;
|
||||
const context = options.parent;
|
||||
context.innerHTML = globalize.translateHtml(template, 'core');
|
||||
|
||||
context.querySelector('.singleRecordingButton').addEventListener('click', onRecordChange.bind(self));
|
||||
|
@ -228,29 +131,134 @@ define(['globalize', 'connectionManager', 'serverNotifications', 'require', 'loa
|
|||
fetchData(self).then(resolve);
|
||||
});
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
RecordingEditor.prototype.hasChanged = function () {
|
||||
hasChanged() {
|
||||
return this.changed;
|
||||
};
|
||||
}
|
||||
|
||||
RecordingEditor.prototype.refresh = function () {
|
||||
refresh() {
|
||||
fetchData(this);
|
||||
};
|
||||
}
|
||||
|
||||
RecordingEditor.prototype.destroy = function () {
|
||||
var timerChangedHandler = this.timerChangedHandler;
|
||||
destroy() {
|
||||
const timerChangedHandler = this.timerChangedHandler;
|
||||
this.timerChangedHandler = null;
|
||||
|
||||
events.off(serverNotifications, 'TimerCreated', timerChangedHandler);
|
||||
events.off(serverNotifications, 'TimerCancelled', timerChangedHandler);
|
||||
|
||||
var seriesTimerChangedHandler = this.seriesTimerChangedHandler;
|
||||
const seriesTimerChangedHandler = this.seriesTimerChangedHandler;
|
||||
this.seriesTimerChangedHandler = null;
|
||||
|
||||
events.off(serverNotifications, 'SeriesTimerCreated', seriesTimerChangedHandler);
|
||||
events.off(serverNotifications, 'SeriesTimerCancelled', seriesTimerChangedHandler);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
return RecordingEditor;
|
||||
});
|
||||
function onManageRecordingClick(e) {
|
||||
const options = this.options;
|
||||
if (!this.TimerId || this.Status === 'Cancelled') {
|
||||
return;
|
||||
}
|
||||
|
||||
const self = this;
|
||||
import('recordingEditor').then(({default: recordingEditor}) => {
|
||||
recordingEditor.show(self.TimerId, options.serverId, {
|
||||
enableCancel: false
|
||||
}).then(function () {
|
||||
self.changed = true;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function onManageSeriesRecordingClick(e) {
|
||||
const options = this.options;
|
||||
|
||||
if (!this.SeriesTimerId) {
|
||||
return;
|
||||
}
|
||||
|
||||
const self = this;
|
||||
|
||||
import('seriesRecordingEditor').then(({default: seriesRecordingEditor}) => {
|
||||
seriesRecordingEditor.show(self.SeriesTimerId, options.serverId, {
|
||||
|
||||
enableCancel: false
|
||||
|
||||
}).then(function () {
|
||||
self.changed = true;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function onRecordChange(e) {
|
||||
this.changed = true;
|
||||
|
||||
const self = this;
|
||||
const options = this.options;
|
||||
const apiClient = connectionManager.getApiClient(options.serverId);
|
||||
|
||||
const button = dom.parentWithTag(e.target, 'BUTTON');
|
||||
const isChecked = !button.querySelector('.material-icons').classList.contains('recordingIcon-active');
|
||||
|
||||
const hasEnabledTimer = this.TimerId && this.Status !== 'Cancelled';
|
||||
|
||||
if (isChecked) {
|
||||
if (!hasEnabledTimer) {
|
||||
loading.show();
|
||||
recordingHelper.createRecording(apiClient, options.programId, false).then(function () {
|
||||
events.trigger(self, 'recordingchanged');
|
||||
fetchData(self);
|
||||
loading.hide();
|
||||
});
|
||||
}
|
||||
} else {
|
||||
if (hasEnabledTimer) {
|
||||
loading.show();
|
||||
recordingHelper.cancelTimer(apiClient, this.TimerId, true).then(function () {
|
||||
events.trigger(self, 'recordingchanged');
|
||||
fetchData(self);
|
||||
loading.hide();
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function sendToast(msg) {
|
||||
import('toast').then(({default: toast}) => {
|
||||
toast(msg);
|
||||
});
|
||||
}
|
||||
|
||||
function onRecordSeriesChange(e) {
|
||||
this.changed = true;
|
||||
|
||||
const self = this;
|
||||
const options = this.options;
|
||||
const apiClient = connectionManager.getApiClient(options.serverId);
|
||||
|
||||
const button = dom.parentWithTag(e.target, 'BUTTON');
|
||||
const isChecked = !button.querySelector('.material-icons').classList.contains('recordingIcon-active');
|
||||
|
||||
if (isChecked) {
|
||||
options.parent.querySelector('.recordSeriesContainer').classList.remove('hide');
|
||||
if (!this.SeriesTimerId) {
|
||||
const promise = this.TimerId ?
|
||||
recordingHelper.changeRecordingToSeries(apiClient, this.TimerId, options.programId) :
|
||||
recordingHelper.createRecording(apiClient, options.programId, true);
|
||||
promise.then(function () {
|
||||
fetchData(self);
|
||||
});
|
||||
}
|
||||
} else {
|
||||
if (this.SeriesTimerId) {
|
||||
apiClient.cancelLiveTvSeriesTimer(this.SeriesTimerId).then(function () {
|
||||
sendToast(globalize.translate('RecordingCancelled'));
|
||||
fetchData(self);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default RecordingEditor;
|
||||
|
|
|
@ -66,7 +66,7 @@ function showSubtitleMenu(context, player, button, item) {
|
|||
});
|
||||
menuItems.unshift({
|
||||
id: -1,
|
||||
name: globalize.translate('ButtonOff'),
|
||||
name: globalize.translate('Off'),
|
||||
selected: currentIndex == null
|
||||
});
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
<option value="Smart">${Smart}</option>
|
||||
<option value="OnlyForced">${OnlyForcedSubtitles}</option>
|
||||
<option value="Always">${AlwaysPlaySubtitles}</option>
|
||||
<option value="None">${NoSubtitles}</option>
|
||||
<option value="None">${None}</option>
|
||||
</select>
|
||||
<div class="fieldDescription subtitlesDefaultHelp subtitlesHelp hide">${DefaultSubtitlesHelp}</div>
|
||||
<div class="fieldDescription subtitlesSmartHelp subtitlesHelp hide">${SmartSubtitlesHelp}</div>
|
||||
|
|
|
@ -737,7 +737,7 @@ import 'emby-itemscontainer';
|
|||
shutdown: function (btn) {
|
||||
import('confirm').then(({default: confirm}) => {
|
||||
confirm({
|
||||
title: globalize.translate('HeaderShutdown'),
|
||||
title: globalize.translate('ButtonShutdown'),
|
||||
text: globalize.translate('MessageConfirmShutdown'),
|
||||
confirmText: globalize.translate('ButtonShutdown'),
|
||||
primary: 'delete'
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
</div>
|
||||
|
||||
<div class="inputContainer">
|
||||
<input is="emby-input" type="text" id="txtCustomName" label="${LabelCustomDeviceDisplayName}" />
|
||||
<input is="emby-input" type="text" id="txtCustomName" label="${LabelDisplayName}" />
|
||||
<div class="fieldDescription">${LabelCustomDeviceDisplayNameHelp}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
<div class="content-primary">
|
||||
<div class="verticalSection verticalSection">
|
||||
<div class="sectionTitleContainer sectionTitleContainer-cards flex align-items-center">
|
||||
<h2 class="sectionTitle sectionTitle-cards">${TabDevices}</h2>
|
||||
<h2 class="sectionTitle sectionTitle-cards">${HeaderDevices}</h2>
|
||||
<a is="emby-linkbutton" rel="noopener noreferrer" class="raised button-alt headerHelpButton" target="_blank" href="https://docs.jellyfin.org/general/server/devices.html">${Help}</a>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -21,7 +21,7 @@ import 'cardStyle';
|
|||
confirm({
|
||||
text: msg,
|
||||
title: globalize.translate('HeaderDeleteDevice'),
|
||||
confirmText: globalize.translate('ButtonDelete'),
|
||||
confirmText: globalize.translate('Delete'),
|
||||
primary: 'delete'
|
||||
}).then(function () {
|
||||
loading.show();
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
</div>
|
||||
</div>
|
||||
<div data-role="controlgroup" data-type="horizontal" data-mini="true">
|
||||
<a href="#" is="emby-linkbutton" data-role="button" class="radioTabButton" id="radioInfo" data-value="tabInfo">${TabInfo}</a>
|
||||
<a href="#" is="emby-linkbutton" data-role="button" class="radioTabButton" id="radioInfo" data-value="tabInfo">${ButtonInfo}</a>
|
||||
<a href="#" is="emby-linkbutton" data-role="button" class="radioTabButton" id="radioDirectPlay" data-value="tabDirectPlayProfiles">${TabDirectPlay}</a>
|
||||
<a href="#" is="emby-linkbutton" data-role="button" class="radioTabButton" id="radioTranscoding" data-value="tabTranscodingProfiles">${Transcoding}</a>
|
||||
<a href="#" is="emby-linkbutton" data-role="button" class="radioTabButton" id="radioContainers" data-value="tabContainerProfiles">${TabContainers}</a>
|
||||
|
@ -231,31 +231,31 @@
|
|||
</div>
|
||||
<div class="tabContent tabDirectPlayProfiles">
|
||||
<p>${HeaderDirectPlayProfileHelp}</p>
|
||||
<button is="emby-button" class="raised submit block btnAddDirectPlayProfile" type="button" data-mini="true" data-icon="plus">${ButtonNew}</button>
|
||||
<button is="emby-button" class="raised submit block btnAddDirectPlayProfile" type="button" data-mini="true" data-icon="plus">${New}</button>
|
||||
<br />
|
||||
<div class="directPlayProfiles"></div>
|
||||
</div>
|
||||
<div class="tabContent tabTranscodingProfiles">
|
||||
<p>${HeaderTranscodingProfileHelp}</p>
|
||||
<button is="emby-button" class="raised submit block btnAddTranscodingProfile" type="button" data-mini="true" data-icon="plus">${ButtonNew}</button>
|
||||
<button is="emby-button" class="raised submit block btnAddTranscodingProfile" type="button" data-mini="true" data-icon="plus">${New}</button>
|
||||
<br />
|
||||
<div class="transcodingProfiles"></div>
|
||||
</div>
|
||||
<div class="tabContent tabContainerProfiles">
|
||||
<p>${HeaderContainerProfileHelp}</p>
|
||||
<button is="emby-button" class="raised submit block btnAddContainerProfile" type="button" data-mini="true" data-icon="plus">${ButtonNew}</button>
|
||||
<button is="emby-button" class="raised submit block btnAddContainerProfile" type="button" data-mini="true" data-icon="plus">${New}</button>
|
||||
<br />
|
||||
<div class="containerProfiles"></div>
|
||||
</div>
|
||||
<div class="tabContent tabCodecProfiles">
|
||||
<p>${HeaderCodecProfileHelp}</p>
|
||||
<button is="emby-button" class="raised submit block btnAddCodecProfile" type="button" data-icon="plus">${ButtonNew}</button>
|
||||
<button is="emby-button" class="raised submit block btnAddCodecProfile" type="button" data-icon="plus">${New}</button>
|
||||
<br />
|
||||
<div class="codecProfiles"></div>
|
||||
</div>
|
||||
<div class="tabContent tabMediaProfiles">
|
||||
<p>${HeaderResponseProfileHelp}</p>
|
||||
<button is="emby-button" class="raised submit block btnAddResponseProfile" type="button" data-mini="true" data-icon="plus">${ButtonNew}</button>
|
||||
<button is="emby-button" class="raised submit block btnAddResponseProfile" type="button" data-mini="true" data-icon="plus">${New}</button>
|
||||
<br />
|
||||
<div class="mediaProfiles"></div>
|
||||
</div>
|
||||
|
@ -319,7 +319,7 @@
|
|||
<div data-role="content">
|
||||
<div data-role="controlgroup" data-type="horizontal" data-mini="true">
|
||||
<input type="radio" name="radioTranscodingTab" class="radioTabButton" id="radioTranscodingBasics" value="tabTranscodingBasics">
|
||||
<label for="radioTranscodingBasics">${TabInfo}</label>
|
||||
<label for="radioTranscodingBasics">${ButtonInfo}</label>
|
||||
<input type="radio" name="radioTranscodingTab" class="radioTabButton" id="radioTranscodingAdvanced" value="tabTranscodingAdvanced">
|
||||
<label for="radioTranscodingAdvanced">${TabAdvanced}</label>
|
||||
</div>
|
||||
|
@ -341,16 +341,16 @@
|
|||
</div>
|
||||
</div>
|
||||
<div class="inputContainer">
|
||||
<input is="emby-input" type="text" id="txtTranscodingContainer" label="${LabelTranscodingContainer}"; required="required" />
|
||||
<input is="emby-input" type="text" id="txtTranscodingContainer" label="${LabelProfileContainer}"; required="required" />
|
||||
</div>
|
||||
<div id="fldTranscodingVideoCodec" style="margin: 1em 0;">
|
||||
<div class="inputContainer">
|
||||
<input is="emby-input" type="text" id="txtTranscodingVideoCodec" label="${LabelTranscodingVideoCodec}" />
|
||||
<input is="emby-input" type="text" id="txtTranscodingVideoCodec" label="${LabelVideoCodec}" />
|
||||
</div>
|
||||
</div>
|
||||
<div id="fldTranscodingAudioCodec" style="margin: 1em 0;">
|
||||
<div class="inputContainer">
|
||||
<input is="emby-input" type="text" id="txtTranscodingAudioCodec" label="${LabelTranscodingAudioCodec}" />
|
||||
<input is="emby-input" type="text" id="txtTranscodingAudioCodec" label="${LabelAudioCodec}" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -46,7 +46,7 @@ import 'emby-button';
|
|||
html += '</div>';
|
||||
|
||||
if (profile.Type == 'User') {
|
||||
html += '<button type="button" is="paper-icon-button-light" class="btnDeleteProfile" data-profileid="' + profile.Id + '" title="' + globalize.translate('ButtonDelete') + '"><span class="material-icons delete"></span></button>';
|
||||
html += '<button type="button" is="paper-icon-button-light" class="btnDeleteProfile" data-profileid="' + profile.Id + '" title="' + globalize.translate('Delete') + '"><span class="material-icons delete"></span></button>';
|
||||
}
|
||||
|
||||
html += '</div>';
|
||||
|
|
|
@ -45,10 +45,10 @@ import libraryMenu from 'libraryMenu';
|
|||
return ApiClient.ajax({
|
||||
url: ApiClient.getUrl('System/MediaEncoder/Path'),
|
||||
type: 'POST',
|
||||
data: {
|
||||
data: JSON.stringify({
|
||||
Path: form.querySelector('.txtEncoderPath').value,
|
||||
PathType: 'Custom'
|
||||
}
|
||||
})
|
||||
}).then(Dashboard.processServerConfigurationUpdateResult, onSaveEncodingPathFailure);
|
||||
});
|
||||
}
|
||||
|
@ -128,7 +128,7 @@ import libraryMenu from 'libraryMenu';
|
|||
name: globalize.translate('Transcoding')
|
||||
}, {
|
||||
href: 'playbackconfiguration.html',
|
||||
name: globalize.translate('TabResumeSettings')
|
||||
name: globalize.translate('ButtonResume')
|
||||
}, {
|
||||
href: 'streamingsettings.html',
|
||||
name: globalize.translate('TabStreaming')
|
||||
|
|
|
@ -17,9 +17,9 @@
|
|||
<div class="selectContainer">
|
||||
<select is="emby-select" id="selectLocalizationLanguage" label="${LabelPreferredDisplayLanguage}"></select>
|
||||
<div class="fieldDescription">
|
||||
<div>${LabelPreferredDisplayLanguageHelp}</div>
|
||||
<div>${LabelDisplayLanguageHelp}</div>
|
||||
<div style="margin-top: .25em;">
|
||||
<a is="emby-linkbutton" rel="noopener noreferrer" class="button-link" href="https://docs.jellyfin.org/general/contributing/index.html" target="_blank">${LabelReadHowYouCanContribute}</a>
|
||||
<a is="emby-linkbutton" rel="noopener noreferrer" class="button-link" href="https://docs.jellyfin.org/general/contributing/index.html" target="_blank">${LearnHowYouCanContribute}</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -93,7 +93,7 @@ import 'emby-itemrefreshindicator';
|
|||
const virtualFolder = virtualFolders[index];
|
||||
const menuItems = [];
|
||||
menuItems.push({
|
||||
name: globalize.translate('ButtonEditImages'),
|
||||
name: globalize.translate('EditImages'),
|
||||
id: 'editimages',
|
||||
icon: 'photo'
|
||||
});
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
<div class="content-primary">
|
||||
<form class="playbackConfigurationForm">
|
||||
<div class="sectionTitleContainer flex align-items-center">
|
||||
<h2 class="sectionTitle">${TabResumeSettings}</h2>
|
||||
<h2 class="sectionTitle">${ButtonResume}</h2>
|
||||
</div>
|
||||
<div class="inputContainer">
|
||||
<input is="emby-input" type="number" id="txtMinResumePct" name="txtMinResumePct" pattern="[0-9]*" required min="0" max="100" label="${LabelMinResumePercentage}"></input>
|
||||
|
|
|
@ -32,7 +32,7 @@ import globalize from 'globalize';
|
|||
name: globalize.translate('Transcoding')
|
||||
}, {
|
||||
href: 'playbackconfiguration.html',
|
||||
name: globalize.translate('TabResumeSettings')
|
||||
name: globalize.translate('ButtonResume')
|
||||
}, {
|
||||
href: 'streamingsettings.html',
|
||||
name: globalize.translate('TabStreaming')
|
||||
|
|
|
@ -28,7 +28,7 @@ function getHeaderText(category) {
|
|||
} else if (category === 'Theme') {
|
||||
category = 'Themes';
|
||||
} else if (category === 'LiveTV') {
|
||||
category = 'HeaderLiveTV';
|
||||
category = 'LiveTV';
|
||||
} else if (category === 'ScreenSaver') {
|
||||
category = 'HeaderScreenSavers';
|
||||
}
|
||||
|
|
|
@ -69,7 +69,7 @@ function getRepositoryHtml(repository) {
|
|||
html += `<h3 class="listItemBodyText">${repository.Name}</h3>`;
|
||||
html += `<div class="listItemBodyText secondary">${repository.Url}</div>`;
|
||||
html += '</div>';
|
||||
html += `<button type="button" is="paper-icon-button-light" id="${repository.Url}" class="btnDelete" title="${globalize.translate('ButtonDelete')}"><span class="material-icons delete"></span></button>`;
|
||||
html += `<button type="button" is="paper-icon-button-light" id="${repository.Url}" class="btnDelete" title="${globalize.translate('Delete')}"><span class="material-icons delete"></span></button>`;
|
||||
html += '</div>';
|
||||
|
||||
return html;
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
<div data-role="popup" id="popupAddTrigger" class="dialog dialog-fixedSize dialog-medium hide" style="position: fixed; top: 10%;">
|
||||
<form class="addTriggerForm" style="padding:1em;">
|
||||
<div class="ui-bar-a">
|
||||
<h3>${HeaderAddScheduledTaskTrigger}</h3>
|
||||
<h3>${ButtonAddScheduledTaskTrigger}</h3>
|
||||
</div>
|
||||
<div data-role="content">
|
||||
<div class="selectContainer">
|
||||
|
@ -31,18 +31,18 @@
|
|||
<option value="DailyTrigger">${OptionDaily}</option>
|
||||
<option value="WeeklyTrigger">${OptionWeekly}</option>
|
||||
<option value="IntervalTrigger">${OptionOnInterval}</option>
|
||||
<option value="StartupTrigger">${OptionOnAppStartup}</option>
|
||||
<option value="StartupTrigger">${OnApplicationStartup}</option>
|
||||
</select>
|
||||
</div>
|
||||
<div id="fldDayOfWeek" class="selectContainer">
|
||||
<select is="emby-select" id="selectDayOfWeek" name="selectDayOfWeek" label="${LabelDay}">
|
||||
<option value="Sunday">${OptionSunday}</option>
|
||||
<option value="Monday">${OptionMonday}</option>
|
||||
<option value="Tuesday">${OptionTuesday}</option>
|
||||
<option value="Wednesday">${OptionWednesday}</option>
|
||||
<option value="Thursday">${OptionThursday}</option>
|
||||
<option value="Friday">${OptionFriday}</option>
|
||||
<option value="Saturday">${OptionSaturday}</option>
|
||||
<option value="Sunday">${Sunday}</option>
|
||||
<option value="Monday">${Monday}</option>
|
||||
<option value="Tuesday">${Tuesday}</option>
|
||||
<option value="Wednesday">${Wednesday}</option>
|
||||
<option value="Thursday">${Thursday}</option>
|
||||
<option value="Friday">${Friday}</option>
|
||||
<option value="Saturday">${Saturday}</option>
|
||||
</select>
|
||||
</div>
|
||||
<div id="fldTimeOfDay" class="selectContainer">
|
||||
|
|
|
@ -75,7 +75,7 @@ import 'emby-select';
|
|||
}
|
||||
|
||||
html += '</div>';
|
||||
html += '<button class="btnDeleteTrigger" data-index="' + i + '" type="button" is="paper-icon-button-light" title="' + globalize.translate('ButtonDelete') + '"><span class="material-icons delete"></span></button>';
|
||||
html += '<button class="btnDeleteTrigger" data-index="' + i + '" type="button" is="paper-icon-button-light" title="' + globalize.translate('Delete') + '"><span class="material-icons delete"></span></button>';
|
||||
html += '</div>';
|
||||
}
|
||||
|
||||
|
|
|
@ -27,7 +27,7 @@ import globalize from 'globalize';
|
|||
name: globalize.translate('Transcoding')
|
||||
}, {
|
||||
href: 'playbackconfiguration.html',
|
||||
name: globalize.translate('TabResumeSettings')
|
||||
name: globalize.translate('ButtonResume')
|
||||
}, {
|
||||
href: 'streamingsettings.html',
|
||||
name: globalize.translate('TabStreaming')
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
<a href="#" is="emby-linkbutton" data-role="button" class="ui-btn-active">${TabProfile}</a>
|
||||
<a href="#" is="emby-linkbutton" data-role="button" onclick="Dashboard.navigate('userlibraryaccess.html', true);">${TabAccess}</a>
|
||||
<a href="#" is="emby-linkbutton" data-role="button" onclick="Dashboard.navigate('userparentalcontrol.html', true);">${TabParentalControl}</a>
|
||||
<a href="#" is="emby-linkbutton" data-role="button" onclick="Dashboard.navigate('userpassword.html', true);">${TabPassword}</a>
|
||||
<a href="#" is="emby-linkbutton" data-role="button" onclick="Dashboard.navigate('userpassword.html', true);">${HeaderPassword}</a>
|
||||
</div>
|
||||
<p class="lnkEditUserPreferencesContainer">
|
||||
<a class="lnkEditUserPreferences button-link" href="#" is="emby-linkbutton">${ButtonEditOtherUserPreferences}</a>
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
<a is="emby-linkbutton" href="#" data-role="button" onclick="Dashboard.navigate('useredit.html', true);">${TabProfile}</a>
|
||||
<a is="emby-linkbutton" href="#" data-role="button" onclick="Dashboard.navigate('userlibraryaccess.html', true);" class="ui-btn-active">${TabAccess}</a>
|
||||
<a is="emby-linkbutton" href="#" data-role="button" onclick="Dashboard.navigate('userparentalcontrol.html', true);">${TabParentalControl}</a>
|
||||
<a is="emby-linkbutton" href="#" data-role="button" onclick="Dashboard.navigate('userpassword.html', true);">${TabPassword}</a>
|
||||
<a is="emby-linkbutton" href="#" data-role="button" onclick="Dashboard.navigate('userpassword.html', true);">${HeaderPassword}</a>
|
||||
</div>
|
||||
<form class="userLibraryAccessForm">
|
||||
|
||||
|
|
|
@ -32,7 +32,7 @@ import globalize from 'globalize';
|
|||
|
||||
function loadChannels(page, user, channels) {
|
||||
let html = '';
|
||||
html += '<h3 class="checkboxListLabel">' + globalize.translate('HeaderChannels') + '</h3>';
|
||||
html += '<h3 class="checkboxListLabel">' + globalize.translate('Channels') + '</h3>';
|
||||
html += '<div class="checkboxList paperList checkboxList-paperList">';
|
||||
|
||||
for (let i = 0, length = channels.length; i < length; i++) {
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
<form class="newUserProfileForm">
|
||||
<div class="verticalSection">
|
||||
<div class="sectionTitleContainer flex align-items-center">
|
||||
<h2 class="sectionTitle">${HeaderAddUser}</h2>
|
||||
<h2 class="sectionTitle">${ButtonAddUser}</h2>
|
||||
<a is="emby-linkbutton" rel="noopener noreferrer" class="raised button-alt headerHelpButton" target="_blank" href="https://docs.jellyfin.org/general/server/users/">${Help}</a>
|
||||
</div>
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@ import 'emby-checkbox';
|
|||
|
||||
function loadChannels(page, channels) {
|
||||
let html = '';
|
||||
html += '<h3 class="checkboxListLabel">' + globalize.translate('HeaderChannels') + '</h3>';
|
||||
html += '<h3 class="checkboxListLabel">' + globalize.translate('Channels') + '</h3>';
|
||||
html += '<div class="checkboxList paperList" style="padding:.5em 1em;">';
|
||||
|
||||
for (let i = 0; i < channels.length; i++) {
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
<a is="emby-linkbutton" href="#" data-role="button" onclick="Dashboard.navigate('useredit.html', true);">${TabProfile}</a>
|
||||
<a is="emby-linkbutton" href="#" data-role="button" onclick="Dashboard.navigate('userlibraryaccess.html', true);">${TabAccess}</a>
|
||||
<a is="emby-linkbutton" href="#" data-role="button" onclick="Dashboard.navigate('userparentalcontrol.html', true);" class="ui-btn-active">${TabParentalControl}</a>
|
||||
<a is="emby-linkbutton" href="#" data-role="button" onclick="Dashboard.navigate('userpassword.html', true);">${TabPassword}</a>
|
||||
<a is="emby-linkbutton" href="#" data-role="button" onclick="Dashboard.navigate('userpassword.html', true);">${HeaderPassword}</a>
|
||||
</div>
|
||||
|
||||
<form class="userParentalControlForm">
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
<a is="emby-linkbutton" href="#" data-role="button" onclick="Dashboard.navigate('useredit.html', true);">${TabProfile}</a>
|
||||
<a is="emby-linkbutton" href="#" data-role="button" onclick="Dashboard.navigate('userlibraryaccess.html', true);">${TabAccess}</a>
|
||||
<a is="emby-linkbutton" href="#" data-role="button" onclick="Dashboard.navigate('userparentalcontrol.html', true);">${TabParentalControl}</a>
|
||||
<a is="emby-linkbutton" href="#" data-role="button" onclick="Dashboard.navigate('userpassword.html', true);" class="ui-btn-active">${TabPassword}</a>
|
||||
<a is="emby-linkbutton" href="#" data-role="button" onclick="Dashboard.navigate('userpassword.html', true);" class="ui-btn-active">${HeaderPassword}</a>
|
||||
</div>
|
||||
|
||||
<div class="readOnlyContent">
|
||||
|
|
|
@ -83,7 +83,7 @@ import 'emby-button';
|
|||
loading.hide();
|
||||
|
||||
import('toast').then(({default: toast}) => {
|
||||
toast(globalize.translate('MessageSettingsSaved'));
|
||||
toast(globalize.translate('SettingsSaved'));
|
||||
});
|
||||
|
||||
loadUser(view, params);
|
||||
|
|
|
@ -18,7 +18,7 @@ import 'flexStyles';
|
|||
confirm({
|
||||
title: globalize.translate('DeleteUser'),
|
||||
text: msg,
|
||||
confirmText: globalize.translate('ButtonDelete'),
|
||||
confirmText: globalize.translate('Delete'),
|
||||
primary: 'delete'
|
||||
}).then(function () {
|
||||
loading.show();
|
||||
|
@ -50,7 +50,7 @@ import 'flexStyles';
|
|||
icon: 'person'
|
||||
});
|
||||
menuItems.push({
|
||||
name: globalize.translate('ButtonDelete'),
|
||||
name: globalize.translate('Delete'),
|
||||
id: 'delete',
|
||||
icon: 'delete'
|
||||
});
|
||||
|
|
|
@ -18,13 +18,13 @@
|
|||
</div>
|
||||
</button>
|
||||
|
||||
<button is="emby-button" type="button" class="button-flat btnPlay hide detailButton" title="${ButtonPlay}" data-mode="play">
|
||||
<button is="emby-button" type="button" class="button-flat btnPlay hide detailButton" title="${Play}" data-mode="play">
|
||||
<div class="detailButton-content">
|
||||
<span class="material-icons detailButton-icon play_arrow"></span>
|
||||
</div>
|
||||
</button>
|
||||
|
||||
<button is="emby-button" type="button" class="button-flat btnDownload hide detailButton" title="${ButtonDownload}">
|
||||
<button is="emby-button" type="button" class="button-flat btnDownload hide detailButton" title="${Download}">
|
||||
<div class="detailButton-content">
|
||||
<span class="material-icons detailButton-icon get_app"></span>
|
||||
</div>
|
||||
|
@ -42,7 +42,7 @@
|
|||
</div>
|
||||
</button>
|
||||
|
||||
<button is="emby-button" type="button" class="button-flat btnShuffle hide detailButton" title="${ButtonShuffle}">
|
||||
<button is="emby-button" type="button" class="button-flat btnShuffle hide detailButton" title="${Shuffle}">
|
||||
<div class="detailButton-content">
|
||||
<span class="material-icons detailButton-icon shuffle"></span>
|
||||
</div>
|
||||
|
@ -147,14 +147,14 @@
|
|||
</div>
|
||||
|
||||
<div class="seriesTimerScheduleSection verticalSection detailVerticalSection hide" style="margin-top:-3em;">
|
||||
<h2 class="sectionTitle">${HeaderSchedule}</h2>
|
||||
<h2 class="sectionTitle">${Schedule}</h2>
|
||||
<div class="seriesTimerSchedule padded-right"></div>
|
||||
</div>
|
||||
|
||||
<div class="collectionItems hide"></div>
|
||||
|
||||
<div class="nextUpSection verticalSection detailVerticalSection hide">
|
||||
<h2 class="sectionTitle sectionTitle-cards">${HeaderNextUp}</h2>
|
||||
<h2 class="sectionTitle sectionTitle-cards">${NextUp}</h2>
|
||||
<div is="emby-itemscontainer" class="nextUpItems vertical-wrap padded-right"></div>
|
||||
</div>
|
||||
|
||||
|
@ -193,7 +193,7 @@
|
|||
</div>
|
||||
|
||||
<div id="castCollapsible" class="verticalSection detailVerticalSection hide">
|
||||
<h2 id="peopleHeader" class="sectionTitle sectionTitle-cards padded-right">${HeaderCastCrew}</h2>
|
||||
<h2 id="peopleHeader" class="sectionTitle sectionTitle-cards padded-right">${HeaderCastAndCrew}</h2>
|
||||
<div is="emby-scroller" class="padded-top-focusscale padded-bottom-focusscale" data-centerfocus="true">
|
||||
<div id="castContent" is="emby-itemscontainer" class="scrollSlider focuscontainer-x itemsContainer"></div>
|
||||
</div>
|
||||
|
|
|
@ -242,7 +242,7 @@ import 'emby-select';
|
|||
return m.Type === 'Audio';
|
||||
});
|
||||
const select = page.querySelector('.selectAudio');
|
||||
select.setLabel(globalize.translate('LabelAudio'));
|
||||
select.setLabel(globalize.translate('Audio'));
|
||||
const selectedId = mediaSource.DefaultAudioStreamIndex;
|
||||
select.innerHTML = tracks.map(function (v) {
|
||||
const selected = v.Index === selectedId ? ' selected' : '';
|
||||
|
@ -271,7 +271,7 @@ import 'emby-select';
|
|||
return m.Type === 'Subtitle';
|
||||
});
|
||||
const select = page.querySelector('.selectSubtitles');
|
||||
select.setLabel(globalize.translate('LabelSubtitles'));
|
||||
select.setLabel(globalize.translate('Subtitles'));
|
||||
const selectedId = mediaSource.DefaultSubtitleStreamIndex == null ? -1 : mediaSource.DefaultSubtitleStreamIndex;
|
||||
|
||||
const videoTracks = mediaSource.MediaStreams.filter(function (m) {
|
||||
|
@ -785,7 +785,7 @@ import 'emby-select';
|
|||
|
||||
function setPeopleHeader(page, item) {
|
||||
if (item.MediaType == 'Audio' || item.Type == 'MusicAlbum' || item.MediaType == 'Book' || item.MediaType == 'Photo') {
|
||||
page.querySelector('#peopleHeader').innerHTML = globalize.translate('HeaderPeople');
|
||||
page.querySelector('#peopleHeader').innerHTML = globalize.translate('People');
|
||||
} else {
|
||||
page.querySelector('#peopleHeader').innerHTML = globalize.translate('HeaderCastAndCrew');
|
||||
}
|
||||
|
@ -1432,13 +1432,13 @@ import 'emby-select';
|
|||
name: globalize.translate('HeaderVideos'),
|
||||
mediaType: 'Video'
|
||||
}, {
|
||||
name: globalize.translate('HeaderSeries'),
|
||||
name: globalize.translate('Series'),
|
||||
type: 'Series'
|
||||
}, {
|
||||
name: globalize.translate('HeaderAlbums'),
|
||||
name: globalize.translate('Albums'),
|
||||
type: 'MusicAlbum'
|
||||
}, {
|
||||
name: globalize.translate('HeaderBooks'),
|
||||
name: globalize.translate('Books'),
|
||||
type: 'Book'
|
||||
}];
|
||||
renderCollectionItems(page, item, collectionItemTypes, result.Items);
|
||||
|
@ -1446,13 +1446,13 @@ import 'emby-select';
|
|||
});
|
||||
|
||||
if (item.Type == 'Season') {
|
||||
page.querySelector('#childrenTitle').innerHTML = globalize.translate('HeaderEpisodes');
|
||||
page.querySelector('#childrenTitle').innerHTML = globalize.translate('Episodes');
|
||||
} else if (item.Type == 'Series') {
|
||||
page.querySelector('#childrenTitle').innerHTML = globalize.translate('HeaderSeasons');
|
||||
} else if (item.Type == 'MusicAlbum') {
|
||||
page.querySelector('#childrenTitle').innerHTML = globalize.translate('HeaderTracks');
|
||||
} else {
|
||||
page.querySelector('#childrenTitle').innerHTML = globalize.translate('HeaderItems');
|
||||
page.querySelector('#childrenTitle').innerHTML = globalize.translate('Items');
|
||||
}
|
||||
|
||||
if (item.Type == 'MusicAlbum' || item.Type == 'Season') {
|
||||
|
@ -1652,7 +1652,7 @@ import 'emby-select';
|
|||
|
||||
if (!items.length) {
|
||||
renderCollectionItemType(page, parentItem, {
|
||||
name: globalize.translate('HeaderItems')
|
||||
name: globalize.translate('Items')
|
||||
}, items);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<div id="liveTvSuggestedPage" data-dom-cache="true" data-role="page" class="page libraryPage liveTvPage pageWithAbsoluteTabs withTabs" data-title="${HeaderLiveTv}" data-backdroptype="series,movie">
|
||||
<div id="liveTvSuggestedPage" data-dom-cache="true" data-role="page" class="page libraryPage liveTvPage pageWithAbsoluteTabs withTabs" data-title="${LiveTV}" data-backdroptype="series,movie">
|
||||
|
||||
<div class="liveTvContainer">
|
||||
|
||||
|
@ -15,7 +15,7 @@
|
|||
<div id="upcomingEpisodes" class="verticalSection">
|
||||
<div class="sectionTitleContainer sectionTitleContainer-cards padded-left">
|
||||
<a href="list.html?type=Programs&IsSeries=true&IsMovie=false&IsNews=false" is="emby-linkbutton" class="button-flat button-flat-mini sectionTitleTextButton sectionTitleTextButton-programs">
|
||||
<h2 class="sectionTitle sectionTitle-cards" style="display: inline-block; vertical-align: middle;">${TabShows}</h2>
|
||||
<h2 class="sectionTitle sectionTitle-cards" style="display: inline-block; vertical-align: middle;">${Shows}</h2>
|
||||
<span class="material-icons chevron_right"></span>
|
||||
</a>
|
||||
</div>
|
||||
|
@ -24,7 +24,7 @@
|
|||
<div id="upcomingTvMovies" class="verticalSection">
|
||||
<div class="sectionTitleContainer sectionTitleContainer-cards padded-left">
|
||||
<a href="list.html?type=Programs&IsMovie=true" is="emby-linkbutton" class="button-flat button-flat-mini sectionTitleTextButton sectionTitleTextButton-programs">
|
||||
<h2 class="sectionTitle sectionTitle-cards" style="display: inline-block; vertical-align: middle;">${HeaderMovies}</h2>
|
||||
<h2 class="sectionTitle sectionTitle-cards" style="display: inline-block; vertical-align: middle;">${Movies}</h2>
|
||||
<span class="material-icons chevron_right"></span>
|
||||
</a>
|
||||
</div>
|
||||
|
@ -63,7 +63,7 @@
|
|||
<div class="pageTabContent" id="channelsTab" data-index="2">
|
||||
<div class="flex align-items-center justify-content-center flex-wrap-wrap padded-top padded-left padded-right padded-bottom">
|
||||
<div class="paging"></div>
|
||||
<button is="paper-icon-button-light" class="btnFilter sectionTitleButton" title="${ButtonFilter}"><span class="material-icons filter_list"></span></button>
|
||||
<button is="paper-icon-button-light" class="btnFilter sectionTitleButton" title="${Filter}"><span class="material-icons filter_list"></span></button>
|
||||
</div>
|
||||
<div is="emby-itemscontainer" id="items" class="itemsContainer vertical-wrap padded-left padded-right"></div>
|
||||
</div>
|
||||
|
|
|
@ -168,15 +168,15 @@ function getTabs() {
|
|||
return [{
|
||||
name: globalize.translate('Programs')
|
||||
}, {
|
||||
name: globalize.translate('TabGuide')
|
||||
name: globalize.translate('Guide')
|
||||
}, {
|
||||
name: globalize.translate('TabChannels')
|
||||
name: globalize.translate('Channels')
|
||||
}, {
|
||||
name: globalize.translate('TabRecordings')
|
||||
name: globalize.translate('Recordings')
|
||||
}, {
|
||||
name: globalize.translate('HeaderSchedule')
|
||||
name: globalize.translate('Schedule')
|
||||
}, {
|
||||
name: globalize.translate('TabSeries')
|
||||
name: globalize.translate('Series')
|
||||
}];
|
||||
}
|
||||
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
<form class="liveTvSettingsForm">
|
||||
<div class="selectContainer">
|
||||
<select is="emby-select" id="selectGuideDays" label="${LabelNumberOfGuideDays}">
|
||||
<option value="">${OptionAutomatic}</option>
|
||||
<option value="">${OptionAuto}</option>
|
||||
<option value="1">1</option>
|
||||
<option value="2">2</option>
|
||||
<option value="3">3</option>
|
||||
|
|
|
@ -137,7 +137,7 @@ function renderProviders(page, providers) {
|
|||
function showProviderOptions(page, providerId, button) {
|
||||
const items = [];
|
||||
items.push({
|
||||
name: globalize.translate('ButtonDelete'),
|
||||
name: globalize.translate('Delete'),
|
||||
id: 'delete'
|
||||
});
|
||||
items.push({
|
||||
|
@ -255,11 +255,11 @@ function addDevice(button) {
|
|||
function showDeviceMenu(button, tunerDeviceId) {
|
||||
const items = [];
|
||||
items.push({
|
||||
name: globalize.translate('ButtonDelete'),
|
||||
name: globalize.translate('Delete'),
|
||||
id: 'delete'
|
||||
});
|
||||
items.push({
|
||||
name: globalize.translate('ButtonEdit'),
|
||||
name: globalize.translate('Edit'),
|
||||
id: 'edit'
|
||||
});
|
||||
|
||||
|
|
|
@ -4,8 +4,8 @@
|
|||
<div class="flex align-items-center justify-content-center flex-wrap-wrap padded-top padded-left padded-right padded-bottom">
|
||||
<div class="paging"></div>
|
||||
<button is="paper-icon-button-light" class="btnSelectView autoSize" title="${ButtonSelectView}"><span class="material-icons view_comfy"></span></button>
|
||||
<button is="paper-icon-button-light" class="btnSort autoSize" title="${ButtonSort}"><span class="material-icons sort_by_alpha"></span></button>
|
||||
<button is="paper-icon-button-light" class="btnFilter autoSize" title="${ButtonFilter}"><span class="material-icons filter_list"></span></button>
|
||||
<button is="paper-icon-button-light" class="btnSort autoSize" title="${Sort}"><span class="material-icons sort_by_alpha"></span></button>
|
||||
<button is="paper-icon-button-light" class="btnFilter autoSize" title="${Filter}"><span class="material-icons filter_list"></span></button>
|
||||
</div>
|
||||
|
||||
<div class="alphaPicker alphaPicker-fixed alphaPicker-vertical">
|
||||
|
@ -46,8 +46,8 @@
|
|||
<div class="pageTabContent" data-index="2">
|
||||
<div class="flex align-items-center justify-content-center flex-wrap-wrap padded-top padded-left padded-right padded-bottom">
|
||||
<div class="paging"></div>
|
||||
<button is="paper-icon-button-light" class="btnSort autoSize" title="${ButtonSort}"><span class="material-icons sort_by_alpha"></span></button>
|
||||
<button is="paper-icon-button-light" class="btnFilter autoSize" title="${ButtonFilter}"><span class="material-icons filter_list"></span></button>
|
||||
<button is="paper-icon-button-light" class="btnSort autoSize" title="${Sort}"><span class="material-icons sort_by_alpha"></span></button>
|
||||
<button is="paper-icon-button-light" class="btnFilter autoSize" title="${Filter}"><span class="material-icons filter_list"></span></button>
|
||||
</div>
|
||||
|
||||
<div class="alphaPicker alphaPicker-fixed alphaPicker-fixed-right alphaPicker-vertical">
|
||||
|
@ -75,7 +75,7 @@
|
|||
<div class="flex align-items-center justify-content-center flex-wrap-wrap padded-top padded-left padded-right padded-bottom">
|
||||
<div class="paging"></div>
|
||||
<button is="paper-icon-button-light" class="btnSelectView autoSize" title="${ButtonSelectView}"><span class="material-icons view_comfy"></span></button>
|
||||
<button is="paper-icon-button-light" class="btnSort autoSize" title="${ButtonSort}"><span class="material-icons sort_by_alpha"></span></button>
|
||||
<button is="paper-icon-button-light" class="btnSort autoSize" title="${Sort}"><span class="material-icons sort_by_alpha"></span></button>
|
||||
<button type="button" is="paper-icon-button-light" class="btnNewCollection autoSize"><span class="material-icons add"></span></button>
|
||||
</div>
|
||||
|
||||
|
|
|
@ -229,13 +229,13 @@ import 'emby-button';
|
|||
}, {
|
||||
name: globalize.translate('Suggestions')
|
||||
}, {
|
||||
name: globalize.translate('TabTrailers')
|
||||
name: globalize.translate('Trailers')
|
||||
}, {
|
||||
name: globalize.translate('TabFavorites')
|
||||
name: globalize.translate('Favorites')
|
||||
}, {
|
||||
name: globalize.translate('TabCollections')
|
||||
name: globalize.translate('Collections')
|
||||
}, {
|
||||
name: globalize.translate('TabGenres')
|
||||
name: globalize.translate('Genres')
|
||||
}];
|
||||
}
|
||||
|
||||
|
@ -403,8 +403,8 @@ import 'emby-button';
|
|||
libraryMenu.setTitle(item.Name);
|
||||
});
|
||||
} else {
|
||||
view.setAttribute('data-title', globalize.translate('TabMovies'));
|
||||
libraryMenu.setTitle(globalize.translate('TabMovies'));
|
||||
view.setAttribute('data-title', globalize.translate('Movies'));
|
||||
libraryMenu.setTitle(globalize.translate('Movies'));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -38,10 +38,10 @@
|
|||
<div class="flex align-items-center justify-content-center flex-wrap-wrap padded-top padded-left padded-right padded-bottom">
|
||||
<div class="paging"></div>
|
||||
<button is="paper-icon-button-light" class="btnPlayAll musicglobalButton" title="${HeaderPlayAll}"><span class="material-icons play_arrow"></span></button>
|
||||
<button is="paper-icon-button-light" class="btnShuffle musicglobalButton" title="${ButtonShuffle}"><span class="material-icons shuffle"></span></button>
|
||||
<button is="paper-icon-button-light" class="btnShuffle musicglobalButton" title="${Shuffle}"><span class="material-icons shuffle"></span></button>
|
||||
<button is="paper-icon-button-light" class="btnSelectView autoSize" title="${ButtonSelectView}"><span class="material-icons view_comfy"></span></button>
|
||||
<button is="paper-icon-button-light" class="btnSort autoSize" title="${ButtonSort}"><span class="material-icons sort_by_alpha"></span></button>
|
||||
<button is="paper-icon-button-light" class="btnFilter autoSize" title="${ButtonFilter}"><span class="material-icons filter_list"></span></button>
|
||||
<button is="paper-icon-button-light" class="btnSort autoSize" title="${Sort}"><span class="material-icons sort_by_alpha"></span></button>
|
||||
<button is="paper-icon-button-light" class="btnFilter autoSize" title="${Filter}"><span class="material-icons filter_list"></span></button>
|
||||
</div>
|
||||
|
||||
<div class="alphaPicker alphaPicker-fixed alphaPicker-vertical">
|
||||
|
@ -57,7 +57,7 @@
|
|||
<div class="flex align-items-center justify-content-center flex-wrap-wrap padded-top padded-left padded-right padded-bottom">
|
||||
<div class="paging"></div>
|
||||
<button is="paper-icon-button-light" class="btnSelectView autoSize" title="${ButtonSelectView}"><span class="material-icons view_comfy"></span></button>
|
||||
<button is="paper-icon-button-light" class="btnFilter autoSize" title="${ButtonFilter}"><span class="material-icons filter_list"></span></button>
|
||||
<button is="paper-icon-button-light" class="btnFilter autoSize" title="${Filter}"><span class="material-icons filter_list"></span></button>
|
||||
</div>
|
||||
|
||||
<div class="alphaPicker alphaPicker-fixed alphaPicker-vertical">
|
||||
|
@ -73,7 +73,7 @@
|
|||
<div class="flex align-items-center justify-content-center flex-wrap-wrap padded-top padded-left padded-right padded-bottom">
|
||||
<div class="paging"></div>
|
||||
<button is="paper-icon-button-light" class="btnSelectView autoSize" title="${ButtonSelectView}"><span class="material-icons view_comfy"></span></button>
|
||||
<button is="paper-icon-button-light" class="btnFilter autoSize" title="${ButtonFilter}"><span class="material-icons filter_list"></span></button>
|
||||
<button is="paper-icon-button-light" class="btnFilter autoSize" title="${Filter}"><span class="material-icons filter_list"></span></button>
|
||||
</div>
|
||||
|
||||
<div class="alphaPicker alphaPicker-fixed alphaPicker-vertical">
|
||||
|
@ -92,8 +92,8 @@
|
|||
<div class="pageTabContent" id="songsTab" data-index="5">
|
||||
<div class="flex align-items-center justify-content-center flex-wrap-wrap padded-top padded-left padded-right padded-bottom">
|
||||
<div class="paging"></div>
|
||||
<button is="paper-icon-button-light" class="btnSort autoSize" title="${ButtonSort}"><span class="material-icons sort_by_alpha"></span></button>
|
||||
<button is="paper-icon-button-light" class="btnFilter autoSize" title="${ButtonFilter}"><span class="material-icons filter_list"></span></button>
|
||||
<button is="paper-icon-button-light" class="btnSort autoSize" title="${Sort}"><span class="material-icons sort_by_alpha"></span></button>
|
||||
<button is="paper-icon-button-light" class="btnFilter autoSize" title="${Filter}"><span class="material-icons filter_list"></span></button>
|
||||
</div>
|
||||
|
||||
<div is="emby-itemscontainer" id="items" class="itemsContainer vertical-list" style="max-width:67.5em;margin: 0 auto;"></div>
|
||||
|
|
|
@ -179,17 +179,17 @@ import 'flexStyles';
|
|||
return [{
|
||||
name: globalize.translate('Suggestions')
|
||||
}, {
|
||||
name: globalize.translate('TabAlbums')
|
||||
name: globalize.translate('Albums')
|
||||
}, {
|
||||
name: globalize.translate('TabAlbumArtists')
|
||||
name: globalize.translate('HeaderAlbumArtists')
|
||||
}, {
|
||||
name: globalize.translate('Artists')
|
||||
}, {
|
||||
name: globalize.translate('TabPlaylists')
|
||||
name: globalize.translate('Playlists')
|
||||
}, {
|
||||
name: globalize.translate('TabSongs')
|
||||
name: globalize.translate('Songs')
|
||||
}, {
|
||||
name: globalize.translate('TabGenres')
|
||||
name: globalize.translate('Genres')
|
||||
}];
|
||||
}
|
||||
|
||||
|
|
|
@ -59,7 +59,7 @@
|
|||
<span class="material-icons forward_30"></span>
|
||||
</button>
|
||||
|
||||
<button is="paper-icon-button-light" class="btnShuffleQueue autoSize" title="${ButtonShuffle}">
|
||||
<button is="paper-icon-button-light" class="btnShuffleQueue autoSize" title="${Shuffle}">
|
||||
<span class="material-icons shuffle"></span>
|
||||
</button>
|
||||
|
||||
|
@ -71,7 +71,7 @@
|
|||
<span class="material-icons audiotrack"></span>
|
||||
</button>
|
||||
|
||||
<button is="paper-icon-button-light" class="btnSubtitles videoButton btnPlayStateCommand autoSize" title="${ButtonSubtitles}" data-command="GoToSearch">
|
||||
<button is="paper-icon-button-light" class="btnSubtitles videoButton btnPlayStateCommand autoSize" title="${Subtitles}" data-command="GoToSearch">
|
||||
<span class="material-icons closed_caption"></span>
|
||||
</button>
|
||||
|
||||
|
@ -81,7 +81,7 @@
|
|||
<span class="material-icons fullscreen"></span>
|
||||
</button>
|
||||
|
||||
<button is="paper-icon-button-light" class="btnShuffleQueue autoSize" title="${ButtonShuffle}">
|
||||
<button is="paper-icon-button-light" class="btnShuffleQueue autoSize" title="${Shuffle}">
|
||||
<span class="material-icons shuffle"></span>
|
||||
</button>
|
||||
|
||||
|
@ -99,7 +99,7 @@
|
|||
<div is="emby-collapse" title="${HeaderNavigation}">
|
||||
<div class="collapseContent">
|
||||
<div>
|
||||
<button is="paper-icon-button-light" class="btnArrowUp btnCommand autoSize button-submit" title="${ButtonArrowUp}" data-command="MoveUp">
|
||||
<button is="paper-icon-button-light" class="btnArrowUp btnCommand autoSize button-submit" title="${Up}" data-command="MoveUp">
|
||||
<span class="material-icons keyboard_arrow_up"></span>
|
||||
</button>
|
||||
</div>
|
||||
|
@ -120,7 +120,7 @@
|
|||
<button is="paper-icon-button-light" class="btnBack btnCommand autoSize" title="${ButtonBack}" data-command="Back">
|
||||
<span class="material-icons arrow_back"></span>
|
||||
</button>
|
||||
<button is="paper-icon-button-light" class="btnArrowDown btnCommand autoSize button-submit" title="${ButtonArrowDown}" data-command="MoveDown">
|
||||
<button is="paper-icon-button-light" class="btnArrowDown btnCommand autoSize button-submit" title="${Down}" data-command="MoveDown">
|
||||
<span class="material-icons keyboard_arrow_down"></span>
|
||||
</button>
|
||||
<button is="paper-icon-button-light" class="btnContextMenu btnCommand autoSize" title="${ButtonInfo}" data-command="ToggleContextMenu">
|
||||
|
@ -129,7 +129,7 @@
|
|||
</div>
|
||||
<br />
|
||||
<div>
|
||||
<button is="paper-icon-button-light" class="btnGoHome btnCommand autoSize" title="${ButtonHome}" data-command="GoHome">
|
||||
<button is="paper-icon-button-light" class="btnGoHome btnCommand autoSize" title="${Home}" data-command="GoHome">
|
||||
<span class="material-icons home"></span>
|
||||
</button>
|
||||
<button is="paper-icon-button-light" class="btnShowSearch btnCommand autoSize" title="${Search}" data-command="GoToSearch">
|
||||
|
|
|
@ -767,7 +767,7 @@ import 'css!assets/css/videoosd';
|
|||
|
||||
if (isPaused) {
|
||||
btnPlayPauseIcon.classList.add('play_arrow');
|
||||
btnPlayPause.setAttribute('title', globalize.translate('ButtonPlay') + ' (k)');
|
||||
btnPlayPause.setAttribute('title', globalize.translate('Play') + ' (k)');
|
||||
} else {
|
||||
btnPlayPauseIcon.classList.add('pause');
|
||||
btnPlayPause.setAttribute('title', globalize.translate('ButtonPause') + ' (k)');
|
||||
|
@ -1243,6 +1243,12 @@ import 'css!assets/css/videoosd';
|
|||
}
|
||||
break;
|
||||
}
|
||||
case '>':
|
||||
playbackManager.increasePlaybackRate(currentPlayer);
|
||||
break;
|
||||
case '<':
|
||||
playbackManager.decreasePlaybackRate(currentPlayer);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
</div>
|
||||
<br />
|
||||
<button is="emby-button" type="submit" class="raised button-submit block">
|
||||
<span>${ButtonConnect}</span>
|
||||
<span>${Connect}</span>
|
||||
</button>
|
||||
<button is="emby-button" type="button" class="raised button-cancel block btnCancel">
|
||||
<span>${ButtonCancel}</span>
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<div class="padded-left padded-right padded-bottom-page">
|
||||
<form class="forgotPasswordForm" style="text-align: center; margin: 0 auto;">
|
||||
<div style="text-align: left;">
|
||||
<h1>${HeaderForgotPassword}</h1>
|
||||
<h1>${ButtonForgotPassword}</h1>
|
||||
|
||||
<div class="inputContainer">
|
||||
<input is="emby-input" type="text" id="txtName" label="${LabelUser}" autocomplete="off"/>
|
||||
|
|
|
@ -6,14 +6,14 @@ import globalize from 'globalize';
|
|||
if (result.Action == 'ContactAdmin') {
|
||||
return void Dashboard.alert({
|
||||
message: globalize.translate('MessageContactAdminToResetPassword'),
|
||||
title: globalize.translate('HeaderForgotPassword')
|
||||
title: globalize.translate('ButtonForgotPassword')
|
||||
});
|
||||
}
|
||||
|
||||
if (result.Action == 'InNetworkRequired') {
|
||||
return void Dashboard.alert({
|
||||
message: globalize.translate('MessageForgotPasswordInNetworkRequired'),
|
||||
title: globalize.translate('HeaderForgotPassword')
|
||||
title: globalize.translate('ButtonForgotPassword')
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -27,7 +27,7 @@ import globalize from 'globalize';
|
|||
msg += '<br/>';
|
||||
return void Dashboard.alert({
|
||||
message: msg,
|
||||
title: globalize.translate('HeaderForgotPassword'),
|
||||
title: globalize.translate('ButtonForgotPassword'),
|
||||
callback: function () {
|
||||
Dashboard.navigate('forgotpasswordpin.html');
|
||||
}
|
||||
|
@ -41,9 +41,9 @@ import globalize from 'globalize';
|
|||
type: 'POST',
|
||||
url: ApiClient.getUrl('Users/ForgotPassword'),
|
||||
dataType: 'json',
|
||||
data: {
|
||||
data: JSON.stringify({
|
||||
EnteredUsername: view.querySelector('#txtName').value
|
||||
}
|
||||
})
|
||||
}).then(processForgotPasswordResult);
|
||||
e.preventDefault();
|
||||
return false;
|
||||
|
|
|
@ -29,9 +29,9 @@ import globalize from 'globalize';
|
|||
type: 'POST',
|
||||
url: ApiClient.getUrl('Users/ForgotPassword/Pin'),
|
||||
dataType: 'json',
|
||||
data: {
|
||||
data: JSON.stringify({
|
||||
Pin: view.querySelector('#txtPin').value
|
||||
}
|
||||
})
|
||||
}).then(processForgotPasswordResult);
|
||||
e.preventDefault();
|
||||
return false;
|
||||
|
|
|
@ -4,8 +4,8 @@
|
|||
<div class="flex align-items-center justify-content-center flex-wrap-wrap padded-top padded-left padded-right padded-bottom">
|
||||
<div class="paging"></div>
|
||||
<button is="paper-icon-button-light" class="btnSelectView autoSize" title="${ButtonSelectView}"><span class="material-icons view_comfy"></span></button>
|
||||
<button is="paper-icon-button-light" class="btnSort autoSize" title="${ButtonSort}"><span class="material-icons sort_by_alpha"></span></button>
|
||||
<button is="paper-icon-button-light" class="btnFilter autoSize" title="${ButtonFilter}"><span class="material-icons filter_list"></span></button>
|
||||
<button is="paper-icon-button-light" class="btnSort autoSize" title="${Sort}"><span class="material-icons sort_by_alpha"></span></button>
|
||||
<button is="paper-icon-button-light" class="btnFilter autoSize" title="${Filter}"><span class="material-icons filter_list"></span></button>
|
||||
</div>
|
||||
|
||||
<div is="emby-itemscontainer" class="itemsContainer padded-left padded-right"></div>
|
||||
|
@ -26,7 +26,7 @@
|
|||
|
||||
<div class="verticalSection">
|
||||
<div class="sectionTitleContainer sectionTitleContainer-cards">
|
||||
<h2 class="sectionTitle sectionTitle-cards padded-left nextUpHeader">${HeaderNextUp}</h2>
|
||||
<h2 class="sectionTitle sectionTitle-cards padded-left nextUpHeader">${NextUp}</h2>
|
||||
</div>
|
||||
<div is="emby-itemscontainer" id="nextUpItems" class="itemsContainer vertical-wrap padded-left padded-right">
|
||||
</div>
|
||||
|
@ -60,8 +60,8 @@
|
|||
<div class="flex align-items-center justify-content-center flex-wrap-wrap padded-top padded-left padded-right padded-bottom">
|
||||
<div class="paging"></div>
|
||||
<button is="paper-icon-button-light" class="btnSelectView autoSize" title="${ButtonSelectView}"><span class="material-icons view_comfy"></span></button>
|
||||
<button is="paper-icon-button-light" class="btnSort autoSize" title="${ButtonSort}"><span class="material-icons sort_by_alpha"></span></button>
|
||||
<button is="paper-icon-button-light" class="btnFilter autoSize" title="${ButtonFilter}"><span class="material-icons filter_list"></span></button>
|
||||
<button is="paper-icon-button-light" class="btnSort autoSize" title="${Sort}"><span class="material-icons sort_by_alpha"></span></button>
|
||||
<button is="paper-icon-button-light" class="btnFilter autoSize" title="${Filter}"><span class="material-icons filter_list"></span></button>
|
||||
</div>
|
||||
<div is="emby-itemscontainer" class="itemsContainer vertical-wrap padded-left padded-right">
|
||||
</div>
|
||||
|
|
|
@ -17,7 +17,7 @@ import 'emby-button';
|
|||
|
||||
function getTabs() {
|
||||
return [{
|
||||
name: globalize.translate('TabShows')
|
||||
name: globalize.translate('Shows')
|
||||
}, {
|
||||
name: globalize.translate('Suggestions')
|
||||
}, {
|
||||
|
@ -25,11 +25,11 @@ import 'emby-button';
|
|||
}, {
|
||||
name: globalize.translate('TabUpcoming')
|
||||
}, {
|
||||
name: globalize.translate('TabGenres')
|
||||
name: globalize.translate('Genres')
|
||||
}, {
|
||||
name: globalize.translate('TabNetworks')
|
||||
}, {
|
||||
name: globalize.translate('TabEpisodes')
|
||||
name: globalize.translate('Episodes')
|
||||
}];
|
||||
}
|
||||
|
||||
|
@ -318,8 +318,8 @@ import 'emby-button';
|
|||
libraryMenu.setTitle(item.Name);
|
||||
});
|
||||
} else {
|
||||
view.setAttribute('data-title', globalize.translate('TabShows'));
|
||||
libraryMenu.setTitle(globalize.translate('TabShows'));
|
||||
view.setAttribute('data-title', globalize.translate('Shows'));
|
||||
libraryMenu.setTitle(globalize.translate('Shows'));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<div id="homeScreenPreferencesPage" data-role="page" class="page libraryPage userPreferencesPage noSecondaryNavPage" data-title="${HeaderHome}" data-backbutton="true">
|
||||
<div id="homeScreenPreferencesPage" data-role="page" class="page libraryPage userPreferencesPage noSecondaryNavPage" data-title="${Home}" data-backbutton="true">
|
||||
<div class="homeScreenSettingsContainer padded-left padded-right padded-bottom-page">
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
<div class="listItem">
|
||||
<span class="material-icons listItemIcon listItemIcon-transparent home"></span>
|
||||
<div class="listItemBody">
|
||||
<div class="listItemBodyText">${HeaderHome}</div>
|
||||
<div class="listItemBodyText">${Home}</div>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
<span>${ButtonAddImage}</span>
|
||||
</button>
|
||||
<button is="emby-button" type="button" class="raised hide" id="btnDeleteImage">
|
||||
<span>${ButtonDeleteImage}</span>
|
||||
<span>${DeleteImage}</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
<div class="wizardNavigation">
|
||||
<button is="emby-button" type="button" class="raised button-cancel" onclick="history.back();">
|
||||
<span class="material-icons arrow_back"></span>
|
||||
<span>${LabelPrevious}</span>
|
||||
<span>${Previous}</span>
|
||||
</button>
|
||||
<button is="emby-button" type="button" class="raised btnWizardNext button-submit">
|
||||
<span class="material-icons check"></span>
|
||||
|
|
|
@ -12,10 +12,10 @@
|
|||
<div class="wizardNavigation">
|
||||
<button is="emby-button" type="button" class="raised button-cancel" onclick="history.back();">
|
||||
<span class="material-icons arrow_back"></span>
|
||||
<span>${LabelPrevious}</span>
|
||||
<span>${Previous}</span>
|
||||
</button>
|
||||
<button is="emby-button" type="button" class="raised button-submit" onclick="WizardLibraryPage.next();">
|
||||
<span>${LabelNext}</span>
|
||||
<span>${Next}</span>
|
||||
<span class="material-icons arrow_forward"></span>
|
||||
</button>
|
||||
</div>
|
||||
|
|
|
@ -22,10 +22,10 @@
|
|||
<div class="wizardNavigation">
|
||||
<button is="emby-button" type="button" class="raised button-cancel" onclick="history.back();">
|
||||
<span class="material-icons arrow_back"></span>
|
||||
<span>${LabelPrevious}</span>
|
||||
<span>${Previous}</span>
|
||||
</button>
|
||||
<button is="emby-button" type="submit" class="raised button-submit">
|
||||
<span>${LabelNext}</span>
|
||||
<span>${Next}</span>
|
||||
<span class="material-icons arrow_forward"></span>
|
||||
</button>
|
||||
</div>
|
||||
|
|
|
@ -11,7 +11,7 @@ function save(page) {
|
|||
config.EnableAutomaticPortMapping = page.querySelector('#chkEnableUpnp').checked;
|
||||
apiClient.ajax({
|
||||
type: 'POST',
|
||||
data: config,
|
||||
data: JSON.stringify(config),
|
||||
url: apiClient.getUrl('Startup/RemoteAccess')
|
||||
}).then(function () {
|
||||
loading.hide();
|
||||
|
|
|
@ -17,10 +17,10 @@
|
|||
<div class="wizardNavigation">
|
||||
<button is="emby-button" type="button" class="raised button-cancel" onclick="history.back();">
|
||||
<span class="material-icons arrow_back"></span>
|
||||
<span>${LabelPrevious}</span>
|
||||
<span>${Previous}</span>
|
||||
</button>
|
||||
<button is="emby-button" type="submit" class="raised button-submit">
|
||||
<span>${LabelNext}</span>
|
||||
<span>${Next}</span>
|
||||
<span class="material-icons arrow_forward"></span>
|
||||
</button>
|
||||
</div>
|
||||
|
|
|
@ -11,7 +11,7 @@ function save(page) {
|
|||
config.MetadataCountryCode = page.querySelector('#selectCountry').value;
|
||||
apiClient.ajax({
|
||||
type: 'POST',
|
||||
data: config,
|
||||
data: JSON.stringify(config),
|
||||
url: apiClient.getUrl('Startup/Configuration')
|
||||
}).then(function () {
|
||||
loading.hide();
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
|
||||
<div class="wizardNavigation" style="text-align:right;">
|
||||
<button is="emby-button" type="submit" class="raised button-submit">
|
||||
<span>${LabelNext}</span>
|
||||
<span>${Next}</span>
|
||||
<span class="material-icons arrow_forward"></span>
|
||||
</button>
|
||||
</div>
|
||||
|
|
|
@ -17,7 +17,7 @@ function save(page) {
|
|||
config.UICulture = $('#selectLocalizationLanguage', page).val();
|
||||
apiClient.ajax({
|
||||
type: 'POST',
|
||||
data: config,
|
||||
data: JSON.stringify(config),
|
||||
url: apiClient.getUrl('Startup/Configuration')
|
||||
}).then(function () {
|
||||
Dashboard.navigate('wizarduser.html');
|
||||
|
|
|
@ -23,10 +23,10 @@
|
|||
<div class="wizardNavigation">
|
||||
<button is="emby-button" type="button" class="raised button-cancel" onclick="history.back();">
|
||||
<span class="material-icons arrow_back"></span>
|
||||
<span>${LabelPrevious}</span>
|
||||
<span>${Previous}</span>
|
||||
</button>
|
||||
<button is="emby-button" type="submit" class="raised button-submit">
|
||||
<span>${LabelNext}</span>
|
||||
<span>${Next}</span>
|
||||
<span class="material-icons arrow_forward"></span>
|
||||
</button>
|
||||
</div>
|
||||
|
|
|
@ -23,10 +23,10 @@ function submit(form) {
|
|||
const apiClient = getApiClient();
|
||||
apiClient.ajax({
|
||||
type: 'POST',
|
||||
data: {
|
||||
data: JSON.stringify({
|
||||
Name: form.querySelector('#txtUsername').value,
|
||||
Password: form.querySelector('#txtManualPassword').value
|
||||
},
|
||||
}),
|
||||
url: apiClient.getUrl('Startup/User')
|
||||
}).then(onUpdateUserComplete);
|
||||
}
|
||||
|
|
|
@ -10,7 +10,7 @@ import 'webcomponents';
|
|||
function onKeyDown(e) {
|
||||
// Don't submit form on enter
|
||||
// Real (non-emulator) Tizen does nothing on Space
|
||||
if (e.keyCode === 13 || e.keyCode === 32) {
|
||||
if (e.keyCode === 13 || (e.keyCode === 32 && browser.tizen)) {
|
||||
e.preventDefault();
|
||||
|
||||
this.checked = !this.checked;
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import layoutManager from 'layoutManager';
|
||||
import 'css!./emby-radio';
|
||||
import 'webcomponents';
|
||||
import browser from 'browser';
|
||||
|
||||
/* eslint-disable indent */
|
||||
|
||||
|
@ -9,7 +10,7 @@ import 'webcomponents';
|
|||
function onKeyDown(e) {
|
||||
// Don't submit form on enter
|
||||
// Real (non-emulator) Tizen does nothing on Space
|
||||
if (e.keyCode === 13 || e.keyCode === 32) {
|
||||
if (e.keyCode === 13 || (e.keyCode === 32 && browser.tizen)) {
|
||||
e.preventDefault();
|
||||
|
||||
if (!this.checked) {
|
||||
|
|
|
@ -1,61 +1,61 @@
|
|||
define(['connectionManager', 'globalize', 'userSettings', 'apphost'], function (connectionManager, globalize, userSettings, appHost) {
|
||||
'use strict';
|
||||
import globalize from 'globalize';
|
||||
import * as userSettings from 'userSettings';
|
||||
import appHost from 'apphost';
|
||||
|
||||
appHost = appHost.default || appHost;
|
||||
// TODO: Replace with date-fns
|
||||
// https://stackoverflow.com/questions/6117814/get-week-of-year-in-javascript-like-in-php
|
||||
function getWeek(date) {
|
||||
const d = new Date(Date.UTC(date.getFullYear(), date.getMonth(), date.getDate()));
|
||||
const dayNum = d.getUTCDay() || 7;
|
||||
d.setUTCDate(d.getUTCDate() + 4 - dayNum);
|
||||
const yearStart = new Date(Date.UTC(d.getUTCFullYear(), 0, 1));
|
||||
return Math.ceil((((d - yearStart) / 86400000) + 1) / 7);
|
||||
}
|
||||
|
||||
// TODO: Replace with date-fns
|
||||
// https://stackoverflow.com/questions/6117814/get-week-of-year-in-javascript-like-in-php
|
||||
function getWeek(date) {
|
||||
var d = new Date(Date.UTC(date.getFullYear(), date.getMonth(), date.getDate()));
|
||||
var dayNum = d.getUTCDay() || 7;
|
||||
d.setUTCDate(d.getUTCDate() + 4 - dayNum);
|
||||
var yearStart = new Date(Date.UTC(d.getUTCFullYear(), 0, 1));
|
||||
return Math.ceil((((d - yearStart) / 86400000) + 1) / 7);
|
||||
function showMessage(text, userSettingsKey, appHostFeature) {
|
||||
if (appHost.supports(appHostFeature)) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
function showMessage(text, userSettingsKey, appHostFeature) {
|
||||
if (appHost.supports(appHostFeature)) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
const now = new Date();
|
||||
|
||||
var now = new Date();
|
||||
// TODO: Use date-fns
|
||||
userSettingsKey += now.getFullYear() + '-w' + getWeek(now);
|
||||
|
||||
// TODO: Use date-fns
|
||||
userSettingsKey += now.getFullYear() + '-w' + getWeek(now);
|
||||
if (userSettings.get(userSettingsKey, false) === '1') {
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
if (userSettings.get(userSettingsKey, false) === '1') {
|
||||
return Promise.resolve();
|
||||
}
|
||||
return new Promise(function (resolve, reject) {
|
||||
userSettings.set(userSettingsKey, '1', false);
|
||||
|
||||
return new Promise(function (resolve, reject) {
|
||||
userSettings.set(userSettingsKey, '1', false);
|
||||
|
||||
require(['alert'], function (alert) {
|
||||
return alert(text).then(resolve, resolve);
|
||||
});
|
||||
import('alert').then(({default: alert}) => {
|
||||
return alert(text).then(resolve, resolve);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function showBlurayMessage() {
|
||||
return showMessage(globalize.translate('UnsupportedPlayback'), 'blurayexpirementalinfo', 'nativeblurayplayback');
|
||||
}
|
||||
function showBlurayMessage() {
|
||||
return showMessage(globalize.translate('UnsupportedPlayback'), 'blurayexpirementalinfo', 'nativeblurayplayback');
|
||||
}
|
||||
|
||||
function showDvdMessage() {
|
||||
return showMessage(globalize.translate('UnsupportedPlayback'), 'dvdexpirementalinfo', 'nativedvdplayback');
|
||||
}
|
||||
function showDvdMessage() {
|
||||
return showMessage(globalize.translate('UnsupportedPlayback'), 'dvdexpirementalinfo', 'nativedvdplayback');
|
||||
}
|
||||
|
||||
function showIsoMessage() {
|
||||
return showMessage(globalize.translate('UnsupportedPlayback'), 'isoexpirementalinfo', 'nativeisoplayback');
|
||||
}
|
||||
function showIsoMessage() {
|
||||
return showMessage(globalize.translate('UnsupportedPlayback'), 'isoexpirementalinfo', 'nativeisoplayback');
|
||||
}
|
||||
|
||||
function ExpirementalPlaybackWarnings() {
|
||||
class ExpirementalPlaybackWarnings {
|
||||
constructor() {
|
||||
this.name = 'Experimental playback warnings';
|
||||
this.type = 'preplayintercept';
|
||||
this.id = 'expirementalplaybackwarnings';
|
||||
}
|
||||
|
||||
ExpirementalPlaybackWarnings.prototype.intercept = function (options) {
|
||||
var item = options.item;
|
||||
intercept(options) {
|
||||
const item = options.item;
|
||||
if (!item) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
@ -73,7 +73,7 @@ define(['connectionManager', 'globalize', 'userSettings', 'apphost'], function (
|
|||
}
|
||||
|
||||
return Promise.resolve();
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
return ExpirementalPlaybackWarnings;
|
||||
});
|
||||
export default ExpirementalPlaybackWarnings;
|
||||
|
|
|
@ -150,7 +150,7 @@ function tryRemoveElement(elem) {
|
|||
/**
|
||||
* @type {string}
|
||||
*/
|
||||
name
|
||||
name;
|
||||
/**
|
||||
* @type {string}
|
||||
*/
|
||||
|
@ -730,7 +730,7 @@ function tryRemoveElement(elem) {
|
|||
const elem = e.target;
|
||||
this.destroyCustomTrack(elem);
|
||||
onEndedInternal(this, elem, this.onError);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @private
|
||||
|
@ -760,7 +760,7 @@ function tryRemoveElement(elem) {
|
|||
}
|
||||
|
||||
events.trigger(this, 'timeupdate');
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @private
|
||||
|
@ -773,7 +773,7 @@ function tryRemoveElement(elem) {
|
|||
const elem = e.target;
|
||||
saveVolume(elem.volume);
|
||||
events.trigger(this, 'volumechange');
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @private
|
||||
|
@ -785,7 +785,7 @@ function tryRemoveElement(elem) {
|
|||
|
||||
this.onStartedAndNavigatedToOsd();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @private
|
||||
|
@ -832,14 +832,14 @@ function tryRemoveElement(elem) {
|
|||
}
|
||||
}
|
||||
events.trigger(this, 'playing');
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
onPlay = () => {
|
||||
events.trigger(this, 'unpause');
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @private
|
||||
|
@ -865,21 +865,21 @@ function tryRemoveElement(elem) {
|
|||
*/
|
||||
onClick = () => {
|
||||
events.trigger(this, 'click');
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
onDblClick = () => {
|
||||
events.trigger(this, 'dblclick');
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
onPause = () => {
|
||||
events.trigger(this, 'pause');
|
||||
}
|
||||
};
|
||||
|
||||
onWaiting() {
|
||||
events.trigger(this, 'waiting');
|
||||
|
@ -929,7 +929,7 @@ function tryRemoveElement(elem) {
|
|||
}
|
||||
|
||||
onErrorInternal(this, type);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @private
|
||||
|
@ -1634,6 +1634,31 @@ function tryRemoveElement(elem) {
|
|||
return null;
|
||||
}
|
||||
|
||||
getSupportedPlaybackRates() {
|
||||
return [{
|
||||
name: '0.5x',
|
||||
id: 0.5
|
||||
}, {
|
||||
name: '0.75x',
|
||||
id: 0.75
|
||||
}, {
|
||||
name: '1x',
|
||||
id: 1.0
|
||||
}, {
|
||||
name: '1.25x',
|
||||
id: 1.25
|
||||
}, {
|
||||
name: '1.5x',
|
||||
id: 1.5
|
||||
}, {
|
||||
name: '1.75x',
|
||||
id: 1.75
|
||||
}, {
|
||||
name: '2x',
|
||||
id: 2.0
|
||||
}];
|
||||
}
|
||||
|
||||
setVolume(val) {
|
||||
const mediaElement = this.#mediaElement;
|
||||
if (mediaElement) {
|
||||
|
|
|
@ -1,132 +1,123 @@
|
|||
define(['playbackManager', 'events', 'serverNotifications', 'connectionManager'], function (playbackManager, events, serverNotifications, connectionManager) {
|
||||
'use strict';
|
||||
import playbackManager from 'playbackManager';
|
||||
import events from 'events';
|
||||
import serverNotifications from 'serverNotifications';
|
||||
import connectionManager from 'connectionManager';
|
||||
|
||||
serverNotifications = serverNotifications.default || serverNotifications;
|
||||
playbackManager = playbackManager.default || playbackManager;
|
||||
function getActivePlayerId() {
|
||||
const info = playbackManager.getPlayerInfo();
|
||||
return info ? info.id : null;
|
||||
}
|
||||
|
||||
function getActivePlayerId() {
|
||||
var info = playbackManager.getPlayerInfo();
|
||||
return info ? info.id : null;
|
||||
function sendPlayCommand(apiClient, options, playType) {
|
||||
const sessionId = getActivePlayerId();
|
||||
|
||||
const ids = options.ids || options.items.map(function (i) {
|
||||
return i.Id;
|
||||
});
|
||||
|
||||
const remoteOptions = {
|
||||
ItemIds: ids.join(','),
|
||||
|
||||
PlayCommand: playType
|
||||
};
|
||||
|
||||
if (options.startPositionTicks) {
|
||||
remoteOptions.StartPositionTicks = options.startPositionTicks;
|
||||
}
|
||||
|
||||
function sendPlayCommand(apiClient, options, playType) {
|
||||
var sessionId = getActivePlayerId();
|
||||
|
||||
var ids = options.ids || options.items.map(function (i) {
|
||||
return i.Id;
|
||||
});
|
||||
|
||||
var remoteOptions = {
|
||||
ItemIds: ids.join(','),
|
||||
|
||||
PlayCommand: playType
|
||||
};
|
||||
|
||||
if (options.startPositionTicks) {
|
||||
remoteOptions.StartPositionTicks = options.startPositionTicks;
|
||||
}
|
||||
|
||||
if (options.mediaSourceId) {
|
||||
remoteOptions.MediaSourceId = options.mediaSourceId;
|
||||
}
|
||||
|
||||
if (options.audioStreamIndex != null) {
|
||||
remoteOptions.AudioStreamIndex = options.audioStreamIndex;
|
||||
}
|
||||
|
||||
if (options.subtitleStreamIndex != null) {
|
||||
remoteOptions.SubtitleStreamIndex = options.subtitleStreamIndex;
|
||||
}
|
||||
|
||||
if (options.startIndex != null) {
|
||||
remoteOptions.StartIndex = options.startIndex;
|
||||
}
|
||||
|
||||
return apiClient.sendPlayCommand(sessionId, remoteOptions);
|
||||
if (options.mediaSourceId) {
|
||||
remoteOptions.MediaSourceId = options.mediaSourceId;
|
||||
}
|
||||
|
||||
function sendPlayStateCommand(apiClient, command, options) {
|
||||
var sessionId = getActivePlayerId();
|
||||
|
||||
apiClient.sendPlayStateCommand(sessionId, command, options);
|
||||
if (options.audioStreamIndex != null) {
|
||||
remoteOptions.AudioStreamIndex = options.audioStreamIndex;
|
||||
}
|
||||
|
||||
function getCurrentApiClient(instance) {
|
||||
var currentServerId = instance.currentServerId;
|
||||
|
||||
if (currentServerId) {
|
||||
return connectionManager.getApiClient(currentServerId);
|
||||
}
|
||||
|
||||
return connectionManager.currentApiClient();
|
||||
if (options.subtitleStreamIndex != null) {
|
||||
remoteOptions.SubtitleStreamIndex = options.subtitleStreamIndex;
|
||||
}
|
||||
|
||||
function sendCommandByName(instance, name, options) {
|
||||
var command = {
|
||||
Name: name
|
||||
};
|
||||
|
||||
if (options) {
|
||||
command.Arguments = options;
|
||||
}
|
||||
|
||||
instance.sendCommand(command);
|
||||
if (options.startIndex != null) {
|
||||
remoteOptions.StartIndex = options.startIndex;
|
||||
}
|
||||
|
||||
function unsubscribeFromPlayerUpdates(instance) {
|
||||
instance.isUpdating = true;
|
||||
return apiClient.sendPlayCommand(sessionId, remoteOptions);
|
||||
}
|
||||
|
||||
var apiClient = getCurrentApiClient(instance);
|
||||
apiClient.sendMessage('SessionsStop');
|
||||
if (instance.pollInterval) {
|
||||
clearInterval(instance.pollInterval);
|
||||
instance.pollInterval = null;
|
||||
}
|
||||
function sendPlayStateCommand(apiClient, command, options) {
|
||||
const sessionId = getActivePlayerId();
|
||||
|
||||
apiClient.sendPlayStateCommand(sessionId, command, options);
|
||||
}
|
||||
|
||||
function getCurrentApiClient(instance) {
|
||||
const currentServerId = instance.currentServerId;
|
||||
|
||||
if (currentServerId) {
|
||||
return connectionManager.getApiClient(currentServerId);
|
||||
}
|
||||
|
||||
function processUpdatedSessions(instance, sessions, apiClient) {
|
||||
var serverId = apiClient.serverId();
|
||||
return connectionManager.currentApiClient();
|
||||
}
|
||||
|
||||
sessions.map(function (s) {
|
||||
if (s.NowPlayingItem) {
|
||||
s.NowPlayingItem.ServerId = serverId;
|
||||
}
|
||||
});
|
||||
function sendCommandByName(instance, name, options) {
|
||||
const command = {
|
||||
Name: name
|
||||
};
|
||||
|
||||
var currentTargetId = getActivePlayerId();
|
||||
|
||||
var session = sessions.filter(function (s) {
|
||||
return s.Id === currentTargetId;
|
||||
})[0];
|
||||
|
||||
if (session) {
|
||||
normalizeImages(session, apiClient);
|
||||
|
||||
var eventNames = getChangedEvents(instance.lastPlayerData, session);
|
||||
instance.lastPlayerData = session;
|
||||
|
||||
for (var i = 0, length = eventNames.length; i < length; i++) {
|
||||
events.trigger(instance, eventNames[i], [session]);
|
||||
}
|
||||
} else {
|
||||
instance.lastPlayerData = session;
|
||||
|
||||
playbackManager.setDefaultPlayerActive();
|
||||
}
|
||||
if (options) {
|
||||
command.Arguments = options;
|
||||
}
|
||||
|
||||
function getChangedEvents(state1, state2) {
|
||||
var names = [];
|
||||
instance.sendCommand(command);
|
||||
}
|
||||
|
||||
if (!state1) {
|
||||
names.push('statechange');
|
||||
names.push('timeupdate');
|
||||
names.push('pause');
|
||||
function unsubscribeFromPlayerUpdates(instance) {
|
||||
instance.isUpdating = true;
|
||||
|
||||
return names;
|
||||
const apiClient = getCurrentApiClient(instance);
|
||||
apiClient.sendMessage('SessionsStop');
|
||||
if (instance.pollInterval) {
|
||||
clearInterval(instance.pollInterval);
|
||||
instance.pollInterval = null;
|
||||
}
|
||||
}
|
||||
|
||||
function processUpdatedSessions(instance, sessions, apiClient) {
|
||||
const serverId = apiClient.serverId();
|
||||
|
||||
sessions.map(function (s) {
|
||||
if (s.NowPlayingItem) {
|
||||
s.NowPlayingItem.ServerId = serverId;
|
||||
}
|
||||
});
|
||||
|
||||
// TODO: Trim these down to prevent the UI from over-refreshing
|
||||
const currentTargetId = getActivePlayerId();
|
||||
|
||||
const session = sessions.filter(function (s) {
|
||||
return s.Id === currentTargetId;
|
||||
})[0];
|
||||
|
||||
if (session) {
|
||||
normalizeImages(session, apiClient);
|
||||
|
||||
const eventNames = getChangedEvents(instance.lastPlayerData, session);
|
||||
instance.lastPlayerData = session;
|
||||
|
||||
for (let i = 0, length = eventNames.length; i < length; i++) {
|
||||
events.trigger(instance, eventNames[i], [session]);
|
||||
}
|
||||
} else {
|
||||
instance.lastPlayerData = session;
|
||||
|
||||
playbackManager.setDefaultPlayerActive();
|
||||
}
|
||||
}
|
||||
|
||||
function getChangedEvents(state1, state2) {
|
||||
const names = [];
|
||||
|
||||
if (!state1) {
|
||||
names.push('statechange');
|
||||
names.push('timeupdate');
|
||||
names.push('pause');
|
||||
|
@ -134,53 +125,62 @@ define(['playbackManager', 'events', 'serverNotifications', 'connectionManager']
|
|||
return names;
|
||||
}
|
||||
|
||||
function onPollIntervalFired() {
|
||||
var instance = this;
|
||||
var apiClient = getCurrentApiClient(instance);
|
||||
if (!apiClient.isMessageChannelOpen()) {
|
||||
apiClient.getSessions().then(function (sessions) {
|
||||
processUpdatedSessions(instance, sessions, apiClient);
|
||||
});
|
||||
}
|
||||
// TODO: Trim these down to prevent the UI from over-refreshing
|
||||
names.push('statechange');
|
||||
names.push('timeupdate');
|
||||
names.push('pause');
|
||||
|
||||
return names;
|
||||
}
|
||||
|
||||
function onPollIntervalFired() {
|
||||
const instance = this;
|
||||
const apiClient = getCurrentApiClient(instance);
|
||||
if (!apiClient.isMessageChannelOpen()) {
|
||||
apiClient.getSessions().then(function (sessions) {
|
||||
processUpdatedSessions(instance, sessions, apiClient);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function subscribeToPlayerUpdates(instance) {
|
||||
instance.isUpdating = true;
|
||||
function subscribeToPlayerUpdates(instance) {
|
||||
instance.isUpdating = true;
|
||||
|
||||
var apiClient = getCurrentApiClient(instance);
|
||||
apiClient.sendMessage('SessionsStart', '100,800');
|
||||
if (instance.pollInterval) {
|
||||
clearInterval(instance.pollInterval);
|
||||
instance.pollInterval = null;
|
||||
}
|
||||
instance.pollInterval = setInterval(onPollIntervalFired.bind(instance), 5000);
|
||||
const apiClient = getCurrentApiClient(instance);
|
||||
apiClient.sendMessage('SessionsStart', '100,800');
|
||||
if (instance.pollInterval) {
|
||||
clearInterval(instance.pollInterval);
|
||||
instance.pollInterval = null;
|
||||
}
|
||||
instance.pollInterval = setInterval(onPollIntervalFired.bind(instance), 5000);
|
||||
}
|
||||
|
||||
function normalizeImages(state, apiClient) {
|
||||
if (state && state.NowPlayingItem) {
|
||||
var item = state.NowPlayingItem;
|
||||
function normalizeImages(state, apiClient) {
|
||||
if (state && state.NowPlayingItem) {
|
||||
const item = state.NowPlayingItem;
|
||||
|
||||
if (!item.ImageTags || !item.ImageTags.Primary) {
|
||||
if (item.PrimaryImageTag) {
|
||||
item.ImageTags = item.ImageTags || {};
|
||||
item.ImageTags.Primary = item.PrimaryImageTag;
|
||||
}
|
||||
}
|
||||
if (item.BackdropImageTag && item.BackdropItemId === item.Id) {
|
||||
item.BackdropImageTags = [item.BackdropImageTag];
|
||||
}
|
||||
if (item.BackdropImageTag && item.BackdropItemId !== item.Id) {
|
||||
item.ParentBackdropImageTags = [item.BackdropImageTag];
|
||||
item.ParentBackdropItemId = item.BackdropItemId;
|
||||
}
|
||||
if (!item.ServerId) {
|
||||
item.ServerId = apiClient.serverId();
|
||||
if (!item.ImageTags || !item.ImageTags.Primary) {
|
||||
if (item.PrimaryImageTag) {
|
||||
item.ImageTags = item.ImageTags || {};
|
||||
item.ImageTags.Primary = item.PrimaryImageTag;
|
||||
}
|
||||
}
|
||||
if (item.BackdropImageTag && item.BackdropItemId === item.Id) {
|
||||
item.BackdropImageTags = [item.BackdropImageTag];
|
||||
}
|
||||
if (item.BackdropImageTag && item.BackdropItemId !== item.Id) {
|
||||
item.ParentBackdropImageTags = [item.BackdropImageTag];
|
||||
item.ParentBackdropItemId = item.BackdropItemId;
|
||||
}
|
||||
if (!item.ServerId) {
|
||||
item.ServerId = apiClient.serverId();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function SessionPlayer() {
|
||||
var self = this;
|
||||
class SessionPlayer {
|
||||
constructor() {
|
||||
const self = this;
|
||||
|
||||
this.name = 'Remote Control';
|
||||
this.type = 'mediaplayer';
|
||||
|
@ -192,7 +192,7 @@ define(['playbackManager', 'events', 'serverNotifications', 'connectionManager']
|
|||
});
|
||||
}
|
||||
|
||||
SessionPlayer.prototype.beginPlayerUpdates = function () {
|
||||
beginPlayerUpdates() {
|
||||
this.playerListenerCount = this.playerListenerCount || 0;
|
||||
|
||||
if (this.playerListenerCount <= 0) {
|
||||
|
@ -202,9 +202,9 @@ define(['playbackManager', 'events', 'serverNotifications', 'connectionManager']
|
|||
}
|
||||
|
||||
this.playerListenerCount++;
|
||||
};
|
||||
}
|
||||
|
||||
SessionPlayer.prototype.endPlayerUpdates = function () {
|
||||
endPlayerUpdates() {
|
||||
this.playerListenerCount = this.playerListenerCount || 0;
|
||||
this.playerListenerCount--;
|
||||
|
||||
|
@ -212,21 +212,21 @@ define(['playbackManager', 'events', 'serverNotifications', 'connectionManager']
|
|||
unsubscribeFromPlayerUpdates(this);
|
||||
this.playerListenerCount = 0;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
SessionPlayer.prototype.getPlayerState = function () {
|
||||
getPlayerState() {
|
||||
return this.lastPlayerData || {};
|
||||
};
|
||||
}
|
||||
|
||||
SessionPlayer.prototype.getTargets = function () {
|
||||
var apiClient = getCurrentApiClient(this);
|
||||
getTargets() {
|
||||
const apiClient = getCurrentApiClient(this);
|
||||
|
||||
var sessionQuery = {
|
||||
const sessionQuery = {
|
||||
ControllableByUserId: apiClient.getCurrentUserId()
|
||||
};
|
||||
|
||||
if (apiClient) {
|
||||
var name = this.name;
|
||||
const name = this.name;
|
||||
|
||||
return apiClient.getSessions(sessionQuery).then(function (sessions) {
|
||||
return sessions.filter(function (s) {
|
||||
|
@ -243,11 +243,9 @@ define(['playbackManager', 'events', 'serverNotifications', 'connectionManager']
|
|||
isLocalPlayer: false,
|
||||
supportedCommands: s.Capabilities.SupportedCommands,
|
||||
user: s.UserId ? {
|
||||
|
||||
Id: s.UserId,
|
||||
Name: s.UserName,
|
||||
PrimaryImageTag: s.UserPrimaryImageTag
|
||||
|
||||
} : null
|
||||
};
|
||||
});
|
||||
|
@ -255,16 +253,16 @@ define(['playbackManager', 'events', 'serverNotifications', 'connectionManager']
|
|||
} else {
|
||||
return Promise.resolve([]);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
SessionPlayer.prototype.sendCommand = function (command) {
|
||||
var sessionId = getActivePlayerId();
|
||||
sendCommand(command) {
|
||||
const sessionId = getActivePlayerId();
|
||||
|
||||
var apiClient = getCurrentApiClient(this);
|
||||
const apiClient = getCurrentApiClient(this);
|
||||
apiClient.sendCommand(sessionId, command);
|
||||
};
|
||||
}
|
||||
|
||||
SessionPlayer.prototype.play = function (options) {
|
||||
play(options) {
|
||||
options = Object.assign({}, options);
|
||||
|
||||
if (options.items) {
|
||||
|
@ -276,251 +274,233 @@ define(['playbackManager', 'events', 'serverNotifications', 'connectionManager']
|
|||
}
|
||||
|
||||
return sendPlayCommand(getCurrentApiClient(this), options, 'PlayNow');
|
||||
};
|
||||
}
|
||||
|
||||
SessionPlayer.prototype.shuffle = function (item) {
|
||||
shuffle(item) {
|
||||
sendPlayCommand(getCurrentApiClient(this), { ids: [item.Id] }, 'PlayShuffle');
|
||||
};
|
||||
}
|
||||
|
||||
SessionPlayer.prototype.instantMix = function (item) {
|
||||
instantMix(item) {
|
||||
sendPlayCommand(getCurrentApiClient(this), { ids: [item.Id] }, 'PlayInstantMix');
|
||||
};
|
||||
}
|
||||
|
||||
SessionPlayer.prototype.queue = function (options) {
|
||||
queue(options) {
|
||||
sendPlayCommand(getCurrentApiClient(this), options, 'PlayNext');
|
||||
};
|
||||
}
|
||||
|
||||
SessionPlayer.prototype.queueNext = function (options) {
|
||||
queueNext(options) {
|
||||
sendPlayCommand(getCurrentApiClient(this), options, 'PlayLast');
|
||||
};
|
||||
}
|
||||
|
||||
SessionPlayer.prototype.canPlayMediaType = function (mediaType) {
|
||||
canPlayMediaType(mediaType) {
|
||||
mediaType = (mediaType || '').toLowerCase();
|
||||
return mediaType === 'audio' || mediaType === 'video';
|
||||
};
|
||||
}
|
||||
|
||||
SessionPlayer.prototype.canQueueMediaType = function (mediaType) {
|
||||
canQueueMediaType(mediaType) {
|
||||
return this.canPlayMediaType(mediaType);
|
||||
};
|
||||
}
|
||||
|
||||
SessionPlayer.prototype.stop = function () {
|
||||
stop() {
|
||||
sendPlayStateCommand(getCurrentApiClient(this), 'stop');
|
||||
};
|
||||
}
|
||||
|
||||
SessionPlayer.prototype.nextTrack = function () {
|
||||
nextTrack() {
|
||||
sendPlayStateCommand(getCurrentApiClient(this), 'nextTrack');
|
||||
};
|
||||
}
|
||||
|
||||
SessionPlayer.prototype.previousTrack = function () {
|
||||
previousTrack() {
|
||||
sendPlayStateCommand(getCurrentApiClient(this), 'previousTrack');
|
||||
};
|
||||
}
|
||||
|
||||
SessionPlayer.prototype.seek = function (positionTicks) {
|
||||
seek(positionTicks) {
|
||||
sendPlayStateCommand(getCurrentApiClient(this), 'seek',
|
||||
{
|
||||
SeekPositionTicks: positionTicks
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
SessionPlayer.prototype.currentTime = function (val) {
|
||||
currentTime(val) {
|
||||
if (val != null) {
|
||||
return this.seek(val);
|
||||
}
|
||||
|
||||
var state = this.lastPlayerData || {};
|
||||
let state = this.lastPlayerData || {};
|
||||
state = state.PlayState || {};
|
||||
return state.PositionTicks;
|
||||
};
|
||||
}
|
||||
|
||||
SessionPlayer.prototype.duration = function () {
|
||||
var state = this.lastPlayerData || {};
|
||||
duration() {
|
||||
let state = this.lastPlayerData || {};
|
||||
state = state.NowPlayingItem || {};
|
||||
return state.RunTimeTicks;
|
||||
};
|
||||
}
|
||||
|
||||
SessionPlayer.prototype.paused = function () {
|
||||
var state = this.lastPlayerData || {};
|
||||
paused() {
|
||||
let state = this.lastPlayerData || {};
|
||||
state = state.PlayState || {};
|
||||
return state.IsPaused;
|
||||
};
|
||||
}
|
||||
|
||||
SessionPlayer.prototype.getVolume = function () {
|
||||
var state = this.lastPlayerData || {};
|
||||
getVolume() {
|
||||
let state = this.lastPlayerData || {};
|
||||
state = state.PlayState || {};
|
||||
return state.VolumeLevel;
|
||||
};
|
||||
}
|
||||
|
||||
SessionPlayer.prototype.isMuted = function () {
|
||||
var state = this.lastPlayerData || {};
|
||||
isMuted() {
|
||||
let state = this.lastPlayerData || {};
|
||||
state = state.PlayState || {};
|
||||
return state.IsMuted;
|
||||
};
|
||||
}
|
||||
|
||||
SessionPlayer.prototype.pause = function () {
|
||||
pause() {
|
||||
sendPlayStateCommand(getCurrentApiClient(this), 'Pause');
|
||||
};
|
||||
}
|
||||
|
||||
SessionPlayer.prototype.unpause = function () {
|
||||
unpause() {
|
||||
sendPlayStateCommand(getCurrentApiClient(this), 'Unpause');
|
||||
};
|
||||
}
|
||||
|
||||
SessionPlayer.prototype.playPause = function () {
|
||||
playPause() {
|
||||
sendPlayStateCommand(getCurrentApiClient(this), 'PlayPause');
|
||||
};
|
||||
}
|
||||
|
||||
SessionPlayer.prototype.setMute = function (isMuted) {
|
||||
setMute(isMuted) {
|
||||
if (isMuted) {
|
||||
sendCommandByName(this, 'Mute');
|
||||
} else {
|
||||
sendCommandByName(this, 'Unmute');
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
SessionPlayer.prototype.toggleMute = function () {
|
||||
toggleMute() {
|
||||
sendCommandByName(this, 'ToggleMute');
|
||||
};
|
||||
}
|
||||
|
||||
SessionPlayer.prototype.setVolume = function (vol) {
|
||||
setVolume(vol) {
|
||||
sendCommandByName(this, 'SetVolume', {
|
||||
Volume: vol
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
SessionPlayer.prototype.volumeUp = function () {
|
||||
volumeUp() {
|
||||
sendCommandByName(this, 'VolumeUp');
|
||||
};
|
||||
}
|
||||
|
||||
SessionPlayer.prototype.volumeDown = function () {
|
||||
volumeDown() {
|
||||
sendCommandByName(this, 'VolumeDown');
|
||||
};
|
||||
}
|
||||
|
||||
SessionPlayer.prototype.toggleFullscreen = function () {
|
||||
toggleFullscreen() {
|
||||
sendCommandByName(this, 'ToggleFullscreen');
|
||||
};
|
||||
}
|
||||
|
||||
SessionPlayer.prototype.audioTracks = function () {
|
||||
var state = this.lastPlayerData || {};
|
||||
audioTracks() {
|
||||
let state = this.lastPlayerData || {};
|
||||
state = state.NowPlayingItem || {};
|
||||
var streams = state.MediaStreams || [];
|
||||
const streams = state.MediaStreams || [];
|
||||
return streams.filter(function (s) {
|
||||
return s.Type === 'Audio';
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
SessionPlayer.prototype.getAudioStreamIndex = function () {
|
||||
var state = this.lastPlayerData || {};
|
||||
getAudioStreamIndex() {
|
||||
let state = this.lastPlayerData || {};
|
||||
state = state.PlayState || {};
|
||||
return state.AudioStreamIndex;
|
||||
};
|
||||
}
|
||||
|
||||
SessionPlayer.prototype.playTrailers = function (item) {
|
||||
playTrailers(item) {
|
||||
sendCommandByName(this, 'PlayTrailers', {
|
||||
ItemId: item.Id
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
SessionPlayer.prototype.setAudioStreamIndex = function (index) {
|
||||
setAudioStreamIndex(index) {
|
||||
sendCommandByName(this, 'SetAudioStreamIndex', {
|
||||
Index: index
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
SessionPlayer.prototype.subtitleTracks = function () {
|
||||
var state = this.lastPlayerData || {};
|
||||
subtitleTracks() {
|
||||
let state = this.lastPlayerData || {};
|
||||
state = state.NowPlayingItem || {};
|
||||
var streams = state.MediaStreams || [];
|
||||
const streams = state.MediaStreams || [];
|
||||
return streams.filter(function (s) {
|
||||
return s.Type === 'Subtitle';
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
SessionPlayer.prototype.getSubtitleStreamIndex = function () {
|
||||
var state = this.lastPlayerData || {};
|
||||
getSubtitleStreamIndex() {
|
||||
let state = this.lastPlayerData || {};
|
||||
state = state.PlayState || {};
|
||||
return state.SubtitleStreamIndex;
|
||||
};
|
||||
}
|
||||
|
||||
SessionPlayer.prototype.setSubtitleStreamIndex = function (index) {
|
||||
setSubtitleStreamIndex(index) {
|
||||
sendCommandByName(this, 'SetSubtitleStreamIndex', {
|
||||
Index: index
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
SessionPlayer.prototype.getMaxStreamingBitrate = function () {
|
||||
|
||||
};
|
||||
|
||||
SessionPlayer.prototype.setMaxStreamingBitrate = function (options) {
|
||||
|
||||
};
|
||||
|
||||
SessionPlayer.prototype.isFullscreen = function () {
|
||||
|
||||
};
|
||||
|
||||
SessionPlayer.prototype.toggleFullscreen = function () {
|
||||
|
||||
};
|
||||
|
||||
SessionPlayer.prototype.getRepeatMode = function () {
|
||||
|
||||
};
|
||||
|
||||
SessionPlayer.prototype.setRepeatMode = function (mode) {
|
||||
setRepeatMode(mode) {
|
||||
sendCommandByName(this, 'SetRepeatMode', {
|
||||
RepeatMode: mode
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
SessionPlayer.prototype.setQueueShuffleMode = function (mode) {
|
||||
getRepeatMode() {
|
||||
}
|
||||
|
||||
setQueueShuffleMode(mode) {
|
||||
sendCommandByName(this, 'SetShuffleQueue', {
|
||||
ShuffleMode: mode
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
SessionPlayer.prototype.getQueueShuffleMode = function () {
|
||||
getQueueShuffleMode() {
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
SessionPlayer.prototype.displayContent = function (options) {
|
||||
displayContent(options) {
|
||||
sendCommandByName(this, 'DisplayContent', options);
|
||||
};
|
||||
}
|
||||
|
||||
SessionPlayer.prototype.isPlaying = function () {
|
||||
var state = this.lastPlayerData || {};
|
||||
isPlaying() {
|
||||
const state = this.lastPlayerData || {};
|
||||
return state.NowPlayingItem != null;
|
||||
};
|
||||
}
|
||||
|
||||
SessionPlayer.prototype.isPlayingVideo = function () {
|
||||
var state = this.lastPlayerData || {};
|
||||
isPlayingVideo() {
|
||||
let state = this.lastPlayerData || {};
|
||||
state = state.NowPlayingItem || {};
|
||||
return state.MediaType === 'Video';
|
||||
};
|
||||
}
|
||||
|
||||
SessionPlayer.prototype.isPlayingAudio = function () {
|
||||
var state = this.lastPlayerData || {};
|
||||
isPlayingAudio() {
|
||||
let state = this.lastPlayerData || {};
|
||||
state = state.NowPlayingItem || {};
|
||||
return state.MediaType === 'Audio';
|
||||
};
|
||||
}
|
||||
|
||||
SessionPlayer.prototype.getPlaylist = function () {
|
||||
getPlaylist() {
|
||||
return Promise.resolve([]);
|
||||
};
|
||||
}
|
||||
|
||||
SessionPlayer.prototype.getCurrentPlaylistItemId = function () {
|
||||
};
|
||||
getCurrentPlaylistItemId() {
|
||||
}
|
||||
|
||||
SessionPlayer.prototype.setCurrentPlaylistItem = function (playlistItemId) {
|
||||
setCurrentPlaylistItem(playlistItemId) {
|
||||
return Promise.resolve();
|
||||
};
|
||||
}
|
||||
|
||||
SessionPlayer.prototype.removeFromPlaylist = function (playlistItemIds) {
|
||||
removeFromPlaylist(playlistItemIds) {
|
||||
return Promise.resolve();
|
||||
};
|
||||
}
|
||||
|
||||
SessionPlayer.prototype.tryPair = function (target) {
|
||||
tryPair(target) {
|
||||
return Promise.resolve();
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
return SessionPlayer;
|
||||
});
|
||||
export default SessionPlayer;
|
||||
|
|
233
src/scripts/clientUtils.js
Normal file
233
src/scripts/clientUtils.js
Normal file
|
@ -0,0 +1,233 @@
|
|||
|
||||
export function getCurrentUser() {
|
||||
return window.ApiClient.getCurrentUser(false);
|
||||
}
|
||||
|
||||
//TODO: investigate url prefix support for serverAddress function
|
||||
export function serverAddress() {
|
||||
if (AppInfo.isNativeApp) {
|
||||
const apiClient = window.ApiClient;
|
||||
|
||||
if (apiClient) {
|
||||
return apiClient.serverAddress();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
const urlLower = window.location.href.toLowerCase();
|
||||
const index = urlLower.lastIndexOf('/web');
|
||||
|
||||
if (index != -1) {
|
||||
return urlLower.substring(0, index);
|
||||
}
|
||||
|
||||
const loc = window.location;
|
||||
let address = loc.protocol + '//' + loc.hostname;
|
||||
|
||||
if (loc.port) {
|
||||
address += ':' + loc.port;
|
||||
}
|
||||
|
||||
return address;
|
||||
}
|
||||
|
||||
export function getCurrentUserId() {
|
||||
const apiClient = window.ApiClient;
|
||||
|
||||
if (apiClient) {
|
||||
return apiClient.getCurrentUserId();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
export function onServerChanged(userId, accessToken, apiClient) {
|
||||
apiClient = apiClient || window.ApiClient;
|
||||
window.ApiClient = apiClient;
|
||||
}
|
||||
|
||||
export function logout() {
|
||||
ConnectionManager.logout().then(function () {
|
||||
let loginPage;
|
||||
|
||||
if (AppInfo.isNativeApp) {
|
||||
loginPage = 'selectserver.html';
|
||||
window.ApiClient = null;
|
||||
} else {
|
||||
loginPage = 'login.html';
|
||||
}
|
||||
|
||||
navigate(loginPage);
|
||||
});
|
||||
}
|
||||
|
||||
export function getConfigurationPageUrl(name) {
|
||||
return 'configurationpage?name=' + encodeURIComponent(name);
|
||||
}
|
||||
|
||||
export function getConfigurationResourceUrl(name) {
|
||||
if (AppInfo.isNativeApp) {
|
||||
return ApiClient.getUrl('web/ConfigurationPage', {
|
||||
name: name
|
||||
});
|
||||
}
|
||||
|
||||
return getConfigurationPageUrl(name);
|
||||
}
|
||||
|
||||
export function navigate(url, preserveQueryString) {
|
||||
if (!url) {
|
||||
throw new Error('url cannot be null or empty');
|
||||
}
|
||||
|
||||
const queryString = getWindowLocationSearch();
|
||||
|
||||
if (preserveQueryString && queryString) {
|
||||
url += queryString;
|
||||
}
|
||||
|
||||
return new Promise(function (resolve, reject) {
|
||||
import('appRouter').then(({default: appRouter}) => {
|
||||
return appRouter.show(url).then(resolve, reject);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
export function processPluginConfigurationUpdateResult() {
|
||||
Promise.all([
|
||||
import('loading'),
|
||||
import('toast')
|
||||
])
|
||||
.then(([{default: loading}, {default: toast}]) => {
|
||||
loading.hide();
|
||||
toast(Globalize.translate('SettingsSaved'));
|
||||
});
|
||||
}
|
||||
|
||||
export function processServerConfigurationUpdateResult(result) {
|
||||
Promise.all([
|
||||
import('loading'),
|
||||
import('toast')
|
||||
])
|
||||
.then(([{default: loading}, {default: toast}]) => {
|
||||
loading.hide();
|
||||
toast(Globalize.translate('SettingsSaved'));
|
||||
});
|
||||
}
|
||||
|
||||
export function processErrorResponse(response) {
|
||||
import('loading').then(({default: loading}) => {
|
||||
loading.hide();
|
||||
});
|
||||
|
||||
let status = '' + response.status;
|
||||
|
||||
if (response.statusText) {
|
||||
status = response.statusText;
|
||||
}
|
||||
|
||||
alert({
|
||||
title: status,
|
||||
message: response.headers ? response.headers.get('X-Application-Error-Code') : null
|
||||
});
|
||||
}
|
||||
|
||||
export function alert(options) {
|
||||
if (typeof options == 'string') {
|
||||
return void import('toast').then(({default: toast}) => {
|
||||
toast({
|
||||
text: options
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
import('alert').then(({default: alert}) => {
|
||||
alert({
|
||||
title: options.title || Globalize.translate('HeaderAlert'),
|
||||
text: options.message
|
||||
}).then(options.callback || function () {});
|
||||
});
|
||||
}
|
||||
|
||||
export function capabilities(appHost) {
|
||||
let capabilities = {
|
||||
PlayableMediaTypes: ['Audio', 'Video'],
|
||||
SupportedCommands: ['MoveUp', 'MoveDown', 'MoveLeft', 'MoveRight', 'PageUp', 'PageDown', 'PreviousLetter', 'NextLetter', 'ToggleOsd', 'ToggleContextMenu', 'Select', 'Back', 'SendKey', 'SendString', 'GoHome', 'GoToSettings', 'VolumeUp', 'VolumeDown', 'Mute', 'Unmute', 'ToggleMute', 'SetVolume', 'SetAudioStreamIndex', 'SetSubtitleStreamIndex', 'DisplayContent', 'GoToSearch', 'DisplayMessage', 'SetRepeatMode', 'SetShuffleQueue', 'ChannelUp', 'ChannelDown', 'PlayMediaSource', 'PlayTrailers'],
|
||||
SupportsPersistentIdentifier: self.appMode === 'cordova' || self.appMode === 'android',
|
||||
SupportsMediaControl: true
|
||||
};
|
||||
return Object.assign(capabilities, appHost.getPushTokenInfo());
|
||||
}
|
||||
|
||||
export function selectServer() {
|
||||
if (window.NativeShell && typeof window.NativeShell.selectServer === 'function') {
|
||||
window.NativeShell.selectServer();
|
||||
} else {
|
||||
navigate('selectserver.html');
|
||||
}
|
||||
}
|
||||
|
||||
export function hideLoadingMsg() {
|
||||
import('loading').then(({default: loading}) => {
|
||||
loading.hide();
|
||||
});
|
||||
}
|
||||
|
||||
export function showLoadingMsg() {
|
||||
import('loading').then(({default: loading}) => {
|
||||
loading.show();
|
||||
});
|
||||
}
|
||||
|
||||
export function confirm(message, title, callback) {
|
||||
import('confirm').then(({default: confirm}) => {
|
||||
confirm(message, title).then(function() {
|
||||
callback(!0);
|
||||
}).catch(function() {
|
||||
callback(!1);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// This is used in plugins and templates, so keep it defined for now.
|
||||
// TODO: Remove once plugins don't need it
|
||||
window.Dashboard = {
|
||||
alert,
|
||||
capabilities,
|
||||
confirm,
|
||||
getConfigurationPageUrl,
|
||||
getConfigurationResourceUrl,
|
||||
getCurrentUser,
|
||||
getCurrentUserId,
|
||||
hideLoadingMsg,
|
||||
logout,
|
||||
navigate,
|
||||
onServerChanged,
|
||||
processErrorResponse,
|
||||
processPluginConfigurationUpdateResult,
|
||||
processServerConfigurationUpdateResult,
|
||||
selectServer,
|
||||
serverAddress,
|
||||
showLoadingMsg
|
||||
};
|
||||
|
||||
export default {
|
||||
alert,
|
||||
capabilities,
|
||||
confirm,
|
||||
getConfigurationPageUrl,
|
||||
getConfigurationResourceUrl,
|
||||
getCurrentUser,
|
||||
getCurrentUserId,
|
||||
hideLoadingMsg,
|
||||
logout,
|
||||
navigate,
|
||||
onServerChanged,
|
||||
processErrorResponse,
|
||||
processPluginConfigurationUpdateResult,
|
||||
processServerConfigurationUpdateResult,
|
||||
selectServer,
|
||||
serverAddress,
|
||||
showLoadingMsg
|
||||
};
|
|
@ -86,7 +86,7 @@ import 'material-icons';
|
|||
if (result.TotalRecordCount) {
|
||||
nodes.push({
|
||||
id: 'livetv',
|
||||
text: globalize.translate('HeaderLiveTV'),
|
||||
text: globalize.translate('LiveTV'),
|
||||
state: {
|
||||
opened: false
|
||||
},
|
||||
|
@ -302,7 +302,7 @@ import 'material-icons';
|
|||
$(document).on('itemsaved', '.metadataEditorPage', function (e, item) {
|
||||
updateEditorNode(this, item);
|
||||
}).on('pagebeforeshow', '.metadataEditorPage', function () {
|
||||
/* eslint-disable-next-line no-unused-expressions */
|
||||
/* eslint-disable-next-line @babel/no-unused-expressions */
|
||||
import('css!assets/css/metadataeditor.css');
|
||||
}).on('pagebeforeshow', '.metadataEditorPage', function () {
|
||||
var page = this;
|
||||
|
|
|
@ -185,6 +185,12 @@ import appHost from 'apphost';
|
|||
'changezoom': () => {
|
||||
playbackManager.toggleAspectRatio();
|
||||
},
|
||||
'increaseplaybackrate': () => {
|
||||
playbackManager.increasePlaybackRate();
|
||||
},
|
||||
'decreaseplaybackrate': () => {
|
||||
playbackManager.decreasePlaybackRate();
|
||||
},
|
||||
'changeaudiotrack': () => {
|
||||
playbackManager.changeAudioStream();
|
||||
},
|
||||
|
|
|
@ -25,42 +25,42 @@ function renderItems(page, item) {
|
|||
|
||||
if (item.MovieCount) {
|
||||
sections.push({
|
||||
name: globalize.translate('TabMovies'),
|
||||
name: globalize.translate('Movies'),
|
||||
type: 'Movie'
|
||||
});
|
||||
}
|
||||
|
||||
if (item.SeriesCount) {
|
||||
sections.push({
|
||||
name: globalize.translate('TabShows'),
|
||||
name: globalize.translate('Shows'),
|
||||
type: 'Series'
|
||||
});
|
||||
}
|
||||
|
||||
if (item.EpisodeCount) {
|
||||
sections.push({
|
||||
name: globalize.translate('TabEpisodes'),
|
||||
name: globalize.translate('Episodes'),
|
||||
type: 'Episode'
|
||||
});
|
||||
}
|
||||
|
||||
if (item.TrailerCount) {
|
||||
sections.push({
|
||||
name: globalize.translate('TabTrailers'),
|
||||
name: globalize.translate('Trailers'),
|
||||
type: 'Trailer'
|
||||
});
|
||||
}
|
||||
|
||||
if (item.AlbumCount) {
|
||||
sections.push({
|
||||
name: globalize.translate('TabAlbums'),
|
||||
name: globalize.translate('Albums'),
|
||||
type: 'MusicAlbum'
|
||||
});
|
||||
}
|
||||
|
||||
if (item.MusicVideoCount) {
|
||||
sections.push({
|
||||
name: globalize.translate('TabMusicVideos'),
|
||||
name: globalize.translate('HeaderMusicVideos'),
|
||||
type: 'MusicVideo'
|
||||
});
|
||||
}
|
||||
|
|
|
@ -155,7 +155,7 @@ export function enable() {
|
|||
function attachGamepadScript(e) {
|
||||
console.log('Gamepad connected! Attaching gamepadtokey.js script');
|
||||
window.removeEventListener('gamepadconnected', attachGamepadScript);
|
||||
/* eslint-disable-next-line no-unused-expressions */
|
||||
/* eslint-disable-next-line @babel/no-unused-expressions */
|
||||
import('scripts/gamepadtokey');
|
||||
}
|
||||
|
||||
|
|
|
@ -105,11 +105,11 @@ export function getQueryPagingHtml (options) {
|
|||
}
|
||||
|
||||
if (options.sortButton) {
|
||||
html += '<button is="paper-icon-button-light" class="btnSort autoSize" title="' + globalize.translate('ButtonSort') + '"><span class="material-icons sort_by_alpha"></span></button>';
|
||||
html += '<button is="paper-icon-button-light" class="btnSort autoSize" title="' + globalize.translate('Sort') + '"><span class="material-icons sort_by_alpha"></span></button>';
|
||||
}
|
||||
|
||||
if (options.filterButton) {
|
||||
html += '<button is="paper-icon-button-light" class="btnFilter autoSize" title="' + globalize.translate('ButtonFilter') + '"><span class="material-icons filter_list"></span></button>';
|
||||
html += '<button is="paper-icon-button-light" class="btnFilter autoSize" title="' + globalize.translate('Filter') + '"><span class="material-icons filter_list"></span></button>';
|
||||
}
|
||||
|
||||
html += '</div>';
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue