aboutsummaryrefslogtreecommitdiff
path: root/MediaBrowser.Plugins.DefaultTheme/Controls
diff options
context:
space:
mode:
Diffstat (limited to 'MediaBrowser.Plugins.DefaultTheme/Controls')
-rw-r--r--MediaBrowser.Plugins.DefaultTheme/Controls/BaseItemTile.xaml23
-rw-r--r--MediaBrowser.Plugins.DefaultTheme/Controls/BaseItemTile.xaml.cs177
-rw-r--r--MediaBrowser.Plugins.DefaultTheme/Controls/Details/BaseDetailsControl.cs44
-rw-r--r--MediaBrowser.Plugins.DefaultTheme/Controls/Details/ItemChapters.xaml23
-rw-r--r--MediaBrowser.Plugins.DefaultTheme/Controls/Details/ItemChapters.xaml.cs67
-rw-r--r--MediaBrowser.Plugins.DefaultTheme/Controls/Details/ItemGallery.xaml23
-rw-r--r--MediaBrowser.Plugins.DefaultTheme/Controls/Details/ItemGallery.xaml.cs163
-rw-r--r--MediaBrowser.Plugins.DefaultTheme/Controls/Details/ItemMediaInfo.xaml22
-rw-r--r--MediaBrowser.Plugins.DefaultTheme/Controls/Details/ItemMediaInfo.xaml.cs49
-rw-r--r--MediaBrowser.Plugins.DefaultTheme/Controls/Details/ItemOverview.xaml68
-rw-r--r--MediaBrowser.Plugins.DefaultTheme/Controls/Details/ItemOverview.xaml.cs109
-rw-r--r--MediaBrowser.Plugins.DefaultTheme/Controls/Details/ItemPerformers.xaml23
-rw-r--r--MediaBrowser.Plugins.DefaultTheme/Controls/Details/ItemPerformers.xaml.cs72
-rw-r--r--MediaBrowser.Plugins.DefaultTheme/Controls/Details/ItemSpecialFeatures.xaml23
-rw-r--r--MediaBrowser.Plugins.DefaultTheme/Controls/Details/ItemSpecialFeatures.xaml.cs77
-rw-r--r--MediaBrowser.Plugins.DefaultTheme/Controls/Details/ItemTrailers.xaml23
-rw-r--r--MediaBrowser.Plugins.DefaultTheme/Controls/Details/ItemTrailers.xaml.cs82
-rw-r--r--MediaBrowser.Plugins.DefaultTheme/Controls/Details/MediaStreamControl.xaml18
-rw-r--r--MediaBrowser.Plugins.DefaultTheme/Controls/Details/MediaStreamControl.xaml.cs142
-rw-r--r--MediaBrowser.Plugins.DefaultTheme/Controls/HomePageTile.xaml22
-rw-r--r--MediaBrowser.Plugins.DefaultTheme/Controls/HomePageTile.xaml.cs128
-rw-r--r--MediaBrowser.Plugins.DefaultTheme/Controls/MultiItemTile.xaml30
-rw-r--r--MediaBrowser.Plugins.DefaultTheme/Controls/MultiItemTile.xaml.cs219
23 files changed, 1627 insertions, 0 deletions
diff --git a/MediaBrowser.Plugins.DefaultTheme/Controls/BaseItemTile.xaml b/MediaBrowser.Plugins.DefaultTheme/Controls/BaseItemTile.xaml
new file mode 100644
index 000000000..a66b1c403
--- /dev/null
+++ b/MediaBrowser.Plugins.DefaultTheme/Controls/BaseItemTile.xaml
@@ -0,0 +1,23 @@
+<controls:BaseUserControl x:Class="MediaBrowser.Plugins.DefaultTheme.Controls.BaseItemTile"
+ xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
+ xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
+ xmlns:controls="clr-namespace:MediaBrowser.UI.Controls;assembly=MediaBrowser.UI.Controls"
+ mc:Ignorable="d"
+ d:DesignHeight="300" d:DesignWidth="300">
+
+ <Grid x:Name="mainGrid" HorizontalAlignment="Center">
+
+ <Border x:Name="border">
+ <Image x:Name="image" Stretch="Uniform"></Image>
+ </Border>
+
+ <Grid HorizontalAlignment="Stretch" VerticalAlignment="Bottom">
+ <Grid.Background>
+ <SolidColorBrush Color="#A6000000"></SolidColorBrush>
+ </Grid.Background>
+ <TextBlock x:Name="txtName" Margin="10 5 0 10" Foreground="White" TextWrapping="Wrap" Style="{StaticResource TextBlockStyle}"></TextBlock>
+ </Grid>
+ </Grid>
+</controls:BaseUserControl>
diff --git a/MediaBrowser.Plugins.DefaultTheme/Controls/BaseItemTile.xaml.cs b/MediaBrowser.Plugins.DefaultTheme/Controls/BaseItemTile.xaml.cs
new file mode 100644
index 000000000..7789584ed
--- /dev/null
+++ b/MediaBrowser.Plugins.DefaultTheme/Controls/BaseItemTile.xaml.cs
@@ -0,0 +1,177 @@
+using MediaBrowser.Model.DTO;
+using MediaBrowser.Model.Net;
+using MediaBrowser.UI;
+using MediaBrowser.UI.Controls;
+using MediaBrowser.UI.Converters;
+using MediaBrowser.UI.ViewModels;
+using System;
+using System.ComponentModel;
+using System.Windows;
+
+namespace MediaBrowser.Plugins.DefaultTheme.Controls
+{
+ /// <summary>
+ /// Interaction logic for BaseItemTile.xaml
+ /// </summary>
+ public partial class BaseItemTile : BaseUserControl
+ {
+ /// <summary>
+ /// Gets the view model.
+ /// </summary>
+ /// <value>The view model.</value>
+ public DtoBaseItemViewModel ViewModel
+ {
+ get { return DataContext as DtoBaseItemViewModel; }
+ }
+
+ /// <summary>
+ /// Gets the item.
+ /// </summary>
+ /// <value>The item.</value>
+ private DtoBaseItem Item
+ {
+ get { return ViewModel.Item; }
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="BaseItemTile" /> class.
+ /// </summary>
+ public BaseItemTile()
+ {
+ InitializeComponent();
+
+ DataContextChanged += BaseItemTile_DataContextChanged;
+ Loaded += BaseItemTile_Loaded;
+ Unloaded += BaseItemTile_Unloaded;
+ }
+
+ /// <summary>
+ /// Handles the Unloaded event of the BaseItemTile control.
+ /// </summary>
+ /// <param name="sender">The source of the event.</param>
+ /// <param name="e">The <see cref="RoutedEventArgs" /> instance containing the event data.</param>
+ void BaseItemTile_Unloaded(object sender, RoutedEventArgs e)
+ {
+ if (ViewModel != null)
+ {
+ ViewModel.PropertyChanged -= ViewModel_PropertyChanged;
+ }
+ }
+
+ /// <summary>
+ /// Handles the Loaded event of the BaseItemTile control.
+ /// </summary>
+ /// <param name="sender">The source of the event.</param>
+ /// <param name="e">The <see cref="RoutedEventArgs" /> instance containing the event data.</param>
+ void BaseItemTile_Loaded(object sender, RoutedEventArgs e)
+ {
+ if (ViewModel != null)
+ {
+ ViewModel.PropertyChanged -= ViewModel_PropertyChanged;
+ ViewModel.PropertyChanged += ViewModel_PropertyChanged;
+ }
+ }
+
+ /// <summary>
+ /// Handles the DataContextChanged event of the BaseItemTile control.
+ /// </summary>
+ /// <param name="sender">The source of the event.</param>
+ /// <param name="e">The <see cref="DependencyPropertyChangedEventArgs" /> instance containing the event data.</param>
+ void BaseItemTile_DataContextChanged(object sender, DependencyPropertyChangedEventArgs e)
+ {
+ OnItemChanged();
+
+ if (ViewModel != null)
+ {
+ ViewModel.PropertyChanged -= ViewModel_PropertyChanged;
+ ViewModel.PropertyChanged += ViewModel_PropertyChanged;
+ }
+ }
+
+ /// <summary>
+ /// Handles the PropertyChanged event of the ViewModel control.
+ /// </summary>
+ /// <param name="sender">The source of the event.</param>
+ /// <param name="e">The <see cref="PropertyChangedEventArgs" /> instance containing the event data.</param>
+ void ViewModel_PropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ ReloadImage();
+ }
+
+ /// <summary>
+ /// Called when [item changed].
+ /// </summary>
+ private void OnItemChanged()
+ {
+ ReloadImage();
+
+ var visibility = Item.HasPrimaryImage && !Item.IsType("Episode") ? Visibility.Collapsed : Visibility.Visible;
+
+ if (Item.IsType("Person") || Item.IsType("IndexFolder"))
+ {
+ visibility = Visibility.Visible;
+ }
+
+ txtName.Visibility = visibility;
+
+ var name = Item.Name;
+
+ if (Item.IndexNumber.HasValue)
+ {
+ name = Item.IndexNumber + " - " + name;
+ }
+
+ txtName.Text = name;
+ }
+
+ /// <summary>
+ /// Reloads the image.
+ /// </summary>
+ private async void ReloadImage()
+ {
+ mainGrid.Height = ViewModel.ParentDisplayPreferences.PrimaryImageHeight;
+ mainGrid.Width = ViewModel.ParentDisplayPreferences.PrimaryImageWidth;
+
+ if (Item.HasPrimaryImage)
+ {
+ var url = ViewModel.GetImageUrl(ViewModel.ParentDisplayPreferences.PrimaryImageType);
+
+ border.Background = null;
+
+ try
+ {
+ image.Source = await App.Instance.GetRemoteBitmapAsync(url);
+ }
+ catch (HttpException)
+ {
+ SetDefaultImage();
+ }
+ }
+ else
+ {
+ SetDefaultImage();
+ }
+ }
+
+ /// <summary>
+ /// Sets the default image.
+ /// </summary>
+ private void SetDefaultImage()
+ {
+ if (Item.IsAudio || Item.IsType("MusicAlbum") || Item.IsType("MusicArtist"))
+ {
+ var imageUri = new Uri("../Resources/Images/AudioDefault.png", UriKind.Relative);
+
+ border.Background = MetroTileBackgroundConverter.GetRandomBackground();
+ image.Source = App.Instance.GetBitmapImage(imageUri);
+ }
+ else
+ {
+ var imageUri = new Uri("../Resources/Images/VideoDefault.png", UriKind.Relative);
+
+ border.Background = MetroTileBackgroundConverter.GetRandomBackground();
+ image.Source = App.Instance.GetBitmapImage(imageUri);
+ }
+ }
+ }
+}
diff --git a/MediaBrowser.Plugins.DefaultTheme/Controls/Details/BaseDetailsControl.cs b/MediaBrowser.Plugins.DefaultTheme/Controls/Details/BaseDetailsControl.cs
new file mode 100644
index 000000000..66dbb9c98
--- /dev/null
+++ b/MediaBrowser.Plugins.DefaultTheme/Controls/Details/BaseDetailsControl.cs
@@ -0,0 +1,44 @@
+using MediaBrowser.Model.DTO;
+using MediaBrowser.UI.Controls;
+
+namespace MediaBrowser.Plugins.DefaultTheme.Controls.Details
+{
+ /// <summary>
+ /// Class BaseDetailsControl
+ /// </summary>
+ public abstract class BaseDetailsControl : BaseUserControl
+ {
+ /// <summary>
+ /// Initializes a new instance of the <see cref="BaseDetailsControl" /> class.
+ /// </summary>
+ protected BaseDetailsControl()
+ {
+ DataContext = this;
+ }
+
+ /// <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>
+ /// Called when [item changed].
+ /// </summary>
+ protected abstract void OnItemChanged();
+ }
+}
diff --git a/MediaBrowser.Plugins.DefaultTheme/Controls/Details/ItemChapters.xaml b/MediaBrowser.Plugins.DefaultTheme/Controls/Details/ItemChapters.xaml
new file mode 100644
index 000000000..4282316b4
--- /dev/null
+++ b/MediaBrowser.Plugins.DefaultTheme/Controls/Details/ItemChapters.xaml
@@ -0,0 +1,23 @@
+<details:BaseDetailsControl x:Class="MediaBrowser.Plugins.DefaultTheme.Controls.Details.ItemChapters"
+ xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
+ xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
+ xmlns:details="clr-namespace:MediaBrowser.Plugins.DefaultTheme.Controls.Details"
+ xmlns:controls="clr-namespace:MediaBrowser.UI.Controls;assembly=MediaBrowser.UI.Controls"
+ mc:Ignorable="d"
+ d:DesignHeight="300" d:DesignWidth="300">
+ <Grid>
+ <controls:ExtendedScrollViewer ScrollViewer.HorizontalScrollBarVisibility="Hidden" ScrollViewer.VerticalScrollBarVisibility="Disabled" CanContentScroll="True">
+ <controls:ScrollingPanel CanHorizontallyScroll="True" CanVerticallyScroll="False">
+ <controls:ExtendedListBox x:Name="lstItems" HorizontalAlignment="Center" VerticalAlignment="Top" ScrollViewer.VerticalScrollBarVisibility="Disabled" ScrollViewer.HorizontalScrollBarVisibility="Disabled" ItemTemplate="{StaticResource ItemChaptersTemplate}" Style="{StaticResource ListBoxStyle}" ItemContainerStyle="{StaticResource ListBoxItemStyle}">
+ <controls:ExtendedListBox.ItemsPanel>
+ <ItemsPanelTemplate>
+ <WrapPanel Orientation="Vertical" Margin="50" />
+ </ItemsPanelTemplate>
+ </controls:ExtendedListBox.ItemsPanel>
+ </controls:ExtendedListBox>
+ </controls:ScrollingPanel>
+ </controls:ExtendedScrollViewer>
+ </Grid>
+</details:BaseDetailsControl>
diff --git a/MediaBrowser.Plugins.DefaultTheme/Controls/Details/ItemChapters.xaml.cs b/MediaBrowser.Plugins.DefaultTheme/Controls/Details/ItemChapters.xaml.cs
new file mode 100644
index 000000000..196b92b69
--- /dev/null
+++ b/MediaBrowser.Plugins.DefaultTheme/Controls/Details/ItemChapters.xaml.cs
@@ -0,0 +1,67 @@
+using MediaBrowser.Model.DTO;
+using MediaBrowser.UI.Controller;
+using MediaBrowser.UI.Controls;
+using MediaBrowser.UI.Playback;
+using MediaBrowser.UI.ViewModels;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Linq;
+
+namespace MediaBrowser.Plugins.DefaultTheme.Controls.Details
+{
+ /// <summary>
+ /// Interaction logic for ItemChapters.xaml
+ /// </summary>
+ public partial class ItemChapters : BaseDetailsControl
+ {
+ /// <summary>
+ /// Initializes a new instance of the <see cref="ItemChapters" /> class.
+ /// </summary>
+ public ItemChapters()
+ {
+ InitializeComponent();
+
+ lstItems.ItemInvoked += lstItems_ItemInvoked;
+ }
+
+ /// <summary>
+ /// LSTs the items_ item invoked.
+ /// </summary>
+ /// <param name="sender">The sender.</param>
+ /// <param name="e">The e.</param>
+ void lstItems_ItemInvoked(object sender, ItemEventArgs<object> e)
+ {
+ var chapterViewModel = (ChapterInfoDtoViewModel) e.Argument;
+
+ UIKernel.Instance.PlaybackManager.Play(new PlayOptions
+ {
+ Items = new List<DtoBaseItem> { Item },
+ StartPositionTicks = chapterViewModel.Chapter.StartPositionTicks
+ });
+ }
+
+ /// <summary>
+ /// Called when [item changed].
+ /// </summary>
+ protected override void OnItemChanged()
+ {
+ const double height = 297;
+
+ var width = ChapterInfoDtoViewModel.GetChapterImageWidth(Item, height, 528);
+
+ var chapters = Item.Chapters ?? new List<ChapterInfoDto> { };
+
+ lstItems.ItemsSource = new ObservableCollection<ChapterInfoDtoViewModel>(chapters.Select(i => new ChapterInfoDtoViewModel
+ {
+ Item = Item,
+ Chapter = i,
+ ImageWidth = width,
+ ImageHeight = height,
+ ImageDownloadOptions = new ImageOptions
+ {
+ MaxHeight = 400
+ }
+ }));
+ }
+ }
+}
diff --git a/MediaBrowser.Plugins.DefaultTheme/Controls/Details/ItemGallery.xaml b/MediaBrowser.Plugins.DefaultTheme/Controls/Details/ItemGallery.xaml
new file mode 100644
index 000000000..312742558
--- /dev/null
+++ b/MediaBrowser.Plugins.DefaultTheme/Controls/Details/ItemGallery.xaml
@@ -0,0 +1,23 @@
+<details:BaseDetailsControl x:Class="MediaBrowser.Plugins.DefaultTheme.Controls.Details.ItemGallery"
+ xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
+ xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
+ xmlns:details="clr-namespace:MediaBrowser.Plugins.DefaultTheme.Controls.Details"
+ xmlns:controls="clr-namespace:MediaBrowser.UI.Controls;assembly=MediaBrowser.UI.Controls"
+ mc:Ignorable="d"
+ d:DesignHeight="300" d:DesignWidth="300">
+ <Grid>
+ <controls:ExtendedScrollViewer ScrollViewer.HorizontalScrollBarVisibility="Hidden" ScrollViewer.VerticalScrollBarVisibility="Disabled" CanContentScroll="True">
+ <controls:ScrollingPanel CanHorizontallyScroll="True" CanVerticallyScroll="False">
+ <controls:ExtendedListBox VerticalAlignment="Top" HorizontalAlignment="Center" x:Name="lstItems" ScrollViewer.VerticalScrollBarVisibility="Disabled" ScrollViewer.HorizontalScrollBarVisibility="Disabled" ItemTemplate="{StaticResource ItemGalleryTemplate}" Style="{StaticResource ListBoxStyle}" ItemContainerStyle="{StaticResource ListBoxItemStyle}">
+ <controls:ExtendedListBox.ItemsPanel>
+ <ItemsPanelTemplate>
+ <WrapPanel Orientation="Vertical" Margin="50" />
+ </ItemsPanelTemplate>
+ </controls:ExtendedListBox.ItemsPanel>
+ </controls:ExtendedListBox>
+ </controls:ScrollingPanel>
+ </controls:ExtendedScrollViewer>
+ </Grid>
+</details:BaseDetailsControl>
diff --git a/MediaBrowser.Plugins.DefaultTheme/Controls/Details/ItemGallery.xaml.cs b/MediaBrowser.Plugins.DefaultTheme/Controls/Details/ItemGallery.xaml.cs
new file mode 100644
index 000000000..d0fa85bf2
--- /dev/null
+++ b/MediaBrowser.Plugins.DefaultTheme/Controls/Details/ItemGallery.xaml.cs
@@ -0,0 +1,163 @@
+using MediaBrowser.Model.DTO;
+using MediaBrowser.Model.Entities;
+using MediaBrowser.Model.Net;
+using MediaBrowser.UI;
+using MediaBrowser.UI.Controller;
+using MediaBrowser.UI.Controls;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+using System.Windows.Media.Imaging;
+
+namespace MediaBrowser.Plugins.DefaultTheme.Controls.Details
+{
+ /// <summary>
+ /// Interaction logic for ItemGallery.xaml
+ /// </summary>
+ public partial class ItemGallery : BaseDetailsControl
+ {
+ /// <summary>
+ /// Initializes a new instance of the <see cref="ItemGallery" /> class.
+ /// </summary>
+ public ItemGallery()
+ : base()
+ {
+ InitializeComponent();
+ lstItems.ItemInvoked += lstItems_ItemInvoked;
+ }
+
+ /// <summary>
+ /// LSTs the items_ item invoked.
+ /// </summary>
+ /// <param name="sender">The sender.</param>
+ /// <param name="e">The e.</param>
+ void lstItems_ItemInvoked(object sender, ItemEventArgs<object> e)
+ {
+ var img = (BitmapImage)e.Argument;
+
+ var index = Images.IndexOf(img);
+
+ //App.Instance.OpenImageViewer(new Uri(ImageUrls[index]), Item.Name);
+ }
+
+ /// <summary>
+ /// The _images
+ /// </summary>
+ private List<BitmapImage> _images;
+ /// <summary>
+ /// Gets or sets the images.
+ /// </summary>
+ /// <value>The images.</value>
+ public List<BitmapImage> Images
+ {
+ get { return _images; }
+ set
+ {
+ _images = value;
+ lstItems.ItemsSource = value;
+ OnPropertyChanged("Images");
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the image urls.
+ /// </summary>
+ /// <value>The image urls.</value>
+ private List<string> ImageUrls { get; set; }
+
+ /// <summary>
+ /// Called when [item changed].
+ /// </summary>
+ protected override async void OnItemChanged()
+ {
+ ImageUrls = GetImages(Item);
+
+ var tasks = ImageUrls.Select(GetImage);
+
+ var results = await Task.WhenAll(tasks);
+
+ Images = results.Where(i => i != null).ToList();
+ }
+
+ /// <summary>
+ /// Gets the image.
+ /// </summary>
+ /// <param name="url">The URL.</param>
+ /// <returns>Task{BitmapImage}.</returns>
+ private async Task<BitmapImage> GetImage(string url)
+ {
+ try
+ {
+ return await App.Instance.GetRemoteBitmapAsync(url);
+ }
+ catch (HttpException)
+ {
+ return null;
+ }
+ }
+
+ /// <summary>
+ /// Gets the images.
+ /// </summary>
+ /// <param name="item">The item.</param>
+ /// <returns>List{System.String}.</returns>
+ internal static List<string> GetImages(DtoBaseItem item)
+ {
+ var images = new List<string> { };
+
+ if (item.BackdropCount > 0)
+ {
+ for (var i = 0; i < item.BackdropCount; i++)
+ {
+ images.Add(UIKernel.Instance.ApiClient.GetImageUrl(item, new ImageOptions
+ {
+ ImageType = ImageType.Backdrop,
+ ImageIndex = i
+ }));
+ }
+ }
+
+ if (item.HasThumb)
+ {
+ images.Add(UIKernel.Instance.ApiClient.GetImageUrl(item, new ImageOptions
+ {
+ ImageType = ImageType.Thumb
+ }));
+ }
+
+ if (item.HasArtImage)
+ {
+ images.Add(UIKernel.Instance.ApiClient.GetImageUrl(item, new ImageOptions
+ {
+ ImageType = ImageType.Art
+ }));
+ }
+
+ if (item.HasDiscImage)
+ {
+ images.Add(UIKernel.Instance.ApiClient.GetImageUrl(item, new ImageOptions
+ {
+ ImageType = ImageType.Disc
+ }));
+ }
+
+ if (item.HasMenuImage)
+ {
+ images.Add(UIKernel.Instance.ApiClient.GetImageUrl(item, new ImageOptions
+ {
+ ImageType = ImageType.Menu
+ }));
+ }
+
+ if (item.HasBoxImage)
+ {
+ images.Add(UIKernel.Instance.ApiClient.GetImageUrl(item, new ImageOptions
+ {
+ ImageType = ImageType.Box
+ }));
+ }
+
+ return images;
+ }
+ }
+}
diff --git a/MediaBrowser.Plugins.DefaultTheme/Controls/Details/ItemMediaInfo.xaml b/MediaBrowser.Plugins.DefaultTheme/Controls/Details/ItemMediaInfo.xaml
new file mode 100644
index 000000000..0cae37a35
--- /dev/null
+++ b/MediaBrowser.Plugins.DefaultTheme/Controls/Details/ItemMediaInfo.xaml
@@ -0,0 +1,22 @@
+<details:BaseDetailsControl x:Class="MediaBrowser.Plugins.DefaultTheme.Controls.Details.ItemMediaInfo"
+ xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
+ xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
+ xmlns:details="clr-namespace:MediaBrowser.Plugins.DefaultTheme.Controls.Details"
+ mc:Ignorable="d"
+ d:DesignHeight="300" d:DesignWidth="300">
+ <Grid>
+ <Grid.RowDefinitions>
+ <RowDefinition Height="auto"></RowDefinition>
+ <RowDefinition Height="auto"></RowDefinition>
+ <RowDefinition Height="*"></RowDefinition>
+ </Grid.RowDefinitions>
+
+ <TextBlock Style="{StaticResource TextBlockStyle}" Grid.Row="0" x:Name="TxtPath"></TextBlock>
+
+ <TextBlock Style="{StaticResource TextBlockStyle}" Grid.Row="1" Margin="0 20 0 0" x:Name="TxtVideoFormat"></TextBlock>
+
+ <StackPanel Orientation="Vertical" x:Name="MediaStreams" Grid.Row="2" Margin="0 20 0 0"></StackPanel>
+ </Grid>
+</details:BaseDetailsControl>
diff --git a/MediaBrowser.Plugins.DefaultTheme/Controls/Details/ItemMediaInfo.xaml.cs b/MediaBrowser.Plugins.DefaultTheme/Controls/Details/ItemMediaInfo.xaml.cs
new file mode 100644
index 000000000..3912093c7
--- /dev/null
+++ b/MediaBrowser.Plugins.DefaultTheme/Controls/Details/ItemMediaInfo.xaml.cs
@@ -0,0 +1,49 @@
+using MediaBrowser.Model.Entities;
+using System.Collections.Generic;
+using System.Windows;
+
+namespace MediaBrowser.Plugins.DefaultTheme.Controls.Details
+{
+ /// <summary>
+ /// Interaction logic for ItemMediaInfo.xaml
+ /// </summary>
+ public partial class ItemMediaInfo : BaseDetailsControl
+ {
+ /// <summary>
+ /// Initializes a new instance of the <see cref="ItemMediaInfo" /> class.
+ /// </summary>
+ public ItemMediaInfo()
+ {
+ InitializeComponent();
+ }
+
+ /// <summary>
+ /// Called when [item changed].
+ /// </summary>
+ protected override void OnItemChanged()
+ {
+ MediaStreams.Children.Clear();
+
+ TxtPath.Text = Item.Path;
+
+ if (Item.VideoFormat.HasValue && Item.VideoFormat.Value != VideoFormat.Standard)
+ {
+ TxtVideoFormat.Visibility = Visibility.Visible;
+
+ TxtVideoFormat.Text = Item.VideoFormat.Value == VideoFormat.Digital3D ? "Digital 3D" : "SBS 3D";
+ }
+ else
+ {
+ TxtVideoFormat.Visibility = Visibility.Collapsed;
+ }
+
+ foreach (var stream in Item.MediaStreams ?? new List<MediaStream> {})
+ {
+ MediaStreams.Children.Add(new MediaStreamControl
+ {
+ MediaStream = stream
+ });
+ }
+ }
+ }
+}
diff --git a/MediaBrowser.Plugins.DefaultTheme/Controls/Details/ItemOverview.xaml b/MediaBrowser.Plugins.DefaultTheme/Controls/Details/ItemOverview.xaml
new file mode 100644
index 000000000..32e16ce9d
--- /dev/null
+++ b/MediaBrowser.Plugins.DefaultTheme/Controls/Details/ItemOverview.xaml
@@ -0,0 +1,68 @@
+<details:BaseDetailsControl x:Class="MediaBrowser.Plugins.DefaultTheme.Controls.Details.ItemOverview"
+ xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
+ xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
+ xmlns:details="clr-namespace:MediaBrowser.Plugins.DefaultTheme.Controls.Details"
+ mc:Ignorable="d"
+ d:DesignHeight="300" d:DesignWidth="300">
+ <Grid>
+ <Grid.RowDefinitions>
+ <RowDefinition Height="auto"></RowDefinition>
+ <RowDefinition Height="auto"></RowDefinition>
+ <RowDefinition Height="auto"></RowDefinition>
+ <RowDefinition Height="auto"></RowDefinition>
+ <RowDefinition Height="auto"></RowDefinition>
+ <RowDefinition Height="auto"></RowDefinition>
+ <RowDefinition Height="auto"></RowDefinition>
+ <RowDefinition Height="*"></RowDefinition>
+ </Grid.RowDefinitions>
+
+ <StackPanel Orientation="Horizontal" Grid.Row="0" x:Name="PnlAlbum" Visibility="Collapsed">
+
+ <TextBlock Style="{StaticResource TextBlockStyle}" Width="250" Text="album"></TextBlock>
+ <TextBlock Style="{StaticResource TextBlockStyle}" x:Name="Album"></TextBlock>
+ </StackPanel>
+
+ <StackPanel Orientation="Horizontal" Grid.Row="1" x:Name="PnlArtist" Visibility="Collapsed">
+
+ <TextBlock Style="{StaticResource TextBlockStyle}" Width="250" Text="artist"></TextBlock>
+ <TextBlock Style="{StaticResource TextBlockStyle}" x:Name="Artist"></TextBlock>
+ </StackPanel>
+
+ <StackPanel Orientation="Horizontal" Grid.Row="2" x:Name="PnlAlbumArtist" Visibility="Collapsed">
+
+ <TextBlock Style="{StaticResource TextBlockStyle}" Width="250" Text="album artist"></TextBlock>
+ <TextBlock Style="{StaticResource TextBlockStyle}" x:Name="AlbumArtist"></TextBlock>
+ </StackPanel>
+
+ <StackPanel Orientation="Horizontal" Grid.Row="3" x:Name="PnlDirectors" Visibility="Collapsed">
+
+ <TextBlock Style="{StaticResource TextBlockStyle}" x:Name="DirectorLabel" Width="250"></TextBlock>
+ <TextBlock Style="{StaticResource TextBlockStyle}" x:Name="Directors"></TextBlock>
+ </StackPanel>
+
+ <StackPanel Orientation="Horizontal" Grid.Row="4" x:Name="PnlGenres" Visibility="Collapsed">
+
+ <TextBlock Style="{StaticResource TextBlockStyle}" x:Name="GenreLabel" Width="250"></TextBlock>
+ <TextBlock Style="{StaticResource TextBlockStyle}" x:Name="Genres"></TextBlock>
+ </StackPanel>
+
+ <StackPanel Orientation="Horizontal" Grid.Row="5" x:Name="PnlStudios" Visibility="Collapsed">
+
+ <TextBlock Style="{StaticResource TextBlockStyle}" x:Name="StudiosLabel" Width="250"></TextBlock>
+ <TextBlock Style="{StaticResource TextBlockStyle}" x:Name="Studios"></TextBlock>
+ </StackPanel>
+
+ <StackPanel Orientation="Horizontal" Grid.Row="6" x:Name="PnlPremiereDate" Visibility="Collapsed">
+
+ <TextBlock Style="{StaticResource TextBlockStyle}" Width="250" Text="premiere date"></TextBlock>
+ <TextBlock Style="{StaticResource TextBlockStyle}" x:Name="PremiereDate"></TextBlock>
+ </StackPanel>
+
+ <Grid Grid.Row="7">
+
+ <TextBlock Style="{StaticResource TextBlockStyle}" x:Name="Overview" Margin="0 20 0 0"></TextBlock>
+ </Grid>
+ </Grid>
+</details:BaseDetailsControl>
diff --git a/MediaBrowser.Plugins.DefaultTheme/Controls/Details/ItemOverview.xaml.cs b/MediaBrowser.Plugins.DefaultTheme/Controls/Details/ItemOverview.xaml.cs
new file mode 100644
index 000000000..1654c2c7b
--- /dev/null
+++ b/MediaBrowser.Plugins.DefaultTheme/Controls/Details/ItemOverview.xaml.cs
@@ -0,0 +1,109 @@
+using MediaBrowser.Model.DTO;
+using System;
+using System.Linq;
+using System.Windows;
+
+namespace MediaBrowser.Plugins.DefaultTheme.Controls.Details
+{
+ /// <summary>
+ /// Interaction logic for ItemOverview.xaml
+ /// </summary>
+ public partial class ItemOverview : BaseDetailsControl
+ {
+ /// <summary>
+ /// Initializes a new instance of the <see cref="ItemOverview" /> class.
+ /// </summary>
+ public ItemOverview()
+ : base()
+ {
+ InitializeComponent();
+ }
+
+ /// <summary>
+ /// Called when [item changed].
+ /// </summary>
+ protected override void OnItemChanged()
+ {
+ var directors = (Item.People ?? new BaseItemPerson[] { }).Where(p => string.Equals(p.Type, "director", StringComparison.OrdinalIgnoreCase)).ToList();
+
+ if (directors.Count > 0)
+ {
+ PnlDirectors.Visibility = Visibility.Visible;
+
+ Directors.Text = string.Join(" / ", directors.Take(3).Select(d => d.Name).ToArray());
+ DirectorLabel.Text = directors.Count > 1 ? "directors" : "director";
+ }
+ else
+ {
+ PnlDirectors.Visibility = Visibility.Collapsed;
+ }
+
+ if (Item.Genres != null && Item.Genres.Count > 0)
+ {
+ PnlGenres.Visibility = Visibility.Visible;
+
+ Genres.Text = string.Join(" / ", Item.Genres.Take(4).ToArray());
+ GenreLabel.Text = Item.Genres.Count > 1 ? "genres" : "genre";
+ }
+ else
+ {
+ PnlGenres.Visibility = Visibility.Collapsed;
+ }
+
+ if (Item.Studios != null && Item.Studios.Count > 0)
+ {
+ PnlStudios.Visibility = Visibility.Visible;
+
+ Studios.Text = string.Join(" / ", Item.Studios.Take(3).ToArray());
+ StudiosLabel.Text = Item.Studios.Count > 1 ? "studios" : "studio";
+ }
+ else
+ {
+ PnlStudios.Visibility = Visibility.Collapsed;
+ }
+
+ if (Item.PremiereDate.HasValue)
+ {
+ PnlPremiereDate.Visibility = Visibility.Visible;
+
+ PremiereDate.Text = Item.PremiereDate.Value.ToShortDateString();
+ }
+ else
+ {
+ PnlPremiereDate.Visibility = Visibility.Collapsed;
+ }
+
+ if (!string.IsNullOrEmpty(Item.Artist))
+ {
+ PnlArtist.Visibility = Visibility.Visible;
+ Artist.Text = Item.Artist;
+ }
+ else
+ {
+ PnlArtist.Visibility = Visibility.Collapsed;
+ }
+
+ if (!string.IsNullOrEmpty(Item.Album))
+ {
+ PnlAlbum.Visibility = Visibility.Visible;
+ Album.Text = Item.Artist;
+ }
+ else
+ {
+ PnlAlbum.Visibility = Visibility.Collapsed;
+ }
+
+ if (!string.IsNullOrEmpty(Item.AlbumArtist))
+ {
+ PnlAlbumArtist.Visibility = Visibility.Visible;
+ AlbumArtist.Text = Item.Artist;
+ }
+ else
+ {
+ PnlAlbumArtist.Visibility = Visibility.Collapsed;
+ }
+
+ Overview.Text = Item.Overview;
+ }
+ }
+}
diff --git a/MediaBrowser.Plugins.DefaultTheme/Controls/Details/ItemPerformers.xaml b/MediaBrowser.Plugins.DefaultTheme/Controls/Details/ItemPerformers.xaml
new file mode 100644
index 000000000..6e2bc9f57
--- /dev/null
+++ b/MediaBrowser.Plugins.DefaultTheme/Controls/Details/ItemPerformers.xaml
@@ -0,0 +1,23 @@
+<details:BaseDetailsControl x:Class="MediaBrowser.Plugins.DefaultTheme.Controls.Details.ItemPerformers"
+ xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
+ xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
+ xmlns:details="clr-namespace:MediaBrowser.Plugins.DefaultTheme.Controls.Details"
+ xmlns:controls="clr-namespace:MediaBrowser.UI.Controls;assembly=MediaBrowser.UI.Controls"
+ mc:Ignorable="d"
+ d:DesignHeight="300" d:DesignWidth="300">
+ <Grid>
+ <controls:ExtendedScrollViewer ScrollViewer.HorizontalScrollBarVisibility="Hidden" ScrollViewer.VerticalScrollBarVisibility="Disabled" CanContentScroll="True">
+ <controls:ScrollingPanel CanHorizontallyScroll="False" CanVerticallyScroll="True">
+ <controls:ExtendedListBox VerticalAlignment="Center" x:Name="lstItems" ScrollViewer.VerticalScrollBarVisibility="Disabled" ScrollViewer.HorizontalScrollBarVisibility="Disabled" ItemsSource="{Binding Path=People}" ItemTemplate="{StaticResource ItemPerformersTemplate}" Style="{StaticResource ListBoxStyle}" ItemContainerStyle="{StaticResource ListBoxItemStyle}">
+ <controls:ExtendedListBox.ItemsPanel>
+ <ItemsPanelTemplate>
+ <WrapPanel Orientation="Vertical" Margin="50" />
+ </ItemsPanelTemplate>
+ </controls:ExtendedListBox.ItemsPanel>
+ </controls:ExtendedListBox>
+ </controls:ScrollingPanel>
+ </controls:ExtendedScrollViewer>
+ </Grid>
+</details:BaseDetailsControl>
diff --git a/MediaBrowser.Plugins.DefaultTheme/Controls/Details/ItemPerformers.xaml.cs b/MediaBrowser.Plugins.DefaultTheme/Controls/Details/ItemPerformers.xaml.cs
new file mode 100644
index 000000000..9ad5fdcac
--- /dev/null
+++ b/MediaBrowser.Plugins.DefaultTheme/Controls/Details/ItemPerformers.xaml.cs
@@ -0,0 +1,72 @@
+using MediaBrowser.Model.DTO;
+using MediaBrowser.UI;
+using MediaBrowser.UI.Controller;
+using MediaBrowser.UI.ViewModels;
+using System.Collections.ObjectModel;
+
+namespace MediaBrowser.Plugins.DefaultTheme.Controls.Details
+{
+ /// <summary>
+ /// Interaction logic for ItemPerformers.xaml
+ /// </summary>
+ public partial class ItemPerformers : BaseDetailsControl
+ {
+ /// <summary>
+ /// Initializes a new instance of the <see cref="ItemPerformers" /> class.
+ /// </summary>
+ public ItemPerformers()
+ {
+ InitializeComponent();
+ }
+
+ /// <summary>
+ /// The _itemsResult
+ /// </summary>
+ private ItemsResult _itemsResult;
+ /// <summary>
+ /// Gets or sets the children of the Folder being displayed
+ /// </summary>
+ /// <value>The children.</value>
+ public ItemsResult ItemsResult
+ {
+ get { return _itemsResult; }
+
+ private set
+ {
+ _itemsResult = value;
+ OnPropertyChanged("ItemsResult");
+
+ Items = DtoBaseItemViewModel.GetObservableItems(ItemsResult.Items);
+ }
+ }
+
+ /// <summary>
+ /// The _display children
+ /// </summary>
+ private ObservableCollection<DtoBaseItemViewModel> _items;
+ /// <summary>
+ /// Gets the actual children that should be displayed.
+ /// Subclasses should bind to this, not ItemsResult.
+ /// </summary>
+ /// <value>The display children.</value>
+ public ObservableCollection<DtoBaseItemViewModel> Items
+ {
+ get { return _items; }
+
+ private set
+ {
+ _items = value;
+ //lstItems.ItemsSource = value;
+ OnPropertyChanged("Items");
+ }
+ }
+
+ /// <summary>
+ /// Called when [item changed].
+ /// </summary>
+ protected override async void OnItemChanged()
+ {
+ ItemsResult = await UIKernel.Instance.ApiClient.GetAllPeopleAsync(App.Instance.CurrentUser.Id, itemId: Item.Id);
+ }
+ }
+}
diff --git a/MediaBrowser.Plugins.DefaultTheme/Controls/Details/ItemSpecialFeatures.xaml b/MediaBrowser.Plugins.DefaultTheme/Controls/Details/ItemSpecialFeatures.xaml
new file mode 100644
index 000000000..09d64612e
--- /dev/null
+++ b/MediaBrowser.Plugins.DefaultTheme/Controls/Details/ItemSpecialFeatures.xaml
@@ -0,0 +1,23 @@
+<details:BaseDetailsControl x:Class="MediaBrowser.Plugins.DefaultTheme.Controls.Details.ItemSpecialFeatures"
+ xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
+ xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
+ xmlns:details="clr-namespace:MediaBrowser.Plugins.DefaultTheme.Controls.Details"
+ xmlns:controls="clr-namespace:MediaBrowser.UI.Controls;assembly=MediaBrowser.UI.Controls"
+ mc:Ignorable="d"
+ d:DesignHeight="300" d:DesignWidth="300">
+ <Grid>
+ <controls:ExtendedScrollViewer ScrollViewer.HorizontalScrollBarVisibility="Hidden" ScrollViewer.VerticalScrollBarVisibility="Disabled" CanContentScroll="True">
+ <controls:ScrollingPanel CanHorizontallyScroll="True" CanVerticallyScroll="False">
+ <controls:ExtendedListBox x:Name="lstItems" HorizontalAlignment="Center" VerticalAlignment="Top" ScrollViewer.VerticalScrollBarVisibility="Disabled" ScrollViewer.HorizontalScrollBarVisibility="Disabled" ItemTemplate="{StaticResource ItemSpecialFeaturesTemplate}" Style="{StaticResource ListBoxStyle}" ItemContainerStyle="{StaticResource ListBoxItemStyle}">
+ <controls:ExtendedListBox.ItemsPanel>
+ <ItemsPanelTemplate>
+ <WrapPanel Orientation="Vertical" Margin="50" />
+ </ItemsPanelTemplate>
+ </controls:ExtendedListBox.ItemsPanel>
+ </controls:ExtendedListBox>
+ </controls:ScrollingPanel>
+ </controls:ExtendedScrollViewer>
+ </Grid>
+</details:BaseDetailsControl>
diff --git a/MediaBrowser.Plugins.DefaultTheme/Controls/Details/ItemSpecialFeatures.xaml.cs b/MediaBrowser.Plugins.DefaultTheme/Controls/Details/ItemSpecialFeatures.xaml.cs
new file mode 100644
index 000000000..46b9ac311
--- /dev/null
+++ b/MediaBrowser.Plugins.DefaultTheme/Controls/Details/ItemSpecialFeatures.xaml.cs
@@ -0,0 +1,77 @@
+using MediaBrowser.Model.DTO;
+using MediaBrowser.Model.Net;
+using MediaBrowser.UI;
+using MediaBrowser.UI.Controller;
+using MediaBrowser.UI.Controls;
+using MediaBrowser.UI.Playback;
+using MediaBrowser.UI.ViewModels;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace MediaBrowser.Plugins.DefaultTheme.Controls.Details
+{
+ /// <summary>
+ /// Interaction logic for ItemSpecialFeatures.xaml
+ /// </summary>
+ public partial class ItemSpecialFeatures : BaseDetailsControl
+ {
+ /// <summary>
+ /// Initializes a new instance of the <see cref="ItemSpecialFeatures" /> class.
+ /// </summary>
+ public ItemSpecialFeatures()
+ {
+ InitializeComponent();
+
+ lstItems.ItemInvoked += lstItems_ItemInvoked;
+ }
+
+ /// <summary>
+ /// LSTs the items_ item invoked.
+ /// </summary>
+ /// <param name="sender">The sender.</param>
+ /// <param name="e">The e.</param>
+ void lstItems_ItemInvoked(object sender, ItemEventArgs<object> e)
+ {
+ var viewModel = (SpecialFeatureViewModel) e.Argument;
+
+ UIKernel.Instance.PlaybackManager.Play(new PlayOptions
+ {
+ Items = new List<DtoBaseItem> { viewModel.Item }
+ });
+ }
+
+ /// <summary>
+ /// Called when [item changed].
+ /// </summary>
+ protected override async void OnItemChanged()
+ {
+ DtoBaseItem[] result;
+
+ try
+ {
+ result = await UIKernel.Instance.ApiClient.GetSpecialFeaturesAsync(App.Instance.CurrentUser.Id, Item.Id);
+ }
+ catch (HttpException)
+ {
+ App.Instance.ShowDefaultErrorMessage();
+
+ return;
+ }
+
+ var resultItems = result ?? new DtoBaseItem[] { };
+
+ const int height = 297;
+ var aspectRatio = DtoBaseItemViewModel.GetAveragePrimaryImageAspectRatio(resultItems);
+
+ var width = aspectRatio == 0 ? 528 : height * aspectRatio;
+
+ lstItems.ItemsSource = resultItems.Select(i => new SpecialFeatureViewModel
+ {
+ Item = i,
+ ImageHeight = height,
+ ImageWidth = width
+
+ }).ToList();
+ }
+ }
+}
diff --git a/MediaBrowser.Plugins.DefaultTheme/Controls/Details/ItemTrailers.xaml b/MediaBrowser.Plugins.DefaultTheme/Controls/Details/ItemTrailers.xaml
new file mode 100644
index 000000000..129885271
--- /dev/null
+++ b/MediaBrowser.Plugins.DefaultTheme/Controls/Details/ItemTrailers.xaml
@@ -0,0 +1,23 @@
+<details:BaseDetailsControl x:Class="MediaBrowser.Plugins.DefaultTheme.Controls.Details.ItemTrailers"
+ xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
+ xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
+ xmlns:details="clr-namespace:MediaBrowser.Plugins.DefaultTheme.Controls.Details"
+ xmlns:controls="clr-namespace:MediaBrowser.UI.Controls;assembly=MediaBrowser.UI.Controls"
+ mc:Ignorable="d"
+ d:DesignHeight="300" d:DesignWidth="300">
+ <Grid>
+ <controls:ExtendedScrollViewer ScrollViewer.HorizontalScrollBarVisibility="Hidden" ScrollViewer.VerticalScrollBarVisibility="Disabled" CanContentScroll="True">
+ <controls:ScrollingPanel CanHorizontallyScroll="True" CanVerticallyScroll="False">
+ <controls:ExtendedListBox x:Name="lstItems" HorizontalAlignment="Center" VerticalAlignment="Top" ScrollViewer.VerticalScrollBarVisibility="Disabled" ScrollViewer.HorizontalScrollBarVisibility="Disabled" ItemTemplate="{StaticResource ItemSpecialFeaturesTemplate}" Style="{StaticResource ListBoxStyle}" ItemContainerStyle="{StaticResource ListBoxItemStyle}">
+ <controls:ExtendedListBox.ItemsPanel>
+ <ItemsPanelTemplate>
+ <WrapPanel Orientation="Vertical" Margin="50" />
+ </ItemsPanelTemplate>
+ </controls:ExtendedListBox.ItemsPanel>
+ </controls:ExtendedListBox>
+ </controls:ScrollingPanel>
+ </controls:ExtendedScrollViewer>
+ </Grid>
+</details:BaseDetailsControl>
diff --git a/MediaBrowser.Plugins.DefaultTheme/Controls/Details/ItemTrailers.xaml.cs b/MediaBrowser.Plugins.DefaultTheme/Controls/Details/ItemTrailers.xaml.cs
new file mode 100644
index 000000000..e8134b634
--- /dev/null
+++ b/MediaBrowser.Plugins.DefaultTheme/Controls/Details/ItemTrailers.xaml.cs
@@ -0,0 +1,82 @@
+using MediaBrowser.Model.DTO;
+using MediaBrowser.Model.Net;
+using MediaBrowser.UI;
+using MediaBrowser.UI.Controller;
+using MediaBrowser.UI.Controls;
+using MediaBrowser.UI.Playback;
+using MediaBrowser.UI.ViewModels;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace MediaBrowser.Plugins.DefaultTheme.Controls.Details
+{
+ /// <summary>
+ /// Interaction logic for ItemTrailers.xaml
+ /// </summary>
+ public partial class ItemTrailers : BaseDetailsControl
+ {
+ /// <summary>
+ /// Initializes a new instance of the <see cref="ItemSpecialFeatures" /> class.
+ /// </summary>
+ public ItemTrailers()
+ {
+ InitializeComponent();
+
+ lstItems.ItemInvoked += lstItems_ItemInvoked;
+ }
+
+ /// <summary>
+ /// LSTs the items_ item invoked.
+ /// </summary>
+ /// <param name="sender">The sender.</param>
+ /// <param name="e">The e.</param>
+ void lstItems_ItemInvoked(object sender, ItemEventArgs<object> e)
+ {
+ var viewModel = (SpecialFeatureViewModel)e.Argument;
+
+ UIKernel.Instance.PlaybackManager.Play(new PlayOptions
+ {
+ Items = new List<DtoBaseItem> { viewModel.Item }
+ });
+ }
+
+ /// <summary>
+ /// Called when [item changed].
+ /// </summary>
+ protected override async void OnItemChanged()
+ {
+ DtoBaseItem[] result;
+
+ try
+ {
+ result = await UIKernel.Instance.ApiClient.GetLocalTrailersAsync(App.Instance.CurrentUser.Id, Item.Id);
+ }
+ catch (HttpException)
+ {
+ App.Instance.ShowDefaultErrorMessage();
+
+ return;
+ }
+
+ var resultItems = result ?? new DtoBaseItem[] { };
+
+ const int height = 297;
+ var aspectRatio = DtoBaseItemViewModel.GetAveragePrimaryImageAspectRatio(resultItems);
+
+ var width = aspectRatio == 0 ? 528 : height * aspectRatio;
+
+ if (Item.TrailerUrls != null)
+ {
+ //resultItems.AddRange(Item.TrailerUrls.Select(i => UIKernel.Instance.PlaybackManager.GetPlayableItem(new Uri(i), "Trailer")));
+ }
+
+ lstItems.ItemsSource = resultItems.Select(i => new SpecialFeatureViewModel
+ {
+ Item = i,
+ ImageHeight = height,
+ ImageWidth = width
+
+ }).ToList();
+ }
+ }
+}
diff --git a/MediaBrowser.Plugins.DefaultTheme/Controls/Details/MediaStreamControl.xaml b/MediaBrowser.Plugins.DefaultTheme/Controls/Details/MediaStreamControl.xaml
new file mode 100644
index 000000000..e841693fe
--- /dev/null
+++ b/MediaBrowser.Plugins.DefaultTheme/Controls/Details/MediaStreamControl.xaml
@@ -0,0 +1,18 @@
+<controls:BaseUserControl x:Class="MediaBrowser.Plugins.DefaultTheme.Controls.Details.MediaStreamControl"
+ xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
+ xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
+ xmlns:controls="clr-namespace:MediaBrowser.UI.Controls;assembly=MediaBrowser.UI.Controls"
+ mc:Ignorable="d"
+ d:DesignHeight="300" d:DesignWidth="300">
+ <Grid>
+ <Grid.ColumnDefinitions>
+ <ColumnDefinition Width="150"></ColumnDefinition>
+ <ColumnDefinition Width="*"></ColumnDefinition>
+ </Grid.ColumnDefinitions>
+
+ <TextBlock Style="{StaticResource TextBlockStyle}" Grid.Column="0" x:Name="StreamName"></TextBlock>
+ <StackPanel Orientation="Vertical" Grid.Column="1" x:Name="StreamDetails"></StackPanel>
+ </Grid>
+</controls:BaseUserControl>
diff --git a/MediaBrowser.Plugins.DefaultTheme/Controls/Details/MediaStreamControl.xaml.cs b/MediaBrowser.Plugins.DefaultTheme/Controls/Details/MediaStreamControl.xaml.cs
new file mode 100644
index 000000000..c0271cdab
--- /dev/null
+++ b/MediaBrowser.Plugins.DefaultTheme/Controls/Details/MediaStreamControl.xaml.cs
@@ -0,0 +1,142 @@
+using MediaBrowser.Model.Entities;
+using MediaBrowser.UI.Controls;
+using System.Collections.Generic;
+using System.Globalization;
+using System.IO;
+using System.Windows.Controls;
+
+namespace MediaBrowser.Plugins.DefaultTheme.Controls.Details
+{
+ /// <summary>
+ /// Interaction logic for MediaStreamControl.xaml
+ /// </summary>
+ public partial class MediaStreamControl : BaseUserControl
+ {
+ private static readonly CultureInfo UsCulture = new CultureInfo("en-US");
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="MediaStreamControl" /> class.
+ /// </summary>
+ public MediaStreamControl()
+ {
+ InitializeComponent();
+ }
+
+ /// <summary>
+ /// The _media stream
+ /// </summary>
+ private MediaStream _mediaStream;
+ /// <summary>
+ /// Gets or sets the media stream.
+ /// </summary>
+ /// <value>The media stream.</value>
+ public MediaStream MediaStream
+ {
+ get { return _mediaStream; }
+ set
+ {
+ _mediaStream = value;
+ OnPropertyChanged("MediaStream");
+ OnStreamChanged();
+ }
+ }
+
+ /// <summary>
+ /// Called when [stream changed].
+ /// </summary>
+ private void OnStreamChanged()
+ {
+ if (MediaStream == null)
+ {
+ StreamName.Text = string.Empty;
+ StreamDetails.Children.Clear();
+ return;
+ }
+
+ var details = new List<string> { };
+
+ if (MediaStream.Type != MediaStreamType.Video)
+ {
+ AddDetail(details, MediaStream.Language);
+ }
+
+ if (!string.IsNullOrEmpty(MediaStream.Path))
+ {
+ AddDetail(details, Path.GetFileName(MediaStream.Path));
+ }
+
+ if (MediaStream.Type == MediaStreamType.Video)
+ {
+ var resolution = string.Format("{0}*{1}", MediaStream.Width, MediaStream.Height);
+
+ AddDetail(details, resolution);
+ }
+
+ AddDetail(details, MediaStream.AspectRatio);
+
+ if (MediaStream.Type != MediaStreamType.Video)
+ {
+ if (MediaStream.IsDefault)
+ {
+ //AddDetail(details, "default");
+ }
+ if (MediaStream.IsForced)
+ {
+ AddDetail(details, "forced");
+ }
+ }
+
+ AddDetail(details, MediaStream.Codec);
+
+ if (MediaStream.Channels.HasValue)
+ {
+ AddDetail(details, MediaStream.Channels.Value.ToString(UsCulture) + "ch");
+ }
+
+ if (MediaStream.BitRate.HasValue)
+ {
+ var text = (MediaStream.BitRate.Value / 1000).ToString(UsCulture) + "kbps";
+
+ AddDetail(details, text);
+ }
+
+ var framerate = MediaStream.AverageFrameRate ?? MediaStream.RealFrameRate ?? 0;
+
+ if (framerate > 0)
+ {
+ AddDetail(details, framerate.ToString(UsCulture));
+ }
+
+ if (MediaStream.SampleRate.HasValue)
+ {
+ AddDetail(details, MediaStream.SampleRate.Value.ToString(UsCulture) + "khz");
+ }
+
+ AddDetail(string.Join(" \u2022 ", details.ToArray()));
+
+ StreamName.Text = MediaStream.Type.ToString();
+ }
+
+ private void AddDetail(string text)
+ {
+ if (string.IsNullOrEmpty(text))
+ {
+ return;
+ }
+
+ var control = new TextBlock() { Text = text };
+ control.SetResourceReference(StyleProperty, "TextBlockStyle");
+ StreamDetails.Children.Add(control);
+ }
+
+ private void AddDetail(ICollection<string> list, string text)
+ {
+ if (string.IsNullOrEmpty(text))
+ {
+ return;
+ }
+
+ list.Add(text);
+ }
+ }
+}
diff --git a/MediaBrowser.Plugins.DefaultTheme/Controls/HomePageTile.xaml b/MediaBrowser.Plugins.DefaultTheme/Controls/HomePageTile.xaml
new file mode 100644
index 000000000..8de68eff9
--- /dev/null
+++ b/MediaBrowser.Plugins.DefaultTheme/Controls/HomePageTile.xaml
@@ -0,0 +1,22 @@
+<controls:BaseUserControl x:Class="MediaBrowser.Plugins.DefaultTheme.Controls.HomePageTile"
+ xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
+ xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
+ xmlns:controls="clr-namespace:MediaBrowser.UI.Controls;assembly=MediaBrowser.UI.Controls"
+ mc:Ignorable="d"
+ d:DesignHeight="300" d:DesignWidth="300">
+ <Grid HorizontalAlignment="Left" Width="400" Height="225">
+
+ <Border Background="{Binding Converter={StaticResource MetroTileBackgroundConverter}}">
+ <Image x:Name="image" Stretch="Uniform"></Image>
+ </Border>
+
+ <Grid HorizontalAlignment="Stretch" VerticalAlignment="Bottom">
+ <Grid.Background>
+ <SolidColorBrush Color="#A6000000"></SolidColorBrush>
+ </Grid.Background>
+ <TextBlock Margin="10 5 0 10" Foreground="White" Text="{Binding Path=Item.Name}" TextWrapping="Wrap"></TextBlock>
+ </Grid>
+ </Grid>
+</controls:BaseUserControl>
diff --git a/MediaBrowser.Plugins.DefaultTheme/Controls/HomePageTile.xaml.cs b/MediaBrowser.Plugins.DefaultTheme/Controls/HomePageTile.xaml.cs
new file mode 100644
index 000000000..a8e238681
--- /dev/null
+++ b/MediaBrowser.Plugins.DefaultTheme/Controls/HomePageTile.xaml.cs
@@ -0,0 +1,128 @@
+using MediaBrowser.Model.DTO;
+using MediaBrowser.Model.Entities;
+using MediaBrowser.Model.Net;
+using MediaBrowser.UI;
+using MediaBrowser.UI.Controls;
+using MediaBrowser.UI.ViewModels;
+using System;
+using System.Windows;
+
+namespace MediaBrowser.Plugins.DefaultTheme.Controls
+{
+ /// <summary>
+ /// Interaction logic for BaseItemTile.xaml
+ /// </summary>
+ public partial class HomePageTile : BaseUserControl
+ {
+ /// <summary>
+ /// Gets the view model.
+ /// </summary>
+ /// <value>The view model.</value>
+ public DtoBaseItemViewModel ViewModel
+ {
+ get { return DataContext as DtoBaseItemViewModel; }
+ }
+
+ /// <summary>
+ /// Gets the item.
+ /// </summary>
+ /// <value>The item.</value>
+ private DtoBaseItem Item
+ {
+ get { return ViewModel.Item; }
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="HomePageTile" /> class.
+ /// </summary>
+ public HomePageTile()
+ {
+ InitializeComponent();
+
+ DataContextChanged += BaseItemTile_DataContextChanged;
+ }
+
+ /// <summary>
+ /// Handles the DataContextChanged event of the BaseItemTile control.
+ /// </summary>
+ /// <param name="sender">The source of the event.</param>
+ /// <param name="e">The <see cref="DependencyPropertyChangedEventArgs" /> instance containing the event data.</param>
+ void BaseItemTile_DataContextChanged(object sender, DependencyPropertyChangedEventArgs e)
+ {
+ OnItemChanged();
+ }
+
+ /// <summary>
+ /// Called when [item changed].
+ /// </summary>
+ private void OnItemChanged()
+ {
+ ReloadImage();
+ }
+
+ /// <summary>
+ /// Reloads the image.
+ /// </summary>
+ private void ReloadImage()
+ {
+ if (Item.HasPrimaryImage)
+ {
+ var url = App.Instance.ApiClient.GetImageUrl(Item, new ImageOptions
+ {
+ ImageType = ImageType.Primary,
+ Height = 225
+ });
+
+ SetImage(url);
+ }
+ else if (Item.BackdropCount > 0)
+ {
+ var url = App.Instance.ApiClient.GetImageUrl(Item, new ImageOptions
+ {
+ ImageType = ImageType.Backdrop,
+ Height = 225,
+ Width = 400
+ });
+
+ SetImage(url);
+ }
+ else if (Item.HasThumb)
+ {
+ var url = App.Instance.ApiClient.GetImageUrl(Item, new ImageOptions
+ {
+ ImageType = ImageType.Thumb,
+ Height = 225,
+ Width = 400
+ });
+
+ SetImage(url);
+ }
+ else
+ {
+ SetDefaultImage();
+ }
+ }
+
+ /// <summary>
+ /// Sets the image.
+ /// </summary>
+ /// <param name="url">The URL.</param>
+ private async void SetImage(string url)
+ {
+ try
+ {
+ image.Source = await App.Instance.GetRemoteBitmapAsync(url);
+ }
+ catch (HttpException)
+ {
+ SetDefaultImage();
+ }
+ }
+
+ private void SetDefaultImage()
+ {
+ var imageUri = new Uri("../Resources/Images/VideoDefault.png", UriKind.Relative);
+ image.Source = App.Instance.GetBitmapImage(imageUri);
+ }
+ }
+}
diff --git a/MediaBrowser.Plugins.DefaultTheme/Controls/MultiItemTile.xaml b/MediaBrowser.Plugins.DefaultTheme/Controls/MultiItemTile.xaml
new file mode 100644
index 000000000..000fc9584
--- /dev/null
+++ b/MediaBrowser.Plugins.DefaultTheme/Controls/MultiItemTile.xaml
@@ -0,0 +1,30 @@
+<controls:BaseUserControl x:Class="MediaBrowser.Plugins.DefaultTheme.Controls.MultiItemTile"
+ xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
+ xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
+ xmlns:controls="clr-namespace:MediaBrowser.UI.Controls;assembly=MediaBrowser.UI.Controls"
+ mc:Ignorable="d"
+ d:DesignHeight="300" d:DesignWidth="300">
+ <Grid x:Name="mainGrid" HorizontalAlignment="Left">
+
+ <Border Background="{Binding Converter={StaticResource MetroTileBackgroundConverter}}">
+ <controls:TransitionControl x:Name="transitionControl">
+ <controls:TransitionControl.TransitionAnimation>
+ <DoubleAnimation Duration="0:0:1" >
+ <DoubleAnimation.EasingFunction>
+ <ExponentialEase EasingMode="EaseInOut"></ExponentialEase>
+ </DoubleAnimation.EasingFunction>
+ </DoubleAnimation>
+ </controls:TransitionControl.TransitionAnimation>
+ </controls:TransitionControl>
+ </Border>
+
+ <Grid HorizontalAlignment="Stretch" VerticalAlignment="Bottom">
+ <Grid.Background>
+ <SolidColorBrush Color="#A6000000"></SolidColorBrush>
+ </Grid.Background>
+ <TextBlock x:Name="txtName" Margin="10 5 0 10" Foreground="White" TextWrapping="Wrap"></TextBlock>
+ </Grid>
+ </Grid>
+</controls:BaseUserControl>
diff --git a/MediaBrowser.Plugins.DefaultTheme/Controls/MultiItemTile.xaml.cs b/MediaBrowser.Plugins.DefaultTheme/Controls/MultiItemTile.xaml.cs
new file mode 100644
index 000000000..66a30bfff
--- /dev/null
+++ b/MediaBrowser.Plugins.DefaultTheme/Controls/MultiItemTile.xaml.cs
@@ -0,0 +1,219 @@
+using MediaBrowser.Model.DTO;
+using MediaBrowser.Model.Entities;
+using MediaBrowser.Model.Net;
+using MediaBrowser.UI;
+using MediaBrowser.UI.Controls;
+using MediaBrowser.UI.ViewModels;
+using Microsoft.Expression.Media.Effects;
+using System;
+using System.ComponentModel;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Media;
+
+namespace MediaBrowser.Plugins.DefaultTheme.Controls
+{
+ /// <summary>
+ /// Interaction logic for MultiItemTile.xaml
+ /// </summary>
+ public partial class MultiItemTile : BaseUserControl
+ {
+ /// <summary>
+ /// The _image width
+ /// </summary>
+ private int _imageWidth;
+ /// <summary>
+ /// Gets or sets the width of the image.
+ /// </summary>
+ /// <value>The width of the image.</value>
+ public int ImageWidth
+ {
+ get { return _imageWidth; }
+ set
+ {
+ _imageWidth = value;
+ mainGrid.Width = value;
+ }
+ }
+
+ /// <summary>
+ /// The _image height
+ /// </summary>
+ private int _imageHeight;
+ /// <summary>
+ /// Gets or sets the height of the image.
+ /// </summary>
+ /// <value>The height of the image.</value>
+ public int ImageHeight
+ {
+ get { return _imageHeight; }
+ set
+ {
+ _imageHeight = value;
+ mainGrid.Height = value;
+ }
+ }
+
+ /// <summary>
+ /// The _effects
+ /// </summary>
+ TransitionEffect[] _effects = new TransitionEffect[]
+ {
+ new BlindsTransitionEffect { Orientation = BlindOrientation.Horizontal },
+ new BlindsTransitionEffect { Orientation = BlindOrientation.Vertical },
+ new CircleRevealTransitionEffect { },
+ new FadeTransitionEffect { },
+ new SlideInTransitionEffect { SlideDirection= SlideDirection.TopToBottom},
+ new SlideInTransitionEffect { SlideDirection= SlideDirection.RightToLeft},
+ new WipeTransitionEffect { WipeDirection = WipeDirection.RightToLeft},
+ new WipeTransitionEffect { WipeDirection = WipeDirection.TopLeftToBottomRight}
+ };
+
+ /// <summary>
+ /// Gets or sets the random.
+ /// </summary>
+ /// <value>The random.</value>
+ private Random Random { get; set; }
+
+ /// <summary>
+ /// Gets the collection.
+ /// </summary>
+ /// <value>The collection.</value>
+ public ItemCollectionViewModel Collection
+ {
+ get { return DataContext as ItemCollectionViewModel; }
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="MultiItemTile" /> class.
+ /// </summary>
+ public MultiItemTile()
+ {
+ InitializeComponent();
+
+ Random = new Random(Guid.NewGuid().GetHashCode());
+
+ mainGrid.Width = ImageWidth;
+ mainGrid.Height = ImageHeight;
+ DataContextChanged += BaseItemTile_DataContextChanged;
+ }
+
+ /// <summary>
+ /// Handles the DataContextChanged event of the BaseItemTile control.
+ /// </summary>
+ /// <param name="sender">The source of the event.</param>
+ /// <param name="e">The <see cref="DependencyPropertyChangedEventArgs" /> instance containing the event data.</param>
+ void BaseItemTile_DataContextChanged(object sender, DependencyPropertyChangedEventArgs e)
+ {
+ OnCurrentItemChanged();
+
+ if (Collection != null)
+ {
+ Collection.PropertyChanged += Collection_PropertyChanged;
+ }
+ }
+
+ /// <summary>
+ /// Handles the PropertyChanged event of the Collection control.
+ /// </summary>
+ /// <param name="sender">The source of the event.</param>
+ /// <param name="e">The <see cref="PropertyChangedEventArgs" /> instance containing the event data.</param>
+ void Collection_PropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ if (e.PropertyName.Equals("CurrentItem"))
+ {
+ OnCurrentItemChanged();
+ }
+ }
+
+ /// <summary>
+ /// Called when [current item changed].
+ /// </summary>
+ private async void OnCurrentItemChanged()
+ {
+ if (Collection == null)
+ {
+ // Setting this to null doesn't seem to clear out the content
+ transitionControl.Content = new FrameworkElement();
+ txtName.Text = null;
+ return;
+ }
+
+ var currentItem = Collection.CurrentItem;
+
+ if (currentItem == null)
+ {
+ // Setting this to null doesn't seem to clear out the content
+ transitionControl.Content = new FrameworkElement();
+ txtName.Text = Collection.Name;
+ return;
+ }
+
+ var img = new Image
+ {
+ Stretch = Stretch.Uniform,
+ Width = ImageWidth,
+ Height = ImageHeight
+ };
+
+ var url = GetImageSource(currentItem);
+
+ if (!string.IsNullOrEmpty(url))
+ {
+ try
+ {
+ img.Source = await App.Instance.GetRemoteBitmapAsync(url);
+ txtName.Text = Collection.Name ?? currentItem.Name;
+ }
+ catch (HttpException)
+ {
+ }
+ }
+
+ transitionControl.TransitionType = _effects[Random.Next(0, _effects.Length)];
+ transitionControl.Content = img;
+ }
+
+ /// <summary>
+ /// Gets the image source.
+ /// </summary>
+ /// <param name="item">The item.</param>
+ /// <returns>Uri.</returns>
+ private string GetImageSource(DtoBaseItem item)
+ {
+ if (item != null)
+ {
+ if (item.BackdropCount > 0)
+ {
+ return App.Instance.ApiClient.GetImageUrl(item, new ImageOptions
+ {
+ ImageType = ImageType.Backdrop,
+ Height = ImageHeight,
+ Width = ImageWidth
+ });
+ }
+
+ if (item.HasThumb)
+ {
+ return App.Instance.ApiClient.GetImageUrl(item, new ImageOptions
+ {
+ ImageType = ImageType.Thumb,
+ Height = ImageHeight,
+ Width = ImageWidth
+ });
+ }
+
+ if (item.HasPrimaryImage)
+ {
+ return App.Instance.ApiClient.GetImageUrl(item, new ImageOptions
+ {
+ ImageType = ImageType.Primary,
+ Height = ImageHeight
+ });
+ }
+ }
+
+ return null;
+ }
+ }
+}