2020-08-13 02:46:11 +08:00
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
2020-07-10 04:14:53 +08:00
using System ;
using System.Collections.Generic ;
using System.Diagnostics ;
using System.Linq ;
using System.Threading.Tasks ;
2020-08-13 02:46:11 +08:00
using Microsoft.Plugin.Program.Programs ;
using Microsoft.Plugin.Program.Storage ;
using Microsoft.PowerToys.Settings.UI.Lib ;
2020-07-10 04:14:53 +08:00
using Wox.Infrastructure.Logger ;
using Wox.Infrastructure.Storage ;
using Wox.Plugin ;
using Stopwatch = Wox . Infrastructure . Stopwatch ;
namespace Microsoft.Plugin.Program
{
public class Main : IPlugin , IPluginI18n , IContextMenu , ISavable , IReloadable , IDisposable
{
2020-08-12 00:08:44 +08:00
internal static ProgramPluginSettings _settings { get ; set ; }
2020-07-10 04:14:53 +08:00
private static bool IsStartupIndexProgramsRequired = > _settings . LastIndexTime . AddDays ( 3 ) < DateTime . Today ;
private static PluginInitContext _context ;
2020-08-12 00:08:44 +08:00
private readonly PluginJsonStorage < ProgramPluginSettings > _settingsStorage ;
2020-06-27 08:42:06 +08:00
private bool _disposed = false ;
2020-08-12 00:08:44 +08:00
private PackageRepository _packageRepository = new PackageRepository ( new PackageCatalogWrapper ( ) , new BinaryStorage < IList < UWPApplication > > ( "UWP" ) ) ;
2020-07-18 13:32:21 +08:00
private static Win32ProgramFileSystemWatchers _win32ProgramRepositoryHelper ;
private static Win32ProgramRepository _win32ProgramRepository ;
2020-07-10 04:14:53 +08:00
public Main ( )
{
2020-08-12 00:08:44 +08:00
_settingsStorage = new PluginJsonStorage < ProgramPluginSettings > ( ) ;
2020-07-10 04:14:53 +08:00
_settings = _settingsStorage . Load ( ) ;
2020-08-14 06:31:14 +08:00
2020-07-18 13:32:21 +08:00
// This helper class initializes the file system watchers based on the locations to watch
_win32ProgramRepositoryHelper = new Win32ProgramFileSystemWatchers ( ) ;
// Initialize the Win32ProgramRepository with the settings object
2020-08-12 00:08:44 +08:00
_win32ProgramRepository = new Win32ProgramRepository ( _win32ProgramRepositoryHelper . _fileSystemWatchers . Cast < IFileSystemWatcherWrapper > ( ) . ToList ( ) , new BinaryStorage < IList < Programs . Win32Program > > ( "Win32" ) , _settings , _win32ProgramRepositoryHelper . _pathsToWatch ) ;
2020-07-10 04:14:53 +08:00
Stopwatch . Normal ( "|Microsoft.Plugin.Program.Main|Preload programs cost" , ( ) = >
{
2020-07-18 13:32:21 +08:00
_win32ProgramRepository . Load ( ) ;
2020-07-10 04:14:53 +08:00
_packageRepository . Load ( ) ;
} ) ;
2020-07-18 13:32:21 +08:00
Log . Info ( $"|Microsoft.Plugin.Program.Main|Number of preload win32 programs <{_win32ProgramRepository.Count()}>" ) ;
2020-07-10 04:14:53 +08:00
var a = Task . Run ( ( ) = >
{
2020-07-18 13:32:21 +08:00
if ( IsStartupIndexProgramsRequired | | ! _win32ProgramRepository . Any ( ) )
Stopwatch . Normal ( "|Microsoft.Plugin.Program.Main|Win32Program index cost" , _win32ProgramRepository . IndexPrograms ) ;
2020-07-10 04:14:53 +08:00
} ) ;
var b = Task . Run ( ( ) = >
{
if ( IsStartupIndexProgramsRequired | | ! _packageRepository . Any ( ) )
Stopwatch . Normal ( "|Microsoft.Plugin.Program.Main|Win32Program index cost" , _packageRepository . IndexPrograms ) ;
} ) ;
Task . WaitAll ( a , b ) ;
_settings . LastIndexTime = DateTime . Today ;
}
public void Save ( )
{
_settingsStorage . Save ( ) ;
2020-07-18 13:32:21 +08:00
_win32ProgramRepository . Save ( ) ;
2020-07-10 04:14:53 +08:00
_packageRepository . Save ( ) ;
}
public List < Result > Query ( Query query )
{
2020-07-18 13:32:21 +08:00
var results1 = _win32ProgramRepository . AsParallel ( )
2020-07-10 04:14:53 +08:00
. Where ( p = > p . Enabled )
. Select ( p = > p . Result ( query . Search , _context . API ) ) ;
var results2 = _packageRepository . AsParallel ( )
. Where ( p = > p . Enabled )
. Select ( p = > p . Result ( query . Search , _context . API ) ) ;
2020-08-11 07:25:34 +08:00
var result = results1 . Concat ( results2 ) . Where ( r = > r ! = null & & r . Score > 0 ) ;
var maxScore = result . Max ( x = > x . Score ) ;
result = result . Where ( x = > x . Score > _settings . MinScoreThreshold * maxScore ) ;
return result . ToList ( ) ;
2020-07-10 04:14:53 +08:00
}
public void Init ( PluginInitContext context )
{
2020-08-12 00:08:44 +08:00
_context = context ? ? throw new ArgumentNullException ( nameof ( context ) ) ; ;
2020-07-10 04:14:53 +08:00
_context . API . ThemeChanged + = OnThemeChanged ;
UpdateUWPIconPath ( _context . API . GetCurrentTheme ( ) ) ;
}
public void OnThemeChanged ( Theme _ , Theme currentTheme )
{
UpdateUWPIconPath ( currentTheme ) ;
}
public void UpdateUWPIconPath ( Theme theme )
{
2020-08-12 00:08:44 +08:00
foreach ( UWPApplication app in _packageRepository )
2020-07-10 04:14:53 +08:00
{
app . UpdatePath ( theme ) ;
}
}
public void IndexPrograms ( )
{
2020-07-18 13:32:21 +08:00
var t1 = Task . Run ( ( ) = > _win32ProgramRepository . IndexPrograms ( ) ) ;
2020-07-10 04:14:53 +08:00
var t2 = Task . Run ( ( ) = > _packageRepository . IndexPrograms ( ) ) ;
Task . WaitAll ( t1 , t2 ) ;
_settings . LastIndexTime = DateTime . Today ;
}
public string GetTranslatedPluginTitle ( )
{
return _context . API . GetTranslation ( "wox_plugin_program_plugin_name" ) ;
}
public string GetTranslatedPluginDescription ( )
{
return _context . API . GetTranslation ( "wox_plugin_program_plugin_description" ) ;
}
public List < ContextMenuResult > LoadContextMenus ( Result selectedResult )
{
2020-08-14 06:31:14 +08:00
if ( selectedResult = = null )
2020-08-12 00:08:44 +08:00
{
throw new ArgumentNullException ( nameof ( selectedResult ) ) ;
}
2020-07-10 04:14:53 +08:00
var menuOptions = new List < ContextMenuResult > ( ) ;
var program = selectedResult . ContextData as Programs . IProgram ;
if ( program ! = null )
{
menuOptions = program . ContextMenus ( _context . API ) ;
}
return menuOptions ;
}
2020-08-12 00:08:44 +08:00
[System.Diagnostics.CodeAnalysis.SuppressMessage("Design", "CA1031:Do not catch general exception types", Justification = "We want to keep the process alive and show the user a warning message")]
2020-07-10 04:14:53 +08:00
public static void StartProcess ( Func < ProcessStartInfo , Process > runProcess , ProcessStartInfo info )
{
try
{
2020-08-14 06:31:14 +08:00
if ( runProcess = = null )
2020-08-12 00:08:44 +08:00
{
throw new ArgumentNullException ( nameof ( runProcess ) ) ;
}
2020-08-14 06:31:14 +08:00
if ( info = = null )
2020-08-12 00:08:44 +08:00
{
throw new ArgumentNullException ( nameof ( info ) ) ;
}
2020-07-10 04:14:53 +08:00
runProcess ( info ) ;
}
catch ( Exception )
{
var name = "Plugin: Program" ;
var message = $"Unable to start: {info.FileName}" ;
_context . API . ShowMsg ( name , message , string . Empty ) ;
}
}
public void ReloadData ( )
{
IndexPrograms ( ) ;
}
2020-08-12 00:08:44 +08:00
public static void UpdateSettings ( PowerLauncherSettings _ )
2020-07-10 04:14:53 +08:00
{
}
2020-06-27 08:42:06 +08:00
public void Dispose ( )
{
Dispose ( disposing : true ) ;
GC . SuppressFinalize ( this ) ;
}
protected virtual void Dispose ( bool disposing )
{
if ( ! _disposed )
{
if ( disposing )
{
_context . API . ThemeChanged - = OnThemeChanged ;
2020-07-18 13:32:21 +08:00
_win32ProgramRepositoryHelper . Dispose ( ) ;
2020-06-27 08:42:06 +08:00
_disposed = true ;
}
}
}
2020-07-10 04:14:53 +08:00
}
2020-08-13 02:46:11 +08:00
}