Skip to content
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
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using Flow.Launcher.Infrastructure.Http;
using Flow.Launcher.Infrastructure.Logger;
using Flow.Launcher.Plugin;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Needed?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Needed?

Record class UserPlugin is moved to Flow.Launcher.Plugin, so we need to use this namespace here

using System;
using System.Collections.Generic;
using System.Net;
Expand Down
1 change: 1 addition & 0 deletions Flow.Launcher.Core/ExternalPlugins/CommunityPluginStore.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Flow.Launcher.Plugin;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Needed?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Needed?

Record class UserPlugin is moved to Flow.Launcher.Plugin, so we need to use this namespace here


namespace Flow.Launcher.Core.ExternalPlugins
{
Expand Down
11 changes: 6 additions & 5 deletions Flow.Launcher.Core/ExternalPlugins/PluginsManifest.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
using Flow.Launcher.Infrastructure.Logger;
using System;
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using CommunityToolkit.Mvvm.DependencyInjection;
using Flow.Launcher.Plugin;

namespace Flow.Launcher.Core.ExternalPlugins
{
Expand All @@ -17,11 +18,11 @@ public static class PluginsManifest
private static readonly SemaphoreSlim manifestUpdateLock = new(1);

private static DateTime lastFetchedAt = DateTime.MinValue;
private static TimeSpan fetchTimeout = TimeSpan.FromMinutes(2);
private static readonly TimeSpan fetchTimeout = TimeSpan.FromMinutes(2);

public static List<UserPlugin> UserPlugins { get; private set; }

public static async Task<bool> UpdateManifestAsync(CancellationToken token = default, bool usePrimaryUrlOnly = false)
public static async Task<bool> UpdateManifestAsync(bool usePrimaryUrlOnly = false, CancellationToken token = default)
{
try
{
Expand All @@ -43,7 +44,7 @@ public static async Task<bool> UpdateManifestAsync(CancellationToken token = def
}
catch (Exception e)
{
Log.Exception($"|PluginsManifest.{nameof(UpdateManifestAsync)}|Http request failed", e);
Ioc.Default.GetRequiredService<IPublicAPI>().LogException(nameof(PluginsManifest), "Http request failed", e);
}
finally
{
Expand Down
23 changes: 0 additions & 23 deletions Flow.Launcher.Core/ExternalPlugins/UserPlugin.cs

This file was deleted.

43 changes: 16 additions & 27 deletions Flow.Launcher.Core/Plugin/PluginManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -454,34 +454,23 @@ private static bool SameOrLesserPluginVersionExists(string metadataPath)

#region Public functions

public static bool PluginModified(string uuid)
public static bool PluginModified(string id)
{
return _modifiedPlugins.Contains(uuid);
return _modifiedPlugins.Contains(id);
}


/// <summary>
/// Update a plugin to new version, from a zip file. By default will remove the zip file if update is via url,
/// unless it's a local path installation
/// </summary>
public static async Task UpdatePluginAsync(PluginMetadata existingVersion, UserPlugin newVersion, string zipFilePath)
{
InstallPlugin(newVersion, zipFilePath, checkModified:false);
await UninstallPluginAsync(existingVersion, removePluginFromSettings:false, removePluginSettings:false, checkModified: false);
_modifiedPlugins.Add(existingVersion.ID);
}

/// <summary>
/// Install a plugin. By default will remove the zip file if installation is from url, unless it's a local path installation
/// </summary>
public static void InstallPlugin(UserPlugin plugin, string zipFilePath)
{
InstallPlugin(plugin, zipFilePath, checkModified: true);
}

/// <summary>
/// Uninstall a plugin.
/// </summary>
public static async Task UninstallPluginAsync(PluginMetadata plugin, bool removePluginFromSettings = true, bool removePluginSettings = false)
{
await UninstallPluginAsync(plugin, removePluginFromSettings, removePluginSettings, true);
Expand Down Expand Up @@ -525,20 +514,20 @@ internal static void InstallPlugin(UserPlugin plugin, string zipFilePath, bool c
var folderName = string.IsNullOrEmpty(plugin.Version) ? $"{plugin.Name}-{Guid.NewGuid()}" : $"{plugin.Name}-{plugin.Version}";

var defaultPluginIDs = new List<string>
{
"0ECADE17459B49F587BF81DC3A125110", // BrowserBookmark
"CEA0FDFC6D3B4085823D60DC76F28855", // Calculator
"572be03c74c642baae319fc283e561a8", // Explorer
"6A122269676E40EB86EB543B945932B9", // PluginIndicator
"9f8f9b14-2518-4907-b211-35ab6290dee7", // PluginsManager
"b64d0a79-329a-48b0-b53f-d658318a1bf6", // ProcessKiller
"791FC278BA414111B8D1886DFE447410", // Program
"D409510CD0D2481F853690A07E6DC426", // Shell
"CEA08895D2544B019B2E9C5009600DF4", // Sys
"0308FD86DE0A4DEE8D62B9B535370992", // URL
"565B73353DBF4806919830B9202EE3BF", // WebSearch
"5043CETYU6A748679OPA02D27D99677A" // WindowsSettings
};
{
"0ECADE17459B49F587BF81DC3A125110", // BrowserBookmark
"CEA0FDFC6D3B4085823D60DC76F28855", // Calculator
"572be03c74c642baae319fc283e561a8", // Explorer
"6A122269676E40EB86EB543B945932B9", // PluginIndicator
"9f8f9b14-2518-4907-b211-35ab6290dee7", // PluginsManager
"b64d0a79-329a-48b0-b53f-d658318a1bf6", // ProcessKiller
"791FC278BA414111B8D1886DFE447410", // Program
"D409510CD0D2481F853690A07E6DC426", // Shell
"CEA08895D2544B019B2E9C5009600DF4", // Sys
"0308FD86DE0A4DEE8D62B9B535370992", // URL
"565B73353DBF4806919830B9202EE3BF", // WebSearch
"5043CETYU6A748679OPA02D27D99677A" // WindowsSettings
};

// Treat default plugin differently, it needs to be removable along with each flow release
var installDirectory = !defaultPluginIDs.Any(x => x == plugin.ID)
Expand Down
57 changes: 57 additions & 0 deletions Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs
Original file line number Diff line number Diff line change
Expand Up @@ -344,5 +344,62 @@ public interface IPublicAPI
/// Stop the loading bar in main window
/// </summary>
public void StopLoadingBar();

/// <summary>
/// Update the plugin manifest
/// </summary>
/// <param name="usePrimaryUrlOnly">
/// FL has multiple urls to download the plugin manifest. Set this to true to only use the primary url.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Have we added support for multiple manifest urls or are they just mirrors?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just mirrors

image

/// </param>
/// <param name="token"></param>
/// <returns>True if the manifest is updated successfully, false otherwise</returns>
public Task<bool> UpdatePluginManifestAsync(bool usePrimaryUrlOnly = false, CancellationToken token = default);

/// <summary>
/// Get the plugin manifest
/// </summary>
/// <returns></returns>
public IReadOnlyList<UserPlugin> GetPluginManifest();

/// <summary>
/// Check if the plugin has been modified.
/// If this plugin is updated, installed or uninstalled and users do not restart the app,
/// it will be marked as modified
/// </summary>
/// <param name="id">Plugin id</param>
/// <returns></returns>
public bool PluginModified(string id);

/// <summary>
/// Update a plugin to new version, from a zip file. By default will remove the zip file if update is via url,
/// unless it's a local path installation
/// </summary>
/// <param name="pluginMetadata">The metadata of the old plugin to update</param>
/// <param name="plugin">The new plugin to update</param>
/// <param name="zipFilePath">
/// Path to the zip file containing the plugin. It will be unzipped to the temporary directory, removed and installed.
/// </param>
/// <returns></returns>
public Task UpdatePluginAsync(PluginMetadata pluginMetadata, UserPlugin plugin, string zipFilePath);

/// <summary>
/// Install a plugin. By default will remove the zip file if installation is from url,
/// unless it's a local path installation
/// </summary>
/// <param name="plugin">The plugin to install</param>
/// <param name="zipFilePath">
/// Path to the zip file containing the plugin. It will be unzipped to the temporary directory, removed and installed.
/// </param>
public void InstallPlugin(UserPlugin plugin, string zipFilePath);

/// <summary>
/// Uninstall a plugin
/// </summary>
/// <param name="pluginMetadata">The metadata of the plugin to uninstall</param>
/// <param name="removePluginSettings">
/// Plugin has their own settings. If this is set to true, the plugin settings will be removed.
/// </param>
/// <returns></returns>
public Task UninstallPluginAsync(PluginMetadata pluginMetadata, bool removePluginSettings = false);
}
}
80 changes: 80 additions & 0 deletions Flow.Launcher.Plugin/UserPlugin.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
using System;

namespace Flow.Launcher.Plugin
{
/// <summary>
/// User Plugin Model for Flow Launcher
/// </summary>
public record UserPlugin
{
/// <summary>
/// Unique identifier of the plugin
/// </summary>
public string ID { get; set; }

/// <summary>
/// Name of the plugin
/// </summary>
public string Name { get; set; }

/// <summary>
/// Description of the plugin
/// </summary>
public string Description { get; set; }

/// <summary>
/// Author of the plugin
/// </summary>
public string Author { get; set; }

/// <summary>
/// Version of the plugin
/// </summary>
public string Version { get; set; }

/// <summary>
/// Allow language of the plugin <see cref="AllowedLanguage"/>
/// </summary>
public string Language { get; set; }

/// <summary>
/// Website of the plugin
/// </summary>
public string Website { get; set; }

/// <summary>
/// URL to download the plugin
/// </summary>
public string UrlDownload { get; set; }

/// <summary>
/// URL to the source code of the plugin
/// </summary>
public string UrlSourceCode { get; set; }

/// <summary>
/// Local path where the plugin is installed
/// </summary>
public string LocalInstallPath { get; set; }

/// <summary>
/// Icon path of the plugin
/// </summary>
public string IcoPath { get; set; }

/// <summary>
/// The date when the plugin was last updated
/// </summary>
public DateTime? LatestReleaseDate { get; set; }

/// <summary>
/// The date when the plugin was added to the local system
/// </summary>
public DateTime? DateAdded { get; set; }

/// <summary>
/// Indicates whether the plugin is installed from a local path
/// </summary>
public bool IsFromLocalInstallPath => !string.IsNullOrEmpty(LocalInstallPath);
}
}
17 changes: 17 additions & 0 deletions Flow.Launcher/PublicAPIInstance.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
using Flow.Launcher.ViewModel;
using JetBrains.Annotations;
using Flow.Launcher.Core.Resource;
using Flow.Launcher.Core.ExternalPlugins;

namespace Flow.Launcher
{
Expand Down Expand Up @@ -354,6 +355,22 @@ public MessageBoxResult ShowMsgBox(string messageBoxText, string caption = "", M

public Task ShowProgressBoxAsync(string caption, Func<Action<double>, Task> reportProgressAsync, Action cancelProgress = null) => ProgressBoxEx.ShowAsync(caption, reportProgressAsync, cancelProgress);

public Task<bool> UpdatePluginManifestAsync(bool usePrimaryUrlOnly = false, CancellationToken token = default) =>
PluginsManifest.UpdateManifestAsync(usePrimaryUrlOnly, token);

public IReadOnlyList<UserPlugin> GetPluginManifest() => PluginsManifest.UserPlugins;

public bool PluginModified(string id) => PluginManager.PluginModified(id);

public Task UpdatePluginAsync(PluginMetadata pluginMetadata, UserPlugin plugin, string zipFilePath) =>
PluginManager.UpdatePluginAsync(pluginMetadata, plugin, zipFilePath);

public void InstallPlugin(UserPlugin plugin, string zipFilePath) =>
PluginManager.InstallPlugin(plugin, zipFilePath);

public Task UninstallPluginAsync(PluginMetadata pluginMetadata, bool removePluginSettings = false) =>
PluginManager.UninstallPluginAsync(pluginMetadata, removePluginSettings);

#endregion

#region Private Methods
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
using System.Linq;
using System.Threading.Tasks;
using CommunityToolkit.Mvvm.Input;
using Flow.Launcher.Core.ExternalPlugins;
using Flow.Launcher.Infrastructure;
using Flow.Launcher.Plugin;
using Flow.Launcher.ViewModel;
Expand All @@ -14,7 +13,7 @@ public partial class SettingsPanePluginStoreViewModel : BaseModel
public string FilterText { get; set; } = string.Empty;

public IList<PluginStoreItemViewModel> ExternalPlugins =>
PluginsManifest.UserPlugins?.Select(p => new PluginStoreItemViewModel(p))
App.API.GetPluginManifest()?.Select(p => new PluginStoreItemViewModel(p))
.OrderByDescending(p => p.Category == PluginStoreItemViewModel.NewRelease)
.ThenByDescending(p => p.Category == PluginStoreItemViewModel.RecentlyUpdated)
.ThenByDescending(p => p.Category == PluginStoreItemViewModel.None)
Expand All @@ -24,7 +23,7 @@ public partial class SettingsPanePluginStoreViewModel : BaseModel
[RelayCommand]
private async Task RefreshExternalPluginsAsync()
{
if (await PluginsManifest.UpdateManifestAsync())
if (await App.API.UpdatePluginManifestAsync())
{
OnPropertyChanged(nameof(ExternalPlugins));
}
Expand Down
2 changes: 0 additions & 2 deletions Flow.Launcher/ViewModel/PluginStoreItemViewModel.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
using System;
using System.Linq;
using CommunityToolkit.Mvvm.Input;
using Flow.Launcher.Core.ExternalPlugins;
using Flow.Launcher.Core.Plugin;
using Flow.Launcher.Plugin;
using SemanticVersioning;
using Version = SemanticVersioning.Version;

namespace Flow.Launcher.ViewModel
Expand Down
3 changes: 1 addition & 2 deletions Plugins/Flow.Launcher.Plugin.PluginsManager/ContextMenu.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using Flow.Launcher.Core.ExternalPlugins;
using System.Collections.Generic;
using System.Collections.Generic;
using System.Text.RegularExpressions;

namespace Flow.Launcher.Plugin.PluginsManager
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,6 @@
</PropertyGroup>

<ItemGroup>
<ProjectReference Include="..\..\Flow.Launcher.Infrastructure\Flow.Launcher.Infrastructure.csproj" />
<ProjectReference Include="..\..\Flow.Launcher.Core\Flow.Launcher.Core.csproj" />
<ProjectReference Include="..\..\Flow.Launcher.Plugin\Flow.Launcher.Plugin.csproj" />
</ItemGroup>

Expand All @@ -37,4 +35,8 @@
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>

<ItemGroup>
<PackageReference Include="SharpZipLib" Version="1.4.2" />
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this is used right?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this is used right?

Previous version also refers to this package as transitive package from Flow.Launcher.Core project becausesquirrel.windows package use SharpZipLib package. Since this PR drops project reference of Flow.Launcher.Core project, we need to add this package reference.

</ItemGroup>
</Project>
Loading
Loading