From 3d0d1dfe3114d50495e75dba913b3624f3a0ca53 Mon Sep 17 00:00:00 2001 From: Ashraf Mansuri Date: Wed, 11 Dec 2024 00:28:32 +0530 Subject: [PATCH 1/5] Created an Interface IGitItem and derived class from it. --- src/Files.App/Data/Items/ListedItem.cs | 137 +++++++++++++++++- .../Enumerators/Win32StorageEnumerator.cs | 26 +++- src/Files.App/ViewModels/ShellViewModel.cs | 6 +- .../Views/Layouts/BaseGroupableLayoutPage.cs | 4 +- src/Files.App/Views/Layouts/BaseLayoutPage.cs | 2 +- .../Views/Layouts/DetailsLayoutPage.xaml.cs | 10 +- .../Views/Layouts/GridLayoutPage.xaml.cs | 2 +- 7 files changed, 168 insertions(+), 19 deletions(-) diff --git a/src/Files.App/Data/Items/ListedItem.cs b/src/Files.App/Data/Items/ListedItem.cs index 84d3e16fe4d1..fe2985dde5bf 100644 --- a/src/Files.App/Data/Items/ListedItem.cs +++ b/src/Files.App/Data/Items/ListedItem.cs @@ -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); @@ -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; } @@ -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) { @@ -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 @@ -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; } + + } } diff --git a/src/Files.App/Utils/Storage/Enumerators/Win32StorageEnumerator.cs b/src/Files.App/Utils/Storage/Enumerators/Win32StorageEnumerator.cs index 64bf1c0e2915..24d41c6fcc9b 100644 --- a/src/Files.App/Utils/Storage/Enumerators/Win32StorageEnumerator.cs +++ b/src/Files.App/Utils/Storage/Enumerators/Win32StorageEnumerator.cs @@ -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); @@ -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, + }; + } else if (FileExtensionHelpers.IsShortcutOrUrlFile(findData.cFileName)) { var isUrl = FileExtensionHelpers.IsWebLinkFile(findData.cFileName); diff --git a/src/Files.App/ViewModels/ShellViewModel.cs b/src/Files.App/ViewModels/ShellViewModel.cs index a69554d6a568..9c58029beba8 100644 --- a/src/Files.App/ViewModels/ShellViewModel.cs +++ b/src/Files.App/ViewModels/ShellViewModel.cs @@ -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)) { @@ -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; @@ -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); }); } diff --git a/src/Files.App/Views/Layouts/BaseGroupableLayoutPage.cs b/src/Files.App/Views/Layouts/BaseGroupableLayoutPage.cs index 009315e3f747..295fb7d4768e 100644 --- a/src/Files.App/Views/Layouts/BaseGroupableLayoutPage.cs +++ b/src/Files.App/Views/Layouts/BaseGroupableLayoutPage.cs @@ -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); } @@ -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; diff --git a/src/Files.App/Views/Layouts/BaseLayoutPage.cs b/src/Files.App/Views/Layouts/BaseLayoutPage.cs index 180bc8c0c907..6b76150e717e 100644 --- a/src/Files.App/Views/Layouts/BaseLayoutPage.cs +++ b/src/Files.App/Views/Layouts/BaseLayoutPage.cs @@ -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); }); } diff --git a/src/Files.App/Views/Layouts/DetailsLayoutPage.xaml.cs b/src/Files.App/Views/Layouts/DetailsLayoutPage.xaml.cs index 073cf5110fb3..8b5f6748c65f 100644 --- a/src/Files.App/Views/Layouts/DetailsLayoutPage.xaml.cs +++ b/src/Files.App/Views/Layouts/DetailsLayoutPage.xaml.cs @@ -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; @@ -696,10 +696,10 @@ private void ResizeColumnToFit(int columnToResize) { 1 => 40, // Check all items columns 2 => FileList.Items.Cast().Select(x => x.Name?.Length ?? 0).Max(), // file name column - 4 => FileList.Items.Cast().Select(x => (x as GitItem)?.GitLastCommitDateHumanized?.Length ?? 0).Max(), // git - 5 => FileList.Items.Cast().Select(x => (x as GitItem)?.GitLastCommitMessage?.Length ?? 0).Max(), // git - 6 => FileList.Items.Cast().Select(x => (x as GitItem)?.GitLastCommitAuthor?.Length ?? 0).Max(), // git - 7 => FileList.Items.Cast().Select(x => (x as GitItem)?.GitLastCommitSha?.Length ?? 0).Max(), // git + 4 => FileList.Items.Cast().Select(x => (x as IGitItem)?.GitLastCommitDateHumanized?.Length ?? 0).Max(), // git + 5 => FileList.Items.Cast().Select(x => (x as IGitItem)?.GitLastCommitMessage?.Length ?? 0).Max(), // git + 6 => FileList.Items.Cast().Select(x => (x as IGitItem)?.GitLastCommitAuthor?.Length ?? 0).Max(), // git + 7 => FileList.Items.Cast().Select(x => (x as IGitItem)?.GitLastCommitSha?.Length ?? 0).Max(), // git 8 => FileList.Items.Cast().Select(x => x.FileTagsUI?.Sum(x => x?.Name?.Length ?? 0) ?? 0).Max(), // file tag column 9 => FileList.Items.Cast().Select(x => x.ItemPath?.Length ?? 0).Max(), // path column 10 => FileList.Items.Cast().Select(x => (x as RecycleBinItem)?.ItemOriginalPath?.Length ?? 0).Max(), // original path column diff --git a/src/Files.App/Views/Layouts/GridLayoutPage.xaml.cs b/src/Files.App/Views/Layouts/GridLayoutPage.xaml.cs index 2868a6e2a0ec..510995f97e20 100644 --- a/src/Files.App/Views/Layouts/GridLayoutPage.xaml.cs +++ b/src/Files.App/Views/Layouts/GridLayoutPage.xaml.cs @@ -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; From ccf9f63b08bbceef97ed5592c8464d2e4e430a51 Mon Sep 17 00:00:00 2001 From: Ashraf Mansuri Date: Sat, 14 Dec 2024 14:30:44 +0530 Subject: [PATCH 2/5] Nested the is git repo in isymlink and shortcut --- src/Files.App/Data/Items/ListedItem.cs | 6 +- .../Enumerators/Win32StorageEnumerator.cs | 157 +++++++++++------- 2 files changed, 96 insertions(+), 67 deletions(-) diff --git a/src/Files.App/Data/Items/ListedItem.cs b/src/Files.App/Data/Items/ListedItem.cs index fe2985dde5bf..7d20285131a4 100644 --- a/src/Files.App/Data/Items/ListedItem.cs +++ b/src/Files.App/Data/Items/ListedItem.cs @@ -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 IGitItem AsGitItem => this as IGitItem; + public GitItem AsGitItem => this as GitItem; public string Key { get; set; } @@ -602,7 +602,7 @@ public override string Name } } - public sealed class GitItem : ListedItem, IGitItem + public class GitItem : ListedItem, IGitItem { private volatile int statusPropertiesInitialized = 0; public bool StatusPropertiesInitialized @@ -678,7 +678,7 @@ public string? GitLastCommitFullSha set => SetProperty(ref _GitLastCommitFullSha, value); } } - public sealed class GitShortcutItem : ListedItem, IGitItem,IShortcutItem + public sealed class GitShortcutItem : GitItem,IShortcutItem { private volatile int statusPropertiesInitialized = 0; public bool StatusPropertiesInitialized diff --git a/src/Files.App/Utils/Storage/Enumerators/Win32StorageEnumerator.cs b/src/Files.App/Utils/Storage/Enumerators/Win32StorageEnumerator.cs index 24d41c6fcc9b..6f5a2c028cde 100644 --- a/src/Files.App/Utils/Storage/Enumerators/Win32StorageEnumerator.cs +++ b/src/Files.App/Utils/Storage/Enumerators/Win32StorageEnumerator.cs @@ -272,53 +272,54 @@ CancellationToken cancellationToken bool isReparsePoint = ((FileAttributes)findData.dwFileAttributes & FileAttributes.ReparsePoint) == FileAttributes.ReparsePoint; bool isSymlink = isReparsePoint && findData.dwReserved0 == Win32PInvoke.IO_REPARSE_TAG_SYMLINK; - if (isSymlink && !isGitRepo) + 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 - }; - } - else if (isSymlink && isGitRepo) - { - var targetPath = Win32Helper.ParseSymLink(itemPath); - - return new GitShortcutItem() + 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 { - 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 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 + }; + } + } else if (FileExtensionHelpers.IsShortcutOrUrlFile(findData.cFileName)) { @@ -328,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)) { From 13c48c00dbb046ab6ae9725f41092c6d2417bad5 Mon Sep 17 00:00:00 2001 From: Ashraf Mansuri Date: Sun, 15 Dec 2024 14:33:00 +0530 Subject: [PATCH 3/5] Replacing is ShortcutItem to the interface --- src/Files.App/Actions/Content/Run/RunAsAdminAction.cs | 2 +- .../Actions/Content/Run/RunAsAnotherUserAction.cs | 2 +- .../Actions/FileSystem/OpenFileLocationAction.cs | 2 +- .../Data/Factories/ContentPageContextFlyoutFactory.cs | 4 ++-- .../Data/Factories/PropertiesNavigationViewItemFactory.cs | 4 ++-- src/Files.App/Data/Items/ListedItem.cs | 6 +++++- src/Files.App/Helpers/UI/UIFilesystemHelpers.cs | 2 +- .../ViewModels/Properties/CompatibilityViewModel.cs | 2 +- src/Files.App/ViewModels/ShellViewModel.cs | 2 +- src/Files.App/Views/Layouts/ColumnLayoutPage.xaml.cs | 8 ++++---- 10 files changed, 19 insertions(+), 15 deletions(-) diff --git a/src/Files.App/Actions/Content/Run/RunAsAdminAction.cs b/src/Files.App/Actions/Content/Run/RunAsAdminAction.cs index a178ea505328..be7b80b43238 100644 --- a/src/Files.App/Actions/Content/Run/RunAsAdminAction.cs +++ b/src/Files.App/Actions/Content/Run/RunAsAdminAction.cs @@ -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") diff --git a/src/Files.App/Actions/Content/Run/RunAsAnotherUserAction.cs b/src/Files.App/Actions/Content/Run/RunAsAnotherUserAction.cs index 53dd3a719b4f..6ca467092a9d 100644 --- a/src/Files.App/Actions/Content/Run/RunAsAnotherUserAction.cs +++ b/src/Files.App/Actions/Content/Run/RunAsAnotherUserAction.cs @@ -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") diff --git a/src/Files.App/Actions/FileSystem/OpenFileLocationAction.cs b/src/Files.App/Actions/FileSystem/OpenFileLocationAction.cs index 8e37acd1be0d..084afe4f90b4 100644 --- a/src/Files.App/Actions/FileSystem/OpenFileLocationAction.cs +++ b/src/Files.App/Actions/FileSystem/OpenFileLocationAction.cs @@ -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() { diff --git a/src/Files.App/Data/Factories/ContentPageContextFlyoutFactory.cs b/src/Files.App/Data/Factories/ContentPageContextFlyoutFactory.cs index 2c282955ac97..49e16ade5266 100644 --- a/src/Files.App/Data/Factories/ContentPageContextFlyoutFactory.cs +++ b/src/Files.App/Data/Factories/ContentPageContextFlyoutFactory.cs @@ -520,12 +520,12 @@ public static List 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 diff --git a/src/Files.App/Data/Factories/PropertiesNavigationViewItemFactory.cs b/src/Files.App/Data/Factories/PropertiesNavigationViewItemFactory.cs index ce6e3d8f856c..3cb8fffedaf4 100644 --- a/src/Files.App/Data/Factories/PropertiesNavigationViewItemFactory.cs +++ b/src/Files.App/Data/Factories/PropertiesNavigationViewItemFactory.cs @@ -75,7 +75,7 @@ public static ObservableCollection 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) @@ -101,7 +101,7 @@ public static ObservableCollection 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); diff --git a/src/Files.App/Data/Items/ListedItem.cs b/src/Files.App/Data/Items/ListedItem.cs index 7d20285131a4..3529e7471728 100644 --- a/src/Files.App/Data/Items/ListedItem.cs +++ b/src/Files.App/Data/Items/ListedItem.cs @@ -796,11 +796,15 @@ public string ItemPath 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; } + + } } diff --git a/src/Files.App/Helpers/UI/UIFilesystemHelpers.cs b/src/Files.App/Helpers/UI/UIFilesystemHelpers.cs index 71a913caab75..a5db9d222c10 100644 --- a/src/Files.App/Helpers/UI/UIFilesystemHelpers.cs +++ b/src/Files.App/Helpers/UI/UIFilesystemHelpers.cs @@ -250,7 +250,7 @@ public static async Task HandleShortcutCannotBeCreated(string shortcutName /// /// /// - 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; diff --git a/src/Files.App/ViewModels/Properties/CompatibilityViewModel.cs b/src/Files.App/ViewModels/Properties/CompatibilityViewModel.cs index c5ed13885e91..33aa87359c42 100644 --- a/src/Files.App/ViewModels/Properties/CompatibilityViewModel.cs +++ b/src/Files.App/ViewModels/Properties/CompatibilityViewModel.cs @@ -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); diff --git a/src/Files.App/ViewModels/ShellViewModel.cs b/src/Files.App/ViewModels/ShellViewModel.cs index 9c58029beba8..94b66b46a8c0 100644 --- a/src/Files.App/ViewModels/ShellViewModel.cs +++ b/src/Files.App/ViewModels/ShellViewModel.cs @@ -1270,7 +1270,7 @@ private bool CheckElevationRights(ListedItem item) if (item.SyncStatusUI.LoadSyncStatus) return false; - return WindowsSecurityService.IsElevationRequired(item.IsShortcut ? ((ShortcutItem)item).TargetPath : item.ItemPath); + return WindowsSecurityService.IsElevationRequired(item.IsShortcut ? ((IShortcutItem)item).TargetPath : item.ItemPath); } public async Task LoadGitPropertiesAsync(IGitItem gitItem) diff --git a/src/Files.App/Views/Layouts/ColumnLayoutPage.xaml.cs b/src/Files.App/Views/Layouts/ColumnLayoutPage.xaml.cs index c5f55acfb441..14088038a636 100644 --- a/src/Files.App/Views/Layouts/ColumnLayoutPage.xaml.cs +++ b/src/Files.App/Views/Layouts/ColumnLayoutPage.xaml.cs @@ -298,7 +298,7 @@ protected override void FileList_SelectionChanged(object sender, SelectionChange // Open the selected folder if selected through tap if (UserSettingsService.FoldersSettingsService.ColumnLayoutOpenFoldersWithOneClick && !isDraggingSelectionRectangle) - ItemInvoked?.Invoke(new ColumnParam { Source = this, NavPathParam = (SelectedItem is ShortcutItem sht ? sht.TargetPath : SelectedItem.ItemPath), ListView = FileList }, EventArgs.Empty); + ItemInvoked?.Invoke(new ColumnParam { Source = this, NavPathParam = (SelectedItem is IShortcutItem sht ? sht.TargetPath : SelectedItem.ItemPath), ListView = FileList }, EventArgs.Empty); else CloseFolder(); } @@ -352,7 +352,7 @@ ParentShellPageInstance is null || e.Handled = true; if (IsItemSelected && SelectedItem?.PrimaryItemAttribute == StorageItemTypes.Folder) - ItemInvoked?.Invoke(new ColumnParam { Source = this, NavPathParam = (SelectedItem is ShortcutItem sht ? sht.TargetPath : SelectedItem.ItemPath), ListView = FileList }, EventArgs.Empty); + ItemInvoked?.Invoke(new ColumnParam { Source = this, NavPathParam = (SelectedItem is IShortcutItem sht ? sht.TargetPath : SelectedItem.ItemPath), ListView = FileList }, EventArgs.Empty); } else if (e.Key == VirtualKey.Enter && e.KeyStatus.IsMenuKeyDown) { @@ -423,7 +423,7 @@ private async void FileList_DoubleTapped(object sender, DoubleTappedRoutedEventA break; case StorageItemTypes.Folder: if (!UserSettingsService.FoldersSettingsService.ColumnLayoutOpenFoldersWithOneClick) - ItemInvoked?.Invoke(new ColumnParam { Source = this, NavPathParam = (item is ShortcutItem sht ? sht.TargetPath : item.ItemPath), ListView = FileList }, EventArgs.Empty); + ItemInvoked?.Invoke(new ColumnParam { Source = this, NavPathParam = (item is IShortcutItem sht ? sht.TargetPath : item.ItemPath), ListView = FileList }, EventArgs.Empty); break; default: if (UserSettingsService.FoldersSettingsService.DoubleClickToGoUp) @@ -566,7 +566,7 @@ protected override void SelectionRectangle_SelectionEnded(object? sender, EventA if (SelectedItems?.Count is 1 && SelectedItem is not null && SelectedItem.PrimaryItemAttribute is StorageItemTypes.Folder) - ItemInvoked?.Invoke(new ColumnParam { Source = this, NavPathParam = (SelectedItem is ShortcutItem sht ? sht.TargetPath : SelectedItem.ItemPath), ListView = FileList }, EventArgs.Empty); + ItemInvoked?.Invoke(new ColumnParam { Source = this, NavPathParam = (SelectedItem is IShortcutItem sht ? sht.TargetPath : SelectedItem.ItemPath), ListView = FileList }, EventArgs.Empty); base.SelectionRectangle_SelectionEnded(sender, e); } From 47bf6440fba2d24a43ada39819af6001bd1fe137 Mon Sep 17 00:00:00 2001 From: Ashraf Mansuri Date: Sun, 15 Dec 2024 16:08:05 +0530 Subject: [PATCH 4/5] Changed cast operation to ShortcutItem --- src/Files.App/ViewModels/ShellViewModel.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Files.App/ViewModels/ShellViewModel.cs b/src/Files.App/ViewModels/ShellViewModel.cs index 94b66b46a8c0..9c58029beba8 100644 --- a/src/Files.App/ViewModels/ShellViewModel.cs +++ b/src/Files.App/ViewModels/ShellViewModel.cs @@ -1270,7 +1270,7 @@ private bool CheckElevationRights(ListedItem item) if (item.SyncStatusUI.LoadSyncStatus) return false; - return WindowsSecurityService.IsElevationRequired(item.IsShortcut ? ((IShortcutItem)item).TargetPath : item.ItemPath); + return WindowsSecurityService.IsElevationRequired(item.IsShortcut ? ((ShortcutItem)item).TargetPath : item.ItemPath); } public async Task LoadGitPropertiesAsync(IGitItem gitItem) From faec3b962c1ba45c1afe06a4f1a50d3582a2d05c Mon Sep 17 00:00:00 2001 From: Ashraf Mansuri Date: Sun, 15 Dec 2024 16:15:21 +0530 Subject: [PATCH 5/5] Cast operation changed to ShortcutItem --- src/Files.App/Data/Items/ListedItem.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Files.App/Data/Items/ListedItem.cs b/src/Files.App/Data/Items/ListedItem.cs index 3529e7471728..358badf6f86f 100644 --- a/src/Files.App/Data/Items/ListedItem.cs +++ b/src/Files.App/Data/Items/ListedItem.cs @@ -407,7 +407,7 @@ public override string ToString() public bool IsRecycleBinItem => this is RecycleBinItem; public bool IsShortcut => this is IShortcutItem; public bool IsLibrary => this is LibraryItem; - public bool IsLinkItem => IsShortcut && ((IShortcutItem)this).IsUrl; + 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;