Skip to content

Commit cd9196b

Browse files
committed
feature: supports get avatar from avatars.githubusercontent.com
* move all images to `src/Resources/Images` folder
1 parent 1729a64 commit cd9196b

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+71
-49
lines changed

src/Models/AvatarManager.cs

Lines changed: 57 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,26 @@
11
using System;
22
using System.Collections.Generic;
3+
using System.Globalization;
34
using System.IO;
45
using System.Net.Http;
6+
using System.Security.Cryptography;
7+
using System.Text;
8+
using System.Text.RegularExpressions;
59
using System.Threading;
610
using System.Threading.Tasks;
711

812
using Avalonia.Media.Imaging;
13+
using Avalonia.Platform;
914
using Avalonia.Threading;
1015

1116
namespace SourceGit.Models
1217
{
1318
public interface IAvatarHost
1419
{
15-
void OnAvatarResourceChanged(string md5);
20+
void OnAvatarResourceChanged(string email);
1621
}
1722

18-
public static class AvatarManager
23+
public static partial class AvatarManager
1924
{
2025
public static string SelectedServer
2126
{
@@ -33,29 +38,35 @@ static AvatarManager()
3338
{
3439
while (true)
3540
{
36-
var md5 = null as string;
41+
var email = null as string;
3742

3843
lock (_synclock)
3944
{
4045
foreach (var one in _requesting)
4146
{
42-
md5 = one;
47+
email = one;
4348
break;
4449
}
4550
}
4651

47-
if (md5 == null)
52+
if (email == null)
4853
{
4954
Thread.Sleep(100);
5055
continue;
5156
}
5257

58+
var md5 = GetEmailHash(email);
59+
var matchGithubUser = REG_GITHUB_USER_EMAIL().Match(email);
60+
var url = matchGithubUser.Success ?
61+
$"https://avatars.githubusercontent.com/{matchGithubUser.Groups[2].Value}" :
62+
$"{SelectedServer}{md5}?d=404";
63+
5364
var localFile = Path.Combine(_storePath, md5);
5465
var img = null as Bitmap;
5566
try
5667
{
5768
var client = new HttpClient() { Timeout = TimeSpan.FromSeconds(2) };
58-
var task = client.GetAsync($"{SelectedServer}{md5}?d=404");
69+
var task = client.GetAsync(url);
5970
task.Wait();
6071

6172
var rsp = task.Result;
@@ -82,13 +93,13 @@ static AvatarManager()
8293

8394
lock (_synclock)
8495
{
85-
_requesting.Remove(md5);
96+
_requesting.Remove(email);
8697
}
8798

8899
Dispatcher.UIThread.InvokeAsync(() =>
89100
{
90-
_resources[md5] = img;
91-
NotifyResourceChanged(md5);
101+
_resources[email] = img;
102+
NotifyResourceChanged(email);
92103
});
93104
}
94105
});
@@ -104,33 +115,44 @@ public static void Unsubscribe(IAvatarHost host)
104115
_avatars.Remove(host);
105116
}
106117

107-
public static Bitmap Request(string md5, bool forceRefetch = false)
118+
public static Bitmap Request(string email, bool forceRefetch)
108119
{
120+
if (email.Equals("[email protected]", StringComparison.Ordinal))
121+
{
122+
if (_githubEmailAvatar == null)
123+
{
124+
var icon = AssetLoader.Open(new Uri($"avares://SourceGit/Resources/Images/github.png", UriKind.RelativeOrAbsolute));
125+
_githubEmailAvatar = new Bitmap(icon);
126+
}
127+
128+
return _githubEmailAvatar;
129+
}
130+
109131
if (forceRefetch)
110132
{
111-
if (_resources.ContainsKey(md5))
112-
_resources.Remove(md5);
133+
if (_resources.ContainsKey(email))
134+
_resources.Remove(email);
113135

114-
var localFile = Path.Combine(_storePath, md5);
136+
var localFile = Path.Combine(_storePath, GetEmailHash(email));
115137
if (File.Exists(localFile))
116138
File.Delete(localFile);
117139

118-
NotifyResourceChanged(md5);
140+
NotifyResourceChanged(email);
119141
}
120142
else
121143
{
122-
if (_resources.TryGetValue(md5, out var value))
144+
if (_resources.TryGetValue(email, out var value))
123145
return value;
124146

125-
var localFile = Path.Combine(_storePath, md5);
147+
var localFile = Path.Combine(_storePath, GetEmailHash(email));
126148
if (File.Exists(localFile))
127149
{
128150
try
129151
{
130152
using (var stream = File.OpenRead(localFile))
131153
{
132154
var img = Bitmap.DecodeToWidth(stream, 128);
133-
_resources.Add(md5, img);
155+
_resources.Add(email, img);
134156
return img;
135157
}
136158
}
@@ -143,18 +165,28 @@ public static Bitmap Request(string md5, bool forceRefetch = false)
143165

144166
lock (_synclock)
145167
{
146-
if (!_requesting.Contains(md5))
147-
_requesting.Add(md5);
168+
if (!_requesting.Contains(email))
169+
_requesting.Add(email);
148170
}
149171

150172
return null;
151173
}
152174

153-
private static void NotifyResourceChanged(string md5)
175+
private static string GetEmailHash(string email)
176+
{
177+
var lowered = email.ToLower(CultureInfo.CurrentCulture).Trim();
178+
var hash = MD5.Create().ComputeHash(Encoding.Default.GetBytes(lowered));
179+
var builder = new StringBuilder();
180+
foreach (var c in hash)
181+
builder.Append(c.ToString("x2"));
182+
return builder.ToString();
183+
}
184+
185+
private static void NotifyResourceChanged(string email)
154186
{
155187
foreach (var avatar in _avatars)
156188
{
157-
avatar.OnAvatarResourceChanged(md5);
189+
avatar.OnAvatarResourceChanged(email);
158190
}
159191
}
160192

@@ -163,5 +195,9 @@ private static void NotifyResourceChanged(string md5)
163195
private static readonly List<IAvatarHost> _avatars = new List<IAvatarHost>();
164196
private static readonly Dictionary<string, Bitmap> _resources = new Dictionary<string, Bitmap>();
165197
private static readonly HashSet<string> _requesting = new HashSet<string>();
198+
199+
[GeneratedRegex(@"^(?:(\d+)\+)?(.+?)@users\.noreply\.github\.com$")]
200+
private static partial Regex REG_GITHUB_USER_EMAIL();
201+
private static Bitmap _githubEmailAvatar = null;
166202
}
167203
}

src/Models/ExternalMerger.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ public Bitmap IconImage
2020
{
2121
get
2222
{
23-
var icon = AssetLoader.Open(new Uri($"avares://SourceGit/Resources/ExternalToolIcons/{Icon}.png", UriKind.RelativeOrAbsolute));
23+
var icon = AssetLoader.Open(new Uri($"avares://SourceGit/Resources/Images/ExternalToolIcons/{Icon}.png", UriKind.RelativeOrAbsolute));
2424
return new Bitmap(icon);
2525
}
2626
}

src/Models/ExternalTool.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ public ExternalTool(string name, string icon, string executable, string openCmdA
2525

2626
try
2727
{
28-
var asset = AssetLoader.Open(new Uri($"avares://SourceGit/Resources/ExternalToolIcons/{icon}.png",
28+
var asset = AssetLoader.Open(new Uri($"avares://SourceGit/Resources/Images/ExternalToolIcons/{icon}.png",
2929
UriKind.RelativeOrAbsolute));
3030
IconImage = new Bitmap(asset);
3131
}

0 commit comments

Comments
 (0)