< Summary - Jellyfin

Information
Class: Emby.Server.Implementations.Library.UserViewManager
Assembly: Emby.Server.Implementations
File(s): /srv/git/jellyfin/Emby.Server.Implementations/Library/UserViewManager.cs
Line coverage
30%
Covered lines: 54
Uncovered lines: 126
Coverable lines: 180
Total lines: 380
Line coverage: 30%
Branch coverage
15%
Covered branches: 15
Total branches: 94
Branch coverage: 15.9%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Coverage history

Coverage history 0 25 50 75 100

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor(...)100%11100%
GetUserViews(...)44.11%54.73473.84%
GetUserSubViewWithName(...)100%210%
GetUserSubView(...)100%210%
GetUserView(...)0%4260%
GetUserView(...)100%210%
GetLatestItems(...)0%156120%
GetItemsForLatestItems(...)0%1806420%

File(s)

/srv/git/jellyfin/Emby.Server.Implementations/Library/UserViewManager.cs

#LineLine coverage
 1#nullable disable
 2
 3#pragma warning disable CS1591
 4
 5using System;
 6using System.Collections.Generic;
 7using System.Linq;
 8using System.Threading;
 9using Jellyfin.Data.Entities;
 10using Jellyfin.Data.Enums;
 11using Jellyfin.Extensions;
 12using MediaBrowser.Controller.Channels;
 13using MediaBrowser.Controller.Configuration;
 14using MediaBrowser.Controller.Dto;
 15using MediaBrowser.Controller.Entities;
 16using MediaBrowser.Controller.Library;
 17using MediaBrowser.Controller.LiveTv;
 18using MediaBrowser.Model.Channels;
 19using MediaBrowser.Model.Globalization;
 20using MediaBrowser.Model.Library;
 21using MediaBrowser.Model.Querying;
 22
 23namespace Emby.Server.Implementations.Library
 24{
 25    public class UserViewManager : IUserViewManager
 26    {
 27        private readonly ILibraryManager _libraryManager;
 28        private readonly ILocalizationManager _localizationManager;
 29
 30        private readonly IChannelManager _channelManager;
 31        private readonly ILiveTvManager _liveTvManager;
 32        private readonly IServerConfigurationManager _config;
 33
 34        public UserViewManager(ILibraryManager libraryManager, ILocalizationManager localizationManager, IChannelManager
 35        {
 2236            _libraryManager = libraryManager;
 2237            _localizationManager = localizationManager;
 2238            _channelManager = channelManager;
 2239            _liveTvManager = liveTvManager;
 2240            _config = config;
 2241        }
 42
 43        public Folder[] GetUserViews(UserViewQuery query)
 44        {
 145            var user = query.User;
 46
 147            var folders = _libraryManager.GetUserRootFolder()
 148                .GetChildren(user, true)
 149                .OfType<Folder>()
 150                .ToList();
 51
 152            var groupedFolders = new List<ICollectionFolder>();
 153            var list = new List<Folder>();
 54
 455            foreach (var folder in folders)
 56            {
 157                var collectionFolder = folder as ICollectionFolder;
 158                var folderViewType = collectionFolder?.CollectionType;
 59
 60                // Playlist library requires special handling because the folder only references user playlists
 161                if (folderViewType == CollectionType.playlists)
 62                {
 163                    var items = folder.GetItemList(new InternalItemsQuery(user)
 164                    {
 165                        ParentId = folder.ParentId
 166                    });
 67
 168                    if (!items.Any(item => item.IsVisible(user)))
 69                    {
 70                        continue;
 71                    }
 72                }
 73
 074                if (UserView.IsUserSpecific(folder))
 75                {
 076                    list.Add(_libraryManager.GetNamedView(user, folder.Name, folder.Id, folderViewType, null));
 077                    continue;
 78                }
 79
 080                if (collectionFolder is not null && UserView.IsEligibleForGrouping(folder) && user.IsFolderGrouped(folde
 81                {
 082                    groupedFolders.Add(collectionFolder);
 083                    continue;
 84                }
 85
 086                if (query.PresetViews.Contains(folderViewType))
 87                {
 088                    list.Add(GetUserView(folder, folderViewType, string.Empty));
 89                }
 90                else
 91                {
 092                    list.Add(folder);
 93                }
 94            }
 95
 696            foreach (var viewType in new[] { CollectionType.movies, CollectionType.tvshows })
 97            {
 298                var parents = groupedFolders.Where(i => i.CollectionType == viewType || i.CollectionType is null)
 299                    .ToList();
 100
 2101                if (parents.Count > 0)
 102                {
 0103                    var localizationKey = viewType == CollectionType.tvshows
 0104                        ? "TvShows"
 0105                        : "Movies";
 106
 0107                    list.Add(GetUserView(parents, viewType, localizationKey, string.Empty, user, query.PresetViews));
 108                }
 109            }
 110
 1111            if (_config.Configuration.EnableFolderView)
 112            {
 0113                var name = _localizationManager.GetLocalizedString("Folders");
 0114                list.Add(_libraryManager.GetNamedView(name, CollectionType.folders, string.Empty));
 115            }
 116
 1117            if (query.IncludeExternalContent)
 118            {
 1119                var channelResult = _channelManager.GetChannelsInternalAsync(new ChannelQuery
 1120                {
 1121                    UserId = user.Id
 1122                }).GetAwaiter().GetResult();
 123
 1124                var channels = channelResult.Items;
 125
 1126                list.AddRange(channels);
 127
 1128                if (_liveTvManager.GetEnabledUsers().Select(i => i.Id).Contains(user.Id))
 129                {
 0130                    list.Add(_liveTvManager.GetInternalLiveTvFolder(CancellationToken.None));
 131                }
 132            }
 133
 1134            if (!query.IncludeHidden)
 135            {
 0136                list = list.Where(i => !user.GetPreferenceValues<Guid>(PreferenceKind.MyMediaExcludes).Contains(i.Id)).T
 137            }
 138
 1139            var sorted = _libraryManager.Sort(list, user, new[] { ItemSortBy.SortName }, SortOrder.Ascending).ToList();
 1140            var orders = user.GetPreferenceValues<Guid>(PreferenceKind.OrderedViews);
 141
 1142            return list
 1143                .OrderBy(i =>
 1144                {
 1145                    var index = Array.IndexOf(orders, i.Id);
 1146                    if (index == -1
 1147                        && i is UserView view
 1148                        && !view.DisplayParentId.IsEmpty())
 1149                    {
 1150                        index = Array.IndexOf(orders, view.DisplayParentId);
 1151                    }
 1152
 1153                    return index == -1 ? int.MaxValue : index;
 1154                })
 1155                .ThenBy(sorted.IndexOf)
 1156                .ThenBy(i => i.SortName)
 1157                .ToArray();
 158        }
 159
 160        public UserView GetUserSubViewWithName(string name, Guid parentId, CollectionType? type, string sortName)
 161        {
 0162            var uniqueId = parentId + "subview" + type;
 163
 0164            return _libraryManager.GetNamedView(name, parentId, type, sortName, uniqueId);
 165        }
 166
 167        public UserView GetUserSubView(Guid parentId, CollectionType? type, string localizationKey, string sortName)
 168        {
 0169            var name = _localizationManager.GetLocalizedString(localizationKey);
 170
 0171            return GetUserSubViewWithName(name, parentId, type, sortName);
 172        }
 173
 174        private Folder GetUserView(
 175            List<ICollectionFolder> parents,
 176            CollectionType? viewType,
 177            string localizationKey,
 178            string sortName,
 179            User user,
 180            CollectionType?[] presetViews)
 181        {
 0182            if (parents.Count == 1 && parents.All(i => i.CollectionType == viewType))
 183            {
 0184                if (!presetViews.Contains(viewType))
 185                {
 0186                    return (Folder)parents[0];
 187                }
 188
 0189                return GetUserView((Folder)parents[0], viewType, string.Empty);
 190            }
 191
 0192            var name = _localizationManager.GetLocalizedString(localizationKey);
 0193            return _libraryManager.GetNamedView(user, name, viewType, sortName);
 194        }
 195
 196        public UserView GetUserView(Folder parent, CollectionType? viewType, string sortName)
 197        {
 0198            return _libraryManager.GetShadowView(parent, viewType, sortName);
 199        }
 200
 201        public List<Tuple<BaseItem, List<BaseItem>>> GetLatestItems(LatestItemsQuery request, DtoOptions options)
 202        {
 0203            var libraryItems = GetItemsForLatestItems(request.User, request, options);
 204
 0205            var list = new List<Tuple<BaseItem, List<BaseItem>>>();
 206
 0207            foreach (var item in libraryItems)
 208            {
 209                // Only grab the index container for media
 0210                var container = item.IsFolder || !request.GroupItems ? null : item.LatestItemsIndexContainer;
 211
 0212                if (container is null)
 213                {
 0214                    list.Add(new Tuple<BaseItem, List<BaseItem>>(null, new List<BaseItem> { item }));
 215                }
 216                else
 217                {
 0218                    var current = list.FirstOrDefault(i => i.Item1 is not null && i.Item1.Id.Equals(container.Id));
 219
 0220                    if (current is not null)
 221                    {
 0222                        current.Item2.Add(item);
 223                    }
 224                    else
 225                    {
 0226                        list.Add(new Tuple<BaseItem, List<BaseItem>>(container, new List<BaseItem> { item }));
 227                    }
 228                }
 229
 0230                if (list.Count >= request.Limit)
 231                {
 0232                    break;
 233                }
 234            }
 235
 0236            return list;
 237        }
 238
 239        private IReadOnlyList<BaseItem> GetItemsForLatestItems(User user, LatestItemsQuery request, DtoOptions options)
 240        {
 0241            var parentId = request.ParentId;
 242
 0243            var includeItemTypes = request.IncludeItemTypes;
 0244            var limit = request.Limit ?? 10;
 245
 0246            var parents = new List<BaseItem>();
 247
 0248            if (!parentId.IsEmpty())
 249            {
 0250                var parentItem = _libraryManager.GetItemById(parentId);
 0251                if (parentItem is Channel)
 252                {
 0253                    return _channelManager.GetLatestChannelItemsInternal(
 0254                        new InternalItemsQuery(user)
 0255                        {
 0256                            ChannelIds = new[] { parentId },
 0257                            IsPlayed = request.IsPlayed,
 0258                            StartIndex = request.StartIndex,
 0259                            Limit = request.Limit,
 0260                            IncludeItemTypes = request.IncludeItemTypes,
 0261                            EnableTotalRecordCount = false
 0262                        },
 0263                        CancellationToken.None).GetAwaiter().GetResult().Items;
 264                }
 265
 0266                if (parentItem is Folder parent)
 267                {
 0268                    parents.Add(parent);
 269                }
 270            }
 271
 0272            var isPlayed = request.IsPlayed;
 273
 0274            if (parents.OfType<ICollectionFolder>().Any(i => i.CollectionType == CollectionType.music))
 275            {
 0276                isPlayed = null;
 277            }
 278
 0279            if (parents.Count == 0)
 280            {
 0281                parents = _libraryManager.GetUserRootFolder().GetChildren(user, true)
 0282                    .Where(i => i is Folder)
 0283                    .Where(i => !user.GetPreferenceValues<Guid>(PreferenceKind.LatestItemExcludes)
 0284                        .Contains(i.Id))
 0285                    .ToList();
 286            }
 287
 0288            if (parents.Count == 0)
 289            {
 0290                return Array.Empty<BaseItem>();
 291            }
 292
 0293            if (includeItemTypes.Length == 0)
 294            {
 295                // Handle situations with the grouping setting, e.g. movies showing up in tv, etc.
 296                // Thanks to mixed content libraries included in the UserView
 0297                var hasCollectionType = parents.OfType<UserView>().ToList();
 0298                if (hasCollectionType.Count > 0)
 299                {
 0300                    if (hasCollectionType.All(i => i.CollectionType == CollectionType.movies))
 301                    {
 0302                        includeItemTypes = new[] { BaseItemKind.Movie };
 303                    }
 0304                    else if (hasCollectionType.All(i => i.CollectionType == CollectionType.tvshows))
 305                    {
 0306                        includeItemTypes = new[] { BaseItemKind.Episode };
 307                    }
 308                }
 309            }
 310
 0311            var mediaTypes = new List<MediaType>();
 312
 0313            if (includeItemTypes.Length == 0)
 314            {
 0315                foreach (var parent in parents.OfType<ICollectionFolder>())
 316                {
 0317                    switch (parent.CollectionType)
 318                    {
 319                        case CollectionType.books:
 0320                            mediaTypes.Add(MediaType.Book);
 0321                            mediaTypes.Add(MediaType.Audio);
 0322                            break;
 323                        case CollectionType.music:
 0324                            mediaTypes.Add(MediaType.Audio);
 0325                            break;
 326                        case CollectionType.photos:
 0327                            mediaTypes.Add(MediaType.Photo);
 0328                            mediaTypes.Add(MediaType.Video);
 0329                            break;
 330                        case CollectionType.homevideos:
 0331                            mediaTypes.Add(MediaType.Photo);
 0332                            mediaTypes.Add(MediaType.Video);
 0333                            break;
 334                        default:
 0335                            mediaTypes.Add(MediaType.Video);
 336                            break;
 337                    }
 338                }
 339
 0340                mediaTypes = mediaTypes.Distinct().ToList();
 341            }
 342
 0343            var excludeItemTypes = includeItemTypes.Length == 0 && mediaTypes.Count == 0
 0344                ? new[]
 0345                {
 0346                    BaseItemKind.Person,
 0347                    BaseItemKind.Studio,
 0348                    BaseItemKind.Year,
 0349                    BaseItemKind.MusicGenre,
 0350                    BaseItemKind.Genre
 0351                }
 0352                : Array.Empty<BaseItemKind>();
 353
 0354            var query = new InternalItemsQuery(user)
 0355            {
 0356                IncludeItemTypes = includeItemTypes,
 0357                OrderBy = new[]
 0358                {
 0359                    (ItemSortBy.DateCreated, SortOrder.Descending),
 0360                    (ItemSortBy.SortName, SortOrder.Descending),
 0361                    (ItemSortBy.ProductionYear, SortOrder.Descending)
 0362                },
 0363                IsFolder = includeItemTypes.Length == 0 ? false : null,
 0364                ExcludeItemTypes = excludeItemTypes,
 0365                IsVirtualItem = false,
 0366                Limit = limit * 5,
 0367                IsPlayed = isPlayed,
 0368                DtoOptions = options,
 0369                MediaTypes = mediaTypes.ToArray()
 0370            };
 371
 0372            if (parents.Count == 0)
 373            {
 0374                return _libraryManager.GetItemList(query, false);
 375            }
 376
 0377            return _libraryManager.GetItemList(query, parents);
 378        }
 379    }
 380}