Skip to content

Commit

Permalink
Merge pull request #1760 from Nexus-Mods/feat/multiple-loadouts-part2
Browse files Browse the repository at this point in the history
Multiple loadouts part2
  • Loading branch information
Al12rs authored Jul 15, 2024
2 parents e06c537 + 181cdd8 commit 55ecac9
Show file tree
Hide file tree
Showing 8 changed files with 337 additions and 103 deletions.
21 changes: 10 additions & 11 deletions src/NexusMods.App.UI/Controls/LoadoutBadge/LoadoutBadge.axaml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<reactiveUi:ReactiveUserControl x:TypeArguments="loadoutBadge:ILoadoutBadgeViewModel"
<reactiveUi:ReactiveUserControl x:TypeArguments="loadoutBadge:ILoadoutBadgeViewModel"
xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
Expand All @@ -7,22 +7,21 @@
xmlns:spinner="clr-namespace:NexusMods.App.UI.Controls.Spinner"
xmlns:reactiveUi="http://reactiveui.net"
xmlns:loadoutBadge="clr-namespace:NexusMods.App.UI.Controls.LoadoutBadge"
xmlns:panels="clr-namespace:Avalonia.Labs.Panels;assembly=Avalonia.Labs.Panels"
mc:Ignorable="d" d:DesignWidth="120" d:DesignHeight="120"
x:Class="NexusMods.App.UI.Controls.LoadoutBadge.LoadoutBadge"
HorizontalAlignment="Right"
VerticalAlignment="Top">
<Design.DataContext>
<loadoutBadge:LoadoutBadgeDesignViewModel />
</Design.DataContext>

<Border x:Name="OuterBorder">
<StackPanel x:Name="ContentsStackPanel"
Orientation="Horizontal">

<panels:FlexPanel x:Name="ContentsFlexPanel">
<Border>
<spinner:Spinner x:Name="Spinner" />
<icons:UnifiedIcon x:Name="Icon"
Classes="Check" />
<TextBlock x:Name="ShortName"
Classes="BodyLGBold"/>
</StackPanel>
</Border>
</Border>
<icons:UnifiedIcon x:Name="Icon"
Classes="Check" />
<TextBlock x:Name="ShortName"/>
</panels:FlexPanel>
</reactiveUi:ReactiveUserControl>
25 changes: 25 additions & 0 deletions src/NexusMods.App.UI/Controls/LoadoutCard/ILoadoutCardViewModel.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,31 @@
using System.Reactive;
using Avalonia.Media;
using NexusMods.App.UI.Controls.LoadoutBadge;
using ReactiveUI;

namespace NexusMods.App.UI.Controls.LoadoutCard;

public interface ILoadoutCardViewModel : IViewModelInterface
{
ILoadoutBadgeViewModel LoadoutBadgeViewModel { get; }

string LoadoutName { get; }

IImage LoadoutImage { get; }

bool IsLoadoutApplied { get; }

string HumanizedLoadoutLastApplyTime { get; }

string HumanizedLoadoutCreationTime { get; }

string LoadoutModCount { get; }

bool IsDeleting { get; }

ReactiveCommand<Unit, Unit> VisitLoadoutCommand { get; }

ReactiveCommand<Unit, Unit> CloneLoadoutCommand { get; }

ReactiveCommand<Unit, Unit> DeleteLoadoutCommand { get; }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
using System.Reactive;
using System.Reactive.Disposables;
using System.Reactive.Linq;
using Avalonia.Media;
using Avalonia.Media.Imaging;
using Avalonia.Platform;
using NexusMods.App.UI.Controls.LoadoutBadge;
using ReactiveUI;
using ReactiveUI.Fody.Helpers;

namespace NexusMods.App.UI.Controls.LoadoutCard;

public class LoadoutCardDesignViewModel : AViewModel<ILoadoutCardViewModel>, ILoadoutCardViewModel
{
public LoadoutCardDesignViewModel()
{
this.WhenActivated(d =>
{
// Cycle thorough all the states for preview purposes
Observable.Interval(TimeSpan.FromSeconds(2.5))
.Subscribe(_ =>
{
IsDeleting = !IsDeleting;
})
.DisposeWith(d);
}
);
}

public ILoadoutBadgeViewModel LoadoutBadgeViewModel { get; } = new LoadoutBadgeDesignViewModel();
public string LoadoutName { get; } = "Loadout B";
public IImage LoadoutImage { get; } = new Bitmap(AssetLoader.Open(new Uri("avares://NexusMods.App.UI/Assets/DesignTime/cyberpunk_game.png")));

public bool IsLoadoutApplied { get; } = true;
public string HumanizedLoadoutLastApplyTime { get; } = "Last applied 2 months ago";
public string HumanizedLoadoutCreationTime { get; } = "Created 10 months ago";
public string LoadoutModCount { get; } = "Mods 276";
[Reactive] public bool IsDeleting { get; private set; } = true;
public ReactiveCommand<Unit, Unit> VisitLoadoutCommand { get; } = ReactiveCommand.Create(() => { });
public ReactiveCommand<Unit, Unit> CloneLoadoutCommand { get; } = ReactiveCommand.Create(() => { });
public ReactiveCommand<Unit, Unit> DeleteLoadoutCommand { get; } = ReactiveCommand.Create(() => { });
}
119 changes: 68 additions & 51 deletions src/NexusMods.App.UI/Controls/LoadoutCard/LoadoutCardView.axaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,79 +7,96 @@
xmlns:panels="clr-namespace:Avalonia.Labs.Panels;assembly=Avalonia.Labs.Panels"
xmlns:icons="clr-namespace:NexusMods.Icons;assembly=NexusMods.Icons"
xmlns:loadoutBadge="clr-namespace:NexusMods.App.UI.Controls.LoadoutBadge"
xmlns:spinner="clr-namespace:NexusMods.App.UI.Controls.Spinner"
mc:Ignorable="d" d:DesignWidth="250" d:DesignHeight="400"
x:Class="NexusMods.App.UI.Controls.LoadoutCard.LoadoutCardView">
<Button x:Name="CardOuterButton">
<Design.DataContext>
<loadoutCard:LoadoutCardDesignViewModel />
</Design.DataContext>

<Border x:Name="ContainerBorder">
<Grid>
<Button x:Name="CardOuterButton">

<panels:FlexPanel x:Name="CardOuterFlexPanel">
<panels:FlexPanel x:Name="CardOuterFlexPanel">

<Border x:Name="ImageSectionBorder">
<Grid>
<Image x:Name="GameImage"
Source="avares://NexusMods.App.UI/Assets/DesignTime/cyberpunk_game.png" />
<Rectangle x:Name="GradientLayerRectangle" />
<loadoutBadge:LoadoutBadge x:Name="LoadoutBadge" />
</Grid>
</Border>
<Border x:Name="ImageSectionBorder">
<Grid>
<Image x:Name="GameImage" />
<Rectangle x:Name="GradientLayerRectangle" />
<loadoutBadge:LoadoutBadge x:Name="LoadoutBadge" Classes="CardSize" />
</Grid>
</Border>

<Border x:Name="DetailsSectionBorder">
<Border x:Name="DetailsSectionBorder">

<panels:FlexPanel x:Name="DetailsSectionFlexPanel">
<panels:FlexPanel x:Name="DetailsSectionFlexPanel">

<TextBlock x:Name="LoadoutNameTextBlock"
Classes="BodyLGBold"
Text="Loadout A" />
<TextBlock x:Name="LoadoutNameTextBlock"
Classes="BodyLGBold" />

<panels:FlexPanel x:Name="BodyAndActionsGroupFlexPanel">
<panels:FlexPanel x:Name="BodyAndActionsGroupFlexPanel">

<panels:FlexPanel x:Name="DetailsBodyFlexPanel">
<panels:FlexPanel x:Name="DetailsBodyFlexPanel">

<panels:FlexPanel x:Name="CurrentlyAppliedFlexPanel">
<panels:FlexPanel x:Name="CurrentlyAppliedFlexPanel">

<TextBlock x:Name="CurrentlyAppliedTextBlock"
Classes="BodySMBold"
Text="Currently Applied" />
<icons:UnifiedIcon x:Name="AppliedCheckBoxIcon"
Classes="CheckBox" />
<TextBlock x:Name="CurrentlyAppliedTextBlock"
Classes="BodySMBold"
Text="Currently Applied" />
<icons:UnifiedIcon x:Name="AppliedCheckBoxIcon"
Classes="CheckBox" />

</panels:FlexPanel>
</panels:FlexPanel>

<TextBlock x:Name="LastAppliedTimeTextBlock"
Classes="BodySMNormal ForegroundSubdued"
Text="Last applied 2 months ago"
IsVisible="False" />
<TextBlock x:Name="LastAppliedTimeTextBlock"
Classes="BodySMNormal ForegroundSubdued"
IsVisible="False" />

<TextBlock x:Name="CreatedTimeTextBlock"
Classes="BodySMNormal ForegroundSubdued"
Text="Created 10 months ago" />
<TextBlock x:Name="CreatedTimeTextBlock"
Classes="BodySMNormal ForegroundSubdued"/>

<TextBlock x:Name="NumberOfModsTextBlock"
Classes="BodySMNormal ForegroundSubdued"
Text="Mods 276" />
<TextBlock x:Name="NumberOfModsTextBlock"
Classes="BodySMNormal ForegroundSubdued"/>

</panels:FlexPanel>
</panels:FlexPanel>

<panels:FlexPanel x:Name="ActionsFlexPanel">
<panels:FlexPanel x:Name="ActionsFlexPanel">

<Button x:Name="CreateCopyButton"
Classes="Rounded Primary">
<StackPanel HorizontalAlignment="Center">
<TextBlock Classes="BodySMBold" Text="Create Copy" />
</StackPanel>
</Button>
<Button x:Name="CreateCopyButton"
Classes="Rounded Primary">
<StackPanel HorizontalAlignment="Center">
<TextBlock Classes="BodySMBold" Text="Create Copy" />
</StackPanel>
</Button>


<Button x:Name="DeleteButton"
Classes="Rounded Primary">
<icons:UnifiedIcon Classes="TrashCanOutline" />
</Button>
</panels:FlexPanel>
<Button x:Name="DeleteButton"
Classes="Rounded Primary">
<icons:UnifiedIcon Classes="TrashCanOutline" />
</Button>
</panels:FlexPanel>

</panels:FlexPanel>

</panels:FlexPanel>
</panels:FlexPanel>
</Border>

</panels:FlexPanel>
</Border>
</Button>

<!-- Needs to be on top of the card button to avoid the disabled opacity -->
<panels:FlexPanel x:Name="OverlayFlexPanel" IsVisible="False">
<panels:FlexPanel x:Name="DeletingSpinnerFlexPanel">
<spinner:Spinner x:Name="DeletingSpinner" />
<TextBlock x:Name="DeletingTextBlock"
Classes="BodyXLNormal ForegroundSubdued"
Text="Deleting..." />
</panels:FlexPanel>
<Border />
</panels:FlexPanel>
</Grid>
</Border>


</panels:FlexPanel>
</Button>
</reactiveUi:ReactiveUserControl>
86 changes: 86 additions & 0 deletions src/NexusMods.App.UI/Controls/LoadoutCard/LoadoutCardView.axaml.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
using System.Reactive.Disposables;
using System.Reactive.Linq;
using Avalonia.ReactiveUI;
using ReactiveUI;

namespace NexusMods.App.UI.Controls.LoadoutCard;

Expand All @@ -7,6 +10,89 @@ public partial class LoadoutCardView : ReactiveUserControl<ILoadoutCardViewModel
public LoadoutCardView()
{
InitializeComponent();

this.WhenActivated(d =>
{
// LoadoutBadge
this.OneWayBind(ViewModel,
vm => vm.LoadoutBadgeViewModel,
view => view.LoadoutBadge.ViewModel)
.DisposeWith(d);

// Game Image
this.OneWayBind(ViewModel,
vm => vm.LoadoutImage,
view => view.GameImage.Source)
.DisposeWith(d);

// Loadout Name
this.OneWayBind(ViewModel,
vm => vm.LoadoutName,
view => view.LoadoutNameTextBlock.Text)
.DisposeWith(d);

// Currently applied visibility
this.OneWayBind(ViewModel,
vm => vm.IsLoadoutApplied,
view => view.CurrentlyAppliedFlexPanel.IsVisible)
.DisposeWith(d);

// Last applied visibility
this.WhenAnyValue(view => view.ViewModel!.IsLoadoutApplied)
.Select(isApplied => !isApplied)
.OnUI()
.BindToView(this, view => view.LastAppliedTimeTextBlock.IsVisible)
.DisposeWith(d);

// Last applied time
this.OneWayBind(ViewModel,
vm => vm.HumanizedLoadoutLastApplyTime,
view => view.LastAppliedTimeTextBlock.Text)
.DisposeWith(d);

// Created time
this.OneWayBind(ViewModel,
vm => vm.HumanizedLoadoutCreationTime,
view => view.CreatedTimeTextBlock.Text)
.DisposeWith(d);

// Mod count
this.OneWayBind(ViewModel,
vm => vm.LoadoutModCount,
view => view.NumberOfModsTextBlock.Text)
.DisposeWith(d);

// Deleting state
this.WhenAnyValue(view => view.ViewModel!.IsDeleting)
.OnUI()
.Subscribe(isDeleting =>
{
IsEnabled = !isDeleting;
OverlayFlexPanel.IsVisible = isDeleting;
CreateCopyButton.IsVisible = !isDeleting;
DeleteButton.IsVisible = !isDeleting;
})
.DisposeWith(d);

// Clone loadout command
this.BindCommand(ViewModel,
vm => vm.CloneLoadoutCommand,
view => view.CreateCopyButton)
.DisposeWith(d);

// Delete loadout command
this.BindCommand(ViewModel,
vm => vm.DeleteLoadoutCommand,
view => view.DeleteButton)
.DisposeWith(d);

// Visit loadout command
this.BindCommand(ViewModel,
vm => vm.DeleteLoadoutCommand,
view => view.DeleteButton)
.DisposeWith(d);
}
);
}
}

6 changes: 6 additions & 0 deletions src/NexusMods.App.UI/NexusMods.App.UI.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -561,6 +561,12 @@
<Compile Update="Controls\Settings\Section\SettingSectionViewModel.cs">
<DependentUpon>ISettingSectionViewModel.cs</DependentUpon>
</Compile>
<Compile Update="Controls\LoadoutBadge\LoadoutBadgeDesignViewModel.cs">
<DependentUpon>ILoadoutBadgeViewModel.cs</DependentUpon>
</Compile>
<Compile Update="Controls\LoadoutCard\LoadoutCardDesignViewModel.cs">
<DependentUpon>ILoadoutCardViewModel.cs</DependentUpon>
</Compile>
</ItemGroup>

<ItemGroup>
Expand Down
Loading

0 comments on commit 55ecac9

Please sign in to comment.