Skip to content

Commit ae2de99

Browse files
committed
Added better error reporting for setting a user image url and added feedback within the config window
1 parent e2d5e0e commit ae2de99

File tree

4 files changed

+54
-14
lines changed

4 files changed

+54
-14
lines changed

TeamCoding/Options/OptionsPage.xaml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,10 @@
1212
<Grid>
1313
<TextBox x:Name="txtUsername" Margin="111,10,109,0" Height="26" VerticalAlignment="Top" Text="{Binding Username, Mode=TwoWay}" ToolTip="Set a custom username. Blank to auto-calculate" AutomationProperties.LabeledBy="{Binding ElementName=lblUsername, Mode=OneWay}"/>
1414
<Label x:Name="lblUsername" Content="Username" HorizontalAlignment="Left" VerticalAlignment="Top" Target="{Binding ElementName=txtUsername, Mode=OneWay}" Margin="0,10,0,0"/>
15-
<TextBox x:Name="txtUserImageUrl" Margin="111,44,0,0" Height="23" VerticalAlignment="Top" Text="{Binding UserImageUrl}" ToolTip="Set a custom image url. Blank to auto-calculate" AutomationProperties.LabeledBy="{Binding ElementName=lblUserImageUrl, Mode=OneWay}"/>
15+
<TextBox x:Name="txtUserImageUrl" Margin="111,44,28,0" Height="23" VerticalAlignment="Top" Text="{Binding UserImageUrl}" ToolTip="Set a custom image url. Blank to auto-calculate" AutomationProperties.LabeledBy="{Binding ElementName=lblUserImageUrl, Mode=OneWay}"/>
16+
<Viewbox Stretch="Uniform" Margin="0,44,0,0" HorizontalAlignment="Right" Width="23" Height="23" VerticalAlignment="Top">
17+
<TextBlock x:Name="tbUserImageUrl" />
18+
</Viewbox>
1619
<Label x:Name="lblUserImageUrl" Content="User Url" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="0,41,0,0" Target="{Binding ElementName=txtUserImageUrl, Mode=OneWay}"/>
1720
<ComboBox x:Name="txtUserTabDisplay" Margin="111,72,0,0" Height="23" VerticalAlignment="Top" ItemsSource="{Binding UserDisplaySettings}" SelectedValue="{Binding UserTabDisplay}" ToolTip="How to display other users in document tabs." AutomationProperties.LabeledBy="{Binding ElementName=lblUserTabDisplay, Mode=OneWay}"/>
1821
<Label x:Name="lblUserTabDisplay" Content="User Tab Display" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="0,69,0,0" Target="{Binding ElementName=txtUserTabDisplay, Mode=OneWay}"/>

TeamCoding/Options/OptionsPage.xaml.cs

Lines changed: 33 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -46,21 +46,31 @@ public OptionsPage(OptionPageGrid optionPageGrid)
4646
comboBox.LostKeyboardFocus += ComboBox_LostKeyboardFocus;
4747
}
4848

49+
string bindingPath;
4950
foreach(var textBox in grpPersistence.FindChildren<TextBox>())
5051
{
51-
var bindingPath = (textBox).GetBindingExpression(TextBox.TextProperty)?.ParentBinding?.Path?.Path;
52+
bindingPath = textBox.GetBindingExpression(TextBox.TextProperty)?.ParentBinding?.Path?.Path;
5253

5354
if(bindingPath != null)
5455
{
5556
TextBoxIsValidTaskCancelSources.Add(textBox, new CancellationTokenSource());
5657
textBox.LostKeyboardFocus += PersistencePropertyBoundTextBox_KeyboardLostFocus;
57-
textBox.TextChanged += PersistencePropertyBoundTextBox_TextChanged;
58+
textBox.TextChanged += PropertyBoundTextBox_TextChanged;
5859
}
5960
}
6061

62+
bindingPath = txtUserImageUrl.GetBindingExpression(TextBox.TextProperty)?.ParentBinding?.Path?.Path;
63+
64+
if (bindingPath != null)
65+
{
66+
TextBoxIsValidTaskCancelSources.Add(txtUserImageUrl, new CancellationTokenSource());
67+
txtUserImageUrl.LostKeyboardFocus += UserPropertyBoundTextBox_KeyboardLostFocus;
68+
txtUserImageUrl.TextChanged += PropertyBoundTextBox_TextChanged;
69+
}
70+
6171
Loaded += OptionsPage_Loaded;
6272
}
63-
private void PersistencePropertyBoundTextBox_TextChanged(object sender, TextChangedEventArgs e)
73+
private void PropertyBoundTextBox_TextChanged(object sender, TextChangedEventArgs e)
6474
{
6575
var textBox = (TextBox)sender;
6676
var bindingPath = textBox.GetBindingExpression(TextBox.TextProperty).ParentBinding.Path.Path;
@@ -72,10 +82,15 @@ private void PersistencePropertyBoundTextBox_TextChanged(object sender, TextChan
7282
private void PersistencePropertyBoundTextBox_KeyboardLostFocus(object sender, KeyboardFocusChangedEventArgs e)
7383
{
7484
var textBox = (TextBox)sender;
75-
ReEvaluateTextboxSetting(textBox);
85+
ReEvaluateTextboxSetting(textBox, TeamCodingPackage.Current.Settings.SharedSettings);
86+
}
87+
private void UserPropertyBoundTextBox_KeyboardLostFocus(object sender, KeyboardFocusChangedEventArgs e)
88+
{
89+
var textBox = (TextBox)sender;
90+
ReEvaluateTextboxSetting(textBox, TeamCodingPackage.Current.Settings.UserSettings);
7691
}
7792

78-
private void ReEvaluateTextboxSetting(TextBox textBox)
93+
private void ReEvaluateTextboxSetting(TextBox textBox, object settingsObject)
7994
{
8095
// Cancel any existing tasks to see if the new setting property is valid (since we're changing it anyway)
8196
TextBoxIsValidTaskCancelSources[textBox].Cancel();
@@ -93,7 +108,7 @@ private void ReEvaluateTextboxSetting(TextBox textBox)
93108
textBlock.Foreground = Brushes.Black;
94109
textBlock.Text = "⏳";
95110
textBlock.ToolTip = "Checking configuration value...";
96-
var settingProperty = (SettingProperty<string>)typeof(SharedSettings).GetField(bindingPath + "Property").GetValue(TeamCodingPackage.Current.Settings.SharedSettings);
111+
var settingProperty = (SettingProperty<string>)settingsObject.GetType().GetField(bindingPath + "Property", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance).GetValue(settingsObject);
97112

98113
// Add a new token to the dictionary to use with this task we're about to create
99114
TextBoxIsValidTaskCancelSources[textBox] = new CancellationTokenSource();
@@ -137,16 +152,26 @@ private void OptionsPage_Loaded(object sender, RoutedEventArgs e)
137152

138153
chkUsingJsonSettings.IsChecked = loadedFromFile;
139154

155+
string bindingPath;
156+
140157
foreach (var textBox in grpPersistence.FindChildren<TextBox>())
141158
{
142-
var bindingPath = textBox.GetBindingExpression(TextBox.TextProperty)?.ParentBinding?.Path?.Path;
159+
bindingPath = textBox.GetBindingExpression(TextBox.TextProperty)?.ParentBinding?.Path?.Path;
143160

144161
if (bindingPath != null)
145162
{
146163
textBox.GetBindingExpression(TextBox.TextProperty).UpdateTarget();
147-
ReEvaluateTextboxSetting(textBox);
164+
ReEvaluateTextboxSetting(textBox, TeamCodingPackage.Current.Settings.SharedSettings);
148165
}
149166
}
167+
168+
bindingPath = txtUserImageUrl.GetBindingExpression(TextBox.TextProperty)?.ParentBinding?.Path?.Path;
169+
170+
if (bindingPath != null)
171+
{
172+
txtUserImageUrl.GetBindingExpression(TextBox.TextProperty).UpdateTarget();
173+
ReEvaluateTextboxSetting(txtUserImageUrl, TeamCodingPackage.Current.Settings.UserSettings);
174+
}
150175
}
151176
private void Control_GotKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e)
152177
{

TeamCoding/Options/UserSettings.cs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ public UserSettings()
4848
UsernameProperty = new SettingProperty<string>(this);
4949
UsernameProperty.Changed += (s, e) => TeamCodingPackage.Current.Logger.WriteInformation($"Changing setting {nameof(Username)}: {Username}");
5050

51-
UserImageUrlProperty = new SettingProperty<string>(this);
51+
UserImageUrlProperty = new SettingProperty<string>(this, CheckUserImageUrl);
5252
UserImageUrlProperty.Changed += (s, e) => TeamCodingPackage.Current.Logger.WriteInformation($"Changing setting {nameof(UserImageUrl)}: {UserImageUrl}");
5353

5454
UserCodeDisplayProperty = new SettingProperty<UserDisplaySetting>(this);
@@ -60,5 +60,11 @@ public UserSettings()
6060
ShowAllBranchesProperty = new SettingProperty<bool>(this, null);
6161
ShowAllBranchesProperty.Changed += (s, e) => TeamCodingPackage.Current.Logger.WriteInformation($"Changing setting {nameof(ShowAllBranches)}: {ShowAllBranches}");
6262
}
63+
64+
private async Task<string> CheckUserImageUrl(string imageUrl)
65+
{
66+
var url = await TeamCodingPackage.Current.UserImages.GetImageFromUrl(imageUrl);
67+
return null;
68+
}
6369
}
6470
}

TeamCoding/VisualStudio/UserImageCache.cs

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
using Microsoft.VisualStudio.Shell;
1313
using TeamCoding.Options;
1414
using TeamCoding.VisualStudio.Controls;
15+
using System.Threading.Tasks;
1516

1617
namespace TeamCoding.VisualStudio
1718
{
@@ -113,10 +114,7 @@ private void SetImageSource(UserAvatarModel context, IUserIdentity userIdentity)
113114
{
114115
try
115116
{
116-
var request = await TeamCodingPackage.Current.HttpClient.GetAsync(userIdentity.ImageUrl);
117-
if (!request.IsSuccessStatusCode) return;
118-
var imageStream = await request.Content.ReadAsStreamAsync();
119-
context.AvatarImageSource = UrlImages[userIdentity.ImageUrl] = BitmapFrame.Create(imageStream, BitmapCreateOptions.None, BitmapCacheOption.OnLoad);
117+
context.AvatarImageSource = await GetImageFromUrl(userIdentity.ImageUrl);
120118
}
121119
catch (Exception ex) when (!System.Diagnostics.Debugger.IsAttached)
122120
{
@@ -131,6 +129,14 @@ private void SetImageSource(UserAvatarModel context, IUserIdentity userIdentity)
131129
context.AvatarImageSource = null;
132130
}
133131
}
132+
public async Task<ImageSource> GetImageFromUrl(string url)
133+
{
134+
var request = await TeamCodingPackage.Current.HttpClient.GetAsync(url);
135+
request.EnsureSuccessStatusCode();
136+
137+
var imageStream = await request.Content.ReadAsStreamAsync();
138+
return UrlImages[url] = BitmapFrame.Create(imageStream, BitmapCreateOptions.None, BitmapCacheOption.OnLoad);
139+
}
134140
/// <summary>
135141
/// Sets properties specific to a user control in a document tab
136142
/// </summary>

0 commit comments

Comments
 (0)