BaseFolderPage.cs 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502
  1. using MediaBrowser.Model.Dto;
  2. using MediaBrowser.Model.Entities;
  3. using MediaBrowser.Model.Net;
  4. using MediaBrowser.UI.ViewModels;
  5. using System;
  6. using System.Collections.Generic;
  7. using System.Collections.ObjectModel;
  8. using System.Linq;
  9. using System.Threading.Tasks;
  10. using System.Windows.Controls;
  11. namespace MediaBrowser.UI.Pages
  12. {
  13. /// <summary>
  14. /// Provides a base class for pages based on a folder item (list, home)
  15. /// </summary>
  16. public abstract class BaseFolderPage : BasePage
  17. {
  18. /// <summary>
  19. /// Initializes a new instance of the <see cref="BaseFolderPage" /> class.
  20. /// </summary>
  21. /// <param name="itemId">The item id.</param>
  22. protected BaseFolderPage(string itemId)
  23. : base()
  24. {
  25. ItemId = itemId;
  26. }
  27. /// <summary>
  28. /// The _item id
  29. /// </summary>
  30. private string _itemId;
  31. /// <summary>
  32. /// Gets or sets the Id of the item being displayed
  33. /// </summary>
  34. /// <value>The item id.</value>
  35. protected string ItemId
  36. {
  37. get { return _itemId; }
  38. private set
  39. {
  40. _itemId = value;
  41. OnPropertyChanged("ItemId");
  42. }
  43. }
  44. /// <summary>
  45. /// The _index by
  46. /// </summary>
  47. private string _indexBy;
  48. /// <summary>
  49. /// Gets or sets the name of the current index function
  50. /// </summary>
  51. /// <value>The index by.</value>
  52. public string IndexBy
  53. {
  54. get { return _indexBy; }
  55. private set
  56. {
  57. _indexBy = value;
  58. OnPropertyChanged("IndexBy");
  59. }
  60. }
  61. /// <summary>
  62. /// The _sort by
  63. /// </summary>
  64. private string _sortBy;
  65. /// <summary>
  66. /// Gets or sets the name of the current sort function
  67. /// </summary>
  68. /// <value>The sort by.</value>
  69. public string SortBy
  70. {
  71. get { return _sortBy; }
  72. private set
  73. {
  74. _sortBy = value;
  75. OnPropertyChanged("SortBy");
  76. }
  77. }
  78. /// <summary>
  79. /// The _folder
  80. /// </summary>
  81. private BaseItemDto _folder;
  82. /// <summary>
  83. /// Gets or sets the Folder being displayed
  84. /// </summary>
  85. /// <value>The folder.</value>
  86. public BaseItemDto Folder
  87. {
  88. get { return _folder; }
  89. set
  90. {
  91. _folder = value;
  92. OnPropertyChanged("Folder");
  93. OnFolderChanged();
  94. ReloadChildren();
  95. }
  96. }
  97. /// <summary>
  98. /// If wrap panels are being used this will get the orientation that should be used, based on scroll direction
  99. /// </summary>
  100. /// <value>The wrap panel orientation.</value>
  101. public Orientation WrapPanelOrientation
  102. {
  103. get
  104. {
  105. return DisplayPreferences.ScrollDirection == ScrollDirection.Horizontal ? Orientation.Vertical : Orientation.Horizontal;
  106. }
  107. }
  108. /// <summary>
  109. /// The _display preferences
  110. /// </summary>
  111. private DisplayPreferences _displayPreferences;
  112. /// <summary>
  113. /// Gets of sets the current DisplayPreferences
  114. /// </summary>
  115. /// <value>The display preferences.</value>
  116. public DisplayPreferences DisplayPreferences
  117. {
  118. get { return _displayPreferences; }
  119. private set
  120. {
  121. _displayPreferences = value;
  122. // If the page is using it's own image type and not honoring the DisplayPreferences setting, set it now
  123. if (_displayPreferences != null && FixedImageType.HasValue)
  124. {
  125. _displayPreferences.PrimaryImageType = FixedImageType.Value;
  126. }
  127. NotifyDisplayPreferencesChanged();
  128. }
  129. }
  130. /// <summary>
  131. /// The _children
  132. /// </summary>
  133. private ItemsResult _children;
  134. /// <summary>
  135. /// Gets or sets the children of the Folder being displayed
  136. /// </summary>
  137. /// <value>The children.</value>
  138. public ItemsResult Children
  139. {
  140. get { return _children; }
  141. private set
  142. {
  143. _children = value;
  144. OnPropertyChanged("Children");
  145. ChildCount = _children.TotalRecordCount;
  146. OnChildrenChanged();
  147. DisplayChildren = DtoBaseItemViewModel.GetObservableItems(Children.Items, AveragePrimaryImageAspectRatio, DisplayPreferences);
  148. }
  149. }
  150. /// <summary>
  151. /// The _display children
  152. /// </summary>
  153. private ObservableCollection<DtoBaseItemViewModel> _displayChildren;
  154. /// <summary>
  155. /// Gets the actual children that should be displayed.
  156. /// Subclasses should bind to this, not Children.
  157. /// </summary>
  158. /// <value>The display children.</value>
  159. public ObservableCollection<DtoBaseItemViewModel> DisplayChildren
  160. {
  161. get { return _displayChildren; }
  162. private set
  163. {
  164. _displayChildren = value;
  165. OnPropertyChanged("DisplayChildren");
  166. }
  167. }
  168. /// <summary>
  169. /// The _child count
  170. /// </summary>
  171. private int _childCount;
  172. /// <summary>
  173. /// Gets or sets the number of children within the Folder
  174. /// </summary>
  175. /// <value>The child count.</value>
  176. public int ChildCount
  177. {
  178. get { return _childCount; }
  179. private set
  180. {
  181. _childCount = value;
  182. OnPropertyChanged("ChildCount");
  183. }
  184. }
  185. /// <summary>
  186. /// If the page is using it's own image type and not honoring the DisplayPreferences setting, it should return it here
  187. /// </summary>
  188. /// <value>The type of the fixed image.</value>
  189. protected virtual ImageType? FixedImageType
  190. {
  191. get { return null; }
  192. }
  193. /// <summary>
  194. /// The _average primary image aspect ratio
  195. /// </summary>
  196. private double _averagePrimaryImageAspectRatio;
  197. /// <summary>
  198. /// Gets or sets the average primary image aspect ratio for all items
  199. /// </summary>
  200. /// <value>The average primary image aspect ratio.</value>
  201. public double AveragePrimaryImageAspectRatio
  202. {
  203. get { return _averagePrimaryImageAspectRatio; }
  204. private set
  205. {
  206. _averagePrimaryImageAspectRatio = value;
  207. OnPropertyChanged("AveragePrimaryImageAspectRatio");
  208. }
  209. }
  210. /// <summary>
  211. /// Gets the aspect ratio that should be used based on a given ImageType
  212. /// </summary>
  213. /// <param name="imageType">Type of the image.</param>
  214. /// <returns>System.Double.</returns>
  215. public double GetAspectRatio(ImageType imageType)
  216. {
  217. return GetAspectRatio(imageType, AveragePrimaryImageAspectRatio);
  218. }
  219. /// <summary>
  220. /// Gets the aspect ratio that should be used based on a given ImageType
  221. /// </summary>
  222. /// <param name="imageType">Type of the image.</param>
  223. /// <param name="averagePrimaryImageAspectRatio">The average primary image aspect ratio.</param>
  224. /// <returns>System.Double.</returns>
  225. public static double GetAspectRatio(ImageType imageType, double averagePrimaryImageAspectRatio)
  226. {
  227. switch (imageType)
  228. {
  229. case ImageType.Art:
  230. return 1.777777777777778;
  231. case ImageType.Backdrop:
  232. return 1.777777777777778;
  233. case ImageType.Banner:
  234. return 5.414285714285714;
  235. case ImageType.Disc:
  236. return 1;
  237. case ImageType.Logo:
  238. return 1.777777777777778;
  239. case ImageType.Primary:
  240. return averagePrimaryImageAspectRatio;
  241. case ImageType.Thumb:
  242. return 1.777777777777778;
  243. default:
  244. return 1;
  245. }
  246. }
  247. /// <summary>
  248. /// Called when [property changed].
  249. /// </summary>
  250. /// <param name="name">The name.</param>
  251. public async override void OnPropertyChanged(string name)
  252. {
  253. base.OnPropertyChanged(name);
  254. // Reload the Folder when the itemId changes
  255. if (name.Equals("ItemId"))
  256. {
  257. await ReloadFolder();
  258. }
  259. }
  260. /// <summary>
  261. /// Reloads the folder
  262. /// </summary>
  263. /// <returns>Task.</returns>
  264. private async Task ReloadFolder()
  265. {
  266. try
  267. {
  268. if (string.IsNullOrEmpty(ItemId))
  269. {
  270. Folder = await App.Instance.ApiClient.GetRootFolderAsync(App.Instance.CurrentUser.Id);
  271. }
  272. else
  273. {
  274. Folder = await App.Instance.ApiClient.GetItemAsync(ItemId, App.Instance.CurrentUser.Id);
  275. }
  276. }
  277. catch (HttpException)
  278. {
  279. App.Instance.ShowDefaultErrorMessage();
  280. }
  281. }
  282. /// <summary>
  283. /// Gets called anytime the Folder gets refreshed
  284. /// </summary>
  285. protected virtual void OnFolderChanged()
  286. {
  287. SetBackdrops(Folder);
  288. DisplayPreferences = Folder.DisplayPreferences;
  289. if (DisplayPreferences.RememberIndexing)
  290. {
  291. IndexBy = DisplayPreferences.IndexBy;
  292. }
  293. if (DisplayPreferences.RememberSorting)
  294. {
  295. SortBy = DisplayPreferences.SortBy ?? Folder.SortOptions.FirstOrDefault();
  296. }
  297. else if (string.IsNullOrEmpty(SortBy))
  298. {
  299. SortBy = Folder.SortOptions.FirstOrDefault();
  300. }
  301. }
  302. /// <summary>
  303. /// Gets called anytime the Children get refreshed
  304. /// </summary>
  305. protected virtual void OnChildrenChanged()
  306. {
  307. AveragePrimaryImageAspectRatio = DtoBaseItemViewModel.GetAveragePrimaryImageAspectRatio(Children.Items);
  308. if (DisplayPreferences != null)
  309. {
  310. DisplayPreferences.PrimaryImageWidth = Convert.ToInt32(DisplayPreferences.PrimaryImageHeight * GetAspectRatio(DisplayPreferences.PrimaryImageType));
  311. }
  312. NotifyDisplayPreferencesChanged();
  313. }
  314. /// <summary>
  315. /// Reloads the Folder's children
  316. /// </summary>
  317. /// <returns>Task.</returns>
  318. public async Task ReloadChildren()
  319. {
  320. var query = new ItemQuery
  321. {
  322. ParentId = Folder.Id,
  323. Fields = new[] {
  324. ItemFields.UserData,
  325. ItemFields.PrimaryImageAspectRatio
  326. },
  327. UserId = App.Instance.CurrentUser.Id,
  328. IndexBy = IndexBy,
  329. DynamicSortBy = SortBy
  330. };
  331. try
  332. {
  333. Children = await App.Instance.ApiClient.GetItemsAsync(query);
  334. }
  335. catch (HttpException)
  336. {
  337. App.Instance.ShowDefaultErrorMessage();
  338. }
  339. }
  340. /// <summary>
  341. /// Gets called anytime a DisplayPreferences property is updated
  342. /// </summary>
  343. public virtual void NotifyDisplayPreferencesChanged()
  344. {
  345. OnPropertyChanged("DisplayPreferences");
  346. if (DisplayChildren != null)
  347. {
  348. // Notify all of the child view models
  349. foreach (var child in DisplayChildren)
  350. {
  351. child.AveragePrimaryImageAspectRatio = AveragePrimaryImageAspectRatio;
  352. child.NotifyDisplayPreferencesChanged();
  353. }
  354. }
  355. OnPropertyChanged("WrapPanelOrientation");
  356. }
  357. /// <summary>
  358. /// Changes the sort option on the page
  359. /// </summary>
  360. /// <param name="option">The option.</param>
  361. /// <returns>Task.</returns>
  362. public async Task UpdateSortOption(string option)
  363. {
  364. var tasks = new List<Task>();
  365. SortBy = option;
  366. if (DisplayPreferences.RememberSorting)
  367. {
  368. DisplayPreferences.SortBy = option;
  369. NotifyDisplayPreferencesChanged();
  370. tasks.Add(Task.Run(async () =>
  371. {
  372. try
  373. {
  374. await App.Instance.ApiClient.UpdateDisplayPreferencesAsync(App.Instance.CurrentUser.Id, Folder.Id, DisplayPreferences);
  375. }
  376. catch
  377. {
  378. App.Instance.ShowDefaultErrorMessage();
  379. }
  380. }));
  381. }
  382. tasks.Add(ReloadChildren());
  383. await Task.WhenAll(tasks);
  384. }
  385. /// <summary>
  386. /// Changes the index option on the page
  387. /// </summary>
  388. /// <param name="option">The option.</param>
  389. /// <returns>Task.</returns>
  390. public async Task UpdateIndexOption(string option)
  391. {
  392. var tasks = new List<Task>();
  393. IndexBy = option;
  394. if (DisplayPreferences.RememberIndexing)
  395. {
  396. DisplayPreferences.IndexBy = option;
  397. NotifyDisplayPreferencesChanged();
  398. tasks.Add(Task.Run(async () =>
  399. {
  400. try
  401. {
  402. await App.Instance.ApiClient.UpdateDisplayPreferencesAsync(App.Instance.CurrentUser.Id, Folder.Id, DisplayPreferences);
  403. }
  404. catch
  405. {
  406. App.Instance.ShowDefaultErrorMessage();
  407. }
  408. }));
  409. }
  410. tasks.Add(ReloadChildren());
  411. await Task.WhenAll(tasks);
  412. }
  413. /// <summary>
  414. /// Updates the index of the remember.
  415. /// </summary>
  416. /// <param name="remember">if set to <c>true</c> [remember].</param>
  417. /// <returns>Task.</returns>
  418. public async Task UpdateRememberIndex(bool remember)
  419. {
  420. DisplayPreferences.RememberIndexing = remember;
  421. if (remember)
  422. {
  423. DisplayPreferences.IndexBy = IndexBy;
  424. }
  425. await App.Instance.ApiClient.UpdateDisplayPreferencesAsync(App.Instance.CurrentUser.Id, Folder.Id, DisplayPreferences);
  426. }
  427. /// <summary>
  428. /// Updates the remember sort.
  429. /// </summary>
  430. /// <param name="remember">if set to <c>true</c> [remember].</param>
  431. /// <returns>Task.</returns>
  432. public async Task UpdateRememberSort(bool remember)
  433. {
  434. DisplayPreferences.RememberSorting = remember;
  435. if (remember)
  436. {
  437. DisplayPreferences.SortBy = SortBy;
  438. }
  439. await App.Instance.ApiClient.UpdateDisplayPreferencesAsync(App.Instance.CurrentUser.Id, Folder.Id, DisplayPreferences);
  440. }
  441. }
  442. }