From 767cdc1f6f6a63ce997fc9476911e2c361f9d402 Mon Sep 17 00:00:00 2001 From: LukePulverenti Date: Wed, 20 Feb 2013 20:33:05 -0500 Subject: Pushing missing changes --- MediaBrowser.UI/Controller/BaseTheme.cs | 60 ++++ MediaBrowser.UI/Controller/PluginUpdater.cs | 537 ++++++++++++++++------------ MediaBrowser.UI/Controller/UIKernel.cs | 298 ++++++++++----- 3 files changed, 567 insertions(+), 328 deletions(-) create mode 100644 MediaBrowser.UI/Controller/BaseTheme.cs (limited to 'MediaBrowser.UI/Controller') diff --git a/MediaBrowser.UI/Controller/BaseTheme.cs b/MediaBrowser.UI/Controller/BaseTheme.cs new file mode 100644 index 0000000000..7d88f93a04 --- /dev/null +++ b/MediaBrowser.UI/Controller/BaseTheme.cs @@ -0,0 +1,60 @@ +using MediaBrowser.Model.DTO; +using System; +using System.Collections.Generic; +using System.Windows; +using System.Windows.Controls; + +namespace MediaBrowser.UI.Controller +{ + /// + /// Class BaseTheme + /// + public abstract class BaseTheme : IDisposable + { + /// + /// Gets the global resources. + /// + /// IEnumerable{ResourceDictionary}. + public abstract IEnumerable GetGlobalResources(); + + /// + /// Gets the list page. + /// + /// The item. + /// Page. + public abstract Page GetListPage(DtoBaseItem item); + /// + /// Gets the detail page. + /// + /// The item. + /// Page. + public abstract Page GetDetailPage(DtoBaseItem item); + /// + /// Gets the home page. + /// + /// Page. + public abstract Page GetHomePage(); + /// + /// Gets the login page. + /// + /// Page. + public abstract Page GetLoginPage(); + /// + /// Gets the internal player page. + /// + /// Page. + public abstract Page GetInternalPlayerPage(); + + /// + /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. + /// + public virtual void Dispose() + { + } + + /// + /// Displays the weather. + /// + public abstract void DisplayWeather(); + } +} diff --git a/MediaBrowser.UI/Controller/PluginUpdater.cs b/MediaBrowser.UI/Controller/PluginUpdater.cs index d9fa48749a..55a82dc277 100644 --- a/MediaBrowser.UI/Controller/PluginUpdater.cs +++ b/MediaBrowser.UI/Controller/PluginUpdater.cs @@ -1,231 +1,306 @@ -using MediaBrowser.Common.Logging; -using MediaBrowser.Common.Plugins; -using MediaBrowser.Common.Serialization; -using MediaBrowser.Model.DTO; -using System; -using System.Collections.Generic; -using System.ComponentModel.Composition; -using System.ComponentModel.Composition.Hosting; -using System.IO; -using System.Linq; -using System.Threading.Tasks; - -namespace MediaBrowser.UI.Controller -{ - /// - /// This keeps ui plugin assemblies in sync with plugins installed on the server - /// - public class PluginUpdater - { - /// - /// Gets the list of currently installed UI plugins - /// - [ImportMany(typeof(BasePlugin))] - private IEnumerable CurrentPlugins { get; set; } - - private CompositionContainer CompositionContainer { get; set; } - - public async Task UpdatePlugins() - { - // First load the plugins that are currently installed - ReloadComposableParts(); - - Logger.LogInfo("Downloading list of installed plugins"); - PluginInfo[] allInstalledPlugins = await UIKernel.Instance.ApiClient.GetInstalledPluginsAsync().ConfigureAwait(false); - - IEnumerable uiPlugins = allInstalledPlugins.Where(p => p.DownloadToUI); - - PluginUpdateResult result = new PluginUpdateResult(); - - result.DeletedPlugins = DeleteUninstalledPlugins(uiPlugins); - - await DownloadPluginAssemblies(uiPlugins, result).ConfigureAwait(false); - - // If any new assemblies were downloaded we'll have to reload the CurrentPlugins list - if (result.NewlyInstalledPlugins.Any()) - { - ReloadComposableParts(); - } - - result.UpdatedConfigurations = await DownloadPluginConfigurations(uiPlugins).ConfigureAwait(false); - - CompositionContainer.Dispose(); - - return result; - } - - /// - /// Downloads plugin assemblies from the server, if they need to be installed or updated. - /// - private async Task DownloadPluginAssemblies(IEnumerable uiPlugins, PluginUpdateResult result) - { - List newlyInstalledPlugins = new List(); - List updatedPlugins = new List(); - - // Loop through the list of plugins that are on the server - foreach (PluginInfo pluginInfo in uiPlugins) - { - // See if it is already installed in the UI - BasePlugin installedPlugin = CurrentPlugins.FirstOrDefault(p => p.AssemblyFileName.Equals(pluginInfo.AssemblyFileName, StringComparison.OrdinalIgnoreCase)); - - // Download the plugin if it is not present, or if the current version is out of date - bool downloadPlugin = installedPlugin == null; - - if (installedPlugin != null) - { - Version serverVersion = Version.Parse(pluginInfo.Version); - - downloadPlugin = serverVersion > installedPlugin.Version; - } - - if (downloadPlugin) - { - await DownloadPlugin(pluginInfo).ConfigureAwait(false); - - if (installedPlugin == null) - { - newlyInstalledPlugins.Add(pluginInfo); - } - else - { - updatedPlugins.Add(pluginInfo); - } - } - } - - result.NewlyInstalledPlugins = newlyInstalledPlugins; - result.UpdatedPlugins = updatedPlugins; - } - - /// - /// Downloads plugin configurations from the server. - /// - private async Task> DownloadPluginConfigurations(IEnumerable uiPlugins) - { - List updatedPlugins = new List(); - - // Loop through the list of plugins that are on the server - foreach (PluginInfo pluginInfo in uiPlugins) - { - // See if it is already installed in the UI - BasePlugin installedPlugin = CurrentPlugins.First(p => p.AssemblyFileName.Equals(pluginInfo.AssemblyFileName, StringComparison.OrdinalIgnoreCase)); - - if (installedPlugin.ConfigurationDateLastModified < pluginInfo.ConfigurationDateLastModified) - { - await DownloadPluginConfiguration(installedPlugin, pluginInfo).ConfigureAwait(false); - - updatedPlugins.Add(pluginInfo); - } - } - - return updatedPlugins; - } - - /// - /// Downloads a plugin assembly from the server - /// - private async Task DownloadPlugin(PluginInfo plugin) - { - Logger.LogInfo("Downloading {0} Plugin", plugin.Name); - - string path = Path.Combine(UIKernel.Instance.ApplicationPaths.PluginsPath, plugin.AssemblyFileName); - - // First download to a MemoryStream. This way if the download is cut off, we won't be left with a partial file - using (MemoryStream memoryStream = new MemoryStream()) - { - Stream assemblyStream = await UIKernel.Instance.ApiClient.GetPluginAssemblyAsync(plugin).ConfigureAwait(false); - - await assemblyStream.CopyToAsync(memoryStream).ConfigureAwait(false); - - memoryStream.Position = 0; - - using (FileStream fileStream = new FileStream(path, FileMode.Create)) - { - await memoryStream.CopyToAsync(fileStream).ConfigureAwait(false); - } - } - } - - /// - /// Downloads the latest configuration for a plugin - /// - private async Task DownloadPluginConfiguration(BasePlugin plugin, PluginInfo pluginInfo) - { - Logger.LogInfo("Downloading {0} Configuration", plugin.Name); - - object config = await UIKernel.Instance.ApiClient.GetPluginConfigurationAsync(pluginInfo, plugin.ConfigurationType).ConfigureAwait(false); - - XmlSerializer.SerializeToFile(config, plugin.ConfigurationFilePath); - - File.SetLastWriteTimeUtc(plugin.ConfigurationFilePath, pluginInfo.ConfigurationDateLastModified); - } - - /// - /// Deletes any plugins that have been uninstalled from the server - /// - private IEnumerable DeleteUninstalledPlugins(IEnumerable uiPlugins) - { - var deletedPlugins = new List(); - - foreach (BasePlugin plugin in CurrentPlugins) - { - PluginInfo latest = uiPlugins.FirstOrDefault(p => p.AssemblyFileName.Equals(plugin.AssemblyFileName, StringComparison.OrdinalIgnoreCase)); - - if (latest == null) - { - DeletePlugin(plugin); - - deletedPlugins.Add(plugin.Name); - } - } - - return deletedPlugins; - } - - /// - /// Deletes an installed ui plugin. - /// Leaves config and data behind in the event it is later re-installed - /// - private void DeletePlugin(BasePlugin plugin) - { - Logger.LogInfo("Deleting {0} Plugin", plugin.Name); - - string path = plugin.AssemblyFilePath; - - if (File.Exists(path)) - { - File.Delete(path); - } - } - - /// - /// Re-uses MEF within the kernel to discover installed plugins - /// - private void ReloadComposableParts() - { - if (CompositionContainer != null) - { - CompositionContainer.Dispose(); - } - - CompositionContainer = UIKernel.Instance.GetCompositionContainer(); - - CompositionContainer.ComposeParts(this); - - CompositionContainer.Catalog.Dispose(); - - foreach (BasePlugin plugin in CurrentPlugins) - { - plugin.Initialize(UIKernel.Instance, false); - } - } - } - - public class PluginUpdateResult - { - public IEnumerable DeletedPlugins { get; set; } - public IEnumerable NewlyInstalledPlugins { get; set; } - public IEnumerable UpdatedPlugins { get; set; } - public IEnumerable UpdatedConfigurations { get; set; } - } -} +using MediaBrowser.Common.IO; +using MediaBrowser.Common.Logging; +using MediaBrowser.Model.Net; +using MediaBrowser.Model.Plugins; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Threading.Tasks; + +namespace MediaBrowser.UI.Controller +{ + /// + /// This keeps ui plugin assemblies in sync with plugins installed on the server + /// + public class PluginUpdater + { + /// + /// Updates the plugins. + /// + /// Task{PluginUpdateResult}. + public async Task UpdatePlugins() + { + Logger.LogInfo("Downloading list of installed plugins"); + var allInstalledPlugins = await UIKernel.Instance.ApiClient.GetInstalledPluginsAsync().ConfigureAwait(false); + + var uiPlugins = allInstalledPlugins.Where(p => p.DownloadToUI).ToList(); + + var result = new PluginUpdateResult { }; + + result.DeletedPlugins = DeleteUninstalledPlugins(uiPlugins); + + await DownloadPluginAssemblies(uiPlugins, result).ConfigureAwait(false); + + result.UpdatedConfigurations = await DownloadPluginConfigurations(uiPlugins).ConfigureAwait(false); + + return result; + } + + /// + /// Downloads plugin assemblies from the server, if they need to be installed or updated. + /// + /// The UI plugins. + /// The result. + /// Task. + private async Task DownloadPluginAssemblies(IEnumerable uiPlugins, PluginUpdateResult result) + { + var newlyInstalledPlugins = new List(); + var updatedPlugins = new List(); + + // Loop through the list of plugins that are on the server + foreach (var pluginInfo in uiPlugins) + { + // See if it is already installed in the UI + var currentAssemblyPath = Path.Combine(UIKernel.Instance.ApplicationPaths.PluginsPath, pluginInfo.AssemblyFileName); + + var isPluginInstalled = File.Exists(currentAssemblyPath); + + // Download the plugin if it is not present, or if the current version is out of date + bool downloadPlugin; + + if (!isPluginInstalled) + { + downloadPlugin = true; + Logger.LogInfo("{0} is not installed and needs to be downloaded.", pluginInfo.Name); + } + else + { + var serverVersion = Version.Parse(pluginInfo.Version); + + var fileVersion = FileVersionInfo.GetVersionInfo(currentAssemblyPath).FileVersion ?? string.Empty; + + downloadPlugin = string.IsNullOrEmpty(fileVersion) || Version.Parse(fileVersion) < serverVersion; + + if (downloadPlugin) + { + Logger.LogInfo("{0} has an updated version on the server and needs to be downloaded. Server version: {1}, UI version: {2}", pluginInfo.Name, serverVersion, fileVersion); + } + } + + if (downloadPlugin) + { + if (UIKernel.Instance.ApplicationVersion < Version.Parse(pluginInfo.MinimumRequiredUIVersion)) + { + Logger.LogWarning("Can't download new version of {0} because the application needs to be updated first.", pluginInfo.Name); + continue; + } + + try + { + await DownloadPlugin(pluginInfo).ConfigureAwait(false); + + if (isPluginInstalled) + { + updatedPlugins.Add(pluginInfo); + } + else + { + newlyInstalledPlugins.Add(pluginInfo); + } + } + catch (HttpException ex) + { + Logger.LogException("Error downloading {0} configuration", ex, pluginInfo.Name); + } + catch (IOException ex) + { + Logger.LogException("Error saving plugin assembly for {0}", ex, pluginInfo.Name); + } + } + } + + result.NewlyInstalledPlugins = newlyInstalledPlugins; + result.UpdatedPlugins = updatedPlugins; + } + + /// + /// Downloads plugin configurations from the server. + /// + /// The UI plugins. + /// Task{List{PluginInfo}}. + private async Task> DownloadPluginConfigurations(IEnumerable uiPlugins) + { + var updatedPlugins = new List(); + + // Loop through the list of plugins that are on the server + foreach (var pluginInfo in uiPlugins + .Where(p => UIKernel.Instance.ApplicationVersion >= Version.Parse(p.MinimumRequiredUIVersion))) + { + // See if it is already installed in the UI + var path = Path.Combine(UIKernel.Instance.ApplicationPaths.PluginConfigurationsPath, pluginInfo.ConfigurationFileName); + + var download = false; + + if (!File.Exists(path)) + { + download = true; + Logger.LogInfo("{0} configuration was not found needs to be downloaded.", pluginInfo.Name); + } + else if (File.GetLastWriteTimeUtc(path) < pluginInfo.ConfigurationDateLastModified) + { + download = true; + Logger.LogInfo("{0} has an updated configuration on the server and needs to be downloaded.", pluginInfo.Name); + } + + if (download) + { + if (UIKernel.Instance.ApplicationVersion < Version.Parse(pluginInfo.MinimumRequiredUIVersion)) + { + Logger.LogWarning("Can't download updated configuration of {0} because the application needs to be updated first.", pluginInfo.Name); + continue; + } + + try + { + await DownloadPluginConfiguration(pluginInfo, path).ConfigureAwait(false); + + updatedPlugins.Add(pluginInfo); + } + catch (HttpException ex) + { + Logger.LogException("Error downloading {0} configuration", ex, pluginInfo.Name); + } + catch (IOException ex) + { + Logger.LogException("Error saving plugin configuration to {0}", ex, path); + } + } + } + + return updatedPlugins; + } + + /// + /// Downloads a plugin assembly from the server + /// + /// The plugin. + /// Task. + private async Task DownloadPlugin(PluginInfo plugin) + { + Logger.LogInfo("Downloading {0} Plugin", plugin.Name); + + var path = Path.Combine(UIKernel.Instance.ApplicationPaths.PluginsPath, plugin.AssemblyFileName); + + // First download to a MemoryStream. This way if the download is cut off, we won't be left with a partial file + using (var memoryStream = new MemoryStream()) + { + var assemblyStream = await UIKernel.Instance.ApiClient.GetPluginAssemblyAsync(plugin).ConfigureAwait(false); + + await assemblyStream.CopyToAsync(memoryStream).ConfigureAwait(false); + + memoryStream.Position = 0; + + using (var fileStream = new FileStream(path, FileMode.Create)) + { + await memoryStream.CopyToAsync(fileStream).ConfigureAwait(false); + } + } + } + + /// + /// Downloads the latest configuration for a plugin + /// + /// The plugin info. + /// The path. + /// Task. + private async Task DownloadPluginConfiguration(PluginInfo pluginInfo, string path) + { + Logger.LogInfo("Downloading {0} Configuration", pluginInfo.Name); + + // First download to a MemoryStream. This way if the download is cut off, we won't be left with a partial file + using (var stream = await UIKernel.Instance.ApiClient.GetPluginConfigurationFileAsync(pluginInfo.UniqueId).ConfigureAwait(false)) + { + using (var memoryStream = new MemoryStream()) + { + await stream.CopyToAsync(memoryStream).ConfigureAwait(false); + + memoryStream.Position = 0; + + using (var fs = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.Read, StreamDefaults.DefaultFileStreamBufferSize, true)) + { + await memoryStream.CopyToAsync(fs).ConfigureAwait(false); + } + } + } + + File.SetLastWriteTimeUtc(path, pluginInfo.ConfigurationDateLastModified); + } + + /// + /// Deletes any plugins that have been uninstalled from the server + /// + /// The UI plugins. + /// IEnumerable{System.String}. + private IEnumerable DeleteUninstalledPlugins(IEnumerable uiPlugins) + { + var deletedPlugins = new List(); + + foreach (var plugin in Directory.EnumerateFiles(UIKernel.Instance.ApplicationPaths.PluginsPath, "*.dll", SearchOption.TopDirectoryOnly) + .Select(Path.GetFileName) + .ToList()) + { + var serverPlugin = uiPlugins.FirstOrDefault(p => p.AssemblyFileName.Equals(plugin, StringComparison.OrdinalIgnoreCase)); + + if (serverPlugin == null) + { + try + { + DeletePlugin(plugin); + + deletedPlugins.Add(plugin); + } + catch (IOException ex) + { + Logger.LogException("Error deleting plugin assembly {0}", ex, plugin); + } + } + } + + return deletedPlugins; + } + + /// + /// Deletes an installed ui plugin. + /// Leaves config and data behind in the event it is later re-installed + /// + /// The plugin. + private void DeletePlugin(string plugin) + { + Logger.LogInfo("Deleting {0} Plugin", plugin); + + if (File.Exists(plugin)) + { + File.Delete(plugin); + } + } + } + + /// + /// Class PluginUpdateResult + /// + public class PluginUpdateResult + { + /// + /// Gets or sets the deleted plugins. + /// + /// The deleted plugins. + public IEnumerable DeletedPlugins { get; set; } + /// + /// Gets or sets the newly installed plugins. + /// + /// The newly installed plugins. + public IEnumerable NewlyInstalledPlugins { get; set; } + /// + /// Gets or sets the updated plugins. + /// + /// The updated plugins. + public IEnumerable UpdatedPlugins { get; set; } + /// + /// Gets or sets the updated configurations. + /// + /// The updated configurations. + public IEnumerable UpdatedConfigurations { get; set; } + } +} diff --git a/MediaBrowser.UI/Controller/UIKernel.cs b/MediaBrowser.UI/Controller/UIKernel.cs index ca24b7852a..be313e1536 100644 --- a/MediaBrowser.UI/Controller/UIKernel.cs +++ b/MediaBrowser.UI/Controller/UIKernel.cs @@ -1,97 +1,201 @@ -using MediaBrowser.ApiInteraction; -using MediaBrowser.Common.Kernel; -using MediaBrowser.Model.Configuration; -using MediaBrowser.Model.DTO; -using MediaBrowser.Model.Progress; -using MediaBrowser.UI.Configuration; -using System; -using System.Threading.Tasks; - -namespace MediaBrowser.UI.Controller -{ - /// - /// This controls application logic as well as server interaction within the UI. - /// - public class UIKernel : BaseKernel - { - public static UIKernel Instance { get; private set; } - - public ApiClient ApiClient { get; private set; } - public DtoUser CurrentUser { get; set; } - public ServerConfiguration ServerConfiguration { get; set; } - - public UIKernel() - : base() - { - Instance = this; - } - - public override KernelContext KernelContext - { - get { return KernelContext.Ui; } - } - - /// - /// Give the UI a different url prefix so that they can share the same port, in case they are installed on the same machine. - /// - protected override string HttpServerUrlPrefix - { - get - { - return "http://+:" + Configuration.HttpServerPortNumber + "/mediabrowser/ui/"; - } - } - - /// - /// Performs initializations that can be reloaded at anytime - /// - protected override async Task ReloadInternal(IProgress progress) - { - ReloadApiClient(); - - await new PluginUpdater().UpdatePlugins().ConfigureAwait(false); - - await base.ReloadInternal(progress).ConfigureAwait(false); - } - - /// - /// Updates and installs new plugin assemblies and configurations from the server - /// - protected async Task UpdatePlugins() - { - return await new PluginUpdater().UpdatePlugins().ConfigureAwait(false); - } - - /// - /// Disposes the current ApiClient and creates a new one - /// - private void ReloadApiClient() - { - DisposeApiClient(); - - ApiClient = new ApiClient - { - ServerHostName = Configuration.ServerHostName, - ServerApiPort = Configuration.ServerApiPort - }; - } - - /// - /// Disposes the current ApiClient - /// - private void DisposeApiClient() - { - if (ApiClient != null) - { - ApiClient.Dispose(); - } - } - - public override void Dispose() - { - base.Dispose(); - - DisposeApiClient(); - } - } -} +using System.Net; +using System.Net.Cache; +using System.Net.Http; +using MediaBrowser.ApiInteraction; +using MediaBrowser.Common.Kernel; +using MediaBrowser.Common.Logging; +using MediaBrowser.Model.Connectivity; +using MediaBrowser.Model.Net; +using MediaBrowser.UI.Configuration; +using MediaBrowser.UI.Playback; +using System; +using System.Collections.Generic; +using System.ComponentModel.Composition; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Reflection; +using System.Threading.Tasks; + +namespace MediaBrowser.UI.Controller +{ + /// + /// This controls application logic as well as server interaction within the UI. + /// + public class UIKernel : BaseKernel + { + /// + /// Gets the instance. + /// + /// The instance. + public static UIKernel Instance { get; private set; } + + /// + /// Gets the API client. + /// + /// The API client. + public ApiClient ApiClient { get; private set; } + + /// + /// Gets the playback manager. + /// + /// The playback manager. + public PlaybackManager PlaybackManager { get; private set; } + + /// + /// Initializes a new instance of the class. + /// + public UIKernel() + : base() + { + Instance = this; + } + + /// + /// Gets the media players. + /// + /// The media players. + [ImportMany(typeof(BaseMediaPlayer))] + public IEnumerable MediaPlayers { get; private set; } + + /// + /// Gets the list of currently loaded themes + /// + /// The themes. + [ImportMany(typeof(BaseTheme))] + public IEnumerable Themes { get; private set; } + + /// + /// Gets the kernel context. + /// + /// The kernel context. + public override KernelContext KernelContext + { + get { return KernelContext.Ui; } + } + + /// + /// Gets the UDP server port number. + /// + /// The UDP server port number. + public override int UdpServerPortNumber + { + get { return 7360; } + } + + /// + /// Give the UI a different url prefix so that they can share the same port, in case they are installed on the same machine. + /// + /// The HTTP server URL prefix. + public override string HttpServerUrlPrefix + { + get + { + return "http://+:" + Configuration.HttpServerPortNumber + "/mediabrowserui/"; + } + } + + /// + /// Reload api client and update plugins after loading configuration + /// + /// Task. + protected override async Task OnConfigurationLoaded() + { + ReloadApiClient(); + + try + { + await new PluginUpdater().UpdatePlugins().ConfigureAwait(false); + } + catch (HttpException ex) + { + Logger.ErrorException("Error updating plugins from the server", ex); + } + } + + /// + /// Disposes the current ApiClient and creates a new one + /// + private void ReloadApiClient() + { + DisposeApiClient(); + + var logger = LogManager.GetLogger("ApiClient"); + + ApiClient = new ApiClient(logger, new AsyncHttpClient(new WebRequestHandler + { + AutomaticDecompression = DecompressionMethods.Deflate, + CachePolicy = new RequestCachePolicy(RequestCacheLevel.Revalidate) + })) + { + ServerHostName = Configuration.ServerHostName, + ServerApiPort = Configuration.ServerApiPort, + ClientType = ClientType.Pc, + DeviceName = Environment.MachineName, + SerializationFormat = SerializationFormats.Json + }; + } + + /// + /// Reloads the internal. + /// + /// Task. + protected override Task ReloadInternal() + { + PlaybackManager = new PlaybackManager(this); + + return base.ReloadInternal(); + } + + /// + /// Gets the composable part assemblies. + /// + /// IEnumerable{Assembly}. + protected override IEnumerable GetComposablePartAssemblies() + { + var runningDirectory = Path.GetDirectoryName(Process.GetCurrentProcess().MainModule.FileName); + + return base.GetComposablePartAssemblies().Concat(new[] { + + Assembly.Load(File.ReadAllBytes(Path.Combine(runningDirectory, "MediaBrowser.Plugins.DefaultTheme.dll"))) + }); + } + + /// + /// Called when [composable parts loaded]. + /// + /// Task. + protected override async Task OnComposablePartsLoaded() + { + await base.OnComposablePartsLoaded().ConfigureAwait(false); + + // Once plugins have loaded give the api a reference to our protobuf serializer + DataSerializer.DynamicSerializer = ProtobufSerializer.TypeModel; + } + + /// + /// Disposes the current ApiClient + /// + private void DisposeApiClient() + { + if (ApiClient != null) + { + ApiClient.Dispose(); + } + } + + /// + /// Releases unmanaged and - optionally - managed resources. + /// + /// true to release both managed and unmanaged resources; false to release only unmanaged resources. + protected override void Dispose(bool dispose) + { + if (dispose) + { + DisposeApiClient(); + } + + base.Dispose(dispose); + } + } +} -- cgit v1.2.3