AppThemeManager.cs 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. using MediaBrowser.Common.Extensions;
  2. using MediaBrowser.Common.IO;
  3. using MediaBrowser.Controller;
  4. using MediaBrowser.Controller.Themes;
  5. using MediaBrowser.Model.Logging;
  6. using MediaBrowser.Model.Serialization;
  7. using MediaBrowser.Model.Themes;
  8. using System;
  9. using System.Collections.Generic;
  10. using System.IO;
  11. using System.Linq;
  12. namespace MediaBrowser.Server.Implementations.Themes
  13. {
  14. public class AppThemeManager : IAppThemeManager
  15. {
  16. private readonly IServerApplicationPaths _appPaths;
  17. private readonly IFileSystem _fileSystem;
  18. private readonly IJsonSerializer _json;
  19. private readonly ILogger _logger;
  20. private readonly string[] _supportedImageExtensions = { ".png", ".jpg", ".jpeg" };
  21. public AppThemeManager(IServerApplicationPaths appPaths, IFileSystem fileSystem, IJsonSerializer json, ILogger logger)
  22. {
  23. _appPaths = appPaths;
  24. _fileSystem = fileSystem;
  25. _json = json;
  26. _logger = logger;
  27. }
  28. private string ThemePath
  29. {
  30. get
  31. {
  32. return Path.Combine(_appPaths.ItemsByNamePath, "appthemes");
  33. }
  34. }
  35. private string GetThemesPath(string applicationName)
  36. {
  37. if (string.IsNullOrWhiteSpace(applicationName))
  38. {
  39. throw new ArgumentNullException("applicationName");
  40. }
  41. // Force everything lowercase for consistency and maximum compatibility with case-sensitive file systems
  42. var name = _fileSystem.GetValidFilename(applicationName.ToLower());
  43. return Path.Combine(ThemePath, name);
  44. }
  45. private string GetThemePath(string applicationName, string name)
  46. {
  47. if (string.IsNullOrWhiteSpace(name))
  48. {
  49. throw new ArgumentNullException("name");
  50. }
  51. // Force everything lowercase for consistency and maximum compatibility with case-sensitive file systems
  52. name = _fileSystem.GetValidFilename(name.ToLower());
  53. return Path.Combine(GetThemesPath(applicationName), name);
  54. }
  55. public IEnumerable<AppThemeInfo> GetThemes(string applicationName)
  56. {
  57. var path = GetThemesPath(applicationName);
  58. try
  59. {
  60. return Directory
  61. .EnumerateFiles(path, "*", SearchOption.AllDirectories)
  62. .Where(i => string.Equals(Path.GetExtension(i), ".json", StringComparison.OrdinalIgnoreCase))
  63. .Select(i =>
  64. {
  65. try
  66. {
  67. return _json.DeserializeFromFile<AppThemeInfo>(i);
  68. }
  69. catch (Exception ex)
  70. {
  71. _logger.ErrorException("Error deserializing {0}", ex, i);
  72. return null;
  73. }
  74. }).Where(i => i != null);
  75. }
  76. catch (DirectoryNotFoundException)
  77. {
  78. return new List<AppThemeInfo>();
  79. }
  80. }
  81. public AppTheme GetTheme(string applicationName, string name)
  82. {
  83. var themePath = GetThemePath(applicationName, name);
  84. var file = Path.Combine(themePath, "theme.json");
  85. var theme = _json.DeserializeFromFile<AppTheme>(file);
  86. theme.Images = new DirectoryInfo(themePath)
  87. .EnumerateFiles("*", SearchOption.TopDirectoryOnly)
  88. .Where(i => _supportedImageExtensions.Contains(i.Extension, StringComparer.OrdinalIgnoreCase))
  89. .Select(GetThemeImage)
  90. .ToList();
  91. return theme;
  92. }
  93. private ThemeImage GetThemeImage(FileInfo file)
  94. {
  95. var dateModified = _fileSystem.GetLastWriteTimeUtc(file);
  96. var cacheTag = (file.FullName + dateModified.Ticks).GetMD5().ToString("N");
  97. return new ThemeImage
  98. {
  99. CacheTag = cacheTag,
  100. Name = file.Name
  101. };
  102. }
  103. public void SaveTheme(AppTheme theme)
  104. {
  105. var themePath = GetThemePath(theme.ApplicationName, theme.Name);
  106. var file = Path.Combine(themePath, "theme.json");
  107. Directory.CreateDirectory(themePath);
  108. // Clone it so that we don't serialize all the images - they're always dynamic
  109. var clone = new AppTheme
  110. {
  111. ApplicationName = theme.ApplicationName,
  112. Name = theme.Name,
  113. Options = theme.Options,
  114. Images = null
  115. };
  116. _json.SerializeToFile(clone, file);
  117. }
  118. public InternalThemeImage GetImageImageInfo(string applicationName, string themeName, string imageName)
  119. {
  120. var themePath = GetThemePath(applicationName, themeName);
  121. var fullPath = Path.Combine(themePath, imageName);
  122. var file = new DirectoryInfo(themePath).EnumerateFiles("*", SearchOption.TopDirectoryOnly)
  123. .First(i => string.Equals(i.FullName, fullPath, StringComparison.OrdinalIgnoreCase));
  124. var themeImage = GetThemeImage(file);
  125. return new InternalThemeImage
  126. {
  127. CacheTag = themeImage.CacheTag,
  128. Name = themeImage.Name,
  129. Path = file.FullName,
  130. DateModified = _fileSystem.GetLastWriteTimeUtc(file)
  131. };
  132. }
  133. }
  134. }