From d791da07e39240696e57463466a681cafcb9ba49 Mon Sep 17 00:00:00 2001 From: ferferga Date: Thu, 19 Mar 2020 00:17:51 +0100 Subject: [PATCH 001/107] Translate alerts --- src/components/directorybrowser/directorybrowser.js | 7 +++---- src/strings/en-us.json | 4 +++- src/strings/es.json | 4 +++- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/src/components/directorybrowser/directorybrowser.js b/src/components/directorybrowser/directorybrowser.js index b71f7bbb05..db53f0a398 100644 --- a/src/components/directorybrowser/directorybrowser.js +++ b/src/components/directorybrowser/directorybrowser.js @@ -163,16 +163,15 @@ define(['loading', 'dialogHelper', 'dom', 'listViewStyle', 'emby-input', 'paper- } }).catch(function(response) { if (response) { - // TODO All alerts (across the project), should use Globalize.translate() if (response.status === 404) { - alertText("The path could not be found. Please ensure the path is valid and try again."); + alertText(Globalize.translate("PathNotFound")); return Promise.reject(); } if (response.status === 500) { if (validateWriteable) { - alertText("Jellyfin Server requires write access to this folder. Please ensure write access and try again."); + alertText(Globalize.translate("WriteAccessRequired")); } else { - alertText("The path could not be found. Please ensure the path is valid and try again.") + alertText(Globalize.translate("PathNotFound")) } return Promise.reject() } diff --git a/src/strings/en-us.json b/src/strings/en-us.json index 62e8fa3f8f..784fa7c7ad 100644 --- a/src/strings/en-us.json +++ b/src/strings/en-us.json @@ -1468,5 +1468,7 @@ "XmlTvPathHelp": "A path to a XMLTV file. Jellyfin will read this file and periodically check it for updates. You are responsible for creating and updating the file.", "XmlTvSportsCategoriesHelp": "Programs with these categories will be displayed as sports programs. Separate multiple with '|'.", "Yes": "Yes", - "Yesterday": "Yesterday" + "Yesterday": "Yesterday", + "PathNotFound": "The path could not be found. Please ensure the path is valid and try again.", + "WriteAccessRequired": "Jellyfin Server requires write access to this folder. Please ensure write access and try again." } diff --git a/src/strings/es.json b/src/strings/es.json index 3d56ff56d8..442459c9ea 100644 --- a/src/strings/es.json +++ b/src/strings/es.json @@ -1476,5 +1476,7 @@ "LabelDroppedFrames": "Frames perdidos:", "LabelCorruptedFrames": "Frames corruptos:", "AskAdminToCreateLibrary": "Solo un administrador puede crear librerías.", - "AllowFfmpegThrottling": "Acelerar transcodificación" + "AllowFfmpegThrottling": "Acelerar transcodificación", + "PathNotFound": "No se encontró la ruta especificada. Asegúrate de que existe e inténtalo de nuevo.", + "WriteAccessRequired": "Jellyfin requiere de permisos de escritura en esta carpeta. Asegúrate de que existe este permiso e inténtalo de nuevo." } From e383c3dee1c52d17b644079359a8e5ff70ce2f6c Mon Sep 17 00:00:00 2001 From: ferferga Date: Thu, 19 Mar 2020 00:40:17 +0100 Subject: [PATCH 002/107] Translate paging phrase --- src/components/imagedownloader/imagedownloader.js | 2 +- src/scripts/librarybrowser.js | 2 +- src/strings/en-us.json | 3 ++- src/strings/es.json | 3 ++- 4 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/components/imagedownloader/imagedownloader.js b/src/components/imagedownloader/imagedownloader.js index ce53b5cf0d..947a50135c 100644 --- a/src/components/imagedownloader/imagedownloader.js +++ b/src/components/imagedownloader/imagedownloader.js @@ -109,7 +109,7 @@ define(['loading', 'apphost', 'dialogHelper', 'connectionManager', 'imageLoader' html += ''; var startAtDisplay = totalRecordCount ? startIndex + 1 : 0; - html += startAtDisplay + '-' + recordsEnd + ' of ' + totalRecordCount; + html += globalize.translate("ListPaging").replace("{0}", startAtDisplay + '-' + recordsEnd).replace("{1}", totalRecordCount); html += ''; diff --git a/src/scripts/librarybrowser.js b/src/scripts/librarybrowser.js index bd8980aed2..a570558f47 100644 --- a/src/scripts/librarybrowser.js +++ b/src/scripts/librarybrowser.js @@ -83,7 +83,7 @@ define(["userSettings"], function (userSettings) { if (html += '
', showControls) { html += ''; - html += (totalRecordCount ? startIndex + 1 : 0) + "-" + recordsEnd + " of " + totalRecordCount; + html += Globalize.translate("ListPaging").replace("{0}", (totalRecordCount ? startIndex + 1 : 0) + "-" + recordsEnd).replace("{1}", totalRecordCount); html += ""; } diff --git a/src/strings/en-us.json b/src/strings/en-us.json index 784fa7c7ad..f3e7756f5e 100644 --- a/src/strings/en-us.json +++ b/src/strings/en-us.json @@ -1470,5 +1470,6 @@ "Yes": "Yes", "Yesterday": "Yesterday", "PathNotFound": "The path could not be found. Please ensure the path is valid and try again.", - "WriteAccessRequired": "Jellyfin Server requires write access to this folder. Please ensure write access and try again." + "WriteAccessRequired": "Jellyfin Server requires write access to this folder. Please ensure write access and try again.", + "ListPaging": "{0} of {1}" } diff --git a/src/strings/es.json b/src/strings/es.json index 442459c9ea..138d19f86c 100644 --- a/src/strings/es.json +++ b/src/strings/es.json @@ -1478,5 +1478,6 @@ "AskAdminToCreateLibrary": "Solo un administrador puede crear librerías.", "AllowFfmpegThrottling": "Acelerar transcodificación", "PathNotFound": "No se encontró la ruta especificada. Asegúrate de que existe e inténtalo de nuevo.", - "WriteAccessRequired": "Jellyfin requiere de permisos de escritura en esta carpeta. Asegúrate de que existe este permiso e inténtalo de nuevo." + "WriteAccessRequired": "Jellyfin requiere de permisos de escritura en esta carpeta. Asegúrate de que existe este permiso e inténtalo de nuevo.", + "ListPaging": "{0} de {1}" } From 79e664ca13dc631c300bcc52c2aa62e07af3eb70 Mon Sep 17 00:00:00 2001 From: MrTimscampi Date: Sat, 21 Mar 2020 23:45:23 +0100 Subject: [PATCH 003/107] Refactor slideshow.js --- src/components/slideshow/slideshow.js | 236 +++++--------------------- 1 file changed, 44 insertions(+), 192 deletions(-) diff --git a/src/components/slideshow/slideshow.js b/src/components/slideshow/slideshow.js index 4d426f2484..cb8f0442b2 100644 --- a/src/components/slideshow/slideshow.js +++ b/src/components/slideshow/slideshow.js @@ -1,8 +1,7 @@ -define(['dialogHelper', 'inputManager', 'connectionManager', 'layoutManager', 'focusManager', 'browser', 'apphost', 'loading', 'css!./style', 'material-icons', 'paper-icon-button-light'], function (dialogHelper, inputManager, connectionManager, layoutManager, focusManager, browser, appHost, loading) { +define(['dialogHelper', 'inputManager', 'connectionManager', 'layoutManager', 'focusManager', 'browser', 'apphost', 'css!./style', 'material-icons', 'paper-icon-button-light'], function (dialogHelper, inputManager, connectionManager, layoutManager, focusManager, browser, appHost) { 'use strict'; function getImageUrl(item, options, apiClient) { - options = options || {}; options.type = options.type || "Primary"; @@ -28,7 +27,6 @@ define(['dialogHelper', 'inputManager', 'connectionManager', 'layoutManager', 'f } function getBackdropImageUrl(item, options, apiClient) { - options = options || {}; options.type = options.type || "Backdrop"; @@ -46,19 +44,14 @@ define(['dialogHelper', 'inputManager', 'connectionManager', 'layoutManager', 'f return null; } - function getImgUrl(item, original) { - + function getImgUrl(item) { var apiClient = connectionManager.getApiClient(item.ServerId); var imageOptions = {}; - if (!original) { - imageOptions.maxWidth = screen.availWidth; - } if (item.BackdropImageTags && item.BackdropImageTags.length) { return getBackdropImageUrl(item, imageOptions, apiClient); } else { - - if (item.MediaType === 'Photo' && original) { + if (item.MediaType === 'Photo') { return apiClient.getItemDownloadUrl(item.Id); } imageOptions.type = "Primary"; @@ -67,14 +60,12 @@ define(['dialogHelper', 'inputManager', 'connectionManager', 'layoutManager', 'f } function getIcon(icon, cssClass, canFocus, autoFocus) { - var tabIndex = canFocus ? '' : ' tabindex="-1"'; autoFocus = autoFocus ? ' autofocus' : ''; return ''; } function setUserScalable(scalable) { - try { appHost.setUserScalable(scalable); } catch (err) { @@ -88,9 +79,8 @@ define(['dialogHelper', 'inputManager', 'connectionManager', 'layoutManager', 'f var swiperInstance; var dlg; var currentTimeout; - var currentIntervalMs; var currentOptions; - var currentIndex; + var _osdOpen = false; // small hack since this is not possible anyway if (browser.chromecast) { @@ -98,6 +88,7 @@ define(['dialogHelper', 'inputManager', 'connectionManager', 'layoutManager', 'f } function createElements(options) { + currentOptions = options; dlg = dialogHelper.createDialog({ exitAnimationDuration: options.interactive ? 400 : 800, @@ -113,10 +104,8 @@ define(['dialogHelper', 'inputManager', 'connectionManager', 'layoutManager', 'f var html = ''; if (options.interactive) { - var actionButtonsOnTop = layoutManager.mobile; - html += '
'; html += '
'; html += getIcon('keyboard_arrow_left', 'btnSlideshowPrevious slideshowButton hide-mouse-idle-tv', false); @@ -137,7 +126,7 @@ define(['dialogHelper', 'inputManager', 'connectionManager', 'layoutManager', 'f if (!actionButtonsOnTop) { html += '
'; - html += getIcon('pause', 'btnSlideshowPause slideshowButton', true, true); + html += getIcon('play_arrow', 'btnSlideshowPause slideshowButton', true, true); if (appHost.supports('filedownload')) { html += getIcon('file_download', 'btnDownload slideshowButton', true); } @@ -148,8 +137,6 @@ define(['dialogHelper', 'inputManager', 'connectionManager', 'layoutManager', 'f html += '
'; } - html += '
'; - } else { html += '

'; } @@ -158,11 +145,8 @@ define(['dialogHelper', 'inputManager', 'connectionManager', 'layoutManager', 'f if (options.interactive) { dlg.querySelector('.btnSlideshowExit').addEventListener('click', function (e) { - dialogHelper.close(dlg); }); - dlg.querySelector('.btnSlideshowNext').addEventListener('click', nextImage); - dlg.querySelector('.btnSlideshowPrevious').addEventListener('click', previousImage); var btnPause = dlg.querySelector('.btnSlideshowPause'); if (btnPause) { @@ -201,25 +185,23 @@ define(['dialogHelper', 'inputManager', 'connectionManager', 'layoutManager', 'f function onAutoplayStart() { var btnSlideshowPause = dlg.querySelector('.btnSlideshowPause i'); if (btnSlideshowPause) { - btnSlideshowPause.classList.remove("play_arrow"); - btnSlideshowPause.classList.add("pause"); + btnSlideshowPause.classList.replace("play_arrow", "pause"); } } function onAutoplayStop() { var btnSlideshowPause = dlg.querySelector('.btnSlideshowPause i'); if (btnSlideshowPause) { - btnSlideshowPause.classList.remove("pause"); - btnSlideshowPause.classList.add("play_arrow"); + btnSlideshowPause.classList.replace("pause", "play_arrow"); } } function loadSwiper(dlg) { - + var slides; if (currentOptions.slides) { - dlg.querySelector('.swiper-wrapper').innerHTML = currentOptions.slides.map(getSwiperSlideHtmlFromSlide).join(''); + slides = currentOptions.slides; } else { - dlg.querySelector('.swiper-wrapper').innerHTML = currentOptions.items.map(getSwiperSlideHtmlFromItem).join(''); + slides = currentOptions.items; } require(['swiper'], function (Swiper) { @@ -227,33 +209,43 @@ define(['dialogHelper', 'inputManager', 'connectionManager', 'layoutManager', 'f swiperInstance = new Swiper(dlg.querySelector('.slideshowSwiperContainer'), { // Optional parameters direction: 'horizontal', - loop: options.loop !== false, - autoplay: { - delay: options.interval || 8000 + loop: false, + autoplay: false, + keyboard: { + enabled: true }, - // Disable preloading of all images - preloadImages: false, - // Enable lazy loading - lazy: true, - loadPrevNext: true, - disableOnInteraction: false, + preloadImages: true, + slidesPerView: 1, + slidesPerColumn: 1, initialSlide: options.startIndex || 0, - speed: 240 + speed: 240, + navigation: { + nextEl: '.btnSlideshowNext', + prevEl: '.btnSlideshowPrevious' + }, + virtual: { + slides: slides, + cache: true, + renderSlide: getSwiperSlideHtml, + addSlidesBefore: 1, + addSlidesAfter: 1 + } }); swiperInstance.on('autoplayStart', onAutoplayStart); swiperInstance.on('autoplayStop', onAutoplayStop); - - if (layoutManager.mobile) { - pause(); - } else { - play(); - } }); } - function getSwiperSlideHtmlFromItem(item) { + function getSwiperSlideHtml(item, index) { + if (currentOptions.slides) { + return getSwiperSlideHtmlFromSlide(item); + } else { + return getSwiperSlideHtmlFromItem(item); + } + } + function getSwiperSlideHtmlFromItem(item) { return getSwiperSlideHtmlFromSlide({ imageUrl: getImgUrl(item), originalImage: getImgUrl(item, true), @@ -265,10 +257,11 @@ define(['dialogHelper', 'inputManager', 'connectionManager', 'layoutManager', 'f } function getSwiperSlideHtmlFromSlide(item) { - var html = ''; - html += '
'; - html += ''; + html += '
'; + html += '
'; + html += ''; + html += '
'; if (item.title || item.subtitle) { html += '
'; html += '
'; @@ -290,42 +283,14 @@ define(['dialogHelper', 'inputManager', 'connectionManager', 'layoutManager', 'f return html; } - function previousImage() { - if (swiperInstance) { - swiperInstance.slidePrev(); - } else { - stopInterval(); - showNextImage(currentIndex - 1); - } - } - - function nextImage() { - if (swiperInstance) { - - if (options.loop === false) { - - if (swiperInstance.activeIndex >= swiperInstance.slides.length - 1) { - dialogHelper.close(dlg); - return; - } - } - - swiperInstance.slideNext(); - } else { - stopInterval(); - showNextImage(currentIndex + 1); - } - } - function getCurrentImageInfo() { - if (swiperInstance) { var slide = document.querySelector('.swiper-slide-active'); if (slide) { return { url: slide.getAttribute('data-original'), - shareUrl: slide.getAttribute('data-imageurl'), + shareUrl: slide.getAttribute('data-original'), itemId: slide.getAttribute('data-itemid'), serverId: slide.getAttribute('data-serverid') }; @@ -337,7 +302,6 @@ define(['dialogHelper', 'inputManager', 'connectionManager', 'layoutManager', 'f } function download() { - var imageInfo = getCurrentImageInfo(); require(['fileDownloader'], function (fileDownloader) { @@ -346,7 +310,6 @@ define(['dialogHelper', 'inputManager', 'connectionManager', 'layoutManager', 'f } function share() { - var imageInfo = getCurrentImageInfo(); navigator.share({ @@ -376,7 +339,6 @@ define(['dialogHelper', 'inputManager', 'connectionManager', 'layoutManager', 'f } function onDialogClosed() { - var swiper = swiperInstance; if (swiper) { swiper.destroy(true, true); @@ -387,31 +349,11 @@ define(['dialogHelper', 'inputManager', 'connectionManager', 'layoutManager', 'f document.removeEventListener((window.PointerEvent ? 'pointermove' : 'mousemove'), onPointerMove); } - function startInterval(options) { - - currentOptions = options; - - stopInterval(); - createElements(options); - - if (!options.interactive) { - currentIntervalMs = options.interval || 11000; - showNextImage(options.startIndex || 0, true); - } - } - - var _osdOpen = false; - - function isOsdOpen() { - return _osdOpen; - } - function getOsdBottom() { return dlg.querySelector('.slideshowBottomBar'); } function showOsd() { - var bottom = getOsdBottom(); if (bottom) { slideUpToShow(bottom); @@ -420,7 +362,6 @@ define(['dialogHelper', 'inputManager', 'connectionManager', 'layoutManager', 'f } function hideOsd() { - var bottom = getOsdBottom(); if (bottom) { slideDownToHide(bottom); @@ -442,7 +383,6 @@ define(['dialogHelper', 'inputManager', 'connectionManager', 'layoutManager', 'f } function slideUpToShow(elem) { - if (!elem.classList.contains('hide')) { return; } @@ -471,7 +411,6 @@ define(['dialogHelper', 'inputManager', 'connectionManager', 'layoutManager', 'f } function slideDownToHide(elem) { - if (elem.classList.contains('hide')) { return; } @@ -529,23 +468,7 @@ define(['dialogHelper', 'inputManager', 'connectionManager', 'layoutManager', 'f } function onInputCommand(e) { - switch (e.detail.command) { - - case 'left': - if (!isOsdOpen()) { - e.preventDefault(); - e.stopPropagation(); - previousImage(); - } - break; - case 'right': - if (!isOsdOpen()) { - e.preventDefault(); - e.stopPropagation(); - nextImage(); - } - break; case 'up': case 'down': case 'select': @@ -561,76 +484,6 @@ define(['dialogHelper', 'inputManager', 'connectionManager', 'layoutManager', 'f } } - function showNextImage(index, skipPreload) { - - index = Math.max(0, index); - if (index >= currentOptions.items.length) { - index = 0; - } - currentIndex = index; - - var options = currentOptions; - var items = options.items; - var item = items[index]; - var imgUrl = getImgUrl(item); - - var onSrcLoaded = function () { - var cardImageContainer = dlg.querySelector('.slideshowImage'); - - var newCardImageContainer = document.createElement('div'); - newCardImageContainer.className = cardImageContainer.className; - - if (options.cover) { - newCardImageContainer.classList.add('slideshowImage-cover'); - } - - newCardImageContainer.style.backgroundImage = "url('" + imgUrl + "')"; - newCardImageContainer.classList.add('hide'); - cardImageContainer.parentNode.appendChild(newCardImageContainer); - - if (options.showTitle) { - dlg.querySelector('.slideshowImageText').innerHTML = item.Name; - } else { - dlg.querySelector('.slideshowImageText').innerHTML = ''; - } - - newCardImageContainer.classList.remove('hide'); - var onAnimationFinished = function () { - - var parentNode = cardImageContainer.parentNode; - if (parentNode) { - parentNode.removeChild(cardImageContainer); - } - }; - - if (newCardImageContainer.animate) { - - var keyframes = [ - { opacity: '0', offset: 0 }, - { opacity: '1', offset: 1 } - ]; - var timing = { duration: 1200, iterations: 1 }; - newCardImageContainer.animate(keyframes, timing).onfinish = onAnimationFinished; - } else { - onAnimationFinished(); - } - - stopInterval(); - currentTimeout = setTimeout(function () { - showNextImage(index + 1, true); - - }, currentIntervalMs); - }; - - if (!skipPreload) { - var img = new Image(); - img.onload = onSrcLoaded; - img.src = imgUrl; - } else { - onSrcLoaded(); - } - } - function stopInterval() { if (currentTimeout) { clearTimeout(currentTimeout); @@ -639,11 +492,10 @@ define(['dialogHelper', 'inputManager', 'connectionManager', 'layoutManager', 'f } self.show = function () { - startInterval(options); + createElements(options); }; self.hide = function () { - var dialog = dlg; if (dialog) { From c2f248f838f3978ce38083a6dfa0ee3fbf138ace Mon Sep 17 00:00:00 2001 From: Peter Maar Date: Sun, 22 Mar 2020 00:18:14 -0400 Subject: [PATCH 004/107] Add controls for DeinterlaceMethod Add controls and US-English text for DeinterlaceMethod in encodingsettings. Uses the values referenced here https://github.com/jellyfin/jellyfin/pull/2639 --- src/encodingsettings.html | 8 ++++++++ src/strings/en-us.json | 2 ++ 2 files changed, 10 insertions(+) diff --git a/src/encodingsettings.html b/src/encodingsettings.html index bcdd86544e..6fbcc133a8 100644 --- a/src/encodingsettings.html +++ b/src/encodingsettings.html @@ -136,6 +136,14 @@
${H264CrfHelp}
+
+ +
${DeinterlaceMethodHelp}
+
+