-
diff --git a/src/controllers/playback/video/index.js b/src/controllers/playback/video/index.js
index 420268ea75..5da8ec45d8 100644
--- a/src/controllers/playback/video/index.js
+++ b/src/controllers/playback/video/index.js
@@ -21,50 +21,6 @@ import 'css!assets/css/videoosd';
/* eslint-disable indent */
- function seriesImageUrl(item, options) {
- if (item.Type !== 'Episode') {
- return null;
- }
-
- options = options || {};
- options.type = options.type || 'Primary';
- if (options.type === 'Primary' && item.SeriesPrimaryImageTag) {
- options.tag = item.SeriesPrimaryImageTag;
- return connectionManager.getApiClient(item.ServerId).getScaledImageUrl(item.SeriesId, options);
- }
-
- if (options.type === 'Thumb') {
- if (item.SeriesThumbImageTag) {
- options.tag = item.SeriesThumbImageTag;
- return connectionManager.getApiClient(item.ServerId).getScaledImageUrl(item.SeriesId, options);
- }
-
- if (item.ParentThumbImageTag) {
- options.tag = item.ParentThumbImageTag;
- return connectionManager.getApiClient(item.ServerId).getScaledImageUrl(item.ParentThumbItemId, options);
- }
- }
-
- return null;
- }
-
- function imageUrl(item, options) {
- options = options || {};
- options.type = options.type || 'Primary';
-
- if (item.ImageTags && item.ImageTags[options.type]) {
- options.tag = item.ImageTags[options.type];
- return connectionManager.getApiClient(item.ServerId).getScaledImageUrl(item.PrimaryImageItemId || item.Id, options);
- }
-
- if (options.type === 'Primary' && item.AlbumId && item.AlbumPrimaryImageTag) {
- options.tag = item.AlbumPrimaryImageTag;
- return connectionManager.getApiClient(item.ServerId).getScaledImageUrl(item.AlbumId, options);
- }
-
- return null;
- }
-
function getOpenedDialog() {
return document.querySelector('.dialogContainer .dialog.opened');
}
@@ -164,7 +120,6 @@ import 'css!assets/css/videoosd';
currentItem = item;
const displayItem = itemInfo.displayItem || item;
updateRecordingButton(displayItem);
- setPoster(displayItem, item);
let parentName = displayItem.SeriesName || displayItem.Album;
if (displayItem.EpisodeTitle || displayItem.IsSeries) {
@@ -172,42 +127,6 @@ import 'css!assets/css/videoosd';
}
setTitle(displayItem, parentName);
- const titleElement = view.querySelector('.osdTitle');
- let displayName = itemHelper.getDisplayName(displayItem, {
- includeParentInfo: displayItem.Type !== 'Program',
- includeIndexNumber: displayItem.Type !== 'Program'
- });
-
- if (!displayName) {
- displayName = displayItem.Type;
- }
-
- titleElement.innerHTML = displayName;
-
- if (displayName) {
- titleElement.classList.remove('hide');
- } else {
- titleElement.classList.add('hide');
- }
-
- const mediaInfoHtml = mediaInfo.getPrimaryMediaInfoHtml(displayItem, {
- runtime: false,
- subtitles: false,
- tomatoes: false,
- endsAt: false,
- episodeTitle: false,
- originalAirDate: displayItem.Type !== 'Program',
- episodeTitleIndexNumber: displayItem.Type !== 'Program',
- programIndicator: false
- });
- const osdMediaInfo = view.querySelector('.osdMediaInfo');
- osdMediaInfo.innerHTML = mediaInfoHtml;
-
- if (mediaInfoHtml) {
- osdMediaInfo.classList.remove('hide');
- } else {
- osdMediaInfo.classList.add('hide');
- }
const secondaryMediaInfo = view.querySelector('.osdSecondaryMediaInfo');
const secondaryMediaInfoHtml = mediaInfo.getSecondaryMediaInfoHtml(displayItem, {
@@ -222,12 +141,6 @@ import 'css!assets/css/videoosd';
secondaryMediaInfo.classList.add('hide');
}
- if (displayName) {
- view.querySelector('.osdMainTextContainer').classList.remove('hide');
- } else {
- view.querySelector('.osdMainTextContainer').classList.add('hide');
- }
-
if (enableProgressByTimeOfDay) {
setDisplayTime(startTimeText, displayItem.StartDate);
setDisplayTime(endTimeText, displayItem.EndDate);
@@ -277,7 +190,6 @@ import 'css!assets/css/videoosd';
currentItem = item;
if (!item) {
- setPoster(null);
updateRecordingButton(null);
Emby.Page.setTitle('');
nowPlayingVolumeSlider.disabled = true;
@@ -314,7 +226,20 @@ import 'css!assets/css/videoosd';
}
function setTitle(item, parentName) {
- Emby.Page.setTitle(parentName || '');
+ let itemName = itemHelper.getDisplayName(item, {
+ includeParentInfo: item.Type !== 'Program',
+ includeIndexNumber: item.Type !== 'Program'
+ });
+
+ if (itemName && parentName) {
+ itemName = `${parentName} - ${itemName}`;
+ }
+
+ if (!itemName) {
+ itemName = parentName || '';
+ }
+
+ Emby.Page.setTitle(itemName);
const documentTitle = parentName || (item ? item.Name : null);
@@ -323,38 +248,6 @@ import 'css!assets/css/videoosd';
}
}
- function setPoster(item, secondaryItem) {
- const osdPoster = view.querySelector('.osdPoster');
-
- if (item) {
- let imgUrl = seriesImageUrl(item, {
- maxWidth: osdPoster.clientWidth,
- type: 'Primary'
- }) || seriesImageUrl(item, {
- maxWidth: osdPoster.clientWidth,
- type: 'Thumb'
- }) || imageUrl(item, {
- maxWidth: osdPoster.clientWidth,
- type: 'Primary'
- });
-
- if (!imgUrl && secondaryItem && (imgUrl = seriesImageUrl(secondaryItem, {
- maxWidth: osdPoster.clientWidth,
- type: 'Primary'
- }) || seriesImageUrl(secondaryItem, {
- maxWidth: osdPoster.clientWidth,
- type: 'Thumb'
- }) || imageUrl(secondaryItem, {
- maxWidth: osdPoster.clientWidth,
- type: 'Primary'
- })), imgUrl) {
- return void (osdPoster.innerHTML = '

');
- }
- }
-
- osdPoster.innerHTML = '';
- }
-
let mouseIsDown = false;
function showOsd() {
From 3f592881583d18025f8475b58e3f2366a56225e4 Mon Sep 17 00:00:00 2001
From: MrTimscampi
Date: Thu, 20 Aug 2020 20:39:33 +0200
Subject: [PATCH 019/365] Improve Up Next dialog
---
src/assets/css/videoosd.css | 51 +++++---------------
src/components/mediainfo/mediainfo.js | 12 ++---
src/components/upnextdialog/upnextdialog.css | 23 +++++++--
src/components/upnextdialog/upnextdialog.js | 13 +++--
4 files changed, 44 insertions(+), 55 deletions(-)
diff --git a/src/assets/css/videoosd.css b/src/assets/css/videoosd.css
index 7273121f53..9995a7ff84 100644
--- a/src/assets/css/videoosd.css
+++ b/src/assets/css/videoosd.css
@@ -6,18 +6,29 @@
-ms-user-select: none;
}
-.osdPoster img,
.videoOsdBottom {
bottom: 0;
left: 0;
right: 0;
+ position: fixed;
+ background: linear-gradient(0deg, rgba(16, 16, 16, 0.6) 0%, rgba(16, 16, 16, 0) 100%);
+ padding-top: 7.5em;
+ padding-bottom: 1.75em;
+ display: flex;
+ flex-direction: row;
+ justify-content: center;
+ will-change: opacity;
+ transition: opacity 0.3s ease-out;
+ color: #fff;
+ user-select: none;
+ -webkit-touch-callout: none;
}
.osdHeader {
transition: opacity 0.3s ease-out;
position: relative;
z-index: 1;
- background: linear-gradient(180deg, rgba(16, 16 16, 0.75) 0%, rgba(16, 16, 16, 0.15) 80%, rgba(16, 16, 16, 0) 100%);
+ background: linear-gradient(180deg, rgba(16, 16, 16, 0.6) 0%, rgba(16, 16, 16, 0) 100%);
backdrop-filter: none;
color: #eee;
height: 7.5em;
@@ -88,21 +99,6 @@
opacity: 0.6;
}
-.videoOsdBottom {
- position: fixed;
- background: linear-gradient(0deg, rgba(16, 16, 16, 0.75) 0%, rgba(16, 16, 16, 0.15) 80%, rgba(16, 16, 16, 0) 100%);
- padding-top: 10em;
- padding-bottom: 1.75em;
- display: flex;
- flex-direction: row;
- justify-content: center;
- will-change: opacity;
- transition: opacity 0.3s ease-out;
- color: #fff;
- user-select: none;
- -webkit-touch-callout: none;
-}
-
.videoOsdBottom-hidden {
opacity: 0;
}
@@ -157,27 +153,6 @@
user-select: none;
}
-.osdPoster {
- width: 10%;
- position: relative;
- margin-right: 0.5em;
-}
-
-.osdPoster img {
- position: absolute;
- height: auto;
- width: 100%;
- -webkit-box-shadow: 0 0 1.9vh #000;
- box-shadow: 0 0 1.9vh #000;
- border: 0.08em solid #222;
- user-drag: none;
- user-select: none;
- -moz-user-select: none;
- -webkit-user-drag: none;
- -webkit-user-select: none;
- -ms-user-select: none;
-}
-
.osdTitle,
.osdTitleSmall {
margin: 0 1em 0 0;
diff --git a/src/components/mediainfo/mediainfo.js b/src/components/mediainfo/mediainfo.js
index 1d78d490a2..d5da29d3bc 100644
--- a/src/components/mediainfo/mediainfo.js
+++ b/src/components/mediainfo/mediainfo.js
@@ -100,11 +100,10 @@ import 'emby-button';
return html;
}
- export function getMediaInfoHtml(item, options) {
+ export function getMediaInfoHtml(item, options = {}) {
let html = '';
const miscInfo = [];
- options = options || {};
let text;
let date;
let minutes;
@@ -289,7 +288,9 @@ import 'emby-button';
return getMediaInfoItem(m);
}).join('');
- html += getStarIconsHtml(item);
+ if (options.starRating !== false) {
+ html += getStarIconsHtml(item);
+ }
if (item.HasSubtitles && options.subtitles !== false) {
html += 'CC
';
@@ -418,9 +419,8 @@ import 'emby-button';
return false;
}
- export function getPrimaryMediaInfoHtml(item, options) {
- options = options || {};
- if (options.interactive == null) {
+ export function getPrimaryMediaInfoHtml(item, options = {}) {
+ if (options.interactive === undefined) {
options.interactive = false;
}
diff --git a/src/components/upnextdialog/upnextdialog.css b/src/components/upnextdialog/upnextdialog.css
index 067804919f..754fd418ca 100644
--- a/src/components/upnextdialog/upnextdialog.css
+++ b/src/components/upnextdialog/upnextdialog.css
@@ -1,9 +1,24 @@
-.upNextDialog {
- width: 30vw;
+.upNextContainer {
+ box-sizing: border-box;
position: fixed;
- left: auto;
+ top: 0;
bottom: 0;
- right: 0;
+ left: 50%;
+ transform: translateX(-50%);
+ padding: 1em;
+ display: flex;
+ flex-grow: 1;
+ width: calc(100vh * (16 / 9));
+ height: 100vh;
+ justify-content: end;
+ align-items: flex-end;
+}
+
+.upNextDialog-container {
+ border-radius: 5px;
+ width: 30em;
+ height: 11em;
+ left: auto;
padding: 1%;
display: flex;
flex-direction: column;
diff --git a/src/components/upnextdialog/upnextdialog.js b/src/components/upnextdialog/upnextdialog.js
index c665d81173..8d3202cc1c 100644
--- a/src/components/upnextdialog/upnextdialog.js
+++ b/src/components/upnextdialog/upnextdialog.js
@@ -17,9 +17,7 @@ import 'flexStyles';
function getHtml() {
let html = '';
- html += '';
- html += '
';
-
+ html += '';
html += '
';
html += '
';
@@ -29,8 +27,6 @@ import 'flexStyles';
html += '
';
html += '
';
- html += '
';
-
html += '
';
html += '
';
+ html += '
';
return html;
}
@@ -73,9 +70,11 @@ import 'flexStyles';
const elem = instance.options.parent;
- elem.querySelector('.upNextDialog-overview').innerHTML = item.Overview || '';
-
elem.querySelector('.upNextDialog-mediainfo').innerHTML = mediaInfo.getPrimaryMediaInfoHtml(item, {
+ criticRating: false,
+ originalAirDate: false,
+ starRating: false,
+ subtitles: false
});
let title = itemHelper.getDisplayName(item);
From e38fa15e4d40d1ccc6e51e10bb6052502317adea Mon Sep 17 00:00:00 2001
From: MrTimscampi
Date: Sat, 22 Aug 2020 02:38:06 +0200
Subject: [PATCH 020/365] Constrain width only on desktop
---
src/assets/css/videoosd.css | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/src/assets/css/videoosd.css b/src/assets/css/videoosd.css
index 9995a7ff84..a23a4cf8ee 100644
--- a/src/assets/css/videoosd.css
+++ b/src/assets/css/videoosd.css
@@ -105,10 +105,13 @@
.osdControls {
flex-grow: 1;
- max-width: calc(100vh * 1.77);
padding: 0 0.8em;
}
+.layout-desktop .osdControls {
+ max-width: calc(100vh * 1.77 - 2vh);
+}
+
.videoOsdBottom .buttons {
padding: 0.25em 0 0;
display: -webkit-box;
From 1812df57ad9a45c40b24378f5bc35953bceead40 Mon Sep 17 00:00:00 2001
From: MrTimscampi
Date: Sat, 22 Aug 2020 14:07:54 +0200
Subject: [PATCH 021/365] Fix up next dialog on Chrome
---
src/components/upnextdialog/upnextdialog.css | 67 ++++----------------
src/components/upnextdialog/upnextdialog.js | 2 -
2 files changed, 11 insertions(+), 58 deletions(-)
diff --git a/src/components/upnextdialog/upnextdialog.css b/src/components/upnextdialog/upnextdialog.css
index 754fd418ca..efb0366488 100644
--- a/src/components/upnextdialog/upnextdialog.css
+++ b/src/components/upnextdialog/upnextdialog.css
@@ -1,25 +1,10 @@
.upNextContainer {
- box-sizing: border-box;
position: fixed;
- top: 0;
+ right: 0;
bottom: 0;
- left: 50%;
- transform: translateX(-50%);
- padding: 1em;
- display: flex;
- flex-grow: 1;
- width: calc(100vh * (16 / 9));
- height: 100vh;
- justify-content: end;
- align-items: flex-end;
-}
-
-.upNextDialog-container {
- border-radius: 5px;
width: 30em;
- height: 11em;
- left: auto;
- padding: 1%;
+ padding: 1em;
+ margin: 0 2em 2em 0;
display: flex;
flex-direction: column;
will-change: transform, opacity;
@@ -38,18 +23,18 @@
font-weight: 500;
}
-.upNextDialog-poster {
- display: none;
- max-width: 40%;
- max-height: 15%;
- position: relative;
- margin-right: 1em;
- flex-shrink: 0;
- margin-bottom: 0.5em;
+.upNextDialog-nextVideoText,
+.upNextDialog-title {
+ width: 25.5em;
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
}
.upNextDialog-buttons {
+ width: 29.75em;
justify-content: end;
+ align-content: flex-end;
}
.upNextDialog-button {
@@ -61,34 +46,4 @@
.upNextDialog {
flex-direction: row;
}
-
- .upNextDialog-poster {
- max-width: initial;
- max-height: initial;
- width: 30%;
- margin-bottom: 0;
- }
-}
-
-@media all and (max-width: 50em) {
- .upNextDialog-overview {
- display: none !important;
- }
-}
-
-.upNextDialog-poster-img {
- position: absolute;
- bottom: 0;
- left: 0;
- right: 0;
- height: auto;
- width: 100%;
- box-shadow: 0 0.0725em 0.29em 0 rgba(0, 0, 0, 0.37);
- user-drag: none;
- border: 0;
- user-select: none;
- -moz-user-select: none;
- -webkit-user-drag: none;
- -webkit-user-select: none;
- -ms-user-select: none;
}
diff --git a/src/components/upnextdialog/upnextdialog.js b/src/components/upnextdialog/upnextdialog.js
index 8d3202cc1c..1d55556710 100644
--- a/src/components/upnextdialog/upnextdialog.js
+++ b/src/components/upnextdialog/upnextdialog.js
@@ -17,7 +17,6 @@ import 'flexStyles';
function getHtml() {
let html = '';
- html += '';
html += '
';
html += '
';
@@ -42,7 +41,6 @@ import 'flexStyles';
// main
html += '';
- html += '
';
return html;
}
From 02015aaa9c60e727242c34363a7130d2c069a831 Mon Sep 17 00:00:00 2001
From: MrTimscampi
Date: Sat, 29 Aug 2020 18:32:42 +0200
Subject: [PATCH 022/365] Adjust OSD color for WCAG compliance
---
src/assets/css/videoosd.css | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/assets/css/videoosd.css b/src/assets/css/videoosd.css
index a23a4cf8ee..f0792c2c45 100644
--- a/src/assets/css/videoosd.css
+++ b/src/assets/css/videoosd.css
@@ -11,7 +11,7 @@
left: 0;
right: 0;
position: fixed;
- background: linear-gradient(0deg, rgba(16, 16, 16, 0.6) 0%, rgba(16, 16, 16, 0) 100%);
+ background: linear-gradient(0deg, rgba(16, 16, 16, 0.75) 0%, rgba(16, 16, 16, 0) 100%);
padding-top: 7.5em;
padding-bottom: 1.75em;
display: flex;
@@ -28,7 +28,7 @@
transition: opacity 0.3s ease-out;
position: relative;
z-index: 1;
- background: linear-gradient(180deg, rgba(16, 16, 16, 0.6) 0%, rgba(16, 16, 16, 0) 100%);
+ background: linear-gradient(180deg, rgba(16, 16, 16, 0.75) 0%, rgba(16, 16, 16, 0) 100%);
backdrop-filter: none;
color: #eee;
height: 7.5em;
From 0db000e5b51b1a66cb7b6150879314b8e3d2918e Mon Sep 17 00:00:00 2001
From: MrTimscampi
Date: Sun, 30 Aug 2020 13:47:37 +0200
Subject: [PATCH 023/365] Fix CSS selector for top OSD header
---
src/assets/css/videoosd.css | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/assets/css/videoosd.css b/src/assets/css/videoosd.css
index f0792c2c45..b2446d5d48 100644
--- a/src/assets/css/videoosd.css
+++ b/src/assets/css/videoosd.css
@@ -24,7 +24,7 @@
-webkit-touch-callout: none;
}
-.osdHeader {
+.skinHeader-withBackground.osdHeader {
transition: opacity 0.3s ease-out;
position: relative;
z-index: 1;
From 8900da42d8f08b1700e04e3296203c49f2dd7aac Mon Sep 17 00:00:00 2001
From: Cameron
Date: Tue, 1 Sep 2020 10:07:06 +0100
Subject: [PATCH 024/365] Hide Alphapicker when not sorting alphabetically
(movies
---
src/controllers/movies/movies.js | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/src/controllers/movies/movies.js b/src/controllers/movies/movies.js
index 91b428ec68..d48812cb94 100644
--- a/src/controllers/movies/movies.js
+++ b/src/controllers/movies/movies.js
@@ -26,6 +26,11 @@ import 'emby-itemscontainer';
const updateFilterControls = () => {
if (this.alphaPicker) {
this.alphaPicker.value(query.NameStartsWithOrGreater);
+ if (query.SortBy.indexOf('SortName') === 0) {
+ this.alphaPicker.visible(true);
+ } else {
+ this.alphaPicker.visible(false);
+ }
}
};
From 477ecfdc9fd8fe2185a8aab9e7c0b06152f8887e Mon Sep 17 00:00:00 2001
From: Cameron
Date: Tue, 1 Sep 2020 10:09:22 +0100
Subject: [PATCH 025/365] Hide Alphapicker when not sorting alphabetically (TV)
---
src/controllers/shows/tvshows.js | 11 ++++++++++-
1 file changed, 10 insertions(+), 1 deletion(-)
diff --git a/src/controllers/shows/tvshows.js b/src/controllers/shows/tvshows.js
index 281c921e48..31ef72621d 100644
--- a/src/controllers/shows/tvshows.js
+++ b/src/controllers/shows/tvshows.js
@@ -198,7 +198,16 @@ import 'emby-itemscontainer';
function updateFilterControls(tabContent) {
const query = getQuery(tabContent);
- self.alphaPicker.value(query.NameStartsWithOrGreater);
+
+ if (self.alphaPicker) {
+ self.alphaPicker.value(query.NameStartsWithOrGreater);
+
+ if (query.SortBy.indexOf('SortName') === 0) {
+ self.alphaPicker.visible(true);
+ } else {
+ self.alphaPicker.visible(false);
+ }
+ }
}
const self = this;
From d8cb6068940d56034a92314754d2b3fdb0d08cef Mon Sep 17 00:00:00 2001
From: Cameron
Date: Tue, 1 Sep 2020 10:09:28 +0100
Subject: [PATCH 026/365] Hide Alphapicker when not sorting alphabetically
(Music)
---
src/controllers/music/musicalbums.js | 11 ++++++++++-
1 file changed, 10 insertions(+), 1 deletion(-)
diff --git a/src/controllers/music/musicalbums.js b/src/controllers/music/musicalbums.js
index 7ea8fa254a..5bb8546e76 100644
--- a/src/controllers/music/musicalbums.js
+++ b/src/controllers/music/musicalbums.js
@@ -186,7 +186,16 @@ import 'emby-itemscontainer';
const updateFilterControls = (tabContent) => {
const query = getQuery();
- this.alphaPicker.value(query.NameStartsWithOrGreater);
+
+ if (this.alphaPicker) {
+ this.alphaPicker.value(query.NameStartsWithOrGreater);
+
+ if (query.SortBy.indexOf('SortName') === 0) {
+ this.alphaPicker.visible(true);
+ } else {
+ this.alphaPicker.visible(false);
+ }
+ }
};
let savedQueryKey;
From ab7fafa891b5c26ec758424a91c594fed7e03efb Mon Sep 17 00:00:00 2001
From: Cameron
Date: Tue, 1 Sep 2020 10:12:10 +0100
Subject: [PATCH 027/365] Remove ailiasing this
---
src/controllers/shows/tvshows.js | 47 ++++++++++++++++----------------
1 file changed, 23 insertions(+), 24 deletions(-)
diff --git a/src/controllers/shows/tvshows.js b/src/controllers/shows/tvshows.js
index 31ef72621d..17407e4c5d 100644
--- a/src/controllers/shows/tvshows.js
+++ b/src/controllers/shows/tvshows.js
@@ -54,8 +54,8 @@ import 'emby-itemscontainer';
return context.savedQueryKey;
}
- function onViewStyleChange() {
- const viewStyle = self.getCurrentViewStyle();
+ const onViewStyleChange = () => {
+ const viewStyle = this.getCurrentViewStyle();
const itemsContainer = tabContent.querySelector('.itemsContainer');
if (viewStyle == 'List') {
@@ -67,13 +67,13 @@ import 'emby-itemscontainer';
}
itemsContainer.innerHTML = '';
- }
+ };
- function reloadItems(page) {
+ const reloadItems = (page) => {
loading.show();
isLoading = true;
const query = getQuery(page);
- ApiClient.getItems(ApiClient.getCurrentUserId(), query).then(function (result) {
+ ApiClient.getItems(ApiClient.getCurrentUserId(), query).then((result) => {
function onNextPageClick() {
if (isLoading) {
return;
@@ -109,7 +109,7 @@ import 'emby-itemscontainer';
sortButton: false,
filterButton: false
});
- const viewStyle = self.getCurrentViewStyle();
+ const viewStyle = this.getCurrentViewStyle();
if (viewStyle == 'Thumb') {
html = cardBuilder.getCardsHtml({
items: result.Items,
@@ -196,25 +196,24 @@ import 'emby-itemscontainer';
});
}
- function updateFilterControls(tabContent) {
+ const updateFilterControls = (tabContent) => {
const query = getQuery(tabContent);
- if (self.alphaPicker) {
- self.alphaPicker.value(query.NameStartsWithOrGreater);
+ if (this.alphaPicker) {
+ this.alphaPicker.value(query.NameStartsWithOrGreater);
if (query.SortBy.indexOf('SortName') === 0) {
- self.alphaPicker.visible(true);
+ this.alphaPicker.visible(true);
} else {
- self.alphaPicker.visible(false);
+ this.alphaPicker.visible(false);
}
}
- }
+ };
- const self = this;
const data = {};
let isLoading = false;
- self.showFilterMenu = function () {
+ this.showFilterMenu = function () {
import('components/filterdialog/filterdialog').then(({default: filterDialogFactory}) => {
const filterDialog = new filterDialogFactory({
query: getQuery(tabContent),
@@ -229,11 +228,11 @@ import 'emby-itemscontainer';
});
};
- self.getCurrentViewStyle = function () {
+ this.getCurrentViewStyle = function () {
return getPageData(tabContent).view;
};
- function initPage(tabContent) {
+ const initPage = (tabContent) => {
const alphaPickerElement = tabContent.querySelector('.alphaPicker');
const itemsContainer = tabContent.querySelector('.itemsContainer');
@@ -244,7 +243,7 @@ import 'emby-itemscontainer';
query.StartIndex = 0;
reloadItems(tabContent);
});
- self.alphaPicker = new AlphaPicker({
+ this.alphaPicker = new AlphaPicker({
element: alphaPickerElement,
valueChangeEvent: 'click'
});
@@ -253,8 +252,8 @@ import 'emby-itemscontainer';
alphaPickerElement.classList.add('alphaPicker-fixed-right');
itemsContainer.classList.add('padded-right-withalphapicker');
- tabContent.querySelector('.btnFilter').addEventListener('click', function () {
- self.showFilterMenu();
+ tabContent.querySelector('.btnFilter').addEventListener('click', () => {
+ this.showFilterMenu();
});
tabContent.querySelector('.btnSort').addEventListener('click', function (e) {
libraryBrowser.showSortMenu({
@@ -286,8 +285,8 @@ import 'emby-itemscontainer';
});
});
const btnSelectView = tabContent.querySelector('.btnSelectView');
- btnSelectView.addEventListener('click', function (e) {
- libraryBrowser.showLayoutMenu(e.target, self.getCurrentViewStyle(), 'Banner,List,Poster,PosterCard,Thumb,ThumbCard'.split(','));
+ btnSelectView.addEventListener('click', (e) => {
+ libraryBrowser.showLayoutMenu(e.target, this.getCurrentViewStyle(), 'Banner,List,Poster,PosterCard,Thumb,ThumbCard'.split(','));
});
btnSelectView.addEventListener('layoutchange', function (e) {
const viewStyle = e.detail.viewStyle;
@@ -297,17 +296,17 @@ import 'emby-itemscontainer';
onViewStyleChange();
reloadItems(tabContent);
});
- }
+ };
initPage(tabContent);
onViewStyleChange();
- self.renderTab = function () {
+ this.renderTab = function () {
reloadItems(tabContent);
updateFilterControls(tabContent);
};
- self.destroy = function () {};
+ this.destroy = function () {};
}
/* eslint-enable indent */
From 840ef01a1303582584b914a31c650822fe57c6b5 Mon Sep 17 00:00:00 2001
From: Cameron
Date: Tue, 1 Sep 2020 10:13:15 +0100
Subject: [PATCH 028/365] Replace loops for for..of
---
src/controllers/shows/tvshows.js | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
diff --git a/src/controllers/shows/tvshows.js b/src/controllers/shows/tvshows.js
index 17407e4c5d..7d76c78faa 100644
--- a/src/controllers/shows/tvshows.js
+++ b/src/controllers/shows/tvshows.js
@@ -169,18 +169,18 @@ import 'emby-itemscontainer';
let elems = tabContent.querySelectorAll('.paging');
- for (let i = 0, length = elems.length; i < length; i++) {
- elems[i].innerHTML = pagingHtml;
+ for (const elem of elems) {
+ elem.innerHTML = pagingHtml;
}
elems = tabContent.querySelectorAll('.btnNextPage');
- for (let i = 0, length = elems.length; i < length; i++) {
- elems[i].addEventListener('click', onNextPageClick);
+ for (const elem of elems) {
+ elem.addEventListener('click', onNextPageClick);
}
elems = tabContent.querySelectorAll('.btnPreviousPage');
- for (let i = 0, length = elems.length; i < length; i++) {
- elems[i].addEventListener('click', onPreviousPageClick);
+ for (const elem of elems) {
+ elem.addEventListener('click', onPreviousPageClick);
}
const itemsContainer = tabContent.querySelector('.itemsContainer');
@@ -194,7 +194,7 @@ import 'emby-itemscontainer';
autoFocuser.autoFocus(page);
});
});
- }
+ };
const updateFilterControls = (tabContent) => {
const query = getQuery(tabContent);
From 4968f71858834e0ad29f9ad446698d0faa2e808d Mon Sep 17 00:00:00 2001
From: Cameron
Date: Tue, 1 Sep 2020 10:14:14 +0100
Subject: [PATCH 029/365] Replace loops for for..of
---
src/controllers/music/musicalbums.js | 20 ++++++++++++++------
1 file changed, 14 insertions(+), 6 deletions(-)
diff --git a/src/controllers/music/musicalbums.js b/src/controllers/music/musicalbums.js
index 5bb8546e76..5ecb553024 100644
--- a/src/controllers/music/musicalbums.js
+++ b/src/controllers/music/musicalbums.js
@@ -155,20 +155,21 @@ import 'emby-itemscontainer';
overlayPlayButton: true
});
}
+
let elems = tabContent.querySelectorAll('.paging');
- for (let i = 0, length = elems.length; i < length; i++) {
- elems[i].innerHTML = pagingHtml;
+ for (const elem of elems) {
+ elem.innerHTML = pagingHtml;
}
elems = tabContent.querySelectorAll('.btnNextPage');
- for (let i = 0, length = elems.length; i < length; i++) {
- elems[i].addEventListener('click', onNextPageClick);
+ for (const elem of elems) {
+ elem.addEventListener('click', onNextPageClick);
}
elems = tabContent.querySelectorAll('.btnPreviousPage');
- for (let i = 0, length = elems.length; i < length; i++) {
- elems[i].addEventListener('click', onPreviousPageClick);
+ for (const elem of elems) {
+ elem.addEventListener('click', onPreviousPageClick);
}
const itemsContainer = tabContent.querySelector('.itemsContainer');
@@ -209,10 +210,12 @@ import 'emby-itemscontainer';
mode: 'albums',
serverId: ApiClient.serverId()
});
+
events.on(filterDialog, 'filterchange', function () {
getQuery().StartIndex = 0;
reloadItems(tabContent);
});
+
filterDialog.show();
});
};
@@ -232,6 +235,7 @@ import 'emby-itemscontainer';
query.StartIndex = 0;
reloadItems(tabContent);
});
+
this.alphaPicker = new AlphaPicker({
element: alphaPickerElement,
valueChangeEvent: 'click'
@@ -244,6 +248,7 @@ import 'emby-itemscontainer';
tabContent.querySelector('.btnFilter').addEventListener('click', () => {
this.showFilterMenu();
});
+
tabContent.querySelector('.btnSort').addEventListener('click', (e) => {
libraryBrowser.showSortMenu({
items: [{
@@ -276,10 +281,12 @@ import 'emby-itemscontainer';
button: e.target
});
});
+
const btnSelectView = tabContent.querySelector('.btnSelectView');
btnSelectView.addEventListener('click', (e) => {
libraryBrowser.showLayoutMenu(e.target, this.getCurrentViewStyle(), 'List,Poster,PosterCard'.split(','));
});
+
btnSelectView.addEventListener('layoutchange', function (e) {
const viewStyle = e.detail.viewStyle;
getPageData().view = viewStyle;
@@ -288,6 +295,7 @@ import 'emby-itemscontainer';
onViewStyleChange();
reloadItems(tabContent);
});
+
tabContent.querySelector('.btnPlayAll').addEventListener('click', playAll);
tabContent.querySelector('.btnShuffle').addEventListener('click', shuffle);
};
From f7d0b9491619262a8e420552872d16a6a5b9ca49 Mon Sep 17 00:00:00 2001
From: Dmitry Lyzo
Date: Tue, 1 Sep 2020 13:32:12 +0300
Subject: [PATCH 030/365] Babel libarchive
---
webpack.dev.js | 2 +-
webpack.prod.js | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/webpack.dev.js b/webpack.dev.js
index 3d0c2a48a0..33e171daa8 100644
--- a/webpack.dev.js
+++ b/webpack.dev.js
@@ -15,7 +15,7 @@ module.exports = merge(common, {
rules: [
{
test: /\.js$/,
- exclude: /node_modules[\\/](?!date-fns|epubjs|jellyfin-apiclient|query-string|split-on-first|strict-uri-encode|xmldom)/,
+ exclude: /node_modules[\\/](?!date-fns|epubjs|libarchive|jellyfin-apiclient|query-string|split-on-first|strict-uri-encode|xmldom)/,
use: {
loader: 'babel-loader',
options: {
diff --git a/webpack.prod.js b/webpack.prod.js
index 52d6d0a865..408eb4bb59 100644
--- a/webpack.prod.js
+++ b/webpack.prod.js
@@ -8,7 +8,7 @@ module.exports = merge(common, {
rules: [
{
test: /\.js$/,
- exclude: /node_modules[\\/](?!date-fns|epubjs|jellyfin-apiclient|query-string|split-on-first|strict-uri-encode|xmldom)/,
+ exclude: /node_modules[\\/](?!date-fns|epubjs|libarchive|jellyfin-apiclient|query-string|split-on-first|strict-uri-encode|xmldom)/,
use: {
loader: 'babel-loader',
options: {
From eccaad366e6150c7dfa2010275714ee8dba8aa07 Mon Sep 17 00:00:00 2001
From: Dmitry Lyzo
Date: Tue, 1 Sep 2020 23:52:27 +0300
Subject: [PATCH 031/365] Add timeout for polyfilled CustomElements (webOS 1.2)
---
src/components/viewContainer.js | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/src/components/viewContainer.js b/src/components/viewContainer.js
index 9d64130cdb..6be8cfd19b 100644
--- a/src/components/viewContainer.js
+++ b/src/components/viewContainer.js
@@ -82,7 +82,8 @@ import 'css!components/viewManager/viewContainer';
}
allPages[pageIndex] = view;
- setControllerClass(view, options).then(() => {
+ // Timeout for polyfilled CustomElements (webOS 1.2)
+ setControllerClass(view, options).then(() => new Promise((resolve) => setTimeout(resolve, 0))).then(() => {
if (onBeforeChange) {
onBeforeChange(view, false, options);
}
From 748592fa9310732bff082466a3308a51f24740bb Mon Sep 17 00:00:00 2001
From: Dmitry Lyzo
Date: Wed, 2 Sep 2020 01:06:07 +0300
Subject: [PATCH 032/365] Remove nested Promise
---
src/components/viewContainer.js | 75 +++++++++++++++++----------------
1 file changed, 38 insertions(+), 37 deletions(-)
diff --git a/src/components/viewContainer.js b/src/components/viewContainer.js
index 6be8cfd19b..bbec0c0e65 100644
--- a/src/components/viewContainer.js
+++ b/src/components/viewContainer.js
@@ -36,54 +36,56 @@ import 'css!components/viewManager/viewContainer';
const newViewInfo = normalizeNewView(options, isPluginpage);
const newView = newViewInfo.elem;
- return new Promise((resolve) => {
- const currentPage = allPages[pageIndex];
+ const currentPage = allPages[pageIndex];
- if (currentPage) {
- triggerDestroy(currentPage);
- }
+ if (currentPage) {
+ triggerDestroy(currentPage);
+ }
- let view = newView;
+ let view = newView;
- if (typeof view == 'string') {
- view = document.createElement('div');
- view.innerHTML = newView;
- }
+ if (typeof view == 'string') {
+ view = document.createElement('div');
+ view.innerHTML = newView;
+ }
- view.classList.add('mainAnimatedPage');
+ view.classList.add('mainAnimatedPage');
- if (currentPage) {
- if (newViewInfo.hasScript && window.$) {
- mainAnimatedPages.removeChild(currentPage);
- view = $(view).appendTo(mainAnimatedPages)[0];
- } else {
- mainAnimatedPages.replaceChild(view, currentPage);
- }
+ if (currentPage) {
+ if (newViewInfo.hasScript && window.$) {
+ mainAnimatedPages.removeChild(currentPage);
+ view = $(view).appendTo(mainAnimatedPages)[0];
} else {
- if (newViewInfo.hasScript && window.$) {
- view = $(view).appendTo(mainAnimatedPages)[0];
- } else {
- mainAnimatedPages.appendChild(view);
- }
+ mainAnimatedPages.replaceChild(view, currentPage);
}
-
- if (options.type) {
- view.setAttribute('data-type', options.type);
+ } else {
+ if (newViewInfo.hasScript && window.$) {
+ view = $(view).appendTo(mainAnimatedPages)[0];
+ } else {
+ mainAnimatedPages.appendChild(view);
}
+ }
- const properties = [];
+ if (options.type) {
+ view.setAttribute('data-type', options.type);
+ }
- if (options.fullscreen) {
- properties.push('fullscreen');
- }
+ const properties = [];
- if (properties.length) {
- view.setAttribute('data-properties', properties.join(','));
- }
+ if (options.fullscreen) {
+ properties.push('fullscreen');
+ }
- allPages[pageIndex] = view;
+ if (properties.length) {
+ view.setAttribute('data-properties', properties.join(','));
+ }
+
+ allPages[pageIndex] = view;
+
+ return setControllerClass(view, options)
// Timeout for polyfilled CustomElements (webOS 1.2)
- setControllerClass(view, options).then(() => new Promise((resolve) => setTimeout(resolve, 0))).then(() => {
+ .then(() => new Promise((resolve) => setTimeout(resolve, 0)))
+ .then(() => {
if (onBeforeChange) {
onBeforeChange(view, false, options);
}
@@ -101,9 +103,8 @@ import 'css!components/viewManager/viewContainer';
$.mobile.activePage = view;
}
- resolve(view);
+ return view;
});
- });
}
}
From 6553cea696995f565cea607edfd03e465d70c8bc Mon Sep 17 00:00:00 2001
From: "Brian J. Murrell"
Date: Thu, 3 Sep 2020 10:33:59 -0400
Subject: [PATCH 033/365] Add BR: git for all distros
Seems the Fedora yarn package also doesn't Requires: git so add it
as a BuildRequires:.
Signed-off-by: Brian J. Murrell
---
fedora/jellyfin-web.spec | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/fedora/jellyfin-web.spec b/fedora/jellyfin-web.spec
index 1d85e5ae6b..d4af00d36b 100644
--- a/fedora/jellyfin-web.spec
+++ b/fedora/jellyfin-web.spec
@@ -2,7 +2,7 @@
Name: jellyfin-web
Version: 10.7.0
-Release: 1%{?dist}
+Release: 2%{?dist}
Summary: The Free Software Media System web client
License: GPLv3
URL: https://jellyfin.org
@@ -11,11 +11,12 @@ Source0: jellyfin-web-%{version}.tar.gz
%if 0%{?centos}
BuildRequires: yarn
-# sadly the yarn RPM at https://dl.yarnpkg.com/rpm/ uses git but doesn't Requires: it
-BuildRequires: git
%else
BuildRequires: nodejs-yarn
%endif
+# sadly the yarn RPM at https://dl.yarnpkg.com/rpm/ uses git but doesn't Requires: it
+# ditto for Fedora's yarn RPM
+BuildRequires: git
BuildArch: noarch
# Disable Automatic Dependency Processing
From 28928ead7cfb101f7b8d55fd21361e0bcfb0fa44 Mon Sep 17 00:00:00 2001
From: Matt Montgomery <33811686+ConfusedPolarBear@users.noreply.github.com>
Date: Thu, 3 Sep 2020 16:19:35 -0500
Subject: [PATCH 034/365] Modified to work with latest server code
---
.../quickConnectSettings.js | 39 ++------
src/controllers/dashboard/quickconnect.js | 5 +-
src/controllers/session/login/index.js | 93 ++++++++-----------
src/controllers/user/quickConnect/index.js | 2 -
src/strings/en-us.json | 1 +
5 files changed, 51 insertions(+), 89 deletions(-)
diff --git a/src/components/quickConnectSettings/quickConnectSettings.js b/src/components/quickConnectSettings/quickConnectSettings.js
index 35f051a121..a62cfc2298 100644
--- a/src/components/quickConnectSettings/quickConnectSettings.js
+++ b/src/components/quickConnectSettings/quickConnectSettings.js
@@ -5,21 +5,14 @@ export class QuickConnectSettings {
constructor() { }
authorize(code) {
- let url = ApiClient.getUrl('/QuickConnect/Authorize');
+ let url = ApiClient.getUrl('/QuickConnect/Authorize?Code=' + code);
ApiClient.ajax({
type: 'POST',
- url: url,
- data: {
- 'Code': code
- }
+ url: url
}, true).then(() => {
- require(['toast'], function (toast) {
- toast(globalize.translate('QuickConnectAuthorizeSuccess'));
- });
+ toast(globalize.translate('QuickConnectAuthorizeSuccess'));
}).catch(() => {
- require(['toast'], function (toast) {
- toast(globalize.translate('QuickConnectAuthorizeFail'));
- });
+ toast(globalize.translate('QuickConnectAuthorizeFail'));
});
// prevent bubbling
@@ -30,28 +23,16 @@ export class QuickConnectSettings {
let url = ApiClient.getUrl('/QuickConnect/Activate');
return ApiClient.ajax({
type: 'POST',
- url: url,
- contentType: 'application/json',
- dataType: 'json'
- }).then((json) => {
- let message = json.Error;
-
- if (message && message !== '') {
- console.error('Error activating quick connect. Error: ', json.Error);
-
- Dashboard.alert({
- title: 'Unable to activate quick connect',
- message: message
- });
-
- return false;
- }
-
+ url: url
+ }).then(() => {
toast(globalize.translate('QuickConnectActivationSuccessful'));
-
return true;
}).catch((e) => {
console.error('Error activating quick connect. Error:', e);
+ Dashboard.alert({
+ title: globalize.translate('HeaderError'),
+ message: globalize.translate('DefaultErrorMessage')
+ });
throw e;
});
}
diff --git a/src/controllers/dashboard/quickconnect.js b/src/controllers/dashboard/quickconnect.js
index 22f4781b7d..9d08bb6b48 100644
--- a/src/controllers/dashboard/quickconnect.js
+++ b/src/controllers/dashboard/quickconnect.js
@@ -26,13 +26,10 @@ import loading from 'loading';
let newStatus = page.querySelector('#chkQuickConnectAvailable').checked ? 'Available' : 'Unavailable';
- let url = ApiClient.getUrl('/QuickConnect/Available');
+ let url = ApiClient.getUrl('/QuickConnect/Available?Status=' + newStatus);
ApiClient.ajax({
type: 'POST',
- data: {
- 'Status': newStatus
- },
url: url
}, true).then(() => {
require(['toast'], function (toast) {
diff --git a/src/controllers/session/login/index.js b/src/controllers/session/login/index.js
index d0446de099..aa5c8cc2d2 100644
--- a/src/controllers/session/login/index.js
+++ b/src/controllers/session/login/index.js
@@ -154,71 +154,56 @@ import 'emby-checkbox';
});
}
+ // FIXME: Clicking ok on the code dialog redirects back to the homepage.
function loginQuickConnect() {
let apiClient = getApiClient();
- let friendlyName = navigator.userAgent;
- let url = apiClient.getUrl('/QuickConnect/Initiate?FriendlyName=' + friendlyName);
- apiClient.getJSON(url)
- .then(json => {
- if (!json.Secret || !json.Code) {
- console.error('Malformed quick connect response', json);
- return false;
- }
+ let url = apiClient.getUrl('/QuickConnect/Initiate');
+ apiClient.getJSON(url).then(function (json) {
+ if (!json.Secret || !json.Code) {
+ console.error('Malformed quick connect response', json);
+ return false;
+ }
- Dashboard.alert({
- message: Globalize.translate('QuickConnectAuthorizeCode', json.Code),
- title: Globalize.translate('QuickConnect')
- });
+ Dashboard.alert({
+ message: globalize.translate('QuickConnectAuthorizeCode', json.Code),
+ title: globalize.translate('QuickConnect')
+ });
- loading.show();
-
- let interval = setInterval(async function() {
- try {
- let connectUrl = apiClient.getUrl('/QuickConnect/Connect?Secret=' + json.Secret);
- let data = await apiClient.getJSON(connectUrl);
- if (data.Authenticated) {
- let result = await apiClient.quickConnect(data.Authentication);
- let user = result.User;
- let serverId = getParameterByName('serverid');
- let newUrl = 'home.html';
-
- if (user.Policy.IsAdministrator && !serverId) {
- newUrl = 'dashboard.html';
- }
-
- loading.hide();
- Dashboard.onServerChanged(user.Id, result.AccessToken, apiClient);
- Dashboard.navigate(newUrl);
- clearInterval(interval);
-
- return true;
- }
- } catch (e) {
- Dashboard.alert({
- message: 'Quick connect was deactivated before the login request could be approved',
- title: 'Unexpected error'
- });
-
- console.error('Unable to login with quick connect', e);
- clearInterval(interval);
- loading.hide();
+ let interval = setInterval(function() {
+ let connectUrl = apiClient.getUrl('/QuickConnect/Connect?Secret=' + json.Secret);
+ apiClient.getJSON(connectUrl).then(async function(data) {
+ if (!data.Authenticated) {
+ return;
}
- return false;
- }, 5000);
+ clearInterval(interval);
- return true;
- }).catch((e) => {
- Dashboard.alert({
- message: Globalize.translate('QuickConnectNotActive'),
- title: 'Error'
+ let result = await apiClient.quickConnect(data.Authentication);
+ Dashboard.onServerChanged(result.User.Id, result.AccessToken, apiClient);
+ Dashboard.navigate('home.html');
+ }, function (e) {
+ clearInterval(interval);
+
+ Dashboard.alert({
+ message: globalize.translate('QuickConnectDeactivated'),
+ title: globalize.translate('HeaderError')
+ });
+
+ console.error('Unable to login with quick connect', e);
});
+ }, 5000);
- console.error('Quick connect error: ', e);
-
- return false;
+ return true;
+ }, function(e) {
+ Dashboard.alert({
+ message: globalize.translate('QuickConnectNotActive'),
+ title: globalize.translate('HeaderError')
});
+
+ console.error('Quick connect error: ', e);
+ return false;
+ });
}
view.querySelector('#divUsers').addEventListener('click', function (e) {
diff --git a/src/controllers/user/quickConnect/index.js b/src/controllers/user/quickConnect/index.js
index 80543a0b58..2d6f4b15c8 100644
--- a/src/controllers/user/quickConnect/index.js
+++ b/src/controllers/user/quickConnect/index.js
@@ -73,6 +73,4 @@ export default function (view) {
throw e;
});
}
-
- renderPage();
}
diff --git a/src/strings/en-us.json b/src/strings/en-us.json
index b46020794e..b4442ee0f9 100644
--- a/src/strings/en-us.json
+++ b/src/strings/en-us.json
@@ -1156,6 +1156,7 @@
"QuickConnectAuthorizeCode": "Authorize request {0} to continue",
"QuickConnectAuthorizeSuccess": "Request authorized",
"QuickConnectAuthorizeFail": "Unknown quick connect code",
+ "QuickConnectDeactivated": "Quick connect was deactivated before the login request could be approved",
"QuickConnectDescription": "To sign in with quick connect, select the Quick Connect button on the device you are logging in from and enter the displayed code below.",
"QuickConnectInvalidCode": "Invalid quick connect code",
"QuickConnectNotAvailable": "Ask your server administrator to enable quick connect",
From 723472aca58a0cc4a4cfbbcbaea8267e83341c48 Mon Sep 17 00:00:00 2001
From: Matt Montgomery <33811686+ConfusedPolarBear@users.noreply.github.com>
Date: Thu, 3 Sep 2020 16:51:15 -0500
Subject: [PATCH 035/365] Complete modifications to work with latest server
code
---
src/controllers/dashboard/quickconnect.js | 7 +-
src/controllers/session/login/index.js | 115 ++++++++++---------
src/controllers/user/quickConnect/index.html | 2 +-
src/controllers/user/quickConnect/index.js | 20 +---
src/quickconnect.html | 2 +-
src/strings/en-us.json | 2 +-
6 files changed, 71 insertions(+), 77 deletions(-)
diff --git a/src/controllers/dashboard/quickconnect.js b/src/controllers/dashboard/quickconnect.js
index 9d08bb6b48..012f7b7aa3 100644
--- a/src/controllers/dashboard/quickconnect.js
+++ b/src/controllers/dashboard/quickconnect.js
@@ -1,4 +1,6 @@
import loading from 'loading';
+import toast from 'toast';
+import globalize from 'globalize';
/* eslint-disable indent */
@@ -32,10 +34,7 @@ import loading from 'loading';
type: 'POST',
url: url
}, true).then(() => {
- require(['toast'], function (toast) {
- toast('Settings saved');
- });
-
+ toast(globalize.translate('SettingsSaved'));
setTimeout(updatePage, 500);
return true;
diff --git a/src/controllers/session/login/index.js b/src/controllers/session/login/index.js
index aa5c8cc2d2..c49ed0aee6 100644
--- a/src/controllers/session/login/index.js
+++ b/src/controllers/session/login/index.js
@@ -19,8 +19,7 @@ import 'emby-checkbox';
var user = result.User;
loading.hide();
- Dashboard.onServerChanged(user.Id, result.AccessToken, apiClient);
- Dashboard.navigate('home.html');
+ onLoginSuccessful(user.Id, result.AccessToken, apiClient);
}, function (response) {
page.querySelector('#txtManualName').value = '';
page.querySelector('#txtManualPassword').value = '';
@@ -41,6 +40,60 @@ import 'emby-checkbox';
});
}
+ function authenticateQuickConnect(apiClient) {
+ let url = apiClient.getUrl('/QuickConnect/Initiate');
+ apiClient.getJSON(url).then(function (json) {
+ if (!json.Secret || !json.Code) {
+ console.error('Malformed quick connect response', json);
+ return false;
+ }
+
+ Dashboard.alert({
+ message: globalize.translate('QuickConnectAuthorizeCode', json.Code),
+ title: globalize.translate('QuickConnect')
+ });
+
+ let connectUrl = apiClient.getUrl('/QuickConnect/Connect?Secret=' + json.Secret);
+
+ let interval = setInterval(function() {
+ apiClient.getJSON(connectUrl).then(async function(data) {
+ if (!data.Authenticated) {
+ return;
+ }
+
+ clearInterval(interval);
+
+ let result = await apiClient.quickConnect(data.Authentication);
+ onLoginSuccessful(result.User.Id, result.AccessToken, apiClient);
+ }, function (e) {
+ clearInterval(interval);
+
+ Dashboard.alert({
+ message: globalize.translate('QuickConnectDeactivated'),
+ title: globalize.translate('HeaderError')
+ });
+
+ console.error('Unable to login with quick connect', e);
+ });
+ }, 5000, connectUrl);
+
+ return true;
+ }, function(e) {
+ Dashboard.alert({
+ message: globalize.translate('QuickConnectNotActive'),
+ title: globalize.translate('HeaderError')
+ });
+
+ console.error('Quick connect error: ', e);
+ return false;
+ });
+ }
+
+ function onLoginSuccessful(id, accessToken, apiClient) {
+ Dashboard.onServerChanged(id, accessToken, apiClient);
+ Dashboard.navigate('home.html');
+ }
+
function showManualForm(context, showCancel, focusPassword) {
context.querySelector('.chkRememberLogin').checked = appSettings.enableAutoLogin();
context.querySelector('.manualLoginForm').classList.remove('hide');
@@ -154,58 +207,6 @@ import 'emby-checkbox';
});
}
- // FIXME: Clicking ok on the code dialog redirects back to the homepage.
- function loginQuickConnect() {
- let apiClient = getApiClient();
-
- let url = apiClient.getUrl('/QuickConnect/Initiate');
- apiClient.getJSON(url).then(function (json) {
- if (!json.Secret || !json.Code) {
- console.error('Malformed quick connect response', json);
- return false;
- }
-
- Dashboard.alert({
- message: globalize.translate('QuickConnectAuthorizeCode', json.Code),
- title: globalize.translate('QuickConnect')
- });
-
- let interval = setInterval(function() {
- let connectUrl = apiClient.getUrl('/QuickConnect/Connect?Secret=' + json.Secret);
- apiClient.getJSON(connectUrl).then(async function(data) {
- if (!data.Authenticated) {
- return;
- }
-
- clearInterval(interval);
-
- let result = await apiClient.quickConnect(data.Authentication);
- Dashboard.onServerChanged(result.User.Id, result.AccessToken, apiClient);
- Dashboard.navigate('home.html');
- }, function (e) {
- clearInterval(interval);
-
- Dashboard.alert({
- message: globalize.translate('QuickConnectDeactivated'),
- title: globalize.translate('HeaderError')
- });
-
- console.error('Unable to login with quick connect', e);
- });
- }, 5000);
-
- return true;
- }, function(e) {
- Dashboard.alert({
- message: globalize.translate('QuickConnectNotActive'),
- title: globalize.translate('HeaderError')
- });
-
- console.error('Quick connect error: ', e);
- return false;
- });
- }
-
view.querySelector('#divUsers').addEventListener('click', function (e) {
const card = dom.parentWithClass(e.target, 'card');
const cardContent = card ? card.querySelector('.cardContent') : null;
@@ -239,7 +240,11 @@ import 'emby-checkbox';
Dashboard.navigate('forgotpassword.html');
});
view.querySelector('.btnCancel').addEventListener('click', showVisualForm);
- view.querySelector('.btnQuick').addEventListener('click', loginQuickConnect);
+ view.querySelector('.btnQuick').addEventListener('click', function () {
+ const apiClient = getApiClient();
+ authenticateQuickConnect(apiClient);
+ return false;
+ });
view.querySelector('.btnManual').addEventListener('click', function () {
view.querySelector('#txtManualName').value = '';
showManualForm(view, true);
diff --git a/src/controllers/user/quickConnect/index.html b/src/controllers/user/quickConnect/index.html
index 5f698a4a6b..15df59ff17 100644
--- a/src/controllers/user/quickConnect/index.html
+++ b/src/controllers/user/quickConnect/index.html
@@ -1,4 +1,4 @@
-
+
diff --git a/src/controllers/user/quickConnect/index.js b/src/controllers/user/quickConnect/index.js
index 2d6f4b15c8..9e8d1a3b31 100644
--- a/src/controllers/user/quickConnect/index.js
+++ b/src/controllers/user/quickConnect/index.js
@@ -8,10 +8,7 @@ export default function (view) {
view.addEventListener('viewshow', function () {
let codeElement = view.querySelector('#txtQuickConnectCode');
- quickConnectSettingsInstance = new QuickConnectSettings({
- page: view,
- interval: 0
- });
+ quickConnectSettingsInstance = new QuickConnectSettings();
view.querySelector('#btnQuickConnectActivate').addEventListener('click', () => {
quickConnectSettingsInstance.activate(quickConnectSettingsInstance).then(() => {
@@ -30,24 +27,17 @@ export default function (view) {
quickConnectSettingsInstance.authorize(code);
});
+ view.querySelector('.quickConnectSettingsContainer').addEventListener('submit', (e) => {
+ e.preventDefault();
+ });
+
renderPage();
});
view.addEventListener('viewbeforehide', function () {
if (quickConnectSettingsInstance) {
quickConnectSettingsInstance.submit();
}
- onDestroy();
});
- view.addEventListener('viewdestroy', function () {
- onDestroy();
- });
-
- function onDestroy() {
- if (quickConnectSettingsInstance) {
- quickConnectSettingsInstance.destroy();
- quickConnectSettingsInstance = null;
- }
- }
function renderPage(forceActive = false) {
ApiClient.getQuickConnect('Status').then((status) => {
diff --git a/src/quickconnect.html b/src/quickconnect.html
index 671bb88d77..b5b6d48991 100644
--- a/src/quickconnect.html
+++ b/src/quickconnect.html
@@ -17,7 +17,7 @@
diff --git a/src/strings/en-us.json b/src/strings/en-us.json
index b4442ee0f9..df5b6a36c6 100644
--- a/src/strings/en-us.json
+++ b/src/strings/en-us.json
@@ -1153,7 +1153,7 @@
"Quality": "Quality",
"QuickConnect": "Quick Connect",
"QuickConnectActivationSuccessful": "Successfully activated",
- "QuickConnectAuthorizeCode": "Authorize request {0} to continue",
+ "QuickConnectAuthorizeCode": "Enter code {0} to login",
"QuickConnectAuthorizeSuccess": "Request authorized",
"QuickConnectAuthorizeFail": "Unknown quick connect code",
"QuickConnectDeactivated": "Quick connect was deactivated before the login request could be approved",
From f10535fc8c616679a611dad2046e656030fb3cc1 Mon Sep 17 00:00:00 2001
From: Nyanmisaka
Date: Fri, 4 Sep 2020 21:45:12 +0800
Subject: [PATCH 036/365] update strings
---
src/controllers/dashboard/encodingsettings.html | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/controllers/dashboard/encodingsettings.html b/src/controllers/dashboard/encodingsettings.html
index 00fcaa53e4..388d2edbad 100644
--- a/src/controllers/dashboard/encodingsettings.html
+++ b/src/controllers/dashboard/encodingsettings.html
@@ -118,7 +118,7 @@
From e9caf5e336bd2830d5ebc66853d6a55b057c8aea Mon Sep 17 00:00:00 2001
From: Ian Walton
Date: Mon, 7 Sep 2020 12:54:12 -0400
Subject: [PATCH 037/365] Add auto-cast feature.
---
package.json | 1 +
src/components/autocast.js | 49 +++++++++++++++++++
.../playback/playerSelectionMenu.js | 21 ++++++++
src/scripts/libraryMenu.js | 8 +++
src/scripts/site.js | 1 +
src/strings/en-us.json | 1 +
6 files changed, 81 insertions(+)
create mode 100644 src/components/autocast.js
diff --git a/package.json b/package.json
index 5ca5c15151..1521a1d918 100644
--- a/package.json
+++ b/package.json
@@ -177,6 +177,7 @@
"src/components/remotecontrol/remotecontrol.js",
"src/components/sanatizefilename.js",
"src/components/scrollManager.js",
+ "src/components/autocast.js",
"src/plugins/experimentalWarnings/plugin.js",
"src/plugins/sessionPlayer/plugin.js",
"src/plugins/htmlAudioPlayer/plugin.js",
diff --git a/src/components/autocast.js b/src/components/autocast.js
new file mode 100644
index 0000000000..3572f42bb2
--- /dev/null
+++ b/src/components/autocast.js
@@ -0,0 +1,49 @@
+import events from 'events';
+import playbackManager from 'playbackManager';
+
+export function supported() {
+ return typeof(Storage) !== 'undefined';
+}
+
+export function enable(isEnabled) {
+ if (!supported()) return;
+
+ if (isEnabled) {
+ const currentPlayerInfo = playbackManager.getPlayerInfo();
+
+ if (currentPlayerInfo && currentPlayerInfo.id && currentPlayerInfo.id) {
+ localStorage.setItem('autocastPlayerId', currentPlayerInfo.id);
+ }
+ } else {
+ localStorage.removeItem('autocastPlayerId');
+ }
+}
+
+export function isEnabled() {
+ if (!supported()) return false;
+
+ const playerId = localStorage.getItem('autocastPlayerId');
+ const currentPlayerInfo = playbackManager.getPlayerInfo();
+
+ return (currentPlayerInfo && playerId && currentPlayerInfo.id === playerId);
+}
+
+function onOpen() {
+ if (!supported()) return;
+
+ const playerId = localStorage.getItem('autocastPlayerId');
+
+ playbackManager.getTargets().then(function (targets) {
+ for (var i = 0; i < targets.length; i++) {
+ if (targets[i].id == playerId) {
+ playbackManager.trySetActivePlayer(targets[i].playerName, targets[i]);
+ break;
+ }
+ }
+ });
+}
+
+const apiClient = window.connectionManager.currentApiClient();
+if (apiClient) {
+ events.on(apiClient, 'websocketopen', onOpen);
+}
diff --git a/src/components/playback/playerSelectionMenu.js b/src/components/playback/playerSelectionMenu.js
index 7799613400..3fe5be70d8 100644
--- a/src/components/playback/playerSelectionMenu.js
+++ b/src/components/playback/playerSelectionMenu.js
@@ -6,6 +6,7 @@ import playbackManager from 'playbackManager';
import appRouter from 'appRouter';
import globalize from 'globalize';
import appHost from 'apphost';
+import * as autocast from 'autocast';
function mirrorItem(info, player) {
var item = info.item;
@@ -219,6 +220,16 @@ function showActivePlayerMenuInternal(dialogHelper, playerInfo) {
html += '';
}
+ html += '
';
+
+ if (autocast.supported()) {
+ html += '';
+ }
+
html += '
';
html += '';
@@ -237,6 +248,12 @@ function showActivePlayerMenuInternal(dialogHelper, playerInfo) {
chkMirror.addEventListener('change', onMirrorChange);
}
+ var chkAutoCast = dlg.querySelector('.chkAutoCast');
+
+ if (chkAutoCast) {
+ chkAutoCast.addEventListener('change', onAutoCastChange);
+ }
+
var destination = '';
var btnRemoteControl = dlg.querySelector('.btnRemoteControl');
@@ -269,6 +286,10 @@ function onMirrorChange() {
playbackManager.enableDisplayMirroring(this.checked);
}
+function onAutoCastChange() {
+ autocast.enable(this.checked);
+}
+
document.addEventListener('viewshow', function (e) {
var state = e.detail.state || {};
var item = state.item;
diff --git a/src/scripts/libraryMenu.js b/src/scripts/libraryMenu.js
index 04edecf198..7a332a853c 100644
--- a/src/scripts/libraryMenu.js
+++ b/src/scripts/libraryMenu.js
@@ -52,6 +52,7 @@ import 'flexStyles';
lazyLoadViewMenuBarImages();
bindMenuEvents();
+ updateCastIcon();
}
function getCurrentApiClient() {
@@ -910,6 +911,12 @@ import 'flexStyles';
}
}
+ function ensureHeader() {
+ return new Promise(function (resolve) {
+ window.connectionManager.user(getCurrentApiClient()).then(updateUserInHeader).then(resolve);
+ });
+ }
+
let currentPageType;
pageClassOn('pagebeforeshow', 'page', function (e) {
if (!this.classList.contains('withTabs')) {
@@ -996,6 +1003,7 @@ import 'flexStyles';
};
window.LibraryMenu = LibraryMenu;
+ renderHeader();
export default LibraryMenu;
diff --git a/src/scripts/site.js b/src/scripts/site.js
index f14670d82d..e8f00080f1 100644
--- a/src/scripts/site.js
+++ b/src/scripts/site.js
@@ -591,6 +591,7 @@ function initClient() {
define('metadataEditor', [componentsPath + '/metadataEditor/metadataEditor'], returnFirstDependency);
define('personEditor', [componentsPath + '/metadataEditor/personEditor'], returnFirstDependency);
define('playerSelectionMenu', [componentsPath + '/playback/playerSelectionMenu'], returnFirstDependency);
+ define('autocast', [componentsPath + '/autocast'], returnFirstDependency);
define('playerSettingsMenu', [componentsPath + '/playback/playersettingsmenu'], returnFirstDependency);
define('playMethodHelper', [componentsPath + '/playback/playmethodhelper'], returnFirstDependency);
define('brightnessOsd', [componentsPath + '/playback/brightnessosd'], returnFirstDependency);
diff --git a/src/strings/en-us.json b/src/strings/en-us.json
index e39199c56f..074d9c95f1 100644
--- a/src/strings/en-us.json
+++ b/src/strings/en-us.json
@@ -183,6 +183,7 @@
"EditImages": "Edit images",
"EditMetadata": "Edit metadata",
"EditSubtitles": "Edit subtitles",
+ "EnableAutoCast": "Set as Default",
"EnableBackdropsHelp": "Display backdrops in the background of some pages while browsing the library.",
"EnableCinemaMode": "Cinema mode",
"EnableColorCodedBackgrounds": "Color coded backgrounds",
From c8c8be39cda9258bebb0adf18a72062cee70d003 Mon Sep 17 00:00:00 2001
From: Ian Walton
Date: Mon, 7 Sep 2020 13:10:38 -0400
Subject: [PATCH 038/365] Appease SonarCloud.
---
src/components/autocast.js | 4 ++--
src/components/playback/playerSelectionMenu.js | 4 ++--
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/src/components/autocast.js b/src/components/autocast.js
index 3572f42bb2..4d191a62da 100644
--- a/src/components/autocast.js
+++ b/src/components/autocast.js
@@ -5,10 +5,10 @@ export function supported() {
return typeof(Storage) !== 'undefined';
}
-export function enable(isEnabled) {
+export function enable(enabled) {
if (!supported()) return;
- if (isEnabled) {
+ if (enabled) {
const currentPlayerInfo = playbackManager.getPlayerInfo();
if (currentPlayerInfo && currentPlayerInfo.id && currentPlayerInfo.id) {
diff --git a/src/components/playback/playerSelectionMenu.js b/src/components/playback/playerSelectionMenu.js
index 3fe5be70d8..dcf36dd9b4 100644
--- a/src/components/playback/playerSelectionMenu.js
+++ b/src/components/playback/playerSelectionMenu.js
@@ -224,8 +224,8 @@ function showActivePlayerMenuInternal(dialogHelper, playerInfo) {
if (autocast.supported()) {
html += '';
}
From fba96da9548ee7cba28a912339c910fcd90ffed2 Mon Sep 17 00:00:00 2001
From: Matt
Date: Wed, 9 Sep 2020 17:34:08 -0400
Subject: [PATCH 039/365] Alpha picker only returns items starting with
selected letter
---
src/controllers/list.js | 2 +-
src/controllers/movies/movies.js | 4 ++--
src/controllers/movies/movietrailers.js | 4 ++--
src/controllers/music/musicalbums.js | 4 ++--
src/controllers/music/musicartists.js | 4 ++--
src/controllers/shows/tvshows.js | 4 ++--
6 files changed, 11 insertions(+), 11 deletions(-)
diff --git a/src/controllers/list.js b/src/controllers/list.js
index fe04fc18e8..07e07eeb05 100644
--- a/src/controllers/list.js
+++ b/src/controllers/list.js
@@ -163,7 +163,7 @@ import 'emby-scroller';
instance.setFilterStatus(hasFilters);
if (instance.alphaPicker) {
- query.NameStartsWithOrGreater = instance.alphaPicker.value();
+ query.NameStartsWith = instance.alphaPicker.value();
}
return query;
diff --git a/src/controllers/movies/movies.js b/src/controllers/movies/movies.js
index ab5aff9ecd..e05b1fa96a 100644
--- a/src/controllers/movies/movies.js
+++ b/src/controllers/movies/movies.js
@@ -25,7 +25,7 @@ import 'emby-itemscontainer';
const updateFilterControls = () => {
if (this.alphaPicker) {
- this.alphaPicker.value(query.NameStartsWithOrGreater);
+ this.alphaPicker.value(query.NameStartsWith);
}
};
@@ -168,7 +168,7 @@ import 'emby-itemscontainer';
if (alphaPickerElement) {
alphaPickerElement.addEventListener('alphavaluechanged', function (e) {
let newValue = e.detail.value;
- query.NameStartsWithOrGreater = newValue;
+ query.NameStartsWith = newValue;
query.StartIndex = 0;
itemsContainer.refreshItems();
});
diff --git a/src/controllers/movies/movietrailers.js b/src/controllers/movies/movietrailers.js
index f2c7feada7..def55d919a 100644
--- a/src/controllers/movies/movietrailers.js
+++ b/src/controllers/movies/movietrailers.js
@@ -185,7 +185,7 @@ import 'emby-itemscontainer';
const updateFilterControls = (tabContent) => {
const query = getQuery(tabContent);
- this.alphaPicker.value(query.NameStartsWithOrGreater);
+ this.alphaPicker.value(query.NameStartsWith);
};
const data = {};
@@ -216,7 +216,7 @@ import 'emby-itemscontainer';
alphaPickerElement.addEventListener('alphavaluechanged', function (e) {
const newValue = e.detail.value;
const query = getQuery(tabContent);
- query.NameStartsWithOrGreater = newValue;
+ query.NameStartsWith = newValue;
query.StartIndex = 0;
reloadItems();
});
diff --git a/src/controllers/music/musicalbums.js b/src/controllers/music/musicalbums.js
index 7947aa1376..42490fd2f4 100644
--- a/src/controllers/music/musicalbums.js
+++ b/src/controllers/music/musicalbums.js
@@ -186,7 +186,7 @@ import 'emby-itemscontainer';
const updateFilterControls = (tabContent) => {
const query = getQuery();
- this.alphaPicker.value(query.NameStartsWithOrGreater);
+ this.alphaPicker.value(query.NameStartsWith);
};
let savedQueryKey;
@@ -219,7 +219,7 @@ import 'emby-itemscontainer';
alphaPickerElement.addEventListener('alphavaluechanged', function (e) {
const newValue = e.detail.value;
const query = getQuery();
- query.NameStartsWithOrGreater = newValue;
+ query.NameStartsWith = newValue;
query.StartIndex = 0;
reloadItems(tabContent);
});
diff --git a/src/controllers/music/musicartists.js b/src/controllers/music/musicartists.js
index 32e0a22a07..3517437622 100644
--- a/src/controllers/music/musicartists.js
+++ b/src/controllers/music/musicartists.js
@@ -169,7 +169,7 @@ import 'emby-itemscontainer';
const updateFilterControls = (tabContent) => {
const query = getQuery(tabContent);
- this.alphaPicker.value(query.NameStartsWithOrGreater);
+ this.alphaPicker.value(query.NameStartsWith);
};
const data = {};
@@ -201,7 +201,7 @@ import 'emby-itemscontainer';
alphaPickerElement.addEventListener('alphavaluechanged', function (e) {
const newValue = e.detail.value;
const query = getQuery(tabContent);
- query.NameStartsWithOrGreater = newValue;
+ query.NameStartsWith = newValue;
query.StartIndex = 0;
reloadItems(tabContent);
});
diff --git a/src/controllers/shows/tvshows.js b/src/controllers/shows/tvshows.js
index ef45eba0f7..fee4fd24a5 100644
--- a/src/controllers/shows/tvshows.js
+++ b/src/controllers/shows/tvshows.js
@@ -198,7 +198,7 @@ import 'emby-itemscontainer';
function updateFilterControls(tabContent) {
const query = getQuery(tabContent);
- self.alphaPicker.value(query.NameStartsWithOrGreater);
+ self.alphaPicker.value(query.NameStartsWith);
}
const self = this;
@@ -231,7 +231,7 @@ import 'emby-itemscontainer';
alphaPickerElement.addEventListener('alphavaluechanged', function (e) {
const newValue = e.detail.value;
const query = getQuery(tabContent);
- query.NameStartsWithOrGreater = newValue;
+ query.NameStartsWith = newValue;
query.StartIndex = 0;
reloadItems(tabContent);
});
From 17fb508d048f746d2ac5a68a4f647c1856a2a167 Mon Sep 17 00:00:00 2001
From: cvium
Date: Thu, 10 Sep 2020 11:10:24 +0200
Subject: [PATCH 040/365] Add known proxies config option
---
src/controllers/dashboard/networking.html | 5 +++++
src/controllers/dashboard/networking.js | 6 ++++++
src/strings/en-us.json | 2 ++
3 files changed, 13 insertions(+)
diff --git a/src/controllers/dashboard/networking.html b/src/controllers/dashboard/networking.html
index 899d0976b7..9fb08aa661 100644
--- a/src/controllers/dashboard/networking.html
+++ b/src/controllers/dashboard/networking.html
@@ -43,6 +43,11 @@
${LanNetworksHelp}
+
+
';
}
- let elem = context.querySelector('.subtitleList');
+ const elem = context.querySelector('.subtitleList');
if (subs.length) {
elem.classList.remove('hide');
@@ -137,18 +137,18 @@ function fillSubtitleList(context, item) {
}
function fillLanguages(context, apiClient, languages) {
- let selectLanguage = context.querySelector('#selectLanguage');
+ const selectLanguage = context.querySelector('#selectLanguage');
selectLanguage.innerHTML = languages.map(function (l) {
return '
';
});
- let lastLanguage = userSettings.get('subtitleeditor-language');
+ const lastLanguage = userSettings.get('subtitleeditor-language');
if (lastLanguage) {
selectLanguage.value = lastLanguage;
} else {
apiClient.getCurrentUser().then(function (user) {
- let lang = user.Configuration.SubtitleLanguagePreference;
+ const lang = user.Configuration.SubtitleLanguagePreference;
if (lang) {
selectLanguage.value = lang;
@@ -171,9 +171,9 @@ function renderSearchResults(context, results) {
context.querySelector('.noSearchResults').classList.add('hide');
for (let i = 0, length = results.length; i < length; i++) {
- let result = results[i];
+ const result = results[i];
- let provider = result.ProviderName;
+ const provider = result.ProviderName;
if (provider !== lastProvider) {
if (i > 0) {
@@ -184,7 +184,7 @@ function renderSearchResults(context, results) {
lastProvider = provider;
}
- let tagName = layoutManager.tv ? 'button' : 'div';
+ const tagName = layoutManager.tv ? 'button' : 'div';
let className = layoutManager.tv ? 'listItem listItem-border btnOptions' : 'listItem listItem-border';
if (layoutManager.tv) {
className += ' listItem-focusscale listItem-button';
@@ -194,7 +194,7 @@ function renderSearchResults(context, results) {
html += '
';
- let bodyClass = result.Comment || result.IsHashMatch ? 'three-line' : 'two-line';
+ const bodyClass = result.Comment || result.IsHashMatch ? 'three-line' : 'two-line';
html += '
';
@@ -231,7 +231,7 @@ function renderSearchResults(context, results) {
html += '
';
}
- let elem = context.querySelector('.subtitleResults');
+ const elem = context.querySelector('.subtitleResults');
elem.innerHTML = html;
loading.hide();
@@ -242,8 +242,8 @@ function searchForSubtitles(context, language) {
loading.show();
- let apiClient = window.connectionManager.getApiClient(currentItem.ServerId);
- let url = apiClient.getUrl('Items/' + currentItem.Id + '/RemoteSearch/Subtitles/' + language);
+ const apiClient = window.connectionManager.getApiClient(currentItem.ServerId);
+ const url = apiClient.getUrl('Items/' + currentItem.Id + '/RemoteSearch/Subtitles/' + language);
apiClient.getJSON(url).then(function (results) {
renderSearchResults(context, results);
@@ -258,7 +258,7 @@ function reload(context, apiClient, itemId) {
fillSubtitleList(context, item);
let file = item.Path || '';
- let index = Math.max(file.lastIndexOf('/'), file.lastIndexOf('\\'));
+ const index = Math.max(file.lastIndexOf('/'), file.lastIndexOf('\\'));
if (index > -1) {
file = file.substring(index + 1);
}
@@ -282,9 +282,9 @@ function reload(context, apiClient, itemId) {
}
function onSearchSubmit(e) {
- let form = this;
+ const form = this;
- let lang = form.querySelector('#selectLanguage', form).value;
+ const lang = form.querySelector('#selectLanguage', form).value;
searchForSubtitles(dom.parentWithClass(form, 'formDialogContent'), lang);
@@ -293,10 +293,10 @@ function onSearchSubmit(e) {
}
function onSubtitleListClick(e) {
- let btnDelete = dom.parentWithClass(e.target, 'btnDelete');
+ const btnDelete = dom.parentWithClass(e.target, 'btnDelete');
if (btnDelete) {
- let index = btnDelete.getAttribute('data-index');
- let context = dom.parentWithClass(btnDelete, 'subtitleEditorDialog');
+ const index = btnDelete.getAttribute('data-index');
+ const context = dom.parentWithClass(btnDelete, 'subtitleEditorDialog');
deleteLocalSubtitle(context, index);
}
}
@@ -305,14 +305,14 @@ function onSubtitleResultsClick(e) {
let subtitleId;
let context;
- let btnOptions = dom.parentWithClass(e.target, 'btnOptions');
+ const btnOptions = dom.parentWithClass(e.target, 'btnOptions');
if (btnOptions) {
subtitleId = btnOptions.getAttribute('data-subid');
context = dom.parentWithClass(btnOptions, 'subtitleEditorDialog');
showDownloadOptions(btnOptions, context, subtitleId);
}
- let btnDownload = dom.parentWithClass(e.target, 'btnDownload');
+ const btnDownload = dom.parentWithClass(e.target, 'btnDownload');
if (btnDownload) {
subtitleId = btnDownload.getAttribute('data-subid');
context = dom.parentWithClass(btnDownload, 'subtitleEditorDialog');
@@ -321,7 +321,7 @@ function onSubtitleResultsClick(e) {
}
function showDownloadOptions(button, context, subtitleId) {
- let items = [];
+ const items = [];
items.push({
name: globalize.translate('Download'),
@@ -347,7 +347,7 @@ function showDownloadOptions(button, context, subtitleId) {
function centerFocus(elem, horiz, on) {
import('scrollHelper').then(({default: scrollHelper}) => {
- let fn = on ? 'on' : 'off';
+ const fn = on ? 'on' : 'off';
scrollHelper.centerFocus[fn](elem, horiz);
});
}
@@ -355,9 +355,9 @@ function centerFocus(elem, horiz, on) {
function showEditorInternal(itemId, serverId, template) {
hasChanges = false;
- let apiClient = window.connectionManager.getApiClient(serverId);
+ const apiClient = window.connectionManager.getApiClient(serverId);
return apiClient.getItem(apiClient.getCurrentUserId(), itemId).then(function (item) {
- let dialogOptions = {
+ const dialogOptions = {
removeOnClose: true,
scrollY: false
};
@@ -368,7 +368,7 @@ function showEditorInternal(itemId, serverId, template) {
dialogOptions.size = 'small';
}
- let dlg = dialogHelper.createDialog(dialogOptions);
+ const dlg = dialogHelper.createDialog(dialogOptions);
dlg.classList.add('formDialog');
dlg.classList.add('subtitleEditorDialog');
@@ -379,7 +379,7 @@ function showEditorInternal(itemId, serverId, template) {
dlg.querySelector('.subtitleSearchForm').addEventListener('submit', onSearchSubmit);
- let btnSubmit = dlg.querySelector('.btnSubmit');
+ const btnSubmit = dlg.querySelector('.btnSubmit');
if (layoutManager.tv) {
centerFocus(dlg.querySelector('.formDialogContent'), false, true);
@@ -388,7 +388,7 @@ function showEditorInternal(itemId, serverId, template) {
btnSubmit.classList.add('hide');
}
- let editorContent = dlg.querySelector('.formDialogContent');
+ const editorContent = dlg.querySelector('.formDialogContent');
dlg.querySelector('.subtitleList').addEventListener('click', onSubtitleListClick);
dlg.querySelector('.subtitleResults').addEventListener('click', onSubtitleResultsClick);
diff --git a/src/components/viewContainer.js b/src/components/viewContainer.js
index c39ad2ba84..0c0b705b52 100644
--- a/src/components/viewContainer.js
+++ b/src/components/viewContainer.js
@@ -14,7 +14,7 @@ import 'css!components/viewManager/viewContainer';
}
controllerUrl = Dashboard.getPluginUrl(controllerUrl);
- let apiUrl = ApiClient.getUrl('/web/' + controllerUrl);
+ const apiUrl = ApiClient.getUrl('/web/' + controllerUrl);
return import(apiUrl).then((ControllerFactory) => {
options.controllerFactory = ControllerFactory;
});
diff --git a/src/controllers/movies/movies.js b/src/controllers/movies/movies.js
index e05b1fa96a..01111d4c1b 100644
--- a/src/controllers/movies/movies.js
+++ b/src/controllers/movies/movies.js
@@ -163,11 +163,11 @@ import 'emby-itemscontainer';
itemsContainer.fetchData = fetchData;
itemsContainer.getItemsHtml = getItemsHtml;
itemsContainer.afterRefresh = afterRefresh;
- let alphaPickerElement = tabContent.querySelector('.alphaPicker');
+ const alphaPickerElement = tabContent.querySelector('.alphaPicker');
if (alphaPickerElement) {
alphaPickerElement.addEventListener('alphavaluechanged', function (e) {
- let newValue = e.detail.value;
+ const newValue = e.detail.value;
query.NameStartsWith = newValue;
query.StartIndex = 0;
itemsContainer.refreshItems();
@@ -237,7 +237,7 @@ import 'emby-itemscontainer';
libraryBrowser.showLayoutMenu(e.target, this.getCurrentViewStyle, 'Banner,List,Poster,PosterCard,Thumb,ThumbCard'.split(','));
});
btnSelectView.addEventListener('layoutchange', function (e) {
- let viewStyle = e.detail.viewStyle;
+ const viewStyle = e.detail.viewStyle;
userSettings.set(savedViewKey, viewStyle);
query.StartIndex = 0;
onViewStyleChange();
@@ -274,7 +274,7 @@ import 'emby-itemscontainer';
this.showFilterMenu = function () {
import('components/filterdialog/filterdialog').then(({default: filterDialogFactory}) => {
- let filterDialog = new filterDialogFactory({
+ const filterDialog = new filterDialogFactory({
query: query,
mode: 'movies',
serverId: ApiClient.serverId()
diff --git a/src/controllers/movies/moviesrecommended.js b/src/controllers/movies/moviesrecommended.js
index 5b85fbadae..4036128b51 100644
--- a/src/controllers/movies/moviesrecommended.js
+++ b/src/controllers/movies/moviesrecommended.js
@@ -58,7 +58,7 @@ import 'emby-button';
}
function loadResume(page, userId, parentId) {
- let screenWidth = dom.getWindowSize().innerWidth;
+ const screenWidth = dom.getWindowSize().innerWidth;
const options = {
SortBy: 'DatePlayed',
SortOrder: 'Descending',
@@ -154,8 +154,8 @@ import 'emby-button';
}
function loadSuggestions(page, userId, parentId) {
- let screenWidth = dom.getWindowSize().innerWidth;
- let url = ApiClient.getUrl('Movies/Recommendations', {
+ const screenWidth = dom.getWindowSize().innerWidth;
+ const url = ApiClient.getUrl('Movies/Recommendations', {
userId: userId,
categoryLimit: 6,
ItemLimit: screenWidth >= 1920 ? 8 : screenWidth >= 1600 ? 8 : screenWidth >= 1200 ? 6 : 5,
@@ -172,7 +172,7 @@ import 'emby-button';
const html = recommendations.map(getRecommendationHtml).join('');
page.querySelector('.noItemsMessage').classList.add('hide');
- let recs = page.querySelector('.recommendations');
+ const recs = page.querySelector('.recommendations');
recs.innerHTML = html;
imageLoader.lazyChildren(recs);
@@ -381,16 +381,16 @@ import 'emby-button';
const suggestionsTabIndex = 1;
this.initTab = function () {
- let tabContent = view.querySelector(".pageTabContent[data-index='" + suggestionsTabIndex + "']");
+ const tabContent = view.querySelector(".pageTabContent[data-index='" + suggestionsTabIndex + "']");
initSuggestedTab(view, tabContent);
};
this.renderTab = function () {
- let tabContent = view.querySelector(".pageTabContent[data-index='" + suggestionsTabIndex + "']");
+ const tabContent = view.querySelector(".pageTabContent[data-index='" + suggestionsTabIndex + "']");
loadSuggestionsTab(view, params, tabContent);
};
- let tabControllers = [];
+ const tabControllers = [];
let renderedTabs = [];
view.addEventListener('viewshow', function (e) {
initTabs();
diff --git a/src/plugins/comicsPlayer/plugin.js b/src/plugins/comicsPlayer/plugin.js
index 7d0ac92df9..2928231391 100644
--- a/src/plugins/comicsPlayer/plugin.js
+++ b/src/plugins/comicsPlayer/plugin.js
@@ -19,14 +19,14 @@ export class ComicsPlayer {
play(options) {
this.progress = 0;
- let elem = this.createMediaElement();
+ const elem = this.createMediaElement();
return this.setCurrentSrc(elem, options);
}
stop() {
this.unbindEvents();
- let elem = this.mediaElement;
+ const elem = this.mediaElement;
if (elem) {
dialogHelper.close(elem);
this.mediaElement = null;
@@ -40,7 +40,7 @@ export class ComicsPlayer {
}
onWindowKeyUp(e) {
- let key = keyboardnavigation.getKeyName(e);
+ const key = keyboardnavigation.getKeyName(e);
switch (key) {
case 'Escape':
this.stop();
@@ -87,20 +87,20 @@ export class ComicsPlayer {
}
setCurrentSrc(elem, options) {
- let item = options.items[0];
+ const item = options.items[0];
this.currentItem = item;
loading.show();
- let serverId = item.ServerId;
- let apiClient = window.connectionManager.getApiClient(serverId);
+ const serverId = item.ServerId;
+ const apiClient = window.connectionManager.getApiClient(serverId);
libarchive.Archive.init({
workerUrl: appRouter.baseUrl() + '/libraries/worker-bundle.js'
});
return new Promise((resolve, reject) => {
- let downloadUrl = apiClient.getItemDownloadUrl(item.Id);
+ const downloadUrl = apiClient.getItemDownloadUrl(item.Id);
const archiveSource = new ArchiveSource(downloadUrl);
var instance = this;
@@ -169,18 +169,18 @@ class ArchiveSource {
}
async load() {
- let res = await fetch(this.url);
+ const res = await fetch(this.url);
if (!res.ok) {
return;
}
- let blob = await res.blob();
+ const blob = await res.blob();
this.archive = await libarchive.Archive.open(blob);
this.raw = await this.archive.getFilesArray();
this.numberOfFiles = this.raw.length;
await this.archive.extractFiles();
- let files = await this.archive.getFilesArray();
+ const files = await this.archive.getFilesArray();
files.sort((a, b) => {
if (a.file.name < b.file.name) {
return -1;
@@ -189,9 +189,9 @@ class ArchiveSource {
}
});
- for (let file of files) {
+ for (const file of files) {
/* eslint-disable-next-line compat/compat */
- let url = URL.createObjectURL(file.file);
+ const url = URL.createObjectURL(file.file);
this.urls.push(url);
}
}
diff --git a/src/scripts/clientUtils.js b/src/scripts/clientUtils.js
index 4d3c049e8c..73801867c0 100644
--- a/src/scripts/clientUtils.js
+++ b/src/scripts/clientUtils.js
@@ -141,7 +141,7 @@ export function alert(options) {
}
export function capabilities(appHost) {
- let capabilities = {
+ const 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: window.appMode === 'cordova' || window.appMode === 'android',
From 6b6841c8c81ab3c24da9b85f008e5601cd3758dd Mon Sep 17 00:00:00 2001
From: Cameron
Date: Fri, 11 Sep 2020 22:39:53 +0100
Subject: [PATCH 049/365] Update CONTRIBUTORS.md
---
CONTRIBUTORS.md | 1 +
1 file changed, 1 insertion(+)
diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md
index 778d899ef7..672795cce1 100644
--- a/CONTRIBUTORS.md
+++ b/CONTRIBUTORS.md
@@ -39,6 +39,7 @@
- [Andrei Oanca](https://github.com/OancaAndrei)
- [Cromefire_](https://github.com/cromefire)
- [Orry Verducci](https://github.com/orryverducci)
+ - [Camc314](https://github.com/camc314)
# Emby Contributors
From 09c7d73c633938a0f25d4bf45462208bda870676 Mon Sep 17 00:00:00 2001
From: ben-dl
Date: Fri, 11 Sep 2020 21:37:22 +0000
Subject: [PATCH 050/365] Translated using Weblate (German) Translation:
Jellyfin/Jellyfin Web Translate-URL:
https://translate.jellyfin.org/projects/jellyfin/jellyfin-web/de/
---
src/strings/de.json | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/src/strings/de.json b/src/strings/de.json
index 4baee1cb69..b0af47256e 100644
--- a/src/strings/de.json
+++ b/src/strings/de.json
@@ -1376,5 +1376,6 @@
"LabelOpenclDevice": "OpenCL-Gerät:",
"LabelColorSpace": "Farbraum:",
"MediaInfoColorSpace": "Farbraum",
- "VideoAudio": "Videoton"
+ "VideoAudio": "Videoton",
+ "AllowTonemappingHelp": "Tone Mapping kann die Dynamic Range eines Videos von HDR zu SDR umwandeln und dabei Bilddetails und Farben beibehalten. Dies funktioniert zur Zeit nur mit dem NVENC HEVC-Decoder beim Transkodieren von HDR10 oder HLG-Videos."
}
From db98cf09b66b4a1fb6e3a0dfeb421e9fff29fa57 Mon Sep 17 00:00:00 2001
From: millallo
Date: Sat, 12 Sep 2020 06:04:52 +0000
Subject: [PATCH 051/365] Translated using Weblate (Italian) Translation:
Jellyfin/Jellyfin Web Translate-URL:
https://translate.jellyfin.org/projects/jellyfin/jellyfin-web/it/
---
src/strings/it.json | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/src/strings/it.json b/src/strings/it.json
index e56bb17d6d..60f312a4c6 100644
--- a/src/strings/it.json
+++ b/src/strings/it.json
@@ -1370,5 +1370,7 @@
"Other": "Altro",
"Data": "Dati",
"Bwdif": "BWDIF",
- "UseDoubleRateDeinterlacing": "Raddoppia il frame rate durante il deinterlacciamento"
+ "UseDoubleRateDeinterlacing": "Raddoppia il frame rate durante il deinterlacciamento",
+ "KnownProxiesHelp": "Lista degli IP separati da virgola dei proxy utilizzati per connettersi a Jellyfin. Ciò consente di gestire al meglio gli header X-Forwarded-For. Richiede il reboot.",
+ "LabelKnownProxies": "Proxy conosciuti:"
}
From 141787281a15bf1e6ae1df630893f715660c3b4b Mon Sep 17 00:00:00 2001
From: Oatavandi
Date: Sat, 12 Sep 2020 07:20:25 +0000
Subject: [PATCH 052/365] Translated using Weblate (Tamil) Translation:
Jellyfin/Jellyfin Web Translate-URL:
https://translate.jellyfin.org/projects/jellyfin/jellyfin-web/ta/
---
src/strings/ta.json | 30 +++++++++++++++++++++++++++++-
1 file changed, 29 insertions(+), 1 deletion(-)
diff --git a/src/strings/ta.json b/src/strings/ta.json
index f17e623a7a..db359774fc 100644
--- a/src/strings/ta.json
+++ b/src/strings/ta.json
@@ -1388,5 +1388,33 @@
"Other": "மற்றவை",
"Bwdif": "BWDIF",
"UseDoubleRateDeinterlacingHelp": "டீஇன்டர்லேசிங் செய்யும் போது இந்த அமைப்பு புலம் வீதத்தைப் பயன்படுத்துகிறது, இது பெரும்பாலும் பாப் டீஇன்டர்லேசிங் என அழைக்கப்படுகிறது, இது டிவியில் ஒன்றோடொன்று இணைக்கப்பட்ட வீடியோவைப் பார்க்கும்போது நீங்கள் பார்ப்பது போன்ற முழு இயக்கத்தையும் வழங்க வீடியோவின் பிரேம் வீதத்தை இரட்டிப்பாக்குகிறது.",
- "UseDoubleRateDeinterlacing": "செயலிழக்கும்போது பிரேம் வீதத்தை இரட்டிப்பாக்குங்கள்"
+ "UseDoubleRateDeinterlacing": "செயலிழக்கும்போது பிரேம் வீதத்தை இரட்டிப்பாக்குங்கள்",
+ "LabelMaxMuxingQueueSizeHelp": "அனைத்து ஸ்ட்ரீம்களையும் துவக்கக் காத்திருக்கும்போது இடையகப்படுத்தக்கூடிய அதிகபட்ச பாக்கெட்டுகள். Ffmpeg பதிவுகளில் \"வெளியீட்டு ஸ்ட்ரீமுக்கு இடையகப்படுத்தப்பட்ட பல பாக்கெட்டுகள்\" பிழையை நீங்கள் இன்னும் சந்தித்தால் அதை அதிகரிக்க முயற்சிக்கவும். பரிந்துரைக்கப்பட்ட மதிப்பு 2048 ஆகும்.",
+ "LabelMaxMuxingQueueSize": "அதிகபட்ச மக்ஸிங் வரிசை அளவு:",
+ "LabelTonemappingParamHelp": "டோன் மேப்பிங் வழிமுறையை டியூன் செய்யுங்கள். பரிந்துரைக்கப்பட்ட மற்றும் இயல்புநிலை மதிப்புகள் NaN ஆகும். பொதுவாக அதை காலியாக விடவும்.",
+ "LabelTonemappingParam": "டோன் மேப்பிங் அளவுரு:",
+ "LabelTonemappingPeakHelp": "இந்த மதிப்புடன் சமிக்ஞை / பெயரளவு / குறிப்பு உச்சத்தை மேலெழுதவும். காட்சி மெட்டாடேட்டாவில் உட்பொதிக்கப்பட்ட உச்ச தகவல் நம்பகத்தன்மையற்றதாக இருக்கும்போது அல்லது குறைந்த வரம்பிலிருந்து அதிக வரம்பிற்கு டோன் மேப்பிங் செய்யும்போது பயனுள்ளதாக இருக்கும். பரிந்துரைக்கப்பட்ட மற்றும் இயல்புநிலை மதிப்புகள் 0 ஆகும்.",
+ "LabelTonemappingPeak": "டோன் மேப்பிங் உச்சம்:",
+ "LabelTonemappingThresholdHelp": "டோன் மேப்பிங் அல்காரிதம் அளவுருக்கள் ஒவ்வொரு காட்சிக்கும் நன்றாக வடிவமைக்கப்பட்டுள்ளன. காட்சி மாறிவிட்டதா இல்லையா என்பதைக் கண்டறிய ஒரு வாசல் பயன்படுத்தப்படுகிறது. தற்போதைய சட்ட சராசரி பிரகாசத்திற்கும் தற்போதைய இயங்கும் சராசரிக்கும் இடையிலான தூரம் ஒரு நுழைவு மதிப்பை மீறினால், காட்சி சராசரி மற்றும் உச்ச பிரகாசத்தை மீண்டும் கணக்கிடுவோம். பரிந்துரைக்கப்பட்ட மற்றும் இயல்புநிலை மதிப்புகள் 0.8 மற்றும் 0.2 ஆகும்.",
+ "LabelTonemappingThreshold": "டோன் மேப்பிங் தொடக்கநிலை:",
+ "LabelTonemappingDesatHelp": "இந்த பிரகாசத்தின் அளவைத் தாண்டிய சிறப்பம்சங்களுக்கு தேய்மானத்தைப் பயன்படுத்துங்கள். அதிக அளவுரு, அதிக வண்ண தகவல்கள் பாதுகாக்கப்படும். இந்த அமைப்பு சூப்பர்-சிறப்பம்சங்களுக்கான இயற்கைக்கு மாறான வண்ணங்களைத் தடுக்க உதவுகிறது, அதற்கு பதிலாக (சுமூகமாக) வெள்ளை நிறமாக மாறுவதன் மூலம். இது வரம்பற்ற வண்ணங்களைப் பற்றிய தகவல்களைக் குறைக்கும் செலவில், படங்கள் மிகவும் இயல்பானதாக உணரவைக்கும். பரிந்துரைக்கப்பட்ட மற்றும் இயல்புநிலை மதிப்புகள் 0 மற்றும் 0.5 ஆகும்.",
+ "LabelTonemappingDesat": "டோன் மேப்பிங் டெசாட்:",
+ "TonemappingRangeHelp": "வெளியீட்டு வண்ண வரம்பைத் தேர்ந்தெடுக்கவும். ஆட்டோ என்பது உள்ளீட்டு வரம்பைப் போன்றது.",
+ "LabelTonemappingRange": "டோன் மேப்பிங் வரம்பு:",
+ "TonemappingAlgorithmHelp": "டோன் மேப்பிங் நன்றாக இருக்கும். இந்த விருப்பங்களை நீங்கள் அறிந்திருக்கவில்லை என்றால், இயல்புநிலையை வைத்திருங்கள்.
பரிந்துரைக்கப்பட்ட மதிப்பு ரெய்ன்ஹார்ட்.",
+ "LabelTonemappingAlgorithm": "பயன்படுத்த டோன் மேப்பிங் வழிமுறையைத் தேர்ந்தெடுக்கவும்:",
+ "AllowTonemappingHelp": "டோன் மேப்பிங் ஒரு வீடியோவின் டைனமிக் வரம்பை எச்.டி.ஆரிலிருந்து எஸ்.டி.ஆருக்கு மாற்றும், அதே நேரத்தில் பட விவரங்களையும் வண்ணங்களையும் பராமரிக்கும், அவை அசல் காட்சியைக் குறிக்கும் மிக முக்கியமான தகவல்கள். தற்போது NVENC HEVC டிகோடரைப் பயன்படுத்தும்போது மற்றும் HDR10 அல்லது HLG வீடியோக்களை டிரான்ஸ்கோடிங் செய்யும் போது மட்டுமே செயல்படும்.",
+ "EnableTonemapping": "டோன் மேப்பிங்கை இயக்கு",
+ "LabelOpenclDeviceHelp": "இது ஓப்பன்சிஎல் சாதனம் ஆகும், இது டன்மேப்பிங்கிற்கு பயன்படுத்தப்படுகிறது. புள்ளியின் இடது புறம் இயங்குதள எண், மற்றும் வலது புறம் இயங்குதளத்தின் சாதன எண். இயல்புநிலை மதிப்பு 0.0. OpenCL வன்பொருள் முடுக்கம் முறையைக் கொண்ட ffmpeg பயன்பாட்டுக் கோப்பு தேவை.",
+ "LabelOpenclDevice": "OpenCL சாதனம்:",
+ "LabelColorPrimaries": "வண்ண முதன்மைகள்:",
+ "LabelColorTransfer": "வண்ண பரிமாற்றம்:",
+ "LabelColorSpace": "வண்ண இடம்:",
+ "LabelVideoRange": "வீடியோ வரம்பு:",
+ "MediaInfoColorPrimaries": "வண்ண முதன்மைகள்",
+ "MediaInfoColorTransfer": "வண்ண பரிமாற்றம்",
+ "MediaInfoColorSpace": "வண்ண இடம்",
+ "MediaInfoVideoRange": "வீடியோ வரம்பு",
+ "LabelKnownProxies": "அறியப்பட்ட பிரதிநிதிகள்:",
+ "KnownProxiesHelp": "உங்கள் ஜெல்லிஃபின் நிகழ்வோடு இணைக்கும்போது பயன்படுத்தப்படும் அறியப்பட்ட ப்ராக்ஸிகளின் ஐபி முகவரிகளின் கமாவால் பிரிக்கப்பட்ட பட்டியல். எக்ஸ்-ஃபார்வர்ட்-ஃபார் தலைப்புகளை முறையாகப் பயன்படுத்த இது தேவைப்படுகிறது. சேமித்த பிறகு மறுதொடக்கம் தேவை."
}
From 2023ce37eb8b760269c43df9e46d69208aeea69a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Kucharczyk?=
Date: Sat, 12 Sep 2020 11:20:21 +0000
Subject: [PATCH 053/365] Translated using Weblate (Czech) Translation:
Jellyfin/Jellyfin Web Translate-URL:
https://translate.jellyfin.org/projects/jellyfin/jellyfin-web/cs/
---
src/strings/cs.json | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/src/strings/cs.json b/src/strings/cs.json
index 697f13ea7f..15cb46f70a 100644
--- a/src/strings/cs.json
+++ b/src/strings/cs.json
@@ -1397,5 +1397,9 @@
"MediaInfoColorPrimaries": "Primární barvy",
"MediaInfoColorTransfer": "Převod barev",
"MediaInfoColorSpace": "Barevný prostor",
- "MediaInfoVideoRange": "Rozsah videa"
+ "MediaInfoVideoRange": "Rozsah videa",
+ "LabelMaxMuxingQueueSizeHelp": "Maximální počet paketů, které je možné napřed načíst při čekání na spuštění všech proudů. Pokud se stále zobrazuje chyba \"Příliš mnoho paketů načtených napřed ve výstupním proudu\" v protokolech ffmpeg, zkuste hodnotu zvýšit. Doporučená hodnota je 2048.",
+ "LabelMaxMuxingQueueSize": "Maximální velikost muxovací fronty:",
+ "LabelKnownProxies": "Známé proxy servery:",
+ "KnownProxiesHelp": "Čárkami oddělený seznam IP adres známých proxy serverů pro připojení k instanci Jellyfin. Vyžadováno pro správné využití HTTP hlavičky X-Forwarded-For. Vyžaduje restart."
}
From 70d7a561c5f4e9508782774374fb518e52ae7cb7 Mon Sep 17 00:00:00 2001
From: Thomas Schwery
Date: Sat, 12 Sep 2020 11:28:16 +0000
Subject: [PATCH 054/365] Translated using Weblate (French) Translation:
Jellyfin/Jellyfin Web Translate-URL:
https://translate.jellyfin.org/projects/jellyfin/jellyfin-web/fr/
---
src/strings/fr.json | 19 ++++++++++++++++++-
1 file changed, 18 insertions(+), 1 deletion(-)
diff --git a/src/strings/fr.json b/src/strings/fr.json
index 587bc1a555..907c67f23e 100644
--- a/src/strings/fr.json
+++ b/src/strings/fr.json
@@ -1373,5 +1373,22 @@
"PosterCard": "Affiche",
"UseDoubleRateDeinterlacing": "Multiplier par deux la fréquence d'images lors du désentrelacement",
"Bwdif": "BWDIF",
- "UseDoubleRateDeinterlacingHelp": "Ce réglage utilise la fréquence de trame lors du désentrelacement, souvent appelé \"bob deinterlacing\", qui double la fréquence d'image de la vidéo pour fournir un mouvement fluide comme en regardant une vidéo entrelacée sur un téléviseur."
+ "UseDoubleRateDeinterlacingHelp": "Ce réglage utilise la fréquence de trame lors du désentrelacement, souvent appelé \"bob deinterlacing\", qui double la fréquence d'image de la vidéo pour fournir un mouvement fluide comme en regardant une vidéo entrelacée sur un téléviseur.",
+ "LabelTonemappingDesat": "Désaturation tonale :",
+ "TonemappingRangeHelp": "Sélectionnez la gamme de couleur de sortie. Auto représente la même gamme qu'en entrée.",
+ "LabelTonemappingRange": "Gamme de mappage tonal :",
+ "TonemappingAlgorithmHelp": "Le mappage tonal peut être affiné. Si vous n'êtes pas familier avec ces options, gardez les valeurs par défaut.
La valeur recommandée est Reinhard.",
+ "LabelTonemappingAlgorithm": "Sélectionnez l'algorithme de mappage tonal à utiliser :",
+ "AllowTonemappingHelp": "Le mappage tonal peut transformer la gamme dynamique d'une vidéo de HDR à SDR tout en maintenant les détails et les couleurs d'image qui sont des informations importantes pour la représentation de la scène originale. Actuellement, ne fonctionne uniquement lorsque le décodeur NVENC HEVC est utilisé et que des vidéos HDR10 ou HLG sont transcodées.",
+ "EnableTonemapping": "Activer le mappage tonal",
+ "LabelOpenclDeviceHelp": "Ce dispositif OpenCL est utilisé pour le mappage tonal. La partie à gauche du point est le numéro de plate-forme et la partie à droite est le numéro du dispositif sur la plate-forme. La valeur par défaut est 0.0. Le fichier de l'application ffmpeg contenant l'accélération matérielle OpenCL est nécessaire.",
+ "LabelOpenclDevice": "Dispositif OpenCL :",
+ "LabelColorPrimaries": "Couleurs primaires :",
+ "LabelColorTransfer": "Transfert couleur :",
+ "LabelColorSpace": "Espace couleur :",
+ "MediaInfoColorPrimaries": "Couleurs primaires",
+ "MediaInfoColorTransfer": "Transfert couleur",
+ "MediaInfoColorSpace": "Espace couleur",
+ "LabelKnownProxies": "Proxies connus :",
+ "KnownProxiesHelp": "Liste séparée par des virgules d'adresses IP des proxies connus utilisés pour se connecter à l'instance Jellyfin. Ceci est nécessaire afin de pouvoir utiliser correctement les entêtes X-Forwarded-For. Nécessite un redémarrage après sauvegarde."
}
From 1dd771d446a3b55efabe1d18ecff62f527ca0388 Mon Sep 17 00:00:00 2001
From: Thomas Schwery
Date: Sat, 12 Sep 2020 12:07:41 +0000
Subject: [PATCH 055/365] Translated using Weblate (French) Translation:
Jellyfin/Jellyfin Web Translate-URL:
https://translate.jellyfin.org/projects/jellyfin/jellyfin-web/fr/
---
src/strings/fr.json | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/src/strings/fr.json b/src/strings/fr.json
index 907c67f23e..ed243f98a4 100644
--- a/src/strings/fr.json
+++ b/src/strings/fr.json
@@ -1390,5 +1390,7 @@
"MediaInfoColorTransfer": "Transfert couleur",
"MediaInfoColorSpace": "Espace couleur",
"LabelKnownProxies": "Proxies connus :",
- "KnownProxiesHelp": "Liste séparée par des virgules d'adresses IP des proxies connus utilisés pour se connecter à l'instance Jellyfin. Ceci est nécessaire afin de pouvoir utiliser correctement les entêtes X-Forwarded-For. Nécessite un redémarrage après sauvegarde."
+ "KnownProxiesHelp": "Liste séparée par des virgules d'adresses IP des proxies connus utilisés pour se connecter à l'instance Jellyfin. Ceci est nécessaire afin de pouvoir utiliser correctement les entêtes X-Forwarded-For. Nécessite un redémarrage après sauvegarde.",
+ "LabelTonemappingThreshold": "Seuil de mappage tonal :",
+ "LabelTonemappingDesatHelp": "Désature les couleurs qui dépassent ce niveau de luminosité. Plus ce paramètre est élevé, plus les informations de couleur seront préservées. Ce paramètre permet d'éviter les couleurs anormalement éclatantes pour les couleurs super-lumineuses en les transformant (de manière lisse) en blanc. Ceci rend l'image plus naturelle au prix d'une réduction d'information dans les couleurs hors-gamme. Les valeurs recommandées et par défaut sont 0 et 0.5."
}
From 8f24c4d2c94b0e712028858b45ae8f7793578da1 Mon Sep 17 00:00:00 2001
From: Moritz
Date: Sat, 12 Sep 2020 19:50:13 +0000
Subject: [PATCH 056/365] Translated using Weblate (German) Translation:
Jellyfin/Jellyfin Web Translate-URL:
https://translate.jellyfin.org/projects/jellyfin/jellyfin-web/de/
---
src/strings/de.json | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/src/strings/de.json b/src/strings/de.json
index b0af47256e..d6104fba72 100644
--- a/src/strings/de.json
+++ b/src/strings/de.json
@@ -1377,5 +1377,10 @@
"LabelColorSpace": "Farbraum:",
"MediaInfoColorSpace": "Farbraum",
"VideoAudio": "Videoton",
- "AllowTonemappingHelp": "Tone Mapping kann die Dynamic Range eines Videos von HDR zu SDR umwandeln und dabei Bilddetails und Farben beibehalten. Dies funktioniert zur Zeit nur mit dem NVENC HEVC-Decoder beim Transkodieren von HDR10 oder HLG-Videos."
+ "AllowTonemappingHelp": "Tone Mapping kann die Dynamic Range eines Videos von HDR zu SDR umwandeln und dabei Bilddetails und Farben beibehalten. Dies funktioniert zur Zeit nur mit dem NVENC HEVC-Decoder beim Transkodieren von HDR10 oder HLG-Videos.",
+ "TonemappingRangeHelp": "Wählen Sie den Ausgabefarbbereich aus. Auto ist derselbe wie der Eingabebereich.",
+ "TonemappingAlgorithmHelp": "Das Tonemapping kann fein abgestimmt werden. Wenn Sie mit diesen Optionen nicht vertraut sind, behalten Sie einfach den Standardwert bei.
Der empfohlene Wert ist Reinhard.",
+ "LabelTonemappingAlgorithm": "Wählen Sie den zu verwendenden Tonemapping-Algorithmus aus:",
+ "LabelKnownProxies": "Bekannte Proxys:",
+ "KnownProxiesHelp": "Kommagetrennte Liste von IP-Adressen bekannter Proxys, die bei der Verbindung mit Ihrer Jellyfin-Instanz verwendet werden. Dies ist erforderlich, um die X-Forwarded-For-Header korrekt verwenden zu können. Erfordert nach dem Speichern einen Neustart."
}
From 1014c6cd352b0d702f341a761018e1ee2a513336 Mon Sep 17 00:00:00 2001
From: millallo
Date: Sun, 13 Sep 2020 17:59:00 +0000
Subject: [PATCH 057/365] Translated using Weblate (Italian) Translation:
Jellyfin/Jellyfin Web Translate-URL:
https://translate.jellyfin.org/projects/jellyfin/jellyfin-web/it/
---
src/strings/it.json | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/strings/it.json b/src/strings/it.json
index 60f312a4c6..f1e30b754f 100644
--- a/src/strings/it.json
+++ b/src/strings/it.json
@@ -568,7 +568,7 @@
"LabelModelName": "Nome Modello",
"LabelModelNumber": "Numero Modello",
"LabelModelUrl": "Modello URL",
- "LabelMonitorUsers": "Monitora l'attività da:",
+ "LabelMonitorUsers": "Monitora l'attività di:",
"LabelMovieCategories": "Categorie film:",
"LabelMoviePrefix": "Prefisso film:",
"LabelMoviePrefixHelp": "Se un prefisso viene applicato ai titoli di film, inseriscilo qui in modo che il server possa gestirlo correttamente.",
From 71c44dccd6ab690bb720b47d01ec1c9b26bcf12d Mon Sep 17 00:00:00 2001
From: grafixeyehero
Date: Mon, 14 Sep 2020 00:04:55 +0300
Subject: [PATCH 058/365] move music tabs suggestions to the second position
---
.../homeScreenSettings/homeScreenSettings.js | 8 ++--
src/controllers/music/music.html | 40 +++++++++----------
src/controllers/music/musicrecommended.js | 19 ++++-----
src/controllers/shows/tvrecommended.js | 34 ++++++++--------
4 files changed, 51 insertions(+), 50 deletions(-)
diff --git a/src/components/homeScreenSettings/homeScreenSettings.js b/src/components/homeScreenSettings/homeScreenSettings.js
index 3348348f20..5825d19a24 100644
--- a/src/components/homeScreenSettings/homeScreenSettings.js
+++ b/src/components/homeScreenSettings/homeScreenSettings.js
@@ -88,13 +88,13 @@ import 'emby-checkbox';
});
} else if (type === 'music') {
list.push({
- name: globalize.translate('Suggestions'),
- value: 'suggestions',
+ name: globalize.translate('Albums'),
+ value: 'albums',
isDefault: true
});
list.push({
- name: globalize.translate('Albums'),
- value: 'albums'
+ name: globalize.translate('Suggestions'),
+ value: 'suggestions'
});
list.push({
name: globalize.translate('HeaderAlbumArtists'),
diff --git a/src/controllers/music/music.html b/src/controllers/music/music.html
index 84d324857d..aba8379f81 100644
--- a/src/controllers/music/music.html
+++ b/src/controllers/music/music.html
@@ -8,7 +8,26 @@
}
}
-
+
+
-
diff --git a/src/controllers/music/musicrecommended.js b/src/controllers/music/musicrecommended.js
index a93bfea4e3..7b11a8eb21 100644
--- a/src/controllers/music/musicrecommended.js
+++ b/src/controllers/music/musicrecommended.js
@@ -177,9 +177,9 @@ import 'flexStyles';
function getTabs() {
return [{
- name: globalize.translate('Suggestions')
- }, {
name: globalize.translate('Albums')
+ }, {
+ name: globalize.translate('Suggestions')
}, {
name: globalize.translate('HeaderAlbumArtists')
}, {
@@ -195,7 +195,7 @@ import 'flexStyles';
function getDefaultTabIndex(folderId) {
switch (userSettings.get('landing-' + folderId)) {
- case 'albums':
+ case 'suggestions':
return 1;
case 'albumartists':
@@ -221,7 +221,7 @@ import 'flexStyles';
export default function (view, params) {
function reload() {
loading.show();
- const tabContent = view.querySelector(".pageTabContent[data-index='0']");
+ const tabContent = view.querySelector(".pageTabContent[data-index='" + suggestionsTabIndex + "']");
loadSuggestionsTab(view, tabContent, params.topParentId);
}
@@ -268,11 +268,11 @@ import 'flexStyles';
switch (index) {
case 0:
- depends = 'controllers/music/musicrecommended';
+ depends = 'controllers/music/musicalbums';
break;
case 1:
- depends = 'controllers/music/musicalbums';
+ depends = 'controllers/music/musicrecommended';
break;
case 2:
@@ -296,7 +296,7 @@ import 'flexStyles';
import(depends).then(({default: controllerFactory}) => {
let tabContent;
- if (index == 0) {
+ if (index == 1) {
tabContent = view.querySelector(".pageTabContent[data-index='" + index + "']");
this.tabContent = tabContent;
}
@@ -306,7 +306,7 @@ import 'flexStyles';
if (!controller) {
tabContent = view.querySelector(".pageTabContent[data-index='" + index + "']");
- if (index === 0) {
+ if (index === 1) {
controller = this;
} else if (index === 7) {
controller = new controllerFactory(view, tabContent, {
@@ -360,9 +360,10 @@ import 'flexStyles';
}
let currentTabIndex = parseInt(params.tab || getDefaultTabIndex(params.topParentId));
+ const suggestionsTabIndex = 1;
this.initTab = function () {
- const tabContent = view.querySelector(".pageTabContent[data-index='0']");
+ const tabContent = view.querySelector(".pageTabContent[data-index='" + suggestionsTabIndex + "']");
const containers = tabContent.querySelectorAll('.itemsContainer');
for (let i = 0, length = containers.length; i < length; i++) {
diff --git a/src/controllers/shows/tvrecommended.js b/src/controllers/shows/tvrecommended.js
index 048d27d45d..da47f9f318 100644
--- a/src/controllers/shows/tvrecommended.js
+++ b/src/controllers/shows/tvrecommended.js
@@ -66,16 +66,16 @@ import 'emby-button';
}
function initSuggestedTab(page, tabContent) {
- var containers = tabContent.querySelectorAll('.itemsContainer');
+ const containers = tabContent.querySelectorAll('.itemsContainer');
- for (var i = 0, length = containers.length; i < length; i++) {
+ for (let i = 0, length = containers.length; i < length; i++) {
setScrollClasses(containers[i], enableScrollX());
}
}
function loadSuggestionsTab(view, params, tabContent) {
- var parentId = params.topParentId;
- var userId = ApiClient.getCurrentUserId();
+ const parentId = params.topParentId;
+ const userId = ApiClient.getCurrentUserId();
console.debug('loadSuggestionsTab');
loadResume(tabContent, userId, parentId);
loadLatest(tabContent, userId, parentId);
@@ -83,8 +83,8 @@ import 'emby-button';
}
function loadResume(view, userId, parentId) {
- var screenWidth = dom.getWindowSize().innerWidth;
- var options = {
+ const screenWidth = dom.getWindowSize().innerWidth;
+ const options = {
SortBy: 'DatePlayed',
SortOrder: 'Descending',
IncludeItemTypes: 'Episode',
@@ -105,8 +105,8 @@ import 'emby-button';
view.querySelector('#resumableSection').classList.add('hide');
}
- var allowBottomPadding = !enableScrollX();
- var container = view.querySelector('#resumableItems');
+ const allowBottomPadding = !enableScrollX();
+ const container = view.querySelector('#resumableItems');
cardBuilder.buildCards(result.Items, {
itemsContainer: container,
preferThumb: true,
@@ -128,7 +128,7 @@ import 'emby-button';
}
function loadLatest(view, userId, parentId) {
- var options = {
+ const options = {
userId: userId,
IncludeItemTypes: 'Episode',
Limit: 30,
@@ -138,9 +138,9 @@ import 'emby-button';
EnableImageTypes: 'Primary,Backdrop,Thumb'
};
ApiClient.getLatestItems(options).then(function (items) {
- var section = view.querySelector('#latestItemsSection');
- var allowBottomPadding = !enableScrollX();
- var container = section.querySelector('#latestEpisodesItems');
+ const section = view.querySelector('#latestItemsSection');
+ const allowBottomPadding = !enableScrollX();
+ const container = section.querySelector('#latestEpisodesItems');
cardBuilder.buildCards(items, {
parentContainer: section,
itemsContainer: container,
@@ -169,7 +169,7 @@ import 'emby-button';
}
function loadNextUp(view, userId, parentId) {
- var query = {
+ const query = {
userId: userId,
Limit: 24,
Fields: 'PrimaryImageAspectRatio,SeriesInfo,DateCreated,BasicSyncInfo',
@@ -186,8 +186,8 @@ import 'emby-button';
view.querySelector('.noNextUpItems').classList.remove('hide');
}
- var section = view.querySelector('#nextUpItemsSection');
- var container = section.querySelector('#nextUpItems');
+ const section = view.querySelector('#nextUpItemsSection');
+ const container = section.querySelector('#nextUpItems');
cardBuilder.buildCards(result.Items, {
parentContainer: section,
itemsContainer: container,
@@ -345,12 +345,12 @@ import 'emby-button';
const suggestionsTabIndex = 1;
self.initTab = function () {
- var tabContent = view.querySelector(".pageTabContent[data-index='" + suggestionsTabIndex + "']");
+ const tabContent = view.querySelector(".pageTabContent[data-index='" + suggestionsTabIndex + "']");
initSuggestedTab(view, tabContent);
};
self.renderTab = function () {
- var tabContent = view.querySelector(".pageTabContent[data-index='" + suggestionsTabIndex + "']");
+ const tabContent = view.querySelector(".pageTabContent[data-index='" + suggestionsTabIndex + "']");
loadSuggestionsTab(view, params, tabContent);
};
From 3cc20ce480df43a23a3f6562436f4cac26112161 Mon Sep 17 00:00:00 2001
From: grafixeyehero
Date: Mon, 14 Sep 2020 01:09:59 +0300
Subject: [PATCH 059/365] add more Landing Screen Options
---
.../homeScreenSettings/homeScreenSettings.js | 12 ++++++++----
src/controllers/movies/movies.html | 12 ++++++------
src/controllers/music/music.html | 2 +-
src/controllers/shows/tvrecommended.html | 2 +-
src/controllers/shows/tvrecommended.js | 10 ++++++++--
5 files changed, 24 insertions(+), 14 deletions(-)
diff --git a/src/components/homeScreenSettings/homeScreenSettings.js b/src/components/homeScreenSettings/homeScreenSettings.js
index 5825d19a24..5138935408 100644
--- a/src/components/homeScreenSettings/homeScreenSettings.js
+++ b/src/components/homeScreenSettings/homeScreenSettings.js
@@ -75,16 +75,20 @@ import 'emby-checkbox';
value: 'suggestions'
});
list.push({
- name: globalize.translate('Latest'),
- value: 'latest'
+ name: globalize.translate('Upcoming'),
+ value: 'upcoming'
});
list.push({
name: globalize.translate('Genres'),
value: 'genres'
});
list.push({
- name: globalize.translate('Favorites'),
- value: 'favorites'
+ name: globalize.translate('Networks'),
+ value: 'networks'
+ });
+ list.push({
+ name: globalize.translate('Episodes'),
+ value: 'episodes'
});
} else if (type === 'music') {
list.push({
diff --git a/src/controllers/movies/movies.html b/src/controllers/movies/movies.html
index dddda3f7f9..5c905d1225 100644
--- a/src/controllers/movies/movies.html
+++ b/src/controllers/movies/movies.html
@@ -1,6 +1,6 @@
-
+
-
+
${HeaderContinueWatching}
@@ -43,7 +43,7 @@
${MessageNoMovieSuggestionsAvailable}
-
+
-
+
-
+
-
+
diff --git a/src/controllers/music/music.html b/src/controllers/music/music.html
index aba8379f81..0ec339db95 100644
--- a/src/controllers/music/music.html
+++ b/src/controllers/music/music.html
@@ -85,7 +85,7 @@
-
+
diff --git a/src/controllers/shows/tvrecommended.html b/src/controllers/shows/tvrecommended.html
index 0d7b7dced8..75e1546936 100644
--- a/src/controllers/shows/tvrecommended.html
+++ b/src/controllers/shows/tvrecommended.html
@@ -54,7 +54,7 @@
-
+
diff --git a/src/controllers/shows/tvrecommended.js b/src/controllers/shows/tvrecommended.js
index da47f9f318..9955df6b58 100644
--- a/src/controllers/shows/tvrecommended.js
+++ b/src/controllers/shows/tvrecommended.js
@@ -36,12 +36,18 @@ import 'emby-button';
case 'suggestions':
return 1;
- case 'favorites':
- return 1;
+ case 'upcoming':
+ return 2;
case 'genres':
return 3;
+ case 'networks':
+ return 4;
+
+ case 'episodes':
+ return 5;
+
default:
return 0;
}
From d3c5b83b290ab5ed3baef95f44ba7c182f5ca563 Mon Sep 17 00:00:00 2001
From: grafixeyehero
Date: Mon, 14 Sep 2020 01:23:20 +0300
Subject: [PATCH 060/365] clean up unused search tab condition
---
src/controllers/movies/movies.html | 2 --
src/controllers/movies/moviesrecommended.js | 5 -----
src/controllers/music/music.html | 2 --
src/controllers/music/musicrecommended.js | 5 -----
src/controllers/shows/tvrecommended.html | 2 --
src/controllers/shows/tvrecommended.js | 5 -----
6 files changed, 21 deletions(-)
diff --git a/src/controllers/movies/movies.html b/src/controllers/movies/movies.html
index 5c905d1225..ec2a975db1 100644
--- a/src/controllers/movies/movies.html
+++ b/src/controllers/movies/movies.html
@@ -88,6 +88,4 @@
-
-
diff --git a/src/controllers/movies/moviesrecommended.js b/src/controllers/movies/moviesrecommended.js
index 4036128b51..44b0fe25fe 100644
--- a/src/controllers/movies/moviesrecommended.js
+++ b/src/controllers/movies/moviesrecommended.js
@@ -320,11 +320,6 @@ import 'emby-button';
if (index === suggestionsTabIndex) {
controller = this;
- } else if (index === 6) {
- controller = new controllerFactory(view, tabContent, {
- collectionType: 'movies',
- parentId: params.topParentId
- });
} else if (index == 0 || index == 3) {
controller = new controllerFactory(view, params, tabContent, {
mode: index ? 'favorites' : 'movies'
diff --git a/src/controllers/music/music.html b/src/controllers/music/music.html
index 0ec339db95..43251226c9 100644
--- a/src/controllers/music/music.html
+++ b/src/controllers/music/music.html
@@ -105,6 +105,4 @@
-
-
diff --git a/src/controllers/music/musicrecommended.js b/src/controllers/music/musicrecommended.js
index 7b11a8eb21..6c569ddd41 100644
--- a/src/controllers/music/musicrecommended.js
+++ b/src/controllers/music/musicrecommended.js
@@ -308,11 +308,6 @@ import 'flexStyles';
if (index === 1) {
controller = this;
- } else if (index === 7) {
- controller = new controllerFactory(view, tabContent, {
- collectionType: 'music',
- parentId: params.topParentId
- });
} else {
controller = new controllerFactory(view, params, tabContent);
}
diff --git a/src/controllers/shows/tvrecommended.html b/src/controllers/shows/tvrecommended.html
index 75e1546936..dbfac37b91 100644
--- a/src/controllers/shows/tvrecommended.html
+++ b/src/controllers/shows/tvrecommended.html
@@ -67,6 +67,4 @@
-
-
diff --git a/src/controllers/shows/tvrecommended.js b/src/controllers/shows/tvrecommended.js
index 9955df6b58..db7bef2d50 100644
--- a/src/controllers/shows/tvrecommended.js
+++ b/src/controllers/shows/tvrecommended.js
@@ -285,11 +285,6 @@ import 'emby-button';
if (index === 1) {
controller = self;
- } else if (index === 6) {
- controller = new controllerFactory(view, tabContent, {
- collectionType: 'tvshows',
- parentId: params.topParentId
- });
} else {
controller = new controllerFactory(view, params, tabContent);
}
From db76b40affa67fcec41d4daec0c6a4c79dee62f1 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=9D=D0=B8=D0=BA=D0=BE=D0=BB=D0=B0=D0=B9=20=D0=98=D0=B2?=
=?UTF-8?q?=D0=B0=D0=BD=D0=BE=D0=B2?=
Date: Sun, 13 Sep 2020 19:55:51 +0000
Subject: [PATCH 061/365] Translated using Weblate (Bulgarian) Translation:
Jellyfin/Jellyfin Web Translate-URL:
https://translate.jellyfin.org/projects/jellyfin/jellyfin-web/bg/
---
src/strings/bg-bg.json | 29 ++++++++++++++++++++++++++++-
1 file changed, 28 insertions(+), 1 deletion(-)
diff --git a/src/strings/bg-bg.json b/src/strings/bg-bg.json
index c0a63032f2..f4d6dfc317 100644
--- a/src/strings/bg-bg.json
+++ b/src/strings/bg-bg.json
@@ -1352,5 +1352,32 @@
"MessagePluginInstallError": "Възникна грешка при инсталирането на добавката.",
"PlaybackRate": "Скорост на възпроизвеждане",
"NextTrack": "Прескочи към следващ",
- "LabelUnstable": "Нестабилна"
+ "LabelUnstable": "Нестабилна",
+ "LabelOpenclDevice": "Устройство OpenCL:",
+ "LabelColorPrimaries": "Цветни първични елементи:",
+ "LabelColorTransfer": "Цветен трансфер:",
+ "LabelColorSpace": "Цветово пространство:",
+ "LabelVideoRange": "Видео обхват:",
+ "MediaInfoColorPrimaries": "Цветни първични материали",
+ "MediaInfoColorTransfer": "Цветен трансфер",
+ "MediaInfoColorSpace": "Цветово пространство",
+ "MediaInfoVideoRange": "Видео обхват",
+ "Bwdif": "Филтър БВДИФ",
+ "VideoAudio": "Видео Аудио",
+ "Video": "Видео",
+ "ThumbCard": "Малък постер",
+ "Subtitle": "Субтитри",
+ "SpecialFeatures": "Специални функции",
+ "SelectServer": "Избери сървър",
+ "Restart": "Рестартирай",
+ "ResetPassword": "Нулира парола",
+ "Profile": "Профил",
+ "PosterCard": "Плакат карта",
+ "Poster": "Плакат",
+ "Photo": "Снимки",
+ "MusicVideos": "Музикални видеа",
+ "LabelKnownProxies": "Познати проксита:",
+ "Image": "Картинка",
+ "Other": "Други",
+ "Data": "Данни"
}
From 7d77cc9900d7adb434f38b4e718dbff0a97688b8 Mon Sep 17 00:00:00 2001
From: Franco Castillo
Date: Sun, 13 Sep 2020 23:51:02 +0000
Subject: [PATCH 062/365] Translated using Weblate (Spanish (Argentina))
Translation: Jellyfin/Jellyfin Web Translate-URL:
https://translate.jellyfin.org/projects/jellyfin/jellyfin-web/es_AR/
---
src/strings/es-ar.json | 19 ++++++++++++++++++-
1 file changed, 18 insertions(+), 1 deletion(-)
diff --git a/src/strings/es-ar.json b/src/strings/es-ar.json
index 521f4ef98f..5f303b1ce2 100644
--- a/src/strings/es-ar.json
+++ b/src/strings/es-ar.json
@@ -1373,5 +1373,22 @@
"Other": "Otro",
"Bwdif": "BWDIF",
"UseDoubleRateDeinterlacingHelp": "Esta configuración utiliza la velocidad de campo al desentrelazar, a menudo denominado desentrelazado bob, que duplica la velocidad de fotogramas del video para proporcionar un movimiento completo como lo que vería al ver un video entrelazado en un televisor.",
- "UseDoubleRateDeinterlacing": "Duplique la velocidad de fotogramas al desentrelazar"
+ "UseDoubleRateDeinterlacing": "Duplique la velocidad de fotogramas al desentrelazar",
+ "LabelTonemappingParam": "Parámetro de mapeo de tonos:",
+ "LabelTonemappingPeak": "Pico de mapeo de tonos:",
+ "LabelTonemappingThreshold": "Umbral de mapeo de tonos:",
+ "LabelTonemappingRange": "Rango de mapeo de tonos:",
+ "LabelTonemappingAlgorithm": "Seleccione el algoritmo de mapeo de tonos para usar:",
+ "EnableTonemapping": "Habilitar mapeo de tonos",
+ "LabelOpenclDeviceHelp": "Este es el dispositivo OpenCL que se utiliza para el mapeo de tonos. El lado izquierdo del punto es el número de plataforma y el lado derecho es el número de dispositivo en la plataforma. El valor predeterminado es 0.0. Se requiere el archivo de aplicación ffmpeg que contiene el método de aceleración por hardware OpenCL.",
+ "LabelOpenclDevice": "Dispositivo OpenCL:",
+ "LabelColorPrimaries": "Primarias de color:",
+ "LabelColorTransfer": "Transferencia de color:",
+ "LabelColorSpace": "Espacio de color:",
+ "LabelVideoRange": "Rango de video:",
+ "MediaInfoColorPrimaries": "Primarias de color",
+ "MediaInfoColorTransfer": "Transferencia de color",
+ "MediaInfoColorSpace": "Espacio de color",
+ "MediaInfoVideoRange": "Rango de video",
+ "LabelKnownProxies": "Proxies conocidos:"
}
From 270f585b265f40012c76bc6e95553576cc8b285b Mon Sep 17 00:00:00 2001
From: Daniyar Itegulov
Date: Mon, 8 Jun 2020 17:44:55 +1000
Subject: [PATCH 063/365] Make book plugin render EPUBs continuously for mobile
devices
---
src/plugins/bookPlayer/plugin.js | 20 +++++++++++++++++++-
1 file changed, 19 insertions(+), 1 deletion(-)
diff --git a/src/plugins/bookPlayer/plugin.js b/src/plugins/bookPlayer/plugin.js
index 0303275be2..8cde3f400f 100644
--- a/src/plugins/bookPlayer/plugin.js
+++ b/src/plugins/bookPlayer/plugin.js
@@ -1,3 +1,4 @@
+import browser from 'browser';
import loading from 'loading';
import keyboardnavigation from 'keyboardnavigation';
import dialogHelper from 'dialogHelper';
@@ -230,6 +231,23 @@ export class BookPlayer {
return elem;
}
+ render(elem, book) {
+ if (browser.mobile) {
+ return book.renderTo(elem, {
+ width: '100%',
+ height: '100%',
+ manager: 'continuous',
+ flow: 'scrolled-doc',
+ offset: 0
+ });
+ } else {
+ return book.renderTo(elem, {
+ width: '100%',
+ height: '100%'
+ });
+ }
+ }
+
setCurrentSrc(elem, options) {
const item = options.items[0];
this._currentItem = item;
@@ -248,7 +266,7 @@ export class BookPlayer {
import('epubjs').then(({default: epubjs}) => {
const downloadHref = apiClient.getItemDownloadUrl(item.Id);
const book = epubjs(downloadHref, {openAs: 'epub'});
- const rendition = book.renderTo(elem, {width: '100%', height: '97%'});
+ const rendition = this.render(elem, book);
this._currentSrc = downloadHref;
this._rendition = rendition;
From 14583cf18e824308f6e7741da95e3204129cf8d1 Mon Sep 17 00:00:00 2001
From: Daniyar Itegulov
Date: Mon, 14 Sep 2020 18:51:03 +1000
Subject: [PATCH 064/365] Add next/prev chapter buttons for mobile devices
Also removes touch events as they interfere with continuous scrolling
---
src/plugins/bookPlayer/plugin.js | 75 +++++++++++++++++---------------
src/plugins/bookPlayer/style.css | 46 ++++++++++++++++----
2 files changed, 77 insertions(+), 44 deletions(-)
diff --git a/src/plugins/bookPlayer/plugin.js b/src/plugins/bookPlayer/plugin.js
index 8cde3f400f..0c3d6850aa 100644
--- a/src/plugins/bookPlayer/plugin.js
+++ b/src/plugins/bookPlayer/plugin.js
@@ -19,6 +19,8 @@ export class BookPlayer {
this.onDialogClosed = this.onDialogClosed.bind(this);
this.openTableOfContents = this.openTableOfContents.bind(this);
+ this.prevChapter = this.prevChapter.bind(this);
+ this.nextChapter = this.nextChapter.bind(this);
this.onWindowKeyUp = this.onWindowKeyUp.bind(this);
}
@@ -123,26 +125,6 @@ export class BookPlayer {
}
}
- onTouchStart(e) {
- // TODO: depending on the event this can be the document or the rendition itself
- const rendition = this._rendition || this;
- const book = rendition.book;
-
- // check that the event is from the book or the document
- if (!book || this._loaded === false) return;
-
- // epubjs stores pages off the screen or something for preloading
- // get the modulus of the touch event to account for the increased width
- if (!e.touches || e.touches.length === 0) return;
-
- const touch = e.touches[0].clientX % dom.getWindowSize().innerWidth;
- if (touch < dom.getWindowSize().innerWidth / 2) {
- book.package.metadata.direction === 'rtl' ? rendition.next() : rendition.prev();
- } else {
- book.package.metadata.direction === 'rtl' ? rendition.prev() : rendition.next();
- }
- }
-
onDialogClosed() {
this.stop();
}
@@ -151,27 +133,33 @@ export class BookPlayer {
const elem = this._mediaElement;
elem.addEventListener('close', this.onDialogClosed, {once: true});
- elem.querySelector('.btnBookplayerExit').addEventListener('click', this.onDialogClosed, {once: true});
- elem.querySelector('.btnBookplayerToc').addEventListener('click', this.openTableOfContents);
+ elem.querySelector('#btnBookplayerExit').addEventListener('click', this.onDialogClosed, {once: true});
+ elem.querySelector('#btnBookplayerToc').addEventListener('click', this.openTableOfContents);
+ if (browser.mobile) {
+ elem.querySelector('#btnBookplayerPrev').addEventListener('click', this.prevChapter);
+ elem.querySelector('#btnBookplayerNext').addEventListener('click', this.nextChapter);
+ }
}
bindEvents() {
this.bindMediaElementEvents();
document.addEventListener('keyup', this.onWindowKeyUp);
- document.addEventListener('touchstart', this.onTouchStart);
// FIXME: I don't really get why document keyup event is not triggered when epub is in focus
this._rendition.on('keyup', this.onWindowKeyUp);
- this._rendition.on('touchstart', this.onTouchStart);
}
unbindMediaElementEvents() {
const elem = this._mediaElement;
elem.removeEventListener('close', this.onDialogClosed);
- elem.querySelector('.btnBookplayerExit').removeEventListener('click', this.onDialogClosed);
- elem.querySelector('.btnBookplayerToc').removeEventListener('click', this.openTableOfContents);
+ elem.querySelector('#btnBookplayerExit').removeEventListener('click', this.onDialogClosed);
+ elem.querySelector('#btnBookplayerToc').removeEventListener('click', this.openTableOfContents);
+ if (browser.mobile) {
+ elem.querySelector('#btnBookplayerPrev').removeEventListener('click', this.prevChapter);
+ elem.querySelector('#btnBookplayerNext').removeEventListener('click', this.nextChapter);
+ }
}
unbindEvents() {
@@ -180,11 +168,9 @@ export class BookPlayer {
}
document.removeEventListener('keyup', this.onWindowKeyUp);
- document.removeEventListener('touchstart', this.onTouchStart);
if (this._rendition) {
this._rendition.off('keyup', this.onWindowKeyUp);
- this._rendition.off('touchstart', this.onTouchStart);
}
}
@@ -194,6 +180,16 @@ export class BookPlayer {
}
}
+ prevChapter(e) {
+ this._rendition.prev();
+ e.preventDefault();
+ }
+
+ nextChapter(e) {
+ this._rendition.next();
+ e.preventDefault();
+ }
+
createMediaElement() {
let elem = this._mediaElement;
if (elem) {
@@ -214,13 +210,22 @@ export class BookPlayer {
elem.id = 'bookPlayer';
let html = '';
- html += '
- ${LabelCurrentStatus}
+ ${LabelCurrentStatus}
-
-
-
${ImportMissingEpisodesHelp}
-
-
${HeaderChapterImages}