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

Merged
merged 5 commits into from
Jan 7, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
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
2 changes: 1 addition & 1 deletion src/Files.App/Actions/Content/Run/RunAsAdminAction.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ ContentPageContext.SelectedItem is not null &&
ContentPageContext.PageType != ContentPageTypes.RecycleBin &&
ContentPageContext.PageType != ContentPageTypes.ZipFolder &&
(FileExtensionHelpers.IsExecutableFile(ContentPageContext.SelectedItem.FileExtension) ||
(ContentPageContext.SelectedItem is ShortcutItem shortcut &&
(ContentPageContext.SelectedItem is IShortcutItem shortcut &&
shortcut.IsExecutable));

public RunAsAdminAction() : base("runas")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ ContentPageContext.SelectedItem is not null &&
ContentPageContext.PageType != ContentPageTypes.ZipFolder &&
!FileExtensionHelpers.IsAhkFile(ContentPageContext.SelectedItem.FileExtension) &&
(FileExtensionHelpers.IsExecutableFile(ContentPageContext.SelectedItem.FileExtension) ||
(ContentPageContext.SelectedItem is ShortcutItem shortcut &&
(ContentPageContext.SelectedItem is IShortcutItem shortcut &&
shortcut.IsExecutable));

public RunAsAnotherUserAction() : base("runasuser")
Expand Down
2 changes: 1 addition & 1 deletion src/Files.App/Actions/FileSystem/OpenFileLocationAction.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public RichGlyph Glyph
public bool IsExecutable =>
context.ShellPage is not null &&
context.HasSelection &&
context.SelectedItem is ShortcutItem;
context.SelectedItem is IShortcutItem;

public OpenFileLocationAction()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -520,12 +520,12 @@ public static List<ContextMenuFlyoutItemViewModel> GetBaseItemMenuItems(
}.Build(),
new ContextMenuFlyoutItemViewModelBuilder(Commands.PinToStart)
{
IsVisible = selectedItems.All(x => (x.PrimaryItemAttribute == StorageItemTypes.Folder || x.IsExecutable || (x is ShortcutItem shortcutItem && FileExtensionHelpers.IsExecutableFile(shortcutItem.TargetPath))) && !x.IsArchive && !x.IsItemPinnedToStart),
IsVisible = selectedItems.All(x => (x.PrimaryItemAttribute == StorageItemTypes.Folder || x.IsExecutable || (x is IShortcutItem shortcutItem && FileExtensionHelpers.IsExecutableFile(shortcutItem.TargetPath))) && !x.IsArchive && !x.IsItemPinnedToStart),
ShowOnShift = true,
}.Build(),
new ContextMenuFlyoutItemViewModelBuilder(Commands.UnpinFromStart)
{
IsVisible = selectedItems.All(x => (x.PrimaryItemAttribute == StorageItemTypes.Folder || x.IsExecutable|| (x is ShortcutItem shortcutItem && FileExtensionHelpers.IsExecutableFile(shortcutItem.TargetPath))) && !x.IsArchive && x.IsItemPinnedToStart),
IsVisible = selectedItems.All(x => (x.PrimaryItemAttribute == StorageItemTypes.Folder || x.IsExecutable|| (x is IShortcutItem shortcutItem && FileExtensionHelpers.IsExecutableFile(shortcutItem.TargetPath))) && !x.IsArchive && x.IsItemPinnedToStart),
ShowOnShift = true,
}.Build(),
new ContextMenuFlyoutItemViewModel
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ public static ObservableCollection<NavigationViewItemButtonStyleItem> Initialize
{
var firstFileExtension = listedItems.FirstOrDefault()?.FileExtension;
var commonFileExt = listedItems.All(x => x.FileExtension == firstFileExtension) ? firstFileExtension : null;
var compatibilityItemEnabled = listedItems.All(listedItem => FileExtensionHelpers.IsExecutableFile(listedItem is ShortcutItem sht ? sht.TargetPath : commonFileExt, true));
var compatibilityItemEnabled = listedItems.All(listedItem => FileExtensionHelpers.IsExecutableFile(listedItem is IShortcutItem sht ? sht.TargetPath : commonFileExt, true));
var onlyFiles = listedItems.All(listedItem => listedItem.PrimaryItemAttribute == StorageItemTypes.File || listedItem.IsArchive);

if (!compatibilityItemEnabled)
Expand All @@ -101,7 +101,7 @@ public static ObservableCollection<NavigationViewItemButtonStyleItem> Initialize
var hashItemEnabled = !(isFolder && !listedItem.IsArchive) && !isLibrary && !listedItem.IsRecycleBinItem;
var detailsItemEnabled = !(isFolder && !listedItem.IsArchive) && !isLibrary && !listedItem.IsRecycleBinItem;
var customizationItemEnabled = !isLibrary && (isFolder && !listedItem.IsArchive || isShortcut && !listedItem.IsLinkItem);
var compatibilityItemEnabled = FileExtensionHelpers.IsExecutableFile(listedItem is ShortcutItem sht ? sht.TargetPath : fileExt, true);
var compatibilityItemEnabled = FileExtensionHelpers.IsExecutableFile(listedItem is IShortcutItem sht ? sht.TargetPath : fileExt, true);

if (!securityItemEnabled)
PropertiesNavigationViewItems.Remove(securityItem);
Expand Down
137 changes: 133 additions & 4 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 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 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 class GitItem : ListedItem, IGitItem
{
private volatile int statusPropertiesInitialized = 0;
public bool StatusPropertiesInitialized
Expand Down Expand Up @@ -678,4 +678,133 @@ public string? GitLastCommitFullSha
set => SetProperty(ref _GitLastCommitFullSha, value);
}
}
public sealed class GitShortcutItem : GitItem,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 Name { get; }
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 bool IsExecutable { get; }


}
}
2 changes: 1 addition & 1 deletion src/Files.App/Helpers/UI/UIFilesystemHelpers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,7 @@ public static async Task<bool> HandleShortcutCannotBeCreated(string shortcutName
/// <param name="arguments"></param>
/// <param name="workingDir"></param>
/// <param name="runAsAdmin"></param>
public static void UpdateShortcutItemProperties(ShortcutItem item, string targetPath, string arguments, string workingDir, bool runAsAdmin)
public static void UpdateShortcutItemProperties(IShortcutItem item, string targetPath, string arguments, string workingDir, bool runAsAdmin)
{
item.TargetPath = Environment.ExpandEnvironmentVariables(targetPath);
item.Arguments = arguments;
Expand Down
133 changes: 93 additions & 40 deletions src/Files.App/Utils/Storage/Enumerators/Win32StorageEnumerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -275,26 +275,51 @@ CancellationToken cancellationToken
if (isSymlink)
{
var targetPath = Win32Helper.ParseSymLink(itemPath);

return new ShortcutItem(null)
if (isGitRepo)
{
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
};
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,
};
}
else
{
return new ShortcutItem(null)
{
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))
{
Expand All @@ -304,28 +329,56 @@ CancellationToken cancellationToken
if (shInfo is null)
return null;

return new ShortcutItem(null)
if (isGitRepo)
{
PrimaryItemAttribute = shInfo.IsFolder ? StorageItemTypes.Folder : StorageItemTypes.File,
FileExtension = itemFileExtension,
IsHiddenItem = isHidden,
Opacity = opacity,
FileImage = null,
LoadFileIcon = !shInfo.IsFolder && itemThumbnailImgVis,
ItemNameRaw = itemName,
ItemDateModifiedReal = itemModifiedDate,
ItemDateAccessedReal = itemLastAccessDate,
ItemDateCreatedReal = itemCreatedDate,
ItemType = isUrl ? "ShortcutWebLinkFileType".GetLocalizedResource() : "Shortcut".GetLocalizedResource(),
ItemPath = itemPath,
FileSize = itemSize,
FileSizeBytes = itemSizeBytes,
TargetPath = shInfo.TargetPath,
Arguments = shInfo.Arguments,
WorkingDirectory = shInfo.WorkingDirectory,
RunAsAdmin = shInfo.RunAsAdmin,
IsUrl = isUrl,
};
return new GitShortcutItem()
{
PrimaryItemAttribute = shInfo.IsFolder ? StorageItemTypes.Folder : StorageItemTypes.File,
FileExtension = itemFileExtension,
IsHiddenItem = isHidden,
Opacity = opacity,
FileImage = null,
LoadFileIcon = !shInfo.IsFolder && itemThumbnailImgVis,
ItemNameRaw = itemName,
ItemDateModifiedReal = itemModifiedDate,
ItemDateAccessedReal = itemLastAccessDate,
ItemDateCreatedReal = itemCreatedDate,
ItemType = isUrl ? "ShortcutWebLinkFileType".GetLocalizedResource() : "Shortcut".GetLocalizedResource(),
ItemPath = itemPath,
FileSize = itemSize,
FileSizeBytes = itemSizeBytes,
TargetPath = shInfo.TargetPath,
Arguments = shInfo.Arguments,
WorkingDirectory = shInfo.WorkingDirectory,
RunAsAdmin = shInfo.RunAsAdmin,
IsUrl = isUrl,
};
}
else
{
return new ShortcutItem(null)
{
PrimaryItemAttribute = shInfo.IsFolder ? StorageItemTypes.Folder : StorageItemTypes.File,
FileExtension = itemFileExtension,
IsHiddenItem = isHidden,
Opacity = opacity,
FileImage = null,
LoadFileIcon = !shInfo.IsFolder && itemThumbnailImgVis,
ItemNameRaw = itemName,
ItemDateModifiedReal = itemModifiedDate,
ItemDateAccessedReal = itemLastAccessDate,
ItemDateCreatedReal = itemCreatedDate,
ItemType = isUrl ? "ShortcutWebLinkFileType".GetLocalizedResource() : "Shortcut".GetLocalizedResource(),
ItemPath = itemPath,
FileSize = itemSize,
FileSizeBytes = itemSizeBytes,
TargetPath = shInfo.TargetPath,
Arguments = shInfo.Arguments,
WorkingDirectory = shInfo.WorkingDirectory,
RunAsAdmin = shInfo.RunAsAdmin,
IsUrl = isUrl,
};
}
}
else if (App.LibraryManager.TryGetLibrary(itemPath, out LibraryLocationItem library))
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ public string SelectedHighDpiOverride

public CompatibilityViewModel(ListedItem item)
{
ItemPath = item is ShortcutItem shortcutItem ? shortcutItem.TargetPath : item.ItemPath;
ItemPath = item is IShortcutItem shortcutItem ? shortcutItem.TargetPath : item.ItemPath;

CompatibilityOptions = WindowsCompatibilityService.GetCompatibilityOptionsForPath(ItemPath);

Expand Down
Loading