2021-05-21 18:32:34 +08:00
// Copyright (c) Microsoft Corporation
2020-04-08 01:19:14 +08:00
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
2020-04-18 06:25:08 +08:00
using System ;
2021-05-21 18:32:34 +08:00
using System.Diagnostics ;
2022-10-13 15:41:21 +08:00
using System.Globalization ;
using System.IO ;
2021-05-21 18:32:34 +08:00
using System.IO.Abstractions ;
2022-11-15 22:11:44 +08:00
using System.Net.NetworkInformation ;
2022-10-13 15:41:21 +08:00
using System.Reflection ;
2020-04-18 06:25:08 +08:00
using System.Runtime.CompilerServices ;
2022-10-13 15:41:21 +08:00
using System.Text.Json ;
using System.Threading.Tasks ;
2022-10-26 21:02:31 +08:00
using Microsoft.PowerToys.Settings.UI.Library ;
2020-10-23 00:45:48 +08:00
using Microsoft.PowerToys.Settings.UI.Library.Helpers ;
using Microsoft.PowerToys.Settings.UI.Library.Interfaces ;
using Microsoft.PowerToys.Settings.UI.Library.Utilities ;
using Microsoft.PowerToys.Settings.UI.Library.ViewModels.Commands ;
2020-03-12 14:25:24 +08:00
2022-10-26 21:02:31 +08:00
namespace Microsoft.PowerToys.Settings.UI.ViewModels
2020-03-12 14:25:24 +08:00
{
public class GeneralViewModel : Observable
{
2020-09-24 04:20:32 +08:00
private GeneralSettings GeneralSettingsConfig { get ; set ; }
2020-09-22 01:14:44 +08:00
2021-05-21 18:32:34 +08:00
private UpdatingSettings UpdatingSettingsConfig { get ; set ; }
2020-10-10 08:58:52 +08:00
public ButtonClickCommand CheckForUpdatesEventHandler { get ; set ; }
2020-04-18 06:25:08 +08:00
2022-10-13 15:41:21 +08:00
public object ResourceLoader { get ; set ; }
private Action HideBackupAndRestoreMessageAreaAction { get ; set ; }
private Action < int > DoBackupAndRestoreDryRun { get ; set ; }
public ButtonClickCommand BackupConfigsEventHandler { get ; set ; }
public ButtonClickCommand RestoreConfigsEventHandler { get ; set ; }
public ButtonClickCommand RefreshBackupStatusEventHandler { get ; set ; }
public ButtonClickCommand SelectSettingBackupDirEventHandler { get ; set ; }
2020-04-18 06:25:08 +08:00
public ButtonClickCommand RestartElevatedButtonEventHandler { get ; set ; }
2021-05-21 18:32:34 +08:00
public ButtonClickCommand UpdateNowButtonEventHandler { get ; set ; }
2020-08-14 06:02:05 +08:00
public Func < string , int > UpdateUIThemeCallBack { get ; }
2020-08-07 02:16:25 +08:00
2020-08-14 06:02:05 +08:00
public Func < string , int > SendConfigMSG { get ; }
2020-08-07 02:16:25 +08:00
2020-08-14 06:02:05 +08:00
public Func < string , int > SendRestartAsAdminConfigMSG { get ; }
public Func < string , int > SendCheckForUpdatesConfigMSG { get ; }
2020-08-20 06:59:10 +08:00
public string RunningAsUserDefaultText { get ; set ; }
2020-08-14 06:02:05 +08:00
2020-08-20 06:59:10 +08:00
public string RunningAsAdminDefaultText { get ; set ; }
2020-05-06 01:02:31 +08:00
2020-08-20 06:59:10 +08:00
private string _settingsConfigFileFolder = string . Empty ;
2020-08-14 06:02:05 +08:00
2021-05-21 18:32:34 +08:00
private IFileSystemWatcher _fileWatcher ;
2022-10-13 15:41:21 +08:00
private Func < Task < string > > PickSingleFolderDialog { get ; }
private SettingsBackupAndRestoreUtils settingsBackupAndRestoreUtils = SettingsBackupAndRestoreUtils . Instance ;
public GeneralViewModel ( ISettingsRepository < GeneralSettings > settingsRepository , string runAsAdminText , string runAsUserText , bool isElevated , bool isAdmin , Func < string , int > updateTheme , Func < string , int > ipcMSGCallBackFunc , Func < string , int > ipcMSGRestartAsAdminMSGCallBackFunc , Func < string , int > ipcMSGCheckForUpdatesCallBackFunc , string configFileSubfolder = "" , Action dispatcherAction = null , Action hideBackupAndRestoreMessageAreaAction = null , Action < int > doBackupAndRestoreDryRun = null , Func < Task < string > > pickSingleFolderDialog = null , object resourceLoader = null )
2020-03-12 14:25:24 +08:00
{
2020-10-10 08:58:52 +08:00
CheckForUpdatesEventHandler = new ButtonClickCommand ( CheckForUpdatesClick ) ;
RestartElevatedButtonEventHandler = new ButtonClickCommand ( RestartElevated ) ;
2021-05-21 18:32:34 +08:00
UpdateNowButtonEventHandler = new ButtonClickCommand ( UpdateNowClick ) ;
2022-10-13 15:41:21 +08:00
BackupConfigsEventHandler = new ButtonClickCommand ( BackupConfigsClick ) ;
SelectSettingBackupDirEventHandler = new ButtonClickCommand ( SelectSettingBackupDir ) ;
RestoreConfigsEventHandler = new ButtonClickCommand ( RestoreConfigsClick ) ;
RefreshBackupStatusEventHandler = new ButtonClickCommand ( RefreshBackupStatusEventHandlerClick ) ;
HideBackupAndRestoreMessageAreaAction = hideBackupAndRestoreMessageAreaAction ;
DoBackupAndRestoreDryRun = doBackupAndRestoreDryRun ;
PickSingleFolderDialog = pickSingleFolderDialog ;
ResourceLoader = resourceLoader ;
2020-04-18 06:25:08 +08:00
2020-09-24 04:20:32 +08:00
// To obtain the general settings configuration of PowerToys if it exists, else to create a new file and return the default configurations.
2020-10-20 04:32:05 +08:00
if ( settingsRepository = = null )
{
throw new ArgumentNullException ( nameof ( settingsRepository ) ) ;
}
2020-09-24 04:20:32 +08:00
GeneralSettingsConfig = settingsRepository . SettingsConfig ;
2021-05-21 18:32:34 +08:00
UpdatingSettingsConfig = UpdatingSettings . LoadSettings ( ) ;
if ( UpdatingSettingsConfig = = null )
{
UpdatingSettingsConfig = new UpdatingSettings ( ) ;
}
2020-04-18 06:25:08 +08:00
2020-08-14 06:02:05 +08:00
// set the callback functions value to hangle outgoing IPC message.
SendConfigMSG = ipcMSGCallBackFunc ;
SendCheckForUpdatesConfigMSG = ipcMSGCheckForUpdatesCallBackFunc ;
SendRestartAsAdminConfigMSG = ipcMSGRestartAsAdminMSGCallBackFunc ;
// set the callback function value to update the UI theme.
UpdateUIThemeCallBack = updateTheme ;
2020-10-20 04:32:05 +08:00
UpdateUIThemeCallBack ( GeneralSettingsConfig . Theme ) ;
2020-08-14 06:02:05 +08:00
// Update Settings file folder:
2020-08-20 06:59:10 +08:00
_settingsConfigFileFolder = configFileSubfolder ;
2020-08-14 06:02:05 +08:00
2022-08-16 02:21:52 +08:00
// Using Invariant here as these are internal strings and the analyzer
2020-10-20 04:32:05 +08:00
// expects strings to be normalized to uppercase. While the theme names
// are represented in lowercase everywhere else, we'll use uppercase
// normalization for switch statements
switch ( GeneralSettingsConfig . Theme . ToUpperInvariant ( ) )
2020-04-18 06:25:08 +08:00
{
2020-10-20 04:32:05 +08:00
case "DARK" :
2021-08-24 01:48:52 +08:00
_themeIndex = 0 ;
break ;
case "LIGHT" :
_themeIndex = 1 ;
2020-04-18 06:25:08 +08:00
break ;
2020-10-20 04:32:05 +08:00
case "SYSTEM" :
2021-08-24 01:48:52 +08:00
_themeIndex = 2 ;
2020-04-18 06:25:08 +08:00
break ;
}
2020-09-24 04:20:32 +08:00
_startup = GeneralSettingsConfig . Startup ;
_autoDownloadUpdates = GeneralSettingsConfig . AutoDownloadUpdates ;
2023-02-15 10:38:53 +08:00
_enableExperimentation = GeneralSettingsConfig . EnableExperimentation ;
2022-10-13 15:41:21 +08:00
2020-08-14 06:02:05 +08:00
_isElevated = isElevated ;
2020-09-24 04:20:32 +08:00
_runElevated = GeneralSettingsConfig . RunElevated ;
2020-05-16 00:38:47 +08:00
2020-08-14 06:02:05 +08:00
RunningAsUserDefaultText = runAsUserText ;
RunningAsAdminDefaultText = runAsAdminText ;
2020-05-16 00:38:47 +08:00
2020-08-14 06:02:05 +08:00
_isAdmin = isAdmin ;
2021-05-21 18:32:34 +08:00
_updatingState = UpdatingSettingsConfig . State ;
_newAvailableVersion = UpdatingSettingsConfig . NewVersion ;
_newAvailableVersionLink = UpdatingSettingsConfig . ReleasePageLink ;
_updateCheckedDate = UpdatingSettingsConfig . LastCheckedDateLocalized ;
if ( dispatcherAction ! = null )
{
_fileWatcher = Helper . GetFileWatcher ( string . Empty , UpdatingSettings . SettingsFile , dispatcherAction ) ;
}
2020-04-18 06:25:08 +08:00
}
2020-10-10 08:58:52 +08:00
private bool _startup ;
private bool _isElevated ;
private bool _runElevated ;
private bool _isAdmin ;
2021-08-24 01:48:52 +08:00
private int _themeIndex ;
2020-10-10 08:58:52 +08:00
private bool _autoDownloadUpdates ;
2023-02-15 10:38:53 +08:00
private bool _enableExperimentation ;
2020-08-14 06:02:05 +08:00
2021-05-21 18:32:34 +08:00
private UpdatingSettings . UpdatingState _updatingState = UpdatingSettings . UpdatingState . UpToDate ;
private string _newAvailableVersion = string . Empty ;
private string _newAvailableVersionLink = string . Empty ;
2020-12-18 00:38:23 +08:00
private string _updateCheckedDate = string . Empty ;
2020-09-04 16:56:52 +08:00
2021-05-21 18:32:34 +08:00
private bool _isNewVersionDownloading ;
private bool _isNewVersionChecked ;
2022-11-15 22:11:44 +08:00
private bool _isNoNetwork ;
2021-05-21 18:32:34 +08:00
2022-10-13 15:41:21 +08:00
private bool _settingsBackupRestoreMessageVisible ;
private string _settingsBackupMessage ;
private string _backupRestoreMessageSeverity ;
2020-04-18 06:25:08 +08:00
// Gets or sets a value indicating whether run powertoys on start-up.
public bool Startup
{
get
{
return _startup ;
}
set
{
if ( _startup ! = value )
{
_startup = value ;
2020-09-24 04:20:32 +08:00
GeneralSettingsConfig . Startup = value ;
2020-10-20 04:32:05 +08:00
NotifyPropertyChanged ( ) ;
2020-04-18 06:25:08 +08:00
}
}
}
2020-05-16 00:38:47 +08:00
public string RunningAsText
2020-05-06 01:02:31 +08:00
{
get
{
if ( ! IsElevated )
{
2020-05-16 00:38:47 +08:00
return RunningAsUserDefaultText ;
2020-05-06 01:02:31 +08:00
}
else
{
2020-05-16 00:38:47 +08:00
return RunningAsAdminDefaultText ;
2020-05-06 01:02:31 +08:00
}
}
set
{
OnPropertyChanged ( "RunningAsAdminText" ) ;
}
}
2020-04-18 06:25:08 +08:00
// Gets or sets a value indicating whether the powertoy elevated.
public bool IsElevated
{
get
{
return _isElevated ;
}
set
{
if ( _isElevated ! = value )
{
_isElevated = value ;
2020-10-10 08:58:52 +08:00
OnPropertyChanged ( nameof ( IsElevated ) ) ;
OnPropertyChanged ( nameof ( IsAdminButtonEnabled ) ) ;
2020-05-06 01:02:31 +08:00
OnPropertyChanged ( "RunningAsAdminText" ) ;
2020-04-18 06:25:08 +08:00
}
}
}
2020-05-06 01:02:31 +08:00
public bool IsAdminButtonEnabled
{
get
{
return ! IsElevated ;
}
set
{
2020-10-10 08:58:52 +08:00
OnPropertyChanged ( nameof ( IsAdminButtonEnabled ) ) ;
2020-05-06 01:02:31 +08:00
}
}
2020-04-18 06:25:08 +08:00
// Gets or sets a value indicating whether powertoys should run elevated.
public bool RunElevated
{
get
{
return _runElevated ;
}
set
{
if ( _runElevated ! = value )
{
_runElevated = value ;
2020-09-24 04:20:32 +08:00
GeneralSettingsConfig . RunElevated = value ;
2020-10-20 04:32:05 +08:00
NotifyPropertyChanged ( ) ;
2020-04-18 06:25:08 +08:00
}
}
}
2020-05-14 17:36:27 +08:00
// Gets a value indicating whether the user is part of administrators group.
public bool IsAdmin
{
get
{
return _isAdmin ;
}
}
2020-05-03 18:17:06 +08:00
public bool AutoDownloadUpdates
{
get
{
return _autoDownloadUpdates ;
}
set
{
if ( _autoDownloadUpdates ! = value )
{
_autoDownloadUpdates = value ;
2020-09-24 04:20:32 +08:00
GeneralSettingsConfig . AutoDownloadUpdates = value ;
2020-10-20 04:32:05 +08:00
NotifyPropertyChanged ( ) ;
2020-05-03 18:17:06 +08:00
}
}
}
2023-02-15 10:38:53 +08:00
public bool EnableExperimentation
{
get
{
return _enableExperimentation ;
}
set
{
if ( _enableExperimentation ! = value )
{
_enableExperimentation = value ;
GeneralSettingsConfig . EnableExperimentation = value ;
NotifyPropertyChanged ( ) ;
}
}
}
2021-01-12 23:34:02 +08:00
public static bool AutoUpdatesEnabled
{
get
{
return Helper . GetProductVersion ( ) ! = "v0.0.1" ;
}
}
2022-10-13 15:41:21 +08:00
public string SettingsBackupAndRestoreDir
{
get
{
return settingsBackupAndRestoreUtils . GetSettingsBackupAndRestoreDir ( ) ;
}
set
{
if ( settingsBackupAndRestoreUtils . GetSettingsBackupAndRestoreDir ( ) ! = value )
{
SettingsBackupAndRestoreUtils . SetRegSettingsBackupAndRestoreItem ( "SettingsBackupAndRestoreDir" , value ) ;
NotifyPropertyChanged ( ) ;
}
}
}
2021-08-24 01:48:52 +08:00
public int ThemeIndex
2020-04-18 06:25:08 +08:00
{
get
{
2021-08-24 01:48:52 +08:00
return _themeIndex ;
2020-04-18 06:25:08 +08:00
}
set
{
2021-08-24 01:48:52 +08:00
if ( _themeIndex ! = value )
2020-04-18 06:25:08 +08:00
{
2021-08-24 01:48:52 +08:00
switch ( value )
2020-05-06 01:02:31 +08:00
{
2021-08-24 01:48:52 +08:00
case 0 : GeneralSettingsConfig . Theme = "dark" ; break ;
case 1 : GeneralSettingsConfig . Theme = "light" ; break ;
case 2 : GeneralSettingsConfig . Theme = "system" ; break ;
2020-05-06 01:02:31 +08:00
}
2021-08-24 01:48:52 +08:00
_themeIndex = value ;
2020-04-18 06:25:08 +08:00
2020-05-06 01:02:31 +08:00
try
{
2020-09-24 04:20:32 +08:00
UpdateUIThemeCallBack ( GeneralSettingsConfig . Theme ) ;
2020-05-06 01:02:31 +08:00
}
2020-10-22 03:32:53 +08:00
catch ( Exception e )
2020-05-06 01:02:31 +08:00
{
2020-10-22 03:32:53 +08:00
Logger . LogError ( "Exception encountered when changing Settings theme" , e ) ;
2020-05-06 01:02:31 +08:00
}
2020-10-20 04:32:05 +08:00
NotifyPropertyChanged ( ) ;
2020-04-18 06:25:08 +08:00
}
}
}
2020-05-06 01:02:31 +08:00
public string PowerToysVersion
{
get
{
return Helper . GetProductVersion ( ) ;
}
2020-05-05 05:40:32 +08:00
}
2020-12-18 00:38:23 +08:00
public string UpdateCheckedDate
{
get
{
RequestUpdateCheckedDate ( ) ;
return _updateCheckedDate ;
}
set
{
if ( _updateCheckedDate ! = value )
{
_updateCheckedDate = value ;
NotifyPropertyChanged ( ) ;
}
}
}
2022-10-13 15:41:21 +08:00
public string LastSettingsBackupDate
{
get
{
try
{
var manifest = settingsBackupAndRestoreUtils . GetLatestSettingsBackupManifest ( ) ;
if ( manifest ! = null )
{
if ( manifest [ "CreateDateTime" ] ! = null )
{
if ( DateTime . TryParse ( manifest [ "CreateDateTime" ] . ToString ( ) , CultureInfo . InvariantCulture , DateTimeStyles . AssumeUniversal , out var theDateTime ) )
{
return theDateTime . ToString ( "G" , CultureInfo . CurrentCulture ) ;
}
else
{
Logger . LogError ( "Failed to parse time from backup" ) ;
return GetResourceString ( "General_SettingsBackupAndRestore_FailedToParseTime" ) ;
}
}
else
{
return GetResourceString ( "General_SettingsBackupAndRestore_UnknownBackupTime" ) ;
}
}
else
{
return GetResourceString ( "General_SettingsBackupAndRestore_NoBackupFound" ) ;
}
}
catch ( Exception e )
{
Logger . LogError ( "Error getting LastSettingsBackupDate" , e ) ;
return GetResourceString ( "General_SettingsBackupAndRestore_UnknownBackupTime" ) ;
}
}
}
public string CurrentSettingMatchText
{
get
{
try
{
var results = settingsBackupAndRestoreUtils . GetLastBackupSettingsResults ( ) ;
var resultText = string . Empty ;
2022-12-18 21:27:14 +08:00
if ( ! results . LastRan . HasValue )
2022-10-13 15:41:21 +08:00
{
// not ran since started.
return GetResourceString ( "General_SettingsBackupAndRestore_CurrentSettingsNoChecked" ) ; // "Current Settings Unknown";
}
else
{
2022-12-18 21:27:14 +08:00
if ( results . Success )
2022-10-13 15:41:21 +08:00
{
2022-12-18 21:27:14 +08:00
if ( results . LastBackupExists )
2022-10-13 15:41:21 +08:00
{
// if true, it means a backup would have been made
resultText = GetResourceString ( "General_SettingsBackupAndRestore_CurrentSettingsDiffer" ) ; // "Current Settings Differ";
}
else
{
// would have done the backup, but there also was not an existing one there.
resultText = GetResourceString ( "General_SettingsBackupAndRestore_NoBackupFound" ) ;
}
}
else
{
2022-12-18 21:27:14 +08:00
if ( results . HadError )
2022-10-13 15:41:21 +08:00
{
// if false and error we don't really know
resultText = GetResourceString ( "General_SettingsBackupAndRestore_CurrentSettingsUnknown" ) ; // "Current Settings Unknown";
}
else
{
// if false, it means a backup would not have been needed/made
resultText = GetResourceString ( "General_SettingsBackupAndRestore_CurrentSettingsMatch" ) ; // "Current Settings Match";
}
}
2022-12-18 21:27:14 +08:00
return $"{resultText} {GetResourceString(" General_SettingsBackupAndRestore_CurrentSettingsStatusAt ")} {results.LastRan.Value.ToLocalTime().ToString(" G ", CultureInfo.CurrentCulture)}" ;
2022-10-13 15:41:21 +08:00
}
}
catch ( Exception e )
{
Logger . LogError ( "Error getting CurrentSettingMatchText" , e ) ;
return string . Empty ;
}
}
}
public string LastSettingsBackupSource
{
get
{
try
{
var manifest = settingsBackupAndRestoreUtils . GetLatestSettingsBackupManifest ( ) ;
if ( manifest ! = null )
{
if ( manifest [ "BackupSource" ] ! = null )
{
if ( manifest [ "BackupSource" ] . ToString ( ) . Equals ( Environment . MachineName , StringComparison . OrdinalIgnoreCase ) )
{
return GetResourceString ( "General_SettingsBackupAndRestore_ThisMachine" ) ;
}
else
{
return manifest [ "BackupSource" ] . ToString ( ) ;
}
}
else
{
return GetResourceString ( "General_SettingsBackupAndRestore_UnknownBackupSource" ) ;
}
}
else
{
return GetResourceString ( "General_SettingsBackupAndRestore_NoBackupFound" ) ;
}
}
catch ( Exception e )
{
Logger . LogError ( "Error getting LastSettingsBackupSource" , e ) ;
return GetResourceString ( "General_SettingsBackupAndRestore_UnknownBackupSource" ) ;
}
}
}
public string LastSettingsBackupFileName
{
get
{
try
{
var fileName = settingsBackupAndRestoreUtils . GetLatestBackupFileName ( ) ;
return ! string . IsNullOrEmpty ( fileName ) ? fileName : GetResourceString ( "General_SettingsBackupAndRestore_NoBackupFound" ) ;
}
catch ( Exception e )
{
Logger . LogError ( "Error getting LastSettingsBackupFileName" , e ) ;
return string . Empty ;
}
}
}
2021-05-21 18:32:34 +08:00
public UpdatingSettings . UpdatingState PowerToysUpdatingState
{
get
{
return _updatingState ;
}
private set
{
if ( value ! = _updatingState )
{
_updatingState = value ;
NotifyPropertyChanged ( ) ;
}
}
}
public string PowerToysNewAvailableVersion
{
get
{
return _newAvailableVersion ;
}
private set
{
if ( value ! = _newAvailableVersion )
{
_newAvailableVersion = value ;
NotifyPropertyChanged ( ) ;
}
}
}
public string PowerToysNewAvailableVersionLink
{
get
{
return _newAvailableVersionLink ;
}
private set
{
if ( value ! = _newAvailableVersionLink )
{
_newAvailableVersionLink = value ;
NotifyPropertyChanged ( ) ;
}
}
}
public bool IsNewVersionDownloading
2020-09-04 16:56:52 +08:00
{
get
{
2021-05-21 18:32:34 +08:00
return _isNewVersionDownloading ;
2020-09-04 16:56:52 +08:00
}
set
{
2021-05-21 18:32:34 +08:00
if ( value ! = _isNewVersionDownloading )
2020-09-04 16:56:52 +08:00
{
2021-05-21 18:32:34 +08:00
_isNewVersionDownloading = value ;
2020-10-20 04:32:05 +08:00
NotifyPropertyChanged ( ) ;
2020-09-04 16:56:52 +08:00
}
}
}
2021-05-21 18:32:34 +08:00
public bool IsNewVersionCheckedAndUpToDate
{
get
{
return _isNewVersionChecked ;
}
}
2022-11-15 22:11:44 +08:00
public bool IsNoNetwork
{
get
{
return _isNoNetwork ;
}
}
2022-10-13 15:41:21 +08:00
public bool SettingsBackupRestoreMessageVisible
{
get
{
return _settingsBackupRestoreMessageVisible ;
}
}
public string BackupRestoreMessageSeverity
{
get
{
return _backupRestoreMessageSeverity ;
}
}
public string SettingsBackupMessage
{
get
{
return _settingsBackupMessage ;
}
}
2021-05-21 18:32:34 +08:00
public bool IsDownloadAllowed
{
get
{
return AutoUpdatesEnabled & & ! IsNewVersionDownloading ;
}
}
2022-10-13 15:41:21 +08:00
public void NotifyPropertyChanged ( [ CallerMemberName ] string propertyName = null , bool reDoBackupDryRun = true )
2020-04-18 06:25:08 +08:00
{
// Notify UI of property change
OnPropertyChanged ( propertyName ) ;
2022-10-13 15:41:21 +08:00
2020-09-24 04:20:32 +08:00
OutGoingGeneralSettings outsettings = new OutGoingGeneralSettings ( GeneralSettingsConfig ) ;
2020-04-18 06:25:08 +08:00
2020-08-14 06:02:05 +08:00
SendConfigMSG ( outsettings . ToString ( ) ) ;
2022-10-13 15:41:21 +08:00
if ( reDoBackupDryRun & & DoBackupAndRestoreDryRun ! = null )
{
DoBackupAndRestoreDryRun ( 500 ) ;
}
}
/// <summary>
/// Method <c>SelectSettingBackupDir</c> opens folder browser to select a backup and retore location.
/// </summary>
private async void SelectSettingBackupDir ( )
{
var currentDir = settingsBackupAndRestoreUtils . GetSettingsBackupAndRestoreDir ( ) ;
var newPath = await PickSingleFolderDialog ( ) ;
if ( ! string . IsNullOrEmpty ( newPath ) )
{
SettingsBackupAndRestoreDir = newPath ;
NotifyAllBackupAndRestoreProperties ( ) ;
}
}
private void RefreshBackupStatusEventHandlerClick ( )
{
DoBackupAndRestoreDryRun ( 0 ) ;
}
/// <summary>
/// Method <c>RestoreConfigsClick</c> starts the restore.
/// </summary>
private void RestoreConfigsClick ( )
{
string settingsBackupAndRestoreDir = settingsBackupAndRestoreUtils . GetSettingsBackupAndRestoreDir ( ) ;
if ( string . IsNullOrEmpty ( settingsBackupAndRestoreDir ) )
{
SelectSettingBackupDir ( ) ;
}
var results = SettingsUtils . RestoreSettings ( ) ;
2022-12-18 21:27:14 +08:00
_backupRestoreMessageSeverity = results . Severity ;
2022-10-13 15:41:21 +08:00
2022-12-18 21:27:14 +08:00
if ( ! results . Success )
2022-10-13 15:41:21 +08:00
{
_settingsBackupRestoreMessageVisible = true ;
2022-12-18 21:27:14 +08:00
_settingsBackupMessage = GetResourceString ( results . Message ) ;
2022-10-13 15:41:21 +08:00
NotifyAllBackupAndRestoreProperties ( ) ;
HideBackupAndRestoreMessageAreaAction ( ) ;
}
else
{
// make sure not to do NotifyPropertyChanged here, else it will persist the configs from memory and
// undo the settings restore.
SettingsBackupAndRestoreUtils . SetRegSettingsBackupAndRestoreItem ( "LastSettingsRestoreDate" , DateTime . UtcNow . ToString ( "u" , CultureInfo . InvariantCulture ) ) ;
Restart ( ) ;
}
}
/// <summary>
/// Method <c>BackupConfigsClick</c> starts the backup.
/// </summary>
private void BackupConfigsClick ( )
{
string settingsBackupAndRestoreDir = settingsBackupAndRestoreUtils . GetSettingsBackupAndRestoreDir ( ) ;
if ( string . IsNullOrEmpty ( settingsBackupAndRestoreDir ) )
{
SelectSettingBackupDir ( ) ;
}
var results = SettingsUtils . BackupSettings ( ) ;
_settingsBackupRestoreMessageVisible = true ;
2022-12-18 21:27:14 +08:00
_backupRestoreMessageSeverity = results . Severity ;
_settingsBackupMessage = GetResourceString ( results . Message ) ;
2022-10-13 15:41:21 +08:00
// now we do a dry run to get the results for "setting match"
var settingsUtils = new SettingsUtils ( ) ;
var appBasePath = Path . GetDirectoryName ( settingsUtils . GetSettingsFilePath ( ) ) ;
settingsBackupAndRestoreUtils . BackupSettings ( appBasePath , settingsBackupAndRestoreDir , true ) ;
NotifyAllBackupAndRestoreProperties ( ) ;
HideBackupAndRestoreMessageAreaAction ( ) ;
}
public void NotifyAllBackupAndRestoreProperties ( )
{
NotifyPropertyChanged ( nameof ( LastSettingsBackupDate ) , false ) ;
NotifyPropertyChanged ( nameof ( LastSettingsBackupSource ) , false ) ;
NotifyPropertyChanged ( nameof ( LastSettingsBackupFileName ) , false ) ;
NotifyPropertyChanged ( nameof ( CurrentSettingMatchText ) , false ) ;
NotifyPropertyChanged ( nameof ( SettingsBackupMessage ) , false ) ;
NotifyPropertyChanged ( nameof ( BackupRestoreMessageSeverity ) , false ) ;
NotifyPropertyChanged ( nameof ( SettingsBackupRestoreMessageVisible ) , false ) ;
2020-04-18 06:25:08 +08:00
}
// callback function to launch the URL to check for updates.
2020-10-10 08:58:52 +08:00
private void CheckForUpdatesClick ( )
2020-04-18 06:25:08 +08:00
{
2022-11-15 22:11:44 +08:00
// check if network is available
bool isNetAvailable = IsNetworkAvailable ( ) ;
// check if the state changed
bool prevState = _isNoNetwork ;
_isNoNetwork = ! isNetAvailable ;
if ( prevState ! = _isNoNetwork )
{
NotifyPropertyChanged ( nameof ( IsNoNetwork ) ) ;
}
if ( ! isNetAvailable )
{
_isNewVersionDownloading = false ;
return ;
}
2021-08-12 19:53:51 +08:00
RefreshUpdatingState ( ) ;
2021-05-21 18:32:34 +08:00
IsNewVersionDownloading = string . IsNullOrEmpty ( UpdatingSettingsConfig . DownloadedInstallerFilename ) ;
NotifyPropertyChanged ( nameof ( IsDownloadAllowed ) ) ;
if ( _isNewVersionChecked )
{
_isNewVersionChecked = ! IsNewVersionDownloading ;
NotifyPropertyChanged ( nameof ( IsNewVersionCheckedAndUpToDate ) ) ;
}
2020-09-25 01:50:49 +08:00
GeneralSettingsConfig . CustomActionName = "check_for_updates" ;
2020-06-23 20:53:02 +08:00
2020-09-25 01:50:49 +08:00
OutGoingGeneralSettings outsettings = new OutGoingGeneralSettings ( GeneralSettingsConfig ) ;
2020-06-23 20:53:02 +08:00
GeneralSettingsCustomAction customaction = new GeneralSettingsCustomAction ( outsettings ) ;
2020-12-18 00:38:23 +08:00
SendCheckForUpdatesConfigMSG ( customaction . ToString ( ) ) ;
}
2021-05-21 18:32:34 +08:00
private void UpdateNowClick ( )
{
IsNewVersionDownloading = string . IsNullOrEmpty ( UpdatingSettingsConfig . DownloadedInstallerFilename ) ;
NotifyPropertyChanged ( nameof ( IsDownloadAllowed ) ) ;
Process . Start ( new ProcessStartInfo ( Helper . GetPowerToysInstallationFolder ( ) + "\\PowerToys.exe" ) { Arguments = "powertoys://update_now/" } ) ;
}
2022-10-13 15:41:21 +08:00
/// <summary>
/// Class <c>GetResourceString</c> gets a localized text.
/// </summary>
/// <remarks>
/// To do: see if there is a betting way to do this, there should be. It does allow us to return missing localization in a way that makes it obvious they were missed.
/// </remarks>
public string GetResourceString ( string resource )
{
if ( ResourceLoader ! = null )
{
var type = ResourceLoader . GetType ( ) ;
MethodInfo methodInfo = type . GetMethod ( "GetString" ) ;
object classInstance = Activator . CreateInstance ( type , null ) ;
object [ ] parametersArray = new object [ ] { resource } ;
var result = ( string ) methodInfo . Invoke ( ResourceLoader , parametersArray ) ;
if ( string . IsNullOrEmpty ( result ) )
{
return resource . ToUpperInvariant ( ) + "!!!" ;
}
else
{
return result ;
}
}
else
{
return resource ;
}
}
2021-01-12 23:34:02 +08:00
public void RequestUpdateCheckedDate ( )
2020-12-18 00:38:23 +08:00
{
GeneralSettingsConfig . CustomActionName = "request_update_state_date" ;
OutGoingGeneralSettings outsettings = new OutGoingGeneralSettings ( GeneralSettingsConfig ) ;
GeneralSettingsCustomAction customaction = new GeneralSettingsCustomAction ( outsettings ) ;
2020-08-14 06:02:05 +08:00
SendCheckForUpdatesConfigMSG ( customaction . ToString ( ) ) ;
2020-04-18 06:25:08 +08:00
}
2020-10-10 08:58:52 +08:00
public void RestartElevated ( )
2020-04-18 06:25:08 +08:00
{
2020-09-25 01:50:49 +08:00
GeneralSettingsConfig . CustomActionName = "restart_elevation" ;
2020-05-03 18:17:06 +08:00
2020-09-25 01:50:49 +08:00
OutGoingGeneralSettings outsettings = new OutGoingGeneralSettings ( GeneralSettingsConfig ) ;
2020-05-03 18:17:06 +08:00
GeneralSettingsCustomAction customaction = new GeneralSettingsCustomAction ( outsettings ) ;
2020-04-18 06:25:08 +08:00
2020-08-14 06:02:05 +08:00
SendRestartAsAdminConfigMSG ( customaction . ToString ( ) ) ;
2020-03-12 14:25:24 +08:00
}
2021-05-21 18:32:34 +08:00
2022-10-13 15:41:21 +08:00
/// <summary>
/// Class <c>Restart</c> begin a restart and signal we want to maintain elevation
/// </summary>
/// <remarks>
/// Other restarts either raised or lowered elevation
/// </remarks>
public void Restart ( )
{
GeneralSettingsConfig . CustomActionName = "restart_maintain_elevation" ;
OutGoingGeneralSettings outsettings = new OutGoingGeneralSettings ( GeneralSettingsConfig ) ;
GeneralSettingsCustomAction customaction = new GeneralSettingsCustomAction ( outsettings ) ;
var dataToSend = customaction . ToString ( ) ;
dataToSend = JsonSerializer . Serialize ( new { action = new { general = new { action_name = "restart_maintain_elevation" } } } ) ;
SendRestartAsAdminConfigMSG ( dataToSend ) ;
}
/// <summary>
/// Class <c>HideBackupAndRestoreMessageArea</c> hides the backup/restore message area
/// </summary>
/// <remarks>
/// We want to have it go away after a short period.
/// </remarks>
public void HideBackupAndRestoreMessageArea ( )
{
_settingsBackupRestoreMessageVisible = false ;
NotifyAllBackupAndRestoreProperties ( ) ;
}
2021-05-21 18:32:34 +08:00
public void RefreshUpdatingState ( )
{
2022-03-18 17:26:29 +08:00
object oLock = new object ( ) ;
lock ( oLock )
2021-05-21 18:32:34 +08:00
{
2022-03-18 17:26:29 +08:00
var config = UpdatingSettings . LoadSettings ( ) ;
2021-05-21 18:32:34 +08:00
2022-03-18 17:26:29 +08:00
// Retry loading if failed
for ( int i = 0 ; i < 3 & & config = = null ; i + + )
{
System . Threading . Thread . Sleep ( 100 ) ;
config = UpdatingSettings . LoadSettings ( ) ;
}
2021-05-21 18:32:34 +08:00
2022-03-18 17:26:29 +08:00
if ( config = = null )
{
return ;
}
2021-05-21 18:32:34 +08:00
2022-03-18 17:26:29 +08:00
UpdatingSettingsConfig = config ;
if ( PowerToysUpdatingState ! = config . State )
{
IsNewVersionDownloading = false ;
}
else
{
bool dateChanged = UpdateCheckedDate = = UpdatingSettingsConfig . LastCheckedDateLocalized ;
bool fileDownloaded = string . IsNullOrEmpty ( UpdatingSettingsConfig . DownloadedInstallerFilename ) ;
IsNewVersionDownloading = ! ( dateChanged | | fileDownloaded ) ;
}
2021-05-21 18:32:34 +08:00
2022-03-18 17:26:29 +08:00
PowerToysUpdatingState = UpdatingSettingsConfig . State ;
PowerToysNewAvailableVersion = UpdatingSettingsConfig . NewVersion ;
PowerToysNewAvailableVersionLink = UpdatingSettingsConfig . ReleasePageLink ;
UpdateCheckedDate = UpdatingSettingsConfig . LastCheckedDateLocalized ;
2021-05-21 18:32:34 +08:00
2022-03-18 17:26:29 +08:00
_isNewVersionChecked = PowerToysUpdatingState = = UpdatingSettings . UpdatingState . UpToDate & & ! IsNewVersionDownloading ;
NotifyPropertyChanged ( nameof ( IsNewVersionCheckedAndUpToDate ) ) ;
2021-05-21 18:32:34 +08:00
2022-03-18 17:26:29 +08:00
NotifyPropertyChanged ( nameof ( IsDownloadAllowed ) ) ;
}
2021-05-21 18:32:34 +08:00
}
2022-11-15 22:11:44 +08:00
/// <summary>
/// Indicates whether any network connection is available
/// Filter virtual network cards.
/// </summary>
/// <returns>
/// <c>true</c> if a network connection is available; otherwise, <c>false</c>.
/// </returns>
public static bool IsNetworkAvailable ( )
{
if ( ! NetworkInterface . GetIsNetworkAvailable ( ) )
{
return false ;
}
foreach ( NetworkInterface ni in NetworkInterface . GetAllNetworkInterfaces ( ) )
{
// discard because of standard reasons
if ( ( ni . OperationalStatus ! = OperationalStatus . Up ) | |
( ni . NetworkInterfaceType = = NetworkInterfaceType . Loopback ) | |
( ni . NetworkInterfaceType = = NetworkInterfaceType . Tunnel ) )
{
continue ;
}
// discard virtual cards (virtual box, virtual pc, etc.)
if ( ni . Description . Contains ( "virtual" , StringComparison . OrdinalIgnoreCase ) | |
ni . Name . Contains ( "virtual" , StringComparison . OrdinalIgnoreCase ) )
{
continue ;
}
// discard "Microsoft Loopback Adapter", it will not show as NetworkInterfaceType.Loopback but as Ethernet Card.
if ( ni . Description . Equals ( "Microsoft Loopback Adapter" , StringComparison . OrdinalIgnoreCase ) )
{
continue ;
}
return true ;
}
return false ;
}
2020-03-12 14:25:24 +08:00
}
}