Fix crash with empty fullname path

This commit is contained in:
2023-02-22 22:13:38 +01:00
parent 28bc479ee4
commit 3dccaa5243
8 changed files with 46 additions and 37 deletions

View File

@@ -128,7 +128,7 @@ public class TabPersistenceService : ITabPersistenceService
if (tab.Path == null) continue; if (tab.Path == null) continue;
IContainer? container = null; IContainer? container = null;
var path = new FullName(tab.Path); var path = FullName.CreateSafe(tab.Path);
while (true) while (true)
{ {
try try

View File

@@ -67,7 +67,7 @@ public abstract partial class ItemViewModel : IItemViewModel
IsSelected = itemViewModelType is ItemViewModelType.Main IsSelected = itemViewModelType is ItemViewModelType.Main
? parentTab.CurrentSelectedItem.Select(EqualsTo) ? parentTab.CurrentSelectedItem.Select(EqualsTo)
: Observable.Return(IsInDeespestPath()); : Observable.Return(IsInDeepestPath());
IsAlternative = sourceCollection.Select(c => c?.Index().FirstOrDefault(i => EqualsTo(i.Value)).Key % 2 == 0); IsAlternative = sourceCollection.Select(c => c?.Index().FirstOrDefault(i => EqualsTo(i.Value)).Key % 2 == 0);
@@ -92,7 +92,7 @@ public abstract partial class ItemViewModel : IItemViewModel
return BaseItem?.FullName?.Path is string path && path == itemViewModel?.BaseItem?.FullName?.Path; return BaseItem?.FullName?.Path is string path && path == itemViewModel?.BaseItem?.FullName?.Path;
} }
private bool IsInDeespestPath() private bool IsInDeepestPath()
{ {
if (_parentTab?.Tab?.LastDeepestSelectedPath is null if (_parentTab?.Tab?.LastDeepestSelectedPath is null
|| BaseItem?.FullName is null) || BaseItem?.FullName is null)
@@ -102,7 +102,7 @@ public abstract partial class ItemViewModel : IItemViewModel
var ownFullName = BaseItem.FullName; var ownFullName = BaseItem.FullName;
var deepestPath = _parentTab.Tab.LastDeepestSelectedPath; var deepestPath = _parentTab.Tab.LastDeepestSelectedPath;
var commonPath = new FullName(PathHelper.GetCommonPath(ownFullName.Path, deepestPath.Path)); var commonPath = FullName.CreateSafe(PathHelper.GetCommonPath(ownFullName.Path, deepestPath.Path));
return commonPath.Path == ownFullName.Path; return commonPath.Path == ownFullName.Path;
} }

View File

@@ -7,11 +7,18 @@ public record FullName(string Path)
var pathParts = Path.TrimEnd(Constants.SeparatorChar).Split(Constants.SeparatorChar); var pathParts = Path.TrimEnd(Constants.SeparatorChar).Split(Constants.SeparatorChar);
return pathParts.Length switch return pathParts.Length switch
{ {
> 1 => new(string.Join(Constants.SeparatorChar, pathParts.SkipLast(1))), > 1 => CreateSafe(string.Join(Constants.SeparatorChar, pathParts.SkipLast(1))),
_ => null _ => null
}; };
} }
public static FullName? CreateSafe(string? path)
{
if (string.IsNullOrWhiteSpace(path))
return null;
return new(path);
}
public string GetName() public string GetName()
=> Path.Split(Constants.SeparatorChar).Last(); => Path.Split(Constants.SeparatorChar).Last();

View File

@@ -55,7 +55,7 @@ public abstract class ContentProviderBase : IContentProvider
protected ContentProviderBase(string name) protected ContentProviderBase(string name)
{ {
DisplayName = Name = name; DisplayName = Name = name;
FullName = new FullName(name); FullName = FullName.CreateSafe(name);
Extensions = new ExtensionCollection(); Extensions = new ExtensionCollection();
_extensions = Extensions.AsReadOnly(); _extensions = Extensions.AsReadOnly();
} }

View File

@@ -1,10 +1,8 @@
using System.Collections.ObjectModel;
using System.Reactive.Linq; using System.Reactive.Linq;
using System.Reactive.Subjects; using System.Reactive.Subjects;
using DynamicData; using DynamicData;
using FileTime.Core.ContentAccess; using FileTime.Core.ContentAccess;
using FileTime.Core.Enums; using FileTime.Core.Enums;
using FileTime.Core.Services;
using FileTime.Core.Timeline; using FileTime.Core.Timeline;
namespace FileTime.Core.Models; namespace FileTime.Core.Models;
@@ -28,7 +26,7 @@ public record Container(
ReadOnlyExtensionCollection Extensions, ReadOnlyExtensionCollection Extensions,
IObservable<IObservable<IChangeSet<AbsolutePath, string>>?> Items) : IContainer IObservable<IObservable<IChangeSet<AbsolutePath, string>>?> Items) : IContainer
{ {
BehaviorSubject<bool> IsLoading { get; } = new BehaviorSubject<bool>(false); BehaviorSubject<bool> IsLoading { get; } = new(false);
IObservable<bool> IContainer.IsLoading => IsLoading.AsObservable(); IObservable<bool> IContainer.IsLoading => IsLoading.AsObservable();
public AbsolutePathType Type => AbsolutePathType.Container; public AbsolutePathType Type => AbsolutePathType.Container;
} }

View File

@@ -1,7 +1,5 @@
using System.Collections.ObjectModel;
using FileTime.Core.ContentAccess; using FileTime.Core.ContentAccess;
using FileTime.Core.Enums; using FileTime.Core.Enums;
using FileTime.Core.Services;
using FileTime.Core.Timeline; using FileTime.Core.Timeline;
namespace FileTime.Core.Models; namespace FileTime.Core.Models;

View File

@@ -37,7 +37,7 @@ public class Tab : ITab
{ {
if (_currentSelectedItemCached is not null) if (_currentSelectedItemCached is not null)
{ {
LastDeepestSelectedPath = new FullName(PathHelper.GetLongerPath(LastDeepestSelectedPath?.Path, _currentSelectedItemCached.Path.Path)); LastDeepestSelectedPath = FullName.CreateSafe(PathHelper.GetLongerPath(LastDeepestSelectedPath?.Path, _currentSelectedItemCached.Path.Path));
} }
}) })
.Publish(null) .Publish(null)
@@ -57,7 +57,7 @@ public class Tab : ITab
.Where(c => c is null) .Where(c => c is null)
.Select(_ => (IObservable<IChangeSet<IItem, string>>?)null) .Select(_ => (IObservable<IChangeSet<IItem, string>>?)null)
) )
.Publish((IObservable<IChangeSet<IItem, string>>?)null) .Publish(null)
.RefCount(); .RefCount();
CurrentSelectedItem = CurrentSelectedItem =
@@ -96,7 +96,7 @@ public class Tab : ITab
_currentLocation.OnNext(currentLocation); _currentLocation.OnNext(currentLocation);
} }
private AbsolutePath? GetSelectedItemByItems(IEnumerable<IItem> items) private AbsolutePath? GetSelectedItemByItems(IReadOnlyCollection<IItem> items)
{ {
if (!items.Any()) return null; if (!items.Any()) return null;
@@ -109,7 +109,7 @@ public class Tab : ITab
{ {
var itemNameToSelect = LastDeepestSelectedPath.Path var itemNameToSelect = LastDeepestSelectedPath.Path
.Split(Constants.SeparatorChar) .Split(Constants.SeparatorChar)
.Skip((parentPath?.Split(Constants.SeparatorChar).Length) ?? 0) .Skip(parentPath.Split(Constants.SeparatorChar).Length)
.FirstOrDefault(); .FirstOrDefault();
var itemToSelect = items.FirstOrDefault(i => i.FullName?.GetName() == itemNameToSelect); var itemToSelect = items.FirstOrDefault(i => i.FullName?.GetName() == itemNameToSelect);
@@ -121,7 +121,7 @@ public class Tab : ITab
} }
} }
LastDeepestSelectedPath = new FullName(PathHelper.GetLongerPath(LastDeepestSelectedPath?.Path, newSelectedItem.Path.Path)); LastDeepestSelectedPath = FullName.CreateSafe(PathHelper.GetLongerPath(LastDeepestSelectedPath?.Path, newSelectedItem.Path.Path));
return newSelectedItem; return newSelectedItem;
} }

View File

@@ -142,10 +142,13 @@ public sealed partial class LocalContentProvider : ContentProviderBase, ILocalCo
var fullName = GetFullName(nativePath); var fullName = GetFullName(nativePath);
var parentFullName = fullName.GetParent(); var parentFullName = fullName.GetParent();
var parent = new AbsolutePath( var parent =
parentFullName is null
? null
: new AbsolutePath(
_timelessContentProvider, _timelessContentProvider,
pointInTime, pointInTime,
parentFullName ?? new FullName(""), parentFullName,
AbsolutePathType.Container); AbsolutePathType.Container);
return new Container( return new Container(
@@ -208,10 +211,13 @@ public sealed partial class LocalContentProvider : ContentProviderBase, ILocalCo
{ {
var fullName = GetFullName(directoryInfo.FullName); var fullName = GetFullName(directoryInfo.FullName);
var parentFullName = fullName.GetParent(); var parentFullName = fullName.GetParent();
var parent = new AbsolutePath( var parent =
parentFullName is null
? null
: new AbsolutePath(
_timelessContentProvider, _timelessContentProvider,
pointInTime, pointInTime,
parentFullName ?? new FullName(""), parentFullName,
AbsolutePathType.Container); AbsolutePathType.Container);
var exceptions = new BehaviorSubject<IEnumerable<Exception>>(Enumerable.Empty<Exception>()); var exceptions = new BehaviorSubject<IEnumerable<Exception>>(Enumerable.Empty<Exception>());
@@ -299,10 +305,10 @@ public sealed partial class LocalContentProvider : ContentProviderBase, ILocalCo
private FullName GetFullName(NativePath nativePath) => GetFullName(nativePath.Path); private FullName GetFullName(NativePath nativePath) => GetFullName(nativePath.Path);
private FullName GetFullName(string nativePath) => private FullName GetFullName(string nativePath) =>
new((Name + Constants.SeparatorChar + FullName.CreateSafe((Name + Constants.SeparatorChar +
string.Join(Constants.SeparatorChar, string.Join(Constants.SeparatorChar,
nativePath.TrimStart(Constants.SeparatorChar).Split(Path.DirectorySeparatorChar))) nativePath.TrimStart(Constants.SeparatorChar).Split(Path.DirectorySeparatorChar)))
.TrimEnd(Constants.SeparatorChar)); .TrimEnd(Constants.SeparatorChar))!;
public override NativePath GetNativePath(FullName fullName) public override NativePath GetNativePath(FullName fullName)
{ {