mirror of
https://github.com/Stone-Red-Code/DesktopMagic.git
synced 2026-09-04 08:56:15 +02:00
Add search functionality to plugin manager and improve UX
This commit is contained in:
@@ -1,13 +1,19 @@
|
|||||||
using DesktopMagic.Plugins;
|
using DesktopMagic.Plugins;
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
using System.ComponentModel;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
using System.Windows;
|
using System.Windows;
|
||||||
using System.Windows.Input;
|
using System.Windows.Input;
|
||||||
|
|
||||||
namespace DesktopMagic.DataContexts;
|
namespace DesktopMagic.DataContexts;
|
||||||
|
|
||||||
internal class PluginEntryDataContext(PluginMetadata pluginMetadata, ICommand command, bool installed = false)
|
internal class PluginEntryDataContext(PluginMetadata pluginMetadata, ICommand command, bool installed = false) : INotifyPropertyChanged
|
||||||
{
|
{
|
||||||
|
public event PropertyChangedEventHandler? PropertyChanged;
|
||||||
|
|
||||||
|
private bool isVisible = true;
|
||||||
|
|
||||||
public string Name => pluginMetadata.Name;
|
public string Name => pluginMetadata.Name;
|
||||||
|
|
||||||
public string? Description => pluginMetadata.Description;
|
public string? Description => pluginMetadata.Description;
|
||||||
@@ -24,4 +30,22 @@ internal class PluginEntryDataContext(PluginMetadata pluginMetadata, ICommand co
|
|||||||
public Visibility InstallButtonVisibility => installed ? Visibility.Collapsed : Visibility.Visible;
|
public Visibility InstallButtonVisibility => installed ? Visibility.Collapsed : Visibility.Visible;
|
||||||
|
|
||||||
public Visibility RemoveButtonVisibility => installed ? Visibility.Visible : Visibility.Collapsed;
|
public Visibility RemoveButtonVisibility => installed ? Visibility.Visible : Visibility.Collapsed;
|
||||||
|
|
||||||
|
public bool IsVisible
|
||||||
|
{
|
||||||
|
get => isVisible;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
isVisible = value;
|
||||||
|
OnPropertyChanged();
|
||||||
|
OnPropertyChanged(nameof(Visibility));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Visibility Visibility => IsVisible ? Visibility.Visible : Visibility.Collapsed;
|
||||||
|
|
||||||
|
private void OnPropertyChanged([CallerMemberName] string? propertyName = null)
|
||||||
|
{
|
||||||
|
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -8,17 +8,19 @@ internal class PluginManagerDataContext : INotifyPropertyChanged
|
|||||||
{
|
{
|
||||||
public event PropertyChangedEventHandler? PropertyChanged;
|
public event PropertyChangedEventHandler? PropertyChanged;
|
||||||
|
|
||||||
|
private string allPluginsSearchText = string.Empty;
|
||||||
|
private string installedPluginsSearchText = string.Empty;
|
||||||
|
private bool isLoading = true;
|
||||||
|
private bool isSearching;
|
||||||
public ObservableCollection<PluginEntryDataContext> AllPlugins { get; } = [];
|
public ObservableCollection<PluginEntryDataContext> AllPlugins { get; } = [];
|
||||||
public ObservableCollection<PluginEntryDataContext> InstalledPlugins { get; } = [];
|
public ObservableCollection<PluginEntryDataContext> InstalledPlugins { get; } = [];
|
||||||
|
|
||||||
private bool _isLoading;
|
|
||||||
|
|
||||||
public bool IsLoading
|
public bool IsLoading
|
||||||
{
|
{
|
||||||
get => _isLoading;
|
get => isLoading;
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
_isLoading = value;
|
isLoading = value;
|
||||||
OnPropertyChanged();
|
OnPropertyChanged();
|
||||||
OnPropertyChanged(nameof(IsNotLoading));
|
OnPropertyChanged(nameof(IsNotLoading));
|
||||||
}
|
}
|
||||||
@@ -26,6 +28,36 @@ internal class PluginManagerDataContext : INotifyPropertyChanged
|
|||||||
|
|
||||||
public bool IsNotLoading => !IsLoading;
|
public bool IsNotLoading => !IsLoading;
|
||||||
|
|
||||||
|
public bool IsSearching
|
||||||
|
{
|
||||||
|
get => isSearching;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
isSearching = value;
|
||||||
|
OnPropertyChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public string AllPluginsSearchText
|
||||||
|
{
|
||||||
|
get => allPluginsSearchText;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
allPluginsSearchText = value;
|
||||||
|
OnPropertyChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public string InstalledPluginsSearchText
|
||||||
|
{
|
||||||
|
get => installedPluginsSearchText;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
installedPluginsSearchText = value;
|
||||||
|
OnPropertyChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
protected void OnPropertyChanged([CallerMemberName] string? name = null)
|
protected void OnPropertyChanged([CallerMemberName] string? name = null)
|
||||||
{
|
{
|
||||||
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
|
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
|
||||||
|
|||||||
@@ -7,11 +7,11 @@
|
|||||||
<ApplicationIcon>icon.ico</ApplicationIcon>
|
<ApplicationIcon>icon.ico</ApplicationIcon>
|
||||||
<RunPostBuildEvent>OnBuildSuccess</RunPostBuildEvent>
|
<RunPostBuildEvent>OnBuildSuccess</RunPostBuildEvent>
|
||||||
<Authors>Stone_Red</Authors>
|
<Authors>Stone_Red</Authors>
|
||||||
<Version>0.0.4.0</Version>
|
<Version>1.0.0.0</Version>
|
||||||
<PackageProjectUrl>https://github.com/Stone-Red-Code/DesktopMagic</PackageProjectUrl>
|
<PackageProjectUrl>https://github.com/Stone-Red-Code/DesktopMagic</PackageProjectUrl>
|
||||||
<RepositoryUrl>https://github.com/Stone-Red-Code/DesktopMagic</RepositoryUrl>
|
<RepositoryUrl>https://github.com/Stone-Red-Code/DesktopMagic</RepositoryUrl>
|
||||||
<AssemblyVersion>0.0.4.0</AssemblyVersion>
|
<AssemblyVersion>1.0.0.0</AssemblyVersion>
|
||||||
<FileVersion>0.0.4.0</FileVersion>
|
<FileVersion>1.0.0.0</FileVersion>
|
||||||
<TargetFramework>net8.0-windows7.0</TargetFramework>
|
<TargetFramework>net8.0-windows7.0</TargetFramework>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ public partial class ColorDialog : Window
|
|||||||
{
|
{
|
||||||
public System.Drawing.Color ResultColor { get; private set; }
|
public System.Drawing.Color ResultColor { get; private set; }
|
||||||
|
|
||||||
public Brush ResultBrush { get; private set; }
|
public Brush ResultBrush { get; private set; } = Brushes.Transparent;
|
||||||
|
|
||||||
public ColorDialog(string content, System.Drawing.Color defaultColor, string title = "ColorDialog")
|
public ColorDialog(string content, System.Drawing.Color defaultColor, string title = "ColorDialog")
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -573,15 +573,16 @@ namespace DesktopMagic
|
|||||||
// Load plugins
|
// Load plugins
|
||||||
foreach (uint pluginId in plugins.Keys)
|
foreach (uint pluginId in plugins.Keys)
|
||||||
{
|
{
|
||||||
|
InternalPluginData internalPluginData = plugins[pluginId];
|
||||||
|
|
||||||
// Add plugin to layout if it doesn't exist
|
// Add plugin to layout if it doesn't exist
|
||||||
if (!Settings.CurrentLayout.Plugins.TryGetValue(pluginId, out PluginSettings? pluginSettings))
|
if (!Settings.CurrentLayout.Plugins.TryGetValue(pluginId, out PluginSettings? pluginSettings))
|
||||||
{
|
{
|
||||||
Settings.CurrentLayout.Plugins.Add(pluginId, new PluginSettings());
|
Settings.CurrentLayout.Plugins.Add(pluginId, new PluginSettings() { Name = internalPluginData.Metadata.Name });
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
InternalPluginData internalPluginData = plugins[pluginId];
|
|
||||||
pluginSettings.Name = internalPluginData.Metadata.Name;
|
pluginSettings.Name = internalPluginData.Metadata.Name;
|
||||||
|
|
||||||
if (pluginSettings.Enabled)
|
if (pluginSettings.Enabled)
|
||||||
|
|||||||
@@ -10,7 +10,8 @@
|
|||||||
mc:Ignorable="d"
|
mc:Ignorable="d"
|
||||||
d:DesignHeight="450" d:DesignWidth="800"
|
d:DesignHeight="450" d:DesignWidth="800"
|
||||||
Background="{DynamicResource MaterialDesignPaper}"
|
Background="{DynamicResource MaterialDesignPaper}"
|
||||||
FontFamily="{DynamicResource MaterialDesignFont}">
|
FontFamily="{DynamicResource MaterialDesignFont}"
|
||||||
|
Visibility="{Binding Visibility}">
|
||||||
<Grid Background="White" Margin="10">
|
<Grid Background="White" Margin="10">
|
||||||
<Grid.RowDefinitions>
|
<Grid.RowDefinitions>
|
||||||
<RowDefinition />
|
<RowDefinition />
|
||||||
@@ -36,7 +37,7 @@
|
|||||||
|
|
||||||
<StackPanel Grid.Row="1" Grid.ColumnSpan="2">
|
<StackPanel Grid.Row="1" Grid.ColumnSpan="2">
|
||||||
<Label Content="{Binding Name}" FontSize="20" />
|
<Label Content="{Binding Name}" FontSize="20" />
|
||||||
<Label Content="{Binding Description}" />
|
<TextBlock Text="{Binding Description}" TextWrapping="Wrap" />
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</Grid>
|
</Grid>
|
||||||
</UserControl>
|
</UserControl>
|
||||||
@@ -33,21 +33,40 @@
|
|||||||
|
|
||||||
<Label Content="All plugins" FontSize="20" />
|
<Label Content="All plugins" FontSize="20" />
|
||||||
|
|
||||||
<TextBox Grid.Row="1" materialDesign:HintAssist.Hint="Search..." materialDesign:TextFieldAssist.HasLeadingIcon="True" materialDesign:TextFieldAssist.LeadingIcon="Search" />
|
<TextBox Grid.Row="1" Text="{Binding AllPluginsSearchText, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" TextChanged="AllPluginsSearchTextBox_TextChanged" materialDesign:HintAssist.Hint="Search..." materialDesign:TextFieldAssist.HasLeadingIcon="True" materialDesign:TextFieldAssist.LeadingIcon="Search" />
|
||||||
|
|
||||||
<ItemsControl Grid.Row="2" ItemsSource="{Binding AllPlugins}">
|
<busyIndicator:BusyMask Grid.Row="2" IsBusy="{Binding IsSearching}" IndicatorType="Ring" BusyContent="Searching..." BusyContentMargin="0,50,0,0" IsBusyAtStartup="False">
|
||||||
<ItemsControl.ItemTemplate>
|
<ScrollViewer VerticalScrollBarVisibility="Auto">
|
||||||
<DataTemplate>
|
<ItemsControl ItemsSource="{Binding AllPlugins}">
|
||||||
<Border BorderBrush="LightGray" BorderThickness="1">
|
<ItemsControl.ItemTemplate>
|
||||||
<local:ModEntry />
|
<DataTemplate>
|
||||||
</Border>
|
<Border BorderBrush="LightGray" BorderThickness="1">
|
||||||
</DataTemplate>
|
<local:ModEntry />
|
||||||
</ItemsControl.ItemTemplate>
|
</Border>
|
||||||
</ItemsControl>
|
</DataTemplate>
|
||||||
|
</ItemsControl.ItemTemplate>
|
||||||
|
<ItemsControl.Style>
|
||||||
|
<Style TargetType="ItemsControl">
|
||||||
|
<Style.Triggers>
|
||||||
|
<Trigger Property="HasItems" Value="false">
|
||||||
|
<Setter Property="Template">
|
||||||
|
<Setter.Value>
|
||||||
|
<ControlTemplate>
|
||||||
|
<TextBlock Text="No plugins found!" FontSize="20" VerticalAlignment="Center" HorizontalAlignment="Center"/>
|
||||||
|
</ControlTemplate>
|
||||||
|
</Setter.Value>
|
||||||
|
</Setter>
|
||||||
|
</Trigger>
|
||||||
|
</Style.Triggers>
|
||||||
|
</Style>
|
||||||
|
</ItemsControl.Style>
|
||||||
|
</ItemsControl>
|
||||||
|
</ScrollViewer>
|
||||||
|
</busyIndicator:BusyMask>
|
||||||
|
|
||||||
<Label Grid.Column="1" Content="Installed plugins" FontSize="20" />
|
<Label Grid.Column="1" Content="Installed plugins" FontSize="20" />
|
||||||
|
|
||||||
<TextBox Grid.Row="1" Grid.Column="1" materialDesign:HintAssist.Hint="Search..." materialDesign:TextFieldAssist.HasLeadingIcon="True" materialDesign:TextFieldAssist.LeadingIcon="Search" />
|
<TextBox Grid.Row="1" Grid.Column="1" Text="{Binding InstalledPluginsSearchText, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" TextChanged="InstalledPluginsSearchTextBox_TextChanged" materialDesign:HintAssist.Hint="Search..." materialDesign:TextFieldAssist.HasLeadingIcon="True" materialDesign:TextFieldAssist.LeadingIcon="Search" />
|
||||||
|
|
||||||
<ItemsControl Grid.Row="2" Grid.Column="1" ItemsSource="{Binding InstalledPlugins}">
|
<ItemsControl Grid.Row="2" Grid.Column="1" ItemsSource="{Binding InstalledPlugins}">
|
||||||
<ItemsControl.ItemTemplate>
|
<ItemsControl.ItemTemplate>
|
||||||
@@ -57,11 +76,26 @@
|
|||||||
</Border>
|
</Border>
|
||||||
</DataTemplate>
|
</DataTemplate>
|
||||||
</ItemsControl.ItemTemplate>
|
</ItemsControl.ItemTemplate>
|
||||||
|
<ItemsControl.Style>
|
||||||
|
<Style TargetType="ItemsControl">
|
||||||
|
<Style.Triggers>
|
||||||
|
<Trigger Property="HasItems" Value="false">
|
||||||
|
<Setter Property="Template">
|
||||||
|
<Setter.Value>
|
||||||
|
<ControlTemplate>
|
||||||
|
<TextBlock Text="No plugins found!" FontSize="20" VerticalAlignment="Center" HorizontalAlignment="Center"/>
|
||||||
|
</ControlTemplate>
|
||||||
|
</Setter.Value>
|
||||||
|
</Setter>
|
||||||
|
</Trigger>
|
||||||
|
</Style.Triggers>
|
||||||
|
</Style>
|
||||||
|
</ItemsControl.Style>
|
||||||
</ItemsControl>
|
</ItemsControl>
|
||||||
|
|
||||||
<DockPanel Grid.Row="3" Grid.ColumnSpan="2">
|
<Border Grid.Row="3" Grid.ColumnSpan="2" Padding="0 5 0 0" BorderThickness="0 2 0 0" BorderBrush="DarkGray">
|
||||||
<Image Source="{StaticResource ModioLogoBlueDark}" Height="30" HorizontalAlignment="Left" />
|
<Image Source="{StaticResource ModioLogoBlueDark}" Cursor="Hand" Height="30" MouseUp="Image_MouseUp" HorizontalAlignment="Left" />
|
||||||
</DockPanel>
|
</Border>
|
||||||
</Grid>
|
</Grid>
|
||||||
</busyIndicator:BusyMask>
|
</busyIndicator:BusyMask>
|
||||||
</Window>
|
</Window>
|
||||||
@@ -2,6 +2,7 @@
|
|||||||
using DesktopMagic.Helpers;
|
using DesktopMagic.Helpers;
|
||||||
|
|
||||||
using Modio.NET;
|
using Modio.NET;
|
||||||
|
using Modio.NET.Filters;
|
||||||
using Modio.NET.Models;
|
using Modio.NET.Models;
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
@@ -15,6 +16,7 @@ using System.Net.Http;
|
|||||||
using System.Text.Json;
|
using System.Text.Json;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using System.Windows;
|
using System.Windows;
|
||||||
|
using System.Windows.Threading;
|
||||||
|
|
||||||
using File = System.IO.File;
|
using File = System.IO.File;
|
||||||
using Path = System.IO.Path;
|
using Path = System.IO.Path;
|
||||||
@@ -26,17 +28,28 @@ namespace DesktopMagic.Plugins;
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public partial class PluginManager : Window
|
public partial class PluginManager : Window
|
||||||
{
|
{
|
||||||
|
private const int modIoGameId = 5665;
|
||||||
private readonly Client client = new Client(new Credentials("88e6ea774c3a502b06114e7fee0829ac"));
|
private readonly Client client = new Client(new Credentials("88e6ea774c3a502b06114e7fee0829ac"));
|
||||||
private readonly HttpClient httpClient = new();
|
private readonly HttpClient httpClient = new();
|
||||||
|
|
||||||
private readonly PluginManagerDataContext pluginManagerDataContext = new();
|
private readonly PluginManagerDataContext pluginManagerDataContext = new();
|
||||||
private readonly string pluginsPath = Path.Combine(App.ApplicationDataPath, "Plugins");
|
private readonly string pluginsPath = Path.Combine(App.ApplicationDataPath, "Plugins");
|
||||||
|
|
||||||
|
private readonly DispatcherTimer searchTimer = new()
|
||||||
|
{
|
||||||
|
Interval = TimeSpan.FromMilliseconds(300),
|
||||||
|
};
|
||||||
|
|
||||||
public PluginManager()
|
public PluginManager()
|
||||||
{
|
{
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
|
|
||||||
DataContext = pluginManagerDataContext;
|
DataContext = pluginManagerDataContext;
|
||||||
|
searchTimer.Tick += async (sender, e) =>
|
||||||
|
{
|
||||||
|
searchTimer.Stop();
|
||||||
|
await SearchAllPlugins(pluginManagerDataContext.AllPluginsSearchText);
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Remove(string pluginPath, uint? id)
|
public void Remove(string pluginPath, uint? id)
|
||||||
@@ -81,7 +94,9 @@ public partial class PluginManager : Window
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
IAsyncEnumerable<Mod> mods = client.Games[5665].Mods.Search().ToEnumerableAsync();
|
Filter filter = ModFilter.Popular.Desc().Limit(100);
|
||||||
|
|
||||||
|
IAsyncEnumerable<Mod> mods = client.Games[modIoGameId].Mods.Search(filter).ToEnumerableAsync();
|
||||||
await foreach (Mod mod in mods)
|
await foreach (Mod mod in mods)
|
||||||
{
|
{
|
||||||
if (pluginIds.Contains(mod.Id))
|
if (pluginIds.Contains(mod.Id))
|
||||||
@@ -91,6 +106,8 @@ public partial class PluginManager : Window
|
|||||||
|
|
||||||
pluginManagerDataContext.AllPlugins.Add(new PluginEntryDataContext(new(mod), new CommandHandler(async () => await Install(mod))));
|
pluginManagerDataContext.AllPlugins.Add(new PluginEntryDataContext(new(mod), new CommandHandler(async () => await Install(mod))));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pluginManagerDataContext.IsLoading = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnClosing(CancelEventArgs e)
|
protected override void OnClosing(CancelEventArgs e)
|
||||||
@@ -102,8 +119,6 @@ public partial class PluginManager : Window
|
|||||||
{
|
{
|
||||||
pluginManagerDataContext.IsLoading = true;
|
pluginManagerDataContext.IsLoading = true;
|
||||||
|
|
||||||
Debug.WriteLine(mod.Modfile?.Download?.BinaryUrl + " | " + pluginsPath);
|
|
||||||
|
|
||||||
if (mod.Modfile?.Download?.BinaryUrl is null)
|
if (mod.Modfile?.Download?.BinaryUrl is null)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
@@ -149,4 +164,65 @@ public partial class PluginManager : Window
|
|||||||
|
|
||||||
pluginManagerDataContext.IsLoading = false;
|
pluginManagerDataContext.IsLoading = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void Image_MouseUp(object sender, System.Windows.Input.MouseButtonEventArgs e)
|
||||||
|
{
|
||||||
|
string uri = "https://mod.io/g/DesktopMagic";
|
||||||
|
ProcessStartInfo psi = new ProcessStartInfo
|
||||||
|
{
|
||||||
|
UseShellExecute = true,
|
||||||
|
FileName = uri
|
||||||
|
};
|
||||||
|
_ = Process.Start(psi);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void AllPluginsSearchTextBox_TextChanged(object sender, System.Windows.Controls.TextChangedEventArgs e)
|
||||||
|
{
|
||||||
|
pluginManagerDataContext.IsSearching = true;
|
||||||
|
searchTimer.Stop();
|
||||||
|
searchTimer.Start();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void InstalledPluginsSearchTextBox_TextChanged(object sender, System.Windows.Controls.TextChangedEventArgs e)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(pluginManagerDataContext.InstalledPluginsSearchText))
|
||||||
|
{
|
||||||
|
foreach (PluginEntryDataContext pluginEntryDataContext in pluginManagerDataContext.InstalledPlugins)
|
||||||
|
{
|
||||||
|
pluginEntryDataContext.IsVisible = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
foreach (PluginEntryDataContext pluginEntryDataContext in pluginManagerDataContext.InstalledPlugins)
|
||||||
|
{
|
||||||
|
pluginEntryDataContext.IsVisible = pluginEntryDataContext.Name.Contains(pluginManagerDataContext.InstalledPluginsSearchText, StringComparison.OrdinalIgnoreCase);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task SearchAllPlugins(string searchString)
|
||||||
|
{
|
||||||
|
pluginManagerDataContext.AllPlugins.Clear();
|
||||||
|
|
||||||
|
if (!searchString.Contains('*'))
|
||||||
|
{
|
||||||
|
searchString = $"*{searchString.Trim()}*";
|
||||||
|
}
|
||||||
|
|
||||||
|
Filter filter = ModFilter.Name.Like($"{searchString}").And(ModFilter.Popular.Desc()).Limit(100);
|
||||||
|
|
||||||
|
IAsyncEnumerable<Mod> mods = client.Games[modIoGameId].Mods.Search(filter).ToEnumerableAsync();
|
||||||
|
await foreach (Mod mod in mods)
|
||||||
|
{
|
||||||
|
if (pluginManagerDataContext.InstalledPlugins.Any(p => p.Id == mod.Id))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
pluginManagerDataContext.AllPlugins.Add(new PluginEntryDataContext(new(mod), new CommandHandler(async () => await Install(mod))));
|
||||||
|
}
|
||||||
|
|
||||||
|
pluginManagerDataContext.IsSearching = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user