Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix: Fixed issue where soft link details were misaligned in git repos #16593

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
137 changes: 131 additions & 6 deletions src/Files.App/Data/Items/ListedItem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -405,13 +405,13 @@ public override string ToString()

public bool IsFolder => PrimaryItemAttribute is StorageItemTypes.Folder;
public bool IsRecycleBinItem => this is RecycleBinItem;
public bool IsShortcut => this is ShortcutItem;
public bool IsShortcut => this is IShortcutItem;
public bool IsLibrary => this is LibraryItem;
public bool IsLinkItem => IsShortcut && ((ShortcutItem)this).IsUrl;
public bool IsLinkItem => IsShortcut && ((IShortcutItem)this).IsUrl;
public bool IsFtpItem => this is FtpItem;
public bool IsArchive => this is ZipItem;
public bool IsAlternateStream => this is AlternateStreamItem;
public bool IsGitItem => this is GitItem;
public bool IsGitItem => this is IGitItem;
public virtual bool IsExecutable => !IsFolder && FileExtensionHelpers.IsExecutableFile(ItemPath);
public virtual bool IsScriptFile => FileExtensionHelpers.IsScriptFile(ItemPath);
public bool IsPinned => App.QuickAccessManager.Model.PinnedFolders.Contains(itemPath);
Expand All @@ -428,7 +428,7 @@ public BaseStorageFile ItemFile
// This is a hack used because x:Bind casting did not work properly
public RecycleBinItem AsRecycleBinItem => this as RecycleBinItem;

public GitItem AsGitItem => this as GitItem;
public IGitItem AsGitItem => this as IGitItem;

public string Key { get; set; }

Expand Down Expand Up @@ -507,7 +507,7 @@ public FtpItem(FtpListItem item, string folder) : base(null)
};
}

public sealed class ShortcutItem : ListedItem
public sealed class ShortcutItem : ListedItem, IShortcutItem
{
public ShortcutItem(string folderRelativeId) : base(folderRelativeId)
{
Expand Down Expand Up @@ -602,7 +602,7 @@ public override string Name
}
}

public sealed class GitItem : ListedItem
public sealed class GitItem : ListedItem, IGitItem
{
private volatile int statusPropertiesInitialized = 0;
public bool StatusPropertiesInitialized
Expand Down Expand Up @@ -678,4 +678,129 @@ public string? GitLastCommitFullSha
set => SetProperty(ref _GitLastCommitFullSha, value);
}
}
public sealed class GitShortcutItem : ListedItem, IGitItem,IShortcutItem
{
private volatile int statusPropertiesInitialized = 0;
public bool StatusPropertiesInitialized
{
get => statusPropertiesInitialized == 1;
set => Interlocked.Exchange(ref statusPropertiesInitialized, value ? 1 : 0);
}

private volatile int commitPropertiesInitialized = 0;
public bool CommitPropertiesInitialized
{
get => commitPropertiesInitialized == 1;
set => Interlocked.Exchange(ref commitPropertiesInitialized, value ? 1 : 0);
}

private Style? _UnmergedGitStatusIcon;
public Style? UnmergedGitStatusIcon
{
get => _UnmergedGitStatusIcon;
set => SetProperty(ref _UnmergedGitStatusIcon, value);
}

private string? _UnmergedGitStatusName;
public string? UnmergedGitStatusName
{
get => _UnmergedGitStatusName;
set => SetProperty(ref _UnmergedGitStatusName, value);
}

private DateTimeOffset? _GitLastCommitDate;
public DateTimeOffset? GitLastCommitDate
{
get => _GitLastCommitDate;
set
{
SetProperty(ref _GitLastCommitDate, value);
GitLastCommitDateHumanized = value is DateTimeOffset dto ? dateTimeFormatter.ToShortLabel(dto) : "";
}
}

private string? _GitLastCommitDateHumanized;
public string? GitLastCommitDateHumanized
{
get => _GitLastCommitDateHumanized;
set => SetProperty(ref _GitLastCommitDateHumanized, value);
}

private string? _GitLastCommitMessage;
public string? GitLastCommitMessage
{
get => _GitLastCommitMessage;
set => SetProperty(ref _GitLastCommitMessage, value);
}

private string? _GitCommitAuthor;
public string? GitLastCommitAuthor
{
get => _GitCommitAuthor;
set => SetProperty(ref _GitCommitAuthor, value);
}

private string? _GitLastCommitSha;
public string? GitLastCommitSha
{
get => _GitLastCommitSha;
set => SetProperty(ref _GitLastCommitSha, value);
}

private string? _GitLastCommitFullSha;
public string? GitLastCommitFullSha
{
get => _GitLastCommitFullSha;
set => SetProperty(ref _GitLastCommitFullSha, value);
}

public string TargetPath { get; set; }

public override string Name
=> IsSymLink ? base.Name : Path.GetFileNameWithoutExtension(ItemNameRaw); // Always hide extension for shortcuts

public string Arguments { get; set; }
public string WorkingDirectory { get; set; }
public bool RunAsAdmin { get; set; }
public bool IsUrl { get; set; }
public bool IsSymLink { get; set; }
public override bool IsExecutable => FileExtensionHelpers.IsExecutableFile(TargetPath, true);
}
public interface IGitItem
{
public bool StatusPropertiesInitialized { get ; set; }
public bool CommitPropertiesInitialized { get; set; }

public Style? UnmergedGitStatusIcon{ get; set; }

public string? UnmergedGitStatusName{ get; set; }

public DateTimeOffset? GitLastCommitDate{ get; set; }

public string? GitLastCommitDateHumanized{ get; set; }

public string? GitLastCommitMessage{ get; set; }

public string? GitLastCommitAuthor{ get; set; }

public string? GitLastCommitSha{ get; set; }

public string? GitLastCommitFullSha{ get; set; }

public string ItemPath
{
get;
set;
}
}
public interface IShortcutItem
{
public string TargetPath { get; set; }
public string Arguments { get; set; }
public string WorkingDirectory { get; set; }
public bool RunAsAdmin { get; set; }
public bool IsUrl { get; set; }
public bool IsSymLink { get; set; }

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -272,7 +272,7 @@ CancellationToken cancellationToken
bool isReparsePoint = ((FileAttributes)findData.dwFileAttributes & FileAttributes.ReparsePoint) == FileAttributes.ReparsePoint;
bool isSymlink = isReparsePoint && findData.dwReserved0 == Win32PInvoke.IO_REPARSE_TAG_SYMLINK;

if (isSymlink)
if (isSymlink && !isGitRepo)
{
var targetPath = Win32Helper.ParseSymLink(itemPath);

Expand All @@ -296,6 +296,30 @@ CancellationToken cancellationToken
IsSymLink = true
};
}
else if (isSymlink && isGitRepo)
{
var targetPath = Win32Helper.ParseSymLink(itemPath);

return new GitShortcutItem()
{
PrimaryItemAttribute = StorageItemTypes.File,
FileExtension = itemFileExtension,
IsHiddenItem = isHidden,
Opacity = opacity,
FileImage = null,
LoadFileIcon = itemThumbnailImgVis,
ItemNameRaw = itemName,
ItemDateModifiedReal = itemModifiedDate,
ItemDateAccessedReal = itemLastAccessDate,
ItemDateCreatedReal = itemCreatedDate,
ItemType = "Shortcut".GetLocalizedResource(),
ItemPath = itemPath,
FileSize = itemSize,
FileSizeBytes = itemSizeBytes,
TargetPath = targetPath,
IsSymLink = true,
};
}
yaira2 marked this conversation as resolved.
Show resolved Hide resolved
else if (FileExtensionHelpers.IsShortcutOrUrlFile(findData.cFileName))
{
var isUrl = FileExtensionHelpers.IsWebLinkFile(findData.cFileName);
Expand Down
6 changes: 3 additions & 3 deletions src/Files.App/ViewModels/ShellViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ public GitProperties EnabledGitProperties
{
filesAndFolders.ToList().ForEach(async item =>
{
if (item is GitItem gitItem &&
if (item is IGitItem gitItem &&
(!gitItem.StatusPropertiesInitialized && value is GitProperties.All or GitProperties.Status
|| !gitItem.CommitPropertiesInitialized && value is GitProperties.All or GitProperties.Commit))
{
Expand Down Expand Up @@ -1273,7 +1273,7 @@ private bool CheckElevationRights(ListedItem item)
return WindowsSecurityService.IsElevationRequired(item.IsShortcut ? ((ShortcutItem)item).TargetPath : item.ItemPath);
}

public async Task LoadGitPropertiesAsync(GitItem gitItem)
public async Task LoadGitPropertiesAsync(IGitItem gitItem)
{
var getStatus = EnabledGitProperties is GitProperties.All or GitProperties.Status && !gitItem.StatusPropertiesInitialized;
var getCommit = EnabledGitProperties is GitProperties.All or GitProperties.Commit && !gitItem.CommitPropertiesInitialized;
Expand Down Expand Up @@ -2585,7 +2585,7 @@ public void UpdateDateDisplay(bool isFormatChange)
await dispatcherQueue.EnqueueOrInvokeAsync(() => item.ItemDateModifiedReal = item.ItemDateModifiedReal);
if (item is RecycleBinItem recycleBinItem && (isFormatChange || IsDateDiff(recycleBinItem.ItemDateDeletedReal)))
await dispatcherQueue.EnqueueOrInvokeAsync(() => recycleBinItem.ItemDateDeletedReal = recycleBinItem.ItemDateDeletedReal);
if (item is GitItem gitItem && gitItem.GitLastCommitDate is DateTimeOffset offset && (isFormatChange || IsDateDiff(offset)))
if (item is IGitItem gitItem && gitItem.GitLastCommitDate is DateTimeOffset offset && (isFormatChange || IsDateDiff(offset)))
await dispatcherQueue.EnqueueOrInvokeAsync(() => gitItem.GitLastCommitDate = gitItem.GitLastCommitDate);
});
}
Expand Down
4 changes: 2 additions & 2 deletions src/Files.App/Views/Layouts/BaseGroupableLayoutPage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ protected virtual async Task ReloadSelectedItemIconAsync()
await ParentShellPageInstance.ShellViewModel.LoadExtendedItemPropertiesAsync(ParentShellPageInstance.SlimContentPage.SelectedItem);

if (ParentShellPageInstance.ShellViewModel.EnabledGitProperties is not GitProperties.None &&
ParentShellPageInstance.SlimContentPage.SelectedItem is GitItem gitItem)
ParentShellPageInstance.SlimContentPage.SelectedItem is IGitItem gitItem)
{
await ParentShellPageInstance.ShellViewModel.LoadGitPropertiesAsync(gitItem);
}
Expand All @@ -161,7 +161,7 @@ protected virtual async Task ReloadSelectedItemsIconAsync()
{
await Task.WhenAll(ParentShellPageInstance.SlimContentPage.SelectedItems.Select(item =>
{
if (item is GitItem gitItem)
if (item is IGitItem gitItem)
return ParentShellPageInstance.ShellViewModel.LoadGitPropertiesAsync(gitItem);

return Task.CompletedTask;
Expand Down
2 changes: 1 addition & 1 deletion src/Files.App/Views/Layouts/BaseLayoutPage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1208,7 +1208,7 @@ private void RefreshItem(SelectorItem container, object item, bool inRecycleQueu
args.RegisterUpdateCallback(callbackPhase, async (s, c) =>
{
await ParentShellPageInstance!.ShellViewModel.LoadExtendedItemPropertiesAsync(listedItem);
if (ParentShellPageInstance.ShellViewModel.EnabledGitProperties is not GitProperties.None && listedItem is GitItem gitItem)
if (ParentShellPageInstance.ShellViewModel.EnabledGitProperties is not GitProperties.None && listedItem is IGitItem gitItem)
await ParentShellPageInstance.ShellViewModel.LoadGitPropertiesAsync(gitItem);
});
}
Expand Down
10 changes: 5 additions & 5 deletions src/Files.App/Views/Layouts/DetailsLayoutPage.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -509,7 +509,7 @@ await Task.WhenAll(filesAndFolders.Select(listedItem =>
{
await Task.WhenAll(filesAndFolders.Select(item =>
{
if (item is GitItem gitItem)
if (item is IGitItem gitItem)
return ParentShellPageInstance.ShellViewModel.LoadGitPropertiesAsync(gitItem);

return Task.CompletedTask;
Expand Down Expand Up @@ -696,10 +696,10 @@ private void ResizeColumnToFit(int columnToResize)
{
1 => 40, // Check all items columns
2 => FileList.Items.Cast<ListedItem>().Select(x => x.Name?.Length ?? 0).Max(), // file name column
4 => FileList.Items.Cast<ListedItem>().Select(x => (x as GitItem)?.GitLastCommitDateHumanized?.Length ?? 0).Max(), // git
5 => FileList.Items.Cast<ListedItem>().Select(x => (x as GitItem)?.GitLastCommitMessage?.Length ?? 0).Max(), // git
6 => FileList.Items.Cast<ListedItem>().Select(x => (x as GitItem)?.GitLastCommitAuthor?.Length ?? 0).Max(), // git
7 => FileList.Items.Cast<ListedItem>().Select(x => (x as GitItem)?.GitLastCommitSha?.Length ?? 0).Max(), // git
4 => FileList.Items.Cast<ListedItem>().Select(x => (x as IGitItem)?.GitLastCommitDateHumanized?.Length ?? 0).Max(), // git
5 => FileList.Items.Cast<ListedItem>().Select(x => (x as IGitItem)?.GitLastCommitMessage?.Length ?? 0).Max(), // git
6 => FileList.Items.Cast<ListedItem>().Select(x => (x as IGitItem)?.GitLastCommitAuthor?.Length ?? 0).Max(), // git
7 => FileList.Items.Cast<ListedItem>().Select(x => (x as IGitItem)?.GitLastCommitSha?.Length ?? 0).Max(), // git
8 => FileList.Items.Cast<ListedItem>().Select(x => x.FileTagsUI?.Sum(x => x?.Name?.Length ?? 0) ?? 0).Max(), // file tag column
9 => FileList.Items.Cast<ListedItem>().Select(x => x.ItemPath?.Length ?? 0).Max(), // path column
10 => FileList.Items.Cast<ListedItem>().Select(x => (x as RecycleBinItem)?.ItemOriginalPath?.Length ?? 0).Max(), // original path column
Expand Down
2 changes: 1 addition & 1 deletion src/Files.App/Views/Layouts/GridLayoutPage.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -519,7 +519,7 @@ private async Task ReloadItemIconsAsync()
{
await Task.WhenAll(filesAndFolders.Select(item =>
{
if (item is GitItem gitItem)
if (item is IGitItem gitItem)
return ParentShellPageInstance.ShellViewModel.LoadGitPropertiesAsync(gitItem);

return Task.CompletedTask;
Expand Down