This commit is contained in:
Pascal
2025-11-14 11:35:40 +01:00
parent cd766f73fc
commit b4e4154445
8 changed files with 304 additions and 26 deletions

View File

@@ -8,5 +8,6 @@
<FluentTheme DensityStyle="Normal" /> <FluentTheme DensityStyle="Normal" />
<!-- <FluentTheme DensityStyle="Compact" /> --> <!-- <FluentTheme DensityStyle="Compact" /> -->
<!-- <SimpleTheme /> --> <!-- <SimpleTheme /> -->
<StyleInclude Source="avares://ModpackUpdater.Apps.Manager/Assets/Styles/StylesEnhancedDefaults.axaml"/>
</Application.Styles> </Application.Styles>
</Application> </Application>

View File

@@ -0,0 +1,16 @@
<Styles xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Design.PreviewWith>
<Border Padding="20">
<!-- Add Controls for Previewer Here -->
</Border>
</Design.PreviewWith>
<Style Selector="Label">
<Setter Property="Padding" Value="0"/>
</Style>
<Style Selector="ComboBox">
<Setter Property="HorizontalAlignment" Value="Stretch"/>
</Style>
</Styles>

View File

@@ -0,0 +1,3 @@
<Weavers>
<PropertyChanged/>
</Weavers>

View File

@@ -3,7 +3,6 @@
<PropertyGroup> <PropertyGroup>
<OutputType>WinExe</OutputType> <OutputType>WinExe</OutputType>
<ApplicationIcon>Assets\app.ico</ApplicationIcon> <ApplicationIcon>Assets\app.ico</ApplicationIcon>
<AssemblyName>MinecraftModpackUpdateManager</AssemblyName>
<IncludeAllContentForSelfExtract>true</IncludeAllContentForSelfExtract> <IncludeAllContentForSelfExtract>true</IncludeAllContentForSelfExtract>
<BuiltInComInteropSupport>true</BuiltInComInteropSupport> <BuiltInComInteropSupport>true</BuiltInComInteropSupport>
<AvaloniaUseCompiledBindingsByDefault>true</AvaloniaUseCompiledBindingsByDefault> <AvaloniaUseCompiledBindingsByDefault>true</AvaloniaUseCompiledBindingsByDefault>
@@ -22,6 +21,7 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Avalonia.Controls.DataGrid" Version="11.3.8" />
<PackageReference Include="MessageBox.Avalonia" Version="3.3.0" /> <PackageReference Include="MessageBox.Avalonia" Version="3.3.0" />
<PackageReference Include="EPPlus" Version="8.2.1" /> <PackageReference Include="EPPlus" Version="8.2.1" />
<PackageReference Include="NGitLab" Version="11.0.1" /> <PackageReference Include="NGitLab" Version="11.0.1" />
@@ -42,6 +42,7 @@
<IncludeAssets Condition="'$(Configuration)' != 'Debug'">None</IncludeAssets> <IncludeAssets Condition="'$(Configuration)' != 'Debug'">None</IncludeAssets>
<PrivateAssets Condition="'$(Configuration)' != 'Debug'">All</PrivateAssets> <PrivateAssets Condition="'$(Configuration)' != 'Debug'">All</PrivateAssets>
</PackageReference> </PackageReference>
<PackageReference Include="PropertyChanged.Fody" Version="4.1.0" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

View File

@@ -6,8 +6,10 @@
xmlns:modpackUpdater="clr-namespace:ModpackUpdater;assembly=ModpackUpdater" xmlns:modpackUpdater="clr-namespace:ModpackUpdater;assembly=ModpackUpdater"
xmlns:local="clr-namespace:ModpackUpdater.Apps.Manager.Ui" xmlns:local="clr-namespace:ModpackUpdater.Apps.Manager.Ui"
xmlns:manager="clr-namespace:ModpackUpdater.Apps.Manager" xmlns:manager="clr-namespace:ModpackUpdater.Apps.Manager"
xmlns:vm="clr-namespace:ModpackUpdater.Apps.Manager.Ui.Models"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450" mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="ModpackUpdater.Apps.Manager.Ui.MainWindow" x:Class="ModpackUpdater.Apps.Manager.Ui.MainWindow"
x:DataType="vm:MainWindowViewModel"
Title="Minecraft Modpack Manager" Title="Minecraft Modpack Manager"
Padding="3"> Padding="3">
@@ -47,19 +49,51 @@
Grid.Column="0" Grid.Column="0"
Margin="3"/> Margin="3"/>
<!-- ... --> <DataGrid
x:Name="DataGridActions"
Grid.Column="1"
Margin="3"
ItemsSource="{Binding Actions}"
SelectedItem="{Binding SelectedAction}">
<DataGrid.Columns>
<DataGridTextColumn
Header="Id"
Binding="{Binding InheritedId}"/>
<DataGridTextColumn
Header="Side"
Binding="{Binding InheritedSide}"/>
<DataGridTextColumn
Header="Update type"
Binding="{Binding InheritedUpdateType}"
IsVisible="{Binding IsUpdate}"/>
<DataGridTextColumn
Header="Source type"
Binding="{Binding InheritedSourceType}"/>
<DataGridTextColumn
Header="Dest path"
Binding="{Binding InheritedDestPath}"/>
</DataGrid.Columns>
</DataGrid>
<ScrollViewer <ScrollViewer
x:Name="ScrollViewerInstallAction"
Grid.Column="2" Grid.Column="2"
Margin="3"
DataContext="{Binding SelectedAction}"
VerticalScrollBarVisibility="Auto"> VerticalScrollBarVisibility="Auto">
<StackPanel> <StackPanel
Spacing="6">
<!-- Update --> <!-- Update -->
<StackPanel <StackPanel
x:Name="StackPanelUpdate" Spacing="6"
Margin="3" IsVisible="{Binding IsUpdate}">
Spacing="6">
<!-- Header --> <!-- Header -->
<StackPanel Orientation="Horizontal" Spacing="6"> <StackPanel Orientation="Horizontal" Spacing="6">
@@ -69,7 +103,9 @@
<!-- Inherit from --> <!-- Inherit from -->
<Label Content="Inherit from" Target="TextBoxUpdateActionInheritFrom"/> <Label Content="Inherit from" Target="TextBoxUpdateActionInheritFrom"/>
<TextBox x:Name="TextBoxUpdateActionInheritFrom" Text="{Binding InheritFrom, DataType=modpackUpdater:UpdateAction}"/> <TextBox
x:Name="TextBoxUpdateActionInheritFrom"
Text="{Binding InheritFrom}"/>
<!-- Source type --> <!-- Source type -->
<Label Content="Source type" Target="ComboBoxUpdateActionSourceType"/> <Label Content="Source type" Target="ComboBoxUpdateActionSourceType"/>
@@ -78,18 +114,17 @@
ItemsSource="{x:Static local:MainWindow.UpdateActionTypes}" ItemsSource="{x:Static local:MainWindow.UpdateActionTypes}"
DisplayMemberBinding="{Binding Value}" DisplayMemberBinding="{Binding Value}"
SelectedValueBinding="{Binding Key}" SelectedValueBinding="{Binding Key}"
SelectedValue="{Binding Type, DataType=modpackUpdater:UpdateAction}"/> SelectedValue="{Binding Type}"/>
<!-- Is Directory --> <!-- Is Directory -->
<CheckBox <CheckBox
x:Name="CheckBoxUpdateActionIsDir" x:Name="CheckBoxUpdateActionIsDir"
Content="Is Directory" Content="Is Directory"
IsChecked="{Binding IsDirectory, DataType=modpackUpdater:UpdateAction}"/> IsChecked="{Binding IsDirectory}"/>
</StackPanel> </StackPanel>
<!-- General --> <!-- General -->
<StackPanel <StackPanel
Margin="3"
Spacing="6"> Spacing="6">
<!-- Header --> <!-- Header -->
@@ -100,11 +135,15 @@
<!-- Id --> <!-- Id -->
<Label Content="Id" Target="TextBoxInstallActionId"/> <Label Content="Id" Target="TextBoxInstallActionId"/>
<TextBox x:Name="TextBoxInstallActionId" Text="{Binding Id, DataType=modpackUpdater:InstallAction}"/> <TextBox
x:Name="TextBoxInstallActionId"
Text="{Binding Id}"/>
<!-- Name --> <!-- Name -->
<Label Content="Name" Target="TextBoxInstallActionName"/> <Label Content="Name" Target="TextBoxInstallActionName"/>
<TextBox x:Name="TextBoxInstallActionName" Text="{Binding Name, DataType=modpackUpdater:InstallAction}"/> <TextBox
x:Name="TextBoxInstallActionName"
Text="{Binding Name}"/>
<!-- Side --> <!-- Side -->
<Label Content="Side" Target="ComboBoxInstallActionSide"/> <Label Content="Side" Target="ComboBoxInstallActionSide"/>
@@ -113,18 +152,17 @@
ItemsSource="{x:Static local:MainWindow.Sides}" ItemsSource="{x:Static local:MainWindow.Sides}"
DisplayMemberBinding="{Binding Value}" DisplayMemberBinding="{Binding Value}"
SelectedValueBinding="{Binding Key}" SelectedValueBinding="{Binding Key}"
SelectedValue="{Binding Side, DataType=modpackUpdater:InstallAction}"/> SelectedValue="{Binding Side}"/>
<!-- Is Extra --> <!-- Is Extra -->
<CheckBox <CheckBox
x:Name="CheckBoxInstallActionIsExtra" x:Name="CheckBoxInstallActionIsExtra"
Content="Is Extra" Content="Is Extra"
IsChecked="{Binding IsExtra, DataType=modpackUpdater:InstallAction}"/> IsChecked="{Binding IsExtra}"/>
</StackPanel> </StackPanel>
<!-- Destination --> <!-- Destination -->
<StackPanel <StackPanel
Margin="3"
Spacing="6"> Spacing="6">
<!-- Header --> <!-- Header -->
@@ -134,12 +172,13 @@
</StackPanel> </StackPanel>
<!-- Destination path --> <!-- Destination path -->
<TextBox x:Name="TextBoxInstallDestPath" Text="{Binding DestPath, DataType=modpackUpdater:InstallAction}"/> <TextBox
x:Name="TextBoxInstallDestPath"
Text="{Binding DestPath}"/>
</StackPanel> </StackPanel>
<!-- Source --> <!-- Source -->
<StackPanel <StackPanel
Margin="3"
Spacing="6"> Spacing="6">
<!-- Header --> <!-- Header -->
@@ -155,37 +194,48 @@
ItemsSource="{x:Static local:MainWindow.SourceTypes}" ItemsSource="{x:Static local:MainWindow.SourceTypes}"
DisplayMemberBinding="{Binding Value}" DisplayMemberBinding="{Binding Value}"
SelectedValueBinding="{Binding Key}" SelectedValueBinding="{Binding Key}"
SelectedValue="{Binding SourceType, DataType=modpackUpdater:InstallAction}"/> SelectedValue="{Binding SourceType}"/>
<!-- Is Zip --> <!-- Is Zip -->
<CheckBox <CheckBox
x:Name="CheckBoxInstallActionIsZip" x:Name="CheckBoxInstallActionIsZip"
Content="Is Zip archive" Content="Is Zip archive"
IsChecked="{Binding IsZip, DataType=modpackUpdater:InstallAction}"/> IsChecked="{Binding IsZip}"/>
<!-- Source owner --> <!-- Source owner -->
<Label Content="Source owner" Target="TextBoxInstallActionSourceOwner"/> <Label Content="Source owner" Target="TextBoxInstallActionSourceOwner"/>
<TextBox x:Name="TextBoxInstallActionSourceOwner" Text="{Binding SourceOwner, DataType=modpackUpdater:InstallAction}"/> <TextBox
x:Name="TextBoxInstallActionSourceOwner"
Text="{Binding SourceOwner}"/>
<!-- Source name --> <!-- Source name -->
<Label Content="Source name" Target="TextBoxInstallActionSourceName"/> <Label Content="Source name" Target="TextBoxInstallActionSourceName"/>
<TextBox x:Name="TextBoxInstallActionSourceName" Text="{Binding SourceName, DataType=modpackUpdater:InstallAction}"/> <TextBox
x:Name="TextBoxInstallActionSourceName"
Text="{Binding SourceName}"/>
<!-- Source RegEx --> <!-- Source RegEx -->
<Label Content="Source RegEx" Target="TextBoxInstallActionSourceRegEx"/> <Label Content="Source RegEx" Target="TextBoxInstallActionSourceRegEx"/>
<TextBox x:Name="TextBoxInstallActionSourceRegEx" Text="{Binding SourceRegex, DataType=modpackUpdater:InstallAction}"/> <TextBox
x:Name="TextBoxInstallActionSourceRegEx"
Text="{Binding SourceRegex}"/>
<!-- Source url --> <!-- Source url -->
<Label Content="Source URL" Target="TextBoxInstallActionSourceUrl"/> <Label Content="Source URL" Target="TextBoxInstallActionSourceUrl"/>
<TextBox x:Name="TextBoxInstallActionSourceUrl" Text="{Binding SourceUrl, DataType=modpackUpdater:InstallAction}"/> <TextBox
x:Name="TextBoxInstallActionSourceUrl" Text="{Binding SourceUrl}"/>
<!-- Zip archive path --> <!-- Zip archive path -->
<Label Content="ZIP archive path" Target="TextBoxInstallActionZipArchivePath"/> <Label Content="ZIP archive path" Target="TextBoxInstallActionZipArchivePath"/>
<TextBox x:Name="TextBoxInstallActionZipArchivePath" Text="{Binding SourceUrl, DataType=modpackUpdater:InstallAction}"/> <TextBox
x:Name="TextBoxInstallActionZipArchivePath"
Text="{Binding SourceUrl}"/>
<!-- Source path --> <!-- Source path -->
<Label Content="Source path" Target="TextBoxInstallActionSourcePath"/> <Label Content="Source path" Target="TextBoxInstallActionSourcePath"/>
<TextBox x:Name="TextBoxInstallActionSourcePath" Text="{Binding SrcPath, DataType=modpackUpdater:UpdateAction}"/> <TextBox
x:Name="TextBoxInstallActionSourcePath"
Text="{Binding SrcPath}"/>
</StackPanel> </StackPanel>
<StackPanel <StackPanel
@@ -200,7 +250,9 @@
<!-- Website --> <!-- Website -->
<Label Content="Website" Target="TextBoxInstallActionWebsite"/> <Label Content="Website" Target="TextBoxInstallActionWebsite"/>
<TextBox x:Name="TextBoxInstallActionWebsite" Text="{Binding Website, DataType=modpackUpdater:InstallAction}"/> <TextBox
x:Name="TextBoxInstallActionWebsite"
Text="{Binding Website}"/>
</StackPanel> </StackPanel>
</StackPanel> </StackPanel>
</ScrollViewer> </ScrollViewer>

View File

@@ -0,0 +1,180 @@
using System.ComponentModel;
using System.Runtime.CompilerServices;
namespace ModpackUpdater.Apps.Manager.Ui.Models;
public class InstallActionViewModel(InstallAction action, IActionSet baseActions) : INotifyPropertyChanged
{
#region Implementation of INotifyPropertyChanged
public event PropertyChangedEventHandler? PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string? propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
#endregion Implementation of INotifyPropertyChanged
public static Dictionary<SourceType, string> SourceTypes { get; } = Enum.GetValues<SourceType>().ToDictionary(n => n, n => Enum.GetName(n)!);
public static Dictionary<Side, string> Sides { get; } = Enum.GetValues<Side>().ToDictionary(n => n, n => Enum.GetName(n)!);
public static Dictionary<UpdateActionType, string> UpdateActionTypes { get; } = Enum.GetValues<UpdateActionType>().ToDictionary(n => n, n => Enum.GetName(n)!);
public InstallAction Action => action;
private InstallAction? Base => action is UpdateAction ua ? baseActions.Actions.FirstOrDefault(n => n.Id == ua.InheritFrom) : null;
private InstallAction Inherited => Base ?? action;
public bool IsUpdate => action is UpdateAction;
public string InheritedId => action is UpdateAction ua && !string.IsNullOrWhiteSpace(ua.InheritFrom) ? ua.InheritFrom : action.Id;
public string InheritedSide => Sides[Inherited.Side];
public string InheritedUpdateType => action is UpdateAction ua ? UpdateActionTypes[ua.Type] : string.Empty;
public string InheritedSourceType => SourceTypes[Inherited.SourceType];
public string InheritedDestPath => Inherited.DestPath;
public string Id
{
get => action.Id;
set
{
action.Id = value;
OnPropertyChanged();
OnPropertyChanged(nameof(InheritedId));
}
}
public string Name
{
get => action.Name;
set => action.Name = value;
}
public string Website
{
get => action.Website;
set => action.Website = value;
}
public bool IsZip
{
get => action.IsZip;
set => action.IsZip = value;
}
public string ZipPath
{
get => action.ZipPath;
set => action.ZipPath = value;
}
public string DestPath
{
get => action.DestPath;
set
{
action.DestPath = value;
OnPropertyChanged();
OnPropertyChanged(nameof(InheritedDestPath));
}
}
public string SourceUrl
{
get => action.SourceUrl;
set => action.SourceUrl = value;
}
public SourceType SourceType
{
get => action.SourceType;
set
{
action.SourceType = value;
OnPropertyChanged();
OnPropertyChanged(nameof(InheritedSourceType));
}
}
public string SourceOwner
{
get => action.SourceOwner;
set => action.SourceOwner = value;
}
public string SourceName
{
get => action.SourceName;
set => action.SourceName = value;
}
public string SourceRegex
{
get => action.SourceRegex;
set => action.SourceRegex = value;
}
public string SourceTag
{
get => action.SourceTag;
set => action.SourceTag = value;
}
public Side Side
{
get => action.Side;
set
{
action.Side = value;
OnPropertyChanged();
OnPropertyChanged(nameof(InheritedSide));
}
}
public bool IsExtra
{
get => action.IsExtra;
set => action.IsExtra = value;
}
public UpdateActionType Type
{
get => action is UpdateAction ua ? ua.Type : default;
set
{
if (action is UpdateAction ua)
ua.Type = value;
}
}
public string SrcPath
{
get => action is UpdateAction ua ? ua.SrcPath : string.Empty;
set
{
if (action is UpdateAction ua)
ua.SrcPath = value;
}
}
public bool IsDirectory
{
get => action is UpdateAction ua && ua.IsDirectory;
set
{
if (action is UpdateAction ua)
ua.IsDirectory = value;
}
}
public string InheritFrom
{
get => action is UpdateAction ua ? ua.InheritFrom : string.Empty;
set
{
if (action is UpdateAction ua)
ua.InheritFrom = value;
OnPropertyChanged();
OnPropertyChanged(nameof(InheritedId));
}
}
}

View File

@@ -0,0 +1,24 @@
using System.ComponentModel;
using System.Runtime.CompilerServices;
namespace ModpackUpdater.Apps.Manager.Ui.Models;
public class MainWindowViewModel : INotifyPropertyChanged
{
#region Implementation of INotifyPropertyChanged
public event PropertyChangedEventHandler? PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string? propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
#endregion Implementation of INotifyPropertyChanged
public bool IsUpdate { get; set; }
public List<InstallActionViewModel> Actions { get; } = [];
public InstallActionViewModel? SelectedAction { get; set; }
}

View File

@@ -1,6 +1,7 @@
using Newtonsoft.Json; using Newtonsoft.Json;
using Newtonsoft.Json.Converters; using Newtonsoft.Json.Converters;
using System.ComponentModel; using System.ComponentModel;
using System.Runtime.CompilerServices;
namespace ModpackUpdater; namespace ModpackUpdater;