Skip to content

Commit

Permalink
Merge branch 'main' into load-order-styling
Browse files Browse the repository at this point in the history
  • Loading branch information
insomnious committed Nov 26, 2024
2 parents af35b2d + 17c2d09 commit 55015af
Show file tree
Hide file tree
Showing 8 changed files with 92 additions and 67 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,7 @@ namespace NexusMods.App.UI.Pages.CollectionDownload;

public class CollectionDownloadDesignViewModel : APageViewModel<ICollectionDownloadViewModel>, ICollectionDownloadViewModel
{
public CollectionDownloadTreeDataGridAdapter RequiredDownloadsAdapter { get; } = null!;
public CollectionDownloadTreeDataGridAdapter OptionalDownloadsAdapter { get; } = null!;
public CollectionDownloadTreeDataGridAdapter TreeDataGridAdapter { get; } = null!;

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

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,28 +48,29 @@
</MenuFlyout>
</reactiveUi:ReactiveUserControl.Resources>

<StackPanel x:Name="Body">
<DockPanel x:Name="Body">

<!-- first row (header) -->
<Border x:Name="HeaderBorderBackground">
<Border x:Name="HeaderBorderBackground" DockPanel.Dock="Top">
<Border x:Name="HeaderBorder">

<StackPanel x:Name="Header">

<!-- first header row (image and metadata) -->
<Border x:Name="MainContentBorder">
<Grid x:Name="MainContent" ColumnDefinitions="Auto, *" >
<Grid x:Name="MainContent" ColumnDefinitions="Auto, *">

<!-- left column (image) -->
<Border Grid.Column="0" x:Name="CollectionImageBorder">
<Image x:Name="CollectionImage" />
</Border>

<!-- right column (metadata) -->
<Grid Grid.Column="1" x:Name="CollectionDetails" RowDefinitions="Auto,Auto,Auto,*" ColumnDefinitions="Auto">
<Grid Grid.Column="1" x:Name="CollectionDetails" RowDefinitions="Auto,Auto,Auto,*"
ColumnDefinitions="Auto">
<TextBlock Grid.Row="0" x:Name="Title">COLLECTION DOWNLOAD</TextBlock>
<TextBlock Grid.Row="1" x:Name="Heading" />
<Border Grid.Row="2" x:Name="TagsPanelBorder">
<TextBlock Grid.Row="1" x:Name="Heading" />
<Border Grid.Row="2" x:Name="TagsPanelBorder">
<StackPanel x:Name="TagsPanel">
<TextBlock x:Name="Revision" />
<StackPanel x:Name="AuthorStackPanel">
Expand All @@ -80,7 +81,7 @@
</StackPanel>
</StackPanel>
</Border>
<TextBlock Grid.Row="3" x:Name="Summary" />
<TextBlock Grid.Row="3" x:Name="Summary" />
</Grid>

</Grid>
Expand All @@ -106,7 +107,8 @@
<TextBlock x:Name="TotalSize" />
</StackPanel>
<StackPanel x:Name="OverallRatingPanel">
<icons:UnifiedIcon x:Name="OverallRatingIcon" Value="{x:Static icons:IconValues.CheckCircle}" />
<icons:UnifiedIcon x:Name="OverallRatingIcon"
Value="{x:Static icons:IconValues.CheckCircle}" />
<TextBlock x:Name="OverallRating" />
</StackPanel>
</StackPanel>
Expand All @@ -116,18 +118,19 @@
</Border>

<!-- second row (buttons) -->
<Border x:Name="ListHeaderRowBorder">
<Border x:Name="ListHeaderRowBorder" DockPanel.Dock="Top">
<panels:FlexPanel x:Name="ListHeaderRow">
<TextBlock x:Name="CollectionStatusText"/>
<TextBlock x:Name="CollectionStatusText" />
<controls:StandardButton x:Name="InstallButton" Text="Install" />
<controls:StandardButton x:Name="DownloadAllButton" Text="Download All"/>
<controls:StandardButton x:Name="FlyoutMenuButton" Flyout="{StaticResource CollectionMenuFlyout}" Text="..."/>
<controls:StandardButton x:Name="DownloadAllButton" Text="Download All" />
<controls:StandardButton x:Name="FlyoutMenuButton" Flyout="{StaticResource CollectionMenuFlyout}"
Text="..." />
</panels:FlexPanel>
</Border>

<!-- third row (tab control and datagrid) -->
<TabControl x:Name="TabControl">
<TabItem>
<TabItem x:Name="RequiredTab">
<TabItem.Header>
<StackPanel x:Name="RequiredModsPanel" Orientation="Horizontal">
<TextBlock>Required</TextBlock>
Expand All @@ -136,10 +139,9 @@
</Border>
</StackPanel>
</TabItem.Header>

<TreeDataGrid x:Name="RequiredDownloadsTree" />
</TabItem>
<TabItem>
<TabItem x:Name="OptionalTab">
<TabItem.Header>
<StackPanel x:Name="OptionalModsPanel" Orientation="Horizontal">
<TextBlock>Optional</TextBlock>
Expand All @@ -151,7 +153,6 @@
<TreeDataGrid x:Name="OptionalDownloadsTree" />
</TabItem>
</TabControl>

</StackPanel>
</DockPanel>

</reactiveUi:ReactiveUserControl>
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using System.Diagnostics;
using System.Reactive.Disposables;
using System.Reactive.Linq;
using Avalonia.Media;
Expand All @@ -15,18 +16,18 @@ public CollectionDownloadView()
{
InitializeComponent();

TreeDataGridViewHelper.SetupTreeDataGridAdapter<CollectionDownloadView, ICollectionDownloadViewModel, ILibraryItemModel, EntityId>(this, RequiredDownloadsTree, vm => vm.RequiredDownloadsAdapter);
TreeDataGridViewHelper.SetupTreeDataGridAdapter<CollectionDownloadView, ICollectionDownloadViewModel, ILibraryItemModel, EntityId>(this, OptionalDownloadsTree, vm => vm.OptionalDownloadsAdapter);
TreeDataGridViewHelper.SetupTreeDataGridAdapter<CollectionDownloadView, ICollectionDownloadViewModel, ILibraryItemModel, EntityId>(this, RequiredDownloadsTree, vm => vm.TreeDataGridAdapter);
TreeDataGridViewHelper.SetupTreeDataGridAdapter<CollectionDownloadView, ICollectionDownloadViewModel, ILibraryItemModel, EntityId>(this, OptionalDownloadsTree, vm => vm.TreeDataGridAdapter);

this.WhenActivated(d =>
{
this.BindCommand(ViewModel, vm => vm.DownloadAllCommand, view => view.DownloadAllButton)
.DisposeWith(d);
this.OneWayBind(ViewModel, vm => vm.RequiredDownloadsAdapter.Source.Value, view => view.RequiredDownloadsTree.Source)
this.OneWayBind(ViewModel, vm => vm.TreeDataGridAdapter.Source.Value, view => view.RequiredDownloadsTree.Source)
.DisposeWith(d);
this.OneWayBind(ViewModel, vm => vm.OptionalDownloadsAdapter.Source.Value, view => view.OptionalDownloadsTree.Source)
this.OneWayBind(ViewModel, vm => vm.TreeDataGridAdapter.Source.Value, view => view.OptionalDownloadsTree.Source)
.DisposeWith(d);
this.WhenAnyValue(view => view.ViewModel!.BackgroundImage)
Expand Down Expand Up @@ -78,14 +79,28 @@ public CollectionDownloadView()
this.OneWayBind(ViewModel, vm => vm.RevisionNumber, view => view.Revision.Text, revision => $"Revision {revision}")
.DisposeWith(d);
this.WhenAnyValue(view => view.TabControl.SelectedItem)
.Select(selectedItem =>
{
if (ReferenceEquals(selectedItem, RequiredTab)) return CollectionDownloadsFilter.OnlyRequired;
if (ReferenceEquals(selectedItem, OptionalTab)) return CollectionDownloadsFilter.OnlyOptional;
throw new UnreachableException();
})
.Subscribe(filter =>
{
ViewModel!.TreeDataGridAdapter.Filter.Value = filter;
})
.DisposeWith(d);
this.WhenAnyValue(view => view.ViewModel)
.WhereNotNull()
.Subscribe(vm =>
.Select(static vm => vm.OptionalDownloadsCount > 0)
.Subscribe(hasOptionalDownloads =>
{
if (vm.OptionalDownloadsCount == 0)
{
// TabControl.IsVisible = false;
}
if (hasOptionalDownloads) TabControl.Classes.Remove("SingleTab");
else TabControl.Classes.Add("SingleTab");
if (!hasOptionalDownloads) TabControl.SelectedItem = RequiredTab;
}).DisposeWith(d);
this.WhenAnyValue(view => view.ViewModel!.OverallRating)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Diagnostics;
using System.Reactive.Linq;
using Avalonia.Controls.Models.TreeDataGrid;
using Avalonia.Media.Imaging;
using DynamicData;
Expand All @@ -20,7 +21,6 @@
using R3;
using ReactiveUI;
using ReactiveUI.Fody.Helpers;
using ReactiveCommand = R3.ReactiveCommand;

namespace NexusMods.App.UI.Pages.CollectionDownload;

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

public CollectionDownloadTreeDataGridAdapter RequiredDownloadsAdapter { get; }

public CollectionDownloadTreeDataGridAdapter OptionalDownloadsAdapter { get; }
public CollectionDownloadTreeDataGridAdapter TreeDataGridAdapter { get; }

public CollectionDownloadViewModel(
IWindowManager windowManager,
Expand All @@ -58,10 +56,8 @@ public CollectionDownloadViewModel(
TabTitle = _collection.Name;
TabIcon = IconValues.Collections;

RequiredDownloadsAdapter = new CollectionDownloadTreeDataGridAdapter(_nexusModsDataProvider, revisionMetadata);
RequiredDownloadsAdapter.ViewHierarchical.Value = false;
OptionalDownloadsAdapter = new CollectionDownloadTreeDataGridAdapter(_nexusModsDataProvider, revisionMetadata);
OptionalDownloadsAdapter.ViewHierarchical.Value = false;
TreeDataGridAdapter = new CollectionDownloadTreeDataGridAdapter(_nexusModsDataProvider, revisionMetadata);
TreeDataGridAdapter.ViewHierarchical.Value = false;

// TODO:
CollectionStatusText = "TODO";
Expand All @@ -86,14 +82,12 @@ public CollectionDownloadViewModel(
configureAwait: false
);

InstallCollectionCommand = new ReactiveCommand<Unit>(canExecuteSource: Observable.Return(false), initialCanExecute: false);
InstallCollectionCommand = new ReactiveCommand<Unit>(canExecuteSource: R3.Observable.Return(false), initialCanExecute: false);

this.WhenActivated(disposables =>
{
RequiredDownloadsAdapter.Activate();
OptionalDownloadsAdapter.Activate();
Disposable.Create(RequiredDownloadsAdapter, static adapter => adapter.Deactivate());
Disposable.Create(OptionalDownloadsAdapter, static adapter => adapter.Deactivate());
TreeDataGridAdapter.Activate();
Disposable.Create(TreeDataGridAdapter, static adapter => adapter.Deactivate());
ImagePipelines.CreateObservable(_collection.Id, tileImagePipeline)
.ObserveOnUIThreadDispatcher()
Expand All @@ -110,7 +104,7 @@ public CollectionDownloadViewModel(
.Subscribe(this, static (bitmap, self) => self.AuthorAvatar = bitmap)
.AddTo(disposables);
RequiredDownloadsAdapter.MessageSubject.Merge(OptionalDownloadsAdapter.MessageSubject).SubscribeAwait(
TreeDataGridAdapter.MessageSubject.SubscribeAwait(
onNextAsync: (message, cancellationToken) =>
{
return message.Item.Match(
Expand Down Expand Up @@ -158,11 +152,14 @@ public class CollectionDownloadTreeDataGridAdapter : TreeDataGridAdapter<ILibrar
private readonly CollectionRevisionMetadata.ReadOnly _revisionMetadata;

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

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

public CollectionDownloadTreeDataGridAdapter(NexusModsDataProvider nexusModsDataProvider, CollectionRevisionMetadata.ReadOnly revisionMetadata)
public CollectionDownloadTreeDataGridAdapter(
NexusModsDataProvider nexusModsDataProvider,
CollectionRevisionMetadata.ReadOnly revisionMetadata)
{
_nexusModsDataProvider = nexusModsDataProvider;
_revisionMetadata = revisionMetadata;
Expand Down Expand Up @@ -213,7 +210,7 @@ protected override void BeforeModelDeactivationHook(ILibraryItemModel model)

protected override IObservable<IChangeSet<ILibraryItemModel, EntityId>> GetRootsObservable(bool viewHierarchical)
{
return _nexusModsDataProvider.ObserveCollectionItems(_revisionMetadata);
return _nexusModsDataProvider.ObserveCollectionItems(_revisionMetadata, Filter.AsSystemObservable());
}

protected override IColumn<ILibraryItemModel>[] CreateColumns(bool viewHierarchical)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,7 @@ namespace NexusMods.App.UI.Pages.CollectionDownload;

public interface ICollectionDownloadViewModel : IPageViewModelInterface
{
CollectionDownloadTreeDataGridAdapter RequiredDownloadsAdapter { get; }
CollectionDownloadTreeDataGridAdapter OptionalDownloadsAdapter { get; }
CollectionDownloadTreeDataGridAdapter TreeDataGridAdapter { get; }

/// <inheritdoc cref="CollectionMetadata.Name"/>
string Name { get; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ int IComparable<ILibraryItemWithAction>.CompareTo(ILibraryItemWithAction? other)
{
(ILibraryItemWithInstallAction, ILibraryItemWithDownloadAction) => -1,
(ILibraryItemWithDownloadAction, ILibraryItemWithInstallAction) => 1,
(ILibraryItemWithDownloadAction a, ILibraryItemWithDownloadAction b) => ((int)a.DownloadState.Value).CompareTo((int)b.DownloadState.Value),
(ILibraryItemWithInstallAction a, ILibraryItemWithInstallAction b) => a.IsInstalled.Value.CompareTo(b.IsInstalled.Value),
_ => 0,
};
}
Expand Down
16 changes: 14 additions & 2 deletions src/NexusMods.App.UI/Pages/NexusModsDataProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,12 @@
namespace NexusMods.App.UI.Pages;
using CollectionDownloadEntity = Abstractions.NexusModsLibrary.Models.CollectionDownload;

public enum CollectionDownloadsFilter
{
OnlyRequired,
OnlyOptional,
}

[UsedImplicitly]
public class NexusModsDataProvider : ILibraryDataProvider, ILoadoutDataProvider
{
Expand All @@ -38,13 +44,19 @@ public NexusModsDataProvider(IServiceProvider serviceProvider)
}

public IObservable<IChangeSet<ILibraryItemModel, EntityId>> ObserveCollectionItems(
CollectionRevisionMetadata.ReadOnly revisionMetadata)
CollectionRevisionMetadata.ReadOnly revisionMetadata,
IObservable<CollectionDownloadsFilter> filterObservable)
{
return _connection
.ObserveDatoms(CollectionDownloadEntity.CollectionRevision, revisionMetadata)
.AsEntityIds()
.Transform(datom => CollectionDownloadEntity.Load(_connection.Db, datom.E))
.Filter(static downloadEntity => downloadEntity.IsCollectionDownloadNexusMods() || downloadEntity.IsCollectionDownloadExternal())
.FilterOnObservable(downloadEntity => filterObservable.Select(filter => filter switch
{
CollectionDownloadsFilter.OnlyRequired => !downloadEntity.IsOptional,
CollectionDownloadsFilter.OnlyOptional => downloadEntity.IsOptional,
}))
.FilterImmutable(static downloadEntity => downloadEntity.IsCollectionDownloadNexusMods() || downloadEntity.IsCollectionDownloadExternal())
.Transform(ILibraryItemModel (downloadEntity) =>
{
if (downloadEntity.TryGetAsCollectionDownloadNexusMods(out var nexusModsDownload))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@
xmlns:panels="clr-namespace:Avalonia.Labs.Panels;assembly=Avalonia.Labs.Panels"
xmlns:collections="clr-namespace:NexusMods.App.UI.Pages.CollectionDownload;assembly=NexusMods.App.UI"
xmlns:icons="clr-namespace:NexusMods.Icons;assembly=NexusMods.Icons">

<Design.PreviewWith>
<Border Width="500" Height="500">
<Border Width="800" Height="500">
<Border.Resources>
<collections:CollectionDownloadDesignViewModel x:Key="CollectionDownloadPageDesignViewModel" />
</Border.Resources>
Expand All @@ -21,27 +22,19 @@
</LinearGradientBrush>
</Style.Resources>

<Style Selector="^ StackPanel#Body">
<Setter Property="Orientation" Value="Vertical" />

<Style Selector="^ DockPanel#Body">
<Style Selector="^ Border#HeaderBorderBackground">

<Style Selector="^ Border#HeaderBorder">
<!-- <Setter Property="MaxWidth" Value="628" /> -->
<Setter Property="HorizontalAlignment" Value="Stretch" />
<Setter Property="Padding" Value="24,24,24,16" />
<Setter Property="Background" Value="{StaticResource HeaderImageLinearGradientBrush}" />


<Style Selector="^ StackPanel#Header">
<!-- -->
<!-- <Setter Property="HorizontalAlignment" Value="Left"/> -->

<!-- NOTE(insomnious): Some weird stuff happening here with max width and backgrounds. Layout wise

<!-- NOTE(insomnious): Some weird stuff happening here with max width and backgrounds. Layout wise
it's working, as things are aligned correctly, but the background is not being applied correctly.
After chatting with @Al12rs, we are leaving this for now as we can't fully test this (yet) and we
don't want to add extra layout code for no reason -->


<Style Selector="^ StackPanel#Header">
<Style Selector="^ Border#MainContentBorder">
<!-- <Setter Property="Background" Value="DarkGoldenrod" /> -->
<Setter Property="Padding" Value="0, 0, 0, 24" />
Expand Down Expand Up @@ -133,7 +126,7 @@
Value="{StaticResource NeutralTranslucentSubduedBrush}" />
<Setter Property="TextWrapping" Value="Wrap" />
<Setter Property="TextTrimming" Value="CharacterEllipsis" />
</Style>
</Style>

</Style>

Expand Down Expand Up @@ -227,6 +220,13 @@
<Setter Property="panels:Flex.AlignSelf" Value="Stretch" />
<Setter Property="Padding" Value="0" />
</Style>

<!-- NOTE(erri120): Hide the tab strip when there's only one tab -->
<Style Selector="^ TabControl.SingleTab">
<Style Selector="^ /template/ ItemsPresenter#PART_ItemsPresenter">
<Setter Property="IsVisible" Value="False"/>
</Style>
</Style>
</Style>
</Style>
</Styles>

0 comments on commit 55015af

Please sign in to comment.