From 61ae73d04c3da1aca1bc649beecfa70a29130765 Mon Sep 17 00:00:00 2001 From: Andy Doyle Date: Tue, 19 Jan 2021 22:04:58 +0000 Subject: [PATCH 01/15] List SharePoint libraries mounted with OneDrive --- Files.Launcher/Program.cs | 41 ++++++++++++++++++ Files/Files.csproj | 1 + .../Cloud/CloudProviderController.cs | 1 + .../OneDriveSharePointCloudProvider.cs | 43 +++++++++++++++++++ 4 files changed, 86 insertions(+) create mode 100644 Files/Filesystem/Cloud/Providers/OneDriveSharePointCloudProvider.cs diff --git a/Files.Launcher/Program.cs b/Files.Launcher/Program.cs index a8fdfe96f832..8758bcf01157 100644 --- a/Files.Launcher/Program.cs +++ b/Files.Launcher/Program.cs @@ -344,6 +344,47 @@ await args.Request.SendResponseAsync(new ValueSet() } break; + case "GetSharePointSyncLocationsFromOneDrive": + using (var oneDriveAccountsKey = Registry.CurrentUser.OpenSubKey(@"SOFTWARE\Microsoft\OneDrive\Accounts", false)) + { + var sharepointAccounts = new ValueSet(); + + foreach (var account in oneDriveAccountsKey.GetSubKeyNames()) + { + var accountKeyName = @$"{oneDriveAccountsKey.Name}\{account}"; + var displayName = (string)Registry.GetValue(accountKeyName, "DisplayName", null); + var userFolderToExcludeFromResults = (string)Registry.GetValue(accountKeyName, "UserFolder", null); + var accountName = string.IsNullOrWhiteSpace(displayName) ? "SharePoint" : $"SharePoint - {displayName}"; + + var sharePointSyncFolders = new List(); + var mountPointKeyName = @$"SOFTWARE\Microsoft\OneDrive\Accounts\{account}\ScopeIdToMountPointPathCache"; + using (var mountPointsKey = Registry.CurrentUser.OpenSubKey(mountPointKeyName)) + { + var valueNames = mountPointsKey.GetValueNames(); + foreach (var valueName in valueNames) + { + var value = (string)Registry.GetValue(@$"HKEY_CURRENT_USER\{mountPointKeyName}", valueName, null); + if (!string.Equals(value, userFolderToExcludeFromResults, StringComparison.OrdinalIgnoreCase)) + { + sharePointSyncFolders.Add(value); + } + } + } + + foreach (var sharePointSyncFolder in sharePointSyncFolders.OrderBy(o => o)) + { + var parentFolder = System.IO.Directory.GetParent(sharePointSyncFolder)?.FullName ?? string.Empty; + if (!sharepointAccounts.Any(acc => string.Equals(acc.Value, parentFolder))) + { + sharepointAccounts.Add(accountName, parentFolder); + } + } + } + + await args.Request.SendResponseAsync(sharepointAccounts); + } + break; + default: if (args.Request.Message.ContainsKey("Application")) { diff --git a/Files/Files.csproj b/Files/Files.csproj index 9d25bc0fe089..0b8ca90e0fc7 100644 --- a/Files/Files.csproj +++ b/Files/Files.csproj @@ -172,6 +172,7 @@ + diff --git a/Files/Filesystem/Cloud/CloudProviderController.cs b/Files/Filesystem/Cloud/CloudProviderController.cs index ec5136bcf916..de572b146b5c 100644 --- a/Files/Filesystem/Cloud/CloudProviderController.cs +++ b/Files/Filesystem/Cloud/CloudProviderController.cs @@ -16,6 +16,7 @@ public CloudProviderController() new GoogleDriveCloudProvider(), new DropBoxCloudProvider(), new OneDriveCloudProvider(), + new OneDriveSharePointCloudProvider(), new MegaCloudProvider(), new BoxCloudProvider(), new AppleCloudProvider(), diff --git a/Files/Filesystem/Cloud/Providers/OneDriveSharePointCloudProvider.cs b/Files/Filesystem/Cloud/Providers/OneDriveSharePointCloudProvider.cs new file mode 100644 index 000000000000..3525922b7c8c --- /dev/null +++ b/Files/Filesystem/Cloud/Providers/OneDriveSharePointCloudProvider.cs @@ -0,0 +1,43 @@ +using Files.Enums; +using Files.Helpers; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Windows.ApplicationModel.AppService; +using Windows.Foundation.Collections; + +namespace Files.Filesystem.Cloud.Providers +{ + public class OneDriveSharePointCloudProvider : ICloudProviderDetector + { + public async Task DetectAsync(List cloudProviders) + { + try + { + using var connection = await AppServiceConnectionHelper.BuildConnection(); + var (status, response) = await connection.SendMessageWithRetryAsync(new ValueSet() + { + { "Arguments", "GetSharePointSyncLocationsFromOneDrive" } + }, TimeSpan.FromSeconds(10)); + if (status == AppServiceResponseStatus.Success) + { + foreach (var key in response.Message.Keys + .OrderBy(o => o)) + { + cloudProviders.Add(new CloudProvider() + { + ID = CloudProviders.OneDrive, + Name = key, + SyncFolder = (string)response.Message[key] + }); + } + } + } + catch + { + // Not detected + } + } + } +} \ No newline at end of file From 7c207aa0be2a0206b019b708ac4194264107b958 Mon Sep 17 00:00:00 2001 From: Andy Doyle Date: Fri, 29 Jan 2021 20:36:13 +0000 Subject: [PATCH 02/15] Improve drive detection and rendering --- Files.Launcher/Files.Launcher.csproj | 6 -- Files.Launcher/Program.cs | 59 +++------------- Files.Launcher/QuickLook.cs | 10 ++- Files/App.xaml.cs | 51 +++++--------- Files/Controllers/SidebarPinnedController.cs | 2 +- Files/DataModels/SidebarPinnedModel.cs | 67 +++++++++++++------ .../Cloud/CloudProviderController.cs | 17 ++--- .../Cloud/Providers/OneDriveCloudProvider.cs | 2 +- Files/Filesystem/CloudDrivesManager.cs | 66 ++++++++++-------- Files/Filesystem/Drives.cs | 56 ++++++++-------- Files/Helpers/AppServiceConnectionHelper.cs | 31 ++++++++- Files/ViewModels/SettingsViewModel.cs | 16 ++++- Files/Views/MainPage.xaml.cs | 3 + Files/Views/ModernShellPage.xaml.cs | 43 ++++-------- 14 files changed, 208 insertions(+), 221 deletions(-) diff --git a/Files.Launcher/Files.Launcher.csproj b/Files.Launcher/Files.Launcher.csproj index 30900bbb821d..11e3ca7c624b 100644 --- a/Files.Launcher/Files.Launcher.csproj +++ b/Files.Launcher/Files.Launcher.csproj @@ -111,9 +111,6 @@ true - - ..\packages\Newtonsoft.Json.12.0.3\lib\net45\Newtonsoft.Json.dll - @@ -126,9 +123,6 @@ - - $(MSBuildProgramFiles32)\Windows Kits\10\UnionMetadata\10.0.18362.0\Windows.winmd - diff --git a/Files.Launcher/Program.cs b/Files.Launcher/Program.cs index 8802cec48466..c6e0abe08419 100644 --- a/Files.Launcher/Program.cs +++ b/Files.Launcher/Program.cs @@ -233,9 +233,13 @@ private static async Task ParseArgumentsAsync(AppServiceRequestReceivedEventArgs await ParseRecycleBinActionAsync(args, binAction); break; - case "StartupTasks": + case "DetectQuickLook": // Check QuickLook Availability - QuickLook.CheckQuickLookAvailability(localSettings); + var available = QuickLook.CheckQuickLookAvailability(); + await args.Request.SendResponseAsync(new ValueSet() + { + { "IsAvailable", available } + }); break; case "ToggleQuickLook": @@ -326,8 +330,10 @@ await args.Request.SendResponseAsync(new ValueSet() break; case "GetOneDriveAccounts": - using (var oneDriveAccountsKey = Registry.CurrentUser.OpenSubKey(@"SOFTWARE\Microsoft\OneDrive\Accounts", false)) + try { + var oneDriveAccountsKey = Registry.CurrentUser.OpenSubKey(@"SOFTWARE\Microsoft\OneDrive\Accounts", false); + if (oneDriveAccountsKey == null) { await args.Request.SendResponseAsync(new ValueSet()); @@ -348,46 +354,9 @@ await args.Request.SendResponseAsync(new ValueSet() } await args.Request.SendResponseAsync(oneDriveAccounts); } - break; - - case "GetSharePointSyncLocationsFromOneDrive": - using (var oneDriveAccountsKey = Registry.CurrentUser.OpenSubKey(@"SOFTWARE\Microsoft\OneDrive\Accounts", false)) + catch { - var sharepointAccounts = new ValueSet(); - - foreach (var account in oneDriveAccountsKey.GetSubKeyNames()) - { - var accountKeyName = @$"{oneDriveAccountsKey.Name}\{account}"; - var displayName = (string)Registry.GetValue(accountKeyName, "DisplayName", null); - var userFolderToExcludeFromResults = (string)Registry.GetValue(accountKeyName, "UserFolder", null); - var accountName = string.IsNullOrWhiteSpace(displayName) ? "SharePoint" : $"SharePoint - {displayName}"; - - var sharePointSyncFolders = new List(); - var mountPointKeyName = @$"SOFTWARE\Microsoft\OneDrive\Accounts\{account}\ScopeIdToMountPointPathCache"; - using (var mountPointsKey = Registry.CurrentUser.OpenSubKey(mountPointKeyName)) - { - var valueNames = mountPointsKey.GetValueNames(); - foreach (var valueName in valueNames) - { - var value = (string)Registry.GetValue(@$"HKEY_CURRENT_USER\{mountPointKeyName}", valueName, null); - if (!string.Equals(value, userFolderToExcludeFromResults, StringComparison.OrdinalIgnoreCase)) - { - sharePointSyncFolders.Add(value); - } - } - } - - foreach (var sharePointSyncFolder in sharePointSyncFolders.OrderBy(o => o)) - { - var parentFolder = System.IO.Directory.GetParent(sharePointSyncFolder)?.FullName ?? string.Empty; - if (!sharepointAccounts.Any(acc => string.Equals(acc.Value, parentFolder))) - { - sharepointAccounts.Add(accountName, parentFolder); - } - } - } - - await args.Request.SendResponseAsync(sharepointAccounts); + await args.Request.SendResponseAsync(new ValueSet()); } break; @@ -829,12 +798,6 @@ private static bool HandleCommandLineArgs() return true; } - else if (arguments == "StartupTasks") - { - // Check QuickLook Availability - QuickLook.CheckQuickLookAvailability(localSettings); - return true; - } } return false; } diff --git a/Files.Launcher/QuickLook.cs b/Files.Launcher/QuickLook.cs index 88b89dd798eb..fbca309a763c 100644 --- a/Files.Launcher/QuickLook.cs +++ b/Files.Launcher/QuickLook.cs @@ -3,7 +3,6 @@ using System.IO; using System.IO.Pipes; using System.Security.Principal; -using Windows.Storage; namespace FilesFullTrust { @@ -30,7 +29,7 @@ public static void ToggleQuickLook(string path) } } - public static void CheckQuickLookAvailability(ApplicationDataContainer localSettings) + public static bool CheckQuickLookAvailability() { static int QuickLookServerAvailable() { @@ -51,7 +50,7 @@ static int QuickLookServerAvailable() return serverInstances; } - catch (TimeoutException e) + catch (TimeoutException) { client.Close(); return 0; @@ -61,14 +60,13 @@ static int QuickLookServerAvailable() try { var result = QuickLookServerAvailable(); - Logger.Info($"QuickLook detected: {result != 0}"); - localSettings.Values["quicklook_enabled"] = result != 0; + return result != 0; } catch (Exception ex) { Logger.Info(ex, ex.Message); - localSettings.Values["quicklook_enabled"] = 0; + return false; } } } diff --git a/Files/App.xaml.cs b/Files/App.xaml.cs index 2faf4ff9d313..fa1c122de2e0 100644 --- a/Files/App.xaml.cs +++ b/Files/App.xaml.cs @@ -46,12 +46,12 @@ sealed partial class App : Application public static IBundlesSettings BundlesSettings = new BundlesSettingsViewModel(); - public static SettingsViewModel AppSettings { get; set; } - public static InteractionViewModel InteractionViewModel { get; set; } + public static SettingsViewModel AppSettings { get; private set; } + public static InteractionViewModel InteractionViewModel { get; private set; } public static JumpListManager JumpList { get; } = new JumpListManager(); - public static SidebarPinnedController SidebarPinnedController { get; set; } - public static CloudDrivesManager CloudDrivesManager { get; set; } - public static DrivesManager DrivesManager { get; set; } + public static SidebarPinnedController SidebarPinnedController { get; private set; }// = new SidebarPinnedController(); + public static CloudDrivesManager CloudDrivesManager { get; private set; } + public static DrivesManager DrivesManager { get; private set; } private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); @@ -79,7 +79,7 @@ public App() StartAppCenter(); } - internal static async Task EnsureSettingsAndConfigurationAreBootstrapped() + private static async Task EnsureSettingsAndConfigurationAreBootstrapped() { if (AppSettings == null) { @@ -91,38 +91,17 @@ internal static async Task EnsureSettingsAndConfigurationAreBootstrapped() } } - if (CloudDrivesManager == null) - { - //Enumerate cloud drives on in the background. It will update the UI itself when finished - _ = Files.Filesystem.CloudDrivesManager.Instance.ContinueWith(o => - { - CloudDrivesManager = o.Result; - }); - } + InteractionViewModel ??= new InteractionViewModel(); + SidebarPinnedController ??= await SidebarPinnedController.CreateInstance(); + DrivesManager ??= new DrivesManager(); + CloudDrivesManager ??= new CloudDrivesManager(); - //Start off a list of tasks we need to run before we can continue startup - var tasksToRun = new List(); - - if (SidebarPinnedController == null) + // Start off a list of tasks we need to run before we can continue startup + _ = Task.Factory.StartNew(async () => { - tasksToRun.Add(Files.Controllers.SidebarPinnedController.CreateInstance().ContinueWith(o => SidebarPinnedController = o.Result)); - } - - if (DrivesManager == null) - { - tasksToRun.Add(Files.Filesystem.DrivesManager.Instance.ContinueWith(o => DrivesManager = o.Result)); - } - - if (InteractionViewModel == null) - { - InteractionViewModel = new InteractionViewModel(); - } - - if (tasksToRun.Any()) - { - //Only proceed when all tasks are completed - await Task.WhenAll(tasksToRun); - } + await DrivesManager.EnumerateDrivesAsync(); + await CloudDrivesManager.EnumerateDrivesAsync(); + }); } private async void StartAppCenter() diff --git a/Files/Controllers/SidebarPinnedController.cs b/Files/Controllers/SidebarPinnedController.cs index 0be5033c9fb9..241003204774 100644 --- a/Files/Controllers/SidebarPinnedController.cs +++ b/Files/Controllers/SidebarPinnedController.cs @@ -82,7 +82,7 @@ private async Task LoadAsync() Model.Save(); } - Model.AddAllItemsToSidebar(); + await Model.AddAllItemsToSidebar(); } public void SaveModel() diff --git a/Files/DataModels/SidebarPinnedModel.cs b/Files/DataModels/SidebarPinnedModel.cs index ebec16e25bd6..819246e7eb30 100644 --- a/Files/DataModels/SidebarPinnedModel.cs +++ b/Files/DataModels/SidebarPinnedModel.cs @@ -2,18 +2,24 @@ using Files.ViewModels; using Files.Views; using Newtonsoft.Json; +using NLog; using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Threading.Tasks; +using Windows.ApplicationModel.Core; +using Windows.UI.Core; using Windows.UI.Xaml.Media; namespace Files.DataModels { public class SidebarPinnedModel { + [JsonIgnore] + private readonly Logger Logger = LogManager.GetCurrentClassLogger(); + [JsonIgnore] public SettingsViewModel AppSettings => App.AppSettings; @@ -140,7 +146,7 @@ ex is ArgumentException // Pinned item was invalid Debug.WriteLine($"An error occured while swapping pinned items in the navigation sidebar. {ex.Message}"); this.Items = sidebarItemsBackup; this.RemoveStaleSidebarItems(); - this.AddAllItemsToSidebar(); + _ = this.AddAllItemsToSidebar(); } } @@ -177,37 +183,54 @@ public int IndexOfItem(INavigationControlItem locationItem, ListTask public async Task AddItemToSidebarAsync(string path) { - var item = await FilesystemTasks.Wrap(() => DrivesManager.GetRootFromPathAsync(path)); - var res = await FilesystemTasks.Wrap(() => StorageFileExtensions.DangerousGetFolderFromPathAsync(path, item)); - if (res || (FilesystemResult)ItemViewModel.CheckFolderAccessWithWin32(path)) + await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, async () => { - int insertIndex = MainPage.SideBarItems.IndexOf(MainPage.SideBarItems.Last(x => x.ItemType == NavigationControlItemType.Location - && !x.Path.Equals(App.AppSettings.RecycleBinPath))) + 1; - var locationItem = new LocationItem + Logger.Info("AddItemToSidebarAsync(string)"); + + await MainPage.sideBarItemsSemaphore.WaitAsync(); + try { - Font = App.Current.Resources["FluentUIGlyphs"] as FontFamily, - Path = path, - Glyph = GetItemIcon(path), - IsDefaultLocation = false, - Text = res.Result?.DisplayName ?? Path.GetFileName(path.TrimEnd('\\')) - }; + var item = await FilesystemTasks.Wrap(() => DrivesManager.GetRootFromPathAsync(path)); + var res = await FilesystemTasks.Wrap(() => StorageFileExtensions.DangerousGetFolderFromPathAsync(path, item)); + if (res) + { + int insertIndex = MainPage.SideBarItems.IndexOf(MainPage.SideBarItems.Last(x => x.ItemType == NavigationControlItemType.Location + && !x.Path.Equals(App.AppSettings.RecycleBinPath))) + 1; + var locationItem = new LocationItem + { + Font = App.Current.Resources["FluentUIGlyphs"] as FontFamily, + Path = path, + Glyph = GetItemIcon(path), + IsDefaultLocation = false, + Text = res.Result?.DisplayName ?? Path.GetFileName(path.TrimEnd('\\')) + }; + + if (!MainPage.SideBarItems.Contains(locationItem)) + { + MainPage.SideBarItems.Insert(insertIndex, locationItem); + } + } + else + { + Debug.WriteLine($"Pinned item was invalid and will be removed from the file lines list soon: {res.ErrorCode}"); + RemoveItem(path); + } - if (!MainPage.SideBarItems.Contains(locationItem)) + } + finally { - MainPage.SideBarItems.Insert(insertIndex, locationItem); + MainPage.sideBarItemsSemaphore.Release(); + Logger.Info("AddItemToSidebarAsync(string) complete"); } - } - else - { - Debug.WriteLine($"Pinned item was invalid and will be removed from the file lines list soon: {res.ErrorCode}"); - RemoveItem(path); - } + }); + + } /// /// Adds all items to the navigation sidebar /// - public async void AddAllItemsToSidebar() + public async Task AddAllItemsToSidebar() { for (int i = 0; i < Items.Count(); i++) { diff --git a/Files/Filesystem/Cloud/CloudProviderController.cs b/Files/Filesystem/Cloud/CloudProviderController.cs index 700c1bf8e546..891cee8f26fa 100644 --- a/Files/Filesystem/Cloud/CloudProviderController.cs +++ b/Files/Filesystem/Cloud/CloudProviderController.cs @@ -7,27 +7,18 @@ namespace Files.Filesystem.Cloud { public class CloudProviderController { - private List cloudProviders = new List(); - - public List CloudProviderDetectors => new List + private List CloudProviderDetectors => new List { new GoogleDriveCloudProvider(), new DropBoxCloudProvider(), new OneDriveCloudProvider(), - new OneDriveSharePointCloudProvider(), new MegaCloudProvider(), new BoxCloudProvider(), new AppleCloudProvider(), - new AmazonDriveProvider() + new AmazonDriveProvider(), }; - public List CloudProviders - { - get => cloudProviders.Where(x => !string.IsNullOrEmpty(x.SyncFolder)).ToList(); - set => cloudProviders = value; - } - - public async Task DetectInstalledCloudProvidersAsync() + public async Task> DetectInstalledCloudProvidersAsync() { var tasks = new List>>(); var results = new List(); @@ -39,7 +30,7 @@ public async Task DetectInstalledCloudProvidersAsync() await Task.WhenAll(tasks); - cloudProviders = tasks.SelectMany(o => o.Result).ToList(); + return tasks.SelectMany(o => o.Result).Distinct().ToList(); } } } \ No newline at end of file diff --git a/Files/Filesystem/Cloud/Providers/OneDriveCloudProvider.cs b/Files/Filesystem/Cloud/Providers/OneDriveCloudProvider.cs index e35fb65a2bfe..99b12d1dfebf 100644 --- a/Files/Filesystem/Cloud/Providers/OneDriveCloudProvider.cs +++ b/Files/Filesystem/Cloud/Providers/OneDriveCloudProvider.cs @@ -15,7 +15,7 @@ public async Task> DetectAsync() { try { - using var connection = await AppServiceConnectionHelper.BuildConnection(); + var connection = await AppServiceConnectionHelper.Instance; var (status, response) = await connection.SendMessageWithRetryAsync(new ValueSet() { { "Arguments", "GetOneDriveAccounts" } diff --git a/Files/Filesystem/CloudDrivesManager.cs b/Files/Filesystem/CloudDrivesManager.cs index 6ec0e92208c4..d658b4fa2096 100644 --- a/Files/Filesystem/CloudDrivesManager.cs +++ b/Files/Filesystem/CloudDrivesManager.cs @@ -5,8 +5,6 @@ using NLog; using System; using System.Collections.Generic; -using System.Diagnostics; -using System.IO; using System.Linq; using System.Threading.Tasks; using Windows.ApplicationModel.Core; @@ -16,10 +14,8 @@ namespace Files.Filesystem { public class CloudDrivesManager : ObservableObject { - private static readonly Task _instanceTask = CreateSingleton(); - - private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); - private List drivesList = new List(); + private readonly Logger Logger = LogManager.GetCurrentClassLogger(); + private readonly List drivesList = new List(); public IReadOnlyList Drives { @@ -33,16 +29,20 @@ public IReadOnlyList Drives } //Private as we want to prevent CloudDriveManager being constructed manually - private CloudDrivesManager() - { } + public CloudDrivesManager() + { + } - private async Task EnumerateDrivesAsync() + public async Task EnumerateDrivesAsync() { var cloudProviderController = new CloudProviderController(); - await cloudProviderController.DetectInstalledCloudProvidersAsync(); + Logger.Info("Detecting installed cloud drives"); + var cloudProviders = await cloudProviderController.DetectInstalledCloudProvidersAsync(); + Logger.Info($"Detected {cloudProviders.Count} cloud drives"); - foreach (var provider in cloudProviderController.CloudProviders) + foreach (var provider in cloudProviders) { + Logger.Info($"Adding cloud provider \"{provider.Name}\" mapped to {provider.SyncFolder}"); var cloudProviderItem = new DriveItem() { Text = provider.Name, @@ -60,49 +60,51 @@ private async Task EnumerateDrivesAsync() return this; } - private static async Task CreateSingleton() - { - var drives = new CloudDrivesManager(); - return await drives.EnumerateDrivesAsync(); - } - - public static Task Instance => _instanceTask; - private async Task RefreshUI() { + Logger.Info("RefreshUI()"); try { await SyncSideBarItemsUI(); } - catch (Exception) // UI Thread not ready yet, so we defer the pervious operation until it is. + catch (Exception ex) // UI Thread not ready yet, so we defer the previous operation until it is. { + Logger.Error(ex, "UI thread not ready yet"); System.Diagnostics.Debug.WriteLine($"RefreshUI Exception"); // Defer because UI-thread is not ready yet (and DriveItem requires it?) CoreApplication.MainView.Activated += RefreshUI; } + Logger.Info("RefreshUI() complete"); } private async void RefreshUI(CoreApplicationView sender, Windows.ApplicationModel.Activation.IActivatedEventArgs args) { - await SyncSideBarItemsUI(); + Logger.Info("RefreshUI(CoreApplicationView, IActivatedEventArgs)"); CoreApplication.MainView.Activated -= RefreshUI; + await SyncSideBarItemsUI(); + Logger.Info("RefreshUI(CoreApplicationView, IActivatedEventArgs) complete"); } private async Task SyncSideBarItemsUI() { - await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => + await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, async () => { - lock (MainPage.SideBarItems) + Logger.Info("SyncSideBarItemsUI()"); + + await MainPage.sideBarItemsSemaphore.WaitAsync(); + try { + var drivesSnapshot = Drives.OrderBy(o => o.Text).ToList(); + var drivesSection = MainPage.SideBarItems.FirstOrDefault(x => x is HeaderTextItem && x.Text == "SidebarCloudDrives".GetLocalized()); - if (drivesSection != null && Drives.Count == 0) + if (drivesSection != null && drivesSnapshot.Count == 0) { //No drives - remove the header MainPage.SideBarItems.Remove(drivesSection); } - if (drivesSection == null && Drives.Count > 0) + if (drivesSection == null && drivesSnapshot.Count > 0) { drivesSection = new HeaderTextItem() { @@ -125,23 +127,29 @@ await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPrio } } - var sectionStartIndex = MainPage.SideBarItems.IndexOf(drivesSection); - //Remove all existing cloud drives from the sidebar foreach (var item in MainPage.SideBarItems .Where(x => x.ItemType == NavigationControlItemType.CloudDrive) .ToList()) { + Logger.Info($"Removing cloud drive \"{item.Text}\""); MainPage.SideBarItems.Remove(item); } //Add all cloud drives to the sidebar - var insertAt = sectionStartIndex + 1; - foreach (var drive in Drives.OrderBy(o => o.Text)) + var insertAt = MainPage.SideBarItems.IndexOf(drivesSection) + 1; + foreach (var drive in drivesSnapshot) { + Logger.Info($"Inserting cloud drive \"{drive.Text}\" at position {insertAt}"); MainPage.SideBarItems.Insert(insertAt, drive); insertAt++; } + + } + finally + { + MainPage.sideBarItemsSemaphore.Release(); + Logger.Info("SyncSideBarItemsUI() complete"); } }); } diff --git a/Files/Filesystem/Drives.cs b/Files/Filesystem/Drives.cs index 4103ae344082..033019ccbce2 100644 --- a/Files/Filesystem/Drives.cs +++ b/Files/Filesystem/Drives.cs @@ -21,9 +21,8 @@ namespace Files.Filesystem { public class DrivesManager : ObservableObject { - private static readonly Task _instanceTask = CreateSingleton(); private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); - private List drivesList = new List(); + private readonly List drivesList = new List(); public IReadOnlyList Drives { @@ -48,20 +47,12 @@ public bool ShowUserConsentOnInit private bool driveEnumInProgress; //Private as we want to prevent CloudDriveManager being constructed manually - private DrivesManager() + public DrivesManager() { SetupDeviceWatcher(); } - private static async Task CreateSingleton() - { - var drives = new DrivesManager(); - return await drives.EnumerateDrivesAsync(); - } - - public static Task Instance => _instanceTask; - - private async Task EnumerateDrivesAsync() + public async Task EnumerateDrivesAsync() { driveEnumInProgress = true; @@ -108,6 +99,7 @@ private async void DeviceWatcher_EnumerationCompleted(DeviceWatcher sender, obje private async Task RefreshUI() { + Logger.Info("RefreshUI()"); try { await SyncSideBarItemsUI(); @@ -118,29 +110,39 @@ private async Task RefreshUI() // Defer because UI-thread is not ready yet (and DriveItem requires it?) CoreApplication.MainView.Activated += RefreshUI; } + Logger.Info("RefreshUI() complete"); } private async void RefreshUI(CoreApplicationView sender, Windows.ApplicationModel.Activation.IActivatedEventArgs args) { + Logger.Info("RefreshUI(CoreApplicationView, IActivatedEventArgs)"); await SyncSideBarItemsUI(); CoreApplication.MainView.Activated -= RefreshUI; + Logger.Info("RefreshUI(CoreApplicationView, IActivatedEventArgs) complete"); } private async Task SyncSideBarItemsUI() { - await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => + await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, async () => { - lock (MainPage.SideBarItems) + Logger.Info("SyncSideBarItemsUI()"); + + await MainPage.sideBarItemsSemaphore.WaitAsync(); + try { + var drivesSnapshot = Drives.OrderBy(o => o.Text).ToList(); + var drivesSection = MainPage.SideBarItems.FirstOrDefault(x => x is HeaderTextItem && x.Text == "SidebarDrives".GetLocalized()); - if (drivesSection != null && Drives.Count == 0) + if (drivesSection != null && drivesSnapshot.Count == 0) { //No drives - remove the header MainPage.SideBarItems.Remove(drivesSection); } - if (drivesSection == null && Drives.Count > 0) + drivesSection = MainPage.SideBarItems.FirstOrDefault(x => x is HeaderTextItem && x.Text == "SidebarDrives".GetLocalized()); + + if (drivesSection == null && drivesSnapshot.Count > 0) { drivesSection = new HeaderTextItem() { @@ -150,8 +152,6 @@ await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPrio MainPage.SideBarItems.Add(drivesSection); } - var sectionStartIndex = MainPage.SideBarItems.IndexOf(drivesSection); - //Remove all existing drives from the sidebar foreach (var item in MainPage.SideBarItems .Where(x => x.ItemType == NavigationControlItemType.Drive) @@ -162,18 +162,21 @@ await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPrio } //Add all drives to the sidebar - var insertAt = sectionStartIndex + 1; - foreach (var drive in Drives) + drivesSection = MainPage.SideBarItems.FirstOrDefault(x => x is HeaderTextItem && x.Text == "SidebarDrives".GetLocalized()); + var insertAt = MainPage.SideBarItems.IndexOf(drivesSection) + 1; + foreach (var drive in drivesSnapshot) { + Logger.Info($"Inserting drive \"{drive.Text}\" at position {insertAt}"); MainPage.SideBarItems.Insert(insertAt, drive); + DrivesWidget.ItemsAdded.Add(drive); insertAt++; - - if (drive.Type != DriveType.VirtualDrive) - { - DrivesWidget.ItemsAdded.Add(drive); - } } } + finally + { + MainPage.sideBarItemsSemaphore.Release(); + Logger.Info("SyncSideBarItemsUI() complete"); + } }); } @@ -308,8 +311,7 @@ private async Task GetDrivesAsync() private DriveType GetDriveType(DriveInfo drive) { - DriveType type = DriveType.Unknown; - + DriveType type; switch (drive.DriveType) { case System.IO.DriveType.CDRom: diff --git a/Files/Helpers/AppServiceConnectionHelper.cs b/Files/Helpers/AppServiceConnectionHelper.cs index a9d654059c1a..64b30492e1e5 100644 --- a/Files/Helpers/AppServiceConnectionHelper.cs +++ b/Files/Helpers/AppServiceConnectionHelper.cs @@ -10,7 +10,36 @@ namespace Files.Helpers { public static class AppServiceConnectionHelper { - public static async Task BuildConnection() + public static Task Instance = BuildConnection(); + + public static event EventHandler> ConnectionChanged; + + static AppServiceConnectionHelper() + { + App.Current.Suspending += OnSuspending; + App.Current.LeavingBackground += OnLeavingBackground; + } + + private static async void OnLeavingBackground(object sender, LeavingBackgroundEventArgs e) + { + if (await Instance == null) + { + // Need to reinitialize AppService when app is resuming + Instance = BuildConnection(); + ConnectionChanged?.Invoke(null, Instance); + } + } + + private async static void OnSuspending(object sender, SuspendingEventArgs e) + { + var deferral = e.SuspendingOperation.GetDeferral(); + (await Instance)?.Dispose(); + Instance = Task.FromResult(null); + ConnectionChanged?.Invoke(null, Instance); + deferral.Complete(); + } + + private static async Task BuildConnection() { var serviceConnection = new AppServiceConnection(); serviceConnection.AppServiceName = "FilesInteropService"; diff --git a/Files/ViewModels/SettingsViewModel.cs b/Files/ViewModels/SettingsViewModel.cs index cf462f736e17..3d83ad82595d 100644 --- a/Files/ViewModels/SettingsViewModel.cs +++ b/Files/ViewModels/SettingsViewModel.cs @@ -17,6 +17,8 @@ using System.Runtime.CompilerServices; using System.Threading.Tasks; using Windows.ApplicationModel; +using Windows.ApplicationModel.AppService; +using Windows.Foundation.Collections; using Windows.Globalization; using Windows.Storage; using Windows.System; @@ -107,8 +109,18 @@ public async void DetectQuickLook() // Detect QuickLook try { - ApplicationData.Current.LocalSettings.Values["Arguments"] = "StartupTasks"; - await FullTrustProcessLauncher.LaunchFullTrustProcessForCurrentAppAsync(); + var connection = await AppServiceConnectionHelper.Instance; + if (connection != null) + { + var (status, response) = await connection.SendMessageWithRetryAsync(new ValueSet() + { + { "Arguments", "DetectQuickLook" } + }, TimeSpan.FromSeconds(10)); + if (status == AppServiceResponseStatus.Success) + { + localSettings.Values["quicklook_enabled"] = response.Message.Get("IsAvailable", false); + } + } } catch (Exception ex) { diff --git a/Files/Views/MainPage.xaml.cs b/Files/Views/MainPage.xaml.cs index 96d7a67cf743..c960256d80ff 100644 --- a/Files/Views/MainPage.xaml.cs +++ b/Files/Views/MainPage.xaml.cs @@ -11,6 +11,7 @@ using System.IO; using System.Linq; using System.Runtime.CompilerServices; +using System.Threading; using System.Threading.Tasks; using Windows.ApplicationModel.Core; using Windows.ApplicationModel.Resources.Core; @@ -19,6 +20,7 @@ using Windows.UI.ViewManagement; using Windows.UI.Xaml; using Windows.UI.Xaml.Controls; +using Windows.UI.Xaml.Data; using Windows.UI.Xaml.Input; using Windows.UI.Xaml.Media; using Windows.UI.Xaml.Navigation; @@ -51,6 +53,7 @@ public TabItem SelectedTabItem public static ObservableCollection AppInstances = new ObservableCollection(); public static ObservableCollection SideBarItems = new ObservableCollection(); + public static SemaphoreSlim sideBarItemsSemaphore = new SemaphoreSlim(1, 1); public MainPage() { diff --git a/Files/Views/ModernShellPage.xaml.cs b/Files/Views/ModernShellPage.xaml.cs index 068806b5c170..cbf141defbf8 100644 --- a/Files/Views/ModernShellPage.xaml.cs +++ b/Files/Views/ModernShellPage.xaml.cs @@ -19,7 +19,6 @@ using System.Runtime.CompilerServices; using System.Threading; using System.Threading.Tasks; -using Windows.ApplicationModel; using Windows.ApplicationModel.AppService; using Windows.ApplicationModel.Core; using Windows.ApplicationModel.DataTransfer; @@ -31,7 +30,6 @@ using Windows.UI.Text; using Windows.UI.Xaml; using Windows.UI.Xaml.Controls; -using Windows.UI.Xaml.Controls.Primitives; using Windows.UI.Xaml.Input; using Windows.UI.Xaml.Media; using Windows.UI.Xaml.Media.Animation; @@ -224,6 +222,8 @@ public ModernShellPage() App.DrivesManager.PropertyChanged += DrivesManager_PropertyChanged; AppSettings.PropertyChanged += AppSettings_PropertyChanged; + + AppServiceConnectionHelper.ConnectionChanged += AppServiceConnectionHelper_ConnectionChanged; } private void AppSettings_PropertyChanged(object sender, PropertyChangedEventArgs e) @@ -906,33 +906,15 @@ private void NotifyPropertyChanged([CallerMemberName] string propertyName = "") private async void Page_Loaded(object sender, RoutedEventArgs e) { - ServiceConnection = await AppServiceConnectionHelper.BuildConnection(); + ServiceConnection = await AppServiceConnectionHelper.Instance; FilesystemViewModel = new ItemViewModel(this); FilesystemViewModel.OnAppServiceConnectionChanged(); InteractionOperations = new Interaction(this); - App.Current.Suspending += Current_Suspending; - App.Current.LeavingBackground += OnLeavingBackground; FilesystemViewModel.WorkingDirectoryModified += ViewModel_WorkingDirectoryModified; OnNavigationParamsChanged(); this.Loaded -= Page_Loaded; } - private async void OnLeavingBackground(object sender, LeavingBackgroundEventArgs e) - { - if (this.ServiceConnection == null) - { - // Need to reinitialize AppService when app is resuming - ServiceConnection = await AppServiceConnectionHelper.BuildConnection(); - FilesystemViewModel?.OnAppServiceConnectionChanged(); - } - } - - private void Current_Suspending(object sender, Windows.ApplicationModel.SuspendingEventArgs e) - { - ServiceConnection?.Dispose(); - ServiceConnection = null; - } - private void ViewModel_WorkingDirectoryModified(object sender, WorkingDirectoryModifiedEventArgs e) { string value = e.Path; @@ -977,10 +959,11 @@ private async void ItemDisplayFrame_Navigated(object sender, NavigationEventArgs NavigationArg = parameters.IsSearchResultPage ? parameters.SearchPathParam : parameters.NavPathParam }; - if(ItemDisplayFrame.CurrentSourcePageType == typeof(YourHome)) + if (ItemDisplayFrame.CurrentSourcePageType == typeof(YourHome)) { UpdatePositioning(true); - } else + } + else { UpdatePositioning(); } @@ -1211,8 +1194,6 @@ public void Dispose() { Window.Current.CoreWindow.PointerPressed -= CoreWindow_PointerPressed; SystemNavigationManager.GetForCurrentView().BackRequested -= ModernShellPage_BackRequested; - App.Current.Suspending -= Current_Suspending; - App.Current.LeavingBackground -= OnLeavingBackground; App.DrivesManager.PropertyChanged -= DrivesManager_PropertyChanged; AppSettings.PropertyChanged -= AppSettings_PropertyChanged; NavigationToolbar.EditModeEnabled -= NavigationToolbar_EditModeEnabled; @@ -1251,9 +1232,13 @@ public void Dispose() FilesystemViewModel.WorkingDirectoryModified -= ViewModel_WorkingDirectoryModified; FilesystemViewModel.Dispose(); } + AppServiceConnectionHelper.ConnectionChanged -= AppServiceConnectionHelper_ConnectionChanged; + } - ServiceConnection?.Dispose(); - ServiceConnection = null; + private async void AppServiceConnectionHelper_ConnectionChanged(object sender, Task e) + { + ServiceConnection = await e; + FilesystemViewModel.OnAppServiceConnectionChanged(); } private void SidebarControl_Loaded(object sender, RoutedEventArgs e) @@ -1326,7 +1311,7 @@ private void RootGrid_SizeChanged(object sender, SizeChangedEventArgs e) /// /// Call this function to update the positioning of the preview pane. - /// This is a workaround as the VisualStateManager causes problems. + /// This is a workaround as the VisualStateManager causes problems. /// private void UpdatePositioning(bool IsHome = false) { @@ -1334,7 +1319,7 @@ private void UpdatePositioning(bool IsHome = false) { PreviewPaneRow.Height = new GridLength(0); PreviewPaneColumn.Width = new GridLength(0); - if(PreviewPaneGridSplitter != null) + if (PreviewPaneGridSplitter != null) { PreviewPaneGridSplitter.Visibility = Visibility.Collapsed; } From 19b04465512a8f4c500c1ff0a9c1f4bad5ba31bd Mon Sep 17 00:00:00 2001 From: Andy Doyle Date: Fri, 29 Jan 2021 20:50:23 +0000 Subject: [PATCH 03/15] Remove SharePoint file that isn't needed in this PR --- .../OneDriveSharePointCloudProvider.cs | 43 ------------------- 1 file changed, 43 deletions(-) delete mode 100644 Files/Filesystem/Cloud/Providers/OneDriveSharePointCloudProvider.cs diff --git a/Files/Filesystem/Cloud/Providers/OneDriveSharePointCloudProvider.cs b/Files/Filesystem/Cloud/Providers/OneDriveSharePointCloudProvider.cs deleted file mode 100644 index 3525922b7c8c..000000000000 --- a/Files/Filesystem/Cloud/Providers/OneDriveSharePointCloudProvider.cs +++ /dev/null @@ -1,43 +0,0 @@ -using Files.Enums; -using Files.Helpers; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; -using Windows.ApplicationModel.AppService; -using Windows.Foundation.Collections; - -namespace Files.Filesystem.Cloud.Providers -{ - public class OneDriveSharePointCloudProvider : ICloudProviderDetector - { - public async Task DetectAsync(List cloudProviders) - { - try - { - using var connection = await AppServiceConnectionHelper.BuildConnection(); - var (status, response) = await connection.SendMessageWithRetryAsync(new ValueSet() - { - { "Arguments", "GetSharePointSyncLocationsFromOneDrive" } - }, TimeSpan.FromSeconds(10)); - if (status == AppServiceResponseStatus.Success) - { - foreach (var key in response.Message.Keys - .OrderBy(o => o)) - { - cloudProviders.Add(new CloudProvider() - { - ID = CloudProviders.OneDrive, - Name = key, - SyncFolder = (string)response.Message[key] - }); - } - } - } - catch - { - // Not detected - } - } - } -} \ No newline at end of file From e412893d84a4adbca7a0bfc44b5620b928c257c0 Mon Sep 17 00:00:00 2001 From: Andy Doyle Date: Fri, 29 Jan 2021 20:54:17 +0000 Subject: [PATCH 04/15] Fix CodeFactor issues --- Files/DataModels/SidebarPinnedModel.cs | 3 --- Files/Filesystem/CloudDrivesManager.cs | 1 - 2 files changed, 4 deletions(-) diff --git a/Files/DataModels/SidebarPinnedModel.cs b/Files/DataModels/SidebarPinnedModel.cs index 819246e7eb30..6f30714f4506 100644 --- a/Files/DataModels/SidebarPinnedModel.cs +++ b/Files/DataModels/SidebarPinnedModel.cs @@ -215,7 +215,6 @@ await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPrio Debug.WriteLine($"Pinned item was invalid and will be removed from the file lines list soon: {res.ErrorCode}"); RemoveItem(path); } - } finally { @@ -223,8 +222,6 @@ await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPrio Logger.Info("AddItemToSidebarAsync(string) complete"); } }); - - } /// diff --git a/Files/Filesystem/CloudDrivesManager.cs b/Files/Filesystem/CloudDrivesManager.cs index d658b4fa2096..6937bffee3df 100644 --- a/Files/Filesystem/CloudDrivesManager.cs +++ b/Files/Filesystem/CloudDrivesManager.cs @@ -144,7 +144,6 @@ await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPrio MainPage.SideBarItems.Insert(insertAt, drive); insertAt++; } - } finally { From 9c4c8cc981c35329656b54d392f0022c0a221906 Mon Sep 17 00:00:00 2001 From: Andy Doyle Date: Fri, 29 Jan 2021 21:12:50 +0000 Subject: [PATCH 05/15] Remove SharePoint file that isn't needed in this PR --- Files/Files.csproj | 1 - 1 file changed, 1 deletion(-) diff --git a/Files/Files.csproj b/Files/Files.csproj index 9eec3396f3f2..a8e07f60eb01 100644 --- a/Files/Files.csproj +++ b/Files/Files.csproj @@ -179,7 +179,6 @@ - From 0469ec82d24893e537e3f4a52b84eda5d67a9dfc Mon Sep 17 00:00:00 2001 From: Andy Doyle Date: Sun, 7 Feb 2021 12:31:49 +0000 Subject: [PATCH 06/15] Resolve feedback from PR --- Files/DataModels/SidebarPinnedModel.cs | 4 ++-- Files/Filesystem/CloudDrivesManager.cs | 4 ++-- Files/Filesystem/Drives.cs | 15 ++------------- Files/Views/MainPage.xaml.cs | 2 +- 4 files changed, 7 insertions(+), 18 deletions(-) diff --git a/Files/DataModels/SidebarPinnedModel.cs b/Files/DataModels/SidebarPinnedModel.cs index 6f30714f4506..5e1027e7e950 100644 --- a/Files/DataModels/SidebarPinnedModel.cs +++ b/Files/DataModels/SidebarPinnedModel.cs @@ -187,7 +187,7 @@ await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPrio { Logger.Info("AddItemToSidebarAsync(string)"); - await MainPage.sideBarItemsSemaphore.WaitAsync(); + await MainPage.SideBarItemsSemaphore.WaitAsync(); try { var item = await FilesystemTasks.Wrap(() => DrivesManager.GetRootFromPathAsync(path)); @@ -218,7 +218,7 @@ await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPrio } finally { - MainPage.sideBarItemsSemaphore.Release(); + MainPage.SideBarItemsSemaphore.Release(); Logger.Info("AddItemToSidebarAsync(string) complete"); } }); diff --git a/Files/Filesystem/CloudDrivesManager.cs b/Files/Filesystem/CloudDrivesManager.cs index 6937bffee3df..1be828498136 100644 --- a/Files/Filesystem/CloudDrivesManager.cs +++ b/Files/Filesystem/CloudDrivesManager.cs @@ -91,7 +91,7 @@ await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPrio { Logger.Info("SyncSideBarItemsUI()"); - await MainPage.sideBarItemsSemaphore.WaitAsync(); + await MainPage.SideBarItemsSemaphore.WaitAsync(); try { var drivesSnapshot = Drives.OrderBy(o => o.Text).ToList(); @@ -147,7 +147,7 @@ await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPrio } finally { - MainPage.sideBarItemsSemaphore.Release(); + MainPage.SideBarItemsSemaphore.Release(); Logger.Info("SyncSideBarItemsUI() complete"); } }); diff --git a/Files/Filesystem/Drives.cs b/Files/Filesystem/Drives.cs index 033019ccbce2..2f6d9295df5c 100644 --- a/Files/Filesystem/Drives.cs +++ b/Files/Filesystem/Drives.cs @@ -99,7 +99,6 @@ private async void DeviceWatcher_EnumerationCompleted(DeviceWatcher sender, obje private async Task RefreshUI() { - Logger.Info("RefreshUI()"); try { await SyncSideBarItemsUI(); @@ -110,24 +109,19 @@ private async Task RefreshUI() // Defer because UI-thread is not ready yet (and DriveItem requires it?) CoreApplication.MainView.Activated += RefreshUI; } - Logger.Info("RefreshUI() complete"); } private async void RefreshUI(CoreApplicationView sender, Windows.ApplicationModel.Activation.IActivatedEventArgs args) { - Logger.Info("RefreshUI(CoreApplicationView, IActivatedEventArgs)"); await SyncSideBarItemsUI(); CoreApplication.MainView.Activated -= RefreshUI; - Logger.Info("RefreshUI(CoreApplicationView, IActivatedEventArgs) complete"); } private async Task SyncSideBarItemsUI() { await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, async () => { - Logger.Info("SyncSideBarItemsUI()"); - - await MainPage.sideBarItemsSemaphore.WaitAsync(); + await MainPage.SideBarItemsSemaphore.WaitAsync(); try { var drivesSnapshot = Drives.OrderBy(o => o.Text).ToList(); @@ -166,7 +160,6 @@ await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPrio var insertAt = MainPage.SideBarItems.IndexOf(drivesSection) + 1; foreach (var drive in drivesSnapshot) { - Logger.Info($"Inserting drive \"{drive.Text}\" at position {insertAt}"); MainPage.SideBarItems.Insert(insertAt, drive); DrivesWidget.ItemsAdded.Add(drive); insertAt++; @@ -174,8 +167,7 @@ await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPrio } finally { - MainPage.sideBarItemsSemaphore.Release(); - Logger.Info("SyncSideBarItemsUI() complete"); + MainPage.SideBarItemsSemaphore.Release(); } }); } @@ -224,9 +216,6 @@ ex is UnauthorizedAccessException } var driveItem = new DriveItem(root, deviceId, type); - - Logger.Info($"Drive added: {driveItem.Path}, {driveItem.Type}"); - drivesList.Add(driveItem); } // Update the collection on the ui-thread. diff --git a/Files/Views/MainPage.xaml.cs b/Files/Views/MainPage.xaml.cs index c960256d80ff..6e70bc5d0660 100644 --- a/Files/Views/MainPage.xaml.cs +++ b/Files/Views/MainPage.xaml.cs @@ -53,7 +53,7 @@ public TabItem SelectedTabItem public static ObservableCollection AppInstances = new ObservableCollection(); public static ObservableCollection SideBarItems = new ObservableCollection(); - public static SemaphoreSlim sideBarItemsSemaphore = new SemaphoreSlim(1, 1); + public static SemaphoreSlim SideBarItemsSemaphore = new SemaphoreSlim(1, 1); public MainPage() { From 5476e5bc10b5a39a199f33d112ce402042af6959 Mon Sep 17 00:00:00 2001 From: Marco Gavelli Date: Sun, 7 Feb 2021 15:49:19 +0100 Subject: [PATCH 07/15] Fixed merge conflicts, removed some logs --- Files/DataModels/SidebarPinnedModel.cs | 6 ------ Files/Filesystem/CloudDrivesManager.cs | 11 ----------- Files/Filesystem/Drives.cs | 3 +++ 3 files changed, 3 insertions(+), 17 deletions(-) diff --git a/Files/DataModels/SidebarPinnedModel.cs b/Files/DataModels/SidebarPinnedModel.cs index 3cb151675624..01be1fd383df 100644 --- a/Files/DataModels/SidebarPinnedModel.cs +++ b/Files/DataModels/SidebarPinnedModel.cs @@ -20,9 +20,6 @@ public class SidebarPinnedModel { private SidebarPinnedController controller; - [JsonIgnore] - private readonly Logger Logger = LogManager.GetCurrentClassLogger(); - [JsonIgnore] public SettingsViewModel AppSettings => App.AppSettings; @@ -193,8 +190,6 @@ public async Task AddItemToSidebarAsync(string path) { await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, async () => { - Logger.Info("AddItemToSidebarAsync(string)"); - await MainPage.SideBarItemsSemaphore.WaitAsync(); try { @@ -227,7 +222,6 @@ await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPrio finally { MainPage.SideBarItemsSemaphore.Release(); - Logger.Info("AddItemToSidebarAsync(string) complete"); } }); } diff --git a/Files/Filesystem/CloudDrivesManager.cs b/Files/Filesystem/CloudDrivesManager.cs index 1be828498136..7bd615ae3c53 100644 --- a/Files/Filesystem/CloudDrivesManager.cs +++ b/Files/Filesystem/CloudDrivesManager.cs @@ -36,9 +36,7 @@ public CloudDrivesManager() public async Task EnumerateDrivesAsync() { var cloudProviderController = new CloudProviderController(); - Logger.Info("Detecting installed cloud drives"); var cloudProviders = await cloudProviderController.DetectInstalledCloudProvidersAsync(); - Logger.Info($"Detected {cloudProviders.Count} cloud drives"); foreach (var provider in cloudProviders) { @@ -62,7 +60,6 @@ public async Task EnumerateDrivesAsync() private async Task RefreshUI() { - Logger.Info("RefreshUI()"); try { await SyncSideBarItemsUI(); @@ -74,23 +71,18 @@ private async Task RefreshUI() // Defer because UI-thread is not ready yet (and DriveItem requires it?) CoreApplication.MainView.Activated += RefreshUI; } - Logger.Info("RefreshUI() complete"); } private async void RefreshUI(CoreApplicationView sender, Windows.ApplicationModel.Activation.IActivatedEventArgs args) { - Logger.Info("RefreshUI(CoreApplicationView, IActivatedEventArgs)"); CoreApplication.MainView.Activated -= RefreshUI; await SyncSideBarItemsUI(); - Logger.Info("RefreshUI(CoreApplicationView, IActivatedEventArgs) complete"); } private async Task SyncSideBarItemsUI() { await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, async () => { - Logger.Info("SyncSideBarItemsUI()"); - await MainPage.SideBarItemsSemaphore.WaitAsync(); try { @@ -132,7 +124,6 @@ await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPrio .Where(x => x.ItemType == NavigationControlItemType.CloudDrive) .ToList()) { - Logger.Info($"Removing cloud drive \"{item.Text}\""); MainPage.SideBarItems.Remove(item); } @@ -140,7 +131,6 @@ await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPrio var insertAt = MainPage.SideBarItems.IndexOf(drivesSection) + 1; foreach (var drive in drivesSnapshot) { - Logger.Info($"Inserting cloud drive \"{drive.Text}\" at position {insertAt}"); MainPage.SideBarItems.Insert(insertAt, drive); insertAt++; } @@ -148,7 +138,6 @@ await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPrio finally { MainPage.SideBarItemsSemaphore.Release(); - Logger.Info("SyncSideBarItemsUI() complete"); } }); } diff --git a/Files/Filesystem/Drives.cs b/Files/Filesystem/Drives.cs index 2f6d9295df5c..e8acb0135514 100644 --- a/Files/Filesystem/Drives.cs +++ b/Files/Filesystem/Drives.cs @@ -216,6 +216,9 @@ ex is UnauthorizedAccessException } var driveItem = new DriveItem(root, deviceId, type); + + Logger.Info($"Drive added: {driveItem.Path}, {driveItem.Type}"); + drivesList.Add(driveItem); } // Update the collection on the ui-thread. From 116b9611d473934fbe2f9ac3db5b64d341ef8290 Mon Sep 17 00:00:00 2001 From: Marco Gavelli Date: Sun, 7 Feb 2021 16:01:20 +0100 Subject: [PATCH 08/15] Fix crash when minimizing --- Files/Views/ModernShellPage.xaml.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Files/Views/ModernShellPage.xaml.cs b/Files/Views/ModernShellPage.xaml.cs index 7f6b30fbb16a..7db95423c0ea 100644 --- a/Files/Views/ModernShellPage.xaml.cs +++ b/Files/Views/ModernShellPage.xaml.cs @@ -1241,7 +1241,10 @@ public void Dispose() private async void AppServiceConnectionHelper_ConnectionChanged(object sender, Task e) { ServiceConnection = await e; - FilesystemViewModel.OnAppServiceConnectionChanged(); + if (FilesystemViewModel != null) + { + FilesystemViewModel.OnAppServiceConnectionChanged(); + } } private void SidebarControl_Loaded(object sender, RoutedEventArgs e) From 13fd9945890021652412bc3a186c548da51d3cca Mon Sep 17 00:00:00 2001 From: Andy Doyle Date: Sun, 7 Feb 2021 15:23:43 +0000 Subject: [PATCH 09/15] Remove drive list sorting and leave to OS --- Files/Filesystem/Drives.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Files/Filesystem/Drives.cs b/Files/Filesystem/Drives.cs index e8acb0135514..4db91590625c 100644 --- a/Files/Filesystem/Drives.cs +++ b/Files/Filesystem/Drives.cs @@ -124,7 +124,7 @@ await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPrio await MainPage.SideBarItemsSemaphore.WaitAsync(); try { - var drivesSnapshot = Drives.OrderBy(o => o.Text).ToList(); + var drivesSnapshot = Drives.ToList(); var drivesSection = MainPage.SideBarItems.FirstOrDefault(x => x is HeaderTextItem && x.Text == "SidebarDrives".GetLocalized()); From 5eceb15df6c7a78e25bb654d157637cb2d5c02cf Mon Sep 17 00:00:00 2001 From: Marco Gavelli Date: Sun, 7 Feb 2021 16:42:08 +0100 Subject: [PATCH 10/15] Call collection.reset --- Files/DataModels/SidebarPinnedModel.cs | 66 +++++++++++++------------- Files/Filesystem/CloudDrivesManager.cs | 1 + Files/Filesystem/Drives.cs | 1 + Files/Views/MainPage.xaml.cs | 2 +- 4 files changed, 35 insertions(+), 35 deletions(-) diff --git a/Files/DataModels/SidebarPinnedModel.cs b/Files/DataModels/SidebarPinnedModel.cs index 01be1fd383df..d335cef946b4 100644 --- a/Files/DataModels/SidebarPinnedModel.cs +++ b/Files/DataModels/SidebarPinnedModel.cs @@ -188,42 +188,31 @@ public int IndexOfItem(INavigationControlItem locationItem, ListTask public async Task AddItemToSidebarAsync(string path) { - await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, async () => + var item = await FilesystemTasks.Wrap(() => DrivesManager.GetRootFromPathAsync(path)); + var res = await FilesystemTasks.Wrap(() => StorageFileExtensions.DangerousGetFolderFromPathAsync(path, item)); + if (res) { - await MainPage.SideBarItemsSemaphore.WaitAsync(); - try + int insertIndex = MainPage.SideBarItems.IndexOf(MainPage.SideBarItems.Last(x => x.ItemType == NavigationControlItemType.Location + && !x.Path.Equals(App.AppSettings.RecycleBinPath))) + 1; + var locationItem = new LocationItem { - var item = await FilesystemTasks.Wrap(() => DrivesManager.GetRootFromPathAsync(path)); - var res = await FilesystemTasks.Wrap(() => StorageFileExtensions.DangerousGetFolderFromPathAsync(path, item)); - if (res) - { - int insertIndex = MainPage.SideBarItems.IndexOf(MainPage.SideBarItems.Last(x => x.ItemType == NavigationControlItemType.Location - && !x.Path.Equals(App.AppSettings.RecycleBinPath))) + 1; - var locationItem = new LocationItem - { - Font = App.Current.Resources["FluentUIGlyphs"] as FontFamily, - Path = path, - Glyph = GetItemIcon(path), - IsDefaultLocation = false, - Text = res.Result?.DisplayName ?? Path.GetFileName(path.TrimEnd('\\')) - }; + Font = App.Current.Resources["FluentUIGlyphs"] as FontFamily, + Path = path, + Glyph = GetItemIcon(path), + IsDefaultLocation = false, + Text = res.Result?.DisplayName ?? Path.GetFileName(path.TrimEnd('\\')) + }; - if (!MainPage.SideBarItems.Contains(locationItem)) - { - MainPage.SideBarItems.Insert(insertIndex, locationItem); - } - } - else - { - Debug.WriteLine($"Pinned item was invalid and will be removed from the file lines list soon: {res.ErrorCode}"); - RemoveItem(path); - } - } - finally + if (!MainPage.SideBarItems.Contains(locationItem)) { - MainPage.SideBarItemsSemaphore.Release(); + MainPage.SideBarItems.Insert(insertIndex, locationItem); } - }); + } + else + { + Debug.WriteLine($"Pinned item was invalid and will be removed from the file lines list soon: {res.ErrorCode}"); + RemoveItem(path); + } } /// @@ -231,10 +220,19 @@ await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPrio /// public async Task AddAllItemsToSidebar() { - for (int i = 0; i < Items.Count(); i++) + await MainPage.SideBarItemsSemaphore.WaitAsync(); + try + { + for (int i = 0; i < Items.Count(); i++) + { + string path = Items[i]; + await AddItemToSidebarAsync(path); + } + MainPage.SideBarItems.EndBulkOperation(); + } + finally { - string path = Items[i]; - await AddItemToSidebarAsync(path); + MainPage.SideBarItemsSemaphore.Release(); } } diff --git a/Files/Filesystem/CloudDrivesManager.cs b/Files/Filesystem/CloudDrivesManager.cs index 7bd615ae3c53..e1ea55711bd2 100644 --- a/Files/Filesystem/CloudDrivesManager.cs +++ b/Files/Filesystem/CloudDrivesManager.cs @@ -134,6 +134,7 @@ await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPrio MainPage.SideBarItems.Insert(insertAt, drive); insertAt++; } + MainPage.SideBarItems.EndBulkOperation(); } finally { diff --git a/Files/Filesystem/Drives.cs b/Files/Filesystem/Drives.cs index 4db91590625c..7f519fa0967f 100644 --- a/Files/Filesystem/Drives.cs +++ b/Files/Filesystem/Drives.cs @@ -164,6 +164,7 @@ await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPrio DrivesWidget.ItemsAdded.Add(drive); insertAt++; } + MainPage.SideBarItems.EndBulkOperation(); } finally { diff --git a/Files/Views/MainPage.xaml.cs b/Files/Views/MainPage.xaml.cs index 6e70bc5d0660..43338f9e5caf 100644 --- a/Files/Views/MainPage.xaml.cs +++ b/Files/Views/MainPage.xaml.cs @@ -52,7 +52,7 @@ public TabItem SelectedTabItem } public static ObservableCollection AppInstances = new ObservableCollection(); - public static ObservableCollection SideBarItems = new ObservableCollection(); + public static BulkConcurrentObservableCollection SideBarItems = new BulkConcurrentObservableCollection(); public static SemaphoreSlim SideBarItemsSemaphore = new SemaphoreSlim(1, 1); public MainPage() From 00409d59ef0c1b663baf432de0d4efa0386bd154 Mon Sep 17 00:00:00 2001 From: Marco Gavelli Date: Sun, 7 Feb 2021 17:56:08 +0100 Subject: [PATCH 11/15] Switch to simple observablecollection --- Files/DataModels/SidebarPinnedModel.cs | 2 +- Files/Filesystem/CloudDrivesManager.cs | 2 +- Files/Filesystem/Drives.cs | 2 +- Files/Helpers/BulkConcurrentObservableCollection.cs | 9 +++++++++ Files/Views/MainPage.xaml.cs | 2 +- 5 files changed, 13 insertions(+), 4 deletions(-) diff --git a/Files/DataModels/SidebarPinnedModel.cs b/Files/DataModels/SidebarPinnedModel.cs index d335cef946b4..1d8995cf2622 100644 --- a/Files/DataModels/SidebarPinnedModel.cs +++ b/Files/DataModels/SidebarPinnedModel.cs @@ -228,7 +228,7 @@ public async Task AddAllItemsToSidebar() string path = Items[i]; await AddItemToSidebarAsync(path); } - MainPage.SideBarItems.EndBulkOperation(); + MainPage.SideBarItems.ResetCollection(); } finally { diff --git a/Files/Filesystem/CloudDrivesManager.cs b/Files/Filesystem/CloudDrivesManager.cs index e1ea55711bd2..9991534dedf4 100644 --- a/Files/Filesystem/CloudDrivesManager.cs +++ b/Files/Filesystem/CloudDrivesManager.cs @@ -134,7 +134,7 @@ await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPrio MainPage.SideBarItems.Insert(insertAt, drive); insertAt++; } - MainPage.SideBarItems.EndBulkOperation(); + MainPage.SideBarItems.ResetCollection(); } finally { diff --git a/Files/Filesystem/Drives.cs b/Files/Filesystem/Drives.cs index 7f519fa0967f..9016937c1064 100644 --- a/Files/Filesystem/Drives.cs +++ b/Files/Filesystem/Drives.cs @@ -164,7 +164,7 @@ await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPrio DrivesWidget.ItemsAdded.Add(drive); insertAt++; } - MainPage.SideBarItems.EndBulkOperation(); + MainPage.SideBarItems.ResetCollection(); } finally { diff --git a/Files/Helpers/BulkConcurrentObservableCollection.cs b/Files/Helpers/BulkConcurrentObservableCollection.cs index 5b6ea63aabb8..fc1a892af83d 100644 --- a/Files/Helpers/BulkConcurrentObservableCollection.cs +++ b/Files/Helpers/BulkConcurrentObservableCollection.cs @@ -1,6 +1,7 @@ using System; using System.Collections; using System.Collections.Generic; +using System.Collections.ObjectModel; using System.Collections.Specialized; using System.ComponentModel; using System.Linq; @@ -8,6 +9,14 @@ namespace Files.Helpers { + public class ResettableObservableCollection : ObservableCollection + { + public void ResetCollection() + { + base.OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset)); + } + } + public class BulkConcurrentObservableCollection : INotifyCollectionChanged, INotifyPropertyChanged, ICollection, IList, ICollection, IList { private bool isBulkOperationStarted; diff --git a/Files/Views/MainPage.xaml.cs b/Files/Views/MainPage.xaml.cs index 43338f9e5caf..e97aab2ed7da 100644 --- a/Files/Views/MainPage.xaml.cs +++ b/Files/Views/MainPage.xaml.cs @@ -52,7 +52,7 @@ public TabItem SelectedTabItem } public static ObservableCollection AppInstances = new ObservableCollection(); - public static BulkConcurrentObservableCollection SideBarItems = new BulkConcurrentObservableCollection(); + public static ResettableObservableCollection SideBarItems = new ResettableObservableCollection(); public static SemaphoreSlim SideBarItemsSemaphore = new SemaphoreSlim(1, 1); public MainPage() From 400d279158b4c064f86487be2fca63d7eaaa789d Mon Sep 17 00:00:00 2001 From: Steven He Date: Mon, 8 Feb 2021 11:06:14 +0800 Subject: [PATCH 12/15] fix bugs in BulkConcurrentCollection --- Files/Files.csproj | 1 + .../BulkConcurrentObservableCollection.cs | 32 +- Files/Helpers/CollectionDebugView.cs | 27 + Files/Strings/hu-HU/Resources.resw | 464 +++++++++--------- 4 files changed, 290 insertions(+), 234 deletions(-) create mode 100644 Files/Helpers/CollectionDebugView.cs diff --git a/Files/Files.csproj b/Files/Files.csproj index 74b4510bee45..7349616bb7e2 100644 --- a/Files/Files.csproj +++ b/Files/Files.csproj @@ -198,6 +198,7 @@ RestartDialog.xaml + diff --git a/Files/Helpers/BulkConcurrentObservableCollection.cs b/Files/Helpers/BulkConcurrentObservableCollection.cs index fc1a892af83d..a0e3485aa780 100644 --- a/Files/Helpers/BulkConcurrentObservableCollection.cs +++ b/Files/Helpers/BulkConcurrentObservableCollection.cs @@ -4,19 +4,13 @@ using System.Collections.ObjectModel; using System.Collections.Specialized; using System.ComponentModel; +using System.Diagnostics; using System.Linq; -using System.Threading; namespace Files.Helpers { - public class ResettableObservableCollection : ObservableCollection - { - public void ResetCollection() - { - base.OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset)); - } - } - + [DebuggerTypeProxy(typeof(CollectionDebugView<>))] + [DebuggerDisplay("Count = {Count}")] public class BulkConcurrentObservableCollection : INotifyCollectionChanged, INotifyPropertyChanged, ICollection, IList, ICollection, IList { private bool isBulkOperationStarted; @@ -70,6 +64,7 @@ protected void OnCollectionChanged(NotifyCollectionChangedEventArgs e) { CollectionChanged?.Invoke(this, e); PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Count))); + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Item[]")); } } @@ -77,6 +72,8 @@ public void EndBulkOperation() { isBulkOperationStarted = false; OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset)); + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Count))); + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Item[]")); } public void Add(T item) @@ -113,12 +110,19 @@ public bool Remove(T item) { bool result; + var index = collection.IndexOf(item); + + if (index == -1) + { + return true; + } + lock (syncRoot) { result = collection.Remove(item); } - OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, item)); + OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, item, index)); return result; } @@ -144,7 +148,7 @@ public void Insert(int index, T item) collection.Insert(index, item); } - OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, item)); + OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, item, index)); } public void RemoveAt(int index) @@ -156,7 +160,7 @@ public void RemoveAt(int index) collection.RemoveAt(index); } - OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, item)); + OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, item, index)); } public void AddRange(IEnumerable items) @@ -203,7 +207,7 @@ public void RemoveRange(int index, int count) collection.RemoveRange(index, count); } - OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, items)); + OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, items, index)); } public void ReplaceRange(int index, IEnumerable items) @@ -224,7 +228,7 @@ public void ReplaceRange(int index, IEnumerable items) collection.RemoveRange(index + count, count); } - OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Replace, newItems, oldItems)); + OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Replace, newItems, oldItems, index)); } int IList.Add(object value) diff --git a/Files/Helpers/CollectionDebugView.cs b/Files/Helpers/CollectionDebugView.cs new file mode 100644 index 000000000000..2c0cca4f8af1 --- /dev/null +++ b/Files/Helpers/CollectionDebugView.cs @@ -0,0 +1,27 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; + +namespace Files.Helpers +{ + internal sealed class CollectionDebugView + { + private readonly ICollection _collection; + + public CollectionDebugView(ICollection collection) + { + _collection = collection ?? throw new ArgumentNullException(nameof(collection)); + } + + [DebuggerBrowsable(DebuggerBrowsableState.RootHidden)] + public T[] Items + { + get + { + var items = new T[_collection.Count]; + _collection.CopyTo(items, 0); + return items; + } + } + } +} diff --git a/Files/Strings/hu-HU/Resources.resw b/Files/Strings/hu-HU/Resources.resw index 196821fed8df..baf24682fcc6 100644 --- a/Files/Strings/hu-HU/Resources.resw +++ b/Files/Strings/hu-HU/Resources.resw @@ -22,7 +22,7 @@ Törlés - Ideiglenes törlés + Végleges törlés Megnyitás új lapon @@ -31,22 +31,22 @@ Megnyitás új ablakban - Új Lap + Új lap - Új Ablak + Új ablak Mappa - Bitmap Kép + Bitmap kép - Szöveges Dokumentum + Szöveges dokumentum - Útvonal másolása + Elérési út másolása Beillesztés @@ -73,7 +73,7 @@ Létrehozva: - Fájlnév + Név Elérési út: @@ -82,25 +82,25 @@ Méret: - Az az a művelet nem elvégezhető + Ez a művelet nem hajtható végre - Az érkezési mappa + A célmappa - almappája az eredeti mappának + almappája a forrásmappának - Tovább + Kihagyás Mégse - Elem típusa: + Típus: - Mind kijelölése + Összes kijelölése Kijelölés megfordítása @@ -112,10 +112,10 @@ Részletek - Módosítás dátuma: + Módosítva: - Megnyitva: + Hozzáférés: Tulajdonos: @@ -130,7 +130,7 @@ Keresés - Előzőleg megtekintett fájlok helye + Itt fognak megjelenni a korábban megnyitott fájlok Fájlt tartalmazó mappa megnyitása @@ -139,7 +139,7 @@ Elem eltávolítása - Legutóbb megnyitott + Előzmények Files @@ -151,16 +151,16 @@ Visszajelzés küldése a fejlesztőknek - Harmadik személytől származó licenc-ek + Harmadik fél licencei - Rólunk + Névjegy Akril oldalsáv - Dátum formátuma + Dátumformátum Téma @@ -169,46 +169,46 @@ Megjelenés - Kiterjesztés mutatása ismert fájlformátumoknál + Kiterjesztés megjelenítése ismert fájltípusoknál - Fájlok és Mappák + Fájlok és mappák - Kísérleti + Kísérleti beállítások Beállítások - Rólunk + Névjegy Megjelenés - Kísérleti + Kísérleti beállítások - Fájlok és Mappák + Fájlok és mappák Induláskor - Preferencia + Működés VIGYÁZAT: Kísérleti beállítások! - Folytassa ahol abbahagyta + Folytassa ott, ahol bezárta a programot Új lap megnyitása - Megadott oldal(ak) megnyitása + Megadott mappák megnyitása Induláskor @@ -217,7 +217,7 @@ Tulajdonos mutatása a tulajdonságoknál - Preferencia + Működés Asztal @@ -229,7 +229,7 @@ Letöltések - Home + Kezdőoldal Zene @@ -238,7 +238,7 @@ Képek - Levétel az oldalsávról + Eltávolítás az oldalsávról Videók @@ -274,7 +274,7 @@ Megnyitás terminálban... - MD5Hash: + MD5 hash: Új @@ -328,10 +328,10 @@ Üdv a Files-ban! - Engedély Biztosítása + Engedély megadása - Kezdésként, engedély kell adnia a fájljai megjelenítéséhez. Ez meg fogja nyitni a Beállításokat ahol engedélyezheti. Amint befelyezte a lépést zárja be és nyissa meg újra a Files-t. + Kezdésként, engedélyt kell adnia a fájljai megjelenítéséhez. Ez meg fogja nyitni a Gépházat ahol ezt elvégezheti. Az engedély megadása és a Gépház bezárása után nyissa meg újra a Files-t. Fájlmappa @@ -340,13 +340,13 @@ Fájl - Írja be a fájl új nevét + Adja meg az elem új nevét - Írja be az új fájl nevét + Adja meg az elem új nevét - Név beállítása + Átnevezés Mégse @@ -370,10 +370,10 @@ Rendszer - Új Mappa + Új mappa - Üres mappa. + Ez a mappa üres. Vissza (Alt + Bal nyíl) @@ -391,10 +391,10 @@ Keresés - Több lehetpség + További lehetőségek - Tulajdonság + Tulajdonságok Attribútumok: @@ -406,19 +406,19 @@ Példa beállítások - Fájl ezzel a névvel már létezik ebben a mappában. + Ezzel a névvel már létezik elem ebben a mappában. - Új név készítése + Átnevezés - Fájl lecserélése + Felülírás/összefésülés - A fájl már létezik + Az elem már létezik - Beállítás zárolt háttérképként + Beállítás zárolási képernyő háttérként Nagy ikonok @@ -436,40 +436,40 @@ OK - Nem tudtuk törölni a fájlt + Nem sikerült törölni ezt az elemet - Hozzáférés Megtagadva + Hozzáférés megtagadva - Helyezze be a meghajtót a fájlhoz való hozzáfáráshez. + Helyezze be a meghajtót a fájlhoz való hozzáféréshez. Meghajtó leválasztva - Az elérni próbált fájl törölt, vagy át lett helyezve. + A fájl, amit próbál megnyitni, már nem található ezen a helyen. - A Fájl nem található + A fájl nem található - A fájl amit próbál megnézni, törölt, vagy át lett helyezve. + A fájl, amelynek az előnézetét próbálja betölteni, már nem található ezen a helyen. - A fájl amit próbál elérni, törölt, vagy át lett helyezve. + A mappa, amit próbál megnyitni, már nem található ezen a helyen. - Ön törölte a mappát? + Ön törölte ezt a mappát? - A fájl amelyet törölné jelenleg használatban van. + A törölni kívánt fájl jelenleg használatban van. A fájl használatban van - Próbálja újra + Újra OK @@ -508,22 +508,22 @@ Új lap - A kért művelet nem támogatott + Ez a művelet nem támogatott - {0} szabad a(z) {1}-ból/ből + Szabad hely: {0} / {1} Társítás - A fájlnév nem tartalmazhatja a következő karaktereket: \ / : * ? " < > | + A név nem tartalmazhatja a következő karaktereket: \ / : * ? " < > | OK - A fájlnév nem tartalmazhatja a következő karaktereket: \ / : * ? " < > | + A név nem tartalmazhatja a következő karaktereket: \ / : * ? " < > | Naplózás helyének megnyitása @@ -538,10 +538,10 @@ kijelölt elem - Elem + elem - Elem + elem Fájlok törlése @@ -556,19 +556,19 @@ Mappa kitűzése az oldalsávra - OK + Igen Mégse - Biztosan törölne minden elemet? + Biztosan véglegesen törölni szeretné ezeket az elemeket? Lomtár kiürítése - bit + bájt KB @@ -592,7 +592,7 @@ Futtatás rendszergazdaként - Tudjon meg többet a dátumok formátumáról + Tudjon meg többet a dátumformátumokról Feloldás @@ -601,13 +601,13 @@ Mégse - Írja be a jelszót a meghajtó feloldásához + Adja meg a jelszót a meghajtó feloldásához Jelszó - Ellenőrizze a jalszavat és próbálja újra. + Ellenőrizze a jelszót és próbálja újra. BitLocker hiba @@ -616,19 +616,19 @@ Tartalmaz: - {0:#,##0} Fájl, {1:#,##0} Mappa + {0:#,##0} fájl, {1:#,##0} mappa Futtatás másik felhasználóként - Minden típus {0}-ból/ból + {0} (mindegyik) Különböző típusok - Minden {0}-ból/ből + {0} (mindegyik) Foglalt: @@ -643,10 +643,10 @@ Fájlrendszer: - Legutóbbi + Előzmények - Program Nyelve + Alkalmazás nyelve Lap áthelyezése ide @@ -661,13 +661,13 @@ Oldalak: - Mindig új ablakban nyíljon meg + Új ablakban - Mappa megnyitása új lapon + Új lapon - Elem megnyitásakor a listáról + Elem előzménylistáról megnyitása Rendszer @@ -679,7 +679,7 @@ Egy megjeleníthető elem sem elérhető - Áthelyezés ide {0} + Áthelyezés ide: {0} A forrás- és a célfájlnév azonos. @@ -688,13 +688,13 @@ A forrás- és a célmappa azonos. - Másolás ide {0} + Másolás ide: {0} - Gyorsgomb létrehozása + Parancsikon létrehozása - Fájl tartalmazó mappa megnyitása + Fájlt tartalmazó mappa megnyitása Argumentumok: @@ -718,22 +718,22 @@ Mappa - Web link + Internet parancsikon Általános - Gyorsgomb + Parancsikon - Gyorsgomb + Parancsikon - Internet gyorsgomb + Internet parancsikon - {0} - gyorsgomb + {0} - parancsikon Fájlt tartalmazó mappa megnyitása @@ -745,10 +745,10 @@ Naplózás helyének megnyitása - Files egy problémába ütközött, amire a fejlesztők még nem készültek fel. + A Files egy problémába ütközött, amire a fejlesztők még nem készültek fel. - Valami elromlott! + Valami hiba történt! Hiba jelentése @@ -760,16 +760,16 @@ Akik hozzájárultak a Files-hoz - Verzió Jegyzet + Változások Újdonságok a Files-ban - A hivatkozott elem helytelen vagy elérhetetlen.{0}Hibaüzenet:{0}{1} + A hivatkozott elem érvénytelen vagy nem elérhető.{0}Hibaüzenet:{0}{1} - Helytelen fájl + Érvénytelen elem Verzió: @@ -778,10 +778,10 @@ Nincs mit megosztani... - A kijelölt fájlok meg lesznek osztva + A kijelölt elemek meg lesznek osztva - A kijelölt fájl meg lesz osztva + A kijelölt elem meg lesz osztva {0} megosztása @@ -790,25 +790,25 @@ {0} {1} megosztása - A fájl amit szeretne megnyitni már nem létezik. Ellenőrizze az átnevezendő fájl helyét. + Az elem, amit át szeretne nevezni már nem létezik. - A fájl már nem létezik + Az elem már nem létezik - A megadott fájlnév helytelen. Ellenőrizze és próbálja újra. + A megadott név helytelen. Ellenőrizze és próbálja újra! - Helytelen fájl név + Helytelen név - A fájlnév hossza elérte a maximumot. Ellenőrizze a nevet, és próbálja újra. + A név hosszabb, mint ami maximálisan megengedett. Kérjük válasszon rövidebb nevet! - Túl hosszú fájlnév + Túl hosszú név - Több + Továbbiak Nem @@ -817,7 +817,7 @@ Igen - A Files újraindítása szükséges a nyelv beállításához, szeretné újraindítani? + A Files újraindítása szükséges a nyelv beállítás érvénybe lépéséhez. Szeretné most újraindítani? Támogatás @@ -826,19 +826,19 @@ Támogatás PayPal-on - Nem tudtuk létrehozni a fájlt + Nem sikerült létrehozni a fájlt - Hozzáférés Megtagadva + Hozzáférés megtagadva Mégse - Biztosan szeretné törölni ezt a(z) {0} fájlt? + Biztosan törölni szeretne {0} fájlt? - Bizotsan törölné ezt az fájlt? + Bizotsan törölni szeretné a fájlt? Lap hozzáadása @@ -847,16 +847,16 @@ Lapok megnyitása - Automatikus (Ajánlott) + Automatikus (ajánlott) - A legjobb lehetőség kiválasztása az ablak méretétől függően. Amikor az ablak kicsi, a vízszintes lap lánc egy menüvé alakul navigációs sávban. + A legjobb lehetőség kiválasztása az ablak méretétől függően. Amikor az ablak kicsi, a vízszintes lap sáv egy menüelemmé alakul át. Vízszintes - Menü elrejtése a navigációs sávból, az eredeti vízszintes lap lánc használata. Felhasználóknak akik állandóan követnék az összes lapot. + Menüelem elrejtése, az eredeti vízszintes lap sáv használata. Olyan felhasználóknak, akik szeretik állandóan figyelemmel követni az összes megnyitott lapot. Multitaszking @@ -865,7 +865,7 @@ Függőleges - A vízszintes lap lánc egy menüvé alakul navigációs sávban, azoknak a felhasználóknak tervezve, akik egy letisztult felhasználói felületet szeretnének igény szerint a multitaszkingal. + A vízszintes lap sáv egy menüelemmé alakul át, azoknak a felhasználóknak tervezve, akik egy letisztult felhasználói felületet szeretnének, de a multitaszking lehetőségével. Multitaszking @@ -874,61 +874,61 @@ Beállítás mint - Hely másolása + Elérési út másolása Mégse - Új elem készítése + Új elem létrehozása - Válasszon fájltípust az alábbiak közűl + Válasszon típust az alábbiak közül Mappa - Új mappa készítése + Új mappa létrehozása Elrendezés - Navigálás hátra + Vissza navigálás - Navigálás előre + Előre navigálás Könyvtár frissítése - Vissza egy mappával + Egy szinttel feljebb - Függőleges lap lánc + Függőleges lap lista - Program Nyelve + Alkalmazás nyelve - Parancssor Alkalmazások + Terminál alkalmazások - Parancssor alkalmazások szerkeztése + Terminál alkalmazások módosítása - Parancssor alkalmazások szerkeztése + Terminál alkalmazások módosítása Példa beeállítások - App Nyelve + Alkalmazás nyelve - Parancssor Programok + Terminál alkalmazások Lomtár kitűzése az oldalsávra @@ -937,31 +937,31 @@ Megerősítő üzenet fájlok vagy mappák törlésekor - Parancssor Programok + Terminál alkalmazások - Több lehetőség + További lehetőségek Kijelölési lehetőségek - Állapot központ + Állapotközpont Elemek megnyitása egy kattintással - Ide + Áthelyezés ide Meghajtók - Könyvtárak megjelenítése a fő oldalon + Könyvtárak megjelenítése a kezdőoldalon - Könyvtárak megjelenítése a fő oldalon + Könyvtárak megjelenítése a kezdőoldalon Widgetek @@ -970,16 +970,16 @@ Widgetek - Meghajtók megjelenítése a fő oldalon + Meghajtók megjelenítése a kezdőoldalon - Meghajtók megjelenítése a fő oldalon + Meghajtók megjelenítése a kezdőoldalon - Legutóbb megnyitottak megjelenítése a fő oldalon + Előzmények megjelenítése a kezdőoldalon - Legutóbbi megnyitottak megjelenítése a fő oldalon + Előzmények megjelenítése a kezdőoldalon Fájl @@ -991,7 +991,7 @@ Lomtár elem - Gyorsgomb elem + Parancsikon elem Rejtett fájlok és mappák mutatása @@ -1000,22 +1000,22 @@ Rejtett fájlok és mappák mutatása - A hardware eltávolítása biztonságos + Eszköz kiadása Az eszköz biztonságosan eltávolítható. - Hiba az eszköz kiadása közben + Hiba történt az eszköz kiadása közben - Az eszköz jelenleg használatban van. Zárjon be minden programot, ablakot ami használhatja, majd próbálja újra. + Az eszköz jelenleg használatban van. Zárjon be minden programot, ablakot vagy oldalt, ami használhatja, majd próbálja újra. Kiadás - Lap kettőzése + Lap megkettőzése Lap áthelyezése új ablakba @@ -1027,7 +1027,7 @@ Keresés - Csak olvasható + Írásvédett Rejtett @@ -1036,13 +1036,13 @@ Minősítés - Elem típusa + Típus Cím - Téma + Tárgy Megjegyzés @@ -1078,28 +1078,28 @@ Színtér - Szélesség (egész) + GPS szélesség (egész) - Magasság (egész) + GPS magasság (egész) - Szélesség + GPS szélesség - Magasság + GPS magasság - Szélesség Ref + GPS szélesség ref - Magasság Ref + GPS magasság ref - Magasság + GPS magasság - Létrehozás dátuma + Készítés dátuma Fényképezőgép gyártója @@ -1116,12 +1116,21 @@ Rekesz + + Megjelenő személyek + Csatornák száma Formátum + + Mintavételi ráta + + + Előadó + Album előadója @@ -1132,13 +1141,13 @@ Előadó - Ütem Per Perc + Ütem / perc Zeneszerző - Zeneszerző + Karmester Lemez száma @@ -1155,11 +1164,20 @@ Képkockák száma + + Védelem típusa + + + Szerző URL + + + Tartalomszolgáltató + Megjelenés dátuma - Adatsor neve + Sorozat Évad @@ -1213,10 +1231,10 @@ Nyomtatás dátuma - Teljes szerkeztési idő + Teljes szerkesztési idő - Minta + Sablon Szavak száma @@ -1231,13 +1249,16 @@ Bekezdések száma - Lapok száma + Oldalak száma + + + Diák száma - Képkockák sebessége + Képkockasebesség - Bitráta kódolása + Kódolási bitráta Tömörítés @@ -1252,7 +1273,7 @@ Tájolás - Leírás + Alap információk Kép @@ -1279,7 +1300,7 @@ Dokumentum - Elérhetőség + Cím Hiba @@ -1294,16 +1315,16 @@ Mégse - Probléma adódott a tulajdonságok mentésekor. + Probléma adódott a tulajdonságok mentése közben. - Pár tulajdonság tartalmazhat személyes információt. + Némelyik tulajdonság személyes adatokat tartalmazhat. - Clear + Eltávolítás - Összes tulajdonság törlése + Mindegyik tulajdonság eltávolítása sRGB @@ -1315,7 +1336,7 @@ Itt ellenőrizheti a fájlműveletek állapotát - Állapotsor + Állapotközpont Licenc @@ -1330,13 +1351,13 @@ Weboldal - Tudjon meg többet a dátumokról + Tudjon meg többet a dátumformátumokról - Másolás ide + Engedje el itt - Keresés eredménye a következőben: + Keresés eredménye itt: Keresési eredmények @@ -1363,7 +1384,7 @@ Nem - Szeretné letőlteni és telepíteni a legújabb Files verziót? + Szeretné letölteni és telepíteni a Files legújabb verzióját? Igen @@ -1372,10 +1393,10 @@ Frissítés elérhető - Védett operációs rendszer fájlok elrejtése (Ajánlott) + Védett operációs rendszer fájlok elrejtése (ajánlott) - Védett operációs rendszer fájlok elrejtése (Ajánlott) + Védett operációs rendszer fájlok elrejtése (ajánlott) Fájl @@ -1384,19 +1405,19 @@ Fájl - Létrehoz egy üres fájlt + Üres fájl létrehozása - Új Fájl + Új fájl - Egyedi preferencia minden egyes mappához + Egyedi beállítások megjegyzése minden mappához - Eredeti elérési út: + Eredeti elérési út - Eredeti elérési út: + Eredeti elérési út Hozzáadás @@ -1408,7 +1429,7 @@ Törlés - Fájlok és mappák gyorsítótárba való helyezése a jobb teljesítményért + Fájlok és mappák gyorsítótárazása a jobb teljesítményért Mégse @@ -1420,37 +1441,37 @@ Folyamatban lévő műveletek - Mindig kettős nézetben nyissa meg az új lapokat + Mindig osztott nézetben nyissa meg az új lapokat - Kettős panel bekapcsolása + Osztott nézet bekapcsolása - Megnyitás második panelben + Megnyitás a jobb oldali panelen Új panel - Megnyitás második panelben + Megnyitás a jobb oldali panelen - Kettós panel + Osztott nézet Nem indexelt elemek mutatása fájl és mappa keresésekor (hosszabb keresési idő) - Hely másolása elem megjelenítése + "Elérési út másolása" elem megjelenítése Ki nem férő elemek almenübe helyezése - Menü testreszabása + Helyi menü testreszabása - Megnyitás új oldalon elem megjelenítése + "Megnyitás új oldalon" elem megjelenítése Mappák @@ -1498,7 +1519,7 @@ Lista - Fájlkiterjesztések mutatása + Fájl kiterjesztések megjelenítése Rejtett fájlok megjelenítése @@ -1516,67 +1537,67 @@ Lap testreszabása - Files indulásakor + A Files indulásakor - Elem elérési útja + Elérési út - Váltás előnézetre (Ctrl + P) + Előnézet panel (Ctrl + P) - Elem neve + Név - Megerősítés + Létrehozás - Csomag ezzel a névvel már létezik! + Már létezik munkaterület ezzel a névvel! A mező nem lehet üres! - Csomag neve + Munkaterület neve - Csomag neve + Munkaterület neve Mégse - Új név + Név - Megerősítés + Átnevezés - Írja be az új nevet + Adja meg az új nevet - "{0} átnevezése" + "{0}" átnevezése Mégse - Csomag neve + Munkaterület neve - Megerősítés + Létrehozás - Új Csomag + Új munkaterület - Csomagok Exportálása + Munkaterületek exportálása - Csomagok Importálása + Munkaterületek importálása - Csomag létrehozása + Munkaterület létrehozása Megnyitás új lapon @@ -1585,34 +1606,34 @@ Elem helyének megnyitása - Eltávolítás a csomagból + Eltávolítás a munkaterületről - Csomag eltávolítása + Munkaterület eltávolítása - Csomagok + Munkaterületek Húzza ide a fájlokat és mappákat a gyors elérésükhöz - Megerősítés + Létrehozás - Írja be az csomag nevét + Adja meg a munkaterület nevét - Csomag létrehozása + Munkaterület létrehozása - Csomag átnevezése + Munkaterület átnevezése - Több lehetőség... + További lehetőségek... - Csomag létrehozása + Munkaterület létrehozása Felhőtárhely @@ -1621,22 +1642,25 @@ Nincs elérhető előnézet - Nincs elérhető részlet + Nincsenek elérhető részletek - Csomagok megjelenítése a fő oldalon + Munkaterületek megjelenítése a kezdőoldalon - Könyvtár levétele az oldalsávról + Levétel az oldalsávról + + + Folyamatban lévő műveletek panel - Online állapotban elérhető + Online elérhető - Offline állapotban is elérhető + Offline is elérhető - Részben elérhető offline módban + Offline részben elérhető Szinkronizálás @@ -1645,7 +1669,7 @@ Kizárva a szinkronizálásból - Kiszámolatlan + Nem meghatározott Ismeretlen @@ -1675,7 +1699,7 @@ Adaptív előnézeti panel engedélyezése - Többszörös kijelölés + Több elem kijelölése Többszörös kijelőlés (jelenleg lista és ikon nézetekben elérhető) From d785e9a2f8298db04cc54749e98c0c0250ffea4e Mon Sep 17 00:00:00 2001 From: Steven He Date: Mon, 8 Feb 2021 11:10:34 +0800 Subject: [PATCH 13/15] restore using BulkConcurrentObservableCollection --- Files/DataModels/SidebarPinnedModel.cs | 2 +- Files/Filesystem/CloudDrivesManager.cs | 2 +- Files/Filesystem/Drives.cs | 2 +- Files/Views/MainPage.xaml.cs | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Files/DataModels/SidebarPinnedModel.cs b/Files/DataModels/SidebarPinnedModel.cs index 1d8995cf2622..d335cef946b4 100644 --- a/Files/DataModels/SidebarPinnedModel.cs +++ b/Files/DataModels/SidebarPinnedModel.cs @@ -228,7 +228,7 @@ public async Task AddAllItemsToSidebar() string path = Items[i]; await AddItemToSidebarAsync(path); } - MainPage.SideBarItems.ResetCollection(); + MainPage.SideBarItems.EndBulkOperation(); } finally { diff --git a/Files/Filesystem/CloudDrivesManager.cs b/Files/Filesystem/CloudDrivesManager.cs index 9991534dedf4..e1ea55711bd2 100644 --- a/Files/Filesystem/CloudDrivesManager.cs +++ b/Files/Filesystem/CloudDrivesManager.cs @@ -134,7 +134,7 @@ await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPrio MainPage.SideBarItems.Insert(insertAt, drive); insertAt++; } - MainPage.SideBarItems.ResetCollection(); + MainPage.SideBarItems.EndBulkOperation(); } finally { diff --git a/Files/Filesystem/Drives.cs b/Files/Filesystem/Drives.cs index 9016937c1064..7f519fa0967f 100644 --- a/Files/Filesystem/Drives.cs +++ b/Files/Filesystem/Drives.cs @@ -164,7 +164,7 @@ await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPrio DrivesWidget.ItemsAdded.Add(drive); insertAt++; } - MainPage.SideBarItems.ResetCollection(); + MainPage.SideBarItems.EndBulkOperation(); } finally { diff --git a/Files/Views/MainPage.xaml.cs b/Files/Views/MainPage.xaml.cs index e97aab2ed7da..43338f9e5caf 100644 --- a/Files/Views/MainPage.xaml.cs +++ b/Files/Views/MainPage.xaml.cs @@ -52,7 +52,7 @@ public TabItem SelectedTabItem } public static ObservableCollection AppInstances = new ObservableCollection(); - public static ResettableObservableCollection SideBarItems = new ResettableObservableCollection(); + public static BulkConcurrentObservableCollection SideBarItems = new BulkConcurrentObservableCollection(); public static SemaphoreSlim SideBarItemsSemaphore = new SemaphoreSlim(1, 1); public MainPage() From ef10b8257aab82df6d87a138c90bb0a1e95baea7 Mon Sep 17 00:00:00 2001 From: Steven He Date: Tue, 9 Feb 2021 12:48:03 +0800 Subject: [PATCH 14/15] more fixes to BulkConcurrentObservableCollection --- .../BulkConcurrentObservableCollection.cs | 41 +++++++++++-------- 1 file changed, 24 insertions(+), 17 deletions(-) diff --git a/Files/Helpers/BulkConcurrentObservableCollection.cs b/Files/Helpers/BulkConcurrentObservableCollection.cs index a0e3485aa780..dba78ad7b53f 100644 --- a/Files/Helpers/BulkConcurrentObservableCollection.cs +++ b/Files/Helpers/BulkConcurrentObservableCollection.cs @@ -46,7 +46,7 @@ public T this[int index] { var item = collection[index]; collection[index] = value; - OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Replace, value, item)); + OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Replace, value, item, index), false); } } @@ -58,12 +58,15 @@ public void BeginBulkOperation() isBulkOperationStarted = true; } - protected void OnCollectionChanged(NotifyCollectionChangedEventArgs e) + protected void OnCollectionChanged(NotifyCollectionChangedEventArgs e, bool countChanged = true) { if (!isBulkOperationStarted) { CollectionChanged?.Invoke(this, e); - PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Count))); + if (countChanged) + { + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Count))); + } PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Item[]")); } } @@ -108,22 +111,22 @@ public void CopyTo(T[] array, int arrayIndex) public bool Remove(T item) { - bool result; - - var index = collection.IndexOf(item); - - if (index == -1) - { - return true; - } + int index; lock (syncRoot) { - result = collection.Remove(item); + index = collection.IndexOf(item); + + if (index == -1) + { + return true; + } + + collection.RemoveAt(index); } OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, item, index)); - return result; + return true; } public IEnumerator GetEnumerator() @@ -153,10 +156,11 @@ public void Insert(int index, T item) public void RemoveAt(int index) { - var item = collection[index]; + T item; lock (syncRoot) { + item = collection[index]; collection.RemoveAt(index); } @@ -200,10 +204,11 @@ public void RemoveRange(int index, int count) return; } - var items = collection.Skip(index).Take(count).ToList(); + List items; lock (syncRoot) { + items = collection.Skip(index).Take(count).ToList(); collection.RemoveRange(index, count); } @@ -219,11 +224,13 @@ public void ReplaceRange(int index, IEnumerable items) return; } - var oldItems = collection.Skip(index).Take(count).ToList(); - var newItems = items.ToList(); + List oldItems; + List newItems; lock (syncRoot) { + oldItems = collection.Skip(index).Take(count).ToList(); + newItems = items.ToList(); collection.InsertRange(index, newItems); collection.RemoveRange(index + count, count); } From 57de6730744f158d02dedb558eb4175d15473e4f Mon Sep 17 00:00:00 2001 From: Marco Gavelli Date: Sat, 13 Feb 2021 14:14:32 +0100 Subject: [PATCH 15/15] Fix duplicate cloud drives when opening a folder from the taskbar jumplist --- Files/App.xaml.cs | 2 +- Files/DataModels/SidebarPinnedModel.cs | 2 +- Files/Filesystem/CloudDrivesManager.cs | 5 ++++- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/Files/App.xaml.cs b/Files/App.xaml.cs index fa1c122de2e0..4e01b54ac0ad 100644 --- a/Files/App.xaml.cs +++ b/Files/App.xaml.cs @@ -49,7 +49,7 @@ sealed partial class App : Application public static SettingsViewModel AppSettings { get; private set; } public static InteractionViewModel InteractionViewModel { get; private set; } public static JumpListManager JumpList { get; } = new JumpListManager(); - public static SidebarPinnedController SidebarPinnedController { get; private set; }// = new SidebarPinnedController(); + public static SidebarPinnedController SidebarPinnedController { get; private set; } public static CloudDrivesManager CloudDrivesManager { get; private set; } public static DrivesManager DrivesManager { get; private set; } diff --git a/Files/DataModels/SidebarPinnedModel.cs b/Files/DataModels/SidebarPinnedModel.cs index d335cef946b4..1e98534cd540 100644 --- a/Files/DataModels/SidebarPinnedModel.cs +++ b/Files/DataModels/SidebarPinnedModel.cs @@ -190,7 +190,7 @@ public async Task AddItemToSidebarAsync(string path) { var item = await FilesystemTasks.Wrap(() => DrivesManager.GetRootFromPathAsync(path)); var res = await FilesystemTasks.Wrap(() => StorageFileExtensions.DangerousGetFolderFromPathAsync(path, item)); - if (res) + if (res || (FilesystemResult)ItemViewModel.CheckFolderAccessWithWin32(path)) { int insertIndex = MainPage.SideBarItems.IndexOf(MainPage.SideBarItems.Last(x => x.ItemType == NavigationControlItemType.Location && !x.Path.Equals(App.AppSettings.RecycleBinPath))) + 1; diff --git a/Files/Filesystem/CloudDrivesManager.cs b/Files/Filesystem/CloudDrivesManager.cs index e1ea55711bd2..67c9b69d3350 100644 --- a/Files/Filesystem/CloudDrivesManager.cs +++ b/Files/Filesystem/CloudDrivesManager.cs @@ -49,7 +49,10 @@ public async Task EnumerateDrivesAsync() }; lock (drivesList) { - drivesList.Add(cloudProviderItem); + if (!drivesList.Any(x => x.Path == cloudProviderItem.Path)) + { + drivesList.Add(cloudProviderItem); + } } }