diff --git a/MediaBrowser.Controller/Collections/ICollectionManager.cs b/MediaBrowser.Controller/Collections/ICollectionManager.cs
index b63c49f99..fdb2a4975 100644
--- a/MediaBrowser.Controller/Collections/ICollectionManager.cs
+++ b/MediaBrowser.Controller/Collections/ICollectionManager.cs
@@ -38,5 +38,12 @@ namespace MediaBrowser.Controller.Collections
/// The user.
/// IEnumerable{BaseItem}.
IEnumerable CollapseItemsWithinBoxSets(IEnumerable items, User user);
+
+ ///
+ /// Gets the collections folder.
+ ///
+ /// The user identifier.
+ /// Folder.
+ Folder GetCollectionsFolder(string userId);
}
}
diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs
index a2ff1b4fd..524d7097b 100644
--- a/MediaBrowser.Controller/Entities/BaseItem.cs
+++ b/MediaBrowser.Controller/Entities/BaseItem.cs
@@ -134,6 +134,11 @@ namespace MediaBrowser.Controller.Entities
}
}
+ public virtual bool IsHiddenFromUser(User user)
+ {
+ return false;
+ }
+
[IgnoreDataMember]
public virtual bool IsOwnedItem
{
diff --git a/MediaBrowser.Controller/Entities/Folder.cs b/MediaBrowser.Controller/Entities/Folder.cs
index f503a5ff4..e54e72cd8 100644
--- a/MediaBrowser.Controller/Entities/Folder.cs
+++ b/MediaBrowser.Controller/Entities/Folder.cs
@@ -809,7 +809,10 @@ namespace MediaBrowser.Controller.Entities
{
if (filter == null || filter(child))
{
- list.Add(child);
+ if (!child.IsHiddenFromUser(user))
+ {
+ list.Add(child);
+ }
}
if (recursive && child.IsFolder)
diff --git a/MediaBrowser.Model/Configuration/NotificationOptions.cs b/MediaBrowser.Model/Configuration/NotificationOptions.cs
index 5aac1652f..dd523d947 100644
--- a/MediaBrowser.Model/Configuration/NotificationOptions.cs
+++ b/MediaBrowser.Model/Configuration/NotificationOptions.cs
@@ -1,6 +1,4 @@
-using System;
-using System.Linq;
-using MediaBrowser.Model.Extensions;
+using MediaBrowser.Model.Extensions;
namespace MediaBrowser.Model.Configuration
{
@@ -90,7 +88,7 @@ namespace MediaBrowser.Model.Configuration
NotificationOption opt = GetOptions(notificationType);
return opt == null ||
- !opt.DisabledServices.Contains(service, StringComparer.OrdinalIgnoreCase);
+ !ListHelper.ContainsIgnoreCase(opt.DisabledServices, service);
}
public bool IsEnabledToMonitorUser(string type, string userId)
@@ -98,7 +96,7 @@ namespace MediaBrowser.Model.Configuration
NotificationOption opt = GetOptions(type);
return opt != null && opt.Enabled &&
- !opt.DisabledMonitorUsers.Contains(userId, StringComparer.OrdinalIgnoreCase);
+ !ListHelper.ContainsIgnoreCase(opt.DisabledMonitorUsers, userId);
}
public bool IsEnabledToSendToUser(string type, string userId, UserConfiguration userConfig)
@@ -117,7 +115,7 @@ namespace MediaBrowser.Model.Configuration
return true;
}
- return opt.SendToUsers.Contains(userId, StringComparer.OrdinalIgnoreCase);
+ return ListHelper.ContainsIgnoreCase(opt.SendToUsers, userId);
}
return false;
diff --git a/MediaBrowser.Model/Configuration/UserConfiguration.cs b/MediaBrowser.Model/Configuration/UserConfiguration.cs
index 84ce2747a..24a41863e 100644
--- a/MediaBrowser.Model/Configuration/UserConfiguration.cs
+++ b/MediaBrowser.Model/Configuration/UserConfiguration.cs
@@ -72,6 +72,7 @@ namespace MediaBrowser.Model.Configuration
public UnratedItem[] BlockUnratedItems { get; set; }
public SubtitlePlaybackMode SubtitleMode { get; set; }
+ public bool DisplayCollectionsView { get; set; }
///
/// Initializes a new instance of the class.
@@ -92,6 +93,8 @@ namespace MediaBrowser.Model.Configuration
BlockUnratedItems = new UnratedItem[] { };
ExcludeFoldersFromGrouping = new string[] { };
+
+ DisplayCollectionsView = true;
}
}
}
diff --git a/MediaBrowser.Model/Dlna/DeviceProfile.cs b/MediaBrowser.Model/Dlna/DeviceProfile.cs
index 807e04427..deaa30714 100644
--- a/MediaBrowser.Model/Dlna/DeviceProfile.cs
+++ b/MediaBrowser.Model/Dlna/DeviceProfile.cs
@@ -115,7 +115,7 @@ namespace MediaBrowser.Model.Dlna
public TranscodingProfile GetAudioTranscodingProfile(string container, string audioCodec)
{
- container = (container ?? string.Empty).TrimStart('.');
+ container = StringHelper.TrimStart((container ?? string.Empty), '.');
foreach (var i in TranscodingProfiles)
{
@@ -141,7 +141,7 @@ namespace MediaBrowser.Model.Dlna
public TranscodingProfile GetVideoTranscodingProfile(string container, string audioCodec, string videoCodec)
{
- container = (container ?? string.Empty).TrimStart('.');
+ container = StringHelper.TrimStart((container ?? string.Empty), '.');
foreach (var i in TranscodingProfiles)
{
@@ -172,7 +172,7 @@ namespace MediaBrowser.Model.Dlna
public ResponseProfile GetAudioMediaProfile(string container, string audioCodec, int? audioChannels, int? audioBitrate)
{
- container = (container ?? string.Empty).TrimStart('.');
+ container = StringHelper.TrimStart((container ?? string.Empty), '.');
foreach (var i in ResponseProfiles)
{
@@ -217,7 +217,7 @@ namespace MediaBrowser.Model.Dlna
public ResponseProfile GetImageMediaProfile(string container, int? width, int? height)
{
- container = (container ?? string.Empty).TrimStart('.');
+ container = StringHelper.TrimStart((container ?? string.Empty), '.');
foreach (var i in ResponseProfiles)
{
@@ -270,7 +270,7 @@ namespace MediaBrowser.Model.Dlna
TransportStreamTimestamp timestamp,
bool? isAnamorphic)
{
- container = (container ?? string.Empty).TrimStart('.');
+ container = StringHelper.TrimStart((container ?? string.Empty), '.');
foreach (var i in ResponseProfiles)
{
diff --git a/MediaBrowser.Model/Dlna/StreamBuilder.cs b/MediaBrowser.Model/Dlna/StreamBuilder.cs
index 877570844..8aadd428f 100644
--- a/MediaBrowser.Model/Dlna/StreamBuilder.cs
+++ b/MediaBrowser.Model/Dlna/StreamBuilder.cs
@@ -136,7 +136,12 @@ namespace MediaBrowser.Model.Dlna
foreach (CodecProfile i in options.Profile.CodecProfiles)
{
if (i.Type == CodecType.Audio && i.ContainsCodec(audioCodec))
- conditions.AddRange(i.Conditions);
+ {
+ foreach (var c in i.Conditions)
+ {
+ conditions.Add(c);
+ }
+ }
}
int? audioChannels = audioStream.Channels;
@@ -195,7 +200,12 @@ namespace MediaBrowser.Model.Dlna
List audioTranscodingConditions = new List();
foreach (CodecProfile i in audioCodecProfiles)
- audioTranscodingConditions.AddRange(i.Conditions);
+ {
+ foreach (var c in i.Conditions)
+ {
+ audioTranscodingConditions.Add(c);
+ }
+ }
ApplyTranscodingConditions(playlistItem, audioTranscodingConditions);
@@ -276,7 +286,10 @@ namespace MediaBrowser.Model.Dlna
{
if (i.Type == CodecType.Video && i.ContainsCodec(transcodingProfile.VideoCodec))
{
- videoTranscodingConditions.AddRange(i.Conditions);
+ foreach (var c in i.Conditions)
+ {
+ videoTranscodingConditions.Add(c);
+ }
break;
}
}
@@ -287,7 +300,10 @@ namespace MediaBrowser.Model.Dlna
{
if (i.Type == CodecType.VideoAudio && i.ContainsCodec(transcodingProfile.AudioCodec))
{
- audioTranscodingConditions.AddRange(i.Conditions);
+ foreach (var c in i.Conditions)
+ {
+ audioTranscodingConditions.Add(c);
+ }
break;
}
}
@@ -363,7 +379,10 @@ namespace MediaBrowser.Model.Dlna
if (i.Type == DlnaProfileType.Video &&
ListHelper.ContainsIgnoreCase(i.GetContainers(), container))
{
- conditions.AddRange(i.Conditions);
+ foreach (var c in i.Conditions)
+ {
+ conditions.Add(c);
+ }
}
}
@@ -405,7 +424,12 @@ namespace MediaBrowser.Model.Dlna
foreach (CodecProfile i in profile.CodecProfiles)
{
if (i.Type == CodecType.Video && i.ContainsCodec(videoCodec))
- conditions.AddRange(i.Conditions);
+ {
+ foreach (var c in i.Conditions)
+ {
+ conditions.Add(c);
+ }
+ }
}
foreach (ProfileCondition i in conditions)
@@ -429,7 +453,12 @@ namespace MediaBrowser.Model.Dlna
foreach (CodecProfile i in profile.CodecProfiles)
{
if (i.Type == CodecType.VideoAudio && i.ContainsCodec(audioCodec))
- conditions.AddRange(i.Conditions);
+ {
+ foreach (var c in i.Conditions)
+ {
+ conditions.Add(c);
+ }
+ }
}
foreach (ProfileCondition i in conditions)
diff --git a/MediaBrowser.Model/Dlna/StreamInfo.cs b/MediaBrowser.Model/Dlna/StreamInfo.cs
index 8d507ae37..b8c256b25 100644
--- a/MediaBrowser.Model/Dlna/StreamInfo.cs
+++ b/MediaBrowser.Model/Dlna/StreamInfo.cs
@@ -305,8 +305,14 @@ namespace MediaBrowser.Model.Dlna
{
int? totalBitrate = TargetTotalBitrate;
+ double totalSeconds = RunTimeTicks.Value;
+ // Convert to ms
+ totalSeconds /= 10000;
+ // Convert to seconds
+ totalSeconds /= 1000;
+
return totalBitrate.HasValue ?
- Convert.ToInt64(totalBitrate.Value * TimeSpan.FromTicks(RunTimeTicks.Value).TotalSeconds) :
+ Convert.ToInt64(totalBitrate.Value * totalSeconds) :
(long?)null;
}
@@ -375,11 +381,14 @@ namespace MediaBrowser.Model.Dlna
Height = videoStream.Height.Value
};
+ double? maxWidth = MaxWidth.HasValue ? (double)MaxWidth.Value : (double?)null;
+ double? maxHeight = MaxHeight.HasValue ? (double)MaxHeight.Value : (double?)null;
+
ImageSize newSize = DrawingUtils.Resize(size,
null,
null,
- MaxWidth,
- MaxHeight);
+ maxWidth,
+ maxHeight);
return Convert.ToInt32(newSize.Width);
}
@@ -402,11 +411,14 @@ namespace MediaBrowser.Model.Dlna
Height = videoStream.Height.Value
};
+ double? maxWidth = MaxWidth.HasValue ? (double)MaxWidth.Value : (double?)null;
+ double? maxHeight = MaxHeight.HasValue ? (double)MaxHeight.Value : (double?)null;
+
ImageSize newSize = DrawingUtils.Resize(size,
null,
null,
- MaxWidth,
- MaxHeight);
+ maxWidth,
+ maxHeight);
return Convert.ToInt32(newSize.Height);
}
diff --git a/MediaBrowser.Model/Extensions/StringHelper.cs b/MediaBrowser.Model/Extensions/StringHelper.cs
index 1c086655f..2eae56cd4 100644
--- a/MediaBrowser.Model/Extensions/StringHelper.cs
+++ b/MediaBrowser.Model/Extensions/StringHelper.cs
@@ -59,5 +59,16 @@ namespace MediaBrowser.Model.Extensions
{
return val.ToString(CultureInfo.InvariantCulture);
}
+
+ ///
+ /// Trims the start.
+ ///
+ /// The string.
+ /// The c.
+ /// System.String.
+ public static string TrimStart(string str, char c)
+ {
+ return str.TrimStart(c);
+ }
}
}
diff --git a/MediaBrowser.Model/Notifications/Notification.cs b/MediaBrowser.Model/Notifications/Notification.cs
index 731c3d303..5439b838d 100644
--- a/MediaBrowser.Model/Notifications/Notification.cs
+++ b/MediaBrowser.Model/Notifications/Notification.cs
@@ -19,10 +19,5 @@ namespace MediaBrowser.Model.Notifications
public string Url { get; set; }
public NotificationLevel Level { get; set; }
-
- public Notification()
- {
- Date = DateTime.UtcNow;
- }
}
}
diff --git a/MediaBrowser.Server.Implementations/Collections/CollectionManager.cs b/MediaBrowser.Server.Implementations/Collections/CollectionManager.cs
index a69f9e94b..d9323573d 100644
--- a/MediaBrowser.Server.Implementations/Collections/CollectionManager.cs
+++ b/MediaBrowser.Server.Implementations/Collections/CollectionManager.cs
@@ -4,13 +4,13 @@ using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Movies;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Providers;
+using MoreLinq;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
-using MoreLinq;
namespace MediaBrowser.Server.Implementations.Collections
{
@@ -27,6 +27,12 @@ namespace MediaBrowser.Server.Implementations.Collections
_iLibraryMonitor = iLibraryMonitor;
}
+ public Folder GetCollectionsFolder(string userId)
+ {
+ return _libraryManager.RootFolder.Children.Concat(_libraryManager.RootFolder.GetHiddenChildren()).OfType()
+ .FirstOrDefault();
+ }
+
public async Task CreateCollection(CollectionCreationOptions options)
{
var name = options.Name;
@@ -104,8 +110,7 @@ namespace MediaBrowser.Server.Implementations.Collections
}
}
- return _libraryManager.RootFolder.Children.OfType().FirstOrDefault() ??
- _libraryManager.RootFolder.GetHiddenChildren().OfType().FirstOrDefault();
+ return GetCollectionsFolder(string.Empty);
}
public async Task AddToCollection(Guid collectionId, IEnumerable ids)
diff --git a/MediaBrowser.Server.Implementations/Collections/ManualCollectionsFolder.cs b/MediaBrowser.Server.Implementations/Collections/ManualCollectionsFolder.cs
index c58b9181b..03479d838 100644
--- a/MediaBrowser.Server.Implementations/Collections/ManualCollectionsFolder.cs
+++ b/MediaBrowser.Server.Implementations/Collections/ManualCollectionsFolder.cs
@@ -28,6 +28,11 @@ namespace MediaBrowser.Server.Implementations.Collections
}
}
+ public override bool IsHiddenFromUser(User user)
+ {
+ return true;
+ }
+
public override string CollectionType
{
get { return Model.Entities.CollectionType.BoxSets; }
diff --git a/MediaBrowser.Server.Implementations/Library/UserViewManager.cs b/MediaBrowser.Server.Implementations/Library/UserViewManager.cs
index 9ac82690b..24e4f0ef4 100644
--- a/MediaBrowser.Server.Implementations/Library/UserViewManager.cs
+++ b/MediaBrowser.Server.Implementations/Library/UserViewManager.cs
@@ -62,28 +62,29 @@ namespace MediaBrowser.Server.Implementations.Library
if (recursiveChildren.OfType().Any())
{
- list.Add(await GetUserView(CollectionType.TvShows, user, cancellationToken).ConfigureAwait(false));
+ list.Add(await GetUserView(CollectionType.TvShows, user, string.Empty, cancellationToken).ConfigureAwait(false));
}
if (recursiveChildren.OfType().Any() ||
recursiveChildren.OfType().Any())
{
- list.Add(await GetUserView(CollectionType.Music, user, cancellationToken).ConfigureAwait(false));
+ list.Add(await GetUserView(CollectionType.Music, user, string.Empty, cancellationToken).ConfigureAwait(false));
}
if (recursiveChildren.OfType().Any())
{
- list.Add(await GetUserView(CollectionType.Movies, user, cancellationToken).ConfigureAwait(false));
+ list.Add(await GetUserView(CollectionType.Movies, user, string.Empty, cancellationToken).ConfigureAwait(false));
}
if (recursiveChildren.OfType().Any())
{
- list.Add(await GetUserView(CollectionType.Games, user, cancellationToken).ConfigureAwait(false));
+ list.Add(await GetUserView(CollectionType.Games, user, string.Empty, cancellationToken).ConfigureAwait(false));
}
- if (recursiveChildren.OfType().Any())
+ if (user.Configuration.DisplayCollectionsView ||
+ recursiveChildren.OfType().Any())
{
- list.Add(await GetUserView(CollectionType.BoxSets, user, cancellationToken).ConfigureAwait(false));
+ list.Add(await GetUserView(CollectionType.BoxSets, user, "zzz_" + CollectionType.BoxSets, cancellationToken).ConfigureAwait(false));
}
if (query.IncludeExternalContent)
@@ -116,11 +117,11 @@ namespace MediaBrowser.Server.Implementations.Library
return list.OrderBy(i => i.SortName);
}
- private Task GetUserView(string type, User user, CancellationToken cancellationToken)
+ private Task GetUserView(string type, User user, string sortName, CancellationToken cancellationToken)
{
var name = _localizationManager.GetLocalizedString("ViewType" + type);
- return _libraryManager.GetNamedView(name, type, string.Empty, cancellationToken);
+ return _libraryManager.GetNamedView(name, type, sortName, cancellationToken);
}
}
}