Skip to content

Commit

Permalink
throttle calls to search, closes #52
Browse files Browse the repository at this point in the history
  • Loading branch information
ScanMountGoat committed Jul 21, 2021
1 parent 7eb546b commit 990c3d7
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 17 deletions.
1 change: 1 addition & 0 deletions ArcExplorer/Tools/FileTree.cs
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,7 @@ private static FileNode CreateFileNode(ArcFile arcFile, ArcFileNode arcNode, Act
// Lazy initialize the shared file list for performance reasons.
List<string> getSharedFiles() => arcFile.GetSharedFilePaths(arcNode, ApplicationSettings.Instance.ArcRegion);

// TODO: Avoid caching this information since it may change when changing regions.
var fileNode = new FileNode(arcNode.FileName, arcNode.Path, arcNode.Extension,
arcNode.IsShared, arcNode.IsRegional, arcNode.Offset, arcNode.CompSize, arcNode.DecompSize, arcNode.IsCompressed,
getSharedFiles);
Expand Down
55 changes: 38 additions & 17 deletions ArcExplorer/ViewModels/MainWindowViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reactive;
using System.Reactive.Linq;
using System.Threading;
using System.Threading.Tasks;

namespace ArcExplorer.ViewModels
Expand All @@ -25,6 +28,8 @@ public AvaloniaList<FileGridItem> Files
}
private AvaloniaList<FileGridItem> files = new AvaloniaList<FileGridItem>();

private readonly object searchLock = new object();

public static Dictionary<Region, string> DescriptionByRegion { get; } = new Dictionary<Region, string>
{
{ Region.Japanese, "Japanese" },
Expand Down Expand Up @@ -177,11 +182,7 @@ public string ErrorDescription
public string SearchText
{
get => searchText;
set
{
this.RaiseAndSetIfChanged(ref searchText, value);
SearchArcFile(searchText);
}
set => this.RaiseAndSetIfChanged(ref searchText, value);
}
private string searchText = "";

Expand All @@ -201,6 +202,14 @@ public MainWindowViewModel()
{
Serilog.Log.Logger.Error("Failed to open Hashes file {@path}", hashesFile);
}

// Throttle search calls to reduce the chance of searching while the user is still typing.
// Subscribing to an asynchronous method described here:
// https://stackoverflow.com/questions/27618401/what-is-the-best-way-to-call-async-methods-using-reactiveui-throttle
this.WhenAnyValue(x => x.SearchText)
.Throttle(TimeSpan.FromMilliseconds(500))
.SelectMany(SearchArcFileAsync)
.Subscribe();
}

private void LogEventHandled(object? sender, EventArgs e)
Expand Down Expand Up @@ -257,19 +266,31 @@ private void InitializeArcFile(string arcPathText)
LoadRootNodes(arcFile);
}

private void SearchArcFile(string searchText)
private async Task<Unit> SearchArcFileAsync(string searchText, CancellationToken cancel)
{
if (arcFile == null)
return;
await Task.Run(() => SearchArcFileThreaded(searchText));
return Unit.Default;
}

if (!string.IsNullOrEmpty(searchText))
{
var nodes = FileTree.SearchAllNodes(arcFile, BackgroundTaskStart, BackgroundTaskReportProgress, BackgroundTaskEnd, searchText, ApplicationSettings.Instance.MergeTrailingSlash);
Files = new AvaloniaList<FileGridItem>(nodes.Select(n => new FileGridItem(n)));
}
else
private void SearchArcFileThreaded(string searchText)
{
// This doesn't make all accesses to the file tree thread safe, but it does prevent multiple searches from running at once.
// This is good enough for calling just this method from multiple threads.
// Calling ARC methods should be inherently thread safe since we don't mutate the ARC struct or its wrapper type.
lock (searchLock)
{
LoadRootNodes(arcFile);
if (arcFile == null)
return;

if (!string.IsNullOrEmpty(searchText))
{
var nodes = FileTree.SearchAllNodes(arcFile, BackgroundTaskStart, BackgroundTaskReportProgress, BackgroundTaskEnd, searchText, ApplicationSettings.Instance.MergeTrailingSlash);
Files = new AvaloniaList<FileGridItem>(nodes.Select(n => new FileGridItem(n)));
}
else
{
LoadRootNodes(arcFile);
}
}
}

Expand Down Expand Up @@ -327,7 +348,7 @@ public void ExitFolder()
}

// Go up one level in the file tree.
var parent = FileTree.CreateNodeFromPath(arcFile, parentPath,
var parent = FileTree.CreateNodeFromPath(arcFile, parentPath,
BackgroundTaskStart, BackgroundTaskReportProgress, BackgroundTaskEnd, ApplicationSettings.Instance.MergeTrailingSlash);
if (parent is FolderNode folder)
LoadFolder(folder);
Expand All @@ -342,7 +363,7 @@ private void LoadFolder(string? path)
{
if (arcFile != null && path != null)
{
var parent = FileTree.CreateNodeFromPath(arcFile, path,
var parent = FileTree.CreateNodeFromPath(arcFile, path,
BackgroundTaskStart, BackgroundTaskReportProgress, BackgroundTaskEnd, ApplicationSettings.Instance.MergeTrailingSlash);
LoadFolder(parent as FolderNode);
}
Expand Down

0 comments on commit 990c3d7

Please sign in to comment.