aboutsummaryrefslogtreecommitdiffstats
path: root/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/ViewModels/UpdateViewVM.cs
diff options
context:
space:
mode:
Diffstat (limited to 'Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/ViewModels/UpdateViewVM.cs')
-rw-r--r--Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/ViewModels/UpdateViewVM.cs305
1 files changed, 305 insertions, 0 deletions
diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/ViewModels/UpdateViewVM.cs b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/ViewModels/UpdateViewVM.cs
new file mode 100644
index 000000000..6be4ba4ca
--- /dev/null
+++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/ViewModels/UpdateViewVM.cs
@@ -0,0 +1,305 @@
+using FluentFTP;
+using Ionic.Zip;
+using Microsoft.Practices.ServiceLocation;
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.IO;
+using System.Linq;
+using System.Runtime.CompilerServices;
+using System.ServiceModel;
+using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
+using Tango.Core.Commands;
+using Tango.Core.Helpers;
+using Tango.Logging;
+using Tango.MachineStudio.Common.Authentication;
+using Tango.MachineStudio.Common.Navigation;
+using Tango.MachineStudio.Common.Notifications;
+using Tango.MachineStudio.Common.StudioApplication;
+using Tango.MachineStudio.Common.Update;
+using Tango.SharedUI;
+
+namespace Tango.MachineStudio.UI.ViewModels
+{
+ public enum UpdateStatus
+ {
+ None,
+ CheckingForUpdate,
+ UpToDate,
+ UpdateAvailable,
+ Downloading,
+ Updating,
+ UpdateCompleted,
+ Error,
+ }
+
+ public class UpdateViewVM : ViewModel
+ {
+ private String _appPath = AppDomain.CurrentDomain.BaseDirectory;
+
+ private INotificationProvider _notification;
+ private INavigationManager _navigation;
+ private IStudioApplicationManager _application;
+ private IAuthenticationProvider _authentication;
+ private CheckForUpdatesResponse _updateInfo;
+ private String _newPackageTempFolder;
+
+ private UpdateStatus _status;
+ public UpdateStatus Status
+ {
+ get { return _status; }
+ set { _status = value; RaisePropertyChangedAuto(); }
+ }
+
+ private String _latestVersion;
+ public String LatestVersion
+ {
+ get { return _latestVersion; }
+ set { _latestVersion = value; RaisePropertyChangedAuto(); }
+ }
+
+ private double _downloadProgress;
+
+ public double DownloadProgress
+ {
+ get { return _downloadProgress; }
+ set { _downloadProgress = value; RaisePropertyChangedAuto(); }
+ }
+
+ private double _updateProgress;
+
+ public double UpdateProgress
+ {
+ get { return _updateProgress; }
+ set { _updateProgress = value; RaisePropertyChangedAuto(); }
+ }
+
+ private String _currentUpdateFile;
+
+ public String CurrentUpdateFile
+ {
+ get { return _currentUpdateFile; }
+ set { _currentUpdateFile = value; RaisePropertyChanged(nameof(CurrentUpdateFile)); }
+ }
+
+ public RelayCommand UpdateCommand { get; set; }
+
+ public RelayCommand BackCommand { get; set; }
+
+ public RelayCommand RestartCommand { get; set; }
+
+ public RelayCommand TryAgainCommand { get; set; }
+
+ public UpdateViewVM(INotificationProvider notification, IAuthenticationProvider authentication, INavigationManager navigation, IStudioApplicationManager application)
+ {
+ _notification = notification;
+ _navigation = navigation;
+ _application = application;
+ _authentication = authentication;
+
+ LatestVersion = "1.0.0.2";
+ Status = UpdateStatus.CheckingForUpdate;
+ UpdateCommand = new RelayCommand(StartUpdate, () => Status == UpdateStatus.UpdateAvailable);
+ BackCommand = new RelayCommand(BackToApplication, () => Status != UpdateStatus.Updating);
+ RestartCommand = new RelayCommand(RestartApplication, () => Status == UpdateStatus.UpdateCompleted);
+ TryAgainCommand = new RelayCommand(TryAgain, () => Status == UpdateStatus.Error);
+ }
+
+ public void OnNavigatedInto()
+ {
+ CheckForUpdates();
+ }
+
+ private void CheckForUpdates()
+ {
+ Status = UpdateStatus.CheckingForUpdate;
+
+ ChannelFactory<IMachineStudioUpdateService> service = null;
+
+ Task.Factory.StartNew(() =>
+ {
+ try
+ {
+ Thread.Sleep(2000);
+
+ service = UpdateServiceHelper.GetUpdateServiceChannel();
+ var client = service.CreateChannel();
+
+ CheckForUpdatesResponse response = client.CheckForUpdates(new CheckForUpdatesRequest()
+ {
+ Email = _authentication.CurrentUser.Email,
+ Password = _authentication.CurrentUser.Password,
+ Version = _application.Version,
+ });
+
+ if (response.IsUpdateAvailable)
+ {
+ _updateInfo = response;
+ Status = UpdateStatus.UpdateAvailable;
+ LatestVersion = response.Version;
+ }
+ else
+ {
+ Status = UpdateStatus.UpToDate;
+ }
+ }
+ catch (Exception ex)
+ {
+ LogManager.Log(ex, "Error while checking for version update!");
+ Status = UpdateStatus.Error;
+ }
+ finally
+ {
+ if (service != null)
+ {
+ service.Close();
+ }
+ }
+ });
+ }
+
+ private void BackToApplication()
+ {
+ if (Status == UpdateStatus.Downloading)
+ {
+ if (!_notification.ShowQuestion("This will abort all update operations. Are you sure?"))
+ {
+ return;
+ }
+ }
+
+ _navigation.NavigateTo(NavigationView.MainView);
+ Status = UpdateStatus.None;
+ }
+
+ private void StartUpdate()
+ {
+ DownloadProgress = 0;
+ UpdateProgress = 0;
+
+ Status = UpdateStatus.Downloading;
+
+ Task.Factory.StartNew(() =>
+ {
+ var tempFile = PathHelper.GetTempFilePath() + ".zip";
+
+ try
+ {
+ LogManager.Log("Creating temporary file " + tempFile);
+
+ int fileSize = 0;
+
+ using (FileStreamWrapper fs = new FileStreamWrapper(tempFile, FileMode.Create, (current) =>
+ {
+ InvokeUINow(() =>
+ {
+ Thread.Sleep(10);
+ DownloadProgress = ((double)current / (double)fileSize) * 100d;
+ });
+ }))
+ {
+ using (FtpClient ftp = new FtpClient(_updateInfo.FtpHost, _updateInfo.UserName, _updateInfo.Password))
+ {
+ LogManager.Log("Connecting to FTP site: " + _updateInfo.FtpHost);
+ ftp.ConnectAsync().Wait();
+ LogManager.Log("Retrieving download size...");
+ fileSize = (int)ftp.GetFileSize(_updateInfo.FilePath);
+ LogManager.Log("Download size: " + fileSize + " bytes.");
+ LogManager.Log("Starting download...");
+ ftp.DownloadAsync(fs, _updateInfo.FilePath).Wait();
+ }
+ }
+
+
+ Status = UpdateStatus.Updating;
+
+ _newPackageTempFolder = PathHelper.GetTempFolderPath();
+
+ using (ZipFile zip = ZipFile.Read(tempFile))
+ {
+ int currentEntry = 0;
+
+ zip.ExtractProgress += (x, args) =>
+ {
+ if (args.EventType == ZipProgressEventType.Extracting_AfterExtractEntry)
+ {
+ LogManager.Log("Extracting " + Path.GetFileName(args.CurrentEntry.FileName));
+ UpdateProgress = ((double)(currentEntry++) / (double)zip.Entries.Count) * 100d;
+ }
+ };
+
+ foreach (ZipEntry entry in zip)
+ {
+ Thread.Sleep(10);
+
+ string newPath = Path.Combine(_newPackageTempFolder, entry.FileName);
+
+ try
+ {
+ if (entry.IsDirectory)
+ {
+ Directory.CreateDirectory(newPath);
+ }
+ else
+ {
+ CurrentUpdateFile = Path.GetFileName(entry.FileName);
+ entry.Extract(_newPackageTempFolder, ExtractExistingFileAction.OverwriteSilently);
+ }
+ }
+ catch
+ {
+ LogManager.Log("Could not extract file " + entry.FileName);
+ }
+ }
+ }
+
+ ServiceLocator.Current.GetInstance<MainViewVM>().DisableCheckForUpdates = true;
+ Status = UpdateStatus.UpdateCompleted;
+ }
+ catch (Exception ex)
+ {
+ LogManager.Log(ex, "Error while extracting update package.");
+ Status = UpdateStatus.Error;
+ }
+ finally
+ {
+ PathHelper.TryDeleteFile(tempFile);
+ }
+ });
+ }
+
+ private void TryAgain()
+ {
+ CheckForUpdates();
+ }
+
+ private void RestartApplication()
+ {
+ try
+ {
+ Process p = new Process();
+ p.StartInfo.FileName = _appPath + "\\Tango.MachineStudio.Updater.exe";
+ p.StartInfo.UseShellExecute = true;
+ p.StartInfo.Arguments = _newPackageTempFolder;
+ p.Start();
+ }
+ catch (Exception ex)
+ {
+ if (ex.Message == "The operation was canceled by the user")
+ {
+ _notification.ShowWarning("It seems like you refused to invoke our update utility. This prevents Machine Studio from completing the update process!");
+ return;
+ }
+ }
+ Environment.Exit(0);
+ }
+
+ protected override void RaisePropertyChangedAuto([CallerMemberName] string caller = null)
+ {
+ base.RaisePropertyChangedAuto(caller);
+ InvalidateRelayCommands();
+ }
+ }
+}