Improved search performance

Pressing enter in the game name field now also starts a search.
This commit is contained in:
Jeddunk 2021-01-01 16:27:42 +01:00
parent 201e122e8b
commit 1042923249
6 changed files with 75 additions and 69 deletions

View File

@ -1,24 +1,36 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
using System.Text.RegularExpressions;
using auto_creamapi.Utils;
namespace auto_creamapi.Models namespace auto_creamapi.Models
{ {
public class SteamApp public class SteamApp
{ {
private string _name;
private string _comparableName;
[JsonPropertyName("appid")] public int AppId { get; set; } [JsonPropertyName("appid")] public int AppId { get; set; }
[JsonPropertyName("name")] public string Name { get; set; } [JsonPropertyName("name")]
public string Name
{
get => _name;
set
{
_name = value;
_comparableName = Regex.Replace(value, Misc.SpecialCharsRegex, "").ToLower();
}
}
public bool CompareName(string value)
{
return _comparableName.Equals(value);
}
public override string ToString() public override string ToString()
{ {
//return $"AppId: {AppId}, Name: {Name}";
return $"{AppId}={Name}"; return $"{AppId}={Name}";
} }
public bool CompareId(SteamApp steamApp)
{
return AppId.Equals(steamApp.AppId);
}
} }
public class AppList public class AppList

View File

@ -1,6 +1,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq;
using System.Net.Http; using System.Net.Http;
using System.Text; using System.Text;
using System.Text.Json; using System.Text.Json;
@ -35,24 +36,7 @@ namespace auto_creamapi.Services
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) " + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) " +
"Chrome/87.0.4280.88 Safari/537.36"; "Chrome/87.0.4280.88 Safari/537.36";
private const string SpecialCharsRegex = "[^0-9a-zA-Z]+"; private HashSet<SteamApp> _cache = new HashSet<SteamApp>();
private List<SteamApp> _cache = new List<SteamApp>();
/*private static readonly Lazy<CacheService> Lazy =
new Lazy<CacheService>(() => new CacheService());
public static CacheService Instance => Lazy.Value;*/
public CacheService()
{
}
/*public async void Initialize()
{
//Languages = _defaultLanguages;
await UpdateCache();
}*/
public async Task Initialize() public async Task Initialize()
{ {
@ -81,7 +65,7 @@ namespace auto_creamapi.Services
} }
var steamApps = JsonSerializer.Deserialize<SteamApps>(cacheString); var steamApps = JsonSerializer.Deserialize<SteamApps>(cacheString);
_cache = steamApps.AppList.Apps; _cache = new HashSet<SteamApp>(steamApps.AppList.Apps);
MyLogger.Log.Information("Loaded cache into memory!"); MyLogger.Log.Information("Loaded cache into memory!");
} }
@ -96,9 +80,8 @@ namespace auto_creamapi.Services
public SteamApp GetAppByName(string name) public SteamApp GetAppByName(string name)
{ {
MyLogger.Log.Information($"Trying to get app {name}"); MyLogger.Log.Information($"Trying to get app {name}");
var app = _cache.Find(x => var comparableName = Regex.Replace(name, Misc.SpecialCharsRegex, "").ToLower();
Regex.Replace(x.Name, SpecialCharsRegex, "").ToLower() var app = _cache.FirstOrDefault(x => x.CompareName(comparableName));
.Equals(Regex.Replace(name, SpecialCharsRegex, "").ToLower()));
if (app != null) MyLogger.Log.Information($"Successfully got app {app}"); if (app != null) MyLogger.Log.Information($"Successfully got app {app}");
return app; return app;
} }
@ -106,7 +89,7 @@ namespace auto_creamapi.Services
public SteamApp GetAppById(int appid) public SteamApp GetAppById(int appid)
{ {
MyLogger.Log.Information($"Trying to get app with ID {appid}"); MyLogger.Log.Information($"Trying to get app with ID {appid}");
var app = _cache.Find(x => x.AppId.Equals(appid)); var app = _cache.FirstOrDefault(x => x.AppId.Equals(appid));
if (app != null) MyLogger.Log.Information($"Successfully got app {app}"); if (app != null) MyLogger.Log.Information($"Successfully got app {app}");
return app; return app;
} }
@ -121,7 +104,7 @@ namespace auto_creamapi.Services
var steamAppDetails = await task; var steamAppDetails = await task;
steamAppDetails?.DLC.ForEach(x => steamAppDetails?.DLC.ForEach(x =>
{ {
var result = _cache.Find(y => y.AppId.Equals(x)) ?? var result = _cache.FirstOrDefault(y => y.AppId.Equals(x)) ??
new SteamApp {AppId = x, Name = $"Unknown DLC {x}"}; new SteamApp {AppId = x, Name = $"Unknown DLC {x}"};
dlcList.Add(result); dlcList.Add(result);
}); });
@ -173,7 +156,7 @@ namespace auto_creamapi.Services
if (query3 != null) dlcName = query3[1].Text().Replace("\n", "").Trim(); if (query3 != null) dlcName = query3[1].Text().Replace("\n", "").Trim();
var dlcApp = new SteamApp {AppId = Convert.ToInt32(dlcId), Name = dlcName}; var dlcApp = new SteamApp {AppId = Convert.ToInt32(dlcId), Name = dlcName};
var i = dlcList.FindIndex(x => x.CompareId(dlcApp)); var i = dlcList.FindIndex(x => x.AppId.Equals(dlcApp.AppId));
if (i > -1) if (i > -1)
{ {
if (dlcList[i].Name.Contains("Unknown DLC")) dlcList[i] = dlcApp; if (dlcList[i].Name.Contains("Unknown DLC")) dlcList[i] = dlcApp;
@ -189,7 +172,7 @@ namespace auto_creamapi.Services
} }
else else
{ {
MyLogger.Log.Error("Could not get DLC from SteamDB1"); MyLogger.Log.Error("Could not get DLC from SteamDB!");
} }
} }
} }

View File

@ -5,7 +5,7 @@ namespace auto_creamapi.Utils
{ {
public class Misc public class Misc
{ {
public const string SpecialCharsRegex = "[^0-9a-zA-Z]+";
public const string DefaultLanguageSelection = "english"; public const string DefaultLanguageSelection = "english";
public static readonly ObservableCollection<string> DefaultLanguages = new ObservableCollection<string>(new[] public static readonly ObservableCollection<string> DefaultLanguages = new ObservableCollection<string>(new[]
{ {

View File

@ -26,7 +26,7 @@ namespace auto_creamapi.ViewModels
private ObservableCollection<SteamApp> _dlcs; private ObservableCollection<SteamApp> _dlcs;
private bool _dllApplied; private bool _dllApplied;
private string _dllPath; private string _dllPath;
private bool _extraprotection; private bool _extraProtection;
private string _gameName; private string _gameName;
private string _lang; private string _lang;
private ObservableCollection<string> _languages; private ObservableCollection<string> _languages;
@ -35,7 +35,7 @@ namespace auto_creamapi.ViewModels
private bool _mainWindowEnabled; private bool _mainWindowEnabled;
private bool _offline; private bool _offline;
private string _status; private string _status;
private bool _unlockall; private bool _unlockAll;
private bool _useSteamDb; private bool _useSteamDb;
//private const string DlcRegexPattern = @"(?<id>.*) *= *(?<name>.*)"; //private const string DlcRegexPattern = @"(?<id>.*) *= *(?<name>.*)";
@ -144,23 +144,23 @@ namespace auto_creamapi.ViewModels
} }
} }
public bool Extraprotection public bool ExtraProtection
{ {
get => _extraprotection; get => _extraProtection;
set set
{ {
_extraprotection = value; _extraProtection = value;
RaisePropertyChanged(() => Extraprotection); RaisePropertyChanged(() => ExtraProtection);
} }
} }
public bool Unlockall public bool UnlockAll
{ {
get => _unlockall; get => _unlockAll;
set set
{ {
_unlockall = value; _unlockAll = value;
RaisePropertyChanged(() => Unlockall); RaisePropertyChanged(() => UnlockAll);
} }
} }
@ -319,8 +319,8 @@ namespace auto_creamapi.ViewModels
_config.SetConfigData( _config.SetConfigData(
AppId, AppId,
Lang, Lang,
Unlockall, UnlockAll,
Extraprotection, ExtraProtection,
Offline, Offline,
Dlcs Dlcs
); );
@ -334,8 +334,8 @@ namespace auto_creamapi.ViewModels
{ {
AppId = _config.Config.AppId; AppId = _config.Config.AppId;
Lang = _config.Config.Language; Lang = _config.Config.Language;
Unlockall = _config.Config.UnlockAll; UnlockAll = _config.Config.UnlockAll;
Extraprotection = _config.Config.ExtraProtection; ExtraProtection = _config.Config.ExtraProtection;
Offline = _config.Config.ForceOffline; Offline = _config.Config.ForceOffline;
Dlcs = new ObservableCollection<SteamApp>(_config.Config.DlcList); Dlcs = new ObservableCollection<SteamApp>(_config.Config.DlcList);
Status = "Changes have been reset."; Status = "Changes have been reset.";

View File

@ -1,3 +1,4 @@
<!-- ReSharper disable once UnusedType.Global -->
<views:MvxWpfView <views:MvxWpfView
xmlns:views="clr-namespace:MvvmCross.Platforms.Wpf.Views;assembly=MvvmCross.Platforms.Wpf" xmlns:views="clr-namespace:MvvmCross.Platforms.Wpf.Views;assembly=MvvmCross.Platforms.Wpf"
x:Class="auto_creamapi.Views.MainView" x:Class="auto_creamapi.Views.MainView"
@ -25,36 +26,45 @@
<RowDefinition Height="Auto" /> <RowDefinition Height="Auto" />
<RowDefinition Height="Auto" /> <RowDefinition Height="Auto" />
</Grid.RowDefinitions> </Grid.RowDefinitions>
<wcl:WatermarkTextBox x:Name="DllPath" Text="{Binding DllPath}" Watermark="Path to game's steam_api(64).dll..." <wcl:WatermarkTextBox Text="{Binding DllPath}" Watermark="Path to game's steam_api(64).dll..."
Margin="10,11,55,0" TextWrapping="NoWrap" VerticalAlignment="Top" Padding="0" Margin="10,11,55,0" TextWrapping="NoWrap" VerticalAlignment="Top" Padding="0"
Grid.Row="0" IsReadOnly="True" IsReadOnlyCaretVisible="True"> Grid.Row="0" IsReadOnly="True" IsReadOnlyCaretVisible="True">
<!--MouseDoubleClick="{Binding Path=OpenFileCommand}"--> <!--MouseDoubleClick="{Binding Path=OpenFileCommand}"-->
<wcl:WatermarkTextBox.InputBindings> <wcl:WatermarkTextBox.InputBindings>
<MouseBinding Gesture="LeftDoubleClick" Command="{Binding OpenFileCommand}" /> <MouseBinding
Gesture="LeftDoubleClick"
Command="{Binding OpenFileCommand}" />
</wcl:WatermarkTextBox.InputBindings> </wcl:WatermarkTextBox.InputBindings>
</wcl:WatermarkTextBox> </wcl:WatermarkTextBox>
<Button Content="&#xE1A5;" HorizontalAlignment="Right" Margin="0,10,10,0" VerticalAlignment="Top" <Button Content="&#xE1A5;" HorizontalAlignment="Right" Margin="0,10,10,0" VerticalAlignment="Top"
FontFamily="Segoe UI Symbol" Width="40" Command="{Binding OpenFileCommand}" ToolTip="Select DLL file." FontFamily="Segoe UI Symbol" Width="40" Command="{Binding OpenFileCommand}" ToolTip="Select DLL file."
Grid.Row="0" /> Grid.Row="0" />
<wcl:WatermarkTextBox Text="{Binding GameName, Mode=TwoWay}" x:Name="Game" Margin="10,10,180,0" <wcl:WatermarkTextBox Text="{Binding GameName, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
Margin="10,10,180,0"
Watermark="Game Name" TextWrapping="Wrap" VerticalAlignment="Top" Padding="0" Watermark="Game Name" TextWrapping="Wrap" VerticalAlignment="Top" Padding="0"
Grid.Row="1" /> Grid.Row="1">
<wcl:WatermarkTextBox.InputBindings>
<KeyBinding
Key="Enter"
Command="{Binding SearchCommand}" />
</wcl:WatermarkTextBox.InputBindings>
</wcl:WatermarkTextBox>
<Button Content="&#xE11A;" HorizontalAlignment="Right" Margin="0,9,135,0" VerticalAlignment="Top" <Button Content="&#xE11A;" HorizontalAlignment="Right" Margin="0,9,135,0" VerticalAlignment="Top"
FontFamily="Segoe UI Symbol" Width="40" Command="{Binding SearchCommand}" ToolTip="Find AppID." FontFamily="Segoe UI Symbol" Width="40" Command="{Binding SearchCommand}" ToolTip="Find AppID."
Grid.Row="1" /> Grid.Row="1" />
<wcl:WatermarkTextBox Text="{Binding AppId, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" x:Name="AppId" <wcl:WatermarkTextBox Text="{Binding AppId, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
HorizontalAlignment="Right" Margin="0,10,10,0" Watermark="AppID" TextWrapping="Wrap" HorizontalAlignment="Right" Margin="0,10,10,0" Watermark="AppID" TextWrapping="Wrap"
VerticalAlignment="Top" Width="120" Padding="0" Grid.Row="1" /> VerticalAlignment="Top" Width="120" Padding="0" Grid.Row="1" />
<TextBlock Grid.Row="2" Margin="10,10,10,0"> <TextBlock Grid.Row="2" Margin="10,10,10,0">
<Hyperlink Command="{Binding GoToForumThreadCommand}">Search for cs.rin.ru thread</Hyperlink> <Hyperlink Command="{Binding GoToForumThreadCommand}">Search for cs.rin.ru thread</Hyperlink>
</TextBlock> </TextBlock>
<ComboBox x:Name="Lang" ItemsSource="{Binding Path=Languages}" SelectedItem="{Binding Path=Lang, Mode=TwoWay}" <ComboBox ItemsSource="{Binding Path=Languages}" SelectedItem="{Binding Path=Lang, Mode=TwoWay}"
HorizontalAlignment="Left" Margin="10,10,0,0" VerticalAlignment="Top" Width="120" Grid.Row="3" /> HorizontalAlignment="Left" Margin="10,10,0,0" VerticalAlignment="Top" Width="120" Grid.Row="3" />
<CheckBox x:Name="ForceOffline" Content="Force offline mode" IsChecked="{Binding Offline, Mode=TwoWay}" <CheckBox Content="Force offline mode" IsChecked="{Binding Offline, Mode=TwoWay}"
HorizontalAlignment="Left" Margin="10,10,0,0" VerticalAlignment="Top" ToolTip="offlinemode" HorizontalAlignment="Left" Margin="10,10,0,0" VerticalAlignment="Top" ToolTip="offlinemode"
Grid.Row="4" /> Grid.Row="4" />
<CheckBox x:Name="ExtraProtection" Content="Try to bypass game-specific protection" <CheckBox Content="Try to bypass game-specific protection"
IsChecked="{Binding Extraprotection, Mode=TwoWay}" HorizontalAlignment="Left" Margin="10,10,0,0" IsChecked="{Binding ExtraProtection, Mode=TwoWay}" HorizontalAlignment="Left" Margin="10,10,0,0"
VerticalAlignment="Top" ToolTip="extraprotection" Grid.Row="5" /> VerticalAlignment="Top" ToolTip="extraprotection" Grid.Row="5" />
<Grid Margin="10,10,10,0" Grid.Row="6"> <Grid Margin="10,10,10,0" Grid.Row="6">
<Grid.RowDefinitions> <Grid.RowDefinitions>
@ -69,20 +79,20 @@
<RowDefinition Height="*" /> <RowDefinition Height="*" />
<RowDefinition Height="Auto" /> <RowDefinition Height="Auto" />
</Grid.RowDefinitions> </Grid.RowDefinitions>
<CheckBox x:Name="UnlockAll" Content="Unlock all DLCs (if possible)" <CheckBox Content="Unlock all DLCs (if possible)"
IsChecked="{Binding Unlockall, Mode=TwoWay}" HorizontalAlignment="Left" IsChecked="{Binding UnlockAll, Mode=TwoWay}" HorizontalAlignment="Left"
Margin="10,10,0,0" VerticalAlignment="Top" ToolTip="unlockall" /> Margin="10,10,0,0" VerticalAlignment="Top" ToolTip="unlockall" />
<CheckBox x:Name="SteamDb" Content="Additionally use SteamDB for DLCs" <CheckBox Content="Additionally use SteamDB for DLCs"
IsChecked="{Binding UseSteamDb, Mode=TwoWay}" HorizontalAlignment="Left" IsChecked="{Binding UseSteamDb, Mode=TwoWay}" HorizontalAlignment="Left"
Margin="10,10,0,0" VerticalAlignment="Top" Grid.Row="1" /> Margin="10,10,0,0" VerticalAlignment="Top" Grid.Row="1" />
<!-- Text="{Binding Dlcs, Converter={StaticResource DlcConv}, Mode=TwoWay}"--> <!-- Text="{Binding Dlcs, Converter={StaticResource DlcConv}, Mode=TwoWay}"-->
<!-- Text="{Binding DlcsString, Mode=TwoWay}"--> <!-- Text="{Binding DlcsString, Mode=TwoWay}"-->
<wcl:WatermarkTextBox x:Name="ListOfDlcs" <wcl:WatermarkTextBox
Text="{Binding Dlcs, Converter={StaticResource DlcConv}, Mode=TwoWay}" Text="{Binding Dlcs, Converter={StaticResource DlcConv}, Mode=TwoWay}"
Margin="10,10,10,0" Watermark="List of DLCs...&#xA;0000 = DLC Name" Margin="10,10,10,0" Watermark="List of DLCs...&#xA;0000 = DLC Name"
TextWrapping="Wrap" AcceptsReturn="True" TextWrapping="Wrap" AcceptsReturn="True"
VerticalScrollBarVisibility="Visible" Padding="0" VerticalScrollBarVisibility="Visible" Padding="0"
FontFamily="../resources/#Courier Prime" Grid.Row="2" /> FontFamily="../resources/#Courier Prime" Grid.Row="2" />
<Button Content="Get DLCs for AppID" Margin="0,10,10,10" Height="19.96" HorizontalAlignment="Right" <Button Content="Get DLCs for AppID" Margin="0,10,10,10" Height="19.96" HorizontalAlignment="Right"
VerticalAlignment="Bottom" Width="108" Command="{Binding GetListOfDlcCommand}" Grid.Row="3" /> VerticalAlignment="Bottom" Width="108" Command="{Binding GetListOfDlcCommand}" Grid.Row="3" />
</Grid> </Grid>
@ -93,9 +103,9 @@
<ColumnDefinition Width="Auto" /> <ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" /> <ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions> </Grid.ColumnDefinitions>
<CheckBox x:Name="CreamApiApplied" Content="CreamAPI DLL applied" Margin="10,10,0,10" <CheckBox Content="CreamAPI DLL applied" Margin="10,10,0,10"
Grid.Column="0" IsChecked="{Binding DllApplied, Mode=TwoWay}" /> Grid.Column="0" IsChecked="{Binding DllApplied, Mode=TwoWay}" />
<CheckBox x:Name="ConfigExists" Content="CreamAPI Config exists" Margin="10,10,0,10" <CheckBox Content="CreamAPI Config exists" Margin="10,10,0,10"
Grid.Column="1" IsChecked="{Binding ConfigExists, Mode=TwoWay}" /> Grid.Column="1" IsChecked="{Binding ConfigExists, Mode=TwoWay}" />
</Grid> </Grid>
</GroupBox> </GroupBox>
@ -106,7 +116,7 @@
VerticalAlignment="Bottom" HorizontalAlignment="Right" Width="40" Grid.Row="7" /> VerticalAlignment="Bottom" HorizontalAlignment="Right" Width="40" Grid.Row="7" />
<StatusBar Grid.Row="8"> <StatusBar Grid.Row="8">
<StatusBarItem Height="30" Margin="0,0,0,0"> <StatusBarItem Height="30" Margin="0,0,0,0">
<TextBlock x:Name="Status" Text="{Binding Status, Mode=TwoWay}" /> <TextBlock Text="{Binding Status, Mode=TwoWay}" />
</StatusBarItem> </StatusBarItem>
</StatusBar> </StatusBar>
</Grid> </Grid>

View File

@ -3,6 +3,7 @@ using MvvmCross.Platforms.Wpf.Presenters.Attributes;
namespace auto_creamapi.Views namespace auto_creamapi.Views
{ {
[MvxContentPresentation(WindowIdentifier = nameof(MainView), StackNavigation = false)] [MvxContentPresentation(WindowIdentifier = nameof(MainView), StackNavigation = false)]
// ReSharper disable once UnusedType.Global
public partial class MainView public partial class MainView
{ {
public MainView() public MainView()