From af8d421a8c33962da3640a7f4a74726048904b95 Mon Sep 17 00:00:00 2001 From: grafixeyehero Date: Tue, 8 Oct 2019 00:56:51 +0300 Subject: [PATCH 001/162] autobackdrops.js --- src/scripts/autobackdrops.js | 77 +++++++++++++++++++++++------------- 1 file changed, 50 insertions(+), 27 deletions(-) diff --git a/src/scripts/autobackdrops.js b/src/scripts/autobackdrops.js index 8cce154a19..73042f83ce 100644 --- a/src/scripts/autobackdrops.js +++ b/src/scripts/autobackdrops.js @@ -1,53 +1,76 @@ -define(["backdrop", "userSettings", "libraryMenu"], function(backdrop, userSettings, libraryMenu) { +define(["backdrop", "userSettings", "libraryMenu"], function (backdrop, userSettings, libraryMenu) { "use strict"; function enabled() { - return userSettings.enableBackdrops() + return userSettings.enableBackdrops(); } function getBackdropItemIds(apiClient, userId, types, parentId) { - var key = "backdrops2_" + userId + (types || "") + (parentId || ""), - data = cache[key]; - if (data) return console.log("Found backdrop id list in cache. Key: " + key), data = JSON.parse(data), Promise.resolve(data); + var key = "backdrops2_" + userId + (types || "") + (parentId || ""); + var data = cache[key]; + + if (data) { + console.log("Found backdrop id list in cache. Key: " + key); + data = JSON.parse(data); + return Promise.resolve(data); + } + var options = { SortBy: "IsFavoriteOrLiked,Random", Limit: 20, - Recursive: !0, + Recursive: true, IncludeItemTypes: types, ImageTypes: "Backdrop", ParentId: parentId, - EnableTotalRecordCount: !1 + EnableTotalRecordCount: false }; - return apiClient.getItems(apiClient.getCurrentUserId(), options).then(function(result) { - var images = result.Items.map(function(i) { + return apiClient.getItems(apiClient.getCurrentUserId(), options).then(function (result) { + var images = result.Items.map(function (i) { return { Id: i.Id, tag: i.BackdropImageTags[0], ServerId: i.ServerId - } + }; }); - return cache[key] = JSON.stringify(images), images - }) + cache[key] = JSON.stringify(images); + return images; + }); } function showBackdrop(type, parentId) { var apiClient = window.ApiClient; - apiClient && getBackdropItemIds(apiClient, apiClient.getCurrentUserId(), type, parentId).then(function(images) { - images.length ? backdrop.setBackdrops(images.map(function(i) { - return i.BackdropImageTags = [i.tag], i - })) : backdrop.clear() - }) + + if (apiClient) { + getBackdropItemIds(apiClient, apiClient.getCurrentUserId(), type, parentId).then(function (images) { + if (images.length) { + backdrop.setBackdrops(images.map(function (i) { + i.BackdropImageTags = [i.tag]; + return i; + })); + } else { + backdrop.clear(); + } + }); + } } + var cache = {}; - pageClassOn("pageshow", "page", function() { + pageClassOn("pageshow", "page", function () { var page = this; - if (!page.classList.contains("selfBackdropPage")) - if (page.classList.contains("backdropPage")) + + if (!page.classList.contains("selfBackdropPage")) { + if (page.classList.contains("backdropPage")) { if (enabled()) { - var type = page.getAttribute("data-backdroptype"), - parentId = page.classList.contains("globalBackdropPage") ? "" : libraryMenu.getTopParentId(); - showBackdrop(type, parentId) - } else page.classList.remove("backdropPage"), backdrop.clear(); - else backdrop.clear() - }) -}); \ No newline at end of file + var type = page.getAttribute("data-backdroptype"); + var parentId = page.classList.contains("globalBackdropPage") ? "" : libraryMenu.getTopParentId(); + showBackdrop(type, parentId); + } else { + page.classList.remove("backdropPage"); + backdrop.clear(); + } + } else { + backdrop.clear(); + } + } + }); +}); From 40e4f6a27a7d05218681cb4eb980115b9ece27e2 Mon Sep 17 00:00:00 2001 From: grafixeyehero Date: Tue, 8 Oct 2019 00:57:40 +0300 Subject: [PATCH 002/162] itembynamedetailpage.js --- src/scripts/itembynamedetailpage.js | 309 ++++++++++++++++++++-------- 1 file changed, 221 insertions(+), 88 deletions(-) diff --git a/src/scripts/itembynamedetailpage.js b/src/scripts/itembynamedetailpage.js index 720c8a1e4e..1de421e6a3 100644 --- a/src/scripts/itembynamedetailpage.js +++ b/src/scripts/itembynamedetailpage.js @@ -1,40 +1,90 @@ -define(["connectionManager", "listView", "cardBuilder", "imageLoader", "libraryBrowser", "emby-itemscontainer", "emby-button"], function(connectionManager, listView, cardBuilder, imageLoader, libraryBrowser) { +define(["connectionManager", "listView", "cardBuilder", "imageLoader", "libraryBrowser", "emby-itemscontainer", "emby-button"], function (connectionManager, listView, cardBuilder, imageLoader, libraryBrowser) { "use strict"; function renderItems(page, item) { var sections = []; - item.ArtistCount && sections.push({ - name: Globalize.translate("TabArtists"), - type: "MusicArtist" - }), item.ProgramCount && "Person" == item.Type && sections.push({ - name: Globalize.translate("HeaderUpcomingOnTV"), - type: "Program" - }), item.MovieCount && sections.push({ - name: Globalize.translate("TabMovies"), - type: "Movie" - }), item.SeriesCount && sections.push({ - name: Globalize.translate("TabShows"), - type: "Series" - }), item.EpisodeCount && sections.push({ - name: Globalize.translate("TabEpisodes"), - type: "Episode" - }), item.TrailerCount && sections.push({ - name: Globalize.translate("TabTrailers"), - type: "Trailer" - }), item.AlbumCount && sections.push({ - name: Globalize.translate("TabAlbums"), - type: "MusicAlbum" - }), item.MusicVideoCount && sections.push({ - name: Globalize.translate("TabMusicVideos"), - type: "MusicVideo" - }); + + if (item.ArtistCount) { + sections.push({ + name: Globalize.translate("TabArtists"), + type: "MusicArtist" + }); + } + + if (item.ProgramCount && "Person" == item.Type) { + sections.push({ + name: Globalize.translate("HeaderUpcomingOnTV"), + type: "Program" + }); + } + + if (item.MovieCount) { + sections.push({ + name: Globalize.translate("TabMovies"), + type: "Movie" + }); + } + + if (item.SeriesCount) { + sections.push({ + name: Globalize.translate("TabShows"), + type: "Series" + }); + } + + if (item.EpisodeCount) { + sections.push({ + name: Globalize.translate("TabEpisodes"), + type: "Episode" + }); + } + + if (item.TrailerCount) { + sections.push({ + name: Globalize.translate("TabTrailers"), + type: "Trailer" + }); + } + + if (item.AlbumCount) { + sections.push({ + name: Globalize.translate("TabAlbums"), + type: "MusicAlbum" + }); + } + + if (item.MusicVideoCount) { + sections.push({ + name: Globalize.translate("TabMusicVideos"), + type: "MusicVideo" + }); + } + var elem = page.querySelector("#childrenContent"); - elem.innerHTML = sections.map(function(section) { - var html = "", - sectionClass = "verticalSection"; - return "Audio" === section.type && (sectionClass += " verticalSection-extrabottompadding"), html += '
', html += '
', html += '

', html += section.name, html += "

", html += '", html += "
", html += '
', html += "
", html += "
" + elem.innerHTML = sections.map(function (section) { + var html = ""; + var sectionClass = "verticalSection"; + + if ("Audio" === section.type) { + sectionClass += " verticalSection-extrabottompadding"; + } + + html += '
'; + html += '
'; + html += '

'; + html += section.name; + html += "

"; + html += '"; + html += "
"; + html += '
'; + html += "
"; + return html += "
"; }).join(""); - for (var sectionElems = elem.querySelectorAll(".verticalSection"), i = 0, length = sectionElems.length; i < length; i++) renderSection(page, item, sectionElems[i], sectionElems[i].getAttribute("data-type")) + var sectionElems = elem.querySelectorAll(".verticalSection"); + + for (var i = 0, length = sectionElems.length; i < length; i++) { + renderSection(page, item, sectionElems[i], sectionElems[i].getAttribute("data-type")); + } } function renderSection(page, item, element, type) { @@ -50,16 +100,17 @@ define(["connectionManager", "listView", "cardBuilder", "imageLoader", "libraryB SortBy: "StartDate" }, { shape: "backdrop", - showTitle: !0, - centerText: !0, - overlayMoreButton: !0, - preferThumb: !0, - overlayText: !1, - showAirTime: !0, - showAirDateTime: !0, - showChannelName: !0 + showTitle: true, + centerText: true, + overlayMoreButton: true, + preferThumb: true, + overlayText: false, + showAirTime: true, + showAirDateTime: true, + showChannelName: true }); break; + case "Movie": loadItems(element, item, type, { MediaTypes: "", @@ -71,13 +122,14 @@ define(["connectionManager", "listView", "cardBuilder", "imageLoader", "libraryB SortBy: "SortName" }, { shape: "portrait", - showTitle: !0, - centerText: !0, - overlayMoreButton: !0, - overlayText: !1, - showYear: !0 + showTitle: true, + centerText: true, + overlayMoreButton: true, + overlayText: false, + showYear: true }); break; + case "MusicVideo": loadItems(element, item, type, { MediaTypes: "", @@ -89,11 +141,12 @@ define(["connectionManager", "listView", "cardBuilder", "imageLoader", "libraryB SortBy: "SortName" }, { shape: "portrait", - showTitle: !0, - centerText: !0, - overlayPlayButton: !0 + showTitle: true, + centerText: true, + overlayPlayButton: true }); break; + case "Trailer": loadItems(element, item, type, { MediaTypes: "", @@ -105,11 +158,12 @@ define(["connectionManager", "listView", "cardBuilder", "imageLoader", "libraryB SortBy: "SortName" }, { shape: "portrait", - showTitle: !0, - centerText: !0, - overlayPlayButton: !0 + showTitle: true, + centerText: true, + overlayPlayButton: true }); break; + case "Series": loadItems(element, item, type, { MediaTypes: "", @@ -121,11 +175,12 @@ define(["connectionManager", "listView", "cardBuilder", "imageLoader", "libraryB SortBy: "SortName" }, { shape: "portrait", - showTitle: !0, - centerText: !0, - overlayMoreButton: !0 + showTitle: true, + centerText: true, + overlayMoreButton: true }); break; + case "MusicAlbum": loadItems(element, item, type, { MediaTypes: "", @@ -137,14 +192,15 @@ define(["connectionManager", "listView", "cardBuilder", "imageLoader", "libraryB SortBy: "ProductionYear,Sortname" }, { shape: "square", - playFromHere: !0, - showTitle: !0, - showYear: !0, - coverImage: !0, - centerText: !0, - overlayPlayButton: !0 + playFromHere: true, + showTitle: true, + showYear: true, + coverImage: true, + centerText: true, + overlayPlayButton: true }); break; + case "MusicArtist": loadItems(element, item, type, { MediaTypes: "", @@ -156,14 +212,15 @@ define(["connectionManager", "listView", "cardBuilder", "imageLoader", "libraryB SortBy: "SortName" }, { shape: "square", - playFromHere: !0, - showTitle: !0, - showParentTitle: !0, - coverImage: !0, - centerText: !0, - overlayPlayButton: !0 + playFromHere: true, + showTitle: true, + showParentTitle: true, + coverImage: true, + centerText: true, + overlayPlayButton: true }); break; + case "Episode": loadItems(element, item, type, { MediaTypes: "", @@ -175,12 +232,13 @@ define(["connectionManager", "listView", "cardBuilder", "imageLoader", "libraryB SortBy: "SortName" }, { shape: "backdrop", - showTitle: !0, - showParentTitle: !0, - centerText: !0, - overlayPlayButton: !0 + showTitle: true, + showParentTitle: true, + centerText: true, + overlayPlayButton: true }); break; + case "Audio": loadItems(element, item, type, { MediaTypes: "", @@ -190,57 +248,132 @@ define(["connectionManager", "listView", "cardBuilder", "imageLoader", "libraryB AlbumArtistIds: "", SortBy: "AlbumArtist,Album,SortName" }, { - playFromHere: !0, + playFromHere: true, action: "playallfromhere", - smallIcon: !0, - artist: !0 - }) + smallIcon: true, + artist: true + }); } } function loadItems(element, item, type, query, listOptions) { - query = getQuery(query, item), getItemsFunction(query, item)(query.StartIndex, query.Limit, query.Fields).then(function(result) { + query = getQuery(query, item); + getItemsFunction(query, item)(query.StartIndex, query.Limit, query.Fields).then(function (result) { var html = ""; + if (query.Limit && result.TotalRecordCount > query.Limit) { var link = element.querySelector("a"); - link.classList.remove("hide"), link.setAttribute("href", getMoreItemsHref(item, type)) - } else element.querySelector("a").classList.add("hide"); + link.classList.remove("hide"); + link.setAttribute("href", getMoreItemsHref(item, type)); + } else { + element.querySelector("a").classList.add("hide"); + } + listOptions.items = result.Items; var itemsContainer = element.querySelector(".itemsContainer"); - "Audio" == type ? (html = listView.getListViewHtml(listOptions), itemsContainer.classList.remove("vertical-wrap"), itemsContainer.classList.add("vertical-list")) : (html = cardBuilder.getCardsHtml(listOptions), itemsContainer.classList.add("vertical-wrap"), itemsContainer.classList.remove("vertical-list")), itemsContainer.innerHTML = html, imageLoader.lazyChildren(itemsContainer) - }) + + if ("Audio" == type) { + html = listView.getListViewHtml(listOptions); + itemsContainer.classList.remove("vertical-wrap"); + itemsContainer.classList.add("vertical-list"); + } else { + html = cardBuilder.getCardsHtml(listOptions); + itemsContainer.classList.add("vertical-wrap"); + itemsContainer.classList.remove("vertical-list"); + } + + itemsContainer.innerHTML = html; + imageLoader.lazyChildren(itemsContainer); + }); } function getMoreItemsHref(item, type) { - return "Genre" == item.Type ? "list.html?type=" + type + "&genreId=" + item.Id + "&serverId=" + item.ServerId : "MusicGenre" == item.Type ? "list.html?type=" + type + "&musicGenreId=" + item.Id + "&serverId=" + item.ServerId : "Studio" == item.Type ? "list.html?type=" + type + "&studioId=" + item.Id + "&serverId=" + item.ServerId : "MusicArtist" == item.Type ? "list.html?type=" + type + "&artistId=" + item.Id + "&serverId=" + item.ServerId : "Person" == item.Type ? "list.html?type=" + type + "&personId=" + item.Id + "&serverId=" + item.ServerId : "list.html?type=" + type + "&parentId=" + item.Id + "&serverId=" + item.ServerId + if ("Genre" == item.Type) { + return "list.html?type=" + type + "&genreId=" + item.Id + "&serverId=" + item.ServerId; + } + + if ("MusicGenre" == item.Type) { + return "list.html?type=" + type + "&musicGenreId=" + item.Id + "&serverId=" + item.ServerId; + } + + if ("Studio" == item.Type) { + return "list.html?type=" + type + "&studioId=" + item.Id + "&serverId=" + item.ServerId; + } + + if ("MusicArtist" == item.Type) { + return "list.html?type=" + type + "&artistId=" + item.Id + "&serverId=" + item.ServerId; + } + + if ("Person" == item.Type) { + return "list.html?type=" + type + "&personId=" + item.Id + "&serverId=" + item.ServerId; + } + + return "list.html?type=" + type + "&parentId=" + item.Id + "&serverId=" + item.ServerId; } function addCurrentItemToQuery(query, item) { - "Person" == item.Type ? query.PersonIds = item.Id : "Genre" == item.Type ? query.GenreIds = item.Id : "MusicGenre" == item.Type ? query.GenreIds = item.Id : "Studio" == item.Type ? query.StudioIds = item.Id : "MusicArtist" == item.Type && (connectionManager.getApiClient(item.ServerId).isMinServerVersion("3.4.1.18") ? query.AlbumArtistIds = item.Id : query.ArtistIds = item.Id) + if ("Person" == item.Type) { + query.PersonIds = item.Id; + } else { + if ("Genre" == item.Type) { + query.GenreIds = item.Id; + } else { + if ("MusicGenre" == item.Type) { + query.GenreIds = item.Id; + } else { + if ("Studio" == item.Type) { + query.StudioIds = item.Id; + } else { + if ("MusicArtist" == item.Type) { + if (connectionManager.getApiClient(item.ServerId).isMinServerVersion("3.4.1.18")) { + query.AlbumArtistIds = item.Id; + } else { + query.ArtistIds = item.Id; + } + } + } + } + } + } } function getQuery(options, item) { var query = { SortOrder: "Ascending", IncludeItemTypes: "", - Recursive: !0, + Recursive: true, Fields: "AudioInfo,SeriesInfo,ParentId,PrimaryImageAspectRatio,BasicSyncInfo", Limit: 100, StartIndex: 0, - CollapseBoxSetItems: !1 + CollapseBoxSetItems: false }; - return query = Object.assign(query, options || {}), addCurrentItemToQuery(query, item), query + query = Object.assign(query, options || {}); + addCurrentItemToQuery(query, item); + return query; } function getItemsFunction(options, item) { var query = getQuery(options, item); - return function(index, limit, fields) { - query.StartIndex = index, query.Limit = limit, fields && (query.Fields += "," + fields); + return function (index, limit, fields) { + query.StartIndex = index; + query.Limit = limit; + + if (fields) { + query.Fields += "," + fields; + } + var apiClient = connectionManager.getApiClient(item.ServerId); - return "MusicArtist" === query.IncludeItemTypes ? (query.IncludeItemTypes = null, apiClient.getAlbumArtists(apiClient.getCurrentUserId(), query)) : apiClient.getItems(apiClient.getCurrentUserId(), query) - } + + if ("MusicArtist" === query.IncludeItemTypes) { + query.IncludeItemTypes = null; + return apiClient.getAlbumArtists(apiClient.getCurrentUserId(), query); + } + + return apiClient.getItems(apiClient.getCurrentUserId(), query); + }; } + window.ItemsByName = { renderItems: renderItems - } + }; }); From f7c8d7b044848c6d09740406c2d66d94711915e3 Mon Sep 17 00:00:00 2001 From: grafixeyehero Date: Tue, 8 Oct 2019 00:58:10 +0300 Subject: [PATCH 003/162] librarybrowser.js --- src/scripts/librarybrowser.js | 198 +++++++++++++++++++++++++--------- 1 file changed, 148 insertions(+), 50 deletions(-) diff --git a/src/scripts/librarybrowser.js b/src/scripts/librarybrowser.js index 5278842d7f..f2edc9030c 100644 --- a/src/scripts/librarybrowser.js +++ b/src/scripts/librarybrowser.js @@ -1,101 +1,199 @@ -define(["userSettings"], function(userSettings) { +define(["userSettings"], function (userSettings) { "use strict"; + var libraryBrowser = { - getSavedQueryKey: function(modifier) { - return window.location.href.split("#")[0] + (modifier || "") + getSavedQueryKey: function (modifier) { + return window.location.href.split("#")[0] + (modifier || ""); }, - loadSavedQueryValues: function(key, query) { + loadSavedQueryValues: function (key, query) { var values = userSettings.get(key); - return values ? (values = JSON.parse(values), Object.assign(query, values)) : query + + if (values) { + values = JSON.parse(values); + return Object.assign(query, values); + } + + return query; }, - saveQueryValues: function(key, query) { + saveQueryValues: function (key, query) { var values = {}; - query.SortBy && (values.SortBy = query.SortBy), query.SortOrder && (values.SortOrder = query.SortOrder), userSettings.set(key, JSON.stringify(values)) + + if (query.SortBy) { + values.SortBy = query.SortBy; + } + + if (query.SortOrder) { + values.SortOrder = query.SortOrder; + } + + userSettings.set(key, JSON.stringify(values)); }, - saveViewSetting: function(key, value) { - userSettings.set(key + "-_view", value) + saveViewSetting: function (key, value) { + userSettings.set(key + "-_view", value); }, - getSavedView: function(key) { - return userSettings.get(key + "-_view") + getSavedView: function (key) { + return userSettings.get(key + "-_view"); }, - showLayoutMenu: function(button, currentLayout, views) { - var dispatchEvent = !0; - views || (dispatchEvent = !1, views = button.getAttribute("data-layouts"), views = views ? views.split(",") : ["List", "Poster", "PosterCard", "Thumb", "ThumbCard"]); - var menuItems = views.map(function(v) { + showLayoutMenu: function (button, currentLayout, views) { + var dispatchEvent = true; + + if (!views) { + dispatchEvent = false; + views = button.getAttribute("data-layouts"); + views = views ? views.split(",") : ["List", "Poster", "PosterCard", "Thumb", "ThumbCard"]; + } + + var menuItems = views.map(function (v) { return { name: Globalize.translate("Option" + v), id: v, selected: currentLayout == v - } + }; }); - require(["actionsheet"], function(actionsheet) { + + require(["actionsheet"], function (actionsheet) { actionsheet.show({ items: menuItems, positionTo: button, - callback: function(id) { + callback: function (id) { button.dispatchEvent(new CustomEvent("layoutchange", { detail: { viewStyle: id }, - bubbles: !0, - cancelable: !1 - })), dispatchEvent || window.$ && $(button).trigger("layoutchange", [id]) + bubbles: true, + cancelable: false + })); + + if (!dispatchEvent) { + if (window.$) { + $(button).trigger("layoutchange", [id]); + } + } } - }) - }) + }); + }); }, - getQueryPagingHtml: function(options) { - var startIndex = options.startIndex, - limit = options.limit, - totalRecordCount = options.totalRecordCount, - html = "", - recordsEnd = Math.min(startIndex + limit, totalRecordCount), - showControls = limit < totalRecordCount; + getQueryPagingHtml: function (options) { + var startIndex = options.startIndex; + var limit = options.limit; + var totalRecordCount = options.totalRecordCount; + var html = ""; + var recordsEnd = Math.min(startIndex + limit, totalRecordCount); + var showControls = limit < totalRecordCount; + if (html += '
', showControls) { html += ''; - html += (totalRecordCount ? startIndex + 1 : 0) + "-" + recordsEnd + " of " + totalRecordCount, html += "" + html += (totalRecordCount ? startIndex + 1 : 0) + "-" + recordsEnd + " of " + totalRecordCount; + html += ""; } - return (showControls || options.viewButton || options.filterButton || options.sortButton || options.addLayoutButton) && (html += '
', showControls && (html += '', html += ''), options.addLayoutButton && (html += ''), options.sortButton && (html += ''), options.filterButton && (html += ''), html += "
"), html += "
" + + if (showControls || options.viewButton || options.filterButton || options.sortButton || options.addLayoutButton) { + html += '
'; + + if (showControls) { + html += ''; + html += ''; + } + + if (options.addLayoutButton) { + html += ''; + } + + if (options.sortButton) { + html += ''; + } + + if (options.filterButton) { + html += ''; + } + + html += "
"; + } + + return html += ""; }, - showSortMenu: function(options) { - require(["dialogHelper", "emby-radio"], function(dialogHelper) { + showSortMenu: function (options) { + require(["dialogHelper", "emby-radio"], function (dialogHelper) { function onSortByChange() { var newValue = this.value; + if (this.checked) { var changed = options.query.SortBy != newValue; - options.query.SortBy = newValue.replace("_", ","), options.query.StartIndex = 0, options.callback && changed && options.callback() + options.query.SortBy = newValue.replace("_", ","); + options.query.StartIndex = 0; + + if (options.callback && changed) { + options.callback(); + } } } function onSortOrderChange() { var newValue = this.value; + if (this.checked) { var changed = options.query.SortOrder != newValue; - options.query.SortOrder = newValue, options.query.StartIndex = 0, options.callback && changed && options.callback() + options.query.SortOrder = newValue; + options.query.StartIndex = 0; + + if (options.callback && changed) { + options.callback(); + } } } + var dlg = dialogHelper.createDialog({ - removeOnClose: !0, - modal: !1, + removeOnClose: true, + modal: false, entryAnimationDuration: 160, exitAnimationDuration: 200 }); - dlg.classList.add("ui-body-a"), dlg.classList.add("background-theme-a"), dlg.classList.add("formDialog"); + dlg.classList.add("ui-body-a"); + dlg.classList.add("background-theme-a"); + dlg.classList.add("formDialog"); var html = ""; - html += '
', html += '

', html += Globalize.translate("HeaderSortBy"), html += "

"; - var i, length, isChecked; + html += '
'; + html += '

'; + html += Globalize.translate("HeaderSortBy"); + html += "

"; + var i; + var length; + var isChecked; + for (html += "
", i = 0, length = options.items.length; i < length; i++) { - var option = options.items[i], - radioValue = option.id.replace(",", "_"); - isChecked = (options.query.SortBy || "").replace(",", "_") == radioValue ? " checked" : "", html += '" + var option = options.items[i]; + var radioValue = option.id.replace(",", "_"); + isChecked = (options.query.SortBy || "").replace(",", "_") == radioValue ? " checked" : ""; + html += '"; } - html += "
", html += '

', html += Globalize.translate("HeaderSortOrder"), html += "

", html += "
", isChecked = "Ascending" == options.query.SortOrder ? " checked" : "", html += '", isChecked = "Descending" == options.query.SortOrder ? " checked" : "", html += '", html += "
", html += "
", dlg.innerHTML = html, dialogHelper.open(dlg); + + html += "
"; + html += '

'; + html += Globalize.translate("HeaderSortOrder"); + html += "

"; + html += "
"; + isChecked = "Ascending" == options.query.SortOrder ? " checked" : ""; + html += '"; + isChecked = "Descending" == options.query.SortOrder ? " checked" : ""; + html += '"; + html += "
"; + html += ""; + dlg.innerHTML = html; + dialogHelper.open(dlg); var sortBys = dlg.querySelectorAll(".menuSortBy"); - for (i = 0, length = sortBys.length; i < length; i++) sortBys[i].addEventListener("change", onSortByChange); + + for (i = 0, length = sortBys.length; i < length; i++) { + sortBys[i].addEventListener("change", onSortByChange); + } + var sortOrders = dlg.querySelectorAll(".menuSortOrder"); - for (i = 0, length = sortOrders.length; i < length; i++) sortOrders[i].addEventListener("change", onSortOrderChange) - }) + + for (i = 0, length = sortOrders.length; i < length; i++) { + sortOrders[i].addEventListener("change", onSortOrderChange); + } + }); } }; - return window.LibraryBrowser = libraryBrowser, libraryBrowser -}); \ No newline at end of file + window.LibraryBrowser = libraryBrowser; + return libraryBrowser; +}); From ecccf00fcb66f36abe5bbd2daaaefb26f5486da2 Mon Sep 17 00:00:00 2001 From: grafixeyehero Date: Tue, 8 Oct 2019 01:01:20 +0300 Subject: [PATCH 004/162] librarymenu.js --- src/scripts/librarymenu.js | 59 +++++++++++++++++++------------------- 1 file changed, 29 insertions(+), 30 deletions(-) diff --git a/src/scripts/librarymenu.js b/src/scripts/librarymenu.js index 9c303d3bde..6b64041966 100644 --- a/src/scripts/librarymenu.js +++ b/src/scripts/librarymenu.js @@ -105,6 +105,7 @@ define(["dom", "layoutManager", "inputManager", "connectionManager", "events", " function bindMenuEvents() { mainDrawerButton = document.querySelector(".mainDrawerButton"); + if (mainDrawerButton) { mainDrawerButton.addEventListener("click", toggleMainDrawer); } @@ -198,18 +199,20 @@ define(["dom", "layoutManager", "inputManager", "connectionManager", "events", " html += '

'; html += globalize.translate("HeaderUser"); html += "

"; + if (appHost.supports("multiserver")) { html += 'wifi' + globalize.translate("ButtonSelectServer") + ""; } + html += 'exit_to_app' + globalize.translate("ButtonSignOut") + ""; html += ""; - } + } // add buttons to navigation drawer - // add buttons to navigation drawer - navDrawerScrollContainer.innerHTML = html; - // bind logout button click to method + navDrawerScrollContainer.innerHTML = html; // bind logout button click to method + var btnLogout = navDrawerScrollContainer.querySelector(".btnLogout"); + if (btnLogout) { btnLogout.addEventListener("click", onLogoutClick); } @@ -250,6 +253,7 @@ define(["dom", "layoutManager", "inputManager", "connectionManager", "events", " pageUrls = pageUrls.split("|"); selected = pageUrls.filter(isUrlInCurrentView).length > 0; } + if (selected) { link.classList.add("navMenuOption-selected"); var title = ""; @@ -377,6 +381,7 @@ define(["dom", "layoutManager", "inputManager", "connectionManager", "events", " function addPluginPagesToMainMenu(links, pluginItems, section) { for (var i = 0, length = pluginItems.length; i < length; i++) { var pluginItem = pluginItems[i]; + if (pluginItem.EnableInMainMenu && pluginItem.MenuSection === section) { links.push({ name: pluginItem.DisplayName, @@ -416,15 +421,14 @@ define(["dom", "layoutManager", "inputManager", "connectionManager", "events", " return getToolsMenuLinks(apiClient).then(function (items) { var item; var menuHtml = ""; - menuHtml += '
'; + for (var i = 0; i < items.length; i++) { item = items[i]; if (item.href) { menuHtml += getToolsLinkHtml(item); - } - else if (item.name) { + } else if (item.name) { menuHtml += '

'; menuHtml += item.name; menuHtml += "

"; @@ -460,8 +464,8 @@ define(["dom", "layoutManager", "inputManager", "connectionManager", "events", " for (var i = 0, length = items.length; i < length; i++) { var view = items[i]; - list.push(view); + if ("livetv" == view.CollectionType) { view.ImageTags = {}; view.icon = "live_tv"; @@ -484,8 +488,7 @@ define(["dom", "layoutManager", "inputManager", "connectionManager", "events", " if (elem) { if (show) { elem.classList.remove("hide"); - } - else { + } else { elem.classList.add("hide"); } } @@ -498,20 +501,18 @@ define(["dom", "layoutManager", "inputManager", "connectionManager", "events", " showBySelector(".libraryMenuDownloads", false); showBySelector(".lnkSyncToOtherDevices", false); return void showBySelector(".userMenuOptions", false); - } + } // FIXME: Potentially the same as above + - // FIXME: Potentially the same as above if (user.Policy.EnableContentDownloading) { showBySelector(".lnkSyncToOtherDevices", true); - } - else { + } else { showBySelector(".lnkSyncToOtherDevices", false); } if (user.Policy.EnableContentDownloading && appHost.supports("sync")) { showBySelector(".libraryMenuDownloads", true); - } - else { + } else { showBySelector(".libraryMenuDownloads", false); } @@ -529,9 +530,11 @@ define(["dom", "layoutManager", "inputManager", "connectionManager", "events", " html += items.map(function (i) { var icon = i.icon || imageHelper.getLibraryIcon(i.CollectionType); var itemId = i.Id; + if (i.onclick) { i.onclick; } + return '' + icon + '' + i.Name + ""; }).join(""); libraryMenuOptions.innerHTML = html; @@ -592,23 +595,17 @@ define(["dom", "layoutManager", "inputManager", "connectionManager", "events", " if (isChannelsPage && "channels" === itemId) { lnkMediaFolder.classList.add("navMenuOption-selected"); - } - else if (isLiveTvPage && "livetv" === itemId) { + } else if (isLiveTvPage && "livetv" === itemId) { lnkMediaFolder.classList.add("navMenuOption-selected"); - } - else if (isEditorPage && "editor" === itemId) { + } else if (isEditorPage && "editor" === itemId) { lnkMediaFolder.classList.add("navMenuOption-selected"); - } - else if (isMySyncPage && "manageoffline" === itemId && -1 != window.location.href.toString().indexOf("mode=download")) { + } else if (isMySyncPage && "manageoffline" === itemId && -1 != window.location.href.toString().indexOf("mode=download")) { lnkMediaFolder.classList.add("navMenuOption-selected"); - } - else if (isMySyncPage && "syncotherdevices" === itemId && -1 == window.location.href.toString().indexOf("mode=download")) { + } else if (isMySyncPage && "syncotherdevices" === itemId && -1 == window.location.href.toString().indexOf("mode=download")) { lnkMediaFolder.classList.add("navMenuOption-selected"); - } - else if (id && itemId == id) { + } else if (id && itemId == id) { lnkMediaFolder.classList.add("navMenuOption-selected"); - } - else { + } else { lnkMediaFolder.classList.remove("navMenuOption-selected"); } } @@ -667,8 +664,7 @@ define(["dom", "layoutManager", "inputManager", "connectionManager", "events", " if (title) { LibraryMenu.setTitle(title); - } - else if (page.classList.contains("standalonePage")) { + } else if (page.classList.contains("standalonePage")) { LibraryMenu.setDefaultTitle(); } } @@ -697,6 +693,7 @@ define(["dom", "layoutManager", "inputManager", "connectionManager", "events", " function refreshLibraryDrawer(user) { loadNavDrawer(); currentDrawerType = "library"; + if (user) { Promise.resolve(user); } else { @@ -729,9 +726,11 @@ define(["dom", "layoutManager", "inputManager", "connectionManager", "events", " return new Promise(function (resolve, reject) { require(["navdrawer"], function (navdrawer) { navDrawerInstance = new navdrawer(getNavDrawerOptions()); + if (!layoutManager.tv) { navDrawerElement.classList.remove("hide"); } + resolve(navDrawerInstance); }); }); From 44ba92261d934399fa4c66bfad52be5c68ece969 Mon Sep 17 00:00:00 2001 From: grafixeyehero Date: Tue, 8 Oct 2019 01:02:07 +0300 Subject: [PATCH 005/162] livetvcomponents.js --- src/scripts/livetvcomponents.js | 124 +++++++++++++++++++++----------- 1 file changed, 83 insertions(+), 41 deletions(-) diff --git a/src/scripts/livetvcomponents.js b/src/scripts/livetvcomponents.js index dee3a92bd1..a883885df1 100644 --- a/src/scripts/livetvcomponents.js +++ b/src/scripts/livetvcomponents.js @@ -1,57 +1,92 @@ -define(["layoutManager", "datetime", "cardBuilder", "apphost"], function(layoutManager, datetime, cardBuilder, appHost) { +define(["layoutManager", "datetime", "cardBuilder", "apphost"], function (layoutManager, datetime, cardBuilder, appHost) { "use strict"; function enableScrollX() { - return !layoutManager.desktop + return !layoutManager.desktop; } function getBackdropShape() { - return enableScrollX() ? "overflowBackdrop" : "backdrop" + if (enableScrollX()) { + return "overflowBackdrop"; + } + + return "backdrop"; } function getTimersHtml(timers, options) { options = options || {}; - var i, length, items = timers.map(function(t) { - return t.Type = "Timer", t - }), - groups = [], - currentGroupName = "", - currentGroup = []; + var i; + var length; + var items = timers.map(function (t) { + t.Type = "Timer"; + return t; + }); + var groups = []; + var currentGroupName = ""; + var currentGroup = []; + for (i = 0, length = items.length; i < length; i++) { - var item = items[i], - dateText = ""; - if (!1 !== options.indexByDate && item.StartDate) try { - var premiereDate = datetime.parseISO8601Date(item.StartDate, !0); - dateText = datetime.toLocaleDateString(premiereDate, { - weekday: "long", - month: "short", - day: "numeric" - }) - } catch (err) {} - dateText != currentGroupName ? (currentGroup.length && groups.push({ + var item = items[i]; + var dateText = ""; + + if (false !== options.indexByDate && item.StartDate) { + try { + var premiereDate = datetime.parseISO8601Date(item.StartDate, true); + dateText = datetime.toLocaleDateString(premiereDate, { + weekday: "long", + month: "short", + day: "numeric" + }); + } catch (err) {} + } + + if (dateText != currentGroupName) { + if (currentGroup.length) { + groups.push({ + name: currentGroupName, + items: currentGroup + }); + } + + currentGroupName = dateText; + currentGroup = [item]; + } else { + currentGroup.push(item); + } + } + + if (currentGroup.length) { + groups.push({ name: currentGroupName, items: currentGroup - }), currentGroupName = dateText, currentGroup = [item]) : currentGroup.push(item) + }); } - currentGroup.length && groups.push({ - name: currentGroupName, - items: currentGroup - }); + var html = ""; + for (i = 0, length = groups.length; i < length; i++) { - var group = groups[i], - supportsImageAnalysis = appHost.supports("imageanalysis"), - cardLayout = appHost.preferVisualCards || supportsImageAnalysis; - if (cardLayout = !0, group.name && (html += '
', html += '

' + group.name + "

"), enableScrollX()) { + var group = groups[i]; + var supportsImageAnalysis = appHost.supports("imageanalysis"); + var cardLayout = appHost.preferVisualCards || supportsImageAnalysis; + + if (cardLayout = true, group.name && (html += '
', html += '

' + group.name + "

"), enableScrollX()) { var scrollXClass = "scrollX hiddenScrollX"; - layoutManager.tv && (scrollXClass += " smoothScrollX"), html += '
' - } else html += '
'; + + if (layoutManager.tv) { + scrollXClass += " smoothScrollX"; + } + + html += '
'; + } else { + html += '
'; + } + html += cardBuilder.getCardsHtml({ items: group.items, shape: cardLayout ? getBackdropShape() : enableScrollX() ? "autoOverflow" : "autoVertical", - showParentTitleOrTitle: !0, - showAirTime: !0, - showAirEndTime: !0, + showParentTitleOrTitle: true, + showAirTime: true, + showAirEndTime: true, showChannelName: !cardLayout, cardLayout: cardLayout, centerText: !cardLayout, @@ -59,15 +94,22 @@ define(["layoutManager", "datetime", "cardBuilder", "apphost"], function(layoutM cardFooterAside: "none", preferThumb: !!cardLayout || "auto", defaultShape: cardLayout ? null : "portrait", - coverImage: !0, - allowBottomPadding: !1, - overlayText: !1, + coverImage: true, + allowBottomPadding: false, + overlayText: false, showChannelLogo: cardLayout - }), html += "
", group.name && (html += "
") + }); + html += "
"; + + if (group.name) { + html += "
"; + } } - return Promise.resolve(html) + + return Promise.resolve(html); } + window.LiveTvHelpers = { getTimersHtml: getTimersHtml - } -}); \ No newline at end of file + }; +}); From f5e62cbd65e59d504eb8f18cabf23d6db756b0f6 Mon Sep 17 00:00:00 2001 From: grafixeyehero Date: Tue, 8 Oct 2019 01:02:37 +0300 Subject: [PATCH 006/162] playlistedit.js --- src/scripts/playlistedit.js | 45 +++++++++++++++++++++++-------------- 1 file changed, 28 insertions(+), 17 deletions(-) diff --git a/src/scripts/playlistedit.js b/src/scripts/playlistedit.js index ef0615e2ba..32a3a960a4 100644 --- a/src/scripts/playlistedit.js +++ b/src/scripts/playlistedit.js @@ -1,39 +1,50 @@ -define(["listView"], function(listView) { +define(["listView"], function (listView) { "use strict"; function getFetchPlaylistItemsFn(itemId) { - return function() { + return function () { var query = { Fields: "PrimaryImageAspectRatio,UserData", EnableImageTypes: "Primary,Backdrop,Banner,Thumb", UserId: ApiClient.getCurrentUserId() }; - return ApiClient.getJSON(ApiClient.getUrl("Playlists/" + itemId + "/Items", query)) - } + return ApiClient.getJSON(ApiClient.getUrl("Playlists/" + itemId + "/Items", query)); + }; } function getItemsHtmlFn(itemId) { - return function(items) { + return function (items) { return listView.getListViewHtml({ items: items, - showIndex: !1, - showRemoveFromPlaylist: !0, - playFromHere: !0, + showIndex: false, + showRemoveFromPlaylist: true, + playFromHere: true, action: "playallfromhere", - smallIcon: !0, - dragHandle: !0, + smallIcon: true, + dragHandle: true, playlistId: itemId - }) - } + }); + }; } function init(page, item) { var elem = page.querySelector("#childrenContent .itemsContainer"); - elem.classList.add("vertical-list"), elem.classList.remove("vertical-wrap"), elem.enableDragReordering(!0), elem.fetchData = getFetchPlaylistItemsFn(item.Id), elem.getItemsHtml = getItemsHtmlFn(item.Id) + elem.classList.add("vertical-list"); + elem.classList.remove("vertical-wrap"); + elem.enableDragReordering(true); + elem.fetchData = getFetchPlaylistItemsFn(item.Id); + elem.getItemsHtml = getItemsHtmlFn(item.Id); } + window.PlaylistViewer = { - render: function(page, item) { - page.playlistInit || (page.playlistInit = !0, init(page, item)), page.querySelector("#childrenContent").classList.add("verticalSection-extrabottompadding"), page.querySelector("#childrenContent .itemsContainer").refreshItems() + render: function (page, item) { + if (!page.playlistInit) { + page.playlistInit = true; + init(page, item); + } + + page.querySelector("#childrenContent").classList.add("verticalSection-extrabottompadding"); + page.querySelector("#childrenContent .itemsContainer").refreshItems(); } - } -}); \ No newline at end of file + }; +}); From 850c2c4baf03ab81b8fde3e66e70403c60e53af7 Mon Sep 17 00:00:00 2001 From: grafixeyehero Date: Tue, 8 Oct 2019 01:03:08 +0300 Subject: [PATCH 007/162] playlists.js --- src/scripts/playlists.js | 222 ++++++++++++++++++++++++--------------- 1 file changed, 137 insertions(+), 85 deletions(-) diff --git a/src/scripts/playlists.js b/src/scripts/playlists.js index ee9fac6c58..606a34c787 100644 --- a/src/scripts/playlists.js +++ b/src/scripts/playlists.js @@ -1,124 +1,176 @@ -define(["loading", "listView", "cardBuilder", "libraryMenu", "libraryBrowser", "apphost", "imageLoader", "emby-itemscontainer"], function(loading, listView, cardBuilder, libraryMenu, libraryBrowser, appHost, imageLoader) { +define(["loading", "listView", "cardBuilder", "libraryMenu", "libraryBrowser", "apphost", "imageLoader", "emby-itemscontainer"], function (loading, listView, cardBuilder, libraryMenu, libraryBrowser, appHost, imageLoader) { "use strict"; - return function(view, params) { + + return function (view, params) { function getPageData(context) { - var key = getSavedQueryKey(context), - pageData = data[key]; - return pageData || (pageData = data[key] = { - query: { - SortBy: "SortName", - SortOrder: "Ascending", - IncludeItemTypes: "Playlist", - Recursive: !0, - Fields: "PrimaryImageAspectRatio,SortName,CumulativeRunTimeTicks,CanDelete", - StartIndex: 0, - Limit: 100 - }, - view: libraryBrowser.getSavedView(key) || "Poster" - }, pageData.query.ParentId = libraryMenu.getTopParentId(), libraryBrowser.loadSavedQueryValues(key, pageData.query)), pageData + var key = getSavedQueryKey(context); + var pageData = data[key]; + + if (!pageData) { + pageData = data[key] = { + query: { + SortBy: "SortName", + SortOrder: "Ascending", + IncludeItemTypes: "Playlist", + Recursive: true, + Fields: "PrimaryImageAspectRatio,SortName,CumulativeRunTimeTicks,CanDelete", + StartIndex: 0, + Limit: 100 + }, + view: libraryBrowser.getSavedView(key) || "Poster" + }; + pageData.query.ParentId = libraryMenu.getTopParentId(); + libraryBrowser.loadSavedQueryValues(key, pageData.query); + } + + return pageData; } function getQuery(context) { - return getPageData(context).query + return getPageData(context).query; } function getSavedQueryKey(context) { - return context.savedQueryKey || (context.savedQueryKey = libraryBrowser.getSavedQueryKey()), context.savedQueryKey + if (!context.savedQueryKey) { + context.savedQueryKey = libraryBrowser.getSavedQueryKey(); + } + + return context.savedQueryKey; } function showLoadingMessage() { - loading.show() + loading.show(); } function hideLoadingMessage() { - loading.hide() + loading.hide(); } function onViewStyleChange() { - var viewStyle = getPageData(view).view, - itemsContainer = view.querySelector(".itemsContainer"); - "List" == viewStyle ? (itemsContainer.classList.add("vertical-list"), itemsContainer.classList.remove("vertical-wrap")) : (itemsContainer.classList.remove("vertical-list"), itemsContainer.classList.add("vertical-wrap")), itemsContainer.innerHTML = "" + var viewStyle = getPageData(view).view; + var itemsContainer = view.querySelector(".itemsContainer"); + + if ("List" == viewStyle) { + itemsContainer.classList.add("vertical-list"); + itemsContainer.classList.remove("vertical-wrap"); + } else { + itemsContainer.classList.remove("vertical-list"); + itemsContainer.classList.add("vertical-wrap"); + } + + itemsContainer.innerHTML = ""; } function reloadItems() { showLoadingMessage(); - var query = getQuery(view), - promise1 = ApiClient.getItems(Dashboard.getCurrentUserId(), query), - promise2 = Dashboard.getCurrentUser(); - Promise.all([promise1, promise2]).then(function(responses) { + var query = getQuery(view); + var promise1 = ApiClient.getItems(Dashboard.getCurrentUserId(), query); + var promise2 = Dashboard.getCurrentUser(); + Promise.all([promise1, promise2]).then(function (responses) { var result = responses[0]; responses[1]; window.scrollTo(0, 0); - var html = "", - viewStyle = getPageData(view).view; + var html = ""; + var viewStyle = getPageData(view).view; view.querySelector(".listTopPaging").innerHTML = libraryBrowser.getQueryPagingHtml({ startIndex: query.StartIndex, limit: query.Limit, totalRecordCount: result.TotalRecordCount, - viewButton: !1, - showLimit: !1, - updatePageSizeSetting: !1, - addLayoutButton: !0, + viewButton: false, + showLimit: false, + updatePageSizeSetting: false, + addLayoutButton: true, layouts: "List,Poster,PosterCard,Thumb,ThumbCard", currentLayout: viewStyle - }), result.TotalRecordCount ? (html = "List" == viewStyle ? listView.getListViewHtml({ - items: result.Items, - sortBy: query.SortBy - }) : "PosterCard" == viewStyle ? cardBuilder.getCardsHtml({ - items: result.Items, - shape: "square", - coverImage: !0, - showTitle: !0, - cardLayout: !0 - }) : "Thumb" == viewStyle ? cardBuilder.getCardsHtml({ - items: result.Items, - shape: "backdrop", - showTitle: !0, - centerText: !0, - preferThumb: !0, - overlayPlayButton: !0 - }) : "ThumbCard" == viewStyle ? cardBuilder.getCardsHtml({ - items: result.Items, - shape: "backdrop", - showTitle: !0, - preferThumb: !0, - cardLayout: !0 - }) : cardBuilder.getCardsHtml({ - items: result.Items, - shape: "square", - showTitle: !0, - coverImage: !0, - centerText: !0, - overlayPlayButton: !0 - }), view.querySelector(".noItemsMessage").classList.add("hide")) : view.querySelector(".noItemsMessage").classList.remove("hide"); + }); + + if (result.TotalRecordCount) { + html = "List" == viewStyle ? listView.getListViewHtml({ + items: result.Items, + sortBy: query.SortBy + }) : "PosterCard" == viewStyle ? cardBuilder.getCardsHtml({ + items: result.Items, + shape: "square", + coverImage: true, + showTitle: true, + cardLayout: true + }) : "Thumb" == viewStyle ? cardBuilder.getCardsHtml({ + items: result.Items, + shape: "backdrop", + showTitle: true, + centerText: true, + preferThumb: true, + overlayPlayButton: true + }) : "ThumbCard" == viewStyle ? cardBuilder.getCardsHtml({ + items: result.Items, + shape: "backdrop", + showTitle: true, + preferThumb: true, + cardLayout: true + }) : cardBuilder.getCardsHtml({ + items: result.Items, + shape: "square", + showTitle: true, + coverImage: true, + centerText: true, + overlayPlayButton: true + }); + view.querySelector(".noItemsMessage").classList.add("hide"); + } else { + view.querySelector(".noItemsMessage").classList.remove("hide"); + } + var elem = view.querySelector(".itemsContainer"); - elem.innerHTML = html, imageLoader.lazyChildren(elem); + elem.innerHTML = html; + imageLoader.lazyChildren(elem); var btnNextPage = view.querySelector(".btnNextPage"); - btnNextPage && btnNextPage.addEventListener("click", function() { - query.StartIndex += query.Limit, reloadItems() - }); + + if (btnNextPage) { + btnNextPage.addEventListener("click", function () { + query.StartIndex += query.Limit; + reloadItems(); + }); + } + var btnPreviousPage = view.querySelector(".btnPreviousPage"); - btnPreviousPage && btnPreviousPage.addEventListener("click", function() { - query.StartIndex -= query.Limit, reloadItems() - }); + + if (btnPreviousPage) { + btnPreviousPage.addEventListener("click", function () { + query.StartIndex -= query.Limit; + reloadItems(); + }); + } + var btnChangeLayout = view.querySelector(".btnChangeLayout"); - btnChangeLayout && btnChangeLayout.addEventListener("layoutchange", function(e) { - var layout = e.detail.viewStyle; - getPageData(view).view = layout, libraryBrowser.saveViewSetting(getSavedQueryKey(view), layout), onViewStyleChange(), reloadItems() - }), libraryBrowser.saveQueryValues(getSavedQueryKey(view), query), hideLoadingMessage() - }) + + if (btnChangeLayout) { + btnChangeLayout.addEventListener("layoutchange", function (e) { + var layout = e.detail.viewStyle; + getPageData(view).view = layout; + libraryBrowser.saveViewSetting(getSavedQueryKey(view), layout); + onViewStyleChange(); + reloadItems(); + }); + } + + libraryBrowser.saveQueryValues(getSavedQueryKey(view), query); + hideLoadingMessage(); + }); } + var data = {}; - view.addEventListener("viewbeforeshow", function() { - reloadItems() - }), view.querySelector(".btnNewPlaylist").addEventListener("click", function() { - require(["playlistEditor"], function(playlistEditor) { + view.addEventListener("viewbeforeshow", function () { + reloadItems(); + }); + view.querySelector(".btnNewPlaylist").addEventListener("click", function () { + require(["playlistEditor"], function (playlistEditor) { var serverId = ApiClient.serverInfo().Id; - (new playlistEditor).show({ + new playlistEditor().show({ items: [], serverId: serverId - }) - }) - }), onViewStyleChange() - } -}); \ No newline at end of file + }); + }); + }); + onViewStyleChange(); + }; +}); From 5bed7bbf350a805e6650495f3f90147fe3e914b9 Mon Sep 17 00:00:00 2001 From: grafixeyehero Date: Tue, 8 Oct 2019 01:03:29 +0300 Subject: [PATCH 008/162] searchtab.js --- src/scripts/searchtab.js | 52 +++++++++++++++++++++++++++++----------- 1 file changed, 38 insertions(+), 14 deletions(-) diff --git a/src/scripts/searchtab.js b/src/scripts/searchtab.js index 538770e42e..c0852bfc77 100644 --- a/src/scripts/searchtab.js +++ b/src/scripts/searchtab.js @@ -1,30 +1,54 @@ -define(["searchFields", "searchResults", "events"], function(SearchFields, SearchResults, events) { +define(["searchFields", "searchResults", "events"], function (SearchFields, SearchResults, events) { "use strict"; function init(instance, tabContent, options) { - tabContent.innerHTML = '
', instance.searchFields = new SearchFields({ + tabContent.innerHTML = '
'; + instance.searchFields = new SearchFields({ element: tabContent.querySelector(".searchFields") - }), instance.searchResults = new SearchResults({ + }); + instance.searchResults = new SearchResults({ element: tabContent.querySelector(".searchResults"), serverId: ApiClient.serverId(), parentId: options.parentId, collectionType: options.collectionType - }), events.on(instance.searchFields, "search", function(e, value) { - instance.searchResults.search(value) - }) + }); + events.on(instance.searchFields, "search", function (e, value) { + instance.searchResults.search(value); + }); } function SearchTab(view, tabContent, options) { var self = this; - options = options || {}, init(this, tabContent, options), self.preRender = function() {}, self.renderTab = function() { + options = options || {}; + init(this, tabContent, options); + + self.preRender = function () {}; + + self.renderTab = function () { var searchFields = this.searchFields; - searchFields && searchFields.focus() - } + + if (searchFields) { + searchFields.focus(); + } + }; } - return SearchTab.prototype.destroy = function() { + + SearchTab.prototype.destroy = function () { var searchFields = this.searchFields; - searchFields && searchFields.destroy(), this.searchFields = null; + + if (searchFields) { + searchFields.destroy(); + } + + this.searchFields = null; var searchResults = this.searchResults; - searchResults && searchResults.destroy(), this.searchResults = null - }, SearchTab -}); \ No newline at end of file + + if (searchResults) { + searchResults.destroy(); + } + + this.searchResults = null; + }; + + return SearchTab; +}); From fe08645a9879b4c34dc34e8a3970459ed28fffa9 Mon Sep 17 00:00:00 2001 From: grafixeyehero Date: Tue, 8 Oct 2019 01:03:49 +0300 Subject: [PATCH 009/162] taskbutton.js --- src/scripts/taskbutton.js | 99 ++++++++++++++++++++++++++++++--------- 1 file changed, 77 insertions(+), 22 deletions(-) diff --git a/src/scripts/taskbutton.js b/src/scripts/taskbutton.js index d41cf7b5c2..37e4a3c973 100644 --- a/src/scripts/taskbutton.js +++ b/src/scripts/taskbutton.js @@ -1,48 +1,103 @@ -define(["events", "userSettings", "serverNotifications", "connectionManager", "emby-button"], function(events, userSettings, serverNotifications, connectionManager) { +define(["events", "userSettings", "serverNotifications", "connectionManager", "emby-button"], function (events, userSettings, serverNotifications, connectionManager) { "use strict"; - return function(options) { + + return function (options) { function pollTasks() { connectionManager.getApiClient(serverId).getScheduledTasks({ - IsEnabled: !0 - }).then(updateTasks) + IsEnabled: true + }).then(updateTasks); } function updateTasks(tasks) { - var task = tasks.filter(function(t) { - return t.Key == options.taskKey + var task = tasks.filter(function (t) { + return t.Key == options.taskKey; })[0]; + if (options.panel && (task ? options.panel.classList.remove("hide") : options.panel.classList.add("hide")), task) { - "Idle" == task.State ? button.removeAttribute("disabled") : button.setAttribute("disabled", "disabled"), button.setAttribute("data-taskid", task.Id); + if ("Idle" == task.State) { + button.removeAttribute("disabled"); + } else { + button.setAttribute("disabled", "disabled"); + } + + button.setAttribute("data-taskid", task.Id); var progress = (task.CurrentProgressPercentage || 0).toFixed(1); + if (options.progressElem && (options.progressElem.value = progress, "Running" == task.State ? options.progressElem.classList.remove("hide") : options.progressElem.classList.add("hide")), options.lastResultElem) { var lastResult = task.LastExecutionResult ? task.LastExecutionResult.Status : ""; - "Failed" == lastResult ? options.lastResultElem.html('(' + Globalize.translate("LabelFailed") + ")") : "Cancelled" == lastResult ? options.lastResultElem.html('(' + Globalize.translate("LabelCancelled") + ")") : "Aborted" == lastResult ? options.lastResultElem.html('' + Globalize.translate("LabelAbortedByServerShutdown") + "") : options.lastResultElem.html(lastResult) + + if ("Failed" == lastResult) { + options.lastResultElem.html('(' + Globalize.translate("LabelFailed") + ")"); + } else { + if ("Cancelled" == lastResult) { + options.lastResultElem.html('(' + Globalize.translate("LabelCancelled") + ")"); + } else { + if ("Aborted" == lastResult) { + options.lastResultElem.html('' + Globalize.translate("LabelAbortedByServerShutdown") + ""); + } else { + options.lastResultElem.html(lastResult); + } + } + } } } } function onScheduledTaskMessageConfirmed(id) { - connectionManager.getApiClient(serverId).startScheduledTask(id).then(pollTasks) + connectionManager.getApiClient(serverId).startScheduledTask(id).then(pollTasks); } function onButtonClick() { - onScheduledTaskMessageConfirmed(this.getAttribute("data-taskid")) + onScheduledTaskMessageConfirmed(this.getAttribute("data-taskid")); } function onScheduledTasksUpdate(e, apiClient, info) { - apiClient.serverId() === serverId && updateTasks(info) + if (apiClient.serverId() === serverId) { + updateTasks(info); + } } function onPollIntervalFired() { - connectionManager.getApiClient(serverId).isMessageChannelOpen() || pollTasks() + if (!connectionManager.getApiClient(serverId).isMessageChannelOpen()) { + pollTasks(); + } } - var pollInterval, button = options.button, - serverId = ApiClient.serverId(); - options.panel && options.panel.classList.add("hide"), "off" == options.mode ? (button.removeEventListener("click", onButtonClick), events.off(serverNotifications, "ScheduledTasksInfo", onScheduledTasksUpdate), function() { - connectionManager.getApiClient(serverId).sendMessage("ScheduledTasksInfoStop"), pollInterval && clearInterval(pollInterval) - }()) : (button.addEventListener("click", onButtonClick), pollTasks(), function() { - var apiClient = connectionManager.getApiClient(serverId); - pollInterval && clearInterval(pollInterval), apiClient.sendMessage("ScheduledTasksInfoStart", "1000,1000"), pollInterval = setInterval(onPollIntervalFired, 1e4) - }(), events.on(serverNotifications, "ScheduledTasksInfo", onScheduledTasksUpdate)) - } -}); \ No newline at end of file + + var pollInterval; + var button = options.button; + var serverId = ApiClient.serverId(); + + if (options.panel) { + options.panel.classList.add("hide"); + } + + if ("off" == options.mode) { + button.removeEventListener("click", onButtonClick); + events.off(serverNotifications, "ScheduledTasksInfo", onScheduledTasksUpdate); + + (function () { + connectionManager.getApiClient(serverId).sendMessage("ScheduledTasksInfoStop"); + + if (pollInterval) { + clearInterval(pollInterval); + } + })(); + } else { + button.addEventListener("click", onButtonClick); + pollTasks(); + + (function () { + var apiClient = connectionManager.getApiClient(serverId); + + if (pollInterval) { + clearInterval(pollInterval); + } + + apiClient.sendMessage("ScheduledTasksInfoStart", "1000,1000"); + pollInterval = setInterval(onPollIntervalFired, 1e4); + })(); + + events.on(serverNotifications, "ScheduledTasksInfo", onScheduledTasksUpdate); + } + }; +}); From 3464b847a6d118c49c905dd2f03aa2069a4a3848 Mon Sep 17 00:00:00 2001 From: grafixeyehero Date: Tue, 8 Oct 2019 01:28:15 +0300 Subject: [PATCH 010/162] wizardfinishpage.js --- src/controllers/wizardfinishpage.js | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/src/controllers/wizardfinishpage.js b/src/controllers/wizardfinishpage.js index 417b2425a5..ba26190a5f 100644 --- a/src/controllers/wizardfinishpage.js +++ b/src/controllers/wizardfinishpage.js @@ -1,22 +1,24 @@ -define(["loading"], function(loading) { +define(["loading"], function (loading) { "use strict"; function onFinish() { - loading.show(), ApiClient.ajax({ + loading.show(); + ApiClient.ajax({ url: ApiClient.getUrl("Startup/Complete"), type: "POST" - }).then(function() { + }).then(function () { Dashboard.navigate("dashboard.html"); loading.hide(); }); } - return function(view, params) { + + return function (view, params) { view.querySelector(".btnWizardNext").addEventListener("click", onFinish); - view.addEventListener("viewshow", function() { - document.querySelector(".skinHeader").classList.add("noHomeButtonHeader") + view.addEventListener("viewshow", function () { + document.querySelector(".skinHeader").classList.add("noHomeButtonHeader"); }); - view.addEventListener("viewhide", function() { - document.querySelector(".skinHeader").classList.remove("noHomeButtonHeader") + view.addEventListener("viewhide", function () { + document.querySelector(".skinHeader").classList.remove("noHomeButtonHeader"); }); }; }); From f9b6b10ef4ed1c979fc4734a0ac40007e79e6c20 Mon Sep 17 00:00:00 2001 From: grafixeyehero Date: Tue, 8 Oct 2019 01:28:30 +0300 Subject: [PATCH 011/162] wizardremoteaccess.js --- src/controllers/wizardremoteaccess.js | 40 ++++++++++++++++----------- 1 file changed, 24 insertions(+), 16 deletions(-) diff --git a/src/controllers/wizardremoteaccess.js b/src/controllers/wizardremoteaccess.js index 6856e0074f..554a417e57 100644 --- a/src/controllers/wizardremoteaccess.js +++ b/src/controllers/wizardremoteaccess.js @@ -1,31 +1,39 @@ -define(["loading", "emby-checkbox", "emby-button", "emby-select"], function(loading) { +define(["loading", "emby-checkbox", "emby-button", "emby-select"], function (loading) { "use strict"; function save(page) { loading.show(); - var apiClient = ApiClient, - config = {}; - config.EnableRemoteAccess = page.querySelector("#chkRemoteAccess").checked, config.EnableAutomaticPortMapping = page.querySelector("#chkEnableUpnp").checked, apiClient.ajax({ + var apiClient = ApiClient; + var config = {}; + config.EnableRemoteAccess = page.querySelector("#chkRemoteAccess").checked; + config.EnableAutomaticPortMapping = page.querySelector("#chkEnableUpnp").checked; + apiClient.ajax({ type: "POST", data: config, url: apiClient.getUrl("Startup/RemoteAccess") - }).then(function() { - loading.hide(), navigateToNextPage() - }) + }).then(function () { + loading.hide(); + navigateToNextPage(); + }); } function navigateToNextPage() { - Dashboard.navigate("wizardfinish.html") + Dashboard.navigate("wizardfinish.html"); } function onSubmit(e) { - return save(this), e.preventDefault(), !1 - } - return function(view, params) { - view.querySelector(".wizardSettingsForm").addEventListener("submit", onSubmit), view.addEventListener("viewshow", function() { - document.querySelector(".skinHeader").classList.add("noHomeButtonHeader") - }), view.addEventListener("viewhide", function() { - document.querySelector(".skinHeader").classList.remove("noHomeButtonHeader") - }) + save(this); + e.preventDefault(); + return false; } + + return function (view, params) { + view.querySelector(".wizardSettingsForm").addEventListener("submit", onSubmit); + view.addEventListener("viewshow", function () { + document.querySelector(".skinHeader").classList.add("noHomeButtonHeader"); + }); + view.addEventListener("viewhide", function () { + document.querySelector(".skinHeader").classList.remove("noHomeButtonHeader"); + }); + }; }); From c94e970ac029ca05e6bffff7d5fa173fd13d4434 Mon Sep 17 00:00:00 2001 From: grafixeyehero Date: Tue, 8 Oct 2019 01:28:44 +0300 Subject: [PATCH 012/162] wizardsettings.js --- src/controllers/wizardsettings.js | 75 +++++++++++++++++++------------ 1 file changed, 46 insertions(+), 29 deletions(-) diff --git a/src/controllers/wizardsettings.js b/src/controllers/wizardsettings.js index 6303d95efa..487f068a40 100644 --- a/src/controllers/wizardsettings.js +++ b/src/controllers/wizardsettings.js @@ -1,67 +1,84 @@ -define(["loading", "emby-checkbox", "emby-button", "emby-select"], function(loading) { +define(["loading", "emby-checkbox", "emby-button", "emby-select"], function (loading) { "use strict"; function save(page) { loading.show(); var apiClient = ApiClient; - apiClient.getJSON(apiClient.getUrl("Startup/Configuration")).then(function(config) { - config.PreferredMetadataLanguage = page.querySelector("#selectLanguage").value, config.MetadataCountryCode = page.querySelector("#selectCountry").value, apiClient.ajax({ + apiClient.getJSON(apiClient.getUrl("Startup/Configuration")).then(function (config) { + config.PreferredMetadataLanguage = page.querySelector("#selectLanguage").value; + config.MetadataCountryCode = page.querySelector("#selectCountry").value; + apiClient.ajax({ type: "POST", data: config, url: apiClient.getUrl("Startup/Configuration") - }).then(function() { - loading.hide(), navigateToNextPage() - }) - }) + }).then(function () { + loading.hide(); + navigateToNextPage(); + }); + }); } function populateLanguages(select, languages) { var html = ""; html += ""; + for (var i = 0, length = languages.length; i < length; i++) { var culture = languages[i]; - html += "" + html += ""; } - select.innerHTML = html + + select.innerHTML = html; } function populateCountries(select, allCountries) { var html = ""; html += ""; + for (var i = 0, length = allCountries.length; i < length; i++) { var culture = allCountries[i]; - html += "" + html += ""; } - select.innerHTML = html + + select.innerHTML = html; } function reloadData(page, config, cultures, countries) { - populateLanguages(page.querySelector("#selectLanguage"), cultures), populateCountries(page.querySelector("#selectCountry"), countries), page.querySelector("#selectLanguage").value = config.PreferredMetadataLanguage, page.querySelector("#selectCountry").value = config.MetadataCountryCode, loading.hide() + populateLanguages(page.querySelector("#selectLanguage"), cultures); + populateCountries(page.querySelector("#selectCountry"), countries); + page.querySelector("#selectLanguage").value = config.PreferredMetadataLanguage; + page.querySelector("#selectCountry").value = config.MetadataCountryCode; + loading.hide(); } function reload(page) { loading.show(); - var apiClient = ApiClient, - promise1 = apiClient.getJSON(apiClient.getUrl("Startup/Configuration")), - promise2 = apiClient.getCultures(), - promise3 = apiClient.getCountries(); - Promise.all([promise1, promise2, promise3]).then(function(responses) { - reloadData(page, responses[0], responses[1], responses[2]) - }) + var apiClient = ApiClient; + var promise1 = apiClient.getJSON(apiClient.getUrl("Startup/Configuration")); + var promise2 = apiClient.getCultures(); + var promise3 = apiClient.getCountries(); + Promise.all([promise1, promise2, promise3]).then(function (responses) { + reloadData(page, responses[0], responses[1], responses[2]); + }); } function navigateToNextPage() { - Dashboard.navigate("wizardremoteaccess.html") + Dashboard.navigate("wizardremoteaccess.html"); } function onSubmit(e) { - return save(this), e.preventDefault(), !1 + save(this); + e.preventDefault(); + return false; } - return function(view, params) { - view.querySelector(".wizardSettingsForm").addEventListener("submit", onSubmit), view.addEventListener("viewshow", function() { - document.querySelector(".skinHeader").classList.add("noHomeButtonHeader"), reload(this) - }), view.addEventListener("viewhide", function() { - document.querySelector(".skinHeader").classList.remove("noHomeButtonHeader") - }) - } -}); \ No newline at end of file + + return function (view, params) { + view.querySelector(".wizardSettingsForm").addEventListener("submit", onSubmit); + view.addEventListener("viewshow", function () { + document.querySelector(".skinHeader").classList.add("noHomeButtonHeader"); + reload(this); + }); + view.addEventListener("viewhide", function () { + document.querySelector(".skinHeader").classList.remove("noHomeButtonHeader"); + }); + }; +}); From e192f1f3c6b138e60e6d18c67d1fad76047b2299 Mon Sep 17 00:00:00 2001 From: grafixeyehero Date: Tue, 8 Oct 2019 01:28:58 +0300 Subject: [PATCH 013/162] wizardstart.js --- src/controllers/wizardstart.js | 59 +++++++++++++++++++--------------- 1 file changed, 33 insertions(+), 26 deletions(-) diff --git a/src/controllers/wizardstart.js b/src/controllers/wizardstart.js index 568ef15b2b..1c2917b9ec 100644 --- a/src/controllers/wizardstart.js +++ b/src/controllers/wizardstart.js @@ -1,41 +1,48 @@ -define(["jQuery", "loading", "emby-button", "emby-select"], function($, loading) { +define(["jQuery", "loading", "emby-button", "emby-select"], function ($, loading) { "use strict"; function loadPage(page, config, languageOptions) { - $("#selectLocalizationLanguage", page).html(languageOptions.map(function(l) { - return '" - })).val(config.UICulture), loading.hide() + $("#selectLocalizationLanguage", page).html(languageOptions.map(function (l) { + return '"; + })).val(config.UICulture); + loading.hide(); } function save(page) { loading.show(); var apiClient = ApiClient; - apiClient.getJSON(apiClient.getUrl("Startup/Configuration")).then(function(config) { - config.UICulture = $("#selectLocalizationLanguage", page).val(), apiClient.ajax({ + apiClient.getJSON(apiClient.getUrl("Startup/Configuration")).then(function (config) { + config.UICulture = $("#selectLocalizationLanguage", page).val(); + apiClient.ajax({ type: "POST", data: config, url: apiClient.getUrl("Startup/Configuration") - }).then(function() { - Dashboard.navigate("wizarduser.html") - }) - }) + }).then(function () { + Dashboard.navigate("wizarduser.html"); + }); + }); } function onSubmit() { - return save($(this).parents(".page")), !1 + save($(this).parents(".page")); + return false; } - return function(view, params) { - $(".wizardStartForm", view).on("submit", onSubmit), view.addEventListener("viewshow", function() { - document.querySelector(".skinHeader").classList.add("noHomeButtonHeader"), loading.show(); - var page = this, - apiClient = ApiClient, - promise1 = apiClient.getJSON(apiClient.getUrl("Startup/Configuration")), - promise2 = apiClient.getJSON(apiClient.getUrl("Localization/Options")); - Promise.all([promise1, promise2]).then(function(responses) { - loadPage(page, responses[0], responses[1]) - }) - }), view.addEventListener("viewhide", function() { - document.querySelector(".skinHeader").classList.remove("noHomeButtonHeader") - }) - } -}); \ No newline at end of file + + return function (view, params) { + $(".wizardStartForm", view).on("submit", onSubmit); + view.addEventListener("viewshow", function () { + document.querySelector(".skinHeader").classList.add("noHomeButtonHeader"); + loading.show(); + var page = this; + var apiClient = ApiClient; + var promise1 = apiClient.getJSON(apiClient.getUrl("Startup/Configuration")); + var promise2 = apiClient.getJSON(apiClient.getUrl("Localization/Options")); + Promise.all([promise1, promise2]).then(function (responses) { + loadPage(page, responses[0], responses[1]); + }); + }); + view.addEventListener("viewhide", function () { + document.querySelector(".skinHeader").classList.remove("noHomeButtonHeader"); + }); + }; +}); From e0cf0141974b59e3c833f05e514278232bb01a0b Mon Sep 17 00:00:00 2001 From: grafixeyehero Date: Tue, 8 Oct 2019 01:29:20 +0300 Subject: [PATCH 014/162] wizarduserpage.js --- src/controllers/wizarduserpage.js | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/src/controllers/wizarduserpage.js b/src/controllers/wizarduserpage.js index a3654edf0e..d29be37c13 100644 --- a/src/controllers/wizarduserpage.js +++ b/src/controllers/wizarduserpage.js @@ -1,4 +1,4 @@ -define(["loading", "globalize", "dashboardcss", "emby-input", "emby-button", "emby-button"], function(loading, globalize) { +define(["loading", "globalize", "dashboardcss", "emby-input", "emby-button", "emby-button"], function (loading, globalize) { "use strict"; function getApiClient() { @@ -30,13 +30,15 @@ define(["loading", "globalize", "dashboardcss", "emby-input", "emby-button", "em function onSubmit(e) { var form = this; + if (form.querySelector("#txtManualPassword").value != form.querySelector("#txtPasswordConfirm").value) { - require(["toast"], function(toast) { + require(["toast"], function (toast) { toast(Globalize.translate("PasswordMatchError")); }); } else { submit(form); } + e.preventDefault(); return false; } @@ -45,20 +47,21 @@ define(["loading", "globalize", "dashboardcss", "emby-input", "emby-button", "em loading.show(); var page = this; var apiClient = getApiClient(); - apiClient.getJSON(apiClient.getUrl("Startup/User")).then(function(user) { + apiClient.getJSON(apiClient.getUrl("Startup/User")).then(function (user) { page.querySelector("#txtUsername").value = user.Name || ""; page.querySelector("#txtManualPassword").value = user.Password || ""; loading.hide(); - }) - } - return function(view, params) { - view.querySelector(".wizardUserForm").addEventListener("submit", onSubmit); - view.addEventListener("viewshow", function() { - document.querySelector(".skinHeader").classList.add("noHomeButtonHeader") }); - view.addEventListener("viewhide", function() { - document.querySelector(".skinHeader").classList.remove("noHomeButtonHeader") + } + + return function (view, params) { + view.querySelector(".wizardUserForm").addEventListener("submit", onSubmit); + view.addEventListener("viewshow", function () { + document.querySelector(".skinHeader").classList.add("noHomeButtonHeader"); + }); + view.addEventListener("viewhide", function () { + document.querySelector(".skinHeader").classList.remove("noHomeButtonHeader"); }); view.addEventListener("viewshow", onViewShow); - } + }; }); From 5ebf1bda80f296a572e73d0edac1a9f1fcca1d2a Mon Sep 17 00:00:00 2001 From: grafixeyehero Date: Tue, 8 Oct 2019 01:29:47 +0300 Subject: [PATCH 015/162] themeloader.js --- src/scripts/themeloader.js | 32 ++++++++++++++++++++++---------- 1 file changed, 22 insertions(+), 10 deletions(-) diff --git a/src/scripts/themeloader.js b/src/scripts/themeloader.js index eb783b132d..ea7ff57f9a 100644 --- a/src/scripts/themeloader.js +++ b/src/scripts/themeloader.js @@ -1,15 +1,27 @@ -define(["userSettings", "skinManager", "connectionManager", "events"], function(userSettings, skinManager, connectionManager, events) { +define(["userSettings", "skinManager", "connectionManager", "events"], function (userSettings, skinManager, connectionManager, events) { "use strict"; + var currentViewType; - pageClassOn("viewbeforeshow", "page", function() { - var classList = this.classList, - viewType = classList.contains("type-interior") || classList.contains("wizardPage") ? "a" : "b"; + pageClassOn("viewbeforeshow", "page", function () { + var classList = this.classList; + var viewType = classList.contains("type-interior") || classList.contains("wizardPage") ? "a" : "b"; + if (viewType !== currentViewType) { currentViewType = viewType; - var theme, context; - "a" === viewType ? (theme = userSettings.dashboardTheme(), context = "serverdashboard") : theme = userSettings.theme(), skinManager.setTheme(theme, context) + var theme; + var context; + + if ("a" === viewType) { + theme = userSettings.dashboardTheme(); + context = "serverdashboard"; + } else { + theme = userSettings.theme(); + } + + skinManager.setTheme(theme, context); } - }), events.on(connectionManager, "localusersignedin", function(e, user) { - currentViewType = null - }) -}); \ No newline at end of file + }); + events.on(connectionManager, "localusersignedin", function (e, user) { + currentViewType = null; + }); +}); From 678b558935b684c207c61005218fe0448bcf7f95 Mon Sep 17 00:00:00 2001 From: grafixeyehero Date: Tue, 8 Oct 2019 01:30:02 +0300 Subject: [PATCH 016/162] userpassword.js --- src/scripts/userpassword.js | 32 +++++++++++++++++++++----------- 1 file changed, 21 insertions(+), 11 deletions(-) diff --git a/src/scripts/userpassword.js b/src/scripts/userpassword.js index 41dc290248..52e06e6cec 100644 --- a/src/scripts/userpassword.js +++ b/src/scripts/userpassword.js @@ -1,20 +1,30 @@ -define(["jQuery", "loading", "libraryMenu"], function($, loading, libraryMenu) { +define(["jQuery", "loading", "libraryMenu"], function ($, loading, libraryMenu) { "use strict"; function loadUser(page, user) { - libraryMenu.setTitle(user.Name), "Guest" == user.ConnectLinkType ? $(".connectMessage", page).show() : $(".connectMessage", page).hide(), loading.hide() + libraryMenu.setTitle(user.Name); + + if ("Guest" == user.ConnectLinkType) { + $(".connectMessage", page).show(); + } else { + $(".connectMessage", page).hide(); + } + + loading.hide(); } function loadData(page) { loading.show(); var userId = getParameterByName("userId"); - ApiClient.getUser(userId).then(function(user) { - loadUser(page, user) - }) + ApiClient.getUser(userId).then(function (user) { + loadUser(page, user); + }); } - $(document).on("pageinit", "#userPasswordPage", function() { - $(".adminUpdatePasswordForm").off("submit", UpdatePasswordPage.onSubmit).on("submit", UpdatePasswordPage.onSubmit), $(".adminLocalAccessForm").off("submit", UpdatePasswordPage.onLocalAccessSubmit).on("submit", UpdatePasswordPage.onLocalAccessSubmit) - }).on("pagebeforeshow", "#userPasswordPage", function() { - loadData(this) - }) -}); \ No newline at end of file + + $(document).on("pageinit", "#userPasswordPage", function () { + $(".adminUpdatePasswordForm").off("submit", UpdatePasswordPage.onSubmit).on("submit", UpdatePasswordPage.onSubmit); + $(".adminLocalAccessForm").off("submit", UpdatePasswordPage.onLocalAccessSubmit).on("submit", UpdatePasswordPage.onLocalAccessSubmit); + }).on("pagebeforeshow", "#userPasswordPage", function () { + loadData(this); + }); +}); From 307e66428609f5c116b975df03d4b93b21925ae6 Mon Sep 17 00:00:00 2001 From: grafixeyehero Date: Tue, 8 Oct 2019 01:30:21 +0300 Subject: [PATCH 017/162] wizardagreement.js --- src/scripts/wizardagreement.js | 36 ++++++++++++++++++++++------------ 1 file changed, 23 insertions(+), 13 deletions(-) diff --git a/src/scripts/wizardagreement.js b/src/scripts/wizardagreement.js index 77c12fb664..148b0ef39a 100644 --- a/src/scripts/wizardagreement.js +++ b/src/scripts/wizardagreement.js @@ -1,17 +1,27 @@ -define(["dom", "emby-button"], function(dom) { +define(["dom", "emby-button"], function (dom) { "use strict"; function onSubmit(e) { - return dom.parentWithClass(this, "page").querySelector(".chkAccept").checked ? Dashboard.navigate("wizardfinish.html") : Dashboard.alert({ - message: Globalize.translate("MessagePleaseAcceptTermsOfServiceBeforeContinuing"), - title: "" - }), e.preventDefault(), !1 + if (dom.parentWithClass(this, "page").querySelector(".chkAccept").checked) { + Dashboard.navigate("wizardfinish.html"); + } else { + Dashboard.alert({ + message: Globalize.translate("MessagePleaseAcceptTermsOfServiceBeforeContinuing"), + title: "" + }); + } + + e.preventDefault(); + return false; } - return function(view, params) { - view.querySelector(".wizardAgreementForm").addEventListener("submit", onSubmit), view.addEventListener("viewshow", function() { - document.querySelector(".skinHeader").classList.add("noHomeButtonHeader") - }), view.addEventListener("viewhide", function() { - document.querySelector(".skinHeader").classList.remove("noHomeButtonHeader") - }) - } -}); \ No newline at end of file + + return function (view, params) { + view.querySelector(".wizardAgreementForm").addEventListener("submit", onSubmit); + view.addEventListener("viewshow", function () { + document.querySelector(".skinHeader").classList.add("noHomeButtonHeader"); + }); + view.addEventListener("viewhide", function () { + document.querySelector(".skinHeader").classList.remove("noHomeButtonHeader"); + }); + }; +}); From e7570d856fd214d5805291fcc5498763bc1e08f9 Mon Sep 17 00:00:00 2001 From: grafixeyehero Date: Tue, 8 Oct 2019 19:54:02 +0300 Subject: [PATCH 018/162] Update Suggested change --- src/scripts/itembynamedetailpage.js | 32 ++++++------- src/scripts/librarybrowser.js | 7 ++- src/scripts/librarymenu.js | 6 ++- src/scripts/livetvcomponents.js | 15 ++++--- src/scripts/playlists.js | 70 ++++++++++++++++------------- src/scripts/taskbutton.js | 60 ++++++++++++++++--------- 6 files changed, 106 insertions(+), 84 deletions(-) diff --git a/src/scripts/itembynamedetailpage.js b/src/scripts/itembynamedetailpage.js index 1de421e6a3..74d69eecf8 100644 --- a/src/scripts/itembynamedetailpage.js +++ b/src/scripts/itembynamedetailpage.js @@ -312,27 +312,21 @@ define(["connectionManager", "listView", "cardBuilder", "imageLoader", "libraryB } function addCurrentItemToQuery(query, item) { - if ("Person" == item.Type) { + if (item.Type == "Person") { query.PersonIds = item.Id; - } else { - if ("Genre" == item.Type) { - query.GenreIds = item.Id; + } else if (item.Type == "Genre") { + query.Genres = item.Name; + } else if (item.Type == "MusicGenre") { + query.Genres = item.Name; + } else if (item.Type == "GameGenre") { + query.Genres = item.Name; + } else if (item.Type == "Studio") { + query.StudioIds = item.Id; + } else if (item.Type == "MusicArtist") { + if (connectionManager.getApiClient(item.ServerId).isMinServerVersion("3.4.1.18")) { + query.AlbumArtistIds = item.Id; } else { - if ("MusicGenre" == item.Type) { - query.GenreIds = item.Id; - } else { - if ("Studio" == item.Type) { - query.StudioIds = item.Id; - } else { - if ("MusicArtist" == item.Type) { - if (connectionManager.getApiClient(item.ServerId).isMinServerVersion("3.4.1.18")) { - query.AlbumArtistIds = item.Id; - } else { - query.ArtistIds = item.Id; - } - } - } - } + query.ArtistIds = item.Id; } } } diff --git a/src/scripts/librarybrowser.js b/src/scripts/librarybrowser.js index f2edc9030c..4f3eaf4144 100644 --- a/src/scripts/librarybrowser.js +++ b/src/scripts/librarybrowser.js @@ -156,11 +156,10 @@ define(["userSettings"], function (userSettings) { html += '

'; html += Globalize.translate("HeaderSortBy"); html += "

"; - var i; - var length; + var i, length; var isChecked; - - for (html += "
", i = 0, length = options.items.length; i < length; i++) { + html += '
'; + for (i = 0, length = options.items.length; i < length; i++) { var option = options.items[i]; var radioValue = option.id.replace(",", "_"); isChecked = (options.query.SortBy || "").replace(",", "_") == radioValue ? " checked" : ""; diff --git a/src/scripts/librarymenu.js b/src/scripts/librarymenu.js index 6b64041966..50031b33b8 100644 --- a/src/scripts/librarymenu.js +++ b/src/scripts/librarymenu.js @@ -206,8 +206,9 @@ define(["dom", "layoutManager", "inputManager", "connectionManager", "events", " html += 'exit_to_app' + globalize.translate("ButtonSignOut") + ""; html += "
"; - } // add buttons to navigation drawer + } + // add buttons to navigation drawer navDrawerScrollContainer.innerHTML = html; // bind logout button click to method @@ -501,8 +502,9 @@ define(["dom", "layoutManager", "inputManager", "connectionManager", "events", " showBySelector(".libraryMenuDownloads", false); showBySelector(".lnkSyncToOtherDevices", false); return void showBySelector(".userMenuOptions", false); - } // FIXME: Potentially the same as above + } + // FIXME: Potentially the same as above if (user.Policy.EnableContentDownloading) { showBySelector(".lnkSyncToOtherDevices", true); diff --git a/src/scripts/livetvcomponents.js b/src/scripts/livetvcomponents.js index a883885df1..cc0e94ca3f 100644 --- a/src/scripts/livetvcomponents.js +++ b/src/scripts/livetvcomponents.js @@ -6,11 +6,7 @@ define(["layoutManager", "datetime", "cardBuilder", "apphost"], function (layout } function getBackdropShape() { - if (enableScrollX()) { - return "overflowBackdrop"; - } - - return "backdrop"; + return enableScrollX() ? 'overflowBackdrop' : 'backdrop'; } function getTimersHtml(timers, options) { @@ -29,7 +25,7 @@ define(["layoutManager", "datetime", "cardBuilder", "apphost"], function (layout var item = items[i]; var dateText = ""; - if (false !== options.indexByDate && item.StartDate) { + if (options.indexByDate !== false && item.StartDate) { try { var premiereDate = datetime.parseISO8601Date(item.StartDate, true); dateText = datetime.toLocaleDateString(premiereDate, { @@ -69,7 +65,12 @@ define(["layoutManager", "datetime", "cardBuilder", "apphost"], function (layout var supportsImageAnalysis = appHost.supports("imageanalysis"); var cardLayout = appHost.preferVisualCards || supportsImageAnalysis; - if (cardLayout = true, group.name && (html += '
', html += '

' + group.name + "

"), enableScrollX()) { + cardLayout = true; + if (group.name) { + html += '
'; + html += '

' + group.name + "

"; + } + if (enableScrollX()) { var scrollXClass = "scrollX hiddenScrollX"; if (layoutManager.tv) { diff --git a/src/scripts/playlists.js b/src/scripts/playlists.js index 606a34c787..91c49017da 100644 --- a/src/scripts/playlists.js +++ b/src/scripts/playlists.js @@ -85,36 +85,46 @@ define(["loading", "listView", "cardBuilder", "libraryMenu", "libraryBrowser", " }); if (result.TotalRecordCount) { - html = "List" == viewStyle ? listView.getListViewHtml({ - items: result.Items, - sortBy: query.SortBy - }) : "PosterCard" == viewStyle ? cardBuilder.getCardsHtml({ - items: result.Items, - shape: "square", - coverImage: true, - showTitle: true, - cardLayout: true - }) : "Thumb" == viewStyle ? cardBuilder.getCardsHtml({ - items: result.Items, - shape: "backdrop", - showTitle: true, - centerText: true, - preferThumb: true, - overlayPlayButton: true - }) : "ThumbCard" == viewStyle ? cardBuilder.getCardsHtml({ - items: result.Items, - shape: "backdrop", - showTitle: true, - preferThumb: true, - cardLayout: true - }) : cardBuilder.getCardsHtml({ - items: result.Items, - shape: "square", - showTitle: true, - coverImage: true, - centerText: true, - overlayPlayButton: true - }); + if (viewStyle == "List") { + html = listView.getListViewHtml({ + items: result.Items, + sortBy: query.SortBy + }); + } else if (viewStyle == "PosterCard") { + html = cardBuilder.getCardsHtml({ + items: result.Items, + shape: "square", + coverImage: true, + showTitle: true, + cardLayout: true + }); + } else if (viewStyle == "Thumb") { + html = cardBuilder.getCardsHtml({ + items: result.Items, + shape: "backdrop", + showTitle: true, + centerText: true, + preferThumb: true, + overlayPlayButton: true + }); + } else if (viewStyle == "ThumbCard") { + html = cardBuilder.getCardsHtml({ + items: result.Items, + shape: "backdrop", + showTitle: true, + preferThumb: true, + cardLayout: true + }); + } else { + html = cardBuilder.getCardsHtml({ + items: result.Items, + shape: "square", + showTitle: true, + coverImage: true, + centerText: true, + overlayPlayButton: true + }); + } view.querySelector(".noItemsMessage").classList.add("hide"); } else { view.querySelector(".noItemsMessage").classList.remove("hide"); diff --git a/src/scripts/taskbutton.js b/src/scripts/taskbutton.js index 37e4a3c973..7e75e9423b 100644 --- a/src/scripts/taskbutton.js +++ b/src/scripts/taskbutton.js @@ -13,32 +13,48 @@ define(["events", "userSettings", "serverNotifications", "connectionManager", "e return t.Key == options.taskKey; })[0]; - if (options.panel && (task ? options.panel.classList.remove("hide") : options.panel.classList.add("hide")), task) { - if ("Idle" == task.State) { - button.removeAttribute("disabled"); + if (options.panel) { + if (task) { + options.panel.classList.remove('hide'); } else { - button.setAttribute("disabled", "disabled"); + options.panel.classList.add('hide'); } + } - button.setAttribute("data-taskid", task.Id); - var progress = (task.CurrentProgressPercentage || 0).toFixed(1); + if (!task) { + return; + } - if (options.progressElem && (options.progressElem.value = progress, "Running" == task.State ? options.progressElem.classList.remove("hide") : options.progressElem.classList.add("hide")), options.lastResultElem) { - var lastResult = task.LastExecutionResult ? task.LastExecutionResult.Status : ""; + if (task.State == 'Idle') { + button.removeAttribute("disabled"); + } else { + button.setAttribute("disabled", "disabled"); + } - if ("Failed" == lastResult) { - options.lastResultElem.html('(' + Globalize.translate("LabelFailed") + ")"); - } else { - if ("Cancelled" == lastResult) { - options.lastResultElem.html('(' + Globalize.translate("LabelCancelled") + ")"); - } else { - if ("Aborted" == lastResult) { - options.lastResultElem.html('' + Globalize.translate("LabelAbortedByServerShutdown") + ""); - } else { - options.lastResultElem.html(lastResult); - } - } - } + button.setAttribute("data-taskid", task.Id); + var progress = (task.CurrentProgressPercentage || 0).toFixed(1); + + if (options.progressElem) { + options.progressElem.value = progress; + + if (task.State == 'Running') { + options.progressElem.classList.remove('hide'); + } else { + options.progressElem.classList.add('hide'); + } + } + + if (options.lastResultElem) { + var lastResult = task.LastExecutionResult ? task.LastExecutionResult.Status : ''; + + if (lastResult == "Failed") { + options.lastResultElem.html('(' + Globalize.translate('LabelFailed') + ')'); + } else if (lastResult == "Cancelled") { + options.lastResultElem.html('(' + Globalize.translate('LabelCancelled') + ')'); + } else if (lastResult == "Aborted") { + options.lastResultElem.html('' + Globalize.translate('LabelAbortedByServerShutdown') + ''); + } else { + options.lastResultElem.html(lastResult); } } } @@ -71,7 +87,7 @@ define(["events", "userSettings", "serverNotifications", "connectionManager", "e options.panel.classList.add("hide"); } - if ("off" == options.mode) { + if (options.mode == 'off') { button.removeEventListener("click", onButtonClick); events.off(serverNotifications, "ScheduledTasksInfo", onScheduledTasksUpdate); From 0e306cad76021063affb75f65af606ec0f2ed7fb Mon Sep 17 00:00:00 2001 From: grafixeyehero Date: Tue, 8 Oct 2019 20:14:43 +0300 Subject: [PATCH 019/162] update taskbutton Suggested change --- src/scripts/taskbutton.js | 46 +++++++++++++++++++-------------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/src/scripts/taskbutton.js b/src/scripts/taskbutton.js index 7e75e9423b..f9774167c0 100644 --- a/src/scripts/taskbutton.js +++ b/src/scripts/taskbutton.js @@ -73,15 +73,33 @@ define(["events", "userSettings", "serverNotifications", "connectionManager", "e } } + var pollInterval; + var button = options.button; + var serverId = ApiClient.serverId(); + function onPollIntervalFired() { if (!connectionManager.getApiClient(serverId).isMessageChannelOpen()) { pollTasks(); } } - var pollInterval; - var button = options.button; - var serverId = ApiClient.serverId(); + function startInterval() { + var apiClient = connectionManager.getApiClient(serverId); + + if (pollInterval) { + clearInterval(pollInterval); + } + apiClient.sendMessage("ScheduledTasksInfoStart", "1000,1000"); + pollInterval = setInterval(onPollIntervalFired, 5000); + } + + function stopInterval() { + connectionManager.getApiClient(serverId).sendMessage("ScheduledTasksInfoStop"); + + if (pollInterval) { + clearInterval(pollInterval); + } + } if (options.panel) { options.panel.classList.add("hide"); @@ -90,29 +108,11 @@ define(["events", "userSettings", "serverNotifications", "connectionManager", "e if (options.mode == 'off') { button.removeEventListener("click", onButtonClick); events.off(serverNotifications, "ScheduledTasksInfo", onScheduledTasksUpdate); - - (function () { - connectionManager.getApiClient(serverId).sendMessage("ScheduledTasksInfoStop"); - - if (pollInterval) { - clearInterval(pollInterval); - } - })(); + stopInterval(); } else { button.addEventListener("click", onButtonClick); pollTasks(); - - (function () { - var apiClient = connectionManager.getApiClient(serverId); - - if (pollInterval) { - clearInterval(pollInterval); - } - - apiClient.sendMessage("ScheduledTasksInfoStart", "1000,1000"); - pollInterval = setInterval(onPollIntervalFired, 1e4); - })(); - + startInterval(); events.on(serverNotifications, "ScheduledTasksInfo", onScheduledTasksUpdate); } }; From 6eb8e1b8fa8fb2ab28647cb3f8fbde80c7c4fb74 Mon Sep 17 00:00:00 2001 From: grafixeyehero Date: Tue, 8 Oct 2019 20:46:05 +0300 Subject: [PATCH 020/162] add console.log --- src/scripts/librarymenu.js | 3 ++- src/scripts/livetvcomponents.js | 4 +++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/scripts/librarymenu.js b/src/scripts/librarymenu.js index 50031b33b8..ed6284b164 100644 --- a/src/scripts/librarymenu.js +++ b/src/scripts/librarymenu.js @@ -210,7 +210,8 @@ define(["dom", "layoutManager", "inputManager", "connectionManager", "events", " // add buttons to navigation drawer - navDrawerScrollContainer.innerHTML = html; // bind logout button click to method + navDrawerScrollContainer.innerHTML = html; + // bind logout button click to method var btnLogout = navDrawerScrollContainer.querySelector(".btnLogout"); diff --git a/src/scripts/livetvcomponents.js b/src/scripts/livetvcomponents.js index cc0e94ca3f..983b86a478 100644 --- a/src/scripts/livetvcomponents.js +++ b/src/scripts/livetvcomponents.js @@ -33,7 +33,9 @@ define(["layoutManager", "datetime", "cardBuilder", "apphost"], function (layout month: "short", day: "numeric" }); - } catch (err) {} + } catch (err) { + console.log("Error parsing premiereDate:" + item.StartDate); + } } if (dateText != currentGroupName) { From 61897f15e20160bd6c58498eaef10cfde2ce8e7c Mon Sep 17 00:00:00 2001 From: grafixeyehero Date: Tue, 8 Oct 2019 21:00:31 +0300 Subject: [PATCH 021/162] double quote --- src/scripts/livetvcomponents.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/scripts/livetvcomponents.js b/src/scripts/livetvcomponents.js index 983b86a478..fb8dadef78 100644 --- a/src/scripts/livetvcomponents.js +++ b/src/scripts/livetvcomponents.js @@ -6,7 +6,7 @@ define(["layoutManager", "datetime", "cardBuilder", "apphost"], function (layout } function getBackdropShape() { - return enableScrollX() ? 'overflowBackdrop' : 'backdrop'; + return enableScrollX() ? "overflowBackdrop" : "backdrop"; } function getTimersHtml(timers, options) { From 8496b3d1f5441e34938e197a0686862f69fc6934 Mon Sep 17 00:00:00 2001 From: redSpoutnik <15638041+redSpoutnik@users.noreply.github.com> Date: Tue, 8 Oct 2019 21:16:33 +0200 Subject: [PATCH 022/162] Fix subtitle sync for .vtt --- src/components/htmlvideoplayer/plugin.js | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/src/components/htmlvideoplayer/plugin.js b/src/components/htmlvideoplayer/plugin.js index 27e02349c0..95da82a26b 100644 --- a/src/components/htmlvideoplayer/plugin.js +++ b/src/components/htmlvideoplayer/plugin.js @@ -580,18 +580,15 @@ define(['browser', 'require', 'events', 'apphost', 'loading', 'dom', 'playbackMa Array.from(videoElement.textTracks) .filter(function(trackElement) { - if (customTrackIndex === -1 ) { - // get showing .vtt textTacks - return trackElement.mode === 'showing'; - } else { - // get current .ass textTrack - return ("textTrack" + customTrackIndex) === trackElement.id; - } + // get showing .vtt textTacks + return (trackElement.mode === 'showing') || + // get current .ass textTrack + (("textTrack" + customTrackIndex) === trackElement.id); }) .forEach(function(trackElement) { - var track = mediaStreamTextTracks.filter(function(stream) { - return ("textTrack" + stream.Index) === trackElement.id; + var track = customTrackIndex === -1 ? null : mediaStreamTextTracks.filter(function (t) { + return t.Index === customTrackIndex; })[0]; if(track) { From 7aa5d285108167bcef71438068e79e73cbfd54d6 Mon Sep 17 00:00:00 2001 From: redSpoutnik <15638041+redSpoutnik@users.noreply.github.com> Date: Tue, 8 Oct 2019 21:45:57 +0200 Subject: [PATCH 023/162] Test correct function in getPlayerSubtitleOffset --- src/components/playback/playbackmanager.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/playback/playbackmanager.js b/src/components/playback/playbackmanager.js index 04fb89b3d1..13497e1912 100644 --- a/src/components/playback/playbackmanager.js +++ b/src/components/playback/playbackmanager.js @@ -1667,7 +1667,7 @@ define(['events', 'datetime', 'appSettings', 'itemHelper', 'pluginManager', 'pla self.getPlayerSubtitleOffset = function(player) { player = player || self._currentPlayer; - if (player.getPlayerSubtitleOffset) { + if (player.getSubtitleOffset) { return player.getSubtitleOffset(); } } From 2e4591b9ae142249af2b1ed3f49c36897aae7cad Mon Sep 17 00:00:00 2001 From: grafixeyehero Date: Wed, 9 Oct 2019 18:49:41 +0300 Subject: [PATCH 024/162] accessschedule --- .../accessschedule/accessschedule.js | 96 +++++++++++++------ 1 file changed, 67 insertions(+), 29 deletions(-) diff --git a/src/components/accessschedule/accessschedule.js b/src/components/accessschedule/accessschedule.js index cce626ae78..4733522d56 100644 --- a/src/components/accessschedule/accessschedule.js +++ b/src/components/accessschedule/accessschedule.js @@ -1,19 +1,33 @@ -define(["dialogHelper", "datetime", "emby-select", "paper-icon-button-light", "formDialogStyle"], function(dialogHelper, datetime) { +define(["dialogHelper", "datetime", "emby-select", "paper-icon-button-light", "formDialogStyle"], function (dialogHelper, datetime) { "use strict"; function getDisplayTime(hours) { - var minutes = 0, - pct = hours % 1; - return pct && (minutes = parseInt(60 * pct)), datetime.getDisplayTime(new Date(2e3, 1, 1, hours, minutes, 0, 0)) + var minutes = 0; + var pct = hours % 1; + + if (pct) { + minutes = parseInt(60 * pct); + } + + return datetime.getDisplayTime(new Date(2e3, 1, 1, hours, minutes, 0, 0)); } function populateHours(context) { - for (var html = "", i = 0; i < 24; i++) html += '"; - html += '", context.querySelector("#selectStart").innerHTML = html, context.querySelector("#selectEnd").innerHTML = html + var html = ""; + + for (var i = 0; i < 24; i++) { + html += '"; + } + + html += '"; + context.querySelector("#selectStart").innerHTML = html; + context.querySelector("#selectEnd").innerHTML = html; } function loadSchedule(context, schedule) { - context.querySelector("#selectDay").value = schedule.DayOfWeek || "Sunday", context.querySelector("#selectStart").value = schedule.StartHour || 0, context.querySelector("#selectEnd").value = schedule.EndHour || 0 + context.querySelector("#selectDay").value = schedule.DayOfWeek || "Sunday"; + context.querySelector("#selectStart").value = schedule.StartHour || 0; + context.querySelector("#selectEnd").value = schedule.EndHour || 0; } function submitSchedule(context, options) { @@ -22,30 +36,54 @@ define(["dialogHelper", "datetime", "emby-select", "paper-icon-button-light", "f StartHour: context.querySelector("#selectStart").value, EndHour: context.querySelector("#selectEnd").value }; - if (parseFloat(updatedSchedule.StartHour) >= parseFloat(updatedSchedule.EndHour)) return void alert(Globalize.translate("ErrorMessageStartHourGreaterThanEnd")); - context.submitted = !0, options.schedule = Object.assign(options.schedule, updatedSchedule), dialogHelper.close(context) + + if (parseFloat(updatedSchedule.StartHour) >= parseFloat(updatedSchedule.EndHour)) { + return void alert(Globalize.translate("ErrorMessageStartHourGreaterThanEnd")); + } + + context.submitted = true; + options.schedule = Object.assign(options.schedule, updatedSchedule); + dialogHelper.close(context); } + return { - show: function(options) { - return new Promise(function(resolve, reject) { - var xhr = new XMLHttpRequest; - xhr.open("GET", "components/accessschedule/accessschedule.template.html", !0), xhr.onload = function(e) { - var template = this.response, - dlg = dialogHelper.createDialog({ - removeOnClose: !0, - size: "small" - }); + show: function (options) { + return new Promise(function (resolve, reject) { + var xhr = new XMLHttpRequest(); + xhr.open("GET", "components/accessschedule/accessschedule.template.html", true); + + xhr.onload = function (e) { + var template = this.response; + var dlg = dialogHelper.createDialog({ + removeOnClose: true, + size: "small" + }); dlg.classList.add("formDialog"); var html = ""; - html += Globalize.translateDocument(template), dlg.innerHTML = html, populateHours(dlg), loadSchedule(dlg, options.schedule), dialogHelper.open(dlg), dlg.addEventListener("close", function() { - dlg.submitted ? resolve(options.schedule) : reject() - }), dlg.querySelector(".btnCancel").addEventListener("click", function(e) { - dialogHelper.close(dlg) - }), dlg.querySelector("form").addEventListener("submit", function(e) { - return submitSchedule(dlg, options), e.preventDefault(), !1 - }) - }, xhr.send() - }) + html += Globalize.translateDocument(template); + dlg.innerHTML = html; + populateHours(dlg); + loadSchedule(dlg, options.schedule); + dialogHelper.open(dlg); + dlg.addEventListener("close", function () { + if (dlg.submitted) { + resolve(options.schedule); + } else { + reject(); + } + }); + dlg.querySelector(".btnCancel").addEventListener("click", function (e) { + dialogHelper.close(dlg); + }); + dlg.querySelector("form").addEventListener("submit", function (e) { + submitSchedule(dlg, options); + e.preventDefault(); + return false; + }); + }; + + xhr.send(); + }); } - } -}); \ No newline at end of file + }; +}); From c750ba55b4d05682f3a93d6ac2465c592ac735ae Mon Sep 17 00:00:00 2001 From: grafixeyehero Date: Wed, 9 Oct 2019 18:52:14 +0300 Subject: [PATCH 025/162] channelmapper --- src/components/channelmapper/channelmapper.js | 119 ++++++++++++------ 1 file changed, 83 insertions(+), 36 deletions(-) diff --git a/src/components/channelmapper/channelmapper.js b/src/components/channelmapper/channelmapper.js index 2abf7e2c9e..d1fdcb1985 100644 --- a/src/components/channelmapper/channelmapper.js +++ b/src/components/channelmapper/channelmapper.js @@ -1,10 +1,15 @@ -define(["dialogHelper", "loading", "connectionManager", "globalize", "actionsheet", "emby-input", "paper-icon-button-light", "emby-button", "listViewStyle", "material-icons", "formDialogStyle"], function(dialogHelper, loading, connectionManager, globalize, actionsheet) { +define(["dialogHelper", "loading", "connectionManager", "globalize", "actionsheet", "emby-input", "paper-icon-button-light", "emby-button", "listViewStyle", "material-icons", "formDialogStyle"], function (dialogHelper, loading, connectionManager, globalize, actionsheet) { "use strict"; - return function(options) { + + return function (options) { function parentWithClass(elem, className) { - for (; !elem.classList || !elem.classList.contains(className);) - if (!(elem = elem.parentNode)) return null; - return elem + for (; !elem.classList || !elem.classList.contains(className);) { + if (!(elem = elem.parentNode)) { + return null; + } + } + + return elem; } function mapChannel(button, channelId, providerChannelId) { @@ -19,33 +24,35 @@ define(["dialogHelper", "loading", "connectionManager", "globalize", "actionshee providerChannelId: providerChannelId }, dataType: "json" - }).then(function(mapping) { + }).then(function (mapping) { var listItem = parentWithClass(button, "listItem"); - button.setAttribute("data-providerid", mapping.ProviderChannelId), listItem.querySelector(".secondary").innerHTML = getMappingSecondaryName(mapping, currentMappingOptions.ProviderName), loading.hide() - }) + button.setAttribute("data-providerid", mapping.ProviderChannelId); + listItem.querySelector(".secondary").innerHTML = getMappingSecondaryName(mapping, currentMappingOptions.ProviderName); + loading.hide(); + }); } function onChannelsElementClick(e) { var btnMap = parentWithClass(e.target, "btnMap"); + if (btnMap) { var channelId = btnMap.getAttribute("data-id"); var providerChannelId = btnMap.getAttribute("data-providerid"); - var menuItems = currentMappingOptions.ProviderChannels.map(function(m) { + var menuItems = currentMappingOptions.ProviderChannels.map(function (m) { return { name: m.Name, id: m.Id, selected: m.Id.toLowerCase() === providerChannelId.toLowerCase() - } + }; }).sort(function (a, b) { return a.name.localeCompare(b.name); }); - actionsheet.show({ positionTo: btnMap, items: menuItems - }).then(function(newChannelId) { - mapChannel(btnMap, channelId, newChannelId) - }) + }).then(function (newChannelId) { + mapChannel(btnMap, channelId, newChannelId); + }); } } @@ -53,47 +60,87 @@ define(["dialogHelper", "loading", "connectionManager", "globalize", "actionshee var apiClient = connectionManager.getApiClient(serverId); return apiClient.getJSON(apiClient.getUrl("LiveTv/ChannelMappingOptions", { providerId: providerId - })) + })); } function getMappingSecondaryName(mapping, providerName) { - return (mapping.ProviderChannelName || "") + " - " + providerName + return (mapping.ProviderChannelName || "") + " - " + providerName; } function getTunerChannelHtml(channel, providerName) { var html = ""; - return html += '
', html += 'dvr', html += '
', html += '

', html += channel.Name, html += "

", html += '
', channel.ProviderChannelName && (html += getMappingSecondaryName(channel, providerName)), html += "
", html += "
", html += '', html += "
" + html += '
'; + html += 'dvr'; + html += '
'; + html += '

'; + html += channel.Name; + html += "

"; + html += '
'; + + if (channel.ProviderChannelName) { + html += getMappingSecondaryName(channel, providerName); + } + + html += "
"; + html += "
"; + html += ''; + return html += "
"; } function getEditorHtml() { var html = ""; - return html += '
', html += '
', html += '
', html += "

" + globalize.translate("HeaderChannels") + "

", html += '
', html += "
", html += "
", html += "
", html += "
" + html += '
'; + html += '
'; + html += '
'; + html += "

" + globalize.translate("HeaderChannels") + "

"; + html += '
'; + html += "
"; + html += "
"; + html += "
"; + return html += "
"; } function initEditor(dlg, options) { - getChannelMappingOptions(options.serverId, options.providerId).then(function(result) { + getChannelMappingOptions(options.serverId, options.providerId).then(function (result) { currentMappingOptions = result; var channelsElement = dlg.querySelector(".channels"); - channelsElement.innerHTML = result.TunerChannels.map(function(channel) { - return getTunerChannelHtml(channel, result.ProviderName) - }).join(""), channelsElement.addEventListener("click", onChannelsElementClick) - }) + channelsElement.innerHTML = result.TunerChannels.map(function (channel) { + return getTunerChannelHtml(channel, result.ProviderName); + }).join(""); + channelsElement.addEventListener("click", onChannelsElementClick); + }); } - var currentMappingOptions, self = this; - self.show = function() { + + var currentMappingOptions; + var self = this; + + self.show = function () { var dialogOptions = { - removeOnClose: !0 + removeOnClose: true }; dialogOptions.size = "small"; var dlg = dialogHelper.createDialog(dialogOptions); - dlg.classList.add("formDialog"), dlg.classList.add("ui-body-a"), dlg.classList.add("background-theme-a"); - var html = "", - title = globalize.translate("MapChannels"); - return html += '
', html += '', html += '

', html += title, html += "

", html += "
", html += getEditorHtml(), dlg.innerHTML = html, initEditor(dlg, options), dlg.querySelector(".btnCancel").addEventListener("click", function() { - dialogHelper.close(dlg) - }), new Promise(function(resolve, reject) { - dlg.addEventListener("close", resolve), dialogHelper.open(dlg) - }) - } - } + dlg.classList.add("formDialog"); + dlg.classList.add("ui-body-a"); + dlg.classList.add("background-theme-a"); + var html = ""; + var title = globalize.translate("MapChannels"); + html += '
'; + html += ''; + html += '

'; + html += title; + html += "

"; + html += "
"; + html += getEditorHtml(); + dlg.innerHTML = html; + initEditor(dlg, options); + dlg.querySelector(".btnCancel").addEventListener("click", function () { + dialogHelper.close(dlg); + }); + return new Promise(function (resolve, reject) { + dlg.addEventListener("close", resolve); + dialogHelper.open(dlg); + }); + }; + }; }); From 0f268a4413afe9ccf39a0f3fbba34087312227eb Mon Sep 17 00:00:00 2001 From: grafixeyehero Date: Wed, 9 Oct 2019 18:59:17 +0300 Subject: [PATCH 026/162] imageoptionseditor --- .../imageoptionseditor/imageoptionseditor.js | 109 ++++++++++++------ 1 file changed, 72 insertions(+), 37 deletions(-) diff --git a/src/components/imageoptionseditor/imageoptionseditor.js b/src/components/imageoptionseditor/imageoptionseditor.js index 94d37d6f7f..c9dc678099 100644 --- a/src/components/imageoptionseditor/imageoptionseditor.js +++ b/src/components/imageoptionseditor/imageoptionseditor.js @@ -1,4 +1,4 @@ -define(["globalize", "dom", "dialogHelper", "emby-checkbox", "emby-select", "emby-input"], function(globalize, dom, dialogHelper) { +define(["globalize", "dom", "dialogHelper", "emby-checkbox", "emby-select", "emby-input"], function (globalize, dom, dialogHelper) { "use strict"; function getDefaultImageConfig(itemType, type) { @@ -6,72 +6,107 @@ define(["globalize", "dom", "dialogHelper", "emby-checkbox", "emby-select", "emb Type: type, MinWidth: 0, Limit: "Primary" === type ? 1 : 0 - } + }; } function findImageOptions(imageOptions, type) { - return imageOptions.filter(function(i) { - return i.Type == type - })[0] + return imageOptions.filter(function (i) { + return i.Type == type; + })[0]; } function getImageConfig(options, availableOptions, imageType, itemType) { - return findImageOptions(options.ImageOptions || [], imageType) || findImageOptions(availableOptions.DefaultImageOptions || [], imageType) || getDefaultImageConfig(itemType, imageType) + return findImageOptions(options.ImageOptions || [], imageType) || findImageOptions(availableOptions.DefaultImageOptions || [], imageType) || getDefaultImageConfig(itemType, imageType); } function setVisibilityOfBackdrops(elem, visible) { - visible ? (elem.classList.remove("hide"), elem.querySelector("input").setAttribute("required", "required")) : (elem.classList.add("hide"), elem.querySelector("input").setAttribute("required", ""), elem.querySelector("input").removeAttribute("required")) + if (visible) { + elem.classList.remove("hide"); + elem.querySelector("input").setAttribute("required", "required"); + } else { + elem.classList.add("hide"); + elem.querySelector("input").setAttribute("required", ""); + elem.querySelector("input").removeAttribute("required"); + } } function loadValues(context, itemType, options, availableOptions) { var supportedImageTypes = availableOptions.SupportedImageTypes || []; - setVisibilityOfBackdrops(context.querySelector(".backdropFields"), -1 != supportedImageTypes.indexOf("Backdrop")), setVisibilityOfBackdrops(context.querySelector(".screenshotFields"), -1 != supportedImageTypes.indexOf("Screenshot")), Array.prototype.forEach.call(context.querySelectorAll(".imageType"), function(i) { - var imageType = i.getAttribute("data-imagetype"), - container = dom.parentWithTag(i, "LABEL"); - 1 == supportedImageTypes.indexOf(imageType) ? container.classList.add("hide") : container.classList.remove("hide"), getImageConfig(options, availableOptions, imageType, itemType).Limit ? i.checked = !0 : i.checked = !1 + setVisibilityOfBackdrops(context.querySelector(".backdropFields"), -1 != supportedImageTypes.indexOf("Backdrop")); + setVisibilityOfBackdrops(context.querySelector(".screenshotFields"), -1 != supportedImageTypes.indexOf("Screenshot")); + Array.prototype.forEach.call(context.querySelectorAll(".imageType"), function (i) { + var imageType = i.getAttribute("data-imagetype"); + var container = dom.parentWithTag(i, "LABEL"); + + if (-1 == supportedImageTypes.indexOf(imageType)) { + container.classList.add("hide"); + } else { + container.classList.remove("hide"); + } + + if (getImageConfig(options, availableOptions, imageType, itemType).Limit) { + i.checked = true; + } else { + i.checked = false; + } }); var backdropConfig = getImageConfig(options, availableOptions, "Backdrop", itemType); - context.querySelector("#txtMaxBackdrops").value = backdropConfig.Limit, context.querySelector("#txtMinBackdropDownloadWidth").value = backdropConfig.MinWidth; + context.querySelector("#txtMaxBackdrops").value = backdropConfig.Limit; + context.querySelector("#txtMinBackdropDownloadWidth").value = backdropConfig.MinWidth; var screenshotConfig = getImageConfig(options, availableOptions, "Screenshot", itemType); - context.querySelector("#txtMaxScreenshots").value = screenshotConfig.Limit, context.querySelector("#txtMinScreenshotDownloadWidth").value = screenshotConfig.MinWidth + context.querySelector("#txtMaxScreenshots").value = screenshotConfig.Limit; + context.querySelector("#txtMinScreenshotDownloadWidth").value = screenshotConfig.MinWidth; } function saveValues(context, options) { - options.ImageOptions = Array.prototype.map.call(context.querySelectorAll(".imageType:not(.hide)"), function(c) { + options.ImageOptions = Array.prototype.map.call(context.querySelectorAll(".imageType:not(.hide)"), function (c) { return { Type: c.getAttribute("data-imagetype"), Limit: c.checked ? 1 : 0, MinWidth: 0 - } - }), options.ImageOptions.push({ + }; + }); + options.ImageOptions.push({ Type: "Backdrop", Limit: context.querySelector("#txtMaxBackdrops").value, MinWidth: context.querySelector("#txtMinBackdropDownloadWidth").value - }), options.ImageOptions.push({ + }); + options.ImageOptions.push({ Type: "Screenshot", Limit: context.querySelector("#txtMaxScreenshots").value, MinWidth: context.querySelector("#txtMinScreenshotDownloadWidth").value - }) + }); } function editor() { - this.show = function(itemType, options, availableOptions) { - return new Promise(function(resolve, reject) { - var xhr = new XMLHttpRequest; - xhr.open("GET", "components/imageoptionseditor/imageoptionseditor.template.html", !0), xhr.onload = function(e) { - var template = this.response, - dlg = dialogHelper.createDialog({ - size: "medium-tall", - removeOnClose: !0, - scrollY: !1 - }); - dlg.classList.add("formDialog"), dlg.innerHTML = globalize.translateDocument(template), dlg.addEventListener("close", function() { - saveValues(dlg, options) - }), loadValues(dlg, itemType, options, availableOptions), dialogHelper.open(dlg).then(resolve, resolve), dlg.querySelector(".btnCancel").addEventListener("click", function() { - dialogHelper.close(dlg) - }) - }, xhr.send() - }) - } + this.show = function (itemType, options, availableOptions) { + return new Promise(function (resolve, reject) { + var xhr = new XMLHttpRequest(); + xhr.open("GET", "components/imageoptionseditor/imageoptionseditor.template.html", true); + + xhr.onload = function (e) { + var template = this.response; + var dlg = dialogHelper.createDialog({ + size: "medium-tall", + removeOnClose: true, + scrollY: false + }); + dlg.classList.add("formDialog"); + dlg.innerHTML = globalize.translateDocument(template); + dlg.addEventListener("close", function () { + saveValues(dlg, options); + }); + loadValues(dlg, itemType, options, availableOptions); + dialogHelper.open(dlg).then(resolve, resolve); + dlg.querySelector(".btnCancel").addEventListener("click", function () { + dialogHelper.close(dlg); + }); + }; + + xhr.send(); + }); + }; } - return editor -}); \ No newline at end of file + + return editor; +}); From 3957592f3104b1e6ad6d0670b3f4bbea48d4d698 Mon Sep 17 00:00:00 2001 From: grafixeyehero Date: Wed, 9 Oct 2019 19:13:07 +0300 Subject: [PATCH 027/162] schedulesdirect --- src/components/tvproviders/schedulesdirect.js | 327 ++++++++++++------ 1 file changed, 228 insertions(+), 99 deletions(-) diff --git a/src/components/tvproviders/schedulesdirect.js b/src/components/tvproviders/schedulesdirect.js index 9af7e5be72..b42744e76d 100644 --- a/src/components/tvproviders/schedulesdirect.js +++ b/src/components/tvproviders/schedulesdirect.js @@ -1,119 +1,195 @@ -define(["jQuery", "loading", "emby-checkbox", "listViewStyle", "emby-input", "emby-select", "emby-button", "flexStyles"], function($, loading) { +define(["jQuery", "loading", "emby-checkbox", "listViewStyle", "emby-input", "emby-select", "emby-button", "flexStyles"], function ($, loading) { "use strict"; - return function(page, providerId, options) { + + return function (page, providerId, options) { function reload() { - loading.show(), ApiClient.getNamedConfiguration("livetv").then(function(config) { - var info = config.ListingProviders.filter(function(i) { - return i.Id === providerId + loading.show(); + ApiClient.getNamedConfiguration("livetv").then(function (config) { + var info = config.ListingProviders.filter(function (i) { + return i.Id === providerId; })[0] || {}; - listingsId = info.ListingsId, $("#selectListing", page).val(info.ListingsId || ""), page.querySelector(".txtUser").value = info.Username || "", page.querySelector(".txtPass").value = "", page.querySelector(".txtZipCode").value = info.ZipCode || "", info.Username && info.Password ? page.querySelector(".listingsSection").classList.remove("hide") : page.querySelector(".listingsSection").classList.add("hide"), page.querySelector(".chkAllTuners").checked = info.EnableAllTuners, page.querySelector(".chkAllTuners").checked ? page.querySelector(".selectTunersSection").classList.add("hide") : page.querySelector(".selectTunersSection").classList.remove("hide"), setCountry(info), refreshTunerDevices(page, info, config.TunerHosts) - }) + listingsId = info.ListingsId; + $("#selectListing", page).val(info.ListingsId || ""); + page.querySelector(".txtUser").value = info.Username || ""; + page.querySelector(".txtPass").value = ""; + page.querySelector(".txtZipCode").value = info.ZipCode || ""; + + if (info.Username && info.Password) { + page.querySelector(".listingsSection").classList.remove("hide"); + } else { + page.querySelector(".listingsSection").classList.add("hide"); + } + + page.querySelector(".chkAllTuners").checked = info.EnableAllTuners; + + if (page.querySelector(".chkAllTuners").checked) { + page.querySelector(".selectTunersSection").classList.add("hide"); + } else { + page.querySelector(".selectTunersSection").classList.remove("hide"); + } + + setCountry(info); + refreshTunerDevices(page, info, config.TunerHosts); + }); } function setCountry(info) { - ApiClient.getJSON(ApiClient.getUrl("LiveTv/ListingProviders/SchedulesDirect/Countries")).then(function(result) { - var i, length, countryList = []; + ApiClient.getJSON(ApiClient.getUrl("LiveTv/ListingProviders/SchedulesDirect/Countries")).then(function (result) { + var i; + var length; + var countryList = []; + for (var region in result) { var countries = result[region]; - if (countries.length && "ZZZ" !== region) - for (i = 0, length = countries.length; i < length; i++) countryList.push({ - name: countries[i].fullName, - value: countries[i].shortName - }) + + if (countries.length && "ZZZ" !== region) { + for (i = 0, length = countries.length; i < length; i++) { + countryList.push({ + name: countries[i].fullName, + value: countries[i].shortName + }); + } + } } - countryList.sort(function(a, b) { - return a.name > b.name ? 1 : a.name < b.name ? -1 : 0 - }), $("#selectCountry", page).html(countryList.map(function(c) { - return '" - }).join("")).val(info.Country || ""), $(page.querySelector(".txtZipCode")).trigger("change") - }, function() { + + countryList.sort(function (a, b) { + if (a.name > b.name) { + return 1; + } + + if (a.name < b.name) { + return -1; + } + + return 0; + }); + $("#selectCountry", page).html(countryList.map(function (c) { + return '"; + }).join("")).val(info.Country || ""); + $(page.querySelector(".txtZipCode")).trigger("change"); + }, function () { Dashboard.alert({ message: Globalize.translate("ErrorGettingTvLineups") - }) - }), loading.hide() + }); + }); + loading.hide(); } function sha256(str) { - if (!self.TextEncoder) return Promise.resolve(""); + if (!self.TextEncoder) { + return Promise.resolve(""); + } + var buffer = new TextEncoder("utf-8").encode(str); - return crypto.subtle.digest("SHA-256", buffer).then(function(hash) { - return hex(hash) - }) + return crypto.subtle.digest("SHA-256", buffer).then(function (hash) { + return hex(hash); + }); } function hex(buffer) { - for (var hexCodes = [], view = new DataView(buffer), i = 0; i < view.byteLength; i += 4) { - var value = view.getUint32(i), - stringValue = value.toString(16), - paddedValue = ("00000000" + stringValue).slice(-"00000000".length); - hexCodes.push(paddedValue) + var hexCodes = []; + + for (var view = new DataView(buffer), i = 0; i < view.byteLength; i += 4) { + var value = view.getUint32(i); + var stringValue = value.toString(16); + var paddedValue = ("00000000" + stringValue).slice(-"00000000".length); + hexCodes.push(paddedValue); } - return hexCodes.join("") + + return hexCodes.join(""); } function submitLoginForm() { - loading.show(), sha256(page.querySelector(".txtPass").value).then(function(passwordHash) { + loading.show(); + sha256(page.querySelector(".txtPass").value).then(function (passwordHash) { var info = { - Type: "SchedulesDirect", - Username: page.querySelector(".txtUser").value, - EnableAllTuners: !0, - Password: passwordHash, - Pw: page.querySelector(".txtPass").value - }, - id = providerId; - id && (info.Id = id), ApiClient.ajax({ + Type: "SchedulesDirect", + Username: page.querySelector(".txtUser").value, + EnableAllTuners: true, + Password: passwordHash, + Pw: page.querySelector(".txtPass").value + }; + var id = providerId; + + if (id) { + info.Id = id; + } + + ApiClient.ajax({ type: "POST", url: ApiClient.getUrl("LiveTv/ListingProviders", { - ValidateLogin: !0 + ValidateLogin: true }), data: JSON.stringify(info), contentType: "application/json", dataType: "json" - }).then(function(result) { - Dashboard.processServerConfigurationUpdateResult(), providerId = result.Id, reload() - }, function() { + }).then(function (result) { + Dashboard.processServerConfigurationUpdateResult(); + providerId = result.Id; + reload(); + }, function () { Dashboard.alert({ message: Globalize.translate("ErrorSavingTvProvider") - }) - }) - }) + }); + }); + }); } function submitListingsForm() { var selectedListingsId = $("#selectListing", page).val(); - if (!selectedListingsId) return void Dashboard.alert({ - message: Globalize.translate("ErrorPleaseSelectLineup") - }); + + if (!selectedListingsId) { + return void Dashboard.alert({ + message: Globalize.translate("ErrorPleaseSelectLineup") + }); + } + loading.show(); var id = providerId; - ApiClient.getNamedConfiguration("livetv").then(function(config) { - var info = config.ListingProviders.filter(function(i) { - return i.Id === id + ApiClient.getNamedConfiguration("livetv").then(function (config) { + var info = config.ListingProviders.filter(function (i) { + return i.Id === id; })[0]; - info.ZipCode = page.querySelector(".txtZipCode").value, info.Country = $("#selectCountry", page).val(), info.ListingsId = selectedListingsId, info.EnableAllTuners = page.querySelector(".chkAllTuners").checked, info.EnabledTuners = info.EnableAllTuners ? [] : $(".chkTuner", page).get().filter(function(i) { - return i.checked - }).map(function(i) { - return i.getAttribute("data-id") - }), ApiClient.ajax({ + info.ZipCode = page.querySelector(".txtZipCode").value; + info.Country = $("#selectCountry", page).val(); + info.ListingsId = selectedListingsId; + info.EnableAllTuners = page.querySelector(".chkAllTuners").checked; + info.EnabledTuners = info.EnableAllTuners ? [] : $(".chkTuner", page).get().filter(function (i) { + return i.checked; + }).map(function (i) { + return i.getAttribute("data-id"); + }); + ApiClient.ajax({ type: "POST", url: ApiClient.getUrl("LiveTv/ListingProviders", { - ValidateListings: !0 + ValidateListings: true }), data: JSON.stringify(info), contentType: "application/json" - }).then(function(result) { - loading.hide(), !1 !== options.showConfirmation && Dashboard.processServerConfigurationUpdateResult(), Events.trigger(self, "submitted") - }, function() { - loading.hide(), Dashboard.alert({ + }).then(function (result) { + loading.hide(); + + if (false !== options.showConfirmation) { + Dashboard.processServerConfigurationUpdateResult(); + } + + Events.trigger(self, "submitted"); + }, function () { + loading.hide(); + Dashboard.alert({ message: Globalize.translate("ErrorAddingListingsToSchedulesDirect") - }) - }) - }) + }); + }); + }); } function refreshListings(value) { - if (!value) return void $("#selectListing", page).html(""); - loading.show(), ApiClient.ajax({ + if (!value) { + return void $("#selectListing", page).html(""); + } + + loading.show(); + ApiClient.ajax({ type: "GET", url: ApiClient.getUrl("LiveTv/ListingProviders/Lineups", { Id: providerId, @@ -121,54 +197,107 @@ define(["jQuery", "loading", "emby-checkbox", "listViewStyle", "emby-input", "em Country: $("#selectCountry", page).val() }), dataType: "json" - }).then(function(result) { - $("#selectListing", page).html(result.map(function(o) { - return '" - })), listingsId && $("#selectListing", page).val(listingsId), loading.hide() - }, function(result) { + }).then(function (result) { + $("#selectListing", page).html(result.map(function (o) { + return '"; + })); + + if (listingsId) { + $("#selectListing", page).val(listingsId); + } + + loading.hide(); + }, function (result) { Dashboard.alert({ message: Globalize.translate("ErrorGettingTvLineups") - }), refreshListings(""), loading.hide() - }) + }); + refreshListings(""); + loading.hide(); + }); } function getTunerName(providerId) { switch (providerId = providerId.toLowerCase()) { case "m3u": return "M3U Playlist"; + case "hdhomerun": return "HDHomerun"; + case "satip": return "DVB"; + default: - return "Unknown" + return "Unknown"; } } function refreshTunerDevices(page, providerInfo, devices) { - for (var html = "", i = 0, length = devices.length; i < length; i++) { + var html = ""; + + for (var i = 0, length = devices.length; i < length; i++) { var device = devices[i]; html += '
'; - var enabledTuners = providerInfo.EnabledTuners || [], - isChecked = providerInfo.EnableAllTuners || -1 !== enabledTuners.indexOf(device.Id), - checkedAttribute = isChecked ? " checked" : ""; - html += '", html += '
', html += '
', html += device.FriendlyName || getTunerName(device.Type), html += "
", html += '
', html += device.Url, html += "
", html += "
", html += "
" + var enabledTuners = providerInfo.EnabledTuners || []; + var isChecked = providerInfo.EnableAllTuners || -1 !== enabledTuners.indexOf(device.Id); + var checkedAttribute = isChecked ? " checked" : ""; + html += '"; + html += '
'; + html += '
'; + html += device.FriendlyName || getTunerName(device.Type); + html += "
"; + html += '
'; + html += device.Url; + html += "
"; + html += "
"; + html += "
"; } - page.querySelector(".tunerList").innerHTML = html + + page.querySelector(".tunerList").innerHTML = html; } - var listingsId, self = this; - self.submit = function() { - page.querySelector(".btnSubmitListingsContainer").click() - }, self.init = function() { - options = options || {}, !1 !== options.showCancelButton ? page.querySelector(".btnCancel").classList.remove("hide") : page.querySelector(".btnCancel").classList.add("hide"), !1 !== options.showSubmitButton ? page.querySelector(".btnSubmitListings").classList.remove("hide") : page.querySelector(".btnSubmitListings").classList.add("hide"), $(".formLogin", page).on("submit", function() { - return submitLoginForm(), !1 - }), $(".formListings", page).on("submit", function() { - return submitListingsForm(), !1 - }), $(".txtZipCode", page).on("change", function() { - refreshListings(this.value) - }), page.querySelector(".chkAllTuners").addEventListener("change", function(e) { - e.target.checked ? page.querySelector(".selectTunersSection").classList.add("hide") : page.querySelector(".selectTunersSection").classList.remove("hide") - }), $(".createAccountHelp", page).html(Globalize.translate("MessageCreateAccountAt", 'http://www.schedulesdirect.org')), reload() - } - } -}); \ No newline at end of file + + var listingsId; + var self = this; + + self.submit = function () { + page.querySelector(".btnSubmitListingsContainer").click(); + }; + + self.init = function () { + options = options || {}; + + if (false !== options.showCancelButton) { + page.querySelector(".btnCancel").classList.remove("hide"); + } else { + page.querySelector(".btnCancel").classList.add("hide"); + } + + if (false !== options.showSubmitButton) { + page.querySelector(".btnSubmitListings").classList.remove("hide"); + } else { + page.querySelector(".btnSubmitListings").classList.add("hide"); + } + + $(".formLogin", page).on("submit", function () { + submitLoginForm(); + return false; + }); + $(".formListings", page).on("submit", function () { + submitListingsForm(); + return false; + }); + $(".txtZipCode", page).on("change", function () { + refreshListings(this.value); + }); + page.querySelector(".chkAllTuners").addEventListener("change", function (e) { + if (e.target.checked) { + page.querySelector(".selectTunersSection").classList.add("hide"); + } else { + page.querySelector(".selectTunersSection").classList.remove("hide"); + } + }); + $(".createAccountHelp", page).html(Globalize.translate("MessageCreateAccountAt", 'http://www.schedulesdirect.org')); + reload(); + }; + }; +}); From f86d2d47ac02f024f88dc20f8d2847bd977df2e7 Mon Sep 17 00:00:00 2001 From: grafixeyehero Date: Wed, 9 Oct 2019 19:15:06 +0300 Subject: [PATCH 028/162] xmltv --- src/components/tvproviders/xmltv.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/components/tvproviders/xmltv.js b/src/components/tvproviders/xmltv.js index 2a9dd88089..a86a1e1099 100644 --- a/src/components/tvproviders/xmltv.js +++ b/src/components/tvproviders/xmltv.js @@ -1,4 +1,4 @@ -define(["jQuery", "loading", "emby-checkbox", "emby-input", "listViewStyle", "paper-icon-button-light"], function ($__q, loading) { +define(["jQuery", "loading", "emby-checkbox", "emby-input", "listViewStyle", "paper-icon-button-light"], function ($, loading) { "use strict"; return function (page, providerId, options) { @@ -69,7 +69,7 @@ define(["jQuery", "loading", "emby-checkbox", "emby-input", "listViewStyle", "pa info.NewsCategories = getCategories(page.querySelector(".txtNews")); info.SportsCategories = getCategories(page.querySelector(".txtSports")); info.EnableAllTuners = page.querySelector(".chkAllTuners").checked; - info.EnabledTuners = info.EnableAllTuners ? [] : $__q(".chkTuner", page).get().filter(function (tuner) { + info.EnabledTuners = info.EnableAllTuners ? [] : $(".chkTuner", page).get().filter(function (tuner) { return tuner.checked; }).map(function (tuner) { return tuner.getAttribute("data-id"); @@ -135,8 +135,8 @@ define(["jQuery", "loading", "emby-checkbox", "emby-input", "listViewStyle", "pa page.querySelector(".tunerList").innerHTML = html; } - function onSelectPathClick(e__u) { - var page = $__q(e__u.target).parents(".xmltvForm")[0]; + function onSelectPathClick(e) { + var page = $(e.target).parents(".xmltvForm")[0]; require(["directorybrowser"], function (directoryBrowser) { var picker = new directoryBrowser(); @@ -175,7 +175,7 @@ define(["jQuery", "loading", "emby-checkbox", "emby-input", "listViewStyle", "pa page.querySelector(".btnSubmitListings").classList.add("hide"); } - $__q("form", page).on("submit", function () { + $("form", page).on("submit", function () { submitListingsForm(); return false; }); From cae2898da28537af44fd7a8043660dc42a889393 Mon Sep 17 00:00:00 2001 From: grafixeyehero Date: Wed, 9 Oct 2019 19:19:20 +0300 Subject: [PATCH 029/162] activitylog --- src/components/activitylog.js | 124 +++++++++++++++++++++++++--------- 1 file changed, 92 insertions(+), 32 deletions(-) diff --git a/src/components/activitylog.js b/src/components/activitylog.js index a6206477e7..6d13beb6b4 100644 --- a/src/components/activitylog.js +++ b/src/components/activitylog.js @@ -1,96 +1,156 @@ -define(["events", "globalize", "dom", "datetime", "userSettings", "serverNotifications", "connectionManager", "emby-button", "listViewStyle"], function(events, globalize, dom, datetime, userSettings, serverNotifications, connectionManager) { +define(["events", "globalize", "dom", "datetime", "userSettings", "serverNotifications", "connectionManager", "emby-button", "listViewStyle"], function (events, globalize, dom, datetime, userSettings, serverNotifications, connectionManager) { "use strict"; function getEntryHtml(entry, apiClient) { var html = ""; html += '
'; var color = "#00a4dc"; - var icon = "notifications"; + var icon = "notifications"; + if ("Error" == entry.Severity || "Fatal" == entry.Severity || "Warn" == entry.Severity) { color = "#cc0000"; icon = "notification_important"; } + if (entry.UserId && entry.UserPrimaryImageTag) { html += 'dvr" + }) + "');background-repeat:no-repeat;background-position:center center;background-size: cover;\">dvr"; } else { html += '' + icon + ''; } - html += '
', html += '
', html += entry.Name, html += "
", html += '
'; - var date = datetime.parseISO8601Date(entry.Date, !0); - return html += datetime.toLocaleString(date).toLowerCase(), html += "
", html += '
', html += entry.ShortOverview || "", html += "
", html += "
", entry.Overview && (html += ''), html += "
" + + html += '
'; + html += '
'; + html += entry.Name; + html += "
"; + html += '
'; + var date = datetime.parseISO8601Date(entry.Date, true); + html += datetime.toLocaleString(date).toLowerCase(); + html += "
"; + html += '
'; + html += entry.ShortOverview || ""; + html += "
"; + html += "
"; + + if (entry.Overview) { + html += ''; + } + + return html += "
"; } function renderList(elem, apiClient, result, startIndex, limit) { - elem.innerHTML = result.Items.map(function(i) { - return getEntryHtml(i, apiClient) - }).join("") + elem.innerHTML = result.Items.map(function (i) { + return getEntryHtml(i, apiClient); + }).join(""); } function reloadData(instance, elem, apiClient, startIndex, limit) { - null == startIndex && (startIndex = parseInt(elem.getAttribute("data-activitystartindex") || "0")), limit = limit || parseInt(elem.getAttribute("data-activitylimit") || "7"); - var minDate = new Date, - hasUserId = "false" !== elem.getAttribute("data-useractivity"); - hasUserId ? minDate.setTime(minDate.getTime() - 864e5) : minDate.setTime(minDate.getTime() - 6048e5), ApiClient.getJSON(ApiClient.getUrl("System/ActivityLog/Entries", { + if (null == startIndex) { + startIndex = parseInt(elem.getAttribute("data-activitystartindex") || "0"); + } + + limit = limit || parseInt(elem.getAttribute("data-activitylimit") || "7"); + var minDate = new Date(); + var hasUserId = "false" !== elem.getAttribute("data-useractivity"); + + if (hasUserId) { + minDate.setTime(minDate.getTime() - 864e5); + } else { + minDate.setTime(minDate.getTime() - 6048e5); + } + + ApiClient.getJSON(ApiClient.getUrl("System/ActivityLog/Entries", { startIndex: startIndex, limit: limit, minDate: minDate.toISOString(), hasUserId: hasUserId - })).then(function(result) { + })).then(function (result) { if (elem.setAttribute("data-activitystartindex", startIndex), elem.setAttribute("data-activitylimit", limit), !startIndex) { var activityContainer = dom.parentWithClass(elem, "activityContainer"); - activityContainer && (result.Items.length ? activityContainer.classList.remove("hide") : activityContainer.classList.add("hide")) + + if (activityContainer) { + if (result.Items.length) { + activityContainer.classList.remove("hide"); + } else { + activityContainer.classList.add("hide"); + } + } } - instance.items = result.Items, renderList(elem, apiClient, result, startIndex, limit) - }) + + instance.items = result.Items; + renderList(elem, apiClient, result, startIndex, limit); + }); } function onActivityLogUpdate(e, apiClient, data) { var options = this.options; - options && options.serverId === apiClient.serverId() && reloadData(this, options.element, apiClient) + + if (options && options.serverId === apiClient.serverId()) { + reloadData(this, options.element, apiClient); + } } function onListClick(e) { var btnEntryInfo = dom.parentWithClass(e.target, "btnEntryInfo"); + if (btnEntryInfo) { - var id = btnEntryInfo.getAttribute("data-id"), - items = this.items; + var id = btnEntryInfo.getAttribute("data-id"); + var items = this.items; + if (items) { - var item = items.filter(function(i) { - return i.Id.toString() === id + var item = items.filter(function (i) { + return i.Id.toString() === id; })[0]; - item && showItemOverview(item) + + if (item) { + showItemOverview(item); + } } } } function showItemOverview(item) { - require(["alert"], function(alert) { + require(["alert"], function (alert) { alert({ text: item.Overview - }) - }) + }); + }); } function ActivityLog(options) { this.options = options; var element = options.element; - element.classList.add("activityLogListWidget"), element.addEventListener("click", onListClick.bind(this)); + element.classList.add("activityLogListWidget"); + element.addEventListener("click", onListClick.bind(this)); var apiClient = connectionManager.getApiClient(options.serverId); reloadData(this, element, apiClient); var onUpdate = onActivityLogUpdate.bind(this); - this.updateFn = onUpdate, events.on(serverNotifications, "ActivityLogEntry", onUpdate), apiClient.sendMessage("ActivityLogEntryStart", "0,1500") + this.updateFn = onUpdate; + events.on(serverNotifications, "ActivityLogEntry", onUpdate); + apiClient.sendMessage("ActivityLogEntryStart", "0,1500"); } - return ActivityLog.prototype.destroy = function() { + + ActivityLog.prototype.destroy = function () { var options = this.options; + if (options) { options.element.classList.remove("activityLogListWidget"); - connectionManager.getApiClient(options.serverId).sendMessage("ActivityLogEntryStop", "0,1500") + connectionManager.getApiClient(options.serverId).sendMessage("ActivityLogEntryStop", "0,1500"); } + var onUpdate = this.updateFn; - onUpdate && events.off(serverNotifications, "ActivityLogEntry", onUpdate), this.items = null, this.options = null - }, ActivityLog + + if (onUpdate) { + events.off(serverNotifications, "ActivityLogEntry", onUpdate); + } + + this.items = null; + this.options = null; + }; + + return ActivityLog; }); From 72cb4bd169df49a6c07f0344bc4d1b1a6848ae79 Mon Sep 17 00:00:00 2001 From: grafixeyehero Date: Wed, 9 Oct 2019 19:23:47 +0300 Subject: [PATCH 030/162] favoriteitems --- src/components/favoriteitems.js | 237 +++++++++++++++++++++----------- 1 file changed, 155 insertions(+), 82 deletions(-) diff --git a/src/components/favoriteitems.js b/src/components/favoriteitems.js index 396d4d3c22..05a8580e61 100644 --- a/src/components/favoriteitems.js +++ b/src/components/favoriteitems.js @@ -1,20 +1,32 @@ -define(["loading", "libraryBrowser", "cardBuilder", "dom", "apphost", "imageLoader", "globalize", "layoutManager", "scrollStyles", "emby-itemscontainer"], function(loading, libraryBrowser, cardBuilder, dom, appHost, imageLoader, globalize, layoutManager) { +define(["loading", "libraryBrowser", "cardBuilder", "dom", "apphost", "imageLoader", "globalize", "layoutManager", "scrollStyles", "emby-itemscontainer"], function (loading, libraryBrowser, cardBuilder, dom, appHost, imageLoader, globalize, layoutManager) { "use strict"; function enableScrollX() { - return !layoutManager.desktop + return !layoutManager.desktop; } function getThumbShape() { - return enableScrollX() ? "overflowBackdrop" : "backdrop" + if (enableScrollX()) { + return "overflowBackdrop"; + } + + return "backdrop"; } function getPosterShape() { - return enableScrollX() ? "overflowPortrait" : "portrait" + if (enableScrollX()) { + return "overflowPortrait"; + } + + return "portrait"; } function getSquareShape() { - return enableScrollX() ? "overflowSquare" : "square" + if (enableScrollX()) { + return "overflowSquare"; + } + + return "square"; } function getSections() { @@ -23,147 +35,208 @@ define(["loading", "libraryBrowser", "cardBuilder", "dom", "apphost", "imageLoad types: "Movie", id: "favoriteMovies", shape: getPosterShape(), - showTitle: !1, - overlayPlayButton: !0 + showTitle: false, + overlayPlayButton: true }, { name: "HeaderFavoriteShows", types: "Series", id: "favoriteShows", shape: getPosterShape(), - showTitle: !1, - overlayPlayButton: !0 + showTitle: false, + overlayPlayButton: true }, { name: "HeaderFavoriteEpisodes", types: "Episode", id: "favoriteEpisode", shape: getThumbShape(), - preferThumb: !1, - showTitle: !0, - showParentTitle: !0, - overlayPlayButton: !0, - overlayText: !1, - centerText: !0 + preferThumb: false, + showTitle: true, + showParentTitle: true, + overlayPlayButton: true, + overlayText: false, + centerText: true }, { name: "HeaderFavoriteVideos", types: "Video,MusicVideo", id: "favoriteVideos", shape: getThumbShape(), - preferThumb: !0, - showTitle: !0, - overlayPlayButton: !0, - overlayText: !1, - centerText: !0 + preferThumb: true, + showTitle: true, + overlayPlayButton: true, + overlayText: false, + centerText: true }, { name: "HeaderFavoriteArtists", types: "MusicArtist", id: "favoriteArtists", shape: getSquareShape(), - preferThumb: !1, - showTitle: !0, - overlayText: !1, - showParentTitle: !1, - centerText: !0, - overlayPlayButton: !0, - coverImage: !0 + preferThumb: false, + showTitle: true, + overlayText: false, + showParentTitle: false, + centerText: true, + overlayPlayButton: true, + coverImage: true }, { name: "HeaderFavoriteAlbums", types: "MusicAlbum", id: "favoriteAlbums", shape: getSquareShape(), - preferThumb: !1, - showTitle: !0, - overlayText: !1, - showParentTitle: !0, - centerText: !0, - overlayPlayButton: !0, - coverImage: !0 + preferThumb: false, + showTitle: true, + overlayText: false, + showParentTitle: true, + centerText: true, + overlayPlayButton: true, + coverImage: true }, { name: "HeaderFavoriteSongs", types: "Audio", id: "favoriteSongs", shape: getSquareShape(), - preferThumb: !1, - showTitle: !0, - overlayText: !1, - showParentTitle: !0, - centerText: !0, - overlayMoreButton: !0, + preferThumb: false, + showTitle: true, + overlayText: false, + showParentTitle: true, + centerText: true, + overlayMoreButton: true, action: "instantmix", - coverImage: !0 - }] + coverImage: true + }]; } function loadSection(elem, userId, topParentId, section, isSingleSection) { - var screenWidth = dom.getWindowSize().innerWidth, - options = { - SortBy: "SortName", - SortOrder: "Ascending", - Filters: "IsFavorite", - Recursive: !0, - Fields: "PrimaryImageAspectRatio,BasicSyncInfo", - CollapseBoxSetItems: !1, - ExcludeLocationTypes: "Virtual", - EnableTotalRecordCount: !1 - }; - topParentId && (options.ParentId = topParentId), isSingleSection || (options.Limit = screenWidth >= 1920 ? 10 : screenWidth >= 1440 ? 8 : 6, enableScrollX() && (options.Limit = 20)); + var screenWidth = dom.getWindowSize().innerWidth; + var options = { + SortBy: "SortName", + SortOrder: "Ascending", + Filters: "IsFavorite", + Recursive: true, + Fields: "PrimaryImageAspectRatio,BasicSyncInfo", + CollapseBoxSetItems: false, + ExcludeLocationTypes: "Virtual", + EnableTotalRecordCount: false + }; + + if (topParentId) { + options.ParentId = topParentId; + } + + if (!isSingleSection) { + options.Limit = screenWidth >= 1920 ? 10 : screenWidth >= 1440 ? 8 : 6; + + if (enableScrollX()) { + options.Limit = 20; + } + } + var promise; - return "MusicArtist" === section.types ? promise = ApiClient.getArtists(userId, options) : (options.IncludeItemTypes = section.types, promise = ApiClient.getItems(userId, options)), promise.then(function(result) { + + if ("MusicArtist" === section.types) { + promise = ApiClient.getArtists(userId, options); + } else { + options.IncludeItemTypes = section.types; + promise = ApiClient.getItems(userId, options); + } + + return promise.then(function (result) { var html = ""; + if (result.Items.length) { if (html += '
', !layoutManager.tv && options.Limit && result.Items.length >= options.Limit) { - html += '', html += '

', html += globalize.translate(section.name), html += "

", html += '', html += "
" - } else html += '

' + globalize.translate(section.name) + "

"; + html += ''; + html += '

'; + html += globalize.translate(section.name); + html += "

"; + html += ''; + html += "
"; + } else { + html += '

' + globalize.translate(section.name) + "

"; + } + if (html += "
", enableScrollX()) { var scrollXClass = "scrollX hiddenScrollX"; - layoutManager.tv && (scrollXClass += " smoothScrollX"), html += '
' - } else html += '
'; - var supportsImageAnalysis = appHost.supports("imageanalysis"), - cardLayout = (appHost.preferVisualCards || supportsImageAnalysis) && section.autoCardLayout && section.showTitle; - cardLayout = !1, html += cardBuilder.getCardsHtml(result.Items, { + + if (layoutManager.tv) { + scrollXClass += " smoothScrollX"; + } + + html += '
'; + } else { + html += '
'; + } + + var supportsImageAnalysis = appHost.supports("imageanalysis"); + var cardLayout = (appHost.preferVisualCards || supportsImageAnalysis) && section.autoCardLayout && section.showTitle; + cardLayout = false; + html += cardBuilder.getCardsHtml(result.Items, { preferThumb: section.preferThumb, shape: section.shape, centerText: section.centerText && !cardLayout, - overlayText: !1 !== section.overlayText, + overlayText: false !== section.overlayText, showTitle: section.showTitle, showParentTitle: section.showParentTitle, - scalable: !0, + scalable: true, coverImage: section.coverImage, overlayPlayButton: section.overlayPlayButton, overlayMoreButton: section.overlayMoreButton && !cardLayout, action: section.action, allowBottomPadding: !enableScrollX(), cardLayout: cardLayout - }), html += "
" + }); + html += "
"; } - elem.innerHTML = html, imageLoader.lazyChildren(elem) - }) + + elem.innerHTML = html; + imageLoader.lazyChildren(elem); + }); } function loadSections(page, userId, topParentId, types) { loading.show(); - var sections = getSections(), - sectionid = getParameterByName("sectionid"); - sectionid && (sections = sections.filter(function(s) { - return s.id === sectionid - })), types && (sections = sections.filter(function(s) { - return -1 !== types.indexOf(s.id) - })); - var i, length, elem = page.querySelector(".favoriteSections"); + var sections = getSections(); + var sectionid = getParameterByName("sectionid"); + + if (sectionid) { + sections = sections.filter(function (s) { + return s.id === sectionid; + }); + } + + if (types) { + sections = sections.filter(function (s) { + return -1 !== types.indexOf(s.id); + }); + } + + var i; + var length; + var elem = page.querySelector(".favoriteSections"); + if (!elem.innerHTML) { var html = ""; - for (i = 0, length = sections.length; i < length; i++) html += '
'; - elem.innerHTML = html + + for (i = 0, length = sections.length; i < length; i++) { + html += '
'; + } + + elem.innerHTML = html; } + var promises = []; + for (i = 0, length = sections.length; i < length; i++) { var section = sections[i]; - elem = page.querySelector(".section" + section.id), promises.push(loadSection(elem, userId, topParentId, section, 1 === sections.length)) + elem = page.querySelector(".section" + section.id); + promises.push(loadSection(elem, userId, topParentId, section, 1 === sections.length)); } - Promise.all(promises).then(function() { - loading.hide() - }) + + Promise.all(promises).then(function () { + loading.hide(); + }); } + return { render: loadSections - } + }; }); From 08ae592e0bab4f93e098069f5b2ebbf2a21e3d90 Mon Sep 17 00:00:00 2001 From: grafixeyehero Date: Wed, 9 Oct 2019 19:26:18 +0300 Subject: [PATCH 031/162] groupedcards --- src/components/groupedcards.js | 57 +++++++++++++++++++++------------- 1 file changed, 35 insertions(+), 22 deletions(-) diff --git a/src/components/groupedcards.js b/src/components/groupedcards.js index a6b1946526..ad638ecdd9 100644 --- a/src/components/groupedcards.js +++ b/src/components/groupedcards.js @@ -1,32 +1,45 @@ -define(["dom", "appRouter", "connectionManager"], function(dom, appRouter, connectionManager) { +define(["dom", "appRouter", "connectionManager"], function (dom, appRouter, connectionManager) { "use strict"; function onGroupedCardClick(e, card) { - var itemId = card.getAttribute("data-id"), - serverId = card.getAttribute("data-serverid"), - apiClient = connectionManager.getApiClient(serverId), - userId = apiClient.getCurrentUserId(), - playedIndicator = card.querySelector(".playedIndicator"), - playedIndicatorHtml = playedIndicator ? playedIndicator.innerHTML : null, - options = { - Limit: parseInt(playedIndicatorHtml || "10"), - Fields: "PrimaryImageAspectRatio,DateCreated", - ParentId: itemId, - GroupItems: !1 - }, - actionableParent = dom.parentWithTag(e.target, ["A", "BUTTON", "INPUT"]); - if (!actionableParent || actionableParent.classList.contains("cardContent")) return apiClient.getJSON(apiClient.getUrl("Users/" + userId + "/Items/Latest", options)).then(function(items) { - if (1 === items.length) return void appRouter.showItem(items[0]); - var url = "itemdetails.html?id=" + itemId + "&serverId=" + serverId; - Dashboard.navigate(url) - }), e.stopPropagation(), e.preventDefault(), !1 + var itemId = card.getAttribute("data-id"); + var serverId = card.getAttribute("data-serverid"); + var apiClient = connectionManager.getApiClient(serverId); + var userId = apiClient.getCurrentUserId(); + var playedIndicator = card.querySelector(".playedIndicator"); + var playedIndicatorHtml = playedIndicator ? playedIndicator.innerHTML : null; + var options = { + Limit: parseInt(playedIndicatorHtml || "10"), + Fields: "PrimaryImageAspectRatio,DateCreated", + ParentId: itemId, + GroupItems: false + }; + var actionableParent = dom.parentWithTag(e.target, ["A", "BUTTON", "INPUT"]); + + if (!actionableParent || actionableParent.classList.contains("cardContent")) { + apiClient.getJSON(apiClient.getUrl("Users/" + userId + "/Items/Latest", options)).then(function (items) { + if (1 === items.length) { + return void appRouter.showItem(items[0]); + } + + var url = "itemdetails.html?id=" + itemId + "&serverId=" + serverId; + Dashboard.navigate(url); + }); + e.stopPropagation(); + e.preventDefault(); + return false; + } } function onItemsContainerClick(e) { var groupedCard = dom.parentWithClass(e.target, "groupedCard"); - groupedCard && onGroupedCardClick(e, groupedCard) + + if (groupedCard) { + onGroupedCardClick(e, groupedCard); + } } + return { onItemsContainerClick: onItemsContainerClick - } -}); \ No newline at end of file + }; +}); From 07aa20a2f7ab541aa8e9ea7e0eaca283d044f669 Mon Sep 17 00:00:00 2001 From: grafixeyehero Date: Wed, 9 Oct 2019 19:35:12 +0300 Subject: [PATCH 032/162] tunerpicker --- src/components/tunerpicker.js | 159 +++++++++++++++++++++++++++------- 1 file changed, 126 insertions(+), 33 deletions(-) diff --git a/src/components/tunerpicker.js b/src/components/tunerpicker.js index 784f677430..77bddba530 100644 --- a/src/components/tunerpicker.js +++ b/src/components/tunerpicker.js @@ -1,78 +1,171 @@ -define(["dialogHelper", "dom", "layoutManager", "connectionManager", "globalize", "loading", "material-icons", "formDialogStyle", "emby-button", "emby-itemscontainer", "cardStyle"], function(dialogHelper, dom, layoutManager, connectionManager, globalize, loading) { +define(["dialogHelper", "dom", "layoutManager", "connectionManager", "globalize", "loading", "material-icons", "formDialogStyle", "emby-button", "emby-itemscontainer", "cardStyle"], function (dialogHelper, dom, layoutManager, connectionManager, globalize, loading) { "use strict"; function getEditorHtml() { var html = ""; - return html += '
', html += '
', html += '
', html += "

" + globalize.translate("DetectingDevices") + "...

", html += "

" + globalize.translate("MessagePleaseWait") + "

", html += "
", html += '

' + globalize.translate("HeaderNewDevices") + "

", html += '
', html += "
", html += "
", html += "
" + html += '
'; + html += '
'; + html += '
'; + html += "

" + globalize.translate("DetectingDevices") + "...

"; + html += "

" + globalize.translate("MessagePleaseWait") + "

"; + html += "
"; + html += '

' + globalize.translate("HeaderNewDevices") + "

"; + html += '
'; + html += "
"; + html += "
"; + return html += "
"; } function getDeviceHtml(device) { - var padderClass, html = "", - cssClass = "card scalableCard", - cardBoxCssClass = "cardBox visualCardBox"; - return cssClass += " backdropCard backdropCard-scalable", padderClass = "cardPadder-backdrop", layoutManager.tv && (cssClass += " card-focusscale", cardBoxCssClass += " cardBox-focustransform"), cardBoxCssClass += " card-focuscontent", html += '" + var padderClass; + var html = ""; + var cssClass = "card scalableCard"; + var cardBoxCssClass = "cardBox visualCardBox"; + cssClass += " backdropCard backdropCard-scalable"; + padderClass = "cardPadder-backdrop"; + + if (layoutManager.tv) { + cssClass += " card-focusscale"; + cardBoxCssClass += " cardBox-focustransform"; + } + + cardBoxCssClass += " card-focuscontent"; + html += '"; } function getTunerName(providerId) { switch (providerId = providerId.toLowerCase()) { case "m3u": return "M3U"; + case "hdhomerun": return "HDHomerun"; + case "hauppauge": return "Hauppauge"; + case "satip": return "DVB"; + default: - return "Unknown" + return "Unknown"; } } function renderDevices(view, devices) { - var i, length, html = ""; - for (i = 0, length = devices.length; i < length; i++) html += getDeviceHtml(devices[i]); - devices.length ? view.querySelector(".devicesHeader").classList.remove("hide") : (html = "


" + globalize.translate("NoNewDevicesFound") + "

", view.querySelector(".devicesHeader").classList.add("hide")); + var i; + var length; + var html = ""; + + for (i = 0, length = devices.length; i < length; i++) { + html += getDeviceHtml(devices[i]); + } + + if (devices.length) { + view.querySelector(".devicesHeader").classList.remove("hide"); + } else { + html = "


" + globalize.translate("NoNewDevicesFound") + "

"; + view.querySelector(".devicesHeader").classList.add("hide"); + } + var elem = view.querySelector(".results"); - elem.innerHTML = html, layoutManager.tv && focusManager.autoFocus(elem) + elem.innerHTML = html; + + if (layoutManager.tv) { + focusManager.autoFocus(elem); + } } function discoverDevices(view, apiClient) { - return loading.show(), view.querySelector(".loadingContent").classList.remove("hide"), ApiClient.getJSON(ApiClient.getUrl("LiveTv/Tuners/Discvover", { - NewDevicesOnly: !0 - })).then(function(devices) { - currentDevices = devices, renderDevices(view, devices), view.querySelector(".loadingContent").classList.add("hide"), loading.hide() - }) + loading.show(); + view.querySelector(".loadingContent").classList.remove("hide"); + return ApiClient.getJSON(ApiClient.getUrl("LiveTv/Tuners/Discvover", { + NewDevicesOnly: true + })).then(function (devices) { + currentDevices = devices; + renderDevices(view, devices); + view.querySelector(".loadingContent").classList.add("hide"); + loading.hide(); + }); } function tunerPicker() { - this.show = function(options) { + this.show = function (options) { var dialogOptions = { - removeOnClose: !0, - scrollY: !1 + removeOnClose: true, + scrollY: false }; - layoutManager.tv ? dialogOptions.size = "fullscreen" : dialogOptions.size = "small"; + + if (layoutManager.tv) { + dialogOptions.size = "fullscreen"; + } else { + dialogOptions.size = "small"; + } + var dlg = dialogHelper.createDialog(dialogOptions); dlg.classList.add("formDialog"); var html = ""; - html += '
', html += '', html += '

', html += globalize.translate("HeaderLiveTvTunerSetup"), html += "

", html += "
", html += getEditorHtml(), dlg.innerHTML = html, dlg.querySelector(".btnCancel").addEventListener("click", function() { - dialogHelper.close(dlg) + html += '
'; + html += ''; + html += '

'; + html += globalize.translate("HeaderLiveTvTunerSetup"); + html += "

"; + html += "
"; + html += getEditorHtml(); + dlg.innerHTML = html; + dlg.querySelector(".btnCancel").addEventListener("click", function () { + dialogHelper.close(dlg); }); var deviceResult; - dlg.querySelector(".results").addEventListener("click", function(e) { + dlg.querySelector(".results").addEventListener("click", function (e) { var tunerCard = dom.parentWithClass(e.target, "card"); + if (tunerCard) { var deviceId = tunerCard.getAttribute("data-id"); - deviceResult = currentDevices.filter(function(d) { - return d.DeviceId === deviceId - })[0], dialogHelper.close(dlg) + deviceResult = currentDevices.filter(function (d) { + return d.DeviceId === deviceId; + })[0]; + dialogHelper.close(dlg); } - }), layoutManager.tv && centerFocus(dlg.querySelector(".formDialogContent"), !1, !0); + }); + + if (layoutManager.tv) { + centerFocus(dlg.querySelector(".formDialogContent"), false, true); + } + var apiClient = connectionManager.getApiClient(options.serverId); - return discoverDevices(dlg, apiClient), layoutManager.tv && centerFocus(dlg.querySelector(".formDialogContent"), !1, !1), dialogHelper.open(dlg).then(function() { - return deviceResult ? Promise.resolve(deviceResult) : Promise.reject() - }) - } + discoverDevices(dlg, apiClient); + + if (layoutManager.tv) { + centerFocus(dlg.querySelector(".formDialogContent"), false, false); + } + + return dialogHelper.open(dlg).then(function () { + if (deviceResult) { + return Promise.resolve(deviceResult); + } + + return Promise.reject(); + }); + }; } + var currentDevices = []; - return tunerPicker -}); \ No newline at end of file + return tunerPicker; +}); From 2c111d2a599b3f13afc81548a78f561c878c847d Mon Sep 17 00:00:00 2001 From: grafixeyehero Date: Wed, 9 Oct 2019 19:37:49 +0300 Subject: [PATCH 033/162] humanedate --- src/components/humanedate.js | 66 +++++++++++++++++++++--------------- 1 file changed, 38 insertions(+), 28 deletions(-) diff --git a/src/components/humanedate.js b/src/components/humanedate.js index 9abaa952c2..1781ad7dab 100644 --- a/src/components/humanedate.js +++ b/src/components/humanedate.js @@ -1,28 +1,42 @@ -define(["datetime"], function(datetime) { +define(["datetime"], function (datetime) { "use strict"; function humaneDate(date_str) { - var format, time_formats = [ - [90, "a minute"], - [3600, "minutes", 60], - [5400, "an hour"], - [86400, "hours", 3600], - [129600, "a day"], - [604800, "days", 86400], - [907200, "a week"], - [2628e3, "weeks", 604800], - [3942e3, "a month"], - [31536e3, "months", 2628e3], - [47304e3, "a year"], - [31536e5, "years", 31536e3] - ], - dt = new Date, - date = datetime.parseISO8601Date(date_str, !0), - seconds = (dt - date) / 1e3, - i = 0; - for (seconds < 0 && (seconds = Math.abs(seconds)); format = time_formats[i++];) - if (seconds < format[0]) return 2 == format.length ? format[1] + " ago" : Math.round(seconds / format[2]) + " " + format[1] + " ago"; - return seconds > 47304e5 ? Math.round(seconds / 47304e5) + " centuries ago" : date_str + var format; + var time_formats = [ + [90, "a minute"], + [3600, "minutes", 60], + [5400, "an hour"], + [86400, "hours", 3600], + [129600, "a day"], + [604800, "days", 86400], + [907200, "a week"], + [2628e3, "weeks", 604800], + [3942e3, "a month"], + [31536e3, "months", 2628e3], + [47304e3, "a year"], + [31536e5, "years", 31536e3] + ]; + var dt = new Date(); + var date = datetime.parseISO8601Date(date_str, true); + var seconds = (dt - date) / 1e3; + var i = 0; + + for (seconds < 0 && (seconds = Math.abs(seconds)); format = time_formats[i++];) { + if (seconds < format[0]) { + if (2 == format.length) { + return format[1] + " ago"; + } + + return Math.round(seconds / format[2]) + " " + format[1] + " ago"; + } + } + + if (seconds > 47304e5) { + return Math.round(seconds / 47304e5) + " centuries ago"; + } + + return date_str; } function humaneElapsed(firstDateStr, secondDateStr) { @@ -30,12 +44,10 @@ define(["datetime"], function(datetime) { var dateOne = new Date(firstDateStr); var dateTwo = new Date(secondDateStr); var delta = (dateTwo.getTime() - dateOne.getTime()) / 1e3; - var days = Math.floor(delta % 31536e3 / 86400); var hours = Math.floor(delta % 31536e3 % 86400 / 3600); var minutes = Math.floor(delta % 31536e3 % 86400 % 3600 / 60); var seconds = Math.round(delta % 31536e3 % 86400 % 3600 % 60); - var elapsed = ""; elapsed += 1 == days ? days + " day " : ""; elapsed += days > 1 ? days + " days " : ""; @@ -46,15 +58,13 @@ define(["datetime"], function(datetime) { elapsed += elapsed.length > 0 ? "and " : ""; elapsed += 1 == seconds ? seconds + " second" : ""; elapsed += 0 == seconds || seconds > 1 ? seconds + " seconds" : ""; - return elapsed; } window.humaneDate = humaneDate; window.humaneElapsed = humaneElapsed; - return { humaneDate: humaneDate, humaneElapsed: humaneElapsed - } -}); \ No newline at end of file + }; +}); From 029e015068bb8564fa858ec59390f2e50d9902ad Mon Sep 17 00:00:00 2001 From: redSpoutnik <15638041+redSpoutnik@users.noreply.github.com> Date: Thu, 10 Oct 2019 17:45:56 +0200 Subject: [PATCH 034/162] more readable statement to find showing textTrack --- src/components/htmlvideoplayer/plugin.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/components/htmlvideoplayer/plugin.js b/src/components/htmlvideoplayer/plugin.js index 95da82a26b..79b135fdad 100644 --- a/src/components/htmlvideoplayer/plugin.js +++ b/src/components/htmlvideoplayer/plugin.js @@ -581,9 +581,11 @@ define(['browser', 'require', 'events', 'apphost', 'loading', 'dom', 'playbackMa Array.from(videoElement.textTracks) .filter(function(trackElement) { // get showing .vtt textTacks - return (trackElement.mode === 'showing') || + var isVttTrackShowing = trackElement.mode === 'showing'; // get current .ass textTrack - (("textTrack" + customTrackIndex) === trackElement.id); + var isAssTrackShowing = ("textTrack" + customTrackIndex) === trackElement.id; + + return isVttTrackShowing || isAssTrackShowing; }) .forEach(function(trackElement) { From d467499a7aab68e0ffa865582602775cfb96bf1c Mon Sep 17 00:00:00 2001 From: grafixeyehero Date: Thu, 10 Oct 2019 20:40:27 +0300 Subject: [PATCH 035/162] remove new lines --- src/scripts/librarymenu.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/scripts/librarymenu.js b/src/scripts/librarymenu.js index ed6284b164..18eddb08bc 100644 --- a/src/scripts/librarymenu.js +++ b/src/scripts/librarymenu.js @@ -208,11 +208,10 @@ define(["dom", "layoutManager", "inputManager", "connectionManager", "events", " html += "
"; } - // add buttons to navigation drawer + // add buttons to navigation drawer navDrawerScrollContainer.innerHTML = html; // bind logout button click to method - var btnLogout = navDrawerScrollContainer.querySelector(".btnLogout"); if (btnLogout) { @@ -506,7 +505,6 @@ define(["dom", "layoutManager", "inputManager", "connectionManager", "events", " } // FIXME: Potentially the same as above - if (user.Policy.EnableContentDownloading) { showBySelector(".lnkSyncToOtherDevices", true); } else { From af3579f328781247f008fa5f05940993fae945fa Mon Sep 17 00:00:00 2001 From: grafixeyehero Date: Thu, 10 Oct 2019 20:41:58 +0300 Subject: [PATCH 036/162] update console.log livetvcomponents --- src/scripts/livetvcomponents.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/scripts/livetvcomponents.js b/src/scripts/livetvcomponents.js index fb8dadef78..4215de4cbe 100644 --- a/src/scripts/livetvcomponents.js +++ b/src/scripts/livetvcomponents.js @@ -34,7 +34,7 @@ define(["layoutManager", "datetime", "cardBuilder", "apphost"], function (layout day: "numeric" }); } catch (err) { - console.log("Error parsing premiereDate:" + item.StartDate); + console.log("Error parsing premiereDate:" + item.StartDate + "; error: " + err); } } From 03a16287a033c45812fe5ecee444d1b98fb207c3 Mon Sep 17 00:00:00 2001 From: grafixeyehero Date: Thu, 10 Oct 2019 20:43:04 +0300 Subject: [PATCH 037/162] remove query.Artistids conditions --- src/scripts/itembynamedetailpage.js | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/scripts/itembynamedetailpage.js b/src/scripts/itembynamedetailpage.js index 74d69eecf8..5d3c9dedb9 100644 --- a/src/scripts/itembynamedetailpage.js +++ b/src/scripts/itembynamedetailpage.js @@ -323,11 +323,7 @@ define(["connectionManager", "listView", "cardBuilder", "imageLoader", "libraryB } else if (item.Type == "Studio") { query.StudioIds = item.Id; } else if (item.Type == "MusicArtist") { - if (connectionManager.getApiClient(item.ServerId).isMinServerVersion("3.4.1.18")) { - query.AlbumArtistIds = item.Id; - } else { - query.ArtistIds = item.Id; - } + query.AlbumArtistIds = item.Id; } } From 63f804df32586ea8086f76857c36a74d7516aa3d Mon Sep 17 00:00:00 2001 From: Daniel Hartung <22015466+dhartung@users.noreply.github.com> Date: Fri, 11 Oct 2019 15:48:28 +0200 Subject: [PATCH 038/162] Fixed #518 --- src/components/htmlvideoplayer/plugin.js | 67 ++++++++++++------------ 1 file changed, 33 insertions(+), 34 deletions(-) diff --git a/src/components/htmlvideoplayer/plugin.js b/src/components/htmlvideoplayer/plugin.js index 27e02349c0..77e8d61b87 100644 --- a/src/components/htmlvideoplayer/plugin.js +++ b/src/components/htmlvideoplayer/plugin.js @@ -1192,44 +1192,43 @@ define(['browser', 'require', 'events', 'apphost', 'loading', 'dom', 'playbackMa } var trackElement = null; - var expectedId = 'manualTrack' + track.Index; + if (videoElement.textTracks && videoElement.textTracks.length > 0) { + trackElement = videoElement.textTracks[0]; - // get list of tracks - var allTracks = videoElement.textTracks; - for (var i = 0; i < allTracks.length; i++) { - - var currentTrack = allTracks[i]; - - if (currentTrack.label === expectedId) { - trackElement = currentTrack; - break; - } else { - currentTrack.mode = 'disabled'; - } - } - - if (!trackElement) { - trackElement = videoElement.addTextTrack('subtitles', 'manualTrack' + track.Index, track.Language || 'und'); - - // download the track json - fetchSubtitles(track, item).then(function (data) { - - // show in ui - console.log('downloaded ' + data.TrackEvents.length + ' track events'); - // add some cues to show the text - // in safari, the cues need to be added before setting the track mode to showing - data.TrackEvents.forEach(function (trackEvent) { - - var trackCueObject = window.VTTCue || window.TextTrackCue; - var cue = new trackCueObject(trackEvent.StartPositionTicks / 10000000, trackEvent.EndPositionTicks / 10000000, normalizeTrackEventText(trackEvent.Text)); - - trackElement.addCue(cue); - }); + // This throws an error in IE, but is fine in chrome + // In IE it's not necessary anyway because changing the src seems to be enough + try { trackElement.mode = 'showing'; - }); + while (trackElement.cues.length) { + trackElement.removeCue(trackElement.cues[0]); + } + } catch (e) { + console.log('Error removing cue from textTrack'); + } + + trackElement.mode = 'disabled'; } else { - trackElement.mode = 'showing'; + // There is a function addTextTrack but no function for removeTextTrack + // Therefore we add ONE element and replace its cue data + trackElement = videoElement.addTextTrack('subtitles', 'manualTrack', 'und'); } + + // download the track json + fetchSubtitles(track, item).then(function (data) { + + // show in ui + console.log('downloaded ' + data.TrackEvents.length + ' track events'); + // add some cues to show the text + // in safari, the cues need to be added before setting the track mode to showing + data.TrackEvents.forEach(function (trackEvent) { + + var trackCueObject = window.VTTCue || window.TextTrackCue; + var cue = new trackCueObject(trackEvent.StartPositionTicks / 10000000, trackEvent.EndPositionTicks / 10000000, normalizeTrackEventText(trackEvent.Text)); + + trackElement.addCue(cue); + }); + trackElement.mode = 'showing'; + }); } function updateSubtitleText(timeMs) { From 418545686338332c183d7b96bc93da2a0c8e6946 Mon Sep 17 00:00:00 2001 From: Daniel Hartung <22015466+dhartung@users.noreply.github.com> Date: Fri, 11 Oct 2019 15:48:52 +0200 Subject: [PATCH 039/162] Added contributors entry --- CONTRIBUTORS.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index c7c8a07162..31b7cb0bfb 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -28,6 +28,7 @@ - [lewazo](https://github.com/lewazo) - [Raghu Saxena](https://github.com/ckcr4lyf) - [Nickbert7](https://github.com/Nickbert7) + - [Daniel Hartung](https://github.com/dhartung) # Emby Contributors From bc44aa5604f01e318516daa0ab6a6e4dcd630a07 Mon Sep 17 00:00:00 2001 From: grafixeyehero Date: Fri, 11 Oct 2019 18:47:17 +0300 Subject: [PATCH 040/162] Unminify connectionmanager.js --- .../apiclient/connectionmanager.js | 1687 +++++++++++------ 1 file changed, 1107 insertions(+), 580 deletions(-) diff --git a/src/bower_components/apiclient/connectionmanager.js b/src/bower_components/apiclient/connectionmanager.js index 8724300658..073a2e477c 100644 --- a/src/bower_components/apiclient/connectionmanager.js +++ b/src/bower_components/apiclient/connectionmanager.js @@ -1,227 +1,375 @@ -define(["events", "apiclient", "appStorage"], function(events, apiClientFactory, appStorage) { +define(["events", "apiclient", "appStorage"], function (events, apiClientFactory, appStorage) { "use strict"; function getServerAddress(server, mode) { switch (mode) { case ConnectionMode.Local: return server.LocalAddress; + case ConnectionMode.Manual: return server.ManualAddress; + case ConnectionMode.Remote: return server.RemoteAddress; + default: - return server.ManualAddress || server.LocalAddress || server.RemoteAddress + return server.ManualAddress || server.LocalAddress || server.RemoteAddress; } } function paramsToString(params) { var values = []; + for (var key in params) { var value = params[key]; - null !== value && void 0 !== value && "" !== value && values.push(encodeURIComponent(key) + "=" + encodeURIComponent(value)) + + if (null !== value && void 0 !== value && "" !== value) { + values.push(encodeURIComponent(key) + "=" + encodeURIComponent(value)); + } } - return values.join("&") + + return values.join("&"); } function resolveFailure(instance, resolve) { resolve({ State: "Unavailable", ConnectUser: instance.connectUser() - }) + }); } function mergeServers(credentialProvider, list1, list2) { - for (var i = 0, length = list2.length; i < length; i++) credentialProvider.addOrUpdateServer(list1, list2[i]); - return list1 + for (var i = 0, length = list2.length; i < length; i++) { + credentialProvider.addOrUpdateServer(list1, list2[i]); + } + + return list1; } function updateServerInfo(server, systemInfo) { - server.Name = systemInfo.ServerName, systemInfo.Id && (server.Id = systemInfo.Id), systemInfo.LocalAddress && (server.LocalAddress = systemInfo.LocalAddress) + server.Name = systemInfo.ServerName; + server.Id = systemInfo.Id; + + if (systemInfo.LocalAddress) { + server.LocalAddress = systemInfo.LocalAddress; + } } function getEmbyServerUrl(baseUrl, handler) { - return baseUrl + "/" + handler + return baseUrl + "/" + handler; } function getFetchPromise(request) { var headers = request.headers || {}; - "json" === request.dataType && (headers.accept = "application/json"); + + if ("json" === request.dataType) { + headers.accept = "application/json"; + } + var fetchRequest = { - headers: headers, - method: request.type, - credentials: "same-origin" - }, - contentType = request.contentType; - return request.data && ("string" == typeof request.data ? fetchRequest.body = request.data : (fetchRequest.body = paramsToString(request.data), contentType = contentType || "application/x-www-form-urlencoded; charset=UTF-8")), contentType && (headers["Content-Type"] = contentType), request.timeout ? fetchWithTimeout(request.url, fetchRequest, request.timeout) : fetch(request.url, fetchRequest) + headers: headers, + method: request.type, + credentials: "same-origin" + }; + var contentType = request.contentType; + + if (request.data) { + if ("string" == typeof request.data) { + fetchRequest.body = request.data; + } else { + fetchRequest.body = paramsToString(request.data); + contentType = contentType || "application/x-www-form-urlencoded; charset=UTF-8"; + } + } + + if (contentType) { + headers["Content-Type"] = contentType; + } + + if (request.timeout) { + return fetchWithTimeout(request.url, fetchRequest, request.timeout); + } + + return fetch(request.url, fetchRequest); } function fetchWithTimeout(url, options, timeoutMs) { - return console.log("fetchWithTimeout: timeoutMs: " + timeoutMs + ", url: " + url), new Promise(function(resolve, reject) { + console.log("fetchWithTimeout: timeoutMs: " + timeoutMs + ", url: " + url); + return new Promise(function (resolve, reject) { var timeout = setTimeout(reject, timeoutMs); - options = options || {}, options.credentials = "same-origin", fetch(url, options).then(function(response) { - clearTimeout(timeout), console.log("fetchWithTimeout: succeeded connecting to url: " + url), resolve(response) - }, function(error) { - clearTimeout(timeout), console.log("fetchWithTimeout: timed out connecting to url: " + url), reject() - }) - }) + options = options || {}; + options.credentials = "same-origin"; + fetch(url, options).then(function (response) { + clearTimeout(timeout); + console.log("fetchWithTimeout: succeeded connecting to url: " + url); + resolve(response); + }, function (error) { + clearTimeout(timeout); + console.log("fetchWithTimeout: timed out connecting to url: " + url); + reject(); + }); + }); } function ajax(request) { - if (!request) throw new Error("Request cannot be null"); - return request.headers = request.headers || {}, console.log("ConnectionManager requesting url: " + request.url), getFetchPromise(request).then(function(response) { - return console.log("ConnectionManager response status: " + response.status + ", url: " + request.url), response.status < 400 ? "json" === request.dataType || "application/json" === request.headers.accept ? response.json() : response : Promise.reject(response) - }, function(err) { - throw console.log("ConnectionManager request failed to url: " + request.url), err - }) + if (!request) { + throw new Error("Request cannot be null"); + } + + request.headers = request.headers || {}; + console.log("ConnectionManager requesting url: " + request.url); + return getFetchPromise(request).then(function (response) { + console.log("ConnectionManager response status: " + response.status + ", url: " + request.url); + + if (response.status < 400) { + if ("json" === request.dataType || "application/json" === request.headers.accept) { + return response.json(); + } + + return response; + } + + return Promise.reject(response); + }, function (err) { + throw console.log("ConnectionManager request failed to url: " + request.url), err; + }); } function getConnectUrl(handler) { - return "https://connect.emby.media/service/" + handler + return "https://connect.emby.media/service/" + handler; } function replaceAll(originalString, strReplace, strWith) { var reg = new RegExp(strReplace, "ig"); - return originalString.replace(reg, strWith) + return originalString.replace(reg, strWith); } function normalizeAddress(address) { - return address = address.trim(), 0 !== address.toLowerCase().indexOf("http") && (address = "http://" + address), address = replaceAll(address, "Http:", "http:"), address = replaceAll(address, "Https:", "https:") + address = address.trim(); + + if (0 !== address.toLowerCase().indexOf("http")) { + address = "http://" + address; + } + + address = replaceAll(address, "Http:", "http:"); + return address = replaceAll(address, "Https:", "https:"); } function stringEqualsIgnoreCase(str1, str2) { - return (str1 || "").toLowerCase() === (str2 || "").toLowerCase() + return (str1 || "").toLowerCase() === (str2 || "").toLowerCase(); } function compareVersions(a, b) { - a = a.split("."), b = b.split("."); + a = a.split("."); + b = b.split("."); + for (var i = 0, length = Math.max(a.length, b.length); i < length; i++) { - var aVal = parseInt(a[i] || "0"), - bVal = parseInt(b[i] || "0"); - if (aVal < bVal) return -1; - if (aVal > bVal) return 1 + var aVal = parseInt(a[i] || "0"); + var bVal = parseInt(b[i] || "0"); + + if (aVal < bVal) { + return -1; + } + + if (aVal > bVal) { + return 1; + } } - return 0 + + return 0; } - var defaultTimeout = 2e4, - ConnectionMode = { - Local: 0, - Remote: 1, - Manual: 2 - }, - ConnectionManager = function(credentialProvider, appName, appVersion, deviceName, deviceId, capabilities, devicePixelRatio) { - function onConnectUserSignIn(user) { - connectUser = user, events.trigger(self, "connectusersignedin", [user]) + + var defaultTimeout = 2e4; + var ConnectionMode = { + Local: 0, + Remote: 1, + Manual: 2 + }; + + var ConnectionManager = function (credentialProvider, appName, appVersion, deviceName, deviceId, capabilities, devicePixelRatio) { + function onConnectUserSignIn(user) { + connectUser = user; + events.trigger(self, "connectusersignedin", [user]); + } + + function onAuthenticated(apiClient, result, options, saveCredentials) { + var credentials = credentialProvider.credentials(); + var servers = credentials.Servers.filter(function (s) { + return s.Id === result.ServerId; + }); + var server = servers.length ? servers[0] : apiClient.serverInfo(); + + if (false !== options.updateDateLastAccessed) { + server.DateLastAccessed = new Date().getTime(); } - function onAuthenticated(apiClient, result, options, saveCredentials) { - var credentials = credentialProvider.credentials(), - servers = credentials.Servers.filter(function(s) { - return s.Id === result.ServerId - }), - server = servers.length ? servers[0] : apiClient.serverInfo(); - return !1 !== options.updateDateLastAccessed && (server.DateLastAccessed = (new Date).getTime()), server.Id = result.ServerId, saveCredentials ? (server.UserId = result.User.Id, server.AccessToken = result.AccessToken) : (server.UserId = null, server.AccessToken = null), credentialProvider.addOrUpdateServer(credentials.Servers, server), credentialProvider.credentials(credentials), apiClient.enableAutomaticBitrateDetection = options.enableAutomaticBitrateDetection, apiClient.serverInfo(server), afterConnected(apiClient, options), onLocalUserSignIn(server, apiClient.serverAddress(), result.User) + server.Id = result.ServerId; + + if (saveCredentials) { + server.UserId = result.User.Id; + server.AccessToken = result.AccessToken; + } else { + server.UserId = null; + server.AccessToken = null; } - function afterConnected(apiClient, options) { - options = options || {}, !1 !== options.reportCapabilities && apiClient.reportCapabilities(capabilities), apiClient.enableAutomaticBitrateDetection = options.enableAutomaticBitrateDetection, !1 !== options.enableWebSocket && (console.log("calling apiClient.ensureWebSocket"), apiClient.ensureWebSocket()) + credentialProvider.addOrUpdateServer(credentials.Servers, server); + credentialProvider.credentials(credentials); + apiClient.enableAutomaticBitrateDetection = options.enableAutomaticBitrateDetection; + apiClient.serverInfo(server); + afterConnected(apiClient, options); + return onLocalUserSignIn(server, apiClient.serverAddress(), result.User); + } + + function afterConnected(apiClient, options) { + options = options || {}; + + if (false !== options.reportCapabilities) { + apiClient.reportCapabilities(capabilities); } - function onLocalUserSignIn(server, serverUrl, user) { - return self._getOrAddApiClient(server, serverUrl), (self.onLocalUserSignedIn ? self.onLocalUserSignedIn.call(self, user) : Promise.resolve()).then(function() { - events.trigger(self, "localusersignedin", [user]) - }) + apiClient.enableAutomaticBitrateDetection = options.enableAutomaticBitrateDetection; + + if (false !== options.enableWebSocket) { + console.log("calling apiClient.ensureWebSocket"); + apiClient.ensureWebSocket(); + } + } + + function onLocalUserSignIn(server, serverUrl, user) { + self._getOrAddApiClient(server, serverUrl); + + return (self.onLocalUserSignedIn ? self.onLocalUserSignedIn.call(self, user) : Promise.resolve()).then(function () { + events.trigger(self, "localusersignedin", [user]); + }); + } + + function ensureConnectUser(credentials) { + if (connectUser && connectUser.Id === credentials.ConnectUserId) { + return Promise.resolve(); } - function ensureConnectUser(credentials) { - return connectUser && connectUser.Id === credentials.ConnectUserId ? Promise.resolve() : credentials.ConnectUserId && credentials.ConnectAccessToken ? (connectUser = null, getConnectUser(credentials.ConnectUserId, credentials.ConnectAccessToken).then(function(user) { - return onConnectUserSignIn(user), Promise.resolve() - }, function() { - return Promise.resolve() - })) : Promise.resolve() + if (credentials.ConnectUserId && credentials.ConnectAccessToken) { + connectUser = null; + return getConnectUser(credentials.ConnectUserId, credentials.ConnectAccessToken).then(function (user) { + onConnectUserSignIn(user); + return Promise.resolve(); + }, function () { + return Promise.resolve(); + }); } - function getConnectUser(userId, accessToken) { - if (!userId) throw new Error("null userId"); - if (!accessToken) throw new Error("null accessToken"); - return ajax({ - type: "GET", - url: "https://connect.emby.media/service/user?id=" + userId, - dataType: "json", - headers: { - "X-Application": appName + "/" + appVersion, - "X-Connect-UserToken": accessToken - } - }) + return Promise.resolve(); + } + + function getConnectUser(userId, accessToken) { + if (!userId) { + throw new Error("null userId"); } - function addAuthenticationInfoFromConnect(server, serverUrl, credentials) { - if (!server.ExchangeToken) throw new Error("server.ExchangeToken cannot be null"); - if (!credentials.ConnectUserId) throw new Error("credentials.ConnectUserId cannot be null"); - var url = getEmbyServerUrl(serverUrl, "Connect/Exchange?format=json&ConnectUserId=" + credentials.ConnectUserId), - auth = 'MediaBrowser Client="' + appName + '", Device="' + deviceName + '", DeviceId="' + deviceId + '", Version="' + appVersion + '"'; - return ajax({ - type: "GET", - url: url, - dataType: "json", - headers: { - "X-MediaBrowser-Token": server.ExchangeToken, - "X-Emby-Authorization": auth - } - }).then(function(auth) { - return server.UserId = auth.LocalUserId, server.AccessToken = auth.AccessToken, auth - }, function() { - return server.UserId = null, server.AccessToken = null, Promise.reject() - }) + if (!accessToken) { + throw new Error("null accessToken"); } - function validateAuthentication(server, serverUrl) { - return ajax({ - type: "GET", - url: getEmbyServerUrl(serverUrl, "System/Info"), - dataType: "json", - headers: { - "X-MediaBrowser-Token": server.AccessToken - } - }).then(function(systemInfo) { - return updateServerInfo(server, systemInfo), Promise.resolve() - }, function() { - return server.UserId = null, server.AccessToken = null, Promise.resolve() - }) + return ajax({ + type: "GET", + url: "https://connect.emby.media/service/user?id=" + userId, + dataType: "json", + headers: { + "X-Application": appName + "/" + appVersion, + "X-Connect-UserToken": accessToken + } + }); + } + + function addAuthenticationInfoFromConnect(server, serverUrl, credentials) { + if (!server.ExchangeToken) { + throw new Error("server.ExchangeToken cannot be null"); } - function getImageUrl(localUser) { - if (connectUser && connectUser.ImageUrl) return { + if (!credentials.ConnectUserId) { + throw new Error("credentials.ConnectUserId cannot be null"); + } + + var url = getEmbyServerUrl(serverUrl, "Connect/Exchange?format=json&ConnectUserId=" + credentials.ConnectUserId); + var auth = 'MediaBrowser Client="' + appName + '", Device="' + deviceName + '", DeviceId="' + deviceId + '", Version="' + appVersion + '"'; + return ajax({ + type: "GET", + url: url, + dataType: "json", + headers: { + "X-MediaBrowser-Token": server.ExchangeToken, + "X-Emby-Authorization": auth + } + }).then(function (auth) { + server.UserId = auth.LocalUserId; + server.AccessToken = auth.AccessToken; + return auth; + }, function () { + server.UserId = null; + server.AccessToken = null; + return Promise.reject(); + }); + } + + function validateAuthentication(server, serverUrl) { + return ajax({ + type: "GET", + url: getEmbyServerUrl(serverUrl, "System/Info"), + dataType: "json", + headers: { + "X-MediaBrowser-Token": server.AccessToken + } + }).then(function (systemInfo) { + updateServerInfo(server, systemInfo); + return Promise.resolve(); + }, function () { + server.UserId = null; + server.AccessToken = null; + return Promise.resolve(); + }); + } + + function getImageUrl(localUser) { + if (connectUser && connectUser.ImageUrl) { + return { url: connectUser.ImageUrl }; - if (localUser && localUser.PrimaryImageTag) { - return { - url: self.getApiClient(localUser).getUserImageUrl(localUser.Id, { - tag: localUser.PrimaryImageTag, - type: "Primary" - }), - supportsParams: !0 - } - } + } + + if (localUser && localUser.PrimaryImageTag) { return { - url: null, - supportsParams: !1 - } + url: self.getApiClient(localUser).getUserImageUrl(localUser.Id, { + tag: localUser.PrimaryImageTag, + type: "Primary" + }), + supportsParams: true + }; } - function logoutOfServer(apiClient) { - var serverInfo = apiClient.serverInfo() || {}, - logoutInfo = { - serverId: serverInfo.Id - }; - return apiClient.logout().then(function() { - events.trigger(self, "localusersignedout", [logoutInfo]) - }, function() { - events.trigger(self, "localusersignedout", [logoutInfo]) - }) - } + return { + url: null, + supportsParams: false + }; + } - function getConnectServers(credentials) { - return console.log("Begin getConnectServers"), credentials.ConnectAccessToken && credentials.ConnectUserId ? ajax({ + function logoutOfServer(apiClient) { + var serverInfo = apiClient.serverInfo() || {}; + var logoutInfo = { + serverId: serverInfo.Id + }; + return apiClient.logout().then(function () { + events.trigger(self, "localusersignedout", [logoutInfo]); + }, function () { + events.trigger(self, "localusersignedout", [logoutInfo]); + }); + } + + function getConnectServers(credentials) { + console.log("Begin getConnectServers"); + + if (credentials.ConnectAccessToken && credentials.ConnectUserId) { + return ajax({ type: "GET", url: "https://connect.emby.media/service/servers?userId=" + credentials.ConnectUserId, dataType: "json", @@ -229,8 +377,8 @@ define(["events", "apiclient", "appStorage"], function(events, apiClientFactory, "X-Application": appName + "/" + appVersion, "X-Connect-UserToken": credentials.ConnectAccessToken } - }).then(function(servers) { - return servers.map(function(i) { + }).then(function (servers) { + return servers.map(function (i) { return { ExchangeToken: i.AccessKey, ConnectServerId: i.Id, @@ -239,307 +387,542 @@ define(["events", "apiclient", "appStorage"], function(events, apiClientFactory, RemoteAddress: i.Url, LocalAddress: i.LocalAddress, UserLinkType: "guest" === (i.UserType || "").toLowerCase() ? "Guest" : "LinkedUser" - } - }) - }, function() { - return credentials.Servers.slice(0).filter(function(s) { - return s.ExchangeToken - }) - }) : Promise.resolve([]) - } - - function filterServers(servers, connectServers) { - return servers.filter(function(server) { - return !server.ExchangeToken || connectServers.filter(function(connectServer) { - return server.Id === connectServer.Id - }).length > 0 - }) - } - - function findServers() { - return new Promise(function(resolve, reject) { - var onFinish = function(foundServers) { - var servers = foundServers.map(function(foundServer) { - var info = { - Id: foundServer.Id, - LocalAddress: convertEndpointAddressToManualAddress(foundServer) || foundServer.Address, - Name: foundServer.Name - }; - return info.LastConnectionMode = info.ManualAddress ? ConnectionMode.Manual : ConnectionMode.Local, info - }); - resolve(servers) - }; - - if (window.NativeShell && typeof window.NativeShell.findServers === 'function') { - window.NativeShell.findServers(1e3).then(onFinish, function() { - onFinish([]) - }); - } else { - resolve([]); - } + }; + }); + }, function () { + return credentials.Servers.slice(0).filter(function (s) { + return s.ExchangeToken; + }); }); } - function convertEndpointAddressToManualAddress(info) { - if (info.Address && info.EndpointAddress) { - var address = info.EndpointAddress.split(":")[0], - parts = info.Address.split(":"); - if (parts.length > 1) { - var portString = parts[parts.length - 1]; - isNaN(parseInt(portString)) || (address += ":" + portString) - } - return normalizeAddress(address) + return Promise.resolve([]); + } + + function filterServers(servers, connectServers) { + return servers.filter(function (server) { + return !server.ExchangeToken || connectServers.filter(function (connectServer) { + return server.Id === connectServer.Id; + }).length > 0; + }); + } + + function findServers() { + return new Promise(function (resolve, reject) { + var onFinish = function (foundServers) { + var servers = foundServers.map(function (foundServer) { + var info = { + Id: foundServer.Id, + LocalAddress: convertEndpointAddressToManualAddress(foundServer) || foundServer.Address, + Name: foundServer.Name + }; + info.LastConnectionMode = info.ManualAddress ? ConnectionMode.Manual : ConnectionMode.Local; + return info; + }); + resolve(servers); + }; + + if (window.NativeShell && typeof window.NativeShell.findServers === 'function') { + window.NativeShell.findServers(1e3).then(onFinish, function () { + onFinish([]); + }); + } else { + resolve([]); } - return null + }); + } + + function convertEndpointAddressToManualAddress(info) { + if (info.Address && info.EndpointAddress) { + var address = info.EndpointAddress.split(":")[0]; + var parts = info.Address.split(":"); + + if (parts.length > 1) { + var portString = parts[parts.length - 1]; + + if (!isNaN(parseInt(portString))) { + address += ":" + portString; + } + } + + return normalizeAddress(address); } - function getTryConnectPromise(url, connectionMode, state, resolve, reject) { - console.log("getTryConnectPromise " + url), ajax({ - url: getEmbyServerUrl(url, "system/info/public"), - timeout: defaultTimeout, - type: "GET", - dataType: "json" - }).then(function(result) { - state.resolved || (state.resolved = !0, console.log("Reconnect succeeded to " + url), resolve({ + return null; + } + + function getTryConnectPromise(url, connectionMode, state, resolve, reject) { + console.log("getTryConnectPromise " + url); + ajax({ + url: getEmbyServerUrl(url, "system/info/public"), + timeout: defaultTimeout, + type: "GET", + dataType: "json" + }).then(function (result) { + if (!state.resolved) { + state.resolved = true; + console.log("Reconnect succeeded to " + url); + resolve({ url: url, connectionMode: connectionMode, data: result - })) - }, function() { - state.resolved || (console.log("Reconnect failed to " + url), ++state.rejects >= state.numAddresses && reject()) - }) - } + }); + } + }, function () { + if (!state.resolved) { + console.log("Reconnect failed to " + url); - function tryReconnect(serverInfo) { - var addresses = [], - addressesStrings = []; - return !serverInfo.manualAddressOnly && serverInfo.LocalAddress && -1 === addressesStrings.indexOf(serverInfo.LocalAddress) && (addresses.push({ + if (++state.rejects >= state.numAddresses) { + reject(); + } + } + }); + } + + function tryReconnect(serverInfo) { + var addresses = []; + var addressesStrings = []; + + if (!serverInfo.manualAddressOnly && serverInfo.LocalAddress && -1 === addressesStrings.indexOf(serverInfo.LocalAddress)) { + addresses.push({ url: serverInfo.LocalAddress, mode: ConnectionMode.Local, timeout: 0 - }), addressesStrings.push(addresses[addresses.length - 1].url)), serverInfo.ManualAddress && -1 === addressesStrings.indexOf(serverInfo.ManualAddress) && (addresses.push({ + }); + addressesStrings.push(addresses[addresses.length - 1].url); + } + + if (serverInfo.ManualAddress && -1 === addressesStrings.indexOf(serverInfo.ManualAddress)) { + addresses.push({ url: serverInfo.ManualAddress, mode: ConnectionMode.Manual, timeout: 100 - }), addressesStrings.push(addresses[addresses.length - 1].url)), !serverInfo.manualAddressOnly && serverInfo.RemoteAddress && -1 === addressesStrings.indexOf(serverInfo.RemoteAddress) && (addresses.push({ + }); + addressesStrings.push(addresses[addresses.length - 1].url); + } + + if (!serverInfo.manualAddressOnly && serverInfo.RemoteAddress && -1 === addressesStrings.indexOf(serverInfo.RemoteAddress)) { + addresses.push({ url: serverInfo.RemoteAddress, mode: ConnectionMode.Remote, timeout: 200 - }), addressesStrings.push(addresses[addresses.length - 1].url)), console.log("tryReconnect: " + addressesStrings.join("|")), new Promise(function(resolve, reject) { - var state = {}; - state.numAddresses = addresses.length, state.rejects = 0, addresses.map(function(url) { - setTimeout(function() { - state.resolved || getTryConnectPromise(url.url, url.mode, state, resolve, reject) - }, url.timeout) - }) - }) - } - - function onSuccessfulConnection(server, systemInfo, connectionMode, serverUrl, options, resolve) { - var credentials = credentialProvider.credentials(); - options = options || {}, credentials.ConnectAccessToken && !1 !== options.enableAutoLogin ? ensureConnectUser(credentials).then(function() { - server.ExchangeToken ? addAuthenticationInfoFromConnect(server, serverUrl, credentials).then(function() { - afterConnectValidated(server, credentials, systemInfo, connectionMode, serverUrl, !0, options, resolve) - }, function() { - afterConnectValidated(server, credentials, systemInfo, connectionMode, serverUrl, !0, options, resolve) - }) : afterConnectValidated(server, credentials, systemInfo, connectionMode, serverUrl, !0, options, resolve) - }) : afterConnectValidated(server, credentials, systemInfo, connectionMode, serverUrl, !0, options, resolve) - } - - function afterConnectValidated(server, credentials, systemInfo, connectionMode, serverUrl, verifyLocalAuthentication, options, resolve) { - if (options = options || {}, !1 === options.enableAutoLogin) server.UserId = null, server.AccessToken = null; - else if (verifyLocalAuthentication && server.AccessToken && !1 !== options.enableAutoLogin) return void validateAuthentication(server, serverUrl).then(function() { - afterConnectValidated(server, credentials, systemInfo, connectionMode, serverUrl, !1, options, resolve) }); - updateServerInfo(server, systemInfo), server.LastConnectionMode = connectionMode, !1 !== options.updateDateLastAccessed && (server.DateLastAccessed = (new Date).getTime()), credentialProvider.addOrUpdateServer(credentials.Servers, server), credentialProvider.credentials(credentials); - var result = { - Servers: [] - }; - result.ApiClient = self._getOrAddApiClient(server, serverUrl), result.ApiClient.setSystemInfo(systemInfo), result.State = server.AccessToken && !1 !== options.enableAutoLogin ? "SignedIn" : "ServerSignIn", result.Servers.push(server), result.ApiClient.enableAutomaticBitrateDetection = options.enableAutomaticBitrateDetection, result.ApiClient.updateServerInfo(server, serverUrl); - var resolveActions = function() { - resolve(result), events.trigger(self, "connected", [result]) - }; - "SignedIn" === result.State ? (afterConnected(result.ApiClient, options), result.ApiClient.getCurrentUser().then(function(user) { - onLocalUserSignIn(server, serverUrl, user).then(resolveActions, resolveActions) - }, resolveActions)) : resolveActions() + addressesStrings.push(addresses[addresses.length - 1].url); } - function getCacheKey(feature, apiClient, options) { - options = options || {}; - var viewOnly = options.viewOnly, - cacheKey = "regInfo-" + apiClient.serverId(); - return viewOnly && (cacheKey += "-viewonly"), cacheKey + console.log("tryReconnect: " + addressesStrings.join("|")); + return new Promise(function (resolve, reject) { + var state = {}; + state.numAddresses = addresses.length; + state.rejects = 0; + addresses.map(function (url) { + setTimeout(function () { + if (!state.resolved) { + getTryConnectPromise(url.url, url.mode, state, resolve, reject); + } + }, url.timeout); + }); + }); + } + + function onSuccessfulConnection(server, systemInfo, connectionMode, serverUrl, options, resolve) { + var credentials = credentialProvider.credentials(); + options = options || {}; + + if (credentials.ConnectAccessToken && false !== options.enableAutoLogin) { + ensureConnectUser(credentials).then(function () { + if (server.ExchangeToken) { + addAuthenticationInfoFromConnect(server, serverUrl, credentials).then(function () { + afterConnectValidated(server, credentials, systemInfo, connectionMode, serverUrl, true, options, resolve); + }, function () { + afterConnectValidated(server, credentials, systemInfo, connectionMode, serverUrl, true, options, resolve); + }); + } else { + afterConnectValidated(server, credentials, systemInfo, connectionMode, serverUrl, true, options, resolve); + } + }); + } else { + afterConnectValidated(server, credentials, systemInfo, connectionMode, serverUrl, true, options, resolve); + } + } + + function afterConnectValidated(server, credentials, systemInfo, connectionMode, serverUrl, verifyLocalAuthentication, options, resolve) { + if (options = options || {}, false === options.enableAutoLogin) { + server.UserId = null; + server.AccessToken = null; + } else if (verifyLocalAuthentication && server.AccessToken && false !== options.enableAutoLogin) { + return void validateAuthentication(server, serverUrl).then(function () { + afterConnectValidated(server, credentials, systemInfo, connectionMode, serverUrl, false, options, resolve); + }); } - function addAppInfoToConnectRequest(request) { - request.headers = request.headers || {}, request.headers["X-Application"] = appName + "/" + appVersion + updateServerInfo(server, systemInfo); + server.LastConnectionMode = connectionMode; + + if (false !== options.updateDateLastAccessed) { + server.DateLastAccessed = new Date().getTime(); } - function exchangePin(pinInfo) { - if (!pinInfo) throw new Error("pinInfo cannot be null"); - var request = { - type: "POST", - url: getConnectUrl("pin/authenticate"), - data: { - deviceId: pinInfo.DeviceId, - pin: pinInfo.Pin - }, - dataType: "json" - }; - return addAppInfoToConnectRequest(request), ajax(request) + credentialProvider.addOrUpdateServer(credentials.Servers, server); + credentialProvider.credentials(credentials); + var result = { + Servers: [] + }; + result.ApiClient = self._getOrAddApiClient(server, serverUrl); + result.ApiClient.setSystemInfo(systemInfo); + result.State = server.AccessToken && false !== options.enableAutoLogin ? "SignedIn" : "ServerSignIn"; + result.Servers.push(server); + result.ApiClient.enableAutomaticBitrateDetection = options.enableAutomaticBitrateDetection; + result.ApiClient.updateServerInfo(server, serverUrl); + + var resolveActions = function () { + resolve(result); + events.trigger(self, "connected", [result]); + }; + + if ("SignedIn" === result.State) { + afterConnected(result.ApiClient, options); + result.ApiClient.getCurrentUser().then(function (user) { + onLocalUserSignIn(server, serverUrl, user).then(resolveActions, resolveActions); + }, resolveActions); + } else { + resolveActions(); } - console.log("Begin ConnectionManager constructor"); - var self = this; - this._apiClients = []; - var connectUser; - self.connectUser = function() { - return connectUser - }, self._minServerVersion = "3.2.33", self.appVersion = function() { - return appVersion - }, self.appName = function() { - return appName - }, self.capabilities = function() { - return capabilities - }, self.deviceId = function() { - return deviceId - }, self.credentialProvider = function() { - return credentialProvider - }, self.connectUserId = function() { - return credentialProvider.credentials().ConnectUserId - }, self.connectToken = function() { - return credentialProvider.credentials().ConnectAccessToken - }, self.getServerInfo = function(id) { - return credentialProvider.credentials().Servers.filter(function(s) { - return s.Id === id - })[0] - }, self.getLastUsedServer = function() { - var servers = credentialProvider.credentials().Servers; - return servers.sort(function(a, b) { - return (b.DateLastAccessed || 0) - (a.DateLastAccessed || 0) - }), servers.length ? servers[0] : null - }, self.addApiClient = function(apiClient) { + } + + function getCacheKey(feature, apiClient, options) { + options = options || {}; + var viewOnly = options.viewOnly; + var cacheKey = "regInfo-" + apiClient.serverId(); + + if (viewOnly) { + cacheKey += "-viewonly"; + } + + return cacheKey; + } + + function addAppInfoToConnectRequest(request) { + request.headers = request.headers || {}; + request.headers["X-Application"] = appName + "/" + appVersion; + } + + function exchangePin(pinInfo) { + if (!pinInfo) { + throw new Error("pinInfo cannot be null"); + } + + var request = { + type: "POST", + url: getConnectUrl("pin/authenticate"), + data: { + deviceId: pinInfo.DeviceId, + pin: pinInfo.Pin + }, + dataType: "json" + }; + addAppInfoToConnectRequest(request); + return ajax(request); + } + + console.log("Begin ConnectionManager constructor"); + var self = this; + this._apiClients = []; + var connectUser; + + self.connectUser = function () { + return connectUser; + }; + + self._minServerVersion = "3.2.33"; + + self.appVersion = function () { + return appVersion; + }; + + self.appName = function () { + return appName; + }; + + self.capabilities = function () { + return capabilities; + }; + + self.deviceId = function () { + return deviceId; + }; + + self.credentialProvider = function () { + return credentialProvider; + }; + + self.connectUserId = function () { + return credentialProvider.credentials().ConnectUserId; + }; + + self.connectToken = function () { + return credentialProvider.credentials().ConnectAccessToken; + }; + + self.getServerInfo = function (id) { + return credentialProvider.credentials().Servers.filter(function (s) { + return s.Id === id; + })[0]; + }; + + self.getLastUsedServer = function () { + var servers = credentialProvider.credentials().Servers; + servers.sort(function (a, b) { + return (b.DateLastAccessed || 0) - (a.DateLastAccessed || 0); + }); + + if (servers.length) { + return servers[0]; + } + + return null; + }; + + self.addApiClient = function (apiClient) { + self._apiClients.push(apiClient); + + var existingServers = credentialProvider.credentials().Servers.filter(function (s) { + return stringEqualsIgnoreCase(s.ManualAddress, apiClient.serverAddress()) || stringEqualsIgnoreCase(s.LocalAddress, apiClient.serverAddress()) || stringEqualsIgnoreCase(s.RemoteAddress, apiClient.serverAddress()); + }); + var existingServer = existingServers.length ? existingServers[0] : apiClient.serverInfo(); + + if (existingServer.DateLastAccessed = new Date().getTime(), existingServer.LastConnectionMode = ConnectionMode.Manual, existingServer.ManualAddress = apiClient.serverAddress(), apiClient.manualAddressOnly && (existingServer.manualAddressOnly = true), apiClient.serverInfo(existingServer), apiClient.onAuthenticated = function (instance, result) { + return onAuthenticated(instance, result, {}, true); + }, !existingServers.length) { + var credentials = credentialProvider.credentials(); + credentials.Servers = [existingServer]; + credentialProvider.credentials(credentials); + } + + events.trigger(self, "apiclientcreated", [apiClient]); + }; + + self.clearData = function () { + console.log("connection manager clearing data"); + connectUser = null; + var credentials = credentialProvider.credentials(); + credentials.ConnectAccessToken = null; + credentials.ConnectUserId = null; + credentials.Servers = []; + credentialProvider.credentials(credentials); + }; + + self._getOrAddApiClient = function (server, serverUrl) { + var apiClient = self.getApiClient(server.Id); + + if (!apiClient) { + apiClient = new apiClientFactory(serverUrl, appName, appVersion, deviceName, deviceId, devicePixelRatio); + self._apiClients.push(apiClient); - var existingServers = credentialProvider.credentials().Servers.filter(function(s) { - return stringEqualsIgnoreCase(s.ManualAddress, apiClient.serverAddress()) || stringEqualsIgnoreCase(s.LocalAddress, apiClient.serverAddress()) || stringEqualsIgnoreCase(s.RemoteAddress, apiClient.serverAddress()) - }), - existingServer = existingServers.length ? existingServers[0] : apiClient.serverInfo(); - if (existingServer.DateLastAccessed = (new Date).getTime(), existingServer.LastConnectionMode = ConnectionMode.Manual, existingServer.ManualAddress = apiClient.serverAddress(), apiClient.manualAddressOnly && (existingServer.manualAddressOnly = !0), apiClient.serverInfo(existingServer), apiClient.onAuthenticated = function(instance, result) { - return onAuthenticated(instance, result, {}, !0) - }, !existingServers.length) { - var credentials = credentialProvider.credentials(); - credentials.Servers = [existingServer], credentialProvider.credentials(credentials) - } - events.trigger(self, "apiclientcreated", [apiClient]) - }, self.clearData = function() { - console.log("connection manager clearing data"), connectUser = null; - var credentials = credentialProvider.credentials(); - credentials.ConnectAccessToken = null, credentials.ConnectUserId = null, credentials.Servers = [], credentialProvider.credentials(credentials) - }, self._getOrAddApiClient = function(server, serverUrl) { - var apiClient = self.getApiClient(server.Id); - return apiClient || (apiClient = new apiClientFactory(serverUrl, appName, appVersion, deviceName, deviceId, devicePixelRatio), self._apiClients.push(apiClient), apiClient.serverInfo(server), apiClient.onAuthenticated = function(instance, result) { - return onAuthenticated(instance, result, {}, !0) - }, events.trigger(self, "apiclientcreated", [apiClient])), console.log("returning instance from getOrAddApiClient"), apiClient - }, self.getOrCreateApiClient = function(serverId) { - var credentials = credentialProvider.credentials(), - servers = credentials.Servers.filter(function(s) { - return stringEqualsIgnoreCase(s.Id, serverId) + + apiClient.serverInfo(server); + + apiClient.onAuthenticated = function (instance, result) { + return onAuthenticated(instance, result, {}, true); + }; + + events.trigger(self, "apiclientcreated", [apiClient]); + } + + console.log("returning instance from getOrAddApiClient"); + return apiClient; + }; + + self.getOrCreateApiClient = function (serverId) { + var credentials = credentialProvider.credentials(); + var servers = credentials.Servers.filter(function (s) { + return stringEqualsIgnoreCase(s.Id, serverId); + }); + + if (!servers.length) { + throw new Error("Server not found: " + serverId); + } + + var server = servers[0]; + return self._getOrAddApiClient(server, getServerAddress(server, server.LastConnectionMode)); + }; + + self.user = function (apiClient) { + return new Promise(function (resolve, reject) { + function onLocalUserDone(e) { + var image = getImageUrl(localUser); + resolve({ + localUser: localUser, + name: connectUser ? connectUser.Name : localUser ? localUser.Name : null, + imageUrl: image.url, + supportsImageParams: image.supportsParams, + connectUser: connectUser }); - if (!servers.length) throw new Error("Server not found: " + serverId); - var server = servers[0]; - return self._getOrAddApiClient(server, getServerAddress(server, server.LastConnectionMode)) - }, self.user = function(apiClient) { - return new Promise(function(resolve, reject) { - function onLocalUserDone(e) { - var image = getImageUrl(localUser); - resolve({ - localUser: localUser, - name: connectUser ? connectUser.Name : localUser ? localUser.Name : null, - imageUrl: image.url, - supportsImageParams: image.supportsParams, - connectUser: connectUser - }) + } + + function onEnsureConnectUserDone() { + if (apiClient && apiClient.getCurrentUserId()) { + apiClient.getCurrentUser().then(function (u) { + localUser = u; + onLocalUserDone(); + }, onLocalUserDone); + } else { + onLocalUserDone(); + } + } + + var localUser; + var credentials = credentialProvider.credentials(); + + if (!credentials.ConnectUserId || !credentials.ConnectAccessToken || apiClient && apiClient.getCurrentUserId()) { + onEnsureConnectUserDone(); + } else { + ensureConnectUser(credentials).then(onEnsureConnectUserDone, onEnsureConnectUserDone); + } + }); + }; + + self.logout = function () { + console.log("begin connectionManager loguot"); + var promises = []; + + for (var i = 0, length = self._apiClients.length; i < length; i++) { + var apiClient = self._apiClients[i]; + + if (apiClient.accessToken()) { + promises.push(logoutOfServer(apiClient)); + } + } + + return Promise.all(promises).then(function () { + var credentials = credentialProvider.credentials(); + var servers = credentials.Servers.filter(function (u) { + return "Guest" !== u.UserLinkType; + }); + + for (var j = 0, numServers = servers.length; j < numServers; j++) { + var server = servers[j]; + server.UserId = null; + server.AccessToken = null; + server.ExchangeToken = null; + } + + credentials.Servers = servers; + credentials.ConnectAccessToken = null; + credentials.ConnectUserId = null; + credentialProvider.credentials(credentials); + + if (connectUser) { + connectUser = null; + events.trigger(self, "connectusersignedout"); + } + }); + }; + + self.getSavedServers = function () { + var credentials = credentialProvider.credentials(); + var servers = credentials.Servers.slice(0); + servers.sort(function (a, b) { + return (b.DateLastAccessed || 0) - (a.DateLastAccessed || 0); + }); + return servers; + }; + + self.getAvailableServers = function () { + console.log("Begin getAvailableServers"); + var credentials = credentialProvider.credentials(); + return Promise.all([getConnectServers(credentials), findServers()]).then(function (responses) { + var connectServers = responses[0]; + var foundServers = responses[1]; + var servers = credentials.Servers.slice(0); + mergeServers(credentialProvider, servers, foundServers); + mergeServers(credentialProvider, servers, connectServers); + servers = filterServers(servers, connectServers); + servers.sort(function (a, b) { + return (b.DateLastAccessed || 0) - (a.DateLastAccessed || 0); + }); + credentials.Servers = servers; + credentialProvider.credentials(credentials); + return servers; + }); + }; + + self.connectToServers = function (servers, options) { + console.log("Begin connectToServers, with " + servers.length + " servers"); + var firstServer = servers.length ? servers[0] : null; + + if (firstServer) { + return self.connectToServer(firstServer, options).then(function (result) { + if ("Unavailable" === result.State) { + result.State = "ServerSelection"; } - function onEnsureConnectUserDone() { - apiClient && apiClient.getCurrentUserId() ? apiClient.getCurrentUser().then(function(u) { - localUser = u, onLocalUserDone() - }, onLocalUserDone) : onLocalUserDone() - } - var localUser, credentials = credentialProvider.credentials(); - !credentials.ConnectUserId || !credentials.ConnectAccessToken || apiClient && apiClient.getCurrentUserId() ? onEnsureConnectUserDone() : ensureConnectUser(credentials).then(onEnsureConnectUserDone, onEnsureConnectUserDone) - }) - }, self.logout = function() { - console.log("begin connectionManager loguot"); - for (var promises = [], i = 0, length = self._apiClients.length; i < length; i++) { - var apiClient = self._apiClients[i]; - apiClient.accessToken() && promises.push(logoutOfServer(apiClient)) - } - return Promise.all(promises).then(function() { - for (var credentials = credentialProvider.credentials(), servers = credentials.Servers.filter(function(u) { - return "Guest" !== u.UserLinkType - }), j = 0, numServers = servers.length; j < numServers; j++) { - var server = servers[j]; - server.UserId = null, server.AccessToken = null, server.ExchangeToken = null - } - credentials.Servers = servers, credentials.ConnectAccessToken = null, credentials.ConnectUserId = null, credentialProvider.credentials(credentials), connectUser && (connectUser = null, events.trigger(self, "connectusersignedout")) - }) - }, self.getSavedServers = function() { - var credentials = credentialProvider.credentials(), - servers = credentials.Servers.slice(0); - return servers.sort(function(a, b) { - return (b.DateLastAccessed || 0) - (a.DateLastAccessed || 0) - }), servers - }, self.getAvailableServers = function() { - console.log("Begin getAvailableServers"); - var credentials = credentialProvider.credentials(); - return Promise.all([getConnectServers(credentials), findServers()]).then(function(responses) { - var connectServers = responses[0], - foundServers = responses[1], - servers = credentials.Servers.slice(0); - return mergeServers(credentialProvider, servers, foundServers), mergeServers(credentialProvider, servers, connectServers), servers = filterServers(servers, connectServers), servers.sort(function(a, b) { - return (b.DateLastAccessed || 0) - (a.DateLastAccessed || 0) - }), credentials.Servers = servers, credentialProvider.credentials(credentials), servers - }) - }, self.connectToServers = function(servers, options) { - console.log("Begin connectToServers, with " + servers.length + " servers"); - var firstServer = servers.length ? servers[0] : null; - return firstServer ? self.connectToServer(firstServer, options).then(function(result) { - return "Unavailable" === result.State && (result.State = "ServerSelection"), console.log("resolving connectToServers with result.State: " + result.State), result - }) : Promise.resolve({ - Servers: servers, - State: servers.length || self.connectUser() ? "ServerSelection" : "ConnectSignIn", - ConnectUser: self.connectUser() - }) - }, self.connectToServer = function(server, options) { - return console.log("begin connectToServer"), new Promise(function(resolve, reject) { - options = options || {}, tryReconnect(server).then(function(result) { - var serverUrl = result.url, - connectionMode = result.connectionMode; - result = result.data, 1 === compareVersions(self.minServerVersion(), result.Version) ? (console.log("minServerVersion requirement not met. Server version: " + result.Version), resolve({ + console.log("resolving connectToServers with result.State: " + result.State); + return result; + }); + } + + return Promise.resolve({ + Servers: servers, + State: servers.length || self.connectUser() ? "ServerSelection" : "ConnectSignIn", + ConnectUser: self.connectUser() + }); + }; + + self.connectToServer = function (server, options) { + console.log("begin connectToServer"); + return new Promise(function (resolve, reject) { + options = options || {}; + tryReconnect(server).then(function (result) { + var serverUrl = result.url; + var connectionMode = result.connectionMode; + result = result.data; + + if (1 === compareVersions(self.minServerVersion(), result.Version)) { + console.log("minServerVersion requirement not met. Server version: " + result.Version); + resolve({ State: "ServerUpdateNeeded", Servers: [server] - })) : server.Id && result.Id !== server.Id ? (console.log("http request succeeded, but found a different server Id than what was expected"), resolveFailure(self, resolve)) : onSuccessfulConnection(server, result, connectionMode, serverUrl, options, resolve) - }, function() { - resolveFailure(self, resolve) - }) - }) - }, self.connectToAddress = function(address, options) { - function onFail() { - return console.log("connectToAddress " + address + " failed"), Promise.resolve({ - State: "Unavailable", - ConnectUser: instance.connectUser() - }) - } - if (!address) return Promise.reject(); - address = normalizeAddress(address); - var instance = this, - server = { - ManualAddress: address, - LastConnectionMode: ConnectionMode.Manual - }; - return self.connectToServer(server, options).catch(onFail) - }, self.loginToConnect = function(username, password) { - return username && password ? ajax({ + }); + } else { + if (server.Id && result.Id !== server.Id) { + console.log("http request succeeded, but found a different server Id than what was expected"); + resolveFailure(self, resolve); + } else { + onSuccessfulConnection(server, result, connectionMode, serverUrl, options, resolve); + } + } + }, function () { + resolveFailure(self, resolve); + }); + }); + }; + + self.connectToAddress = function (address, options) { + function onFail() { + console.log("connectToAddress " + address + " failed"); + return Promise.resolve({ + State: "Unavailable", + ConnectUser: instance.connectUser() + }); + } + + if (!address) { + return Promise.reject(); + } + + address = normalizeAddress(address); + var instance = this; + var server = { + ManualAddress: address, + LastConnectionMode: ConnectionMode.Manual + }; + return self.connectToServer(server, options).catch(onFail); + }; + + self.loginToConnect = function (username, password) { + if (username && password) { + return ajax({ type: "POST", url: "https://connect.emby.media/service/user/authenticate", data: { @@ -551,197 +934,341 @@ define(["events", "apiclient", "appStorage"], function(events, apiClientFactory, headers: { "X-Application": appName + "/" + appVersion } - }).then(function(result) { + }).then(function (result) { var credentials = credentialProvider.credentials(); - return credentials.ConnectAccessToken = result.AccessToken, credentials.ConnectUserId = result.User.Id, credentialProvider.credentials(credentials), onConnectUserSignIn(result.User), result - }) : Promise.reject() - }, self.signupForConnect = function(options) { - var email = options.email, - username = options.username, - password = options.password, - passwordConfirm = options.passwordConfirm; - if (!email) return Promise.reject({ + credentials.ConnectAccessToken = result.AccessToken; + credentials.ConnectUserId = result.User.Id; + credentialProvider.credentials(credentials); + onConnectUserSignIn(result.User); + return result; + }); + } + + return Promise.reject(); + }; + + self.signupForConnect = function (options) { + var email = options.email; + var username = options.username; + var password = options.password; + var passwordConfirm = options.passwordConfirm; + + if (!email) { + return Promise.reject({ errorCode: "invalidinput" }); - if (!username) return Promise.reject({ + } + + if (!username) { + return Promise.reject({ errorCode: "invalidinput" }); - if (!password) return Promise.reject({ + } + + if (!password) { + return Promise.reject({ errorCode: "invalidinput" }); - if (!passwordConfirm) return Promise.reject({ + } + + if (!passwordConfirm) { + return Promise.reject({ errorCode: "passwordmatch" }); - if (password !== passwordConfirm) return Promise.reject({ + } + + if (password !== passwordConfirm) { + return Promise.reject({ errorCode: "passwordmatch" }); - var data = { - email: email, - userName: username, - rawpw: password - }; - return options.grecaptcha && (data.grecaptcha = options.grecaptcha), ajax({ - type: "POST", - url: "https://connect.emby.media/service/register", - data: data, - dataType: "json", - contentType: "application/x-www-form-urlencoded; charset=UTF-8", - headers: { - "X-Application": appName + "/" + appVersion, - "X-CONNECT-TOKEN": "CONNECT-REGISTER" + } + + var data = { + email: email, + userName: username, + rawpw: password + }; + + if (options.grecaptcha) { + data.grecaptcha = options.grecaptcha; + } + + return ajax({ + type: "POST", + url: "https://connect.emby.media/service/register", + data: data, + dataType: "json", + contentType: "application/x-www-form-urlencoded; charset=UTF-8", + headers: { + "X-Application": appName + "/" + appVersion, + "X-CONNECT-TOKEN": "CONNECT-REGISTER" + } + }).catch(function (response) { + try { + return response.json(); + } catch (err) { + throw err; + } + }).then(function (result) { + if (result && result.Status) { + if ("SUCCESS" === result.Status) { + return Promise.resolve(result); } - }).catch(function(response) { - try { - return response.json() - } catch (err) { - throw err - } - }).then(function(result) { - if (result && result.Status) return "SUCCESS" === result.Status ? Promise.resolve(result) : Promise.reject({ + + return Promise.reject({ errorCode: result.Status }); - Promise.reject() - }) - }, self.getUserInvitations = function() { - var connectToken = self.connectToken(); - if (!connectToken) throw new Error("null connectToken"); - if (!self.connectUserId()) throw new Error("null connectUserId"); - return ajax({ - type: "GET", - url: "https://connect.emby.media/service/servers?userId=" + self.connectUserId() + "&status=Waiting", - dataType: "json", - headers: { - "X-Connect-UserToken": connectToken, - "X-Application": appName + "/" + appVersion - } - }) - }, self.deleteServer = function(serverId) { - if (!serverId) throw new Error("null serverId"); - var server = credentialProvider.credentials().Servers.filter(function(s) { - return s.Id === serverId - }); - return server = server.length ? server[0] : null, new Promise(function(resolve, reject) { - function onDone() { - var credentials = credentialProvider.credentials(); - credentials.Servers = credentials.Servers.filter(function(s) { - return s.Id !== serverId - }), credentialProvider.credentials(credentials), resolve() - } - if (!server.ConnectServerId) return void onDone(); - var connectToken = self.connectToken(), - connectUserId = self.connectUserId(); - if (!connectToken || !connectUserId) return void onDone(); - ajax({ - type: "DELETE", - url: "https://connect.emby.media/service/serverAuthorizations?serverId=" + server.ConnectServerId + "&userId=" + connectUserId, - headers: { - "X-Connect-UserToken": connectToken, - "X-Application": appName + "/" + appVersion - } - }).then(onDone, onDone) - }) - }, self.rejectServer = function(serverId) { - var connectToken = self.connectToken(); - if (!serverId) throw new Error("null serverId"); - if (!connectToken) throw new Error("null connectToken"); - if (!self.connectUserId()) throw new Error("null connectUserId"); - var url = "https://connect.emby.media/service/serverAuthorizations?serverId=" + serverId + "&userId=" + self.connectUserId(); - return fetch(url, { - method: "DELETE", - headers: { - "X-Connect-UserToken": connectToken, - "X-Application": appName + "/" + appVersion - } - }) - }, self.acceptServer = function(serverId) { - var connectToken = self.connectToken(); - if (!serverId) throw new Error("null serverId"); - if (!connectToken) throw new Error("null connectToken"); - if (!self.connectUserId()) throw new Error("null connectUserId"); - return ajax({ - type: "GET", - url: "https://connect.emby.media/service/ServerAuthorizations/accept?serverId=" + serverId + "&userId=" + self.connectUserId(), - headers: { - "X-Connect-UserToken": connectToken, - "X-Application": appName + "/" + appVersion - } - }) - }, self.resetRegistrationInfo = function(apiClient) { - var cacheKey = getCacheKey("themes", apiClient, { - viewOnly: !0 - }); - appStorage.removeItem(cacheKey), cacheKey = getCacheKey("themes", apiClient, { - viewOnly: !1 - }), appStorage.removeItem(cacheKey) - }, self.getRegistrationInfo = function(feature, apiClient, options) { - var cacheKey = getCacheKey(feature, apiClient, options); - appStorage.setItem(cacheKey, JSON.stringify({ - lastValidDate: new Date().getTime(), - deviceId: self.deviceId() - })); - return Promise.resolve(); - }, self.createPin = function() { - var request = { - type: "POST", - url: getConnectUrl("pin"), - data: { - deviceId: deviceId - }, - dataType: "json" - }; - return addAppInfoToConnectRequest(request), ajax(request) - }, self.getPinStatus = function(pinInfo) { - if (!pinInfo) throw new Error("pinInfo cannot be null"); - var queryString = { - deviceId: pinInfo.DeviceId, - pin: pinInfo.Pin - }, - request = { - type: "GET", - url: getConnectUrl("pin") + "?" + paramsToString(queryString), - dataType: "json" - }; - return addAppInfoToConnectRequest(request), ajax(request) - }, self.exchangePin = function(pinInfo) { - if (!pinInfo) throw new Error("pinInfo cannot be null"); - return exchangePin(pinInfo).then(function(result) { - var credentials = credentialProvider.credentials(); - return credentials.ConnectAccessToken = result.AccessToken, credentials.ConnectUserId = result.UserId, credentialProvider.credentials(credentials), ensureConnectUser(credentials) - }) - } + } + + Promise.reject(); + }); }; - return ConnectionManager.prototype.connect = function(options) { + + self.getUserInvitations = function () { + var connectToken = self.connectToken(); + + if (!connectToken) { + throw new Error("null connectToken"); + } + + if (!self.connectUserId()) { + throw new Error("null connectUserId"); + } + + return ajax({ + type: "GET", + url: "https://connect.emby.media/service/servers?userId=" + self.connectUserId() + "&status=Waiting", + dataType: "json", + headers: { + "X-Connect-UserToken": connectToken, + "X-Application": appName + "/" + appVersion + } + }); + }; + + self.deleteServer = function (serverId) { + if (!serverId) { + throw new Error("null serverId"); + } + + var server = credentialProvider.credentials().Servers.filter(function (s) { + return s.Id === serverId; + }); + server = server.length ? server[0] : null; + return new Promise(function (resolve, reject) { + function onDone() { + var credentials = credentialProvider.credentials(); + credentials.Servers = credentials.Servers.filter(function (s) { + return s.Id !== serverId; + }); + credentialProvider.credentials(credentials); + resolve(); + } + + if (!server.ConnectServerId) { + return void onDone(); + } + + var connectToken = self.connectToken(); + var connectUserId = self.connectUserId(); + + if (!connectToken || !connectUserId) { + return void onDone(); + } + + ajax({ + type: "DELETE", + url: "https://connect.emby.media/service/serverAuthorizations?serverId=" + server.ConnectServerId + "&userId=" + connectUserId, + headers: { + "X-Connect-UserToken": connectToken, + "X-Application": appName + "/" + appVersion + } + }).then(onDone, onDone); + }); + }; + + self.rejectServer = function (serverId) { + var connectToken = self.connectToken(); + + if (!serverId) { + throw new Error("null serverId"); + } + + if (!connectToken) { + throw new Error("null connectToken"); + } + + if (!self.connectUserId()) { + throw new Error("null connectUserId"); + } + + var url = "https://connect.emby.media/service/serverAuthorizations?serverId=" + serverId + "&userId=" + self.connectUserId(); + return fetch(url, { + method: "DELETE", + headers: { + "X-Connect-UserToken": connectToken, + "X-Application": appName + "/" + appVersion + } + }); + }; + + self.acceptServer = function (serverId) { + var connectToken = self.connectToken(); + + if (!serverId) { + throw new Error("null serverId"); + } + + if (!connectToken) { + throw new Error("null connectToken"); + } + + if (!self.connectUserId()) { + throw new Error("null connectUserId"); + } + + return ajax({ + type: "GET", + url: "https://connect.emby.media/service/ServerAuthorizations/accept?serverId=" + serverId + "&userId=" + self.connectUserId(), + headers: { + "X-Connect-UserToken": connectToken, + "X-Application": appName + "/" + appVersion + } + }); + }; + + self.resetRegistrationInfo = function (apiClient) { + var cacheKey = getCacheKey("themes", apiClient, { + viewOnly: true + }); + appStorage.removeItem(cacheKey); + cacheKey = getCacheKey("themes", apiClient, { + viewOnly: false + }); + appStorage.removeItem(cacheKey); + }; + + self.getRegistrationInfo = function (feature, apiClient, options) { + var cacheKey = getCacheKey(feature, apiClient, options); + appStorage.setItem(cacheKey, JSON.stringify({ + lastValidDate: new Date().getTime(), + deviceId: self.deviceId() + })); + return Promise.resolve(); + }; + + self.createPin = function () { + var request = { + type: "POST", + url: getConnectUrl("pin"), + data: { + deviceId: deviceId + }, + dataType: "json" + }; + addAppInfoToConnectRequest(request); + return ajax(request); + }; + + self.getPinStatus = function (pinInfo) { + if (!pinInfo) { + throw new Error("pinInfo cannot be null"); + } + + var queryString = { + deviceId: pinInfo.DeviceId, + pin: pinInfo.Pin + }; + var request = { + type: "GET", + url: getConnectUrl("pin") + "?" + paramsToString(queryString), + dataType: "json" + }; + addAppInfoToConnectRequest(request); + return ajax(request); + }; + + self.exchangePin = function (pinInfo) { + if (!pinInfo) { + throw new Error("pinInfo cannot be null"); + } + + return exchangePin(pinInfo).then(function (result) { + var credentials = credentialProvider.credentials(); + credentials.ConnectAccessToken = result.AccessToken; + credentials.ConnectUserId = result.UserId; + credentialProvider.credentials(credentials); + return ensureConnectUser(credentials); + }); + }; + }; + + ConnectionManager.prototype.connect = function (options) { console.log("Begin connect"); var instance = this; - return instance.getAvailableServers().then(function(servers) { - return instance.connectToServers(servers, options) - }) - }, ConnectionManager.prototype.isLoggedIntoConnect = function() { - return !(!this.connectToken() || !this.connectUserId()) - }, ConnectionManager.prototype.getApiClients = function() { - for (var servers = this.getSavedServers(), i = 0, length = servers.length; i < length; i++) { + return instance.getAvailableServers().then(function (servers) { + return instance.connectToServers(servers, options); + }); + }; + + ConnectionManager.prototype.isLoggedIntoConnect = function () { + return !(!this.connectToken() || !this.connectUserId()); + }; + + ConnectionManager.prototype.getApiClients = function () { + var servers = this.getSavedServers(); + + for (var i = 0, length = servers.length; i < length; i++) { var server = servers[i]; - server.Id && this._getOrAddApiClient(server, getServerAddress(server, server.LastConnectionMode)) - } - return this._apiClients - }, ConnectionManager.prototype.getApiClient = function(item) { - if (!item) throw new Error("item or serverId cannot be null"); - return item.ServerId && (item = item.ServerId), this._apiClients.filter(function(a) { - var serverInfo = a.serverInfo(); - return !serverInfo || serverInfo.Id === item - })[0] - }, ConnectionManager.prototype.minServerVersion = function(val) { - return val && (this._minServerVersion = val), this._minServerVersion - }, ConnectionManager.prototype.handleMessageReceived = function(msg) { - var serverId = msg.ServerId; - if (serverId) { - var apiClient = this.getApiClient(serverId); - if (apiClient) { - if ("string" == typeof msg.Data) try { - msg.Data = JSON.parse(msg.Data) - } catch (err) {} - apiClient.handleMessageReceived(msg) + + if (server.Id) { + this._getOrAddApiClient(server, getServerAddress(server, server.LastConnectionMode)); } } - }, ConnectionManager + + return this._apiClients; + }; + + ConnectionManager.prototype.getApiClient = function (item) { + if (!item) { + throw new Error("item or serverId cannot be null"); + } + + if (item.ServerId) { + item = item.ServerId; + } + + return this._apiClients.filter(function (a) { + var serverInfo = a.serverInfo(); + return !serverInfo || serverInfo.Id === item; + })[0]; + }; + + ConnectionManager.prototype.minServerVersion = function (val) { + if (val) { + this._minServerVersion = val; + } + + return this._minServerVersion; + }; + + ConnectionManager.prototype.handleMessageReceived = function (msg) { + var serverId = msg.ServerId; + + if (serverId) { + var apiClient = this.getApiClient(serverId); + + if (apiClient) { + if ("string" == typeof msg.Data) { + try { + msg.Data = JSON.parse(msg.Data); + } catch (err) {} + } + + apiClient.handleMessageReceived(msg); + } + } + }; + + return ConnectionManager; }); From d5c91f872b0fcafeb1f8aafe170abf991ceacf65 Mon Sep 17 00:00:00 2001 From: grafixeyehero Date: Fri, 11 Oct 2019 18:48:17 +0300 Subject: [PATCH 041/162] commit out to remove --- .../apiclient/connectionmanager.js | 25 +++++++++++-------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/src/bower_components/apiclient/connectionmanager.js b/src/bower_components/apiclient/connectionmanager.js index 073a2e477c..5350cb7449 100644 --- a/src/bower_components/apiclient/connectionmanager.js +++ b/src/bower_components/apiclient/connectionmanager.js @@ -135,9 +135,10 @@ define(["events", "apiclient", "appStorage"], function (events, apiClientFactory }); } - function getConnectUrl(handler) { + //To be remove + /*function getConnectUrl(handler) { return "https://connect.emby.media/service/" + handler; - } + }*/ function replaceAll(originalString, strReplace, strWith) { var reg = new RegExp(strReplace, "ig"); @@ -262,7 +263,8 @@ define(["events", "apiclient", "appStorage"], function (events, apiClientFactory return Promise.resolve(); } - function getConnectUser(userId, accessToken) { + //To be remove + /*function getConnectUser(userId, accessToken) { if (!userId) { throw new Error("null userId"); } @@ -280,7 +282,7 @@ define(["events", "apiclient", "appStorage"], function (events, apiClientFactory "X-Connect-UserToken": accessToken } }); - } + }*/ function addAuthenticationInfoFromConnect(server, serverUrl, credentials) { if (!server.ExchangeToken) { @@ -365,7 +367,8 @@ define(["events", "apiclient", "appStorage"], function (events, apiClientFactory }); } - function getConnectServers(credentials) { + //To be remove + /*function getConnectServers(credentials) { console.log("Begin getConnectServers"); if (credentials.ConnectAccessToken && credentials.ConnectUserId) { @@ -397,7 +400,7 @@ define(["events", "apiclient", "appStorage"], function (events, apiClientFactory } return Promise.resolve([]); - } + }*/ function filterServers(servers, connectServers) { return servers.filter(function (server) { @@ -920,7 +923,8 @@ define(["events", "apiclient", "appStorage"], function (events, apiClientFactory return self.connectToServer(server, options).catch(onFail); }; - self.loginToConnect = function (username, password) { + //To be remove + /*self.loginToConnect = function (username, password) { if (username && password) { return ajax({ type: "POST", @@ -1044,7 +1048,7 @@ define(["events", "apiclient", "appStorage"], function (events, apiClientFactory "X-Application": appName + "/" + appVersion } }); - }; + };*/ self.deleteServer = function (serverId) { if (!serverId) { @@ -1137,7 +1141,8 @@ define(["events", "apiclient", "appStorage"], function (events, apiClientFactory }); }; - self.resetRegistrationInfo = function (apiClient) { + //To be remove + /*self.resetRegistrationInfo = function (apiClient) { var cacheKey = getCacheKey("themes", apiClient, { viewOnly: true }); @@ -1155,7 +1160,7 @@ define(["events", "apiclient", "appStorage"], function (events, apiClientFactory deviceId: self.deviceId() })); return Promise.resolve(); - }; + };*/ self.createPin = function () { var request = { From 1ec2c59e879aded3c1067b7ba75129208e5d3b2e Mon Sep 17 00:00:00 2001 From: grafixeyehero Date: Fri, 11 Oct 2019 18:56:34 +0300 Subject: [PATCH 042/162] To be remove --- src/bower_components/apiclient/connectionmanager.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/bower_components/apiclient/connectionmanager.js b/src/bower_components/apiclient/connectionmanager.js index 5350cb7449..7d0d433fa6 100644 --- a/src/bower_components/apiclient/connectionmanager.js +++ b/src/bower_components/apiclient/connectionmanager.js @@ -1048,7 +1048,7 @@ define(["events", "apiclient", "appStorage"], function (events, apiClientFactory "X-Application": appName + "/" + appVersion } }); - };*/ + }; self.deleteServer = function (serverId) { if (!serverId) { @@ -1141,8 +1141,7 @@ define(["events", "apiclient", "appStorage"], function (events, apiClientFactory }); }; - //To be remove - /*self.resetRegistrationInfo = function (apiClient) { + self.resetRegistrationInfo = function (apiClient) { var cacheKey = getCacheKey("themes", apiClient, { viewOnly: true }); From 697c652f7ca233b706671bc3396633091905a0c7 Mon Sep 17 00:00:00 2001 From: grafixeyehero Date: Fri, 11 Oct 2019 20:31:09 +0300 Subject: [PATCH 043/162] remove getconnectservers for promise array --- src/bower_components/apiclient/connectionmanager.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bower_components/apiclient/connectionmanager.js b/src/bower_components/apiclient/connectionmanager.js index 7d0d433fa6..b3ff1fc9e3 100644 --- a/src/bower_components/apiclient/connectionmanager.js +++ b/src/bower_components/apiclient/connectionmanager.js @@ -834,7 +834,7 @@ define(["events", "apiclient", "appStorage"], function (events, apiClientFactory self.getAvailableServers = function () { console.log("Begin getAvailableServers"); var credentials = credentialProvider.credentials(); - return Promise.all([getConnectServers(credentials), findServers()]).then(function (responses) { + return Promise.all([findServers()]).then(function (responses) { var connectServers = responses[0]; var foundServers = responses[1]; var servers = credentials.Servers.slice(0); From 155ad2c6d2b772528fc28c7f524147c3d2ed6a4a Mon Sep 17 00:00:00 2001 From: grafixeyehero Date: Fri, 11 Oct 2019 20:35:12 +0300 Subject: [PATCH 044/162] commit out mergeserver --- src/bower_components/apiclient/connectionmanager.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/bower_components/apiclient/connectionmanager.js b/src/bower_components/apiclient/connectionmanager.js index b3ff1fc9e3..80247f8cb1 100644 --- a/src/bower_components/apiclient/connectionmanager.js +++ b/src/bower_components/apiclient/connectionmanager.js @@ -838,8 +838,8 @@ define(["events", "apiclient", "appStorage"], function (events, apiClientFactory var connectServers = responses[0]; var foundServers = responses[1]; var servers = credentials.Servers.slice(0); - mergeServers(credentialProvider, servers, foundServers); - mergeServers(credentialProvider, servers, connectServers); + //mergeServers(credentialProvider, servers, foundServers); + //mergeServers(credentialProvider, servers, connectServers); servers = filterServers(servers, connectServers); servers.sort(function (a, b) { return (b.DateLastAccessed || 0) - (a.DateLastAccessed || 0); From 19ff6ae97adf6558b4cb1115b419f9113ac5fa88 Mon Sep 17 00:00:00 2001 From: grafixeyehero Date: Fri, 11 Oct 2019 21:30:32 +0300 Subject: [PATCH 045/162] commit out onConnectUserSignIn --- .../apiclient/connectionmanager.js | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/src/bower_components/apiclient/connectionmanager.js b/src/bower_components/apiclient/connectionmanager.js index 80247f8cb1..144733cba7 100644 --- a/src/bower_components/apiclient/connectionmanager.js +++ b/src/bower_components/apiclient/connectionmanager.js @@ -131,7 +131,8 @@ define(["events", "apiclient", "appStorage"], function (events, apiClientFactory return Promise.reject(response); }, function (err) { - throw console.log("ConnectionManager request failed to url: " + request.url), err; + console.log("ConnectionManager request failed to url: " + request.url); + throw err; }); } @@ -153,7 +154,9 @@ define(["events", "apiclient", "appStorage"], function (events, apiClientFactory } address = replaceAll(address, "Http:", "http:"); - return address = replaceAll(address, "Https:", "https:"); + address = replaceAll(address, "Https:", "https:"); + + return address; } function stringEqualsIgnoreCase(str1, str2) { @@ -188,10 +191,12 @@ define(["events", "apiclient", "appStorage"], function (events, apiClientFactory }; var ConnectionManager = function (credentialProvider, appName, appVersion, deviceName, deviceId, capabilities, devicePixelRatio) { - function onConnectUserSignIn(user) { + + //ToDo: Remove + /*function onConnectUserSignIn(user) { connectUser = user; events.trigger(self, "connectusersignedin", [user]); - } + }*/ function onAuthenticated(apiClient, result, options, saveCredentials) { var credentials = credentialProvider.credentials(); @@ -250,7 +255,8 @@ define(["events", "apiclient", "appStorage"], function (events, apiClientFactory return Promise.resolve(); } - if (credentials.ConnectUserId && credentials.ConnectAccessToken) { + // ToDO: Remove + /*if (credentials.ConnectUserId && credentials.ConnectAccessToken) { connectUser = null; return getConnectUser(credentials.ConnectUserId, credentials.ConnectAccessToken).then(function (user) { onConnectUserSignIn(user); @@ -258,7 +264,7 @@ define(["events", "apiclient", "appStorage"], function (events, apiClientFactory }, function () { return Promise.resolve(); }); - } + }*/ return Promise.resolve(); } From bccb1e6147cc9d06cf7f9041d79828bdd570da68 Mon Sep 17 00:00:00 2001 From: redSpoutnik <15638041+redSpoutnik@users.noreply.github.com> Date: Sun, 13 Oct 2019 14:10:51 +0200 Subject: [PATCH 046/162] Fix subtitle sync for .ass --- src/components/htmlvideoplayer/plugin.js | 45 ++++++++++++------------ 1 file changed, 22 insertions(+), 23 deletions(-) diff --git a/src/components/htmlvideoplayer/plugin.js b/src/components/htmlvideoplayer/plugin.js index 79b135fdad..41ddcf56f7 100644 --- a/src/components/htmlvideoplayer/plugin.js +++ b/src/components/htmlvideoplayer/plugin.js @@ -575,35 +575,34 @@ define(['browser', 'require', 'events', 'apphost', 'loading', 'dom', 'playbackMa self.setSubtitleOffset = function(offset) { var offsetValue = parseFloat(offset); - var videoElement = self._mediaElement; - var mediaStreamTextTracks = getMediaStreamTextTracks(self._currentPlayOptions.mediaSource); - Array.from(videoElement.textTracks) - .filter(function(trackElement) { - // get showing .vtt textTacks - var isVttTrackShowing = trackElement.mode === 'showing'; - // get current .ass textTrack - var isAssTrackShowing = ("textTrack" + customTrackIndex) === trackElement.id; - - return isVttTrackShowing || isAssTrackShowing; - }) - .forEach(function(trackElement) { + // if .ass currently rendering + if(currentAssRenderer){ + updateCurrentTrackOffset(offsetValue); + } else { + var videoElement = self._mediaElement; + var mediaStreamTextTracks = getMediaStreamTextTracks(self._currentPlayOptions.mediaSource); - var track = customTrackIndex === -1 ? null : mediaStreamTextTracks.filter(function (t) { - return t.Index === customTrackIndex; - })[0]; + Array.from(videoElement.textTracks) + .filter(function(trackElement) { + // get showing .vtt textTacks + return trackElement.mode === 'showing'; + }) + .forEach(function(trackElement) { - if(track) { - offsetValue = updateCurrentTrackOffset(offsetValue); - var format = (track.Codec || '').toLowerCase(); - if (format !== 'ass' && format !== 'ssa') { + var track = customTrackIndex === -1 ? null : mediaStreamTextTracks.filter(function (t) { + return t.Index === customTrackIndex; + })[0]; + + if(track) { + offsetValue = updateCurrentTrackOffset(offsetValue); setVttSubtitleOffset(trackElement, offsetValue); + } else { + console.log("No available track, cannot apply offset : " + offsetValue); } - } else { - console.log("No available track, cannot apply offset : " + offsetValue); - } - }); + }); + } }; function updateCurrentTrackOffset(offsetValue) { From 1d1042513fc4ca4d0db76b7f6479d64c809cbcaa Mon Sep 17 00:00:00 2001 From: grafixeyehero Date: Sun, 13 Oct 2019 21:33:07 +0300 Subject: [PATCH 047/162] Remove padded class --- src/components/homesections/homesections.js | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/components/homesections/homesections.js b/src/components/homesections/homesections.js index d2106c93bd..3fc549e6e4 100644 --- a/src/components/homesections/homesections.js +++ b/src/components/homesections/homesections.js @@ -560,31 +560,31 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la if (enableScrollX()) { html += '
'; - html += '
'; + html += '
'; } else { - html += '
'; + html += '
'; } - html += '' + globalize.translate('Programs') + ''; - html += '' + globalize.translate('Guide') + ''; - html += '' + globalize.translate('Recordings') + ''; - html += '' + globalize.translate('Schedule') + ''; - html += '' + globalize.translate('Series') + ''; From a971c33b1e057c74b824fdebd632e3275a220ed4 Mon Sep 17 00:00:00 2001 From: grafixeyehero Date: Tue, 15 Oct 2019 20:15:22 +0300 Subject: [PATCH 048/162] update accessschedule Suggested change --- src/components/accessschedule/accessschedule.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/accessschedule/accessschedule.js b/src/components/accessschedule/accessschedule.js index 4733522d56..2f4be8b2a7 100644 --- a/src/components/accessschedule/accessschedule.js +++ b/src/components/accessschedule/accessschedule.js @@ -9,7 +9,7 @@ define(["dialogHelper", "datetime", "emby-select", "paper-icon-button-light", "f minutes = parseInt(60 * pct); } - return datetime.getDisplayTime(new Date(2e3, 1, 1, hours, minutes, 0, 0)); + return datetime.getDisplayTime(new Date(2000, 1, 1, hours, minutes, 0, 0)); } function populateHours(context) { From d30ca449970426369e33271fe248f9ea146c7ce9 Mon Sep 17 00:00:00 2001 From: grafixeyehero Date: Tue, 15 Oct 2019 20:15:58 +0300 Subject: [PATCH 049/162] update activitylog Suggested change --- src/components/activitylog.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/components/activitylog.js b/src/components/activitylog.js index 2359c44004..e02fb0c868 100644 --- a/src/components/activitylog.js +++ b/src/components/activitylog.js @@ -57,9 +57,9 @@ define(["events", "globalize", "dom", "datetime", "userSettings", "serverNotific var hasUserId = "false" !== elem.getAttribute("data-useractivity"); if (hasUserId) { - minDate.setTime(minDate.getTime() - 864e5); + minDate.setTime(minDate.getTime() - 24 * 60 * 60 * 1000); // one day back } else { - minDate.setTime(minDate.getTime() - 6048e5); + minDate.setTime(minDate.getTime() - 7 * 24 * 60 * 60 * 1000); // one week back } ApiClient.getJSON(ApiClient.getUrl("System/ActivityLog/Entries", { @@ -68,7 +68,9 @@ define(["events", "globalize", "dom", "datetime", "userSettings", "serverNotific minDate: minDate.toISOString(), hasUserId: hasUserId })).then(function (result) { - if (elem.setAttribute("data-activitystartindex", startIndex), elem.setAttribute("data-activitylimit", limit), !startIndex) { + elem.setAttribute("data-activitystartindex", startIndex); + elem.setAttribute("data-activitylimit", limit); + if (!startIndex) { var activityContainer = dom.parentWithClass(elem, "activityContainer"); if (activityContainer) { From e3d8b142453f447b7d737b39eda04fdb14658bd5 Mon Sep 17 00:00:00 2001 From: grafixeyehero Date: Tue, 15 Oct 2019 20:16:58 +0300 Subject: [PATCH 050/162] update favoriteitems Suggested change --- src/components/favoriteitems.js | 22 +++++----------------- 1 file changed, 5 insertions(+), 17 deletions(-) diff --git a/src/components/favoriteitems.js b/src/components/favoriteitems.js index 05a8580e61..c84d84f585 100644 --- a/src/components/favoriteitems.js +++ b/src/components/favoriteitems.js @@ -6,27 +6,15 @@ define(["loading", "libraryBrowser", "cardBuilder", "dom", "apphost", "imageLoad } function getThumbShape() { - if (enableScrollX()) { - return "overflowBackdrop"; - } - - return "backdrop"; + return enableScrollX() ? "overflowBackdrop" : "backdrop"; } function getPosterShape() { - if (enableScrollX()) { - return "overflowPortrait"; - } - - return "portrait"; + return enableScrollX() ? "overflowPortrait" : "portrait"; } function getSquareShape() { - if (enableScrollX()) { - return "overflowSquare"; - } - - return "square"; + return enableScrollX() ? "overflowSquare" : "square"; } function getSections() { @@ -154,9 +142,9 @@ define(["loading", "libraryBrowser", "cardBuilder", "dom", "apphost", "imageLoad html += '

' + globalize.translate(section.name) + "

"; } - if (html += "
", enableScrollX()) { + html += "
"; + if (enableScrollX()) { var scrollXClass = "scrollX hiddenScrollX"; - if (layoutManager.tv) { scrollXClass += " smoothScrollX"; } From 36fae11a38aeb1840a51496aa2334c8cce7c8c36 Mon Sep 17 00:00:00 2001 From: grafixeyehero Date: Tue, 15 Oct 2019 20:18:55 +0300 Subject: [PATCH 051/162] update schedulesdirect Suggested change --- src/components/tvproviders/schedulesdirect.js | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/src/components/tvproviders/schedulesdirect.js b/src/components/tvproviders/schedulesdirect.js index b42744e76d..093b31ebaa 100644 --- a/src/components/tvproviders/schedulesdirect.js +++ b/src/components/tvproviders/schedulesdirect.js @@ -22,7 +22,7 @@ define(["jQuery", "loading", "emby-checkbox", "listViewStyle", "emby-input", "em page.querySelector(".chkAllTuners").checked = info.EnableAllTuners; - if (page.querySelector(".chkAllTuners").checked) { + if (info.EnableAllTuners) { page.querySelector(".selectTunersSection").classList.add("hide"); } else { page.querySelector(".selectTunersSection").classList.remove("hide"); @@ -67,7 +67,7 @@ define(["jQuery", "loading", "emby-checkbox", "listViewStyle", "emby-input", "em return '"; }).join("")).val(info.Country || ""); $(page.querySelector(".txtZipCode")).trigger("change"); - }, function () { + }, function () { // ApiClient.getJSON() error handler Dashboard.alert({ message: Globalize.translate("ErrorGettingTvLineups") }); @@ -88,8 +88,9 @@ define(["jQuery", "loading", "emby-checkbox", "listViewStyle", "emby-input", "em function hex(buffer) { var hexCodes = []; + var view = new DataView(buffer); - for (var view = new DataView(buffer), i = 0; i < view.byteLength; i += 4) { + for (i = 0; i < view.byteLength; i += 4) { var value = view.getUint32(i); var stringValue = value.toString(16); var paddedValue = ("00000000" + stringValue).slice(-"00000000".length); @@ -128,7 +129,7 @@ define(["jQuery", "loading", "emby-checkbox", "listViewStyle", "emby-input", "em providerId = result.Id; reload(); }, function () { - Dashboard.alert({ + Dashboard.alert({ // ApiClient.ajax() error handler message: Globalize.translate("ErrorSavingTvProvider") }); }); @@ -169,7 +170,7 @@ define(["jQuery", "loading", "emby-checkbox", "listViewStyle", "emby-input", "em }).then(function (result) { loading.hide(); - if (false !== options.showConfirmation) { + if (options.showConfirmation) { Dashboard.processServerConfigurationUpdateResult(); } @@ -220,13 +221,10 @@ define(["jQuery", "loading", "emby-checkbox", "listViewStyle", "emby-input", "em switch (providerId = providerId.toLowerCase()) { case "m3u": return "M3U Playlist"; - case "hdhomerun": return "HDHomerun"; - case "satip": return "DVB"; - default: return "Unknown"; } @@ -266,13 +264,13 @@ define(["jQuery", "loading", "emby-checkbox", "listViewStyle", "emby-input", "em self.init = function () { options = options || {}; - if (false !== options.showCancelButton) { + if (options.showCancelButton) { page.querySelector(".btnCancel").classList.remove("hide"); } else { page.querySelector(".btnCancel").classList.add("hide"); } - if (false !== options.showSubmitButton) { + if (options.showSubmitButton) { page.querySelector(".btnSubmitListings").classList.remove("hide"); } else { page.querySelector(".btnSubmitListings").classList.add("hide"); From 0299223b81c2a9aecf9147cf44b4b6bedd719714 Mon Sep 17 00:00:00 2001 From: Dmitry Lyzo Date: Thu, 10 Oct 2019 17:25:22 +0300 Subject: [PATCH 052/162] Remove tab activation on focus --- src/components/emby-tabs/emby-tabs.js | 29 --------------------------- 1 file changed, 29 deletions(-) diff --git a/src/components/emby-tabs/emby-tabs.js b/src/components/emby-tabs/emby-tabs.js index d88b111060..4a0060cf88 100644 --- a/src/components/emby-tabs/emby-tabs.js +++ b/src/components/emby-tabs/emby-tabs.js @@ -10,23 +10,6 @@ define(['dom', 'scroller', 'browser', 'layoutManager', 'focusManager', 'register newButton.classList.add(activeButtonClass); } - function getFocusCallback(tabs, e) { - return function () { - onClick.call(tabs, e); - }; - } - - function onFocus(e) { - - if (layoutManager.tv) { - - if (this.focusTimeout) { - clearTimeout(this.focusTimeout); - } - this.focusTimeout = setTimeout(getFocusCallback(this, e), 700); - } - } - function getTabPanel(tabs, index) { return null; @@ -87,10 +70,6 @@ define(['dom', 'scroller', 'browser', 'layoutManager', 'focusManager', 'register function onClick(e) { - if (this.focusTimeout) { - clearTimeout(this.focusTimeout); - } - var tabs = this; var current = tabs.querySelector('.' + activeButtonClass); @@ -177,10 +156,6 @@ define(['dom', 'scroller', 'browser', 'layoutManager', 'focusManager', 'register dom.addEventListener(this, 'click', onClick, { passive: true }); - dom.addEventListener(this, 'focus', onFocus, { - passive: true, - capture: true - }); }; EmbyTabs.focus = function () { @@ -237,10 +212,6 @@ define(['dom', 'scroller', 'browser', 'layoutManager', 'focusManager', 'register dom.removeEventListener(this, 'click', onClick, { passive: true }); - dom.removeEventListener(this, 'focus', onFocus, { - passive: true, - capture: true - }); }; function getSelectedTabButton(elem) { From 79cd65ea82a0af92d764f0ba82330bc262121550 Mon Sep 17 00:00:00 2001 From: Dmitry Lyzo Date: Thu, 10 Oct 2019 18:03:12 +0300 Subject: [PATCH 053/162] Set "Resume" action on season item on TV --- src/controllers/itemdetailpage.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/controllers/itemdetailpage.js b/src/controllers/itemdetailpage.js index 03e0f68a9b..6991f63caa 100644 --- a/src/controllers/itemdetailpage.js +++ b/src/controllers/itemdetailpage.js @@ -818,7 +818,7 @@ define(["loading", "appRouter", "layoutManager", "connectionManager", "cardBuild imageSize: "large", enableSideMediaInfo: !1, highlight: !1, - action: "none", + action: layoutManager.tv ? "resume" : "none", infoButton: !0, imagePlayButton: !0, includeParentInfoInTitle: !1 From a1538a4ba6ca72c6f79e625ab6a39637be528426 Mon Sep 17 00:00:00 2001 From: grafixeyehero Date: Wed, 16 Oct 2019 18:23:18 +0300 Subject: [PATCH 054/162] missing var --- src/components/tvproviders/schedulesdirect.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/tvproviders/schedulesdirect.js b/src/components/tvproviders/schedulesdirect.js index 093b31ebaa..a1265e7cc9 100644 --- a/src/components/tvproviders/schedulesdirect.js +++ b/src/components/tvproviders/schedulesdirect.js @@ -90,7 +90,7 @@ define(["jQuery", "loading", "emby-checkbox", "listViewStyle", "emby-input", "em var hexCodes = []; var view = new DataView(buffer); - for (i = 0; i < view.byteLength; i += 4) { + for (var i = 0; i < view.byteLength; i += 4) { var value = view.getUint32(i); var stringValue = value.toString(16); var paddedValue = ("00000000" + stringValue).slice(-"00000000".length); From 0e6c54ecc222281dae80aa4a2ff3763dc1438927 Mon Sep 17 00:00:00 2001 From: grafixeyehero Date: Wed, 16 Oct 2019 18:48:42 +0300 Subject: [PATCH 055/162] update channelmapper --- src/components/channelmapper/channelmapper.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/components/channelmapper/channelmapper.js b/src/components/channelmapper/channelmapper.js index d1fdcb1985..841a6a81af 100644 --- a/src/components/channelmapper/channelmapper.js +++ b/src/components/channelmapper/channelmapper.js @@ -3,8 +3,9 @@ define(["dialogHelper", "loading", "connectionManager", "globalize", "actionshee return function (options) { function parentWithClass(elem, className) { - for (; !elem.classList || !elem.classList.contains(className);) { - if (!(elem = elem.parentNode)) { + while (!elem.classList || !elem.classList.contains(className)) { + elem = elem.parentNode; + if (!elem) { return null; } } From 1d2744d7b98a0a55da255fedbbdbf2ac35caab4b Mon Sep 17 00:00:00 2001 From: grafixeyehero Date: Wed, 16 Oct 2019 19:23:50 +0300 Subject: [PATCH 056/162] update channelmapper suggestion change --- src/components/channelmapper/channelmapper.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/components/channelmapper/channelmapper.js b/src/components/channelmapper/channelmapper.js index 841a6a81af..d1fdcb1985 100644 --- a/src/components/channelmapper/channelmapper.js +++ b/src/components/channelmapper/channelmapper.js @@ -3,9 +3,8 @@ define(["dialogHelper", "loading", "connectionManager", "globalize", "actionshee return function (options) { function parentWithClass(elem, className) { - while (!elem.classList || !elem.classList.contains(className)) { - elem = elem.parentNode; - if (!elem) { + for (; !elem.classList || !elem.classList.contains(className);) { + if (!(elem = elem.parentNode)) { return null; } } From c7284dba87292d6d9cf3a6f59aeaee8a787db7cc Mon Sep 17 00:00:00 2001 From: grafixeyehero Date: Thu, 17 Oct 2019 00:02:23 +0300 Subject: [PATCH 057/162] update humanedate suggestion change --- src/components/humanedate.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/components/humanedate.js b/src/components/humanedate.js index 1781ad7dab..85d3a6d3bf 100644 --- a/src/components/humanedate.js +++ b/src/components/humanedate.js @@ -19,10 +19,13 @@ define(["datetime"], function (datetime) { ]; var dt = new Date(); var date = datetime.parseISO8601Date(date_str, true); - var seconds = (dt - date) / 1e3; + var seconds = (dt - date) / 1000.0; var i = 0; - for (seconds < 0 && (seconds = Math.abs(seconds)); format = time_formats[i++];) { + if (seconds < 0) { + seconds = Math.abs(seconds); + } + for (; format = time_formats[i++];) { if (seconds < format[0]) { if (2 == format.length) { return format[1] + " ago"; From 9954eec88dd855c49f1f5e1504d5eb90595424f0 Mon Sep 17 00:00:00 2001 From: grafixeyehero Date: Thu, 17 Oct 2019 00:06:32 +0300 Subject: [PATCH 058/162] revert channelmappers back --- src/components/channelmapper/channelmapper.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/components/channelmapper/channelmapper.js b/src/components/channelmapper/channelmapper.js index d1fdcb1985..841a6a81af 100644 --- a/src/components/channelmapper/channelmapper.js +++ b/src/components/channelmapper/channelmapper.js @@ -3,8 +3,9 @@ define(["dialogHelper", "loading", "connectionManager", "globalize", "actionshee return function (options) { function parentWithClass(elem, className) { - for (; !elem.classList || !elem.classList.contains(className);) { - if (!(elem = elem.parentNode)) { + while (!elem.classList || !elem.classList.contains(className)) { + elem = elem.parentNode; + if (!elem) { return null; } } From 9207ece95f485722ea3ffa4235315b0b32fbfd34 Mon Sep 17 00:00:00 2001 From: grafixeyehero Date: Thu, 17 Oct 2019 01:31:21 +0300 Subject: [PATCH 059/162] Remove commented --- .../apiclient/connectionmanager.js | 340 +----------------- 1 file changed, 16 insertions(+), 324 deletions(-) diff --git a/src/bower_components/apiclient/connectionmanager.js b/src/bower_components/apiclient/connectionmanager.js index 144733cba7..5d25aa6c17 100644 --- a/src/bower_components/apiclient/connectionmanager.js +++ b/src/bower_components/apiclient/connectionmanager.js @@ -48,7 +48,9 @@ define(["events", "apiclient", "appStorage"], function (events, apiClientFactory function updateServerInfo(server, systemInfo) { server.Name = systemInfo.ServerName; - server.Id = systemInfo.Id; + if (systemInfo.Id) { + server.Id = systemInfo.Id; + } if (systemInfo.LocalAddress) { server.LocalAddress = systemInfo.LocalAddress; @@ -136,11 +138,6 @@ define(["events", "apiclient", "appStorage"], function (events, apiClientFactory }); } - //To be remove - /*function getConnectUrl(handler) { - return "https://connect.emby.media/service/" + handler; - }*/ - function replaceAll(originalString, strReplace, strWith) { var reg = new RegExp(strReplace, "ig"); return originalString.replace(reg, strWith); @@ -192,12 +189,6 @@ define(["events", "apiclient", "appStorage"], function (events, apiClientFactory var ConnectionManager = function (credentialProvider, appName, appVersion, deviceName, deviceId, capabilities, devicePixelRatio) { - //ToDo: Remove - /*function onConnectUserSignIn(user) { - connectUser = user; - events.trigger(self, "connectusersignedin", [user]); - }*/ - function onAuthenticated(apiClient, result, options, saveCredentials) { var credentials = credentialProvider.credentials(); var servers = credentials.Servers.filter(function (s) { @@ -255,41 +246,9 @@ define(["events", "apiclient", "appStorage"], function (events, apiClientFactory return Promise.resolve(); } - // ToDO: Remove - /*if (credentials.ConnectUserId && credentials.ConnectAccessToken) { - connectUser = null; - return getConnectUser(credentials.ConnectUserId, credentials.ConnectAccessToken).then(function (user) { - onConnectUserSignIn(user); - return Promise.resolve(); - }, function () { - return Promise.resolve(); - }); - }*/ - return Promise.resolve(); } - //To be remove - /*function getConnectUser(userId, accessToken) { - if (!userId) { - throw new Error("null userId"); - } - - if (!accessToken) { - throw new Error("null accessToken"); - } - - return ajax({ - type: "GET", - url: "https://connect.emby.media/service/user?id=" + userId, - dataType: "json", - headers: { - "X-Application": appName + "/" + appVersion, - "X-Connect-UserToken": accessToken - } - }); - }*/ - function addAuthenticationInfoFromConnect(server, serverUrl, credentials) { if (!server.ExchangeToken) { throw new Error("server.ExchangeToken cannot be null"); @@ -373,41 +332,6 @@ define(["events", "apiclient", "appStorage"], function (events, apiClientFactory }); } - //To be remove - /*function getConnectServers(credentials) { - console.log("Begin getConnectServers"); - - if (credentials.ConnectAccessToken && credentials.ConnectUserId) { - return ajax({ - type: "GET", - url: "https://connect.emby.media/service/servers?userId=" + credentials.ConnectUserId, - dataType: "json", - headers: { - "X-Application": appName + "/" + appVersion, - "X-Connect-UserToken": credentials.ConnectAccessToken - } - }).then(function (servers) { - return servers.map(function (i) { - return { - ExchangeToken: i.AccessKey, - ConnectServerId: i.Id, - Id: i.SystemId, - Name: i.Name, - RemoteAddress: i.Url, - LocalAddress: i.LocalAddress, - UserLinkType: "guest" === (i.UserType || "").toLowerCase() ? "Guest" : "LinkedUser" - }; - }); - }, function () { - return credentials.Servers.slice(0).filter(function (s) { - return s.ExchangeToken; - }); - }); - } - - return Promise.resolve([]); - }*/ - function filterServers(servers, connectServers) { return servers.filter(function (server) { return !server.ExchangeToken || connectServers.filter(function (connectServer) { @@ -556,7 +480,8 @@ define(["events", "apiclient", "appStorage"], function (events, apiClientFactory } function afterConnectValidated(server, credentials, systemInfo, connectionMode, serverUrl, verifyLocalAuthentication, options, resolve) { - if (options = options || {}, false === options.enableAutoLogin) { + options = options || {}; + if (false === options.enableAutoLogin) { server.UserId = null; server.AccessToken = null; } else if (verifyLocalAuthentication && server.AccessToken && false !== options.enableAutoLogin) { @@ -700,9 +625,17 @@ define(["events", "apiclient", "appStorage"], function (events, apiClientFactory }); var existingServer = existingServers.length ? existingServers[0] : apiClient.serverInfo(); - if (existingServer.DateLastAccessed = new Date().getTime(), existingServer.LastConnectionMode = ConnectionMode.Manual, existingServer.ManualAddress = apiClient.serverAddress(), apiClient.manualAddressOnly && (existingServer.manualAddressOnly = true), apiClient.serverInfo(existingServer), apiClient.onAuthenticated = function (instance, result) { - return onAuthenticated(instance, result, {}, true); - }, !existingServers.length) { + existingServer.DateLastAccessed = new Date().getTime(); + existingServer.LastConnectionMode = ConnectionMode.Manual; + existingServer.ManualAddress = apiClient.serverAddress(); + if (apiClient.manualAddressOnly) { + existingServer.manualAddressOnly = true; + } + apiClient.serverInfo(existingServer); + apiClient.onAuthenticated = function (instance, result) { + return onAuthenticated(instance, result, {}, true); + }; + if (!existingServers.length) { var credentials = credentialProvider.credentials(); credentials.Servers = [existingServer]; credentialProvider.credentials(credentials); @@ -726,11 +659,8 @@ define(["events", "apiclient", "appStorage"], function (events, apiClientFactory if (!apiClient) { apiClient = new apiClientFactory(serverUrl, appName, appVersion, deviceName, deviceId, devicePixelRatio); - self._apiClients.push(apiClient); - apiClient.serverInfo(server); - apiClient.onAuthenticated = function (instance, result) { return onAuthenticated(instance, result, {}, true); }; @@ -929,244 +859,6 @@ define(["events", "apiclient", "appStorage"], function (events, apiClientFactory return self.connectToServer(server, options).catch(onFail); }; - //To be remove - /*self.loginToConnect = function (username, password) { - if (username && password) { - return ajax({ - type: "POST", - url: "https://connect.emby.media/service/user/authenticate", - data: { - nameOrEmail: username, - rawpw: password - }, - dataType: "json", - contentType: "application/x-www-form-urlencoded; charset=UTF-8", - headers: { - "X-Application": appName + "/" + appVersion - } - }).then(function (result) { - var credentials = credentialProvider.credentials(); - credentials.ConnectAccessToken = result.AccessToken; - credentials.ConnectUserId = result.User.Id; - credentialProvider.credentials(credentials); - onConnectUserSignIn(result.User); - return result; - }); - } - - return Promise.reject(); - }; - - self.signupForConnect = function (options) { - var email = options.email; - var username = options.username; - var password = options.password; - var passwordConfirm = options.passwordConfirm; - - if (!email) { - return Promise.reject({ - errorCode: "invalidinput" - }); - } - - if (!username) { - return Promise.reject({ - errorCode: "invalidinput" - }); - } - - if (!password) { - return Promise.reject({ - errorCode: "invalidinput" - }); - } - - if (!passwordConfirm) { - return Promise.reject({ - errorCode: "passwordmatch" - }); - } - - if (password !== passwordConfirm) { - return Promise.reject({ - errorCode: "passwordmatch" - }); - } - - var data = { - email: email, - userName: username, - rawpw: password - }; - - if (options.grecaptcha) { - data.grecaptcha = options.grecaptcha; - } - - return ajax({ - type: "POST", - url: "https://connect.emby.media/service/register", - data: data, - dataType: "json", - contentType: "application/x-www-form-urlencoded; charset=UTF-8", - headers: { - "X-Application": appName + "/" + appVersion, - "X-CONNECT-TOKEN": "CONNECT-REGISTER" - } - }).catch(function (response) { - try { - return response.json(); - } catch (err) { - throw err; - } - }).then(function (result) { - if (result && result.Status) { - if ("SUCCESS" === result.Status) { - return Promise.resolve(result); - } - - return Promise.reject({ - errorCode: result.Status - }); - } - - Promise.reject(); - }); - }; - - self.getUserInvitations = function () { - var connectToken = self.connectToken(); - - if (!connectToken) { - throw new Error("null connectToken"); - } - - if (!self.connectUserId()) { - throw new Error("null connectUserId"); - } - - return ajax({ - type: "GET", - url: "https://connect.emby.media/service/servers?userId=" + self.connectUserId() + "&status=Waiting", - dataType: "json", - headers: { - "X-Connect-UserToken": connectToken, - "X-Application": appName + "/" + appVersion - } - }); - }; - - self.deleteServer = function (serverId) { - if (!serverId) { - throw new Error("null serverId"); - } - - var server = credentialProvider.credentials().Servers.filter(function (s) { - return s.Id === serverId; - }); - server = server.length ? server[0] : null; - return new Promise(function (resolve, reject) { - function onDone() { - var credentials = credentialProvider.credentials(); - credentials.Servers = credentials.Servers.filter(function (s) { - return s.Id !== serverId; - }); - credentialProvider.credentials(credentials); - resolve(); - } - - if (!server.ConnectServerId) { - return void onDone(); - } - - var connectToken = self.connectToken(); - var connectUserId = self.connectUserId(); - - if (!connectToken || !connectUserId) { - return void onDone(); - } - - ajax({ - type: "DELETE", - url: "https://connect.emby.media/service/serverAuthorizations?serverId=" + server.ConnectServerId + "&userId=" + connectUserId, - headers: { - "X-Connect-UserToken": connectToken, - "X-Application": appName + "/" + appVersion - } - }).then(onDone, onDone); - }); - }; - - self.rejectServer = function (serverId) { - var connectToken = self.connectToken(); - - if (!serverId) { - throw new Error("null serverId"); - } - - if (!connectToken) { - throw new Error("null connectToken"); - } - - if (!self.connectUserId()) { - throw new Error("null connectUserId"); - } - - var url = "https://connect.emby.media/service/serverAuthorizations?serverId=" + serverId + "&userId=" + self.connectUserId(); - return fetch(url, { - method: "DELETE", - headers: { - "X-Connect-UserToken": connectToken, - "X-Application": appName + "/" + appVersion - } - }); - }; - - self.acceptServer = function (serverId) { - var connectToken = self.connectToken(); - - if (!serverId) { - throw new Error("null serverId"); - } - - if (!connectToken) { - throw new Error("null connectToken"); - } - - if (!self.connectUserId()) { - throw new Error("null connectUserId"); - } - - return ajax({ - type: "GET", - url: "https://connect.emby.media/service/ServerAuthorizations/accept?serverId=" + serverId + "&userId=" + self.connectUserId(), - headers: { - "X-Connect-UserToken": connectToken, - "X-Application": appName + "/" + appVersion - } - }); - }; - - self.resetRegistrationInfo = function (apiClient) { - var cacheKey = getCacheKey("themes", apiClient, { - viewOnly: true - }); - appStorage.removeItem(cacheKey); - cacheKey = getCacheKey("themes", apiClient, { - viewOnly: false - }); - appStorage.removeItem(cacheKey); - }; - - self.getRegistrationInfo = function (feature, apiClient, options) { - var cacheKey = getCacheKey(feature, apiClient, options); - appStorage.setItem(cacheKey, JSON.stringify({ - lastValidDate: new Date().getTime(), - deviceId: self.deviceId() - })); - return Promise.resolve(); - };*/ - self.createPin = function () { var request = { type: "POST", From df720d2d14d9ce8514ea3edf78825180f715897b Mon Sep 17 00:00:00 2001 From: grafixeyehero Date: Thu, 17 Oct 2019 20:04:32 +0300 Subject: [PATCH 060/162] update suggestion change on connectionmanagers --- .../apiclient/connectionmanager.js | 38 +------------------ 1 file changed, 2 insertions(+), 36 deletions(-) diff --git a/src/bower_components/apiclient/connectionmanager.js b/src/bower_components/apiclient/connectionmanager.js index 5d25aa6c17..bc4cba7f0d 100644 --- a/src/bower_components/apiclient/connectionmanager.js +++ b/src/bower_components/apiclient/connectionmanager.js @@ -242,41 +242,11 @@ define(["events", "apiclient", "appStorage"], function (events, apiClientFactory } function ensureConnectUser(credentials) { - if (connectUser && connectUser.Id === credentials.ConnectUserId) { - return Promise.resolve(); - } - return Promise.resolve(); } function addAuthenticationInfoFromConnect(server, serverUrl, credentials) { - if (!server.ExchangeToken) { - throw new Error("server.ExchangeToken cannot be null"); - } - - if (!credentials.ConnectUserId) { - throw new Error("credentials.ConnectUserId cannot be null"); - } - - var url = getEmbyServerUrl(serverUrl, "Connect/Exchange?format=json&ConnectUserId=" + credentials.ConnectUserId); - var auth = 'MediaBrowser Client="' + appName + '", Device="' + deviceName + '", DeviceId="' + deviceId + '", Version="' + appVersion + '"'; - return ajax({ - type: "GET", - url: url, - dataType: "json", - headers: { - "X-MediaBrowser-Token": server.ExchangeToken, - "X-Emby-Authorization": auth - } - }).then(function (auth) { - server.UserId = auth.LocalUserId; - server.AccessToken = auth.AccessToken; - return auth; - }, function () { - server.UserId = null; - server.AccessToken = null; - return Promise.reject(); - }); + return Promise.reject(); } function validateAuthentication(server, serverUrl) { @@ -771,12 +741,8 @@ define(["events", "apiclient", "appStorage"], function (events, apiClientFactory console.log("Begin getAvailableServers"); var credentials = credentialProvider.credentials(); return Promise.all([findServers()]).then(function (responses) { - var connectServers = responses[0]; - var foundServers = responses[1]; + var foundServers = responses[0]; var servers = credentials.Servers.slice(0); - //mergeServers(credentialProvider, servers, foundServers); - //mergeServers(credentialProvider, servers, connectServers); - servers = filterServers(servers, connectServers); servers.sort(function (a, b) { return (b.DateLastAccessed || 0) - (a.DateLastAccessed || 0); }); From 1e3b03dde10c1cc27a40cdc745b63a1c9a1ca380 Mon Sep 17 00:00:00 2001 From: grafixeyehero Date: Thu, 17 Oct 2019 20:49:30 +0300 Subject: [PATCH 061/162] manual minifying --- src/bower_components/apiclient/connectionmanager.js | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/bower_components/apiclient/connectionmanager.js b/src/bower_components/apiclient/connectionmanager.js index bc4cba7f0d..5bd21f579c 100644 --- a/src/bower_components/apiclient/connectionmanager.js +++ b/src/bower_components/apiclient/connectionmanager.js @@ -180,7 +180,7 @@ define(["events", "apiclient", "appStorage"], function (events, apiClientFactory return 0; } - var defaultTimeout = 2e4; + var defaultTimeout = 20000; var ConnectionMode = { Local: 0, Remote: 1, @@ -236,9 +236,10 @@ define(["events", "apiclient", "appStorage"], function (events, apiClientFactory function onLocalUserSignIn(server, serverUrl, user) { self._getOrAddApiClient(server, serverUrl); - return (self.onLocalUserSignedIn ? self.onLocalUserSignedIn.call(self, user) : Promise.resolve()).then(function () { - events.trigger(self, "localusersignedin", [user]); - }); + var promise = self.onLocalUserSignedIn ? self.onLocalUserSignedIn.call(self, user) : Promise.resolve(); + return promise.then(function () { + events.trigger(self, "localusersignedin", [user]) + }) } function ensureConnectUser(credentials) { From 223945bd3622108b1cd25306f948552c20cc5ee3 Mon Sep 17 00:00:00 2001 From: grafixeyehero Date: Thu, 17 Oct 2019 21:33:19 +0300 Subject: [PATCH 062/162] clean up unused code --- .../apiclient/connectionmanager.js | 28 ------------------- 1 file changed, 28 deletions(-) diff --git a/src/bower_components/apiclient/connectionmanager.js b/src/bower_components/apiclient/connectionmanager.js index 5bd21f579c..8be95a0016 100644 --- a/src/bower_components/apiclient/connectionmanager.js +++ b/src/bower_components/apiclient/connectionmanager.js @@ -38,14 +38,6 @@ define(["events", "apiclient", "appStorage"], function (events, apiClientFactory }); } - function mergeServers(credentialProvider, list1, list2) { - for (var i = 0, length = list2.length; i < length; i++) { - credentialProvider.addOrUpdateServer(list1, list2[i]); - } - - return list1; - } - function updateServerInfo(server, systemInfo) { server.Name = systemInfo.ServerName; if (systemInfo.Id) { @@ -303,14 +295,6 @@ define(["events", "apiclient", "appStorage"], function (events, apiClientFactory }); } - function filterServers(servers, connectServers) { - return servers.filter(function (server) { - return !server.ExchangeToken || connectServers.filter(function (connectServer) { - return server.Id === connectServer.Id; - }).length > 0; - }); - } - function findServers() { return new Promise(function (resolve, reject) { var onFinish = function (foundServers) { @@ -495,18 +479,6 @@ define(["events", "apiclient", "appStorage"], function (events, apiClientFactory } } - function getCacheKey(feature, apiClient, options) { - options = options || {}; - var viewOnly = options.viewOnly; - var cacheKey = "regInfo-" + apiClient.serverId(); - - if (viewOnly) { - cacheKey += "-viewonly"; - } - - return cacheKey; - } - function addAppInfoToConnectRequest(request) { request.headers = request.headers || {}; request.headers["X-Application"] = appName + "/" + appVersion; From 9063e153c183b85430af585da6aa15aa437fac5e Mon Sep 17 00:00:00 2001 From: grafixeyehero Date: Fri, 18 Oct 2019 17:05:50 +0300 Subject: [PATCH 063/162] add item path --- .../itemidentifier/itemidentifier.js | 10 ++++++++++ .../itemidentifier.template.html | 20 ++++++++++++++----- 2 files changed, 25 insertions(+), 5 deletions(-) diff --git a/src/components/itemidentifier/itemidentifier.js b/src/components/itemidentifier/itemidentifier.js index 36a337cb7e..c192d76955 100644 --- a/src/components/itemidentifier/itemidentifier.js +++ b/src/components/itemidentifier/itemidentifier.js @@ -370,6 +370,14 @@ define(['dialogHelper', 'loading', 'connectionManager', 'require', 'globalize', scrollHelper.centerFocus.on(dlg.querySelector('.formDialogContent'), false); } + if (item.Path) { + dlg.querySelector('.fldPath').classList.remove('hide'); + } else { + dlg.querySelector('.fldPath').classList.add('hide'); + } + + dlg.querySelector('.txtPath').innerHTML = item.Path || ''; + dialogHelper.open(dlg); dlg.querySelector('.popupIdentifyForm').addEventListener('submit', function (e) { @@ -440,6 +448,8 @@ define(['dialogHelper', 'loading', 'connectionManager', 'require', 'globalize', scrollHelper.centerFocus.on(dlg.querySelector('.formDialogContent'), false); } + + dialogHelper.open(dlg); dlg.querySelector('.btnCancel').addEventListener('click', function (e) { diff --git a/src/components/itemidentifier/itemidentifier.template.html b/src/components/itemidentifier/itemidentifier.template.html index e9ba163a02..7f7195760d 100644 --- a/src/components/itemidentifier/itemidentifier.template.html +++ b/src/components/itemidentifier/itemidentifier.template.html @@ -1,5 +1,7 @@
- +

${Identify}

@@ -9,12 +11,19 @@
+
+
${LabelPath}
+
+
+

${HeaderIdentifyItemHelp}

- +
- +
@@ -43,10 +52,11 @@
-
-
\ No newline at end of file +
From 5461d812751d2e161e67327a72c78d78ee0055f6 Mon Sep 17 00:00:00 2001 From: grafixeyehero Date: Sat, 19 Oct 2019 15:42:28 +0300 Subject: [PATCH 064/162] improve redirect --- src/controllers/wizardfinishpage.js | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/src/controllers/wizardfinishpage.js b/src/controllers/wizardfinishpage.js index 417b2425a5..caaaf3a1ef 100644 --- a/src/controllers/wizardfinishpage.js +++ b/src/controllers/wizardfinishpage.js @@ -6,17 +6,12 @@ define(["loading"], function(loading) { url: ApiClient.getUrl("Startup/Complete"), type: "POST" }).then(function() { - Dashboard.navigate("dashboard.html"); loading.hide(); + window.location.href = "index.html"; + }); } return function(view, params) { view.querySelector(".btnWizardNext").addEventListener("click", onFinish); - view.addEventListener("viewshow", function() { - document.querySelector(".skinHeader").classList.add("noHomeButtonHeader") - }); - view.addEventListener("viewhide", function() { - document.querySelector(".skinHeader").classList.remove("noHomeButtonHeader") - }); }; }); From 4abfc56fa8fa08d27e5474a7cacf5b56ed56fbd9 Mon Sep 17 00:00:00 2001 From: grafixeyehero Date: Sat, 19 Oct 2019 16:06:08 +0300 Subject: [PATCH 065/162] fix code style --- src/wizardfinish.html | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/wizardfinish.html b/src/wizardfinish.html index 0e68f88854..2c01ec22b8 100644 --- a/src/wizardfinish.html +++ b/src/wizardfinish.html @@ -10,8 +10,14 @@

${WizardCompleted}

- - + +
From 78576a7cb2b3f395998db2e3d1dcdcb7005d5375 Mon Sep 17 00:00:00 2001 From: grafixeyehero Date: Mon, 21 Oct 2019 16:50:11 +0300 Subject: [PATCH 066/162] remove new line --- src/controllers/wizardfinishpage.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/controllers/wizardfinishpage.js b/src/controllers/wizardfinishpage.js index caaaf3a1ef..ab3d269dea 100644 --- a/src/controllers/wizardfinishpage.js +++ b/src/controllers/wizardfinishpage.js @@ -8,7 +8,6 @@ define(["loading"], function(loading) { }).then(function() { loading.hide(); window.location.href = "index.html"; - }); } return function(view, params) { From b6db366d0e5774939d25d78b60a8b05035ccd514 Mon Sep 17 00:00:00 2001 From: seokjong Date: Mon, 21 Oct 2019 05:02:56 +0000 Subject: [PATCH 067/162] Translated using Weblate (Korean) Translation: Jellyfin/Jellyfin Web Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-web/ko/ --- src/strings/ko.json | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/strings/ko.json b/src/strings/ko.json index 4c1c5b2f85..f226872953 100644 --- a/src/strings/ko.json +++ b/src/strings/ko.json @@ -814,7 +814,7 @@ "AllComplexFormats": "모든 복잡한 포맷 (ASS, SSA, VOBSUB, PGS, SUB/IDX 등)", "AllLibraries": "모든 라이브러리", "AllowMediaConversion": "미디어 변환 허용", - "AllowOnTheFlySubtitleExtraction": "스트리밍시 자막 추출 허용", + "AllowOnTheFlySubtitleExtraction": "실시간 자막 추출 허용", "AllowOnTheFlySubtitleExtractionHelp": "비디오 트랜스코딩을 방지하기 위해 내장된 자막을 비디오에서 추출하여 텍스트로 클라이언트에 전송할 수 있습니다. 다만, 일부 시스템에서 추출 과정은 긴 시간이 걸리고 비디오 재생을 멈출 수 있습니다. 클라이언트에서 트랜스코딩을 사용할 수 없는 경우 이 기능을 비활성화하여 트랜스코딩 시 자막을 영상에 삽입하십시오.", "AllowRemoteAccess": "이 Jellyfin 서버에 원격 접속을 허용합니다.", "AllowRemoteAccessHelp": "체크 해제 시 모든 외부 접속은 차단됩니다.", @@ -881,7 +881,7 @@ "DoNotRecord": "녹화 안 함", "Disconnect": "연결 끊기", "Disabled": "비활성화됨", - "DirectorValue": "", + "DirectorValue": "감독: {0}", "DirectPlaying": "다이렉트 재생", "DirectStreaming": "다이렉트 스트리밍", "DirectStreamHelp2": "다이렉트 스트리밍은 비디오 퀄리티의 손실없이 매우 적은 처리능력을 사용합니다.", @@ -1271,5 +1271,12 @@ "NoPluginConfigurationMessage": "", "OptionExtractChapterImage": "챕터 이미지 추출 활성화", "RestartPleaseWaitMessage": "Jellyfin 서버가 종료되었다가 다시 시작될 때까지 기다리십시오. 1-2분 정도 걸릴 수 있습니다.", - "Up": "위" + "Up": "위", + "EasyPasswordHelp": "쉬운 핀 코드는 지원되는 기기에서 오프라인 접근을 할 때나 내부 내트워크 로그인에서 사용됩니다.", + "CriticRating": "평점", + "DisplayInMyMedia": "홈화면에 표시", + "DisplayInOtherHomeScreenSections": "보고 있는 것이나 최신 미디어 등을 홈 페이지에 표시합니다", + "DisplayMissingEpisodesWithinSeasonsHelp": "서버 환경설정에서도 TV 라이브러리가 활성화되어있어야 합니다.", + "ErrorAddingMediaPathToVirtualFolder": "미디어 경로를 추가하는 데에 오류가 발생했습니다. 경로를 다시 확인하거나 Jellyfin 서버가 해당 경로에 접근할 수 있는지 확인해 주세요.", + "ErrorGettingTvLineups": "TV 구성을 다운로드 하는 중에 오류가 발생하였습니다. 정보가 맞는지 확인한 후 다시 시도해 주세요." } From 08f249b007fdced273044ed695e92780e3812821 Mon Sep 17 00:00:00 2001 From: grafixeyehero Date: Wed, 23 Oct 2019 00:36:04 +0300 Subject: [PATCH 068/162] diminify favorites.js --- src/controllers/favorites.js | 294 ++++++++++++++++++++++------------- 1 file changed, 187 insertions(+), 107 deletions(-) diff --git a/src/controllers/favorites.js b/src/controllers/favorites.js index 6c521f7bfe..42b1fd85b2 100644 --- a/src/controllers/favorites.js +++ b/src/controllers/favorites.js @@ -1,4 +1,4 @@ -define(["appRouter", "cardBuilder", "dom", "globalize", "connectionManager", "apphost", "layoutManager", "focusManager", "emby-itemscontainer", "emby-scroller"], function(appRouter, cardBuilder, dom, globalize, connectionManager, appHost, layoutManager, focusManager) { +define(["appRouter", "cardBuilder", "dom", "globalize", "connectionManager", "apphost", "layoutManager", "focusManager", "emby-itemscontainer", "emby-scroller"], function (appRouter, cardBuilder, dom, globalize, connectionManager, appHost, layoutManager, focusManager) { "use strict"; function enableScrollX() { @@ -22,92 +22,92 @@ define(["appRouter", "cardBuilder", "dom", "globalize", "connectionManager", "ap name: "HeaderFavoriteMovies", types: "Movie", shape: getPosterShape(), - showTitle: !0, - showYear: !0, - overlayPlayButton: !0, - overlayText: !1, - centerText: !0 + showTitle: true, + showYear: true, + overlayPlayButton: true, + overlayText: false, + centerText: true }, { name: "HeaderFavoriteShows", types: "Series", shape: getPosterShape(), - showTitle: !0, - showYear: !0, - overlayPlayButton: !0, - overlayText: !1, - centerText: !0 + showTitle: true, + showYear: true, + overlayPlayButton: true, + overlayText: false, + centerText: true }, { name: "HeaderFavoriteEpisodes", types: "Episode", shape: getThumbShape(), - preferThumb: !1, - showTitle: !0, - showParentTitle: !0, - overlayPlayButton: !0, - overlayText: !1, - centerText: !0 + preferThumb: false, + showTitle: true, + showParentTitle: true, + overlayPlayButton: true, + overlayText: false, + centerText: true }, { name: "HeaderFavoriteVideos", types: "Video", shape: getThumbShape(), - preferThumb: !0, - showTitle: !0, - overlayPlayButton: !0, - overlayText: !1, - centerText: !0 + preferThumb: true, + showTitle: true, + overlayPlayButton: true, + overlayText: false, + centerText: true }, { name: "HeaderFavoriteCollections", types: "BoxSet", shape: getPosterShape(), - showTitle: !0, - overlayPlayButton: !0, - overlayText: !1, - centerText: !0 + showTitle: true, + overlayPlayButton: true, + overlayText: false, + centerText: true }, { name: "HeaderFavoritePlaylists", types: "Playlist", shape: getSquareShape(), - preferThumb: !1, - showTitle: !0, - overlayText: !1, - showParentTitle: !1, - centerText: !0, - overlayPlayButton: !0, - coverImage: !0 + preferThumb: false, + showTitle: true, + overlayText: false, + showParentTitle: false, + centerText: true, + overlayPlayButton: true, + coverImage: true }, { name: "HeaderFavoriteArtists", types: "MusicArtist", shape: getSquareShape(), - preferThumb: !1, - showTitle: !0, - overlayText: !1, - showParentTitle: !1, - centerText: !0, - overlayPlayButton: !0, - coverImage: !0 + preferThumb: false, + showTitle: true, + overlayText: false, + showParentTitle: false, + centerText: true, + overlayPlayButton: true, + coverImage: true }, { name: "HeaderFavoriteAlbums", types: "MusicAlbum", shape: getSquareShape(), - preferThumb: !1, - showTitle: !0, - overlayText: !1, - showParentTitle: !0, - centerText: !0, - overlayPlayButton: !0, - coverImage: !0 + preferThumb: false, + showTitle: true, + overlayText: false, + showParentTitle: true, + centerText: true, + overlayPlayButton: true, + coverImage: true }, { name: "HeaderFavoriteSongs", types: "Audio", shape: getSquareShape(), - preferThumb: !1, - showTitle: !0, - overlayText: !1, - showParentTitle: !0, - centerText: !0, - overlayMoreButton: !0, + preferThumb: false, + showTitle: true, + overlayText: false, + showParentTitle: true, + centerText: true, + overlayMoreButton: true, action: "instantmix", - coverImage: !0 + coverImage: true }, { name: "HeaderFavoriteBooks", types: "Book", @@ -117,59 +117,78 @@ define(["appRouter", "cardBuilder", "dom", "globalize", "connectionManager", "ap overlayPlayButton: true, overlayText: false, centerText: true - }] + }]; } function getFetchDataFn(section) { - return function() { - var apiClient = this.apiClient, - options = { - SortBy: (section.types, "SeriesName,SortName"), - SortOrder: "Ascending", - Filters: "IsFavorite", - Recursive: !0, - Fields: "PrimaryImageAspectRatio,BasicSyncInfo", - CollapseBoxSetItems: !1, - ExcludeLocationTypes: "Virtual", - EnableTotalRecordCount: !1 - }; + return function () { + var apiClient = this.apiClient; + var options = { + SortBy: (section.types, "SeriesName,SortName"), + SortOrder: "Ascending", + Filters: "IsFavorite", + Recursive: true, + Fields: "PrimaryImageAspectRatio,BasicSyncInfo", + CollapseBoxSetItems: false, + ExcludeLocationTypes: "Virtual", + EnableTotalRecordCount: false + }; options.Limit = 20; var userId = apiClient.getCurrentUserId(); - return "MusicArtist" === section.types ? apiClient.getArtists(userId, options) : (options.IncludeItemTypes = section.types, apiClient.getItems(userId, options)) - } + + if ("MusicArtist" === section.types) { + return apiClient.getArtists(userId, options); + } + + options.IncludeItemTypes = section.types; + return apiClient.getItems(userId, options); + }; } function getRouteUrl(section, serverId) { return appRouter.getRouteUrl("list", { serverId: serverId, itemTypes: section.types, - isFavorite: !0 - }) + isFavorite: true + }); } function getItemsHtmlFn(section) { - return function(items) { - var supportsImageAnalysis = appHost.supports("imageanalysis"), - cardLayout = (appHost.preferVisualCards || supportsImageAnalysis) && section.autoCardLayout && section.showTitle; - cardLayout = !1; - var serverId = this.apiClient.serverId(), - leadingButtons = layoutManager.tv ? [{ - name: globalize.translate("All"), - id: "more", - icon: "", - routeUrl: getRouteUrl(section, serverId) - }] : null, - lines = 0; - return section.showTitle && lines++, section.showYear && lines++, section.showParentTitle && lines++, cardBuilder.getCardsHtml({ + return function (items) { + var supportsImageAnalysis = appHost.supports("imageanalysis"); + var cardLayout = (appHost.preferVisualCards || supportsImageAnalysis) && section.autoCardLayout && section.showTitle; + cardLayout = false; + var serverId = this.apiClient.serverId(); + var leadingButtons = layoutManager.tv ? [{ + name: globalize.translate("All"), + id: "more", + icon: "", + routeUrl: getRouteUrl(section, serverId) + }] : null; + var lines = 0; + + if (section.showTitle) { + lines++; + } + + if (section.showYear) { + lines++; + } + + if (section.showParentTitle) { + lines++; + } + + return cardBuilder.getCardsHtml({ items: items, preferThumb: section.preferThumb, shape: section.shape, centerText: section.centerText && !cardLayout, - overlayText: !1 !== section.overlayText, + overlayText: false !== section.overlayText, showTitle: section.showTitle, showYear: section.showYear, showParentTitle: section.showParentTitle, - scalable: !0, + scalable: true, coverImage: section.coverImage, overlayPlayButton: section.overlayPlayButton, overlayMoreButton: section.overlayMoreButton && !cardLayout, @@ -178,39 +197,100 @@ define(["appRouter", "cardBuilder", "dom", "globalize", "connectionManager", "ap cardLayout: cardLayout, leadingButtons: leadingButtons, lines: lines - }) - } + }); + }; } function FavoritesTab(view, params) { - this.view = view, this.params = params, this.apiClient = connectionManager.currentApiClient(), this.sectionsContainer = view.querySelector(".sections"), createSections(this, this.sectionsContainer, this.apiClient) + this.view = view; + this.params = params; + this.apiClient = connectionManager.currentApiClient(); + this.sectionsContainer = view.querySelector(".sections"); + createSections(this, this.sectionsContainer, this.apiClient); } function createSections(instance, elem, apiClient) { - var i, length, sections = getSections(), - html = ""; + var i; + var length; + var sections = getSections(); + var html = ""; + for (i = 0, length = sections.length; i < length; i++) { - var section = sections[i], - sectionClass = "verticalSection"; - section.showTitle || (sectionClass += " verticalSection-extrabottompadding"), html += '
', html += '
', layoutManager.tv ? html += '

' + globalize.translate(section.name) + "

" : (html += '', html += '

', html += globalize.translate(section.name), html += "

", html += '', html += "
"), html += "
", html += '
', html += "
" + var section = sections[i]; + var sectionClass = "verticalSection"; + + if (!section.showTitle) { + sectionClass += " verticalSection-extrabottompadding"; + } + + html += '
'; + html += '
'; + + if (layoutManager.tv) { + html += '

' + globalize.translate(section.name) + "

"; + } else { + html += ''; + html += '

'; + html += globalize.translate(section.name); + html += "

"; + html += ''; + html += "
"; + } + + html += "
"; + html += '
'; + html += "
"; } + elem.innerHTML = html; var elems = elem.querySelectorAll(".itemsContainer"); + for (i = 0, length = elems.length; i < length; i++) { var itemsContainer = elems[i]; - itemsContainer.fetchData = getFetchDataFn(sections[i]).bind(instance), itemsContainer.getItemsHtml = getItemsHtmlFn(sections[i]).bind(instance), itemsContainer.parentContainer = dom.parentWithClass(itemsContainer, "verticalSection") + itemsContainer.fetchData = getFetchDataFn(sections[i]).bind(instance); + itemsContainer.getItemsHtml = getItemsHtmlFn(sections[i]).bind(instance); + itemsContainer.parentContainer = dom.parentWithClass(itemsContainer, "verticalSection"); } } - return FavoritesTab.prototype.onResume = function(options) { - for (var promises = (this.apiClient, []), view = this.view, elems = this.sectionsContainer.querySelectorAll(".itemsContainer"), i = 0, length = elems.length; i < length; i++) promises.push(elems[i].resume(options)); - Promise.all(promises).then(function() { - options.autoFocus && focusManager.autoFocus(view) - }) - }, FavoritesTab.prototype.onPause = function() { - for (var elems = this.sectionsContainer.querySelectorAll(".itemsContainer"), i = 0, length = elems.length; i < length; i++) elems[i].pause() - }, FavoritesTab.prototype.destroy = function() { - this.view = null, this.params = null, this.apiClient = null; - for (var elems = this.sectionsContainer.querySelectorAll(".itemsContainer"), i = 0, length = elems.length; i < length; i++) elems[i].fetchData = null, elems[i].getItemsHtml = null, elems[i].parentContainer = null; - this.sectionsContainer = null - }, FavoritesTab + + FavoritesTab.prototype.onResume = function (options) { + var promises = (this.apiClient, []); + var view = this.view; + var elems = this.sectionsContainer.querySelectorAll(".itemsContainer"); + + for (var i = 0, length = elems.length; i < length; i++) { + promises.push(elems[i].resume(options)); + } + + Promise.all(promises).then(function () { + if (options.autoFocus) { + focusManager.autoFocus(view); + } + }); + }; + + FavoritesTab.prototype.onPause = function () { + var elems = this.sectionsContainer.querySelectorAll(".itemsContainer"); + + for (var i = 0, length = elems.length; i < length; i++) { + elems[i].pause(); + } + }; + + FavoritesTab.prototype.destroy = function () { + this.view = null; + this.params = null; + this.apiClient = null; + var elems = this.sectionsContainer.querySelectorAll(".itemsContainer"); + + for (var i = 0, length = elems.length; i < length; i++) { + elems[i].fetchData = null; + elems[i].getItemsHtml = null; + elems[i].parentContainer = null; + } + + this.sectionsContainer = null; + }; + + return FavoritesTab; }); From e8af133ed2d9b65134dcc19d8427df0354b0ddbf Mon Sep 17 00:00:00 2001 From: grafixeyehero Date: Wed, 23 Oct 2019 01:14:32 +0300 Subject: [PATCH 069/162] add person to favorite section --- src/controllers/favorites.js | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/controllers/favorites.js b/src/controllers/favorites.js index 42b1fd85b2..95a4ec975a 100644 --- a/src/controllers/favorites.js +++ b/src/controllers/favorites.js @@ -74,6 +74,17 @@ define(["appRouter", "cardBuilder", "dom", "globalize", "connectionManager", "ap centerText: true, overlayPlayButton: true, coverImage: true + }, { + name: "HeaderFavoritePeople", + types: "Person", + shape: getPosterShape(), + preferThumb: false, + showTitle: true, + overlayText: false, + showParentTitle: false, + centerText: true, + overlayPlayButton: true, + coverImage: true }, { name: "HeaderFavoriteArtists", types: "MusicArtist", @@ -140,6 +151,10 @@ define(["appRouter", "cardBuilder", "dom", "globalize", "connectionManager", "ap return apiClient.getArtists(userId, options); } + if ("Person" === section.types) { + return apiClient.getPeople(userId, options); + } + options.IncludeItemTypes = section.types; return apiClient.getItems(userId, options); }; From 5099c95c22d01e06e17fab9d3fbb519243797a5c Mon Sep 17 00:00:00 2001 From: grafixeyehero Date: Wed, 23 Oct 2019 01:19:14 +0300 Subject: [PATCH 070/162] disable favorites rate button on season and studio --- src/components/itemhelper.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/components/itemhelper.js b/src/components/itemhelper.js index f8bdb28ac5..9707f5404c 100644 --- a/src/components/itemhelper.js +++ b/src/components/itemhelper.js @@ -273,8 +273,13 @@ define(['apphost', 'globalize'], function (appHost, globalize) { }, canRate: function (item) { + var itemType = item.Type; - if (item.Type === 'Program' || item.Type === 'Timer' || item.Type === 'SeriesTimer' || item.Type === 'CollectionFolder' || item.Type === 'UserView' || item.Type === 'Channel') { + if (item.Type === 'Program' || item.Type === 'Timer' || item.Type === 'SeriesTimer' || item.Type === 'CollectionFolder' || item.Type === 'UserView' || item.Type === 'Channel' || itemType === 'Season' || itemType === 'Studio') { + return false; + } + + if (!item.UserData) { return false; } From 4999690d0c9d7467688772e35ebc766a8c7ca620 Mon Sep 17 00:00:00 2001 From: grafixeyehero Date: Wed, 23 Oct 2019 01:20:07 +0300 Subject: [PATCH 071/162] add HeaderFavoritePeople strings --- src/strings/en-us.json | 1 + 1 file changed, 1 insertion(+) diff --git a/src/strings/en-us.json b/src/strings/en-us.json index 4d83b070d1..d72b74971a 100644 --- a/src/strings/en-us.json +++ b/src/strings/en-us.json @@ -354,6 +354,7 @@ "HeaderFavoriteShows": "Favorite Shows", "HeaderFavoriteEpisodes": "Favorite Episodes", "HeaderFavoriteAlbums": "Favorite Albums", + "HeaderFavoritePeople": "Favorite People", "HeaderFavoriteArtists": "Favorite Artists", "HeaderFavoriteSongs": "Favorite Songs", "HeaderFavoriteVideos": "Favorite Videos", From f547188775d494a99762047c548159070ed81c3c Mon Sep 17 00:00:00 2001 From: emmanuel billeaud Date: Tue, 22 Oct 2019 13:47:03 +0000 Subject: [PATCH 072/162] Translated using Weblate (French) Translation: Jellyfin/Jellyfin Web Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-web/fr/ --- src/strings/fr.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/strings/fr.json b/src/strings/fr.json index 67e50642f5..e13d8ffc14 100644 --- a/src/strings/fr.json +++ b/src/strings/fr.json @@ -307,7 +307,7 @@ "HeaderContainerProfile": "Profil de conteneur", "HeaderContainerProfileHelp": "Les profils de conteneur indiquent les limites d'un appareil lors de la lecture de formats spécifiques. Si la limite s'applique au média, ce dernier sera transcodé, même si le format est configuré pour la lecture directe.", "HeaderContinueListening": "Reprendre l'écoute", - "HeaderContinueWatching": "Reprendre", + "HeaderContinueWatching": "Continuer à regarder", "HeaderCustomDlnaProfiles": "Profils personnalisés", "HeaderDateIssued": "Date de publication", "HeaderDefaultRecordingSettings": "Paramètres d'enregistrement par défaut", From c1d88b1540e63bcbc71485f7909ec1a986c9eb5e Mon Sep 17 00:00:00 2001 From: Rotekoppen Date: Tue, 22 Oct 2019 19:52:45 +0000 Subject: [PATCH 073/162] =?UTF-8?q?Translated=20using=20Weblate=20(Norwegi?= =?UTF-8?q?an=20Bokm=C3=A5l)=20Translation:=20Jellyfin/Jellyfin=20Web=20Tr?= =?UTF-8?q?anslate-URL:=20https://translate.jellyfin.org/projects/jellyfin?= =?UTF-8?q?/jellyfin-web/nb=5FNO/?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/strings/nb.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/strings/nb.json b/src/strings/nb.json index bab746ffeb..cfef5d43e2 100644 --- a/src/strings/nb.json +++ b/src/strings/nb.json @@ -1448,5 +1448,6 @@ "DropShadow": "Underskygge", "Depressed": "Nedtrykt", "Features": "Med", - "LabelParentNumber": "Foreldrenummer:" + "LabelParentNumber": "Foreldrenummer:", + "OptionResElement": "res element" } From d5464834c4236f21fc67159be08aa574da9ee842 Mon Sep 17 00:00:00 2001 From: delfino434 Date: Wed, 23 Oct 2019 14:42:03 +0000 Subject: [PATCH 074/162] Translated using Weblate (Turkish) Translation: Jellyfin/Jellyfin Web Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-web/tr/ --- src/strings/tr.json | 143 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 142 insertions(+), 1 deletion(-) diff --git a/src/strings/tr.json b/src/strings/tr.json index 347d7f5652..11c1ecebe4 100644 --- a/src/strings/tr.json +++ b/src/strings/tr.json @@ -288,5 +288,146 @@ "AllLanguages": "Bütün diller", "AllowMediaConversion": "Medya dönüşümüne izin ver", "AddItemToCollectionHelp": "Ögeleri koleksiyona eklemek için arama yapın ve üzerine sağ tıklayın veya sekme menüsünden koleksiyona ekleyin.", - "AllowHWTranscodingHelp": "Ayarlayıcının anında akışları dönüştürmesine izin verin. Bu, sunucunun gerektirdiği kodlamanın azaltılmasına yardımcı olabilir." + "AllowHWTranscodingHelp": "Ayarlayıcının anında akışları dönüştürmesine izin verin. Bu, sunucunun gerektirdiği kodlamanın azaltılmasına yardımcı olabilir.", + "ColorSpace": "Renk Uzayı", + "ButtonConnect": "Bağlan", + "ColorTransfer": "Renk transferi", + "ButtonPreviousTrack": "Önceki parça", + "ButtonProfile": "Profil", + "ButtonRefresh": "Yenile", + "ButtonRename": "Yeniden Adlandır", + "ButtonRepeat": "Tekrar", + "ButtonResume": "Devam Et", + "ButtonRevoke": "geri al", + "ChannelNumber": "Kanal Numarası", + "ContinueWatching": "İzlemeye devam et", + "CriticRating": "Kritik değerlendirme", + "CustomDlnaProfilesHelp": "Yeni bir cihazı hedeflemek veya bir sistem profilini geçersiz kılmak için özel bir profil oluşturun.", + "Descending": "Azalan", + "DetectingDevices": "Cihazları tespit", + "DirectPlaying": "Doğrudan oynatma", + "CommunityRating": "Topluluk değerlendirmesi", + "Composer": "Besteci", + "ConfigureDateAdded": "Eklenen tarihin, Kitaplık ayarları altındaki Jellyfin Sunucu kontrol panelinde nasıl belirleneceğini yapılandırın", + "ConfirmDeleteImage": "Resmi Sil?", + "ButtonResetEasyPassword": "Kolay pin kodunu sıfırla", + "ColorPrimaries": "Renk primerleri", + "DirectStreamHelp2": "Doğrudan Akış, video kalitesinde herhangi bir kayıp olmadan çok az işlem gücü kullanır.", + "DirectStreaming": "Doğrudan akış", + "Director": "yönetmen", + "DirectorValue": "Yönetmen: {0}", + "DirectorsValue": "Yöneticiler: {0}", + "Disabled": "Deaktif", + "DisplayModeHelp": "Jellyfin’i çalıştırdığınız ekran türünü seçin.", + "DoNotRecord": "Kaydetme", + "Down": "Aşağı", + "Download": "İndir", + "DownloadsValue": "{0} indirme", + "EditImages": "Resimleri düzenle", + "EditMetadata": "Meta verileri düzenle", + "EditSubtitles": "Altyazıları düzenle", + "EnableBackdropsHelp": "Kütüphaneye göz atarken arka plandaki bazı sayfaların arka planında görüntüleyin.", + "AllowMediaConversionHelp": "Dönüştürme özelliğine erişim izni verme veya reddetme.", + "AllowOnTheFlySubtitleExtraction": "Anında altyazı çıkartmaya izin ver", + "ButtonSelectServer": "Sunucu Seç", + "Disc": "Disk", + "ButtonAddImage": "Resim ekle", + "ButtonAddScheduledTaskTrigger": "Tetikleyici ekle", + "ButtonAddServer": "Sunucu ekle", + "ButtonAudioTracks": "Ses Parçalari", + "ButtonChangeServer": "Sunucu Değiştir", + "ButtonGotIt": "Anladım", + "ButtonMore": "Daha", + "ButtonOpen": "Açık", + "ButtonArrowUp": "Yukarı", + "ButtonNetwork": "Ağ", + "ButtonDownload": "İndir", + "ButtonNextTrack": "Sonraki parça", + "ButtonOff": "Kapalı", + "ButtonParentalControl": "Ebeveyn Kontrolü", + "ButtonArrowDown": "Aşağı", + "ButtonArrowLeft": "Sol", + "ButtonDown": "Aşağı", + "ButtonGuide": "Rehber", + "ButtonLearnMore": "Daha fazla bilgi edin", + "ButtonLibraryAccess": "Kütüphane erişimi", + "ButtonScanAllLibraries": "Tüm Kütüphaneleri Tara", + "ButtonSelectView": "Görünüm seç", + "ButtonShuffle": "Karıştır", + "ButtonShutdown": "Kapat", + "ChannelNameOnly": "Yalnızca {0} kanalı", + "ConfirmDeleteItems": "Bu öğeleri silmek, onları hem dosya sisteminden hem de medya kitaplığınızdan siler. Devam etmek istediğinize emin misiniz?", + "ConfirmDeletion": "Silmeyi onayla", + "ConfirmEndPlayerSession": "Jellyfin'i {0} tarihinde kapatmak ister misiniz?", + "Connect": "Bağlan", + "Disconnect": "Bağlantısız", + "Dislike": "Beğenmemek", + "Display": "Görüntüle", + "DisplayInMyMedia": "Ana ekranda görüntüleme", + "DisplayInOtherHomeScreenSections": "En son medya gibi ana ekran bölümlerinde görüntüleyin ve izlemeye devam edin", + "EnableBackdrops": "Arka planında", + "BurnSubtitlesHelp": "Altyazı formatına bağlı olarak video dönüştürülürken sunucunun altyazılarda yazıp yazmayacağını belirler. Altyazılarda yanmaktan kaçınmak, sunucu performansını iyileştirir. Görüntü tabanlı biçimleri (VOBSUB, PGS, SUB / IDX, vb.) Ve bazı ASS / SSA altyazılarını yazmak için Otomatik'i seçin.", + "ConfirmDeleteItem": "Bu öğeyi silmek, onu hem dosya sisteminden hem de medya kütüphanenizden siler. Devam etmek istediğinize emin misiniz?", + "ValueSpecialEpisodeName": "Özel -{0}", + "DeviceAccessHelp": "Bu, yalnızca benzersiz şekilde tanımlanabilen ve tarayıcı erişimini engellemeyen cihazlar için geçerlidir. Kullanıcı cihazlarına erişimin filtrelenmesi, burada onaylanana kadar yeni cihazları kullanmalarını önler.", + "DirectStreamHelp1": "Medya, çözünürlük ve medya türüyle (H.264, AC3, vb.) İlgili cihazla uyumludur, ancak uyumsuz bir dosya konteynerinde (mkv, avi, wmv, vb.) Bulunur. Video, cihaza aktarılmadan önce anında yeniden paketlenecek.", + "DisplayMissingEpisodesWithinSeasonsHelp": "Bu, sunucu yapılandırmasındaki TV kütüphaneleri için de etkinleştirilmelidir.", + "EasyPasswordHelp": "Kolay pin kodunuz, desteklenen istemcilerde çevrimdışı erişim için kullanılır ve ayrıca ağ içinde oturum açmak için de kullanılabilir.", + "ChangingMetadataImageSettingsNewContent": "Meta veri veya resim indirme ayarlarında yapılan değişiklikler yalnızca kitaplığınıza eklenen yeni içerikler için geçerli olacaktır. Değişiklikleri mevcut başlıklara uygulamak için meta verilerini el ile yenilemeniz gerekir.", + "CinemaModeConfigurationHelp": "Sinema modu, ana özellikten önce fragmanlar ve özel tanıtımlar oynatabilen tiyatro deneyimini doğrudan oturma odanıza getirir.", + "Browse": "Gözat", + "AllowOnTheFlySubtitleExtractionHelp": "Gömülü alt yazılar, videoların kodlanmasını önlemek için videolardan çıkarılabilir ve istemcilere düz metin olarak gönderilebilir. Bazı sistemlerde bu uzun zaman alabilir ve çıkarma işlemi sırasında video oynatmanın durmasına neden olabilir. İstemci cihaz tarafından doğal olarak desteklenmiyorsa, video kod kodlaması ile birlikte yakılmış gömülü altyazılara sahip olmak için bunu devre dışı bırakın.", + "AllowedRemoteAddressesHelp": "Uzaktan bağlanmasına izin verilecek ağlar için virgülle ayrılmış IP adresleri listesi veya IP / ağ maskesi girişleri. Boş bırakılırsa, tüm uzak adreslere izin verilir.", + "AlwaysPlaySubtitlesHelp": "Dil tercihi ile eşleşen altyazılar, ses diline bakılmaksızın yüklenir.", + "AnyLanguage": "Herhangi bir dil", + "Anytime": "İstediğin zaman", + "AroundTime": "{0} civarında", + "Art": "Sanat", + "AsManyAsPossible": "Mümkün olduğunca", + "Ascending": "yükselen", + "AspectRatio": "Boy oranı", + "Audio": "Ses", + "AuthProviderHelp": "Bu kullanıcının şifresini doğrulamak için kullanılacak bir Kimlik Doğrulama Sağlayıcısı seçin.", + "AutoBasedOnLanguageSetting": "Otomatik (dil ayarına göre)", + "Backdrop": "zemin", + "Backdrops": "Zeminler", + "Banner": "afiş", + "BirthDateValue": "Doğan: {0}", + "BirthLocation": "Doğum yeri", + "BirthPlaceValue": "Doğum yeri: {0}", + "Auto": "Oto", + "Blacklist": "kara liste", + "BoxRear": "Kutu (arka)", + "ButtonAddMediaLibrary": "Medya Kitaplığı Ekle", + "ButtonSubmit": "Sunmak", + "ButtonStart": "Başlat", + "ButtonTrailer": "Fragman", + "Box": "Kutu", + "ButtonViewWebsite": "Web sitesini görüntüle", + "CancelRecording": "Kaydı iptal et", + "CancelSeries": "Serileri iptal et", + "ButtonUninstall": "Kaldır", + "ButtonUp": "Yukarı", + "ButtonWebsite": "Website", + "Categories": "Kategoriler", + "DrmChannelsNotImported": "DRM'li kanallar içe aktarılmayacak.", + "DropShadow": "Düşen gölge", + "CopyStreamURL": "Akış URL’sini kopyala", + "DefaultSubtitlesHelp": "Altyazılar, gömülü meta verilerdeki varsayılan ve zorunlu bayraklara göre yüklenir. Birden fazla seçenek olduğunda dil tercihleri göz önünde bulundurulur.", + "DeleteDeviceConfirmation": "Bu cihazı silmek istediğinden emin misin? Bir kullanıcı bir sonraki oturum açışında yeniden görünecektir.", + "DisplayMissingEpisodesWithinSeasons": "Sezonlardaki eksik bölümleri görüntüleme", + "AlwaysPlaySubtitles": "Her zaman altyazıları oynat", + "CopyStreamURLSuccess": "URL başarıyla kopyalandı.", + "DateAdded": "Ekleme Tarihi", + "DatePlayed": "Oynanan tarih", + "DeathDateValue": "Öldü: {0}", + "Default": "Varsayılan", + "DefaultErrorMessage": "İsteğin işlenmesi sırasında bir hata oluştu. Lütfen daha sonra tekrar deneyiniz.", + "DefaultMetadataLangaugeDescription": "Bunlar varsayılan ayarlarınızdır ve kitaplık bazında özelleştirilebilir.", + "DeleteUserConfirmation": "Bu kullanıcıyı silmek istediğinden emin misin?", + "Depressed": "Bunalımlı", + "Desktop": "Masaüstü", + "HeaderFavoriteShows": "Favori Diziler", + "HeaderFavoriteEpisodes": "Favori Bölümler", + "BookLibraryHelp": "Ses ve ders kitapları desteklenir. {0} kitap adlandırma kılavuzunu {1} gözden geçirin." } From ab7d3b16e61d4d912d83383e6b090688d78d62a1 Mon Sep 17 00:00:00 2001 From: grafixeyehero Date: Fri, 25 Oct 2019 01:11:43 +0300 Subject: [PATCH 075/162] Fix metadata editor side bar live tv loading --- src/scripts/editorsidebar.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/scripts/editorsidebar.js b/src/scripts/editorsidebar.js index 90d5ecdaba..bb35d8f60f 100644 --- a/src/scripts/editorsidebar.js +++ b/src/scripts/editorsidebar.js @@ -107,8 +107,9 @@ define(["datetime", "jQuery", "material-icons"], function (datetime, $) { }); } - function loadLiveTvChannels(openItems, callback) { + function loadLiveTvChannels(service, openItems, callback) { ApiClient.getLiveTvChannels({ + ServiceName: service, AddCurrentProgram: false }).then(function (result) { var nodes = result.Items.map(function (i) { From fe8155c2262089c938bc15b2b270a4b53b133aa8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9E=A5=EA=B1=B4?= Date: Thu, 24 Oct 2019 09:58:07 +0000 Subject: [PATCH 076/162] Translated using Weblate (Korean) Translation: Jellyfin/Jellyfin Web Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-web/ko/ --- src/strings/ko.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/strings/ko.json b/src/strings/ko.json index f226872953..845f02a025 100644 --- a/src/strings/ko.json +++ b/src/strings/ko.json @@ -1278,5 +1278,6 @@ "DisplayInOtherHomeScreenSections": "보고 있는 것이나 최신 미디어 등을 홈 페이지에 표시합니다", "DisplayMissingEpisodesWithinSeasonsHelp": "서버 환경설정에서도 TV 라이브러리가 활성화되어있어야 합니다.", "ErrorAddingMediaPathToVirtualFolder": "미디어 경로를 추가하는 데에 오류가 발생했습니다. 경로를 다시 확인하거나 Jellyfin 서버가 해당 경로에 접근할 수 있는지 확인해 주세요.", - "ErrorGettingTvLineups": "TV 구성을 다운로드 하는 중에 오류가 발생하였습니다. 정보가 맞는지 확인한 후 다시 시도해 주세요." + "ErrorGettingTvLineups": "TV 구성을 다운로드 하는 중에 오류가 발생하였습니다. 정보가 맞는지 확인한 후 다시 시도해 주세요.", + "BoxRear": "상자 (후면)" } From d2b796e3cd18ad58314c11ad8fd9e7b347a20a3e Mon Sep 17 00:00:00 2001 From: tluciomiranda Date: Thu, 24 Oct 2019 13:47:31 +0000 Subject: [PATCH 077/162] Translated using Weblate (Portuguese (Portugal)) Translation: Jellyfin/Jellyfin Web Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-web/pt_PT/ --- src/strings/pt-pt.json | 33 ++++++++++++++++----------------- 1 file changed, 16 insertions(+), 17 deletions(-) diff --git a/src/strings/pt-pt.json b/src/strings/pt-pt.json index e6628fbd89..917137207c 100644 --- a/src/strings/pt-pt.json +++ b/src/strings/pt-pt.json @@ -340,8 +340,6 @@ "LabelEpisodeNumber": "Número do episódio:", "LabelEvent": "Evento:", "LabelEveryXMinutes": "A cada:", - "LabelExtractChaptersDuringLibraryScan": "Extrair imagens dos capítulos durante o rastreamento da biblioteca", - "LabelExtractChaptersDuringLibraryScanHelp": "Se ativado, as imagens dos capítulos serão extraídas quando os vídeos forem importados durante a pesquisa na biblioteca. Se desativado, elas serão extraídas durante a tarefa agendada de imagens dos capítulos, permitindo que a pesquisa na biblioteca seja mais rápida.", "LabelExtractChaptersDuringLibraryScan": "Extrair imagens dos capítulos durante a atualização da biblioteca", "LabelExtractChaptersDuringLibraryScanHelp": "Se ativado, as imagens dos capítulos serão extraídas quando os vídeos forem importados durante a atualização da biblioteca. Se desativado, serão extraídas durante a tarefa agendada de extração de imagens dos capítulos, permitindo que a atualização da biblioteca seja mais rápida.", "LabelFailed": "Falhou", @@ -834,7 +832,7 @@ "Browse": "Procurar", "BoxRear": "Caixa (verso)", "Box": "Caixa", - "BookLibraryHelp": "Livros de texto e áudio são suportados. Consulte o Guia de Nomenclatura de Livros Jellyfin {1}.", + "BookLibraryHelp": "Livros de texto e áudio são suportados. Consulte o guia de nomenclatura de livros{1}.", "BirthLocation": "Local de nascimento", "AsManyAsPossible": "Tantos quanto possível", "Art": "Capa", @@ -880,13 +878,13 @@ "GenreValue": "Género: {0}", "General": "Geral", "FormatValue": "Formato: {0}", - "FolderTypeUnset": "Conteúdo misto", + "FolderTypeUnset": "Conteúdo Misto", "Filters": "Filtros", "File": "Ficheiro", "Favorite": "Favoritos", "FFmpegSavePathNotFound": "Não foi possível encontrar o binário FFmpeg na localização que introduziu. O binário FFprobe também é necessário, e deve estar na mesma pasta. Estes componentes são, por norma, instalados em conjunto. Por favor, verifique o caminho da localização e tente de novo.", "Extras": "Extras", - "ExtraLarge": "Extra grande", + "ExtraLarge": "Extra Grande", "EveryNDays": "A cada {0} dias", "ErrorSavingTvProvider": "Ocorreu um erro ao guardar o provedor do serviços de TV. Por favor, garanta que está acessível e tente de novo.", "ErrorMessageStartHourGreaterThanEnd": "A hora de fim deve ser superior à hora de início.", @@ -895,15 +893,15 @@ "ErrorAddingXmlTvFile": "Ocorreu um erro ao aceder ao ficheiro XmlTV. Por favor, garanta que o ficheiro está acessível e tente de novo.", "Episodes": "Episódios", "EndsAtValue": "Termina às {0}", - "EnablePhotosHelp": "Fotografias serão detetadas e mostradas em conjunto com outros ficheiros multimédia.", - "EnablePhotos": "Ativar fotografias", + "EnablePhotosHelp": "Imagens serão detetadas e mostradas em conjunto com outros ficheiros multimédia.", + "EnablePhotos": "Mostrar fotografias", "EnableNextVideoInfoOverlayHelp": "No final de um vídeo, mostrar informação sobre o próximo vídeo da lista de reprodução.", - "EnableNextVideoInfoOverlay": "Ativar informação sobre o próximo vídeo durante a reprodução", + "EnableNextVideoInfoOverlay": "Mostrar informação sobre o próximo vídeo durante a reprodução", "EnableHardwareEncoding": "Ativar codificação por hardware", "EnableExternalVideoPlayersHelp": "O menu de um reprodutor externo será mostrado no início da reprodução de vídeo.", - "EnableExternalVideoPlayers": "Ativar reprodutores de vídeo externos", - "EnableDisplayMirroring": "Ativar espelho de ecrã", - "EnableColorCodedBackgrounds": "Ativar código de cores para o fundo", + "EnableExternalVideoPlayers": "Reprodutores de vídeo externos", + "EnableDisplayMirroring": "Duplicação de ecrã", + "EnableColorCodedBackgrounds": "Código de cores para o fundo", "EditSubtitles": "Editar legendas", "EditMetadata": "Editar metadados", "EditImages": "Editar imagens", @@ -912,7 +910,7 @@ "Download": "Transferir", "DoNotRecord": "Não gravar", "DisplayModeHelp": "Selecione o tipo de ecrã onde o Jellyfin será utilizado.", - "DisplayMissingEpisodesWithinSeasonsHelp": "Deve também ser ativado para as bibliotecas de TV no Painel Principal do Servidor Jellyfin.", + "DisplayMissingEpisodesWithinSeasonsHelp": "Deve também ser ativado para as bibliotecas de TV nas configurações do servidor.", "DisplayMissingEpisodesWithinSeasons": "Mostrar episódios em falta numa série", "DisplayInOtherHomeScreenSections": "Mostrar no ecrã principal em secções como multimédia recente ou continue a ver", "DisplayInMyMedia": "Mostrar no ecrã principal", @@ -969,7 +967,7 @@ "Items": "Itens", "InstallingPackage": "A instalar {0}", "HttpsRequiresCert": "Para ativar ligações seguras, é necessário fornecer um certificado SSL confiável. Forneça um certificado SSL ou desative as ligações seguras.", - "DirectStreamHelp1": "O tipo de multimédia (H.264, AC3, etc.) e a sua resolução são compatíveis com o dispositivo, no entanto, o formato (.mkv, .avi, .wmv, etc.) não é. O conteúdo é reempacotado em tempo real antes de ser enviado para o dispositivo.", + "DirectStreamHelp1": "O tipo de multimédia (H.264, AC3, etc.) e a sua resolução são compatíveis com o dispositivo, no entanto, o formato (mkv, avi, wmv, etc.) não é. O conteúdo é reempacotado em tempo real antes de ser enviado para o dispositivo.", "DirectPlaying": "Reprodução direta", "Backdrop": "Imagem de Fundo", "SortChannelsBy": "Ordenar canais por:", @@ -1050,9 +1048,9 @@ "Display": "Visualização", "ManageLibrary": "Gerir biblioteca", "HeaderLibraryOrder": "Ordenação da Biblioteca", - "EnableThemeVideosHelp": "Se ativado, serão reproduzidos vídeos do tema em plano de fundo durante a navegação pela Biblioteca.", - "EnableThemeSongsHelp": "Se ativado, serão reproduzidas músicas do tema em plano de fundo durante a navegação pela Biblioteca.", - "EnableBackdropsHelp": "Se ativado, serão mostradas imagens de fundo em algumas páginas durante a navegação pela Biblioteca.", + "EnableThemeVideosHelp": "Reproduzir vídeos do tema em plano de fundo durante a navegação pela Biblioteca.", + "EnableThemeSongsHelp": "Reproduzir músicas do tema em plano de fundo durante a navegação pela Biblioteca.", + "EnableBackdropsHelp": "Mostrar imagens de fundo em algumas páginas durante a navegação pela Biblioteca.", "MediaInfoSize": "Tamanho", "LabelTextSize": "Tamanho do Texto:", "HeaderSubtitleAppearance": "Aparência das Legendas", @@ -1082,5 +1080,6 @@ "HeaderMovies": "Filmes", "DirectorsValue": "Realização: {0}", "DirectorValue": "Realizador: {0}", - "ButtonOff": "Desligado" + "ButtonOff": "Desligado", + "ButtonAddImage": "Adicionar Imagem" } From fdb7c99ed445850b775b0214ce3883e100404b0b Mon Sep 17 00:00:00 2001 From: dkanada Date: Fri, 25 Oct 2019 23:14:42 +0900 Subject: [PATCH 078/162] remove dashboard icon from header --- src/scripts/librarymenu.js | 33 +++++---------------------------- 1 file changed, 5 insertions(+), 28 deletions(-) diff --git a/src/scripts/librarymenu.js b/src/scripts/librarymenu.js index 3c7918d66c..a3ce22fe9f 100644 --- a/src/scripts/librarymenu.js +++ b/src/scripts/librarymenu.js @@ -52,14 +52,6 @@ define(["dom", "layoutManager", "inputManager", "connectionManager", "events", " headerSearchButton.classList.remove("hide"); } - if (headerSettingsButton) { - if (user.localUser.Policy.IsAdministrator) { - headerSettingsButton.classList.remove("hide"); - } else { - headerSettingsButton.classList.add("hide"); - } - } - headerCastButton.classList.remove("hide"); } else { headerHomeButton.classList.add("hide"); @@ -68,10 +60,6 @@ define(["dom", "layoutManager", "inputManager", "connectionManager", "events", " if (headerSearchButton) { headerSearchButton.classList.add("hide"); } - - if (headerSettingsButton) { - headerSettingsButton.classList.add("hide"); - } } requiresUserRefresh = false; @@ -95,10 +83,6 @@ define(["dom", "layoutManager", "inputManager", "connectionManager", "events", " Dashboard.navigate("mypreferencesmenu.html"); } - function onSettingsClick(e) { - Dashboard.navigate("dashboard.html"); - } - function onHeaderHomeButtonClick() { Dashboard.navigate("home.html"); } @@ -121,12 +105,9 @@ define(["dom", "layoutManager", "inputManager", "connectionManager", "events", " headerUserButton.addEventListener("click", onHeaderUserButtonClick); headerHomeButton.addEventListener("click", onHeaderHomeButtonClick); - initHeadRoom(skinHeader); headerCastButton.addEventListener("click", onCastButtonClicked); - if (headerSettingsButton) { - headerSettingsButton.addEventListener("click", onSettingsClick); - } + initHeadRoom(skinHeader); } function onCastButtonClicked() { @@ -747,7 +728,6 @@ define(["dom", "layoutManager", "inputManager", "connectionManager", "events", " var headerBackButton; var headerUserButton; var currentUser; - var headerSettingsButton; var headerCastButton; var headerSearchButton; var enableLibraryNavDrawer = !layoutManager.tv; @@ -873,23 +853,20 @@ define(["dom", "layoutManager", "inputManager", "connectionManager", "events", " html += ''; html += ''; html += ''; - - if (!layoutManager.mobile) { - html += ''; - } - html += "
"; html += "
"; html += '
'; html += "
"; + skinHeader.classList.add("skinHeader-withBackground"); + skinHeader.classList.add("skinHeader-blurred"); skinHeader.innerHTML = html; + headerHomeButton = skinHeader.querySelector(".headerHomeButton"); headerUserButton = skinHeader.querySelector(".headerUserButton"); - headerSettingsButton = skinHeader.querySelector(".headerSettingsButton"); headerCastButton = skinHeader.querySelector(".headerCastButton"); headerSearchButton = skinHeader.querySelector(".headerSearchButton"); - skinHeader.classList.add("skinHeader-blurred"); + lazyLoadViewMenuBarImages(); bindMenuEvents(); })(); From a36663da439df31bf6efcd9cb2afc3d9000e70b9 Mon Sep 17 00:00:00 2001 From: grafixeyehero Date: Fri, 25 Oct 2019 18:24:49 +0300 Subject: [PATCH 079/162] change single quote to double quote for itemidentifier --- .../itemidentifier/itemidentifier.js | 174 +++++++++--------- .../itemidentifier.template.html | 2 +- 2 files changed, 88 insertions(+), 88 deletions(-) diff --git a/src/components/itemidentifier/itemidentifier.js b/src/components/itemidentifier/itemidentifier.js index 36a337cb7e..dc9140cb80 100644 --- a/src/components/itemidentifier/itemidentifier.js +++ b/src/components/itemidentifier/itemidentifier.js @@ -1,5 +1,5 @@ -define(['dialogHelper', 'loading', 'connectionManager', 'require', 'globalize', 'scrollHelper', 'layoutManager', 'focusManager', 'browser', 'emby-input', 'emby-checkbox', 'paper-icon-button-light', 'css!./../formdialog', 'material-icons', 'cardStyle'], function (dialogHelper, loading, connectionManager, require, globalize, scrollHelper, layoutManager, focusManager, browser) { - 'use strict'; +define(["dialogHelper", "loading", "connectionManager", "require", "globalize", "scrollHelper", "layoutManager", "focusManager", "browser", "emby-input", "emby-checkbox", "paper-icon-button-light", "css!./../formdialog", "material-icons", "cardStyle"], function (dialogHelper, loading, connectionManager, require, globalize, scrollHelper, layoutManager, focusManager, browser) { + "use strict"; var currentItem; var currentItemType; @@ -20,7 +20,7 @@ define(['dialogHelper', 'loading', 'connectionManager', 'require', 'globalize', }; var i, length; - var identifyField = page.querySelectorAll('.identifyField'); + var identifyField = page.querySelectorAll(".identifyField"); var value; for (i = 0, length = identifyField.length; i < length; i++) { @@ -28,17 +28,17 @@ define(['dialogHelper', 'loading', 'connectionManager', 'require', 'globalize', if (value) { - if (identifyField[i].type === 'number') { + if (identifyField[i].type === "number") { value = parseInt(value); } - lookupInfo[identifyField[i].getAttribute('data-lookup')] = value; + lookupInfo[identifyField[i].getAttribute("data-lookup")] = value; } } var hasId = false; - var txtLookupId = page.querySelectorAll('.txtLookupId'); + var txtLookupId = page.querySelectorAll(".txtLookupId"); for (i = 0, length = txtLookupId.length; i < length; i++) { value = txtLookupId[i].value; @@ -46,12 +46,12 @@ define(['dialogHelper', 'loading', 'connectionManager', 'require', 'globalize', if (value) { hasId = true; } - lookupInfo.ProviderIds[txtLookupId[i].getAttribute('data-providerkey')] = value; + lookupInfo.ProviderIds[txtLookupId[i].getAttribute("data-providerkey")] = value; } if (!hasId && !lookupInfo.Name) { - require(['toast'], function (toast) { - toast(globalize.translate('PleaseEnterNameOrId')); + require(["toast"], function (toast) { + toast(globalize.translate("PleaseEnterNameOrId")); }); return; } @@ -76,7 +76,7 @@ define(['dialogHelper', 'loading', 'connectionManager', 'require', 'globalize', url: apiClient.getUrl("Items/RemoteSearch/" + currentItemType), data: JSON.stringify(lookupInfo), contentType: "application/json", - dataType: 'json' + dataType: "json" }).then(function (results) { @@ -87,14 +87,14 @@ define(['dialogHelper', 'loading', 'connectionManager', 'require', 'globalize', function showIdentificationSearchResults(page, results) { - var identificationSearchResults = page.querySelector('.identificationSearchResults'); + var identificationSearchResults = page.querySelector(".identificationSearchResults"); - page.querySelector('.popupIdentifyForm').classList.add('hide'); - identificationSearchResults.classList.remove('hide'); - page.querySelector('.identifyOptionsForm').classList.add('hide'); - page.querySelector('.dialogContentInner').classList.remove('dialog-content-centered'); + page.querySelector(".popupIdentifyForm").classList.add("hide"); + identificationSearchResults.classList.remove("hide"); + page.querySelector(".identifyOptionsForm").classList.add("hide"); + page.querySelector(".dialogContentInner").classList.remove("dialog-content-centered"); - var html = ''; + var html = ""; var i, length; for (i = 0, length = results.length; i < length; i++) { @@ -102,11 +102,11 @@ define(['dialogHelper', 'loading', 'connectionManager', 'require', 'globalize', html += getSearchResultHtml(result, i); } - var elem = page.querySelector('.identificationSearchResultList'); + var elem = page.querySelector(".identificationSearchResultList"); elem.innerHTML = html; function onSearchImageClick() { - var index = parseInt(this.getAttribute('data-index')); + var index = parseInt(this.getAttribute("data-index")); var currentResult = results[index]; @@ -119,10 +119,10 @@ define(['dialogHelper', 'loading', 'connectionManager', 'require', 'globalize', } } - var searchImages = elem.querySelectorAll('.card'); + var searchImages = elem.querySelectorAll(".card"); for (i = 0, length = searchImages.length; i < length; i++) { - searchImages[i].addEventListener('click', onSearchImageClick); + searchImages[i].addEventListener("click", onSearchImageClick); } if (layoutManager.tv) { @@ -140,13 +140,13 @@ define(['dialogHelper', 'loading', 'connectionManager', 'require', 'globalize', function showIdentifyOptions(page, identifyResult) { - var identifyOptionsForm = page.querySelector('.identifyOptionsForm'); + var identifyOptionsForm = page.querySelector(".identifyOptionsForm"); - page.querySelector('.popupIdentifyForm').classList.add('hide'); - page.querySelector('.identificationSearchResults').classList.add('hide'); - identifyOptionsForm.classList.remove('hide'); - page.querySelector('#chkIdentifyReplaceImages').checked = true; - page.querySelector('.dialogContentInner').classList.add('dialog-content-centered'); + page.querySelector(".popupIdentifyForm").classList.add("hide"); + page.querySelector(".identificationSearchResults").classList.add("hide"); + identifyOptionsForm.classList.remove("hide"); + page.querySelector("#chkIdentifyReplaceImages").checked = true; + page.querySelector(".dialogContentInner").classList.add("dialog-content-centered"); currentSearchResult = identifyResult; @@ -157,47 +157,47 @@ define(['dialogHelper', 'loading', 'connectionManager', 'require', 'globalize', lines.push(identifyResult.ProductionYear); } - var resultHtml = lines.join('
'); + var resultHtml = lines.join("
"); if (identifyResult.ImageUrl) { var displayUrl = getSearchImageDisplayUrl(identifyResult.ImageUrl, identifyResult.SearchProviderName); - resultHtml = '
' + resultHtml + '
'; + resultHtml = '
' + resultHtml + "
"; } - page.querySelector('.selectedSearchResult').innerHTML = resultHtml; + page.querySelector(".selectedSearchResult").innerHTML = resultHtml; - focusManager.focus(identifyOptionsForm.querySelector('.btnSubmit')); + focusManager.focus(identifyOptionsForm.querySelector(".btnSubmit")); } function getSearchResultHtml(result, index) { - var html = ''; + var html = ""; var cssClass = "card scalableCard"; - var cardBoxCssClass = 'cardBox'; + var cardBoxCssClass = "cardBox"; var padderClass; if (currentItemType === "Episode") { cssClass += " backdropCard backdropCard-scalable"; - padderClass = 'cardPadder-backdrop'; + padderClass = "cardPadder-backdrop"; } else if (currentItemType === "MusicAlbum" || currentItemType === "MusicArtist") { cssClass += " squareCard squareCard-scalable"; - padderClass = 'cardPadder-square'; + padderClass = "cardPadder-square"; } else { cssClass += " portraitCard portraitCard-scalable"; - padderClass = 'cardPadder-portrait'; + padderClass = "cardPadder-portrait"; } if (layoutManager.tv && !browser.slow) { - cardBoxCssClass += ' cardBox-focustransform'; + cardBoxCssClass += " cardBox-focustransform"; } - cardBoxCssClass += ' cardBox-bottompadded'; + cardBoxCssClass += " cardBox-bottompadded"; if (layoutManager.tv) { - cardBoxCssClass += ' card-focuscontent cardBox-withfocuscontent'; + cardBoxCssClass += " card-focuscontent cardBox-withfocuscontent"; } html += '
'; - html += '
'; + html += "
"; + html += "
"; var numLines = 2; if (currentItemType === "MusicAlbum") { @@ -239,12 +239,12 @@ define(['dialogHelper', 'loading', 'connectionManager', 'require', 'globalize', } else { html += '
'; } - html += lines[i] || ' '; - html += '
'; + html += lines[i] || " "; + html += "
"; } - html += '
'; - html += ''; + html += "
"; + html += ""; return html; } @@ -259,7 +259,7 @@ define(['dialogHelper', 'loading', 'connectionManager', 'require', 'globalize', loading.show(); var options = { - ReplaceAllImages: page.querySelector('#chkIdentifyReplaceImages').checked + ReplaceAllImages: page.querySelector("#chkIdentifyReplaceImages").checked }; var apiClient = getApiClient(); @@ -291,7 +291,7 @@ define(['dialogHelper', 'loading', 'connectionManager', 'require', 'globalize', apiClient.getJSON(apiClient.getUrl("Items/" + item.Id + "/ExternalIdInfos")).then(function (idList) { - var html = ''; + var html = ""; var providerIds = item.ProviderIds || {}; @@ -303,30 +303,30 @@ define(['dialogHelper', 'loading', 'connectionManager', 'require', 'globalize', html += '
'; - var idLabel = globalize.translate('LabelDynamicExternalId').replace('{0}', idInfo.Name); + var idLabel = globalize.translate("LabelDynamicExternalId").replace("{0}", idInfo.Name); - var value = providerIds[idInfo.Key] || ''; + var value = providerIds[idInfo.Key] || ""; html += ''; - html += '
'; + html += ""; } - page.querySelector('#txtLookupName').value = ''; + page.querySelector("#txtLookupName").value = ""; if (item.Type === "Person" || item.Type === "BoxSet") { - page.querySelector('.fldLookupYear').classList.add('hide'); - page.querySelector('#txtLookupYear').value = ''; + page.querySelector(".fldLookupYear").classList.add("hide"); + page.querySelector("#txtLookupYear").value = ""; } else { - page.querySelector('.fldLookupYear').classList.remove('hide'); - page.querySelector('#txtLookupYear').value = ''; + page.querySelector(".fldLookupYear").classList.remove("hide"); + page.querySelector("#txtLookupYear").value = ""; } - page.querySelector('.identifyProviderIds').innerHTML = html; + page.querySelector(".identifyProviderIds").innerHTML = html; - page.querySelector('.formDialogHeaderTitle').innerHTML = globalize.translate('Identify'); + page.querySelector(".formDialogHeaderTitle").innerHTML = globalize.translate("Identify"); }); } @@ -334,7 +334,7 @@ define(['dialogHelper', 'loading', 'connectionManager', 'require', 'globalize', loading.show(); - require(['text!./itemidentifier.template.html'], function (template) { + require(["text!./itemidentifier.template.html"], function (template) { var apiClient = getApiClient(); @@ -344,54 +344,54 @@ define(['dialogHelper', 'loading', 'connectionManager', 'require', 'globalize', currentItemType = currentItem.Type; var dialogOptions = { - size: 'fullscreen-border', + size: "fullscreen-border", removeOnClose: true, scrollY: false }; if (layoutManager.tv) { - dialogOptions.size = 'fullscreen'; + dialogOptions.size = "fullscreen"; } var dlg = dialogHelper.createDialog(dialogOptions); - dlg.classList.add('formDialog'); - dlg.classList.add('recordingDialog'); + dlg.classList.add("formDialog"); + dlg.classList.add("recordingDialog"); - var html = ''; - html += globalize.translateDocument(template, 'core'); + var html = ""; + html += globalize.translateDocument(template, "core"); dlg.innerHTML = html; // Has to be assigned a z-index after the call to .open() - dlg.addEventListener('close', onDialogClosed); + dlg.addEventListener("close", onDialogClosed); if (layoutManager.tv) { - scrollHelper.centerFocus.on(dlg.querySelector('.formDialogContent'), false); + scrollHelper.centerFocus.on(dlg.querySelector(".formDialogContent"), false); } dialogHelper.open(dlg); - dlg.querySelector('.popupIdentifyForm').addEventListener('submit', function (e) { + dlg.querySelector(".popupIdentifyForm").addEventListener("submit", function (e) { e.preventDefault(); searchForIdentificationResults(dlg); return false; }); - dlg.querySelector('.identifyOptionsForm').addEventListener('submit', function (e) { + dlg.querySelector(".identifyOptionsForm").addEventListener("submit", function (e) { e.preventDefault(); submitIdentficationResult(dlg); return false; }); - dlg.querySelector('.btnCancel').addEventListener('click', function (e) { + dlg.querySelector(".btnCancel").addEventListener("click", function (e) { dialogHelper.close(dlg); }); - dlg.classList.add('identifyDialog'); + dlg.classList.add("identifyDialog"); showIdentificationForm(dlg, item); loading.hide(); @@ -414,47 +414,47 @@ define(['dialogHelper', 'loading', 'connectionManager', 'require', 'globalize', currentItem = null; currentItemType = itemType; - require(['text!./itemidentifier.template.html'], function (template) { + require(["text!./itemidentifier.template.html"], function (template) { var dialogOptions = { - size: 'fullscreen-border', + size: "fullscreen-border", removeOnClose: true, scrollY: false }; if (layoutManager.tv) { - dialogOptions.size = 'fullscreen'; + dialogOptions.size = "fullscreen"; } var dlg = dialogHelper.createDialog(dialogOptions); - dlg.classList.add('formDialog'); - dlg.classList.add('recordingDialog'); + dlg.classList.add("formDialog"); + dlg.classList.add("recordingDialog"); - var html = ''; - html += globalize.translateDocument(template, 'core'); + var html = ""; + html += globalize.translateDocument(template, "core"); dlg.innerHTML = html; if (layoutManager.tv) { - scrollHelper.centerFocus.on(dlg.querySelector('.formDialogContent'), false); + scrollHelper.centerFocus.on(dlg.querySelector(".formDialogContent"), false); } dialogHelper.open(dlg); - dlg.querySelector('.btnCancel').addEventListener('click', function (e) { + dlg.querySelector(".btnCancel").addEventListener("click", function (e) { dialogHelper.close(dlg); }); - dlg.querySelector('.popupIdentifyForm').addEventListener('submit', function (e) { + dlg.querySelector(".popupIdentifyForm").addEventListener("submit", function (e) { e.preventDefault(); searchForIdentificationResults(dlg); return false; }); - dlg.addEventListener('close', function () { + dlg.addEventListener("close", function () { loading.hide(); var foundItem = hasChanges ? currentSearchResult : null; @@ -462,7 +462,7 @@ define(['dialogHelper', 'loading', 'connectionManager', 'require', 'globalize', resolveFunc(foundItem); }); - dlg.classList.add('identifyDialog'); + dlg.classList.add("identifyDialog"); showIdentificationFormFindNew(dlg, itemName, itemYear, itemType); }); @@ -470,20 +470,20 @@ define(['dialogHelper', 'loading', 'connectionManager', 'require', 'globalize', function showIdentificationFormFindNew(dlg, itemName, itemYear, itemType) { - dlg.querySelector('#txtLookupName').value = itemName; + dlg.querySelector("#txtLookupName").value = itemName; if (itemType === "Person" || itemType === "BoxSet") { - dlg.querySelector('.fldLookupYear').classList.add('hide'); - dlg.querySelector('#txtLookupYear').value = ''; + dlg.querySelector(".fldLookupYear").classList.add("hide"); + dlg.querySelector("#txtLookupYear").value = ""; } else { - dlg.querySelector('.fldLookupYear').classList.remove('hide'); - dlg.querySelector('#txtLookupYear').value = itemYear; + dlg.querySelector(".fldLookupYear").classList.remove("hide"); + dlg.querySelector("#txtLookupYear").value = itemYear; } - dlg.querySelector('.formDialogHeaderTitle').innerHTML = globalize.translate('Search'); + dlg.querySelector(".formDialogHeaderTitle").innerHTML = globalize.translate("Search"); } return { diff --git a/src/components/itemidentifier/itemidentifier.template.html b/src/components/itemidentifier/itemidentifier.template.html index e9ba163a02..80980b3b58 100644 --- a/src/components/itemidentifier/itemidentifier.template.html +++ b/src/components/itemidentifier/itemidentifier.template.html @@ -49,4 +49,4 @@ - \ No newline at end of file + From 82fdc6fc33f09688a232819c0ab0dcd5be09a375 Mon Sep 17 00:00:00 2001 From: grafixeyehero Date: Fri, 25 Oct 2019 18:47:25 +0300 Subject: [PATCH 080/162] move headeridenifyitemhelp on top --- src/components/itemidentifier/itemidentifier.template.html | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/components/itemidentifier/itemidentifier.template.html b/src/components/itemidentifier/itemidentifier.template.html index 7f7195760d..9750bab57d 100644 --- a/src/components/itemidentifier/itemidentifier.template.html +++ b/src/components/itemidentifier/itemidentifier.template.html @@ -11,12 +11,11 @@
+

${HeaderIdentifyItemHelp}

${LabelPath}
-
-
+
-

${HeaderIdentifyItemHelp}

From f6eedbb221b61382c4591f4d295885bd33f1c4a1 Mon Sep 17 00:00:00 2001 From: redSpoutnik <15638041+redSpoutnik@users.noreply.github.com> Date: Fri, 25 Oct 2019 18:21:38 +0200 Subject: [PATCH 081/162] Update src/components/htmlvideoplayer/plugin.js Co-Authored-By: dkanada --- src/components/htmlvideoplayer/plugin.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/htmlvideoplayer/plugin.js b/src/components/htmlvideoplayer/plugin.js index 41ddcf56f7..ab46215383 100644 --- a/src/components/htmlvideoplayer/plugin.js +++ b/src/components/htmlvideoplayer/plugin.js @@ -584,7 +584,7 @@ define(['browser', 'require', 'events', 'apphost', 'loading', 'dom', 'playbackMa var mediaStreamTextTracks = getMediaStreamTextTracks(self._currentPlayOptions.mediaSource); Array.from(videoElement.textTracks) - .filter(function(trackElement) { + .filter(function(trackElement) { // get showing .vtt textTacks return trackElement.mode === 'showing'; }) From 608a3e3200d058aa30a4ead43a96ed8517f3478a Mon Sep 17 00:00:00 2001 From: redSpoutnik <15638041+redSpoutnik@users.noreply.github.com> Date: Fri, 25 Oct 2019 18:21:46 +0200 Subject: [PATCH 082/162] Update src/components/htmlvideoplayer/plugin.js Co-Authored-By: dkanada --- src/components/htmlvideoplayer/plugin.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/htmlvideoplayer/plugin.js b/src/components/htmlvideoplayer/plugin.js index ab46215383..d30389609c 100644 --- a/src/components/htmlvideoplayer/plugin.js +++ b/src/components/htmlvideoplayer/plugin.js @@ -577,7 +577,7 @@ define(['browser', 'require', 'events', 'apphost', 'loading', 'dom', 'playbackMa var offsetValue = parseFloat(offset); // if .ass currently rendering - if(currentAssRenderer){ + if (currentAssRenderer){ updateCurrentTrackOffset(offsetValue); } else { var videoElement = self._mediaElement; From c30e6b56a36acab3fec915ddc5c5511f23479a4b Mon Sep 17 00:00:00 2001 From: redSpoutnik <15638041+redSpoutnik@users.noreply.github.com> Date: Fri, 25 Oct 2019 18:21:54 +0200 Subject: [PATCH 083/162] Update src/components/htmlvideoplayer/plugin.js Co-Authored-By: dkanada --- src/components/htmlvideoplayer/plugin.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/htmlvideoplayer/plugin.js b/src/components/htmlvideoplayer/plugin.js index d30389609c..88a59a29ea 100644 --- a/src/components/htmlvideoplayer/plugin.js +++ b/src/components/htmlvideoplayer/plugin.js @@ -594,7 +594,7 @@ define(['browser', 'require', 'events', 'apphost', 'loading', 'dom', 'playbackMa return t.Index === customTrackIndex; })[0]; - if(track) { + if (track) { offsetValue = updateCurrentTrackOffset(offsetValue); setVttSubtitleOffset(trackElement, offsetValue); } else { From effd80caa2f3a1e24d93660a97b0b5c27866207b Mon Sep 17 00:00:00 2001 From: SaddFox Date: Fri, 25 Oct 2019 21:35:44 +0000 Subject: [PATCH 084/162] Translated using Weblate (Slovenian) Translation: Jellyfin/Jellyfin Web Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-web/sl/ --- src/strings/sl-si.json | 41 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) diff --git a/src/strings/sl-si.json b/src/strings/sl-si.json index b38437061a..25f611793a 100644 --- a/src/strings/sl-si.json +++ b/src/strings/sl-si.json @@ -614,5 +614,44 @@ "LabelAirsAfterSeason": "Predvajanje po sezoni:", "LabelAirsBeforeSeason": "Predvajanje pred sezono:", "LabelAlbumArtists": "Izvajalci albuma:", - "LabelAll": "Vse" + "LabelAll": "Vse", + "LabelCustomRating": "Prilagojena ocena:", + "LabelDashboardTheme": "Tema pregledne plošče strežnika:", + "LabelBirthDate": "Datum rojstva:", + "LabelCache": "Predpomnilnik:", + "LabelCachePath": "Pot predpomnilnika:", + "LabelCancelled": "Prekinjeno", + "LabelCertificatePassword": "Geslo certifikata:", + "LabelCertificatePasswordHelp": "V kolikor vaš certifikat potrebuje geslo ga prosimo vnesite tukaj.", + "LabelChannels": "Kanali:", + "LabelCommunityRating": "Ocena skupnosti:", + "LabelCriticRating": "Ocena kritikov:", + "LabelCustomCertificatePathHelp": "Pot do PKCS #12 datoteke, ki vsebuje certifikat in zasebni ključ, za omogočanje TLS povezave na domenah po meri.", + "LabelCustomCss": "CSS po meri:", + "LabelCustomCssHelp": "Določite vaš lasten stil spletnega vmesnika.", + "LabelCustomDeviceDisplayName": "Prikazano ime:", + "LabelCustomDeviceDisplayNameHelp": "Določi prikazano ime naprave. Pusti prazno za uporabo imena kot ga sporoči naprava sama.", + "LabelDefaultScreen": "Privzeti zaslon:", + "LabelDateAdded": "Datum dodajanja:", + "LabelDateAddedBehavior": "Vedenje datuma dodajanja za nove vsebine:", + "LabelDateAddedBehaviorHelp": "V kolikor so prisotni ustrezni metapodatki bodo ti vedno uporabljeni najprej.", + "LabelDateTimeLocale": "Lokacija datuma/časa:", + "LabelDefaultUser": "Privzeti uporabnik:", + "LabelDeviceDescription": "Opis naprave", + "LabelDiscNumber": "Številka diska:", + "LabelDisplayLanguage": "Jezik prikaza:", + "LabelDisplayLanguageHelp": "Prevajanje Jellyfin strežnika je tekoči projekt.", + "LabelBirthYear": "Letnica rojstva:", + "LabelBlastMessageIntervalHelp": "Določi dolžino intervala v sekundah med pošiljanjem sporočil o dostopnosti.", + "LabelBurnSubtitles": "Vžgi podnapise:", + "LabelCachePathHelp": "Določi lokacijo po meri za predpomnjene podatke, na primer slike. Pusti prazno za uporabo privzete lokacije.", + "LabelCollection": "Zbirka:", + "LabelCustomCertificatePath": "Lokacija certifikata ssl po meri:", + "LabelDidlMode": "DIDL način:", + "LabelDisplayMissingEpisodesWithinSeasons": "Prikaži manjkajoče epizode znotraj sezon", + "LabelDay": "Dan:", + "LabelDeathDate": "Datum smrti:", + "LabelBitrate": "Bitna hitrost:", + "LabelBlastMessageInterval": "Interval sporočila o dostopnosti (sekunde)", + "LabelDefaultUserHelp": "Določi knjižnica katerega uporabnika bo prikazana na povezanih napravah. To lahko preglasite s profili za posamezno napravo." } From aca1fca0c227ec9304e39dc8c0ce9533a3998fc5 Mon Sep 17 00:00:00 2001 From: grafixeyehero Date: Sat, 26 Oct 2019 17:41:47 +0300 Subject: [PATCH 085/162] remove addAuthericatonInfoconnect --- .../apiclient/connectionmanager.js | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/src/bower_components/apiclient/connectionmanager.js b/src/bower_components/apiclient/connectionmanager.js index 8be95a0016..8712882a2b 100644 --- a/src/bower_components/apiclient/connectionmanager.js +++ b/src/bower_components/apiclient/connectionmanager.js @@ -235,11 +235,7 @@ define(["events", "apiclient", "appStorage"], function (events, apiClientFactory } function ensureConnectUser(credentials) { - return Promise.resolve(); - } - - function addAuthenticationInfoFromConnect(server, serverUrl, credentials) { - return Promise.reject(); + return Promise.resolve(); } function validateAuthentication(server, serverUrl) { @@ -419,15 +415,7 @@ define(["events", "apiclient", "appStorage"], function (events, apiClientFactory if (credentials.ConnectAccessToken && false !== options.enableAutoLogin) { ensureConnectUser(credentials).then(function () { - if (server.ExchangeToken) { - addAuthenticationInfoFromConnect(server, serverUrl, credentials).then(function () { - afterConnectValidated(server, credentials, systemInfo, connectionMode, serverUrl, true, options, resolve); - }, function () { - afterConnectValidated(server, credentials, systemInfo, connectionMode, serverUrl, true, options, resolve); - }); - } else { - afterConnectValidated(server, credentials, systemInfo, connectionMode, serverUrl, true, options, resolve); - } + afterConnectValidated(server, credentials, systemInfo, connectionMode, serverUrl, true, options, resolve); }); } else { afterConnectValidated(server, credentials, systemInfo, connectionMode, serverUrl, true, options, resolve); From 2542339e42be85a8bf36198876533b248c3a2e97 Mon Sep 17 00:00:00 2001 From: grafixeyehero Date: Sat, 26 Oct 2019 17:42:19 +0300 Subject: [PATCH 086/162] restore condition for ensureConnectUser --- src/bower_components/apiclient/connectionmanager.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/bower_components/apiclient/connectionmanager.js b/src/bower_components/apiclient/connectionmanager.js index 8712882a2b..092f53e38b 100644 --- a/src/bower_components/apiclient/connectionmanager.js +++ b/src/bower_components/apiclient/connectionmanager.js @@ -235,7 +235,9 @@ define(["events", "apiclient", "appStorage"], function (events, apiClientFactory } function ensureConnectUser(credentials) { + if (connectUser && connectUser.Id === credentials.ConnectUserId) { return Promise.resolve(); + } } function validateAuthentication(server, serverUrl) { From 5bd7b3d0dd3ffeea0cfa13f24777a93493b8ed82 Mon Sep 17 00:00:00 2001 From: gnehs Date: Sat, 26 Oct 2019 13:00:16 +0000 Subject: [PATCH 087/162] Translated using Weblate (Chinese (Traditional)) Translation: Jellyfin/Jellyfin Web Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-web/zh_Hant/ --- src/strings/zh-tw.json | 520 ++++++++++++++++++++++++++++++++--------- 1 file changed, 412 insertions(+), 108 deletions(-) diff --git a/src/strings/zh-tw.json b/src/strings/zh-tw.json index dc85b350b8..d36980d1b5 100644 --- a/src/strings/zh-tw.json +++ b/src/strings/zh-tw.json @@ -1,12 +1,12 @@ { - "Add": "添加", + "Add": "新增", "All": "全部", "AllowRemoteAccessHelp": "如果未勾選,所有連線都將被阻擋。", "Browse": "瀏覽", "BrowsePluginCatalogMessage": "瀏覽我們的插件目錄來查看可用的插件。", - "ButtonAdd": "添加", + "ButtonAdd": "新增", "ButtonAddServer": "新增伺服器", - "ButtonAddUser": "添加使用者", + "ButtonAddUser": "新增使用者", "ButtonCancel": "取消", "ButtonDelete": "刪除", "ButtonDeleteImage": "刪除圖像", @@ -29,17 +29,17 @@ "ButtonSearch": "搜尋", "ButtonSelectDirectory": "選擇目錄", "ButtonSelectServer": "選擇伺服器", - "ButtonSignIn": "登錄", + "ButtonSignIn": "登入", "ButtonSignOut": "登出", "ButtonSort": "排序", "ConfirmDeleteItem": "刪除此項目時,也會一併從檔案系統及媒體櫃中刪除。確定要刪除嗎?", "ConfirmDeletion": "確定刪除", "Continuing": "持續", - "CustomDlnaProfilesHelp": "為新的設備創建自定義配置或覆蓋原有系統配置。", + "CustomDlnaProfilesHelp": "為新的設備新增自訂設定檔或覆蓋原有系統設定。", "Delete": "刪除", "DeleteImage": "刪除圖像", "DeleteImageConfirmation": "你確定要刪除這張圖像?", - "DeleteUser": "刪除用戶", + "DeleteUser": "刪除使用者", "Dislike": "不喜歡", "Download": "下載", "Edit": "編輯", @@ -63,7 +63,7 @@ "HeaderAutomaticUpdates": "自動更新", "HeaderCastCrew": "拍攝人員及演員", "HeaderChannels": "頻道", - "HeaderCustomDlnaProfiles": "自定義配置", + "HeaderCustomDlnaProfiles": "自訂設定檔", "HeaderDeleteItem": "刪除項目", "HeaderEasyPinCode": "簡易 PIN 碼", "HeaderFeatureAccess": "可以使用的功能", @@ -81,8 +81,8 @@ "HeaderLinks": "鏈接", "HeaderLiveTV": "電視直播", "HeaderLiveTv": "電視", - "HeaderMediaFolders": "媒體文件夾", - "HeaderMusicVideos": "音樂視頻", + "HeaderMediaFolders": "媒體資料夾", + "HeaderMusicVideos": "MV", "HeaderNewRecording": "新錄製", "HeaderNewUsers": "新使用者", "HeaderNextUp": "接下來", @@ -90,7 +90,7 @@ "HeaderParentalRating": "Parental Rating", "HeaderPaths": "路徑", "HeaderPlayAll": "全部播放", - "HeaderPleaseSignIn": "請登錄", + "HeaderPleaseSignIn": "請登入", "HeaderPreferredMetadataLanguage": "首選媒體資料語言", "HeaderRecentlyPlayed": "最近播放", "HeaderScenes": "場景", @@ -99,12 +99,12 @@ "HeaderSeries": "系列", "HeaderSpecialFeatures": "特色", "HeaderStatus": "狀態", - "HeaderSystemDlnaProfiles": "系統配置", + "HeaderSystemDlnaProfiles": "系統設定", "HeaderUsers": "使用者", "Help": "說明", "ItemCount": "{0}個項目", "LabelAllowServerAutoRestart": "允許伺服器自動重新啟動去安裝更新資料", - "LabelAllowServerAutoRestartHelp": "伺服器只會在沒有活躍用戶及空閒期間重新啟動。", + "LabelAllowServerAutoRestartHelp": "伺服器只會在沒有使用者在使用時重新啟動。", "LabelAudioLanguagePreference": "音頻語言偏好選項:", "LabelCachePath": "緩存路徑:", "LabelCollection": "收藏櫃:", @@ -115,26 +115,26 @@ "LabelDisplayMissingEpisodesWithinSeasons": "顯示節目季度內缺少的單元", "LabelEnableDlnaClientDiscoveryInterval": "尋找客戶端時間間隔(秒)", "LabelEnableDlnaDebugLogging": "記錄DLNA除錯信息到日誌", - "LabelEnableDlnaDebugLoggingHelp": "這將創建一個非常大的日誌文件,建議只需要進行故障排除時啟動。", + "LabelEnableDlnaDebugLoggingHelp": "將會建立非常大的日誌檔案,建議在進行故障排除時啟用。", "LabelEnableDlnaPlayTo": "播放到DLNA設備", "LabelEnableRealtimeMonitor": "啟用實時監控", - "LabelEnableRealtimeMonitorHelp": "支持的文件系統上的更改,將會立即處理。", + "LabelEnableRealtimeMonitorHelp": "支持的檔案系統上的更改,將會立即處理。", "LabelEvent": "事件:", "LabelEveryXMinutes": "每:", "LabelFinish": "完成", - "LabelServerNameHelp": "此名稱將用於標識伺服器。如果留空,計算機名稱將被使用。", + "LabelServerNameHelp": "名稱將用於辨識服務器,預設是伺服器的電腦名稱。", "LabelLanguage": "語言:", "LabelMaxBackdropsPerItem": "每個項目背景的最大數目:", "LabelMaxParentalRating": "最大允許的家長評級:", - "LabelMaxResumePercentage": "最大恢復播放百分比:", - "LabelMaxResumePercentageHelp": "媒體如果在這個時間之後停止,會被認定為已播放", + "LabelMaxResumePercentage": "最大繼續播放百分比:", + "LabelMaxResumePercentageHelp": "媒體若於該時間後停止,會被認定為已播放。", "LabelMaxScreenshotsPerItem": "每件物品截圖的最大數量:", - "LabelMetadataPath": "媒體資料文件夾路徑:", + "LabelMetadataPath": "中繼資料資料夾路徑:", "LabelMinBackdropDownloadWidth": "最小背景下載寬度:", - "LabelMinResumeDuration": "最少恢復播放時間(秒):", - "LabelMinResumeDurationHelp": "媒體比這更短不可恢復播放", - "LabelMinResumePercentage": "最低恢復播放百分比:", - "LabelMinResumePercentageHelp": "媒體如果在這個時間之前停止,會被定為未播放", + "LabelMinResumeDuration": "最小繼續播放時間:", + "LabelMinResumeDurationHelp": "以秒為單位的最短影片長度,它將保存播放位置並讓您繼續播放。", + "LabelMinResumePercentage": "最低繼續播放百分比:", + "LabelMinResumePercentageHelp": "媒體如果在這個時間之前停止,會被認定為未播放。", "LabelMinScreenshotDownloadWidth": "最小截圖下載寬度:", "LabelName": "名字:", "LabelNewPassword": "新密碼:", @@ -145,24 +145,24 @@ "LabelPrevious": "上一個", "LabelRefreshMode": "更新模式:", "LabelSaveLocalMetadata": "將媒體圖像及資料檔存到媒體所在的資料夾", - "LabelSaveLocalMetadataHelp": "直接保存媒體圖像及資料到媒體所在的文件夾能使編輯工作更容易。", + "LabelSaveLocalMetadataHelp": "直接儲存圖片及資料到媒體所在的資料夾能使編輯更容易。", "LabelTime": "時間:", "LabelTriggerType": "觸發類型:", "LabelUser": "使用者:", "LabelYourFirstName": "你的名字:", "LabelYoureDone": "完成!", - "LibraryAccessHelp": "選擇媒體文件夾與這用戶共享。管理員將可以使用媒體資料據管理器編輯所有的媒體文件夾。", + "LibraryAccessHelp": "選擇媒體資料夾與此使用者共享。管理員將可以使用中繼資料管理器編輯所有的媒體資料夾。", "Like": "喜歡", - "MaxParentalRatingHelp": "具有較高的家長評級內容將從這用戶被隱藏。", + "MaxParentalRatingHelp": "具有較高的家長評級內容將從這使用者被隱藏。", "MessageAreYouSureDeleteSubtitles": "您真的要刪除這個字幕檔嗎?", "MessageDownloadQueued": "下載已排程。", "MessageItemsAdded": "已新增項目。", "MessageNoMovieSuggestionsAvailable": "目前並沒有推薦的電影。開始觀看並對您的電影評分後,我們就會為您推薦您可能會喜歡的內容。", "MessageNothingHere": "這裡沒有什麼。", - "MessagePasswordResetForUsers": "下列使用者的密碼已被重新設置。從現時起,該使用者可以使用在密碼重置時所使用之 PIN 代碼進行登入。", + "MessagePasswordResetForUsers": "下列使用者的密碼已被重新設置。該使用者現在可以使用在密碼重置時所使用之 PIN 代碼進行登入。", "MessagePleaseEnsureInternetMetadata": "請確保已啟用從互聯網下載媒體資料。", "Monday": "星期一", - "MoreUsersCanBeAddedLater": "往後可以在控制台內添加更多用戶。", + "MoreUsersCanBeAddedLater": "也可於控制台內新增使用者。", "MySubtitles": "我的字幕", "NewCollection": "新合集", "NewCollectionHelp": "收藏櫃讓您能夠建立個人化的影音及其他媒體的分類。", @@ -173,7 +173,7 @@ "OptionAlbumArtist": "專輯歌手", "OptionAllowBrowsingLiveTv": "允許使用電視", "OptionAllowManageLiveTv": "允許管理電視節目錄影", - "OptionAllowUserToManageServer": "允許這用戶管理伺服器", + "OptionAllowUserToManageServer": "允許該使用者管理伺服器", "OptionArtist": "歌手", "OptionAscending": "升序", "OptionAutomatic": "自動", @@ -183,11 +183,11 @@ "OptionContinuing": "持續", "OptionCriticRating": "評論家評價", "OptionDaily": "每日", - "OptionDateAdded": "添加日期", + "OptionDateAdded": "新增日期", "OptionDatePlayed": "播放日期", "OptionDescending": "降序", - "OptionDisableUser": "禁用此用戶", - "OptionDisableUserHelp": "被禁用的用戶將不允許連接伺服器。現有的連接將被即時終止。", + "OptionDisableUser": "停用該使用者", + "OptionDisableUserHelp": "被停用的使用者將被伺服器封鎖,即便正處於連線狀態也將被中斷。", "OptionDislikes": "不喜歡", "OptionDownloadArtImage": "圖像", "OptionDownloadBackImage": "媒體包裝背面", @@ -203,7 +203,7 @@ "OptionFriday": "星期五", "OptionHasSubtitles": "字幕", "OptionHasThemeSong": "主題曲", - "OptionHasThemeVideo": "主題視頻", + "OptionHasThemeVideo": "主題影片", "OptionHideUser": "在登入頁面隱藏此使用者", "OptionImdbRating": "IMDB評分", "OptionIsHD": "高清", @@ -279,8 +279,8 @@ "TabNetworks": "網絡", "TabPassword": "密碼", "TabPlaylist": "播放清單", - "TabProfile": "配置", - "TabProfiles": "配置", + "TabProfile": "設定", + "TabProfiles": "設定", "TabRecordings": "錄影", "TabSeries": "電視劇", "TabServer": "伺服器", @@ -298,12 +298,12 @@ "Tuesday": "星期二", "UninstallPluginConfirmation": "你確定要卸載{0}?", "UninstallPluginHeader": "卸載插件", - "UserProfilesIntro": "Jellyfin 包含對用戶配置文件的內置支持,使每個用戶都可以擁有自己的顯示設置,播放狀態和家長控制。", + "UserProfilesIntro": "Jellyfin 可單獨對使用者進行設定,所有使用者擁有自己的顯示設置,播放狀態和家長控制。", "Users": "使用者", "VersionNumber": "版本 {0}", "Wednesday": "星期三", "WelcomeToProject": "歡迎使用 Jellyfin!", - "WizardCompleted": "這就是我們所需要的全部資訊,Jellyfin現在正在收集你的媒體櫃的資料,在這段時間內,不妨參考我們推出的應用程式。按一下完成進入伺服器總覽頁。", + "WizardCompleted": "這就是我們所需的全部資訊,Jellyfin 現在正在收集你的媒體櫃的資料,在這段時間內,不妨參考我們推出的應用程式。按一下完成進入伺服器總覽頁。", "Actor": "演員", "AddToPlayQueue": "加入播放清單", "AddToPlaylist": "加入播放列表", @@ -350,19 +350,19 @@ "ButtonAudioTracks": "音軌", "ButtonBack": "回去", "ButtonChangeServer": "更換伺服器", - "AddItemToCollectionHelp": "利用搜尋並使用右鍵或點擊目錄將項目添加到收藏中。", + "AddItemToCollectionHelp": "利用搜尋並使用右鍵或點擊目錄將項目新增到收藏中。", "AddToCollection": "加入收藏", "AirDate": "播出日期", "Aired": "已播於", "AllEpisodes": "所有集數", - "AllowHWTranscodingHelp": "若啟用,將會允許調諧器同步轉檔,這會減少Jellyfin伺服器轉檔必要。", + "AllowHWTranscodingHelp": "若啟用,將會允許調諧器同步轉檔,這會減少 Jellyfin 伺服器轉檔必要。", "AllowOnTheFlySubtitleExtraction": "允許同步字幕截取", - "AllowOnTheFlySubtitleExtractionHelp": "可以從影片中提取內建字幕並以純文字的形式給 Jellyfin 應用程式以避免影片轉碼。在某些系統中這個提取的進程可能會花費較長時間並導致視頻播放出現停滯。若禁用這個選項,當內置字幕不被播放端設備支援時,字幕將透過影片轉碼燒進影片中。", + "AllowOnTheFlySubtitleExtractionHelp": "可以從影片中提取內建字幕並以純文字的形式給 Jellyfin 應用程式以避免影片轉碼。在某些系統中這個提取的進程可能會花費較長時間並導致影片播放出現停滯。若停用這個選項,當內置字幕不被播放端設備支援時,字幕將透過影片轉碼燒進影片中。", "AllowedRemoteAddressesHelp": "可以從非本地連線的IP位址,用冒號分隔,若留白,則允許所有IP。", - "BookLibraryHelp": "支援有聲書和電子書。請瀏覽Jellyfin書籍命名指南。", + "BookLibraryHelp": "支援有聲書和電子書。請瀏覽 Jellyfin 書籍命名指南。", "Box": "盒子", "BoxRear": "盒子(背面)", - "BurnSubtitlesHelp": "根據字幕格式決定服務器在轉換視頻時是否燒錄字幕。避免燒錄字幕會提高服務器性能。選擇“自動”以燒錄基於圖像的字幕格式(如 VOBSUB, PGS, SUB/IDX 等)和一些複雜的 ASS/SSA 字幕。", + "BurnSubtitlesHelp": "根據字幕格式決定伺服器在轉換影片時是否燒錄字幕。避免燒錄字幕會提高伺服器性能。選擇「自動」以燒錄基於圖片的字幕格式(如 VOBSUB, PGS, SUB/IDX 等)和一些複雜的 ASS/SSA 字幕。", "ButtonArrowDown": "下", "ButtonConnect": "連結", "ButtonDown": "下", @@ -407,8 +407,8 @@ "CancelRecording": "取消錄影", "CancelSeries": "取消系列", "Categories": "類別", - "ChangingMetadataImageSettingsNewContent": "更改影片詳細資料或媒體圖像像的下載設定僅對以後添加至媒體庫中的新内容生效,若要採用更改,您需要手動刷新數據。", - "ChannelAccessHelp": "選擇此用戶之共享頻道。管理員將能夠使用資料管理器編輯所有資料夾。", + "ChangingMetadataImageSettingsNewContent": "更改影片詳細資料或媒體圖像像的下載設定僅對以後添加至媒體庫中的新内容生效,若要更改已存在的資料,您需要手動更新中繼資料。", + "ChannelAccessHelp": "選擇此使用者之共享頻道。管理員將能夠使用資料管理器編輯所有資料夾。", "ChannelNameOnly": "只在頻道 {0}", "ChannelNumber": "頻道號碼", "Channels": "頻道", @@ -418,14 +418,14 @@ "CloudSyncFeatureDescription": "將您的媒體備份到雲端當作簡單的備份,收藏和轉檔。", "Collections": "合輯", "Composer": "作曲家", - "ConfigureDateAdded": "調整媒體庫設定裡 伺服器怎麼判定「添加日期」", + "ConfigureDateAdded": "調整伺服器怎麼判定媒體褲的「新增日期」", "ConfirmDeleteImage": "刪除圖片?", "ConfirmDeleteItems": "刪除這些項目會將檔案從系統和媒體庫中刪除。你真的要繼續嗎?", "ConfirmEndPlayerSession": "您要在 {0} 秒後將 Jellyfin關機嗎?", "Connect": "連結", "ContinueWatching": "繼續觀看", "CriticRating": "影評評分", - "DateAdded": "添加日期", + "DateAdded": "新增日期", "DatePlayed": "播放日期", "DeathDateValue": "死於: {0}", "Default": "預設", @@ -437,20 +437,20 @@ "CommunityRating": "公眾評分", "DefaultCameraUploadPathHelp": "請選擇自訂上傳路徑。若留白, 將會使用預設資料夾。如果使用自訂路徑,則還需要在Jellyfin庫設置中作為“媒體庫”添加。", "DefaultErrorMessage": "處理請求時發生錯誤。請稍後再試。", - "DefaultMetadataLangaugeDescription": "這些是你的默認設定並可以在你的每個媒體庫中單獨設定。", - "DefaultSubtitlesHelp": "字幕將基於內建數據中的“默認”標題和“強制”標題來載入。當有多個選項可用時,將根據語言偏好決定。", - "DeleteDeviceConfirmation": "你確定你要刪除這個裝置嗎?當下一次有用戶用這個裝置登入時,這個裝置會再次出現。", + "DefaultMetadataLangaugeDescription": "這些預設設定可以在你的媒體庫中單獨設定。", + "DefaultSubtitlesHelp": "字幕將基於內建資料中的「預設」標記和「強制」標記來載入,當有多個選項可用時,將根據語言偏好決定。", + "DeleteDeviceConfirmation": "你確定你要刪除這個裝置嗎?當有使用者用這個裝置登入時,這個裝置會再次出現。", "DeleteMedia": "刪除媒體", - "DeleteUserConfirmation": "你確定要刪除此用戶?", + "DeleteUserConfirmation": "你確定要刪除此使用者?", "Descending": "降序", "Desktop": "桌面", "DetectingDevices": "正在偵測裝置", - "DeviceAccessHelp": "只適用於用唯一辨識方法的裝置,並不會阻止瀏覽器存取。已過濾的用戶裝置會被拒絕存取,直到他們被批准。", + "DeviceAccessHelp": "只適用於用唯一辨識方法的裝置,並不會阻止瀏覽器存取。已過濾的使用者裝置會被拒絕存取,直到他們被批准。", "DeviceLastUsedByUserName": "最後被 {0} 使用", "DirectPlayError": "直接播放錯誤", "DirectPlaying": "直接播放", - "DirectStreamHelp1": "媒體在畫質和媒體類型(H.264,AC3等)方面與裝置相容,但是在不相容的容器(.mkv,.avi,.wmv等)中。 在影片傳輸到裝置之前,將會重新包裝。", - "DirectStreamHelp2": "直接串流一個文件就會占用非常少的處理效能並且影片的品質不會有任何損失。", + "DirectStreamHelp1": "媒體在畫質和媒體類型(H.264,AC3等)方面與裝置相容。但是在不相容的檔案格式(.mkv,.avi,.wmv等)中,在影片傳輸到裝置之前,將會重新轉檔。", + "DirectStreamHelp2": "直接串流檔案會占用非常少的處理效能並且影片的品質不會有任何損失。", "DirectStreaming": "直接串流", "Director": "導演", "DirectorValue": "導演: {0}", @@ -462,7 +462,7 @@ "DisplayInMyMedia": "在主畫面顯示", "DisplayInOtherHomeScreenSections": "在“最新媒體”和“繼續觀看“等主畫面區塊中顯示", "DisplayMissingEpisodesWithinSeasons": "顯示每季缺少的劇集", - "DisplayMissingEpisodesWithinSeasonsHelp": "必須在 Jellyfin 伺服器的 電視媒體庫設置中啟用該功能。", + "DisplayMissingEpisodesWithinSeasonsHelp": "必須在 Jellyfin 伺服器的電視媒體庫設定中啟用該功能。", "DisplayModeHelp": "選擇您正在運行Jellyfin的螢幕類型。", "DoNotRecord": "不要錄", "Down": "下", @@ -475,27 +475,27 @@ "DrmChannelsNotImported": "受 DMR 保護的頻道將不會被導入。", "DropShadow": "背景投影", "DvrFeatureDescription": "使用Jellyfin DVR安排個人直播電視錄製,系列錄製等。", - "EasyPasswordHelp": "你的簡易 PIN 碼將會用於在支援的 Jellyfin 應用 上進行離線存取,同時也可以被用於連網狀態下的登錄。", + "EasyPasswordHelp": "你的簡易 PIN 碼將會用於在支援的 Jellyfin 應用上進行離線存取,同時也可被用於區域網路的登入。", "EditMetadata": "編輯數據", "EditSubtitles": "編輯字幕", - "EnableBackdrops": "啟用背景", - "EnableBackdropsHelp": "若啟用,當瀏覽媒體庫時背景圖將作為一些頁面的背景。", - "EnableCinemaMode": "啟用影院模式", - "EnableColorCodedBackgrounds": "啟用色彩背景", - "EnableDisplayMirroring": "啟用雙螢幕", - "EnableExternalVideoPlayers": "啟用外接影片播放器", - "EnableExternalVideoPlayersHelp": "當你開始播放影片時,將會顯示一個外接播放器目錄。", + "EnableBackdrops": "背景", + "EnableBackdropsHelp": "瀏覽媒體庫時背景圖將作為頁面的背景。", + "EnableCinemaMode": "影院模式", + "EnableColorCodedBackgrounds": "色彩背景", + "EnableDisplayMirroring": "鏡像顯示器", + "EnableExternalVideoPlayers": "外部影片播放器", + "EnableExternalVideoPlayersHelp": "當你開始播放影片時,將會顯示外部播放器選單。", "EnableHardwareEncoding": "啟用硬體編碼", - "EnableNextVideoInfoOverlay": "在播放時啟用下一個影片資訊", + "EnableNextVideoInfoOverlay": "在播放時顯示下一個影片資訊", "EnableNextVideoInfoOverlayHelp": "在影片結束前,顯示當前播放列表中下一個影片的資訊。", - "EnablePhotos": "啟用圖片", - "EnablePhotosHelp": "照片將被偵測到並和其他媒體文件一起顯示。", + "EnablePhotos": "顯示圖片", + "EnablePhotosHelp": "圖片將被偵測到並和其他媒體檔案一起顯示。", "EnableStreamLooping": "自動循環播放直播", "EnableStreamLoopingHelp": "如果直播僅包含了幾秒鐘的數據並且需要被不斷的請求,請啟用此項。如果在沒有相關問題的情況下啟動此項,可能會導致一些問題。", - "EnableThemeSongs": "啟用主題曲", - "EnableThemeSongsHelp": "如果啟用,當瀏覽媒體庫時主題曲將作為背景音樂播放。", + "EnableThemeSongs": "主題曲", + "EnableThemeSongsHelp": "瀏覽媒體庫時主題曲將作為背景音樂播放。", "EnableThemeVideos": "啟用主題影片", - "EnableThemeVideosHelp": "如果啟用,當瀏覽媒體庫時主題影片將作為背景影片播放。", + "EnableThemeVideosHelp": "瀏覽媒體庫時主題影片將作為背景影片播放。", "EnterFFmpegLocation": "輸入 FFmpeg 路徑", "Episodes": "劇集", "Error": "錯誤", @@ -505,29 +505,29 @@ "ErrorAddingJellyfinConnectAccount1": "新增Jellyfin Connect時發生錯誤。您有建立Jellyfin帳號嗎?您可以在 {0} 創建帳號。", "ErrorAddingJellyfinConnectAccount2": "若你還是遇到問題,請用發生問題的email帳號發送email至 {0}。", "ErrorAddingJellyfinConnectAccount3": "這個 Jellyfin 帳號已經被連接至一個本地帳號。一個 Jellyfin帳號 只能同時被連接到一個本機帳號。", - "ErrorAddingMediaPathToVirtualFolder": "添加媒體路徑時發生錯誤。請確認路徑是否有效,且你的 Jellyfin 伺服器有對該位置的存取權。", - "ErrorAddingTunerDevice": "添加調諧器設備時發生錯誤。請確認它是否可被存取後再試一次。", - "ErrorAddingXmlTvFile": "存取 XmlTV 文件時發生錯誤。請確認該文件是否存在然後再試一次。", + "ErrorAddingMediaPathToVirtualFolder": "新增媒體路徑時發生錯誤,請確認路徑是否有效,且你的 Jellyfin 伺服器有對該位置的存取權。", + "ErrorAddingTunerDevice": "新增調諧器設備時發生錯誤,請確認它是否可被存取後再試一次。", + "ErrorAddingXmlTvFile": "存取 XmlTV 文件時發生錯誤。請確認該檔案是否存在後再試一次。", "ErrorConnectServerUnreachable": "處理請求時發生錯誤。您的伺服器無法與我們位於 {0} 的 Jellyfin Connect伺服器溝通。請確認你的伺服器有網路連結且防火牆或其他安全性程式允許這個程式對外溝通。", "ErrorDeletingItem": "從Jellyfin伺服器刪除項目時發生錯誤。請確認伺服器有那個磁碟的寫入權限並再試一次。", - "ErrorGettingTvLineups": "下載電視節目表時發生錯誤。請確認你的資訊是正確的然後再試一次。", + "ErrorGettingTvLineups": "下載電視節目表時發生錯誤,請確認你的資訊是正確的然後再試一次。", "ErrorMessagePasswordNotMatchConfirm": "密碼和密碼確認必須吻合。", "ErrorMessageStartHourGreaterThanEnd": "結束時間必須在開始時間後。", "ErrorMessageUsernameInUse": "用戶名已存在。請重新選個名稱再試。", - "ErrorPleaseSelectLineup": "請選擇一個節目表, 然後再試一次。如果沒有可用的節目表, 請檢查您的用戶名、密碼和郵遞區號是否正確。", + "ErrorPleaseSelectLineup": "請選擇節目表,然後再試一次。如果沒有可用的節目表,請檢查您的使用者名稱、密碼和郵遞區號是否正確。", "ErrorReachingJellyfinConnect": "連接 Jellyfin Connect 伺服器時發生錯誤。請確認你的網絡狀態是否穩定後再試一次。", "ErrorRemovingJellyfinConnectAccount": "移除 Jellyfin Connect 帳號時發生錯誤。請確認你的網絡狀態是否穩定後再試一次。", "ErrorSavingTvProvider": "儲存電視供應商時發生錯誤。請確認它是可存取後再試一次。", "EveryNDays": "每 {0} 天", "ExitFullscreen": "結束全螢幕", "ExtraLarge": "特大", - "ExtractChapterImagesHelp": "提取章節圖像將允許 Jellyfin 應用程式顯示一個圖像形式的場景選擇目錄。這個提取的過程可能會非常緩慢、佔用大量 CPU 資源,並且可能需要幾個GB的硬碟空間。提取將會在影片被偵測到時啟動,同時也可作為一個夜間計劃任務運行。這個任務可以在“計劃任務”選項中進行設置。不建議在尖峰時刻使用時間進行這個任務。", + "ExtractChapterImagesHelp": "提取章節圖片將允許 Jellyfin 顯示圖片形式的章節選單,提取過程可能會非常緩慢、佔用大量 CPU 資源,並且可能需要幾 GB 的硬碟空間。\n提取會在影片被偵測到時啟動,同時也可作為一個夜間計劃任務運行。這個任務可以在「計劃任務」選項中進行設定。不建議在尖峰時刻使用時間進行這個任務。", "Extras": "額外", "FFmpegSavePathNotFound": "我們無法通過你輸入的路徑找到 FFmpeg。 FFprobe 同樣也是必要且應該被放在同一個資料夾中。他們通常會被打包在一起以供下載。請檢查這個路徑然後再試一次。", "FastForward": "快轉", "Favorites": "我的最愛", "Features": "功能", - "FileReadCancelled": "文件讀取已取消。", + "FileReadCancelled": "檔案讀取已取消。", "Fill": "填滿", "Filters": "濾鏡", "FolderTypeBooks": "書籍", @@ -548,13 +548,13 @@ "GuestUserNotFound": "未找到用戶。請確保用戶名稱正確後重試,或者嘗試輸入他們的電子郵件地址。", "Guide": "指南", "GuideProviderSelectListings": "選擇列表", - "H264CrfHelp": "The Constant Rate Factor (CRF) 是 x264 編碼器的默認畫質設置。您可以設介於0和51之間的值, 其中較低的值將導致更好的畫質 (以更大的文件大小為代價)。正常值介於18和28之間。 x264 的默認值為 23, 可以將其用作起始點。", - "H264EncodingPresetHelp": "選擇一個更快的值以提升性能,或者選擇一個更慢的值以提升畫質。", + "H264CrfHelp": "The Constant Rate Factor (CRF) 是 x264 編碼器的默認畫質設置。此方法允許編碼器自動分配位元速率來試著達到一定輸出品質。讓每個畫格得到它需要的位元數來保持所需的品質等級。CRF 會得到最佳的位元速率分配結果。", + "H264EncodingPresetHelp": "速度越慢則會得到更好的壓縮編碼效率。", "HDPrograms": "HD節目", "HandledByProxy": "由反向代理處理", "HardwareAccelerationWarning": "啟動硬體加速可能在某些環境下導致系統不穩定。請確認你的作業系統和影片驅動程式是最新的。如果你在開啟此項後播放影片產生困難,那麼你需要將此選項設回”自動“。", "HeaderAccessSchedule": "存取時程", - "HeaderAccessScheduleHelp": "創建一個存取時程以限制可存取的時段。", + "HeaderAccessScheduleHelp": "建立一個存取時程以限制可存取的時段。", "HeaderActiveDevices": "運行中裝置", "HeaderActivity": "活動", "HeaderAddDevice": "新增裝置", @@ -572,7 +572,7 @@ "HeaderAllowMediaDeletionFrom": "允許從中刪除媒體", "HeaderApiKey": "API 金鑰", "HeaderApiKeys": "API 金鑰", - "HeaderApiKeysHelp": "外部應用程式需要有一個 API 金鑰以用於和 Jellyfin 伺服器溝通。金鑰將在通過 Jellyfin 帳戶登錄時自動發行,或者你可以手動為應用程式生成一個金鑰。", + "HeaderApiKeysHelp": "外部應用程式需要有一個 API 金鑰以用於和 Jellyfin 伺服器溝通。金鑰將在通過 Jellyfin 帳戶登入時自動發行,或者你可以手動為應用程式生成一個金鑰。", "HeaderApp": "應用程式", "HeaderAppearsOn": "同時出現於", "HeaderAudio": "音訊", @@ -596,11 +596,11 @@ "HeaderCinemaMode": "劇院模式", "HeaderClients": "客戶端", "HeaderCloudSync": "雲端同步", - "HeaderCodecProfile": "編碼配置", - "HeaderCodecProfileHelp": "編碼器的配置文件標明了設備播放特定編碼時的限制。如果在限制之內則媒體將被轉碼,否則編碼器將被配置為直接播放。", + "HeaderCodecProfile": "編碼設定檔", + "HeaderCodecProfileHelp": "編碼器的設定檔標明了設備播放特定編碼時的限制;如果在限制之內則媒體將被轉碼,否則編碼器將被設定為直接播放。", "HeaderCollections": "收藏", "HeaderColumns": "列", - "HeaderConfigureRemoteAccess": "配置遠端控制", + "HeaderConfigureRemoteAccess": "設定遠端控制", "HeaderConfirm": "確認", "HeaderConfirmDeletion": "確認刪除", "HeaderConfirmPluginInstallation": "確認插件安裝", @@ -613,8 +613,8 @@ "HeaderConfirmation": "確認", "HeaderConnectToServer": "連結至伺服器", "HeaderConnectionFailure": "連結失敗", - "HeaderContainerProfile": "媒體載體配置", - "HeaderContainerProfileHelp": "媒體載體的配置文件標明了設備播放特定媒體格式時的限制。如果在限制之內則媒體將被轉碼,否則媒體格式將被配置為直接播放。", + "HeaderContainerProfile": "媒體載體設定檔", + "HeaderContainerProfileHelp": "媒體載體的設定檔標明了設備播放特定媒體格式時的限制。如果在限制之內則媒體將被轉碼,否則媒體格式將被設定為直接播放。", "HeaderContinueListening": "繼續聆聽", "HeaderContinueWatching": "繼續觀賞", "HeaderConvertYourRecordings": "為你的錄制轉檔", @@ -622,7 +622,7 @@ "HeaderDashboardUserPassword": "用戶的密碼被管理在每個用戶的私人配置設置中。", "HeaderDate": "日期", "HeaderDateIssued": "發布日期", - "HeaderDefaultRecordingSettings": "默認錄製設定", + "HeaderDefaultRecordingSettings": "預設錄製設定", "HeaderDeleteDevice": "刪除裝置", "HeaderDeleteImage": "刪除圖片", "HeaderDeleteItems": "刪除項目", @@ -634,8 +634,8 @@ "HeaderDevice": "裝置", "HeaderDeviceAccess": "允許裝置存取", "HeaderDevices": "裝置", - "HeaderDirectPlayProfile": "直接播放配置", - "HeaderDirectPlayProfileHelp": "添加直接播放配置,標明哪些媒體格式設備可以自己處理。", + "HeaderDirectPlayProfile": "直接播放設定檔", + "HeaderDirectPlayProfileHelp": "新增直接播放設定檔,標明哪些媒體格式設備可以自己處理。", "HeaderDisplay": "顯示", "HeaderDownloadSettings": "下載設定", "HeaderDownloadSubtitlesFor": "下載字幕:", @@ -845,30 +845,30 @@ "Songs": "歌曲", "Sync": "同步", "ValueSpecialEpisodeName": "特典 - {0}", - "AuthProviderHelp": "選擇用於驗證用戶密碼的身份驗證提供者", + "AuthProviderHelp": "選擇用於驗證使用者密碼的身份驗證提供者。", "HeaderParentalRatings": "家長評級", "HeaderPendingInvitations": "等待邀請", - "HeaderProfile": "配置", - "HeaderProfileInformation": "配置信息", + "HeaderProfile": "設定檔", + "HeaderProfileInformation": "設定檔信息", "HeaderProfileServerSettingsHelp": "這些數值將控制 Jellyfin 伺服器如何呈現給設備。", - "HeaderResponseProfile": "反應配置", - "HeaderResponseProfileHelp": "當播放某些類型的媒體時,反應配置提供一種方法來發送自定訊息到設備。", + "HeaderResponseProfile": "回覆設定檔", + "HeaderResponseProfileHelp": "當播放某些類型的媒體時,回覆設定檔提供一種方法來發送自定訊息到設備。", "HeaderRestartingServer": "重新啟動伺服器", "HeaderSchedule": "日程表", "HeaderSelectCertificatePath": "選擇證書路徑", "HeaderSelectMetadataPath": "選擇數據路徑", - "HeaderSubtitleProfile": "字幕配置", - "HeaderSubtitleProfiles": "字幕配置", - "HeaderSubtitleProfilesHelp": "字幕配置文件描述設備所支援的字幕格式。", + "HeaderSubtitleProfile": "字幕設定檔", + "HeaderSubtitleProfiles": "字幕設定檔", + "HeaderSubtitleProfilesHelp": "字幕設定檔描述設備所支援的字幕格式。", "HeaderTaskTriggers": "任務觸發", - "HeaderTranscodingProfile": "轉碼配置", - "HeaderTranscodingProfileHelp": "添加轉碼配置文件標明哪些媒體格式需要轉碼處理。", + "HeaderTranscodingProfile": "轉碼設定", + "HeaderTranscodingProfileHelp": "新增轉碼設定檔標明哪些媒體格式需要轉碼處理。", "HeaderTuners": "調諧器", "HeaderTypeImageFetchers": "{0} 圖片獲取程序", "HeaderTypeText": "輸入文字", "HeaderUpcomingOnTV": "即將播放", "HeaderUploadImage": "上傳圖片", - "HeaderUser": "用戶", + "HeaderUser": "使用者", "HeaderVideoQuality": "影片畫質", "HeaderVideoType": "影片類型", "HeaderVideoTypes": "影片類型", @@ -882,7 +882,7 @@ "HideWatchedContentFromLatestMedia": "從最新媒體中隱藏已觀看的內容", "Home": "首頁", "Horizontal": "橫向", - "HttpsRequiresCert": "要啟用安全連線,您需要提供受信任的SSL證書,例如Lets Encrypt。 請提供證書,或停用安全連線。", + "HttpsRequiresCert": "要啟用安全連線,您需要提供受信任的SSL證書,如 Lets Encrypt。 請提供證書,或停用安全連線。", "Identify": "識別", "Images": "圖片", "ImportFavoriteChannelsHelp": "如果啟用,只有在調諧器設備中被標記為我的最愛的頻道才會被導入。", @@ -925,27 +925,27 @@ "LabelBirthDate": "出生日期:", "LabelBirthYear": "出生年份:", "LabelBlastMessageInterval": "活動信號的時間間隔(秒)", - "LabelBlastMessageIntervalHelp": "確定服務器活動消息之間的持續時間(秒)。", + "LabelBlastMessageIntervalHelp": "確定伺服器活動消息之間的持續時間(秒)。", "LabelBlockContentWithTags": "通過標籤鎖定內容:", "LabelBurnSubtitles": "燒錄字幕:", "LabelCache": "快取:", - "LabelCachePathHelp": "選擇指定所需的緩存文件路徑,如圖像。保留空白以使用默認設定。", + "LabelCachePathHelp": "選擇指定所需的快取檔案(像是圖片)路徑。保留空白以使用預設設定。", "LabelCancelled": "已取消", - "LabelCertificatePassword": "证书密码:", + "LabelCertificatePassword": "證書密碼:", "LabelCertificatePasswordHelp": "如果你的證書需要密碼,請在此輸入它。", "LabelChannels": "頻道:", "LabelCommunityRating": "討論區評分:", "LabelCriticRating": "影評評分:", - "LabelCustomCertificatePath": "自定 SSL 證書路徑:", - "LabelCustomCertificatePathHelp": "提供一個包含了證書和金鑰的 PKCS #12 文件的路徑以在一個自定義域名上啟動 TLS 支持。", + "LabelCustomCertificatePath": "自訂 SSL 證書路徑:", + "LabelCustomCertificatePathHelp": "提供包含證書和金鑰的 PKCS #12 文件的路徑以在自訂域名上啟用 TLS。", "LabelCustomCss": "自訂 CSS:", - "LabelCustomCssHelp": "應用自訂 CSS Web 界面。", + "LabelCustomCssHelp": "於 Web 介面套用您的自訂樣式。", "LabelCustomDeviceDisplayName": "顯示名稱:", "Depressed": "凹陷", "HeaderHome": "主頁", - "HeaderSelectMetadataPathHelp": "瀏覽或者鍵入一個文件庫路徑以用於保存原數據。請確保該文件庫可以被寫入。", - "HeaderSelectServerCachePathHelp": "瀏覽或者鍵入一個文件庫路徑以用於伺服器緩存檔案。請確保該文件庫可以被寫入。", - "LabelCustomDeviceDisplayNameHelp": "為設備提供一個自訂的顯示名稱,或者留空以使用設備自己報告的名稱。", + "HeaderSelectMetadataPathHelp": "瀏覽或者輸入路徑以用於保存中繼資料,請確保資料夾可以寫入。", + "HeaderSelectServerCachePathHelp": "瀏覽或者輸入路徑以用於伺服器快取檔案。請確保該資料夾可以被寫入。", + "LabelCustomDeviceDisplayNameHelp": "指定自訂的顯示名稱,或者留空以使用設備自己報告的名稱。", "LabelCustomRating": "自訂分級:", "LabelDashboardTheme": "儀表板佈景主題:", "LabelDateAdded": "新增日期:", @@ -960,5 +960,309 @@ "LabelDisplayLanguage": "顯示語言:", "LabelDisplayLanguageHelp": "翻譯 Jellyfin 是個進行中的專案。", "LabelDisplayMode": "顯示模式:", - "LabelDisplayName": "顯示名稱:" + "LabelDisplayName": "顯示名稱:", + "MessageNoPluginsInstalled": "您尚未安裝任何模組。", + "Mobile": "手機", + "Option3D": "3D", + "OptionEveryday": "每天", + "OptionMax": "最大", + "LabelAudioBitDepth": "音訊位元深度:", + "LabelBaseUrl": "根路徑:", + "LabelIconMaxHeight": "Icon 最高高度:", + "LabelHttpsPortHelp": "Jellyfin 的 HTTPS 伺服器應綁定的 TCP 端口。", + "LabelIconMaxHeightHelp": "通過 upnp:icon 的圖標最大解析度。", + "CopyStreamURL": "複製串流連結", + "MediaInfoDefault": "預設", + "MediaInfoStreamTypeAudio": "音訊", + "LabelDateAddedBehaviorHelp": "如果原本就有中繼資料,則將始終在這些選項之一之前使用它。", + "LabelScreensaver": "螢幕保護程式:", + "LabelSeasonNumber": "季:", + "LabelDropImageHere": "拖移圖片到這裡,或是點擊來選取。", + "LabelImageType": "圖片格式:", + "LabelIdentificationFieldHelp": "不區分大小寫的子字符串或正則表達式。", + "Large": "大", + "LabelTranscodingAudioCodec": "音訊編碼:", + "MessageSettingsSaved": "設定已儲存.", + "LabelTranscodePath": "轉檔路徑:", + "LabelTranscodes": "轉檔:", + "MinutesAfter": "分後", + "LabelVersion": "版本:", + "LabelVersionInstalled": "{0} 已安裝", + "DashboardVersionNumber": "版本:{0}", + "DashboardServerName": "伺服器:{0}", + "NoSubtitles": "沒有字幕", + "List": "清單", + "OptionAllowMediaPlayback": "允許播放媒體", + "OneChannel": "單聲道", + "RecommendationDirectedBy": "由 {0} 執導", + "RefreshQueued": "已排到佇列中。", + "ReleaseDate": "釋出日期", + "RepeatOne": "單曲重複", + "ResumeAt": "從 {0} 繼續播放", + "Settings": "設定", + "TabAccess": "存取", + "TabDevices": "裝置", + "TabDirectPlay": "直接播放", + "ThemeSongs": "主題曲", + "ThemeVideos": "主題曲影片", + "Upload": "上傳", + "PasswordResetHeader": "重設密碼", + "ScanLibrary": "掃描媒體庫", + "ValueAudioCodec": "音訊編碼:{0}", + "ValueCodec": "編碼:{0}", + "ValueSongCount": "{0} 首歌", + "LabelFileOrUrl": "檔案或路徑:", + "LabelKodiMetadataSaveImagePaths": "在 nfo 檔案中儲存圖片路徑", + "LabelLanNetworks": "區域網路:", + "LabelMetadataPathHelp": "指定自訂路徑來儲存下載的圖片與中繼資料。", + "LabelZipCode": "郵遞區號:", + "LabelffmpegPath": "FFmpeg 路徑:", + "LearnHowYouCanContribute": "了解如何貢獻。", + "Played": "已看過", + "RefreshMetadata": "重新抓取中繼資料", + "RememberMe": "記住我", + "Screenshots": "截圖", + "SendMessage": "傳送訊息", + "ShowAdvancedSettings": "顯示進階選項", + "ShowTitle": "顯示標題", + "ShowYear": "顯示年份", + "Shuffle": "隨ㄔㄧ", + "Smart": "智慧", + "HeaderFavoriteBooks": "最愛的書籍", + "LabelAudioBitrate": "音訊比特率:", + "LabelAudioCodec": "音訊編碼:", + "LabelBitrate": "比特率:", + "LabelAudioChannels": "音訊聲道:", + "LabelAudioSampleRate": "音訊取樣率:", + "LabelFont": "字體:", + "LabelFolder": "資料夾:", + "LabelDisplayOrder": "顯示順序:", + "LabelEnableBlastAliveMessages": "活動訊息", + "LabelEnableDlnaServer": "啟用 DLNA 伺服器", + "LabelEnableDlnaServerHelp": "允許網絡上的 UPnP 設備瀏覽和播放內容。", + "LabelEnableHardwareDecodingFor": "為以下啟用硬體解碼:", + "LabelEpisodeNumber": "集:", + "LabelBaseUrlHelp": "您可以在此處新增自訂路徑來進入伺服器。", + "LabelExtractChaptersDuringLibraryScan": "於媒體庫掃描時提取章節圖片", + "LabelHttpsPort": "本地 HTTPS 端口:", + "LabelFailed": "失敗", + "LabelSubtitles": "字幕:", + "LabelSupportedMediaTypes": "支援的媒體類型:", + "LabelTextBackgroundColor": "文字背景顏色:", + "LabelTextColor": "文字顏色:", + "LabelTextSize": "文字大小:", + "LabelTheme": "主題:", + "LabelTimeLimitHours": "時間限制(小時):", + "LabelTitle": "標題:", + "LabelTrackNumber": "追蹤編號:", + "LabelTranscodingFramerate": "轉檔幀率:", + "LabelTranscodingProgress": "轉檔進度:", + "LabelType": "類型:", + "LabelTypeMetadataDownloaders": "{0} 個中繼資料下載器:", + "LabelTypeText": "文本", + "LabelUsername": "使用者名稱:", + "DashboardOperatingSystem": "作業系統:{0}", + "LabelVideo": "影片:", + "LabelVideoCodec": "影片編碼:", + "LabelYear": "年:", + "LatestFromLibrary": "最新 {0}", + "Logo": "Logo", + "ManageLibrary": "管理媒體庫", + "MarkPlayed": "標記為已播放", + "MarkUnplayed": "標記為未播放", + "MediaInfoBitrate": "比特率", + "MediaInfoChannels": "聲道", + "MediaInfoCodec": "編碼", + "MediaInfoContainer": "容器", + "MediaInfoExternal": "外部", + "MediaInfoForced": "強迫", + "MediaInfoFramerate": "幀率", + "MediaInfoLanguage": "語言", + "MediaInfoLayout": "佈局", + "MediaInfoPath": "路徑", + "MessageAreYouSureYouWishToRemoveMediaFolder": "您確定要移除此媒體資料夾嗎?", + "MessageConfirmDeleteTunerDevice": "您確定要刪除這部裝置嗎?", + "MessageConfirmRecordingCancellation": "取消錄製?", + "MessageImageFileTypeAllowed": "僅支援 JPEG 和 PNG。", + "MessageInvalidUser": "錯誤的使用者名稱或密碼,請再試一次。", + "MessageItemSaved": "項目已儲存。", + "MessagePleaseWait": "請稍候。", + "MinutesBefore": "分前", + "MoreMediaInfo": "媒體資訊", + "MoveLeft": "移到左邊", + "MoveRight": "移到右邊", + "MusicAlbum": "專輯", + "MusicArtist": "演出者", + "MusicVideo": "MV", + "Name": "名稱", + "NewEpisodes": "新集數", + "NewEpisodesOnly": "僅限新集數", + "NextUp": "即將播放", + "No": "不要", + "Off": "關閉", + "OptionAdminUsers": "管理員", + "OptionAllowRemoteControlOthers": "允許其他使用者遠端控制", + "OptionAuto": "自動", + "OptionBlockBooks": "書", + "OptionBlockChannelContent": "網路頻道內容", + "OptionHasTrailer": "預告", + "OptionNone": "無", + "OptionPosterCard": "海報卡片", + "OptionProfileAudio": "音訊", + "OptionProfileVideo": "影片", + "OptionProfileVideoAudio": "影片與圖片", + "OptionReleaseDate": "釋出日期", + "OptionWeekends": "假日", + "PlayNextEpisodeAutomatically": "自動播放下一集", + "RecentlyWatched": "最近觀賞", + "RecommendationBecauseYouLike": "因為您喜歡 {0}", + "SearchResults": "搜尋結果", + "TabPlaylists": "播放清單", + "TabPlugins": "模組", + "Transcoding": "轉檔", + "ValueTimeLimitMultiHour": "時間限制:{0} 小時", + "ValueVideoCodec": "影片編碼:{0}", + "ViewAlbum": "查看專輯", + "LabelKodiMetadataDateFormatHelp": "NFO 檔案中的所有日期都將使用此格式。", + "LabelServerHostHelp": "192.168.1.100:8096 或是 https://myserver.com", + "LabelServerName": "伺服器名稱:", + "LabelTag": "標記:", + "LabelTranscodingTempPathHelp": "指定轉檔後的儲存路徑,留空將使用預設值。", + "LabelffmpegPathHelp": "路徑指向 FFmpeg,或是包含其的資料夾。", + "ManageRecording": "管理錄影", + "MessageAlreadyInstalled": "已安裝此版本。", + "MessageConfirmRestart": "您確定要重新啟動嗎?", + "Metadata": "ˊ中繼資料", + "OptionAllUsers": "所有使用者", + "OptionHomeVideos": "圖片", + "OptionPoster": "海報", + "OptionProfilePhoto": "圖片", + "OptionRegex": "正則表達式", + "OptionThumb": "預覽", + "OptionThumbCard": "預覽卡片", + "RecommendationBecauseYouWatched": "因為您看過 {0}", + "RepeatMode": "重複模式", + "Runtime": "運行時間", + "TV": "電視", + "TabUsers": "使用者", + "Trailers": "預告", + "LabelImageFetchersHelp": "按優先級啟用並排列您喜歡的圖片抓取器。", + "LabelDownMixAudioScale": "縮混時的音訊增強:", + "LabelDownMixAudioScaleHelp": "縮混時增強音訊。其中一個音軌將保持原始音量。", + "LabelDownloadLanguages": "下載語言:", + "LabelDynamicExternalId": "{0} Id:", + "LabelEasyPinCode": "簡易代碼:", + "LabelEnableAutomaticPortMap": "啟用自動端口映射", + "LabelEnableSingleImageInDidlLimit": "限制單個嵌入式圖片", + "LabelEndDate": "結束日期:", + "LabelLockItemToPreventChanges": "鎖定此項目來避免被更改", + "LabelManufacturer": "製造商", + "LabelLoginDisclaimerHelp": "顯示在登入頁面底部的訊息。", + "LabelManufacturerUrl": "製造商網址", + "LabelMaxChromecastBitrate": "Chromecast 串流解析度:", + "LabelOriginalTitle": "原始標題:", + "LabelSelectUsers": "選擇使用者:", + "LabelSelectVersionToInstall": "選擇要安裝的版本:", + "LabelSendNotificationToUsers": "傳送通知給:", + "LabelSortBy": "排序依:", + "LabelVideoBitrate": "影片比特率:", + "MediaInfoSize": "大小", + "MediaInfoTimestamp": "時間戳", + "MediaInfoSoftware": "軟體", + "MediaInfoStreamTypeData": "檔案", + "MediaInfoStreamTypeEmbeddedImage": "內嵌語言", + "MediaInfoStreamTypeSubtitle": "字幕", + "MediaInfoStreamTypeVideo": "影片", + "Menu": "選單", + "MetadataManager": "中繼資料管理器", + "NoPluginConfigurationMessage": "這個模組沒有設定選項可供更改。", + "NoSubtitlesHelp": "字幕不會自動讀取,但可於播放時手動選取。", + "Normal": "正常", + "OptionAllowContentDownloading": "允許下載及同步媒體", + "OptionAllowLinkSharing": "允許分享到社群媒體", + "OptionBlockMusic": "音樂", + "OptionBlockTrailers": "預告", + "OptionBlockTvShows": "電視節目", + "OptionList": "清單", + "TabMusicVideos": "MV", + "Yesterday": "昨天", + "Yes": "是", + "ButtonAddImage": "新增圖片", + "LabelForgotPasswordUsernameHelp": "假如您還記得的話,請輸入您的使用者名稱。", + "LabelFormat": "格式:", + "LabelFriendlyName": "好聽的名字:", + "LabelGroupMoviesIntoCollections": "將電影分組", + "LabelKodiMetadataDateFormat": "釋出日期格式:", + "LabelIconMaxWidth": "Icon 最寬寬度:", + "LabelGroupMoviesIntoCollectionsHelp": "顯示電影列表時,屬於相同集合的電影將作為分組項目顯示。", + "LabelH264EncodingPreset": "H264 解碼品質:", + "LabelHardwareAccelerationType": "硬體加速:", + "LabelIconMaxWidthHelp": "通過 upnp:icon 的圖標最大解析度。", + "LabelImportOnlyFavoriteChannels": "僅限收藏的頻道", + "LabelInNetworkSignInWithEasyPassword": "啟用以簡易密碼進行區域網路登入", + "LabelH264Crf": "H264 編碼 CRF:", + "LabelMaxStreamingBitrate": "最大串流畫質:", + "LabelMaxStreamingBitrateHelp": "指定最大串流比特率。", + "LabelMessageText": "訊息文字:", + "LabelMessageTitle": "訊息標題:", + "LabelMetadataDownloadLanguage": "首選下載語言:", + "LabelMetadata": "中繼資料:", + "LabelMethod": "方法:", + "LabelNewName": "新名稱:", + "LabelProfileAudioCodecs": "音訊編碼:", + "LabelProfileCodecs": "編碼:", + "LabelProfileVideoCodecs": "影片編碼:", + "Live": "直播", + "NumLocationsValue": "{0} 個資料夾", + "RemoveFromPlaylist": "從播放清單中移除", + "Repeat": "重複", + "RepeatAll": "重複全部", + "Screenshot": "截圖", + "Suggestions": "建議", + "TabCodecs": "編碼", + "TabContainers": "容器", + "TabDashboard": "控制台", + "TabDisplay": "顯示", + "TabFavorites": "最愛", + "TabLogs": "紀錄檔", + "TabNotifications": "通知", + "TabOther": "其他", + "TabParentalControl": "家長控制", + "TabScheduledTasks": "已排程的任務", + "TabStreaming": "串流", + "TagsValue": "標記:{0}", + "Thumb": "縮圖", + "TabResumeSettings": "繼續播放", + "ValueAlbumCount": "{0} 張專輯", + "ValueContainer": "容器:{0}", + "ValueEpisodeCount": "{0} 集", + "ValueDiscNumber": "光碟#{0}", + "ValueMinutes": "{0} 分", + "ValueMovieCount": "{0} 部電影", + "ValueMusicVideoCount": "{0} 部 MV", + "ValueOneAlbum": "1 張專輯", + "ValueOneEpisode": "1 集", + "ValueOneMovie": "1 部電影", + "ValueOneMusicVideo": "1 部 MV", + "ValueOneSong": "1 首歌", + "ValueSeconds": "{0} 秒", + "ValueTimeLimitSingleHour": "時間限制:1 小時", + "ViewArtist": "查看演出者", + "Watched": "已看過", + "Whitelist": "白名單", + "Tags": "標記", + "OptionProtocolHttp": "HTTP", + "TabNfoSettings": "NFO 設定", + "FetchingData": "獲取額外資料", + "LabelTranscodingVideoCodec": "影片編碼:", + "MediaInfoBitDepth": "位元深度", + "Mute": "靜音", + "MessageConfirmShutdown": "你確定要關閉伺服器嗎?", + "Never": "從不", + "OptionBlockMovies": "電影", + "CopyStreamURLSuccess": "連結複製成功。", + "PerfectMatch": "最佳配對", + "PictureInPicture": "浮窗播放", + "PlayFromBeginning": "從頭開始播放", + "PlayNext": "播放下一個" } From c565c9015b5700114ec5c38ba2b5b2bbae18f0ab Mon Sep 17 00:00:00 2001 From: Pika <15848969+ThatNerdyPikachu@users.noreply.github.com> Date: Sat, 26 Oct 2019 20:45:14 -0400 Subject: [PATCH 088/162] Actually make DatePlayed use a colon on ItemDetails --- src/controllers/itemdetailpage.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/controllers/itemdetailpage.js b/src/controllers/itemdetailpage.js index 03e0f68a9b..16cf3fe362 100644 --- a/src/controllers/itemdetailpage.js +++ b/src/controllers/itemdetailpage.js @@ -399,7 +399,7 @@ define(["loading", "appRouter", "layoutManager", "connectionManager", "cardBuild if (item.UserData && item.UserData.LastPlayedDate) { lastPlayedElement.classList.remove("hide"); var datePlayed = datetime.parseISO8601Date(item.UserData.LastPlayedDate); - lastPlayedElement.innerHTML = globalize.translate("DatePlayed") + " " + datetime.toLocaleDateString(datePlayed) + " " + datetime.getDisplayTime(datePlayed); + lastPlayedElement.innerHTML = globalize.translate("DatePlayed") + ": " + datetime.toLocaleDateString(datePlayed) + " " + datetime.getDisplayTime(datePlayed); } else { lastPlayedElement.classList.add("hide"); } From f64c1c08a3ada693b60decdd37d2863b0235d7ce Mon Sep 17 00:00:00 2001 From: delfino434 Date: Sun, 27 Oct 2019 06:55:02 +0000 Subject: [PATCH 089/162] Translated using Weblate (Turkish) Translation: Jellyfin/Jellyfin Web Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-web/tr/ --- src/strings/tr.json | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/strings/tr.json b/src/strings/tr.json index 11c1ecebe4..e2dde03926 100644 --- a/src/strings/tr.json +++ b/src/strings/tr.json @@ -429,5 +429,15 @@ "Desktop": "Masaüstü", "HeaderFavoriteShows": "Favori Diziler", "HeaderFavoriteEpisodes": "Favori Bölümler", - "BookLibraryHelp": "Ses ve ders kitapları desteklenir. {0} kitap adlandırma kılavuzunu {1} gözden geçirin." + "BookLibraryHelp": "Ses ve ders kitapları desteklenir. {0} kitap adlandırma kılavuzunu {1} gözden geçirin.", + "EnableDisplayMirroring": "Ekran Yansıtma", + "EnableExternalVideoPlayers": "Harici video oynatıcılar", + "EnableExternalVideoPlayersHelp": "Video oynatmaya başlarken harici bir oynatıcı menüsü görüntülenecektir.", + "EnableHardwareEncoding": "Donanım kodlamasını etkinleştir", + "EnableNextVideoInfoOverlayHelp": "Bir videonun sonunda, geçerli oynatma listesinde çıkan bir sonraki video hakkındaki bilgileri görüntüleyin.", + "EnablePhotos": "Fotoğrafları göster", + "EnableNextVideoInfoOverlay": "Oynatma sırasında bir sonraki video bilgisini göster", + "EnablePhotosHelp": "Görüntüler diğer medya dosyalarıyla birlikte algılanacak ve gösterilecektir.", + "EnableCinemaMode": "Sinema Modu", + "EnableColorCodedBackgrounds": "Renk kodlu arka planlar" } From 651a53d64a2d44abaa7bfd9bf1bf58e5a7fe4122 Mon Sep 17 00:00:00 2001 From: grafixeyehero Date: Sun, 27 Oct 2019 16:55:18 +0300 Subject: [PATCH 090/162] Move almada and require.js from source control to npm --- assets.js | 6 + package.json | 3 + src/bower_components/alameda/alameda.js | 419 --------------- src/bower_components/requirejs/require.js | 607 ---------------------- src/scripts/apploader.js | 2 +- webpack.common.js | 15 +- 6 files changed, 24 insertions(+), 1028 deletions(-) create mode 100644 assets.js delete mode 100644 src/bower_components/alameda/alameda.js delete mode 100644 src/bower_components/requirejs/require.js diff --git a/assets.js b/assets.js new file mode 100644 index 0000000000..98ec18c227 --- /dev/null +++ b/assets.js @@ -0,0 +1,6 @@ +const JS = [ + 'alameda/alameda.js', + 'requirejs/require.js' +]; + +module.exports = [...JS]; diff --git a/package.json b/package.json index bcbdd3dacc..051102239b 100644 --- a/package.json +++ b/package.json @@ -5,6 +5,7 @@ "repository": "https://github.com/jellyfin/jellyfin-web", "license": "GPL-2.0-or-later", "devDependencies": { + "clean-webpack-plugin": "^3.0.0", "copy-webpack-plugin": "^5.0.3", "css-loader": "^2.1.0", "eslint": "^5.16.0", @@ -16,12 +17,14 @@ "webpack-merge": "^4.2.2" }, "dependencies": { + "alameda": "^1.3.0", "flv.js": "^1.5.0", "hls.js": "^0.12.4", "howler": "^2.1.2", "jquery": "^3.4.1", "jstree": "^3.3.7", "libjass": "^0.11.0", + "requirejs": "^2.3.5", "shaka-player": "^2.5.5", "sortablejs": "^1.9.0", "swiper": "^3.4.2" diff --git a/src/bower_components/alameda/alameda.js b/src/bower_components/alameda/alameda.js deleted file mode 100644 index 4ac0f7496b..0000000000 --- a/src/bower_components/alameda/alameda.js +++ /dev/null @@ -1,419 +0,0 @@ -var requirejs, require, define; -! function(global, Promise, undef) { - function commentReplace(match, singlePrefix) { - return singlePrefix || "" - } - - function hasProp(obj, prop) { - return hasOwn.call(obj, prop) - } - - function getOwn(obj, prop) { - return obj && hasProp(obj, prop) && obj[prop] - } - - function obj() { - return Object.create(null) - } - - function eachProp(obj, func) { - var prop; - for (prop in obj) - if (hasProp(obj, prop) && func(obj[prop], prop)) break - } - - function mixin(target, source, force, deepStringMixin) { - return source && eachProp(source, function(value, prop) { - !force && hasProp(target, prop) || (!deepStringMixin || "object" != typeof value || !value || Array.isArray(value) || "function" == typeof value || value instanceof RegExp ? target[prop] = value : (target[prop] || (target[prop] = {}), mixin(target[prop], value, force, deepStringMixin))) - }), target - } - - function getGlobal(value) { - if (!value) return value; - var g = global; - return value.split(".").forEach(function(part) { - g = g[part] - }), g - } - - function newContext(contextName) { - function trimDots(ary) { - var i, part, length = ary.length; - for (i = 0; i < length; i++) - if ("." === (part = ary[i])) ary.splice(i, 1), i -= 1; - else if (".." === part) { - if (0 === i || 1 === i && ".." === ary[2] || ".." === ary[i - 1]) continue; - i > 0 && (ary.splice(i - 1, 2), i -= 2) - } - } - - function normalize(name, baseName, applyMap) { - var mapValue, nameParts, i, j, nameSegment, lastIndex, foundMap, foundI, foundStarMap, starI, baseParts = baseName && baseName.split("/"), - normalizedBaseParts = baseParts, - map = config.map, - starMap = map && map["*"]; - if (name && (name = name.split("/"), lastIndex = name.length - 1, config.nodeIdCompat && jsSuffixRegExp.test(name[lastIndex]) && (name[lastIndex] = name[lastIndex].replace(jsSuffixRegExp, "")), "." === name[0].charAt(0) && baseParts && (normalizedBaseParts = baseParts.slice(0, baseParts.length - 1), name = normalizedBaseParts.concat(name)), trimDots(name), name = name.join("/")), applyMap && map && (baseParts || starMap)) { - nameParts = name.split("/"); - outerLoop: for (i = nameParts.length; i > 0; i -= 1) { - if (nameSegment = nameParts.slice(0, i).join("/"), baseParts) - for (j = baseParts.length; j > 0; j -= 1) - if ((mapValue = getOwn(map, baseParts.slice(0, j).join("/"))) && (mapValue = getOwn(mapValue, nameSegment))) { - foundMap = mapValue, foundI = i; - break outerLoop - }! foundStarMap && starMap && getOwn(starMap, nameSegment) && (foundStarMap = getOwn(starMap, nameSegment), starI = i) - }!foundMap && foundStarMap && (foundMap = foundStarMap, foundI = starI), foundMap && (nameParts.splice(0, foundI, foundMap), name = nameParts.join("/")) - } - return getOwn(config.pkgs, name) || name - } - - function makeShimExports(value) { - function fn() { - var ret; - return value.init && (ret = value.init.apply(global, arguments)), ret || value.exports && getGlobal(value.exports) - } - return fn - } - - function takeQueue(anonId) { - var i, id, args, shim; - for (i = 0; i < queue.length; i += 1) { - if ("string" != typeof queue[i][0]) { - if (!anonId) break; - queue[i].unshift(anonId), anonId = undef - } - args = queue.shift(), id = args[0], i -= 1, id in defined || id in waiting || (id in deferreds ? main.apply(undef, args) : waiting[id] = args) - } - anonId && (shim = getOwn(config.shim, anonId) || {}, main(anonId, shim.deps || [], shim.exportsFn)) - } - - function makeRequire(relName, topLevel) { - var req = function(deps, callback, errback, alt) { - var name, cfg; - if (topLevel && takeQueue(), "string" == typeof deps) { - if (handlers[deps]) return handlers[deps](relName); - if (!((name = makeMap(deps, relName, !0).id) in defined)) throw new Error("Not loaded: " + name); - return defined[name] - } - return deps && !Array.isArray(deps) && (cfg = deps, deps = undef, Array.isArray(callback) && (deps = callback, callback = errback, errback = alt), topLevel) ? req.config(cfg)(deps, callback, errback) : (callback = callback || function() { - return slice.call(arguments, 0) - }, asyncResolve.then(function() { - return takeQueue(), main(undef, deps || [], callback, errback, relName) - })) - }; - return req.isBrowser = "undefined" != typeof document && "undefined" != typeof navigator, req.nameToUrl = function(moduleName, ext, skipExt) { - var paths, syms, i, parentModule, url, parentPath, bundleId, pkgMain = getOwn(config.pkgs, moduleName); - if (pkgMain && (moduleName = pkgMain), bundleId = getOwn(bundlesMap, moduleName)) return req.nameToUrl(bundleId, ext, skipExt); - if (urlRegExp.test(moduleName)) url = moduleName + (ext || ""); - else { - for (paths = config.paths, syms = moduleName.split("/"), i = syms.length; i > 0; i -= 1) - if (parentModule = syms.slice(0, i).join("/"), parentPath = getOwn(paths, parentModule)) { - Array.isArray(parentPath) && (parentPath = parentPath[0]), syms.splice(0, i, parentPath); - break - } url = syms.join("/"), url += ext || (/^data\:|^blob\:|\?/.test(url) || skipExt ? "" : ".js"), url = ("/" === url.charAt(0) || url.match(/^[\w\+\.\-]+:/) ? "" : config.baseUrl) + url - } - return config.urlArgs && !/^blob\:/.test(url) ? url + config.urlArgs(moduleName, url) : url - }, req.toUrl = function(moduleNamePlusExt) { - var ext, index = moduleNamePlusExt.lastIndexOf("."), - segment = moduleNamePlusExt.split("/")[0], - isRelative = "." === segment || ".." === segment; - return -1 !== index && (!isRelative || index > 1) && (ext = moduleNamePlusExt.substring(index, moduleNamePlusExt.length), moduleNamePlusExt = moduleNamePlusExt.substring(0, index)), req.nameToUrl(normalize(moduleNamePlusExt, relName), ext, !0) - }, req.defined = function(id) { - return makeMap(id, relName, !0).id in defined - }, req.specified = function(id) { - return (id = makeMap(id, relName, !0).id) in defined || id in deferreds - }, req - } - - function resolve(name, d, value) { - name && (defined[name] = value, requirejs.onResourceLoad && requirejs.onResourceLoad(context, d.map, d.deps)), d.finished = !0, d.resolve(value) - } - - function reject(d, err) { - d.finished = !0, d.rejected = !0, d.reject(err) - } - - function makeNormalize(relName) { - return function(name) { - return normalize(name, relName, !0) - } - } - - function defineModule(d) { - d.factoryCalled = !0; - var ret, name = d.map.id; - try { - ret = context.execCb(name, d.factory, d.values, defined[name]) - } catch (err) { - return reject(d, err) - } - name ? ret === undef && (d.cjsModule ? ret = d.cjsModule.exports : d.usingExports && (ret = defined[name])) : requireDeferreds.splice(requireDeferreds.indexOf(d), 1), resolve(name, d, ret) - } - - function depFinished(val, i) { - this.rejected || this.depDefined[i] || (this.depDefined[i] = !0, this.depCount += 1, this.values[i] = val, this.depending || this.depCount !== this.depMax || defineModule(this)) - } - - function makeDefer(name, calculatedMap) { - var d = {}; - return d.promise = new Promise(function(resolve, reject) { - d.resolve = resolve, d.reject = function(err) { - name || requireDeferreds.splice(requireDeferreds.indexOf(d), 1), reject(err) - } - }), d.map = name ? calculatedMap || makeMap(name) : {}, d.depCount = 0, d.depMax = 0, d.values = [], d.depDefined = [], d.depFinished = depFinished, d.map.pr && (d.deps = [makeMap(d.map.pr)]), d - } - - function getDefer(name, calculatedMap) { - var d; - return name ? (d = name in deferreds && deferreds[name]) || (d = deferreds[name] = makeDefer(name, calculatedMap)) : (d = makeDefer(), requireDeferreds.push(d)), d - } - - function makeErrback(d, name) { - return function(err) { - d.rejected || (err.dynaId || (err.dynaId = "id" + (errCount += 1), err.requireModules = [name]), reject(d, err)) - } - } - - function waitForDep(depMap, relName, d, i) { - d.depMax += 1, callDep(depMap, relName).then(function(val) { - d.depFinished(val, i) - }, makeErrback(d, depMap.id)).catch(makeErrback(d, d.map.id)) - } - - function makeLoad(id) { - function load(value) { - fromTextCalled || resolve(id, getDefer(id), value) - } - var fromTextCalled; - return load.error = function(err) { - reject(getDefer(id), err) - }, load.fromText = function(text, textAlt) { - var execError, d = getDefer(id), - map = makeMap(makeMap(id).n), - plainId = map.id; - fromTextCalled = !0, d.factory = function(p, val) { - return val - }, textAlt && (text = textAlt), hasProp(config.config, id) && (config.config[plainId] = config.config[id]); - try { - req.exec(text) - } catch (e) { - execError = new Error("fromText eval for " + plainId + " failed: " + e), execError.requireType = "fromtexteval", reject(d, execError) - } - takeQueue(plainId), d.deps = [map], waitForDep(map, null, d, d.deps.length) - }, load - } - - function callPlugin(plugin, map, relName) { - plugin.load(map.n, makeRequire(relName), makeLoad(map.id), config) - } - - function splitPrefix(name) { - var prefix, index = name ? name.indexOf("!") : -1; - return index > -1 && (prefix = name.substring(0, index), name = name.substring(index + 1, name.length)), [prefix, name] - } - - function breakCycle(d, traced, processed) { - var id = d.map.id; - traced[id] = !0, !d.finished && d.deps && d.deps.forEach(function(depMap) { - var depId = depMap.id, - dep = !hasProp(handlers, depId) && getDefer(depId, depMap); - !dep || dep.finished || processed[depId] || (hasProp(traced, depId) ? d.deps.forEach(function(depMap, i) { - depMap.id === depId && d.depFinished(defined[depId], i) - }) : breakCycle(dep, traced, processed)) - }), processed[id] = !0 - } - - function check(d) { - var err, mid, dfd, notFinished = [], - waitInterval = 1e3 * config.waitSeconds, - expired = waitInterval && startTime + waitInterval < (new Date).getTime(); - if (0 === loadCount && (d ? d.finished || breakCycle(d, {}, {}) : requireDeferreds.length && requireDeferreds.forEach(function(d) { - breakCycle(d, {}, {}) - })), expired) { - for (mid in deferreds) dfd = deferreds[mid], dfd.finished || notFinished.push(dfd.map.id); - err = new Error("Timeout for modules: " + notFinished), err.requireModules = notFinished, err.requireType = "timeout", notFinished.forEach(function(id) { - reject(getDefer(id), err) - }) - } else(loadCount || requireDeferreds.length) && (checkingLater || (checkingLater = !0, setTimeout(function() { - checkingLater = !1, check() - }, 70))) - } - - function delayedError(e) { - console.log(e.stack); - return setTimeout(function() { - e.dynaId && trackedErrors[e.dynaId] || (trackedErrors[e.dynaId] = !0, req.onError(e)) - }), e - } - var req, main, makeMap, callDep, handlers, checkingLater, load, context, defined = obj(), - waiting = obj(), - config = { - waitSeconds: 7, - baseUrl: "./", - paths: {}, - bundles: {}, - pkgs: {}, - shim: {}, - config: {} - }, - mapCache = obj(), - requireDeferreds = [], - deferreds = obj(), - calledDefine = obj(), - calledPlugin = obj(), - loadCount = 0, - startTime = (new Date).getTime(), - errCount = 0, - trackedErrors = obj(), - urlFetched = obj(), - bundlesMap = obj(), - asyncResolve = Promise.resolve(undefined); - return load = "function" == typeof importScripts ? function(map) { - var url = map.url; - urlFetched[url] || (urlFetched[url] = !0, getDefer(map.id), importScripts(url), takeQueue(map.id)) - } : function(map) { - var script, id = map.id, - url = map.url; - urlFetched[url] || (urlFetched[url] = !0, script = document.createElement("script"), script.setAttribute("data-requiremodule", id), script.type = config.scriptType || "text/javascript", script.charset = "utf-8", script.async = !0, loadCount += 1, script.addEventListener("load", function() { - loadCount -= 1, takeQueue(id) - }, !1), script.addEventListener("error", function() { - loadCount -= 1; - var err, pathConfig = getOwn(config.paths, id); - if (pathConfig && Array.isArray(pathConfig) && pathConfig.length > 1) { - script.parentNode.removeChild(script), pathConfig.shift(); - var d = getDefer(id); - d.map = makeMap(id), d.map.url = req.nameToUrl(id), load(d.map) - } else err = new Error("Load failed: " + id + ": " + script.src), err.requireModules = [id], err.requireType = "scripterror", reject(getDefer(id), err) - }, !1), script.src = url, 10 === document.documentMode ? asap.then(function() { - document.head.appendChild(script) - }) : document.head.appendChild(script)) - }, callDep = function(map, relName) { - var args, bundleId, name = map.id, - shim = config.shim[name]; - if (name in waiting) args = waiting[name], delete waiting[name], main.apply(undef, args); - else if (!(name in deferreds)) - if (map.pr) { - if (!(bundleId = getOwn(bundlesMap, name))) return callDep(makeMap(map.pr)).then(function(plugin) { - var newMap = map.prn ? map : makeMap(name, relName, !0), - newId = newMap.id, - shim = getOwn(config.shim, newId); - return newId in calledPlugin || (calledPlugin[newId] = !0, shim && shim.deps ? req(shim.deps, function() { - callPlugin(plugin, newMap, relName) - }) : callPlugin(plugin, newMap, relName)), getDefer(newId).promise - }); - map.url = req.nameToUrl(bundleId), load(map) - } else shim && shim.deps ? req(shim.deps, function() { - load(map) - }) : load(map); - return getDefer(name).promise - }, makeMap = function(name, relName, applyMap) { - if ("string" != typeof name) return name; - var plugin, url, parts, prefix, result, prefixNormalized, cacheKey = name + " & " + (relName || "") + " & " + !!applyMap; - return parts = splitPrefix(name), prefix = parts[0], name = parts[1], !prefix && cacheKey in mapCache ? mapCache[cacheKey] : (prefix && (prefix = normalize(prefix, relName, applyMap), plugin = prefix in defined && defined[prefix]), prefix ? plugin && plugin.normalize ? (name = plugin.normalize(name, makeNormalize(relName)), prefixNormalized = !0) : name = -1 === name.indexOf("!") ? normalize(name, relName, applyMap) : name : (name = normalize(name, relName, applyMap), parts = splitPrefix(name), prefix = parts[0], name = parts[1], url = req.nameToUrl(name)), result = { - id: prefix ? prefix + "!" + name : name, - n: name, - pr: prefix, - url: url, - prn: prefix && prefixNormalized - }, prefix || (mapCache[cacheKey] = result), result) - }, handlers = { - require: function(name) { - return makeRequire(name) - }, - exports: function(name) { - var e = defined[name]; - return void 0 !== e ? e : defined[name] = {} - }, - module: function(name) { - return { - id: name, - uri: "", - exports: handlers.exports(name), - config: function() { - return getOwn(config.config, name) || {} - } - } - } - }, main = function(name, deps, factory, errback, relName) { - if (name) { - if (name in calledDefine) return; - calledDefine[name] = !0 - } - var d = getDefer(name); - return deps && !Array.isArray(deps) && (factory = deps, deps = []), deps = deps ? slice.call(deps, 0) : null, errback || (hasProp(config, "defaultErrback") ? config.defaultErrback && (errback = config.defaultErrback) : errback = delayedError), errback && d.promise.catch(errback), relName = relName || name, "function" == typeof factory ? (!deps.length && factory.length && (factory.toString().replace(commentRegExp, commentReplace).replace(cjsRequireRegExp, function(match, dep) { - deps.push(dep) - }), deps = (1 === factory.length ? ["require"] : ["require", "exports", "module"]).concat(deps)), d.factory = factory, d.deps = deps, d.depending = !0, deps.forEach(function(depName, i) { - var depMap; - deps[i] = depMap = makeMap(depName, relName, !0), depName = depMap.id, "require" === depName ? d.values[i] = handlers.require(name) : "exports" === depName ? (d.values[i] = handlers.exports(name), d.usingExports = !0) : "module" === depName ? d.values[i] = d.cjsModule = handlers.module(name) : void 0 === depName ? d.values[i] = void 0 : waitForDep(depMap, relName, d, i) - }), d.depending = !1, d.depCount === d.depMax && defineModule(d)) : name && resolve(name, d, factory), startTime = (new Date).getTime(), name || check(d), d.promise - }, req = makeRequire(null, !0), req.config = function(cfg) { - if (cfg.context && cfg.context !== contextName) { - var existingContext = getOwn(contexts, cfg.context); - return existingContext ? existingContext.req.config(cfg) : newContext(cfg.context).config(cfg) - } - if (mapCache = obj(), cfg.baseUrl && "/" !== cfg.baseUrl.charAt(cfg.baseUrl.length - 1) && (cfg.baseUrl += "/"), "string" == typeof cfg.urlArgs) { - var urlArgs = cfg.urlArgs; - cfg.urlArgs = function(id, url) { - return (-1 === url.indexOf("?") ? "?" : "&") + urlArgs - } - } - var shim = config.shim, - objs = { - paths: !0, - bundles: !0, - config: !0, - map: !0 - }; - return eachProp(cfg, function(value, prop) { - objs[prop] ? (config[prop] || (config[prop] = {}), mixin(config[prop], value, !0, !0)) : config[prop] = value - }), cfg.bundles && eachProp(cfg.bundles, function(value, prop) { - value.forEach(function(v) { - v !== prop && (bundlesMap[v] = prop) - }) - }), cfg.shim && (eachProp(cfg.shim, function(value, id) { - Array.isArray(value) && (value = { - deps: value - }), !value.exports && !value.init || value.exportsFn || (value.exportsFn = makeShimExports(value)), shim[id] = value - }), config.shim = shim), cfg.packages && cfg.packages.forEach(function(pkgObj) { - var location, name; - pkgObj = "string" == typeof pkgObj ? { - name: pkgObj - } : pkgObj, name = pkgObj.name, location = pkgObj.location, location && (config.paths[name] = pkgObj.location), config.pkgs[name] = pkgObj.name + "/" + (pkgObj.main || "main").replace(currDirRegExp, "").replace(jsSuffixRegExp, "") - }), (cfg.deps || cfg.callback) && req(cfg.deps, cfg.callback), req - }, req.onError = function(err) { - throw err - }, context = { - id: contextName, - defined: defined, - waiting: waiting, - config: config, - deferreds: deferreds, - req: req, - execCb: function(name, callback, args, exports) { - return callback.apply(exports, args) - } - }, contexts[contextName] = context, req - } - if (!Promise) throw new Error("No Promise implementation available"); - var topReq, dataMain, src, subPath, bootstrapConfig = requirejs || require, - hasOwn = Object.prototype.hasOwnProperty, - contexts = {}, - queue = [], - currDirRegExp = /^\.\//, - urlRegExp = /^\/|\:|\?|\.js$/, - commentRegExp = /\/\*[\s\S]*?\*\/|([^:"'=]|^)\/\/.*$/gm, - cjsRequireRegExp = /[^.]\s*require\s*\(\s*["']([^'"\s]+)["']\s*\)/g, - jsSuffixRegExp = /\.js$/, - slice = Array.prototype.slice; - if ("function" != typeof requirejs) { - var asap = Promise.resolve(void 0); - requirejs = topReq = newContext("_"), "function" != typeof require && (require = topReq), topReq.exec = function(text) { - return eval(text) - }, topReq.contexts = contexts, define = function() { - queue.push(slice.call(arguments, 0)) - }, define.amd = { - jQuery: !0 - }, bootstrapConfig && topReq.config(bootstrapConfig), topReq.isBrowser && !contexts._.config.skipDataMain && (dataMain = document.querySelectorAll("script[data-main]")[0], (dataMain = dataMain && dataMain.getAttribute("data-main")) && (dataMain = dataMain.replace(jsSuffixRegExp, ""), bootstrapConfig && bootstrapConfig.baseUrl || -1 !== dataMain.indexOf("!") || (src = dataMain.split("/"), dataMain = src.pop(), subPath = src.length ? src.join("/") + "/" : "./", topReq.config({ - baseUrl: subPath - })), topReq([dataMain]))) - } -}(this, "undefined" != typeof Promise ? Promise : void 0); diff --git a/src/bower_components/requirejs/require.js b/src/bower_components/requirejs/require.js deleted file mode 100644 index 71ac94c3b5..0000000000 --- a/src/bower_components/requirejs/require.js +++ /dev/null @@ -1,607 +0,0 @@ -var requirejs, require, define; -! function(global, setTimeout) { - function commentReplace(match, singlePrefix) { - return singlePrefix || "" - } - - function isFunction(it) { - return "[object Function]" === ostring.call(it) - } - - function isArray(it) { - return "[object Array]" === ostring.call(it) - } - - function each(ary, func) { - if (ary) { - var i; - for (i = 0; i < ary.length && (!ary[i] || !func(ary[i], i, ary)); i += 1); - } - } - - function eachReverse(ary, func) { - if (ary) { - var i; - for (i = ary.length - 1; i > -1 && (!ary[i] || !func(ary[i], i, ary)); i -= 1); - } - } - - function hasProp(obj, prop) { - return hasOwn.call(obj, prop) - } - - function getOwn(obj, prop) { - return hasProp(obj, prop) && obj[prop] - } - - function eachProp(obj, func) { - var prop; - for (prop in obj) - if (hasProp(obj, prop) && func(obj[prop], prop)) break - } - - function mixin(target, source, force, deepStringMixin) { - return source && eachProp(source, function(value, prop) { - !force && hasProp(target, prop) || (!deepStringMixin || "object" != typeof value || !value || isArray(value) || isFunction(value) || value instanceof RegExp ? target[prop] = value : (target[prop] || (target[prop] = {}), mixin(target[prop], value, force, deepStringMixin))) - }), target - } - - function bind(obj, fn) { - return function() { - return fn.apply(obj, arguments) - } - } - - function scripts() { - return document.getElementsByTagName("script") - } - - function defaultOnError(err) { - throw err - } - - function getGlobal(value) { - if (!value) return value; - var g = global; - return each(value.split("."), function(part) { - g = g[part] - }), g - } - - function makeError(id, msg, err, requireModules) { - var e = new Error(msg + "\nhttp://requirejs.org/docs/errors.html#" + id); - return e.requireType = id, e.requireModules = requireModules, err && (e.originalError = err), e - } - - function newContext(contextName) { - function trimDots(ary) { - var i, part; - for (i = 0; i < ary.length; i++) - if ("." === (part = ary[i])) ary.splice(i, 1), i -= 1; - else if (".." === part) { - if (0 === i || 1 === i && ".." === ary[2] || ".." === ary[i - 1]) continue; - i > 0 && (ary.splice(i - 1, 2), i -= 2) - } - } - - function normalize(name, baseName, applyMap) { - var mapValue, nameParts, i, j, nameSegment, lastIndex, foundMap, foundI, foundStarMap, starI, normalizedBaseParts, baseParts = baseName && baseName.split("/"), - map = config.map, - starMap = map && map["*"]; - if (name && (name = name.split("/"), lastIndex = name.length - 1, config.nodeIdCompat && jsSuffixRegExp.test(name[lastIndex]) && (name[lastIndex] = name[lastIndex].replace(jsSuffixRegExp, "")), "." === name[0].charAt(0) && baseParts && (normalizedBaseParts = baseParts.slice(0, baseParts.length - 1), name = normalizedBaseParts.concat(name)), trimDots(name), name = name.join("/")), applyMap && map && (baseParts || starMap)) { - nameParts = name.split("/"); - outerLoop: for (i = nameParts.length; i > 0; i -= 1) { - if (nameSegment = nameParts.slice(0, i).join("/"), baseParts) - for (j = baseParts.length; j > 0; j -= 1) - if ((mapValue = getOwn(map, baseParts.slice(0, j).join("/"))) && (mapValue = getOwn(mapValue, nameSegment))) { - foundMap = mapValue, foundI = i; - break outerLoop - }! foundStarMap && starMap && getOwn(starMap, nameSegment) && (foundStarMap = getOwn(starMap, nameSegment), starI = i) - }!foundMap && foundStarMap && (foundMap = foundStarMap, foundI = starI), foundMap && (nameParts.splice(0, foundI, foundMap), name = nameParts.join("/")) - } - return getOwn(config.pkgs, name) || name - } - - function removeScript(name) { - isBrowser && each(scripts(), function(scriptNode) { - if (scriptNode.getAttribute("data-requiremodule") === name && scriptNode.getAttribute("data-requirecontext") === context.contextName) return scriptNode.parentNode.removeChild(scriptNode), !0 - }) - } - - function hasPathFallback(id) { - var pathConfig = getOwn(config.paths, id); - if (pathConfig && isArray(pathConfig) && pathConfig.length > 1) return pathConfig.shift(), context.require.undef(id), context.makeRequire(null, { - skipMap: !0 - })([id]), !0 - } - - function splitPrefix(name) { - var prefix, index = name ? name.indexOf("!") : -1; - return index > -1 && (prefix = name.substring(0, index), name = name.substring(index + 1, name.length)), [prefix, name] - } - - function makeModuleMap(name, parentModuleMap, isNormalized, applyMap) { - var url, pluginModule, suffix, nameParts, prefix = null, - parentName = parentModuleMap ? parentModuleMap.name : null, - originalName = name, - isDefine = !0, - normalizedName = ""; - return name || (isDefine = !1, name = "_@r" + (requireCounter += 1)), nameParts = splitPrefix(name), prefix = nameParts[0], name = nameParts[1], prefix && (prefix = normalize(prefix, parentName, applyMap), pluginModule = getOwn(defined, prefix)), name && (prefix ? normalizedName = isNormalized ? name : pluginModule && pluginModule.normalize ? pluginModule.normalize(name, function(name) { - return normalize(name, parentName, applyMap) - }) : -1 === name.indexOf("!") ? normalize(name, parentName, applyMap) : name : (normalizedName = normalize(name, parentName, applyMap), nameParts = splitPrefix(normalizedName), prefix = nameParts[0], normalizedName = nameParts[1], isNormalized = !0, url = context.nameToUrl(normalizedName))), suffix = !prefix || pluginModule || isNormalized ? "" : "_unnormalized" + (unnormalizedCounter += 1), { - prefix: prefix, - name: normalizedName, - parentMap: parentModuleMap, - unnormalized: !!suffix, - url: url, - originalName: originalName, - isDefine: isDefine, - id: (prefix ? prefix + "!" + normalizedName : normalizedName) + suffix - } - } - - function getModule(depMap) { - var id = depMap.id, - mod = getOwn(registry, id); - return mod || (mod = registry[id] = new context.Module(depMap)), mod - } - - function on(depMap, name, fn) { - var id = depMap.id, - mod = getOwn(registry, id); - !hasProp(defined, id) || mod && !mod.defineEmitComplete ? (mod = getModule(depMap), mod.error && "error" === name ? fn(mod.error) : mod.on(name, fn)) : "defined" === name && fn(defined[id]) - } - - function onError(err, errback) { - var ids = err.requireModules, - notified = !1; - errback ? errback(err) : (each(ids, function(id) { - var mod = getOwn(registry, id); - mod && (mod.error = err, mod.events.error && (notified = !0, mod.emit("error", err))) - }), notified || req.onError(err)) - } - - function takeGlobalQueue() { - globalDefQueue.length && (each(globalDefQueue, function(queueItem) { - var id = queueItem[0]; - "string" == typeof id && (context.defQueueMap[id] = !0), defQueue.push(queueItem) - }), globalDefQueue = []) - } - - function cleanRegistry(id) { - delete registry[id], delete enabledRegistry[id] - } - - function breakCycle(mod, traced, processed) { - var id = mod.map.id; - mod.error ? mod.emit("error", mod.error) : (traced[id] = !0, each(mod.depMaps, function(depMap, i) { - var depId = depMap.id, - dep = getOwn(registry, depId); - !dep || mod.depMatched[i] || processed[depId] || (getOwn(traced, depId) ? (mod.defineDep(i, defined[depId]), mod.check()) : breakCycle(dep, traced, processed)) - }), processed[id] = !0) - } - - function checkLoaded() { - var err, usingPathFallback, waitInterval = 1e3 * config.waitSeconds, - expired = waitInterval && context.startTime + waitInterval < (new Date).getTime(), - noLoads = [], - reqCalls = [], - stillLoading = !1, - needCycleCheck = !0; - if (!inCheckLoaded) { - if (inCheckLoaded = !0, eachProp(enabledRegistry, function(mod) { - var map = mod.map, - modId = map.id; - if (mod.enabled && (map.isDefine || reqCalls.push(mod), !mod.error)) - if (!mod.inited && expired) hasPathFallback(modId) ? (usingPathFallback = !0, stillLoading = !0) : (noLoads.push(modId), removeScript(modId)); - else if (!mod.inited && mod.fetched && map.isDefine && (stillLoading = !0, !map.prefix)) return needCycleCheck = !1 - }), expired && noLoads.length) return err = makeError("timeout", "Load timeout for modules: " + noLoads, null, noLoads), err.contextName = context.contextName, onError(err); - needCycleCheck && each(reqCalls, function(mod) { - breakCycle(mod, {}, {}) - }), expired && !usingPathFallback || !stillLoading || !isBrowser && !isWebWorker || checkLoadedTimeoutId || (checkLoadedTimeoutId = setTimeout(function() { - checkLoadedTimeoutId = 0, checkLoaded() - }, 50)), inCheckLoaded = !1 - } - } - - function callGetModule(args) { - hasProp(defined, args[0]) || getModule(makeModuleMap(args[0], null, !0)).init(args[1], args[2]) - } - - function removeListener(node, func, name, ieName) { - node.detachEvent && !isOpera ? ieName && node.detachEvent(ieName, func) : node.removeEventListener(name, func, !1) - } - - function getScriptData(evt) { - var node = evt.currentTarget || evt.srcElement; - return removeListener(node, context.onScriptLoad, "load", "onreadystatechange"), removeListener(node, context.onScriptError, "error"), { - node: node, - id: node && node.getAttribute("data-requiremodule") - } - } - - function intakeDefines() { - var args; - for (takeGlobalQueue(); defQueue.length;) { - if (args = defQueue.shift(), null === args[0]) return onError(makeError("mismatch", "Mismatched anonymous define() module: " + args[args.length - 1])); - callGetModule(args) - } - context.defQueueMap = {} - } - var inCheckLoaded, Module, context, handlers, checkLoadedTimeoutId, config = { - waitSeconds: 7, - baseUrl: "./", - paths: {}, - bundles: {}, - pkgs: {}, - shim: {}, - config: {} - }, - registry = {}, - enabledRegistry = {}, - undefEvents = {}, - defQueue = [], - defined = {}, - urlFetched = {}, - bundlesMap = {}, - requireCounter = 1, - unnormalizedCounter = 1; - return handlers = { - require: function(mod) { - return mod.require ? mod.require : mod.require = context.makeRequire(mod.map) - }, - exports: function(mod) { - if (mod.usingExports = !0, mod.map.isDefine) return mod.exports ? defined[mod.map.id] = mod.exports : mod.exports = defined[mod.map.id] = {} - }, - module: function(mod) { - return mod.module ? mod.module : mod.module = { - id: mod.map.id, - uri: mod.map.url, - config: function() { - return getOwn(config.config, mod.map.id) || {} - }, - exports: mod.exports || (mod.exports = {}) - } - } - }, Module = function(map) { - this.events = getOwn(undefEvents, map.id) || {}, this.map = map, this.shim = getOwn(config.shim, map.id), this.depExports = [], this.depMaps = [], this.depMatched = [], this.pluginMaps = {}, this.depCount = 0 - }, Module.prototype = { - init: function(depMaps, factory, errback, options) { - options = options || {}, this.inited || (this.factory = factory, errback ? this.on("error", errback) : this.events.error && (errback = bind(this, function(err) { - this.emit("error", err) - })), this.depMaps = depMaps && depMaps.slice(0), this.errback = errback, this.inited = !0, this.ignore = options.ignore, options.enabled || this.enabled ? this.enable() : this.check()) - }, - defineDep: function(i, depExports) { - this.depMatched[i] || (this.depMatched[i] = !0, this.depCount -= 1, this.depExports[i] = depExports) - }, - fetch: function() { - if (!this.fetched) { - this.fetched = !0, context.startTime = (new Date).getTime(); - var map = this.map; - if (!this.shim) return map.prefix ? this.callPlugin() : this.load(); - context.makeRequire(this.map, { - enableBuildCallback: !0 - })(this.shim.deps || [], bind(this, function() { - return map.prefix ? this.callPlugin() : this.load() - })) - } - }, - load: function() { - var url = this.map.url; - urlFetched[url] || (urlFetched[url] = !0, context.load(this.map.id, url)) - }, - check: function() { - if (this.enabled && !this.enabling) { - var err, cjsModule, id = this.map.id, - depExports = this.depExports, - exports = this.exports, - factory = this.factory; - if (this.inited) { - if (this.error) this.emit("error", this.error); - else if (!this.defining) { - if (this.defining = !0, this.depCount < 1 && !this.defined) { - if (isFunction(factory)) { - if (this.events.error && this.map.isDefine || req.onError !== defaultOnError) try { - exports = context.execCb(id, factory, depExports, exports) - } catch (e) { - err = e - } else exports = context.execCb(id, factory, depExports, exports); - if (this.map.isDefine && void 0 === exports && (cjsModule = this.module, cjsModule ? exports = cjsModule.exports : this.usingExports && (exports = this.exports)), err) return err.requireMap = this.map, err.requireModules = this.map.isDefine ? [this.map.id] : null, err.requireType = this.map.isDefine ? "define" : "require", onError(this.error = err) - } else exports = factory; - if (this.exports = exports, this.map.isDefine && !this.ignore && (defined[id] = exports, req.onResourceLoad)) { - var resLoadMaps = []; - each(this.depMaps, function(depMap) { - resLoadMaps.push(depMap.normalizedMap || depMap) - }), req.onResourceLoad(context, this.map, resLoadMaps) - } - cleanRegistry(id), this.defined = !0 - } - this.defining = !1, this.defined && !this.defineEmitted && (this.defineEmitted = !0, this.emit("defined", this.exports), this.defineEmitComplete = !0) - } - } else hasProp(context.defQueueMap, id) || this.fetch() - } - }, - callPlugin: function() { - var map = this.map, - id = map.id, - pluginMap = makeModuleMap(map.prefix); - this.depMaps.push(pluginMap), on(pluginMap, "defined", bind(this, function(plugin) { - var load, normalizedMap, normalizedMod, bundleId = getOwn(bundlesMap, this.map.id), - name = this.map.name, - parentName = this.map.parentMap ? this.map.parentMap.name : null, - localRequire = context.makeRequire(map.parentMap, { - enableBuildCallback: !0 - }); - return this.map.unnormalized ? (plugin.normalize && (name = plugin.normalize(name, function(name) { - return normalize(name, parentName, !0) - }) || ""), normalizedMap = makeModuleMap(map.prefix + "!" + name, this.map.parentMap, !0), on(normalizedMap, "defined", bind(this, function(value) { - this.map.normalizedMap = normalizedMap, this.init([], function() { - return value - }, null, { - enabled: !0, - ignore: !0 - }) - })), void((normalizedMod = getOwn(registry, normalizedMap.id)) && (this.depMaps.push(normalizedMap), this.events.error && normalizedMod.on("error", bind(this, function(err) { - this.emit("error", err) - })), normalizedMod.enable()))) : bundleId ? (this.map.url = context.nameToUrl(bundleId), void this.load()) : (load = bind(this, function(value) { - this.init([], function() { - return value - }, null, { - enabled: !0 - }) - }), load.error = bind(this, function(err) { - this.inited = !0, this.error = err, err.requireModules = [id], eachProp(registry, function(mod) { - 0 === mod.map.id.indexOf(id + "_unnormalized") && cleanRegistry(mod.map.id) - }), onError(err) - }), load.fromText = bind(this, function(text, textAlt) { - var moduleName = map.name, - moduleMap = makeModuleMap(moduleName), - hasInteractive = useInteractive; - textAlt && (text = textAlt), hasInteractive && (useInteractive = !1), getModule(moduleMap), hasProp(config.config, id) && (config.config[moduleName] = config.config[id]); - try { - req.exec(text) - } catch (e) { - return onError(makeError("fromtexteval", "fromText eval for " + id + " failed: " + e, e, [id])) - } - hasInteractive && (useInteractive = !0), this.depMaps.push(moduleMap), context.completeLoad(moduleName), localRequire([moduleName], load) - }), void plugin.load(map.name, localRequire, load, config)) - })), context.enable(pluginMap, this), this.pluginMaps[pluginMap.id] = pluginMap - }, - enable: function() { - enabledRegistry[this.map.id] = this, this.enabled = !0, this.enabling = !0, each(this.depMaps, bind(this, function(depMap, i) { - var id, mod, handler; - if ("string" == typeof depMap) { - if (depMap = makeModuleMap(depMap, this.map.isDefine ? this.map : this.map.parentMap, !1, !this.skipMap), this.depMaps[i] = depMap, handler = getOwn(handlers, depMap.id)) return void(this.depExports[i] = handler(this)); - this.depCount += 1, on(depMap, "defined", bind(this, function(depExports) { - this.undefed || (this.defineDep(i, depExports), this.check()) - })), this.errback ? on(depMap, "error", bind(this, this.errback)) : this.events.error && on(depMap, "error", bind(this, function(err) { - this.emit("error", err) - })) - } - id = depMap.id, mod = registry[id], hasProp(handlers, id) || !mod || mod.enabled || context.enable(depMap, this) - })), eachProp(this.pluginMaps, bind(this, function(pluginMap) { - var mod = getOwn(registry, pluginMap.id); - mod && !mod.enabled && context.enable(pluginMap, this) - })), this.enabling = !1, this.check() - }, - on: function(name, cb) { - var cbs = this.events[name]; - cbs || (cbs = this.events[name] = []), cbs.push(cb) - }, - emit: function(name, evt) { - each(this.events[name], function(cb) { - cb(evt) - }), "error" === name && delete this.events[name] - } - }, context = { - config: config, - contextName: contextName, - registry: registry, - defined: defined, - urlFetched: urlFetched, - defQueue: defQueue, - defQueueMap: {}, - Module: Module, - makeModuleMap: makeModuleMap, - nextTick: req.nextTick, - onError: onError, - configure: function(cfg) { - if (cfg.baseUrl && "/" !== cfg.baseUrl.charAt(cfg.baseUrl.length - 1) && (cfg.baseUrl += "/"), "string" == typeof cfg.urlArgs) { - var urlArgs = cfg.urlArgs; - cfg.urlArgs = function(id, url) { - return (-1 === url.indexOf("?") ? "?" : "&") + urlArgs - } - } - var shim = config.shim, - objs = { - paths: !0, - bundles: !0, - config: !0, - map: !0 - }; - eachProp(cfg, function(value, prop) { - objs[prop] ? (config[prop] || (config[prop] = {}), mixin(config[prop], value, !0, !0)) : config[prop] = value - }), cfg.bundles && eachProp(cfg.bundles, function(value, prop) { - each(value, function(v) { - v !== prop && (bundlesMap[v] = prop) - }) - }), cfg.shim && (eachProp(cfg.shim, function(value, id) { - isArray(value) && (value = { - deps: value - }), !value.exports && !value.init || value.exportsFn || (value.exportsFn = context.makeShimExports(value)), shim[id] = value - }), config.shim = shim), cfg.packages && each(cfg.packages, function(pkgObj) { - var location, name; - pkgObj = "string" == typeof pkgObj ? { - name: pkgObj - } : pkgObj, name = pkgObj.name, location = pkgObj.location, location && (config.paths[name] = pkgObj.location), config.pkgs[name] = pkgObj.name + "/" + (pkgObj.main || "main").replace(currDirRegExp, "").replace(jsSuffixRegExp, "") - }), eachProp(registry, function(mod, id) { - mod.inited || mod.map.unnormalized || (mod.map = makeModuleMap(id, null, !0)) - }), (cfg.deps || cfg.callback) && context.require(cfg.deps || [], cfg.callback) - }, - makeShimExports: function(value) { - function fn() { - var ret; - return value.init && (ret = value.init.apply(global, arguments)), ret || value.exports && getGlobal(value.exports) - } - return fn - }, - makeRequire: function(relMap, options) { - function localRequire(deps, callback, errback) { - var id, map, requireMod; - return options.enableBuildCallback && callback && isFunction(callback) && (callback.__requireJsBuild = !0), "string" == typeof deps ? isFunction(callback) ? onError(makeError("requireargs", "Invalid require call"), errback) : relMap && hasProp(handlers, deps) ? handlers[deps](registry[relMap.id]) : req.get ? req.get(context, deps, relMap, localRequire) : (map = makeModuleMap(deps, relMap, !1, !0), id = map.id, hasProp(defined, id) ? defined[id] : onError(makeError("notloaded", 'Module name "' + id + '" has not been loaded yet for context: ' + contextName + (relMap ? "" : ". Use require([])")))) : (intakeDefines(), context.nextTick(function() { - intakeDefines(), requireMod = getModule(makeModuleMap(null, relMap)), requireMod.skipMap = options.skipMap, requireMod.init(deps, callback, errback, { - enabled: !0 - }), checkLoaded() - }), localRequire) - } - return options = options || {}, mixin(localRequire, { - isBrowser: isBrowser, - toUrl: function(moduleNamePlusExt) { - var ext, index = moduleNamePlusExt.lastIndexOf("."), - segment = moduleNamePlusExt.split("/")[0], - isRelative = "." === segment || ".." === segment; - return -1 !== index && (!isRelative || index > 1) && (ext = moduleNamePlusExt.substring(index, moduleNamePlusExt.length), moduleNamePlusExt = moduleNamePlusExt.substring(0, index)), context.nameToUrl(normalize(moduleNamePlusExt, relMap && relMap.id, !0), ext, !0) - }, - defined: function(id) { - return hasProp(defined, makeModuleMap(id, relMap, !1, !0).id) - }, - specified: function(id) { - return id = makeModuleMap(id, relMap, !1, !0).id, hasProp(defined, id) || hasProp(registry, id) - } - }), relMap || (localRequire.undef = function(id) { - takeGlobalQueue(); - var map = makeModuleMap(id, relMap, !0), - mod = getOwn(registry, id); - mod.undefed = !0, removeScript(id), delete defined[id], delete urlFetched[map.url], delete undefEvents[id], eachReverse(defQueue, function(args, i) { - args[0] === id && defQueue.splice(i, 1) - }), delete context.defQueueMap[id], mod && (mod.events.defined && (undefEvents[id] = mod.events), cleanRegistry(id)) - }), localRequire - }, - enable: function(depMap) { - getOwn(registry, depMap.id) && getModule(depMap).enable() - }, - completeLoad: function(moduleName) { - var found, args, mod, shim = getOwn(config.shim, moduleName) || {}, - shExports = shim.exports; - for (takeGlobalQueue(); defQueue.length;) { - if (args = defQueue.shift(), null === args[0]) { - if (args[0] = moduleName, found) break; - found = !0 - } else args[0] === moduleName && (found = !0); - callGetModule(args) - } - if (context.defQueueMap = {}, mod = getOwn(registry, moduleName), !found && !hasProp(defined, moduleName) && mod && !mod.inited) { - if (!(!config.enforceDefine || shExports && getGlobal(shExports))) return hasPathFallback(moduleName) ? void 0 : onError(makeError("nodefine", "No define call for " + moduleName, null, [moduleName])); - callGetModule([moduleName, shim.deps || [], shim.exportsFn]) - } - checkLoaded() - }, - nameToUrl: function(moduleName, ext, skipExt) { - var paths, syms, i, parentModule, url, parentPath, bundleId, pkgMain = getOwn(config.pkgs, moduleName); - if (pkgMain && (moduleName = pkgMain), bundleId = getOwn(bundlesMap, moduleName)) return context.nameToUrl(bundleId, ext, skipExt); - if (req.jsExtRegExp.test(moduleName)) url = moduleName + (ext || ""); - else { - for (paths = config.paths, syms = moduleName.split("/"), i = syms.length; i > 0; i -= 1) - if (parentModule = syms.slice(0, i).join("/"), parentPath = getOwn(paths, parentModule)) { - isArray(parentPath) && (parentPath = parentPath[0]), syms.splice(0, i, parentPath); - break - } url = syms.join("/"), url += ext || (/^data\:|^blob\:|\?/.test(url) || skipExt ? "" : ".js"), url = ("/" === url.charAt(0) || url.match(/^[\w\+\.\-]+:/) ? "" : config.baseUrl) + url - } - return config.urlArgs && !/^blob\:/.test(url) ? url + config.urlArgs(moduleName, url) : url - }, - load: function(id, url) { - req.load(context, id, url) - }, - execCb: function(name, callback, args, exports) { - return callback.apply(exports, args) - }, - onScriptLoad: function(evt) { - if ("load" === evt.type || readyRegExp.test((evt.currentTarget || evt.srcElement).readyState)) { - interactiveScript = null; - var data = getScriptData(evt); - context.completeLoad(data.id) - } - }, - onScriptError: function(evt) { - var data = getScriptData(evt); - if (!hasPathFallback(data.id)) { - var parents = []; - return eachProp(registry, function(value, key) { - 0 !== key.indexOf("_@r") && each(value.depMaps, function(depMap) { - if (depMap.id === data.id) return parents.push(key), !0 - }) - }), onError(makeError("scripterror", 'Script error for "' + data.id + (parents.length ? '", needed by: ' + parents.join(", ") : '"'), evt, [data.id])) - } - } - }, context.require = context.makeRequire(), context - } - - function getInteractiveScript() { - return interactiveScript && "interactive" === interactiveScript.readyState ? interactiveScript : (eachReverse(scripts(), function(script) { - if ("interactive" === script.readyState) return interactiveScript = script - }), interactiveScript) - } - var req, s, head, baseElement, dataMain, src, interactiveScript, currentlyAddingScript, mainScript, subPath, version = "2.3.5", - commentRegExp = /\/\*[\s\S]*?\*\/|([^:"'=]|^)\/\/.*$/gm, - cjsRequireRegExp = /[^.]\s*require\s*\(\s*["']([^'"\s]+)["']\s*\)/g, - jsSuffixRegExp = /\.js$/, - currDirRegExp = /^\.\//, - op = Object.prototype, - ostring = op.toString, - hasOwn = op.hasOwnProperty, - isBrowser = !("undefined" == typeof window || "undefined" == typeof navigator || !window.document), - isWebWorker = !isBrowser && "undefined" != typeof importScripts, - readyRegExp = isBrowser && "PLAYSTATION 3" === navigator.platform ? /^complete$/ : /^(complete|loaded)$/, - defContextName = "_", - isOpera = "undefined" != typeof opera && "[object Opera]" === opera.toString(), - contexts = {}, - cfg = {}, - globalDefQueue = [], - useInteractive = !1; - if (void 0 === define) { - if (void 0 !== requirejs) { - if (isFunction(requirejs)) return; - cfg = requirejs, requirejs = void 0 - } - void 0 === require || isFunction(require) || (cfg = require, require = void 0), req = requirejs = function(deps, callback, errback, optional) { - var context, config, contextName = defContextName; - return isArray(deps) || "string" == typeof deps || (config = deps, isArray(callback) ? (deps = callback, callback = errback, errback = optional) : deps = []), config && config.context && (contextName = config.context), context = getOwn(contexts, contextName), context || (context = contexts[contextName] = req.s.newContext(contextName)), config && context.configure(config), context.require(deps, callback, errback) - }, req.config = function(config) { - return req(config) - }, req.nextTick = void 0 !== setTimeout ? function(fn) { - setTimeout(fn, 4) - } : function(fn) { - fn() - }, require || (require = req), req.version = version, req.jsExtRegExp = /^\/|:|\?|\.js$/, req.isBrowser = isBrowser, s = req.s = { - contexts: contexts, - newContext: newContext - }, req({}), each(["toUrl", "undef", "defined", "specified"], function(prop) { - req[prop] = function() { - var ctx = contexts[defContextName]; - return ctx.require[prop].apply(ctx, arguments) - } - }), isBrowser && (head = s.head = document.getElementsByTagName("head")[0], (baseElement = document.getElementsByTagName("base")[0]) && (head = s.head = baseElement.parentNode)), req.onError = defaultOnError, req.createNode = function(config, moduleName, url) { - var node = config.xhtml ? document.createElementNS("http://www.w3.org/1999/xhtml", "html:script") : document.createElement("script"); - return node.type = config.scriptType || "text/javascript", node.charset = "utf-8", node.async = !0, node - }, req.load = function(context, moduleName, url) { - var node, config = context && context.config || {}; - if (isBrowser) return node = req.createNode(config, moduleName, url), node.setAttribute("data-requirecontext", context.contextName), node.setAttribute("data-requiremodule", moduleName), !node.attachEvent || node.attachEvent.toString && node.attachEvent.toString().indexOf("[native code") < 0 || isOpera ? (node.addEventListener("load", context.onScriptLoad, !1), node.addEventListener("error", context.onScriptError, !1)) : (useInteractive = !0, node.attachEvent("onreadystatechange", context.onScriptLoad)), node.src = url, config.onNodeCreated && config.onNodeCreated(node, config, moduleName, url), currentlyAddingScript = node, baseElement ? head.insertBefore(node, baseElement) : head.appendChild(node), currentlyAddingScript = null, node; - if (isWebWorker) try { - setTimeout(function() {}, 0), importScripts(url), context.completeLoad(moduleName) - } catch (e) { - context.onError(makeError("importscripts", "importScripts failed for " + moduleName + " at " + url, e, [moduleName])) - } - }, isBrowser && !cfg.skipDataMain && eachReverse(scripts(), function(script) { - if (head || (head = script.parentNode), dataMain = script.getAttribute("data-main")) return mainScript = dataMain, cfg.baseUrl || -1 !== mainScript.indexOf("!") || (src = mainScript.split("/"), mainScript = src.pop(), subPath = src.length ? src.join("/") + "/" : "./", cfg.baseUrl = subPath), mainScript = mainScript.replace(jsSuffixRegExp, ""), req.jsExtRegExp.test(mainScript) && (mainScript = dataMain), cfg.deps = cfg.deps ? cfg.deps.concat(mainScript) : [mainScript], !0 - }), define = function(name, deps, callback) { - var node, context; - "string" != typeof name && (callback = deps, deps = name, name = null), isArray(deps) || (callback = deps, deps = null), !deps && isFunction(callback) && (deps = [], callback.length && (callback.toString().replace(commentRegExp, commentReplace).replace(cjsRequireRegExp, function(match, dep) { - deps.push(dep) - }), deps = (1 === callback.length ? ["require"] : ["require", "exports", "module"]).concat(deps))), useInteractive && (node = currentlyAddingScript || getInteractiveScript()) && (name || (name = node.getAttribute("data-requiremodule")), context = contexts[node.getAttribute("data-requirecontext")]), context ? (context.defQueue.push([name, deps, callback]), context.defQueueMap[name] = !0) : globalDefQueue.push([name, deps, callback]) - }, define.amd = { - jQuery: !0 - }, req.exec = function(text) { - return eval(text) - }, req(cfg) - } -}(this, "undefined" == typeof setTimeout ? void 0 : setTimeout); \ No newline at end of file diff --git a/src/scripts/apploader.js b/src/scripts/apploader.js index 9067ae6070..2328f88968 100644 --- a/src/scripts/apploader.js +++ b/src/scripts/apploader.js @@ -20,7 +20,7 @@ } injectScriptElement( - self.Promise ? "./bower_components/alameda/alameda.js" : "./bower_components/requirejs/require.js", + self.Promise ? "./bower_components/alameda.js" : "./bower_components/require.js", function() { // onload of require library injectScriptElement("./scripts/site.js"); diff --git a/webpack.common.js b/webpack.common.js index 05b2b0cb46..6e82da181e 100644 --- a/webpack.common.js +++ b/webpack.common.js @@ -1,6 +1,10 @@ const path = require("path"); +const { CleanWebpackPlugin} = require("clean-webpack-plugin"); const CopyPlugin = require("copy-webpack-plugin"); +// assets.js +const Assets = require('./assets'); + module.exports = { context: path.resolve(__dirname, "src"), entry: "./bundle.js", @@ -10,9 +14,18 @@ module.exports = { ] }, plugins: [ + new CleanWebpackPlugin(), new CopyPlugin([{ from: "**/*", to: "." - }]) + }]), + new CopyPlugin( + Assets.map(asset => { + return { + from: path.resolve(__dirname, `./node_modules/${asset}`), + to: path.resolve(__dirname, './dist/bower_components') + }; + }) + ) ] }; From 1e5568943c8626a1479c821ef1a6d0b183ce3b58 Mon Sep 17 00:00:00 2001 From: grafixeyehero Date: Mon, 28 Oct 2019 01:31:45 +0300 Subject: [PATCH 091/162] remove ensureConnectUser --- .../apiclient/connectionmanager.js | 24 +------------------ 1 file changed, 1 insertion(+), 23 deletions(-) diff --git a/src/bower_components/apiclient/connectionmanager.js b/src/bower_components/apiclient/connectionmanager.js index 092f53e38b..4c9bb66a51 100644 --- a/src/bower_components/apiclient/connectionmanager.js +++ b/src/bower_components/apiclient/connectionmanager.js @@ -234,12 +234,6 @@ define(["events", "apiclient", "appStorage"], function (events, apiClientFactory }) } - function ensureConnectUser(credentials) { - if (connectUser && connectUser.Id === credentials.ConnectUserId) { - return Promise.resolve(); - } - } - function validateAuthentication(server, serverUrl) { return ajax({ type: "GET", @@ -415,13 +409,7 @@ define(["events", "apiclient", "appStorage"], function (events, apiClientFactory var credentials = credentialProvider.credentials(); options = options || {}; - if (credentials.ConnectAccessToken && false !== options.enableAutoLogin) { - ensureConnectUser(credentials).then(function () { - afterConnectValidated(server, credentials, systemInfo, connectionMode, serverUrl, true, options, resolve); - }); - } else { - afterConnectValidated(server, credentials, systemInfo, connectionMode, serverUrl, true, options, resolve); - } + afterConnectValidated(server, credentials, systemInfo, connectionMode, serverUrl, true, options, resolve); } function afterConnectValidated(server, credentials, systemInfo, connectionMode, serverUrl, verifyLocalAuthentication, options, resolve) { @@ -648,8 +636,6 @@ define(["events", "apiclient", "appStorage"], function (events, apiClientFactory if (!credentials.ConnectUserId || !credentials.ConnectAccessToken || apiClient && apiClient.getCurrentUserId()) { onEnsureConnectUserDone(); - } else { - ensureConnectUser(credentials).then(onEnsureConnectUserDone, onEnsureConnectUserDone); } }); }; @@ -823,14 +809,6 @@ define(["events", "apiclient", "appStorage"], function (events, apiClientFactory if (!pinInfo) { throw new Error("pinInfo cannot be null"); } - - return exchangePin(pinInfo).then(function (result) { - var credentials = credentialProvider.credentials(); - credentials.ConnectAccessToken = result.AccessToken; - credentials.ConnectUserId = result.UserId; - credentialProvider.credentials(credentials); - return ensureConnectUser(credentials); - }); }; }; From 1c84e18c8afaf50dc6dcad56bc5f268bdb008923 Mon Sep 17 00:00:00 2001 From: grafixeyehero Date: Mon, 28 Oct 2019 01:55:05 +0300 Subject: [PATCH 092/162] remove reaming getconnect related --- .../apiclient/connectionmanager.js | 60 ------------------- 1 file changed, 60 deletions(-) diff --git a/src/bower_components/apiclient/connectionmanager.js b/src/bower_components/apiclient/connectionmanager.js index 4c9bb66a51..763fd784c1 100644 --- a/src/bower_components/apiclient/connectionmanager.js +++ b/src/bower_components/apiclient/connectionmanager.js @@ -457,29 +457,6 @@ define(["events", "apiclient", "appStorage"], function (events, apiClientFactory } } - function addAppInfoToConnectRequest(request) { - request.headers = request.headers || {}; - request.headers["X-Application"] = appName + "/" + appVersion; - } - - function exchangePin(pinInfo) { - if (!pinInfo) { - throw new Error("pinInfo cannot be null"); - } - - var request = { - type: "POST", - url: getConnectUrl("pin/authenticate"), - data: { - deviceId: pinInfo.DeviceId, - pin: pinInfo.Pin - }, - dataType: "json" - }; - addAppInfoToConnectRequest(request); - return ajax(request); - } - console.log("Begin ConnectionManager constructor"); var self = this; this._apiClients = []; @@ -773,43 +750,6 @@ define(["events", "apiclient", "appStorage"], function (events, apiClientFactory }; return self.connectToServer(server, options).catch(onFail); }; - - self.createPin = function () { - var request = { - type: "POST", - url: getConnectUrl("pin"), - data: { - deviceId: deviceId - }, - dataType: "json" - }; - addAppInfoToConnectRequest(request); - return ajax(request); - }; - - self.getPinStatus = function (pinInfo) { - if (!pinInfo) { - throw new Error("pinInfo cannot be null"); - } - - var queryString = { - deviceId: pinInfo.DeviceId, - pin: pinInfo.Pin - }; - var request = { - type: "GET", - url: getConnectUrl("pin") + "?" + paramsToString(queryString), - dataType: "json" - }; - addAppInfoToConnectRequest(request); - return ajax(request); - }; - - self.exchangePin = function (pinInfo) { - if (!pinInfo) { - throw new Error("pinInfo cannot be null"); - } - }; }; ConnectionManager.prototype.connect = function (options) { From 99c8134b1a2c13d63f85269228b267349b6f259e Mon Sep 17 00:00:00 2001 From: ThePBone Date: Sun, 27 Oct 2019 17:23:27 +0000 Subject: [PATCH 093/162] Translated using Weblate (German) Translation: Jellyfin/Jellyfin Web Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-web/de/ --- src/strings/de.json | 28 +++++++++++++++++++++++----- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/src/strings/de.json b/src/strings/de.json index eb158e5eaa..83796fb303 100644 --- a/src/strings/de.json +++ b/src/strings/de.json @@ -22,11 +22,11 @@ "AllLanguages": "Alle Sprachen", "AllLibraries": "Alle Bibliotheken", "AllowDeletionFromAll": "Erlaube Medienlöschung in allen Bibliotheken", - "AllowHWTranscodingHelp": "Wenn aktiviert, übernimmt der Tuner die Transkodierung in Echtzeit. Das hilft eventuell die Transkodierung auf dem Jellyfin Servers zu reduzieren. (Spart Hardwareressourcen)", + "AllowHWTranscodingHelp": "Erlaube dem Tuner die Transkodierung in Echtzeit. Das hilft eventuell die Transkodierung auf dem Jellyfin Servers zu reduzieren. (Spart Hardwareressourcen)", "AllowMediaConversion": "Erlaube Medienkonvertierung", "AllowMediaConversionHelp": "Erlaube oder unterbinde Zugriff auf die Medienkonvertierung.", "AllowOnTheFlySubtitleExtraction": "Erlaube Untertitelextraktion \"on-the-fly\"", - "AllowOnTheFlySubtitleExtractionHelp": "Eingebettete Untertitel können aus Videos extrahiert und in Textformat an Jellyfin gesendet werden um Transkodieren zu vermeiden. Auf manchen Systemen kann dieser Vorgang eine lange Zeit in Anspruch nehmen und die Videowiedergabe zum Halten bringen während der Extraktion. Deaktiviere diese Option um eingebettete Untertitel während des Videotranskodierens einbrennen zu lassen, wenn sie nicht nativ vom Client unterstützt werden.", + "AllowOnTheFlySubtitleExtractionHelp": "Eingebettete Untertitel können aus Videos extrahiert und in Textformat an Clients gesendet werden um Transkodieren zu vermeiden. Auf manchen Systemen kann dieser Vorgang eine lange Zeit in Anspruch nehmen und die Videowiedergabe zum Halten bringen während der Extraktion. Deaktiviere diese Option um eingebettete Untertitel während der Videotranskodierung einbrennen zu lassen, wenn sie nicht nativ vom Client unterstützt werden.", "AllowRemoteAccess": "Erlaube externe Verbindungen zu diesem Jellyfin Server.", "AllowRemoteAccessHelp": "Wenn deaktiviert werden alle externen Verbindungen blockiert.", "AllowSeasonalThemes": "Erlaube automatische Jahreszeitenmotive", @@ -55,7 +55,7 @@ "BirthLocation": "Geburtsort", "BirthPlaceValue": "Geburtsort: {0}", "BobAndWeaveWithHelp": "Bob & Weave (höhere Qualität, aber langsamer)", - "BookLibraryHelp": "Hörbücher und E-Books werden unterstützt. Schaue in den {0}Jellyfin Book Naming Guide {1}.", + "BookLibraryHelp": "Hörbücher und E-Books werden unterstützt. Schaue in den {0}Book Naming Guide {1}.", "Books": "Bücher", "BoxRear": "Box (Rückseite)", "Browse": "Blättern", @@ -1401,7 +1401,7 @@ "Thumb": "Miniaturansicht", "TitleSupport": "Hilfe", "Whitelist": "Erlaubt", - "AuthProviderHelp": "Auswählen eines Authentifizierungsanbieter, der zur Authentifizierung des Passworts dieses Benutzes verwendet werden soll", + "AuthProviderHelp": "Auswählen eines Authentifizierungsanbieter, der zur Authentifizierung des Passworts dieses Benutzes verwendet werden soll.", "Features": "Features", "HeaderFavoriteBooks": "Lieblingsbücher", "HeaderFavoriteMovies": "Lieblingsfilme", @@ -1437,5 +1437,23 @@ "HeaderTypeImageFetchers": "{0} Bildquellen", "LabelBitrate": "Bitrate:", "LabelAudioBitrate": "Tonbitrate:", - "ButtonAddImage": "Bild hinzufügen" + "ButtonAddImage": "Bild hinzufügen", + "LabelSize": "Größe:", + "LabelTranscodes": "Transkoder:", + "LabelTranscodingProgress": "Transcodierungsfortschritt:", + "LabelAudioBitDepth": "Audio-Bittiefe:", + "LabelPleaseRestart": "Die Änderungen werden nach dem manuellen Neuladen des Webclients wirksam.", + "LabelVideoBitrate": "Video-Bitrate:", + "LabelTranscodingFramerate": "Transcodierrate:", + "LabelAudioSampleRate": "Audio-Abtastrate:", + "LabelBaseUrl": "Basis URL:", + "LabelBaseUrlHelp": "Du kannst hier ein benutzerdefiniertes Unterverzeichnis hinzufügen, um über eine eindeutige URL auf den Server zuzugreifen.", + "LabelFolder": "Ordner:", + "LabelPasswordResetProvider": "Anbieter zum Zurücksetzen des Passwortes:", + "LabelPlayMethod": "Spielmethode:", + "DashboardOperatingSystem": "Betriebssystem: {O}", + "DashboardArchitecture": "Architektur: {0}", + "LabelVideoCodec": "Videocodec:", + "LaunchWebAppOnStartup": "Das Webinterface öffnen, wenn der Server startet", + "LaunchWebAppOnStartupHelp": "Öffne den Webclient in Standard-Webbrowser, wenn der Server zum ersten Mal gestartet wird. Dies tritt bei Verwendung der Neustart-Serverfunktion nicht auf." } From 54de766bb78af5c235e0e0e58a32ba4e244599fe Mon Sep 17 00:00:00 2001 From: ZsiGiT Date: Sun, 27 Oct 2019 19:36:13 +0000 Subject: [PATCH 094/162] Translated using Weblate (Hungarian) Translation: Jellyfin/Jellyfin Web Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-web/hu/ --- src/strings/hu.json | 61 ++++++++++++++++++++++++--------------------- 1 file changed, 33 insertions(+), 28 deletions(-) diff --git a/src/strings/hu.json b/src/strings/hu.json index f2b6e1220f..1b5a307718 100644 --- a/src/strings/hu.json +++ b/src/strings/hu.json @@ -34,7 +34,7 @@ "ButtonEdit": "Szerkesztés", "ButtonEditImages": "Képek szerkesztése", "ButtonFilter": "Szűrő", - "ButtonForgotPassword": "Elfelejtett jelszó", + "ButtonForgotPassword": "Elfelejtett Jelszó", "ButtonGotIt": "Értettem", "ButtonHelp": "Segítség", "ButtonHome": "Kezdőlap", @@ -117,7 +117,7 @@ "FolderTypeMovies": "Filmek", "FolderTypeMusic": "Zenék", "FolderTypeMusicVideos": "Zenei Videók", - "FolderTypeTvShows": "Műsorok", + "FolderTypeTvShows": "TV Műsorok", "FolderTypeUnset": "Vegyes Tartalom", "Folders": "Könyvtárak", "Friday": "Péntek", @@ -267,7 +267,7 @@ "LabelGroupMoviesIntoCollections": "Filmek csoportosítása gyűjteményekbe", "LabelH264EncodingPreset": "H264 enkóder beállítások:", "LabelHardwareAccelerationType": "Hardveres gyorsítás:", - "LabelHardwareAccelerationTypeHelp": "Csak támogatott rendszereken érhető el.", + "LabelHardwareAccelerationTypeHelp": "Ez egy kísérleti szolgáltatás, amely csak a támogatott rendszereken érhető el.", "LabelHomeScreenSectionValue": "Kezdőképernyő blokk {0}:", "LabelImageType": "Kép típusa:", "LabelKodiMetadataDateFormat": "Megjelenési dátum formátuma:", @@ -607,7 +607,7 @@ "AlwaysPlaySubtitlesHelp": "A nyelvi beállításoknak megfelelő feliratok az audió nyelvétől függetlenül kerülnek betöltésre.", "Artists": "Előadók", "Blacklist": "Feketelista", - "BookLibraryHelp": "Az audió- és szövegkönyvek támogatottak. Nézd meg a {0} Jellyfin Könyvelnevezési útmutatót {1}.", + "BookLibraryHelp": "Az audió- és szövegkönyvek támogatottak. Nézd meg a {0} könyvelnevezési útmutatót {1}.", "BrowsePluginCatalogMessage": "Böngéssz a Bővítmény katalógusunkban a rendelkezésre álló bővítmények megtekintéséhez.", "AddItemToCollectionHelp": "Adj elemeket a gyűjteményekhez, ehhez keresed meg őket, majd kattints jobb egérgombbal, vagy kattints a menüre és add hozzá a gyűjteményhez.", "AllowedRemoteAddressesHelp": "Vesszővel válaszd el az IP-címek vagy IP / netmask címek listáját annak a hálózatnak amelyből távolról csatlakozhatnak. Ha üresen marad, az összes távoli cím megengedett.", @@ -689,8 +689,8 @@ "ErrorMessageStartHourGreaterThanEnd": "A befejezési időnek nagyobbnak kell lennie mint a kezdési idő.", "ErrorSavingTvProvider": "Hiba történt a TV szolgáltató mentésekor. Kérlek győződj meg róla, hogy elérhető és próbálkozz meg újra.", "EveryNDays": "Minden {0} nap", - "ExtraLarge": "Extra nagy", - "ExtractChapterImagesHelp": "A fejezetképek kivonása lehetővé teszi, hogy a Jellyfin alkalmazások grafikus jelenetválasztási menüket jelenítsenek meg. A folyamat lehet lassú, CPU intenzív és több gigabájt területet igényelhet. A kivonás akkor történik, amikor új videók kerülnek a Médiatárba, valamint egy éjszakai ütemezett feladatként. Az ütemezés konfigurálható az Ütemezett Feladatok menüpontban. Nem ajánlott ezt a feladatot a csúcshasználati órákban futtatni.", + "ExtraLarge": "Extra NAGY", + "ExtractChapterImagesHelp": "A fejezetképek kivonása lehetővé teszi, hogy az alkalmazások grafikus jelenetválasztási menüket jelenítsenek meg. A folyamat lehet lassú, erőforrás igényes, és több gigabájt területet igényelhet. A kivonás akkor történik, amikor új videók kerülnek a Médiatárba, valamint egy éjszakai ütemezett feladatként. Az ütemezés konfigurálható az Ütemezett Feladatok menüpontban. Nem ajánlott ezt a feladatot a csúcshasználati órákban futtatni.", "Extras": "Extrák", "FFmpegSavePathNotFound": "Nem található az FFmpeg a megadott útvonalon. FFprobe is szükséges, és ugyanabban a mappában kell lennie. Ezek az összetevők általában ugyanabban a csomagban találhatók. Kérlek ellenőrizd a megadott útvonalat és próbáld meg újra.", "File": "Fájl", @@ -845,7 +845,7 @@ "LabelBindToLocalNetworkAddressHelp": "Opcionális. A helyi IP cím felülbírálása a http szerverhez való csatlakozáshoz. Ha üres marad, a szerver minden elérhető címhez kötődik. Az érték megváltoztatásához a Jellyfin Szerver újraindítása szükséges.", "LabelBirthDate": "Születési dátum:", "LabelBlastMessageInterval": "Élő üzenetintervallum (másodperc)", - "LabelBlastMessageIntervalHelp": "Meghatározza az időtartamot másodpercben a szerver üzenetei között.", + "LabelBlastMessageIntervalHelp": "Meghatározza másodpercben az üzenetek közötti időtartamot.", "LabelBlockContentWithTags": "Blokkolja a címkével ellátott elemeket:", "LabelCache": "Gyorsítótár:", "LabelCachePathHelp": "Adj meg egy egyéni helyet a szerver gyorsítótár fájljainak, például a képeknek. Hagyd üresen az alapértelmezett beállításához.", @@ -879,44 +879,44 @@ "LabelEnableDlnaDebugLogging": "DLNA hibakeresési naplózás engedélyezése", "LabelEnableDlnaDebugLoggingHelp": "Ez nagy naplófájlokat hoz létre és csak hibaelhárítás céljából használható.", "LabelEnableDlnaPlayTo": "DLNA Play To engedélyezése", - "LabelEnableDlnaPlayToHelp": "A Jellyfin képes érzékelni a hálózaton belüli eszközöket, és képes a távoli vezérlésükre.", - "LabelEnableDlnaServer": "Dlna szerver engedélyezése", - "LabelEnableDlnaServerHelp": "Lehetővé teszi a hálózaton található UPnP eszközöknek, hogy a Jellyfin tartalmát böngésszék és lejátszák.", + "LabelEnableDlnaPlayToHelp": "Felismerheti a hálózaton belüli eszközöket, és lehetővé teszi azok távvezérlését.", + "LabelEnableDlnaServer": "DLNA szerver engedélyezése", + "LabelEnableDlnaServerHelp": "Lehetővé teszi a hálózaton található UPnP eszközöknek, hogy böngésszenek és lejátszanak tartalmat.", "LabelEnableSingleImageInDidlLimit": "Korlátozás egyetlen beágyazott képre", "LabelEnableSingleImageInDidlLimitHelp": "Néhány eszköz nem jeleníti meg megfelelően, ha több kép van beágyazva a Didl-be.", "LabelEndDate": "Befejezés dátuma:", "LabelExtractChaptersDuringLibraryScan": "Fejezet képek készítése a könyvtár beolvasása során", - "LabelExtractChaptersDuringLibraryScanHelp": "Ha engedélyezve van, a fejezetképek elkészítése a könyvtár beolvasása során történik meg. Ha le van tiltva, akkor az elkészítés az Ütemezett feladatokban meghatározott időben készül el, ami lehetővé teszi a könyvtárbeolvasás gyorsítását.", + "LabelExtractChaptersDuringLibraryScanHelp": "A fejezetképek elkészítése a könyvtár beolvasása során történik meg. Ellenkező esetben az elkészítés az Ütemezett feladatokban meghatározott időben készül el, ami lehetővé teszi a könyvtárbeolvasás gyorsítását.", "LabelFailed": "Sikertelen", "LabelFileOrUrl": "Fájl vagy URL:", "LabelFont": "Betűtípus:", "LabelFormat": "Formátum:", "LabelFriendlyName": "Könnyen megjegyezhető név:", - "LabelServerNameHelp": "Ez a név kerül a Szerver azonosítására. Ha üresen marad, a számítógép neve kerül felhasználásra.", + "LabelServerNameHelp": "Ez a név kerül a Szerver azonosítására és alapértelmezetten a számítógép neve kerül felhasználásra.", "LabelGroupMoviesIntoCollectionsHelp": "A filmlisták megjelenítésekor a gyűjteményhez tartozó filmek egy csoportos elemként jelennek meg.", "LabelH264Crf": "H264 enkóder CRF:", "LabelHomeNetworkQuality": "Otthoni hálózat minősége:", - "LabelHttpsPort": "Helyi https port száma:", + "LabelHttpsPort": "Helyi HTTPS port száma:", "LabelImageFetchersHelp": "Engedélyezd és rangsorold az előnyben részesített képletöltőket prioritásuk sorrendjében.", "LabelImportOnlyFavoriteChannels": "Csak a kedvencként megjelölt csatornákra korlátozza", "LabelInNetworkSignInWithEasyPassword": "Engedélyezze a hálózaton belüli bejelentkezést az egyszerű PIN kóddal", - "LabelInNetworkSignInWithEasyPasswordHelp": "Ha engedélyezve van, akkor az egyszerű PIN kódod segítségével beléphetsz a Jellyfin alkalmazásokba az otthoni hálózaton belül. A szokásos jelszót csak akkor kell használni, ha az otthoni hálózaton kívül vagy. Ha a PIN kód üres, akkor nem lesz szükség jelszóra az otthoni hálózaton belül.", + "LabelInNetworkSignInWithEasyPasswordHelp": "Az egyszerű PIN kódod segítségével beléphetsz az alkalmazásokból az otthoni hálózaton belül. A szokásos jelszót csak akkor kell használni, ha az otthoni hálózaton kívül vagy. Ha a PIN kód üres, akkor nem lesz szükség jelszóra az otthoni hálózaton belül.", "LabelInternetQuality": "Internet minősége:", "LabelKidsCategories": "Gyermek kategóriák:", - "LabelKodiMetadataDateFormatHelp": "Az nfo-n belüli összes dátum ezzel a formátummal lesz írva és olvasva.", - "LabelKodiMetadataEnableExtraThumbs": "Másolja az extrafanartot extrathumbs-ba", + "LabelKodiMetadataDateFormatHelp": "Az NFO-n belüli összes dátum ezzel a formátummal lesz kezelve.", + "LabelKodiMetadataEnableExtraThumbs": "Másolja az extrafanartot extrathumbs mezőbe", "LabelKodiMetadataEnableExtraThumbsHelp": "A képek letöltésekor mind az extrafanart, mind az extrathumbs-ba menthetőek a maximális Kodi skin kompatibilitáshoz.", "LabelKodiMetadataEnablePathSubstitution": "Útvonal helyettesítés engedélyezése", "LabelKodiMetadataEnablePathSubstitutionHelp": "Lehetővé teszi a képútvonalak helyettesítését a szerver útvonal helyettesítési beállításaival.", "LabelKodiMetadataSaveImagePaths": "A képek útvonalának mentése az nfo fájlokban", "LabelKodiMetadataSaveImagePathsHelp": "Ez akkor ajánlott, ha olyan képfájlnevek vannak amelyek nem felelnek meg a Kodi irányelveinek.", "LabelLanNetworks": "LAN hálózatok:", - "LabelLocalHttpServerPortNumber": "Helyi http port száma:", + "LabelLocalHttpServerPortNumber": "Helyi HTTP port száma:", "LabelLockItemToPreventChanges": "Az elem zárolása a jövőbeni változások elkerülése érdekében", "LabelLoginDisclaimer": "Bejelentkezési nyilatkozat:", - "LabelLoginDisclaimerHelp": "Ez a bejelentkezési oldal alján jelenik meg.", + "LabelLoginDisclaimerHelp": "Ez az üzenet a bejelentkezési oldal alján jelenik meg.", "LabelManufacturer": "Gyártó", - "LabelManufacturerUrl": "Gyártó url címe", + "LabelManufacturerUrl": "Gyártó URL címe", "LabelMatchType": "Egyezés típusa:", "LabelMaxBackdropsPerItem": "A hátterek maximális száma elemenként:", "LabelMaxChromecastBitrate": "Chromecast streaming minősége:", @@ -931,7 +931,7 @@ "LabelModelUrl": "Modell URL", "LabelMovieCategories": "Film kategóriák:", "LabelMoviePrefix": "Film előtag:", - "LabelMoviePrefixHelp": "Ha a filmcímekhez előtagot használsz írd be ide, hogy Jellyfin megfelelően kezelje.", + "LabelMoviePrefixHelp": "Ha a filmcímekhez előtagot használsz, írd be ide, hogy a szerver megfelelően kezelje.", "LabelMovieRecordingPath": "Filmfelvételi útvonal (opcionális):", "LabelMusicStreamingTranscodingBitrate": "Zene átkódolási bitráta:", "LabelNewName": "Új név:", @@ -970,7 +970,7 @@ "OptionDateAddedFileTime": "Használja a fájl létrehozásának dátumát", "LabelMinBackdropDownloadWidth": "A letöltendő háttérkép minimális szélessége:", "LabelMinResumeDuration": "A folytatás minimum időtartama:", - "LabelMinResumeDurationHelp": "A rövidebb videó hosszúság másodpercben, melynél a lejátszás helye mentésre kerül, így később folytatható lesz", + "LabelMinResumeDurationHelp": "A rövidebb videó hosszúság másodpercben, melynél a lejátszás helye mentésre kerül, így később folytatható lesz.", "LabelMinResumePercentage": "Minimum folytatás százalékban:", "LabelMinScreenshotDownloadWidth": "Minimális képernyőkép letöltési szélesség:", "LabelPreferredSubtitleLanguage": "Alapértelmezett feliratnyelv:", @@ -1280,9 +1280,9 @@ "XmlTvSportsCategoriesHelp": "Az ilyen kategóriákkal rendelkező programok sportprogramként jelennek meg. Válaszd el őket a '|' elválasztóval.", "Yes": "Igen", "LabelMaxResumePercentage": "Maximum folytatás százalékban:", - "LabelMaxResumePercentageHelp": "A címeket teljesen lejátszottnak tekintjük, ha ezen idő után fejezed be", + "LabelMaxResumePercentageHelp": "A címeket teljesen lejátszottnak tekintjük, ha ezen idő után fejezed be.", "LabelMaxStreamingBitrateHelp": "Adj meg egy maximum bitrátát a streameléshez.", - "LabelMinResumePercentageHelp": "A címeket nem lejátszottnak tekintjük, ha ez alatt az idő alatt fejezed be", + "LabelMinResumePercentageHelp": "A címeket nem lejátszottnak tekintjük, ha ez alatt az idő alatt fejezed be.", "LabelMusicStreamingTranscodingBitrateHelp": "Határozz meg egy streamelési max bitrátát a zenékhez", "DashboardVersionNumber": "Verzió: {0}", "DashboardServerName": "Szerver: {0}", @@ -1294,7 +1294,7 @@ "LabelUserAgent": "Felhasználó ügynök:", "LabelUserLoginAttemptsBeforeLockout": "Sikertelen bejelentkezési kísérletek a felhasználó zárolása előtt:", "DashboardOperatingSystem": "Operációs rendszer: {0}", - "DashboardArchitecture": "Rendszer típusa: {0}", + "DashboardArchitecture": "Platform: {0}", "LaunchWebAppOnStartup": "Indítsa el a Jellyfin webes alkalmazást a böngészőben, amikor a Jellyfin Szerver elindul", "MessageNoCollectionsAvailable": "A gyűjtemények lehetővé teszik Filmek, Sorozatok és Albumok egyéni csoportosítását. A gyűjtemények létrehozásához kattints a + gombra.", "MessageNoServersAvailable": "Az automatikus kiszolgálókeresés nem talált szervert.", @@ -1343,7 +1343,7 @@ "LabelDateAddedBehavior": "Új tartalom esetén alkalmazandó hozzáadás dátuma mód:", "LabelDateAddedBehaviorHelp": "Ha egy metaadat érték jelen van, akkor mindig az lesz előnyben részesítve ezen opciók előtt.", "LabelDownMixAudioScale": "Hangkiemelés átkódolás esetén:", - "LabelDownMixAudioScaleHelp": "Hangkiemelés átkódoláskor. Állítsd 1-re az eredeti hangerő érték megőrzéséhez.", + "LabelDownMixAudioScaleHelp": "Hangkiemelés átkódoláskor. Az egy érték az eredeti hangerő értékének felel meg.", "LabelEmbedAlbumArtDidl": "Albumborító beágyazása a Didl-be", "LabelEmbedAlbumArtDidlHelp": "Néhány eszköz ezt a megoldást részesíti előnyben az albumborítók esetében. Mások esetlegesen lejátszási hibát jeleznek, ha ez az opció engedélyezve van.", "LabelEnableBlastAliveMessages": "Blast alive üzenetek", @@ -1354,8 +1354,8 @@ "LabelIconMaxWidthHelp": "Ikon maximális szélesség, mely az upnp:icon keresztül kiajánlásra kerül.", "LabelIdentificationFieldHelp": "Kis-és nagybetű különbséget figyelmen kívül hagyó szöveg vagy reguláris kifejezés.", "LabelKeepUpTo": "Őrizd meg:", - "LabelKodiMetadataUser": "Mentsd el a következő felhasználó megtekintési adatát az nfo-ba:", - "LabelKodiMetadataUserHelp": "Ha ezt engedélyezed, akkor a kiválasztott felhasználó megtekintési adata elmentésre kerül az NFO fájlokba, melyet azután más alkalmazások használhatnak.", + "LabelKodiMetadataUser": "Mentsd el a következő felhasználó megtekintési adatát az NFO-ba:", + "LabelKodiMetadataUserHelp": "A kiválasztott felhasználó megtekintési adata elmentésre kerül az NFO fájlokba, melyet azután más alkalmazások használhatnak.", "LabelLocalHttpServerPortNumberHelp": "A TCP port száma, melyen a Jellyfin HTTP szerver figyel.", "UserAgentHelp": "Adj meg egy egyedi http user-agent fejlécet, amennyiben szükséges.", "XmlDocumentAttributeListHelp": "Ezek a tulajdonságok minden xml válaszüzenet gyökér elemére alkalmazásra kerülnek.", @@ -1371,5 +1371,10 @@ "HeaderFavoriteBooks": "Kedvenc Könyvek", "CopyStreamURLSuccess": "URL másolása sikeres.", "CopyStreamURL": "Stream URL másolása", - "PlaybackData": "Lejátszási adatok" + "PlaybackData": "Lejátszási adatok", + "ButtonAddImage": "Kép hozzáadása", + "LabelPasswordResetProvider": "Jelszó Visszaállítási Szolgáltató:", + "FetchingData": "További adatok lekérése", + "LabelBaseUrl": "Alap URL:", + "Depressed": "Nyomott" } From d916dd7268f6e9b755c7d1b13316cd7ef94f09ec Mon Sep 17 00:00:00 2001 From: tluciomiranda Date: Sat, 26 Oct 2019 23:39:33 +0000 Subject: [PATCH 095/162] Translated using Weblate (Portuguese (Portugal)) Translation: Jellyfin/Jellyfin Web Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-web/pt_PT/ --- src/strings/pt-pt.json | 112 +++++++++++++++++++++++++++++++++-------- 1 file changed, 92 insertions(+), 20 deletions(-) diff --git a/src/strings/pt-pt.json b/src/strings/pt-pt.json index 917137207c..424897880e 100644 --- a/src/strings/pt-pt.json +++ b/src/strings/pt-pt.json @@ -90,7 +90,7 @@ "Director": "Realizador", "EasyPasswordHelp": "O código PIN é utilizado para acesso off-line em clientes suportados e pode ser usado para um acesso fácil dentro da rede.", "Edit": "Editar", - "EnableCinemaMode": "Ativar modo cinema", + "EnableCinemaMode": "Modo cinema", "Ended": "Terminado", "ErrorAddingMediaPathToVirtualFolder": "Ocorreu um erro ao adicionar a localização dos seus ficheiros. Por favor, assegure-se que o local é valido e que o processo do Jellyfin Server tenha acesso a essa localização.", "ErrorGettingTvLineups": "Ocorreu um erro ao transferir a programação de TV. Por favor, certifique-se que a sua informação está correta e tente novamente.", @@ -341,17 +341,17 @@ "LabelEvent": "Evento:", "LabelEveryXMinutes": "A cada:", "LabelExtractChaptersDuringLibraryScan": "Extrair imagens dos capítulos durante a atualização da biblioteca", - "LabelExtractChaptersDuringLibraryScanHelp": "Se ativado, as imagens dos capítulos serão extraídas quando os vídeos forem importados durante a atualização da biblioteca. Se desativado, serão extraídas durante a tarefa agendada de extração de imagens dos capítulos, permitindo que a atualização da biblioteca seja mais rápida.", + "LabelExtractChaptersDuringLibraryScanHelp": "Gerar imagens dos capítulos quando os vídeos forem importados durante a atualização da biblioteca. Caso contrário, serão geradas durante a tarefa agendada de extração de imagens dos capítulos, permitindo que a atualização da biblioteca seja mais rápida.", "LabelFailed": "Falhou", "LabelFinish": "Terminar", "LabelForgotPasswordUsernameHelp": "Introduza o seu nome de utilizador, se se recordar.", "LabelFormat": "Formato:", "LabelFriendlyName": "Nome amigável:", - "LabelServerNameHelp": "Este nome será utilizado para identificar o servidor. Se não for preenchido, será usado o nome do computador.", + "LabelServerNameHelp": "Este nome será utilizado para identificar o servidor. Por defeito, é usado o nome do computador.", "LabelGroupMoviesIntoCollections": "Agrupar filmes em coleções", "LabelGroupMoviesIntoCollectionsHelp": "Ao mostrar listas de filmes, filmes que pertençam a uma coleção serão mostrados como um único item agrupado.", "LabelHardwareAccelerationType": "Aceleração por hardware:", - "LabelHardwareAccelerationTypeHelp": "Disponível apenas em sistemas suportados.", + "LabelHardwareAccelerationTypeHelp": "Esta funcionalidade é experimental e está disponível apenas em sistemas suportados.", "LabelHttpsPort": "Número do porto HTTPS local:", "LabelHttpsPortHelp": "Número do porto TCP em que o servidor HTTPS do Jellyfin ficará à escuta.", "LabelIconMaxHeight": "Altura máxima do ícone:", @@ -362,10 +362,10 @@ "LabelImageType": "Tipo de imagem:", "LabelImportOnlyFavoriteChannels": "Restringir a canais marcados como favoritos", "LabelInNetworkSignInWithEasyPassword": "Ativar acesso dentro da rede com código PIN", - "LabelInNetworkSignInWithEasyPasswordHelp": "Se ativado, poderá utilizar um código PIN para entrar no Jellyfin dentro da rede. A palavra-passe só será necessária fora da rede. Se o código PIN for deixado em branco, não será necessária autenticação dentro da rede.", + "LabelInNetworkSignInWithEasyPasswordHelp": "Utilizar um código PIN para entrar no Jellyfin dentro da rede. A palavra-passe só será necessária fora da rede. Se o código PIN for deixado em branco, não será necessária autenticação dentro da rede.", "LabelKodiMetadataDateFormat": "Formato da data de lançamento:", - "LabelKodiMetadataDateFormatHelp": "Todas as datas dentro dos nfo's serão lidas e gravadas usando este formato.", - "LabelKodiMetadataEnableExtraThumbs": "Copiar extrafanart para extrathumbs", + "LabelKodiMetadataDateFormatHelp": "Todas as datas presentes em ficheiros NFO serão analisadas utilizando este formato.", + "LabelKodiMetadataEnableExtraThumbs": "Copiar o parâmetro extrafanart para extrathumbs", "LabelKodiMetadataEnableExtraThumbsHelp": "Ao transferir imagens, estas podem ser guardadas como extrafanart e extrathumbs para uma maior compatibilidade com os temas Kodi.", "LabelKodiMetadataEnablePathSubstitution": "Ativar substituição de local", "LabelKodiMetadataEnablePathSubstitutionHelp": "Ativa a substituição do local das imagens usando as opções de substituição de caminho no servidor.", @@ -378,8 +378,8 @@ "LabelLockItemToPreventChanges": "Bloquear este item para evitar alterações futuras", "LabelLoginDisclaimer": "Aviso legal de login:", "LabelLoginDisclaimerHelp": "Este aviso será mostrado na parte inferior da página de login.", - "LabelManufacturer": "Fabricante:", - "LabelManufacturerUrl": "URL do fabricante:", + "LabelManufacturer": "Fabricante", + "LabelManufacturerUrl": "URL do Fabricante", "LabelMatchType": "Tipo de correspondência:", "LabelMaxBackdropsPerItem": "Número máximo de imagens de fundo por item:", "LabelMaxParentalRating": "Controlo parental máximo permitido:", @@ -406,7 +406,7 @@ "LabelModelUrl": "URL do modelo", "LabelMonitorUsers": "Monitorizar atividade de:", "LabelMusicStreamingTranscodingBitrate": "Taxa de transcodificação de música:", - "LabelMusicStreamingTranscodingBitrateHelp": "Defina a taxa máxima ao fazer transmissão de música.", + "LabelMusicStreamingTranscodingBitrateHelp": "Defina a taxa máxima ao fazer transmissão de música", "LabelName": "Nome:", "LabelNewPassword": "Nova palavra-passe:", "LabelNewPasswordConfirm": "Confirmar nova palavra-passe:", @@ -453,7 +453,7 @@ "LabelSendNotificationToUsers": "Enviar notificação para:", "LabelSerialNumber": "Número de série", "LabelServerHost": "Servidor:", - "LabelServerHostHelp": "192.168.1.100 ou https://omeudominio.com", + "LabelServerHostHelp": "192.168.1.100:8096 ou https://omeudominio.com", "LabelSkipIfAudioTrackPresent": "Ignorar no caso de o idioma da faixa de áudio principal coincidir com o idioma de transferência", "LabelSkipIfAudioTrackPresentHelp": "Desmarque esta opção para garantir que todos os vídeos têm legendas, independentemente do idioma do áudio.", "LabelSkipIfGraphicalSubsPresent": "Ignorar se o vídeo já possuir legendas integradas", @@ -473,7 +473,7 @@ "LabelTimeLimitHours": "Limite de tempo (horas):", "LabelTranscodingAudioCodec": "Codec de áudio:", "LabelTranscodingContainer": "Contentor:", - "LabelTranscodingTempPathHelp": "Esta pasta contém ficheiros ativos utilizados pelo transcodificador. Indique uma localização personalizada ou deixe em branco para utilizar o caminho por defeito.", + "LabelTranscodingTempPathHelp": "Indique uma localização personalizada para os ficheiros de transcodificação em utilização, ou deixe em branco para utilizar o caminho por defeito.", "LabelTranscodingThreadCount": "Número de threads de transcodificação:", "LabelTranscodingThreadCountHelp": "Indique o número máximo de threads a ser utilizado para transcodificação. Reduzir o número de threads diminuirá a utilização do CPU, mas pode não converter rápido o suficiente para uma experiência de reprodução suave.", "LabelTranscodingVideoCodec": "Codec do vídeo:", @@ -503,7 +503,7 @@ "MessageConfirmRecordingCancellation": "Cancelar a gravação?", "MessageConfirmRestart": "Tem a certeza de que deseja reiniciar o Servidor Jellyfin?", "MessageConfirmRevokeApiKey": "Tem a certeza de que deseja revogar esta chave da API? A ligação da aplicação ao Servidor Jellyfin vai ser terminada de imediato.", - "MessageConfirmShutdown": "Tem a certeza de que deseja encerrar o Servidor Jellyfin?", + "MessageConfirmShutdown": "Tem a certeza de que deseja encerrar o servidor?", "MessageDeleteTaskTrigger": "Tem a certeza de que deseja remover o agendamento desta tarefa?", "MessageDirectoryPickerBSDInstruction": "Num sistema operativo BSD, é necessário configurar o disco Jail FreeNAS para permitir o acesso do Servidor Jellyfin.", "MessageDirectoryPickerInstruction": "As localizações de rede podem ser escritas manualmente caso o botão \"Rede\" não consiga encontrar os dispositivos. Por exemplo, {0} ou {1}.", @@ -544,7 +544,7 @@ "OptionAllowMediaPlaybackTranscodingHelp": "Restringir o acesso à transcodificação pode causar falhas de reprodução nas aplicações do Jellyfin devido a formatos multimédia não suportados.", "OptionAllowRemoteControlOthers": "Permitir controlo remoto de outros utilizadores", "OptionAllowRemoteSharedDevices": "Permitir controlo remoto de dispositivos compartilhados", - "OptionAllowRemoteSharedDevicesHelp": "Dispositivos DLNA são considerados compartilhados até que um utilizador comece a controlá-lo.", + "OptionAllowRemoteSharedDevicesHelp": "Dispositivos DLNA são considerados como partilhados até que um utilizador comece a controlá-lo.", "OptionAllowUserToManageServer": "Permitir a este utilizador gerir o servidor", "OptionAllowVideoPlaybackTranscoding": "Permitir reprodução de vídeo que necessite de transcodificação", "OptionArtist": "Artista", @@ -597,7 +597,7 @@ "OptionHasThemeVideo": "Vídeo de Tema", "OptionHideUser": "Ocultar este utilizador nos formulários de início de sessão", "OptionHideUserFromLoginHelp": "Útil para contas de administrador privadas ou ocultas. O utilizador necessita de entrar manualmente, introduzindo o seu nome de utilizador e palavra-passe.", - "OptionHlsSegmentedSubtitles": "Legendas segmentadas hls", + "OptionHlsSegmentedSubtitles": "Legendas segmentadas HLS", "OptionIgnoreTranscodeByteRangeRequests": "Ignorar requisições de extensão do byte de transcodificação", "OptionIgnoreTranscodeByteRangeRequestsHelp": "Se ativadas, estas requisições serão honradas mas irão ignorar o cabeçalho da extensão do byte.", "OptionImdbRating": "Classificação no IMDb", @@ -740,7 +740,7 @@ "UninstallPluginConfirmation": "Tem a certeza de que deseja desinstalar {0}?", "UninstallPluginHeader": "Desinstalar Extensão", "Unmute": "Ativar som", - "UserProfilesIntro": "O Jellyfin inclui suporte nativo de perfis de utilizadores, permitindo que cada utilizador tenha as suas configurações de visualização, estado da reprodução e controlos parentais.", + "UserProfilesIntro": "O Jellyfin suporta perfis de utilizadores, permitindo que cada utilizador tenha as suas configurações de visualização, estado da reprodução e controlos parentais.", "ValueAudioCodec": "Codec de Áudio: {0}", "ValueConditions": "Condições: {0}", "ValueSpecialEpisodeName": "Especial - {0}", @@ -749,9 +749,9 @@ "ValueVideoCodec": "Codec de Vídeo: {0}", "Wednesday": "Quarta", "WelcomeToProject": "Bem-vindo ao Jellyfin!", - "WizardCompleted": "É tudo, de momento. O Jellyfin iniciou a recolha de informações da sua biblioteca multimédia. Conheça algumas das nossas aplicações e, de seguida, clique Terminar para ver o Painel Principal do Servidor.", + "WizardCompleted": "É tudo, de momento. O Jellyfin iniciou a recolha de informações da sua biblioteca multimédia. Conheça algumas das nossas aplicações e, de seguida, clique Terminar para ver o Painel Principal.", "Writer": "Escritor", - "XmlDocumentAttributeListHelp": "Estes atributos são aplicados ao elemento principal de cada resposta xml.", + "XmlDocumentAttributeListHelp": "Estes atributos são aplicados ao elemento principal de cada resposta XML.", "AccessRestrictedTryAgainLater": "Acesso restrito. Por favor, tente mais tarde.", "AddItemToCollectionHelp": "Adicione itens às coleções pesquisando-os e utilizando o respetivo menu de toque ou clique direito para os adicionar a uma coleção.", "AddToCollection": "Adicionar à coleção", @@ -929,7 +929,7 @@ "MessageContactAdminToResetPassword": "Por favor, contacte o Administrador de sistema para repôr a sua password.", "MessageConfirmRemoveMediaLocation": "Tem a certeza de que deseja remover esta localização?", "MessageConfirmDeleteTunerDevice": "Tem a certeza de que deseja remover este dispositivo?", - "UserAgentHelp": "Forneça um user-agent HTTP personalizado, se necessário.", + "UserAgentHelp": "Forneça um user-agent HTTP personalizado.", "OptionProtocolHttp": "HTTP", "OptionProtocolHls": "Emissão HTTP em direto", "LabelHomeScreenSectionValue": "Secção {0} do Painel Principal:", @@ -1081,5 +1081,77 @@ "DirectorsValue": "Realização: {0}", "DirectorValue": "Realizador: {0}", "ButtonOff": "Desligado", - "ButtonAddImage": "Adicionar Imagem" + "ButtonAddImage": "Adicionar Imagem", + "LabelOriginalTitle": "Título original:", + "LabelPostProcessorArgumentsHelp": "Utilizar o caminho {path} como caminho para o ficheiro de gravação.", + "Hide": "Esconder", + "LabelBaseUrl": "URL Base:", + "LabelNewName": "Novo nome:", + "HeaderUploadImage": "Enviar Imagem", + "EnableThemeSongs": "Músicas do tema", + "EnableThemeVideos": "Vídeos do tema", + "HeaderMoreLikeThis": "Mais Como Este", + "HeaderRecordingPostProcessing": "Pós-Processamento de Gravações", + "Descending": "Descendente", + "CopyStreamURLSuccess": "URL copiado com sucesso.", + "ErrorAddingListingsToSchedulesDirect": "Ocorreu um erro ao adicionar o alinhamento à sua conta Schedules Direct. As contas Schedules Direct permitem apenas um número limitado de alinhamentos. Poderá ser necessário iniciar sessão na sua conta e remover outras listagens antes de prosseguir.", + "HeaderFavoriteBooks": "Livros Favoritos", + "HeaderStopRecording": "Parar Gravação", + "HeaderVideoQuality": "Qualidade do Vídeo", + "HeaderVideoType": "Tipo de Vídeo", + "LabelFolder": "Pasta:", + "LabelOptionalNetworkPath": "(Opcional) Pasta partilhada de rede:", + "ColorSpace": "Espaço de cores", + "HeaderMyMediaSmall": "A Minha Multimédia (pequeno)", + "HeaderNewDevices": "Novos Dispositivos", + "HeaderRecordingOptions": "Opções de Gravação", + "HeaderSortOrder": "Direção de Ordenação", + "LabelBaseUrlHelp": "Pode adicionar uma sub-pasta personalizada aqui para aceder ao servidor através de um URL mais direto.", + "LabelMoviePrefixHelp": "Se aplicar um prefixo aos títulos dos filmes, introduza-o aqui para que o servidor consiga tratá-los corretamente.", + "LabelPleaseRestart": "As alterações produzirão efeito depois de recarregar a página web.", + "LabelRecordingPathHelp": "Especifique a localização por defeito para guardar as gravações. Se for deixado em branco, será utilizada a pasta base do servidor.", + "ColorTransfer": "Transferência de cores", + "ExtractChapterImagesHelp": "Extrair imagens do capítulo permite aos clientes apresentar menus de seleção de cenas com gráficos. O processo poderá ser lento e exigente em recursos, bem como ocupar múltiplos gigabytes em disco. Este processo é corrido quando novos vídeos são encontrados e também através de uma tarefa agendada noturna. É possível configurar a hora de execução para que, idealmente, não coincida com horas de maior utilização.", + "Features": "Funcionalidades", + "HeaderMusicQuality": "Qualidade da Música", + "HeaderMyDevice": "O Meu Dispositivo", + "HeaderSortBy": "Ordenar Por", + "LabelOptionalNetworkPathHelp": "Se esta pasta estiver partilhada na rede, fornecer o caminho de rede pode permitir aos clientes aceder diretamente aos ficheiros multimédia.", + "LabelPersonRoleHelp": "Exemplo: motorista da carrinha de gelados", + "LabelPlayer": "Reprodutor:", + "LabelServerName": "Nome do servidor:", + "LabelSize": "Tamanho:", + "LabelLanNetworks": "Redes locais (LAN):", + "HeaderOtherItems": "Outros Itens", + "HeaderPhotoAlbums": "Álbuns de Fotografias", + "HeaderSeasons": "Temporadas", + "HeaderSecondsValue": "{0} Segundos", + "HeaderSeriesOptions": "Opções da Série", + "HeaderSeriesStatus": "Estado da Série", + "HeaderTracks": "Faixas", + "HeaderTuners": "Sintonizadores", + "Horizontal": "Horizontal", + "LabelAudioBitrate": "Taxa de bits de áudio:", + "LabelAudioChannels": "Canais de áudio:", + "LabelAudioCodec": "Codec de áudio:", + "LabelAudioSampleRate": "Taxa de amostragem de áudio:", + "LabelBitrate": "Taxa de bits:", + "LabelCache": "Cache:", + "LabelDiscNumber": "Número do disco:", + "LabelInternetQuality": "Qualidade para a Internet:", + "LabelKidsCategories": "Categorias para crianças:", + "LabelMovieCategories": "Categorias para filmes:", + "LabelMoviePrefix": "Prefixo para filmes:", + "LabelMovieRecordingPath": "Caminho para gravação de filmes (opcional):", + "LabelNewsCategories": "Categorias para notícias:", + "LabelNumber": "Número:", + "LabelPlayMethod": "Método de reprodução:", + "LabelPostProcessor": "Aplicação de pós-processamento:", + "LabelPostProcessorArguments": "Argumentos de linha de comandos para a aplicação de pós-processamento:", + "LabelPreferredSubtitleLanguage": "Idioma preferencial das legendas:", + "LabelProfileCodecs": "Codecs:", + "LabelReasonForTranscoding": "Razão para transcodificação:", + "LabelScreensaver": "Proteção de Ecrã:", + "LabelSecureConnectionsMode": "Modo de ligação segura:", + "LabelSeriesRecordingPath": "Caminho para gravação de séries (opcional):" } From 2498014aac982404d9566dc2150323d86609f327 Mon Sep 17 00:00:00 2001 From: TheSergioEduP Date: Sun, 27 Oct 2019 21:37:45 +0000 Subject: [PATCH 096/162] Translated using Weblate (Portuguese (Portugal)) Translation: Jellyfin/Jellyfin Web Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-web/pt_PT/ --- src/strings/pt-pt.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/strings/pt-pt.json b/src/strings/pt-pt.json index 424897880e..3f3e5ac9d3 100644 --- a/src/strings/pt-pt.json +++ b/src/strings/pt-pt.json @@ -1153,5 +1153,6 @@ "LabelReasonForTranscoding": "Razão para transcodificação:", "LabelScreensaver": "Proteção de Ecrã:", "LabelSecureConnectionsMode": "Modo de ligação segura:", - "LabelSeriesRecordingPath": "Caminho para gravação de séries (opcional):" + "LabelSeriesRecordingPath": "Caminho para gravação de séries (opcional):", + "ColorPrimaries": "Cores primárias" } From 96bed867360853318831cc7837aafa8030e1b416 Mon Sep 17 00:00:00 2001 From: Pan Renzhou <1773834430@qq.com> Date: Sun, 27 Oct 2019 08:57:54 +0000 Subject: [PATCH 097/162] Translated using Weblate (Chinese (Simplified)) Translation: Jellyfin/Jellyfin Web Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-web/zh_Hans/ --- src/strings/zh-cn.json | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/strings/zh-cn.json b/src/strings/zh-cn.json index 3225feba24..4852805465 100644 --- a/src/strings/zh-cn.json +++ b/src/strings/zh-cn.json @@ -323,7 +323,7 @@ "HeaderFrequentlyPlayed": "多次播放", "HeaderGenres": "风格", "HeaderGuideProviders": "电视指南数据提供方", - "HeaderHttpHeaders": "HTTP 标头", + "HeaderHttpHeaders": "HTTP 头部", "HeaderIdentification": "身份识别", "HeaderIdentificationCriteriaHelp": "至少输入一个识别标准。", "HeaderIdentificationHeader": "身份认证标头", @@ -868,7 +868,7 @@ "MessageNoPluginsInstalled": "你没有安装插件。", "MessageNoTrailersFound": "未发现任何预告片。安装 Trailer channel 以通过添加一个网络预告片媒体库来增强你的电影体验。", "MessageNothingHere": "这里没有可显示的内容。", - "MessagePasswordResetForUsers": "下列用户的密码已重置。现在,可使用重置时的 PIN 码进行登录。", + "MessagePasswordResetForUsers": "下列用户的密码已被重置。他们现在可以用执行复位的pin码登录。", "MessagePleaseEnsureInternetMetadata": "请确认已启用从网络上下载媒体资料的选项。", "MessagePleaseWait": "请稍等。这将花费大约1分钟的时间。", "MessagePluginConfigurationRequiresLocalAccess": "请直接登录你的本地服务器以设置这个插件。", @@ -1149,7 +1149,7 @@ "ServerNameIsRestarting": "Jellyfin Server - {0} 重启中。", "ServerNameIsShuttingDown": "Jellyfin 服务器 - {0} 正在关闭。", "ServerRestartNeededAfterPluginInstall": "安装插件后,Jellyfin 服务器需要重启以使插件生效。", - "ServerUpdateNeeded": "Jellyfin 服务器需要更新,请访问 {0} 以下载最新的版本。", + "ServerUpdateNeeded": "Jellyfin 服务器需要更新,请访问 {0} 以下载最新的版本", "Settings": "设置", "SettingsSaved": "设置已保存。", "SettingsWarning": "更改这些值可能会导致不稳定或连接故障。如果您遇到任何问题, 我们建议将它们重新更改为默认值。", @@ -1362,7 +1362,7 @@ "DashboardServerName": "服务器:{0}", "LabelVideo": "视频:", "LabelWeb": "网站: ", - "LeaveBlankToNotSetAPassword": "可选 - 留空以设置无密码", + "LeaveBlankToNotSetAPassword": "您可以将此字段留空以设置空密码。", "LinksValue": "链接:{0}", "LiveBroadcasts": "直播", "LiveTV": "电视直播", @@ -1383,7 +1383,7 @@ "Option3D": "三维", "OptionDownloadLogoImage": "标志", "OptionLoginAttemptsBeforeLockout": "确定在锁定之前可以进行多少次不正确的登录尝试。", - "OptionLoginAttemptsBeforeLockoutHelp": "0 表示默认设置(非管理员 3 次,管理员 5 次),-1 表示不限制次数", + "OptionLoginAttemptsBeforeLockoutHelp": "如果值为0,则表示将允许普通用户尝试三次、管理员尝试五次的默认值。将此设置为-1将禁用此功能。", "PasswordResetProviderHelp": "选择一个密码重置提供者用于密码重置", "PlaceFavoriteChannelsAtBeginning": "将最喜爱的频道置顶", "PlayNext": "播放下一个", From 5eb28e69d054be97f0706ddc8755d23e5ea04a4a Mon Sep 17 00:00:00 2001 From: gnehs Date: Sun, 27 Oct 2019 05:53:15 +0000 Subject: [PATCH 098/162] Translated using Weblate (Chinese (Traditional)) Translation: Jellyfin/Jellyfin Web Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-web/zh_Hant/ --- src/strings/zh-tw.json | 389 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 374 insertions(+), 15 deletions(-) diff --git a/src/strings/zh-tw.json b/src/strings/zh-tw.json index d36980d1b5..7b428ad51a 100644 --- a/src/strings/zh-tw.json +++ b/src/strings/zh-tw.json @@ -3,7 +3,7 @@ "All": "全部", "AllowRemoteAccessHelp": "如果未勾選,所有連線都將被阻擋。", "Browse": "瀏覽", - "BrowsePluginCatalogMessage": "瀏覽我們的插件目錄來查看可用的插件。", + "BrowsePluginCatalogMessage": "瀏覽我們的插件目錄來查看可用的模組。", "ButtonAdd": "新增", "ButtonAddServer": "新增伺服器", "ButtonAddUser": "新增使用者", @@ -114,7 +114,7 @@ "LabelDay": "日:", "LabelDisplayMissingEpisodesWithinSeasons": "顯示節目季度內缺少的單元", "LabelEnableDlnaClientDiscoveryInterval": "尋找客戶端時間間隔(秒)", - "LabelEnableDlnaDebugLogging": "記錄DLNA除錯信息到日誌", + "LabelEnableDlnaDebugLogging": "記錄 DLNA 除錯資料到日誌", "LabelEnableDlnaDebugLoggingHelp": "將會建立非常大的日誌檔案,建議在進行故障排除時啟用。", "LabelEnableDlnaPlayTo": "播放到DLNA設備", "LabelEnableRealtimeMonitor": "啟用實時監控", @@ -287,7 +287,7 @@ "TabSettings": "設定", "TabShows": "節目", "TabSongs": "歌曲", - "TabSuggestions": "推薦內容", + "TabSuggestions": "建議", "TabTrailers": "預告", "TabTranscoding": "轉碼中", "TabUpcoming": "接下來", @@ -499,7 +499,7 @@ "EnterFFmpegLocation": "輸入 FFmpeg 路徑", "Episodes": "劇集", "Error": "錯誤", - "ErrorAddingListingsToSchedulesDirect": "我們將陣容添加到您的Schedules Direct帳戶時出錯。Schedules Direct只允許有限的帳號排序。您可能在繼續前直接登入Schedules Direct 網站和刪除其他清單。", + "ErrorAddingListingsToSchedulesDirect": "", "ErrorAddingGuestAccount1": "新增Jellyfin Connect時發生錯誤。你的賓客有建立Jellyfin帳號嗎?他們可以在 {0} 創建帳號。", "ErrorAddingGuestAccount2": "若你還是遇到問題,請發送email至 {0} 並附上你和他們的email帳號。", "ErrorAddingJellyfinConnectAccount1": "新增Jellyfin Connect時發生錯誤。您有建立Jellyfin帳號嗎?您可以在 {0} 創建帳號。", @@ -521,7 +521,7 @@ "EveryNDays": "每 {0} 天", "ExitFullscreen": "結束全螢幕", "ExtraLarge": "特大", - "ExtractChapterImagesHelp": "提取章節圖片將允許 Jellyfin 顯示圖片形式的章節選單,提取過程可能會非常緩慢、佔用大量 CPU 資源,並且可能需要幾 GB 的硬碟空間。\n提取會在影片被偵測到時啟動,同時也可作為一個夜間計劃任務運行。這個任務可以在「計劃任務」選項中進行設定。不建議在尖峰時刻使用時間進行這個任務。", + "ExtractChapterImagesHelp": "擷取章節圖片將允許 Jellyfin 顯示圖片形式的章節選單,過程可能會非常緩慢、佔用大量 CPU 資源,並且可能需要幾 GB 的硬碟空間。\n擷取會在影片被偵測到時啟動,同時也可作為一個夜間計劃任務運行,這個任務可以在「計劃任務」選項中進行設定,不建議在尖峰時刻使用時間進行這個任務。", "Extras": "額外", "FFmpegSavePathNotFound": "我們無法通過你輸入的路徑找到 FFmpeg。 FFprobe 同樣也是必要且應該被放在同一個資料夾中。他們通常會被打包在一起以供下載。請檢查這個路徑然後再試一次。", "FastForward": "快轉", @@ -572,7 +572,7 @@ "HeaderAllowMediaDeletionFrom": "允許從中刪除媒體", "HeaderApiKey": "API 金鑰", "HeaderApiKeys": "API 金鑰", - "HeaderApiKeysHelp": "外部應用程式需要有一個 API 金鑰以用於和 Jellyfin 伺服器溝通。金鑰將在通過 Jellyfin 帳戶登入時自動發行,或者你可以手動為應用程式生成一個金鑰。", + "HeaderApiKeysHelp": "外部應用程式需要有一個 API 金鑰以用於和 Jellyfin 伺服器溝通。金鑰將在通過 Jellyfin 帳戶登入時自動發行,或者你可以手動為應用程式產生一個金鑰。", "HeaderApp": "應用程式", "HeaderAppearsOn": "同時出現於", "HeaderAudio": "音訊", @@ -613,8 +613,8 @@ "HeaderConfirmation": "確認", "HeaderConnectToServer": "連結至伺服器", "HeaderConnectionFailure": "連結失敗", - "HeaderContainerProfile": "媒體載體設定檔", - "HeaderContainerProfileHelp": "媒體載體的設定檔標明了設備播放特定媒體格式時的限制。如果在限制之內則媒體將被轉碼,否則媒體格式將被設定為直接播放。", + "HeaderContainerProfile": "影片容器設定檔", + "HeaderContainerProfileHelp": "影片容器的設定檔標明了設備播放特定媒體格式時的限制。如果在限制之內則媒體將被轉碼,否則媒體格式將被設定為直接播放。", "HeaderContinueListening": "繼續聆聽", "HeaderContinueWatching": "繼續觀賞", "HeaderConvertYourRecordings": "為你的錄制轉檔", @@ -1043,7 +1043,7 @@ "LabelEnableHardwareDecodingFor": "為以下啟用硬體解碼:", "LabelEpisodeNumber": "集:", "LabelBaseUrlHelp": "您可以在此處新增自訂路徑來進入伺服器。", - "LabelExtractChaptersDuringLibraryScan": "於媒體庫掃描時提取章節圖片", + "LabelExtractChaptersDuringLibraryScan": "於媒體庫掃描時擷取章節圖片", "LabelHttpsPort": "本地 HTTPS 端口:", "LabelFailed": "失敗", "LabelSubtitles": "字幕:", @@ -1066,14 +1066,14 @@ "LabelVideoCodec": "影片編碼:", "LabelYear": "年:", "LatestFromLibrary": "最新 {0}", - "Logo": "Logo", + "Logo": "標誌", "ManageLibrary": "管理媒體庫", "MarkPlayed": "標記為已播放", "MarkUnplayed": "標記為未播放", "MediaInfoBitrate": "比特率", "MediaInfoChannels": "聲道", "MediaInfoCodec": "編碼", - "MediaInfoContainer": "容器", + "MediaInfoContainer": "影片容器", "MediaInfoExternal": "外部", "MediaInfoForced": "強迫", "MediaInfoFramerate": "幀率", @@ -1220,11 +1220,11 @@ "Screenshot": "截圖", "Suggestions": "建議", "TabCodecs": "編碼", - "TabContainers": "容器", + "TabContainers": "影片容器", "TabDashboard": "控制台", "TabDisplay": "顯示", "TabFavorites": "最愛", - "TabLogs": "紀錄檔", + "TabLogs": "日誌", "TabNotifications": "通知", "TabOther": "其他", "TabParentalControl": "家長控制", @@ -1234,7 +1234,7 @@ "Thumb": "縮圖", "TabResumeSettings": "繼續播放", "ValueAlbumCount": "{0} 張專輯", - "ValueContainer": "容器:{0}", + "ValueContainer": "影片容器:{0}", "ValueEpisodeCount": "{0} 集", "ValueDiscNumber": "光碟#{0}", "ValueMinutes": "{0} 分", @@ -1264,5 +1264,364 @@ "PerfectMatch": "最佳配對", "PictureInPicture": "浮窗播放", "PlayFromBeginning": "從頭開始播放", - "PlayNext": "播放下一個" + "PlayNext": "播放下一個", + "Next": "下一個", + "OptionCaptionInfoExSamsung": "CaptionInfoEx(三星)", + "People": "人物", + "OptionEnableExternalContentInSuggestions": "在建議中啟用外部內容", + "OptionEnableM2tsMode": "啟用 M2ts 模式", + "LabelKeepUpTo": "保持:", + "LabelKidsCategories": "兒童分類:", + "LabelKodiMetadataEnablePathSubstitution": "啟用路徑替換", + "LabelKodiMetadataEnableExtraThumbs": "複製 extrafanart 到 extrathumbs 欄位", + "LabelMovieCategories": "電影分類:", + "LabelMoviePrefix": "電影前綴:", + "LabelProfileContainer": "影片容器:", + "LabelDropShadow": "陰影:", + "LabelSecureConnectionsMode": "安全連接模式:", + "LabelTVHomeScreen": "電視模式主畫面:", + "LabelTranscodingContainer": "影片容器:", + "MovieLibraryHelp": "查看 {0}Jellyfin 電影命名指南{1}。", + "None": "無", + "LinksValue": "連結:{0}", + "OptionAllowMediaPlaybackTranscodingHelp": "由於不支持的媒體格式,限制轉檔可能會導致 Jellyfin 應用程式播放失敗。", + "MediaInfoLevel": "等級", + "MessageNoTrailersFound": "沒有任何預告片,安裝 Trailer channel 來優化你的電影體驗。", + "OptionHasSpecialFeatures": "特色", + "RecommendationStarring": "主演 {0}", + "Rewind": "倒帶", + "RunAtStartup": "開機時啟動", + "SubtitleOffset": "字幕偏移", + "TabPlayback": "播放", + "Unrated": "尚未評等", + "Up": "上", + "ValueOneSeries": "1 劇集", + "Writer": "編劇", + "XmlTvMovieCategoriesHelp": "有這些類別的節目會被當作電影。用「|」分隔多個。", + "ValueSeriesCount": "{0} 劇集", + "LabelHardwareAccelerationTypeHelp": "這個功能只能在支援的系統上使用。", + "LabelHomeNetworkQuality": "區域網路畫質:", + "LabelHomeScreenSectionValue": "主畫面模塊 {0}:", + "LabelMetadataDownloadersHelp": "啟用媒體屬性下載器的優先次序,愈下次序只會用來填補缺少的信息。", + "LabelMetadataReaders": "中繼資料閱讀器:", + "LabelMetadataSaversHelp": "選取儲存中繼資料的檔案格式。", + "LabelModelNumber": "型號", + "LabelNewsCategories": "新分類:", + "LabelValue": "數值:", + "OptionBanner": "橫幅", + "OptionDownloadBannerImage": "橫幅", + "OptionEnableAccessToAllChannels": "允許存取所有頻道", + "OptionEnableAccessToAllLibraries": "允許存取所有媒體庫", + "OptionEnableAutomaticServerUpdates": "啟用自動更新", + "OptionEnableForAllTuners": "开启所有调谐器", + "OptionExtractChapterImage": "開啟章節圖片擷取", + "OptionEnableM2tsModeHelp": "當編碼為 MPEGTS 時啟用 M2TS 模式。", + "OptionEquals": "等於", + "OptionEstimateContentLength": "轉檔時,估計內容長度", + "OptionExternallyDownloaded": "外部下載", + "OptionHlsSegmentedSubtitles": "HLS 分段字幕", + "OptionLoginAttemptsBeforeLockout": "確定在被封鎖之前可以登入失敗幾次。", + "OptionRequirePerfectSubtitleMatch": "只下載與我的影片檔案完美匹配的字幕", + "PlayCount": "播放次數", + "Series": "電視劇", + "SeriesCancelled": "電視劇已取消。", + "SeriesDisplayOrderHelp": "按播出日期、DVD 順序或編號對劇集進行排序。", + "SeriesSettings": "系列設定", + "SeriesYearToPresent": "{0} - 現在", + "ServerNameIsRestarting": "Jellyfin Server - {0} 重啟中。", + "ServerNameIsShuttingDown": "Jellyfin 伺服器 - {0} 正在關閉。", + "SimultaneousConnectionLimitHelp": "允許的同時串流的最大數量。輸入 0 表示無限制。", + "SkipEpisodesAlreadyInMyLibrary": "不錄製我的媒體庫裡已存在的劇集", + "SmallCaps": "小型大寫字母", + "SortChannelsBy": "頻道排序方式:", + "SortName": "排序名稱", + "Sports": "體育", + "StopRecording": "停止錄影", + "LabelDefaultUserHelp": "確定哪些使用者媒體庫將顯示在連接裝置上。這可以為每個裝置提供不同的使用者設定檔。", + "LabelEnableBlastAliveMessagesHelp": "若此伺服器無法被其他 UPnP 裝置偵測到,請啟用此選項。", + "LabelEnableDlnaClientDiscoveryIntervalHelp": "由 Jellyfin 決定進行 SSDP 搜尋之間的持續時間(以秒為單位)。", + "LabelEnableDlnaPlayToHelp": "偵測您網路裡的設備並遠端控制它們。", + "LabelExtractChaptersDuringLibraryScanHelp": "當媒體庫匯入影片並掃描時,將擷取章節圖片。\n否則,章節圖片將在之後的計畫任務中擷取,而媒體庫會更快完成掃描。", + "LabelMoviePrefixHelp": "若前綴套用到電影標題,請在此處輸入它來方便伺服器能夠正確處理。", + "LabelMovieRecordingPath": "電影錄製路徑(選用):", + "LabelNotificationEnabled": "啟用這個通知", + "LabelProfileContainersHelp": "以逗號分隔。留空則適用於所有影片容器。", + "LabelSelectFolderGroupsHelp": "未選中的資料夾將在其自己的檢視中顯示。", + "LabelSerialNumber": "序號", + "LabelSeriesRecordingPath": "電視劇錄影路徑(選用):", + "LabelServerHost": "主機:", + "LabelSimultaneousConnectionLimit": "同時串流限制:", + "LabelSize": "大小:", + "LabelSkin": "主題:", + "LabelSkipBackLength": "跳過長度:", + "LabelSkipIfGraphicalSubsPresentHelp": "保留文字版本的字幕會更有效率傳遞,減低影片轉碼的機會。", + "LabelStopWhenPossible": "當可能時自動停止:", + "LabelStopping": "停止", + "LabelTagline": "個性宣言:", + "LabelSubtitleDownloaders": "字幕下載器:", + "LabelSubtitleFormatHelp": "例如:SRT", + "LabelSubtitlePlaybackMode": "字幕模式:", + "LabelTranscodingThreadCount": "轉檔執行緒數:", + "LabelTunerIpAddress": "調諧器 IP 位址:", + "LabelTunerType": "調諧器類型:", + "LabelUseNotificationServices": "使用以下服務:", + "LabelUserAgent": "使用者代理:", + "LabelUserLibrary": "使用者程式庫:", + "LabelUserLibraryHelp": "選擇在裝置上顯示的使用者媒體庫,留空則使用預設設定值。", + "LabelUserLoginAttemptsBeforeLockout": "使用者被封鎖前可嘗試的次數:", + "LabelVaapiDeviceHelp": "此渲染節點用來硬體加速。", + "LabelWeb": "網站: ", + "LabelXDlnaCapHelp": "決定在 urn:schemas-dlna-org:device-1-0 namespace 中的 X_DLNACAP 元素的內容。", + "LabelXDlnaDocHelp": "決定在 urn:schemas-dlna-org:device-1-0 namespace 中的 X-Dlna doc 元素的內容。", + "LaunchWebAppOnStartup": "在啟動伺服器時啟動使用者介面", + "LabelUserRemoteClientBitrateLimitHelp": "覆蓋伺服器重播設定中設置的預設全域值。", + "LabelTranscodingThreadCountHelp": "選擇轉檔時要使用的最大執行緒數,減少執行緒數將降低 CPU 使用率,但轉換速度可能不足以提供流暢的播放體驗。", + "LabelXDlnaCap": "X-DLNA 上限:", + "LabelXDlnaDoc": "X-DLNA 檔案:", + "LeaveBlankToNotSetAPassword": "您可以將此欄位留空來將密碼設定為無。", + "LiveTV": "電視直播", + "MapChannels": "映射頻道", + "MediaInfoAnamorphic": "畸形", + "MediaInfoAspectRatio": "長寬比", + "MediaInfoCodecTag": "編碼標籤", + "MediaInfoInterlaced": "隔行掃描", + "MediaInfoPixelFormat": "像素格式", + "MediaInfoProfile": "設定檔", + "MediaInfoRefFrames": "參考幀", + "MediaInfoResolution": "解析度", + "MediaIsBeingConverted": "媒體正在轉換為相容播放裝置的格式。", + "MessageConfirmDeleteGuideProvider": "您確定要刪除此指南提供者嗎?", + "MessageConfirmProfileDeletion": "您確定要刪除這個設定檔嗎?", + "MessageConfirmRemoveMediaLocation": "您確定要移除這個位置嗎?", + "MessageConfirmRevokeApiKey": "您確定要撤銷這個 API 金鑰嗎?這個應用程式與 Jellyfin 伺服器的連接將立即中斷。", + "MessageCreateAccountAt": "在 {0} 建立使用者", + "MessageDeleteTaskTrigger": "您確定要刪除這個任務觸發器嗎?", + "MessageDirectoryPickerBSDInstruction": "對於 BSD 系統,您需要設定包含您 FreeNAS Jail 虛擬機的儲存以便 Jellyfin 存取。", + "MessageDirectoryPickerInstruction": "在網路按鈕無法找到您的裝置的情況下,網路路徑可被手動輸入。例如:{0} 或 {1}。", + "MessageDirectoryPickerLinuxInstruction": "使用 Linux on Arch Linux、CentOS、Debian、Fedora、OpenSuse 或 Ubuntu 作業系統,您必須授權使用者至少讀取權限來存取您的儲存路徑。", + "MessageEnablingOptionLongerScans": "啟用這個選項可能會延長媒體庫的掃描時間。", + "MessageFileReadError": "讀取檔案時發生錯誤。", + "MessageForgotPasswordInNetworkRequired": "請檢查您的區域網路後再試一次來開始密碼重置流程。", + "MessageForgotPasswordFileCreated": "已在伺服器上建立了以下檔案,並包含有關後續步驟說明:", + "MessageNoAvailablePlugins": "沒有可用的模組。", + "MessageNoServersAvailable": "無法自動偵測伺服器。", + "MessageLeaveEmptyToInherit": "保留為空以繼承父項或全域預設值的設定。", + "MessageNoCollectionsAvailable": "分組能夠讓您享受個性化的影片、劇集和專輯。點擊+按鈕開始建立分組。", + "MessagePlayAccessRestricted": "此內容的播放受到限制,聯繫您的伺服器管理員以獲取更多訊息。", + "MessagePluginConfigurationRequiresLocalAccess": "請直接登入你的本地伺服器以設定這個模組。", + "MessagePluginInstallDisclaimer": "安裝 Jellyfin 社區成員建立的模組來獲取額外的功能可以最佳化您的 Jellyfin。但他們可能會對你的 Jellyfin 伺服器造成的影響,如更長的媒體庫掃描時間、額外的背景資料處理和降低系統穩定性等。", + "MessageReenableUser": "請參閱以下以重新啟用", + "MessageUnableToConnectToServer": "無法連上所選的伺服器,請確保該伺服器正在運作中。", + "MessageYouHaveVersionInstalled": "你目前安裝了 {0} 版本。", + "MoreFromValue": "更多來自 {0}", + "News": "新聞", + "NoNewDevicesFound": "找不到裝置,要添加新調諧器,請關閉此對話框並手動輸入裝置訊息。", + "OnlyForcedSubtitles": "僅顯示強制字幕", + "OnlyImageFormats": "僅圖片格式(VOBSUB、PGS、SUB 等)", + "OptionAllowLinkSharingHelp": "只有網頁包含的媒體訊息會被共享,媒體檔案本身不會被公開共享,共享的內容會在 {0} 天後到期。", + "OptionAllowRemoteSharedDevices": "允許遠端控制共享裝置", + "OptionAllowSyncTranscoding": "允許需要轉檔的媒體下載和同步", + "OptionAllowVideoPlaybackRemuxing": "允許播放需轉換但無需重新編碼的影片", + "MessageTheFollowingLocationWillBeRemovedFromLibrary": "以下媒體位置將從您的媒體庫中刪除:", + "MetadataSettingChangeHelp": "更改中繼資料設定將影響新增的新內容。要重新整理現有內容,請打開詳細訊息視窗並點選「重新整理」按鈕,或使用中繼資料管理器執行批次重新整理。", + "MusicLibraryHelp": "查看{0}音樂命名指南{1}。", + "OptionAutomaticallyGroupSeries": "自動合併分布在不同資料夾的電視劇", + "OptionAutomaticallyGroupSeriesHelp": "分布在這個媒體庫的多個文件夾中的同一部電視劇將會自動整合成一部電視劇。", + "OptionDateAddedImportTime": "使用加入媒體庫時的掃描日期", + "OptionDisplayFolderView": "顯示「資料夾」類別來瀏覽你的媒體資料夾", + "OptionEmbedSubtitles": "在影片容器中嵌入", + "OptionDownloadImagesInAdvance": "提前下載圖片", + "OptionEnableAccessFromAllDevices": "允許所有裝置存取", + "OptionDownloadImagesInAdvanceHelp": "預設情況下,大多數圖片僅在Jellyfin應用程式請求時下載。啟用此選項可於匯入新媒體後提前下載所有圖片,可能會延長的媒體庫掃描時間。", + "OptionEnableExternalContentInSuggestionsHelp": "允許將網際網路預告片和直播電視節目包含在建議的內容中。", + "OptionHideUserFromLoginHelp": "對私人或隱藏的管理員帳戶很有用,但需手動輸入使用者名稱和密碼登入。", + "OptionPlainStorageFolders": "顯示所有資料夾作為一般存儲資料夾", + "OptionPlainVideoItems": "顯示所有影片為一般影片項目", + "OptionPlainVideoItemsHelp": "所有影片在 DIDL 中顯示為「object.item.videoItem」,而不是一個更具體的類型,如「object.item.videoItem.movie」。", + "OptionProtocolHls": "HTTP 直播串流", + "OptionReportByteRangeSeekingWhenTranscoding": "轉檔時,回報伺服器支持的位元組查詢", + "OptionSaveMetadataAsHidden": "儲存媒體資料和圖片為隱藏文件", + "OptionSubstring": "子串", + "OptionWeekdays": "工作日", + "Overview": "概述", + "PackageInstallCancelled": "{0} 安裝被取消。", + "PlayAllFromHere": "從這裡開始全部播放", + "PleaseAddAtLeastOneFolder": "請點擊新增按鈕,新增至少一個資料夾到這個媒體庫。", + "PleaseConfirmPluginInstallation": "點擊「OK」以確認您已經閱讀了上述內容並希望繼續安裝模組。", + "PleaseEnterNameOrId": "請輸入一個名稱或一個外部 ID。", + "PleaseRestartServerName": "請重啟 Jellyfin 伺服器 - {0}。", + "PleaseSelectTwoItems": "請至少選擇 2 個項目。", + "PreferEmbeddedTitlesOverFileNames": "優先使用內建的標題而不是檔案名稱", + "PreferEmbeddedTitlesOverFileNamesHelp": "這將在沒有網路上的中繼資料或本地中繼資料可用時顯示預設標題。", + "PreferredNotRequired": "首選,但非必需", + "Premiere": "首映", + "Premieres": "首映", + "Previous": "上一個", + "Primary": "封面圖", + "Producer": "監製", + "ProductionLocations": "產地", + "Programs": "節目", + "Quality": "品質", + "PackageInstallFailed": "{0} 安裝失敗。", + "QueueAllFromHere": "將這裡的全部內容加入佇列", + "Raised": "提高", + "Rate": "評等", + "Recordings": "錄影", + "ServerRestartNeededAfterPluginInstall": "安裝模組後,Jellyfin 伺服器需要重啟以使模組生效。", + "ShowIndicatorsFor": "顯示指標:", + "Sort": "排序", + "Studios": "工作室", + "TheseSettingsAffectSubtitlesOnThisDevice": "這些設定僅影響該裝置的字幕顯示", + "TitleHardwareAcceleration": "硬體加速", + "TitleHostingSettings": "主機設定", + "Uniform": "輪廓", + "Unmute": "取消靜音", + "Unplayed": "尚未播放", + "TvLibraryHelp": "查看{0}電視命名指南{1}。", + "LabelMonitorUsers": "監控活動:", + "LabelPleaseRestart": "改動將在手動重啟用戶端後生效。", + "LabelProfileCodecsHelp": "以逗號分隔。留空則適用於所有編解碼器。", + "OptionPlainStorageFoldersHelp": "如果啟用,所有文件夾在DIDL中顯示為「object.container.storageFolder 」,而不是一個更具體的類型,如「object.container.person.musicArtist」。", + "LabelInNetworkSignInWithEasyPasswordHelp": "你可以在你的家庭網路中使用你的簡易 PIN 碼登錄 Jellyfin 應用程式,僅在你使用外部網路時才需要輸入密碼,如果 PIN 碼留空,那麼在你的區域網路中便不需輸入密碼。", + "LabelReleaseDate": "釋出日期:", + "LabelRemoteClientBitrateLimit": "網際網路串流傳輸位元率限制(Mbps):", + "LanNetworksHelp": "", + "OptionIgnoreTranscodeByteRangeRequests": "忽略轉檔位元組範圍請求", + "OptionIgnoreTranscodeByteRangeRequestsHelp": "如果啟用,這些請求會被兌現,但會忽略的位元組範圍標頭。", + "OptionLoginAttemptsBeforeLockoutHelp": "若值為 0,則表示將允許普通使用者嘗試三次、管理員嘗試五次的預設值,設定為 -1 來停用此功能。", + "OptionRequirePerfectSubtitleMatchHelp": "", + "PluginInstalledMessage": "這個模組安裝成功,但 Jellyfin 伺服器需要重啟以使模組生效。", + "RecordingPathChangeMessage": "更改錄製資料夾不會將現有錄製從舊位置遷移到新的,您需要手動移動它們。", + "RestartPleaseWaitMessage": "Jellyfin 伺服器將重新啟動,這將花費幾分鐘時間。", + "LabelEmbedAlbumArtDidl": "於 Didl 中嵌入專輯封面", + "LabelEnableAutomaticPortMapHelp": "自動嘗試映射公共連接埠到 UPnP 本地連接埠。這可能無法用於某些路由器。", + "LabelEmbedAlbumArtDidlHelp": "有些裝置使用這個方式來取得專輯封面,啟用這個選項可能導致其他設備播放失敗。", + "SettingsWarning": "更改這些值可能會導致不穩定或連線故障。如果您遇到任何問題,建議將它們重新更改為預設值。", + "LabelEnableSingleImageInDidlLimitHelp": "若在 Didl 中嵌入多個圖片,某些裝置可能無法正常顯示。", + "SortByValue": "排序方式:{0}", + "LabelLineup": "排隊:", + "LabelLocalHttpServerPortNumber": "本地 HTTP 端口:", + "LabelLocalHttpServerPortNumberHelp": "Jellyfin HTTP 伺服器監聽的 TCP 端口。", + "SubtitleAppearanceSettingsAlsoPassedToCastDevices": "這些設定也會被套用在任何透過此裝置發起的 Chromecast 播放。", + "LabelLoginDisclaimer": "登入字句:", + "LabelLogs": "日誌:", + "SubtitleDownloadersHelp": "按優先順序啟用並排列您的首選字幕下載程式。", + "LabelMatchType": "匹配的類型:", + "SystemDlnaProfilesHelp": "系統設定檔案是唯讀的,更改系統設定檔案將被儲存到自訂的新設定檔案。", + "LabelNumber": "編號:", + "LabelNumberOfGuideDays": "下載電視指南日數:", + "OnlyForcedSubtitlesHelp": "只有標記為「強制」的字幕會被載入。", + "PackageInstallCompleted": "{0} 安裝完成。", + "OptionDisplayFolderViewHelp": "在其他媒體庫旁邊顯示資料夾,對想要一個普通的資料夾檢視很有用。", + "LabelReasonForTranscoding": "轉檔原因:", + "LabelRecord": "錄影:", + "LabelRecordingPath": "預設錄影路徑:", + "LabelRecordingPathHelp": "指定用於存儲轉檔的位置,留空將使用伺服器的程式根目錄。", + "LabelRemoteClientBitrateLimitHelp": "所有網路裝置都有可選的流位元率限制,這對於防止設備請求比網路連接所能處理的更高的位元率非常有用。這可能會導致伺服器上的 CPU 負載增加,以便將影片轉檔到較低的位元率。", + "SmartSubtitlesHelp": "當音訊為外語時,將載入與語言偏好匹配的字幕。", + "SubtitleAppearanceSettingsDisclaimer": "這些設定將不會套用在圖形字幕(如 PGS、DVD 等),或者一些有著自己的內建樣式的字幕(ASS/SSA)。", + "UserAgentHelp": "提供自訂的使用者代理 HTTP 標頭。", + "LabelRuntimeMinutes": "播放時長(分鐘):", + "LabelScheduledTaskLastRan": "最後執行 {0},花費時間 {1}。", + "LabelSkipForwardLength": "快轉長度:", + "LabelSkipIfAudioTrackPresent": "如果預設音軌的語言和下載語言一樣則跳過", + "LabelSkipIfAudioTrackPresentHelp": "取消此項,無論音訊語言是否一致,所有影片都會下載字幕。", + "LabelSkipIfGraphicalSubsPresent": "跳過有內嵌字幕的影片", + "LabelSonyAggregationFlags": "Sony 整合標誌:", + "LabelSonyAggregationFlagsHelp": "決定在 urn:schemas-dlna-org:device-1-0 namespace 中的 aggregationFlags 元素的內容。", + "LabelSortOrder": "排列順序:", + "LabelSortTitle": "短標題:", + "LabelSoundEffects": "音效:", + "LabelSource": "來源:", + "LabelSpecialSeasonsDisplayName": "SP 季顯示名稱:", + "LabelSportsCategories": "體育分類:", + "LabelStartWhenPossible": "當可能時自動開始:", + "LabelVaapiDevice": "VA API 裝置:", + "DashboardArchitecture": "結構:{0}", + "MediaInfoSampleRate": "採樣率", + "MessageContactAdminToResetPassword": "請聯繫您的管理員來重置密碼。", + "MessageUnsetContentHelp": "內容將顯示為純資料夾,建議使用中繼資料管理器設置子資料夾的內容類型。", + "OptionAllowAudioPlaybackTranscoding": "允許播放需要轉檔的音訊", + "OptionCustomUsers": "自訂", + "OptionDateAddedFileTime": "使用檔案建立日期", + "OptionReportByteRangeSeekingWhenTranscodingHelp": "", + "XmlTvNewsCategoriesHelp": "有這些類別的節目會被當作新聞節目。用「|」分隔多個。", + "LabelKodiMetadataEnableExtraThumbsHelp": "為了相容 Kodi 主題,下載的圖片將被同時儲存在 extrafanart 和 extrathumbs 資料夾中。", + "LabelInternetQuality": "網路畫質:", + "LabelKodiMetadataEnablePathSubstitutionHelp": "允許將圖片的路徑以伺服器路徑來替換。", + "LabelKodiMetadataSaveImagePathsHelp": "如果您的圖片檔案名稱不符合 Kodi 規範,建議啟用。", + "LabelKodiMetadataUser": "儲存這些使用者的觀看資料到 NFO 檔案裏:", + "LabelKodiMetadataUserHelp": "儲存觀看資料到 NFO 檔案中以便其他應用程式使用。", + "LabelMetadataReadersHelp": "優先排序您的首選資料屬性來源,首個找到的文件將被讀取。", + "LabelMetadataSavers": "中繼資料儲存方式:", + "LabelModelDescription": "型號描述", + "LabelModelName": "型號名稱", + "LabelModelUrl": "型號網址", + "LabelMusicStreamingTranscodingBitrate": "音樂轉檔比特率:", + "LabelMusicStreamingTranscodingBitrateHelp": "指定音樂串流時的最大比特率", + "LabelOptionalNetworkPathHelp": "如果這個資料夾在網路上分享,提供網路分享路徑可以供其他 Jellyfin 應用程式直接存取媒體檔案。", + "LabelOriginalAspectRatio": "原始長寬比:", + "LabelOverview": "內容概述:", + "LabelParentalRating": "家長分級:", + "LabelPasswordConfirm": "確認密碼:", + "LabelPasswordResetProvider": "密碼重設提供者:", + "LabelPasswordRecoveryPinCode": "PIN 碼:", + "LabelPath": "路徑:", + "LabelPersonRole": "角色:", + "LabelPersonRoleHelp": "例如:冰淇淋車司機", + "LabelPlaceOfBirth": "出生地:", + "LabelPlayDefaultAudioTrack": "無論如何都播放預設音軌", + "LabelPlayer": "播放器:", + "LabelPlayMethod": "播放方式:", + "LabelParentNumber": "父編號:", + "LabelPostProcessor": "後處理應用程式:", + "LabelPostProcessorArguments": "處理器後命令行參數:", + "LabelPostProcessorArgumentsHelp": "使用 {path} 作為錄製檔案的路徑。", + "LabelPreferredDisplayLanguage": "首選語言:", + "LabelPreferredDisplayLanguageHelp": "翻譯 Jellyfin 是一個進行中的項目。", + "LabelPreferredSubtitleLanguage": "字幕語言偏好:", + "LabelProtocol": "協議:", + "LabelProtocolInfo": "協議資訊:", + "LabelPublicHttpPort": "公開 HTTP 端口:", + "LabelPublicHttpsPort": "公開 HTTPS 端口:", + "LabelProtocolInfoHelp": "當響應來自裝置的 GetProtocolInfo(獲取協議訊息)請求時,該值將被使用。", + "LabelPublicHttpPortHelp": "公開連接埠應映射到本地 HTTP 連接埠。", + "LabelPublicHttpsPortHelp": "公開連接埠應映射到本地 HTTPS 連接埠。", + "LabelReadHowYouCanContribute": "了解如何作出貢獻。", + "LabelSelectFolderGroups": "自動將以下資料夾中的內容分組到視圖中,例如電影、音樂和電視:", + "LabelStatus": "狀態:", + "LiveBroadcasts": "直播", + "MessageImageTypeNotSelected": "在下拉選單中選取圖片類型。", + "RemoveFromCollection": "從收藏移除", + "RepeatEpisodes": "重複劇集", + "RequiredForAllRemoteConnections": "所有遠端連接都需要", + "SaveSubtitlesIntoMediaFolders": "保存字幕到媒體所在資料夾", + "SaveSubtitlesIntoMediaFoldersHelp": "將字幕存儲在影片檔案旁邊可以讓管理更方便。", + "ScanForNewAndUpdatedFiles": "掃描新的和有修改的文件", + "Schedule": "排程", + "TabCollections": "收藏", + "TabNetworking": "網路", + "TitlePlayback": "播放", + "ValueConditions": "條件:{0}", + "Vertical": "垂直", + "VideoRange": "影片範圍", + "ViewPlaybackInfo": "查看播放訊息", + "XmlTvSportsCategoriesHelp": "有這些類別的節目會被當作體育節目。用「|」分隔多個。", + "XmlTvPathHelp": "XML 電視檔案的路徑,Jellyfin 將讀取該檔案並定期檢查其更新,您負責建立和更新檔案。", + "MessageInvalidForgotPasswordPin": "簡易代碼錯誤或已過期,請再試一次。", + "OptionAllowVideoPlaybackTranscoding": "允許播放需要轉檔的影片", + "Small": "小", + "Smaller": "更小", + "XmlTvKidsCategoriesHelp": "有這些類別的節目會被當作兒童節目。用「|」分隔多個。", + "TabResponses": "響應", + "LabelDisplaySpecialsWithinSeasons": "顯示劇集季度中的特集", + "LabelNumberOfGuideDaysHelp": "下載更多電視指南資料會提供更好時間表查看能力,但將需要更長的下載時間。自動基於頻道數目來選擇。", + "LabelOptionalNetworkPath": "(選用)分享的網路資料夾:", + "MessageInstallPluginFromApp": "必須從要在其中使用它的應用程式中安裝此模組。", + "OptionResElement": "res 元素", + "PinCodeResetComplete": "PIN 碼已被重設。", + "PinCodeResetConfirmation": "你確定要重設 PIN 碼?", + "PasswordResetProviderHelp": "選擇密碼重設提供者以便使用者重設密碼", + "PlaceFavoriteChannelsAtBeginning": "將喜愛的頻道置頂", + "PlaybackData": "恢復播放資料" } From d20b1fed685f311fc4cc6820aa049c966a4fcb52 Mon Sep 17 00:00:00 2001 From: grafixeyehero Date: Mon, 28 Oct 2019 18:56:48 +0300 Subject: [PATCH 099/162] remove isLoggedIntoConnect --- src/bower_components/apiclient/connectionmanager.js | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/bower_components/apiclient/connectionmanager.js b/src/bower_components/apiclient/connectionmanager.js index 763fd784c1..e6c9430cc4 100644 --- a/src/bower_components/apiclient/connectionmanager.js +++ b/src/bower_components/apiclient/connectionmanager.js @@ -760,10 +760,6 @@ define(["events", "apiclient", "appStorage"], function (events, apiClientFactory }); }; - ConnectionManager.prototype.isLoggedIntoConnect = function () { - return !(!this.connectToken() || !this.connectUserId()); - }; - ConnectionManager.prototype.getApiClients = function () { var servers = this.getSavedServers(); From 0b13b0328a44032d9d84f6c9f644853d8604de50 Mon Sep 17 00:00:00 2001 From: grafixeyehero Date: Mon, 28 Oct 2019 20:35:35 +0300 Subject: [PATCH 100/162] Remove connectuser --- .../apiclient/connectionmanager.js | 41 +------------------ 1 file changed, 1 insertion(+), 40 deletions(-) diff --git a/src/bower_components/apiclient/connectionmanager.js b/src/bower_components/apiclient/connectionmanager.js index e6c9430cc4..e0c40e19ba 100644 --- a/src/bower_components/apiclient/connectionmanager.js +++ b/src/bower_components/apiclient/connectionmanager.js @@ -34,7 +34,6 @@ define(["events", "apiclient", "appStorage"], function (events, apiClientFactory function resolveFailure(instance, resolve) { resolve({ State: "Unavailable", - ConnectUser: instance.connectUser() }); } @@ -253,12 +252,6 @@ define(["events", "apiclient", "appStorage"], function (events, apiClientFactory } function getImageUrl(localUser) { - if (connectUser && connectUser.ImageUrl) { - return { - url: connectUser.ImageUrl - }; - } - if (localUser && localUser.PrimaryImageTag) { return { url: self.getApiClient(localUser).getUserImageUrl(localUser.Id, { @@ -460,12 +453,6 @@ define(["events", "apiclient", "appStorage"], function (events, apiClientFactory console.log("Begin ConnectionManager constructor"); var self = this; this._apiClients = []; - var connectUser; - - self.connectUser = function () { - return connectUser; - }; - self._minServerVersion = "3.2.33"; self.appVersion = function () { @@ -488,14 +475,6 @@ define(["events", "apiclient", "appStorage"], function (events, apiClientFactory return credentialProvider; }; - self.connectUserId = function () { - return credentialProvider.credentials().ConnectUserId; - }; - - self.connectToken = function () { - return credentialProvider.credentials().ConnectAccessToken; - }; - self.getServerInfo = function (id) { return credentialProvider.credentials().Servers.filter(function (s) { return s.Id === id; @@ -590,10 +569,9 @@ define(["events", "apiclient", "appStorage"], function (events, apiClientFactory var image = getImageUrl(localUser); resolve({ localUser: localUser, - name: connectUser ? connectUser.Name : localUser ? localUser.Name : null, + name: localUser ? localUser.Name : null, imageUrl: image.url, supportsImageParams: image.supportsParams, - connectUser: connectUser }); } @@ -641,16 +619,6 @@ define(["events", "apiclient", "appStorage"], function (events, apiClientFactory server.AccessToken = null; server.ExchangeToken = null; } - - credentials.Servers = servers; - credentials.ConnectAccessToken = null; - credentials.ConnectUserId = null; - credentialProvider.credentials(credentials); - - if (connectUser) { - connectUser = null; - events.trigger(self, "connectusersignedout"); - } }); }; @@ -692,12 +660,6 @@ define(["events", "apiclient", "appStorage"], function (events, apiClientFactory return result; }); } - - return Promise.resolve({ - Servers: servers, - State: servers.length || self.connectUser() ? "ServerSelection" : "ConnectSignIn", - ConnectUser: self.connectUser() - }); }; self.connectToServer = function (server, options) { @@ -734,7 +696,6 @@ define(["events", "apiclient", "appStorage"], function (events, apiClientFactory console.log("connectToAddress " + address + " failed"); return Promise.resolve({ State: "Unavailable", - ConnectUser: instance.connectUser() }); } From e7023dd51ab67a541fccfe0f1296ac07a40a043d Mon Sep 17 00:00:00 2001 From: grafixeyehero Date: Mon, 28 Oct 2019 20:37:39 +0300 Subject: [PATCH 101/162] Restore deleteServer --- .../apiclient/connectionmanager.js | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/src/bower_components/apiclient/connectionmanager.js b/src/bower_components/apiclient/connectionmanager.js index e0c40e19ba..553c11900d 100644 --- a/src/bower_components/apiclient/connectionmanager.js +++ b/src/bower_components/apiclient/connectionmanager.js @@ -711,6 +711,31 @@ define(["events", "apiclient", "appStorage"], function (events, apiClientFactory }; return self.connectToServer(server, options).catch(onFail); }; + + self.deleteServer = function (serverId) { + if (!serverId) { + throw new Error("null serverId"); + } + + var server = credentialProvider.credentials().Servers.filter(function (s) { + return s.Id === serverId; + }); + server = server.length ? server[0] : null; + return new Promise(function (resolve, reject) { + function onDone() { + var credentials = credentialProvider.credentials(); + credentials.Servers = credentials.Servers.filter(function (s) { + return s.Id !== serverId; + }); + credentialProvider.credentials(credentials); + resolve(); + } + + if (!server.ConnectServerId) { + return void onDone(); + } + }); + }; }; ConnectionManager.prototype.connect = function (options) { From ee0b3f9ce9c45d0d5dbe770c49e6d029ac3bb0a8 Mon Sep 17 00:00:00 2001 From: grafixeyehero Date: Mon, 28 Oct 2019 20:44:08 +0300 Subject: [PATCH 102/162] remove reaming connectuser --- src/bower_components/apiclient/connectionmanager.js | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/bower_components/apiclient/connectionmanager.js b/src/bower_components/apiclient/connectionmanager.js index 553c11900d..afd72e451e 100644 --- a/src/bower_components/apiclient/connectionmanager.js +++ b/src/bower_components/apiclient/connectionmanager.js @@ -523,10 +523,7 @@ define(["events", "apiclient", "appStorage"], function (events, apiClientFactory self.clearData = function () { console.log("connection manager clearing data"); - connectUser = null; var credentials = credentialProvider.credentials(); - credentials.ConnectAccessToken = null; - credentials.ConnectUserId = null; credentials.Servers = []; credentialProvider.credentials(credentials); }; @@ -589,7 +586,7 @@ define(["events", "apiclient", "appStorage"], function (events, apiClientFactory var localUser; var credentials = credentialProvider.credentials(); - if (!credentials.ConnectUserId || !credentials.ConnectAccessToken || apiClient && apiClient.getCurrentUserId()) { + if (apiClient && apiClient.getCurrentUserId()) { onEnsureConnectUserDone(); } }); From a9b439e458a9e2a960b1b81373f2901c0d91ee6f Mon Sep 17 00:00:00 2001 From: grafixeyehero Date: Mon, 28 Oct 2019 21:04:01 +0300 Subject: [PATCH 103/162] restore enableautologin condition --- .../apiclient/connectionmanager.js | 32 ++++++++++--------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/src/bower_components/apiclient/connectionmanager.js b/src/bower_components/apiclient/connectionmanager.js index afd72e451e..6b718d615e 100644 --- a/src/bower_components/apiclient/connectionmanager.js +++ b/src/bower_components/apiclient/connectionmanager.js @@ -402,7 +402,9 @@ define(["events", "apiclient", "appStorage"], function (events, apiClientFactory var credentials = credentialProvider.credentials(); options = options || {}; - afterConnectValidated(server, credentials, systemInfo, connectionMode, serverUrl, true, options, resolve); + if (false !== options.enableAutoLogin) { + afterConnectValidated(server, credentials, systemInfo, connectionMode, serverUrl, true, options, resolve); + } } function afterConnectValidated(server, credentials, systemInfo, connectionMode, serverUrl, verifyLocalAuthentication, options, resolve) { @@ -711,28 +713,28 @@ define(["events", "apiclient", "appStorage"], function (events, apiClientFactory self.deleteServer = function (serverId) { if (!serverId) { - throw new Error("null serverId"); + throw new Error("null serverId"); } var server = credentialProvider.credentials().Servers.filter(function (s) { - return s.Id === serverId; + return s.Id === serverId; }); server = server.length ? server[0] : null; return new Promise(function (resolve, reject) { - function onDone() { - var credentials = credentialProvider.credentials(); - credentials.Servers = credentials.Servers.filter(function (s) { - return s.Id !== serverId; - }); - credentialProvider.credentials(credentials); - resolve(); - } + function onDone() { + var credentials = credentialProvider.credentials(); + credentials.Servers = credentials.Servers.filter(function (s) { + return s.Id !== serverId; + }); + credentialProvider.credentials(credentials); + resolve(); + } - if (!server.ConnectServerId) { - return void onDone(); - } + if (!server.ConnectServerId) { + return void onDone(); + } }); - }; + }; }; ConnectionManager.prototype.connect = function (options) { From 365240e17a9bc0c8762b99300fccf6d16e47d14e Mon Sep 17 00:00:00 2001 From: grafixeyehero Date: Mon, 28 Oct 2019 21:35:49 +0300 Subject: [PATCH 104/162] Restore mergeServers condition --- src/bower_components/apiclient/connectionmanager.js | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/bower_components/apiclient/connectionmanager.js b/src/bower_components/apiclient/connectionmanager.js index 6b718d615e..95a819ea4c 100644 --- a/src/bower_components/apiclient/connectionmanager.js +++ b/src/bower_components/apiclient/connectionmanager.js @@ -37,6 +37,14 @@ define(["events", "apiclient", "appStorage"], function (events, apiClientFactory }); } + function mergeServers(credentialProvider, list1, list2) { + for (var i = 0, length = list2.length; i < length; i++) { + credentialProvider.addOrUpdateServer(list1, list2[i]); + } + + return list1; + } + function updateServerInfo(server, systemInfo) { server.Name = systemInfo.ServerName; if (systemInfo.Id) { @@ -636,6 +644,7 @@ define(["events", "apiclient", "appStorage"], function (events, apiClientFactory return Promise.all([findServers()]).then(function (responses) { var foundServers = responses[0]; var servers = credentials.Servers.slice(0); + mergeServers(credentialProvider, servers, foundServers); servers.sort(function (a, b) { return (b.DateLastAccessed || 0) - (a.DateLastAccessed || 0); }); From f6a8b8195905711d3135a0db0568a859b789790c Mon Sep 17 00:00:00 2001 From: grafixeyehero Date: Tue, 29 Oct 2019 00:29:28 +0300 Subject: [PATCH 105/162] merge onEnsureConnectUserDone method with onLocalUserDone --- .../apiclient/connectionmanager.js | 29 +++++++------------ 1 file changed, 10 insertions(+), 19 deletions(-) diff --git a/src/bower_components/apiclient/connectionmanager.js b/src/bower_components/apiclient/connectionmanager.js index 95a819ea4c..dcb8f28bc8 100644 --- a/src/bower_components/apiclient/connectionmanager.js +++ b/src/bower_components/apiclient/connectionmanager.js @@ -39,11 +39,11 @@ define(["events", "apiclient", "appStorage"], function (events, apiClientFactory function mergeServers(credentialProvider, list1, list2) { for (var i = 0, length = list2.length; i < length; i++) { - credentialProvider.addOrUpdateServer(list1, list2[i]); + credentialProvider.addOrUpdateServer(list1, list2[i]); } return list1; - } + } function updateServerInfo(server, systemInfo) { server.Name = systemInfo.ServerName; @@ -573,31 +573,22 @@ define(["events", "apiclient", "appStorage"], function (events, apiClientFactory self.user = function (apiClient) { return new Promise(function (resolve, reject) { function onLocalUserDone(e) { - var image = getImageUrl(localUser); - resolve({ - localUser: localUser, - name: localUser ? localUser.Name : null, - imageUrl: image.url, - supportsImageParams: image.supportsParams, - }); - } - - function onEnsureConnectUserDone() { if (apiClient && apiClient.getCurrentUserId()) { apiClient.getCurrentUser().then(function (u) { localUser = u; - onLocalUserDone(); + var image = getImageUrl(localUser); + resolve({ + localUser: localUser, + name: localUser ? localUser.Name : null, + imageUrl: image.url, + supportsImageParams: image.supportsParams, + }); }, onLocalUserDone); - } else { - onLocalUserDone(); } } - var localUser; - var credentials = credentialProvider.credentials(); - if (apiClient && apiClient.getCurrentUserId()) { - onEnsureConnectUserDone(); + onLocalUserDone(); } }); }; From 71c148fc01bd82808deeb916af44f98c1084a150 Mon Sep 17 00:00:00 2001 From: delfino434 Date: Thu, 31 Oct 2019 11:51:01 +0000 Subject: [PATCH 106/162] Translated using Weblate (Turkish) Translation: Jellyfin/Jellyfin Web Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-web/tr/ --- src/strings/tr.json | 118 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 117 insertions(+), 1 deletion(-) diff --git a/src/strings/tr.json b/src/strings/tr.json index e2dde03926..f517eb10e9 100644 --- a/src/strings/tr.json +++ b/src/strings/tr.json @@ -439,5 +439,121 @@ "EnableNextVideoInfoOverlay": "Oynatma sırasında bir sonraki video bilgisini göster", "EnablePhotosHelp": "Görüntüler diğer medya dosyalarıyla birlikte algılanacak ve gösterilecektir.", "EnableCinemaMode": "Sinema Modu", - "EnableColorCodedBackgrounds": "Renk kodlu arka planlar" + "EnableColorCodedBackgrounds": "Renk kodlu arka planlar", + "HeaderGuideProviders": "TV Rehberi Veri Sağlayıcıları", + "HeaderGenres": "Türler", + "HeaderForgotPassword": "Parolanızı mı unuttunuz", + "HeaderForKids": "Çocuklar için", + "HeaderFetcherSettings": "Alıcı Ayarları", + "HeaderFetchImages": "Görüntüleri Getir:", + "HeaderFeatures": "Özellikleri", + "HeaderFeatureAccess": "Özellik Erişimi", + "HeaderFavoriteVideos": "Favori Videolar", + "HeaderFavoriteMovies": "Favori Filmler", + "HeaderFavoriteBooks": "favori kitaplar", + "HeaderExternalIds": "Dış kimlikler:", + "HeaderError": "Hata", + "HeaderEpisodes": "Bölümler", + "HeaderEnabledFieldsHelp": "Kilitlemek ve verilerinin değişmesini önlemek için bir alanın işaretini kaldırın.", + "HeaderEnabledFields": "Etkin Alanlar", + "HeaderEditImages": "Görüntüleri Düzenle", + "HeaderDownloadSync": "İndir ve Eşitle", + "HeaderDisplay": "Görüntüle", + "HeaderDirectPlayProfileHelp": "Aygıtın yerel olarak hangi biçimlerde kullanılabileceğini göstermek için doğrudan oynatma profilleri ekleyin.", + "HeaderDirectPlayProfile": "Doğrudan Oyun Profili", + "HeaderDevices": "Cihazlar", + "HeaderDeveloperInfo": "Geliştirici Bilgisi", + "HeaderDetectMyDevices": "Cihazlarımı Algıla", + "HeaderDeleteTaskTrigger": "Görev Tetikleyicisini Sil", + "HeaderDeleteProvider": "Sağlayıcıyı Sil", + "HeaderDeleteItems": "Ürünleri sil", + "HeaderDeleteItem": "Öğeyi sil", + "HeaderDeleteDevice": "Cihazı Sil", + "HeaderDefaultRecordingSettings": "Varsayılan Kayıt Ayarları", + "HeaderDateIssued": "Çıkış Tarihi", + "HeaderContinueListening": "Dinlemeye Devam Et", + "HeaderContainerProfileHelp": "Konteyner profilleri, belirli formatları oynatırken cihazın sınırlamalarını gösterir. Bir sınırlama uygulanırsa, format doğrudan oynatma için yapılandırılmış olsa bile ortam kodlanır.", + "HeaderContainerProfile": "Konteyner Profili", + "HeaderConnectionFailure": "Bağlantı hatası", + "HeaderConnectToServer": "Sunucuya bağlan", + "HeaderConfirmRevokeApiKey": "API Anahtarını İptal Et", + "HeaderConfirmProfileDeletion": "Profil Silme İşlemini Onayla", + "HeaderConfirmPluginInstallation": "Eklenti Yüklemesini Onayla", + "HeaderConfigureRemoteAccess": "Uzaktan Erişimi Yapılandırma", + "HeaderCodecProfileHelp": "Codec profilleri, belirli kodlayıcıları oynatırken cihazın sınırlamalarını gösterir. Eğer bir sınırlama uygulanırsa, kodeğin doğrudan oynaması için yapılandırılmış olsa bile, ortam kodlanır.", + "HeaderChapterImages": "Bölüm Görüntüleri", + "HeaderChannelAccess": "Kanal erişimi", + "HeaderCastCrew": "Kast ekibi", + "HeaderCastAndCrew": "Kast ekibi", + "HeaderCancelSeries": "Serileri İptal Et", + "HeaderCancelRecording": "Kaydı İptal Et", + "HeaderBranding": "dağlama", + "HeaderBooks": "Kitaplar", + "HeaderBlockItemsWithNoRating": "Tanınmayan veya bilinmeyen derecelendirme bilgisine sahip öğeleri engelle:", + "HeaderAudioSettings": "Ses ayarları", + "HeaderAudioBooks": "Sesli Kitaplar", + "HeaderAppearsOn": "Görünür", + "HeaderApp": "Uygulama", + "HeaderApiKeysHelp": "Jellyfin Server ile iletişim kurabilmek için harici uygulamaların bir API anahtarına sahip olmaları gerekir. Anahtarlar bir Jellyfin hesabıyla giriş yaparak veya uygulamaya manuel olarak bir anahtar vererek verilir.", + "HeaderApiKeys": "API Anahtarları", + "HeaderApiKey": "API Anahtarı", + "HeaderAllowMediaDeletionFrom": "Medyadan Silinmeye İzin Ver", + "HeaderAlert": "Alarm", + "HeaderAlbums": "Albümler", + "HeaderAdmin": "Yönetici", + "HeaderAdditionalParts": "İlave parçalar", + "HeaderAddUpdateImage": "Resim Ekle / Güncelle", + "HeaderAddToPlaylist": "Oynatma listesine ekle", + "HeaderAddToCollection": "Koleksiyona ekle", + "HeaderAddScheduledTaskTrigger": "Tetikleyici ekle", + "HeaderActivity": "Aktivite", + "HeaderActiveDevices": "Aktif Cihazlar", + "HeaderAccessScheduleHelp": "Belirli saatlerle erişimi sınırlamak için bir erişim programı oluşturun.", + "HeaderAccessSchedule": "Erişim Takvimi", + "HardwareAccelerationWarning": "Donanım ivmesini etkinleştirmek bazı ortamlarda dengesizliğe neden olabilir. İşletim sisteminizin ve video sürücülerinizin tamamen güncel olduğundan emin olun. Bunu etkinleştirdikten sonra video oynatmakta zorluk çekiyorsanız, ayarı tekrar Auto (Otomatik) olarak değiştirmeniz gerekecektir.", + "HandledByProxy": "Ters proxy tarafından kullanılır", + "HDPrograms": "HD programlar", + "H264EncodingPresetHelp": "Performansı artırmak için daha hızlı bir değer veya kaliteyi artırmak için daha yavaş bir değer seçin.", + "H264CrfHelp": "Sabit Hız Faktörü (CRF), x264 kodlayıcı için varsayılan kalite ayarıdır. Değerleri 0 ile 51 arasında ayarlayabilirsiniz, burada daha düşük değerler daha iyi kaliteyle sonuçlanır (daha yüksek dosya boyutları pahasına). Aklı başında değerleri 18 ila 28 arasındadır. X264 için varsayılan 23, bu nedenle bunu başlangıç noktası olarak kullanabilirsiniz.", + "GuideProviderSelectListings": "İlan Seç", + "GuideProviderLogin": "Oturum aç", + "Guide": "Rehber", + "GuestStar": "Konuk sanatçı", + "GroupVersions": "Grup versiyonları", + "GroupBySeries": "Seriye göre gruplandır", + "GenresValue": "Türler: {0}", + "GenreValue": "Tür: {0}", + "General": "Genel", + "Fullscreen": "Tam ekran", + "FormatValue": "Biçim: {0}", + "FolderTypeUnset": "Karışık içerik", + "Filters": "Filtreler", + "File": "Dosya", + "FetchingData": "Ek veri alınıyor", + "Features": "Özellikleri", + "Favorite": "Favori", + "FastForward": "İleri sar", + "FFmpegSavePathNotFound": "Girdiğiniz yolu kullanarak FFmpeg'i bulamıyoruz. FFprobe da gereklidir ve aynı klasörde bulunmalıdır. Bu bileşenler normalde aynı indirmede birlikte paketlenmiştir. Lütfen yolu kontrol edip tekrar deneyin.", + "Extras": "Ekstralar", + "ExtractChapterImagesHelp": "Bölüm görüntülerini çıkarmak, müşterilerin grafiksel sahne seçim menülerini görüntülemesini sağlar. İşlem yavaş olabilir, kaynak yoğun olabilir ve birkaç gigabaytlık alan gerektirebilir. Videolar keşfedildiğinde ve ayrıca zamanlanmış bir görev olarak çalışır. Zamanlanmış, zamanlanmış görevler alanında yapılandırılabilir. Bu görevi yoğun kullanım saatlerinde yapmanız önerilmez.", + "ExtraLarge": "Ekstra büyük", + "ExitFullscreen": "Tam ekrandan çık", + "EveryNDays": "Her {0} günde", + "ErrorSavingTvProvider": "TV sağlayıcısını kaydederken bir hata oluştu. Lütfen erişilebilir olduğundan emin olun ve tekrar deneyin.", + "ErrorPleaseSelectLineup": "Lütfen bir grup seçin ve tekrar deneyin. Hiç bir sıralama yoksa, lütfen kullanıcı adınızın, şifrenizin ve posta kodunuzun doğru olup olmadığını kontrol edin.", + "ErrorMessageStartHourGreaterThanEnd": "Bitiş saati, başlangıç saatinden büyük olmalıdır.", + "ErrorGettingTvLineups": "TV dizilimini indirirken bir hata oluştu. Lütfen bilgilerinizin doğru olduğundan emin olun ve tekrar deneyin.", + "ErrorDeletingItem": "Öğe Jellyfin Sunucusundan silinirken bir hata oluştu. Lütfen Jellyfin Server'ın medya klasörüne yazma erişimi olup olmadığını kontrol edin ve tekrar deneyin.", + "ErrorAddingXmlTvFile": "XmlTV dosyasına erişilirken bir hata oluştu. Lütfen dosyanın var olduğundan emin olun ve tekrar deneyin.", + "ErrorAddingTunerDevice": "Tuner cihazı eklenirken bir hata oluştu. Lütfen erişilebilir olduğundan emin olun ve tekrar deneyin.", + "ErrorAddingMediaPathToVirtualFolder": "Medya yolu eklenirken bir hata oluştu. Lütfen yolun geçerli olduğundan ve Jellyfin Server işleminin o konuma erişebildiğinden emin olun.", + "ErrorAddingListingsToSchedulesDirect": "Dizilişi Schedules Direct hesabınıza eklerken bir hata oluştu. Schedules Direct, hesap başına yalnızca sınırlı sayıda kadroya izin verir. Devam etmeden önce Schedules Direct web sitesine giriş yapmanız ve başka girişleri hesabınızdan kaldırmanız gerekebilir.", + "Episodes": "Bölümler", + "EndsAtValue": "{0} konumundaki biter", + "EnableThemeVideosHelp": "Kitaplığa göz atarken tema videoları arka planda oynatın.", + "EnableThemeVideos": "Tema videoları", + "EnableThemeSongsHelp": "Kitaplığa göz atarken tema şarkıları arka planda çalın.", + "EnableThemeSongs": "Tema şarkıları", + "EnableStreamLoopingHelp": "Canlı akışlar yalnızca birkaç saniye veri içeriyorsa ve sürekli istenmesi gerekiyorsa bunu etkinleştirin. Gerekmediğinde bunu etkinleştirmek sorunlara neden olabilir.", + "EnableStreamLooping": "Otomatik döngü canlı akışları" } From 79266230f934d7f57f491b1e2900e84879a5393c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juhos=20Istv=C3=A1n?= Date: Fri, 1 Nov 2019 03:40:59 +0000 Subject: [PATCH 107/162] Translated using Weblate (Hungarian) Translation: Jellyfin/Jellyfin Web Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-web/hu/ --- src/strings/hu.json | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/strings/hu.json b/src/strings/hu.json index 1b5a307718..8d60f299e8 100644 --- a/src/strings/hu.json +++ b/src/strings/hu.json @@ -710,7 +710,7 @@ "HeaderActivity": "Tevékenység", "HeaderAdditionalParts": "További részek", "HeaderAdmin": "Adminisztrátor", - "HeaderAlbumArtists": "Album Előadók", + "HeaderAlbumArtists": "Album előadók", "HeaderAlert": "Figyelem", "HeaderAllowMediaDeletionFrom": "Média törlés engedélyezése", "HeaderApiKey": "API Kulcs", @@ -1300,7 +1300,7 @@ "MessageNoServersAvailable": "Az automatikus kiszolgálókeresés nem talált szervert.", "OptionLoginAttemptsBeforeLockout": "Meghatározza, hogy hány érvénytelen bejelentkezési kísérlet történhet zárolás előtt.", "TabNetworking": "Hálózat", - "HeaderFavoriteArtists": "Kedvenc Előadók", + "HeaderFavoriteArtists": "Kedvenc előadók", "SmallCaps": "Kiskapitális", "AllowOnTheFlySubtitleExtractionHelp": "A beágyazott feliratokat ki lehet távolítani a videókból és elküldeni a Jellyfin alkalmazásoknak sima szöveg formátumba, hogy ne legyen átkódolás. Néhány eszközön ez hosszú ideig is eltarthat, valamint a videó lejátszás megakadhat az eltávolítási folyamat futása közben. Ezt kikapcsolva a beágyazott feliratok videó átkódolással beégetésre kerülnek azon kliens eszközökre melyek nem támogatják a külső feliratokat.", "Art": "ClearArt", @@ -1321,10 +1321,10 @@ "HeaderContinueListening": "Folyamatban lévő zenék", "HeaderDeleteTaskTrigger": "Feladatvezérlő törlése", "HeaderFavoriteMovies": "Kedvenc Filmek", - "HeaderFavoriteShows": "Kedvenc Sorozatok", - "HeaderFavoriteEpisodes": "Kedvenc Epizódok", - "HeaderFavoriteAlbums": "Kedvenc Albumok", - "HeaderFavoriteSongs": "Kedvenc Dalok", + "HeaderFavoriteShows": "Kedvenc sorozatok", + "HeaderFavoriteEpisodes": "Kedvenc epizódok", + "HeaderFavoriteAlbums": "Kedvenc albumok", + "HeaderFavoriteSongs": "Kedvenc dalok", "HeaderFavoriteVideos": "Kedvenc Videók", "HeaderGuideProviders": "TV műsorújság Szolgáltatók", "HeaderHome": "Kezdőlap", From 643a7289b4bdd45a06278772d0a6dd1c52011af6 Mon Sep 17 00:00:00 2001 From: GigaFyde Date: Fri, 1 Nov 2019 15:21:08 +0000 Subject: [PATCH 108/162] Translated using Weblate (Dutch) Translation: Jellyfin/Jellyfin Web Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-web/nl/ --- src/strings/nl.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/strings/nl.json b/src/strings/nl.json index 9f31521cd5..38f529af9d 100644 --- a/src/strings/nl.json +++ b/src/strings/nl.json @@ -1327,5 +1327,6 @@ "LabelProfileVideoCodecs": "Video codecs:", "LabelProtocolInfo": "Protocol info:", "LabelServerName": "Server naam:", - "LabelSkin": "Skin:" + "LabelSkin": "Skin:", + "ButtonAddImage": "Voeg afbeelding toe" } From aecd2a5b27c6f2b0e14286dbe5716d7110b6c8de Mon Sep 17 00:00:00 2001 From: Dmitry Lyzo Date: Sat, 2 Nov 2019 23:35:44 +0300 Subject: [PATCH 109/162] Fix focus of library order item after change --- src/components/homescreensettings/homescreensettings.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/components/homescreensettings/homescreensettings.js b/src/components/homescreensettings/homescreensettings.js index e881edbdbd..633437d26e 100644 --- a/src/components/homescreensettings/homescreensettings.js +++ b/src/components/homescreensettings/homescreensettings.js @@ -330,6 +330,7 @@ define(['require', 'apphost', 'layoutManager', 'focusManager', 'globalize', 'loa if (next) { viewItem.parentNode.removeChild(viewItem); next.parentNode.insertBefore(viewItem, next.nextSibling); + focusManager.focus(e.target); } } else { @@ -339,6 +340,7 @@ define(['require', 'apphost', 'layoutManager', 'focusManager', 'globalize', 'loa if (prev) { viewItem.parentNode.removeChild(viewItem); prev.parentNode.insertBefore(viewItem, prev); + focusManager.focus(e.target); } } } From bdc6796184038d83d808d5d94f3779249ccfe5c5 Mon Sep 17 00:00:00 2001 From: Dmitry Lyzo Date: Thu, 10 Oct 2019 18:07:44 +0300 Subject: [PATCH 110/162] Added appropriate focuscontainer styles --- src/index.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/index.html b/src/index.html index bc9c7b64c5..d95784a3dc 100644 --- a/src/index.html +++ b/src/index.html @@ -98,8 +98,8 @@
-
-
+
+
From ef546edf892af8628e8ec5af558312325d046168 Mon Sep 17 00:00:00 2001 From: Aragon Date: Sat, 2 Nov 2019 16:38:53 +0000 Subject: [PATCH 111/162] Translated using Weblate (Hebrew) Translation: Jellyfin/Jellyfin Web Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-web/he/ --- src/strings/he.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/strings/he.json b/src/strings/he.json index bf17cc4e7f..9674439d78 100644 --- a/src/strings/he.json +++ b/src/strings/he.json @@ -509,5 +509,7 @@ "Writer": "כותב", "Albums": "אלבומים", "Artists": "אמנים", - "Books": "ספרים" + "Books": "ספרים", + "Absolute": "מוחלט", + "AccessRestrictedTryAgainLater": "הגישה כרגע מוגבלת. אנא נסה שוב מאוחר יותר." } From cf6c077b931d8afc07c8d564afaa0648f0acdc82 Mon Sep 17 00:00:00 2001 From: Aragon Date: Sun, 3 Nov 2019 12:41:08 +0000 Subject: [PATCH 112/162] Translated using Weblate (Hebrew) Translation: Jellyfin/Jellyfin Web Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-web/he/ --- src/strings/he.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/strings/he.json b/src/strings/he.json index 9674439d78..6add390ce3 100644 --- a/src/strings/he.json +++ b/src/strings/he.json @@ -511,5 +511,6 @@ "Artists": "אמנים", "Books": "ספרים", "Absolute": "מוחלט", - "AccessRestrictedTryAgainLater": "הגישה כרגע מוגבלת. אנא נסה שוב מאוחר יותר." + "AccessRestrictedTryAgainLater": "הגישה כרגע מוגבלת. אנא נסה שוב מאוחר יותר.", + "AddedOnValue": "נוסף {0}" } From 536e44c4957a9494fb27c02e51fd515990f06bc2 Mon Sep 17 00:00:00 2001 From: Anthony Lavado Date: Mon, 4 Nov 2019 02:34:52 -0500 Subject: [PATCH 113/162] Update stale.yml --- .github/stale.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/stale.yml b/.github/stale.yml index e478e25d21..e61e0ed476 100644 --- a/.github/stale.yml +++ b/.github/stale.yml @@ -8,6 +8,7 @@ exemptLabels: - future - feature - enhancement + - confirmed # Label to use when marking an issue as stale staleLabel: stale # Comment to post when marking an issue as stale. Set to `false` to disable From d3c3501632ba53ace26738896bdc219dc5bc5ab0 Mon Sep 17 00:00:00 2001 From: grafixeyehero Date: Tue, 5 Nov 2019 18:00:47 +0300 Subject: [PATCH 114/162] update Icon --- src/controllers/medialibrarypage.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/controllers/medialibrarypage.js b/src/controllers/medialibrarypage.js index 6b616ce58d..4da64641ef 100644 --- a/src/controllers/medialibrarypage.js +++ b/src/controllers/medialibrarypage.js @@ -88,27 +88,27 @@ define(["jQuery", "apphost", "scripts/taskbutton", "loading", "libraryMenu", "gl menuItems.push({ name: globalize.translate("ButtonEditImages"), id: "editimages", - ironIcon: "photo" + icon: "photo" }); menuItems.push({ name: globalize.translate("ManageLibrary"), id: "edit", - ironIcon: "folder_open" + icon: "folder_open" }); menuItems.push({ name: globalize.translate("ButtonRemove"), id: "delete", - ironIcon: "remove" + icon: "delete" }); menuItems.push({ name: globalize.translate("ButtonRename"), id: "rename", - ironIcon: "mode_edit" + icon: "mode_edit" }); menuItems.push({ name: globalize.translate("ScanLibrary"), id: "refresh", - ironIcon: "refresh" + icon: "refresh" }); require(["actionsheet"], function (actionsheet) { From faa1a263b9e9b803e6491f6d2360af8044d82a5a Mon Sep 17 00:00:00 2001 From: grafixeyehero Date: Tue, 5 Nov 2019 18:24:39 +0300 Subject: [PATCH 115/162] change ironicon to icon --- src/components/multiselect/multiselect.js | 10 +++++----- src/controllers/devices.js | 4 ++-- src/controllers/installedplugins.js | 4 ++-- src/controllers/userprofilespage.js | 10 +++++----- 4 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/components/multiselect/multiselect.js b/src/components/multiselect/multiselect.js index d706b76b99..b3fb2a7312 100644 --- a/src/components/multiselect/multiselect.js +++ b/src/components/multiselect/multiselect.js @@ -192,13 +192,13 @@ define(['browser', 'appStorage', 'apphost', 'loading', 'connectionManager', 'glo menuItems.push({ name: globalize.translate('AddToCollection'), id: 'addtocollection', - ironIcon: 'add' + icon: 'add' }); menuItems.push({ name: globalize.translate('AddToPlaylist'), id: 'playlist', - ironIcon: 'playlist-add' + icon: 'playlist_add' }); // TODO: Be more dynamic based on what is selected @@ -206,7 +206,7 @@ define(['browser', 'appStorage', 'apphost', 'loading', 'connectionManager', 'glo menuItems.push({ name: globalize.translate('Delete'), id: 'delete', - ironIcon: 'delete' + icon: 'delete' }); } @@ -214,7 +214,7 @@ define(['browser', 'appStorage', 'apphost', 'loading', 'connectionManager', 'glo menuItems.push({ name: Globalize.translate('ButtonDownload'), id: 'download', - ironIcon: 'file-download' + icon: 'file_download' }); } @@ -222,7 +222,7 @@ define(['browser', 'appStorage', 'apphost', 'loading', 'connectionManager', 'glo menuItems.push({ name: globalize.translate('GroupVersions'), id: 'groupvideos', - ironIcon: 'call-merge' + icon: 'call_merge' }); } diff --git a/src/controllers/devices.js b/src/controllers/devices.js index 94d7eb70ea..9048739f0f 100644 --- a/src/controllers/devices.js +++ b/src/controllers/devices.js @@ -31,11 +31,11 @@ define(["loading", "dom", "libraryMenu", "globalize", "scripts/imagehelper", "hu canEdit && menuItems.push({ name: globalize.translate("Edit"), id: "open", - ironIcon: "mode-edit" + icon: "mode_edit" }), canDelete(deviceId) && menuItems.push({ name: globalize.translate("Delete"), id: "delete", - ironIcon: "delete" + icon: "delete" }), require(["actionsheet"], function(actionsheet) { actionsheet.show({ items: menuItems, diff --git a/src/controllers/installedplugins.js b/src/controllers/installedplugins.js index f9653fe260..5127015e20 100644 --- a/src/controllers/installedplugins.js +++ b/src/controllers/installedplugins.js @@ -107,13 +107,13 @@ define(["loading", "libraryMenu", "dom", "globalize", "cardStyle", "emby-button" menuItems.push({ name: globalize.translate("ButtonSettings"), id: "open", - ironIcon: "mode-edit" + icon: "mode_edit" }); } menuItems.push({ name: globalize.translate("ButtonUninstall"), id: "delete", - ironIcon: "delete" + icon: "delete" }); require(["actionsheet"], function(actionsheet) { actionsheet.show({ diff --git a/src/controllers/userprofilespage.js b/src/controllers/userprofilespage.js index 3c22ff3cbf..0e9a79a8b2 100644 --- a/src/controllers/userprofilespage.js +++ b/src/controllers/userprofilespage.js @@ -27,22 +27,22 @@ define(["loading", "dom", "globalize", "humanedate", "paper-icon-button-light", menuItems.push({ name: globalize.translate("ButtonOpen"), id: "open", - ironIcon: "mode-edit" + icon: "mode_edit" }); menuItems.push({ name: globalize.translate("ButtonLibraryAccess"), id: "access", - ironIcon: "lock" + icon: "lock" }); menuItems.push({ name: globalize.translate("ButtonParentalControl"), id: "parentalcontrol", - ironIcon: "person" + icon: "person" }); menuItems.push({ name: globalize.translate("ButtonDelete"), id: "delete", - ironIcon: "delete" + icon: "delete" }); require(["actionsheet"], function (actionsheet) { @@ -149,7 +149,7 @@ define(["loading", "dom", "globalize", "humanedate", "paper-icon-button-light", menuItems.push({ name: globalize.translate("ButtonCancel"), id: "delete", - ironIcon: "delete" + icon: "delete" }); require(["actionsheet"], function (actionsheet) { From d536866ed5bd70d0e753fac8aa885db0e12b15ae Mon Sep 17 00:00:00 2001 From: grafixeyehero Date: Tue, 5 Nov 2019 18:43:10 +0300 Subject: [PATCH 116/162] update muliselect icon --- src/components/multiselect/multiselect.js | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/components/multiselect/multiselect.js b/src/components/multiselect/multiselect.js index b3fb2a7312..a614bfef8c 100644 --- a/src/components/multiselect/multiselect.js +++ b/src/components/multiselect/multiselect.js @@ -228,17 +228,20 @@ define(['browser', 'appStorage', 'apphost', 'loading', 'connectionManager', 'glo menuItems.push({ name: globalize.translate('MarkPlayed'), - id: 'markplayed' + id: 'markplayed', + icon: "check_box" }); menuItems.push({ name: globalize.translate('MarkUnplayed'), - id: 'markunplayed' + id: 'markunplayed', + icon: "check_box_outline_blank" }); menuItems.push({ name: globalize.translate('RefreshMetadata'), - id: 'refresh' + id: 'refresh', + icon: "refresh" }); From dd109c3324970681f5f5fbcb231a062ac0d960ae Mon Sep 17 00:00:00 2001 From: grafixeyehero Date: Tue, 5 Nov 2019 18:50:41 +0300 Subject: [PATCH 117/162] change single quote to double quote --- src/components/multiselect/multiselect.js | 194 +++++++++++----------- 1 file changed, 97 insertions(+), 97 deletions(-) diff --git a/src/components/multiselect/multiselect.js b/src/components/multiselect/multiselect.js index a614bfef8c..f4a0d2a29d 100644 --- a/src/components/multiselect/multiselect.js +++ b/src/components/multiselect/multiselect.js @@ -1,5 +1,5 @@ -define(['browser', 'appStorage', 'apphost', 'loading', 'connectionManager', 'globalize', 'appRouter', 'dom', 'css!./multiselect'], function (browser, appStorage, appHost, loading, connectionManager, globalize, appRouter, dom) { - 'use strict'; +define(["browser", "appStorage", "apphost", "loading", "connectionManager", "globalize", "appRouter", "dom", "css!./multiselect"], function (browser, appStorage, appHost, loading, connectionManager, globalize, appRouter, dom) { + "use strict"; var selectedItems = []; var selectedElements = []; @@ -15,12 +15,12 @@ define(['browser', 'appStorage', 'apphost', 'loading', 'connectionManager', 'glo selectedItems = []; selectedElements = []; - var elems = document.querySelectorAll('.itemSelectionPanel'); + var elems = document.querySelectorAll(".itemSelectionPanel"); for (var i = 0, length = elems.length; i < length; i++) { var parent = elems[i].parentNode; parent.removeChild(elems[i]); - parent.classList.remove('withMultiSelect'); + parent.classList.remove("withMultiSelect"); } } } @@ -28,13 +28,13 @@ define(['browser', 'appStorage', 'apphost', 'loading', 'connectionManager', 'glo function onItemSelectionPanelClick(e, itemSelectionPanel) { // toggle the checkbox, if it wasn't clicked on - if (!dom.parentWithClass(e.target, 'chkItemSelect')) { - var chkItemSelect = itemSelectionPanel.querySelector('.chkItemSelect'); + if (!dom.parentWithClass(e.target, "chkItemSelect")) { + var chkItemSelect = itemSelectionPanel.querySelector(".chkItemSelect"); if (chkItemSelect) { - if (chkItemSelect.classList.contains('checkedInitial')) { - chkItemSelect.classList.remove('checkedInitial'); + if (chkItemSelect.classList.contains("checkedInitial")) { + chkItemSelect.classList.remove("checkedInitial"); } else { var newValue = !chkItemSelect.checked; chkItemSelect.checked = newValue; @@ -50,7 +50,7 @@ define(['browser', 'appStorage', 'apphost', 'loading', 'connectionManager', 'glo function updateItemSelection(chkItemSelect, selected) { - var id = dom.parentWithAttribute(chkItemSelect, 'data-id').getAttribute('data-id'); + var id = dom.parentWithAttribute(chkItemSelect, "data-id").getAttribute("data-id"); if (selected) { @@ -73,7 +73,7 @@ define(['browser', 'appStorage', 'apphost', 'loading', 'connectionManager', 'glo } if (selectedItems.length) { - var itemSelectionCount = document.querySelector('.itemSelectionCount'); + var itemSelectionCount = document.querySelector(".itemSelectionCount"); if (itemSelectionCount) { itemSelectionCount.innerHTML = selectedItems.length; } @@ -88,27 +88,27 @@ define(['browser', 'appStorage', 'apphost', 'loading', 'connectionManager', 'glo function showSelection(item, isChecked) { - var itemSelectionPanel = item.querySelector('.itemSelectionPanel'); + var itemSelectionPanel = item.querySelector(".itemSelectionPanel"); if (!itemSelectionPanel) { - itemSelectionPanel = document.createElement('div'); - itemSelectionPanel.classList.add('itemSelectionPanel'); + itemSelectionPanel = document.createElement("div"); + itemSelectionPanel.classList.add("itemSelectionPanel"); - var parent = item.querySelector('.cardBox') || item.querySelector('.cardContent'); - parent.classList.add('withMultiSelect'); + var parent = item.querySelector(".cardBox") || item.querySelector(".cardContent"); + parent.classList.add("withMultiSelect"); parent.appendChild(itemSelectionPanel); - var cssClass = 'chkItemSelect'; + var cssClass = "chkItemSelect"; if (isChecked && !browser.firefox) { // In firefox, the initial tap hold doesnt' get treated as a click // In other browsers it does, so we need to make sure that initial click is ignored - cssClass += ' checkedInitial'; + cssClass += " checkedInitial"; } - var checkedAttribute = isChecked ? ' checked' : ''; + var checkedAttribute = isChecked ? " checked" : ""; itemSelectionPanel.innerHTML = ''; - var chkItemSelect = itemSelectionPanel.querySelector('.chkItemSelect'); - chkItemSelect.addEventListener('change', onSelectionChange); + var chkItemSelect = itemSelectionPanel.querySelector(".chkItemSelect"); + chkItemSelect.addEventListener("change", onSelectionChange); } } @@ -118,27 +118,27 @@ define(['browser', 'appStorage', 'apphost', 'loading', 'connectionManager', 'glo if (!selectionCommandsPanel) { - selectionCommandsPanel = document.createElement('div'); - selectionCommandsPanel.classList.add('selectionCommandsPanel'); + selectionCommandsPanel = document.createElement("div"); + selectionCommandsPanel.classList.add("selectionCommandsPanel"); document.body.appendChild(selectionCommandsPanel); currentSelectionCommandsPanel = selectionCommandsPanel; - var html = ''; + var html = ""; html += ''; html += '

'; - var moreIcon = ''; + var moreIcon = ""; html += ''; selectionCommandsPanel.innerHTML = html; - selectionCommandsPanel.querySelector('.btnCloseSelectionPanel').addEventListener('click', hideSelections); + selectionCommandsPanel.querySelector(".btnCloseSelectionPanel").addEventListener("click", hideSelections); - var btnSelectionPanelOptions = selectionCommandsPanel.querySelector('.btnSelectionPanelOptions'); + var btnSelectionPanelOptions = selectionCommandsPanel.querySelector(".btnSelectionPanelOptions"); - dom.addEventListener(btnSelectionPanelOptions, 'click', showMenuForSelectedItems, { passive: true }); + dom.addEventListener(btnSelectionPanelOptions, "click", showMenuForSelectedItems, { passive: true }); } } @@ -146,7 +146,7 @@ define(['browser', 'appStorage', 'apphost', 'loading', 'connectionManager', 'glo return new Promise(function (resolve, reject) { - require(['alert'], function (alert) { + require(["alert"], function (alert) { alert(options).then(resolve, resolve); }); }); @@ -156,15 +156,15 @@ define(['browser', 'appStorage', 'apphost', 'loading', 'connectionManager', 'glo return new Promise(function (resolve, reject) { - var msg = globalize.translate('ConfirmDeleteItem'); - var title = globalize.translate('HeaderDeleteItem'); + var msg = globalize.translate("ConfirmDeleteItem"); + var title = globalize.translate("HeaderDeleteItem"); if (itemIds.length > 1) { - msg = globalize.translate('ConfirmDeleteItems'); - title = globalize.translate('HeaderDeleteItems'); + msg = globalize.translate("ConfirmDeleteItems"); + title = globalize.translate("HeaderDeleteItems"); } - require(['confirm'], function (confirm) { + require(["confirm"], function (confirm) { confirm(msg, title).then(function () { var promises = itemIds.map(function (itemId) { @@ -173,7 +173,7 @@ define(['browser', 'appStorage', 'apphost', 'loading', 'connectionManager', 'glo Promise.all(promises).then(resolve, function () { - alertText(globalize.translate('ErrorDeletingItem')).then(reject, reject); + alertText(globalize.translate("ErrorDeletingItem")).then(reject, reject); }); }, reject); @@ -190,63 +190,63 @@ define(['browser', 'appStorage', 'apphost', 'loading', 'connectionManager', 'glo var menuItems = []; menuItems.push({ - name: globalize.translate('AddToCollection'), - id: 'addtocollection', - icon: 'add' + name: globalize.translate("AddToCollection"), + id: "addtocollection", + icon: "add" }); menuItems.push({ - name: globalize.translate('AddToPlaylist'), - id: 'playlist', - icon: 'playlist_add' + name: globalize.translate("AddToPlaylist"), + id: "playlist", + icon: "playlist_add" }); // TODO: Be more dynamic based on what is selected if (user.Policy.EnableContentDeletion) { menuItems.push({ - name: globalize.translate('Delete'), - id: 'delete', - icon: 'delete' + name: globalize.translate("Delete"), + id: "delete", + icon: "delete" }); } - if (user.Policy.EnableContentDownloading && appHost.supports('filedownload')) { + if (user.Policy.EnableContentDownloading && appHost.supports("filedownload")) { menuItems.push({ - name: Globalize.translate('ButtonDownload'), - id: 'download', - icon: 'file_download' + name: Globalize.translate("ButtonDownload"), + id: "download", + icon: "file_download" }); } if (user.Policy.IsAdministrator) { menuItems.push({ - name: globalize.translate('GroupVersions'), - id: 'groupvideos', - icon: 'call_merge' + name: globalize.translate("GroupVersions"), + id: "groupvideos", + icon: "call_merge" }); } menuItems.push({ - name: globalize.translate('MarkPlayed'), - id: 'markplayed', + name: globalize.translate("MarkPlayed"), + id: "markplayed", icon: "check_box" }); menuItems.push({ - name: globalize.translate('MarkUnplayed'), - id: 'markunplayed', + name: globalize.translate("MarkUnplayed"), + id: "markunplayed", icon: "check_box_outline_blank" }); menuItems.push({ - name: globalize.translate('RefreshMetadata'), - id: 'refresh', + name: globalize.translate("RefreshMetadata"), + id: "refresh", icon: "refresh" }); - require(['actionsheet'], function (actionsheet) { + require(["actionsheet"], function (actionsheet) { actionsheet.show({ items: menuItems, positionTo: e.target, @@ -255,8 +255,8 @@ define(['browser', 'appStorage', 'apphost', 'loading', 'connectionManager', 'glo var serverId = apiClient.serverInfo().Id; switch (id) { - case 'addtocollection': - require(['collectionEditor'], function (collectionEditor) { + case "addtocollection": + require(["collectionEditor"], function (collectionEditor) { new collectionEditor().show({ items: items, serverId: serverId @@ -265,8 +265,8 @@ define(['browser', 'appStorage', 'apphost', 'loading', 'connectionManager', 'glo hideSelections(); dispatchNeedsRefresh(); break; - case 'playlist': - require(['playlistEditor'], function (playlistEditor) { + case "playlist": + require(["playlistEditor"], function (playlistEditor) { new playlistEditor().show({ items: items, serverId: serverId @@ -275,30 +275,30 @@ define(['browser', 'appStorage', 'apphost', 'loading', 'connectionManager', 'glo hideSelections(); dispatchNeedsRefresh(); break; - case 'delete': + case "delete": deleteItems(apiClient, items).then(dispatchNeedsRefresh); hideSelections(); dispatchNeedsRefresh(); break; - case 'groupvideos': + case "groupvideos": combineVersions(apiClient, items); break; - case 'markplayed': + case "markplayed": items.forEach(function (itemId) { apiClient.markPlayed(apiClient.getCurrentUserId(), itemId); }); hideSelections(); dispatchNeedsRefresh(); break; - case 'markunplayed': + case "markunplayed": items.forEach(function (itemId) { apiClient.markUnplayed(apiClient.getCurrentUserId(), itemId); }); hideSelections(); dispatchNeedsRefresh(); break; - case 'refresh': - require(['refreshDialog'], function (refreshDialog) { + case "refresh": + require(["refreshDialog"], function (refreshDialog) { new refreshDialog({ itemIds: items, serverId: serverId @@ -323,7 +323,7 @@ define(['browser', 'appStorage', 'apphost', 'loading', 'connectionManager', 'glo [].forEach.call(selectedElements, function (i) { - var container = dom.parentWithAttribute(i, 'is', 'emby-itemscontainer'); + var container = dom.parentWithAttribute(i, "is", "emby-itemscontainer"); if (container && elems.indexOf(container) === -1) { elems.push(container); @@ -339,9 +339,9 @@ define(['browser', 'appStorage', 'apphost', 'loading', 'connectionManager', 'glo if (selection.length < 2) { - require(['alert'], function (alert) { + require(["alert"], function (alert) { alert({ - text: globalize.translate('PleaseSelectTwoItems') + text: globalize.translate("PleaseSelectTwoItems") }); }); return; @@ -352,7 +352,7 @@ define(['browser', 'appStorage', 'apphost', 'loading', 'connectionManager', 'glo apiClient.ajax({ type: "POST", - url: apiClient.getUrl("Videos/MergeVersions", { Ids: selection.join(',') }) + url: apiClient.getUrl("Videos/MergeVersions", { Ids: selection.join(",") }) }).then(function () { @@ -364,8 +364,8 @@ define(['browser', 'appStorage', 'apphost', 'loading', 'connectionManager', 'glo function showSelections(initialCard) { - require(['emby-checkbox'], function () { - var cards = document.querySelectorAll('.card'); + require(["emby-checkbox"], function () { + var cards = document.querySelectorAll(".card"); for (var i = 0, length = cards.length; i < length; i++) { showSelection(cards[i], initialCard === cards[i]); } @@ -381,9 +381,9 @@ define(['browser', 'appStorage', 'apphost', 'loading', 'connectionManager', 'glo if (selectedItems.length) { - var card = dom.parentWithClass(target, 'card'); + var card = dom.parentWithClass(target, "card"); if (card) { - var itemSelectionPanel = card.querySelector('.itemSelectionPanel'); + var itemSelectionPanel = card.querySelector(".itemSelectionPanel"); if (itemSelectionPanel) { return onItemSelectionPanelClick(e, itemSelectionPanel); } @@ -395,7 +395,7 @@ define(['browser', 'appStorage', 'apphost', 'loading', 'connectionManager', 'glo } } - document.addEventListener('viewbeforehide', hideSelections); + document.addEventListener("viewbeforehide", hideSelections); return function (options) { @@ -405,7 +405,7 @@ define(['browser', 'appStorage', 'apphost', 'loading', 'connectionManager', 'glo function onTapHold(e) { - var card = dom.parentWithClass(e.target, 'card'); + var card = dom.parentWithClass(e.target, "card"); if (card) { @@ -442,7 +442,7 @@ define(['browser', 'appStorage', 'apphost', 'loading', 'connectionManager', 'glo var element = touch.target; if (element) { - var card = dom.parentWithClass(element, 'card'); + var card = dom.parentWithClass(element, "card"); if (card) { @@ -511,7 +511,7 @@ define(['browser', 'appStorage', 'apphost', 'loading', 'connectionManager', 'glo return; } - var card = dom.parentWithClass(touchTarget, 'card'); + var card = dom.parentWithClass(touchTarget, "card"); touchTarget = null; if (card) { @@ -524,27 +524,27 @@ define(['browser', 'appStorage', 'apphost', 'loading', 'connectionManager', 'glo // mobile safari doesn't allow contextmenu override if (browser.touch && !browser.safari) { - element.addEventListener('contextmenu', onTapHold); + element.addEventListener("contextmenu", onTapHold); } else { - dom.addEventListener(element, 'touchstart', onTouchStart, { + dom.addEventListener(element, "touchstart", onTouchStart, { passive: true }); - dom.addEventListener(element, 'touchmove', onTouchMove, { + dom.addEventListener(element, "touchmove", onTouchMove, { passive: true }); - dom.addEventListener(element, 'touchend', onTouchEnd, { + dom.addEventListener(element, "touchend", onTouchEnd, { passive: true }); - dom.addEventListener(element, 'touchcancel', onTouchEnd, { + dom.addEventListener(element, "touchcancel", onTouchEnd, { passive: true }); - dom.addEventListener(element, 'mousedown', onMouseDown, { + dom.addEventListener(element, "mousedown", onMouseDown, { passive: true }); - dom.addEventListener(element, 'mouseleave', onMouseOut, { + dom.addEventListener(element, "mouseleave", onMouseOut, { passive: true }); - dom.addEventListener(element, 'mouseup', onMouseOut, { + dom.addEventListener(element, "mouseup", onMouseOut, { passive: true }); } @@ -553,38 +553,38 @@ define(['browser', 'appStorage', 'apphost', 'loading', 'connectionManager', 'glo initTapHold(container); if (options.bindOnClick !== false) { - container.addEventListener('click', onContainerClick); + container.addEventListener("click", onContainerClick); } self.onContainerClick = onContainerClick; self.destroy = function () { - container.removeEventListener('click', onContainerClick); - container.removeEventListener('contextmenu', onTapHold); + container.removeEventListener("click", onContainerClick); + container.removeEventListener("contextmenu", onTapHold); var element = container; - dom.removeEventListener(element, 'touchstart', onTouchStart, { + dom.removeEventListener(element, "touchstart", onTouchStart, { passive: true }); - dom.removeEventListener(element, 'touchmove', onTouchMove, { + dom.removeEventListener(element, "touchmove", onTouchMove, { passive: true }); - dom.removeEventListener(element, 'touchend', onTouchEnd, { + dom.removeEventListener(element, "touchend", onTouchEnd, { passive: true }); // this fires in safari due to magnifying class - //dom.removeEventListener(element, 'touchcancel', onTouchEnd, { + //dom.removeEventListener(element, "touchcancel", onTouchEnd, { // passive: true //}); - dom.removeEventListener(element, 'mousedown', onMouseDown, { + dom.removeEventListener(element, "mousedown", onMouseDown, { passive: true }); - dom.removeEventListener(element, 'mouseleave', onMouseOut, { + dom.removeEventListener(element, "mouseleave", onMouseOut, { passive: true }); - dom.removeEventListener(element, 'mouseup', onMouseOut, { + dom.removeEventListener(element, "mouseup", onMouseOut, { passive: true }); }; From 23677db99011b84f6da92e11e4afd2e468d7e833 Mon Sep 17 00:00:00 2001 From: grafixeyehero <32230989+grafixeyehero@users.noreply.github.com> Date: Wed, 6 Nov 2019 13:43:39 +0300 Subject: [PATCH 118/162] Deminify part 2 (#509) This de-minifies and de-uglifies `controllers` subdirectory --- src/controllers/addpluginpage.js | 59 +- src/controllers/addserver.js | 2 +- src/controllers/apikeys.js | 64 +- src/controllers/dashboardpage.js | 70 +- src/controllers/device.js | 42 +- src/controllers/devices.js | 93 +- src/controllers/dlnaprofile.js | 74 +- src/controllers/dlnaprofiles.js | 84 +- src/controllers/dlnasettings.js | 58 +- src/controllers/edititemmetadata.js | 38 +- src/controllers/encodingsettings.js | 174 +- src/controllers/forgotpassword.js | 52 +- src/controllers/forgotpasswordpin.js | 32 +- src/controllers/home.js | 65 +- src/controllers/hometab.js | 83 +- src/controllers/installedplugins.js | 60 +- src/controllers/itemdetailpage.js | 2380 ++++++++++++------ src/controllers/list.js | 1146 +++++++-- src/controllers/livetv/livetvchannels.js | 122 +- src/controllers/livetv/livetvguide.js | 43 +- src/controllers/livetv/livetvrecordings.js | 115 +- src/controllers/livetv/livetvschedule.js | 133 +- src/controllers/livetv/livetvseriestimers.js | 52 +- src/controllers/livetv/livetvsuggested.js | 40 +- src/controllers/livetvguideprovider.js | 28 +- src/controllers/livetvsettings.js | 156 +- src/controllers/livetvstatus.js | 244 +- src/controllers/livetvtuner.js | 204 +- src/controllers/metadatanfo.js | 66 +- src/controllers/movies/moviecollections.js | 316 ++- src/controllers/movies/moviegenres.js | 267 +- src/controllers/movies/movies.js | 354 +-- src/controllers/movies/moviesrecommended.js | 358 ++- src/controllers/movies/movietrailers.js | 382 +-- src/controllers/music/musicalbums.js | 373 +-- src/controllers/music/musicartists.js | 298 ++- src/controllers/music/musicgenres.js | 171 +- src/controllers/music/musicplaylists.js | 93 +- src/controllers/music/musicrecommended.js | 345 ++- src/controllers/music/songs.js | 264 +- src/controllers/notificationsetting.js | 173 +- src/controllers/nowplayingpage.js | 31 +- src/controllers/playbackconfiguration.js | 35 +- src/controllers/scheduledtaskpage.js | 266 +- src/controllers/searchpage.js | 49 +- src/controllers/selectserver.js | 120 +- src/controllers/serveractivity.js | 41 +- src/controllers/shows/episodes.js | 326 ++- src/controllers/shows/tvgenres.js | 263 +- src/controllers/shows/tvlatest.js | 76 +- src/controllers/shows/tvrecommended.js | 296 ++- src/controllers/shows/tvshows.js | 403 +-- src/controllers/shows/tvstudios.js | 77 +- src/controllers/shows/tvupcoming.js | 149 +- src/controllers/streamingsettings.js | 52 +- src/controllers/user/display.js | 71 +- src/controllers/user/home.js | 68 +- src/controllers/user/menu.js | 6 +- src/controllers/user/playback.js | 68 +- src/controllers/user/subtitles.js | 68 +- src/controllers/useredit.js | 148 +- src/controllers/userlibraryaccess.js | 198 +- src/controllers/usernew.js | 49 +- src/controllers/userparentalcontrol.js | 290 ++- src/controllers/userpasswordpage.js | 198 +- src/controllers/wizardfinishpage.js | 2 +- 66 files changed, 8296 insertions(+), 4227 deletions(-) diff --git a/src/controllers/addpluginpage.js b/src/controllers/addpluginpage.js index 0ecb65ab75..7930d6927b 100644 --- a/src/controllers/addpluginpage.js +++ b/src/controllers/addpluginpage.js @@ -1,31 +1,37 @@ -define(["jQuery", "loading", "libraryMenu", "globalize", "connectionManager", "emby-button"], function($, loading, libraryMenu, globalize, connectionManager) { +define(["jQuery", "loading", "libraryMenu", "globalize", "connectionManager", "emby-button"], function ($, loading, libraryMenu, globalize, connectionManager) { "use strict"; function populateHistory(packageInfo, page) { var html = ""; var length = Math.min(packageInfo.versions.length, 10); + for (var i = 0; i < length; i++) { var version = packageInfo.versions[i]; html += '

' + version.versionStr + " (" + version.classification + ")

"; html += '
' + version.description + "
"; } + $("#revisionHistory", page).html(html); } function populateVersions(packageInfo, page, installedPlugin) { var html = ""; + for (var i = 0; i < packageInfo.versions.length; i++) { var version = packageInfo.versions[i]; html += '"; } + var selectmenu = $("#selectVersion", page).html(html); + if (!installedPlugin) { $("#pCurrentVersion", page).hide().html(""); } - var packageVersion = packageInfo.versions.filter(function(current) { + + var packageVersion = packageInfo.versions.filter(function (current) { return "Release" == current.classification; })[0]; - packageVersion = packageVersion || packageInfo.versions.filter(function(current) { + packageVersion = packageVersion || packageInfo.versions.filter(function (current) { return "Beta" == current.classification; })[0]; @@ -36,12 +42,13 @@ define(["jQuery", "loading", "libraryMenu", "globalize", "connectionManager", "e } function renderPackage(pkg, installedPlugins, page) { - var installedPlugin = installedPlugins.filter(function(ip) { - return ip.Name == pkg.name + var installedPlugin = installedPlugins.filter(function (ip) { + return ip.Name == pkg.name; })[0]; populateVersions(pkg, page, installedPlugin); populateHistory(pkg, page); $(".pluginName", page).html(pkg.name); + if ("Server" == pkg.targetSystem) { $("#btnInstallDiv", page).removeClass("hide"); $("#nonServerMsg", page).hide(); @@ -52,60 +59,69 @@ define(["jQuery", "loading", "libraryMenu", "globalize", "connectionManager", "e var msg = globalize.translate("MessageInstallPluginFromApp"); $("#nonServerMsg", page).html(msg).show(); } + if (pkg.shortDescription) { $("#tagline", page).show().html(pkg.shortDescription); } else { $("#tagline", page).hide(); } + $("#overview", page).html(pkg.overview || ""); $("#developer", page).html(pkg.owner); + if (pkg.richDescUrl) { $("#pViewWebsite", page).show(); $("#pViewWebsite a", page).attr("href", pkg.richDescUrl); } else { $("#pViewWebsite", page).hide(); } + if (pkg.previewImage || pkg.thumbImage) { var img = pkg.previewImage ? pkg.previewImage : pkg.thumbImage; $("#pPreviewImage", page).show().html(""); } else { $("#pPreviewImage", page).hide().html(""); } + if (installedPlugin) { var currentVersionText = globalize.translate("MessageYouHaveVersionInstalled").replace("{0}", "" + installedPlugin.Version + ""); $("#pCurrentVersion", page).show().html(currentVersionText); } else { $("#pCurrentVersion", page).hide().html(""); } + loading.hide(); } function alertText(options) { - require(["alert"], function(alert) { - alert(options) - }) + require(["alert"], function (alert) { + alert(options); + }); } function performInstallation(page, packageName, guid, updateClass, version) { var developer = $("#developer", page).html().toLowerCase(); - var alertCallback = function() { + + var alertCallback = function () { loading.show(); page.querySelector("#btnInstall").disabled = true; - ApiClient.installPlugin(packageName, guid, updateClass, version).then(function() { + ApiClient.installPlugin(packageName, guid, updateClass, version).then(function () { loading.hide(); alertText(globalize.translate("PluginInstalledMessage")); }); }; + if (developer !== 'jellyfin') { loading.hide(); var msg = globalize.translate("MessagePluginInstallDisclaimer"); msg += "
"; msg += "
"; msg += globalize.translate("PleaseConfirmPluginInstallation"); - require(["confirm"], function(confirm) { - confirm(msg, globalize.translate("HeaderConfirmPluginInstallation")).then(function() { + + require(["confirm"], function (confirm) { + confirm(msg, globalize.translate("HeaderConfirmPluginInstallation")).then(function () { alertCallback(); - }, function() { + }, function () { console.log('plugin not installed'); }); }); @@ -114,18 +130,19 @@ define(["jQuery", "loading", "libraryMenu", "globalize", "connectionManager", "e } } - return function(view, params) { - $(".addPluginForm", view).on("submit", function() { + return function (view, params) { + $(".addPluginForm", view).on("submit", function () { loading.show(); var page = $(this).parents("#addPluginPage")[0]; var name = params.name; var guid = params.guid; - ApiClient.getInstalledPlugins().then(function(plugins) { - var installedPlugin = plugins.filter(function(plugin) { + ApiClient.getInstalledPlugins().then(function (plugins) { + var installedPlugin = plugins.filter(function (plugin) { return plugin.Name == name; })[0]; var vals = $("#selectVersion", page).val().split("|"); var version = vals[0]; + if (installedPlugin) { if (installedPlugin.Version === version) { loading.hide(); @@ -140,16 +157,16 @@ define(["jQuery", "loading", "libraryMenu", "globalize", "connectionManager", "e }); return false; }); - view.addEventListener("viewshow", function() { + view.addEventListener("viewshow", function () { var page = this; loading.show(); var name = params.name; var guid = params.guid; var promise1 = ApiClient.getPackageInfo(name, guid); var promise2 = ApiClient.getInstalledPlugins(); - Promise.all([promise1, promise2]).then(function(responses) { + Promise.all([promise1, promise2]).then(function (responses) { renderPackage(responses[0], responses[1], page); }); - }) - } + }); + }; }); diff --git a/src/controllers/addserver.js b/src/controllers/addserver.js index 6d596632b2..55b670f546 100644 --- a/src/controllers/addserver.js +++ b/src/controllers/addserver.js @@ -57,5 +57,5 @@ define(["appSettings", "loading", "browser", "emby-button"], function(appSetting appRouter.back(); }); } - } + }; }); diff --git a/src/controllers/apikeys.js b/src/controllers/apikeys.js index 3315e304e3..448ffa29a7 100644 --- a/src/controllers/apikeys.js +++ b/src/controllers/apikeys.js @@ -1,14 +1,14 @@ -define(["datetime", "loading", "libraryMenu", "dom", "globalize", "emby-button"], function(datetime, loading, libraryMenu, dom, globalize) { +define(["datetime", "loading", "libraryMenu", "dom", "globalize", "emby-button"], function (datetime, loading, libraryMenu, dom, globalize) { "use strict"; function revoke(page, key) { - require(["confirm"], function(confirm) { - confirm(globalize.translate("MessageConfirmRevokeApiKey"), globalize.translate("HeaderConfirmRevokeApiKey")).then(function() { + require(["confirm"], function (confirm) { + confirm(globalize.translate("MessageConfirmRevokeApiKey"), globalize.translate("HeaderConfirmRevokeApiKey")).then(function () { loading.show(); ApiClient.ajax({ type: "DELETE", url: ApiClient.getUrl("Auth/Keys/" + key) - }).then(function() { + }).then(function () { loadData(page); }); }); @@ -16,11 +16,23 @@ define(["datetime", "loading", "libraryMenu", "dom", "globalize", "emby-button"] } function renderKeys(page, keys) { - var rows = keys.map(function(item) { + var rows = keys.map(function (item) { var html = ""; - html += '', html += '', html += '", html += "", html += '', html += item.AccessToken, html += "", html += '', html += item.AppName || "", html += "", html += ''; - var date = datetime.parseISO8601Date(item.DateCreated, !0); - return html += datetime.toLocaleDateString(date) + " " + datetime.getDisplayTime(date), html += "", html += "" + html += ''; + html += ''; + html += '"; + html += ""; + html += ''; + html += item.AccessToken; + html += ""; + html += ''; + html += item.AppName || ""; + html += ""; + html += ''; + var date = datetime.parseISO8601Date(item.DateCreated, true); + html += datetime.toLocaleDateString(date) + " " + datetime.getDisplayTime(date); + html += ""; + return html += ""; }).join(""); page.querySelector(".resultBody").innerHTML = rows; loading.hide(); @@ -28,42 +40,44 @@ define(["datetime", "loading", "libraryMenu", "dom", "globalize", "emby-button"] function loadData(page) { loading.show(); - ApiClient.getJSON(ApiClient.getUrl("Auth/Keys")).then(function(result) { + ApiClient.getJSON(ApiClient.getUrl("Auth/Keys")).then(function (result) { renderKeys(page, result.Items); }); } function showNewKeyPrompt(page) { - require(["prompt"], function(prompt) { + require(["prompt"], function (prompt) { prompt({ title: globalize.translate("HeaderNewApiKey"), label: globalize.translate("LabelAppName"), description: globalize.translate("LabelAppNameExample") - }).then(function(value) { + }).then(function (value) { ApiClient.ajax({ type: "POST", url: ApiClient.getUrl("Auth/Keys", { App: value }) - }).then(function() { - loadData(page) - }) - }) - }) + }).then(function () { + loadData(page); + }); + }); + }); } - pageIdOn("pageinit", "apiKeysPage", function() { + pageIdOn("pageinit", "apiKeysPage", function () { var page = this; - page.querySelector(".btnNewKey").addEventListener("click", function() { - showNewKeyPrompt(page) + page.querySelector(".btnNewKey").addEventListener("click", function () { + showNewKeyPrompt(page); }); - page.querySelector(".tblApiKeys").addEventListener("click", function(e) { + page.querySelector(".tblApiKeys").addEventListener("click", function (e) { var btnRevoke = dom.parentWithClass(e.target, "btnRevoke"); - btnRevoke && revoke(page, btnRevoke.getAttribute("data-token")) + + if (btnRevoke) { + revoke(page, btnRevoke.getAttribute("data-token")); + } }); }); - - pageIdOn("pagebeforeshow", "apiKeysPage", function() { + pageIdOn("pagebeforeshow", "apiKeysPage", function () { loadData(this); - }) -}); \ No newline at end of file + }); +}); diff --git a/src/controllers/dashboardpage.js b/src/controllers/dashboardpage.js index 229befdeda..de86ffc2bd 100644 --- a/src/controllers/dashboardpage.js +++ b/src/controllers/dashboardpage.js @@ -5,8 +5,8 @@ define(["datetime", "events", "itemHelper", "serverNotifications", "dom", "globa require(["alert"], function (alert) { var title; var text = []; - var displayPlayMethod = playMethodHelper.getDisplayPlayMethod(session); + if (displayPlayMethod === "DirectStream") { title = globalize.translate("DirectStreaming"); text.push(globalize.translate("DirectStreamHelp1")); @@ -15,6 +15,7 @@ define(["datetime", "events", "itemHelper", "serverNotifications", "dom", "globa } else if (displayPlayMethod === "Transcode") { title = globalize.translate("Transcoding"); text.push(globalize.translate("MediaIsBeingConverted")); + if (session.TranscodingInfo && session.TranscodingInfo.TranscodeReasons && session.TranscodingInfo.TranscodeReasons.length) { text.push("
"); text.push(globalize.translate("LabelReasonForTranscoding")); @@ -23,6 +24,7 @@ define(["datetime", "events", "itemHelper", "serverNotifications", "dom", "globa }); } } + alert({ text: text.join("
"), title: title @@ -73,6 +75,7 @@ define(["datetime", "events", "itemHelper", "serverNotifications", "dom", "globa case "sendmessage": showSendMessageForm(btn, session); break; + case "transcodinginfo": showPlaybackInfo(btn, session); } @@ -124,6 +127,7 @@ define(["datetime", "events", "itemHelper", "serverNotifications", "dom", "globa list.push(session); } } + return list; } @@ -139,7 +143,7 @@ define(["datetime", "events", "itemHelper", "serverNotifications", "dom", "globa if (!result.Items.length) { view.querySelector(".activeRecordingsSection").classList.add("hide"); - return void (itemsContainer.innerHTML = ""); + return void(itemsContainer.innerHTML = ""); } view.querySelector(".activeRecordingsSection").classList.remove("hide"); @@ -165,13 +169,13 @@ define(["datetime", "events", "itemHelper", "serverNotifications", "dom", "globa function reloadSystemInfo(view, apiClient) { apiClient.getSystemInfo().then(function (systemInfo) { view.querySelector("#serverName").innerHTML = globalize.translate("DashboardServerName", systemInfo.ServerName); - var localizedVersion = globalize.translate("DashboardVersionNumber", systemInfo.Version); + if (systemInfo.SystemUpdateLevel !== "Release") { localizedVersion += " " + systemInfo.SystemUpdateLevel; } - view.querySelector("#versionNumber").innerHTML = localizedVersion; + view.querySelector("#versionNumber").innerHTML = localizedVersion; view.querySelector("#operatingSystem").innerHTML = globalize.translate("DashboardOperatingSystem", systemInfo.OperatingSystem); view.querySelector("#architecture").innerHTML = globalize.translate("DashboardArchitecture", systemInfo.SystemArchitecture); @@ -226,14 +230,13 @@ define(["datetime", "events", "itemHelper", "serverNotifications", "dom", "globa } else { var nowPlayingItem = session.NowPlayingItem; var className = "scalableCard card activeSession backdropCard backdropCard-scalable"; - html += '
'; html += '
'; html += '
'; html += '
'; html += '
'; - var imgUrl = DashboardPage.getNowPlayingImageUrl(nowPlayingItem); + if (imgUrl) { html += '
"; @@ -243,8 +246,8 @@ define(["datetime", "events", "itemHelper", "serverNotifications", "dom", "globa html += '
'; html += '
'; - var clientImage = DashboardPage.getClientImage(session); + if (clientImage) { html += clientImage; } @@ -261,28 +264,36 @@ define(["datetime", "events", "itemHelper", "serverNotifications", "dom", "globa html += '
'; } - html += '
' + html += '
'; var nowPlayingName = DashboardPage.getNowPlayingName(session); html += '
'; html += nowPlayingName.html; html += "
"; html += '
' + DashboardPage.getSessionNowPlayingTime(session) + "
"; - html += '
' + html += '
'; if (nowPlayingItem && nowPlayingItem.RunTimeTicks) { var percent = 100 * (session.PlayState.PositionTicks || 0) / nowPlayingItem.RunTimeTicks; - html += indicators.getProgressHtml(percent, { containerClass: "playbackProgress" }); + html += indicators.getProgressHtml(percent, { + containerClass: "playbackProgress" + }); } else { // need to leave the element in just in case the device starts playback - html += indicators.getProgressHtml(0, { containerClass: "playbackProgress hide" }); + html += indicators.getProgressHtml(0, { + containerClass: "playbackProgress hide" + }); } if (session.TranscodingInfo && session.TranscodingInfo.CompletionPercentage) { var percent = session.TranscodingInfo.CompletionPercentage.toFixed(1); - html += indicators.getProgressHtml(percent, { containerClass: "transcodingProgress" }); + html += indicators.getProgressHtml(percent, { + containerClass: "transcodingProgress" + }); } else { // same issue as playbackProgress element above - html += indicators.getProgressHtml(0, { containerClass: "transcodingProgress hide" }); + html += indicators.getProgressHtml(0, { + containerClass: "transcodingProgress hide" + }); } html += "
"; @@ -317,6 +328,7 @@ define(["datetime", "events", "itemHelper", "serverNotifications", "dom", "globa parentElement.insertAdjacentHTML("beforeend", html); var deadSessionElem = parentElement.querySelector(".deadSession"); + if (deadSessionElem) { deadSessionElem.parentNode.removeChild(deadSessionElem); } @@ -340,9 +352,9 @@ define(["datetime", "events", "itemHelper", "serverNotifications", "dom", "globa for (var i = 0, length = tasks.length; i < length; i++) { var task = tasks[i]; - html += "

"; html += task.Name + "
"; + if (task.State === "Running") { var progress = (task.CurrentProgressPercentage || 0).toFixed(1); html += ''; @@ -373,19 +385,24 @@ define(["datetime", "events", "itemHelper", "serverNotifications", "dom", "globa var html = ""; var showTranscodingInfo = false; var displayPlayMethod = playMethodHelper.getDisplayPlayMethod(session); + if (displayPlayMethod === "DirectStream") { html += globalize.translate("DirectStreaming"); } else if (displayPlayMethod === "Transcode") { html += globalize.translate("Transcoding"); + if (session.TranscodingInfo && session.TranscodingInfo.Framerate) { html += " (" + session.TranscodingInfo.Framerate + " fps)"; } + showTranscodingInfo = true; } else if (displayPlayMethod === "DirectPlay") { html += globalize.translate("DirectPlaying"); } + if (showTranscodingInfo) { var line = []; + if (session.TranscodingInfo) { if (session.TranscodingInfo.Bitrate) { if (session.TranscodingInfo.Bitrate > 1e6) { @@ -493,6 +510,7 @@ define(["datetime", "events", "itemHelper", "serverNotifications", "dom", "globa }, getUsersHtml: function (session) { var html = []; + if (session.UserId) { html.push(session.UserName); } @@ -516,8 +534,8 @@ define(["datetime", "events", "itemHelper", "serverNotifications", "dom", "globa }, updateSession: function (row, session) { row.classList.remove("deadSession"); - var nowPlayingItem = session.NowPlayingItem; + if (nowPlayingItem) { row.classList.add("playingSession"); } else { @@ -537,6 +555,7 @@ define(["datetime", "events", "itemHelper", "serverNotifications", "dom", "globa } var btnSessionPlayPause = row.querySelector(".btnSessionPlayPause"); + if (session.ServerId && nowPlayingItem && session.SupportsRemoteControl && session.DeviceId !== connectionManager.deviceId()) { btnSessionPlayPause.classList.remove("hide"); row.querySelector(".btnSessionStop").classList.remove("hide"); @@ -565,19 +584,29 @@ define(["datetime", "events", "itemHelper", "serverNotifications", "dom", "globa } var playbackProgressElem = row.querySelector(".playbackProgress"); + if (nowPlayingItem && nowPlayingItem.RunTimeTicks) { var percent = 100 * (session.PlayState.PositionTicks || 0) / nowPlayingItem.RunTimeTicks; - playbackProgressElem.outerHTML = indicators.getProgressHtml(percent, { containerClass: "playbackProgress" }); + playbackProgressElem.outerHTML = indicators.getProgressHtml(percent, { + containerClass: "playbackProgress" + }); } else { - playbackProgressElem.outerHTML = indicators.getProgressHtml(0, { containerClass: "playbackProgress hide" }); + playbackProgressElem.outerHTML = indicators.getProgressHtml(0, { + containerClass: "playbackProgress hide" + }); } var transcodingProgress = row.querySelector(".transcodingProgress"); + if (session.TranscodingInfo && session.TranscodingInfo.CompletionPercentage) { var percent = session.TranscodingInfo.CompletionPercentage.toFixed(1); - transcodingProgress.outerHTML = indicators.getProgressHtml(percent, { containerClass: "transcodingProgress" }); + transcodingProgress.outerHTML = indicators.getProgressHtml(percent, { + containerClass: "transcodingProgress" + }); } else { - transcodingProgress.outerHTML = indicators.getProgressHtml(0, { containerClass: "transcodingProgress hide" }); + transcodingProgress.outerHTML = indicators.getProgressHtml(0, { + containerClass: "transcodingProgress hide" + }); } var imgUrl = DashboardPage.getNowPlayingImageUrl(nowPlayingItem) || ""; @@ -815,10 +844,13 @@ define(["datetime", "events", "itemHelper", "serverNotifications", "dom", "globa view.addEventListener("viewdestroy", function () { var page = this; var userActivityLog = page.userActivityLog; + if (userActivityLog) { userActivityLog.destroy(); } + var serverActivityLog = page.serverActivityLog; + if (serverActivityLog) { serverActivityLog.destroy(); } diff --git a/src/controllers/device.js b/src/controllers/device.js index e704b964aa..cfe7efbe73 100644 --- a/src/controllers/device.js +++ b/src/controllers/device.js @@ -1,23 +1,25 @@ -define(["loading", "libraryMenu", "dom", "emby-input", "emby-button"], function(loading, libraryMenu, dom) { +define(["loading", "libraryMenu", "dom", "emby-input", "emby-button"], function (loading, libraryMenu, dom) { "use strict"; function load(page, device, deviceOptions) { - page.querySelector("#txtCustomName", page).value = deviceOptions.CustomName || "", page.querySelector(".reportedName", page).innerHTML = device.Name || "" + page.querySelector("#txtCustomName", page).value = deviceOptions.CustomName || ""; + page.querySelector(".reportedName", page).innerHTML = device.Name || ""; } function loadData() { var page = this; loading.show(); - var id = getParameterByName("id"), - promise1 = ApiClient.getJSON(ApiClient.getUrl("Devices/Info", { - Id: id - })), - promise2 = ApiClient.getJSON(ApiClient.getUrl("Devices/Options", { - Id: id - })); - Promise.all([promise1, promise2]).then(function(responses) { - load(page, responses[0], responses[1]), loading.hide() - }) + var id = getParameterByName("id"); + var promise1 = ApiClient.getJSON(ApiClient.getUrl("Devices/Info", { + Id: id + })); + var promise2 = ApiClient.getJSON(ApiClient.getUrl("Devices/Options", { + Id: id + })); + Promise.all([promise1, promise2]).then(function (responses) { + load(page, responses[0], responses[1]); + loading.hide(); + }); } function save(page) { @@ -31,14 +33,18 @@ define(["loading", "libraryMenu", "dom", "emby-input", "emby-button"], function( CustomName: page.querySelector("#txtCustomName").value }), contentType: "application/json" - }).then(Dashboard.processServerConfigurationUpdateResult) + }).then(Dashboard.processServerConfigurationUpdateResult); } function onSubmit(e) { var form = this; - return save(dom.parentWithClass(form, "page")), e.preventDefault(), !1 + save(dom.parentWithClass(form, "page")); + e.preventDefault(); + return false; } - return function(view, params) { - view.querySelector("form").addEventListener("submit", onSubmit), view.addEventListener("viewshow", loadData) - } -}); \ No newline at end of file + + return function (view, params) { + view.querySelector("form").addEventListener("submit", onSubmit); + view.addEventListener("viewshow", loadData); + }; +}); diff --git a/src/controllers/devices.js b/src/controllers/devices.js index 94d7eb70ea..36f2cf88a6 100644 --- a/src/controllers/devices.js +++ b/src/controllers/devices.js @@ -1,61 +1,73 @@ -define(["loading", "dom", "libraryMenu", "globalize", "scripts/imagehelper", "humanedate", "emby-button", "emby-itemscontainer", "cardStyle"], function(loading, dom, libraryMenu, globalize, imageHelper) { +define(["loading", "dom", "libraryMenu", "globalize", "scripts/imagehelper", "humanedate", "emby-button", "emby-itemscontainer", "cardStyle"], function (loading, dom, libraryMenu, globalize, imageHelper) { "use strict"; function canDelete(deviceId) { - return deviceId !== ApiClient.deviceId() + return deviceId !== ApiClient.deviceId(); } function deleteDevice(page, id) { var msg = globalize.translate("DeleteDeviceConfirmation"); - require(["confirm"], function(confirm) { + + require(["confirm"], function (confirm) { confirm({ text: msg, title: globalize.translate("HeaderDeleteDevice"), confirmText: globalize.translate("ButtonDelete"), primary: "delete" - }).then(function() { - loading.show(), ApiClient.ajax({ + }).then(function () { + loading.show(); + ApiClient.ajax({ type: "DELETE", url: ApiClient.getUrl("Devices", { Id: id }) - }).then(function() { - loadData(page) - }) - }) - }) + }).then(function () { + loadData(page); + }); + }); + }); } function showDeviceMenu(view, btn, deviceId) { var menuItems = []; - canEdit && menuItems.push({ - name: globalize.translate("Edit"), - id: "open", - ironIcon: "mode-edit" - }), canDelete(deviceId) && menuItems.push({ - name: globalize.translate("Delete"), - id: "delete", - ironIcon: "delete" - }), require(["actionsheet"], function(actionsheet) { + + if (canEdit) { + menuItems.push({ + name: globalize.translate("Edit"), + id: "open", + ironIcon: "mode-edit" + }); + } + + if (canDelete(deviceId)) { + menuItems.push({ + name: globalize.translate("Delete"), + id: "delete", + ironIcon: "delete" + }); + } + + require(["actionsheet"], function (actionsheet) { actionsheet.show({ items: menuItems, positionTo: btn, - callback: function(id) { + callback: function (id) { switch (id) { case "open": Dashboard.navigate("device.html?id=" + deviceId); break; + case "delete": - deleteDevice(view, deviceId) + deleteDevice(view, deviceId); } } - }) - }) + }); + }); } function load(page, devices) { var html = ""; - html += devices.map(function(device) { + html += devices.map(function (device) { var deviceHtml = ""; deviceHtml += "

"; deviceHtml += '
'; @@ -63,20 +75,24 @@ define(["loading", "dom", "libraryMenu", "globalize", "scripts/imagehelper", "hu deviceHtml += '
'; deviceHtml += ''; var iconUrl = imageHelper.getDeviceIcon(device.Name); + if (iconUrl) { deviceHtml += '
"; deviceHtml += "
"; } else { deviceHtml += 'tablet_android'; } + deviceHtml += "
"; deviceHtml += "
"; deviceHtml += '
'; + if (canEdit || canDelete(device.Id)) { deviceHtml += '
'; deviceHtml += ''; deviceHtml += "
"; } + deviceHtml += "
"; deviceHtml += device.Name; deviceHtml += "
"; @@ -84,10 +100,12 @@ define(["loading", "dom", "libraryMenu", "globalize", "scripts/imagehelper", "hu deviceHtml += device.AppName + " " + device.AppVersion; deviceHtml += "
"; deviceHtml += "
"; + if (device.LastUserName) { deviceHtml += device.LastUserName; deviceHtml += ", " + humaneDate(device.DateLastActivity); } + deviceHtml += " "; deviceHtml += "
"; deviceHtml += "
"; @@ -99,17 +117,24 @@ define(["loading", "dom", "libraryMenu", "globalize", "scripts/imagehelper", "hu } function loadData(page) { - loading.show(), ApiClient.getJSON(ApiClient.getUrl("Devices")).then(function(result) { - load(page, result.Items), loading.hide() - }) + loading.show(); + ApiClient.getJSON(ApiClient.getUrl("Devices")).then(function (result) { + load(page, result.Items); + loading.hide(); + }); } + var canEdit = ApiClient.isMinServerVersion("3.4.1.31"); - return function(view, params) { - view.querySelector(".devicesList").addEventListener("click", function(e) { + return function (view, params) { + view.querySelector(".devicesList").addEventListener("click", function (e) { var btnDeviceMenu = dom.parentWithClass(e.target, "btnDeviceMenu"); - btnDeviceMenu && showDeviceMenu(view, btnDeviceMenu, btnDeviceMenu.getAttribute("data-id")) - }), view.addEventListener("viewshow", function() { - loadData(this) - }) - } + + if (btnDeviceMenu) { + showDeviceMenu(view, btnDeviceMenu, btnDeviceMenu.getAttribute("data-id")); + } + }); + view.addEventListener("viewshow", function () { + loadData(this); + }); + }; }); diff --git a/src/controllers/dlnaprofile.js b/src/controllers/dlnaprofile.js index b4e320e6e4..e9239693d8 100644 --- a/src/controllers/dlnaprofile.js +++ b/src/controllers/dlnaprofile.js @@ -65,8 +65,8 @@ define(["jQuery", "loading", "fnchecked", "emby-select", "emby-button", "emby-in profile.ContainerProfiles = profile.ContainerProfiles || []; profile.CodecProfiles = profile.CodecProfiles || []; profile.ResponseProfiles = profile.ResponseProfiles || []; - var usersHtml = "" + users.map(function (u__w) { - return '"; + var usersHtml = "" + users.map(function (u) { + return '"; }).join(""); $("#selectUser", page).html(usersHtml).val(profile.UserId || ""); renderSubProfiles(page, profile); @@ -74,12 +74,12 @@ define(["jQuery", "loading", "fnchecked", "emby-select", "emby-button", "emby-in function renderIdentificationHeaders(page, headers) { var index = 0; - var html = '
' + headers.map(function (h__e) { + var html = '
' + headers.map(function (h) { var li = '
'; li += 'info'; li += '
'; - li += '

' + h__e.Name + ": " + (h__e.Value || "") + "

"; - li += '
' + (h__e.Match || "") + "
"; + li += '

' + h.Name + ": " + (h.Value || "") + "

"; + li += '
' + (h.Match || "") + "
"; li += "
"; li += ''; li += "
"; @@ -130,11 +130,11 @@ define(["jQuery", "loading", "fnchecked", "emby-select", "emby-button", "emby-in } function renderXmlDocumentAttributes(page, attribute) { - var html = '
' + attribute.map(function (h__r) { + var html = '
' + attribute.map(function (h) { var li = '
'; li += 'info'; li += '
'; - li += '

' + h__r.Name + " = " + (h__r.Value || "") + "

"; + li += '

' + h.Name + " = " + (h.Value || "") + "

"; li += "
"; li += ''; return li += "
"; @@ -172,11 +172,11 @@ define(["jQuery", "loading", "fnchecked", "emby-select", "emby-button", "emby-in function renderSubtitleProfiles(page, profiles) { var index = 0; - var html = '
' + profiles.map(function (h__t) { + var html = '
' + profiles.map(function (h) { var li = '
'; li += 'info'; li += '
'; - li += '

' + (h__t.Format || "") + "

"; + li += '

' + (h.Format || "") + "

"; li += "
"; li += ''; li += "
"; @@ -248,8 +248,8 @@ define(["jQuery", "loading", "fnchecked", "emby-select", "emby-button", "emby-in html += '
    '; var currentType; - for (var i__y = 0, length = profiles.length; i__y < length; i__y++) { - var profile = profiles[i__y]; + for (var i = 0, length = profiles.length; i < length; i++) { + var profile = profiles[i]; if (profile.Type !== currentType) { html += '
  • ' + profile.Type + "
  • "; @@ -257,7 +257,7 @@ define(["jQuery", "loading", "fnchecked", "emby-select", "emby-button", "emby-in } html += ""; } @@ -308,8 +308,8 @@ define(["jQuery", "loading", "fnchecked", "emby-select", "emby-button", "emby-in html += '
      '; var currentType; - for (var i__u = 0, length = profiles.length; i__u < length; i__u++) { - var profile = profiles[i__u]; + for (var i = 0, length = profiles.length; i < length; i++) { + var profile = profiles[i]; if (profile.Type !== currentType) { html += '
    • ' + profile.Type + "
    • "; @@ -317,7 +317,7 @@ define(["jQuery", "loading", "fnchecked", "emby-select", "emby-button", "emby-in } html += ""; } @@ -394,8 +394,8 @@ define(["jQuery", "loading", "fnchecked", "emby-select", "emby-button", "emby-in html += '
        '; var currentType; - for (var i__i = 0, length = profiles.length; i__i < length; i__i++) { - var profile = profiles[i__i]; + for (var i = 0, length = profiles.length; i < length; i++) { + var profile = profiles[i]; if (profile.Type !== currentType) { html += '
      • ' + profile.Type + "
      • "; @@ -403,19 +403,19 @@ define(["jQuery", "loading", "fnchecked", "emby-select", "emby-button", "emby-in } html += ""; } @@ -465,8 +465,8 @@ define(["jQuery", "loading", "fnchecked", "emby-select", "emby-button", "emby-in html += '
          '; var currentType; - for (var i__p = 0, length = profiles.length; i__p < length; i__p++) { - var profile = profiles[i__p]; + for (var i = 0, length = profiles.length; i < length; i++) { + var profile = profiles[i]; var type = profile.Type.replace("VideoAudio", "Video Audio"); if (type !== currentType) { @@ -475,19 +475,19 @@ define(["jQuery", "loading", "fnchecked", "emby-select", "emby-button", "emby-in } html += ""; } @@ -537,8 +537,8 @@ define(["jQuery", "loading", "fnchecked", "emby-select", "emby-button", "emby-in html += '
            '; var currentType; - for (var i__s = 0, length = profiles.length; i__s < length; i__s++) { - var profile = profiles[i__s]; + for (var i = 0, length = profiles.length; i < length; i++) { + var profile = profiles[i]; if (profile.Type !== currentType) { html += '
          • ' + profile.Type + "
          • "; @@ -546,7 +546,7 @@ define(["jQuery", "loading", "fnchecked", "emby-select", "emby-button", "emby-in } html += ""; } @@ -649,8 +649,8 @@ define(["jQuery", "loading", "fnchecked", "emby-select", "emby-button", "emby-in profile.Name = $("#txtName", page).val(); profile.EnableAlbumArtInDidl = $("#chkEnableAlbumArtInDidl", page).checked(); profile.EnableSingleAlbumArtLimit = $("#chkEnableSingleImageLimit", page).checked(); - profile.SupportedMediaTypes = $(".chkMediaType:checked", page).get().map(function (c__f) { - return c__f.getAttribute("data-value"); + profile.SupportedMediaTypes = $(".chkMediaType:checked", page).get().map(function (c) { + return c.getAttribute("data-value"); }).join(","); profile.Identification = profile.Identification || {}; profile.FriendlyName = $("#txtInfoFriendlyName", page).val(); diff --git a/src/controllers/dlnaprofiles.js b/src/controllers/dlnaprofiles.js index 95350120c5..ae708bcd4e 100644 --- a/src/controllers/dlnaprofiles.js +++ b/src/controllers/dlnaprofiles.js @@ -1,48 +1,75 @@ -define(["jQuery", "globalize", "loading", "libraryMenu", "listViewStyle", "emby-button"], function($, globalize, loading, libraryMenu) { +define(["jQuery", "globalize", "loading", "libraryMenu", "listViewStyle", "emby-button"], function ($, globalize, loading, libraryMenu) { "use strict"; function loadProfiles(page) { - loading.show(), ApiClient.getJSON(ApiClient.getUrl("Dlna/ProfileInfos")).then(function(result) { - renderUserProfiles(page, result), renderSystemProfiles(page, result), loading.hide() - }) + loading.show(); + ApiClient.getJSON(ApiClient.getUrl("Dlna/ProfileInfos")).then(function (result) { + renderUserProfiles(page, result); + renderSystemProfiles(page, result); + loading.hide(); + }); } function renderUserProfiles(page, profiles) { - renderProfiles(page, page.querySelector(".customProfiles"), profiles.filter(function(p) { - return "User" == p.Type - })) + renderProfiles(page, page.querySelector(".customProfiles"), profiles.filter(function (p) { + return "User" == p.Type; + })); } function renderSystemProfiles(page, profiles) { - renderProfiles(page, page.querySelector(".systemProfiles"), profiles.filter(function(p) { - return "System" == p.Type - })) + renderProfiles(page, page.querySelector(".systemProfiles"), profiles.filter(function (p) { + return "System" == p.Type; + })); } function renderProfiles(page, element, profiles) { var html = ""; - profiles.length && (html += '
            '); + + if (profiles.length) { + html += '
            '; + } + for (var i = 0, length = profiles.length; i < length; i++) { var profile = profiles[i]; - html += '
            ', html += 'live_tv', html += '", "User" == profile.Type && (html += ''), html += "
            " + html += '
            '; + html += 'live_tv'; + html += '"; + + if ("User" == profile.Type) { + html += ''; + } + + html += "
            "; } - profiles.length && (html += "
            "), element.innerHTML = html, $(".btnDeleteProfile", element).on("click", function() { + + if (profiles.length) { + html += "
            "; + } + + element.innerHTML = html; + $(".btnDeleteProfile", element).on("click", function () { var id = this.getAttribute("data-profileid"); - deleteProfile(page, id) - }) + deleteProfile(page, id); + }); } function deleteProfile(page, id) { - require(["confirm"], function(confirm) { - confirm(globalize.translate("MessageConfirmProfileDeletion"), globalize.translate("HeaderConfirmProfileDeletion")).then(function() { - loading.show(), ApiClient.ajax({ + require(["confirm"], function (confirm) { + confirm(globalize.translate("MessageConfirmProfileDeletion"), globalize.translate("HeaderConfirmProfileDeletion")).then(function () { + loading.show(); + ApiClient.ajax({ type: "DELETE", url: ApiClient.getUrl("Dlna/Profiles/" + id) - }).then(function() { - loading.hide(), loadProfiles(page) - }) - }) - }) + }).then(function () { + loading.hide(); + loadProfiles(page); + }); + }); + }); } function getTabs() { @@ -52,10 +79,11 @@ define(["jQuery", "globalize", "loading", "libraryMenu", "listViewStyle", "emby- }, { href: "dlnaprofiles.html", name: globalize.translate("TabProfiles") - }] + }]; } - $(document).on("pageshow", "#dlnaProfilesPage", function() { - libraryMenu.setTabs("dlna", 1, getTabs), loadProfiles(this) - }) -}); \ No newline at end of file + $(document).on("pageshow", "#dlnaProfilesPage", function () { + libraryMenu.setTabs("dlna", 1, getTabs); + loadProfiles(this); + }); +}); diff --git a/src/controllers/dlnasettings.js b/src/controllers/dlnasettings.js index cc4693096a..fbb3af1205 100644 --- a/src/controllers/dlnasettings.js +++ b/src/controllers/dlnasettings.js @@ -1,20 +1,34 @@ -define(["jQuery", "loading", "libraryMenu", "fnchecked"], function($, loading, libraryMenu) { +define(["jQuery", "loading", "libraryMenu", "fnchecked"], function ($, loading, libraryMenu) { "use strict"; function loadPage(page, config, users) { - page.querySelector("#chkEnablePlayTo").checked = config.EnablePlayTo, page.querySelector("#chkEnableDlnaDebugLogging").checked = config.EnableDebugLog, $("#txtClientDiscoveryInterval", page).val(config.ClientDiscoveryIntervalSeconds), $("#chkEnableServer", page).checked(config.EnableServer), $("#chkBlastAliveMessages", page).checked(config.BlastAliveMessages), $("#txtBlastInterval", page).val(config.BlastAliveMessageIntervalSeconds); - var usersHtml = users.map(function(u) { - return '" + page.querySelector("#chkEnablePlayTo").checked = config.EnablePlayTo; + page.querySelector("#chkEnableDlnaDebugLogging").checked = config.EnableDebugLog; + $("#txtClientDiscoveryInterval", page).val(config.ClientDiscoveryIntervalSeconds); + $("#chkEnableServer", page).checked(config.EnableServer); + $("#chkBlastAliveMessages", page).checked(config.BlastAliveMessages); + $("#txtBlastInterval", page).val(config.BlastAliveMessageIntervalSeconds); + var usersHtml = users.map(function (u) { + return '"; }).join(""); - $("#selectUser", page).html(usersHtml).val(config.DefaultUserId || ""), loading.hide() + $("#selectUser", page).html(usersHtml).val(config.DefaultUserId || ""); + loading.hide(); } function onSubmit() { loading.show(); var form = this; - return ApiClient.getNamedConfiguration("dlna").then(function(config) { - config.EnablePlayTo = form.querySelector("#chkEnablePlayTo").checked, config.EnableDebugLog = form.querySelector("#chkEnableDlnaDebugLogging").checked, config.ClientDiscoveryIntervalSeconds = $("#txtClientDiscoveryInterval", form).val(), config.EnableServer = $("#chkEnableServer", form).checked(), config.BlastAliveMessages = $("#chkBlastAliveMessages", form).checked(), config.BlastAliveMessageIntervalSeconds = $("#txtBlastInterval", form).val(), config.DefaultUserId = $("#selectUser", form).val(), ApiClient.updateNamedConfiguration("dlna", config).then(Dashboard.processServerConfigurationUpdateResult) - }), !1 + ApiClient.getNamedConfiguration("dlna").then(function (config) { + config.EnablePlayTo = form.querySelector("#chkEnablePlayTo").checked; + config.EnableDebugLog = form.querySelector("#chkEnableDlnaDebugLogging").checked; + config.ClientDiscoveryIntervalSeconds = $("#txtClientDiscoveryInterval", form).val(); + config.EnableServer = $("#chkEnableServer", form).checked(); + config.BlastAliveMessages = $("#chkBlastAliveMessages", form).checked(); + config.BlastAliveMessageIntervalSeconds = $("#txtBlastInterval", form).val(); + config.DefaultUserId = $("#selectUser", form).val(); + ApiClient.updateNamedConfiguration("dlna", config).then(Dashboard.processServerConfigurationUpdateResult); + }); + return false; } function getTabs() { @@ -24,17 +38,19 @@ define(["jQuery", "loading", "libraryMenu", "fnchecked"], function($, loading, l }, { href: "dlnaprofiles.html", name: Globalize.translate("TabProfiles") - }] + }]; } - $(document).on("pageinit", "#dlnaSettingsPage", function() { - $(".dlnaSettingsForm").off("submit", onSubmit).on("submit", onSubmit) - }).on("pageshow", "#dlnaSettingsPage", function() { - libraryMenu.setTabs("dlna", 0, getTabs), loading.show(); - var page = this, - promise1 = ApiClient.getNamedConfiguration("dlna"), - promise2 = ApiClient.getUsers(); - Promise.all([promise1, promise2]).then(function(responses) { - loadPage(page, responses[0], responses[1]) - }) - }) -}); \ No newline at end of file + + $(document).on("pageinit", "#dlnaSettingsPage", function () { + $(".dlnaSettingsForm").off("submit", onSubmit).on("submit", onSubmit); + }).on("pageshow", "#dlnaSettingsPage", function () { + libraryMenu.setTabs("dlna", 0, getTabs); + loading.show(); + var page = this; + var promise1 = ApiClient.getNamedConfiguration("dlna"); + var promise2 = ApiClient.getUsers(); + Promise.all([promise1, promise2]).then(function (responses) { + loadPage(page, responses[0], responses[1]); + }); + }); +}); diff --git a/src/controllers/edititemmetadata.js b/src/controllers/edititemmetadata.js index bb5e70695a..aba741d64c 100644 --- a/src/controllers/edititemmetadata.js +++ b/src/controllers/edititemmetadata.js @@ -1,17 +1,31 @@ -define(["loading", "scripts/editorsidebar"], function(loading) { +define(["loading", "scripts/editorsidebar"], function (loading) { "use strict"; function reload(context, itemId) { - loading.show(), itemId ? require(["metadataEditor"], function(metadataEditor) { - metadataEditor.embed(context.querySelector(".editPageInnerContent"), itemId, ApiClient.serverInfo().Id) - }) : (context.querySelector(".editPageInnerContent").innerHTML = "", loading.hide()) + loading.show(); + + if (itemId) { + require(["metadataEditor"], function (metadataEditor) { + metadataEditor.embed(context.querySelector(".editPageInnerContent"), itemId, ApiClient.serverInfo().Id); + }); + } else { + context.querySelector(".editPageInnerContent").innerHTML = ""; + loading.hide(); + } } - return function(view, params) { - view.addEventListener("viewshow", function() { - reload(this, MetadataEditor.getCurrentItemId()) - }), MetadataEditor.setCurrentItemId(null), view.querySelector(".libraryTree").addEventListener("itemclicked", function(event) { + + return function (view, params) { + view.addEventListener("viewshow", function () { + reload(this, MetadataEditor.getCurrentItemId()); + }); + MetadataEditor.setCurrentItemId(null); + view.querySelector(".libraryTree").addEventListener("itemclicked", function (event) { var data = event.detail; - data.id != MetadataEditor.getCurrentItemId() && (MetadataEditor.setCurrentItemId(data.id), reload(view, data.id)) - }) - } -}); \ No newline at end of file + + if (data.id != MetadataEditor.getCurrentItemId()) { + MetadataEditor.setCurrentItemId(data.id); + reload(view, data.id); + } + }); + }; +}); diff --git a/src/controllers/encodingsettings.js b/src/controllers/encodingsettings.js index 0319d59a79..f3dfd2706e 100644 --- a/src/controllers/encodingsettings.js +++ b/src/controllers/encodingsettings.js @@ -1,9 +1,9 @@ -define(["jQuery", "loading", "globalize", "dom", "libraryMenu"], function($, loading, globalize, dom, libraryMenu) { +define(["jQuery", "loading", "globalize", "dom", "libraryMenu"], function ($, loading, globalize, dom, libraryMenu) { "use strict"; function loadPage(page, config, systemInfo) { - Array.prototype.forEach.call(page.querySelectorAll(".chkDecodeCodec"), function(c) { - c.checked = -1 !== (config.HardwareDecodingCodecs || []).indexOf(c.getAttribute("data-codec")) + Array.prototype.forEach.call(page.querySelectorAll(".chkDecodeCodec"), function (c) { + c.checked = -1 !== (config.HardwareDecodingCodecs || []).indexOf(c.getAttribute("data-codec")); }); page.querySelector("#chkHardwareEncoding").checked = config.EnableHardwareEncoding; $("#selectVideoDecoder", page).val(config.HardwareAccelerationType); @@ -17,19 +17,22 @@ define(["jQuery", "loading", "globalize", "dom", "libraryMenu"], function($, loa page.querySelector("#chkEnableSubtitleExtraction").checked = config.EnableSubtitleExtraction || false; page.querySelector("#selectVideoDecoder").dispatchEvent(new CustomEvent("change", { bubbles: true - })), loading.hide() + })); + loading.hide(); } function onSaveEncodingPathFailure(response) { loading.hide(); var msg = ""; - msg = globalize.translate("FFmpegSavePathNotFound"), require(["alert"], function(alert) { - alert(msg) - }) + msg = globalize.translate("FFmpegSavePathNotFound"); + + require(["alert"], function (alert) { + alert(msg); + }); } function updateEncoder(form) { - return ApiClient.getSystemInfo().then(function(systemInfo) { + return ApiClient.getSystemInfo().then(function (systemInfo) { return ApiClient.ajax({ url: ApiClient.getUrl("System/MediaEncoder/Path"), type: "POST", @@ -37,37 +40,67 @@ define(["jQuery", "loading", "globalize", "dom", "libraryMenu"], function($, loa Path: form.querySelector(".txtEncoderPath").value, PathType: "Custom" } - }).then(Dashboard.processServerConfigurationUpdateResult, onSaveEncodingPathFailure) - }) + }).then(Dashboard.processServerConfigurationUpdateResult, onSaveEncodingPathFailure); + }); } function onSubmit() { - var form = this, - onDecoderConfirmed = function() { - loading.show(), ApiClient.getNamedConfiguration("encoding").then(function(config) { - config.DownMixAudioBoost = $("#txtDownMixAudioBoost", form).val(), config.TranscodingTempPath = $("#txtTranscodingTempPath", form).val(), config.EncodingThreadCount = $("#selectThreadCount", form).val(), config.HardwareAccelerationType = $("#selectVideoDecoder", form).val(), config.VaapiDevice = $("#txtVaapiDevice", form).val(), config.H264Preset = form.querySelector("#selectH264Preset").value, config.H264Crf = parseInt(form.querySelector("#txtH264Crf").value || "0"), config.EnableSubtitleExtraction = form.querySelector("#chkEnableSubtitleExtraction").checked, config.HardwareDecodingCodecs = Array.prototype.map.call(Array.prototype.filter.call(form.querySelectorAll(".chkDecodeCodec"), function(c) { - return c.checked - }), function(c) { - return c.getAttribute("data-codec") - }), config.EnableHardwareEncoding = form.querySelector("#chkHardwareEncoding").checked, ApiClient.updateNamedConfiguration("encoding", config).then(function() { - updateEncoder(form) - }) - }) - }; - return $("#selectVideoDecoder", form).val() ? require(["alert"], function(alert) { - alert({ - title: globalize.translate("TitleHardwareAcceleration"), - text: globalize.translate("HardwareAccelerationWarning") - }).then(onDecoderConfirmed) - }) : onDecoderConfirmed(), !1 + var form = this; + + var onDecoderConfirmed = function () { + loading.show(); + ApiClient.getNamedConfiguration("encoding").then(function (config) { + config.DownMixAudioBoost = $("#txtDownMixAudioBoost", form).val(); + config.TranscodingTempPath = $("#txtTranscodingTempPath", form).val(); + config.EncodingThreadCount = $("#selectThreadCount", form).val(); + config.HardwareAccelerationType = $("#selectVideoDecoder", form).val(); + config.VaapiDevice = $("#txtVaapiDevice", form).val(); + config.H264Preset = form.querySelector("#selectH264Preset").value; + config.H264Crf = parseInt(form.querySelector("#txtH264Crf").value || "0"); + config.EnableSubtitleExtraction = form.querySelector("#chkEnableSubtitleExtraction").checked; + config.HardwareDecodingCodecs = Array.prototype.map.call(Array.prototype.filter.call(form.querySelectorAll(".chkDecodeCodec"), function (c) { + return c.checked; + }), function (c) { + return c.getAttribute("data-codec"); + }); + config.EnableHardwareEncoding = form.querySelector("#chkHardwareEncoding").checked; + ApiClient.updateNamedConfiguration("encoding", config).then(function () { + updateEncoder(form); + }); + }); + }; + + if ($("#selectVideoDecoder", form).val()) { + require(["alert"], function (alert) { + alert({ + title: globalize.translate("TitleHardwareAcceleration"), + text: globalize.translate("HardwareAccelerationWarning") + }).then(onDecoderConfirmed); + }); + } else { + onDecoderConfirmed(); + } + + return false; } function setDecodingCodecsVisible(context, value) { value = value || ""; var any; - Array.prototype.forEach.call(context.querySelectorAll(".chkDecodeCodec"), function(c) { - -1 === c.getAttribute("data-types").split(",").indexOf(value) ? dom.parentWithTag(c, "LABEL").classList.add("hide") : (dom.parentWithTag(c, "LABEL").classList.remove("hide"), any = !0) - }), any ? context.querySelector(".decodingCodecsList").classList.remove("hide") : context.querySelector(".decodingCodecsList").classList.add("hide") + Array.prototype.forEach.call(context.querySelectorAll(".chkDecodeCodec"), function (c) { + if (-1 === c.getAttribute("data-types").split(",").indexOf(value)) { + dom.parentWithTag(c, "LABEL").classList.add("hide"); + } else { + dom.parentWithTag(c, "LABEL").classList.remove("hide"); + any = true; + } + }); + + if (any) { + context.querySelector(".decodingCodecsList").classList.remove("hide"); + } else { + context.querySelector(".decodingCodecsList").classList.add("hide"); + } } function getTabs() { @@ -80,44 +113,69 @@ define(["jQuery", "loading", "globalize", "dom", "libraryMenu"], function($, loa }, { href: "streamingsettings.html", name: Globalize.translate("TabStreaming") - }] + }]; } - $(document).on("pageinit", "#encodingSettingsPage", function() { + $(document).on("pageinit", "#encodingSettingsPage", function () { var page = this; - page.querySelector("#selectVideoDecoder").addEventListener("change", function() { - "vaapi" == this.value ? (page.querySelector(".fldVaapiDevice").classList.remove("hide"), page.querySelector("#txtVaapiDevice").setAttribute("required", "required")) : (page.querySelector(".fldVaapiDevice").classList.add("hide"), page.querySelector("#txtVaapiDevice").removeAttribute("required")), this.value ? page.querySelector(".hardwareAccelerationOptions").classList.remove("hide") : page.querySelector(".hardwareAccelerationOptions").classList.add("hide"), setDecodingCodecsVisible(page, this.value) - }), $("#btnSelectEncoderPath", page).on("click.selectDirectory", function() { - require(["directorybrowser"], function(directoryBrowser) { - var picker = new directoryBrowser; + page.querySelector("#selectVideoDecoder").addEventListener("change", function () { + if ("vaapi" == this.value) { + page.querySelector(".fldVaapiDevice").classList.remove("hide"); + page.querySelector("#txtVaapiDevice").setAttribute("required", "required"); + } else { + page.querySelector(".fldVaapiDevice").classList.add("hide"); + page.querySelector("#txtVaapiDevice").removeAttribute("required"); + } + + if (this.value) { + page.querySelector(".hardwareAccelerationOptions").classList.remove("hide"); + } else { + page.querySelector(".hardwareAccelerationOptions").classList.add("hide"); + } + + setDecodingCodecsVisible(page, this.value); + }); + $("#btnSelectEncoderPath", page).on("click.selectDirectory", function () { + require(["directorybrowser"], function (directoryBrowser) { + var picker = new directoryBrowser(); picker.show({ - includeFiles: !0, - callback: function(path) { - path && $(".txtEncoderPath", page).val(path), picker.close() + includeFiles: true, + callback: function (path) { + if (path) { + $(".txtEncoderPath", page).val(path); + } + + picker.close(); } - }) - }) - }), $("#btnSelectTranscodingTempPath", page).on("click.selectDirectory", function() { - require(["directorybrowser"], function(directoryBrowser) { - var picker = new directoryBrowser; + }); + }); + }); + $("#btnSelectTranscodingTempPath", page).on("click.selectDirectory", function () { + require(["directorybrowser"], function (directoryBrowser) { + var picker = new directoryBrowser(); picker.show({ - callback: function(path) { - path && $("#txtTranscodingTempPath", page).val(path), picker.close() + callback: function (path) { + if (path) { + $("#txtTranscodingTempPath", page).val(path); + } + + picker.close(); }, - validateWriteable: !0, + validateWriteable: true, header: globalize.translate("HeaderSelectTranscodingPath"), instruction: globalize.translate("HeaderSelectTranscodingPathHelp") - }) - }) - }), $(".encodingSettingsForm").off("submit", onSubmit).on("submit", onSubmit) - }).on("pageshow", "#encodingSettingsPage", function() { + }); + }); + }); + $(".encodingSettingsForm").off("submit", onSubmit).on("submit", onSubmit); + }).on("pageshow", "#encodingSettingsPage", function () { loading.show(); libraryMenu.setTabs("playback", 0, getTabs); var page = this; - ApiClient.getNamedConfiguration("encoding").then(function(config) { - ApiClient.getSystemInfo().then(function(systemInfo) { + ApiClient.getNamedConfiguration("encoding").then(function (config) { + ApiClient.getSystemInfo().then(function (systemInfo) { loadPage(page, config, systemInfo); - }) - }) - }) + }); + }); + }); }); diff --git a/src/controllers/forgotpassword.js b/src/controllers/forgotpassword.js index ac010a9b34..e0f8ea4ef8 100644 --- a/src/controllers/forgotpassword.js +++ b/src/controllers/forgotpassword.js @@ -1,37 +1,53 @@ -define([], function() { +define([], function () { "use strict"; function processForgotPasswordResult(result) { - if ("ContactAdmin" == result.Action) return void Dashboard.alert({ - message: Globalize.translate("MessageContactAdminToResetPassword"), - title: Globalize.translate("HeaderForgotPassword") - }); - if ("InNetworkRequired" == result.Action) return void Dashboard.alert({ - message: Globalize.translate("MessageForgotPasswordInNetworkRequired"), - title: Globalize.translate("HeaderForgotPassword") - }); + if ("ContactAdmin" == result.Action) { + return void Dashboard.alert({ + message: Globalize.translate("MessageContactAdminToResetPassword"), + title: Globalize.translate("HeaderForgotPassword") + }); + } + + if ("InNetworkRequired" == result.Action) { + return void Dashboard.alert({ + message: Globalize.translate("MessageForgotPasswordInNetworkRequired"), + title: Globalize.translate("HeaderForgotPassword") + }); + } + if ("PinCode" == result.Action) { var msg = Globalize.translate("MessageForgotPasswordFileCreated"); - return msg += "
            ", msg += "
            ", msg += "Enter PIN here to finish Password Reset
            " ,msg += "
            ",msg += result.PinFile, msg += "
            ", void Dashboard.alert({ + msg += "
            "; + msg += "
            "; + msg += "Enter PIN here to finish Password Reset
            "; + msg += "
            "; + msg += result.PinFile; + msg += "
            "; + return void Dashboard.alert({ message: msg, title: Globalize.translate("HeaderForgotPassword"), - callback: function() { - Dashboard.navigate("forgotpasswordpin.html") + callback: function () { + Dashboard.navigate("forgotpasswordpin.html"); } - }) + }); } } - return function(view, params) { + + return function (view, params) { function onSubmit(e) { - return ApiClient.ajax({ + ApiClient.ajax({ type: "POST", url: ApiClient.getUrl("Users/ForgotPassword"), dataType: "json", data: { EnteredUsername: view.querySelector("#txtName").value } - }).then(processForgotPasswordResult), e.preventDefault(), !1 + }).then(processForgotPasswordResult); + e.preventDefault(); + return false; } - view.querySelector("form").addEventListener("submit", onSubmit) - } + + view.querySelector("form").addEventListener("submit", onSubmit); + }; }); diff --git a/src/controllers/forgotpasswordpin.js b/src/controllers/forgotpasswordpin.js index e7dccc7be1..47b1c899b9 100644 --- a/src/controllers/forgotpasswordpin.js +++ b/src/controllers/forgotpasswordpin.js @@ -1,33 +1,41 @@ -define([], function() { +define([], function () { "use strict"; function processForgotPasswordResult(result) { if (result.Success) { var msg = Globalize.translate("MessagePasswordResetForUsers"); - return msg += "
            ", msg += "
            ", msg += result.UsersReset.join("
            "), void Dashboard.alert({ + msg += "
            "; + msg += "
            "; + msg += result.UsersReset.join("
            "); + return void Dashboard.alert({ message: msg, title: Globalize.translate("HeaderPasswordReset"), - callback: function() { - window.location.href = "index.html" + callback: function () { + window.location.href = "index.html"; } - }) + }); } + Dashboard.alert({ message: Globalize.translate("MessageInvalidForgotPasswordPin"), title: Globalize.translate("HeaderPasswordReset") - }) + }); } - return function(view, params) { + + return function (view, params) { function onSubmit(e) { - return ApiClient.ajax({ + ApiClient.ajax({ type: "POST", url: ApiClient.getUrl("Users/ForgotPassword/Pin"), dataType: "json", data: { Pin: view.querySelector("#txtPin").value } - }).then(processForgotPasswordResult), e.preventDefault(), !1 + }).then(processForgotPasswordResult); + e.preventDefault(); + return false; } - view.querySelector("form").addEventListener("submit", onSubmit) - } -}); \ No newline at end of file + + view.querySelector("form").addEventListener("submit", onSubmit); + }; +}); diff --git a/src/controllers/home.js b/src/controllers/home.js index 0ab31f291d..b1dd70ebd6 100644 --- a/src/controllers/home.js +++ b/src/controllers/home.js @@ -1,4 +1,4 @@ -define(["tabbedView", "globalize", "require", "emby-tabs", "emby-button", "emby-scroller"], function(TabbedView, globalize, require) { +define(["tabbedView", "globalize", "require", "emby-tabs", "emby-button", "emby-scroller"], function (TabbedView, globalize, require) { "use strict"; function getTabs() { @@ -6,47 +6,70 @@ define(["tabbedView", "globalize", "require", "emby-tabs", "emby-button", "emby- name: globalize.translate("Home") }, { name: globalize.translate("Favorites") - }] + }]; } function getDefaultTabIndex() { - return 0 + return 0; } function getRequirePromise(deps) { - return new Promise(function(resolve, reject) { - require(deps, resolve) - }) + return new Promise(function (resolve, reject) { + require(deps, resolve); + }); } function getTabController(index) { - if (null == index) throw new Error("index cannot be null"); + if (null == index) { + throw new Error("index cannot be null"); + } + var depends = []; + switch (index) { case 0: depends.push("controllers/hometab"); break; + case 1: - depends.push("controllers/favorites") + depends.push("controllers/favorites"); } + var instance = this; - return getRequirePromise(depends).then(function(controllerFactory) { + return getRequirePromise(depends).then(function (controllerFactory) { var controller = instance.tabControllers[index]; + if (!controller) { - controller = new controllerFactory(instance.view.querySelector(".tabContent[data-index='" + index + "']"), instance.params), instance.tabControllers[index] = controller + controller = new controllerFactory(instance.view.querySelector(".tabContent[data-index='" + index + "']"), instance.params); + instance.tabControllers[index] = controller; } - return controller - }) + + return controller; + }); } function HomeView(view, params) { - TabbedView.call(this, view, params) + TabbedView.call(this, view, params); } - return Object.assign(HomeView.prototype, TabbedView.prototype), HomeView.prototype.getTabs = getTabs, HomeView.prototype.getDefaultTabIndex = getDefaultTabIndex, HomeView.prototype.getTabController = getTabController, HomeView.prototype.setTitle = function() { - Emby.Page.setTitle(null) - }, HomeView.prototype.onPause = function() { - TabbedView.prototype.onPause.call(this), document.querySelector(".skinHeader").classList.remove("noHomeButtonHeader") - }, HomeView.prototype.onResume = function(options) { - TabbedView.prototype.onResume.call(this, options), document.querySelector(".skinHeader").classList.add("noHomeButtonHeader") - }, HomeView -}); \ No newline at end of file + + Object.assign(HomeView.prototype, TabbedView.prototype); + HomeView.prototype.getTabs = getTabs; + HomeView.prototype.getDefaultTabIndex = getDefaultTabIndex; + HomeView.prototype.getTabController = getTabController; + + HomeView.prototype.setTitle = function () { + Emby.Page.setTitle(null); + }; + + HomeView.prototype.onPause = function () { + TabbedView.prototype.onPause.call(this); + document.querySelector(".skinHeader").classList.remove("noHomeButtonHeader"); + }; + + HomeView.prototype.onResume = function (options) { + TabbedView.prototype.onResume.call(this, options); + document.querySelector(".skinHeader").classList.add("noHomeButtonHeader"); + }; + + return HomeView; +}); diff --git a/src/controllers/hometab.js b/src/controllers/hometab.js index fed9b72146..d2adcb2da2 100644 --- a/src/controllers/hometab.js +++ b/src/controllers/hometab.js @@ -1,35 +1,74 @@ -define(["userSettings", "loading", "connectionManager", "apphost", "layoutManager", "focusManager", "homeSections", "emby-itemscontainer"], function(userSettings, loading, connectionManager, appHost, layoutManager, focusManager, homeSections) { +define(["userSettings", "loading", "connectionManager", "apphost", "layoutManager", "focusManager", "homeSections", "emby-itemscontainer"], function (userSettings, loading, connectionManager, appHost, layoutManager, focusManager, homeSections) { "use strict"; function HomeTab(view, params) { - this.view = view, this.params = params, this.apiClient = connectionManager.currentApiClient(), this.sectionsContainer = view.querySelector(".sections"), view.querySelector(".sections").addEventListener("settingschange", onHomeScreenSettingsChanged.bind(this)) + this.view = view; + this.params = params; + this.apiClient = connectionManager.currentApiClient(); + this.sectionsContainer = view.querySelector(".sections"); + view.querySelector(".sections").addEventListener("settingschange", onHomeScreenSettingsChanged.bind(this)); } function onHomeScreenSettingsChanged() { - this.sectionsRendered = !1, this.paused || this.onResume({ - refresh: !0 - }) + this.sectionsRendered = false; + + if (!this.paused) { + this.onResume({ + refresh: true + }); + } } - return HomeTab.prototype.onResume = function(options) { + + HomeTab.prototype.onResume = function (options) { if (this.sectionsRendered) { var sectionsContainer = this.sectionsContainer; - return sectionsContainer ? homeSections.resume(sectionsContainer, options) : Promise.resolve() + + if (sectionsContainer) { + return homeSections.resume(sectionsContainer, options); + } + + return Promise.resolve(); } + loading.show(); - var view = this.view, - apiClient = this.apiClient; - return this.destroyHomeSections(), this.sectionsRendered = !0, apiClient.getCurrentUser().then(function(user) { - return homeSections.loadSections(view.querySelector(".sections"), apiClient, user, userSettings).then(function() { - options.autoFocus && focusManager.autoFocus(view), loading.hide() - }) - }) - }, HomeTab.prototype.onPause = function() { + var view = this.view; + var apiClient = this.apiClient; + this.destroyHomeSections(); + this.sectionsRendered = true; + return apiClient.getCurrentUser().then(function (user) { + return homeSections.loadSections(view.querySelector(".sections"), apiClient, user, userSettings).then(function () { + if (options.autoFocus) { + focusManager.autoFocus(view); + } + + loading.hide(); + }); + }); + }; + + HomeTab.prototype.onPause = function () { var sectionsContainer = this.sectionsContainer; - sectionsContainer && homeSections.pause(sectionsContainer) - }, HomeTab.prototype.destroy = function() { - this.view = null, this.params = null, this.apiClient = null, this.destroyHomeSections(), this.sectionsContainer = null - }, HomeTab.prototype.destroyHomeSections = function() { + + if (sectionsContainer) { + homeSections.pause(sectionsContainer); + } + }; + + HomeTab.prototype.destroy = function () { + this.view = null; + this.params = null; + this.apiClient = null; + this.destroyHomeSections(); + this.sectionsContainer = null; + }; + + HomeTab.prototype.destroyHomeSections = function () { var sectionsContainer = this.sectionsContainer; - sectionsContainer && homeSections.destroySections(sectionsContainer) - }, HomeTab -}); \ No newline at end of file + + if (sectionsContainer) { + homeSections.destroySections(sectionsContainer); + } + }; + + return HomeTab; +}); diff --git a/src/controllers/installedplugins.js b/src/controllers/installedplugins.js index f9653fe260..a88f49d186 100644 --- a/src/controllers/installedplugins.js +++ b/src/controllers/installedplugins.js @@ -1,21 +1,22 @@ -define(["loading", "libraryMenu", "dom", "globalize", "cardStyle", "emby-button"], function(loading, libraryMenu, dom, globalize) { +define(["loading", "libraryMenu", "dom", "globalize", "cardStyle", "emby-button"], function (loading, libraryMenu, dom, globalize) { "use strict"; function deletePlugin(page, uniqueid, name) { var msg = globalize.translate("UninstallPluginConfirmation").replace("{0}", name); - require(["confirm"], function(confirm) { + + require(["confirm"], function (confirm) { confirm({ title: globalize.translate("UninstallPluginHeader"), text: msg, primary: "delete", confirmText: globalize.translate("UninstallPluginHeader") - }).then(function() { + }).then(function () { loading.show(); - ApiClient.uninstallPlugin(uniqueid).then(function() { + ApiClient.uninstallPlugin(uniqueid).then(function () { reloadList(page); }); - }) - }) + }); + }); } function showNoConfigurationMessage() { @@ -31,23 +32,24 @@ define(["loading", "libraryMenu", "dom", "globalize", "cardStyle", "emby-button" } function getPluginCardHtml(plugin, pluginConfigurationPages) { - var configPage = pluginConfigurationPages.filter(function(pluginConfigurationPage) { - return pluginConfigurationPage.PluginId == plugin.Id; + var configPage = pluginConfigurationPages.filter(function (pluginConfigurationPage) { + return pluginConfigurationPage.PluginId == plugin.Id; })[0]; var configPageUrl = configPage ? Dashboard.getConfigurationPageUrl(configPage.Name) : null; - var html = ""; html += "
            "; html += '
            '; html += '"; html += '
            '; @@ -67,21 +69,26 @@ define(["loading", "libraryMenu", "dom", "globalize", "cardStyle", "emby-button" } function renderPlugins(page, plugins) { - ApiClient.getJSON(ApiClient.getUrl("web/configurationpages") + "?pageType=PluginConfiguration").then(function(configPages) { + ApiClient.getJSON(ApiClient.getUrl("web/configurationpages") + "?pageType=PluginConfiguration").then(function (configPages) { populateList(page, plugins, configPages); }); } function populateList(page, plugins, pluginConfigurationPages) { - plugins = plugins.sort(function(plugin1, plugin2) { - return plugin1.Name > plugin2.Name ? 1 : -1 + plugins = plugins.sort(function (plugin1, plugin2) { + if (plugin1.Name > plugin2.Name) { + return 1; + } + + return -1; }); - var html = plugins.map(function(p) { - return getPluginCardHtml(p, pluginConfigurationPages) + var html = plugins.map(function (p) { + return getPluginCardHtml(p, pluginConfigurationPages); }).join(""); var installedPluginsElement = page.querySelector(".installedPlugins"); installedPluginsElement.removeEventListener("click", onInstalledPluginsClick); installedPluginsElement.addEventListener("click", onInstalledPluginsClick); + if (plugins.length) { installedPluginsElement.classList.add("itemsContainer"); installedPluginsElement.classList.add("vertical-wrap"); @@ -93,6 +100,7 @@ define(["loading", "libraryMenu", "dom", "globalize", "cardStyle", "emby-button" html += "

            "; html += "
            "; } + installedPluginsElement.innerHTML = html; loading.hide(); } @@ -103,6 +111,7 @@ define(["loading", "libraryMenu", "dom", "globalize", "cardStyle", "emby-button" var name = card.getAttribute("data-name"); var configHref = card.querySelector(".cardContent").getAttribute("href"); var menuItems = []; + if (configHref) { menuItems.push({ name: globalize.translate("ButtonSettings"), @@ -110,22 +119,25 @@ define(["loading", "libraryMenu", "dom", "globalize", "cardStyle", "emby-button" ironIcon: "mode-edit" }); } + menuItems.push({ name: globalize.translate("ButtonUninstall"), id: "delete", ironIcon: "delete" }); - require(["actionsheet"], function(actionsheet) { + + require(["actionsheet"], function (actionsheet) { actionsheet.show({ items: menuItems, positionTo: elem, - callback: function(resultId) { + callback: function (resultId) { switch (resultId) { case "open": Dashboard.navigate(configHref); break; + case "delete": - deletePlugin(page, id, name) + deletePlugin(page, id, name); } } }); @@ -134,7 +146,7 @@ define(["loading", "libraryMenu", "dom", "globalize", "cardStyle", "emby-button" function reloadList(page) { loading.show(); - ApiClient.getInstalledPlugins().then(function(plugins) { + ApiClient.getInstalledPlugins().then(function (plugins) { renderPlugins(page, plugins); }); } @@ -146,7 +158,7 @@ define(["loading", "libraryMenu", "dom", "globalize", "cardStyle", "emby-button" }, { href: "availableplugins.html", name: globalize.translate("TabCatalog") - }] + }]; } function onInstalledPluginsClick(e) { @@ -156,16 +168,18 @@ define(["loading", "libraryMenu", "dom", "globalize", "cardStyle", "emby-button" showConnectMessage(); } else { var btnCardMenu = dom.parentWithClass(e.target, "btnCardMenu"); - btnCardMenu && showPluginMenu(dom.parentWithClass(btnCardMenu, "page"), btnCardMenu); + + if (btnCardMenu) { + showPluginMenu(dom.parentWithClass(btnCardMenu, "page"), btnCardMenu); + } } } - pageIdOn("pageshow", "pluginsPage", function() { + pageIdOn("pageshow", "pluginsPage", function () { libraryMenu.setTabs("plugins", 0, getTabs); reloadList(this); }); - window.PluginsPage = { renderPlugins: renderPlugins - } + }; }); diff --git a/src/controllers/itemdetailpage.js b/src/controllers/itemdetailpage.js index 6991f63caa..37416dd3b7 100644 --- a/src/controllers/itemdetailpage.js +++ b/src/controllers/itemdetailpage.js @@ -1,37 +1,61 @@ -define(["loading", "appRouter", "layoutManager", "connectionManager", "cardBuilder", "datetime", "mediaInfo", "backdrop", "listView", "itemContextMenu", "itemHelper", "dom", "indicators", "apphost", "imageLoader", "libraryMenu", "globalize", "browser", "events", "scrollHelper", "playbackManager", "libraryBrowser", "scrollStyles", "emby-itemscontainer", "emby-checkbox", "emby-button", "emby-playstatebutton", "emby-ratingbutton", "emby-scroller", "emby-select"], function(loading, appRouter, layoutManager, connectionManager, cardBuilder, datetime, mediaInfo, backdrop, listView, itemContextMenu, itemHelper, dom, indicators, appHost, imageLoader, libraryMenu, globalize, browser, events, scrollHelper, playbackManager, libraryBrowser) { +define(["loading", "appRouter", "layoutManager", "connectionManager", "cardBuilder", "datetime", "mediaInfo", "backdrop", "listView", "itemContextMenu", "itemHelper", "dom", "indicators", "apphost", "imageLoader", "libraryMenu", "globalize", "browser", "events", "scrollHelper", "playbackManager", "libraryBrowser", "scrollStyles", "emby-itemscontainer", "emby-checkbox", "emby-button", "emby-playstatebutton", "emby-ratingbutton", "emby-scroller", "emby-select"], function (loading, appRouter, layoutManager, connectionManager, cardBuilder, datetime, mediaInfo, backdrop, listView, itemContextMenu, itemHelper, dom, indicators, appHost, imageLoader, libraryMenu, globalize, browser, events, scrollHelper, playbackManager, libraryBrowser) { "use strict"; function getPromise(apiClient, params) { var id = params.id; - if (id) return apiClient.getItem(apiClient.getCurrentUserId(), id); - if (params.seriesTimerId) return apiClient.getLiveTvSeriesTimer(params.seriesTimerId); - var name = params.genre; - if (name) return apiClient.getGenre(name, apiClient.getCurrentUserId()); - if (name = params.musicgenre) return apiClient.getMusicGenre(name, apiClient.getCurrentUserId()); - if (name = params.musicartist) return apiClient.getArtist(name, apiClient.getCurrentUserId()); - throw new Error("Invalid request") + + if (id) { + return apiClient.getItem(apiClient.getCurrentUserId(), id); + } + + if (params.seriesTimerId) { + return apiClient.getLiveTvSeriesTimer(params.seriesTimerId); + } + + if (params.genre) { + return apiClient.getGenre(params.genre, apiClient.getCurrentUserId()); + } + + if (params.musicgenre) { + return apiClient.getMusicGenre(params.musicgenre, apiClient.getCurrentUserId()); + } + + if (params.musicartist) { + return apiClient.getArtist(params.musicartist, apiClient.getCurrentUserId()); + } + + throw new Error("Invalid request"); } function hideAll(page, className, show) { - var i, length, elems = page.querySelectorAll("." + className); - for (i = 0, length = elems.length; i < length; i++) show ? elems[i].classList.remove("hide") : elems[i].classList.add("hide") + var i; + var length; + var elems = page.querySelectorAll("." + className); + + for (i = 0, length = elems.length; i < length; i++) { + if (show) { + elems[i].classList.remove("hide"); + } else { + elems[i].classList.add("hide"); + } + } } function getContextMenuOptions(item, user, button) { var options = { item: item, - open: !1, - play: !1, - playAllFromHere: !1, - queueAllFromHere: !1, + open: false, + play: false, + playAllFromHere: false, + queueAllFromHere: false, positionTo: button, - cancelTimer: !1, - record: !1, - deleteItem: !0 === item.IsFolder, - shuffle: !1, - instantMix: !1, + cancelTimer: false, + record: false, + deleteItem: true === item.IsFolder, + shuffle: false, + instantMix: false, user: user, - share: !0 + share: true }; return options; } @@ -39,18 +63,20 @@ define(["loading", "appRouter", "layoutManager", "connectionManager", "cardBuild function getProgramScheduleHtml(items, options) { options = options || {}; var html = ""; - return html += '
            ', html += listView.getListViewHtml({ + html += '
            '; + html += listView.getListViewHtml({ items: items, - enableUserDataButtons: !1, - image: !0, + enableUserDataButtons: false, + image: true, imageSource: "channel", - showProgramDateTime: !0, - showChannel: !1, - mediaInfo: !1, + showProgramDateTime: true, + showChannel: false, + mediaInfo: false, action: "none", - moreButton: !1, - recordButton: !1 - }), html += "
            " + moreButton: false, + recordButton: false + }); + return html += "
            "; } function renderSeriesTimerSchedule(page, apiClient, seriesTimerId) { @@ -59,184 +85,339 @@ define(["loading", "appRouter", "layoutManager", "connectionManager", "cardBuild ImageTypeLimit: 1, EnableImageTypes: "Primary,Backdrop,Thumb", SortBy: "StartDate", - EnableTotalRecordCount: !1, - EnableUserData: !1, + EnableTotalRecordCount: false, + EnableUserData: false, SeriesTimerId: seriesTimerId, Fields: "ChannelInfo,ChannelImage" - }).then(function(result) { - result.Items.length && result.Items[0].SeriesTimerId != seriesTimerId && (result.Items = []); - var html = getProgramScheduleHtml(result.Items), - scheduleTab = page.querySelector(".seriesTimerSchedule"); - scheduleTab.innerHTML = html, imageLoader.lazyChildren(scheduleTab) - }) + }).then(function (result) { + if (result.Items.length && result.Items[0].SeriesTimerId != seriesTimerId) { + result.Items = []; + } + + var html = getProgramScheduleHtml(result.Items); + var scheduleTab = page.querySelector(".seriesTimerSchedule"); + scheduleTab.innerHTML = html; + imageLoader.lazyChildren(scheduleTab); + }); } function renderTimerEditor(page, item, apiClient, user) { - if ("Recording" !== item.Type || !user.Policy.EnableLiveTvManagement || !item.TimerId || "InProgress" !== item.Status) return void hideAll(page, "btnCancelTimer"); - hideAll(page, "btnCancelTimer", !0) + if ("Recording" !== item.Type || !user.Policy.EnableLiveTvManagement || !item.TimerId || "InProgress" !== item.Status) { + return void hideAll(page, "btnCancelTimer"); + } + + hideAll(page, "btnCancelTimer", true); } function renderSeriesTimerEditor(page, item, apiClient, user) { - return "SeriesTimer" !== item.Type ? void hideAll(page, "btnCancelSeriesTimer") : user.Policy.EnableLiveTvManagement ? (require(["seriesRecordingEditor"], function(seriesRecordingEditor) { - seriesRecordingEditor.embed(item, apiClient.serverId(), { - context: page.querySelector(".seriesRecordingEditor") - }) - }), page.querySelector(".seriesTimerScheduleSection").classList.remove("hide"), hideAll(page, "btnCancelSeriesTimer", !0), void renderSeriesTimerSchedule(page, apiClient, item.Id)) : (page.querySelector(".seriesTimerScheduleSection").classList.add("hide"), void hideAll(page, "btnCancelSeriesTimer")) + if ("SeriesTimer" !== item.Type) { + return void hideAll(page, "btnCancelSeriesTimer"); + } + + if (user.Policy.EnableLiveTvManagement) { + require(["seriesRecordingEditor"], function (seriesRecordingEditor) { + seriesRecordingEditor.embed(item, apiClient.serverId(), { + context: page.querySelector(".seriesRecordingEditor") + }); + }); + + page.querySelector(".seriesTimerScheduleSection").classList.remove("hide"); + hideAll(page, "btnCancelSeriesTimer", true); + return void renderSeriesTimerSchedule(page, apiClient, item.Id); + } + + page.querySelector(".seriesTimerScheduleSection").classList.add("hide"); + return void hideAll(page, "btnCancelSeriesTimer"); } function renderTrackSelections(page, instance, item, forceReload) { var select = page.querySelector(".selectSource"); - if (!item.MediaSources || !itemHelper.supportsMediaSourceSelection(item) || -1 === playbackManager.getSupportedCommands().indexOf("PlayMediaSource") || !playbackManager.canPlay(item)) return page.querySelector(".trackSelections").classList.add("hide"), select.innerHTML = "", page.querySelector(".selectVideo").innerHTML = "", page.querySelector(".selectAudio").innerHTML = "", void(page.querySelector(".selectSubtitles").innerHTML = ""); - playbackManager.getPlaybackMediaSources(item).then(function(mediaSources) { - instance._currentPlaybackMediaSources = mediaSources, page.querySelector(".trackSelections").classList.remove("hide"), select.setLabel(globalize.translate("LabelVersion")); - var currentValue = select.value, - selectedId = mediaSources[0].Id; - select.innerHTML = mediaSources.map(function(v) { + + if (!item.MediaSources || !itemHelper.supportsMediaSourceSelection(item) || -1 === playbackManager.getSupportedCommands().indexOf("PlayMediaSource") || !playbackManager.canPlay(item)) { + page.querySelector(".trackSelections").classList.add("hide"); + select.innerHTML = ""; + page.querySelector(".selectVideo").innerHTML = ""; + page.querySelector(".selectAudio").innerHTML = ""; + page.querySelector(".selectSubtitles").innerHTML = ""; + return; + } + + playbackManager.getPlaybackMediaSources(item).then(function (mediaSources) { + instance._currentPlaybackMediaSources = mediaSources; + page.querySelector(".trackSelections").classList.remove("hide"); + select.setLabel(globalize.translate("LabelVersion")); + var currentValue = select.value; + var selectedId = mediaSources[0].Id; + select.innerHTML = mediaSources.map(function (v) { var selected = v.Id === selectedId ? " selected" : ""; - return '" - }).join(""), mediaSources.length > 1 ? page.querySelector(".selectSourceContainer").classList.remove("hide") : page.querySelector(".selectSourceContainer").classList.add("hide"), (select.value !== currentValue || forceReload) && (renderVideoSelections(page, mediaSources), renderAudioSelections(page, mediaSources), renderSubtitleSelections(page, mediaSources)) - }) + return '"; + }).join(""); + + if (mediaSources.length > 1) { + page.querySelector(".selectSourceContainer").classList.remove("hide"); + } else { + page.querySelector(".selectSourceContainer").classList.add("hide"); + } + + if (select.value !== currentValue || forceReload) { + renderVideoSelections(page, mediaSources); + renderAudioSelections(page, mediaSources); + renderSubtitleSelections(page, mediaSources); + } + }); } function renderVideoSelections(page, mediaSources) { - var mediaSourceId = page.querySelector(".selectSource").value, - mediaSource = mediaSources.filter(function(m) { - return m.Id === mediaSourceId - })[0], - tracks = mediaSource.MediaStreams.filter(function(m) { - return "Video" === m.Type - }), - select = page.querySelector(".selectVideo"); + var mediaSourceId = page.querySelector(".selectSource").value; + var mediaSource = mediaSources.filter(function (m) { + return m.Id === mediaSourceId; + })[0]; + var tracks = mediaSource.MediaStreams.filter(function (m) { + return "Video" === m.Type; + }); + var select = page.querySelector(".selectVideo"); select.setLabel(globalize.translate("LabelVideo")); var selectedId = tracks.length ? tracks[0].Index : -1; - select.innerHTML = tracks.map(function(v) { - var selected = v.Index === selectedId ? " selected" : "", - titleParts = [], - resolutionText = mediaInfo.getResolutionText(v); - return resolutionText && titleParts.push(resolutionText), v.Codec && titleParts.push(v.Codec.toUpperCase()), '" - }).join(""), select.setAttribute("disabled", "disabled"), tracks.length ? page.querySelector(".selectVideoContainer").classList.remove("hide") : page.querySelector(".selectVideoContainer").classList.add("hide") + select.innerHTML = tracks.map(function (v) { + var selected = v.Index === selectedId ? " selected" : ""; + var titleParts = []; + var resolutionText = mediaInfo.getResolutionText(v); + + if (resolutionText) { + titleParts.push(resolutionText); + } + + if (v.Codec) { + titleParts.push(v.Codec.toUpperCase()); + } + + return '"; + }).join(""); + select.setAttribute("disabled", "disabled"); + + if (tracks.length) { + page.querySelector(".selectVideoContainer").classList.remove("hide"); + } else { + page.querySelector(".selectVideoContainer").classList.add("hide"); + } } function renderAudioSelections(page, mediaSources) { - var mediaSourceId = page.querySelector(".selectSource").value, - mediaSource = mediaSources.filter(function(m) { - return m.Id === mediaSourceId - })[0], - tracks = mediaSource.MediaStreams.filter(function(m) { - return "Audio" === m.Type - }), - select = page.querySelector(".selectAudio"); + var mediaSourceId = page.querySelector(".selectSource").value; + var mediaSource = mediaSources.filter(function (m) { + return m.Id === mediaSourceId; + })[0]; + var tracks = mediaSource.MediaStreams.filter(function (m) { + return "Audio" === m.Type; + }); + var select = page.querySelector(".selectAudio"); select.setLabel(globalize.translate("LabelAudio")); var selectedId = mediaSource.DefaultAudioStreamIndex; - select.innerHTML = tracks.map(function(v) { + select.innerHTML = tracks.map(function (v) { var selected = v.Index === selectedId ? " selected" : ""; - return '" - }).join(""), tracks.length > 1 ? select.removeAttribute("disabled") : select.setAttribute("disabled", "disabled"), tracks.length ? page.querySelector(".selectAudioContainer").classList.remove("hide") : page.querySelector(".selectAudioContainer").classList.add("hide") + return '"; + }).join(""); + + if (tracks.length > 1) { + select.removeAttribute("disabled"); + } else { + select.setAttribute("disabled", "disabled"); + } + + if (tracks.length) { + page.querySelector(".selectAudioContainer").classList.remove("hide"); + } else { + page.querySelector(".selectAudioContainer").classList.add("hide"); + } } function renderSubtitleSelections(page, mediaSources) { - var mediaSourceId = page.querySelector(".selectSource").value, - mediaSource = mediaSources.filter(function(m) { - return m.Id === mediaSourceId - })[0], - tracks = mediaSource.MediaStreams.filter(function(m) { - return "Subtitle" === m.Type - }), - select = page.querySelector(".selectSubtitles"); + var mediaSourceId = page.querySelector(".selectSource").value; + var mediaSource = mediaSources.filter(function (m) { + return m.Id === mediaSourceId; + })[0]; + var tracks = mediaSource.MediaStreams.filter(function (m) { + return "Subtitle" === m.Type; + }); + var select = page.querySelector(".selectSubtitles"); select.setLabel(globalize.translate("LabelSubtitles")); var selectedId = null == mediaSource.DefaultSubtitleStreamIndex ? -1 : mediaSource.DefaultSubtitleStreamIndex; + if (tracks.length) { var selected = -1 === selectedId ? " selected" : ""; - select.innerHTML = '" + tracks.map(function(v) { - return selected = v.Index === selectedId ? " selected" : "", '" - }).join(""), page.querySelector(".selectSubtitlesContainer").classList.remove("hide") - } else select.innerHTML = "", page.querySelector(".selectSubtitlesContainer").classList.add("hide") + select.innerHTML = '" + tracks.map(function (v) { + selected = v.Index === selectedId ? " selected" : ""; + return '"; + }).join(""); + page.querySelector(".selectSubtitlesContainer").classList.remove("hide"); + } else { + select.innerHTML = ""; + page.querySelector(".selectSubtitlesContainer").classList.add("hide"); + } } function reloadPlayButtons(page, item) { - var canPlay = !1; + var canPlay = false; + if ("Program" == item.Type) { - var now = new Date; - now >= datetime.parseISO8601Date(item.StartDate, !0) && now < datetime.parseISO8601Date(item.EndDate, !0) ? (hideAll(page, "btnPlay", !0), canPlay = !0) : hideAll(page, "btnPlay"), hideAll(page, "btnResume"), hideAll(page, "btnInstantMix"), hideAll(page, "btnShuffle") + var now = new Date(); + + if (now >= datetime.parseISO8601Date(item.StartDate, true) && now < datetime.parseISO8601Date(item.EndDate, true)) { + hideAll(page, "btnPlay", true); + canPlay = true; + } else { + hideAll(page, "btnPlay"); + } + + hideAll(page, "btnResume"); + hideAll(page, "btnInstantMix"); + hideAll(page, "btnShuffle"); } else if (playbackManager.canPlay(item)) { - hideAll(page, "btnPlay", !0); + hideAll(page, "btnPlay", true); var enableInstantMix = -1 !== ["Audio", "MusicAlbum", "MusicGenre", "MusicArtist"].indexOf(item.Type); hideAll(page, "btnInstantMix", enableInstantMix); var enableShuffle = item.IsFolder || -1 !== ["MusicAlbum", "MusicGenre", "MusicArtist"].indexOf(item.Type); - hideAll(page, "btnShuffle", enableShuffle), canPlay = !0, hideAll(page, "btnResume", item.UserData && item.UserData.PlaybackPositionTicks > 0) - } else hideAll(page, "btnPlay"), hideAll(page, "btnResume"), hideAll(page, "btnInstantMix"), hideAll(page, "btnShuffle"); - return canPlay + hideAll(page, "btnShuffle", enableShuffle); + canPlay = true; + hideAll(page, "btnResume", item.UserData && item.UserData.PlaybackPositionTicks > 0); + } else { + hideAll(page, "btnPlay"); + hideAll(page, "btnResume"); + hideAll(page, "btnInstantMix"); + hideAll(page, "btnShuffle"); + } + + return canPlay; } function reloadUserDataButtons(page, item) { - var i, length, btnPlaystates = page.querySelectorAll(".btnPlaystate"); + var i; + var length; + var btnPlaystates = page.querySelectorAll(".btnPlaystate"); + for (i = 0, length = btnPlaystates.length; i < length; i++) { var btnPlaystate = btnPlaystates[i]; - itemHelper.canMarkPlayed(item) ? (btnPlaystate.classList.remove("hide"), btnPlaystate.setItem(item)) : (btnPlaystate.classList.add("hide"), btnPlaystate.setItem(null)) + + if (itemHelper.canMarkPlayed(item)) { + btnPlaystate.classList.remove("hide"); + btnPlaystate.setItem(item); + } else { + btnPlaystate.classList.add("hide"); + btnPlaystate.setItem(null); + } } + var btnUserRatings = page.querySelectorAll(".btnUserRating"); + for (i = 0, length = btnUserRatings.length; i < length; i++) { var btnUserRating = btnUserRatings[i]; - itemHelper.canRate(item) ? (btnUserRating.classList.remove("hide"), btnUserRating.setItem(item)) : (btnUserRating.classList.add("hide"), btnUserRating.setItem(null)) + + if (itemHelper.canRate(item)) { + btnUserRating.classList.remove("hide"); + btnUserRating.setItem(item); + } else { + btnUserRating.classList.add("hide"); + btnUserRating.setItem(null); + } } } function getArtistLinksHtml(artists, serverId, context) { - for (var html = [], i = 0, length = artists.length; i < length; i++) { - var artist = artists[i], - href = appRouter.getRouteUrl(artist, { - context: context, - itemType: "MusicArtist", - serverId: serverId - }); - html.push('' + artist.Name + "") + var html = []; + + for (var i = 0, length = artists.length; i < length; i++) { + var artist = artists[i]; + var href = appRouter.getRouteUrl(artist, { + context: context, + itemType: "MusicArtist", + serverId: serverId + }); + html.push('' + artist.Name + ""); } - return html = html.join(" / ") + + return html = html.join(" / "); } function renderName(item, container, isStatic, context) { - var parentRoute, parentNameHtml = [], - parentNameLast = !1; - item.AlbumArtists ? (parentNameHtml.push(getArtistLinksHtml(item.AlbumArtists, item.ServerId, context)), parentNameLast = !0) : item.ArtistItems && item.ArtistItems.length && "MusicVideo" === item.Type ? (parentNameHtml.push(getArtistLinksHtml(item.ArtistItems, item.ServerId, context)), parentNameLast = !0) : item.SeriesName && "Episode" === item.Type ? (parentRoute = appRouter.getRouteUrl({ - Id: item.SeriesId, - Name: item.SeriesName, - Type: "Series", - IsFolder: !0, - ServerId: item.ServerId - }, { - context: context - }), parentNameHtml.push('' + item.SeriesName + "")) : (item.IsSeries || item.EpisodeTitle) && parentNameHtml.push(item.Name), item.SeriesName && "Season" === item.Type ? (parentRoute = appRouter.getRouteUrl({ - Id: item.SeriesId, - Name: item.SeriesName, - Type: "Series", - IsFolder: !0, - ServerId: item.ServerId - }, { - context: context - }), parentNameHtml.push('' + item.SeriesName + "")) : null != item.ParentIndexNumber && "Episode" === item.Type ? (parentRoute = appRouter.getRouteUrl({ - Id: item.SeasonId, - Name: item.SeasonName, - Type: "Season", - IsFolder: !0, - ServerId: item.ServerId - }, { - context: context - }), parentNameHtml.push('' + item.SeasonName + "")) : null != item.ParentIndexNumber && item.IsSeries ? parentNameHtml.push(item.SeasonName || "S" + item.ParentIndexNumber) : item.Album && item.AlbumId && ("MusicVideo" === item.Type || "Audio" === item.Type) ? (parentRoute = appRouter.getRouteUrl({ - Id: item.AlbumId, - Name: item.Album, - Type: "MusicAlbum", - IsFolder: !0, - ServerId: item.ServerId - }, { - context: context - }), parentNameHtml.push('' + item.Album + "")) : item.Album && parentNameHtml.push(item.Album); - var html = ""; - parentNameHtml.length && (html = parentNameLast ? '

            ' + parentNameHtml.join(" - ") + "

            " : '

            ' + parentNameHtml.join(" - ") + "

            "); - var name = itemHelper.getDisplayName(item, { - includeParentInfo: !1 - }); + var parentRoute; + var parentNameHtml = []; + var parentNameLast = false; + if (item.AlbumArtists) { + parentNameHtml.push(getArtistLinksHtml(item.AlbumArtists, item.ServerId, context)); + parentNameLast = true; + } else if (item.ArtistItems && item.ArtistItems.length && "MusicVideo" === item.Type) { + parentNameHtml.push(getArtistLinksHtml(item.ArtistItems, item.ServerId, context)); + parentNameLast = true; + } else if (item.SeriesName && "Episode" === item.Type) { + parentRoute = appRouter.getRouteUrl({ + Id: item.SeriesId, + Name: item.SeriesName, + Type: "Series", + IsFolder: true, + ServerId: item.ServerId + }, { + context: context + }); + parentNameHtml.push('' + item.SeriesName + ""); + } else if (item.IsSeries || item.EpisodeTitle) { + parentNameHtml.push(item.Name); + } + + if (item.SeriesName && "Season" === item.Type) { + parentRoute = appRouter.getRouteUrl({ + Id: item.SeriesId, + Name: item.SeriesName, + Type: "Series", + IsFolder: true, + ServerId: item.ServerId + }, { + context: context + }); + parentNameHtml.push('' + item.SeriesName + ""); + } else if (null != item.ParentIndexNumber && "Episode" === item.Type) { + parentRoute = appRouter.getRouteUrl({ + Id: item.SeasonId, + Name: item.SeasonName, + Type: "Season", + IsFolder: true, + ServerId: item.ServerId + }, { + context: context + }); + parentNameHtml.push('' + item.SeasonName + ""); + } else if (null != item.ParentIndexNumber && item.IsSeries) { + parentNameHtml.push(item.SeasonName || "S" + item.ParentIndexNumber); + } else if (item.Album && item.AlbumId && ("MusicVideo" === item.Type || "Audio" === item.Type)) { + parentRoute = appRouter.getRouteUrl({ + Id: item.AlbumId, + Name: item.Album, + Type: "MusicAlbum", + IsFolder: true, + ServerId: item.ServerId + }, { + context: context + }); + parentNameHtml.push('' + item.Album + ""); + } else if (item.Album) { + parentNameHtml.push(item.Album); + } + + var html = ""; + + if (parentNameHtml.length) { + if (parentNameLast) { + html = '

            ' + parentNameHtml.join(" - ") + "

            "; + } else { + html = '

            ' + parentNameHtml.join(" - ") + "

            "; + } + } + + var name = itemHelper.getDisplayName(item, { + includeParentInfo: false + }); var offset = parentNameLast ? ".25em" : ".5em"; + if (html && !parentNameLast) { html += '

            ' + name + '

            '; } else { @@ -248,110 +429,206 @@ define(["loading", "appRouter", "layoutManager", "connectionManager", "cardBuild } container.innerHTML = html; - html.length ? container.classList.remove("hide") : container.classList.add("hide") + + if (html.length) { + container.classList.remove("hide"); + } else { + container.classList.add("hide"); + } } function setTrailerButtonVisibility(page, item) { - (item.LocalTrailerCount || item.RemoteTrailers && item.RemoteTrailers.length) && -1 !== playbackManager.getSupportedCommands().indexOf("PlayTrailers") ? hideAll(page, "btnPlayTrailer", !0) : hideAll(page, "btnPlayTrailer") - } - - function renderDetailPageBackdrop(page, item, apiClient) { - var imgUrl, screenWidth = screen.availWidth, - hasbackdrop = !1, - itemBackdropElement = page.querySelector("#itemBackdrop"), - usePrimaryImage = ("Video" === item.MediaType && "Movie" !== item.Type && "Trailer" !== item.Type) || (item.MediaType && "Video" !== item.MediaType) || ("MusicAlbum" === item.Type) || ("MusicArtist" === item.Type); - return "Program" === item.Type && item.ImageTags && item.ImageTags.Thumb ? (imgUrl = apiClient.getScaledImageUrl(item.Id, { - type: "Thumb", - index: 0, - maxWidth: screenWidth, - tag: item.ImageTags.Thumb - }), itemBackdropElement.classList.remove("noBackdrop"), imageLoader.lazyImage(itemBackdropElement, imgUrl, !1), hasbackdrop = !0) : usePrimaryImage && item.ImageTags && item.ImageTags.Primary ? (imgUrl = apiClient.getScaledImageUrl(item.Id, { - type: "Primary", - index: 0, - maxWidth: screenWidth, - tag: item.ImageTags.Primary - }), itemBackdropElement.classList.remove("noBackdrop"), imageLoader.lazyImage(itemBackdropElement, imgUrl, !1), hasbackdrop = !0) : item.BackdropImageTags && item.BackdropImageTags.length ? (imgUrl = apiClient.getScaledImageUrl(item.Id, { - type: "Backdrop", - index: 0, - maxWidth: screenWidth, - tag: item.BackdropImageTags[0] - }), itemBackdropElement.classList.remove("noBackdrop"), imageLoader.lazyImage(itemBackdropElement, imgUrl, !1), hasbackdrop = !0) : item.ParentBackdropItemId && item.ParentBackdropImageTags && item.ParentBackdropImageTags.length ? (imgUrl = apiClient.getScaledImageUrl(item.ParentBackdropItemId, { - type: "Backdrop", - index: 0, - tag: item.ParentBackdropImageTags[0], - maxWidth: screenWidth - }), itemBackdropElement.classList.remove("noBackdrop"), imageLoader.lazyImage(itemBackdropElement, imgUrl, !1), hasbackdrop = !0) : item.ImageTags && item.ImageTags.Thumb ? (imgUrl = apiClient.getScaledImageUrl(item.Id, { - type: "Thumb", - index: 0, - maxWidth: screenWidth, - tag: item.ImageTags.Thumb - }), itemBackdropElement.classList.remove("noBackdrop"), imageLoader.lazyImage(itemBackdropElement, imgUrl, !1), hasbackdrop = !0) : (itemBackdropElement.classList.add("noBackdrop"), itemBackdropElement.style.backgroundImage = ""), hasbackdrop - } - - function reloadFromItem(instance, page, params, item, user) { - var context = params.context; - renderName(item, page.querySelector(".nameContainer"), !1, context); - var apiClient = connectionManager.getApiClient(item.ServerId); - renderSeriesTimerEditor(page, item, apiClient, user), renderTimerEditor(page, item, apiClient, user), renderImage(page, item, apiClient, user), renderLogo(page, item, apiClient), setTitle(item, apiClient), setInitialCollapsibleState(page, item, apiClient, context, user), renderDetails(page, item, apiClient, context), renderTrackSelections(page, instance, item), dom.getWindowSize().innerWidth >= 1e3 ? backdrop.setBackdrops([item]) : backdrop.clear(), renderDetailPageBackdrop(page, item, apiClient); - var canPlay = reloadPlayButtons(page, item); if ((item.LocalTrailerCount || item.RemoteTrailers && item.RemoteTrailers.length) && -1 !== playbackManager.getSupportedCommands().indexOf("PlayTrailers")) { hideAll(page, "btnPlayTrailer", true); } else { hideAll(page, "btnPlayTrailer"); } + } + + function renderDetailPageBackdrop(page, item, apiClient) { + var imgUrl; + var screenWidth = screen.availWidth; + var hasbackdrop = false; + var itemBackdropElement = page.querySelector("#itemBackdrop"); + var usePrimaryImage = item.MediaType === "Video" && item.Type !== "Movie" && item.Type !== "Trailer" || + item.MediaType && item.MediaType !== "Video" || + item.Type === "MusicAlbum" || + item.Type === "MusicArtist"; + + if ("Program" === item.Type && item.ImageTags && item.ImageTags.Thumb) { + imgUrl = apiClient.getScaledImageUrl(item.Id, { + type: "Thumb", + index: 0, + maxWidth: screenWidth, + tag: item.ImageTags.Thumb + }); + itemBackdropElement.classList.remove("noBackdrop"); + imageLoader.lazyImage(itemBackdropElement, imgUrl, false); + hasbackdrop = true; + } else if (usePrimaryImage && item.ImageTags && item.ImageTags.Primary) { + imgUrl = apiClient.getScaledImageUrl(item.Id, { + type: "Primary", + index: 0, + maxWidth: screenWidth, + tag: item.ImageTags.Primary + }); + itemBackdropElement.classList.remove("noBackdrop"); + imageLoader.lazyImage(itemBackdropElement, imgUrl, false); + hasbackdrop = true; + } else if (item.BackdropImageTags && item.BackdropImageTags.length) { + imgUrl = apiClient.getScaledImageUrl(item.Id, { + type: "Backdrop", + index: 0, + maxWidth: screenWidth, + tag: item.BackdropImageTags[0] + }); + itemBackdropElement.classList.remove("noBackdrop"); + imageLoader.lazyImage(itemBackdropElement, imgUrl, false); + hasbackdrop = true; + } else if (item.ParentBackdropItemId && item.ParentBackdropImageTags && item.ParentBackdropImageTags.length) { + imgUrl = apiClient.getScaledImageUrl(item.ParentBackdropItemId, { + type: "Backdrop", + index: 0, + tag: item.ParentBackdropImageTags[0], + maxWidth: screenWidth + }); + itemBackdropElement.classList.remove("noBackdrop"); + imageLoader.lazyImage(itemBackdropElement, imgUrl, false); + hasbackdrop = true; + } else if (item.ImageTags && item.ImageTags.Thumb) { + imgUrl = apiClient.getScaledImageUrl(item.Id, { + type: "Thumb", + index: 0, + maxWidth: screenWidth, + tag: item.ImageTags.Thumb + }); + itemBackdropElement.classList.remove("noBackdrop"); + imageLoader.lazyImage(itemBackdropElement, imgUrl, false); + hasbackdrop = true; + } else { + itemBackdropElement.classList.add("noBackdrop"); + itemBackdropElement.style.backgroundImage = ""; + } + + return hasbackdrop; + } + + function reloadFromItem(instance, page, params, item, user) { + var context = params.context; + renderName(item, page.querySelector(".nameContainer"), false, context); + var apiClient = connectionManager.getApiClient(item.ServerId); + renderSeriesTimerEditor(page, item, apiClient, user); + renderTimerEditor(page, item, apiClient, user); + renderImage(page, item, apiClient, user); + renderLogo(page, item, apiClient); + setTitle(item, apiClient); + setInitialCollapsibleState(page, item, apiClient, context, user); + renderDetails(page, item, apiClient, context); + renderTrackSelections(page, instance, item); + + if (dom.getWindowSize().innerWidth >= 1000) { + backdrop.setBackdrops([item]); + } else { + backdrop.clear(); + } + + renderDetailPageBackdrop(page, item, apiClient); + var canPlay = reloadPlayButtons(page, item); + + if ((item.LocalTrailerCount || item.RemoteTrailers && item.RemoteTrailers.length) && -1 !== playbackManager.getSupportedCommands().indexOf("PlayTrailers")) { + hideAll(page, "btnPlayTrailer", true); + } else { + hideAll(page, "btnPlayTrailer"); + } + setTrailerButtonVisibility(page, item); + if (item.CanDelete && !item.IsFolder) { hideAll(page, "btnDeleteItem", true); } else { hideAll(page, "btnDeleteItem"); } + if ("Program" !== item.Type || canPlay) { hideAll(page, "mainDetailButtons", true); } else { hideAll(page, "mainDetailButtons"); } + showRecordingFields(instance, page, item, user); - var groupedVersions = (item.MediaSources || []).filter(function(g) { - return "Grouping" == g.Type + var groupedVersions = (item.MediaSources || []).filter(function (g) { + return "Grouping" == g.Type; }); - user.Policy.IsAdministrator && groupedVersions.length ? page.querySelector(".btnSplitVersions").classList.remove("hide") : page.querySelector(".btnSplitVersions").classList.add("hide"), itemContextMenu.getCommands(getContextMenuOptions(item, user)).length ? hideAll(page, "btnMoreCommands", !0) : hideAll(page, "btnMoreCommands"); - var itemBirthday = page.querySelector("#itemBirthday"); - if ("Person" == item.Type && item.PremiereDate) try { - var birthday = datetime.parseISO8601Date(item.PremiereDate, !0).toDateString(); - itemBirthday.classList.remove("hide"), itemBirthday.innerHTML = globalize.translate("BirthDateValue").replace("{0}", birthday) - } catch (err) { - itemBirthday.classList.add("hide") - } else itemBirthday.classList.add("hide"); - var itemDeathDate = page.querySelector("#itemDeathDate"); - if ("Person" == item.Type && item.EndDate) try { - var deathday = datetime.parseISO8601Date(item.EndDate, !0).toDateString(); - itemDeathDate.classList.remove("hide"), itemDeathDate.innerHTML = globalize.translate("DeathDateValue").replace("{0}", deathday) - } catch (err) { - itemDeathDate.classList.add("hide") + + if (user.Policy.IsAdministrator && groupedVersions.length) { + page.querySelector(".btnSplitVersions").classList.remove("hide"); + } else { + page.querySelector(".btnSplitVersions").classList.add("hide"); } + + if (itemContextMenu.getCommands(getContextMenuOptions(item, user)).length) { + hideAll(page, "btnMoreCommands", true); + } else { + hideAll(page, "btnMoreCommands"); + } + + var itemBirthday = page.querySelector("#itemBirthday"); + + if ("Person" == item.Type && item.PremiereDate) { + try { + var birthday = datetime.parseISO8601Date(item.PremiereDate, true).toDateString(); + itemBirthday.classList.remove("hide"); + itemBirthday.innerHTML = globalize.translate("BirthDateValue").replace("{0}", birthday); + } catch (err) { + itemBirthday.classList.add("hide"); + } + } else { + itemBirthday.classList.add("hide"); + } + + var itemDeathDate = page.querySelector("#itemDeathDate"); + + if ("Person" == item.Type && item.EndDate) { + try { + var deathday = datetime.parseISO8601Date(item.EndDate, true).toDateString(); + itemDeathDate.classList.remove("hide"); + itemDeathDate.innerHTML = globalize.translate("DeathDateValue").replace("{0}", deathday); + } catch (err) { + itemDeathDate.classList.add("hide"); + } + } else { + itemDeathDate.classList.add("hide"); + } + var itemBirthLocation = page.querySelector("#itemBirthLocation"); + if ("Person" == item.Type && item.ProductionLocations && item.ProductionLocations.length) { var gmap = '' + item.ProductionLocations[0] + ""; - itemBirthLocation.classList.remove("hide"), itemBirthLocation.innerHTML = globalize.translate("BirthPlaceValue").replace("{0}", gmap) - } else itemBirthLocation.classList.add("hide"); - setPeopleHeader(page, item), loading.hide() + itemBirthLocation.classList.remove("hide"); + itemBirthLocation.innerHTML = globalize.translate("BirthPlaceValue").replace("{0}", gmap); + } else { + itemBirthLocation.classList.add("hide"); + } + + setPeopleHeader(page, item); + loading.hide(); if (item.Type === "Book") { hideAll(page, "btnDownload", true); } try { - require(["focusManager"], function(focusManager) { + require(["focusManager"], function (focusManager) { [".btnResume", ".btnPlay"].every(function (cls) { - var elems = page.querySelectorAll(cls); - + for (var i = 0; i < elems.length; i++) { if (focusManager.isCurrentlyFocusable(elems[i])) { focusManager.focus(elems[i]); return false; } } + return true; }); }); @@ -361,35 +638,68 @@ define(["loading", "appRouter", "layoutManager", "connectionManager", "cardBuild } function logoImageUrl(item, apiClient, options) { - return options = options || {}, options.type = "Logo", item.ImageTags && item.ImageTags.Logo ? (options.tag = item.ImageTags.Logo, apiClient.getScaledImageUrl(item.Id, options)) : item.ParentLogoImageTag ? (options.tag = item.ParentLogoImageTag, apiClient.getScaledImageUrl(item.ParentLogoItemId, options)) : null + options = options || {}; + options.type = "Logo"; + + if (item.ImageTags && item.ImageTags.Logo) { + options.tag = item.ImageTags.Logo; + return apiClient.getScaledImageUrl(item.Id, options); + } + + if (item.ParentLogoImageTag) { + options.tag = item.ParentLogoImageTag; + return apiClient.getScaledImageUrl(item.ParentLogoItemId, options); + } + + return null; } function setTitle(item, apiClient) { var url = logoImageUrl(item, apiClient, {}); + if (url = null) { var pageTitle = document.querySelector(".pageTitle"); - pageTitle.style.backgroundImage = "url('" + url + "')", pageTitle.classList.add("pageTitleWithLogo"), pageTitle.innerHTML = "" - } else Emby.Page.setTitle("") + pageTitle.style.backgroundImage = "url('" + url + "')"; + pageTitle.classList.add("pageTitleWithLogo"); + pageTitle.innerHTML = ""; + } else { + Emby.Page.setTitle(""); + } } function renderLogo(page, item, apiClient) { var url = logoImageUrl(item, apiClient, { - maxWidth: 400 - }), - detailLogo = page.querySelector(".detailLogo"); - url ? (detailLogo.classList.remove("hide"), detailLogo.classList.add("lazy"), detailLogo.setAttribute("data-src", url), imageLoader.lazyImage(detailLogo)) : detailLogo.classList.add("hide") + maxWidth: 400 + }); + var detailLogo = page.querySelector(".detailLogo"); + + if (url) { + detailLogo.classList.remove("hide"); + detailLogo.classList.add("lazy"); + detailLogo.setAttribute("data-src", url); + imageLoader.lazyImage(detailLogo); + } else { + detailLogo.classList.add("hide"); + } } function showRecordingFields(instance, page, item, user) { if (!instance.currentRecordingFields) { var recordingFieldsElement = page.querySelector(".recordingFields"); - "Program" == item.Type && user.Policy.EnableLiveTvManagement ? require(["recordingFields"], function(recordingFields) { - instance.currentRecordingFields = new recordingFields({ - parent: recordingFieldsElement, - programId: item.Id, - serverId: item.ServerId - }), recordingFieldsElement.classList.remove("hide") - }) : (recordingFieldsElement.classList.add("hide"), recordingFieldsElement.innerHTML = "") + + if ("Program" == item.Type && user.Policy.EnableLiveTvManagement) { + require(["recordingFields"], function (recordingFields) { + instance.currentRecordingFields = new recordingFields({ + parent: recordingFieldsElement, + programId: item.Id, + serverId: item.ServerId + }); + recordingFieldsElement.classList.remove("hide"); + }); + } else { + recordingFieldsElement.classList.add("hide"); + recordingFieldsElement.innerHTML = ""; + } } } @@ -407,145 +717,340 @@ define(["loading", "appRouter", "layoutManager", "connectionManager", "cardBuild function renderLinks(linksElem, item) { var html = []; + if (item.DateCreated && itemHelper.enableDateAddedDisplay(item)) { var dateCreated = datetime.parseISO8601Date(item.DateCreated); - html.push(globalize.translate("AddedOnValue", datetime.toLocaleDateString(dateCreated) + " " + datetime.getDisplayTime(dateCreated))) + html.push(globalize.translate("AddedOnValue", datetime.toLocaleDateString(dateCreated) + " " + datetime.getDisplayTime(dateCreated))); } + var links = []; - if (!layoutManager.tv && (item.HomePageUrl && links.push('' + globalize.translate("ButtonWebsite") + ""), item.ExternalUrls)) + + if (!layoutManager.tv && item.HomePageUrl) { + links.push('' + globalize.translate("ButtonWebsite") + ""); + } + if (item.ExternalUrls) { for (var i = 0, length = item.ExternalUrls.length; i < length; i++) { var url = item.ExternalUrls[i]; - links.push('' + url.Name + "") + links.push('' + url.Name + ""); } - links.length && html.push(globalize.translate("LinksValue", links.join(", "))), linksElem.innerHTML = html.join(", "), html.length ? linksElem.classList.remove("hide") : linksElem.classList.add("hide") + } + + if (links.length) { + html.push(globalize.translate("LinksValue", links.join(", "))); + } + + linksElem.innerHTML = html.join(", "); + + if (html.length) { + linksElem.classList.remove("hide"); + } else { + linksElem.classList.add("hide"); + } } function renderDetailImage(page, elem, item, apiClient, editable, imageLoader, indicators) { - "SeriesTimer" !== item.Type && "Program" !== item.Type || (editable = !1), "Person" !== item.Type ? (elem.classList.add("detailimg-hidemobile"), page.querySelector(".detailPageContent").classList.add("detailPageContent-nodetailimg")) : page.querySelector(".detailPageContent").classList.remove("detailPageContent-nodetailimg"); + if ("SeriesTimer" === item.Type || "Program" === item.Type) { + editable = false; + } + + if ("Person" !== item.Type) { + elem.classList.add("detailimg-hidemobile"); + page.querySelector(".detailPageContent").classList.add("detailPageContent-nodetailimg"); + } else { + page.querySelector(".detailPageContent").classList.remove("detailPageContent-nodetailimg"); + } + var imageTags = item.ImageTags || {}; - item.PrimaryImageTag && (imageTags.Primary = item.PrimaryImageTag); - var url, html = "", - shape = "portrait", - detectRatio = !1; - imageTags.Primary ? (url = apiClient.getScaledImageUrl(item.Id, { - type: "Primary", - tag: item.ImageTags.Primary - }), detectRatio = !0) : item.BackdropImageTags && item.BackdropImageTags.length ? (url = apiClient.getScaledImageUrl(item.Id, { - type: "Backdrop", - tag: item.BackdropImageTags[0] - }), shape = "thumb") : imageTags.Thumb ? (url = apiClient.getScaledImageUrl(item.Id, { - type: "Thumb", - tag: item.ImageTags.Thumb - }), shape = "thumb") : imageTags.Disc ? (url = apiClient.getScaledImageUrl(item.Id, { - type: "Disc", - tag: item.ImageTags.Disc - }), shape = "square") : item.AlbumId && item.AlbumPrimaryImageTag ? (url = apiClient.getScaledImageUrl(item.AlbumId, { - type: "Primary", - tag: item.AlbumPrimaryImageTag - }), shape = "square") : item.SeriesId && item.SeriesPrimaryImageTag ? url = apiClient.getScaledImageUrl(item.SeriesId, { - type: "Primary", - tag: item.SeriesPrimaryImageTag - }) : item.ParentPrimaryImageItemId && item.ParentPrimaryImageTag && (url = apiClient.getScaledImageUrl(item.ParentPrimaryImageItemId, { - type: "Primary", - tag: item.ParentPrimaryImageTag - })), html += '
            ', editable && (html += ""), detectRatio && item.PrimaryImageAspectRatio && (item.PrimaryImageAspectRatio >= 1.48 ? shape = "thumb" : item.PrimaryImageAspectRatio >= .85 && item.PrimaryImageAspectRatio <= 1.34 && (shape = "square")), html += "", editable && (html += ""); + + if (item.PrimaryImageTag) { + imageTags.Primary = item.PrimaryImageTag; + } + + var url; + var html = ""; + var shape = "portrait"; + var detectRatio = false; + + if (imageTags.Primary) { + url = apiClient.getScaledImageUrl(item.Id, { + type: "Primary", + tag: item.ImageTags.Primary + }); + detectRatio = true; + } else if (item.BackdropImageTags && item.BackdropImageTags.length) { + url = apiClient.getScaledImageUrl(item.Id, { + type: "Backdrop", + tag: item.BackdropImageTags[0] + }); + shape = "thumb"; + } else if (imageTags.Thumb) { + url = apiClient.getScaledImageUrl(item.Id, { + type: "Thumb", + tag: item.ImageTags.Thumb + }); + shape = "thumb"; + } else if (imageTags.Disc) { + url = apiClient.getScaledImageUrl(item.Id, { + type: "Disc", + tag: item.ImageTags.Disc + }); + shape = "square"; + } else if (item.AlbumId && item.AlbumPrimaryImageTag) { + url = apiClient.getScaledImageUrl(item.AlbumId, { + type: "Primary", + tag: item.AlbumPrimaryImageTag + }); + shape = "square"; + } else if (item.SeriesId && item.SeriesPrimaryImageTag) { + url = apiClient.getScaledImageUrl(item.SeriesId, { + type: "Primary", + tag: item.SeriesPrimaryImageTag + }); + } else if (item.ParentPrimaryImageItemId && item.ParentPrimaryImageTag) { + url = apiClient.getScaledImageUrl(item.ParentPrimaryImageItemId, { + type: "Primary", + tag: item.ParentPrimaryImageTag + }); + } + + html += '
            '; + + if (editable) { + html += ""; + } + + if (detectRatio && item.PrimaryImageAspectRatio) { + if (item.PrimaryImageAspectRatio >= 1.48) { + shape = "thumb"; + } else if (item.PrimaryImageAspectRatio >= .85 && item.PrimaryImageAspectRatio <= 1.34) { + shape = "square"; + } + } + + html += ""; + + if (editable) { + html += ""; + } + var progressHtml = item.IsFolder || !item.UserData ? "" : indicators.getProgressBarHtml(item); - html += '
            ', progressHtml && (html += progressHtml), html += "
            ", html += "
            ", elem.innerHTML = html, "thumb" == shape ? (elem.classList.add("thumbDetailImageContainer"), elem.classList.remove("portraitDetailImageContainer"), elem.classList.remove("squareDetailImageContainer")) : "square" == shape ? (elem.classList.remove("thumbDetailImageContainer"), elem.classList.remove("portraitDetailImageContainer"), elem.classList.add("squareDetailImageContainer")) : (elem.classList.remove("thumbDetailImageContainer"), elem.classList.add("portraitDetailImageContainer"), elem.classList.remove("squareDetailImageContainer")), url && imageLoader.lazyImage(elem.querySelector("img"), url) + html += '
            '; + + if (progressHtml) { + html += progressHtml; + } + + html += "
            "; + html += "
            "; + elem.innerHTML = html; + + if ("thumb" == shape) { + elem.classList.add("thumbDetailImageContainer"); + elem.classList.remove("portraitDetailImageContainer"); + elem.classList.remove("squareDetailImageContainer"); + } else if ("square" == shape) { + elem.classList.remove("thumbDetailImageContainer"); + elem.classList.remove("portraitDetailImageContainer"); + elem.classList.add("squareDetailImageContainer"); + } else { + elem.classList.remove("thumbDetailImageContainer"); + elem.classList.add("portraitDetailImageContainer"); + elem.classList.remove("squareDetailImageContainer"); + } + + + if (url) { + imageLoader.lazyImage(elem.querySelector("img"), url); + } } function renderImage(page, item, apiClient, user) { - renderDetailImage(page, page.querySelector(".detailImageContainer"), item, apiClient, user.Policy.IsAdministrator && "Photo" != item.MediaType, imageLoader, indicators) + renderDetailImage( + page, + page.querySelector(".detailImageContainer"), + item, + apiClient, + user.Policy.IsAdministrator && "Photo" != item.MediaType, + imageLoader, + indicators + ); } function refreshDetailImageUserData(elem, item) { - elem.querySelector(".detailImageProgressContainer").innerHTML = indicators.getProgressBarHtml(item) + elem.querySelector(".detailImageProgressContainer").innerHTML = indicators.getProgressBarHtml(item); } function refreshImage(page, item, user) { - refreshDetailImageUserData(page.querySelector(".detailImageContainer"), item) + refreshDetailImageUserData(page.querySelector(".detailImageContainer"), item); } function setPeopleHeader(page, item) { - "Audio" == item.MediaType || "MusicAlbum" == item.Type || "Book" == item.MediaType || "Photo" == item.MediaType ? page.querySelector("#peopleHeader").innerHTML = globalize.translate("HeaderPeople") : page.querySelector("#peopleHeader").innerHTML = globalize.translate("HeaderCastAndCrew") + if ("Audio" == item.MediaType || "MusicAlbum" == item.Type || "Book" == item.MediaType || "Photo" == item.MediaType) { + page.querySelector("#peopleHeader").innerHTML = globalize.translate("HeaderPeople"); + } else { + page.querySelector("#peopleHeader").innerHTML = globalize.translate("HeaderCastAndCrew"); + } } function renderNextUp(page, item, user) { var section = page.querySelector(".nextUpSection"); - if ("Series" != item.Type) return void section.classList.add("hide"); + + if ("Series" != item.Type) { + return void section.classList.add("hide"); + } + connectionManager.getApiClient(item.ServerId).getNextUpEpisodes({ SeriesId: item.Id, UserId: user.Id - }).then(function(result) { - result.Items.length ? section.classList.remove("hide") : section.classList.add("hide"); + }).then(function (result) { + if (result.Items.length) { + section.classList.remove("hide"); + } else { + section.classList.add("hide"); + } + var html = cardBuilder.getCardsHtml({ - items: result.Items, - shape: getThumbShape(!1), - showTitle: !0, - displayAsSpecial: "Season" == item.Type && item.IndexNumber, - overlayText: !1, - centerText: !0, - overlayPlayButton: !0 - }), - itemsContainer = section.querySelector(".nextUpItems"); - itemsContainer.innerHTML = html, imageLoader.lazyChildren(itemsContainer) - }) + items: result.Items, + shape: getThumbShape(false), + showTitle: true, + displayAsSpecial: "Season" == item.Type && item.IndexNumber, + overlayText: false, + centerText: true, + overlayPlayButton: true + }); + var itemsContainer = section.querySelector(".nextUpItems"); + itemsContainer.innerHTML = html; + imageLoader.lazyChildren(itemsContainer); + }); } function setInitialCollapsibleState(page, item, apiClient, context, user) { - page.querySelector(".collectionItems").innerHTML = "", "Playlist" == item.Type ? (page.querySelector("#childrenCollapsible").classList.remove("hide"), renderPlaylistItems(page, item, user)) : "Studio" == item.Type || "Person" == item.Type || "Genre" == item.Type || "MusicGenre" == item.Type || "MusicArtist" == item.Type ? (page.querySelector("#childrenCollapsible").classList.remove("hide"), renderItemsByName(page, item, user)) : item.IsFolder ? ("BoxSet" == item.Type && page.querySelector("#childrenCollapsible").classList.add("hide"), renderChildren(page, item)) : page.querySelector("#childrenCollapsible").classList.add("hide"), "Series" == item.Type && renderSeriesSchedule(page, item, user), "Series" == item.Type ? renderNextUp(page, item, user) : page.querySelector(".nextUpSection").classList.add("hide"), renderScenes(page, item), item.SpecialFeatureCount && 0 != item.SpecialFeatureCount && "Series" != item.Type ? (page.querySelector("#specialsCollapsible").classList.remove("hide"), renderSpecials(page, item, user, 6)) : page.querySelector("#specialsCollapsible").classList.add("hide"), renderCast(page, item, context, enableScrollX() ? null : 12), item.PartCount && item.PartCount > 1 ? (page.querySelector("#additionalPartsCollapsible").classList.remove("hide"), renderAdditionalParts(page, item, user)) : page.querySelector("#additionalPartsCollapsible").classList.add("hide"), "MusicAlbum" == item.Type ? renderMusicVideos(page, item, user) : page.querySelector("#musicVideosCollapsible").classList.add("hide") + page.querySelector(".collectionItems").innerHTML = ""; + + if ("Playlist" == item.Type) { + page.querySelector("#childrenCollapsible").classList.remove("hide"); + renderPlaylistItems(page, item, user); + } else if ("Studio" == item.Type || "Person" == item.Type || "Genre" == item.Type || "MusicGenre" == item.Type || "MusicArtist" == item.Type) { + page.querySelector("#childrenCollapsible").classList.remove("hide"); + renderItemsByName(page, item, user); + } else if (item.IsFolder) { + if ("BoxSet" == item.Type) { + page.querySelector("#childrenCollapsible").classList.add("hide"); + } + + renderChildren(page, item); + } else { + page.querySelector("#childrenCollapsible").classList.add("hide"); + } + + if ("Series" == item.Type) { + renderSeriesSchedule(page, item, user); + renderNextUp(page, item, user); + } else { + page.querySelector(".nextUpSection").classList.add("hide"); + } + + renderScenes(page, item); + + if (item.SpecialFeatureCount && 0 != item.SpecialFeatureCount && "Series" != item.Type) { + page.querySelector("#specialsCollapsible").classList.remove("hide"); + renderSpecials(page, item, user, 6); + } else { + page.querySelector("#specialsCollapsible").classList.add("hide"); + } + + renderCast(page, item, context, enableScrollX() ? null : 12); + + if (item.PartCount && item.PartCount > 1) { + page.querySelector("#additionalPartsCollapsible").classList.remove("hide"); + renderAdditionalParts(page, item, user); + } else { + page.querySelector("#additionalPartsCollapsible").classList.add("hide"); + } + + if ("MusicAlbum" == item.Type) { + renderMusicVideos(page, item, user); + } else { + page.querySelector("#musicVideosCollapsible").classList.add("hide"); + } } function renderOverview(elems, item) { for (var i = 0, length = elems.length; i < length; i++) { - var elem = elems[i], - overview = item.Overview || ""; + var elem = elems[i]; + var overview = item.Overview || ""; + if (overview) { - elem.innerHTML = overview, elem.classList.remove("hide"); - for (var anchors = elem.querySelectorAll("a"), j = 0, length2 = anchors.length; j < length2; j++) anchors[j].setAttribute("target", "_blank") - } else elem.innerHTML = "", elem.classList.add("hide") + elem.innerHTML = overview; + elem.classList.remove("hide"); + var anchors = elem.querySelectorAll("a"); + + for (var j = 0, length2 = anchors.length; j < length2; j++) { + anchors[j].setAttribute("target", "_blank"); + } + } else { + elem.innerHTML = ""; + elem.classList.add("hide"); + } } } function renderGenres(page, item, apiClient, context, isStatic) { context = context || inferContext(item); - var type, genres = item.GenreItems || []; + var type; + var genres = item.GenreItems || []; + switch (context) { case "music": type = "MusicGenre"; break; + default: - type = "Genre" + type = "Genre"; + } + + var html = genres.map(function (p) { + return '' + p.Name + ""; + }).join(", "); + var elem = page.querySelector(".genres"); + elem.innerHTML = globalize.translate(genres.length > 1 ? "GenresValue" : "GenreValue", html); + + if (genres.length) { + elem.classList.remove("hide"); + } else { + elem.classList.add("hide"); } - var html = genres.map(function(p) { - return '' + p.Name + "" - }).join(", "), - elem = page.querySelector(".genres"); - elem.innerHTML = genres.length > 1 ? globalize.translate("GenresValue", html) : globalize.translate("GenreValue", html), genres.length ? elem.classList.remove("hide") : elem.classList.add("hide") } function renderDirector(page, item, apiClient, context, isStatic) { - var directors = (item.People || []).filter(function(p) { - return "Director" === p.Type - }), - html = directors.map(function(p) { - return '' + p.Name + "" - }).join(", "), - elem = page.querySelector(".directors"); - elem.innerHTML = directors.length > 1 ? globalize.translate("DirectorsValue", html) : globalize.translate("DirectorValue", html), directors.length ? elem.classList.remove("hide") : elem.classList.add("hide") + var directors = (item.People || []).filter(function (p) { + return "Director" === p.Type; + }); + var html = directors.map(function (p) { + return '' + p.Name + ""; + }).join(", "); + var elem = page.querySelector(".directors"); + elem.innerHTML = globalize.translate(directors.length > 1 ? "DirectorsValue" : "DirectorValue", html); + + if (directors.length) { + elem.classList.remove("hide"); + } else { + elem.classList.add("hide"); + } } function renderDetails(page, item, apiClient, context, isStatic) { @@ -555,8 +1060,8 @@ define(["loading", "appRouter", "layoutManager", "connectionManager", "cardBuild renderDirector(page, item, apiClient, context, isStatic); renderGenres(page, item, apiClient, context, isStatic); renderChannelGuide(page, apiClient, item); - var taglineElement = page.querySelector(".tagline"); + if (item.Taglines && item.Taglines.length) { taglineElement.classList.remove("hide"); taglineElement.innerHTML = item.Taglines[0]; @@ -571,15 +1076,17 @@ define(["loading", "appRouter", "layoutManager", "connectionManager", "cardBuild overview.classList.add("detailsHiddenOnMobile"); externalLinksElem.classList.add("detailsHiddenOnMobile"); } - renderOverview([overview], item); - var i, itemMiscInfo; + renderOverview([overview], item); + var i; + var itemMiscInfo; itemMiscInfo = page.querySelectorAll(".itemMiscInfo-primary"); + for (i = 0; i < itemMiscInfo.length; i++) { mediaInfo.fillPrimaryMediaInfo(itemMiscInfo[i], item, { - interactive: !0, - episodeTitle: !1, - subtitles: !1 + interactive: true, + episodeTitle: false, + subtitles: false }); if (itemMiscInfo[i].innerHTML && "SeriesTimer" !== item.Type) { @@ -589,11 +1096,12 @@ define(["loading", "appRouter", "layoutManager", "connectionManager", "cardBuild } } - itemMiscInfo = page.querySelectorAll(".itemMiscInfo-secondary") + itemMiscInfo = page.querySelectorAll(".itemMiscInfo-secondary"); + for (i = 0; i < itemMiscInfo.length; i++) { mediaInfo.fillSecondaryMediaInfo(itemMiscInfo[i], item, { - interactive: !0 - }) + interactive: true + }); if (itemMiscInfo[i].innerHTML && "SeriesTimer" !== item.Type) { itemMiscInfo[i].classList.remove("hide"); @@ -601,230 +1109,382 @@ define(["loading", "appRouter", "layoutManager", "connectionManager", "cardBuild itemMiscInfo[i].classList.add("hide"); } } - + reloadUserDataButtons(page, item); renderLinks(externalLinksElem, item); renderUserInfo(page, item); renderTags(page, item); - renderSeriesAirTime(page, item, isStatic) + renderSeriesAirTime(page, item, isStatic); } function enableScrollX() { - return browser.mobile && screen.availWidth <= 1e3 + return browser.mobile && screen.availWidth <= 1000; } function getPortraitShape(scrollX) { - return null == scrollX && (scrollX = enableScrollX()), scrollX ? "overflowPortrait" : "portrait" + if (null == scrollX) { + scrollX = enableScrollX(); + } + + return scrollX ? "overflowPortrait" : "portrait"; } function getSquareShape(scrollX) { - return null == scrollX && (scrollX = enableScrollX()), scrollX ? "overflowSquare" : "square" + if (null == scrollX) { + scrollX = enableScrollX(); + } + + return scrollX ? "overflowSquare" : "square"; } function getThumbShape(scrollX) { - return null == scrollX && (scrollX = enableScrollX()), scrollX ? "overflowBackdrop" : "backdrop" + if (null == scrollX) { + scrollX = enableScrollX(); + } + + return scrollX ? "overflowBackdrop" : "backdrop"; } function renderMoreFromSeason(view, item, apiClient) { var section = view.querySelector(".moreFromSeasonSection"); + if (section) { - if ("Episode" !== item.Type || !item.SeasonId || !item.SeriesId) return void section.classList.add("hide"); + if ("Episode" !== item.Type || !item.SeasonId || !item.SeriesId) { + return void section.classList.add("hide"); + } + var userId = apiClient.getCurrentUserId(); apiClient.getEpisodes(item.SeriesId, { SeasonId: item.SeasonId, UserId: userId, Fields: "ItemCounts,PrimaryImageAspectRatio,BasicSyncInfo,CanDelete,MediaSourceCount" - }).then(function(result) { - if (result.Items.length < 2) return void section.classList.add("hide"); - section.classList.remove("hide"), section.querySelector("h2").innerHTML = globalize.translate("MoreFromValue", item.SeasonName); + }).then(function (result) { + if (result.Items.length < 2) { + return void section.classList.add("hide"); + } + + section.classList.remove("hide"); + section.querySelector("h2").innerHTML = globalize.translate("MoreFromValue", item.SeasonName); var itemsContainer = section.querySelector(".itemsContainer"); cardBuilder.buildCards(result.Items, { parentContainer: section, itemsContainer: itemsContainer, shape: "autooverflow", sectionTitleTagName: "h2", - scalable: !0, - showTitle: !0, - overlayText: !1, - centerText: !0, - includeParentInfoInTitle: !1, - allowBottomPadding: !1 + scalable: true, + showTitle: true, + overlayText: false, + centerText: true, + includeParentInfoInTitle: false, + allowBottomPadding: false }); var card = itemsContainer.querySelector('.card[data-id="' + item.Id + '"]'); - card && setTimeout(function() { - section.querySelector(".emby-scroller").toStart(card.previousSibling || card, !0) - }, 100) - }) + + if (card) { + setTimeout(function () { + section.querySelector(".emby-scroller").toStart(card.previousSibling || card, true); + }, 100); + } + }); } } function renderMoreFromArtist(view, item, apiClient) { var section = view.querySelector(".moreFromArtistSection"); + if (section) { if ("MusicArtist" === item.Type) { - if (!apiClient.isMinServerVersion("3.4.1.19")) return void section.classList.add("hide") - } else if ("MusicAlbum" !== item.Type || !item.AlbumArtists || !item.AlbumArtists.length) return void section.classList.add("hide"); + if (!apiClient.isMinServerVersion("3.4.1.19")) { + return void section.classList.add("hide"); + } + } else if ("MusicAlbum" !== item.Type || !item.AlbumArtists || !item.AlbumArtists.length) { + return void section.classList.add("hide"); + } + var query = { IncludeItemTypes: "MusicAlbum", - Recursive: !0, + Recursive: true, ExcludeItemIds: item.Id, SortBy: "ProductionYear,SortName", SortOrder: "Descending" }; - "MusicArtist" === item.Type ? query.ContributingArtistIds = item.Id : apiClient.isMinServerVersion("3.4.1.18") ? query.AlbumArtistIds = item.AlbumArtists[0].Id : query.ArtistIds = item.AlbumArtists[0].Id, apiClient.getItems(apiClient.getCurrentUserId(), query).then(function(result) { - if (!result.Items.length) return void section.classList.add("hide"); - section.classList.remove("hide"), "MusicArtist" === item.Type ? section.querySelector("h2").innerHTML = globalize.translate("HeaderAppearsOn") : section.querySelector("h2").innerHTML = globalize.translate("MoreFromValue", item.AlbumArtists[0].Name), cardBuilder.buildCards(result.Items, { + + if ("MusicArtist" === item.Type) { + query.ContributingArtistIds = item.Id; + } else if (apiClient.isMinServerVersion("3.4.1.18")) { + query.AlbumArtistIds = item.AlbumArtists[0].Id; + } else { + query.ArtistIds = item.AlbumArtists[0].Id; + } + + apiClient.getItems(apiClient.getCurrentUserId(), query).then(function (result) { + if (!result.Items.length) { + return void section.classList.add("hide"); + } + + section.classList.remove("hide"); + + if ("MusicArtist" === item.Type) { + section.querySelector("h2").innerHTML = globalize.translate("HeaderAppearsOn"); + } else { + section.querySelector("h2").innerHTML = globalize.translate("MoreFromValue", item.AlbumArtists[0].Name); + } + + cardBuilder.buildCards(result.Items, { parentContainer: section, itemsContainer: section.querySelector(".itemsContainer"), shape: "autooverflow", sectionTitleTagName: "h2", - scalable: !0, + scalable: true, coverImage: "MusicArtist" === item.Type || "MusicAlbum" === item.Type, - showTitle: !0, - showParentTitle: !1, - centerText: !0, - overlayText: !1, - overlayPlayButton: !0, - showYear: !0 - }) - }) + showTitle: true, + showParentTitle: false, + centerText: true, + overlayText: false, + overlayPlayButton: true, + showYear: true + }); + }); } } function renderSimilarItems(page, item, context) { var similarCollapsible = page.querySelector("#similarCollapsible"); + if (similarCollapsible) { - if ("Movie" != item.Type && "Trailer" != item.Type && "Series" != item.Type && "Program" != item.Type && "Recording" != item.Type && "MusicAlbum" != item.Type && "MusicArtist" != item.Type && "Playlist" != item.Type) return void similarCollapsible.classList.add("hide"); + if ("Movie" != item.Type && "Trailer" != item.Type && "Series" != item.Type && "Program" != item.Type && "Recording" != item.Type && "MusicAlbum" != item.Type && "MusicArtist" != item.Type && "Playlist" != item.Type) { + return void similarCollapsible.classList.add("hide"); + } + similarCollapsible.classList.remove("hide"); - var apiClient = connectionManager.getApiClient(item.ServerId), - options = { - userId: apiClient.getCurrentUserId(), - limit: 12, - fields: "PrimaryImageAspectRatio,UserData,CanDelete" - }; - "MusicAlbum" == item.Type && item.AlbumArtists && item.AlbumArtists.length && (options.ExcludeArtistIds = item.AlbumArtists[0].Id), apiClient.getSimilarItems(item.Id, options).then(function(result) { - if (!result.Items.length) return void similarCollapsible.classList.add("hide"); + var apiClient = connectionManager.getApiClient(item.ServerId); + var options = { + userId: apiClient.getCurrentUserId(), + limit: 12, + fields: "PrimaryImageAspectRatio,UserData,CanDelete" + }; + + if ("MusicAlbum" == item.Type && item.AlbumArtists && item.AlbumArtists.length) { + options.ExcludeArtistIds = item.AlbumArtists[0].Id; + } + + apiClient.getSimilarItems(item.Id, options).then(function (result) { + if (!result.Items.length) { + return void similarCollapsible.classList.add("hide"); + } + similarCollapsible.classList.remove("hide"); var html = ""; html += cardBuilder.getCardsHtml({ items: result.Items, shape: "autooverflow", showParentTitle: "MusicAlbum" == item.Type, - centerText: !0, - showTitle: !0, + centerText: true, + showTitle: true, context: context, - lazy: !0, - showDetailsMenu: !0, + lazy: true, + showDetailsMenu: true, coverImage: "MusicAlbum" == item.Type || "MusicArtist" == item.Type, - overlayPlayButton: !0, - overlayText: !1, + overlayPlayButton: true, + overlayText: false, showYear: "Movie" === item.Type || "Trailer" === item.Type }); var similarContent = similarCollapsible.querySelector(".similarContent"); - similarContent.innerHTML = html, imageLoader.lazyChildren(similarContent) - }) + similarContent.innerHTML = html; + imageLoader.lazyChildren(similarContent); + }); } } function renderSeriesAirTime(page, item, isStatic) { var seriesAirTime = page.querySelector("#seriesAirTime"); - if ("Series" != item.Type) return void seriesAirTime.classList.add("hide"); + if ("Series" != item.Type) { + seriesAirTime.classList.add("hide"); + return; + } var html = ""; - if (item.AirDays && item.AirDays.length && (html += 7 == item.AirDays.length ? "daily" : item.AirDays.map(function(a) { - return a + "s" - }).join(",")), item.AirTime && (html += " at " + item.AirTime), item.Studios.length) - if (isStatic) html += " on " + item.Studios[0].Name; - else { - var context = inferContext(item), - href = appRouter.getRouteUrl(item.Studios[0], { - context: context, - itemType: "Studio", - serverId: item.ServerId - }); - html += ' on ' + item.Studios[0].Name + "" - } html ? (html = ("Ended" == item.Status ? "Aired " : "Airs ") + html, seriesAirTime.innerHTML = html, seriesAirTime.classList.remove("hide")) : seriesAirTime.classList.add("hide") + if (item.AirDays && item.AirDays.length) { + if (7 == item.AirDays.length) { + html += "daily"; + } else { + html += item.AirDays.map(function (a) { + return a + "s"; + }).join(","); + } + } + if (item.AirTime) { + html += " at " + item.AirTime; + } + if (item.Studios.length) { + if (isStatic) { + html += " on " + item.Studios[0].Name; + } else { + var context = inferContext(item); + var href = appRouter.getRouteUrl(item.Studios[0], { + context: context, + itemType: "Studio", + serverId: item.ServerId + }); + html += ' on ' + item.Studios[0].Name + ""; + } + } + if (html) { + html = ("Ended" == item.Status ? "Aired " : "Airs ") + html; + seriesAirTime.innerHTML = html; + seriesAirTime.classList.remove("hide"); + } else { + seriesAirTime.classList.add("hide"); + } } function renderTags(page, item) { - var itemTags = page.querySelector(".itemTags"), - tagElements = [], - tags = item.Tags || []; - "Program" === item.Type && (tags = []); - for (var i = 0, length = tags.length; i < length; i++) tagElements.push(tags[i]); - tagElements.length ? (itemTags.innerHTML = globalize.translate("TagsValue", tagElements.join(", ")), itemTags.classList.remove("hide")) : (itemTags.innerHTML = "", itemTags.classList.add("hide")) + var itemTags = page.querySelector(".itemTags"); + var tagElements = []; + var tags = item.Tags || []; + + if ("Program" === item.Type) { + tags = []; + } + + for (var i = 0, length = tags.length; i < length; i++) { + tagElements.push(tags[i]); + } + + if (tagElements.length) { + itemTags.innerHTML = globalize.translate("TagsValue", tagElements.join(", ")); + itemTags.classList.remove("hide"); + } else { + itemTags.innerHTML = ""; + itemTags.classList.add("hide"); + } } function renderChildren(page, item) { - var fields = "ItemCounts,PrimaryImageAspectRatio,BasicSyncInfo,CanDelete,MediaSourceCount", - query = { - ParentId: item.Id, + var fields = "ItemCounts,PrimaryImageAspectRatio,BasicSyncInfo,CanDelete,MediaSourceCount"; + var query = { + ParentId: item.Id, + Fields: fields + }; + + if ("BoxSet" !== item.Type) { + query.SortBy = "SortName"; + } + + var promise; + var apiClient = connectionManager.getApiClient(item.ServerId); + var userId = apiClient.getCurrentUserId(); + + if ("Series" == item.Type) { + promise = apiClient.getSeasons(item.Id, { + userId: userId, Fields: fields - }; - "BoxSet" !== item.Type && (query.SortBy = "SortName"); - var promise, apiClient = connectionManager.getApiClient(item.ServerId), - userId = apiClient.getCurrentUserId(); - "Series" == item.Type ? promise = apiClient.getSeasons(item.Id, { - userId: userId, - Fields: fields - }) : "Season" == item.Type ? (fields += ",Overview", promise = apiClient.getEpisodes(item.SeriesId, { - seasonId: item.Id, - userId: userId, - Fields: fields - })) : "MusicAlbum" == item.Type || "MusicArtist" == item.Type && (query.SortBy = "ProductionYear,SortName"), promise = promise || apiClient.getItems(apiClient.getCurrentUserId(), query), promise.then(function(result) { - var html = "", - scrollX = !1, - isList = !1, - childrenItemsContainer = page.querySelector(".childrenItemsContainer"); - if ("MusicAlbum" == item.Type) html = listView.getListViewHtml({ - items: result.Items, - smallIcon: !0, - showIndex: !0, - index: "disc", - showIndexNumberLeft: !0, - playFromHere: !0, - action: "playallfromhere", - image: !1, - artist: "auto", - containerAlbumArtists: item.AlbumArtists, - addToListButton: !0 - }), isList = !0; - else if ("Series" == item.Type) scrollX = enableScrollX(), html = cardBuilder.getCardsHtml({ - items: result.Items, - shape: getPortraitShape(), - showTitle: !0, - centerText: !0, - lazy: !0, - overlayPlayButton: !0, - allowBottomPadding: !scrollX }); - else if ("Season" == item.Type || "Episode" == item.Type) { - if ("Episode" === item.Type || (isList = !0), scrollX = "Episode" == item.Type, result.Items.length < 2 && "Episode" === item.Type) return; - "Episode" === item.Type ? html = cardBuilder.getCardsHtml({ + } else if ("Season" == item.Type) { + fields += ",Overview"; + promise = apiClient.getEpisodes(item.SeriesId, { + seasonId: item.Id, + userId: userId, + Fields: fields + }); + } else if ("MusicArtist" == item.Type) { + query.SortBy = "ProductionYear,SortName"; + } + + promise = promise || apiClient.getItems(apiClient.getCurrentUserId(), query); + promise.then(function (result) { + var html = ""; + var scrollX = false; + var isList = false; + var childrenItemsContainer = page.querySelector(".childrenItemsContainer"); + + if ("MusicAlbum" == item.Type) { + html = listView.getListViewHtml({ items: result.Items, - shape: getThumbShape(scrollX), - showTitle: !0, - displayAsSpecial: "Season" == item.Type && item.IndexNumber, - playFromHere: !0, - overlayText: !0, - lazy: !0, - showDetailsMenu: !0, - overlayPlayButton: !0, - allowBottomPadding: !scrollX, - includeParentInfoInTitle: !1 - }) : "Season" === item.Type && (html = listView.getListViewHtml({ + smallIcon: true, + showIndex: true, + index: "disc", + showIndexNumberLeft: true, + playFromHere: true, + action: "playallfromhere", + image: false, + artist: "auto", + containerAlbumArtists: item.AlbumArtists, + addToListButton: true + }); + isList = true; + } else if ("Series" == item.Type) { + scrollX = enableScrollX(); + html = cardBuilder.getCardsHtml({ items: result.Items, - showIndexNumber: !1, - enableOverview: !0, - imageSize: "large", - enableSideMediaInfo: !1, - highlight: !1, - action: layoutManager.tv ? "resume" : "none", - infoButton: !0, - imagePlayButton: !0, - includeParentInfoInTitle: !1 - })) + shape: getPortraitShape(), + showTitle: true, + centerText: true, + lazy: true, + overlayPlayButton: true, + allowBottomPadding: !scrollX + }); + } else if ("Season" == item.Type || "Episode" == item.Type) { + if ("Episode" !== item.Type) { + isList = true; + } + scrollX = "Episode" == item.Type; + if (result.Items.length < 2 && "Episode" === item.Type) { + return; + } + + if ("Episode" === item.Type) { + html = cardBuilder.getCardsHtml({ + items: result.Items, + shape: getThumbShape(scrollX), + showTitle: true, + displayAsSpecial: "Season" == item.Type && item.IndexNumber, + playFromHere: true, + overlayText: true, + lazy: true, + showDetailsMenu: true, + overlayPlayButton: true, + allowBottomPadding: !scrollX, + includeParentInfoInTitle: false + }); + } else if ("Season" === item.Type) { + html = listView.getListViewHtml({ + items: result.Items, + showIndexNumber: false, + enableOverview: true, + imageSize: "large", + enableSideMediaInfo: false, + highlight: false, + action: layoutManager.tv ? "resume" : "none", + infoButton: true, + imagePlayButton: true, + includeParentInfoInTitle: false + }); + } } - if ("BoxSet" !== item.Type && page.querySelector("#childrenCollapsible").classList.remove("hide"), scrollX ? (childrenItemsContainer.classList.add("scrollX"), childrenItemsContainer.classList.add("hiddenScrollX"), childrenItemsContainer.classList.remove("vertical-wrap"), childrenItemsContainer.classList.remove("vertical-list")) : (childrenItemsContainer.classList.remove("scrollX"), childrenItemsContainer.classList.remove("hiddenScrollX"), childrenItemsContainer.classList.remove("smoothScrollX"), isList ? (childrenItemsContainer.classList.add("vertical-list"), childrenItemsContainer.classList.remove("vertical-wrap")) : (childrenItemsContainer.classList.add("vertical-wrap"), childrenItemsContainer.classList.remove("vertical-list"))), childrenItemsContainer.innerHTML = html, imageLoader.lazyChildren(childrenItemsContainer), "BoxSet" == item.Type) { + + if ("BoxSet" !== item.Type) { + page.querySelector("#childrenCollapsible").classList.remove("hide"); + } + if (scrollX) { + childrenItemsContainer.classList.add("scrollX"); + childrenItemsContainer.classList.add("hiddenScrollX"); + childrenItemsContainer.classList.remove("vertical-wrap"); + childrenItemsContainer.classList.remove("vertical-list"); + } else { + childrenItemsContainer.classList.remove("scrollX"); + childrenItemsContainer.classList.remove("hiddenScrollX"); + childrenItemsContainer.classList.remove("smoothScrollX"); + if (isList) { + childrenItemsContainer.classList.add("vertical-list"); + childrenItemsContainer.classList.remove("vertical-wrap"); + } else { + childrenItemsContainer.classList.add("vertical-wrap"); + childrenItemsContainer.classList.remove("vertical-list"); + } + } + childrenItemsContainer.innerHTML = html; + imageLoader.lazyChildren(childrenItemsContainer); + if ("BoxSet" == item.Type) { var collectionItemTypes = [{ name: globalize.translate("HeaderVideos"), mediaType: "Video" @@ -838,175 +1498,276 @@ define(["loading", "appRouter", "layoutManager", "connectionManager", "cardBuild name: globalize.translate("HeaderBooks"), type: "Book" }]; - renderCollectionItems(page, item, collectionItemTypes, result.Items) + renderCollectionItems(page, item, collectionItemTypes, result.Items); } - }), "Season" == item.Type ? page.querySelector("#childrenTitle").innerHTML = globalize.translate("HeaderEpisodes") : "Series" == item.Type ? page.querySelector("#childrenTitle").innerHTML = globalize.translate("HeaderSeasons") : "MusicAlbum" == item.Type ? page.querySelector("#childrenTitle").innerHTML = globalize.translate("HeaderTracks") : page.querySelector("#childrenTitle").innerHTML = globalize.translate("HeaderItems"), "MusicAlbum" == item.Type || "Season" == item.Type ? (page.querySelector(".childrenSectionHeader").classList.add("hide"), page.querySelector("#childrenCollapsible").classList.add("verticalSection-extrabottompadding")) : page.querySelector(".childrenSectionHeader").classList.remove("hide") + }); + + if ("Season" == item.Type) { + page.querySelector("#childrenTitle").innerHTML = globalize.translate("HeaderEpisodes"); + } else if ("Series" == item.Type) { + page.querySelector("#childrenTitle").innerHTML = globalize.translate("HeaderSeasons"); + } else if ("MusicAlbum" == item.Type) { + page.querySelector("#childrenTitle").innerHTML = globalize.translate("HeaderTracks"); + } else { + page.querySelector("#childrenTitle").innerHTML = globalize.translate("HeaderItems"); + } + + if ("MusicAlbum" == item.Type || "Season" == item.Type) { + page.querySelector(".childrenSectionHeader").classList.add("hide"); + page.querySelector("#childrenCollapsible").classList.add("verticalSection-extrabottompadding"); + } else { + page.querySelector(".childrenSectionHeader").classList.remove("hide"); + } } function renderItemsByName(page, item, user) { - require("scripts/itembynamedetailpage".split(","), function() { - window.ItemsByName.renderItems(page, item) - }) + require("scripts/itembynamedetailpage".split(","), function () { + window.ItemsByName.renderItems(page, item); + }); } function renderPlaylistItems(page, item, user) { - require("scripts/playlistedit".split(","), function() { - PlaylistViewer.render(page, item) - }) + require("scripts/playlistedit".split(","), function () { + PlaylistViewer.render(page, item); + }); } function renderProgramsForChannel(page, result) { - for (var html = "", currentItems = [], currentStartDate = null, i = 0, length = result.Items.length; i < length; i++) { - var item = result.Items[i], - itemStartDate = datetime.parseISO8601Date(item.StartDate); - currentStartDate && currentStartDate.toDateString() === itemStartDate.toDateString() || (currentItems.length && (html += '
            ', html += '

            ' + datetime.toLocaleDateString(currentStartDate, { + var html = ""; + var currentItems = []; + var currentStartDate = null; + + for (var i = 0, length = result.Items.length; i < length; i++) { + var item = result.Items[i]; + var itemStartDate = datetime.parseISO8601Date(item.StartDate); + + if (!(currentStartDate && currentStartDate.toDateString() === itemStartDate.toDateString())) { + if (currentItems.length) { + html += '
            '; + html += '

            ' + datetime.toLocaleDateString(currentStartDate, { + weekday: "long", + month: "long", + day: "numeric" + }) + "

            "; + html += '
            ' + listView.getListViewHtml({ + items: currentItems, + enableUserDataButtons: false, + showParentTitle: true, + image: false, + showProgramTime: true, + mediaInfo: false, + parentTitleWithTitle: true + }) + "
            "; + } + + currentStartDate = itemStartDate; + currentItems = []; + } + + currentItems.push(item); + } + + if (currentItems.length) { + html += '
            '; + html += '

            ' + datetime.toLocaleDateString(currentStartDate, { weekday: "long", month: "long", day: "numeric" - }) + "

            ", html += '
            ' + listView.getListViewHtml({ + }) + "

            "; + html += '
            ' + listView.getListViewHtml({ items: currentItems, - enableUserDataButtons: !1, - showParentTitle: !0, - image: !1, - showProgramTime: !0, - mediaInfo: !1, - parentTitleWithTitle: !0 - }) + "
            "), currentStartDate = itemStartDate, currentItems = []), currentItems.push(item) + enableUserDataButtons: false, + showParentTitle: true, + image: false, + showProgramTime: true, + mediaInfo: false, + parentTitleWithTitle: true + }) + "
            "; } - currentItems.length && (html += '
            ', html += '

            ' + datetime.toLocaleDateString(currentStartDate, { - weekday: "long", - month: "long", - day: "numeric" - }) + "

            ", html += '
            ' + listView.getListViewHtml({ - items: currentItems, - enableUserDataButtons: !1, - showParentTitle: !0, - image: !1, - showProgramTime: !0, - mediaInfo: !1, - parentTitleWithTitle: !0 - }) + "
            "), page.querySelector(".programGuide").innerHTML = html + + page.querySelector(".programGuide").innerHTML = html; } function renderChannelGuide(page, apiClient, item) { - "TvChannel" === item.Type && (page.querySelector(".programGuideSection").classList.remove("hide"), apiClient.getLiveTvPrograms({ - ChannelIds: item.Id, - UserId: apiClient.getCurrentUserId(), - HasAired: !1, - SortBy: "StartDate", - EnableTotalRecordCount: !1, - EnableImages: !1, - ImageTypeLimit: 0, - EnableUserData: !1 - }).then(function(result) { - renderProgramsForChannel(page, result) - })) + if ("TvChannel" === item.Type) { + page.querySelector(".programGuideSection").classList.remove("hide"); + apiClient.getLiveTvPrograms({ + ChannelIds: item.Id, + UserId: apiClient.getCurrentUserId(), + HasAired: false, + SortBy: "StartDate", + EnableTotalRecordCount: false, + EnableImages: false, + ImageTypeLimit: 0, + EnableUserData: false + }).then(function (result) { + renderProgramsForChannel(page, result); + }); + } } function renderSeriesSchedule(page, item, user) { var apiClient = connectionManager.getApiClient(item.ServerId); apiClient.getLiveTvPrograms({ UserId: apiClient.getCurrentUserId(), - HasAired: !1, + HasAired: false, SortBy: "StartDate", - EnableTotalRecordCount: !1, - EnableImages: !1, + EnableTotalRecordCount: false, + EnableImages: false, ImageTypeLimit: 0, Limit: 50, - EnableUserData: !1, + EnableUserData: false, LibrarySeriesId: item.Id - }).then(function(result) { - result.Items.length ? page.querySelector("#seriesScheduleSection").classList.remove("hide") : page.querySelector("#seriesScheduleSection").classList.add("hide"), page.querySelector("#seriesScheduleList").innerHTML = listView.getListViewHtml({ + }).then(function (result) { + if (result.Items.length) { + page.querySelector("#seriesScheduleSection").classList.remove("hide"); + } else { + page.querySelector("#seriesScheduleSection").classList.add("hide"); + } + + page.querySelector("#seriesScheduleList").innerHTML = listView.getListViewHtml({ items: result.Items, - enableUserDataButtons: !1, - showParentTitle: !1, - image: !1, - showProgramDateTime: !0, - mediaInfo: !1, - showTitle: !0, - moreButton: !1, + enableUserDataButtons: false, + showParentTitle: false, + image: false, + showProgramDateTime: true, + mediaInfo: false, + showTitle: true, + moreButton: false, action: "programdialog" - }), loading.hide() - }) + }); + loading.hide(); + }); } function inferContext(item) { - return "Movie" === item.Type || "BoxSet" === item.Type ? "movies" : "Series" === item.Type || "Season" === item.Type || "Episode" === item.Type ? "tvshows" : "MusicArtist" === item.Type || "MusicAlbum" === item.Type || "Audio" === item.Type || "AudioBook" === item.Type ? "music" : "Program" === item.Type ? "livetv" : null + if ("Movie" === item.Type || "BoxSet" === item.Type) { + return "movies"; + } + + if ("Series" === item.Type || "Season" === item.Type || "Episode" === item.Type) { + return "tvshows"; + } + + if ("MusicArtist" === item.Type || "MusicAlbum" === item.Type || "Audio" === item.Type || "AudioBook" === item.Type) { + return "music"; + } + + if ("Program" === item.Type) { + return "livetv"; + } + + return null; } function filterItemsByCollectionItemType(items, typeInfo) { - return items.filter(function(item) { - return typeInfo.mediaType ? item.MediaType == typeInfo.mediaType : item.Type == typeInfo.type - }) + return items.filter(function (item) { + if (typeInfo.mediaType) { + return item.MediaType == typeInfo.mediaType; + } + + return item.Type == typeInfo.type; + }); } function canPlaySomeItemInCollection(items) { var i = 0; + for (length = items.length; i < length; i++) { if (playbackManager.canPlay(items[i])) { return true; } } + return false; } function renderCollectionItems(page, parentItem, types, items) { page.querySelector(".collectionItems").innerHTML = ""; - var i, length; + var i; + var length; + for (i = 0, length = types.length; i < length; i++) { - var type = types[i], - typeItems = filterItemsByCollectionItemType(items, type); - typeItems.length && renderCollectionItemType(page, parentItem, type, typeItems) + var type = types[i]; + var typeItems = filterItemsByCollectionItemType(items, type); + + if (typeItems.length) { + renderCollectionItemType(page, parentItem, type, typeItems); + } } + var otherType = { - name: globalize.translate("HeaderOtherItems") - }, - otherTypeItems = items.filter(function(curr) { - return !types.filter(function(t) { - return filterItemsByCollectionItemType([curr], t).length > 0 - }).length - }); - otherTypeItems.length && renderCollectionItemType(page, parentItem, otherType, otherTypeItems), items.length || renderCollectionItemType(page, parentItem, { - name: globalize.translate("HeaderItems") - }, items); - var containers = page.querySelectorAll(".collectionItemsContainer"), - notifyRefreshNeeded = function() { - renderChildren(page, parentItem) - }; - for (i = 0, length = containers.length; i < length; i++) containers[i].notifyRefreshNeeded = notifyRefreshNeeded + name: globalize.translate("HeaderOtherItems") + }; + var otherTypeItems = items.filter(function (curr) { + return !types.filter(function (t) { + return filterItemsByCollectionItemType([curr], t).length > 0; + }).length; + }); + + if (otherTypeItems.length) { + renderCollectionItemType(page, parentItem, otherType, otherTypeItems); + } + + if (!items.length) { + renderCollectionItemType(page, parentItem, { + name: globalize.translate("HeaderItems") + }, items); + } + + var containers = page.querySelectorAll(".collectionItemsContainer"); + + var notifyRefreshNeeded = function () { + renderChildren(page, parentItem); + }; + + for (i = 0, length = containers.length; i < length; i++) { + containers[i].notifyRefreshNeeded = notifyRefreshNeeded; + } // if nothing in the collection can be played hide play and shuffle buttons if (!canPlaySomeItemInCollection(items)) { hideAll(page, "btnPlay", false); hideAll(page, "btnShuffle", false); - } + } } function renderCollectionItemType(page, parentItem, type, items) { var html = ""; - html += '
            ', html += '
            ', html += '

            ', html += "" + type.name + "", html += "

            ", html += '', html += "
            ", html += '
            '; - var shape = "MusicAlbum" == type.type ? getSquareShape(!1) : getPortraitShape(!1); + html += '
            '; + html += '
            '; + html += '

            '; + html += "" + type.name + ""; + html += "

            "; + html += ''; + html += "
            "; + html += '
            '; + var shape = "MusicAlbum" == type.type ? getSquareShape(false) : getPortraitShape(false); html += cardBuilder.getCardsHtml({ items: items, shape: shape, - showTitle: !0, - centerText: !0, - lazy: !0, - showDetailsMenu: !0, - overlayMoreButton: !0, - showAddToCollection: !1, - showRemoveFromCollection: !0, + showTitle: true, + centerText: true, + lazy: true, + showDetailsMenu: true, + overlayMoreButton: true, + showAddToCollection: false, + showRemoveFromCollection: true, collectionId: parentItem.Id - }), html += "
            ", html += "
            "; + }); + html += "
            "; + html += "
            "; var collectionItems = page.querySelector(".collectionItems"); - collectionItems.insertAdjacentHTML("beforeend", html), imageLoader.lazyChildren(collectionItems), collectionItems.querySelector(".btnAddToCollection").addEventListener("click", function() { - require(["alert"], function(alert) { + collectionItems.insertAdjacentHTML("beforeend", html); + imageLoader.lazyChildren(collectionItems); + collectionItems.querySelector(".btnAddToCollection").addEventListener("click", function () { + require(["alert"], function (alert) { alert({ text: globalize.translate("AddItemToCollectionHelp"), html: globalize.translate("AddItemToCollectionHelp") + '

            ' + globalize.translate("ButtonLearnMore") + "" - }) - }) - }) + }); + }); + }); } function renderMusicVideos(page, item, user) { @@ -1014,295 +1775,362 @@ define(["loading", "appRouter", "layoutManager", "connectionManager", "cardBuild SortBy: "SortName", SortOrder: "Ascending", IncludeItemTypes: "MusicVideo", - Recursive: !0, + Recursive: true, Fields: "PrimaryImageAspectRatio,BasicSyncInfo,CanDelete,MediaSourceCount", AlbumIds: item.Id - }).then(function(result) { + }).then(function (result) { if (result.Items.length) { page.querySelector("#musicVideosCollapsible").classList.remove("hide"); var musicVideosContent = page.querySelector(".musicVideosContent"); - musicVideosContent.innerHTML = getVideosHtml(result.Items, user), imageLoader.lazyChildren(musicVideosContent) - } else page.querySelector("#musicVideosCollapsible").classList.add("hide") - }) + musicVideosContent.innerHTML = getVideosHtml(result.Items, user); + imageLoader.lazyChildren(musicVideosContent); + } else { + page.querySelector("#musicVideosCollapsible").classList.add("hide"); + } + }); } function renderAdditionalParts(page, item, user) { - connectionManager.getApiClient(item.ServerId).getAdditionalVideoParts(user.Id, item.Id).then(function(result) { + connectionManager.getApiClient(item.ServerId).getAdditionalVideoParts(user.Id, item.Id).then(function (result) { if (result.Items.length) { page.querySelector("#additionalPartsCollapsible").classList.remove("hide"); var additionalPartsContent = page.querySelector("#additionalPartsContent"); - additionalPartsContent.innerHTML = getVideosHtml(result.Items, user), imageLoader.lazyChildren(additionalPartsContent) - } else page.querySelector("#additionalPartsCollapsible").classList.add("hide") - }) + additionalPartsContent.innerHTML = getVideosHtml(result.Items, user); + imageLoader.lazyChildren(additionalPartsContent); + } else { + page.querySelector("#additionalPartsCollapsible").classList.add("hide"); + } + }); } function renderScenes(page, item) { var chapters = item.Chapters || []; + if (chapters.length && !chapters[0].ImageTag && (chapters = []), chapters.length) { page.querySelector("#scenesCollapsible").classList.remove("hide"); var scenesContent = page.querySelector("#scenesContent"); - require(["chaptercardbuilder"], function(chaptercardbuilder) { + + require(["chaptercardbuilder"], function (chaptercardbuilder) { chaptercardbuilder.buildChapterCards(item, chapters, { itemsContainer: scenesContent, width: 400, backdropShape: "overflowBackdrop", squareShape: "overflowSquare" - }) - }) - } else page.querySelector("#scenesCollapsible").classList.add("hide") + }); + }); + } else { + page.querySelector("#scenesCollapsible").classList.add("hide"); + } } function getVideosHtml(items, user, limit, moreButtonClass) { var html = cardBuilder.getCardsHtml({ items: items, shape: "auto", - showTitle: !0, + showTitle: true, action: "play", - overlayText: !1, - centerText: !0, - showRuntime: !0 + overlayText: false, + centerText: true, + showRuntime: true }); - return limit && items.length > limit && (html += '

            "), html + + if (limit && items.length > limit) { + html += '

            "; + } + + return html; } function renderSpecials(page, item, user, limit) { - connectionManager.getApiClient(item.ServerId).getSpecialFeatures(user.Id, item.Id).then(function(specials) { + connectionManager.getApiClient(item.ServerId).getSpecialFeatures(user.Id, item.Id).then(function (specials) { var specialsContent = page.querySelector("#specialsContent"); - specialsContent.innerHTML = getVideosHtml(specials, user, limit, "moreSpecials"), imageLoader.lazyChildren(specialsContent) - }) + specialsContent.innerHTML = getVideosHtml(specials, user, limit, "moreSpecials"); + imageLoader.lazyChildren(specialsContent); + }); } function renderCast(page, item, context, limit, isStatic) { - var people = (item.People || []).filter(function(p) { - return "Director" !== p.Type + var people = (item.People || []).filter(function (p) { + return "Director" !== p.Type; }); - if (!people.length) return void page.querySelector("#castCollapsible").classList.add("hide"); + + if (!people.length) { + return void page.querySelector("#castCollapsible").classList.add("hide"); + } + page.querySelector("#castCollapsible").classList.remove("hide"); var castContent = page.querySelector("#castContent"); - require(["peoplecardbuilder"], function(peoplecardbuilder) { + + require(["peoplecardbuilder"], function (peoplecardbuilder) { peoplecardbuilder.buildPeopleCards(people, { itemsContainer: castContent, - coverImage: !0, + coverImage: true, serverId: item.ServerId, width: 160, shape: getPortraitShape() - }) - }) + }); + }); } function itemDetailPage() { var self = this; - self.setInitialCollapsibleState = setInitialCollapsibleState, self.renderDetails = renderDetails, self.renderCast = renderCast + self.setInitialCollapsibleState = setInitialCollapsibleState; + self.renderDetails = renderDetails; + self.renderCast = renderCast; } function bindAll(view, selector, eventName, fn) { - var i, length, elems = view.querySelectorAll(selector); - for (i = 0, length = elems.length; i < length; i++) elems[i].addEventListener(eventName, fn) + var i; + var length; + var elems = view.querySelectorAll(selector); + + for (i = 0, length = elems.length; i < length; i++) { + elems[i].addEventListener(eventName, fn); + } } function onTrackSelectionsSubmit(e) { - return e.preventDefault(), !1 + e.preventDefault(); + return false; } - return window.ItemDetailPage = new itemDetailPage, - function(view, params) { - function reload(instance, page, params) { - loading.show(); - var apiClient = params.serverId ? connectionManager.getApiClient(params.serverId) : ApiClient, - promises = [getPromise(apiClient, params), apiClient.getCurrentUser()]; - Promise.all(promises).then(function(responses) { - var item = responses[0], - user = responses[1]; - currentItem = item, reloadFromItem(instance, page, params, item, user) - }) - } - function splitVersions(instance, page, apiClient, params) { - require(["confirm"], function(confirm) { - confirm("Are you sure you wish to split the media sources into separate items?", "Split Media Apart").then(function() { - loading.show(), apiClient.ajax({ - type: "DELETE", - url: apiClient.getUrl("Videos/" + params.id + "/AlternateSources") - }).then(function() { - loading.hide(), reload(instance, page, params) - }) - }) - }) - } + window.ItemDetailPage = new itemDetailPage(); + return function (view, params) { + function reload(instance, page, params) { + loading.show(); + var apiClient = params.serverId ? connectionManager.getApiClient(params.serverId) : ApiClient; + var promises = [getPromise(apiClient, params), apiClient.getCurrentUser()]; + Promise.all(promises).then(function (responses) { + var item = responses[0]; + var user = responses[1]; + currentItem = item; + reloadFromItem(instance, page, params, item, user); + }); + } - function getPlayOptions(startPosition) { - var audioStreamIndex = view.querySelector(".selectAudio").value || null; - return { - startPositionTicks: startPosition, - mediaSourceId: view.querySelector(".selectSource").value, - audioStreamIndex: audioStreamIndex, - subtitleStreamIndex: view.querySelector(".selectSubtitles").value - } - } + function splitVersions(instance, page, apiClient, params) { + require(["confirm"], function (confirm) { + confirm("Are you sure you wish to split the media sources into separate items?", "Split Media Apart").then(function () { + loading.show(); + apiClient.ajax({ + type: "DELETE", + url: apiClient.getUrl("Videos/" + params.id + "/AlternateSources") + }).then(function () { + loading.hide(); + reload(instance, page, params); + }); + }); + }); + } - function playItem(item, startPosition) { - var playOptions = getPlayOptions(startPosition); - playOptions.items = [item], playbackManager.play(playOptions) - } + function getPlayOptions(startPosition) { + var audioStreamIndex = view.querySelector(".selectAudio").value || null; + return { + startPositionTicks: startPosition, + mediaSourceId: view.querySelector(".selectSource").value, + audioStreamIndex: audioStreamIndex, + subtitleStreamIndex: view.querySelector(".selectSubtitles").value + }; + } - function playTrailer(page) { - playbackManager.playTrailers(currentItem) - } + function playItem(item, startPosition) { + var playOptions = getPlayOptions(startPosition); + playOptions.items = [item]; + playbackManager.play(playOptions); + } - function playCurrentItem(button, mode) { - var item = currentItem; - if ("Program" === item.Type) { - var apiClient = connectionManager.getApiClient(item.ServerId); - return void apiClient.getLiveTvChannel(item.ChannelId, apiClient.getCurrentUserId()).then(function(channel) { - playbackManager.play({ - items: [channel] - }) - }) - } - playItem(item, item.UserData && "resume" === mode ? item.UserData.PlaybackPositionTicks : 0) - } + function playTrailer(page) { + playbackManager.playTrailers(currentItem); + } - function onPlayClick() { - playCurrentItem(this, this.getAttribute("data-mode")) - } + function playCurrentItem(button, mode) { + var item = currentItem; - function onInstantMixClick() { - playbackManager.instantMix(currentItem) - } - - function onShuffleClick() { - playbackManager.shuffle(currentItem) - } - - function onDeleteClick() { - require(["deleteHelper"], function(deleteHelper) { - deleteHelper.deleteItem({ - item: currentItem, - navigate: !0 - }) - }) - } - - function onCancelSeriesTimerClick() { - require(["recordingHelper"], function(recordingHelper) { - recordingHelper.cancelSeriesTimerWithConfirmation(currentItem.Id, currentItem.ServerId).then(function() { - Dashboard.navigate("livetv.html") - }) - }) - } - - function onCancelTimerClick() { - require(["recordingHelper"], function(recordingHelper) { - recordingHelper.cancelTimer(connectionManager.getApiClient(currentItem.ServerId), currentItem.TimerId).then(function() { - reload(self, view, params) - }) - }) - } - - function onPlayTrailerClick() { - playTrailer(view) - } - - function onDownloadChange() { - reload(self, view, params) - } - - function onDownloadClick() { - require(['fileDownloader'], function (fileDownloader) { - var downloadHref = apiClient.getItemDownloadUrl(currentItem.Id); - fileDownloader.download([{ - url: downloadHref, - itemId: currentItem.Id, - serverId: currentItem.serverId - }]); + if ("Program" === item.Type) { + var apiClient = connectionManager.getApiClient(item.ServerId); + return void apiClient.getLiveTvChannel(item.ChannelId, apiClient.getCurrentUserId()).then(function (channel) { + playbackManager.play({ + items: [channel] + }); }); } - function onMoreCommandsClick() { - var button = this; - apiClient.getCurrentUser().then(function(user) { - itemContextMenu.show(getContextMenuOptions(currentItem, user, button)).then(function(result) { - result.deleted ? appRouter.goHome() : result.updated && reload(self, view, params) - }) - }) - } + playItem(item, item.UserData && "resume" === mode ? item.UserData.PlaybackPositionTicks : 0); + } - function onPlayerChange() { - renderTrackSelections(view, self, currentItem), setTrailerButtonVisibility(view, currentItem) - } + function onPlayClick() { + playCurrentItem(this, this.getAttribute("data-mode")); + } - function editImages() { - return new Promise(function(resolve, reject) { - require(["imageEditor"], function(imageEditor) { - imageEditor.show({ - itemId: currentItem.Id, - serverId: currentItem.ServerId - }).then(resolve, reject) - }) - }) - } + function onInstantMixClick() { + playbackManager.instantMix(currentItem); + } - function onWebSocketMessage(e, data) { - var msg = data; - if ("UserDataChanged" === msg.MessageType && currentItem && msg.Data.UserId == apiClient.getCurrentUserId()) { - var key = currentItem.UserData.Key, - userData = msg.Data.UserDataList.filter(function(u) { - return u.Key == key - })[0]; - userData && (currentItem.UserData = userData, reloadPlayButtons(view, currentItem), apiClient.getCurrentUser().then(function(user) { - refreshImage(view, currentItem, user) - })) + function onShuffleClick() { + playbackManager.shuffle(currentItem); + } + + function onDeleteClick() { + require(["deleteHelper"], function (deleteHelper) { + deleteHelper.deleteItem({ + item: currentItem, + navigate: true + }); + }); + } + + function onCancelSeriesTimerClick() { + require(["recordingHelper"], function (recordingHelper) { + recordingHelper.cancelSeriesTimerWithConfirmation(currentItem.Id, currentItem.ServerId).then(function () { + Dashboard.navigate("livetv.html"); + }); + }); + } + + function onCancelTimerClick() { + require(["recordingHelper"], function (recordingHelper) { + recordingHelper.cancelTimer(connectionManager.getApiClient(currentItem.ServerId), currentItem.TimerId).then(function () { + reload(self, view, params); + }); + }); + } + + function onPlayTrailerClick() { + playTrailer(view); + } + + function onDownloadChange() { + reload(self, view, params); + } + + function onDownloadClick() { + require(['fileDownloader'], function (fileDownloader) { + var downloadHref = apiClient.getItemDownloadUrl(currentItem.Id); + fileDownloader.download([{ + url: downloadHref, + itemId: currentItem.Id, + serverId: currentItem.serverId + }]); + }); + } + + function onMoreCommandsClick() { + var button = this; + apiClient.getCurrentUser().then(function (user) { + itemContextMenu.show(getContextMenuOptions(currentItem, user, button)).then(function (result) { + if (result.deleted) { + appRouter.goHome(); + } else if (result.updated) { + reload(self, view, params); + } + }); + }); + } + + function onPlayerChange() { + renderTrackSelections(view, self, currentItem); + setTrailerButtonVisibility(view, currentItem); + } + + function editImages() { + return new Promise(function (resolve, reject) { + require(["imageEditor"], function (imageEditor) { + imageEditor.show({ + itemId: currentItem.Id, + serverId: currentItem.ServerId + }).then(resolve, reject); + }); + }); + } + + function onWebSocketMessage(e, data) { + var msg = data; + + if ("UserDataChanged" === msg.MessageType && currentItem && msg.Data.UserId == apiClient.getCurrentUserId()) { + var key = currentItem.UserData.Key; + var userData = msg.Data.UserDataList.filter(function (u) { + return u.Key == key; + })[0]; + + if (userData) { + currentItem.UserData = userData; + reloadPlayButtons(view, currentItem); + apiClient.getCurrentUser().then(function (user) { + refreshImage(view, currentItem, user); + }); } } - - var currentItem; - var self = this; - var apiClient = params.serverId ? connectionManager.getApiClient(params.serverId) : ApiClient; - view.querySelectorAll(".btnPlay"); - bindAll(view, ".btnPlay", "click", onPlayClick); - bindAll(view, ".btnResume", "click", onPlayClick); - bindAll(view, ".btnInstantMix", "click", onInstantMixClick); - bindAll(view, ".btnShuffle", "click", onShuffleClick); - bindAll(view, ".btnPlayTrailer", "click", onPlayTrailerClick); - bindAll(view, ".btnCancelSeriesTimer", "click", onCancelSeriesTimerClick); - bindAll(view, ".btnCancelTimer", "click", onCancelTimerClick); - bindAll(view, ".btnDeleteItem", "click", onDeleteClick); - bindAll(view, ".btnDownload", "click", onDownloadClick); - view.querySelector(".btnMoreCommands i").innerHTML = ""; - view.querySelector(".trackSelections").addEventListener("submit", onTrackSelectionsSubmit); - view.querySelector(".btnSplitVersions").addEventListener("click", function() { - splitVersions(self, view, apiClient, params) - }); - bindAll(view, ".btnMoreCommands", "click", onMoreCommandsClick); - view.querySelector(".selectSource").addEventListener("change", function() { - renderVideoSelections(view, self._currentPlaybackMediaSources); - renderAudioSelections(view, self._currentPlaybackMediaSources); - renderSubtitleSelections(view, self._currentPlaybackMediaSources); - }); - view.addEventListener("click", function(e) { - dom.parentWithClass(e.target, "moreScenes") ? apiClient.getCurrentUser().then(function(user) { - renderScenes(view, currentItem) - }) : dom.parentWithClass(e.target, "morePeople") ? renderCast(view, currentItem, params.context) : dom.parentWithClass(e.target, "moreSpecials") && apiClient.getCurrentUser().then(function(user) { - renderSpecials(view, currentItem, user) - }) - }); - view.querySelector(".detailImageContainer").addEventListener("click", function(e) { - dom.parentWithClass(e.target, "itemDetailGalleryLink") && editImages().then(function() { - reload(self, view, params) - }) - }); - view.addEventListener("viewshow", function(e) { - var page = this; - libraryMenu.setTransparentMenu(!0), e.detail.isRestored ? currentItem && (setTitle(currentItem, connectionManager.getApiClient(currentItem.ServerId)), renderTrackSelections(page, self, currentItem, !0)) : reload(self, page, params), events.on(apiClient, "message", onWebSocketMessage), events.on(playbackManager, "playerchange", onPlayerChange) - }); - view.addEventListener("viewbeforehide", function() { - events.off(apiClient, "message", onWebSocketMessage); - events.off(playbackManager, "playerchange", onPlayerChange); - libraryMenu.setTransparentMenu(false); - }); - view.addEventListener("viewdestroy", function() { - currentItem = null; - self._currentPlaybackMediaSources = null; - self.currentRecordingFields = null; - }) } + + var currentItem; + var self = this; + var apiClient = params.serverId ? connectionManager.getApiClient(params.serverId) : ApiClient; + view.querySelectorAll(".btnPlay"); + bindAll(view, ".btnPlay", "click", onPlayClick); + bindAll(view, ".btnResume", "click", onPlayClick); + bindAll(view, ".btnInstantMix", "click", onInstantMixClick); + bindAll(view, ".btnShuffle", "click", onShuffleClick); + bindAll(view, ".btnPlayTrailer", "click", onPlayTrailerClick); + bindAll(view, ".btnCancelSeriesTimer", "click", onCancelSeriesTimerClick); + bindAll(view, ".btnCancelTimer", "click", onCancelTimerClick); + bindAll(view, ".btnDeleteItem", "click", onDeleteClick); + bindAll(view, ".btnDownload", "click", onDownloadClick); + view.querySelector(".btnMoreCommands i").innerHTML = ""; + view.querySelector(".trackSelections").addEventListener("submit", onTrackSelectionsSubmit); + view.querySelector(".btnSplitVersions").addEventListener("click", function () { + splitVersions(self, view, apiClient, params); + }); + bindAll(view, ".btnMoreCommands", "click", onMoreCommandsClick); + view.querySelector(".selectSource").addEventListener("change", function () { + renderVideoSelections(view, self._currentPlaybackMediaSources); + renderAudioSelections(view, self._currentPlaybackMediaSources); + renderSubtitleSelections(view, self._currentPlaybackMediaSources); + }); + view.addEventListener("click", function (e) { + if (dom.parentWithClass(e.target, "moreScenes")) { + apiClient.getCurrentUser().then(function (user) { + renderScenes(view, currentItem); + }); + } else if (dom.parentWithClass(e.target, "morePeople")) { + renderCast(view, currentItem, params.context); + } else if (dom.parentWithClass(e.target, "moreSpecials")) { + apiClient.getCurrentUser().then(function (user) { + renderSpecials(view, currentItem, user); + }); + } + }); + view.querySelector(".detailImageContainer").addEventListener("click", function (e) { + if (dom.parentWithClass(e.target, "itemDetailGalleryLink")) { + editImages().then(function () { + reload(self, view, params); + }); + } + }); + view.addEventListener("viewshow", function (e) { + var page = this; + libraryMenu.setTransparentMenu(true); + + if (e.detail.isRestored) { + if (currentItem) { + setTitle(currentItem, connectionManager.getApiClient(currentItem.ServerId)); + renderTrackSelections(page, self, currentItem, true); + } + } else { + reload(self, page, params); + } + + events.on(apiClient, "message", onWebSocketMessage); + events.on(playbackManager, "playerchange", onPlayerChange); + }); + view.addEventListener("viewbeforehide", function () { + events.off(apiClient, "message", onWebSocketMessage); + events.off(playbackManager, "playerchange", onPlayerChange); + libraryMenu.setTransparentMenu(false); + }); + view.addEventListener("viewdestroy", function () { + currentItem = null; + self._currentPlaybackMediaSources = null; + self.currentRecordingFields = null; + }); + }; }); diff --git a/src/controllers/list.js b/src/controllers/list.js index aac1818592..d15ebd2444 100644 --- a/src/controllers/list.js +++ b/src/controllers/list.js @@ -1,4 +1,4 @@ -define(["globalize", "listView", "layoutManager", "userSettings", "focusManager", "cardBuilder", "loading", "connectionManager", "alphaNumericShortcuts", "scroller", "playbackManager", "alphaPicker", "emby-itemscontainer", "emby-scroller"], function(globalize, listView, layoutManager, userSettings, focusManager, cardBuilder, loading, connectionManager, AlphaNumericShortcuts, scroller, playbackManager, alphaPicker) { +define(["globalize", "listView", "layoutManager", "userSettings", "focusManager", "cardBuilder", "loading", "connectionManager", "alphaNumericShortcuts", "scroller", "playbackManager", "alphaPicker", "emby-itemscontainer", "emby-scroller"], function (globalize, listView, layoutManager, userSettings, focusManager, cardBuilder, loading, connectionManager, AlphaNumericShortcuts, scroller, playbackManager, alphaPicker) { "use strict"; function getInitialLiveTvQuery(instance, params) { @@ -8,83 +8,303 @@ define(["globalize", "listView", "layoutManager", "userSettings", "focusManager" Fields: "ChannelInfo,PrimaryImageAspectRatio", Limit: 300 }; - return "Recordings" === params.type ? query.IsInProgress = !1 : query.HasAired = !1, params.genreId && (query.GenreIds = params.genreId), "true" === params.IsMovie ? query.IsMovie = !0 : "false" === params.IsMovie && (query.IsMovie = !1), "true" === params.IsSeries ? query.IsSeries = !0 : "false" === params.IsSeries && (query.IsSeries = !1), "true" === params.IsNews ? query.IsNews = !0 : "false" === params.IsNews && (query.IsNews = !1), "true" === params.IsSports ? query.IsSports = !0 : "false" === params.IsSports && (query.IsSports = !1), "true" === params.IsKids ? query.IsKids = !0 : "false" === params.IsKids && (query.IsKids = !1), "true" === params.IsAiring ? query.IsAiring = !0 : "false" === params.IsAiring && (query.IsAiring = !1), modifyQueryWithFilters(instance, query) + + if ("Recordings" === params.type) { + query.IsInProgress = false; + } else { + query.HasAired = false; + } + + if (params.genreId) { + query.GenreIds = params.genreId; + } + + if ("true" === params.IsMovie) { + query.IsMovie = true; + } else if ("false" === params.IsMovie) { + query.IsMovie = false; + } + + if ("true" === params.IsSeries) { + query.IsSeries = true; + } else if ("false" === params.IsSeries) { + query.IsSeries = false; + } + + if ("true" === params.IsNews) { + query.IsNews = true; + } else if ("false" === params.IsNews) { + query.IsNews = false; + } + + if ("true" === params.IsSports) { + query.IsSports = true; + } else if ("false" === params.IsSports) { + query.IsSports = false; + } + + if ("true" === params.IsKids) { + query.IsKids = true; + } else if ("false" === params.IsKids) { + query.IsKids = false; + } + + if ("true" === params.IsAiring) { + query.IsAiring = true; + } else if ("false" === params.IsAiring) { + query.IsAiring = false; + } + + return modifyQueryWithFilters(instance, query); } function modifyQueryWithFilters(instance, query) { var sortValues = instance.getSortValues(); - query.SortBy || (query.SortBy = sortValues.sortBy, query.SortOrder = sortValues.sortOrder), query.Fields = query.Fields ? query.Fields + ",PrimaryImageAspectRatio" : "PrimaryImageAspectRatio", query.ImageTypeLimit = 1; - var hasFilters, queryFilters = [], - filters = instance.getFilters(); - return filters.IsPlayed && (queryFilters.push("IsPlayed"), hasFilters = !0), filters.IsUnplayed && (queryFilters.push("IsUnplayed"), hasFilters = !0), filters.IsFavorite && (queryFilters.push("IsFavorite"), hasFilters = !0), filters.IsResumable && (queryFilters.push("IsResumable"), hasFilters = !0), filters.VideoTypes && (hasFilters = !0, query.VideoTypes = filters.VideoTypes), filters.GenreIds && (hasFilters = !0, query.GenreIds = filters.GenreIds), filters.Is4K && (query.Is4K = !0, hasFilters = !0), filters.IsHD && (query.IsHD = !0, hasFilters = !0), filters.IsSD && (query.IsHD = !1, hasFilters = !0), filters.Is3D && (query.Is3D = !0, hasFilters = !0), filters.HasSubtitles && (query.HasSubtitles = !0, hasFilters = !0), filters.HasTrailer && (query.HasTrailer = !0, hasFilters = !0), filters.HasSpecialFeature && (query.HasSpecialFeature = !0, hasFilters = !0), filters.HasThemeSong && (query.HasThemeSong = !0, hasFilters = !0), filters.HasThemeVideo && (query.HasThemeVideo = !0, hasFilters = !0), query.Filters = queryFilters.length ? queryFilters.join(",") : null, instance.setFilterStatus(hasFilters), instance.alphaPicker && (query.NameStartsWithOrGreater = instance.alphaPicker.value()), query + + if (!query.SortBy) { + query.SortBy = sortValues.sortBy; + query.SortOrder = sortValues.sortOrder; + } + + query.Fields = query.Fields ? query.Fields + ",PrimaryImageAspectRatio" : "PrimaryImageAspectRatio"; + query.ImageTypeLimit = 1; + var hasFilters; + var queryFilters = []; + var filters = instance.getFilters(); + + if (filters.IsPlayed) { + queryFilters.push("IsPlayed"); + hasFilters = true; + } + + if (filters.IsUnplayed) { + queryFilters.push("IsUnplayed"); + hasFilters = true; + } + + if (filters.IsFavorite) { + queryFilters.push("IsFavorite"); + hasFilters = true; + } + + if (filters.IsResumable) { + queryFilters.push("IsResumable"); + hasFilters = true; + } + + if (filters.VideoTypes) { + hasFilters = true; + query.VideoTypes = filters.VideoTypes; + } + + if (filters.GenreIds) { + hasFilters = true; + query.GenreIds = filters.GenreIds; + } + + if (filters.Is4K) { + query.Is4K = true; + hasFilters = true; + } + + if (filters.IsHD) { + query.IsHD = true; + hasFilters = true; + } + + if (filters.IsSD) { + query.IsHD = false; + hasFilters = true; + } + + if (filters.Is3D) { + query.Is3D = true; + hasFilters = true; + } + + if (filters.HasSubtitles) { + query.HasSubtitles = true; + hasFilters = true; + } + + if (filters.HasTrailer) { + query.HasTrailer = true; + hasFilters = true; + } + + if (filters.HasSpecialFeature) { + query.HasSpecialFeature = true; + hasFilters = true; + } + + if (filters.HasThemeSong) { + query.HasThemeSong = true; + hasFilters = true; + } + + if (filters.HasThemeVideo) { + query.HasThemeVideo = true; + hasFilters = true; + } + + query.Filters = queryFilters.length ? queryFilters.join(",") : null; + instance.setFilterStatus(hasFilters); + + if (instance.alphaPicker) { + query.NameStartsWithOrGreater = instance.alphaPicker.value(); + } + + return query; } function updateSortText(instance) { var btnSortText = instance.btnSortText; + if (btnSortText) { - for (var options = instance.getSortMenuOptions(), values = instance.getSortValues(), sortBy = values.sortBy, i = 0, length = options.length; i < length; i++) + var options = instance.getSortMenuOptions(); + var values = instance.getSortValues(); + var sortBy = values.sortBy; + + for (var i = 0, length = options.length; i < length; i++) { if (sortBy === options[i].value) { btnSortText.innerHTML = globalize.translate("SortByValue", options[i].name); - break - } var btnSortIcon = instance.btnSortIcon; - btnSortIcon && (btnSortIcon.innerHTML = "Descending" === values.sortOrder ? "" : "") + break; + } + } + + var btnSortIcon = instance.btnSortIcon; + + if (btnSortIcon) { + btnSortIcon.innerHTML = "Descending" === values.sortOrder ? "" : ""; + } } } function updateItemsContainerForViewType(instance) { - "list" === instance.getViewSettings().imageType ? (instance.itemsContainer.classList.remove("vertical-wrap"), instance.itemsContainer.classList.add("vertical-list")) : (instance.itemsContainer.classList.add("vertical-wrap"), instance.itemsContainer.classList.remove("vertical-list")) + if ("list" === instance.getViewSettings().imageType) { + instance.itemsContainer.classList.remove("vertical-wrap"); + instance.itemsContainer.classList.add("vertical-list"); + } else { + instance.itemsContainer.classList.add("vertical-wrap"); + instance.itemsContainer.classList.remove("vertical-list"); + } } function updateAlphaPickerState(instance, numItems) { if (instance.alphaPicker) { var alphaPicker = instance.alphaPickerElement; + if (alphaPicker) { var values = instance.getSortValues(); - null == numItems && (numItems = 100), "SortName" === values.sortBy && "Ascending" === values.sortOrder && numItems > 40 ? (alphaPicker.classList.remove("hide"), layoutManager.tv ? instance.itemsContainer.parentNode.classList.add("padded-left-withalphapicker") : instance.itemsContainer.parentNode.classList.add("padded-right-withalphapicker")) : (alphaPicker.classList.add("hide"), instance.itemsContainer.parentNode.classList.remove("padded-left-withalphapicker"), instance.itemsContainer.parentNode.classList.remove("padded-right-withalphapicker")) + + if (null == numItems) { + numItems = 100; + } + + if ("SortName" === values.sortBy && "Ascending" === values.sortOrder && numItems > 40) { + alphaPicker.classList.remove("hide"); + + if (layoutManager.tv) { + instance.itemsContainer.parentNode.classList.add("padded-left-withalphapicker"); + } else { + instance.itemsContainer.parentNode.classList.add("padded-right-withalphapicker"); + } + } else { + alphaPicker.classList.add("hide"); + instance.itemsContainer.parentNode.classList.remove("padded-left-withalphapicker"); + instance.itemsContainer.parentNode.classList.remove("padded-right-withalphapicker"); + } } } } function getItems(instance, params, item, sortBy, startIndex, limit) { var apiClient = connectionManager.getApiClient(params.serverId); - if (instance.queryRecursive = !1, "Recordings" === params.type) return apiClient.getLiveTvRecordings(getInitialLiveTvQuery(instance, params)); - if ("Programs" === params.type) return "true" === params.IsAiring ? apiClient.getLiveTvRecommendedPrograms(getInitialLiveTvQuery(instance, params)) : apiClient.getLiveTvPrograms(getInitialLiveTvQuery(instance, params)); - if ("nextup" === params.type) return apiClient.getNextUpEpisodes(modifyQueryWithFilters(instance, { - Limit: limit, - Fields: "PrimaryImageAspectRatio,SeriesInfo,DateCreated,BasicSyncInfo", - UserId: apiClient.getCurrentUserId(), - ImageTypeLimit: 1, - EnableImageTypes: "Primary,Backdrop,Thumb", - EnableTotalRecordCount: !1, - SortBy: sortBy - })); + + instance.queryRecursive = false; + if ("Recordings" === params.type) { + return apiClient.getLiveTvRecordings(getInitialLiveTvQuery(instance, params)); + } + + if ("Programs" === params.type) { + if ("true" === params.IsAiring) { + return apiClient.getLiveTvRecommendedPrograms(getInitialLiveTvQuery(instance, params)); + } + + return apiClient.getLiveTvPrograms(getInitialLiveTvQuery(instance, params)); + } + + if ("nextup" === params.type) { + return apiClient.getNextUpEpisodes(modifyQueryWithFilters(instance, { + Limit: limit, + Fields: "PrimaryImageAspectRatio,SeriesInfo,DateCreated,BasicSyncInfo", + UserId: apiClient.getCurrentUserId(), + ImageTypeLimit: 1, + EnableImageTypes: "Primary,Backdrop,Thumb", + EnableTotalRecordCount: false, + SortBy: sortBy + })); + } + if (!item) { - instance.queryRecursive = !0; + instance.queryRecursive = true; var method = "getItems"; - return "MusicArtist" === params.type ? method = "getArtists" : "Person" === params.type && (method = "getPeople"), apiClient[method](apiClient.getCurrentUserId(), modifyQueryWithFilters(instance, { + + if ("MusicArtist" === params.type) { + method = "getArtists"; + } else if ("Person" === params.type) { + method = "getPeople"; + } + + return apiClient[method](apiClient.getCurrentUserId(), modifyQueryWithFilters(instance, { StartIndex: startIndex, Limit: limit, Fields: "PrimaryImageAspectRatio,SortName", ImageTypeLimit: 1, IncludeItemTypes: "MusicArtist" === params.type || "Person" === params.type ? null : params.type, - Recursive: !0, + Recursive: true, IsFavorite: "true" === params.IsFavorite || null, ArtistIds: params.artistId || null, SortBy: sortBy - })) + })); } + if ("Genre" === item.Type || "MusicGenre" === item.Type || "Studio" === item.Type || "Person" === item.Type) { - instance.queryRecursive = !0; + instance.queryRecursive = true; var query = { StartIndex: startIndex, Limit: limit, Fields: "PrimaryImageAspectRatio,SortName", - Recursive: !0, + Recursive: true, parentId: params.parentId, SortBy: sortBy }; - return "Studio" === item.Type ? query.StudioIds = item.Id : "Genre" === item.Type || "MusicGenre" === item.Type ? query.GenreIds = item.Id : "Person" === item.Type && (query.PersonIds = item.Id), "MusicGenre" === item.Type ? query.IncludeItemTypes = "MusicAlbum" : "GameGenre" === item.Type ? query.IncludeItemTypes = "Game" : "movies" === item.CollectionType ? query.IncludeItemTypes = "Movie" : "tvshows" === item.CollectionType ? query.IncludeItemTypes = "Series" : "Genre" === item.Type ? query.IncludeItemTypes = "Movie,Series,Video" : "Person" === item.Type && (query.IncludeItemTypes = params.type), apiClient.getItems(apiClient.getCurrentUserId(), modifyQueryWithFilters(instance, query)) + + if ("Studio" === item.Type) { + query.StudioIds = item.Id; + } else if ("Genre" === item.Type || "MusicGenre" === item.Type) { + query.GenreIds = item.Id; + } else if ("Person" === item.Type) { + query.PersonIds = item.Id; + } + + if ("MusicGenre" === item.Type) { + query.IncludeItemTypes = "MusicAlbum"; + } else if ("GameGenre" === item.Type) { + query.IncludeItemTypes = "Game"; + } else if ("movies" === item.CollectionType) { + query.IncludeItemTypes = "Movie"; + } else if ("tvshows" === item.CollectionType) { + query.IncludeItemTypes = "Series"; + } else if ("Genre" === item.Type) { + query.IncludeItemTypes = "Movie,Series,Video"; + } else if ("Person" === item.Type) { + query.IncludeItemTypes = params.type; + } + + return apiClient.getItems(apiClient.getCurrentUserId(), modifyQueryWithFilters(instance, query)); } + return apiClient.getItems(apiClient.getCurrentUserId(), modifyQueryWithFilters(instance, { StartIndex: startIndex, Limit: limit, @@ -92,35 +312,44 @@ define(["globalize", "listView", "layoutManager", "userSettings", "focusManager" ImageTypeLimit: 1, ParentId: item.Id, SortBy: sortBy - })) + })); } function getItem(params) { - if ("Recordings" === params.type) return Promise.resolve(null); - if ("Programs" === params.type) return Promise.resolve(null); - if ("nextup" === params.type) return Promise.resolve(null); - var apiClient = connectionManager.getApiClient(params.serverId), - itemId = params.genreId || params.musicGenreId || params.studioId || params.personId || params.parentId; - return itemId ? apiClient.getItem(apiClient.getCurrentUserId(), itemId) : Promise.resolve(null) + if ("Recordings" === params.type || "Programs" === params.type || "nextup" === params.type) { + return Promise.resolve(null); + } + + var apiClient = connectionManager.getApiClient(params.serverId); + var itemId = params.genreId || params.musicGenreId || params.studioId || params.personId || params.parentId; + + if (itemId) { + return apiClient.getItem(apiClient.getCurrentUserId(), itemId); + } + + return Promise.resolve(null); } function showViewSettingsMenu() { var instance = this; - require(["viewSettings"], function(ViewSettings) { - (new ViewSettings).show({ + + require(["viewSettings"], function (ViewSettings) { + new ViewSettings().show({ settingsKey: instance.getSettingsKey(), settings: instance.getViewSettings(), visibleSettings: instance.getVisibleViewSettings() - }).then(function() { - updateItemsContainerForViewType(instance), instance.itemsContainer.refreshItems() - }) - }) + }).then(function () { + updateItemsContainerForViewType(instance); + instance.itemsContainer.refreshItems(); + }); + }); } function showFilterMenu() { var instance = this; - require(["filterMenu"], function(FilterMenu) { - (new FilterMenu).show({ + + require(["filterMenu"], function (FilterMenu) { + new FilterMenu().show({ settingsKey: instance.getSettingsKey(), settings: instance.getFilters(), visibleSettings: instance.getVisibleFilters(), @@ -129,201 +358,497 @@ define(["globalize", "listView", "layoutManager", "userSettings", "focusManager" itemTypes: instance.getItemTypes(), serverId: instance.params.serverId, filterMenuOptions: instance.getFilterMenuOptions() - }).then(function() { - instance.itemsContainer.refreshItems() - }) - }) + }).then(function () { + instance.itemsContainer.refreshItems(); + }); + }); } function showSortMenu() { var instance = this; - require(["sortMenu"], function(SortMenu) { - (new SortMenu).show({ + + require(["sortMenu"], function (SortMenu) { + new SortMenu().show({ settingsKey: instance.getSettingsKey(), settings: instance.getSortValues(), onChange: instance.itemsContainer.refreshItems.bind(instance.itemsContainer), serverId: instance.params.serverId, sortOptions: instance.getSortMenuOptions() - }).then(function() { - updateSortText(instance), updateAlphaPickerState(instance), instance.itemsContainer.refreshItems() - }) - }) + }).then(function () { + updateSortText(instance); + updateAlphaPickerState(instance); + instance.itemsContainer.refreshItems(); + }); + }); } function onNewItemClick() { var instance = this; - require(["playlistEditor"], function(playlistEditor) { - (new playlistEditor).show({ + + require(["playlistEditor"], function (playlistEditor) { + new playlistEditor().show({ items: [], serverId: instance.params.serverId - }) - }) + }); + }); } function hideOrShowAll(elems, hide) { - for (var i = 0, length = elems.length; i < length; i++) hide ? elems[i].classList.add("hide") : elems[i].classList.remove("hide") + for (var i = 0, length = elems.length; i < length; i++) { + if (hide) { + elems[i].classList.add("hide"); + } else { + elems[i].classList.remove("hide"); + } + } } function bindAll(elems, eventName, fn) { - for (var i = 0, length = elems.length; i < length; i++) elems[i].addEventListener(eventName, fn) + for (var i = 0, length = elems.length; i < length; i++) { + elems[i].addEventListener(eventName, fn); + } } function ItemsView(view, params) { function fetchData() { - return getItems(self, params, self.currentItem).then(function(result) { - return null == self.totalItemCount && (self.totalItemCount = result.Items ? result.Items.length : result.length), updateAlphaPickerState(self, self.totalItemCount), result - }) + return getItems(self, params, self.currentItem).then(function (result) { + if (null == self.totalItemCount) { + self.totalItemCount = result.Items ? result.Items.length : result.length; + } + + updateAlphaPickerState(self, self.totalItemCount); + return result; + }); } function getItemsHtml(items) { var settings = self.getViewSettings(); - if ("list" === settings.imageType) return listView.getListViewHtml({ - items: items - }); - var shape, preferThumb, preferDisc, preferLogo, defaultShape, item = self.currentItem, - lines = settings.showTitle ? 2 : 0; - "banner" === settings.imageType ? shape = "banner" : "disc" === settings.imageType ? (shape = "square", preferDisc = !0) : "logo" === settings.imageType ? (shape = "backdrop", preferLogo = !0) : "thumb" === settings.imageType ? (shape = "backdrop", preferThumb = !0) : "nextup" === params.type ? (shape = "backdrop", preferThumb = "thumb" === settings.imageType) : "Programs" === params.type || "Recordings" === params.type ? (shape = "true" === params.IsMovie ? "portrait" : "autoVertical", preferThumb = "true" !== params.IsMovie && "auto", defaultShape = "true" === params.IsMovie ? "portrait" : "backdrop") : shape = "autoVertical"; + + if ("list" === settings.imageType) { + return listView.getListViewHtml({ + items: items + }); + } + + var shape; + var preferThumb; + var preferDisc; + var preferLogo; + var defaultShape; + var item = self.currentItem; + var lines = settings.showTitle ? 2 : 0; + + if ("banner" === settings.imageType) { + shape = "banner"; + } else if ("disc" === settings.imageType) { + shape = "square"; + preferDisc = true; + } else if ("logo" === settings.imageType) { + shape = "backdrop"; + preferLogo = true; + } else if ("thumb" === settings.imageType) { + shape = "backdrop"; + preferThumb = true; + } else if ("nextup" === params.type) { + shape = "backdrop"; + preferThumb = "thumb" === settings.imageType; + } else if ("Programs" === params.type || "Recordings" === params.type) { + shape = "true" === params.IsMovie ? "portrait" : "autoVertical"; + preferThumb = "true" !== params.IsMovie ? "auto" : false; + defaultShape = "true" === params.IsMovie ? "portrait" : "backdrop"; + } else { + shape = "autoVertical"; + } + var posterOptions = { shape: shape, showTitle: settings.showTitle, showYear: settings.showTitle, - centerText: !0, - coverImage: !0, + centerText: true, + coverImage: true, preferThumb: preferThumb, preferDisc: preferDisc, preferLogo: preferLogo, - overlayPlayButton: !1, - overlayMoreButton: !0, + overlayPlayButton: false, + overlayMoreButton: true, overlayText: !settings.showTitle, defaultShape: defaultShape, action: "Audio" === params.type ? "playallfromhere" : null }; - if ("nextup" === params.type) posterOptions.showParentTitle = settings.showTitle; - else if ("Person" === params.type) posterOptions.showYear = !1, posterOptions.showParentTitle = !1, lines = 1; - else if ("Audio" === params.type) posterOptions.showParentTitle = settings.showTitle; - else if ("MusicAlbum" === params.type) posterOptions.showParentTitle = settings.showTitle; - else if ("Episode" === params.type) posterOptions.showParentTitle = settings.showTitle; - else if ("MusicArtist" === params.type) posterOptions.showYear = !1, lines = 1; - else if ("Programs" === params.type) { + + if ("nextup" === params.type) { + posterOptions.showParentTitle = settings.showTitle; + } else if ("Person" === params.type) { + posterOptions.showYear = false; + posterOptions.showParentTitle = false; + lines = 1; + } else if ("Audio" === params.type) { + posterOptions.showParentTitle = settings.showTitle; + } else if ("MusicAlbum" === params.type) { + posterOptions.showParentTitle = settings.showTitle; + } else if ("Episode" === params.type) { + posterOptions.showParentTitle = settings.showTitle; + } else if ("MusicArtist" === params.type) { + posterOptions.showYear = false; + lines = 1; + } else if ("Programs" === params.type) { lines = settings.showTitle ? 1 : 0; var showParentTitle = settings.showTitle && "true" !== params.IsMovie; - showParentTitle && lines++; + + if (showParentTitle) { + lines++; + } + var showAirTime = settings.showTitle && "Recordings" !== params.type; - showAirTime && lines++; + + if (showAirTime) { + lines++; + } + var showYear = settings.showTitle && "true" === params.IsMovie && "Recordings" === params.type; - showYear && lines++, posterOptions = Object.assign(posterOptions, { + + if (showYear) { + lines++; + } + + posterOptions = Object.assign(posterOptions, { inheritThumb: "Recordings" === params.type, context: "livetv", showParentTitle: showParentTitle, showAirTime: showAirTime, showAirDateTime: showAirTime, - overlayPlayButton: !1, - overlayMoreButton: !0, + overlayPlayButton: false, + overlayMoreButton: true, showYear: showYear, - coverImage: !0 - }) - } else posterOptions.showParentTitle = settings.showTitle; - return posterOptions.lines = lines, posterOptions.items = items, item && "folders" === item.CollectionType && (posterOptions.context = "folders"), cardBuilder.getCardsHtml(posterOptions) + coverImage: true + }); + } else { + posterOptions.showParentTitle = settings.showTitle; + } + + posterOptions.lines = lines; + posterOptions.items = items; + + if (item && "folders" === item.CollectionType) { + posterOptions.context = "folders"; + } + + return cardBuilder.getCardsHtml(posterOptions); } function initAlphaPicker() { self.scroller = view.querySelector(".scrollFrameY"); var alphaPickerElement = self.alphaPickerElement; - layoutManager.tv ? (alphaPickerElement.classList.add("alphaPicker-fixed-left"), alphaPickerElement.classList.add("focuscontainer-left"), self.itemsContainer.parentNode.classList.add("padded-left-withalphapicker")) : (alphaPickerElement.classList.add("alphaPicker-fixed-right"), alphaPickerElement.classList.add("focuscontainer-right"), self.itemsContainer.parentNode.classList.add("padded-right-withalphapicker")), self.alphaPicker = new alphaPicker({ + + if (layoutManager.tv) { + alphaPickerElement.classList.add("alphaPicker-fixed-left"); + alphaPickerElement.classList.add("focuscontainer-left"); + self.itemsContainer.parentNode.classList.add("padded-left-withalphapicker"); + } else { + alphaPickerElement.classList.add("alphaPicker-fixed-right"); + alphaPickerElement.classList.add("focuscontainer-right"); + self.itemsContainer.parentNode.classList.add("padded-right-withalphapicker"); + } + + self.alphaPicker = new alphaPicker({ element: alphaPickerElement, itemsContainer: layoutManager.tv ? self.itemsContainer : null, itemClass: "card", valueChangeEvent: layoutManager.tv ? null : "click" - }), self.alphaPicker.on("alphavaluechanged", onAlphaPickerValueChanged) + }); + self.alphaPicker.on("alphavaluechanged", onAlphaPickerValueChanged); } function onAlphaPickerValueChanged() { self.alphaPicker.value(); - self.itemsContainer.refreshItems() + self.itemsContainer.refreshItems(); } function setTitle(item) { - Emby.Page.setTitle(getTitle(item) || ""), item && "playlists" === item.CollectionType ? hideOrShowAll(view.querySelectorAll(".btnNewItem"), !1) : hideOrShowAll(view.querySelectorAll(".btnNewItem"), !0) + Emby.Page.setTitle(getTitle(item) || ""); + + if (item && "playlists" === item.CollectionType) { + hideOrShowAll(view.querySelectorAll(".btnNewItem"), false); + } else { + hideOrShowAll(view.querySelectorAll(".btnNewItem"), true); + } } function getTitle(item) { - return "Recordings" === params.type ? globalize.translate("Recordings") : "Programs" === params.type ? "true" === params.IsMovie ? globalize.translate("Movies") : "true" === params.IsSports ? globalize.translate("Sports") : "true" === params.IsKids ? globalize.translate("HeaderForKids") : "true" === params.IsAiring ? globalize.translate("HeaderOnNow") : "true" === params.IsSeries ? globalize.translate("Shows") : "true" === params.IsNews ? globalize.translate("News") : globalize.translate("Programs") : "nextup" === params.type ? globalize.translate("NextUp") : "favoritemovies" === params.type ? globalize.translate("FavoriteMovies") : item ? item.Name : "Movie" === params.type ? globalize.translate("Movies") : "Series" === params.type ? globalize.translate("Shows") : "Season" === params.type ? globalize.translate("Seasons") : "Episode" === params.type ? globalize.translate("Episodes") : "MusicArtist" === params.type ? globalize.translate("Artists") : "MusicAlbum" === params.type ? globalize.translate("Albums") : "Audio" === params.type ? globalize.translate("Songs") : "Video" === params.type ? globalize.translate("Videos") : void 0 + if ("Recordings" === params.type) { + return globalize.translate("Recordings"); + } + + if ("Programs" === params.type) { + if ("true" === params.IsMovie) { + return globalize.translate("Movies"); + } + + if ("true" === params.IsSports) { + return globalize.translate("Sports"); + } + + if ("true" === params.IsKids) { + return globalize.translate("HeaderForKids"); + } + + if ("true" === params.IsAiring) { + return globalize.translate("HeaderOnNow"); + } + + if ("true" === params.IsSeries) { + return globalize.translate("Shows"); + } + + if ("true" === params.IsNews) { + return globalize.translate("News"); + } + + return globalize.translate("Programs"); + } + + if ("nextup" === params.type) { + return globalize.translate("NextUp"); + } + + if ("favoritemovies" === params.type) { + return globalize.translate("FavoriteMovies"); + } + + if (item) { + return item.Name; + } + + if ("Movie" === params.type) { + return globalize.translate("Movies"); + } + + if ("Series" === params.type) { + return globalize.translate("Shows"); + } + + if ("Season" === params.type) { + return globalize.translate("Seasons"); + } + + if ("Episode" === params.type) { + return globalize.translate("Episodes"); + } + + if ("MusicArtist" === params.type) { + return globalize.translate("Artists"); + } + + if ("MusicAlbum" === params.type) { + return globalize.translate("Albums"); + } + + if ("Audio" === params.type) { + return globalize.translate("Songs"); + } + + if ("Video" === params.type) { + return globalize.translate("Videos"); + } + + return void 0; } function play() { var currentItem = self.currentItem; - if (currentItem && !self.hasFilters) return void playbackManager.play({ - items: [currentItem] - }); - getItems(self, self.params, currentItem, null, null, 300).then(function(result) { + + if (currentItem && !self.hasFilters) { playbackManager.play({ - items: result.Items - }) - }) + items: [currentItem] + }); + } else { + getItems(self, self.params, currentItem, null, null, 300).then(function (result) { + playbackManager.play({ + items: result.Items + }); + }); + } } function queue() { var currentItem = self.currentItem; - if (currentItem && !self.hasFilters) return void playbackManager.queue({ - items: [currentItem] - }); - getItems(self, self.params, currentItem, null, null, 300).then(function(result) { + + if (currentItem && !self.hasFilters) { playbackManager.queue({ - items: result.Items - }) - }) + items: [currentItem] + }); + } else { + getItems(self, self.params, currentItem, null, null, 300).then(function (result) { + playbackManager.queue({ + items: result.Items + }); + }); + } } function shuffle() { var currentItem = self.currentItem; - if (currentItem && !self.hasFilters) return void playbackManager.shuffle(currentItem); - getItems(self, self.params, currentItem, "Random", null, 300).then(function(result) { - playbackManager.play({ - items: result.Items - }) - }) + + if (currentItem && !self.hasFilters) { + playbackManager.shuffle(currentItem); + } else { + getItems(self, self.params, currentItem, "Random", null, 300).then(function (result) { + playbackManager.play({ + items: result.Items + }); + }); + } } + var self = this; - self.params = params, this.itemsContainer = view.querySelector(".itemsContainer"), params.parentId ? this.itemsContainer.setAttribute("data-parentid", params.parentId) : "nextup" === params.type ? this.itemsContainer.setAttribute("data-monitor", "videoplayback") : "favoritemovies" === params.type ? this.itemsContainer.setAttribute("data-monitor", "markfavorite") : "Programs" === params.type && this.itemsContainer.setAttribute("data-refreshinterval", "300000"); - var i, length, btnViewSettings = view.querySelectorAll(".btnViewSettings"); - for (i = 0, length = btnViewSettings.length; i < length; i++) btnViewSettings[i].addEventListener("click", showViewSettingsMenu.bind(this)); + self.params = params; + this.itemsContainer = view.querySelector(".itemsContainer"); + + if (params.parentId) { + this.itemsContainer.setAttribute("data-parentid", params.parentId); + } else if ("nextup" === params.type) { + this.itemsContainer.setAttribute("data-monitor", "videoplayback"); + } else if ("favoritemovies" === params.type) { + this.itemsContainer.setAttribute("data-monitor", "markfavorite"); + } else if ("Programs" === params.type) { + this.itemsContainer.setAttribute("data-refreshinterval", "300000"); + } + + var i; + var length; + var btnViewSettings = view.querySelectorAll(".btnViewSettings"); + + for (i = 0, length = btnViewSettings.length; i < length; i++) { + btnViewSettings[i].addEventListener("click", showViewSettingsMenu.bind(this)); + } + var filterButtons = view.querySelectorAll(".btnFilter"); this.filterButtons = filterButtons; var hasVisibleFilters = this.getVisibleFilters().length; + for (i = 0, length = filterButtons.length; i < length; i++) { var btnFilter = filterButtons[i]; - btnFilter.addEventListener("click", showFilterMenu.bind(this)), hasVisibleFilters ? btnFilter.classList.remove("hide") : btnFilter.classList.add("hide") + btnFilter.addEventListener("click", showFilterMenu.bind(this)); + + if (hasVisibleFilters) { + btnFilter.classList.remove("hide"); + } else { + btnFilter.classList.add("hide"); + } } + var sortButtons = view.querySelectorAll(".btnSort"); + for (this.sortButtons = sortButtons, i = 0, length = sortButtons.length; i < length; i++) { var sortButton = sortButtons[i]; - sortButton.addEventListener("click", showSortMenu.bind(this)), "nextup" !== params.type && sortButton.classList.remove("hide") + sortButton.addEventListener("click", showSortMenu.bind(this)); + + if ("nextup" !== params.type) { + sortButton.classList.remove("hide"); + } } - this.btnSortText = view.querySelector(".btnSortText"), this.btnSortIcon = view.querySelector(".btnSortIcon"), bindAll(view.querySelectorAll(".btnNewItem"), "click", onNewItemClick.bind(this)), this.alphaPickerElement = view.querySelector(".alphaPicker"), self.itemsContainer.fetchData = fetchData, self.itemsContainer.getItemsHtml = getItemsHtml, view.addEventListener("viewshow", function(e) { + + this.btnSortText = view.querySelector(".btnSortText"); + this.btnSortIcon = view.querySelector(".btnSortIcon"); + bindAll(view.querySelectorAll(".btnNewItem"), "click", onNewItemClick.bind(this)); + this.alphaPickerElement = view.querySelector(".alphaPicker"); + self.itemsContainer.fetchData = fetchData; + self.itemsContainer.getItemsHtml = getItemsHtml; + view.addEventListener("viewshow", function (e) { var isRestored = e.detail.isRestored; - isRestored || (loading.show(), updateSortText(self), updateItemsContainerForViewType(self)), setTitle(null), getItem(params).then(function(item) { - setTitle(item), self.currentItem = item; + + if (!isRestored) { + loading.show(); + updateSortText(self); + updateItemsContainerForViewType(self); + } + + setTitle(null); + getItem(params).then(function (item) { + setTitle(item); + self.currentItem = item; var refresh = !isRestored; self.itemsContainer.resume({ refresh: refresh - }).then(function() { - loading.hide(), refresh && focusManager.autoFocus(self.itemsContainer) - }), isRestored || item && "PhotoAlbum" !== item.Type && initAlphaPicker(); + }).then(function () { + loading.hide(); + + if (refresh) { + focusManager.autoFocus(self.itemsContainer); + } + }); + + if (!isRestored && item && "PhotoAlbum" !== item.Type) { + initAlphaPicker(); + } + var itemType = item ? item.Type : null; - "MusicGenre" === itemType || "Programs" !== params.type && "Channel" !== itemType ? hideOrShowAll(view.querySelectorAll(".btnPlay"), !1) : hideOrShowAll(view.querySelectorAll(".btnPlay"), !0), "MusicGenre" === itemType || "Programs" !== params.type && "nextup" !== params.type && "Channel" !== itemType ? hideOrShowAll(view.querySelectorAll(".btnShuffle"), !1) : hideOrShowAll(view.querySelectorAll(".btnShuffle"), !0), item && playbackManager.canQueue(item) ? hideOrShowAll(view.querySelectorAll(".btnQueue"), !1) : hideOrShowAll(view.querySelectorAll(".btnQueue"), !0) - }), isRestored || (bindAll(view.querySelectorAll(".btnPlay"), "click", play), bindAll(view.querySelectorAll(".btnQueue"), "click", queue), bindAll(view.querySelectorAll(".btnShuffle"), "click", shuffle)), this.alphaNumericShortcuts = new AlphaNumericShortcuts({ + + if ("MusicGenre" === itemType || "Programs" !== params.type && "Channel" !== itemType) { + hideOrShowAll(view.querySelectorAll(".btnPlay"), false); + } else { + hideOrShowAll(view.querySelectorAll(".btnPlay"), true); + } + + if ("MusicGenre" === itemType || "Programs" !== params.type && "nextup" !== params.type && "Channel" !== itemType) { + hideOrShowAll(view.querySelectorAll(".btnShuffle"), false); + } else { + hideOrShowAll(view.querySelectorAll(".btnShuffle"), true); + } + + if (item && playbackManager.canQueue(item)) { + hideOrShowAll(view.querySelectorAll(".btnQueue"), false); + } else { + hideOrShowAll(view.querySelectorAll(".btnQueue"), true); + } + }); + + if (!isRestored) { + bindAll(view.querySelectorAll(".btnPlay"), "click", play); + bindAll(view.querySelectorAll(".btnQueue"), "click", queue); + bindAll(view.querySelectorAll(".btnShuffle"), "click", shuffle); + } + + this.alphaNumericShortcuts = new AlphaNumericShortcuts({ itemsContainer: self.itemsContainer - }) - }), view.addEventListener("viewhide", function(e) { + }); + }); + view.addEventListener("viewhide", function (e) { var itemsContainer = self.itemsContainer; - itemsContainer && itemsContainer.pause(); + + if (itemsContainer) { + itemsContainer.pause(); + } + var alphaNumericShortcuts = self.alphaNumericShortcuts; - alphaNumericShortcuts && (alphaNumericShortcuts.destroy(), self.alphaNumericShortcuts = null) - }), view.addEventListener("viewdestroy", function() { - self.listController && self.listController.destroy(), self.alphaPicker && (self.alphaPicker.off("alphavaluechanged", onAlphaPickerValueChanged), self.alphaPicker.destroy()), self.currentItem = null, self.scroller = null, self.itemsContainer = null, self.filterButtons = null, self.sortButtons = null, self.btnSortText = null, self.btnSortIcon = null, self.alphaPickerElement = null - }) + + if (alphaNumericShortcuts) { + alphaNumericShortcuts.destroy(); + self.alphaNumericShortcuts = null; + } + }); + view.addEventListener("viewdestroy", function () { + if (self.listController) { + self.listController.destroy(); + } + + if (self.alphaPicker) { + self.alphaPicker.off("alphavaluechanged", onAlphaPickerValueChanged); + self.alphaPicker.destroy(); + } + + self.currentItem = null; + self.scroller = null; + self.itemsContainer = null; + self.filterButtons = null; + self.sortButtons = null; + self.btnSortText = null; + self.btnSortIcon = null; + self.alphaPickerElement = null; + }); } - return ItemsView.prototype.getFilters = function() { + + ItemsView.prototype.getFilters = function () { var basekey = this.getSettingsKey(); return { IsPlayed: "true" === userSettings.getFilter(basekey + "-filter-IsPlayed"), @@ -342,87 +867,211 @@ define(["globalize", "listView", "layoutManager", "userSettings", "focusManager" HasThemeSong: userSettings.getFilter(basekey + "-filter-HasThemeSong"), HasThemeVideo: userSettings.getFilter(basekey + "-filter-HasThemeVideo"), GenreIds: userSettings.getFilter(basekey + "-filter-GenreIds") - } - }, ItemsView.prototype.getSortValues = function() { + }; + }; + + ItemsView.prototype.getSortValues = function () { var basekey = this.getSettingsKey(); return { sortBy: userSettings.getFilter(basekey + "-sortby") || this.getDefaultSortBy(), sortOrder: "Descending" === userSettings.getFilter(basekey + "-sortorder") ? "Descending" : "Ascending" + }; + }; + + ItemsView.prototype.getDefaultSortBy = function () { + var params = this.params; + var sortNameOption = this.getNameSortOption(params); + + if (params.type) { + return sortNameOption.value; } - }, ItemsView.prototype.getDefaultSortBy = function() { - var params = this.params, - sortNameOption = this.getNameSortOption(params); - return params.type ? sortNameOption.value : "IsFolder," + sortNameOption.value - }, ItemsView.prototype.getSortMenuOptions = function() { - var sortBy = [], - params = this.params; - "Programs" === params.type && sortBy.push({ - name: globalize.translate("AirDate"), - value: "StartDate,SortName" - }); + + return "IsFolder," + sortNameOption.value; + }; + + ItemsView.prototype.getSortMenuOptions = function () { + var sortBy = []; + var params = this.params; + + if ("Programs" === params.type) { + sortBy.push({ + name: globalize.translate("AirDate"), + value: "StartDate,SortName" + }); + } + var option = this.getNameSortOption(params); - return option && sortBy.push(option), option = this.getCommunityRatingSortOption(), option && sortBy.push(option), option = this.getCriticRatingSortOption(), option && sortBy.push(option), "Programs" !== params.type && sortBy.push({ - name: globalize.translate("DateAdded"), - value: "DateCreated,SortName" - }), option = this.getDatePlayedSortOption(), option && sortBy.push(option), params.type || (option = this.getNameSortOption(params), sortBy.push({ - name: globalize.translate("Folders"), - value: "IsFolder," + option.value - })), sortBy.push({ + + if (option) { + sortBy.push(option); + } + + option = this.getCommunityRatingSortOption(); + + if (option) { + sortBy.push(option); + } + + option = this.getCriticRatingSortOption(); + + if (option) { + sortBy.push(option); + } + + if ("Programs" !== params.type) { + sortBy.push({ + name: globalize.translate("DateAdded"), + value: "DateCreated,SortName" + }); + } + + option = this.getDatePlayedSortOption(); + + if (option) { + sortBy.push(option); + } + + if (!params.type) { + option = this.getNameSortOption(params); + sortBy.push({ + name: globalize.translate("Folders"), + value: "IsFolder," + option.value + }); + } + + sortBy.push({ name: globalize.translate("ParentalRating"), value: "OfficialRating,SortName" - }), option = this.getPlayCountSortOption(), option && sortBy.push(option), sortBy.push({ + }); + option = this.getPlayCountSortOption(); + + if (option) { + sortBy.push(option); + } + + sortBy.push({ name: globalize.translate("ReleaseDate"), value: "ProductionYear,PremiereDate,SortName" - }), sortBy.push({ + }); + sortBy.push({ name: globalize.translate("Runtime"), value: "Runtime,SortName" - }), sortBy - }, ItemsView.prototype.getNameSortOption = function(params) { - return "Episode" === params.type ? { - name: globalize.translate("Name"), - value: "SeriesName,SortName" - } : { + }); + return sortBy; + }; + + ItemsView.prototype.getNameSortOption = function (params) { + if ("Episode" === params.type) { + return { + name: globalize.translate("Name"), + value: "SeriesName,SortName" + }; + } + + return { name: globalize.translate("Name"), value: "SortName" + }; + }; + + ItemsView.prototype.getPlayCountSortOption = function () { + if ("Programs" === this.params.type) { + return null; } - }, ItemsView.prototype.getPlayCountSortOption = function() { - return "Programs" === this.params.type ? null : { + + return { name: globalize.translate("PlayCount"), value: "PlayCount,SortName" + }; + }; + + ItemsView.prototype.getDatePlayedSortOption = function () { + if ("Programs" === this.params.type) { + return null; } - }, ItemsView.prototype.getDatePlayedSortOption = function() { - return "Programs" === this.params.type ? null : { + + return { name: globalize.translate("DatePlayed"), value: "DatePlayed,SortName" + }; + }; + + ItemsView.prototype.getCriticRatingSortOption = function () { + if ("Programs" === this.params.type) { + return null; } - }, ItemsView.prototype.getCriticRatingSortOption = function() { - return "Programs" === this.params.type ? null : { + + return { name: globalize.translate("CriticRating"), value: "CriticRating,SortName" - } - }, ItemsView.prototype.getCommunityRatingSortOption = function() { + }; + }; + + ItemsView.prototype.getCommunityRatingSortOption = function () { return { name: globalize.translate("CommunityRating"), value: "CommunityRating,SortName" + }; + }; + + ItemsView.prototype.getVisibleFilters = function () { + var filters = []; + var params = this.params; + + if (!("nextup" === params.type)) { + if ("Programs" === params.type) { + filters.push("Genres"); + } else { + params.type; + filters.push("IsUnplayed"); + filters.push("IsPlayed"); + + if (!params.IsFavorite) { + filters.push("IsFavorite"); + } + + filters.push("IsResumable"); + filters.push("VideoType"); + filters.push("HasSubtitles"); + filters.push("HasTrailer"); + filters.push("HasSpecialFeature"); + filters.push("HasThemeSong"); + filters.push("HasThemeVideo"); + } } - }, ItemsView.prototype.getVisibleFilters = function() { - var filters = [], - params = this.params; - return "nextup" === params.type || ("Programs" === params.type ? filters.push("Genres") : (params.type, filters.push("IsUnplayed"), filters.push("IsPlayed"), params.IsFavorite || filters.push("IsFavorite"), filters.push("IsResumable"), filters.push("VideoType"), filters.push("HasSubtitles"), filters.push("HasTrailer"), filters.push("HasSpecialFeature"), filters.push("HasThemeSong"), filters.push("HasThemeVideo"))), filters - }, ItemsView.prototype.setFilterStatus = function(hasFilters) { + + return filters; + }; + + ItemsView.prototype.setFilterStatus = function (hasFilters) { this.hasFilters = hasFilters; var filterButtons = this.filterButtons; - if (filterButtons.length) + + if (filterButtons.length) { for (var i = 0, length = filterButtons.length; i < length; i++) { - var btnFilter = filterButtons[i], - bubble = btnFilter.querySelector(".filterButtonBubble"); + var btnFilter = filterButtons[i]; + var bubble = btnFilter.querySelector(".filterButtonBubble"); + if (!bubble) { - if (!hasFilters) continue; - btnFilter.insertAdjacentHTML("afterbegin", '
            !
            '), btnFilter.classList.add("btnFilterWithBubble"), bubble = btnFilter.querySelector(".filterButtonBubble") + if (!hasFilters) { + continue; + } + + btnFilter.insertAdjacentHTML("afterbegin", '
            !
            '); + btnFilter.classList.add("btnFilterWithBubble"); + bubble = btnFilter.querySelector(".filterButtonBubble"); + } + + if (hasFilters) { + bubble.classList.remove("hide"); + } else { + bubble.classList.add("hide"); } - hasFilters ? bubble.classList.remove("hide") : bubble.classList.add("hide") } - }, ItemsView.prototype.getFilterMenuOptions = function() { + } + }; + + ItemsView.prototype.getFilterMenuOptions = function () { var params = this.params; return { IsAiring: params.IsAiring, @@ -432,31 +1081,126 @@ define(["globalize", "listView", "layoutManager", "userSettings", "focusManager" IsNews: params.IsNews, IsSeries: params.IsSeries, Recursive: this.queryRecursive + }; + }; + + ItemsView.prototype.getVisibleViewSettings = function () { + var item = (this.params, this.currentItem); + var fields = ["showTitle"]; + + if (!item || "PhotoAlbum" !== item.Type && "ChannelFolderItem" !== item.Type) { + fields.push("imageType"); } - }, ItemsView.prototype.getVisibleViewSettings = function() { - var item = (this.params, this.currentItem), - fields = ["showTitle"]; - return (!item || "PhotoAlbum" !== item.Type && "ChannelFolderItem" !== item.Type) && fields.push("imageType"), fields.push("viewType"), fields - }, ItemsView.prototype.getViewSettings = function() { - var basekey = this.getSettingsKey(), - params = this.params, - item = this.currentItem, - showTitle = userSettings.get(basekey + "-showTitle"); - "true" === showTitle ? showTitle = !0 : "false" === showTitle ? showTitle = !1 : "Programs" === params.type || "Recordings" === params.type || "Person" === params.type || "nextup" === params.type || "Audio" === params.type || "MusicAlbum" === params.type || "MusicArtist" === params.type ? showTitle = !0 : item && "PhotoAlbum" !== item.Type && (showTitle = !0); + + fields.push("viewType"); + return fields; + }; + + ItemsView.prototype.getViewSettings = function () { + var basekey = this.getSettingsKey(); + var params = this.params; + var item = this.currentItem; + var showTitle = userSettings.get(basekey + "-showTitle"); + + if ("true" === showTitle) { + showTitle = true; + } else if ("false" === showTitle) { + showTitle = false; + } else if ("Programs" === params.type || "Recordings" === params.type || "Person" === params.type || "nextup" === params.type || "Audio" === params.type || "MusicAlbum" === params.type || "MusicArtist" === params.type) { + showTitle = true; + } else if (item && "PhotoAlbum" !== item.Type) { + showTitle = true; + } + var imageType = userSettings.get(basekey + "-imageType"); - return imageType || "nextup" === params.type && (imageType = "thumb"), { + + if (!imageType && "nextup" === params.type) { + imageType = "thumb"; + } + + return { showTitle: showTitle, showYear: "false" !== userSettings.get(basekey + "-showYear"), imageType: imageType || "primary", viewType: userSettings.get(basekey + "-viewType") || "images" - } - }, ItemsView.prototype.getItemTypes = function() { + }; + }; + + ItemsView.prototype.getItemTypes = function () { var params = this.params; - return "nextup" === params.type ? ["Episode"] : "Programs" === params.type ? ["Program"] : [] - }, ItemsView.prototype.getSettingsKey = function() { + + if ("nextup" === params.type) { + return ["Episode"]; + } + + if ("Programs" === params.type) { + return ["Program"]; + } + + return []; + }; + + ItemsView.prototype.getSettingsKey = function () { var values = []; values.push("items"); var params = this.params; - return params.type ? values.push(params.type) : params.parentId && values.push(params.parentId), params.IsAiring && values.push("IsAiring"), params.IsMovie && values.push("IsMovie"), params.IsKids && values.push("IsKids"), params.IsSports && values.push("IsSports"), params.IsNews && values.push("IsNews"), params.IsSeries && values.push("IsSeries"), params.IsFavorite && values.push("IsFavorite"), params.genreId && values.push("Genre"), params.musicGenreId && values.push("MusicGenre"), params.studioId && values.push("Studio"), params.personId && values.push("Person"), params.parentId && values.push("Folder"), values.join("-") - }, ItemsView + + if (params.type) { + values.push(params.type); + } else if (params.parentId) { + values.push(params.parentId); + } + + if (params.IsAiring) { + values.push("IsAiring"); + } + + if (params.IsMovie) { + values.push("IsMovie"); + } + + if (params.IsKids) { + values.push("IsKids"); + } + + if (params.IsSports) { + values.push("IsSports"); + } + + if (params.IsNews) { + values.push("IsNews"); + } + + if (params.IsSeries) { + values.push("IsSeries"); + } + + if (params.IsFavorite) { + values.push("IsFavorite"); + } + + if (params.genreId) { + values.push("Genre"); + } + + if (params.musicGenreId) { + values.push("MusicGenre"); + } + + if (params.studioId) { + values.push("Studio"); + } + + if (params.personId) { + values.push("Person"); + } + + if (params.parentId) { + values.push("Folder"); + } + + return values.join("-"); + }; + + return ItemsView; }); diff --git a/src/controllers/livetv/livetvchannels.js b/src/controllers/livetv/livetvchannels.js index cc2eda5053..3e310a17a3 100644 --- a/src/controllers/livetv/livetvchannels.js +++ b/src/controllers/livetv/livetvchannels.js @@ -1,89 +1,119 @@ -define(["cardBuilder", "imageLoader", "libraryBrowser", "loading", "events", "emby-itemscontainer"], function(cardBuilder, imageLoader, libraryBrowser, loading, events) { +define(["cardBuilder", "imageLoader", "libraryBrowser", "loading", "events", "emby-itemscontainer"], function (cardBuilder, imageLoader, libraryBrowser, loading, events) { "use strict"; - return function(view, params, tabContent) { + + return function (view, params, tabContent) { function getPageData() { - return pageData || (pageData = { - query: { - StartIndex: 0, - Limit: 100, - Fields: "PrimaryImageAspectRatio" - } - }), pageData + if (!pageData) { + pageData = { + query: { + StartIndex: 0, + Limit: 100, + Fields: "PrimaryImageAspectRatio" + } + }; + } + + return pageData; } function getQuery() { - return getPageData().query + return getPageData().query; } function getChannelsHtml(channels) { return cardBuilder.getCardsHtml({ items: channels, shape: "square", - showTitle: !0, - lazy: !0, - cardLayout: !0, - showDetailsMenu: !0, - showCurrentProgram: !0, - showCurrentProgramTime: !0 - }) + showTitle: true, + lazy: true, + cardLayout: true, + showDetailsMenu: true, + showCurrentProgram: true, + showCurrentProgramTime: true + }); } function renderChannels(context, result) { function onNextPageClick() { - if (isLoading) return; - query.StartIndex += query.Limit, reloadItems(context) + if (isLoading) { + return; + } + + query.StartIndex += query.Limit; + reloadItems(context); } function onPreviousPageClick() { - if (isLoading) return; - query.StartIndex -= query.Limit, reloadItems(context) + if (isLoading) { + return; + } + + query.StartIndex -= query.Limit; + reloadItems(context); } + var query = getQuery(); context.querySelector(".paging").innerHTML = libraryBrowser.getQueryPagingHtml({ startIndex: query.StartIndex, limit: query.Limit, totalRecordCount: result.TotalRecordCount, - showLimit: !1, - updatePageSizeSetting: !1, - filterButton: !1 + showLimit: false, + updatePageSizeSetting: false, + filterButton: false }); - var html = getChannelsHtml(result.Items), - elem = context.querySelector("#items"); - elem.innerHTML = html, imageLoader.lazyChildren(elem); - var i, length, elems; - for (elems = context.querySelectorAll(".btnNextPage"), i = 0, length = elems.length; i < length; i++) elems[i].addEventListener("click", onNextPageClick); - for (elems = context.querySelectorAll(".btnPreviousPage"), i = 0, length = elems.length; i < length; i++) elems[i].addEventListener("click", onPreviousPageClick) + var html = getChannelsHtml(result.Items); + var elem = context.querySelector("#items"); + elem.innerHTML = html; + imageLoader.lazyChildren(elem); + var i; + var length; + var elems; + + for (elems = context.querySelectorAll(".btnNextPage"), i = 0, length = elems.length; i < length; i++) { + elems[i].addEventListener("click", onNextPageClick); + } + + for (elems = context.querySelectorAll(".btnPreviousPage"), i = 0, length = elems.length; i < length; i++) { + elems[i].addEventListener("click", onPreviousPageClick); + } } function showFilterMenu(context) { - require(["components/filterdialog/filterdialog"], function(filterDialogFactory) { + require(["components/filterdialog/filterdialog"], function (filterDialogFactory) { var filterDialog = new filterDialogFactory({ query: getQuery(), mode: "livetvchannels", serverId: ApiClient.serverId() }); - events.on(filterDialog, "filterchange", function() { - reloadItems(context) - }), filterDialog.show() - }) + events.on(filterDialog, "filterchange", function () { + reloadItems(context); + }); + filterDialog.show(); + }); } function reloadItems(context, save) { loading.show(); isLoading = true; - var query = getQuery(), - apiClient = ApiClient; - query.UserId = apiClient.getCurrentUserId(), apiClient.getLiveTvChannels(query).then(function(result) { + var query = getQuery(); + var apiClient = ApiClient; + query.UserId = apiClient.getCurrentUserId(); + apiClient.getLiveTvChannels(query).then(function (result) { renderChannels(context, result); loading.hide(); isLoading = false; - }) + }); } - var pageData, self = this, isLoading = false; - tabContent.querySelector(".btnFilter").addEventListener("click", function() { - showFilterMenu(tabContent) - }), self.renderTab = function() { - reloadItems(tabContent) - } - } + + var pageData; + var self = this; + var isLoading = false; + tabContent.querySelector(".btnFilter").addEventListener("click", function () { + showFilterMenu(tabContent); + }); + + self.renderTab = function () { + reloadItems(tabContent); + }; + }; }); diff --git a/src/controllers/livetv/livetvguide.js b/src/controllers/livetv/livetvguide.js index 3c8b3f4109..f7c2f1baaa 100644 --- a/src/controllers/livetv/livetvguide.js +++ b/src/controllers/livetv/livetvguide.js @@ -1,16 +1,29 @@ -define(["tvguide"], function(tvguide) { +define(["tvguide"], function (tvguide) { "use strict"; - return function(view, params, tabContent) { - var guideInstance, self = this; - self.renderTab = function() { - guideInstance || (guideInstance = new tvguide({ - element: tabContent, - serverId: ApiClient.serverId() - })) - }, self.onShow = function() { - guideInstance && guideInstance.resume() - }, self.onHide = function() { - guideInstance && guideInstance.pause() - } - } -}); \ No newline at end of file + + return function (view, params, tabContent) { + var guideInstance; + var self = this; + + self.renderTab = function () { + if (!guideInstance) { + guideInstance = new tvguide({ + element: tabContent, + serverId: ApiClient.serverId() + }); + } + }; + + self.onShow = function () { + if (guideInstance) { + guideInstance.resume(); + } + }; + + self.onHide = function () { + if (guideInstance) { + guideInstance.pause(); + } + }; + }; +}); diff --git a/src/controllers/livetv/livetvrecordings.js b/src/controllers/livetv/livetvrecordings.js index f82b150a21..ed3ae24087 100644 --- a/src/controllers/livetv/livetvrecordings.js +++ b/src/controllers/livetv/livetvrecordings.js @@ -1,69 +1,106 @@ -define(["layoutManager", "loading", "cardBuilder", "apphost", "imageLoader", "scripts/livetvcomponents", "listViewStyle", "emby-itemscontainer"], function(layoutManager, loading, cardBuilder, appHost, imageLoader) { +define(["layoutManager", "loading", "cardBuilder", "apphost", "imageLoader", "scripts/livetvcomponents", "listViewStyle", "emby-itemscontainer"], function (layoutManager, loading, cardBuilder, appHost, imageLoader) { "use strict"; function renderRecordings(elem, recordings, cardOptions, scrollX) { - recordings.length ? elem.classList.remove("hide") : elem.classList.add("hide"); + if (recordings.length) { + elem.classList.remove("hide"); + } else { + elem.classList.add("hide"); + } + var recordingItems = elem.querySelector(".recordingItems"); - scrollX ? (recordingItems.classList.add("scrollX"), recordingItems.classList.add("hiddenScrollX"), recordingItems.classList.remove("vertical-wrap")) : (recordingItems.classList.remove("scrollX"), recordingItems.classList.remove("hiddenScrollX"), recordingItems.classList.add("vertical-wrap")); + + if (scrollX) { + recordingItems.classList.add("scrollX"); + recordingItems.classList.add("hiddenScrollX"); + recordingItems.classList.remove("vertical-wrap"); + } else { + recordingItems.classList.remove("scrollX"); + recordingItems.classList.remove("hiddenScrollX"); + recordingItems.classList.add("vertical-wrap"); + } + appHost.supports("imageanalysis"); recordingItems.innerHTML = cardBuilder.getCardsHtml(Object.assign({ items: recordings, shape: scrollX ? "autooverflow" : "auto", defaultShape: scrollX ? "overflowBackdrop" : "backdrop", - showTitle: !0, - showParentTitle: !0, - coverImage: !0, - cardLayout: !1, - centerText: !0, + showTitle: true, + showParentTitle: true, + coverImage: true, + cardLayout: false, + centerText: true, allowBottomPadding: !scrollX, preferThumb: "auto", - overlayText: !1 - }, cardOptions || {})), imageLoader.lazyChildren(recordingItems) + overlayText: false + }, cardOptions || {})); + imageLoader.lazyChildren(recordingItems); } function renderLatestRecordings(context, promise) { - promise.then(function(result) { + promise.then(function (result) { renderRecordings(context.querySelector("#latestRecordings"), result.Items, { - showYear: !0, + showYear: true, lines: 2 - }, !1), loading.hide() - }) + }, false); + loading.hide(); + }); } function renderRecordingFolders(context, promise) { - promise.then(function(result) { + promise.then(function (result) { renderRecordings(context.querySelector("#recordingFolders"), result.Items, { - showYear: !1, - showParentTitle: !1 - }, !1) - }) + showYear: false, + showParentTitle: false + }, false); + }); } function onMoreClick(e) { - var type = this.getAttribute("data-type"), - serverId = ApiClient.serverId(); + var type = this.getAttribute("data-type"); + var serverId = ApiClient.serverId(); + switch (type) { case "latest": - Dashboard.navigate("list.html?type=Recordings&serverId=" + serverId) + Dashboard.navigate("list.html?type=Recordings&serverId=" + serverId); } } - return function(view, params, tabContent) { + + return function (view, params, tabContent) { function enableFullRender() { - return (new Date).getTime() - lastFullRender > 3e5 + return new Date().getTime() - lastFullRender > 300000; } - var foldersPromise, latestPromise, self = this, - lastFullRender = 0; - for (var moreButtons = tabContent.querySelectorAll(".more"), i = 0, length = moreButtons.length; i < length; i++) moreButtons[i].addEventListener("click", onMoreClick); - self.preRender = function() { - enableFullRender() && (latestPromise = ApiClient.getLiveTvRecordings({ - UserId: Dashboard.getCurrentUserId(), - Limit: 12, - Fields: "CanDelete,PrimaryImageAspectRatio,BasicSyncInfo", - EnableTotalRecordCount: !1, - EnableImageTypes: "Primary,Thumb,Backdrop" - }), foldersPromise = ApiClient.getRecordingFolders(Dashboard.getCurrentUserId())) - }, self.renderTab = function() { - enableFullRender() && (loading.show(), renderLatestRecordings(tabContent, latestPromise), renderRecordingFolders(tabContent, foldersPromise), lastFullRender = (new Date).getTime()) + + var foldersPromise; + var latestPromise; + var self = this; + var lastFullRender = 0; + var moreButtons = tabContent.querySelectorAll(".more"); + + for (var i = 0, length = moreButtons.length; i < length; i++) { + moreButtons[i].addEventListener("click", onMoreClick); } - } -}); \ No newline at end of file + + self.preRender = function () { + if (enableFullRender()) { + latestPromise = ApiClient.getLiveTvRecordings({ + UserId: Dashboard.getCurrentUserId(), + Limit: 12, + Fields: "CanDelete,PrimaryImageAspectRatio,BasicSyncInfo", + EnableTotalRecordCount: false, + EnableImageTypes: "Primary,Thumb,Backdrop" + }); + foldersPromise = ApiClient.getRecordingFolders(Dashboard.getCurrentUserId()); + } + }; + + self.renderTab = function () { + if (enableFullRender()) { + loading.show(); + renderLatestRecordings(tabContent, latestPromise); + renderRecordingFolders(tabContent, foldersPromise); + lastFullRender = new Date().getTime(); + } + }; + }; +}); diff --git a/src/controllers/livetv/livetvschedule.js b/src/controllers/livetv/livetvschedule.js index 24ece42dbe..3ee56a2a95 100644 --- a/src/controllers/livetv/livetvschedule.js +++ b/src/controllers/livetv/livetvschedule.js @@ -1,27 +1,50 @@ -define(["layoutManager", "cardBuilder", "apphost", "imageLoader", "loading", "scripts/livetvcomponents", "emby-button", "emby-itemscontainer"], function(layoutManager, cardBuilder, appHost, imageLoader, loading) { +define(["layoutManager", "cardBuilder", "apphost", "imageLoader", "loading", "scripts/livetvcomponents", "emby-button", "emby-itemscontainer"], function (layoutManager, cardBuilder, appHost, imageLoader, loading) { "use strict"; function enableScrollX() { - return !layoutManager.desktop + return !layoutManager.desktop; } function renderRecordings(elem, recordings, cardOptions) { - recordings.length ? elem.classList.remove("hide") : elem.classList.add("hide"); + if (recordings.length) { + elem.classList.remove("hide"); + } else { + elem.classList.add("hide"); + } + var recordingItems = elem.querySelector(".recordingItems"); - enableScrollX() ? (recordingItems.classList.add("scrollX"), layoutManager.tv && recordingItems.classList.add("smoothScrollX"), recordingItems.classList.add("hiddenScrollX"), recordingItems.classList.remove("vertical-wrap")) : (recordingItems.classList.remove("scrollX"), recordingItems.classList.remove("smoothScrollX"), recordingItems.classList.remove("hiddenScrollX"), recordingItems.classList.add("vertical-wrap")); - var supportsImageAnalysis = appHost.supports("imageanalysis"), - cardLayout = appHost.preferVisualCards || supportsImageAnalysis; - cardLayout = !1, recordingItems.innerHTML = cardBuilder.getCardsHtml(Object.assign({ + + if (enableScrollX()) { + recordingItems.classList.add("scrollX"); + + if (layoutManager.tv) { + recordingItems.classList.add("smoothScrollX"); + } + + recordingItems.classList.add("hiddenScrollX"); + recordingItems.classList.remove("vertical-wrap"); + } else { + recordingItems.classList.remove("scrollX"); + recordingItems.classList.remove("smoothScrollX"); + recordingItems.classList.remove("hiddenScrollX"); + recordingItems.classList.add("vertical-wrap"); + } + + var supportsImageAnalysis = appHost.supports("imageanalysis"); + var cardLayout = appHost.preferVisualCards || supportsImageAnalysis; + cardLayout = false; + recordingItems.innerHTML = cardBuilder.getCardsHtml(Object.assign({ items: recordings, shape: enableScrollX() ? "autooverflow" : "auto", - showTitle: !0, - showParentTitle: !0, - coverImage: !0, + showTitle: true, + showParentTitle: true, + coverImage: true, cardLayout: cardLayout, centerText: !cardLayout, allowBottomPadding: !enableScrollX(), preferThumb: "auto" - }, cardOptions || {})), imageLoader.lazyChildren(recordingItems) + }, cardOptions || {})); + imageLoader.lazyChildren(recordingItems); } function getBackdropShape() { @@ -29,52 +52,72 @@ define(["layoutManager", "cardBuilder", "apphost", "imageLoader", "loading", "sc } function renderActiveRecordings(context, promise) { - promise.then(function(result) { + promise.then(function (result) { renderRecordings(context.querySelector("#activeRecordings"), result.Items, { shape: enableScrollX() ? "autooverflow" : "auto", defaultShape: getBackdropShape(), - showParentTitle: !1, - showParentTitleOrTitle: !0, - showTitle: !1, - showAirTime: !0, - showAirEndTime: !0, - showChannelName: !0, - coverImage: !0, - overlayText: !1, - overlayMoreButton: !0 - }) - }) + showParentTitle: false, + showParentTitleOrTitle: true, + showTitle: false, + showAirTime: true, + showAirEndTime: true, + showChannelName: true, + coverImage: true, + overlayText: false, + overlayMoreButton: true + }); + }); } function renderTimers(context, timers, options) { - LiveTvHelpers.getTimersHtml(timers, options).then(function(html) { + LiveTvHelpers.getTimersHtml(timers, options).then(function (html) { var elem = context; - html ? elem.classList.remove("hide") : elem.classList.add("hide"), elem.querySelector(".recordingItems").innerHTML = html, imageLoader.lazyChildren(elem) - }) + + if (html) { + elem.classList.remove("hide"); + } else { + elem.classList.add("hide"); + } + + elem.querySelector(".recordingItems").innerHTML = html; + imageLoader.lazyChildren(elem); + }); } function renderUpcomingRecordings(context, promise) { - promise.then(function(result) { - renderTimers(context.querySelector("#upcomingRecordings"), result.Items), loading.hide() - }) + promise.then(function (result) { + renderTimers(context.querySelector("#upcomingRecordings"), result.Items); + loading.hide(); + }); } - return function(view, params, tabContent) { - var activeRecordingsPromise, upcomingRecordingsPromise, self = this; - tabContent.querySelector("#upcomingRecordings .recordingItems").addEventListener("timercancelled", function() { - self.preRender(), self.renderTab() - }), self.preRender = function() { + + return function (view, params, tabContent) { + var activeRecordingsPromise; + var upcomingRecordingsPromise; + var self = this; + tabContent.querySelector("#upcomingRecordings .recordingItems").addEventListener("timercancelled", function () { + self.preRender(); + self.renderTab(); + }); + + self.preRender = function () { activeRecordingsPromise = ApiClient.getLiveTvRecordings({ UserId: Dashboard.getCurrentUserId(), - IsInProgress: !0, + IsInProgress: true, Fields: "CanDelete,PrimaryImageAspectRatio,BasicSyncInfo", - EnableTotalRecordCount: !1, + EnableTotalRecordCount: false, EnableImageTypes: "Primary,Thumb,Backdrop" - }), upcomingRecordingsPromise = ApiClient.getLiveTvTimers({ - IsActive: !1, - IsScheduled: !0 - }) - }, self.renderTab = function() { - loading.show(), renderActiveRecordings(tabContent, activeRecordingsPromise), renderUpcomingRecordings(tabContent, upcomingRecordingsPromise) - } - } -}); \ No newline at end of file + }); + upcomingRecordingsPromise = ApiClient.getLiveTvTimers({ + IsActive: false, + IsScheduled: true + }); + }; + + self.renderTab = function () { + loading.show(); + renderActiveRecordings(tabContent, activeRecordingsPromise); + renderUpcomingRecordings(tabContent, upcomingRecordingsPromise); + }; + }; +}); diff --git a/src/controllers/livetv/livetvseriestimers.js b/src/controllers/livetv/livetvseriestimers.js index 5acd9f326c..9c95cfa91f 100644 --- a/src/controllers/livetv/livetvseriestimers.js +++ b/src/controllers/livetv/livetvseriestimers.js @@ -1,4 +1,4 @@ -define(["datetime", "cardBuilder", "imageLoader", "apphost", "loading", "paper-icon-button-light", "emby-button"], function(datetime, cardBuilder, imageLoader, appHost, loading) { +define(["datetime", "cardBuilder", "imageLoader", "apphost", "loading", "paper-icon-button-light", "emby-button"], function (datetime, cardBuilder, imageLoader, appHost, loading) { "use strict"; function renderTimers(context, timers) { @@ -8,36 +8,44 @@ define(["datetime", "cardBuilder", "imageLoader", "apphost", "loading", "paper-i items: timers, shape: "auto", defaultShape: "portrait", - showTitle: !0, - cardLayout: !1, + showTitle: true, + cardLayout: false, preferThumb: "auto", - coverImage: !0, - overlayText: !1, - showSeriesTimerTime: !0, - showSeriesTimerChannel: !0, - centerText: !0, - overlayMoreButton: !0, + coverImage: true, + overlayText: false, + showSeriesTimerTime: true, + showSeriesTimerChannel: true, + centerText: true, + overlayMoreButton: true, lines: 3 }); var elem = context.querySelector("#items"); - elem.innerHTML = html, imageLoader.lazyChildren(elem), loading.hide() + elem.innerHTML = html; + imageLoader.lazyChildren(elem); + loading.hide(); } function reload(context, promise) { - loading.show(), promise.then(function(result) { - renderTimers(context, result.Items) - }) + loading.show(); + promise.then(function (result) { + renderTimers(context, result.Items); + }); } + var query = { SortBy: "SortName", SortOrder: "Ascending" }; - return function(view, params, tabContent) { - var timersPromise, self = this; - self.preRender = function() { - timersPromise = ApiClient.getLiveTvSeriesTimers(query) - }, self.renderTab = function() { - reload(tabContent, timersPromise) - } - } -}); \ No newline at end of file + return function (view, params, tabContent) { + var timersPromise; + var self = this; + + self.preRender = function () { + timersPromise = ApiClient.getLiveTvSeriesTimers(query); + }; + + self.renderTab = function () { + reload(tabContent, timersPromise); + }; + }; +}); diff --git a/src/controllers/livetv/livetvsuggested.js b/src/controllers/livetv/livetvsuggested.js index 4fc51467e6..509b7f521c 100644 --- a/src/controllers/livetv/livetvsuggested.js +++ b/src/controllers/livetv/livetvsuggested.js @@ -23,6 +23,7 @@ define(["layoutManager", "userSettings", "inputManager", "loading", "globalize", if (enableScrollX()) { return 12; } + return 9; } @@ -150,15 +151,22 @@ define(["layoutManager", "userSettings", "inputManager", "loading", "globalize", } function getTabs() { - return [ - { name: globalize.translate("Programs") }, - { name: globalize.translate("TabGuide") }, - { name: globalize.translate("TabChannels") }, - { name: globalize.translate("TabRecordings") }, - { name: globalize.translate("HeaderSchedule") }, - { name: globalize.translate("TabSeries") }, - { name: globalize.translate("ButtonSearch"), cssClass: "searchTabButton" } - ]; + return [{ + name: globalize.translate("Programs") + }, { + name: globalize.translate("TabGuide") + }, { + name: globalize.translate("TabChannels") + }, { + name: globalize.translate("TabRecordings") + }, { + name: globalize.translate("HeaderSchedule") + }, { + name: globalize.translate("TabSeries") + }, { + name: globalize.translate("ButtonSearch"), + cssClass: "searchTabButton" + }]; } function setScrollClasses(elem, scrollX) { @@ -183,6 +191,7 @@ define(["layoutManager", "userSettings", "inputManager", "loading", "globalize", if (userSettings.get("landing-" + folderId) === "guide") { return 1; } + return 0; } @@ -220,21 +229,27 @@ define(["layoutManager", "userSettings", "inputManager", "loading", "globalize", switch (index) { case 0: break; + case 1: depends.push("controllers/livetv/livetvguide"); break; + case 2: depends.push("controllers/livetv/livetvchannels"); break; + case 3: depends.push("controllers/livetv/livetvrecordings"); break; + case 4: depends.push("controllers/livetv/livetvschedule"); break; + case 5: depends.push("controllers/livetv/livetvseriestimers"); break; + case 6: depends.push("scripts/searchtab"); } @@ -251,6 +266,7 @@ define(["layoutManager", "userSettings", "inputManager", "loading", "globalize", if (!controller) { tabContent = view.querySelector(".pageTabContent[data-index='" + index + "']"); + if (0 === index) { controller = self; } else if (6 === index) { @@ -260,6 +276,7 @@ define(["layoutManager", "userSettings", "inputManager", "loading", "globalize", } else { controller = new controllerFactory(view, params, tabContent); } + tabControllers[index] = controller; if (controller.initTab) { @@ -347,15 +364,18 @@ define(["layoutManager", "userSettings", "inputManager", "loading", "globalize", }); view.addEventListener("viewshow", function (evt) { isViewRestored = evt.detail.isRestored; + if (!isViewRestored) { mainTabsManager.selectedTabIndex(initialTabIndex); } + inputManager.on(window, onInputCommand); }); - view.addEventListener("viewbeforehide", function (e__u) { + view.addEventListener("viewbeforehide", function (e) { if (currentTabController && currentTabController.onHide) { currentTabController.onHide(); } + inputManager.off(window, onInputCommand); }); view.addEventListener("viewdestroy", function (evt) { diff --git a/src/controllers/livetvguideprovider.js b/src/controllers/livetvguideprovider.js index 40617cdb90..a58917f22d 100644 --- a/src/controllers/livetvguideprovider.js +++ b/src/controllers/livetvguideprovider.js @@ -1,26 +1,30 @@ -define(["events", "loading"], function(events, loading) { +define(["events", "loading"], function (events, loading) { "use strict"; function onListingsSubmitted() { - Dashboard.navigate("livetvstatus.html") + Dashboard.navigate("livetvstatus.html"); } function init(page, type, providerId) { var url = "components/tvproviders/" + type + ".js"; - require([url], function(factory) { + + require([url], function (factory) { var instance = new factory(page, providerId, {}); - events.on(instance, "submitted", onListingsSubmitted), instance.init() - }) + events.on(instance, "submitted", onListingsSubmitted); + instance.init(); + }); } function loadTemplate(page, type, providerId) { - require(["text!./components/tvproviders/" + type + ".template.html"], function(html) { - page.querySelector(".providerTemplate").innerHTML = Globalize.translateDocument(html), init(page, type, providerId) - }) + require(["text!./components/tvproviders/" + type + ".template.html"], function (html) { + page.querySelector(".providerTemplate").innerHTML = Globalize.translateDocument(html); + init(page, type, providerId); + }); } - pageIdOn("pageshow", "liveTvGuideProviderPage", function() { + + pageIdOn("pageshow", "liveTvGuideProviderPage", function () { loading.show(); var providerId = getParameterByName("id"); - loadTemplate(this, getParameterByName("type"), providerId) - }) -}); \ No newline at end of file + loadTemplate(this, getParameterByName("type"), providerId); + }); +}); diff --git a/src/controllers/livetvsettings.js b/src/controllers/livetvsettings.js index 422257e33d..2b11071c75 100644 --- a/src/controllers/livetvsettings.js +++ b/src/controllers/livetvsettings.js @@ -1,79 +1,127 @@ -define(["jQuery", "loading", "fnchecked", "emby-button"], function($, loading) { +define(["jQuery", "loading", "fnchecked", "emby-button"], function ($, loading) { "use strict"; function loadPage(page, config) { - $(".liveTvSettingsForm", page).show(), $(".noLiveTvServices", page).hide(), $("#selectGuideDays", page).val(config.GuideDays || ""), $("#txtPrePaddingMinutes", page).val(config.PrePaddingSeconds / 60), $("#txtPostPaddingMinutes", page).val(config.PostPaddingSeconds / 60), page.querySelector("#txtRecordingPath").value = config.RecordingPath || "", page.querySelector("#txtMovieRecordingPath").value = config.MovieRecordingPath || "", page.querySelector("#txtSeriesRecordingPath").value = config.SeriesRecordingPath || "", page.querySelector("#txtPostProcessor").value = config.RecordingPostProcessor || "", page.querySelector("#txtPostProcessorArguments").value = config.RecordingPostProcessorArguments || "", loading.hide() + $(".liveTvSettingsForm", page).show(); + $(".noLiveTvServices", page).hide(); + $("#selectGuideDays", page).val(config.GuideDays || ""); + $("#txtPrePaddingMinutes", page).val(config.PrePaddingSeconds / 60); + $("#txtPostPaddingMinutes", page).val(config.PostPaddingSeconds / 60); + page.querySelector("#txtRecordingPath").value = config.RecordingPath || ""; + page.querySelector("#txtMovieRecordingPath").value = config.MovieRecordingPath || ""; + page.querySelector("#txtSeriesRecordingPath").value = config.SeriesRecordingPath || ""; + page.querySelector("#txtPostProcessor").value = config.RecordingPostProcessor || ""; + page.querySelector("#txtPostProcessorArguments").value = config.RecordingPostProcessorArguments || ""; + loading.hide(); } function onSubmit() { loading.show(); var form = this; - return ApiClient.getNamedConfiguration("livetv").then(function(config) { + ApiClient.getNamedConfiguration("livetv").then(function (config) { config.GuideDays = $("#selectGuideDays", form).val() || null; - var recordingPath = form.querySelector("#txtRecordingPath").value || null, - movieRecordingPath = form.querySelector("#txtMovieRecordingPath").value || null, - seriesRecordingPath = form.querySelector("#txtSeriesRecordingPath").value || null, - recordingPathChanged = recordingPath != config.RecordingPath || movieRecordingPath != config.MovieRecordingPath || seriesRecordingPath != config.SeriesRecordingPath; - config.RecordingPath = recordingPath, config.MovieRecordingPath = movieRecordingPath, config.SeriesRecordingPath = seriesRecordingPath, config.RecordingEncodingFormat = "mkv", config.PrePaddingSeconds = 60 * $("#txtPrePaddingMinutes", form).val(), config.PostPaddingSeconds = 60 * $("#txtPostPaddingMinutes", form).val(), config.RecordingPostProcessor = $("#txtPostProcessor", form).val(), config.RecordingPostProcessorArguments = $("#txtPostProcessorArguments", form).val(), ApiClient.updateNamedConfiguration("livetv", config).then(function() { - Dashboard.processServerConfigurationUpdateResult(), showSaveMessage(recordingPathChanged) - }) - }), !1 + var recordingPath = form.querySelector("#txtRecordingPath").value || null; + var movieRecordingPath = form.querySelector("#txtMovieRecordingPath").value || null; + var seriesRecordingPath = form.querySelector("#txtSeriesRecordingPath").value || null; + var recordingPathChanged = recordingPath != config.RecordingPath || movieRecordingPath != config.MovieRecordingPath || seriesRecordingPath != config.SeriesRecordingPath; + config.RecordingPath = recordingPath; + config.MovieRecordingPath = movieRecordingPath; + config.SeriesRecordingPath = seriesRecordingPath; + config.RecordingEncodingFormat = "mkv"; + config.PrePaddingSeconds = 60 * $("#txtPrePaddingMinutes", form).val(); + config.PostPaddingSeconds = 60 * $("#txtPostPaddingMinutes", form).val(); + config.RecordingPostProcessor = $("#txtPostProcessor", form).val(); + config.RecordingPostProcessorArguments = $("#txtPostProcessorArguments", form).val(); + ApiClient.updateNamedConfiguration("livetv", config).then(function () { + Dashboard.processServerConfigurationUpdateResult(); + showSaveMessage(recordingPathChanged); + }); + }); + return false; } function showSaveMessage(recordingPathChanged) { var msg = ""; - recordingPathChanged && (msg += Globalize.translate("RecordingPathChangeMessage")), msg && require(["alert"], function(alert) { - alert(msg) - }) + + if (recordingPathChanged) { + msg += Globalize.translate("RecordingPathChangeMessage"); + } + + if (msg) { + require(["alert"], function (alert) { + alert(msg); + }); + } } - $(document).on("pageinit", "#liveTvSettingsPage", function() { + + $(document).on("pageinit", "#liveTvSettingsPage", function () { var page = this; - $(".liveTvSettingsForm").off("submit", onSubmit).on("submit", onSubmit), $("#btnSelectRecordingPath", page).on("click.selectDirectory", function() { - require(["directorybrowser"], function(directoryBrowser) { - var picker = new directoryBrowser; + $(".liveTvSettingsForm").off("submit", onSubmit).on("submit", onSubmit); + $("#btnSelectRecordingPath", page).on("click.selectDirectory", function () { + require(["directorybrowser"], function (directoryBrowser) { + var picker = new directoryBrowser(); picker.show({ - callback: function(path) { - path && $("#txtRecordingPath", page).val(path), picker.close() + callback: function (path) { + if (path) { + $("#txtRecordingPath", page).val(path); + } + + picker.close(); }, - validateWriteable: !0 - }) - }) - }), $("#btnSelectMovieRecordingPath", page).on("click.selectDirectory", function() { - require(["directorybrowser"], function(directoryBrowser) { - var picker = new directoryBrowser; + validateWriteable: true + }); + }); + }); + $("#btnSelectMovieRecordingPath", page).on("click.selectDirectory", function () { + require(["directorybrowser"], function (directoryBrowser) { + var picker = new directoryBrowser(); picker.show({ - callback: function(path) { - path && $("#txtMovieRecordingPath", page).val(path), picker.close() + callback: function (path) { + if (path) { + $("#txtMovieRecordingPath", page).val(path); + } + + picker.close(); }, - validateWriteable: !0 - }) - }) - }), $("#btnSelectSeriesRecordingPath", page).on("click.selectDirectory", function() { - require(["directorybrowser"], function(directoryBrowser) { - var picker = new directoryBrowser; + validateWriteable: true + }); + }); + }); + $("#btnSelectSeriesRecordingPath", page).on("click.selectDirectory", function () { + require(["directorybrowser"], function (directoryBrowser) { + var picker = new directoryBrowser(); picker.show({ - callback: function(path) { - path && $("#txtSeriesRecordingPath", page).val(path), picker.close() + callback: function (path) { + if (path) { + $("#txtSeriesRecordingPath", page).val(path); + } + + picker.close(); }, - validateWriteable: !0 - }) - }) - }), $("#btnSelectPostProcessorPath", page).on("click.selectDirectory", function() { - require(["directorybrowser"], function(directoryBrowser) { - var picker = new directoryBrowser; + validateWriteable: true + }); + }); + }); + $("#btnSelectPostProcessorPath", page).on("click.selectDirectory", function () { + require(["directorybrowser"], function (directoryBrowser) { + var picker = new directoryBrowser(); picker.show({ - includeFiles: !0, - callback: function(path) { - path && $("#txtPostProcessor", page).val(path), picker.close() + includeFiles: true, + callback: function (path) { + if (path) { + $("#txtPostProcessor", page).val(path); + } + + picker.close(); } - }) - }) - }) - }).on("pageshow", "#liveTvSettingsPage", function() { + }); + }); + }); + }).on("pageshow", "#liveTvSettingsPage", function () { loading.show(); var page = this; - ApiClient.getNamedConfiguration("livetv").then(function(config) { - loadPage(page, config) - }) - }) -}); \ No newline at end of file + ApiClient.getNamedConfiguration("livetv").then(function (config) { + loadPage(page, config); + }); + }); +}); diff --git a/src/controllers/livetvstatus.js b/src/controllers/livetvstatus.js index d268be2991..03cad1a907 100644 --- a/src/controllers/livetvstatus.js +++ b/src/controllers/livetvstatus.js @@ -1,42 +1,75 @@ -define(["jQuery", "globalize", "scripts/taskbutton", "dom", "libraryMenu", "layoutManager", "loading", "listViewStyle", "flexStyles", "emby-itemscontainer", "cardStyle", "material-icons", "emby-button"], function($, globalize, taskButton, dom, libraryMenu, layoutManager, loading) { +define(["jQuery", "globalize", "scripts/taskbutton", "dom", "libraryMenu", "layoutManager", "loading", "listViewStyle", "flexStyles", "emby-itemscontainer", "cardStyle", "material-icons", "emby-button"], function ($, globalize, taskButton, dom, libraryMenu, layoutManager, loading) { "use strict"; function getDeviceHtml(device) { - var padderClass, html = "", - cssClass = "card scalableCard", - cardBoxCssClass = "cardBox visualCardBox"; - return cssClass += " backdropCard backdropCard-scalable", padderClass = "cardPadder-backdrop", layoutManager.tv && (cssClass += " card-focusscale", cardBoxCssClass += " cardBox-focustransform"), cardBoxCssClass += " card-focuscontent", html += '
            ', html += '
            ', html += '
            ', html += '
            ', html += '
            ', html += '
            dvr
            ', html += "
            ", html += "
            ", html += '
            ', html += '', html += '
            ' + (device.FriendlyName || getTunerName(device.Type)) + "
            ", html += '
            ', html += device.Url || " ", html += "
            ", html += "
            ", html += "
            ", html += "
            " + var padderClass; + var html = ""; + var cssClass = "card scalableCard"; + var cardBoxCssClass = "cardBox visualCardBox"; + cssClass += " backdropCard backdropCard-scalable"; + padderClass = "cardPadder-backdrop"; + + if (layoutManager.tv) { + cssClass += " card-focusscale"; + cardBoxCssClass += " cardBox-focustransform"; + } + + cardBoxCssClass += " card-focuscontent"; + html += '
            '; + html += '
            '; + html += '
            '; + html += '
            '; + html += '
            '; + html += '
            dvr
            '; + html += "
            "; + html += "
            "; + html += '
            '; + html += ''; + html += '
            ' + (device.FriendlyName || getTunerName(device.Type)) + "
            "; + html += '
            '; + html += device.Url || " "; + html += "
            "; + html += "
            "; + html += "
            "; + return html += "
            "; } function renderDevices(page, devices) { var html = devices.map(getDeviceHtml).join(""); - page.querySelector(".devicesList").innerHTML = html + page.querySelector(".devicesList").innerHTML = html; } function deleteDevice(page, id) { var message = globalize.translate("MessageConfirmDeleteTunerDevice"); - require(["confirm"], function(confirm) { - confirm(message, globalize.translate("HeaderDeleteDevice")).then(function() { - loading.show(), ApiClient.ajax({ + + require(["confirm"], function (confirm) { + confirm(message, globalize.translate("HeaderDeleteDevice")).then(function () { + loading.show(); + ApiClient.ajax({ type: "DELETE", url: ApiClient.getUrl("LiveTv/TunerHosts", { Id: id }) - }).then(function() { - reload(page) - }) - }) - }) + }).then(function () { + reload(page); + }); + }); + }); } function reload(page) { - loading.show(), ApiClient.getNamedConfiguration("livetv").then(function(config) { - renderDevices(page, config.TunerHosts), renderProviders(page, config.ListingProviders) - }), loading.hide() + loading.show(); + ApiClient.getNamedConfiguration("livetv").then(function (config) { + renderDevices(page, config.TunerHosts); + renderProviders(page, config.ListingProviders); + }); + loading.hide(); } function submitAddDeviceForm(page) { - page.querySelector(".dlgAddDevice").close(), loading.show(), ApiClient.ajax({ + page.querySelector(".dlgAddDevice").close(); + loading.show(); + ApiClient.ajax({ type: "POST", url: ApiClient.getUrl("LiveTv/TunerHosts"), data: JSON.stringify({ @@ -44,30 +77,47 @@ define(["jQuery", "globalize", "scripts/taskbutton", "dom", "libraryMenu", "layo Url: $("#txtDevicePath", page).val() }), contentType: "application/json" - }).then(function() { - reload(page) - }, function() { + }).then(function () { + reload(page); + }, function () { Dashboard.alert({ message: globalize.translate("ErrorAddingTunerDevice") - }) - }) + }); + }); } function renderProviders(page, providers) { var html = ""; + if (providers.length) { html += '
            '; + for (var i = 0, length = providers.length; i < length; i++) { var provider = providers[i]; - html += '" + html += '"; } - html += "
            " + + html += "
"; } + var elem = $(".providerList", page).html(html); - $(".btnOptions", elem).on("click", function() { + $(".btnOptions", elem).on("click", function () { var id = this.getAttribute("data-id"); - showProviderOptions(page, id, this) - }) + showProviderOptions(page, id, this); + }); } function showProviderOptions(page, providerId, button) { @@ -75,64 +125,74 @@ define(["jQuery", "globalize", "scripts/taskbutton", "dom", "libraryMenu", "layo items.push({ name: globalize.translate("ButtonDelete"), id: "delete" - }), items.push({ + }); + items.push({ name: globalize.translate("MapChannels"), id: "map" - }), require(["actionsheet"], function(actionsheet) { + }); + + require(["actionsheet"], function (actionsheet) { actionsheet.show({ items: items, positionTo: button - }).then(function(id) { + }).then(function (id) { switch (id) { case "delete": deleteProvider(page, providerId); break; + case "map": - mapChannels(page, providerId) + mapChannels(page, providerId); } - }) - }) + }); + }); } function mapChannels(page, providerId) { - require(["components/channelmapper/channelmapper"], function(channelmapper) { + require(["components/channelmapper/channelmapper"], function (channelmapper) { new channelmapper({ serverId: ApiClient.serverInfo().Id, providerId: providerId - }).show() - }) + }).show(); + }); } function deleteProvider(page, id) { var message = globalize.translate("MessageConfirmDeleteGuideProvider"); - require(["confirm"], function(confirm) { - confirm(message, globalize.translate("HeaderDeleteProvider")).then(function() { - loading.show(), ApiClient.ajax({ + + require(["confirm"], function (confirm) { + confirm(message, globalize.translate("HeaderDeleteProvider")).then(function () { + loading.show(); + ApiClient.ajax({ type: "DELETE", url: ApiClient.getUrl("LiveTv/ListingProviders", { Id: id }) - }).then(function() { - reload(page) - }, function() { - reload(page) - }) - }) - }) + }).then(function () { + reload(page); + }, function () { + reload(page); + }); + }); + }); } function getTunerName(providerId) { switch (providerId = providerId.toLowerCase()) { case "m3u": return "M3U"; + case "hdhomerun": return "HDHomerun"; + case "hauppauge": return "Hauppauge"; + case "satip": return "DVB"; + default: - return "Unknown" + return "Unknown"; } } @@ -140,12 +200,15 @@ define(["jQuery", "globalize", "scripts/taskbutton", "dom", "libraryMenu", "layo switch (providerId = providerId.toLowerCase()) { case "schedulesdirect": return "Schedules Direct"; + case "xmltv": return "Xml TV"; + case "emby": return "Emby Guide"; + default: - return "Unknown" + return "Unknown"; } } @@ -153,10 +216,12 @@ define(["jQuery", "globalize", "scripts/taskbutton", "dom", "libraryMenu", "layo switch (providerId = providerId.toLowerCase()) { case "xmltv": return "livetvguideprovider.html?type=xmltv"; + case "schedulesdirect": return "livetvguideprovider.html?type=schedulesdirect"; + case "emby": - return "livetvguideprovider.html?type=emby" + return "livetvguideprovider.html?type=emby"; } } @@ -165,22 +230,25 @@ define(["jQuery", "globalize", "scripts/taskbutton", "dom", "libraryMenu", "layo menuItems.push({ name: "Schedules Direct", id: "SchedulesDirect" - }), menuItems.push({ + }); + menuItems.push({ name: "Xml TV", id: "xmltv" - }), require(["actionsheet"], function(actionsheet) { + }); + + require(["actionsheet"], function (actionsheet) { actionsheet.show({ items: menuItems, positionTo: button, - callback: function(id) { - Dashboard.navigate(getProviderConfigurationUrl(id)) + callback: function (id) { + Dashboard.navigate(getProviderConfigurationUrl(id)); } - }) - }) + }); + }); } function addDevice(button) { - Dashboard.navigate("livetvtuner.html") + Dashboard.navigate("livetvtuner.html"); } function showDeviceMenu(button, tunerDeviceId) { @@ -188,57 +256,73 @@ define(["jQuery", "globalize", "scripts/taskbutton", "dom", "libraryMenu", "layo items.push({ name: globalize.translate("ButtonDelete"), id: "delete" - }), items.push({ + }); + items.push({ name: globalize.translate("ButtonEdit"), id: "edit" - }), require(["actionsheet"], function(actionsheet) { + }); + + require(["actionsheet"], function (actionsheet) { actionsheet.show({ items: items, positionTo: button - }).then(function(id) { + }).then(function (id) { switch (id) { case "delete": deleteDevice(dom.parentWithClass(button, "page"), tunerDeviceId); break; + case "edit": - Dashboard.navigate("livetvtuner.html?id=" + tunerDeviceId) + Dashboard.navigate("livetvtuner.html?id=" + tunerDeviceId); } - }) - }) + }); + }); } function onDevicesListClick(e) { var card = dom.parentWithClass(e.target, "card"); + if (card) { - var id = card.getAttribute("data-id"), - btnCardOptions = dom.parentWithClass(e.target, "btnCardOptions"); - btnCardOptions ? showDeviceMenu(btnCardOptions, id) : Dashboard.navigate("livetvtuner.html?id=" + id) + var id = card.getAttribute("data-id"); + var btnCardOptions = dom.parentWithClass(e.target, "btnCardOptions"); + + if (btnCardOptions) { + showDeviceMenu(btnCardOptions, id); + } else { + Dashboard.navigate("livetvtuner.html?id=" + id); + } } } - $(document).on("pageinit", "#liveTvStatusPage", function() { + + $(document).on("pageinit", "#liveTvStatusPage", function () { var page = this; - $(".btnAddDevice", page).on("click", function() { - addDevice(this) - }), $(".formAddDevice", page).on("submit", function() { - return submitAddDeviceForm(page), !1 - }), $(".btnAddProvider", page).on("click", function() { - addProvider(this) - }), page.querySelector(".devicesList").addEventListener("click", onDevicesListClick) - }).on("pageshow", "#liveTvStatusPage", function() { + $(".btnAddDevice", page).on("click", function () { + addDevice(this); + }); + $(".formAddDevice", page).on("submit", function () { + submitAddDeviceForm(page); + return false; + }); + $(".btnAddProvider", page).on("click", function () { + addProvider(this); + }); + page.querySelector(".devicesList").addEventListener("click", onDevicesListClick); + }).on("pageshow", "#liveTvStatusPage", function () { var page = this; - reload(page), taskButton({ + reload(page); + taskButton({ mode: "on", progressElem: page.querySelector(".refreshGuideProgress"), taskKey: "RefreshGuide", button: page.querySelector(".btnRefresh") - }) - }).on("pagehide", "#liveTvStatusPage", function() { + }); + }).on("pagehide", "#liveTvStatusPage", function () { var page = this; taskButton({ mode: "off", progressElem: page.querySelector(".refreshGuideProgress"), taskKey: "RefreshGuide", button: page.querySelector(".btnRefresh") - }) - }) + }); + }); }); diff --git a/src/controllers/livetvtuner.js b/src/controllers/livetvtuner.js index 43082e6844..55a86d4be7 100644 --- a/src/controllers/livetvtuner.js +++ b/src/controllers/livetvtuner.js @@ -1,4 +1,4 @@ -define(["globalize", "loading", "libraryMenu", "dom", "emby-input", "emby-button", "emby-checkbox", "emby-select"], function(globalize, loading, libraryMenu, dom) { +define(["globalize", "loading", "libraryMenu", "dom", "emby-input", "emby-button", "emby-checkbox", "emby-select"], function (globalize, loading, libraryMenu, dom) { "use strict"; function isM3uVariant(type) { @@ -6,17 +6,16 @@ define(["globalize", "loading", "libraryMenu", "dom", "emby-input", "emby-button } function fillTypes(view, currentId) { - return ApiClient.getJSON(ApiClient.getUrl("LiveTv/TunerHosts/Types")).then(function(types) { + return ApiClient.getJSON(ApiClient.getUrl("LiveTv/TunerHosts/Types")).then(function (types) { var selectType = view.querySelector(".selectType"); var html = ""; - html += types.map(function(tuner) { + html += types.map(function (tuner) { return '"; }).join(""); html += '"; selectType.innerHTML = html; - selectType.disabled = null != currentId; selectType.value = ""; onTypeChange.call(selectType); @@ -27,9 +26,10 @@ define(["globalize", "loading", "libraryMenu", "dom", "emby-input", "emby-button view.querySelector(".txtDevicePath").value = ""; view.querySelector(".chkFavorite").checked = false; view.querySelector(".txtDevicePath").value = ""; + if (providerId) { - ApiClient.getNamedConfiguration("livetv").then(function(config) { - var info = config.TunerHosts.filter(function(i) { + ApiClient.getNamedConfiguration("livetv").then(function (config) { + var info = config.TunerHosts.filter(function (i) { return i.Id === providerId; })[0]; fillTunerHostInfo(view, info); @@ -40,9 +40,11 @@ define(["globalize", "loading", "libraryMenu", "dom", "emby-input", "emby-button function fillTunerHostInfo(view, info) { var selectType = view.querySelector(".selectType"); var type = info.Type || ""; + if (info.Source && isM3uVariant(info.Source)) { type = info.Source; } + selectType.value = type; onTypeChange.call(selectType); view.querySelector(".txtDevicePath").value = info.Url || ""; @@ -68,76 +70,164 @@ define(["globalize", "loading", "libraryMenu", "dom", "emby-input", "emby-button AllowHWTranscoding: page.querySelector(".chkTranscode").checked, EnableStreamLooping: page.querySelector(".chkStreamLoop").checked }; - isM3uVariant(info.Type) && (info.Source = info.Type, info.Type = "m3u"); + + if (isM3uVariant(info.Type)) { + info.Source = info.Type; + info.Type = "m3u"; + } + var id = getParameterByName("id"); - id && (info.Id = id); + + if (id) { + info.Id = id; + } + info.Id; ApiClient.ajax({ type: "POST", url: ApiClient.getUrl("LiveTv/TunerHosts"), data: JSON.stringify(info), contentType: "application/json" - }).then(function(result) { - Dashboard.processServerConfigurationUpdateResult(), Dashboard.navigate("livetvstatus.html") - }, function() { - loading.hide(), Dashboard.alert({ + }).then(function (result) { + Dashboard.processServerConfigurationUpdateResult(); + Dashboard.navigate("livetvstatus.html"); + }, function () { + loading.hide(); + Dashboard.alert({ message: globalize.translate("ErrorSavingTvProvider") - }) - }) + }); + }); } function getRequirePromise(deps) { - return new Promise(function(resolve, reject) { - require(deps, resolve) - }) + return new Promise(function (resolve, reject) { + require(deps, resolve); + }); } function getDetectedDevice() { - return getRequirePromise(["tunerPicker"]).then(function(tunerPicker) { - return (new tunerPicker).show({ + return getRequirePromise(["tunerPicker"]).then(function (tunerPicker) { + return new tunerPicker().show({ serverId: ApiClient.serverId() - }) - }) + }); + }); } function onTypeChange() { - var value = this.value, - view = dom.parentWithClass(this, "page"), - mayIncludeUnsupportedDrmChannels = "hdhomerun" === value, - supportsTranscoding = "hdhomerun" === value, - supportsFavorites = "hdhomerun" === value, - supportsTunerIpAddress = "hdhomerun" === value, - supportsTunerFileOrUrl = "m3u" === value, - supportsStreamLooping = "m3u" === value, - supportsTunerCount = "m3u" === value, - supportsUserAgent = "m3u" === value, - suppportsSubmit = "other" !== value, - supportsSelectablePath = supportsTunerFileOrUrl, - txtDevicePath = view.querySelector(".txtDevicePath"); - supportsTunerIpAddress ? (txtDevicePath.label(globalize.translate("LabelTunerIpAddress")), view.querySelector(".fldPath").classList.remove("hide")) : supportsTunerFileOrUrl ? (txtDevicePath.label(globalize.translate("LabelFileOrUrl")), view.querySelector(".fldPath").classList.remove("hide")) : view.querySelector(".fldPath").classList.add("hide"), supportsSelectablePath ? (view.querySelector(".btnSelectPath").classList.remove("hide"), view.querySelector(".txtDevicePath").setAttribute("required", "required")) : (view.querySelector(".btnSelectPath").classList.add("hide"), view.querySelector(".txtDevicePath").removeAttribute("required")), supportsUserAgent ? view.querySelector(".fldUserAgent").classList.remove("hide") : view.querySelector(".fldUserAgent").classList.add("hide"), supportsFavorites ? view.querySelector(".fldFavorites").classList.remove("hide") : view.querySelector(".fldFavorites").classList.add("hide"), supportsTranscoding ? view.querySelector(".fldTranscode").classList.remove("hide") : view.querySelector(".fldTranscode").classList.add("hide"), supportsStreamLooping ? view.querySelector(".fldStreamLoop").classList.remove("hide") : view.querySelector(".fldStreamLoop").classList.add("hide"), supportsTunerCount ? (view.querySelector(".fldTunerCount").classList.remove("hide"), view.querySelector(".txtTunerCount").setAttribute("required", "required")) : (view.querySelector(".fldTunerCount").classList.add("hide"), view.querySelector(".txtTunerCount").removeAttribute("required")), mayIncludeUnsupportedDrmChannels ? view.querySelector(".drmMessage").classList.remove("hide") : view.querySelector(".drmMessage").classList.add("hide"), suppportsSubmit ? view.querySelector(".button-submit").classList.remove("hide") : view.querySelector(".button-submit").classList.add("hide") + var value = this.value; + var view = dom.parentWithClass(this, "page"); + var mayIncludeUnsupportedDrmChannels = "hdhomerun" === value; + var supportsTranscoding = "hdhomerun" === value; + var supportsFavorites = "hdhomerun" === value; + var supportsTunerIpAddress = "hdhomerun" === value; + var supportsTunerFileOrUrl = "m3u" === value; + var supportsStreamLooping = "m3u" === value; + var supportsTunerCount = "m3u" === value; + var supportsUserAgent = "m3u" === value; + var suppportsSubmit = "other" !== value; + var supportsSelectablePath = supportsTunerFileOrUrl; + var txtDevicePath = view.querySelector(".txtDevicePath"); + + if (supportsTunerIpAddress) { + txtDevicePath.label(globalize.translate("LabelTunerIpAddress")); + view.querySelector(".fldPath").classList.remove("hide"); + } else if (supportsTunerFileOrUrl) { + txtDevicePath.label(globalize.translate("LabelFileOrUrl")); + view.querySelector(".fldPath").classList.remove("hide"); + } else { + view.querySelector(".fldPath").classList.add("hide"); + } + + if (supportsSelectablePath) { + view.querySelector(".btnSelectPath").classList.remove("hide"); + view.querySelector(".txtDevicePath").setAttribute("required", "required"); + } else { + view.querySelector(".btnSelectPath").classList.add("hide"); + view.querySelector(".txtDevicePath").removeAttribute("required"); + } + + if (supportsUserAgent) { + view.querySelector(".fldUserAgent").classList.remove("hide"); + } else { + view.querySelector(".fldUserAgent").classList.add("hide"); + } + + if (supportsFavorites) { + view.querySelector(".fldFavorites").classList.remove("hide"); + } else { + view.querySelector(".fldFavorites").classList.add("hide"); + } + + if (supportsTranscoding) { + view.querySelector(".fldTranscode").classList.remove("hide"); + } else { + view.querySelector(".fldTranscode").classList.add("hide"); + } + + if (supportsStreamLooping) { + view.querySelector(".fldStreamLoop").classList.remove("hide"); + } else { + view.querySelector(".fldStreamLoop").classList.add("hide"); + } + + if (supportsTunerCount) { + view.querySelector(".fldTunerCount").classList.remove("hide"); + view.querySelector(".txtTunerCount").setAttribute("required", "required"); + } else { + view.querySelector(".fldTunerCount").classList.add("hide"); + view.querySelector(".txtTunerCount").removeAttribute("required"); + } + + if (mayIncludeUnsupportedDrmChannels) { + view.querySelector(".drmMessage").classList.remove("hide"); + } else { + view.querySelector(".drmMessage").classList.add("hide"); + } + + if (suppportsSubmit) { + view.querySelector(".button-submit").classList.remove("hide"); + } else { + view.querySelector(".button-submit").classList.add("hide"); + } } - return function(view, params) { - params.id || view.querySelector(".btnDetect").classList.remove("hide"), view.addEventListener("viewshow", function() { + + return function (view, params) { + if (!params.id) { + view.querySelector(".btnDetect").classList.remove("hide"); + } + + view.addEventListener("viewshow", function () { var currentId = params.id; - fillTypes(view, currentId).then(function() { - reload(view, currentId) - }) - }), view.querySelector("form").addEventListener("submit", function(e) { - return submitForm(view), e.preventDefault(), e.stopPropagation(), !1 - }), view.querySelector(".selectType").addEventListener("change", onTypeChange), view.querySelector(".btnDetect").addEventListener("click", function() { - getDetectedDevice().then(function(info) { - fillTunerHostInfo(view, info) - }) - }), view.querySelector(".btnSelectPath").addEventListener("click", function() { - require(["directorybrowser"], function(directoryBrowser) { - var picker = new directoryBrowser; + fillTypes(view, currentId).then(function () { + reload(view, currentId); + }); + }); + view.querySelector("form").addEventListener("submit", function (e) { + submitForm(view); + e.preventDefault(); + e.stopPropagation(); + return false; + }); + view.querySelector(".selectType").addEventListener("change", onTypeChange); + view.querySelector(".btnDetect").addEventListener("click", function () { + getDetectedDevice().then(function (info) { + fillTunerHostInfo(view, info); + }); + }); + view.querySelector(".btnSelectPath").addEventListener("click", function () { + require(["directorybrowser"], function (directoryBrowser) { + var picker = new directoryBrowser(); picker.show({ - includeFiles: !0, - callback: function(path) { - path && (view.querySelector(".txtDevicePath").value = path), picker.close() + includeFiles: true, + callback: function (path) { + if (path) { + view.querySelector(".txtDevicePath").value = path; + } + + picker.close(); } - }) - }) - }) - } -}); \ No newline at end of file + }); + }); + }); + }; +}); diff --git a/src/controllers/metadatanfo.js b/src/controllers/metadatanfo.js index 1de17ae836..20049837dd 100644 --- a/src/controllers/metadatanfo.js +++ b/src/controllers/metadatanfo.js @@ -1,30 +1,45 @@ -define(["jQuery", "loading", "libraryMenu"], function($, loading, libraryMenu) { +define(["jQuery", "loading", "libraryMenu"], function ($, loading, libraryMenu) { "use strict"; function loadPage(page, config, users) { var html = '"; - html += users.map(function(user) { - return '" - }).join(""), $("#selectUser", page).html(html).val(config.UserId || ""), $("#selectReleaseDateFormat", page).val(config.ReleaseDateFormat), page.querySelector("#chkSaveImagePaths").checked = config.SaveImagePathsInNfo, page.querySelector("#chkEnablePathSubstitution").checked = config.EnablePathSubstitution, page.querySelector("#chkEnableExtraThumbs").checked = config.EnableExtraThumbsDuplication, loading.hide() + html += users.map(function (user) { + return '"; + }).join(""); + $("#selectUser", page).html(html).val(config.UserId || ""); + $("#selectReleaseDateFormat", page).val(config.ReleaseDateFormat); + page.querySelector("#chkSaveImagePaths").checked = config.SaveImagePathsInNfo; + page.querySelector("#chkEnablePathSubstitution").checked = config.EnablePathSubstitution; + page.querySelector("#chkEnableExtraThumbs").checked = config.EnableExtraThumbsDuplication; + loading.hide(); } function onSubmit() { loading.show(); var form = this; - return ApiClient.getNamedConfiguration(metadataKey).then(function(config) { - config.UserId = $("#selectUser", form).val() || null, config.ReleaseDateFormat = $("#selectReleaseDateFormat", form).val(), config.SaveImagePathsInNfo = form.querySelector("#chkSaveImagePaths").checked, config.EnablePathSubstitution = form.querySelector("#chkEnablePathSubstitution").checked, config.EnableExtraThumbsDuplication = form.querySelector("#chkEnableExtraThumbs").checked, ApiClient.updateNamedConfiguration(metadataKey, config).then(function() { - Dashboard.processServerConfigurationUpdateResult(), showConfirmMessage(config) - }) - }), !1 + ApiClient.getNamedConfiguration(metadataKey).then(function (config) { + config.UserId = $("#selectUser", form).val() || null; + config.ReleaseDateFormat = $("#selectReleaseDateFormat", form).val(); + config.SaveImagePathsInNfo = form.querySelector("#chkSaveImagePaths").checked; + config.EnablePathSubstitution = form.querySelector("#chkEnablePathSubstitution").checked; + config.EnableExtraThumbsDuplication = form.querySelector("#chkEnableExtraThumbs").checked; + ApiClient.updateNamedConfiguration(metadataKey, config).then(function () { + Dashboard.processServerConfigurationUpdateResult(); + showConfirmMessage(config); + }); + }); + return false; } function showConfirmMessage(config) { var msg = []; - msg.push(Globalize.translate("MetadataSettingChangeHelp")), require(["alert"], function(alert) { + msg.push(Globalize.translate("MetadataSettingChangeHelp")); + + require(["alert"], function (alert) { alert({ text: msg.join("

") - }) - }) + }); + }); } function getTabs() { @@ -40,19 +55,20 @@ define(["jQuery", "loading", "libraryMenu"], function($, loading, libraryMenu) { }, { href: "metadatanfo.html", name: Globalize.translate("TabNfoSettings") - }] + }]; } var metadataKey = "xbmcmetadata"; - $(document).on("pageinit", "#metadataNfoPage", function() { - $(".metadataNfoForm").off("submit", onSubmit).on("submit", onSubmit) - }).on("pageshow", "#metadataNfoPage", function() { - libraryMenu.setTabs("metadata", 3, getTabs), loading.show(); - var page = this, - promise1 = ApiClient.getUsers(), - promise2 = ApiClient.getNamedConfiguration(metadataKey); - Promise.all([promise1, promise2]).then(function(responses) { - loadPage(page, responses[1], responses[0]) - }) - }) -}); \ No newline at end of file + $(document).on("pageinit", "#metadataNfoPage", function () { + $(".metadataNfoForm").off("submit", onSubmit).on("submit", onSubmit); + }).on("pageshow", "#metadataNfoPage", function () { + libraryMenu.setTabs("metadata", 3, getTabs); + loading.show(); + var page = this; + var promise1 = ApiClient.getUsers(); + var promise2 = ApiClient.getNamedConfiguration(metadataKey); + Promise.all([promise1, promise2]).then(function (responses) { + loadPage(page, responses[1], responses[0]); + }); + }); +}); diff --git a/src/controllers/movies/moviecollections.js b/src/controllers/movies/moviecollections.js index 1e83f11f3c..d5bd96d349 100644 --- a/src/controllers/movies/moviecollections.js +++ b/src/controllers/movies/moviecollections.js @@ -1,9 +1,11 @@ -define(["loading", "events", "libraryBrowser", "imageLoader", "listView", "cardBuilder", "apphost", "emby-itemscontainer"], function(loading, events, libraryBrowser, imageLoader, listView, cardBuilder, appHost) { +define(["loading", "events", "libraryBrowser", "imageLoader", "listView", "cardBuilder", "apphost", "emby-itemscontainer"], function (loading, events, libraryBrowser, imageLoader, listView, cardBuilder, appHost) { "use strict"; - return function(view, params, tabContent) { + + return function (view, params, tabContent) { function getPageData(context) { - var key = getSavedQueryKey(context), - pageData = data[key]; + var key = getSavedQueryKey(context); + var pageData = data[key]; + if (!pageData) { pageData = data[key] = { query: { @@ -22,153 +24,223 @@ define(["loading", "events", "libraryBrowser", "imageLoader", "listView", "cardB pageData.query.ParentId = params.topParentId; libraryBrowser.loadSavedQueryValues(key, pageData.query); } + return pageData; } function getQuery(context) { - return getPageData(context).query + return getPageData(context).query; } function getSavedQueryKey(context) { - return context.savedQueryKey || (context.savedQueryKey = libraryBrowser.getSavedQueryKey("moviecollections")), context.savedQueryKey + if (!context.savedQueryKey) { + context.savedQueryKey = libraryBrowser.getSavedQueryKey("moviecollections"); + } + + return context.savedQueryKey; } function onViewStyleChange() { - var viewStyle = self.getCurrentViewStyle(), - itemsContainer = tabContent.querySelector(".itemsContainer"); - "List" == viewStyle ? (itemsContainer.classList.add("vertical-list"), itemsContainer.classList.remove("vertical-wrap")) : (itemsContainer.classList.remove("vertical-list"), itemsContainer.classList.add("vertical-wrap")), itemsContainer.innerHTML = "" + var viewStyle = self.getCurrentViewStyle(); + var itemsContainer = tabContent.querySelector(".itemsContainer"); + + if ("List" == viewStyle) { + itemsContainer.classList.add("vertical-list"); + itemsContainer.classList.remove("vertical-wrap"); + } else { + itemsContainer.classList.remove("vertical-list"); + itemsContainer.classList.add("vertical-wrap"); + } + + itemsContainer.innerHTML = ""; } function reloadItems(page) { loading.show(); isLoading = true; var query = getQuery(page); - ApiClient.getItems(ApiClient.getCurrentUserId(), query).then(function(result) { + ApiClient.getItems(ApiClient.getCurrentUserId(), query).then(function (result) { function onNextPageClick() { - if (isLoading) return; - query.StartIndex += query.Limit, reloadItems(tabContent) + if (isLoading) { + return; + } + + query.StartIndex += query.Limit; + reloadItems(tabContent); } function onPreviousPageClick() { - if (isLoading) return; - query.StartIndex -= query.Limit, reloadItems(tabContent) + if (isLoading) { + return; + } + + query.StartIndex -= query.Limit; + reloadItems(tabContent); } + window.scrollTo(0, 0); - var html, pagingHtml = libraryBrowser.getQueryPagingHtml({ - startIndex: query.StartIndex, - limit: query.Limit, - totalRecordCount: result.TotalRecordCount, - showLimit: !1, - updatePageSizeSetting: !1, - addLayoutButton: !1, - sortButton: !1, - filterButton: !1 - }), - viewStyle = self.getCurrentViewStyle(); - html = "Thumb" == viewStyle ? cardBuilder.getCardsHtml({ - items: result.Items, - shape: "backdrop", - preferThumb: !0, - context: "movies", - overlayPlayButton: !0, - centerText: !0, - showTitle: !0 - }) : "ThumbCard" == viewStyle ? cardBuilder.getCardsHtml({ - items: result.Items, - shape: "backdrop", - preferThumb: !0, - context: "movies", - lazy: !0, - cardLayout: !0, - showTitle: !0 - }) : "Banner" == viewStyle ? cardBuilder.getCardsHtml({ - items: result.Items, - shape: "banner", - preferBanner: !0, - context: "movies", - lazy: !0 - }) : "List" == viewStyle ? listView.getListViewHtml({ - items: result.Items, - context: "movies", - sortBy: query.SortBy - }) : "PosterCard" == viewStyle ? cardBuilder.getCardsHtml({ - items: result.Items, - shape: "auto", - context: "movies", - showTitle: !0, - centerText: !1, - cardLayout: !0 - }) : cardBuilder.getCardsHtml({ - items: result.Items, - shape: "auto", - context: "movies", - centerText: !0, - overlayPlayButton: !0, - showTitle: !0 + var html; + var pagingHtml = libraryBrowser.getQueryPagingHtml({ + startIndex: query.StartIndex, + limit: query.Limit, + totalRecordCount: result.TotalRecordCount, + showLimit: false, + updatePageSizeSetting: false, + addLayoutButton: false, + sortButton: false, + filterButton: false }); - var i, length, elems = tabContent.querySelectorAll(".paging"); - for (i = 0, length = elems.length; i < length; i++) elems[i].innerHTML = pagingHtml; - for (elems = tabContent.querySelectorAll(".btnNextPage"), i = 0, length = elems.length; i < length; i++) elems[i].addEventListener("click", onNextPageClick); - for (elems = tabContent.querySelectorAll(".btnPreviousPage"), i = 0, length = elems.length; i < length; i++) elems[i].addEventListener("click", onPreviousPageClick); - result.Items.length || (html = '

' + Globalize.translate("MessageNoCollectionsAvailable") + "

"); + var viewStyle = self.getCurrentViewStyle(); + if (viewStyle == "Thumb") { + html = cardBuilder.getCardsHtml({ + items: result.Items, + shape: "backdrop", + preferThumb: true, + context: "movies", + overlayPlayButton: true, + centerText: true, + showTitle: true + }); + } else if (viewStyle == "ThumbCard") { + html = cardBuilder.getCardsHtml({ + items: result.Items, + shape: "backdrop", + preferThumb: true, + context: "movies", + lazy: true, + cardLayout: true, + showTitle: true + }); + } else if (viewStyle == "Banner") { + html = cardBuilder.getCardsHtml({ + items: result.Items, + shape: "banner", + preferBanner: true, + context: "movies", + lazy: true + }); + } else if (viewStyle == "List") { + html = listView.getListViewHtml({ + items: result.Items, + context: "movies", + sortBy: query.SortBy + }); + } else if (viewStyle == "PosterCard") { + html = cardBuilder.getCardsHtml({ + items: result.Items, + shape: "auto", + context: "movies", + showTitle: true, + centerText: false, + cardLayout: true + }); + } else { + html = cardBuilder.getCardsHtml({ + items: result.Items, + shape: "auto", + context: "movies", + centerText: true, + overlayPlayButton: true, + showTitle: true + }); + } + var i; + var length; + var elems = tabContent.querySelectorAll(".paging"); + + for (i = 0, length = elems.length; i < length; i++) { + elems[i].innerHTML = pagingHtml; + } + + elems = tabContent.querySelectorAll(".btnNextPage"); + for (i = 0, length = elems.length; i < length; i++) { + elems[i].addEventListener("click", onNextPageClick); + } + + elems = tabContent.querySelectorAll(".btnPreviousPage"); + for (i = 0, length = elems.length; i < length; i++) { + elems[i].addEventListener("click", onPreviousPageClick); + } + + if (!result.Items.length) { + html = '

' + Globalize.translate("MessageNoCollectionsAvailable") + "

"; + } + var itemsContainer = tabContent.querySelector(".itemsContainer"); itemsContainer.innerHTML = html; imageLoader.lazyChildren(itemsContainer); libraryBrowser.saveQueryValues(getSavedQueryKey(page), query); loading.hide(); isLoading = false; - }) + }); } - var self = this, - pageSize = 100, - data = {}, - isLoading = false; - self.getCurrentViewStyle = function() { - return getPageData(tabContent).view - }, - function(tabContent) { - tabContent.querySelector(".btnSort").addEventListener("click", function(e) { - libraryBrowser.showSortMenu({ - items: [{ - name: Globalize.translate("OptionNameSort"), - id: "SortName" - }, { - name: Globalize.translate("OptionImdbRating"), - id: "CommunityRating,SortName" - }, { - name: Globalize.translate("OptionDateAdded"), - id: "DateCreated,SortName" - }, { - name: Globalize.translate("OptionParentalRating"), - id: "OfficialRating,SortName" - }, { - name: Globalize.translate("OptionReleaseDate"), - id: "PremiereDate,SortName" - }], - callback: function() { - getQuery(tabContent).StartIndex = 0, reloadItems(tabContent) - }, - query: getQuery(tabContent), - button: e.target - }) + + var self = this; + var pageSize = 100; + var data = {}; + var isLoading = false; + + self.getCurrentViewStyle = function () { + return getPageData(tabContent).view; + }; + + function initPage(tabContent) { + tabContent.querySelector(".btnSort").addEventListener("click", function (e) { + libraryBrowser.showSortMenu({ + items: [{ + name: Globalize.translate("OptionNameSort"), + id: "SortName" + }, { + name: Globalize.translate("OptionImdbRating"), + id: "CommunityRating,SortName" + }, { + name: Globalize.translate("OptionDateAdded"), + id: "DateCreated,SortName" + }, { + name: Globalize.translate("OptionParentalRating"), + id: "OfficialRating,SortName" + }, { + name: Globalize.translate("OptionReleaseDate"), + id: "PremiereDate,SortName" + }], + callback: function () { + getQuery(tabContent).StartIndex = 0; + reloadItems(tabContent); + }, + query: getQuery(tabContent), + button: e.target }); - var btnSelectView = tabContent.querySelector(".btnSelectView"); - btnSelectView.addEventListener("click", function(e) { - libraryBrowser.showLayoutMenu(e.target, self.getCurrentViewStyle(), "List,Poster,PosterCard,Thumb,ThumbCard".split(",")) - }), btnSelectView.addEventListener("layoutchange", function(e) { - var viewStyle = e.detail.viewStyle; - getPageData(tabContent).view = viewStyle, libraryBrowser.saveViewSetting(getSavedQueryKey(tabContent), viewStyle), getQuery(tabContent).StartIndex = 0, onViewStyleChange(), reloadItems(tabContent) - }), tabContent.querySelector(".btnNewCollection").addEventListener("click", function() { - require(["collectionEditor"], function(collectionEditor) { - var serverId = ApiClient.serverInfo().Id; - (new collectionEditor).show({ - items: [], - serverId: serverId - }) - }) - }) - }(tabContent), onViewStyleChange(), self.renderTab = function() { - reloadItems(tabContent) - }, self.destroy = function() {} - } + }); + var btnSelectView = tabContent.querySelector(".btnSelectView"); + btnSelectView.addEventListener("click", function (e) { + libraryBrowser.showLayoutMenu(e.target, self.getCurrentViewStyle(), "List,Poster,PosterCard,Thumb,ThumbCard".split(",")); + }); + btnSelectView.addEventListener("layoutchange", function (e) { + var viewStyle = e.detail.viewStyle; + getPageData(tabContent).view = viewStyle; + libraryBrowser.saveViewSetting(getSavedQueryKey(tabContent), viewStyle); + getQuery(tabContent).StartIndex = 0; + onViewStyleChange(); + reloadItems(tabContent); + }); + tabContent.querySelector(".btnNewCollection").addEventListener("click", function () { + require(["collectionEditor"], function (collectionEditor) { + var serverId = ApiClient.serverInfo().Id; + new collectionEditor().show({ + items: [], + serverId: serverId + }); + }); + }); + } + + initPage(tabContent); + onViewStyleChange(); + + self.renderTab = function () { + reloadItems(tabContent); + }; + + self.destroy = function () {}; + }; }); diff --git a/src/controllers/movies/moviegenres.js b/src/controllers/movies/moviegenres.js index 78fd601fd7..80197b01cc 100644 --- a/src/controllers/movies/moviegenres.js +++ b/src/controllers/movies/moviegenres.js @@ -1,139 +1,204 @@ -define(["layoutManager", "loading", "libraryBrowser", "cardBuilder", "lazyLoader", "apphost", "globalize", "appRouter", "dom", "emby-button"], function(layoutManager, loading, libraryBrowser, cardBuilder, lazyLoader, appHost, globalize, appRouter, dom) { +define(["layoutManager", "loading", "libraryBrowser", "cardBuilder", "lazyLoader", "apphost", "globalize", "appRouter", "dom", "emby-button"], function (layoutManager, loading, libraryBrowser, cardBuilder, lazyLoader, appHost, globalize, appRouter, dom) { "use strict"; - return function(view, params, tabContent) { + + return function (view, params, tabContent) { function getPageData() { - var key = getSavedQueryKey(), - pageData = data[key]; - return pageData || (pageData = data[key] = { - query: { - SortBy: "SortName", - SortOrder: "Ascending", - IncludeItemTypes: "Movie", - Recursive: !0, - EnableTotalRecordCount: !1 - }, - view: "Poster" - }, pageData.query.ParentId = params.topParentId, libraryBrowser.loadSavedQueryValues(key, pageData.query)), pageData + var key = getSavedQueryKey(); + var pageData = data[key]; + + if (!pageData) { + pageData = data[key] = { + query: { + SortBy: "SortName", + SortOrder: "Ascending", + IncludeItemTypes: "Movie", + Recursive: true, + EnableTotalRecordCount: false + }, + view: "Poster" + }; + pageData.query.ParentId = params.topParentId; + libraryBrowser.loadSavedQueryValues(key, pageData.query); + } + + return pageData; } function getQuery() { - return getPageData().query + return getPageData().query; } function getSavedQueryKey() { - return libraryBrowser.getSavedQueryKey("moviegenres") + return libraryBrowser.getSavedQueryKey("moviegenres"); } function getPromise() { loading.show(); var query = getQuery(); - return ApiClient.getGenres(ApiClient.getCurrentUserId(), query) + return ApiClient.getGenres(ApiClient.getCurrentUserId(), query); } function enableScrollX() { - return !layoutManager.desktop + return !layoutManager.desktop; } function getThumbShape() { - return enableScrollX() ? "overflowBackdrop" : "backdrop" + return enableScrollX() ? "overflowBackdrop" : "backdrop"; } function getPortraitShape() { - return enableScrollX() ? "overflowPortrait" : "portrait" + return enableScrollX() ? "overflowPortrait" : "portrait"; } function fillItemsContainer(elem) { - var id = elem.getAttribute("data-id"), - viewStyle = self.getCurrentViewStyle(), - limit = "Thumb" == viewStyle || "ThumbCard" == viewStyle ? 5 : 9; - enableScrollX() && (limit = 10); - var enableImageTypes = "Thumb" == viewStyle || "ThumbCard" == viewStyle ? "Primary,Backdrop,Thumb" : "Primary", - query = { - SortBy: "SortName", - SortOrder: "Ascending", - IncludeItemTypes: "Movie", - Recursive: !0, - Fields: "PrimaryImageAspectRatio,MediaSourceCount,BasicSyncInfo", - ImageTypeLimit: 1, - EnableImageTypes: enableImageTypes, - Limit: limit, - GenreIds: id, - EnableTotalRecordCount: !1, - ParentId: params.topParentId - }; - ApiClient.getItems(ApiClient.getCurrentUserId(), query).then(function(result) { + var id = elem.getAttribute("data-id"); + var viewStyle = self.getCurrentViewStyle(); + var limit = "Thumb" == viewStyle || "ThumbCard" == viewStyle ? 5 : 9; + + if (enableScrollX()) { + limit = 10; + } + + var enableImageTypes = "Thumb" == viewStyle || "ThumbCard" == viewStyle ? "Primary,Backdrop,Thumb" : "Primary"; + var query = { + SortBy: "SortName", + SortOrder: "Ascending", + IncludeItemTypes: "Movie", + Recursive: true, + Fields: "PrimaryImageAspectRatio,MediaSourceCount,BasicSyncInfo", + ImageTypeLimit: 1, + EnableImageTypes: enableImageTypes, + Limit: limit, + GenreIds: id, + EnableTotalRecordCount: false, + ParentId: params.topParentId + }; + ApiClient.getItems(ApiClient.getCurrentUserId(), query).then(function (result) { var supportsImageAnalysis = appHost.supports("imageanalysis"); - "Thumb" == viewStyle ? cardBuilder.buildCards(result.Items, { - itemsContainer: elem, - shape: getThumbShape(), - preferThumb: !0, - showTitle: !0, - scalable: !0, - centerText: !0, - overlayMoreButton: !0, - allowBottomPadding: !1 - }) : "ThumbCard" == viewStyle ? cardBuilder.buildCards(result.Items, { - itemsContainer: elem, - shape: getThumbShape(), - preferThumb: !0, - showTitle: !0, - scalable: !0, - centerText: !1, - cardLayout: !0, - showYear: !0 - }) : "PosterCard" == viewStyle ? cardBuilder.buildCards(result.Items, { - itemsContainer: elem, - shape: getPortraitShape(), - showTitle: !0, - scalable: !0, - centerText: !1, - cardLayout: !0, - showYear: !0 - }) : "Poster" == viewStyle && cardBuilder.buildCards(result.Items, { - itemsContainer: elem, - shape: getPortraitShape(), - scalable: !0, - overlayMoreButton: !0, - allowBottomPadding: !1 - }), result.Items.length >= query.Limit && tabContent.querySelector(".btnMoreFromGenre" + id + " i").classList.remove("hide") - }) + + if (viewStyle == "Thumb") { + cardBuilder.buildCards(result.Items, { + itemsContainer: elem, + shape: getThumbShape(), + preferThumb: true, + showTitle: true, + scalable: true, + centerText: true, + overlayMoreButton: true, + allowBottomPadding: false + }); + } else if (viewStyle == "ThumbCard") { + cardBuilder.buildCards(result.Items, { + itemsContainer: elem, + shape: getThumbShape(), + preferThumb: true, + showTitle: true, + scalable: true, + centerText: false, + cardLayout: true, + showYear: true + }); + } else if (viewStyle == "PosterCard") { + cardBuilder.buildCards(result.Items, { + itemsContainer: elem, + shape: getPortraitShape(), + showTitle: true, + scalable: true, + centerText: false, + cardLayout: true, + showYear: true + }); + } else if (viewStyle == "Poster") { + cardBuilder.buildCards(result.Items, { + itemsContainer: elem, + shape: getPortraitShape(), + scalable: true, + overlayMoreButton: true, + allowBottomPadding: false + }); + } + if (result.Items.length >= query.Limit) { + tabContent.querySelector(".btnMoreFromGenre" + id + " i").classList.remove("hide"); + } + }); } function reloadItems(context, promise) { var query = getQuery(); - promise.then(function(result) { - for (var elem = context.querySelector("#items"), html = "", items = result.Items, i = 0, length = items.length; i < length; i++) { + promise.then(function (result) { + var elem = context.querySelector("#items"); + var html = ""; + var items = result.Items; + + for (var i = 0, length = items.length; i < length; i++) { var item = items[i]; - if (html += '
', html += '", enableScrollX()) { + + html += '
'; + html += '"; + if (enableScrollX()) { var scrollXClass = "scrollX hiddenScrollX"; - layoutManager.tv && (scrollXClass += " smoothScrollX"), html += '
' - } else html += '
'; - html += "
", html += "
" + + if (layoutManager.tv) { + scrollXClass += "smoothScrollX"; + } + + html += '
'; + } else { + html += '
'; + } + + html += "
"; + html += "
"; } - elem.innerHTML = html, lazyLoader.lazyChildren(elem, fillItemsContainer), libraryBrowser.saveQueryValues(getSavedQueryKey(), query), loading.hide() - }) + + elem.innerHTML = html; + lazyLoader.lazyChildren(elem, fillItemsContainer); + libraryBrowser.saveQueryValues(getSavedQueryKey(), query); + loading.hide(); + }); } function fullyReload() { - self.preRender(), self.renderTab() + self.preRender(); + self.renderTab(); } - var self = this, - data = {}; - self.getViewStyles = function() { - return "Poster,PosterCard,Thumb,ThumbCard".split(",") - }, self.getCurrentViewStyle = function() { - return getPageData(tabContent).view - }, self.setCurrentViewStyle = function(viewStyle) { - getPageData(tabContent).view = viewStyle, libraryBrowser.saveViewSetting(getSavedQueryKey(tabContent), viewStyle), fullyReload() - }, self.enableViewSelection = !0; + + var self = this; + var data = {}; + + self.getViewStyles = function () { + return "Poster,PosterCard,Thumb,ThumbCard".split(","); + }; + + self.getCurrentViewStyle = function () { + return getPageData(tabContent).view; + }; + + self.setCurrentViewStyle = function (viewStyle) { + getPageData(tabContent).view = viewStyle; + libraryBrowser.saveViewSetting(getSavedQueryKey(tabContent), viewStyle); + fullyReload(); + }; + + self.enableViewSelection = true; var promise; - self.preRender = function() { - promise = getPromise() - }, self.renderTab = function() { - reloadItems(tabContent, promise) - } - } -}); \ No newline at end of file + + self.preRender = function () { + promise = getPromise(); + }; + + self.renderTab = function () { + reloadItems(tabContent, promise); + }; + }; +}); diff --git a/src/controllers/movies/movies.js b/src/controllers/movies/movies.js index e0a5947ca6..b4e30602fd 100644 --- a/src/controllers/movies/movies.js +++ b/src/controllers/movies/movies.js @@ -1,7 +1,7 @@ -define(["loading", "layoutManager", "userSettings", "events", "libraryBrowser", "alphaPicker", "listView", "cardBuilder", "emby-itemscontainer"], - function(loading, layoutManager, userSettings, events, libraryBrowser, alphaPicker, listView, cardBuilder) { +define(["loading", "layoutManager", "userSettings", "events", "libraryBrowser", "alphaPicker", "listView", "cardBuilder", "emby-itemscontainer"], function (loading, layoutManager, userSettings, events, libraryBrowser, alphaPicker, listView, cardBuilder) { "use strict"; - return function(view, params, tabContent, options) { + + return function (view, params, tabContent, options) { function onViewStyleChange() { if (self.getCurrentViewStyle() == "List") { itemsContainer.classList.add("vertical-list"); @@ -10,103 +10,141 @@ define(["loading", "layoutManager", "userSettings", "events", "libraryBrowser", itemsContainer.classList.remove("vertical-list"); itemsContainer.classList.add("vertical-wrap"); } + itemsContainer.innerHTML = ""; } function updateFilterControls() { - self.alphaPicker && self.alphaPicker.value(query.NameStartsWithOrGreater) + if (self.alphaPicker) { + self.alphaPicker.value(query.NameStartsWithOrGreater); + } } function fetchData() { isLoading = true; loading.show(); - return ApiClient.getItems(ApiClient.getCurrentUserId(), query) + return ApiClient.getItems(ApiClient.getCurrentUserId(), query); } function afterRefresh(result) { function onNextPageClick() { - if (isLoading) return; + if (isLoading) { + return; + } + query.StartIndex += query.Limit; itemsContainer.refreshItems(); } function onPreviousPageClick() { - if (isLoading) return; + if (isLoading) { + return; + } + query.StartIndex -= query.Limit; itemsContainer.refreshItems(); } + window.scrollTo(0, 0); updateFilterControls(); - var i, length, elems, pagingHtml = libraryBrowser.getQueryPagingHtml({ - startIndex: query.StartIndex, - limit: query.Limit, - totalRecordCount: result.TotalRecordCount, - showLimit: !1, - updatePageSizeSetting: !1, - addLayoutButton: !1, - sortButton: !1, - filterButton: !1 - }); - for (elems = tabContent.querySelectorAll(".paging"), i = 0, length = elems.length; i < length; i++) + var pagingHtml = libraryBrowser.getQueryPagingHtml({ + startIndex: query.StartIndex, + limit: query.Limit, + totalRecordCount: result.TotalRecordCount, + showLimit: false, + updatePageSizeSetting: false, + addLayoutButton: false, + sortButton: false, + filterButton: false + }); + var i; + var length; + var elems = tabContent.querySelectorAll(".paging"); + + for (i = 0, length = elems.length; i < length; i++) { elems[i].innerHTML = pagingHtml; - for (elems = tabContent.querySelectorAll(".btnNextPage"), i = 0, length = elems.length; i < length; i++) + } + + elems = tabContent.querySelectorAll(".btnNextPage"); + for (i = 0, length = elems.length; i < length; i++) { elems[i].addEventListener("click", onNextPageClick); - for (elems = tabContent.querySelectorAll(".btnPreviousPage"), i = 0, length = elems.length; i < length; i++) - elems[i].addEventListener("click", onPreviousPageClick) + } + + elems = tabContent.querySelectorAll(".btnPreviousPage"); + for (i = 0, length = elems.length; i < length; i++) { + elems[i].addEventListener("click", onPreviousPageClick); + } + isLoading = false; loading.hide(); } function getItemsHtml(items) { + var html; var viewStyle = self.getCurrentViewStyle(); - return "Thumb" == viewStyle ? cardBuilder.getCardsHtml({ - items: items, - shape: "backdrop", - preferThumb: !0, - context: "movies", - lazy: !0, - overlayPlayButton: !0, - showTitle: !0, - showYear: !0, - centerText: !0 - }) : "ThumbCard" == viewStyle ? cardBuilder.getCardsHtml({ - items: items, - shape: "backdrop", - preferThumb: !0, - context: "movies", - lazy: !0, - cardLayout: !0, - showTitle: !0, - showYear: !0, - centerText: !0 - }) : "Banner" == viewStyle ? cardBuilder.getCardsHtml({ - items: items, - shape: "banner", - preferBanner: !0, - context: "movies", - lazy: !0 - }) : "List" == viewStyle ? listView.getListViewHtml({ - items: items, - context: "movies", - sortBy: query.SortBy - }) : "PosterCard" == viewStyle ? cardBuilder.getCardsHtml({ - items: items, - shape: "portrait", - context: "movies", - showTitle: !0, - showYear: !0, - centerText: !0, - lazy: !0, - cardLayout: !0 - }) : cardBuilder.getCardsHtml({ - items: items, - shape: "portrait", - context: "movies", - overlayPlayButton: !0, - showTitle: !0, - showYear: !0, - centerText: !0 - }) + + if (viewStyle == "Thumb") { + html = cardBuilder.getCardsHtml({ + items: items, + shape: "backdrop", + preferThumb: true, + context: "movies", + lazy: true, + overlayPlayButton: true, + showTitle: true, + showYear: true, + centerText: true + }); + } else if (viewStyle == "ThumbCard") { + html = cardBuilder.getCardsHtml({ + items: items, + shape: "backdrop", + preferThumb: true, + context: "movies", + lazy: true, + cardLayout: true, + showTitle: true, + showYear: true, + centerText: true + }); + } else if (viewStyle == "Banner") { + html = cardBuilder.getCardsHtml({ + items: items, + shape: "banner", + preferBanner: true, + context: "movies", + lazy: true + }); + } else if (viewStyle == "List") { + html = listView.getListViewHtml({ + items: items, + context: "movies", + sortBy: query.SortBy + }); + } else if (viewStyle == "PosterCard") { + html = cardBuilder.getCardsHtml({ + items: items, + shape: "portrait", + context: "movies", + showTitle: true, + showYear: true, + centerText: true, + lazy: true, + cardLayout: true + }); + } else { + html = cardBuilder.getCardsHtml({ + items: items, + shape: "portrait", + context: "movies", + overlayPlayButton: true, + showTitle: true, + showYear: true, + centerText: true + }); + } + + return html; } function initPage(tabContent) { @@ -114,8 +152,9 @@ define(["loading", "layoutManager", "userSettings", "events", "libraryBrowser", itemsContainer.getItemsHtml = getItemsHtml; itemsContainer.afterRefresh = afterRefresh; var alphaPickerElement = tabContent.querySelector(".alphaPicker"); + if (alphaPickerElement) { - alphaPickerElement.addEventListener("alphavaluechanged", function(e) { + alphaPickerElement.addEventListener("alphavaluechanged", function (e) { var newValue = e.detail.value; query.NameStartsWithOrGreater = newValue; query.StartIndex = 0; @@ -125,109 +164,132 @@ define(["loading", "layoutManager", "userSettings", "events", "libraryBrowser", element: alphaPickerElement, valueChangeEvent: "click" }); + if (layoutManager.desktop || layoutManager.mobile) { alphaPickerElement.classList.add("alphabetPicker-right"); itemsContainer.classList.remove("padded-left-withalphapicker"); itemsContainer.classList.add("padded-right-withalphapicker"); } } + var btnFilter = tabContent.querySelector(".btnFilter"); - btnFilter && btnFilter.addEventListener("click", function() { - self.showFilterMenu() - }); + + if (btnFilter) { + btnFilter.addEventListener("click", function () { + self.showFilterMenu(); + }); + } var btnSort = tabContent.querySelector(".btnSort"); - btnSort && btnSort.addEventListener("click", function(e) { - libraryBrowser.showSortMenu({ - items: [{ - name: Globalize.translate("OptionNameSort"), - id: "SortName,ProductionYear" - }, { - name: Globalize.translate("OptionImdbRating"), - id: "CommunityRating,SortName,ProductionYear" - }, { - name: Globalize.translate("OptionCriticRating"), - id: "CriticRating,SortName,ProductionYear" - }, { - name: Globalize.translate("OptionDateAdded"), - id: "DateCreated,SortName,ProductionYear" - }, { - name: Globalize.translate("OptionDatePlayed"), - id: "DatePlayed,SortName,ProductionYear" - }, { - name: Globalize.translate("OptionParentalRating"), - id: "OfficialRating,SortName,ProductionYear" - }, { - name: Globalize.translate("OptionPlayCount"), - id: "PlayCount,SortName,ProductionYear" - }, { - name: Globalize.translate("OptionReleaseDate"), - id: "PremiereDate,SortName,ProductionYear" - }, { - name: Globalize.translate("OptionRuntime"), - id: "Runtime,SortName,ProductionYear" - }], - callback: function() { - query.StartIndex = 0, userSettings.saveQuerySettings(savedQueryKey, query), itemsContainer.refreshItems() - }, - query: query, - button: e.target - }) - }); + + if (btnSort) { + btnSort.addEventListener("click", function (e) { + libraryBrowser.showSortMenu({ + items: [{ + name: Globalize.translate("OptionNameSort"), + id: "SortName,ProductionYear" + }, { + name: Globalize.translate("OptionImdbRating"), + id: "CommunityRating,SortName,ProductionYear" + }, { + name: Globalize.translate("OptionCriticRating"), + id: "CriticRating,SortName,ProductionYear" + }, { + name: Globalize.translate("OptionDateAdded"), + id: "DateCreated,SortName,ProductionYear" + }, { + name: Globalize.translate("OptionDatePlayed"), + id: "DatePlayed,SortName,ProductionYear" + }, { + name: Globalize.translate("OptionParentalRating"), + id: "OfficialRating,SortName,ProductionYear" + }, { + name: Globalize.translate("OptionPlayCount"), + id: "PlayCount,SortName,ProductionYear" + }, { + name: Globalize.translate("OptionReleaseDate"), + id: "PremiereDate,SortName,ProductionYear" + }, { + name: Globalize.translate("OptionRuntime"), + id: "Runtime,SortName,ProductionYear" + }], + callback: function () { + query.StartIndex = 0; + userSettings.saveQuerySettings(savedQueryKey, query); + itemsContainer.refreshItems(); + }, + query: query, + button: e.target + }); + }); + } var btnSelectView = tabContent.querySelector(".btnSelectView"); - btnSelectView.addEventListener("click", function(e) { - libraryBrowser.showLayoutMenu(e.target, self.getCurrentViewStyle(), "Banner,List,Poster,PosterCard,Thumb,ThumbCard".split(",")) - }), btnSelectView.addEventListener("layoutchange", function(e) { + btnSelectView.addEventListener("click", function (e) { + libraryBrowser.showLayoutMenu(e.target, self.getCurrentViewStyle(), "Banner,List,Poster,PosterCard,Thumb,ThumbCard".split(",")); + }); + btnSelectView.addEventListener("layoutchange", function (e) { var viewStyle = e.detail.viewStyle; userSettings.set(savedViewKey, viewStyle); query.StartIndex = 0; onViewStyleChange(); itemsContainer.refreshItems(); - }) + }); } - var self = this, - itemsContainer = tabContent.querySelector(".itemsContainer"), - savedQueryKey = params.topParentId + "-" + options.mode, - savedViewKey = savedQueryKey + "-view", - query = { - SortBy: "SortName,ProductionYear", - SortOrder: "Ascending", - IncludeItemTypes: "Movie", - Recursive: !0, - Fields: "PrimaryImageAspectRatio,MediaSourceCount,BasicSyncInfo", - ImageTypeLimit: 1, - EnableImageTypes: "Primary,Backdrop,Banner,Thumb", - StartIndex: 0, - Limit: 100, - ParentId: params.topParentId - }, - isLoading = false; - if (options.mode === "favorites") query.IsFavorite = true; + + var self = this; + var itemsContainer = tabContent.querySelector(".itemsContainer"); + var savedQueryKey = params.topParentId + "-" + options.mode; + var savedViewKey = savedQueryKey + "-view"; + var query = { + SortBy: "SortName,ProductionYear", + SortOrder: "Ascending", + IncludeItemTypes: "Movie", + Recursive: true, + Fields: "PrimaryImageAspectRatio,MediaSourceCount,BasicSyncInfo", + ImageTypeLimit: 1, + EnableImageTypes: "Primary,Backdrop,Banner,Thumb", + StartIndex: 0, + Limit: 100, + ParentId: params.topParentId + }; + var isLoading = false; + + if (options.mode === "favorites") { + query.IsFavorite = true; + } + query = userSettings.loadQuerySettings(savedQueryKey, query); - self.showFilterMenu = function() { - require(["components/filterdialog/filterdialog"], function(filterDialogFactory) { + + self.showFilterMenu = function () { + require(["components/filterdialog/filterdialog"], function (filterDialogFactory) { var filterDialog = new filterDialogFactory({ query: query, mode: "movies", serverId: ApiClient.serverId() }); - events.on(filterDialog, "filterchange", function() { - query.StartIndex = 0, itemsContainer.refreshItems() - }), filterDialog.show() - }) + events.on(filterDialog, "filterchange", function () { + query.StartIndex = 0; + itemsContainer.refreshItems(); + }); + filterDialog.show(); + }); }; - self.getCurrentViewStyle = function() { - return userSettings.get(savedViewKey) || "Poster" + + self.getCurrentViewStyle = function () { + return userSettings.get(savedViewKey) || "Poster"; }; - self.initTab = function() { + + self.initTab = function () { initPage(tabContent); onViewStyleChange(); }; - self.renderTab = function() { + + self.renderTab = function () { itemsContainer.refreshItems(); updateFilterControls(); }; - self.destroy = function() { - itemsContainer = null - } - } + + self.destroy = function () { + itemsContainer = null; + }; + }; }); diff --git a/src/controllers/movies/moviesrecommended.js b/src/controllers/movies/moviesrecommended.js index 2bab767735..82c0b6a12d 100644 --- a/src/controllers/movies/moviesrecommended.js +++ b/src/controllers/movies/moviesrecommended.js @@ -1,16 +1,16 @@ -define(["events", "layoutManager", "inputManager", "userSettings", "libraryMenu", "mainTabsManager", "cardBuilder", "dom", "imageLoader", "playbackManager", "emby-itemscontainer", "emby-tabs", "emby-button"], function(events, layoutManager, inputManager, userSettings, libraryMenu, mainTabsManager, cardBuilder, dom, imageLoader, playbackManager) { +define(["events", "layoutManager", "inputManager", "userSettings", "libraryMenu", "mainTabsManager", "cardBuilder", "dom", "imageLoader", "playbackManager", "emby-itemscontainer", "emby-tabs", "emby-button"], function (events, layoutManager, inputManager, userSettings, libraryMenu, mainTabsManager, cardBuilder, dom, imageLoader, playbackManager) { "use strict"; function enableScrollX() { - return !layoutManager.desktop + return !layoutManager.desktop; } function getPortraitShape() { - return enableScrollX() ? "overflowPortrait" : "portrait" + return enableScrollX() ? "overflowPortrait" : "portrait"; } function getThumbShape() { - return enableScrollX() ? "overflowBackdrop" : "backdrop" + return enableScrollX() ? "overflowBackdrop" : "backdrop"; } function loadLatest(page, userId, parentId) { @@ -21,118 +21,168 @@ define(["events", "layoutManager", "inputManager", "userSettings", "libraryMenu" ParentId: parentId, ImageTypeLimit: 1, EnableImageTypes: "Primary,Backdrop,Banner,Thumb", - EnableTotalRecordCount: !1 + EnableTotalRecordCount: false }; - ApiClient.getJSON(ApiClient.getUrl("Users/" + userId + "/Items/Latest", options)).then(function(items) { - var allowBottomPadding = !enableScrollX(), - container = page.querySelector("#recentlyAddedItems"); + ApiClient.getJSON(ApiClient.getUrl("Users/" + userId + "/Items/Latest", options)).then(function (items) { + var allowBottomPadding = !enableScrollX(); + var container = page.querySelector("#recentlyAddedItems"); cardBuilder.buildCards(items, { itemsContainer: container, shape: getPortraitShape(), - scalable: !0, - overlayPlayButton: !0, + scalable: true, + overlayPlayButton: true, allowBottomPadding: allowBottomPadding, - showTitle: !0, - showYear: !0, - centerText: !0 - }) - }) + showTitle: true, + showYear: true, + centerText: true + }); + }); } function loadResume(page, userId, parentId) { - var screenWidth = dom.getWindowSize().innerWidth, - options = { - SortBy: "DatePlayed", - SortOrder: "Descending", - IncludeItemTypes: "Movie", - Filters: "IsResumable", - Limit: screenWidth >= 1920 ? 5 : screenWidth >= 1600 ? 5 : 3, - Recursive: !0, - Fields: "PrimaryImageAspectRatio,MediaSourceCount,BasicSyncInfo", - CollapseBoxSetItems: !1, - ParentId: parentId, - ImageTypeLimit: 1, - EnableImageTypes: "Primary,Backdrop,Banner,Thumb", - EnableTotalRecordCount: !1 - }; - ApiClient.getItems(userId, options).then(function(result) { - result.Items.length ? page.querySelector("#resumableSection").classList.remove("hide") : page.querySelector("#resumableSection").classList.add("hide"); - var allowBottomPadding = !enableScrollX(), - container = page.querySelector("#resumableItems"); + var screenWidth = dom.getWindowSize().innerWidth; + var options = { + SortBy: "DatePlayed", + SortOrder: "Descending", + IncludeItemTypes: "Movie", + Filters: "IsResumable", + Limit: screenWidth >= 1920 ? 5 : screenWidth >= 1600 ? 5 : 3, + Recursive: true, + Fields: "PrimaryImageAspectRatio,MediaSourceCount,BasicSyncInfo", + CollapseBoxSetItems: false, + ParentId: parentId, + ImageTypeLimit: 1, + EnableImageTypes: "Primary,Backdrop,Banner,Thumb", + EnableTotalRecordCount: false + }; + ApiClient.getItems(userId, options).then(function (result) { + if (result.Items.length) { + page.querySelector("#resumableSection").classList.remove("hide"); + } else { + page.querySelector("#resumableSection").classList.add("hide"); + } + + var allowBottomPadding = !enableScrollX(); + var container = page.querySelector("#resumableItems"); cardBuilder.buildCards(result.Items, { itemsContainer: container, - preferThumb: !0, + preferThumb: true, shape: getThumbShape(), - scalable: !0, - overlayPlayButton: !0, + scalable: true, + overlayPlayButton: true, allowBottomPadding: allowBottomPadding, - cardLayout: !1, - showTitle: !0, - showYear: !0, - centerText: !0 - }) - }) + cardLayout: false, + showTitle: true, + showYear: true, + centerText: true + }); + }); } function getRecommendationHtml(recommendation) { - var html = "", - title = ""; + var html = ""; + var title = ""; + switch (recommendation.RecommendationType) { case "SimilarToRecentlyPlayed": title = Globalize.translate("RecommendationBecauseYouWatched").replace("{0}", recommendation.BaselineItemName); break; + case "SimilarToLikedItem": title = Globalize.translate("RecommendationBecauseYouLike").replace("{0}", recommendation.BaselineItemName); break; + case "HasDirectorFromRecentlyPlayed": case "HasLikedDirector": title = Globalize.translate("RecommendationDirectedBy").replace("{0}", recommendation.BaselineItemName); break; + case "HasActorFromRecentlyPlayed": case "HasLikedActor": - title = Globalize.translate("RecommendationStarring").replace("{0}", recommendation.BaselineItemName) + title = Globalize.translate("RecommendationStarring").replace("{0}", recommendation.BaselineItemName); + break; } - html += '
', html += '

' + title + "

"; - var allowBottomPadding = !0; - return enableScrollX() ? (allowBottomPadding = !1, html += '
') : html += '
', html += cardBuilder.getCardsHtml(recommendation.Items, { + + html += '
'; + html += '

' + title + "

"; + var allowBottomPadding = true; + + if (enableScrollX()) { + allowBottomPadding = false; + html += '
'; + } else { + html += '
'; + } + + html += cardBuilder.getCardsHtml(recommendation.Items, { shape: getPortraitShape(), - scalable: !0, - overlayPlayButton: !0, + scalable: true, + overlayPlayButton: true, allowBottomPadding: allowBottomPadding - }), html += "
", html += "
" + }); + html += "
"; + html += "
"; + return html; } function loadSuggestions(page, userId, parentId) { - var screenWidth = dom.getWindowSize().innerWidth, - url = ApiClient.getUrl("Movies/Recommendations", { - userId: userId, - categoryLimit: 6, - ItemLimit: screenWidth >= 1920 ? 8 : screenWidth >= 1600 ? 8 : screenWidth >= 1200 ? 6 : 5, - Fields: "PrimaryImageAspectRatio,MediaSourceCount,BasicSyncInfo", - ImageTypeLimit: 1, - EnableImageTypes: "Primary,Backdrop,Banner,Thumb" - }); - ApiClient.getJSON(url).then(function(recommendations) { - if (!recommendations.length) return page.querySelector(".noItemsMessage").classList.remove("hide"), void(page.querySelector(".recommendations").innerHTML = ""); + var screenWidth = dom.getWindowSize().innerWidth; + var url = ApiClient.getUrl("Movies/Recommendations", { + userId: userId, + categoryLimit: 6, + ItemLimit: screenWidth >= 1920 ? 8 : screenWidth >= 1600 ? 8 : screenWidth >= 1200 ? 6 : 5, + Fields: "PrimaryImageAspectRatio,MediaSourceCount,BasicSyncInfo", + ImageTypeLimit: 1, + EnableImageTypes: "Primary,Backdrop,Banner,Thumb" + }); + ApiClient.getJSON(url).then(function (recommendations) { + if (!recommendations.length) { + page.querySelector(".noItemsMessage").classList.remove("hide"); + page.querySelector(".recommendations").innerHTML = ""; + return; + } + var html = recommendations.map(getRecommendationHtml).join(""); page.querySelector(".noItemsMessage").classList.add("hide"); var recs = page.querySelector(".recommendations"); - recs.innerHTML = html, imageLoader.lazyChildren(recs) - }) + recs.innerHTML = html; + imageLoader.lazyChildren(recs); + }); } function setScrollClasses(elem, scrollX) { - scrollX ? (elem.classList.add("hiddenScrollX"), layoutManager.tv && elem.classList.add("smoothScrollX"), elem.classList.add("scrollX"), elem.classList.remove("vertical-wrap")) : (elem.classList.remove("hiddenScrollX"), elem.classList.remove("smoothScrollX"), elem.classList.remove("scrollX"), elem.classList.add("vertical-wrap")) + if (scrollX) { + elem.classList.add("hiddenScrollX"); + + if (layoutManager.tv) { + elem.classList.add("smoothScrollX"); + } + + elem.classList.add("scrollX"); + elem.classList.remove("vertical-wrap"); + } else { + elem.classList.remove("hiddenScrollX"); + elem.classList.remove("smoothScrollX"); + elem.classList.remove("scrollX"); + elem.classList.add("vertical-wrap"); + } } function initSuggestedTab(page, tabContent) { - for (var containers = tabContent.querySelectorAll(".itemsContainer"), i = 0, length = containers.length; i < length; i++) setScrollClasses(containers[i], enableScrollX()) + var containers = tabContent.querySelectorAll(".itemsContainer"); + + for (var i = 0, length = containers.length; i < length; i++) { + setScrollClasses(containers[i], enableScrollX()); + } } function loadSuggestionsTab(view, params, tabContent) { - var parentId = params.topParentId, - userId = ApiClient.getCurrentUserId(); - console.log("loadSuggestionsTab"), loadResume(tabContent, userId, parentId), loadLatest(tabContent, userId, parentId), loadSuggestions(tabContent, userId, parentId) + var parentId = params.topParentId; + var userId = ApiClient.getCurrentUserId(); + console.log("loadSuggestionsTab"); + loadResume(tabContent, userId, parentId); + loadLatest(tabContent, userId, parentId); + loadSuggestions(tabContent, userId, parentId); } function getTabs() { @@ -151,126 +201,196 @@ define(["events", "layoutManager", "inputManager", "userSettings", "libraryMenu" }, { name: Globalize.translate("ButtonSearch"), cssClass: "searchTabButton" - }] + }]; } function getDefaultTabIndex(folderId) { switch (userSettings.get("landing-" + folderId)) { case "suggestions": return 1; + case "favorites": return 3; + case "collections": return 4; + case "genres": return 5; + default: - return 0 + return 0; } } - return function(view, params) { + + return function (view, params) { function onBeforeTabChange(e) { - preLoadTab(view, parseInt(e.detail.selectedTabIndex)) + preLoadTab(view, parseInt(e.detail.selectedTabIndex)); } function onTabChange(e) { var newIndex = parseInt(e.detail.selectedTabIndex); - loadTab(view, newIndex) + loadTab(view, newIndex); } function getTabContainers() { - return view.querySelectorAll(".pageTabContent") + return view.querySelectorAll(".pageTabContent"); } function initTabs() { - mainTabsManager.setTabs(view, currentTabIndex, getTabs, getTabContainers, onBeforeTabChange, onTabChange) + mainTabsManager.setTabs(view, currentTabIndex, getTabs, getTabContainers, onBeforeTabChange, onTabChange); } function getTabController(page, index, callback) { var depends = []; + switch (index) { case 0: depends.push("controllers/movies/movies"); break; + case 1: break; + case 2: depends.push("controllers/movies/movietrailers"); break; + case 3: depends.push("controllers/movies/movies"); break; + case 4: depends.push("controllers/movies/moviecollections"); break; + case 5: depends.push("controllers/movies/moviegenres"); break; + case 6: - depends.push("scripts/searchtab") + depends.push("scripts/searchtab"); } - require(depends, function(controllerFactory) { + + require(depends, function (controllerFactory) { var tabContent; - index === suggestionsTabIndex && (tabContent = view.querySelector(".pageTabContent[data-index='" + index + "']"), self.tabContent = tabContent); + + if (index === suggestionsTabIndex) { + tabContent = view.querySelector(".pageTabContent[data-index='" + index + "']"); + self.tabContent = tabContent; + } + var controller = tabControllers[index]; - controller || (tabContent = view.querySelector(".pageTabContent[data-index='" + index + "']"), controller = index === suggestionsTabIndex ? self : 6 === index ? new controllerFactory(view, tabContent, { - collectionType: "movies", - parentId: params.topParentId - }) : 0 === index || 3 === index ? new controllerFactory(view, params, tabContent, { - mode: index ? "favorites" : "movies" - }) : new controllerFactory(view, params, tabContent), tabControllers[index] = controller, controller.initTab && controller.initTab()), callback(controller) - }) + + if (!controller) { + tabContent = view.querySelector(".pageTabContent[data-index='" + index + "']"); + + if (index === suggestionsTabIndex) { + controller = self; + } 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" + }); + } else { + controller = new controllerFactory(view, params, tabContent); + } + + tabControllers[index] = controller; + + if (controller.initTab) { + controller.initTab(); + } + } + + callback(controller); + }); } function preLoadTab(page, index) { - getTabController(page, index, function(controller) { - -1 == renderedTabs.indexOf(index) && controller.preRender && controller.preRender() - }) + getTabController(page, index, function (controller) { + if (renderedTabs.indexOf(index) == -1 && controller.preRender) { + controller.preRender(); + } + }); } function loadTab(page, index) { - currentTabIndex = index, getTabController(page, index, function(controller) { - initialTabIndex = null, -1 == renderedTabs.indexOf(index) && (renderedTabs.push(index), controller.renderTab()) - }) + currentTabIndex = index; + getTabController(page, index, function (controller) { + initialTabIndex = null; + + if (renderedTabs.indexOf(index) == -1) { + renderedTabs.push(index); + controller.renderTab(); + } + }); } function onPlaybackStop(e, state) { - state.NowPlayingItem && "Video" == state.NowPlayingItem.MediaType && (renderedTabs = [], mainTabsManager.getTabsElement().triggerTabChange()) + if (state.NowPlayingItem && state.NowPlayingItem.MediaType == "Video") { + renderedTabs = []; + mainTabsManager.getTabsElement().triggerTabChange(); + } } function onInputCommand(e) { switch (e.detail.command) { case "search": - e.preventDefault(), Dashboard.navigate("search.html?collectionType=movies&parentId=" + params.topParentId) + e.preventDefault(); + Dashboard.navigate("search.html?collectionType=movies&parentId=" + params.topParentId); } } - var isViewRestored, self = this, - currentTabIndex = parseInt(params.tab || getDefaultTabIndex(params.topParentId)), - initialTabIndex = currentTabIndex, - suggestionsTabIndex = 1; - self.initTab = function() { + + var isViewRestored; + var self = this; + var currentTabIndex = parseInt(params.tab || getDefaultTabIndex(params.topParentId)); + var initialTabIndex = currentTabIndex; + var suggestionsTabIndex = 1; + + self.initTab = function () { var tabContent = view.querySelector(".pageTabContent[data-index='" + suggestionsTabIndex + "']"); initSuggestedTab(view, tabContent); - }, self.renderTab = function() { - var tabContent = view.querySelector(".pageTabContent[data-index='" + suggestionsTabIndex + "']"); - loadSuggestionsTab(view, params, tabContent) }; - var tabControllers = [], - renderedTabs = []; - view.addEventListener("viewshow", function(e) { + + self.renderTab = function () { + var tabContent = view.querySelector(".pageTabContent[data-index='" + suggestionsTabIndex + "']"); + loadSuggestionsTab(view, params, tabContent); + }; + + var tabControllers = []; + var renderedTabs = []; + view.addEventListener("viewshow", function (e) { if (isViewRestored = e.detail.isRestored, initTabs(), !view.getAttribute("data-title")) { var parentId = params.topParentId; - parentId ? ApiClient.getItem(ApiClient.getCurrentUserId(), parentId).then(function(item) { - view.setAttribute("data-title", item.Name), libraryMenu.setTitle(item.Name) - }) : (view.setAttribute("data-title", Globalize.translate("TabMovies")), libraryMenu.setTitle(Globalize.translate("TabMovies"))) + + if (parentId) { + ApiClient.getItem(ApiClient.getCurrentUserId(), parentId).then(function (item) { + view.setAttribute("data-title", item.Name); + libraryMenu.setTitle(item.Name); + }); + } else { + view.setAttribute("data-title", Globalize.translate("TabMovies")); + libraryMenu.setTitle(Globalize.translate("TabMovies")); + } } - events.on(playbackManager, "playbackstop", onPlaybackStop), inputManager.on(window, onInputCommand) - }), view.addEventListener("viewbeforehide", function(e) { - inputManager.off(window, onInputCommand) - }), view.addEventListener("viewdestroy", function(e) { - tabControllers.forEach(function(t) { - t.destroy && t.destroy() - }) - }) - } -}); \ No newline at end of file + + events.on(playbackManager, "playbackstop", onPlaybackStop); + inputManager.on(window, onInputCommand); + }); + view.addEventListener("viewbeforehide", function (e) { + inputManager.off(window, onInputCommand); + }); + view.addEventListener("viewdestroy", function (e) { + tabControllers.forEach(function (t) { + if (t.destroy) { + t.destroy(); + } + }); + }); + }; +}); diff --git a/src/controllers/movies/movietrailers.js b/src/controllers/movies/movietrailers.js index 2d1fdda63c..3e62298613 100644 --- a/src/controllers/movies/movietrailers.js +++ b/src/controllers/movies/movietrailers.js @@ -1,185 +1,261 @@ -define(["layoutManager", "loading", "events", "libraryBrowser", "imageLoader", "alphaPicker", "listView", "cardBuilder", "apphost", "emby-itemscontainer"], function(layoutManager, loading, events, libraryBrowser, imageLoader, alphaPicker, listView, cardBuilder, appHost) { +define(["layoutManager", "loading", "events", "libraryBrowser", "imageLoader", "alphaPicker", "listView", "cardBuilder", "apphost", "emby-itemscontainer"], function (layoutManager, loading, events, libraryBrowser, imageLoader, alphaPicker, listView, cardBuilder, appHost) { "use strict"; - return function(view, params, tabContent) { + + return function (view, params, tabContent) { function getPageData(context) { - var key = getSavedQueryKey(context), - pageData = data[key]; - return pageData || (pageData = data[key] = { - query: { - SortBy: "SortName", - SortOrder: "Ascending", - IncludeItemTypes: "Trailer", - Recursive: !0, - Fields: "PrimaryImageAspectRatio,SortName,BasicSyncInfo", - ImageTypeLimit: 1, - EnableImageTypes: "Primary,Backdrop,Banner,Thumb", - StartIndex: 0, - Limit: pageSize - }, - view: libraryBrowser.getSavedView(key) || "Poster" - }, libraryBrowser.loadSavedQueryValues(key, pageData.query)), pageData + var key = getSavedQueryKey(context); + var pageData = data[key]; + + if (!pageData) { + pageData = data[key] = { + query: { + SortBy: "SortName", + SortOrder: "Ascending", + IncludeItemTypes: "Trailer", + Recursive: true, + Fields: "PrimaryImageAspectRatio,SortName,BasicSyncInfo", + ImageTypeLimit: 1, + EnableImageTypes: "Primary,Backdrop,Banner,Thumb", + StartIndex: 0, + Limit: pageSize + }, + view: libraryBrowser.getSavedView(key) || "Poster" + }; + libraryBrowser.loadSavedQueryValues(key, pageData.query); + } + + return pageData; } function getQuery(context) { - return getPageData(context).query + return getPageData(context).query; } function getSavedQueryKey(context) { - return context.savedQueryKey || (context.savedQueryKey = libraryBrowser.getSavedQueryKey("trailers")), context.savedQueryKey + if (!context.savedQueryKey) { + context.savedQueryKey = libraryBrowser.getSavedQueryKey("trailers"); + } + + return context.savedQueryKey; } function reloadItems() { loading.show(); isLoading = true; var query = getQuery(tabContent); - ApiClient.getItems(ApiClient.getCurrentUserId(), query).then(function(result) { + ApiClient.getItems(ApiClient.getCurrentUserId(), query).then(function (result) { function onNextPageClick() { - if (isLoading) return; - query.StartIndex += query.Limit, reloadItems() + if (isLoading) { + return; + } + + query.StartIndex += query.Limit; + reloadItems(); } function onPreviousPageClick() { - if (isLoading) return; - query.StartIndex -= query.Limit, reloadItems() + if (isLoading) { + return; + } + + query.StartIndex -= query.Limit; + reloadItems(); } - window.scrollTo(0, 0), updateFilterControls(tabContent); - var html, pagingHtml = libraryBrowser.getQueryPagingHtml({ - startIndex: query.StartIndex, - limit: query.Limit, - totalRecordCount: result.TotalRecordCount, - showLimit: !1, - updatePageSizeSetting: !1, - addLayoutButton: !1, - sortButton: !1, - filterButton: !1 - }), - viewStyle = self.getCurrentViewStyle(); - html = "Thumb" == viewStyle ? cardBuilder.getCardsHtml({ - items: result.Items, - shape: "backdrop", - preferThumb: !0, - context: "movies", - overlayPlayButton: !0 - }) : "ThumbCard" == viewStyle ? cardBuilder.getCardsHtml({ - items: result.Items, - shape: "backdrop", - preferThumb: !0, - context: "movies", - cardLayout: !0, - showTitle: !0, - showYear: !0, - centerText: !0 - }) : "Banner" == viewStyle ? cardBuilder.getCardsHtml({ - items: result.Items, - shape: "banner", - preferBanner: !0, - context: "movies" - }) : "List" == viewStyle ? listView.getListViewHtml({ - items: result.Items, - context: "movies", - sortBy: query.SortBy - }) : "PosterCard" == viewStyle ? cardBuilder.getCardsHtml({ - items: result.Items, - shape: "portrait", - context: "movies", - showTitle: !0, - showYear: !0, - centerText: !0, - cardLayout: !0 - }) : cardBuilder.getCardsHtml({ - items: result.Items, - shape: "portrait", - context: "movies", - centerText: !0, - overlayPlayButton: !0, - showTitle: !0, - showYear: !0 + + window.scrollTo(0, 0); + updateFilterControls(tabContent); + var pagingHtml = libraryBrowser.getQueryPagingHtml({ + startIndex: query.StartIndex, + limit: query.Limit, + totalRecordCount: result.TotalRecordCount, + showLimit: false, + updatePageSizeSetting: false, + addLayoutButton: false, + sortButton: false, + filterButton: false }); - var i, length, elems = tabContent.querySelectorAll(".paging"); - for (i = 0, length = elems.length; i < length; i++) elems[i].innerHTML = pagingHtml; - for (elems = tabContent.querySelectorAll(".btnNextPage"), i = 0, length = elems.length; i < length; i++) elems[i].addEventListener("click", onNextPageClick); - for (elems = tabContent.querySelectorAll(".btnPreviousPage"), i = 0, length = elems.length; i < length; i++) elems[i].addEventListener("click", onPreviousPageClick); - result.Items.length || (html = '

' + Globalize.translate("MessageNoTrailersFound") + "

"); + var html; + var viewStyle = self.getCurrentViewStyle(); + + if (viewStyle == "Thumb") { + html = cardBuilder.getCardsHtml({ + items: result.Items, + shape: "backdrop", + preferThumb: true, + context: "movies", + overlayPlayButton: true + }); + } else if (viewStyle == "ThumbCard") { + html = cardBuilder.getCardsHtml({ + items: result.Items, + shape: "backdrop", + preferThumb: true, + context: "movies", + cardLayout: true, + showTitle: true, + showYear: true, + centerText: true + }); + } else if (viewStyle == "Banner") { + html = cardBuilder.getCardsHtml({ + items: result.Items, + shape: "banner", + preferBanner: true, + context: "movies" + }); + } else if (viewStyle == "List") { + html = listView.getListViewHtml({ + items: result.Items, + context: "movies", + sortBy: query.SortBy + }); + } else if (viewStyle == "PosterCard") { + html = cardBuilder.getCardsHtml({ + items: result.Items, + shape: "portrait", + context: "movies", + showTitle: true, + showYear: true, + cardLayout: true, + centerText: true + }); + } else { + html = cardBuilder.getCardsHtml({ + items: result.Items, + shape: "portrait", + context: "movies", + centerText: true, + overlayPlayButton: true, + showTitle: true, + showYear: true + }); + } + + var i; + var length; + var elems = tabContent.querySelectorAll(".paging"); + + for (i = 0, length = elems.length; i < length; i++) { + elems[i].innerHTML = pagingHtml; + } + + elems = tabContent.querySelectorAll(".btnNextPage"); + for (i = 0, length = elems.length; i < length; i++) { + elems[i].addEventListener("click", onNextPageClick); + } + + elems = tabContent.querySelectorAll(".btnPreviousPage"); + for (i = 0, length = elems.length; i < length; i++) { + elems[i].addEventListener("click", onPreviousPageClick); + } + + if (!result.Items.length) { + html = '

' + Globalize.translate("MessageNoTrailersFound") + "

"; + } + var itemsContainer = tabContent.querySelector(".itemsContainer"); itemsContainer.innerHTML = html; imageLoader.lazyChildren(itemsContainer); libraryBrowser.saveQueryValues(getSavedQueryKey(tabContent), query); loading.hide(); isLoading = false; - }) + }); } function updateFilterControls(tabContent) { var query = getQuery(tabContent); - self.alphaPicker.value(query.NameStartsWithOrGreater) + self.alphaPicker.value(query.NameStartsWithOrGreater); } - var self = this, - pageSize = 100, - data = {}, - isLoading = false; - self.showFilterMenu = function() { - require(["components/filterdialog/filterdialog"], function(filterDialogFactory) { - var filterDialog = new filterDialogFactory({ - query: getQuery(tabContent), - mode: "movies", - serverId: ApiClient.serverId() - }); - events.on(filterDialog, "filterchange", function() { - getQuery(tabContent).StartIndex = 0, reloadItems() - }), filterDialog.show() - }) - }, self.getCurrentViewStyle = function() { - return getPageData(tabContent).view - }, - function(tabContent) { - var alphaPickerElement = tabContent.querySelector(".alphaPicker"); - if (alphaPickerElement.addEventListener("alphavaluechanged", function(e) { - var newValue = e.detail.value, - query = getQuery(tabContent); - query.NameStartsWithOrGreater = newValue, query.StartIndex = 0, reloadItems() - }), self.alphaPicker = new alphaPicker({ - element: alphaPickerElement, - valueChangeEvent: "click" - }), layoutManager.desktop || layoutManager.mobile) { - tabContent.querySelector(".alphaPicker").classList.add("alphabetPicker-right"); - var itemsContainer = tabContent.querySelector(".itemsContainer"); - itemsContainer.classList.remove("padded-left-withalphapicker"), itemsContainer.classList.add("padded-right-withalphapicker") - } - tabContent.querySelector(".btnFilter").addEventListener("click", function() { - self.showFilterMenu() - }), tabContent.querySelector(".btnSort").addEventListener("click", function(e) { - libraryBrowser.showSortMenu({ - items: [{ - name: Globalize.translate("OptionNameSort"), - id: "SortName" - }, { - name: Globalize.translate("OptionImdbRating"), - id: "CommunityRating,SortName" - }, { - name: Globalize.translate("OptionDateAdded"), - id: "DateCreated,SortName" - }, { - name: Globalize.translate("OptionDatePlayed"), - id: "DatePlayed,SortName" - }, { - name: Globalize.translate("OptionParentalRating"), - id: "OfficialRating,SortName" - }, { - name: Globalize.translate("OptionPlayCount"), - id: "PlayCount,SortName" - }, { - name: Globalize.translate("OptionReleaseDate"), - id: "PremiereDate,SortName" - }], - callback: function() { - getQuery(tabContent).StartIndex = 0, reloadItems() - }, - query: getQuery(tabContent), - button: e.target - }) - }) - }(tabContent), self.renderTab = function() { - reloadItems(), updateFilterControls(tabContent) - }, self.destroy = function() {} - } + + var self = this; + var pageSize = 100; + var data = {}; + var isLoading = false; + + self.showFilterMenu = function () { + require(["components/filterdialog/filterdialog"], function (filterDialogFactory) { + var filterDialog = new filterDialogFactory({ + query: getQuery(tabContent), + mode: "movies", + serverId: ApiClient.serverId() + }); + events.on(filterDialog, "filterchange", function () { + getQuery(tabContent).StartIndex = 0; + reloadItems(); + }); + filterDialog.show(); + }); + }; + + self.getCurrentViewStyle = function () { + return getPageData(tabContent).view; + }; + + function initPage(tabContent) { + var alphaPickerElement = tabContent.querySelector(".alphaPicker"); + alphaPickerElement.addEventListener("alphavaluechanged", function (e) { + var newValue = e.detail.value; + var query = getQuery(tabContent); + query.NameStartsWithOrGreater = newValue; + query.StartIndex = 0; + reloadItems(); + }); + self.alphaPicker = new alphaPicker({ + element: alphaPickerElement, + valueChangeEvent: "click" + }); + + if (layoutManager.desktop || layoutManager.mobile) { + tabContent.querySelector(".alphaPicker").classList.add("alphabetPicker-right"); + var itemsContainer = tabContent.querySelector(".itemsContainer"); + itemsContainer.classList.remove("padded-left-withalphapicker"); + itemsContainer.classList.add("padded-right-withalphapicker"); + } + + tabContent.querySelector(".btnFilter").addEventListener("click", function () { + self.showFilterMenu(); + }); + tabContent.querySelector(".btnSort").addEventListener("click", function (e) { + libraryBrowser.showSortMenu({ + items: [{ + name: Globalize.translate("OptionNameSort"), + id: "SortName" + }, { + name: Globalize.translate("OptionImdbRating"), + id: "CommunityRating,SortName" + }, { + name: Globalize.translate("OptionDateAdded"), + id: "DateCreated,SortName" + }, { + name: Globalize.translate("OptionDatePlayed"), + id: "DatePlayed,SortName" + }, { + name: Globalize.translate("OptionParentalRating"), + id: "OfficialRating,SortName" + }, { + name: Globalize.translate("OptionPlayCount"), + id: "PlayCount,SortName" + }, { + name: Globalize.translate("OptionReleaseDate"), + id: "PremiereDate,SortName" + }], + callback: function () { + getQuery(tabContent).StartIndex = 0; + reloadItems(); + }, + query: getQuery(tabContent), + button: e.target + }); + }); + } + + initPage(tabContent); + + self.renderTab = function () { + reloadItems(); + updateFilterControls(tabContent); + }; + + self.destroy = function () {}; + }; }); diff --git a/src/controllers/music/musicalbums.js b/src/controllers/music/musicalbums.js index 8a562c532d..ac45d9a15b 100644 --- a/src/controllers/music/musicalbums.js +++ b/src/controllers/music/musicalbums.js @@ -1,190 +1,275 @@ -define(["layoutManager", "playbackManager", "loading", "events", "libraryBrowser", "imageLoader", "alphaPicker", "listView", "cardBuilder", "apphost", "emby-itemscontainer"], function(layoutManager, playbackManager, loading, events, libraryBrowser, imageLoader, alphaPicker, listView, cardBuilder, appHost) { +define(["layoutManager", "playbackManager", "loading", "events", "libraryBrowser", "imageLoader", "alphaPicker", "listView", "cardBuilder", "apphost", "emby-itemscontainer"], function (layoutManager, playbackManager, loading, events, libraryBrowser, imageLoader, alphaPicker, listView, cardBuilder, appHost) { "use strict"; - return function(view, params, tabContent) { + + return function (view, params, tabContent) { function playAll() { - ApiClient.getItem(ApiClient.getCurrentUserId(), params.topParentId).then(function(item) { + ApiClient.getItem(ApiClient.getCurrentUserId(), params.topParentId).then(function (item) { playbackManager.play({ items: [item] - }) - }) + }); + }); } function shuffle() { - ApiClient.getItem(ApiClient.getCurrentUserId(), params.topParentId).then(function(item) { + ApiClient.getItem(ApiClient.getCurrentUserId(), params.topParentId).then(function (item) { getQuery(); - playbackManager.shuffle(item, null) - }) + playbackManager.shuffle(item, null); + }); } function getPageData() { var key = getSavedQueryKey(); - return pageData || (pageData = { - query: { - SortBy: "SortName", - SortOrder: "Ascending", - IncludeItemTypes: "MusicAlbum", - Recursive: !0, - Fields: "PrimaryImageAspectRatio,SortName,BasicSyncInfo", - ImageTypeLimit: 1, - EnableImageTypes: "Primary,Backdrop,Banner,Thumb", - StartIndex: 0, - Limit: pageSize - }, - view: libraryBrowser.getSavedView(key) || "Poster" - }, pageData.query.ParentId = params.topParentId, libraryBrowser.loadSavedQueryValues(key, pageData.query)), pageData + + if (!pageData) { + pageData = { + query: { + SortBy: "SortName", + SortOrder: "Ascending", + IncludeItemTypes: "MusicAlbum", + Recursive: true, + Fields: "PrimaryImageAspectRatio,SortName,BasicSyncInfo", + ImageTypeLimit: 1, + EnableImageTypes: "Primary,Backdrop,Banner,Thumb", + StartIndex: 0, + Limit: pageSize + }, + view: libraryBrowser.getSavedView(key) || "Poster" + }; + pageData.query.ParentId = params.topParentId; + libraryBrowser.loadSavedQueryValues(key, pageData.query); + } + + return pageData; } function getQuery() { - return getPageData().query + return getPageData().query; } function getSavedQueryKey() { - return savedQueryKey || (savedQueryKey = libraryBrowser.getSavedQueryKey("musicalbums")), savedQueryKey + if (!savedQueryKey) { + savedQueryKey = libraryBrowser.getSavedQueryKey("musicalbums"); + } + + return savedQueryKey; } function onViewStyleChange() { - var viewStyle = self.getCurrentViewStyle(), - itemsContainer = tabContent.querySelector(".itemsContainer"); - "List" == viewStyle ? (itemsContainer.classList.add("vertical-list"), itemsContainer.classList.remove("vertical-wrap")) : (itemsContainer.classList.remove("vertical-list"), itemsContainer.classList.add("vertical-wrap")), itemsContainer.innerHTML = "" + var viewStyle = self.getCurrentViewStyle(); + var itemsContainer = tabContent.querySelector(".itemsContainer"); + + if ("List" == viewStyle) { + itemsContainer.classList.add("vertical-list"); + itemsContainer.classList.remove("vertical-wrap"); + } else { + itemsContainer.classList.remove("vertical-list"); + itemsContainer.classList.add("vertical-wrap"); + } + + itemsContainer.innerHTML = ""; } function reloadItems(page) { loading.show(); isLoading = true; var query = getQuery(); - ApiClient.getItems(ApiClient.getCurrentUserId(), query).then(function(result) { + ApiClient.getItems(ApiClient.getCurrentUserId(), query).then(function (result) { function onNextPageClick() { - if (isLoading) return; - query.StartIndex += query.Limit, reloadItems(tabContent) + if (isLoading) { + return; + } + + query.StartIndex += query.Limit; + reloadItems(tabContent); } function onPreviousPageClick() { - if (isLoading) return; - query.StartIndex -= query.Limit, reloadItems(tabContent) + if (isLoading) { + return; + } + + query.StartIndex -= query.Limit; + reloadItems(tabContent); } - window.scrollTo(0, 0), updateFilterControls(page); - var html, pagingHtml = libraryBrowser.getQueryPagingHtml({ - startIndex: query.StartIndex, - limit: query.Limit, - totalRecordCount: result.TotalRecordCount, - showLimit: !1, - updatePageSizeSetting: !1, - addLayoutButton: !1, - sortButton: !1, - filterButton: !1 - }), - viewStyle = self.getCurrentViewStyle(); - html = "List" == viewStyle ? listView.getListViewHtml({ - items: result.Items, - context: "music", - sortBy: query.SortBy, - addToListButton: !0 - }) : "PosterCard" == viewStyle ? cardBuilder.getCardsHtml({ - items: result.Items, - shape: "square", - context: "music", - showTitle: !0, - coverImage: !0, - showParentTitle: !0, - lazy: !0, - cardLayout: !0 - }) : cardBuilder.getCardsHtml({ - items: result.Items, - shape: "square", - context: "music", - showTitle: !0, - showParentTitle: !0, - lazy: !0, - centerText: !0, - overlayPlayButton: !0 + + window.scrollTo(0, 0); + updateFilterControls(page); + var html; + var pagingHtml = libraryBrowser.getQueryPagingHtml({ + startIndex: query.StartIndex, + limit: query.Limit, + totalRecordCount: result.TotalRecordCount, + showLimit: false, + updatePageSizeSetting: false, + addLayoutButton: false, + sortButton: false, + filterButton: false }); - var i, length, elems = tabContent.querySelectorAll(".paging"); - for (i = 0, length = elems.length; i < length; i++) elems[i].innerHTML = pagingHtml; - for (elems = tabContent.querySelectorAll(".btnNextPage"), i = 0, length = elems.length; i < length; i++) elems[i].addEventListener("click", onNextPageClick); - for (elems = tabContent.querySelectorAll(".btnPreviousPage"), i = 0, length = elems.length; i < length; i++) elems[i].addEventListener("click", onPreviousPageClick); + var viewStyle = self.getCurrentViewStyle(); + if (viewStyle == "List") { + html = listView.getListViewHtml({ + items: result.Items, + context: "music", + sortBy: query.SortBy, + addToListButton: true + }); + } else if (viewStyle == "PosterCard") { + html = cardBuilder.getCardsHtml({ + items: result.Items, + shape: "square", + context: "music", + showTitle: true, + coverImage: true, + showParentTitle: true, + lazy: true, + cardLayout: true + }); + } else { + html = cardBuilder.getCardsHtml({ + items: result.Items, + shape: "square", + context: "music", + showTitle: true, + showParentTitle: true, + lazy: true, + centerText: true, + overlayPlayButton: true + }); + } + var i; + var length; + var elems = tabContent.querySelectorAll(".paging"); + + for (i = 0, length = elems.length; i < length; i++) { + elems[i].innerHTML = pagingHtml; + } + + elems = tabContent.querySelectorAll(".btnNextPage"); + for (i = 0, length = elems.length; i < length; i++) { + elems[i].addEventListener("click", onNextPageClick); + } + + elems = tabContent.querySelectorAll(".btnPreviousPage"); + for (i = 0, length = elems.length; i < length; i++) { + elems[i].addEventListener("click", onPreviousPageClick); + } + var itemsContainer = tabContent.querySelector(".itemsContainer"); itemsContainer.innerHTML = html; imageLoader.lazyChildren(itemsContainer); libraryBrowser.saveQueryValues(getSavedQueryKey(), query); loading.hide(); isLoading = false; - }) + }); } function updateFilterControls(tabContent) { var query = getQuery(); - self.alphaPicker.value(query.NameStartsWithOrGreater) + self.alphaPicker.value(query.NameStartsWithOrGreater); } - var savedQueryKey, pageData, self = this, - pageSize = 100, - isLoading = false; - self.showFilterMenu = function() { - require(["components/filterdialog/filterdialog"], function(filterDialogFactory) { - var filterDialog = new filterDialogFactory({ - query: getQuery(), - mode: "albums", - serverId: ApiClient.serverId() - }); - events.on(filterDialog, "filterchange", function() { - getQuery().StartIndex = 0, reloadItems(tabContent) - }), filterDialog.show() - }) - }, self.getCurrentViewStyle = function() { - return getPageData().view - }, - function(tabContent) { - var alphaPickerElement = tabContent.querySelector(".alphaPicker"); - if (alphaPickerElement.addEventListener("alphavaluechanged", function(e) { - var newValue = e.detail.value, - query = getQuery(); - query.NameStartsWithOrGreater = newValue, query.StartIndex = 0, reloadItems(tabContent) - }), self.alphaPicker = new alphaPicker({ - element: alphaPickerElement, - valueChangeEvent: "click" - }), layoutManager.desktop || layoutManager.mobile) { - tabContent.querySelector(".alphaPicker").classList.add("alphabetPicker-right"); - var itemsContainer = tabContent.querySelector(".itemsContainer"); - itemsContainer.classList.remove("padded-left-withalphapicker"), itemsContainer.classList.add("padded-right-withalphapicker") - } - tabContent.querySelector(".btnFilter").addEventListener("click", function() { - self.showFilterMenu() - }), tabContent.querySelector(".btnSort").addEventListener("click", function(e) { - libraryBrowser.showSortMenu({ - items: [{ - name: Globalize.translate("OptionNameSort"), - id: "SortName" - }, { - name: Globalize.translate("OptionAlbumArtist"), - id: "AlbumArtist,SortName" - }, { - name: Globalize.translate("OptionCommunityRating"), - id: "CommunityRating,SortName" - }, { - name: Globalize.translate("OptionCriticRating"), - id: "CriticRating,SortName" - }, { - name: Globalize.translate("OptionDateAdded"), - id: "DateCreated,SortName" - }, { - name: Globalize.translate("OptionReleaseDate"), - id: "ProductionYear,PremiereDate,SortName" - }], - callback: function() { - getQuery().StartIndex = 0, reloadItems(tabContent) - }, - query: getQuery(), - button: e.target - }) + + var savedQueryKey; + var pageData; + var self = this; + var pageSize = 100; + var isLoading = false; + + self.showFilterMenu = function () { + require(["components/filterdialog/filterdialog"], function (filterDialogFactory) { + var filterDialog = new filterDialogFactory({ + query: getQuery(), + mode: "albums", + serverId: ApiClient.serverId() }); - var btnSelectView = tabContent.querySelector(".btnSelectView"); - btnSelectView.addEventListener("click", function(e) { - libraryBrowser.showLayoutMenu(e.target, self.getCurrentViewStyle(), "List,Poster,PosterCard".split(",")) - }), btnSelectView.addEventListener("layoutchange", function(e) { - var viewStyle = e.detail.viewStyle; - getPageData().view = viewStyle, libraryBrowser.saveViewSetting(getSavedQueryKey(), viewStyle), getQuery().StartIndex = 0, onViewStyleChange(), reloadItems(tabContent) - }), tabContent.querySelector(".btnPlayAll").addEventListener("click", playAll), tabContent.querySelector(".btnShuffle").addEventListener("click", shuffle) - }(tabContent), onViewStyleChange(), self.renderTab = function() { - reloadItems(tabContent), updateFilterControls(tabContent) - }, self.destroy = function() {} - } + events.on(filterDialog, "filterchange", function () { + getQuery().StartIndex = 0; + reloadItems(tabContent); + }); + filterDialog.show(); + }); + }; + + self.getCurrentViewStyle = function () { + return getPageData().view; + }; + + function initPage(tabContent) { + var alphaPickerElement = tabContent.querySelector(".alphaPicker"); + + alphaPickerElement.addEventListener("alphavaluechanged", function (e) { + var newValue = e.detail.value; + var query = getQuery(); + query.NameStartsWithOrGreater = newValue; + query.StartIndex = 0; + reloadItems(tabContent); + }); + self.alphaPicker = new alphaPicker({ + element: alphaPickerElement, + valueChangeEvent: "click" + }); + if (layoutManager.desktop || layoutManager.mobile) { + tabContent.querySelector(".alphaPicker").classList.add("alphabetPicker-right"); + var itemsContainer = tabContent.querySelector(".itemsContainer"); + itemsContainer.classList.remove("padded-left-withalphapicker"); + itemsContainer.classList.add("padded-right-withalphapicker"); + } + + tabContent.querySelector(".btnFilter").addEventListener("click", function () { + self.showFilterMenu(); + }); + tabContent.querySelector(".btnSort").addEventListener("click", function (e) { + libraryBrowser.showSortMenu({ + items: [{ + name: Globalize.translate("OptionNameSort"), + id: "SortName" + }, { + name: Globalize.translate("OptionAlbumArtist"), + id: "AlbumArtist,SortName" + }, { + name: Globalize.translate("OptionCommunityRating"), + id: "CommunityRating,SortName" + }, { + name: Globalize.translate("OptionCriticRating"), + id: "CriticRating,SortName" + }, { + name: Globalize.translate("OptionDateAdded"), + id: "DateCreated,SortName" + }, { + name: Globalize.translate("OptionReleaseDate"), + id: "ProductionYear,PremiereDate,SortName" + }], + callback: function () { + getQuery().StartIndex = 0; + reloadItems(tabContent); + }, + query: getQuery(), + button: e.target + }); + }); + var btnSelectView = tabContent.querySelector(".btnSelectView"); + btnSelectView.addEventListener("click", function (e) { + libraryBrowser.showLayoutMenu(e.target, self.getCurrentViewStyle(), "List,Poster,PosterCard".split(",")); + }); + btnSelectView.addEventListener("layoutchange", function (e) { + var viewStyle = e.detail.viewStyle; + getPageData().view = viewStyle; + libraryBrowser.saveViewSetting(getSavedQueryKey(), viewStyle); + getQuery().StartIndex = 0; + onViewStyleChange(); + reloadItems(tabContent); + }); + tabContent.querySelector(".btnPlayAll").addEventListener("click", playAll); + tabContent.querySelector(".btnShuffle").addEventListener("click", shuffle); + } + + initPage(tabContent); + onViewStyleChange(); + + self.renderTab = function () { + reloadItems(tabContent); + updateFilterControls(tabContent); + }; + + self.destroy = function () {}; + }; }); diff --git a/src/controllers/music/musicartists.js b/src/controllers/music/musicartists.js index b28385169d..5159f635f8 100644 --- a/src/controllers/music/musicartists.js +++ b/src/controllers/music/musicartists.js @@ -1,144 +1,226 @@ -define(["layoutManager", "loading", "events", "libraryBrowser", "imageLoader", "alphaPicker", "listView", "cardBuilder", "apphost", "emby-itemscontainer"], function(layoutManager, loading, events, libraryBrowser, imageLoader, alphaPicker, listView, cardBuilder, appHost) { +define(["layoutManager", "loading", "events", "libraryBrowser", "imageLoader", "alphaPicker", "listView", "cardBuilder", "apphost", "emby-itemscontainer"], function (layoutManager, loading, events, libraryBrowser, imageLoader, alphaPicker, listView, cardBuilder, appHost) { "use strict"; - return function(view, params, tabContent) { + + return function (view, params, tabContent) { function getPageData(context) { - var key = getSavedQueryKey(context), - pageData = data[key]; - return pageData || (pageData = data[key] = { - query: { - SortBy: "SortName", - SortOrder: "Ascending", - Recursive: !0, - Fields: "PrimaryImageAspectRatio,SortName,BasicSyncInfo", - StartIndex: 0, - ImageTypeLimit: 1, - EnableImageTypes: "Primary,Backdrop,Banner,Thumb", - Limit: 100 - }, - view: libraryBrowser.getSavedView(key) || "Poster" - }, pageData.query.ParentId = params.topParentId, libraryBrowser.loadSavedQueryValues(key, pageData.query)), pageData + var key = getSavedQueryKey(context); + var pageData = data[key]; + + if (!pageData) { + pageData = data[key] = { + query: { + SortBy: "SortName", + SortOrder: "Ascending", + Recursive: true, + Fields: "PrimaryImageAspectRatio,SortName,BasicSyncInfo", + StartIndex: 0, + ImageTypeLimit: 1, + EnableImageTypes: "Primary,Backdrop,Banner,Thumb", + Limit: 100 + }, + view: libraryBrowser.getSavedView(key) || "Poster" + }; + pageData.query.ParentId = params.topParentId; + libraryBrowser.loadSavedQueryValues(key, pageData.query); + } + + return pageData; } function getQuery(context) { - return getPageData(context).query + return getPageData(context).query; } function getSavedQueryKey(context) { - return context.savedQueryKey || (context.savedQueryKey = libraryBrowser.getSavedQueryKey(self.mode)), context.savedQueryKey + if (!context.savedQueryKey) { + context.savedQueryKey = libraryBrowser.getSavedQueryKey(self.mode); + } + + return context.savedQueryKey; } function onViewStyleChange() { - var viewStyle = self.getCurrentViewStyle(), - itemsContainer = tabContent.querySelector(".itemsContainer"); - "List" == viewStyle ? (itemsContainer.classList.add("vertical-list"), itemsContainer.classList.remove("vertical-wrap")) : (itemsContainer.classList.remove("vertical-list"), itemsContainer.classList.add("vertical-wrap")), itemsContainer.innerHTML = "" + var viewStyle = self.getCurrentViewStyle(); + var itemsContainer = tabContent.querySelector(".itemsContainer"); + + if ("List" == viewStyle) { + itemsContainer.classList.add("vertical-list"); + itemsContainer.classList.remove("vertical-wrap"); + } else { + itemsContainer.classList.remove("vertical-list"); + itemsContainer.classList.add("vertical-wrap"); + } + + itemsContainer.innerHTML = ""; } function reloadItems(page) { loading.show(); isLoading = true; var query = getQuery(page); - ("albumartists" == self.mode ? ApiClient.getAlbumArtists(ApiClient.getCurrentUserId(), query) : ApiClient.getArtists(ApiClient.getCurrentUserId(), query)).then(function(result) { + var promise = self.mode == 'albumartists' ? + ApiClient.getAlbumArtists(ApiClient.getCurrentUserId(), query) : + ApiClient.getArtists(ApiClient.getCurrentUserId(), query); + promise.then(function (result) { function onNextPageClick() { - if (isLoading) return; - query.StartIndex += query.Limit, reloadItems(tabContent) + if (isLoading) { + return; + } + + query.StartIndex += query.Limit; + reloadItems(tabContent); } function onPreviousPageClick() { - if (isLoading) return; - query.StartIndex -= query.Limit, reloadItems(tabContent) + if (isLoading) { + return; + } + + query.StartIndex -= query.Limit; + reloadItems(tabContent); } - window.scrollTo(0, 0), updateFilterControls(page); - var html, pagingHtml = libraryBrowser.getQueryPagingHtml({ - startIndex: query.StartIndex, - limit: query.Limit, - totalRecordCount: result.TotalRecordCount, - showLimit: !1, - updatePageSizeSetting: !1, - addLayoutButton: !1, - sortButton: !1, - filterButton: !1 - }), - viewStyle = self.getCurrentViewStyle(); - html = "List" == viewStyle ? listView.getListViewHtml({ - items: result.Items, - sortBy: query.SortBy - }) : "PosterCard" == viewStyle ? cardBuilder.getCardsHtml({ - items: result.Items, - shape: "square", - context: "music", - showTitle: !0, - coverImage: !0, - cardLayout: !0 - }) : cardBuilder.getCardsHtml({ - items: result.Items, - shape: "square", - context: "music", - showTitle: !0, - coverImage: !0, - lazy: !0, - centerText: !0, - overlayPlayButton: !0 + + window.scrollTo(0, 0); + updateFilterControls(page); + var html; + var pagingHtml = libraryBrowser.getQueryPagingHtml({ + startIndex: query.StartIndex, + limit: query.Limit, + totalRecordCount: result.TotalRecordCount, + showLimit: false, + updatePageSizeSetting: false, + addLayoutButton: false, + sortButton: false, + filterButton: false }); - var i, length, elems = tabContent.querySelectorAll(".paging"); - for (i = 0, length = elems.length; i < length; i++) elems[i].innerHTML = pagingHtml; - for (elems = tabContent.querySelectorAll(".btnNextPage"), i = 0, length = elems.length; i < length; i++) elems[i].addEventListener("click", onNextPageClick); - for (elems = tabContent.querySelectorAll(".btnPreviousPage"), i = 0, length = elems.length; i < length; i++) elems[i].addEventListener("click", onPreviousPageClick); + var viewStyle = self.getCurrentViewStyle(); + if (viewStyle == "List") { + html = listView.getListViewHtml({ + items: result.Items, + sortBy: query.SortBy + }); + } else if (viewStyle == "PosterCard") { + html = cardBuilder.getCardsHtml({ + items: result.Items, + shape: "square", + context: "music", + showTitle: true, + coverImage: true, + cardLayout: true + }); + } else { + html = cardBuilder.getCardsHtml({ + items: result.Items, + shape: "square", + context: "music", + showTitle: true, + coverImage: true, + lazy: true, + centerText: true, + overlayPlayButton: true + }); + } + var i; + var length; + var elems = tabContent.querySelectorAll(".paging"); + + for (i = 0, length = elems.length; i < length; i++) { + elems[i].innerHTML = pagingHtml; + } + + elems = tabContent.querySelectorAll(".btnNextPage"); + for (i = 0, length = elems.length; i < length; i++) { + elems[i].addEventListener("click", onNextPageClick); + } + + elems = tabContent.querySelectorAll(".btnPreviousPage"); + for (i = 0, length = elems.length; i < length; i++) { + elems[i].addEventListener("click", onPreviousPageClick); + } + var itemsContainer = tabContent.querySelector(".itemsContainer"); itemsContainer.innerHTML = html; imageLoader.lazyChildren(itemsContainer); libraryBrowser.saveQueryValues(getSavedQueryKey(page), query); loading.hide(); isLoading = false; - }) + }); } function updateFilterControls(tabContent) { var query = getQuery(tabContent); - self.alphaPicker.value(query.NameStartsWithOrGreater) + self.alphaPicker.value(query.NameStartsWithOrGreater); } - var self = this, - data = {}, - isLoading = false; - self.showFilterMenu = function() { - require(["components/filterdialog/filterdialog"], function(filterDialogFactory) { - var filterDialog = new filterDialogFactory({ - query: getQuery(tabContent), - mode: self.mode, - serverId: ApiClient.serverId() - }); - events.on(filterDialog, "filterchange", function() { - getQuery(tabContent).StartIndex = 0, reloadItems(tabContent) - }), filterDialog.show() - }) - }, self.getCurrentViewStyle = function() { - return getPageData(tabContent).view - }, - function(tabContent) { - var alphaPickerElement = tabContent.querySelector(".alphaPicker"); - if (alphaPickerElement.addEventListener("alphavaluechanged", function(e) { - var newValue = e.detail.value, - query = getQuery(tabContent); - query.NameStartsWithOrGreater = newValue, query.StartIndex = 0, reloadItems(tabContent) - }), self.alphaPicker = new alphaPicker({ - element: alphaPickerElement, - valueChangeEvent: "click" - }), layoutManager.desktop || layoutManager.mobile) { - tabContent.querySelector(".alphaPicker").classList.add("alphabetPicker-right"); - var itemsContainer = tabContent.querySelector(".itemsContainer"); - itemsContainer.classList.remove("padded-left-withalphapicker"), itemsContainer.classList.add("padded-right-withalphapicker") - } - tabContent.querySelector(".btnFilter").addEventListener("click", function() { - self.showFilterMenu() + + var self = this; + var data = {}; + var isLoading = false; + + self.showFilterMenu = function () { + require(["components/filterdialog/filterdialog"], function (filterDialogFactory) { + var filterDialog = new filterDialogFactory({ + query: getQuery(tabContent), + mode: self.mode, + serverId: ApiClient.serverId() }); - var btnSelectView = tabContent.querySelector(".btnSelectView"); - btnSelectView.addEventListener("click", function(e) { - libraryBrowser.showLayoutMenu(e.target, self.getCurrentViewStyle(), "List,Poster,PosterCard".split(",")) - }), btnSelectView.addEventListener("layoutchange", function(e) { - var viewStyle = e.detail.viewStyle; - getPageData(tabContent).view = viewStyle, libraryBrowser.saveViewSetting(getSavedQueryKey(tabContent), viewStyle), getQuery(tabContent).StartIndex = 0, onViewStyleChange(), reloadItems(tabContent) - }) - }(tabContent), onViewStyleChange(), self.renderTab = function() { - reloadItems(tabContent), updateFilterControls(tabContent) - }, self.destroy = function() {} - } + events.on(filterDialog, "filterchange", function () { + getQuery(tabContent).StartIndex = 0; + reloadItems(tabContent); + }); + filterDialog.show(); + }); + }; + + self.getCurrentViewStyle = function () { + return getPageData(tabContent).view; + }; + + function initPage(tabContent) { + var alphaPickerElement = tabContent.querySelector(".alphaPicker"); + + alphaPickerElement.addEventListener("alphavaluechanged", function (e) { + var newValue = e.detail.value; + var query = getQuery(tabContent); + query.NameStartsWithOrGreater = newValue; + query.StartIndex = 0; + reloadItems(tabContent); + }); + self.alphaPicker = new alphaPicker({ + element: alphaPickerElement, + valueChangeEvent: "click" + }); + if (layoutManager.desktop || layoutManager.mobile) { + tabContent.querySelector(".alphaPicker").classList.add("alphabetPicker-right"); + var itemsContainer = tabContent.querySelector(".itemsContainer"); + itemsContainer.classList.remove("padded-left-withalphapicker"); + itemsContainer.classList.add("padded-right-withalphapicker"); + } + + tabContent.querySelector(".btnFilter").addEventListener("click", function () { + self.showFilterMenu(); + }); + var btnSelectView = tabContent.querySelector(".btnSelectView"); + btnSelectView.addEventListener("click", function (e) { + libraryBrowser.showLayoutMenu(e.target, self.getCurrentViewStyle(), "List,Poster,PosterCard".split(",")); + }); + btnSelectView.addEventListener("layoutchange", function (e) { + var viewStyle = e.detail.viewStyle; + getPageData(tabContent).view = viewStyle; + libraryBrowser.saveViewSetting(getSavedQueryKey(tabContent), viewStyle); + getQuery(tabContent).StartIndex = 0; + onViewStyleChange(); + reloadItems(tabContent); + }); + } + + initPage(tabContent); + onViewStyleChange(); + + self.renderTab = function () { + reloadItems(tabContent); + updateFilterControls(tabContent); + }; + + self.destroy = function () {}; + }; }); diff --git a/src/controllers/music/musicgenres.js b/src/controllers/music/musicgenres.js index f66afcdb20..ed1efc0a6a 100644 --- a/src/controllers/music/musicgenres.js +++ b/src/controllers/music/musicgenres.js @@ -1,91 +1,126 @@ -define(["libraryBrowser", "cardBuilder", "apphost", "imageLoader", "loading"], function(libraryBrowser, cardBuilder, appHost, imageLoader, loading) { +define(["libraryBrowser", "cardBuilder", "apphost", "imageLoader", "loading"], function (libraryBrowser, cardBuilder, appHost, imageLoader, loading) { "use strict"; - return function(view, params, tabContent) { + + return function (view, params, tabContent) { function getPageData() { - var key = getSavedQueryKey(), - pageData = data[key]; - return pageData || (pageData = data[key] = { - query: { - SortBy: "SortName", - SortOrder: "Ascending", - Recursive: !0, - Fields: "PrimaryImageAspectRatio,ItemCounts", - StartIndex: 0 - }, - view: libraryBrowser.getSavedView(key) || "Poster" - }, pageData.query.ParentId = params.topParentId, libraryBrowser.loadSavedQueryValues(key, pageData.query)), pageData + var key = getSavedQueryKey(); + var pageData = data[key]; + + if (!pageData) { + pageData = data[key] = { + query: { + SortBy: "SortName", + SortOrder: "Ascending", + Recursive: true, + Fields: "PrimaryImageAspectRatio,ItemCounts", + StartIndex: 0 + }, + view: libraryBrowser.getSavedView(key) || "Poster" + }; + pageData.query.ParentId = params.topParentId; + libraryBrowser.loadSavedQueryValues(key, pageData.query); + } + + return pageData; } function getQuery() { - return getPageData().query + return getPageData().query; } function getSavedQueryKey() { - return libraryBrowser.getSavedQueryKey("genres") + return libraryBrowser.getSavedQueryKey("genres"); } function getPromise() { loading.show(); var query = getQuery(); - return ApiClient.getGenres(ApiClient.getCurrentUserId(), query) + return ApiClient.getGenres(ApiClient.getCurrentUserId(), query); } function reloadItems(context, promise) { var query = getQuery(); - promise.then(function(result) { - var html = "", - viewStyle = self.getCurrentViewStyle(); - "Thumb" == viewStyle ? html = cardBuilder.getCardsHtml({ - items: result.Items, - shape: "backdrop", - preferThumb: !0, - context: "music", - centerText: !0, - overlayMoreButton: !0, - showTitle: !0 - }) : "ThumbCard" == viewStyle ? html = cardBuilder.getCardsHtml({ - items: result.Items, - shape: "backdrop", - preferThumb: !0, - context: "music", - cardLayout: !0, - showTitle: !0 - }) : "PosterCard" == viewStyle ? html = cardBuilder.getCardsHtml({ - items: result.Items, - shape: "auto", - context: "music", - cardLayout: !0, - showTitle: !0 - }) : "Poster" == viewStyle && (html = cardBuilder.getCardsHtml({ - items: result.Items, - shape: "auto", - context: "music", - centerText: !0, - overlayMoreButton: !0, - showTitle: !0 - })); + promise.then(function (result) { + var html = ""; + var viewStyle = self.getCurrentViewStyle(); + + if (viewStyle == "Thumb") { + html = cardBuilder.getCardsHtml({ + items: result.Items, + shape: "backdrop", + preferThumb: true, + context: 'music', + centerText: true, + overlayMoreButton: true, + showTitle: true + }); + } else if (viewStyle == "ThumbCard") { + html = cardBuilder.getCardsHtml({ + items: result.Items, + shape: "backdrop", + preferThumb: true, + context: 'music', + cardLayout: true, + showTitle: true, + }); + } else if (viewStyle == "PosterCard") { + html = cardBuilder.getCardsHtml({ + items: result.Items, + shape: "auto", + context: 'music', + cardLayout: true, + showTitle: true, + }); + } else if (viewStyle == "Poster") { + html = cardBuilder.getCardsHtml({ + items: result.Items, + shape: "auto", + context: 'music', + centerText: true, + overlayMoreButton: true, + showTitle: true + }); + } + var elem = context.querySelector("#items"); - elem.innerHTML = html, imageLoader.lazyChildren(elem), libraryBrowser.saveQueryValues(getSavedQueryKey(), query), loading.hide() - }) + elem.innerHTML = html; + imageLoader.lazyChildren(elem); + libraryBrowser.saveQueryValues(getSavedQueryKey(), query); + loading.hide(); + }); } function fullyReload() { - self.preRender(), self.renderTab() + self.preRender(); + self.renderTab(); } - var self = this, - data = {}; - self.getViewStyles = function() { - return "Poster,PosterCard,Thumb,ThumbCard".split(",") - }, self.getCurrentViewStyle = function() { - return getPageData(tabContent).view - }, self.setCurrentViewStyle = function(viewStyle) { - getPageData(tabContent).view = viewStyle, libraryBrowser.saveViewSetting(getSavedQueryKey(tabContent), viewStyle), fullyReload() - }, self.enableViewSelection = !0; + + var self = this; + var data = {}; + + self.getViewStyles = function () { + return "Poster,PosterCard,Thumb,ThumbCard".split(","); + }; + + self.getCurrentViewStyle = function () { + return getPageData(tabContent).view; + }; + + self.setCurrentViewStyle = function (viewStyle) { + getPageData(tabContent).view = viewStyle; + libraryBrowser.saveViewSetting(getSavedQueryKey(tabContent), viewStyle); + fullyReload(); + }; + + self.enableViewSelection = true; var promise; - self.preRender = function() { - promise = getPromise() - }, self.renderTab = function() { - reloadItems(tabContent, promise) - } - } -}); \ No newline at end of file + + self.preRender = function () { + promise = getPromise(); + }; + + self.renderTab = function () { + reloadItems(tabContent, promise); + }; + }; +}); diff --git a/src/controllers/music/musicplaylists.js b/src/controllers/music/musicplaylists.js index 511ace73a7..964896077b 100644 --- a/src/controllers/music/musicplaylists.js +++ b/src/controllers/music/musicplaylists.js @@ -1,64 +1,81 @@ -define(["libraryBrowser", "cardBuilder", "apphost", "imageLoader", "loading"], function(libraryBrowser, cardBuilder, appHost, imageLoader, loading) { +define(["libraryBrowser", "cardBuilder", "apphost", "imageLoader", "loading"], function (libraryBrowser, cardBuilder, appHost, imageLoader, loading) { "use strict"; - return function(view, params, tabContent) { + + return function (view, params, tabContent) { function getPageData() { - var key = getSavedQueryKey(), - pageData = data[key]; - return pageData || (pageData = data[key] = { - query: { - SortBy: "SortName", - SortOrder: "Ascending", - IncludeItemTypes: "Playlist", - Recursive: !0, - Fields: "PrimaryImageAspectRatio,SortName,CanDelete", - StartIndex: 0 - }, - view: libraryBrowser.getSavedView(key) || "Poster" - }, pageData.query.ParentId = params.topParentId, libraryBrowser.loadSavedQueryValues(key, pageData.query)), pageData + var key = getSavedQueryKey(); + var pageData = data[key]; + + if (!pageData) { + pageData = data[key] = { + query: { + SortBy: "SortName", + SortOrder: "Ascending", + IncludeItemTypes: "Playlist", + Recursive: true, + Fields: "PrimaryImageAspectRatio,SortName,CanDelete", + StartIndex: 0 + }, + view: libraryBrowser.getSavedView(key) || "Poster" + }; + pageData.query.ParentId = params.topParentId; + libraryBrowser.loadSavedQueryValues(key, pageData.query); + } + + return pageData; } function getQuery() { - return getPageData().query + return getPageData().query; } function getSavedQueryKey() { - return libraryBrowser.getSavedQueryKey("genres") + return libraryBrowser.getSavedQueryKey("genres"); } function getPromise() { loading.show(); var query = getQuery(); - return ApiClient.getItems(ApiClient.getCurrentUserId(), query) + return ApiClient.getItems(ApiClient.getCurrentUserId(), query); } function reloadItems(context, promise) { var query = getQuery(); - promise.then(function(result) { + promise.then(function (result) { var html = ""; html = cardBuilder.getCardsHtml({ items: result.Items, shape: "square", - showTitle: !0, - coverImage: !0, - centerText: !0, - overlayPlayButton: !0, - allowBottomPadding: !0, - cardLayout: !1 + showTitle: true, + coverImage: true, + centerText: true, + overlayPlayButton: true, + allowBottomPadding: true, + cardLayout: false }); var elem = context.querySelector("#items"); - elem.innerHTML = html, imageLoader.lazyChildren(elem), libraryBrowser.saveQueryValues(getSavedQueryKey(), query), loading.hide() - }) + elem.innerHTML = html; + imageLoader.lazyChildren(elem); + libraryBrowser.saveQueryValues(getSavedQueryKey(), query); + loading.hide(); + }); } - var self = this, - data = {}; - self.getCurrentViewStyle = function() { - return getPageData(tabContent).view + + var self = this; + var data = {}; + + self.getCurrentViewStyle = function () { + return getPageData(tabContent).view; }; + var promise; - self.preRender = function() { - promise = getPromise() - }, self.renderTab = function() { - reloadItems(tabContent, promise) - } - } -}); \ No newline at end of file + + self.preRender = function () { + promise = getPromise(); + }; + + self.renderTab = function () { + reloadItems(tabContent, promise); + }; + }; +}); diff --git a/src/controllers/music/musicrecommended.js b/src/controllers/music/musicrecommended.js index 5dee7c5f52..fc3371833d 100644 --- a/src/controllers/music/musicrecommended.js +++ b/src/controllers/music/musicrecommended.js @@ -1,49 +1,65 @@ -define(["browser", "layoutManager", "userSettings", "inputManager", "loading", "cardBuilder", "dom", "apphost", "imageLoader", "libraryMenu", "playbackManager", "mainTabsManager", "scrollStyles", "emby-itemscontainer", "emby-tabs", "emby-button", "flexStyles"], function(browser, layoutManager, userSettings, inputManager, loading, cardBuilder, dom, appHost, imageLoader, libraryMenu, playbackManager, mainTabsManager) { +define(["browser", "layoutManager", "userSettings", "inputManager", "loading", "cardBuilder", "dom", "apphost", "imageLoader", "libraryMenu", "playbackManager", "mainTabsManager", "scrollStyles", "emby-itemscontainer", "emby-tabs", "emby-button", "flexStyles"], function (browser, layoutManager, userSettings, inputManager, loading, cardBuilder, dom, appHost, imageLoader, libraryMenu, playbackManager, mainTabsManager) { "use strict"; function itemsPerRow() { var screenWidth = dom.getWindowSize().innerWidth; - return screenWidth >= 1920 ? 9 : screenWidth >= 1200 ? 12 : screenWidth >= 1e3 ? 10 : 8 + + if (screenWidth >= 1920) { + return 9; + } + + if (screenWidth >= 1200) { + return 12; + } + + if (screenWidth >= 1000) { + return 10; + } + + return 8; } function enableScrollX() { - return !layoutManager.desktop + return !layoutManager.desktop; } function getSquareShape() { - return enableScrollX() ? "overflowSquare" : "square" + return enableScrollX() ? "overflowSquare" : "square"; } function loadLatest(page, parentId) { loading.show(); - var userId = ApiClient.getCurrentUserId(), - options = { - IncludeItemTypes: "Audio", - Limit: enableScrollX() ? 3 * itemsPerRow() : 2 * itemsPerRow(), - Fields: "PrimaryImageAspectRatio,BasicSyncInfo", - ParentId: parentId, - ImageTypeLimit: 1, - EnableImageTypes: "Primary,Backdrop,Banner,Thumb", - EnableTotalRecordCount: !1 - }; - ApiClient.getJSON(ApiClient.getUrl("Users/" + userId + "/Items/Latest", options)).then(function(items) { - var elem = page.querySelector("#recentlyAddedSongs"), - supportsImageAnalysis = appHost.supports("imageanalysis"); - supportsImageAnalysis = !1, elem.innerHTML = cardBuilder.getCardsHtml({ + var userId = ApiClient.getCurrentUserId(); + var options = { + IncludeItemTypes: "Audio", + Limit: enableScrollX() ? 3 * itemsPerRow() : 2 * itemsPerRow(), + Fields: "PrimaryImageAspectRatio,BasicSyncInfo", + ParentId: parentId, + ImageTypeLimit: 1, + EnableImageTypes: "Primary,Backdrop,Banner,Thumb", + EnableTotalRecordCount: false + }; + ApiClient.getJSON(ApiClient.getUrl("Users/" + userId + "/Items/Latest", options)).then(function (items) { + var elem = page.querySelector("#recentlyAddedSongs"); + var supportsImageAnalysis = appHost.supports("imageanalysis"); + supportsImageAnalysis = false; + elem.innerHTML = cardBuilder.getCardsHtml({ items: items, - showUnplayedIndicator: !1, - showLatestItemsPopup: !1, + showUnplayedIndicator: false, + showLatestItemsPopup: false, shape: getSquareShape(), - showTitle: !0, - showParentTitle: !0, - lazy: !0, + showTitle: true, + showParentTitle: true, + lazy: true, centerText: !supportsImageAnalysis, overlayPlayButton: !supportsImageAnalysis, allowBottomPadding: !enableScrollX(), cardLayout: supportsImageAnalysis, - coverImage: !0 - }), imageLoader.lazyChildren(elem), loading.hide() - }) + coverImage: true + }); + imageLoader.lazyChildren(elem); + loading.hide(); + }); } function loadRecentlyPlayed(page, parentId) { @@ -52,34 +68,42 @@ define(["browser", "layoutManager", "userSettings", "inputManager", "loading", " SortOrder: "Descending", IncludeItemTypes: "Audio", Limit: itemsPerRow(), - Recursive: !0, + Recursive: true, Fields: "PrimaryImageAspectRatio,AudioInfo", Filters: "IsPlayed", ParentId: parentId, ImageTypeLimit: 1, EnableImageTypes: "Primary,Backdrop,Banner,Thumb", - EnableTotalRecordCount: !1 + EnableTotalRecordCount: false }; - ApiClient.getItems(ApiClient.getCurrentUserId(), options).then(function(result) { + ApiClient.getItems(ApiClient.getCurrentUserId(), options).then(function (result) { var elem = page.querySelector("#recentlyPlayed"); - result.Items.length ? elem.classList.remove("hide") : elem.classList.add("hide"); - var itemsContainer = elem.querySelector(".itemsContainer"), - supportsImageAnalysis = appHost.supports("imageanalysis"); - supportsImageAnalysis = !1, itemsContainer.innerHTML = cardBuilder.getCardsHtml({ + + if (result.Items.length) { + elem.classList.remove("hide"); + } else { + elem.classList.add("hide"); + } + + var itemsContainer = elem.querySelector(".itemsContainer"); + var supportsImageAnalysis = appHost.supports("imageanalysis"); + supportsImageAnalysis = false; + itemsContainer.innerHTML = cardBuilder.getCardsHtml({ items: result.Items, - showUnplayedIndicator: !1, + showUnplayedIndicator: false, shape: getSquareShape(), - showTitle: !0, - showParentTitle: !0, + showTitle: true, + showParentTitle: true, action: "instantmix", - lazy: !0, + lazy: true, centerText: !supportsImageAnalysis, overlayMoreButton: !supportsImageAnalysis, allowBottomPadding: !enableScrollX(), cardLayout: supportsImageAnalysis, - coverImage: !0 - }), imageLoader.lazyChildren(itemsContainer) - }) + coverImage: true + }); + imageLoader.lazyChildren(itemsContainer); + }); } function loadFrequentlyPlayed(page, parentId) { @@ -88,40 +112,53 @@ define(["browser", "layoutManager", "userSettings", "inputManager", "loading", " SortOrder: "Descending", IncludeItemTypes: "Audio", Limit: itemsPerRow(), - Recursive: !0, + Recursive: true, Fields: "PrimaryImageAspectRatio,AudioInfo", Filters: "IsPlayed", ParentId: parentId, ImageTypeLimit: 1, EnableImageTypes: "Primary,Backdrop,Banner,Thumb", - EnableTotalRecordCount: !1 + EnableTotalRecordCount: false }; - ApiClient.getItems(ApiClient.getCurrentUserId(), options).then(function(result) { + ApiClient.getItems(ApiClient.getCurrentUserId(), options).then(function (result) { var elem = page.querySelector("#topPlayed"); - result.Items.length ? elem.classList.remove("hide") : elem.classList.add("hide"); - var itemsContainer = elem.querySelector(".itemsContainer"), - supportsImageAnalysis = appHost.supports("imageanalysis"); - supportsImageAnalysis = !1, itemsContainer.innerHTML = cardBuilder.getCardsHtml({ + + if (result.Items.length) { + elem.classList.remove("hide"); + } else { + elem.classList.add("hide"); + } + + var itemsContainer = elem.querySelector(".itemsContainer"); + var supportsImageAnalysis = appHost.supports("imageanalysis"); + supportsImageAnalysis = false; + itemsContainer.innerHTML = cardBuilder.getCardsHtml({ items: result.Items, - showUnplayedIndicator: !1, + showUnplayedIndicator: false, shape: getSquareShape(), - showTitle: !0, - showParentTitle: !0, + showTitle: true, + showParentTitle: true, action: "instantmix", - lazy: !0, + lazy: true, centerText: !supportsImageAnalysis, overlayMoreButton: !supportsImageAnalysis, allowBottomPadding: !enableScrollX(), cardLayout: supportsImageAnalysis, - coverImage: !0 - }), imageLoader.lazyChildren(itemsContainer) - }) + coverImage: true + }); + imageLoader.lazyChildren(itemsContainer); + }); } function loadSuggestionsTab(page, tabContent, parentId) { - console.log("loadSuggestionsTab"), loadLatest(tabContent, parentId), loadRecentlyPlayed(tabContent, parentId), loadFrequentlyPlayed(tabContent, parentId), require(["components/favoriteitems"], function(favoriteItems) { - favoriteItems.render(tabContent, ApiClient.getCurrentUserId(), parentId, ["favoriteArtists", "favoriteAlbums", "favoriteSongs"]) - }) + console.log("loadSuggestionsTab"); + loadLatest(tabContent, parentId); + loadRecentlyPlayed(tabContent, parentId); + loadFrequentlyPlayed(tabContent, parentId); + + require(["components/favoriteitems"], function (favoriteItems) { + favoriteItems.render(tabContent, ApiClient.getCurrentUserId(), parentId, ["favoriteArtists", "favoriteAlbums", "favoriteSongs"]); + }); } function getTabs() { @@ -142,135 +179,227 @@ define(["browser", "layoutManager", "userSettings", "inputManager", "loading", " }, { name: Globalize.translate("ButtonSearch"), cssClass: "searchTabButton" - }] + }]; } function getDefaultTabIndex(folderId) { switch (userSettings.get("landing-" + folderId)) { case "albums": return 1; + case "albumartists": return 2; + case "artists": return 3; + case "playlists": return 4; + case "songs": return 5; + case "genres": return 6; + default: - return 0 + return 0; } } - return function(view, params) { + + return function (view, params) { function reload() { loading.show(); var tabContent = view.querySelector(".pageTabContent[data-index='0']"); - loadSuggestionsTab(view, tabContent, params.topParentId) + loadSuggestionsTab(view, tabContent, params.topParentId); } function enableScrollX() { - return browser.mobile + return browser.mobile; } function setScrollClasses(elem, scrollX) { - scrollX ? (elem.classList.add("hiddenScrollX"), layoutManager.tv && elem.classList.add("smoothScrollX"), elem.classList.add("scrollX"), elem.classList.remove("vertical-wrap")) : (elem.classList.remove("hiddenScrollX"), elem.classList.remove("smoothScrollX"), elem.classList.remove("scrollX"), elem.classList.add("vertical-wrap")) + if (scrollX) { + elem.classList.add("hiddenScrollX"); + + if (layoutManager.tv) { + elem.classList.add("smoothScrollX"); + } + + elem.classList.add("scrollX"); + elem.classList.remove("vertical-wrap"); + } else { + elem.classList.remove("hiddenScrollX"); + elem.classList.remove("smoothScrollX"); + elem.classList.remove("scrollX"); + elem.classList.add("vertical-wrap"); + } } function onBeforeTabChange(e) { - preLoadTab(view, parseInt(e.detail.selectedTabIndex)) + preLoadTab(view, parseInt(e.detail.selectedTabIndex)); } function onTabChange(e) { - loadTab(view, parseInt(e.detail.selectedTabIndex)) + loadTab(view, parseInt(e.detail.selectedTabIndex)); } function getTabContainers() { - return view.querySelectorAll(".pageTabContent") + return view.querySelectorAll(".pageTabContent"); } function initTabs() { - mainTabsManager.setTabs(view, currentTabIndex, getTabs, getTabContainers, onBeforeTabChange, onTabChange) + mainTabsManager.setTabs(view, currentTabIndex, getTabs, getTabContainers, onBeforeTabChange, onTabChange); } function getTabController(page, index, callback) { var depends = []; + switch (index) { case 0: break; + case 1: depends.push("controllers/music/musicalbums"); break; + case 2: case 3: depends.push("controllers/music/musicartists"); break; + case 4: depends.push("controllers/music/musicplaylists"); break; + case 5: depends.push("controllers/music/songs"); break; + case 6: depends.push("controllers/music/musicgenres"); break; + case 7: - depends.push("scripts/searchtab") + depends.push("scripts/searchtab"); } - require(depends, function(controllerFactory) { + + require(depends, function (controllerFactory) { var tabContent; - 0 == index && (tabContent = view.querySelector(".pageTabContent[data-index='" + index + "']"), self.tabContent = tabContent); + + if (0 == index) { + tabContent = view.querySelector(".pageTabContent[data-index='" + index + "']"); + self.tabContent = tabContent; + } + var controller = tabControllers[index]; - controller || (tabContent = view.querySelector(".pageTabContent[data-index='" + index + "']"), controller = 0 === index ? self : 7 === index ? new controllerFactory(view, tabContent, { - collectionType: "music", - parentId: params.topParentId - }) : new controllerFactory(view, params, tabContent), 2 == index ? controller.mode = "albumartists" : 3 == index && (controller.mode = "artists"), tabControllers[index] = controller, controller.initTab && controller.initTab()), callback(controller) - }) + + if (!controller) { + tabContent = view.querySelector(".pageTabContent[data-index='" + index + "']"); + + if (index === 0) { + controller = self; + } else if (index === 7) { + controller = new controllerFactory(view, tabContent, { + collectionType: "music", + parentId: params.topParentId + }); + } else { + controller = new controllerFactory(view, params, tabContent); + } + + if (index == 2) { + controller.mode = "albumartists"; + } else if (index == 3) { + controller.mode = "artists"; + } + + tabControllers[index] = controller; + if (controller.initTab) { + controller.initTab(); + } + } + + callback(controller); + }); } function preLoadTab(page, index) { - getTabController(page, index, function(controller) { - -1 == renderedTabs.indexOf(index) && controller.preRender && controller.preRender() - }) + getTabController(page, index, function (controller) { + if (renderedTabs.indexOf(index) == -1 && controller.preRender) { + controller.preRender(); + } + }); } function loadTab(page, index) { - currentTabIndex = index, getTabController(page, index, function(controller) { - initialTabIndex = null, -1 == renderedTabs.indexOf(index) && (renderedTabs.push(index), controller.renderTab()) - }) + currentTabIndex = index; + getTabController(page, index, function (controller) { + initialTabIndex = null; + + if (renderedTabs.indexOf(index) == -1) { + renderedTabs.push(index); + controller.renderTab(); + } + }); } function onInputCommand(e) { switch (e.detail.command) { case "search": - e.preventDefault(), Dashboard.navigate("search.html?collectionType=music&parentId=" + params.topParentId) + e.preventDefault(); + Dashboard.navigate("search.html?collectionType=music&parentId=" + params.topParentId); } } - var isViewRestored, self = this, - currentTabIndex = parseInt(params.tab || getDefaultTabIndex(params.topParentId)), - initialTabIndex = currentTabIndex; - self.initTab = function() { - for (var tabContent = view.querySelector(".pageTabContent[data-index='0']"), containers = tabContent.querySelectorAll(".itemsContainer"), i = 0, length = containers.length; i < length; i++) setScrollClasses(containers[i], enableScrollX()) - }, self.renderTab = function() { - reload() - }; - var tabControllers = [], - renderedTabs = []; - view.addEventListener("viewshow", function(e) { - if (isViewRestored = e.detail.isRestored, initTabs(), !view.getAttribute("data-title")) { - var parentId = params.topParentId; - parentId ? ApiClient.getItem(ApiClient.getCurrentUserId(), parentId).then(function(item) { - view.setAttribute("data-title", item.Name), libraryMenu.setTitle(item.Name) - }) : (view.setAttribute("data-title", Globalize.translate("TabMusic")), libraryMenu.setTitle(Globalize.translate("TabMusic"))) + + var isViewRestored; + var self = this; + var currentTabIndex = parseInt(params.tab || getDefaultTabIndex(params.topParentId)); + var initialTabIndex = currentTabIndex; + + self.initTab = function () { + var tabContent = view.querySelector(".pageTabContent[data-index='0']"); + var containers = tabContent.querySelectorAll(".itemsContainer"); + + for (var i = 0, length = containers.length; i < length; i++) { + setScrollClasses(containers[i], enableScrollX()); } - inputManager.on(window, onInputCommand) - }), view.addEventListener("viewbeforehide", function(e) { - inputManager.off(window, onInputCommand) - }), view.addEventListener("viewdestroy", function(e) { - tabControllers.forEach(function(t) { - t.destroy && t.destroy() - }) - }) - } -}); \ No newline at end of file + }; + + self.renderTab = function () { + reload(); + }; + + var tabControllers = []; + var renderedTabs = []; + view.addEventListener("viewshow", function (e) { + isViewRestored = e.detail.isRestored; + initTabs(); + if (!view.getAttribute("data-title")) { + var parentId = params.topParentId; + + if (parentId) { + ApiClient.getItem(ApiClient.getCurrentUserId(), parentId).then(function (item) { + view.setAttribute("data-title", item.Name); + libraryMenu.setTitle(item.Name); + }); + } else { + view.setAttribute("data-title", Globalize.translate("TabMusic")); + libraryMenu.setTitle(Globalize.translate("TabMusic")); + } + } + + inputManager.on(window, onInputCommand); + }); + view.addEventListener("viewbeforehide", function (e) { + inputManager.off(window, onInputCommand); + }); + view.addEventListener("viewdestroy", function (e) { + tabControllers.forEach(function (t) { + if (t.destroy) { + t.destroy(); + } + }); + }); + }; +}); diff --git a/src/controllers/music/songs.js b/src/controllers/music/songs.js index f03abe75ff..4806195edd 100644 --- a/src/controllers/music/songs.js +++ b/src/controllers/music/songs.js @@ -1,135 +1,185 @@ -define(["events", "libraryBrowser", "imageLoader", "listView", "loading", "emby-itemscontainer"], function(events, libraryBrowser, imageLoader, listView, loading) { +define(["events", "libraryBrowser", "imageLoader", "listView", "loading", "emby-itemscontainer"], function (events, libraryBrowser, imageLoader, listView, loading) { "use strict"; - return function(view, params, tabContent) { + + return function (view, params, tabContent) { function getPageData(context) { - var key = getSavedQueryKey(context), - pageData = data[key]; - return pageData || (pageData = data[key] = { - query: { - SortBy: "Album,SortName", - SortOrder: "Ascending", - IncludeItemTypes: "Audio", - Recursive: !0, - Fields: "AudioInfo,ParentId", - Limit: 100, - StartIndex: 0, - ImageTypeLimit: 1, - EnableImageTypes: "Primary" - } - }, pageData.query.ParentId = params.topParentId, libraryBrowser.loadSavedQueryValues(key, pageData.query)), pageData + var key = getSavedQueryKey(context); + var pageData = data[key]; + + if (!pageData) { + pageData = data[key] = { + query: { + SortBy: "Album,SortName", + SortOrder: "Ascending", + IncludeItemTypes: "Audio", + Recursive: true, + Fields: "AudioInfo,ParentId", + Limit: 100, + StartIndex: 0, + ImageTypeLimit: 1, + EnableImageTypes: "Primary" + } + }; + pageData.query.ParentId = params.topParentId; + libraryBrowser.loadSavedQueryValues(key, pageData.query); + } + + return pageData; } function getQuery(context) { - return getPageData(context).query + return getPageData(context).query; } function getSavedQueryKey(context) { - return context.savedQueryKey || (context.savedQueryKey = libraryBrowser.getSavedQueryKey("songs")), context.savedQueryKey + if (!context.savedQueryKey) { + context.savedQueryKey = libraryBrowser.getSavedQueryKey("songs"); + } + + return context.savedQueryKey; } function reloadItems(page) { loading.show(); isLoading = true; var query = getQuery(page); - ApiClient.getItems(Dashboard.getCurrentUserId(), query).then(function(result) { + ApiClient.getItems(Dashboard.getCurrentUserId(), query).then(function (result) { function onNextPageClick() { - if (isLoading) return; - query.StartIndex += query.Limit, reloadItems(tabContent) + if (isLoading) { + return; + } + + query.StartIndex += query.Limit; + reloadItems(tabContent); } function onPreviousPageClick() { - if (isLoading) return; - query.StartIndex -= query.Limit, reloadItems(tabContent) + if (isLoading) { + return; + } + + query.StartIndex -= query.Limit; + reloadItems(tabContent); } + window.scrollTo(0, 0); - var i, length, pagingHtml = libraryBrowser.getQueryPagingHtml({ - startIndex: query.StartIndex, - limit: query.Limit, - totalRecordCount: result.TotalRecordCount, - showLimit: !1, - updatePageSizeSetting: !1, - addLayoutButton: !1, - sortButton: !1, - filterButton: !1 - }), - html = listView.getListViewHtml({ - items: result.Items, - action: "playallfromhere", - smallIcon: !0, - artist: !0, - addToListButton: !0 - }), - elems = tabContent.querySelectorAll(".paging"); - for (i = 0, length = elems.length; i < length; i++) elems[i].innerHTML = pagingHtml; - for (elems = tabContent.querySelectorAll(".btnNextPage"), i = 0, length = elems.length; i < length; i++) elems[i].addEventListener("click", onNextPageClick); - for (elems = tabContent.querySelectorAll(".btnPreviousPage"), i = 0, length = elems.length; i < length; i++) elems[i].addEventListener("click", onPreviousPageClick); + var i; + var length; + var pagingHtml = libraryBrowser.getQueryPagingHtml({ + startIndex: query.StartIndex, + limit: query.Limit, + totalRecordCount: result.TotalRecordCount, + showLimit: false, + updatePageSizeSetting: false, + addLayoutButton: false, + sortButton: false, + filterButton: false + }); + var html = listView.getListViewHtml({ + items: result.Items, + action: "playallfromhere", + smallIcon: true, + artist: true, + addToListButton: true + }); + var elems = tabContent.querySelectorAll(".paging"); + + for (i = 0, length = elems.length; i < length; i++) { + elems[i].innerHTML = pagingHtml; + } + + elems = tabContent.querySelectorAll(".btnNextPage"); + for (i = 0, length = elems.length; i < length; i++) { + elems[i].addEventListener("click", onNextPageClick); + } + + elems = tabContent.querySelectorAll(".btnPreviousPage"); + for (i = 0, length = elems.length; i < length; i++) { + elems[i].addEventListener("click", onPreviousPageClick); + } + var itemsContainer = tabContent.querySelector(".itemsContainer"); itemsContainer.innerHTML = html; imageLoader.lazyChildren(itemsContainer); libraryBrowser.saveQueryValues(getSavedQueryKey(page), query); loading.hide(); isLoading = false; - }) + }); } - var self = this, - data = {}, - isLoading = false; - self.showFilterMenu = function() { - require(["components/filterdialog/filterdialog"], function(filterDialogFactory) { - var filterDialog = new filterDialogFactory({ - query: getQuery(tabContent), - mode: "songs", - serverId: ApiClient.serverId() - }); - events.on(filterDialog, "filterchange", function() { - getQuery(tabContent).StartIndex = 0, reloadItems(tabContent) - }), filterDialog.show() - }) - }, self.getCurrentViewStyle = function() { - return getPageData(tabContent).view - }, - function(tabContent) { - tabContent.querySelector(".btnFilter").addEventListener("click", function() { - self.showFilterMenu() - }), tabContent.querySelector(".btnSort").addEventListener("click", function(e) { - libraryBrowser.showSortMenu({ - items: [{ - name: Globalize.translate("OptionTrackName"), - id: "Name" - }, { - name: Globalize.translate("OptionAlbum"), - id: "Album,SortName" - }, { - name: Globalize.translate("OptionAlbumArtist"), - id: "AlbumArtist,Album,SortName" - }, { - name: Globalize.translate("OptionArtist"), - id: "Artist,Album,SortName" - }, { - name: Globalize.translate("OptionDateAdded"), - id: "DateCreated,SortName" - }, { - name: Globalize.translate("OptionDatePlayed"), - id: "DatePlayed,SortName" - }, { - name: Globalize.translate("OptionPlayCount"), - id: "PlayCount,SortName" - }, { - name: Globalize.translate("OptionReleaseDate"), - id: "PremiereDate,AlbumArtist,Album,SortName" - }, { - name: Globalize.translate("OptionRuntime"), - id: "Runtime,AlbumArtist,Album,SortName" - }], - callback: function() { - getQuery(tabContent).StartIndex = 0, reloadItems(tabContent) - }, - query: getQuery(tabContent), - button: e.target - }) - }) - }(tabContent), self.renderTab = function() { - reloadItems(tabContent) - }, self.destroy = function() {} - } + + var self = this; + var data = {}; + var isLoading = false; + + self.showFilterMenu = function () { + require(["components/filterdialog/filterdialog"], function (filterDialogFactory) { + var filterDialog = new filterDialogFactory({ + query: getQuery(tabContent), + mode: "songs", + serverId: ApiClient.serverId() + }); + events.on(filterDialog, "filterchange", function () { + getQuery(tabContent).StartIndex = 0; + reloadItems(tabContent); + }); + filterDialog.show(); + }); + }; + + self.getCurrentViewStyle = function () { + return getPageData(tabContent).view; + }; + + function initPage(tabContent) { + tabContent.querySelector(".btnFilter").addEventListener("click", function () { + self.showFilterMenu(); + }); + tabContent.querySelector(".btnSort").addEventListener("click", function (e) { + libraryBrowser.showSortMenu({ + items: [{ + name: Globalize.translate("OptionTrackName"), + id: "Name" + }, { + name: Globalize.translate("OptionAlbum"), + id: "Album,SortName" + }, { + name: Globalize.translate("OptionAlbumArtist"), + id: "AlbumArtist,Album,SortName" + }, { + name: Globalize.translate("OptionArtist"), + id: "Artist,Album,SortName" + }, { + name: Globalize.translate("OptionDateAdded"), + id: "DateCreated,SortName" + }, { + name: Globalize.translate("OptionDatePlayed"), + id: "DatePlayed,SortName" + }, { + name: Globalize.translate("OptionPlayCount"), + id: "PlayCount,SortName" + }, { + name: Globalize.translate("OptionReleaseDate"), + id: "PremiereDate,AlbumArtist,Album,SortName" + }, { + name: Globalize.translate("OptionRuntime"), + id: "Runtime,AlbumArtist,Album,SortName" + }], + callback: function () { + getQuery(tabContent).StartIndex = 0; + reloadItems(tabContent); + }, + query: getQuery(tabContent), + button: e.target + }); + }); + } + + initPage(tabContent); + + self.renderTab = function () { + reloadItems(tabContent); + }; + + self.destroy = function () {}; + }; }); diff --git a/src/controllers/notificationsetting.js b/src/controllers/notificationsetting.js index a9333ba5a3..70e6adaf61 100644 --- a/src/controllers/notificationsetting.js +++ b/src/controllers/notificationsetting.js @@ -1,85 +1,122 @@ -define(["jQuery", "emby-checkbox", "fnchecked"], function($) { +define(["jQuery", "emby-checkbox", "fnchecked"], function ($) { "use strict"; function fillItems(elem, items, cssClass, idPrefix, currentList, isEnabledList) { var html = '
'; - html += items.map(function(u) { - var isChecked = isEnabledList ? -1 != currentList.indexOf(u.Id) : -1 == currentList.indexOf(u.Id), - checkedHtml = isChecked ? ' checked="checked"' : ""; - return '" - }).join(""), html += "
", elem.html(html).trigger("create") + html += items.map(function (u) { + var isChecked = isEnabledList ? currentList.indexOf(u.Id) != -1 : currentList.indexOf(u.Id) == -1; + var checkedHtml = isChecked ? ' checked="checked"' : ""; + return '"; + }).join(""); + html += "
"; + elem.html(html).trigger("create"); } function reload(page) { - var type = getParameterByName("type"), - promise1 = ApiClient.getUsers(), - promise2 = ApiClient.getNamedConfiguration(notificationsConfigurationKey), - promise3 = ApiClient.getJSON(ApiClient.getUrl("Notifications/Types")), - promise4 = ApiClient.getJSON(ApiClient.getUrl("Notifications/Services")); - Promise.all([promise1, promise2, promise3, promise4]).then(function(responses) { - var users = responses[0], - notificationOptions = responses[1], - types = responses[2], - services = responses[3], - notificationConfig = notificationOptions.Options.filter(function(n) { - return n.Type == type - })[0], - typeInfo = types.filter(function(n) { - return n.Type == type - })[0] || {}; - typeInfo.IsBasedOnUserEvent ? $(".monitorUsers", page).show() : $(".monitorUsers", page).hide(), $(".notificationType", page).html(typeInfo.Name || "Unknown Notification"), notificationConfig || (notificationConfig = { - DisabledMonitorUsers: [], - SendToUsers: [], - DisabledServices: [], - SendToUserMode: "Admins" - }), fillItems($(".monitorUsersList", page), users, "chkMonitor", "chkMonitor", notificationConfig.DisabledMonitorUsers), fillItems($(".sendToUsersList", page), users, "chkSendTo", "chkSendTo", notificationConfig.SendToUsers, !0), fillItems($(".servicesList", page), services, "chkService", "chkService", notificationConfig.DisabledServices), $("#chkEnabled", page).checked(notificationConfig.Enabled || !1), $("#selectUsers", page).val(notificationConfig.SendToUserMode).trigger("change") - }) + var type = getParameterByName("type"); + var promise1 = ApiClient.getUsers(); + var promise2 = ApiClient.getNamedConfiguration(notificationsConfigurationKey); + var promise3 = ApiClient.getJSON(ApiClient.getUrl("Notifications/Types")); + var promise4 = ApiClient.getJSON(ApiClient.getUrl("Notifications/Services")); + Promise.all([promise1, promise2, promise3, promise4]).then(function (responses) { + var users = responses[0]; + var notificationOptions = responses[1]; + var types = responses[2]; + var services = responses[3]; + var notificationConfig = notificationOptions.Options.filter(function (n) { + return n.Type == type; + })[0]; + var typeInfo = types.filter(function (n) { + return n.Type == type; + })[0] || {}; + + if (typeInfo.IsBasedOnUserEvent) { + $(".monitorUsers", page).show(); + } else { + $(".monitorUsers", page).hide(); + } + + $(".notificationType", page).html(typeInfo.Name || "Unknown Notification"); + + if (!notificationConfig) { + notificationConfig = { + DisabledMonitorUsers: [], + SendToUsers: [], + DisabledServices: [], + SendToUserMode: "Admins" + }; + } + + fillItems($(".monitorUsersList", page), users, "chkMonitor", "chkMonitor", notificationConfig.DisabledMonitorUsers); + fillItems($(".sendToUsersList", page), users, "chkSendTo", "chkSendTo", notificationConfig.SendToUsers, true); + fillItems($(".servicesList", page), services, "chkService", "chkService", notificationConfig.DisabledServices); + $("#chkEnabled", page).checked(notificationConfig.Enabled || false); + $("#selectUsers", page).val(notificationConfig.SendToUserMode).trigger("change"); + }); } function save(page) { - var type = getParameterByName("type"), - promise1 = ApiClient.getNamedConfiguration(notificationsConfigurationKey), - promise2 = ApiClient.getJSON(ApiClient.getUrl("Notifications/Types")); - Promise.all([promise1, promise2]).then(function(responses) { - var notificationOptions = responses[0], - types = responses[1], - notificationConfig = notificationOptions.Options.filter(function(n) { - return n.Type == type - })[0]; - notificationConfig || (notificationConfig = { - Type: type - }, notificationOptions.Options.push(notificationConfig)); - types.filter(function(n) { - return n.Type == type + var type = getParameterByName("type"); + var promise1 = ApiClient.getNamedConfiguration(notificationsConfigurationKey); + var promise2 = ApiClient.getJSON(ApiClient.getUrl("Notifications/Types")); + Promise.all([promise1, promise2]).then(function (responses) { + var notificationOptions = responses[0]; + var types = responses[1]; + var notificationConfig = notificationOptions.Options.filter(function (n) { + return n.Type == type; })[0]; - notificationConfig.Enabled = $("#chkEnabled", page).checked(), notificationConfig.SendToUserMode = $("#selectUsers", page).val(), notificationConfig.DisabledMonitorUsers = $(".chkMonitor", page).get().filter(function(c) { - return !c.checked - }).map(function(c) { - return c.getAttribute("data-itemid") - }), notificationConfig.SendToUsers = $(".chkSendTo", page).get().filter(function(c) { - return c.checked - }).map(function(c) { - return c.getAttribute("data-itemid") - }), notificationConfig.DisabledServices = $(".chkService", page).get().filter(function(c) { - return !c.checked - }).map(function(c) { - return c.getAttribute("data-itemid") - }), ApiClient.updateNamedConfiguration(notificationsConfigurationKey, notificationOptions).then(function(r) { - Dashboard.processServerConfigurationUpdateResult(), Dashboard.navigate("notificationsettings.html") - }) - }) + + if (!notificationConfig) { + notificationConfig = { + Type: type + }; + notificationOptions.Options.push(notificationConfig); + } + + types.filter(function (n) { + return n.Type == type; + })[0]; + notificationConfig.Enabled = $("#chkEnabled", page).checked(); + notificationConfig.SendToUserMode = $("#selectUsers", page).val(); + notificationConfig.DisabledMonitorUsers = $(".chkMonitor", page).get().filter(function (c) { + return !c.checked; + }).map(function (c) { + return c.getAttribute("data-itemid"); + }); + notificationConfig.SendToUsers = $(".chkSendTo", page).get().filter(function (c) { + return c.checked; + }).map(function (c) { + return c.getAttribute("data-itemid"); + }); + notificationConfig.DisabledServices = $(".chkService", page).get().filter(function (c) { + return !c.checked; + }).map(function (c) { + return c.getAttribute("data-itemid"); + }); + ApiClient.updateNamedConfiguration(notificationsConfigurationKey, notificationOptions).then(function (r) { + Dashboard.processServerConfigurationUpdateResult(); + Dashboard.navigate("notificationsettings.html"); + }); + }); } function onSubmit() { - return save($(this).parents(".page")), !1 + save($(this).parents(".page")); + return false; } + var notificationsConfigurationKey = "notifications"; - $(document).on("pageinit", "#notificationSettingPage", function() { + $(document).on("pageinit", "#notificationSettingPage", function () { var page = this; - $("#selectUsers", page).on("change", function() { - "Custom" == this.value ? $(".selectCustomUsers", page).show() : $(".selectCustomUsers", page).hide() - }), $(".notificationSettingForm").off("submit", onSubmit).on("submit", onSubmit) - }).on("pageshow", "#notificationSettingPage", function() { - reload(this) - }) -}); \ No newline at end of file + $("#selectUsers", page).on("change", function () { + if ("Custom" == this.value) { + $(".selectCustomUsers", page).show(); + } else { + $(".selectCustomUsers", page).hide(); + } + }); + $(".notificationSettingForm").off("submit", onSubmit).on("submit", onSubmit); + }).on("pageshow", "#notificationSettingPage", function () { + reload(this); + }); +}); diff --git a/src/controllers/nowplayingpage.js b/src/controllers/nowplayingpage.js index 7f1b9b3f11..6fcdb2a79c 100644 --- a/src/controllers/nowplayingpage.js +++ b/src/controllers/nowplayingpage.js @@ -1,11 +1,22 @@ -define(["components/remotecontrol/remotecontrol", "libraryMenu", "emby-button"], function(remotecontrolFactory, libraryMenu) { +define(["components/remotecontrol/remotecontrol", "libraryMenu", "emby-button"], function (remotecontrolFactory, libraryMenu) { "use strict"; - return function(view, params) { - var remoteControl = new remotecontrolFactory; - remoteControl.init(view, view.querySelector(".remoteControlContent")), view.addEventListener("viewshow", function(e) { - libraryMenu.setTransparentMenu(!0), remoteControl && remoteControl.onShow() - }), view.addEventListener("viewbeforehide", function(e) { - libraryMenu.setTransparentMenu(!1), remoteControl && remoteControl.destroy() - }) - } -}); \ No newline at end of file + + return function (view, params) { + var remoteControl = new remotecontrolFactory(); + remoteControl.init(view, view.querySelector(".remoteControlContent")); + view.addEventListener("viewshow", function (e) { + libraryMenu.setTransparentMenu(true); + + if (remoteControl) { + remoteControl.onShow(); + } + }); + view.addEventListener("viewbeforehide", function (e) { + libraryMenu.setTransparentMenu(false); + + if (remoteControl) { + remoteControl.destroy(); + } + }); + }; +}); diff --git a/src/controllers/playbackconfiguration.js b/src/controllers/playbackconfiguration.js index 35a780949d..76c704f7eb 100644 --- a/src/controllers/playbackconfiguration.js +++ b/src/controllers/playbackconfiguration.js @@ -1,16 +1,25 @@ -define(["jQuery", "loading", "libraryMenu"], function($, loading, libraryMenu) { +define(["jQuery", "loading", "libraryMenu"], function ($, loading, libraryMenu) { "use strict"; function loadPage(page, config) { - $("#txtMinResumePct", page).val(config.MinResumePct), $("#txtMaxResumePct", page).val(config.MaxResumePct), $("#txtMinResumeDuration", page).val(config.MinResumeDurationSeconds), loading.hide() + $("#txtMinResumePct", page).val(config.MinResumePct); + $("#txtMaxResumePct", page).val(config.MaxResumePct); + $("#txtMinResumeDuration", page).val(config.MinResumeDurationSeconds); + loading.hide(); } function onSubmit() { loading.show(); var form = this; - return ApiClient.getServerConfiguration().then(function(config) { - config.MinResumePct = $("#txtMinResumePct", form).val(), config.MaxResumePct = $("#txtMaxResumePct", form).val(), config.MinResumeDurationSeconds = $("#txtMinResumeDuration", form).val(), ApiClient.updateServerConfiguration(config).then(Dashboard.processServerConfigurationUpdateResult) - }), !1 + ApiClient.getServerConfiguration().then(function (config) { + config.MinResumePct = $('#txtMinResumePct', form).val(); + config.MaxResumePct = $('#txtMaxResumePct', form).val(); + config.MinResumeDurationSeconds = $('#txtMinResumeDuration', form).val(); + + ApiClient.updateServerConfiguration(config).then(Dashboard.processServerConfigurationUpdateResult); + }); + + return false; } function getTabs() { @@ -23,17 +32,17 @@ define(["jQuery", "loading", "libraryMenu"], function($, loading, libraryMenu) { }, { href: "streamingsettings.html", name: Globalize.translate("TabStreaming") - }] + }]; } - $(document).on("pageinit", "#playbackConfigurationPage", function() { + $(document).on("pageinit", "#playbackConfigurationPage", function () { $(".playbackConfigurationForm").off("submit", onSubmit).on("submit", onSubmit) - }).on("pageshow", "#playbackConfigurationPage", function() { + }).on("pageshow", "#playbackConfigurationPage", function () { loading.show(); libraryMenu.setTabs("playback", 1, getTabs); var page = this; - ApiClient.getServerConfiguration().then(function(config) { - loadPage(page, config) - }) - }) -}); \ No newline at end of file + ApiClient.getServerConfiguration().then(function (config) { + loadPage(page, config); + }); + }); +}); diff --git a/src/controllers/scheduledtaskpage.js b/src/controllers/scheduledtaskpage.js index 32838c6de3..7dae03cb3d 100644 --- a/src/controllers/scheduledtaskpage.js +++ b/src/controllers/scheduledtaskpage.js @@ -1,111 +1,237 @@ -define(["jQuery", "loading", "datetime", "dom", "globalize", "emby-input", "emby-button", "emby-select"], function($, loading, datetime, dom, globalize) { +define(["jQuery", "loading", "datetime", "dom", "globalize", "emby-input", "emby-button", "emby-select"], function ($, loading, datetime, dom, globalize) { "use strict"; function fillTimeOfDay(select) { - for (var options = [], i = 0; i < 864e5; i += 9e5) options.push({ - name: ScheduledTaskPage.getDisplayTime(1e4 * i), - value: 1e4 * i - }); - select.innerHTML = options.map(function(o) { - return '" - }).join("") + + var options = []; + + for (var i = 0; i < 86400000; i += 900000) { + options.push({ + name: ScheduledTaskPage.getDisplayTime(i * 10000), + value: i * 10000 + }); + } + + select.innerHTML = options.map(function (o) { + return ''; + }).join(""); } - Array.prototype.remove = function(from, to) { + + Array.prototype.remove = function (from, to) { var rest = this.slice((to || from) + 1 || this.length); - return this.length = from < 0 ? this.length + from : from, this.push.apply(this, rest) + this.length = from < 0 ? this.length + from : from; + return this.push.apply(this, rest); }; + var ScheduledTaskPage = { - refreshScheduledTask: function(view) { + refreshScheduledTask: function (view) { loading.show(); var id = getParameterByName("id"); - ApiClient.getScheduledTask(id).then(function(task) { - ScheduledTaskPage.loadScheduledTask(view, task) - }) + ApiClient.getScheduledTask(id).then(function (task) { + ScheduledTaskPage.loadScheduledTask(view, task); + }); }, - loadScheduledTask: function(view, task) { - $(".taskName", view).html(task.Name), $("#pTaskDescription", view).html(task.Description), require(["listViewStyle"], function() { - ScheduledTaskPage.loadTaskTriggers(view, task) - }), loading.hide() + loadScheduledTask: function (view, task) { + $(".taskName", view).html(task.Name); + $("#pTaskDescription", view).html(task.Description); + + require(["listViewStyle"], function () { + ScheduledTaskPage.loadTaskTriggers(view, task); + }); + + loading.hide(); }, - loadTaskTriggers: function(context, task) { + loadTaskTriggers: function (context, task) { var html = ""; html += '
'; + for (var i = 0, length = task.Triggers.length; i < length; i++) { var trigger = task.Triggers[i]; - if (html += '
', html += 'schedule', trigger.MaxRuntimeTicks ? html += '
' : html += '
', html += "
" + ScheduledTaskPage.getTriggerFriendlyName(trigger) + "
", trigger.MaxRuntimeTicks) { + + html += '
'; + html += 'schedule'; + if (trigger.MaxRuntimeMs) { + html += '
'; + } else { + html += '
'; + } + html += "
" + ScheduledTaskPage.getTriggerFriendlyName(trigger) + "
"; + if (trigger.MaxRuntimeMs) { html += '
'; var hours = trigger.MaxRuntimeTicks / 36e9; - html += 1 == hours ? globalize.translate("ValueTimeLimitSingleHour") : globalize.translate("ValueTimeLimitMultiHour", hours), html += "
" + if (hours == 1) { + html += globalize.translate("ValueTimeLimitSingleHour"); + } else { + html += globalize.translate("ValueTimeLimitMultiHour", hours); + } + html += "
"; } - html += "
", html += '', html += "
" + + html += "
"; + html += ''; + html += "
"; } - html += "
", context.querySelector(".taskTriggers").innerHTML = html + + html += "
"; + context.querySelector(".taskTriggers").innerHTML = html; }, - getTriggerFriendlyName: function(trigger) { - if ("DailyTrigger" == trigger.Type) return "Daily at " + ScheduledTaskPage.getDisplayTime(trigger.TimeOfDayTicks); - if ("WeeklyTrigger" == trigger.Type) return trigger.DayOfWeek + "s at " + ScheduledTaskPage.getDisplayTime(trigger.TimeOfDayTicks); - if ("SystemEventTrigger" == trigger.Type && "WakeFromSleep" == trigger.SystemEvent) return "On wake from sleep"; - if ("IntervalTrigger" == trigger.Type) { + getTriggerFriendlyName: function (trigger) { + if ("DailyTrigger" == trigger.Type) { + return "Daily at " + ScheduledTaskPage.getDisplayTime(trigger.TimeOfDayTicks); + } + + if ("WeeklyTrigger" == trigger.Type) { + return trigger.DayOfWeek + "s at " + ScheduledTaskPage.getDisplayTime(trigger.TimeOfDayTicks); + } + + if ("SystemEventTrigger" == trigger.Type && "WakeFromSleep" == trigger.SystemEvent) { + return "On wake from sleep"; + } + + if (trigger.Type == "IntervalTrigger") { + var hours = trigger.IntervalTicks / 36e9; - return .25 == hours ? "Every 15 minutes" : .5 == hours ? "Every 30 minutes" : .75 == hours ? "Every 45 minutes" : 1 == hours ? "Every hour" : "Every " + hours + " hours" + + if (hours == .25) { + return "Every 15 minutes"; + } + if (hours == .5) { + return "Every 30 minutes"; + } + if (hours == .75) { + return "Every 45 minutes"; + } + if (hours == 1) { + return "Every hour"; + } + + return "Every " + hours + " hours"; } - return "StartupTrigger" == trigger.Type ? "On application startup" : trigger.Type + + if (trigger.Type == "StartupTrigger") { + return "On application startup"; + } + + return trigger.Type; }, - getDisplayTime: function(ticks) { - var ms = ticks / 1e4, - now = new Date; - return now.setHours(0, 0, 0, 0), now.setTime(now.getTime() + ms), datetime.getDisplayTime(now) + getDisplayTime: function (ticks) { + var ms = ticks / 1e4; + var now = new Date(); + now.setHours(0, 0, 0, 0); + now.setTime(now.getTime() + ms); + return datetime.getDisplayTime(now); }, - showAddTriggerPopup: function(view) { - $("#selectTriggerType", view).val("DailyTrigger"), view.querySelector("#selectTriggerType").dispatchEvent(new CustomEvent("change", {})), $("#popupAddTrigger", view).removeClass("hide") + showAddTriggerPopup: function (view) { + $("#selectTriggerType", view).val("DailyTrigger"); + view.querySelector("#selectTriggerType").dispatchEvent(new CustomEvent("change", {})); + $("#popupAddTrigger", view).removeClass("hide"); }, - confirmDeleteTrigger: function(view, index) { - require(["confirm"], function(confirm) { - confirm(globalize.translate("MessageDeleteTaskTrigger"), globalize.translate("HeaderDeleteTaskTrigger")).then(function() { - ScheduledTaskPage.deleteTrigger(view, index) - }) - }) + confirmDeleteTrigger: function (view, index) { + require(["confirm"], function (confirm) { + confirm(globalize.translate("MessageDeleteTaskTrigger"), globalize.translate("HeaderDeleteTaskTrigger")).then(function () { + ScheduledTaskPage.deleteTrigger(view, index); + }); + }); }, - deleteTrigger: function(view, index) { + deleteTrigger: function (view, index) { loading.show(); var id = getParameterByName("id"); - ApiClient.getScheduledTask(id).then(function(task) { - task.Triggers.remove(index), ApiClient.updateScheduledTaskTriggers(task.Id, task.Triggers).then(function() { - ScheduledTaskPage.refreshScheduledTask(view) - }) - }) + ApiClient.getScheduledTask(id).then(function (task) { + task.Triggers.remove(index); + ApiClient.updateScheduledTaskTriggers(task.Id, task.Triggers).then(function () { + ScheduledTaskPage.refreshScheduledTask(view); + }); + }); }, - refreshTriggerFields: function(page, triggerType) { - "DailyTrigger" == triggerType ? ($("#fldTimeOfDay", page).show(), $("#fldDayOfWeek", page).hide(), $("#fldSelectSystemEvent", page).hide(), $("#fldSelectInterval", page).hide(), $("#selectTimeOfDay", page).attr("required", "required")) : "WeeklyTrigger" == triggerType ? ($("#fldTimeOfDay", page).show(), $("#fldDayOfWeek", page).show(), $("#fldSelectSystemEvent", page).hide(), $("#fldSelectInterval", page).hide(), $("#selectTimeOfDay", page).attr("required", "required")) : "SystemEventTrigger" == triggerType ? ($("#fldTimeOfDay", page).hide(), $("#fldDayOfWeek", page).hide(), $("#fldSelectSystemEvent", page).show(), $("#fldSelectInterval", page).hide(), $("#selectTimeOfDay", page).removeAttr("required")) : "IntervalTrigger" == triggerType ? ($("#fldTimeOfDay", page).hide(), $("#fldDayOfWeek", page).hide(), $("#fldSelectSystemEvent", page).hide(), $("#fldSelectInterval", page).show(), $("#selectTimeOfDay", page).removeAttr("required")) : "StartupTrigger" == triggerType && ($("#fldTimeOfDay", page).hide(), $("#fldDayOfWeek", page).hide(), $("#fldSelectSystemEvent", page).hide(), $("#fldSelectInterval", page).hide(), $("#selectTimeOfDay", page).removeAttr("required")) + refreshTriggerFields: function (page, triggerType) { + if (triggerType == "DailyTrigger") { + $("#fldTimeOfDay", page).show(); + $("#fldDayOfWeek", page).hide(); + $("#fldSelectSystemEvent", page).hide(); + $("#fldSelectInterval", page).hide(); + $("#selectTimeOfDay", page).attr("required", "required"); + } else if (triggerType == "WeeklyTrigger") { + $("#fldTimeOfDay", page).show(); + $("#fldDayOfWeek", page).show(); + $("#fldSelectSystemEvent", page).hide(); + $("#fldSelectInterval", page).hide(); + $("#selectTimeOfDay", page).attr("required", "required"); + } else if (triggerType == "SystemEventTrigger") { + $("#fldTimeOfDay", page).hide(); + $("#fldDayOfWeek", page).hide(); + $("#fldSelectSystemEvent", page).show(); + $("#fldSelectInterval", page).hide(); + $("#selectTimeOfDay", page).removeAttr("required"); + } else if (triggerType == "IntervalTrigger") { + $("#fldTimeOfDay", page).hide(); + $("#fldDayOfWeek", page).hide(); + $("#fldSelectSystemEvent", page).hide(); + $("#fldSelectInterval", page).show(); + $("#selectTimeOfDay", page).removeAttr("required"); + } else if (triggerType == "StartupTrigger") { + $("#fldTimeOfDay", page).hide(); + $("#fldDayOfWeek", page).hide(); + $("#fldSelectSystemEvent", page).hide(); + $("#fldSelectInterval", page).hide(); + $("#selectTimeOfDay", page).removeAttr("required"); + } }, - getTriggerToAdd: function(page) { + getTriggerToAdd: function (page) { var trigger = { Type: $("#selectTriggerType", page).val() }; - "DailyTrigger" == trigger.Type ? trigger.TimeOfDayTicks = $("#selectTimeOfDay", page).val() : "WeeklyTrigger" == trigger.Type ? (trigger.DayOfWeek = $("#selectDayOfWeek", page).val(), trigger.TimeOfDayTicks = $("#selectTimeOfDay", page).val()) : "SystemEventTrigger" == trigger.Type ? trigger.SystemEvent = $("#selectSystemEvent", page).val() : "IntervalTrigger" == trigger.Type && (trigger.IntervalTicks = $("#selectInterval", page).val()); + + if (trigger.Type == "DailyTrigger") { + trigger.TimeOfDayTicks = $("#selectTimeOfDay", page).val(); + } else if (trigger.Type == "WeeklyTrigger") { + trigger.DayOfWeek = $("#selectDayOfWeek", page).val(); + trigger.TimeOfDayTicks = $("#selectTimeOfDay", page).val(); + } else if (trigger.Type == "SystemEventTrigger") { + trigger.SystemEvent = $("#selectSystemEvent", page).val(); + } else if (trigger.Type == "IntervalTrigger") { + trigger.IntervalTicks = $("#selectInterval", page).val(); + } + var timeLimit = $("#txtTimeLimit", page).val() || "0"; - return timeLimit = 36e5 * parseFloat(timeLimit), trigger.MaxRuntimeMs = timeLimit || null, trigger + timeLimit = parseFloat(timeLimit) * 3600000; + + trigger.MaxRuntimeMs = timeLimit || null; + + return trigger; } }; - return function(view, params) { + return function (view, params) { function onSubmit(e) { loading.show(); var id = getParameterByName("id"); - ApiClient.getScheduledTask(id).then(function(task) { - task.Triggers.push(ScheduledTaskPage.getTriggerToAdd(view)), ApiClient.updateScheduledTaskTriggers(task.Id, task.Triggers).then(function() { - $("#popupAddTrigger").addClass("hide"), ScheduledTaskPage.refreshScheduledTask(view) - }) - }), e.preventDefault() + ApiClient.getScheduledTask(id).then(function (task) { + task.Triggers.push(ScheduledTaskPage.getTriggerToAdd(view)); + ApiClient.updateScheduledTaskTriggers(task.Id, task.Triggers).then(function () { + $("#popupAddTrigger").addClass("hide"); + ScheduledTaskPage.refreshScheduledTask(view); + }); + }); + e.preventDefault(); } - view.querySelector(".addTriggerForm").addEventListener("submit", onSubmit), fillTimeOfDay(view.querySelector("#selectTimeOfDay")), $(view.querySelector("#popupAddTrigger").parentNode).trigger("create"), view.querySelector(".selectTriggerType").addEventListener("change", function() { - ScheduledTaskPage.refreshTriggerFields(view, this.value) - }), view.querySelector(".btnAddTrigger").addEventListener("click", function() { - ScheduledTaskPage.showAddTriggerPopup(view) - }), view.addEventListener("click", function(e) { + + view.querySelector(".addTriggerForm").addEventListener("submit", onSubmit); + fillTimeOfDay(view.querySelector("#selectTimeOfDay")); + $(view.querySelector("#popupAddTrigger").parentNode).trigger("create"); + view.querySelector(".selectTriggerType").addEventListener("change", function () { + ScheduledTaskPage.refreshTriggerFields(view, this.value); + }); + view.querySelector(".btnAddTrigger").addEventListener("click", function () { + ScheduledTaskPage.showAddTriggerPopup(view); + }); + view.addEventListener("click", function (e) { var btnDeleteTrigger = dom.parentWithClass(e.target, "btnDeleteTrigger"); - btnDeleteTrigger && ScheduledTaskPage.confirmDeleteTrigger(view, parseInt(btnDeleteTrigger.getAttribute("data-index"))) - }), view.addEventListener("viewshow", function() { - ScheduledTaskPage.refreshScheduledTask(view) - }) - } -}); \ No newline at end of file + + if (btnDeleteTrigger) { + ScheduledTaskPage.confirmDeleteTrigger(view, parseInt(btnDeleteTrigger.getAttribute("data-index"))); + } + }); + view.addEventListener("viewshow", function () { + ScheduledTaskPage.refreshScheduledTask(view); + }); + }; +}); diff --git a/src/controllers/searchpage.js b/src/controllers/searchpage.js index b188a8b318..b260ef5751 100644 --- a/src/controllers/searchpage.js +++ b/src/controllers/searchpage.js @@ -1,21 +1,36 @@ -define(["focusManager", "searchFields", "searchResults", "events"], function(focusManager, SearchFields, SearchResults, events) { +define(["focusManager", "searchFields", "searchResults", "events"], function (focusManager, SearchFields, SearchResults, events) { "use strict"; - return function(view, params) { + + return function (view, params) { function onSearch(e, value) { - self.searchResults.search(value) + self.searchResults.search(value); } + var self = this; - view.addEventListener("viewshow", function() { - self.searchFields || (self.searchFields = new SearchFields({ - element: view.querySelector(".searchFields") - }), self.searchResults = new SearchResults({ - element: view.querySelector(".searchResults"), - serverId: params.serverId || ApiClient.serverId(), - parentId: params.parentId, - collectionType: params.collectionType - }), events.on(self.searchFields, "search", onSearch)) - }), view.addEventListener("viewdestroy", function() { - self.searchFields && (self.searchFields.destroy(), self.searchFields = null), self.searchResults && (self.searchResults.destroy(), self.searchResults = null) - }) - } -}); \ No newline at end of file + view.addEventListener("viewshow", function () { + if (!self.searchFields) { + self.searchFields = new SearchFields({ + element: view.querySelector(".searchFields") + }); + self.searchResults = new SearchResults({ + element: view.querySelector(".searchResults"), + serverId: params.serverId || ApiClient.serverId(), + parentId: params.parentId, + collectionType: params.collectionType + }); + events.on(self.searchFields, "search", onSearch); + } + }); + view.addEventListener("viewdestroy", function () { + if (self.searchFields) { + self.searchFields.destroy(); + self.searchFields = null; + } + + if (self.searchResults) { + self.searchResults.destroy(); + self.searchResults = null; + } + }); + }; +}); diff --git a/src/controllers/selectserver.js b/src/controllers/selectserver.js index 385ab69ca2..80ecb13f00 100644 --- a/src/controllers/selectserver.js +++ b/src/controllers/selectserver.js @@ -1,50 +1,56 @@ -define(["loading", "appRouter", "layoutManager", "appSettings", "apphost", "focusManager", "connectionManager", "globalize", "actionsheet", "dom", "material-icons", "flexStyles", "emby-scroller", "emby-itemscontainer", "cardStyle", "emby-button"], function(loading, appRouter, layoutManager, appSettings, appHost, focusManager, connectionManager, globalize, actionSheet, dom) { +define(["loading", "appRouter", "layoutManager", "appSettings", "apphost", "focusManager", "connectionManager", "globalize", "actionsheet", "dom", "material-icons", "flexStyles", "emby-scroller", "emby-itemscontainer", "cardStyle", "emby-button"], function (loading, appRouter, layoutManager, appSettings, appHost, focusManager, connectionManager, globalize, actionSheet, dom) { "use strict"; function renderSelectServerItems(view, servers) { - var items = servers.map(function(server) { - return { - name: server.Name, - showIcon: !0, - icon: "", - cardType: "", - id: server.Id, - server: server - } + var items = servers.map(function (server) { + return { + name: server.Name, + showIcon: true, + icon: "", + cardType: "", + id: server.Id, + server: server + }; }); - var html = items.map(function(item) { - var cardImageContainer; - if (item.showIcon) { - cardImageContainer = '' + item.icon + ""; - } else { - cardImageContainer = '
'; - } - var cardBoxCssClass = "cardBox"; - if (layoutManager.tv) { - cardBoxCssClass += " cardBox-focustransform"; - } - var innerOpening = '
'; - var cardContainer = ''; - cardContainer += '
'; - return cardContainer; + var html = items.map(function (item) { + var cardImageContainer; + + if (item.showIcon) { + cardImageContainer = '' + item.icon + ""; + } else { + cardImageContainer = '
'; + } + + var cardBoxCssClass = "cardBox"; + + if (layoutManager.tv) { + cardBoxCssClass += " cardBox-focustransform"; + } + + var innerOpening = '
'; + var cardContainer = ''; + cardContainer += '
'; + return cardContainer; }).join(""); var itemsContainer = view.querySelector(".servers"); + if (!items.length) { html = '

' + globalize.translate("MessageNoServersAvailable") + "

"; } + itemsContainer.innerHTML = html; loading.hide(); } @@ -73,7 +79,7 @@ define(["loading", "appRouter", "layoutManager", "appSettings", "apphost", "focu } function alertTextWithOptions(options) { - require(["alert"], function(alert) { + require(["alert"], function (alert) { alert(options); }); } @@ -82,38 +88,42 @@ define(["loading", "appRouter", "layoutManager", "appSettings", "apphost", "focu alertText(globalize.translate("MessageUnableToConnectToServer"), globalize.translate("HeaderConnectionFailure")); } - return function(view, params) { + return function (view, params) { function connectToServer(server) { loading.show(); connectionManager.connectToServer(server, { enableAutoLogin: appSettings.enableAutoLogin() - }).then(function(result) { + }).then(function (result) { loading.hide(); var apiClient = result.ApiClient; + switch (result.State) { case "SignedIn": Dashboard.onServerChanged(apiClient.getCurrentUserId(), apiClient.accessToken(), apiClient); Dashboard.navigate("home.html"); break; + case "ServerSignIn": Dashboard.onServerChanged(null, null, apiClient); Dashboard.navigate("login.html?serverid=" + result.Servers[0].Id); break; + case "ServerUpdateNeeded": alertTextWithOptions({ text: globalize.translate("core#ServerUpdateNeeded", "https://github.com/jellyfin/jellyfin"), html: globalize.translate("core#ServerUpdateNeeded", 'https://github.com/jellyfin/jellyfin') }); break; + default: showServerConnectionFailure(); } - }) + }); } function deleteServer(server) { loading.show(); - connectionManager.deleteServer(server.Id).then(function() { + connectionManager.deleteServer(server.Id).then(function () { loading.hide(); loadServers(); }); @@ -132,20 +142,22 @@ define(["loading", "appRouter", "layoutManager", "appSettings", "apphost", "focu actionSheet.show({ items: menuItems, title: server.Name - }).then(function(id) { + }).then(function (id) { switch (id) { case "connect": connectToServer(server); break; + case "delete": deleteServer(server); } - }) + }); } function onServersRetrieved(result) { servers = result; renderSelectServerItems(view, result); + if (layoutManager.tv) { focusManager.autoFocus(view); } @@ -158,25 +170,29 @@ define(["loading", "appRouter", "layoutManager", "appSettings", "apphost", "focu var servers; updatePageStyle(view, params); - - view.addEventListener("viewshow", function(e) { + view.addEventListener("viewshow", function (e) { var isRestored = e.detail.isRestored; appRouter.setTitle(null); - if (!isRestored) loadServers(); + + if (!isRestored) { + loadServers(); + } }); - view.querySelector(".servers").addEventListener("click", function(e) { + view.querySelector(".servers").addEventListener("click", function (e) { var card = dom.parentWithClass(e.target, "card"); + if (card) { var url = card.getAttribute("data-url"); + if (url) { appRouter.show(url); } else { var id = card.getAttribute("data-id"); - onServerClick(servers.filter(function(s) { + onServerClick(servers.filter(function (s) { return s.Id === id; })[0]); } } - }) - } + }); + }; }); diff --git a/src/controllers/serveractivity.js b/src/controllers/serveractivity.js index 2b43215c93..fb3b8112dc 100644 --- a/src/controllers/serveractivity.js +++ b/src/controllers/serveractivity.js @@ -1,14 +1,31 @@ -define(["components/activitylog", "globalize"], function(ActivityLog, globalize) { +define(["components/activitylog", "globalize"], function (ActivityLog, globalize) { "use strict"; - return function(view, params) { + + return function (view, params) { var activityLog; - "false" !== params.useractivity ? (view.querySelector(".activityItems").setAttribute("data-useractivity", "true"), view.querySelector(".sectionTitle").innerHTML = globalize.translate("HeaderActivity")) : (view.querySelector(".activityItems").setAttribute("data-useractivity", "false"), view.querySelector(".sectionTitle").innerHTML = globalize.translate("Alerts")), view.addEventListener("viewshow", function() { - activityLog || (activityLog = new ActivityLog({ - serverId: ApiClient.serverId(), - element: view.querySelector(".activityItems") - })) - }), view.addEventListener("viewdestroy", function() { - activityLog && activityLog.destroy(), activityLog = null - }) - } -}); \ No newline at end of file + + if (params.useractivity !== "false") { + view.querySelector(".activityItems").setAttribute("data-useractivity", "true"); + view.querySelector(".sectionTitle").innerHTML = globalize.translate("HeaderActivity"); + } else { + view.querySelector(".activityItems").setAttribute("data-useractivity", "false"); + view.querySelector(".sectionTitle").innerHTML = globalize.translate("Alerts"); + } + + view.addEventListener("viewshow", function () { + if (!activityLog) { + activityLog = new ActivityLog({ + serverId: ApiClient.serverId(), + element: view.querySelector(".activityItems") + }); + } + }); + view.addEventListener("viewdestroy", function () { + if (activityLog) { + activityLog.destroy(); + } + + activityLog = null; + }); + }; +}); diff --git a/src/controllers/shows/episodes.js b/src/controllers/shows/episodes.js index 1f783631fb..42d9d89f7a 100644 --- a/src/controllers/shows/episodes.js +++ b/src/controllers/shows/episodes.js @@ -1,169 +1,233 @@ -define(["loading", "events", "libraryBrowser", "imageLoader", "listView", "cardBuilder", "emby-itemscontainer"], function(loading, events, libraryBrowser, imageLoader, listView, cardBuilder) { +define(["loading", "events", "libraryBrowser", "imageLoader", "listView", "cardBuilder", "emby-itemscontainer"], function (loading, events, libraryBrowser, imageLoader, listView, cardBuilder) { "use strict"; - return function(view, params, tabContent) { + + return function (view, params, tabContent) { function getPageData(context) { - var key = getSavedQueryKey(context), - pageData = data[key]; - return pageData || (pageData = data[key] = { - query: { - SortBy: "SeriesSortName,SortName", - SortOrder: "Ascending", - IncludeItemTypes: "Episode", - Recursive: !0, - Fields: "PrimaryImageAspectRatio,MediaSourceCount,UserData", - IsMissing: !1, - ImageTypeLimit: 1, - EnableImageTypes: "Primary,Backdrop,Thumb", - StartIndex: 0, - Limit: pageSize - }, - view: libraryBrowser.getSavedView(key) || "Poster" - }, pageData.query.ParentId = params.topParentId, libraryBrowser.loadSavedQueryValues(key, pageData.query)), pageData + var key = getSavedQueryKey(context); + var pageData = data[key]; + + if (!pageData) { + pageData = data[key] = { + query: { + SortBy: "SeriesSortName,SortName", + SortOrder: "Ascending", + IncludeItemTypes: "Episode", + Recursive: true, + Fields: "PrimaryImageAspectRatio,MediaSourceCount,UserData", + IsMissing: false, + ImageTypeLimit: 1, + EnableImageTypes: "Primary,Backdrop,Thumb", + StartIndex: 0, + Limit: pageSize + }, + view: libraryBrowser.getSavedView(key) || "Poster" + }; + pageData.query.ParentId = params.topParentId; + libraryBrowser.loadSavedQueryValues(key, pageData.query); + } + + return pageData; } function getQuery(context) { - return getPageData(context).query + return getPageData(context).query; } function getSavedQueryKey(context) { - return context.savedQueryKey || (context.savedQueryKey = libraryBrowser.getSavedQueryKey("episodes")), context.savedQueryKey + if (!context.savedQueryKey) { + context.savedQueryKey = libraryBrowser.getSavedQueryKey("episodes"); + } + + return context.savedQueryKey; } function onViewStyleChange() { - var viewStyle = self.getCurrentViewStyle(), - itemsContainer = tabContent.querySelector(".itemsContainer"); - "List" == viewStyle ? (itemsContainer.classList.add("vertical-list"), itemsContainer.classList.remove("vertical-wrap")) : (itemsContainer.classList.remove("vertical-list"), itemsContainer.classList.add("vertical-wrap")), itemsContainer.innerHTML = "" + var viewStyle = self.getCurrentViewStyle(); + var itemsContainer = tabContent.querySelector(".itemsContainer"); + + if ("List" == viewStyle) { + itemsContainer.classList.add("vertical-list"); + itemsContainer.classList.remove("vertical-wrap"); + } else { + itemsContainer.classList.remove("vertical-list"); + itemsContainer.classList.add("vertical-wrap"); + } + + itemsContainer.innerHTML = ""; } function reloadItems(page) { loading.show(); isLoading = true; var query = getQuery(page); - ApiClient.getItems(Dashboard.getCurrentUserId(), query).then(function(result) { + ApiClient.getItems(Dashboard.getCurrentUserId(), query).then(function (result) { function onNextPageClick() { - if (isLoading) return; + if (isLoading) { + return; + } + query.StartIndex += query.Limit; - reloadItems(tabContent) + reloadItems(tabContent); } function onPreviousPageClick() { - if (isLoading) return; + if (isLoading) { + return; + } + query.StartIndex -= query.Limit; - reloadItems(tabContent) + reloadItems(tabContent); } window.scrollTo(0, 0); - var html, pagingHtml = libraryBrowser.getQueryPagingHtml({ - startIndex: query.StartIndex, - limit: query.Limit, - totalRecordCount: result.TotalRecordCount, - showLimit: !1, - updatePageSizeSetting: !1, - addLayoutButton: !1, - sortButton: !1, - filterButton: !1 - }), - viewStyle = self.getCurrentViewStyle(), - itemsContainer = tabContent.querySelector(".itemsContainer"); - html = "List" == viewStyle ? listView.getListViewHtml({ - items: result.Items, - sortBy: query.SortBy, - showParentTitle: !0 - }) : "PosterCard" == viewStyle ? cardBuilder.getCardsHtml({ - items: result.Items, - shape: "backdrop", - showTitle: !0, - showParentTitle: !0, - scalable: !0, - cardLayout: !0 - }) : cardBuilder.getCardsHtml({ - items: result.Items, - shape: "backdrop", - showTitle: !0, - showParentTitle: !0, - overlayText: !1, - centerText: !0, - scalable: !0, - overlayPlayButton: !0 + var html; + var pagingHtml = libraryBrowser.getQueryPagingHtml({ + startIndex: query.StartIndex, + limit: query.Limit, + totalRecordCount: result.TotalRecordCount, + showLimit: false, + updatePageSizeSetting: false, + addLayoutButton: false, + sortButton: false, + filterButton: false }); - var i, length, elems; - for (elems = tabContent.querySelectorAll(".paging"), i = 0, length = elems.length; i < length; i++) + var viewStyle = self.getCurrentViewStyle(); + var itemsContainer = tabContent.querySelector(".itemsContainer"); + if (viewStyle == "List") { + html = listView.getListViewHtml({ + items: result.Items, + sortBy: query.SortBy, + showParentTitle: true + }); + } else if (viewStyle == "PosterCard") { + html = cardBuilder.getCardsHtml({ + items: result.Items, + shape: "backdrop", + showTitle: true, + showParentTitle: true, + scalable: true, + cardLayout: true + }); + } else { + html = cardBuilder.getCardsHtml({ + items: result.Items, + shape: "backdrop", + showTitle: true, + showParentTitle: true, + overlayText: false, + centerText: true, + scalable: true, + overlayPlayButton: true + }); + } + var i; + var length; + var elems; + + elems = tabContent.querySelectorAll(".paging"); + for (i = 0, length = elems.length; i < length; i++) { elems[i].innerHTML = pagingHtml; - for (elems = tabContent.querySelectorAll(".btnNextPage"), i = 0, length = elems.length; i < length; i++) + } + + elems = tabContent.querySelectorAll(".btnNextPage"); + for (i = 0, length = elems.length; i < length; i++) { elems[i].addEventListener("click", onNextPageClick); - for (elems = tabContent.querySelectorAll(".btnPreviousPage"), i = 0, length = elems.length; i < length; i++) + } + + elems = tabContent.querySelectorAll(".btnPreviousPage"); + for (i = 0, length = elems.length; i < length; i++) { elems[i].addEventListener("click", onPreviousPageClick); + } + itemsContainer.innerHTML = html; imageLoader.lazyChildren(itemsContainer); libraryBrowser.saveQueryValues(getSavedQueryKey(page), query); loading.hide(); isLoading = false; - }) + }); } - var self = this, - pageSize = 100, - data = {}, - isLoading = false; - self.showFilterMenu = function() { - require(["components/filterdialog/filterdialog"], function(filterDialogFactory) { - var filterDialog = new filterDialogFactory({ - query: getQuery(tabContent), - mode: "episodes", - serverId: ApiClient.serverId() - }); - events.on(filterDialog, "filterchange", function() { - reloadItems(tabContent) - }), filterDialog.show() - }) - }, self.getCurrentViewStyle = function() { - return getPageData(tabContent).view - }, - function(tabContent) { - tabContent.querySelector(".btnFilter").addEventListener("click", function() { - self.showFilterMenu() - }), tabContent.querySelector(".btnSort").addEventListener("click", function(e) { - libraryBrowser.showSortMenu({ - items: [{ - name: Globalize.translate("OptionNameSort"), - id: "SeriesSortName,SortName" - }, { - name: Globalize.translate("OptionTvdbRating"), - id: "CommunityRating,SeriesSortName,SortName" - }, { - name: Globalize.translate("OptionDateAdded"), - id: "DateCreated,SeriesSortName,SortName" - }, { - name: Globalize.translate("OptionPremiereDate"), - id: "PremiereDate,SeriesSortName,SortName" - }, { - name: Globalize.translate("OptionDatePlayed"), - id: "DatePlayed,SeriesSortName,SortName" - }, { - name: Globalize.translate("OptionParentalRating"), - id: "OfficialRating,SeriesSortName,SortName" - }, { - name: Globalize.translate("OptionPlayCount"), - id: "PlayCount,SeriesSortName,SortName" - }, { - name: Globalize.translate("OptionRuntime"), - id: "Runtime,SeriesSortName,SortName" - }], - callback: function() { - reloadItems(tabContent) - }, - query: getQuery(tabContent), - button: e.target - }) + + var self = this; + var pageSize = 100; + var data = {}; + var isLoading = false; + + self.showFilterMenu = function () { + require(["components/filterdialog/filterdialog"], function (filterDialogFactory) { + var filterDialog = new filterDialogFactory({ + query: getQuery(tabContent), + mode: "episodes", + serverId: ApiClient.serverId() }); - var btnSelectView = tabContent.querySelector(".btnSelectView"); - btnSelectView.addEventListener("click", function(e) { - libraryBrowser.showLayoutMenu(e.target, self.getCurrentViewStyle(), "List,Poster,PosterCard".split(",")) - }), btnSelectView.addEventListener("layoutchange", function(e) { - var viewStyle = e.detail.viewStyle; - getPageData(tabContent).view = viewStyle, libraryBrowser.saveViewSetting(getSavedQueryKey(tabContent), viewStyle), onViewStyleChange(), reloadItems(tabContent) - }) - }(tabContent), onViewStyleChange(), self.renderTab = function() { - reloadItems(tabContent) - }, self.destroy = function() {} - } + events.on(filterDialog, "filterchange", function () { + reloadItems(tabContent); + }); + filterDialog.show(); + }); + }; + + self.getCurrentViewStyle = function () { + return getPageData(tabContent).view; + }; + + function initPage(tabContent) { + tabContent.querySelector(".btnFilter").addEventListener("click", function () { + self.showFilterMenu(); + }); + tabContent.querySelector(".btnSort").addEventListener("click", function (e) { + libraryBrowser.showSortMenu({ + items: [{ + name: Globalize.translate("OptionNameSort"), + id: "SeriesSortName,SortName" + }, { + name: Globalize.translate("OptionTvdbRating"), + id: "CommunityRating,SeriesSortName,SortName" + }, { + name: Globalize.translate("OptionDateAdded"), + id: "DateCreated,SeriesSortName,SortName" + }, { + name: Globalize.translate("OptionPremiereDate"), + id: "PremiereDate,SeriesSortName,SortName" + }, { + name: Globalize.translate("OptionDatePlayed"), + id: "DatePlayed,SeriesSortName,SortName" + }, { + name: Globalize.translate("OptionParentalRating"), + id: "OfficialRating,SeriesSortName,SortName" + }, { + name: Globalize.translate("OptionPlayCount"), + id: "PlayCount,SeriesSortName,SortName" + }, { + name: Globalize.translate("OptionRuntime"), + id: "Runtime,SeriesSortName,SortName" + }], + callback: function () { + reloadItems(tabContent); + }, + query: getQuery(tabContent), + button: e.target + }); + }); + var btnSelectView = tabContent.querySelector(".btnSelectView"); + btnSelectView.addEventListener("click", function (e) { + libraryBrowser.showLayoutMenu(e.target, self.getCurrentViewStyle(), "List,Poster,PosterCard".split(",")); + }); + btnSelectView.addEventListener("layoutchange", function (e) { + var viewStyle = e.detail.viewStyle; + getPageData(tabContent).view = viewStyle; + libraryBrowser.saveViewSetting(getSavedQueryKey(tabContent), viewStyle); + onViewStyleChange(); + reloadItems(tabContent); + }); + } + + initPage(tabContent); + onViewStyleChange(); + + self.renderTab = function () { + reloadItems(tabContent); + }; + + self.destroy = function () {}; + }; }); diff --git a/src/controllers/shows/tvgenres.js b/src/controllers/shows/tvgenres.js index e9559155e1..956b8fa6fa 100644 --- a/src/controllers/shows/tvgenres.js +++ b/src/controllers/shows/tvgenres.js @@ -1,139 +1,200 @@ -define(["layoutManager", "loading", "libraryBrowser", "cardBuilder", "lazyLoader", "apphost", "globalize", "appRouter", "dom", "emby-button"], function(layoutManager, loading, libraryBrowser, cardBuilder, lazyLoader, appHost, globalize, appRouter, dom) { +define(["layoutManager", "loading", "libraryBrowser", "cardBuilder", "lazyLoader", "apphost", "globalize", "appRouter", "dom", "emby-button"], function (layoutManager, loading, libraryBrowser, cardBuilder, lazyLoader, appHost, globalize, appRouter, dom) { "use strict"; - return function(view, params, tabContent) { + + return function (view, params, tabContent) { function getPageData() { - var key = getSavedQueryKey(), - pageData = data[key]; - return pageData || (pageData = data[key] = { - query: { - SortBy: "SortName", - SortOrder: "Ascending", - IncludeItemTypes: "Series", - Recursive: !0, - EnableTotalRecordCount: !1 - }, - view: "Poster" - }, pageData.query.ParentId = params.topParentId, libraryBrowser.loadSavedQueryValues(key, pageData.query)), pageData + var key = getSavedQueryKey(); + var pageData = data[key]; + + if (!pageData) { + pageData = data[key] = { + query: { + SortBy: "SortName", + SortOrder: "Ascending", + IncludeItemTypes: "Series", + Recursive: true, + EnableTotalRecordCount: false + }, + view: "Poster" + }; + pageData.query.ParentId = params.topParentId; + libraryBrowser.loadSavedQueryValues(key, pageData.query); + } + + return pageData; } function getQuery() { - return getPageData().query + return getPageData().query; } function getSavedQueryKey() { - return libraryBrowser.getSavedQueryKey("seriesgenres") + return libraryBrowser.getSavedQueryKey("seriesgenres"); } function getPromise() { loading.show(); var query = getQuery(); - return ApiClient.getGenres(ApiClient.getCurrentUserId(), query) + return ApiClient.getGenres(ApiClient.getCurrentUserId(), query); } function enableScrollX() { - return !layoutManager.desktop + return !layoutManager.desktop; } function getThumbShape() { - return enableScrollX() ? "overflowBackdrop" : "backdrop" + return enableScrollX() ? "overflowBackdrop" : "backdrop"; } function getPortraitShape() { - return enableScrollX() ? "overflowPortrait" : "portrait" + return enableScrollX() ? "overflowPortrait" : "portrait"; } function fillItemsContainer(elem) { - var id = elem.getAttribute("data-id"), - viewStyle = self.getCurrentViewStyle(), - limit = "Thumb" == viewStyle || "ThumbCard" == viewStyle ? 5 : 9; - enableScrollX() && (limit = 10); - var enableImageTypes = "Thumb" == viewStyle || "ThumbCard" == viewStyle ? "Primary,Backdrop,Thumb" : "Primary", - query = { - SortBy: "SortName", - SortOrder: "Ascending", - IncludeItemTypes: "Series", - Recursive: !0, - Fields: "PrimaryImageAspectRatio,MediaSourceCount,BasicSyncInfo", - ImageTypeLimit: 1, - EnableImageTypes: enableImageTypes, - Limit: limit, - GenreIds: id, - EnableTotalRecordCount: !1, - ParentId: params.topParentId - }; - ApiClient.getItems(ApiClient.getCurrentUserId(), query).then(function(result) { + var id = elem.getAttribute("data-id"); + var viewStyle = self.getCurrentViewStyle(); + var limit = "Thumb" == viewStyle || "ThumbCard" == viewStyle ? 5 : 9; + + if (enableScrollX()) { + limit = 10; + } + + var enableImageTypes = "Thumb" == viewStyle || "ThumbCard" == viewStyle ? "Primary,Backdrop,Thumb" : "Primary"; + var query = { + SortBy: "SortName", + SortOrder: "Ascending", + IncludeItemTypes: "Series", + Recursive: true, + Fields: "PrimaryImageAspectRatio,MediaSourceCount,BasicSyncInfo", + ImageTypeLimit: 1, + EnableImageTypes: enableImageTypes, + Limit: limit, + GenreIds: id, + EnableTotalRecordCount: false, + ParentId: params.topParentId + }; + ApiClient.getItems(ApiClient.getCurrentUserId(), query).then(function (result) { var supportsImageAnalysis = appHost.supports("imageanalysis"); - "Thumb" == viewStyle ? cardBuilder.buildCards(result.Items, { - itemsContainer: elem, - shape: getThumbShape(), - preferThumb: !0, - showTitle: !0, - scalable: !0, - centerText: !0, - overlayMoreButton: !0, - allowBottomPadding: !1 - }) : "ThumbCard" == viewStyle ? cardBuilder.buildCards(result.Items, { - itemsContainer: elem, - shape: getThumbShape(), - preferThumb: !0, - showTitle: !0, - scalable: !0, - centerText: !1, - cardLayout: !0, - showYear: !0 - }) : "PosterCard" == viewStyle ? cardBuilder.buildCards(result.Items, { - itemsContainer: elem, - shape: getPortraitShape(), - showTitle: !0, - scalable: !0, - centerText: !1, - cardLayout: !0, - showYear: !0 - }) : "Poster" == viewStyle && cardBuilder.buildCards(result.Items, { - itemsContainer: elem, - shape: getPortraitShape(), - scalable: !0, - overlayMoreButton: !0, - allowBottomPadding: !1 - }), result.Items.length >= query.Limit && tabContent.querySelector(".btnMoreFromGenre" + id + " i").classList.remove("hide") - }) + + if (viewStyle == "Thumb") { + cardBuilder.buildCards(result.Items, { + itemsContainer: elem, + shape: getThumbShape(), + preferThumb: true, + showTitle: true, + scalable: true, + centerText: true, + overlayMoreButton: true, + allowBottomPadding: false + }); + } else if (viewStyle == "ThumbCard") { + cardBuilder.buildCards(result.Items, { + itemsContainer: elem, + shape: getThumbShape(), + preferThumb: true, + showTitle: true, + scalable: true, + centerText: false, + cardLayout: true, + showYear: true + }); + } else if (viewStyle == "PosterCard") { + cardBuilder.buildCards(result.Items, { + itemsContainer: elem, + shape: getPortraitShape(), + showTitle: true, + scalable: true, + centerText: false, + cardLayout: true, + showYear: true + }); + } else if (viewStyle == "Poster") { + cardBuilder.buildCards(result.Items, { + itemsContainer: elem, + shape: getPortraitShape(), + scalable: true, + overlayMoreButton: true, + allowBottomPadding: false + }); + } + if (result.Items.length >= query.Limit) { + tabContent.querySelector(".btnMoreFromGenre" + id + " i").classList.remove("hide"); + } + }); } function reloadItems(context, promise) { var query = getQuery(); - promise.then(function(result) { - for (var elem = context.querySelector("#items"), html = "", items = result.Items, i = 0, length = items.length; i < length; i++) { + promise.then(function (result) { + var elem = context.querySelector("#items"); + var html = ""; + var items = result.Items; + + for (var i = 0, length = items.length; i < length; i++) { var item = items[i]; - if (html += '
', html += '", enableScrollX()) { + html += '
'; + html += '"; + if (enableScrollX()) { var scrollXClass = "scrollX hiddenScrollX"; - layoutManager.tv && (scrollXClass += " smoothScrollX"), html += '
' - } else html += '
'; - html += "
", html += "
" + if (layoutManager.tv) { + scrollXClass += "smoothScrollX"; + } + html += '
'; + } else { + html += '
'; + } + html += "
"; + html += "
"; } - elem.innerHTML = html, lazyLoader.lazyChildren(elem, fillItemsContainer), libraryBrowser.saveQueryValues(getSavedQueryKey(), query), loading.hide() - }) + + elem.innerHTML = html; + lazyLoader.lazyChildren(elem, fillItemsContainer); + libraryBrowser.saveQueryValues(getSavedQueryKey(), query); + loading.hide(); + }); } function fullyReload() { - self.preRender(), self.renderTab() + self.preRender(); + self.renderTab(); } - var self = this, - data = {}; - self.getViewStyles = function() { - return "Poster,PosterCard,Thumb,ThumbCard".split(",") - }, self.getCurrentViewStyle = function() { - return getPageData(tabContent).view - }, self.setCurrentViewStyle = function(viewStyle) { - getPageData(tabContent).view = viewStyle, libraryBrowser.saveViewSetting(getSavedQueryKey(tabContent), viewStyle), fullyReload() - }, self.enableViewSelection = !0; + + var self = this; + var data = {}; + + self.getViewStyles = function () { + return "Poster,PosterCard,Thumb,ThumbCard".split(","); + }; + + self.getCurrentViewStyle = function () { + return getPageData(tabContent).view; + }; + + self.setCurrentViewStyle = function (viewStyle) { + getPageData(tabContent).view = viewStyle; + libraryBrowser.saveViewSetting(getSavedQueryKey(tabContent), viewStyle); + fullyReload(); + }; + + self.enableViewSelection = true; var promise; - self.preRender = function() { - promise = getPromise() - }, self.renderTab = function() { - reloadItems(tabContent, promise) - } - } -}); \ No newline at end of file + + self.preRender = function () { + promise = getPromise(); + }; + + self.renderTab = function () { + reloadItems(tabContent, promise); + }; + }; +}); diff --git a/src/controllers/shows/tvlatest.js b/src/controllers/shows/tvlatest.js index 006f41e6ce..2a1ed56bf4 100644 --- a/src/controllers/shows/tvlatest.js +++ b/src/controllers/shows/tvlatest.js @@ -1,52 +1,60 @@ -define(["loading", "components/groupedcards", "cardBuilder", "apphost", "imageLoader"], function(loading, groupedcards, cardBuilder, appHost, imageLoader) { +define(["loading", "components/groupedcards", "cardBuilder", "apphost", "imageLoader"], function (loading, groupedcards, cardBuilder, appHost, imageLoader) { "use strict"; function getLatestPromise(context, params) { loading.show(); - var userId = ApiClient.getCurrentUserId(), - parentId = params.topParentId, - options = { - IncludeItemTypes: "Episode", - Limit: 30, - Fields: "PrimaryImageAspectRatio,BasicSyncInfo", - ParentId: parentId, - ImageTypeLimit: 1, - EnableImageTypes: "Primary,Backdrop,Thumb" - }; - return ApiClient.getJSON(ApiClient.getUrl("Users/" + userId + "/Items/Latest", options)) + var userId = ApiClient.getCurrentUserId(); + var parentId = params.topParentId; + var options = { + IncludeItemTypes: "Episode", + Limit: 30, + Fields: "PrimaryImageAspectRatio,BasicSyncInfo", + ParentId: parentId, + ImageTypeLimit: 1, + EnableImageTypes: "Primary,Backdrop,Thumb" + }; + return ApiClient.getJSON(ApiClient.getUrl("Users/" + userId + "/Items/Latest", options)); } function loadLatest(context, params, promise) { - promise.then(function(items) { + promise.then(function (items) { var html = ""; appHost.supports("imageanalysis"); html += cardBuilder.getCardsHtml({ items: items, shape: "backdrop", - preferThumb: !0, - showTitle: !0, - showSeriesYear: !0, - showParentTitle: !0, - overlayText: !1, - cardLayout: !1, - showUnplayedIndicator: !1, - showChildCountIndicator: !0, - centerText: !0, - lazy: !0, - overlayPlayButton: !0, + preferThumb: true, + showTitle: true, + showSeriesYear: true, + showParentTitle: true, + overlayText: false, + cardLayout: false, + showUnplayedIndicator: false, + showChildCountIndicator: true, + centerText: true, + lazy: true, + overlayPlayButton: true, lines: 2 }); var elem = context.querySelector("#latestEpisodes"); - elem.innerHTML = html, imageLoader.lazyChildren(elem), loading.hide() - }) + elem.innerHTML = html; + imageLoader.lazyChildren(elem); + loading.hide(); + }); } - return function(view, params, tabContent) { + + return function (view, params, tabContent) { var self = this; var latestPromise; - self.preRender = function() { - latestPromise = getLatestPromise(view, params) - }, self.renderTab = function() { - loadLatest(tabContent, params, latestPromise) - }, tabContent.querySelector("#latestEpisodes").addEventListener("click", groupedcards.onItemsContainerClick) - } -}); \ No newline at end of file + + self.preRender = function () { + latestPromise = getLatestPromise(view, params); + }; + + self.renderTab = function () { + loadLatest(tabContent, params, latestPromise); + }; + + tabContent.querySelector("#latestEpisodes").addEventListener("click", groupedcards.onItemsContainerClick); + }; +}); diff --git a/src/controllers/shows/tvrecommended.js b/src/controllers/shows/tvrecommended.js index 9de1461b3d..1386e76a31 100644 --- a/src/controllers/shows/tvrecommended.js +++ b/src/controllers/shows/tvrecommended.js @@ -1,4 +1,4 @@ -define(["events", "inputManager", "libraryMenu", "layoutManager", "loading", "dom", "userSettings", "cardBuilder", "playbackManager", "mainTabsManager", "scrollStyles", "emby-itemscontainer", "emby-button"], function(events, inputManager, libraryMenu, layoutManager, loading, dom, userSettings, cardBuilder, playbackManager, mainTabsManager) { +define(["events", "inputManager", "libraryMenu", "layoutManager", "loading", "dom", "userSettings", "cardBuilder", "playbackManager", "mainTabsManager", "scrollStyles", "emby-itemscontainer", "emby-button"], function (events, inputManager, libraryMenu, layoutManager, loading, dom, userSettings, cardBuilder, playbackManager, mainTabsManager) { "use strict"; function getTabs() { @@ -19,30 +19,51 @@ define(["events", "inputManager", "libraryMenu", "layoutManager", "loading", "do }, { name: Globalize.translate("ButtonSearch"), cssClass: "searchTabButton" - }] + }]; } function getDefaultTabIndex(folderId) { switch (userSettings.get("landing-" + folderId)) { case "suggestions": return 1; + case "latest": return 2; + case "favorites": return 1; + case "genres": return 4; + default: - return 0 + return 0; } } function setScrollClasses(elem, scrollX) { - scrollX ? (elem.classList.add("hiddenScrollX"), layoutManager.tv && elem.classList.add("smoothScrollX"), elem.classList.add("scrollX"), elem.classList.remove("vertical-wrap")) : (elem.classList.remove("hiddenScrollX"), elem.classList.remove("smoothScrollX"), elem.classList.remove("scrollX"), elem.classList.add("vertical-wrap")) + if (scrollX) { + elem.classList.add("hiddenScrollX"); + + if (layoutManager.tv) { + elem.classList.add("smoothScrollX"); + } + + elem.classList.add("scrollX"); + elem.classList.remove("vertical-wrap"); + } else { + elem.classList.remove("hiddenScrollX"); + elem.classList.remove("smoothScrollX"); + elem.classList.remove("scrollX"); + elem.classList.add("vertical-wrap"); + } } - return function(view, params) { + + return function (view, params) { function reload() { - loading.show(), loadResume(), loadNextUp() + loading.show(); + loadResume(); + loadNextUp(); } function loadNextUp() { @@ -52,178 +73,263 @@ define(["events", "inputManager", "libraryMenu", "layoutManager", "loading", "do UserId: ApiClient.getCurrentUserId(), ImageTypeLimit: 1, EnableImageTypes: "Primary,Backdrop,Thumb", - EnableTotalRecordCount: !1 + EnableTotalRecordCount: false }; - query.ParentId = libraryMenu.getTopParentId(), ApiClient.getNextUpEpisodes(query).then(function(result) { - result.Items.length ? view.querySelector(".noNextUpItems").classList.add("hide") : view.querySelector(".noNextUpItems").classList.remove("hide"); + query.ParentId = libraryMenu.getTopParentId(); + ApiClient.getNextUpEpisodes(query).then(function (result) { + if (result.Items.length) { + view.querySelector(".noNextUpItems").classList.add("hide"); + } else { + view.querySelector(".noNextUpItems").classList.remove("hide"); + } + var container = view.querySelector("#nextUpItems"); cardBuilder.buildCards(result.Items, { itemsContainer: container, - preferThumb: !0, + preferThumb: true, shape: "backdrop", - scalable: !0, - showTitle: !0, - showParentTitle: !0, - overlayText: !1, - centerText: !0, - overlayPlayButton: !0, - cardLayout: !1 - }), loading.hide() - }) + scalable: true, + showTitle: true, + showParentTitle: true, + overlayText: false, + centerText: true, + overlayPlayButton: true, + cardLayout: false + }); + loading.hide(); + }); } function enableScrollX() { - return !layoutManager.desktop + return !layoutManager.desktop; } function getThumbShape() { - return enableScrollX() ? "overflowBackdrop" : "backdrop" + return enableScrollX() ? "overflowBackdrop" : "backdrop"; } function loadResume() { - var parentId = libraryMenu.getTopParentId(), - screenWidth = dom.getWindowSize().innerWidth, - limit = screenWidth >= 1600 ? 5 : 6, - options = { - SortBy: "DatePlayed", - SortOrder: "Descending", - IncludeItemTypes: "Episode", - Filters: "IsResumable", - Limit: limit, - Recursive: !0, - Fields: "PrimaryImageAspectRatio,SeriesInfo,UserData,BasicSyncInfo", - ExcludeLocationTypes: "Virtual", - ParentId: parentId, - ImageTypeLimit: 1, - EnableImageTypes: "Primary,Backdrop,Thumb", - EnableTotalRecordCount: !1 - }; - ApiClient.getItems(ApiClient.getCurrentUserId(), options).then(function(result) { - result.Items.length ? view.querySelector("#resumableSection").classList.remove("hide") : view.querySelector("#resumableSection").classList.add("hide"); - var allowBottomPadding = !enableScrollX(), - container = view.querySelector("#resumableItems"); + var parentId = libraryMenu.getTopParentId(); + var screenWidth = dom.getWindowSize().innerWidth; + var limit = screenWidth >= 1600 ? 5 : 6; + var options = { + SortBy: "DatePlayed", + SortOrder: "Descending", + IncludeItemTypes: "Episode", + Filters: "IsResumable", + Limit: limit, + Recursive: true, + Fields: "PrimaryImageAspectRatio,SeriesInfo,UserData,BasicSyncInfo", + ExcludeLocationTypes: "Virtual", + ParentId: parentId, + ImageTypeLimit: 1, + EnableImageTypes: "Primary,Backdrop,Thumb", + EnableTotalRecordCount: false + }; + ApiClient.getItems(ApiClient.getCurrentUserId(), options).then(function (result) { + if (result.Items.length) { + view.querySelector("#resumableSection").classList.remove("hide"); + } else { + view.querySelector("#resumableSection").classList.add("hide"); + } + + var allowBottomPadding = !enableScrollX(); + var container = view.querySelector("#resumableItems"); cardBuilder.buildCards(result.Items, { itemsContainer: container, - preferThumb: !0, + preferThumb: true, shape: getThumbShape(), - scalable: !0, - showTitle: !0, - showParentTitle: !0, - overlayText: !1, - centerText: !0, - overlayPlayButton: !0, + scalable: true, + showTitle: true, + showParentTitle: true, + overlayText: false, + centerText: true, + overlayPlayButton: true, allowBottomPadding: allowBottomPadding, - cardLayout: !1 - }) - }) + cardLayout: false + }); + }); } function onBeforeTabChange(e) { - preLoadTab(view, parseInt(e.detail.selectedTabIndex)) + preLoadTab(view, parseInt(e.detail.selectedTabIndex)); } function onTabChange(e) { var newIndex = parseInt(e.detail.selectedTabIndex); - loadTab(view, newIndex) + loadTab(view, newIndex); } function getTabContainers() { - return view.querySelectorAll(".pageTabContent") + return view.querySelectorAll(".pageTabContent"); } function initTabs() { - mainTabsManager.setTabs(view, currentTabIndex, getTabs, getTabContainers, onBeforeTabChange, onTabChange) + mainTabsManager.setTabs(view, currentTabIndex, getTabs, getTabContainers, onBeforeTabChange, onTabChange); } function getTabController(page, index, callback) { var depends = []; + switch (index) { case 0: depends.push("controllers/shows/tvshows"); break; + case 1: break; + case 2: depends.push("controllers/shows/tvlatest"); break; + case 3: depends.push("controllers/shows/tvupcoming"); break; + case 4: depends.push("controllers/shows/tvgenres"); break; + case 5: depends.push("controllers/shows/tvstudios"); break; + case 6: depends.push("controllers/shows/episodes"); break; + case 7: - depends.push("scripts/searchtab") + depends.push("scripts/searchtab"); } - require(depends, function(controllerFactory) { + + require(depends, function (controllerFactory) { var tabContent; - 1 === index && (tabContent = view.querySelector(".pageTabContent[data-index='" + index + "']"), self.tabContent = tabContent); + + if (index === 1) { + tabContent = view.querySelector(".pageTabContent[data-index='" + index + "']"); + self.tabContent = tabContent; + } + var controller = tabControllers[index]; - controller || (tabContent = view.querySelector(".pageTabContent[data-index='" + index + "']"), controller = 1 === index ? self : 7 === index ? new controllerFactory(view, tabContent, { - collectionType: "tvshows", - parentId: params.topParentId - }) : new controllerFactory(view, params, tabContent), tabControllers[index] = controller, controller.initTab && controller.initTab()), callback(controller) - }) + + if (!controller) { + tabContent = view.querySelector(".pageTabContent[data-index='" + index + "']"); + + if (index === 1) { + controller = self; + } else if (index === 7) { + controller = new controllerFactory(view, tabContent, { + collectionType: "tvshows", + parentId: params.topParentId + }); + } else { + controller = new controllerFactory(view, params, tabContent); + } + + tabControllers[index] = controller; + + if (controller.initTab) { + controller.initTab(); + } + } + + callback(controller); + }); } function preLoadTab(page, index) { - getTabController(page, index, function(controller) { - -1 == renderedTabs.indexOf(index) && controller.preRender && controller.preRender() - }) + getTabController(page, index, function (controller) { + if (renderedTabs.indexOf(index) == -1 && controller.preRender) { + controller.preRender(); + } + }); } function loadTab(page, index) { - currentTabIndex = index, getTabController(page, index, function(controller) { - initialTabIndex = null, -1 == renderedTabs.indexOf(index) && (renderedTabs.push(index), controller.renderTab()) - }) + currentTabIndex = index; + getTabController(page, index, function (controller) { + initialTabIndex = null; + + if (renderedTabs.indexOf(index) == -1) { + renderedTabs.push(index); + controller.renderTab(); + } + }); } function onPlaybackStop(e, state) { - state.NowPlayingItem && "Video" == state.NowPlayingItem.MediaType && (renderedTabs = [], mainTabsManager.getTabsElement().triggerTabChange()) + if (state.NowPlayingItem && state.NowPlayingItem.MediaType == "Video") { + renderedTabs = []; + mainTabsManager.getTabsElement().triggerTabChange(); + } } function onWebSocketMessage(e, data) { var msg = data; - "UserDataChanged" === msg.MessageType && msg.Data.UserId == ApiClient.getCurrentUserId() && (renderedTabs = []) + + if (msg.MessageType === "UserDataChanged" && msg.Data.UserId == ApiClient.getCurrentUserId()) { + renderedTabs = []; + } } function onInputCommand(e) { switch (e.detail.command) { case "search": - e.preventDefault(), Dashboard.navigate("search.html?collectionType=tv&parentId=" + params.topParentId) + e.preventDefault(); + Dashboard.navigate("search.html?collectionType=tv&parentId=" + params.topParentId); } } - var isViewRestored, self = this, - currentTabIndex = parseInt(params.tab || getDefaultTabIndex(params.topParentId)), - initialTabIndex = currentTabIndex; - self.initTab = function() { + + var isViewRestored; + var self = this; + var currentTabIndex = parseInt(params.tab || getDefaultTabIndex(params.topParentId)); + var initialTabIndex = currentTabIndex; + + self.initTab = function () { var tabContent = self.tabContent; setScrollClasses(tabContent.querySelector("#resumableItems"), enableScrollX()); - }, self.renderTab = function() { - reload() }; - var tabControllers = [], - renderedTabs = []; - setScrollClasses(view.querySelector("#resumableItems"), enableScrollX()), view.addEventListener("viewshow", function(e) { - if (isViewRestored = e.detail.isRestored, initTabs(), !view.getAttribute("data-title")) { + + self.renderTab = function () { + reload(); + }; + + var tabControllers = []; + var renderedTabs = []; + setScrollClasses(view.querySelector("#resumableItems"), enableScrollX()); + view.addEventListener("viewshow", function (e) { + isViewRestored = e.detail.isRestored; + initTabs(); + if (!view.getAttribute("data-title")) { var parentId = params.topParentId; - parentId ? ApiClient.getItem(ApiClient.getCurrentUserId(), parentId).then(function(item) { - view.setAttribute("data-title", item.Name), libraryMenu.setTitle(item.Name) - }) : (view.setAttribute("data-title", Globalize.translate("TabShows")), libraryMenu.setTitle(Globalize.translate("TabShows"))) + + if (parentId) { + ApiClient.getItem(ApiClient.getCurrentUserId(), parentId).then(function (item) { + view.setAttribute("data-title", item.Name); + libraryMenu.setTitle(item.Name); + }); + } else { + view.setAttribute("data-title", Globalize.translate("TabShows")); + libraryMenu.setTitle(Globalize.translate("TabShows")); + } } - events.on(playbackManager, "playbackstop", onPlaybackStop), events.on(ApiClient, "message", onWebSocketMessage), inputManager.on(window, onInputCommand) - }), view.addEventListener("viewbeforehide", function(e) { - inputManager.off(window, onInputCommand), events.off(playbackManager, "playbackstop", onPlaybackStop), events.off(ApiClient, "message", onWebSocketMessage) - }), view.addEventListener("viewdestroy", function(e) { - tabControllers.forEach(function(t) { - t.destroy && t.destroy() - }) - }) - } + + events.on(playbackManager, "playbackstop", onPlaybackStop); + events.on(ApiClient, "message", onWebSocketMessage); + inputManager.on(window, onInputCommand); + }); + view.addEventListener("viewbeforehide", function (e) { + inputManager.off(window, onInputCommand); + events.off(playbackManager, "playbackstop", onPlaybackStop); + events.off(ApiClient, "message", onWebSocketMessage); + }); + view.addEventListener("viewdestroy", function (e) { + tabControllers.forEach(function (t) { + if (t.destroy) { + t.destroy(); + } + }); + }); + }; }); diff --git a/src/controllers/shows/tvshows.js b/src/controllers/shows/tvshows.js index ac832a915e..adccd98234 100644 --- a/src/controllers/shows/tvshows.js +++ b/src/controllers/shows/tvshows.js @@ -1,199 +1,284 @@ -define(["layoutManager", "loading", "events", "libraryBrowser", "imageLoader", "listView", "cardBuilder", "alphaPicker", "emby-itemscontainer"], function(layoutManager, loading, events, libraryBrowser, imageLoader, listView, cardBuilder, alphaPicker) { +define(["layoutManager", "loading", "events", "libraryBrowser", "imageLoader", "listView", "cardBuilder", "alphaPicker", "emby-itemscontainer"], function (layoutManager, loading, events, libraryBrowser, imageLoader, listView, cardBuilder, alphaPicker) { "use strict"; - return function(view, params, tabContent) { + + return function (view, params, tabContent) { function getPageData(context) { - var key = getSavedQueryKey(context), - pageData = data[key]; - return pageData || (pageData = data[key] = { - query: { - SortBy: "SortName", - SortOrder: "Ascending", - IncludeItemTypes: "Series", - Recursive: !0, - Fields: "PrimaryImageAspectRatio,BasicSyncInfo", - ImageTypeLimit: 1, - EnableImageTypes: "Primary,Backdrop,Banner,Thumb", - StartIndex: 0, - Limit: pageSize - }, - view: libraryBrowser.getSavedView(key) || "Poster" - }, pageData.query.ParentId = params.topParentId, libraryBrowser.loadSavedQueryValues(key, pageData.query)), pageData + var key = getSavedQueryKey(context); + var pageData = data[key]; + + if (!pageData) { + pageData = data[key] = { + query: { + SortBy: "SortName", + SortOrder: "Ascending", + IncludeItemTypes: "Series", + Recursive: true, + Fields: "PrimaryImageAspectRatio,BasicSyncInfo", + ImageTypeLimit: 1, + EnableImageTypes: "Primary,Backdrop,Banner,Thumb", + StartIndex: 0, + Limit: pageSize + }, + view: libraryBrowser.getSavedView(key) || "Poster" + }; + pageData.query.ParentId = params.topParentId; + libraryBrowser.loadSavedQueryValues(key, pageData.query); + } + + return pageData; } function getQuery(context) { - return getPageData(context).query + return getPageData(context).query; } function getSavedQueryKey(context) { - return context.savedQueryKey || (context.savedQueryKey = libraryBrowser.getSavedQueryKey("series")), context.savedQueryKey + if (!context.savedQueryKey) { + context.savedQueryKey = libraryBrowser.getSavedQueryKey("series"); + } + + return context.savedQueryKey; } function onViewStyleChange() { - var viewStyle = self.getCurrentViewStyle(), - itemsContainer = tabContent.querySelector(".itemsContainer"); - "List" == viewStyle ? (itemsContainer.classList.add("vertical-list"), itemsContainer.classList.remove("vertical-wrap")) : (itemsContainer.classList.remove("vertical-list"), itemsContainer.classList.add("vertical-wrap")), itemsContainer.innerHTML = "" + var viewStyle = self.getCurrentViewStyle(); + var itemsContainer = tabContent.querySelector(".itemsContainer"); + + if ("List" == viewStyle) { + itemsContainer.classList.add("vertical-list"); + itemsContainer.classList.remove("vertical-wrap"); + } else { + itemsContainer.classList.remove("vertical-list"); + itemsContainer.classList.add("vertical-wrap"); + } + + itemsContainer.innerHTML = ""; } function reloadItems(page) { loading.show(); isLoading = true; var query = getQuery(page); - ApiClient.getItems(ApiClient.getCurrentUserId(), query).then(function(result) { + ApiClient.getItems(ApiClient.getCurrentUserId(), query).then(function (result) { function onNextPageClick() { - if (isLoading) return; + if (isLoading) { + return; + } + query.StartIndex += query.Limit; reloadItems(tabContent); } function onPreviousPageClick() { - if (isLoading) return; + if (isLoading) { + return; + } + query.StartIndex -= query.Limit; reloadItems(tabContent); } - window.scrollTo(0, 0), updateFilterControls(page); - var html, pagingHtml = libraryBrowser.getQueryPagingHtml({ - startIndex: query.StartIndex, - limit: query.Limit, - totalRecordCount: result.TotalRecordCount, - showLimit: !1, - updatePageSizeSetting: !1, - addLayoutButton: !1, - sortButton: !1, - filterButton: !1 - }), - viewStyle = self.getCurrentViewStyle(); - html = "Thumb" == viewStyle ? cardBuilder.getCardsHtml({ - items: result.Items, - shape: "backdrop", - preferThumb: !0, - context: "tvshows", - overlayMoreButton: !0, - showTitle: !0, - centerText: !0 - }) : "ThumbCard" == viewStyle ? cardBuilder.getCardsHtml({ - items: result.Items, - shape: "backdrop", - preferThumb: !0, - context: "tvshows", - cardLayout: !0, - showTitle: !0, - showYear: !0, - centerText: !0 - }) : "Banner" == viewStyle ? cardBuilder.getCardsHtml({ - items: result.Items, - shape: "banner", - preferBanner: !0, - context: "tvshows" - }) : "List" == viewStyle ? listView.getListViewHtml({ - items: result.Items, - context: "tvshows", - sortBy: query.SortBy - }) : "PosterCard" == viewStyle ? cardBuilder.getCardsHtml({ - items: result.Items, - shape: "portrait", - context: "tvshows", - showTitle: !0, - showYear: !0, - centerText: !0, - cardLayout: !0 - }) : cardBuilder.getCardsHtml({ - items: result.Items, - shape: "portrait", - context: "tvshows", - centerText: !0, - lazy: !0, - overlayMoreButton: !0, - showTitle: !0, - showYear: !0 + + window.scrollTo(0, 0); + updateFilterControls(page); + var html; + var pagingHtml = libraryBrowser.getQueryPagingHtml({ + startIndex: query.StartIndex, + limit: query.Limit, + totalRecordCount: result.TotalRecordCount, + showLimit: false, + updatePageSizeSetting: false, + addLayoutButton: false, + sortButton: false, + filterButton: false }); - var i, length, elems = tabContent.querySelectorAll(".paging"); - for (i = 0, length = elems.length; i < length; i++) elems[i].innerHTML = pagingHtml; - for (elems = tabContent.querySelectorAll(".btnNextPage"), i = 0, length = elems.length; i < length; i++) elems[i].addEventListener("click", onNextPageClick); - for (elems = tabContent.querySelectorAll(".btnPreviousPage"), i = 0, length = elems.length; i < length; i++) elems[i].addEventListener("click", onPreviousPageClick); + var viewStyle = self.getCurrentViewStyle(); + if (viewStyle == "Thumb") { + html = cardBuilder.getCardsHtml({ + items: result.Items, + shape: "backdrop", + preferThumb: true, + context: "tvshows", + overlayMoreButton: true, + showTitle: true, + centerText: true + }); + } else if (viewStyle == "ThumbCard") { + html = cardBuilder.getCardsHtml({ + items: result.Items, + shape: "backdrop", + preferThumb: true, + context: "tvshows", + cardLayout: true, + showTitle: true, + showYear: true, + centerText: true + }); + } else if (viewStyle == "Banner") { + html = cardBuilder.getCardsHtml({ + items: result.Items, + shape: "banner", + preferBanner: true, + context: "tvshows" + }); + } else if (viewStyle == "List") { + html = listView.getListViewHtml({ + items: result.Items, + context: "tvshows", + sortBy: query.SortBy + }); + } else if (viewStyle == "PosterCard") { + html = cardBuilder.getCardsHtml({ + items: result.Items, + shape: "portrait", + context: "tvshows", + showTitle: true, + showYear: true, + centerText: true, + cardLayout: true + }); + } else { + html = cardBuilder.getCardsHtml({ + items: result.Items, + shape: "portrait", + context: "tvshows", + centerText: true, + lazy: true, + overlayMoreButton: true, + showTitle: true, + showYear: true + }); + } + var i; + var length; + var elems = tabContent.querySelectorAll(".paging"); + + for (i = 0, length = elems.length; i < length; i++) { + elems[i].innerHTML = pagingHtml; + } + + elems = tabContent.querySelectorAll(".btnNextPage"); + for (i = 0, length = elems.length; i < length; i++) { + elems[i].addEventListener("click", onNextPageClick); + } + + elems = tabContent.querySelectorAll(".btnPreviousPage"); + for (i = 0, length = elems.length; i < length; i++) { + elems[i].addEventListener("click", onPreviousPageClick); + } + var itemsContainer = tabContent.querySelector(".itemsContainer"); itemsContainer.innerHTML = html; imageLoader.lazyChildren(itemsContainer); libraryBrowser.saveQueryValues(getSavedQueryKey(page), query); loading.hide(); isLoading = false; - }) + }); } function updateFilterControls(tabContent) { var query = getQuery(tabContent); - self.alphaPicker.value(query.NameStartsWithOrGreater) + self.alphaPicker.value(query.NameStartsWithOrGreater); } - var self = this, - pageSize = 100, - data = {}, - isLoading = false; - self.showFilterMenu = function() { - require(["components/filterdialog/filterdialog"], function(filterDialogFactory) { - var filterDialog = new filterDialogFactory({ - query: getQuery(tabContent), - mode: "series", - serverId: ApiClient.serverId() - }); - events.on(filterDialog, "filterchange", function() { - getQuery(tabContent).StartIndex = 0, reloadItems(tabContent) - }), filterDialog.show() - }) - }, self.getCurrentViewStyle = function() { - return getPageData(tabContent).view - }, - function(tabContent) { - var alphaPickerElement = tabContent.querySelector(".alphaPicker"); - if (alphaPickerElement.addEventListener("alphavaluechanged", function(e) { - var newValue = e.detail.value, - query = getQuery(tabContent); - query.NameStartsWithOrGreater = newValue, query.StartIndex = 0, reloadItems(tabContent) - }), self.alphaPicker = new alphaPicker({ - element: alphaPickerElement, - valueChangeEvent: "click" - }), layoutManager.desktop || layoutManager.mobile) { - tabContent.querySelector(".alphaPicker").classList.add("alphabetPicker-right"); - var itemsContainer = tabContent.querySelector(".itemsContainer"); - itemsContainer.classList.remove("padded-left-withalphapicker"), itemsContainer.classList.add("padded-right-withalphapicker") - } - tabContent.querySelector(".btnFilter").addEventListener("click", function() { - self.showFilterMenu() - }), tabContent.querySelector(".btnSort").addEventListener("click", function(e) { - libraryBrowser.showSortMenu({ - items: [{ - name: Globalize.translate("OptionNameSort"), - id: "SortName" - }, { - name: Globalize.translate("OptionImdbRating"), - id: "CommunityRating,SortName" - }, { - name: Globalize.translate("OptionDateAdded"), - id: "DateCreated,SortName" - }, { - name: Globalize.translate("OptionDatePlayed"), - id: "DatePlayed,SortName" - }, { - name: Globalize.translate("OptionParentalRating"), - id: "OfficialRating,SortName" - }, { - name: Globalize.translate("OptionReleaseDate"), - id: "PremiereDate,SortName" - }], - callback: function() { - getQuery(tabContent).StartIndex = 0, reloadItems(tabContent) - }, - query: getQuery(tabContent), - button: e.target - }) + + var self = this; + var pageSize = 100; + var data = {}; + var isLoading = false; + + self.showFilterMenu = function () { + require(["components/filterdialog/filterdialog"], function (filterDialogFactory) { + var filterDialog = new filterDialogFactory({ + query: getQuery(tabContent), + mode: "series", + serverId: ApiClient.serverId() }); - var btnSelectView = tabContent.querySelector(".btnSelectView"); - btnSelectView.addEventListener("click", function(e) { - libraryBrowser.showLayoutMenu(e.target, self.getCurrentViewStyle(), "Banner,List,Poster,PosterCard,Thumb,ThumbCard".split(",")) - }), btnSelectView.addEventListener("layoutchange", function(e) { - var viewStyle = e.detail.viewStyle; - getPageData(tabContent).view = viewStyle, libraryBrowser.saveViewSetting(getSavedQueryKey(tabContent), viewStyle), getQuery(tabContent).StartIndex = 0, onViewStyleChange(), reloadItems(tabContent) - }) - }(tabContent), onViewStyleChange(), self.renderTab = function() { - reloadItems(tabContent), updateFilterControls(tabContent) - }, self.destroy = function() {} - } + events.on(filterDialog, "filterchange", function () { + getQuery(tabContent).StartIndex = 0; + reloadItems(tabContent); + }); + filterDialog.show(); + }); + }; + + self.getCurrentViewStyle = function () { + return getPageData(tabContent).view; + }; + + function initPage(tabContent) { + var alphaPickerElement = tabContent.querySelector(".alphaPicker"); + + alphaPickerElement.addEventListener("alphavaluechanged", function (e) { + var newValue = e.detail.value; + var query = getQuery(tabContent); + query.NameStartsWithOrGreater = newValue; + query.StartIndex = 0; + reloadItems(tabContent); + }); + self.alphaPicker = new alphaPicker({ + element: alphaPickerElement, + valueChangeEvent: "click" + }); + if (layoutManager.desktop || layoutManager.mobile) { + tabContent.querySelector(".alphaPicker").classList.add("alphabetPicker-right"); + var itemsContainer = tabContent.querySelector(".itemsContainer"); + itemsContainer.classList.remove("padded-left-withalphapicker"); + itemsContainer.classList.add("padded-right-withalphapicker"); + } + + tabContent.querySelector(".btnFilter").addEventListener("click", function () { + self.showFilterMenu(); + }); + tabContent.querySelector(".btnSort").addEventListener("click", function (e) { + libraryBrowser.showSortMenu({ + items: [{ + name: Globalize.translate("OptionNameSort"), + id: "SortName" + }, { + name: Globalize.translate("OptionImdbRating"), + id: "CommunityRating,SortName" + }, { + name: Globalize.translate("OptionDateAdded"), + id: "DateCreated,SortName" + }, { + name: Globalize.translate("OptionDatePlayed"), + id: "DatePlayed,SortName" + }, { + name: Globalize.translate("OptionParentalRating"), + id: "OfficialRating,SortName" + }, { + name: Globalize.translate("OptionReleaseDate"), + id: "PremiereDate,SortName" + }], + callback: function () { + getQuery(tabContent).StartIndex = 0; + reloadItems(tabContent); + }, + query: getQuery(tabContent), + button: e.target + }); + }); + var btnSelectView = tabContent.querySelector(".btnSelectView"); + btnSelectView.addEventListener("click", function (e) { + libraryBrowser.showLayoutMenu(e.target, self.getCurrentViewStyle(), "Banner,List,Poster,PosterCard,Thumb,ThumbCard".split(",")); + }); + btnSelectView.addEventListener("layoutchange", function (e) { + var viewStyle = e.detail.viewStyle; + getPageData(tabContent).view = viewStyle; + libraryBrowser.saveViewSetting(getSavedQueryKey(tabContent), viewStyle); + getQuery(tabContent).StartIndex = 0; + onViewStyleChange(); + reloadItems(tabContent); + }); + } + + initPage(tabContent); + onViewStyleChange(); + + self.renderTab = function () { + reloadItems(tabContent); + updateFilterControls(tabContent); + }; + + self.destroy = function () {}; + }; }); diff --git a/src/controllers/shows/tvstudios.js b/src/controllers/shows/tvstudios.js index bfa33401f4..3c000a8e72 100644 --- a/src/controllers/shows/tvstudios.js +++ b/src/controllers/shows/tvstudios.js @@ -1,52 +1,65 @@ -define(["loading", "libraryBrowser", "cardBuilder", "apphost"], function(loading, libraryBrowser, cardBuilder, appHost) { +define(["loading", "libraryBrowser", "cardBuilder", "apphost"], function (loading, libraryBrowser, cardBuilder, appHost) { "use strict"; function getQuery(params) { - var key = getSavedQueryKey(), - pageData = data[key]; - return pageData || (pageData = data[key] = { - query: { - SortBy: "SortName", - SortOrder: "Ascending", - IncludeItemTypes: "Series", - Recursive: !0, - Fields: "DateCreated,PrimaryImageAspectRatio", - StartIndex: 0 - } - }, pageData.query.ParentId = params.topParentId), pageData.query + var key = getSavedQueryKey(); + var pageData = data[key]; + + if (!pageData) { + pageData = data[key] = { + query: { + SortBy: "SortName", + SortOrder: "Ascending", + IncludeItemTypes: "Series", + Recursive: true, + Fields: "DateCreated,PrimaryImageAspectRatio", + StartIndex: 0 + } + }; + pageData.query.ParentId = params.topParentId; + } + + return pageData.query; } function getSavedQueryKey() { - return libraryBrowser.getSavedQueryKey("studios") + return libraryBrowser.getSavedQueryKey("studios"); } function getPromise(context, params) { var query = getQuery(params); - return loading.show(), ApiClient.getStudios(ApiClient.getCurrentUserId(), query) + loading.show(); + return ApiClient.getStudios(ApiClient.getCurrentUserId(), query); } function reloadItems(context, params, promise) { - promise.then(function(result) { + promise.then(function (result) { var elem = context.querySelector("#items"); cardBuilder.buildCards(result.Items, { itemsContainer: elem, shape: "backdrop", - preferThumb: !0, - showTitle: !0, - scalable: !0, - centerText: !0, - overlayMoreButton: !0, + preferThumb: true, + showTitle: true, + scalable: true, + centerText: true, + overlayMoreButton: true, context: "tvshows" - }), loading.hide() - }) + }); + loading.hide(); + }); } + var data = {}; - return function(view, params, tabContent) { - var promise, self = this; - self.preRender = function() { - promise = getPromise(view, params) - }, self.renderTab = function() { - reloadItems(tabContent, params, promise) - } - } -}); \ No newline at end of file + return function (view, params, tabContent) { + var promise; + var self = this; + + self.preRender = function () { + promise = getPromise(view, params); + }; + + self.renderTab = function () { + reloadItems(tabContent, params, promise); + }; + }; +}); diff --git a/src/controllers/shows/tvupcoming.js b/src/controllers/shows/tvupcoming.js index 9d6a79a5ef..162e6fcb34 100644 --- a/src/controllers/shows/tvupcoming.js +++ b/src/controllers/shows/tvupcoming.js @@ -1,4 +1,4 @@ -define(["layoutManager", "loading", "datetime", "libraryBrowser", "cardBuilder", "apphost", "imageLoader", "scrollStyles", "emby-itemscontainer"], function(layoutManager, loading, datetime, libraryBrowser, cardBuilder, appHost, imageLoader) { +define(["layoutManager", "loading", "datetime", "libraryBrowser", "cardBuilder", "apphost", "imageLoader", "scrollStyles", "emby-itemscontainer"], function (layoutManager, loading, datetime, libraryBrowser, cardBuilder, appHost, imageLoader) { "use strict"; function getUpcomingPromise(context, params) { @@ -9,82 +9,129 @@ define(["layoutManager", "loading", "datetime", "libraryBrowser", "cardBuilder", UserId: ApiClient.getCurrentUserId(), ImageTypeLimit: 1, EnableImageTypes: "Primary,Backdrop,Banner,Thumb", - EnableTotalRecordCount: !1 + EnableTotalRecordCount: false }; - return query.ParentId = params.topParentId, ApiClient.getJSON(ApiClient.getUrl("Shows/Upcoming", query)) + query.ParentId = params.topParentId; + return ApiClient.getJSON(ApiClient.getUrl("Shows/Upcoming", query)); } function loadUpcoming(context, params, promise) { - promise.then(function(result) { + promise.then(function (result) { var items = result.Items; - items.length ? context.querySelector(".noItemsMessage").style.display = "none" : context.querySelector(".noItemsMessage").style.display = "block", renderUpcoming(context.querySelector("#upcomingItems"), items), loading.hide() - }) + + if (items.length) { + context.querySelector(".noItemsMessage").style.display = "none"; + } else { + context.querySelector(".noItemsMessage").style.display = "block"; + } + + renderUpcoming(context.querySelector("#upcomingItems"), items); + loading.hide(); + }); } function enableScrollX() { - return !layoutManager.desktop + return !layoutManager.desktop; } function getThumbShape() { - return enableScrollX() ? "overflowBackdrop" : "backdrop" + return enableScrollX() ? "overflowBackdrop" : "backdrop"; } function renderUpcoming(elem, items) { - var i, length, groups = [], - currentGroupName = "", - currentGroup = []; + var i; + var length; + var groups = []; + var currentGroupName = ""; + var currentGroup = []; + for (i = 0, length = items.length; i < length; i++) { - var item = items[i], - dateText = ""; - if (item.PremiereDate) try { - var premiereDate = datetime.parseISO8601Date(item.PremiereDate, !0); - dateText = datetime.isRelativeDay(premiereDate, -1) ? Globalize.translate("Yesterday") : datetime.toLocaleDateString(premiereDate, { - weekday: "long", - month: "short", - day: "numeric" - }) - } catch (err) {} - dateText != currentGroupName ? (currentGroup.length && groups.push({ - name: currentGroupName, - items: currentGroup - }), currentGroupName = dateText, currentGroup = [item]) : currentGroup.push(item) + var item = items[i]; + var dateText = ""; + + if (item.PremiereDate) { + try { + var premiereDate = datetime.parseISO8601Date(item.PremiereDate, true); + dateText = datetime.isRelativeDay(premiereDate, -1) ? Globalize.translate("Yesterday") : datetime.toLocaleDateString(premiereDate, { + weekday: "long", + month: "short", + day: "numeric" + }); + } catch (err) {} + } + + if (dateText != currentGroupName) { + if (currentGroup.length) { + groups.push({ + name: currentGroupName, + items: currentGroup + }); + } + + currentGroupName = dateText; + currentGroup = [item]; + } else { + currentGroup.push(item); + } } + var html = ""; + for (i = 0, length = groups.length; i < length; i++) { var group = groups[i]; - html += '
', html += '

' + group.name + "

"; - var allowBottomPadding = !0; + html += '
'; + html += '

' + group.name + "

"; + var allowBottomPadding = true; + if (enableScrollX()) { - allowBottomPadding = !1; + allowBottomPadding = false; var scrollXClass = "scrollX hiddenScrollX"; - layoutManager.tv && (scrollXClass += " smoothScrollX"), html += '
' - } else html += '
'; + + if (layoutManager.tv) { + scrollXClass += " smoothScrollX"; + } + + html += '
'; + } else { + html += '
'; + } + var supportsImageAnalysis = appHost.supports("imageanalysis"); - supportsImageAnalysis = !1, html += cardBuilder.getCardsHtml({ + supportsImageAnalysis = false; + html += cardBuilder.getCardsHtml({ items: group.items, - showLocationTypeIndicator: !1, + showLocationTypeIndicator: false, shape: getThumbShape(), - showTitle: !0, - preferThumb: !0, - lazy: !0, - showDetailsMenu: !0, + showTitle: true, + preferThumb: true, + lazy: true, + showDetailsMenu: true, centerText: !supportsImageAnalysis, - showParentTitle: !0, - overlayText: !1, + showParentTitle: true, + overlayText: false, allowBottomPadding: allowBottomPadding, cardLayout: supportsImageAnalysis, - overlayMoreButton: !0, - missingIndicator: !1 - }), html += "
", html += "
" + overlayMoreButton: true, + missingIndicator: false + }); + html += "
"; + html += "
"; } - elem.innerHTML = html, imageLoader.lazyChildren(elem) + + elem.innerHTML = html; + imageLoader.lazyChildren(elem); } - return function(view, params, tabContent) { - var upcomingPromise, self = this; - self.preRender = function() { - upcomingPromise = getUpcomingPromise(view, params) - }, self.renderTab = function() { - loadUpcoming(tabContent, params, upcomingPromise) - } - } -}); \ No newline at end of file + + return function (view, params, tabContent) { + var upcomingPromise; + var self = this; + + self.preRender = function () { + upcomingPromise = getUpcomingPromise(view, params); + }; + + self.renderTab = function () { + loadUpcoming(tabContent, params, upcomingPromise); + }; + }; +}); diff --git a/src/controllers/streamingsettings.js b/src/controllers/streamingsettings.js index 6f19a68422..6c85034458 100644 --- a/src/controllers/streamingsettings.js +++ b/src/controllers/streamingsettings.js @@ -1,16 +1,19 @@ -define(["jQuery", "libraryMenu", "loading"], function($, libraryMenu, loading) { +define(["jQuery", "libraryMenu", "loading"], function ($, libraryMenu, loading) { "use strict"; function loadPage(page, config) { - $("#txtRemoteClientBitrateLimit", page).val(config.RemoteClientBitrateLimit / 1e6 || ""), loading.hide() + $("#txtRemoteClientBitrateLimit", page).val(config.RemoteClientBitrateLimit / 1e6 || ""); + loading.hide(); } function onSubmit() { loading.show(); var form = this; - return ApiClient.getServerConfiguration().then(function(config) { - config.RemoteClientBitrateLimit = parseInt(1e6 * parseFloat($("#txtRemoteClientBitrateLimit", form).val() || "0")), ApiClient.updateServerConfiguration(config).then(Dashboard.processServerConfigurationUpdateResult) - }), !1 + ApiClient.getServerConfiguration().then(function (config) { + config.RemoteClientBitrateLimit = parseInt(1e6 * parseFloat($("#txtRemoteClientBitrateLimit", form).val() || "0")); + ApiClient.updateServerConfiguration(config).then(Dashboard.processServerConfigurationUpdateResult); + }); + return false; } function getTabs() { @@ -23,30 +26,35 @@ define(["jQuery", "libraryMenu", "loading"], function($, libraryMenu, loading) { }, { href: "streamingsettings.html", name: Globalize.translate("TabStreaming") - }] + }]; } - $(document).on("pageinit", "#streamingSettingsPage", function() { + $(document).on("pageinit", "#streamingSettingsPage", function () { var page = this; - $("#btnSelectTranscodingTempPath", page).on("click.selectDirectory", function() { - require(["directorybrowser"], function(directoryBrowser) { - var picker = new directoryBrowser; + $("#btnSelectTranscodingTempPath", page).on("click.selectDirectory", function () { + require(["directorybrowser"], function (directoryBrowser) { + var picker = new directoryBrowser(); picker.show({ - callback: function(path) { - path && $("#txtTranscodingTempPath", page).val(path), picker.close() + callback: function (path) { + if (path) { + $("#txtTranscodingTempPath", page).val(path); + } + + picker.close(); }, - validateWriteable: !0, + validateWriteable: true, header: Globalize.translate("HeaderSelectTranscodingPath"), instruction: Globalize.translate("HeaderSelectTranscodingPathHelp") - }) - }) - }), $(".streamingSettingsForm").off("submit", onSubmit).on("submit", onSubmit) - }).on("pageshow", "#streamingSettingsPage", function() { + }); + }); + }); + $(".streamingSettingsForm").off("submit", onSubmit).on("submit", onSubmit); + }).on("pageshow", "#streamingSettingsPage", function () { loading.show(); libraryMenu.setTabs("playback", 2, getTabs); var page = this; - ApiClient.getServerConfiguration().then(function(config) { - loadPage(page, config) - }) - }) -}); \ No newline at end of file + ApiClient.getServerConfiguration().then(function (config) { + loadPage(page, config); + }); + }); +}); diff --git a/src/controllers/user/display.js b/src/controllers/user/display.js index 4b4440f96a..f91e874a89 100644 --- a/src/controllers/user/display.js +++ b/src/controllers/user/display.js @@ -1,28 +1,49 @@ -define(["displaySettings", "userSettingsBuilder", "userSettings"], function(DisplaySettings, userSettingsBuilder, currentUserSettings) { +define(["displaySettings", "userSettingsBuilder", "userSettings"], function (DisplaySettings, userSettingsBuilder, currentUserSettings) { "use strict"; - return function(view, params) { + + return function (view, params) { function onBeforeUnload(e) { - hasChanges && (e.returnValue = "You currently have unsaved changes. Are you sure you wish to leave?") + if (hasChanges) { + e.returnValue = "You currently have unsaved changes. Are you sure you wish to leave?"; + } } - var settingsInstance, hasChanges, userId = params.userId || ApiClient.getCurrentUserId(), - userSettings = userId === ApiClient.getCurrentUserId() ? currentUserSettings : new userSettingsBuilder; - view.addEventListener("viewshow", function() { - window.addEventListener("beforeunload", onBeforeUnload), settingsInstance ? settingsInstance.loadData() : settingsInstance = new DisplaySettings({ - serverId: ApiClient.serverId(), - userId: userId, - element: view.querySelector(".settingsContainer"), - userSettings: userSettings, - enableSaveButton: !1, - enableSaveConfirmation: !1 - }) - }), view.addEventListener("change", function() { - hasChanges = !0 - }), view.addEventListener("viewbeforehide", function() { - window.removeEventListener("beforeunload", onBeforeUnload), hasChanges = !1, settingsInstance && settingsInstance.submit() - }), view.addEventListener("viewdestroy", function() { - settingsInstance && (settingsInstance.destroy(), settingsInstance = null) - }), view.addEventListener("viewdestroy", function() { - settingsInstance && (settingsInstance.destroy(), settingsInstance = null) - }) - } -}); \ No newline at end of file + + var settingsInstance; + var hasChanges; + var userId = params.userId || ApiClient.getCurrentUserId(); + var userSettings = userId === ApiClient.getCurrentUserId() ? currentUserSettings : new userSettingsBuilder(); + view.addEventListener("viewshow", function () { + window.addEventListener("beforeunload", onBeforeUnload); + + if (settingsInstance) { + settingsInstance.loadData(); + } else { + settingsInstance = new DisplaySettings({ + serverId: ApiClient.serverId(), + userId: userId, + element: view.querySelector(".settingsContainer"), + userSettings: userSettings, + enableSaveButton: false, + enableSaveConfirmation: false + }); + } + }); + view.addEventListener("change", function () { + hasChanges = true; + }); + view.addEventListener("viewbeforehide", function () { + window.removeEventListener("beforeunload", onBeforeUnload); + hasChanges = false; + + if (settingsInstance) { + settingsInstance.submit(); + } + }); + view.addEventListener("viewdestroy", function () { + if (settingsInstance) { + settingsInstance.destroy(); + settingsInstance = null; + } + }); + }; +}); diff --git a/src/controllers/user/home.js b/src/controllers/user/home.js index a7147ddda3..5794d58723 100644 --- a/src/controllers/user/home.js +++ b/src/controllers/user/home.js @@ -1,26 +1,48 @@ -define(["homescreenSettings", "userSettingsBuilder", "dom", "globalize", "loading", "userSettings", "listViewStyle"], function(HomescreenSettings, userSettingsBuilder, dom, globalize, loading, currentUserSettings) { +define(["homescreenSettings", "userSettingsBuilder", "dom", "globalize", "loading", "userSettings", "listViewStyle"], function (HomescreenSettings, userSettingsBuilder, dom, globalize, loading, currentUserSettings) { "use strict"; - return function(view, params) { + + return function (view, params) { function onBeforeUnload(e) { - hasChanges && (e.returnValue = "You currently have unsaved changes. Are you sure you wish to leave?") + if (hasChanges) { + e.returnValue = "You currently have unsaved changes. Are you sure you wish to leave?"; + } } - var homescreenSettingsInstance, hasChanges, userId = params.userId || ApiClient.getCurrentUserId(), - userSettings = userId === ApiClient.getCurrentUserId() ? currentUserSettings : new userSettingsBuilder; - view.addEventListener("viewshow", function() { - window.addEventListener("beforeunload", onBeforeUnload), homescreenSettingsInstance ? homescreenSettingsInstance.loadData() : homescreenSettingsInstance = new HomescreenSettings({ - serverId: ApiClient.serverId(), - userId: userId, - element: view.querySelector(".homeScreenSettingsContainer"), - userSettings: userSettings, - enableSaveButton: !1, - enableSaveConfirmation: !1 - }) - }), view.addEventListener("change", function() { - hasChanges = !0 - }), view.addEventListener("viewbeforehide", function() { - hasChanges = !1, homescreenSettingsInstance && homescreenSettingsInstance.submit() - }), view.addEventListener("viewdestroy", function() { - homescreenSettingsInstance && (homescreenSettingsInstance.destroy(), homescreenSettingsInstance = null) - }) - } -}); \ No newline at end of file + + var homescreenSettingsInstance; + var hasChanges; + var userId = params.userId || ApiClient.getCurrentUserId(); + var userSettings = userId === ApiClient.getCurrentUserId() ? currentUserSettings : new userSettingsBuilder(); + view.addEventListener("viewshow", function () { + window.addEventListener("beforeunload", onBeforeUnload); + + if (homescreenSettingsInstance) { + homescreenSettingsInstance.loadData(); + } else { + homescreenSettingsInstance = new HomescreenSettings({ + serverId: ApiClient.serverId(), + userId: userId, + element: view.querySelector(".homeScreenSettingsContainer"), + userSettings: userSettings, + enableSaveButton: false, + enableSaveConfirmation: false + }); + } + }); + view.addEventListener("change", function () { + hasChanges = true; + }); + view.addEventListener("viewbeforehide", function () { + hasChanges = false; + + if (homescreenSettingsInstance) { + homescreenSettingsInstance.submit(); + } + }); + view.addEventListener("viewdestroy", function () { + if (homescreenSettingsInstance) { + homescreenSettingsInstance.destroy(); + homescreenSettingsInstance = null; + } + }); + }; +}); diff --git a/src/controllers/user/menu.js b/src/controllers/user/menu.js index 6bac0011d2..d9fa2ab998 100644 --- a/src/controllers/user/menu.js +++ b/src/controllers/user/menu.js @@ -18,7 +18,7 @@ define(["apphost", "connectionManager", "listViewStyle", "emby-button"], functio page.querySelector(".lnkSubtitlePreferences").setAttribute("href", "mypreferencessubtitles.html?userId=" + userId); if (appHost.supports("multiserver")) { - page.querySelector(".selectServer").classList.remove("hide") + page.querySelector(".selectServer").classList.remove("hide"); } else { page.querySelector(".selectServer").classList.add("hide"); } @@ -35,6 +35,6 @@ define(["apphost", "connectionManager", "listViewStyle", "emby-button"], functio page.querySelector(".adminSection").classList.add("hide"); } }); - }) - } + }); + }; }); diff --git a/src/controllers/user/playback.js b/src/controllers/user/playback.js index 856470948a..f2463ad8df 100644 --- a/src/controllers/user/playback.js +++ b/src/controllers/user/playback.js @@ -1,26 +1,48 @@ -define(["playbackSettings", "userSettingsBuilder", "dom", "globalize", "loading", "userSettings", "listViewStyle"], function(PlaybackSettings, userSettingsBuilder, dom, globalize, loading, currentUserSettings) { +define(["playbackSettings", "userSettingsBuilder", "dom", "globalize", "loading", "userSettings", "listViewStyle"], function (PlaybackSettings, userSettingsBuilder, dom, globalize, loading, currentUserSettings) { "use strict"; - return function(view, params) { + + return function (view, params) { function onBeforeUnload(e) { - hasChanges && (e.returnValue = "You currently have unsaved changes. Are you sure you wish to leave?") + if (hasChanges) { + e.returnValue = "You currently have unsaved changes. Are you sure you wish to leave?"; + } } - var settingsInstance, hasChanges, userId = params.userId || ApiClient.getCurrentUserId(), - userSettings = userId === ApiClient.getCurrentUserId() ? currentUserSettings : new userSettingsBuilder; - view.addEventListener("viewshow", function() { - window.addEventListener("beforeunload", onBeforeUnload), settingsInstance ? settingsInstance.loadData() : settingsInstance = new PlaybackSettings({ - serverId: ApiClient.serverId(), - userId: userId, - element: view.querySelector(".settingsContainer"), - userSettings: userSettings, - enableSaveButton: !1, - enableSaveConfirmation: !1 - }) - }), view.addEventListener("change", function() { - hasChanges = !0 - }), view.addEventListener("viewbeforehide", function() { - hasChanges = !1, settingsInstance && settingsInstance.submit() - }), view.addEventListener("viewdestroy", function() { - settingsInstance && (settingsInstance.destroy(), settingsInstance = null) - }) - } -}); \ No newline at end of file + + var settingsInstance; + var hasChanges; + var userId = params.userId || ApiClient.getCurrentUserId(); + var userSettings = userId === ApiClient.getCurrentUserId() ? currentUserSettings : new userSettingsBuilder(); + view.addEventListener("viewshow", function () { + window.addEventListener("beforeunload", onBeforeUnload); + + if (settingsInstance) { + settingsInstance.loadData(); + } else { + settingsInstance = new PlaybackSettings({ + serverId: ApiClient.serverId(), + userId: userId, + element: view.querySelector(".settingsContainer"), + userSettings: userSettings, + enableSaveButton: false, + enableSaveConfirmation: false + }); + } + }); + view.addEventListener("change", function () { + hasChanges = true; + }); + view.addEventListener("viewbeforehide", function () { + hasChanges = false; + + if (settingsInstance) { + settingsInstance.submit(); + } + }); + view.addEventListener("viewdestroy", function () { + if (settingsInstance) { + settingsInstance.destroy(); + settingsInstance = null; + } + }); + }; +}); diff --git a/src/controllers/user/subtitles.js b/src/controllers/user/subtitles.js index 81d949e1a9..205265efcd 100644 --- a/src/controllers/user/subtitles.js +++ b/src/controllers/user/subtitles.js @@ -1,26 +1,48 @@ -define(["subtitleSettings", "userSettingsBuilder", "userSettings"], function(SubtitleSettings, userSettingsBuilder, currentUserSettings) { +define(["subtitleSettings", "userSettingsBuilder", "userSettings"], function (SubtitleSettings, userSettingsBuilder, currentUserSettings) { "use strict"; - return function(view, params) { + + return function (view, params) { function onBeforeUnload(e) { - hasChanges && (e.returnValue = "You currently have unsaved changes. Are you sure you wish to leave?") + if (hasChanges) { + e.returnValue = "You currently have unsaved changes. Are you sure you wish to leave?"; + } } - var subtitleSettingsInstance, hasChanges, userId = params.userId || ApiClient.getCurrentUserId(), - userSettings = userId === ApiClient.getCurrentUserId() ? currentUserSettings : new userSettingsBuilder; - view.addEventListener("viewshow", function() { - window.addEventListener("beforeunload", onBeforeUnload), subtitleSettingsInstance ? subtitleSettingsInstance.loadData() : subtitleSettingsInstance = new SubtitleSettings({ - serverId: ApiClient.serverId(), - userId: userId, - element: view.querySelector(".settingsContainer"), - userSettings: userSettings, - enableSaveButton: !1, - enableSaveConfirmation: !1 - }) - }), view.addEventListener("change", function() { - hasChanges = !0 - }), view.addEventListener("viewbeforehide", function() { - hasChanges = !1, subtitleSettingsInstance && subtitleSettingsInstance.submit() - }), view.addEventListener("viewdestroy", function() { - subtitleSettingsInstance && (subtitleSettingsInstance.destroy(), subtitleSettingsInstance = null) - }) - } -}); \ No newline at end of file + + var subtitleSettingsInstance; + var hasChanges; + var userId = params.userId || ApiClient.getCurrentUserId(); + var userSettings = userId === ApiClient.getCurrentUserId() ? currentUserSettings : new userSettingsBuilder(); + view.addEventListener("viewshow", function () { + window.addEventListener("beforeunload", onBeforeUnload); + + if (subtitleSettingsInstance) { + subtitleSettingsInstance.loadData(); + } else { + subtitleSettingsInstance = new SubtitleSettings({ + serverId: ApiClient.serverId(), + userId: userId, + element: view.querySelector(".settingsContainer"), + userSettings: userSettings, + enableSaveButton: false, + enableSaveConfirmation: false + }); + } + }); + view.addEventListener("change", function () { + hasChanges = true; + }); + view.addEventListener("viewbeforehide", function () { + hasChanges = false; + + if (subtitleSettingsInstance) { + subtitleSettingsInstance.submit(); + } + }); + view.addEventListener("viewdestroy", function () { + if (subtitleSettingsInstance) { + subtitleSettingsInstance.destroy(); + subtitleSettingsInstance = null; + } + }); + }; +}); diff --git a/src/controllers/useredit.js b/src/controllers/useredit.js index 0709e8dae9..fb6a3f94cd 100644 --- a/src/controllers/useredit.js +++ b/src/controllers/useredit.js @@ -1,53 +1,84 @@ -define(["jQuery", "loading", "libraryMenu", "fnchecked"], function($, loading, libraryMenu) { +define(["jQuery", "loading", "libraryMenu", "fnchecked"], function ($, loading, libraryMenu) { "use strict"; function loadDeleteFolders(page, user, mediaFolders) { ApiClient.getJSON(ApiClient.getUrl("Channels", { - SupportsMediaDeletion: !0 - })).then(function(channelsResult) { - var i, length, folder, isChecked, checkedAttribute, html = ""; - for (i = 0, length = mediaFolders.length; i < length; i++) folder = mediaFolders[i], isChecked = user.Policy.EnableContentDeletion || -1 != user.Policy.EnableContentDeletionFromFolders.indexOf(folder.Id), checkedAttribute = isChecked ? ' checked="checked"' : "", html += '"; - for (i = 0, length = channelsResult.Items.length; i < length; i++) folder = channelsResult.Items[i], isChecked = user.Policy.EnableContentDeletion || -1 != user.Policy.EnableContentDeletionFromFolders.indexOf(folder.Id), checkedAttribute = isChecked ? ' checked="checked"' : "", html += '"; - $(".deleteAccess", page).html(html).trigger("create"), $("#chkEnableDeleteAllFolders", page).checked(user.Policy.EnableContentDeletion).trigger("change") - }) + SupportsMediaDeletion: true + })).then(function (channelsResult) { + var i; + var length; + var folder; + var isChecked; + var checkedAttribute; + var html = ""; + + for (i = 0, length = mediaFolders.length; i < length; i++) { + folder = mediaFolders[i]; + isChecked = user.Policy.EnableContentDeletion || -1 != user.Policy.EnableContentDeletionFromFolders.indexOf(folder.Id); + checkedAttribute = isChecked ? ' checked="checked"' : ""; + html += '"; + } + + for (i = 0, length = channelsResult.Items.length; i < length; i++) { + folder = channelsResult.Items[i]; + isChecked = user.Policy.EnableContentDeletion || -1 != user.Policy.EnableContentDeletionFromFolders.indexOf(folder.Id); + checkedAttribute = isChecked ? ' checked="checked"' : ""; + html += '"; + } + + $(".deleteAccess", page).html(html).trigger("create"); + $("#chkEnableDeleteAllFolders", page).checked(user.Policy.EnableContentDeletion).trigger("change"); + }); } function loadAuthProviders(page, user, providers) { - providers.length > 1 ? page.querySelector(".fldSelectLoginProvider").classList.remove("hide") : page.querySelector(".fldSelectLoginProvider").classList.add("hide"); + if (providers.length > 1) { + page.querySelector(".fldSelectLoginProvider").classList.remove("hide"); + } else { + page.querySelector(".fldSelectLoginProvider").classList.add("hide"); + } + var currentProviderId = user.Policy.AuthenticationProviderId; - page.querySelector(".selectLoginProvider").innerHTML = providers.map(function(provider) { + page.querySelector(".selectLoginProvider").innerHTML = providers.map(function (provider) { var selected = provider.Id === currentProviderId || providers.length < 2 ? " selected" : ""; - return '" - }) + return '"; + }); } function loadPasswordResetProviders(page, user, providers) { - providers.length > 1 ? page.querySelector(".fldSelectPasswordResetProvider").classList.remove("hide") : page.querySelector(".fldSelectPasswordResetProvider").classList.add("hide"); + if (providers.length > 1) { + page.querySelector(".fldSelectPasswordResetProvider").classList.remove("hide"); + } else { + page.querySelector(".fldSelectPasswordResetProvider").classList.add("hide"); + } + var currentProviderId = user.Policy.PasswordResetProviderId; - page.querySelector(".selectPasswordResetProvider").innerHTML = providers.map(function(provider) { - var selected = (provider.Id === currentProviderId || providers.length < 2) ? " selected" : ""; - return '" - }) + page.querySelector(".selectPasswordResetProvider").innerHTML = providers.map(function (provider) { + var selected = provider.Id === currentProviderId || providers.length < 2 ? " selected" : ""; + return '"; + }); } function loadUser(page, user) { currentUser = user; - ApiClient.getJSON(ApiClient.getUrl("Auth/Providers")).then(function(providers) { - loadAuthProviders(page, user, providers) + ApiClient.getJSON(ApiClient.getUrl("Auth/Providers")).then(function (providers) { + loadAuthProviders(page, user, providers); }); - ApiClient.getJSON(ApiClient.getUrl("Auth/PasswordResetProviders")).then(function(providers) { - loadPasswordResetProviders(page, user, providers) + ApiClient.getJSON(ApiClient.getUrl("Auth/PasswordResetProviders")).then(function (providers) { + loadPasswordResetProviders(page, user, providers); }); ApiClient.getJSON(ApiClient.getUrl("Library/MediaFolders", { - IsHidden: false - })).then(function(folders) { - loadDeleteFolders(page, user, folders.Items) + IsHidden: false + })).then(function (folders) { + loadDeleteFolders(page, user, folders.Items); }); + if (user.Policy.IsDisabled) { $(".disabledUserBanner", page).show(); } else { $(".disabledUserBanner", page).hide(); } + $("#txtUserName", page).prop("disabled", "").removeAttr("disabled"); $("#fldConnectInfo", page).show(); $(".lnkEditUserPreferences", page).attr("href", "mypreferencesmenu.html?userId=" + user.Id); @@ -78,7 +109,8 @@ define(["jQuery", "loading", "libraryMenu", "fnchecked"], function($, loading, l function onSaveComplete(page, user) { Dashboard.navigate("userprofiles.html"); loading.hide(); - require(["toast"], function(toast) { + + require(["toast"], function (toast) { toast(Globalize.translate("SettingsSaved")); }); } @@ -106,45 +138,59 @@ define(["jQuery", "loading", "libraryMenu", "fnchecked"], function($, loading, l user.Policy.AuthenticationProviderId = page.querySelector(".selectLoginProvider").value; user.Policy.PasswordResetProviderId = page.querySelector(".selectPasswordResetProvider").value; user.Policy.EnableContentDeletion = $("#chkEnableDeleteAllFolders", page).checked(); - user.Policy.EnableContentDeletionFromFolders = user.Policy.EnableContentDeletion ? [] : $(".chkFolder", page).get().filter(function(c) { - return c.checked - }).map(function(c) { - return c.getAttribute("data-id") + user.Policy.EnableContentDeletionFromFolders = user.Policy.EnableContentDeletion ? [] : $(".chkFolder", page).get().filter(function (c) { + return c.checked; + }).map(function (c) { + return c.getAttribute("data-id"); + }); + ApiClient.updateUser(user).then(function () { + ApiClient.updateUserPolicy(user.Id, user.Policy).then(function () { + onSaveComplete(page, user); + }); }); - ApiClient.updateUser(user).then(function() { - ApiClient.updateUserPolicy(user.Id, user.Policy).then(function() { - onSaveComplete(page, user) - }) - }) } function onSubmit() { var page = $(this).parents(".page")[0]; - return loading.show(), getUser().then(function(result) { - saveUser(result, page) - }), !1 + loading.show(); + getUser().then(function (result) { + saveUser(result, page); + }); + return false; } function getUser() { var userId = getParameterByName("userId"); - return ApiClient.getUser(userId) + return ApiClient.getUser(userId); } function loadData(page) { - loading.show(), getUser().then(function(user) { - loadUser(page, user) - }) + loading.show(); + getUser().then(function (user) { + loadUser(page, user); + }); } + var currentUser; - $(document).on("pageinit", "#editUserPage", function() { - $(".editUserProfileForm").off("submit", onSubmit).on("submit", onSubmit), this.querySelector(".sharingHelp").innerHTML = Globalize.translate("OptionAllowLinkSharingHelp", 30); + $(document).on("pageinit", "#editUserPage", function () { + $(".editUserProfileForm").off("submit", onSubmit).on("submit", onSubmit); + this.querySelector(".sharingHelp").innerHTML = Globalize.translate("OptionAllowLinkSharingHelp", 30); var page = this; - $("#chkEnableDeleteAllFolders", this).on("change", function() { - this.checked ? $(".deleteAccess", page).hide() : $(".deleteAccess", page).show() - }), ApiClient.getServerConfiguration().then(function(config) { - config.EnableRemoteAccess ? page.querySelector(".fldRemoteAccess").classList.remove("hide") : page.querySelector(".fldRemoteAccess").classList.add("hide") - }) - }).on("pagebeforeshow", "#editUserPage", function() { - loadData(this) - }) + $("#chkEnableDeleteAllFolders", this).on("change", function () { + if (this.checked) { + $(".deleteAccess", page).hide(); + } else { + $(".deleteAccess", page).show(); + } + }); + ApiClient.getServerConfiguration().then(function (config) { + if (config.EnableRemoteAccess) { + page.querySelector(".fldRemoteAccess").classList.remove("hide"); + } else { + page.querySelector(".fldRemoteAccess").classList.add("hide"); + } + }); + }).on("pagebeforeshow", "#editUserPage", function () { + loadData(this); + }); }); diff --git a/src/controllers/userlibraryaccess.js b/src/controllers/userlibraryaccess.js index 8352e90c3e..38418f5190 100644 --- a/src/controllers/userlibraryaccess.js +++ b/src/controllers/userlibraryaccess.js @@ -1,112 +1,178 @@ -define(["jQuery", "loading", "libraryMenu", "fnchecked"], function($, loading, libraryMenu) { +define(["jQuery", "loading", "libraryMenu", "fnchecked"], function ($, loading, libraryMenu) { "use strict"; function triggerChange(select) { var evt = document.createEvent("HTMLEvents"); - evt.initEvent("change", !1, !0), select.dispatchEvent(evt) + evt.initEvent("change", false, true); + select.dispatchEvent(evt); } function loadMediaFolders(page, user, mediaFolders) { var html = ""; - html += '

' + Globalize.translate("HeaderLibraries") + "

", html += '
'; + html += '

' + Globalize.translate("HeaderLibraries") + "

"; + html += '
'; + for (var i = 0, length = mediaFolders.length; i < length; i++) { - var folder = mediaFolders[i], - isChecked = user.Policy.EnableAllFolders || -1 != user.Policy.EnabledFolders.indexOf(folder.Id), - checkedAttribute = isChecked ? ' checked="checked"' : ""; - html += '" + var folder = mediaFolders[i]; + var isChecked = user.Policy.EnableAllFolders || -1 != user.Policy.EnabledFolders.indexOf(folder.Id); + var checkedAttribute = isChecked ? ' checked="checked"' : ""; + html += '"; } - html += "
", page.querySelector(".folderAccess").innerHTML = html; + + html += "
"; + page.querySelector(".folderAccess").innerHTML = html; var chkEnableAllFolders = page.querySelector("#chkEnableAllFolders"); - chkEnableAllFolders.checked = user.Policy.EnableAllFolders, triggerChange(chkEnableAllFolders) + chkEnableAllFolders.checked = user.Policy.EnableAllFolders; + triggerChange(chkEnableAllFolders); } function loadChannels(page, user, channels) { var html = ""; - html += '

' + Globalize.translate("HeaderChannels") + "

", html += '
'; + html += '

' + Globalize.translate("HeaderChannels") + "

"; + html += '
'; + for (var i = 0, length = channels.length; i < length; i++) { - var folder = channels[i], - isChecked = user.Policy.EnableAllChannels || -1 != user.Policy.EnabledChannels.indexOf(folder.Id), - checkedAttribute = isChecked ? ' checked="checked"' : ""; - html += '" + var folder = channels[i]; + var isChecked = user.Policy.EnableAllChannels || -1 != user.Policy.EnabledChannels.indexOf(folder.Id); + var checkedAttribute = isChecked ? ' checked="checked"' : ""; + html += '"; } - html += "
", $(".channelAccess", page).show().html(html), channels.length ? $(".channelAccessContainer", page).show() : $(".channelAccessContainer", page).hide(), $("#chkEnableAllChannels", page).checked(user.Policy.EnableAllChannels).trigger("change") + + html += "
"; + $(".channelAccess", page).show().html(html); + + if (channels.length) { + $(".channelAccessContainer", page).show(); + } else { + $(".channelAccessContainer", page).hide(); + } + + $("#chkEnableAllChannels", page).checked(user.Policy.EnableAllChannels).trigger("change"); } function loadDevices(page, user, devices) { var html = ""; - html += '

' + Globalize.translate("HeaderDevices") + "

", html += '
'; + html += '

' + Globalize.translate("HeaderDevices") + "

"; + html += '
'; + for (var i = 0, length = devices.length; i < length; i++) { - var device = devices[i], - checkedAttribute = user.Policy.EnableAllDevices || -1 != user.Policy.EnabledDevices.indexOf(device.Id) ? ' checked="checked"' : ""; - html += '" + var device = devices[i]; + var checkedAttribute = user.Policy.EnableAllDevices || -1 != user.Policy.EnabledDevices.indexOf(device.Id) ? ' checked="checked"' : ""; + html += '"; + } + + html += "
"; + $(".deviceAccess", page).show().html(html); + $("#chkEnableAllDevices", page).checked(user.Policy.EnableAllDevices).trigger("change"); + + if (user.Policy.IsAdministrator) { + page.querySelector(".deviceAccessContainer").classList.add("hide"); + } else { + page.querySelector(".deviceAccessContainer").classList.remove("hide"); } - html += "
", $(".deviceAccess", page).show().html(html), $("#chkEnableAllDevices", page).checked(user.Policy.EnableAllDevices).trigger("change"), user.Policy.IsAdministrator ? page.querySelector(".deviceAccessContainer").classList.add("hide") : page.querySelector(".deviceAccessContainer").classList.remove("hide") } function loadUser(page, user, loggedInUser, mediaFolders, channels, devices) { - page.querySelector(".username").innerHTML = user.Name, libraryMenu.setTitle(user.Name), loadChannels(page, user, channels), loadMediaFolders(page, user, mediaFolders), loadDevices(page, user, devices), loading.hide() + page.querySelector(".username").innerHTML = user.Name; + libraryMenu.setTitle(user.Name); + loadChannels(page, user, channels); + loadMediaFolders(page, user, mediaFolders); + loadDevices(page, user, devices); + loading.hide(); } function onSaveComplete(page) { - loading.hide(), require(["toast"], function(toast) { - toast(Globalize.translate("SettingsSaved")) - }) + loading.hide(); + + require(["toast"], function (toast) { + toast(Globalize.translate("SettingsSaved")); + }); } function saveUser(user, page) { - user.Policy.EnableAllFolders = $("#chkEnableAllFolders", page).checked(), user.Policy.EnabledFolders = user.Policy.EnableAllFolders ? [] : $(".chkFolder", page).get().filter(function(c) { - return c.checked - }).map(function(c) { - return c.getAttribute("data-id") - }), user.Policy.EnableAllChannels = $("#chkEnableAllChannels", page).checked(), user.Policy.EnabledChannels = user.Policy.EnableAllChannels ? [] : $(".chkChannel", page).get().filter(function(c) { - return c.checked - }).map(function(c) { - return c.getAttribute("data-id") - }), user.Policy.EnableAllDevices = $("#chkEnableAllDevices", page).checked(), user.Policy.EnabledDevices = user.Policy.EnableAllDevices ? [] : $(".chkDevice", page).get().filter(function(c) { - return c.checked - }).map(function(c) { - return c.getAttribute("data-id") - }), user.Policy.BlockedChannels = null, user.Policy.BlockedMediaFolders = null, ApiClient.updateUserPolicy(user.Id, user.Policy).then(function() { - onSaveComplete(page) - }) + user.Policy.EnableAllFolders = $("#chkEnableAllFolders", page).checked(); + user.Policy.EnabledFolders = user.Policy.EnableAllFolders ? [] : $(".chkFolder", page).get().filter(function (c) { + return c.checked; + }).map(function (c) { + return c.getAttribute("data-id"); + }); + user.Policy.EnableAllChannels = $("#chkEnableAllChannels", page).checked(); + user.Policy.EnabledChannels = user.Policy.EnableAllChannels ? [] : $(".chkChannel", page).get().filter(function (c) { + return c.checked; + }).map(function (c) { + return c.getAttribute("data-id"); + }); + user.Policy.EnableAllDevices = $("#chkEnableAllDevices", page).checked(); + user.Policy.EnabledDevices = user.Policy.EnableAllDevices ? [] : $(".chkDevice", page).get().filter(function (c) { + return c.checked; + }).map(function (c) { + return c.getAttribute("data-id"); + }); + user.Policy.BlockedChannels = null; + user.Policy.BlockedMediaFolders = null; + ApiClient.updateUserPolicy(user.Id, user.Policy).then(function () { + onSaveComplete(page); + }); } function onSubmit() { var page = $(this).parents(".page"); loading.show(); var userId = getParameterByName("userId"); - return ApiClient.getUser(userId).then(function(result) { - saveUser(result, page) - }), !1 + ApiClient.getUser(userId).then(function (result) { + saveUser(result, page); + }); + return false; } - $(document).on("pageinit", "#userLibraryAccessPage", function() { + + $(document).on("pageinit", "#userLibraryAccessPage", function () { var page = this; - $("#chkEnableAllDevices", page).on("change", function() { - this.checked ? $(".deviceAccessListContainer", page).hide() : $(".deviceAccessListContainer", page).show() - }), $("#chkEnableAllChannels", page).on("change", function() { - this.checked ? $(".channelAccessListContainer", page).hide() : $(".channelAccessListContainer", page).show() - }), page.querySelector("#chkEnableAllFolders").addEventListener("change", function() { - this.checked ? page.querySelector(".folderAccessListContainer").classList.add("hide") : page.querySelector(".folderAccessListContainer").classList.remove("hide") - }), $(".userLibraryAccessForm").off("submit", onSubmit).on("submit", onSubmit) - }).on("pageshow", "#userLibraryAccessPage", function() { + $("#chkEnableAllDevices", page).on("change", function () { + if (this.checked) { + $(".deviceAccessListContainer", page).hide(); + } else { + $(".deviceAccessListContainer", page).show(); + } + }); + $("#chkEnableAllChannels", page).on("change", function () { + if (this.checked) { + $(".channelAccessListContainer", page).hide(); + } else { + $(".channelAccessListContainer", page).show(); + } + }); + page.querySelector("#chkEnableAllFolders").addEventListener("change", function () { + if (this.checked) { + page.querySelector(".folderAccessListContainer").classList.add("hide"); + } else { + page.querySelector(".folderAccessListContainer").classList.remove("hide"); + } + }); + $(".userLibraryAccessForm").off("submit", onSubmit).on("submit", onSubmit); + }).on("pageshow", "#userLibraryAccessPage", function () { var page = this; loading.show(); - var promise1, userId = getParameterByName("userId"); - if (userId) promise1 = ApiClient.getUser(userId); - else { + var promise1; + var userId = getParameterByName("userId"); + + if (userId) { + promise1 = ApiClient.getUser(userId); + } else { var deferred = $.Deferred(); deferred.resolveWith(null, [{ Configuration: {} - }]), promise1 = deferred.promise() + }]); + promise1 = deferred.promise(); } - var promise2 = Dashboard.getCurrentUser(), - promise4 = ApiClient.getJSON(ApiClient.getUrl("Library/MediaFolders", { - IsHidden: !1 - })), - promise5 = ApiClient.getJSON(ApiClient.getUrl("Channels")), - promise6 = ApiClient.getJSON(ApiClient.getUrl("Devices")); - Promise.all([promise1, promise2, promise4, promise5, promise6]).then(function(responses) { - loadUser(page, responses[0], responses[1], responses[2].Items, responses[3].Items, responses[4].Items) - }) - }) -}); \ No newline at end of file + + var promise2 = Dashboard.getCurrentUser(); + var promise4 = ApiClient.getJSON(ApiClient.getUrl("Library/MediaFolders", { + IsHidden: false + })); + var promise5 = ApiClient.getJSON(ApiClient.getUrl("Channels")); + var promise6 = ApiClient.getJSON(ApiClient.getUrl("Devices")); + Promise.all([promise1, promise2, promise4, promise5, promise6]).then(function (responses) { + loadUser(page, responses[0], responses[1], responses[2].Items, responses[3].Items, responses[4].Items); + }); + }); +}); diff --git a/src/controllers/usernew.js b/src/controllers/usernew.js index 10fa6fc4f3..ec80679f8c 100644 --- a/src/controllers/usernew.js +++ b/src/controllers/usernew.js @@ -1,14 +1,16 @@ -define(["jQuery", "loading", "fnchecked", "emby-checkbox"], function($, loading) { +define(["jQuery", "loading", "fnchecked", "emby-checkbox"], function ($, loading) { "use strict"; function loadMediaFolders(page, mediaFolders) { var html = ""; html += '

' + Globalize.translate("HeaderLibraries") + "

"; html += '
'; + for (var i = 0; i < mediaFolders.length; i++) { var folder = mediaFolders[i]; html += '"; } + html += "
"; $(".folderAccess", page).html(html).trigger("create"); $("#chkEnableAllFolders", page).checked(true).trigger("change"); @@ -18,17 +20,21 @@ define(["jQuery", "loading", "fnchecked", "emby-checkbox"], function($, loading) var html = ""; html += '

' + Globalize.translate("HeaderChannels") + "

"; html += '
'; + for (var i = 0; i < channels.length; i++) { var folder = channels[i]; html += '"; } + html += "
"; $(".channelAccess", page).show().html(html).trigger("create"); + if (channels.length) { $(".channelAccessContainer", page).show(); } else { $(".channelAccessContainer", page).hide(); } + $("#chkEnableAllChannels", page).checked(true).trigger("change"); } @@ -37,46 +43,51 @@ define(["jQuery", "loading", "fnchecked", "emby-checkbox"], function($, loading) $("#txtPassword", page).val(""); loading.show(); var promiseFolders = ApiClient.getJSON(ApiClient.getUrl("Library/MediaFolders", { - IsHidden: false + IsHidden: false })); var promiseChannels = ApiClient.getJSON(ApiClient.getUrl("Channels")); - Promise.all([promiseFolders, promiseChannels]).then(function(responses) { + Promise.all([promiseFolders, promiseChannels]).then(function (responses) { loadMediaFolders(page, responses[0].Items); loadChannels(page, responses[1].Items); loading.hide(); - }) + }); } function saveUser(page) { var user = {}; user.Name = $("#txtUsername", page).val(); user.Password = $("#txtPassword", page).val(); - ApiClient.createUser(user).then(function(user) { + ApiClient.createUser(user).then(function (user) { user.Policy.EnableAllFolders = $("#chkEnableAllFolders", page).checked(); user.Policy.EnabledFolders = []; + if (!user.Policy.EnableAllFolders) { - user.Policy.EnabledFolders = $(".chkFolder", page).get().filter(function(i) { - return i.checked - }).map(function(i) { + user.Policy.EnabledFolders = $(".chkFolder", page).get().filter(function (i) { + return i.checked; + }).map(function (i) { return i.getAttribute("data-id"); }); } + user.Policy.EnableAllChannels = $("#chkEnableAllChannels", page).checked(); user.Policy.EnabledChannels = []; + if (!user.Policy.EnableAllChannels) { - user.Policy.EnabledChannels = $(".chkChannel", page).get().filter(function(i) { - return i.checked - }).map(function(i) { + user.Policy.EnabledChannels = $(".chkChannel", page).get().filter(function (i) { + return i.checked; + }).map(function (i) { return i.getAttribute("data-id"); }); } - ApiClient.updateUserPolicy(user.Id, user.Policy).then(function() { + + ApiClient.updateUserPolicy(user.Id, user.Policy).then(function () { Dashboard.navigate("useredit.html?userId=" + user.Id); }); - }, function(response) { - require(["toast"], function(toast) { + }, function (response) { + require(["toast"], function (toast) { toast(Globalize.translate("DefaultErrorMessage")); }); + loading.hide(); }); } @@ -92,16 +103,16 @@ define(["jQuery", "loading", "fnchecked", "emby-checkbox"], function($, loading) loadUser(page); } - $(document).on("pageinit", "#newUserPage", function() { + $(document).on("pageinit", "#newUserPage", function () { var page = this; - $("#chkEnableAllChannels", page).on("change", function() { + $("#chkEnableAllChannels", page).on("change", function () { if (this.checked) { $(".channelAccessListContainer", page).hide(); } else { $(".channelAccessListContainer", page).show(); } }); - $("#chkEnableAllFolders", page).on("change", function() { + $("#chkEnableAllFolders", page).on("change", function () { if (this.checked) { $(".folderAccessListContainer", page).hide(); } else { @@ -109,7 +120,7 @@ define(["jQuery", "loading", "fnchecked", "emby-checkbox"], function($, loading) } }); $(".newUserProfileForm").off("submit", onSubmit).on("submit", onSubmit); - }).on("pageshow", "#newUserPage", function() { + }).on("pageshow", "#newUserPage", function () { loadData(this); }); -}); \ No newline at end of file +}); diff --git a/src/controllers/userparentalcontrol.js b/src/controllers/userparentalcontrol.js index 381dc8cea9..2a862912d5 100644 --- a/src/controllers/userparentalcontrol.js +++ b/src/controllers/userparentalcontrol.js @@ -1,185 +1,271 @@ -define(["jQuery", "datetime", "loading", "libraryMenu", "listViewStyle", "paper-icon-button-light"], function($, datetime, loading, libraryMenu) { +define(["jQuery", "datetime", "loading", "libraryMenu", "listViewStyle", "paper-icon-button-light"], function ($, datetime, loading, libraryMenu) { "use strict"; function populateRatings(allParentalRatings, page) { var html = ""; html += ""; - var i, length, rating, ratings = []; + var i; + var length; + var rating; + var ratings = []; + for (i = 0, length = allParentalRatings.length; i < length; i++) { if (rating = allParentalRatings[i], ratings.length) { var lastRating = ratings[ratings.length - 1]; + if (lastRating.Value === rating.Value) { lastRating.Name += "/" + rating.Name; - continue + continue; } } + ratings.push({ Name: rating.Name, Value: rating.Value - }) + }); } - for (i = 0, length = ratings.length; i < length; i++) rating = ratings[i], html += ""; - $("#selectMaxParentalRating", page).html(html) + + for (i = 0, length = ratings.length; i < length; i++) { + rating = ratings[i]; + html += ""; + } + + $("#selectMaxParentalRating", page).html(html); } function loadUnratedItems(page, user) { var items = [{ - name: Globalize.translate("OptionBlockBooks"), - value: "Book" - }, { - name: Globalize.translate("OptionBlockChannelContent"), - value: "ChannelContent" - }, { - name: Globalize.translate("OptionBlockLiveTvChannels"), - value: "LiveTvChannel" - }, { - name: Globalize.translate("OptionBlockMovies"), - value: "Movie" - }, { - name: Globalize.translate("OptionBlockMusic"), - value: "Music" - }, { - name: Globalize.translate("OptionBlockTrailers"), - value: "Trailer" - }, { - name: Globalize.translate("OptionBlockTvShows"), - value: "Series" - }], - html = ""; - html += '

' + Globalize.translate("HeaderBlockItemsWithNoRating") + "

", html += '
'; + name: Globalize.translate("OptionBlockBooks"), + value: "Book" + }, { + name: Globalize.translate("OptionBlockChannelContent"), + value: "ChannelContent" + }, { + name: Globalize.translate("OptionBlockLiveTvChannels"), + value: "LiveTvChannel" + }, { + name: Globalize.translate("OptionBlockMovies"), + value: "Movie" + }, { + name: Globalize.translate("OptionBlockMusic"), + value: "Music" + }, { + name: Globalize.translate("OptionBlockTrailers"), + value: "Trailer" + }, { + name: Globalize.translate("OptionBlockTvShows"), + value: "Series" + }]; + var html = ""; + html += '

' + Globalize.translate("HeaderBlockItemsWithNoRating") + "

"; + html += '
'; + for (var i = 0, length = items.length; i < length; i++) { - var item = items[i], - checkedAttribute = -1 != user.Policy.BlockUnratedItems.indexOf(item.value) ? ' checked="checked"' : ""; - html += '" + var item = items[i]; + var checkedAttribute = -1 != user.Policy.BlockUnratedItems.indexOf(item.value) ? ' checked="checked"' : ""; + html += '"; } - html += "
", $(".blockUnratedItems", page).html(html).trigger("create") + + html += "
"; + $(".blockUnratedItems", page).html(html).trigger("create"); } function loadUser(page, user, allParentalRatings) { - page.querySelector(".username").innerHTML = user.Name, libraryMenu.setTitle(user.Name), loadUnratedItems(page, user), loadBlockedTags(page, user.Policy.BlockedTags), populateRatings(allParentalRatings, page); + page.querySelector(".username").innerHTML = user.Name; + libraryMenu.setTitle(user.Name); + loadUnratedItems(page, user); + loadBlockedTags(page, user.Policy.BlockedTags); + populateRatings(allParentalRatings, page); var ratingValue = ""; - if (user.Policy.MaxParentalRating) + + if (user.Policy.MaxParentalRating) { for (var i = 0, length = allParentalRatings.length; i < length; i++) { var rating = allParentalRatings[i]; - user.Policy.MaxParentalRating >= rating.Value && (ratingValue = rating.Value) + + if (user.Policy.MaxParentalRating >= rating.Value) { + ratingValue = rating.Value; + } } - $("#selectMaxParentalRating", page).val(ratingValue), user.Policy.IsAdministrator ? $(".accessScheduleSection", page).hide() : $(".accessScheduleSection", page).show(), renderAccessSchedule(page, user.Policy.AccessSchedules || []), loading.hide() + } + + $("#selectMaxParentalRating", page).val(ratingValue); + + if (user.Policy.IsAdministrator) { + $(".accessScheduleSection", page).hide(); + } else { + $(".accessScheduleSection", page).show(); + } + + renderAccessSchedule(page, user.Policy.AccessSchedules || []); + loading.hide(); } function loadBlockedTags(page, tags) { - var html = tags.map(function(h) { + var html = tags.map(function (h) { var li = '
'; - return li += '
', li += '

', li += h, li += "

", li += "
", li += '', li += "
" + li += '
'; + li += '

'; + li += h; + li += "

"; + li += "
"; + li += ''; + return li += "
"; }).join(""); - html && (html = '
' + html + "
"); + + if (html) { + html = '
' + html + "
"; + } + var elem = $(".blockedTags", page).html(html).trigger("create"); - $(".btnDeleteTag", elem).on("click", function() { - var tag = this.getAttribute("data-tag"), - newTags = tags.filter(function(t) { - return t != tag - }); - loadBlockedTags(page, newTags) - }) + $(".btnDeleteTag", elem).on("click", function () { + var tag = this.getAttribute("data-tag"); + var newTags = tags.filter(function (t) { + return t != tag; + }); + loadBlockedTags(page, newTags); + }); } function deleteAccessSchedule(page, schedules, index) { - schedules.splice(index, 1), renderAccessSchedule(page, schedules) + schedules.splice(index, 1); + renderAccessSchedule(page, schedules); } function renderAccessSchedule(page, schedules) { - var html = "", - index = 0; - html += schedules.map(function(a) { + var html = ""; + var index = 0; + html += schedules.map(function (a) { var itemHtml = ""; - return itemHtml += '
', itemHtml += '
', itemHtml += '

', itemHtml += Globalize.translate("Option" + a.DayOfWeek), itemHtml += "

", itemHtml += '
' + getDisplayTime(a.StartHour) + " - " + getDisplayTime(a.EndHour) + "
", itemHtml += "
", itemHtml += '', itemHtml += "
", index++, itemHtml + itemHtml += '
'; + itemHtml += '
'; + itemHtml += '

'; + itemHtml += Globalize.translate("Option" + a.DayOfWeek); + itemHtml += "

"; + itemHtml += '
' + getDisplayTime(a.StartHour) + " - " + getDisplayTime(a.EndHour) + "
"; + itemHtml += "
"; + itemHtml += ''; + itemHtml += "
"; + index++; + return itemHtml; }).join(""); var accessScheduleList = page.querySelector(".accessScheduleList"); - accessScheduleList.innerHTML = html, $(".btnDelete", accessScheduleList).on("click", function() { - deleteAccessSchedule(page, schedules, parseInt(this.getAttribute("data-index"))) - }) + accessScheduleList.innerHTML = html; + $(".btnDelete", accessScheduleList).on("click", function () { + deleteAccessSchedule(page, schedules, parseInt(this.getAttribute("data-index"))); + }); } function onSaveComplete(page) { - loading.hide(), require(["toast"], function(toast) { - toast(Globalize.translate("SettingsSaved")) - }) + loading.hide(); + + require(["toast"], function (toast) { + toast(Globalize.translate("SettingsSaved")); + }); } function saveUser(user, page) { - user.Policy.MaxParentalRating = $("#selectMaxParentalRating", page).val() || null, user.Policy.BlockUnratedItems = $(".chkUnratedItem", page).get().filter(function(i) { - return i.checked - }).map(function(i) { - return i.getAttribute("data-itemtype") - }), user.Policy.AccessSchedules = getSchedulesFromPage(page), user.Policy.BlockedTags = getBlockedTagsFromPage(page), ApiClient.updateUserPolicy(user.Id, user.Policy).then(function() { - onSaveComplete(page) - }) + user.Policy.MaxParentalRating = $("#selectMaxParentalRating", page).val() || null; + user.Policy.BlockUnratedItems = $(".chkUnratedItem", page).get().filter(function (i) { + return i.checked; + }).map(function (i) { + return i.getAttribute("data-itemtype"); + }); + user.Policy.AccessSchedules = getSchedulesFromPage(page); + user.Policy.BlockedTags = getBlockedTagsFromPage(page); + ApiClient.updateUserPolicy(user.Id, user.Policy).then(function () { + onSaveComplete(page); + }); } function getDisplayTime(hours) { - var minutes = 0, - pct = hours % 1; - return pct && (minutes = parseInt(60 * pct)), datetime.getDisplayTime(new Date(2e3, 1, 1, hours, minutes, 0, 0)) + var minutes = 0; + var pct = hours % 1; + + if (pct) { + minutes = parseInt(60 * pct); + } + + return datetime.getDisplayTime(new Date(2000, 1, 1, hours, minutes, 0, 0)); } function showSchedulePopup(page, schedule, index) { - schedule = schedule || {}, require(["components/accessschedule/accessschedule"], function(accessschedule) { + schedule = schedule || {}; + + require(["components/accessschedule/accessschedule"], function (accessschedule) { accessschedule.show({ schedule: schedule - }).then(function(updatedSchedule) { - var schedules = getSchedulesFromPage(page); - 1 == index && (index = schedules.length), schedules[index] = updatedSchedule, renderAccessSchedule(page, schedules) - }) - }) + }).then(function (updatedSchedule) { + var schedules = getSchedulesFromPage(page); + + if (-1 == index) { + index = schedules.length; + } + + schedules[index] = updatedSchedule; + renderAccessSchedule(page, schedules); + }); + }); } function getSchedulesFromPage(page) { - return $(".liSchedule", page).map(function() { + return $(".liSchedule", page).map(function () { return { DayOfWeek: this.getAttribute("data-day"), StartHour: this.getAttribute("data-start"), EndHour: this.getAttribute("data-end") - } - }).get() + }; + }).get(); } function getBlockedTagsFromPage(page) { - return $(".blockedTag", page).map(function() { - return this.getAttribute("data-tag") - }).get() + return $(".blockedTag", page).map(function () { + return this.getAttribute("data-tag"); + }).get(); } function showBlockedTagPopup(page) { - require(["prompt"], function(prompt) { + require(["prompt"], function (prompt) { prompt({ label: Globalize.translate("LabelTag") - }).then(function(value) { - var tags = getBlockedTagsFromPage(page); - 1 == tags.indexOf(value) && (tags.push(value), loadBlockedTags(page, tags)) - }) - }) + }).then(function (value) { + var tags = getBlockedTagsFromPage(page); + + if (-1 == tags.indexOf(value)) { + tags.push(value); + loadBlockedTags(page, tags); + } + }); + }); } + window.UserParentalControlPage = { - onSubmit: function() { + onSubmit: function () { var page = $(this).parents(".page"); loading.show(); var userId = getParameterByName("userId"); - return ApiClient.getUser(userId).then(function(result) { - saveUser(result, page) - }), !1 + ApiClient.getUser(userId).then(function (result) { + saveUser(result, page); + }); + return false; } - }, $(document).on("pageinit", "#userParentalControlPage", function() { + }; + $(document).on("pageinit", "#userParentalControlPage", function () { var page = this; - $(".btnAddSchedule", page).on("click", function() { - showSchedulePopup(page, {}, -1) - }), $(".btnAddBlockedTag", page).on("click", function() { - showBlockedTagPopup(page) - }), $(".userParentalControlForm").off("submit", UserParentalControlPage.onSubmit).on("submit", UserParentalControlPage.onSubmit) - }).on("pageshow", "#userParentalControlPage", function() { + $(".btnAddSchedule", page).on("click", function () { + showSchedulePopup(page, {}, -1); + }); + $(".btnAddBlockedTag", page).on("click", function () { + showBlockedTagPopup(page); + }); + $(".userParentalControlForm").off("submit", UserParentalControlPage.onSubmit).on("submit", UserParentalControlPage.onSubmit); + }).on("pageshow", "#userParentalControlPage", function () { var page = this; loading.show(); - var userId = getParameterByName("userId"), - promise1 = ApiClient.getUser(userId), - promise2 = ApiClient.getParentalRatings(); - Promise.all([promise1, promise2]).then(function(responses) { - loadUser(page, responses[0], responses[1]) - }) - }) + var userId = getParameterByName("userId"); + var promise1 = ApiClient.getUser(userId); + var promise2 = ApiClient.getParentalRatings(); + Promise.all([promise1, promise2]).then(function (responses) { + loadUser(page, responses[0], responses[1]); + }); + }); }); diff --git a/src/controllers/userpasswordpage.js b/src/controllers/userpasswordpage.js index d1eef004f6..30ca063278 100644 --- a/src/controllers/userpasswordpage.js +++ b/src/controllers/userpasswordpage.js @@ -1,101 +1,183 @@ -define(["loading", "libraryMenu", "emby-button"], function(loading, libraryMenu) { +define(["loading", "libraryMenu", "emby-button"], function (loading, libraryMenu) { "use strict"; function loadUser(page, params) { var userid = params.userId; - ApiClient.getUser(userid).then(function(user) { - Dashboard.getCurrentUser().then(function(loggedInUser) { - libraryMenu.setTitle(user.Name), page.querySelector(".username").innerHTML = user.Name; - var showPasswordSection = !0, - showLocalAccessSection = !1; - "Guest" == user.ConnectLinkType ? (page.querySelector(".localAccessSection").classList.add("hide"), showPasswordSection = !1) : user.HasConfiguredPassword ? (page.querySelector("#btnResetPassword").classList.remove("hide"), page.querySelector("#fldCurrentPassword").classList.remove("hide"), showLocalAccessSection = !0) : (page.querySelector("#btnResetPassword").classList.add("hide"), page.querySelector("#fldCurrentPassword").classList.add("hide")), showPasswordSection && (loggedInUser.Policy.IsAdministrator || user.Policy.EnableUserPreferenceAccess) ? page.querySelector(".passwordSection").classList.remove("hide") : page.querySelector(".passwordSection").classList.add("hide"), showLocalAccessSection && (loggedInUser.Policy.IsAdministrator || user.Policy.EnableUserPreferenceAccess) ? page.querySelector(".localAccessSection").classList.remove("hide") : page.querySelector(".localAccessSection").classList.add("hide"); + ApiClient.getUser(userid).then(function (user) { + Dashboard.getCurrentUser().then(function (loggedInUser) { + libraryMenu.setTitle(user.Name); + page.querySelector(".username").innerHTML = user.Name; + var showPasswordSection = true; + var showLocalAccessSection = false; + + if ("Guest" == user.ConnectLinkType) { + page.querySelector(".localAccessSection").classList.add("hide"); + showPasswordSection = false; + } else if (user.HasConfiguredPassword) { + page.querySelector("#btnResetPassword").classList.remove("hide"); + page.querySelector("#fldCurrentPassword").classList.remove("hide"); + showLocalAccessSection = true; + } else { + page.querySelector("#btnResetPassword").classList.add("hide"); + page.querySelector("#fldCurrentPassword").classList.add("hide"); + } + + if (showPasswordSection && (loggedInUser.Policy.IsAdministrator || user.Policy.EnableUserPreferenceAccess)) { + page.querySelector(".passwordSection").classList.remove("hide"); + } else { + page.querySelector(".passwordSection").classList.add("hide"); + } + + if (showLocalAccessSection && (loggedInUser.Policy.IsAdministrator || user.Policy.EnableUserPreferenceAccess)) { + page.querySelector(".localAccessSection").classList.remove("hide"); + } else { + page.querySelector(".localAccessSection").classList.add("hide"); + } + var txtEasyPassword = page.querySelector("#txtEasyPassword"); - txtEasyPassword.value = "", user.HasConfiguredEasyPassword ? (txtEasyPassword.placeholder = "******", page.querySelector("#btnResetEasyPassword").classList.remove("hide")) : (txtEasyPassword.removeAttribute("placeholder"), txtEasyPassword.placeholder = "", page.querySelector("#btnResetEasyPassword").classList.add("hide")), page.querySelector(".chkEnableLocalEasyPassword").checked = user.Configuration.EnableLocalPassword - }) - }), page.querySelector("#txtCurrentPassword").value = "", page.querySelector("#txtNewPassword").value = "", page.querySelector("#txtNewPasswordConfirm").value = "" + txtEasyPassword.value = ""; + + if (user.HasConfiguredEasyPassword) { + txtEasyPassword.placeholder = "******"; + page.querySelector("#btnResetEasyPassword").classList.remove("hide"); + } else { + txtEasyPassword.removeAttribute("placeholder"); + txtEasyPassword.placeholder = ""; + page.querySelector("#btnResetEasyPassword").classList.add("hide"); + } + + page.querySelector(".chkEnableLocalEasyPassword").checked = user.Configuration.EnableLocalPassword; + }); + }); + page.querySelector("#txtCurrentPassword").value = ""; + page.querySelector("#txtNewPassword").value = ""; + page.querySelector("#txtNewPasswordConfirm").value = ""; } - return function(view, params) { + + return function (view, params) { function saveEasyPassword() { - var userId = params.userId, - easyPassword = view.querySelector("#txtEasyPassword").value; - easyPassword ? ApiClient.updateEasyPassword(userId, easyPassword).then(function() { - onEasyPasswordSaved(userId) - }) : onEasyPasswordSaved(userId) + var userId = params.userId; + var easyPassword = view.querySelector("#txtEasyPassword").value; + + if (easyPassword) { + ApiClient.updateEasyPassword(userId, easyPassword).then(function () { + onEasyPasswordSaved(userId); + }); + } else { + onEasyPasswordSaved(userId); + } } function onEasyPasswordSaved(userId) { - ApiClient.getUser(userId).then(function(user) { - user.Configuration.EnableLocalPassword = view.querySelector(".chkEnableLocalEasyPassword").checked, ApiClient.updateUserConfiguration(user.Id, user.Configuration).then(function() { - loading.hide(), require(["toast"], function(toast) { - toast(Globalize.translate("MessageSettingsSaved")) - }), loadUser(view, params) - }) - }) + ApiClient.getUser(userId).then(function (user) { + user.Configuration.EnableLocalPassword = view.querySelector(".chkEnableLocalEasyPassword").checked; + ApiClient.updateUserConfiguration(user.Id, user.Configuration).then(function () { + loading.hide(); + + require(["toast"], function (toast) { + toast(Globalize.translate("MessageSettingsSaved")); + }); + + loadUser(view, params); + }); + }); } function savePassword() { - var userId = params.userId, - currentPassword = view.querySelector("#txtCurrentPassword").value, - newPassword = view.querySelector("#txtNewPassword").value; + var userId = params.userId; + var currentPassword = view.querySelector("#txtCurrentPassword").value; + var newPassword = view.querySelector("#txtNewPassword").value; + if (view.querySelector("#fldCurrentPassword").classList.contains("hide")) { // Firefox does not respect autocomplete=off, so clear it if the field is supposed to be hidden (and blank) // This should only happen when user.HasConfiguredPassword is false, but this information is not passed on currentPassword = ""; } - ApiClient.updateUserPassword(userId, currentPassword, newPassword).then(function() { - loading.hide(), require(["toast"], function(toast) { - toast(Globalize.translate("PasswordSaved")) - }), loadUser(view, params) - }, function() { - loading.hide(), Dashboard.alert({ + + ApiClient.updateUserPassword(userId, currentPassword, newPassword).then(function () { + loading.hide(); + + require(["toast"], function (toast) { + toast(Globalize.translate("PasswordSaved")); + }); + + loadUser(view, params); + }, function () { + loading.hide(); + Dashboard.alert({ title: Globalize.translate("HeaderLoginFailure"), message: Globalize.translate("MessageInvalidUser") - }) - }) + }); + }); } function onSubmit(e) { var form = this; - return form.querySelector("#txtNewPassword").value != form.querySelector("#txtNewPasswordConfirm").value ? require(["toast"], function(toast) { - toast(Globalize.translate("PasswordMatchError")) - }) : (loading.show(), savePassword()), e.preventDefault(), !1 + + if (form.querySelector("#txtNewPassword").value != form.querySelector("#txtNewPasswordConfirm").value) { + require(["toast"], function (toast) { + toast(Globalize.translate("PasswordMatchError")); + }); + } else { + loading.show(); + savePassword(); + } + + e.preventDefault(); + return false; } function onLocalAccessSubmit(e) { - return loading.show(), saveEasyPassword(), e.preventDefault(), !1 + loading.show(); + saveEasyPassword(); + e.preventDefault(); + return false; } function resetPassword() { var msg = Globalize.translate("PasswordResetConfirmation"); - require(["confirm"], function(confirm) { - confirm(msg, Globalize.translate("PasswordResetHeader")).then(function() { + + require(["confirm"], function (confirm) { + confirm(msg, Globalize.translate("PasswordResetHeader")).then(function () { var userId = params.userId; - loading.show(), ApiClient.resetUserPassword(userId).then(function() { - loading.hide(), Dashboard.alert({ + loading.show(); + ApiClient.resetUserPassword(userId).then(function () { + loading.hide(); + Dashboard.alert({ message: Globalize.translate("PasswordResetComplete"), title: Globalize.translate("PasswordResetHeader") - }), loadUser(view, params) - }) - }) - }) + }); + loadUser(view, params); + }); + }); + }); } function resetEasyPassword() { var msg = Globalize.translate("PinCodeResetConfirmation"); - require(["confirm"], function(confirm) { - confirm(msg, Globalize.translate("HeaderPinCodeReset")).then(function() { + + require(["confirm"], function (confirm) { + confirm(msg, Globalize.translate("HeaderPinCodeReset")).then(function () { var userId = params.userId; - loading.show(), ApiClient.resetEasyPassword(userId).then(function() { - loading.hide(), Dashboard.alert({ + loading.show(); + ApiClient.resetEasyPassword(userId).then(function () { + loading.hide(); + Dashboard.alert({ message: Globalize.translate("PinCodeResetComplete"), title: Globalize.translate("HeaderPinCodeReset") - }), loadUser(view, params) - }) - }) - }) + }); + loadUser(view, params); + }); + }); + }); } - view.querySelector(".updatePasswordForm").addEventListener("submit", onSubmit), view.querySelector(".localAccessForm").addEventListener("submit", onLocalAccessSubmit), view.querySelector("#btnResetEasyPassword").addEventListener("click", resetEasyPassword), view.querySelector("#btnResetPassword").addEventListener("click", resetPassword), view.addEventListener("viewshow", function() { - loadUser(view, params) - }) - } + + view.querySelector(".updatePasswordForm").addEventListener("submit", onSubmit); + view.querySelector(".localAccessForm").addEventListener("submit", onLocalAccessSubmit); + view.querySelector("#btnResetEasyPassword").addEventListener("click", resetEasyPassword); + view.querySelector("#btnResetPassword").addEventListener("click", resetPassword); + view.addEventListener("viewshow", function () { + loadUser(view, params); + }); + }; }); diff --git a/src/controllers/wizardfinishpage.js b/src/controllers/wizardfinishpage.js index 180af64b58..8242a16cb4 100644 --- a/src/controllers/wizardfinishpage.js +++ b/src/controllers/wizardfinishpage.js @@ -6,7 +6,7 @@ define(["loading"], function (loading) { ApiClient.ajax({ url: ApiClient.getUrl("Startup/Complete"), type: "POST" - }).then(function() { + }).then(function () { loading.hide(); window.location.href = "index.html"; }); From af2b49ac303d36de2c107a0eeb98968679609cce Mon Sep 17 00:00:00 2001 From: grafixeyehero Date: Wed, 6 Nov 2019 19:25:24 +0300 Subject: [PATCH 119/162] change directory for almada and requrie,js --- src/scripts/apploader.js | 2 +- webpack.common.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/scripts/apploader.js b/src/scripts/apploader.js index 2328f88968..4b5d2e8eec 100644 --- a/src/scripts/apploader.js +++ b/src/scripts/apploader.js @@ -20,7 +20,7 @@ } injectScriptElement( - self.Promise ? "./bower_components/alameda.js" : "./bower_components/require.js", + self.Promise ? "./libraries/alameda.js" : "./libraries/require.js", function() { // onload of require library injectScriptElement("./scripts/site.js"); diff --git a/webpack.common.js b/webpack.common.js index 6e82da181e..75d8d311db 100644 --- a/webpack.common.js +++ b/webpack.common.js @@ -23,7 +23,7 @@ module.exports = { Assets.map(asset => { return { from: path.resolve(__dirname, `./node_modules/${asset}`), - to: path.resolve(__dirname, './dist/bower_components') + to: path.resolve(__dirname, './dist/libraries') }; }) ) From 863eb067c22b45a1416800d3dc2667d896dbf12a Mon Sep 17 00:00:00 2001 From: grafixeyehero Date: Thu, 7 Nov 2019 03:02:32 +0300 Subject: [PATCH 120/162] move assets to webpack.common.js --- assets.js | 6 ------ webpack.common.js | 7 ++++--- 2 files changed, 4 insertions(+), 9 deletions(-) delete mode 100644 assets.js diff --git a/assets.js b/assets.js deleted file mode 100644 index 98ec18c227..0000000000 --- a/assets.js +++ /dev/null @@ -1,6 +0,0 @@ -const JS = [ - 'alameda/alameda.js', - 'requirejs/require.js' -]; - -module.exports = [...JS]; diff --git a/webpack.common.js b/webpack.common.js index 75d8d311db..f0d03bc4cd 100644 --- a/webpack.common.js +++ b/webpack.common.js @@ -1,9 +1,10 @@ const path = require("path"); const { CleanWebpackPlugin} = require("clean-webpack-plugin"); const CopyPlugin = require("copy-webpack-plugin"); - -// assets.js -const Assets = require('./assets'); +const Assets = [ + "alameda/alameda.js", + "requirejs/require.js" +]; module.exports = { context: path.resolve(__dirname, "src"), From 321da7ae3ede9bdbc60fc86be39366388860a20d Mon Sep 17 00:00:00 2001 From: DJSweder Date: Fri, 8 Nov 2019 08:20:51 +0000 Subject: [PATCH 121/162] Translated using Weblate (Czech) Translation: Jellyfin/Jellyfin Web Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-web/cs/ --- src/strings/cs.json | 88 ++++++++++++++++++++++++++++----------------- 1 file changed, 55 insertions(+), 33 deletions(-) diff --git a/src/strings/cs.json b/src/strings/cs.json index 3d03fc9455..5d53076d31 100644 --- a/src/strings/cs.json +++ b/src/strings/cs.json @@ -13,7 +13,7 @@ "AllChannels": "Všechny kanály", "AllEpisodes": "Všechny epizody", "AllLanguages": "Všechny jazyky", - "AllowHWTranscodingHelp": "Pokud nastavíte, povolíte tuneru překódování v reálném čase. Může snížit zátěž překódovávání požadované Jellyfin serverem.", + "AllowHWTranscodingHelp": "Povolit tuneru překódování v reálném čase. Může snížit zátěž překódovávání požadované Jellyfin serverem.", "AlwaysPlaySubtitles": "Vždy zobrazit titulky", "AlwaysPlaySubtitlesHelp": "Titulky odpovídající jazykové předvolbě se načtou bez ohledu na jazyk audia.", "Anytime": "Kdykoliv", @@ -30,7 +30,7 @@ "BirthDateValue": "Narozen: {0}", "BirthLocation": "Místo narození", "BirthPlaceValue": "Místo narození: {0}", - "BookLibraryHelp": "Audio a textové knihy jsou podporovány. Přečtěte si {0}pravidla pro názvy knih v Jellyfin{1}.", + "BookLibraryHelp": "Audio a textové knihy jsou podporovány. Přečtěte si {0}pravidla pro názvy knih {1}.", "Books": "Knihy", "Box": "Pouzdro", "BoxRear": "Zadní část pouzdra", @@ -157,7 +157,7 @@ "Dislike": "Nemám rád", "Display": "Zobrazení", "DisplayMissingEpisodesWithinSeasons": "Zobrazit chybějící epizody", - "DisplayMissingEpisodesWithinSeasonsHelp": "Toto musí být zapnuto pro knihovny TV v nastavení Jellyfin serveru.", + "DisplayMissingEpisodesWithinSeasonsHelp": "Toto musí být zapnuto pro knihovny TV v nastavení serveru.", "DisplayModeHelp": "Zvolte typ obrazovky, na které používáte Jellyfin.", "DoNotRecord": "Nenahrávat", "Down": "Dolů", @@ -522,7 +522,7 @@ "LabelEnableDlnaClientDiscoveryInterval": "Čas pro vyhledání klienta (sekund)", "LabelEnableDlnaClientDiscoveryIntervalHelp": "Určuje dobu trvání v sekundách mezi SSDP vyhledávání prováděných pomocí Jellyfin.", "LabelEnableDlnaDebugLogging": "Povolit DLNA protokolování (pro ladění)", - "LabelEnableDlnaDebugLoggingHelp": "Toto nastavení vytváří velmi velké soubory se záznamy a doporučuje se pouze v případě problémů.", + "LabelEnableDlnaDebugLoggingHelp": "Vytváří velké soubory se záznamy a doporučuje se používat pouze pro potřeby odstraňování problémů.", "LabelEnableDlnaPlayTo": "Povolit DLNA přehrávání", "LabelEnableDlnaPlayToHelp": "Jellyfin dokáže detekovat zařízení v rámci vaší sítě a nabízí možnost jeho dálkového ovládání.", "LabelEnableDlnaServer": "Povolit Dlna Server", @@ -611,9 +611,9 @@ "LabelMethod": "Metoda:", "LabelMinBackdropDownloadWidth": "Maximální šířka pro stažení pozadí:", "LabelMinResumeDuration": "Minimální doba trvání:", - "LabelMinResumeDurationHelp": "Videa kratší než tato délka nebudou pozastavitelné", + "LabelMinResumeDurationHelp": "Videa kratší než tato délka nebudou pozastavitelné.", "LabelMinResumePercentage": "Minimální procento pro přerušení:", - "LabelMinResumePercentageHelp": "Tituly budou označeny jako \"nepřehráno\", pokud budou zastaveny před tímto časem", + "LabelMinResumePercentageHelp": "Tituly budou označeny jako \"nepřehráno\", pokud budou zastaveny před tímto časem.", "LabelMinScreenshotDownloadWidth": "Minimální šířka screenshotu obrazovky:", "LabelModelDescription": "Popis modelu", "LabelModelName": "Název modelu", @@ -1027,7 +1027,7 @@ "PlaybackErrorNotAllowed": "V současné době nejste oprávněni přehrávat tento obsah. Pro více informací se obraťte se na správce systému.", "PlaybackErrorPlaceHolder": "Chcete-li toto video přehrát, vložte disk.", "Played": "Přehráno", - "Playlists": "Playlisty", + "Playlists": "Seznamy skladeb", "PleaseAddAtLeastOneFolder": "Přidejte prosím nejméně jednu složku do této knihovny pomocí tlačítka Přidat.", "PleaseConfirmPluginInstallation": "Pro potvrzení, že jste si přečetli text výše a chcete pokračovat v instalaci zásuvných modulů, klikněte na tlačítko OK.", "PleaseEnterNameOrId": "Prosím, zadejte název nebo externí Id.", @@ -1230,7 +1230,7 @@ "AllowMediaConversion": "Povolit konverzi médií", "AllowMediaConversionHelp": "Povolit nebo zakázat přístup k funkci konverze médií.", "AllowOnTheFlySubtitleExtraction": "Povolit extrahování titulků za běhu", - "AllowOnTheFlySubtitleExtractionHelp": "Vložené titulky mohou být extrahovány z videa a dodávány do aplikace Jellyfin ve formě prostého textu, aby se zabránilo překódování videa. V některých systémech to může trvat dlouho a způsobit zasekávání přehrávání videa. Při vypnutí funkce budou během překódování obsažené titulky vypáleny do obrazu, pokud je klientské zařízení nativně nepodporuje.", + "AllowOnTheFlySubtitleExtractionHelp": "Vložené titulky mohou být extrahovány z videa a dodávány do aplikací ve formě prostého textu, aby se zabránilo překódování videa. V některých systémech to může trvat dlouho a způsobit zasekávání přehrávání videa. Při vypnutí funkce budou během překódování obsažené titulky vypáleny do obrazu, pokud je klientské zařízení nativně nepodporuje.", "AllowRemoteAccess": "Povolit vzdálené připojení na server Jellyfin.", "AllowRemoteAccessHelp": "Pokud není zapnuto, všechna vzdálená připojení budou blokována.", "AllowSeasonalThemesHelp": "Pokud je povoleno, sezónní motivy občas přepíšou nastavení vašeho motivu.", @@ -1249,7 +1249,7 @@ "Blacklist": "Blacklist", "BobAndWeaveWithHelp": "Bob and weave (vyšší kvalita, ale pomalejší)", "Browse": "Procházet", - "BurnSubtitlesHelp": "Určuje, zda má server vypalovat titulky při převodu videa v závislosti na formátu titulků. Vynechání vypalování titulků zlepší výkon serveru. Chcete-li vypálit grafické formáty (např. VOBSUB, PGS, SUB / IDX atd.), stejně jako některé titulky ASS / SSA, vyberte možnost Auto", + "BurnSubtitlesHelp": "Určuje, zda má server vypalovat titulky při převodu videa v závislosti na formátu titulků. Vynechání vypalování titulků zlepší výkon serveru. Chcete-li vypálit grafické formáty (VOBSUB, PGS, SUB / IDX atd.) a některé titulky ASS / SSA, vyberte možnost Auto.", "ButtonInfo": "Info", "ButtonMenu": "Menu", "ButtonOk": "Ok", @@ -1304,7 +1304,7 @@ "HandledByProxy": "Zpracováno reverzním proxy", "HeaderAddLocalUser": "Přidat místního uživatele", "HeaderAllowMediaDeletionFrom": "Povolit smazání médií z", - "HeaderAppearsOn": "Appears On", + "HeaderAppearsOn": "Objeví se", "HeaderAudio": "Audio", "HeaderBlockItemsWithNoRating": "Blokovat položky s žádnými nebo nerozpoznanými informacemi o hodnocení:", "HeaderCameraUploadHelp": "Aplikace Jellyfin mohou automaticky nahrávat fotografie z mobilních zařízení do serveru Jellyfin.", @@ -1322,8 +1322,8 @@ "HeaderImageOptions": "Volby obrázku", "HeaderInviteWithJellyfinConnect": "Pozvat s Jellyfin Connect", "HeaderKodiMetadataHelp": "Chcete-li povolit nebo zakázat Nfo metadata, upravte nastavení knihovny v sekci ukládání metadat.", - "HeaderLiveTV": "Live TV", - "HeaderLiveTv": "Live TV", + "HeaderLiveTV": "Živá TV", + "HeaderLiveTv": "Živá TV", "HeaderLiveTvTunerSetup": "Nastavení tuneru Live TV", "HeaderMenu": "Menu", "HeaderNewDevices": "Nové zařízení", @@ -1350,7 +1350,7 @@ "LabelAlbum": "Album:", "LabelAllowedRemoteAddresses": "Filtr vzdálené IP adresy:", "LabelAllowedRemoteAddressesMode": "Režim filtru vzdálené IP adresy:", - "LabelAudioCodec": "Audio: {0}", + "LabelAudioCodec": "Audio kodek:", "LabelAutomaticallyRefreshInternetMetadataEvery": "Automaticky aktualizovat metadata z internetu:", "LabelBlockContentWithTags": "Blokovat položky s tagy:", "LabelBurnSubtitles": "Vypálit titulky:", @@ -1369,8 +1369,8 @@ "LabelEnableHardwareDecodingFor": "Povolit hardwarové dekódování pro:", "LabelHomeNetworkQuality": "Kvalita na domácí síti:", "LabelInternetQuality": "Kvalita na internetu:", - "LabelKodiMetadataUser": "Uložení dat sledování uživatele do nfo pro:", - "LabelKodiMetadataUserHelp": "Povolte toto nastavení pro uložení dat sledování do souborů NFO pro jiné aplikace, které chcete používat.", + "LabelKodiMetadataUser": "Uložit data sledování uživatele do NFO souboru pro:", + "LabelKodiMetadataUserHelp": "Uložit sledovaná data o přehrávání pro využití dalšími aplikacemi.", "LabelLanNetworks": "Sítě LAN:", "LabelLimit": "Limit:", "LabelMaxStreamingBitrate": "Maximální kvalita streamování:", @@ -1383,7 +1383,7 @@ "LabelSecureConnectionsMode": "Režim zabezpečeného připojení:", "LabelServerHost": "Host:", "LabelSimultaneousConnectionLimit": "Limit současně běžících streamů:", - "LabelSkin": "Skin:", + "LabelSkin": "Vzhled:", "LabelSortBy": "Řadit podle:", "LabelSortOrder": "Pořadí řazení:", "LabelSpecialSeasonsDisplayName": "Zobrazovaný název pro zvláštní sezónu:", @@ -1395,14 +1395,14 @@ "LabelTypeText": "Text", "LabelUrl": "URL:", "LabelUserAgent": "User agent:", - "LabelUserRemoteClientBitrateLimitHelp": "Toto přepíše výchozí globální hodnotu nastavenou v nastavení přehrávání serveru.", + "LabelUserRemoteClientBitrateLimitHelp": "Přepíše výchozí globální hodnotu nastavenou v nastavení přehrávání serveru.", "LabelVideo": "Video:", - "LabelVideoCodec": "Video: {0}", - "LeaveBlankToNotSetAPassword": "Volitelné - ponechat prázdné pro nastavení bez hesla", + "LabelVideoCodec": "Video kodek:", + "LeaveBlankToNotSetAPassword": "Můžete ponechat prázdné pro nastavení bez hesla.", "LetterButtonAbbreviation": "A", "LinkApi": "API", "LinksValue": "Odkazy: {0}", - "LiveTV": "Live TV", + "LiveTV": "Živá TV", "LiveTvFeatureDescription": "Streamujte televizní vysílání do libovolné aplikace Jellyfin s kompatibilním televizním tunerem instalovaným na serveru Jellyfin.", "Logo": "Logo", "ManageLibrary": "Spravovat knihovnu", @@ -1411,7 +1411,7 @@ "MediaInfoStreamTypeAudio": "Audio", "MediaInfoStreamTypeData": "Data", "MediaInfoStreamTypeVideo": "Video", - "AuthProviderHelp": "Vyberte poskytovatele ověřování, který bude použit k ověření hesla tohoto uživatele", + "AuthProviderHelp": "Vyberte poskytovatele ověřování, který bude použit k ověření hesla tohoto uživatele.", "HeaderFavoriteMovies": "Oblíbená videa", "HeaderFavoriteShows": "Oblíbené seriály", "HeaderFavoriteEpisodes": "Oblíbené epizody", @@ -1420,7 +1420,7 @@ "HeaderFavoriteSongs": "Oblíbená hudba", "HeaderRestartingServer": "Restartování serveru", "LabelAuthProvider": "Poskytovatel ověření:", - "LabelServerNameHelp": "Tento název bude použit k identifikaci tohoto serveru. Pokud zůstane prázdné, bude použit název počítače.", + "LabelServerNameHelp": "Tento název bude použit k identifikaci serveru a bude výchozí pro název počítače serveru.", "LabelPasswordResetProvider": "Poskytovatel obnovy hesla:", "LabelServerName": "Název serveru:", "LabelTranscodePath": "Cesta pro překódování:", @@ -1439,16 +1439,16 @@ "MessageNoCollectionsAvailable": "Kolekce vám umožní vychutnat si osobní seskupení filmů, seriálů a hudebních alb. Chcete-li je začít vytvářet, klikněte na tlačítko +.", "MessagePleaseWait": "Prosím, čekejte. Může to trvat několik minut.", "Metadata": "Metadata", - "MovieLibraryHelp": "Podívejte se na {0}průvodce pojmenováním filmů Jellyfin{1}.", + "MovieLibraryHelp": "Podívejte se na {0}průvodce pojmenováním filmů{1}.", "Never": "Nikdy", "NextUp": "Další", "NoNewDevicesFound": "Nebyla nalezena žádná nová zařízení. Chcete-li přidat nový tuner, zavřete tento dialog a zadejte informace o zařízení ručně.", - "OnlyImageFormats": "Pouze obrazové formáty (VOBSUB, PGS, SUB/IDX, atd.)", + "OnlyImageFormats": "Pouze obrazové formáty (VOBSUB, PGS, SUB, atd.)", "Option3D": "3D", "OptionAlbum": "Album", "OptionAllowMediaPlaybackTranscodingHelp": "Omezení přístupu k překódování může způsobit selhání přehrávání v aplikacích Jellyfin kvůli nepodporovaným formátům médií.", "OptionAllowSyncTranscoding": "Povolit stahování a synchronizaci médií, které vyžaduje překódování", - "OptionBluray": "Bluray", + "OptionBluray": "Blu-ray", "OptionCaptionInfoExSamsung": "CaptionInfoEx (Samsung)", "OptionDownloadBannerImage": "Banner", "OptionDownloadBoxImage": "Box", @@ -1456,7 +1456,7 @@ "OptionIsHD": "HD", "OptionIsSD": "SD", "OptionLoginAttemptsBeforeLockout": "Určuje, kolik chybných pokusů o přihlášení lze provést před zablokováním.", - "OptionLoginAttemptsBeforeLockoutHelp": "0 znamená zdědění výchozí hodnoty 3 pro non-admin a 5 pro admin, -1 deaktivuje uzamykání", + "OptionLoginAttemptsBeforeLockoutHelp": "0 znamená zdědění výchozí hodnoty 3 pokusů pro běžné uživatele a 5 pro administrátory. Nastavení na -1 deaktivuje funkci.", "OptionMax": "Max", "OptionProfileAudio": "Audio", "OptionProfileVideo": "Video", @@ -1489,14 +1489,14 @@ "Sort": "Třídit", "StatsForNerds": "Statistiky pro šprty", "SubtitleAppearanceSettingsAlsoPassedToCastDevices": "Tato nastavení platí také pro jakékoli přehrávání na Chromecastu spuštěné tímto zařízením.", - "SubtitleAppearanceSettingsDisclaimer": "Tato nastavení se nevztahuje na grafické titulky (PGS, DVD atd.) nebo titulky, které mají vlastní vložené styly (ASS / SSA).", + "SubtitleAppearanceSettingsDisclaimer": "Tato nastavení se nevztahuje na grafické titulky (PGS, DVD atd.) nebo ASS/SSA titulky, které mají vlastní vložené styly.", "SubtitleDownloadersHelp": "Povolte a zařaďte preferované stahovače titulků v pořadí podle priority.", "SubtitleSettings": "Nastavení titulků", "SubtitleSettingsIntro": "Chcete-li nastavit výchozí vzhled a jazyk titulků, zastavte přehrávání videa a klepněte na ikonu uživatele v pravé horní části aplikace.", "TV": "TV", "TabDirectPlay": "Přímé přehrávání", "TabInfo": "Info", - "TabLiveTV": "Live TV", + "TabLiveTV": "Živá TV", "TabMetadata": "Metadata", "TabPlaylist": "Playlist", "TabServer": "Server", @@ -1504,10 +1504,10 @@ "ThemeSongs": "Tematická hudba", "ThemeVideos": "Tematická videa", "Trailers": "Trailery", - "TvLibraryHelp": "Podívejte se na {0}průvodce pojmenováním TV Jellyfin{1}.", + "TvLibraryHelp": "Podívejte se na {0}průvodce pojmenováním TV pořadů{1}.", "Uniform": "Uniformní", "Unplayed": "Nepřehrané", - "UserAgentHelp": "V případě potřeby zadejte vlastní hlavičku user agenta http.", + "UserAgentHelp": "Zadejte vlastní HTTP hlavičku user agenta.", "ValueMinutes": "{0} min", "ValueOneAlbum": "1 album", "ValueOneSong": "1 skladba", @@ -1518,8 +1518,8 @@ "HeaderHome": "Domů", "DashboardOperatingSystem": "Operační systém: {0}", "DashboardArchitecture": "Architektura: {0}", - "LaunchWebAppOnStartup": "Spusťte webovou aplikaci Jellyfin ve svém webovém prohlížeči po nastartování Jellyfin serveru", - "LaunchWebAppOnStartupHelp": "Toto otevře se webovou aplikaci ve vašem výchozím webovém prohlížeči, když se spustí server Jellyfin. K tomu nedochází při použití funkce restartování serveru.", + "LaunchWebAppOnStartup": "Spustit webové rozhraní po spustění serveru", + "LaunchWebAppOnStartupHelp": "Otevře se webový klient ve vašem výchozím webovém prohlížeči, když server se spustí. K tomu nedochází při použití funkce restartování serveru.", "MessageNoServersAvailable": "Pomocí automatického zjišťování nebyly nalezeny žádné servery.", "OptionBanner": "Banner", "OptionList": "Seznam", @@ -1532,5 +1532,27 @@ "MusicArtist": "Interpret", "MusicVideo": "Videoklip", "SubtitleOffset": "Nastavení titulků", - "TabNetworking": "Vytváření sítí" + "TabNetworking": "Vytváření sítí", + "MusicLibraryHelp": "Prostudujte si {0}průvodce pojmenováním hudby{1}.", + "MoreMediaInfo": "Informace o médiu", + "LabelVideoBitrate": "Datový tok videa:", + "LabelTranscodingProgress": "Průběh překódování:", + "LabelTranscodingFramerate": "Snimková frekvence pro překódování:", + "LabelSize": "Velikost:", + "LabelPleaseRestart": "Změny se projeví až po ručním obnovení webového klienta.", + "LabelPlayMethod": "Způsob přehrání:", + "LabelPlayer": "Přehrávač:", + "LabelFolder": "Složka:", + "LabelBaseUrlHelp": "Zde můžete přidat vlastní podsložku aby bylo možné přistupovat na server z unikátnější adresy.", + "LabelBaseUrl": "Výchozí URL:", + "LabelBitrate": "Datový tok:", + "LabelAudioSampleRate": "Vzorkovací frekvence zvuku:", + "LabelAudioChannels": "Počet kanálů zvuku:", + "LabelAudioBitrate": "Datový tok zvuku:", + "LabelAudioBitDepth": "Bitová hloubka zvuku:", + "HeaderFavoriteBooks": "Oblíbené knihy", + "FetchingData": "Načtení dalších dat", + "CopyStreamURLSuccess": "Úspěšně zkopírovaná URL.", + "CopyStreamURL": "Kopírovat URL adresu streamu", + "ButtonAddImage": "Přidat obrázek" } From 3896c18e2646f99d35d0c3c1eb468495ca168350 Mon Sep 17 00:00:00 2001 From: Dmitry Lyzo Date: Sat, 9 Nov 2019 11:48:52 +0300 Subject: [PATCH 122/162] Make navigation and playback control TV-friendly --- src/components/emby-slider/emby-slider.css | 4 + src/components/emby-slider/emby-slider.js | 118 +++++++++++++++++++++ src/controllers/videoosd.js | 19 ++++ src/videoosd.html | 2 +- 4 files changed, 142 insertions(+), 1 deletion(-) diff --git a/src/components/emby-slider/emby-slider.css b/src/components/emby-slider/emby-slider.css index bd258d3bc5..b173f5c511 100644 --- a/src/components/emby-slider/emby-slider.css +++ b/src/components/emby-slider/emby-slider.css @@ -87,6 +87,10 @@ _:-ms-input-placeholder { transform: scale(1.6); } +.mdl-slider.show-focus:focus::-webkit-slider-thumb { + transform: scale(1.6); +} + .slider-no-webkit-thumb::-webkit-slider-thumb { opacity: 0 !important; } diff --git a/src/components/emby-slider/emby-slider.js b/src/components/emby-slider/emby-slider.js index 1ca1448ea1..c1d58d59a3 100644 --- a/src/components/emby-slider/emby-slider.js +++ b/src/components/emby-slider/emby-slider.js @@ -19,6 +19,11 @@ define(['browser', 'dom', 'layoutManager', 'css!./emby-slider', 'registerElement function updateValues() { + // Do not update values when dragging with keyboard to keep current progress for reference + if (!!this.keyboardDragging) { + return; + } + var range = this; var value = range.value; @@ -82,6 +87,9 @@ define(['browser', 'dom', 'layoutManager', 'css!./emby-slider', 'registerElement if (!layoutManager.mobile) { this.classList.add('mdl-slider-hoverthumb'); } + if (layoutManager.tv) { + this.classList.add('show-focus'); + } var containerElement = this.parentNode; containerElement.classList.add('mdl-slider-container'); @@ -177,6 +185,116 @@ define(['browser', 'dom', 'layoutManager', 'css!./emby-slider', 'registerElement } }; + /** + * Keyboard dragging timeout. + * After this delay "change" event will be fired. + */ + var KeyboardDraggingTimeout = 1000; + + /** + * Keyboard dragging timer. + */ + var keyboardDraggingTimer; + + /** + * Start keyboard dragging. + * + * @param {Object} elem slider itself + */ + function startKeyboardDragging(elem) { + + elem.keyboardDragging = true; + + clearTimeout(keyboardDraggingTimer); + + keyboardDraggingTimer = setTimeout(function () { + finishKeyboardDragging(elem); + }, KeyboardDraggingTimeout); + } + + /** + * Finish keyboard dragging. + * + * @param {Object} elem slider itself + */ + function finishKeyboardDragging(elem) { + + clearTimeout(keyboardDraggingTimer); + keyboardDraggingTimer = undefined; + + elem.keyboardDragging = false; + + var event = new Event('change', { + bubbles: true, + cancelable: false + }); + elem.dispatchEvent(event); + } + + /** + * Do step by delta. + * + * @param {Object} elem slider itself + * @param {number} delta step amount + */ + function stepKeyboard(elem, delta) { + + startKeyboardDragging(elem); + + elem.value = Math.max(elem.min, Math.min(elem.max, parseFloat(elem.value) + delta)); + + var event = new Event('input', { + bubbles: true, + cancelable: false + }); + elem.dispatchEvent(event); + } + + /** + * Handle KeyDown event + */ + function onKeyDown(e) { + + switch (e.key) { + case 'ArrowLeft': + case 'Left': + stepKeyboard(this, -this.keyboardStepDown || -1); + e.preventDefault(); + e.stopPropagation(); + break; + + case 'ArrowRight': + case 'Right': + stepKeyboard(this, this.keyboardStepUp || 1); + e.preventDefault(); + e.stopPropagation(); + break; + } + } + + /** + * Enable keyboard dragging. + */ + EmbySliderPrototype.enableKeyboardDragging = function () { + + if (!this.keyboardDraggingEnabled) { + this.addEventListener('keydown', onKeyDown); + this.keyboardDraggingEnabled = true; + } + } + + /** + * Set steps for keyboard input. + * + * @param {number} stepDown step to reduce + * @param {number} stepUp step to increase + */ + EmbySliderPrototype.setKeyboardSteps = function (stepDown, stepUp) { + + this.keyboardStepDown = stepDown || stepUp || 1; + this.keyboardStepUp = stepUp || stepDown || 1; + } + function setRange(elem, startPercent, endPercent) { var style = elem.style; diff --git a/src/controllers/videoosd.js b/src/controllers/videoosd.js index b610886963..81e819e4e0 100644 --- a/src/controllers/videoosd.js +++ b/src/controllers/videoosd.js @@ -770,6 +770,10 @@ define(["playbackManager", "dom", "inputManager", "datetime", "itemHelper", "med var isProgressClear = state.MediaSource && null == state.MediaSource.RunTimeTicks; nowPlayingPositionSlider.setIsClear(isProgressClear); + if (nowPlayingItem.RunTimeTicks) { + nowPlayingPositionSlider.setKeyboardSteps(userSettings.skipBackLength() * 1000000 / nowPlayingItem.RunTimeTicks, userSettings.skipForwardLength() * 1000000 / nowPlayingItem.RunTimeTicks); + } + if (-1 === supportedCommands.indexOf("ToggleFullscreen") || player.isLocalPlayer && layoutManager.tv && playbackManager.isFullscreen(player)) { view.querySelector(".btnFullscreen").classList.add("hide"); } else { @@ -1070,12 +1074,21 @@ define(["playbackManager", "dom", "inputManager", "datetime", "itemHelper", "med } } + /** + * Keys used for keyboard navigation. + */ + var NavigationKeys = ["ArrowLeft", "ArrowRight", "ArrowUp", "ArrowDown"]; + function onWindowKeyDown(e) { if (!currentVisibleMenu && 32 === e.keyCode) { playbackManager.playPause(currentPlayer); return void showOsd(); } + if (layoutManager.tv && NavigationKeys.indexOf(e.key) != -1) { + return void showOsd(); + } + switch (e.key) { case "k": playbackManager.playPause(currentPlayer); @@ -1237,6 +1250,12 @@ define(["playbackManager", "dom", "inputManager", "datetime", "itemHelper", "med var transitionEndEventName = dom.whichTransitionEvent(); var headerElement = document.querySelector(".skinHeader"); var osdBottomElement = document.querySelector(".videoOsdBottom-maincontrols"); + + if (layoutManager.tv) { + nowPlayingPositionSlider.classList.add("focusable"); + nowPlayingPositionSlider.enableKeyboardDragging(); + } + view.addEventListener("viewbeforeshow", function (e) { headerElement.classList.add("osdHeader"); Emby.Page.setTransparency("full"); diff --git a/src/videoosd.html b/src/videoosd.html index 0f4be75916..34c73a3019 100644 --- a/src/videoosd.html +++ b/src/videoosd.html @@ -31,7 +31,7 @@
-
+
From d260cf5390390c0ae16069a3b0fadab875b2966c Mon Sep 17 00:00:00 2001 From: Sander Lambrechts Date: Fri, 8 Nov 2019 22:23:56 +0000 Subject: [PATCH 123/162] Translated using Weblate (Dutch) Translation: Jellyfin/Jellyfin Web Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-web/nl/ --- src/strings/nl.json | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/strings/nl.json b/src/strings/nl.json index 38f529af9d..6388edb647 100644 --- a/src/strings/nl.json +++ b/src/strings/nl.json @@ -18,11 +18,11 @@ "AllEpisodes": "Alle afleveringen", "AllLanguages": "Alle talen", "AllLibraries": "Alle bibliotheken", - "AllowHWTranscodingHelp": "Wanneer ingeschakeld zal de tuner streams direct transcoderen. Dit kan helpen de transcodering vereist door Jellyfin Server te verlagen.", + "AllowHWTranscodingHelp": "Direct transcoderen toestaan door de tuner. Dit kan helpen om de transcodering te verlagen die vereist is door de server.", "AllowMediaConversion": "Mediaconversie toestaan", "AllowMediaConversionHelp": "Toegang verlenen of weigeren tot de mediaconversie functie.", "AllowOnTheFlySubtitleExtraction": "Directe ondertitel extractie toestaan", - "AllowOnTheFlySubtitleExtractionHelp": "Ingebakken ondertitels kunnen uit de video's gehaald worden en als tekst bezorgd worden aan de Jellyfin apps om transcodering te helpen voorkomen. Op sommige systemen kan dit een lange tijd duren en dit er voor zorgen dat het afspelen van video stopt tijdens de extractie. Schakel dit uit om ingebakken ondertiteling in de video te laten branden met transcodering als deze niet standaard ondersteund worden door het afspeelapparaat.", + "AllowOnTheFlySubtitleExtractionHelp": "Ingebakken ondertitels kunnen uit de video's gehaald worden en als tekst bezorgd worden aan de clients om transcodering te helpen voorkomen. Op sommige systemen kan dit een lange tijd duren en dit er voor zorgen dat het afspelen van video stopt tijdens de extractie. Schakel dit uit om ingebakken ondertiteling in de video te laten branden met transcodering als deze niet standaard ondersteund worden door het afspeelapparaat.", "AllowRemoteAccess": "Externe verbindingen met deze Jellyfin Server toestaan.", "AllowRemoteAccessHelp": "Indien niet aangevinkt worden alle externe verbindingen geblokkeerd.", "AllowedRemoteAddressesHelp": "Komma-gescheiden lijst van IP-adressen of IP/netmask adressen voor netwerken die op afstand verbinding mogen maken. Indien blanco, worden alle externe adressen toegestaan.", @@ -44,7 +44,7 @@ "BirthDateValue": "Geboren: {0}", "BirthLocation": "Geboorte Locatie", "BirthPlaceValue": "Geboorte plaats: {0})", - "BookLibraryHelp": "Audio- en tekstboeken worden ondersteund. Bekijk de {0}Jellyfin Boeken naamgeving{1}.", + "BookLibraryHelp": "Audio- en tekstboeken worden ondersteund. Bekijk de {0}boeken naamgevingsgids{1}.", "Books": "Boeken", "BoxRear": "Hoes (achterkant)", "Browse": "Bladeren", @@ -722,7 +722,7 @@ "LabelSerialNumber": "Serienummer", "LabelSeriesRecordingPath": "Serieopname pad (optioneel):", "LabelServerHost": "Server:", - "LabelServerHostHelp": "192.168.1.100 of https://myserver.com", + "LabelServerHostHelp": "192.168.1.100:8096 of https://mijnserver.nl", "LabelSimultaneousConnectionLimit": "Gelijktijdige streams limiet:", "LabelSkipBackLength": "Terugspoellengte", "LabelSkipForwardLength": "Vooruitspoellengte", @@ -1293,7 +1293,7 @@ "HeaderSync": "Synchronisatie", "HeaderTV": "TV", "HeaderTopPlugins": "Top Plugins", - "AuthProviderHelp": "Selecteer een Authentication Provider om de gebruiker's wachtwoord te verifiëren ", + "AuthProviderHelp": "Selecteer een Authenticatie Provider om het wachtwoord van deze gebruiker te verifiëren", "HeaderFavoriteMovies": "Favoriete Films", "HeaderFavoriteShows": "Favoriete shows", "HeaderFavoriteEpisodes": "Favoriete afleveringen", @@ -1328,5 +1328,6 @@ "LabelProtocolInfo": "Protocol info:", "LabelServerName": "Server naam:", "LabelSkin": "Skin:", - "ButtonAddImage": "Voeg afbeelding toe" + "ButtonAddImage": "Voeg afbeelding toe", + "LabelSize": "Grootte:" } From 9c47f8fc1c5ec9a99fdb2742097c6ed1ffc57488 Mon Sep 17 00:00:00 2001 From: nextlooper42 Date: Fri, 8 Nov 2019 15:53:51 +0000 Subject: [PATCH 124/162] Translated using Weblate (Slovak) Translation: Jellyfin/Jellyfin Web Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-web/sk/ --- src/strings/sk.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/strings/sk.json b/src/strings/sk.json index 7c0048db2f..14b75e053e 100644 --- a/src/strings/sk.json +++ b/src/strings/sk.json @@ -957,7 +957,7 @@ "HeaderSelectCertificatePath": "Vybrať cestu k certifikátu", "HeaderSortOrder": "Poradie zoradzovania", "HeaderSpecialEpisodeInfo": "Informácie o špeciálnej epizóde", - "HeaderSpecialFeatures": "Špeciálne funkcie", + "HeaderSpecialFeatures": "Bonusové materiály", "HeaderSubtitleDownloads": "Sťahovanie titulkov", "HeaderTags": "Tagy", "HeaderVideoType": "Typ videa", @@ -976,7 +976,7 @@ "OptionDownloadPrimaryImage": "Primárne", "OptionDvd": "DVD", "OptionExtractChapterImage": "Povoliť extrakciu obrázkov z videa", - "OptionHasSpecialFeatures": "Špeciálne funkcie", + "OptionHasSpecialFeatures": "Bonusové materiály", "OptionHasTrailer": "Ukážka/Trailer", "OptionIsHD": "HD", "OptionIsSD": "SD", From d11e93b0dafccc92d89143068337802a410059a9 Mon Sep 17 00:00:00 2001 From: dkanada Date: Mon, 11 Nov 2019 01:39:06 +0900 Subject: [PATCH 125/162] redirect to select server if no credentials found --- src/bower_components/apiclient/connectionmanager.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/bower_components/apiclient/connectionmanager.js b/src/bower_components/apiclient/connectionmanager.js index dcb8f28bc8..9ccb3aa087 100644 --- a/src/bower_components/apiclient/connectionmanager.js +++ b/src/bower_components/apiclient/connectionmanager.js @@ -659,6 +659,11 @@ define(["events", "apiclient", "appStorage"], function (events, apiClientFactory return result; }); } + + return Promise.resolve({ + Servers: servers, + State: "ServerSelection" + }); }; self.connectToServer = function (server, options) { From 105891b40932d717064c9b5f0eb866991b560513 Mon Sep 17 00:00:00 2001 From: dkanada Date: Mon, 11 Nov 2019 01:45:01 +0900 Subject: [PATCH 126/162] move more dependencies to webpack --- package.json | 7 +- .../document-register-element/basic.html | 12 - .../build/document-register-element.js | 246 --- src/bower_components/fetch/fetch.js | 263 --- .../native-promise-only/lib/npo.src.js | 373 ---- .../native-promise-only/test_adapter.js | 21 - .../ResizeObserver.js | 939 ---------- .../webcomponentsjs/webcomponents-lite.min.js | 1571 ----------------- src/bundle.js | 20 + src/scripts/site.js | 17 +- webpack.common.js | 4 +- 11 files changed, 40 insertions(+), 3433 deletions(-) delete mode 100644 src/bower_components/document-register-element/basic.html delete mode 100644 src/bower_components/document-register-element/build/document-register-element.js delete mode 100644 src/bower_components/fetch/fetch.js delete mode 100644 src/bower_components/native-promise-only/lib/npo.src.js delete mode 100644 src/bower_components/native-promise-only/test_adapter.js delete mode 100644 src/bower_components/resize-observer-polyfill/ResizeObserver.js delete mode 100644 src/bower_components/webcomponentsjs/webcomponents-lite.min.js diff --git a/package.json b/package.json index 051102239b..8eea3ca247 100644 --- a/package.json +++ b/package.json @@ -18,16 +18,21 @@ }, "dependencies": { "alameda": "^1.3.0", + "document-register-element": "^0.5.4", "flv.js": "^1.5.0", "hls.js": "^0.12.4", "howler": "^2.1.2", "jquery": "^3.4.1", "jstree": "^3.3.7", "libjass": "^0.11.0", + "native-promise-only": "^0.8.0-a", "requirejs": "^2.3.5", + "resize-observer-polyfill": "^1.5.1", "shaka-player": "^2.5.5", "sortablejs": "^1.9.0", - "swiper": "^3.4.2" + "swiper": "^3.4.2", + "webcomponents.js-2": "^0.7.24", + "whatwg-fetch": "^1.1.1" }, "scripts": { "serve": "webpack-dev-server --config webpack.dev.js --open", diff --git a/src/bower_components/document-register-element/basic.html b/src/bower_components/document-register-element/basic.html deleted file mode 100644 index 713a029e4c..0000000000 --- a/src/bower_components/document-register-element/basic.html +++ /dev/null @@ -1,12 +0,0 @@ - - - - testing my-element - - - - - - some content - - \ No newline at end of file diff --git a/src/bower_components/document-register-element/build/document-register-element.js b/src/bower_components/document-register-element/build/document-register-element.js deleted file mode 100644 index 57fe40a366..0000000000 --- a/src/bower_components/document-register-element/build/document-register-element.js +++ /dev/null @@ -1,246 +0,0 @@ -/*! (C) WebReflection Mit Style License */ -(function(e, t, n, r) { - "use strict"; - - function rt(e, t) { - for (var n = 0, r = e.length; n < r; n++) vt(e[n], t) - } - - function it(e) { - for (var t = 0, n = e.length, r; t < n; t++) r = e[t], nt(r, b[ot(r)]) - } - - function st(e) { - return function(t) { - j(t) && (vt(t, e), rt(t.querySelectorAll(w), e)) - } - } - - function ot(e) { - var t = e.getAttribute("is"), - n = e.nodeName.toUpperCase(), - r = S.call(y, t ? v + t.toUpperCase() : d + n); - return t && -1 < r && !ut(n, t) ? -1 : r - } - - function ut(e, t) { - return -1 < w.indexOf(e + '[is="' + t + '"]') - } - - function at(e) { - var t = e.currentTarget, - n = e.attrChange, - r = e.attrName, - i = e.target; - Q && (!i || i === t) && t.attributeChangedCallback && r !== "style" && e.prevValue !== e.newValue && t.attributeChangedCallback(r, n === e[a] ? null : e.prevValue, n === e[l] ? null : e.newValue) - } - - function ft(e) { - var t = st(e); - return function(e) { - X.push(t, e.target) - } - } - - function lt(e) { - K && (K = !1, e.currentTarget.removeEventListener(h, lt)), rt((e.target || t).querySelectorAll(w), e.detail === o ? o : s), B && pt() - } - - function ct(e, t) { - var n = this; - q.call(n, e, t), G.call(n, { - target: n - }) - } - - function ht(e, t) { - D(e, t), et ? et.observe(e, z) : (J && (e.setAttribute = ct, e[i] = Z(e), e.addEventListener(p, G)), e.addEventListener(c, at)), e.createdCallback && Q && (e.created = !0, e.createdCallback(), e.created = !1) - } - - function pt() { - for (var e, t = 0, n = F.length; t < n; t++) e = F[t], E.contains(e) || (n--, F.splice(t--, 1), vt(e, o)) - } - - function dt(e) { - throw new Error("A " + e + " type is already registered") - } - - function vt(e, t) { - var n, r = ot(e); - 1 < r && (tt(e, b[r]), r = 0, t === s && !e[s] ? (e[o] = !1, e[s] = !0, r = 1, B && S.call(F, e) < 0 && F.push(e)) : t === o && !e[o] && (e[s] = !1, e[o] = !0, r = 1), r && (n = e[t + "Callback"]) && n.call(e)) - } - if (r in t) return; - var i = "__" + r + (Math.random() * 1e5 >> 0), - s = "attached", - o = "detached", - u = "extends", - a = "ADDITION", - f = "MODIFICATION", - l = "REMOVAL", - c = "DOMAttrModified", - h = "DOMContentLoaded", - p = "DOMSubtreeModified", - d = "<", - v = "=", - m = /^[A-Z][A-Z0-9]*(?:-[A-Z0-9]+)+$/, - g = ["ANNOTATION-XML", "COLOR-PROFILE", "FONT-FACE", "FONT-FACE-SRC", "FONT-FACE-URI", "FONT-FACE-FORMAT", "FONT-FACE-NAME", "MISSING-GLYPH"], - y = [], - b = [], - w = "", - E = t.documentElement, - S = y.indexOf || function(e) { - for (var t = this.length; t-- && this[t] !== e;); - return t - }, - x = n.prototype, - T = x.hasOwnProperty, - N = x.isPrototypeOf, - C = n.defineProperty, - k = n.getOwnPropertyDescriptor, - L = n.getOwnPropertyNames, - A = n.getPrototypeOf, - O = n.setPrototypeOf, - M = !!n.__proto__, - _ = n.create || function mt(e) { - return e ? (mt.prototype = e, new mt) : this - }, - D = O || (M ? function(e, t) { - return e.__proto__ = t, e - } : L && k ? function() { - function e(e, t) { - for (var n, r = L(t), i = 0, s = r.length; i < s; i++) n = r[i], T.call(e, n) || C(e, n, k(t, n)) - } - return function(t, n) { - do e(t, n); while ((n = A(n)) && !N.call(n, t)); - return t - } - }() : function(e, t) { - for (var n in t) e[n] = t[n]; - return e - }), - P = e.MutationObserver || e.WebKitMutationObserver, - H = (e.HTMLElement || e.Element || e.Node).prototype, - B = !N.call(H, E), - j = B ? function(e) { - return e.nodeType === 1 - } : function(e) { - return N.call(H, e) - }, - F = B && [], - I = H.cloneNode, - q = H.setAttribute, - R = H.removeAttribute, - U = t.createElement, - z = P && { - attributes: !0, - characterData: !0, - attributeOldValue: !0 - }, - W = P || function(e) { - J = !1, E.removeEventListener(c, W) - }, - X, V = e.requestAnimationFrame || e.webkitRequestAnimationFrame || e.mozRequestAnimationFrame || e.msRequestAnimationFrame || function(e) { - setTimeout(e, 10) - }, - $ = !1, - J = !0, - K = !0, - Q = !0, - G, Y, Z, et, tt, nt; - O || M ? (tt = function(e, t) { - N.call(t, e) || ht(e, t) - }, nt = ht) : (tt = function(e, t) { - e[i] || (e[i] = n(!0), ht(e, t)) - }, nt = tt), B ? (J = !1, function() { - var e = k(H, "addEventListener"), - t = e.value, - n = function(e) { - var t = new CustomEvent(c, { - bubbles: !0 - }); - t.attrName = e, t.prevValue = this.getAttribute(e), t.newValue = null, t[l] = t.attrChange = 2, R.call(this, e), this.dispatchEvent(t) - }, - r = function(e, t) { - var n = this.hasAttribute(e), - r = n && this.getAttribute(e), - i = new CustomEvent(c, { - bubbles: !0 - }); - q.call(this, e, t), i.attrName = e, i.prevValue = n ? r : null, i.newValue = t, n ? i[f] = i.attrChange = 1 : i[a] = i.attrChange = 0, this.dispatchEvent(i) - }, - s = function(e) { - var t = e.currentTarget, - n = t[i], - r = e.propertyName, - s; - n.hasOwnProperty(r) && (n = n[r], s = new CustomEvent(c, { - bubbles: !0 - }), s.attrName = n.name, s.prevValue = n.value || null, s.newValue = n.value = t[r] || null, s.prevValue == null ? s[a] = s.attrChange = 0 : s[f] = s.attrChange = 1, t.dispatchEvent(s)) - }; - e.value = function(e, o, u) { - e === c && this.attributeChangedCallback && this.setAttribute !== r && (this[i] = { - className: { - name: "class", - value: this.className - } - }, this.setAttribute = r, this.removeAttribute = n, t.call(this, "propertychange", s)), t.call(this, e, o, u) - }, C(H, "addEventListener", e) - }()) : P || (E.addEventListener(c, W), E.setAttribute(i, 1), E.removeAttribute(i), J && (G = function(e) { - var t = this, - n, r, s; - if (t === e.target) { - n = t[i], t[i] = r = Z(t); - for (s in r) { - if (!(s in n)) return Y(0, t, s, n[s], r[s], a); - if (r[s] !== n[s]) return Y(1, t, s, n[s], r[s], f) - } - for (s in n) - if (!(s in r)) return Y(2, t, s, n[s], r[s], l) - } - }, Y = function(e, t, n, r, i, s) { - var o = { - attrChange: e, - currentTarget: t, - attrName: n, - prevValue: r, - newValue: i - }; - o[s] = e, at(o) - }, Z = function(e) { - for (var t, n, r = {}, i = e.attributes, s = 0, o = i.length; s < o; s++) t = i[s], n = t.name, n !== "setAttribute" && (r[n] = t.value); - return r - })), t[r] = function(n, r) { - c = n.toUpperCase(), $ || ($ = !0, P ? (et = function(e, t) { - function n(e, t) { - for (var n = 0, r = e.length; n < r; t(e[n++])); - } - return new P(function(r) { - for (var i, s, o, u = 0, a = r.length; u < a; u++) i = r[u], i.type === "childList" ? (n(i.addedNodes, e), n(i.removedNodes, t)) : (s = i.target, Q && s.attributeChangedCallback && i.attributeName !== "style" && (o = s.getAttribute(i.attributeName), o !== i.oldValue && s.attributeChangedCallback(i.attributeName, i.oldValue, o))) - }) - }(st(s), st(o)), et.observe(t, { - childList: !0, - subtree: !0 - })) : (X = [], V(function E() { - while (X.length) X.shift().call(null, X.shift()); - V(E) - }), t.addEventListener("DOMNodeInserted", ft(s)), t.addEventListener("DOMNodeRemoved", ft(o))), t.addEventListener(h, lt), t.addEventListener("readystatechange", lt), t.createElement = function(e, n) { - var r = U.apply(t, arguments), - i = "" + e, - s = S.call(y, (n ? v : d) + (n || i).toUpperCase()), - o = -1 < s; - return n && (r.setAttribute("is", n = n.toLowerCase()), o && (o = ut(i.toUpperCase(), n))), Q = !t.createElement.innerHTMLHelper, o && nt(r, b[s]), r - }, H.cloneNode = function(e) { - var t = I.call(this, !!e), - n = ot(t); - return -1 < n && nt(t, b[n]), e && it(t.querySelectorAll(w)), t - }), -2 < S.call(y, v + c) + S.call(y, d + c) && dt(n); - if (!m.test(c) || -1 < S.call(g, c)) throw new Error("The type " + n + " is invalid"); - var i = function() { - return f ? t.createElement(l, c) : t.createElement(l) - }, - a = r || x, - f = T.call(a, u), - l = f ? r[u].toUpperCase() : c, - c, p; - return f && -1 < S.call(y, d + l) && dt(l), p = y.push((f ? v : d) + c) - 1, w = w.concat(w.length ? "," : "", f ? l + '[is="' + n.toLowerCase() + '"]' : l), i.prototype = b[p] = T.call(a, "prototype") ? a.prototype : _(H), rt(t.querySelectorAll(w), s), i - } -})(window, document, Object, "registerElement"); \ No newline at end of file diff --git a/src/bower_components/fetch/fetch.js b/src/bower_components/fetch/fetch.js deleted file mode 100644 index cd40b3ed2d..0000000000 --- a/src/bower_components/fetch/fetch.js +++ /dev/null @@ -1,263 +0,0 @@ -! function(self) { - "use strict"; - - function normalizeName(name) { - if ("string" != typeof name && (name = String(name)), /[^a-z0-9\-#$%&'*+.\^_`|~]/i.test(name)) throw new TypeError("Invalid character in header field name"); - return name.toLowerCase() - } - - function normalizeValue(value) { - return "string" != typeof value && (value = String(value)), value - } - - function iteratorFor(items) { - var iterator = { - next: function() { - var value = items.shift(); - return { - done: void 0 === value, - value: value - } - } - }; - return support.iterable && (iterator[Symbol.iterator] = function() { - return iterator - }), iterator - } - - function Headers(headers) { - this.map = {}, headers instanceof Headers ? headers.forEach(function(value, name) { - this.append(name, value) - }, this) : headers && Object.getOwnPropertyNames(headers).forEach(function(name) { - this.append(name, headers[name]) - }, this) - } - - function consumed(body) { - if (body.bodyUsed) return Promise.reject(new TypeError("Already read")); - body.bodyUsed = !0 - } - - function fileReaderReady(reader) { - return new Promise(function(resolve, reject) { - reader.onload = function() { - resolve(reader.result) - }, reader.onerror = function() { - reject(reader.error) - } - }) - } - - function readBlobAsArrayBuffer(blob) { - var reader = new FileReader, - promise = fileReaderReady(reader); - return reader.readAsArrayBuffer(blob), promise - } - - function readBlobAsText(blob) { - var reader = new FileReader, - promise = fileReaderReady(reader); - return reader.readAsText(blob), promise - } - - function readArrayBufferAsText(buf) { - for (var view = new Uint8Array(buf), chars = new Array(view.length), i = 0; i < view.length; i++) chars[i] = String.fromCharCode(view[i]); - return chars.join("") - } - - function bufferClone(buf) { - if (buf.slice) return buf.slice(0); - var view = new Uint8Array(buf.byteLength); - return view.set(new Uint8Array(buf)), view.buffer - } - - function Body() { - return this.bodyUsed = !1, this._initBody = function(body) { - if (this._bodyInit = body, body) - if ("string" == typeof body) this._bodyText = body; - else if (support.blob && Blob.prototype.isPrototypeOf(body)) this._bodyBlob = body; - else if (support.formData && FormData.prototype.isPrototypeOf(body)) this._bodyFormData = body; - else if (support.searchParams && URLSearchParams.prototype.isPrototypeOf(body)) this._bodyText = body.toString(); - else if (support.arrayBuffer && support.blob && isDataView(body)) this._bodyArrayBuffer = bufferClone(body.buffer), this._bodyInit = new Blob([this._bodyArrayBuffer]); - else { - if (!support.arrayBuffer || !ArrayBuffer.prototype.isPrototypeOf(body) && !isArrayBufferView(body)) throw new Error("unsupported BodyInit type"); - this._bodyArrayBuffer = bufferClone(body) - } else this._bodyText = ""; - this.headers.get("content-type") || ("string" == typeof body ? this.headers.set("content-type", "text/plain;charset=UTF-8") : this._bodyBlob && this._bodyBlob.type ? this.headers.set("content-type", this._bodyBlob.type) : support.searchParams && URLSearchParams.prototype.isPrototypeOf(body) && this.headers.set("content-type", "application/x-www-form-urlencoded;charset=UTF-8")) - }, support.blob && (this.blob = function() { - var rejected = consumed(this); - if (rejected) return rejected; - if (this._bodyBlob) return Promise.resolve(this._bodyBlob); - if (this._bodyArrayBuffer) return Promise.resolve(new Blob([this._bodyArrayBuffer])); - if (this._bodyFormData) throw new Error("could not read FormData body as blob"); - return Promise.resolve(new Blob([this._bodyText])) - }, this.arrayBuffer = function() { - return this._bodyArrayBuffer ? consumed(this) || Promise.resolve(this._bodyArrayBuffer) : this.blob().then(readBlobAsArrayBuffer) - }), this.text = function() { - var rejected = consumed(this); - if (rejected) return rejected; - if (this._bodyBlob) return readBlobAsText(this._bodyBlob); - if (this._bodyArrayBuffer) return Promise.resolve(readArrayBufferAsText(this._bodyArrayBuffer)); - if (this._bodyFormData) throw new Error("could not read FormData body as text"); - return Promise.resolve(this._bodyText) - }, support.formData && (this.formData = function() { - return this.text().then(decode) - }), this.json = function() { - return this.text().then(JSON.parse) - }, this - } - - function normalizeMethod(method) { - var upcased = method.toUpperCase(); - return methods.indexOf(upcased) > -1 ? upcased : method - } - - function Request(input, options) { - options = options || {}; - var body = options.body; - if ("string" == typeof input) this.url = input; - else { - if (input.bodyUsed) throw new TypeError("Already read"); - this.url = input.url, this.credentials = input.credentials, options.headers || (this.headers = new Headers(input.headers)), this.method = input.method, this.mode = input.mode, body || null == input._bodyInit || (body = input._bodyInit, input.bodyUsed = !0) - } - if (this.credentials = options.credentials || this.credentials || "omit", !options.headers && this.headers || (this.headers = new Headers(options.headers)), this.method = normalizeMethod(options.method || this.method || "GET"), this.mode = options.mode || this.mode || null, this.referrer = null, ("GET" === this.method || "HEAD" === this.method) && body) throw new TypeError("Body not allowed for GET or HEAD requests"); - this._initBody(body) - } - - function decode(body) { - var form = new FormData; - return body.trim().split("&").forEach(function(bytes) { - if (bytes) { - var split = bytes.split("="), - name = split.shift().replace(/\+/g, " "), - value = split.join("=").replace(/\+/g, " "); - form.append(decodeURIComponent(name), decodeURIComponent(value)) - } - }), form - } - - function parseHeaders(rawHeaders) { - var headers = new Headers; - return rawHeaders.split("\r\n").forEach(function(line) { - var parts = line.split(":"), - key = parts.shift().trim(); - if (key) { - var value = parts.join(":").trim(); - headers.append(key, value) - } - }), headers - } - - function Response(bodyInit, options) { - options || (options = {}), this.type = "default", this.status = "status" in options ? options.status : 200, this.ok = this.status >= 200 && this.status < 300, this.statusText = "statusText" in options ? options.statusText : "OK", this.headers = new Headers(options.headers), this.url = options.url || "", this._initBody(bodyInit) - } - if (!self.fetch) { - var support = { - searchParams: "URLSearchParams" in self, - iterable: "Symbol" in self && "iterator" in Symbol, - blob: "FileReader" in self && "Blob" in self && function() { - try { - return new Blob, !0 - } catch (e) { - return !1 - } - }(), - formData: "FormData" in self, - arrayBuffer: "ArrayBuffer" in self - }; - if (support.arrayBuffer) var viewClasses = ["[object Int8Array]", "[object Uint8Array]", "[object Uint8ClampedArray]", "[object Int16Array]", "[object Uint16Array]", "[object Int32Array]", "[object Uint32Array]", "[object Float32Array]", "[object Float64Array]"], - isDataView = function(obj) { - return obj && DataView.prototype.isPrototypeOf(obj) - }, - isArrayBufferView = ArrayBuffer.isView || function(obj) { - return obj && viewClasses.indexOf(Object.prototype.toString.call(obj)) > -1 - }; - Headers.prototype.append = function(name, value) { - name = normalizeName(name), value = normalizeValue(value); - var list = this.map[name]; - list || (list = [], this.map[name] = list), list.push(value) - }, Headers.prototype.delete = function(name) { - delete this.map[normalizeName(name)] - }, Headers.prototype.get = function(name) { - var values = this.map[normalizeName(name)]; - return values ? values[0] : null - }, Headers.prototype.getAll = function(name) { - return this.map[normalizeName(name)] || [] - }, Headers.prototype.has = function(name) { - return this.map.hasOwnProperty(normalizeName(name)) - }, Headers.prototype.set = function(name, value) { - this.map[normalizeName(name)] = [normalizeValue(value)] - }, Headers.prototype.forEach = function(callback, thisArg) { - Object.getOwnPropertyNames(this.map).forEach(function(name) { - this.map[name].forEach(function(value) { - callback.call(thisArg, value, name, this) - }, this) - }, this) - }, Headers.prototype.keys = function() { - var items = []; - return this.forEach(function(value, name) { - items.push(name) - }), iteratorFor(items) - }, Headers.prototype.values = function() { - var items = []; - return this.forEach(function(value) { - items.push(value) - }), iteratorFor(items) - }, Headers.prototype.entries = function() { - var items = []; - return this.forEach(function(value, name) { - items.push([name, value]) - }), iteratorFor(items) - }, support.iterable && (Headers.prototype[Symbol.iterator] = Headers.prototype.entries); - var methods = ["DELETE", "GET", "HEAD", "OPTIONS", "POST", "PUT"]; - Request.prototype.clone = function() { - return new Request(this, { - body: this._bodyInit - }) - }, Body.call(Request.prototype), Body.call(Response.prototype), Response.prototype.clone = function() { - return new Response(this._bodyInit, { - status: this.status, - statusText: this.statusText, - headers: new Headers(this.headers), - url: this.url - }) - }, Response.error = function() { - var response = new Response(null, { - status: 0, - statusText: "" - }); - return response.type = "error", response - }; - var redirectStatuses = [301, 302, 303, 307, 308]; - Response.redirect = function(url, status) { - if (-1 === redirectStatuses.indexOf(status)) throw new RangeError("Invalid status code"); - return new Response(null, { - status: status, - headers: { - location: url - } - }) - }, self.Headers = Headers, self.Request = Request, self.Response = Response, self.fetch = function(input, init) { - return new Promise(function(resolve, reject) { - var request = new Request(input, init), - xhr = new XMLHttpRequest; - xhr.onload = function() { - var options = { - status: xhr.status, - statusText: xhr.statusText, - headers: parseHeaders(xhr.getAllResponseHeaders() || "") - }; - options.url = "responseURL" in xhr ? xhr.responseURL : options.headers.get("X-Request-URL"); - var body = "response" in xhr ? xhr.response : xhr.responseText; - resolve(new Response(body, options)) - }, xhr.onerror = function() { - reject(new TypeError("Network request failed")) - }, xhr.ontimeout = function() { - reject(new TypeError("Network request failed")) - }, xhr.open(request.method, request.url, !0), "include" === request.credentials && (xhr.withCredentials = !0), "responseType" in xhr && support.blob && (xhr.responseType = "blob"), request.headers.forEach(function(value, name) { - xhr.setRequestHeader(name, value) - }), xhr.send(void 0 === request._bodyInit ? null : request._bodyInit) - }) - }, self.fetch.polyfill = !0 - } -}("undefined" != typeof self ? self : this); \ No newline at end of file diff --git a/src/bower_components/native-promise-only/lib/npo.src.js b/src/bower_components/native-promise-only/lib/npo.src.js deleted file mode 100644 index 1c8cb07867..0000000000 --- a/src/bower_components/native-promise-only/lib/npo.src.js +++ /dev/null @@ -1,373 +0,0 @@ -/*! Native Promise Only - v0.8.0-a (c) Kyle Simpson - MIT License: http://getify.mit-license.org -*/ - -(function UMD(name,context,definition){ - // special form of UMD for polyfilling across evironments - context[name] = definition(); - if (typeof module != "undefined" && module.exports) { module.exports = context[name]; } - else if (typeof define == "function" && define.amd) { define(function $AMD$(){ return context[name]; }); } -})("Promise",typeof global != "undefined" ? global : this,function DEF(){ - /*jshint validthis:true */ - "use strict"; - - var builtInProp, cycle, scheduling_queue, - ToString = Object.prototype.toString, - timer = (typeof setImmediate != "undefined") ? - function timer(fn) { return setImmediate(fn); } : - setTimeout - ; - - // dammit, IE8. - try { - Object.defineProperty({},"x",{}); - builtInProp = function builtInProp(obj,name,val,config) { - return Object.defineProperty(obj,name,{ - value: val, - writable: true, - configurable: config !== false - }); - }; - } - catch (err) { - builtInProp = function builtInProp(obj,name,val) { - obj[name] = val; - return obj; - }; - } - - // Note: using a queue instead of array for efficiency - scheduling_queue = (function Queue() { - var first, last, item; - - function Item(fn,self) { - this.fn = fn; - this.self = self; - this.next = void 0; - } - - return { - add: function add(fn,self) { - item = new Item(fn,self); - if (last) { - last.next = item; - } - else { - first = item; - } - last = item; - item = void 0; - }, - drain: function drain() { - var f = first; - first = last = cycle = void 0; - - while (f) { - f.fn.call(f.self); - f = f.next; - } - } - }; - })(); - - function schedule(fn,self) { - scheduling_queue.add(fn,self); - if (!cycle) { - cycle = timer(scheduling_queue.drain); - } - } - - // promise duck typing - function isThenable(o) { - var _then, o_type = typeof o; - - if (o != null && - ( - o_type == "object" || o_type == "function" - ) - ) { - _then = o.then; - } - return typeof _then == "function" ? _then : false; - } - - function notify() { - for (var i=0; i 0) { - schedule(notify,self); - } - } - } - catch (err) { - reject.call(new MakeDefWrapper(self),err); - } - } - - function reject(msg) { - var self = this; - - // already triggered? - if (self.triggered) { return; } - - self.triggered = true; - - // unwrap - if (self.def) { - self = self.def; - } - - self.msg = msg; - self.state = 2; - if (self.chain.length > 0) { - schedule(notify,self); - } - } - - function iteratePromises(Constructor,arr,resolver,rejecter) { - for (var idx=0; idx} arr - * @param {*} key - * @returns {number} - */ - function getIndex(arr, key) { - var result = -1; - - arr.some(function (entry, index) { - if (entry[0] === key) { - result = index; - - return true; - } - - return false; - }); - - return result; - } - - return (function () { - function anonymous() { - this.__entries__ = []; - } - - var prototypeAccessors = { size: { configurable: true } }; - - /** - * @returns {boolean} - */ - prototypeAccessors.size.get = function () { - return this.__entries__.length; - }; - - /** - * @param {*} key - * @returns {*} - */ - anonymous.prototype.get = function (key) { - var index = getIndex(this.__entries__, key); - var entry = this.__entries__[index]; - - return entry && entry[1]; - }; - - /** - * @param {*} key - * @param {*} value - * @returns {void} - */ - anonymous.prototype.set = function (key, value) { - var index = getIndex(this.__entries__, key); - - if (~index) { - this.__entries__[index][1] = value; - } else { - this.__entries__.push([key, value]); - } - }; - - /** - * @param {*} key - * @returns {void} - */ - anonymous.prototype.delete = function (key) { - var entries = this.__entries__; - var index = getIndex(entries, key); - - if (~index) { - entries.splice(index, 1); - } - }; - - /** - * @param {*} key - * @returns {void} - */ - anonymous.prototype.has = function (key) { - return !!~getIndex(this.__entries__, key); - }; - - /** - * @returns {void} - */ - anonymous.prototype.clear = function () { - this.__entries__.splice(0); - }; - - /** - * @param {Function} callback - * @param {*} [ctx=null] - * @returns {void} - */ - anonymous.prototype.forEach = function (callback, ctx) { - var this$1 = this; - if ( ctx === void 0 ) ctx = null; - - for (var i = 0, list = this$1.__entries__; i < list.length; i += 1) { - var entry = list[i]; - - callback.call(ctx, entry[1], entry[0]); - } - }; - - Object.defineProperties( anonymous.prototype, prototypeAccessors ); - - return anonymous; - }()); -})(); - -/** - * Detects whether window and document objects are available in current environment. - */ -var isBrowser = typeof window !== 'undefined' && typeof document !== 'undefined' && window.document === document; - -// Returns global object of a current environment. -var global$1 = (function () { - if (typeof global !== 'undefined' && global.Math === Math) { - return global; - } - - if (typeof self !== 'undefined' && self.Math === Math) { - return self; - } - - if (typeof window !== 'undefined' && window.Math === Math) { - return window; - } - - // eslint-disable-next-line no-new-func - return Function('return this')(); -})(); - -/** - * A shim for the requestAnimationFrame which falls back to the setTimeout if - * first one is not supported. - * - * @returns {number} Requests' identifier. - */ -var requestAnimationFrame$1 = (function () { - if (typeof requestAnimationFrame === 'function') { - // It's required to use a bounded function because IE sometimes throws - // an "Invalid calling object" error if rAF is invoked without the global - // object on the left hand side. - return requestAnimationFrame.bind(global$1); - } - - return function (callback) { return setTimeout(function () { return callback(Date.now()); }, 1000 / 60); }; -})(); - -// Defines minimum timeout before adding a trailing call. -var trailingTimeout = 2; - -/** - * Creates a wrapper function which ensures that provided callback will be - * invoked only once during the specified delay period. - * - * @param {Function} callback - Function to be invoked after the delay period. - * @param {number} delay - Delay after which to invoke callback. - * @returns {Function} - */ -var throttle = function (callback, delay) { - var leadingCall = false, - trailingCall = false, - lastCallTime = 0; - - /** - * Invokes the original callback function and schedules new invocation if - * the "proxy" was called during current request. - * - * @returns {void} - */ - function resolvePending() { - if (leadingCall) { - leadingCall = false; - - callback(); - } - - if (trailingCall) { - proxy(); - } - } - - /** - * Callback invoked after the specified delay. It will further postpone - * invocation of the original function delegating it to the - * requestAnimationFrame. - * - * @returns {void} - */ - function timeoutCallback() { - requestAnimationFrame$1(resolvePending); - } - - /** - * Schedules invocation of the original function. - * - * @returns {void} - */ - function proxy() { - var timeStamp = Date.now(); - - if (leadingCall) { - // Reject immediately following calls. - if (timeStamp - lastCallTime < trailingTimeout) { - return; - } - - // Schedule new call to be in invoked when the pending one is resolved. - // This is important for "transitions" which never actually start - // immediately so there is a chance that we might miss one if change - // happens amids the pending invocation. - trailingCall = true; - } else { - leadingCall = true; - trailingCall = false; - - setTimeout(timeoutCallback, delay); - } - - lastCallTime = timeStamp; - } - - return proxy; -}; - -// Minimum delay before invoking the update of observers. -var REFRESH_DELAY = 20; - -// A list of substrings of CSS properties used to find transition events that -// might affect dimensions of observed elements. -var transitionKeys = ['top', 'right', 'bottom', 'left', 'width', 'height', 'size', 'weight']; - -// Check if MutationObserver is available. -var mutationObserverSupported = typeof MutationObserver !== 'undefined'; - -/** - * Singleton controller class which handles updates of ResizeObserver instances. - */ -var ResizeObserverController = function() { - this.connected_ = false; - this.mutationEventsAdded_ = false; - this.mutationsObserver_ = null; - this.observers_ = []; - - this.onTransitionEnd_ = this.onTransitionEnd_.bind(this); - this.refresh = throttle(this.refresh.bind(this), REFRESH_DELAY); -}; - -/** - * Adds observer to observers list. - * - * @param {ResizeObserverSPI} observer - Observer to be added. - * @returns {void} - */ - - -/** - * Holds reference to the controller's instance. - * - * @private {ResizeObserverController} - */ - - -/** - * Keeps reference to the instance of MutationObserver. - * - * @private {MutationObserver} - */ - -/** - * Indicates whether DOM listeners have been added. - * - * @private {boolean} - */ -ResizeObserverController.prototype.addObserver = function (observer) { - if (!~this.observers_.indexOf(observer)) { - this.observers_.push(observer); - } - - // Add listeners if they haven't been added yet. - if (!this.connected_) { - this.connect_(); - } -}; - -/** - * Removes observer from observers list. - * - * @param {ResizeObserverSPI} observer - Observer to be removed. - * @returns {void} - */ -ResizeObserverController.prototype.removeObserver = function (observer) { - var observers = this.observers_; - var index = observers.indexOf(observer); - - // Remove observer if it's present in registry. - if (~index) { - observers.splice(index, 1); - } - - // Remove listeners if controller has no connected observers. - if (!observers.length && this.connected_) { - this.disconnect_(); - } -}; - -/** - * Invokes the update of observers. It will continue running updates insofar - * it detects changes. - * - * @returns {void} - */ -ResizeObserverController.prototype.refresh = function () { - var changesDetected = this.updateObservers_(); - - // Continue running updates if changes have been detected as there might - // be future ones caused by CSS transitions. - if (changesDetected) { - this.refresh(); - } -}; - -/** - * Updates every observer from observers list and notifies them of queued - * entries. - * - * @private - * @returns {boolean} Returns "true" if any observer has detected changes in - * dimensions of it's elements. - */ -ResizeObserverController.prototype.updateObservers_ = function () { - // Collect observers that have active observations. - var activeObservers = this.observers_.filter(function (observer) { - return observer.gatherActive(), observer.hasActive(); - }); - - // Deliver notifications in a separate cycle in order to avoid any - // collisions between observers, e.g. when multiple instances of - // ResizeObserver are tracking the same element and the callback of one - // of them changes content dimensions of the observed target. Sometimes - // this may result in notifications being blocked for the rest of observers. - activeObservers.forEach(function (observer) { return observer.broadcastActive(); }); - - return activeObservers.length > 0; -}; - -/** - * Initializes DOM listeners. - * - * @private - * @returns {void} - */ -ResizeObserverController.prototype.connect_ = function () { - // Do nothing if running in a non-browser environment or if listeners - // have been already added. - if (!isBrowser || this.connected_) { - return; - } - - // Subscription to the "Transitionend" event is used as a workaround for - // delayed transitions. This way it's possible to capture at least the - // final state of an element. - document.addEventListener('transitionend', this.onTransitionEnd_); - - window.addEventListener('resize', this.refresh); - window.addEventListener('orientationchange', this.refresh); - - if (mutationObserverSupported) { - this.mutationsObserver_ = new MutationObserver(this.refresh); - - this.mutationsObserver_.observe(document, { - attributes: true, - childList: true, - characterData: true, - subtree: true - }); - } else { - document.addEventListener('DOMSubtreeModified', this.refresh); - - this.mutationEventsAdded_ = true; - } - - this.connected_ = true; -}; - -/** - * Removes DOM listeners. - * - * @private - * @returns {void} - */ -ResizeObserverController.prototype.disconnect_ = function () { - // Do nothing if running in a non-browser environment or if listeners - // have been already removed. - if (!isBrowser || !this.connected_) { - return; - } - - document.removeEventListener('transitionend', this.onTransitionEnd_); - window.removeEventListener('resize', this.refresh); - window.removeEventListener('orientationchange', this.refresh); - - if (this.mutationsObserver_) { - this.mutationsObserver_.disconnect(); - } - - if (this.mutationEventsAdded_) { - document.removeEventListener('DOMSubtreeModified', this.refresh); - } - - this.mutationsObserver_ = null; - this.mutationEventsAdded_ = false; - this.connected_ = false; -}; - -/** - * "Transitionend" event handler. - * - * @private - * @param {TransitionEvent} event - * @returns {void} - */ -ResizeObserverController.prototype.onTransitionEnd_ = function (ref) { - var propertyName = ref.propertyName; if ( propertyName === void 0 ) propertyName = ''; - - // Detect whether transition may affect dimensions of an element. - var isReflowProperty = transitionKeys.some(function (key) { - return !!~propertyName.indexOf(key); - }); - - if (isReflowProperty) { - this.refresh(); - } -}; - -/** - * Returns instance of the ResizeObserverController. - * - * @returns {ResizeObserverController} - */ -ResizeObserverController.getInstance = function () { - if (!this.instance_) { - this.instance_ = new ResizeObserverController(); - } - - return this.instance_; -}; - -ResizeObserverController.instance_ = null; - -/** - * Defines non-writable/enumerable properties of the provided target object. - * - * @param {Object} target - Object for which to define properties. - * @param {Object} props - Properties to be defined. - * @returns {Object} Target object. - */ -var defineConfigurable = (function (target, props) { - for (var i = 0, list = Object.keys(props); i < list.length; i += 1) { - var key = list[i]; - - Object.defineProperty(target, key, { - value: props[key], - enumerable: false, - writable: false, - configurable: true - }); - } - - return target; -}); - -/** - * Returns the global object associated with provided element. - * - * @param {Object} target - * @returns {Object} - */ -var getWindowOf = (function (target) { - // Assume that the element is an instance of Node, which means that it - // has the "ownerDocument" property from which we can retrieve a - // corresponding global object. - var ownerGlobal = target && target.ownerDocument && target.ownerDocument.defaultView; - - // Return the local global object if it's not possible extract one from - // provided element. - return ownerGlobal || global$1; -}); - -// Placeholder of an empty content rectangle. -var emptyRect = createRectInit(0, 0, 0, 0); - -/** - * Converts provided string to a number. - * - * @param {number|string} value - * @returns {number} - */ -function toFloat(value) { - return parseFloat(value) || 0; -} - -/** - * Extracts borders size from provided styles. - * - * @param {CSSStyleDeclaration} styles - * @param {...string} positions - Borders positions (top, right, ...) - * @returns {number} - */ -function getBordersSize(styles) { - var positions = [], len = arguments.length - 1; - while ( len-- > 0 ) positions[ len ] = arguments[ len + 1 ]; - - return positions.reduce(function (size, position) { - var value = styles['border-' + position + '-width']; - - return size + toFloat(value); - }, 0); -} - -/** - * Extracts paddings sizes from provided styles. - * - * @param {CSSStyleDeclaration} styles - * @returns {Object} Paddings box. - */ -function getPaddings(styles) { - var positions = ['top', 'right', 'bottom', 'left']; - var paddings = {}; - - for (var i = 0, list = positions; i < list.length; i += 1) { - var position = list[i]; - - var value = styles['padding-' + position]; - - paddings[position] = toFloat(value); - } - - return paddings; -} - -/** - * Calculates content rectangle of provided SVG element. - * - * @param {SVGGraphicsElement} target - Element content rectangle of which needs - * to be calculated. - * @returns {DOMRectInit} - */ -function getSVGContentRect(target) { - var bbox = target.getBBox(); - - return createRectInit(0, 0, bbox.width, bbox.height); -} - -/** - * Calculates content rectangle of provided HTMLElement. - * - * @param {HTMLElement} target - Element for which to calculate the content rectangle. - * @returns {DOMRectInit} - */ -function getHTMLElementContentRect(target) { - - var rect = target.getBoundingClientRect(); - return createRectInit(rect.left, rect.top, rect.width, rect.height); -} - -/** - * Checks whether provided element is a document element (). - * - * @param {Element} target - Element to be checked. - * @returns {boolean} - */ -function isDocumentElement(target) { - return target === getWindowOf(target).document.documentElement; -} - -/** - * Calculates an appropriate content rectangle for provided html or svg element. - * - * @param {Element} target - Element content rectangle of which needs to be calculated. - * @returns {DOMRectInit} - */ -function getContentRect(target) { - if (!isBrowser) { - return emptyRect; - } - - return getHTMLElementContentRect(target); -} - -/** - * Creates rectangle with an interface of the DOMRectReadOnly. - * Spec: https://drafts.fxtf.org/geometry/#domrectreadonly - * - * @param {DOMRectInit} rectInit - Object with rectangle's x/y coordinates and dimensions. - * @returns {DOMRectReadOnly} - */ -function createReadOnlyRect(ref) { - var x = ref.x; - var y = ref.y; - var width = ref.width; - var height = ref.height; - - // If DOMRectReadOnly is available use it as a prototype for the rectangle. - var Constr = typeof DOMRectReadOnly !== 'undefined' ? DOMRectReadOnly : Object; - var rect = Object.create(Constr.prototype); - - // Rectangle's properties are not writable and non-enumerable. - defineConfigurable(rect, { - x: x, y: y, width: width, height: height, - top: y, - right: x + width, - bottom: height + y, - left: x - }); - - return rect; -} - -/** - * Creates DOMRectInit object based on the provided dimensions and the x/y coordinates. - * Spec: https://drafts.fxtf.org/geometry/#dictdef-domrectinit - * - * @param {number} x - X coordinate. - * @param {number} y - Y coordinate. - * @param {number} width - Rectangle's width. - * @param {number} height - Rectangle's height. - * @returns {DOMRectInit} - */ -function createRectInit(x, y, width, height) { - return { x: x, y: y, width: width, height: height }; -} - -/** - * Class that is responsible for computations of the content rectangle of - * provided DOM element and for keeping track of it's changes. - */ -var ResizeObservation = function(target) { - this.broadcastWidth = 0; - this.broadcastHeight = 0; - this.contentRect_ = createRectInit(0, 0, 0, 0); - - this.target = target; -}; - -/** - * Updates content rectangle and tells whether it's width or height properties - * have changed since the last broadcast. - * - * @returns {boolean} - */ - - -/** - * Reference to the last observed content rectangle. - * - * @private {DOMRectInit} - */ - - -/** - * Broadcasted width of content rectangle. - * - * @type {number} - */ -ResizeObservation.prototype.isActive = function () { - var rect = getContentRect(this.target); - - this.contentRect_ = rect; - return rect.width !== this.broadcastWidth || rect.height !== this.broadcastHeight; -}; - -/** - * Updates 'broadcastWidth' and 'broadcastHeight' properties with a data - * from the corresponding properties of the last observed content rectangle. - * - * @returns {DOMRectInit} Last observed content rectangle. - */ -ResizeObservation.prototype.broadcastRect = function () { - var rect = this.contentRect_; - - this.broadcastWidth = rect.width; - this.broadcastHeight = rect.height; - - return rect; -}; - -var ResizeObserverEntry = function(target, rectInit) { - var contentRect = createReadOnlyRect(rectInit); - - // According to the specification following properties are not writable - // and are also not enumerable in the native implementation. - // - // Property accessors are not being used as they'd require to define a - // private WeakMap storage which may cause memory leaks in browsers that - // don't support this type of collections. - defineConfigurable(this, { target: target, contentRect: contentRect }); -}; - -var ResizeObserverSPI = function(callback, controller, callbackCtx) { - this.activeObservations_ = []; - this.observations_ = new MapShim(); - - if (typeof callback !== 'function') { - throw new TypeError('The callback provided as parameter 1 is not a function.'); - } - - this.callback_ = callback; - this.controller_ = controller; - this.callbackCtx_ = callbackCtx; -}; - -/** - * Starts observing provided element. - * - * @param {Element} target - Element to be observed. - * @returns {void} - */ - - -/** - * Registry of the ResizeObservation instances. - * - * @private {Map} - */ - - -/** - * Public ResizeObserver instance which will be passed to the callback - * function and used as a value of it's "this" binding. - * - * @private {ResizeObserver} - */ - -/** - * Collection of resize observations that have detected changes in dimensions - * of elements. - * - * @private {Array} - */ -ResizeObserverSPI.prototype.observe = function (target) { - if (!arguments.length) { - throw new TypeError('1 argument required, but only 0 present.'); - } - - // Do nothing if current environment doesn't have the Element interface. - if (typeof Element === 'undefined' || !(Element instanceof Object)) { - return; - } - - if (!(target instanceof getWindowOf(target).Element)) { - throw new TypeError('parameter 1 is not of type "Element".'); - } - - var observations = this.observations_; - - // Do nothing if element is already being observed. - if (observations.has(target)) { - return; - } - - observations.set(target, new ResizeObservation(target)); - - this.controller_.addObserver(this); - - // Force the update of observations. - this.controller_.refresh(); -}; - -/** - * Stops observing provided element. - * - * @param {Element} target - Element to stop observing. - * @returns {void} - */ -ResizeObserverSPI.prototype.unobserve = function (target) { - if (!arguments.length) { - throw new TypeError('1 argument required, but only 0 present.'); - } - - // Do nothing if current environment doesn't have the Element interface. - if (typeof Element === 'undefined' || !(Element instanceof Object)) { - return; - } - - if (!(target instanceof getWindowOf(target).Element)) { - throw new TypeError('parameter 1 is not of type "Element".'); - } - - var observations = this.observations_; - - // Do nothing if element is not being observed. - if (!observations.has(target)) { - return; - } - - observations.delete(target); - - if (!observations.size) { - this.controller_.removeObserver(this); - } -}; - -/** - * Stops observing all elements. - * - * @returns {void} - */ -ResizeObserverSPI.prototype.disconnect = function () { - this.clearActive(); - this.observations_.clear(); - this.controller_.removeObserver(this); -}; - -/** - * Collects observation instances the associated element of which has changed - * it's content rectangle. - * - * @returns {void} - */ -ResizeObserverSPI.prototype.gatherActive = function () { - var this$1 = this; - - this.clearActive(); - - this.observations_.forEach(function (observation) { - if (observation.isActive()) { - this$1.activeObservations_.push(observation); - } - }); -}; - -/** - * Invokes initial callback function with a list of ResizeObserverEntry - * instances collected from active resize observations. - * - * @returns {void} - */ -ResizeObserverSPI.prototype.broadcastActive = function () { - // Do nothing if observer doesn't have active observations. - if (!this.hasActive()) { - return; - } - - var ctx = this.callbackCtx_; - - // Create ResizeObserverEntry instance for every active observation. - var entries = this.activeObservations_.map(function (observation) { - return new ResizeObserverEntry(observation.target, observation.broadcastRect()); - }); - - this.callback_.call(ctx, entries, ctx); - this.clearActive(); -}; - -/** - * Clears the collection of active observations. - * - * @returns {void} - */ -ResizeObserverSPI.prototype.clearActive = function () { - this.activeObservations_.splice(0); -}; - -/** - * Tells whether observer has active observations. - * - * @returns {boolean} - */ -ResizeObserverSPI.prototype.hasActive = function () { - return this.activeObservations_.length > 0; -}; - -// Registry of internal observers. If WeakMap is not available use current shim -// for the Map collection as it has all required methods and because WeakMap -// can't be fully polyfilled anyway. -var observers = typeof WeakMap !== 'undefined' ? new WeakMap() : new MapShim(); - -/** - * ResizeObserver API. Encapsulates the ResizeObserver SPI implementation - * exposing only those methods and properties that are defined in the spec. - */ -var ResizeObserver = function(callback) { - if (!(this instanceof ResizeObserver)) { - throw new TypeError('Cannot call a class as a function.'); - } - if (!arguments.length) { - throw new TypeError('1 argument required, but only 0 present.'); - } - - var controller = ResizeObserverController.getInstance(); - var observer = new ResizeObserverSPI(callback, controller, this); - - observers.set(this, observer); -}; - -// Expose public methods of ResizeObserver. -['observe', 'unobserve', 'disconnect'].forEach(function (method) { - ResizeObserver.prototype[method] = function () { - return (ref = observers.get(this))[method].apply(ref, arguments); - var ref; - }; -}); - -var index = (function () { - // Export existing implementation if available. - if (typeof global$1.ResizeObserver !== 'undefined') { - return global$1.ResizeObserver; - } - - return ResizeObserver; -})(); - -return index; - -}))); diff --git a/src/bower_components/webcomponentsjs/webcomponents-lite.min.js b/src/bower_components/webcomponentsjs/webcomponents-lite.min.js deleted file mode 100644 index 163ef436fc..0000000000 --- a/src/bower_components/webcomponentsjs/webcomponents-lite.min.js +++ /dev/null @@ -1,1571 +0,0 @@ -/** - * @license - * Copyright (c) 2014 The Polymer Project Authors. All rights reserved. - * This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt - * The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt - * The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt - * Code distributed by Google as part of the polymer project is also - * subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt - */ -// @version 0.7.24 -! function() { - window.WebComponents = window.WebComponents || { - flags: {} - }; - var e = "webcomponents-lite.js", - t = document.querySelector('script[src*="' + e + '"]'), - n = {}; - if (!n.noOpts) { - if (location.search.slice(1).split("&").forEach(function(e) { - var t, o = e.split("="); - o[0] && (t = o[0].match(/wc-(.+)/)) && (n[t[1]] = o[1] || !0) - }), t) - for (var o, r = 0; o = t.attributes[r]; r++) "src" !== o.name && (n[o.name] = o.value || !0); - if (n.log && n.log.split) { - var i = n.log.split(","); - n.log = {}, i.forEach(function(e) { - n.log[e] = !0 - }) - } else n.log = {} - } - n.register && (window.CustomElements = window.CustomElements || { - flags: {} - }, window.CustomElements.flags.register = n.register), WebComponents.flags = n -}(), -function(e) { - "use strict"; - - function t(e) { - return void 0 !== h[e] - } - - function n() { - s.call(this), this._isInvalid = !0 - } - - function o(e) { - return "" == e && n.call(this), e.toLowerCase() - } - - function r(e) { - var t = e.charCodeAt(0); - return t > 32 && t < 127 && [34, 35, 60, 62, 63, 96].indexOf(t) == -1 ? e : encodeURIComponent(e) - } - - function i(e) { - var t = e.charCodeAt(0); - return t > 32 && t < 127 && [34, 35, 60, 62, 96].indexOf(t) == -1 ? e : encodeURIComponent(e) - } - - function a(e, a, s) { - function c(e) { - g.push(e) - } - var d = a || "scheme start", - l = 0, - u = "", - w = !1, - _ = !1, - g = []; - e: for (; - (e[l - 1] != p || 0 == l) && !this._isInvalid;) { - var b = e[l]; - switch (d) { - case "scheme start": - if (!b || !m.test(b)) { - if (a) { - c("Invalid scheme."); - break e - } - u = "", d = "no scheme"; - continue - } - u += b.toLowerCase(), d = "scheme"; - break; - case "scheme": - if (b && v.test(b)) u += b.toLowerCase(); - else { - if (":" != b) { - if (a) { - if (p == b) break e; - c("Code point not allowed in scheme: " + b); - break e - } - u = "", l = 0, d = "no scheme"; - continue - } - if (this._scheme = u, u = "", a) break e; - t(this._scheme) && (this._isRelative = !0), d = "file" == this._scheme ? "relative" : this._isRelative && s && s._scheme == this._scheme ? "relative or authority" : this._isRelative ? "authority first slash" : "scheme data" - } - break; - case "scheme data": - "?" == b ? (this._query = "?", d = "query") : "#" == b ? (this._fragment = "#", d = "fragment") : p != b && "\t" != b && "\n" != b && "\r" != b && (this._schemeData += r(b)); - break; - case "no scheme": - if (s && t(s._scheme)) { - d = "relative"; - continue - } - c("Missing scheme."), n.call(this); - break; - case "relative or authority": - if ("/" != b || "/" != e[l + 1]) { - c("Expected /, got: " + b), d = "relative"; - continue - } - d = "authority ignore slashes"; - break; - case "relative": - if (this._isRelative = !0, "file" != this._scheme && (this._scheme = s._scheme), p == b) { - this._host = s._host, this._port = s._port, this._path = s._path.slice(), this._query = s._query, this._username = s._username, this._password = s._password; - break e - } - if ("/" == b || "\\" == b) "\\" == b && c("\\ is an invalid code point."), d = "relative slash"; - else if ("?" == b) this._host = s._host, this._port = s._port, this._path = s._path.slice(), this._query = "?", this._username = s._username, this._password = s._password, d = "query"; - else { - if ("#" != b) { - var y = e[l + 1], - E = e[l + 2]; - ("file" != this._scheme || !m.test(b) || ":" != y && "|" != y || p != E && "/" != E && "\\" != E && "?" != E && "#" != E) && (this._host = s._host, this._port = s._port, this._username = s._username, this._password = s._password, this._path = s._path.slice(), this._path.pop()), d = "relative path"; - continue - } - this._host = s._host, this._port = s._port, this._path = s._path.slice(), this._query = s._query, this._fragment = "#", this._username = s._username, this._password = s._password, d = "fragment" - } - break; - case "relative slash": - if ("/" != b && "\\" != b) { - "file" != this._scheme && (this._host = s._host, this._port = s._port, this._username = s._username, this._password = s._password), d = "relative path"; - continue - } - "\\" == b && c("\\ is an invalid code point."), d = "file" == this._scheme ? "file host" : "authority ignore slashes"; - break; - case "authority first slash": - if ("/" != b) { - c("Expected '/', got: " + b), d = "authority ignore slashes"; - continue - } - d = "authority second slash"; - break; - case "authority second slash": - if (d = "authority ignore slashes", "/" != b) { - c("Expected '/', got: " + b); - continue - } - break; - case "authority ignore slashes": - if ("/" != b && "\\" != b) { - d = "authority"; - continue - } - c("Expected authority, got: " + b); - break; - case "authority": - if ("@" == b) { - w && (c("@ already seen."), u += "%40"), w = !0; - for (var L = 0; L < u.length; L++) { - var N = u[L]; - if ("\t" != N && "\n" != N && "\r" != N) - if (":" != N || null !== this._password) { - var M = r(N); - null !== this._password ? this._password += M : this._username += M - } else this._password = ""; - else c("Invalid whitespace in authority.") - } - u = "" - } else { - if (p == b || "/" == b || "\\" == b || "?" == b || "#" == b) { - l -= u.length, u = "", d = "host"; - continue - } - u += b - } - break; - case "file host": - if (p == b || "/" == b || "\\" == b || "?" == b || "#" == b) { - 2 != u.length || !m.test(u[0]) || ":" != u[1] && "|" != u[1] ? 0 == u.length ? d = "relative path start" : (this._host = o.call(this, u), u = "", d = "relative path start") : d = "relative path"; - continue - } - "\t" == b || "\n" == b || "\r" == b ? c("Invalid whitespace in file host.") : u += b; - break; - case "host": - case "hostname": - if (":" != b || _) { - if (p == b || "/" == b || "\\" == b || "?" == b || "#" == b) { - if (this._host = o.call(this, u), u = "", d = "relative path start", a) break e; - continue - } - "\t" != b && "\n" != b && "\r" != b ? ("[" == b ? _ = !0 : "]" == b && (_ = !1), u += b) : c("Invalid code point in host/hostname: " + b) - } else if (this._host = o.call(this, u), u = "", d = "port", "hostname" == a) break e; - break; - case "port": - if (/[0-9]/.test(b)) u += b; - else { - if (p == b || "/" == b || "\\" == b || "?" == b || "#" == b || a) { - if ("" != u) { - var T = parseInt(u, 10); - T != h[this._scheme] && (this._port = T + ""), u = "" - } - if (a) break e; - d = "relative path start"; - continue - } - "\t" == b || "\n" == b || "\r" == b ? c("Invalid code point in port: " + b) : n.call(this) - } - break; - case "relative path start": - if ("\\" == b && c("'\\' not allowed in path."), d = "relative path", "/" != b && "\\" != b) continue; - break; - case "relative path": - if (p != b && "/" != b && "\\" != b && (a || "?" != b && "#" != b)) "\t" != b && "\n" != b && "\r" != b && (u += r(b)); - else { - "\\" == b && c("\\ not allowed in relative path."); - var O; - (O = f[u.toLowerCase()]) && (u = O), ".." == u ? (this._path.pop(), "/" != b && "\\" != b && this._path.push("")) : "." == u && "/" != b && "\\" != b ? this._path.push("") : "." != u && ("file" == this._scheme && 0 == this._path.length && 2 == u.length && m.test(u[0]) && "|" == u[1] && (u = u[0] + ":"), this._path.push(u)), u = "", "?" == b ? (this._query = "?", d = "query") : "#" == b && (this._fragment = "#", d = "fragment") - } - break; - case "query": - a || "#" != b ? p != b && "\t" != b && "\n" != b && "\r" != b && (this._query += i(b)) : (this._fragment = "#", d = "fragment"); - break; - case "fragment": - p != b && "\t" != b && "\n" != b && "\r" != b && (this._fragment += b) - } - l++ - } - } - - function s() { - this._scheme = "", this._schemeData = "", this._username = "", this._password = null, this._host = "", this._port = "", this._path = [], this._query = "", this._fragment = "", this._isInvalid = !1, this._isRelative = !1 - } - - function c(e, t) { - void 0 === t || t instanceof c || (t = new c(String(t))), this._url = e, s.call(this); - var n = e.replace(/^[ \t\r\n\f]+|[ \t\r\n\f]+$/g, ""); - a.call(this, n, null, t) - } - var d = !1; - if (!e.forceJURL) try { - var l = new URL("b", "http://a"); - l.pathname = "c%20d", d = "http://a/c%20d" === l.href - } catch (u) {} - if (!d) { - var h = Object.create(null); - h.ftp = 21, h.file = 0, h.gopher = 70, h.http = 80, h.https = 443, h.ws = 80, h.wss = 443; - var f = Object.create(null); - f["%2e"] = ".", f[".%2e"] = "..", f["%2e."] = "..", f["%2e%2e"] = ".."; - var p = void 0, - m = /[a-zA-Z]/, - v = /[a-zA-Z0-9\+\-\.]/; - c.prototype = { - toString: function() { - return this.href - }, - get href() { - if (this._isInvalid) return this._url; - var e = ""; - return "" == this._username && null == this._password || (e = this._username + (null != this._password ? ":" + this._password : "") + "@"), this.protocol + (this._isRelative ? "//" + e + this.host : "") + this.pathname + this._query + this._fragment - }, - set href(e) { - s.call(this), a.call(this, e) - }, - get protocol() { - return this._scheme + ":" - }, - set protocol(e) { - this._isInvalid || a.call(this, e + ":", "scheme start") - }, - get host() { - return this._isInvalid ? "" : this._port ? this._host + ":" + this._port : this._host - }, - set host(e) { - !this._isInvalid && this._isRelative && a.call(this, e, "host") - }, - get hostname() { - return this._host - }, - set hostname(e) { - !this._isInvalid && this._isRelative && a.call(this, e, "hostname") - }, - get port() { - return this._port - }, - set port(e) { - !this._isInvalid && this._isRelative && a.call(this, e, "port") - }, - get pathname() { - return this._isInvalid ? "" : this._isRelative ? "/" + this._path.join("/") : this._schemeData - }, - set pathname(e) { - !this._isInvalid && this._isRelative && (this._path = [], a.call(this, e, "relative path start")) - }, - get search() { - return this._isInvalid || !this._query || "?" == this._query ? "" : this._query - }, - set search(e) { - !this._isInvalid && this._isRelative && (this._query = "?", "?" == e[0] && (e = e.slice(1)), a.call(this, e, "query")) - }, - get hash() { - return this._isInvalid || !this._fragment || "#" == this._fragment ? "" : this._fragment - }, - set hash(e) { - this._isInvalid || (this._fragment = "#", "#" == e[0] && (e = e.slice(1)), a.call(this, e, "fragment")) - }, - get origin() { - var e; - if (this._isInvalid || !this._scheme) return ""; - switch (this._scheme) { - case "data": - case "file": - case "javascript": - case "mailto": - return "null" - } - return e = this.host, e ? this._scheme + "://" + e : "" - } - }; - var w = e.URL; - w && (c.createObjectURL = function(e) { - return w.createObjectURL.apply(w, arguments) - }, c.revokeObjectURL = function(e) { - w.revokeObjectURL(e) - }), e.URL = c - } -}(self), "undefined" == typeof WeakMap && ! function() { - var e = Object.defineProperty, - t = Date.now() % 1e9, - n = function() { - this.name = "__st" + (1e9 * Math.random() >>> 0) + (t++ + "__") - }; - n.prototype = { - set: function(t, n) { - var o = t[this.name]; - return o && o[0] === t ? o[1] = n : e(t, this.name, { - value: [t, n], - writable: !0 - }), this - }, - get: function(e) { - var t; - return (t = e[this.name]) && t[0] === e ? t[1] : void 0 - }, - "delete": function(e) { - var t = e[this.name]; - return !(!t || t[0] !== e) && (t[0] = t[1] = void 0, !0) - }, - has: function(e) { - var t = e[this.name]; - return !!t && t[0] === e - } - }, window.WeakMap = n - }(), - function(e) { - function t(e) { - b.push(e), g || (g = !0, m(o)) - } - - function n(e) { - return window.ShadowDOMPolyfill && window.ShadowDOMPolyfill.wrapIfNeeded(e) || e - } - - function o() { - g = !1; - var e = b; - b = [], e.sort(function(e, t) { - return e.uid_ - t.uid_ - }); - var t = !1; - e.forEach(function(e) { - var n = e.takeRecords(); - r(e), n.length && (e.callback_(n, e), t = !0) - }), t && o() - } - - function r(e) { - e.nodes_.forEach(function(t) { - var n = v.get(t); - n && n.forEach(function(t) { - t.observer === e && t.removeTransientObservers() - }) - }) - } - - function i(e, t) { - for (var n = e; n; n = n.parentNode) { - var o = v.get(n); - if (o) - for (var r = 0; r < o.length; r++) { - var i = o[r], - a = i.options; - if (n === e || a.subtree) { - var s = t(a); - s && i.enqueue(s) - } - } - } - } - - function a(e) { - this.callback_ = e, this.nodes_ = [], this.records_ = [], this.uid_ = ++y - } - - function s(e, t) { - this.type = e, this.target = t, this.addedNodes = [], this.removedNodes = [], this.previousSibling = null, this.nextSibling = null, this.attributeName = null, this.attributeNamespace = null, this.oldValue = null - } - - function c(e) { - var t = new s(e.type, e.target); - return t.addedNodes = e.addedNodes.slice(), t.removedNodes = e.removedNodes.slice(), t.previousSibling = e.previousSibling, t.nextSibling = e.nextSibling, t.attributeName = e.attributeName, t.attributeNamespace = e.attributeNamespace, t.oldValue = e.oldValue, t - } - - function d(e, t) { - return E = new s(e, t) - } - - function l(e) { - return L ? L : (L = c(E), L.oldValue = e, L) - } - - function u() { - E = L = void 0 - } - - function h(e) { - return e === L || e === E - } - - function f(e, t) { - return e === t ? e : L && h(e) ? L : null - } - - function p(e, t, n) { - this.observer = e, this.target = t, this.options = n, this.transientObservedNodes = [] - } - if (!e.JsMutationObserver) { - var m, v = new WeakMap; - if (/Trident|Edge/.test(navigator.userAgent)) m = setTimeout; - else if (window.setImmediate) m = window.setImmediate; - else { - var w = [], - _ = String(Math.random()); - window.addEventListener("message", function(e) { - if (e.data === _) { - var t = w; - w = [], t.forEach(function(e) { - e() - }) - } - }), m = function(e) { - w.push(e), window.postMessage(_, "*") - } - } - var g = !1, - b = [], - y = 0; - a.prototype = { - observe: function(e, t) { - if (e = n(e), !t.childList && !t.attributes && !t.characterData || t.attributeOldValue && !t.attributes || t.attributeFilter && t.attributeFilter.length && !t.attributes || t.characterDataOldValue && !t.characterData) throw new SyntaxError; - var o = v.get(e); - o || v.set(e, o = []); - for (var r, i = 0; i < o.length; i++) - if (o[i].observer === this) { - r = o[i], r.removeListeners(), r.options = t; - break - } r || (r = new p(this, e, t), o.push(r), this.nodes_.push(e)), r.addListeners() - }, - disconnect: function() { - this.nodes_.forEach(function(e) { - for (var t = v.get(e), n = 0; n < t.length; n++) { - var o = t[n]; - if (o.observer === this) { - o.removeListeners(), t.splice(n, 1); - break - } - } - }, this), this.records_ = [] - }, - takeRecords: function() { - var e = this.records_; - return this.records_ = [], e - } - }; - var E, L; - p.prototype = { - enqueue: function(e) { - var n = this.observer.records_, - o = n.length; - if (n.length > 0) { - var r = n[o - 1], - i = f(r, e); - if (i) return void(n[o - 1] = i) - } else t(this.observer); - n[o] = e - }, - addListeners: function() { - this.addListeners_(this.target) - }, - addListeners_: function(e) { - var t = this.options; - t.attributes && e.addEventListener("DOMAttrModified", this, !0), t.characterData && e.addEventListener("DOMCharacterDataModified", this, !0), t.childList && e.addEventListener("DOMNodeInserted", this, !0), (t.childList || t.subtree) && e.addEventListener("DOMNodeRemoved", this, !0) - }, - removeListeners: function() { - this.removeListeners_(this.target) - }, - removeListeners_: function(e) { - var t = this.options; - t.attributes && e.removeEventListener("DOMAttrModified", this, !0), t.characterData && e.removeEventListener("DOMCharacterDataModified", this, !0), t.childList && e.removeEventListener("DOMNodeInserted", this, !0), (t.childList || t.subtree) && e.removeEventListener("DOMNodeRemoved", this, !0) - }, - addTransientObserver: function(e) { - if (e !== this.target) { - this.addListeners_(e), this.transientObservedNodes.push(e); - var t = v.get(e); - t || v.set(e, t = []), t.push(this) - } - }, - removeTransientObservers: function() { - var e = this.transientObservedNodes; - this.transientObservedNodes = [], e.forEach(function(e) { - this.removeListeners_(e); - for (var t = v.get(e), n = 0; n < t.length; n++) - if (t[n] === this) { - t.splice(n, 1); - break - } - }, this) - }, - handleEvent: function(e) { - switch (e.stopImmediatePropagation(), e.type) { - case "DOMAttrModified": - var t = e.attrName, - n = e.relatedNode.namespaceURI, - o = e.target, - r = new d("attributes", o); - r.attributeName = t, r.attributeNamespace = n; - var a = e.attrChange === MutationEvent.ADDITION ? null : e.prevValue; - i(o, function(e) { - if (e.attributes && (!e.attributeFilter || !e.attributeFilter.length || e.attributeFilter.indexOf(t) !== -1 || e.attributeFilter.indexOf(n) !== -1)) return e.attributeOldValue ? l(a) : r - }); - break; - case "DOMCharacterDataModified": - var o = e.target, - r = d("characterData", o), - a = e.prevValue; - i(o, function(e) { - if (e.characterData) return e.characterDataOldValue ? l(a) : r - }); - break; - case "DOMNodeRemoved": - this.addTransientObserver(e.target); - case "DOMNodeInserted": - var s, c, h = e.target; - "DOMNodeInserted" === e.type ? (s = [h], c = []) : (s = [], c = [h]); - var f = h.previousSibling, - p = h.nextSibling, - r = d("childList", e.target.parentNode); - r.addedNodes = s, r.removedNodes = c, r.previousSibling = f, r.nextSibling = p, i(e.relatedNode, function(e) { - if (e.childList) return r - }) - } - u() - } - }, e.JsMutationObserver = a, e.MutationObserver || (e.MutationObserver = a, a._isPolyfilled = !0) - } - }(self), - function() { - function e(e) { - switch (e) { - case "&": - return "&"; - case "<": - return "<"; - case ">": - return ">"; - case " ": - return " " - } - } - - function t(t) { - return t.replace(u, e) - } - var n = "undefined" == typeof HTMLTemplateElement; - /Trident/.test(navigator.userAgent) && ! function() { - var e = document.importNode; - document.importNode = function() { - var t = e.apply(document, arguments); - if (t.nodeType === Node.DOCUMENT_FRAGMENT_NODE) { - var n = document.createDocumentFragment(); - return n.appendChild(t), n - } - return t - } - }(); - var o = function() { - if (!n) { - var e = document.createElement("template"), - t = document.createElement("template"); - t.content.appendChild(document.createElement("div")), e.content.appendChild(t); - var o = e.cloneNode(!0); - return 0 === o.content.childNodes.length || 0 === o.content.firstChild.content.childNodes.length - } - }(), - r = "template", - i = function() {}; - if (n) { - var a = document.implementation.createHTMLDocument("template"), - s = !0, - c = document.createElement("style"); - c.textContent = r + "{display:none;}"; - var d = document.head; - d.insertBefore(c, d.firstElementChild), i.prototype = Object.create(HTMLElement.prototype), i.decorate = function(e) { - if (!e.content) { - e.content = a.createDocumentFragment(); - for (var n; n = e.firstChild;) e.content.appendChild(n); - if (e.cloneNode = function(e) { - return i.cloneNode(this, e) - }, s) try { - Object.defineProperty(e, "innerHTML", { - get: function() { - for (var e = "", n = this.content.firstChild; n; n = n.nextSibling) e += n.outerHTML || t(n.data); - return e - }, - set: function(e) { - for (a.body.innerHTML = e, i.bootstrap(a); this.content.firstChild;) this.content.removeChild(this.content.firstChild); - for (; a.body.firstChild;) this.content.appendChild(a.body.firstChild) - }, - configurable: !0 - }) - } catch (o) { - s = !1 - } - i.bootstrap(e.content) - } - }, i.bootstrap = function(e) { - for (var t, n = e.querySelectorAll(r), o = 0, a = n.length; o < a && (t = n[o]); o++) i.decorate(t) - }, document.addEventListener("DOMContentLoaded", function() { - i.bootstrap(document) - }); - var l = document.createElement; - document.createElement = function() { - "use strict"; - var e = l.apply(document, arguments); - return "template" === e.localName && i.decorate(e), e - }; - var u = /[&\u00A0<>]/g - } - if (n || o) { - var h = Node.prototype.cloneNode; - i.cloneNode = function(e, t) { - var n = h.call(e, !1); - return this.decorate && this.decorate(n), t && (n.content.appendChild(h.call(e.content, !0)), this.fixClonedDom(n.content, e.content)), n - }, i.fixClonedDom = function(e, t) { - if (t.querySelectorAll) - for (var n, o, i = t.querySelectorAll(r), a = e.querySelectorAll(r), s = 0, c = a.length; s < c; s++) o = i[s], n = a[s], this.decorate && this.decorate(o), n.parentNode.replaceChild(o.cloneNode(!0), n) - }; - var f = document.importNode; - Node.prototype.cloneNode = function(e) { - var t = h.call(this, e); - return e && i.fixClonedDom(t, this), t - }, document.importNode = function(e, t) { - if (e.localName === r) return i.cloneNode(e, t); - var n = f.call(document, e, t); - return t && i.fixClonedDom(n, e), n - }, o && (HTMLTemplateElement.prototype.cloneNode = function(e) { - return i.cloneNode(this, e) - }) - } - n && (window.HTMLTemplateElement = i) - }(), - function(e) { - "use strict"; - if (!window.performance || !window.performance.now) { - var t = Date.now(); - window.performance = { - now: function() { - return Date.now() - t - } - } - } - window.requestAnimationFrame || (window.requestAnimationFrame = function() { - var e = window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame; - return e ? function(t) { - return e(function() { - t(performance.now()) - }) - } : function(e) { - return window.setTimeout(e, 1e3 / 60) - } - }()), window.cancelAnimationFrame || (window.cancelAnimationFrame = function() { - return window.webkitCancelAnimationFrame || window.mozCancelAnimationFrame || function(e) { - clearTimeout(e) - } - }()); - var n = function() { - var e = document.createEvent("Event"); - return e.initEvent("foo", !0, !0), e.preventDefault(), e.defaultPrevented - }(); - if (!n) { - var o = Event.prototype.preventDefault; - Event.prototype.preventDefault = function() { - this.cancelable && (o.call(this), Object.defineProperty(this, "defaultPrevented", { - get: function() { - return !0 - }, - configurable: !0 - })) - } - } - var r = /Trident/.test(navigator.userAgent); - if ((!window.CustomEvent || r && "function" != typeof window.CustomEvent) && (window.CustomEvent = function(e, t) { - t = t || {}; - var n = document.createEvent("CustomEvent"); - return n.initCustomEvent(e, Boolean(t.bubbles), Boolean(t.cancelable), t.detail), n - }, window.CustomEvent.prototype = window.Event.prototype), !window.Event || r && "function" != typeof window.Event) { - var i = window.Event; - window.Event = function(e, t) { - t = t || {}; - var n = document.createEvent("Event"); - return n.initEvent(e, Boolean(t.bubbles), Boolean(t.cancelable)), n - }, window.Event.prototype = i.prototype - } - }(window.WebComponents), window.HTMLImports = window.HTMLImports || { - flags: {} - }, - function(e) { - function t(e, t) { - t = t || p, o(function() { - i(e, t) - }, t) - } - - function n(e) { - return "complete" === e.readyState || e.readyState === w - } - - function o(e, t) { - if (n(t)) e && e(); - else { - var r = function() { - "complete" !== t.readyState && t.readyState !== w || (t.removeEventListener(_, r), o(e, t)) - }; - t.addEventListener(_, r) - } - } - - function r(e) { - e.target.__loaded = !0 - } - - function i(e, t) { - function n() { - c == d && e && e({ - allImports: s, - loadedImports: l, - errorImports: u - }) - } - - function o(e) { - r(e), l.push(this), c++, n() - } - - function i(e) { - u.push(this), c++, n() - } - var s = t.querySelectorAll("link[rel=import]"), - c = 0, - d = s.length, - l = [], - u = []; - if (d) - for (var h, f = 0; f < d && (h = s[f]); f++) a(h) ? (l.push(this), c++, n()) : (h.addEventListener("load", o), h.addEventListener("error", i)); - else n() - } - - function a(e) { - return u ? e.__loaded || e["import"] && "loading" !== e["import"].readyState : e.__importParsed - } - - function s(e) { - for (var t, n = 0, o = e.length; n < o && (t = e[n]); n++) c(t) && d(t) - } - - function c(e) { - return "link" === e.localName && "import" === e.rel - } - - function d(e) { - var t = e["import"]; - t ? r({ - target: e - }) : (e.addEventListener("load", r), e.addEventListener("error", r)) - } - var l = "import", - u = Boolean(l in document.createElement("link")), - h = Boolean(window.ShadowDOMPolyfill), - f = function(e) { - return h ? window.ShadowDOMPolyfill.wrapIfNeeded(e) : e - }, - p = f(document), - m = { - get: function() { - var e = window.HTMLImports.currentScript || document.currentScript || ("complete" !== document.readyState ? document.scripts[document.scripts.length - 1] : null); - return f(e) - }, - configurable: !0 - }; - Object.defineProperty(document, "_currentScript", m), Object.defineProperty(p, "_currentScript", m); - var v = /Trident/.test(navigator.userAgent), - w = v ? "complete" : "interactive", - _ = "readystatechange"; - u && (new MutationObserver(function(e) { - for (var t, n = 0, o = e.length; n < o && (t = e[n]); n++) t.addedNodes && s(t.addedNodes) - }).observe(document.head, { - childList: !0 - }), function() { - if ("loading" === document.readyState) - for (var e, t = document.querySelectorAll("link[rel=import]"), n = 0, o = t.length; n < o && (e = t[n]); n++) d(e) - }()), t(function(e) { - window.HTMLImports.ready = !0, window.HTMLImports.readyTime = (new Date).getTime(); - var t = p.createEvent("CustomEvent"); - t.initCustomEvent("HTMLImportsLoaded", !0, !0, e), p.dispatchEvent(t) - }), e.IMPORT_LINK_TYPE = l, e.useNative = u, e.rootDocument = p, e.whenReady = t, e.isIE = v - }(window.HTMLImports), - function(e) { - var t = [], - n = function(e) { - t.push(e) - }, - o = function() { - t.forEach(function(t) { - t(e) - }) - }; - e.addModule = n, e.initializeModules = o - }(window.HTMLImports), window.HTMLImports.addModule(function(e) { - var t = /(url\()([^)]*)(\))/g, - n = /(@import[\s]+(?!url\())([^;]*)(;)/g, - o = { - resolveUrlsInStyle: function(e, t) { - var n = e.ownerDocument, - o = n.createElement("a"); - return e.textContent = this.resolveUrlsInCssText(e.textContent, t, o), e - }, - resolveUrlsInCssText: function(e, o, r) { - var i = this.replaceUrls(e, r, o, t); - return i = this.replaceUrls(i, r, o, n) - }, - replaceUrls: function(e, t, n, o) { - return e.replace(o, function(e, o, r, i) { - var a = r.replace(/["']/g, ""); - return n && (a = new URL(a, n).href), t.href = a, a = t.href, o + "'" + a + "'" + i - }) - } - }; - e.path = o - }), window.HTMLImports.addModule(function(e) { - var t = { - async: !0, - ok: function(e) { - return e.status >= 200 && e.status < 300 || 304 === e.status || 0 === e.status - }, - load: function(n, o, r) { - var i = new XMLHttpRequest; - return (e.flags.debug || e.flags.bust) && (n += "?" + Math.random()), i.open("GET", n, t.async), i.addEventListener("readystatechange", function(e) { - if (4 === i.readyState) { - var n = null; - try { - var a = i.getResponseHeader("Location"); - a && (n = "/" === a.substr(0, 1) ? location.origin + a : a) - } catch (e) { - console.error(e.message) - } - o.call(r, !t.ok(i) && i, i.response || i.responseText, n) - } - }), i.send(), i - }, - loadDocument: function(e, t, n) { - this.load(e, t, n).responseType = "document" - } - }; - e.xhr = t - }), window.HTMLImports.addModule(function(e) { - var t = e.xhr, - n = e.flags, - o = function(e, t) { - this.cache = {}, this.onload = e, this.oncomplete = t, this.inflight = 0, this.pending = {} - }; - o.prototype = { - addNodes: function(e) { - this.inflight += e.length; - for (var t, n = 0, o = e.length; n < o && (t = e[n]); n++) this.require(t); - this.checkDone() - }, - addNode: function(e) { - this.inflight++, this.require(e), this.checkDone() - }, - require: function(e) { - var t = e.src || e.href; - e.__nodeUrl = t, this.dedupe(t, e) || this.fetch(t, e) - }, - dedupe: function(e, t) { - if (this.pending[e]) return this.pending[e].push(t), !0; - return this.cache[e] ? (this.onload(e, t, this.cache[e]), this.tail(), !0) : (this.pending[e] = [t], !1) - }, - fetch: function(e, o) { - if (n.load && console.log("fetch", e, o), e) - if (e.match(/^data:/)) { - var r = e.split(","), - i = r[0], - a = r[1]; - a = i.indexOf(";base64") > -1 ? atob(a) : decodeURIComponent(a), setTimeout(function() { - this.receive(e, o, null, a) - }.bind(this), 0) - } else { - var s = function(t, n, r) { - this.receive(e, o, t, n, r) - }.bind(this); - t.load(e, s) - } - else setTimeout(function() { - this.receive(e, o, { - error: "href must be specified" - }, null) - }.bind(this), 0) - }, - receive: function(e, t, n, o, r) { - this.cache[e] = o; - for (var i, a = this.pending[e], s = 0, c = a.length; s < c && (i = a[s]); s++) this.onload(e, i, o, n, r), this.tail(); - this.pending[e] = null - }, - tail: function() { - --this.inflight, this.checkDone() - }, - checkDone: function() { - this.inflight || this.oncomplete() - } - }, e.Loader = o - }), window.HTMLImports.addModule(function(e) { - var t = function(e) { - this.addCallback = e, this.mo = new MutationObserver(this.handler.bind(this)) - }; - t.prototype = { - handler: function(e) { - for (var t, n = 0, o = e.length; n < o && (t = e[n]); n++) "childList" === t.type && t.addedNodes.length && this.addedNodes(t.addedNodes) - }, - addedNodes: function(e) { - this.addCallback && this.addCallback(e); - for (var t, n = 0, o = e.length; n < o && (t = e[n]); n++) t.children && t.children.length && this.addedNodes(t.children) - }, - observe: function(e) { - this.mo.observe(e, { - childList: !0, - subtree: !0 - }) - } - }, e.Observer = t - }), window.HTMLImports.addModule(function(e) { - function t(e) { - return "link" === e.localName && e.rel === l - } - - function n(e) { - var t = o(e); - return "data:text/javascript;charset=utf-8," + encodeURIComponent(t) - } - - function o(e) { - return e.textContent + r(e) - } - - function r(e) { - var t = e.ownerDocument; - t.__importedScripts = t.__importedScripts || 0; - var n = e.ownerDocument.baseURI, - o = t.__importedScripts ? "-" + t.__importedScripts : ""; - return t.__importedScripts++, "\n//# sourceURL=" + n + o + ".js\n" - } - - function i(e) { - var t = e.ownerDocument.createElement("style"); - return t.textContent = e.textContent, a.resolveUrlsInStyle(t), t - } - var a = e.path, - s = e.rootDocument, - c = e.flags, - d = e.isIE, - l = e.IMPORT_LINK_TYPE, - u = "link[rel=" + l + "]", - h = { - documentSelectors: u, - importsSelectors: [u, "link[rel=stylesheet]:not([type])", "style:not([type])", "script:not([type])", 'script[type="application/javascript"]', 'script[type="text/javascript"]'].join(","), - map: { - link: "parseLink", - script: "parseScript", - style: "parseStyle" - }, - dynamicElements: [], - parseNext: function() { - var e = this.nextToParse(); - e && this.parse(e) - }, - parse: function(e) { - if (this.isParsed(e)) return void(c.parse && console.log("[%s] is already parsed", e.localName)); - var t = this[this.map[e.localName]]; - t && (this.markParsing(e), t.call(this, e)) - }, - parseDynamic: function(e, t) { - this.dynamicElements.push(e), t || this.parseNext() - }, - markParsing: function(e) { - c.parse && console.log("parsing", e), this.parsingElement = e - }, - markParsingComplete: function(e) { - e.__importParsed = !0, this.markDynamicParsingComplete(e), e.__importElement && (e.__importElement.__importParsed = !0, this.markDynamicParsingComplete(e.__importElement)), this.parsingElement = null, c.parse && console.log("completed", e) - }, - markDynamicParsingComplete: function(e) { - var t = this.dynamicElements.indexOf(e); - t >= 0 && this.dynamicElements.splice(t, 1) - }, - parseImport: function(e) { - if (e["import"] = e.__doc, window.HTMLImports.__importsParsingHook && window.HTMLImports.__importsParsingHook(e), e["import"] && (e["import"].__importParsed = !0), this.markParsingComplete(e), e.__resource && !e.__error ? e.dispatchEvent(new CustomEvent("load", { - bubbles: !1 - })) : e.dispatchEvent(new CustomEvent("error", { - bubbles: !1 - })), e.__pending) - for (var t; e.__pending.length;) t = e.__pending.shift(), t && t({ - target: e - }); - this.parseNext() - }, - parseLink: function(e) { - t(e) ? this.parseImport(e) : (e.href = e.href, this.parseGeneric(e)) - }, - parseStyle: function(e) { - var t = e; - e = i(e), t.__appliedElement = e, e.__importElement = t, this.parseGeneric(e) - }, - parseGeneric: function(e) { - this.trackElement(e), this.addElementToDocument(e) - }, - rootImportForElement: function(e) { - for (var t = e; t.ownerDocument.__importLink;) t = t.ownerDocument.__importLink; - return t - }, - addElementToDocument: function(e) { - var t = this.rootImportForElement(e.__importElement || e); - t.parentNode.insertBefore(e, t) - }, - trackElement: function(e, t) { - var n = this, - o = function(r) { - e.removeEventListener("load", o), e.removeEventListener("error", o), t && t(r), n.markParsingComplete(e), n.parseNext() - }; - if (e.addEventListener("load", o), e.addEventListener("error", o), d && "style" === e.localName) { - var r = !1; - if (e.textContent.indexOf("@import") == -1) r = !0; - else if (e.sheet) { - r = !0; - for (var i, a = e.sheet.cssRules, s = a ? a.length : 0, c = 0; c < s && (i = a[c]); c++) i.type === CSSRule.IMPORT_RULE && (r = r && Boolean(i.styleSheet)) - } - r && setTimeout(function() { - e.dispatchEvent(new CustomEvent("load", { - bubbles: !1 - })) - }) - } - }, - parseScript: function(t) { - var o = document.createElement("script"); - o.__importElement = t, o.src = t.src ? t.src : n(t), e.currentScript = t, this.trackElement(o, function(t) { - o.parentNode && o.parentNode.removeChild(o), e.currentScript = null - }), this.addElementToDocument(o) - }, - nextToParse: function() { - return this._mayParse = [], !this.parsingElement && (this.nextToParseInDoc(s) || this.nextToParseDynamic()) - }, - nextToParseInDoc: function(e, n) { - if (e && this._mayParse.indexOf(e) < 0) { - this._mayParse.push(e); - for (var o, r = e.querySelectorAll(this.parseSelectorsForNode(e)), i = 0, a = r.length; i < a && (o = r[i]); i++) - if (!this.isParsed(o)) return this.hasResource(o) ? t(o) ? this.nextToParseInDoc(o.__doc, o) : o : void 0 - } - return n - }, - nextToParseDynamic: function() { - return this.dynamicElements[0] - }, - parseSelectorsForNode: function(e) { - var t = e.ownerDocument || e; - return t === s ? this.documentSelectors : this.importsSelectors - }, - isParsed: function(e) { - return e.__importParsed - }, - needsDynamicParsing: function(e) { - return this.dynamicElements.indexOf(e) >= 0 - }, - hasResource: function(e) { - return !t(e) || void 0 !== e.__doc - } - }; - e.parser = h, e.IMPORT_SELECTOR = u - }), window.HTMLImports.addModule(function(e) { - function t(e) { - return n(e, a) - } - - function n(e, t) { - return "link" === e.localName && e.getAttribute("rel") === t - } - - function o(e) { - return !!Object.getOwnPropertyDescriptor(e, "baseURI") - } - - function r(e, t) { - var n = document.implementation.createHTMLDocument(a); - n._URL = t; - var r = n.createElement("base"); - r.setAttribute("href", t), n.baseURI || o(n) || Object.defineProperty(n, "baseURI", { - value: t - }); - var i = n.createElement("meta"); - return i.setAttribute("charset", "utf-8"), n.head.appendChild(i), n.head.appendChild(r), n.body.innerHTML = e, window.HTMLTemplateElement && HTMLTemplateElement.bootstrap && HTMLTemplateElement.bootstrap(n), n - } - var i = e.flags, - a = e.IMPORT_LINK_TYPE, - s = e.IMPORT_SELECTOR, - c = e.rootDocument, - d = e.Loader, - l = e.Observer, - u = e.parser, - h = { - documents: {}, - documentPreloadSelectors: s, - importsPreloadSelectors: [s].join(","), - loadNode: function(e) { - f.addNode(e) - }, - loadSubtree: function(e) { - var t = this.marshalNodes(e); - f.addNodes(t) - }, - marshalNodes: function(e) { - return e.querySelectorAll(this.loadSelectorsForNode(e)) - }, - loadSelectorsForNode: function(e) { - var t = e.ownerDocument || e; - return t === c ? this.documentPreloadSelectors : this.importsPreloadSelectors - }, - loaded: function(e, n, o, a, s) { - if (i.load && console.log("loaded", e, n), n.__resource = o, n.__error = a, t(n)) { - var c = this.documents[e]; - void 0 === c && (c = a ? null : r(o, s || e), c && (c.__importLink = n, this.bootDocument(c)), this.documents[e] = c), n.__doc = c - } - u.parseNext() - }, - bootDocument: function(e) { - this.loadSubtree(e), this.observer.observe(e), u.parseNext() - }, - loadedAll: function() { - u.parseNext() - } - }, - f = new d(h.loaded.bind(h), h.loadedAll.bind(h)); - if (h.observer = new l, !document.baseURI) { - var p = { - get: function() { - var e = document.querySelector("base"); - return e ? e.href : window.location.href - }, - configurable: !0 - }; - Object.defineProperty(document, "baseURI", p), Object.defineProperty(c, "baseURI", p) - } - e.importer = h, e.importLoader = f - }), window.HTMLImports.addModule(function(e) { - var t = e.parser, - n = e.importer, - o = { - added: function(e) { - for (var o, r, i, a, s = 0, c = e.length; s < c && (a = e[s]); s++) o || (o = a.ownerDocument, r = t.isParsed(o)), i = this.shouldLoadNode(a), i && n.loadNode(a), this.shouldParseNode(a) && r && t.parseDynamic(a, i) - }, - shouldLoadNode: function(e) { - return 1 === e.nodeType && r.call(e, n.loadSelectorsForNode(e)) - }, - shouldParseNode: function(e) { - return 1 === e.nodeType && r.call(e, t.parseSelectorsForNode(e)) - } - }; - n.observer.addCallback = o.added.bind(o); - var r = HTMLElement.prototype.matches || HTMLElement.prototype.matchesSelector || HTMLElement.prototype.webkitMatchesSelector || HTMLElement.prototype.mozMatchesSelector || HTMLElement.prototype.msMatchesSelector - }), - function(e) { - function t() { - window.HTMLImports.importer.bootDocument(o) - } - var n = e.initializeModules; - e.isIE; - if (!e.useNative) { - n(); - var o = e.rootDocument; - "complete" === document.readyState || "interactive" === document.readyState && !window.attachEvent ? t() : document.addEventListener("DOMContentLoaded", t) - } - }(window.HTMLImports), window.CustomElements = window.CustomElements || { - flags: {} - }, - function(e) { - var t = e.flags, - n = [], - o = function(e) { - n.push(e) - }, - r = function() { - n.forEach(function(t) { - t(e) - }) - }; - e.addModule = o, e.initializeModules = r, e.hasNative = Boolean(document.registerElement), e.isIE = /Trident/.test(navigator.userAgent), e.useNative = !t.register && e.hasNative && !window.ShadowDOMPolyfill && (!window.HTMLImports || window.HTMLImports.useNative) - }(window.CustomElements), window.CustomElements.addModule(function(e) { - function t(e, t) { - n(e, function(e) { - return !!t(e) || void o(e, t) - }), o(e, t) - } - - function n(e, t, o) { - var r = e.firstElementChild; - if (!r) - for (r = e.firstChild; r && r.nodeType !== Node.ELEMENT_NODE;) r = r.nextSibling; - for (; r;) t(r, o) !== !0 && n(r, t, o), r = r.nextElementSibling; - return null - } - - function o(e, n) { - for (var o = e.shadowRoot; o;) t(o, n), o = o.olderShadowRoot - } - - function r(e, t) { - i(e, t, []) - } - - function i(e, t, n) { - if (e = window.wrap(e), !(n.indexOf(e) >= 0)) { - n.push(e); - for (var o, r = e.querySelectorAll("link[rel=" + a + "]"), s = 0, c = r.length; s < c && (o = r[s]); s++) o["import"] && i(o["import"], t, n); - t(e) - } - } - var a = window.HTMLImports ? window.HTMLImports.IMPORT_LINK_TYPE : "none"; - e.forDocumentTree = r, e.forSubtree = t - }), window.CustomElements.addModule(function(e) { - function t(e, t) { - return n(e, t) || o(e, t) - } - - function n(t, n) { - return !!e.upgrade(t, n) || void(n && a(t)) - } - - function o(e, t) { - g(e, function(e) { - if (n(e, t)) return !0 - }) - } - - function r(e) { - L.push(e), E || (E = !0, setTimeout(i)) - } - - function i() { - E = !1; - for (var e, t = L, n = 0, o = t.length; n < o && (e = t[n]); n++) e(); - L = [] - } - - function a(e) { - y ? r(function() { - s(e); - }) : s(e) - } - - function s(e) { - e.__upgraded__ && !e.__attached && (e.__attached = !0, e.attachedCallback && e.attachedCallback()) - } - - function c(e) { - d(e), g(e, function(e) { - d(e) - }) - } - - function d(e) { - y ? r(function() { - l(e) - }) : l(e) - } - - function l(e) { - e.__upgraded__ && e.__attached && (e.__attached = !1, e.detachedCallback && e.detachedCallback()) - } - - function u(e) { - for (var t = e, n = window.wrap(document); t;) { - if (t == n) return !0; - t = t.parentNode || t.nodeType === Node.DOCUMENT_FRAGMENT_NODE && t.host - } - } - - function h(e) { - if (e.shadowRoot && !e.shadowRoot.__watched) { - _.dom && console.log("watching shadow-root for: ", e.localName); - for (var t = e.shadowRoot; t;) m(t), t = t.olderShadowRoot - } - } - - function f(e, n) { - if (_.dom) { - var o = n[0]; - if (o && "childList" === o.type && o.addedNodes && o.addedNodes) { - for (var r = o.addedNodes[0]; r && r !== document && !r.host;) r = r.parentNode; - var i = r && (r.URL || r._URL || r.host && r.host.localName) || ""; - i = i.split("/?").shift().split("/").pop() - } - console.group("mutations (%d) [%s]", n.length, i || "") - } - var a = u(e); - n.forEach(function(e) { - "childList" === e.type && (N(e.addedNodes, function(e) { - e.localName && t(e, a) - }), N(e.removedNodes, function(e) { - e.localName && c(e) - })) - }), _.dom && console.groupEnd() - } - - function p(e) { - for (e = window.wrap(e), e || (e = window.wrap(document)); e.parentNode;) e = e.parentNode; - var t = e.__observer; - t && (f(e, t.takeRecords()), i()) - } - - function m(e) { - if (!e.__observer) { - var t = new MutationObserver(f.bind(this, e)); - t.observe(e, { - childList: !0, - subtree: !0 - }), e.__observer = t - } - } - - function v(e) { - e = window.wrap(e), _.dom && console.group("upgradeDocument: ", e.baseURI.split("/").pop()); - var n = e === window.wrap(document); - t(e, n), m(e), _.dom && console.groupEnd() - } - - function w(e) { - b(e, v) - } - var _ = e.flags, - g = e.forSubtree, - b = e.forDocumentTree, - y = window.MutationObserver._isPolyfilled && _["throttle-attached"]; - e.hasPolyfillMutations = y, e.hasThrottledAttached = y; - var E = !1, - L = [], - N = Array.prototype.forEach.call.bind(Array.prototype.forEach), - M = Element.prototype.createShadowRoot; - M && (Element.prototype.createShadowRoot = function() { - var e = M.call(this); - return window.CustomElements.watchShadow(this), e - }), e.watchShadow = h, e.upgradeDocumentTree = w, e.upgradeDocument = v, e.upgradeSubtree = o, e.upgradeAll = t, e.attached = a, e.takeRecords = p - }), window.CustomElements.addModule(function(e) { - function t(t, o) { - if ("template" === t.localName && window.HTMLTemplateElement && HTMLTemplateElement.decorate && HTMLTemplateElement.decorate(t), !t.__upgraded__ && t.nodeType === Node.ELEMENT_NODE) { - var r = t.getAttribute("is"), - i = e.getRegisteredDefinition(t.localName) || e.getRegisteredDefinition(r); - if (i && (r && i.tag == t.localName || !r && !i["extends"])) return n(t, i, o) - } - } - - function n(t, n, r) { - return a.upgrade && console.group("upgrade:", t.localName), n.is && t.setAttribute("is", n.is), o(t, n), t.__upgraded__ = !0, i(t), r && e.attached(t), e.upgradeSubtree(t, r), a.upgrade && console.groupEnd(), t - } - - function o(e, t) { - Object.__proto__ ? e.__proto__ = t.prototype : (r(e, t.prototype, t["native"]), e.__proto__ = t.prototype) - } - - function r(e, t, n) { - for (var o = {}, r = t; r !== n && r !== HTMLElement.prototype;) { - for (var i, a = Object.getOwnPropertyNames(r), s = 0; i = a[s]; s++) o[i] || (Object.defineProperty(e, i, Object.getOwnPropertyDescriptor(r, i)), o[i] = 1); - r = Object.getPrototypeOf(r) - } - } - - function i(e) { - e.createdCallback && e.createdCallback() - } - var a = e.flags; - e.upgrade = t, e.upgradeWithDefinition = n, e.implementPrototype = o - }), window.CustomElements.addModule(function(e) { - function t(t, o) { - var c = o || {}; - if (!t) throw new Error("document.registerElement: first argument `name` must not be empty"); - if (t.indexOf("-") < 0) throw new Error("document.registerElement: first argument ('name') must contain a dash ('-'). Argument provided was '" + String(t) + "'."); - if (r(t)) throw new Error("Failed to execute 'registerElement' on 'Document': Registration failed for type '" + String(t) + "'. The type name is invalid."); - if (d(t)) throw new Error("DuplicateDefinitionError: a type with name '" + String(t) + "' is already registered"); - return c.prototype || (c.prototype = Object.create(HTMLElement.prototype)), c.__name = t.toLowerCase(), c["extends"] && (c["extends"] = c["extends"].toLowerCase()), c.lifecycle = c.lifecycle || {}, c.ancestry = i(c["extends"]), a(c), s(c), n(c.prototype), l(c.__name, c), c.ctor = u(c), c.ctor.prototype = c.prototype, c.prototype.constructor = c.ctor, e.ready && v(document), c.ctor - } - - function n(e) { - if (!e.setAttribute._polyfilled) { - var t = e.setAttribute; - e.setAttribute = function(e, n) { - o.call(this, e, n, t) - }; - var n = e.removeAttribute; - e.removeAttribute = function(e) { - o.call(this, e, null, n) - }, e.setAttribute._polyfilled = !0 - } - } - - function o(e, t, n) { - e = e.toLowerCase(); - var o = this.getAttribute(e); - n.apply(this, arguments); - var r = this.getAttribute(e); - this.attributeChangedCallback && r !== o && this.attributeChangedCallback(e, o, r) - } - - function r(e) { - for (var t = 0; t < y.length; t++) - if (e === y[t]) return !0 - } - - function i(e) { - var t = d(e); - return t ? i(t["extends"]).concat([t]) : [] - } - - function a(e) { - for (var t, n = e["extends"], o = 0; t = e.ancestry[o]; o++) n = t.is && t.tag; - e.tag = n || e.__name, n && (e.is = e.__name) - } - - function s(e) { - if (!Object.__proto__) { - var t = HTMLElement.prototype; - if (e.is) { - var n = document.createElement(e.tag); - t = Object.getPrototypeOf(n) - } - for (var o, r = e.prototype, i = !1; r;) r == t && (i = !0), o = Object.getPrototypeOf(r), o && (r.__proto__ = o), r = o; - i || console.warn(e.tag + " prototype not found in prototype chain for " + e.is), e["native"] = t - } - } - - function c(e) { - return _(N(e.tag), e) - } - - function d(e) { - if (e) return E[e.toLowerCase()] - } - - function l(e, t) { - E[e] = t - } - - function u(e) { - return function() { - return c(e) - } - } - - function h(e, t, n) { - return e === L ? f(t, n) : M(e, t) - } - - function f(e, t) { - e && (e = e.toLowerCase()), t && (t = t.toLowerCase()); - var n = d(t || e); - if (n) { - if (e == n.tag && t == n.is) return new n.ctor; - if (!t && !n.is) return new n.ctor - } - var o; - return t ? (o = f(e), o.setAttribute("is", t), o) : (o = N(e), e.indexOf("-") >= 0 && g(o, HTMLElement), o) - } - - function p(e, t) { - var n = e[t]; - e[t] = function() { - var e = n.apply(this, arguments); - return w(e), e - } - } - var m, v = (e.isIE, e.upgradeDocumentTree), - w = e.upgradeAll, - _ = e.upgradeWithDefinition, - g = e.implementPrototype, - b = e.useNative, - y = ["annotation-xml", "color-profile", "font-face", "font-face-src", "font-face-uri", "font-face-format", "font-face-name", "missing-glyph"], - E = {}, - L = "http://www.w3.org/1999/xhtml", - N = document.createElement.bind(document), - M = document.createElementNS.bind(document); - m = Object.__proto__ || b ? function(e, t) { - return e instanceof t - } : function(e, t) { - if (e instanceof t) return !0; - for (var n = e; n;) { - if (n === t.prototype) return !0; - n = n.__proto__ - } - return !1 - }, p(Node.prototype, "cloneNode"), p(document, "importNode"), document.registerElement = t, document.createElement = f, document.createElementNS = h, e.registry = E, e["instanceof"] = m, e.reservedTagList = y, e.getRegisteredDefinition = d, document.register = document.registerElement - }), - function(e) { - function t() { - i(window.wrap(document)), window.CustomElements.ready = !0; - var e = window.requestAnimationFrame || function(e) { - setTimeout(e, 16) - }; - e(function() { - setTimeout(function() { - window.CustomElements.readyTime = Date.now(), window.HTMLImports && (window.CustomElements.elapsed = window.CustomElements.readyTime - window.HTMLImports.readyTime), document.dispatchEvent(new CustomEvent("WebComponentsReady", { - bubbles: !0 - })) - }) - }) - } - var n = e.useNative, - o = e.initializeModules; - e.isIE; - if (n) { - var r = function() {}; - e.watchShadow = r, e.upgrade = r, e.upgradeAll = r, e.upgradeDocumentTree = r, e.upgradeSubtree = r, e.takeRecords = r, e["instanceof"] = function(e, t) { - return e instanceof t - } - } else o(); - var i = e.upgradeDocumentTree, - a = e.upgradeDocument; - if (window.wrap || (window.ShadowDOMPolyfill ? (window.wrap = window.ShadowDOMPolyfill.wrapIfNeeded, window.unwrap = window.ShadowDOMPolyfill.unwrapIfNeeded) : window.wrap = window.unwrap = function(e) { - return e - }), window.HTMLImports && (window.HTMLImports.__importsParsingHook = function(e) { - e["import"] && a(wrap(e["import"])) - }), "complete" === document.readyState || e.flags.eager) t(); - else if ("interactive" !== document.readyState || window.attachEvent || window.HTMLImports && !window.HTMLImports.ready) { - var s = window.HTMLImports && !window.HTMLImports.ready ? "HTMLImportsLoaded" : "DOMContentLoaded"; - window.addEventListener(s, t) - } else t() - }(window.CustomElements), - function(e) { - var t = document.createElement("style"); - t.textContent = "body {transition: opacity ease-in 0.2s; } \nbody[unresolved] {opacity: 0; display: block; overflow: hidden; position: relative; } \n"; - var n = document.querySelector("head"); - n.insertBefore(t, n.firstChild) - }(window.WebComponents); \ No newline at end of file diff --git a/src/bundle.js b/src/bundle.js index 86e10aab7d..4643b23f0d 100644 --- a/src/bundle.js +++ b/src/bundle.js @@ -4,6 +4,14 @@ // Use define from require.js not webpack's define var _define = window.define; +// document-register-element +var docRegister = require("document-register-element"); +_define("document-register-element", function() { return docRegister; }); + +// fetch +var fetch = require("whatwg-fetch"); +_define("fetch", function() { return fetch }); + // flvjs var flvjs = require("flv.js"); _define("flvjs", function() { return flvjs; }); @@ -25,6 +33,14 @@ _define("hlsjs", function() { return hlsjs; }); var howler = require("howler"); _define("howler", function() { return howler; }); +// native-promise-only +var nativePromise = require("native-promise-only"); +_define("native-promise-only", function() { return nativePromise; }); + +// resize-observer-polyfill +var resize = require("resize-observer-polyfill"); +_define("resize-observer-polyfill", function() { return resize; }); + // shaka var shaka = require("shaka-player"); _define("shaka", function() { return shaka; }); @@ -38,6 +54,10 @@ _define("swiper", function() { return swiper; }); var sortable = require("sortablejs"); _define("sortable", function() { return sortable; }); +// webcomponents +var webcomponents = require("webcomponents.js-2"); +_define("webcomponents", function() { return webcomponents }); + // libjass var libjass = require("libjass"); require("libjass/libjass.css"); diff --git a/src/scripts/site.js b/src/scripts/site.js index b5fa85ac6c..48eb2d7c2a 100644 --- a/src/scripts/site.js +++ b/src/scripts/site.js @@ -387,7 +387,7 @@ var AppInfo = {}; return self.ResizeObserver; }); } else { - define("ResizeObserver", [getBowerPath() + "/resize-observer-polyfill/ResizeObserver"], returnFirstDependency); + define("ResizeObserver", ["resize-observer-polyfill"], returnFirstDependency); } } @@ -410,9 +410,9 @@ var AppInfo = {}; if ("registerElement" in document) { define("registerElement", []); } else if (browser.msie) { - define("registerElement", [bowerPath + "/webcomponentsjs/webcomponents-lite.min.js"], returnFirstDependency); + define("registerElement", ["webcomponents"], returnFirstDependency); } else { - define("registerElement", [bowerPath + "/document-register-element/build/document-register-element"], returnFirstDependency); + define("registerElement", ["document-register-element"], returnFirstDependency); } define("imageFetcher", [componentsPath + "/images/imageFetcher"], returnFirstDependency); @@ -632,7 +632,7 @@ var AppInfo = {}; } if (!window.Promise || browser.web0s) { - require([getBowerPath() + "/native-promise-only/lib/npo.src"], init); + require(["native-promise-only"], init); } else { init(); } @@ -681,15 +681,20 @@ var AppInfo = {}; }, bundles: { bundle: [ + "document-register-element", + "fetch", "flvjs", "jstree", "jQuery", "hlsjs", "howler", + "native-promise-only", + "resize-observer-polyfill", "shaka", "swiper", "sortable", - "libjass" + "libjass", + "webcomponents" ] }, urlArgs: urlArgs, @@ -743,7 +748,7 @@ var AppInfo = {}; // also pull out these libs define("page", [bowerPath + "/page"], returnFirstDependency); - define("fetch", [bowerPath + "/fetch/fetch"], returnFirstDependency); + define("fetch", ["fetch"], returnFirstDependency); define("queryString", [bowerPath + "/query-string/index"], function () { return queryString; }); diff --git a/webpack.common.js b/webpack.common.js index f0d03bc4cd..59a1c4e55e 100644 --- a/webpack.common.js +++ b/webpack.common.js @@ -1,6 +1,8 @@ const path = require("path"); -const { CleanWebpackPlugin} = require("clean-webpack-plugin"); + +const { CleanWebpackPlugin } = require("clean-webpack-plugin"); const CopyPlugin = require("copy-webpack-plugin"); + const Assets = [ "alameda/alameda.js", "requirejs/require.js" From b12442703979706352b286040a369fa9565b68f7 Mon Sep 17 00:00:00 2001 From: dkanada Date: Mon, 11 Nov 2019 01:47:28 +0900 Subject: [PATCH 127/162] move remaining libraries to new folder --- src/{bower_components => libraries}/apiclient/apiclient.js | 2 +- .../apiclient/apiclientcore.js | 0 src/{bower_components => libraries}/apiclient/appStorage.js | 0 .../apiclient/connectionmanager.js | 0 .../apiclient/credentialprovider.js | 0 src/{bower_components => libraries}/apiclient/events.js | 0 .../apiclient/localassetmanager.js | 0 src/{bower_components => libraries}/apiclient/package.json | 0 .../apiclient/sync/filerepository.js | 0 .../apiclient/sync/itemrepository.js | 0 .../apiclient/sync/localsync.js | 0 .../apiclient/sync/mediasync.js | 0 .../apiclient/sync/multiserversync.js | 0 .../apiclient/sync/serversync.js | 0 .../apiclient/sync/transfermanager.js | 0 .../apiclient/sync/useractionrepository.js | 0 src/{bower_components => libraries/pagejs}/page.js | 0 src/{bower_components => libraries}/query-string/index.js | 0 src/{bower_components => libraries}/query-string/test.js | 0 src/scripts/site.js | 4 ++-- 20 files changed, 3 insertions(+), 3 deletions(-) rename src/{bower_components => libraries}/apiclient/apiclient.js (99%) rename src/{bower_components => libraries}/apiclient/apiclientcore.js (100%) rename src/{bower_components => libraries}/apiclient/appStorage.js (100%) rename src/{bower_components => libraries}/apiclient/connectionmanager.js (100%) rename src/{bower_components => libraries}/apiclient/credentialprovider.js (100%) rename src/{bower_components => libraries}/apiclient/events.js (100%) rename src/{bower_components => libraries}/apiclient/localassetmanager.js (100%) rename src/{bower_components => libraries}/apiclient/package.json (100%) rename src/{bower_components => libraries}/apiclient/sync/filerepository.js (100%) rename src/{bower_components => libraries}/apiclient/sync/itemrepository.js (100%) rename src/{bower_components => libraries}/apiclient/sync/localsync.js (100%) rename src/{bower_components => libraries}/apiclient/sync/mediasync.js (100%) rename src/{bower_components => libraries}/apiclient/sync/multiserversync.js (100%) rename src/{bower_components => libraries}/apiclient/sync/serversync.js (100%) rename src/{bower_components => libraries}/apiclient/sync/transfermanager.js (100%) rename src/{bower_components => libraries}/apiclient/sync/useractionrepository.js (100%) rename src/{bower_components => libraries/pagejs}/page.js (100%) rename src/{bower_components => libraries}/query-string/index.js (100%) rename src/{bower_components => libraries}/query-string/test.js (100%) diff --git a/src/bower_components/apiclient/apiclient.js b/src/libraries/apiclient/apiclient.js similarity index 99% rename from src/bower_components/apiclient/apiclient.js rename to src/libraries/apiclient/apiclient.js index 98aaed75e3..06d9cf0861 100644 --- a/src/bower_components/apiclient/apiclient.js +++ b/src/libraries/apiclient/apiclient.js @@ -1,5 +1,5 @@ //TODO: (vitorsemeano) modify this lines for webpack -define(["bower_components/apiclient/apiclientcore", "localassetmanager"], function(ApiClient, localassetmanager) { +define(["libraries/apiclient/apiclientcore", "localassetmanager"], function(ApiClient, localassetmanager) { "use strict"; if ("cordova" !== window.appMode && "android" !== window.appMode) { diff --git a/src/bower_components/apiclient/apiclientcore.js b/src/libraries/apiclient/apiclientcore.js similarity index 100% rename from src/bower_components/apiclient/apiclientcore.js rename to src/libraries/apiclient/apiclientcore.js diff --git a/src/bower_components/apiclient/appStorage.js b/src/libraries/apiclient/appStorage.js similarity index 100% rename from src/bower_components/apiclient/appStorage.js rename to src/libraries/apiclient/appStorage.js diff --git a/src/bower_components/apiclient/connectionmanager.js b/src/libraries/apiclient/connectionmanager.js similarity index 100% rename from src/bower_components/apiclient/connectionmanager.js rename to src/libraries/apiclient/connectionmanager.js diff --git a/src/bower_components/apiclient/credentialprovider.js b/src/libraries/apiclient/credentialprovider.js similarity index 100% rename from src/bower_components/apiclient/credentialprovider.js rename to src/libraries/apiclient/credentialprovider.js diff --git a/src/bower_components/apiclient/events.js b/src/libraries/apiclient/events.js similarity index 100% rename from src/bower_components/apiclient/events.js rename to src/libraries/apiclient/events.js diff --git a/src/bower_components/apiclient/localassetmanager.js b/src/libraries/apiclient/localassetmanager.js similarity index 100% rename from src/bower_components/apiclient/localassetmanager.js rename to src/libraries/apiclient/localassetmanager.js diff --git a/src/bower_components/apiclient/package.json b/src/libraries/apiclient/package.json similarity index 100% rename from src/bower_components/apiclient/package.json rename to src/libraries/apiclient/package.json diff --git a/src/bower_components/apiclient/sync/filerepository.js b/src/libraries/apiclient/sync/filerepository.js similarity index 100% rename from src/bower_components/apiclient/sync/filerepository.js rename to src/libraries/apiclient/sync/filerepository.js diff --git a/src/bower_components/apiclient/sync/itemrepository.js b/src/libraries/apiclient/sync/itemrepository.js similarity index 100% rename from src/bower_components/apiclient/sync/itemrepository.js rename to src/libraries/apiclient/sync/itemrepository.js diff --git a/src/bower_components/apiclient/sync/localsync.js b/src/libraries/apiclient/sync/localsync.js similarity index 100% rename from src/bower_components/apiclient/sync/localsync.js rename to src/libraries/apiclient/sync/localsync.js diff --git a/src/bower_components/apiclient/sync/mediasync.js b/src/libraries/apiclient/sync/mediasync.js similarity index 100% rename from src/bower_components/apiclient/sync/mediasync.js rename to src/libraries/apiclient/sync/mediasync.js diff --git a/src/bower_components/apiclient/sync/multiserversync.js b/src/libraries/apiclient/sync/multiserversync.js similarity index 100% rename from src/bower_components/apiclient/sync/multiserversync.js rename to src/libraries/apiclient/sync/multiserversync.js diff --git a/src/bower_components/apiclient/sync/serversync.js b/src/libraries/apiclient/sync/serversync.js similarity index 100% rename from src/bower_components/apiclient/sync/serversync.js rename to src/libraries/apiclient/sync/serversync.js diff --git a/src/bower_components/apiclient/sync/transfermanager.js b/src/libraries/apiclient/sync/transfermanager.js similarity index 100% rename from src/bower_components/apiclient/sync/transfermanager.js rename to src/libraries/apiclient/sync/transfermanager.js diff --git a/src/bower_components/apiclient/sync/useractionrepository.js b/src/libraries/apiclient/sync/useractionrepository.js similarity index 100% rename from src/bower_components/apiclient/sync/useractionrepository.js rename to src/libraries/apiclient/sync/useractionrepository.js diff --git a/src/bower_components/page.js b/src/libraries/pagejs/page.js similarity index 100% rename from src/bower_components/page.js rename to src/libraries/pagejs/page.js diff --git a/src/bower_components/query-string/index.js b/src/libraries/query-string/index.js similarity index 100% rename from src/bower_components/query-string/index.js rename to src/libraries/query-string/index.js diff --git a/src/bower_components/query-string/test.js b/src/libraries/query-string/test.js similarity index 100% rename from src/bower_components/query-string/test.js rename to src/libraries/query-string/test.js diff --git a/src/scripts/site.js b/src/scripts/site.js index 48eb2d7c2a..4ca730fd70 100644 --- a/src/scripts/site.js +++ b/src/scripts/site.js @@ -308,7 +308,7 @@ var AppInfo = {}; } function getBowerPath() { - return "bower_components"; + return "libraries"; } function getComponentsPath() { @@ -747,7 +747,7 @@ var AppInfo = {}; define("useractionrepository", [bowerPath + "/apiclient/sync/useractionrepository"], returnFirstDependency); // also pull out these libs - define("page", [bowerPath + "/page"], returnFirstDependency); + define("page", [bowerPath + "/pagejs/page"], returnFirstDependency); define("fetch", ["fetch"], returnFirstDependency); define("queryString", [bowerPath + "/query-string/index"], function () { return queryString; From ffd3886372e2f8dbd2899d102173587de8ca11c2 Mon Sep 17 00:00:00 2001 From: dkanada Date: Mon, 11 Nov 2019 01:59:23 +0900 Subject: [PATCH 128/162] improve some comments --- src/scripts/site.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/scripts/site.js b/src/scripts/site.js index 4ca730fd70..e05712c076 100644 --- a/src/scripts/site.js +++ b/src/scripts/site.js @@ -746,9 +746,10 @@ var AppInfo = {}; define("itemrepository", [bowerPath + "/apiclient/sync/itemrepository"], returnFirstDependency); define("useractionrepository", [bowerPath + "/apiclient/sync/useractionrepository"], returnFirstDependency); - // also pull out these libs + // TODO remove these libraries + // all three have been modified so we need to fix that first define("page", [bowerPath + "/pagejs/page"], returnFirstDependency); - define("fetch", ["fetch"], returnFirstDependency); + define("scroller", [componentsPath + "/scroller"], returnFirstDependency); define("queryString", [bowerPath + "/query-string/index"], function () { return queryString; }); @@ -848,7 +849,6 @@ var AppInfo = {}; define("sortMenu", [componentsPath + "/sortmenu/sortmenu"], returnFirstDependency); define("idb", [componentsPath + "/idb"], returnFirstDependency); define("sanitizefilename", [componentsPath + "/sanitizefilename"], returnFirstDependency); - define("scroller", [componentsPath + "/scroller"], returnFirstDependency); define("toast", [componentsPath + "/toast/toast"], returnFirstDependency); define("scrollHelper", [componentsPath + "/scrollhelper"], returnFirstDependency); define("touchHelper", [componentsPath + "/touchhelper"], returnFirstDependency); From ad8fe23ef80363c73d0fdf8d5b286fff61d27ef3 Mon Sep 17 00:00:00 2001 From: Dmitry Lyzo <56478732+dmitrylyzo@users.noreply.github.com> Date: Mon, 11 Nov 2019 12:28:27 +0300 Subject: [PATCH 129/162] Make login card scalable on focus (#535) * Make login card scalable on focus * Remove focus related classes --- src/components/cardbuilder/card.css | 11 +++--- src/components/cardbuilder/cardBuilder.js | 38 +++++-------------- .../cardbuilder/chaptercardbuilder.js | 27 ++++++------- .../imagedownloader/imagedownloader.js | 16 +++++--- src/components/imageeditor/imageeditor.js | 14 ++++--- .../itemidentifier/itemidentifier.js | 16 +++++--- src/components/themes/appletv/theme.css | 5 ++- src/components/themes/blueradiance/theme.css | 5 ++- src/components/themes/dark/theme.css | 5 ++- src/components/themes/emby/theme.css | 5 ++- src/components/themes/light/theme.css | 5 ++- src/components/themes/purple-haze/theme.css | 5 ++- src/components/themes/wmc/theme.css | 5 ++- src/components/tunerpicker.js | 14 +++++-- src/controllers/livetvstatus.js | 14 +++++-- src/controllers/loginpage.js | 22 ++++++++++- src/controllers/selectserver.js | 20 +++++++--- 17 files changed, 131 insertions(+), 96 deletions(-) diff --git a/src/components/cardbuilder/card.css b/src/components/cardbuilder/card.css index 942e05c77a..874b6d0416 100644 --- a/src/components/cardbuilder/card.css +++ b/src/components/cardbuilder/card.css @@ -26,7 +26,7 @@ button { font-weight: inherit !important; } -.card-nofocustransform { +.card:not(.show-animation) { contain: layout style paint; } @@ -98,20 +98,21 @@ button { contain: layout style; } -.cardBox-withfocuscontent-large { +.card.show-focus:not(.show-animation) .cardBox { margin: .4em; } -.card-focuscontent-large { +.card.show-focus:not(.show-animation) .cardBox.visualCardBox, +.card.show-focus:not(.show-animation) .cardBox:not(.visualCardBox) .cardScalable { border: .5em solid transparent; } -.cardBox-focustransform { +.card.show-animation .cardBox { will-change: transform; transition: transform 200ms ease-out; } -.card:focus > .cardBox-focustransform { +.card.show-animation:focus > .cardBox { transform: scale(1.18, 1.18); } diff --git a/src/components/cardbuilder/cardBuilder.js b/src/components/cardbuilder/cardBuilder.js index d91802dc71..09ad8f1a6d 100644 --- a/src/components/cardbuilder/cardBuilder.js +++ b/src/components/cardbuilder/cardBuilder.js @@ -3,7 +3,7 @@ define(['datetime', 'imageLoader', 'connectionManager', 'itemHelper', 'focusMana 'use strict'; var devicePixelRatio = window.devicePixelRatio || 1; - var enableFocusTransfrom = !browser.slow && !browser.edge; + var enableFocusTransform = !browser.slow && !browser.edge; function getCardsHtml(items, options) { if (arguments.length === 1) { @@ -1203,6 +1203,8 @@ define(['datetime', 'imageLoader', 'connectionManager', 'itemHelper', 'focusMana shape = shape || 'mixedSquare'; } + // TODO move card creation code to Card component + var className = 'card'; if (shape) { @@ -1221,8 +1223,12 @@ define(['datetime', 'imageLoader', 'connectionManager', 'itemHelper', 'focusMana className += ' card-hoverable'; } - if (!enableFocusTransfrom || !layoutManager.tv) { - className += ' card-nofocustransform'; + if (layoutManager.tv) { + className += ' show-focus'; + + if (enableFocusTransform) { + className += ' show-animation'; + } } var imgInfo = getCardImageUrl(item, apiClient, options, shape); @@ -1250,23 +1256,6 @@ define(['datetime', 'imageLoader', 'connectionManager', 'itemHelper', 'focusMana var cardBoxClass = options.cardLayout ? 'cardBox visualCardBox' : 'cardBox'; - if (layoutManager.tv) { - - if (enableFocusTransfrom) { - cardBoxClass += ' cardBox-focustransform cardBox-withfocuscontent'; - } else { - cardBoxClass += ' cardBox-withfocuscontent-large'; - } - - if (options.cardLayout) { - cardBoxClass += ' card-focuscontent'; - - if (!enableFocusTransfrom) { - cardBoxClass += ' card-focuscontent-large'; - } - } - } - var footerCssClass; var progressHtml = indicators.getProgressBarHtml(item); @@ -1385,15 +1374,6 @@ define(['datetime', 'imageLoader', 'connectionManager', 'itemHelper', 'focusMana var cardScalableClass = 'cardScalable'; - if (layoutManager.tv && !options.cardLayout) { - - cardScalableClass += ' card-focuscontent'; - - if (!enableFocusTransfrom) { - cardScalableClass += ' card-focuscontent-large'; - } - } - cardImageContainerOpen = '
' + cardImageContainerOpen; cardBoxClose = '
'; cardScalableClose = '
'; diff --git a/src/components/cardbuilder/chaptercardbuilder.js b/src/components/cardbuilder/chaptercardbuilder.js index 900f4befc1..0f42e14584 100644 --- a/src/components/cardbuilder/chaptercardbuilder.js +++ b/src/components/cardbuilder/chaptercardbuilder.js @@ -1,12 +1,20 @@ define(['datetime', 'imageLoader', 'connectionManager', 'layoutManager', 'browser'], function (datetime, imageLoader, connectionManager, layoutManager, browser) { 'use strict'; + var enableFocusTransform = !browser.slow && !browser.edge; + function buildChapterCardsHtml(item, chapters, options) { + // TODO move card creation code to Card component + var className = 'card itemAction chapterCard'; - if (layoutManager.tv && (browser.animate || browser.edge)) { - className += ' card-focusscale'; + if (layoutManager.tv) { + className += ' show-focus'; + + if (enableFocusTransform) { + className += ' show-animation'; + } } var mediaStreams = ((item.MediaSources || [])[0] || {}).MediaStreams || []; @@ -92,19 +100,6 @@ define(['datetime', 'imageLoader', 'connectionManager', 'layoutManager', 'browse var cardBoxCssClass = 'cardBox'; var cardScalableClass = 'cardScalable'; - if (layoutManager.tv) { - var enableFocusTransfrom = !browser.slow && !browser.edge; - - cardScalableClass += ' card-focuscontent'; - - if (enableFocusTransfrom) { - cardBoxCssClass += ' cardBox-focustransform cardBox-withfocuscontent'; - } else { - cardBoxCssClass += ' cardBox-withfocuscontent-large'; - cardScalableClass += ' card-focuscontent-large'; - } - } - var html = '
'; return html; @@ -137,4 +132,4 @@ define(['datetime', 'imageLoader', 'connectionManager', 'layoutManager', 'browse buildChapterCards: buildChapterCards }; -}); \ No newline at end of file +}); diff --git a/src/components/imagedownloader/imagedownloader.js b/src/components/imagedownloader/imagedownloader.js index 729bce3382..182b72071f 100644 --- a/src/components/imagedownloader/imagedownloader.js +++ b/src/components/imagedownloader/imagedownloader.js @@ -1,6 +1,8 @@ define(['loading', 'apphost', 'dialogHelper', 'connectionManager', 'imageLoader', 'browser', 'layoutManager', 'scrollHelper', 'globalize', 'require', 'emby-checkbox', 'paper-icon-button-light', 'emby-button', 'formDialogStyle', 'cardStyle'], function (loading, appHost, dialogHelper, connectionManager, imageLoader, browser, layoutManager, scrollHelper, globalize, require) { 'use strict'; + var enableFocusTransform = !browser.slow && !browser.edge; + var currentItemId; var currentItemType; var currentResolve; @@ -164,6 +166,8 @@ define(['loading', 'apphost', 'dialogHelper', 'connectionManager', 'imageLoader' var tagName = layoutManager.tv ? 'button' : 'div'; var enableFooterButtons = !layoutManager.tv; + // TODO move card creation code to Card component + var html = ''; var cssClass = "card scalableCard imageEditorCard"; @@ -196,12 +200,12 @@ define(['loading', 'apphost', 'dialogHelper', 'connectionManager', 'imageLoader' if (tagName === 'button') { cssClass += ' btnImageCard'; - if (layoutManager.tv && !browser.slow) { - cardBoxCssClass += ' cardBox-focustransform'; - } - if (layoutManager.tv) { - cardBoxCssClass += ' card-focuscontent cardBox-withfocuscontent'; + cssClass += ' show-focus'; + + if (enableFocusTransform) { + cssClass += ' show-animation'; + } } html += ''; } html += "
"; @@ -188,9 +188,9 @@ define(['loading', 'dialogHelper', 'dom', 'listViewStyle', 'emby-input', 'paper- var path = lnkPath.getAttribute("data-path"); if (lnkPath.classList.contains("lnkFile")) { content.querySelector("#txtDirectoryPickerPath").value = path; - } else { + } else { refreshDirectoryBrowser(content, path, fileOptions, true) - }; + } } }); @@ -254,10 +254,10 @@ define(['loading', 'dialogHelper', 'dom', 'listViewStyle', 'emby-input', 'paper- var systemInfo = responses[0]; var initialPath = responses[1]; var dlg = dialogHelper.createDialog({ - size: "medium-tall", - removeOnClose: true, - scrollY: false - }); + size: "medium-tall", + removeOnClose: true, + scrollY: false + }); dlg.classList.add("ui-body-a"); dlg.classList.add("background-theme-a"); dlg.classList.add("directoryPicker"); diff --git a/src/components/dom.js b/src/components/dom.js index ea8902b98e..da03b87428 100644 --- a/src/components/dom.js +++ b/src/components/dom.js @@ -68,7 +68,9 @@ define([], function () { } }); window.addEventListener("test", null, opts); - } catch (e) { } + } catch (e) { + console.log('error checking capture support'); + } function addEventListenerWithOptions(target, type, handler, options) { var optionsOrCapture = options; @@ -116,8 +118,8 @@ define([], function () { return _animationEvent; } - var t, - el = document.createElement("div"); + var t; + var el = document.createElement("div"); var animations = { "animation": "animationend", "OAnimation": "oAnimationEnd", @@ -146,8 +148,8 @@ define([], function () { return _transitionEvent; } - var t, - el = document.createElement("div"); + var t; + var el = document.createElement("div"); var transitions = { "transition": "transitionend", "OTransition": "oTransitionEnd", diff --git a/src/components/emby-input/emby-input.js b/src/components/emby-input/emby-input.js index acc9154318..7d2ea63a0d 100644 --- a/src/components/emby-input/emby-input.js +++ b/src/components/emby-input/emby-input.js @@ -28,11 +28,12 @@ define(['layoutManager', 'browser', 'dom', 'css!./emby-input', 'registerElement' } EmbyInputPrototype.createdCallback = function () { - if (!this.id) { this.id = 'embyinput' + inputId; inputId++; - } if (this.classList.contains('emby-input')) { + } + + if (this.classList.contains('emby-input')) { return; } diff --git a/src/components/emby-progressring/emby-progressring.js b/src/components/emby-progressring/emby-progressring.js index 7148079a19..80c5458528 100644 --- a/src/components/emby-progressring/emby-progressring.js +++ b/src/components/emby-progressring/emby-progressring.js @@ -47,8 +47,7 @@ define(['require', 'css!./emby-progressring', 'registerElement'], function (requ this.querySelector('.animate-25-50-b').style.transform = 'rotate(-90deg)'; this.querySelector('.animate-50-75-b').style.transform = 'rotate(-90deg)'; this.querySelector('.animate-75-100-b').style.transform = 'rotate(-90deg)'; - } - else if (progress >= 25 && progress < 50) { + } else if (progress >= 25 && progress < 50) { angle = -90 + ((progress - 25) / 100) * 360; @@ -57,8 +56,7 @@ define(['require', 'css!./emby-progressring', 'registerElement'], function (requ this.querySelector('.animate-50-75-b').style.transform = 'rotate(-90deg)'; this.querySelector('.animate-75-100-b').style.transform = 'rotate(-90deg)'; - } - else if (progress >= 50 && progress < 75) { + } else if (progress >= 50 && progress < 75) { angle = -90 + ((progress - 50) / 100) * 360; this.querySelector('.animate-0-25-b').style.transform = 'none'; @@ -66,8 +64,7 @@ define(['require', 'css!./emby-progressring', 'registerElement'], function (requ this.querySelector('.animate-50-75-b').style.transform = 'rotate(' + angle + 'deg)'; this.querySelector('.animate-75-100-b').style.transform = 'rotate(-90deg)'; - } - else if (progress >= 75 && progress <= 100) { + } else if (progress >= 75 && progress <= 100) { angle = -90 + ((progress - 75) / 100) * 360; this.querySelector('.animate-0-25-b').style.transform = 'none'; @@ -85,7 +82,6 @@ define(['require', 'css!./emby-progressring', 'registerElement'], function (requ EmbyProgressRing.detachedCallback = function () { - var observer = this.observer; if (observer) { diff --git a/src/components/emby-tabs/emby-tabs.js b/src/components/emby-tabs/emby-tabs.js index 4a0060cf88..9fedf0bfe9 100644 --- a/src/components/emby-tabs/emby-tabs.js +++ b/src/components/emby-tabs/emby-tabs.js @@ -142,7 +142,7 @@ define(['dom', 'scroller', 'browser', 'layoutManager', 'focusManager', 'register tabs.classList.add('scrollX'); tabs.classList.add('hiddenScrollX'); tabs.classList.add('smoothScrollX'); - } + } } EmbyTabs.createdCallback = function () { diff --git a/src/components/emby-textarea/emby-textarea.js b/src/components/emby-textarea/emby-textarea.js index 7dec1f0955..c500db6e1f 100644 --- a/src/components/emby-textarea/emby-textarea.js +++ b/src/components/emby-textarea/emby-textarea.js @@ -14,9 +14,9 @@ define(['layoutManager', 'browser', 'css!./emby-textarea', 'registerElement', 'e * @returns {number} */ self.getOffset = function (textarea) { - var style = window.getComputedStyle(textarea, null), - props = ['paddingTop', 'paddingBottom'], - offset = 0; + var style = window.getComputedStyle(textarea, null); + var props = ['paddingTop', 'paddingBottom']; + var offset = 0; for (var i = 0; i < props.length; i++) { offset += parseInt(style[props[i]]); @@ -43,13 +43,13 @@ define(['layoutManager', 'browser', 'css!./emby-textarea', 'registerElement', 'e textarea.rows = 3; return; } - var newHeight = 0, hasGrown = false; + var newHeight = 0; + var hasGrown = false; if ((textarea.scrollHeight - offset) > self.maxAllowedHeight) { textarea.style.overflowY = 'scroll'; newHeight = self.maxAllowedHeight; - } - else { + } else { textarea.style.overflowY = 'hidden'; textarea.style.height = 'auto'; newHeight = textarea.scrollHeight/* - offset*/; diff --git a/src/components/filtermenu/filtermenu.js b/src/components/filtermenu/filtermenu.js index 89457aa4e6..2f18223d41 100644 --- a/src/components/filtermenu/filtermenu.js +++ b/src/components/filtermenu/filtermenu.js @@ -94,7 +94,8 @@ define(['require', 'dom', 'focusManager', 'dialogHelper', 'loading', 'apphost', context.querySelector('form').addEventListener('submit', onSubmit); var elems = context.querySelectorAll('.simpleFilter'); - var i, length; + var i; + var length; for (i = 0, length = elems.length; i < length; i++) { @@ -137,7 +138,8 @@ define(['require', 'dom', 'focusManager', 'dialogHelper', 'loading', 'apphost', function saveValues(context, settings, settingsKey) { var elems = context.querySelectorAll('.simpleFilter'); - var i, length; + var i; + var length; for (i = 0, length = elems.length; i < length; i++) { if (elems[i].tagName === 'INPUT') { diff --git a/src/components/focusManager.js b/src/components/focusManager.js index 8c2f0ad442..ec23a151c2 100644 --- a/src/components/focusManager.js +++ b/src/components/focusManager.js @@ -99,7 +99,7 @@ define(['dom'], function (dom) { return normalizeFocusable(elem, originalElement); } - // Determines if a focusable element can be focused at a given point in time + // Determines if a focusable element can be focused at a given point in time function isCurrentlyFocusableInternal(elem) { // http://stackoverflow.com/questions/19669786/check-if-element-is-visible-in-dom @@ -110,7 +110,7 @@ define(['dom'], function (dom) { return true; } - // Determines if a focusable element can be focused at a given point in time + // Determines if a focusable element can be focused at a given point in time function isCurrentlyFocusable(elem) { if (elem.disabled) { @@ -181,21 +181,18 @@ define(['dom'], function (dom) { if (classList.contains('focuscontainer-left')) { return true; } - } - else if (direction === 1) { + } else if (direction === 1) { if (classList.contains('focuscontainer-x')) { return true; } if (classList.contains('focuscontainer-right')) { return true; } - } - else if (direction === 2) { + } else if (direction === 2) { if (classList.contains('focuscontainer-y')) { return true; } - } - else if (direction === 3) { + } else if (direction === 3) { if (classList.contains('focuscontainer-y')) { return true; } @@ -275,14 +272,14 @@ define(['dom'], function (dom) { var rect = getOffset(activeElement); // Get elements and work out x/y points - var cache = [], - point1x = parseFloat(rect.left) || 0, - point1y = parseFloat(rect.top) || 0, - point2x = parseFloat(point1x + rect.width - 1) || point1x, - point2y = parseFloat(point1y + rect.height - 1) || point1y, - // Shortcuts to help with compression - min = Math.min, - max = Math.max; + var cache = []; + var point1x = parseFloat(rect.left) || 0; + var point1y = parseFloat(rect.top) || 0; + var point2x = parseFloat(point1x + rect.width - 1) || point1x; + var point2y = parseFloat(point1y + rect.height - 1) || point1y; + // Shortcuts to help with compression + var min = Math.min; + var max = Math.max; var sourceMidX = rect.left + (rect.width / 2); var sourceMidY = rect.top + (rect.height / 2); @@ -357,10 +354,10 @@ define(['dom'], function (dom) { break; } - var x = elementRect.left, - y = elementRect.top, - x2 = x + elementRect.width - 1, - y2 = y + elementRect.height - 1; + var x = elementRect.left; + var y = elementRect.top; + var x2 = x + elementRect.width - 1; + var y2 = y + elementRect.height - 1; var intersectX = intersects(point1x, point2x, x, x2); var intersectY = intersects(point1y, point2y, y, y2); @@ -470,7 +467,9 @@ define(['dom'], function (dom) { var elems = container.querySelectorAll(focusableSelector); var list = []; - var i, length, elem; + var i; + var length; + var elem; for (i = 0, length = elems.length; i < length; i++) { @@ -513,32 +512,24 @@ define(['dom'], function (dom) { focusableParent: focusableParent, getFocusableElements: getFocusableElements, moveLeft: function (sourceElement, options) { - var container = options ? options.container : null; var focusableElements = options ? options.focusableElements : null; nav(sourceElement, 0, container, focusableElements); - }, moveRight: function (sourceElement, options) { - var container = options ? options.container : null; var focusableElements = options ? options.focusableElements : null; nav(sourceElement, 1, container, focusableElements); - }, moveUp: function (sourceElement, options) { - var container = options ? options.container : null; var focusableElements = options ? options.focusableElements : null; nav(sourceElement, 2, container, focusableElements); - }, moveDown: function (sourceElement, options) { - var container = options ? options.container : null; var focusableElements = options ? options.focusableElements : null; nav(sourceElement, 3, container, focusableElements); - }, sendText: sendText, isCurrentlyFocusable: isCurrentlyFocusable, diff --git a/src/components/fullscreenManager.js b/src/components/fullscreenManager.js index 360986cc54..8ae31073a2 100644 --- a/src/components/fullscreenManager.js +++ b/src/components/fullscreenManager.js @@ -55,7 +55,7 @@ define(['events', 'dom', 'apphost', 'browser'], function (events, dom, appHost, return document.fullscreen || document.mozFullScreen || document.webkitIsFullScreen || - document.msFullscreenElement || /* IE/Edge syntax */ + document.msFullscreenElement || /* IE/Edge syntax */ document.fullscreenElement || /* Standard syntax */ document.webkitFullscreenElement || /* Chrome, Safari and Opera syntax */ document.mozFullScreenElement; /* Firefox syntax */ diff --git a/src/components/guide/guide-settings.js b/src/components/guide/guide-settings.js index 47eb026db8..9ee43be9f1 100644 --- a/src/components/guide/guide-settings.js +++ b/src/components/guide/guide-settings.js @@ -39,7 +39,8 @@ define(['dialogHelper', 'globalize', 'userSettings', 'layoutManager', 'connectio function save(context) { - var i, length; + var i; + var length; var chkIndicators = context.querySelectorAll('.chkIndicator'); for (i = 0, length = chkIndicators.length; i < length; i++) { @@ -62,7 +63,8 @@ define(['dialogHelper', 'globalize', 'userSettings', 'layoutManager', 'connectio function load(context) { - var i, length; + var i; + var length; var chkIndicators = context.querySelectorAll('.chkIndicator'); for (i = 0, length = chkIndicators.length; i < length; i++) { diff --git a/src/components/guide/guide.js b/src/components/guide/guide.js index d299d7fd7c..1e9484caf8 100644 --- a/src/components/guide/guide.js +++ b/src/components/guide/guide.js @@ -277,7 +277,7 @@ define(['require', 'inputManager', 'browser', 'globalize', 'connectionManager', var nextDay = new Date(date.getTime() + msPerDay - 2000); // Normally we'd want to just let responsive css handle this, - // but since mobile browsers are often underpowered, + // but since mobile browsers are often underpowered, // it can help performance to get them out of the markup var allowIndicators = dom.getWindowSize().innerWidth >= 600; @@ -392,27 +392,20 @@ define(['require', 'inputManager', 'browser', 'globalize', 'connectionManager', } function parseDates(program) { - if (!program.StartDateLocal) { try { - program.StartDateLocal = datetime.parseISO8601Date(program.StartDate, { toLocal: true }); - } catch (err) { - + console.log('error parsing timestamp for start date'); } - } if (!program.EndDateLocal) { try { - program.EndDateLocal = datetime.parseISO8601Date(program.EndDate, { toLocal: true }); - } catch (err) { - + console.log('error parsing timestamp for end date'); } - } return null; @@ -424,16 +417,13 @@ define(['require', 'inputManager', 'browser', 'globalize', 'connectionManager', if (item.Type === 'SeriesTimer') { return ''; - } - else if (item.TimerId || item.SeriesTimerId) { + } else if (item.TimerId || item.SeriesTimerId) { status = item.Status || 'Cancelled'; - } - else if (item.Type === 'Timer') { + } else if (item.Type === 'Timer') { status = item.Status; - } - else { + } else { return ''; } @@ -529,11 +519,9 @@ define(['require', 'inputManager', 'browser', 'globalize', 'connectionManager', } else if (program.IsMovie) { displayInnerContent = displayMovieContent; accentCssClass = 'movie'; - } - else if (program.IsSeries) { + } else if (program.IsSeries) { displayInnerContent = displaySeriesContent; - } - else { + } else { displayInnerContent = displayMovieContent && displayNewsContent && displaySportsContent && displayKidsContent && displaySeriesContent; } @@ -569,14 +557,11 @@ define(['require', 'inputManager', 'browser', 'globalize', 'connectionManager', var indicatorHtml = null; if (program.IsLive && options.showLiveIndicator) { indicatorHtml = '' + globalize.translate('Live') + ''; - } - else if (program.IsPremiere && options.showPremiereIndicator) { + } else if (program.IsPremiere && options.showPremiereIndicator) { indicatorHtml = '' + globalize.translate('Premiere') + ''; - } - else if (program.IsSeries && !program.IsRepeat && options.showNewIndicator) { + } else if (program.IsSeries && !program.IsRepeat && options.showNewIndicator) { indicatorHtml = '' + globalize.translate('AttributeNew') + ''; - } - else if (program.IsSeries && program.IsRepeat && options.showRepeatIndicator) { + } else if (program.IsSeries && program.IsRepeat && options.showRepeatIndicator) { indicatorHtml = '' + globalize.translate('Repeat') + ''; } html += indicatorHtml || ''; @@ -614,7 +599,6 @@ define(['require', 'inputManager', 'browser', 'globalize', 'connectionManager', return html; } - function renderChannelHeaders(context, channels, apiClient) { var html = ''; @@ -1079,17 +1063,13 @@ define(['require', 'inputManager', 'browser', 'globalize', 'connectionManager', scrollHelper.toStart(programGrid, programCell, true, true); } - } - - else if (lastFocusDirection === 'right') { + } else if (lastFocusDirection === 'right') { if (programCell) { scrollHelper.toCenter(programGrid, programCell, true, true); } - } - - else if (lastFocusDirection === 'up' || lastFocusDirection === 'down') { + } else if (lastFocusDirection === 'up' || lastFocusDirection === 'down') { var verticalScroller = dom.parentWithClass(target, 'guideVerticalScroller'); if (verticalScroller) { @@ -1195,14 +1175,14 @@ define(['require', 'inputManager', 'browser', 'globalize', 'connectionManager', dom.addEventListener(programGrid, 'scroll', function (e) { onProgramGridScroll(context, this, timeslotHeaders); }, { - passive: true - }); + passive: true + }); dom.addEventListener(timeslotHeaders, 'scroll', function () { onTimeslotHeadersScroll(context, this); }, { - passive: true - }); + passive: true + }); programGrid.addEventListener('click', onProgramGridClick); diff --git a/src/components/headroom/headroom.js b/src/components/headroom/headroom.js index a3cc5b0435..9c058a8e82 100644 --- a/src/components/headroom/headroom.js +++ b/src/components/headroom/headroom.js @@ -255,8 +255,8 @@ define(['dom', 'layoutManager', 'browser', 'css!./headroom'], function (dom, lay * @return {bool} true if should unpin, false otherwise */ this.shouldUnpin = function (currentScrollY) { - var scrollingDown = currentScrollY > this.lastKnownScrollY, - pastOffset = currentScrollY >= this.offset; + var scrollingDown = currentScrollY > this.lastKnownScrollY; + var pastOffset = currentScrollY >= this.offset; return scrollingDown && pastOffset; }; @@ -267,8 +267,8 @@ define(['dom', 'layoutManager', 'browser', 'css!./headroom'], function (dom, lay * @return {bool} true if should pin, false otherwise */ this.shouldPin = function (currentScrollY) { - var scrollingUp = currentScrollY < this.lastKnownScrollY, - pastOffset = currentScrollY <= this.offset; + var scrollingUp = currentScrollY < this.lastKnownScrollY; + var pastOffset = currentScrollY <= this.offset; return scrollingUp || pastOffset; }; @@ -290,11 +290,9 @@ define(['dom', 'layoutManager', 'browser', 'css!./headroom'], function (dom, lay if (currentScrollY <= (isTv ? 120 : 10)) { this.clear(); - } - else if (this.shouldUnpin(currentScrollY)) { + } else if (this.shouldUnpin(currentScrollY)) { this.unpin(); - } - else if (this.shouldPin(currentScrollY)) { + } else if (this.shouldPin(currentScrollY)) { var toleranceExceeded = Math.abs(currentScrollY - lastKnownScrollY) >= 14; @@ -310,7 +308,6 @@ define(['dom', 'layoutManager', 'browser', 'css!./headroom'], function (dom, lay this.lastKnownScrollY = currentScrollY; }; - if (browser.supportsCssAnimation()) { for (var i = 0, length = this.elems.length; i < length; i++) { this.elems[i].classList.add(this.initialClass); diff --git a/src/components/homescreensettings/homescreensettings.js b/src/components/homescreensettings/homescreensettings.js index 633437d26e..dc7769be36 100644 --- a/src/components/homescreensettings/homescreensettings.js +++ b/src/components/homescreensettings/homescreensettings.js @@ -57,8 +57,7 @@ define(['require', 'apphost', 'layoutManager', 'focusManager', 'globalize', 'loa name: globalize.translate('Collections'), value: 'collections' }); - } - else if (type === 'tvshows') { + } else if (type === 'tvshows') { list.push({ name: globalize.translate('Shows'), @@ -78,8 +77,7 @@ define(['require', 'apphost', 'layoutManager', 'focusManager', 'globalize', 'loa name: globalize.translate('Favorites'), value: 'favorites' }); - } - else if (type === 'music') { + } else if (type === 'music') { list.push({ name: globalize.translate('Suggestions'), @@ -111,8 +109,7 @@ define(['require', 'apphost', 'layoutManager', 'focusManager', 'globalize', 'loa name: globalize.translate('Genres'), value: 'genres' }); - } - else if (type === 'livetv') { + } else if (type === 'livetv') { list.push({ name: globalize.translate('Suggestions'), @@ -256,7 +253,6 @@ define(['require', 'apphost', 'layoutManager', 'focusManager', 'globalize', 'loa html += '
'; } - return html; } @@ -384,7 +380,8 @@ define(['require', 'apphost', 'layoutManager', 'focusManager', 'globalize', 'loa var viewItems = context.querySelectorAll('.viewItem'); var orderedViews = []; - var i, length; + var i; + var length; for (i = 0, length = viewItems.length; i < length; i++) { orderedViews.push(viewItems[i].getAttribute('data-viewid')); } diff --git a/src/components/homesections/homesections.js b/src/components/homesections/homesections.js index 3fc549e6e4..0c92f34e3d 100644 --- a/src/components/homesections/homesections.js +++ b/src/components/homesections/homesections.js @@ -1,4 +1,4 @@ -define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'layoutManager', 'imageLoader', 'globalize', 'itemShortcuts', 'itemHelper', 'appRouter', 'scripts/imagehelper','paper-icon-button-light', 'emby-itemscontainer', 'emby-scroller', 'emby-button', 'css!./homesections'], function (connectionManager, cardBuilder, appSettings, dom, appHost, layoutManager, imageLoader, globalize, itemShortcuts, itemHelper, appRouter, imageHelper) { +define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'layoutManager', 'imageLoader', 'globalize', 'itemShortcuts', 'itemHelper', 'appRouter', 'scripts/imagehelper', 'paper-icon-button-light', 'emby-itemscontainer', 'emby-scroller', 'emby-button', 'css!./homesections'], function (connectionManager, cardBuilder, appSettings, dom, appHost, layoutManager, imageLoader, globalize, itemShortcuts, itemHelper, appRouter, imageHelper) { 'use strict'; function getDefaultSection(index) { @@ -83,7 +83,8 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la function resume(elem, options) { var elems = elem.querySelectorAll('.itemsContainer'); - var i, length; + var i; + var length; var promises = []; for (i = 0, length = elems.length; i < length; i++) { @@ -567,7 +568,7 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la html += '' + globalize.translate('Programs') + ''; html += '
'; - } - else { + } else { html += ''; } diff --git a/src/components/imageeditor/imageeditor.js b/src/components/imageeditor/imageeditor.js index 2c649bdd16..fade0dd04c 100644 --- a/src/components/imageeditor/imageeditor.js +++ b/src/components/imageeditor/imageeditor.js @@ -24,8 +24,7 @@ define(['dialogHelper', 'connectionManager', 'loading', 'dom', 'layoutManager', if (item) { apiClient = connectionManager.getApiClient(item.ServerId); reloadItem(page, item, apiClient, focusContext); - } - else { + } else { apiClient = connectionManager.getApiClient(currentItem.ServerId); apiClient.getItem(apiClient.getCurrentUserId(), currentItem.Id).then(function (item) { @@ -60,7 +59,6 @@ define(['dialogHelper', 'connectionManager', 'loading', 'dom', 'layoutManager', } } - apiClient.getItemImageInfos(currentItem.Id).then(function (imageInfos) { renderStandardImages(page, apiClient, item, imageInfos, providers); @@ -167,8 +165,7 @@ define(['dialogHelper', 'connectionManager', 'loading', 'dom', 'layoutManager', } else { html += ''; } - } - else { + } else { if (imageProviders.length) { html += ''; } diff --git a/src/components/images/imageLoader.js b/src/components/images/imageLoader.js index 2a77daa216..a2906cca85 100644 --- a/src/components/images/imageLoader.js +++ b/src/components/images/imageLoader.js @@ -70,7 +70,9 @@ define(['lazyLoader', 'imageFetcher', 'layoutManager', 'browser', 'appSettings', } // Use the median - values.sort(function (a, b) { return a - b; }); + values.sort(function (a, b) { + return a - b; + }); var half = Math.floor(values.length / 2); @@ -78,8 +80,7 @@ define(['lazyLoader', 'imageFetcher', 'layoutManager', 'browser', 'appSettings', if (values.length % 2) { result = values[half]; - } - else { + } else { result = (values[half - 1] + values[half]) / 2.0; } diff --git a/src/components/imageuploader/imageuploader.js b/src/components/imageuploader/imageuploader.js index 3a52d7110d..98fcf0ebce 100644 --- a/src/components/imageuploader/imageuploader.js +++ b/src/components/imageuploader/imageuploader.js @@ -150,7 +150,7 @@ define(['dialogHelper', 'connectionManager', 'dom', 'loading', 'scrollHelper', ' scrollHelper.centerFocus.on(dlg, false); } - // Has to be assigned a z-index after the call to .open() + // Has to be assigned a z-index after the call to .open() dlg.addEventListener('close', function () { if (layoutManager.tv) { diff --git a/src/components/itemcontextmenu.js b/src/components/itemcontextmenu.js index 46a65cabc3..a3aa8cac4f 100644 --- a/src/components/itemcontextmenu.js +++ b/src/components/itemcontextmenu.js @@ -52,8 +52,6 @@ define(["apphost", "globalize", "connectionManager", "itemHelper", "appRouter", //} } - - if (item.IsFolder || item.Type === "MusicArtist" || item.Type === "MusicGenre") { if (item.CollectionType !== "livetv") { if (options.shuffle !== false) { diff --git a/src/components/itemhelper.js b/src/components/itemhelper.js index f8bdb28ac5..f0b1de4a12 100644 --- a/src/components/itemhelper.js +++ b/src/components/itemhelper.js @@ -250,9 +250,7 @@ define(['apphost', 'globalize'], function (appHost, globalize) { if (item.Type !== 'TvChannel') { return true; } - } - - else if (item.MediaType === 'Audio') { + } else if (item.MediaType === 'Audio') { if (item.Type === 'AudioPodcast') { return true; } diff --git a/src/components/itemidentifier/itemidentifier.js b/src/components/itemidentifier/itemidentifier.js index fa01a4aced..6f28de0b3b 100644 --- a/src/components/itemidentifier/itemidentifier.js +++ b/src/components/itemidentifier/itemidentifier.js @@ -21,7 +21,8 @@ define(["dialogHelper", "loading", "connectionManager", "require", "globalize", ProviderIds: {} }; - var i, length; + var i; + var length; var identifyField = page.querySelectorAll(".identifyField"); var value; for (i = 0, length = identifyField.length; i < length; i++) { @@ -64,8 +65,7 @@ define(["dialogHelper", "loading", "connectionManager", "require", "globalize", if (currentItem && currentItem.Id) { lookupInfo.ItemId = currentItem.Id; - } - else { + } else { lookupInfo.IncludeDisabledProviders = true; } @@ -97,7 +97,8 @@ define(["dialogHelper", "loading", "connectionManager", "require", "globalize", page.querySelector(".dialogContentInner").classList.remove("dialog-content-centered"); var html = ""; - var i, length; + var i; + var length; for (i = 0, length = results.length; i < length; i++) { var result = results[i]; @@ -184,12 +185,10 @@ define(["dialogHelper", "loading", "connectionManager", "require", "globalize", if (currentItemType === "Episode") { cssClass += " backdropCard backdropCard-scalable"; padderClass = "cardPadder-backdrop"; - } - else if (currentItemType === "MusicAlbum" || currentItemType === "MusicArtist") { + } else if (currentItemType === "MusicAlbum" || currentItemType === "MusicArtist") { cssClass += " squareCard squareCard-scalable"; padderClass = "cardPadder-square"; - } - else { + } else { cssClass += " portraitCard portraitCard-scalable"; padderClass = "cardPadder-portrait"; } @@ -452,8 +451,6 @@ define(["dialogHelper", "loading", "connectionManager", "require", "globalize", scrollHelper.centerFocus.on(dlg.querySelector(".formDialogContent"), false); } - - dialogHelper.open(dlg); dlg.querySelector(".btnCancel").addEventListener("click", function (e) { diff --git a/src/components/itemsrefresher.js b/src/components/itemsrefresher.js index d9bef95b4b..46956d2df5 100644 --- a/src/components/itemsrefresher.js +++ b/src/components/itemsrefresher.js @@ -11,8 +11,7 @@ define(['playbackManager', 'serverNotifications', 'events'], function (playbackM if (eventsToMonitor.indexOf('markfavorite') !== -1) { instance.notifyRefreshNeeded(); - } - else if (eventsToMonitor.indexOf('markplayed') !== -1) { + } else if (eventsToMonitor.indexOf('markplayed') !== -1) { instance.notifyRefreshNeeded(); } @@ -115,9 +114,7 @@ define(['playbackManager', 'serverNotifications', 'events'], function (playbackM instance.notifyRefreshNeeded(true); return; } - } - - else if (state.NowPlayingItem && state.NowPlayingItem.MediaType === 'Audio') { + } else if (state.NowPlayingItem && state.NowPlayingItem.MediaType === 'Audio') { if (eventsToMonitor.indexOf('audioplayback') !== -1) { diff --git a/src/components/keyboardnavigation.js b/src/components/keyboardnavigation.js index 7ed74f2201..8c0bb1a3ae 100644 --- a/src/components/keyboardnavigation.js +++ b/src/components/keyboardnavigation.js @@ -8,20 +8,20 @@ define(['inputManager', 'focusManager'], function(inputManager, focusManager) { var capture = true; switch (e.keyCode) { - case 37: // ArrowLeft - inputManager.handle('left'); - break; - case 38: // ArrowUp - inputManager.handle('up'); - break; - case 39: // ArrowRight - inputManager.handle('right'); - break; - case 40: // ArrowDown - inputManager.handle('down'); - break; - default: - capture = false; + case 37: // ArrowLeft + inputManager.handle('left'); + break; + case 38: // ArrowUp + inputManager.handle('up'); + break; + case 39: // ArrowRight + inputManager.handle('right'); + break; + case 40: // ArrowDown + inputManager.handle('down'); + break; + default: + capture = false; } if (capture) { console.log("Disabling default event handling"); @@ -31,6 +31,6 @@ define(['inputManager', 'focusManager'], function(inputManager, focusManager) { } return { - enable: enable, + enable: enable }; }); diff --git a/src/components/lazyloader/lazyloader-intersectionobserver.js b/src/components/lazyloader/lazyloader-intersectionobserver.js index 261ca84261..1935f65a30 100644 --- a/src/components/lazyloader/lazyloader-intersectionobserver.js +++ b/src/components/lazyloader/lazyloader-intersectionobserver.js @@ -45,7 +45,7 @@ define(['require', 'browser'], function (require, browser) { } } }, - observerOptions + observerOptions ); this.observer = observer; diff --git a/src/components/listview/listview.js b/src/components/listview/listview.js index 257551abf6..974cb0ab09 100644 --- a/src/components/listview/listview.js +++ b/src/components/listview/listview.js @@ -9,7 +9,8 @@ define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutMan } var sortBy = (options.sortBy || '').toLowerCase(); - var code, name; + var code; + var name; if (sortBy.indexOf('sortname') === 0) { @@ -85,15 +86,12 @@ define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutMan options.tag = item.AlbumPrimaryImageTag; return apiClient.getScaledImageUrl(item.AlbumId, options); - } - - else if (item.SeriesId && item.SeriesPrimaryImageTag) { + } else if (item.SeriesId && item.SeriesPrimaryImageTag) { options.tag = item.SeriesPrimaryImageTag; return apiClient.getScaledImageUrl(item.SeriesId, options); - } - else if (item.ParentPrimaryImageTag) { + } else if (item.ParentPrimaryImageTag) { options.tag = item.ParentPrimaryImageTag; return apiClient.getScaledImageUrl(item.ParentPrimaryImageItemId, options); @@ -209,8 +207,7 @@ define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutMan if (i === 0) { html += '

'; - } - else { + } else { html += '

'; } html += itemGroupTitle; @@ -349,9 +346,7 @@ define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutMan if (options.showParentTitle) { if (item.Type === 'Episode') { parentTitle = item.SeriesName; - } - - else if (item.IsSeries || (item.EpisodeTitle && item.Name)) { + } else if (item.IsSeries || (item.EpisodeTitle && item.Name)) { parentTitle = item.Name; } } @@ -375,8 +370,7 @@ define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutMan } textlines.push(parentTitle || ''); - } - else if (options.showParentTitle) { + } else if (options.showParentTitle) { textlines.push(parentTitle || ''); } @@ -400,8 +394,7 @@ define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutMan if (!artistItems || !artistItems.length) { showArtist = true; - } - else if (artistItems.length > 1 || containerAlbumArtistIds.indexOf(artistItems[0].Id) === -1) { + } else if (artistItems.length > 1 || containerAlbumArtistIds.indexOf(artistItems[0].Id) === -1) { showArtist = true; } } diff --git a/src/components/loading/loading.js b/src/components/loading/loading.js index ad9aea950a..510f311217 100644 --- a/src/components/loading/loading.js +++ b/src/components/loading/loading.js @@ -45,7 +45,8 @@ define(['components/loading/loadingLegacy', 'browser', 'css!./loading'], functio layer3.classList.add('mdl-spinner__layer-3-active'); layer4.classList.add('mdl-spinner__layer-4-active'); - var i, length; + var i; + var length; for (i = 0, length = circleLefts.length; i < length; i++) { circleLefts[i].classList.add('mdl-spinner__circleLeft-active'); @@ -67,7 +68,8 @@ define(['components/loading/loadingLegacy', 'browser', 'css!./loading'], functio elem.classList.remove('mdl-spinner__layer-3-active'); elem.classList.remove('mdl-spinner__layer-4-active'); - var i, length; + var i; + var length; for (i = 0, length = circleLefts.length; i < length; i++) { circleLefts[i].classList.remove('mdl-spinner__circleLeft-active'); diff --git a/src/components/mediainfo/mediainfo.js b/src/components/mediainfo/mediainfo.js index 441adac3dd..0fb4a1e7be 100644 --- a/src/components/mediainfo/mediainfo.js +++ b/src/components/mediainfo/mediainfo.js @@ -7,16 +7,13 @@ define(['datetime', 'globalize', 'appRouter', 'itemHelper', 'indicators', 'mater if (item.Type === 'SeriesTimer') { return ''; - } - else if (item.TimerId || item.SeriesTimerId) { + } else if (item.TimerId || item.SeriesTimerId) { status = item.Status || 'Cancelled'; - } - else if (item.Type === 'Timer') { + } else if (item.Type === 'Timer') { status = item.Status; - } - else { + } else { return ''; } @@ -36,7 +33,8 @@ define(['datetime', 'globalize', 'appRouter', 'itemHelper', 'indicators', 'mater var html = ''; var miscInfo = []; - var text, date; + var text; + var date; if (item.StartDate && options.programTime !== false) { @@ -58,8 +56,7 @@ define(['datetime', 'globalize', 'appRouter', 'itemHelper', 'indicators', 'mater } miscInfo.push(text); - } - catch (e) { + } catch (e) { console.log("Error parsing date: " + item.StartDate); } } @@ -107,7 +104,9 @@ define(['datetime', 'globalize', 'appRouter', 'itemHelper', 'indicators', 'mater var miscInfo = []; options = options || {}; - var text, date, minutes; + var text; + var date; + var minutes; var count; var showFolderRuntime = item.Type === "MusicAlbum" || item.MediaType === 'MusicArtist' || item.MediaType === 'Playlist' || item.MediaType === 'MusicGenre'; @@ -124,9 +123,7 @@ define(['datetime', 'globalize', 'appRouter', 'itemHelper', 'indicators', 'mater if (item.RunTimeTicks) { miscInfo.push(datetime.getDisplayRunningTime(item.RunTimeTicks)); } - } - - else if (item.Type === "PhotoAlbum" || item.Type === "BoxSet") { + } else if (item.Type === "PhotoAlbum" || item.Type === "BoxSet") { count = item.ChildCount; @@ -145,8 +142,7 @@ define(['datetime', 'globalize', 'appRouter', 'itemHelper', 'indicators', 'mater text = datetime.toLocaleDateString(date); miscInfo.push(text); - } - catch (e) { + } catch (e) { console.log("Error parsing date: " + item.PremiereDate); } } @@ -162,8 +158,7 @@ define(['datetime', 'globalize', 'appRouter', 'itemHelper', 'indicators', 'mater if (item.RecordAnyChannel) { miscInfo.push(globalize.translate('AllChannels')); - } - else { + } else { miscInfo.push(item.ChannelName || globalize.translate('OneChannel')); } } @@ -180,8 +175,7 @@ define(['datetime', 'globalize', 'appRouter', 'itemHelper', 'indicators', 'mater text = datetime.getDisplayTime(date); miscInfo.push(text); } - } - catch (e) { + } catch (e) { console.log("Error parsing date: " + item.StartDate); } } @@ -191,8 +185,7 @@ define(['datetime', 'globalize', 'appRouter', 'itemHelper', 'indicators', 'mater if (item.Status === "Continuing") { miscInfo.push(globalize.translate('SeriesYearToPresent', item.ProductionYear)); - } - else if (item.ProductionYear) { + } else if (item.ProductionYear) { text = item.ProductionYear; @@ -206,8 +199,7 @@ define(['datetime', 'globalize', 'appRouter', 'itemHelper', 'indicators', 'mater text += "-" + datetime.parseISO8601Date(item.EndDate).getFullYear(); } - } - catch (e) { + } catch (e) { console.log("Error parsing date: " + item.EndDate); } } @@ -223,18 +215,15 @@ define(['datetime', 'globalize', 'appRouter', 'itemHelper', 'indicators', 'mater miscInfo.push({ html: '
' + globalize.translate('Live') + '
' }); - } - else if (item.IsPremiere) { + } else if (item.IsPremiere) { miscInfo.push({ html: '
' + globalize.translate('Premiere') + '
' }); - } - else if (item.IsSeries && !item.IsRepeat) { + } else if (item.IsSeries && !item.IsRepeat) { miscInfo.push({ html: '
' + globalize.translate('AttributeNew') + '
' }); - } - else if (item.IsSeries && item.IsRepeat) { + } else if (item.IsSeries && item.IsRepeat) { miscInfo.push({ html: '
' + globalize.translate('Repeat') + '
' }); @@ -250,20 +239,15 @@ define(['datetime', 'globalize', 'appRouter', 'itemHelper', 'indicators', 'mater if (text) { miscInfo.push(text); } - } - - else if (item.IsMovie && item.ProductionYear && options.originalAirDate !== false) { + } else if (item.IsMovie && item.ProductionYear && options.originalAirDate !== false) { miscInfo.push(item.ProductionYear); - } - - else if (item.PremiereDate && options.originalAirDate !== false) { + } else if (item.PremiereDate && options.originalAirDate !== false) { try { date = datetime.parseISO8601Date(item.PremiereDate); text = globalize.translate('OriginalAirDateValue', datetime.toLocaleDateString(date)); miscInfo.push(text); - } - catch (e) { + } catch (e) { console.log("Error parsing date: " + item.PremiereDate); } } else if (item.ProductionYear) { @@ -277,14 +261,12 @@ define(['datetime', 'globalize', 'appRouter', 'itemHelper', 'indicators', 'mater if (item.ProductionYear) { miscInfo.push(item.ProductionYear); - } - else if (item.PremiereDate) { + } else if (item.PremiereDate) { try { text = datetime.parseISO8601Date(item.PremiereDate).getFullYear(); miscInfo.push(text); - } - catch (e) { + } catch (e) { console.log("Error parsing date: " + item.PremiereDate); } } diff --git a/src/components/medialibrarycreator/medialibrarycreator.js b/src/components/medialibrarycreator/medialibrarycreator.js index 54c13a4ebe..183e22551f 100644 --- a/src/components/medialibrarycreator/medialibrarycreator.js +++ b/src/components/medialibrarycreator/medialibrarycreator.js @@ -151,13 +151,13 @@ define(["loading", "dialogHelper", "dom", "jQuery", "components/libraryoptionsed var xhr = new XMLHttpRequest; xhr.open("GET", "components/medialibrarycreator/medialibrarycreator.template.html", true); xhr.onload = function(e) { - var template = this.response, - dlg = dialogHelper.createDialog({ - size: "medium-tall", - modal: false, - removeOnClose: true, - scrollY: false - }); + var template = this.response; + var dlg = dialogHelper.createDialog({ + size: "medium-tall", + modal: false, + removeOnClose: true, + scrollY: false + }); dlg.classList.add("ui-body-a"); dlg.classList.add("background-theme-a"); dlg.classList.add("dlg-librarycreator"); diff --git a/src/components/metadataeditor/metadataeditor.js b/src/components/metadataeditor/metadataeditor.js index 552c716c1f..8843dc159c 100644 --- a/src/components/metadataeditor/metadataeditor.js +++ b/src/components/metadataeditor/metadataeditor.js @@ -144,7 +144,9 @@ define(['itemHelper', 'dom', 'layoutManager', 'dialogHelper', 'datetime', 'loadi AirTime: form.querySelector('#txtAirTime').value, Genres: getListValues(form.querySelector("#listGenres")), Tags: getListValues(form.querySelector("#listTags")), - Studios: getListValues(form.querySelector("#listStudios")).map(function (element) { return { Name: element }; }), + Studios: getListValues(form.querySelector("#listStudios")).map(function (element) { + return { Name: element }; + }), PremiereDate: getDateValue(form, '#txtPremiereDate', 'PremiereDate'), DateCreated: getDateValue(form, '#txtDateAdded', 'DateCreated'), @@ -202,7 +204,9 @@ define(['itemHelper', 'dom', 'layoutManager', 'dialogHelper', 'datetime', 'loadi } function getListValues(list) { - return Array.prototype.map.call(list.querySelectorAll('.textValue'), function (el) { return el.textContent; }); + return Array.prototype.map.call(list.querySelectorAll('.textValue'), function (el) { + return el.textContent; + }); } function addElementToList(source, sortCallback) { @@ -439,7 +443,6 @@ define(['itemHelper', 'dom', 'layoutManager', 'dialogHelper', 'datetime', 'loadi var html = metadataInfo.ContentTypeOptions.map(function (i) { - return ''; }).join(''); @@ -744,7 +747,9 @@ define(['itemHelper', 'dom', 'layoutManager', 'dialogHelper', 'datetime', 'loadi populateListView(context.querySelector('#listGenres'), item.Genres); populatePeople(context, item.People || []); - populateListView(context.querySelector('#listStudios'), (item.Studios || []).map(function (element) { return element.Name || ''; })); + populateListView(context.querySelector('#listStudios'), (item.Studios || []).map(function (element) { + return element.Name || ''; + })); populateListView(context.querySelector('#listTags'), item.Tags); @@ -783,8 +788,7 @@ define(['itemHelper', 'dom', 'layoutManager', 'dialogHelper', 'datetime', 'loadi if (item.Type === 'Series') { context.querySelector('#selectDisplayOrder').value = item.DisplayOrder || ''; - } - else { + } else { context.querySelector('#selectDisplayOrder').value = item.DisplayOrder || ''; } @@ -859,7 +863,9 @@ define(['itemHelper', 'dom', 'layoutManager', 'dialogHelper', 'datetime', 'loadi html += ""; var ratings = []; - var i, length, rating; + var i; + var length; + var rating; var currentValueFound = false; @@ -901,7 +907,9 @@ define(['itemHelper', 'dom', 'layoutManager', 'dialogHelper', 'datetime', 'loadi items = items || []; if (typeof (sortCallback) === 'undefined') { - items.sort(function (a, b) { return a.toLowerCase().localeCompare(b.toLowerCase()); }); + items.sort(function (a, b) { + return a.toLowerCase().localeCompare(b.toLowerCase()); + }); } else { items = sortCallback(items); } diff --git a/src/components/multiselect/multiselect.js b/src/components/multiselect/multiselect.js index d706b76b99..a6a416d528 100644 --- a/src/components/multiselect/multiselect.js +++ b/src/components/multiselect/multiselect.js @@ -241,8 +241,6 @@ define(['browser', 'appStorage', 'apphost', 'loading', 'connectionManager', 'glo id: 'refresh' }); - - require(['actionsheet'], function (actionsheet) { actionsheet.show({ items: menuItems, diff --git a/src/components/navdrawer/navdrawer.js b/src/components/navdrawer/navdrawer.js index cbf5c1eebc..69adbd1f5a 100644 --- a/src/components/navdrawer/navdrawer.js +++ b/src/components/navdrawer/navdrawer.js @@ -21,13 +21,13 @@ define(["browser", "dom", "css!./navdrawer", "scrollStyles"], function(browser, } function onMenuTouchMove(e) { - var isOpen = self.visible, - touches = getTouches(e), - touch = touches[0] || {}, - endX = touch.clientX || 0, - endY = touch.clientY || 0, - deltaX = endX - (menuTouchStartX || 0), - deltaY = endY - (menuTouchStartY || 0); + var isOpen = self.visible; + var touches = getTouches(e); + var touch = touches[0] || {}; + var endX = touch.clientX || 0; + var endY = touch.clientY || 0; + var deltaX = endX - (menuTouchStartX || 0); + var deltaY = endY - (menuTouchStartY || 0); setVelocity(deltaX), isOpen && 1 !== dragMode && deltaX > 0 && (dragMode = 2), 0 === dragMode && (!isOpen || Math.abs(deltaX) >= 10) && Math.abs(deltaY) < 5 ? (dragMode = 1, scrollContainer.addEventListener("scroll", disableEvent), self.showMask()) : 0 === dragMode && Math.abs(deltaY) >= 5 && (dragMode = 2), 1 === dragMode && (newPos = currentPos + deltaX, self.changeMenuPos()) } @@ -36,12 +36,12 @@ define(["browser", "dom", "css!./navdrawer", "scrollStyles"], function(browser, scrollContainer.removeEventListener("scroll", disableEvent); dragMode = 0; - var touches = getTouches(e), - touch = touches[0] || {}, - endX = touch.clientX || 0, - endY = touch.clientY || 0, - deltaX = endX - (menuTouchStartX || 0), - deltaY = endY - (menuTouchStartY || 0); + var touches = getTouches(e); + var touch = touches[0] || {}; + var endX = touch.clientX || 0; + var endY = touch.clientY || 0; + var deltaX = endX - (menuTouchStartX || 0); + var deltaY = endY - (menuTouchStartY || 0); currentPos = deltaX; self.checkMenuState(deltaX, deltaY); @@ -78,15 +78,15 @@ define(["browser", "dom", "css!./navdrawer", "scrollStyles"], function(browser, } function onBackgroundTouchStart(e) { - var touches = getTouches(e), - touch = touches[0] || {}; + var touches = getTouches(e); + var touch = touches[0] || {}; backgroundTouchStartX = touch.clientX, backgroundTouchStartTime = (new Date).getTime() } function onBackgroundTouchMove(e) { - var touches = getTouches(e), - touch = touches[0] || {}, - endX = touch.clientX || 0; + var touches = getTouches(e); + var touch = touches[0] || {}; + var endX = touch.clientX || 0; if (endX <= options.width && self.isVisible) { countStart++; var deltaX = endX - (backgroundTouchStartX || 0); @@ -100,10 +100,10 @@ define(["browser", "dom", "css!./navdrawer", "scrollStyles"], function(browser, } function onBackgroundTouchEnd(e) { - var touches = getTouches(e), - touch = touches[0] || {}, - endX = touch.clientX || 0, - deltaX = endX - (backgroundTouchStartX || 0); + var touches = getTouches(e); + var touch = touches[0] || {}; + var endX = touch.clientX || 0; + var deltaX = endX - (backgroundTouchStartX || 0); self.checkMenuState(deltaX), countStart = 0 } @@ -111,21 +111,24 @@ define(["browser", "dom", "css!./navdrawer", "scrollStyles"], function(browser, var classList = mask.classList; classList.contains("backdrop") || classList.add("hide") } - var self, defaults, mask, newPos = 0, - currentPos = 0, - startPoint = 0, - countStart = 0, - velocity = 0; + var self; + var defaults; + var mask; + var newPos = 0; + var currentPos = 0; + var startPoint = 0; + var countStart = 0; + var velocity = 0; options.target.classList.add("transition"); - var dragMode = 0, - scrollContainer = options.target.querySelector(".mainDrawer-scrollContainer"); + var dragMode = 0; + var scrollContainer = options.target.querySelector(".mainDrawer-scrollContainer"); scrollContainer.classList.add("scrollY"); var TouchMenuLA = function() { self = this, defaults = { width: 260, handleSize: 10, disableMask: !1, - maxMaskOpacity: .5 + maxMaskOpacity: 0.5 }, this.isVisible = !1, this.initialize() }; TouchMenuLA.prototype.initElements = function() { @@ -133,8 +136,11 @@ define(["browser", "dom", "css!./navdrawer", "scrollStyles"], function(browser, passive: !0 })) }; - var menuTouchStartX, menuTouchStartY, menuTouchStartTime, edgeContainer = document.querySelector(".mainDrawerHandle"), - isPeeking = !1; + var menuTouchStartX; + var menuTouchStartY; + var menuTouchStartTime; + var edgeContainer = document.querySelector(".mainDrawerHandle"); + var isPeeking = false; TouchMenuLA.prototype.animateToPosition = function(pos) { requestAnimationFrame(function() { options.target.style.transform = pos ? "translateX(" + pos + "px)" : "none" @@ -146,7 +152,7 @@ define(["browser", "dom", "css!./navdrawer", "scrollStyles"], function(browser, self.close() }) }, TouchMenuLA.prototype.checkMenuState = function(deltaX, deltaY) { - velocity >= .4 ? deltaX >= 0 || Math.abs(deltaY || 0) >= 70 ? self.open() : self.close() : newPos >= 100 ? self.open() : newPos && self.close() + velocity >= 0.4 ? deltaX >= 0 || Math.abs(deltaY || 0) >= 70 ? self.open() : self.close() : newPos >= 100 ? self.open() : newPos && self.close() }, TouchMenuLA.prototype.open = function() { this.animateToPosition(options.width), currentPos = options.width, this.isVisible = !0, options.target.classList.add("drawer-open"), self.showMask(), self.invoke(options.onChange) }, TouchMenuLA.prototype.close = function() { @@ -154,7 +160,8 @@ define(["browser", "dom", "css!./navdrawer", "scrollStyles"], function(browser, }, TouchMenuLA.prototype.toggle = function() { self.isVisible ? self.close() : self.open() }; - var backgroundTouchStartX, backgroundTouchStartTime; + var backgroundTouchStartX; + var backgroundTouchStartTime; TouchMenuLA.prototype.showMask = function() { mask.classList.remove("hide"), mask.offsetWidth, mask.classList.add("backdrop") }, TouchMenuLA.prototype.hideMask = function() { diff --git a/src/components/notifications/notifications.js b/src/components/notifications/notifications.js index 304eec7e08..62de365d99 100644 --- a/src/components/notifications/notifications.js +++ b/src/components/notifications/notifications.js @@ -21,8 +21,7 @@ define(['serverNotifications', 'playbackManager', 'events', 'globalize', 'requir if (notification.close) { notification.close(); - } - else if (notification.cancel) { + } else if (notification.cancel) { notification.cancel(); } }, timeoutMs); @@ -180,15 +179,12 @@ define(['serverNotifications', 'playbackManager', 'events', 'globalize', 'requir if (status === 'completed') { notification.title = globalize.translate('PackageInstallCompleted').replace('{0}', installation.Name + ' ' + installation.Version); notification.vibrate = true; - } - else if (status === 'cancelled') { + } else if (status === 'cancelled') { notification.title = globalize.translate('PackageInstallCancelled').replace('{0}', installation.Name + ' ' + installation.Version); - } - else if (status === 'failed') { + } else if (status === 'failed') { notification.title = globalize.translate('PackageInstallFailed').replace('{0}', installation.Name + ' ' + installation.Version); notification.vibrate = true; - } - else if (status === 'progress') { + } else if (status === 'progress') { notification.title = globalize.translate('InstallingPackage').replace('{0}', installation.Name + ' ' + installation.Version); notification.actions = diff --git a/src/components/nowplayingbar/nowplayingbar.js b/src/components/nowplayingbar/nowplayingbar.js index 9fac61ba1f..d7be482c52 100644 --- a/src/components/nowplayingbar/nowplayingbar.js +++ b/src/components/nowplayingbar/nowplayingbar.js @@ -134,7 +134,8 @@ define(['require', 'datetime', 'itemHelper', 'events', 'browser', 'imageLoader', } }); - var i, length; + var i; + var length; playPauseButtons = elem.querySelectorAll('.playPauseButton'); for (i = 0, length = playPauseButtons.length; i < length; i++) { playPauseButtons[i].addEventListener('click', onPlayPauseClick); @@ -195,7 +196,6 @@ define(['require', 'datetime', 'itemHelper', 'events', 'browser', 'imageLoader', volumeSlider.addEventListener('mousemove', setVolume); volumeSlider.addEventListener('touchmove', setVolume); - positionSlider = elem.querySelector('.nowPlayingBarPositionSlider'); positionSlider.addEventListener('change', function () { @@ -282,8 +282,8 @@ define(['require', 'datetime', 'itemHelper', 'events', 'browser', 'imageLoader', } function updatePlayPauseState(isPaused) { - - var i, length; + var i; + var length; if (playPauseButtons) { if (isPaused) { @@ -345,8 +345,7 @@ define(['require', 'datetime', 'itemHelper', 'events', 'browser', 'imageLoader', if (repeatMode === 'RepeatAll') { toggleRepeatButtonIcon.innerHTML = "repeat"; toggleRepeatButton.classList.add('repeatButton-active'); - } - else if (repeatMode === 'RepeatOne') { + } else if (repeatMode === 'RepeatOne') { toggleRepeatButtonIcon.innerHTML = "repeat_one"; toggleRepeatButton.classList.add('repeatButton-active'); } else { diff --git a/src/components/playback/autoplaydetect.js b/src/components/playback/autoplaydetect.js index 7a7a73a538..3610eef2ab 100644 --- a/src/components/playback/autoplaydetect.js +++ b/src/components/playback/autoplaydetect.js @@ -48,9 +48,7 @@ define([], function () { } timeout = setTimeout(testAutoplay, 500); - } - - catch (e) { + } catch (e) { reject(); return; } diff --git a/src/components/playback/brightnessosd.js b/src/components/playback/brightnessosd.js index 1797463f29..c949743bec 100644 --- a/src/components/playback/brightnessosd.js +++ b/src/components/playback/brightnessosd.js @@ -103,8 +103,7 @@ define(['events', 'playbackManager', 'dom', 'browser', 'css!./iconosd', 'materia if (iconElement) { if (brightness >= 80) { iconElement.innerHTML = ''; - } - else if (brightness >= 20) { + } else if (brightness >= 20) { iconElement.innerHTML = ''; } else { iconElement.innerHTML = ''; diff --git a/src/components/playback/mediasession.js b/src/components/playback/mediasession.js index 63e0bde6c1..7f4b9f519e 100644 --- a/src/components/playback/mediasession.js +++ b/src/components/playback/mediasession.js @@ -158,7 +158,7 @@ define(['playbackManager', 'nowPlayingHelper', 'events', 'connectionManager'], f lastUpdateTime = now; - if (navigator.mediaSession){ + if (navigator.mediaSession) { navigator.mediaSession.metadata = new MediaMetadata({ title: title, artist: artist, @@ -278,7 +278,6 @@ define(['playbackManager', 'nowPlayingHelper', 'events', 'connectionManager'], f } if (navigator.mediaSession) { - navigator.mediaSession.setActionHandler('previoustrack', function () { execute('previousTrack'); }); diff --git a/src/components/playback/nowplayinghelper.js b/src/components/playback/nowplayinghelper.js index d5803b426f..b1af977ab0 100644 --- a/src/components/playback/nowplayinghelper.js +++ b/src/components/playback/nowplayinghelper.js @@ -43,8 +43,7 @@ define([], function () { } else if (nowPlayingItem.Artists && nowPlayingItem.Artists.length) { bottomText = nowPlayingItem.Artists.join(', '); - } - else if (nowPlayingItem.SeriesName || nowPlayingItem.Album) { + } else if (nowPlayingItem.SeriesName || nowPlayingItem.Album) { bottomText = topText; topText = nowPlayingItem.SeriesName || nowPlayingItem.Album; @@ -60,8 +59,7 @@ define([], function () { } else { topItem = null; } - } - else if (nowPlayingItem.ProductionYear && includeNonNameInfo !== false) { + } else if (nowPlayingItem.ProductionYear && includeNonNameInfo !== false) { bottomText = nowPlayingItem.ProductionYear; } diff --git a/src/components/playback/playbackmanager.js b/src/components/playback/playbackmanager.js index 13497e1912..23f0d4572e 100644 --- a/src/components/playback/playbackmanager.js +++ b/src/components/playback/playbackmanager.js @@ -107,8 +107,7 @@ define(['events', 'datetime', 'appSettings', 'itemHelper', 'pluginManager', 'pla TotalRecordCount: 1 }; }); - } - else { + } else { query.Limit = query.Limit || 300; query.Fields = "Chapters"; @@ -182,8 +181,7 @@ define(['events', 'datetime', 'appSettings', 'itemHelper', 'pluginManager', 'pla if (container === 'm4a') { return 'audio/mp4'; } - } - else if (type === 'video') { + } else if (type === 'video') { if (container === 'mkv') { return 'video/x-matroska'; } @@ -212,8 +210,7 @@ define(['events', 'datetime', 'appSettings', 'itemHelper', 'pluginManager', 'pla var results = regex.exec(url); if (results == null) { return ""; - } - else { + } else { return decodeURIComponent(results[1].replace(/\+/g, " ")); } } @@ -649,13 +646,10 @@ define(['events', 'datetime', 'appSettings', 'itemHelper', 'pluginManager', 'pla // If this is the only way it can be played, then allow it if (!mediaSource.SupportsDirectStream && !mediaSource.SupportsTranscoding) { return Promise.resolve(true); - } - else { + } else { return isHostReachable(mediaSource, apiClient); } - } - - else if (mediaSource.Protocol === 'File') { + } else if (mediaSource.Protocol === 'File') { return new Promise(function (resolve, reject) { @@ -1272,7 +1266,8 @@ define(['events', 'datetime', 'appSettings', 'itemHelper', 'pluginManager', 'pla var currentMediaSource = self.currentMediaSource(player); var mediaStreams = []; - var i, length; + var i; + var length; for (i = 0, length = currentMediaSource.MediaStreams.length; i < length; i++) { if (currentMediaSource.MediaStreams[i].Type === 'Audio') { mediaStreams.push(currentMediaSource.MediaStreams[i]); @@ -1316,7 +1311,8 @@ define(['events', 'datetime', 'appSettings', 'itemHelper', 'pluginManager', 'pla var currentMediaSource = self.currentMediaSource(player); var mediaStreams = []; - var i, length; + var i; + var length; for (i = 0, length = currentMediaSource.MediaStreams.length; i < length; i++) { if (currentMediaSource.MediaStreams[i].Type === 'Subtitle') { mediaStreams.push(currentMediaSource.MediaStreams[i]); @@ -1360,7 +1356,8 @@ define(['events', 'datetime', 'appSettings', 'itemHelper', 'pluginManager', 'pla function isAudioStreamSupported(mediaSource, index, deviceProfile) { var mediaStream; - var i, length; + var i; + var length; var mediaStreams = mediaSource.MediaStreams; for (i = 0, length = mediaStreams.length; i < length; i++) { @@ -1423,8 +1420,7 @@ define(['events', 'datetime', 'appSettings', 'itemHelper', 'pluginManager', 'pla if (isAudioStreamSupported(self.currentMediaSource(player), index, profile)) { player.setAudioStreamIndex(index); getPlayerData(player).audioStreamIndex = index; - } - else { + } else { changeStream(player, getCurrentTicks(player), { AudioStreamIndex: index }); getPlayerData(player).audioStreamIndex = index; } @@ -1595,8 +1591,7 @@ define(['events', 'datetime', 'appSettings', 'itemHelper', 'pluginManager', 'pla // Need to change the transcoded stream to remove subs changeStream(player, getCurrentTicks(player), { SubtitleStreamIndex: -1 }); } - } - else if (!currentStream && newStream) { + } else if (!currentStream && newStream) { if (getDeliveryMethod(newStream) === 'External') { selectedTrackElementIndex = index; @@ -1607,8 +1602,7 @@ define(['events', 'datetime', 'appSettings', 'itemHelper', 'pluginManager', 'pla // Need to change the transcoded stream to add subs changeStream(player, getCurrentTicks(player), { SubtitleStreamIndex: index }); } - } - else if (currentStream && newStream) { + } else if (currentStream && newStream) { // Switching tracks // We can handle this clientside if the new track is external or the new track is embedded and we're not transcoding @@ -1645,7 +1639,7 @@ define(['events', 'datetime', 'appSettings', 'itemHelper', 'pluginManager', 'pla player = player || self._currentPlayer; if (player.disableShowingSubtitleOffset) { player.disableShowingSubtitleOffset(); - } + } } self.isShowingSubtitleOffsetEnabled = function(player) { @@ -1674,7 +1668,7 @@ define(['events', 'datetime', 'appSettings', 'itemHelper', 'pluginManager', 'pla self.canHandleOffsetOnCurrentSubtitle = function(player) { var index = self.getSubtitleStreamIndex(player); - return index !== -1 && self.isSubtitleStreamExternal(index, player); + return index !== -1 && self.isSubtitleStreamExternal(index, player); } self.seek = function (ticks, player) { @@ -1865,17 +1859,15 @@ define(['events', 'datetime', 'appSettings', 'itemHelper', 'pluginManager', 'pla if (firstItem.Type === "Program") { promise = getItemsForPlayback(serverId, { - Ids: firstItem.ChannelId, + Ids: firstItem.ChannelId }); - } - else if (firstItem.Type === "Playlist") { + } else if (firstItem.Type === "Playlist") { promise = getItemsForPlayback(serverId, { ParentId: firstItem.Id, SortBy: options.shuffle ? 'Random' : null }); - } - else if (firstItem.Type === "MusicArtist") { + } else if (firstItem.Type === "MusicArtist") { promise = getItemsForPlayback(serverId, { ArtistIds: firstItem.Id, @@ -1885,8 +1877,7 @@ define(['events', 'datetime', 'appSettings', 'itemHelper', 'pluginManager', 'pla MediaTypes: "Audio" }); - } - else if (firstItem.MediaType === "Photo") { + } else if (firstItem.MediaType === "Photo") { promise = getItemsForPlayback(serverId, { ParentId: firstItem.ParentId, @@ -1915,8 +1906,7 @@ define(['events', 'datetime', 'appSettings', 'itemHelper', 'pluginManager', 'pla return Promise.resolve(result); }); - } - else if (firstItem.Type === "PhotoAlbum") { + } else if (firstItem.Type === "PhotoAlbum") { promise = getItemsForPlayback(serverId, { ParentId: firstItem.Id, @@ -1928,8 +1918,7 @@ define(['events', 'datetime', 'appSettings', 'itemHelper', 'pluginManager', 'pla Limit: 1000 }); - } - else if (firstItem.Type === "MusicGenre") { + } else if (firstItem.Type === "MusicGenre") { promise = getItemsForPlayback(serverId, { GenreIds: firstItem.Id, @@ -1938,8 +1927,7 @@ define(['events', 'datetime', 'appSettings', 'itemHelper', 'pluginManager', 'pla SortBy: options.shuffle ? 'Random' : 'SortName', MediaTypes: "Audio" }); - } - else if (firstItem.IsFolder) { + } else if (firstItem.IsFolder) { promise = getItemsForPlayback(serverId, mergePlaybackQueries({ @@ -1951,8 +1939,7 @@ define(['events', 'datetime', 'appSettings', 'itemHelper', 'pluginManager', 'pla MediaTypes: "Audio,Video" }, queryOptions)); - } - else if (firstItem.Type === "Episode" && items.length === 1 && getPlayer(firstItem, options).supportsProgress !== false) { + } else if (firstItem.Type === "Episode" && items.length === 1 && getPlayer(firstItem, options).supportsProgress !== false) { promise = new Promise(function (resolve, reject) { var apiClient = connectionManager.getApiClient(firstItem.ServerId); @@ -2537,16 +2524,12 @@ define(['events', 'datetime', 'appSettings', 'itemHelper', 'pluginManager', 'pla playMethod = 'DirectPlay'; - } - - else if (mediaSource.StreamUrl) { + } else if (mediaSource.StreamUrl) { // Only used for audio playMethod = 'Transcode'; mediaUrl = mediaSource.StreamUrl; - } - - else if (mediaSource.SupportsDirectStream) { + } else if (mediaSource.SupportsDirectStream) { directOptions = { Static: true, @@ -2706,9 +2689,7 @@ define(['events', 'datetime', 'appSettings', 'itemHelper', 'pluginManager', 'pla return p.canPlayItem(item, playOptions); } return true; - } - - else if (item.Url && p.canPlayUrl) { + } else if (item.Url && p.canPlayUrl) { return p.canPlayUrl(item.Url); } } @@ -3222,8 +3203,7 @@ define(['events', 'datetime', 'appSettings', 'itemHelper', 'pluginManager', 'pla if (displayErrorCode && typeof (displayErrorCode) === 'string') { showPlaybackInfoErrorMessage(self, displayErrorCode, nextItem); - } - else if (nextItem) { + } else if (nextItem) { self.nextTrack(); } } diff --git a/src/components/playback/playbackorientation.js b/src/components/playback/playbackorientation.js index 731d9c3c42..3253d8acdf 100644 --- a/src/components/playback/playbackorientation.js +++ b/src/components/playback/playbackorientation.js @@ -29,8 +29,7 @@ define(['playbackManager', 'layoutManager', 'events'], function (playbackManager // returns a boolean orientationLocked = promise; } - } - catch (err) { + } catch (err) { onOrientationChangeError(err); } } @@ -46,8 +45,7 @@ define(['playbackManager', 'layoutManager', 'events'], function (playbackManager if (unlockOrientation) { try { unlockOrientation(); - } - catch (err) { + } catch (err) { console.log('error unlocking orientation: ' + err); } orientationLocked = false; diff --git a/src/components/playback/playerSelectionMenu.js b/src/components/playback/playerSelectionMenu.js index 2102720e9a..7e4352bcb7 100644 --- a/src/components/playback/playerSelectionMenu.js +++ b/src/components/playback/playerSelectionMenu.js @@ -153,7 +153,6 @@ define(['appSettings', 'events', 'browser', 'loading', 'playbackManager', 'appRo }); } - function disconnectFromPlayer(currentDeviceName) { if (playbackManager.getSupportedCommands().indexOf('EndSession') !== -1) { @@ -193,7 +192,6 @@ define(['appSettings', 'events', 'browser', 'loading', 'playbackManager', 'appRo }); - } else { playbackManager.setDefaultPlayerActive(); @@ -275,8 +273,7 @@ define(['appSettings', 'events', 'browser', 'loading', 'playbackManager', 'appRo dialogHelper.open(dlg).then(function () { if (destination === 'nowplaying') { appRouter.showNowPlaying(); - } - else if (destination === 'disconnectFromPlayer') { + } else if (destination === 'disconnectFromPlayer') { disconnectFromPlayer(currentDeviceName); } }, emptyCallback); diff --git a/src/components/playback/playmethodhelper.js b/src/components/playback/playmethodhelper.js index 58458aa399..4e85f87093 100644 --- a/src/components/playback/playmethodhelper.js +++ b/src/components/playback/playmethodhelper.js @@ -9,14 +9,11 @@ define([], function () { if (session.TranscodingInfo && session.TranscodingInfo.IsVideoDirect) { return 'DirectStream'; - } - else if (session.PlayState.PlayMethod === 'Transcode') { + } else if (session.PlayState.PlayMethod === 'Transcode') { return 'Transcode'; - } - else if (session.PlayState.PlayMethod === 'DirectStream') { + } else if (session.PlayState.PlayMethod === 'DirectStream') { return 'DirectPlay'; - } - else if (session.PlayState.PlayMethod === 'DirectPlay') { + } else if (session.PlayState.PlayMethod === 'DirectPlay') { return 'DirectPlay'; } } diff --git a/src/components/playback/playqueuemanager.js b/src/components/playback/playqueuemanager.js index 2cbaf1d9f4..ed2076a814 100644 --- a/src/components/playback/playqueuemanager.js +++ b/src/components/playback/playqueuemanager.js @@ -58,15 +58,15 @@ define([], function () { function arrayInsertAt(destArray, pos, arrayToInsert) { var args = []; - args.push(pos); // where to insert - args.push(0); // nothing to remove - args = args.concat(arrayToInsert); // add on array to insert - destArray.splice.apply(destArray, args); // splice it in + args.push(pos); // where to insert + args.push(0); // nothing to remove + args = args.concat(arrayToInsert); // add on array to insert + destArray.splice.apply(destArray, args); // splice it in } PlayQueueManager.prototype.queueNext = function (items) { - - var i, length; + var i; + var length; for (i = 0, length = items.length; i < length; i++) { diff --git a/src/components/playerstats/playerstats.js b/src/components/playerstats/playerstats.js index 5e097f2fe2..4179192dd2 100644 --- a/src/components/playerstats/playerstats.js +++ b/src/components/playerstats/playerstats.js @@ -364,8 +364,7 @@ define(['events', 'globalize', 'playbackManager', 'connectionManager', 'playMeth var category = playerStats[i]; if (category.type === 'audio') { category.name = 'Audio Info'; - } - else if (category.type === 'video') { + } else if (category.type === 'video') { category.name = 'Video Info'; } categories.push(category); diff --git a/src/components/recordingcreator/recordingbutton.js b/src/components/recordingcreator/recordingbutton.js index 0a76d3914c..f51f8f2766 100644 --- a/src/components/recordingcreator/recordingbutton.js +++ b/src/components/recordingcreator/recordingbutton.js @@ -46,16 +46,13 @@ define(['globalize', 'connectionManager', 'require', 'loading', 'apphost', 'dom' if (item.Type === 'SeriesTimer') { return ''; - } - else if (item.TimerId || item.SeriesTimerId) { + } else if (item.TimerId || item.SeriesTimerId) { status = item.Status || 'Cancelled'; - } - else if (item.Type === 'Timer') { + } else if (item.Type === 'Timer') { status = item.Status; - } - else { + } else { return ''; } diff --git a/src/components/recordingcreator/recordingcreator.js b/src/components/recordingcreator/recordingcreator.js index b3d16a0dab..614d483b21 100644 --- a/src/components/recordingcreator/recordingcreator.js +++ b/src/components/recordingcreator/recordingcreator.js @@ -40,8 +40,7 @@ define(['dialogHelper', 'globalize', 'layoutManager', 'mediaInfo', 'apphost', 'c maxHeight: imageHeight, tag: item.ImageTags.Primary }); - } - else if (imageTags.Thumb) { + } else if (imageTags.Thumb) { return apiClient.getScaledImageUrl(item.Id, { type: "Thumb", diff --git a/src/components/recordingcreator/recordingeditor.js b/src/components/recordingcreator/recordingeditor.js index 69b8b1023b..3a1d4ba943 100644 --- a/src/components/recordingcreator/recordingeditor.js +++ b/src/components/recordingcreator/recordingeditor.js @@ -95,7 +95,6 @@ define(['dialogHelper', 'globalize', 'layoutManager', 'mediaInfo', 'apphost', 'c currentResolve = resolve; require(['text!./recordingeditor.template.html'], function (template) { - var dialogOptions = { removeOnClose: true, scrollY: false @@ -103,7 +102,6 @@ define(['dialogHelper', 'globalize', 'layoutManager', 'mediaInfo', 'apphost', 'c if (layoutManager.tv) { dialogOptions.size = 'fullscreen'; - } else { } var dlg = dialogHelper.createDialog(dialogOptions); diff --git a/src/components/recordingcreator/recordinghelper.js b/src/components/recordingcreator/recordinghelper.js index 8c56b578c9..4bfd316c73 100644 --- a/src/components/recordingcreator/recordinghelper.js +++ b/src/components/recordingcreator/recordinghelper.js @@ -166,8 +166,7 @@ define(['globalize', 'loading', 'connectionManager'], function (globalize, loadi loading.show(); cancelTimer(apiClient, timerId, true).then(resolve, reject); - } - else if (result === 'cancelseriestimer') { + } else if (result === 'cancelseriestimer') { loading.show(); diff --git a/src/components/recordingcreator/seriesrecordingeditor.js b/src/components/recordingcreator/seriesrecordingeditor.js index 9878081e67..73a98cf5e7 100644 --- a/src/components/recordingcreator/seriesrecordingeditor.js +++ b/src/components/recordingcreator/seriesrecordingeditor.js @@ -139,7 +139,7 @@ define(['dialogHelper', 'globalize', 'layoutManager', 'mediaInfo', 'apphost', 'c context.querySelector('.selectKeepUpTo').innerHTML = html; } - + function onFieldChange(e) { this.querySelector('.btnSubmit').click(); } diff --git a/src/components/remotecontrol/remotecontrol.js b/src/components/remotecontrol/remotecontrol.js index e586a1e124..562ea7ea35 100644 --- a/src/components/remotecontrol/remotecontrol.js +++ b/src/components/remotecontrol/remotecontrol.js @@ -179,15 +179,15 @@ define(["browser", "datetime", "backdrop", "libraryBrowser", "listView", "imageL if (player) { switch (playbackManager.getRepeatMode(player)) { case "RepeatNone": - playbackManager.setRepeatMode("RepeatAll", player); - break; + playbackManager.setRepeatMode("RepeatAll", player); + break; case "RepeatAll": - playbackManager.setRepeatMode("RepeatOne", player); - break; + playbackManager.setRepeatMode("RepeatOne", player); + break; case "RepeatOne": - playbackManager.setRepeatMode("RepeatNone", player); + playbackManager.setRepeatMode("RepeatNone", player); } } } diff --git a/src/components/sanitizefilename.js b/src/components/sanitizefilename.js index 843ab31f04..d422a95533 100644 --- a/src/components/sanitizefilename.js +++ b/src/components/sanitizefilename.js @@ -34,18 +34,14 @@ define([], function () { // when parsing previous hi-surrogate, 3 is added to byteLength if (prevCodePoint != null && isHighSurrogate(prevCodePoint)) { byteLength += 1; - } - else { + } else { byteLength += 3; } - } - else if (codePoint <= 0x7f) { + } else if (codePoint <= 0x7f) { byteLength += 1; - } - else if (codePoint >= 0x80 && codePoint <= 0x7ff) { + } else if (codePoint >= 0x80 && codePoint <= 0x7ff) { byteLength += 2; - } - else if (codePoint >= 0x800 && codePoint <= 0xffff) { + } else if (codePoint >= 0x800 && codePoint <= 0xffff) { byteLength += 3; } prevCodePoint = codePoint; @@ -77,8 +73,7 @@ define([], function () { if (curByteLength === byteLength) { return string.slice(0, i + 1); - } - else if (curByteLength > byteLength) { + } else if (curByteLength > byteLength) { return string.slice(0, i - segment.length + 1); } } @@ -89,11 +84,11 @@ define([], function () { return { sanitize: function (input, replacement) { var sanitized = input - .replace(illegalRe, replacement) - .replace(controlRe, replacement) - .replace(reservedRe, replacement) - .replace(windowsReservedRe, replacement) - .replace(windowsTrailingRe, replacement); + .replace(illegalRe, replacement) + .replace(controlRe, replacement) + .replace(reservedRe, replacement) + .replace(windowsReservedRe, replacement) + .replace(windowsTrailingRe, replacement); return truncate(sanitized, 255); } }; diff --git a/src/components/scroller.js b/src/components/scroller.js index de0ce6b932..65f33b8e8d 100644 --- a/src/components/scroller.js +++ b/src/components/scroller.js @@ -82,7 +82,7 @@ define(['browser', 'layoutManager', 'dom', 'focusManager', 'ResizeObserver', 'sc intervactive: null, // Selector for special interactive elements. // Mixed options - speed: 0, // Animations speed in milliseconds. 0 to disable animations. + speed: 0 // Animations speed in milliseconds. 0 to disable animations. }, options); @@ -93,17 +93,14 @@ define(['browser', 'layoutManager', 'dom', 'focusManager', 'ResizeObserver', 'sc // in cases with firefox, if the smooth scroll api is supported then use that because their implementation is very good if (options.allowNativeScroll === false) { options.enableNativeScroll = false; - } - else if (isSmoothScrollSupported && ((browser.firefox && !layoutManager.tv) || options.allowNativeSmoothScroll)) { + } else if (isSmoothScrollSupported && ((browser.firefox && !layoutManager.tv) || options.allowNativeSmoothScroll)) { // native smooth scroll options.enableNativeScroll = true; - } - else if (options.requireAnimation && (browser.animate || browser.supportsCssAnimation())) { + } else if (options.requireAnimation && (browser.animate || browser.supportsCssAnimation())) { // transform is the only way to guarantee animation options.enableNativeScroll = false; - } - else if (!layoutManager.tv || !browser.animate) { + } else if (!layoutManager.tv || !browser.animate) { options.enableNativeScroll = true; } @@ -211,7 +208,9 @@ define(['browser', 'layoutManager', 'dom', 'focusManager', 'ResizeObserver', 'sc self.frameResizeObserver.observe(frame); } - self.reload = function () { load(); }; + self.reload = function () { + load(); + }; self.getScrollEventName = function () { return transform ? 'scrollanimate' : 'scroll'; @@ -227,7 +226,6 @@ define(['browser', 'layoutManager', 'dom', 'focusManager', 'ResizeObserver', 'sc function nativeScrollTo(container, pos, immediate) { - if (container.scroll) { if (o.horizontal) { @@ -242,8 +240,7 @@ define(['browser', 'layoutManager', 'dom', 'focusManager', 'ResizeObserver', 'sc behavior: immediate ? 'instant' : 'smooth' }); } - } - else if (!immediate && container.scrollTo) { + } else if (!immediate && container.scrollTo) { if (o.horizontal) { container.scrollTo(Math.round(pos), 0); } else { diff --git a/src/components/search/searchresults.js b/src/components/search/searchresults.js index e42088c066..d979a94693 100644 --- a/src/components/search/searchresults.js +++ b/src/components/search/searchresults.js @@ -56,8 +56,7 @@ define(['layoutManager', 'globalize', 'require', 'events', 'connectionManager', if (instance.options.collectionType === 'tvshows') { if (query.IncludeArtists) { allowSearch = false; - } - else if (queryIncludeItemTypes === 'Movie' || + } else if (queryIncludeItemTypes === 'Movie' || queryIncludeItemTypes === 'LiveTvProgram' || queryIncludeItemTypes === 'MusicAlbum' || queryIncludeItemTypes === 'Audio' || @@ -69,12 +68,10 @@ define(['layoutManager', 'globalize', 'require', 'events', 'connectionManager', query.MediaTypes === 'Photo') { allowSearch = false; } - } - else if (instance.options.collectionType === 'movies') { + } else if (instance.options.collectionType === 'movies') { if (query.IncludeArtists) { allowSearch = false; - } - else if (queryIncludeItemTypes === 'Series' || + } else if (queryIncludeItemTypes === 'Series' || queryIncludeItemTypes === 'Episode' || queryIncludeItemTypes === 'LiveTvProgram' || queryIncludeItemTypes === 'MusicAlbum' || @@ -87,23 +84,19 @@ define(['layoutManager', 'globalize', 'require', 'events', 'connectionManager', query.MediaTypes === 'Photo') { allowSearch = false; } - } - else if (instance.options.collectionType === 'music') { + } else if (instance.options.collectionType === 'music') { if (query.People) { allowSearch = false; - } - else if (queryIncludeItemTypes === 'Series' || + } else if (queryIncludeItemTypes === 'Series' || queryIncludeItemTypes === 'Episode' || queryIncludeItemTypes === 'LiveTvProgram' || queryIncludeItemTypes === 'Movie') { allowSearch = false; } - } - else if (instance.options.collectionType === 'livetv') { + } else if (instance.options.collectionType === 'livetv') { if (query.IncludeArtists || query.IncludePeople) { allowSearch = false; - } - else if (queryIncludeItemTypes === 'Series' || + } else if (queryIncludeItemTypes === 'Series' || queryIncludeItemTypes === 'Episode' || queryIncludeItemTypes === 'MusicAlbum' || queryIncludeItemTypes === 'Audio' || @@ -142,7 +135,7 @@ define(['layoutManager', 'globalize', 'require', 'events', 'connectionManager', } else if (query.IncludeArtists) { methodName = 'getArtists'; - } + } } return apiClient[methodName](apiClient.getCurrentUserId(), query); @@ -179,19 +172,19 @@ define(['layoutManager', 'globalize', 'require', 'events', 'connectionManager', }, context, '.movieResults', { - preferThumb: true, - inheritThumb: false, - shape: (enableScrollX() ? 'overflowPortrait' : 'portrait'), - showParentTitleOrTitle: true, - showTitle: false, - centerText: true, - coverImage: true, - overlayText: false, - overlayMoreButton: true, - showAirTime: true, - showAirDateTime: true, - showChannelName: true - }); + preferThumb: true, + inheritThumb: false, + shape: (enableScrollX() ? 'overflowPortrait' : 'portrait'), + showParentTitleOrTitle: true, + showTitle: false, + centerText: true, + coverImage: true, + overlayText: false, + overlayMoreButton: true, + showAirTime: true, + showAirDateTime: true, + showChannelName: true + }); } else { searchType(instance, apiClient, { @@ -205,11 +198,11 @@ define(['layoutManager', 'globalize', 'require', 'events', 'connectionManager', }, context, '.movieResults', { - showTitle: true, - overlayText: false, - centerText: true, - showYear: true - }); + showTitle: true, + overlayText: false, + centerText: true, + showYear: true + }); } searchType(instance, apiClient, { @@ -223,11 +216,11 @@ define(['layoutManager', 'globalize', 'require', 'events', 'connectionManager', }, context, '.seriesResults', { - showTitle: true, - overlayText: false, - centerText: true, - showYear: true - }); + showTitle: true, + overlayText: false, + centerText: true, + showYear: true + }); if (instance.options.collectionType === 'livetv') { @@ -246,19 +239,19 @@ define(['layoutManager', 'globalize', 'require', 'events', 'connectionManager', }, context, '.episodeResults', { - preferThumb: true, - inheritThumb: false, - shape: (enableScrollX() ? 'overflowBackdrop' : 'backdrop'), - showParentTitleOrTitle: true, - showTitle: false, - centerText: true, - coverImage: true, - overlayText: false, - overlayMoreButton: true, - showAirTime: true, - showAirDateTime: true, - showChannelName: true - }); + preferThumb: true, + inheritThumb: false, + shape: (enableScrollX() ? 'overflowBackdrop' : 'backdrop'), + showParentTitleOrTitle: true, + showTitle: false, + centerText: true, + coverImage: true, + overlayText: false, + overlayMoreButton: true, + showAirTime: true, + showAirDateTime: true, + showChannelName: true + }); } else { @@ -273,10 +266,10 @@ define(['layoutManager', 'globalize', 'require', 'events', 'connectionManager', }, context, '.episodeResults', { - coverImage: true, - showTitle: true, - showParentTitle: true - }); + coverImage: true, + showTitle: true, + showParentTitle: true + }); } searchType(instance, apiClient, { @@ -292,20 +285,20 @@ define(['layoutManager', 'globalize', 'require', 'events', 'connectionManager', }, context, '.sportsResults', { - preferThumb: true, - inheritThumb: false, - shape: (enableScrollX() ? 'overflowBackdrop' : 'backdrop'), - showParentTitleOrTitle: true, - showTitle: false, - centerText: true, - coverImage: true, - overlayText: false, - overlayMoreButton: true, - showAirTime: true, - showAirDateTime: true, - showChannelName: true + preferThumb: true, + inheritThumb: false, + shape: (enableScrollX() ? 'overflowBackdrop' : 'backdrop'), + showParentTitleOrTitle: true, + showTitle: false, + centerText: true, + coverImage: true, + overlayText: false, + overlayMoreButton: true, + showAirTime: true, + showAirDateTime: true, + showChannelName: true - }); + }); searchType(instance, apiClient, { searchTerm: value, @@ -320,20 +313,20 @@ define(['layoutManager', 'globalize', 'require', 'events', 'connectionManager', }, context, '.kidsResults', { - preferThumb: true, - inheritThumb: false, - shape: (enableScrollX() ? 'overflowBackdrop' : 'backdrop'), - showParentTitleOrTitle: true, - showTitle: false, - centerText: true, - coverImage: true, - overlayText: false, - overlayMoreButton: true, - showAirTime: true, - showAirDateTime: true, - showChannelName: true + preferThumb: true, + inheritThumb: false, + shape: (enableScrollX() ? 'overflowBackdrop' : 'backdrop'), + showParentTitleOrTitle: true, + showTitle: false, + centerText: true, + coverImage: true, + overlayText: false, + overlayMoreButton: true, + showAirTime: true, + showAirDateTime: true, + showChannelName: true - }); + }); searchType(instance, apiClient, { searchTerm: value, @@ -348,20 +341,20 @@ define(['layoutManager', 'globalize', 'require', 'events', 'connectionManager', }, context, '.newsResults', { - preferThumb: true, - inheritThumb: false, - shape: (enableScrollX() ? 'overflowBackdrop' : 'backdrop'), - showParentTitleOrTitle: true, - showTitle: false, - centerText: true, - coverImage: true, - overlayText: false, - overlayMoreButton: true, - showAirTime: true, - showAirDateTime: true, - showChannelName: true + preferThumb: true, + inheritThumb: false, + shape: (enableScrollX() ? 'overflowBackdrop' : 'backdrop'), + showParentTitleOrTitle: true, + showTitle: false, + centerText: true, + coverImage: true, + overlayText: false, + overlayMoreButton: true, + showAirTime: true, + showAirDateTime: true, + showChannelName: true - }); + }); searchType(instance, apiClient, { searchTerm: value, @@ -379,20 +372,20 @@ define(['layoutManager', 'globalize', 'require', 'events', 'connectionManager', }, context, '.programResults', { - preferThumb: true, - inheritThumb: false, - shape: (enableScrollX() ? 'overflowBackdrop' : 'backdrop'), - showParentTitleOrTitle: true, - showTitle: false, - centerText: true, - coverImage: true, - overlayText: false, - overlayMoreButton: true, - showAirTime: true, - showAirDateTime: true, - showChannelName: true + preferThumb: true, + inheritThumb: false, + shape: (enableScrollX() ? 'overflowBackdrop' : 'backdrop'), + showParentTitleOrTitle: true, + showTitle: false, + centerText: true, + coverImage: true, + overlayText: false, + overlayMoreButton: true, + showAirTime: true, + showAirDateTime: true, + showChannelName: true - }); + }); searchType(instance, apiClient, { searchTerm: value, @@ -406,11 +399,11 @@ define(['layoutManager', 'globalize', 'require', 'events', 'connectionManager', }, context, '.videoResults', { - showParentTitle: true, - showTitle: true, - overlayText: false, - centerText: true - }); + showParentTitle: true, + showTitle: true, + overlayText: false, + centerText: true + }); searchType(instance, apiClient, { searchTerm: value, @@ -422,9 +415,9 @@ define(['layoutManager', 'globalize', 'require', 'events', 'connectionManager', }, context, '.peopleResults', { - coverImage: true, - showTitle: true - }); + coverImage: true, + showTitle: true + }); searchType(instance, apiClient, { searchTerm: value, @@ -435,9 +428,9 @@ define(['layoutManager', 'globalize', 'require', 'events', 'connectionManager', IncludeArtists: true }, context, '.artistResults', { - coverImage: true, - showTitle: true - }); + coverImage: true, + showTitle: true + }); searchType(instance, apiClient, { searchTerm: value, @@ -450,11 +443,11 @@ define(['layoutManager', 'globalize', 'require', 'events', 'connectionManager', }, context, '.albumResults', { - showParentTitle: true, - showTitle: true, - overlayText: false, - centerText: true - }); + showParentTitle: true, + showTitle: true, + overlayText: false, + centerText: true + }); searchType(instance, apiClient, { searchTerm: value, @@ -467,13 +460,13 @@ define(['layoutManager', 'globalize', 'require', 'events', 'connectionManager', }, context, '.songResults', { - showParentTitle: true, - showTitle: true, - overlayText: false, - centerText: true, - action: 'play' + showParentTitle: true, + showTitle: true, + overlayText: false, + centerText: true, + action: 'play' - }); + }); searchType(instance, apiClient, { searchTerm: value, @@ -486,11 +479,11 @@ define(['layoutManager', 'globalize', 'require', 'events', 'connectionManager', }, context, '.photoResults', { - showParentTitle: false, - showTitle: true, - overlayText: false, - centerText: true - }); + showParentTitle: false, + showTitle: true, + overlayText: false, + centerText: true + }); searchType(instance, apiClient, { searchTerm: value, @@ -503,10 +496,10 @@ define(['layoutManager', 'globalize', 'require', 'events', 'connectionManager', }, context, '.photoAlbumResults', { - showTitle: true, - overlayText: false, - centerText: true - }); + showTitle: true, + overlayText: false, + centerText: true + }); searchType(instance, apiClient, { searchTerm: value, @@ -519,11 +512,11 @@ define(['layoutManager', 'globalize', 'require', 'events', 'connectionManager', }, context, '.bookResults', { - showTitle: true, - overlayText: false, - centerText: true + showTitle: true, + overlayText: false, + centerText: true - }); + }); searchType(instance, apiClient, { searchTerm: value, @@ -536,10 +529,10 @@ define(['layoutManager', 'globalize', 'require', 'events', 'connectionManager', }, context, '.audioBookResults', { - showTitle: true, - overlayText: false, - centerText: true - }); + showTitle: true, + overlayText: false, + centerText: true + }); searchType(instance, apiClient, { searchTerm: value, @@ -552,10 +545,10 @@ define(['layoutManager', 'globalize', 'require', 'events', 'connectionManager', }, context, '.playlistResults', { - showTitle: true, - overlayText: false, - centerText: true - }); + showTitle: true, + overlayText: false, + centerText: true + }); } function searchType(instance, apiClient, query, context, section, cardOptions) { diff --git a/src/components/serverNotifications/gamepadtokey.js b/src/components/serverNotifications/gamepadtokey.js index 5dafb2828b..abf3ddb38b 100644 --- a/src/components/serverNotifications/gamepadtokey.js +++ b/src/components/serverNotifications/gamepadtokey.js @@ -22,44 +22,44 @@ require(['apphost'], function (appHost) { "use strict"; - var _GAMEPAD_A_BUTTON_INDEX = 0, - _GAMEPAD_B_BUTTON_INDEX = 1, - _GAMEPAD_DPAD_UP_BUTTON_INDEX = 12, - _GAMEPAD_DPAD_DOWN_BUTTON_INDEX = 13, - _GAMEPAD_DPAD_LEFT_BUTTON_INDEX = 14, - _GAMEPAD_DPAD_RIGHT_BUTTON_INDEX = 15, - _GAMEPAD_A_KEY = "GamepadA", - _GAMEPAD_B_KEY = "GamepadB", - _GAMEPAD_DPAD_UP_KEY = "GamepadDPadUp", - _GAMEPAD_DPAD_DOWN_KEY = "GamepadDPadDown", - _GAMEPAD_DPAD_LEFT_KEY = "GamepadDPadLeft", - _GAMEPAD_DPAD_RIGHT_KEY = "GamepadDPadRight", - _GAMEPAD_LEFT_THUMBSTICK_UP_KEY = "GamepadLeftThumbStickUp", - _GAMEPAD_LEFT_THUMBSTICK_DOWN_KEY = "GamepadLeftThumbStickDown", - _GAMEPAD_LEFT_THUMBSTICK_LEFT_KEY = "GamepadLeftThumbStickLeft", - _GAMEPAD_LEFT_THUMBSTICK_RIGHT_KEY = "GamepadLeftThumbStickRight", - _GAMEPAD_A_KEYCODE = 0, - _GAMEPAD_B_KEYCODE = 27, - _GAMEPAD_DPAD_UP_KEYCODE = 38, - _GAMEPAD_DPAD_DOWN_KEYCODE = 40, - _GAMEPAD_DPAD_LEFT_KEYCODE = 37, - _GAMEPAD_DPAD_RIGHT_KEYCODE = 39, - _GAMEPAD_LEFT_THUMBSTICK_UP_KEYCODE = 38, - _GAMEPAD_LEFT_THUMBSTICK_DOWN_KEYCODE = 40, - _GAMEPAD_LEFT_THUMBSTICK_LEFT_KEYCODE = 37, - _GAMEPAD_LEFT_THUMBSTICK_RIGHT_KEYCODE = 39, - _THUMB_STICK_THRESHOLD = 0.75; + var _GAMEPAD_A_BUTTON_INDEX = 0; + var _GAMEPAD_B_BUTTON_INDEX = 1; + var _GAMEPAD_DPAD_UP_BUTTON_INDEX = 12; + var _GAMEPAD_DPAD_DOWN_BUTTON_INDEX = 13; + var _GAMEPAD_DPAD_LEFT_BUTTON_INDEX = 14; + var _GAMEPAD_DPAD_RIGHT_BUTTON_INDEX = 15; + var _GAMEPAD_A_KEY = "GamepadA"; + var _GAMEPAD_B_KEY = "GamepadB"; + var _GAMEPAD_DPAD_UP_KEY = "GamepadDPadUp"; + var _GAMEPAD_DPAD_DOWN_KEY = "GamepadDPadDown"; + var _GAMEPAD_DPAD_LEFT_KEY = "GamepadDPadLeft"; + var _GAMEPAD_DPAD_RIGHT_KEY = "GamepadDPadRight"; + var _GAMEPAD_LEFT_THUMBSTICK_UP_KEY = "GamepadLeftThumbStickUp"; + var _GAMEPAD_LEFT_THUMBSTICK_DOWN_KEY = "GamepadLeftThumbStickDown"; + var _GAMEPAD_LEFT_THUMBSTICK_LEFT_KEY = "GamepadLeftThumbStickLeft"; + var _GAMEPAD_LEFT_THUMBSTICK_RIGHT_KEY = "GamepadLeftThumbStickRight"; + var _GAMEPAD_A_KEYCODE = 0; + var _GAMEPAD_B_KEYCODE = 27; + var _GAMEPAD_DPAD_UP_KEYCODE = 38; + var _GAMEPAD_DPAD_DOWN_KEYCODE = 40; + var _GAMEPAD_DPAD_LEFT_KEYCODE = 37; + var _GAMEPAD_DPAD_RIGHT_KEYCODE = 39; + var _GAMEPAD_LEFT_THUMBSTICK_UP_KEYCODE = 38; + var _GAMEPAD_LEFT_THUMBSTICK_DOWN_KEYCODE = 40; + var _GAMEPAD_LEFT_THUMBSTICK_LEFT_KEYCODE = 37; + var _GAMEPAD_LEFT_THUMBSTICK_RIGHT_KEYCODE = 39; + var _THUMB_STICK_THRESHOLD = 0.75; - var _leftThumbstickUpPressed = false, - _leftThumbstickDownPressed = false, - _leftThumbstickLeftPressed = false, - _leftThumbstickRightPressed = false, - _dPadUpPressed = false, - _dPadDownPressed = false, - _dPadLeftPressed = false, - _dPadRightPressed = false, - _gamepadAPressed = false, - _gamepadBPressed = false; + var _leftThumbstickUpPressed = false; + var _leftThumbstickDownPressed = false; + var _leftThumbstickLeftPressed = false; + var _leftThumbstickRightPressed = false; + var _dPadUpPressed = false; + var _dPadDownPressed = false; + var _dPadLeftPressed = false; + var _dPadRightPressed = false; + var _gamepadAPressed = false; + var _gamepadBPressed = false; // The set of buttons on the gamepad we listen for. var ProcessedButtons = [ @@ -260,7 +260,9 @@ require(['apphost'], function (appHost) { gamepads = navigator.webkitGetGamepads(); } gamepads = gamepads || []; - var i, j, len; + var i; + var j; + var len; for (i = 0, len = gamepads.length; i < len; i++) { var gamepad = gamepads[i]; if (gamepad) { diff --git a/src/components/serverNotifications/serverNotifications.js b/src/components/serverNotifications/serverNotifications.js index 74c65cd473..ff571b1e1a 100644 --- a/src/components/serverNotifications/serverNotifications.js +++ b/src/components/serverNotifications/serverNotifications.js @@ -18,8 +18,7 @@ define(['connectionManager', 'playbackManager', 'events', 'inputManager', 'focus toast({ title: args.Header, text: args.Text }); }); - } - else { + } else { require(['alert'], function (alert) { alert({ title: args.Header, text: args.Text }); }); @@ -157,11 +156,9 @@ define(['connectionManager', 'playbackManager', 'events', 'inputManager', 'focus if (msg.Data.PlayCommand === "PlayNext") { playbackManager.queueNext({ ids: msg.Data.ItemIds, serverId: serverId }); - } - else if (msg.Data.PlayCommand === "PlayLast") { + } else if (msg.Data.PlayCommand === "PlayLast") { playbackManager.queue({ ids: msg.Data.ItemIds, serverId: serverId }); - } - else { + } else { playbackManager.play({ ids: msg.Data.ItemIds, startPositionTicks: msg.Data.StartPositionTicks, @@ -173,38 +170,29 @@ define(['connectionManager', 'playbackManager', 'events', 'inputManager', 'focus }); } - } - else if (msg.MessageType === "Playstate") { + } else if (msg.MessageType === "Playstate") { if (msg.Data.Command === 'Stop') { inputManager.trigger('stop'); - } - else if (msg.Data.Command === 'Pause') { + } else if (msg.Data.Command === 'Pause') { inputManager.trigger('pause'); - } - else if (msg.Data.Command === 'Unpause') { + } else if (msg.Data.Command === 'Unpause') { inputManager.trigger('play'); - } - else if (msg.Data.Command === 'PlayPause') { + } else if (msg.Data.Command === 'PlayPause') { inputManager.trigger('playpause'); - } - else if (msg.Data.Command === 'Seek') { + } else if (msg.Data.Command === 'Seek') { playbackManager.seek(msg.Data.SeekPositionTicks); - } - else if (msg.Data.Command === 'NextTrack') { + } else if (msg.Data.Command === 'NextTrack') { inputManager.trigger('next'); - } - else if (msg.Data.Command === 'PreviousTrack') { + } else if (msg.Data.Command === 'PreviousTrack') { inputManager.trigger('previous'); } else { notifyApp(); } - } - else if (msg.MessageType === "GeneralCommand") { + } else if (msg.MessageType === "GeneralCommand") { var cmd = msg.Data; processGeneralCommand(cmd, apiClient); - } - else if (msg.MessageType === "UserDataChanged") { + } else if (msg.MessageType === "UserDataChanged") { if (msg.Data.UserId === apiClient.getCurrentUserId()) { @@ -212,8 +200,7 @@ define(['connectionManager', 'playbackManager', 'events', 'inputManager', 'focus events.trigger(serverNotifications, 'UserDataChanged', [apiClient, msg.Data.UserDataList[i]]); } } - } - else { + } else { events.trigger(serverNotifications, msg.MessageType, [apiClient, msg.Data]); } diff --git a/src/components/serverRestartDialog.js b/src/components/serverRestartDialog.js index 6c7e5b7386..4c20183b2a 100644 --- a/src/components/serverRestartDialog.js +++ b/src/components/serverRestartDialog.js @@ -6,9 +6,7 @@ define(['loading', 'events', 'dialogHelper', 'dom', 'layoutManager', 'scrollHelp var currentInstance; function reloadPageWhenServerAvailable(retryCount) { - var apiClient = currentApiClient; - if (!apiClient) { return; } @@ -31,7 +29,6 @@ define(['loading', 'events', 'dialogHelper', 'dom', 'layoutManager', 'scrollHelp function retryReload(retryCount) { setTimeout(function () { - retryCount = retryCount || 0; retryCount++; @@ -42,15 +39,12 @@ define(['loading', 'events', 'dialogHelper', 'dom', 'layoutManager', 'scrollHelp } function startRestart(instance, apiClient, dlg) { - currentApiClient = apiClient; currentDlg = dlg; currentInstance = instance; apiClient.restartServer().then(function () { - setTimeout(reloadPageWhenServerAvailable, 250); - }); } @@ -94,7 +88,8 @@ define(['loading', 'events', 'dialogHelper', 'dom', 'layoutManager', 'scrollHelp dlg.querySelector('.text').innerHTML = globalize.translate('RestartPleaseWaitMessage'); - var i, length; + var i; + var length; var html = ''; for (i = 0, length = configuredButtons.length; i < length; i++) { var item = configuredButtons[i]; @@ -138,12 +133,10 @@ define(['loading', 'events', 'dialogHelper', 'dom', 'layoutManager', 'scrollHelp } function ServerRestartDialog(options) { - this.options = options; } ServerRestartDialog.prototype.show = function () { - var instance = this; loading.show(); @@ -155,7 +148,6 @@ define(['loading', 'events', 'dialogHelper', 'dom', 'layoutManager', 'scrollHelp }; ServerRestartDialog.prototype.destroy = function () { - currentApiClient = null; currentDlg = null; currentInstance = null; diff --git a/src/components/shell.js b/src/components/shell.js index 762039ac42..534a57b027 100644 --- a/src/components/shell.js +++ b/src/components/shell.js @@ -8,7 +8,7 @@ define([], function () { } else { window.open(url, target || '_blank'); } - + }, canExec: false, exec: function (options) { diff --git a/src/components/shortcuts.js b/src/components/shortcuts.js index f6c1e97893..9d2b1847e5 100644 --- a/src/components/shortcuts.js +++ b/src/components/shortcuts.js @@ -128,8 +128,7 @@ define(['playbackManager', 'inputManager', 'connectionManager', 'appRouter', 'gl if (result.command === 'playallfromhere' || result.command === 'queueallfromhere') { executeAction(card, options.positionTo, result.command); - } - else if (result.updated || result.deleted) { + } else if (result.updated || result.deleted) { notifyRefreshNeeded(card, options.itemsContainer); } }); @@ -204,21 +203,15 @@ define(['playbackManager', 'inputManager', 'connectionManager', 'appRouter', 'gl context: card.getAttribute('data-context'), parentId: card.getAttribute('data-parentid') }); - } - - else if (action === 'programdialog') { + } else if (action === 'programdialog') { showProgramDialog(item); - } - - else if (action === 'instantmix') { + } else if (action === 'instantmix') { playbackManager.instantMix({ Id: playableItemId, ServerId: serverId }); - } - - else if (action === 'play' || action === 'resume') { + } else if (action === 'play' || action === 'resume') { var startPositionTicks = parseInt(card.getAttribute('data-positionticks') || '0'); @@ -227,9 +220,7 @@ define(['playbackManager', 'inputManager', 'connectionManager', 'appRouter', 'gl startPositionTicks: startPositionTicks, serverId: serverId }); - } - - else if (action === 'queue') { + } else if (action === 'queue') { if (playbackManager.isPlaying()) { playbackManager.queue({ @@ -243,25 +234,15 @@ define(['playbackManager', 'inputManager', 'connectionManager', 'appRouter', 'gl serverId: serverId }); } - } - - else if (action === 'playallfromhere') { + } else if (action === 'playallfromhere') { playAllFromHere(card, serverId); - } - - else if (action === 'queueallfromhere') { + } else if (action === 'queueallfromhere') { playAllFromHere(card, serverId, true); - } - - else if (action === 'setplaylistindex') { + } else if (action === 'setplaylistindex') { playbackManager.setCurrentPlaylistItem(card.getAttribute('data-playlistitemid')); - } - - else if (action === 'record') { + } else if (action === 'record') { onRecordCommand(serverId, id, type, card.getAttribute('data-timerid'), card.getAttribute('data-seriestimerid')); - } - - else if (action === 'menu') { + } else if (action === 'menu') { var options = target.getAttribute('data-playoptions') === 'false' ? { @@ -277,27 +258,17 @@ define(['playbackManager', 'inputManager', 'connectionManager', 'appRouter', 'gl options.positionTo = target; showContextMenu(card, options); - } - - else if (action === 'playmenu') { + } else if (action === 'playmenu') { showPlayMenu(card, target); - } - - else if (action === 'edit') { + } else if (action === 'edit') { getItem(target).then(function (item) { editItem(item, serverId); }); - } - - else if (action === 'playtrailer') { + } else if (action === 'playtrailer') { getItem(target).then(playTrailer); - } - - else if (action === 'addtoplaylist') { + } else if (action === 'addtoplaylist') { getItem(target).then(addToPlaylist); - } - - else if (action === 'custom') { + } else if (action === 'custom') { var customAction = target.getAttribute('data-customaction'); diff --git a/src/components/skinManager.js b/src/components/skinManager.js index 780b8273bb..9f96516422 100644 --- a/src/components/skinManager.js +++ b/src/components/skinManager.js @@ -20,7 +20,7 @@ define(['apphost', 'userSettings', 'browser', 'events', 'pluginManager', 'backdr } else { Emby.Page.goHome(); } - }; + } function getThemes() { return [{ @@ -36,7 +36,7 @@ define(['apphost', 'userSettings', 'browser', 'events', 'pluginManager', 'backdr isDefaultServerDashboard: true }, { name: "Emby", - id: "emby", + id: "emby" }, { name: "Light", id: "light" @@ -47,7 +47,7 @@ define(['apphost', 'userSettings', 'browser', 'events', 'pluginManager', 'backdr name: "Windows Media Center", id: "wmc" }]; - }; + } var skinManager = { getThemes: getThemes, diff --git a/src/components/slideshow/slideshow.js b/src/components/slideshow/slideshow.js index 6bb485a616..a5acd042b3 100644 --- a/src/components/slideshow/slideshow.js +++ b/src/components/slideshow/slideshow.js @@ -77,8 +77,7 @@ define(['dialogHelper', 'inputManager', 'connectionManager', 'layoutManager', 'f try { appHost.setUserScalable(scalable); - } - catch (err) { + } catch (err) { console.log('error in appHost.setUserScalable: ' + err); } } diff --git a/src/components/subtitleeditor/subtitleeditor.js b/src/components/subtitleeditor/subtitleeditor.js index 27055f5976..b79bf4ba1a 100644 --- a/src/components/subtitleeditor/subtitleeditor.js +++ b/src/components/subtitleeditor/subtitleeditor.js @@ -192,8 +192,7 @@ define(['dialogHelper', 'require', 'layoutManager', 'globalize', 'userSettings', var lastLanguage = userSettings.get('subtitleeditor-language'); if (lastLanguage) { selectLanguage.value = lastLanguage; - } - else { + } else { apiClient.getCurrentUser().then(function (user) { @@ -347,8 +346,7 @@ define(['dialogHelper', 'require', 'layoutManager', 'globalize', 'userSettings', if (typeof itemId === 'string') { apiClient.getItem(apiClient.getCurrentUserId(), itemId).then(onGetItem); - } - else { + } else { onGetItem(itemId); } } diff --git a/src/components/subtitlesettings/subtitleappearancehelper.js b/src/components/subtitlesettings/subtitleappearancehelper.js index 588f491a67..8a40bd134b 100644 --- a/src/components/subtitlesettings/subtitleappearancehelper.js +++ b/src/components/subtitlesettings/subtitleappearancehelper.js @@ -33,7 +33,7 @@ define([], function () { case 'smaller': list.push({ name: 'font-size', value: '.8em' }); break; - case 'small': + case 'small': list.push({ name: 'font-size', value: 'inherit' }); break; case 'larger': @@ -132,7 +132,6 @@ define([], function () { function applyStyleList(styles, elem) { - for (var i = 0, length = styles.length; i < length; i++) { var style = styles[i]; diff --git a/src/components/subtitlesync/subtitlesync.js b/src/components/subtitlesync/subtitlesync.js index 3389b7bf89..904c612317 100644 --- a/src/components/subtitlesync/subtitlesync.js +++ b/src/components/subtitlesync/subtitlesync.js @@ -25,10 +25,10 @@ define(['playbackManager', 'text!./subtitlesync.template.html', 'css!./subtitles subtitleSyncTextField.addEventListener("keypress", function(event) { - if(event.key === "Enter"){ + if (event.key === "Enter") { // if input key is enter search for float pattern var inputOffset = /[-+]?\d+\.?\d*/g.exec(this.textContent); - if(inputOffset) { + if (inputOffset) { inputOffset = inputOffset[0]; // replace current text by considered offset @@ -48,7 +48,7 @@ define(['playbackManager', 'text!./subtitlesync.template.html', 'css!./subtitles } else { // keep focus to prevent fade with bottom layout this.hasFocus = true; - if(event.key.match(/[+-\d.s]/) === null) { + if (event.key.match(/[+-\d.s]/) === null) { event.preventDefault(); } } @@ -92,14 +92,13 @@ define(['playbackManager', 'text!./subtitlesync.template.html', 'css!./subtitles instance.element = parent; } - function getOffsetFromPercentage(value) { // convert percent to fraction var offset = (value - 50) / 50; // multiply by offset min/max range value (-x to +x) : offset *= 30; return offset.toFixed(1); - }; + } function getPercentageFromOffset(value) { // divide by offset min/max range value (-x to +x) : @@ -108,16 +107,16 @@ define(['playbackManager', 'text!./subtitlesync.template.html', 'css!./subtitles percentValue *= 50; percentValue += 50; return Math.min(100, Math.max(0, percentValue.toFixed())); - }; + } function SubtitleSync(currentPlayer) { player = currentPlayer; init(this); } - SubtitleSync.prototype.destroy = function(){ + SubtitleSync.prototype.destroy = function() { SubtitleSync.prototype.toggle("forceToHide"); - if(player){ + if (player) { playbackManager.disableShowingSubtitleOffset(player); playbackManager.setSubtitleOffset(0, player); } @@ -130,27 +129,30 @@ define(['playbackManager', 'text!./subtitlesync.template.html', 'css!./subtitles SubtitleSync.prototype.toggle = function(action) { - if(player && playbackManager.supportSubtitleOffset(player)){ + if (player && playbackManager.supportSubtitleOffset(player)) { - switch(action) { + switch (action) { case undefined: // if showing subtitle sync is enabled - if(playbackManager.isShowingSubtitleOffsetEnabled(player) && + if (playbackManager.isShowingSubtitleOffsetEnabled(player) && // if there is an external subtitle stream enabled - playbackManager.canHandleOffsetOnCurrentSubtitle(player)){ - // if no subtitle offset is defined - if(!playbackManager.getPlayerSubtitleOffset(player)) { - // set default offset to '0' = 50% - subtitleSyncSlider.value = "50"; - subtitleSyncTextField.textContent = "0s"; - playbackManager.setSubtitleOffset(0, player); - } - // show subtitle sync - subtitleSyncContainer.classList.remove("hide"); - break; // stop here + playbackManager.canHandleOffsetOnCurrentSubtitle(player)) { + // if no subtitle offset is defined + if (!playbackManager.getPlayerSubtitleOffset(player)) { + // set default offset to '0' = 50% + subtitleSyncSlider.value = "50"; + subtitleSyncTextField.textContent = "0s"; + playbackManager.setSubtitleOffset(0, player); + } + // show subtitle sync + subtitleSyncContainer.classList.remove("hide"); + break; // stop here } // else continue and hide case "hide": - if(subtitleSyncTextField.hasFocus){break;} // else continue and hide + // only break if element has focus + if (subtitleSyncTextField.hasFocus) { + break; + } case "forceToHide": subtitleSyncContainer.classList.add("hide"); break; diff --git a/src/components/tabbedview/itemstab.js b/src/components/tabbedview/itemstab.js index ec874c69e9..7381232fc9 100644 --- a/src/components/tabbedview/itemstab.js +++ b/src/components/tabbedview/itemstab.js @@ -246,7 +246,8 @@ define(['playbackManager', 'userSettings', 'alphaPicker', 'alphaNumericShortcuts this.itemsContainer.setAttribute('data-parentid', params.parentId); } - var i, length; + var i; + var length; var btnViewSettings = view.querySelectorAll('.btnViewSettings'); for (i = 0, length = btnViewSettings.length; i < length; i++) { @@ -559,7 +560,6 @@ define(['playbackManager', 'userSettings', 'alphaPicker', 'alphaNumericShortcuts }; ItemsTab.prototype.onPause = function () { - var scroller = this.scroller; if (scroller && scroller.pause) { scroller.pause(); @@ -573,7 +573,6 @@ define(['playbackManager', 'userSettings', 'alphaPicker', 'alphaNumericShortcuts }; ItemsTab.prototype.destroy = function () { - this.view = null; this.itemsContainer = null; this.params = null; @@ -585,6 +584,7 @@ define(['playbackManager', 'userSettings', 'alphaPicker', 'alphaNumericShortcuts this.alphaPicker.destroy(); this.alphaPicker = null; } + this.sortButtons = null; this.btnSortText = null; this.btnSortIcon = null; diff --git a/src/components/tabbedview/tabbedview.js b/src/components/tabbedview/tabbedview.js index bc656bc3e2..33f1c6e6cc 100644 --- a/src/components/tabbedview/tabbedview.js +++ b/src/components/tabbedview/tabbedview.js @@ -101,8 +101,7 @@ define(['backdrop', 'mainTabsManager', 'layoutManager', 'emby-tabs'], function ( if (!currentTabController) { mainTabsManager.selectedTabIndex(this.initialTabIndex); - } - else if (currentTabController && currentTabController.onResume) { + } else if (currentTabController && currentTabController.onResume) { currentTabController.onResume({}); } }; diff --git a/src/components/thememediaplayer.js b/src/components/thememediaplayer.js index 732cbb1cb0..a8298fad37 100644 --- a/src/components/thememediaplayer.js +++ b/src/components/thememediaplayer.js @@ -94,8 +94,7 @@ define(['playbackManager', 'userSettings', 'connectionManager'], function (playb if (viewOptions.supportsThemeMedia) { // Do nothing here, allow it to keep playing - } - else { + } else { playThemeMedia([], null); } diff --git a/src/components/touchhelper.js b/src/components/touchhelper.js index 66d115046b..0f6d34aace 100644 --- a/src/components/touchhelper.js +++ b/src/components/touchhelper.js @@ -78,11 +78,9 @@ define(['dom', 'events'], function (dom, events) { if (deltaX > swipeXThreshold && Math.abs(deltaY) < swipeXMaxY) { events.trigger(self, 'swiperight', [touchTarget]); - } - else if (deltaX < (0 - swipeXThreshold) && Math.abs(deltaY) < swipeXMaxY) { + } else if (deltaX < (0 - swipeXThreshold) && Math.abs(deltaY) < swipeXMaxY) { events.trigger(self, 'swipeleft', [touchTarget]); - } - else if ((deltaY < (0 - swipeYThreshold) || thresholdYMet) && Math.abs(deltaX) < swipeXMaxY) { + } else if ((deltaY < (0 - swipeYThreshold) || thresholdYMet) && Math.abs(deltaX) < swipeXMaxY) { thresholdYMet = true; @@ -94,8 +92,7 @@ define(['dom', 'events'], function (dom, events) { currentDeltaX: currentDeltaX, currentDeltaY: currentDeltaY }]); - } - else if ((deltaY > swipeYThreshold || thresholdYMet) && Math.abs(deltaX) < swipeXMaxY) { + } else if ((deltaY > swipeYThreshold || thresholdYMet) && Math.abs(deltaX) < swipeXMaxY) { thresholdYMet = true; events.trigger(self, 'swipedown', [touchTarget, { diff --git a/src/components/userdatabuttons/emby-ratingbutton.js b/src/components/userdatabuttons/emby-ratingbutton.js index 40cf033cd5..190424d44d 100644 --- a/src/components/userdatabuttons/emby-ratingbutton.js +++ b/src/components/userdatabuttons/emby-ratingbutton.js @@ -33,8 +33,7 @@ define(['connectionManager', 'serverNotifications', 'events', 'globalize', 'emby var isFavorite = this.getAttribute('data-isfavorite') === 'true'; if (likes === 'true') { likes = true; - } - else if (likes === 'false') { + } else if (likes === 'false') { likes = false; } else { likes = null; @@ -64,7 +63,7 @@ define(['connectionManager', 'serverNotifications', 'events', 'globalize', 'emby if (icon) { icon.innerHTML = ''; - icon.classList.add('ratingbutton-icon-withrating'); + icon.classList.add('ratingbutton-icon-withrating'); } button.classList.add('ratingbutton-withrating'); @@ -73,7 +72,7 @@ define(['connectionManager', 'serverNotifications', 'events', 'globalize', 'emby if (icon) { icon.innerHTML = ''; - icon.classList.remove('ratingbutton-icon-withrating'); + icon.classList.remove('ratingbutton-icon-withrating'); //icon.innerHTML = ''; } button.classList.remove('ratingbutton-withrating'); @@ -82,7 +81,7 @@ define(['connectionManager', 'serverNotifications', 'events', 'globalize', 'emby if (icon) { icon.innerHTML = ''; - icon.classList.remove('ratingbutton-icon-withrating'); + icon.classList.remove('ratingbutton-icon-withrating'); //icon.innerHTML = ''; } button.classList.remove('ratingbutton-withrating'); @@ -91,7 +90,7 @@ define(['connectionManager', 'serverNotifications', 'events', 'globalize', 'emby if (icon) { icon.innerHTML = ''; - icon.classList.remove('ratingbutton-icon-withrating'); + icon.classList.remove('ratingbutton-icon-withrating'); //icon.innerHTML = ''; } button.classList.remove('ratingbutton-withrating'); @@ -152,8 +151,7 @@ define(['connectionManager', 'serverNotifications', 'events', 'globalize', 'emby var isFavorite = this.getAttribute('data-isfavorite') === 'true'; if (likes === 'true') { likes = true; - } - else if (likes === 'false') { + } else if (likes === 'false') { likes = false; } else { likes = null; diff --git a/src/components/viewContainer.js b/src/components/viewContainer.js index ece8da1ed6..c2d060162e 100644 --- a/src/components/viewContainer.js +++ b/src/components/viewContainer.js @@ -42,7 +42,6 @@ define(["browser", "dom", "layoutManager", "css!components/viewManager/viewConta var newViewInfo = normalizeNewView(options, isPluginpage); var newView = newViewInfo.elem; - if (isPluginpage) { require(["legacyDashboard"]); } diff --git a/src/components/viewManager/viewManager.js b/src/components/viewManager/viewManager.js index 23612d5a1e..a8e514e06e 100644 --- a/src/components/viewManager/viewManager.js +++ b/src/components/viewManager/viewManager.js @@ -50,8 +50,7 @@ define(['viewContainer', 'focusManager', 'queryString', 'layoutManager'], functi if (options.autoFocus !== false) { focusManager.autoFocus(view); } - } - else if (!layoutManager.mobile) { + } else if (!layoutManager.mobile) { if (view.activeElement && document.body.contains(view.activeElement) && focusManager.isCurrentlyFocusable(view.activeElement)) { focusManager.focus(view.activeElement); } else { diff --git a/src/components/viewsettings/viewsettings.js b/src/components/viewsettings/viewsettings.js index 617e021115..5195598d99 100644 --- a/src/components/viewsettings/viewsettings.js +++ b/src/components/viewsettings/viewsettings.js @@ -29,7 +29,7 @@ define(['require', 'dialogHelper', 'loading', 'apphost', 'layoutManager', 'conne } userSettings.set(settingsKey + '-imageType', context.querySelector('.selectImageType').value); - } + } function centerFocus(elem, horiz, on) { require(['scrollHelper'], function (scrollHelper) { diff --git a/src/components/visibleinviewport.js b/src/components/visibleinviewport.js index 23a2a9d73c..3768740175 100644 --- a/src/components/visibleinviewport.js +++ b/src/components/visibleinviewport.js @@ -22,17 +22,17 @@ define(['dom'], function (dom) { var windowSize = dom.getWindowSize(); - var vpWidth = windowSize.innerWidth, - vpHeight = windowSize.innerHeight; + var vpWidth = windowSize.innerWidth; + var vpHeight = windowSize.innerHeight; // Use this native browser method, if available. - var rec = elem.getBoundingClientRect(), - tViz = rec.top >= 0 && rec.top < vpHeight + thresholdY, - bViz = rec.bottom > 0 && rec.bottom <= vpHeight + thresholdY, - lViz = rec.left >= 0 && rec.left < vpWidth + thresholdX, - rViz = rec.right > 0 && rec.right <= vpWidth + thresholdX, - vVisible = partial ? tViz || bViz : tViz && bViz, - hVisible = partial ? lViz || rViz : lViz && rViz; + var rec = elem.getBoundingClientRect(); + var tViz = rec.top >= 0 && rec.top < vpHeight + thresholdY; + var bViz = rec.bottom > 0 && rec.bottom <= vpHeight + thresholdY; + var lViz = rec.left >= 0 && rec.left < vpWidth + thresholdX; + var rViz = rec.right > 0 && rec.right <= vpWidth + thresholdX; + var vVisible = partial ? tViz || bViz : tViz && bViz; + var hVisible = partial ? lViz || rViz : lViz && rViz; return vVisible && hVisible; } diff --git a/src/components/youtubeplayer/plugin.js b/src/components/youtubeplayer/plugin.js index 1ed95e2110..a2478cd3f4 100644 --- a/src/components/youtubeplayer/plugin.js +++ b/src/components/youtubeplayer/plugin.js @@ -135,7 +135,6 @@ define(['require', 'events', 'browser', 'appRouter', 'loading'], function (requi require(['queryString'], function (queryString) { - instance._currentSrc = options.url; var params = queryString.parse(options.url.split('?')[1]); // 3. This function creates an