diff --git a/DailyDesktop.Core/DailyDesktopCore.cs b/DailyDesktop.Core/DailyDesktopCore.cs index 73cacf8..d7c00f5 100644 --- a/DailyDesktop.Core/DailyDesktopCore.cs +++ b/DailyDesktop.Core/DailyDesktopCore.cs @@ -19,12 +19,12 @@ namespace DailyDesktop.Core /// module scanning, though is fully functional as /// a standalone class. /// - public class DailyDesktopCore : IDisposable + public sealed class DailyDesktopCore : IDisposable { private Microsoft.Win32.TaskScheduler.Task? task; private string taskName; - private readonly ProviderStore store = new ProviderStore(); + private readonly ProviderStore store = new(); /// /// Read-only interface to the path configuration. @@ -62,8 +62,12 @@ public string TaskName /// /// The currently selected provider corresponding to . /// - public IProvider? CurrentProvider => currentProvider; - private IProvider? currentProvider; + public IProvider? CurrentProvider => Providers.ContainsKey(taskConfig.Dll) ? IProvider.Instantiate(Providers[taskConfig.Dll]) : null; + + /// + /// The collection of currently loaded s. + /// + public IReadOnlyDictionary Providers => store.Providers; /// /// The state of the desktop wallpaper update task. @@ -79,35 +83,24 @@ public string TaskName /// The . public static async Task CreateCoreAsync(PathConfiguration pathConfig, string taskName, bool isAutoCreatingTask, CancellationToken cancellationToken) { - var core = new DailyDesktopCore(pathConfig, taskName); - - core.IsAutoCreatingTask = isAutoCreatingTask; + var core = new DailyDesktopCore(pathConfig, taskName) + { + IsAutoCreatingTask = isAutoCreatingTask + }; core.taskConfig.OnUpdateAsync += core.onTaskConfigUpdateAsync; if (!await core.taskConfig.TryDeserializeAsync(cancellationToken)) await core.taskConfig.UpdateAsync(cancellationToken); - var providers = await core.GetProvidersAsync(cancellationToken); - if (providers.ContainsKey(core.taskConfig.Dll)) - core.currentProvider = IProvider.Instantiate(providers[core.taskConfig.Dll]); - - if (core.IsAutoCreatingTask) - core.CreateTask(); - return core; } /// - /// Get an asynchronously scanned dictionary of values and DLL module path keys. + /// Scans for s and populates . /// /// The . - /// The dictionary of DLL path s to s. - public async Task> GetProvidersAsync(CancellationToken cancellationToken) - { - await store.ScanAsync(pathConfig.ProvidersDir, cancellationToken); - return store.Providers; - } + public async Task ScanProvidersAsync(CancellationToken cancellationToken) => await store.ScanAsync(pathConfig.ProvidersDir, cancellationToken); /// /// Creates a under the name . If @@ -190,11 +183,8 @@ private DailyDesktopCore(PathConfiguration pathConfig, string taskName) private async Task onTaskConfigUpdateAsync(object? sender, EventArgs? args, CancellationToken cancellationToken) { - var providers = await GetProvidersAsync(cancellationToken); - currentProvider = providers.ContainsKey(taskConfig.Dll) ? IProvider.Instantiate(providers[taskConfig.Dll]) : null; - if (IsAutoCreatingTask) - CreateTask(); + await Task.Run(CreateTask, cancellationToken); } /// diff --git a/DailyDesktop.Core/Providers/ProviderStore.cs b/DailyDesktop.Core/Providers/ProviderStore.cs index 1a94db5..0c165c0 100644 --- a/DailyDesktop.Core/Providers/ProviderStore.cs +++ b/DailyDesktop.Core/Providers/ProviderStore.cs @@ -89,7 +89,7 @@ private Type addImpl(string dllPath, Assembly assembly) public void Scan(string directory) { if (!Directory.Exists(directory)) - return; + throw new DirectoryNotFoundException($"{directory} does not exist"); foreach (var path in Directory.GetFiles(directory, PROVIDERS_SEARCH_PATTERN, SearchOption.AllDirectories)) { @@ -113,10 +113,13 @@ public void Scan(string directory) public async Task ScanAsync(string directory, CancellationToken cancellationToken) { if (!Directory.Exists(directory)) - return; + throw new DirectoryNotFoundException($"{directory} does not exist"); foreach (var path in Directory.GetFiles(directory, PROVIDERS_SEARCH_PATTERN, SearchOption.AllDirectories)) { + if (cancellationToken.IsCancellationRequested) + throw new OperationCanceledException(); + try { await AddAsync(path, cancellationToken); diff --git a/DailyDesktop.Desktop/MainForm.cs b/DailyDesktop.Desktop/MainForm.cs index d2ddad7..8d3f0c3 100644 --- a/DailyDesktop.Desktop/MainForm.cs +++ b/DailyDesktop.Desktop/MainForm.cs @@ -36,6 +36,8 @@ public partial class MainForm : Form private const string null_text = "null"; private const string fetched_text = "fetched on"; + private const string failed_scan_text = "Could not load all providers. (took too long?)"; + private readonly DailyDesktopCore core; private readonly WallpaperConfiguration wallpaperConfig; @@ -64,7 +66,7 @@ public static async Task CreateFormAsync() AssemblyDir = assemblyDir, ProvidersDir = providersDir, SerializationDir = serializationDir, - }, taskName, true, AsyncUtils.TimedCancel(2500))); + }, taskName, true, AsyncUtils.TimedCancel())); } private MainForm(DailyDesktopCore core) @@ -129,40 +131,56 @@ private void MainForm_FormClosing(object? sender, EventArgs e) private async void providerComboBox_SelectedIndexChanged(object? sender, EventArgs e) { - if (providerComboBox.SelectedItem is ProviderWrapper provider) - await taskConfig.SetDllAsync(provider.Dll, AsyncUtils.TimedCancel()); + if (providerComboBox.SelectedItem is not ProviderWrapper p) + return; + + await taskConfig.SetDllAsync(p.Dll, AsyncUtils.TimedCancel()); - providerDescriptionLabel.Text = core.CurrentProvider?.Description ?? null_description; - providerSourceLinkLabel.Text = core.CurrentProvider?.SourceUri ?? null_text; - providerSourceLinkLabel.Links[0].Enabled = Uri.TryCreate(providerSourceLinkLabel.Text, UriKind.Absolute, out _); - providerSourceLinkLabel.TabStop = wallpaperAuthorLinkLabel.Links[0].Enabled; + Invoke(() => + { + var provider = core.CurrentProvider; + providerDescriptionLabel.Text = provider?.Description ?? null_description; + providerSourceLinkLabel.Text = provider?.SourceUri ?? null_text; + providerSourceLinkLabel.Links[0].Enabled = Uri.TryCreate(providerSourceLinkLabel.Text, UriKind.Absolute, out _); + providerSourceLinkLabel.TabStop = wallpaperAuthorLinkLabel.Links[0].Enabled; + }); } private async Task repopulateProviderComboBox() { - var providers = await core.GetProvidersAsync(AsyncUtils.TimedCancel()); + bool isFullyLoaded = true; - providerComboBox.Items.Clear(); - providerComboBox.Items.Add(ProviderWrapper.Null); + try + { + await core.ScanProvidersAsync(AsyncUtils.TimedCancel(3000)); + } + catch (OperationCanceledException) + { + isFullyLoaded = false; + } - foreach (var keyVal in providers) + Invoke(() => { - try - { - var provider = IProvider.Instantiate(keyVal.Value); - var item = new ProviderWrapper(keyVal.Key, provider); - providerComboBox.Items.Add(item); - } - catch (ProviderException pe) + providerComboBox.Items.Clear(); + providerComboBox.Items.Add(isFullyLoaded ? ProviderWrapper.Null : failed_scan_text); + + foreach (var keyVal in core.Providers) { - Console.WriteLine(pe.StackTrace); + try + { + var provider = IProvider.Instantiate(keyVal.Value); + var item = new ProviderWrapper(keyVal.Key, provider); + providerComboBox.Items.Add(item); + } + catch (ProviderException pe) + { + Console.WriteLine(pe.StackTrace); + } } - } - - int index = providerComboBox.FindString(core.CurrentProvider?.DisplayName ?? ""); - if (index >= 0) - providerComboBox.SelectedIndex = index; + if (core.CurrentProvider != null) + providerComboBox.SelectedIndex = providerComboBox.FindString(core.CurrentProvider.DisplayName); + }); } private async void providerComboBox_DropDown(object? sender, EventArgs e) => await repopulateProviderComboBox();