UserRootFolder.cs 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. using MediaBrowser.Common.Extensions;
  2. using MediaBrowser.Controller.Entities.Audio;
  3. using MediaBrowser.Controller.Entities.Movies;
  4. using MediaBrowser.Controller.Entities.TV;
  5. using MediaBrowser.Controller.Providers;
  6. using MediaBrowser.Model.Entities;
  7. using System;
  8. using System.Collections.Generic;
  9. using System.IO;
  10. using System.Linq;
  11. using System.Threading;
  12. using System.Threading.Tasks;
  13. namespace MediaBrowser.Controller.Entities
  14. {
  15. /// <summary>
  16. /// Special class used for User Roots. Children contain actual ones defined for this user
  17. /// PLUS the virtual folders from the physical root (added by plug-ins).
  18. /// </summary>
  19. public class UserRootFolder : Folder
  20. {
  21. /// <summary>
  22. /// Get the children of this folder from the actual file system
  23. /// </summary>
  24. /// <returns>IEnumerable{BaseItem}.</returns>
  25. protected override IEnumerable<BaseItem> GetNonCachedChildren(IDirectoryService directoryService)
  26. {
  27. return base.GetNonCachedChildren(directoryService).Concat(LibraryManager.RootFolder.VirtualChildren);
  28. }
  29. public override bool BeforeMetadataRefresh()
  30. {
  31. var hasChanges = base.BeforeMetadataRefresh();
  32. if (string.Equals("default", Name, StringComparison.OrdinalIgnoreCase))
  33. {
  34. Name = "Media Folders";
  35. hasChanges = true;
  36. }
  37. return hasChanges;
  38. }
  39. protected override async Task ValidateChildrenInternal(IProgress<double> progress, CancellationToken cancellationToken, bool recursive, bool refreshChildMetadata, MetadataRefreshOptions refreshOptions, IDirectoryService directoryService)
  40. {
  41. await base.ValidateChildrenInternal(progress, cancellationToken, recursive, refreshChildMetadata, refreshOptions, directoryService)
  42. .ConfigureAwait(false);
  43. // Not the best way to handle this, but it solves an issue
  44. // CollectionFolders aren't always getting saved after changes
  45. // This means that grabbing the item by Id may end up returning the old one
  46. // Fix is in two places - make sure the folder gets saved
  47. // And here to remedy it for affected users.
  48. // In theory this can be removed eventually.
  49. foreach (var item in Children)
  50. {
  51. LibraryManager.RegisterItem(item);
  52. }
  53. }
  54. public async Task<IEnumerable<Folder>> GetViews(User user, CancellationToken cancellationToken)
  55. {
  56. var folders = user.RootFolder
  57. .GetChildren(user, true)
  58. .OfType<Folder>()
  59. .ToList();
  60. var list = new List<Folder>();
  61. var excludeFolderIds = user.Configuration.ExcludeFoldersFromGrouping.Select(i => new Guid(i)).ToList();
  62. var standaloneFolders = folders.Where(i => UserView.IsExcludedFromGrouping(i) || excludeFolderIds.Contains(i.Id)).ToList();
  63. list.AddRange(standaloneFolders);
  64. var recursiveChildren = folders
  65. .Except(standaloneFolders)
  66. .SelectMany(i => i.GetRecursiveChildren(user, false))
  67. .ToList();
  68. if (recursiveChildren.OfType<Series>().Any())
  69. {
  70. list.Add(await GetUserView(CollectionType.TvShows, user, cancellationToken).ConfigureAwait(false));
  71. }
  72. if (recursiveChildren.OfType<MusicAlbum>().Any() ||
  73. recursiveChildren.OfType<MusicVideo>().Any())
  74. {
  75. list.Add(await GetUserView(CollectionType.Music, user, cancellationToken).ConfigureAwait(false));
  76. }
  77. if (recursiveChildren.OfType<Movie>().Any())
  78. {
  79. list.Add(await GetUserView(CollectionType.Movies, user, cancellationToken).ConfigureAwait(false));
  80. }
  81. if (recursiveChildren.OfType<Game>().Any())
  82. {
  83. list.Add(await GetUserView(CollectionType.Games, user, cancellationToken).ConfigureAwait(false));
  84. }
  85. if (recursiveChildren.OfType<BoxSet>().Any())
  86. {
  87. list.Add(await GetUserView(CollectionType.BoxSets, user, cancellationToken).ConfigureAwait(false));
  88. }
  89. return list.OrderBy(i => i.SortName);
  90. }
  91. // Use this to force new entity creation, as needed
  92. private const string DataVersion = "5";
  93. private async Task<UserView> GetUserView(string type, User user, CancellationToken cancellationToken)
  94. {
  95. var name = LocalizationManager.GetLocalizedString("ViewType" + type);
  96. var id = "view" + name + DataVersion + user.Id.ToString("N");
  97. var guid = id.GetMD5();
  98. var item = LibraryManager.GetItemById(guid) as UserView;
  99. if (item == null)
  100. {
  101. var path = System.IO.Path.Combine(user.ConfigurationDirectoryPath,
  102. "views",
  103. FileSystem.GetValidFilename(name));
  104. Directory.CreateDirectory(System.IO.Path.GetDirectoryName(path));
  105. item = new UserView
  106. {
  107. Path = path,
  108. Id = guid,
  109. DateCreated = DateTime.UtcNow,
  110. Name = name,
  111. ViewType = type
  112. };
  113. await LibraryManager.CreateItem(item, cancellationToken).ConfigureAwait(false);
  114. await item.RefreshMetadata(cancellationToken).ConfigureAwait(false);
  115. }
  116. return item;
  117. }
  118. }
  119. }