Commit 585de890 authored by Martin Finkel's avatar Martin Finkel

StreamsViewModel refactoring

Created base classes for UWP page and ViewModel
XAML binding now references ViewModel
Disabled NavigationCacheMode to lower memory footprint
Refactored MetaServices
parent 4cfec1a7
using VLC.Model.Library;
namespace VLC.Services.RunTime
{
public abstract class MetaService
{
protected readonly MediaLibrary MediaLibrary;
protected readonly NetworkListenerService NetworkListenerService;
protected MetaService(MediaLibrary mediaLibrary, NetworkListenerService networkListenerService)
{
MediaLibrary = mediaLibrary;
NetworkListenerService = networkListenerService;
}
}
}
\ No newline at end of file
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Threading.Tasks;
using Windows.Storage;
using Windows.Storage.Streams;
using System.Threading.Tasks;
using Windows.UI.Core;
using VLC.Model.Music;
using VLC.MusicMetaFetcher;
using VLC.MusicMetaFetcher.Models.MusicEntities;
using VLC.Utils;
using VLC.ViewModels;
using VLC.Helpers;
using VLC.MediaMetaFetcher;
using VLC.Model.Library;
namespace VLC.Services.RunTime
{
public sealed class MusicMetaService
public sealed class MusicMetaService : MetaService
{
readonly MusicMDFetcher musicMdFetcher = new MusicMDFetcher(App.DeezerAppID, App.ApiKeyLastFm);
private readonly MusicMDFetcher _musicMdFetcher = new MusicMDFetcher(App.DeezerAppID, App.ApiKeyLastFm);
public MusicMetaService(MediaLibrary mediaLibrary, NetworkListenerService networkListenerService)
: base(mediaLibrary, networkListenerService)
{
}
public async Task GetSimilarArtists(ArtistItem artist)
{
var artists = await musicMdFetcher.GetArtistSimilarsArtist(artist.Name);
var artists = await _musicMdFetcher.GetArtistSimilarsArtist(artist.Name);
if (artists == null) return;
await DispatchHelper.InvokeInUIThread(CoreDispatcherPriority.Normal, () =>
{
......@@ -32,7 +31,7 @@ namespace VLC.Services.RunTime
public async Task GetPopularAlbums(ArtistItem artist)
{
var albums = await musicMdFetcher.GetArtistTopAlbums(artist.Name);
var albums = await _musicMdFetcher.GetArtistTopAlbums(artist.Name);
if (albums == null) return;
await DispatchHelper.InvokeInUIThread(CoreDispatcherPriority.Normal, () =>
{
......@@ -43,20 +42,20 @@ namespace VLC.Services.RunTime
public async Task GetArtistBiography(ArtistItem artist)
{
var bio = await musicMdFetcher.GetArtistBiography(artist.Name);
var bio = await _musicMdFetcher.GetArtistBiography(artist.Name);
if (bio == null) return;
await DispatchHelper.InvokeInUIThread(CoreDispatcherPriority.Normal, () =>
{
artist.Biography = bio;
});
Locator.MediaLibrary.Update(artist);
MediaLibrary.Update(artist);
}
public async Task<bool> GetAlbumCover(AlbumItem album)
{
if (NetworkListenerService.IsConnected && !string.IsNullOrEmpty(album.Name))
{
var bytes = await musicMdFetcher.GetAlbumPictureFromInternet(album.Name, album.Artist);
var bytes = await _musicMdFetcher.GetAlbumPictureFromInternet(album.Name, album.Artist);
if (bytes == null)
{
// TODO: Add a TriedWithNoSuccess flag in DB
......@@ -64,7 +63,7 @@ namespace VLC.Services.RunTime
var success = bytes != null && await SaveAlbumImageAsync(album, bytes);
if (success)
{
Locator.MediaLibrary.Update(album);
MediaLibrary.Update(album);
return true;
}
}
......@@ -75,17 +74,15 @@ namespace VLC.Services.RunTime
{
if (NetworkListenerService.IsConnected && !string.IsNullOrEmpty(artist.Name))
{
var bytes = await musicMdFetcher.GetArtistPicture(artist.Name);
var bytes = await _musicMdFetcher.GetArtistPicture(artist.Name);
if (bytes == null)
{
// TODO: Add a TriedWithNoSuccess flag in DB
}
var success = bytes != null && await SaveArtistImageAsync(artist, bytes);
if (success)
{
Locator.MediaLibrary.Update(artist);
return true;
}
if (!success) return false;
MediaLibrary.Update(artist);
return true;
}
return false;
}
......
......@@ -4,7 +4,7 @@ using VLC.Model.Events;
namespace VLC.Services.RunTime
{
class NetworkListenerService
public class NetworkListenerService
{
public event EventHandler<InternetConnectionChangedEventArgs> InternetConnectionChanged;
......@@ -26,14 +26,8 @@ namespace VLC.Services.RunTime
var arg = new InternetConnectionChangedEventArgs(IsConnected);
InternetConnectionChanged(null, arg);
}
public static bool IsConnected
{
get
{
var profile = NetworkInformation.GetInternetConnectionProfile();
return (profile != null && profile.GetNetworkConnectivityLevel() == NetworkConnectivityLevel.InternetAccess);
}
}
public bool IsConnected => NetworkInformation.GetInternetConnectionProfile()?.GetNetworkConnectivityLevel() ==
NetworkConnectivityLevel.InternetAccess;
}
}
using System;
using System.Collections.Generic;
using System.IO.Compression;
using System.Text;
using System.Xml.Linq;
using System.Threading.Tasks;
using System.Threading.Tasks;
using VLC.MediaMetaFetcher;
using VLC.Model.Video;
using VLC.Utils;
using VLC.ViewModels;
using Windows.Storage;
using System.Linq;
using VLC.Model.Library;
namespace VLC.Services.RunTime
{
public sealed class VideoMetaService
public sealed class VideoMetaService : MetaService
{
readonly VideoMDFetcher videoMdFetcher = new VideoMDFetcher(App.ApiKeyMovieDb);
private readonly VideoMDFetcher _videoMdFetcher = new VideoMDFetcher(App.ApiKeyMovieDb);
public VideoMetaService(MediaLibrary mediaLibrary, NetworkListenerService networkListenerService)
: base(mediaLibrary, networkListenerService)
{
}
public async Task<bool> GetMovieSubtitle(VideoItem video)
{
if (NetworkListenerService.IsConnected && !string.IsNullOrEmpty(video.Path))
{
var bytes = await videoMdFetcher.GetMovieSubtitle(video);
var bytes = await _videoMdFetcher.GetMovieSubtitle(video);
if (bytes != null)
{
......@@ -30,7 +29,7 @@ namespace VLC.Services.RunTime
{
if (video.Id > -1)
{
Locator.MediaLibrary.UpdateVideo(video);
MediaLibrary.UpdateVideo(video);
}
return true;
}
......@@ -56,20 +55,19 @@ namespace VLC.Services.RunTime
}
return false;
}
public async Task<bool> GetMoviePicture(VideoItem video)
{
if (NetworkListenerService.IsConnected && !string.IsNullOrEmpty(video.Name))
{
var bytes = await videoMdFetcher.GetMovieCover(video.Name);
var bytes = await _videoMdFetcher.GetMovieCover(video.Name);
if (bytes != null)
{
var success = await SaveMoviePictureAsync(video, bytes);
if (success)
{
Locator.MediaLibrary.UpdateVideo(video);
MediaLibrary.UpdateVideo(video);
return true;
}
}
......
......@@ -198,6 +198,7 @@
<Compile Include="$(MSBuildThisFileDirectory)Services\RunTime\HttpServer.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Services\RunTime\HttpResponseSender.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Services\RunTime\KeyboardListenerService.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Services\RunTime\MetaService.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Services\RunTime\NavigationService.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Services\RunTime\PlaybackService.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Services\RunTime\PlaylistService.cs" />
......@@ -235,6 +236,7 @@
<Compile Include="$(MSBuildThisFileDirectory)ViewModels\Settings\SettingsViewModel.cs" />
<Compile Include="$(MSBuildThisFileDirectory)ViewModels\VideoVM\VideoLibraryVM.cs" />
<Compile Include="$(MSBuildThisFileDirectory)ViewModels\VideoVM\VideoPlayerVM.cs" />
<Compile Include="$(MSBuildThisFileDirectory)ViewModels\ViewModelBase.cs" />
</ItemGroup>
<ItemGroup>
<Content Include="$(MSBuildThisFileDirectory)Assets\NewStoreLogo.scale-100.png" />
......
......@@ -42,7 +42,6 @@ namespace VLC.ViewModels
private static VideoLibraryVM _videoLibraryVM;
private static VideoPlayerVM _videoPlayer;
private static VLCExplorerViewModel _vlcExplorer;
private static StreamsViewModel _streams;
private static SettingsViewModel _settings;
private static SearchViewModel _search;
private static SpecialThanksViewModel _specialThanks;
......@@ -87,7 +86,6 @@ namespace VLC.ViewModels
public static SettingsViewModel SettingsVM => _settings ?? (_settings = App.Container.Resolve<SettingsViewModel>());
public static SearchViewModel SearchVM => _search ?? (_search = App.Container.Resolve<SearchViewModel>());
public static StreamsViewModel StreamsVM => _streams ?? (_streams = App.Container.Resolve<StreamsViewModel>());
public static SpecialThanksViewModel SpecialThanksVM => _specialThanks ?? (_specialThanks = App.Container.Resolve<SpecialThanksViewModel>());
public static NavigationService NavigationService => _navigationService ?? (_navigationService = App.Container.Resolve<NavigationService>());
......
using System;
using System.Collections.Generic;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Windows.UI.Xaml;
using Windows.UI.Core;
using VLC.Database;
using VLC.Model.Stream;
using VLC.Utils;
using VLC.Commands;
using Windows.UI.Xaml;
using Autofac;
using VLC.Services.RunTime;
using VLC.Commands.StreamsLibrary;
using VLC.Model.Library;
namespace VLC.ViewModels.Others
{
public class StreamsViewModel : BindableBase, IDisposable
public class StreamsViewModel : ViewModelBase
{
public IEnumerable<StreamMedia> StreamsHistoryAndFavoritesGrouped
{
get { return Locator.MediaLibrary.Streams?.OrderBy(x => x.Order); }
}
private MediaLibrary _mediaLibrary;
private NetworkListenerService _networkListenerService;
public bool IsCollectionEmpty
public StreamsViewModel(MediaLibrary mediaLibrary, NetworkListenerService networkListenerService)
{
get { return !Locator.MediaLibrary.Streams.Any(); }
_mediaLibrary = mediaLibrary;
_networkListenerService = networkListenerService;
}
public PlayNetworkMRLCommand PlayStreamCommand { get; private set; } = new PlayNetworkMRLCommand();
public IEnumerable<StreamMedia> StreamsHistoryAndFavoritesGrouped => _mediaLibrary.Streams?.OrderBy(x => x.Order);
public bool IsCollectionEmpty => !_mediaLibrary.Streams.Any();
public Visibility NoInternetPlaceholderEnabled => _networkListenerService.IsConnected ? Visibility.Collapsed : Visibility.Visible;
public Visibility NoInternetPlaceholderEnabled => NetworkListenerService.IsConnected ? Visibility.Collapsed : Visibility.Visible;
public PlayNetworkMRLCommand PlayStreamCommand { get; } = new PlayNetworkMRLCommand();
public void OnNavigatedTo()
public override void Initialize()
{
Task.Run(() => Initialize());
}
_networkListenerService.InternetConnectionChanged += StreamsViewModel_InternetConnectionChanged;
_mediaLibrary.Streams.CollectionChanged += Streams_CollectionChanged;
public void OnNavigatedFrom()
{
Dispose();
Task.Run(async () => await _mediaLibrary.LoadStreamsFromDatabase());
}
async Task Initialize()
public override void Stop()
{
App.Container.Resolve<NetworkListenerService>().InternetConnectionChanged += StreamsViewModel_InternetConnectionChanged;
Locator.MediaLibrary.Streams.CollectionChanged += Streams_CollectionChanged;
await Locator.MediaLibrary.LoadStreamsFromDatabase();
}
_mediaLibrary.Streams.CollectionChanged -= Streams_CollectionChanged;
_networkListenerService.InternetConnectionChanged -= StreamsViewModel_InternetConnectionChanged;
_mediaLibrary = null;
_networkListenerService = null;
PlayStreamCommand = null;
}
private async void StreamsViewModel_InternetConnectionChanged(object sender, Model.Events.InternetConnectionChangedEventArgs e)
{
await DispatchHelper.InvokeInUIThread(CoreDispatcherPriority.Normal, () => OnPropertyChanged(nameof(NoInternetPlaceholderEnabled)));
......@@ -57,11 +57,5 @@ namespace VLC.ViewModels.Others
OnPropertyChanged(nameof(StreamsHistoryAndFavoritesGrouped));
OnPropertyChanged(nameof(IsCollectionEmpty));
}
public void Dispose()
{
Locator.MediaLibrary.Streams.CollectionChanged -= Streams_CollectionChanged;
App.Container.Resolve<NetworkListenerService>().InternetConnectionChanged -= StreamsViewModel_InternetConnectionChanged;
}
}
}
}
\ No newline at end of file
using VLC.Utils;
namespace VLC.ViewModels
{
public abstract class ViewModelBase : BindableBase
{
public virtual void Initialize() { }
public virtual void Stop() { }
}
}
\ No newline at end of file
......@@ -144,6 +144,7 @@
<Compile Include="Views\MainPages\MusicPanes\SongCollectionBase.xaml.cs">
<DependentUpon>SongCollectionBase.xaml</DependentUpon>
</Compile>
<Compile Include="Views\MainPages\VlcPage.cs" />
<Compile Include="Views\MusicPages\AlbumPageControls\AlbumPageBase.xaml.cs">
<DependentUpon>AlbumPageBase.xaml</DependentUpon>
</Compile>
......
<Page x:Class="VLC.UI.Views.MainPages.MainPageNetwork"
<local:StreamsPage x:Class="VLC.UI.Views.MainPages.MainPageNetwork"
NavigationCacheMode="Disabled"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:VLC.UI.Views.MainPages"
......@@ -8,11 +9,11 @@
xmlns:placeholder="using:VLC.UI.Views.UserControls.Placeholder"
xmlns:triggers="using:WinRT.Triggers"
mc:Ignorable="d"
DataContext="{Binding Source={StaticResource Locator}, Path=StreamsVM}">
DataContext="{x:Bind ViewModel}">
<Page.Resources>
<CollectionViewSource x:Key="StreamsHistoryAndFavoritesGroupedResource"
Source="{Binding StreamsHistoryAndFavoritesGrouped}"
Source="{x:Bind ViewModel.StreamsHistoryAndFavoritesGrouped}"
IsSourceGrouped="False" />
</Page.Resources>
......@@ -52,7 +53,7 @@
Style="{StaticResource TextBlockButtonStyle}"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
Command="{Binding Source={StaticResource Locator}, Path=StreamsVM.PlayStreamCommand}"
Command="{x:Bind ViewModel.PlayStreamCommand}"
CommandParameter="{Binding ElementName=MrlTextBox, Path=Text}">
<Button.Content>
<FontIcon Glyph="{StaticResource CheckSymbol}"
......@@ -61,7 +62,7 @@
</Button>
</Grid>
<placeholder:NothingToSeeHere Grid.Row="1"
Visibility="{Binding IsCollectionEmpty, Converter={StaticResource BooleanToVisibilityConverter}}" />
Visibility="{x:Bind ViewModel.IsCollectionEmpty, Converter={StaticResource BooleanToVisibilityConverter}}" />
<ListView Grid.Row="1"
ItemsSource="{Binding Source={StaticResource StreamsHistoryAndFavoritesGroupedResource}}"
IsItemClickEnabled="True"
......@@ -69,7 +70,7 @@
ItemContainerStyle="{StaticResource ListViewItemStyle}">
<triggers:Interactions.Triggers>
<triggers:EventTrigger EventName="ItemClick">
<triggers:InvokeCommandAction Command="{Binding Source={StaticResource Locator}, Path=StreamsVM.PlayStreamCommand}"
<triggers:InvokeCommandAction Command="{x:Bind ViewModel.PlayStreamCommand}"
PassEventArgsToCommand="True" />
</triggers:EventTrigger>
</triggers:Interactions.Triggers>
......@@ -121,7 +122,7 @@
</ListView>
<Grid Grid.Row="1"
Background="{ThemeResource ApplicationChromeThemeBrush}"
Visibility="{Binding NoInternetPlaceholderEnabled}">
Visibility="{x:Bind ViewModel.NoInternetPlaceholderEnabled}">
<TextBlock Text="{Binding Source={StaticResource Strings}, Path=NoInternetConnection}"
Style="{StaticResource SubheaderTextBlockStyle}"
VerticalAlignment="Center"
......@@ -139,4 +140,4 @@
Width="100" />
</Grid>
</Grid>
</Page>
\ No newline at end of file
</local:StreamsPage>
\ No newline at end of file
using Windows.System;
using Windows.UI.Core;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Navigation;
using VLC.Services.RunTime;
using VLC.ViewModels;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;
using VLC.ViewModels.Others;
namespace VLC.UI.Views.MainPages
{
public sealed partial class MainPageNetwork : Page
public sealed partial class MainPageNetwork : StreamsPage
{
public MainPageNetwork()
{
......@@ -20,21 +18,19 @@ namespace VLC.UI.Views.MainPages
{
base.OnNavigatedTo(e);
CoreWindow.GetForCurrentThread().KeyDown += KeyboardListenerService_KeyDown;
Locator.StreamsVM.OnNavigatedTo();
}
protected override void OnNavigatedFrom(NavigationEventArgs e)
{
base.OnNavigatedFrom(e);
CoreWindow.GetForCurrentThread().KeyDown -= KeyboardListenerService_KeyDown;
Locator.StreamsVM.OnNavigatedFrom();
}
private void KeyboardListenerService_KeyDown(CoreWindow sender, KeyEventArgs args)
{
if (args.VirtualKey == VirtualKey.Enter)
{
Locator.StreamsVM.PlayStreamCommand.Execute(MrlTextBox.Text);
ViewModel.PlayStreamCommand.Execute(MrlTextBox.Text);
}
}
......@@ -43,4 +39,11 @@ namespace VLC.UI.Views.MainPages
MrlTextBox.Foreground = App.Current.Resources["MainColor"] as SolidColorBrush;
}
}
/// <summary>
/// Mandatory intermediate class as partial page classes inheriting generic abstract classes do not play well with XAML
/// </summary>
public class StreamsPage : VlcPage<StreamsViewModel>
{
}
}
\ No newline at end of file
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Navigation;
using Autofac;
using VLC.ViewModels;
namespace VLC.UI.Views.MainPages
{
public abstract class VlcPage<TViewModelBase> : Page where TViewModelBase : ViewModelBase
{
private TViewModelBase _viewModel;
protected virtual TViewModelBase ViewModel => _viewModel ?? (_viewModel = App.Container.Resolve<TViewModelBase>());
protected override void OnNavigatedTo(NavigationEventArgs e)
{
base.OnNavigatedTo(e);
ViewModel.Initialize();
}
protected override void OnNavigatedFrom(NavigationEventArgs e)
{
base.OnNavigatedFrom(e);
ViewModel.Stop();
_viewModel = null;
}
}
}
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment