From 38f32e1baa437107e417fb75c808a47e1945baa0 Mon Sep 17 00:00:00 2001 From: dovholuknf <46322585+dovholuknf@users.noreply.github.com> Date: Fri, 12 Aug 2022 17:50:34 -0400 Subject: [PATCH 1/6] fix math bug and add a log statement when the hash doesn't match --- ZitiUpdateService/UpdateService.cs | 2 +- ZitiUpdateService/checkers/GithubCheck.cs | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/ZitiUpdateService/UpdateService.cs b/ZitiUpdateService/UpdateService.cs index 6c6cab57..8dc5046e 100644 --- a/ZitiUpdateService/UpdateService.cs +++ b/ZitiUpdateService/UpdateService.cs @@ -584,7 +584,7 @@ namespace ZitiUpdateService { upInt = new TimeSpan(0, 10, 0); } - if (upInt.TotalMilliseconds < 10 * 60 * 60 * 1000) + if (upInt.TotalMilliseconds < 10 * 60 * 1000) { Logger.Warn("provided time [{0}] is too small. Using 10 minutes.", updateTimerInterval); #if MOCKUPDATE || ALLOWFASTINTERVAL diff --git a/ZitiUpdateService/checkers/GithubCheck.cs b/ZitiUpdateService/checkers/GithubCheck.cs index 7e213c46..fa456f44 100644 --- a/ZitiUpdateService/checkers/GithubCheck.cs +++ b/ZitiUpdateService/checkers/GithubCheck.cs @@ -97,6 +97,7 @@ namespace ZitiUpdateService.Checkers { string computed = BitConverter.ToString(sha256bytes).Replace("-", ""); File.Delete(sha256dest); + Logger.Info("comparing computed hash: {0} to downloaded hash: {1}", computed, hash); return computed.ToLower().Trim() == hash.ToLower().Trim(); } } From be3157e332fab5011e7ebf2c2bd3bd0c4a61b92f Mon Sep 17 00:00:00 2001 From: dovholuknf <46322585+dovholuknf@users.noreply.github.com> Date: Mon, 15 Aug 2022 12:55:16 -0400 Subject: [PATCH 2/6] initial rev of automatic upgrade disabling --- DesktopEdge/MainWindow.xaml.cs | 12 ++- DesktopEdge/Views/Screens/MainMenu.xaml | 5 ++ DesktopEdge/Views/Screens/MainMenu.xaml.cs | 52 ++++++++++++- .../DataStructures/DataStructures.cs | 7 ++ ZitiDesktopEdge.Client/Server/IPCServer.cs | 6 ++ .../ServiceClient/DataClient.cs | 4 +- .../ServiceClient/MonitorClient.cs | 16 ++++ ZitiUpdateService/UpdateService.cs | 76 ++++++++++++++----- ZitiUpdateService/ZitiUpdateService.csproj | 1 + 9 files changed, 150 insertions(+), 29 deletions(-) diff --git a/DesktopEdge/MainWindow.xaml.cs b/DesktopEdge/MainWindow.xaml.cs index a95372fb..e1d85964 100644 --- a/DesktopEdge/MainWindow.xaml.cs +++ b/DesktopEdge/MainWindow.xaml.cs @@ -648,7 +648,9 @@ namespace ZitiDesktopEdge { } private void MonitorClient_OnCommunicationError(object sender, Exception e) { - ShowError("Communication Error", e.Message); + string msg = "Communication Error with monitor?"; + logger.Warn(msg); + ShowError(msg, e.Message); } private void MainMenu_OnShowBlurb(string message) { @@ -754,8 +756,10 @@ namespace ZitiDesktopEdge { string nextVersionStr = null; - private void MonitorClient_OnReconnectFailure(object sender, object e) { - if (nextVersionStr == null) { + private void MonitorClient_OnReconnectFailure(object sender, object e) + { + logger.Debug("OnReconnectFailure triggered"); + if (nextVersionStr == null) { // check for the current version nextVersionStr = "checking for update"; Version nextVersion = VersionUtil.NormalizeVersion(GithubAPI.GetVersion(GithubAPI.GetJson(GithubAPI.ProdUrl))); @@ -779,6 +783,7 @@ namespace ZitiDesktopEdge { private void MonitorClient_OnShutdownEvent(object sender, StatusEvent e) { + logger.Info("The monitor has indicated the application should shut down."); this.Dispatcher.Invoke(() => { Application.Current.Shutdown(); }); @@ -795,6 +800,7 @@ namespace ZitiDesktopEdge { } logger.Debug("MonitorClient_OnServiceStatusEvent: {0}", evt.Status); Application.Current.Properties["ReleaseStream"] = evt.ReleaseStream; + Application.Current.Properties["AutomaticUpgradeDisabled"] = evt.AutomaticUpgradeDisabled; ServiceControllerStatus status = (ServiceControllerStatus)Enum.Parse(typeof(ServiceControllerStatus), evt.Status); switch (status) { diff --git a/DesktopEdge/Views/Screens/MainMenu.xaml b/DesktopEdge/Views/Screens/MainMenu.xaml index 8f424d0a..bc90f7b6 100644 --- a/DesktopEdge/Views/Screens/MainMenu.xaml +++ b/DesktopEdge/Views/Screens/MainMenu.xaml @@ -64,6 +64,7 @@ + @@ -96,6 +97,10 @@ + + + + diff --git a/DesktopEdge/Views/Screens/MainMenu.xaml.cs b/DesktopEdge/Views/Screens/MainMenu.xaml.cs index df6383be..3520d09c 100644 --- a/DesktopEdge/Views/Screens/MainMenu.xaml.cs +++ b/DesktopEdge/Views/Screens/MainMenu.xaml.cs @@ -35,12 +35,18 @@ namespace ZitiDesktopEdge { private string appVersion = null; private bool allowReleaseSelect = false; public double MainHeight = 500; - + private bool isBeta { get { return Application.Current.Properties["ReleaseStream"]?.ToString() == "beta"; } } + private bool automaticUpgradeDisabled { + get + { + return bool.TrueString.ToLower() == ("" + Application.Current.Properties["AutomaticUpgradeDisabled"]?.ToString()).ToLower().Trim(); + } + } public void ShowUpdateAvailable(double timeLeft, DateTime updateTime) { ForceUpdate.Visibility = Visibility.Visible; @@ -124,6 +130,12 @@ namespace ZitiDesktopEdge { UpdateState(); } + private void ShowAutomaticUpgradesMenuAction(object sender, MouseButtonEventArgs e) + { + menuState = "ConfigureAutomaticUpgrades"; + UpdateState(); + } + async private void SetReleaseStreamMenuAction(object sender, MouseButtonEventArgs e) { CheckForUpdateStatus.Visibility = Visibility.Collapsed; TriggerUpdateButton.Visibility = Visibility.Collapsed; @@ -154,6 +166,23 @@ namespace ZitiDesktopEdge { UpdateState(); } + async private void SetAutomaticUpgradesMenuAction(object sender, MouseButtonEventArgs e) { + bool disableAutomaticUpgrades = false; + if(sender == AutomaticUpgradesItemOff) { + disableAutomaticUpgrades = true; + } + var monitorClient = (MonitorClient)Application.Current.Properties["MonitorClient"]; + + SvcResponse r = await monitorClient.SetAutomaticUpgradeDisabledAsync(disableAutomaticUpgrades); + if(r.Code != 0) { + logger.Error(r?.Error); + } else { + Application.Current.Properties["AutomaticUpgradeDisabled"] = disableAutomaticUpgrades; + } + SetAutomaticUpgradesState(disableAutomaticUpgrades); + UpdateState(); + } + private void checkResponse(SvcResponse r, string titleOnErr, string msgOnErr) { if (r == null) { MainWindow.ShowError(titleOnErr, msgOnErr); @@ -168,7 +197,10 @@ namespace ZitiDesktopEdge { } private void UpdateState() { - IdListScrollView.Height = this.ActualHeight-100.00; + double h = this.ActualHeight - 100.00; + if (h > 0) { + IdListScrollView.Height = h; + } IdListScrollView.Visibility = Visibility.Collapsed; MainItems.Visibility = Visibility.Collapsed; AboutItems.Visibility = Visibility.Collapsed; @@ -181,7 +213,8 @@ namespace ZitiDesktopEdge { ConfigItems.Visibility = Visibility.Collapsed; LogLevelItems.Visibility = Visibility.Collapsed; ReleaseStreamItems.Visibility = Visibility.Collapsed; - + AutomaticUpgradesItems.Visibility = Visibility.Collapsed; + if (menuState == "About") { MenuTitle.Content = "About"; AboutItemsArea.Visibility = Visibility.Visible; @@ -233,12 +266,18 @@ namespace ZitiDesktopEdge { MenuTitle.Content = "Set Release Stream"; ReleaseStreamItems.Visibility = allowReleaseSelect ? Visibility.Visible : Visibility.Collapsed; BackArrow.Visibility = Visibility.Visible; + } else if (menuState == "ConfigureAutomaticUpgrades") + { + SetAutomaticUpgradesState(automaticUpgradeDisabled); + MenuTitle.Content = "Automatic Upgrades"; + AutomaticUpgradesItems.Visibility = Visibility.Visible; + BackArrow.Visibility = Visibility.Visible; } else if (menuState == "Config") { MenuTitle.Content = "Tunnel Configuration"; ConfigItems.Visibility = Visibility.Visible; BackArrow.Visibility = Visibility.Visible; - ConfigPageSize.Value = ((Application.Current.Properties.Contains("ApiPageSize"))?Application.Current.Properties["ApiPageSize"].ToString(): "250"); + ConfigPageSize.Value = ((Application.Current.Properties.Contains("ApiPageSize"))?Application.Current.Properties["ApiPageSize"].ToString(): "25"); ConfigIp.Value = Application.Current.Properties["ip"]?.ToString(); ConfigSubnet.Value = Application.Current.Properties["subnet"]?.ToString(); ConfigMtu.Value = Application.Current.Properties["mtu"]?.ToString(); @@ -391,6 +430,11 @@ namespace ZitiDesktopEdge { this.ReleaseStreamItemBeta.IsSelected = isBeta; this.ReleaseStreamItemStable.IsSelected = !isBeta; } + private void SetAutomaticUpgradesState(bool yesNo) + { + this.AutomaticUpgradesItemOn.IsSelected = !yesNo; + this.AutomaticUpgradesItemOff.IsSelected = yesNo; + } async private void CheckForUpdate_Click(object sender, RoutedEventArgs e) { logger.Info("checking for update..."); diff --git a/ZitiDesktopEdge.Client/DataStructures/DataStructures.cs b/ZitiDesktopEdge.Client/DataStructures/DataStructures.cs index f12a61f6..bc9b44b9 100644 --- a/ZitiDesktopEdge.Client/DataStructures/DataStructures.cs +++ b/ZitiDesktopEdge.Client/DataStructures/DataStructures.cs @@ -478,9 +478,16 @@ namespace ZitiDesktopEdge.DataStructures { } + public class MonitorConfigEvent : ActionEvent + { + public bool AutomaticUpdatesDisabled { get; set; } + } + + public class MonitorServiceStatusEvent : SvcResponse { public string Status { get; set; } public string ReleaseStream { get; set; } + public string AutomaticUpgradeDisabled { get; set; } public bool IsStopped() { return "Stopped" == this.Status; diff --git a/ZitiDesktopEdge.Client/Server/IPCServer.cs b/ZitiDesktopEdge.Client/Server/IPCServer.cs index b3b39133..d6232148 100644 --- a/ZitiDesktopEdge.Client/Server/IPCServer.cs +++ b/ZitiDesktopEdge.Client/Server/IPCServer.cs @@ -39,6 +39,9 @@ namespace ZitiDesktopEdge.Server { public delegate SvcResponse TriggerUpdateDelegate(); public TriggerUpdateDelegate TriggerUpdate { get; set; } + public delegate SvcResponse SetAutomaticUpdateDisabledDelegate(bool enabled); + public SetAutomaticUpdateDisabledDelegate SetAutomaticUpdateDisabled { get; set; } + public IPCServer() { ipcPipeName = PipeName; eventPipeName = EventPipeName; @@ -234,6 +237,9 @@ namespace ZitiDesktopEdge.Server { case "triggerupdate": r = TriggerUpdate(); break; + case "setautomaticupgradedisabled": + r = SetAutomaticUpdateDisabled(bool.TrueString.ToLower() == ("" + ae.Action).ToLower().Trim()); + break; default: r.Message = "FAILURE"; r.Code = -3; diff --git a/ZitiDesktopEdge.Client/ServiceClient/DataClient.cs b/ZitiDesktopEdge.Client/ServiceClient/DataClient.cs index 79f58ba8..b8b76a4a 100644 --- a/ZitiDesktopEdge.Client/ServiceClient/DataClient.cs +++ b/ZitiDesktopEdge.Client/ServiceClient/DataClient.cs @@ -4,14 +4,12 @@ using System.IO; using System.IO.Pipes; using System.Security.Principal; using System.Security.AccessControl; -using System.Threading; using System.Threading.Tasks; using Newtonsoft.Json; using NLog; using ZitiDesktopEdge.DataStructures; -using ZitiDesktopEdge.Server; /// /// The implementation will abstract away the setup of the communication to @@ -413,7 +411,7 @@ namespace ZitiDesktopEdge.ServiceClient { //almost certainly a problem with the pipe - recreate the pipe... //setupPipe(); //throw ioe; - Logger.Error(ioe, "Unexpected error"); + Logger.Error(ioe, "Could not perform ziti dump. Unexpected error. Is ziti running?"); } return; } diff --git a/ZitiDesktopEdge.Client/ServiceClient/MonitorClient.cs b/ZitiDesktopEdge.Client/ServiceClient/MonitorClient.cs index 51a650ca..f9535396 100644 --- a/ZitiDesktopEdge.Client/ServiceClient/MonitorClient.cs +++ b/ZitiDesktopEdge.Client/ServiceClient/MonitorClient.cs @@ -67,6 +67,11 @@ namespace ZitiDesktopEdge.ServiceClient { var instEvt = serializer.Deserialize(new JsonTextReader(new StringReader(line))); InstallationNotificationEvent(instEvt); break; + case "Config": + var cfg = serializer.Deserialize(new JsonTextReader(new StringReader(line))); + + Logger.Error("CONFIG EVENT: " + cfg.AutomaticUpdatesDisabled); + break; default: ServiceStatusEvent(evt); break; @@ -135,6 +140,7 @@ namespace ZitiDesktopEdge.ServiceClient { } return null; } + async public Task SetReleaseStreamAsync(string stream) { ActionEvent action = new ActionEvent() { Op = "SetReleaseStream", Action = stream }; try { @@ -179,5 +185,15 @@ namespace ZitiDesktopEdge.ServiceClient { } return null; } + async public Task SetAutomaticUpgradeDisabledAsync(bool enabled) { + ActionEvent action = new ActionEvent() { Op = "SetAutomaticUpgradeDisabled", Action = (enabled ? "true" : "false")}; + try { + await sendAsync(action); + return await readAsync(ipcReader); + } catch (Exception ex) { + Logger.Error(ex, "Unexpected error"); + } + return null; + } } } \ No newline at end of file diff --git a/ZitiUpdateService/UpdateService.cs b/ZitiUpdateService/UpdateService.cs index 8dc5046e..433ab82d 100644 --- a/ZitiUpdateService/UpdateService.cs +++ b/ZitiUpdateService/UpdateService.cs @@ -21,12 +21,13 @@ using Newtonsoft.Json; using System.Net; using DnsClient; using DnsClient.Protocol; -using ZitiUpdateService.Checkers.PeFile; +using ZitiUpdateService.Utils; using ZitiUpdateService.Checkers; namespace ZitiUpdateService { public partial class UpdateService : ServiceBase { private string betaStreamMarkerFile = "use-beta-stream.txt"; + private static Settings CurrentSettings = new Settings(true); public bool IsBeta { get { @@ -34,6 +35,12 @@ namespace ZitiUpdateService { } private set { } } + public bool AutomaticUpgradeDisabled { + get { + return CurrentSettings.AutomaticUpdatesDisabled; + } + private set { } + } private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); @@ -62,6 +69,10 @@ namespace ZitiUpdateService { public UpdateService() { InitializeComponent(); + + CurrentSettings.Load(); + CurrentSettings.OnConfigurationChange += CurrentSettings_OnConfigurationChange; + base.CanHandlePowerEvent = true; exeLocation = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); @@ -79,6 +90,7 @@ namespace ZitiUpdateService { svr.SetReleaseStream = SetReleaseStream; svr.DoUpdateCheck = DoUpdateCheck; svr.TriggerUpdate = TriggerUpdate; + svr.SetAutomaticUpdateDisabled = SetAutomaticUpdateDisabled; string assemblyVersionStr = Assembly.GetExecutingAssembly().GetName().Version.ToString(); //fetch from ziti? assemblyVersion = new Version(assemblyVersionStr); @@ -90,7 +102,30 @@ namespace ZitiUpdateService { } } - private SvcResponse TriggerUpdate() { + private void CurrentSettings_OnConfigurationChange(object sender, ControllerEvent e) + { + MonitorServiceStatusEvent status = new MonitorServiceStatusEvent() + { + Code = 0, + Error = "", + Message = "Configuration Changed", + Status = ServiceActions.ServiceStatus(), + ReleaseStream = IsBeta ? "beta" : "stable", + AutomaticUpgradeDisabled = AutomaticUpgradeDisabled.ToString() + }; + EventRegistry.SendEventToConsumers(status); + } + + private SvcResponse SetAutomaticUpdateDisabled(bool disabled) + { + CurrentSettings.AutomaticUpdatesDisabled = disabled; + CurrentSettings.Write(); + SvcResponse r = new SvcResponse(); + r.Message = "Success"; + return r; + } + + private SvcResponse TriggerUpdate() { SvcResponse r = new SvcResponse(); r.Message = "Initiating Update"; @@ -136,7 +171,7 @@ namespace ZitiUpdateService { private void SetLogLevel(string level) { try { Logger.Info("request to change log level received: {0}", level); - if (("" + level).ToLower() == "verbose") + if (("" + level).ToLower().Trim() == "verbose") { level = "trace"; Logger.Info("request to change log level to verbose - but using trace instead"); @@ -445,7 +480,7 @@ namespace ZitiUpdateService { int dnsProbeIntervalInSeconds = 60; bool dnsProbeStarted = false; - private void DnsProbe_Elapsed(object sender, ElapsedEventArgs e) { + private void DnsProbe_Elapsed(object sender, ElapsedEventArgs e) { if (dnsProbeStarted) return; //skip out if it's already going... dnsProbeStarted = true; Logger.Trace("dns probe started"); @@ -501,7 +536,7 @@ namespace ZitiUpdateService { } } - async private Task onEventsClientAsync(StreamWriter writer) { + async private Task onEventsClientAsync(StreamWriter writer) { Logger.Info("a new events client was connected"); //reset to release stream //initial status when connecting the event stream @@ -511,7 +546,8 @@ namespace ZitiUpdateService { Message = "Success", Type = "Status", Status = ServiceActions.ServiceStatus(), - ReleaseStream = IsBeta ? "beta" : "stable" + ReleaseStream = IsBeta ? "beta" : "stable", + AutomaticUpgradeDisabled = AutomaticUpgradeDisabled.ToString() }; await writer.WriteLineAsync(JsonConvert.SerializeObject(status)); await writer.FlushAsync(); @@ -585,7 +621,7 @@ namespace ZitiUpdateService { } if (upInt.TotalMilliseconds < 10 * 60 * 1000) - { + { Logger.Warn("provided time [{0}] is too small. Using 10 minutes.", updateTimerInterval); #if MOCKUPDATE || ALLOWFASTINTERVAL Logger.Info("MOCKUPDATE detected. Not limiting check to 10 minutes"); @@ -636,7 +672,7 @@ namespace ZitiUpdateService { static DateTime mockDate = DateTime.Now; #endif private UpdateCheck getCheck(Version v) - { + { #if MOCKUPDATE //run with MOCKUPDATE to enable debugging/mocking the update check var check = new FilesystemCheck(v, -1, mockDate, "FilesysteCheck.download.mock.txt", new Version("2.1.4")); @@ -724,15 +760,15 @@ namespace ZitiUpdateService { #if !SKIPUPDATE new SignedFileValidator(fileDestination).Verify(); try { - StopZiti(); - StopUI().Wait(); + StopZiti(); + StopUI().Wait(); - Logger.Info("Running update package: " + fileDestination); - // shell out to a new process and run the uninstall, reinstall steps which SHOULD stop this current process as well - Process.Start(fileDestination, "/passive"); - } catch (Exception ex) { - Logger.Error(ex, "Unexpected error during installation"); - } + Logger.Info("Running update package: " + fileDestination); + // shell out to a new process and run the uninstall, reinstall steps which SHOULD stop this current process as well + Process.Start(fileDestination, "/passive"); + } catch (Exception ex) { + Logger.Error(ex, "Unexpected error during installation"); + } #else Logger.Warn("SKIPUPDATE IS SET - NOT PERFORMING UPDATE"); Logger.Warn("SKIPUPDATE IS SET - NOT PERFORMING UPDATE"); @@ -910,7 +946,8 @@ namespace ZitiUpdateService { Code = 0, Error = "SERVICE DOWN", Message = "SERVICE DOWN", - Status = ServiceActions.ServiceStatus() + Status = ServiceActions.ServiceStatus(), + AutomaticUpgradeDisabled = AutomaticUpgradeDisabled.ToString() }; EventRegistry.SendEventToConsumers(status); } else { @@ -921,7 +958,8 @@ namespace ZitiUpdateService { Error = "SERVICE DOWN", Message = "SERVICE DOWN", Status = ServiceActions.ServiceStatus(), - ReleaseStream = IsBeta ? "beta" : "stable" + ReleaseStream = IsBeta ? "beta" : "stable", + AutomaticUpgradeDisabled = AutomaticUpgradeDisabled.ToString() }; EventRegistry.SendEventToConsumers(status); } @@ -966,7 +1004,7 @@ namespace ZitiUpdateService { } private bool InstallationIsCritical(DateTime publishDate) - { + { var installationReminderIntervalStr = ConfigurationManager.AppSettings.Get("InstallationCritical"); var instCritTimespan = TimeSpan.Zero; if (!TimeSpan.TryParse(installationReminderIntervalStr, out instCritTimespan)) diff --git a/ZitiUpdateService/ZitiUpdateService.csproj b/ZitiUpdateService/ZitiUpdateService.csproj index e8828d5b..fac52706 100644 --- a/ZitiUpdateService/ZitiUpdateService.csproj +++ b/ZitiUpdateService/ZitiUpdateService.csproj @@ -160,6 +160,7 @@ ProjectInstaller.cs + Component From 011cefa519d6ffafe56836b7d787c3b629cad6dc Mon Sep 17 00:00:00 2001 From: dovholuknf <46322585+dovholuknf@users.noreply.github.com> Date: Mon, 15 Aug 2022 13:00:42 -0400 Subject: [PATCH 3/6] forgot the settings.cs --- ZitiUpdateService/utils/Settings.cs | 119 ++++++++++++++++++++++++++++ 1 file changed, 119 insertions(+) create mode 100644 ZitiUpdateService/utils/Settings.cs diff --git a/ZitiUpdateService/utils/Settings.cs b/ZitiUpdateService/utils/Settings.cs new file mode 100644 index 00000000..1d95f209 --- /dev/null +++ b/ZitiUpdateService/utils/Settings.cs @@ -0,0 +1,119 @@ +using System.IO; +using Newtonsoft.Json; +using NLog; +using ZitiDesktopEdge.DataStructures; + +namespace ZitiUpdateService.Utils +{ + internal class Settings + { + private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); + private FileSystemWatcher watcher; + + [JsonIgnore] + private string Location { get; set; } + + public bool AutomaticUpdatesDisabled { get; set; } + + public event System.EventHandler OnConfigurationChange; + + internal Settings(bool doInit) + { + if (doInit) + { + init(); + } + } + + public Settings() + { + } + + private void init() + { + string folder = Path.Combine(System.Environment.GetFolderPath(System.Environment.SpecialFolder.ApplicationData), "NetFoundry", "ZitiUpdateService"); + string file = "settings.json"; + Location = Path.Combine(folder, file); + Directory.CreateDirectory(folder); + watcher = new FileSystemWatcher(folder); + watcher.Filter = file; + + watcher.NotifyFilter = NotifyFilters.Attributes + | NotifyFilters.CreationTime + | NotifyFilters.DirectoryName + | NotifyFilters.FileName + | NotifyFilters.LastAccess + | NotifyFilters.LastWrite + | NotifyFilters.Security + | NotifyFilters.Size; + watcher.Changed += OnChanged; + watcher.Deleted += OnDeleted; + watcher.Renamed += OnRenamed; + watcher.Error += OnError; + watcher.EnableRaisingEvents = true; + } + + private static JsonSerializer serializer = new JsonSerializer() { Formatting = Formatting.Indented }; + internal void Load() + { + try + { + string json = File.ReadAllText(Location); + var jsonReaderEvt = new JsonTextReader(new StringReader(json)); + Settings s = serializer.Deserialize(jsonReaderEvt); + Update(s); + } + catch + { + // do nothing + } + } + internal void Write() + { + try + { + using (StreamWriter file = File.CreateText(Location)) + { + serializer.Serialize(file, this); + } + this.OnConfigurationChange?.Invoke(null, null); + } + catch + { + // do nothing + } + } + + + private static void OnError(object sender, ErrorEventArgs e) + { + } + + private void OnRenamed(object sender, RenamedEventArgs e) + { + Logger.Info("Settings file renamed. Resetting to defaults..."); + this.Update(new Settings()); + } + + private void OnDeleted(object sender, FileSystemEventArgs e) + { + Logger.Info("Settings file deleted. Resetting to defaults..."); + this.Update(new Settings()); + } + + private void OnCreated(object sender, FileSystemEventArgs e) + { + } + + private void OnChanged(object sender, FileSystemEventArgs e) + { + Logger.Info("Settings file changed. Reloading..."); + this.Load(); + } + + private void Update(Settings source) + { + this.AutomaticUpdatesDisabled = source.AutomaticUpdatesDisabled; + } + } +} From 8aed285c2b58d41a7535c38f18543c634e2a4fdb Mon Sep 17 00:00:00 2001 From: dovholuknf <46322585+dovholuknf@users.noreply.github.com> Date: Mon, 15 Aug 2022 13:18:29 -0400 Subject: [PATCH 4/6] tweaks after review --- DesktopEdge/MainWindow.xaml.cs | 3 +-- ZitiDesktopEdge.Client/Server/IPCServer.cs | 2 +- ZitiDesktopEdge.Client/ServiceClient/MonitorClient.cs | 4 ++-- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/DesktopEdge/MainWindow.xaml.cs b/DesktopEdge/MainWindow.xaml.cs index e1d85964..8e04e49d 100644 --- a/DesktopEdge/MainWindow.xaml.cs +++ b/DesktopEdge/MainWindow.xaml.cs @@ -756,8 +756,7 @@ namespace ZitiDesktopEdge { string nextVersionStr = null; - private void MonitorClient_OnReconnectFailure(object sender, object e) - { + private void MonitorClient_OnReconnectFailure(object sender, object e) { logger.Debug("OnReconnectFailure triggered"); if (nextVersionStr == null) { // check for the current version diff --git a/ZitiDesktopEdge.Client/Server/IPCServer.cs b/ZitiDesktopEdge.Client/Server/IPCServer.cs index d6232148..3c6442b4 100644 --- a/ZitiDesktopEdge.Client/Server/IPCServer.cs +++ b/ZitiDesktopEdge.Client/Server/IPCServer.cs @@ -39,7 +39,7 @@ namespace ZitiDesktopEdge.Server { public delegate SvcResponse TriggerUpdateDelegate(); public TriggerUpdateDelegate TriggerUpdate { get; set; } - public delegate SvcResponse SetAutomaticUpdateDisabledDelegate(bool enabled); + public delegate SvcResponse SetAutomaticUpdateDisabledDelegate(bool disabled); public SetAutomaticUpdateDisabledDelegate SetAutomaticUpdateDisabled { get; set; } public IPCServer() { diff --git a/ZitiDesktopEdge.Client/ServiceClient/MonitorClient.cs b/ZitiDesktopEdge.Client/ServiceClient/MonitorClient.cs index f9535396..f9a7e368 100644 --- a/ZitiDesktopEdge.Client/ServiceClient/MonitorClient.cs +++ b/ZitiDesktopEdge.Client/ServiceClient/MonitorClient.cs @@ -185,8 +185,8 @@ namespace ZitiDesktopEdge.ServiceClient { } return null; } - async public Task SetAutomaticUpgradeDisabledAsync(bool enabled) { - ActionEvent action = new ActionEvent() { Op = "SetAutomaticUpgradeDisabled", Action = (enabled ? "true" : "false")}; + async public Task SetAutomaticUpgradeDisabledAsync(bool disabled) { + ActionEvent action = new ActionEvent() { Op = "SetAutomaticUpgradeDisabled", Action = (disabled ? "true" : "false")}; try { await sendAsync(action); return await readAsync(ipcReader); From 33ae8f05a5fbe1b76ee2957ee03beb950f91d98a Mon Sep 17 00:00:00 2001 From: dovholuknf <46322585+dovholuknf@users.noreply.github.com> Date: Mon, 15 Aug 2022 13:21:21 -0400 Subject: [PATCH 5/6] more style commits --- DesktopEdge/Views/Screens/MainMenu.xaml.cs | 8 +++----- ZitiDesktopEdge.Client/ServiceClient/MonitorClient.cs | 3 +-- ZitiUpdateService/UpdateService.cs | 6 ++---- 3 files changed, 6 insertions(+), 11 deletions(-) diff --git a/DesktopEdge/Views/Screens/MainMenu.xaml.cs b/DesktopEdge/Views/Screens/MainMenu.xaml.cs index 3520d09c..083859e4 100644 --- a/DesktopEdge/Views/Screens/MainMenu.xaml.cs +++ b/DesktopEdge/Views/Screens/MainMenu.xaml.cs @@ -170,7 +170,7 @@ namespace ZitiDesktopEdge { bool disableAutomaticUpgrades = false; if(sender == AutomaticUpgradesItemOff) { disableAutomaticUpgrades = true; - } + } var monitorClient = (MonitorClient)Application.Current.Properties["MonitorClient"]; SvcResponse r = await monitorClient.SetAutomaticUpgradeDisabledAsync(disableAutomaticUpgrades); @@ -266,8 +266,7 @@ namespace ZitiDesktopEdge { MenuTitle.Content = "Set Release Stream"; ReleaseStreamItems.Visibility = allowReleaseSelect ? Visibility.Visible : Visibility.Collapsed; BackArrow.Visibility = Visibility.Visible; - } else if (menuState == "ConfigureAutomaticUpgrades") - { + } else if (menuState == "ConfigureAutomaticUpgrades") { SetAutomaticUpgradesState(automaticUpgradeDisabled); MenuTitle.Content = "Automatic Upgrades"; AutomaticUpgradesItems.Visibility = Visibility.Visible; @@ -430,8 +429,7 @@ namespace ZitiDesktopEdge { this.ReleaseStreamItemBeta.IsSelected = isBeta; this.ReleaseStreamItemStable.IsSelected = !isBeta; } - private void SetAutomaticUpgradesState(bool yesNo) - { + private void SetAutomaticUpgradesState(bool yesNo) { this.AutomaticUpgradesItemOn.IsSelected = !yesNo; this.AutomaticUpgradesItemOff.IsSelected = yesNo; } diff --git a/ZitiDesktopEdge.Client/ServiceClient/MonitorClient.cs b/ZitiDesktopEdge.Client/ServiceClient/MonitorClient.cs index f9a7e368..7e5ff171 100644 --- a/ZitiDesktopEdge.Client/ServiceClient/MonitorClient.cs +++ b/ZitiDesktopEdge.Client/ServiceClient/MonitorClient.cs @@ -69,8 +69,7 @@ namespace ZitiDesktopEdge.ServiceClient { break; case "Config": var cfg = serializer.Deserialize(new JsonTextReader(new StringReader(line))); - - Logger.Error("CONFIG EVENT: " + cfg.AutomaticUpdatesDisabled); + Logger.Debug("CONFIG EVENT: " + cfg.AutomaticUpdatesDisabled); break; default: ServiceStatusEvent(evt); diff --git a/ZitiUpdateService/UpdateService.cs b/ZitiUpdateService/UpdateService.cs index 433ab82d..9cf00a84 100644 --- a/ZitiUpdateService/UpdateService.cs +++ b/ZitiUpdateService/UpdateService.cs @@ -104,8 +104,7 @@ namespace ZitiUpdateService { private void CurrentSettings_OnConfigurationChange(object sender, ControllerEvent e) { - MonitorServiceStatusEvent status = new MonitorServiceStatusEvent() - { + MonitorServiceStatusEvent status = new MonitorServiceStatusEvent() { Code = 0, Error = "", Message = "Configuration Changed", @@ -116,8 +115,7 @@ namespace ZitiUpdateService { EventRegistry.SendEventToConsumers(status); } - private SvcResponse SetAutomaticUpdateDisabled(bool disabled) - { + private SvcResponse SetAutomaticUpdateDisabled(bool disabled) { CurrentSettings.AutomaticUpdatesDisabled = disabled; CurrentSettings.Write(); SvcResponse r = new SvcResponse(); From a63b9ce8a3b0d3c4b94922929faba993708e4643 Mon Sep 17 00:00:00 2001 From: Jeremy Tellier Date: Mon, 15 Aug 2022 13:24:35 -0400 Subject: [PATCH 6/6] Auto Upgrade UI --- DesktopEdge/Assets/Images/processing.png | Bin 0 -> 31346 bytes DesktopEdge/Views/Screens/MainMenu.xaml.cs | 9 ++++----- DesktopEdge/ZitiDesktopEdge.csproj | 3 +++ ZitiUpdateService/Properties/app.manifest | 2 +- ZitiUpdateService/ZitiUpdateService.csproj | 2 +- 5 files changed, 9 insertions(+), 7 deletions(-) create mode 100644 DesktopEdge/Assets/Images/processing.png diff --git a/DesktopEdge/Assets/Images/processing.png b/DesktopEdge/Assets/Images/processing.png new file mode 100644 index 0000000000000000000000000000000000000000..e7fcfe4f41060a9a87963c61dd939b835c80a6b8 GIT binary patch literal 31346 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

MaAoW}PpSz`RaYw(rOsX1eOe$2E4uhmcq zq{@r=S&%O^f`(`QG_bqt$%M*bMDCq+@VsnXe^Urr5IAV*cm6=(pNS3bRcX-jj8u_$ z)=O-sNnyfjK!D-*`0VLxfGz)Zi?ta*7R|4#ajHDHNFL^f_~Mw?dkdfCl;Hyo=HH*V zhE(;41nDA5BVhp^M=< zK0YUNrla)0=a4q&p4GPvz)kFE3USYy-03UUr@sFyiG> zBe!WT&}fJ|d;FXd=-U#R8R94NDtrJsz?HfZrohYuuz5oWy_BcDa#y(3x-jBs>-!6| zC%B%bbATzbA@Bk4f<^dAUX;?>E8yIV@AotE*e*yYuA@A^2xz}pV1!6S$&X}Mp^H+K z4jXDw-+!8MD_1viYb`)`Pj4Vtn<-9+P?$Ll^b%Epo+CMD!9BaLFB2VRp%f`6`#}NFS2~CuRTNEvB=i~;hdLv~-csOj?gI0{_&ark6 z9Okf!xt)W^2Sa*965n?~)|g-m#viMLALRRmA9m3Az;0j8dKgeCqO~_w)Hm@)YoNNc zu!HQaGS8&|<(gZR0Z%+ZmHyrhupc8dlaCRFv0|9#PcfhAq2&Gs`B$M4Hxd`N;HVTG zTKeYYG<+FG2>vwz;btNn>=b?I7=!P?T`RmT)J!V!CDp~AEMiV?y3bl5UPlOezFu>4bQ2;tY0u+PswE{}_`l@m6R zp(#MQKsUvgGoqYNbqQs4IFWomE??U9xhILUp%wBwMOq;eOzs%`7h#36nt^CK8`@1N5q*o=xjp?DF=-5&oxv%_p zg{N-b-AZ?c$8kmB!X0tZVjZ>vY$g&%NZ+kKWfQWqmE5Fncu1;@YsXfz-1n`D>f|Kz z#HJqh;>9^MVwa6)e^?_VVXmTD*oPdzocafth)-BpN$NghclgmGLRxpa5sz5%(yWB- zi6LEuuXBzgdNZa8_<(OV+LpHpjU`3dp$FMoc#Vo|irg5rtC$j)%bb)r^{URZC>KFc znGNrl;*~|Kk)^4?Zpd8Om3=GtETIEqER2wMmqOu-?G908jV9p??atdDc!qXEbP+EW zqzOOD7u+wQU>4_X&^UqPBWL%-xK=#7_iamzi<@tD@#qH8H4Q}9ZBUp~@qn?w0_L-j zk^&4CL3Q29R9k4y=_QC?!Hnu;ZytXM!45CxNnec8F`IjR-4v@E}&a%(0@7YV@wuTFxlY43W6Q(vV%&Oa_c0k4H*|108F&n zTrOM)OR|YL#tQ^LOm}9kqY}HNz`bn#ib>46h<eA#+k$Dg*Y$irPs$8|S!~qFK z{lPJ_Dem8`lim?`R2**;g3iM*coD$)=L?TZg4+YG+KQSp3VyjAH|>;7R;P-0idAOg zo*i~ZsS%e*s+PL-8<7$lym#}LhsaxuqCHO*sp~u{5fDeQ)h0Mb;-}h;$=+I?;Up5)XB%t_e>TYQw0r1g?XPnK$CJiB=$Oec$N%5 zN>|6jR+;_Gf9rElq8};VFJCHP9;hHv1jT=1PoPRK(lRuG5V~rtcZ8j>1nK&d$5NuY zbM)B-A)vyn&CjF75hF{F^eZ&Li5BeePjDJ9eOM}d1M*8Nh8?LXA~;s#Ks8*V9+R#< zEv$=Xu4+|ZJBGCv|Bb}}-}2Um?8hxL?2zw|7VOOr-1PfMq@DLIr_^%t;u7JbKzrB? z{^$OY&m7NUyPuW*u=+GlGxV`+(3zBZ)eeMA1RZRn9RBL2KzGofeW7h_QR3BMq*Qi# zLxm>=t#-3enW`ic3auWsM25WluE(AS3PGI{e8!N#l*$wswI>=T!vEeg5iEvlDNfl85RDW?F*03YpS)sR zd@>1%f4(eup^EcN_%}_B=!wr}$IBivRh*uWRHx<%zZg)M8a{f94aIjjiR1NDO9d<3paHl7e{`)!A9ucGKmr8eR z+dQk}=&$vO1d@m@hiB<0D#Bgh-3&}JCewlE?{Us^`MH*L+WngF=7KN+oD&NDl`JW4 z9;Hd=!7cAX6*@UoI$`wXXT@0;`nq2fungTa*^4E?&q1M#ZLDJ|Nmy8dt7&p@hdV)oF6hjU3qR7nLiP{i!VcZEc02&&^NO>tH10DjaQ! z7m>%=;>s^V%(sQsJ)tvyLbM=%r$~wsU09ZCT+Qbpy4SSah zrMD)RHmBoivLeSxoAm1V8h2`fHy$%k;$3m|2OpA6?-`dpe4DmaR1wj0FUl=_Rud9J zig3dz4_}%!rhTXa^_02pj_1#^FtzHSdip7qkD|cXoajQ zh(^akeBySFQmYynTGD7HY#dVl9!R;RAQrvo7VGG0j$NsuC1{Lt} zU6kL9=on{sC{;DS)8u-@8k2W*1&--6v8{-?!dTJ|Mi0ljEtZa;>4j|Tdtj{EdpV!*UZ(j3=*pUHD z>(a%#8ah)F5bUp$rV;e@Os&giQE2&gVi)(E`|li(0m^M!uI*vpFr$h>a13N3hp+eq z>wjf&>yo@xBS$mfNqFjXjM(qpraI_xmBpU(=7bKj17fN}F0(lbe}*3}ShKaFc#TJx zNH1SoH-{DoHvRceoyhgQ8@(2_48DtbK*xOFrEfnE>$^FYAifDY&KzPXZCf+s1bpuO z*dpiSa28||t-o7O3`Dek@kpZgSH;?{HYVQ!Li)ocv#0vfJ@u(e=KR4YONwDt)1k?QU7LwIGVd!0`0uUgK5p1PZ92Mm%b?!pILvw(~&-Kwbc zsR|kAqo>hcyA$8BEF%%ly_>iq&fQtzQ>F<@dS6u)<_aY0*ot8dPqe1v+0%6DypTQ* z;Zk>f1lc^{t!J)b1aXp6Opna1FU;fSPIhwbbc9wZc9V`jNC|YtZo^E~sk=5hCU1E+ zzZ|e3rOBEgb_{8Wc887f_#1hUG7&J>2fzs2kXY}Q+QQ~!@|r9JzTF(XDMofXIz0AU zBETwiv%wLkxxWw52|66u-kIN#(R}Lg-dI!}Wifb|U_Ge*U4~+#=*QED{D^bFDfIw_ zBL-!M5_dkd_tEIRe87kkZT!U$Q`fDF0h(mMudZQFtx1NSVs>ZXcEs9aM{u5d*ah*(;m;*?!t(3 zzRLJhrr6ip(;lP=vt0Hlf-Dq#2mC6|ip5YqN1I zAP$(-x6^=Fv92wsnp1BwBTl(v>qEaG{NRGncFuFS`vQKD!Njm5V;NR6)&Yn2|8J%T z^e<17&$3j?`A~f7C%sajl^el(&jD(fUa#2-F*{FqJr0^RVGxv4d?0 zS-4Bp``2%z67*#qi1~Dn4bm)hFjhcrLXDDCwH%W6(y0m9 z82FcOPEn1hRaPc^+x_E3!vrW4+fsPum_t976QEG?`p(-D-M<~T120Kx<3W3YP(c(Z zT+o$pj)t$#7H)%bG^u+MYc~~<8aCM`#TZU4>@UwUKi(1DK2|+d6-V2dL-a?K`Iw=} z&MRqCd)rT=jea0V&oH#G&kVjO57HiSiNfX_Iu}Mx56?|-&NlDQK;e9XOjIfXJ)S#7 z0+r;lu;rl^hvxUwKt9AkwC?M7lIKLB-mV7aa16S09NSQBZ?ix918M`XwB{Rh>T3T#z~aXDVE# z3E|1YwDfTy44tfK;E9$;2qTWCJPL^70D9G!XsyG)peXSED|2TQs9;(}S?#j*GsClV zWP@eb?}k-C5@{Yg${Z2%s_BG#IPfYwZ*2#{0bQVtwddLtlQ9(`L>QOe=8)IHzD(km zYI;MCAYxdykD;7T1meXlZpz~w$^a@Pfb1my+^Lv14SEjnitRbGp?j%Yh#JX7f2!Z?Q^9_- zsbl8Ec8DpaY4}9=Zd^VwUxo~QfQs@M*&vNLWRZH|7KmJMaw5!+1vvG{5$yAAO8f$i znH(z^A<)T(Ju;W-D9{HGM-g1VIB8L=Dq4Q``_*%#Cz3Y}E+?@aMPmB~6|5dIgfTo+ zv<%L#FmL+TS|_8r@%u02KyKoVpTzk9H*DKBaSy?@6#O$K@tNa$1J+h8AS0%=Sbzun zj)E#)2~AqRo%ZwVJ&>tZ^LH8Xb?heB7WCWApA68&k+>o(7`@|mJDZ_S|fG(ntGF{oGRgZ0*#sFg9r+dsQL*WE#CJpN zoX8q5es@B{?7go-DF#DUS|;aLau5mqV#0--U`tAyK>lK?au&Dl2jyucak9*jFJYB% zNjQtnli8TkCy6W=MJEVpbt1gozinsQ?lWoZFR%6)IN`tE2YSsUY8H5u^(@e}hNxr4g3-kt%Hp-VyVP;YXwGNfT$ASWFH-T(an|V<8?@vhx;oX!^~Dfzp4>e5_WrWw#<~#?>pQ#ZkE@J9)m5} zT%5mV>mHU*3rj&Dc zbaoL3qb$Rlc);}8~GGDs(=s=S9rxuXx?f3y=$5u>_5o- z3)zeoDX!y1nNvC1^q;aZrUy?**JXoAzuo%%c3?iSu*sIDTEtb&Lx=f{*_9TGtJpJE zn*eR@nALCkF5#F{pW9@FAXi1F?=Y#Rf3KcN-CFCueEX^P)<+Y_mWJSBR-1^G%XYO4 zX%9WWE0+}$Yuu?2cHW_kfNq|80NE6@VcU%*ONDMyCpf2$9SH<^O;c#~+EYPS<5V!} zKRoZ*ukbN4l#8f3?|WSUZ zD!z-8ix_Uw6i|G-$11IFQg_UIn~?ZV`N55OX*iRALKMcf1Qrh)K*{9>hFZg=NsW&#%x9d%)#(juaf zss<83TWno*fKT8blINOpLdUb5)w!>aUm_>foyCiL&ZGx_hOq2qsy5n7ef#!{!U%u4 z*Jio8RE}P%eLsxo>wO|BlP2)z^4&G>vz0nqqEml~bNyBsm<$fE z&-0oRX!uhHh&^gZH9Q6uqP3N`P|~FYg7{U8w+LnjS-YIZYnzzhYfD$XHV za`}5@9^#E_s18LC3ZufMP?$$Q?^cy(&A5^oYWU~kZZKR@L54a+#!BMUC={1#p(^cl~}3cffYi_ zCW8#n1LW_xW5=h`vPm3H_8h%a8;Yf{c2FpDTeX58QfOw9Q!Kw|wM#S)Z=TAJdcjHQ zOY2aIILPwwf#Hoy)gVvoed)*$0@^ROZ>5FAAX6I)^V8uQA&!84O{45o5F=s<5l$GEnE+>sxAL=`!B^@aV_zBhN5dD7D5F ztDfsuB)K!YHn@N$*W2J*IOUV3+XjkRn&E^zTx+e*`arK@{IR&E9?TpP4k^Puovn4IlwVAoqBOveu6O?H<<=0 z-P4F>IZmY93neUxoo?#Zp)({m*NFYUN>xn z-hZg_nb5hQw?wJ%5#r&K?foxa(hSPpSL!0f0{q|tY!gDnw7-yn=wB6|z6?|KoRAaV zyVz>BP{KlpvlBvexF7FjnU!Su7v7OV`um!Xk#aN{E}Fg_ys@fJNI+-I00ri@Sp8*r zVFh!YWFu*R)|A3WBc5mTh06Rzr$YOR{0YOHevB@=M~;@iU>9xc)-EON7fcut&Dp!{}igCuJ!I?`~g{~JR2VQCt0!LK1kkaEFRbDI(4(~lyg8>44fuf^h?a7&aaxq4uqnfBjo-dA4)O1arHz`!Q@U{RmX&rL;O6o1s+v1$-pz`^D48j4>?74~c; zgSB!vKg={+a2}^2y^_$8^dFlt)jJsQ^3xo-*OLSCdv^;WINoW&j)3#qg`zbo^ z(4gnAml8Of!Z&I?buzQQ;`0D`&deD+D~m-{P7E-^a)by`A=s9%(BIDCfOFR9Ay%LfQYF_B_&7NM~L*!Gjx zEAjv$AVa=haPUj2cvKPgt65UwI;5xwiMaE2Uq~zy;?wTqkj4i;EPe87-s-17o0(un zkS~uJR)FnAd^;hxxnO+*XUrJdU^r0ClRH>^8)}uN;P4Aa^0}(&Yd`q|d6#2w33So> z;EJ@7&}CBiEh+%}DJ1lxHU0-(Bt$7-At z7R>Vm+zxnRn1HC_x9ZQ$Io$XmB~osED?XhPR`2k=`ydhfz8}$_L*(N+VlbdKE)(bq z_&jkHr{gA77r}#mnU$Hkyq>dnjIc5Nq063T9+BeJbkV|Xb?<)vQ~73>{COJ3q?-Bd zcwRTh|E%;Vf!PYuGZYRN*8#_9Vd~CWhUdn)c4C@ZxlCgZ_>`(Hr{uoh7=O@?5aorc zcJ=^c^S;L>y(lN$45(+a&n$6NX@XRr8u_stc(H5sNIz`F7&{guvU!2Bp^N2FXEAe6 zN5WQ0@dNUpHjX1GR*i6AZ#MsHI%l?>!x2H_V7fG(J+O2+7Dg)BWNZ0X0xRN;Zw`&W zMQOuVRgC6RKCiF%2=q^8;KHa;-k*WUp<1oO$WLK3C0nN>2(MA3(U0x=fKJ!f9>}Cw zTuPCUlnh0$OsK9TA3>FN!j0Gy+kjHgbHmDWS4NQlav+n`*C5b=Cs8Pow`FENFO@En zYSDzKA#*${qfqTJwz?60Hh-u*U~zIbhjsJU3p2n-tZPXBj^UI8SW&`!H1BN_G+BMH zP&v%Z4f-LpGMi%L>Q+*?LLpt4G9#1h2ePD-YRqw4Br3y&1>m{H3)iQk58)>`_LMjd zujWtISKGxLf2}`~*=~Bgv$>a!TV6g=^_HBcVk=ouzG-<8KndhS7qjQ)&6hvR;ZN!T zL2i!RxO#7(lKAmAw2{yLGp`JapIYq_&Vu>iAC7_fgzI;D*PgNJRpj~X7wAoYlx50F zzUr*{nUDXp_`9LfPi5{xkG>#d_ewen<@^a5d~v7v20(qy5B!-Q;86xp!GbZzhf#&| zN?y0=jGhPb(`1$MOon0Bn_LUkyXXIk`SSle1XmNwrl6sWInCO*rd_Q!&-I| zH^=JIhg<--;@iW9C0tdXwwC97t#D&HspS%YWHv=&*6CfeUhxZV;p;RZto!$t#_LO6Qf9?vBsl^8RY3}GweWd6m-hD>w$5DuSV09 zn;|IWCvFvK=R*u2X})?P#JB+tm(Rc}pik_Cw|$R=hC>RAD*2lq(5dHPOEdYz^gGM{ z-u0co=s`uea<%5R0HvyfQ<|)vWzfMVS|f~kXU3=Wk+=#lEvhzj4c>Y~G_d8r^PjDt z8X9zW*I(ZHzGmW`J5Xqgx7RKngR9Dx*}4 zLFuzl-tqB_^-8vvT*L`|6m#CctrLnWZF9b(*tQjMlY_otPP%@ve?bNUD)1$$u?|rO zVe(ihrQ>=E;&KR;aN_G5H{joU1+~6f(6C2w|6p{_wE)#YwL1qHb;upFzS;h9ENl?< zaj?$%-*11g4)x$d&`ysOh*HlUJpO0gfD#36_uDq#L`kB-YIdZzMb|jaNLqrcz=@Cj zBZZnVP>7X1#oQ2}ZfdZieC7?-dBqjl)cz}Go@o^Vw1W;v{o3!pw6njhWZ1(r@VF&}|3uy{&_1YF{phRF?Y7;jqRAODpy$0Qk z$@5n&$Qs?ZwWM}#db)h>Uy{XmY_$7LTl>+iYUiIjY!Mqt_D3({294)!t zWQ|M3@^8jz5%=G8d=GN$yt&s*dDo?)i_BhuKE?v77Ixd%#|S?7T+MCZD9bV(Xt>}x z|3PjY20Z;iW*(5uxfx-BhVvm>CPw$}rKtzdN~#LBx{YjkVF&dq%X$(}pwBWeC=-vO z8oB1NB%G{f+Yhi6OuwuEUGWUW-^X7yKQ?Ya20Vg0T>Ht+@yNu0tM`MQ;SYU|kMpfs zShKlL?7)Zbiz@Gdua0z4FntDcw&7DS)iU97cO3SvlKpDL3fAJUCxu>sY)3Mq8n08T zcio2xJAA0-)JWCAz(~zVBMZlMd;bH<8(mb{mi**3IE4?eqK-+?YHn-Nt=z9*QH>ca zMdpi19O_haLDRtK1gt8TwxUW3qd3N$ZyFfQNBw8VW7%px~J zj4#bcHNNOQo=ts?54UsI;g^X|M@1;wz)&ktdvy@#aeg*f(^x)Ee@rDi0+3Bj zC6)0q&>%Ewin$!THg`v!mt6Smz%@xP;x{xUL4?H)*fk&nf8<1`#trC?N$<;|jS=cm z=TUk|$Afj_xTfGk&Z}ydgSh<}x*&S0xwsz-QH{WBe)zh&D3c4;lTxXJK{dEn*ALav zo51n{4(=b%C(abAks2}Qt$)vSQsfY|er0*5G5qe$%(egV0x z&q6I1=@w9B-zR*^gD|9<&|y><1~%{#2Sm@lEqqSXCf^bDLDJdPgBhs^Z0j__e2o`1 zwe4I+SswJKPt(lGo{m8fEmFlt zk%$L%zH%(w0JmUD?yXZ>suUZZk7e$J7-rS026W53 z+V&PzVCPkXVv{&lxm!P?MzR|ZtfhEy#xQ2HbkB(86R1y6bm zew^PPTSB|Xyd|CYZZio4nZ7<)0`#L2u-A9oLPv$Q?Izh!Q4-Mb31YIW*Hr58TJbxEXtlJ^TXXve!*5)&>N>KFtjCuHkiv$uh%L+1e# zx$7I|`Q1b1vgzbFZgWa-B+vZ2>0z9KaNB=k!14{X2?MS@k6A!Vtjl{!hKk0g#y-^N zu`&It=I}Nz;G2CxgeJHdbo-a3S(#^}wh_XJackI}vupvK9#vN4-b5ta|B zM#AM43(~+Q*98I?nZ8}Mc;|}``%GHeG4x7Cf8LP~zUE1MlCanA;#$oJ7`T=@(nD$J zAmsL=<(oM0Ia}AX3e)n>wbH+c)k~1DLR)D|F?vm4gdg{J&T}*>TU8sFYNP^ihT^jM ztDeeZxZle%A@mh5=w!69+t`cxT&4;4kncyJC9b8qO)fE4+9x)Q3?)RiXyb4rjM`wf)lx%7=w_47PAmXa_SbViEy<}ZWR>IiBcDPn)s z(bj)z1hswbAC)_!aor=1c1J;#U_ z5f~8d>7;wrNR;{&P z(DAN#gjSib9}kjeDP-9|X& zK8&N^de2W4DTx(;8CxQVmwYH0nO~lG$ncc~QW&ThK9w*K4-&O}#!<_i*bwHfl-P6sa3DwuCMYq4Ng1_z85Yq%EYS`P*8SAWW$58=(74}P za{GqYjRd$2@AnXb{^)A(N03|MBll$+KUB>o@&XPxDdHU@wv?t1m0Fd1$hb`G-C;wq zC-!y1L-Wth&}UvKW|?cf&>F78mcQPe=vsiShtg71WmwMWRYTXf=fPH-Ge?0xxxXdX z6bzcz)7hEbgv|Jh+f(|&BOTLEp4HHJ$s0(8;n(^-EJwc@=P4YXaEv2|;A-+r;9F-> zJuJOsx7eYUIRKoGfhrJ`cB@X|`e{eW(wGr>nN4b)0XuZp(2cvWN}RpPE{(4GXw=@q zYDIHWHtG$Oswb~9+lXU)F2kK4xbYvH*u5@MkmA0n$K9R&pBa;vWA#M}-8m1R3Jx>Q z7Q6S5p`SKv3xXTkuGp_$gDYGb8K+3>nOI=ufLr^3^&@)Oq4n^ z+^K?8*x&_kJ|Mt+ru?*oX!T<5Djx`5ccVmV`1(IlH%9@@Y=B3?-^gig8fD75DJ&R_ zC=+QVhT`LT45^!I(m6qXvgNUTp%i@^fWHTxc`4E08D1-;od3H-=k3|8<9(0LM6~t4 zp-^?_T@U5-mmv7GmtlA1%z4#**oswcKvWGTY`!Rho(;zVa)VYMD%R+?+)&4sV`$yW z)scO>GjoFJd?ncWdX(xMA zfZAw*JLSVl*ClZCL2Dol6o56Kf!GI^;qCAu;t)!G!Y+TY*EVnmkIK|bHnV3AT?E&8 zSUOquxAq#I@~AJ|9r&sNyQ{5hJE)wXalf7YRdR^Z=~%+v98Y8j?KK=hvfC|EuaoqfrW2v<^gSBkTYUXStCVUuJ(TSF%T6m5N zjr#nC<<%F@w4v1kbff+;vjle1mWDRDuitfN)u(X-$IE1@dDG(^WnS4Fjp=Th#YB1E_mtP#@ zy5is+pRuo8&=T%8pHd*jcqZDqA+hD~{(1gDr%udM))4s5o5HD|n*ryYdZ@r_4?y%3 zbEf2D(6Xp(gk7KTCQ}DF2uY6UrmXnJ?mQU8bak^}Cr7OIGZVk97t6w2D(|I zFeIo>D@tQNzGSF7g`7g7sOO&YGj4B&YTbJE{`sZY$;FRoEy<{OP29xz!Wl;v(`B=8 z%+|3(cF&8=uExN@S9$bHh1W%=9;qGhJ}bC$AnuJp3pPPxt$IUSv?3xQVQQY@`}d0x z$M*DD)P}1nzX7%O5&6+FC5L)*hg$-_q;G3Z`uuyMX77}NJ)o)~FTl|Eo(i$y5qp3N zI@7@a;I)*4s+(~GAk)6PawU56Rz3flS|R$i&fPVL$X<3*4D2e7`Xm{G{#F0!rcd<%)38w#B}{19DQZ&QvWVzME~Nt(BG(gz@cz;^`Sb%2MnPfUSNjCAEu24 z!vV9B$SQ@$I48( ztxfCEmzPNTQl(=~&{B^unUsh*o)LCv-@Wi8{$+UWs8SY=YrNadKa*_gK*-YbMU)FA zk!}5d@toA|$|vL6a@MS5+9lng);&`7>x!qahL4n@!!w`tAV6`5HyV5Aedlo_)QI=s z-TnA?{CZYQHK<<+VpK)+E4?vW*3EE&3j~i@H&7ZCLztxH-{YDVQC(z7CJb?N6Gu_o z8F%UD+@cE!d*|giI=d%{L2ZOJ8%j5K(O$VVNAmU1>!h(6$Yw80;a~3zRhy z5JNf-#LJM~!zKALm?|VVhwD%Gjd*b<-8&;!nl*J_|B((E-z?g5uqL~1t8Zg1nfFrP z?A~`2R-k98*p&N&eL}`0N%}thvsd{QD>c#Q)1x(z@P~IP4q#ARh%q+kLH6aC`hcB> z)NnAW4a`6g+NsQhgw$2rRcE@hQ}Wo$o2z^-qIwAJT~cAIpg?SV*dkgJ^-C3rTqfJm z&36G0Q_geow_}`~!?a? zu1ic#2^y9J!fqflxX%Ts*1pkQ5k3ptpiO59!r_%VHh2CD?$T!!ETY2+2X<>LEkYDT z8atljAb#RrLqClph6bG&buYbwC-$Ki!#rak*7uSJd2y-D_#Q4nbxYET0|pNbP!+Z< zj1Vw`X8o}=2vKAOJkx4NrD{4CpS>O0pi>sftPWFUPyP!@A4o@UgaSG?7}|D7fnkTz zUwFe&A6G_OSPmYoTF_{S^Iw!MA?Iswe&^bR3Ly#zk=S=mrs$@~y@i<h z-H?WHoLATt2|Yf}W_MJ7HM%sj^QfC+1atMpFkb*=K^s5~w&YZ~{Y%u5tj=!wf&|Uj z6u%L3jF)^hJ`D4Ey77xl_P;~XXu^)6?o6Z4{5ZUxZui$x=e#u%v@c3}S0qoFOK6Ww z(UXm10?CdVb7hD3sX>y_gdHvS%2nA^Jyp{$$>VI`p zAIO$eO5r4$Ab1ExA^u?rRYxf8*QZzI8AfSGT4)BiwlFSFOF+Vd^g$A>(OHm0s#bwJ zV!nUjq)ZlHqJ`t#{VkJNnTdg^eJCiR12YSq2pfb1A{{G|6&_O_9EJ9i@e z_S$G|)`c+sZ&`tA+1P?XS=)>%{J-E|KqM*aUTxyOH(3LnY@nfwb^E03C7Wt!0Z;5lj=9?tvJdI`B&rJ57b1KeR*T8nWHmz*2G*4n-8QFtW$$(U> zWNf%F1vcF8ms`&}^nWc?og&_0CcUHmMU6ei_wSx5KHDTnKr=w^z_MM=9%W!bAw%2v z(za1~8z`dBG*x}vZc)-4EPy2wY!Da{_v*ri^I<>YlgM#l1XjCQ++FX$mvDU)+2pFu zCz+CQQMDCLjy@qI%b^u%2gc;{AHUxWo*ypfdqzLt2-^L^e{cmvMaM;oS5}-gY}=%S zOjrIM=|(}Cp!vXJ{2}dZ@(`sZFst&SE=yb%%1jq3*!8|G{=wahhyJTW0Bl5aMouR5 zW82wMk{&k?VdLrfLrj6lyC;jkG-B_5o$ML=Vg}L%##+cRA)o0No2&^OnUV;hfV@54 zz}?91G)Qdr*ljM%Et$K|43zLAxJ1cCxl;Ck=#073NBOCWukuQ0yX^Ucs#m!unOr-5 zhhAVM>S^`g1DV7&-s)KoH{mZ4pg1m&ET+R$IN$x-?VS1F)Euhi+u_>dYwcWb31(*%N!EhUqQ zs+1w6CC_rmfODL@FY|Vhjw2vZ&hPIKunZMkYT%}(suuV?WA0EvJFvfq2n=(T(E9Zq z^kgs6a#7a5(uhK+OPsJ7HBhlYK_=}^SJfsaACntLo>W&8JRPH@TMjZgA>XxeQa0Fa ztopJz9*~&YcP`GX|6+V>un~YQ#Pxy8rr$P1yX)G(636KyF-;dPyHh|hqb+4lv)r{J zL~;BWaB8?nt(&U=C=jewaSP+wy?zLHuCfrWCy(ze#Iw!6-4s1LV(yCAv`)m@PkOcE z^3r^#Xo-Q*<0P?${29o5R0HX%e{VgQI&u!d={{Eol9^2!xMN6J)Jz$6msuc2iZ;|y zdzvuJ8z&Z+=XoscPNQs$IJ#js%5T~-&YNb+f#9FrK46SEIQoEyz-*QW_hWVU^t-LB zjrR2E<0N&Bvp_RECw@!n=TD`9UC(82?w^V8MuV|Yjo8$$OT2d-m=BmSo@+x~t%x`= z>o-&;Wcypd<0>{VGcOS41WJe{R=V>fc<$>ND>l|%YT(F#@8*c)VWN$knnNLe~HTh5%g_j1@a-S-ru5jW99 z0CdUYoOvr>DCBHMYl*G@gr6WQ<~n>i(Vjfu*!rFl%M}ktZm`9oXsEFD7qW)rO}|fJ z&ck^0=&zXoiYCy{Vx-?OsevMsgY|Brk>05RV$bV|x9O)Lsvb?zS$rV`#-M1r=#?7M zPu#|3Le6y^2;_Z&Y+|R|Sxe?lb#OTY{tW$mwkO zicDCph?uyI)KgN6VewtkSZ)01)r0de6}3Eg-ddqfZ|$B1!<;m!`-3qhq^icF#2J*>`Myjjb2qZJys5ekrMb&-1FtG zrY|DAC-$Lf-P2MZDMTjE#4wCLs3W*nJ{1=+n!+oA+w1f}@L&8;h=shHt&5f6THrjw zU;V>xV$9@9NVNdr3}vJ=*UadERzABeoh)$GfVHLhnxIBxsKsMV?iTj@6k==kuuP~2 zH`7_MRUuPwZ+HT!{)3DABq-}zLjD}`CXwh#sQlHj!;8<lEG&gW86tg$!x^; z7xU03<8I^uAMAZ?LMI2zwYw5Iv?u{@hlUK29cf1Lw1esr-4jzy|EBo(OrK<@{5e4z z_?7c_V`e1)VDPlB(6qZAv4ev~Cm$=!XoS&B+uOo=>0KGm5Bsk8RE`V);kYY>5C z0$w_7tL^(J(N>?O7rPNJc=G;dLVK$4Zu~Js{sfgu{kE)VbTq~C)%du*sky93-;N4% zZW|Ylvdjf8w2F_=O#Y`xy%@ndTZM}vu3ohZzPZxH$7bTOAd7y`V}IrRLGKj2 zPTCSV3{@G0*3bm4Mmciv5eK04&MFt94}eJURDNI|sw2m0MSg)7$K9-N018DE-K%K; z6=W#;DZd<$D=950Mfb_Tk5bQd1cRWhB{T`|nfCtDo^}M+{Os&xA^K>n-w_;xSAGGV z4gDZWDp~uTp83~5I{3L*vZvXnmXh%<9^IzOF`d}y&9JHR_xePjc^k5zOR2OUCV+rw zBFyi0FDkm@d@RZ(Y#Qx7^ZZGjju&Ln z8-`^Nris7!LGBr;4IDn?$_V>Tp3%l&s8`F3o7ypEFV z08nqLhhq2_0LPcOaEo5#X&I-QfnOwcbfACKK3_y2Pqyb>TGai}88&T9bw;Z4!zV|m z+-khMR|>Sefex&7spzT?hv=gO%Xz!@vGkF1C3w4QuqnBwdwu*+9k(kxL@9ecU^k9@ z+>dc*|8l^ywGo6ngsOUUh`x6gh>SK1UM5sIwez|ZVXijb0>bhIug&aw1(BF*jKZp2 zE^zsE@JANVkdf(}{LubGV_T$Jbq8<tKI+WA8g|1}D;2 zND9$>Z?2+|B>SlYzZhjH5TK!uT?IN%d8N^dubAB$whSE zUl=hMwuO`e$5v;NsDVC`K(gSPpWWyv(IhEh#6oq1&JA-CC1=tK(VHRcbTF}A!bFRr z-1)`#(_78+n0+f{f<8Wi8uqdads#F0Lh-th;qIeoUh7)aig_ZxmtyytXbs4bUE zPGyGbJKgtZoYS*3FLir>>3c3XVK58u_j2(5nqkd2eZg{9c1O0=F>n9g;@jhu1mBXJ zQ4SE7Gt?T8@My;6CC|MmJtQa~mg;X*`rGn7b$XxsbSZ>}_FiwN{*GyzDhERStB_aw zIq0MQ??aMx5)k04D3o(oY|4MCx^t&b5(Q2Mqo-*qD`B6@?$1?pDcG%9s8D?Nyo3fP zz7yHmTmD5E%JQL`J{_Hx|D2Ueg#+{O=L~g>Vm=W_Vntk^?0rA465UoT-DO}|x)TTN zq+5oDyoi60gf%+K-i%~LCAJF(O-&W_O5T6n?h9|~?RS5P73T>q_Fj(o=Y^P;Y)*?2 zb9DsQG%$%Z&sR7!vSN4-VySE#pM0?NgI;00xc;HVsKx4{L04>qzVV*@uZ!AlB1yVf ziiF_HH`-qOH+pN5$o}-zLv+zxL1JZcrAfN)Y)`--Zy$3q7%}Awl#5VPclkkCT)RPW z+B$4A2h)B_1~ZX9ukB4+q(l1V;WAO6_=`^jcc2%fo2DPxm6J*? zmJ{4b`8PNs?jY>#+eUV^wi(>TsimZ59_+_`Nhuh<(ESScva=%mk0Po?H=(c zrko$yK~aF->ZwxEtJs&iBE9F%>&nH0?jp8Lm0zzwv11e6x>FVMMjp!DdbcLOlABk* zXsVcj>em%c!=wR+y$9CYCZ_#zy8WGNQ><>33C7)nT9Fr4XjClqd^tkPq)o-9YdUL* zaf=6*bo$P89NjAg;QD>IA)dvaut(yowX5_Jr#^`;)G96#1zkdL z>8`uRt6(4^2d-~YC<^0Hn8$?fUSiD6wL?#X9#V!~jJG`8hd(E?LxOi{eBXiHUJPZC zVT`R6JwT1`q5=h>e;T-iBNQWsJHKD_2VSC!>0+STZ&7ryUL8ws68FPd#W!-r!qHVs z#nCv)jQ*`W`S(v-kV5W*5+wz6U{{qNP&hPPTN;(WvWTr48UDGm)#nFU3P ztc0vxdnDS?$Lu3aqR#nCU4hrp7vV1xZlN_{aAMv_IAht2QX~EXM1=P|VYG1Kn(AS9 zwEG0bK9{~m2^+{UitAgviUJ}foC-zp#1|F7OZCINP>$!^;B!d(S)*;e(2SFB2qfd7qXRAFhC9;~_nW^;0+aLaqO+B#3K$*=D3%5P&9Ce&WmA!boh%Y z3X68Zl8AQPvU}bDDvl#!)zozFhQ--^(`-Y+H~T>PAxb zKwCyZZo#$jvJ&`a%OxG)!2ys{`Cn>9bO?Y8%FlN?(M^pZ#Gi}STBLrVA7*R3Hl!b& z!RjJGfv?joG0+zjB1q9{ZyQj5tZl+FE2usC3OP* zlrghUn5R!DjzzE}SQf*EF=2Xi@vLkHX{JXw*CVHbCK64b-~g_)jTdv?imtZi6m$y7 zcw(M8{9Kp2i4^clagQhp-BkmG?c!ThO<|l~u8HE-Ip_4jEn{mxPkiCJG%-4eXPzs^ z3#LLpR9SNXBFfh(|5Be(jBwq4;;kJMvMs8SzZXE6+s2e@)qTgZi)8q9;C?Cb!7Ee5kwx8NtElZtGpF!`( z3lj$slelv+kF4xLy5a6B30j#R`{E4&ZZmea;@?AGM)uRE5{9mVN?xeze6hP2Di{sV zF^vSUo%hCQ&AErFUZK!uz;!KN4*9qWTc?j|(}`o|BaM7_@T-LFYhUA3X#v*nSl)f1{ ze<1!%`5JmNZFLf82@||{()3^9l-fbW2iE-HhrqS>fng8D8U2iu_^#?%?^@NvaCM(< zS7k+hrH;~D)+qy^Ge}V{PacG;dEvsU*U1pXkuKU#p{#KP;P5^*$n7(nr6B3!sDkRgNIN4q^yQKkuN!zs!JztRsplYh_S z1E$vv{ciR9u~wp&SzEI}{mJ8txcnp8<-8s!DJx!@0PI;U8rGt^ z&viCZ)ITu0hY%{3M>tbKlyPU3?-q7|U|0dv{Q+8bMp?uj!39pMKc%6$il z5NEam*w*~p736hO%TD3I0Ez9#K|0im5T-I;`gfDENoyho%TRdY1*|!1m=8Sxcwgmz zo&B9w%5}J}V0`blYWxzSGi(_^G5T7H2+Ge4QXD{mnu>uJ-)bo}RWtp;$%D|)!>)6yh(mq;AG8ag(ZMEoy?+tJsTV}=O2ZQ2%YWM+^lV54mxPDAACwW3 zl$D$H;V{sUGLPj;dy$h%jKsz~0ykwX>}1d~5Djix@`HJ}aQWpy%+1$mCj^C{)t+j) zs=2LKnnNS{Gw3xy$>ajiTyY6gKH>oFJJ1OC5;d-=VRZXLq_yW}QC2;1W+`ViSqnHG zqHbs&{`8>(^mWu6lqECI%}*FWk2!#^qfpQkCi1lU^)K!*Re%6HJ#dr$UL=6blY#2T zj^gJp-^FmXU;Rg6GYW!qq9>uX7#`hCL!&{f^6o=?rQ|>WQ6Z*1bS{{7VjFhzr{nSg z>xo_1P#tT1V4||#FX^t<`t=Xr$0u4p@W1k5t&#EcigIC9^+`BV+C$R8t^d$Aqs){< zb$%15!Q1ZMvlF|rq5{;eK!<7_SHL6g)hMgPaA&Zag}a45JUe7TSo;V!(B3~v(xSKP zY5O_wV11z`B4jO66%ZXNx>aFOr>xLH}j**~Zj!`Hn;4^3Tn9+zy=(t)rcF=-Xf$7+^t}L9Y^f9i`bc|aTTKBf+FQN0GoSs( zs^^2G$2{Bf5vl+;**j`STr1lcbMe|Ha-~D*+jFhhnnoLd0&C4rd1)BoH!Z&uEpxaR zrjWEcGfupCUBLRYl3sAvNz~Kq;~6dVvG4WZ7fcoN#G-fsgfoI&*GYP|Q_AR}BPa_Q zwUc8?Cd+&PE7mI;Ztt$0SbzT;5gLXa_MLeTxI69&b_`m+>%skIhT$4Pbtfv;k1AVx zMPI{=h1pYx8JlAG3&%6GQ%uWE5R6_pHV$N9NdAF?+;q%4s0Tp72}kJON8h1-Xf(85 z_$T1a66dfA(|6)p=9F>H*E|eW8EcRBN_IIwJB)d#@yW{)Wc0cx+AigDSlHtQ&qQ8k zqOt+mK86PG1}ZbV^7fynwEB?b(C&-cS-T)PkW`kQ3zZ;erbcm3g|!e-O5l691!K5I z>EE9Yz`#bh&DhP<+9bYlV^Qos4usPSh;y^cUJrO$YAjTW8Uqmm3nTLGmuGMh=7Ud> znz|*at+CVVBVO`Hv`8|f^yzo?u-Cd34^1DvC_VYRP~p&=ttK*0yWPZkYdwA80Ag=d zajkq~>crs?oEg?*a}yu28qWN63$;gbcrfN}Y!ob*ERcs=5IheaV@Q_e6k+ZElJR$| z?*XO8ZLPh2LmjD%FlYZa#=!`fDvht=m2Q{FV9ahaB)u93=#5O~%7Xp>;#e(VzVo3e z_3pO}eC?c`P5{2&3&>?r-*0p}K1aVu^1>R5^j{;r1XD?`iE@l%FMhQE-G{H-aqxi~ z)|MavYyhJc1z4qh`yv6cN#_i;Q}iVKDZEMdNq3u9(`tHFq|V*F1fmy_(md~!IX_NN z6k7a-Aqm(&{=IvhdJ`go{4)S^N`9_$_4}r*_weiEZ(f3AVZ$CEb;+p`cT@pX2_l1X-LsIQr?LS$ms1VVE_#;nrDLoL-9RzC znP$@z*hZbLXvB>~KkMMtTBDdvyR z|B{)2JS%`48v-@9YatU|rHIM*)7@o4b$Zf4OyE}ZugeDjykF=D&y$5y!q@vP;3ov; z3`$5?Nti{6?H5TtvSz|&yoTpzd}Y0#$%ja1NoTU_&2ILNp5&~0;T=1Ri2-vQNIO9i z*9%`R`OF?TB5;Kg8GY0kR_2sJ#kC1zjLL zSsThNc_11cL%YGCox>Z!Ie$G%VoT47#hF7K;5s3;ov{jT8f;)`=P@C_nlNg zCvc|y{d5W9W0?dey$^JU|7P4Gas?+Y2vZc?4E9(yWq$>#|A8v&v=#NPN~=gzzA!Qy z;ZnAV=ti)g61?6u!b+Sm!%mDg4-ekR_U)TTI3YR@Z71XbqU2-Z4rOgi3uF^w#jA-Z z{UWSCmHOh}(9UX^#1OjXR*gmbu?ckX^dzIw0^6fxZFV^2^&kh3lVA>*^!2BZHwi=N znQ?8I6_+5)x0`Uolxd`prS*vBb6a;yv56ny^~5h~z+(OQ zwWOrRdw$sH&@?5q^}F&N@_!Yj2xsNrFr&edUoRRqFdqgF8+K&)rJt~`ZFhn_|B z*Gjlv5$1b0+HmW(B#LAdfF4W`4420&fD|-b?ABa>11ZdC<5_t~PrI zEo{nCZt-bv^CvA{{I85ZcsnJ+rSs6mRre<%g3N@xgzwq4DsN9d4#|XqHJ}~)JxcTw zlU{hf0~ZQn)IKje8fnh&-rmxaq*0cc9sDcv?&0A3f&rHl>Gg~o3x7Y|<@j~kYU|KT z{4-`&^|AMg0A26-LxM=EH&Kb>x_}nn6+wfv8OaQK0N=JdO{t3#7@hej2<6SC#A8OO zL1MjeH|LiVm+NY4Q~r4*S#Q-YrvSTZbJd3>FXD&*o~E3m8+v~O4=W2o>agI@u(_Bk zb)Cu!stkE~hrxjJmH^#iy@5iv`7_psCq7!&!FYM`R3x}^gCW2hz5`3B9t)k~A}Tq` z8;pgd*ZMxYS>Odgqh@^*4IS%SNLdwp8x6{1;>T<*2B^a`P|UXtHts`%PXvBV^q1>& z=WDOJ_j~OgN`thrjc8^FXGkxf^=4CT&In*NlQg4IPzUm8{ZRRY|CleLf(vaIW%q3l zJi2>mRM7WNCu%dHpP6qS!++UUKx|AW5NhzefjP8fzi%*ZOxJYDG%QzF{>v%~8z~qG z90f|6_Z!|DY72V2*%@;A6m#S4>ZC*rT>VAgceD2$h<*YBppyQGVHX~EX@-r4{m^~A zIx%GGxb?GptMNf@VNWy(24sBV2_A7h03rCxu>VF4=+zkIxrxypk{x1rdaSQ=2hf%R zR)8pgYBLV}U~zR3sWU%)21G=}v2Ka|&Bl{VcE2cr-yA`gy}kljELH{kjMBy4sIM(?^B8akWOwteBg^&GNbsO|LP6RCXT05eaROyB7u^{MEX5AY8 z8c2=gwmPyMqhs_2p*|wLTL3lhZxt6$;&{wVC8?JhAEcivQxHCDZP`0CZI{ZM#Wswq z1c*9teQTQ9mde^X;+lE-Ie=M8!$y||FMV3wID*L))+0MV9jwAIg6%tITiS3$c}VE| z`NV2{=jMIr8*;mqP(ruYNvoj8AHD2Qvaz?=U%4@fK(ti?ym>4M9F%KNi0Peir$K0w zLvE;t73-m0d9}cJL~lm5-Y?va^)ut#(1MrU52dT3sVblG|H~;SI{Wu-jP^0#Tm-Nc z0LkX^h#qr$0e`5)0PP0;c-&5bfB!#yVBi5NV6rHnny;b(~fKG#yLlDB;Of2drP A>Hq)$ literal 0 HcmV?d00001 diff --git a/DesktopEdge/Views/Screens/MainMenu.xaml.cs b/DesktopEdge/Views/Screens/MainMenu.xaml.cs index 3520d09c..d800a37f 100644 --- a/DesktopEdge/Views/Screens/MainMenu.xaml.cs +++ b/DesktopEdge/Views/Screens/MainMenu.xaml.cs @@ -168,7 +168,7 @@ namespace ZitiDesktopEdge { async private void SetAutomaticUpgradesMenuAction(object sender, MouseButtonEventArgs e) { bool disableAutomaticUpgrades = false; - if(sender == AutomaticUpgradesItemOff) { + if (sender == AutomaticUpgradesItemOff) { disableAutomaticUpgrades = true; } var monitorClient = (MonitorClient)Application.Current.Properties["MonitorClient"]; @@ -180,7 +180,6 @@ namespace ZitiDesktopEdge { Application.Current.Properties["AutomaticUpgradeDisabled"] = disableAutomaticUpgrades; } SetAutomaticUpgradesState(disableAutomaticUpgrades); - UpdateState(); } private void checkResponse(SvcResponse r, string titleOnErr, string msgOnErr) { @@ -266,9 +265,9 @@ namespace ZitiDesktopEdge { MenuTitle.Content = "Set Release Stream"; ReleaseStreamItems.Visibility = allowReleaseSelect ? Visibility.Visible : Visibility.Collapsed; BackArrow.Visibility = Visibility.Visible; - } else if (menuState == "ConfigureAutomaticUpgrades") - { + } else if (menuState == "ConfigureAutomaticUpgrades") { SetAutomaticUpgradesState(automaticUpgradeDisabled); + MenuTitle.Content = "Automatic Upgrades"; AutomaticUpgradesItems.Visibility = Visibility.Visible; BackArrow.Visibility = Visibility.Visible; @@ -317,7 +316,7 @@ namespace ZitiDesktopEdge { } private void GoBack(object sender, MouseButtonEventArgs e) { - if (menuState == "Config" || menuState == "LogLevel" || menuState == "UILogs" || menuState == "SetReleaseStream") { + if (menuState == "Config" || menuState == "LogLevel" || menuState == "UILogs" || menuState == "SetReleaseStream" || menuState == "ConfigureAutomaticUpgrades") { menuState = "Advanced"; } else if (menuState == "Licenses") { menuState = "About"; diff --git a/DesktopEdge/ZitiDesktopEdge.csproj b/DesktopEdge/ZitiDesktopEdge.csproj index e7116423..abdb6a8c 100644 --- a/DesktopEdge/ZitiDesktopEdge.csproj +++ b/DesktopEdge/ZitiDesktopEdge.csproj @@ -473,5 +473,8 @@ + + + \ No newline at end of file diff --git a/ZitiUpdateService/Properties/app.manifest b/ZitiUpdateService/Properties/app.manifest index 3b5ed3da..60eec770 100644 --- a/ZitiUpdateService/Properties/app.manifest +++ b/ZitiUpdateService/Properties/app.manifest @@ -19,8 +19,8 @@ - + diff --git a/ZitiUpdateService/ZitiUpdateService.csproj b/ZitiUpdateService/ZitiUpdateService.csproj index fac52706..5af66053 100644 --- a/ZitiUpdateService/ZitiUpdateService.csproj +++ b/ZitiUpdateService/ZitiUpdateService.csproj @@ -61,7 +61,7 @@ - true + false LocalIntranet