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

Support for third party extension #1081

Merged
merged 5 commits into from
Mar 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added assets/logo/Icon-Windows-Linux.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
18 changes: 10 additions & 8 deletions src/app/dev/DevToys.Api/DevToys.Api.csproj
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>$(NetCore)</TargetFrameworks>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
Expand All @@ -11,9 +11,12 @@
<Authors>veler,btiteux</Authors>
<Description>SDK for developing extensions for DevToys 2.0 and higher</Description>
<PackageProjectUrl>https://devtoys.app</PackageProjectUrl>
<RepositoryUrl>https://github.com/veler/DevToys</RepositoryUrl>
<PackageTags>devtoys</PackageTags>
<RepositoryUrl>https://github.com/DevToys-app/DevToys</RepositoryUrl>
<PackageTags>devtoys-app</PackageTags>
<PackageLicenseFile>LICENSE.md</PackageLicenseFile>
<PackageReadmeFile>README.md</PackageReadmeFile>
<DevelopmentDependency>true</DevelopmentDependency>
<PackageIcon>Icon-Windows-Linux.png</PackageIcon>
</PropertyGroup>

<ItemGroup>
Expand All @@ -23,15 +26,14 @@
<PackageReference Include="OneOf" />
<PackageReference Include="System.ComponentModel.Composition" />
<PackageReference Include="System.Threading.Tasks.Extensions" />
<PackageReference Include="SixLabors.ImageSharp"/>
<PackageReference Include="SixLabors.ImageSharp" />
</ItemGroup>

<ItemGroup>
<None Include="$(AssemblyName).props" Pack="true" PackagePath="build" />
<None Include="$(RepoRoot)LICENSE.md" Link="LICENSE.md">
<Pack>True</Pack>
<PackagePath>\</PackagePath>
</None>
<None Include="README.md" Pack="true" PackagePath="\" />
<None Include="$(RepoRoot)LICENSE.md" Link="LICENSE.md" Pack="true" PackagePath="\" />
<None Include="$(RepoRoot)assets\logo\Icon-Windows-Linux.png" Link="Icon-Windows-Linux.png" Pack="true" PackagePath="" />
</ItemGroup>

<ItemGroup>
Expand Down
5 changes: 5 additions & 0 deletions src/app/dev/DevToys.Api/DevToys.Api.props
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
<Project>
<PropertyGroup>
<!-- See https://learn.microsoft.com/en-us/dotnet/core/project-sdk/msbuild-props#enabledynamicloading -->
<EnableDynamicLoading>true</EnableDynamicLoading>

<!-- Make any NuGet using DevToys.API to have the tag "devtoys-app" so we can find every published extensions on Nuget.org through this tag. -->
<PackageTags>devtoys-app $(PackageTags)</PackageTags>
</PropertyGroup>
</Project>
1 change: 1 addition & 0 deletions src/app/dev/DevToys.Api/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Build an extension for [DevToys](https://devtoys.app).
veler marked this conversation as resolved.
Show resolved Hide resolved
2 changes: 1 addition & 1 deletion src/app/dev/DevToys.Blazor/Pages/Index.razor
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@
<FontIcon FontFamily="@item.ToolInstance.IconFontName" Glyph="@item.ToolInstance.IconGlyph" />
</div>
<div class="sidebar-searchbar-result-item-text">
<TextBlock NoWrap="true" Text="@item.ToolInstance.LongDisplayTitle" HighlightedSpans="@item.MatchedSpans" />
<TextBlock NoWrap="true" Text="@item.ToolInstance.LongOrShortDisplayTitle" HighlightedSpans="@item.MatchedSpans" />
</div>
</div>
</SearchResultItemTemplate>
Expand Down
12 changes: 9 additions & 3 deletions src/app/dev/DevToys.Blazor/Pages/SubPages/ToolPage.razor
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

<ScrollViewer @ref=_scrollViewer
Class="entrance-theme-transition tool-page-content"
IsScrollable="@(!IsInFullScreenMode && ViewModel.ToolView.IsScrollable)">
IsScrollable="@(!IsInFullScreenMode && ViewModel.ToolView is not null && ViewModel.ToolView.IsScrollable)">
@RenderToolWithHeader(true)
</ScrollViewer>

Expand All @@ -15,15 +15,15 @@
{
UIDialogService.DialogContent = (__builder) =>
{
@if (ViewModel.ToolView.CurrentOpenedDialog is not null)
@if (ViewModel.ToolView?.CurrentOpenedDialog is not null)
{
<UIElementPresenter UIElement="@ViewModel.ToolView.CurrentOpenedDialog.DialogContent" />
}
};

UIDialogService.FooterContent = (__builder) =>
{
@if (ViewModel.ToolView.CurrentOpenedDialog is not null)
@if (ViewModel.ToolView?.CurrentOpenedDialog is not null)
{
<UIElementPresenter UIElement="@ViewModel.ToolView.CurrentOpenedDialog.FooterContent" />
}
Expand Down Expand Up @@ -62,6 +62,12 @@
<TextBlock Text="@ViewModel.GetFavoriteButtonText(ViewModel.IsSelectedMenuItemAFavoriteTool)" />
</StackPanel>
</Button>
<Button IsVisible="@Debugger.IsAttached"
Appearance="ButtonAppearance.Stealth"
ToolTip="Hot reload"
@onclick="@OnHotReloadButtonClick">
<FontIcon Glyph="@('\uEF68')" Style="color: red;" />
</Button>
</StackPanel>
</GridCell>

Expand Down
7 changes: 7 additions & 0 deletions src/app/dev/DevToys.Blazor/Pages/SubPages/ToolPage.razor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ private void ToolView_PropertyChanged(object? sender, PropertyChangedEventArgs e

private void ToolView_CurrentOpenedDialogChanged(object? sender, EventArgs e)
{
Guard.IsNotNull(ViewModel.ToolView);
if (ViewModel.ToolView.CurrentOpenedDialog is null)
{
UIDialogService.CloseDialog();
Expand All @@ -103,6 +104,7 @@ private void ToolView_CurrentOpenedDialogChanged(object? sender, EventArgs e)

private void DialogService_CloseDialogRequested(object? sender, EventArgs e)
{
Guard.IsNotNull(ViewModel.ToolView);
if (ViewModel.ToolView.CurrentOpenedDialog is not null)
{
ViewModel.ToolView.CurrentOpenedDialog.IsOpenedChanged -= DialogService_CloseDialogRequested;
Expand All @@ -128,4 +130,9 @@ private void OnHotReloadRequestUpdateApplication(object? sender, HotReloadEventA
{
ViewModel.RebuildViewCommand.Execute(null);
}

private void OnHotReloadButtonClick()
{
ViewModel.RebuildViewCommand.Execute(null);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ namespace DevToys.Business.Services;
[Export]
internal sealed class CommandLineLauncherService : ObservableRecipient
{
internal const string ToolArgument = "--tool:";
internal const string ToolArgument = "tool";

private readonly GuiToolProvider _guiToolProvider;
private readonly IMefProvider _mefProvider;
Expand All @@ -25,9 +25,9 @@ public CommandLineLauncherService(GuiToolProvider guiToolProvider, IMefProvider

internal void HandleCommandLineArguments()
{
if (Environment.CommandLine.Contains(ToolArgument))
string toolName = AppHelper.GetCommandLineArgument(ToolArgument);
if (!string.IsNullOrEmpty(toolName))
{
string toolName = Environment.CommandLine.Substring(Environment.CommandLine.IndexOf(ToolArgument) + ToolArgument.Length);
GuiToolInstance? tool = _guiToolProvider.GetToolFromInternalName(toolName);
if (tool is not null)
{
Expand All @@ -44,7 +44,7 @@ internal void LaunchTool(string toolInternalName)
if (tool is not null)
{
string appStartExe = Process.GetCurrentProcess().MainModule!.FileName;
OSHelper.OpenFileInShell(appStartExe, $"{ToolArgument}{toolInternalName}");
OSHelper.OpenFileInShell(appStartExe, $"--{ToolArgument}:\"{toolInternalName}\"");
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ internal sealed partial class ToolPageViewModel : ObservableRecipient
/// <summary>
/// Gets the UI of the tool.
/// </summary>
internal UIToolView ToolView
internal UIToolView? ToolView
{
get
{
Expand Down
53 changes: 53 additions & 0 deletions src/app/dev/DevToys.Core/AppHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,57 @@ var assemblyInformationalVersion
.GetCustomAttribute(typeof(AssemblyInformationalVersionAttribute))!;
return assemblyInformationalVersion.InformationalVersion.Contains("pre", StringComparison.CurrentCultureIgnoreCase);
});

/// <summary>
/// Gets the value of the specified command line argument.
/// </summary>
/// <param name="argumentName">The name of the argument. The name will be interpreted as "--name:". The string should not contains "--" and ":".</param>
/// <returns>The argument value or <see cref="string.Empty"/> if not found.</returns>
/// <remarks>
/// This method will search for the argument in the command line arguments. The search is case-insensitive.
/// Arguments must be like `--name:value` or `--name: value` or `--name: "value with space"`.
/// </remarks>
public static string GetCommandLineArgument(string argumentName)
{
return GetCommandLineArgument(Environment.GetCommandLineArgs(), argumentName);
}

/// <summary>
/// Gets the value of the specified command line argument.
/// </summary>
/// <param name="arguments">The list of command line arguments</param>
/// <param name="argumentName">The name of the argument. The name will be interpreted as "--name:". The string should not contains "--" and ":".</param>
/// <returns>The argument value or <see cref="string.Empty"/> if not found.</returns>
/// <remarks>
/// This method will search for the argument in the command line arguments. The search is case-insensitive.
/// Arguments must be like `--name:value` or `--name: value` or `--name: "value with space"`.
/// </remarks>
public static string GetCommandLineArgument(string[] arguments, string argumentName)
{
Guard.IsNotNull(arguments);
Guard.IsNotNullOrWhiteSpace(argumentName);

argumentName = $"--{argumentName}:";
for (int i = 0; i < arguments.Length; i++)
{
string argument = arguments[i];
if (argument.StartsWith(argumentName, StringComparison.OrdinalIgnoreCase))
{
if (argument.Length == argumentName.Length)
{
if (i + 1 < arguments.Length)
{
return arguments[i + 1].Trim('\"');
}

return string.Empty;
}
else
{
return argument.Substring(argumentName.Length).Trim('\"');
}
}
}
return string.Empty;
}
}
15 changes: 10 additions & 5 deletions src/app/dev/DevToys.Core/Mef/MefComposer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,12 @@ namespace DevToys.Core.Mef;
/// </summary>
public sealed partial class MefComposer : IDisposable
{
private const string ExtraPluginArgument = "extraplugin";

private readonly ILogger _logger;
private readonly Assembly[] _assemblies;
private readonly string[]? _pluginFolders;
private readonly string _extraPlugin;
private readonly object[] _customExports;
private bool _isExportProviderDisposed = true;

Expand All @@ -21,13 +24,10 @@ public sealed partial class MefComposer : IDisposable

public MefComposer(Assembly[]? assemblies = null, string[]? pluginFolders = null, params object[] customExports)
{
if (Provider is not null)
{
throw new InvalidOperationException("Mef composer already initialized.");
}

_logger = this.Log();

_extraPlugin = AppHelper.GetCommandLineArgument(ExtraPluginArgument);

_assemblies = assemblies ?? Array.Empty<Assembly>();
_pluginFolders = pluginFolders;
_customExports = customExports ?? Array.Empty<object>();
Expand Down Expand Up @@ -127,6 +127,11 @@ private IEnumerable<string> GetPotentialPluginFolders()
pluginFolders = new[] { Path.Combine(appFolder!, "Plugins") };
}

if (!string.IsNullOrWhiteSpace(_extraPlugin) && Directory.Exists(_extraPlugin))
{
yield return _extraPlugin;
}

for (int i = 0; i < pluginFolders.Length; i++)
{
string pluginFolder = pluginFolders[i];
Expand Down
8 changes: 4 additions & 4 deletions src/app/dev/DevToys.Core/Tools/GuiToolInstance.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ namespace DevToys.Core.Tools;
[DebuggerDisplay($"InternalComponentName = {{{nameof(InternalComponentName)}}}")]
public sealed partial class GuiToolInstance : ObservableObject, IDisposable
{
private Lazy<UIToolView> _view;
private Lazy<UIToolView?> _view;
private readonly ILogger _logger;
private readonly Lazy<IGuiTool, GuiToolMetadata> _guiToolDefinition;
private readonly Lazy<IGuiTool> _instance;
Expand Down Expand Up @@ -79,7 +79,7 @@ internal GuiToolInstance(Lazy<IGuiTool, GuiToolMetadata> guiToolDefinition, Asse
/// Gets the view of the tool.
/// Calling this property is expensive the first time as it will create the instance of the tool and the instance of the view.
/// </summary>
public UIToolView View => _view.Value;
public UIToolView? View => _view.Value;

public void Dispose()
{
Expand Down Expand Up @@ -124,7 +124,7 @@ public void RebuildView()
{
if (_view is not null && _view.IsValueCreated)
{
_view.Value.CurrentOpenedDialog?.Dispose();
_view.Value?.CurrentOpenedDialog?.Dispose();
}

_view
Expand All @@ -133,7 +133,7 @@ public void RebuildView()
Exception? exception = null;
try
{
return _instance.Value.View;
return _instance.Value?.View;
}
catch (NotImplementedException) { }
catch (Exception ex)
Expand Down
5 changes: 2 additions & 3 deletions src/app/dev/DevToys.Core/Tools/GuiToolProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -339,8 +339,7 @@ public void SearchTools(string searchQuery, ObservableCollection<GuiToolViewItem
{
GuiToolInstance tool = AllTools[i];

if (!tool.NotSearchable // do not search tools marked as non-searchable
&& !string.IsNullOrWhiteSpace(tool.LongDisplayTitle)) // do not search tools without long display name.
if (!tool.NotSearchable) // do not search tools marked as non-searchable
{
SearchTool(searchQueries, tool, out TextSpan[] matchedSpans, out double weight);

Expand Down Expand Up @@ -659,7 +658,7 @@ private static void SearchTool(string[] searchQueries, GuiToolInstance tool, out
weight = 0;
foreach (string? query in searchQueries)
{
WeightMatch(query, tool.LongDisplayTitle, out double titleWeight, out IReadOnlyList<TextSpan> spans);
WeightMatch(query, tool.LongOrShortDisplayTitle, out double titleWeight, out IReadOnlyList<TextSpan> spans);
WeightMatch(query, tool.SearchKeywords, out double searchKeywordsWeight, out _);
WeightMatch(query, tool.Description, out double descriptionWeight, out _);

Expand Down
12 changes: 2 additions & 10 deletions src/app/dev/platforms/desktop/DevToys.MacOS/DevToys.MacOS.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,8 @@
<EnableDefaultCssItems>false</EnableDefaultCssItems>
<DefineConstants>$(DefineConstants);__MACOS__</DefineConstants>

<!-- The default runtime is osx-x64, except in Release config, in which case the default is osx-x64;osx-arm64.
When specifying both architectures, use the plural <RuntimeIdentifiers> instead of the singular <RuntimeIdentifer>.
The App Store will NOT accept apps with ONLY osx-arm64 indicated;
either BOTH runtimes must be indicated or ONLY osx-x64. -->
<!-- ex. <RuntimeIdentifiers>osx-x64;osx-arm64</RuntimeIdentifiers> -->

<!-- The following 3 properties disable trimming and AOT. This allow us to load plugins at runtime. -->
<!-- <UseInterpreter>true</UseInterpreter>
<MtouchLink>None</MtouchLink>
<MtouchInterpreter>all</MtouchInterpreter> -->
<!-- The following property disable trimming and AOT. This allow us to load plugins at runtime. -->
<LinkMode>None</LinkMode>

<ApplicationId>com.devtoys</ApplicationId>
</PropertyGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ private static void AddToolToJumpList(JumpList jumpList, GuiToolInstance tool, s
Title = tool.LongOrShortDisplayTitle,
Description = tool.Description,
CustomCategory = category,
Arguments = $"{CommandLineLauncherService.ToolArgument}{tool.InternalComponentName}"
Arguments = $"--{CommandLineLauncherService.ToolArgument}:\"{tool.InternalComponentName}\""
};

jumpList.JumpItems.Add(jumpTask);
Expand Down
18 changes: 18 additions & 0 deletions src/app/tests/DevToys.UnitTests/Core/AppHelperTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
using DevToys.Core;

namespace DevToys.UnitTests.Core;

public class AppHelperTests
{
[Theory]
[InlineData(new[] { "" }, "tool", "")]
[InlineData(new[] { "tool" }, "tool", "")]
[InlineData(new[] { "--tool:" }, "tool", "")]
[InlineData(new[] { "--tool:value" }, "tool", "value")]
[InlineData(new[] { "--tool:", "value" }, "tool", "value")]
[InlineData(new[] { "--tool:", "\"value with space\"" }, "tool", "value with space")]
public void GetCommandLineArgument(string[] arguments, string searchedArgumentName, string expectedResult)
{
AppHelper.GetCommandLineArgument(arguments, searchedArgumentName).Should().Be(expectedResult);
}
}
Loading