mirror of
https://github.com/achiez/NebulaAuth-Steam-Desktop-Authenticator-by-Achies.git
synced 2026-07-25 06:14:31 +00:00
Added a temporary solution for validating old mafiles when reading SteamID, as well as changes to the UI and minor fixes
This commit is contained in:
@@ -20,6 +20,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "changelog", "changelog", "{
|
|||||||
changelog\1.4.6.html = changelog\1.4.6.html
|
changelog\1.4.6.html = changelog\1.4.6.html
|
||||||
changelog\1.4.7.html = changelog\1.4.7.html
|
changelog\1.4.7.html = changelog\1.4.7.html
|
||||||
changelog\1.4.8.html = changelog\1.4.8.html
|
changelog\1.4.8.html = changelog\1.4.8.html
|
||||||
|
changelog\1.4.9.html = changelog\1.4.9.html
|
||||||
EndProjectSection
|
EndProjectSection
|
||||||
EndProject
|
EndProject
|
||||||
Global
|
Global
|
||||||
|
|||||||
@@ -21,6 +21,7 @@
|
|||||||
<converters:ProxyDataTextConverter x:Key="ProxyDataTextConverter"/>
|
<converters:ProxyDataTextConverter x:Key="ProxyDataTextConverter"/>
|
||||||
<converters:MultiCommandParameterConverter x:Key="MultiCommandParameterConverter"/>
|
<converters:MultiCommandParameterConverter x:Key="MultiCommandParameterConverter"/>
|
||||||
<converters:ColorToBrushConverter x:Key="ColorToBrushConverter"/>
|
<converters:ColorToBrushConverter x:Key="ColorToBrushConverter"/>
|
||||||
|
<converters:AnyMafilesToVisibilityConverter x:Key="AnyMafilesToVisibilityConverter"/>
|
||||||
<!-- Background converters-->
|
<!-- Background converters-->
|
||||||
<background:BackgroundImageVisibleConverter x:Key="BackgroundImageVisibleConverter"/>
|
<background:BackgroundImageVisibleConverter x:Key="BackgroundImageVisibleConverter"/>
|
||||||
<background:BackgroundSourceConverter x:Key="BackgroundSourceConverter"/>
|
<background:BackgroundSourceConverter x:Key="BackgroundSourceConverter"/>
|
||||||
|
|||||||
@@ -0,0 +1,30 @@
|
|||||||
|
using System;
|
||||||
|
using System.Globalization;
|
||||||
|
using System.Windows;
|
||||||
|
using System.Windows.Data;
|
||||||
|
|
||||||
|
namespace NebulaAuth.Converters;
|
||||||
|
|
||||||
|
public class AnyMafilesToVisibilityConverter : IValueConverter
|
||||||
|
{
|
||||||
|
private static bool EverAnyMafiles;
|
||||||
|
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||||
|
{
|
||||||
|
if (EverAnyMafiles)
|
||||||
|
{
|
||||||
|
return Visibility.Collapsed;
|
||||||
|
}
|
||||||
|
if (value is 0)
|
||||||
|
{
|
||||||
|
return Visibility.Visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
EverAnyMafiles = true;
|
||||||
|
return Visibility.Collapsed;
|
||||||
|
}
|
||||||
|
|
||||||
|
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -68,7 +68,11 @@
|
|||||||
</MenuItem>
|
</MenuItem>
|
||||||
</Menu>
|
</Menu>
|
||||||
<Separator />
|
<Separator />
|
||||||
<ComboBox ToolTip="{Tr MainWindow.AppBar.GroupToolTip}" MinWidth="100" Margin="8,0,8,0" VerticalAlignment="Center" md:HintAssist.Hint="{Tr MainWindow.AppBar.GroupsHint}" md:TextFieldAssist.HasClearButton="True" IsEditable="True" ItemsSource="{Binding Groups}" SelectedValue="{Binding SelectedGroup}">
|
<ComboBox ToolTip="{Tr MainWindow.AppBar.GroupToolTip}" md:HintAssist.Hint="{Tr MainWindow.AppBar.GroupsHint}"
|
||||||
|
MinWidth="100" Margin="8,0,8,0" VerticalAlignment="Center" IsEditable="True"
|
||||||
|
ItemsSource="{Binding Groups}"
|
||||||
|
SelectedValue="{Binding SelectedGroup}">
|
||||||
|
|
||||||
<FrameworkElement.Resources>
|
<FrameworkElement.Resources>
|
||||||
<ResourceDictionary>
|
<ResourceDictionary>
|
||||||
<Style TargetType="md:PackIcon">
|
<Style TargetType="md:PackIcon">
|
||||||
@@ -152,6 +156,11 @@
|
|||||||
</ContextMenu>
|
</ContextMenu>
|
||||||
</FrameworkElement.ContextMenu>
|
</FrameworkElement.ContextMenu>
|
||||||
</ListBox>
|
</ListBox>
|
||||||
|
<TextBlock Visibility="{Binding MaFiles.Count, Converter={StaticResource AnyMafilesToVisibilityConverter}, Mode=OneWay}" Margin="5" FontSize="16" Grid.Row="0" TextWrapping="WrapWithOverflow" Text="{Tr MainWindow.Global.StartTip}">
|
||||||
|
<TextBlock.Background>
|
||||||
|
<SolidColorBrush Color="DarkGray" Opacity="0.5"/>
|
||||||
|
</TextBlock.Background>
|
||||||
|
</TextBlock>
|
||||||
<TextBox Style="{StaticResource MaterialDesignFloatingHintTextBox}" md:TextFieldAssist.HasClearButton="True" w:FontScaleWindow.Scale="0.7" w:FontScaleWindow.ResizeFont="True" Grid.Row="1" Margin="10" md:HintAssist.Hint="{Tr MainWindow.LeftPart.SearchBoxHint}" Text="{Binding SearchText, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
|
<TextBox Style="{StaticResource MaterialDesignFloatingHintTextBox}" md:TextFieldAssist.HasClearButton="True" w:FontScaleWindow.Scale="0.7" w:FontScaleWindow.ResizeFont="True" Grid.Row="1" Margin="10" md:HintAssist.Hint="{Tr MainWindow.LeftPart.SearchBoxHint}" Text="{Binding SearchText, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
|
||||||
</Grid>
|
</Grid>
|
||||||
<md:Card Grid.Column="1" Margin="10,10,15,10" UniformCornerRadius="15">
|
<md:Card Grid.Column="1" Margin="10,10,15,10" UniformCornerRadius="15">
|
||||||
|
|||||||
@@ -68,6 +68,7 @@ public static class ProxyStorage
|
|||||||
}
|
}
|
||||||
|
|
||||||
Proxies[id] = proxyData;
|
Proxies[id] = proxyData;
|
||||||
|
|
||||||
Save();
|
Save();
|
||||||
}
|
}
|
||||||
public static void RemoveProxy(int id)
|
public static void RemoveProxy(int id)
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
<SatelliteResourceLanguages>en;ru;ua</SatelliteResourceLanguages>
|
<SatelliteResourceLanguages>en;ru;ua</SatelliteResourceLanguages>
|
||||||
<ApplicationIcon>Theme\lock.ico</ApplicationIcon>
|
<ApplicationIcon>Theme\lock.ico</ApplicationIcon>
|
||||||
<SupportedOSPlatformVersion>7.0</SupportedOSPlatformVersion>
|
<SupportedOSPlatformVersion>7.0</SupportedOSPlatformVersion>
|
||||||
<AssemblyVersion>1.4.8</AssemblyVersion>
|
<AssemblyVersion>1.4.9</AssemblyVersion>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
@@ -19,7 +19,7 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Autoupdater.NET.Official" Version="1.8.4" />
|
<PackageReference Include="Autoupdater.NET.Official" Version="1.8.5" />
|
||||||
<PackageReference Include="CodingSeb.Localization.JsonFileLoader" Version="1.3.0" />
|
<PackageReference Include="CodingSeb.Localization.JsonFileLoader" Version="1.3.0" />
|
||||||
<PackageReference Include="CodingSeb.Localization.WPF" Version="1.3.0" />
|
<PackageReference Include="CodingSeb.Localization.WPF" Version="1.3.0" />
|
||||||
<PackageReference Include="CodingSebLocalization.Fody" Version="1.3.0" />
|
<PackageReference Include="CodingSebLocalization.Fody" Version="1.3.0" />
|
||||||
|
|||||||
@@ -26,14 +26,14 @@
|
|||||||
<Run Text="{Tr LoginAgainDialog.LoginFor, IsDynamic=False}"/>
|
<Run Text="{Tr LoginAgainDialog.LoginFor, IsDynamic=False}"/>
|
||||||
<Run FontWeight="Bold" Text="{Binding UserName}"/>
|
<Run FontWeight="Bold" Text="{Binding UserName}"/>
|
||||||
</TextBlock>
|
</TextBlock>
|
||||||
<TextBox Text="{Binding Password}" Margin="10,10,10,0" Grid.Row="1" Style="{StaticResource MaterialDesignFloatingHintTextBox}" materialDesign:HintAssist.Hint="{Tr LoginAgainDialog.PasswordBox}"></TextBox>
|
<TextBox Text="{Binding Password, UpdateSourceTrigger=PropertyChanged}" Margin="10,10,10,0" Grid.Row="1" Style="{StaticResource MaterialDesignFloatingHintTextBox}" materialDesign:HintAssist.Hint="{Tr LoginAgainDialog.PasswordBox}"></TextBox>
|
||||||
<CheckBox Grid.Row="2" Margin="10,10,10,0" IsEnabled="{Binding Source={x:Static model:PHandler.IsPasswordSet}}" IsChecked="{Binding SavePassword}" Content="{Tr LoginAgainDialog.SaveEncryptedPassword}"/>
|
<CheckBox Grid.Row="2" Margin="10,10,10,0" IsEnabled="{Binding Source={x:Static model:PHandler.IsPasswordSet}}" IsChecked="{Binding SavePassword}" Content="{Tr LoginAgainDialog.SaveEncryptedPassword}"/>
|
||||||
<Grid Grid.Row="3" Margin="10,10,10,0">
|
<Grid Grid.Row="3" Margin="10,10,10,0">
|
||||||
<Grid.ColumnDefinitions>
|
<Grid.ColumnDefinitions>
|
||||||
<ColumnDefinition/>
|
<ColumnDefinition/>
|
||||||
<ColumnDefinition/>
|
<ColumnDefinition/>
|
||||||
</Grid.ColumnDefinitions>
|
</Grid.ColumnDefinitions>
|
||||||
<Button IsDefault="True" Margin="0,0,5,5" Style="{StaticResource MaterialDesignOutlinedButton}" Command="{x:Static materialDesign:DialogHost.CloseDialogCommand}" CommandParameter="{StaticResource True}" Content="{Tr LoginAgainDialog.LoginButton}"/>
|
<Button IsDefault="True" IsEnabled="{Binding IsFormValid}" Margin="0,0,5,5" Style="{StaticResource MaterialDesignOutlinedButton}" Command="{x:Static materialDesign:DialogHost.CloseDialogCommand}" CommandParameter="{StaticResource True}" Content="{Tr LoginAgainDialog.LoginButton}"/>
|
||||||
<Button IsCancel="True" Grid.Column="1" Margin="5,0,0,5" Style="{StaticResource MaterialDesignOutlinedButton}" Command="{x:Static materialDesign:DialogHost.CloseDialogCommand}" CommandParameter="{StaticResource False}" Content="{Tr LoginAgainDialog.CancelButton}"/>
|
<Button IsCancel="True" Grid.Column="1" Margin="5,0,0,5" Style="{StaticResource MaterialDesignOutlinedButton}" Command="{x:Static materialDesign:DialogHost.CloseDialogCommand}" CommandParameter="{StaticResource False}" Content="{Tr LoginAgainDialog.CancelButton}"/>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|||||||
@@ -28,7 +28,7 @@
|
|||||||
<Run Text="{Tr LoginAgainDialog.LoginFor, IsDynamic=False}"/>
|
<Run Text="{Tr LoginAgainDialog.LoginFor, IsDynamic=False}"/>
|
||||||
<Run FontWeight="Bold" Text="{Binding UserName}"/>
|
<Run FontWeight="Bold" Text="{Binding UserName}"/>
|
||||||
</TextBlock>
|
</TextBlock>
|
||||||
<TextBox Text="{Binding Password}" Margin="10,10,10,0" Grid.Row="1" Style="{StaticResource MaterialDesignFloatingHintTextBox}" materialDesign:HintAssist.Hint="{Tr LoginAgainDialog.PasswordBox}"></TextBox>
|
<TextBox Text="{Binding Password, UpdateSourceTrigger=PropertyChanged}" Margin="10,10,10,0" Grid.Row="1" Style="{StaticResource MaterialDesignFloatingHintTextBox}" materialDesign:HintAssist.Hint="{Tr LoginAgainDialog.PasswordBox}"></TextBox>
|
||||||
<ComboBox ToolTip="{Tr LoginAgainDialog.ProxyToolTip}" Grid.Row="2" Margin="10,18,10,0" materialDesign:HintAssist.Hint="{Tr Common.Proxy}" ItemsSource="{Binding Proxies}" SelectedItem="{Binding SelectedProxy}" >
|
<ComboBox ToolTip="{Tr LoginAgainDialog.ProxyToolTip}" Grid.Row="2" Margin="10,18,10,0" materialDesign:HintAssist.Hint="{Tr Common.Proxy}" ItemsSource="{Binding Proxies}" SelectedItem="{Binding SelectedProxy}" >
|
||||||
<ItemsControl.ItemTemplate>
|
<ItemsControl.ItemTemplate>
|
||||||
<DataTemplate DataType="{x:Type entities:MaProxy}">
|
<DataTemplate DataType="{x:Type entities:MaProxy}">
|
||||||
@@ -46,7 +46,7 @@
|
|||||||
<ColumnDefinition/>
|
<ColumnDefinition/>
|
||||||
<ColumnDefinition/>
|
<ColumnDefinition/>
|
||||||
</Grid.ColumnDefinitions>
|
</Grid.ColumnDefinitions>
|
||||||
<Button IsDefault="True" Margin="0,5,5,5" Style="{StaticResource MaterialDesignOutlinedButton}" Command="{x:Static materialDesign:DialogHost.CloseDialogCommand}" CommandParameter="{StaticResource True}" Content="{Tr LoginAgainDialog.LoginButton}"/>
|
<Button IsEnabled="{Binding IsFormValid}" IsDefault="True" Margin="0,5,5,5" Style="{StaticResource MaterialDesignOutlinedButton}" Command="{x:Static materialDesign:DialogHost.CloseDialogCommand}" CommandParameter="{StaticResource True}" Content="{Tr LoginAgainDialog.LoginButton}"/>
|
||||||
<Button IsCancel="True" Grid.Column="1" Margin="5,5,0,5" Style="{StaticResource MaterialDesignOutlinedButton}" Command="{x:Static materialDesign:DialogHost.CloseDialogCommand}" CommandParameter="{StaticResource False}" Content="{Tr LoginAgainDialog.CancelButton}"/>
|
<Button IsCancel="True" Grid.Column="1" Margin="5,5,0,5" Style="{StaticResource MaterialDesignOutlinedButton}" Command="{x:Static materialDesign:DialogHost.CloseDialogCommand}" CommandParameter="{StaticResource False}" Content="{Tr LoginAgainDialog.CancelButton}"/>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|||||||
@@ -16,7 +16,7 @@
|
|||||||
d:DataContext="{d:DesignInstance other:ProxyManagerVM}"
|
d:DataContext="{d:DesignInstance other:ProxyManagerVM}"
|
||||||
Background="{DynamicResource WindowBackground}">
|
Background="{DynamicResource WindowBackground}">
|
||||||
<d:DesignerProperties.DesignStyle>
|
<d:DesignerProperties.DesignStyle>
|
||||||
<Style TargetType="UserControl">
|
<Style TargetType="UserControl">
|
||||||
<Setter Property="Background" Value="{DynamicResource WindowBackground}" />
|
<Setter Property="Background" Value="{DynamicResource WindowBackground}" />
|
||||||
</Style>
|
</Style>
|
||||||
</d:DesignerProperties.DesignStyle>
|
</d:DesignerProperties.DesignStyle>
|
||||||
@@ -29,40 +29,39 @@
|
|||||||
<RowDefinition Height="*"/>
|
<RowDefinition Height="*"/>
|
||||||
<RowDefinition Height="Auto"/>
|
<RowDefinition Height="Auto"/>
|
||||||
</Grid.RowDefinitions>
|
</Grid.RowDefinitions>
|
||||||
<Grid>
|
<Grid>
|
||||||
<Grid.ColumnDefinitions>
|
<Grid.ColumnDefinitions>
|
||||||
<ColumnDefinition/>
|
<ColumnDefinition/>
|
||||||
<ColumnDefinition/>
|
<ColumnDefinition/>
|
||||||
</Grid.ColumnDefinitions>
|
</Grid.ColumnDefinitions>
|
||||||
<TextBlock Margin="10" FontStyle="Normal" Foreground="DarkGray" HorizontalAlignment="Left" VerticalAlignment="Center" FontSize="18" Text="{Tr ProxyManagerDialog.Title}"/>
|
<TextBlock Margin="10" FontStyle="Normal" Foreground="DarkGray" HorizontalAlignment="Left" VerticalAlignment="Center" FontSize="18" Text="{Tr ProxyManagerDialog.Title}"/>
|
||||||
<Button Margin="0,0,10,0" IsCancel="True" Grid.Column="1" Width="30" Height="30" Style="{StaticResource MaterialDesignIconForegroundButton}" HorizontalAlignment="Right" Command="{x:Static md:DialogHost.CloseDialogCommand}">
|
<Button Margin="0,0,10,0" IsCancel="True" Grid.Column="1" Width="30" Height="30" Style="{StaticResource MaterialDesignIconForegroundButton}" HorizontalAlignment="Right" Command="{x:Static md:DialogHost.CloseDialogCommand}">
|
||||||
<md:PackIcon Kind="Close" Width="24" Height="24" Foreground="IndianRed"></md:PackIcon>
|
<md:PackIcon Kind="Close" Width="24" Height="24" Foreground="IndianRed"></md:PackIcon>
|
||||||
</Button>
|
</Button>
|
||||||
|
|
||||||
</Grid>
|
</Grid>
|
||||||
<Separator Grid.Row="1"></Separator>
|
<Separator Grid.Row="1"></Separator>
|
||||||
<Grid Grid.Row="2">
|
<Grid Grid.Row="2">
|
||||||
<Grid.ColumnDefinitions>
|
<Grid.ColumnDefinitions>
|
||||||
<ColumnDefinition Width="*"/>
|
<ColumnDefinition Width="*"/>
|
||||||
<ColumnDefinition Width="Auto"/>
|
<ColumnDefinition Width="Auto"/>
|
||||||
<ColumnDefinition Width="Auto"/>
|
|
||||||
</Grid.ColumnDefinitions>
|
</Grid.ColumnDefinitions>
|
||||||
<TextBlock HorizontalAlignment="Stretch"
|
<TextBlock HorizontalAlignment="Stretch"
|
||||||
Margin="15" FontSize="16">
|
Margin="15" FontSize="16">
|
||||||
<Run Text="{Tr ProxyManagerDialog.DefaultProxy, IsDynamic=False}"/>
|
<Run Text="{Tr ProxyManagerDialog.DefaultProxy, IsDynamic=False}"/>
|
||||||
<Run Text="{Binding DefaultProxy.Key, StringFormat='
0:', FallbackValue='X', Mode=OneWay}"/>
|
<Run Text="{Binding DefaultProxy.Key, StringFormat='
0:', FallbackValue='-', Mode=OneWay}"/>
|
||||||
<Run Text="{Binding DefaultProxy.Value, Converter='{StaticResource ProxyDataTextConverter}', Mode=OneWay, FallbackValue=''}"/>
|
<Run Text="{Binding DefaultProxy.Value, Converter='{StaticResource ProxyDataTextConverter}', Mode=OneWay, FallbackValue=''}"/>
|
||||||
</TextBlock>
|
</TextBlock>
|
||||||
|
|
||||||
<Button Grid.Column="1" Command="{Binding SetDefaultCommand}">
|
<Button Grid.Column="1" Command="{Binding RemoveDefaultCommand}" Cursor="Hand">
|
||||||
<md:PackIcon Kind="HeartBoxOutline" Width="20" Height="20"></md:PackIcon>
|
|
||||||
</Button>
|
|
||||||
<Button Grid.Column="2" Command="{Binding RemoveDefaultCommand}" Cursor="Hand">
|
|
||||||
<md:PackIcon Kind="ClearBox" Width="20" Height="20"></md:PackIcon>
|
<md:PackIcon Kind="ClearBox" Width="20" Height="20"></md:PackIcon>
|
||||||
</Button>
|
</Button>
|
||||||
</Grid>
|
</Grid>
|
||||||
<md:Card Grid.Row="3" Margin="10">
|
<md:Card Grid.Row="3" Margin="10">
|
||||||
<ListBox FontSize="14" SelectedValue="{Binding SelectedProxy}" ItemsSource="{Binding Proxies}">
|
<ListBox VirtualizingStackPanel.VirtualizationMode="Recycling" FontSize="14" SelectedValue="{Binding SelectedProxy}" ItemsSource="{Binding Proxies}">
|
||||||
|
<ListBox.InputBindings>
|
||||||
|
<KeyBinding Key="Delete" Command="{Binding DataContext.RemoveProxyCommand, RelativeSource={RelativeSource AncestorType=UserControl}}" />
|
||||||
|
</ListBox.InputBindings>
|
||||||
<ListBox.ItemContainerStyle>
|
<ListBox.ItemContainerStyle>
|
||||||
<Style TargetType="ListBoxItem" BasedOn="{StaticResource MaterialDesignListBoxItem}">
|
<Style TargetType="ListBoxItem" BasedOn="{StaticResource MaterialDesignListBoxItem}">
|
||||||
<Setter Property="Tag" Value="{Binding RelativeSource={RelativeSource AncestorType=UserControl}, Path=DataContext}"/>
|
<Setter Property="Tag" Value="{Binding RelativeSource={RelativeSource AncestorType=UserControl}, Path=DataContext}"/>
|
||||||
@@ -78,22 +77,37 @@
|
|||||||
</ContextMenu>
|
</ContextMenu>
|
||||||
</Setter.Value>
|
</Setter.Value>
|
||||||
</Setter>
|
</Setter>
|
||||||
|
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
|
||||||
|
|
||||||
|
|
||||||
</Style>
|
</Style>
|
||||||
</ListBox.ItemContainerStyle>
|
</ListBox.ItemContainerStyle>
|
||||||
|
|
||||||
<ListBox.ItemTemplate>
|
<ListBox.ItemTemplate>
|
||||||
<DataTemplate>
|
<DataTemplate>
|
||||||
<TextBlock>
|
<Grid >
|
||||||
<Run Text="{Binding Key, Mode=OneWay}"/><Run Text=": "/>
|
<Grid.ColumnDefinitions>
|
||||||
<Run Text="{Binding Value, Mode=OneWay, Converter={StaticResource ProxyDataTextConverter}}"/>
|
<ColumnDefinition Width="*"/>
|
||||||
|
<ColumnDefinition Width="Auto"/>
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
<TextBlock VerticalAlignment="Center">
|
||||||
|
<Run Text="{Binding Key, Mode=OneWay}"/><Run Text=": "/>
|
||||||
|
<Run Text="{Binding Value, Mode=OneWay, Converter={StaticResource ProxyDataTextConverter}}"/>
|
||||||
|
|
||||||
</TextBlock>
|
</TextBlock>
|
||||||
|
<Button Style="{StaticResource MaterialDesignIconButton}" Padding="0" Width="24" Height="24" md:RippleAssist.IsDisabled="True" Grid.Column="1" HorizontalAlignment="Right"
|
||||||
|
Command="{Binding DataContext.SetDefaultCommand, RelativeSource={RelativeSource AncestorType=UserControl}}"
|
||||||
|
CommandParameter="{Binding}">
|
||||||
|
<md:PackIcon Height="16" Width="16" Kind="Heart"></md:PackIcon>
|
||||||
|
</Button>
|
||||||
|
|
||||||
|
</Grid>
|
||||||
|
|
||||||
</DataTemplate>
|
</DataTemplate>
|
||||||
</ListBox.ItemTemplate>
|
</ListBox.ItemTemplate>
|
||||||
</ListBox>
|
</ListBox>
|
||||||
</md:Card>
|
</md:Card>
|
||||||
<Grid Grid.Row="4">
|
<Grid Grid.Row="4" Margin="5,0,15,0">
|
||||||
<Grid.ColumnDefinitions>
|
<Grid.ColumnDefinitions>
|
||||||
<ColumnDefinition Width="*"/>
|
<ColumnDefinition Width="*"/>
|
||||||
<ColumnDefinition Width="Auto"/>
|
<ColumnDefinition Width="Auto"/>
|
||||||
|
|||||||
@@ -23,6 +23,8 @@ public partial class MainVM : ObservableObject
|
|||||||
private ObservableCollection<Mafile> _maFiles = Storage.MaFiles;
|
private ObservableCollection<Mafile> _maFiles = Storage.MaFiles;
|
||||||
public SnackbarMessageQueue MessageQueue => SnackbarController.MessageQueue;
|
public SnackbarMessageQueue MessageQueue => SnackbarController.MessageQueue;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public Mafile? SelectedMafile
|
public Mafile? SelectedMafile
|
||||||
{
|
{
|
||||||
get => _selectedMafile;
|
get => _selectedMafile;
|
||||||
|
|||||||
@@ -10,7 +10,9 @@ namespace NebulaAuth.ViewModel.Other;
|
|||||||
public partial class LoginAgainOnImportVM : ObservableObject
|
public partial class LoginAgainOnImportVM : ObservableObject
|
||||||
{
|
{
|
||||||
public ObservableCollection<MaProxy> Proxies { get; } = new();
|
public ObservableCollection<MaProxy> Proxies { get; } = new();
|
||||||
[ObservableProperty] private string _password = null!;
|
[ObservableProperty]
|
||||||
|
[NotifyPropertyChangedFor(nameof(IsFormValid))]
|
||||||
|
private string _password = null!;
|
||||||
[ObservableProperty] private bool _savePassword;
|
[ObservableProperty] private bool _savePassword;
|
||||||
[ObservableProperty] private string _userName = null!;
|
[ObservableProperty] private string _userName = null!;
|
||||||
[ObservableProperty] private bool _mafileHasProxy;
|
[ObservableProperty] private bool _mafileHasProxy;
|
||||||
@@ -38,7 +40,7 @@ public partial class LoginAgainOnImportVM : ObservableObject
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool IsFormValid => !string.IsNullOrWhiteSpace(Password);
|
||||||
|
|
||||||
|
|
||||||
private MaProxy? _selectedProxy;
|
private MaProxy? _selectedProxy;
|
||||||
|
|||||||
@@ -9,9 +9,18 @@ namespace NebulaAuth.ViewModel.Other;
|
|||||||
|
|
||||||
public partial class LoginAgainVM : ObservableObject
|
public partial class LoginAgainVM : ObservableObject
|
||||||
{
|
{
|
||||||
[ObservableProperty] private string _password = null!;
|
[ObservableProperty]
|
||||||
[ObservableProperty] private bool _savePassword;
|
[NotifyPropertyChangedFor(nameof(IsFormValid))]
|
||||||
[ObservableProperty] private string _userName = null!;
|
private string _password = null!;
|
||||||
|
|
||||||
|
[ObservableProperty]
|
||||||
|
private bool _savePassword;
|
||||||
|
|
||||||
|
[ObservableProperty]
|
||||||
|
private string _userName = null!;
|
||||||
|
|
||||||
|
|
||||||
|
public bool IsFormValid => !string.IsNullOrWhiteSpace(Password);
|
||||||
|
|
||||||
public LoginAgainVM()
|
public LoginAgainVM()
|
||||||
{ }
|
{ }
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ public partial class ProxyManagerVM : ObservableObject
|
|||||||
var idPresent = (bool?)null;
|
var idPresent = (bool?)null;
|
||||||
var proxies = new List<KeyValuePair<int?, ProxyData>>();
|
var proxies = new List<KeyValuePair<int?, ProxyData>>();
|
||||||
var i = 0;
|
var i = 0;
|
||||||
foreach (var str in split)
|
foreach (var str in split.Where(s => string.IsNullOrWhiteSpace(s) == false))
|
||||||
{
|
{
|
||||||
i++;
|
i++;
|
||||||
int? id = null;
|
int? id = null;
|
||||||
@@ -113,17 +113,37 @@ public partial class ProxyManagerVM : ObservableObject
|
|||||||
[RelayCommand]
|
[RelayCommand]
|
||||||
private void RemoveProxy()
|
private void RemoveProxy()
|
||||||
{
|
{
|
||||||
if (SelectedProxy == null) return;
|
var selected = SelectedProxy;
|
||||||
ProxyStorage.RemoveProxy(SelectedProxy.Value.Key);
|
if (selected == null) return;
|
||||||
|
var s = selected.Value;
|
||||||
|
|
||||||
|
|
||||||
|
KeyValuePair<int, ProxyData>? nextNeighbor = null;
|
||||||
|
KeyValuePair<int, ProxyData>? prevNeighbor = null;
|
||||||
|
foreach (var id in Proxies.Keys.Order())
|
||||||
|
{
|
||||||
|
if (id < s.Key)
|
||||||
|
{
|
||||||
|
prevNeighbor = KeyValuePair.Create(id, Proxies[id]);
|
||||||
|
}
|
||||||
|
else if (id > s.Key)
|
||||||
|
{
|
||||||
|
nextNeighbor = KeyValuePair.Create(id, Proxies[id]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ProxyStorage.RemoveProxy(s.Key);
|
||||||
|
SelectedProxy = nextNeighbor ?? prevNeighbor;
|
||||||
CheckIfDefaultProxyStay();
|
CheckIfDefaultProxyStay();
|
||||||
}
|
}
|
||||||
|
|
||||||
[RelayCommand]
|
[RelayCommand]
|
||||||
private void SetDefault()
|
private void SetDefault(object? arg)
|
||||||
{
|
{
|
||||||
if (SelectedProxy == null) return;
|
if (arg is not KeyValuePair<int, ProxyData> proxy) return;
|
||||||
DefaultProxy = SelectedProxy;
|
DefaultProxy = proxy;
|
||||||
MaClient.DefaultProxy = SelectedProxy.Value.Value;
|
MaClient.DefaultProxy = proxy.Value;
|
||||||
ProxyStorage.Save();
|
ProxyStorage.Save();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -64,11 +64,16 @@
|
|||||||
"ru": "Отпустите для импорта мафайлов",
|
"ru": "Отпустите для импорта мафайлов",
|
||||||
"ua": "Відпустіть для імпорту мафайлів"
|
"ua": "Відпустіть для імпорту мафайлів"
|
||||||
},
|
},
|
||||||
"LoadingHint":{
|
"LoadingHint": {
|
||||||
"en": "Loading...",
|
"en": "Loading...",
|
||||||
"ru": "Загрузка...",
|
"ru": "Загрузка...",
|
||||||
"ua": "Завантаження..."
|
"ua": "Завантаження..."
|
||||||
}
|
},
|
||||||
|
"StartTip": {
|
||||||
|
"ru": "Чтобы начать пользоваться программой вы можете привязать аккаунт через меню \"Аккаунт\", либо импортировать существующие мафайлы одним из способов:\n1. Скопировать их в папку mafiles и перезапустить приложение\n2. Перетянуть файлы прямо в окно программы\n3. Скопировать файлы и нажать CTRL+V в окне программы\n4. Через меню \"Файл\" - \"Импорт\"",
|
||||||
|
"en": "To start using the program, you can link an account through the \"Account\" menu, or import existing mafiles in one of the following ways:\n1. Copy them to the mafiles folder and restart the application\n2. Drag files directly into the program window\n3. Copy files and press CTRL+V in the program window\n4. Through the \"File\" - \"Import\" menu",
|
||||||
|
"ua": "Щоб почати користуватися програмою, ви можете прив'язати акаунт через меню \"Акаунт\", або імпортувати існуючі мафайли одним із способів:\n1. Скопіювати їх у папку mafiles та перезапустити програму\n2. Перетягнути файли безпосередньо в вікно програми\n3. Скопіювати файли та натиснути CTRL+V в вікні програми\n4. Через меню \"Файл\" - \"Імпорт\""
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"Menu": {
|
"Menu": {
|
||||||
"File": {
|
"File": {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<item>
|
<item>
|
||||||
<version>1.4.8.0</version>
|
<version>1.4.9.0</version>
|
||||||
<url>https://github.com/achiez/NebulaAuth-Steam-Desktop-Authenticator-by-Achies/releases/download/1.4.8/NebulaAuth.1.4.8.zip</url>
|
<url>https://github.com/achiez/NebulaAuth-Steam-Desktop-Authenticator-by-Achies/releases/download/1.4.9/NebulaAuth.1.4.9.zip</url>
|
||||||
<changelog>https://achiez.github.io/NebulaAuth-Steam-Desktop-Authenticator-by-Achies/changelog/1.4.8.html</changelog>
|
<changelog>https://achiez.github.io/NebulaAuth-Steam-Desktop-Authenticator-by-Achies/changelog/1.4.9.html</changelog>
|
||||||
<mandatory>false</mandatory>
|
<mandatory>false</mandatory>
|
||||||
</item>
|
</item>
|
||||||
@@ -4,7 +4,7 @@ public class MafileCredits : IMafileCredits
|
|||||||
{
|
{
|
||||||
internal static readonly MafileCredits Instance = new();
|
internal static readonly MafileCredits Instance = new();
|
||||||
private const string ORIGINAL_AUTHOR = "Achies";
|
private const string ORIGINAL_AUTHOR = "Achies";
|
||||||
private const string MOBILE_APP = "https://github.com/achiez/NebulaAuth";
|
private const string MOBILE_APP = "https://github.com/achiez/NebulaAuth-Steam-Desktop-Authenticator-by-Achies";
|
||||||
|
|
||||||
public string OriginalAuthor => ORIGINAL_AUTHOR;
|
public string OriginalAuthor => ORIGINAL_AUTHOR;
|
||||||
public string BestOpenSourceMobileApp => MOBILE_APP;
|
public string BestOpenSourceMobileApp => MOBILE_APP;
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using Newtonsoft.Json.Linq;
|
using AchiesUtilities.Models;
|
||||||
|
using Newtonsoft.Json.Linq;
|
||||||
using SteamLib.Account;
|
using SteamLib.Account;
|
||||||
using SteamLib.Authentication;
|
using SteamLib.Authentication;
|
||||||
using SteamLib.Core.Enums;
|
using SteamLib.Core.Enums;
|
||||||
@@ -14,7 +15,7 @@ public partial class MafileSerializer //SessionData
|
|||||||
"refresh", "OAuthToken");
|
"refresh", "OAuthToken");
|
||||||
|
|
||||||
|
|
||||||
SteamAuthToken refreshToken;
|
SteamAuthToken? refreshToken = null;
|
||||||
if (refreshTokenToken == null || refreshTokenToken.Type == JTokenType.Null) return null;
|
if (refreshTokenToken == null || refreshTokenToken.Type == JTokenType.Null) return null;
|
||||||
if (refreshTokenToken.Type == JTokenType.String && SteamTokenHelper.TryParse(refreshTokenToken.Value<string>()!, out var parsed))
|
if (refreshTokenToken.Type == JTokenType.String && SteamTokenHelper.TryParse(refreshTokenToken.Value<string>()!, out var parsed))
|
||||||
{
|
{
|
||||||
@@ -28,13 +29,9 @@ public partial class MafileSerializer //SessionData
|
|||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
return null;
|
//Ignored
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
var sessionId = GetString(j, "sessionid", "session_id", "session");
|
var sessionId = GetString(j, "sessionid", "session_id", "session");
|
||||||
@@ -66,12 +63,20 @@ public partial class MafileSerializer //SessionData
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
var sessionData = new MobileSessionData(sessionId, refreshToken.SteamId, refreshToken, accessToken, new Dictionary<SteamDomain, SteamAuthToken>());
|
var steamId = refreshToken?.SteamId ?? GetSessionSteamId(j);
|
||||||
|
if (steamId == null)
|
||||||
|
{
|
||||||
|
result = DeserializedMafileSessionResult.Invalid;
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
refreshToken ??= CreateInvalid(steamId.Value);
|
||||||
|
var sessionData = new MobileSessionData(sessionId, steamId.Value, refreshToken.Value, accessToken, new Dictionary<SteamDomain, SteamAuthToken>());
|
||||||
sessionData.IsValid = SessionDataValidator.Validate(null, sessionData).Succeeded;
|
sessionData.IsValid = SessionDataValidator.Validate(null, sessionData).Succeeded;
|
||||||
if(sessionData.IsValid == false)
|
if(sessionData.IsValid == false)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
if (refreshToken.IsExpired || refreshToken.Type != SteamAccessTokenType.MobileRefresh)
|
if (refreshToken.Value.IsExpired || refreshToken.Value.Type != SteamAccessTokenType.MobileRefresh)
|
||||||
{
|
{
|
||||||
result = DeserializedMafileSessionResult.Expired;
|
result = DeserializedMafileSessionResult.Expired;
|
||||||
}
|
}
|
||||||
@@ -82,4 +87,34 @@ public partial class MafileSerializer //SessionData
|
|||||||
|
|
||||||
return sessionData;
|
return sessionData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static SteamId? GetSessionSteamId(JObject j)
|
||||||
|
{
|
||||||
|
var token = GetToken(j, "steamid");
|
||||||
|
if (token == null || token.Type == JTokenType.Null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
if(token.Type == JTokenType.Integer)
|
||||||
|
return SteamId.FromSteam64(token.Value<long>());
|
||||||
|
|
||||||
|
if (token.Type == JTokenType.String && long.TryParse(token.Value<string>()!, out var steamId))
|
||||||
|
{
|
||||||
|
return SteamId.FromSteam64(steamId);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Workaround to avoid session being invalidated due to missing a valid token.
|
||||||
|
//The reason for this change is the inability to proxy/change group for old mafiles, which creates more problems than benefits.
|
||||||
|
//A temporary solution until I decide how to read the SteamID correctly without invalidating the entire session.
|
||||||
|
//It also makes the LoginAgainOnImport mechanism useless, which is good outcome.
|
||||||
|
//Most likely I need to reconsider the reaction to an “invalid” session and simply feed it to the software as “expired”.
|
||||||
|
//Also, when deciding not to validate RefreshToken, I need to reconsider the entire validation method in the Validator class and think through the consequences in the rest of the code.
|
||||||
|
//FIXME: Refactor code to avoid this workaround and make it more organic.
|
||||||
|
//TODO: after fixing the issue, reflect changes in the original library
|
||||||
|
private static SteamAuthToken CreateInvalid(SteamId steamId)
|
||||||
|
{
|
||||||
|
return new SteamAuthToken("invalid", steamId, UnixTimeStamp.FromDateTime(DateTime.Now - TimeSpan.FromSeconds(1)), SteamDomain.Community, SteamAccessTokenType.MobileRefresh);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -8,7 +8,7 @@ public partial class MafileSerializer //Utility
|
|||||||
{
|
{
|
||||||
foreach (var name in aliases)
|
foreach (var name in aliases)
|
||||||
{
|
{
|
||||||
if (j.TryGetValue(name, StringComparison.InvariantCultureIgnoreCase, out var token))
|
if (j.TryGetValue(name, StringComparison.OrdinalIgnoreCase, out var token))
|
||||||
{
|
{
|
||||||
return token;
|
return token;
|
||||||
}
|
}
|
||||||
@@ -21,7 +21,7 @@ public partial class MafileSerializer //Utility
|
|||||||
{
|
{
|
||||||
foreach (var name in aliases)
|
foreach (var name in aliases)
|
||||||
{
|
{
|
||||||
if (!j.TryGetValue(name, StringComparison.InvariantCultureIgnoreCase, out var token)) continue;
|
if (!j.TryGetValue(name, StringComparison.OrdinalIgnoreCase, out var token)) continue;
|
||||||
var parent = token.Parent as JProperty;
|
var parent = token.Parent as JProperty;
|
||||||
removeFrom.Remove(parent!.Name);
|
removeFrom.Remove(parent!.Name);
|
||||||
return token;
|
return token;
|
||||||
@@ -34,7 +34,7 @@ public partial class MafileSerializer //Utility
|
|||||||
{
|
{
|
||||||
foreach (var name in aliases)
|
foreach (var name in aliases)
|
||||||
{
|
{
|
||||||
if (!j.TryGetValue(name, StringComparison.InvariantCultureIgnoreCase, out var token)) continue;
|
if (!j.TryGetValue(name, StringComparison.OrdinalIgnoreCase, out var token)) continue;
|
||||||
if (token.Type == JTokenType.Null)
|
if (token.Type == JTokenType.Null)
|
||||||
{
|
{
|
||||||
throw new ArgumentException($"Required property {propertyName} is null");
|
throw new ArgumentException($"Required property {propertyName} is null");
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ public partial class MafileSerializer //Validate
|
|||||||
public static void IsValidBase64(string name, string base64)
|
public static void IsValidBase64(string name, string base64)
|
||||||
{
|
{
|
||||||
var buffer = new Span<byte>(new byte[base64.Length]);
|
var buffer = new Span<byte>(new byte[base64.Length]);
|
||||||
if(Convert.TryFromBase64String(base64, buffer, out _) == false)
|
if (Convert.TryFromBase64String(base64, buffer, out _) == false)
|
||||||
throw new ArgumentException($"{name} is not valid base64 string");
|
throw new ArgumentException($"{name} is not valid base64 string");
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -63,7 +63,6 @@ public partial class MafileSerializer //Validate
|
|||||||
if (d.SessionData.RefreshToken.IsExpired)
|
if (d.SessionData.RefreshToken.IsExpired)
|
||||||
{
|
{
|
||||||
sessionResult = DeserializedMafileSessionResult.Expired;
|
sessionResult = DeserializedMafileSessionResult.Expired;
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
d.SessionData.IsValid = SessionDataValidator.Validate(null, d.SessionData).Succeeded;
|
d.SessionData.IsValid = SessionDataValidator.Validate(null, d.SessionData).Succeeded;
|
||||||
|
|||||||
@@ -0,0 +1,86 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>Changelog</title>
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
|
||||||
|
background-color: #eeeeee;
|
||||||
|
color: #333;
|
||||||
|
line-height: 1.6;
|
||||||
|
}
|
||||||
|
|
||||||
|
.changelog-container {
|
||||||
|
background-color: #fff;
|
||||||
|
border-radius: 10px;
|
||||||
|
padding: 25px;
|
||||||
|
margin: 25px auto;
|
||||||
|
max-width: 800px;
|
||||||
|
box-shadow: 0 5px 15px rgba(0,0,0,0.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
.change {
|
||||||
|
margin-bottom: 20px;
|
||||||
|
padding: 0;
|
||||||
|
border-left: 4px solid #a50ec7;
|
||||||
|
background-color: #f9f9f9;
|
||||||
|
}
|
||||||
|
|
||||||
|
.version {
|
||||||
|
font-weight: 600;
|
||||||
|
font-size: 1.5em;
|
||||||
|
color: #a50ec7;
|
||||||
|
margin-left: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.date {
|
||||||
|
font-style: italic;
|
||||||
|
color: #888;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
margin-left: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.description {
|
||||||
|
font-size: 1em;
|
||||||
|
padding: 0 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.description ul {
|
||||||
|
list-style: inside square;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media only screen and (max-width: 600px) {
|
||||||
|
.changelog-container {
|
||||||
|
width: 90%;
|
||||||
|
margin: 25px auto;
|
||||||
|
padding: 25px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<div class="changelog-container">
|
||||||
|
<!-- Changelog entry -->
|
||||||
|
<div class="change">
|
||||||
|
<div class="version">Version 1.4.9</div>
|
||||||
|
<div class="date">25.04.2024</div>
|
||||||
|
<div class="description">
|
||||||
|
- Improved compatibility with old mafiles<br/>
|
||||||
|
- FIX: Now 'Login' button is disabled if password is empty (caused crash before)<br />
|
||||||
|
- FIX: The tutorial for beginners is no longer shown after ever hiding (for example, when searching without suitable mafiles)<br />
|
||||||
|
- UI/UX improvements in proxy manager: <br />
|
||||||
|
- Favourite button is placed on proxy item<br />
|
||||||
|
- Pressing 'DEL' now removes selected proxy<br />
|
||||||
|
- After proxy is removed next to it is selected (allows to remove proxies quickly)<br />
|
||||||
|
- Empty lines on import now ignored (previously entire import was cancelling)<br />
|
||||||
|
- Mafile credits now corresponds to the actual github repository<br />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
Reference in New Issue
Block a user