aboutsummaryrefslogtreecommitdiff
path: root/MediaBrowser.UI/ViewModels
diff options
context:
space:
mode:
Diffstat (limited to 'MediaBrowser.UI/ViewModels')
-rw-r--r--MediaBrowser.UI/ViewModels/BaseItemPersonViewModel.cs27
-rw-r--r--MediaBrowser.UI/ViewModels/BaseViewModel.cs27
-rw-r--r--MediaBrowser.UI/ViewModels/ChapterInfoDtoViewModel.cs182
-rw-r--r--MediaBrowser.UI/ViewModels/DtoBaseItemViewModel.cs184
-rw-r--r--MediaBrowser.UI/ViewModels/ItemCollectionViewModel.cs158
-rw-r--r--MediaBrowser.UI/ViewModels/SpecialFeatureViewModel.cs135
6 files changed, 713 insertions, 0 deletions
diff --git a/MediaBrowser.UI/ViewModels/BaseItemPersonViewModel.cs b/MediaBrowser.UI/ViewModels/BaseItemPersonViewModel.cs
new file mode 100644
index 000000000..95ff86094
--- /dev/null
+++ b/MediaBrowser.UI/ViewModels/BaseItemPersonViewModel.cs
@@ -0,0 +1,27 @@
+using MediaBrowser.Model.DTO;
+
+namespace MediaBrowser.UI.ViewModels
+{
+ public class BaseItemPersonViewModel : BaseViewModel
+ {
+ /// <summary>
+ /// The _item
+ /// </summary>
+ private BaseItemPerson _item;
+ /// <summary>
+ /// Gets or sets the item.
+ /// </summary>
+ /// <value>The item.</value>
+ public BaseItemPerson Item
+ {
+ get { return _item; }
+
+ set
+ {
+ _item = value;
+ OnPropertyChanged("Item");
+ OnPropertyChanged("Image");
+ }
+ }
+ }
+}
diff --git a/MediaBrowser.UI/ViewModels/BaseViewModel.cs b/MediaBrowser.UI/ViewModels/BaseViewModel.cs
new file mode 100644
index 000000000..03ac9d18a
--- /dev/null
+++ b/MediaBrowser.UI/ViewModels/BaseViewModel.cs
@@ -0,0 +1,27 @@
+using System.ComponentModel;
+
+namespace MediaBrowser.UI.ViewModels
+{
+ /// <summary>
+ /// Represents a base ViewModel
+ /// </summary>
+ public abstract class BaseViewModel : INotifyPropertyChanged
+ {
+ /// <summary>
+ /// Occurs when [property changed].
+ /// </summary>
+ public event PropertyChangedEventHandler PropertyChanged;
+
+ /// <summary>
+ /// Called when [property changed].
+ /// </summary>
+ /// <param name="name">The name.</param>
+ public virtual void OnPropertyChanged(string name)
+ {
+ if (PropertyChanged != null)
+ {
+ PropertyChanged(this, new PropertyChangedEventArgs(name));
+ }
+ }
+ }
+}
diff --git a/MediaBrowser.UI/ViewModels/ChapterInfoDtoViewModel.cs b/MediaBrowser.UI/ViewModels/ChapterInfoDtoViewModel.cs
new file mode 100644
index 000000000..53ab787c4
--- /dev/null
+++ b/MediaBrowser.UI/ViewModels/ChapterInfoDtoViewModel.cs
@@ -0,0 +1,182 @@
+using MediaBrowser.Model.DTO;
+using MediaBrowser.Model.Entities;
+using MediaBrowser.Model.Net;
+using System;
+using System.Linq;
+using System.Windows.Media.Imaging;
+
+namespace MediaBrowser.UI.ViewModels
+{
+ /// <summary>
+ /// Class ChapterInfoDtoViewModel
+ /// </summary>
+ public class ChapterInfoDtoViewModel : BaseViewModel
+ {
+ /// <summary>
+ /// Gets or sets the image download options.
+ /// </summary>
+ /// <value>The image download options.</value>
+ public ImageOptions ImageDownloadOptions { get; set; }
+
+ /// <summary>
+ /// The _image width
+ /// </summary>
+ private double _imageWidth;
+ /// <summary>
+ /// Gets or sets the width of the image.
+ /// </summary>
+ /// <value>The width of the image.</value>
+ public double ImageWidth
+ {
+ get { return _imageWidth; }
+
+ set
+ {
+ _imageWidth = value;
+ OnPropertyChanged("ImageWidth");
+ }
+ }
+
+ /// <summary>
+ /// The _image height
+ /// </summary>
+ private double _imageHeight;
+ /// <summary>
+ /// Gets or sets the height of the image.
+ /// </summary>
+ /// <value>The height of the image.</value>
+ public double ImageHeight
+ {
+ get { return _imageHeight; }
+
+ set
+ {
+ _imageHeight = value;
+ OnPropertyChanged("ImageHeight");
+ }
+ }
+
+ /// <summary>
+ /// The _item
+ /// </summary>
+ private ChapterInfoDto _chapter;
+ /// <summary>
+ /// Gets or sets the item.
+ /// </summary>
+ /// <value>The item.</value>
+ public ChapterInfoDto Chapter
+ {
+ get { return _chapter; }
+
+ set
+ {
+ _chapter = value;
+ OnPropertyChanged("Chapter");
+ OnPropertyChanged("TimeString");
+ OnChapterChanged();
+ }
+ }
+
+ /// <summary>
+ /// The _item
+ /// </summary>
+ private DtoBaseItem _item;
+ /// <summary>
+ /// Gets or sets the item.
+ /// </summary>
+ /// <value>The item.</value>
+ public DtoBaseItem Item
+ {
+ get { return _item; }
+
+ set
+ {
+ _item = value;
+ OnPropertyChanged("Item");
+ }
+ }
+
+ /// <summary>
+ /// Gets the time string.
+ /// </summary>
+ /// <value>The time string.</value>
+ public string TimeString
+ {
+ get
+ {
+ var time = TimeSpan.FromTicks(Chapter.StartPositionTicks);
+
+ return time.ToString(time.TotalHours < 1 ? "m':'ss" : "h':'mm':'ss");
+ }
+ }
+
+ /// <summary>
+ /// The _image
+ /// </summary>
+ private BitmapImage _image;
+ /// <summary>
+ /// Gets the image.
+ /// </summary>
+ /// <value>The image.</value>
+ public BitmapImage Image
+ {
+ get { return _image; }
+ set
+ {
+ _image = value;
+ OnPropertyChanged("Image");
+ }
+ }
+
+ /// <summary>
+ /// Called when [item changed].
+ /// </summary>
+ private async void OnChapterChanged()
+ {
+ var options = ImageDownloadOptions ?? new ImageOptions { };
+
+ options.ImageType = ImageType.ChapterImage;
+ options.ImageIndex = Item.Chapters.IndexOf(Chapter);
+
+ try
+ {
+ Image = await App.Instance.GetRemoteBitmapAsync(App.Instance.ApiClient.GetImageUrl(Item, options));
+ }
+ catch (HttpException)
+ {
+ }
+ }
+
+ /// <summary>
+ /// Gets the height of the chapter image.
+ /// </summary>
+ /// <param name="item">The item.</param>
+ /// <param name="height">The height.</param>
+ /// <param name="defaultWidth">The default width.</param>
+ /// <returns>System.Double.</returns>
+ public static double GetChapterImageWidth(DtoBaseItem item, double height, double defaultWidth)
+ {
+ var width = defaultWidth;
+
+ if (item.MediaStreams != null)
+ {
+ var videoStream = item.MediaStreams.FirstOrDefault(s => s.Type == MediaStreamType.Video);
+
+ if (videoStream != null)
+ {
+ double streamHeight = videoStream.Height ?? 0;
+ double streamWidth = videoStream.Width ?? 0;
+
+ if (streamHeight > 0 && streamWidth > 0)
+ {
+ var aspectRatio = streamWidth / streamHeight;
+
+ width = height * aspectRatio;
+ }
+ }
+ }
+
+ return width;
+ }
+ }
+}
diff --git a/MediaBrowser.UI/ViewModels/DtoBaseItemViewModel.cs b/MediaBrowser.UI/ViewModels/DtoBaseItemViewModel.cs
new file mode 100644
index 000000000..0c9e27db3
--- /dev/null
+++ b/MediaBrowser.UI/ViewModels/DtoBaseItemViewModel.cs
@@ -0,0 +1,184 @@
+using MediaBrowser.Common.Logging;
+using MediaBrowser.Model.DTO;
+using MediaBrowser.Model.Entities;
+using MediaBrowser.UI.Pages;
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Linq;
+
+namespace MediaBrowser.UI.ViewModels
+{
+ /// <summary>
+ /// Class DtoBaseItemViewModel
+ /// </summary>
+ public class DtoBaseItemViewModel : BaseViewModel
+ {
+ /// <summary>
+ /// The _average primary image aspect ratio
+ /// </summary>
+ private double _averagePrimaryImageAspectRatio;
+ /// <summary>
+ /// Gets the aspect ratio that should be used if displaying the primary image
+ /// </summary>
+ /// <value>The average primary image aspect ratio.</value>
+ public double AveragePrimaryImageAspectRatio
+ {
+ get { return _averagePrimaryImageAspectRatio; }
+
+ set
+ {
+ _averagePrimaryImageAspectRatio = value;
+ OnPropertyChanged("AveragePrimaryImageAspectRatio");
+ }
+ }
+
+ /// <summary>
+ /// The _parent display preferences
+ /// </summary>
+ private DisplayPreferences _parentDisplayPreferences;
+ /// <summary>
+ /// Gets of sets the current DisplayPreferences
+ /// </summary>
+ /// <value>The parent display preferences.</value>
+ public DisplayPreferences ParentDisplayPreferences
+ {
+ get { return _parentDisplayPreferences; }
+
+ set
+ {
+ _parentDisplayPreferences = value;
+ NotifyDisplayPreferencesChanged();
+ }
+ }
+
+ /// <summary>
+ /// The _item
+ /// </summary>
+ private DtoBaseItem _item;
+ /// <summary>
+ /// Gets or sets the item.
+ /// </summary>
+ /// <value>The item.</value>
+ public DtoBaseItem Item
+ {
+ get { return _item; }
+
+ set
+ {
+ _item = value;
+ OnPropertyChanged("Item");
+ }
+ }
+
+ /// <summary>
+ /// Notifies the display preferences changed.
+ /// </summary>
+ public void NotifyDisplayPreferencesChanged()
+ {
+ OnPropertyChanged("DisplayPreferences");
+ }
+
+ /// <summary>
+ /// Gets an image url that can be used to download an image from the api
+ /// </summary>
+ /// <param name="imageType">The type of image requested</param>
+ /// <param name="imageIndex">The image index, if there are multiple. Currently only applies to backdrops. Supply null or 0 for first backdrop.</param>
+ /// <returns>System.String.</returns>
+ public string GetImageUrl(ImageType imageType, int? imageIndex = null)
+ {
+ var height = ParentDisplayPreferences.PrimaryImageHeight;
+
+ var averageAspectRatio = BaseFolderPage.GetAspectRatio(imageType, AveragePrimaryImageAspectRatio);
+
+ var width = height * averageAspectRatio;
+
+ var imageOptions = new ImageOptions
+ {
+ ImageType = imageType,
+ ImageIndex = imageIndex,
+ Height = height
+ };
+
+ if (imageType == ImageType.Primary)
+ {
+ var currentAspectRatio = imageType == ImageType.Primary ? Item.PrimaryImageAspectRatio ?? width / height : width / height;
+
+ // Preserve the exact AR if it deviates from the average significantly
+ var preserveExactAspectRatio = Math.Abs(currentAspectRatio - averageAspectRatio) > .10;
+
+ if (!preserveExactAspectRatio)
+ {
+ imageOptions.Width = Convert.ToInt32(width);
+ }
+ }
+
+ return App.Instance.ApiClient.GetImageUrl(Item, imageOptions);
+ }
+
+ /// <summary>
+ /// Gets the average primary image aspect ratio.
+ /// </summary>
+ /// <param name="items">The items.</param>
+ /// <returns>System.Double.</returns>
+ /// <exception cref="System.ArgumentNullException">items</exception>
+ public static double GetAveragePrimaryImageAspectRatio(IEnumerable<DtoBaseItem> items)
+ {
+ if (items == null)
+ {
+ throw new ArgumentNullException("items");
+ }
+
+ double total = 0;
+ var count = 0;
+
+ foreach (var child in items)
+ {
+ var ratio = child.PrimaryImageAspectRatio ?? 0;
+
+ if (ratio.Equals(0))
+ {
+ continue;
+ }
+
+ total += ratio;
+ count++;
+ }
+
+ return count == 0 ? 1 : total / count;
+ }
+
+ /// <summary>
+ /// Gets the observable items.
+ /// </summary>
+ /// <param name="items">The items.</param>
+ /// <returns>ObservableCollection{DtoBaseItemViewModel}.</returns>
+ public static ObservableCollection<DtoBaseItemViewModel> GetObservableItems(DtoBaseItem[] items)
+ {
+ return GetObservableItems(items, GetAveragePrimaryImageAspectRatio(items));
+ }
+
+ /// <summary>
+ /// Gets the observable items.
+ /// </summary>
+ /// <param name="items">The items.</param>
+ /// <param name="averagePrimaryImageAspectRatio">The average primary image aspect ratio.</param>
+ /// <param name="parentDisplayPreferences">The parent display preferences.</param>
+ /// <returns>ObservableCollection{DtoBaseItemViewModel}.</returns>
+ /// <exception cref="System.ArgumentNullException">items</exception>
+ public static ObservableCollection<DtoBaseItemViewModel> GetObservableItems(IEnumerable<DtoBaseItem> items, double averagePrimaryImageAspectRatio, DisplayPreferences parentDisplayPreferences = null)
+ {
+ if (items == null)
+ {
+ throw new ArgumentNullException("items");
+ }
+
+ return new ObservableCollection<DtoBaseItemViewModel>(items.Select(i => new DtoBaseItemViewModel
+ {
+ Item = i,
+ ParentDisplayPreferences = parentDisplayPreferences,
+ AveragePrimaryImageAspectRatio = averagePrimaryImageAspectRatio
+ }));
+ }
+ }
+}
diff --git a/MediaBrowser.UI/ViewModels/ItemCollectionViewModel.cs b/MediaBrowser.UI/ViewModels/ItemCollectionViewModel.cs
new file mode 100644
index 000000000..82feedbd7
--- /dev/null
+++ b/MediaBrowser.UI/ViewModels/ItemCollectionViewModel.cs
@@ -0,0 +1,158 @@
+using MediaBrowser.Model.DTO;
+using System;
+using System.Threading;
+using System.Windows;
+
+namespace MediaBrowser.UI.ViewModels
+{
+ /// <summary>
+ /// Represents a view model that contains multiple items.
+ /// This should be used if you want to display a button or list item that holds more than one item,
+ /// and cycle through them periodically.
+ /// </summary>
+ public class ItemCollectionViewModel : BaseViewModel, IDisposable
+ {
+ private int RotationPeriodMs { get; set; }
+
+ public ItemCollectionViewModel(int rotationPeriodMs = 10000, int rotationDevaiationMs = 2000)
+ : base()
+ {
+ if (rotationDevaiationMs > 0)
+ {
+ rotationPeriodMs += new Random(Guid.NewGuid().GetHashCode()).Next(0 - rotationDevaiationMs, rotationDevaiationMs);
+ }
+
+ RotationPeriodMs = rotationPeriodMs;
+ }
+
+ /// <summary>
+ /// Gets the timer that updates the current item
+ /// </summary>
+ private Timer CurrentItemTimer { get; set; }
+
+ private string _name;
+ /// <summary>
+ /// Gets or sets the name of the collection
+ /// </summary>
+ public string Name
+ {
+ get { return _name; }
+ set
+ {
+ _name = value;
+ OnPropertyChanged("Name");
+ }
+ }
+
+ private DtoBaseItem[] _items;
+ /// <summary>
+ /// Gets or sets the list of items
+ /// </summary>
+ public DtoBaseItem[] Items
+ {
+ get { return _items; }
+ set
+ {
+ _items = value ?? new DtoBaseItem[] { };
+ OnPropertyChanged("Items");
+ CurrentItemIndex = Items.Length == 0 ? -1 : 0;
+
+ ReloadTimer();
+ }
+ }
+
+ private int _currentItemIndex;
+ /// <summary>
+ /// Gets or sets the index of the current item
+ /// </summary>
+ public int CurrentItemIndex
+ {
+ get { return _currentItemIndex; }
+ set
+ {
+ _currentItemIndex = value;
+ OnPropertyChanged("CurrentItemIndex");
+ OnPropertyChanged("CurrentItem");
+ OnPropertyChanged("NextItem");
+ }
+ }
+
+ /// <summary>
+ /// Gets the current item
+ /// </summary>
+ public DtoBaseItem CurrentItem
+ {
+ get { return CurrentItemIndex == -1 ? null : Items[CurrentItemIndex]; }
+ }
+
+ /// <summary>
+ /// Gets the next item
+ /// </summary>
+ public DtoBaseItem NextItem
+ {
+ get
+ {
+ if (CurrentItem == null || CurrentItemIndex == -1)
+ {
+ return null;
+ }
+ var index = CurrentItemIndex + 1;
+
+ if (index >= Items.Length)
+ {
+ index = 0;
+ }
+
+ return Items[index];
+ }
+ }
+
+ /// <summary>
+ /// Disposes the timer
+ /// </summary>
+ private void DisposeTimer()
+ {
+ if (CurrentItemTimer != null)
+ {
+ CurrentItemTimer.Dispose();
+ }
+ }
+
+ /// <summary>
+ /// Reloads the timer
+ /// </summary>
+ private void ReloadTimer()
+ {
+ DisposeTimer();
+
+ // Don't bother unless there's at least two items
+ if (Items.Length > 1)
+ {
+ CurrentItemTimer = new Timer(state => Application.Current.Dispatcher.InvokeAsync(IncrementCurrentItemIndex), null, RotationPeriodMs, RotationPeriodMs);
+ }
+ }
+
+ /// <summary>
+ /// Increments current item index, or resets it back to zero if we're at the end of the list
+ /// </summary>
+ private void IncrementCurrentItemIndex()
+ {
+ var newIndex = CurrentItemIndex + 1;
+
+ if (newIndex >= Items.Length)
+ {
+ newIndex = 0;
+ }
+
+ CurrentItemIndex = newIndex;
+ }
+
+ /// <summary>
+ /// Disposes the collection
+ /// </summary>
+ public void Dispose()
+ {
+ DisposeTimer();
+ }
+ }
+}
diff --git a/MediaBrowser.UI/ViewModels/SpecialFeatureViewModel.cs b/MediaBrowser.UI/ViewModels/SpecialFeatureViewModel.cs
new file mode 100644
index 000000000..9d7b9d39d
--- /dev/null
+++ b/MediaBrowser.UI/ViewModels/SpecialFeatureViewModel.cs
@@ -0,0 +1,135 @@
+using MediaBrowser.Model.DTO;
+using MediaBrowser.Model.Entities;
+using MediaBrowser.Model.Net;
+using System;
+using System.Windows.Media.Imaging;
+
+namespace MediaBrowser.UI.ViewModels
+{
+ /// <summary>
+ /// Class SpecialFeatureViewModel
+ /// </summary>
+ public class SpecialFeatureViewModel : BaseViewModel
+ {
+ /// <summary>
+ /// Gets or sets the image download options.
+ /// </summary>
+ /// <value>The image download options.</value>
+ public ImageOptions ImageDownloadOptions { get; set; }
+
+ /// <summary>
+ /// The _image width
+ /// </summary>
+ private double _imageWidth;
+ /// <summary>
+ /// Gets or sets the width of the image.
+ /// </summary>
+ /// <value>The width of the image.</value>
+ public double ImageWidth
+ {
+ get { return _imageWidth; }
+
+ set
+ {
+ _imageWidth = value;
+ OnPropertyChanged("ImageWidth");
+ }
+ }
+
+ /// <summary>
+ /// The _image height
+ /// </summary>
+ private double _imageHeight;
+ /// <summary>
+ /// Gets or sets the height of the image.
+ /// </summary>
+ /// <value>The height of the image.</value>
+ public double ImageHeight
+ {
+ get { return _imageHeight; }
+
+ set
+ {
+ _imageHeight = value;
+ OnPropertyChanged("ImageHeight");
+ }
+ }
+
+ /// <summary>
+ /// The _item
+ /// </summary>
+ private DtoBaseItem _item;
+ /// <summary>
+ /// Gets or sets the item.
+ /// </summary>
+ /// <value>The item.</value>
+ public DtoBaseItem Item
+ {
+ get { return _item; }
+
+ set
+ {
+ _item = value;
+ OnPropertyChanged("Item");
+ OnItemChanged();
+ }
+ }
+
+ /// <summary>
+ /// Gets the time string.
+ /// </summary>
+ /// <value>The time string.</value>
+ public string MinutesString
+ {
+ get
+ {
+ var time = TimeSpan.FromTicks(Item.RunTimeTicks ?? 0);
+
+ var minutes = Math.Round(time.TotalMinutes);
+
+ if (minutes <= 1)
+ {
+ return "1 minute";
+ }
+
+ return string.Format("{0} minutes", minutes);
+ }
+ }
+
+ /// <summary>
+ /// The _image
+ /// </summary>
+ private BitmapImage _image;
+ /// <summary>
+ /// Gets the image.
+ /// </summary>
+ /// <value>The image.</value>
+ public BitmapImage Image
+ {
+ get { return _image; }
+ set
+ {
+ _image = value;
+ OnPropertyChanged("Image");
+ }
+ }
+
+ /// <summary>
+ /// Called when [item changed].
+ /// </summary>
+ private async void OnItemChanged()
+ {
+ var options = ImageDownloadOptions ?? new ImageOptions { };
+
+ options.ImageType = ImageType.Primary;
+
+ try
+ {
+ Image = await App.Instance.GetRemoteBitmapAsync(App.Instance.ApiClient.GetImageUrl(Item, options));
+ }
+ catch (HttpException)
+ {
+ }
+ }
+ }
+}