Skip to content

Commit f48b4c1

Browse files
authored
Merge pull request #2300 from erri120/feat/2254-optional
Working Required/Optional tabs
2 parents b079ec3 + 91022bd commit f48b4c1

File tree

8 files changed

+64
-33
lines changed

8 files changed

+64
-33
lines changed

src/NexusMods.App.UI/Pages/CollectionDownload/CollectionDownloadDesignViewModel.cs

+1-2
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,7 @@ namespace NexusMods.App.UI.Pages.CollectionDownload;
1111

1212
public class CollectionDownloadDesignViewModel : APageViewModel<ICollectionDownloadViewModel>, ICollectionDownloadViewModel
1313
{
14-
public CollectionDownloadTreeDataGridAdapter RequiredDownloadsAdapter { get; } = null!;
15-
public CollectionDownloadTreeDataGridAdapter OptionalDownloadsAdapter { get; } = null!;
14+
public CollectionDownloadTreeDataGridAdapter TreeDataGridAdapter { get; } = null!;
1615

1716
public CollectionDownloadDesignViewModel() : base(new DesignWindowManager()) { }
1817

src/NexusMods.App.UI/Pages/CollectionDownload/CollectionDownloadView.axaml

+2-2
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@
127127

128128
<!-- third row (tab control and datagrid) -->
129129
<TabControl x:Name="TabControl">
130-
<TabItem>
130+
<TabItem x:Name="RequiredTab">
131131
<TabItem.Header>
132132
<StackPanel x:Name="RequiredModsPanel" Orientation="Horizontal">
133133
<TextBlock>Required</TextBlock>
@@ -139,7 +139,7 @@
139139

140140
<TreeDataGrid x:Name="RequiredDownloadsTree" />
141141
</TabItem>
142-
<TabItem>
142+
<TabItem x:Name="OptionalTab">
143143
<TabItem.Header>
144144
<StackPanel x:Name="OptionalModsPanel" Orientation="Horizontal">
145145
<TextBlock>Optional</TextBlock>

src/NexusMods.App.UI/Pages/CollectionDownload/CollectionDownloadView.axaml.cs

+24-9
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
using System.Diagnostics;
12
using System.Reactive.Disposables;
23
using System.Reactive.Linq;
34
using Avalonia.Media;
@@ -15,18 +16,18 @@ public CollectionDownloadView()
1516
{
1617
InitializeComponent();
1718

18-
TreeDataGridViewHelper.SetupTreeDataGridAdapter<CollectionDownloadView, ICollectionDownloadViewModel, ILibraryItemModel, EntityId>(this, RequiredDownloadsTree, vm => vm.RequiredDownloadsAdapter);
19-
TreeDataGridViewHelper.SetupTreeDataGridAdapter<CollectionDownloadView, ICollectionDownloadViewModel, ILibraryItemModel, EntityId>(this, OptionalDownloadsTree, vm => vm.OptionalDownloadsAdapter);
19+
TreeDataGridViewHelper.SetupTreeDataGridAdapter<CollectionDownloadView, ICollectionDownloadViewModel, ILibraryItemModel, EntityId>(this, RequiredDownloadsTree, vm => vm.TreeDataGridAdapter);
20+
TreeDataGridViewHelper.SetupTreeDataGridAdapter<CollectionDownloadView, ICollectionDownloadViewModel, ILibraryItemModel, EntityId>(this, OptionalDownloadsTree, vm => vm.TreeDataGridAdapter);
2021

2122
this.WhenActivated(d =>
2223
{
2324
this.BindCommand(ViewModel, vm => vm.DownloadAllCommand, view => view.DownloadAllButton)
2425
.DisposeWith(d);
2526

26-
this.OneWayBind(ViewModel, vm => vm.RequiredDownloadsAdapter.Source.Value, view => view.RequiredDownloadsTree.Source)
27+
this.OneWayBind(ViewModel, vm => vm.TreeDataGridAdapter.Source.Value, view => view.RequiredDownloadsTree.Source)
2728
.DisposeWith(d);
2829

29-
this.OneWayBind(ViewModel, vm => vm.OptionalDownloadsAdapter.Source.Value, view => view.OptionalDownloadsTree.Source)
30+
this.OneWayBind(ViewModel, vm => vm.TreeDataGridAdapter.Source.Value, view => view.OptionalDownloadsTree.Source)
3031
.DisposeWith(d);
3132

3233
this.WhenAnyValue(view => view.ViewModel!.BackgroundImage)
@@ -78,14 +79,28 @@ public CollectionDownloadView()
7879
this.OneWayBind(ViewModel, vm => vm.RevisionNumber, view => view.Revision.Text, revision => $"Revision {revision}")
7980
.DisposeWith(d);
8081

82+
this.WhenAnyValue(view => view.TabControl.SelectedItem)
83+
.Select(selectedItem =>
84+
{
85+
if (ReferenceEquals(selectedItem, RequiredTab)) return CollectionDownloadsFilter.OnlyRequired;
86+
if (ReferenceEquals(selectedItem, OptionalTab)) return CollectionDownloadsFilter.OnlyOptional;
87+
throw new UnreachableException();
88+
})
89+
.Subscribe(filter =>
90+
{
91+
ViewModel!.TreeDataGridAdapter.Filter.Value = filter;
92+
})
93+
.DisposeWith(d);
94+
8195
this.WhenAnyValue(view => view.ViewModel)
8296
.WhereNotNull()
83-
.Subscribe(vm =>
97+
.Select(static vm => vm.OptionalDownloadsCount > 0)
98+
.Subscribe(hasOptionalDownloads =>
8499
{
85-
if (vm.OptionalDownloadsCount == 0)
86-
{
87-
// TabControl.IsVisible = false;
88-
}
100+
if (hasOptionalDownloads) TabControl.Classes.Remove("SingleTab");
101+
else TabControl.Classes.Add("SingleTab");
102+
103+
if (!hasOptionalDownloads) TabControl.SelectedItem = RequiredTab;
89104
}).DisposeWith(d);
90105

91106
this.WhenAnyValue(view => view.ViewModel!.OverallRating)

src/NexusMods.App.UI/Pages/CollectionDownload/CollectionDownloadViewModel.cs

+13-16
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System.Diagnostics;
2+
using System.Reactive.Linq;
23
using Avalonia.Controls.Models.TreeDataGrid;
34
using Avalonia.Media.Imaging;
45
using DynamicData;
@@ -20,7 +21,6 @@
2021
using R3;
2122
using ReactiveUI;
2223
using ReactiveUI.Fody.Helpers;
23-
using ReactiveCommand = R3.ReactiveCommand;
2424

2525
namespace NexusMods.App.UI.Pages.CollectionDownload;
2626

@@ -34,9 +34,7 @@ public class CollectionDownloadViewModel : APageViewModel<ICollectionDownloadVie
3434
private readonly NexusModsDataProvider _nexusModsDataProvider;
3535
private readonly CollectionDownloader _collectionDownloader;
3636

37-
public CollectionDownloadTreeDataGridAdapter RequiredDownloadsAdapter { get; }
38-
39-
public CollectionDownloadTreeDataGridAdapter OptionalDownloadsAdapter { get; }
37+
public CollectionDownloadTreeDataGridAdapter TreeDataGridAdapter { get; }
4038

4139
public CollectionDownloadViewModel(
4240
IWindowManager windowManager,
@@ -58,10 +56,8 @@ public CollectionDownloadViewModel(
5856
TabTitle = _collection.Name;
5957
TabIcon = IconValues.Collections;
6058

61-
RequiredDownloadsAdapter = new CollectionDownloadTreeDataGridAdapter(_nexusModsDataProvider, revisionMetadata);
62-
RequiredDownloadsAdapter.ViewHierarchical.Value = false;
63-
OptionalDownloadsAdapter = new CollectionDownloadTreeDataGridAdapter(_nexusModsDataProvider, revisionMetadata);
64-
OptionalDownloadsAdapter.ViewHierarchical.Value = false;
59+
TreeDataGridAdapter = new CollectionDownloadTreeDataGridAdapter(_nexusModsDataProvider, revisionMetadata);
60+
TreeDataGridAdapter.ViewHierarchical.Value = false;
6561

6662
// TODO:
6763
CollectionStatusText = "TODO";
@@ -86,14 +82,12 @@ public CollectionDownloadViewModel(
8682
configureAwait: false
8783
);
8884

89-
InstallCollectionCommand = new ReactiveCommand<Unit>(canExecuteSource: Observable.Return(false), initialCanExecute: false);
85+
InstallCollectionCommand = new ReactiveCommand<Unit>(canExecuteSource: R3.Observable.Return(false), initialCanExecute: false);
9086

9187
this.WhenActivated(disposables =>
9288
{
93-
RequiredDownloadsAdapter.Activate();
94-
OptionalDownloadsAdapter.Activate();
95-
Disposable.Create(RequiredDownloadsAdapter, static adapter => adapter.Deactivate());
96-
Disposable.Create(OptionalDownloadsAdapter, static adapter => adapter.Deactivate());
89+
TreeDataGridAdapter.Activate();
90+
Disposable.Create(TreeDataGridAdapter, static adapter => adapter.Deactivate());
9791

9892
ImagePipelines.CreateObservable(_collection.Id, tileImagePipeline)
9993
.ObserveOnUIThreadDispatcher()
@@ -110,7 +104,7 @@ public CollectionDownloadViewModel(
110104
.Subscribe(this, static (bitmap, self) => self.AuthorAvatar = bitmap)
111105
.AddTo(disposables);
112106

113-
RequiredDownloadsAdapter.MessageSubject.Merge(OptionalDownloadsAdapter.MessageSubject).SubscribeAwait(
107+
TreeDataGridAdapter.MessageSubject.SubscribeAwait(
114108
onNextAsync: (message, cancellationToken) =>
115109
{
116110
return message.Item.Match(
@@ -158,11 +152,14 @@ public class CollectionDownloadTreeDataGridAdapter : TreeDataGridAdapter<ILibrar
158152
private readonly CollectionRevisionMetadata.ReadOnly _revisionMetadata;
159153

160154
public Subject<DownloadMessage> MessageSubject { get; } = new();
155+
public R3.ReactiveProperty<CollectionDownloadsFilter> Filter { get; } = new(value: CollectionDownloadsFilter.OnlyRequired);
161156

162157
private readonly Dictionary<ILibraryItemModel, IDisposable> _commandDisposables = new();
163158
private readonly IDisposable _activationDisposable;
164159

165-
public CollectionDownloadTreeDataGridAdapter(NexusModsDataProvider nexusModsDataProvider, CollectionRevisionMetadata.ReadOnly revisionMetadata)
160+
public CollectionDownloadTreeDataGridAdapter(
161+
NexusModsDataProvider nexusModsDataProvider,
162+
CollectionRevisionMetadata.ReadOnly revisionMetadata)
166163
{
167164
_nexusModsDataProvider = nexusModsDataProvider;
168165
_revisionMetadata = revisionMetadata;
@@ -213,7 +210,7 @@ protected override void BeforeModelDeactivationHook(ILibraryItemModel model)
213210

214211
protected override IObservable<IChangeSet<ILibraryItemModel, EntityId>> GetRootsObservable(bool viewHierarchical)
215212
{
216-
return _nexusModsDataProvider.ObserveCollectionItems(_revisionMetadata);
213+
return _nexusModsDataProvider.ObserveCollectionItems(_revisionMetadata, Filter.AsSystemObservable());
217214
}
218215

219216
protected override IColumn<ILibraryItemModel>[] CreateColumns(bool viewHierarchical)

src/NexusMods.App.UI/Pages/CollectionDownload/ICollectionDownloadViewModel.cs

+1-2
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,7 @@ namespace NexusMods.App.UI.Pages.CollectionDownload;
99

1010
public interface ICollectionDownloadViewModel : IPageViewModelInterface
1111
{
12-
CollectionDownloadTreeDataGridAdapter RequiredDownloadsAdapter { get; }
13-
CollectionDownloadTreeDataGridAdapter OptionalDownloadsAdapter { get; }
12+
CollectionDownloadTreeDataGridAdapter TreeDataGridAdapter { get; }
1413

1514
/// <inheritdoc cref="CollectionMetadata.Name"/>
1615
string Name { get; }

src/NexusMods.App.UI/Pages/LibraryPage/ILibraryItemWithAction.cs

+2
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ int IComparable<ILibraryItemWithAction>.CompareTo(ILibraryItemWithAction? other)
1818
{
1919
(ILibraryItemWithInstallAction, ILibraryItemWithDownloadAction) => -1,
2020
(ILibraryItemWithDownloadAction, ILibraryItemWithInstallAction) => 1,
21+
(ILibraryItemWithDownloadAction a, ILibraryItemWithDownloadAction b) => ((int)a.DownloadState.Value).CompareTo((int)b.DownloadState.Value),
22+
(ILibraryItemWithInstallAction a, ILibraryItemWithInstallAction b) => a.IsInstalled.Value.CompareTo(b.IsInstalled.Value),
2123
_ => 0,
2224
};
2325
}

src/NexusMods.App.UI/Pages/NexusModsDataProvider.cs

+14-2
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,12 @@
2525
namespace NexusMods.App.UI.Pages;
2626
using CollectionDownloadEntity = Abstractions.NexusModsLibrary.Models.CollectionDownload;
2727

28+
public enum CollectionDownloadsFilter
29+
{
30+
OnlyRequired,
31+
OnlyOptional,
32+
}
33+
2834
[UsedImplicitly]
2935
public class NexusModsDataProvider : ILibraryDataProvider, ILoadoutDataProvider
3036
{
@@ -38,13 +44,19 @@ public NexusModsDataProvider(IServiceProvider serviceProvider)
3844
}
3945

4046
public IObservable<IChangeSet<ILibraryItemModel, EntityId>> ObserveCollectionItems(
41-
CollectionRevisionMetadata.ReadOnly revisionMetadata)
47+
CollectionRevisionMetadata.ReadOnly revisionMetadata,
48+
IObservable<CollectionDownloadsFilter> filterObservable)
4249
{
4350
return _connection
4451
.ObserveDatoms(CollectionDownloadEntity.CollectionRevision, revisionMetadata)
4552
.AsEntityIds()
4653
.Transform(datom => CollectionDownloadEntity.Load(_connection.Db, datom.E))
47-
.Filter(static downloadEntity => downloadEntity.IsCollectionDownloadNexusMods() || downloadEntity.IsCollectionDownloadExternal())
54+
.FilterOnObservable(downloadEntity => filterObservable.Select(filter => filter switch
55+
{
56+
CollectionDownloadsFilter.OnlyRequired => !downloadEntity.IsOptional,
57+
CollectionDownloadsFilter.OnlyOptional => downloadEntity.IsOptional,
58+
}))
59+
.FilterImmutable(static downloadEntity => downloadEntity.IsCollectionDownloadNexusMods() || downloadEntity.IsCollectionDownloadExternal())
4860
.Transform(ILibraryItemModel (downloadEntity) =>
4961
{
5062
if (downloadEntity.TryGetAsCollectionDownloadNexusMods(out var nexusModsDownload))

src/Themes/NexusMods.Themes.NexusFluentDark/Styles/UserControls/CollectionDownloadPage/CollectionDownloadPageStyles.axaml

+7
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,13 @@
227227
<Setter Property="panels:Flex.AlignSelf" Value="Stretch" />
228228
<Setter Property="Padding" Value="0" />
229229
</Style>
230+
231+
<!-- NOTE(erri120): Hide the tab strip when there's only one tab -->
232+
<Style Selector="^ TabControl.SingleTab">
233+
<Style Selector="^ /template/ ItemsPresenter#PART_ItemsPresenter">
234+
<Setter Property="IsVisible" Value="False"/>
235+
</Style>
236+
</Style>
230237
</Style>
231238
</Style>
232239
</Styles>

0 commit comments

Comments
 (0)