diff --git a/BDInfo/BDInfo.csproj b/BDInfo/BDInfo.csproj
index 8c0404c4de..a8f5060e69 100644
--- a/BDInfo/BDInfo.csproj
+++ b/BDInfo/BDInfo.csproj
@@ -34,10 +34,10 @@
- ..\packages\MediaBrowser.Common.3.3.50-beta\lib\netstandard2.0\MediaBrowser.Common.dll
+ ..\packages\MediaBrowser.Common.3.3.53-beta\lib\netstandard2.0\MediaBrowser.Common.dll
- ..\packages\MediaBrowser.Common.3.3.50-beta\lib\netstandard2.0\MediaBrowser.Model.dll
+ ..\packages\MediaBrowser.Common.3.3.53-beta\lib\netstandard2.0\MediaBrowser.Model.dll
diff --git a/BDInfo/packages.config b/BDInfo/packages.config
index 76aa4bb8c7..85e552f7ee 100644
--- a/BDInfo/packages.config
+++ b/BDInfo/packages.config
@@ -1,4 +1,4 @@
-
+
\ No newline at end of file
diff --git a/DvdLib/DvdLib.csproj b/DvdLib/DvdLib.csproj
index 91fb09c058..ea1b43767a 100644
--- a/DvdLib/DvdLib.csproj
+++ b/DvdLib/DvdLib.csproj
@@ -49,10 +49,10 @@
- ..\packages\MediaBrowser.Common.3.3.50-beta\lib\netstandard2.0\MediaBrowser.Common.dll
+ ..\packages\MediaBrowser.Common.3.3.53-beta\lib\netstandard2.0\MediaBrowser.Common.dll
- ..\packages\MediaBrowser.Common.3.3.50-beta\lib\netstandard2.0\MediaBrowser.Model.dll
+ ..\packages\MediaBrowser.Common.3.3.53-beta\lib\netstandard2.0\MediaBrowser.Model.dll
diff --git a/DvdLib/packages.config b/DvdLib/packages.config
index 76aa4bb8c7..85e552f7ee 100644
--- a/DvdLib/packages.config
+++ b/DvdLib/packages.config
@@ -1,4 +1,4 @@
-
+
\ No newline at end of file
diff --git a/Emby.Dlna/Emby.Dlna.csproj b/Emby.Dlna/Emby.Dlna.csproj
index 3bac21a93b..33d2c31aad 100644
--- a/Emby.Dlna/Emby.Dlna.csproj
+++ b/Emby.Dlna/Emby.Dlna.csproj
@@ -174,19 +174,19 @@
- ..\packages\MediaBrowser.Common.3.3.50-beta\lib\netstandard2.0\MediaBrowser.Common.dll
+ ..\packages\MediaBrowser.Common.3.3.53-beta\lib\netstandard2.0\MediaBrowser.Common.dll
- ..\packages\MediaBrowser.Server.Core.3.3.50-beta\lib\netstandard2.0\MediaBrowser.Controller.dll
+ ..\packages\MediaBrowser.Server.Core.3.3.53-beta\lib\netstandard2.0\MediaBrowser.Controller.dll
- ..\packages\MediaBrowser.Common.3.3.50-beta\lib\netstandard2.0\MediaBrowser.Model.dll
+ ..\packages\MediaBrowser.Common.3.3.53-beta\lib\netstandard2.0\MediaBrowser.Model.dll
- ..\packages\System.Runtime.CompilerServices.Unsafe.4.5.0\lib\netstandard2.0\System.Runtime.CompilerServices.Unsafe.dll
+ ..\packages\System.Runtime.CompilerServices.Unsafe.4.5.1\lib\netstandard2.0\System.Runtime.CompilerServices.Unsafe.dll
diff --git a/Emby.Dlna/packages.config b/Emby.Dlna/packages.config
index d7821eae0f..b5355baf69 100644
--- a/Emby.Dlna/packages.config
+++ b/Emby.Dlna/packages.config
@@ -1,6 +1,6 @@
-
-
-
+
+
+
\ No newline at end of file
diff --git a/Emby.Drawing.ImageMagick/Emby.Drawing.ImageMagick.csproj b/Emby.Drawing.ImageMagick/Emby.Drawing.ImageMagick.csproj
index f674e9945a..3e0583e5bb 100644
--- a/Emby.Drawing.ImageMagick/Emby.Drawing.ImageMagick.csproj
+++ b/Emby.Drawing.ImageMagick/Emby.Drawing.ImageMagick.csproj
@@ -35,13 +35,13 @@
..\packages\ImageMagickSharp.1.0.0.19\lib\net45\ImageMagickSharp.dll
- ..\packages\MediaBrowser.Common.3.3.50-beta\lib\netstandard2.0\MediaBrowser.Common.dll
+ ..\packages\MediaBrowser.Common.3.3.53-beta\lib\netstandard2.0\MediaBrowser.Common.dll
- ..\packages\MediaBrowser.Server.Core.3.3.50-beta\lib\netstandard2.0\MediaBrowser.Controller.dll
+ ..\packages\MediaBrowser.Server.Core.3.3.53-beta\lib\netstandard2.0\MediaBrowser.Controller.dll
- ..\packages\MediaBrowser.Common.3.3.50-beta\lib\netstandard2.0\MediaBrowser.Model.dll
+ ..\packages\MediaBrowser.Common.3.3.53-beta\lib\netstandard2.0\MediaBrowser.Model.dll
diff --git a/Emby.Drawing.ImageMagick/packages.config b/Emby.Drawing.ImageMagick/packages.config
index 57284567b2..46dca35426 100644
--- a/Emby.Drawing.ImageMagick/packages.config
+++ b/Emby.Drawing.ImageMagick/packages.config
@@ -1,6 +1,6 @@
-
-
+
+
\ No newline at end of file
diff --git a/Emby.Drawing.Skia/Emby.Drawing.Skia.csproj b/Emby.Drawing.Skia/Emby.Drawing.Skia.csproj
index 9af5d94331..864e8f1844 100644
--- a/Emby.Drawing.Skia/Emby.Drawing.Skia.csproj
+++ b/Emby.Drawing.Skia/Emby.Drawing.Skia.csproj
@@ -43,13 +43,13 @@
- ..\packages\MediaBrowser.Common.3.3.50-beta\lib\netstandard2.0\MediaBrowser.Common.dll
+ ..\packages\MediaBrowser.Common.3.3.53-beta\lib\netstandard2.0\MediaBrowser.Common.dll
- ..\packages\MediaBrowser.Server.Core.3.3.50-beta\lib\netstandard2.0\MediaBrowser.Controller.dll
+ ..\packages\MediaBrowser.Server.Core.3.3.53-beta\lib\netstandard2.0\MediaBrowser.Controller.dll
- ..\packages\MediaBrowser.Common.3.3.50-beta\lib\netstandard2.0\MediaBrowser.Model.dll
+ ..\packages\MediaBrowser.Common.3.3.53-beta\lib\netstandard2.0\MediaBrowser.Model.dll
diff --git a/Emby.Drawing.Skia/packages.config b/Emby.Drawing.Skia/packages.config
index 272298aec8..9756e911d7 100644
--- a/Emby.Drawing.Skia/packages.config
+++ b/Emby.Drawing.Skia/packages.config
@@ -1,6 +1,6 @@
-
-
+
+
\ No newline at end of file
diff --git a/Emby.Drawing/Emby.Drawing.csproj b/Emby.Drawing/Emby.Drawing.csproj
index 4b5d7dde4f..725e8d28c8 100644
--- a/Emby.Drawing/Emby.Drawing.csproj
+++ b/Emby.Drawing/Emby.Drawing.csproj
@@ -41,13 +41,13 @@
- ..\packages\MediaBrowser.Common.3.3.50-beta\lib\netstandard2.0\MediaBrowser.Common.dll
+ ..\packages\MediaBrowser.Common.3.3.53-beta\lib\netstandard2.0\MediaBrowser.Common.dll
- ..\packages\MediaBrowser.Server.Core.3.3.50-beta\lib\netstandard2.0\MediaBrowser.Controller.dll
+ ..\packages\MediaBrowser.Server.Core.3.3.53-beta\lib\netstandard2.0\MediaBrowser.Controller.dll
- ..\packages\MediaBrowser.Common.3.3.50-beta\lib\netstandard2.0\MediaBrowser.Model.dll
+ ..\packages\MediaBrowser.Common.3.3.53-beta\lib\netstandard2.0\MediaBrowser.Model.dll
diff --git a/Emby.Drawing/packages.config b/Emby.Drawing/packages.config
index 1c4aaf7ddf..c26580a70a 100644
--- a/Emby.Drawing/packages.config
+++ b/Emby.Drawing/packages.config
@@ -1,5 +1,5 @@
-
-
+
+
\ No newline at end of file
diff --git a/Emby.Photos/Emby.Photos.csproj b/Emby.Photos/Emby.Photos.csproj
index 92201bfc37..05be07fa92 100644
--- a/Emby.Photos/Emby.Photos.csproj
+++ b/Emby.Photos/Emby.Photos.csproj
@@ -32,13 +32,13 @@
- ..\packages\MediaBrowser.Common.3.3.50-beta\lib\netstandard2.0\MediaBrowser.Common.dll
+ ..\packages\MediaBrowser.Common.3.3.53-beta\lib\netstandard2.0\MediaBrowser.Common.dll
- ..\packages\MediaBrowser.Server.Core.3.3.50-beta\lib\netstandard2.0\MediaBrowser.Controller.dll
+ ..\packages\MediaBrowser.Server.Core.3.3.53-beta\lib\netstandard2.0\MediaBrowser.Controller.dll
- ..\packages\MediaBrowser.Common.3.3.50-beta\lib\netstandard2.0\MediaBrowser.Model.dll
+ ..\packages\MediaBrowser.Common.3.3.53-beta\lib\netstandard2.0\MediaBrowser.Model.dll
..\ThirdParty\taglib\TagLib.Portable.dll
diff --git a/Emby.Photos/packages.config b/Emby.Photos/packages.config
index 1c4aaf7ddf..c26580a70a 100644
--- a/Emby.Photos/packages.config
+++ b/Emby.Photos/packages.config
@@ -1,5 +1,5 @@
-
-
+
+
\ No newline at end of file
diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs
index 8bd4a6e485..8cdcc9c6b5 100644
--- a/Emby.Server.Implementations/ApplicationHost.cs
+++ b/Emby.Server.Implementations/ApplicationHost.cs
@@ -1008,7 +1008,7 @@ protected void RegisterResources()
var deviceRepo = new SqliteDeviceRepository(LogManager.GetLogger("DeviceManager"), ServerConfigurationManager, FileSystemManager, JsonSerializer);
deviceRepo.Initialize();
- DeviceManager = new DeviceManager(deviceRepo, LibraryManager, LocalizationManager, UserManager, FileSystemManager, LibraryMonitor, ServerConfigurationManager, LogManager.GetLogger("DeviceManager"), NetworkManager);
+ DeviceManager = new DeviceManager(AuthenticationRepository, deviceRepo, LibraryManager, LocalizationManager, UserManager, FileSystemManager, LibraryMonitor, ServerConfigurationManager, LogManager.GetLogger("DeviceManager"), NetworkManager);
RegisterSingleInstance(deviceRepo);
RegisterSingleInstance(DeviceManager);
@@ -1065,7 +1065,7 @@ protected void RegisterResources()
RegisterSingleInstance(activityLogRepo);
RegisterSingleInstance(new ActivityManager(LogManager.GetLogger("ActivityManager"), activityLogRepo, UserManager));
- var authContext = new AuthorizationContext(AuthenticationRepository, ConnectManager);
+ var authContext = new AuthorizationContext(AuthenticationRepository, ConnectManager, UserManager);
RegisterSingleInstance(authContext);
RegisterSingleInstance(new SessionContext(UserManager, authContext, SessionManager));
@@ -1930,6 +1930,7 @@ private bool EnablePlugin(string path)
"mbintros.dll",
"embytv.dll",
"Messenger.dll",
+ "Messages.dll",
"MediaBrowser.Plugins.TvMazeProvider.dll",
"MBBookshelf.dll",
"MediaBrowser.Channels.Adult.YouJizz.dll",
diff --git a/Emby.Server.Implementations/Data/SqliteItemRepository.cs b/Emby.Server.Implementations/Data/SqliteItemRepository.cs
index 4164463bab..00e3e65fc0 100644
--- a/Emby.Server.Implementations/Data/SqliteItemRepository.cs
+++ b/Emby.Server.Implementations/Data/SqliteItemRepository.cs
@@ -221,7 +221,7 @@ var createMediaStreamsTableCommand
AddColumn(db, "TypedBaseItems", "ProviderIds", "Text", existingColumnNames);
AddColumn(db, "TypedBaseItems", "Images", "Text", existingColumnNames);
AddColumn(db, "TypedBaseItems", "ProductionLocations", "Text", existingColumnNames);
- AddColumn(db, "TypedBaseItems", "ThemeSongIds", "Text", existingColumnNames);
+ AddColumn(db, "TypedBaseItems", "ExtraIds", "Text", existingColumnNames);
AddColumn(db, "TypedBaseItems", "TotalBitrate", "INT", existingColumnNames);
AddColumn(db, "TypedBaseItems", "ExtraType", "Text", existingColumnNames);
AddColumn(db, "TypedBaseItems", "Artists", "Text", existingColumnNames);
@@ -404,7 +404,7 @@ var createMediaStreamsTableCommand
"ProviderIds",
"Images",
"ProductionLocations",
- "ThemeSongIds",
+ "ExtraIds",
"TotalBitrate",
"ExtraType",
"Artists",
@@ -522,7 +522,7 @@ private string GetSaveItemCommandText()
"ProviderIds",
"Images",
"ProductionLocations",
- "ThemeSongIds",
+ "ExtraIds",
"TotalBitrate",
"ExtraType",
"Artists",
@@ -1007,13 +1007,13 @@ private void SaveItem(BaseItem item, BaseItem topParent, string userDataKey, ISt
saveItemStatement.TryBindNull("@ProductionLocations");
}
- if (item.ThemeSongIds.Length > 0)
+ if (item.ExtraIds.Length > 0)
{
- saveItemStatement.TryBind("@ThemeSongIds", string.Join("|", item.ThemeSongIds.ToArray()));
+ saveItemStatement.TryBind("@ExtraIds", string.Join("|", item.ExtraIds.ToArray()));
}
else
{
- saveItemStatement.TryBindNull("@ThemeSongIds");
+ saveItemStatement.TryBindNull("@ExtraIds");
}
saveItemStatement.TryBind("@TotalBitrate", item.TotalBitrate);
@@ -1864,11 +1864,11 @@ private BaseItem GetItem(IReadOnlyList reader, InternalItemsQue
index++;
}
- if (HasField(query, ItemFields.ThemeSongIds))
+ if (HasField(query, ItemFields.ExtraIds))
{
if (!reader.IsDBNull(index))
{
- item.ThemeSongIds = SplitToGuids(reader.GetString(index));
+ item.ExtraIds = SplitToGuids(reader.GetString(index));
}
index++;
}
@@ -2230,7 +2230,7 @@ private bool HasField(InternalItemsQuery query, ItemFields name)
case ItemFields.Taglines:
case ItemFields.SortName:
case ItemFields.Studios:
- case ItemFields.ThemeSongIds:
+ case ItemFields.ExtraIds:
case ItemFields.DateCreated:
case ItemFields.Overview:
case ItemFields.Genres:
@@ -2534,11 +2534,7 @@ private string[] GetFinalColumnsToSelect(InternalItemsQuery query, string[] star
if (query.IncludeItemTypes.Length == 0 || query.IncludeItemTypes.Contains(typeof(Trailer).Name))
{
- var hasTrailers = item as IHasTrailers;
- if (hasTrailers != null)
- {
- excludeIds.AddRange(hasTrailers.GetTrailerIds());
- }
+ excludeIds.AddRange(item.ExtraIds);
}
query.ExcludeItemIds = excludeIds.ToArray(excludeIds.Count);
@@ -3436,12 +3432,42 @@ private List GetWhereClauses(InternalItemsQuery query, IStatement statem
{
//whereClauses.Add("(UserId is null or UserId=@UserId)");
}
- if (query.MinWidth.HasValue)
+
+ var minWidth = query.MinWidth;
+ var maxWidth = query.MaxWidth;
+
+ if (query.IsHD.HasValue)
+ {
+ var threshold = 1200;
+ if (query.IsHD.Value)
+ {
+ minWidth = threshold;
+ }
+ else
+ {
+ maxWidth = threshold - 1;
+ }
+ }
+
+ if (query.Is4K.HasValue)
+ {
+ var threshold = 3800;
+ if (query.Is4K.Value)
+ {
+ minWidth = threshold;
+ }
+ else
+ {
+ maxWidth = threshold - 1;
+ }
+ }
+
+ if (minWidth.HasValue)
{
whereClauses.Add("Width>=@MinWidth");
if (statement != null)
{
- statement.TryBind("@MinWidth", query.MinWidth);
+ statement.TryBind("@MinWidth", minWidth);
}
}
if (query.MinHeight.HasValue)
@@ -3452,12 +3478,12 @@ private List GetWhereClauses(InternalItemsQuery query, IStatement statem
statement.TryBind("@MinHeight", query.MinHeight);
}
}
- if (query.MaxWidth.HasValue)
+ if (maxWidth.HasValue)
{
whereClauses.Add("Width<=@MaxWidth");
if (statement != null)
{
- statement.TryBind("@MaxWidth", query.MaxWidth);
+ statement.TryBind("@MaxWidth", maxWidth);
}
}
if (query.MaxHeight.HasValue)
@@ -4079,6 +4105,25 @@ private List GetWhereClauses(InternalItemsQuery query, IStatement statem
whereClauses.Add(clause);
}
+ if (query.AlbumArtistIds.Length > 0)
+ {
+ var clauses = new List();
+ var index = 0;
+ foreach (var artistId in query.AlbumArtistIds)
+ {
+ var paramName = "@ArtistIds" + index;
+
+ clauses.Add("(select CleanName from TypedBaseItems where guid=" + paramName + ") in (select CleanValue from itemvalues where ItemId=Guid and Type=1)");
+ if (statement != null)
+ {
+ statement.TryBind(paramName, artistId.ToGuidBlob());
+ }
+ index++;
+ }
+ var clause = "(" + string.Join(" OR ", clauses.ToArray()) + ")";
+ whereClauses.Add(clause);
+ }
+
if (query.AlbumIds.Length > 0)
{
var clauses = new List();
@@ -4253,6 +4298,18 @@ private List GetWhereClauses(InternalItemsQuery query, IStatement statem
}
}
+ if (query.HasOfficialRating.HasValue)
+ {
+ if (query.HasOfficialRating.Value)
+ {
+ whereClauses.Add("(OfficialRating not null AND OfficialRating<>'')");
+ }
+ else
+ {
+ whereClauses.Add("(OfficialRating is null OR OfficialRating='')");
+ }
+ }
+
if (query.HasOverview.HasValue)
{
if (query.HasOverview.Value)
@@ -4265,6 +4322,18 @@ private List GetWhereClauses(InternalItemsQuery query, IStatement statem
}
}
+ if (query.HasOwnerId.HasValue)
+ {
+ if (query.HasOwnerId.Value)
+ {
+ whereClauses.Add("OwnerId not null");
+ }
+ else
+ {
+ whereClauses.Add("OwnerId is null");
+ }
+ }
+
if (!string.IsNullOrWhiteSpace(query.HasNoAudioTrackWithLanguage))
{
whereClauses.Add("((select language from MediaStreams where MediaStreams.ItemId=A.Guid and MediaStreams.StreamType='Audio' and MediaStreams.Language=@HasNoAudioTrackWithLanguage limit 1) is null)");
@@ -4301,6 +4370,18 @@ private List GetWhereClauses(InternalItemsQuery query, IStatement statem
}
}
+ if (query.HasSubtitles.HasValue)
+ {
+ if (query.HasSubtitles.Value)
+ {
+ whereClauses.Add("((select type from MediaStreams where MediaStreams.ItemId=A.Guid and MediaStreams.StreamType='Subtitle' limit 1) not null)");
+ }
+ else
+ {
+ whereClauses.Add("((select type from MediaStreams where MediaStreams.ItemId=A.Guid and MediaStreams.StreamType='Subtitle' limit 1) is null)");
+ }
+ }
+
if (query.HasChapterImages.HasValue)
{
if (query.HasChapterImages.Value)
@@ -4453,7 +4534,40 @@ private List GetWhereClauses(InternalItemsQuery query, IStatement statem
break;
}
- whereClauses.Add(string.Join(" AND ", excludeIds.ToArray()));
+ if (excludeIds.Count > 0)
+ {
+ whereClauses.Add(string.Join(" AND ", excludeIds.ToArray()));
+ }
+ }
+
+ if (query.HasAnyProviderId.Count > 0)
+ {
+ var hasProviderIds = new List();
+
+ var index = 0;
+ foreach (var pair in query.HasAnyProviderId)
+ {
+ if (string.Equals(pair.Key, MetadataProviders.TmdbCollection.ToString(), StringComparison.OrdinalIgnoreCase))
+ {
+ continue;
+ }
+
+ var paramName = "@HasAnyProviderId" + index;
+ //hasProviderIds.Add("(COALESCE((select value from ProviderIds where ItemId=Guid and Name = '" + pair.Key + "'), '') <> " + paramName + ")");
+ hasProviderIds.Add("ProviderIds like " + paramName + "");
+ if (statement != null)
+ {
+ statement.TryBind(paramName, "%" + pair.Key + "=" + pair.Value + "%");
+ }
+ index++;
+
+ break;
+ }
+
+ if (hasProviderIds.Count > 0)
+ {
+ whereClauses.Add("(" + string.Join(" OR ", hasProviderIds.ToArray()) + ")");
+ }
}
if (query.HasImdbId.HasValue)
@@ -4470,17 +4584,6 @@ private List GetWhereClauses(InternalItemsQuery query, IStatement statem
{
whereClauses.Add("ProviderIds like '%tvdb=%'");
}
- if (query.HasThemeSong.HasValue)
- {
- if (query.HasThemeSong.Value)
- {
- whereClauses.Add("ThemeSongIds not null");
- }
- else
- {
- whereClauses.Add("ThemeSongIds is null");
- }
- }
var includedItemByNameTypes = GetItemByNameTypesInQuery(query).SelectMany(MapIncludeItemTypes).ToList();
var enableItemsByName = (query.IncludeItemsByName ?? false) && includedItemByNameTypes.Count > 0;
@@ -4590,6 +4693,102 @@ private List GetWhereClauses(InternalItemsQuery query, IStatement statem
whereClauses.Add("((select CleanValue from itemvalues where ItemId=Guid and Type=6 and cleanvalue in (" + tagValuesList + ")) is null)");
}
+ if (query.SeriesStatuses.Length > 0)
+ {
+ var statuses = new List();
+
+ foreach (var seriesStatus in query.SeriesStatuses)
+ {
+ statuses.Add("data like '%" + seriesStatus + "%'");
+ }
+
+ whereClauses.Add("(" + string.Join(" OR ", statuses.ToArray()) + ")");
+ }
+
+ if (query.VideoTypes.Length > 0)
+ {
+ var videoTypes = new List();
+
+ foreach (var videoType in query.VideoTypes)
+ {
+ videoTypes.Add("data like '%" + videoType + "%'");
+ }
+
+ whereClauses.Add("(" + string.Join(" OR ", videoTypes.ToArray()) + ")");
+ }
+
+ if (query.Is3D.HasValue)
+ {
+ if (query.Is3D.Value)
+ {
+ whereClauses.Add("data like '%Video3DFormat%'");
+ }
+ else
+ {
+ whereClauses.Add("data not like '%Video3DFormat%'");
+ }
+ }
+
+ if (query.IsPlaceHolder.HasValue)
+ {
+ if (query.IsPlaceHolder.Value)
+ {
+ whereClauses.Add("data like '\"IsPlaceHolder\":true");
+ }
+ else
+ {
+ whereClauses.Add("data not like '\"IsPlaceHolder\":true");
+ }
+ }
+
+ if (query.HasSpecialFeature.HasValue)
+ {
+ if (query.HasSpecialFeature.Value)
+ {
+ whereClauses.Add("(data not like '%\"ExtraIds\":[]%' and data like '%ExtraIds%')");
+ }
+ else
+ {
+ whereClauses.Add("(data like '%\"ExtraIds\":[]%' or data not like '%ExtraIds%')");
+ }
+ }
+
+ if (query.HasTrailer.HasValue)
+ {
+ if (query.HasTrailer.Value)
+ {
+ whereClauses.Add("((data not like '%\"LocalTrailerIds\":[]%' and data like '%LocalTrailerIds%') or (data not like '%\"RemoteTrailerIds\":[]%' and data like '%RemoteTrailerIds%') or (data not like '%\"RemoteTrailers\":[]%' and data like '%RemoteTrailers%'))");
+ }
+ else
+ {
+ whereClauses.Add("((data like '%\"LocalTrailerIds\":[]%' or data not like '%LocalTrailerIds%') and (data like '%\"RemoteTrailerIds\":[]%' or data not like '%RemoteTrailerIds%') and (data like '%\"RemoteTrailers\":[]%' or data not like '%RemoteTrailers%'))");
+ }
+ }
+
+ if (query.HasThemeSong.HasValue)
+ {
+ if (query.HasThemeSong.Value)
+ {
+ whereClauses.Add("(data not like '%\"ExtraIds\":[]%' and data like '%ExtraIds%')");
+ }
+ else
+ {
+ whereClauses.Add("(data like '%\"ExtraIds\":[]%' or data not like '%ExtraIds%')");
+ }
+ }
+
+ if (query.HasThemeVideo.HasValue)
+ {
+ if (query.HasThemeVideo.Value)
+ {
+ whereClauses.Add("(data not like '%\"ExtraIds\":[]%' and data like '%ExtraIds%')");
+ }
+ else
+ {
+ whereClauses.Add("(data like '%\"ExtraIds\":[]%' or data not like '%ExtraIds%')");
+ }
+ }
+
return whereClauses;
}
diff --git a/Emby.Server.Implementations/Devices/DeviceManager.cs b/Emby.Server.Implementations/Devices/DeviceManager.cs
index 882ebc3b3a..93af05bdbb 100644
--- a/Emby.Server.Implementations/Devices/DeviceManager.cs
+++ b/Emby.Server.Implementations/Devices/DeviceManager.cs
@@ -23,6 +23,7 @@
using MediaBrowser.Model.Configuration;
using MediaBrowser.Controller.Plugins;
using MediaBrowser.Model.Globalization;
+using MediaBrowser.Controller.Security;
namespace Emby.Server.Implementations.Devices
{
@@ -38,14 +39,11 @@ public class DeviceManager : IDeviceManager
private readonly ILibraryManager _libraryManager;
private readonly ILocalizationManager _localizationManager;
- public event EventHandler> CameraImageUploaded;
+ private readonly IAuthenticationRepository _authRepo;
- ///
- /// Occurs when [device options updated].
- ///
- public event EventHandler> DeviceOptionsUpdated;
+ public event EventHandler> CameraImageUploaded;
- public DeviceManager(IDeviceRepository repo, ILibraryManager libraryManager, ILocalizationManager localizationManager, IUserManager userManager, IFileSystem fileSystem, ILibraryMonitor libraryMonitor, IServerConfigurationManager config, ILogger logger, INetworkManager network)
+ public DeviceManager(IAuthenticationRepository authRepo, IDeviceRepository repo, ILibraryManager libraryManager, ILocalizationManager localizationManager, IUserManager userManager, IFileSystem fileSystem, ILibraryMonitor libraryMonitor, IServerConfigurationManager config, ILogger logger, INetworkManager network)
{
_repo = repo;
_userManager = userManager;
@@ -56,68 +54,7 @@ public DeviceManager(IDeviceRepository repo, ILibraryManager libraryManager, ILo
_network = network;
_libraryManager = libraryManager;
_localizationManager = localizationManager;
- }
-
- public DeviceInfo RegisterDevice(string reportedId, string name, string appName, string appVersion, string usedByUserId, string usedByUserName)
- {
- if (string.IsNullOrEmpty(reportedId))
- {
- throw new ArgumentNullException("reportedId");
- }
-
- var save = false;
- var device = GetDevice(reportedId);
-
- if (device == null)
- {
- device = new DeviceInfo
- {
- Id = reportedId
- };
- save = true;
- }
-
- if (!string.Equals(device.ReportedName, name, StringComparison.Ordinal))
- {
- device.ReportedName = name;
- save = true;
- }
- if (!string.Equals(device.AppName, appName, StringComparison.Ordinal))
- {
- device.AppName = appName;
- save = true;
- }
- if (!string.Equals(device.AppVersion, appVersion, StringComparison.Ordinal))
- {
- device.AppVersion = appVersion;
- save = true;
- }
-
- if (!string.IsNullOrEmpty(usedByUserId))
- {
- if (!string.Equals(device.LastUserId, usedByUserId, StringComparison.Ordinal) ||
- !string.Equals(device.LastUserName, usedByUserName, StringComparison.Ordinal))
- {
- device.LastUserId = usedByUserId;
- device.LastUserName = usedByUserName;
- save = true;
- }
- }
-
- var displayName = string.IsNullOrWhiteSpace(device.CustomName) ? device.ReportedName : device.CustomName;
- if (!string.Equals(device.Name, displayName, StringComparison.Ordinal))
- {
- device.Name = displayName;
- save = true;
- }
-
- if (save)
- {
- device.DateLastModified = DateTime.UtcNow;
- _repo.SaveDevice(device);
- }
-
- return device;
+ _authRepo = authRepo;
}
public void SaveCapabilities(string reportedId, ClientCapabilities capabilities)
@@ -127,44 +64,53 @@ public void SaveCapabilities(string reportedId, ClientCapabilities capabilities)
public ClientCapabilities GetCapabilities(string reportedId)
{
- return _repo.GetCapabilities(reportedId);
+ return _repo.GetCapabilities(reportedId) ?? new ClientCapabilities();
}
public DeviceInfo GetDevice(string id)
{
- return _repo.GetDevice(id);
+ return GetDevice(id, true);
}
- public QueryResult GetDevices(DeviceQuery query)
+ private DeviceInfo GetDevice(string id, bool includeCapabilities)
{
- IEnumerable devices = _repo.GetDevices();
+ var session = _authRepo.Get(new AuthenticationInfoQuery
+ {
+ DeviceId = id
- if (query.SupportsSync.HasValue)
+ }).Items.FirstOrDefault();
+
+ var device = session == null ? null : ToDeviceInfo(session);
+
+ return device;
+ }
+
+ public QueryResult GetDevices(DeviceQuery query)
+ {
+ var sessions = _authRepo.Get(new AuthenticationInfoQuery
{
- var val = query.SupportsSync.Value;
+ //UserId = query.UserId
+ IsActive = true,
+ HasUser = true
- devices = devices.Where(i => i.Capabilities.SupportsSync == val);
- }
+ }).Items;
- if (query.SupportsPersistentIdentifier.HasValue)
+ if (query.SupportsSync.HasValue)
{
- var val = query.SupportsPersistentIdentifier.Value;
+ var val = query.SupportsSync.Value;
- devices = devices.Where(i =>
- {
- var deviceVal = i.Capabilities.SupportsPersistentIdentifier;
- return deviceVal == val;
- });
+ sessions = sessions.Where(i => GetCapabilities(i.DeviceId).SupportsSync == val).ToArray();
}
if (!query.UserId.Equals(Guid.Empty))
{
var user = _userManager.GetUserById(query.UserId);
- devices = devices.Where(i => CanAccessDevice(user, i.Id));
+ sessions = sessions.Where(i => CanAccessDevice(user, i.DeviceId)).ToArray();
}
- var array = devices.ToArray();
+ var array = sessions.Select(ToDeviceInfo).ToArray();
+
return new QueryResult
{
Items = array,
@@ -172,9 +118,18 @@ public QueryResult GetDevices(DeviceQuery query)
};
}
- public void DeleteDevice(string id)
+ private DeviceInfo ToDeviceInfo(AuthenticationInfo authInfo)
{
- _repo.DeleteDevice(id);
+ return new DeviceInfo
+ {
+ AppName = authInfo.AppName,
+ AppVersion = authInfo.AppVersion,
+ Id = authInfo.DeviceId,
+ LastUserId = authInfo.UserId,
+ LastUserName = authInfo.UserName,
+ Name = authInfo.DeviceName,
+ DateLastActivity = authInfo.DateLastActivity
+ };
}
public ContentUploadHistory GetCameraUploadHistory(string deviceId)
@@ -184,7 +139,7 @@ public ContentUploadHistory GetCameraUploadHistory(string deviceId)
public async Task AcceptCameraUpload(string deviceId, Stream stream, LocalFileInfo file)
{
- var device = GetDevice(deviceId);
+ var device = GetDevice(deviceId, false);
var uploadPathInfo = GetUploadPath(device);
var path = uploadPathInfo.Item1;
@@ -264,11 +219,6 @@ internal Task EnsureLibraryFolder(string path, string name)
private Tuple GetUploadPath(DeviceInfo device)
{
- if (!string.IsNullOrWhiteSpace(device.CameraUploadPath))
- {
- return new Tuple(device.CameraUploadPath, device.CameraUploadPath, _fileSystem.GetDirectoryName(device.CameraUploadPath));
- }
-
var config = _config.GetUploadOptions();
var path = config.CameraUploadPath;
@@ -305,20 +255,6 @@ private string DefaultCameraUploadsPath
get { return Path.Combine(_config.CommonApplicationPaths.DataPath, "camerauploads"); }
}
- public void UpdateDeviceInfo(string id, DeviceOptions options)
- {
- var device = GetDevice(id);
-
- device.CustomName = options.CustomName;
- device.CameraUploadPath = options.CameraUploadPath;
-
- device.Name = string.IsNullOrWhiteSpace(device.CustomName) ? device.ReportedName : device.CustomName;
-
- _repo.SaveDevice(device);
-
- EventHelper.FireEventIfNotNull(DeviceOptionsUpdated, this, new GenericEventArgs(device), _logger);
- }
-
public bool CanAccessDevice(User user, string deviceId)
{
if (user == null)
diff --git a/Emby.Server.Implementations/Devices/SqliteDeviceRepository.cs b/Emby.Server.Implementations/Devices/SqliteDeviceRepository.cs
index d80b11d6f7..408c41a25b 100644
--- a/Emby.Server.Implementations/Devices/SqliteDeviceRepository.cs
+++ b/Emby.Server.Implementations/Devices/SqliteDeviceRepository.cs
@@ -22,10 +22,13 @@ public class SqliteDeviceRepository : BaseSqliteRepository, IDeviceRepository
{
private readonly CultureInfo _usCulture = new CultureInfo("en-US");
protected IFileSystem FileSystem { get; private set; }
- private readonly object _syncLock = new object();
+ private readonly object _cameraUploadSyncLock = new object();
+ private readonly object _capabilitiesSyncLock = new object();
private readonly IJsonSerializer _json;
private IServerApplicationPaths _appPaths;
+ private bool _enableDatabase;
+
public SqliteDeviceRepository(ILogger logger, IServerConfigurationManager config, IFileSystem fileSystem, IJsonSerializer json)
: base(logger)
{
@@ -35,325 +38,108 @@ public SqliteDeviceRepository(ILogger logger, IServerConfigurationManager config
FileSystem = fileSystem;
_json = json;
_appPaths = appPaths;
+
}
public void Initialize()
{
- try
- {
- InitializeInternal();
- }
- catch (Exception ex)
- {
- Logger.ErrorException("Error loading database file. Will reset and retry.", ex);
+ _enableDatabase = FileSystem.FileExists(DbFilePath);
- FileSystem.DeleteFile(DbFilePath);
-
- InitializeInternal();
- }
- }
-
- private void InitializeInternal()
- {
- using (var connection = CreateConnection())
+ if (_enableDatabase)
{
- RunDefaultInitialization(connection);
+ try
+ {
+ using (var connection = CreateConnection())
+ {
+ RunDefaultInitialization(connection);
- string[] queries = {
+ string[] queries = {
"create table if not exists Devices (Id TEXT PRIMARY KEY, Name TEXT NOT NULL, ReportedName TEXT NOT NULL, CustomName TEXT, CameraUploadPath TEXT, LastUserName TEXT, AppName TEXT NOT NULL, AppVersion TEXT NOT NULL, LastUserId TEXT, DateLastModified DATETIME NOT NULL, Capabilities TEXT NOT NULL)",
"create index if not exists idx_id on Devices(Id)"
};
- connection.RunQueries(queries);
-
- MigrateDevices();
- }
- }
-
- private void MigrateDevices()
- {
- List files;
- try
- {
- files = FileSystem
- .GetFilePaths(GetDevicesPath(), true)
- .Where(i => string.Equals(Path.GetFileName(i), "device.json", StringComparison.OrdinalIgnoreCase))
- .ToList();
- }
- catch (IOException)
- {
- return;
- }
-
- foreach (var file in files)
- {
- try
- {
- var device = _json.DeserializeFromFile(file);
-
- device.Name = string.IsNullOrWhiteSpace(device.CustomName) ? device.ReportedName : device.CustomName;
-
- SaveDevice(device);
- }
- catch (Exception ex)
- {
- Logger.ErrorException("Error reading {0}", ex, file);
- }
- finally
- {
- try
- {
- FileSystem.DeleteFile(file);
- }
- catch (IOException)
- {
- try
- {
- FileSystem.MoveFile(file, Path.ChangeExtension(file, ".old"));
- }
- catch (IOException)
- {
- }
+ connection.RunQueries(queries);
}
}
- }
- }
-
- private const string BaseSelectText = "select Id, Name, ReportedName, CustomName, CameraUploadPath, LastUserName, AppName, AppVersion, LastUserId, DateLastModified, Capabilities from Devices";
-
- public void SaveCapabilities(string deviceId, ClientCapabilities capabilities)
- {
- using (WriteLock.Write())
- {
- using (var connection = CreateConnection())
+ catch (Exception ex)
{
- connection.RunInTransaction(db =>
- {
- using (var statement = db.PrepareStatement("update devices set Capabilities=@Capabilities where Id=@Id"))
- {
- statement.TryBind("@Id", deviceId);
+ Logger.ErrorException("Error loading database file. Will reset and retry.", ex);
- if (capabilities == null)
- {
- statement.TryBindNull("@Capabilities");
- }
- else
- {
- statement.TryBind("@Capabilities", _json.SerializeToString(capabilities));
- }
+ FileSystem.DeleteFile(DbFilePath);
- statement.MoveNext();
- }
- }, TransactionMode);
+ _enableDatabase = false;
}
}
}
- public void SaveDevice(DeviceInfo entry)
+ public void SaveCapabilities(string deviceId, ClientCapabilities capabilities)
{
- if (entry == null)
- {
- throw new ArgumentNullException("entry");
- }
+ var path = Path.Combine(GetDevicePath(deviceId), "capabilities.json");
+ FileSystem.CreateDirectory(FileSystem.GetDirectoryName(path));
- using (WriteLock.Write())
+ lock (_capabilitiesSyncLock)
{
- using (var connection = CreateConnection())
- {
- connection.RunInTransaction(db =>
- {
- using (var statement = db.PrepareStatement("replace into Devices (Id, Name, ReportedName, CustomName, CameraUploadPath, LastUserName, AppName, AppVersion, LastUserId, DateLastModified, Capabilities) values (@Id, @Name, @ReportedName, @CustomName, @CameraUploadPath, @LastUserName, @AppName, @AppVersion, @LastUserId, @DateLastModified, @Capabilities)"))
- {
- statement.TryBind("@Id", entry.Id);
- statement.TryBind("@Name", entry.Name);
- statement.TryBind("@ReportedName", entry.ReportedName);
- statement.TryBind("@CustomName", entry.CustomName);
- statement.TryBind("@CameraUploadPath", entry.CameraUploadPath);
- statement.TryBind("@LastUserId", entry.LastUserId);
- statement.TryBind("@LastUserName", entry.LastUserName);
- statement.TryBind("@AppName", entry.AppName);
- statement.TryBind("@AppVersion", entry.AppVersion);
- statement.TryBind("@DateLastModified", entry.DateLastModified);
-
- if (entry.Capabilities == null)
- {
- statement.TryBindNull("@Capabilities");
- }
- else
- {
- statement.TryBind("@Capabilities", _json.SerializeToString(entry.Capabilities));
- }
+ _capabilitiesCache[deviceId] = capabilities;
- statement.MoveNext();
- }
- }, TransactionMode);
- }
+ _json.SerializeToFile(capabilities, path);
}
}
- public DeviceInfo GetDevice(string id)
+ private Dictionary _capabilitiesCache = new Dictionary(StringComparer.OrdinalIgnoreCase);
+ public ClientCapabilities GetCapabilities(string id)
{
- using (WriteLock.Read())
+ lock (_capabilitiesSyncLock)
{
- using (var connection = CreateConnection(true))
+ ClientCapabilities result;
+ if (_capabilitiesCache.TryGetValue(id, out result))
{
- var statementTexts = new List();
- statementTexts.Add(BaseSelectText + " where Id=@Id");
-
- return connection.RunInTransaction(db =>
- {
- var statements = PrepareAllSafe(db, statementTexts).ToList();
-
- using (var statement = statements[0])
- {
- statement.TryBind("@Id", id);
-
- foreach (var row in statement.ExecuteQuery())
- {
- return GetEntry(row);
- }
- }
-
- return null;
-
- }, ReadTransactionMode);
+ return result;
}
- }
- }
- public List GetDevices()
- {
- using (WriteLock.Read())
- {
- using (var connection = CreateConnection(true))
+ var path = Path.Combine(GetDevicePath(id), "capabilities.json");
+ try
+ {
+ return _json.DeserializeFromFile(path);
+ }
+ catch
{
- var statementTexts = new List();
- statementTexts.Add(BaseSelectText + " order by DateLastModified desc");
-
- return connection.RunInTransaction(db =>
- {
- var list = new List();
-
- var statements = PrepareAllSafe(db, statementTexts).ToList();
-
- using (var statement = statements[0])
- {
- foreach (var row in statement.ExecuteQuery())
- {
- list.Add(GetEntry(row));
- }
- }
-
- return list;
-
- }, ReadTransactionMode);
}
}
- }
- public ClientCapabilities GetCapabilities(string id)
- {
- using (WriteLock.Read())
+ if (_enableDatabase)
{
- using (var connection = CreateConnection(true))
+ using (WriteLock.Read())
{
- var statementTexts = new List();
- statementTexts.Add("Select Capabilities from Devices where Id=@Id");
-
- return connection.RunInTransaction(db =>
+ using (var connection = CreateConnection(true))
{
- var statements = PrepareAllSafe(db, statementTexts).ToList();
+ var statementTexts = new List();
+ statementTexts.Add("Select Capabilities from Devices where Id=@Id");
- using (var statement = statements[0])
+ return connection.RunInTransaction(db =>
{
- statement.TryBind("@Id", id);
+ var statements = PrepareAllSafe(db, statementTexts).ToList();
- foreach (var row in statement.ExecuteQuery())
+ using (var statement = statements[0])
{
- if (row[0].SQLiteType != SQLiteType.Null)
+ statement.TryBind("@Id", id);
+
+ foreach (var row in statement.ExecuteQuery())
{
- return _json.DeserializeFromString(row.GetString(0));
+ if (row[0].SQLiteType != SQLiteType.Null)
+ {
+ return _json.DeserializeFromString(row.GetString(0));
+ }
}
- }
- }
- return null;
+ return new ClientCapabilities();
+ }
- }, ReadTransactionMode);
+ }, ReadTransactionMode);
+ }
}
}
- }
-
- private DeviceInfo GetEntry(IReadOnlyList reader)
- {
- var index = 0;
-
- var info = new DeviceInfo
- {
- Id = reader.GetString(index)
- };
-
- index++;
- if (reader[index].SQLiteType != SQLiteType.Null)
- {
- info.Name = reader.GetString(index);
- }
-
- index++;
- if (reader[index].SQLiteType != SQLiteType.Null)
- {
- info.ReportedName = reader.GetString(index);
- }
-
- index++;
- if (reader[index].SQLiteType != SQLiteType.Null)
- {
- info.CustomName = reader.GetString(index);
- }
-
- index++;
- if (reader[index].SQLiteType != SQLiteType.Null)
- {
- info.CameraUploadPath = reader.GetString(index);
- }
- index++;
- if (reader[index].SQLiteType != SQLiteType.Null)
- {
- info.LastUserName = reader.GetString(index);
- }
-
- index++;
- if (reader[index].SQLiteType != SQLiteType.Null)
- {
- info.AppName = reader.GetString(index);
- }
-
- index++;
- if (reader[index].SQLiteType != SQLiteType.Null)
- {
- info.AppVersion = reader.GetString(index);
- }
-
- index++;
- if (reader[index].SQLiteType != SQLiteType.Null)
- {
- info.LastUserId = reader.GetString(index);
- }
-
- index++;
- if (reader[index].SQLiteType != SQLiteType.Null)
- {
- info.DateLastModified = reader[index].ReadDateTime();
- }
-
- index++;
- if (reader[index].SQLiteType != SQLiteType.Null)
- {
- info.Capabilities = _json.DeserializeFromString(reader.GetString(index));
- }
-
- return info;
+ return new ClientCapabilities();
}
private string GetDevicesPath()
@@ -370,7 +156,7 @@ public ContentUploadHistory GetCameraUploadHistory(string deviceId)
{
var path = Path.Combine(GetDevicePath(deviceId), "camerauploads.json");
- lock (_syncLock)
+ lock (_cameraUploadSyncLock)
{
try
{
@@ -391,7 +177,7 @@ public void AddCameraUpload(string deviceId, LocalFileInfo file)
var path = Path.Combine(GetDevicePath(deviceId), "camerauploads.json");
FileSystem.CreateDirectory(FileSystem.GetDirectoryName(path));
- lock (_syncLock)
+ lock (_cameraUploadSyncLock)
{
ContentUploadHistory history;
@@ -416,37 +202,5 @@ public void AddCameraUpload(string deviceId, LocalFileInfo file)
_json.SerializeToFile(history, path);
}
}
-
- public void DeleteDevice(string id)
- {
- using (WriteLock.Write())
- {
- using (var connection = CreateConnection())
- {
- connection.RunInTransaction(db =>
- {
- using (var statement = db.PrepareStatement("delete from devices where Id=@Id"))
- {
- statement.TryBind("@Id", id);
-
- statement.MoveNext();
- }
- }, TransactionMode);
- }
- }
-
- var path = GetDevicePath(id);
-
- lock (_syncLock)
- {
- try
- {
- FileSystem.DeleteDirectory(path, true);
- }
- catch (IOException)
- {
- }
- }
- }
}
}
diff --git a/Emby.Server.Implementations/Dto/DtoService.cs b/Emby.Server.Implementations/Dto/DtoService.cs
index e0f8fc11a3..5e67a44158 100644
--- a/Emby.Server.Implementations/Dto/DtoService.cs
+++ b/Emby.Server.Implementations/Dto/DtoService.cs
@@ -841,12 +841,6 @@ private void AttachBasicFields(BaseItemDto dto, BaseItem item, BaseItem owner, D
dto.CriticRating = item.CriticRating;
- var hasTrailers = item as IHasTrailers;
- if (hasTrailers != null)
- {
- dto.LocalTrailerCount = hasTrailers.GetTrailerIds().Count;
- }
-
var hasDisplayOrder = item as IHasDisplayOrder;
if (hasDisplayOrder != null)
{
@@ -861,9 +855,7 @@ private void AttachBasicFields(BaseItemDto dto, BaseItem item, BaseItem owner, D
if (fields.Contains(ItemFields.RemoteTrailers))
{
- dto.RemoteTrailers = hasTrailers != null ?
- hasTrailers.RemoteTrailers :
- new MediaUrl[] { };
+ dto.RemoteTrailers = item.RemoteTrailers;
}
dto.Name = item.Name;
@@ -1139,15 +1131,26 @@ private void AttachBasicFields(BaseItemDto dto, BaseItem item, BaseItem owner, D
}
}
- var hasSpecialFeatures = item as IHasSpecialFeatures;
- if (hasSpecialFeatures != null)
+ BaseItem[] allExtras = null;
+
+ if (fields.Contains(ItemFields.SpecialFeatureCount))
{
- var specialFeatureCount = hasSpecialFeatures.SpecialFeatureIds.Length;
+ if (allExtras == null)
+ {
+ allExtras = item.GetExtras().ToArray();
+ }
+
+ dto.SpecialFeatureCount = allExtras.Count(i => i.ExtraType.HasValue && BaseItem.DisplayExtraTypes.Contains(i.ExtraType.Value));
+ }
- if (specialFeatureCount > 0)
+ if (fields.Contains(ItemFields.LocalTrailerCount))
+ {
+ if (allExtras == null)
{
- dto.SpecialFeatureCount = specialFeatureCount;
+ allExtras = item.GetExtras().ToArray();
}
+
+ dto.LocalTrailerCount = allExtras.Count(i => i.ExtraType.HasValue && i.ExtraType.Value == ExtraType.Trailer);
}
// Add EpisodeInfo
diff --git a/Emby.Server.Implementations/Emby.Server.Implementations.csproj b/Emby.Server.Implementations/Emby.Server.Implementations.csproj
index a715782485..47cf2df8c5 100644
--- a/Emby.Server.Implementations/Emby.Server.Implementations.csproj
+++ b/Emby.Server.Implementations/Emby.Server.Implementations.csproj
@@ -338,7 +338,6 @@
-
@@ -605,7 +604,7 @@
Mono.Nat
- ..\packages\MediaBrowser.Naming.1.1.5-beta\lib\netstandard2.0\Emby.Naming.dll
+ ..\packages\MediaBrowser.Naming.1.1.6-beta\lib\netstandard2.0\Emby.Naming.dll
..\ThirdParty\emby\Emby.Server.MediaEncoding.dll
@@ -614,13 +613,13 @@
..\packages\Emby.XmlTv.1.0.14\lib\portable-net45+netstandard2.0+win8\Emby.XmlTv.dll
- ..\packages\MediaBrowser.Common.3.3.50-beta\lib\netstandard2.0\MediaBrowser.Common.dll
+ ..\packages\MediaBrowser.Common.3.3.53-beta\lib\netstandard2.0\MediaBrowser.Common.dll
- ..\packages\MediaBrowser.Server.Core.3.3.50-beta\lib\netstandard2.0\MediaBrowser.Controller.dll
+ ..\packages\MediaBrowser.Server.Core.3.3.53-beta\lib\netstandard2.0\MediaBrowser.Controller.dll
- ..\packages\MediaBrowser.Common.3.3.50-beta\lib\netstandard2.0\MediaBrowser.Model.dll
+ ..\packages\MediaBrowser.Common.3.3.53-beta\lib\netstandard2.0\MediaBrowser.Model.dll
..\packages\Microsoft.Win32.Primitives.4.3.0\lib\net46\Microsoft.Win32.Primitives.dll
@@ -630,12 +629,11 @@
..\packages\PlaylistsNET.1.0.0\lib\netstandard1.4\PlaylistsNET.dll
-
- ..\packages\ServiceStack.Text.4.5.8\lib\net45\ServiceStack.Text.dll
- True
+
+ ..\packages\ServiceStack.Text.5.1.0\lib\net45\ServiceStack.Text.dll
-
- ..\packages\SharpCompress.0.18.2\lib\net45\SharpCompress.dll
+
+ ..\packages\SharpCompress.0.21.1\lib\net45\SharpCompress.dll
..\packages\SimpleInjector.4.3.0\lib\net45\SimpleInjector.dll
@@ -644,6 +642,9 @@
..\packages\SQLitePCL.pretty.1.1.0\lib\portable-net45+netcore45+wpa81+wp8\SQLitePCL.pretty.dll
True
+
+ ..\packages\System.Runtime.CompilerServices.Unsafe.4.5.1\lib\netstandard2.0\System.Runtime.CompilerServices.Unsafe.dll
+
..\packages\System.Xml.ReaderWriter.4.3.1\lib\net46\System.Xml.ReaderWriter.dll
True
@@ -741,9 +742,6 @@
True
True
-
- ..\packages\System.Runtime.CompilerServices.Unsafe.4.5.0\lib\netstandard2.0\System.Runtime.CompilerServices.Unsafe.dll
-
..\packages\System.Runtime.Extensions.4.3.0\lib\net462\System.Runtime.Extensions.dll
True
diff --git a/Emby.Server.Implementations/HttpServer/Security/AuthService.cs b/Emby.Server.Implementations/HttpServer/Security/AuthService.cs
index fa6fbc0bd2..09157c1bf8 100644
--- a/Emby.Server.Implementations/HttpServer/Security/AuthService.cs
+++ b/Emby.Server.Implementations/HttpServer/Security/AuthService.cs
@@ -64,9 +64,7 @@ private void ValidateUser(IRequest request, IAuthenticationAttributes authAttrib
throw new SecurityException("Operation not found.");
}
- var user = auth.UserId.Equals(Guid.Empty)
- ? null
- : UserManager.GetUserById(auth.UserId);
+ var user = auth.User;
if (user == null & !auth.UserId.Equals(Guid.Empty))
{
diff --git a/Emby.Server.Implementations/HttpServer/Security/AuthorizationContext.cs b/Emby.Server.Implementations/HttpServer/Security/AuthorizationContext.cs
index 5693b8ce0a..c0d520a92a 100644
--- a/Emby.Server.Implementations/HttpServer/Security/AuthorizationContext.cs
+++ b/Emby.Server.Implementations/HttpServer/Security/AuthorizationContext.cs
@@ -6,6 +6,7 @@
using MediaBrowser.Model.Services;
using System.Linq;
using System.Threading;
+using MediaBrowser.Controller.Library;
namespace Emby.Server.Implementations.HttpServer.Security
{
@@ -13,11 +14,13 @@ public class AuthorizationContext : IAuthorizationContext
{
private readonly IAuthenticationRepository _authRepo;
private readonly IConnectManager _connectManager;
+ private readonly IUserManager _userManager;
- public AuthorizationContext(IAuthenticationRepository authRepo, IConnectManager connectManager)
+ public AuthorizationContext(IAuthenticationRepository authRepo, IConnectManager connectManager, IUserManager userManager)
{
_authRepo = authRepo;
_connectManager = connectManager;
+ _userManager = userManager;
}
public AuthorizationInfo GetAuthorizationInfo(object requestContext)
@@ -94,8 +97,6 @@ private AuthorizationInfo GetAuthorization(IRequest httpReq)
if (tokenInfo != null)
{
- info.UserId = tokenInfo.UserId;
-
var updateToken = false;
// TODO: Remove these checks for IsNullOrWhiteSpace
@@ -109,15 +110,21 @@ private AuthorizationInfo GetAuthorization(IRequest httpReq)
info.DeviceId = tokenInfo.DeviceId;
}
+ // Temporary. TODO - allow clients to specify that the token has been shared with a casting device
+ var allowTokenInfoUpdate = info.Client == null || info.Client.IndexOf("chromecast", StringComparison.OrdinalIgnoreCase) == -1;
if (string.IsNullOrWhiteSpace(info.Device))
{
info.Device = tokenInfo.DeviceName;
}
+
else if (!string.Equals(info.Device, tokenInfo.DeviceName, StringComparison.OrdinalIgnoreCase))
{
- updateToken = true;
- tokenInfo.DeviceName = info.Device;
+ if (allowTokenInfoUpdate)
+ {
+ updateToken = true;
+ tokenInfo.DeviceName = info.Device;
+ }
}
if (string.IsNullOrWhiteSpace(info.Version))
@@ -126,8 +133,28 @@ private AuthorizationInfo GetAuthorization(IRequest httpReq)
}
else if (!string.Equals(info.Version, tokenInfo.AppVersion, StringComparison.OrdinalIgnoreCase))
{
+ if (allowTokenInfoUpdate)
+ {
+ updateToken = true;
+ tokenInfo.AppVersion = info.Version;
+ }
+ }
+
+ if ((DateTime.UtcNow - tokenInfo.DateLastActivity).TotalMinutes > 3)
+ {
+ tokenInfo.DateLastActivity = DateTime.UtcNow;
updateToken = true;
- tokenInfo.AppVersion = info.Version;
+ }
+
+ if (!tokenInfo.UserId.Equals(Guid.Empty))
+ {
+ info.User = _userManager.GetUserById(tokenInfo.UserId);
+
+ if (info.User != null && !string.Equals(info.User.Name, tokenInfo.UserName, StringComparison.OrdinalIgnoreCase))
+ {
+ tokenInfo.UserName = info.User.Name;
+ updateToken = true;
+ }
}
if (updateToken)
@@ -137,11 +164,7 @@ private AuthorizationInfo GetAuthorization(IRequest httpReq)
}
else
{
- var user = _connectManager.GetUserFromExchangeToken(token);
- if (user != null)
- {
- info.UserId = user.Id;
- }
+ info.User = _connectManager.GetUserFromExchangeToken(token);
}
httpReq.Items["OriginalAuthenticationInfo"] = tokenInfo;
}
diff --git a/Emby.Server.Implementations/HttpServer/Security/SessionContext.cs b/Emby.Server.Implementations/HttpServer/Security/SessionContext.cs
index b25daf554d..a919ce0083 100644
--- a/Emby.Server.Implementations/HttpServer/Security/SessionContext.cs
+++ b/Emby.Server.Implementations/HttpServer/Security/SessionContext.cs
@@ -26,7 +26,7 @@ public SessionInfo GetSession(IRequest requestContext)
{
var authorization = _authContext.GetAuthorizationInfo(requestContext);
- var user = authorization.UserId.Equals(Guid.Empty) ? null : _userManager.GetUserById(authorization.UserId);
+ var user = authorization.User;
return _sessionManager.LogSessionActivity(authorization.Client, authorization.Version, authorization.DeviceId, authorization.Device, requestContext.RemoteIp, user);
}
diff --git a/Emby.Server.Implementations/IO/ManagedFileSystem.cs b/Emby.Server.Implementations/IO/ManagedFileSystem.cs
index 7978b82548..66d7802c6f 100644
--- a/Emby.Server.Implementations/IO/ManagedFileSystem.cs
+++ b/Emby.Server.Implementations/IO/ManagedFileSystem.cs
@@ -30,7 +30,7 @@ public class ManagedFileSystem : IFileSystem
private string _defaultDirectory;
- public ManagedFileSystem(ILogger logger, IEnvironmentInfo environmentInfo, string defaultDirectory, string tempPath)
+ public ManagedFileSystem(ILogger logger, IEnvironmentInfo environmentInfo, string defaultDirectory, string tempPath, bool enableSeparateFileAndDirectoryQueries)
{
Logger = logger;
_supportsAsyncFileStreams = true;
@@ -38,10 +38,8 @@ public ManagedFileSystem(ILogger logger, IEnvironmentInfo environmentInfo, strin
_environmentInfo = environmentInfo;
_defaultDirectory = defaultDirectory;
- // On Linux, this needs to be true or symbolic links are ignored
- // TODO: See if still needed under .NET Core
- EnableSeparateFileAndDirectoryQueries = environmentInfo.OperatingSystem != MediaBrowser.Model.System.OperatingSystem.Windows &&
- environmentInfo.OperatingSystem != MediaBrowser.Model.System.OperatingSystem.OSX;
+ // On Linux with mono, this needs to be true or symbolic links are ignored
+ EnableSeparateFileAndDirectoryQueries = enableSeparateFileAndDirectoryQueries;
SetInvalidFileNameChars(environmentInfo.OperatingSystem == MediaBrowser.Model.System.OperatingSystem.Windows);
diff --git a/Emby.Server.Implementations/Library/LibraryManager.cs b/Emby.Server.Implementations/Library/LibraryManager.cs
index fabe0c434e..31af9370c7 100644
--- a/Emby.Server.Implementations/Library/LibraryManager.cs
+++ b/Emby.Server.Implementations/Library/LibraryManager.cs
@@ -2593,11 +2593,10 @@ public IEnumerable FindTrailers(BaseItem owner, List
{
video = dbItem;
}
- else
- {
- // item is new
- video.ExtraType = ExtraType.Trailer;
- }
+
+ video.ParentId = Guid.Empty;
+ video.OwnerId = owner.Id;
+ video.ExtraType = ExtraType.Trailer;
video.TrailerTypes = new [] { TrailerType.LocalTrailer };
return video;
@@ -2640,6 +2639,9 @@ public IEnumerable FindExtras(BaseItem owner, List fi
video = dbItem;
}
+ video.ParentId = Guid.Empty;
+ video.OwnerId = owner.Id;
+
SetExtraTypeFromFilename(video);
return video;
diff --git a/Emby.Server.Implementations/Library/LocalTrailerPostScanTask.cs b/Emby.Server.Implementations/Library/LocalTrailerPostScanTask.cs
deleted file mode 100644
index d36a52696b..0000000000
--- a/Emby.Server.Implementations/Library/LocalTrailerPostScanTask.cs
+++ /dev/null
@@ -1,106 +0,0 @@
-using MediaBrowser.Controller.Channels;
-using MediaBrowser.Controller.Entities;
-using MediaBrowser.Controller.Library;
-using MediaBrowser.Model.Entities;
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Threading;
-using System.Threading.Tasks;
-using MediaBrowser.Controller.Dto;
-using MediaBrowser.Controller.Entities.Movies;
-using MediaBrowser.Controller.Entities.TV;
-
-namespace Emby.Server.Implementations.Library
-{
- public class LocalTrailerPostScanTask : ILibraryPostScanTask
- {
- private readonly ILibraryManager _libraryManager;
- private readonly IChannelManager _channelManager;
-
- public LocalTrailerPostScanTask(ILibraryManager libraryManager, IChannelManager channelManager)
- {
- _libraryManager = libraryManager;
- _channelManager = channelManager;
- }
-
- public Task Run(IProgress progress, CancellationToken cancellationToken)
- {
- var items = _libraryManager.GetItemList(new InternalItemsQuery
- {
- IncludeItemTypes = new[] { typeof(BoxSet).Name, typeof(Game).Name, typeof(Movie).Name, typeof(Series).Name },
- Recursive = true,
- DtoOptions = new DtoOptions(true)
-
- }).OfType().ToList();
-
- var trailerTypes = Enum.GetNames(typeof(TrailerType))
- .Select(i => (TrailerType)Enum.Parse(typeof(TrailerType), i, true))
- .Except(new[] { TrailerType.LocalTrailer })
- .ToArray();
-
- var trailers = _libraryManager.GetItemList(new InternalItemsQuery
- {
- IncludeItemTypes = new[] { typeof(Trailer).Name },
- TrailerTypes = trailerTypes,
- Recursive = true,
- DtoOptions = new DtoOptions(false)
- });
-
- var numComplete = 0;
-
- foreach (var item in items)
- {
- cancellationToken.ThrowIfCancellationRequested();
-
- AssignTrailers(item, trailers);
-
- numComplete++;
- double percent = numComplete;
- percent /= items.Count;
- progress.Report(percent * 100);
- }
-
- progress.Report(100);
-
- return Task.CompletedTask;
- }
-
- private void AssignTrailers(IHasTrailers item, IEnumerable channelTrailers)
- {
- if (item is Game)
- {
- return;
- }
-
- var imdbId = item.GetProviderId(MetadataProviders.Imdb);
- var tmdbId = item.GetProviderId(MetadataProviders.Tmdb);
-
- var trailers = channelTrailers.Where(i =>
- {
- if (!string.IsNullOrEmpty(imdbId) &&
- string.Equals(imdbId, i.GetProviderId(MetadataProviders.Imdb), StringComparison.OrdinalIgnoreCase))
- {
- return true;
- }
- if (!string.IsNullOrEmpty(tmdbId) &&
- string.Equals(tmdbId, i.GetProviderId(MetadataProviders.Tmdb), StringComparison.OrdinalIgnoreCase))
- {
- return true;
- }
- return false;
- });
-
- var trailerIds = trailers.Select(i => i.Id)
- .ToArray();
-
- if (!trailerIds.SequenceEqual(item.RemoteTrailerIds))
- {
- item.RemoteTrailerIds = trailerIds;
-
- var baseItem = (BaseItem)item;
- baseItem.UpdateToRepository(ItemUpdateType.MetadataImport, CancellationToken.None);
- }
- }
- }
-}
diff --git a/Emby.Server.Implementations/Library/UserDataManager.cs b/Emby.Server.Implementations/Library/UserDataManager.cs
index f2578348cc..2f632d3843 100644
--- a/Emby.Server.Implementations/Library/UserDataManager.cs
+++ b/Emby.Server.Implementations/Library/UserDataManager.cs
@@ -230,13 +230,15 @@ public bool UpdatePlayState(BaseItem item, UserItemData data, long? reportedPosi
{
var playedToCompletion = false;
- var positionTicks = reportedPositionTicks ?? item.RunTimeTicks ?? 0;
- var hasRuntime = item.RunTimeTicks.HasValue && item.RunTimeTicks > 0;
+ var runtimeTicks = item.GetRunTimeTicksForPlayState();
+
+ var positionTicks = reportedPositionTicks ?? runtimeTicks;
+ var hasRuntime = runtimeTicks > 0;
// If a position has been reported, and if we know the duration
if (positionTicks > 0 && hasRuntime)
{
- var pctIn = Decimal.Divide(positionTicks, item.RunTimeTicks.Value) * 100;
+ var pctIn = Decimal.Divide(positionTicks, runtimeTicks) * 100;
// Don't track in very beginning
if (pctIn < _config.Configuration.MinResumePct)
@@ -245,7 +247,7 @@ public bool UpdatePlayState(BaseItem item, UserItemData data, long? reportedPosi
}
// If we're at the end, assume completed
- else if (pctIn > _config.Configuration.MaxResumePct || positionTicks >= item.RunTimeTicks.Value)
+ else if (pctIn > _config.Configuration.MaxResumePct || positionTicks >= runtimeTicks)
{
positionTicks = 0;
data.Played = playedToCompletion = true;
@@ -254,7 +256,7 @@ public bool UpdatePlayState(BaseItem item, UserItemData data, long? reportedPosi
else
{
// Enforce MinResumeDuration
- var durationSeconds = TimeSpan.FromTicks(item.RunTimeTicks.Value).TotalSeconds;
+ var durationSeconds = TimeSpan.FromTicks(runtimeTicks).TotalSeconds;
if (durationSeconds < _config.Configuration.MinResumeDurationSeconds)
{
diff --git a/Emby.Server.Implementations/Library/UserManager.cs b/Emby.Server.Implementations/Library/UserManager.cs
index 74a44752d7..d9df23b2aa 100644
--- a/Emby.Server.Implementations/Library/UserManager.cs
+++ b/Emby.Server.Implementations/Library/UserManager.cs
@@ -1267,7 +1267,7 @@ private void UpdateDeviceAccess(User user)
{
if (!string.IsNullOrEmpty(authInfo.DeviceId) && !_deviceManager.CanAccessDevice(user, authInfo.DeviceId))
{
- _sessionManager.Logout(authInfo.AccessToken);
+ _sessionManager.Logout(authInfo);
}
}
}
diff --git a/Emby.Server.Implementations/Networking/NetworkManager.cs b/Emby.Server.Implementations/Networking/NetworkManager.cs
index e2e45229e1..20abaf27c2 100644
--- a/Emby.Server.Implementations/Networking/NetworkManager.cs
+++ b/Emby.Server.Implementations/Networking/NetworkManager.cs
@@ -28,8 +28,7 @@ public NetworkManager(ILogger logger, IEnvironmentInfo environment)
Logger = logger;
// In FreeBSD these events cause a crash
- if (environment.OperatingSystem != MediaBrowser.Model.System.OperatingSystem.BSD &&
- environment.OperatingSystem != MediaBrowser.Model.System.OperatingSystem.Linux)
+ if (environment.OperatingSystem != MediaBrowser.Model.System.OperatingSystem.BSD)
{
try
{
diff --git a/Emby.Server.Implementations/ScheduledTasks/PluginUpdateTask.cs b/Emby.Server.Implementations/ScheduledTasks/PluginUpdateTask.cs
index 9f887ba030..db8a093807 100644
--- a/Emby.Server.Implementations/ScheduledTasks/PluginUpdateTask.cs
+++ b/Emby.Server.Implementations/ScheduledTasks/PluginUpdateTask.cs
@@ -71,14 +71,13 @@ public async Task Execute(CancellationToken cancellationToken, IProgress
var numComplete = 0;
- // Create tasks for each one
- var tasks = packagesToInstall.Select(i => Task.Run(async () =>
+ foreach (var package in packagesToInstall)
{
cancellationToken.ThrowIfCancellationRequested();
try
{
- await _installationManager.InstallPackage(i, true, new SimpleProgress(), cancellationToken).ConfigureAwait(false);
+ await _installationManager.InstallPackage(package, true, new SimpleProgress(), cancellationToken).ConfigureAwait(false);
}
catch (OperationCanceledException)
{
@@ -90,11 +89,11 @@ public async Task Execute(CancellationToken cancellationToken, IProgress
}
catch (HttpException ex)
{
- _logger.ErrorException("Error downloading {0}", ex, i.name);
+ _logger.ErrorException("Error downloading {0}", ex, package.name);
}
catch (IOException ex)
{
- _logger.ErrorException("Error updating {0}", ex, i.name);
+ _logger.ErrorException("Error updating {0}", ex, package.name);
}
// Update progress
@@ -106,11 +105,7 @@ public async Task Execute(CancellationToken cancellationToken, IProgress
progress.Report(90 * percent + 10);
}
- }));
-
- cancellationToken.ThrowIfCancellationRequested();
-
- await Task.WhenAll(tasks).ConfigureAwait(false);
+ }
progress.Report(100);
}
diff --git a/Emby.Server.Implementations/Security/AuthenticationRepository.cs b/Emby.Server.Implementations/Security/AuthenticationRepository.cs
index 1a2c2ebcc0..d9bc6df3bf 100644
--- a/Emby.Server.Implementations/Security/AuthenticationRepository.cs
+++ b/Emby.Server.Implementations/Security/AuthenticationRepository.cs
@@ -34,7 +34,7 @@ public void Initialize()
string[] queries = {
- "create table if not exists AccessTokens (Id GUID PRIMARY KEY NOT NULL, AccessToken TEXT NOT NULL, DeviceId TEXT NOT NULL, AppName TEXT NOT NULL, AppVersion TEXT NOT NULL, DeviceName TEXT NOT NULL, UserId TEXT, IsActive BIT NOT NULL, DateCreated DATETIME NOT NULL, DateRevoked DATETIME)",
+ "create table if not exists AccessTokens (Id GUID PRIMARY KEY NOT NULL, AccessToken TEXT NOT NULL, DeviceId TEXT NOT NULL, AppName TEXT NOT NULL, AppVersion TEXT NOT NULL, DeviceName TEXT NOT NULL, UserId TEXT, UserName TEXT, IsActive BIT NOT NULL, DateCreated DATETIME NOT NULL, DateLastActivity DATETIME NOT NULL, DateRevoked DATETIME)",
"create index if not exists idx_AccessTokens on AccessTokens(Id)"
};
@@ -44,6 +44,8 @@ public void Initialize()
{
var existingColumnNames = GetColumnNames(db, "AccessTokens");
+ AddColumn(db, "AccessTokens", "UserName", "TEXT", existingColumnNames);
+ AddColumn(db, "AccessTokens", "DateLastActivity", "DATETIME", existingColumnNames);
AddColumn(db, "AccessTokens", "AppVersion", "TEXT", existingColumnNames);
}, TransactionMode);
@@ -72,7 +74,7 @@ public void Update(AuthenticationInfo info, CancellationToken cancellationToken)
{
connection.RunInTransaction(db =>
{
- using (var statement = db.PrepareStatement("replace into AccessTokens (Id, AccessToken, DeviceId, AppName, AppVersion, DeviceName, UserId, IsActive, DateCreated, DateRevoked) values (@Id, @AccessToken, @DeviceId, @AppName, @AppVersion, @DeviceName, @UserId, @IsActive, @DateCreated, @DateRevoked)"))
+ using (var statement = db.PrepareStatement("replace into AccessTokens (Id, AccessToken, DeviceId, AppName, AppVersion, DeviceName, UserId, UserName, IsActive, DateCreated, DateLastActivity, DateRevoked) values (@Id, @AccessToken, @DeviceId, @AppName, @AppVersion, @DeviceName, @UserId, @UserName, @IsActive, @DateCreated, @DateLastActivity, @DateRevoked)"))
{
statement.TryBind("@Id", info.Id.ToGuidBlob());
statement.TryBind("@AccessToken", info.AccessToken);
@@ -82,8 +84,10 @@ public void Update(AuthenticationInfo info, CancellationToken cancellationToken)
statement.TryBind("@AppVersion", info.AppVersion);
statement.TryBind("@DeviceName", info.DeviceName);
statement.TryBind("@UserId", (info.UserId.Equals(Guid.Empty) ? null : info.UserId.ToString("N")));
+ statement.TryBind("@UserName", info.UserName);
statement.TryBind("@IsActive", info.IsActive);
statement.TryBind("@DateCreated", info.DateCreated.ToDateTimeParamValue());
+ statement.TryBind("@DateLastActivity", info.DateLastActivity.ToDateTimeParamValue());
if (info.DateRevoked.HasValue)
{
@@ -102,7 +106,7 @@ public void Update(AuthenticationInfo info, CancellationToken cancellationToken)
}
}
- private const string BaseSelectText = "select Id, AccessToken, DeviceId, AppName, AppVersion, DeviceName, UserId, IsActive, DateCreated, DateRevoked from AccessTokens";
+ private const string BaseSelectText = "select Id, AccessToken, DeviceId, AppName, AppVersion, DeviceName, UserId, UserName, IsActive, DateCreated, DateLastActivity, DateRevoked from AccessTokens";
private void BindAuthenticationQueryParams(AuthenticationInfoQuery query, IStatement statement)
{
@@ -138,8 +142,6 @@ public QueryResult Get(AuthenticationInfoQuery query)
var whereClauses = new List();
- var startIndex = query.StartIndex ?? 0;
-
if (!string.IsNullOrEmpty(query.AccessToken))
{
whereClauses.Add("AccessToken=@AccessToken");
@@ -176,28 +178,23 @@ public QueryResult Get(AuthenticationInfoQuery query)
string.Empty :
" where " + string.Join(" AND ", whereClauses.ToArray(whereClauses.Count));
- if (startIndex > 0)
- {
- var pagingWhereText = whereClauses.Count == 0 ?
- string.Empty :
- " where " + string.Join(" AND ", whereClauses.ToArray(whereClauses.Count));
+ commandText += whereTextWithoutPaging;
- whereClauses.Add(string.Format("Id NOT IN (SELECT Id FROM AccessTokens {0} ORDER BY DateCreated LIMIT {1})",
- pagingWhereText,
- startIndex.ToString(_usCulture)));
- }
+ commandText += " ORDER BY DateLastActivity desc, DateCreated desc";
- var whereText = whereClauses.Count == 0 ?
- string.Empty :
- " where " + string.Join(" AND ", whereClauses.ToArray(whereClauses.Count));
-
- commandText += whereText;
+ if (query.Limit.HasValue || query.StartIndex.HasValue)
+ {
+ var offset = query.StartIndex ?? 0;
- commandText += " ORDER BY DateCreated";
+ if (query.Limit.HasValue || offset > 0)
+ {
+ commandText += " LIMIT " + (query.Limit ?? int.MaxValue).ToString(CultureInfo.InvariantCulture);
+ }
- if (query.Limit.HasValue)
- {
- commandText += " LIMIT " + query.Limit.Value.ToString(_usCulture);
+ if (offset > 0)
+ {
+ commandText += " OFFSET " + offset.ToString(CultureInfo.InvariantCulture);
+ }
}
var list = new List();
@@ -304,12 +301,26 @@ private AuthenticationInfo Get(IReadOnlyList reader)
info.UserId = new Guid(reader[6].ToString());
}
- info.IsActive = reader[7].ToBool();
- info.DateCreated = reader[8].ReadDateTime();
+ if (reader[7].SQLiteType != SQLiteType.Null)
+ {
+ info.UserName = reader[7].ToString();
+ }
+
+ info.IsActive = reader[8].ToBool();
+ info.DateCreated = reader[9].ReadDateTime();
+
+ if (reader[10].SQLiteType != SQLiteType.Null)
+ {
+ info.DateLastActivity = reader[10].ReadDateTime();
+ }
+ else
+ {
+ info.DateLastActivity = info.DateCreated;
+ }
- if (reader[9].SQLiteType != SQLiteType.Null)
+ if (reader[11].SQLiteType != SQLiteType.Null)
{
- info.DateRevoked = reader[9].TryReadDateTime();
+ info.DateRevoked = reader[11].TryReadDateTime();
}
return info;
diff --git a/Emby.Server.Implementations/Session/FirebaseSessionController.cs b/Emby.Server.Implementations/Session/FirebaseSessionController.cs
index 98a9c9d9ba..cfe513305e 100644
--- a/Emby.Server.Implementations/Session/FirebaseSessionController.cs
+++ b/Emby.Server.Implementations/Session/FirebaseSessionController.cs
@@ -50,7 +50,7 @@ public bool IsSessionActive
{
get
{
- return (DateTime.UtcNow - Session.LastActivityDate).TotalHours <= 48;
+ return (DateTime.UtcNow - Session.LastActivityDate).TotalDays <= 3;
}
}
diff --git a/Emby.Server.Implementations/Session/SessionManager.cs b/Emby.Server.Implementations/Session/SessionManager.cs
index 25dc3cc4bc..38dd0e319e 100644
--- a/Emby.Server.Implementations/Session/SessionManager.cs
+++ b/Emby.Server.Implementations/Session/SessionManager.cs
@@ -108,8 +108,6 @@ public SessionManager(IUserDataManager userDataManager, ILogger logger, ILibrary
_deviceManager = deviceManager;
_mediaSourceManager = mediaSourceManager;
_timerFactory = timerFactory;
-
- _deviceManager.DeviceOptionsUpdated += _deviceManager_DeviceOptionsUpdated;
}
private bool _disposed;
@@ -126,17 +124,6 @@ public void CheckDisposed()
}
}
- void _deviceManager_DeviceOptionsUpdated(object sender, GenericEventArgs e)
- {
- foreach (var session in Sessions)
- {
- if (string.Equals(session.DeviceId, e.Argument.Id))
- {
- session.DeviceName = e.Argument.Name;
- }
- }
- }
-
///
/// Gets all connections.
///
@@ -185,19 +172,7 @@ public void UpdateDeviceName(string sessionId, string deviceName)
if (session != null)
{
- var deviceId = session.DeviceId;
-
- if (!string.IsNullOrEmpty(deviceId))
- {
- var device = _deviceManager.GetDevice(deviceId);
-
- if (device != null)
- {
- device = _deviceManager.RegisterDevice(device.Id, deviceName, device.AppName, device.AppVersion, device.LastUserId, device.LastUserName);
-
- session.DeviceName = device.Name;
- }
- }
+ session.DeviceName = deviceName;
}
}
@@ -436,8 +411,6 @@ private SessionInfo GetSessionInfo(string appName, string appVersion, string dev
private SessionInfo CreateSession(string key, string appName, string appVersion, string deviceId, string deviceName, string remoteEndPoint, User user)
{
- DeviceInfo device = null;
-
var sessionInfo = new SessionInfo(this, _logger)
{
Client = appName,
@@ -458,20 +431,6 @@ private SessionInfo CreateSession(string key, string appName, string appVersion,
deviceName = "Network Device";
}
- if (!string.IsNullOrEmpty(deviceId))
- {
- var userIdString = user != null ? user.Id.ToString("N") : null;
- device = _deviceManager.RegisterDevice(deviceId, deviceName, appName, appVersion, userIdString, username);
- }
-
- if (device != null)
- {
- if (!string.IsNullOrEmpty(device.CustomName))
- {
- deviceName = device.CustomName;
- }
- }
-
sessionInfo.DeviceName = deviceName;
OnSessionStarted(sessionInfo);
@@ -1380,7 +1339,7 @@ private async Task AuthenticateNewSessionInternal(Authenti
user = result;
}
- var token = GetAuthorizationToken(user.Id, request.DeviceId, request.App, request.AppVersion, request.DeviceName);
+ var token = GetAuthorizationToken(user, request.DeviceId, request.App, request.AppVersion, request.DeviceName);
EventHelper.FireEventIfNotNull(AuthenticationSucceeded, this, new GenericEventArgs(request), _logger);
@@ -1400,36 +1359,62 @@ private async Task AuthenticateNewSessionInternal(Authenti
};
}
- private string GetAuthorizationToken(Guid userId, string deviceId, string app, string appVersion, string deviceName)
+ private string GetAuthorizationToken(User user, string deviceId, string app, string appVersion, string deviceName)
{
var existing = _authRepo.Get(new AuthenticationInfoQuery
{
DeviceId = deviceId,
IsActive = true,
- UserId = userId,
+ UserId = user.Id,
Limit = 1
- });
- if (existing.Items.Length > 0)
+ }).Items.FirstOrDefault();
+
+ if (existing != null)
{
- var token = existing.Items[0].AccessToken;
- _logger.Info("Reissuing access token: " + token);
- return token;
+ var allExistingForDevice = _authRepo.Get(new AuthenticationInfoQuery
+ {
+ DeviceId = deviceId,
+ IsActive = true
+
+ }).Items;
+
+ foreach (var auth in allExistingForDevice)
+ {
+ if (!string.Equals(auth.AccessToken, existing.AccessToken, StringComparison.Ordinal))
+ {
+ try
+ {
+ Logout(auth);
+ }
+ catch
+ {
+
+ }
+ }
+ }
+
+ _logger.Info("Reissuing access token: " + existing.AccessToken);
+ return existing.AccessToken;
}
+ var now = DateTime.UtcNow;
+
var newToken = new AuthenticationInfo
{
AppName = app,
AppVersion = appVersion,
- DateCreated = DateTime.UtcNow,
+ DateCreated = now,
+ DateLastActivity = now,
DeviceId = deviceId,
DeviceName = deviceName,
- UserId = userId,
+ UserId = user.Id,
IsActive = true,
- AccessToken = Guid.NewGuid().ToString("N")
+ AccessToken = Guid.NewGuid().ToString("N"),
+ UserName = user.Name
};
- _logger.Info("Creating new access token for user {0}", userId);
+ _logger.Info("Creating new access token for user {0}", user.Id);
_authRepo.Create(newToken, CancellationToken.None);
return newToken.AccessToken;
@@ -1444,8 +1429,6 @@ public void Logout(string accessToken)
throw new ArgumentNullException("accessToken");
}
- _logger.Info("Logging out access token {0}", accessToken);
-
var existing = _authRepo.Get(new AuthenticationInfoQuery
{
Limit = 1,
@@ -1455,24 +1438,34 @@ public void Logout(string accessToken)
if (existing != null)
{
- existing.IsActive = false;
+ Logout(existing);
+ }
+ }
+
+ public void Logout(AuthenticationInfo existing)
+ {
+ CheckDisposed();
- _authRepo.Update(existing, CancellationToken.None);
+ _logger.Info("Logging out access token {0}", existing.AccessToken);
- var sessions = Sessions
- .Where(i => string.Equals(i.DeviceId, existing.DeviceId, StringComparison.OrdinalIgnoreCase))
- .ToList();
+ existing.IsActive = false;
+ existing.DateRevoked = DateTime.UtcNow;
- foreach (var session in sessions)
+ _authRepo.Update(existing, CancellationToken.None);
+
+ var sessions = Sessions
+ .Where(i => string.Equals(i.DeviceId, existing.DeviceId, StringComparison.OrdinalIgnoreCase))
+ .ToList();
+
+ foreach (var session in sessions)
+ {
+ try
{
- try
- {
- ReportSessionEnded(session.Id);
- }
- catch (Exception ex)
- {
- _logger.ErrorException("Error reporting session ended", ex);
- }
+ ReportSessionEnded(session.Id);
+ }
+ catch (Exception ex)
+ {
+ _logger.ErrorException("Error reporting session ended", ex);
}
}
}
@@ -1491,7 +1484,7 @@ public void RevokeUserTokens(Guid userId, string currentAccessToken)
{
if (!string.Equals(currentAccessToken, info.AccessToken, StringComparison.OrdinalIgnoreCase))
{
- Logout(info.AccessToken);
+ Logout(info);
}
}
}
@@ -1612,7 +1605,7 @@ private BaseItemDto GetItemInfo(BaseItem item, MediaSourceInfo mediaSource)
fields.Remove(ItemFields.Settings);
fields.Remove(ItemFields.SortName);
fields.Remove(ItemFields.Tags);
- fields.Remove(ItemFields.ThemeSongIds);
+ fields.Remove(ItemFields.ExtraIds);
dtoOptions.Fields = fields.ToArray(fields.Count);
@@ -1702,22 +1695,7 @@ public SessionInfo GetSessionByAuthenticationToken(AuthenticationInfo info, stri
var deviceName = info.DeviceName;
var appName = info.AppName;
- if (!string.IsNullOrEmpty(deviceId))
- {
- // Replace the info from the token with more recent info
- var device = _deviceManager.GetDevice(deviceId);
- if (device != null)
- {
- deviceName = device.Name;
- appName = device.AppName;
-
- if (!string.IsNullOrEmpty(device.AppVersion))
- {
- appVersion = device.AppVersion;
- }
- }
- }
- else
+ if (string.IsNullOrEmpty(deviceId))
{
deviceId = info.DeviceId;
}
@@ -1808,8 +1786,7 @@ public Task SendMessageToUserSessions(List userIds, string name, T data
return Task.WhenAll(tasks);
}
- public Task SendMessageToUserDeviceSessions(string deviceId, string name, T data,
- CancellationToken cancellationToken)
+ public Task SendMessageToUserDeviceSessions(string deviceId, string name, T data, CancellationToken cancellationToken)
{
CheckDisposed();
@@ -1830,5 +1807,36 @@ public Task SendMessageToUserDeviceSessions(string deviceId, string name, T d
return Task.WhenAll(tasks);
}
+
+ public Task SendMessageToUserDeviceAndAdminSessions(string deviceId, string name, T data, CancellationToken cancellationToken)
+ {
+ CheckDisposed();
+
+ var sessions = Sessions
+ .Where(i => string.Equals(i.DeviceId, deviceId, StringComparison.OrdinalIgnoreCase) || IsAdminSession(i))
+ .ToList();
+
+ var tasks = sessions.Select(session => Task.Run(async () =>
+ {
+ try
+ {
+ await SendMessageToSession(session, name, data, cancellationToken).ConfigureAwait(false);
+ }
+ catch (Exception ex)
+ {
+ _logger.ErrorException("Error sending message", ex);
+ }
+
+ }, cancellationToken)).ToArray();
+
+ return Task.WhenAll(tasks);
+ }
+
+ private bool IsAdminSession(SessionInfo s)
+ {
+ var user = _userManager.GetUserById(s.UserId);
+
+ return user != null && user.Policy.IsAdministrator;
+ }
}
}
\ No newline at end of file
diff --git a/Emby.Server.Implementations/packages.config b/Emby.Server.Implementations/packages.config
index ffc2204a93..540c1d51e6 100644
--- a/Emby.Server.Implementations/packages.config
+++ b/Emby.Server.Implementations/packages.config
@@ -1,15 +1,15 @@
-
-
-
+
+
+
-
-
+
+
@@ -40,7 +40,7 @@
-
+
diff --git a/MediaBrowser.Api/BaseApiService.cs b/MediaBrowser.Api/BaseApiService.cs
index e98915e908..2d0fc9c632 100644
--- a/MediaBrowser.Api/BaseApiService.cs
+++ b/MediaBrowser.Api/BaseApiService.cs
@@ -88,7 +88,7 @@ protected void AssertCanUpdateUser(IAuthorizationContext authContext, IUserManag
{
var auth = authContext.GetAuthorizationInfo(Request);
- var authenticatedUser = userManager.GetUserById(auth.UserId);
+ var authenticatedUser = auth.User;
// If they're going to update the record of another user, they must be an administrator
if (!userId.Equals(auth.UserId))
diff --git a/MediaBrowser.Api/Devices/DeviceService.cs b/MediaBrowser.Api/Devices/DeviceService.cs
index 05d0e9615c..92e8dc2e07 100644
--- a/MediaBrowser.Api/Devices/DeviceService.cs
+++ b/MediaBrowser.Api/Devices/DeviceService.cs
@@ -7,6 +7,8 @@
using System.IO;
using System.Threading.Tasks;
using MediaBrowser.Model.Services;
+using MediaBrowser.Controller.Security;
+using MediaBrowser.Controller.Session;
namespace MediaBrowser.Api.Devices
{
@@ -50,56 +52,17 @@ public class PostCameraUpload : IRequiresRequestStream, IReturnVoid
public Stream RequestStream { get; set; }
}
- [Route("/Devices/Info", "GET", Summary = "Gets device info")]
- [Authenticated]
- public class GetDeviceInfo : IReturn
- {
- [ApiMember(Name = "Id", Description = "Device Id", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "DELETE")]
- public string Id { get; set; }
- }
-
- [Route("/Devices/Capabilities", "GET", Summary = "Gets device capabilities")]
- [Authenticated]
- public class GetDeviceCapabilities : IReturn
- {
- [ApiMember(Name = "Id", Description = "Device Id", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "DELETE")]
- public string Id { get; set; }
- }
-
- [Route("/Devices/Options", "POST", Summary = "Updates device options")]
- [Authenticated(Roles = "Admin")]
- public class PostDeviceOptions : DeviceOptions, IReturnVoid
- {
- [ApiMember(Name = "Id", Description = "Device Id", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "DELETE")]
- public string Id { get; set; }
- }
-
public class DeviceService : BaseApiService
{
private readonly IDeviceManager _deviceManager;
+ private readonly IAuthenticationRepository _authRepo;
+ private readonly ISessionManager _sessionManager;
- public DeviceService(IDeviceManager deviceManager)
+ public DeviceService(IDeviceManager deviceManager, IAuthenticationRepository authRepo, ISessionManager sessionManager)
{
_deviceManager = deviceManager;
- }
-
- public void Post(PostDeviceOptions request)
- {
- _deviceManager.UpdateDeviceInfo(request.Id, new DeviceOptions
- {
- CustomName = request.CustomName,
- CameraUploadPath = request.CameraUploadPath
- });
- }
-
- public object Get(GetDeviceInfo request)
- {
- return ToOptimizedResult(_deviceManager.GetDevice(request.Id));
- }
-
- public object Get(GetDeviceCapabilities request)
- {
- return ToOptimizedResult(_deviceManager.GetCapabilities(request.Id));
+ _authRepo = authRepo;
+ _sessionManager = sessionManager;
}
public object Get(GetDevices request)
@@ -114,7 +77,17 @@ public object Get(GetCameraUploads request)
public void Delete(DeleteDevice request)
{
- _deviceManager.DeleteDevice(request.Id);
+ var sessions = _authRepo.Get(new AuthenticationInfoQuery
+ {
+ DeviceId = request.Id,
+ IsActive = true
+
+ }).Items;
+
+ foreach (var session in sessions)
+ {
+ _sessionManager.Logout(session);
+ }
}
public Task Post(PostCameraUpload request)
diff --git a/MediaBrowser.Api/Library/LibraryService.cs b/MediaBrowser.Api/Library/LibraryService.cs
index 6bd993848c..46d136b481 100644
--- a/MediaBrowser.Api/Library/LibraryService.cs
+++ b/MediaBrowser.Api/Library/LibraryService.cs
@@ -802,7 +802,7 @@ public Task Get(GetDownload request)
var item = _libraryManager.GetItemById(request.Id);
var auth = _authContext.GetAuthorizationInfo(Request);
- var user = _userManager.GetUserById(auth.UserId);
+ var user = auth.User;
if (user != null)
{
@@ -1023,7 +1023,7 @@ public void Delete(DeleteItems request)
{
var item = _libraryManager.GetItemById(i);
var auth = _authContext.GetAuthorizationInfo(Request);
- var user = _userManager.GetUserById(auth.UserId);
+ var user = auth.User;
if (!item.CanDelete(user))
{
diff --git a/MediaBrowser.Api/MediaBrowser.Api.csproj b/MediaBrowser.Api/MediaBrowser.Api.csproj
index 199ac7ce94..b9e0282e68 100644
--- a/MediaBrowser.Api/MediaBrowser.Api.csproj
+++ b/MediaBrowser.Api/MediaBrowser.Api.csproj
@@ -105,13 +105,13 @@
- ..\packages\MediaBrowser.Common.3.3.50-beta\lib\netstandard2.0\MediaBrowser.Common.dll
+ ..\packages\MediaBrowser.Common.3.3.53-beta\lib\netstandard2.0\MediaBrowser.Common.dll
- ..\packages\MediaBrowser.Server.Core.3.3.50-beta\lib\netstandard2.0\MediaBrowser.Controller.dll
+ ..\packages\MediaBrowser.Server.Core.3.3.53-beta\lib\netstandard2.0\MediaBrowser.Controller.dll
- ..\packages\MediaBrowser.Common.3.3.50-beta\lib\netstandard2.0\MediaBrowser.Model.dll
+ ..\packages\MediaBrowser.Common.3.3.53-beta\lib\netstandard2.0\MediaBrowser.Model.dll
diff --git a/MediaBrowser.Api/Session/SessionsService.cs b/MediaBrowser.Api/Session/SessionsService.cs
index 4150a42f21..74ad88e7b2 100644
--- a/MediaBrowser.Api/Session/SessionsService.cs
+++ b/MediaBrowser.Api/Session/SessionsService.cs
@@ -27,6 +27,8 @@ public class GetSessions : IReturn
[ApiMember(Name = "DeviceId", Description = "Optional. Filter by device id.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
public string DeviceId { get; set; }
+
+ public int? ActiveWithinSeconds { get; set; }
}
///
@@ -199,9 +201,6 @@ public class PostCapabilities : IReturnVoid
[ApiMember(Name = "SupportedCommands", Description = "A list of supported remote control commands, comma delimited", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST")]
public string SupportedCommands { get; set; }
- [ApiMember(Name = "MessageCallbackUrl", Description = "A url to post messages to, including remote control commands.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST")]
- public string MessageCallbackUrl { get; set; }
-
[ApiMember(Name = "SupportsMediaControl", Description = "Determines whether media can be played remotely.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "POST")]
public bool SupportsMediaControl { get; set; }
@@ -211,8 +210,6 @@ public class PostCapabilities : IReturnVoid
[ApiMember(Name = "SupportsPersistentIdentifier", Description = "Determines whether the device supports a unique identifier.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "POST")]
public bool SupportsPersistentIdentifier { get; set; }
- public bool SupportsContentUploading { get; set; }
-
public PostCapabilities()
{
SupportsPersistentIdentifier = true;
@@ -367,6 +364,12 @@ public object Get(GetSessions request)
result = result.Where(i => !i.UserId.Equals(Guid.Empty));
}
+ if (request.ActiveWithinSeconds.HasValue && request.ActiveWithinSeconds.Value > 0)
+ {
+ var minActiveDate = DateTime.UtcNow.AddSeconds(0 - request.ActiveWithinSeconds.Value);
+ result = result.Where(i => i.LastActivityDate >= minActiveDate);
+ }
+
result = result.Where(i =>
{
var deviceId = i.DeviceId;
@@ -503,12 +506,8 @@ public void Post(PostCapabilities request)
SupportsMediaControl = request.SupportsMediaControl,
- MessageCallbackUrl = request.MessageCallbackUrl,
-
SupportsSync = request.SupportsSync,
- SupportsContentUploading = request.SupportsContentUploading,
-
SupportsPersistentIdentifier = request.SupportsPersistentIdentifier
});
}
diff --git a/MediaBrowser.Api/UserLibrary/BaseItemsRequest.cs b/MediaBrowser.Api/UserLibrary/BaseItemsRequest.cs
index 92538b91f8..c98d253a2e 100644
--- a/MediaBrowser.Api/UserLibrary/BaseItemsRequest.cs
+++ b/MediaBrowser.Api/UserLibrary/BaseItemsRequest.cs
@@ -276,6 +276,8 @@ protected BaseItemsRequest()
[ApiMember(Name = "ArtistIds", Description = "Optional. If specified, results will be filtered based on artist. This allows multiple, pipe delimeted.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
public string ArtistIds { get; set; }
+ public string AlbumArtistIds { get; set; }
+
[ApiMember(Name = "Albums", Description = "Optional. If specified, results will be filtered based on album. This allows multiple, pipe delimeted.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
public string Albums { get; set; }
diff --git a/MediaBrowser.Api/UserLibrary/ItemsService.cs b/MediaBrowser.Api/UserLibrary/ItemsService.cs
index dd28841955..6a66b06a4b 100644
--- a/MediaBrowser.Api/UserLibrary/ItemsService.cs
+++ b/MediaBrowser.Api/UserLibrary/ItemsService.cs
@@ -287,10 +287,13 @@ private InternalItemsQuery GetItemsQuery(GetItems request, DtoOptions dtoOptions
HasThemeSong = request.HasThemeSong,
HasThemeVideo = request.HasThemeVideo,
HasTrailer = request.HasTrailer,
+ IsHD = request.IsHD,
+ Is4K = request.Is4K,
Tags = request.GetTags(),
OfficialRatings = request.GetOfficialRatings(),
Genres = request.GetGenres(),
ArtistIds = GetGuids(request.ArtistIds),
+ AlbumArtistIds = GetGuids(request.AlbumArtistIds),
GenreIds = GetGuids(request.GenreIds),
StudioIds = GetGuids(request.StudioIds),
Person = request.Person,
@@ -307,38 +310,11 @@ private InternalItemsQuery GetItemsQuery(GetItems request, DtoOptions dtoOptions
MinCriticRating = request.MinCriticRating,
ParentId = string.IsNullOrWhiteSpace(request.ParentId) ? Guid.Empty : new Guid(request.ParentId),
ParentIndexNumber = request.ParentIndexNumber,
- AiredDuringSeason = request.AiredDuringSeason,
EnableTotalRecordCount = request.EnableTotalRecordCount,
ExcludeItemIds = GetGuids(request.ExcludeItemIds),
DtoOptions = dtoOptions
};
- if (request.IsHD.HasValue)
- {
- var threshold = 1200;
- if (request.IsHD.Value)
- {
- query.MinWidth = threshold;
- }
- else
- {
- query.MaxWidth = threshold - 1;
- }
- }
-
- if (request.Is4K.HasValue)
- {
- var threshold = 3800;
- if (request.Is4K.Value)
- {
- query.MinWidth = threshold;
- }
- else
- {
- query.MaxWidth = threshold - 1;
- }
- }
-
if (!string.IsNullOrWhiteSpace(request.Ids))
{
query.CollapseBoxSetItems = false;
diff --git a/MediaBrowser.Api/UserLibrary/UserLibraryService.cs b/MediaBrowser.Api/UserLibrary/UserLibraryService.cs
index dbcd61ec6a..bb92fad7d5 100644
--- a/MediaBrowser.Api/UserLibrary/UserLibraryService.cs
+++ b/MediaBrowser.Api/UserLibrary/UserLibraryService.cs
@@ -347,40 +347,12 @@ private BaseItemDto[] GetAsync(GetSpecialFeatures request)
_libraryManager.GetUserRootFolder() :
_libraryManager.GetItemById(request.Id);
- var series = item as Series;
-
- // Get them from the child tree
- if (series != null)
- {
- var dtoOptions = GetDtoOptions(_authContext, request);
-
- // Avoid implicitly captured closure
- var currentUser = user;
-
- var dtos = series
- .GetEpisodes(user, dtoOptions)
- .Where(i => i.ParentIndexNumber.HasValue && i.ParentIndexNumber.Value == 0)
- .Select(i => _dtoService.GetBaseItemDto(i, dtoOptions, currentUser));
-
- return dtos.ToArray();
- }
-
- var movie = item as IHasSpecialFeatures;
-
- // Get them from the db
- if (movie != null)
- {
- var dtoOptions = GetDtoOptions(_authContext, request);
-
- var dtos = movie.SpecialFeatureIds
- .Select(_libraryManager.GetItemById)
- .OrderBy(i => i.SortName)
- .Select(i => _dtoService.GetBaseItemDto(i, dtoOptions, user, item));
+ var dtoOptions = GetDtoOptions(_authContext, request);
- return dtos.ToArray();
- }
+ var dtos = item.GetDisplayExtras()
+ .Select(i => _dtoService.GetBaseItemDto(i, dtoOptions, user, item));
- return new BaseItemDto[] { };
+ return dtos.ToArray();
}
///
@@ -394,22 +366,9 @@ public object Get(GetLocalTrailers request)
var item = string.IsNullOrEmpty(request.Id) ? _libraryManager.GetUserRootFolder() : _libraryManager.GetItemById(request.Id);
- List trailerIds = null;
-
- var hasTrailers = item as IHasTrailers;
- if (hasTrailers != null)
- {
- trailerIds = hasTrailers.GetTrailerIds();
- }
- else
- {
- trailerIds = new List();
- }
-
var dtoOptions = GetDtoOptions(_authContext, request);
- var dtos = trailerIds
- .Select(_libraryManager.GetItemById)
+ var dtos = item.GetExtras(new[] { ExtraType.Trailer })
.Select(i => _dtoService.GetBaseItemDto(i, dtoOptions, user, item))
.ToArray();
@@ -507,7 +466,7 @@ public async Task Get(GetIntros request)
/// The request.
public object Post(MarkFavoriteItem request)
{
- var dto = MarkFavorite(request.UserId, request.Id, true);
+ var dto = MarkFavorite(request.UserId, request.Id, true);
return ToOptimizedResult(dto);
}
@@ -541,7 +500,7 @@ private UserItemDataDto MarkFavorite(Guid userId, Guid itemId, bool isFavorite)
// Set favorite status
data.IsFavorite = isFavorite;
- _userDataRepository.SaveUserData(user.Id, item, data, UserDataSaveReason.UpdateUserRating, CancellationToken.None);
+ _userDataRepository.SaveUserData(user.Id, item, data, UserDataSaveReason.UpdateUserRating, CancellationToken.None);
return _userDataRepository.GetUserDataDto(item, user);
}
@@ -563,7 +522,7 @@ public object Delete(DeleteUserItemRating request)
/// The request.
public object Post(UpdateUserItemRating request)
{
- var dto = UpdateUserItemRating(request.UserId, request.Id, request.Likes);
+ var dto = UpdateUserItemRating(request.UserId, request.Id, request.Likes);
return ToOptimizedResult(dto);
}
@@ -585,7 +544,7 @@ private UserItemDataDto UpdateUserItemRating(Guid userId, Guid itemId, bool? lik
data.Likes = likes;
- _userDataRepository.SaveUserData(user.Id, item, data, UserDataSaveReason.UpdateUserRating, CancellationToken.None);
+ _userDataRepository.SaveUserData(user.Id, item, data, UserDataSaveReason.UpdateUserRating, CancellationToken.None);
return _userDataRepository.GetUserDataDto(item, user);
}
diff --git a/MediaBrowser.Api/packages.config b/MediaBrowser.Api/packages.config
index 1c4aaf7ddf..c26580a70a 100644
--- a/MediaBrowser.Api/packages.config
+++ b/MediaBrowser.Api/packages.config
@@ -1,5 +1,5 @@
-
-
+
+
\ No newline at end of file
diff --git a/MediaBrowser.LocalMetadata/MediaBrowser.LocalMetadata.csproj b/MediaBrowser.LocalMetadata/MediaBrowser.LocalMetadata.csproj
index 3d4eaba3b9..68f8ce71d8 100644
--- a/MediaBrowser.LocalMetadata/MediaBrowser.LocalMetadata.csproj
+++ b/MediaBrowser.LocalMetadata/MediaBrowser.LocalMetadata.csproj
@@ -57,13 +57,13 @@
- ..\packages\MediaBrowser.Common.3.3.50-beta\lib\netstandard2.0\MediaBrowser.Common.dll
+ ..\packages\MediaBrowser.Common.3.3.53-beta\lib\netstandard2.0\MediaBrowser.Common.dll
- ..\packages\MediaBrowser.Server.Core.3.3.50-beta\lib\netstandard2.0\MediaBrowser.Controller.dll
+ ..\packages\MediaBrowser.Server.Core.3.3.53-beta\lib\netstandard2.0\MediaBrowser.Controller.dll
- ..\packages\MediaBrowser.Common.3.3.50-beta\lib\netstandard2.0\MediaBrowser.Model.dll
+ ..\packages\MediaBrowser.Common.3.3.53-beta\lib\netstandard2.0\MediaBrowser.Model.dll
diff --git a/MediaBrowser.LocalMetadata/Parsers/BaseItemXmlParser.cs b/MediaBrowser.LocalMetadata/Parsers/BaseItemXmlParser.cs
index 62c3c906cd..05874ec2cf 100644
--- a/MediaBrowser.LocalMetadata/Parsers/BaseItemXmlParser.cs
+++ b/MediaBrowser.LocalMetadata/Parsers/BaseItemXmlParser.cs
@@ -450,13 +450,9 @@ protected virtual void FetchDataFromXmlNode(XmlReader reader, MetadataResult
{
var val = reader.ReadElementContentAsString();
- var hasTrailers = item as IHasTrailers;
- if (hasTrailers != null)
+ if (!string.IsNullOrWhiteSpace(val))
{
- if (!string.IsNullOrWhiteSpace(val))
- {
- hasTrailers.AddTrailerUrl(val);
- }
+ item.AddTrailerUrl(val);
}
break;
}
@@ -482,11 +478,7 @@ protected virtual void FetchDataFromXmlNode(XmlReader reader, MetadataResult
{
using (var subtree = reader.ReadSubtree())
{
- var hasTrailers = item as IHasTrailers;
- if (hasTrailers != null)
- {
- FetchDataFromTrailersNode(subtree, hasTrailers);
- }
+ FetchDataFromTrailersNode(subtree, item);
}
}
else
@@ -1007,7 +999,7 @@ private void FetchDataFromPersonsNode(XmlReader reader, MetadataResult item)
}
}
- private void FetchDataFromTrailersNode(XmlReader reader, IHasTrailers item)
+ private void FetchDataFromTrailersNode(XmlReader reader, T item)
{
reader.MoveToContent();
reader.Read();
diff --git a/MediaBrowser.LocalMetadata/Savers/BaseXmlSaver.cs b/MediaBrowser.LocalMetadata/Savers/BaseXmlSaver.cs
index 5e2e56450a..81622f54c5 100644
--- a/MediaBrowser.LocalMetadata/Savers/BaseXmlSaver.cs
+++ b/MediaBrowser.LocalMetadata/Savers/BaseXmlSaver.cs
@@ -251,20 +251,16 @@ public static void AddCommonNodes(BaseItem item, XmlWriter writer, ILibraryManag
}
}
- var hasTrailers = item as IHasTrailers;
- if (hasTrailers != null)
+ if (item.RemoteTrailers.Length > 0)
{
- if (hasTrailers.RemoteTrailers.Length > 0)
- {
- writer.WriteStartElement("Trailers");
-
- foreach (var trailer in hasTrailers.RemoteTrailers)
- {
- writer.WriteElementString("Trailer", trailer.Url);
- }
+ writer.WriteStartElement("Trailers");
- writer.WriteEndElement();
+ foreach (var trailer in item.RemoteTrailers)
+ {
+ writer.WriteElementString("Trailer", trailer.Url);
}
+
+ writer.WriteEndElement();
}
if (item.ProductionLocations.Length > 0)
diff --git a/MediaBrowser.LocalMetadata/packages.config b/MediaBrowser.LocalMetadata/packages.config
index 1c4aaf7ddf..c26580a70a 100644
--- a/MediaBrowser.LocalMetadata/packages.config
+++ b/MediaBrowser.LocalMetadata/packages.config
@@ -1,5 +1,5 @@
-
-
+
+
\ No newline at end of file
diff --git a/MediaBrowser.Providers/Manager/ProviderManager.cs b/MediaBrowser.Providers/Manager/ProviderManager.cs
index 1e13b6565c..4c9312b83b 100644
--- a/MediaBrowser.Providers/Manager/ProviderManager.cs
+++ b/MediaBrowser.Providers/Manager/ProviderManager.cs
@@ -309,17 +309,17 @@ public IEnumerable> GetMetadataProviders(BaseItem item,
{
var globalMetadataOptions = GetMetadataOptions(item);
- return GetMetadataProvidersInternal(item, libraryOptions, globalMetadataOptions, false, false, true);
+ return GetMetadataProvidersInternal(item, libraryOptions, globalMetadataOptions, false, false);
}
- private IEnumerable> GetMetadataProvidersInternal(BaseItem item, LibraryOptions libraryOptions, MetadataOptions globalMetadataOptions, bool includeDisabled, bool forceEnableInternetMetadata, bool checkIsOwnedItem)
+ private IEnumerable> GetMetadataProvidersInternal(BaseItem item, LibraryOptions libraryOptions, MetadataOptions globalMetadataOptions, bool includeDisabled, bool forceEnableInternetMetadata)
where T : BaseItem
{
// Avoid implicitly captured closure
var currentOptions = globalMetadataOptions;
return _metadataProviders.OfType>()
- .Where(i => CanRefresh(i, item, libraryOptions, currentOptions, includeDisabled, forceEnableInternetMetadata, checkIsOwnedItem))
+ .Where(i => CanRefresh(i, item, libraryOptions, currentOptions, includeDisabled, forceEnableInternetMetadata))
.OrderBy(i => GetConfiguredOrder(item, i, libraryOptions, globalMetadataOptions))
.ThenBy(GetDefaultOrder);
}
@@ -332,7 +332,7 @@ private IEnumerable GetRemoteImageProviders(BaseItem item,
return GetImageProviders(item, libraryOptions, options, new ImageRefreshOptions(new DirectoryService(_logger, _fileSystem)), includeDisabled).OfType();
}
- private bool CanRefresh(IMetadataProvider provider, BaseItem item, LibraryOptions libraryOptions, MetadataOptions options, bool includeDisabled, bool forceEnableInternetMetadata, bool checkIsOwnedItem)
+ private bool CanRefresh(IMetadataProvider provider, BaseItem item, LibraryOptions libraryOptions, MetadataOptions options, bool includeDisabled, bool forceEnableInternetMetadata)
{
if (!includeDisabled)
{
@@ -357,9 +357,9 @@ private bool CanRefresh(IMetadataProvider provider, BaseItem item, LibraryOption
}
// If this restriction is ever lifted, movie xml providers will have to be updated to prevent owned items like trailers from reading those files
- if (checkIsOwnedItem && item.ExtraType.HasValue)
+ if (!item.OwnerId.Equals(Guid.Empty))
{
- if (provider is ILocalMetadataProvider)
+ if (provider is ILocalMetadataProvider || provider is IRemoteMetadataProvider)
{
return false;
}
@@ -539,7 +539,7 @@ private MetadataPluginSummary GetPluginSummary()
private void AddMetadataPlugins(List list, T item, LibraryOptions libraryOptions, MetadataOptions options)
where T : BaseItem
{
- var providers = GetMetadataProvidersInternal(item, libraryOptions, options, true, true, false).ToList();
+ var providers = GetMetadataProvidersInternal(item, libraryOptions, options, true, true).ToList();
// Locals
list.AddRange(providers.Where(i => (i is ILocalMetadataProvider)).Select(i => new MetadataPlugin
@@ -769,7 +769,7 @@ public async Task> GetRemoteSearchResults(referenceItem, libraryOptions, options, searchInfo.IncludeDisabledProviders, false, false)
+ var providers = GetMetadataProvidersInternal(referenceItem, libraryOptions, options, searchInfo.IncludeDisabledProviders, false)
.OfType>();
if (!string.IsNullOrEmpty(searchInfo.SearchProviderName))
diff --git a/MediaBrowser.Providers/Manager/ProviderUtils.cs b/MediaBrowser.Providers/Manager/ProviderUtils.cs
index 30ecf5e9b8..3a961fe0ec 100644
--- a/MediaBrowser.Providers/Manager/ProviderUtils.cs
+++ b/MediaBrowser.Providers/Manager/ProviderUtils.cs
@@ -274,15 +274,9 @@ private static void MergeCriticRating(BaseItem source, BaseItem target, Metadata
private static void MergeTrailers(BaseItem source, BaseItem target, MetadataFields[] lockedFields, bool replaceData)
{
- var sourceCast = source as IHasTrailers;
- var targetCast = target as IHasTrailers;
-
- if (sourceCast != null && targetCast != null)
+ if (replaceData || target.RemoteTrailers.Length == 0)
{
- if (replaceData || targetCast.RemoteTrailers.Length == 0)
- {
- targetCast.RemoteTrailers = sourceCast.RemoteTrailers;
- }
+ target.RemoteTrailers = source.RemoteTrailers;
}
}
diff --git a/MediaBrowser.Providers/MediaBrowser.Providers.csproj b/MediaBrowser.Providers/MediaBrowser.Providers.csproj
index 9b837ce995..2698d3d96d 100644
--- a/MediaBrowser.Providers/MediaBrowser.Providers.csproj
+++ b/MediaBrowser.Providers/MediaBrowser.Providers.csproj
@@ -140,13 +140,13 @@
- ..\packages\MediaBrowser.Common.3.3.50-beta\lib\netstandard2.0\MediaBrowser.Common.dll
+ ..\packages\MediaBrowser.Common.3.3.53-beta\lib\netstandard2.0\MediaBrowser.Common.dll
- ..\packages\MediaBrowser.Server.Core.3.3.50-beta\lib\netstandard2.0\MediaBrowser.Controller.dll
+ ..\packages\MediaBrowser.Server.Core.3.3.53-beta\lib\netstandard2.0\MediaBrowser.Controller.dll
- ..\packages\MediaBrowser.Common.3.3.50-beta\lib\netstandard2.0\MediaBrowser.Model.dll
+ ..\packages\MediaBrowser.Common.3.3.53-beta\lib\netstandard2.0\MediaBrowser.Model.dll
..\packages\Microsoft.Win32.Primitives.4.3.0\lib\net46\Microsoft.Win32.Primitives.dll
@@ -241,7 +241,7 @@
True
- ..\packages\System.Runtime.CompilerServices.Unsafe.4.5.0\lib\netstandard2.0\System.Runtime.CompilerServices.Unsafe.dll
+ ..\packages\System.Runtime.CompilerServices.Unsafe.4.5.1\lib\netstandard2.0\System.Runtime.CompilerServices.Unsafe.dll
..\packages\System.Runtime.Extensions.4.3.0\lib\net462\System.Runtime.Extensions.dll
diff --git a/MediaBrowser.Providers/Movies/GenericMovieDbInfo.cs b/MediaBrowser.Providers/Movies/GenericMovieDbInfo.cs
index efd9cd2dad..8a409f9cfe 100644
--- a/MediaBrowser.Providers/Movies/GenericMovieDbInfo.cs
+++ b/MediaBrowser.Providers/Movies/GenericMovieDbInfo.cs
@@ -305,19 +305,14 @@ private void ProcessMainInfo(MetadataResult resultItem, TmdbSettingsResult se
// movie.Keywords = movieData.keywords.keywords.Select(i => i.name).ToList();
//}
- if (movieData.trailers != null && movieData.trailers.youtube != null &&
- movieData.trailers.youtube.Count > 0)
+ if (movieData.trailers != null && movieData.trailers.youtube != null)
{
- var hasTrailers = movie as IHasTrailers;
- if (hasTrailers != null)
+ movie.RemoteTrailers = movieData.trailers.youtube.Select(i => new MediaUrl
{
- hasTrailers.RemoteTrailers = movieData.trailers.youtube.Select(i => new MediaUrl
- {
- Url = string.Format("https://www.youtube.com/watch?v={0}", i.source),
- Name = i.name
+ Url = string.Format("https://www.youtube.com/watch?v={0}", i.source),
+ Name = i.name
- }).ToArray();
- }
+ }).ToArray();
}
}
diff --git a/MediaBrowser.Providers/packages.config b/MediaBrowser.Providers/packages.config
index a913db587a..4456c940e3 100644
--- a/MediaBrowser.Providers/packages.config
+++ b/MediaBrowser.Providers/packages.config
@@ -1,7 +1,7 @@
-
-
+
+
@@ -32,7 +32,7 @@
-
+
diff --git a/MediaBrowser.Server.Mono/MediaBrowser.Server.Mono.csproj b/MediaBrowser.Server.Mono/MediaBrowser.Server.Mono.csproj
index 3bc2ddfe7d..8ea812e8db 100644
--- a/MediaBrowser.Server.Mono/MediaBrowser.Server.Mono.csproj
+++ b/MediaBrowser.Server.Mono/MediaBrowser.Server.Mono.csproj
@@ -51,20 +51,19 @@
..\packages\Emby.XmlTv.1.0.14\lib\portable-net45+netstandard2.0+win8\Emby.XmlTv.dll
- ..\packages\MediaBrowser.Common.3.3.50-beta\lib\netstandard2.0\MediaBrowser.Common.dll
+ ..\packages\MediaBrowser.Common.3.3.53-beta\lib\netstandard2.0\MediaBrowser.Common.dll
- ..\packages\MediaBrowser.Server.Core.3.3.50-beta\lib\netstandard2.0\MediaBrowser.Controller.dll
+ ..\packages\MediaBrowser.Server.Core.3.3.53-beta\lib\netstandard2.0\MediaBrowser.Controller.dll
- ..\packages\MediaBrowser.Common.3.3.50-beta\lib\netstandard2.0\MediaBrowser.Model.dll
+ ..\packages\MediaBrowser.Common.3.3.53-beta\lib\netstandard2.0\MediaBrowser.Model.dll
-
- ..\packages\ServiceStack.Text.4.5.8\lib\net45\ServiceStack.Text.dll
- True
+
+ ..\packages\ServiceStack.Text.5.1.0\lib\net45\ServiceStack.Text.dll
-
- ..\packages\SharpCompress.0.18.2\lib\net45\SharpCompress.dll
+
+ ..\packages\SharpCompress.0.21.1\lib\net45\SharpCompress.dll
..\packages\SimpleInjector.4.3.0\lib\net45\SimpleInjector.dll
@@ -87,12 +86,9 @@
..\packages\System.Numerics.Vectors.4.5.0\lib\net46\System.Numerics.Vectors.dll
- ..\packages\System.Runtime.CompilerServices.Unsafe.4.5.0\lib\netstandard2.0\System.Runtime.CompilerServices.Unsafe.dll
+ ..\packages\System.Runtime.CompilerServices.Unsafe.4.5.1\lib\netstandard2.0\System.Runtime.CompilerServices.Unsafe.dll
-
- ..\packages\System.Threading.Tasks.Extensions.4.5.0\lib\netstandard2.0\System.Threading.Tasks.Extensions.dll
-
diff --git a/MediaBrowser.Server.Mono/Program.cs b/MediaBrowser.Server.Mono/Program.cs
index a445a0f799..8a01163440 100644
--- a/MediaBrowser.Server.Mono/Program.cs
+++ b/MediaBrowser.Server.Mono/Program.cs
@@ -98,7 +98,7 @@ private static void RunApplication(ServerApplicationPaths appPaths, ILogManager
var environmentInfo = GetEnvironmentInfo(options);
- var fileSystem = new ManagedFileSystem(logManager.GetLogger("FileSystem"), environmentInfo, null, appPaths.TempDirectory);
+ var fileSystem = new ManagedFileSystem(logManager.GetLogger("FileSystem"), environmentInfo, null, appPaths.TempDirectory, true);
FileSystem = fileSystem;
diff --git a/MediaBrowser.Server.Mono/packages.config b/MediaBrowser.Server.Mono/packages.config
index f374e88bbd..cd97f1d94e 100644
--- a/MediaBrowser.Server.Mono/packages.config
+++ b/MediaBrowser.Server.Mono/packages.config
@@ -1,15 +1,14 @@
-
-
-
-
+
+
+
+
-
-
+
\ No newline at end of file
diff --git a/MediaBrowser.ServerApplication/MainStartup.cs b/MediaBrowser.ServerApplication/MainStartup.cs
index 682db6d062..cfd8e9c125 100644
--- a/MediaBrowser.ServerApplication/MainStartup.cs
+++ b/MediaBrowser.ServerApplication/MainStartup.cs
@@ -330,7 +330,7 @@ private static void RunApplication(ServerApplicationPaths appPaths, ILogManager
{
var environmentInfo = new EnvironmentInfo();
- var fileSystem = new ManagedFileSystem(logManager.GetLogger("FileSystem"), environmentInfo, null, appPaths.TempDirectory);
+ var fileSystem = new ManagedFileSystem(logManager.GetLogger("FileSystem"), environmentInfo, null, appPaths.TempDirectory, false);
FileSystem = fileSystem;
diff --git a/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj b/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj
index 54afca95d6..70d97a4e6b 100644
--- a/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj
+++ b/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj
@@ -77,20 +77,19 @@
..\packages\Emby.XmlTv.1.0.14\lib\portable-net45+netstandard2.0+win8\Emby.XmlTv.dll
- ..\packages\MediaBrowser.Common.3.3.50-beta\lib\netstandard2.0\MediaBrowser.Common.dll
+ ..\packages\MediaBrowser.Common.3.3.53-beta\lib\netstandard2.0\MediaBrowser.Common.dll
- ..\packages\MediaBrowser.Server.Core.3.3.50-beta\lib\netstandard2.0\MediaBrowser.Controller.dll
+ ..\packages\MediaBrowser.Server.Core.3.3.53-beta\lib\netstandard2.0\MediaBrowser.Controller.dll
- ..\packages\MediaBrowser.Common.3.3.50-beta\lib\netstandard2.0\MediaBrowser.Model.dll
+ ..\packages\MediaBrowser.Common.3.3.53-beta\lib\netstandard2.0\MediaBrowser.Model.dll
-
- ..\packages\ServiceStack.Text.4.5.8\lib\net45\ServiceStack.Text.dll
- True
+
+ ..\packages\ServiceStack.Text.5.1.0\lib\net45\ServiceStack.Text.dll
-
- ..\packages\SharpCompress.0.18.2\lib\net45\SharpCompress.dll
+
+ ..\packages\SharpCompress.0.21.1\lib\net45\SharpCompress.dll
..\packages\SimpleInjector.4.3.0\lib\net45\SimpleInjector.dll
@@ -116,13 +115,10 @@
..\packages\System.Numerics.Vectors.4.5.0\lib\net46\System.Numerics.Vectors.dll
- ..\packages\System.Runtime.CompilerServices.Unsafe.4.5.0\lib\netstandard2.0\System.Runtime.CompilerServices.Unsafe.dll
+ ..\packages\System.Runtime.CompilerServices.Unsafe.4.5.1\lib\netstandard2.0\System.Runtime.CompilerServices.Unsafe.dll
-
- ..\packages\System.Threading.Tasks.Extensions.4.5.0\lib\netstandard2.0\System.Threading.Tasks.Extensions.dll
-
diff --git a/MediaBrowser.ServerApplication/packages.config b/MediaBrowser.ServerApplication/packages.config
index 2b15095326..34cd2e9548 100644
--- a/MediaBrowser.ServerApplication/packages.config
+++ b/MediaBrowser.ServerApplication/packages.config
@@ -1,15 +1,14 @@
-
-
-
-
+
+
+
+
-
-
+
\ No newline at end of file
diff --git a/MediaBrowser.Tests/MediaBrowser.Tests.csproj b/MediaBrowser.Tests/MediaBrowser.Tests.csproj
index 583740b01e..2ae356a178 100644
--- a/MediaBrowser.Tests/MediaBrowser.Tests.csproj
+++ b/MediaBrowser.Tests/MediaBrowser.Tests.csproj
@@ -41,13 +41,13 @@
..\ThirdParty\emby\Emby.Server.MediaEncoding.dll
- ..\packages\MediaBrowser.Common.3.3.50-beta\lib\netstandard2.0\MediaBrowser.Common.dll
+ ..\packages\MediaBrowser.Common.3.3.53-beta\lib\netstandard2.0\MediaBrowser.Common.dll
- ..\packages\MediaBrowser.Server.Core.3.3.50-beta\lib\netstandard2.0\MediaBrowser.Controller.dll
+ ..\packages\MediaBrowser.Server.Core.3.3.53-beta\lib\netstandard2.0\MediaBrowser.Controller.dll
- ..\packages\MediaBrowser.Common.3.3.50-beta\lib\netstandard2.0\MediaBrowser.Model.dll
+ ..\packages\MediaBrowser.Common.3.3.53-beta\lib\netstandard2.0\MediaBrowser.Model.dll
diff --git a/MediaBrowser.Tests/packages.config b/MediaBrowser.Tests/packages.config
index 1c4aaf7ddf..c26580a70a 100644
--- a/MediaBrowser.Tests/packages.config
+++ b/MediaBrowser.Tests/packages.config
@@ -1,5 +1,5 @@
-
-
+
+
\ No newline at end of file
diff --git a/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj b/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj
index c8a17ddeca..74b7c491b4 100644
--- a/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj
+++ b/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj
@@ -46,13 +46,13 @@
- ..\packages\MediaBrowser.Common.3.3.50-beta\lib\netstandard2.0\MediaBrowser.Common.dll
+ ..\packages\MediaBrowser.Common.3.3.53-beta\lib\netstandard2.0\MediaBrowser.Common.dll
- ..\packages\MediaBrowser.Server.Core.3.3.50-beta\lib\netstandard2.0\MediaBrowser.Controller.dll
+ ..\packages\MediaBrowser.Server.Core.3.3.53-beta\lib\netstandard2.0\MediaBrowser.Controller.dll
- ..\packages\MediaBrowser.Common.3.3.50-beta\lib\netstandard2.0\MediaBrowser.Model.dll
+ ..\packages\MediaBrowser.Common.3.3.53-beta\lib\netstandard2.0\MediaBrowser.Model.dll
diff --git a/MediaBrowser.WebDashboard/dashboard-ui/bower_components/emby-apiclient/sync/mediasync.js b/MediaBrowser.WebDashboard/dashboard-ui/bower_components/emby-apiclient/sync/mediasync.js
index 2df2de801c..fd2ae5306d 100644
--- a/MediaBrowser.WebDashboard/dashboard-ui/bower_components/emby-apiclient/sync/mediasync.js
+++ b/MediaBrowser.WebDashboard/dashboard-ui/bower_components/emby-apiclient/sync/mediasync.js
@@ -1 +1 @@
-define(["localassetmanager"],function(localassetmanager){"use strict";function processDownloadStatus(apiClient,serverInfo,options){return console.log("[mediasync] Begin processDownloadStatus"),localassetmanager.resyncTransfers().then(function(){return localassetmanager.getServerItems(serverInfo.Id).then(function(items){console.log("[mediasync] Begin processDownloadStatus getServerItems completed");var p=Promise.resolve(),cnt=0;return items.filter(function(item){return"transferring"===item.SyncStatus||"queued"===item.SyncStatus}).forEach(function(item){p=p.then(function(){return reportTransfer(apiClient,item)}),cnt++}),p.then(function(){return console.log("[mediasync] Exit processDownloadStatus. Items reported: "+cnt.toString()),Promise.resolve()})})})}function reportTransfer(apiClient,item){return localassetmanager.getItemFileSize(item.LocalPath).then(function(size){return size>0?apiClient.reportSyncJobItemTransferred(item.SyncJobItemId).then(function(){return item.SyncStatus="synced",localassetmanager.addOrUpdateLocalItem(item)},function(error){return console.error("[mediasync] Mediasync error on reportSyncJobItemTransferred",error),item.SyncStatus="error",localassetmanager.addOrUpdateLocalItem(item)}):localassetmanager.isDownloadFileInQueue(item.LocalPath).then(function(result){return result?Promise.resolve():(console.log("[mediasync] reportTransfer: Size is 0 and download no longer in queue. Deleting item."),localassetmanager.removeLocalItem(item).then(function(){return console.log("[mediasync] reportTransfer: Item deleted."),Promise.resolve()},function(err2){return console.log("[mediasync] reportTransfer: Failed to delete item.",err2),Promise.resolve()}))})},function(error){return console.error("[mediasync] reportTransfer: error on getItemFileSize. Deleting item.",error),localassetmanager.removeLocalItem(item).then(function(){return console.log("[mediasync] reportTransfer: Item deleted."),Promise.resolve()},function(err2){return console.log("[mediasync] reportTransfer: Failed to delete item.",err2),Promise.resolve()})})}function reportOfflineActions(apiClient,serverInfo){return console.log("[mediasync] Begin reportOfflineActions"),localassetmanager.getUserActions(serverInfo.Id).then(function(actions){return actions.length?apiClient.reportOfflineActions(actions).then(function(){return localassetmanager.deleteUserActions(actions).then(function(){return console.log("[mediasync] Exit reportOfflineActions (actions reported and deleted.)"),Promise.resolve()})},function(err){return console.error("[mediasync] error on apiClient.reportOfflineActions: "+err.toString()),localassetmanager.deleteUserActions(actions)}):(console.log("[mediasync] Exit reportOfflineActions (no actions)"),Promise.resolve())})}function syncData(apiClient,serverInfo){return console.log("[mediasync] Begin syncData"),localassetmanager.getServerItems(serverInfo.Id).then(function(items){var completedItems=items.filter(function(item){return item&&("synced"===item.SyncStatus||"error"===item.SyncStatus)}),request={TargetId:apiClient.deviceId(),LocalItemIds:completedItems.map(function(xitem){return xitem.ItemId})};return apiClient.syncData(request).then(function(result){return afterSyncData(apiClient,serverInfo,result).then(function(){return console.log("[mediasync] Exit syncData"),Promise.resolve()},function(err){return console.error("[mediasync] Error in syncData: "+err.toString()),Promise.resolve()})})})}function afterSyncData(apiClient,serverInfo,syncDataResult){console.log("[mediasync] Begin afterSyncData");var p=Promise.resolve();return syncDataResult.ItemIdsToRemove&&syncDataResult.ItemIdsToRemove.length>0&&syncDataResult.ItemIdsToRemove.forEach(function(itemId){p=p.then(function(){return removeLocalItem(itemId,serverInfo.Id)})}),p=p.then(function(){return removeObsoleteContainerItems(serverInfo.Id)}),p.then(function(){return console.log("[mediasync] Exit afterSyncData"),Promise.resolve()})}function removeObsoleteContainerItems(serverId){return console.log("[mediasync] Begin removeObsoleteContainerItems"),localassetmanager.removeObsoleteContainerItems(serverId)}function removeLocalItem(itemId,serverId){return console.log("[mediasync] Begin removeLocalItem"),localassetmanager.getLocalItem(serverId,itemId).then(function(item){return item?localassetmanager.removeLocalItem(item):Promise.resolve()})}function getNewMedia(apiClient,downloadCount){return console.log("[mediasync] Begin getNewMedia"),apiClient.getReadySyncItems(apiClient.deviceId()).then(function(jobItems){var p=Promise.resolve(),currentCount=downloadCount;return jobItems.forEach(function(jobItem){currentCount++<=10&&(p=p.then(function(){return getNewItem(jobItem,apiClient)}))}),p.then(function(){return console.log("[mediasync] Exit getNewMedia"),Promise.resolve()})})}function afterMediaDownloaded(apiClient,jobItem,localItem){return console.log("[mediasync] Begin afterMediaDownloaded"),getImages(apiClient,jobItem,localItem).then(function(){var libraryItem=jobItem.Item;return downloadParentItems(apiClient,jobItem,libraryItem).then(function(){return getSubtitles(apiClient,jobItem,localItem)})})}function createLocalItem(libraryItem,jobItem){console.log("[localassetmanager] Begin createLocalItem");var item={Item:libraryItem,ItemId:libraryItem.Id,ServerId:libraryItem.ServerId,Id:libraryItem.Id};return jobItem&&(item.SyncJobItemId=jobItem.SyncJobItemId),console.log("[localassetmanager] End createLocalItem"),item}function getNewItem(jobItem,apiClient){console.log("[mediasync] Begin getNewItem");var libraryItem=jobItem.Item;return localassetmanager.getLocalItem(libraryItem.ServerId,libraryItem.Id).then(function(existingItem){if(existingItem&&("queued"===existingItem.SyncStatus||"transferring"===existingItem.SyncStatus||"synced"===existingItem.SyncStatus)&&(console.log("[mediasync] getNewItem: getLocalItem found existing item"),localassetmanager.enableBackgroundCompletion()))return afterMediaDownloaded(apiClient,jobItem,existingItem);libraryItem.CanDelete=!1,libraryItem.CanDownload=!1,libraryItem.SupportsSync=!1,libraryItem.People=[],libraryItem.Chapters=[],libraryItem.Studios=[],libraryItem.SpecialFeatureCount=null,libraryItem.LocalTrailerCount=null,libraryItem.RemoteTrailers=[];var localItem=createLocalItem(libraryItem,jobItem);return localItem.SyncStatus="queued",downloadMedia(apiClient,jobItem,localItem)})}function downloadParentItems(apiClient,jobItem,libraryItem){var p=Promise.resolve();return libraryItem.SeriesId&&(p=p.then(function(){return downloadItem(apiClient,libraryItem.SeriesId)})),libraryItem.SeasonId&&(p=p.then(function(){return downloadItem(apiClient,libraryItem.SeasonId).then(function(seasonItem){return libraryItem.SeasonPrimaryImageTag=(seasonItem.Item.ImageTags||{}).Primary,Promise.resolve()})})),libraryItem.AlbumId&&(p=p.then(function(){return downloadItem(apiClient,libraryItem.AlbumId)})),p}function downloadItem(apiClient,itemId){return apiClient.getItem(apiClient.getCurrentUserId(),itemId).then(function(downloadedItem){downloadedItem.CanDelete=!1,downloadedItem.CanDownload=!1,downloadedItem.SupportsSync=!1,downloadedItem.People=[],downloadedItem.SpecialFeatureCount=null,downloadedItem.BackdropImageTags=null,downloadedItem.ParentBackdropImageTags=null,downloadedItem.ParentArtImageTag=null,downloadedItem.ParentLogoImageTag=null;var localItem=createLocalItem(downloadedItem,null);return localassetmanager.addOrUpdateLocalItem(localItem).then(function(){return Promise.resolve(localItem)},function(err){return console.error("[mediasync] downloadItem failed: "+err.toString()),Promise.resolve(null)})})}function ensureLocalPathParts(localItem,jobItem){if(!localItem.LocalPathParts){var libraryItem=localItem.Item,parts=localassetmanager.getDirectoryPath(libraryItem);parts.push(localassetmanager.getLocalFileName(libraryItem,jobItem.OriginalFileName)),localItem.LocalPathParts=parts}}function downloadMedia(apiClient,jobItem,localItem){var url=apiClient.getUrl("Sync/JobItems/"+jobItem.SyncJobItemId+"/File",{api_key:apiClient.accessToken()});return ensureLocalPathParts(localItem,jobItem),localassetmanager.downloadFile(url,localItem).then(function(result){console.log("[mediasync] downloadMedia: localassetmanager.downloadFile returned.");var localPath=result.path,libraryItem=localItem.Item;if(localPath&&libraryItem.MediaSources)for(var i=0;i2?Promise.resolve():reportOfflineActions(apiClient,serverInfo).then(function(){return getNewMedia(apiClient,downloadCount).then(function(){return syncData(apiClient,serverInfo).then(function(){return console.log("[mediasync]************************************* Exit sync"),Promise.resolve()})})})})})},function(err){console.error(err.toString())})}:self.sync=function(apiClient,serverInfo,options){return console.log("[mediasync]************************************* Start sync"),checkLocalFileExistence(apiClient,serverInfo,options).then(function(){return syncData(apiClient,serverInfo).then(function(){return processDownloadStatus(apiClient,serverInfo,options).then(function(){return localassetmanager.getDownloadItemCount().then(function(downloadCount){return!0===options.syncCheckProgressOnly&&downloadCount>2?Promise.resolve():reportOfflineActions(apiClient,serverInfo).then(function(){return getNewMedia(apiClient,downloadCount).then(function(){return syncData(apiClient,serverInfo)})})})})})},function(err){console.error(err.toString())})}}});
\ No newline at end of file
+define(["localassetmanager"],function(localassetmanager){"use strict";function processDownloadStatus(apiClient,serverInfo,options){return console.log("[mediasync] Begin processDownloadStatus"),localassetmanager.resyncTransfers().then(function(){return localassetmanager.getServerItems(serverInfo.Id).then(function(items){console.log("[mediasync] Begin processDownloadStatus getServerItems completed");var p=Promise.resolve(),cnt=0;return items.filter(function(item){return"transferring"===item.SyncStatus||"queued"===item.SyncStatus}).forEach(function(item){p=p.then(function(){return reportTransfer(apiClient,item)}),cnt++}),p.then(function(){return console.log("[mediasync] Exit processDownloadStatus. Items reported: "+cnt.toString()),Promise.resolve()})})})}function reportTransfer(apiClient,item){return localassetmanager.getItemFileSize(item.LocalPath).then(function(size){return size>0?apiClient.reportSyncJobItemTransferred(item.SyncJobItemId).then(function(){return item.SyncStatus="synced",localassetmanager.addOrUpdateLocalItem(item)},function(error){return console.error("[mediasync] Mediasync error on reportSyncJobItemTransferred",error),item.SyncStatus="error",localassetmanager.addOrUpdateLocalItem(item)}):localassetmanager.isDownloadFileInQueue(item.LocalPath).then(function(result){return result?Promise.resolve():(console.log("[mediasync] reportTransfer: Size is 0 and download no longer in queue. Deleting item."),localassetmanager.removeLocalItem(item).then(function(){return console.log("[mediasync] reportTransfer: Item deleted."),Promise.resolve()},function(err2){return console.log("[mediasync] reportTransfer: Failed to delete item.",err2),Promise.resolve()}))})},function(error){return console.error("[mediasync] reportTransfer: error on getItemFileSize. Deleting item.",error),localassetmanager.removeLocalItem(item).then(function(){return console.log("[mediasync] reportTransfer: Item deleted."),Promise.resolve()},function(err2){return console.log("[mediasync] reportTransfer: Failed to delete item.",err2),Promise.resolve()})})}function reportOfflineActions(apiClient,serverInfo){return console.log("[mediasync] Begin reportOfflineActions"),localassetmanager.getUserActions(serverInfo.Id).then(function(actions){return actions.length?apiClient.reportOfflineActions(actions).then(function(){return localassetmanager.deleteUserActions(actions).then(function(){return console.log("[mediasync] Exit reportOfflineActions (actions reported and deleted.)"),Promise.resolve()})},function(err){return console.error("[mediasync] error on apiClient.reportOfflineActions: "+err.toString()),localassetmanager.deleteUserActions(actions)}):(console.log("[mediasync] Exit reportOfflineActions (no actions)"),Promise.resolve())})}function syncData(apiClient,serverInfo){return console.log("[mediasync] Begin syncData"),localassetmanager.getServerItems(serverInfo.Id).then(function(items){var completedItems=items.filter(function(item){return item&&("synced"===item.SyncStatus||"error"===item.SyncStatus)}),request={TargetId:apiClient.deviceId(),LocalItemIds:completedItems.map(function(xitem){return xitem.ItemId})};return apiClient.syncData(request).then(function(result){return afterSyncData(apiClient,serverInfo,result).then(function(){return console.log("[mediasync] Exit syncData"),Promise.resolve()},function(err){return console.error("[mediasync] Error in syncData: "+err.toString()),Promise.resolve()})})})}function afterSyncData(apiClient,serverInfo,syncDataResult){console.log("[mediasync] Begin afterSyncData");var p=Promise.resolve();return syncDataResult.ItemIdsToRemove&&syncDataResult.ItemIdsToRemove.length>0&&syncDataResult.ItemIdsToRemove.forEach(function(itemId){p=p.then(function(){return removeLocalItem(itemId,serverInfo.Id)})}),p=p.then(function(){return removeObsoleteContainerItems(serverInfo.Id)}),p.then(function(){return console.log("[mediasync] Exit afterSyncData"),Promise.resolve()})}function removeObsoleteContainerItems(serverId){return console.log("[mediasync] Begin removeObsoleteContainerItems"),localassetmanager.removeObsoleteContainerItems(serverId)}function removeLocalItem(itemId,serverId){return console.log("[mediasync] Begin removeLocalItem"),localassetmanager.getLocalItem(serverId,itemId).then(function(item){return item?localassetmanager.removeLocalItem(item):Promise.resolve()})}function getNewMedia(apiClient,downloadCount){return console.log("[mediasync] Begin getNewMedia"),apiClient.getReadySyncItems(apiClient.deviceId()).then(function(jobItems){var p=Promise.resolve(),currentCount=downloadCount;return jobItems.forEach(function(jobItem){currentCount++<=10&&(p=p.then(function(){return getNewItem(jobItem,apiClient)}))}),p.then(function(){return console.log("[mediasync] Exit getNewMedia"),Promise.resolve()})})}function afterMediaDownloaded(apiClient,jobItem,localItem){return console.log("[mediasync] Begin afterMediaDownloaded"),getImages(apiClient,jobItem,localItem).then(function(){var libraryItem=jobItem.Item;return downloadParentItems(apiClient,jobItem,libraryItem).then(function(){return getSubtitles(apiClient,jobItem,localItem)})})}function createLocalItem(libraryItem,jobItem){console.log("[localassetmanager] Begin createLocalItem");var item={Item:libraryItem,ItemId:libraryItem.Id,ServerId:libraryItem.ServerId,Id:libraryItem.Id};return jobItem&&(item.SyncJobItemId=jobItem.SyncJobItemId),console.log("[localassetmanager] End createLocalItem"),item}function getNewItem(jobItem,apiClient){console.log("[mediasync] Begin getNewItem");var libraryItem=jobItem.Item;return localassetmanager.getLocalItem(libraryItem.ServerId,libraryItem.Id).then(function(existingItem){if(existingItem&&("queued"===existingItem.SyncStatus||"transferring"===existingItem.SyncStatus||"synced"===existingItem.SyncStatus)&&(console.log("[mediasync] getNewItem: getLocalItem found existing item"),localassetmanager.enableBackgroundCompletion()))return afterMediaDownloaded(apiClient,jobItem,existingItem);libraryItem.CanDelete=!1,libraryItem.CanDownload=!1,libraryItem.SupportsSync=!1,libraryItem.People=[],libraryItem.Chapters=[],libraryItem.Studios=[],libraryItem.SpecialFeatureCount=null,libraryItem.LocalTrailerCount=null,libraryItem.RemoteTrailers=[];var localItem=createLocalItem(libraryItem,jobItem);return localItem.SyncStatus="queued",downloadMedia(apiClient,jobItem,localItem)})}function downloadParentItems(apiClient,jobItem,libraryItem){var p=Promise.resolve();return libraryItem.SeriesId&&(p=p.then(function(){return downloadItem(apiClient,libraryItem.SeriesId)})),libraryItem.SeasonId&&(p=p.then(function(){return downloadItem(apiClient,libraryItem.SeasonId).then(function(seasonItem){return libraryItem.SeasonPrimaryImageTag=(seasonItem.Item.ImageTags||{}).Primary,Promise.resolve()})})),libraryItem.AlbumId&&(p=p.then(function(){return downloadItem(apiClient,libraryItem.AlbumId)})),p}function downloadItem(apiClient,itemId){return apiClient.getItem(apiClient.getCurrentUserId(),itemId).then(function(downloadedItem){downloadedItem.CanDelete=!1,downloadedItem.CanDownload=!1,downloadedItem.SupportsSync=!1,downloadedItem.People=[],downloadedItem.SpecialFeatureCount=null,downloadedItem.BackdropImageTags=null,downloadedItem.ParentBackdropImageTags=null,downloadedItem.ParentArtImageTag=null,downloadedItem.ParentLogoImageTag=null;var localItem=createLocalItem(downloadedItem,null);return localassetmanager.addOrUpdateLocalItem(localItem).then(function(){return Promise.resolve(localItem)},function(err){return console.error("[mediasync] downloadItem failed: "+err.toString()),Promise.resolve(null)})})}function ensureLocalPathParts(localItem,jobItem){if(!localItem.LocalPathParts){var libraryItem=localItem.Item,parts=localassetmanager.getDirectoryPath(libraryItem);parts.push(localassetmanager.getLocalFileName(libraryItem,jobItem.OriginalFileName)),localItem.LocalPathParts=parts}}function downloadMedia(apiClient,jobItem,localItem){var url=apiClient.getUrl("Sync/JobItems/"+jobItem.SyncJobItemId+"/File",{api_key:apiClient.accessToken()});return ensureLocalPathParts(localItem,jobItem),localassetmanager.downloadFile(url,localItem).then(function(result){console.log("[mediasync] downloadMedia: localassetmanager.downloadFile returned.");var localPath=result.path,libraryItem=localItem.Item;if(localPath&&libraryItem.MediaSources)for(var i=0;i2?Promise.resolve():reportOfflineActions(apiClient,serverInfo).then(function(){return getNewMedia(apiClient,downloadCount).then(function(){return syncData(apiClient,serverInfo).then(function(){return console.log("[mediasync]************************************* Exit sync"),Promise.resolve()})})})})})},function(err){console.error(err.toString())})}:self.sync=function(apiClient,serverInfo,options){return console.log("[mediasync]************************************* Start sync"),checkLocalFileExistence(apiClient,serverInfo,options).then(function(){return syncData(apiClient,serverInfo).then(function(){return processDownloadStatus(apiClient,serverInfo,options).then(function(){return localassetmanager.getDownloadItemCount().then(function(downloadCount){return!0===options.syncCheckProgressOnly&&downloadCount>2?Promise.resolve():reportOfflineActions(apiClient,serverInfo).then(function(){return getNewMedia(apiClient,downloadCount).then(function(){return syncData(apiClient,serverInfo)})})})})})},function(err){console.error(err.toString())})}}});
\ No newline at end of file
diff --git a/MediaBrowser.WebDashboard/dashboard-ui/bower_components/emby-webcomponents/cardbuilder/card.css b/MediaBrowser.WebDashboard/dashboard-ui/bower_components/emby-webcomponents/cardbuilder/card.css
index d51478a3e3..346716d26d 100644
--- a/MediaBrowser.WebDashboard/dashboard-ui/bower_components/emby-webcomponents/cardbuilder/card.css
+++ b/MediaBrowser.WebDashboard/dashboard-ui/bower_components/emby-webcomponents/cardbuilder/card.css
@@ -1 +1 @@
-.card,.card:focus{font-weight:inherit!important}.card,.cardBox,.cardContent,.textActionButton{-webkit-tap-highlight-color:transparent;outline:0!important}button::-moz-focus-inner{padding:0;border:0}button{-webkit-border-fit:border!important}.card{border:0;font-size:inherit!important;font-family:inherit!important;text-transform:none;background:0 0!important;margin:0;padding:0;display:block;color:inherit!important;cursor:pointer;contain:layout style;-webkit-flex-shrink:0;flex-shrink:0}.cardContent-button,.textActionButton{cursor:pointer;vertical-align:middle;font-family:inherit}.card-nofocustransform{contain:layout style paint}.itemsContainer{display:-webkit-box;display:-webkit-flex;display:flex}.vertical-list,.vertical-wrap{display:-webkit-box;display:-webkit-flex;-webkit-box-direction:normal}.vertical-list{display:flex;-webkit-box-orient:vertical;-webkit-flex-direction:column;flex-direction:column;-webkit-flex-wrap:nowrap;flex-wrap:nowrap}.vertical-wrap{display:flex;-webkit-box-orient:horizontal;-webkit-flex-direction:row;flex-direction:row;-webkit-flex-wrap:wrap;flex-wrap:wrap}.cardImageContainer,.mediaSourceIndicator{display:-webkit-box;-webkit-box-align:center}.vertical-wrap.centered{-webkit-box-pack:center;-webkit-justify-content:center;justify-content:center}.cardScalable{position:relative;contain:layout style}.cardPadder-backdrop,.cardPadder-mixedBackdrop,.cardPadder-overflowBackdrop,.cardPadder-overflowSmallBackdrop,.cardPadder-smallBackdrop{padding-bottom:56.25%;contain:strict}.cardPadder-mixedSquare,.cardPadder-overflowSquare,.cardPadder-square,.overflowSquareCard-textCardPadder{padding-bottom:100%;contain:strict}.cardPadder-mixedPortrait,.cardPadder-overflowPortrait,.cardPadder-portrait,.overflowPortraitCard-textCardPadder{padding-bottom:150%;contain:strict}.cardPadder-banner{padding-bottom:18.5%;contain:strict}.cardBox{padding:0!important;margin:.9em;-webkit-transition:none;-o-transition:none;transition:none;border:0 solid transparent;contain:layout style}.cardBox-withfocuscontent-large{margin:.5em}@media (max-width:50em){.cardBox{margin:.4em}}.card-focuscontent-large{border:.4em solid transparent}.cardBox-focustransform{will-change:transform;-webkit-transition:-webkit-transform .2s ease-out;-o-transition:transform .2s ease-out;transition:transform .2s ease-out}.card:focus>.cardBox-focustransform{-webkit-transform:scale(1.18,1.18);transform:scale(1.18,1.18)}.cardBox-bottompadded{margin-bottom:1.8em!important}@media (max-width:50em){.cardBox-bottompadded{margin-bottom:1.2em!important}}.card:focus{position:relative!important;z-index:10!important}.btnCardOptions{position:absolute;bottom:.25em;right:0;margin:0!important;z-index:1}.mediaSourceIndicator{display:-webkit-flex;display:flex;position:absolute;-webkit-align-items:center;align-items:center;-webkit-box-pack:center;-webkit-justify-content:center;justify-content:center;top:.3em;left:.3em;text-align:center;vertical-align:middle;width:1.6em;height:1.6em;-webkit-border-radius:50%;border-radius:50%;color:#fff;background:#38c}.cardText,.innerCardFooter{overflow:hidden;text-align:left}.cardImageContainer{-webkit-background-size:contain;background-size:contain;background-repeat:no-repeat;background-position:center center;-webkit-align-items:center;align-items:center;-webkit-box-pack:center;-webkit-justify-content:center;justify-content:center;position:relative;-webkit-background-clip:content-box!important;background-clip:content-box!important;color:inherit;height:100%;contain:strict}.cardContent,.cardImage{position:absolute;right:0;top:0;left:0;bottom:0}.chapterCardImageContainer{background-color:#000;-webkit-border-radius:0;border-radius:0}.textCardImageContainer{background-color:#333}.cardContent{overflow:hidden;display:block;margin:0!important;height:100%;contain:strict}.cardContent-button{border:0!important;padding:0!important;color:inherit;width:100%;font-size:inherit}.cardContent-button:not(.defaultCardBackground){background-color:transparent}.visualCardBox .cardContent{-webkit-border-bottom-left-radius:0;border-bottom-left-radius:0;-webkit-border-bottom-right-radius:0;border-bottom-right-radius:0}.cardContent-shadow{-webkit-box-shadow:0 .0725em .29em 0 rgba(0,0,0,.37);box-shadow:0 .0725em .29em 0 rgba(0,0,0,.37)}.cardImageContainer{display:-webkit-box;display:-webkit-flex;display:flex}.cardImage{-webkit-background-size:contain;background-size:contain;background-repeat:no-repeat;background-position:center bottom}.cardImage-img{max-height:100%;max-width:100%;min-height:70%;min-width:70%;margin:auto}.coveredImage-img{width:100%;height:100%}.coveredImage-noscale-img{max-height:none;max-width:none}.coveredImage{-webkit-background-size:100% 100%;background-size:100% 100%;background-position:center center}.coveredImage-noScale{-webkit-background-size:cover;background-size:cover}.cardFooter{padding:.3em .3em .5em;position:relative}.visualCardBox{-webkit-box-shadow:0 .0725em .29em 0 rgba(0,0,0,.37);box-shadow:0 .0725em .29em 0 rgba(0,0,0,.37);-webkit-border-radius:.145em;border-radius:.145em}.innerCardFooter{background:rgba(0,0,0,.7);position:absolute;bottom:0;left:0;z-index:1;max-width:100%;color:#fff}.innerCardFooterClear{background-color:transparent}.fullInnerCardFooter{right:0}.cardText{padding:.06em .5em;white-space:nowrap;-o-text-overflow:ellipsis;text-overflow:ellipsis}.cardDefaultText,.cardTextCentered{text-align:center}.cardText-secondary{font-size:84%}.cardText-first{padding-top:.24em}.innerCardFooter>.cardText{padding:.3em .5em}.cardFooter-withlogo{padding-left:4em;position:relative}.cardFooterLogo{position:absolute;top:0;bottom:0;left:0;width:4.5em;-webkit-background-size:70% auto;background-size:70% auto;background-repeat:no-repeat;background-position:center center}.cardText-rightmargin{margin-right:2em}.cardDefaultText{white-space:normal}.textActionButton{background:0 0;border:0!important;padding:0!important;color:inherit;font-size:inherit}.textActionButton:hover{text-decoration:underline}.cardImageIcon{width:1em;height:1em;font-size:5em;color:inherit}.cardImageIcon-small{font-size:3em;margin-bottom:.1em}.cardIndicators{right:.225em;top:.225em;position:absolute;display:-webkit-box;display:-webkit-flex;display:flex;-webkit-box-align:center;-webkit-align-items:center;align-items:center;contain:layout style}.cardProgramAttributeIndicators{top:0;left:0;position:absolute;display:-webkit-box;display:-webkit-flex;display:flex;text-transform:uppercase;font-size:92%}.programAttributeIndicator{padding:.18em .5em;color:#fff;font-weight:500}.cardOverlayButton{color:rgba(255,255,255,.76)!important;margin:0;z-index:1;padding:.75em;font-size:88%}.cardOverlayButton-br{position:absolute;bottom:0;right:0}.cardOverlayButtonIcon{background-color:rgba(0,0,0,.7)!important;-webkit-border-radius:100em;border-radius:100em;width:1.5em!important;height:1.5em!important;-webkit-box-pack:center;-webkit-justify-content:center;justify-content:center;-webkit-box-align:center;-webkit-align-items:center;align-items:center;display:-webkit-box;display:-webkit-flex;display:flex;font-size:1.66956521739130434em!important}.cardOverlayButton-centered{bottom:initial;right:initial;position:static;position:absolute;display:-webkit-box;display:-webkit-flex;display:flex;font-size:112%;margin:-1.3em 0 0 -1.3em;width:2.6em;height:2.6em;top:50%;left:50%;background-color:rgba(0,0,0,.5)!important;border:.06em solid rgba(255,255,255,.6);padding:.38em!important;color:rgba(255,255,255,.76);-webkit-transition:-webkit-transform .2s ease-out;-o-transition:transform .2s ease-out;transition:transform .2s ease-out}.cardOverlayButton-centered:hover{-webkit-transform:scale(1.2,1.2);transform:scale(1.2,1.2)}.backdropCard,.bannerCard{width:100%}.smallBackdropCard,.squareCard{width:50%}.portraitCard{width:33.333333333333333333333333333333%}.mixedPortraitCard{width:12em}.mixedSquareCard{width:18em}.mixedBackdropCard{width:32em}@media (min-width:25em){.backdropCard{width:50%}}@media (min-width:31.25em){.portraitCard,.smallBackdropCard,.squareCard{width:33.333333333333333333333333333333%}}@media (min-width:43.75em){.portraitCard,.squareCard{width:25%}}@media (min-width:48.125em){.backdropCard{width:33.333333333333333333333333333333%}}@media (min-width:50em){.bannerCard{width:50%}.portraitCard,.squareCard{width:20%}.smallBackdropCard{width:25%}}@media (min-width:62.5em){.smallBackdropCard{width:20%}}@media (min-width:75em){.backdropCard{width:25%}.portraitCard,.squareCard{width:16.666666666666666666666666666667%}.bannerCard{width:33.333333333333333333333333333333%}.smallBackdropCard{width:16.666666666666666666666666666667%}}@media (min-width:87.5em){.portraitCard,.smallBackdropCard,.squareCard{width:14.285714285714285714285714285714%}}@media (min-width:100em){.smallBackdropCard{width:12.5%}.backdropCard{width:20%}.portraitCard,.squareCard{width:12.5%}}@media (min-width:120em){.portraitCard,.squareCard{width:11.111111111111111111111111111111%}}@media (min-width:131.25em){.bannerCard{width:25%}.portraitCard,.squareCard{width:10%}}@media (min-width:156.25em){.backdropCard{width:16.666666666666666666666666666667%}}.itemsContainer-tv>.backdropCard{width:25%}.itemsContainer-tv>.portraitCard,.itemsContainer-tv>.squareCard{width:16.666666666666666666666666666667%}@media (orientation:portrait){.overflowPortraitCard{width:42vw}.overflowBackdropCard,.overflowSmallBackdropCard{width:72vw}.overflowSquareCard{width:42vw}}@media (orientation:landscape){.overflowBackdropCard,.overflowSmallBackdropCard{width:23.3vw}.overflowPortraitCard,.overflowSquareCard{width:15.5vw}}@media (orientation:portrait) and (min-width:33.75em){.overflowSmallBackdropCard{width:30vw}}@media (orientation:landscape) and (min-width:50em){.overflowSmallBackdropCard{width:15.5vw}}@media (orientation:landscape) and (min-width:106.25em){.overflowBackdropCard{width:18.5vw}.overflowPortraitCard,.overflowSquareCard{width:11.6vw}}@media (orientation:portrait) and (min-width:25em){.overflowPortraitCard{width:31.5vw}}@media (orientation:portrait) and (min-width:33.75em){.overflowBackdropCard{width:64vw}.overflowSquareCard{width:31.5vw}}@media (orientation:portrait) and (min-width:40em){.overflowBackdropCard{width:56vw}}@media (orientation:portrait) and (min-width:47.5em){.overflowPortraitCard{width:23vw}.overflowBackdropCard{width:40vw}.overflowSquareCard{width:23vw}}@media (orientation:portrait) and (min-width:75em){.overflowPortraitCard,.overflowSquareCard{width:18vw}}@media (orientation:portrait) and (min-width:87.5em){.overflowPortraitCard,.overflowSquareCard{width:15vw}.overflowBackdropCard{width:30vw}}@media (orientation:portrait) and (min-width:112.5em){.overflowBackdropCard{width:23.5vw}}.itemsContainer-tv>.overflowBackdropCard{width:23.3vw}.overflowBackdropCard-textCard{width:15.5vw!important}.overflowBackdropCard-textCardPadder{padding-bottom:87.75%}.itemsContainer-tv>.overflowPortraitCard,.itemsContainer-tv>.overflowSquareCard{width:15.5vw}.itemsContainer-tv>.overflowSmallBackdropCard{width:18.9vw}.cardOverlayContainer{background:-webkit-radial-gradient(50% 50%,farthest-corner,rgba(30,30,30,.5) 50%,#2c2c2c 100%);background:-o-radial-gradient(50% 50%,farthest-corner,rgba(30,30,30,.5) 50%,#2c2c2c 100%);background:radial-gradient(farthest-corner at 50% 50%,rgba(30,30,30,.5) 50%,#2c2c2c 100%);opacity:0;-webkit-transition:opacity .2s;-o-transition:opacity .2s;transition:opacity .2s;position:absolute;top:0;left:0;bottom:0;right:0;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.card-hoverable :hover .cardOverlayContainer{opacity:1}.cardOverlayButton-hover{opacity:0;-webkit-transition:opacity .2s;-o-transition:opacity .2s;transition:opacity .2s;background:0 0;color:#fff!important;padding:.5em}.cardOverlayButtonIcon-hover{background:0 0!important}.card-hoverable:hover .cardOverlayButton-hover{opacity:1}.cardOverlayFab-primary{font-size:130%;padding:0;width:3em;height:3em;margin-top:-1.5em;margin-left:-1.5em;position:absolute;top:50%;left:50%}.cardOverlayFab-primary i{border:.07em solid rgba(255,255,255,.9);color:#fff}
\ No newline at end of file
+.card,.card:focus{font-weight:inherit!important}.card,.cardBox,.cardContent,.textActionButton{-webkit-tap-highlight-color:transparent;outline:0!important}button::-moz-focus-inner{padding:0;border:0}button{-webkit-border-fit:border!important}.card{border:0;font-size:inherit!important;font-family:inherit!important;text-transform:none;background:0 0!important;margin:0;padding:0;display:block;color:inherit!important;cursor:pointer;contain:layout style;-webkit-flex-shrink:0;flex-shrink:0}.cardContent-button,.textActionButton{cursor:pointer;vertical-align:middle;font-family:inherit}.card-nofocustransform{contain:layout style paint}.itemsContainer{display:-webkit-box;display:-webkit-flex;display:flex}.vertical-list,.vertical-wrap{display:-webkit-box;display:-webkit-flex;-webkit-box-direction:normal}.vertical-list{display:flex;-webkit-box-orient:vertical;-webkit-flex-direction:column;flex-direction:column;-webkit-flex-wrap:nowrap;flex-wrap:nowrap}.vertical-wrap{display:flex;-webkit-box-orient:horizontal;-webkit-flex-direction:row;flex-direction:row;-webkit-flex-wrap:wrap;flex-wrap:wrap}.cardImageContainer,.mediaSourceIndicator{display:-webkit-box;-webkit-box-align:center}.vertical-wrap.centered{-webkit-box-pack:center;-webkit-justify-content:center;justify-content:center}.cardScalable{position:relative;contain:layout style}.cardPadder-backdrop,.cardPadder-mixedBackdrop,.cardPadder-overflowBackdrop,.cardPadder-overflowSmallBackdrop,.cardPadder-smallBackdrop{padding-bottom:56.25%;contain:strict}.cardPadder-mixedSquare,.cardPadder-overflowSquare,.cardPadder-square,.overflowSquareCard-textCardPadder{padding-bottom:100%;contain:strict}.cardPadder-mixedPortrait,.cardPadder-overflowPortrait,.cardPadder-portrait,.overflowPortraitCard-textCardPadder{padding-bottom:150%;contain:strict}.cardPadder-banner{padding-bottom:18.5%;contain:strict}.cardBox{padding:0!important;margin:.4em;-webkit-transition:none;-o-transition:none;transition:none;border:0 solid transparent;contain:layout style}@media (min-width:50em){.cardBox{margin:1em}}.cardBox-withfocuscontent-large{margin:.5em}.card-focuscontent-large{border:.5em solid transparent}.cardBox-focustransform{will-change:transform;-webkit-transition:-webkit-transform .2s ease-out;-o-transition:transform .2s ease-out;transition:transform .2s ease-out}.card:focus>.cardBox-focustransform{-webkit-transform:scale(1.18,1.18);transform:scale(1.18,1.18)}.cardBox-bottompadded{margin-bottom:1.8em!important}@media (max-width:50em){.cardBox-bottompadded{margin-bottom:1.2em!important}}.card:focus{position:relative!important;z-index:10!important}.btnCardOptions{position:absolute;bottom:.25em;right:0;margin:0!important;z-index:1}.mediaSourceIndicator{display:-webkit-flex;display:flex;position:absolute;-webkit-align-items:center;align-items:center;-webkit-box-pack:center;-webkit-justify-content:center;justify-content:center;top:.3em;left:.3em;text-align:center;vertical-align:middle;width:1.6em;height:1.6em;-webkit-border-radius:50%;border-radius:50%;color:#fff;background:#38c}.cardText,.innerCardFooter{overflow:hidden;text-align:left}.cardImageContainer{-webkit-background-size:contain;background-size:contain;background-repeat:no-repeat;background-position:center center;-webkit-align-items:center;align-items:center;-webkit-box-pack:center;-webkit-justify-content:center;justify-content:center;position:relative;-webkit-background-clip:content-box!important;background-clip:content-box!important;color:inherit;height:100%;contain:strict}.cardContent,.cardImage{position:absolute;right:0;top:0;left:0;bottom:0}.chapterCardImageContainer{background-color:#000;-webkit-border-radius:0;border-radius:0}.textCardImageContainer{background-color:#333}.cardContent{overflow:hidden;display:block;margin:0!important;height:100%;contain:strict}.cardContent-button{border:0!important;padding:0!important;color:inherit;width:100%;font-size:inherit}.cardContent-button:not(.defaultCardBackground){background-color:transparent}.visualCardBox .cardContent{-webkit-border-bottom-left-radius:0;border-bottom-left-radius:0;-webkit-border-bottom-right-radius:0;border-bottom-right-radius:0}.cardContent-shadow{-webkit-box-shadow:0 .0725em .29em 0 rgba(0,0,0,.37);box-shadow:0 .0725em .29em 0 rgba(0,0,0,.37)}.cardImageContainer{display:-webkit-box;display:-webkit-flex;display:flex}.cardImage{-webkit-background-size:contain;background-size:contain;background-repeat:no-repeat;background-position:center bottom}.cardImage-img{max-height:100%;max-width:100%;min-height:70%;min-width:70%;margin:auto}.coveredImage-img{width:100%;height:100%}.coveredImage-noscale-img{max-height:none;max-width:none}.coveredImage{-webkit-background-size:100% 100%;background-size:100% 100%;background-position:center center}.coveredImage-noScale{-webkit-background-size:cover;background-size:cover}.cardFooter{padding:.3em .3em .5em;position:relative}.visualCardBox{-webkit-box-shadow:0 .0725em .29em 0 rgba(0,0,0,.37);box-shadow:0 .0725em .29em 0 rgba(0,0,0,.37);-webkit-border-radius:.145em;border-radius:.145em}.innerCardFooter{background:rgba(0,0,0,.7);position:absolute;bottom:0;left:0;z-index:1;max-width:100%;color:#fff}.innerCardFooterClear{background-color:transparent}.fullInnerCardFooter{right:0}.cardText{padding:.06em .5em;white-space:nowrap;-o-text-overflow:ellipsis;text-overflow:ellipsis}.cardDefaultText,.cardTextCentered{text-align:center}.cardText-secondary{font-size:86%}.cardText-first{padding-top:.24em}.innerCardFooter>.cardText{padding:.3em .5em}.cardFooter-withlogo{padding-left:4em;position:relative}.cardFooterLogo{position:absolute;top:0;bottom:0;left:0;width:4.5em;-webkit-background-size:70% auto;background-size:70% auto;background-repeat:no-repeat;background-position:center center}.cardText-rightmargin{margin-right:2em}.cardDefaultText{white-space:normal}.textActionButton{background:0 0;border:0!important;padding:0!important;color:inherit;font-size:inherit}.textActionButton:hover{text-decoration:underline}.cardImageIcon{width:1em;height:1em;font-size:5em;color:inherit}.cardImageIcon-small{font-size:3em;margin-bottom:.1em}.cardIndicators{right:.225em;top:.225em;position:absolute;display:-webkit-box;display:-webkit-flex;display:flex;-webkit-box-align:center;-webkit-align-items:center;align-items:center;contain:layout style}.cardProgramAttributeIndicators{top:0;left:0;position:absolute;display:-webkit-box;display:-webkit-flex;display:flex;text-transform:uppercase;font-size:92%}.programAttributeIndicator{padding:.18em .5em;color:#fff;font-weight:500}.cardOverlayButton{color:rgba(255,255,255,.76)!important;margin:0;z-index:1;padding:.75em;font-size:88%}.cardOverlayButton-br{position:absolute;bottom:0;right:0}.cardOverlayButtonIcon{background-color:rgba(0,0,0,.7)!important;-webkit-border-radius:100em;border-radius:100em;width:1.5em!important;height:1.5em!important;-webkit-box-pack:center;-webkit-justify-content:center;justify-content:center;-webkit-box-align:center;-webkit-align-items:center;align-items:center;display:-webkit-box;display:-webkit-flex;display:flex;font-size:1.66956521739130434em!important}.cardOverlayButton-centered{bottom:initial;right:initial;position:static;position:absolute;display:-webkit-box;display:-webkit-flex;display:flex;font-size:112%;margin:-1.3em 0 0 -1.3em;width:2.6em;height:2.6em;top:50%;left:50%;background-color:rgba(0,0,0,.5)!important;border:.06em solid rgba(255,255,255,.6);padding:.38em!important;color:rgba(255,255,255,.76);-webkit-transition:-webkit-transform .2s ease-out;-o-transition:transform .2s ease-out;transition:transform .2s ease-out}.cardOverlayButton-centered:hover{-webkit-transform:scale(1.2,1.2);transform:scale(1.2,1.2)}.backdropCard,.bannerCard{width:100%}.smallBackdropCard,.squareCard{width:50%}.portraitCard{width:33.333333333333333333333333333333%}.mixedPortraitCard{width:12em}.mixedSquareCard{width:18em}.mixedBackdropCard{width:32em}@media (min-width:25em){.backdropCard{width:50%}}@media (min-width:31.25em){.portraitCard,.smallBackdropCard,.squareCard{width:33.333333333333333333333333333333%}}@media (min-width:43.75em){.portraitCard,.squareCard{width:25%}}@media (min-width:48.125em){.backdropCard{width:33.333333333333333333333333333333%}}@media (min-width:50em){.bannerCard{width:50%}.portraitCard,.squareCard{width:20%}.smallBackdropCard{width:25%}}@media (min-width:62.5em){.smallBackdropCard{width:20%}}@media (min-width:75em){.backdropCard{width:25%}.portraitCard,.squareCard{width:16.666666666666666666666666666667%}.bannerCard{width:33.333333333333333333333333333333%}.smallBackdropCard{width:16.666666666666666666666666666667%}}@media (min-width:87.5em){.portraitCard,.smallBackdropCard,.squareCard{width:14.285714285714285714285714285714%}}@media (min-width:100em){.smallBackdropCard{width:12.5%}.backdropCard{width:20%}.portraitCard,.squareCard{width:12.5%}}@media (min-width:120em){.portraitCard,.squareCard{width:11.111111111111111111111111111111%}}@media (min-width:131.25em){.bannerCard{width:25%}.portraitCard,.squareCard{width:10%}}@media (min-width:156.25em){.backdropCard{width:16.666666666666666666666666666667%}}.itemsContainer-tv>.backdropCard{width:25%}.itemsContainer-tv>.portraitCard,.itemsContainer-tv>.squareCard{width:16.666666666666666666666666666667%}@media (orientation:portrait){.overflowPortraitCard{width:42vw}.overflowBackdropCard,.overflowSmallBackdropCard{width:72vw}.overflowSquareCard{width:42vw}}@media (orientation:landscape){.overflowBackdropCard,.overflowSmallBackdropCard{width:23.3vw}.overflowPortraitCard,.overflowSquareCard{width:15.5vw}}@media (orientation:portrait) and (min-width:33.75em){.overflowSmallBackdropCard{width:30vw}}@media (orientation:landscape) and (min-width:50em){.overflowSmallBackdropCard{width:15.5vw}}@media (orientation:landscape) and (min-width:106.25em){.overflowBackdropCard{width:18.5vw}.overflowPortraitCard,.overflowSquareCard{width:11.6vw}}@media (orientation:portrait) and (min-width:25em){.overflowPortraitCard{width:31.5vw}}@media (orientation:portrait) and (min-width:33.75em){.overflowBackdropCard{width:64vw}.overflowSquareCard{width:31.5vw}}@media (orientation:portrait) and (min-width:40em){.overflowBackdropCard{width:56vw}}@media (orientation:portrait) and (min-width:47.5em){.overflowPortraitCard{width:23vw}.overflowBackdropCard{width:40vw}.overflowSquareCard{width:23vw}}@media (orientation:portrait) and (min-width:75em){.overflowPortraitCard,.overflowSquareCard{width:18vw}}@media (orientation:portrait) and (min-width:87.5em){.overflowPortraitCard,.overflowSquareCard{width:15vw}.overflowBackdropCard{width:30vw}}@media (orientation:portrait) and (min-width:112.5em){.overflowBackdropCard{width:23.5vw}}.itemsContainer-tv>.overflowBackdropCard{width:23.3vw}.overflowBackdropCard-textCard{width:15.5vw!important}.overflowBackdropCard-textCardPadder{padding-bottom:87.75%}.itemsContainer-tv>.overflowPortraitCard,.itemsContainer-tv>.overflowSquareCard{width:15.5vw}.itemsContainer-tv>.overflowSmallBackdropCard{width:18.9vw}.cardOverlayContainer{background:-webkit-radial-gradient(50% 50%,farthest-corner,rgba(30,30,30,.5) 50%,#2c2c2c 100%);background:-o-radial-gradient(50% 50%,farthest-corner,rgba(30,30,30,.5) 50%,#2c2c2c 100%);background:radial-gradient(farthest-corner at 50% 50%,rgba(30,30,30,.5) 50%,#2c2c2c 100%);opacity:0;-webkit-transition:opacity .2s;-o-transition:opacity .2s;transition:opacity .2s;position:absolute;top:0;left:0;bottom:0;right:0;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.card-hoverable :hover .cardOverlayContainer{opacity:1}.cardOverlayButton-hover{opacity:0;-webkit-transition:opacity .2s;-o-transition:opacity .2s;transition:opacity .2s;background:0 0;color:#fff!important;padding:.5em}.cardOverlayButtonIcon-hover{background:0 0!important}.card-hoverable:hover .cardOverlayButton-hover{opacity:1}.cardOverlayFab-primary{font-size:130%;padding:0;width:3em;height:3em;margin-top:-1.5em;margin-left:-1.5em;position:absolute;top:50%;left:50%}.cardOverlayFab-primary i{border:.07em solid rgba(255,255,255,.9);color:#fff}
\ No newline at end of file
diff --git a/MediaBrowser.WebDashboard/dashboard-ui/bower_components/emby-webcomponents/fullscreen/fullscreen-doubleclick.js b/MediaBrowser.WebDashboard/dashboard-ui/bower_components/emby-webcomponents/fullscreen/fullscreen-dc.js
similarity index 100%
rename from MediaBrowser.WebDashboard/dashboard-ui/bower_components/emby-webcomponents/fullscreen/fullscreen-doubleclick.js
rename to MediaBrowser.WebDashboard/dashboard-ui/bower_components/emby-webcomponents/fullscreen/fullscreen-dc.js
diff --git a/MediaBrowser.WebDashboard/dashboard-ui/bower_components/emby-webcomponents/strings/en-us.json b/MediaBrowser.WebDashboard/dashboard-ui/bower_components/emby-webcomponents/strings/en-us.json
index 9b82ee106d..3729867898 100644
--- a/MediaBrowser.WebDashboard/dashboard-ui/bower_components/emby-webcomponents/strings/en-us.json
+++ b/MediaBrowser.WebDashboard/dashboard-ui/bower_components/emby-webcomponents/strings/en-us.json
@@ -306,7 +306,8 @@
"ConfirmDeleteItems": "Deleting these items will delete them from both the file system and your media library. Are you sure you wish to continue?",
"PleaseRestartServerName": "Please restart Emby Server - {0}.",
"LabelSyncJobName": "Sync job name:",
- "SyncJobCreated": "Sync job created",
+ "SyncingDots": "Syncing...",
+ "ConvertingDots": "Converting...",
"LabelQuality": "Quality:",
"LabelSyncNoTargetsHelp": "It looks like you don't currently have any apps that support offline downloading.",
"DownloadingDots": "Downloading...",
diff --git a/MediaBrowser.WebDashboard/dashboard-ui/bower_components/emby-webcomponents/sync/sync.js b/MediaBrowser.WebDashboard/dashboard-ui/bower_components/emby-webcomponents/sync/sync.js
index 72c05e1abd..eb76e14715 100644
--- a/MediaBrowser.WebDashboard/dashboard-ui/bower_components/emby-webcomponents/sync/sync.js
+++ b/MediaBrowser.WebDashboard/dashboard-ui/bower_components/emby-webcomponents/sync/sync.js
@@ -1 +1 @@
-define(["apphost","globalize","connectionManager","layoutManager","focusManager","scrollHelper","appSettings","registrationServices","dialogHelper","paper-icon-button-light","formDialogStyle"],function(appHost,globalize,connectionManager,layoutManager,focusManager,scrollHelper,appSettings,registrationServices,dialogHelper){"use strict";function submitJob(dlg,apiClient,userId,syncOptions,form){if(!userId)throw new Error("userId cannot be null");if(!syncOptions)throw new Error("syncOptions cannot be null");if(!form)throw new Error("form cannot be null");var selectSyncTarget=form.querySelector("#selectSyncTarget"),target=selectSyncTarget?selectSyncTarget.value:null;if(!target)return require(["toast"],function(toast){toast(globalize.translate("sharedcomponents#PleaseSelectDeviceToSyncTo"))}),!1;var options={userId:userId,TargetId:target,ParentId:syncOptions.ParentId,Category:syncOptions.Category};return setJobValues(options,form),syncOptions.items&&syncOptions.items.length&&(options.ItemIds=(syncOptions.items||[]).map(function(i){return i.Id||i}).join(",")),apiClient.ajax({type:"POST",url:apiClient.getUrl("Sync/Jobs"),data:JSON.stringify(options),contentType:"application/json",dataType:"json"}).then(function(){dialogHelper.close(dlg),require(["toast"],function(toast){showSubmissionToast(target,apiClient),"download"===syncOptions.mode&&syncNow()})}),!0}function showSubmissionToast(targetId,apiClient){require(["toast"],function(toast){toast(targetId===apiClient.deviceId()?globalize.translate("sharedcomponents#DownloadingDots"):globalize.translate("sharedcomponents#SyncJobCreated"))})}function syncNow(){require(["localsync"],function(localSync){localSync.sync()})}function submitQuickSyncJob(apiClient,userId,targetId,syncOptions){if(!userId)throw new Error("userId cannot be null");if(!syncOptions)throw new Error("syncOptions cannot be null");if(!targetId)throw new Error("targetId cannot be null");var options={userId:userId,TargetId:targetId,ParentId:syncOptions.ParentId,Category:syncOptions.Category,Quality:syncOptions.Quality,Bitrate:syncOptions.Bitrate};return syncOptions.items&&syncOptions.items.length&&(options.ItemIds=(syncOptions.items||[]).map(function(i){return i.Id||i}).join(",")),apiClient.ajax({type:"POST",url:apiClient.getUrl("Sync/Jobs"),data:JSON.stringify(options),contentType:"application/json",dataType:"json"}).then(function(){require(["toast"],function(toast){showSubmissionToast(targetId,apiClient),"download"===syncOptions.mode&&syncNow()})})}function setJobValues(job,form){var txtBitrate=form.querySelector("#txtBitrate"),bitrate=txtBitrate?txtBitrate.value:null;bitrate&&(bitrate=1e6*parseFloat(bitrate)),job.Bitrate=bitrate;var selectQuality=form.querySelector("#selectQuality");selectQuality&&(job.Quality=selectQuality.value,appSettings.set("sync-lastquality",job.Quality||""));var selectProfile=form.querySelector("#selectProfile");selectProfile&&(job.Profile=selectProfile.value);var txtItemLimit=form.querySelector("#txtItemLimit");txtItemLimit&&(job.ItemLimit=txtItemLimit.value||null);var chkSyncNewContent=form.querySelector("#chkSyncNewContent");chkSyncNewContent&&(job.SyncNewContent=chkSyncNewContent.checked);var chkUnwatchedOnly=form.querySelector("#chkUnwatchedOnly");chkUnwatchedOnly&&(job.UnwatchedOnly=chkUnwatchedOnly.checked)}function renderForm(options){return new Promise(function(resolve,reject){require(["emby-checkbox","emby-input","emby-select"],function(){renderFormInternal(options,connectionManager.deviceId(),resolve)})})}function renderFormInternal(options,defaultTargetId,resolve){var elem=options.elem,dialogOptions=options.dialogOptions,targets=dialogOptions.Targets,html="",mode=options.mode,targetContainerClass="download"===mode?" hide":"",syncTargetLabel="convert"===mode?globalize.translate("sharedcomponents#LabelConvertTo"):globalize.translate("sharedcomponents#LabelSyncTo");options.readOnlySyncTarget?(html+='',html+=' ',html+="
"):(html+='',html+='
',html+=targets.map(function(t){return"'+t.Name+" "}).join(""),html+=" ",targets.length||(html+='
'+globalize.translate("sharedcomponents#LabelSyncNoTargetsHelp")+"
"),appHost.supports("externallinks")&&(html+='
"),html+="
"),html+='',html+='
',html+=" ",html+='
',html+="
",html+='',html+='
',html+=" ",html+='
',html+="
",html+='',html+=' ',html+="
",-1!==dialogOptions.Options.indexOf("UnwatchedOnly")&&(html+='',html+="
",html+=' ',html+="convert"===mode?""+globalize.translate("sharedcomponents#ConvertUnwatchedVideosOnly")+" ":""+globalize.translate("sharedcomponents#SyncUnwatchedVideosOnly")+" ",html+=" ",html+="convert"===mode?'
'+globalize.translate("sharedcomponents#ConvertUnwatchedVideosOnlyHelp")+"
":'
'+globalize.translate("sharedcomponents#SyncUnwatchedVideosOnlyHelp")+"
",html+="
"),-1!==dialogOptions.Options.indexOf("SyncNewContent")&&(html+='',html+="
",html+=' ',html+="convert"===mode?""+globalize.translate("sharedcomponents#AutomaticallyConvertNewContent")+" ":""+globalize.translate("sharedcomponents#AutomaticallySyncNewContent")+" ",html+=" ",html+="convert"===mode?'
'+globalize.translate("sharedcomponents#AutomaticallyConvertNewContentHelp")+"
":'
'+globalize.translate("sharedcomponents#AutomaticallySyncNewContentHelp")+"
",html+="
"),-1!==dialogOptions.Options.indexOf("ItemLimit")&&(html+='"),elem.innerHTML=html;var selectSyncTarget=elem.querySelector("#selectSyncTarget");selectSyncTarget&&(selectSyncTarget.addEventListener("change",function(){loadQualityOptions(elem,this.value,options.dialogOptionsFn).then(resolve)}),selectSyncTarget.dispatchEvent(new CustomEvent("change",{bubbles:!0})));var selectProfile=elem.querySelector("#selectProfile");selectProfile&&(selectProfile.addEventListener("change",function(){onProfileChange(elem,this.value)}),dialogOptions.ProfileOptions.length&&selectProfile.dispatchEvent(new CustomEvent("change",{bubbles:!0})));var selectQuality=elem.querySelector("#selectQuality");selectQuality&&(selectQuality.addEventListener("change",function(){onQualityChange(elem,this.value)}),selectQuality.dispatchEvent(new CustomEvent("change",{bubbles:!0}))),setTimeout(function(){focusManager.autoFocus(elem)},100)}function showWifiMessage(){require(["dialog","appRouter"],function(dialog,appRouter){var options={title:globalize.translate("sharedcomponents#HeaderWaitingForWifi"),text:globalize.translate("sharedcomponents#WifiRequiredToDownload")},items=[];items.push({name:options.confirmText||globalize.translate("sharedcomponents#ButtonOk"),id:"ok",type:"submit"}),items.push({name:options.cancelText||globalize.translate("sharedcomponents#HeaderDownloadSettings"),id:"downloadsettings",type:"cancel"}),options.buttons=items,dialog(options).then(function(result){return"ok"===result?Promise.resolve():"downloadsettings"===result?(appRouter.show(appRouter.getRouteUrl("downloadsettings")),Promise.resolve()):Promise.reject()})})}function validateNetwork(){switch(navigator.connection?navigator.connection.type:null){case"cellular":case"bluetooth":return showWifiMessage(),!1;default:return!0}}function showSyncMenu(options){return"download"===options.mode&&appSettings.syncOnlyOnWifi()&&!validateNetwork()?Promise.reject():registrationServices.validateFeature("sync").then(function(){return showSyncMenuInternal(options)})}function enableAutoSync(options){if("download"!==options.mode)return!1;var firstItem=(options.items||[])[0]||{};return"Audio"===firstItem.Type||("MusicAlbum"===firstItem.Type||("MusicArtist"===firstItem.Type||("MusicGenre"===firstItem.Type||"Playlist"===firstItem.Type&&"Audio"===firstItem.MediaType)))}function showSyncMenuInternal(options){var apiClient=connectionManager.getApiClient(options.serverId),userId=apiClient.getCurrentUserId();if(enableAutoSync(options))return submitQuickSyncJob(apiClient,userId,apiClient.deviceId(),{items:options.items,Quality:"custom",Bitrate:appSettings.maxStaticMusicBitrate()});var dialogOptionsFn=getTargetDialogOptionsFn(apiClient,{UserId:userId,ItemIds:(options.items||[]).map(function(i){return i.Id||i}).join(","),ParentId:options.ParentId,Category:options.Category,IncludeProviders:"convert"===options.mode?"ConvertSyncProvider":null,ExcludeProviders:"convert"===options.mode?null:"ConvertSyncProvider"});return dialogOptionsFn().then(function(dialogOptions){currentDialogOptions=dialogOptions;var dlgElementOptions={removeOnClose:!0,scrollY:!1,autoFocus:!1};layoutManager.tv?dlgElementOptions.size="fullscreen":dlgElementOptions.size="small";var dlg=dialogHelper.createDialog(dlgElementOptions);dlg.classList.add("formDialog");var html="";html+='",html+='",dlg.innerHTML=html;var submitted=!1;dlg.querySelector("form").addEventListener("submit",function(e){return submitted=submitJob(dlg,apiClient,userId,options,this),e.preventDefault(),!1}),dlg.querySelector(".btnCancel").addEventListener("click",function(){dialogHelper.close(dlg)}),layoutManager.tv&&scrollHelper.centerFocus.on(dlg.querySelector(".formDialogContent"),!1);var promise=dialogHelper.open(dlg);return renderForm({elem:dlg.querySelector(".formFields"),dialogOptions:dialogOptions,dialogOptionsFn:dialogOptionsFn,mode:options.mode}),promise.then(function(){return layoutManager.tv&&scrollHelper.centerFocus.off(dlg.querySelector(".formDialogContent"),!1),submitted?Promise.resolve():Promise.reject()})})}function getTargetDialogOptionsFn(apiClient,query){return function(targetId){return query.TargetId=targetId,apiClient.getJSON(apiClient.getUrl("Sync/Options",query))}}function setQualityFieldVisible(form,visible){var fldQuality=form.querySelector(".fldQuality"),selectQuality=form.querySelector("#selectQuality");visible?(fldQuality&&fldQuality.classList.remove("hide"),selectQuality&&selectQuality.removeAttribute("required")):(fldQuality&&fldQuality.classList.add("hide"),selectQuality&&selectQuality.removeAttribute("required"))}function onProfileChange(form,profileId){var options=currentDialogOptions||{},profileOptions=options.ProfileOptions||[];if(profileOptions.length){var option=profileOptions.filter(function(o){return o.Id===profileId})[0],qualityOptions=options.QualityOptions||[];option?(form.querySelector(".profileDescription").innerHTML=option.Description||"",setQualityFieldVisible(form,qualityOptions.length>0&&option.EnableQualityOptions&&-1!==options.Options.indexOf("Quality"))):(form.querySelector(".profileDescription").innerHTML="",setQualityFieldVisible(form,qualityOptions.length>0&&-1!==options.Options.indexOf("Quality")))}}function onQualityChange(form,qualityId){var options=currentDialogOptions||{},option=(options.QualityOptions||[]).filter(function(o){return o.Id===qualityId})[0],qualityDescription=form.querySelector(".qualityDescription");qualityDescription.innerHTML=option?option.Description||"":"";var fldBitrate=form.querySelector(".fldBitrate"),txtBitrate=form.querySelector("#txtBitrate");"custom"===qualityId?(fldBitrate&&fldBitrate.classList.remove("hide"),txtBitrate&&txtBitrate.setAttribute("required","required")):(fldBitrate&&fldBitrate.classList.add("hide"),txtBitrate&&txtBitrate.removeAttribute("required"))}function renderTargetDialogOptions(form,options){currentDialogOptions=options;var fldProfile=form.querySelector(".fldProfile"),selectProfile=form.querySelector("#selectProfile");options.ProfileOptions.length&&-1!==options.Options.indexOf("Profile")?(fldProfile&&fldProfile.classList.remove("hide"),selectProfile&&selectProfile.setAttribute("required","required")):(fldProfile&&fldProfile.classList.add("hide"),selectProfile&&selectProfile.removeAttribute("required")),setQualityFieldVisible(form,options.QualityOptions.length>0),selectProfile&&(selectProfile.innerHTML=options.ProfileOptions.map(function(o){var selectedAttribute=o.IsDefault?' selected="selected"':"";return'"+o.Name+" "}).join(""),selectProfile.dispatchEvent(new CustomEvent("change",{bubbles:!0})));var selectQuality=form.querySelector("#selectQuality");if(selectQuality){selectQuality.innerHTML=options.QualityOptions.map(function(o){var selectedAttribute=o.IsDefault?' selected="selected"':"";return'"+o.Name+" "}).join("");var lastQuality=appSettings.get("sync-lastquality");lastQuality&&options.QualityOptions.filter(function(i){return i.Id===lastQuality}).length&&(selectQuality.value=lastQuality),selectQuality.dispatchEvent(new CustomEvent("change",{bubbles:!0}))}}function loadQualityOptions(form,targetId,dialogOptionsFn){return dialogOptionsFn(targetId).then(function(options){return renderTargetDialogOptions(form,options)})}var currentDialogOptions;return{showMenu:showSyncMenu,renderForm:renderForm,setJobValues:setJobValues}});
\ No newline at end of file
+define(["apphost","globalize","connectionManager","layoutManager","focusManager","scrollHelper","appSettings","registrationServices","dialogHelper","paper-icon-button-light","formDialogStyle"],function(appHost,globalize,connectionManager,layoutManager,focusManager,scrollHelper,appSettings,registrationServices,dialogHelper){"use strict";function submitJob(dlg,apiClient,userId,syncOptions,form){if(!userId)throw new Error("userId cannot be null");if(!syncOptions)throw new Error("syncOptions cannot be null");if(!form)throw new Error("form cannot be null");var selectSyncTarget=form.querySelector("#selectSyncTarget"),target=selectSyncTarget?selectSyncTarget.value:null;if(!target)return require(["toast"],function(toast){toast(globalize.translate("sharedcomponents#PleaseSelectDeviceToSyncTo"))}),!1;var options={userId:userId,TargetId:target,ParentId:syncOptions.ParentId,Category:syncOptions.Category};return setJobValues(options,form),syncOptions.items&&syncOptions.items.length&&(options.ItemIds=(syncOptions.items||[]).map(function(i){return i.Id||i}).join(",")),apiClient.ajax({type:"POST",url:apiClient.getUrl("Sync/Jobs"),data:JSON.stringify(options),contentType:"application/json",dataType:"json"}).then(function(){dialogHelper.close(dlg),require(["toast"],function(toast){showSubmissionToast(target,apiClient),"download"===syncOptions.mode&&syncNow()})}),!0}function showSubmissionToast(targetId,apiClient){require(["toast"],function(toast){toast(targetId===apiClient.deviceId()?globalize.translate("sharedcomponents#DownloadingDots"):globalize.translate("sharedcomponents#SyncingDots"))})}function syncNow(){require(["localsync"],function(localSync){localSync.sync()})}function submitQuickSyncJob(apiClient,userId,targetId,syncOptions){if(!userId)throw new Error("userId cannot be null");if(!syncOptions)throw new Error("syncOptions cannot be null");if(!targetId)throw new Error("targetId cannot be null");var options={userId:userId,TargetId:targetId,ParentId:syncOptions.ParentId,Category:syncOptions.Category,Quality:syncOptions.Quality,Bitrate:syncOptions.Bitrate};return syncOptions.items&&syncOptions.items.length&&(options.ItemIds=(syncOptions.items||[]).map(function(i){return i.Id||i}).join(",")),apiClient.ajax({type:"POST",url:apiClient.getUrl("Sync/Jobs"),data:JSON.stringify(options),contentType:"application/json",dataType:"json"}).then(function(){require(["toast"],function(toast){showSubmissionToast(targetId,apiClient),"download"===syncOptions.mode&&syncNow()})})}function setJobValues(job,form){var txtBitrate=form.querySelector("#txtBitrate"),bitrate=txtBitrate?txtBitrate.value:null;bitrate&&(bitrate=1e6*parseFloat(bitrate)),job.Bitrate=bitrate;var selectQuality=form.querySelector("#selectQuality");selectQuality&&(job.Quality=selectQuality.value,appSettings.set("sync-lastquality",job.Quality||""));var selectProfile=form.querySelector("#selectProfile");selectProfile&&(job.Profile=selectProfile.value);var txtItemLimit=form.querySelector("#txtItemLimit");txtItemLimit&&(job.ItemLimit=txtItemLimit.value||null);var chkSyncNewContent=form.querySelector("#chkSyncNewContent");chkSyncNewContent&&(job.SyncNewContent=chkSyncNewContent.checked);var chkUnwatchedOnly=form.querySelector("#chkUnwatchedOnly");chkUnwatchedOnly&&(job.UnwatchedOnly=chkUnwatchedOnly.checked)}function renderForm(options){return new Promise(function(resolve,reject){require(["emby-checkbox","emby-input","emby-select"],function(){renderFormInternal(options,connectionManager.deviceId(),resolve)})})}function renderFormInternal(options,defaultTargetId,resolve){var elem=options.elem,dialogOptions=options.dialogOptions,targets=dialogOptions.Targets,html="",mode=options.mode,targetContainerClass="download"===mode?" hide":"",syncTargetLabel="convert"===mode?globalize.translate("sharedcomponents#LabelConvertTo"):globalize.translate("sharedcomponents#LabelSyncTo");options.readOnlySyncTarget?(html+='',html+=' ',html+="
"):(html+='',html+='
',html+=targets.map(function(t){return"'+t.Name+" "}).join(""),html+=" ",targets.length||(html+='
'+globalize.translate("sharedcomponents#LabelSyncNoTargetsHelp")+"
"),appHost.supports("externallinks")&&(html+='
"),html+="
"),html+='',html+='
',html+=" ",html+='
',html+="
",html+='',html+='
',html+=" ",html+='
',html+="
",html+='',html+=' ',html+="
",-1!==dialogOptions.Options.indexOf("UnwatchedOnly")&&(html+='',html+="
",html+=' ',html+="convert"===mode?""+globalize.translate("sharedcomponents#ConvertUnwatchedVideosOnly")+" ":""+globalize.translate("sharedcomponents#SyncUnwatchedVideosOnly")+" ",html+=" ",html+="convert"===mode?'
'+globalize.translate("sharedcomponents#ConvertUnwatchedVideosOnlyHelp")+"
":'
'+globalize.translate("sharedcomponents#SyncUnwatchedVideosOnlyHelp")+"
",html+="
"),-1!==dialogOptions.Options.indexOf("SyncNewContent")&&(html+='',html+="
",html+=' ',html+="convert"===mode?""+globalize.translate("sharedcomponents#AutomaticallyConvertNewContent")+" ":""+globalize.translate("sharedcomponents#AutomaticallySyncNewContent")+" ",html+=" ",html+="convert"===mode?'
'+globalize.translate("sharedcomponents#AutomaticallyConvertNewContentHelp")+"
":'
'+globalize.translate("sharedcomponents#AutomaticallySyncNewContentHelp")+"
",html+="
"),-1!==dialogOptions.Options.indexOf("ItemLimit")&&(html+='"),elem.innerHTML=html;var selectSyncTarget=elem.querySelector("#selectSyncTarget");selectSyncTarget&&(selectSyncTarget.addEventListener("change",function(){loadQualityOptions(elem,this.value,options.dialogOptionsFn).then(resolve)}),selectSyncTarget.dispatchEvent(new CustomEvent("change",{bubbles:!0})));var selectProfile=elem.querySelector("#selectProfile");selectProfile&&(selectProfile.addEventListener("change",function(){onProfileChange(elem,this.value)}),dialogOptions.ProfileOptions.length&&selectProfile.dispatchEvent(new CustomEvent("change",{bubbles:!0})));var selectQuality=elem.querySelector("#selectQuality");selectQuality&&(selectQuality.addEventListener("change",function(){onQualityChange(elem,this.value)}),selectQuality.dispatchEvent(new CustomEvent("change",{bubbles:!0}))),setTimeout(function(){focusManager.autoFocus(elem)},100)}function showWifiMessage(){require(["dialog","appRouter"],function(dialog,appRouter){var options={title:globalize.translate("sharedcomponents#HeaderWaitingForWifi"),text:globalize.translate("sharedcomponents#WifiRequiredToDownload")},items=[];items.push({name:options.confirmText||globalize.translate("sharedcomponents#ButtonOk"),id:"ok",type:"submit"}),items.push({name:options.cancelText||globalize.translate("sharedcomponents#HeaderDownloadSettings"),id:"downloadsettings",type:"cancel"}),options.buttons=items,dialog(options).then(function(result){return"ok"===result?Promise.resolve():"downloadsettings"===result?(appRouter.show(appRouter.getRouteUrl("downloadsettings")),Promise.resolve()):Promise.reject()})})}function validateNetwork(){switch(navigator.connection?navigator.connection.type:null){case"cellular":case"bluetooth":return showWifiMessage(),!1;default:return!0}}function showSyncMenu(options){return"download"===options.mode&&appSettings.syncOnlyOnWifi()&&!validateNetwork()?Promise.reject():registrationServices.validateFeature("sync").then(function(){return showSyncMenuInternal(options)})}function enableAutoSync(options){if("download"!==options.mode)return!1;var firstItem=(options.items||[])[0]||{};return"Audio"===firstItem.Type||("MusicAlbum"===firstItem.Type||("MusicArtist"===firstItem.Type||("MusicGenre"===firstItem.Type||"Playlist"===firstItem.Type&&"Audio"===firstItem.MediaType)))}function showSyncMenuInternal(options){var apiClient=connectionManager.getApiClient(options.serverId),userId=apiClient.getCurrentUserId();if(enableAutoSync(options))return submitQuickSyncJob(apiClient,userId,apiClient.deviceId(),{items:options.items,Quality:"custom",Bitrate:appSettings.maxStaticMusicBitrate()});var dialogOptionsFn=getTargetDialogOptionsFn(apiClient,{UserId:userId,ItemIds:(options.items||[]).map(function(i){return i.Id||i}).join(","),ParentId:options.ParentId,Category:options.Category,IncludeProviders:"convert"===options.mode?"ConvertSyncProvider":null,ExcludeProviders:"convert"===options.mode?null:"ConvertSyncProvider"});return dialogOptionsFn().then(function(dialogOptions){currentDialogOptions=dialogOptions;var dlgElementOptions={removeOnClose:!0,scrollY:!1,autoFocus:!1};layoutManager.tv?dlgElementOptions.size="fullscreen":dlgElementOptions.size="small";var dlg=dialogHelper.createDialog(dlgElementOptions);dlg.classList.add("formDialog");var html="";html+='",html+='",dlg.innerHTML=html;var submitted=!1;dlg.querySelector("form").addEventListener("submit",function(e){return submitted=submitJob(dlg,apiClient,userId,options,this),e.preventDefault(),!1}),dlg.querySelector(".btnCancel").addEventListener("click",function(){dialogHelper.close(dlg)}),layoutManager.tv&&scrollHelper.centerFocus.on(dlg.querySelector(".formDialogContent"),!1);var promise=dialogHelper.open(dlg);return renderForm({elem:dlg.querySelector(".formFields"),dialogOptions:dialogOptions,dialogOptionsFn:dialogOptionsFn,mode:options.mode}),promise.then(function(){return layoutManager.tv&&scrollHelper.centerFocus.off(dlg.querySelector(".formDialogContent"),!1),submitted?Promise.resolve():Promise.reject()})})}function getTargetDialogOptionsFn(apiClient,query){return function(targetId){return query.TargetId=targetId,apiClient.getJSON(apiClient.getUrl("Sync/Options",query))}}function setQualityFieldVisible(form,visible){var fldQuality=form.querySelector(".fldQuality"),selectQuality=form.querySelector("#selectQuality");visible?(fldQuality&&fldQuality.classList.remove("hide"),selectQuality&&selectQuality.removeAttribute("required")):(fldQuality&&fldQuality.classList.add("hide"),selectQuality&&selectQuality.removeAttribute("required"))}function onProfileChange(form,profileId){var options=currentDialogOptions||{},profileOptions=options.ProfileOptions||[];if(profileOptions.length){var option=profileOptions.filter(function(o){return o.Id===profileId})[0],qualityOptions=options.QualityOptions||[];option?(form.querySelector(".profileDescription").innerHTML=option.Description||"",setQualityFieldVisible(form,qualityOptions.length>0&&option.EnableQualityOptions&&-1!==options.Options.indexOf("Quality"))):(form.querySelector(".profileDescription").innerHTML="",setQualityFieldVisible(form,qualityOptions.length>0&&-1!==options.Options.indexOf("Quality")))}}function onQualityChange(form,qualityId){var options=currentDialogOptions||{},option=(options.QualityOptions||[]).filter(function(o){return o.Id===qualityId})[0],qualityDescription=form.querySelector(".qualityDescription");qualityDescription.innerHTML=option?option.Description||"":"";var fldBitrate=form.querySelector(".fldBitrate"),txtBitrate=form.querySelector("#txtBitrate");"custom"===qualityId?(fldBitrate&&fldBitrate.classList.remove("hide"),txtBitrate&&txtBitrate.setAttribute("required","required")):(fldBitrate&&fldBitrate.classList.add("hide"),txtBitrate&&txtBitrate.removeAttribute("required"))}function renderTargetDialogOptions(form,options){currentDialogOptions=options;var fldProfile=form.querySelector(".fldProfile"),selectProfile=form.querySelector("#selectProfile");options.ProfileOptions.length&&-1!==options.Options.indexOf("Profile")?(fldProfile&&fldProfile.classList.remove("hide"),selectProfile&&selectProfile.setAttribute("required","required")):(fldProfile&&fldProfile.classList.add("hide"),selectProfile&&selectProfile.removeAttribute("required")),setQualityFieldVisible(form,options.QualityOptions.length>0),selectProfile&&(selectProfile.innerHTML=options.ProfileOptions.map(function(o){var selectedAttribute=o.IsDefault?' selected="selected"':"";return'"+o.Name+" "}).join(""),selectProfile.dispatchEvent(new CustomEvent("change",{bubbles:!0})));var selectQuality=form.querySelector("#selectQuality");if(selectQuality){selectQuality.innerHTML=options.QualityOptions.map(function(o){var selectedAttribute=o.IsDefault?' selected="selected"':"";return'"+o.Name+" "}).join("");var lastQuality=appSettings.get("sync-lastquality");lastQuality&&options.QualityOptions.filter(function(i){return i.Id===lastQuality}).length&&(selectQuality.value=lastQuality),selectQuality.dispatchEvent(new CustomEvent("change",{bubbles:!0}))}}function loadQualityOptions(form,targetId,dialogOptionsFn){return dialogOptionsFn(targetId).then(function(options){return renderTargetDialogOptions(form,options)})}var currentDialogOptions;return{showMenu:showSyncMenu,renderForm:renderForm,setJobValues:setJobValues}});
\ No newline at end of file
diff --git a/MediaBrowser.WebDashboard/dashboard-ui/bower_components/emby-webcomponents/sync/syncjoblist.js b/MediaBrowser.WebDashboard/dashboard-ui/bower_components/emby-webcomponents/sync/syncjoblist.js
index 666799c612..0208990a9a 100644
--- a/MediaBrowser.WebDashboard/dashboard-ui/bower_components/emby-webcomponents/sync/syncjoblist.js
+++ b/MediaBrowser.WebDashboard/dashboard-ui/bower_components/emby-webcomponents/sync/syncjoblist.js
@@ -1 +1 @@
-define(["serverNotifications","events","loading","connectionManager","imageLoader","dom","globalize","registrationServices","layoutManager","listViewStyle"],function(serverNotifications,events,loading,connectionManager,imageLoader,dom,globalize,registrationServices,layoutManager){"use strict";function onSyncJobsUpdated(e,apiClient,data){renderList(this,data,apiClient)}function refreshList(listInstance,jobs){for(var i=0,length=jobs.length;i0&&progress<100&&(progress=progress.toFixed(1)),html+=progress+"%"}return html}function getSyncJobHtml(listInstance,job,apiClient){var html="",tagName=layoutManager.tv?"button":"div",typeAttribute="button"===tagName?' type="button"':"",listItemClass="listItem listItem-border";layoutManager.tv&&(listItemClass+=" listItem-button listItem-focusscale",listItemClass+=" btnJobMenu");var canEdit=(job.ItemCount||1)>1||"Queued"===job.Status;html+="<"+tagName+typeAttribute+' class="'+listItemClass+'" data-canedit="'+canEdit+'" data-id="'+job.Id+'" data-status="'+job.Status+'">';var imgUrl;job.PrimaryImageItemId&&(imgUrl=apiClient.getImageUrl(job.PrimaryImageItemId,{type:"Primary",width:80,tag:job.PrimaryImageTag,minScale:1.5})),imgUrl?(html+='',html+="
"):html+='file_download ';var textLines=[],name=job.Name;job.ParentName&&(name+=" - "+job.ParentName),textLines.push(name),1===job.ItemCount||textLines.push(globalize.translate("sharedcomponents#ItemCount",job.ItemCount)),html+='';for(var i=0,length=textLines.length;i
',html+=textLines[i],html+=""):(html+='',html+=textLines[i],html+="
");return html+='',html+=getProgressText(job),html+="
",html+=" ",layoutManager.tv||(html+=canEdit?'':'delete '),html+=""+tagName+">"}function renderList(listInstance,jobs,apiClient){if((new Date).getTime()-listInstance.lastDataLoad<6e4)return void refreshList(listInstance,jobs);listInstance.lastDataLoad=(new Date).getTime();for(var html="",lastTargetName="",mode=listInstance.options.mode,showTargetName="download"!==mode,hasOpenSection=!1,i=0,length=jobs.length;i",html+=" ",hasOpenSection=!1),lastTargetName=targetName,html+='',html+='
',html+='
'+targetName+" ",html+="",html+='
',hasOpenSection=!0)}html+=getSyncJobHtml(listInstance,job,apiClient)}hasOpenSection&&(html+="
",html+="
");var elem=listInstance.options.element.querySelector(".syncJobListContent");html||(html="download"===mode?''+globalize.translate("sharedcomponents#MessageNoDownloadsFound")+"
":''+globalize.translate("sharedcomponents#MessageNoSyncJobsFound")+"
"),elem.innerHTML=html,imageLoader.lazyChildren(elem)}function fetchData(listInstance){listInstance.lastDataLoad=0,loading.show();var options={},apiClient=getApiClient(listInstance);return listInstance.options.userId&&(options.UserId=listInstance.options.userId),"download"===listInstance.options.mode&&(options.TargetId=apiClient.deviceId()),apiClient.getJSON(apiClient.getUrl("Sync/Jobs",options)).then(function(response){renderList(listInstance,response.Items,apiClient),loading.hide()})}function startListening(listInstance){var startParams="0,1500",apiClient=getApiClient(listInstance);listInstance.options.userId&&(startParams+=","+listInstance.options.userId),"download"===listInstance.options.mode?startParams+=","+apiClient.deviceId():!1===listInstance.options.enableRemoteSyncManagement&&(startParams+=",true"),apiClient.sendMessage("SyncJobsStart",startParams)}function stopListening(listInstance){getApiClient(listInstance).sendMessage("SyncJobsStop","")}function getApiClient(listInstance){return connectionManager.getApiClient(listInstance.options.serverId)}function showJobMenu(listInstance,elem){var item=dom.parentWithClass(elem,"listItem"),jobId=item.getAttribute("data-id"),menuItems=(item.getAttribute("data-status"),[]);"true"===item.getAttribute("data-canedit")&&menuItems.push({name:globalize.translate("sharedcomponents#Edit"),id:"edit"});var txt=globalize.translate("sharedcomponents#RemoveDownload");menuItems.push({name:txt,id:"cancel"}),require(["actionsheet"],function(actionsheet){actionsheet.show({items:menuItems,positionTo:elem,callback:function(id){switch(id){case"delete":case"cancel":cancelJob(listInstance,jobId);break;case"edit":showJobEditor(listInstance,elem)}}})})}function onElementClick(e){var listInstance=this,btnJobMenu=dom.parentWithClass(e.target,"btnJobMenu");if(btnJobMenu)return void showJobMenu(listInstance,btnJobMenu);var btnCancelJob=dom.parentWithClass(e.target,"btnCancelJob");if(btnCancelJob){var listItem=dom.parentWithClass(btnCancelJob,"listItem");if(listItem){cancelJob(listInstance,listItem.getAttribute("data-id"))}}else showJobEditor(listInstance,e.target)}function showJobEditor(listInstance,elem){var listItem=dom.parentWithClass(elem,"listItem");if(listItem&&"true"===listItem.getAttribute("data-canedit")){var jobId=listItem.getAttribute("data-id");require(["syncJobEditor"],function(syncJobEditor){syncJobEditor.show({serverId:listInstance.options.serverId,jobId:jobId,mode:listInstance.options.mode}).then(function(){fetchData(listInstance)})})}}function syncJobList(options){this.options=options;var onSyncJobsUpdatedHandler=onSyncJobsUpdated.bind(this);this.onSyncJobsUpdatedHandler=onSyncJobsUpdatedHandler,events.on(serverNotifications,"SyncJobs",onSyncJobsUpdatedHandler);var onClickHandler=onElementClick.bind(this);options.element.addEventListener("click",onClickHandler),this.onClickHandler=onClickHandler,options.element.innerHTML='
',fetchData(this),startListening(this),initSupporterInfo(options.element,getApiClient(this))}function showSupporterInfo(context){var html='';html+="",html+=globalize.translate("sharedcomponents#HeaderSyncRequiresSub"),html+="
",html+='',html+=globalize.translate("sharedcomponents#LearnMore"),html+="
",html+=" 0&&progress<100&&(progress=progress.toFixed(1)),html+=progress+"%"}return html}function getSyncJobHtml(listInstance,job,apiClient){var html="",tagName=layoutManager.tv?"button":"div",typeAttribute="button"===tagName?' type="button"':"",listItemClass="listItem listItem-border";layoutManager.tv&&(listItemClass+=" listItem-button listItem-focusscale",listItemClass+=" btnJobMenu");var canEdit=(job.ItemCount||1)>1||"Queued"===job.Status;html+="<"+tagName+typeAttribute+' class="'+listItemClass+'" data-canedit="'+canEdit+'" data-id="'+job.Id+'" data-status="'+job.Status+'">';var imgUrl;job.PrimaryImageItemId&&(imgUrl=apiClient.getImageUrl(job.PrimaryImageItemId,{type:"Primary",width:80,tag:job.PrimaryImageTag,minScale:1.5})),imgUrl?(html+='',html+="
"):html+='file_download ';var textLines=[],name=job.Name;job.ParentName&&(name+=" - "+job.ParentName),textLines.push(name),1===job.ItemCount||textLines.push(globalize.translate("sharedcomponents#ItemCount",job.ItemCount)),html+='';for(var i=0,length=textLines.length;i
',html+=textLines[i],html+=""):(html+='',html+=textLines[i],html+="
");return html+='',html+=getProgressText(job),html+="
",html+=" ",layoutManager.tv||(html+=canEdit?'':'delete '),html+=""+tagName+">"}function renderList(listInstance,jobs,apiClient){if((new Date).getTime()-listInstance.lastDataLoad<6e4)return void refreshList(listInstance,jobs);listInstance.lastDataLoad=(new Date).getTime();for(var html="",lastTargetName="",mode=listInstance.options.mode,showTargetName="download"!==mode,hasOpenSection=!1,i=0,length=jobs.length;i",html+=" ",hasOpenSection=!1),lastTargetName=targetName,html+='',html+='
',html+='
'+targetName+" ",html+="",html+='
',hasOpenSection=!0)}html+=getSyncJobHtml(listInstance,job,apiClient)}hasOpenSection&&(html+="
",html+="
");var elem=listInstance.options.element.querySelector(".syncJobListContent");html||(html="download"===mode?''+globalize.translate("sharedcomponents#MessageNoDownloadsFound")+"
":''+globalize.translate("sharedcomponents#MessageNoSyncJobsFound")+"
"),elem.innerHTML=html,imageLoader.lazyChildren(elem)}function fetchData(listInstance){listInstance.lastDataLoad=0,loading.show();var options={},apiClient=getApiClient(listInstance);return listInstance.options.userId&&(options.UserId=listInstance.options.userId),"download"===listInstance.options.mode&&(options.TargetId=apiClient.deviceId()),apiClient.getJSON(apiClient.getUrl("Sync/Jobs",options)).then(function(response){renderList(listInstance,response.Items,apiClient),loading.hide()})}function getApiClient(listInstance){return connectionManager.getApiClient(listInstance.options.serverId)}function showJobMenu(listInstance,elem){var item=dom.parentWithClass(elem,"listItem"),jobId=item.getAttribute("data-id"),menuItems=(item.getAttribute("data-status"),[]);"true"===item.getAttribute("data-canedit")&&menuItems.push({name:globalize.translate("sharedcomponents#Edit"),id:"edit"});var txt=globalize.translate("sharedcomponents#RemoveDownload");menuItems.push({name:txt,id:"cancel"}),require(["actionsheet"],function(actionsheet){actionsheet.show({items:menuItems,positionTo:elem,callback:function(id){switch(id){case"delete":case"cancel":cancelJob(listInstance,jobId);break;case"edit":showJobEditor(listInstance,elem)}}})})}function onElementClick(e){var listInstance=this,btnJobMenu=dom.parentWithClass(e.target,"btnJobMenu");if(btnJobMenu)return void showJobMenu(listInstance,btnJobMenu);var btnCancelJob=dom.parentWithClass(e.target,"btnCancelJob");if(btnCancelJob){var listItem=dom.parentWithClass(btnCancelJob,"listItem");if(listItem){cancelJob(listInstance,listItem.getAttribute("data-id"))}}else showJobEditor(listInstance,e.target)}function showJobEditor(listInstance,elem){var listItem=dom.parentWithClass(elem,"listItem");if(listItem&&"true"===listItem.getAttribute("data-canedit")){var jobId=listItem.getAttribute("data-id");require(["syncJobEditor"],function(syncJobEditor){syncJobEditor.show({serverId:listInstance.options.serverId,jobId:jobId,mode:listInstance.options.mode}).then(function(){fetchData(listInstance)})})}}function syncJobList(options){this.options=options;var onSyncJobCreatedHandler=onSyncJobCreated.bind(this);this.onSyncJobCreatedHandler=onSyncJobCreatedHandler,events.on(serverNotifications,"SyncJobCreated",onSyncJobCreatedHandler);var onSyncJobCancelledHandler=onSyncJobCancelled.bind(this);this.onSyncJobCancelledHandler=onSyncJobCancelledHandler,events.on(serverNotifications,"SyncJobCancelled",onSyncJobCancelledHandler);var onSyncJobUpdatedHandler=onSyncJobUpdated.bind(this);this.onSyncJobUpdatedHandler=onSyncJobUpdatedHandler,events.on(serverNotifications,"SyncJobUpdated",onSyncJobUpdatedHandler);var onClickHandler=onElementClick.bind(this);options.element.addEventListener("click",onClickHandler),this.onClickHandler=onClickHandler,options.element.innerHTML='
',fetchData(this),initSupporterInfo(options.element,getApiClient(this))}function showSupporterInfo(context){var html='';html+="",html+=globalize.translate("sharedcomponents#HeaderSyncRequiresSub"),html+="
",html+='',html+=globalize.translate("sharedcomponents#LearnMore"),html+="
",html+=" option{color:inherit;background:#222}.emby-select-withcolor:focus{border-color:#52B54B!important}.emby-select-tv-withcolor:focus{background-color:#52B54B!important;color:#fff!important}.emby-checkbox:checked+span+span+.checkboxOutline{border-color:#52B54B}.emby-checkbox:focus+span+.emby-checkbox-focushelper{background-color:rgba(82,181,75,.26)}.emby-checkbox:checked+span+span+.checkboxOutline,.itemProgressBarForeground{background-color:#52B54B}.itemProgressBarForeground-recording{background-color:#CB272A}.countIndicator,.fullSyncIndicator,.playedIndicator{background:#52B54B}.fullSyncIndicator{color:#fff}.mainDrawer{background-color:#1c1c1c}.navMenuOption:hover{background:#252528}.navMenuOption-selected{background:#52B54B!important;color:#fff}.emby-button-focusscale:focus{background:#52B54B;color:#fff}.emby-tab-button{color:#999;color:rgba(255,255,255,.4)}.emby-tab-button-active{color:#52B54B}.emby-tab-button-active.emby-button-tv{color:#fff}.emby-tab-button.emby-button-tv:focus{color:#52B54B;background:0 0}.channelPrograms,.guide-channelHeaderCell,.programCell{border-color:rgba(255,255,255,.05)}.programCell-sports{background:#3949AB!important}.programCell-movie{background:#5E35B1!important}.programCell-kids{background:#039BE5!important}.programCell-news{background:#43A047!important}.programCell-active{background:#1e1e1e!important}.guide-channelHeaderCell:focus,.programCell:focus{background-color:#52B54B!important;color:#fff!important}.guide-programTextIcon{color:#1e1e1e;background:#555}.guide-headerTimeslots{color:inherit}.guide-date-tab-button{color:#555;color:rgba(255,255,255,.3)}.guide-date-tab-button.emby-tab-button-active,.guide-date-tab-button:focus{color:#52B54B}.guide-date-tab-button.emby-button-tv:focus{background-color:#52B54B;color:#fff}.itemBackdropFader{background:-webkit-gradient(linear,left top,left bottom,from(rgba(0,0,0,0)),to(#1a1a1a));background:-webkit-linear-gradient(rgba(0,0,0,0),#1a1a1a);background:-o-linear-gradient(rgba(0,0,0,0),#1a1a1a);background:linear-gradient(rgba(0,0,0,0),#1a1a1a)}.infoBanner{color:#ddd;background:#111;padding:1em;-webkit-border-radius:.25em;border-radius:.25em}.ratingbutton-icon-withrating{color:#c33}.downloadbutton-icon-complete,.downloadbutton-icon-on{color:#4285F4}.playstatebutton-icon-played{color:#c33}.repeatButton-active{color:#4285F4}.card:focus .card-focuscontent{border-color:#52B54B}.layout-desktop ::-webkit-scrollbar{width:1em;height:1em}::-webkit-scrollbar-track{-webkit-box-shadow:inset 0 0 6px rgba(0,0,0,.3)}::-webkit-scrollbar-track-piece{background-color:#3b3b3b}::-webkit-scrollbar-thumb:horizontal,::-webkit-scrollbar-thumb:vertical{-webkit-border-radius:2px;background:center no-repeat #888}.timeslotHeaders-desktop::-webkit-scrollbar{height:.7em}
\ No newline at end of file
+html{color:#ddd;color:rgba(255,255,255,.8)}.emby-collapsible-button{border-color:#383838;border-color:rgba(255,255,255,.135)}.skinHeader-withBackground{background-color:#1f1f1f}.skinHeader.semiTransparent{-webkit-backdrop-filter:none!important;backdrop-filter:none!important;background-color:rgba(0,0,0,.3);background:-webkit-gradient(linear,left top,left bottom,from(rgba(0,0,0,.6)),to(rgba(0,0,0,0)));background:-webkit-linear-gradient(rgba(0,0,0,.6),rgba(0,0,0,0));background:-o-linear-gradient(rgba(0,0,0,.6),rgba(0,0,0,0));background:linear-gradient(rgba(0,0,0,.6),rgba(0,0,0,0))}.pageTitleWithDefaultLogo{background-image:url(../logowhite.png)}.backgroundContainer,.dialog,html{background-color:#1a1a1a}.backgroundContainer.withBackdrop{background-color:rgba(0,0,0,.86)}.paper-icon-button-light:focus{color:#52B54B;background-color:rgba(82,181,75,.2)}.fab,.raised{background:#303030;color:rgba(255,255,255,.87)}.fab:focus,.raised:focus{background:#383838}.button-submit{background:#52B54B;color:#fff}.button-submit:focus{background:#5EC157;color:#fff}.checkboxLabel{color:inherit}.checkboxListLabel,.inputLabel,.inputLabelUnfocused,.paperListLabel,.textareaLabelUnfocused{color:#bbb;color:rgba(255,255,255,.7)}.inputLabelFocused,.selectLabelFocused,.textareaLabelFocused{color:#52B54B}.checkboxOutline{border-color:currentColor}.collapseContent,.formDialogFooter:not(.formDialogFooter-clear),.formDialogHeader:not(.formDialogHeader-clear),.paperList,.visualCardBox{background-color:#242424}.defaultCardBackground1{background-color:#d2b019}.defaultCardBackground2{background-color:#338abb}.defaultCardBackground3{background-color:#6b689d}.defaultCardBackground4{background-color:#dd452b}.defaultCardBackground5{background-color:#5ccea9}.cardText-secondary,.fieldDescription,.guide-programNameCaret,.listItem .secondary,.nowPlayingBarSecondaryText,.programSecondaryTitle,.secondaryText{color:#999;color:rgba(255,255,255,.5)}.actionsheetDivider{background:#444;background:rgba(255,255,255,.14)}.cardFooter-vibrant .cardText-secondary{color:inherit;opacity:.5}.actionSheetMenuItem:hover{background-color:#242424}.toast{background:#303030;color:#fff;color:rgba(255,255,255,.87)}.appfooter{background:#101010;color:#ccc;color:rgba(255,255,255,.78)}@supports (backdrop-filter:blur(10px)) or (-webkit-backdrop-filter:blur(10px)){.appfooter-blurred{background:rgba(24,24,24,.7);-webkit-backdrop-filter:blur(20px);backdrop-filter:blur(20px)}}.itemSelectionPanel{border:1px solid #52B54B}.selectionCommandsPanel{background:#52B54B;color:#fff}.upNextDialog-countdownText{color:#52B54B}.alphaPickerButton{color:#999;color:rgba(255,255,255,.5);background-color:transparent}.alphaPickerButton-selected{color:#fff}.alphaPickerButton-tv:focus{background-color:#52B54B;color:#fff!important}.detailTableBodyRow-shaded:nth-child(even){background:#1c1c1c;background:rgba(30,30,30,.9)}.listItem-border{border-color:rgba(46,46,46,.9)!important}.listItem:focus{background:#333}.progressring-spiner{border-color:#52B54B}.button-flat-accent,.button-link{color:#52B54B}.mediaInfoText{color:#ddd;background:rgba(170,170,190,.2)}.mediaInfoTimerIcon,.starIcon{color:#CB272A}.emby-input,.emby-textarea{color:inherit;background:#292929;border:.07em solid #292929;-webkit-border-radius:.15em;border-radius:.15em}.emby-input:focus,.emby-textarea:focus{border-color:#52B54B}.emby-select-withcolor{color:inherit;background:#292929;border:.07em solid #292929}.emby-select-withcolor>option{color:inherit;background:#222}.emby-select-withcolor:focus{border-color:#52B54B!important}.emby-select-tv-withcolor:focus{background-color:#52B54B!important;color:#fff!important}.emby-checkbox:checked+span+span+.checkboxOutline{border-color:#52B54B}.emby-checkbox:focus+span+.emby-checkbox-focushelper{background-color:rgba(82,181,75,.26)}.emby-checkbox:checked+span+span+.checkboxOutline,.itemProgressBarForeground{background-color:#52B54B}.itemProgressBarForeground-recording{background-color:#CB272A}.countIndicator,.fullSyncIndicator,.playedIndicator{background:#52B54B}.fullSyncIndicator{color:#fff}.mainDrawer{background-color:#1c1c1c}.navMenuOption:hover{background:#252528}.navMenuOption-selected{background:#52B54B!important;color:#fff}.emby-button-focusscale:focus{background:#52B54B;color:#fff}.emby-tab-button{color:#999;color:rgba(255,255,255,.4)}.emby-tab-button-active{color:#52B54B}.emby-tab-button-active.emby-button-tv{color:#fff}.emby-tab-button.emby-button-tv:focus{color:#52B54B;background:0 0}.channelPrograms,.guide-channelHeaderCell,.programCell{border-color:rgba(255,255,255,.05)}.programCell-sports{background:#3949AB!important}.programCell-movie{background:#5E35B1!important}.programCell-kids{background:#039BE5!important}.programCell-news{background:#43A047!important}.programCell-active{background:#1e1e1e!important}.guide-channelHeaderCell:focus,.programCell:focus{background-color:#52B54B!important;color:#fff!important}.guide-programTextIcon{color:#1e1e1e;background:#555}.guide-headerTimeslots{color:inherit}.guide-date-tab-button{color:#555;color:rgba(255,255,255,.3)}.guide-date-tab-button.emby-tab-button-active,.guide-date-tab-button:focus{color:#52B54B}.guide-date-tab-button.emby-button-tv:focus{background-color:#52B54B;color:#fff}.itemBackdropFader{background:-webkit-gradient(linear,left top,left bottom,from(rgba(0,0,0,0)),to(#1a1a1a));background:-webkit-linear-gradient(rgba(0,0,0,0),#1a1a1a);background:-o-linear-gradient(rgba(0,0,0,0),#1a1a1a);background:linear-gradient(rgba(0,0,0,0),#1a1a1a)}.infoBanner{color:#ddd;background:#111;padding:1em;-webkit-border-radius:.25em;border-radius:.25em}.ratingbutton-icon-withrating{color:#c33}.downloadbutton-icon-complete,.downloadbutton-icon-on{color:#4285F4}.playstatebutton-icon-played{color:#c33}.repeatButton-active{color:#4285F4}.card:focus .card-focuscontent{border-color:#52B54B}.layout-desktop ::-webkit-scrollbar{width:1em;height:1em}::-webkit-scrollbar-track{-webkit-box-shadow:inset 0 0 6px rgba(0,0,0,.3)}::-webkit-scrollbar-track-piece{background-color:#3b3b3b}::-webkit-scrollbar-thumb:horizontal,::-webkit-scrollbar-thumb:vertical{-webkit-border-radius:2px;background:center no-repeat #888}.timeslotHeaders-desktop::-webkit-scrollbar{height:.7em}
\ No newline at end of file
diff --git a/MediaBrowser.WebDashboard/dashboard-ui/components/filterdialog/filterdialog.js b/MediaBrowser.WebDashboard/dashboard-ui/components/filterdialog/filterdialog.js
index 0e1c9f8a0c..17d79f670f 100644
--- a/MediaBrowser.WebDashboard/dashboard-ui/components/filterdialog/filterdialog.js
+++ b/MediaBrowser.WebDashboard/dashboard-ui/components/filterdialog/filterdialog.js
@@ -1 +1 @@
-define(["dialogHelper","globalize","connectionManager","events","browser","require","emby-checkbox","emby-collapse","css!./style"],function(dialogHelper,globalize,connectionManager,events,browser,require){"use strict";function renderOptions(context,selector,cssClass,items,isCheckedFn){var elem=context.querySelector(selector);items.length?elem.classList.remove("hide"):elem.classList.add("hide");var html="";html+='',html+=items.map(function(filter){var itemHtml="",checkedHtml=isCheckedFn(filter)?" checked":"";return itemHtml+="",itemHtml+=' ',itemHtml+=""+filter+" ",itemHtml+=" "}).join(""),html+="
",elem.querySelector(".filterOptions").innerHTML=html}function renderFilters(context,result,query){result.Tags&&(result.Tags.length=Math.min(result.Tags.length,50)),renderOptions(context,".genreFilters","chkGenreFilter",result.Genres,function(i){return-1!=("|"+(query.Genres||"")+"|").indexOf("|"+i+"|")}),renderOptions(context,".officialRatingFilters","chkOfficialRatingFilter",result.OfficialRatings,function(i){return-1!=("|"+(query.OfficialRatings||"")+"|").indexOf("|"+i+"|")}),renderOptions(context,".tagFilters","chkTagFilter",result.Tags,function(i){return-1!=("|"+(query.Tags||"")+"|").indexOf("|"+i+"|")}),renderOptions(context,".yearFilters","chkYearFilter",result.Years,function(i){return-1!=(","+(query.Years||"")+",").indexOf(","+i+",")})}function loadDynamicFilters(context,apiClient,userId,itemQuery){return apiClient.getJSON(apiClient.getUrl("Items/Filters",{UserId:userId,ParentId:itemQuery.ParentId,IncludeItemTypes:itemQuery.IncludeItemTypes})).then(function(result){renderFilters(context,result,itemQuery)})}function updateFilterControls(context,options){var elems,i,length,query=options.query;if("livetvchannels"==options.mode)context.querySelector(".chkFavorite").checked=1==query.IsFavorite,context.querySelector(".chkLikes").checked=1==query.IsLiked,context.querySelector(".chkDislikes").checked=1==query.IsDisliked;else for(elems=context.querySelectorAll(".chkStandardFilter"),i=0,length=elems.length;i',html+=items.map(function(filter){var itemHtml="",checkedHtml=isCheckedFn(filter)?" checked":"";return itemHtml+="",itemHtml+=' ',itemHtml+=""+filter+" ",itemHtml+=" "}).join(""),html+="",elem.querySelector(".filterOptions").innerHTML=html}function renderFilters(context,result,query){result.Tags&&(result.Tags.length=Math.min(result.Tags.length,50)),renderOptions(context,".genreFilters","chkGenreFilter",result.Genres,function(i){return-1!=("|"+(query.Genres||"")+"|").indexOf("|"+i+"|")}),renderOptions(context,".officialRatingFilters","chkOfficialRatingFilter",result.OfficialRatings,function(i){return-1!=("|"+(query.OfficialRatings||"")+"|").indexOf("|"+i+"|")}),renderOptions(context,".tagFilters","chkTagFilter",result.Tags,function(i){return-1!=("|"+(query.Tags||"")+"|").indexOf("|"+i+"|")}),renderOptions(context,".yearFilters","chkYearFilter",result.Years,function(i){return-1!=(","+(query.Years||"")+",").indexOf(","+i+",")})}function loadDynamicFilters(context,apiClient,userId,itemQuery){return apiClient.getJSON(apiClient.getUrl("Items/Filters",{UserId:userId,ParentId:itemQuery.ParentId,IncludeItemTypes:itemQuery.IncludeItemTypes})).then(function(result){renderFilters(context,result,itemQuery)})}function updateFilterControls(context,options){var elems,i,length,query=options.query;if("livetvchannels"==options.mode)context.querySelector(".chkFavorite").checked=1==query.IsFavorite,context.querySelector(".chkLikes").checked=1==query.IsLiked,context.querySelector(".chkDislikes").checked=1==query.IsDisliked;else for(elems=context.querySelectorAll(".chkStandardFilter"),i=0,length=elems.length;i
${OptionIsHD}
+
+
+ 4K
+
+
${OptionIsSD}
diff --git a/MediaBrowser.WebDashboard/dashboard-ui/css/librarybrowser.css b/MediaBrowser.WebDashboard/dashboard-ui/css/librarybrowser.css
index e904b7d518..e9a69632da 100644
--- a/MediaBrowser.WebDashboard/dashboard-ui/css/librarybrowser.css
+++ b/MediaBrowser.WebDashboard/dashboard-ui/css/librarybrowser.css
@@ -1 +1 @@
-.headerUserImage,.navMenuOption,.pageTitle{vertical-align:middle}.detailButton-mobile,.itemLinks,.listPaging,.sectionTabs,.viewSettings{text-align:center}.headerSelectedPlayer,.itemMiscInfo{-o-text-overflow:ellipsis;text-overflow:ellipsis;overflow:hidden}.libraryPage{padding-top:7em!important}.itemDetailPage{padding-top:4em!important}.standalonePage{padding-top:4.5em!important}.wizardPage{padding-top:7em!important}.libraryPage:not(.noSecondaryNavPage){padding-top:7.5em!important}.absolutePageTabContent{position:absolute;left:0;right:0;bottom:0;z-index:1;margin:0!important;top:6.9em!important;-webkit-transition:-webkit-transform .2s ease-out;-o-transition:transform .2s ease-out;transition:transform .2s ease-out}.pageTabContent:not(.is-active){display:none!important}.headerUserImage{-webkit-background-size:contain;background-size:contain;background-repeat:no-repeat;background-position:center center;-webkit-border-radius:100em;border-radius:100em;display:inline-block}.headerUserButtonRound img{-webkit-border-radius:100em;border-radius:100em}.headerButton{-webkit-flex-shrink:0;flex-shrink:0}.hideMainDrawer .mainDrawerButton{display:none}.noHeaderRight .headerRight,.noHomeButtonHeader .headerHomeButton{display:none!important}.pageTitle{display:-webkit-inline-box;display:-webkit-inline-flex;display:inline-flex;margin:0 0 0 .5em;height:1.7em;-webkit-box-align:center;-webkit-align-items:center;align-items:center;-webkit-flex-shrink:1;flex-shrink:1}.headerLeft,.skinHeader{display:-webkit-box;display:-webkit-flex}.detailButton-mobile,.skinHeader{-webkit-flex-direction:column;-webkit-box-orient:vertical;-webkit-box-direction:normal}.pageTitleWithLogo{background-position:left center;-webkit-background-size:contain;background-size:contain;background-repeat:no-repeat;width:13.2em}.pageTitleWithDefaultLogo{height:1.22em}.skinHeader{position:fixed;right:0;left:0;z-index:999;top:0;border:0;display:flex;flex-direction:column;contain:layout style paint}.headerLeft,.headerRight{-webkit-box-align:center}.mainAnimatedPages,.pageTabContent{contain:layout style}.hiddenViewMenuBar .skinHeader{display:none}.headerTop{padding:.865em 0}.headerLeft{display:flex;-webkit-align-items:center;align-items:center;-webkit-box-flex:1;-webkit-flex-grow:1;flex-grow:1;overflow:hidden}.sectionTabs{width:100%}.headerRight{display:-webkit-box;display:-webkit-flex;display:flex;-webkit-align-items:center;align-items:center;-webkit-box-pack:end;-webkit-justify-content:flex-end;justify-content:flex-end}.selectedMediaFolder{background-color:#f2f2f2!important}.navMenuOption{display:-webkit-box!important;display:-webkit-flex!important;display:flex!important;-webkit-box-align:center;-webkit-align-items:center;align-items:center;text-decoration:none;color:inherit;padding:.9em 0 .9em 2.4em!important;-webkit-box-flex:1;-webkit-flex-grow:1;flex-grow:1;font-weight:400!important;margin:0!important;-webkit-border-radius:0!important;border-radius:0!important}.layout-desktop .searchTabButton,.layout-mobile .searchTabButton,.layout-tv .headerSearchButton,body:not(.dashboardDocument) .btnNotifications{display:none!important}.navMenuOptionIcon{margin-right:1em;-webkit-flex-shrink:0;flex-shrink:0}.sidebarHeader{padding-left:1.2em;margin:1em 0 .5em}.dashboardDocument .skinBody{-webkit-transition:left ease-in-out .3s,padding ease-in-out .3s;-o-transition:left ease-in-out .3s,padding ease-in-out .3s;transition:left ease-in-out .3s,padding ease-in-out .3s;position:absolute;top:0;right:0;bottom:0;left:0}.mainDrawer-scrollContainer{padding-bottom:10vh}@media all and (min-width:40em){.dashboardDocument .adminDrawerLogo,.dashboardDocument .mainDrawerButton{display:none!important}.dashboardDocument .mainDrawer{z-index:inherit!important;left:0!important;top:0!important;-webkit-transform:none!important;transform:none!important;-webkit-box-shadow:none!important;box-shadow:none!important;width:20.205em!important;font-size:94%}.dashboardDocument .mainDrawer-scrollContainer{margin-top:5em!important}.dashboardDocument withSectionTabs .mainDrawer-scrollContainer{margin-top:8.7em!important}.dashboardDocument .skinBody{left:20em}}@media all and (min-width:40em) and (max-width:84em){.dashboardDocument.withSectionTabs .mainDrawer-scrollContainer{margin-top:8.4em!important}}@media all and (max-width:60em){.libraryDocument .mainDrawerButton{display:none}}@media all and (max-width:84em){.withSectionTabs .headerTop{padding-bottom:.2em}.sectionTabs{font-size:83.5%}}@media all and (min-width:84em){.headerTop{padding:1.489em 0}.headerTabs{-webkit-align-self:center;align-self:center;width:auto;-webkit-box-align:center;-webkit-align-items:center;align-items:center;-webkit-box-pack:center;-webkit-justify-content:center;justify-content:center;margin-top:-3.34em;position:relative;top:-1.05em}.libraryPage:not(.noSecondaryNavPage){padding-top:4.6em!important}.pageWithAbsoluteTabs:not(.noSecondaryNavPage){padding-top:6.7em!important}.absolutePageTabContent{top:5.7em!important}.dashboardDocument.withSectionTabs .mainDrawer-scrollContainer{margin-top:6.1em!important}.dashboardDocument .mainDrawer-scrollContainer{margin-top:6.3em!important}}.headerSelectedPlayer{max-width:10em;white-space:nowrap}@media all and (max-width:37.5em){.headerSelectedPlayer{display:none}}.hidingAnimatedTab{visibility:hidden}.headerArrowImage{height:20px;margin-left:.5em}.backdropContainer{position:fixed;top:0;left:0;right:0;bottom:0;z-index:-1}.libraryPage .header{padding-bottom:0}.flexPageTabContent.is-active{display:-webkit-box!important;display:-webkit-flex!important;display:flex!important}.viewSettings{margin:0 0 .25em}.viewControls+.listTopPaging{margin-left:.5em!important}.criticReview{margin:1.5em 0;background:#222;padding:.8em .8em .8em 3em;-webkit-border-radius:.3em;border-radius:.3em;position:relative}.detailLogo,.itemBackdrop{background-repeat:no-repeat;background-position:center center}.criticReview:first-child{margin-top:.5em}.criticReview img{width:2.4em}.criticRatingScore{margin-bottom:.5em}.itemTag{display:inline-block;margin-right:1em}.itemOverview{white-space:pre-wrap}.itemLinks{padding:0}.itemLinks p{margin:.5em 0}.reviewLink,.reviewerName{margin-top:.5em}.reviewerName{color:#ccc}.reviewDate{margin-left:1em}.reviewScore{position:absolute;left:.8em}.itemBackdrop{-webkit-background-size:cover;background-size:cover;height:50vh;position:relative}.itemBackdropProgressBar{position:absolute!important;bottom:0;left:0;right:0}.itemBackdropFader{position:absolute;bottom:-1px;left:0;right:0;height:15vh}.desktopMiscInfoContainer{position:absolute;bottom:.75em}.detailImageContainer{margin-right:2em;width:280px;-webkit-flex-shrink:0;flex-shrink:0}.detailPagePrimaryContent{position:relative;-webkit-box-flex:1;-webkit-flex-grow:1;flex-grow:1}.detailLogo{width:21.3em;height:5em;position:absolute;top:13.5%;right:19.5%;-webkit-background-size:contain;background-size:contain}@media all and (max-width:87.5em){.detailLogo{right:5%}}@media all and (max-width:75em){.detailLogo{right:2%}}@media all and (max-width:68.75em){.detailLogo{width:14.91em;height:3.5em;right:5%;bottom:5%;top:auto;background-position:center right;display:none}}.itemDetailImage{width:100%}.thumbDetailImageContainer{width:400px}.itemDetailImage.loaded{-webkit-box-shadow:0 .0725em .29em 0 rgba(0,0,0,.37);box-shadow:0 .0725em .29em 0 rgba(0,0,0,.37)}@media all and (max-width:62.5em){.detailPageContent{position:relative}.detailImageContainer{position:absolute;top:-90px;left:5%;width:auto}.itemDetailImage{height:120px;width:auto!important}.btnPlaySimple{display:none!important}}@media all and (min-width:62.5em){.itemBackdrop{display:none}.detailPagePrimaryContainer{display:-webkit-box;display:-webkit-flex;display:flex;margin-bottom:3.6em}}@media all and (max-width:75em){.lnkSibling{display:none!important}}.parentName{display:block;margin-bottom:.5em}.emby-button.detailFloatingButton{position:absolute;background-color:rgba(0,0,0,.5)!important;z-index:1;top:50%;left:50%;margin:-2.2em 0 0 -2.2em;border:2.7px solid rgba(255,255,255,.6);padding:.38em!important;color:rgba(255,255,255,.76)}.emby-button.detailFloatingButton i{font-size:3.5em}@media all and (max-width:62.5em){.parentName{margin-bottom:1em}.itemDetailPage{padding-top:0!important}.detailimg-hidemobile{display:none}}@media all and (min-width:31.25em){.mobileDetails{display:none}}@media all and (max-width:31.25em){.desktopDetails{display:none!important}}.detailButton-mobile,.mainDetailButtons{display:-webkit-box;display:-webkit-flex}.itemName{margin:.5em 0}.empty{margin:0}.detailCollapsibleSection:not(.hide)+.detailCollapsibleSection{margin-top:-2em}.detailPageCollabsible{margin-top:0}.mainDetailButtons{display:flex;-webkit-box-align:center;-webkit-align-items:center;align-items:center;-webkit-flex-wrap:wrap;flex-wrap:wrap;margin:1em 0}.recordingFields button{margin-left:0;margin-right:.5em;-webkit-flex-shrink:0;flex-shrink:0}.mainDetailButtons.hide+.recordingFields{margin-top:1.5em!important}.detailButton-mobile{display:flex;flex-direction:column;-webkit-box-pack:center;-webkit-justify-content:center;justify-content:center;-webkit-box-align:center;-webkit-align-items:center;align-items:center;margin:0!important;padding:.5em .7em!important}.detailButton{margin:0 .5em 0 0!important}@media all and (min-width:29em){.detailButton-mobile{padding-left:.75em!important;padding-right:.75em!important}}@media all and (min-width:32em){.detailButton-mobile{padding-left:.8em!important;padding-right:.8em!important}}@media all and (min-width:35em){.detailButton-mobile{padding-left:.85em!important;padding-right:.85em!important}}.detailButton-mobile-content{display:-webkit-box;display:-webkit-flex;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;flex-direction:column;-webkit-box-pack:center;-webkit-justify-content:center;justify-content:center;-webkit-box-align:center;-webkit-align-items:center;align-items:center}.detailButton-mobile-icon{font-size:1.6em!important;width:1em;height:1em}.detailImageProgressContainer{position:absolute;bottom:4px;right:1px;left:1px;text-align:center}.detailButton-mobile-text{margin-top:.7em;font-size:80%;font-weight:400}@media all and (max-width:62.5em){.mainDetailButtons{margin-left:-.5em}.detailButton{display:none!important}}@media all and (min-width:62.5em){.detailButton-mobile{display:none!important}.mainDetailButtons{font-size:108%;margin:1.25em 0}}.listTopPaging,.viewControls{display:inline-block}@media all and (max-width:50em){.editorMenuLink{display:none}}.itemMiscInfo{display:-webkit-box;display:-webkit-flex;display:flex;-webkit-flex-wrap:wrap;flex-wrap:wrap;-webkit-box-align:center;-webkit-align-items:center;align-items:center}@media all and (max-width:31.25em){.mobileDetails .itemMiscInfo{text-align:center;-webkit-box-pack:center;-webkit-justify-content:center;justify-content:center}.itemMiscInfo .endsAt{display:none}}.layout-tv .detailVerticalSection{margin-bottom:3.4em!important}.detailPageContent{border-spacing:0;border-collapse:collapse;padding-top:3em}@media all and (max-width:62.5em){.detailPageContent-nodetailimg{padding-top:0;margin-top:-3em}}@media all and (min-width:75em){.itemDetailPage .padded-left{padding-left:4%!important}.itemDetailPage .padded-right{padding-right:4%!important}}.mediaInfoStream{margin:0 3em 0 0;display:inline-block;vertical-align:top}.mediaInfoStreamType{display:block;margin:1em 0}.mediaInfoAttribute,.mediaInfoLabel{display:inline-block}.mediaInfoLabel{margin-right:1em;font-weight:600}.recordingProgressBar::-moz-progress-bar{background-color:#c33}.recordingProgressBar::-webkit-progress-value{background-color:#c33}.recordingProgressBar[aria-valuenow]:before{background-color:#c33}.timelineHeader{margin-bottom:.25em;line-height:1.25em;line-height:initial}.itemsContainer{margin:0 auto}@media all and (max-height:31.25em){.itemBackdrop{height:52vh}}@media all and (max-width:75em){.listViewUserDataButtons{display:none!important}}@media all and (max-width:62.5em){.detailsHiddenOnMobile{display:none}}.btnSyncComplete{background:#673AB7!important}.btnSyncComplete i{-webkit-border-radius:1000px;border-radius:1000px}.bulletSeparator{margin:0 .35em}.mediaInfoIcons{display:-webkit-box;display:-webkit-flex;display:flex;-webkit-box-align:center;-webkit-align-items:center;align-items:center;margin:1em 0;-webkit-flex-wrap:wrap;flex-wrap:wrap}.verticalSection-extrabottompadding{margin-bottom:2.7em}.sectionTitleContainer{margin:1.25em 0}.sectionTitleButton,.sectionTitleIconButton{margin-right:0!important;display:inline-block;vertical-align:middle}.sectionTitleContainer-cards{margin-bottom:.1em}.sectionTitle{margin-bottom:1em}.sectionTitle-cards{margin-left:.55em;margin-bottom:0}@media all and (max-width:50em){.sectionTitle-cards{margin-left:.28em}}.sectionTitleContainer>.sectionTitle{margin-top:0;margin-bottom:0;display:inline-block;vertical-align:middle}.sectionTitleButton{margin-left:1.5em!important;-webkit-flex-shrink:0;flex-shrink:0}.sectionTitleButton+.sectionTitleButton{margin-left:.5em!important}.sectionTitleIconButton{margin-left:1.5em!important;-webkit-flex-shrink:0;flex-shrink:0;font-size:84%!important;padding:.5em!important}.horizontalItemsContainer{display:-webkit-box;display:-webkit-flex;display:flex}.sectionTitleTextButton{margin:0!important;display:-webkit-inline-box!important;display:-webkit-inline-flex!important;display:inline-flex!important;color:inherit!important}.sectionTitleTextButton:not(.padded-left){padding:0!important}.sectionTitleTextButton.padded-left{padding-bottom:0!important;padding-right:0!important;padding-top:0!important}.sectionTitleTextButton>.sectionTitle{margin-bottom:0;margin-top:0}.padded-left{padding-left:2%}.padded-right{padding-right:2%}.padded-top{padding-top:1em}.padded-bottom{padding-bottom:1em}.layout-tv .padded-top-focusscale{padding-top:1.6em;margin-top:-1.6em}.layout-tv .padded-bottom-focusscale{padding-bottom:1.6em;margin-bottom:-1.6em}@media all and (min-height:500px){.padded-left-withalphapicker{padding-left:7.5%}.padded-right-withalphapicker{padding-right:7.5%}}@media all and (min-width:500px){.padded-left{padding-left:6%}.padded-right{padding-right:6%}}@media all and (min-width:600px){.padded-left{padding-left:4%}.padded-right{padding-right:4%}}@media all and (min-width:800px){.padded-left{padding-left:3.2%}.padded-right{padding-right:3.2%}}@media all and (min-width:1280px){.padded-left{padding-left:3.3%}.padded-right{padding-right:3.3%}}@media all and (min-width:800px){.layout-tv .padded-left-withalphapicker{padding-left:4.5%}.layout-tv .padded-right-withalphapicker{padding-right:4.5%}}.searchfields-icon{color:#aaa}.button-accent-flat{color:#52B54B!important}.clearLink{text-decoration:none;font-weight:inherit!important;vertical-align:middle;color:inherit!important}.itemsViewSettingsContainer{-webkit-box-pack:center;-webkit-justify-content:center;justify-content:center}@media all and (min-width:40em){.listIconButton-autohide{display:none!important}}@media all and (max-width:40em){.listTextButton-autohide{display:none!important}}.layout-tv .itemsViewSettingsContainer{-webkit-box-pack:end;-webkit-justify-content:flex-end;justify-content:flex-end;padding:1.5em .75em 1em 0;font-size:92%}.itemsViewSettingsContainer>.button-flat{margin:0}
\ No newline at end of file
+.headerUserImage,.navMenuOption,.pageTitle{vertical-align:middle}.detailButton-mobile,.itemLinks,.listPaging,.sectionTabs,.viewSettings{text-align:center}.headerSelectedPlayer,.itemMiscInfo{-o-text-overflow:ellipsis;text-overflow:ellipsis;overflow:hidden}.libraryPage{padding-top:7em!important}.itemDetailPage{padding-top:4em!important}.standalonePage{padding-top:4.5em!important}.wizardPage{padding-top:7em!important}.libraryPage:not(.noSecondaryNavPage){padding-top:7.5em!important}.absolutePageTabContent{position:absolute;left:0;right:0;bottom:0;z-index:1;margin:0!important;top:6.9em!important;-webkit-transition:-webkit-transform .2s ease-out;-o-transition:transform .2s ease-out;transition:transform .2s ease-out}.pageTabContent:not(.is-active){display:none!important}.headerUserImage{-webkit-background-size:contain;background-size:contain;background-repeat:no-repeat;background-position:center center;-webkit-border-radius:100em;border-radius:100em;display:inline-block}.headerUserButtonRound img{-webkit-border-radius:100em;border-radius:100em}.headerButton{-webkit-flex-shrink:0;flex-shrink:0}.hideMainDrawer .mainDrawerButton{display:none}.noHeaderRight .headerRight,.noHomeButtonHeader .headerHomeButton{display:none!important}.pageTitle{display:-webkit-inline-box;display:-webkit-inline-flex;display:inline-flex;margin:0 0 0 .5em;height:1.7em;-webkit-box-align:center;-webkit-align-items:center;align-items:center;-webkit-flex-shrink:1;flex-shrink:1}.headerLeft,.skinHeader{display:-webkit-box;display:-webkit-flex}.detailButton-mobile,.skinHeader{-webkit-flex-direction:column;-webkit-box-orient:vertical;-webkit-box-direction:normal}.pageTitleWithLogo{background-position:left center;-webkit-background-size:contain;background-size:contain;background-repeat:no-repeat;width:13.2em}.pageTitleWithDefaultLogo{height:1.22em}.skinHeader{position:fixed;right:0;left:0;z-index:999;top:0;border:0;display:flex;flex-direction:column;contain:layout style paint}.headerLeft,.headerRight{-webkit-box-align:center}.mainAnimatedPages,.pageTabContent{contain:layout style}.hiddenViewMenuBar .skinHeader{display:none}.headerTop{padding:.865em 0}.headerLeft{display:flex;-webkit-align-items:center;align-items:center;-webkit-box-flex:1;-webkit-flex-grow:1;flex-grow:1;overflow:hidden}.sectionTabs{width:100%}.headerRight{display:-webkit-box;display:-webkit-flex;display:flex;-webkit-align-items:center;align-items:center;-webkit-box-pack:end;-webkit-justify-content:flex-end;justify-content:flex-end}.selectedMediaFolder{background-color:#f2f2f2!important}.navMenuOption{display:-webkit-box!important;display:-webkit-flex!important;display:flex!important;-webkit-box-align:center;-webkit-align-items:center;align-items:center;text-decoration:none;color:inherit;padding:.9em 0 .9em 2.4em!important;-webkit-box-flex:1;-webkit-flex-grow:1;flex-grow:1;font-weight:400!important;margin:0!important;-webkit-border-radius:0!important;border-radius:0!important}.layout-desktop .searchTabButton,.layout-mobile .searchTabButton,.layout-tv .headerSearchButton,body:not(.dashboardDocument) .btnNotifications{display:none!important}.navMenuOptionIcon{margin-right:1em;-webkit-flex-shrink:0;flex-shrink:0}.sidebarHeader{padding-left:1.2em;margin:1em 0 .5em}.dashboardDocument .skinBody{-webkit-transition:left ease-in-out .3s,padding ease-in-out .3s;-o-transition:left ease-in-out .3s,padding ease-in-out .3s;transition:left ease-in-out .3s,padding ease-in-out .3s;position:absolute;top:0;right:0;bottom:0;left:0}.mainDrawer-scrollContainer{padding-bottom:10vh}@media all and (min-width:40em){.dashboardDocument .adminDrawerLogo,.dashboardDocument .mainDrawerButton{display:none!important}.dashboardDocument .mainDrawer{z-index:inherit!important;left:0!important;top:0!important;-webkit-transform:none!important;transform:none!important;-webkit-box-shadow:none!important;box-shadow:none!important;width:20.205em!important;font-size:94%}.dashboardDocument .mainDrawer-scrollContainer{margin-top:5em!important}.dashboardDocument withSectionTabs .mainDrawer-scrollContainer{margin-top:8.7em!important}.dashboardDocument .skinBody{left:20em}}@media all and (min-width:40em) and (max-width:84em){.dashboardDocument.withSectionTabs .mainDrawer-scrollContainer{margin-top:8.4em!important}}@media all and (max-width:60em){.libraryDocument .mainDrawerButton{display:none}}@media all and (max-width:84em){.withSectionTabs .headerTop{padding-bottom:.2em}.sectionTabs{font-size:83.5%}}@media all and (min-width:84em){.headerTop{padding:1.489em 0}.headerTabs{-webkit-align-self:center;align-self:center;width:auto;-webkit-box-align:center;-webkit-align-items:center;align-items:center;-webkit-box-pack:center;-webkit-justify-content:center;justify-content:center;margin-top:-3.34em;position:relative;top:-1.05em}.libraryPage:not(.noSecondaryNavPage){padding-top:4.6em!important}.pageWithAbsoluteTabs:not(.noSecondaryNavPage){padding-top:6.7em!important}.absolutePageTabContent{top:5.7em!important}.dashboardDocument.withSectionTabs .mainDrawer-scrollContainer{margin-top:6.1em!important}.dashboardDocument .mainDrawer-scrollContainer{margin-top:6.3em!important}}.headerSelectedPlayer{max-width:10em;white-space:nowrap}@media all and (max-width:37.5em){.headerSelectedPlayer{display:none}}.hidingAnimatedTab{visibility:hidden}.headerArrowImage{height:20px;margin-left:.5em}.backdropContainer{position:fixed;top:0;left:0;right:0;bottom:0;z-index:-1}.libraryPage .header{padding-bottom:0}.flexPageTabContent.is-active{display:-webkit-box!important;display:-webkit-flex!important;display:flex!important}.viewSettings{margin:0 0 .25em}.viewControls+.listTopPaging{margin-left:.5em!important}.criticReview{margin:1.5em 0;background:#222;padding:.8em .8em .8em 3em;-webkit-border-radius:.3em;border-radius:.3em;position:relative}.detailLogo,.itemBackdrop{background-repeat:no-repeat;background-position:center center}.criticReview:first-child{margin-top:.5em}.criticReview img{width:2.4em}.criticRatingScore{margin-bottom:.5em}.itemTag{display:inline-block;margin-right:1em}.itemOverview{white-space:pre-wrap}.itemLinks{padding:0}.itemLinks p{margin:.5em 0}.reviewLink,.reviewerName{margin-top:.5em}.reviewerName{color:#ccc}.reviewDate{margin-left:1em}.reviewScore{position:absolute;left:.8em}.itemBackdrop{-webkit-background-size:cover;background-size:cover;height:50vh;position:relative}.itemBackdropProgressBar{position:absolute!important;bottom:0;left:0;right:0}.itemBackdropFader{position:absolute;bottom:-1px;left:0;right:0;height:15vh}.desktopMiscInfoContainer{position:absolute;bottom:.75em}.detailImageContainer{margin-right:2em;width:280px;-webkit-flex-shrink:0;flex-shrink:0}.detailPagePrimaryContent{position:relative;-webkit-box-flex:1;-webkit-flex-grow:1;flex-grow:1}.detailLogo{width:21.3em;height:5em;position:absolute;top:13.5%;right:19.5%;-webkit-background-size:contain;background-size:contain}@media all and (max-width:87.5em){.detailLogo{right:5%}}@media all and (max-width:75em){.detailLogo{right:2%}}@media all and (max-width:68.75em){.detailLogo{width:14.91em;height:3.5em;right:5%;bottom:5%;top:auto;background-position:center right;display:none}}.itemDetailImage{width:100%}.thumbDetailImageContainer{width:400px}.itemDetailImage.loaded{-webkit-box-shadow:0 .0725em .29em 0 rgba(0,0,0,.37);box-shadow:0 .0725em .29em 0 rgba(0,0,0,.37)}@media all and (max-width:62.5em){.detailPageContent{position:relative}.detailImageContainer{position:absolute;top:-90px;left:5%;width:auto}.itemDetailImage{height:120px;width:auto!important}.btnPlaySimple{display:none!important}}@media all and (min-width:62.5em){.itemBackdrop{display:none}.detailPagePrimaryContainer{display:-webkit-box;display:-webkit-flex;display:flex;margin-bottom:3.6em}}@media all and (max-width:75em){.lnkSibling{display:none!important}}.parentName{display:block;margin-bottom:.5em}.emby-button.detailFloatingButton{position:absolute;background-color:rgba(0,0,0,.5)!important;z-index:1;top:50%;left:50%;margin:-2.2em 0 0 -2.2em;border:2.7px solid rgba(255,255,255,.6);padding:.38em!important;color:rgba(255,255,255,.76)}.emby-button.detailFloatingButton i{font-size:3.5em}@media all and (max-width:62.5em){.parentName{margin-bottom:1em}.itemDetailPage{padding-top:0!important}.detailimg-hidemobile{display:none}}@media all and (min-width:31.25em){.mobileDetails{display:none}}@media all and (max-width:31.25em){.desktopDetails{display:none!important}}.detailButton-mobile,.mainDetailButtons{display:-webkit-box;display:-webkit-flex}.itemName{margin:.5em 0}.empty{margin:0}.detailCollapsibleSection:not(.hide)+.detailCollapsibleSection{margin-top:-2em}.detailPageCollabsible{margin-top:0}.mainDetailButtons{display:flex;-webkit-box-align:center;-webkit-align-items:center;align-items:center;-webkit-flex-wrap:wrap;flex-wrap:wrap;margin:1em 0}.recordingFields button{margin-left:0;margin-right:.5em;-webkit-flex-shrink:0;flex-shrink:0}.mainDetailButtons.hide+.recordingFields{margin-top:1.5em!important}.detailButton-mobile{display:flex;flex-direction:column;-webkit-box-pack:center;-webkit-justify-content:center;justify-content:center;-webkit-box-align:center;-webkit-align-items:center;align-items:center;margin:0!important;padding:.5em .7em!important}.detailButton{margin:0 .5em 0 0!important}@media all and (min-width:29em){.detailButton-mobile{padding-left:.75em!important;padding-right:.75em!important}}@media all and (min-width:32em){.detailButton-mobile{padding-left:.8em!important;padding-right:.8em!important}}@media all and (min-width:35em){.detailButton-mobile{padding-left:.85em!important;padding-right:.85em!important}}.detailButton-mobile-content{display:-webkit-box;display:-webkit-flex;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;flex-direction:column;-webkit-box-pack:center;-webkit-justify-content:center;justify-content:center;-webkit-box-align:center;-webkit-align-items:center;align-items:center}.detailButton-mobile-icon{font-size:1.6em!important;width:1em;height:1em}.detailImageProgressContainer{position:absolute;bottom:4px;right:1px;left:1px;text-align:center}.detailButton-mobile-text{margin-top:.7em;font-size:80%;font-weight:400}@media all and (max-width:62.5em){.mainDetailButtons{margin-left:-.5em}.detailButton{display:none!important}}@media all and (min-width:62.5em){.detailButton-mobile{display:none!important}.mainDetailButtons{font-size:108%;margin:1.25em 0}}.listTopPaging,.viewControls{display:inline-block}@media all and (max-width:50em){.editorMenuLink{display:none}}.itemMiscInfo{display:-webkit-box;display:-webkit-flex;display:flex;-webkit-flex-wrap:wrap;flex-wrap:wrap;-webkit-box-align:center;-webkit-align-items:center;align-items:center}@media all and (max-width:31.25em){.mobileDetails .itemMiscInfo{text-align:center;-webkit-box-pack:center;-webkit-justify-content:center;justify-content:center}.itemMiscInfo .endsAt{display:none}}.layout-tv .detailVerticalSection{margin-bottom:3.4em!important}.detailPageContent{border-spacing:0;border-collapse:collapse;padding-top:3em}@media all and (max-width:62.5em){.detailPageContent-nodetailimg{padding-top:0;margin-top:-3em}}@media all and (min-width:75em){.itemDetailPage .padded-left{padding-left:4%!important}.itemDetailPage .padded-right{padding-right:4%!important}}.mediaInfoStream{margin:0 3em 0 0;display:inline-block;vertical-align:top}.mediaInfoStreamType{display:block;margin:1em 0}.mediaInfoAttribute,.mediaInfoLabel{display:inline-block}.mediaInfoLabel{margin-right:1em;font-weight:600}.recordingProgressBar::-moz-progress-bar{background-color:#c33}.recordingProgressBar::-webkit-progress-value{background-color:#c33}.recordingProgressBar[aria-valuenow]:before{background-color:#c33}.timelineHeader{margin-bottom:.25em;line-height:1.25em;line-height:initial}.itemsContainer{margin:0 auto}@media all and (max-height:31.25em){.itemBackdrop{height:52vh}}@media all and (max-width:75em){.listViewUserDataButtons{display:none!important}}@media all and (max-width:62.5em){.detailsHiddenOnMobile{display:none}}.btnSyncComplete{background:#673AB7!important}.btnSyncComplete i{-webkit-border-radius:100em;border-radius:100em}.bulletSeparator{margin:0 .35em}.mediaInfoIcons{display:-webkit-box;display:-webkit-flex;display:flex;-webkit-box-align:center;-webkit-align-items:center;align-items:center;margin:1em 0;-webkit-flex-wrap:wrap;flex-wrap:wrap}.verticalSection-extrabottompadding{margin-bottom:2.7em}.sectionTitleContainer{margin:1.25em 0}.sectionTitleButton,.sectionTitleIconButton{margin-right:0!important;display:inline-block;vertical-align:middle}.sectionTitleContainer-cards{margin-bottom:.1em}.sectionTitle{margin-bottom:1em}.sectionTitle-cards{margin-left:.28em;margin-bottom:0}@media all and (min-width:50em){.sectionTitle-cards{margin-left:.6em}}.sectionTitleContainer>.sectionTitle{margin-top:0;margin-bottom:0;display:inline-block;vertical-align:middle}.sectionTitleButton{margin-left:1.5em!important;-webkit-flex-shrink:0;flex-shrink:0}.sectionTitleButton+.sectionTitleButton{margin-left:.5em!important}.sectionTitleIconButton{margin-left:1.5em!important;-webkit-flex-shrink:0;flex-shrink:0;font-size:84%!important;padding:.5em!important}.horizontalItemsContainer{display:-webkit-box;display:-webkit-flex;display:flex}.sectionTitleTextButton{margin:0!important;display:-webkit-inline-box!important;display:-webkit-inline-flex!important;display:inline-flex!important;color:inherit!important}.sectionTitleTextButton:not(.padded-left){padding:0!important}.sectionTitleTextButton.padded-left{padding-bottom:0!important;padding-right:0!important;padding-top:0!important}.sectionTitleTextButton>.sectionTitle{margin-bottom:0;margin-top:0}.padded-left{padding-left:2%}.padded-right{padding-right:2%}.padded-top{padding-top:1em}.padded-bottom{padding-bottom:1em}.layout-tv .padded-top-focusscale{padding-top:1.6em;margin-top:-1.6em}.layout-tv .padded-bottom-focusscale{padding-bottom:1.6em;margin-bottom:-1.6em}@media all and (min-height:31.25em){.padded-left-withalphapicker{padding-left:7.5%}.padded-right-withalphapicker{padding-right:7.5%}}@media all and (min-width:31.25em){.padded-left{padding-left:6%}.padded-right{padding-right:6%}}@media all and (min-width:37.5em){.padded-left{padding-left:4%}.padded-right{padding-right:4%}}@media all and (min-width:50em){.padded-left{padding-left:3.2%}.padded-right{padding-right:3.2%}}@media all and (min-width:64em){.padded-left{padding-left:3.1%}.padded-right{padding-right:3.1%}}@media all and (min-width:50em){.layout-tv .padded-left-withalphapicker{padding-left:4.5%}.layout-tv .padded-right-withalphapicker{padding-right:4.5%}}.searchfields-icon{color:#aaa}.button-accent-flat{color:#52B54B!important}.clearLink{text-decoration:none;font-weight:inherit!important;vertical-align:middle;color:inherit!important}.itemsViewSettingsContainer{-webkit-box-pack:center;-webkit-justify-content:center;justify-content:center}@media all and (min-width:40em){.listIconButton-autohide{display:none!important}}@media all and (max-width:40em){.listTextButton-autohide{display:none!important}}.layout-tv .itemsViewSettingsContainer{-webkit-box-pack:end;-webkit-justify-content:flex-end;justify-content:flex-end;padding:1.5em .75em 1em 0;font-size:92%}.itemsViewSettingsContainer>.button-flat{margin:0}
\ No newline at end of file
diff --git a/MediaBrowser.WebDashboard/dashboard-ui/device.html b/MediaBrowser.WebDashboard/dashboard-ui/device.html
deleted file mode 100644
index 3623b8597d..0000000000
--- a/MediaBrowser.WebDashboard/dashboard-ui/device.html
+++ /dev/null
@@ -1,36 +0,0 @@
-
\ No newline at end of file
diff --git a/MediaBrowser.WebDashboard/dashboard-ui/devices.html b/MediaBrowser.WebDashboard/dashboard-ui/devices.html
index cc143e5f43..58825ed64e 100644
--- a/MediaBrowser.WebDashboard/dashboard-ui/devices.html
+++ b/MediaBrowser.WebDashboard/dashboard-ui/devices.html
@@ -1,21 +1,19 @@
-
+
-
-
${TabDevices}
+
+
${TabDevices}
-
diff --git a/MediaBrowser.WebDashboard/dashboard-ui/scripts/dashboardpage.js b/MediaBrowser.WebDashboard/dashboard-ui/scripts/dashboardpage.js
index 826795f4d3..f9318cb292 100644
--- a/MediaBrowser.WebDashboard/dashboard-ui/scripts/dashboardpage.js
+++ b/MediaBrowser.WebDashboard/dashboard-ui/scripts/dashboardpage.js
@@ -1,2 +1,2 @@
-define(["datetime","jQuery","events","itemHelper","serverNotifications","dom","globalize","loading","connectionManager","playMethodHelper","cardBuilder","imageLoader","components/activitylog","humanedate","listViewStyle","emby-linkbutton","flexStyles","buttonenabled","emby-button","emby-itemscontainer"],function(datetime,$,events,itemHelper,serverNotifications,dom,globalize,loading,connectionManager,playMethodHelper,cardBuilder,imageLoader,ActivityLog){"use strict";function onConnectionHelpClick(e){return e.preventDefault(),!1}function onEditServerNameClick(e){var page=dom.parentWithClass(this,"page");return require(["prompt"],function(prompt){prompt({label:globalize.translate("LabelFriendlyServerName"),description:globalize.translate("LabelFriendlyServerNameHelp"),value:page.querySelector(".serverNameHeader").innerHTML,confirmText:globalize.translate("ButtonSave")}).then(function(value){loading.show(),ApiClient.getServerConfiguration().then(function(config){config.ServerName=value,ApiClient.updateServerConfiguration(config).then(function(){page.querySelector(".serverNameHeader").innerHTML=value,loading.hide()})})})}),e.preventDefault(),!1}function showPlaybackInfo(btn,session){require(["alert"],function(alert){var showTranscodeReasons,title,text=[],displayPlayMethod=playMethodHelper.getDisplayPlayMethod(session),isDirectStream="DirectStream"===displayPlayMethod,isTranscode="Transcode"===displayPlayMethod;isDirectStream?(title=globalize.translate("sharedcomponents#DirectStreaming"),text.push(globalize.translate("sharedcomponents#DirectStreamHelp1")),text.push("
"),text.push(globalize.translate("sharedcomponents#DirectStreamHelp2"))):isTranscode&&(title=globalize.translate("sharedcomponents#Transcoding"),text.push(globalize.translate("sharedcomponents#MediaIsBeingConverted")),session.TranscodingInfo&&session.TranscodingInfo.TranscodeReasons&&session.TranscodingInfo.TranscodeReasons.length&&(text.push("
"),text.push(globalize.translate("sharedcomponents#LabelReasonForTranscoding")),showTranscodeReasons=!0)),showTranscodeReasons&&session.TranscodingInfo.TranscodeReasons.forEach(function(t){text.push(globalize.translate("sharedcomponents#"+t))}),alert({text:text.join("
"),title:title})})}function showSendMessageForm(btn,session){require(["prompt"],function(prompt){prompt({title:globalize.translate("HeaderSendMessage"),label:globalize.translate("LabelMessageText"),confirmText:globalize.translate("ButtonSend")}).then(function(text){if(text){connectionManager.getApiClient(session.ServerId).sendMessageCommand(session.Id,{Text:text,TimeoutMs:5e3})}})})}function showOptionsMenu(btn,session){require(["actionsheet"],function(actionsheet){var menuItems=[];return session.ServerId&&session.DeviceId!==connectionManager.deviceId()&&menuItems.push({name:globalize.translate("SendMessage"),id:"sendmessage"}),session.TranscodingInfo&&session.TranscodingInfo.TranscodeReasons&&session.TranscodingInfo.TranscodeReasons.length&&menuItems.push({name:globalize.translate("ViewPlaybackInfo"),id:"transcodinginfo"}),actionsheet.show({items:menuItems,positionTo:btn}).then(function(id){switch(id){case"sendmessage":showSendMessageForm(btn,session);break;case"transcodinginfo":showPlaybackInfo(btn,session)}})})}function onActiveDevicesClick(e){var btn=dom.parentWithClass(e.target,"sessionCardButton");if(btn){var card=dom.parentWithClass(btn,"card");if(card){var sessionId=card.id,session=(DashboardPage.sessionsList||[]).filter(function(s){return"session"+s.Id===sessionId})[0];session&&(btn.classList.contains("btnCardOptions")?showOptionsMenu(btn,session):btn.classList.contains("btnSessionInfo")?showPlaybackInfo(btn,session):btn.classList.contains("btnSessionSendMessage")?showSendMessageForm(btn,session):btn.classList.contains("btnSessionStop")?connectionManager.getApiClient(session.ServerId).sendPlayStateCommand(session.Id,"Stop"):btn.classList.contains("btnSessionPlayPause")&&session.PlayState&&connectionManager.getApiClient(session.ServerId).sendPlayStateCommand(session.Id,"PlayPause"))}}}function filterSessions(sessions){for(var list=[],i=0,length=sessions.length;i
'+globalize.translate("PleaseUpdateManually")+""),DashboardPage.renderPaths(view,systemInfo),renderHasPendingRestart(view,apiClient,systemInfo.HasPendingRestart)})}function renderInfo(view,sessions,forceUpdate){sessions=filterSessions(sessions),renderActiveConnections(view,sessions),DashboardPage.renderPluginUpdateInfo(view,forceUpdate),loading.hide()}function pollForInfo(view,apiClient,forceUpdate){apiClient.getSessions().then(function(sessions){renderInfo(view,sessions,forceUpdate)}),apiClient.getScheduledTasks().then(function(tasks){renderRunningTasks(view,tasks)})}function renderActiveConnections(view,sessions){var html="";DashboardPage.sessionsList=sessions;var parentElement=view.querySelector(".activeDevices");$(".card",parentElement).addClass("deadSession");for(var i=0,length=sessions.length;i',html+='',html+='
',html+='
',html+='
';var imgUrl=DashboardPage.getNowPlayingImageUrl(nowPlayingItem);imgUrl?(html+='
",html+='
',html+='
';var clientImage=DashboardPage.getClientImage(session);clientImage&&(html+=clientImage),html+='
',html+='
'+session.DeviceName+"
",html+='
'+DashboardPage.getAppSecondaryText(session)+"
",html+="
",html+="
",html+='
'+DashboardPage.getSessionNowPlayingTime(session)+"
",session.TranscodingInfo&&session.TranscodingInfo.Framerate?html+='
'+session.TranscodingInfo.Framerate+" fps
":html+='
';var nowPlayingName=DashboardPage.getNowPlayingName(session);if(html+='
',html+=nowPlayingName.html,html+="
",nowPlayingItem&&nowPlayingItem.RunTimeTicks){html+='
'}else html+='
';session.TranscodingInfo&&session.TranscodingInfo.CompletionPercentage?html+='
':html+='
',html+="
",html+="
",html+="
",html+='",html+="
",html+=" "}}parentElement.insertAdjacentHTML("beforeend",html),$(".deadSession",parentElement).remove()}function renderRunningTasks(view,tasks){var html="";tasks=tasks.filter(function(t){return"Idle"!=t.State&&!t.IsHidden}),tasks.length?view.querySelector(".runningTasksContainer").classList.remove("hide"):view.querySelector(".runningTasksContainer").classList.add("hide"),tasks.filter(function(t){return t.Key==DashboardPage.systemUpdateTaskKey}).length?$("#btnUpdateApplication",view).buttonEnabled(!1):$("#btnUpdateApplication",view).buttonEnabled(!0);for(var i=0,length=tasks.length;i
",html+=task.Name+" ","Running"==task.State){var progress=(task.CurrentProgressPercentage||0).toFixed(1);html+='',html+=progress+"%",html+=" ",html+=""+progress+"% ",html+='cancel '}else"Cancelling"==task.State&&(html+=''+globalize.translate("LabelStopping")+" ");html+=""}view.querySelector("#divRunningTasks").innerHTML=html}return window.DashboardPage={newsStartIndex:0,renderPaths:function(page,systemInfo){$("#cachePath",page).html(systemInfo.CachePath),$("#logPath",page).html(systemInfo.LogPath),$("#transcodingTemporaryPath",page).html(systemInfo.TranscodingTempPath),$("#metadataPath",page).html(systemInfo.InternalMetadataPath)},reloadNews:function(page){var query={StartIndex:DashboardPage.newsStartIndex,Limit:4};ApiClient.getProductNews(query).then(function(result){var html=result.Items.map(function(item){var itemHtml="";itemHtml+='',itemHtml+='',itemHtml+='
dvr ',itemHtml+='
',itemHtml+='
',itemHtml+=item.Title,itemHtml+="
",itemHtml+='
';var date=datetime.parseISO8601Date(item.Date,!0);return itemHtml+=datetime.toLocaleDateString(date),itemHtml+="
",itemHtml+="
",itemHtml+="
",itemHtml+=" "});page.querySelector(".latestNewsItems").innerHTML=html.join("")})},startInterval:function(apiClient){apiClient.sendMessage("SessionsStart","0,1500"),apiClient.sendMessage("ScheduledTasksInfoStart","0,1000")},stopInterval:function(apiClient){apiClient.sendMessage("SessionsStop"),apiClient.sendMessage("ScheduledTasksInfoStop")},getSessionNowPlayingStreamInfo:function(session){var html="",showTranscodingInfo=!1,displayPlayMethod=playMethodHelper.getDisplayPlayMethod(session);if("DirectStream"===displayPlayMethod?(html+=globalize.translate("sharedcomponents#DirectStreaming"),!0):"Transcode"==displayPlayMethod?(html+=globalize.translate("sharedcomponents#Transcoding"),session.TranscodingInfo&&session.TranscodingInfo.Framerate&&(html+=" ("+session.TranscodingInfo.Framerate+" fps)"),showTranscodingInfo=!0,!0):"DirectPlay"==displayPlayMethod&&(html+=globalize.translate("sharedcomponents#DirectPlaying")),showTranscodingInfo){var line=[];session.TranscodingInfo&&(session.TranscodingInfo.Bitrate&&(session.TranscodingInfo.Bitrate>1e6?line.push((session.TranscodingInfo.Bitrate/1e6).toFixed(1)+" Mbps"):line.push(Math.floor(session.TranscodingInfo.Bitrate/1e3)+" kbps")),session.TranscodingInfo.Container&&line.push(session.TranscodingInfo.Container),session.TranscodingInfo.VideoCodec&&line.push(session.TranscodingInfo.VideoCodec),session.TranscodingInfo.AudioCodec&&session.TranscodingInfo.AudioCodec!=session.TranscodingInfo.Container&&line.push(session.TranscodingInfo.AudioCodec)),line.length&&(html+=" - "+line.join(" "))}return html||" "},getSessionNowPlayingTime:function(session){var nowPlayingItem=session.NowPlayingItem,html="";return nowPlayingItem?(session.PlayState.PositionTicks?html+=datetime.getDisplayRunningTime(session.PlayState.PositionTicks):html+="--:--:--",html+=" / ",nowPlayingItem&&nowPlayingItem.RunTimeTicks?html+=datetime.getDisplayRunningTime(nowPlayingItem.RunTimeTicks):html+="--:--:--",html):html},getAppSecondaryText:function(session){return session.Client+" "+session.ApplicationVersion},getNowPlayingName:function(session){var imgUrl="",nowPlayingItem=session.NowPlayingItem;if(!nowPlayingItem)return{html:"Last seen "+humane_date(session.LastActivityDate),image:imgUrl};var topText=itemHelper.getDisplayName(nowPlayingItem),bottomText="";return nowPlayingItem.Artists&&nowPlayingItem.Artists.length?(bottomText=topText,topText=nowPlayingItem.Artists[0]):nowPlayingItem.SeriesName||nowPlayingItem.Album?(bottomText=topText,topText=nowPlayingItem.SeriesName||nowPlayingItem.Album):nowPlayingItem.ProductionYear&&(bottomText=nowPlayingItem.ProductionYear),nowPlayingItem.ImageTags&&nowPlayingItem.ImageTags.Logo?imgUrl=ApiClient.getScaledImageUrl(nowPlayingItem.Id,{tag:nowPlayingItem.ImageTags.Logo,maxHeight:24,maxWidth:130,type:"Logo"}):nowPlayingItem.ParentLogoImageTag&&(imgUrl=ApiClient.getScaledImageUrl(nowPlayingItem.ParentLogoItemId,{tag:nowPlayingItem.ParentLogoImageTag,maxHeight:24,maxWidth:130,type:"Logo"})),imgUrl&&(topText=' '),{html:bottomText?topText+" "+bottomText:topText,image:imgUrl}},getUsersHtml:function(session){var html=[];session.UserId&&html.push(session.UserName);for(var i=0,length=session.AdditionalUsers.length;i ";if("dashboard"==clientLowered||"emby web client"==clientLowered){return" "}return-1!=clientLowered.indexOf("android")?" ":-1!=clientLowered.indexOf("ios")?" ":"mb-classic"==clientLowered?" ":"roku"==clientLowered?" ":"dlna"==clientLowered?" ":"kodi"==clientLowered||"xbmc"==clientLowered?" ":"chromecast"==clientLowered?" ":null},getNowPlayingImageUrl:function(item){if(item&&item.BackdropImageTags&&item.BackdropImageTags.length)return ApiClient.getScaledImageUrl(item.Id,{type:"Backdrop",width:275,tag:item.BackdropImageTags[0]});if(item&&item.ParentBackdropImageTags&&item.ParentBackdropImageTags.length)return ApiClient.getScaledImageUrl(item.ParentBackdropItemId,{type:"Backdrop",width:275,tag:item.ParentBackdropImageTags[0]});if(item&&item.BackdropImageTag)return ApiClient.getScaledImageUrl(item.BackdropItemId,{type:"Backdrop",width:275,tag:item.BackdropImageTag});var imageTags=(item||{}).ImageTags||{};return item&&imageTags.Thumb?ApiClient.getScaledImageUrl(item.Id,{type:"Thumb",width:275,tag:imageTags.Thumb}):item&&item.ParentThumbImageTag?ApiClient.getScaledImageUrl(item.ParentThumbItemId,{type:"Thumb",width:275,tag:item.ParentThumbImageTag}):item&&item.ThumbImageTag?ApiClient.getScaledImageUrl(item.ThumbItemId,{type:"Thumb",width:275,tag:item.ThumbImageTag}):item&&imageTags.Primary?ApiClient.getScaledImageUrl(item.Id,{type:"Primary",width:275,tag:imageTags.Primary}):item&&item.PrimaryImageTag?ApiClient.getScaledImageUrl(item.PrimaryImageItemId,{type:"Primary",width:275,tag:item.PrimaryImageTag}):null},systemUpdateTaskKey:"SystemUpdateTask",renderUrls:function(page,systemInfo){var helpButton=''+globalize.translate("ButtonHelp")+" ";if(systemInfo.LocalAddress){var localAccessHtml=globalize.translate("LabelLocalAccessUrl",''+systemInfo.LocalAddress+" ");$(".localUrl",page).html(localAccessHtml+helpButton).show()}else $(".externalUrl",page).hide();if(systemInfo.WanAddress){var externalUrl=systemInfo.WanAddress,remoteAccessHtml=globalize.translate("LabelRemoteAccessUrl",''+externalUrl+" ");$(".externalUrl",page).html(remoteAccessHtml+helpButton).show()}else $(".externalUrl",page).hide()},renderSupporterIcon:function(page,pluginSecurityInfo){var imgUrl,text,supporterIconContainer=page.querySelector(".supporterIconContainer");pluginSecurityInfo.IsMBSupporter?(supporterIconContainer.classList.remove("hide"),imgUrl="css/images/supporter/supporterbadge.png",text=globalize.translate("MessageThankYouForSupporting"),supporterIconContainer.innerHTML=' '):supporterIconContainer.classList.add("hide")},renderPendingInstallations:function(page,systemInfo){if(!systemInfo.CompletedInstallations.length)return void page.querySelector("#collapsiblePendingInstallations").classList.add("hide");page.querySelector("#collapsiblePendingInstallations").classList.remove("hide");for(var html="",i=0,length=systemInfo.CompletedInstallations.length;i"+update.Name+" ("+update.Version+") "}$("#pendingInstallations",page).html(html)},renderPluginUpdateInfo:function(page,forceUpdate){!forceUpdate&&DashboardPage.lastPluginUpdateCheck&&(new Date).getTime()-DashboardPage.lastPluginUpdateCheck<18e5||(DashboardPage.lastPluginUpdateCheck=(new Date).getTime(),ApiClient.getAvailablePluginUpdates().then(function(updates){var elem=page.querySelector("#pPluginUpdates");if(!updates.length)return void $(elem).hide();$(elem).show();for(var html="",i=0,length=updates.length;i
"+globalize.translate("NewVersionOfSomethingAvailable").replace("{0}",update.name)+" ",html+=''+globalize.translate("ButtonUpdateNow")+" "}elem.innerHTML=html}))},installPluginUpdate:function(button){$(button).buttonEnabled(!1);var name=button.getAttribute("data-name"),guid=button.getAttribute("data-guid"),version=button.getAttribute("data-version"),classification=button.getAttribute("data-classification");loading.show(),ApiClient.installPlugin(name,guid,classification,version).then(function(){loading.hide()})},updateApplication:function(){var page=$($.mobile.activePage)[0];$("#btnUpdateApplication",page).buttonEnabled(!1),loading.show(),ApiClient.getScheduledTasks().then(function(tasks){var task=tasks.filter(function(t){return t.Key==DashboardPage.systemUpdateTaskKey})[0];ApiClient.startScheduledTask(task.Id).then(function(){pollForInfo(page,ApiClient),loading.hide()})})},stopTask:function(id){var page=$($.mobile.activePage)[0];ApiClient.stopScheduledTask(id).then(function(){pollForInfo(page,ApiClient)})},restart:function(){require(["confirm"],function(confirm){confirm({title:globalize.translate("HeaderRestart"),text:globalize.translate("MessageConfirmRestart"),confirmText:globalize.translate("ButtonRestart"),primary:"cancel"}).then(function(){$("#btnRestartServer").buttonEnabled(!1),$("#btnShutdown").buttonEnabled(!1),Dashboard.restartServer()})})},shutdown:function(){require(["confirm"],function(confirm){confirm({title:globalize.translate("HeaderShutdown"),text:globalize.translate("MessageConfirmShutdown"),confirmText:globalize.translate("ButtonShutdown"),primary:"cancel"}).then(function(){$("#btnRestartServer").buttonEnabled(!1),$("#btnShutdown").buttonEnabled(!1),ApiClient.shutdownServer()})})}},pageClassOn("pageshow","type-interior",function(){var page=this;getPluginSecurityInfo().then(function(pluginSecurityInfo){if(!page.querySelector(".customSupporterPromotion")&&($(".supporterPromotion",page).remove(),!pluginSecurityInfo.IsMBSupporter)){var html='",page.querySelector(".content-primary").insertAdjacentHTML("afterbegin",html)}})}),function(view,params){function onRestartRequired(e,apiClient){apiClient.serverId()===serverId&&renderHasPendingRestart(view,apiClient,!0)}function onServerShuttingDown(e,apiClient){apiClient.serverId()===serverId&&renderHasPendingRestart(view,apiClient,!0)}function onServerRestarting(e,apiClient){apiClient.serverId()===serverId&&renderHasPendingRestart(view,apiClient,!0)}function onPackageInstalling(e,apiClient){apiClient.serverId()===serverId&&(pollForInfo(view,apiClient,!0),reloadSystemInfo(view,apiClient))}function onPackageInstallationCompleted(e,apiClient){apiClient.serverId()===serverId&&(pollForInfo(view,apiClient,!0),reloadSystemInfo(view,apiClient))}function onSessionsUpdate(e,apiClient,info){apiClient.serverId()===serverId&&renderInfo(view,info)}function onScheduledTasksUpdate(e,apiClient,info){apiClient.serverId()===serverId&&renderRunningTasks(view,info)}var serverId=ApiClient.serverId();view.querySelector(".btnConnectionHelp").addEventListener("click",onConnectionHelpClick),view.querySelector(".btnEditServerName").addEventListener("click",onEditServerNameClick),view.querySelector(".activeDevices").addEventListener("click",onActiveDevicesClick),view.addEventListener("viewshow",function(){var page=this,apiClient=ApiClient;apiClient&&(DashboardPage.newsStartIndex=0,loading.show(),pollForInfo(page,apiClient),DashboardPage.startInterval(apiClient),events.on(serverNotifications,"RestartRequired",onRestartRequired),events.on(serverNotifications,"ServerShuttingDown",onServerShuttingDown),events.on(serverNotifications,"ServerRestarting",onServerRestarting),events.on(serverNotifications,"PackageInstalling",onPackageInstalling),events.on(serverNotifications,"PackageInstallationCompleted",onPackageInstallationCompleted),events.on(serverNotifications,"Sessions",onSessionsUpdate),events.on(serverNotifications,"ScheduledTasksInfo",onScheduledTasksUpdate),DashboardPage.lastAppUpdateCheck=null,DashboardPage.lastPluginUpdateCheck=null,getPluginSecurityInfo().then(function(pluginSecurityInfo){DashboardPage.renderSupporterIcon(page,pluginSecurityInfo)}),reloadSystemInfo(page,ApiClient),DashboardPage.reloadNews(page),page.activityLog||(page.activityLog=new ActivityLog({serverId:ApiClient.serverId(),element:page.querySelector(".activityItems")})),page.querySelector(".swaggerLink").setAttribute("href","http://swagger.emby.media?url="+ApiClient.getUrl("swagger")),refreshActiveRecordings(view,apiClient))}),view.addEventListener("viewbeforehide",function(){var page=this,activityLog=page.activityLog;activityLog&&activityLog.destroy(),page.activityLog=null;var apiClient=ApiClient
-;events.off(serverNotifications,"RestartRequired",onRestartRequired),events.off(serverNotifications,"ServerShuttingDown",onServerShuttingDown),events.off(serverNotifications,"ServerRestarting",onServerRestarting),events.off(serverNotifications,"PackageInstalling",onPackageInstalling),events.off(serverNotifications,"PackageInstallationCompleted",onPackageInstallationCompleted),events.off(serverNotifications,"Sessions",onSessionsUpdate),events.off(serverNotifications,"ScheduledTasksInfo",onScheduledTasksUpdate),apiClient&&DashboardPage.stopInterval(apiClient)})}});
\ No newline at end of file
+define(["datetime","jQuery","events","itemHelper","serverNotifications","dom","globalize","loading","connectionManager","playMethodHelper","cardBuilder","imageLoader","components/activitylog","humanedate","listViewStyle","emby-linkbutton","flexStyles","buttonenabled","emby-button","emby-itemscontainer"],function(datetime,$,events,itemHelper,serverNotifications,dom,globalize,loading,connectionManager,playMethodHelper,cardBuilder,imageLoader,ActivityLog){"use strict";function onConnectionHelpClick(e){return e.preventDefault(),!1}function onEditServerNameClick(e){var page=dom.parentWithClass(this,"page");return require(["prompt"],function(prompt){prompt({label:globalize.translate("LabelFriendlyServerName"),description:globalize.translate("LabelFriendlyServerNameHelp"),value:page.querySelector(".serverNameHeader").innerHTML,confirmText:globalize.translate("ButtonSave")}).then(function(value){loading.show(),ApiClient.getServerConfiguration().then(function(config){config.ServerName=value,ApiClient.updateServerConfiguration(config).then(function(){page.querySelector(".serverNameHeader").innerHTML=value,loading.hide()})})})}),e.preventDefault(),!1}function showPlaybackInfo(btn,session){require(["alert"],function(alert){var showTranscodeReasons,title,text=[],displayPlayMethod=playMethodHelper.getDisplayPlayMethod(session),isDirectStream="DirectStream"===displayPlayMethod,isTranscode="Transcode"===displayPlayMethod;isDirectStream?(title=globalize.translate("sharedcomponents#DirectStreaming"),text.push(globalize.translate("sharedcomponents#DirectStreamHelp1")),text.push(" "),text.push(globalize.translate("sharedcomponents#DirectStreamHelp2"))):isTranscode&&(title=globalize.translate("sharedcomponents#Transcoding"),text.push(globalize.translate("sharedcomponents#MediaIsBeingConverted")),session.TranscodingInfo&&session.TranscodingInfo.TranscodeReasons&&session.TranscodingInfo.TranscodeReasons.length&&(text.push(" "),text.push(globalize.translate("sharedcomponents#LabelReasonForTranscoding")),showTranscodeReasons=!0)),showTranscodeReasons&&session.TranscodingInfo.TranscodeReasons.forEach(function(t){text.push(globalize.translate("sharedcomponents#"+t))}),alert({text:text.join(" "),title:title})})}function showSendMessageForm(btn,session){require(["prompt"],function(prompt){prompt({title:globalize.translate("HeaderSendMessage"),label:globalize.translate("LabelMessageText"),confirmText:globalize.translate("ButtonSend")}).then(function(text){if(text){connectionManager.getApiClient(session.ServerId).sendMessageCommand(session.Id,{Text:text,TimeoutMs:5e3})}})})}function showOptionsMenu(btn,session){require(["actionsheet"],function(actionsheet){var menuItems=[];return session.ServerId&&session.DeviceId!==connectionManager.deviceId()&&menuItems.push({name:globalize.translate("SendMessage"),id:"sendmessage"}),session.TranscodingInfo&&session.TranscodingInfo.TranscodeReasons&&session.TranscodingInfo.TranscodeReasons.length&&menuItems.push({name:globalize.translate("ViewPlaybackInfo"),id:"transcodinginfo"}),actionsheet.show({items:menuItems,positionTo:btn}).then(function(id){switch(id){case"sendmessage":showSendMessageForm(btn,session);break;case"transcodinginfo":showPlaybackInfo(btn,session)}})})}function onActiveDevicesClick(e){var btn=dom.parentWithClass(e.target,"sessionCardButton");if(btn){var card=dom.parentWithClass(btn,"card");if(card){var sessionId=card.id,session=(DashboardPage.sessionsList||[]).filter(function(s){return"session"+s.Id===sessionId})[0];session&&(btn.classList.contains("btnCardOptions")?showOptionsMenu(btn,session):btn.classList.contains("btnSessionInfo")?showPlaybackInfo(btn,session):btn.classList.contains("btnSessionSendMessage")?showSendMessageForm(btn,session):btn.classList.contains("btnSessionStop")?connectionManager.getApiClient(session.ServerId).sendPlayStateCommand(session.Id,"Stop"):btn.classList.contains("btnSessionPlayPause")&&session.PlayState&&connectionManager.getApiClient(session.ServerId).sendPlayStateCommand(session.Id,"PlayPause"))}}}function filterSessions(sessions){for(var list=[],minActiveDate=(new Date).getTime()-9e5,i=0,length=sessions.length;i=minActiveDate&&list.push(session)}}return list}function getPluginSecurityInfo(){var apiClient=window.ApiClient;return apiClient?connectionManager.getRegistrationInfo("themes",apiClient,{viewOnly:!0}).then(function(result){return{IsMBSupporter:!0}},function(){return{IsMBSupporter:!1}}):Promise.reject()}function refreshActiveRecordings(view,apiClient){apiClient.getLiveTvRecordings({UserId:Dashboard.getCurrentUserId(),IsInProgress:!0,Fields:"CanDelete,PrimaryImageAspectRatio",EnableTotalRecordCount:!1,EnableImageTypes:"Primary,Thumb,Backdrop"}).then(function(result){var itemsContainer=view.querySelector(".activeRecordingItems");if(!result.Items.length)return view.querySelector(".activeRecordingsSection").classList.add("hide"),void(itemsContainer.innerHTML="");view.querySelector(".activeRecordingsSection").classList.remove("hide");itemsContainer.innerHTML=cardBuilder.getCardsHtml({items:result.Items,shape:"auto",defaultShape:"backdrop",showTitle:!0,showParentTitle:!0,coverImage:!0,cardLayout:!1,centerText:!0,preferThumb:"auto",overlayText:!1,overlayMoreButton:!0,action:"none",centerPlayButton:!0}),imageLoader.lazyChildren(itemsContainer)})}function renderHasPendingRestart(view,apiClient,hasPendingRestart){if(hasPendingRestart)view.querySelector("#pUpToDate").classList.add("hide"),$("#pUpdateNow",view).hide();else{if(DashboardPage.lastAppUpdateCheck&&(new Date).getTime()-DashboardPage.lastAppUpdateCheck<18e5)return;DashboardPage.lastAppUpdateCheck=(new Date).getTime(),apiClient.getAvailableApplicationUpdate().then(function(packageInfo){var version=packageInfo[0];version?(view.querySelector("#pUpToDate").classList.add("hide"),$("#pUpdateNow",view).show(),$("#newVersionNumber",view).html(globalize.translate("VersionXIsAvailableForDownload").replace("{0}",version.versionStr))):(view.querySelector("#pUpToDate").classList.remove("hide"),$("#pUpdateNow",view).hide())})}}function reloadSystemInfo(view,apiClient){apiClient.getSystemInfo().then(function(systemInfo){view.querySelector(".serverNameHeader").innerHTML=systemInfo.ServerName;var localizedVersion=globalize.translate("LabelVersionNumber",systemInfo.Version);systemInfo.SystemUpdateLevel&&"Release"!=systemInfo.SystemUpdateLevel&&(localizedVersion+=" "+globalize.translate("Option"+systemInfo.SystemUpdateLevel).toLowerCase()),systemInfo.CanSelfRestart?$(".btnRestartContainer",view).removeClass("hide"):$(".btnRestartContainer",view).addClass("hide"),$("#appVersionNumber",view).html(localizedVersion),systemInfo.SupportsHttps?$("#ports",view).html(globalize.translate("LabelRunningOnPorts",systemInfo.HttpServerPortNumber,systemInfo.HttpsPortNumber)):$("#ports",view).html(globalize.translate("LabelRunningOnPort",systemInfo.HttpServerPortNumber)),DashboardPage.renderUrls(view,systemInfo),DashboardPage.renderPendingInstallations(view,systemInfo),systemInfo.CanSelfUpdate?($("#btnUpdateApplicationContainer",view).show(),$("#btnManualUpdateContainer",view).hide()):($("#btnUpdateApplicationContainer",view).hide(),$("#btnManualUpdateContainer",view).show()),"synology"==systemInfo.PackageName?$("#btnManualUpdateContainer").html(globalize.translate("SynologyUpdateInstructions")):$("#btnManualUpdateContainer").html(''+globalize.translate("PleaseUpdateManually")+" "),DashboardPage.renderPaths(view,systemInfo),renderHasPendingRestart(view,apiClient,systemInfo.HasPendingRestart)})}function renderInfo(view,sessions,forceUpdate){sessions=filterSessions(sessions),renderActiveConnections(view,sessions),DashboardPage.renderPluginUpdateInfo(view,forceUpdate),loading.hide()}function pollForInfo(view,apiClient,forceUpdate){apiClient.getSessions({ActiveWithinSeconds:960}).then(function(sessions){renderInfo(view,sessions,forceUpdate)}),apiClient.getScheduledTasks().then(function(tasks){renderRunningTasks(view,tasks)})}function renderActiveConnections(view,sessions){var html="";DashboardPage.sessionsList=sessions;var parentElement=view.querySelector(".activeDevices");$(".card",parentElement).addClass("deadSession");for(var i=0,length=sessions.length;i',html+='',html+='
',html+='
',html+='
';var imgUrl=DashboardPage.getNowPlayingImageUrl(nowPlayingItem);imgUrl?(html+='
",html+='
',html+='
';var clientImage=DashboardPage.getClientImage(session);clientImage&&(html+=clientImage),html+='
',html+='
'+session.DeviceName+"
",html+='
'+DashboardPage.getAppSecondaryText(session)+"
",html+="
",html+="
",html+='
'+DashboardPage.getSessionNowPlayingTime(session)+"
",session.TranscodingInfo&&session.TranscodingInfo.Framerate?html+='
'+session.TranscodingInfo.Framerate+" fps
":html+='
';var nowPlayingName=DashboardPage.getNowPlayingName(session);if(html+='
',html+=nowPlayingName.html,html+="
",nowPlayingItem&&nowPlayingItem.RunTimeTicks){html+='
'}else html+='
';session.TranscodingInfo&&session.TranscodingInfo.CompletionPercentage?html+='
':html+='
',html+="
",html+="
",html+="
",html+='",html+="
",html+=" "}}parentElement.insertAdjacentHTML("beforeend",html),$(".deadSession",parentElement).remove()}function renderRunningTasks(view,tasks){var html="";tasks=tasks.filter(function(t){return"Idle"!=t.State&&!t.IsHidden}),tasks.length?view.querySelector(".runningTasksContainer").classList.remove("hide"):view.querySelector(".runningTasksContainer").classList.add("hide"),tasks.filter(function(t){return t.Key==DashboardPage.systemUpdateTaskKey}).length?$("#btnUpdateApplication",view).buttonEnabled(!1):$("#btnUpdateApplication",view).buttonEnabled(!0);for(var i=0,length=tasks.length;i
",html+=task.Name+" ","Running"==task.State){var progress=(task.CurrentProgressPercentage||0).toFixed(1);html+='',html+=progress+"%",html+=" ",html+=""+progress+"% ",html+='cancel '}else"Cancelling"==task.State&&(html+=''+globalize.translate("LabelStopping")+" ");html+=""}view.querySelector("#divRunningTasks").innerHTML=html}return window.DashboardPage={newsStartIndex:0,renderPaths:function(page,systemInfo){$("#cachePath",page).html(systemInfo.CachePath),$("#logPath",page).html(systemInfo.LogPath),$("#transcodingTemporaryPath",page).html(systemInfo.TranscodingTempPath),$("#metadataPath",page).html(systemInfo.InternalMetadataPath)},reloadNews:function(page){var query={StartIndex:DashboardPage.newsStartIndex,Limit:4};ApiClient.getProductNews(query).then(function(result){var html=result.Items.map(function(item){var itemHtml="";itemHtml+='',itemHtml+='',itemHtml+='
dvr ',itemHtml+='
',itemHtml+='
',itemHtml+=item.Title,itemHtml+="
",itemHtml+='
';var date=datetime.parseISO8601Date(item.Date,!0);return itemHtml+=datetime.toLocaleDateString(date),itemHtml+="
",itemHtml+="
",itemHtml+="
",itemHtml+=" "});page.querySelector(".latestNewsItems").innerHTML=html.join("")})},startInterval:function(apiClient){apiClient.sendMessage("SessionsStart","0,1500"),apiClient.sendMessage("ScheduledTasksInfoStart","0,1000")},stopInterval:function(apiClient){apiClient.sendMessage("SessionsStop"),apiClient.sendMessage("ScheduledTasksInfoStop")},getSessionNowPlayingStreamInfo:function(session){var html="",showTranscodingInfo=!1,displayPlayMethod=playMethodHelper.getDisplayPlayMethod(session);if("DirectStream"===displayPlayMethod?(html+=globalize.translate("sharedcomponents#DirectStreaming"),!0):"Transcode"==displayPlayMethod?(html+=globalize.translate("sharedcomponents#Transcoding"),session.TranscodingInfo&&session.TranscodingInfo.Framerate&&(html+=" ("+session.TranscodingInfo.Framerate+" fps)"),showTranscodingInfo=!0,!0):"DirectPlay"==displayPlayMethod&&(html+=globalize.translate("sharedcomponents#DirectPlaying")),showTranscodingInfo){var line=[];session.TranscodingInfo&&(session.TranscodingInfo.Bitrate&&(session.TranscodingInfo.Bitrate>1e6?line.push((session.TranscodingInfo.Bitrate/1e6).toFixed(1)+" Mbps"):line.push(Math.floor(session.TranscodingInfo.Bitrate/1e3)+" kbps")),session.TranscodingInfo.Container&&line.push(session.TranscodingInfo.Container),session.TranscodingInfo.VideoCodec&&line.push(session.TranscodingInfo.VideoCodec),session.TranscodingInfo.AudioCodec&&session.TranscodingInfo.AudioCodec!=session.TranscodingInfo.Container&&line.push(session.TranscodingInfo.AudioCodec)),line.length&&(html+=" - "+line.join(" "))}return html||" "},getSessionNowPlayingTime:function(session){var nowPlayingItem=session.NowPlayingItem,html="";return nowPlayingItem?(session.PlayState.PositionTicks?html+=datetime.getDisplayRunningTime(session.PlayState.PositionTicks):html+="--:--:--",html+=" / ",nowPlayingItem&&nowPlayingItem.RunTimeTicks?html+=datetime.getDisplayRunningTime(nowPlayingItem.RunTimeTicks):html+="--:--:--",html):html},getAppSecondaryText:function(session){return session.Client+" "+session.ApplicationVersion},getNowPlayingName:function(session){var imgUrl="",nowPlayingItem=session.NowPlayingItem;if(!nowPlayingItem)return{html:"Last seen "+humane_date(session.LastActivityDate),image:imgUrl};var topText=itemHelper.getDisplayName(nowPlayingItem),bottomText="";return nowPlayingItem.Artists&&nowPlayingItem.Artists.length?(bottomText=topText,topText=nowPlayingItem.Artists[0]):nowPlayingItem.SeriesName||nowPlayingItem.Album?(bottomText=topText,topText=nowPlayingItem.SeriesName||nowPlayingItem.Album):nowPlayingItem.ProductionYear&&(bottomText=nowPlayingItem.ProductionYear),nowPlayingItem.ImageTags&&nowPlayingItem.ImageTags.Logo?imgUrl=ApiClient.getScaledImageUrl(nowPlayingItem.Id,{tag:nowPlayingItem.ImageTags.Logo,maxHeight:24,maxWidth:130,type:"Logo"}):nowPlayingItem.ParentLogoImageTag&&(imgUrl=ApiClient.getScaledImageUrl(nowPlayingItem.ParentLogoItemId,{tag:nowPlayingItem.ParentLogoImageTag,maxHeight:24,maxWidth:130,type:"Logo"})),imgUrl&&(topText=' '),{html:bottomText?topText+" "+bottomText:topText,image:imgUrl}},getUsersHtml:function(session){var html=[];session.UserId&&html.push(session.UserName);for(var i=0,length=session.AdditionalUsers.length;i ";if("dashboard"==clientLowered||"emby web client"==clientLowered){return" "}return-1!=clientLowered.indexOf("android")?" ":-1!=clientLowered.indexOf("ios")?" ":"mb-classic"==clientLowered?" ":"roku"==clientLowered?" ":"dlna"==clientLowered?" ":"kodi"==clientLowered||"xbmc"==clientLowered?" ":"chromecast"==clientLowered?" ":null},getNowPlayingImageUrl:function(item){if(item&&item.BackdropImageTags&&item.BackdropImageTags.length)return ApiClient.getScaledImageUrl(item.Id,{type:"Backdrop",width:275,tag:item.BackdropImageTags[0]});if(item&&item.ParentBackdropImageTags&&item.ParentBackdropImageTags.length)return ApiClient.getScaledImageUrl(item.ParentBackdropItemId,{type:"Backdrop",width:275,tag:item.ParentBackdropImageTags[0]});if(item&&item.BackdropImageTag)return ApiClient.getScaledImageUrl(item.BackdropItemId,{type:"Backdrop",width:275,tag:item.BackdropImageTag});var imageTags=(item||{}).ImageTags||{};return item&&imageTags.Thumb?ApiClient.getScaledImageUrl(item.Id,{type:"Thumb",width:275,tag:imageTags.Thumb}):item&&item.ParentThumbImageTag?ApiClient.getScaledImageUrl(item.ParentThumbItemId,{type:"Thumb",width:275,tag:item.ParentThumbImageTag}):item&&item.ThumbImageTag?ApiClient.getScaledImageUrl(item.ThumbItemId,{type:"Thumb",width:275,tag:item.ThumbImageTag}):item&&imageTags.Primary?ApiClient.getScaledImageUrl(item.Id,{type:"Primary",width:275,tag:imageTags.Primary}):item&&item.PrimaryImageTag?ApiClient.getScaledImageUrl(item.PrimaryImageItemId,{type:"Primary",width:275,tag:item.PrimaryImageTag}):null},systemUpdateTaskKey:"SystemUpdateTask",renderUrls:function(page,systemInfo){var helpButton=''+globalize.translate("ButtonHelp")+" ";if(systemInfo.LocalAddress){var localAccessHtml=globalize.translate("LabelLocalAccessUrl",''+systemInfo.LocalAddress+" ");$(".localUrl",page).html(localAccessHtml+helpButton).show()}else $(".externalUrl",page).hide();if(systemInfo.WanAddress){var externalUrl=systemInfo.WanAddress,remoteAccessHtml=globalize.translate("LabelRemoteAccessUrl",''+externalUrl+" ");$(".externalUrl",page).html(remoteAccessHtml+helpButton).show()}else $(".externalUrl",page).hide()},renderSupporterIcon:function(page,pluginSecurityInfo){var imgUrl,text,supporterIconContainer=page.querySelector(".supporterIconContainer");pluginSecurityInfo.IsMBSupporter?(supporterIconContainer.classList.remove("hide"),imgUrl="css/images/supporter/supporterbadge.png",text=globalize.translate("MessageThankYouForSupporting"),supporterIconContainer.innerHTML=' '):supporterIconContainer.classList.add("hide")},renderPendingInstallations:function(page,systemInfo){if(!systemInfo.CompletedInstallations.length)return void page.querySelector("#collapsiblePendingInstallations").classList.add("hide");page.querySelector("#collapsiblePendingInstallations").classList.remove("hide");for(var html="",i=0,length=systemInfo.CompletedInstallations.length;i"+update.Name+" ("+update.Version+") "}$("#pendingInstallations",page).html(html)},renderPluginUpdateInfo:function(page,forceUpdate){!forceUpdate&&DashboardPage.lastPluginUpdateCheck&&(new Date).getTime()-DashboardPage.lastPluginUpdateCheck<18e5||(DashboardPage.lastPluginUpdateCheck=(new Date).getTime(),ApiClient.getAvailablePluginUpdates().then(function(updates){var elem=page.querySelector("#pPluginUpdates");if(!updates.length)return void $(elem).hide();$(elem).show();for(var html="",i=0,length=updates.length;i"+globalize.translate("NewVersionOfSomethingAvailable").replace("{0}",update.name)+"
",html+=''+globalize.translate("ButtonUpdateNow")+" "}elem.innerHTML=html}))},installPluginUpdate:function(button){$(button).buttonEnabled(!1);var name=button.getAttribute("data-name"),guid=button.getAttribute("data-guid"),version=button.getAttribute("data-version"),classification=button.getAttribute("data-classification");loading.show(),ApiClient.installPlugin(name,guid,classification,version).then(function(){loading.hide()})},updateApplication:function(){var page=$($.mobile.activePage)[0];$("#btnUpdateApplication",page).buttonEnabled(!1),loading.show(),ApiClient.getScheduledTasks().then(function(tasks){var task=tasks.filter(function(t){return t.Key==DashboardPage.systemUpdateTaskKey})[0];ApiClient.startScheduledTask(task.Id).then(function(){pollForInfo(page,ApiClient),loading.hide()})})},stopTask:function(id){var page=$($.mobile.activePage)[0];ApiClient.stopScheduledTask(id).then(function(){pollForInfo(page,ApiClient)})},restart:function(){require(["confirm"],function(confirm){confirm({title:globalize.translate("HeaderRestart"),text:globalize.translate("MessageConfirmRestart"),confirmText:globalize.translate("ButtonRestart"),primary:"cancel"}).then(function(){$("#btnRestartServer").buttonEnabled(!1),$("#btnShutdown").buttonEnabled(!1),Dashboard.restartServer()})})},shutdown:function(){require(["confirm"],function(confirm){confirm({title:globalize.translate("HeaderShutdown"),text:globalize.translate("MessageConfirmShutdown"),confirmText:globalize.translate("ButtonShutdown"),primary:"cancel"}).then(function(){$("#btnRestartServer").buttonEnabled(!1),$("#btnShutdown").buttonEnabled(!1),ApiClient.shutdownServer()})})}},pageClassOn("pageshow","type-interior",function(){var page=this;getPluginSecurityInfo().then(function(pluginSecurityInfo){if(!page.querySelector(".customSupporterPromotion")&&($(".supporterPromotion",page).remove(),!pluginSecurityInfo.IsMBSupporter)){var html='",page.querySelector(".content-primary").insertAdjacentHTML("afterbegin",html)}})}),function(view,params){function onRestartRequired(e,apiClient){apiClient.serverId()===serverId&&renderHasPendingRestart(view,apiClient,!0)}function onServerShuttingDown(e,apiClient){apiClient.serverId()===serverId&&renderHasPendingRestart(view,apiClient,!0)}function onServerRestarting(e,apiClient){apiClient.serverId()===serverId&&renderHasPendingRestart(view,apiClient,!0)}function onPackageInstalling(e,apiClient){apiClient.serverId()===serverId&&(pollForInfo(view,apiClient,!0),reloadSystemInfo(view,apiClient))}function onPackageInstallationCompleted(e,apiClient){apiClient.serverId()===serverId&&(pollForInfo(view,apiClient,!0),reloadSystemInfo(view,apiClient))}function onSessionsUpdate(e,apiClient,info){apiClient.serverId()===serverId&&renderInfo(view,info)}function onScheduledTasksUpdate(e,apiClient,info){apiClient.serverId()===serverId&&renderRunningTasks(view,info)}var serverId=ApiClient.serverId();view.querySelector(".btnConnectionHelp").addEventListener("click",onConnectionHelpClick),view.querySelector(".btnEditServerName").addEventListener("click",onEditServerNameClick),view.querySelector(".activeDevices").addEventListener("click",onActiveDevicesClick),view.addEventListener("viewshow",function(){var page=this,apiClient=ApiClient;apiClient&&(DashboardPage.newsStartIndex=0,loading.show(),pollForInfo(page,apiClient),DashboardPage.startInterval(apiClient),events.on(serverNotifications,"RestartRequired",onRestartRequired),events.on(serverNotifications,"ServerShuttingDown",onServerShuttingDown),events.on(serverNotifications,"ServerRestarting",onServerRestarting),events.on(serverNotifications,"PackageInstalling",onPackageInstalling),events.on(serverNotifications,"PackageInstallationCompleted",onPackageInstallationCompleted),events.on(serverNotifications,"Sessions",onSessionsUpdate),events.on(serverNotifications,"ScheduledTasksInfo",onScheduledTasksUpdate),DashboardPage.lastAppUpdateCheck=null,DashboardPage.lastPluginUpdateCheck=null,getPluginSecurityInfo().then(function(pluginSecurityInfo){DashboardPage.renderSupporterIcon(page,pluginSecurityInfo)}),reloadSystemInfo(page,ApiClient),DashboardPage.reloadNews(page),page.activityLog||(page.activityLog=new ActivityLog({serverId:ApiClient.serverId(),element:page.querySelector(".activityItems")})),page.querySelector(".swaggerLink").setAttribute("href","http://swagger.emby.media?url="+ApiClient.getUrl("swagger")),refreshActiveRecordings(view,apiClient))}),
+view.addEventListener("viewbeforehide",function(){var page=this,activityLog=page.activityLog;activityLog&&activityLog.destroy(),page.activityLog=null;var apiClient=ApiClient;events.off(serverNotifications,"RestartRequired",onRestartRequired),events.off(serverNotifications,"ServerShuttingDown",onServerShuttingDown),events.off(serverNotifications,"ServerRestarting",onServerRestarting),events.off(serverNotifications,"PackageInstalling",onPackageInstalling),events.off(serverNotifications,"PackageInstallationCompleted",onPackageInstallationCompleted),events.off(serverNotifications,"Sessions",onSessionsUpdate),events.off(serverNotifications,"ScheduledTasksInfo",onScheduledTasksUpdate),apiClient&&DashboardPage.stopInterval(apiClient)})}});
\ No newline at end of file
diff --git a/MediaBrowser.WebDashboard/dashboard-ui/scripts/device.js b/MediaBrowser.WebDashboard/dashboard-ui/scripts/device.js
deleted file mode 100644
index 76529dfa65..0000000000
--- a/MediaBrowser.WebDashboard/dashboard-ui/scripts/device.js
+++ /dev/null
@@ -1 +0,0 @@
-define(["jQuery","loading","libraryMenu"],function($,loading,libraryMenu){"use strict";function load(page,device,capabilities){capabilities.SupportsContentUploading?$("#fldCameraUploadPath",page).removeClass("hide"):$("#fldCameraUploadPath",page).addClass("hide"),$("#txtCustomName",page).val(device.CustomName||""),$("#txtUploadPath",page).val(device.CameraUploadPath||""),$(".reportedName",page).html(device.ReportedName||"")}function loadData(page){loading.show();var id=getParameterByName("id"),promise1=ApiClient.getJSON(ApiClient.getUrl("Devices/Info",{Id:id})),promise2=ApiClient.getJSON(ApiClient.getUrl("Devices/Capabilities",{Id:id}));Promise.all([promise1,promise2]).then(function(responses){load(page,responses[0],responses[1]),loading.hide()})}function save(page){var id=getParameterByName("id");ApiClient.ajax({url:ApiClient.getUrl("Devices/Options",{Id:id}),type:"POST",data:JSON.stringify({CustomName:$("#txtCustomName",page).val(),CameraUploadPath:$("#txtUploadPath",page).val()}),contentType:"application/json"}).then(Dashboard.processServerConfigurationUpdateResult)}function onSubmit(){return save($(this).parents(".page")),!1}$(document).on("pageinit","#devicePage",function(){var page=this;$("#btnSelectUploadPath",page).on("click.selectDirectory",function(){require(["directorybrowser"],function(directoryBrowser){var picker=new directoryBrowser;picker.show({callback:function(path){path&&$("#txtUploadPath",page).val(path),picker.close()},validateWriteable:!0,header:Globalize.translate("HeaderSelectUploadPath")})})}),$(".deviceForm").off("submit",onSubmit).on("submit",onSubmit)}).on("pageshow","#devicePage",function(){loadData(this)})});
\ No newline at end of file
diff --git a/MediaBrowser.WebDashboard/dashboard-ui/scripts/devices.js b/MediaBrowser.WebDashboard/dashboard-ui/scripts/devices.js
index 6c19dea426..0c5e96d3a6 100644
--- a/MediaBrowser.WebDashboard/dashboard-ui/scripts/devices.js
+++ b/MediaBrowser.WebDashboard/dashboard-ui/scripts/devices.js
@@ -1 +1 @@
-define(["jQuery","loading","libraryMenu","globalize","listViewStyle","emby-linkbutton"],function($,loading,libraryMenu,globalize){"use strict";function deleteDevice(page,id){var msg=globalize.translate("DeleteDeviceConfirmation");require(["confirm"],function(confirm){confirm({text:msg,title:globalize.translate("HeaderDeleteDevice"),confirmText:globalize.translate("ButtonDelete"),primary:"cancel"}).then(function(){loading.show(),ApiClient.ajax({type:"DELETE",url:ApiClient.getUrl("Devices",{Id:id})}).then(function(){loadData(page)})})})}function load(page,devices){var html="";devices.length&&(html+=''),html+=devices.map(function(d){var deviceHtml="";return deviceHtml+='
',deviceHtml+='
tablet_android ',d.AppName&&d.LastUserName?deviceHtml+='
':deviceHtml+='
',deviceHtml+='
',deviceHtml+='',deviceHtml+=d.Name,deviceHtml+="
",d.AppName&&(deviceHtml+='',deviceHtml+=d.AppName,deviceHtml+="
"),d.LastUserName&&(deviceHtml+='',deviceHtml+=globalize.translate("DeviceLastUsedByUserName",d.LastUserName),deviceHtml+="
"),deviceHtml+=" ",deviceHtml+="
",deviceHtml+='
delete ',deviceHtml+="
"}).join(""),devices.length&&(html+="
");var elem=$(".devicesList",page).html(html).trigger("create");$(".btnDeleteDevice",elem).on("click",function(){deleteDevice(page,this.getAttribute("data-id"))})}function loadData(page){loading.show(),ApiClient.getJSON(ApiClient.getUrl("Devices",{SupportsPersistentIdentifier:!0})).then(function(result){load(page,result.Items),loading.hide()})}$(document).on("pageshow","#devicesPage",function(){loadData(this)})});
\ No newline at end of file
+define(["loading","dom","libraryMenu","globalize","humanedate","emby-linkbutton","emby-itemscontainer","cardStyle"],function(loading,dom,libraryMenu,globalize){"use strict";function deleteDevice(page,id){var msg=globalize.translate("DeleteDeviceConfirmation");require(["confirm"],function(confirm){confirm({text:msg,title:globalize.translate("HeaderDeleteDevice"),confirmText:globalize.translate("ButtonDelete"),primary:"cancel"}).then(function(){loading.show(),ApiClient.ajax({type:"DELETE",url:ApiClient.getUrl("Devices",{Id:id})}).then(function(){loadData(page)})})})}function load(page,devices){var html="";html+=devices.map(function(device){var deviceHtml="";return deviceHtml+="
",deviceHtml+='
',deviceHtml+='
',deviceHtml+='
',deviceHtml+='
',device.ImageUrl?(deviceHtml+='
",deviceHtml+="
"):deviceHtml+='
tablet_android ',deviceHtml+="
",deviceHtml+="
",deviceHtml+='",deviceHtml+="
",deviceHtml+="
"}).join(""),page.querySelector(".devicesList").innerHTML=html}function loadData(page){loading.show(),ApiClient.getJSON(ApiClient.getUrl("Devices")).then(function(result){load(page,result.Items),loading.hide()})}return function(view,params){view.querySelector(".devicesList").addEventListener("click",function(e){var btnDelete=dom.parentWithClass(e.target,"btnDeleteDevice");btnDelete&&deleteDevice(view,btnDelete.getAttribute("data-id"))}),view.addEventListener("viewshow",function(){loadData(this)})}});
\ No newline at end of file
diff --git a/MediaBrowser.WebDashboard/dashboard-ui/scripts/itembynamedetailpage.js b/MediaBrowser.WebDashboard/dashboard-ui/scripts/itembynamedetailpage.js
index c5912d8865..621070a4fe 100644
--- a/MediaBrowser.WebDashboard/dashboard-ui/scripts/itembynamedetailpage.js
+++ b/MediaBrowser.WebDashboard/dashboard-ui/scripts/itembynamedetailpage.js
@@ -1 +1 @@
-define(["connectionManager","listView","cardBuilder","imageLoader","libraryBrowser","emby-itemscontainer","emby-linkbutton"],function(connectionManager,listView,cardBuilder,imageLoader,libraryBrowser){"use strict";function renderItems(page,item){var sections=[];item.ArtistCount&§ions.push({name:Globalize.translate("TabArtists"),type:"MusicArtist"}),item.ProgramCount&&"Person"==item.Type&§ions.push({name:Globalize.translate("HeaderUpcomingOnTV"),type:"Program"}),item.MovieCount&§ions.push({name:Globalize.translate("TabMovies"),type:"Movie"}),item.SeriesCount&§ions.push({name:Globalize.translate("TabShows"),type:"Series"}),item.EpisodeCount&§ions.push({name:Globalize.translate("TabEpisodes"),type:"Episode"}),item.TrailerCount&§ions.push({name:Globalize.translate("TabTrailers"),type:"Trailer"}),item.GameCount&§ions.push({name:Globalize.translate("TabGames"),type:"Game"}),item.AlbumCount&§ions.push({name:Globalize.translate("TabAlbums"),type:"MusicAlbum"}),item.SongCount&§ions.push({name:Globalize.translate("TabSongs"),type:"Audio"}),item.MusicVideoCount&§ions.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+="
",html+="
"}).join("");for(var sectionElems=elem.querySelectorAll(".verticalSection"),i=0,length=sectionElems.length;i
query.Limit){var link=element.querySelector("a");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)})}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:"GameGenre"==item.Type?"list.html?type="+type+"&gameGenreId="+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}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:"GameGenre"==item.Type?query.GenreIds=item.Id:"Studio"==item.Type?query.StudioIds=item.Id:"MusicArtist"==item.Type&&(query.ArtistIds=item.Id)}function getQuery(options,item){var query={SortOrder:"Ascending",IncludeItemTypes:"",Recursive:!0,Fields:"AudioInfo,SeriesInfo,ParentId,PrimaryImageAspectRatio,BasicSyncInfo",Limit:libraryBrowser.getDefaultPageSize(),StartIndex:0,CollapseBoxSetItems:!1};return query=Object.assign(query,options||{}),addCurrentItemToQuery(query,item),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);var apiClient=connectionManager.getApiClient(item.ServerId);return"MusicArtist"===query.IncludeItemTypes?(query.IncludeItemTypes=null,apiClient.getAlbumArtists(apiClient.getCurrentUserId(),query)):apiClient.getItems(apiClient.getCurrentUserId(),query)}}window.ItemsByName={renderItems:renderItems}});
\ No newline at end of file
+define(["connectionManager","listView","cardBuilder","imageLoader","libraryBrowser","emby-itemscontainer","emby-linkbutton"],function(connectionManager,listView,cardBuilder,imageLoader,libraryBrowser){"use strict";function renderItems(page,item){var sections=[];item.ArtistCount&§ions.push({name:Globalize.translate("TabArtists"),type:"MusicArtist"}),item.ProgramCount&&"Person"==item.Type&§ions.push({name:Globalize.translate("HeaderUpcomingOnTV"),type:"Program"}),item.MovieCount&§ions.push({name:Globalize.translate("TabMovies"),type:"Movie"}),item.SeriesCount&§ions.push({name:Globalize.translate("TabShows"),type:"Series"}),item.EpisodeCount&§ions.push({name:Globalize.translate("TabEpisodes"),type:"Episode"}),item.TrailerCount&§ions.push({name:Globalize.translate("TabTrailers"),type:"Trailer"}),item.GameCount&§ions.push({name:Globalize.translate("TabGames"),type:"Game"}),item.AlbumCount&§ions.push({name:Globalize.translate("TabAlbums"),type:"MusicAlbum"}),item.MusicVideoCount&§ions.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+="
",html+="
"}).join("");for(var sectionElems=elem.querySelectorAll(".verticalSection"),i=0,length=sectionElems.length;iquery.Limit){var link=element.querySelector("a");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)})}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:"GameGenre"==item.Type?"list.html?type="+type+"&gameGenreId="+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}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:"GameGenre"==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)}function getQuery(options,item){var query={SortOrder:"Ascending",IncludeItemTypes:"",Recursive:!0,Fields:"AudioInfo,SeriesInfo,ParentId,PrimaryImageAspectRatio,BasicSyncInfo",Limit:libraryBrowser.getDefaultPageSize(),StartIndex:0,CollapseBoxSetItems:!1};return query=Object.assign(query,options||{}),addCurrentItemToQuery(query,item),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);var apiClient=connectionManager.getApiClient(item.ServerId);return"MusicArtist"===query.IncludeItemTypes?(query.IncludeItemTypes=null,apiClient.getAlbumArtists(apiClient.getCurrentUserId(),query)):apiClient.getItems(apiClient.getCurrentUserId(),query)}}window.ItemsByName={renderItems:renderItems}});
\ No newline at end of file
diff --git a/MediaBrowser.WebDashboard/dashboard-ui/scripts/itemdetailpage.js b/MediaBrowser.WebDashboard/dashboard-ui/scripts/itemdetailpage.js
index 8c51cbc67c..c9de0708fb 100644
--- a/MediaBrowser.WebDashboard/dashboard-ui/scripts/itemdetailpage.js
+++ b/MediaBrowser.WebDashboard/dashboard-ui/scripts/itemdetailpage.js
@@ -1,2 +1,2 @@
-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-linkbutton","emby-playstatebutton","emby-ratingbutton","emby-downloadbutton","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.gamegenre)return apiClient.getGameGenre(name,apiClient.getCurrentUserId());if(name=params.musicartist)return apiClient.getArtist(name,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',html+=listView.getListViewHtml({items:items,enableUserDataButtons:!1,image:!0,imageSource:"channel",showProgramDateTime:!0,showChannel:!1,mediaInfo:!1,action:"none",moreButton:!1,recordButton:!1}),html+=" "}function renderSeriesTimerSchedule(page,apiClient,seriesTimerId){apiClient.getLiveTvTimers({UserId:apiClient.getCurrentUserId(),ImageTypeLimit:1,EnableImageTypes:"Primary,Backdrop,Thumb",SortBy:"StartDate",EnableTotalRecordCount:!1,EnableUserData:!1,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)})}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)}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"))}function renderTrackSelections(page,instance,item){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("sharedcomponents#LabelVersion"));var currentValue=select.value,selectedId=mediaSources[0].Id;select.innerHTML=mediaSources.map(function(v){var selected=v.Id===selectedId?" selected":"";return'"+v.Name+" "}).join(""),mediaSources.length>1?page.querySelector(".selectSourceContainer").classList.remove("hide"):page.querySelector(".selectSourceContainer").classList.add("hide"),select.value!==currentValue&&(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");select.setLabel(globalize.translate("sharedcomponents#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()),'"+(v.DisplayTitle||titleParts.join(" "))+" "}).join(""),select.setAttribute("disabled","disabled"),tracks.length?page.querySelector(".selectVideoContainer").classList.remove("hide"):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");select.setLabel(globalize.translate("sharedcomponents#LabelAudio"));var selectedId=mediaSource.DefaultAudioStreamIndex;select.innerHTML=tracks.map(function(v){var selected=v.Index===selectedId?" selected":"";return'"+v.DisplayTitle+" "}).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")}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");select.setLabel(globalize.translate("sharedcomponents#LabelSubtitles"));var selectedId=null==mediaSource.DefaultSubtitleStreamIndex?-1:mediaSource.DefaultSubtitleStreamIndex;if(tracks.length){var selected=-1===selectedId?" selected":"";select.innerHTML=''+globalize.translate("sharedcomponents#Off")+" "+tracks.map(function(v){return selected=v.Index===selectedId?" selected":"",'"+v.DisplayTitle+" "}).join(""),page.querySelector(".selectSubtitlesContainer").classList.remove("hide")}else select.innerHTML="",page.querySelector(".selectSubtitlesContainer").classList.add("hide")}function reloadPlayButtons(page,item){var canPlay=!1;if("Program"==item.Type){var now=new Date;now>=datetime.parseISO8601Date(item.StartDate,!0)&&now0)}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");for(i=0,length=btnPlaystates.length;i'+artist.Name+"")}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&&"Audio"===item.Type&&(item.AlbumId||item.ParentId)?(parentRoute=appRouter.getRouteUrl({Id:item.AlbumId||item.ParentId,Name:item.Album,Type:"MusicAlbum",IsFolder:!0,ServerId:item.ServerId},{context:context}),parentNameHtml.push(''+item.Album+" ")):item.Album&&"MusicVideo"===item.Type&&item.AlbumId?(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});html&&!parentNameLast?html+=''+name+" ":html=parentNameLast?''+name+" "+html:''+name+" "+html,container.innerHTML=html,html.length?container.classList.remove("hide"):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 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(),libraryBrowser.renderDetailPageBackdrop(page,item,apiClient,imageLoader,indicators);var canPlay=reloadPlayButtons(page,item);(item.LocalTrailerCount||item.RemoteTrailers&&item.RemoteTrailers.length)&&-1!==playbackManager.getSupportedCommands().indexOf("PlayTrailers")?hideAll(page,"btnPlayTrailer",!0):hideAll(page,"btnPlayTrailer"),setTrailerButtonVisibility(page,item),item.CanDelete&&!item.IsFolder?hideAll(page,"btnDeleteItem",!0):hideAll(page,"btnDeleteItem"),renderSyncLocalContainer(page,params,user,item),"Program"!==item.Type||canPlay?hideAll(page,"mainDetailButtons",!0):hideAll(page,"mainDetailButtons"),showRecordingFields(instance,page,item,user);var groupedVersions=(item.MediaSources||[]).filter(function(g){return"Grouping"==g.Type});user.Policy.IsAdministrator&&groupedVersions.length?page.querySelector(".splitVersionContainer").classList.remove("hide"):page.querySelector(".splitVersionContainer").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")}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()}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}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("")}function renderLogo(page,item,apiClient){var url=logoImageUrl(item,apiClient,{maxWidth:300}),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")}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="")}}function renderLinks(linksElem,item){var html=[];if(item.DateCreated&&itemHelper.enableDateAddedDisplay(item)){var dateCreated=datetime.parseISO8601Date(item.DateCreated);html.push(globalize.translate("sharedcomponents#AddedOnValue",datetime.toLocaleDateString(dateCreated)+" "+datetime.getDisplayTime(dateCreated)))}var links=[];if(!layoutManager.tv&&(item.HomePageUrl&&links.push(''+globalize.translate("ButtonWebsite")+" "),item.ExternalUrls))for(var i=0,length=item.ExternalUrls.length;i'+url.Name+"")}links.length&&html.push(globalize.translate("sharedcomponents#LinksValue",links.join(", "))),linksElem.innerHTML=html.join(", "),html.length?linksElem.classList.remove("hide"):linksElem.classList.add("hide")}function renderImage(page,item,apiClient,user){var container=page.querySelector(".detailImageContainer");libraryBrowser.renderDetailImage(page,container,item,apiClient,user.Policy.IsAdministrator&&"Photo"!=item.MediaType,imageLoader,indicators)}function refreshDetailImageUserData(elem,item){elem.querySelector(".detailImageProgressContainer").innerHTML=indicators.getProgressBarHtml(item)}function refreshImage(page,item,user){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")}function renderNextUp(page,item,user){var section=page.querySelector(".nextUpSection");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");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)})}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||"GameGenre"==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"),item.Type,"Series"==item.Type?renderNextUp(page,item,user):page.querySelector(".nextUpSection").classList.add("hide"),item.MediaSources&&item.MediaSources.length&&(null==item.EnableMediaSourceDisplay?"Channel"!==item.SourceType:item.EnableMediaSourceDisplay)?renderMediaSources(page,user,item):page.querySelector(".audioVideoMediaInfo").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"),page.querySelector("#themeSongsCollapsible").classList.add("hide"),page.querySelector("#themeVideosCollapsible").classList.add("hide"),"MusicAlbum"==item.Type?renderMusicVideos(page,item,user):page.querySelector("#musicVideosCollapsible").classList.add("hide"),renderThemeMedia(page,item)}function renderOverview(elems,item){for(var i=0,length=elems.length;i'+p.Name+""}).join(", "),elem=page.querySelector(".genres");elem.innerHTML=genres.length>1?globalize.translate("sharedcomponents#GenresValue",html):globalize.translate("sharedcomponents#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("sharedcomponents#DirectorsValue",html):globalize.translate("sharedcomponents#DirectorValue",html),directors.length?elem.classList.remove("hide"):elem.classList.add("hide")}function renderDetails(page,item,apiClient,context,isStatic){renderSimilarItems(page,item,context),renderMoreFromSeason(page,item,apiClient),renderMoreFromArtist(page,item,apiClient),renderDirector(page,item,apiClient,context,isStatic),renderGenres(page,item,apiClient,context,isStatic),renderChannelGuide(page,apiClient,item);var taglineElement=page.querySelector(".tagline");item.Taglines&&item.Taglines.length?(taglineElement.classList.remove("hide"),taglineElement.innerHTML=item.Taglines[0]):taglineElement.classList.add("hide");var overview=page.querySelector(".overview"),externalLinksElem=page.querySelector(".itemExternalLinks");"Season"!==item.Type&&"MusicAlbum"!==item.Type&&"MusicArtist"!==item.Type||(overview.classList.add("detailsHiddenOnMobile"),externalLinksElem.classList.add("detailsHiddenOnMobile")),renderOverview([overview],item);var i,length,itemMiscInfo=page.querySelectorAll(".itemMiscInfo-primary");for(i=0,length=itemMiscInfo.length;i "),page.querySelector(".photoInfoContent").innerHTML=html}function enableScrollX(){return browserInfo.mobile&&screen.availWidth<=1e3}function getPortraitShape(scrollX){return null==scrollX&&(scrollX=enableScrollX()),scrollX?"overflowPortrait":"portrait"}function getSquareShape(scrollX){return null==scrollX&&(scrollX=enableScrollX()),scrollX?"overflowSquare":"square"}function getThumbShape(scrollX){return null==scrollX&&(scrollX=enableScrollX()),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");var userId=apiClient.getCurrentUserId();apiClient.getEpisodes(item.SeriesId,{SeasonId:item.SeasonId,UserId:userId,Fields:"ItemCounts,PrimaryImageAspectRatio,BasicSyncInfo,CanDelete"}).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:"autoVertical",sectionTitleTagName:"h2",scalable:!0,showTitle:!0,overlayText:!1,centerText:!0,includeParentInfoInTitle:!1,allowBottomPadding:!1});var card=itemsContainer.querySelector('.card[data-id="'+item.Id+'"]');card&&setTimeout(function(){section.querySelector(".emby-scroller").toStart(card.previousSibling||card,!0)},100)})}}function renderMoreFromArtist(view,item,apiClient){var section=view.querySelector(".moreFromArtistSection");if(section)return"MusicAlbum"===item.Type&&item.AlbumArtists&&item.AlbumArtists.length?void apiClient.getItems(apiClient.getCurrentUserId(),{IncludeItemTypes:"MusicAlbum",ArtistIds:item.AlbumArtists[0].Id,Recursive:!0,ExcludeItemIds:item.Id,SortBy:"ProductionYear,SortName",SortOrder:"Descending"}).then(function(result){if(!result.Items.length)return void section.classList.add("hide");section.classList.remove("hide"),section.querySelector("h2").innerHTML=globalize.translate("MoreFromValue",item.AlbumArtists[0].Name),cardBuilder.buildCards(result.Items,{parentContainer:section,itemsContainer:section.querySelector(".itemsContainer"),shape:"autoVertical",sectionTitleTagName:"h2",scalable:!0,coverImage:"MusicArtist"===item.Type||"MusicAlbum"===item.Type,showTitle:!0,showParentTitle:!1,centerText:!0,overlayText:!1,overlayPlayButton:!0})}):void section.classList.add("hide")}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&&"Game"!=item.Type&&"MusicAlbum"!=item.Type&&"MusicArtist"!=item.Type&&"ChannelVideoItem"!=item.Type)return void similarCollapsible.classList.add("hide");similarCollapsible.classList.remove("hide");var shape="MusicAlbum"==item.Type||"MusicArtist"==item.Type?"square":"portrait",apiClient=connectionManager.getApiClient(item.ServerId),options={userId:apiClient.getCurrentUserId(),limit:"MusicAlbum"==item.Type||"MusicArtist"==item.Type?8:10,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");similarCollapsible.classList.remove("hide");var html="";html+='';var supportsImageAnalysis=appHost.supports("imageanalysis"),cardLayout=supportsImageAnalysis&&("MusicAlbum"==item.Type||"Game"==item.Type||"MusicArtist"==item.Type);cardLayout=!1,html+=cardBuilder.getCardsHtml({items:result.Items,shape:shape,showParentTitle:"MusicAlbum"==item.Type,centerText:!cardLayout,showTitle:"MusicAlbum"==item.Type||"Game"==item.Type||"MusicArtist"==item.Type,context:context,lazy:!0,showDetailsMenu:!0,coverImage:"MusicAlbum"==item.Type||"MusicArtist"==item.Type,overlayPlayButton:!0,cardLayout:cardLayout,vibrant:cardLayout&&supportsImageAnalysis}),html+="
";var similarContent=similarCollapsible.querySelector(".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");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")}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',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})+"
"),currentStartDate=itemStartDate,currentItems=[]),currentItems.push(item)}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}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)}))}function inferContext(item){return"Movie"===item.Type||"BoxSet"===item.Type?"movies":"Series"===item.Type||"Season"===item.Type||"Episode"===item.Type?"tvshows":"Game"===item.Type||"GameSystem"===item.Type?"games":"Game"===item.Type||"GameSystem"===item.Type?"games":"MusicArtist"===item.Type||"MusicAlbum"===item.Type?"music":"Program"===item.Type?"livetv":null}function filterItemsByCollectionItemType(items,typeInfo){return items.filter(function(item){return typeInfo.mediaType?item.MediaType==typeInfo.mediaType:item.Type==typeInfo.type})}function renderCollectionItems(page,parentItem,types,items){page.querySelector(".collectionItems").innerHTML="";var i,length;for(i=0,length=types.length;i0}).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',html+='',html+='
',html+=""+type.name+" ",html+=" ",html+=' ',html+="",html+='';var shape="MusicAlbum"==type.type?getSquareShape(!1):getPortraitShape(!1);html+=cardBuilder.getCardsHtml({items:items,shape:shape,showTitle:!0,centerText:!0,lazy:!0,showDetailsMenu:!0,overlayMoreButton:!0,showAddToCollection:!1,showRemoveFromCollection:!0,collectionId:parentItem.Id}),html+="
",html+="";var collectionItems=page.querySelector(".collectionItems");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 renderThemeMedia(page,item){if("SeriesTimer"!==item.Type&&"Timer"!==item.Type&&"Genre"!==item.Type&&"MusicGenre"!==item.Type&&"GameGenre"!==item.Type&&"Studio"!==item.Type&&"Person"!==item.Type){var apiClient=connectionManager.getApiClient(item.ServerId);apiClient.getThemeMedia(apiClient.getCurrentUserId(),item.Id,!0).then(function(result){var themeSongs=result.ThemeSongsResult.OwnerId==item.Id?result.ThemeSongsResult.Items:[],themeVideos=result.ThemeVideosResult.OwnerId==item.Id?result.ThemeVideosResult.Items:[];renderThemeSongs(page,themeSongs),renderThemeVideos(page,themeVideos)})}}function renderThemeSongs(page,items){if(items.length){page.querySelector("#themeSongsCollapsible").classList.remove("hide");var html=listView.getListViewHtml({items:items});page.querySelector("#themeSongsContent").innerHTML=html}else page.querySelector("#themeSongsCollapsible").classList.add("hide")}function renderThemeVideos(page,items,user){if(items.length){page.querySelector("#themeVideosCollapsible").classList.remove("hide");var themeVideosContent=page.querySelector("#themeVideosContent");themeVideosContent.innerHTML=getVideosHtml(items,user),imageLoader.lazyChildren(themeVideosContent)}else page.querySelector("#themeVideosCollapsible").classList.add("hide")}function renderMusicVideos(page,item,user){connectionManager.getApiClient(item.ServerId).getItems(user.Id,{SortBy:"SortName",SortOrder:"Ascending",IncludeItemTypes:"MusicVideo",Recursive:!0,Fields:"DateCreated,CanDelete",AlbumIds:item.Id}).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")})}function renderAdditionalParts(page,item,user){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")})}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");enableScrollX()?scenesContent.classList.add("scrollX"):scenesContent.classList.add("vertical-wrap"),require(["chaptercardbuilder"],function(chaptercardbuilder){chaptercardbuilder.buildChapterCards(item,chapters,{itemsContainer:scenesContent,width:400,backdropShape:getThumbShape(),squareShape:getSquareShape()})})}else page.querySelector("#scenesCollapsible").classList.add("hide")}function renderMediaSources(page,user,item){var html=item.MediaSources.map(function(v){return getMediaSourceHtml(user,item,v)}).join('
');item.MediaSources.length>1&&(html=" "+html),page.querySelector("#mediaInfoContent").innerHTML=html,html?page.querySelector(".audioVideoMediaInfo").classList.remove("hide"):page.querySelector(".audioVideoMediaInfo").classList.add("hide")}function getMediaSourceHtml(user,item,version){var html="";version.Name&&item.MediaSources.length>1&&(html+=''+version.Name+"
");for(var i=0,length=version.MediaStreams.length;i';html+='";var attributes=[];stream.DisplayTitle&&attributes.push(createAttribute("Title",stream.DisplayTitle)),stream.Language&&"Video"!=stream.Type&&attributes.push(createAttribute(globalize.translate("MediaInfoLanguage"),stream.Language)),stream.Codec&&attributes.push(createAttribute(globalize.translate("MediaInfoCodec"),stream.Codec.toUpperCase())),stream.CodecTag&&attributes.push(createAttribute(globalize.translate("MediaInfoCodecTag"),stream.CodecTag)),null!=stream.IsAVC&&attributes.push(createAttribute("AVC",stream.IsAVC?"Yes":"No")),stream.Profile&&attributes.push(createAttribute(globalize.translate("MediaInfoProfile"),stream.Profile)),stream.Level&&attributes.push(createAttribute(globalize.translate("MediaInfoLevel"),stream.Level)),(stream.Width||stream.Height)&&attributes.push(createAttribute(globalize.translate("MediaInfoResolution"),stream.Width+"x"+stream.Height)),stream.AspectRatio&&"mjpeg"!=stream.Codec&&attributes.push(createAttribute(globalize.translate("MediaInfoAspectRatio"),stream.AspectRatio)),"Video"==stream.Type&&(null!=stream.IsAnamorphic&&attributes.push(createAttribute(globalize.translate("MediaInfoAnamorphic"),stream.IsAnamorphic?"Yes":"No")),attributes.push(createAttribute(globalize.translate("MediaInfoInterlaced"),stream.IsInterlaced?"Yes":"No"))),(stream.AverageFrameRate||stream.RealFrameRate)&&attributes.push(createAttribute(globalize.translate("MediaInfoFramerate"),stream.AverageFrameRate||stream.RealFrameRate)),stream.ChannelLayout&&attributes.push(createAttribute(globalize.translate("MediaInfoLayout"),stream.ChannelLayout)),stream.Channels&&attributes.push(createAttribute(globalize.translate("MediaInfoChannels"),stream.Channels+" ch")),stream.BitRate&&"mjpeg"!=stream.Codec&&attributes.push(createAttribute(globalize.translate("MediaInfoBitrate"),parseInt(stream.BitRate/1e3)+" kbps")),stream.SampleRate&&attributes.push(createAttribute(globalize.translate("MediaInfoSampleRate"),stream.SampleRate+" Hz")),stream.VideoRange&&"SDR"!==stream.VideoRange&&attributes.push(createAttribute(globalize.translate("sharedcomponents#VideoRange"),stream.VideoRange)),stream.ColorPrimaries&&attributes.push(createAttribute(globalize.translate("sharedcomponents#ColorPrimaries"),stream.ColorPrimaries)),stream.ColorSpace&&attributes.push(createAttribute(globalize.translate("sharedcomponents#ColorSpace"),stream.ColorSpace)),stream.ColorTransfer&&attributes.push(createAttribute(globalize.translate("sharedcomponents#ColorTransfer"),stream.ColorTransfer)),stream.BitDepth&&attributes.push(createAttribute(globalize.translate("MediaInfoBitDepth"),stream.BitDepth+" bit")),stream.PixelFormat&&attributes.push(createAttribute(globalize.translate("MediaInfoPixelFormat"),stream.PixelFormat)),stream.RefFrames&&attributes.push(createAttribute(globalize.translate("MediaInfoRefFrames"),stream.RefFrames)),stream.NalLengthSize&&attributes.push(createAttribute("NAL",stream.NalLengthSize)),"Video"!=stream.Type&&attributes.push(createAttribute(globalize.translate("MediaInfoDefault"),stream.IsDefault?"Yes":"No")),"Subtitle"==stream.Type&&(attributes.push(createAttribute(globalize.translate("MediaInfoForced"),stream.IsForced?"Yes":"No")),attributes.push(createAttribute(globalize.translate("MediaInfoExternal"),stream.IsExternal?"Yes":"No"))),"Video"==stream.Type&&version.Timestamp&&attributes.push(createAttribute(globalize.translate("MediaInfoTimestamp"),version.Timestamp)),html+=attributes.join(" "),html+=""}}if(version.Container&&(html+=''+globalize.translate("MediaInfoContainer")+' '+version.Container+"
"),version.Formats&&version.Formats.length,version.Path&&"Http"!=version.Protocol&&user&&user.Policy.IsAdministrator&&(html+=''+globalize.translate("MediaInfoPath")+' '+version.Path+"
"),version.Size){var size=(version.Size/1048576).toFixed(0);html+=''+globalize.translate("MediaInfoSize")+' '+size+" MB
"}return html}function createAttribute(label,value){return''+label+' '+value+" "}function getVideosHtml(items,user,limit,moreButtonClass){var html=cardBuilder.getCardsHtml({items:items,shape:"auto",showTitle:!0,action:"play",overlayText:!1,centerText:!0,showRuntime:!0});return limit&&items.length>limit&&(html+=''+globalize.translate("ButtonMore")+"
"),html}function renderSpecials(page,item,user,limit){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)})}function renderCast(page,item,context,limit,isStatic){var people=(item.People||[]).filter(function(p){return"Director"!==p.Type});if(!people.length)return void page.querySelector("#castCollapsible").classList.add("hide");page.querySelector("#castCollapsible").classList.remove("hide");var castContent=page.querySelector("#castContent");enableScrollX()?(castContent.classList.add("scrollX"),limit=32):castContent.classList.add("vertical-wrap");var limitExceeded=limit&&people.length>limit;limitExceeded&&(people=people.slice(0),people.length=Math.min(limit,people.length)),require(["peoplecardbuilder"],function(peoplecardbuilder){peoplecardbuilder.buildPeopleCards(people,{itemsContainer:castContent,coverImage:!0,serverId:item.ServerId,width:160,shape:getPortraitShape()})});var morePeopleButton=page.querySelector(".morePeople");morePeopleButton&&(limitExceeded&&!enableScrollX()?morePeopleButton.classList.remove("hide"):morePeopleButton.classList.add("hide"))}function itemDetailPage(){var self=this;self.setInitialCollapsibleState=setInitialCollapsibleState,self.renderDetails=renderDetails,self.renderCast=renderCast,self.renderMediaSources=renderMediaSources}function bindAll(view,selector,eventName,fn){var i,length,elems=view.querySelectorAll(selector);for(i=0,length=elems.length;i',html+=listView.getListViewHtml({items:items,enableUserDataButtons:!1,image:!0,imageSource:"channel",showProgramDateTime:!0,showChannel:!1,mediaInfo:!1,action:"none",moreButton:!1,recordButton:!1}),html+=""}function renderSeriesTimerSchedule(page,apiClient,seriesTimerId){apiClient.getLiveTvTimers({UserId:apiClient.getCurrentUserId(),ImageTypeLimit:1,EnableImageTypes:"Primary,Backdrop,Thumb",SortBy:"StartDate",EnableTotalRecordCount:!1,EnableUserData:!1,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)})}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)}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"))}function renderTrackSelections(page,instance,item){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("sharedcomponents#LabelVersion"));var currentValue=select.value,selectedId=mediaSources[0].Id;select.innerHTML=mediaSources.map(function(v){var selected=v.Id===selectedId?" selected":"";return'"+v.Name+" "}).join(""),mediaSources.length>1?page.querySelector(".selectSourceContainer").classList.remove("hide"):page.querySelector(".selectSourceContainer").classList.add("hide"),select.value!==currentValue&&(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");select.setLabel(globalize.translate("sharedcomponents#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()),'"+(v.DisplayTitle||titleParts.join(" "))+" "}).join(""),select.setAttribute("disabled","disabled"),tracks.length?page.querySelector(".selectVideoContainer").classList.remove("hide"):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");select.setLabel(globalize.translate("sharedcomponents#LabelAudio"));var selectedId=mediaSource.DefaultAudioStreamIndex;select.innerHTML=tracks.map(function(v){var selected=v.Index===selectedId?" selected":"";return'"+v.DisplayTitle+" "}).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")}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");select.setLabel(globalize.translate("sharedcomponents#LabelSubtitles"));var selectedId=null==mediaSource.DefaultSubtitleStreamIndex?-1:mediaSource.DefaultSubtitleStreamIndex;if(tracks.length){var selected=-1===selectedId?" selected":"";select.innerHTML=''+globalize.translate("sharedcomponents#Off")+" "+tracks.map(function(v){return selected=v.Index===selectedId?" selected":"",'"+v.DisplayTitle+" "}).join(""),page.querySelector(".selectSubtitlesContainer").classList.remove("hide")}else select.innerHTML="",page.querySelector(".selectSubtitlesContainer").classList.add("hide")}function reloadPlayButtons(page,item){var canPlay=!1;if("Program"==item.Type){var now=new Date;now>=datetime.parseISO8601Date(item.StartDate,!0)&&now0)}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");for(i=0,length=btnPlaystates.length;i'+artist.Name+"")}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&&"Audio"===item.Type&&(item.AlbumId||item.ParentId)?(parentRoute=appRouter.getRouteUrl({Id:item.AlbumId||item.ParentId,Name:item.Album,Type:"MusicAlbum",IsFolder:!0,ServerId:item.ServerId},{context:context}),parentNameHtml.push(''+item.Album+" ")):item.Album&&"MusicVideo"===item.Type&&item.AlbumId?(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});html&&!parentNameLast?html+=''+name+" ":html=parentNameLast?''+name+" "+html:''+name+" "+html,container.innerHTML=html,html.length?container.classList.remove("hide"):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 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(),libraryBrowser.renderDetailPageBackdrop(page,item,apiClient,imageLoader,indicators);var canPlay=reloadPlayButtons(page,item);(item.LocalTrailerCount||item.RemoteTrailers&&item.RemoteTrailers.length)&&-1!==playbackManager.getSupportedCommands().indexOf("PlayTrailers")?hideAll(page,"btnPlayTrailer",!0):hideAll(page,"btnPlayTrailer"),setTrailerButtonVisibility(page,item),item.CanDelete&&!item.IsFolder?hideAll(page,"btnDeleteItem",!0):hideAll(page,"btnDeleteItem"),renderSyncLocalContainer(page,params,user,item),"Program"!==item.Type||canPlay?hideAll(page,"mainDetailButtons",!0):hideAll(page,"mainDetailButtons"),showRecordingFields(instance,page,item,user);var groupedVersions=(item.MediaSources||[]).filter(function(g){return"Grouping"==g.Type});user.Policy.IsAdministrator&&groupedVersions.length?page.querySelector(".splitVersionContainer").classList.remove("hide"):page.querySelector(".splitVersionContainer").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")}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()}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}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("")}function renderLogo(page,item,apiClient){var url=logoImageUrl(item,apiClient,{maxWidth:300}),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")}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="")}}function renderLinks(linksElem,item){var html=[];if(item.DateCreated&&itemHelper.enableDateAddedDisplay(item)){var dateCreated=datetime.parseISO8601Date(item.DateCreated);html.push(globalize.translate("sharedcomponents#AddedOnValue",datetime.toLocaleDateString(dateCreated)+" "+datetime.getDisplayTime(dateCreated)))}var links=[];if(!layoutManager.tv&&(item.HomePageUrl&&links.push(''+globalize.translate("ButtonWebsite")+" "),item.ExternalUrls))for(var i=0,length=item.ExternalUrls.length;i'+url.Name+"")}links.length&&html.push(globalize.translate("sharedcomponents#LinksValue",links.join(", "))),linksElem.innerHTML=html.join(", "),html.length?linksElem.classList.remove("hide"):linksElem.classList.add("hide")}function renderImage(page,item,apiClient,user){var container=page.querySelector(".detailImageContainer");libraryBrowser.renderDetailImage(page,container,item,apiClient,user.Policy.IsAdministrator&&"Photo"!=item.MediaType,imageLoader,indicators)}function refreshDetailImageUserData(elem,item){elem.querySelector(".detailImageProgressContainer").innerHTML=indicators.getProgressBarHtml(item)}function refreshImage(page,item,user){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")}function renderNextUp(page,item,user){var section=page.querySelector(".nextUpSection");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");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)})}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||"GameGenre"==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"),item.Type,"Series"==item.Type?renderNextUp(page,item,user):page.querySelector(".nextUpSection").classList.add("hide"),item.MediaSources&&item.MediaSources.length&&(null==item.EnableMediaSourceDisplay?"Channel"!==item.SourceType:item.EnableMediaSourceDisplay)?renderMediaSources(page,user,item):page.querySelector(".audioVideoMediaInfo").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"),page.querySelector("#themeSongsCollapsible").classList.add("hide"),page.querySelector("#themeVideosCollapsible").classList.add("hide"),"MusicAlbum"==item.Type?renderMusicVideos(page,item,user):page.querySelector("#musicVideosCollapsible").classList.add("hide"),renderThemeMedia(page,item)}function renderOverview(elems,item){for(var i=0,length=elems.length;i'+p.Name+""}).join(", "),elem=page.querySelector(".genres");elem.innerHTML=genres.length>1?globalize.translate("sharedcomponents#GenresValue",html):globalize.translate("sharedcomponents#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("sharedcomponents#DirectorsValue",html):globalize.translate("sharedcomponents#DirectorValue",html),directors.length?elem.classList.remove("hide"):elem.classList.add("hide")}function renderDetails(page,item,apiClient,context,isStatic){renderSimilarItems(page,item,context),renderMoreFromSeason(page,item,apiClient),renderMoreFromArtist(page,item,apiClient),renderDirector(page,item,apiClient,context,isStatic),renderGenres(page,item,apiClient,context,isStatic),renderChannelGuide(page,apiClient,item);var taglineElement=page.querySelector(".tagline");item.Taglines&&item.Taglines.length?(taglineElement.classList.remove("hide"),taglineElement.innerHTML=item.Taglines[0]):taglineElement.classList.add("hide");var overview=page.querySelector(".overview"),externalLinksElem=page.querySelector(".itemExternalLinks");"Season"!==item.Type&&"MusicAlbum"!==item.Type&&"MusicArtist"!==item.Type||(overview.classList.add("detailsHiddenOnMobile"),externalLinksElem.classList.add("detailsHiddenOnMobile")),renderOverview([overview],item);var i,length,itemMiscInfo=page.querySelectorAll(".itemMiscInfo-primary");for(i=0,length=itemMiscInfo.length;i "),page.querySelector(".photoInfoContent").innerHTML=html}function enableScrollX(){return browserInfo.mobile&&screen.availWidth<=1e3}function getPortraitShape(scrollX){return null==scrollX&&(scrollX=enableScrollX()),scrollX?"overflowPortrait":"portrait"}function getSquareShape(scrollX){return null==scrollX&&(scrollX=enableScrollX()),scrollX?"overflowSquare":"square"}function getThumbShape(scrollX){return null==scrollX&&(scrollX=enableScrollX()),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");var userId=apiClient.getCurrentUserId();apiClient.getEpisodes(item.SeriesId,{SeasonId:item.SeasonId,UserId:userId,Fields:"ItemCounts,PrimaryImageAspectRatio,BasicSyncInfo,CanDelete"}).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:"autoVertical",sectionTitleTagName:"h2",scalable:!0,showTitle:!0,overlayText:!1,centerText:!0,includeParentInfoInTitle:!1,allowBottomPadding:!1});var card=itemsContainer.querySelector('.card[data-id="'+item.Id+'"]');card&&setTimeout(function(){section.querySelector(".emby-scroller").toStart(card.previousSibling||card,!0)},100)})}}function renderMoreFromArtist(view,item,apiClient){var section=view.querySelector(".moreFromArtistSection");if(section){if("MusicAlbum"!==item.Type||!item.AlbumArtists||!item.AlbumArtists.length)return void section.classList.add("hide");var query={IncludeItemTypes:"MusicAlbum",Recursive:!0,ExcludeItemIds:item.Id,SortBy:"ProductionYear,SortName",SortOrder:"Descending"};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"),section.querySelector("h2").innerHTML=globalize.translate("MoreFromValue",item.AlbumArtists[0].Name),cardBuilder.buildCards(result.Items,{parentContainer:section,itemsContainer:section.querySelector(".itemsContainer"),shape:"autoVertical",sectionTitleTagName:"h2",scalable:!0,coverImage:"MusicArtist"===item.Type||"MusicAlbum"===item.Type,showTitle:!0,showParentTitle:!1,centerText:!0,overlayText:!1,overlayPlayButton:!0})})}}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&&"Game"!=item.Type&&"MusicAlbum"!=item.Type&&"MusicArtist"!=item.Type&&"ChannelVideoItem"!=item.Type)return void similarCollapsible.classList.add("hide");similarCollapsible.classList.remove("hide");var shape="MusicAlbum"==item.Type||"MusicArtist"==item.Type?"square":"portrait",apiClient=connectionManager.getApiClient(item.ServerId),options={userId:apiClient.getCurrentUserId(),limit:"MusicAlbum"==item.Type||"MusicArtist"==item.Type?8:10,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");similarCollapsible.classList.remove("hide");var html="";html+='';var supportsImageAnalysis=appHost.supports("imageanalysis"),cardLayout=supportsImageAnalysis&&("MusicAlbum"==item.Type||"Game"==item.Type||"MusicArtist"==item.Type);cardLayout=!1,html+=cardBuilder.getCardsHtml({items:result.Items,shape:shape,showParentTitle:"MusicAlbum"==item.Type,centerText:!cardLayout,showTitle:"MusicAlbum"==item.Type||"Game"==item.Type||"MusicArtist"==item.Type,context:context,lazy:!0,showDetailsMenu:!0,coverImage:"MusicAlbum"==item.Type||"MusicArtist"==item.Type,overlayPlayButton:!0,cardLayout:cardLayout,vibrant:cardLayout&&supportsImageAnalysis}),html+="
";var similarContent=similarCollapsible.querySelector(".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");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")}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',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})+"
"),currentStartDate=itemStartDate,currentItems=[]),currentItems.push(item)}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}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)}))}function inferContext(item){return"Movie"===item.Type||"BoxSet"===item.Type?"movies":"Series"===item.Type||"Season"===item.Type||"Episode"===item.Type?"tvshows":"Game"===item.Type||"GameSystem"===item.Type?"games":"Game"===item.Type||"GameSystem"===item.Type?"games":"MusicArtist"===item.Type||"MusicAlbum"===item.Type?"music":"Program"===item.Type?"livetv":null}function filterItemsByCollectionItemType(items,typeInfo){return items.filter(function(item){return typeInfo.mediaType?item.MediaType==typeInfo.mediaType:item.Type==typeInfo.type})}function renderCollectionItems(page,parentItem,types,items){page.querySelector(".collectionItems").innerHTML="";var i,length;for(i=0,length=types.length;i0}).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',html+='',html+='
',html+=""+type.name+" ",html+=" ",html+=' ',html+="",html+='';var shape="MusicAlbum"==type.type?getSquareShape(!1):getPortraitShape(!1);html+=cardBuilder.getCardsHtml({items:items,shape:shape,showTitle:!0,centerText:!0,lazy:!0,showDetailsMenu:!0,overlayMoreButton:!0,showAddToCollection:!1,showRemoveFromCollection:!0,collectionId:parentItem.Id}),html+="
",html+="";var collectionItems=page.querySelector(".collectionItems");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 renderThemeMedia(page,item){if("SeriesTimer"!==item.Type&&"Timer"!==item.Type&&"Genre"!==item.Type&&"MusicGenre"!==item.Type&&"GameGenre"!==item.Type&&"Studio"!==item.Type&&"Person"!==item.Type){var apiClient=connectionManager.getApiClient(item.ServerId);apiClient.getThemeMedia(apiClient.getCurrentUserId(),item.Id,!0).then(function(result){var themeSongs=result.ThemeSongsResult.OwnerId==item.Id?result.ThemeSongsResult.Items:[],themeVideos=result.ThemeVideosResult.OwnerId==item.Id?result.ThemeVideosResult.Items:[];renderThemeSongs(page,themeSongs),renderThemeVideos(page,themeVideos)})}}function renderThemeSongs(page,items){if(items.length){page.querySelector("#themeSongsCollapsible").classList.remove("hide");var html=listView.getListViewHtml({items:items});page.querySelector("#themeSongsContent").innerHTML=html}else page.querySelector("#themeSongsCollapsible").classList.add("hide")}function renderThemeVideos(page,items,user){if(items.length){page.querySelector("#themeVideosCollapsible").classList.remove("hide");var themeVideosContent=page.querySelector("#themeVideosContent");themeVideosContent.innerHTML=getVideosHtml(items,user),imageLoader.lazyChildren(themeVideosContent)}else page.querySelector("#themeVideosCollapsible").classList.add("hide")}function renderMusicVideos(page,item,user){connectionManager.getApiClient(item.ServerId).getItems(user.Id,{SortBy:"SortName",SortOrder:"Ascending",IncludeItemTypes:"MusicVideo",Recursive:!0,Fields:"DateCreated,CanDelete",AlbumIds:item.Id}).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")})}function renderAdditionalParts(page,item,user){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")})}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");enableScrollX()?scenesContent.classList.add("scrollX"):scenesContent.classList.add("vertical-wrap"),require(["chaptercardbuilder"],function(chaptercardbuilder){chaptercardbuilder.buildChapterCards(item,chapters,{itemsContainer:scenesContent,width:400,backdropShape:getThumbShape(),squareShape:getSquareShape()})})}else page.querySelector("#scenesCollapsible").classList.add("hide")}function renderMediaSources(page,user,item){var html=item.MediaSources.map(function(v){return getMediaSourceHtml(user,item,v)}).join('
');item.MediaSources.length>1&&(html=" "+html),page.querySelector("#mediaInfoContent").innerHTML=html,html?page.querySelector(".audioVideoMediaInfo").classList.remove("hide"):page.querySelector(".audioVideoMediaInfo").classList.add("hide")}function getMediaSourceHtml(user,item,version){var html="";version.Name&&item.MediaSources.length>1&&(html+=''+version.Name+"
");for(var i=0,length=version.MediaStreams.length;i';html+='";var attributes=[];stream.DisplayTitle&&attributes.push(createAttribute("Title",stream.DisplayTitle)),stream.Language&&"Video"!=stream.Type&&attributes.push(createAttribute(globalize.translate("MediaInfoLanguage"),stream.Language)),stream.Codec&&attributes.push(createAttribute(globalize.translate("MediaInfoCodec"),stream.Codec.toUpperCase())),stream.CodecTag&&attributes.push(createAttribute(globalize.translate("MediaInfoCodecTag"),stream.CodecTag)),null!=stream.IsAVC&&attributes.push(createAttribute("AVC",stream.IsAVC?"Yes":"No")),stream.Profile&&attributes.push(createAttribute(globalize.translate("MediaInfoProfile"),stream.Profile)),stream.Level&&attributes.push(createAttribute(globalize.translate("MediaInfoLevel"),stream.Level)),(stream.Width||stream.Height)&&attributes.push(createAttribute(globalize.translate("MediaInfoResolution"),stream.Width+"x"+stream.Height)),stream.AspectRatio&&"mjpeg"!=stream.Codec&&attributes.push(createAttribute(globalize.translate("MediaInfoAspectRatio"),stream.AspectRatio)),"Video"==stream.Type&&(null!=stream.IsAnamorphic&&attributes.push(createAttribute(globalize.translate("MediaInfoAnamorphic"),stream.IsAnamorphic?"Yes":"No")),attributes.push(createAttribute(globalize.translate("MediaInfoInterlaced"),stream.IsInterlaced?"Yes":"No"))),(stream.AverageFrameRate||stream.RealFrameRate)&&attributes.push(createAttribute(globalize.translate("MediaInfoFramerate"),stream.AverageFrameRate||stream.RealFrameRate)),stream.ChannelLayout&&attributes.push(createAttribute(globalize.translate("MediaInfoLayout"),stream.ChannelLayout)),stream.Channels&&attributes.push(createAttribute(globalize.translate("MediaInfoChannels"),stream.Channels+" ch")),stream.BitRate&&"mjpeg"!=stream.Codec&&attributes.push(createAttribute(globalize.translate("MediaInfoBitrate"),parseInt(stream.BitRate/1e3)+" kbps")),stream.SampleRate&&attributes.push(createAttribute(globalize.translate("MediaInfoSampleRate"),stream.SampleRate+" Hz")),stream.VideoRange&&"SDR"!==stream.VideoRange&&attributes.push(createAttribute(globalize.translate("sharedcomponents#VideoRange"),stream.VideoRange)),stream.ColorPrimaries&&attributes.push(createAttribute(globalize.translate("sharedcomponents#ColorPrimaries"),stream.ColorPrimaries)),stream.ColorSpace&&attributes.push(createAttribute(globalize.translate("sharedcomponents#ColorSpace"),stream.ColorSpace)),stream.ColorTransfer&&attributes.push(createAttribute(globalize.translate("sharedcomponents#ColorTransfer"),stream.ColorTransfer)),stream.BitDepth&&attributes.push(createAttribute(globalize.translate("MediaInfoBitDepth"),stream.BitDepth+" bit")),stream.PixelFormat&&attributes.push(createAttribute(globalize.translate("MediaInfoPixelFormat"),stream.PixelFormat)),stream.RefFrames&&attributes.push(createAttribute(globalize.translate("MediaInfoRefFrames"),stream.RefFrames)),stream.NalLengthSize&&attributes.push(createAttribute("NAL",stream.NalLengthSize)),"Video"!=stream.Type&&attributes.push(createAttribute(globalize.translate("MediaInfoDefault"),stream.IsDefault?"Yes":"No")),"Subtitle"==stream.Type&&(attributes.push(createAttribute(globalize.translate("MediaInfoForced"),stream.IsForced?"Yes":"No")),attributes.push(createAttribute(globalize.translate("MediaInfoExternal"),stream.IsExternal?"Yes":"No"))),"Video"==stream.Type&&version.Timestamp&&attributes.push(createAttribute(globalize.translate("MediaInfoTimestamp"),version.Timestamp)),html+=attributes.join(" "),html+=""}}if(version.Container&&(html+=''+globalize.translate("MediaInfoContainer")+' '+version.Container+"
"),version.Formats&&version.Formats.length,version.Path&&"Http"!=version.Protocol&&user&&user.Policy.IsAdministrator&&(html+=''+globalize.translate("MediaInfoPath")+' '+version.Path+"
"),version.Size){var size=(version.Size/1048576).toFixed(0);html+=''+globalize.translate("MediaInfoSize")+' '+size+" MB
"}return html}function createAttribute(label,value){return''+label+' '+value+" "}function getVideosHtml(items,user,limit,moreButtonClass){var html=cardBuilder.getCardsHtml({items:items,shape:"auto",showTitle:!0,action:"play",overlayText:!1,centerText:!0,showRuntime:!0});return limit&&items.length>limit&&(html+=''+globalize.translate("ButtonMore")+"
"),html}function renderSpecials(page,item,user,limit){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)})}function renderCast(page,item,context,limit,isStatic){var people=(item.People||[]).filter(function(p){return"Director"!==p.Type});if(!people.length)return void page.querySelector("#castCollapsible").classList.add("hide");page.querySelector("#castCollapsible").classList.remove("hide");var castContent=page.querySelector("#castContent");enableScrollX()?(castContent.classList.add("scrollX"),limit=32):castContent.classList.add("vertical-wrap");var limitExceeded=limit&&people.length>limit;limitExceeded&&(people=people.slice(0),people.length=Math.min(limit,people.length)),require(["peoplecardbuilder"],function(peoplecardbuilder){peoplecardbuilder.buildPeopleCards(people,{itemsContainer:castContent,coverImage:!0,serverId:item.ServerId,width:160,shape:getPortraitShape()})});var morePeopleButton=page.querySelector(".morePeople");morePeopleButton&&(limitExceeded&&!enableScrollX()?morePeopleButton.classList.remove("hide"):morePeopleButton.classList.add("hide"))}function itemDetailPage(){var self=this;self.setInitialCollapsibleState=setInitialCollapsibleState,self.renderDetails=renderDetails,self.renderCast=renderCast,self.renderMediaSources=renderMediaSources}function bindAll(view,selector,eventName,fn){var i,length,elems=view.querySelectorAll(selector);for(i=0,length=elems.length;i=11&&list.push("cordova/mpvplayer")),list.push("bower_components/emby-webcomponents/htmlaudioplayer/plugin"),"cordova"===self.appMode&&list.push("cordova/chromecast"),"android"===self.appMode&&list.push("cordova/externalplayer"),list.push("bower_components/emby-webcomponents/htmlvideoplayer/plugin"),list.push("bower_components/emby-webcomponents/photoplayer/plugin"),appHost.supports("remotecontrol")&&(list.push("bower_components/emby-webcomponents/sessionplayer"),(browser.chrome||browser.opera)&&list.push("bower_components/emby-webcomponents/chromecast/chromecastplayer")),list.push("bower_components/emby-webcomponents/youtubeplayer/plugin");for(var i=0,length=externalPlugins.length;i=11&&list.push("cordova/mpvplayer")),list.push("bower_components/emby-webcomponents/htmlaudioplayer/plugin"),"cordova"===self.appMode&&list.push("cordova/chromecast"),"android"===self.appMode&&list.push("cordova/externalplayer"),list.push("bower_components/emby-webcomponents/htmlvideoplayer/plugin"),list.push("bower_components/emby-webcomponents/photoplayer/plugin"),appHost.supports("remotecontrol")&&(list.push("bower_components/emby-webcomponents/sessionplayer"),(browser.chrome||browser.opera)&&list.push("bower_components/emby-webcomponents/chromecast/chromecastplayer")),list.push("bower_components/emby-webcomponents/youtubeplayer/plugin");for(var i=0,length=externalPlugins.length;i'+Globalize.translate("HeaderLibraries")+"",html+='';for(var i=0,length=mediaFolders.length;i"+folder.Name+" "}html+="
",page.querySelector(".folderAccess").innerHTML=html;var chkEnableAllFolders=page.querySelector("#chkEnableAllFolders");chkEnableAllFolders.checked=user.Policy.EnableAllFolders,triggerChange(chkEnableAllFolders)}function loadChannels(page,user,channels){var html="";html+=''+Globalize.translate("HeaderChannels")+" ",html+='';for(var i=0,length=channels.length;i"+folder.Name+" "}html+="
",$(".channelAccess",page).show().html(html),channels.length?$(".channelAccessContainer",page).show():$(".channelAccessContainer",page).hide(),$("#chkEnableAllChannels",page).checked(user.Policy.EnableAllChannels).trigger("change")}function loadDevices(page,user,devices){var html="";html+=''+Globalize.translate("HeaderDevices")+" ",html+='';for(var i=0,length=devices.length;i"+device.Name+" - "+device.AppName+" "}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()}function onSaveComplete(page){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)})}function onSubmit(){var page=$(this).parents(".page");loading.show();var userId=getParameterByName("userId");return ApiClient.getUser(userId).then(function(result){saveUser(result,page)}),!1}$(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(){var page=this;loading.show();var promise1,userId=getParameterByName("userId");if(userId)promise1=ApiClient.getUser(userId);else{var deferred=$.Deferred();deferred.resolveWith(null,[{Configuration:{}}]),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",{SupportsPersistentIdentifier:!0}));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
+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)}function loadMediaFolders(page,user,mediaFolders){var html="";html+=''+Globalize.translate("HeaderLibraries")+" ",html+='';for(var i=0,length=mediaFolders.length;i"+folder.Name+" "}html+="
",page.querySelector(".folderAccess").innerHTML=html;var chkEnableAllFolders=page.querySelector("#chkEnableAllFolders");chkEnableAllFolders.checked=user.Policy.EnableAllFolders,triggerChange(chkEnableAllFolders)}function loadChannels(page,user,channels){var html="";html+=''+Globalize.translate("HeaderChannels")+" ",html+='';for(var i=0,length=channels.length;i"+folder.Name+" "}html+="
",$(".channelAccess",page).show().html(html),channels.length?$(".channelAccessContainer",page).show():$(".channelAccessContainer",page).hide(),$("#chkEnableAllChannels",page).checked(user.Policy.EnableAllChannels).trigger("change")}function loadDevices(page,user,devices){var html="";html+=''+Globalize.translate("HeaderDevices")+" ",html+='';for(var i=0,length=devices.length;i"+device.Name+" - "+device.AppName+" "}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()}function onSaveComplete(page){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)})}function onSubmit(){var page=$(this).parents(".page");loading.show();var userId=getParameterByName("userId");return ApiClient.getUser(userId).then(function(result){saveUser(result,page)}),!1}$(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(){var page=this;loading.show();var promise1,userId=getParameterByName("userId");if(userId)promise1=ApiClient.getUser(userId);else{var deferred=$.Deferred();deferred.resolveWith(null,[{Configuration:{}}]),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
diff --git a/MediaBrowser.WebDashboard/packages.config b/MediaBrowser.WebDashboard/packages.config
index 1c4aaf7ddf..c26580a70a 100644
--- a/MediaBrowser.WebDashboard/packages.config
+++ b/MediaBrowser.WebDashboard/packages.config
@@ -1,5 +1,5 @@
-
-
+
+
\ No newline at end of file
diff --git a/MediaBrowser.XbmcMetadata/MediaBrowser.XbmcMetadata.csproj b/MediaBrowser.XbmcMetadata/MediaBrowser.XbmcMetadata.csproj
index 8e3b426762..a718425204 100644
--- a/MediaBrowser.XbmcMetadata/MediaBrowser.XbmcMetadata.csproj
+++ b/MediaBrowser.XbmcMetadata/MediaBrowser.XbmcMetadata.csproj
@@ -61,13 +61,13 @@
- ..\packages\MediaBrowser.Common.3.3.50-beta\lib\netstandard2.0\MediaBrowser.Common.dll
+ ..\packages\MediaBrowser.Common.3.3.53-beta\lib\netstandard2.0\MediaBrowser.Common.dll
- ..\packages\MediaBrowser.Server.Core.3.3.50-beta\lib\netstandard2.0\MediaBrowser.Controller.dll
+ ..\packages\MediaBrowser.Server.Core.3.3.53-beta\lib\netstandard2.0\MediaBrowser.Controller.dll
- ..\packages\MediaBrowser.Common.3.3.50-beta\lib\netstandard2.0\MediaBrowser.Model.dll
+ ..\packages\MediaBrowser.Common.3.3.53-beta\lib\netstandard2.0\MediaBrowser.Model.dll
diff --git a/MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs b/MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs
index 97e97cc9c1..517241ee56 100644
--- a/MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs
+++ b/MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs
@@ -575,15 +575,11 @@ protected virtual void FetchDataFromXmlNode(XmlReader reader, MetadataResult
{
var val = reader.ReadElementContentAsString();
- var hasTrailer = item as IHasTrailers;
- if (hasTrailer != null)
+ if (!string.IsNullOrWhiteSpace(val))
{
- if (!string.IsNullOrWhiteSpace(val))
- {
- val = val.Replace("plugin://plugin.video.youtube/?action=play_video&videoid=", BaseNfoSaver.YouTubeWatchUrl, StringComparison.OrdinalIgnoreCase);
+ val = val.Replace("plugin://plugin.video.youtube/?action=play_video&videoid=", BaseNfoSaver.YouTubeWatchUrl, StringComparison.OrdinalIgnoreCase);
- hasTrailer.AddTrailerUrl(val);
- }
+ item.AddTrailerUrl(val);
}
break;
}
diff --git a/MediaBrowser.XbmcMetadata/Savers/BaseNfoSaver.cs b/MediaBrowser.XbmcMetadata/Savers/BaseNfoSaver.cs
index 89fbcbce84..505fec65fb 100644
--- a/MediaBrowser.XbmcMetadata/Savers/BaseNfoSaver.cs
+++ b/MediaBrowser.XbmcMetadata/Savers/BaseNfoSaver.cs
@@ -528,13 +528,9 @@ private void AddCommonNodes(BaseItem item, XmlWriter writer, ILibraryManager lib
writer.WriteElementString("credits", person);
}
- var hasTrailer = item as IHasTrailers;
- if (hasTrailer != null)
+ foreach (var trailer in item.RemoteTrailers)
{
- foreach (var trailer in hasTrailer.RemoteTrailers)
- {
- writer.WriteElementString("trailer", GetOutputTrailerUrl(trailer.Url));
- }
+ writer.WriteElementString("trailer", GetOutputTrailerUrl(trailer.Url));
}
if (item.CommunityRating.HasValue)
diff --git a/MediaBrowser.XbmcMetadata/packages.config b/MediaBrowser.XbmcMetadata/packages.config
index 1c4aaf7ddf..c26580a70a 100644
--- a/MediaBrowser.XbmcMetadata/packages.config
+++ b/MediaBrowser.XbmcMetadata/packages.config
@@ -1,5 +1,5 @@
-
-
+
+
\ No newline at end of file
diff --git a/Mono.Nat/Mono.Nat.csproj b/Mono.Nat/Mono.Nat.csproj
index b5a0436bd9..074b9ab578 100644
--- a/Mono.Nat/Mono.Nat.csproj
+++ b/Mono.Nat/Mono.Nat.csproj
@@ -32,10 +32,10 @@
- ..\packages\MediaBrowser.Common.3.3.50-beta\lib\netstandard2.0\MediaBrowser.Common.dll
+ ..\packages\MediaBrowser.Common.3.3.53-beta\lib\netstandard2.0\MediaBrowser.Common.dll
- ..\packages\MediaBrowser.Common.3.3.50-beta\lib\netstandard2.0\MediaBrowser.Model.dll
+ ..\packages\MediaBrowser.Common.3.3.53-beta\lib\netstandard2.0\MediaBrowser.Model.dll
diff --git a/Mono.Nat/packages.config b/Mono.Nat/packages.config
index 76aa4bb8c7..85e552f7ee 100644
--- a/Mono.Nat/packages.config
+++ b/Mono.Nat/packages.config
@@ -1,4 +1,4 @@
-
+
\ No newline at end of file
diff --git a/RSSDP/RSSDP.csproj b/RSSDP/RSSDP.csproj
index a0c4a23306..ab76d3ba03 100644
--- a/RSSDP/RSSDP.csproj
+++ b/RSSDP/RSSDP.csproj
@@ -58,10 +58,10 @@
- ..\packages\MediaBrowser.Common.3.3.50-beta\lib\netstandard2.0\MediaBrowser.Common.dll
+ ..\packages\MediaBrowser.Common.3.3.53-beta\lib\netstandard2.0\MediaBrowser.Common.dll
- ..\packages\MediaBrowser.Common.3.3.50-beta\lib\netstandard2.0\MediaBrowser.Model.dll
+ ..\packages\MediaBrowser.Common.3.3.53-beta\lib\netstandard2.0\MediaBrowser.Model.dll
diff --git a/RSSDP/packages.config b/RSSDP/packages.config
index 76aa4bb8c7..85e552f7ee 100644
--- a/RSSDP/packages.config
+++ b/RSSDP/packages.config
@@ -1,4 +1,4 @@
-
+
\ No newline at end of file
diff --git a/SharedVersion.cs b/SharedVersion.cs
index 54d3c0e92e..9e9d629065 100644
--- a/SharedVersion.cs
+++ b/SharedVersion.cs
@@ -1,3 +1,3 @@
using System.Reflection;
-[assembly: AssemblyVersion("3.4.1.17")]
+[assembly: AssemblyVersion("3.4.1.18")]
diff --git a/SocketHttpListener/SocketHttpListener.csproj b/SocketHttpListener/SocketHttpListener.csproj
index 417158295f..7c58e11fc7 100644
--- a/SocketHttpListener/SocketHttpListener.csproj
+++ b/SocketHttpListener/SocketHttpListener.csproj
@@ -36,10 +36,10 @@
- ..\packages\MediaBrowser.Common.3.3.50-beta\lib\netstandard2.0\MediaBrowser.Common.dll
+ ..\packages\MediaBrowser.Common.3.3.53-beta\lib\netstandard2.0\MediaBrowser.Common.dll
- ..\packages\MediaBrowser.Common.3.3.50-beta\lib\netstandard2.0\MediaBrowser.Model.dll
+ ..\packages\MediaBrowser.Common.3.3.53-beta\lib\netstandard2.0\MediaBrowser.Model.dll
diff --git a/SocketHttpListener/packages.config b/SocketHttpListener/packages.config
index 76aa4bb8c7..85e552f7ee 100644
--- a/SocketHttpListener/packages.config
+++ b/SocketHttpListener/packages.config
@@ -1,4 +1,4 @@
-
+
\ No newline at end of file
diff --git a/ThirdParty/emby/Emby.Server.Connect.dll b/ThirdParty/emby/Emby.Server.Connect.dll
index 28170e317a..120b3776b9 100644
Binary files a/ThirdParty/emby/Emby.Server.Connect.dll and b/ThirdParty/emby/Emby.Server.Connect.dll differ
diff --git a/ThirdParty/emby/Emby.Server.MediaEncoding.dll b/ThirdParty/emby/Emby.Server.MediaEncoding.dll
index 8f7def8f16..a69aec8e4f 100644
Binary files a/ThirdParty/emby/Emby.Server.MediaEncoding.dll and b/ThirdParty/emby/Emby.Server.MediaEncoding.dll differ
diff --git a/ThirdParty/emby/Emby.Server.Sync.dll b/ThirdParty/emby/Emby.Server.Sync.dll
index a11117c896..28868bc85e 100644
Binary files a/ThirdParty/emby/Emby.Server.Sync.dll and b/ThirdParty/emby/Emby.Server.Sync.dll differ
diff --git a/packages/MediaBrowser.Common.3.3.50-beta/MediaBrowser.Common.3.3.50-beta.nupkg b/packages/MediaBrowser.Common.3.3.50-beta/MediaBrowser.Common.3.3.50-beta.nupkg
deleted file mode 100644
index 18ead30dc3..0000000000
Binary files a/packages/MediaBrowser.Common.3.3.50-beta/MediaBrowser.Common.3.3.50-beta.nupkg and /dev/null differ
diff --git a/packages/MediaBrowser.Common.3.3.50-beta/lib/netstandard2.0/MediaBrowser.Model.dll b/packages/MediaBrowser.Common.3.3.50-beta/lib/netstandard2.0/MediaBrowser.Model.dll
deleted file mode 100644
index bea7439b1a..0000000000
Binary files a/packages/MediaBrowser.Common.3.3.50-beta/lib/netstandard2.0/MediaBrowser.Model.dll and /dev/null differ
diff --git a/packages/MediaBrowser.Common.3.3.53-beta/MediaBrowser.Common.3.3.53-beta.nupkg b/packages/MediaBrowser.Common.3.3.53-beta/MediaBrowser.Common.3.3.53-beta.nupkg
new file mode 100644
index 0000000000..0e52cd0fde
Binary files /dev/null and b/packages/MediaBrowser.Common.3.3.53-beta/MediaBrowser.Common.3.3.53-beta.nupkg differ
diff --git a/packages/MediaBrowser.Common.3.3.50-beta/lib/netstandard2.0/MediaBrowser.Common.dll b/packages/MediaBrowser.Common.3.3.53-beta/lib/netstandard2.0/MediaBrowser.Common.dll
similarity index 100%
rename from packages/MediaBrowser.Common.3.3.50-beta/lib/netstandard2.0/MediaBrowser.Common.dll
rename to packages/MediaBrowser.Common.3.3.53-beta/lib/netstandard2.0/MediaBrowser.Common.dll
diff --git a/packages/MediaBrowser.Common.3.3.53-beta/lib/netstandard2.0/MediaBrowser.Model.dll b/packages/MediaBrowser.Common.3.3.53-beta/lib/netstandard2.0/MediaBrowser.Model.dll
new file mode 100644
index 0000000000..dee51c2a21
Binary files /dev/null and b/packages/MediaBrowser.Common.3.3.53-beta/lib/netstandard2.0/MediaBrowser.Model.dll differ
diff --git a/packages/MediaBrowser.Naming.1.1.5-beta/MediaBrowser.Naming.1.1.5-beta.nupkg b/packages/MediaBrowser.Naming.1.1.5-beta/MediaBrowser.Naming.1.1.5-beta.nupkg
deleted file mode 100644
index 8a1cc88bbd..0000000000
Binary files a/packages/MediaBrowser.Naming.1.1.5-beta/MediaBrowser.Naming.1.1.5-beta.nupkg and /dev/null differ
diff --git a/packages/MediaBrowser.Naming.1.1.6-beta/MediaBrowser.Naming.1.1.6-beta.nupkg b/packages/MediaBrowser.Naming.1.1.6-beta/MediaBrowser.Naming.1.1.6-beta.nupkg
new file mode 100644
index 0000000000..69b4a1330b
Binary files /dev/null and b/packages/MediaBrowser.Naming.1.1.6-beta/MediaBrowser.Naming.1.1.6-beta.nupkg differ
diff --git a/packages/MediaBrowser.Naming.1.1.5-beta/lib/netstandard2.0/Emby.Naming.dll b/packages/MediaBrowser.Naming.1.1.6-beta/lib/netstandard2.0/Emby.Naming.dll
similarity index 91%
rename from packages/MediaBrowser.Naming.1.1.5-beta/lib/netstandard2.0/Emby.Naming.dll
rename to packages/MediaBrowser.Naming.1.1.6-beta/lib/netstandard2.0/Emby.Naming.dll
index e8184af4e1..adc3e81e8f 100644
Binary files a/packages/MediaBrowser.Naming.1.1.5-beta/lib/netstandard2.0/Emby.Naming.dll and b/packages/MediaBrowser.Naming.1.1.6-beta/lib/netstandard2.0/Emby.Naming.dll differ
diff --git a/packages/MediaBrowser.Server.Core.3.3.50-beta/MediaBrowser.Server.Core.3.3.50-beta.nupkg b/packages/MediaBrowser.Server.Core.3.3.50-beta/MediaBrowser.Server.Core.3.3.50-beta.nupkg
deleted file mode 100644
index c1a047eeb6..0000000000
Binary files a/packages/MediaBrowser.Server.Core.3.3.50-beta/MediaBrowser.Server.Core.3.3.50-beta.nupkg and /dev/null differ
diff --git a/packages/MediaBrowser.Server.Core.3.3.53-beta/MediaBrowser.Server.Core.3.3.53-beta.nupkg b/packages/MediaBrowser.Server.Core.3.3.53-beta/MediaBrowser.Server.Core.3.3.53-beta.nupkg
new file mode 100644
index 0000000000..9f29e264ab
Binary files /dev/null and b/packages/MediaBrowser.Server.Core.3.3.53-beta/MediaBrowser.Server.Core.3.3.53-beta.nupkg differ
diff --git a/packages/MediaBrowser.Server.Core.3.3.50-beta/lib/netstandard2.0/MediaBrowser.Controller.dll b/packages/MediaBrowser.Server.Core.3.3.53-beta/lib/netstandard2.0/MediaBrowser.Controller.dll
similarity index 94%
rename from packages/MediaBrowser.Server.Core.3.3.50-beta/lib/netstandard2.0/MediaBrowser.Controller.dll
rename to packages/MediaBrowser.Server.Core.3.3.53-beta/lib/netstandard2.0/MediaBrowser.Controller.dll
index 2ef9916d2c..0870eaf0e0 100644
Binary files a/packages/MediaBrowser.Server.Core.3.3.50-beta/lib/netstandard2.0/MediaBrowser.Controller.dll and b/packages/MediaBrowser.Server.Core.3.3.53-beta/lib/netstandard2.0/MediaBrowser.Controller.dll differ
diff --git a/packages/ServiceStack.Text.4.5.8/ServiceStack.Text.4.5.8.nupkg b/packages/ServiceStack.Text.4.5.8/ServiceStack.Text.4.5.8.nupkg
deleted file mode 100644
index 52d85b9c72..0000000000
Binary files a/packages/ServiceStack.Text.4.5.8/ServiceStack.Text.4.5.8.nupkg and /dev/null differ
diff --git a/packages/ServiceStack.Text.4.5.8/lib/net45/ServiceStack.Text.dll b/packages/ServiceStack.Text.4.5.8/lib/net45/ServiceStack.Text.dll
deleted file mode 100644
index b7e1c054b5..0000000000
Binary files a/packages/ServiceStack.Text.4.5.8/lib/net45/ServiceStack.Text.dll and /dev/null differ
diff --git a/packages/ServiceStack.Text.4.5.8/lib/portable-net45+win8+monotouch+monoandroid+xamarin.ios10/ServiceStack.Text.dll b/packages/ServiceStack.Text.4.5.8/lib/portable-net45+win8+monotouch+monoandroid+xamarin.ios10/ServiceStack.Text.dll
deleted file mode 100644
index 74ee9763a8..0000000000
Binary files a/packages/ServiceStack.Text.4.5.8/lib/portable-net45+win8+monotouch+monoandroid+xamarin.ios10/ServiceStack.Text.dll and /dev/null differ
diff --git a/packages/ServiceStack.Text.4.5.8/lib/sl5/ServiceStack.Text.dll b/packages/ServiceStack.Text.4.5.8/lib/sl5/ServiceStack.Text.dll
deleted file mode 100644
index 664ac40ab9..0000000000
Binary files a/packages/ServiceStack.Text.4.5.8/lib/sl5/ServiceStack.Text.dll and /dev/null differ
diff --git a/packages/ServiceStack.Text.4.5.8/lib/sl5/ServiceStack.Text.xml b/packages/ServiceStack.Text.4.5.8/lib/sl5/ServiceStack.Text.xml
deleted file mode 100644
index b4eed5973f..0000000000
--- a/packages/ServiceStack.Text.4.5.8/lib/sl5/ServiceStack.Text.xml
+++ /dev/null
@@ -1,2375 +0,0 @@
-
-
-
- ServiceStack.Text
-
-
-
-
- Utils to load types
-
-
-
-
- Find the type from the name supplied
-
- [typeName] or [typeName, assemblyName]
-
-
-
-
- The top-most interface of the given type, if any.
-
-
-
-
- Find type if it exists
-
-
-
- The type if it exists
-
-
-
- Search key structure for
-
- Type of the key.
- Type of the value.
-
-
-
- A Concurrent implementation.
-
- Type of the keys.
- Type of the values.
-
- This class is threadsafe and highly concurrent. This means that multiple threads can do lookup and insert operations
- on this dictionary simultaneously.
- It is not guaranteed that collisions will not occur. The dictionary is partitioned in segments. A segment contains
- a set of items based on a hash of those items. The more segments there are and the beter the hash, the fewer collisions will occur.
- This means that a nearly empty ConcurrentDictionary is not as concurrent as one containing many items.
-
-
-
-
- Constructs a instance using the default to compare keys.
-
-
-
-
- Constructs a instance using the specified to compare keys.
-
- The tp compare keys with.
- is null.
-
-
-
- Gives the of TKey that is used to compare keys.
-
-
-
-
- Get a hashcode for given storeable item.
-
- Reference to the item to get a hash value for.
- The hash value as an .
-
- The hash returned should be properly randomized hash. The standard GetItemHashCode methods are usually not good enough.
- A storeable item and a matching search key should return the same hash code.
- So the statement ItemEqualsItem(storeableItem, searchKey) ? GetItemHashCode(storeableItem) == GetItemHashCode(searchKey) : true
should always be true;
-
-
-
-
- Get a hashcode for given search key.
-
- Reference to the key to get a hash value for.
- The hash value as an .
-
- The hash returned should be properly randomized hash. The standard GetItemHashCode methods are usually not good enough.
- A storeable item and a matching search key should return the same hash code.
- So the statement ItemEqualsItem(storeableItem, searchKey) ? GetItemHashCode(storeableItem) == GetItemHashCode(searchKey) : true
should always be true;
-
-
-
-
- Compares a storeable item to a search key. Should return true if they match.
-
- Reference to the storeable item to compare.
- Reference to the search key to compare.
- True if the storeable item and search key match; false otherwise.
-
-
-
- Compares two storeable items for equality.
-
- Reference to the first storeable item to compare.
- Reference to the second storeable item to compare.
- True if the two soreable items should be regarded as equal.
-
-
-
- Indicates if a specific item reference contains a valid item.
-
- The storeable item reference to check.
- True if the reference doesn't refer to a valid item; false otherwise.
- The statement IsEmpty(default(TStoredI))
should always be true.
-
-
-
- Adds an element with the provided key and value to the dictionary.
-
- The object to use as the key of the element to add.
- The object to use as the value of the element to add.
- An element with the same key already exists in the dictionary.
-
-
-
- Determines whether the dictionary
- contains an element with the specified key.
-
- The key to locate in the dictionary.
- true if the dictionary contains
- an element with the key; otherwise, false.
-
-
-
- Gets an containing the keys of
- the dictionary.
-
- An containing the keys of the dictionary.
- This property takes a snapshot of the current keys collection of the dictionary at the moment of invocation.
-
-
-
- Removes the element with the specified key from the dictionary.
-
- The key of the element to remove.
- true if the element is successfully removed; otherwise, false. This method
- also returns false if key was not found in the original dictionary.
-
-
-
- Gets the value associated with the specified key.
-
- The key whose value to get.
-
- When this method returns, the value associated with the specified key, if
- the key is found; otherwise, the default value for the type of the value
- parameter. This parameter is passed uninitialized.
-
-
- true if the dictionary contains an element with the specified key; otherwise, false.
-
-
-
-
- Gets an containing the values in
- the dictionary.
-
-
- An containing the values in the dictionary.
-
- This property takes a snapshot of the current keys collection of the dictionary at the moment of invocation.
-
-
-
- Gets or sets the value associated with the specified key.
-
- The key of the value to get or set.
- The value associated with the specified key. If the specified key is not found, a get operation throws a KeyNotFoundException, and a set operation creates a new element with the specified key.
-
- When working with multiple threads, that can each potentialy remove the searched for item, a can always be expected.
-
-
-
-
- Adds an association to the dictionary.
-
- A that represents the association to add.
- An association with an equal key already exists in the dicitonary.
-
-
-
- Removes all items from the dictionary.
-
- WHen working with multiple threads, that each can add items to this dictionary, it is not guaranteed that the dictionary will be empty when this method returns.
-
-
-
- Determines whether the specified association exists in the dictionary.
-
- The key-value association to search fo in the dicionary.
- True if item is found in the dictionary; otherwise, false.
-
- This method compares both key and value. It uses the default equality comparer to compare values.
-
-
-
-
- Copies all associations of the dictionary to an
- , starting at a particular index.
-
- The one-dimensional that is the destination of the associations
- copied from . The must
- have zero-based indexing.
- The zero-based index in at which copying begins.
- is null.
- is less than 0.
- is equal to or greater than the length of .
- The number of associations to be copied
- is greater than the available space from to the end of the destination
- .
-
-
-
- Gets the number of elements contained in the .
-
-
-
-
- Gets a value indicating whether the is read-only, which is always false.
-
-
-
-
- Removes the specified association from the , comparing both key and value.
-
- A representing the association to remove.
- true if the association was successfully removed from the ;
- otherwise, false. This method also returns false if the association is not found in
- the original .
-
-
-
-
- Returns an enumerator that iterates through all associations in the at the moment of invocation.
-
- A that can be used to iterate through the associations.
-
-
-
- Returns an enumerator that iterates through all associations in the at the moment of invocation.
-
- A that can be used to iterate through the associations.
-
-
-
- Base class for concurrent hashtable implementations
-
- Type of the items stored in the hashtable.
- Type of the key to search with.
-
-
-
- Constructor (protected)
-
- Use Initialize method after construction.
-
-
-
- Initialize the newly created ConcurrentHashtable. Invoke in final (sealed) constructor
- or Create method.
-
-
-
-
- Create a segment range
-
- Number of segments in range.
- Number of slots allocated initialy in each segment.
- The created instance.
-
-
-
- While adjusting the segmentation, _NewRange will hold a reference to the new range of segments.
- when the adjustment is complete this reference will be copied to _CurrentRange.
-
-
-
-
- Will hold the most current reange of segments. When busy adjusting the segmentation, this
- field will hold a reference to the old range.
-
-
-
-
- While adjusting the segmentation this field will hold a boundary.
- Clients accessing items with a key hash value below this boundary (unsigned compared)
- will access _NewRange. The others will access _CurrentRange
-
-
-
-
- Get a hashcode for given storeable item.
-
- Reference to the item to get a hash value for.
- The hash value as an .
-
- The hash returned should be properly randomized hash. The standard GetItemHashCode methods are usually not good enough.
- A storeable item and a matching search key should return the same hash code.
- So the statement ItemEqualsItem(storeableItem, searchKey) ? GetItemHashCode(storeableItem) == GetItemHashCode(searchKey) : true
should always be true;
-
-
-
-
- Get a hashcode for given search key.
-
- Reference to the key to get a hash value for.
- The hash value as an .
-
- The hash returned should be properly randomized hash. The standard GetItemHashCode methods are usually not good enough.
- A storeable item and a matching search key should return the same hash code.
- So the statement ItemEqualsItem(storeableItem, searchKey) ? GetItemHashCode(storeableItem) == GetItemHashCode(searchKey) : true
should always be true;
-
-
-
-
- Compares a storeable item to a search key. Should return true if they match.
-
- Reference to the storeable item to compare.
- Reference to the search key to compare.
- True if the storeable item and search key match; false otherwise.
-
-
-
- Compares two storeable items for equality.
-
- Reference to the first storeable item to compare.
- Reference to the second storeable item to compare.
- True if the two soreable items should be regarded as equal.
-
-
-
- Indicates if a specific item reference contains a valid item.
-
- The storeable item reference to check.
- True if the reference doesn't refer to a valid item; false otherwise.
- The statement IsEmpty(default(TStoredI))
should always be true.
-
-
-
- Returns the type of the key value or object.
-
- The stored item to get the type of the key for.
- The actual type of the key or null if it can not be determined.
-
- Used for diagnostics purposes.
-
-
-
-
- Returns an object that serves as a lock for range operations
-
-
- Clients use this primarily for enumerating over the Tables contents.
- Locking doesn't guarantee that the contents don't change, but prevents operations that would
- disrupt the enumeration process.
- Operations that use this lock:
- Count, Clear, DisposeGarbage and AssessSegmentation.
- Keeping this lock will prevent the table from re-segmenting.
-
-
-
-
- Gets a segment out of either _NewRange or _CurrentRange based on the hash value.
-
-
-
-
-
-
- Gets a LOCKED segment out of either _NewRange or _CurrentRange based on the hash value.
- Unlock needs to be called on this segment before it can be used by other clients.
-
-
-
-
-
-
- Gets a LOCKED segment out of either _NewRange or _CurrentRange based on the hash value.
- Unlock needs to be called on this segment before it can be used by other clients.
-
-
-
-
-
-
- Finds an item in the table collection that maches the given searchKey
-
- The key to the item.
- Out reference to a field that will receive the found item.
- A boolean that will be true if an item has been found and false otherwise.
-
-
-
- Looks for an existing item in the table contents using an alternative copy. If it can be found it will be returned.
- If not then the alternative copy will be added to the table contents and the alternative copy will be returned.
-
- A copy to search an already existing instance with
- Out reference to receive the found item or the alternative copy
- A boolean that will be true if an existing copy was found and false otherwise.
-
-
-
- Replaces and existing item
-
-
-
-
- true is the existing item was successfully replaced.
-
-
-
- Inserts an item in the table contents possibly replacing an existing item.
-
- The item to insert in the table
- Out reference to a field that will receive any possibly replaced item.
- A boolean that will be true if an existing copy was found and replaced and false otherwise.
-
-
-
- Removes an item from the table contents.
-
- The key to find the item with.
- Out reference to a field that will receive the found and removed item.
- A boolean that will be rue if an item was found and removed and false otherwise.
-
-
-
- Enumerates all segments in _CurrentRange and locking them before yielding them and resleasing the lock afterwards
- The order in which the segments are returned is undefined.
- Lock SyncRoot before using this enumerable.
-
-
-
-
-
- Gets an IEnumerable to iterate over all items in all segments.
-
-
-
- A lock should be aquired and held on SyncRoot while this IEnumerable is being used.
- The order in which the items are returned is undetermined.
-
-
-
-
- Removes all items from the collection.
- Aquires a lock on SyncRoot before it does it's thing.
- When this method returns and multiple threads have access to this table it
- is not guaranteed that the table is actually empty.
-
-
-
-
- Returns a count of all items in teh collection. This may not be
- aqurate when multiple threads are accessing this table.
- Aquires a lock on SyncRoot before it does it's thing.
-
-
-
-
- Gives the minimum number of segments a hashtable can contain. This should be 1 or more and always a power of 2.
-
-
-
-
- Gives the minimum number of allocated item slots per segment. This should be 1 or more, always a power of 2
- and less than 1/2 of MeanSegmentAllocatedSpace.
-
-
-
-
- Gives the prefered number of allocated item slots per segment. This should be 4 or more and always a power of 2.
-
-
-
-
- Determines if a segmentation adjustment is needed.
-
- True
-
-
-
- Bool as int (for interlocked functions) that is true if a Segmentation assesment is pending.
-
-
-
-
- The total allocated number of item slots. Filled with nonempty items or not.
-
-
-
-
- When a segment resizes it uses this method to inform the hashtable of the change in allocated space.
-
-
-
-
-
- Schedule a call to the AssessSegmentation() method.
-
-
-
-
- Checks if segmentation needs to be adjusted and if so performs the adjustment.
-
-
-
-
-
- This method is called when a re-segmentation is expected to be needed. It checks if it actually is needed and, if so, performs the re-segementation.
-
-
-
-
- Adjusts the segmentation to the new segment count
-
- The new number of segments to use. This must be a power of 2.
- The number of item slots to reserve in each segment.
-
-
-
- Initialize the segment.
-
-
-
-
-
- When segment gets introduced into hashtable then its allocated space should be added to the
- total allocated space.
- Single threaded access or locking is needed
-
-
-
-
-
- When segment gets removed from hashtable then its allocated space should be subtracted to the
- total allocated space.
- Single threaded access or locking is needed
-
-
-
-
-
- Array with 'slots'. Each slot can be filled or empty.
-
-
-
-
- Boolean value indicating if this segment has not been trashed yet.
-
-
-
-
- Inserts an item into a *not empty* spot given by position i. It moves items forward until an empty spot is found.
-
-
-
-
-
-
-
-
- Find item in segment.
-
- Reference to the search key to use.
- Out reference to store the found item in.
- Object that tells this segment how to treat items and keys.
- True if an item could be found, otherwise false.
-
-
-
- Find an existing item or, if it can't be found, insert a new item.
-
- Reference to the item that will be inserted if an existing item can't be found. It will also be used to search with.
- Out reference to store the found item or, if it can not be found, the new inserted item.
- Object that tells this segment how to treat items and keys.
- True if an existing item could be found, otherwise false.
-
-
-
- Inserts an item in the segment, possibly replacing an equal existing item.
-
- A reference to the item to insert.
- An out reference where any replaced item will be written to, if no item was replaced the new item will be written to this reference.
- Object that tells this segment how to treat items and keys.
- True if an existing item could be found and is replaced, otherwise false.
-
-
-
- Removes an item from the segment.
-
- A reference to the key to search with.
- An out reference where the removed item will be stored or default( ) if no item to remove can be found.
- Object that tells this segment how to treat items and keys.
- True if an item could be found and is removed, false otherwise.
-
-
-
- Iterate over items in the segment.
-
- Position beyond which the next filled slot will be found and the item in that slot returned. (Starting with -1)
- Out reference where the next item will be stored or default if the end of the segment is reached.
- Object that tells this segment how to treat items and keys.
- The index position the next item has been found or -1 otherwise.
-
-
-
- Total numer of filled slots in _List.
-
-
-
-
- Remove any excess allocated space
-
-
-
-
-
- Release a reader lock
-
-
-
-
- Release a writer lock
-
-
-
-
- Aquire a reader lock. Wait until lock is aquired.
-
-
-
-
- Aquire a reader lock.
-
- True if to wait until lock aquired, False to return immediately.
- Boolean indicating if lock was successfuly aquired.
-
-
-
- Aquire a writer lock. Wait until lock is aquired.
-
-
-
-
- Aquire a writer lock.
-
- True if to wait until lock aquired, False to return immediately.
- Boolean indicating if lock was successfuly aquired.
-
-
-
- If AlwaysUseUtc is set to true then convert all DateTime to UTC. If PreserveUtc is set to true then UTC dates will not convert to local
-
-
-
-
-
-
- Repairs an out-of-spec XML date/time string which incorrectly uses a space instead of a 'T' to separate the date from the time.
- These string are occasionally generated by SQLite and can cause errors in OrmLite when reading these columns from the DB.
-
- The XML date/time string to repair
- The repaired string. If no repairs were made, the original string is returned.
-
-
-
- WCF Json format: /Date(unixts+0000)/
-
-
-
-
-
-
- WCF Json format: /Date(unixts+0000)/
-
-
-
-
-
-
- Get the type(string) constructor if exists
-
- The type.
-
-
-
-
- micro optimizations: using flags instead of value.IndexOfAny(EscapeChars)
-
-
-
-
-
-
- Class to hold
-
-
-
-
-
- A fast, standards-based, serialization-issue free DateTime serailizer.
-
-
-
-
- Determines whether this serializer can create the specified type from a string.
-
- The type.
-
- true if this instance [can create from string] the specified type; otherwise, false .
-
-
-
-
- Parses the specified value.
-
- The value.
-
-
-
-
- Deserializes from reader.
-
- The reader.
-
-
-
-
- Serializes to string.
-
- The value.
-
-
-
-
- Serializes to writer.
-
- The value.
- The writer.
-
-
-
- Sets which format to use when serializing TimeSpans
-
-
-
-
- if the is configured
- to take advantage of specification,
- to support user-friendly serialized formats, ie emitting camelCasing for JSON
- and parsing member names and enum values in a case-insensitive manner.
-
-
-
-
- if the is configured
- to support web-friendly serialized formats, ie emitting lowercase_underscore_casing for JSON
-
-
-
-
- Define how property names are mapped during deserialization
-
-
-
-
- Gets or sets a value indicating if the framework should throw serialization exceptions
- or continue regardless of deserialization errors. If the framework
- will throw; otherwise, it will parse as many fields as possible. The default is .
-
-
-
-
- Gets or sets a value indicating if the framework should always convert to UTC format instead of local time.
-
-
-
-
- Gets or sets a value indicating if the framework should skip automatic conversions.
- Dates will be handled literally, any included timezone encoding will be lost and the date will be treaded as DateTimeKind.Local
- Utc formatted input will result in DateTimeKind.Utc output. Any input without TZ data will be set DateTimeKind.Unspecified
- This will take precedence over other flags like AlwaysUseUtc
- JsConfig.DateHandler = DateHandler.ISO8601 should be used when set true for consistent de/serialization.
-
-
-
-
- Gets or sets a value indicating if the framework should always assume is in UTC format if Kind is Unspecified.
-
-
-
-
- Gets or sets whether we should append the Utc offset when we serialize Utc dates. Defaults to no.
- Only supported for when the JsConfig.DateHandler == JsonDateHandler.TimestampOffset
-
-
-
-
- Gets or sets a value indicating if unicode symbols should be serialized as "\uXXXX".
-
-
-
-
- Gets or sets a value indicating if HTML entity chars [> < & = '] should be escaped as "\uXXXX".
-
-
-
-
- Gets or sets a value indicating if the framework should call an error handler when
- an exception happens during the deserialization.
-
- Parameters have following meaning in order: deserialized entity, property name, parsed value, property type, caught exception.
-
-
-
- If set to true, Interface types will be prefered over concrete types when serializing.
-
-
-
-
- If set to true, Interface types will be prefered over concrete types when serializing.
-
-
-
-
- Sets the maximum depth to avoid circular dependencies
-
-
-
-
- Set this to enable your own type construction provider.
- This is helpful for integration with IoC containers where you need to call the container constructor.
- Return null if you don't know how to construct the type and the parameterless constructor will be used.
-
-
-
-
- Always emit type info for this type. Takes precedence over ExcludeTypeInfo
-
-
-
-
- Never emit type info for this type
-
-
-
-
- if the is configured
- to take advantage of specification,
- to support user-friendly serialized formats, ie emitting camelCasing for JSON
- and parsing member names and enum values in a case-insensitive manner.
-
-
-
-
- Define custom serialization fn for BCL Structs
-
-
-
-
- Opt-in flag to set some Value Types to be treated as a Ref Type
-
-
-
-
- Whether there is a fn (raw or otherwise)
-
-
-
-
- Define custom raw serialization fn
-
-
-
-
- Define custom serialization hook
-
-
-
-
- Define custom after serialization hook
-
-
-
-
- Define custom deserialization fn for BCL Structs
-
-
-
-
- Define custom raw deserialization fn for objects
-
-
-
-
- Exclude specific properties of this type from being serialized
-
-
-
-
- The property names on target types must match property names in the JSON source
-
-
-
-
- The property names on target types may not match the property names in the JSON source
-
-
-
-
- Uses the xsd format like PT15H10M20S
-
-
-
-
- Uses the standard .net ToString method of the TimeSpan class
-
-
-
-
- Get JSON string value converted to T
-
-
-
-
- Get JSON string value
-
-
-
-
- Get JSON string value
-
-
-
-
- Get unescaped string value
-
-
-
-
- Get unescaped string value
-
-
-
-
- Write JSON Array, Object, bool or number values as raw string
-
-
-
-
- Creates an instance of a Type from a string value
-
-
-
-
- Parses the specified value.
-
- The value.
-
-
-
-
- Shortcut escape when we're sure value doesn't contain any escaped chars
-
-
-
-
-
-
- Given a character as utf32, returns the equivalent string provided that the character
- is legal json.
-
-
-
-
-
-
- Micro-optimization keep pre-built char arrays saving a .ToCharArray() + function call (see .net implementation of .Write(string))
-
-
-
-
- Searches the string for one or more non-printable characters.
-
- The string to search.
-
- True if there are any characters that require escaping. False if the value can be written verbatim.
-
- Micro optimizations: since quote and backslash are the only printable characters requiring escaping, removed previous optimization
- (using flags instead of value.IndexOfAny(EscapeChars)) in favor of two equality operations saving both memory and CPU time.
- Also slightly reduced code size by re-arranging conditions.
- TODO: Possible Linq-only solution requires profiling: return value.Any(c => !c.IsPrintable() || c == QuoteChar || c == EscapeChar);
-
-
-
-
- Implement the serializer using a more static approach
-
-
-
-
-
- Implement the serializer using a more static approach
-
-
-
-
-
- Pretty Thread-Safe cache class from:
- http://code.google.com/p/dapper-dot-net/source/browse/Dapper/SqlMapper.cs
-
- This is a micro-cache; suitable when the number of terms is controllable (a few hundred, for example),
- and strictly append-only; you cannot change existing values. All key matches are on **REFERENCE**
- equality. The type is fully thread-safe.
-
-
-
-
- Generic implementation of object pooling pattern with predefined pool size limit. The main
- purpose is that limited number of frequently used objects can be kept in the pool for
- further recycling.
-
- Notes:
- 1) it is not the goal to keep all returned objects. Pool is not meant for storage. If there
- is no space in the pool, extra returned objects will be dropped.
-
- 2) it is implied that if object was obtained from a pool, the caller will return it back in
- a relatively short time. Keeping checked out objects for long durations is ok, but
- reduces usefulness of pooling. Just new up your own.
-
- Not returning objects to the pool in not detrimental to the pool's work, but is a bad practice.
- Rationale:
- If there is no intent for reusing the object, do not use pool - just use "new".
-
-
-
-
- Not using System.Func{T} because this file is linked into the (debugger) Formatter,
- which does not have that type (since it compiles against .NET 2.0).
-
-
-
-
- Produces an instance.
-
-
- Search strategy is a simple linear probing which is chosen for it cache-friendliness.
- Note that Free will try to store recycled objects close to the start thus statistically
- reducing how far we will typically search.
-
-
-
-
- Returns objects to the pool.
-
-
- Search strategy is a simple linear probing which is chosen for it cache-friendliness.
- Note that Free will try to store recycled objects close to the start thus statistically
- reducing how far we will typically search in Allocate.
-
-
-
-
- Removes an object from leak tracking.
-
- This is called when an object is returned to the pool. It may also be explicitly
- called if an object allocated from the pool is intentionally not being returned
- to the pool. This can be of use with pooled arrays if the consumer wants to
- return a larger array to the pool than was originally allocated.
-
-
-
-
- this is RAII object to automatically release pooled object when its owning pool
-
-
-
-
- Shared object pool for roslyn
-
- Use this shared pool if only concern is reducing object allocations.
- if perf of an object pool itself is also a concern, use ObjectPool directly.
-
- For example, if you want to create a million of small objects within a second,
- use the ObjectPool directly. it should have much less overhead than using this.
-
-
-
-
- pool that uses default constructor with 100 elements pooled
-
-
-
-
- pool that uses default constructor with 20 elements pooled
-
-
-
-
- pool that uses string as key with StringComparer.OrdinalIgnoreCase as key comparer
-
-
-
-
- pool that uses string as element with StringComparer.OrdinalIgnoreCase as element comparer
-
-
-
-
- pool that uses string as element with StringComparer.Ordinal as element comparer
-
-
-
-
- Used to reduce the # of temporary byte[]s created to satisfy serialization and
- other I/O requests
-
-
-
- pooled memory : 4K * 512 = 4MB
-
-
-
- Reusable StringBuilder ThreadStatic Cache
-
-
-
-
- Alternative Reusable StringBuilder ThreadStatic Cache
-
-
-
-
- Reusable StringWriter ThreadStatic Cache
-
-
-
-
- Alternative Reusable StringWriter ThreadStatic Cache
-
-
-
-
- A class to allow the conversion of doubles to string representations of
- their exact decimal values. The implementation aims for readability over
- efficiency.
-
- Courtesy of @JonSkeet
- http://www.yoda.arachsys.com/csharp/DoubleConverter.cs
-
-
-
-
-
-
-
- How many digits are *after* the decimal point
-
-
-
-
- Constructs an arbitrary decimal expansion from the given long.
- The long must not be negative.
-
-
-
-
- Multiplies the current expansion by the given amount, which should
- only be 2 or 5.
-
-
-
-
- Shifts the decimal point; a negative value makes
- the decimal expansion bigger (as fewer digits come after the
- decimal place) and a positive value makes the decimal
- expansion smaller.
-
-
-
-
- Removes leading/trailing zeroes from the expansion.
-
-
-
-
- Converts the value to a proper decimal string representation.
-
-
-
-
- Creates an instance of a Type from a string value
-
-
-
-
- Determines whether the specified type is convertible from string.
-
- The type.
-
- true if the specified type is convertible from string; otherwise, false .
-
-
-
-
- Parses the specified value.
-
- The value.
-
-
-
-
- Parses the specified type.
-
- The type.
- The value.
-
-
-
-
- Useful extension method to get the Dictionary[string,string] representation of any POCO type.
-
-
-
-
-
- Recursively prints the contents of any POCO object in a human-friendly, readable format
-
-
-
-
-
- Print Dump to Console.WriteLine
-
-
-
-
- Print string.Format to Console.WriteLine
-
-
-
-
- Parses the specified value.
-
- The value.
-
-
-
-
- Populate an object with Example data.
-
-
-
-
-
-
- Populates the object with example data.
-
-
- Tracks how deeply nested we are
-
-
-
-
- Add a Property attribute at runtime.
- Not threadsafe, should only add attributes on Startup.
-
-
-
-
- Add a Property attribute at runtime.
- Not threadsafe, should only add attributes on Startup.
-
-
-
-
- Public Code API to register commercial license for ServiceStack.
-
-
-
-
- Internal Utilities to verify licensing
-
-
-
-
- Maps the path of a file in the context of a VS project in a Consle App
-
- the relative path
- the absolute path
- Assumes static content is two directories above the /bin/ directory,
- eg. in a unit test scenario the assembly would be in /bin/Debug/.
-
-
-
- Maps the path of a file in the bin\ folder of a self-hosted scenario
-
- the relative path
- the absolute path
- Assumes static content is copied to /bin/ folder with the assemblies
-
-
-
- Maps the path of a file in an ASP.NET hosted scenario
-
- the relative path
- the absolute path
- Assumes static content is in the parent folder of the /bin/ directory
-
-
-
- Implement the serializer using a more static approach
-
-
-
-
-
- Creates a new instance of type.
- First looks at JsConfig.ModelFactory before falling back to CreateInstance
-
-
-
-
- Creates a new instance of type.
- First looks at JsConfig.ModelFactory before falling back to CreateInstance
-
-
-
-
- Creates a new instance from the default constructor of type
-
-
-
-
- BigInteger library by Chew Keong TAN (See project source for info).
-
-
-
-
- Interface which must be implemented by all custom padding providers.
- Padding is used to provide randomness and unpredictability to the data
- before it is encrypted.
-
-
-
-
- Adds padding to the input data and returns the padded data.
-
- Data to be padded prior to encryption
- RSA Parameters used for padding computation
- Padded message
-
-
-
- Removes padding that was added to the unencrypted data prior to encryption.
-
- Data to have padding removed
- RSA Parameters used for padding computation
- Unpadded message
-
-
-
- Gets the maximum message length for this padding provider.
-
- RSA Parameters used for padding computation
- Max message length
-
-
-
- Uses PKCS#1 v 1.5 padding scheme to pad the data.
-
-
-
-
-
- Default constructor.
-
-
-
-
- Adds padding to the input data and returns the padded data.
-
- Data to be padded prior to encryption
- RSA Parameters used for padding computation
- Padded message
-
-
-
- Removes padding that was added to the unencrypted data prior to encryption.
-
- Data to have padding removed
- RSA Parameters used for padding computation
- Unpadded message
-
-
-
- Gets the maximum message length for this padding provider.
-
- RSA Parameters used for padding computation
- Max message length
-
-
-
- The NoPadding class does not add any padding to the data.
- This is not recommended.
-
-
-
-
- Default constructor.
-
-
-
-
- Adds padding to the input data and returns the padded data.
-
- Data to be padded prior to encryption
- RSA Parameters used for padding computation
- Padded message
-
-
-
- Removes padding that was added to the unencrypted data prior to encryption.
-
- Data to have padding removed
- RSA Parameters used for padding computation
- Unpadded message
-
-
-
- Gets the maximum message length for this padding provider.
-
- RSA Parameters used for padding computation
- Max message length
-
-
-
- Uses OAEP Padding defined in PKCS#1 v 2.1. Uses the
- default standard SHA1 hash. This padding provider is
- compatible with .NET's OAEP implementation.
-
-
-
-
- Default constructor. Uses the default SHA1 Hash for OAEP hash calculation.
-
-
-
-
- Internal constructor (used to perform OAEP with a different hash and hash output length
-
-
-
-
-
-
- Adds padding to the input data and returns the padded data.
-
- Data to be padded prior to encryption
- RSA Parameters used for padding computation
- Padded message
-
-
-
- Removes padding that was added to the unencrypted data prior to encryption.
-
- Data to have padding removed
- RSA Parameters used for padding computation
- Unpadded message
-
-
-
- Gets the maximum message length for this padding provider.
-
- RSA Parameters used for padding computation
- Max message length
-
-
-
- Uses OAEP Padding Scheme defined in PKCS#1 v 2.1. Uses a
- SHA256 hash. This padding provider is currently
- not compatible with .NET's OAEP implementation.
-
-
-
-
- Default constructor. Uses a SHA256 Hash for OAEP hash calculation.
- This PaddingProvider provides added security to message padding,
- however it requires the data to be encrypted to be shorter and
- is not compatible with the RSACryptoServiceProvider's implementation
- of OAEP.
-
-
-
-
- Adds padding to the input data and returns the padded data.
-
- Data to be padded prior to encryption
- RSA Parameters used for padding computation
- Padded message
-
-
-
- Removes padding that was added to the unencrypted data prior to encryption.
-
- Data to have padding removed
- RSA Parameters used for padding computation
- Unpadded message
-
-
-
- Gets the maximum message length for this padding provider.
-
- RSA Parameters used for padding computation
- Max message length
-
-
-
- All custom signature providers must implement this interface. The
- RSACrypto class handles encryption and decryption of data. The
- SignatureProvider is intended to provide the hashing and signature
- generation mechanism used to create the comparison data.
-
-
-
-
- Generates a hash for the input data.
-
- Data to be signed
- RSA Parameters used for signature calculation
- Computed signature (pre-encryption)
-
-
-
- Verifies the signed data against the unsigned data after decryption.
-
- Unsigned data
- Signed data (after decryption)
- RSAParameters used for signature computation
- Boolean representing whether the input data matches the signed data
-
-
-
- Uses the DER (Distinguished Encoding Rules)
- and the SHA1 hash provider for encoding generation.
-
-
-
-
- Default constructor
-
-
-
-
- Hashes and encodes the signature for encryption. Uses the DER (Distinguished Encoding Rules)
- and the SHA1 hash provider for encoding generation.
-
- Data to be signed
- RSA Parameters used for signature calculation
- Computed signature (pre-encryption)
-
-
-
- Verifies the signed data against the unsigned data after decryption.
-
- Unsigned data
- Signed data (after decryption)
- RSAParameters used for signature computation
- Boolean representing whether the input data matches the signed data
-
-
-
- Uses the DER (Distinguished Encoding Rules)
- and the SHA256 hash provider for encoding generation.
-
-
-
-
- Default constructor
-
-
-
-
- Hashes and encodes the signature for encryption. Uses the DER (Distinguished Encoding Rules)
- and the SHA256 hash provider for encoding generation.
-
- Data to be signed
- RSA Parameters used for signature calculation
- Computed signature (pre-encryption)
-
-
-
- Verifies the signed data against the unsigned data after decryption.
-
- Unsigned data
- Signed data (after decryption)
- RSAParameters used for signature computation
- Boolean representing whether the input data matches the signed data
-
-
-
- Base interface that must be implemented by all hash providers.
-
-
-
-
- Compute the hash of the input byte array and return the hashed value as a byte array.
-
- Input data
- Hashed data.
-
-
-
- Hash provider based on SHA256
-
-
-
-
- Default constructor.
-
-
-
-
- Compute the hash of the input byte array and return the hashed value as a byte array.
-
- Input data
- SHA256 Hashed data
-
-
-
- Hash provider based on HMACSHA256 to allow inclusion of a hash seed value
-
-
-
-
- Constructor accepting a private key (seed) value
-
- Byte array containing the private hash seed
-
-
-
- Compute the hash of the input byte array and return the hashed value as a byte array.
-
- Input data
- HMACSHA256 Hashed data.
-
-
-
- Hash provider based on SHA1
-
-
-
-
- Default constructor.
-
-
-
-
- Compute the hash of the input byte array and return the hashed value as a byte array.
-
- Input data
- SHA1 Hashed data.
-
-
-
- Hash provider based on HMACSHA1 to allow inclusion of a hash seed value
-
-
-
-
- Constructor accepting a private key (seed) value
-
- Byte array containing the private hash seed
-
-
-
- Compute the hash of the input byte array and return the hashed value as a byte array.
-
- Input data
- HMACSHA1 Hashed data.
-
-
-
- RSA Cryptography class
-
-
-
-
- Different versions of RSA use different padding schemes. This property allows you to
- set the padding scheme you wish to use. If not set, the default of OAEP will be
- used. While PKCS1 v1.5 is supported, OAEP is the recommended padding scheme to use.
- You can create your own padding schemes by implementing the IPaddingProvider interface.
-
- Padding provider instance
- Current padding provider
-
-
-
- Based on the padding provider, messages are stricted to certain lengths for encryption. Also,
- ensure that the key pair has either been generated or imported.
-
-
-
-
- Default constructor for the RSA Class. A cipher strength of 1024-bit will used by default. To specify
- a higher cipher strength, please use the alternate RSACrypto(cipherStrength) constructor.
-
-
-
-
- RSA Class Constructor
-
-
- Cipher strength in bits. 2048 is recommended. Must be a multiple of 8.
- Max supported by this class is 4096. Minimum is 256. Cipher strength only
- needs to be specified if generating new key pairs. It is not necessary to
- know the cipher strength when importing existing key pairs.
-
-
-
-
- Return the currently loaded key as XML. This method will automatically
- return an empty string if no key has been loaded.
-
- Signals whether to include the private key in the output data.
- XML String with the key data.
-
-
-
- Sets the current class internal variables based on the supplied XML.
- Attempts to validate the XML prior to setting.
-
- XML String containing key info
-
-
-
-
- Import an existing set of RSA Parameters. If only the public key is to be loaded,
- Do not set the P, Q, DP, DQ, IQ or D values. If P, Q or D are set, the parameters
- will automatically be validated for existence of private key.
-
- RSAParameters object containing key data.
-
-
-
- Returns an RSAParameters object that contains the key data for the currently loaded key.
-
- Instance of the currently loaded RSAParameters object or null if no key is loaded
-
-
-
-
- Imports a blob that represents asymmetric key information.
-
- A byte array that represents an asymmetric key blob.
- Invalid key blob data
- Initialized RSAParameters structure
-
-
-
- Exports a blob that contains the key information associated with an AsymmetricAlgorithm object.
-
- true to include the private key; otherwise, false.
- A byte array that contains the key information associated with an AsymmetricAlgorithm object
-
-
-
- Generate the RSA Key Pair using the default exponent of 65537.
-
-
-
-
- Generate the RSA Key Pair using a supplied cipher strength and the default
- exponent value of 65537. If a cipherStrength was specified in the constructor,
- the supplied value will override it.
-
- The strength of the cipher in bits. Must be a multiple of 8
- and between 256 and 4096
-
-
-
- Generate the RSA Key Pair using a supplied cipher strength value and exponent value.
- A prime number value between 3 and 65537 is recommended for the exponent. Larger
- exponents can increase security but also increase encryption time. Your supplied
- exponent may be automatically adjusted to ensure compatibility with the RSA algorithm
- security requirements. If a cipherStrength was specified in the constructor,
- the supplied value will override it.
-
- The strength of the cipher in bits. Must be a multiple of 8
- and between 256 and 4096
- Custom exponent value to be used for RSA Calculation
-
-
-
- Delegate for OnKeysGenerated event
-
- Object
-
-
-
- Fires when key generation is complete.
-
-
-
-
- Encrypt input bytes with the public key. Data can only be decrypted with
- the private key. If no PaddingProvider is set, the default padding provider of OAEP will be assumed. To
- specify a different padding algorithm, make sure you set the PaddingProvider property.
-
- Data bytes to be encrypted
- Encrypted byte array
- Key generation is CPU intensive. It is highly recommended that you create
- your key pair in advance and use a predetermined key pair. If you do choose to allow
- the key pair to be automatically generated, it can be exported to XML or an RSAParameter
- set after the encryption is complete.
-
-
-
- Run the encryption routine using the private key for encryption. While this may be useful in some
- fringe scenarios, if simple verification is needed it is recommended that you use the Sign() method
- instead, which signs a hashed version of your data. If no PaddingProvider is set, the default padding
- provider of OAEP will be assumed. To specify a different padding algorithm, make sure you set the
- PaddingProvider property.
-
- Data to be encrypted with the private key
- Encrypted data bytes
-
- This method uses the PaddingProvider for message verification. To create signature
- hashes, please use the SignData and VerifyData methods.
- Data encrypted this way can be decrypted using your PUBLIC KEY. This method of encryption is meant
- for verification purposes only and does not secure your data against decryption.
-
-
-
-
- Sign a hash of the input data using the supplied Signature Provider and encrypt with the private key.
-
- Data to be hashed and signed
- The signature provider to use for signature generation.
- Signed hash bytes
-
-
-
- Decrypt data that was encrypted using the Public Key. If no PaddingProvider is set, the default
- padding provider of OAEP will be assumed. To specify a different padding algorithm, make sure
- you set the PaddingProvider property.
-
- Encrypted bytes
- Decrypted bytes
-
-
-
- Decrypt data that was encrypted with the Private Key. NOTE: This method
- uses the PaddingProvider for message decoding. To create signature
- hashes, please use the SignData and VerifyData methods. If no PaddingProvider is set, the default
- padding provider of OAEP will be assumed. To specify a different padding algorithm, make sure
- you set the PaddingProvider property.
-
- Encrypted bytes
- Decrypted bytes
-
-
-
- Verify the signature against the unsigned data. The encryptedData is decrypted using the public key and
- the unsignedData is hashed and compared to the un-encrypted signed data using the supplied SignatureProvider.
-
- The raw, unencrypted data to be hashed and compared.
- The data that has been hashed and encrypted with the private key.
- The signature provider that matches the algorithm used to generate the original signature
- Boolean representing whether the signature was valid (verified)
-
-
-
- Cryptographic Exception
-
-
-
-
- Constructor
-
- Error Message
-
-
-
- Constructor
-
- Error Message
- Inner Exception
-
-
-
- CALG_RSA_KEYX = (ALG_CLASS_KEY_EXCHANGE|ALG_TYPE_RSA|ALG_SID_RSA_ANY)
-
-
-
-
- Simple Key BLOB
-
-
-
-
- Public Key BLOB
-
-
-
-
- Private Key BLOB
-
-
-
-
- PlainText Key BLOB
-
-
-
-
- Opaque Key BLOB
-
-
-
-
- Public Key BLOB Extended
-
-
-
-
- Symmetric Wrap Key BLOB
-
-
-
-
- A BLOBHEADER / PUBLICKEYSTRUC structure (Import from WinCrypt.h)
-
- http://msdn.microsoft.com/en-us/library/ms884652.aspx
-
-
-
- Key BLOB type. The only BLOB types currently defined are PUBLICKEYBLOB, PRIVATEKEYBLOB, and SIMPLEBLOB. Other key BLOB types will be defined as needed.
-
-
-
-
- Version number of the key BLOB format. This member currently must always have a value of 0x02.
-
-
-
-
- Reserved for future use. This member must be set to zero.
-
-
-
-
- Algorithm identifier for the key contained by the key BLOB structure
-
-
-
-
- Create and initialize structure from binary data
-
- On validate errors
- Initialized structure
-
-
-
- Serializes structure as binary data
-
-
-
-
- Create and initialize structure from RSAParameters
-
- Initialized structure
-
-
-
- Returns a that represents this instance.
-
-
- A that represents this instance.
-
-
-
-
- RSA public key data
-
- http://msdn.microsoft.com/en-us/library/aa387685(v=VS.85).aspx
-
-
-
- The magic member must be set to 0x31415352 (public only) / 0x32415352 (including private). This hex value is the ASCII encoding of RSA1 / RSA2.
-
-
-
-
- # of bits in modulus
-
-
-
-
- Public exponent
-
-
-
-
- Create and initialize structure from binary data
-
- On validate errors
- Initialized structure
-
-
-
- Serializes structure as binary data
-
-
-
-
- Create and initialize structure from RSAParameters
-
- Initialized structure
-
-
-
- Create and initialize RSAParameters structure
-
- Initialized structure
- http://msdn.microsoft.com/en-us/library/system.security.cryptography.rsaparameters.aspx
-
-
-
- Returns a that represents this instance.
-
-
- A that represents this instance.
-
-
-
-
- Private-key BLOBs, type PRIVATEKEYBLOB, are used to store private keys outside a CSP. Extended provider private-key BLOBs have the following format.
-
-
-
-
- BLOB Header
-
-
-
-
- RSA public key data
-
-
-
-
- The modulus. This has a value of prime1 * prime2 and is often known as n.
-
-
-
-
- Prime number 1, often known as p.
-
-
-
-
- Prime number 2, often known as q.
-
-
-
-
- Exponent 1. This has a numeric value of d mod (p - 1).
-
-
-
-
- Exponent 2. This has a numeric value of d mod (q - 1).
-
-
-
-
- Coefficient. This has a numeric value of (inverse of q mod p).
-
-
-
-
- Private exponent, often known as d.
-
-
-
-
- Create and initialize structure from binary data
-
- On validate errors
- Initialized structure
-
-
-
- Create and initialize structure from binary data with defined header
-
- On validate errors
- Initialized structure
-
-
-
- Serializes structure as binary data
-
-
-
-
- Create and initialize structure from RSAParameters
-
- Initialized structure
- http://msdn.microsoft.com/en-us/library/system.security.cryptography.rsaparameters.aspx
-
-
-
- Create and initialize RSAParameters structure
-
- Initialized structure
- http://msdn.microsoft.com/en-us/library/system.security.cryptography.rsaparameters.aspx
-
-
-
- Returns a that represents this instance.
-
-
- A that represents this instance.
-
-
-
-
- Public-key BLOBs, type PUBLICKEYBLOB, are used to store public keys outside a CSP. Extended provider public-key BLOBs have the following format.
-
-
-
-
- BLOB Header
-
-
-
-
- RSA public key data
-
-
-
-
- The public-key modulus data
-
-
-
-
- Create and initialize structure from binary data
-
- On validate errors
- Initialized structure
-
-
-
- Create and initialize structure from binary data with defined header
-
- On validate errors
- Initialized structure
-
-
-
- Serializes structure as binary data
-
-
-
-
- Create and initialize structure from RSAParameters
-
- Initialized structure
- http://msdn.microsoft.com/en-us/library/system.security.cryptography.rsaparameters.aspx
-
-
-
- Create and initialize RSAParameters structure
-
- Initialized structure
- http://msdn.microsoft.com/en-us/library/system.security.cryptography.rsaparameters.aspx
-
-
-
- Returns a that represents this instance.
-
-
- A that represents this instance.
-
-
-
-
- RSAParameters for Import / Export
-
-
-
-
- Parameter value E
-
-
-
-
- Parameter value N
-
-
-
-
- Parameter value P
-
-
-
-
- Parameter value Q
-
-
-
-
- Parameter value DP
-
-
-
-
- Parameter value DQ
-
-
-
-
- Parameter value IQ
-
-
-
-
- Parameter value D
-
-
-
-
- Parameter value Phi
-
-
-
-
- Bitwise XOR for 2 byte arrays. Arrays must be the same length.
-
- Left side for comparison
- Right side for comparison
- Resulting byte array
-
-
-
- Bitwise XOR for 2 Bytes.
-
- Left side for comparison
- Right side for comparison
- Resulting byte
-
-
-
- Convert the input Integer to an Octet String.
-
- input integer
- size in octets (bytes)
- Resulting byte array of specified length
-
-
-
- Mask generation function.
-
- Seed
- Length of generated mask
- Length of the hash produced by the supplied hash provider
- Hash provider to use in mask generation
- Generated mask of specified length
-
-
-
- @jonskeet: Collection of utility methods which operate on streams.
- r285, February 26th 2009: http://www.yoda.arachsys.com/csharp/miscutil/
-
-
-
-
- Reads the given stream up to the end, returning the data as a byte
- array.
-
-
-
-
- Reads the given stream up to the end, returning the data as a byte
- array, using the given buffer size.
-
-
-
-
- Reads the given stream up to the end, returning the data as a byte
- array, using the given buffer for transferring data. Note that the
- current contents of the buffer is ignored, so the buffer needn't
- be cleared beforehand.
-
-
-
-
- Copies all the data from one stream into another.
-
-
-
-
- Copies all the data from one stream into another, using a buffer
- of the given size.
-
-
-
-
- Copies all the data from one stream into another, using the given
- buffer for transferring data. Note that the current contents of
- the buffer is ignored, so the buffer needn't be cleared beforehand.
-
-
-
-
- Reads exactly the given number of bytes from the specified stream.
- If the end of the stream is reached before the specified amount
- of data is read, an exception is thrown.
-
-
-
-
- Reads into a buffer, filling it completely.
-
-
-
-
- Reads exactly the given number of bytes from the specified stream,
- into the given buffer, starting at position 0 of the array.
-
-
-
-
- Reads exactly the given number of bytes from the specified stream,
- into the given buffer, starting at position 0 of the array.
-
-
-
-
- Same as ReadExactly, but without the argument checks.
-
-
-
-
- Converts from base: 0 - 62
-
- The source.
- From.
- To.
-
-
-
-
- Skip the encoding process for 'safe strings'
-
-
-
-
-
-
diff --git a/packages/ServiceStack.Text.5.1.0/ServiceStack.Text.5.1.0.nupkg b/packages/ServiceStack.Text.5.1.0/ServiceStack.Text.5.1.0.nupkg
new file mode 100644
index 0000000000..5a85948dc5
Binary files /dev/null and b/packages/ServiceStack.Text.5.1.0/ServiceStack.Text.5.1.0.nupkg differ
diff --git a/packages/ServiceStack.Text.5.1.0/lib/net45/ServiceStack.Text.dll b/packages/ServiceStack.Text.5.1.0/lib/net45/ServiceStack.Text.dll
new file mode 100644
index 0000000000..6a92be7f4a
Binary files /dev/null and b/packages/ServiceStack.Text.5.1.0/lib/net45/ServiceStack.Text.dll differ
diff --git a/packages/ServiceStack.Text.5.1.0/lib/net45/ServiceStack.Text.xml b/packages/ServiceStack.Text.5.1.0/lib/net45/ServiceStack.Text.xml
new file mode 100644
index 0000000000..cd0e03eb94
--- /dev/null
+++ b/packages/ServiceStack.Text.5.1.0/lib/net45/ServiceStack.Text.xml
@@ -0,0 +1,1612 @@
+
+
+
+ ServiceStack.Text
+
+
+
+
+ Utils to load types
+
+
+
+
+ Find the type from the name supplied
+
+ [typeName] or [typeName, assemblyName]
+
+
+
+
+ The top-most interface of the given type, if any.
+
+
+
+
+ Find type if it exists
+
+
+
+ The type if it exists
+
+
+
+ If AlwaysUseUtc is set to true then convert all DateTime to UTC. If PreserveUtc is set to true then UTC dates will not convert to local
+
+
+
+
+
+
+ Repairs an out-of-spec XML date/time string which incorrectly uses a space instead of a 'T' to separate the date from the time.
+ These string are occasionally generated by SQLite and can cause errors in OrmLite when reading these columns from the DB.
+
+ The XML date/time string to repair
+ The repaired string. If no repairs were made, the original string is returned.
+
+
+
+ WCF Json format: /Date(unixts+0000)/
+
+
+
+
+
+
+ WCF Json format: /Date(unixts+0000)/
+
+
+
+
+
+
+ Get the type(string) constructor if exists
+
+ The type.
+
+
+
+
+ micro optimizations: using flags instead of value.IndexOfAny(EscapeChars)
+
+
+
+
+
+
+ Class to hold
+
+
+
+
+
+ A fast, standards-based, serialization-issue free DateTime serailizer.
+
+
+
+
+ Determines whether this serializer can create the specified type from a string.
+
+ The type.
+
+ true if this instance [can create from string] the specified type; otherwise, false .
+
+
+
+
+ Parses the specified value.
+
+ The value.
+
+
+
+
+ Deserializes from reader.
+
+ The reader.
+
+
+
+
+ Serializes to string.
+
+ The value.
+
+
+
+
+ Serializes to writer.
+
+ The value.
+ The writer.
+
+
+
+ Sets which format to use when serializing TimeSpans
+
+
+
+
+ if the is configured
+ to take advantage of specification,
+ to support user-friendly serialized formats, ie emitting camelCasing for JSON
+ and parsing member names and enum values in a case-insensitive manner.
+
+
+
+
+ if the is configured
+ to support web-friendly serialized formats, ie emitting lowercase_underscore_casing for JSON
+
+
+
+
+ Define how property names are mapped during deserialization
+
+
+
+
+ Gets or sets a value indicating if the framework should throw serialization exceptions
+ or continue regardless of deserialization errors. If the framework
+ will throw; otherwise, it will parse as many fields as possible. The default is .
+
+
+
+
+ Gets or sets a value indicating if the framework should always convert to UTC format instead of local time.
+
+
+
+
+ Gets or sets a value indicating if the framework should skip automatic conversions.
+ Dates will be handled literally, any included timezone encoding will be lost and the date will be treaded as DateTimeKind.Local
+ Utc formatted input will result in DateTimeKind.Utc output. Any input without TZ data will be set DateTimeKind.Unspecified
+ This will take precedence over other flags like AlwaysUseUtc
+ JsConfig.DateHandler = DateHandler.ISO8601 should be used when set true for consistent de/serialization.
+
+
+
+
+ Gets or sets a value indicating if the framework should always assume is in UTC format if Kind is Unspecified.
+
+
+
+
+ Gets or sets whether we should append the Utc offset when we serialize Utc dates. Defaults to no.
+ Only supported for when the JsConfig.DateHandler == JsonDateHandler.TimestampOffset
+
+
+
+
+ Gets or sets a value indicating if unicode symbols should be serialized as "\uXXXX".
+
+
+
+
+ Gets or sets a value indicating if HTML entity chars [> < & = '] should be escaped as "\uXXXX".
+
+
+
+
+ Gets or sets a value indicating if the framework should call an error handler when
+ an exception happens during the deserialization.
+
+ Parameters have following meaning in order: deserialized entity, property name, parsed value, property type, caught exception.
+
+
+
+ If set to true, Interface types will be prefered over concrete types when serializing.
+
+
+
+
+ If set to true, Interface types will be prefered over concrete types when serializing.
+
+
+
+
+ Sets the maximum depth to avoid circular dependencies
+
+
+
+
+ Set this to enable your own type construction provider.
+ This is helpful for integration with IoC containers where you need to call the container constructor.
+ Return null if you don't know how to construct the type and the parameterless constructor will be used.
+
+
+
+
+ Always emit type info for this type. Takes precedence over ExcludeTypeInfo
+
+
+
+
+ Never emit type info for this type
+
+
+
+
+ if the is configured
+ to take advantage of specification,
+ to support user-friendly serialized formats, ie emitting camelCasing for JSON
+ and parsing member names and enum values in a case-insensitive manner.
+
+
+
+
+ Define custom serialization fn for BCL Structs
+
+
+
+
+ Opt-in flag to set some Value Types to be treated as a Ref Type
+
+
+
+
+ Whether there is a fn (raw or otherwise)
+
+
+
+
+ Define custom raw serialization fn
+
+
+
+
+ Define custom serialization hook
+
+
+
+
+ Define custom after serialization hook
+
+
+
+
+ Define custom deserialization fn for BCL Structs
+
+
+
+
+ Define custom raw deserialization fn for objects
+
+
+
+
+ Exclude specific properties of this type from being serialized
+
+
+
+
+ The property names on target types must match property names in the JSON source
+
+
+
+
+ The property names on target types may not match the property names in the JSON source
+
+
+
+
+ Uses the xsd format like PT15H10M20S
+
+
+
+
+ Uses the standard .net ToString method of the TimeSpan class
+
+
+
+
+ Get JSON string value converted to T
+
+
+
+
+ Get JSON string value
+
+
+
+
+ Get JSON string value
+
+
+
+
+ Get unescaped string value
+
+
+
+
+ Get unescaped string value
+
+
+
+
+ Write JSON Array, Object, bool or number values as raw string
+
+
+
+
+ Creates an instance of a Type from a string value
+
+
+
+
+ Parses the specified value.
+
+ The value.
+
+
+
+
+ Shortcut escape when we're sure value doesn't contain any escaped chars
+
+
+
+
+
+
+ Given a character as utf32, returns the equivalent string provided that the character
+ is legal json.
+
+
+
+
+
+
+ Micro-optimization keep pre-built char arrays saving a .ToCharArray() + function call (see .net implementation of .Write(string))
+
+
+
+
+ Searches the string for one or more non-printable characters.
+
+ The string to search.
+
+ True if there are any characters that require escaping. False if the value can be written verbatim.
+
+ Micro optimizations: since quote and backslash are the only printable characters requiring escaping, removed previous optimization
+ (using flags instead of value.IndexOfAny(EscapeChars)) in favor of two equality operations saving both memory and CPU time.
+ Also slightly reduced code size by re-arranging conditions.
+ TODO: Possible Linq-only solution requires profiling: return value.Any(c => !c.IsPrintable() || c == QuoteChar || c == EscapeChar);
+
+
+
+
+ Implement the serializer using a more static approach
+
+
+
+
+
+ Implement the serializer using a more static approach
+
+
+
+
+
+ Pretty Thread-Safe cache class from:
+ http://code.google.com/p/dapper-dot-net/source/browse/Dapper/SqlMapper.cs
+
+ This is a micro-cache; suitable when the number of terms is controllable (a few hundred, for example),
+ and strictly append-only; you cannot change existing values. All key matches are on **REFERENCE**
+ equality. The type is fully thread-safe.
+
+
+
+
+ Represents an individual object, allowing access to members by-name
+
+
+
+
+ Get or Set the value of a named member for the underlying object
+
+
+
+
+ The object represented by this instance
+
+
+
+
+ Use the target types definition of equality
+
+
+
+
+ Obtain the hash of the target object
+
+
+
+
+ Use the target's definition of a string representation
+
+
+
+
+ Wraps an individual object, allowing by-name access to that instance
+
+
+
+
+ Provides by-name member-access to objects of a given type
+
+
+
+
+ Does this type support new instances via a parameterless constructor?
+
+
+
+
+ Create a new instance of this type
+
+
+
+
+ Provides a type-specific accessor, allowing by-name access for all objects of that type
+
+ The accessor is cached internally; a pre-existing accessor may be returned
+
+
+
+ Get or set the value of a named member on the target instance
+
+
+
+
+ Generic implementation of object pooling pattern with predefined pool size limit. The main
+ purpose is that limited number of frequently used objects can be kept in the pool for
+ further recycling.
+
+ Notes:
+ 1) it is not the goal to keep all returned objects. Pool is not meant for storage. If there
+ is no space in the pool, extra returned objects will be dropped.
+
+ 2) it is implied that if object was obtained from a pool, the caller will return it back in
+ a relatively short time. Keeping checked out objects for long durations is ok, but
+ reduces usefulness of pooling. Just new up your own.
+
+ Not returning objects to the pool in not detrimental to the pool's work, but is a bad practice.
+ Rationale:
+ If there is no intent for reusing the object, do not use pool - just use "new".
+
+
+
+
+ Not using System.Func{T} because this file is linked into the (debugger) Formatter,
+ which does not have that type (since it compiles against .NET 2.0).
+
+
+
+
+ Produces an instance.
+
+
+ Search strategy is a simple linear probing which is chosen for it cache-friendliness.
+ Note that Free will try to store recycled objects close to the start thus statistically
+ reducing how far we will typically search.
+
+
+
+
+ Returns objects to the pool.
+
+
+ Search strategy is a simple linear probing which is chosen for it cache-friendliness.
+ Note that Free will try to store recycled objects close to the start thus statistically
+ reducing how far we will typically search in Allocate.
+
+
+
+
+ Removes an object from leak tracking.
+
+ This is called when an object is returned to the pool. It may also be explicitly
+ called if an object allocated from the pool is intentionally not being returned
+ to the pool. This can be of use with pooled arrays if the consumer wants to
+ return a larger array to the pool than was originally allocated.
+
+
+
+
+ this is RAII object to automatically release pooled object when its owning pool
+
+
+
+
+ Shared object pool for roslyn
+
+ Use this shared pool if only concern is reducing object allocations.
+ if perf of an object pool itself is also a concern, use ObjectPool directly.
+
+ For example, if you want to create a million of small objects within a second,
+ use the ObjectPool directly. it should have much less overhead than using this.
+
+
+
+
+ pool that uses default constructor with 100 elements pooled
+
+
+
+
+ pool that uses default constructor with 20 elements pooled
+
+
+
+
+ pool that uses string as key with StringComparer.OrdinalIgnoreCase as key comparer
+
+
+
+
+ pool that uses string as element with StringComparer.OrdinalIgnoreCase as element comparer
+
+
+
+
+ pool that uses string as element with StringComparer.Ordinal as element comparer
+
+
+
+
+ Used to reduce the # of temporary byte[]s created to satisfy serialization and
+ other I/O requests
+
+
+
+ pooled memory : 4K * 512 = 4MB
+
+
+
+ Manages pools of RecyclableMemoryStream objects.
+
+
+ There are two pools managed in here. The small pool contains same-sized buffers that are handed to streams
+ as they write more data.
+
+ For scenarios that need to call GetBuffer(), the large pool contains buffers of various sizes, all
+ multiples of LargeBufferMultiple (1 MB by default). They are split by size to avoid overly-wasteful buffer
+ usage. There should be far fewer 8 MB buffers than 1 MB buffers, for example.
+
+
+
+
+ Generic delegate for handling events without any arguments.
+
+
+
+
+ Delegate for handling large buffer discard reports.
+
+ Reason the buffer was discarded.
+
+
+
+ Delegate for handling reports of stream size when streams are allocated
+
+ Bytes allocated.
+
+
+
+ Delegate for handling periodic reporting of memory use statistics.
+
+ Bytes currently in use in the small pool.
+ Bytes currently free in the small pool.
+ Bytes currently in use in the large pool.
+ Bytes currently free in the large pool.
+
+
+
+ pools[0] = 1x largeBufferMultiple buffers
+ pools[1] = 2x largeBufferMultiple buffers
+ etc., up to maximumBufferSize
+
+
+
+
+ Initializes the memory manager with the default block/buffer specifications.
+
+
+
+
+ Initializes the memory manager with the given block requiredSize.
+
+ Size of each block that is pooled. Must be > 0.
+ Each large buffer will be a multiple of this value.
+ Buffers larger than this are not pooled
+ blockSize is not a positive number, or largeBufferMultiple is not a positive number, or maximumBufferSize is less than blockSize.
+ maximumBufferSize is not a multiple of largeBufferMultiple
+
+
+
+ The size of each block. It must be set at creation and cannot be changed.
+
+
+
+
+ All buffers are multiples of this number. It must be set at creation and cannot be changed.
+
+
+
+
+ Gets or sets the maximum buffer size.
+
+ Any buffer that is returned to the pool that is larger than this will be
+ discarded and garbage collected.
+
+
+
+ Number of bytes in small pool not currently in use
+
+
+
+
+ Number of bytes currently in use by stream from the small pool
+
+
+
+
+ Number of bytes in large pool not currently in use
+
+
+
+
+ Number of bytes currently in use by streams from the large pool
+
+
+
+
+ How many blocks are in the small pool
+
+
+
+
+ How many buffers are in the large pool
+
+
+
+
+ How many bytes of small free blocks to allow before we start dropping
+ those returned to us.
+
+
+
+
+ How many bytes of large free buffers to allow before we start dropping
+ those returned to us.
+
+
+
+
+ Maximum stream capacity in bytes. Attempts to set a larger capacity will
+ result in an exception.
+
+ A value of 0 indicates no limit.
+
+
+
+ Whether to save callstacks for stream allocations. This can help in debugging.
+ It should NEVER be turned on generally in production.
+
+
+
+
+ Whether dirty buffers can be immediately returned to the buffer pool. E.g. when GetBuffer() is called on
+ a stream and creates a single large buffer, if this setting is enabled, the other blocks will be returned
+ to the buffer pool immediately.
+ Note when enabling this setting that the user is responsible for ensuring that any buffer previously
+ retrieved from a stream which is subsequently modified is not used after modification (as it may no longer
+ be valid).
+
+
+
+
+ Removes and returns a single block from the pool.
+
+ A byte[] array
+
+
+
+ Returns a buffer of arbitrary size from the large buffer pool. This buffer
+ will be at least the requiredSize and always be a multiple of largeBufferMultiple.
+
+ The minimum length of the buffer
+ The tag of the stream returning this buffer, for logging if necessary.
+ A buffer of at least the required size.
+
+
+
+ Returns the buffer to the large pool
+
+ The buffer to return.
+ The tag of the stream returning this buffer, for logging if necessary.
+ buffer is null
+ buffer.Length is not a multiple of LargeBufferMultiple (it did not originate from this pool)
+
+
+
+ Returns the blocks to the pool
+
+ Collection of blocks to return to the pool
+ The tag of the stream returning these blocks, for logging if necessary.
+ blocks is null
+ blocks contains buffers that are the wrong size (or null) for this memory manager
+
+
+
+ Retrieve a new MemoryStream object with no tag and a default initial capacity.
+
+ A MemoryStream.
+
+
+
+ Retrieve a new MemoryStream object with the given tag and a default initial capacity.
+
+ A tag which can be used to track the source of the stream.
+ A MemoryStream.
+
+
+
+ Retrieve a new MemoryStream object with the given tag and at least the given capacity.
+
+ A tag which can be used to track the source of the stream.
+ The minimum desired capacity for the stream.
+ A MemoryStream.
+
+
+
+ Retrieve a new MemoryStream object with the given tag and at least the given capacity, possibly using
+ a single continugous underlying buffer.
+
+ Retrieving a MemoryStream which provides a single contiguous buffer can be useful in situations
+ where the initial size is known and it is desirable to avoid copying data between the smaller underlying
+ buffers to a single large one. This is most helpful when you know that you will always call GetBuffer
+ on the underlying stream.
+ A tag which can be used to track the source of the stream.
+ The minimum desired capacity for the stream.
+ Whether to attempt to use a single contiguous buffer.
+ A MemoryStream.
+
+
+
+ Retrieve a new MemoryStream object with the given tag and with contents copied from the provided
+ buffer. The provided buffer is not wrapped or used after construction.
+
+ The new stream's position is set to the beginning of the stream when returned.
+ A tag which can be used to track the source of the stream.
+ The byte buffer to copy data from.
+ The offset from the start of the buffer to copy from.
+ The number of bytes to copy from the buffer.
+ A MemoryStream.
+
+
+
+ Triggered when a new block is created.
+
+
+
+
+ Triggered when a new block is created.
+
+
+
+
+ Triggered when a new large buffer is created.
+
+
+
+
+ Triggered when a new stream is created.
+
+
+
+
+ Triggered when a stream is disposed.
+
+
+
+
+ Triggered when a stream is finalized.
+
+
+
+
+ Triggered when a stream is finalized.
+
+
+
+
+ Triggered when a user converts a stream to array.
+
+
+
+
+ Triggered when a large buffer is discarded, along with the reason for the discard.
+
+
+
+
+ Periodically triggered to report usage statistics.
+
+
+
+
+ MemoryStream implementation that deals with pooling and managing memory streams which use potentially large
+ buffers.
+
+
+ This class works in tandem with the RecylableMemoryStreamManager to supply MemoryStream
+ objects to callers, while avoiding these specific problems:
+ 1. LOH allocations - since all large buffers are pooled, they will never incur a Gen2 GC
+ 2. Memory waste - A standard memory stream doubles its size when it runs out of room. This
+ leads to continual memory growth as each stream approaches the maximum allowed size.
+ 3. Memory copying - Each time a MemoryStream grows, all the bytes are copied into new buffers.
+ This implementation only copies the bytes when GetBuffer is called.
+ 4. Memory fragmentation - By using homogeneous buffer sizes, it ensures that blocks of memory
+ can be easily reused.
+
+ The stream is implemented on top of a series of uniformly-sized blocks. As the stream's length grows,
+ additional blocks are retrieved from the memory manager. It is these blocks that are pooled, not the stream
+ object itself.
+
+ The biggest wrinkle in this implementation is when GetBuffer() is called. This requires a single
+ contiguous buffer. If only a single block is in use, then that block is returned. If multiple blocks
+ are in use, we retrieve a larger buffer from the memory manager. These large buffers are also pooled,
+ split by size--they are multiples of a chunk size (1 MB by default).
+
+ Once a large buffer is assigned to the stream the blocks are NEVER again used for this stream. All operations take place on the
+ large buffer. The large buffer can be replaced by a larger buffer from the pool as needed. All blocks and large buffers
+ are maintained in the stream until the stream is disposed (unless AggressiveBufferReturn is enabled in the stream manager).
+
+
+
+
+
+ All of these blocks must be the same size
+
+
+
+
+ This is only set by GetBuffer() if the necessary buffer is larger than a single block size, or on
+ construction if the caller immediately requests a single large buffer.
+
+ If this field is non-null, it contains the concatenation of the bytes found in the individual
+ blocks. Once it is created, this (or a larger) largeBuffer will be used for the life of the stream.
+
+
+
+
+ This list is used to store buffers once they're replaced by something larger.
+ This is for the cases where you have users of this class that may hold onto the buffers longer
+ than they should and you want to prevent race conditions which could corrupt the data.
+
+
+
+
+ Unique identifier for this stream across it's entire lifetime
+
+ Object has been disposed
+
+
+
+ A temporary identifier for the current usage of this stream.
+
+ Object has been disposed
+
+
+
+ Gets the memory manager being used by this stream.
+
+ Object has been disposed
+
+
+
+ Callstack of the constructor. It is only set if MemoryManager.GenerateCallStacks is true,
+ which should only be in debugging situations.
+
+
+
+
+ Callstack of the Dispose call. It is only set if MemoryManager.GenerateCallStacks is true,
+ which should only be in debugging situations.
+
+
+
+
+ This buffer exists so that WriteByte can forward all of its calls to Write
+ without creating a new byte[] buffer on every call.
+
+
+
+
+ Allocate a new RecyclableMemoryStream object.
+
+ The memory manager
+
+
+
+ Allocate a new RecyclableMemoryStream object
+
+ The memory manager
+ A string identifying this stream for logging and debugging purposes
+
+
+
+ Allocate a new RecyclableMemoryStream object
+
+ The memory manager
+ A string identifying this stream for logging and debugging purposes
+ The initial requested size to prevent future allocations
+
+
+
+ Allocate a new RecyclableMemoryStream object
+
+ The memory manager
+ A string identifying this stream for logging and debugging purposes
+ The initial requested size to prevent future allocations
+ An initial buffer to use. This buffer will be owned by the stream and returned to the memory manager upon Dispose.
+
+
+
+ Returns the memory used by this stream back to the pool.
+
+ Whether we're disposing (true), or being called by the finalizer (false)
+ This method is not thread safe and it may not be called more than once.
+
+
+
+ Equivalent to Dispose
+
+
+
+
+ Gets or sets the capacity
+
+ Capacity is always in multiples of the memory manager's block size, unless
+ the large buffer is in use. Capacity never decreases during a stream's lifetime.
+ Explicitly setting the capacity to a lower value than the current value will have no effect.
+ This is because the buffers are all pooled by chunks and there's little reason to
+ allow stream truncation.
+
+ Object has been disposed
+
+
+
+ Gets the number of bytes written to this stream.
+
+ Object has been disposed
+
+
+
+ Gets the current position in the stream
+
+ Object has been disposed
+
+
+
+ Whether the stream can currently read
+
+
+
+
+ Whether the stream can currently seek
+
+
+
+
+ Always false
+
+
+
+
+ Whether the stream can currently write
+
+
+
+
+ Returns a single buffer containing the contents of the stream.
+ The buffer may be longer than the stream length.
+
+ A byte[] buffer
+ IMPORTANT: Doing a Write() after calling GetBuffer() invalidates the buffer. The old buffer is held onto
+ until Dispose is called, but the next time GetBuffer() is called, a new buffer from the pool will be required.
+ Object has been disposed
+
+
+
+ Returns a new array with a copy of the buffer's contents. You should almost certainly be using GetBuffer combined with the Length to
+ access the bytes in this stream. Calling ToArray will destroy the benefits of pooled buffers, but it is included
+ for the sake of completeness.
+
+ Object has been disposed
+
+
+
+ Reads from the current position into the provided buffer
+
+ Destination buffer
+ Offset into buffer at which to start placing the read bytes.
+ Number of bytes to read.
+ The number of bytes read
+ buffer is null
+ offset or count is less than 0
+ offset subtracted from the buffer length is less than count
+ Object has been disposed
+
+
+
+ Writes the buffer to the stream
+
+ Source buffer
+ Start position
+ Number of bytes to write
+ buffer is null
+ offset or count is negative
+ buffer.Length - offset is not less than count
+ Object has been disposed
+
+
+
+ Returns a useful string for debugging. This should not normally be called in actual production code.
+
+
+
+
+ Writes a single byte to the current position in the stream.
+
+ byte value to write
+ Object has been disposed
+
+
+
+ Reads a single byte from the current position in the stream.
+
+ The byte at the current position, or -1 if the position is at the end of the stream.
+ Object has been disposed
+
+
+
+ Sets the length of the stream
+
+ value is negative or larger than MaxStreamLength
+ Object has been disposed
+
+
+
+ Sets the position to the offset from the seek location
+
+ How many bytes to move
+ From where
+ The new position
+ Object has been disposed
+ offset is larger than MaxStreamLength
+ Invalid seek origin
+ Attempt to set negative position
+
+
+
+ Synchronously writes this stream's bytes to the parameter stream.
+
+ Destination stream
+ Important: This does a synchronous write, which may not be desired in some situations
+
+
+
+ Release the large buffer (either stores it for eventual release or returns it immediately).
+
+
+
+
+ Allow Type to be deserialized into late-bould object Types using __type info
+
+
+
+
+ Allow Type to be deserialized into late-bould object Types using __type info
+
+
+
+
+ Reusable StringBuilder ThreadStatic Cache
+
+
+
+
+ Alternative Reusable StringBuilder ThreadStatic Cache
+
+
+
+
+ An optimized representation of a substring.
+
+
+
+
+ Initializes an instance of the struct.
+
+
+ The original . The includes the whole .
+
+
+
+
+ Initializes an instance of the struct.
+
+ The original used as buffer.
+ The offset of the segment within the .
+ The length of the segment.
+
+
+
+ Gets the buffer for this .
+
+
+
+
+ Gets the offset within the buffer for this .
+
+
+
+
+ Gets the length of this .
+
+
+
+
+ Gets the value of this segment as a .
+
+
+
+
+ Gets whether or not this contains a valid value.
+
+
+
+
+
+
+
+ Indicates whether the current object is equal to another object of the same type.
+
+ An object to compare with this object.
+ true
if the current object is equal to the other parameter; otherwise, false
.
+
+
+
+ Indicates whether the current object is equal to another object of the same type.
+
+ An object to compare with this object.
+ One of the enumeration values that specifies the rules to use in the comparison.
+ true
if the current object is equal to the other parameter; otherwise, false
.
+
+
+
+ Checks if the specified is equal to the current .
+
+ The to compare with the current .
+ true
if the specified is equal to the current ; otherwise, false
.
+
+
+
+ Checks if the specified is equal to the current .
+
+ The to compare with the current .
+ One of the enumeration values that specifies the rules to use in the comparison.
+ true
if the specified is equal to the current ; otherwise, false
.
+
+
+
+
+ This GetHashCode is expensive since it allocates on every call.
+ However this is required to ensure we retain any behavior (such as hash code randomization) that
+ string.GetHashCode has.
+
+
+
+
+ Checks if two specified have the same value.
+
+ The first to compare, or null
.
+ The second to compare, or null
.
+ true
if the value of is the same as the value of ; otherwise, false
.
+
+
+
+ Checks if two specified have different values.
+
+ The first to compare, or null
.
+ The second to compare, or null
.
+ true
if the value of is different from the value of ; otherwise, false
.
+
+
+
+ Checks if the beginning of this matches the specified when compared using the specified .
+
+ The to compare.
+ One of the enumeration values that specifies the rules to use in the comparison.
+ true
if matches the beginning of this ; otherwise, false
.
+
+
+
+ Checks if the end of this matches the specified when compared using the specified .
+
+ The to compare.
+ One of the enumeration values that specifies the rules to use in the comparison.
+ true
if matches the end of this ; otherwise, false
.
+
+
+
+ Retrieves a substring from this .
+ The substring starts at the position specified by and has the specified .
+
+ The zero-based starting character position of a substring in this .
+ The number of characters in the substring.
+ A that is equivalent to the substring of length that begins at in this
+
+
+
+ Retrieves a that represents a substring from this .
+ The starts at the position specified by and has the specified .
+
+ The zero-based starting character position of a substring in this .
+ The number of characters in the substring.
+ A that is equivalent to the substring of length that begins at in this
+
+
+
+ Gets the zero-based index of the first occurrence of the character in this .
+ The search starts at and examines a specified number of character positions.
+
+ The Unicode character to seek.
+ The zero-based index position at which the search starts.
+ The number of characters to examine.
+ The zero-based index position of from the beginning of the if that character is found, or -1 if it is not.
+
+
+
+ Gets the zero-based index of the first occurrence of the character in this .
+ The search starts at .
+
+ The Unicode character to seek.
+ The zero-based index position at which the search starts.
+ The zero-based index position of from the beginning of the if that character is found, or -1 if it is not.
+
+
+
+ Gets the zero-based index of the first occurrence of the character in this .
+
+ The Unicode character to seek.
+ The zero-based index position of from the beginning of the if that character is found, or -1 if it is not.
+
+
+
+ Removes all leading and trailing whitespaces.
+
+ The trimmed .
+
+
+
+ Removes all leading whitespaces.
+
+ The trimmed .
+
+
+
+ Removes all trailing whitespaces.
+
+ The trimmed .
+
+
+
+ Returns the represented by this or String.Empty
if the does not contain a value.
+
+ The represented by this or String.Empty
if the does not contain a value.
+
+
+
+ Reusable StringWriter ThreadStatic Cache
+
+
+
+
+ Alternative Reusable StringWriter ThreadStatic Cache
+
+
+
+
+ A class to allow the conversion of doubles to string representations of
+ their exact decimal values. The implementation aims for readability over
+ efficiency.
+
+ Courtesy of @JonSkeet
+ http://www.yoda.arachsys.com/csharp/DoubleConverter.cs
+
+
+
+
+
+
+
+ How many digits are *after* the decimal point
+
+
+
+
+ Constructs an arbitrary decimal expansion from the given long.
+ The long must not be negative.
+
+
+
+
+ Multiplies the current expansion by the given amount, which should
+ only be 2 or 5.
+
+
+
+
+ Shifts the decimal point; a negative value makes
+ the decimal expansion bigger (as fewer digits come after the
+ decimal place) and a positive value makes the decimal
+ expansion smaller.
+
+
+
+
+ Removes leading/trailing zeroes from the expansion.
+
+
+
+
+ Converts the value to a proper decimal string representation.
+
+
+
+
+ Creates an instance of a Type from a string value
+
+
+
+
+ Determines whether the specified type is convertible from string.
+
+ The type.
+
+ true if the specified type is convertible from string; otherwise, false .
+
+
+
+
+ Parses the specified value.
+
+ The value.
+
+
+
+
+ Parses the specified type.
+
+ The type.
+ The value.
+
+
+
+
+ Useful extension method to get the Dictionary[string,string] representation of any POCO type.
+
+
+
+
+
+ Recursively prints the contents of any POCO object in a human-friendly, readable format
+
+
+
+
+
+ Print Dump to Console.WriteLine
+
+
+
+
+ Print string.Format to Console.WriteLine
+
+
+
+
+ Parses the specified value.
+
+ The value.
+
+
+
+
+ Populate an object with Example data.
+
+
+
+
+
+
+ Populates the object with example data.
+
+
+ Tracks how deeply nested we are
+
+
+
+
+ Public Code API to register commercial license for ServiceStack.
+
+
+
+
+ Internal Utilities to verify licensing
+
+
+
+
+ Maps the path of a file in the context of a VS project in a Console App
+
+ the relative path
+ the absolute path
+ Assumes static content is two directories above the /bin/ directory,
+ eg. in a unit test scenario the assembly would be in /bin/Debug/.
+
+
+
+ Maps the path of a file in the context of a VS 2017+ multi-platform project in a Console App
+
+ the relative path
+ the absolute path
+ Assumes static content is two directories above the /bin/ directory,
+ eg. in a unit test scenario the assembly would be in /bin/Debug/net45
+
+
+
+ Maps the path of a file in the bin\ folder of a self-hosted scenario
+
+ the relative path
+ the absolute path
+ Assumes static content is copied to /bin/ folder with the assemblies
+
+
+
+ Maps the path of a file in an ASP.NET hosted scenario
+
+ the relative path
+ the absolute path
+ Assumes static content is in the parent folder of the /bin/ directory
+
+
+
+ Add a Property attribute at runtime.
+ Not threadsafe, should only add attributes on Startup.
+
+
+
+
+ Add a Property attribute at runtime.
+ Not threadsafe, should only add attributes on Startup.
+
+
+
+
+ Implement the serializer using a more static approach
+
+
+
+
+
+ Creates a new instance of type.
+ First looks at JsConfig.ModelFactory before falling back to CreateInstance
+
+
+
+
+ Creates a new instance of type.
+ First looks at JsConfig.ModelFactory before falling back to CreateInstance
+
+
+
+
+ Creates a new instance from the default constructor of type
+
+
+
+
+ @jonskeet: Collection of utility methods which operate on streams.
+ r285, February 26th 2009: http://www.yoda.arachsys.com/csharp/miscutil/
+
+
+
+
+ Reads the given stream up to the end, returning the data as a byte
+ array.
+
+
+
+
+ Reads the given stream up to the end, returning the data as a byte
+ array, using the given buffer size.
+
+
+
+
+ Reads the given stream up to the end, returning the data as a byte
+ array, using the given buffer for transferring data. Note that the
+ current contents of the buffer is ignored, so the buffer needn't
+ be cleared beforehand.
+
+
+
+
+ Copies all the data from one stream into another.
+
+
+
+
+ Copies all the data from one stream into another, using a buffer
+ of the given size.
+
+
+
+
+ Copies all the data from one stream into another, using the given
+ buffer for transferring data. Note that the current contents of
+ the buffer is ignored, so the buffer needn't be cleared beforehand.
+
+
+
+
+ Reads exactly the given number of bytes from the specified stream.
+ If the end of the stream is reached before the specified amount
+ of data is read, an exception is thrown.
+
+
+
+
+ Reads into a buffer, filling it completely.
+
+
+
+
+ Reads exactly the given number of bytes from the specified stream,
+ into the given buffer, starting at position 0 of the array.
+
+
+
+
+ Reads exactly the given number of bytes from the specified stream,
+ into the given buffer, starting at position 0 of the array.
+
+
+
+
+ Same as ReadExactly, but without the argument checks.
+
+
+
+
+ Converts from base: 0 - 62
+
+ The source.
+ From.
+ To.
+
+
+
+
+ Skip the encoding process for 'safe strings'
+
+
+
+
+
+
diff --git a/packages/ServiceStack.Text.5.1.0/lib/netstandard2.0/ServiceStack.Text.deps.json b/packages/ServiceStack.Text.5.1.0/lib/netstandard2.0/ServiceStack.Text.deps.json
new file mode 100644
index 0000000000..d21a9158b4
--- /dev/null
+++ b/packages/ServiceStack.Text.5.1.0/lib/netstandard2.0/ServiceStack.Text.deps.json
@@ -0,0 +1,240 @@
+{
+ "runtimeTarget": {
+ "name": ".NETStandard,Version=v2.0/",
+ "signature": "3adc12bffbd422090fc8d06f36917353721f6fe5"
+ },
+ "compilationOptions": {},
+ "targets": {
+ ".NETStandard,Version=v2.0": {},
+ ".NETStandard,Version=v2.0/": {
+ "ServiceStack.Text/5.1.0": {
+ "dependencies": {
+ "Microsoft.CSharp": "4.4.1",
+ "Microsoft.Extensions.Primitives": "2.0.0",
+ "NETStandard.Library": "2.0.0",
+ "System.Reflection.Emit": "4.3.0",
+ "System.Reflection.Emit.Lightweight": "4.3.0",
+ "System.Runtime": "4.3.0"
+ },
+ "runtime": {
+ "ServiceStack.Text.dll": {}
+ }
+ },
+ "Microsoft.CSharp/4.4.1": {
+ "runtime": {
+ "lib/netstandard2.0/Microsoft.CSharp.dll": {}
+ }
+ },
+ "Microsoft.Extensions.Primitives/2.0.0": {
+ "dependencies": {
+ "System.Runtime.CompilerServices.Unsafe": "4.4.0"
+ },
+ "runtime": {
+ "lib/netstandard2.0/Microsoft.Extensions.Primitives.dll": {}
+ }
+ },
+ "Microsoft.NETCore.Platforms/1.1.0": {},
+ "Microsoft.NETCore.Targets/1.1.0": {},
+ "NETStandard.Library/2.0.0": {
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.1.0"
+ }
+ },
+ "System.IO/4.3.0": {
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.1.0",
+ "Microsoft.NETCore.Targets": "1.1.0",
+ "System.Runtime": "4.3.0",
+ "System.Text.Encoding": "4.3.0",
+ "System.Threading.Tasks": "4.3.0"
+ }
+ },
+ "System.Reflection/4.3.0": {
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.1.0",
+ "Microsoft.NETCore.Targets": "1.1.0",
+ "System.IO": "4.3.0",
+ "System.Reflection.Primitives": "4.3.0",
+ "System.Runtime": "4.3.0"
+ }
+ },
+ "System.Reflection.Emit/4.3.0": {
+ "dependencies": {
+ "System.IO": "4.3.0",
+ "System.Reflection": "4.3.0",
+ "System.Reflection.Emit.ILGeneration": "4.3.0",
+ "System.Reflection.Primitives": "4.3.0",
+ "System.Runtime": "4.3.0"
+ },
+ "runtime": {
+ "lib/netstandard1.3/System.Reflection.Emit.dll": {}
+ }
+ },
+ "System.Reflection.Emit.ILGeneration/4.3.0": {
+ "dependencies": {
+ "System.Reflection": "4.3.0",
+ "System.Reflection.Primitives": "4.3.0",
+ "System.Runtime": "4.3.0"
+ },
+ "runtime": {
+ "lib/netstandard1.3/System.Reflection.Emit.ILGeneration.dll": {}
+ }
+ },
+ "System.Reflection.Emit.Lightweight/4.3.0": {
+ "dependencies": {
+ "System.Reflection": "4.3.0",
+ "System.Reflection.Emit.ILGeneration": "4.3.0",
+ "System.Reflection.Primitives": "4.3.0",
+ "System.Runtime": "4.3.0"
+ },
+ "runtime": {
+ "lib/netstandard1.3/System.Reflection.Emit.Lightweight.dll": {}
+ }
+ },
+ "System.Reflection.Primitives/4.3.0": {
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.1.0",
+ "Microsoft.NETCore.Targets": "1.1.0",
+ "System.Runtime": "4.3.0"
+ }
+ },
+ "System.Runtime/4.3.0": {
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.1.0",
+ "Microsoft.NETCore.Targets": "1.1.0"
+ }
+ },
+ "System.Runtime.CompilerServices.Unsafe/4.4.0": {
+ "runtime": {
+ "lib/netstandard2.0/System.Runtime.CompilerServices.Unsafe.dll": {}
+ }
+ },
+ "System.Text.Encoding/4.3.0": {
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.1.0",
+ "Microsoft.NETCore.Targets": "1.1.0",
+ "System.Runtime": "4.3.0"
+ }
+ },
+ "System.Threading.Tasks/4.3.0": {
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.1.0",
+ "Microsoft.NETCore.Targets": "1.1.0",
+ "System.Runtime": "4.3.0"
+ }
+ }
+ }
+ },
+ "libraries": {
+ "ServiceStack.Text/5.1.0": {
+ "type": "project",
+ "serviceable": false,
+ "sha512": ""
+ },
+ "Microsoft.CSharp/4.4.1": {
+ "type": "package",
+ "serviceable": true,
+ "sha512": "sha512-A5hI3gk6WpcBI0QGZY6/d5CCaYUxJgi7iENn1uYEng+Olo8RfI5ReGVkjXjeu3VR3srLvVYREATXa2M0X7FYJA==",
+ "path": "microsoft.csharp/4.4.1",
+ "hashPath": "microsoft.csharp.4.4.1.nupkg.sha512"
+ },
+ "Microsoft.Extensions.Primitives/2.0.0": {
+ "type": "package",
+ "serviceable": true,
+ "sha512": "sha512-ukg53qNlqTrK38WA30b5qhw0GD7y3jdI9PHHASjdKyTcBHTevFM2o23tyk3pWCgAV27Bbkm+CPQ2zUe1ZOuYSA==",
+ "path": "microsoft.extensions.primitives/2.0.0",
+ "hashPath": "microsoft.extensions.primitives.2.0.0.nupkg.sha512"
+ },
+ "Microsoft.NETCore.Platforms/1.1.0": {
+ "type": "package",
+ "serviceable": true,
+ "sha512": "sha512-kz0PEW2lhqygehI/d6XsPCQzD7ff7gUJaVGPVETX611eadGsA3A877GdSlU0LRVMCTH/+P3o2iDTak+S08V2+A==",
+ "path": "microsoft.netcore.platforms/1.1.0",
+ "hashPath": "microsoft.netcore.platforms.1.1.0.nupkg.sha512"
+ },
+ "Microsoft.NETCore.Targets/1.1.0": {
+ "type": "package",
+ "serviceable": true,
+ "sha512": "sha512-aOZA3BWfz9RXjpzt0sRJJMjAscAUm3Hoa4UWAfceV9UTYxgwZ1lZt5nO2myFf+/jetYQo4uTP7zS8sJY67BBxg==",
+ "path": "microsoft.netcore.targets/1.1.0",
+ "hashPath": "microsoft.netcore.targets.1.1.0.nupkg.sha512"
+ },
+ "NETStandard.Library/2.0.0": {
+ "type": "package",
+ "serviceable": true,
+ "sha512": "sha512-7jnbRU+L08FXKMxqUflxEXtVymWvNOrS8yHgu9s6EM8Anr6T/wIX4nZ08j/u3Asz+tCufp3YVwFSEvFTPYmBPA==",
+ "path": "netstandard.library/2.0.0",
+ "hashPath": "netstandard.library.2.0.0.nupkg.sha512"
+ },
+ "System.IO/4.3.0": {
+ "type": "package",
+ "serviceable": true,
+ "sha512": "sha512-3qjaHvxQPDpSOYICjUoTsmoq5u6QJAFRUITgeT/4gqkF1bajbSmb1kwSxEA8AHlofqgcKJcM8udgieRNhaJ5Cg==",
+ "path": "system.io/4.3.0",
+ "hashPath": "system.io.4.3.0.nupkg.sha512"
+ },
+ "System.Reflection/4.3.0": {
+ "type": "package",
+ "serviceable": true,
+ "sha512": "sha512-KMiAFoW7MfJGa9nDFNcfu+FpEdiHpWgTcS2HdMpDvt9saK3y/G4GwprPyzqjFH9NTaGPQeWNHU+iDlDILj96aQ==",
+ "path": "system.reflection/4.3.0",
+ "hashPath": "system.reflection.4.3.0.nupkg.sha512"
+ },
+ "System.Reflection.Emit/4.3.0": {
+ "type": "package",
+ "serviceable": true,
+ "sha512": "sha512-228FG0jLcIwTVJyz8CLFKueVqQK36ANazUManGaJHkO0icjiIypKW7YLWLIWahyIkdh5M7mV2dJepllLyA1SKg==",
+ "path": "system.reflection.emit/4.3.0",
+ "hashPath": "system.reflection.emit.4.3.0.nupkg.sha512"
+ },
+ "System.Reflection.Emit.ILGeneration/4.3.0": {
+ "type": "package",
+ "serviceable": true,
+ "sha512": "sha512-59tBslAk9733NXLrUJrwNZEzbMAcu8k344OYo+wfSVygcgZ9lgBdGIzH/nrg3LYhXceynyvTc8t5/GD4Ri0/ng==",
+ "path": "system.reflection.emit.ilgeneration/4.3.0",
+ "hashPath": "system.reflection.emit.ilgeneration.4.3.0.nupkg.sha512"
+ },
+ "System.Reflection.Emit.Lightweight/4.3.0": {
+ "type": "package",
+ "serviceable": true,
+ "sha512": "sha512-oadVHGSMsTmZsAF864QYN1t1QzZjIcuKU3l2S9cZOwDdDueNTrqq1yRj7koFfIGEnKpt6NjpL3rOzRhs4ryOgA==",
+ "path": "system.reflection.emit.lightweight/4.3.0",
+ "hashPath": "system.reflection.emit.lightweight.4.3.0.nupkg.sha512"
+ },
+ "System.Reflection.Primitives/4.3.0": {
+ "type": "package",
+ "serviceable": true,
+ "sha512": "sha512-5RXItQz5As4xN2/YUDxdpsEkMhvw3e6aNveFXUn4Hl/udNTCNhnKp8lT9fnc3MhvGKh1baak5CovpuQUXHAlIA==",
+ "path": "system.reflection.primitives/4.3.0",
+ "hashPath": "system.reflection.primitives.4.3.0.nupkg.sha512"
+ },
+ "System.Runtime/4.3.0": {
+ "type": "package",
+ "serviceable": true,
+ "sha512": "sha512-JufQi0vPQ0xGnAczR13AUFglDyVYt4Kqnz1AZaiKZ5+GICq0/1MH/mO/eAJHt/mHW1zjKBJd7kV26SrxddAhiw==",
+ "path": "system.runtime/4.3.0",
+ "hashPath": "system.runtime.4.3.0.nupkg.sha512"
+ },
+ "System.Runtime.CompilerServices.Unsafe/4.4.0": {
+ "type": "package",
+ "serviceable": true,
+ "sha512": "sha512-9dLLuBxr5GNmOfl2jSMcsHuteEg32BEfUotmmUkmZjpR3RpVHE8YQwt0ow3p6prwA1ME8WqDVZqrr8z6H8G+Kw==",
+ "path": "system.runtime.compilerservices.unsafe/4.4.0",
+ "hashPath": "system.runtime.compilerservices.unsafe.4.4.0.nupkg.sha512"
+ },
+ "System.Text.Encoding/4.3.0": {
+ "type": "package",
+ "serviceable": true,
+ "sha512": "sha512-BiIg+KWaSDOITze6jGQynxg64naAPtqGHBwDrLaCtixsa5bKiR8dpPOHA7ge3C0JJQizJE+sfkz1wV+BAKAYZw==",
+ "path": "system.text.encoding/4.3.0",
+ "hashPath": "system.text.encoding.4.3.0.nupkg.sha512"
+ },
+ "System.Threading.Tasks/4.3.0": {
+ "type": "package",
+ "serviceable": true,
+ "sha512": "sha512-LbSxKEdOUhVe8BezB/9uOGGppt+nZf6e1VFyw6v3DN6lqitm0OSn2uXMOdtP0M3W4iMcqcivm2J6UgqiwwnXiA==",
+ "path": "system.threading.tasks/4.3.0",
+ "hashPath": "system.threading.tasks.4.3.0.nupkg.sha512"
+ }
+ }
+}
\ No newline at end of file
diff --git a/packages/ServiceStack.Text.5.1.0/lib/netstandard2.0/ServiceStack.Text.dll b/packages/ServiceStack.Text.5.1.0/lib/netstandard2.0/ServiceStack.Text.dll
new file mode 100644
index 0000000000..df96ff2cad
Binary files /dev/null and b/packages/ServiceStack.Text.5.1.0/lib/netstandard2.0/ServiceStack.Text.dll differ
diff --git a/packages/ServiceStack.Text.4.5.8/lib/net45/ServiceStack.Text.xml b/packages/ServiceStack.Text.5.1.0/lib/netstandard2.0/ServiceStack.Text.xml
similarity index 96%
rename from packages/ServiceStack.Text.4.5.8/lib/net45/ServiceStack.Text.xml
rename to packages/ServiceStack.Text.5.1.0/lib/netstandard2.0/ServiceStack.Text.xml
index 3bae85c837..70987c132b 100644
--- a/packages/ServiceStack.Text.4.5.8/lib/net45/ServiceStack.Text.xml
+++ b/packages/ServiceStack.Text.5.1.0/lib/netstandard2.0/ServiceStack.Text.xml
@@ -396,67 +396,6 @@
equality. The type is fully thread-safe.
-
-
- Represents an individual object, allowing access to members by-name
-
-
-
-
- Get or Set the value of a named member for the underlying object
-
-
-
-
- The object represented by this instance
-
-
-
-
- Use the target types definition of equality
-
-
-
-
- Obtain the hash of the target object
-
-
-
-
- Use the target's definition of a string representation
-
-
-
-
- Wraps an individual object, allowing by-name access to that instance
-
-
-
-
- Provides by-name member-access to objects of a given type
-
-
-
-
- Does this type support new instances via a parameterless constructor?
-
-
-
-
- Create a new instance of this type
-
-
-
-
- Provides a type-specific accessor, allowing by-name access for all objects of that type
-
- The accessor is cached internally; a pre-existing accessor may be returned
-
-
-
- Get or set the value of a named member on the target instance
-
-
Generic implementation of object pooling pattern with predefined pool size limit. The main
@@ -562,26 +501,6 @@
pooled memory : 4K * 512 = 4MB
-
-
- Reusable StringBuilder ThreadStatic Cache
-
-
-
-
- Alternative Reusable StringBuilder ThreadStatic Cache
-
-
-
-
- Reusable StringWriter ThreadStatic Cache
-
-
-
-
- Alternative Reusable StringWriter ThreadStatic Cache
-
-
Manages pools of RecyclableMemoryStream objects.
@@ -1122,6 +1041,36 @@
Release the large buffer (either stores it for eventual release or returns it immediately).
+
+
+ Allow Type to be deserialized into late-bould object Types using __type info
+
+
+
+
+ Allow Type to be deserialized into late-bould object Types using __type info
+
+
+
+
+ Reusable StringBuilder ThreadStatic Cache
+
+
+
+
+ Alternative Reusable StringBuilder ThreadStatic Cache
+
+
+
+
+ Reusable StringWriter ThreadStatic Cache
+
+
+
+
+ Alternative Reusable StringWriter ThreadStatic Cache
+
+
A class to allow the conversion of doubles to string representations of
@@ -1199,7 +1148,7 @@
The value.
-
+
Useful extension method to get the Dictionary[string,string] representation of any POCO type.
@@ -1243,18 +1192,6 @@
Tracks how deeply nested we are
-
-
- Add a Property attribute at runtime.
- Not threadsafe, should only add attributes on Startup.
-
-
-
-
- Add a Property attribute at runtime.
- Not threadsafe, should only add attributes on Startup.
-
-
Public Code API to register commercial license for ServiceStack.
@@ -1267,13 +1204,22 @@
- Maps the path of a file in the context of a VS project in a Consle App
+ Maps the path of a file in the context of a VS project in a Console App
the relative path
the absolute path
Assumes static content is two directories above the /bin/ directory,
eg. in a unit test scenario the assembly would be in /bin/Debug/.
+
+
+ Maps the path of a file in the context of a VS 2017+ multi-platform project in a Console App
+
+ the relative path
+ the absolute path
+ Assumes static content is two directories above the /bin/ directory,
+ eg. in a unit test scenario the assembly would be in /bin/Debug/net45
+
Maps the path of a file in the bin\ folder of a self-hosted scenario
@@ -1290,6 +1236,18 @@
the absolute path
Assumes static content is in the parent folder of the /bin/ directory
+
+
+ Add a Property attribute at runtime.
+ Not threadsafe, should only add attributes on Startup.
+
+
+
+
+ Add a Property attribute at runtime.
+ Not threadsafe, should only add attributes on Startup.
+
+
Implement the serializer using a more static approach
diff --git a/packages/SharpCompress.0.18.2/SharpCompress.0.18.2.nupkg b/packages/SharpCompress.0.18.2/SharpCompress.0.18.2.nupkg
deleted file mode 100644
index f70560fad5..0000000000
Binary files a/packages/SharpCompress.0.18.2/SharpCompress.0.18.2.nupkg and /dev/null differ
diff --git a/packages/SharpCompress.0.18.2/lib/net35/SharpCompress.dll b/packages/SharpCompress.0.18.2/lib/net35/SharpCompress.dll
deleted file mode 100644
index e7892331c2..0000000000
Binary files a/packages/SharpCompress.0.18.2/lib/net35/SharpCompress.dll and /dev/null differ
diff --git a/packages/SharpCompress.0.18.2/lib/net45/SharpCompress.dll b/packages/SharpCompress.0.18.2/lib/net45/SharpCompress.dll
deleted file mode 100644
index 01b71a5897..0000000000
Binary files a/packages/SharpCompress.0.18.2/lib/net45/SharpCompress.dll and /dev/null differ
diff --git a/packages/SharpCompress.0.18.2/lib/netstandard1.0/SharpCompress.dll b/packages/SharpCompress.0.18.2/lib/netstandard1.0/SharpCompress.dll
deleted file mode 100644
index d745c40b15..0000000000
Binary files a/packages/SharpCompress.0.18.2/lib/netstandard1.0/SharpCompress.dll and /dev/null differ
diff --git a/packages/SharpCompress.0.18.2/lib/netstandard1.3/SharpCompress.dll b/packages/SharpCompress.0.18.2/lib/netstandard1.3/SharpCompress.dll
deleted file mode 100644
index 2ef2e75ed4..0000000000
Binary files a/packages/SharpCompress.0.18.2/lib/netstandard1.3/SharpCompress.dll and /dev/null differ
diff --git a/packages/SharpCompress.0.21.1/SharpCompress.0.21.1.nupkg b/packages/SharpCompress.0.21.1/SharpCompress.0.21.1.nupkg
new file mode 100644
index 0000000000..5ed42d85a3
Binary files /dev/null and b/packages/SharpCompress.0.21.1/SharpCompress.0.21.1.nupkg differ
diff --git a/packages/SharpCompress.0.21.1/lib/net35/SharpCompress.dll b/packages/SharpCompress.0.21.1/lib/net35/SharpCompress.dll
new file mode 100644
index 0000000000..6a2dbf20ff
Binary files /dev/null and b/packages/SharpCompress.0.21.1/lib/net35/SharpCompress.dll differ
diff --git a/packages/SharpCompress.0.21.1/lib/net45/SharpCompress.dll b/packages/SharpCompress.0.21.1/lib/net45/SharpCompress.dll
new file mode 100644
index 0000000000..df34637029
Binary files /dev/null and b/packages/SharpCompress.0.21.1/lib/net45/SharpCompress.dll differ
diff --git a/packages/SharpCompress.0.21.1/lib/netstandard1.0/SharpCompress.dll b/packages/SharpCompress.0.21.1/lib/netstandard1.0/SharpCompress.dll
new file mode 100644
index 0000000000..40f82c3597
Binary files /dev/null and b/packages/SharpCompress.0.21.1/lib/netstandard1.0/SharpCompress.dll differ
diff --git a/packages/SharpCompress.0.21.1/lib/netstandard1.3/SharpCompress.dll b/packages/SharpCompress.0.21.1/lib/netstandard1.3/SharpCompress.dll
new file mode 100644
index 0000000000..e3c8f38d43
Binary files /dev/null and b/packages/SharpCompress.0.21.1/lib/netstandard1.3/SharpCompress.dll differ
diff --git a/packages/SharpCompress.0.21.1/lib/netstandard2.0/SharpCompress.dll b/packages/SharpCompress.0.21.1/lib/netstandard2.0/SharpCompress.dll
new file mode 100644
index 0000000000..b0fa0c19ef
Binary files /dev/null and b/packages/SharpCompress.0.21.1/lib/netstandard2.0/SharpCompress.dll differ
diff --git a/packages/System.Runtime.CompilerServices.Unsafe.4.5.0/System.Runtime.CompilerServices.Unsafe.4.5.0.nupkg b/packages/System.Runtime.CompilerServices.Unsafe.4.5.0/System.Runtime.CompilerServices.Unsafe.4.5.0.nupkg
deleted file mode 100644
index 6d19129c01..0000000000
Binary files a/packages/System.Runtime.CompilerServices.Unsafe.4.5.0/System.Runtime.CompilerServices.Unsafe.4.5.0.nupkg and /dev/null differ
diff --git a/packages/System.Runtime.CompilerServices.Unsafe.4.5.0/lib/uap10.0.16300/_._ b/packages/System.Runtime.CompilerServices.Unsafe.4.5.0/lib/uap10.0.16300/_._
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/packages/System.Runtime.CompilerServices.Unsafe.4.5.0/ref/uap10.0.16300/_._ b/packages/System.Runtime.CompilerServices.Unsafe.4.5.0/ref/uap10.0.16300/_._
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/packages/System.Runtime.CompilerServices.Unsafe.4.5.0/version.txt b/packages/System.Runtime.CompilerServices.Unsafe.4.5.0/version.txt
deleted file mode 100644
index 47004a02b3..0000000000
--- a/packages/System.Runtime.CompilerServices.Unsafe.4.5.0/version.txt
+++ /dev/null
@@ -1 +0,0 @@
-30ab651fcb4354552bd4891619a0bdd81e0ebdbf
diff --git a/packages/System.Runtime.CompilerServices.Unsafe.4.5.0/.signature.p7s b/packages/System.Runtime.CompilerServices.Unsafe.4.5.1/.signature.p7s
similarity index 88%
rename from packages/System.Runtime.CompilerServices.Unsafe.4.5.0/.signature.p7s
rename to packages/System.Runtime.CompilerServices.Unsafe.4.5.1/.signature.p7s
index 43d3c83875..3bed878f52 100644
Binary files a/packages/System.Runtime.CompilerServices.Unsafe.4.5.0/.signature.p7s and b/packages/System.Runtime.CompilerServices.Unsafe.4.5.1/.signature.p7s differ
diff --git a/packages/System.Runtime.CompilerServices.Unsafe.4.5.0/LICENSE.TXT b/packages/System.Runtime.CompilerServices.Unsafe.4.5.1/LICENSE.TXT
similarity index 100%
rename from packages/System.Runtime.CompilerServices.Unsafe.4.5.0/LICENSE.TXT
rename to packages/System.Runtime.CompilerServices.Unsafe.4.5.1/LICENSE.TXT
diff --git a/packages/System.Runtime.CompilerServices.Unsafe.4.5.1/System.Runtime.CompilerServices.Unsafe.4.5.1.nupkg b/packages/System.Runtime.CompilerServices.Unsafe.4.5.1/System.Runtime.CompilerServices.Unsafe.4.5.1.nupkg
new file mode 100644
index 0000000000..50684fb38e
Binary files /dev/null and b/packages/System.Runtime.CompilerServices.Unsafe.4.5.1/System.Runtime.CompilerServices.Unsafe.4.5.1.nupkg differ
diff --git a/packages/System.Runtime.CompilerServices.Unsafe.4.5.0/THIRD-PARTY-NOTICES.TXT b/packages/System.Runtime.CompilerServices.Unsafe.4.5.1/THIRD-PARTY-NOTICES.TXT
similarity index 100%
rename from packages/System.Runtime.CompilerServices.Unsafe.4.5.0/THIRD-PARTY-NOTICES.TXT
rename to packages/System.Runtime.CompilerServices.Unsafe.4.5.1/THIRD-PARTY-NOTICES.TXT
diff --git a/packages/System.Runtime.CompilerServices.Unsafe.4.5.0/lib/netcoreapp2.0/System.Runtime.CompilerServices.Unsafe.dll b/packages/System.Runtime.CompilerServices.Unsafe.4.5.1/lib/netcoreapp2.0/System.Runtime.CompilerServices.Unsafe.dll
similarity index 73%
rename from packages/System.Runtime.CompilerServices.Unsafe.4.5.0/lib/netcoreapp2.0/System.Runtime.CompilerServices.Unsafe.dll
rename to packages/System.Runtime.CompilerServices.Unsafe.4.5.1/lib/netcoreapp2.0/System.Runtime.CompilerServices.Unsafe.dll
index 55d867e645..a8df002aee 100644
Binary files a/packages/System.Runtime.CompilerServices.Unsafe.4.5.0/lib/netcoreapp2.0/System.Runtime.CompilerServices.Unsafe.dll and b/packages/System.Runtime.CompilerServices.Unsafe.4.5.1/lib/netcoreapp2.0/System.Runtime.CompilerServices.Unsafe.dll differ
diff --git a/packages/System.Runtime.CompilerServices.Unsafe.4.5.0/lib/netcoreapp2.0/System.Runtime.CompilerServices.Unsafe.xml b/packages/System.Runtime.CompilerServices.Unsafe.4.5.1/lib/netcoreapp2.0/System.Runtime.CompilerServices.Unsafe.xml
similarity index 100%
rename from packages/System.Runtime.CompilerServices.Unsafe.4.5.0/lib/netcoreapp2.0/System.Runtime.CompilerServices.Unsafe.xml
rename to packages/System.Runtime.CompilerServices.Unsafe.4.5.1/lib/netcoreapp2.0/System.Runtime.CompilerServices.Unsafe.xml
diff --git a/packages/System.Runtime.CompilerServices.Unsafe.4.5.0/lib/netstandard2.0/System.Runtime.CompilerServices.Unsafe.dll b/packages/System.Runtime.CompilerServices.Unsafe.4.5.1/lib/netstandard1.0/System.Runtime.CompilerServices.Unsafe.dll
similarity index 74%
rename from packages/System.Runtime.CompilerServices.Unsafe.4.5.0/lib/netstandard2.0/System.Runtime.CompilerServices.Unsafe.dll
rename to packages/System.Runtime.CompilerServices.Unsafe.4.5.1/lib/netstandard1.0/System.Runtime.CompilerServices.Unsafe.dll
index 0b45903440..22f108a5f8 100644
Binary files a/packages/System.Runtime.CompilerServices.Unsafe.4.5.0/lib/netstandard2.0/System.Runtime.CompilerServices.Unsafe.dll and b/packages/System.Runtime.CompilerServices.Unsafe.4.5.1/lib/netstandard1.0/System.Runtime.CompilerServices.Unsafe.dll differ
diff --git a/packages/System.Runtime.CompilerServices.Unsafe.4.5.0/lib/netstandard1.0/System.Runtime.CompilerServices.Unsafe.xml b/packages/System.Runtime.CompilerServices.Unsafe.4.5.1/lib/netstandard1.0/System.Runtime.CompilerServices.Unsafe.xml
similarity index 100%
rename from packages/System.Runtime.CompilerServices.Unsafe.4.5.0/lib/netstandard1.0/System.Runtime.CompilerServices.Unsafe.xml
rename to packages/System.Runtime.CompilerServices.Unsafe.4.5.1/lib/netstandard1.0/System.Runtime.CompilerServices.Unsafe.xml
diff --git a/packages/System.Runtime.CompilerServices.Unsafe.4.5.0/lib/netstandard1.0/System.Runtime.CompilerServices.Unsafe.dll b/packages/System.Runtime.CompilerServices.Unsafe.4.5.1/lib/netstandard2.0/System.Runtime.CompilerServices.Unsafe.dll
similarity index 74%
rename from packages/System.Runtime.CompilerServices.Unsafe.4.5.0/lib/netstandard1.0/System.Runtime.CompilerServices.Unsafe.dll
rename to packages/System.Runtime.CompilerServices.Unsafe.4.5.1/lib/netstandard2.0/System.Runtime.CompilerServices.Unsafe.dll
index 63403d72f7..23a1be2557 100644
Binary files a/packages/System.Runtime.CompilerServices.Unsafe.4.5.0/lib/netstandard1.0/System.Runtime.CompilerServices.Unsafe.dll and b/packages/System.Runtime.CompilerServices.Unsafe.4.5.1/lib/netstandard2.0/System.Runtime.CompilerServices.Unsafe.dll differ
diff --git a/packages/System.Runtime.CompilerServices.Unsafe.4.5.0/lib/netstandard2.0/System.Runtime.CompilerServices.Unsafe.xml b/packages/System.Runtime.CompilerServices.Unsafe.4.5.1/lib/netstandard2.0/System.Runtime.CompilerServices.Unsafe.xml
similarity index 100%
rename from packages/System.Runtime.CompilerServices.Unsafe.4.5.0/lib/netstandard2.0/System.Runtime.CompilerServices.Unsafe.xml
rename to packages/System.Runtime.CompilerServices.Unsafe.4.5.1/lib/netstandard2.0/System.Runtime.CompilerServices.Unsafe.xml
diff --git a/packages/System.Runtime.CompilerServices.Unsafe.4.5.0/ref/netstandard1.0/System.Runtime.CompilerServices.Unsafe.dll b/packages/System.Runtime.CompilerServices.Unsafe.4.5.1/ref/netstandard1.0/System.Runtime.CompilerServices.Unsafe.dll
similarity index 61%
rename from packages/System.Runtime.CompilerServices.Unsafe.4.5.0/ref/netstandard1.0/System.Runtime.CompilerServices.Unsafe.dll
rename to packages/System.Runtime.CompilerServices.Unsafe.4.5.1/ref/netstandard1.0/System.Runtime.CompilerServices.Unsafe.dll
index 8761451153..0d58f11ca7 100644
Binary files a/packages/System.Runtime.CompilerServices.Unsafe.4.5.0/ref/netstandard1.0/System.Runtime.CompilerServices.Unsafe.dll and b/packages/System.Runtime.CompilerServices.Unsafe.4.5.1/ref/netstandard1.0/System.Runtime.CompilerServices.Unsafe.dll differ
diff --git a/packages/System.Runtime.CompilerServices.Unsafe.4.5.0/ref/netstandard1.0/System.Runtime.CompilerServices.Unsafe.xml b/packages/System.Runtime.CompilerServices.Unsafe.4.5.1/ref/netstandard1.0/System.Runtime.CompilerServices.Unsafe.xml
similarity index 100%
rename from packages/System.Runtime.CompilerServices.Unsafe.4.5.0/ref/netstandard1.0/System.Runtime.CompilerServices.Unsafe.xml
rename to packages/System.Runtime.CompilerServices.Unsafe.4.5.1/ref/netstandard1.0/System.Runtime.CompilerServices.Unsafe.xml
diff --git a/packages/System.Runtime.CompilerServices.Unsafe.4.5.0/ref/netstandard2.0/System.Runtime.CompilerServices.Unsafe.dll b/packages/System.Runtime.CompilerServices.Unsafe.4.5.1/ref/netstandard2.0/System.Runtime.CompilerServices.Unsafe.dll
similarity index 63%
rename from packages/System.Runtime.CompilerServices.Unsafe.4.5.0/ref/netstandard2.0/System.Runtime.CompilerServices.Unsafe.dll
rename to packages/System.Runtime.CompilerServices.Unsafe.4.5.1/ref/netstandard2.0/System.Runtime.CompilerServices.Unsafe.dll
index e7637d8730..7dffaa9d98 100644
Binary files a/packages/System.Runtime.CompilerServices.Unsafe.4.5.0/ref/netstandard2.0/System.Runtime.CompilerServices.Unsafe.dll and b/packages/System.Runtime.CompilerServices.Unsafe.4.5.1/ref/netstandard2.0/System.Runtime.CompilerServices.Unsafe.dll differ
diff --git a/packages/System.Runtime.CompilerServices.Unsafe.4.5.0/ref/netstandard2.0/System.Runtime.CompilerServices.Unsafe.xml b/packages/System.Runtime.CompilerServices.Unsafe.4.5.1/ref/netstandard2.0/System.Runtime.CompilerServices.Unsafe.xml
similarity index 100%
rename from packages/System.Runtime.CompilerServices.Unsafe.4.5.0/ref/netstandard2.0/System.Runtime.CompilerServices.Unsafe.xml
rename to packages/System.Runtime.CompilerServices.Unsafe.4.5.1/ref/netstandard2.0/System.Runtime.CompilerServices.Unsafe.xml
diff --git a/packages/System.Runtime.CompilerServices.Unsafe.4.5.0/useSharedDesignerContext.txt b/packages/System.Runtime.CompilerServices.Unsafe.4.5.1/useSharedDesignerContext.txt
similarity index 100%
rename from packages/System.Runtime.CompilerServices.Unsafe.4.5.0/useSharedDesignerContext.txt
rename to packages/System.Runtime.CompilerServices.Unsafe.4.5.1/useSharedDesignerContext.txt
diff --git a/packages/System.Runtime.CompilerServices.Unsafe.4.5.1/version.txt b/packages/System.Runtime.CompilerServices.Unsafe.4.5.1/version.txt
new file mode 100644
index 0000000000..69c27cff61
--- /dev/null
+++ b/packages/System.Runtime.CompilerServices.Unsafe.4.5.1/version.txt
@@ -0,0 +1 @@
+7ee84596d92e178bce54c986df31ccc52479e772
diff --git a/packages/System.Threading.Tasks.Extensions.4.5.0/.signature.p7s b/packages/System.Threading.Tasks.Extensions.4.5.0/.signature.p7s
deleted file mode 100644
index 6d8c3555ae..0000000000
Binary files a/packages/System.Threading.Tasks.Extensions.4.5.0/.signature.p7s and /dev/null differ
diff --git a/packages/System.Threading.Tasks.Extensions.4.5.0/LICENSE.TXT b/packages/System.Threading.Tasks.Extensions.4.5.0/LICENSE.TXT
deleted file mode 100644
index 984713a496..0000000000
--- a/packages/System.Threading.Tasks.Extensions.4.5.0/LICENSE.TXT
+++ /dev/null
@@ -1,23 +0,0 @@
-The MIT License (MIT)
-
-Copyright (c) .NET Foundation and Contributors
-
-All rights reserved.
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
diff --git a/packages/System.Threading.Tasks.Extensions.4.5.0/System.Threading.Tasks.Extensions.4.5.0.nupkg b/packages/System.Threading.Tasks.Extensions.4.5.0/System.Threading.Tasks.Extensions.4.5.0.nupkg
deleted file mode 100644
index fc86d88cf5..0000000000
Binary files a/packages/System.Threading.Tasks.Extensions.4.5.0/System.Threading.Tasks.Extensions.4.5.0.nupkg and /dev/null differ
diff --git a/packages/System.Threading.Tasks.Extensions.4.5.0/THIRD-PARTY-NOTICES.TXT b/packages/System.Threading.Tasks.Extensions.4.5.0/THIRD-PARTY-NOTICES.TXT
deleted file mode 100644
index db542ca24f..0000000000
--- a/packages/System.Threading.Tasks.Extensions.4.5.0/THIRD-PARTY-NOTICES.TXT
+++ /dev/null
@@ -1,309 +0,0 @@
-.NET Core uses third-party libraries or other resources that may be
-distributed under licenses different than the .NET Core software.
-
-In the event that we accidentally failed to list a required notice, please
-bring it to our attention. Post an issue or email us:
-
- dotnet@microsoft.com
-
-The attached notices are provided for information only.
-
-License notice for Slicing-by-8
--------------------------------
-
-http://sourceforge.net/projects/slicing-by-8/
-
-Copyright (c) 2004-2006 Intel Corporation - All Rights Reserved
-
-
-This software program is licensed subject to the BSD License, available at
-http://www.opensource.org/licenses/bsd-license.html.
-
-
-License notice for Unicode data
--------------------------------
-
-http://www.unicode.org/copyright.html#License
-
-Copyright © 1991-2017 Unicode, Inc. All rights reserved.
-Distributed under the Terms of Use in http://www.unicode.org/copyright.html.
-
-Permission is hereby granted, free of charge, to any person obtaining
-a copy of the Unicode data files and any associated documentation
-(the "Data Files") or Unicode software and any associated documentation
-(the "Software") to deal in the Data Files or Software
-without restriction, including without limitation the rights to use,
-copy, modify, merge, publish, distribute, and/or sell copies of
-the Data Files or Software, and to permit persons to whom the Data Files
-or Software are furnished to do so, provided that either
-(a) this copyright and permission notice appear with all copies
-of the Data Files or Software, or
-(b) this copyright and permission notice appear in associated
-Documentation.
-
-THE DATA FILES AND SOFTWARE ARE PROVIDED "AS IS", WITHOUT WARRANTY OF
-ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
-WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-NONINFRINGEMENT OF THIRD PARTY RIGHTS.
-IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS
-NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL
-DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
-DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
-TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
-PERFORMANCE OF THE DATA FILES OR SOFTWARE.
-
-Except as contained in this notice, the name of a copyright holder
-shall not be used in advertising or otherwise to promote the sale,
-use or other dealings in these Data Files or Software without prior
-written authorization of the copyright holder.
-
-License notice for Zlib
------------------------
-
-https://github.com/madler/zlib
-http://zlib.net/zlib_license.html
-
-/* zlib.h -- interface of the 'zlib' general purpose compression library
- version 1.2.11, January 15th, 2017
-
- Copyright (C) 1995-2017 Jean-loup Gailly and Mark Adler
-
- This software is provided 'as-is', without any express or implied
- warranty. In no event will the authors be held liable for any damages
- arising from the use of this software.
-
- Permission is granted to anyone to use this software for any purpose,
- including commercial applications, and to alter it and redistribute it
- freely, subject to the following restrictions:
-
- 1. The origin of this software must not be misrepresented; you must not
- claim that you wrote the original software. If you use this software
- in a product, an acknowledgment in the product documentation would be
- appreciated but is not required.
- 2. Altered source versions must be plainly marked as such, and must not be
- misrepresented as being the original software.
- 3. This notice may not be removed or altered from any source distribution.
-
- Jean-loup Gailly Mark Adler
- jloup@gzip.org madler@alumni.caltech.edu
-
-*/
-
-License notice for Mono
--------------------------------
-
-http://www.mono-project.com/docs/about-mono/
-
-Copyright (c) .NET Foundation Contributors
-
-MIT License
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the Software), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-License notice for International Organization for Standardization
------------------------------------------------------------------
-
-Portions (C) International Organization for Standardization 1986:
- Permission to copy in any form is granted for use with
- conforming SGML systems and applications as defined in
- ISO 8879, provided this notice is included in all copies.
-
-License notice for Intel
-------------------------
-
-"Copyright (c) 2004-2006 Intel Corporation - All Rights Reserved
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
-1. Redistributions of source code must retain the above copyright notice, this
-list of conditions and the following disclaimer.
-
-2. Redistributions in binary form must reproduce the above copyright notice,
-this list of conditions and the following disclaimer in the documentation
-and/or other materials provided with the distribution.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
-FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
-OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-License notice for Xamarin and Novell
--------------------------------------
-
-Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com)
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
-
-Copyright (c) 2011 Novell, Inc (http://www.novell.com)
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
-
-Third party notice for W3C
---------------------------
-
-"W3C SOFTWARE AND DOCUMENT NOTICE AND LICENSE
-Status: This license takes effect 13 May, 2015.
-This work is being provided by the copyright holders under the following license.
-License
-By obtaining and/or copying this work, you (the licensee) agree that you have read, understood, and will comply with the following terms and conditions.
-Permission to copy, modify, and distribute this work, with or without modification, for any purpose and without fee or royalty is hereby granted, provided that you include the following on ALL copies of the work or portions thereof, including modifications:
-The full text of this NOTICE in a location viewable to users of the redistributed or derivative work.
-Any pre-existing intellectual property disclaimers, notices, or terms and conditions. If none exist, the W3C Software and Document Short Notice should be included.
-Notice of any changes or modifications, through a copyright statement on the new code or document such as "This software or document includes material copied from or derived from [title and URI of the W3C document]. Copyright © [YEAR] W3C® (MIT, ERCIM, Keio, Beihang)."
-Disclaimers
-THIS WORK IS PROVIDED "AS IS," AND COPYRIGHT HOLDERS MAKE NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF THE SOFTWARE OR DOCUMENT WILL NOT INFRINGE ANY THIRD PARTY PATENTS, COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS.
-COPYRIGHT HOLDERS WILL NOT BE LIABLE FOR ANY DIRECT, INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF ANY USE OF THE SOFTWARE OR DOCUMENT.
-The name and trademarks of copyright holders may NOT be used in advertising or publicity pertaining to the work without specific, written prior permission. Title to copyright in this work will at all times remain with copyright holders."
-
-License notice for Bit Twiddling Hacks
---------------------------------------
-
-Bit Twiddling Hacks
-
-By Sean Eron Anderson
-seander@cs.stanford.edu
-
-Individually, the code snippets here are in the public domain (unless otherwise
-noted) — feel free to use them however you please. The aggregate collection and
-descriptions are © 1997-2005 Sean Eron Anderson. The code and descriptions are
-distributed in the hope that they will be useful, but WITHOUT ANY WARRANTY and
-without even the implied warranty of merchantability or fitness for a particular
-purpose.
-
-License notice for Brotli
---------------------------------------
-
-Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors.
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
-
-compress_fragment.c:
-Copyright (c) 2011, Google Inc.
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are
-met:
-
- * Redistributions of source code must retain the above copyright
-notice, this list of conditions and the following disclaimer.
- * Redistributions in binary form must reproduce the above
-copyright notice, this list of conditions and the following disclaimer
-in the documentation and/or other materials provided with the
-distribution.
- * Neither the name of Google Inc. nor the names of its
-contributors may be used to endorse or promote products derived from
-this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-""AS IS"" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-decode_fuzzer.c:
-Copyright (c) 2015 The Chromium Authors. All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are
-met:
-
- * Redistributions of source code must retain the above copyright
-notice, this list of conditions and the following disclaimer.
- * Redistributions in binary form must reproduce the above
-copyright notice, this list of conditions and the following disclaimer
-in the documentation and/or other materials provided with the
-distribution.
- * Neither the name of Google Inc. nor the names of its
-contributors may be used to endorse or promote products derived from
-this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-""AS IS"" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-
diff --git a/packages/System.Threading.Tasks.Extensions.4.5.0/lib/netcoreapp2.1/_._ b/packages/System.Threading.Tasks.Extensions.4.5.0/lib/netcoreapp2.1/_._
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/packages/System.Threading.Tasks.Extensions.4.5.0/lib/netstandard1.0/System.Threading.Tasks.Extensions.dll b/packages/System.Threading.Tasks.Extensions.4.5.0/lib/netstandard1.0/System.Threading.Tasks.Extensions.dll
deleted file mode 100644
index 55408aec35..0000000000
Binary files a/packages/System.Threading.Tasks.Extensions.4.5.0/lib/netstandard1.0/System.Threading.Tasks.Extensions.dll and /dev/null differ
diff --git a/packages/System.Threading.Tasks.Extensions.4.5.0/lib/netstandard1.0/System.Threading.Tasks.Extensions.xml b/packages/System.Threading.Tasks.Extensions.4.5.0/lib/netstandard1.0/System.Threading.Tasks.Extensions.xml
deleted file mode 100644
index 5e02a99d75..0000000000
--- a/packages/System.Threading.Tasks.Extensions.4.5.0/lib/netstandard1.0/System.Threading.Tasks.Extensions.xml
+++ /dev/null
@@ -1,166 +0,0 @@
-
-
- System.Threading.Tasks.Extensions
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Provides a value type that wraps a and a TResult , only one of which is used.
- The result.
-
-
- Initializes a new instance of the class using the supplied task that represents the operation.
- The task.
- The task argument is null.
-
-
- Initializes a new instance of the class using the supplied result of a successful operation.
- The result.
-
-
- Retrieves a object that represents this .
- The object that is wrapped in this if one exists, or a new object that represents the result.
-
-
- Configures an awaiter for this value.
- true to attempt to marshal the continuation back to the captured context; otherwise, false.
- The configured awaiter.
-
-
- Creates a method builder for use with an async method.
- The created builder.
-
-
- Determines whether the specified object is equal to the current object.
- The object to compare with the current object.
- true if the specified object is equal to the current object; otherwise, false.
-
-
- Determines whether the specified object is equal to the current object.
- The object to compare with the current object.
- true if the specified object is equal to the current object; otherwise, false.
-
-
- Creates an awaiter for this value.
- The awaiter.
-
-
- Returns the hash code for this instance.
- The hash code for the current object.
-
-
- Gets a value that indicates whether this object represents a canceled operation.
- true if this object represents a canceled operation; otherwise, false.
-
-
- Gets a value that indicates whether this object represents a completed operation.
- true if this object represents a completed operation; otherwise, false.
-
-
- Gets a value that indicates whether this object represents a successfully completed operation.
- true if this object represents a successfully completed operation; otherwise, false.
-
-
- Gets a value that indicates whether this object represents a failed operation.
- true if this object represents a failed operation; otherwise, false.
-
-
- Compares two values for equality.
- The first value to compare.
- The second value to compare.
- true if the two values are equal; otherwise, false.
-
-
- Determines whether two values are unequal.
- The first value to compare.
- The seconed value to compare.
- true if the two values are not equal; otherwise, false.
-
-
- Gets the result.
- The result.
-
-
- Returns a string that represents the current object.
- A string that represents the current object.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/packages/System.Threading.Tasks.Extensions.4.5.0/lib/netstandard2.0/System.Threading.Tasks.Extensions.dll b/packages/System.Threading.Tasks.Extensions.4.5.0/lib/netstandard2.0/System.Threading.Tasks.Extensions.dll
deleted file mode 100644
index d98daeaa09..0000000000
Binary files a/packages/System.Threading.Tasks.Extensions.4.5.0/lib/netstandard2.0/System.Threading.Tasks.Extensions.dll and /dev/null differ
diff --git a/packages/System.Threading.Tasks.Extensions.4.5.0/lib/netstandard2.0/System.Threading.Tasks.Extensions.xml b/packages/System.Threading.Tasks.Extensions.4.5.0/lib/netstandard2.0/System.Threading.Tasks.Extensions.xml
deleted file mode 100644
index 5e02a99d75..0000000000
--- a/packages/System.Threading.Tasks.Extensions.4.5.0/lib/netstandard2.0/System.Threading.Tasks.Extensions.xml
+++ /dev/null
@@ -1,166 +0,0 @@
-
-
- System.Threading.Tasks.Extensions
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Provides a value type that wraps a and a TResult , only one of which is used.
- The result.
-
-
- Initializes a new instance of the class using the supplied task that represents the operation.
- The task.
- The task argument is null.
-
-
- Initializes a new instance of the class using the supplied result of a successful operation.
- The result.
-
-
- Retrieves a object that represents this .
- The object that is wrapped in this if one exists, or a new object that represents the result.
-
-
- Configures an awaiter for this value.
- true to attempt to marshal the continuation back to the captured context; otherwise, false.
- The configured awaiter.
-
-
- Creates a method builder for use with an async method.
- The created builder.
-
-
- Determines whether the specified object is equal to the current object.
- The object to compare with the current object.
- true if the specified object is equal to the current object; otherwise, false.
-
-
- Determines whether the specified object is equal to the current object.
- The object to compare with the current object.
- true if the specified object is equal to the current object; otherwise, false.
-
-
- Creates an awaiter for this value.
- The awaiter.
-
-
- Returns the hash code for this instance.
- The hash code for the current object.
-
-
- Gets a value that indicates whether this object represents a canceled operation.
- true if this object represents a canceled operation; otherwise, false.
-
-
- Gets a value that indicates whether this object represents a completed operation.
- true if this object represents a completed operation; otherwise, false.
-
-
- Gets a value that indicates whether this object represents a successfully completed operation.
- true if this object represents a successfully completed operation; otherwise, false.
-
-
- Gets a value that indicates whether this object represents a failed operation.
- true if this object represents a failed operation; otherwise, false.
-
-
- Compares two values for equality.
- The first value to compare.
- The second value to compare.
- true if the two values are equal; otherwise, false.
-
-
- Determines whether two values are unequal.
- The first value to compare.
- The seconed value to compare.
- true if the two values are not equal; otherwise, false.
-
-
- Gets the result.
- The result.
-
-
- Returns a string that represents the current object.
- A string that represents the current object.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/packages/System.Threading.Tasks.Extensions.4.5.0/lib/portable-net45+win8+wp8+wpa81/System.Threading.Tasks.Extensions.dll b/packages/System.Threading.Tasks.Extensions.4.5.0/lib/portable-net45+win8+wp8+wpa81/System.Threading.Tasks.Extensions.dll
deleted file mode 100644
index 55408aec35..0000000000
Binary files a/packages/System.Threading.Tasks.Extensions.4.5.0/lib/portable-net45+win8+wp8+wpa81/System.Threading.Tasks.Extensions.dll and /dev/null differ
diff --git a/packages/System.Threading.Tasks.Extensions.4.5.0/lib/portable-net45+win8+wp8+wpa81/System.Threading.Tasks.Extensions.xml b/packages/System.Threading.Tasks.Extensions.4.5.0/lib/portable-net45+win8+wp8+wpa81/System.Threading.Tasks.Extensions.xml
deleted file mode 100644
index 5e02a99d75..0000000000
--- a/packages/System.Threading.Tasks.Extensions.4.5.0/lib/portable-net45+win8+wp8+wpa81/System.Threading.Tasks.Extensions.xml
+++ /dev/null
@@ -1,166 +0,0 @@
-
-
- System.Threading.Tasks.Extensions
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Provides a value type that wraps a and a TResult , only one of which is used.
- The result.
-
-
- Initializes a new instance of the class using the supplied task that represents the operation.
- The task.
- The task argument is null.
-
-
- Initializes a new instance of the class using the supplied result of a successful operation.
- The result.
-
-
- Retrieves a object that represents this .
- The object that is wrapped in this if one exists, or a new object that represents the result.
-
-
- Configures an awaiter for this value.
- true to attempt to marshal the continuation back to the captured context; otherwise, false.
- The configured awaiter.
-
-
- Creates a method builder for use with an async method.
- The created builder.
-
-
- Determines whether the specified object is equal to the current object.
- The object to compare with the current object.
- true if the specified object is equal to the current object; otherwise, false.
-
-
- Determines whether the specified object is equal to the current object.
- The object to compare with the current object.
- true if the specified object is equal to the current object; otherwise, false.
-
-
- Creates an awaiter for this value.
- The awaiter.
-
-
- Returns the hash code for this instance.
- The hash code for the current object.
-
-
- Gets a value that indicates whether this object represents a canceled operation.
- true if this object represents a canceled operation; otherwise, false.
-
-
- Gets a value that indicates whether this object represents a completed operation.
- true if this object represents a completed operation; otherwise, false.
-
-
- Gets a value that indicates whether this object represents a successfully completed operation.
- true if this object represents a successfully completed operation; otherwise, false.
-
-
- Gets a value that indicates whether this object represents a failed operation.
- true if this object represents a failed operation; otherwise, false.
-
-
- Compares two values for equality.
- The first value to compare.
- The second value to compare.
- true if the two values are equal; otherwise, false.
-
-
- Determines whether two values are unequal.
- The first value to compare.
- The seconed value to compare.
- true if the two values are not equal; otherwise, false.
-
-
- Gets the result.
- The result.
-
-
- Returns a string that represents the current object.
- A string that represents the current object.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/packages/System.Threading.Tasks.Extensions.4.5.0/lib/uap10.0.16300/_._ b/packages/System.Threading.Tasks.Extensions.4.5.0/lib/uap10.0.16300/_._
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/packages/System.Threading.Tasks.Extensions.4.5.0/ref/netcoreapp2.1/_._ b/packages/System.Threading.Tasks.Extensions.4.5.0/ref/netcoreapp2.1/_._
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/packages/System.Threading.Tasks.Extensions.4.5.0/ref/netstandard1.0/System.Threading.Tasks.Extensions.dll b/packages/System.Threading.Tasks.Extensions.4.5.0/ref/netstandard1.0/System.Threading.Tasks.Extensions.dll
deleted file mode 100644
index 5acf022f93..0000000000
Binary files a/packages/System.Threading.Tasks.Extensions.4.5.0/ref/netstandard1.0/System.Threading.Tasks.Extensions.dll and /dev/null differ
diff --git a/packages/System.Threading.Tasks.Extensions.4.5.0/ref/netstandard1.0/System.Threading.Tasks.Extensions.xml b/packages/System.Threading.Tasks.Extensions.4.5.0/ref/netstandard1.0/System.Threading.Tasks.Extensions.xml
deleted file mode 100644
index 5e02a99d75..0000000000
--- a/packages/System.Threading.Tasks.Extensions.4.5.0/ref/netstandard1.0/System.Threading.Tasks.Extensions.xml
+++ /dev/null
@@ -1,166 +0,0 @@
-
-
- System.Threading.Tasks.Extensions
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Provides a value type that wraps a and a TResult , only one of which is used.
- The result.
-
-
- Initializes a new instance of the class using the supplied task that represents the operation.
- The task.
- The task argument is null.
-
-
- Initializes a new instance of the class using the supplied result of a successful operation.
- The result.
-
-
- Retrieves a object that represents this .
- The object that is wrapped in this if one exists, or a new object that represents the result.
-
-
- Configures an awaiter for this value.
- true to attempt to marshal the continuation back to the captured context; otherwise, false.
- The configured awaiter.
-
-
- Creates a method builder for use with an async method.
- The created builder.
-
-
- Determines whether the specified object is equal to the current object.
- The object to compare with the current object.
- true if the specified object is equal to the current object; otherwise, false.
-
-
- Determines whether the specified object is equal to the current object.
- The object to compare with the current object.
- true if the specified object is equal to the current object; otherwise, false.
-
-
- Creates an awaiter for this value.
- The awaiter.
-
-
- Returns the hash code for this instance.
- The hash code for the current object.
-
-
- Gets a value that indicates whether this object represents a canceled operation.
- true if this object represents a canceled operation; otherwise, false.
-
-
- Gets a value that indicates whether this object represents a completed operation.
- true if this object represents a completed operation; otherwise, false.
-
-
- Gets a value that indicates whether this object represents a successfully completed operation.
- true if this object represents a successfully completed operation; otherwise, false.
-
-
- Gets a value that indicates whether this object represents a failed operation.
- true if this object represents a failed operation; otherwise, false.
-
-
- Compares two values for equality.
- The first value to compare.
- The second value to compare.
- true if the two values are equal; otherwise, false.
-
-
- Determines whether two values are unequal.
- The first value to compare.
- The seconed value to compare.
- true if the two values are not equal; otherwise, false.
-
-
- Gets the result.
- The result.
-
-
- Returns a string that represents the current object.
- A string that represents the current object.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/packages/System.Threading.Tasks.Extensions.4.5.0/ref/netstandard2.0/System.Threading.Tasks.Extensions.dll b/packages/System.Threading.Tasks.Extensions.4.5.0/ref/netstandard2.0/System.Threading.Tasks.Extensions.dll
deleted file mode 100644
index 6be0435650..0000000000
Binary files a/packages/System.Threading.Tasks.Extensions.4.5.0/ref/netstandard2.0/System.Threading.Tasks.Extensions.dll and /dev/null differ
diff --git a/packages/System.Threading.Tasks.Extensions.4.5.0/ref/netstandard2.0/System.Threading.Tasks.Extensions.xml b/packages/System.Threading.Tasks.Extensions.4.5.0/ref/netstandard2.0/System.Threading.Tasks.Extensions.xml
deleted file mode 100644
index 5e02a99d75..0000000000
--- a/packages/System.Threading.Tasks.Extensions.4.5.0/ref/netstandard2.0/System.Threading.Tasks.Extensions.xml
+++ /dev/null
@@ -1,166 +0,0 @@
-
-
- System.Threading.Tasks.Extensions
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Provides a value type that wraps a and a TResult , only one of which is used.
- The result.
-
-
- Initializes a new instance of the class using the supplied task that represents the operation.
- The task.
- The task argument is null.
-
-
- Initializes a new instance of the class using the supplied result of a successful operation.
- The result.
-
-
- Retrieves a object that represents this .
- The object that is wrapped in this if one exists, or a new object that represents the result.
-
-
- Configures an awaiter for this value.
- true to attempt to marshal the continuation back to the captured context; otherwise, false.
- The configured awaiter.
-
-
- Creates a method builder for use with an async method.
- The created builder.
-
-
- Determines whether the specified object is equal to the current object.
- The object to compare with the current object.
- true if the specified object is equal to the current object; otherwise, false.
-
-
- Determines whether the specified object is equal to the current object.
- The object to compare with the current object.
- true if the specified object is equal to the current object; otherwise, false.
-
-
- Creates an awaiter for this value.
- The awaiter.
-
-
- Returns the hash code for this instance.
- The hash code for the current object.
-
-
- Gets a value that indicates whether this object represents a canceled operation.
- true if this object represents a canceled operation; otherwise, false.
-
-
- Gets a value that indicates whether this object represents a completed operation.
- true if this object represents a completed operation; otherwise, false.
-
-
- Gets a value that indicates whether this object represents a successfully completed operation.
- true if this object represents a successfully completed operation; otherwise, false.
-
-
- Gets a value that indicates whether this object represents a failed operation.
- true if this object represents a failed operation; otherwise, false.
-
-
- Compares two values for equality.
- The first value to compare.
- The second value to compare.
- true if the two values are equal; otherwise, false.
-
-
- Determines whether two values are unequal.
- The first value to compare.
- The seconed value to compare.
- true if the two values are not equal; otherwise, false.
-
-
- Gets the result.
- The result.
-
-
- Returns a string that represents the current object.
- A string that represents the current object.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/packages/System.Threading.Tasks.Extensions.4.5.0/ref/uap10.0.16300/_._ b/packages/System.Threading.Tasks.Extensions.4.5.0/ref/uap10.0.16300/_._
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/packages/System.Threading.Tasks.Extensions.4.5.0/useSharedDesignerContext.txt b/packages/System.Threading.Tasks.Extensions.4.5.0/useSharedDesignerContext.txt
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/packages/System.Threading.Tasks.Extensions.4.5.0/version.txt b/packages/System.Threading.Tasks.Extensions.4.5.0/version.txt
deleted file mode 100644
index 47004a02b3..0000000000
--- a/packages/System.Threading.Tasks.Extensions.4.5.0/version.txt
+++ /dev/null
@@ -1 +0,0 @@
-30ab651fcb4354552bd4891619a0bdd81e0ebdbf