From b472fa678376af56b29d28ed41ae2e4781b0c95f Mon Sep 17 00:00:00 2001 From: Efrain Bastidas Date: Thu, 5 Nov 2020 22:19:44 -0500 Subject: [PATCH] [CastIt] Added a splash page --- CastIt/Application.cs | 2 +- CastIt/MainWindow.xaml | 3 - CastIt/MainWindow.xaml.cs | 2 + CastIt/Resources/Resource.Designer.cs | 9 +++ CastIt/Resources/Resource.es.resx | 3 + CastIt/Resources/Resource.resx | 3 + CastIt/Setup.cs | 1 + CastIt/ViewModels/BaseViewModel.cs | 67 ++++++++++++++++ CastIt/ViewModels/MainViewModel.cs | 42 ++-------- CastIt/ViewModels/SplashViewModel.cs | 109 ++++++++++++++++++++++++++ CastIt/Views/MainPage.xaml.cs | 24 ------ CastIt/Views/Splash.xaml | 29 +++++++ CastIt/Views/Splash.xaml.cs | 65 +++++++++++++++ 13 files changed, 296 insertions(+), 63 deletions(-) create mode 100644 CastIt/ViewModels/SplashViewModel.cs create mode 100644 CastIt/Views/Splash.xaml create mode 100644 CastIt/Views/Splash.xaml.cs diff --git a/CastIt/Application.cs b/CastIt/Application.cs index 18794f7c..8582e906 100644 --- a/CastIt/Application.cs +++ b/CastIt/Application.cs @@ -52,7 +52,7 @@ public override void Initialize() Mvx.IoCProvider.RegisterType(); Mvx.IoCProvider.ConstructAndRegisterSingleton(typeof(SettingsViewModel)); - RegisterAppStart(); + RegisterAppStart(); } private IMapper CreateMapper() diff --git a/CastIt/MainWindow.xaml b/CastIt/MainWindow.xaml index 2d1d65eb..437458e7 100644 --- a/CastIt/MainWindow.xaml +++ b/CastIt/MainWindow.xaml @@ -9,13 +9,10 @@ xmlns:views="clr-namespace:MvvmCross.Platforms.Wpf.Views;assembly=MvvmCross.Platforms.Wpf" x:Name="AppMainWindow" Title="{x:Static common:AppConstants.AppName}" - MinWidth="{x:Static common:AppConstants.MinWindowWidth}" - MinHeight="{x:Static common:AppConstants.MinWindowHeight}" AllowsTransparency="True" Icon="/Resources/favicon.ico" Loaded="AppMainWindow_Loaded" MouseDown="Window_MouseDown" - ResizeMode="CanResize" SizeChanged="AppMainWindow_SizeChanged" Style="{StaticResource WindowStyle}" WindowStartupLocation="CenterScreen" diff --git a/CastIt/MainWindow.xaml.cs b/CastIt/MainWindow.xaml.cs index 622154ea..a0787c64 100644 --- a/CastIt/MainWindow.xaml.cs +++ b/CastIt/MainWindow.xaml.cs @@ -74,6 +74,8 @@ private void AppMainWindow_Loaded(object sender, RoutedEventArgs e) private void AppMainWindow_SizeChanged(object sender, SizeChangedEventArgs e) { var view = Content as MainPage; + if (view == null) + return; if (e.NewSize.Height <= AppConstants.MinWindowHeight && view.ViewModel.IsExpanded) diff --git a/CastIt/Resources/Resource.Designer.cs b/CastIt/Resources/Resource.Designer.cs index 82c8605a..62bea646 100644 --- a/CastIt/Resources/Resource.Designer.cs +++ b/CastIt/Resources/Resource.Designer.cs @@ -699,6 +699,15 @@ public static string LoadFirstSubtitleFoundAutomatically { } } + /// + /// Looks up a localized string similar to Loading. + /// + public static string Loading { + get { + return ResourceManager.GetString("Loading", resourceCulture); + } + } + /// /// Looks up a localized string similar to Loop this file. /// diff --git a/CastIt/Resources/Resource.es.resx b/CastIt/Resources/Resource.es.resx index f4101a6c..faca4d89 100644 --- a/CastIt/Resources/Resource.es.resx +++ b/CastIt/Resources/Resource.es.resx @@ -531,4 +531,7 @@ El archivo no puedo ser abierto + + Cargando + \ No newline at end of file diff --git a/CastIt/Resources/Resource.resx b/CastIt/Resources/Resource.resx index f99c8c6a..810929e9 100644 --- a/CastIt/Resources/Resource.resx +++ b/CastIt/Resources/Resource.resx @@ -531,4 +531,7 @@ File could not be opened + + Loading + \ No newline at end of file diff --git a/CastIt/Setup.cs b/CastIt/Setup.cs index 9b61be22..ce74c438 100644 --- a/CastIt/Setup.cs +++ b/CastIt/Setup.cs @@ -43,6 +43,7 @@ protected override IMvxLogProvider CreateLogProvider() {$"{typeof(FileItemViewModel).FullName}", "vm_fileitem_.txt"}, {$"{typeof(DeviceItemViewModel).FullName}", "vm_deviceitem_.txt"}, {$"{typeof(DownloadDialogViewModel).FullName}", "vm_download_dialog_.txt"}, + {$"{typeof(SplashViewModel).FullName}", "vm_splash_.txt"}, {$"{typeof(CastService).FullName}", "service_cast_.txt"}, {$"{typeof(AppSettingsService).FullName}", "service_appsettings_.txt"}, {$"{typeof(FFMpegService).FullName}", "service_ffmpeg_.txt"}, diff --git a/CastIt/ViewModels/BaseViewModel.cs b/CastIt/ViewModels/BaseViewModel.cs index aa7d72c1..46e15363 100644 --- a/CastIt/ViewModels/BaseViewModel.cs +++ b/CastIt/ViewModels/BaseViewModel.cs @@ -76,6 +76,73 @@ public string GetText(string key, params string[] args) ?? throw new Exception($"{key} was not found in the resources file"); } + public abstract class BaseViewModel : MvxViewModel, IBaseViewModel + { + #region Members + public List SubscriptionTokens = new List(); + #endregion + + #region Properties + public ITextProvider TextProvider { get; } + public IMvxMessenger Messenger { get; } + public IMvxLog Logger { get; } + public string this[string key] + => TextProvider.GetText(string.Empty, string.Empty, key) + ?? throw new Exception($"{key} was not found in the resources file"); + #endregion + + protected BaseViewModel( + ITextProvider textProvider, + IMvxMessenger messenger, + IMvxLog logger) + { + TextProvider = textProvider; + Messenger = messenger; + Logger = logger; + + RegisterMessages(); + SetCommands(); + } + + public virtual void SetCommands() + { + } + + public virtual void RegisterMessages() + { + SubscriptionTokens.Add(Messenger.Subscribe(_ => RaiseAllPropertiesChanged())); + } + + public override void ViewAppeared() + { + base.ViewAppeared(); + if (SubscriptionTokens.Count == 0) + { + RegisterMessages(); + } + } + + public override void ViewDestroy(bool viewFinishing = true) + { + base.ViewDestroy(viewFinishing); + if (!viewFinishing) + return; + foreach (var token in SubscriptionTokens) + { + token.Dispose(); + } + SubscriptionTokens.Clear(); + } + + public string GetText(string key) + => TextProvider.GetText(string.Empty, string.Empty, key) + ?? throw new Exception($"{key} was not found in the resources file"); + + public string GetText(string key, params string[] args) + => TextProvider.GetText(string.Empty, string.Empty, key, args) + ?? throw new Exception($"{key} was not found in the resources file"); + } + public abstract class BaseViewModelResult : MvxViewModelResult, IBaseViewModel { #region Members diff --git a/CastIt/ViewModels/MainViewModel.cs b/CastIt/ViewModels/MainViewModel.cs index f4346781..07345380 100644 --- a/CastIt/ViewModels/MainViewModel.cs +++ b/CastIt/ViewModels/MainViewModel.cs @@ -24,7 +24,7 @@ namespace CastIt.ViewModels { - public class MainViewModel : BaseViewModel, IMainViewModel + public class MainViewModel : BaseViewModel>, IMainViewModel { #region Members private const int NoStreamSelectedId = -1; @@ -66,7 +66,6 @@ public class MainViewModel : BaseViewModel, IMainViewModel private readonly CancellationTokenSource _webServerCancellationToken = new CancellationTokenSource(); private readonly MvxInteraction _closeApp = new MvxInteraction(); - private readonly MvxInteraction<(double, double)> _setWindowWidthAndHeight = new MvxInteraction<(double, double)>(); private readonly MvxInteraction _openSubTitleFileDialog = new MvxInteraction(); private readonly MvxInteraction _beforeDeletingPlayList = new MvxInteraction(); #endregion @@ -246,8 +245,6 @@ public int CurrentFileQuality #region Interactors public IMvxInteraction CloseApp => _closeApp; - public IMvxInteraction<(double, double)> SetWindowWidthAndHeight - => _setWindowWidthAndHeight; public IMvxInteraction OpenSubTitleFileDialog => _openSubTitleFileDialog; public IMvxInteraction BeforeDeletingPlayList @@ -279,25 +276,18 @@ public MainViewModel( } #region Methods + + public override void Prepare(List parameter) + { + PlayLists.AddRange(parameter.OrderBy(pl => pl.Position)); + } + public override async Task Initialize() { IsExpanded = _settingsService.IsPlayListExpanded; Logger.Info($"{nameof(Initialize)}: Initializing cast service..."); _castService.Init(); - Logger.Info($"{nameof(Initialize)}: Getting all playlists..."); - var playLists = await _playListsService.GetAllPlayLists(); - PlayLists.AddRange(playLists.OrderBy(pl => pl.Position)); - foreach (var playlist in playLists) - { - var files = await _playListsService.GetAllFiles(playlist.Id); - playlist.Items.AddRange(files.OrderBy(f => f.Position)); - } - - foreach (var pl in PlayLists) - { - pl.SetPositionIfChanged(); - } //This needs to happen after the playlist/files are initialized, otherwise, you will be sending a lot of ws msgs Logger.Info($"{nameof(Initialize)}: Initializing web server..."); _appWebServer.Init(this, _webServerCancellationToken.Token); @@ -314,21 +304,6 @@ public override async Task Initialize() _castService.OnVolumeChanged += OnVolumeChanged; _castService.OnFileLoadFailed += OnFileLoadFailed; - Logger.Info($"{nameof(Initialize)}: Applying app theme and accent color..."); - WindowsUtils.ChangeTheme(_settingsService.AppTheme, _settingsService.AccentColor); - - Logger.Info($"{nameof(Initialize)}: Deleting old preview / log files..."); - try - { - FileUtils.DeleteFilesInDirectory(FileUtils.GetPreviewsPath(), DateTime.Now.AddDays(-1)); - FileUtils.DeleteFilesInDirectory(FileUtils.GetLogsPath(), DateTime.Now.AddDays(-3)); - } - catch (Exception e) - { - Logger.Error(e, $"{nameof(Initialize)}: Error occurred while trying to delete previews"); - _telemetryService.TrackError(e); - } - InitializeOrUpdateFileWatcher(false); Logger.Info($"{nameof(Initialize)}: Completed"); @@ -405,9 +380,6 @@ public override void RegisterMessages() public override void ViewAppeared() { base.ViewAppeared(); - var tuple = (_settingsService.WindowWidth, _settingsService.WindowHeight); - _setWindowWidthAndHeight.Raise(tuple); - Logger.Info($"{nameof(ViewAppeared)}: Creating the file duration task.."); DurationTaskNotifier = MvxNotifyTask.Create(SetFileDurations()); string path = FileUtils.GetFFMpegPath(); diff --git a/CastIt/ViewModels/SplashViewModel.cs b/CastIt/ViewModels/SplashViewModel.cs new file mode 100644 index 00000000..1dd0be96 --- /dev/null +++ b/CastIt/ViewModels/SplashViewModel.cs @@ -0,0 +1,109 @@ +using CastIt.Common.Utils; +using CastIt.Interfaces; +using CastIt.ViewModels.Items; +using MvvmCross.Logging; +using MvvmCross.Navigation; +using MvvmCross.Plugin.Messenger; +using MvvmCross.ViewModels; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using System.Timers; + +namespace CastIt.ViewModels +{ + public class SplashViewModel : BaseViewModel + { + private readonly IMvxNavigationService _navigationService; + private readonly ITelemetryService _telemetryService; + private readonly IAppSettingsService _settingsService; + private readonly IPlayListsService _playListsService; + private readonly Timer _timer; + + private string _loadingText; + + private readonly MvxInteraction _beforeNavigatingToMainViewModel = new MvxInteraction(); + + public string LoadingText + { + get => _loadingText; + set => SetProperty(ref _loadingText, value); + } + + public IMvxInteraction BeforeNavigatingToMainViewModel + => _beforeNavigatingToMainViewModel; + + public SplashViewModel( + ITextProvider textProvider, + IMvxMessenger messenger, + IMvxLogProvider logProvider, + IMvxNavigationService navigationService, + ITelemetryService telemetryService, + IAppSettingsService settingsService, + IPlayListsService playListsService) : base(textProvider, messenger, logProvider.GetLogFor()) + { + _navigationService = navigationService; + _telemetryService = telemetryService; + _settingsService = settingsService; + _playListsService = playListsService; + + _timer = new Timer(800) + { + AutoReset = false + }; + _timer.Elapsed += TimerElapsed; + } + + public override Task Initialize() + { + LoadingText = $"{GetText("Loading")}..."; + Logger.Info($"{nameof(Initialize)}: Applying app theme and accent color..."); + WindowsUtils.ChangeTheme(_settingsService.AppTheme, _settingsService.AccentColor); + + Logger.Info($"{nameof(Initialize)}: Deleting old preview / log files..."); + try + { + FileUtils.DeleteFilesInDirectory(FileUtils.GetPreviewsPath(), DateTime.Now.AddDays(-1)); + FileUtils.DeleteFilesInDirectory(FileUtils.GetLogsPath(), DateTime.Now.AddDays(-3)); + } + catch (Exception e) + { + Logger.Error(e, $"{nameof(Initialize)}: Error occurred while trying to delete previews"); + _telemetryService.TrackError(e); + } + return base.Initialize(); + } + + public override void ViewAppeared() + { + base.ViewAppeared(); + _timer.Start(); + } + + public (double, double) GetWindowWidthAndHeight() + { + return (_settingsService.WindowWidth, _settingsService.WindowHeight); + } + + private async void TimerElapsed(object sender, ElapsedEventArgs e) + { + _timer.Stop(); + _timer.Elapsed -= TimerElapsed; + _timer.Dispose(); + + Logger.Info($"{nameof(Initialize)}: Getting all playlists..."); + var playLists = await _playListsService.GetAllPlayLists(); + foreach (var playlist in playLists) + { + var files = await _playListsService.GetAllFiles(playlist.Id); + playlist.Items.AddRange(files.OrderBy(f => f.Position)); + playlist.SetPositionIfChanged(); + } + + Logger.Info($"{nameof(Initialize)}: Navigating to main view model..."); + await _navigationService.Navigate>(playLists); + _beforeNavigatingToMainViewModel.Raise(); + } + } +} diff --git a/CastIt/Views/MainPage.xaml.cs b/CastIt/Views/MainPage.xaml.cs index 1fbb4da9..58804f71 100644 --- a/CastIt/Views/MainPage.xaml.cs +++ b/CastIt/Views/MainPage.xaml.cs @@ -18,7 +18,6 @@ public partial class MainPage : MvxWpfView //TODO: IF YOU DRAG OUT OF THE WINDOW, THE SEPARATORS ARE SHOWN private IMvxInteraction _closeAppRequest; - private IMvxInteraction<(double, double)> _setWindowWithAndHeightRequest; private IMvxInteraction _openSubTitleFileDialogRequest; private IMvxInteraction _beforeDeletingPlayListRequest; @@ -36,20 +35,6 @@ public IMvxInteraction CloseAppRequest } } - public IMvxInteraction<(double, double)> SetWindowWithAndHeightRequest - { - get => _setWindowWithAndHeightRequest; - set - { - if (_setWindowWithAndHeightRequest != null) - _setWindowWithAndHeightRequest.Requested -= SetWindowWidthAndHeight; - - _setWindowWithAndHeightRequest = value; - if (value != null) - _setWindowWithAndHeightRequest.Requested += SetWindowWidthAndHeight; - } - } - public IMvxInteraction OpenSubTitleFileDialogRequest { get => _openSubTitleFileDialogRequest; @@ -83,7 +68,6 @@ public MainPage() InitializeComponent(); var set = this.CreateBindingSet(); - set.Bind(this).For(v => v.SetWindowWithAndHeightRequest).To(vm => vm.SetWindowWidthAndHeight).OneWay(); set.Bind(this).For(v => v.CloseAppRequest).To(vm => vm.CloseApp).OneWay(); set.Bind(this).For(v => v.OpenSubTitleFileDialogRequest).To(vm => vm.OpenSubTitleFileDialog).OneWay(); set.Bind(this).For(v => v.BeforeDeletingPlayListRequest).To(vm => vm.BeforeDeletingPlayList).OneWay(); @@ -94,14 +78,6 @@ public Dictionary GetTabsPosition() => PlayListTabControl.GetOrderedHeaders() .ToDictionary(a => (a.Content as PlayListItemViewModel), a => a.LogicalIndex); - private void SetWindowWidthAndHeight(object sender, MvxValueEventArgs<(double, double)> e) - { - //TODO: SOMETIMES, THE INTERACTION IS NOT BEING RAISED - var window = System.Windows.Application.Current.MainWindow; - window.Width = e.Value.Item1; - window.Height = e.Value.Item2; - } - private void OpenSubtitleFileDialog(object sender, EventArgs e) { var allowedFormats = AppConstants.AllowedSubtitleFormatsString; diff --git a/CastIt/Views/Splash.xaml b/CastIt/Views/Splash.xaml new file mode 100644 index 00000000..37187114 --- /dev/null +++ b/CastIt/Views/Splash.xaml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + diff --git a/CastIt/Views/Splash.xaml.cs b/CastIt/Views/Splash.xaml.cs new file mode 100644 index 00000000..b627410e --- /dev/null +++ b/CastIt/Views/Splash.xaml.cs @@ -0,0 +1,65 @@ +using CastIt.Common; +using CastIt.ViewModels; +using MvvmCross.Platforms.Wpf.Views; +using MvvmCross.ViewModels; +using System; +using System.Windows; + +namespace CastIt.Views +{ + [MvxViewFor(typeof(SplashViewModel))] + public partial class Splash : MvxWpfView + { + private IMvxInteraction _beforeNavigatingToMainViewModelRequest; + + public IMvxInteraction BeforeNavigatingToMainViewModelRequest + { + get => _beforeNavigatingToMainViewModelRequest; + set + { + if (_beforeNavigatingToMainViewModelRequest != null) + _beforeNavigatingToMainViewModelRequest.Requested -= BeforeNavigatingToMainViewModel; + + _beforeNavigatingToMainViewModelRequest = value; + if (value != null) + _beforeNavigatingToMainViewModelRequest.Requested += BeforeNavigatingToMainViewModel; + } + } + + public Splash() + { + InitializeComponent(); + + //Small values to make the splash screen look good + SetWindowWidthAndHeight(450, 300, false, false, false); + + var set = CreateBindingSet(); + set.Bind(this).For(v => v.BeforeNavigatingToMainViewModelRequest).To(vm => vm.BeforeNavigatingToMainViewModel).OneWay(); + set.Apply(); + } + + private void BeforeNavigatingToMainViewModel(object sender, EventArgs e) + { + var (width, height) = ViewModel.GetWindowWidthAndHeight(); + SetWindowWidthAndHeight(width, height, true, true, true); + } + + private void SetWindowWidthAndHeight(double width, double height, bool canResize, bool updateMinSizes, bool showInTaskBar) + { + Dispatcher.Invoke(() => + { + var window = System.Windows.Application.Current.MainWindow; + window.Width = width; + window.Height = height; + if (updateMinSizes) + { + window.MinWidth = AppConstants.MinWindowWidth; + window.MinHeight = AppConstants.MinWindowHeight; + } + + window.ResizeMode = canResize ? ResizeMode.CanResize : ResizeMode.NoResize; + window.ShowInTaskbar = showInTaskBar; + }); + } + } +}