Add settings, cloud places, and optional archive-content indexing.
Keep official clients in charge of sync while Explorer can group locations, persist UI prefs, and list zip/rar/7z members without extracting them. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -162,6 +162,53 @@ public sealed class SourceManager
|
||||
return source;
|
||||
}
|
||||
|
||||
public bool IsPresentInWindows(Source source)
|
||||
{
|
||||
var online = _volumes.EnumerateOnlineVolumes();
|
||||
foreach (var fp in online)
|
||||
{
|
||||
var match = VolumeIdentityMatcher.Match(fp, [source]);
|
||||
if (match.Source is not null)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (source.LastRootPath is not null && RootsEqual(fp.RootPath, source.LastRootPath))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return source.LastRootPath is not null && _volumes.IsPathReachable(source.LastRootPath);
|
||||
}
|
||||
|
||||
public bool CanForget(Source source) => !IsPresentInWindows(source);
|
||||
|
||||
public async Task<bool> CanForgetPathAsync(string path, CancellationToken cancellationToken = default)
|
||||
{
|
||||
var source = await FindSourceRootAsync(path, cancellationToken).ConfigureAwait(false);
|
||||
return source is not null && CanForget(source);
|
||||
}
|
||||
|
||||
public async Task<bool> ForgetDisconnectedAsync(string path, CancellationToken cancellationToken = default)
|
||||
{
|
||||
var source = await FindSourceRootAsync(path, cancellationToken).ConfigureAwait(false);
|
||||
if (source is null || !CanForget(source))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
await _store.RunWriteAsync(store => store.Sources.DeleteAsync(source.Id, cancellationToken), cancellationToken)
|
||||
.ConfigureAwait(false);
|
||||
if (source.LastRootPath is not null && PathRules.IsUnc(source.LastRootPath))
|
||||
{
|
||||
ForgetUnc(PathRules.CanonicalUncRoot(source.LastRootPath));
|
||||
}
|
||||
|
||||
_logger.LogInformation("Forgot disconnected source {DisplayName} ({Path})", source.DisplayName, source.LastRootPath);
|
||||
return true;
|
||||
}
|
||||
|
||||
public async Task<Source?> FindByPathAsync(string path, CancellationToken cancellationToken = default)
|
||||
{
|
||||
var sources = await _store.Sources.GetAllAsync(cancellationToken).ConfigureAwait(false);
|
||||
@@ -194,7 +241,7 @@ public sealed class SourceManager
|
||||
|
||||
public async Task<Source?> EnsureForPathAsync(string path, CancellationToken cancellationToken = default)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(path) || path == "This PC")
|
||||
if (string.IsNullOrWhiteSpace(path) || LocationRoots.IsVirtual(path))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
@@ -255,6 +302,50 @@ public sealed class SourceManager
|
||||
return created;
|
||||
}
|
||||
|
||||
private async Task<Source?> FindSourceRootAsync(string path, CancellationToken cancellationToken)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(path) || LocationRoots.IsVirtual(path))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var source = await FindByPathAsync(path, cancellationToken).ConfigureAwait(false);
|
||||
if (source?.LastRootPath is null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return RootsEqual(source.LastRootPath, path) ? source : null;
|
||||
}
|
||||
|
||||
private static bool RootsEqual(string a, string b)
|
||||
{
|
||||
var left = PathRules.EnsureDirectoryTrailingSlashIfRoot(PathRules.FromExtended(a).TrimEnd('\\'));
|
||||
var right = PathRules.EnsureDirectoryTrailingSlashIfRoot(PathRules.FromExtended(b).TrimEnd('\\'));
|
||||
return left.Equals(right, StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
private void ForgetUnc(string root)
|
||||
{
|
||||
try
|
||||
{
|
||||
var file = Path.Combine(_env.DataDirectory, "recents.txt");
|
||||
if (!File.Exists(file))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var lines = LoadRecents()
|
||||
.Where(l => !PathRules.CanonicalUncRoot(l).Equals(root, StringComparison.OrdinalIgnoreCase))
|
||||
.ToList();
|
||||
File.WriteAllLines(file, lines);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogDebug(ex, "Failed updating recents");
|
||||
}
|
||||
}
|
||||
|
||||
private IReadOnlyList<string> LoadRecents()
|
||||
{
|
||||
var file = Path.Combine(_env.DataDirectory, "recents.txt");
|
||||
|
||||
Reference in New Issue
Block a user