diff --git a/src/Artemis.UI/Screens/Workshop/Library/Tabs/InstalledTabItemView.axaml b/src/Artemis.UI/Screens/Workshop/Library/Tabs/InstalledTabItemView.axaml
new file mode 100644
index 000000000..4d01b32b0
--- /dev/null
+++ b/src/Artemis.UI/Screens/Workshop/Library/Tabs/InstalledTabItemView.axaml
@@ -0,0 +1,53 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Artemis.UI/Screens/Workshop/Library/Tabs/InstalledTabItemView.axaml.cs b/src/Artemis.UI/Screens/Workshop/Library/Tabs/InstalledTabItemView.axaml.cs
new file mode 100644
index 000000000..be6199b60
--- /dev/null
+++ b/src/Artemis.UI/Screens/Workshop/Library/Tabs/InstalledTabItemView.axaml.cs
@@ -0,0 +1,13 @@
+using Avalonia;
+using Avalonia.Controls;
+using Avalonia.Markup.Xaml;
+
+namespace Artemis.UI.Screens.Workshop.Library.Tabs;
+
+public partial class InstalledTabItemView : UserControl
+{
+ public InstalledTabItemView()
+ {
+ InitializeComponent();
+ }
+}
\ No newline at end of file
diff --git a/src/Artemis.UI/Screens/Workshop/Library/Tabs/InstalledTabItemViewModel.cs b/src/Artemis.UI/Screens/Workshop/Library/Tabs/InstalledTabItemViewModel.cs
new file mode 100644
index 000000000..54f171c52
--- /dev/null
+++ b/src/Artemis.UI/Screens/Workshop/Library/Tabs/InstalledTabItemViewModel.cs
@@ -0,0 +1,14 @@
+using Artemis.UI.Shared;
+using Artemis.WebClient.Workshop.Services;
+
+namespace Artemis.UI.Screens.Workshop.Library.Tabs;
+
+public class InstalledTabItemViewModel : ViewModelBase
+{
+ public InstalledTabItemViewModel(InstalledEntry installedEntry)
+ {
+ InstalledEntry = installedEntry;
+ }
+
+ public InstalledEntry InstalledEntry { get; }
+}
\ No newline at end of file
diff --git a/src/Artemis.UI/Screens/Workshop/Library/Tabs/InstalledTabView.axaml b/src/Artemis.UI/Screens/Workshop/Library/Tabs/InstalledTabView.axaml
index df334299a..9689f09bf 100644
--- a/src/Artemis.UI/Screens/Workshop/Library/Tabs/InstalledTabView.axaml
+++ b/src/Artemis.UI/Screens/Workshop/Library/Tabs/InstalledTabView.axaml
@@ -2,7 +2,17 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
+ xmlns:tabs="clr-namespace:Artemis.UI.Screens.Workshop.Library.Tabs"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
- x:Class="Artemis.UI.Screens.Workshop.Library.Tabs.InstalledTabView">
- Installed entries management here 🫡
-
+ x:Class="Artemis.UI.Screens.Workshop.Library.Tabs.InstalledTabView"
+ x:DataType="tabs:InstalledTabViewModel">
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Artemis.UI/Screens/Workshop/Library/Tabs/InstalledTabViewModel.cs b/src/Artemis.UI/Screens/Workshop/Library/Tabs/InstalledTabViewModel.cs
index 3bfdf406f..9e02249f7 100644
--- a/src/Artemis.UI/Screens/Workshop/Library/Tabs/InstalledTabViewModel.cs
+++ b/src/Artemis.UI/Screens/Workshop/Library/Tabs/InstalledTabViewModel.cs
@@ -1,9 +1,55 @@
-using Artemis.UI.Shared;
+using System;
+using System.Collections.ObjectModel;
+using System.Reactive.Disposables;
+using System.Reactive.Linq;
using Artemis.UI.Shared.Routing;
+using Artemis.WebClient.Workshop.Services;
+using Avalonia.ReactiveUI;
+using DynamicData;
+using DynamicData.Binding;
+using ReactiveUI;
namespace Artemis.UI.Screens.Workshop.Library.Tabs;
public class InstalledTabViewModel : RoutableScreen
{
-
+ private string? _searchEntryInput;
+
+ public InstalledTabViewModel(IWorkshopService workshopService, Func getInstalledTabItemViewModel)
+ {
+ SourceList installedEntries = new();
+ IObservable> pluginFilter = this.WhenAnyValue(vm => vm.SearchEntryInput).Throttle(TimeSpan.FromMilliseconds(100)).Select(CreatePredicate);
+
+ installedEntries.Connect()
+ .Filter(pluginFilter)
+ .Sort(SortExpressionComparer.Ascending(p => p.Name))
+ .Transform(getInstalledTabItemViewModel)
+ .ObserveOn(AvaloniaScheduler.Instance)
+ .Bind(out ReadOnlyObservableCollection installedEntryViewModels)
+ .Subscribe();
+ InstalledEntries = installedEntryViewModels;
+
+ this.WhenActivated(d =>
+ {
+ installedEntries.AddRange(workshopService.GetInstalledEntries());
+ Disposable.Create(installedEntries, e => e.Clear()).DisposeWith(d);
+ });
+ }
+
+ public ReadOnlyObservableCollection InstalledEntries { get; }
+
+ public string? SearchEntryInput
+ {
+ get => _searchEntryInput;
+ set => RaiseAndSetIfChanged(ref _searchEntryInput, value);
+ }
+
+ private Func CreatePredicate(string? text)
+ {
+ if (string.IsNullOrWhiteSpace(text))
+ return _ => true;
+
+ return data => data.Name.Contains(text, StringComparison.InvariantCultureIgnoreCase) ||
+ data.Summary.Contains(text, StringComparison.InvariantCultureIgnoreCase);
+ }
}
\ No newline at end of file
diff --git a/src/Artemis.WebClient.Workshop/Services/Interfaces/IWorkshopService.cs b/src/Artemis.WebClient.Workshop/Services/Interfaces/IWorkshopService.cs
index d7c0f8764..bda524109 100644
--- a/src/Artemis.WebClient.Workshop/Services/Interfaces/IWorkshopService.cs
+++ b/src/Artemis.WebClient.Workshop/Services/Interfaces/IWorkshopService.cs
@@ -10,6 +10,8 @@ public interface IWorkshopService
Task GetWorkshopStatus(CancellationToken cancellationToken);
Task ValidateWorkshopStatus(CancellationToken cancellationToken);
Task NavigateToEntry(Guid entryId, EntryType entryType);
+
+ List GetInstalledEntries();
InstalledEntry? GetInstalledEntry(IGetEntryById_Entry entry);
InstalledEntry CreateInstalledEntry(IGetEntryById_Entry entry);
void SaveInstalledEntry(InstalledEntry entry);
diff --git a/src/Artemis.WebClient.Workshop/Services/WorkshopService.cs b/src/Artemis.WebClient.Workshop/Services/WorkshopService.cs
index af29c9bb0..41924b8e1 100644
--- a/src/Artemis.WebClient.Workshop/Services/WorkshopService.cs
+++ b/src/Artemis.WebClient.Workshop/Services/WorkshopService.cs
@@ -103,6 +103,11 @@ public class WorkshopService : IWorkshopService
}
}
+ public List GetInstalledEntries()
+ {
+ return _entryRepository.GetAll().Select(e => new InstalledEntry(e)).ToList();
+ }
+
///
public InstalledEntry? GetInstalledEntry(IGetEntryById_Entry entry)
{