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

Merge remote-tracking branch 'upstream/master' into details-placeholder

This commit is contained in:
MrTimscampi 2020-02-12 09:10:42 +01:00
commit 1f91034aa9
94 changed files with 1550 additions and 1312 deletions

View file

@ -107,19 +107,11 @@
bottom: 1%;
}
.alphaPicker-fixed-left {
left: 0.4em;
}
.alphaPicker-fixed-right {
right: 0.4em;
}
@media all and (min-width: 62.5em) {
.alphaPicker-fixed-left {
left: 1em;
}
.alphaPicker-fixed-right {
right: 1em;
}

View file

@ -545,13 +545,18 @@ define(['loading', 'globalize', 'events', 'viewManager', 'layoutManager', 'skinM
page.back();
}
/**
* Pages of "no return" (when "Go back" should behave differently, probably quitting the application).
*/
var startPages = ['home', 'login', 'selectserver'];
function canGoBack() {
var curr = current();
if (!curr) {
return false;
}
if (curr.type === 'home') {
if (!document.querySelector('.dialogContainer') && startPages.indexOf(curr.type) !== -1) {
return false;
}
return page.canGoBack();

View file

@ -2,24 +2,18 @@ define(['browser', 'css!./appfooter'], function (browser) {
'use strict';
function render(options) {
var elem = document.createElement('div');
elem.classList.add('appfooter');
elem.classList.add('appfooter-blurred');
document.body.appendChild(elem);
return elem;
}
function appFooter(options) {
var self = this;
self.element = render(options);
self.add = function (elem) {
self.element.appendChild(elem);
};

View file

@ -104,7 +104,7 @@ define(["appSettings", "browser", "events", "htmlMediaHelper"], function (appSet
function getDeviceName() {
var deviceName;
deviceName = browser.tizen ? "Samsung Smart TV" : browser.web0s ? "LG Smart TV" : browser.operaTv ? "Opera TV" : browser.xboxOne ? "Xbox One" : browser.ps4 ? "Sony PS4" : browser.chrome ? "Chrome" : browser.edge ? "Edge" : browser.firefox ? "Firefox" : browser.msie ? "Internet Explorer" : browser.opera ? "Opera" : "Web Browser";
deviceName = browser.tizen ? "Samsung Smart TV" : browser.web0s ? "LG Smart TV" : browser.operaTv ? "Opera TV" : browser.xboxOne ? "Xbox One" : browser.ps4 ? "Sony PS4" : browser.chrome ? "Chrome" : browser.edge ? "Edge" : browser.firefox ? "Firefox" : browser.msie ? "Internet Explorer" : browser.opera ? "Opera" : browser.safari ? "Safari" : "Web Browser";
if (browser.ipad) {
deviceName += " iPad";
@ -299,6 +299,52 @@ define(["appSettings", "browser", "events", "htmlMediaHelper"], function (appSet
return features;
}();
/**
* Do exit according to platform
*/
function doExit() {
try {
if (window.NativeShell) {
window.NativeShell.AppHost.exit();
} else if (browser.tizen) {
tizen.application.getCurrentApplication().exit();
} else if (browser.web0s) {
webOS.platformBack();
} else {
window.close();
}
} catch (err) {
console.log("error closing application: " + err);
}
}
var exitPromise;
/**
* Ask user for exit
*/
function askForExit() {
if (!!exitPromise) {
return;
}
require(["actionsheet"], function (actionsheet) {
exitPromise = actionsheet.show({
title: Globalize.translate("MessageConfirmAppExit"),
items: [
{id: "yes", name: Globalize.translate("Yes")},
{id: "no", name: Globalize.translate("No")}
]
}).then(function (value) {
if (value === "yes") {
doExit();
}
}).finally(function () {
exitPromise = null;
});
});
}
var deviceId;
var deviceName;
var appName = "Jellyfin Web";
@ -314,16 +360,10 @@ define(["appSettings", "browser", "events", "htmlMediaHelper"], function (appSet
alert("setWindowState is not supported and should not be called");
},
exit: function () {
if (window.NativeShell) {
window.NativeShell.AppHost.exit();
} else if (browser.tizen) {
try {
tizen.application.getCurrentApplication().exit();
} catch (err) {
console.log("error closing application: " + err);
}
if (!!window.appMode && browser.tizen) {
askForExit();
} else {
window.close();
doExit();
}
},
supports: function (command) {

View file

@ -686,6 +686,13 @@ define(['appSettings', 'userSettings', 'playbackManager', 'connectionManager', '
});
}
if (options.items.length > 1 && options && options.ids) {
// Use the original request id array for sorting the result in the proper order
options.items.sort(function (a, b) {
return options.ids.indexOf(a.Id) - options.ids.indexOf(b.Id);
});
}
return this._castPlayer.loadMedia(options, command);
};

View file

@ -180,6 +180,7 @@ define(['require', 'browser', 'layoutManager', 'appSettings', 'pluginManager', '
context.querySelector('#chkThemeSong').checked = userSettings.enableThemeSongs();
context.querySelector('#chkThemeVideo').checked = userSettings.enableThemeVideos();
context.querySelector('#chkFadein').checked = userSettings.enableFastFadein();
context.querySelector('#chkBackdrops').checked = userSettings.enableBackdrops();
context.querySelector('#selectLanguage').value = userSettings.language() || '';
@ -216,6 +217,7 @@ define(['require', 'browser', 'layoutManager', 'appSettings', 'pluginManager', '
userSettingsInstance.skin(context.querySelector('.selectSkin').value);
userSettingsInstance.enableFastFadein(context.querySelector('#chkFadein').checked);
userSettingsInstance.enableBackdrops(context.querySelector('#chkBackdrops').checked);
if (user.Id === apiClient.getCurrentUserId()) {

View file

@ -3,6 +3,7 @@
<h2 class="sectionTitle">
${Display}
</h2>
<div class="selectContainer languageSection hide">
<select id="selectLanguage" is="emby-select" label="${LabelDisplayLanguage}">
<option value="">${Auto}</option>
@ -133,6 +134,7 @@
<div class="selectContainer selectDashboardThemeContainer hide">
<select id="selectDashboardTheme" is="emby-select" label="${LabelDashboardTheme}"></select>
</div>
<div class="selectContainer hide selectScreensaverContainer">
<select is="emby-select" class="selectScreensaver" label="${LabelScreensaver}"></select>
</div>
@ -141,6 +143,14 @@
<select is="emby-select" class="selectSoundEffects" label="${LabelSoundEffects}"></select>
</div>
<div class="checkboxContainer checkboxContainer-withDescription fldFadein">
<label>
<input type="checkbox" is="emby-checkbox" id="chkFadein" />
<span>${EnableFastImageFadeIn}</span>
</label>
<div class="fieldDescription checkboxFieldDescription">${EnableFastImageFadeInHelp}</div>
</div>
<div class="checkboxContainer checkboxContainer-withDescription fldBackdrops hide">
<label>
<input type="checkbox" is="emby-checkbox" id="chkBackdrops" />
@ -148,6 +158,7 @@
</label>
<div class="fieldDescription checkboxFieldDescription">${EnableBackdropsHelp}</div>
</div>
<div class="checkboxContainer checkboxContainer-withDescription fldThemeSong hide">
<label>
<input type="checkbox" is="emby-checkbox" id="chkThemeSong" />
@ -155,6 +166,7 @@
</label>
<div class="fieldDescription checkboxFieldDescription">${EnableThemeSongsHelp}</div>
</div>
<div class="checkboxContainer checkboxContainer-withDescription fldThemeVideo hide">
<label>
<input type="checkbox" is="emby-checkbox" id="chkThemeVideo" />

View file

@ -13,6 +13,11 @@
margin-right: 1.2em;
}
.servers > .card > .cardBox {
margin-left: 0.6em;
margin-right: 0.6em;
}
.layout-tv .emby-scroller,
.layout-mobile .emby-scroller {
padding-left: 3.3%;

View file

@ -1,4 +1,7 @@
.emby-tab-button {
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
background: transparent;
box-shadow: none;
cursor: pointer;
@ -10,7 +13,7 @@
vertical-align: middle;
flex-shrink: 0;
margin: 0;
padding: 1em 0.9em;
padding: 1.5em;
position: relative;
height: auto;
min-width: initial;
@ -31,6 +34,10 @@
overflow: hidden;
}
.layout-mobile .emby-tabs-slider {
overflow: auto;
}
.tabContent:not(.is-active) {
display: none;
}

View file

@ -1,4 +1,4 @@
define(['browser', 'require', 'events', 'apphost', 'loading', 'dom', 'playbackManager', 'appRouter', 'appSettings', 'connectionManager', 'htmlMediaHelper', 'itemHelper', 'fullscreenManager'], function (browser, require, events, appHost, loading, dom, playbackManager, appRouter, appSettings, connectionManager, htmlMediaHelper, itemHelper, fullscreenManager) {
define(['browser', 'require', 'events', 'apphost', 'loading', 'dom', 'playbackManager', 'appRouter', 'appSettings', 'connectionManager', 'htmlMediaHelper', 'itemHelper', 'fullscreenManager', 'globalize'], function (browser, require, events, appHost, loading, dom, playbackManager, appRouter, appSettings, connectionManager, htmlMediaHelper, itemHelper, fullscreenManager, globalize) {
"use strict";
var mediaManager;
@ -1855,7 +1855,7 @@ define(['browser', 'require', 'events', 'apphost', 'loading', 'dom', 'playbackMa
if (protocol) {
mediaCategory.stats.push({
label: 'Protocol:',
label: globalize.translate("LabelProtocol"),
value: protocol
});
}
@ -1865,12 +1865,12 @@ define(['browser', 'require', 'events', 'apphost', 'loading', 'dom', 'playbackMa
if (this._hlsPlayer || this._shakaPlayer) {
mediaCategory.stats.push({
label: 'Stream type:',
label: globalize.translate("LabelStreamType"),
value: 'HLS'
});
} else {
mediaCategory.stats.push({
label: 'Stream type:',
label: globalize.translate("LabelStreamType"),
value: 'Video'
});
}
@ -1882,13 +1882,13 @@ define(['browser', 'require', 'events', 'apphost', 'loading', 'dom', 'playbackMa
categories.push(videoCategory);
var rect = mediaElement.getBoundingClientRect ? mediaElement.getBoundingClientRect() : {};
var height = rect.height;
var width = rect.width;
var height = parseInt(rect.height);
var width = parseInt(rect.width);
// Don't show player dimensions on smart TVs because the app UI could be lower resolution than the video and this causes users to think there is a problem
if (width && height && !browser.tv) {
videoCategory.stats.push({
label: 'Player dimensions:',
label: globalize.translate("LabelPlayerDimensions"),
value: width + 'x' + height
});
}
@ -1898,7 +1898,7 @@ define(['browser', 'require', 'events', 'apphost', 'loading', 'dom', 'playbackMa
if (width && height) {
videoCategory.stats.push({
label: 'Video resolution:',
label: globalize.translate("LabelVideoResolution"),
value: width + 'x' + height
});
}
@ -1908,13 +1908,13 @@ define(['browser', 'require', 'events', 'apphost', 'loading', 'dom', 'playbackMa
var droppedVideoFrames = playbackQuality.droppedVideoFrames || 0;
videoCategory.stats.push({
label: 'Dropped frames:',
label: globalize.translate("LabelDroppedFrames"),
value: droppedVideoFrames
});
var corruptedVideoFrames = playbackQuality.corruptedVideoFrames || 0;
videoCategory.stats.push({
label: 'Corrupted frames:',
label: globalize.translate("LabelCorruptedFrames"),
value: corruptedVideoFrames
});
}

View file

@ -1,4 +1,4 @@
define(['lazyLoader', 'imageFetcher', 'layoutManager', 'browser', 'appSettings', 'require', 'css!./style'], function (lazyLoader, imageFetcher, layoutManager, browser, appSettings, require) {
define(['lazyLoader', 'imageFetcher', 'layoutManager', 'browser', 'appSettings', 'userSettings', 'require', 'css!./style'], function (lazyLoader, imageFetcher, layoutManager, browser, appSettings, userSettings, require) {
'use strict';
var requestIdleCallback = window.requestIdleCallback || function (fn) {
@ -7,9 +7,6 @@ define(['lazyLoader', 'imageFetcher', 'layoutManager', 'browser', 'appSettings',
var self = {};
// seeing slow performance with firefox
var enableFade = false;
function fillImage(elem, source, enableEffects) {
if (!elem) {
@ -30,7 +27,7 @@ define(['lazyLoader', 'imageFetcher', 'layoutManager', 'browser', 'appSettings',
function fillImageElement(elem, source, enableEffects) {
imageFetcher.loadImage(elem, source).then(function () {
if (enableFade && enableEffects !== false) {
if (enableEffects !== false) {
fadeIn(elem);
}
@ -39,10 +36,11 @@ define(['lazyLoader', 'imageFetcher', 'layoutManager', 'browser', 'appSettings',
}
function fadeIn(elem) {
var cssClass = 'lazy-image-fadein';
elem.classList.add(cssClass);
if (userSettings.enableFastFadein()) {
elem.classList.add('lazy-image-fadein-fast');
} else {
elem.classList.add('lazy-image-fadein');
}
}
function lazyChildren(elem) {

View file

@ -346,22 +346,25 @@ define(["apphost", "globalize", "connectionManager", "itemHelper", "appRouter",
break;
case "copy-stream":
var downloadHref = apiClient.getItemDownloadUrl(itemId);
var textArea = document.createElement("textarea");
textArea.value = downloadHref;
document.body.appendChild(textArea);
textArea.focus();
textArea.select();
try {
document.execCommand("copy");
navigator.clipboard.writeText(downloadHref).then(function () {
require(["toast"], function (toast) {
toast(globalize.translate("CopyStreamURLSuccess"));
});
} catch (err) {
console.error("Failed to copy to clipboard");
}
document.body.removeChild(textArea);
}, function () {
var textArea = document.createElement("textarea");
textArea.value = downloadHref;
document.body.appendChild(textArea);
textArea.focus();
textArea.select();
if (document.execCommand("copy")) {
require(["toast"], function (toast) {
toast(globalize.translate("CopyStreamURLSuccess"));
});
} else {
prompt(globalize.translate("CopyStreamURL"), downloadHref);
}
document.body.removeChild(textArea);
});
getResolveFunction(resolve, id)();
break;
case "editsubtitles":

View file

@ -36,6 +36,11 @@ define(["inputManager", "layoutManager"], function (inputManager, layoutManager)
10252: "MediaPlayPause"
};
/**
* Keys used for keyboard navigation.
*/
var NavigationKeys = ["ArrowLeft", "ArrowRight", "ArrowUp", "ArrowDown"];
var hasFieldKey = false;
try {
hasFieldKey = "key" in new KeyboardEvent("keydown");
@ -60,11 +65,28 @@ define(["inputManager", "layoutManager"], function (inputManager, layoutManager)
return KeyNames[event.keyCode] || event.key;
}
/**
* Returns _true_ if key is used for navigation.
*
* @param {string} key name
* @return {boolean} _true_ if key is used for navigation
*/
function isNavigationKey(key) {
return NavigationKeys.indexOf(key) != -1;
}
function enable() {
document.addEventListener("keydown", function (e) {
var key = getKeyName(e);
// Ignore navigation keys for non-TV
if (!layoutManager.tv && isNavigationKey(key)) {
return;
}
var capture = true;
switch (getKeyName(e)) {
switch (key) {
case "ArrowLeft":
inputManager.handle("left");
break;
@ -128,6 +150,7 @@ define(["inputManager", "layoutManager"], function (inputManager, layoutManager)
return {
enable: enable,
getKeyName: getKeyName
getKeyName: getKeyName,
isNavigationKey: isNavigationKey
};
});

View file

@ -111,6 +111,10 @@
text-overflow: ellipsis;
}
.layout-desktop .listItemBodyText {
margin: 0.25em 0 0 0;
}
.listItemBodyText-nowrap {
white-space: nowrap;
}
@ -162,13 +166,14 @@
@media all and (max-width: 64em) {
.listItemImage-large {
width: 33.75vw;
height: 22.5vw;
width: 22vw;
height: 16vw;
margin-right: 0 !important;
}
.listItemIndicators,
.listItemImageButton {
font-size: 1em !important;
font-size: 0.6em !important;
}
.listItemBody {

View file

@ -471,6 +471,8 @@ define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutMan
html += indicators.getTimerIndicator(item).replace('indicatorIcon', 'indicatorIcon listItemAside');
}
html += '<div class="listViewUserDataButtons">';
if (!clickEntireItem) {
if (options.addToListButton) {
@ -491,8 +493,6 @@ define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutMan
if (options.enableUserDataButtons !== false) {
html += '<span class="listViewUserDataButtons flex align-items-center">';
var userData = item.UserData || {};
var likes = userData.Likes == null ? '' : userData.Likes;
@ -503,10 +503,9 @@ define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutMan
if (itemHelper.canRate(item)) {
html += '<button is="emby-ratingbutton" type="button" class="listItemButton paper-icon-button-light" data-id="' + item.Id + '" data-serverid="' + item.ServerId + '" data-itemtype="' + item.Type + '" data-likes="' + likes + '" data-isfavorite="' + (userData.IsFavorite) + '"><i class="material-icons">favorite</i></button>';
}
html += '</span>';
}
}
html += '</div>';
if (enableContentWrapper) {
html += '</div>';

Binary file not shown.

Before

Width:  |  Height:  |  Size: 39 KiB

View file

@ -160,7 +160,7 @@ define(["pluginManager"], function (pluginManager) {
elem.classList.add("logoScreenSaver");
document.body.appendChild(elem);
elem.innerHTML = '<img class="logoScreenSaverImage" src="' + pluginManager.mapPath(self, "assets/img/banner-light.png") + '" />';
elem.innerHTML = '<img class="logoScreenSaverImage" src="assets/img/banner-light.png" />';
}
stopInterval();

View file

@ -385,16 +385,13 @@ define(['datetime', 'globalize', 'appRouter', 'itemHelper', 'indicators', 'mater
}
function getStarIconsHtml(item) {
var html = '';
var rating = item.CommunityRating;
if (rating) {
if (item.CommunityRating) {
html += '<div class="starRatingContainer mediaInfoItem">';
html += '<i class="material-icons starIcon">star</i>';
html += rating;
html += item.CommunityRating.toFixed(1);
html += '</div>';
}

View file

@ -392,20 +392,7 @@ define(["dom", "browser", "layoutManager"], function (dom, browser, layoutManage
* Returns true if scroll manager is enabled.
*/
var isEnabled = function() {
if (!layoutManager.tv) {
return false;
}
if (browser.tizen) {
return true;
}
if (browser.web0s) {
return true;
}
return false;
return layoutManager.tv;
};
/**

View file

@ -212,13 +212,15 @@ define(['dialogHelper', 'inputManager', 'connectionManager', 'layoutManager', 'f
// Optional parameters
direction: 'horizontal',
loop: options.loop !== false,
autoplay: options.interval || 8000,
autoplay: {
delay: options.interval || 8000
},
// Disable preloading of all images
preloadImages: false,
// Enable lazy loading
lazyLoading: true,
lazyLoadingInPrevNext: true,
autoplayDisableOnInteraction: false,
lazy: true,
loadPrevNext: true,
disableOnInteraction: false,
initialSlide: options.startIndex || 0,
speed: 240
});

View file

@ -104,24 +104,17 @@ define(['playbackManager', 'userSettings', 'alphaPicker', 'alphaNumericShortcuts
}
function showSortMenu() {
var instance = this;
require(['sortMenu'], function (SortMenu) {
new SortMenu().show({
settingsKey: instance.getSettingsKey(),
settings: instance.getSortValues(),
onChange: instance.itemsContainer.refreshItems.bind(instance.itemsContainer),
serverId: instance.params.serverId,
sortOptions: instance.getSortMenuOptions()
}).then(function () {
updateSortText(instance);
updateAlphaPickerState(instance);
instance.itemsContainer.refreshItems();
});
});