diff --git a/MatterControlLib/Library/Providers/GitHub/GitHubContainer.cs b/MatterControlLib/Library/Providers/GitHub/GitHubContainer.cs index e79a4f400..8c9893bb6 100644 --- a/MatterControlLib/Library/Providers/GitHub/GitHubContainer.cs +++ b/MatterControlLib/Library/Providers/GitHub/GitHubContainer.cs @@ -64,6 +64,8 @@ namespace MatterHackers.MatterControl.Library public string RepoDirectory { get; } + private object locker = new object(); + public GitHubContainer(string containerName, string account, string repositor, string repoDirectory) { this.ChildContainers = new List(); @@ -74,40 +76,25 @@ namespace MatterHackers.MatterControl.Library this.RepoDirectory = repoDirectory; } - public override async void Load() - { - try - { - await GetRepo(); - } - catch - { - // show an error - } - - OnContentChanged(); - } - - // Get all files from a repo - public async Task GetRepo() - { - var client = new HttpClient(); - await ReadDirectory("root", - client, - $"https://api.github.com/repos/{Account}/{Repository}/contents/{RepoDirectory}"); - client.Dispose(); - } - - private async Task ReadDirectory(string name, HttpClient client, string uri) + public override void Load() { + var uri = $"https://api.github.com/repos/{Account}/{Repository}/contents/{RepoDirectory}"; // get the directory contents - var request = new HttpRequestMessage(HttpMethod.Get, uri); - AddCromeHeaders(request); + WebCache.RetrieveText(uri, + (content) => + { + lock (locker) + { + ParseJson(content); + } + }, + false, + AddCromeHeaders); + } + private void ParseJson(string jsonStr) + { // parse result - HttpResponseMessage response = client.SendAsync(request).Result; - string jsonStr = response.Content.ReadAsStringAsync().Result; - response.Dispose(); FileInfo[] dirContents = JsonConvert.DeserializeObject(jsonStr); // read in data @@ -136,7 +123,7 @@ namespace MatterHackers.MatterControl.Library } } - this.ChildContainers.Sort((a, b) => a.Name.CompareTo(b.Name)); + OnContentChanged(); } public static void AddCromeHeaders(HttpRequestMessage request) @@ -246,27 +233,8 @@ namespace MatterHackers.MatterControl.Library public override async Task GetContainer(Action reportProgress) { - try - { - // download the .library file - var downLoadUrl = new HttpRequestMessage(HttpMethod.Get, path); - GitHubContainer.AddCromeHeaders(downLoadUrl); - - using (var client = new HttpClient()) - { - using (HttpResponseMessage contentResponse = await client.SendAsync(downLoadUrl)) - { - var content = await contentResponse.Content.ReadAsStringAsync(); - // parse it - return await LibraryJsonFile.ContainerFromJson(Name, content).GetContainer(null); - } - } - } - catch - { - } - - return null; + var content = WebCache.GetCachedText(path, false, AddCromeHeaders); + return await LibraryJsonFile.ContainerFromJson(Name, content).GetContainer(null); } } } diff --git a/MatterControlLib/Utilities/WebUtilities/WebCache.cs b/MatterControlLib/Utilities/WebUtilities/WebCache.cs index 75fa6ddb2..54896a7c6 100644 --- a/MatterControlLib/Utilities/WebUtilities/WebCache.cs +++ b/MatterControlLib/Utilities/WebUtilities/WebCache.cs @@ -32,6 +32,7 @@ using System.Collections.Generic; using System.IO; using System.Net; using System.Net.Http; +using System.Threading; using System.Threading.Tasks; using MatterHackers.Agg; using MatterHackers.Agg.Image; @@ -216,11 +217,68 @@ namespace MatterHackers.MatterControl } } - public static void RetrieveText(string uriToLoad, Action updateResult) + /// + /// Return the first result that can be found (usually the cache). Wait up to 5 seconds to populate the cache + /// if it does not exist. + /// + /// + /// + /// + /// + public static string GetCachedText(string uriToLoad, + bool addToAppCache = true, + Action addHeaders = null) + { + string results = null; + WebCache.RetrieveText(uriToLoad, + (content) => + { + results = content; + }, + false, + addHeaders); + + var startTime = UiThread.CurrentTimerMs; + // wait up to 5 seconds for a response + while (results == null + && UiThread.CurrentTimerMs < startTime + 5000) + { + Thread.Sleep(10); + } + + return results; + } + + /// + /// Retrieve text from a url async, but first return any existing cache of the text synchronously + /// + /// The web path to find the text, will also be used as the cache key + /// A function to call when the text is received if it is different than the cache. + /// Add the results to a directory that can be copied into the main distribution, + /// or add them to a directory that is only for the local machine. + public static void RetrieveText(string uriToLoad, + Action updateResult, + bool addToAppCache = true, + Action addHeaders = null) + { + if (addToAppCache) + { + RetrieveText(uriToLoad, "TextWebCache", updateResult, addHeaders); + } + else + { + RetrieveText(uriToLoad, "Text", updateResult, addHeaders); + } + } + + private static void RetrieveText(string uriToLoad, + string cacheFolder, + Action updateResult, + Action addHeaders = null) { var longHash = uriToLoad.GetLongHashCode(); - var appDataFileName = ApplicationController.CacheablePath("TextWebCache", longHash.ToString() + ".txt"); + var appDataFileName = ApplicationController.CacheablePath(cacheFolder, longHash.ToString() + ".txt"); string fileText = null; // first try the cache in the users applications folder @@ -237,7 +295,7 @@ namespace MatterHackers.MatterControl } else // We could not find it in the application cache. Check if it is in static data. { - var staticDataPath = Path.Combine("TextWebCache", longHash.ToString() + ".txt"); + var staticDataPath = Path.Combine(cacheFolder, longHash.ToString() + ".txt"); if (AggContext.StaticData.FileExists(staticDataPath)) { @@ -255,13 +313,20 @@ namespace MatterHackers.MatterControl // whether we find it or not check the web for the latest version Task.Run(async () => { - var client = new HttpClient(); - var text = await client.GetStringAsync(uriToLoad); - if (!string.IsNullOrEmpty(text) - && text != fileText) + var requestMessage = new HttpRequestMessage(HttpMethod.Get, uriToLoad); + addHeaders?.Invoke(requestMessage); + using (var client = new HttpClient()) { - File.WriteAllText(appDataFileName, text); - updateResult?.Invoke(text); + using (HttpResponseMessage response = await client.SendAsync(requestMessage)) + { + var text = await response.Content.ReadAsStringAsync(); + if (!string.IsNullOrEmpty(text) + && text != fileText) + { + File.WriteAllText(appDataFileName, text); + updateResult?.Invoke(text); + } + } } }); }