Skip to content

Commit 0e93777

Browse files
authored
Improve startup performance (#3257)
1 parent 5eb839c commit 0e93777

18 files changed

+141
-83
lines changed

Files/App.xaml.cs

Lines changed: 32 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,9 @@ sealed partial class App : Application
5050
public static InteractionViewModel InteractionViewModel { get; set; }
5151
public static JumpListManager JumpList { get; } = new JumpListManager();
5252
public static SidebarPinnedController SidebarPinnedController { get; set; }
53+
public static CloudDrivesManager CloudDrivesManager { get; set; }
54+
public static DrivesManager DrivesManager { get; set; }
55+
5356
private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
5457

5558
public static class AppData
@@ -80,22 +83,45 @@ internal static async Task EnsureSettingsAndConfigurationAreBootstrapped()
8083
{
8184
if (AppSettings == null)
8285
{
86+
//We can't create AppSettings at the same time as everything else as other dependencies depend on AppSettings
8387
AppSettings = await SettingsViewModel.CreateInstance();
88+
if (App.AppSettings?.AcrylicTheme == null)
89+
{
90+
Helpers.ThemeHelper.Initialize();
91+
}
92+
}
93+
94+
if (CloudDrivesManager == null)
95+
{
96+
//Enumerate cloud drives on in the background. It will update the UI itself when finished
97+
_ = Files.Filesystem.CloudDrivesManager.Instance.ContinueWith(o =>
98+
{
99+
CloudDrivesManager = o.Result;
100+
});
84101
}
85102

86-
if (App.AppSettings?.AcrylicTheme == null)
103+
//Start off a list of tasks we need to run before we can continue startup
104+
var tasksToRun = new List<Task>();
105+
106+
if (SidebarPinnedController == null)
107+
{
108+
tasksToRun.Add(Files.Controllers.SidebarPinnedController.CreateInstance().ContinueWith(o => SidebarPinnedController = o.Result));
109+
}
110+
111+
if (DrivesManager == null)
87112
{
88-
ThemeHelper.Initialize();
113+
tasksToRun.Add(Files.Filesystem.DrivesManager.Instance.ContinueWith(o => DrivesManager = o.Result));
89114
}
90115

91116
if (InteractionViewModel == null)
92117
{
93118
InteractionViewModel = new InteractionViewModel();
94119
}
95120

96-
if (SidebarPinnedController == null)
121+
if (tasksToRun.Any())
97122
{
98-
SidebarPinnedController = await SidebarPinnedController.CreateInstance();
123+
//Only proceed when all tasks are completed
124+
await Task.WhenAll(tasksToRun);
99125
}
100126
}
101127

@@ -118,7 +144,7 @@ private async void StartAppCenter()
118144

119145
private void OnLeavingBackground(object sender, LeavingBackgroundEventArgs e)
120146
{
121-
AppSettings?.DrivesManager?.ResumeDeviceWatcher();
147+
DrivesManager?.ResumeDeviceWatcher();
122148
}
123149

124150
public static INavigationControlItem RightClickedItem;
@@ -387,7 +413,7 @@ private void OnSuspending(object sender, SuspendingEventArgs e)
387413
var deferral = e.SuspendingOperation.GetDeferral();
388414
//TODO: Save application state and stop any background activity
389415

390-
AppSettings?.Dispose();
416+
DrivesManager?.Dispose();
391417
deferral.Complete();
392418
}
393419

Files/Filesystem/Cloud/CloudProviderController.cs

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,9 @@ namespace Files.Filesystem.Cloud
77
{
88
public class CloudProviderController
99
{
10-
private List<CloudProvider> cloudProviders;
10+
private List<CloudProvider> cloudProviders = new List<CloudProvider>();
1111

12-
public CloudProviderController()
13-
{
14-
CloudProviderDetectors = new List<ICloudProviderDetector>
12+
public List<ICloudProviderDetector> CloudProviderDetectors => new List<ICloudProviderDetector>
1513
{
1614
new GoogleDriveCloudProvider(),
1715
new DropBoxCloudProvider(),
@@ -22,11 +20,6 @@ public CloudProviderController()
2220
new AmazonDriveProvider()
2321
};
2422

25-
CloudProviders = new List<CloudProvider>();
26-
}
27-
28-
public List<ICloudProviderDetector> CloudProviderDetectors { get; set; }
29-
3023
public List<CloudProvider> CloudProviders
3124
{
3225
get => cloudProviders.Where(x => !string.IsNullOrEmpty(x.SyncFolder)).ToList();
@@ -35,10 +28,17 @@ public List<CloudProvider> CloudProviders
3528

3629
public async Task DetectInstalledCloudProvidersAsync()
3730
{
31+
var tasks = new List<Task<IList<CloudProvider>>>();
32+
var results = new List<CloudProvider>();
33+
3834
foreach (var provider in CloudProviderDetectors)
3935
{
40-
await provider.DetectAsync(cloudProviders);
36+
tasks.Add(provider.DetectAsync());
4137
}
38+
39+
await Task.WhenAll(tasks);
40+
41+
cloudProviders = tasks.SelectMany(o => o.Result).ToList();
4242
}
4343
}
4444
}

Files/Filesystem/Cloud/ICloudProviderDetector.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,6 @@ namespace Files.Filesystem.Cloud
55
{
66
public interface ICloudProviderDetector
77
{
8-
Task DetectAsync(List<CloudProvider> cloudProviders);
8+
Task<IList<CloudProvider>> DetectAsync();
99
}
1010
}
Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,38 @@
11
using Files.Enums;
22
using Microsoft.Win32;
3+
using System;
34
using System.Collections.Generic;
45
using System.Threading.Tasks;
56

67
namespace Files.Filesystem.Cloud.Providers
78
{
89
public class AmazonDriveProvider : ICloudProviderDetector
910
{
10-
public async Task DetectAsync(List<CloudProvider> cloudProviders)
11+
public async Task<IList<CloudProvider>> DetectAsync()
1112
{
12-
await Task.Run(() =>
13+
try
1314
{
14-
try
15-
{
16-
using var key = Registry.ClassesRoot.OpenSubKey(@"CLSID\{9B57F475-CCB0-4C85-88A9-2AA9A6C0809A}\Instance\InitPropertyBag");
17-
var syncedFolder = (string)key?.GetValue("TargetFolderPath");
15+
using var key = Registry.ClassesRoot.OpenSubKey(@"CLSID\{9B57F475-CCB0-4C85-88A9-2AA9A6C0809A}\Instance\InitPropertyBag");
16+
var syncedFolder = (string)key?.GetValue("TargetFolderPath");
1817

19-
if (syncedFolder == null)
20-
{
21-
return;
22-
}
18+
if (syncedFolder == null)
19+
{
20+
return Array.Empty<CloudProvider>();
21+
}
2322

24-
cloudProviders.Add(new CloudProvider()
23+
return new[] { new CloudProvider()
2524
{
2625
ID = CloudProviders.AmazonDrive,
2726
Name = "Amazon Drive",
2827
SyncFolder = syncedFolder
29-
});
30-
}
31-
catch
32-
{
33-
// Not detected
34-
}
35-
});
28+
}
29+
};
30+
}
31+
catch
32+
{
33+
// Not detected
34+
return Array.Empty<CloudProvider>();
35+
}
3636
}
3737
}
3838
}

Files/Filesystem/Cloud/Providers/AppleCloudProvider.cs

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,24 +9,26 @@ namespace Files.Filesystem.Cloud.Providers
99
{
1010
public class AppleCloudProvider : ICloudProviderDetector
1111
{
12-
public async Task DetectAsync(List<CloudProvider> cloudProviders)
12+
public async Task<IList<CloudProvider>> DetectAsync()
1313
{
1414
try
1515
{
1616
var userPath = UserDataPaths.GetDefault().Profile;
1717
var iCloudPath = "iCloudDrive";
1818
var driveFolder = await StorageFolder.GetFolderFromPathAsync(Path.Combine(userPath, iCloudPath));
1919

20-
cloudProviders.Add(new CloudProvider()
21-
{
22-
ID = CloudProviders.AppleCloud,
23-
Name = "iCloud",
24-
SyncFolder = driveFolder.Path
25-
});
20+
return new[] { new CloudProvider()
21+
{
22+
ID = CloudProviders.AppleCloud,
23+
Name = "iCloud",
24+
SyncFolder = driveFolder.Path
25+
}
26+
};
2627
}
2728
catch
2829
{
2930
// Not detected
31+
return Array.Empty<CloudProvider>();
3032
}
3133
}
3234
}

Files/Filesystem/Cloud/Providers/BoxCloudProvider.cs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ namespace Files.Filesystem.Cloud.Providers
99
{
1010
public class BoxCloudProvider : ICloudProviderDetector
1111
{
12-
public async Task DetectAsync(List<CloudProvider> cloudProviders)
12+
public async Task<IList<CloudProvider>> DetectAsync()
1313
{
1414
try
1515
{
@@ -29,18 +29,22 @@ public async Task DetectAsync(List<CloudProvider> cloudProviders)
2929

3030
if (!string.IsNullOrEmpty(syncPath))
3131
{
32-
cloudProviders.Add(new CloudProvider()
32+
return new[] { new CloudProvider()
3333
{
3434
ID = CloudProviders.Box,
3535
Name = "Box",
3636
SyncFolder = syncPath
37-
});
37+
}
38+
};
3839
}
3940
}
41+
42+
return Array.Empty<CloudProvider>();
4043
}
4144
catch
4245
{
4346
// Not detected
47+
return Array.Empty<CloudProvider>();
4448
}
4549
}
4650
}

Files/Filesystem/Cloud/Providers/DropBoxCloudProvider.cs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,19 +10,20 @@ namespace Files.Filesystem.Cloud.Providers
1010
{
1111
public class DropBoxCloudProvider : ICloudProviderDetector
1212
{
13-
public async Task DetectAsync(List<CloudProvider> cloudProviders)
13+
public async Task<IList<CloudProvider>> DetectAsync()
1414
{
1515
try
1616
{
1717
var infoPath = @"Dropbox\info.json";
1818
var jsonPath = Path.Combine(UserDataPaths.GetDefault().LocalAppData, infoPath);
1919
var configFile = await StorageFile.GetFileFromPathAsync(jsonPath);
2020
var jsonObj = JObject.Parse(await FileIO.ReadTextAsync(configFile));
21+
var results = new List<CloudProvider>();
2122

2223
if (jsonObj.ContainsKey("personal"))
2324
{
2425
var dropboxPath = (string)jsonObj["personal"]["path"];
25-
cloudProviders.Add(new CloudProvider()
26+
results.Add(new CloudProvider()
2627
{
2728
ID = CloudProviders.DropBox,
2829
Name = "Dropbox",
@@ -33,17 +34,20 @@ public async Task DetectAsync(List<CloudProvider> cloudProviders)
3334
if (jsonObj.ContainsKey("business"))
3435
{
3536
var dropboxPath = (string)jsonObj["business"]["path"];
36-
cloudProviders.Add(new CloudProvider()
37+
results.Add(new CloudProvider()
3738
{
3839
ID = CloudProviders.DropBox,
3940
Name = "Dropbox Business",
4041
SyncFolder = dropboxPath
4142
});
4243
}
44+
45+
return results;
4346
}
4447
catch
4548
{
4649
// Not detected
50+
return Array.Empty<CloudProvider>();
4751
}
4852
}
4953
}

Files/Filesystem/Cloud/Providers/GoogleDriveCloudProvider.cs

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ namespace Files.Filesystem.Cloud.Providers
1010
{
1111
public class GoogleDriveCloudProvider : ICloudProviderDetector
1212
{
13-
public async Task DetectAsync(List<CloudProvider> cloudProviders)
13+
public async Task<IList<CloudProvider>> DetectAsync()
1414
{
1515
try
1616
{
@@ -29,13 +29,15 @@ public async Task DetectAsync(List<CloudProvider> cloudProviders)
2929
// Open the connection and execute the command
3030
con.Open();
3131
var reader = cmd.ExecuteReader();
32+
var results = new List<CloudProvider>();
33+
3234
while (reader.Read())
3335
{
3436
// Extract the data from the reader
3537
string path = reader["data_value"]?.ToString();
3638
if (string.IsNullOrWhiteSpace(path))
3739
{
38-
return;
40+
return Array.Empty<CloudProvider>();
3941
}
4042

4143
// By default, the path will be prefixed with "\\?\" (unless another app has explicitly changed it).
@@ -62,13 +64,16 @@ public async Task DetectAsync(List<CloudProvider> cloudProviders)
6264
googleCloud.Name = "Google Drive";
6365
}
6466

65-
cloudProviders.Add(googleCloud);
67+
results.Add(googleCloud);
6668
}
69+
70+
return results;
6771
}
6872
}
6973
catch
7074
{
7175
// Not detected
76+
return Array.Empty<CloudProvider>();
7277
}
7378
}
7479
}

Files/Filesystem/Cloud/Providers/MegaCloudProvider.cs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ namespace Files.Filesystem.Cloud.Providers
1515
{
1616
public class MegaCloudProvider : ICloudProviderDetector
1717
{
18-
public async Task DetectAsync(List<CloudProvider> cloudProviders)
18+
public async Task<IList<CloudProvider>> DetectAsync()
1919
{
2020
try
2121
{
@@ -42,6 +42,8 @@ public async Task DetectAsync(List<CloudProvider> cloudProviders)
4242

4343
var syncKey = Hash("Syncs", currentAccountSectionKey, encryptionKey);
4444
var syncGroups = currentAccountSection.Keys.Where(s => s.KeyName.StartsWith(syncKey)).Select(x => x.KeyName.Split('\\')[1]).Distinct();
45+
var results = new List<CloudProvider>();
46+
4547
foreach (var sync in syncGroups)
4648
{
4749
currentGroup = string.Join("/", currentAccountSectionKey, syncKey, sync);
@@ -52,17 +54,20 @@ public async Task DetectAsync(List<CloudProvider> cloudProviders)
5254
var localFolderStr = currentAccountSection.Keys.First(s => s.KeyName == string.Join("\\", syncKey, sync, localFolderKey));
5355
var localFolderDecrypted = Decrypt(localFolderKey, localFolderStr.Value.Replace("\"", ""), currentGroup);
5456

55-
cloudProviders.Add(new CloudProvider()
57+
results.Add(new CloudProvider()
5658
{
5759
ID = CloudProviders.Mega,
5860
Name = $"MEGA ({syncNameDecrypted})",
5961
SyncFolder = localFolderDecrypted
6062
});
6163
}
64+
65+
return results;
6266
}
6367
catch
6468
{
6569
// Not detected
70+
return Array.Empty<CloudProvider>();
6671
}
6772
}
6873

0 commit comments

Comments
 (0)