Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Port All Apps plugin again #409

Open
wants to merge 12 commits into
base: main
Choose a base branch
from
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,11 @@
// See the LICENSE file in the project root for more information.

using System.Linq;
using Microsoft.CmdPal.Ext.Apps.Properties;
using Microsoft.CommandPalette.Extensions;
using Microsoft.CommandPalette.Extensions.Toolkit;

namespace Microsoft.CmdPal.Ext.Apps.Programs;
namespace Microsoft.CmdPal.Ext.Apps;

public partial class AllAppsCommandProvider : CommandProvider
{
Expand All @@ -17,10 +18,10 @@ public partial class AllAppsCommandProvider : CommandProvider
public AllAppsCommandProvider()
{
Id = "AllApps";
DisplayName = "Installed apps";
DisplayName = Resources.installed_apps;
Icon = new IconInfo("\ue71d");

_listItem = new(Page) { Subtitle = "Search installed apps" };
_listItem = new(Page) { Subtitle = Resources.search_installed_apps };
}

public override ICommandItem[] TopLevelCommands() => [_listItem];
Expand Down
87 changes: 52 additions & 35 deletions src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Apps/AllAppsPage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,82 +2,99 @@
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.CmdPal.Ext.Apps.Programs;
using Microsoft.CmdPal.Ext.Apps.Properties;
using Microsoft.CmdPal.Ext.Apps.Storage;
using Microsoft.CmdPal.Ext.Apps.Utils;
using Microsoft.CommandPalette.Extensions;
using Microsoft.CommandPalette.Extensions.Toolkit;

namespace Microsoft.CmdPal.Ext.Apps.Programs;
namespace Microsoft.CmdPal.Ext.Apps;

public sealed partial class AllAppsPage : ListPage
{
private IListItem[] allAppsSection = [];

private object l = new();

public AllAppsPage()
{
StringMatcher.Instance = new StringMatcher();
this.Name = "All Apps";
this.Name = Resources.all_apps;
this.Icon = new IconInfo("\ue71d");
this.ShowDetails = true;
this.IsLoading = true;
this.PlaceholderText = "Search installed apps...";
this.PlaceholderText = Resources.search_installed_apps_placeholder;

Task.Run(() =>
{
lock (l)
{
this.allAppsSection = GetPrograms()
.Select((app) => new AppListItem(app))
.ToArray();

this.IsLoading = false;
}
});
}

public override IListItem[] GetItems()
{
if (this.allAppsSection == null || allAppsSection.Length == 0)
if (this.allAppsSection == null || allAppsSection.Length == 0 || AppCache.Instance.Value.ShouldReload())
{
var apps = GetPrograms();
this.IsLoading = false;
this.allAppsSection = apps
.Select((app) => new AppListItem(app))
.ToArray();
lock (l)
{
this.IsLoading = true;

var apps = GetPrograms();
this.allAppsSection = apps
.Select((app) => new AppListItem(app))
.ToArray();

this.IsLoading = false;

AppCache.Instance.Value.ResetReloadFlag();
}
}

return allAppsSection;
}

internal static List<AppItem> GetPrograms()
internal List<AppItem> GetPrograms()
{
// NOTE TO SELF:
//
// There's logic in Win32Program.All() here to pick the "sources" for programs.
// I've manually hardcoded it to:
// * StartMenuProgramPaths
// * DesktopProgramPaths
// * RegistryAppProgramPaths
// for now. I've disabled the "PATH" source too, because it's n o i s y
//
// This also doesn't include Packaged apps, cause they're enumerated entirely separately.
var cache = AppCache.Instance.Value;
var uwps = cache.UWPs;
var win32s = cache.Win32s;
var uwpResults = uwps
.Where((application) => application.Enabled /*&& application.Valid*/)
var uwpResults = AppCache.Instance.Value.UWPs
.Where((application) => application.Enabled)
.Select(app =>
new AppItem
new AppItem()
{
Name = app.Name,
Subtitle = app.Description,
Type = UWPApplication.Type(),
IcoPath = app.LogoType != LogoType.Error ? app.LogoPath : string.Empty,
DirPath = app.Location,
UserModelId = app.UserModelId,

// ExePath = app.FullPath,
IsPackaged = true,
Commands = app.GetCommands(),
});
var win32Results = win32s
.Where((application) => application.Enabled /*&& application.Valid*/)

var win32Results = AppCache.Instance.Value.Win32s
.Where((application) => application.Enabled && application.Valid)
.Select(app =>
{
return new AppItem
return new AppItem()
{
Name = app.Name,
Subtitle = app.Description,
IcoPath = app.AppType == Win32Program.ApplicationType.InternetShortcutApplication ?
app.IcoPath :
app.FullPath,
Type = app.Type(),
IcoPath = app.IcoPath,
ExePath = !string.IsNullOrEmpty(app.LnkFilePath) ? app.LnkFilePath : app.FullPath,
DirPath = app.Location,
Commands = app.GetCommands(),
};
});

Expand Down
82 changes: 76 additions & 6 deletions src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Apps/AppCache.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,87 @@

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.CmdPal.Ext.Apps.Programs;
using Microsoft.CmdPal.Ext.Apps.Storage;
using Microsoft.CmdPal.Ext.Apps.Utils;

namespace Microsoft.CmdPal.Ext.Apps.Programs;
namespace Microsoft.CmdPal.Ext.Apps;

public sealed class AppCache
public sealed class AppCache : IDisposable
{
private readonly IList<Win32Program> _win32s = Win32Program.All();
private readonly IList<UWPApplication> _uwps = UWP.All();
private Win32ProgramFileSystemWatchers _win32ProgramRepositoryHelper;

public IList<Win32Program> Win32s => _win32s;
private PackageRepository _packageRepository;

public IList<UWPApplication> UWPs => _uwps;
private Win32ProgramRepository _win32ProgramRepository;

private bool _disposed;

public IList<Win32Program> Win32s => _win32ProgramRepository.Items;

public IList<UWPApplication> UWPs => _packageRepository.Items;

public static readonly Lazy<AppCache> Instance = new(() => new());

public AppCache()
{
_win32ProgramRepositoryHelper = new Win32ProgramFileSystemWatchers();
_win32ProgramRepository = new Win32ProgramRepository(_win32ProgramRepositoryHelper.FileSystemWatchers.Cast<IFileSystemWatcherWrapper>().ToList(), AllAppsSettings.Instance, _win32ProgramRepositoryHelper.PathsToWatch);

_packageRepository = new PackageRepository(new PackageCatalogWrapper());

var a = Task.Run(() =>
{
_win32ProgramRepository.IndexPrograms();
});

var b = Task.Run(() =>
{
_packageRepository.IndexPrograms();
UpdateUWPIconPath(ThemeHelper.GetCurrentTheme());
});

Task.WaitAll(a, b);

AllAppsSettings.Instance.LastIndexTime = DateTime.Today;
}

private void UpdateUWPIconPath(Theme theme)
{
if (_packageRepository != null)
{
foreach (UWPApplication app in _packageRepository)
{
app.UpdateLogoPath(theme);
}
}
}

public bool ShouldReload() => _packageRepository.ShouldReload() || _win32ProgramRepository.ShouldReload();

public void ResetReloadFlag()
{
_packageRepository.ResetReloadFlag();
_win32ProgramRepository.ResetReloadFlag();
}

public void Dispose()
{
Dispose(disposing: true);
GC.SuppressFinalize(this);
}

private void Dispose(bool disposing)
{
if (!_disposed)
{
if (disposing)
{
_win32ProgramRepositoryHelper?.Dispose();
_disposed = true;
}
}
}
}
12 changes: 11 additions & 1 deletion src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Apps/AppItem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,20 @@
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

namespace Microsoft.CmdPal.Ext.Apps.Programs;
using System.Collections.Generic;
using Microsoft.CmdPal.Ext.Apps.Programs;
using Microsoft.CommandPalette.Extensions.Toolkit;

namespace Microsoft.CmdPal.Ext.Apps;

internal sealed class AppItem
{
public string Name { get; set; } = string.Empty;

public string Subtitle { get; set; } = string.Empty;

public string Type { get; set; } = string.Empty;

public string IcoPath { get; set; } = string.Empty;

public string ExePath { get; set; } = string.Empty;
Expand All @@ -18,6 +24,10 @@ internal sealed class AppItem

public string UserModelId { get; set; } = string.Empty;

public bool IsPackaged { get; set; }

public List<CommandContextItem>? Commands { get; set; }

public AppItem()
{
}
Expand Down
22 changes: 3 additions & 19 deletions src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Apps/AppListItem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using Microsoft.CmdPal.Ext.Apps.Programs;
using Microsoft.CommandPalette.Extensions.Toolkit;

namespace Microsoft.CmdPal.Ext.Apps.Programs;
Expand All @@ -10,7 +11,6 @@ internal sealed partial class AppListItem : ListItem
{
private readonly AppItem _app;
private static readonly Tag _appTag = new("App");
private static readonly IconInfo _openPathIcon = new IconInfo("\ue838");

public AppListItem(AppItem app)
: base(new AppCommand(app))
Expand All @@ -24,25 +24,9 @@ public AppListItem(AppItem app)
{
Title = this.Title,
HeroImage = ((AppCommand)Command!).Icon ?? new IconInfo(string.Empty),
Body = "### App",
Body = "### " + app.Type,
stefansjfw marked this conversation as resolved.
Show resolved Hide resolved
};

if (string.IsNullOrEmpty(app.UserModelId))
{
// Win32 exe or other non UWP app
MoreCommands = [
new CommandContextItem(
new OpenPathCommand(app.DirPath)
{
Name = "Open location",
Icon = _openPathIcon,
})
];
}
else
{
// UWP app
MoreCommands = [];
}
MoreCommands = _app.Commands!.ToArray();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,8 @@
<OutputPath>$(SolutionDir)$(Platform)\$(Configuration)\WinUI3Apps\CmdPal</OutputPath>
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
<AppendRuntimeIdentifierToOutputPath>false</AppendRuntimeIdentifierToOutputPath>
<!-- MRT from windows app sdk will search for a pri file with the same name of the module before defaulting to resources.pri -->
<ProjectPriFileName>Microsoft.CmdPal.Ext.Apps.pri</ProjectPriFileName>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="System.IO.Abstractions" />
<PackageReference Include="Microsoft.Windows.CsWin32">
Expand All @@ -18,4 +17,19 @@

<ProjectReference Include="..\..\extensionsdk\Microsoft.CommandPalette.Extensions.Toolkit\Microsoft.CommandPalette.Extensions.Toolkit.csproj" />
</ItemGroup>

<ItemGroup>
<Compile Update="Properties\Resources.Designer.cs">
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
<DependentUpon>Resources.resx</DependentUpon>
</Compile>
</ItemGroup>

<ItemGroup>
<EmbeddedResource Update="Properties\Resources.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
</EmbeddedResource>
</ItemGroup>
</Project>
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using System.Collections.Generic;
using System.Runtime.InteropServices;
using Windows.Win32.System.Com;
using static Microsoft.CmdPal.Ext.Apps.Utils.Native;

namespace Microsoft.CmdPal.Ext.Apps.Programs;

Expand Down Expand Up @@ -32,10 +33,9 @@ internal static IEnumerable<IAppxManifestApplication> GetAppsFromManifest(IStrea
}
}

public static T CheckHRAndReturnOrThrow<T>(int hr, T result)
internal static T CheckHRAndReturnOrThrow<T>(HRESULT hr, T result)
{
// HRESULT.S_OK
if (hr != 0)
if (hr != HRESULT.S_OK)
{
Marshal.ThrowExceptionForHR((int)hr);
}
Expand Down
Loading
Loading