diff --git a/PCK-Studio/Forms/Editor/LOCEditor.resx b/PCK-Studio/Forms/Editor/LOCEditor.resx
index 25a5f709..67350c15 100644
--- a/PCK-Studio/Forms/Editor/LOCEditor.resx
+++ b/PCK-Studio/Forms/Editor/LOCEditor.resx
@@ -121,15 +121,6 @@
17, 17
-
- 163, 48
-
-
- contextMenuStrip1
-
-
- System.Windows.Forms.ContextMenuStrip, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
162, 22
@@ -142,18 +133,18 @@
Delete Display ID
+
+ 163, 48
+
+
+ contextMenuStrip1
+
+
+ System.Windows.Forms.ContextMenuStrip, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
172, 17
-
- 173, 48
-
-
- GridContextMenu
-
-
- MetroFramework.Controls.MetroContextMenu, MetroFramework, Version=1.4.0.0, Culture=neutral, PublicKeyToken=5f91a84759bf584a
-
172, 22
@@ -166,6 +157,15 @@
Remove Language
+
+ 173, 48
+
+
+ GridContextMenu
+
+
+ MetroFramework.Controls.MetroContextMenu, MetroFramework, Version=1.4.0.0, Culture=neutral, PublicKeyToken=5f91a84759bf584a
+
321, 17
@@ -333,6 +333,12 @@
<?xml version="1.0" encoding="utf-16"?><TableLayoutSettings><Controls><Control Name="buttonReplaceAll" Row="1" RowSpan="1" Column="2" ColumnSpan="1" /><Control Name="dataGridViewLocEntryData" Row="2" RowSpan="1" Column="1" ColumnSpan="2" /><Control Name="menuStrip" Row="0" RowSpan="1" Column="0" ColumnSpan="3" /><Control Name="textBoxReplaceAll" Row="1" RowSpan="1" Column="1" ColumnSpan="1" /><Control Name="treeViewLocKeys" Row="1" RowSpan="2" Column="0" ColumnSpan="1" /></Controls><Columns Styles="Absolute,350,Percent,100,AutoSize,0" /><Rows Styles="Absolute,23,AutoSize,0,Percent,100,Absolute,20" /></TableLayoutSettings>
+
+ 98, 22
+
+
+ Save
+
37, 19
@@ -360,12 +366,6 @@
2
-
- 180, 22
-
-
- Save
-
True
diff --git a/PCK-Studio/MainForm.resx b/PCK-Studio/MainForm.resx
index 847b3f98..8e3a6fd5 100644
--- a/PCK-Studio/MainForm.resx
+++ b/PCK-Studio/MainForm.resx
@@ -1318,7 +1318,7 @@
False
- 180, 22
+ 160, 22
Full Box Support
@@ -1571,7 +1571,7 @@
- 180, 22
+ 161, 22
Pck Manager
@@ -1589,7 +1589,7 @@
Binka -> Wav
- 180, 22
+ 161, 22
Audio Converter
@@ -4025,7 +4025,7 @@
True
- 1014, 14
+ 1014, 13
4, 3, 4, 3
diff --git a/PCK-Studio/ToolboxItems/GithubUserPanel.cs b/PCK-Studio/ToolboxItems/GithubUserPanel.cs
index e6fde8e5..78cdce22 100644
--- a/PCK-Studio/ToolboxItems/GithubUserPanel.cs
+++ b/PCK-Studio/ToolboxItems/GithubUserPanel.cs
@@ -42,23 +42,50 @@ namespace PckStudio.ToolboxItems
private void LoadAuthor()
{
- // TODO: find a better way to check if the avatar has changed since last cache.
- string cacheKey = Convert.ToBase64String(Encoding.Default.GetBytes(_contributor.AvatarUrl));
+ // This should fix avatars not updating when changed on GitHub :3
+ // Cache by stable user id, not by URL
+ string cacheKey = $"gh-avatar-{_contributor.Id}";
+ string cachedPath = ApplicationScope.DataCacher.GetCachedFilepath(cacheKey);
- if (!ApplicationScope.DataCacher.HasFileCached(cacheKey))
+ // Refresh avatars periodically
+ bool needsRefresh = true;
+ if (ApplicationScope.DataCacher.HasFileCached(cacheKey))
+ {
+ try
+ {
+ var age = DateTime.UtcNow - File.GetLastWriteTimeUtc(cachedPath);
+ needsRefresh = age > TimeSpan.FromDays(1); // refresh daily
+ }
+ catch
+ {
+ needsRefresh = true;
+ }
+ }
+ if (needsRefresh)
{
using (WebClient webClient = new WebClient())
{
- Stream avatarImgStream = webClient.OpenRead(_contributor.AvatarUrl);
- MemoryStream ms = new MemoryStream();
- new Bitmap(avatarImgStream).Save(ms, ImageFormat.Png);
- avatarImgStream.Flush();
- avatarImgStream.Dispose();
- ApplicationScope.DataCacher.Cache(ms.ToArray(), cacheKey);
+ webClient.Headers.Add(HttpRequestHeader.CacheControl, "no-cache");
+ webClient.Headers.Add(HttpRequestHeader.Pragma, "no-cache");
+ webClient.Headers.Add(HttpRequestHeader.UserAgent, "PckStudio");
+
+ string url = _contributor.AvatarUrl;
+ string sep = url.Contains("?") ? "&" : "?";
+ string fetchUrl = url + sep + "cb=" + DateTimeOffset.UtcNow.ToUnixTimeSeconds();
+
+ byte[] bytes = webClient.DownloadData(fetchUrl);
+ ApplicationScope.DataCacher.Cache(bytes, cacheKey);
+ cachedPath = ApplicationScope.DataCacher.GetCachedFilepath(cacheKey);
}
}
- Image avatarUserImg = Image.FromFile(ApplicationScope.DataCacher.GetCachedFilepath(cacheKey));
+ // Load without locking the file on disk
+ Image avatarUserImg;
+ using (var fs = new FileStream(cachedPath, System.IO.FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
+ using (var temp = Image.FromStream(fs))
+ {
+ avatarUserImg = (Image)temp.Clone();
+ }
Action setUiElements = () =>
{