diff --git a/Torch.Server/Views/PluginBrowser.xaml.cs b/Torch.Server/Views/PluginBrowser.xaml.cs index 8c97be8..1e2707d 100644 --- a/Torch.Server/Views/PluginBrowser.xaml.cs +++ b/Torch.Server/Views/PluginBrowser.xaml.cs @@ -21,6 +21,8 @@ using NLog; using Torch.API.WebAPI; using Torch.Collections; using Torch.Server.Annotations; +using Torch.Managers; +using Torch.API.Managers; namespace Torch.Server.Views { @@ -31,8 +33,11 @@ namespace Torch.Server.Views { private static Logger Log = LogManager.GetCurrentClassLogger(); + public MtObservableList PluginsSource { get; set; } = new MtObservableList(); public MtObservableList Plugins { get; set; } = new MtObservableList(); public PluginItem CurrentItem { get; set; } + public const string PLUGINS_SEARCH_TEXT = "Plugins search..."; + private string PreviousSearchQuery = ""; private string _description = "Loading data from server, please wait.."; public string CurrentDescription @@ -45,18 +50,25 @@ namespace Torch.Server.Views } } - public PluginBrowser() + public PluginBrowser(IPluginManager pluginManager) { InitializeComponent(); + var installedPlugins = pluginManager.Plugins; Task.Run(async () => { var res = await PluginQuery.Instance.QueryAll(); if (res == null) return; - foreach (var item in res.Plugins) + foreach (var item in res.Plugins.OrderBy(i => i.Name)) { + if (installedPlugins.Keys.Contains(Guid.Parse(item.ID))) + item.Installed = true; + Plugins.Add(item); PluginsList.Dispatcher.Invoke(() => PluginsList.SelectedIndex = 0); + PluginsSource.Add(item); + } + CurrentDescription = "Please select a plugin..."; }); MarkdownFlow.CommandBindings.Add(new CommandBinding(NavigationCommands.GoToPage, (sender, e) => OpenUri((string)e.Parameter))); @@ -83,23 +95,49 @@ namespace Torch.Server.Views private void PluginsList_SelectionChanged(object sender, SelectionChangedEventArgs e) { CurrentItem = (PluginItem)PluginsList.SelectedItem; - CurrentDescription = CurrentItem.Description; - DownloadButton.IsEnabled = !string.IsNullOrEmpty(CurrentItem.LatestVersion); + if (CurrentItem != null) { + CurrentDescription = CurrentItem.Description; + DownloadButton.IsEnabled = !string.IsNullOrEmpty(CurrentItem.LatestVersion); + UninstallButton.IsEnabled = !string.IsNullOrEmpty(CurrentItem.LatestVersion); + } } private void DownloadButton_OnClick(object sender, RoutedEventArgs e) { - var item = CurrentItem; - TorchBase.Instance.Config.Plugins.Add(new Guid(item.ID)); + var SelectedItems = PluginsList.SelectedItems; + + foreach(PluginItem PluginItem in SelectedItems) + TorchBase.Instance.Config.Plugins.Add(new Guid(PluginItem.ID)); + TorchBase.Instance.Config.Save(); - Task.Run(async () => - { - var result = await PluginQuery.Instance.DownloadPlugin(item.ID); - MessageBox.Show(result ? "Plugin downloaded successfully! Please restart the server to load changes." - : "Plugin failed to download! See log for details.", - "Plugin Downloader", - MessageBoxButton.OK); - }); + Log.Info($"Started to download {SelectedItems.Count} plugin(s)"); + + PluginDownloader DownloadProgress = new PluginDownloader(SelectedItems); + DownloadProgress.Show(); + } + + private void UninstallButton_OnClick(object sender, RoutedEventArgs e) { + var SelectedItems = PluginsList.SelectedItems; + if(SelectedItems.Cast().Any(x => x.Installed == false)) { + MessageBox.Show($"Error! You have selected at least 1 plugin which isnt currently installed. Please de-select and try again!", "Uninstall Error", MessageBoxButton.OK, MessageBoxImage.Warning); + return; + } + var result = MessageBox.Show($"Are you sure you want to attempt uninstall of {SelectedItems.Count} plugin(s)?", "Uninstall Confirmation", MessageBoxButton.YesNo); + if (result == MessageBoxResult.Yes) { + foreach(PluginItem PluginItem in SelectedItems) { + if(TorchBase.Instance.Config.Plugins.Contains(Guid.Parse(PluginItem.ID))) { + TorchBase.Instance.Config.Plugins.Remove(Guid.Parse(PluginItem.ID)); + + string path = $"Plugins\\{PluginItem.Name}.zip"; + + if (File.Exists(path)) + File.Delete(path); + + Log.Info($"Uninstalled {PluginItem.Name}"); + } + } + MessageBox.Show($"Plugins removed... Please restart your server for changes to take effect.", "Uninstall Confirmation", MessageBoxButton.OK); + } } public event PropertyChangedEventHandler PropertyChanged; @@ -109,6 +147,59 @@ namespace Torch.Server.Views { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } + + private void TxtPluginsSearch_GotFocus(object sender, RoutedEventArgs e) { + if (txtPluginsSearch.Text == PLUGINS_SEARCH_TEXT) { + txtPluginsSearch.Clear(); + txtPluginsSearch.Foreground = Brushes.Black; + return; + } + } + + private void TxtPluginsSearch_LostFocus(object sender, RoutedEventArgs e) { + if(txtPluginsSearch.Text == "") { + txtPluginsSearch.Foreground = Brushes.Gray; + txtPluginsSearch.Text = PLUGINS_SEARCH_TEXT; + return; + } + } + + private void TxtPluginsSearch_TextChanged(object sender, TextChangedEventArgs e) { + string SearchQueryString = txtPluginsSearch.Text; + + if(SearchQueryString.Length < PreviousSearchQuery.Length) { + ResetSearchFilter(); + } + + if (SearchQueryString != PLUGINS_SEARCH_TEXT && SearchQueryString != string.Empty) { + SearchPlugins(SearchQueryString); + } else { + ResetSearchFilter(); + } + + PreviousSearchQuery = SearchQueryString; + } + + private void SearchPlugins(string SearchQueryString) { + foreach (var plugin in Plugins.Where(p => !p.Name.Contains(SearchQueryString, StringComparison.OrdinalIgnoreCase) && + !p.Author.Contains(SearchQueryString, StringComparison.OrdinalIgnoreCase))) { + Plugins.Remove(plugin); + } + + foreach (var plugin in Plugins.Where(p => p.Name.Contains(SearchQueryString, StringComparison.OrdinalIgnoreCase) || + p.Author.Contains(SearchQueryString, StringComparison.OrdinalIgnoreCase))) { + if (!Plugins.Contains(plugin)) + Plugins.Add(plugin); + } + } + + private void ResetSearchFilter() { + Plugins.Clear(); + foreach (var plugin in PluginsSource) { + if (!Plugins.Contains(plugin)) + Plugins.Add(plugin); + } + } } }