Skip to content
This repository was archived by the owner on Jun 21, 2023. It is now read-only.

Commit 678745b

Browse files
committed
Display connection errors in GitHub pane.
1 parent b2facb8 commit 678745b

File tree

12 files changed

+207
-13
lines changed

12 files changed

+207
-13
lines changed

src/GitHub.App/GitHub.App.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,7 @@
258258
<Compile Include="ViewModels\GitHubPane\NavigationViewModel.cs" />
259259
<Compile Include="ViewModels\GitHubPane\GitHubPaneViewModel.cs" />
260260
<Compile Include="SampleData\PullRequestCheckViewModelDesigner.cs" />
261+
<Compile Include="ViewModels\GitHubPane\LoginFailedViewModel.cs" />
261262
<Compile Include="ViewModels\GitHubPane\PullRequestFilesViewModel.cs" />
262263
<Compile Include="ViewModels\GitHubPane\PullRequestListItemViewModel.cs" />
263264
<Compile Include="ViewModels\GitHubPane\PullRequestListViewModel.cs" />

src/GitHub.App/Services/StandardUserErrors.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -209,7 +209,7 @@ static IObservable<RecoveryOptionResult> DisplayErrorMessage(this Exception exce
209209
return userError.Throw();
210210
}
211211

212-
static UserError GetUserFriendlyError(this Exception exception, ErrorType errorType, params object[] messageArgs)
212+
public static UserError GetUserFriendlyError(this Exception exception, ErrorType errorType, params object[] messageArgs)
213213
{
214214
return Translator.Value.GetUserError(errorType, exception, messageArgs);
215215
}

src/GitHub.App/ViewModels/GitHubPane/GitHubPaneViewModel.cs

Lines changed: 43 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ public sealed class GitHubPaneViewModel : ViewModelBase, IGitHubPaneViewModel, I
4444
readonly ILoggedOutViewModel loggedOut;
4545
readonly INotAGitHubRepositoryViewModel notAGitHubRepository;
4646
readonly INotAGitRepositoryViewModel notAGitRepository;
47+
readonly ILoginFailedViewModel loginFailed;
4748
readonly SemaphoreSlim navigating = new SemaphoreSlim(1);
4849
readonly ObservableAsPropertyHelper<ContentOverride> contentOverride;
4950
readonly ObservableAsPropertyHelper<bool> isSearchEnabled;
@@ -52,6 +53,7 @@ public sealed class GitHubPaneViewModel : ViewModelBase, IGitHubPaneViewModel, I
5253
readonly ReactiveCommand<Unit> showPullRequests;
5354
readonly ReactiveCommand<object> openInBrowser;
5455
readonly ReactiveCommand<object> help;
56+
IDisposable connectionSubscription;
5557
Task initializeTask;
5658
IViewModel content;
5759
ILocalRepositoryModel localRepository;
@@ -68,7 +70,8 @@ public GitHubPaneViewModel(
6870
INavigationViewModel navigator,
6971
ILoggedOutViewModel loggedOut,
7072
INotAGitHubRepositoryViewModel notAGitHubRepository,
71-
INotAGitRepositoryViewModel notAGitRepository)
73+
INotAGitRepositoryViewModel notAGitRepository,
74+
ILoginFailedViewModel loginFailed)
7275
{
7376
Guard.ArgumentNotNull(viewModelFactory, nameof(viewModelFactory));
7477
Guard.ArgumentNotNull(apiClientFactory, nameof(apiClientFactory));
@@ -80,6 +83,7 @@ public GitHubPaneViewModel(
8083
Guard.ArgumentNotNull(loggedOut, nameof(loggedOut));
8184
Guard.ArgumentNotNull(notAGitHubRepository, nameof(notAGitHubRepository));
8285
Guard.ArgumentNotNull(notAGitRepository, nameof(notAGitRepository));
86+
Guard.ArgumentNotNull(loginFailed, nameof(loginFailed));
8387

8488
this.viewModelFactory = viewModelFactory;
8589
this.apiClientFactory = apiClientFactory;
@@ -89,6 +93,7 @@ public GitHubPaneViewModel(
8993
this.loggedOut = loggedOut;
9094
this.notAGitHubRepository = notAGitHubRepository;
9195
this.notAGitRepository = notAGitRepository;
96+
this.loginFailed = loginFailed;
9297

9398
var contentAndNavigatorContent = Observable.CombineLatest(
9499
this.WhenAnyValue(x => x.Content),
@@ -389,6 +394,8 @@ async Task UpdateContent(ILocalRepositoryModel repository)
389394
log.Debug("UpdateContent called with {CloneUrl}", repository?.CloneUrl);
390395

391396
LocalRepository = repository;
397+
connectionSubscription?.Dispose();
398+
connectionSubscription = null;
392399
Connection = null;
393400
Content = null;
394401
navigator.Clear();
@@ -410,26 +417,56 @@ async Task UpdateContent(ILocalRepositoryModel repository)
410417
var isDotCom = HostAddress.IsGitHubDotComUri(repositoryUrl);
411418
var client = await apiClientFactory.Create(repository.CloneUrl);
412419
var isEnterprise = isDotCom ? false : await client.IsEnterprise();
420+
var notGitHubRepo = true;
413421

414-
if ((isDotCom || isEnterprise) && await IsValidRepository(client))
422+
if (isDotCom || isEnterprise)
415423
{
416424
var hostAddress = HostAddress.Create(repository.CloneUrl);
417425

426+
notGitHubRepo = false;
427+
418428
Connection = await connectionManager.GetConnection(hostAddress);
429+
Connection?.WhenAnyValue(
430+
x => x.IsLoggedIn,
431+
x => x.IsLoggingIn,
432+
(_, __) => Unit.Default)
433+
.Skip(1)
434+
.Throttle(TimeSpan.FromMilliseconds(100))
435+
.ObserveOn(RxApp.MainThreadScheduler)
436+
.Subscribe(_ => UpdateContent(LocalRepository).Forget());
419437

420438
if (Connection?.IsLoggedIn == true)
421439
{
422-
log.Debug("Found a GitHub repository: {CloneUrl}", repository?.CloneUrl);
423-
Content = navigator;
424-
await ShowDefaultPage();
440+
if (await IsValidRepository(client) == true)
441+
{
442+
log.Debug("Found a GitHub repository: {CloneUrl}", repository?.CloneUrl);
443+
Content = navigator;
444+
await ShowDefaultPage();
445+
}
446+
else
447+
{
448+
notGitHubRepo = true;
449+
}
450+
}
451+
else if (Connection?.IsLoggingIn == true)
452+
{
453+
log.Debug("Found a GitHub repository: {CloneUrl} and logging in", repository?.CloneUrl);
454+
Content = null;
455+
}
456+
else if (Connection?.ConnectionError != null)
457+
{
458+
log.Debug("Found a GitHub repository: {CloneUrl} with login error", repository?.CloneUrl);
459+
loginFailed.Initialize(Connection.ConnectionError.GetUserFriendlyError(ErrorType.LoginFailed));
460+
Content = loginFailed;
425461
}
426462
else
427463
{
428464
log.Debug("Found a a GitHub repository but not logged in: {CloneUrl}", repository?.CloneUrl);
429465
Content = loggedOut;
430466
}
431467
}
432-
else
468+
469+
if (notGitHubRepo)
433470
{
434471
log.Debug("Not a GitHub repository: {CloneUrl}", repository?.CloneUrl);
435472
Content = notAGitHubRepository;
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
using System;
2+
using System.ComponentModel.Composition;
3+
using GitHub.Services;
4+
using ReactiveUI;
5+
6+
namespace GitHub.ViewModels.GitHubPane
7+
{
8+
/// <summary>
9+
/// The view model for the "Login Failed" view in the GitHub pane.
10+
/// </summary>
11+
[Export(typeof(ILoginFailedViewModel))]
12+
[PartCreationPolicy(CreationPolicy.NonShared)]
13+
public class LoginFailedViewModel : PanePageViewModelBase, ILoginFailedViewModel
14+
{
15+
readonly ITeamExplorerServices teServices;
16+
UserError loginError;
17+
18+
/// <summary>
19+
/// Initializes a new instance of the <see cref="LoginFailedViewModel"/> class.
20+
/// </summary>
21+
[ImportingConstructor]
22+
public LoginFailedViewModel(ITeamExplorerServices teServices)
23+
{
24+
this.teServices = teServices;
25+
OpenTeamExplorer = ReactiveCommand.Create().OnExecuteCompleted(_ => DoOpenTeamExplorer());
26+
}
27+
28+
/// <inheritdoc/>
29+
public UserError LoginError
30+
{
31+
get => loginError;
32+
private set => this.RaiseAndSetIfChanged(ref loginError, value);
33+
}
34+
35+
/// <inheritdoc/>
36+
public ReactiveCommand<object> OpenTeamExplorer { get; }
37+
38+
public void Initialize(UserError error)
39+
{
40+
LoginError = error;
41+
}
42+
43+
void DoOpenTeamExplorer() => teServices.ShowConnectPage();
44+
}
45+
}

src/GitHub.Exports.Reactive/GitHub.Exports.Reactive.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,7 @@
203203
<Compile Include="ViewModels\GitHubPane\IIssueListViewModelBase.cs" />
204204
<Compile Include="ViewModels\GitHubPane\ILoggedOutViewModel.cs" />
205205
<Compile Include="ViewModels\GitHubPane\INavigationViewModel.cs" />
206+
<Compile Include="ViewModels\GitHubPane\ILoginFailedViewModel.cs" />
206207
<Compile Include="ViewModels\GitHubPane\IPanePageViewModel.cs" />
207208
<Compile Include="ViewModels\GitHubPane\IPullRequestCheckViewModel.cs" />
208209
<Compile Include="ViewModels\GitHubPane\IPullRequestFilesViewModel.cs" />
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
using ReactiveUI;
2+
3+
namespace GitHub.ViewModels.GitHubPane
4+
{
5+
/// <summary>
6+
/// Defines the view model for the "Login Failed" view in the GitHub pane.
7+
/// </summary>
8+
public interface ILoginFailedViewModel : IPanePageViewModel
9+
{
10+
/// <summary>
11+
/// Gets a description of the login failure.
12+
/// </summary>
13+
UserError LoginError { get; }
14+
15+
/// <summary>
16+
/// Gets a command which opens the Team Explorer Connect page.
17+
/// </summary>
18+
ReactiveCommand<object> OpenTeamExplorer { get; }
19+
20+
/// <summary>
21+
/// Initializes the view model with an error.
22+
/// </summary>
23+
/// <param name="error">The error.</param>
24+
void Initialize(UserError error);
25+
}
26+
}

src/GitHub.Exports/Services/ITeamExplorerServices.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ namespace GitHub.Services
44
{
55
public interface ITeamExplorerServices : INotificationService
66
{
7+
void ShowConnectPage();
78
void ShowPublishSection();
89
void ClearNotifications();
910
}

src/GitHub.TeamFoundation.14/Services/TeamExplorerServices.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,12 @@ public TeamExplorerServices(IGitHubServiceProvider serviceProvider)
2828
this.serviceProvider = serviceProvider;
2929
}
3030

31+
public void ShowConnectPage()
32+
{
33+
var te = serviceProvider.TryGetService<ITeamExplorer>();
34+
var foo = te.NavigateToPage(new Guid(TeamExplorerPageIds.Connect), null);
35+
}
36+
3137
public void ShowPublishSection()
3238
{
3339
var te = serviceProvider.TryGetService<ITeamExplorer>();

src/GitHub.VisualStudio/GitHub.VisualStudio.csproj

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -409,6 +409,9 @@
409409
<Compile Include="Views\GitHubPane\GitHubPaneView.xaml.cs">
410410
<DependentUpon>GitHubPaneView.xaml</DependentUpon>
411411
</Compile>
412+
<Compile Include="Views\GitHubPane\LoginFailedView.xaml.cs">
413+
<DependentUpon>LoginFailedView.xaml</DependentUpon>
414+
</Compile>
412415
<Compile Include="Views\GitHubPane\PullRequestFileCommentsView.xaml.cs">
413416
<DependentUpon>PullRequestFileCommentsView.xaml</DependentUpon>
414417
</Compile>
@@ -593,6 +596,9 @@
593596
<SubType>Designer</SubType>
594597
<Generator>MSBuild:Compile</Generator>
595598
</Page>
599+
<Page Include="Views\GitHubPane\LoginFailedView.xaml">
600+
<Generator>MSBuild:Compile</Generator>
601+
</Page>
596602
<Page Include="Views\GitHubPane\PullRequestFileCommentsView.xaml">
597603
<Generator>MSBuild:Compile</Generator>
598604
<SubType>Designer</SubType>
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
<UserControl x:Class="GitHub.VisualStudio.Views.GitHubPane.LoginFailedView"
2+
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
3+
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
4+
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
5+
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
6+
xmlns:ghfvs="https://github.com/github/VisualStudio"
7+
mc:Ignorable="d" d:DesignHeight="300" d:DesignWidth="300">
8+
9+
<Control.Resources>
10+
<ResourceDictionary>
11+
<ResourceDictionary.MergedDictionaries>
12+
<ghfvs:SharedDictionaryManager Source="pack://application:,,,/GitHub.VisualStudio.UI;component/SharedDictionary.xaml" />
13+
<ghfvs:SharedDictionaryManager Source="pack://application:,,,/GitHub.UI;component/SharedDictionary.xaml" />
14+
</ResourceDictionary.MergedDictionaries>
15+
</ResourceDictionary>
16+
</Control.Resources>
17+
18+
<StackPanel Margin="10" Orientation="Vertical">
19+
<ghfvs:OcticonImage Icon="mark_github" Margin="0,5" Width="48" Height="48" />
20+
<Label FontSize="16"
21+
HorizontalAlignment="Center"
22+
Content="{Binding LoginError.ErrorMessage}"/>
23+
<TextBlock Text="{Binding LoginError.ErrorCauseOrResolution}"
24+
TextAlignment="Center"
25+
TextWrapping="Wrap"/>
26+
<ghfvs:GitHubActionLink Command="{Binding OpenTeamExplorer}"
27+
Content="Open Team Explorer"
28+
HorizontalAlignment="Center"
29+
Margin="0,15"/>
30+
</StackPanel>
31+
</UserControl>

0 commit comments

Comments
 (0)