From 8d92f6d48aa428b1e92a26de53fbf511e780793c Mon Sep 17 00:00:00 2001 From: Sean Hall Date: Fri, 15 Feb 2019 18:49:04 -0600 Subject: Import WixBA from old v4 repo --- src/WixToolset.WixBA/UpdateViewModel.cs | 207 ++++++++++++++++++++++++++++++++ 1 file changed, 207 insertions(+) create mode 100644 src/WixToolset.WixBA/UpdateViewModel.cs (limited to 'src/WixToolset.WixBA/UpdateViewModel.cs') diff --git a/src/WixToolset.WixBA/UpdateViewModel.cs b/src/WixToolset.WixBA/UpdateViewModel.cs new file mode 100644 index 00000000..6b60112c --- /dev/null +++ b/src/WixToolset.WixBA/UpdateViewModel.cs @@ -0,0 +1,207 @@ +// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. + +namespace WixToolset.UX +{ + using System; + using System.ComponentModel; + using System.Windows.Input; + using WixToolset.Bootstrapper; + + /// + /// The states of the update view model. + /// + public enum UpdateState + { + Unknown, + Initializing, + Checking, + Current, + Available, + Failed, + } + + /// + /// The model of the update view. + /// + public class UpdateViewModel : PropertyNotifyBase + { + private RootViewModel root; + private UpdateState state; + private ICommand updateCommand; + private string updateVersion; + private string updateChanges; + + + public UpdateViewModel(RootViewModel root) + { + this.root = root; + WixBA.Model.Bootstrapper.DetectUpdateBegin += this.DetectUpdateBegin; + WixBA.Model.Bootstrapper.DetectUpdate += this.DetectUpdate; + WixBA.Model.Bootstrapper.DetectUpdateComplete += this.DetectUpdateComplete; + + this.root.PropertyChanged += new PropertyChangedEventHandler(this.RootPropertyChanged); + + this.State = UpdateState.Initializing; + } + + void RootPropertyChanged(object sender, PropertyChangedEventArgs e) + { + if ("InstallState" == e.PropertyName) + { + base.OnPropertyChanged("CanUpdate"); + } + } + + public bool CheckingEnabled + { + get { return this.State == UpdateState.Initializing || this.State == UpdateState.Checking; } + } + + public bool CanUpdate + { + get + { + switch(this.root.InstallState) + { + case InstallationState.Waiting: + case InstallationState.Applied: + case InstallationState.Failed: + return this.IsUpdateAvailable; + default: + return false; + } + } + } + + public ICommand UpdateCommand + { + get + { + if (this.updateCommand == null) + { + this.updateCommand = new RelayCommand(param => WixBA.Plan(LaunchAction.UpdateReplace), param => this.CanUpdate); + } + + return this.updateCommand; + } + } + + public bool IsUpdateAvailable + { + get { return this.State == UpdateState.Available; } + } + + /// + /// Gets and sets the state of the update view model. + /// + public UpdateState State + { + get + { + return this.state; + } + + set + { + if (this.state != value) + { + this.state = value; + base.OnPropertyChanged("State"); + base.OnPropertyChanged("CanUpdate"); + base.OnPropertyChanged("CheckingEnabled"); + base.OnPropertyChanged("IsUpdateAvailable"); + } + } + } + /// + /// The version of an available update. + /// + public string UpdateVersion + { + get + { + return updateVersion; + } + set + { + if (this.updateVersion != value) + { + this.updateVersion = value; + base.OnPropertyChanged("UpdateVersion"); + } + } + } + + /// + /// The changes in the available update. + /// + public string UpdateChanges + { + get + { + return updateChanges; + } + set + { + if (this.updateChanges != value) + { + this.updateChanges = value; + base.OnPropertyChanged("UpdateChanges"); + } + } + } + + private void DetectUpdateBegin(object sender, Bootstrapper.DetectUpdateBeginEventArgs e) + { + // Don't check for updates if: + // the first check failed (no retry) + // if we are being run as an uninstall + // if we are not under a full UI. + if ((UpdateState.Failed != this.State) && (LaunchAction.Uninstall != WixBA.Model.Command.Action) && (Display.Full == WixBA.Model.Command.Display)) + { + this.State = UpdateState.Checking; + e.Skip = false; + } + } + + private void DetectUpdate(object sender, Bootstrapper.DetectUpdateEventArgs e) + { + // The list of updates is sorted in descending version, so the first callback should be the largest update available. + // This update should be either larger than ours (so we are out of date), the same as ours (so we are current) + // or smaller than ours (we have a private build). If we really wanted to, we could leave the e.StopProcessingUpdates alone and + // enumerate all of the updates. + WixBA.Model.Engine.Log(LogLevel.Verbose, String.Format("Potential update v{0} from '{1}'; current version: v{2}", e.Version, e.UpdateLocation, WixBA.Model.Version)); + if (e.Version > WixBA.Model.Version) + { + WixBA.Model.Engine.SetUpdate(null, e.UpdateLocation, e.Size, UpdateHashType.None, null); + this.UpdateVersion = String.Concat("v", e.Version.ToString()); + string changesFormat = @"{0}"; + this.UpdateChanges = String.Format(changesFormat, e.Content); + this.State = UpdateState.Available; + } + else + { + this.State = UpdateState.Current; + } + e.StopProcessingUpdates = true; + } + + private void DetectUpdateComplete(object sender, Bootstrapper.DetectUpdateCompleteEventArgs e) + { + // Failed to process an update, allow the existing bundle to still install. + if ((UpdateState.Failed != this.State) && !Hresult.Succeeded(e.Status)) + { + this.State = UpdateState.Failed; + WixBA.Model.Engine.Log(LogLevel.Verbose, String.Format("Failed to locate an update, status of 0x{0:X8}, updates disabled.", e.Status)); + e.IgnoreError = true; + } + // If we are uninstalling, we don't want to check or show an update + // If we are checking, then the feed didn't find any valid enclosures + // If we are initializing, we're either uninstalling or not a full UI + else if ((LaunchAction.Uninstall == WixBA.Model.Command.Action) || (UpdateState.Initializing == this.State) || (UpdateState.Checking == this.State)) + { + this.State = UpdateState.Unknown; + } + } + } +} -- cgit v1.2.3-55-g6feb