Compare commits

...

26 Commits

Author SHA1 Message Date
8e8d7d534f Merge pull request 'Improve Installer Update Controls' (#69) from waffle.lord/SPT-AKI-Installer:impr/installer-update-control into master
Reviewed-on: CWX/SPT-AKI-Installer#69
2024-03-27 13:27:05 +00:00
94b7d04908 finish update button controls 2024-03-27 09:26:11 -04:00
992931b15c add properties to control 2024-03-26 18:59:22 -04:00
bb4c535244 new update control WIP 2024-03-26 16:11:14 -04:00
ef487334fb Merge pull request 'impr/cache-info-display' (#68) from waffle.lord/SPT-AKI-Installer:impr/cache-info-display into master
Reviewed-on: CWX/SPT-AKI-Installer#68
2024-03-25 23:21:35 +00:00
1b05ed67e7 bump version 2024-03-25 19:14:59 -04:00
19e9ad0cd2 update cache info control 2024-03-25 19:00:01 -04:00
e53240b417 update problem paths
including scoped_dir for operagx nonsense, and entire downloads folder now
2024-03-25 18:27:57 -04:00
f0f2c1e7aa Merge pull request 'impr/precheck-details-refresh' (#67) from waffle.lord/SPT-AKI-Installer:impr/precheck-details-refresh into master
Reviewed-on: CWX/SPT-AKI-Installer#67
2024-03-25 22:24:26 +00:00
5742351bb4 Merge branch 'master' into impr/precheck-details-refresh 2024-03-25 22:24:20 +00:00
be4ba865eb Merge pull request 'fix/vaious-bugs' (#66) from waffle.lord/SPT-AKI-Installer:fix/vaious-bugs into master
Reviewed-on: CWX/SPT-AKI-Installer#66
2024-03-25 22:23:17 +00:00
fc908386bc better precheck details handling 2024-03-25 18:19:16 -04:00
9693da7d37 Merge branch 'impr/precheck-details-refresh' of https://dev.sp-tarkov.com/waffle.lord/SPT-AKI-Installer into impr/precheck-details-refresh 2024-03-25 17:38:36 -04:00
0aca296115 trying something WIP
trying to see if I can just get the selected index and bind to it... doesn't seem to be working though ...
2024-03-25 17:38:29 -04:00
a6cab6e898 Merge branch 'fix/vaious-bugs' of https://dev.sp-tarkov.com/waffle.lord/SPT-AKI-Installer into fix/vaious-bugs 2024-03-25 17:33:32 -04:00
de4059ca50 use correct property to show action button 2024-03-25 17:33:24 -04:00
85e8ad99a0 add logging to move patcher command 2024-03-25 17:33:24 -04:00
7ca0eab4d7 slightly more logging for hashes 2024-03-25 17:33:24 -04:00
e17441a1a9 always stream 7z out of assembly
during client setup task
2024-03-25 17:33:24 -04:00
38a102bf72 revert 2b93eafabddf91f72df3aab94559b809f2e9a016
revert Edit install path requirements:
Fail if `Desktop` exists in path, not ends with
Fail if `Downloads` exists in path, not ends with
2024-03-25 21:02:26 +00:00
0c82c4335f trying something WIP
trying to see if I can just get the selected index and bind to it... doesn't seem to be working though ...
2024-03-25 16:12:15 -04:00
Dev
2b93eafabd Edit install path requirements:
Fail if `Desktop` exists in path, not ends with
Fail if `Downloads` exists in path, not ends with
2024-03-25 19:32:50 +00:00
b94ed37f05 use correct property to show action button 2024-03-25 14:54:23 -04:00
2c512bae82 add logging to move patcher command 2024-03-25 14:40:29 -04:00
c63bfa89ff slightly more logging for hashes 2024-03-25 14:40:09 -04:00
a83cc0faee always stream 7z out of assembly
during client setup task
2024-03-25 14:28:34 -04:00
18 changed files with 315 additions and 178 deletions

View File

@ -8,10 +8,12 @@
<entry key="SPTInstaller/CustomControls/CacheInfo.axaml" value="SPTInstaller/SPTInstaller.csproj" /> <entry key="SPTInstaller/CustomControls/CacheInfo.axaml" value="SPTInstaller/SPTInstaller.csproj" />
<entry key="SPTInstaller/CustomControls/DetailedPreCheckItem.axaml" value="SPTInstaller/SPTInstaller.csproj" /> <entry key="SPTInstaller/CustomControls/DetailedPreCheckItem.axaml" value="SPTInstaller/SPTInstaller.csproj" />
<entry key="SPTInstaller/CustomControls/Dialogs/WhyCacheThoughDialog.axaml" value="SPTInstaller/SPTInstaller.csproj" /> <entry key="SPTInstaller/CustomControls/Dialogs/WhyCacheThoughDialog.axaml" value="SPTInstaller/SPTInstaller.csproj" />
<entry key="SPTInstaller/CustomControls/MainInstallerButton.axaml" value="SPTInstaller/SPTInstaller.csproj" />
<entry key="SPTInstaller/CustomControls/PreCheckDetails.axaml" value="SPTInstaller/SPTInstaller.csproj" /> <entry key="SPTInstaller/CustomControls/PreCheckDetails.axaml" value="SPTInstaller/SPTInstaller.csproj" />
<entry key="SPTInstaller/CustomControls/PreCheckItem.axaml" value="SPTInstaller/SPTInstaller.csproj" /> <entry key="SPTInstaller/CustomControls/PreCheckItem.axaml" value="SPTInstaller/SPTInstaller.csproj" />
<entry key="SPTInstaller/CustomControls/ProgressableTaskItem.axaml" value="SPTInstaller/SPTInstaller.csproj" /> <entry key="SPTInstaller/CustomControls/ProgressableTaskItem.axaml" value="SPTInstaller/SPTInstaller.csproj" />
<entry key="SPTInstaller/CustomControls/SPTInstallButton.axaml" value="SPTInstaller/SPTInstaller.csproj" /> <entry key="SPTInstaller/CustomControls/SPTInstallButton.axaml" value="SPTInstaller/SPTInstaller.csproj" />
<entry key="SPTInstaller/CustomControls/UpdateButton.axaml" value="SPTInstaller/SPTInstaller.csproj" />
<entry key="SPTInstaller/CustomControls/UpdateInfoCard.axaml" value="SPTInstaller/SPTInstaller.csproj" /> <entry key="SPTInstaller/CustomControls/UpdateInfoCard.axaml" value="SPTInstaller/SPTInstaller.csproj" />
<entry key="SPTInstaller/Views/DetailedPreChecksView.axaml" value="SPTInstaller/SPTInstaller.csproj" /> <entry key="SPTInstaller/Views/DetailedPreChecksView.axaml" value="SPTInstaller/SPTInstaller.csproj" />
<entry key="SPTInstaller/Views/MainWindow.axaml" value="SPTInstaller/SPTInstaller.csproj" /> <entry key="SPTInstaller/Views/MainWindow.axaml" value="SPTInstaller/SPTInstaller.csproj" />

View File

@ -21,6 +21,7 @@
<Color x:Key="AKI_White">#FFFFFF</Color> <Color x:Key="AKI_White">#FFFFFF</Color>
<Color x:Key="AKI_Gray">#282828</Color> <Color x:Key="AKI_Gray">#282828</Color>
<Color x:Key="AKI_DarkGrayBlue">#323947</Color> <Color x:Key="AKI_DarkGrayBlue">#323947</Color>
<Color x:Key="AKI_LightGrayBlue">#444259</Color>
<!-- Brushes --> <!-- Brushes -->
<SolidColorBrush x:Key="AKI_Foreground_Light" Color="{StaticResource AKI_White}"/> <SolidColorBrush x:Key="AKI_Foreground_Light" Color="{StaticResource AKI_White}"/>
@ -28,6 +29,7 @@
<SolidColorBrush x:Key="AKI_Background_Dark" Color="{StaticResource AKI_DarkGray}"/> <SolidColorBrush x:Key="AKI_Background_Dark" Color="{StaticResource AKI_DarkGray}"/>
<SolidColorBrush x:Key="AKI_Brush_Yellow" Color="{StaticResource AKI_Yellow}"/> <SolidColorBrush x:Key="AKI_Brush_Yellow" Color="{StaticResource AKI_Yellow}"/>
<SolidColorBrush x:Key="AKI_Brush_DarkGrayBlue" Color="{StaticResource AKI_DarkGrayBlue}"/> <SolidColorBrush x:Key="AKI_Brush_DarkGrayBlue" Color="{StaticResource AKI_DarkGrayBlue}"/>
<SolidColorBrush x:Key="AKI_Brush_LightGrayBlue" Color="{StaticResource AKI_LightGrayBlue}"/>
<SolidColorBrush x:Key="AKI_Brush_Lighter" Color="Gainsboro"/> <SolidColorBrush x:Key="AKI_Brush_Lighter" Color="Gainsboro"/>
<!-- Path Geometry --> <!-- Path Geometry -->

View File

@ -123,16 +123,13 @@
<!-- SourceRef: https://github.com/AvaloniaUI/Avalonia/blob/master/src/Avalonia.Themes.Fluent/Controls/Button.xaml --> <!-- SourceRef: https://github.com/AvaloniaUI/Avalonia/blob/master/src/Avalonia.Themes.Fluent/Controls/Button.xaml -->
<Style Selector="Button"> <Style Selector="Button">
<Setter Property="Background" Value="{StaticResource AKI_Brush_DarkGrayBlue}"/> <Setter Property="Background" Value="{StaticResource AKI_Brush_DarkGrayBlue}"/>
<Setter Property="Foreground" Value="{StaticResource AKI_Background_Dark}"/> <Setter Property="Foreground" Value="{StaticResource AKI_White}"/>
</Style>
<Style Selector="Button:pointerover">
<Setter Property="FontWeight" Value="SemiBold"/>
</Style> </Style>
<Style Selector="Button:pointerover /template/ ContentPresenter"> <Style Selector="Button:pointerover /template/ ContentPresenter">
<Setter Property="Background" Value="{StaticResource AKI_Background_Light}"/> <Setter Property="Background" Value="{StaticResource AKI_LightGrayBlue}"/>
<Setter Property="BorderBrush" Value="{StaticResource AKI_Brush_Yellow}"/> <Setter Property="BorderBrush" Value="{StaticResource AKI_LightGrayBlue}"/>
<Setter Property="Foreground" Value="{StaticResource AKI_White}"/>
<Setter Property="BorderThickness" Value="1"/> <Setter Property="BorderThickness" Value="1"/>
</Style> </Style>
@ -159,6 +156,7 @@
<Style Selector="Button.yellow:pointerover /template/ ContentPresenter"> <Style Selector="Button.yellow:pointerover /template/ ContentPresenter">
<Setter Property="Background" Value="Gold"/> <Setter Property="Background" Value="Gold"/>
<Setter Property="BorderBrush" Value="{StaticResource AKI_Brush_DarkGrayBlue}"/> <Setter Property="BorderBrush" Value="{StaticResource AKI_Brush_DarkGrayBlue}"/>
<Setter Property="Foreground" Value="{StaticResource AKI_Background_Dark}"/>
<Setter Property="BorderThickness" Value="1"/> <Setter Property="BorderThickness" Value="1"/>
</Style> </Style>

View File

@ -0,0 +1,39 @@
using System.Globalization;
using Avalonia.Data.Converters;
using Avalonia.Media;
using SPTInstaller.CustomControls;
namespace SPTInstaller.Converters;
public class StateSpinnerStateToColorConverter : IValueConverter
{
public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture)
{
if (value == null)
return null;
if (value is not StatusSpinner.SpinnerState state)
return null;
switch (state)
{
case StatusSpinner.SpinnerState.Pending:
return new SolidColorBrush(Colors.Gray);
case StatusSpinner.SpinnerState.Running:
return new SolidColorBrush(Colors.DodgerBlue);
case StatusSpinner.SpinnerState.OK:
return new SolidColorBrush(Colors.ForestGreen);
case StatusSpinner.SpinnerState.Warning:
return new SolidColorBrush(Colors.Goldenrod);
case StatusSpinner.SpinnerState.Error:
return new SolidColorBrush(Colors.Crimson);
default:
throw new ArgumentOutOfRangeException();
}
}
public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture)
{
return value;
}
}

View File

@ -10,22 +10,22 @@
<convt:StatusSpinnerIsProcessingConverter x:Key="IsInProcessingStateConverter"/> <convt:StatusSpinnerIsProcessingConverter x:Key="IsInProcessingStateConverter"/>
</UserControl.Resources> </UserControl.Resources>
<Grid ColumnDefinitions="AUTO,10,AUTO,10,AUTO"> <Grid RowDefinitions="Auto,Auto" ColumnDefinitions="*,AUTO,10,AUTO,*">
<cc:StatusSpinner State="{Binding State, RelativeSource={RelativeSource AncestorType=UserControl}}" <cc:StatusSpinner Grid.Column="1" State="{Binding State, RelativeSource={RelativeSource AncestorType=UserControl}}"
IsVisible="{Binding State, RelativeSource={RelativeSource AncestorType=UserControl}, IsVisible="{Binding State, RelativeSource={RelativeSource AncestorType=UserControl},
Converter={StaticResource IsInProcessingStateConverter}}" Converter={StaticResource IsInProcessingStateConverter}}"
/> />
<Path Data="{StaticResource Cache}" Fill="DodgerBlue" Margin="0 6 0 0" <Path Grid.Column="1" Data="{StaticResource Cache}" Fill="DodgerBlue" Margin="0 6 0 0"
IsVisible="{Binding State, RelativeSource={RelativeSource AncestorType=UserControl}, IsVisible="{Binding State, RelativeSource={RelativeSource AncestorType=UserControl},
Converter={StaticResource IsInProcessingStateConverter}, Converter={StaticResource IsInProcessingStateConverter},
ConverterParameter=invert}" ConverterParameter=invert}"
/> />
<Label Grid.Column="2" Content="{Binding InfoText, RelativeSource={RelativeSource AncestorType=UserControl}}" <Label Grid.Column="3" Content="{Binding InfoText, RelativeSource={RelativeSource AncestorType=UserControl}}"
Margin="0 2 0 0" Margin="0 2 0 0"
/> />
<Button Grid.Column="4" Content="What's this?" Classes="link" <Button Grid.Row="1" Grid.Column="1" Grid.ColumnSpan="3" Content="What's this?" Classes="link" HorizontalAlignment="Center"
Command="{Binding ShowCacheDialogCommand, RelativeSource={RelativeSource AncestorType=UserControl}}"/> Command="{Binding ShowCacheDialogCommand, RelativeSource={RelativeSource AncestorType=UserControl}}"/>
</Grid> </Grid>
</UserControl> </UserControl>

View File

@ -63,7 +63,9 @@ public partial class WhyCacheThoughDialog : UserControl
if (!downloadsFolder.Exists) if (!downloadsFolder.Exists)
{ {
AdditionalInfo = "Could not get downloads folder :("; var message = "Could not get downloads folder :(";
Log.Error($"[MV_0] {message}");
AdditionalInfo = message;
AdditionalInfoColor = "red"; AdditionalInfoColor = "red";
_movePatcherState = -1; _movePatcherState = -1;
return; return;
@ -73,13 +75,15 @@ public partial class WhyCacheThoughDialog : UserControl
if (_foundPatcher == null || !_foundPatcher.Exists) if (_foundPatcher == null || !_foundPatcher.Exists)
{ {
AdditionalInfo = var message = "Could not find a patcher file in your downloads folder";
"Could not find a patcher file in your downloads folder"; Log.Warning($"[MV_0] {message}");
AdditionalInfo = message;
AdditionalInfoColor = "red"; AdditionalInfoColor = "red";
return; return;
} }
Log.Information($"[MV_0] Found patcher for move: {_foundPatcher.Name}");
AdditionalInfo = $"Click again to move the below patcher file to the cache folder\n{_foundPatcher?.Name ?? "-SOMETHING WENT WRONG-"}"; AdditionalInfo = $"Click again to move the below patcher file to the cache folder\n{_foundPatcher?.Name ?? "-SOMETHING WENT WRONG-"}";
AdditionalInfoColor = "#FFC107"; AdditionalInfoColor = "#FFC107";
_movePatcherState = 1; _movePatcherState = 1;
@ -89,7 +93,9 @@ public partial class WhyCacheThoughDialog : UserControl
{ {
var cacheFilePath = Path.Join(DownloadCacheHelper.CachePath, "patcher"); var cacheFilePath = Path.Join(DownloadCacheHelper.CachePath, "patcher");
_foundPatcher?.MoveTo(cacheFilePath, true); _foundPatcher?.MoveTo(cacheFilePath, true);
AdditionalInfo = "Patch was moved into cache :D"; var message = "Patcher was moved into cache :D";
Log.Information($"[MV_1] {message}");
AdditionalInfo = message;
AdditionalInfoColor = "ForestGreen"; AdditionalInfoColor = "ForestGreen";
} }
catch (Exception ex) catch (Exception ex)
@ -99,6 +105,9 @@ public partial class WhyCacheThoughDialog : UserControl
Log.Error(ex, "Failed to move downloaded patcher file into cache"); Log.Error(ex, "Failed to move downloaded patcher file into cache");
} }
break; break;
default:
Log.Error("[MV_ ] Move state is broken :(");
break;
} }
} }
} }

View File

@ -2,41 +2,60 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:model="using:SPTInstaller.Models"
xmlns:cvt="using:SPTInstaller.Converters"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450" mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="SPTInstaller.CustomControls.PreCheckDetails"> x:Class="SPTInstaller.CustomControls.PreCheckDetails">
<UserControl.Resources>
<cvt:StateSpinnerStateToColorConverter x:Key="colorConverter"/>
</UserControl.Resources>
<Panel> <Panel>
<!-- show when nothing is selected --> <!-- show when nothing is selected -->
<Label Content="Select a Pre-Check to see more info" FontSize="20" <Label Content="Select a Pre-Check to see more info" FontSize="20"
HorizontalAlignment="Center" VerticalAlignment="Center" HorizontalAlignment="Center" VerticalAlignment="Center"
IsVisible="{Binding PreCheckName, RelativeSource={RelativeSource AncestorType=UserControl}, Converter={x:Static StringConverters.IsNullOrEmpty}}" IsVisible="{Binding HasSelection, RelativeSource={RelativeSource AncestorType=UserControl}, Converter={x:Static BoolConverters.Not}}"
/> />
<ItemsControl ItemsSource="{Binding PreChecks}" VerticalAlignment="Stretch">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Grid />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate DataType="model:PreCheckBase">
<!-- selected precheck details --> <!-- selected precheck details -->
<Grid RowDefinitions="10, *, Auto, 10" ColumnDefinitions="10, 10, *, 10" <Grid RowDefinitions="10, *, Auto, 10" ColumnDefinitions="10, 10, *, 10" VerticalAlignment="Stretch"
IsVisible="{Binding PreCheckName, RelativeSource={RelativeSource AncestorType=UserControl}, Converter={x:Static StringConverters.IsNotNullOrEmpty}}" IsVisible="{Binding IsSelected}"
> >
<Rectangle Grid.Row="1" Grid.Column="1" Width="3" Fill="{Binding BarColor, RelativeSource={RelativeSource AncestorType=UserControl}}" HorizontalAlignment="Left"/> <Rectangle Grid.Row="1" Grid.Column="1" Width="3" Fill="{Binding State, Converter={StaticResource colorConverter}}"
HorizontalAlignment="Left"/>
<StackPanel Grid.Row="1" Grid.Column="2" HorizontalAlignment="Left"> <StackPanel Grid.Row="1" Grid.Column="2" HorizontalAlignment="Left">
<Label Content="{Binding PreCheckName, RelativeSource={RelativeSource AncestorType=UserControl}}" <Label Content="{Binding Name}"
FontSize="20" FontSize="20"
/> />
<Rectangle Height="1" Fill="Gray" Margin="0 10"/> <Rectangle Height="1" Fill="Gray" Margin="0 10"/>
<TextBlock Text="{Binding Details, RelativeSource={RelativeSource AncestorType=UserControl}}" <TextBlock Text="{Binding PreCheckDetails}"
TextWrapping="Wrap" TextWrapping="Wrap"
/> />
</StackPanel> </StackPanel>
<Button Grid.Row="2" Grid.Column="1" Grid.ColumnSpan="2" Classes="yellow" <Button Grid.Row="2" Grid.Column="1" Grid.ColumnSpan="2" Classes="yellow"
IsVisible="{Binding ShowAction, RelativeSource={RelativeSource AncestorType=UserControl}}" IsVisible="{Binding ActionButtonIsVisible}"
CornerRadius="15" CornerRadius="15"
Margin="0 10" Margin="0 10"
Command="{Binding ActionCommand, RelativeSource={RelativeSource AncestorType=UserControl}}" Command="{Binding ActionButtonCommand}"
Content="{Binding ActionButtonText, RelativeSource={RelativeSource AncestorType=UserControl}}" Content="{Binding ActionButtonText}"
HorizontalContentAlignment="Center" VerticalContentAlignment="Center" HorizontalContentAlignment="Center" VerticalContentAlignment="Center"
HorizontalAlignment="Stretch" HorizontalAlignment="Stretch"
/> />
</Grid> </Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Panel> </Panel>
</UserControl> </UserControl>

View File

@ -1,6 +1,7 @@
using System.Windows.Input; using System.Collections.ObjectModel;
using Avalonia; using Avalonia;
using Avalonia.Controls; using Avalonia.Controls;
using SPTInstaller.Models;
namespace SPTInstaller.CustomControls; namespace SPTInstaller.CustomControls;
@ -11,57 +12,21 @@ public partial class PreCheckDetails : UserControl
InitializeComponent(); InitializeComponent();
} }
public static readonly StyledProperty<string> PreCheckNameProperty = public static readonly StyledProperty<ObservableCollection<PreCheckBase>> PreChecksProperty =
AvaloniaProperty.Register<PreCheckDetails, string>(nameof(PreCheckName)); AvaloniaProperty.Register<PreCheckDetails, ObservableCollection<PreCheckBase>>(nameof(PreChecks));
public string PreCheckName public ObservableCollection<PreCheckBase> PreChecks
{ {
get => GetValue(PreCheckNameProperty); get => GetValue(PreChecksProperty);
set => SetValue(PreCheckNameProperty, value); set => SetValue(PreChecksProperty, value);
} }
public static readonly StyledProperty<string> DetailsProperty = public static readonly StyledProperty<bool> HasSelectionProperty =
AvaloniaProperty.Register<PreCheckDetails, string>(nameof(Details)); AvaloniaProperty.Register<PreCheckDetails, bool>(nameof(HasSelection));
public string Details public bool HasSelection
{ {
get => GetValue(DetailsProperty); get => GetValue(HasSelectionProperty);
set => SetValue(DetailsProperty, value); set => SetValue(HasSelectionProperty, value);
}
public static readonly StyledProperty<string> ActionButtonTextProperty =
AvaloniaProperty.Register<PreCheckDetails, string>(nameof(ActionButtonText));
public string ActionButtonText
{
get => GetValue(ActionButtonTextProperty);
set => SetValue(ActionButtonTextProperty, value);
}
public static readonly StyledProperty<ICommand> ActionCommandProperty =
AvaloniaProperty.Register<PreCheckDetails, ICommand>(nameof(ActionCommand));
public ICommand ActionCommand
{
get => GetValue(ActionCommandProperty);
set => SetValue(ActionCommandProperty, value);
}
public static readonly StyledProperty<bool> ShowActionProperty =
AvaloniaProperty.Register<PreCheckDetails, bool>(nameof(ShowAction));
public bool ShowAction
{
get => GetValue(ShowActionProperty);
set => SetValue(ShowActionProperty, value);
}
public static readonly StyledProperty<string> BarColorProperty =
AvaloniaProperty.Register<PreCheckDetails, string>(nameof(BarColor));
public string BarColor
{
get => GetValue(BarColorProperty);
set => SetValue(BarColorProperty, value);
} }
} }

View File

@ -38,8 +38,7 @@
</Style> </Style>
<Style Selector="Button.selected"> <Style Selector="Button.selected">
<Setter Property="Background" Value="{StaticResource AKI_Brush_DarkGrayBlue}" /> <Setter Property="Background" Value="{StaticResource AKI_Brush_LightGrayBlue}" />
<Setter Property="BorderBrush" Value="{StaticResource AKI_Yellow}"/>
<Setter Property="BorderThickness" Value="1"/> <Setter Property="BorderThickness" Value="1"/>
</Style> </Style>
</UserControl.Styles> </UserControl.Styles>

View File

@ -0,0 +1,47 @@
<UserControl xmlns="https://github.com/avaloniaui"
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"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="SPTInstaller.CustomControls.UpdateButton">
<UserControl.Styles>
<StyleInclude Source="../Assets/Styles.axaml"/>
</UserControl.Styles>
<Panel>
<StackPanel Orientation="Horizontal">
<StackPanel.IsVisible>
<MultiBinding Converter="{x:Static BoolConverters.And}">
<Binding Path="!Updating" RelativeSource="{RelativeSource AncestorType=UserControl}"/>
<Binding Path="UpdateAvailable" RelativeSource="{RelativeSource AncestorType=UserControl}"/>
</MultiBinding>
</StackPanel.IsVisible>
<Button Content="{Binding InfoText, RelativeSource={RelativeSource AncestorType=UserControl}}"
CornerRadius="20 0 0 20"
Classes="yellow"
Command="{Binding UpdateCommand, RelativeSource={RelativeSource AncestorType=UserControl}}"
/>
<Button Content="Not now" CornerRadius="0 20 20 0"
Command="{Binding DismissCommand, RelativeSource={RelativeSource AncestorType=UserControl}}"
/>
</StackPanel>
<Panel Margin="0 10">
<Panel.IsVisible>
<MultiBinding Converter="{x:Static BoolConverters.Or}">
<Binding Path="Updating" RelativeSource="{RelativeSource AncestorType=UserControl}"/>
<Binding Path="CheckingForUpdate" RelativeSource="{RelativeSource AncestorType=UserControl}"/>
</MultiBinding>
</Panel.IsVisible>
<ProgressBar CornerRadius="20" VerticalAlignment="Stretch"
Value="{Binding DownloadProgress, RelativeSource={RelativeSource AncestorType=UserControl}}"
IsIndeterminate="{Binding IsIndeterminate, RelativeSource={RelativeSource AncestorType=UserControl}}"
/>
<Label Content="{Binding InfoText, RelativeSource={RelativeSource AncestorType=UserControl}}"
VerticalAlignment="Center" HorizontalAlignment="Center"
Foreground="Black" FontWeight="SemiBold"/>
</Panel>
</Panel>
</UserControl>

View File

@ -0,0 +1,85 @@
using System.Windows.Input;
using Avalonia;
using Avalonia.Controls;
namespace SPTInstaller.CustomControls;
public partial class UpdateButton : UserControl
{
public UpdateButton()
{
InitializeComponent();
}
public static readonly StyledProperty<string> InfoTextProperty = AvaloniaProperty.Register<UpdateButton, string>(
"InfoText");
public string InfoText
{
get => GetValue(InfoTextProperty);
set => SetValue(InfoTextProperty, value);
}
public static readonly StyledProperty<bool> CheckingForUpdateProperty = AvaloniaProperty.Register<UpdateButton, bool>(
"CheckingForUpdate");
public bool CheckingForUpdate
{
get => GetValue(CheckingForUpdateProperty);
set => SetValue(CheckingForUpdateProperty, value);
}
public static readonly StyledProperty<ICommand> DismissCommandProperty = AvaloniaProperty.Register<UpdateButton, ICommand>(
"DismissCommand");
public ICommand DismissCommand
{
get => GetValue(DismissCommandProperty);
set => SetValue(DismissCommandProperty, value);
}
public static readonly StyledProperty<ICommand> UpdateCommandProperty = AvaloniaProperty.Register<UpdateButton, ICommand>(
"UpdateCommand");
public ICommand UpdateCommand
{
get => GetValue(UpdateCommandProperty);
set => SetValue(UpdateCommandProperty, value);
}
public static readonly StyledProperty<bool> UpdatingProperty = AvaloniaProperty.Register<UpdateButton, bool>(
"Updating");
public bool Updating
{
get => GetValue(UpdatingProperty);
set => SetValue(UpdatingProperty, value);
}
public static readonly StyledProperty<int> DownloadProgressProperty = AvaloniaProperty.Register<UpdateButton, int>(
"DownloadProgress");
public int DownloadProgress
{
get => GetValue(DownloadProgressProperty);
set => SetValue(DownloadProgressProperty, value);
}
public static readonly StyledProperty<bool> IsIndeterminateProperty = AvaloniaProperty.Register<UpdateButton, bool>(
"IsIndeterminate");
public bool IsIndeterminate
{
get => GetValue(IsIndeterminateProperty);
set => SetValue(IsIndeterminateProperty, value);
}
public static readonly StyledProperty<bool> UpdateAvailableProperty = AvaloniaProperty.Register<UpdateButton, bool>(
"UpdateAvailable");
public bool UpdateAvailable
{
get => GetValue(UpdateAvailableProperty);
set => SetValue(UpdateAvailableProperty, value);
}
}

View File

@ -66,13 +66,16 @@ public static class DownloadCacheHelper
if (FileHashHelper.CheckHash(cacheFile, expectedHash)) if (FileHashHelper.CheckHash(cacheFile, expectedHash))
{ {
fileInCache = cacheFile; fileInCache = cacheFile;
Log.Information("Hashes MATCH");
return true; return true;
} }
Log.Warning("Hashes DO NOT MATCH");
return false; return false;
} }
catch catch(Exception ex)
{ {
Log.Error(ex, "Something went wrong during hashing");
return false; return false;
} }
} }

View File

@ -176,15 +176,16 @@ public static class FileHelper
var problemNames = new Dictionary<string, PathCheckType>() var problemNames = new Dictionary<string, PathCheckType>()
{ {
{ "Desktop", PathCheckType.EndsWith }, { "Desktop", PathCheckType.EndsWith },
{ "Downloads", PathCheckType.EndsWith }, { "Documents", PathCheckType.EndsWith },
{ "Documents", PathCheckType.EndsWith}, { "scoped_dir", PathCheckType.Contains },
{ "Downloads", PathCheckType.Contains },
{ "OneDrive", PathCheckType.Contains }, { "OneDrive", PathCheckType.Contains },
{ "NextCloud", PathCheckType.Contains }, { "NextCloud", PathCheckType.Contains },
{ "DropBox", PathCheckType.Contains }, { "DropBox", PathCheckType.Contains },
{ "Google", PathCheckType.Contains }, { "Google", PathCheckType.Contains },
{ "Program Files", PathCheckType.Contains}, { "Program Files", PathCheckType.Contains },
{ "Program Files (x86)", PathCheckType.Contains}, { "Program Files (x86)", PathCheckType.Contains },
{ "Drive Root", PathCheckType.DriveRoot} { "Drive Root", PathCheckType.DriveRoot }
}; };
foreach (var name in problemNames) foreach (var name in problemNames)

View File

@ -25,9 +25,6 @@ public class SetupClientTask : InstallerTaskBase
var progress = new Progress<double>((d) => { SetStatus(null, null, (int)Math.Floor(d)); }); var progress = new Progress<double>((d) => { SetStatus(null, null, (int)Math.Floor(d)); });
if (_data.PatchNeeded)
{
SetStatus("Preparing 7z", "", null, ProgressStyle.Indeterminate); SetStatus("Preparing 7z", "", null, ProgressStyle.Indeterminate);
if (!FileHelper.StreamAssemblyResourceOut("7z.dll", Path.Join(DownloadCacheHelper.CachePath, "7z.dll"))) if (!FileHelper.StreamAssemblyResourceOut("7z.dll", Path.Join(DownloadCacheHelper.CachePath, "7z.dll")))
@ -35,6 +32,8 @@ public class SetupClientTask : InstallerTaskBase
return Result.FromError("Failed to prepare 7z"); return Result.FromError("Failed to prepare 7z");
} }
if (_data.PatchNeeded)
{
// extract patcher files // extract patcher files
SetStatus("Extrating Patcher", "", 0); SetStatus("Extrating Patcher", "", 0);

View File

@ -20,11 +20,11 @@ public class InstallerUpdateInfo : ReactiveObject
set => this.RaiseAndSetIfChanged(ref _updateInfoText, value); set => this.RaiseAndSetIfChanged(ref _updateInfoText, value);
} }
private bool _showCard = false; private bool _show = false;
public bool ShowCard public bool Show
{ {
get => _showCard; get => _show;
set => this.RaiseAndSetIfChanged(ref _showCard, value); set => this.RaiseAndSetIfChanged(ref _show, value);
} }
private bool _updating = false; private bool _updating = false;
@ -89,7 +89,7 @@ public class InstallerUpdateInfo : ReactiveObject
private async Task<string> DownloadNewInstaller() private async Task<string> DownloadNewInstaller()
{ {
UpdateInfoText = $"Downloading new installer v{_newVersion}"; UpdateInfoText = $"Downloading installer v{_newVersion}";
var progress = new Progress<double>(x => DownloadProgress = (int)x); var progress = new Progress<double>(x => DownloadProgress = (int)x);
@ -112,21 +112,7 @@ public class InstallerUpdateInfo : ReactiveObject
} }
UpdateInfoText = infoText; UpdateInfoText = infoText;
Show = updateAvailable;
if (!updateAvailable)
{
Task.Run(async () =>
{
// delay card dismiss
await Task.Delay(TimeSpan.FromSeconds(2));
ShowCard = updateAvailable;
});
}
else
{
ShowCard = updateAvailable;
}
CheckingForUpdates = false; CheckingForUpdates = false;
UpdateAvailable = updateAvailable; UpdateAvailable = updateAvailable;
} }
@ -137,7 +123,7 @@ public class InstallerUpdateInfo : ReactiveObject
return; return;
UpdateInfoText = "Checking for installer updates"; UpdateInfoText = "Checking for installer updates";
ShowCard = true; Show = true;
CheckingForUpdates = true; CheckingForUpdates = true;
try try
@ -172,7 +158,7 @@ public class InstallerUpdateInfo : ReactiveObject
NewInstallerUrl = latest.Assets[0].BrowserDownloadUrl; NewInstallerUrl = latest.Assets[0].BrowserDownloadUrl;
EndCheck($"Update available, version {latestVersion}", true); EndCheck($"Update available: v{latestVersion}", true);
return; return;
} }

View File

@ -9,8 +9,8 @@
<PackageIcon>icon.ico</PackageIcon> <PackageIcon>icon.ico</PackageIcon>
<ApplicationIcon>Assets\icon.ico</ApplicationIcon> <ApplicationIcon>Assets\icon.ico</ApplicationIcon>
<Configurations>Debug;Release;TEST</Configurations> <Configurations>Debug;Release;TEST</Configurations>
<AssemblyVersion>2.52</AssemblyVersion> <AssemblyVersion>2.54</AssemblyVersion>
<FileVersion>2.52</FileVersion> <FileVersion>2.54</FileVersion>
<Company>SPT-AKI</Company> <Company>SPT-AKI</Company>
</PropertyGroup> </PropertyGroup>

View File

@ -19,7 +19,13 @@ namespace SPTInstaller.ViewModels;
public class PreChecksViewModel : ViewModelBase public class PreChecksViewModel : ViewModelBase
{ {
public PreCheckDetailInfo SelectedPreCheck { get; set; } = new(); private bool _hasPreCheckSelected;
public bool HasPreCheckSelected
{
get => _hasPreCheckSelected;
set => this.RaiseAndSetIfChanged(ref _hasPreCheckSelected, value);
}
public ObservableCollection<PreCheckBase> PreChecks { get; set; } = new(ServiceHelper.GetAll<PreCheckBase>()); public ObservableCollection<PreCheckBase> PreChecks { get; set; } = new(ServiceHelper.GetAll<PreCheckBase>());
@ -202,30 +208,8 @@ public class PreChecksViewModel : ViewModelBase
if (check.Id == precheck.Id) if (check.Id == precheck.Id)
{ {
precheck.IsSelected = true; precheck.IsSelected = true;
SelectedPreCheck.Name = precheck.Name;
SelectedPreCheck.Details = precheck.PreCheckDetails;
SelectedPreCheck.ActionButtonText = precheck.ActionButtonText;
SelectedPreCheck.ActionButtonCommand = precheck.ActionButtonCommand;
SelectedPreCheck.ShowActionButton = precheck.ActionButtonIsVisible;
switch (precheck.State) HasPreCheckSelected = true;
{
case StatusSpinner.SpinnerState.Pending:
SelectedPreCheck.BarColor = "gray";
break;
case StatusSpinner.SpinnerState.Running:
SelectedPreCheck.BarColor = "dodgerblue";
break;
case StatusSpinner.SpinnerState.OK:
SelectedPreCheck.BarColor = "forestgreen";
break;
case StatusSpinner.SpinnerState.Warning:
SelectedPreCheck.BarColor = "gold";
break;
case StatusSpinner.SpinnerState.Error:
SelectedPreCheck.BarColor = "red";
break;
}
continue; continue;
} }
@ -236,7 +220,7 @@ public class PreChecksViewModel : ViewModelBase
StartInstallCommand = ReactiveCommand.Create(async () => StartInstallCommand = ReactiveCommand.Create(async () =>
{ {
UpdateInfo.ShowCard = false; UpdateInfo.Show = false;
NavigateTo(new InstallViewModel(HostScreen)); NavigateTo(new InstallViewModel(HostScreen));
}); });
@ -249,7 +233,7 @@ public class PreChecksViewModel : ViewModelBase
DismissUpdateCommand = ReactiveCommand.Create(() => DismissUpdateCommand = ReactiveCommand.Create(() =>
{ {
UpdateInfo.ShowCard = false; UpdateInfo.Show = false;
}); });

View File

@ -21,12 +21,8 @@
<!-- selected precheck details grid --> <!-- selected precheck details grid -->
<cc:PreCheckDetails Grid.Row="2" Grid.Column="1" <cc:PreCheckDetails Grid.Row="2" Grid.Column="1"
PreCheckName="{Binding SelectedPreCheck.Name}" PreChecks="{Binding PreChecks}"
Details="{Binding SelectedPreCheck.Details}" HasSelection="{Binding HasPreCheckSelected}"
ActionButtonText="{Binding SelectedPreCheck.ActionButtonText}"
ActionCommand="{Binding SelectedPreCheck.ActionButtonCommand}"
ShowAction="{Binding SelectedPreCheck.ActionButtonIsVisible}"
BarColor="{Binding SelectedPreCheck.BarColor}"
/> />
<!-- info card vertical separator --> <!-- info card vertical separator -->
@ -79,9 +75,10 @@
<!-- Start install button --> <!-- Start install button -->
<Button Grid.Column="2" Grid.Row="3" Padding="20 10" <Button Grid.Column="2" Grid.Row="3" Padding="20 10"
IsVisible="{Binding !UpdateInfo.Show}"
IsEnabled="{Binding AllowInstall}"
FontSize="15" FontWeight="SemiBold" FontSize="15" FontWeight="SemiBold"
Classes="yellow" Classes="yellow"
IsEnabled="{Binding AllowInstall}"
Command="{Binding StartInstallCommand}" Command="{Binding StartInstallCommand}"
CornerRadius="15" CornerRadius="15"
> >
@ -91,16 +88,18 @@
</StackPanel> </StackPanel>
</Button> </Button>
<cc:UpdateInfoCard Grid.Row="1" Grid.RowSpan="5" Grid.ColumnSpan="5" Padding="10" <!-- Update installer button -->
VerticalAlignment="Center" HorizontalAlignment="Center" <cc:UpdateButton Grid.Column="2" Grid.Row="3"
IsVisible="{Binding UpdateInfo.Show}"
IsEnabled="{Binding UpdateInfo.Show}"
IsIndeterminate="{Binding UpdateInfo.CheckingForUpdates}"
InfoText="{Binding UpdateInfo.UpdateInfoText}" InfoText="{Binding UpdateInfo.UpdateInfoText}"
ShowUpdateCard="{Binding UpdateInfo.ShowCard}"
NotNowCommand="{Binding DismissUpdateCommand}"
UpdateInstallerCommand="{Binding UpdateInstallerCommand}"
Updating="{Binding UpdateInfo.Updating}" Updating="{Binding UpdateInfo.Updating}"
DismissCommand="{Binding DismissUpdateCommand}"
UpdateCommand="{Binding UpdateInstallerCommand}"
DownloadProgress="{Binding UpdateInfo.DownloadProgress}" DownloadProgress="{Binding UpdateInfo.DownloadProgress}"
IndeterminateProgress="{Binding UpdateInfo.CheckingForUpdates}"
UpdateAvailable="{Binding UpdateInfo.UpdateAvailable}" UpdateAvailable="{Binding UpdateInfo.UpdateAvailable}"
CheckingForUpdate="{Binding UpdateInfo.CheckingForUpdates}"
/> />
</Grid> </Grid>
</UserControl> </UserControl>