using MediaBrowser.Model.DTO; using MediaBrowser.Model.Entities; using MediaBrowser.Model.Net; using MediaBrowser.UI.ViewModels; using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Linq; using System.Threading.Tasks; using System.Windows.Controls; namespace MediaBrowser.UI.Pages { /// /// Provides a base class for pages based on a folder item (list, home) /// public abstract class BaseFolderPage : BasePage { /// /// Initializes a new instance of the class. /// /// The item id. protected BaseFolderPage(string itemId) : base() { ItemId = itemId; } /// /// The _item id /// private string _itemId; /// /// Gets or sets the Id of the item being displayed /// /// The item id. protected string ItemId { get { return _itemId; } private set { _itemId = value; OnPropertyChanged("ItemId"); } } /// /// The _index by /// private string _indexBy; /// /// Gets or sets the name of the current index function /// /// The index by. public string IndexBy { get { return _indexBy; } private set { _indexBy = value; OnPropertyChanged("IndexBy"); } } /// /// The _sort by /// private string _sortBy; /// /// Gets or sets the name of the current sort function /// /// The sort by. public string SortBy { get { return _sortBy; } private set { _sortBy = value; OnPropertyChanged("SortBy"); } } /// /// The _folder /// private DtoBaseItem _folder; /// /// Gets or sets the Folder being displayed /// /// The folder. public DtoBaseItem Folder { get { return _folder; } set { _folder = value; OnPropertyChanged("Folder"); OnFolderChanged(); ReloadChildren(); } } /// /// If wrap panels are being used this will get the orientation that should be used, based on scroll direction /// /// The wrap panel orientation. public Orientation WrapPanelOrientation { get { return DisplayPreferences.ScrollDirection == ScrollDirection.Horizontal ? Orientation.Vertical : Orientation.Horizontal; } } /// /// The _display preferences /// private DisplayPreferences _displayPreferences; /// /// Gets of sets the current DisplayPreferences /// /// The display preferences. public DisplayPreferences DisplayPreferences { get { return _displayPreferences; } private set { _displayPreferences = value; // If the page is using it's own image type and not honoring the DisplayPreferences setting, set it now if (_displayPreferences != null && FixedImageType.HasValue) { _displayPreferences.PrimaryImageType = FixedImageType.Value; } NotifyDisplayPreferencesChanged(); } } /// /// The _children /// private ItemsResult _children; /// /// Gets or sets the children of the Folder being displayed /// /// The children. public ItemsResult Children { get { return _children; } private set { _children = value; OnPropertyChanged("Children"); ChildCount = _children.TotalRecordCount; OnChildrenChanged(); DisplayChildren = DtoBaseItemViewModel.GetObservableItems(Children.Items, AveragePrimaryImageAspectRatio, DisplayPreferences); } } /// /// The _display children /// private ObservableCollection _displayChildren; /// /// Gets the actual children that should be displayed. /// Subclasses should bind to this, not Children. /// /// The display children. public ObservableCollection DisplayChildren { get { return _displayChildren; } private set { _displayChildren = value; OnPropertyChanged("DisplayChildren"); } } /// /// The _child count /// private int _childCount; /// /// Gets or sets the number of children within the Folder /// /// The child count. public int ChildCount { get { return _childCount; } private set { _childCount = value; OnPropertyChanged("ChildCount"); } } /// /// If the page is using it's own image type and not honoring the DisplayPreferences setting, it should return it here /// /// The type of the fixed image. protected virtual ImageType? FixedImageType { get { return null; } } /// /// The _average primary image aspect ratio /// private double _averagePrimaryImageAspectRatio; /// /// Gets or sets the average primary image aspect ratio for all items /// /// The average primary image aspect ratio. public double AveragePrimaryImageAspectRatio { get { return _averagePrimaryImageAspectRatio; } private set { _averagePrimaryImageAspectRatio = value; OnPropertyChanged("AveragePrimaryImageAspectRatio"); } } /// /// Gets the aspect ratio that should be used based on a given ImageType /// /// Type of the image. /// System.Double. public double GetAspectRatio(ImageType imageType) { return GetAspectRatio(imageType, AveragePrimaryImageAspectRatio); } /// /// Gets the aspect ratio that should be used based on a given ImageType /// /// Type of the image. /// The average primary image aspect ratio. /// System.Double. public static double GetAspectRatio(ImageType imageType, double averagePrimaryImageAspectRatio) { switch (imageType) { case ImageType.Art: return 1.777777777777778; case ImageType.Backdrop: return 1.777777777777778; case ImageType.Banner: return 5.414285714285714; case ImageType.Disc: return 1; case ImageType.Logo: return 1.777777777777778; case ImageType.Primary: return averagePrimaryImageAspectRatio; case ImageType.Thumb: return 1.777777777777778; default: return 1; } } /// /// Called when [property changed]. /// /// The name. public async override void OnPropertyChanged(string name) { base.OnPropertyChanged(name); // Reload the Folder when the itemId changes if (name.Equals("ItemId")) { await ReloadFolder(); } } /// /// Reloads the folder /// /// Task. private async Task ReloadFolder() { try { if (string.IsNullOrEmpty(ItemId)) { Folder = await App.Instance.ApiClient.GetRootFolderAsync(App.Instance.CurrentUser.Id); } else { Folder = await App.Instance.ApiClient.GetItemAsync(ItemId, App.Instance.CurrentUser.Id); } } catch (HttpException) { App.Instance.ShowDefaultErrorMessage(); } } /// /// Gets called anytime the Folder gets refreshed /// protected virtual void OnFolderChanged() { SetBackdrops(Folder); DisplayPreferences = Folder.DisplayPreferences; if (DisplayPreferences.RememberIndexing) { IndexBy = DisplayPreferences.IndexBy; } if (DisplayPreferences.RememberSorting) { SortBy = DisplayPreferences.SortBy ?? Folder.SortOptions.FirstOrDefault(); } else if (string.IsNullOrEmpty(SortBy)) { SortBy = Folder.SortOptions.FirstOrDefault(); } } /// /// Gets called anytime the Children get refreshed /// protected virtual void OnChildrenChanged() { AveragePrimaryImageAspectRatio = DtoBaseItemViewModel.GetAveragePrimaryImageAspectRatio(Children.Items); if (DisplayPreferences != null) { DisplayPreferences.PrimaryImageWidth = Convert.ToInt32(DisplayPreferences.PrimaryImageHeight * GetAspectRatio(DisplayPreferences.PrimaryImageType)); } NotifyDisplayPreferencesChanged(); } /// /// Reloads the Folder's children /// /// Task. public async Task ReloadChildren() { var query = new ItemQuery { ParentId = Folder.Id, Fields = new[] { ItemFields.UserData, ItemFields.PrimaryImageAspectRatio }, UserId = App.Instance.CurrentUser.Id, IndexBy = IndexBy, DynamicSortBy = SortBy }; try { Children = await App.Instance.ApiClient.GetItemsAsync(query); } catch (HttpException) { App.Instance.ShowDefaultErrorMessage(); } } /// /// Gets called anytime a DisplayPreferences property is updated /// public virtual void NotifyDisplayPreferencesChanged() { OnPropertyChanged("DisplayPreferences"); if (DisplayChildren != null) { // Notify all of the child view models foreach (var child in DisplayChildren) { child.AveragePrimaryImageAspectRatio = AveragePrimaryImageAspectRatio; child.NotifyDisplayPreferencesChanged(); } } OnPropertyChanged("WrapPanelOrientation"); } /// /// Changes the sort option on the page /// /// The option. /// Task. public async Task UpdateSortOption(string option) { var tasks = new List(); SortBy = option; if (DisplayPreferences.RememberSorting) { DisplayPreferences.SortBy = option; NotifyDisplayPreferencesChanged(); tasks.Add(Task.Run(async () => { try { await App.Instance.ApiClient.UpdateDisplayPreferencesAsync(App.Instance.CurrentUser.Id, Folder.Id, DisplayPreferences); } catch { App.Instance.ShowDefaultErrorMessage(); } })); } tasks.Add(ReloadChildren()); await Task.WhenAll(tasks); } /// /// Changes the index option on the page /// /// The option. /// Task. public async Task UpdateIndexOption(string option) { var tasks = new List(); IndexBy = option; if (DisplayPreferences.RememberIndexing) { DisplayPreferences.IndexBy = option; NotifyDisplayPreferencesChanged(); tasks.Add(Task.Run(async () => { try { await App.Instance.ApiClient.UpdateDisplayPreferencesAsync(App.Instance.CurrentUser.Id, Folder.Id, DisplayPreferences); } catch { App.Instance.ShowDefaultErrorMessage(); } })); } tasks.Add(ReloadChildren()); await Task.WhenAll(tasks); } /// /// Updates the index of the remember. /// /// if set to true [remember]. /// Task. public async Task UpdateRememberIndex(bool remember) { DisplayPreferences.RememberIndexing = remember; if (remember) { DisplayPreferences.IndexBy = IndexBy; } await App.Instance.ApiClient.UpdateDisplayPreferencesAsync(App.Instance.CurrentUser.Id, Folder.Id, DisplayPreferences); } /// /// Updates the remember sort. /// /// if set to true [remember]. /// Task. public async Task UpdateRememberSort(bool remember) { DisplayPreferences.RememberSorting = remember; if (remember) { DisplayPreferences.SortBy = SortBy; } await App.Instance.ApiClient.UpdateDisplayPreferencesAsync(App.Instance.CurrentUser.Id, Folder.Id, DisplayPreferences); } } }