11using System ;
2+ using System . Collections . Generic ;
23using System . Globalization ;
34using System . IO ;
45using System . Security . Cryptography ;
56using System . Text ;
67
78using Avalonia ;
89using Avalonia . Controls ;
10+ using Avalonia . Data ;
911using Avalonia . Interactivity ;
1012using Avalonia . Media ;
1113using Avalonia . Media . Imaging ;
@@ -24,9 +26,25 @@ public Models.User User
2426 set => SetValue ( UserProperty , value ) ;
2527 }
2628
29+ public static readonly StyledProperty < bool > UseGitHubStyleAvatarProperty =
30+ AvaloniaProperty . Register < Avatar , bool > ( nameof ( UseGitHubStyleAvatar ) ) ;
31+
32+ public bool UseGitHubStyleAvatar
33+ {
34+ get => GetValue ( UseGitHubStyleAvatarProperty ) ;
35+ set => SetValue ( UseGitHubStyleAvatarProperty , value ) ;
36+ }
37+
2738 public Avatar ( )
2839 {
2940 RenderOptions . SetBitmapInterpolationMode ( this , BitmapInterpolationMode . HighQuality ) ;
41+
42+ this . Bind ( UseGitHubStyleAvatarProperty , new Binding ( )
43+ {
44+ Mode = BindingMode . OneWay ,
45+ Source = ViewModels . Preferences . Instance ,
46+ Path = "UseGitHubStyleAvatar"
47+ } ) ;
3048 }
3149
3250 public override void Render ( DrawingContext context )
@@ -42,6 +60,34 @@ public override void Render(DrawingContext context)
4260 {
4361 context . DrawImage ( _img , rect ) ;
4462 }
63+ else if ( ! UseGitHubStyleAvatar )
64+ {
65+ var fallback = GetFallbackString ( User . Name ) ;
66+ var typeface = new Typeface ( "fonts:SourceGit#JetBrains Mono" ) ;
67+ var label = new FormattedText (
68+ fallback ,
69+ CultureInfo . CurrentCulture ,
70+ FlowDirection . LeftToRight ,
71+ typeface ,
72+ Bounds . Width * 0.65 ,
73+ Brushes . White ) ;
74+
75+ var chars = fallback . ToCharArray ( ) ;
76+ var sum = 0 ;
77+ foreach ( var c in chars )
78+ sum += Math . Abs ( c ) ;
79+
80+ var bg = new LinearGradientBrush ( )
81+ {
82+ GradientStops = FALLBACK_GRADIENTS [ sum % FALLBACK_GRADIENTS . Length ] ,
83+ StartPoint = new RelativePoint ( 0 , 0 , RelativeUnit . Relative ) ,
84+ EndPoint = new RelativePoint ( 0 , 1 , RelativeUnit . Relative ) ,
85+ } ;
86+
87+ Point textOrigin = new Point ( ( Bounds . Width - label . Width ) * 0.5 , ( Bounds . Height - label . Height ) * 0.5 ) ;
88+ context . DrawRectangle ( bg , null , new Rect ( 0 , 0 , Bounds . Width , Bounds . Height ) , corner , corner ) ;
89+ context . DrawText ( label , textOrigin ) ;
90+ }
4591 else
4692 {
4793 context . DrawRectangle ( Brushes . White , new Pen ( new SolidColorBrush ( Colors . Black , 0.3f ) , 0.65f ) , rect , corner , corner ) ;
@@ -130,6 +176,11 @@ protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs chang
130176 _img = Models . AvatarManager . Instance . Request ( User . Email , false ) ;
131177 InvalidateVisual ( ) ;
132178 }
179+ else if ( change . Property == UseGitHubStyleAvatarProperty )
180+ {
181+ if ( _img == null )
182+ InvalidateVisual ( ) ;
183+ }
133184 }
134185
135186 private void OnContextRequested ( object sender , ContextRequestedEventArgs e )
@@ -220,6 +271,30 @@ private void OnContextRequested(object sender, ContextRequestedEventArgs e)
220271 menu . Open ( this ) ;
221272 }
222273
274+ private string GetFallbackString ( string name )
275+ {
276+ if ( string . IsNullOrWhiteSpace ( name ) )
277+ return "?" ;
278+
279+ var parts = name . Split ( ' ' , StringSplitOptions . RemoveEmptyEntries ) ;
280+ var chars = new List < char > ( ) ;
281+ foreach ( var part in parts )
282+ chars . Add ( part [ 0 ] ) ;
283+
284+ if ( chars . Count >= 2 && char . IsAsciiLetterOrDigit ( chars [ 0 ] ) && char . IsAsciiLetterOrDigit ( chars [ ^ 1 ] ) )
285+ return string . Format ( "{0}{1}" , chars [ 0 ] , chars [ ^ 1 ] ) ;
286+
287+ return name . Substring ( 0 , 1 ) ;
288+ }
289+
290+ private static readonly GradientStops [ ] FALLBACK_GRADIENTS = [
291+ new GradientStops ( ) { new GradientStop ( Colors . Orange , 0 ) , new GradientStop ( Color . FromRgb ( 255 , 213 , 134 ) , 1 ) } ,
292+ new GradientStops ( ) { new GradientStop ( Colors . DodgerBlue , 0 ) , new GradientStop ( Colors . LightSkyBlue , 1 ) } ,
293+ new GradientStops ( ) { new GradientStop ( Colors . LimeGreen , 0 ) , new GradientStop ( Color . FromRgb ( 124 , 241 , 124 ) , 1 ) } ,
294+ new GradientStops ( ) { new GradientStop ( Colors . Orchid , 0 ) , new GradientStop ( Color . FromRgb ( 248 , 161 , 245 ) , 1 ) } ,
295+ new GradientStops ( ) { new GradientStop ( Colors . Tomato , 0 ) , new GradientStop ( Color . FromRgb ( 252 , 165 , 150 ) , 1 ) } ,
296+ ] ;
297+
223298 private Bitmap _img = null ;
224299 }
225300}
0 commit comments