using System; using System.Threading.Tasks; using Filtration.Common.ViewModels; using Filtration.Interface; using Filtration.Services; using GalaSoft.MvvmLight.CommandWpf; namespace Filtration.ViewModels { public interface IUpdateViewModel : IDocument { RelayCommand HideUpdateWindowCommand { get; } RelayCommand NextStepCommand { get; } UpdateStatus UpdateStatus { get; } string ReleaseNotes { get; } string Version { get; } string NextStepButtonText { get; } bool Visible { get; } bool IsInErrorState { get; } } /// /// This ViewModel is shared between UpdateView.xaml and UpdateTabView.xaml since they are both /// parts of the same update process, first the user gets given the opportunity to download the /// update from the UpdateView box and then once it is ready to install they click Update /// and are taken to the UpdateTabView tab where they can see the changes and begin the installation /// of the update. /// internal class UpdateViewModel : PaneViewModel, IUpdateViewModel { private readonly IAvalonDockWorkspaceViewModel _avalonDockWorkspaceViewModel; private readonly IUpdateService _updateService; private string _nextStepButtonText; private bool _visible; private bool _updateTabShown; public UpdateViewModel(IAvalonDockWorkspaceViewModel avalonDockWorkspaceViewModel, IUpdateService updateService) { _avalonDockWorkspaceViewModel = avalonDockWorkspaceViewModel; _updateService = updateService; updateService.UpdateProgressChanged += UpdateServiceOnUpdateProgressChanged; updateService.UpdateStatusChanged += UpdateServiceOnUpdateStatusChanged; HideUpdateWindowCommand = new RelayCommand(OnHideUpdateWindowCommand, () => UpdateStatus == UpdateStatus.UpdateAvailable || UpdateStatus == UpdateStatus.Error); NextStepCommand = new RelayCommand(async () => await OnNextStepCommandAsync(), () => NextStepCommandEnabled); Title = "Update Available"; } public RelayCommand NextStepCommand { get; } public RelayCommand HideUpdateWindowCommand { get; } public UpdateStatus UpdateStatus => _updateService.UpdateStatus; public bool IsInErrorState => UpdateStatus == UpdateStatus.Error; public async Task Close() { await Task.FromResult(true); } public RelayCommand CloseCommand { get; } public bool IsScript => false; public bool IsTheme => false; public bool Visible { get => _visible; private set { _visible = value; RaisePropertyChanged(); } } public string ReleaseNotes => _updateService.LatestReleaseNotes; public string Version => _updateService.LatestReleaseVersion; public string NextStepButtonText { get => _nextStepButtonText; set { _nextStepButtonText = value; RaisePropertyChanged(); } } private bool NextStepCommandEnabled => UpdateStatus == UpdateStatus.UpdateAvailable || UpdateStatus == UpdateStatus.ReadyToApplyUpdate || UpdateStatus == UpdateStatus.UpdateComplete; private async Task OnNextStepCommandAsync() { switch (UpdateStatus) { case UpdateStatus.UpdateAvailable: { await _updateService.DownloadUpdatesAsync(); break; } case UpdateStatus.ReadyToApplyUpdate: { if (!_updateTabShown) { // When the update has downloaded and is ready to apply, clicking the button // closes the update popup and shows the update tab. _avalonDockWorkspaceViewModel.AddDocument(this); Visible = false; _updateTabShown = true; NextStepButtonText = "Update"; } else { await _updateService.ApplyUpdatesAsync(); } break; } case UpdateStatus.UpdateComplete: { _updateService.RestartAfterUpdate(); break; } } } private void UpdateServiceOnUpdateStatusChanged(object sender, UpdateStatusChangedEventArgs e) { switch (UpdateStatus) { case UpdateStatus.UpdateAvailable: { Visible = true; NextStepButtonText = "Download"; RaisePropertyChanged(nameof(Version)); break; } case UpdateStatus.Downloading: { HideUpdateWindowCommand.RaiseCanExecuteChanged(); NextStepButtonText = "Downloading (0%)"; break; } case UpdateStatus.ReadyToApplyUpdate: { RaisePropertyChanged(nameof(ReleaseNotes)); NextStepButtonText = "Update Ready"; break; } case UpdateStatus.Updating: { NextStepButtonText = "Updating (0%)"; break; } case UpdateStatus.UpdateComplete: { NextStepButtonText = "Restart"; break; } case UpdateStatus.Error: { NextStepButtonText = "Update Error - Check Logs"; Visible = true; break; } } NextStepCommand.RaiseCanExecuteChanged(); RaisePropertyChanged(nameof(UpdateStatus)); RaisePropertyChanged(nameof(IsInErrorState)); } private void UpdateServiceOnUpdateProgressChanged(object sender, UpdateProgressChangedEventArgs e) { if (UpdateStatus == UpdateStatus.Downloading) { NextStepButtonText = $"Downloading ({e.Progress}%)"; } else if (UpdateStatus == UpdateStatus.Updating) { NextStepButtonText = $"Updating ({e.Progress}%)"; } } private void OnHideUpdateWindowCommand() { Visible = false; } } }