Skip to content
This repository was archived by the owner on Jun 21, 2023. It is now read-only.
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 4 additions & 8 deletions src/GitHub.App/ViewModels/RepositoryPublishViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -151,23 +151,19 @@ ReactiveCommand<Unit> InitializePublishRepositoryCommand()
return ReactiveCommand.CreateAsyncObservable(canCreate, OnPublishRepository);
}

private IObservable<Unit> OnPublishRepository(object arg)
IObservable<Unit> OnPublishRepository(object arg)
{
var newRepository = GatherRepositoryInfo();
var account = SelectedAccount;

return repositoryPublishService.PublishRepository(newRepository, account, SelectedHost.ApiClient)
.SelectUnit()
.Do(_ => vsServices.ShowMessage("Repository published successfully."))
.Catch<Unit, Exception>(ex =>
{
log.Error(ex);
if (!ex.IsCriticalException())
{
log.Error(ex);
var error = new PublishRepositoryUserError(ex.Message);
vsServices.ShowError((error.ErrorMessage + Environment.NewLine + error.ErrorCauseOrResolution).TrimEnd());
}
return Observable.Return(Unit.Default);
ex = new UnhandledUserErrorException(new PublishRepositoryUserError(ex.Message));
return Observable.Throw<Unit>(ex);
});
}

Expand Down
1 change: 1 addition & 0 deletions src/GitHub.Exports/UI/IView.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,6 @@ public interface IView
IObservable<object> Done { get; }
IObservable<object> Cancel { get; }
IObservable<bool> IsBusy { get; }
IObservable<object> Error { get; }
}
}
10 changes: 10 additions & 0 deletions src/GitHub.UI.Reactive/Controls/SimpleViewUserControl.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ public class SimpleViewUserControl : UserControl, IDisposable, IActivatable
{
readonly Subject<object> close = new Subject<object>();
readonly Subject<object> cancel = new Subject<object>();
readonly Subject<object> error = new Subject<object>();
readonly Subject<bool> isBusy = new Subject<bool>();

public SimpleViewUserControl()
Expand All @@ -39,6 +40,8 @@ public SimpleViewUserControl()

public IObservable<object> Cancel { get { return cancel; } }

public IObservable<object> Error { get { return error; } }

public IObservable<bool> IsBusy{ get { return isBusy; } }

protected void NotifyDone()
Expand All @@ -53,6 +56,12 @@ protected void NotifyCancel()
cancel.OnCompleted();
}

protected void NotifyError(string message)
{
error.OnNext(message);
error.OnCompleted();
}

protected void NotifyIsBusy(bool busy)
{
isBusy.OnNext(busy);
Expand All @@ -66,6 +75,7 @@ protected virtual void Dispose(bool disposing)
if (disposed) return;

close.Dispose();
error.Dispose();
disposed = true;
}
}
Expand Down
76 changes: 47 additions & 29 deletions src/GitHub.VisualStudio/TeamExplorer/Sync/GitHubPublishSection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@
using GitHub.Models;
using GitHub.Services;
using GitHub.Info;
using ReactiveUI;
using System.Reactive.Linq;
using GitHub.Extensions;
using GitHub.Api;
using GitHub.VisualStudio.TeamExplorer;
using System.Reactive.Disposables;
using System.Windows.Controls;

namespace GitHub.VisualStudio.TeamExplorer.Sync
{
Expand All @@ -24,8 +24,9 @@ public class GitHubPublishSection : TeamExplorerSectionBase, IGitHubInvitationSe

readonly Lazy<IVisualStudioBrowser> lazyBrowser;
readonly IRepositoryHosts hosts;
IDisposable disposable;
readonly CompositeDisposable disposables = new CompositeDisposable();
bool loggedIn;
readonly UserControl view;

[ImportingConstructor]
public GitHubPublishSection(ISimpleApiClientFactory apiFactory, ITeamExplorerServiceHolder holder,
Expand All @@ -45,12 +46,12 @@ public GitHubPublishSection(ISimpleApiClientFactory apiFactory, ITeamExplorerSer
ShowGetStarted = false;
IsVisible = false;
IsExpanded = true;
var view = new GitHubInvitationContent();
view = new GitHubInvitationContent();
SectionContent = view;
view.DataContext = this;
}

async void RTMSetup()
async void Setup()
{
if (ActiveRepo != null && ActiveRepoUri == null)
{
Expand All @@ -64,39 +65,23 @@ async void RTMSetup()
IsVisible = false;
}

async void PreRTMSetup()
{
if (ActiveRepo != null && ActiveRepoUri == null)
{
IsVisible = true;
loggedIn = await connectionManager.IsLoggedIn(hosts);
if (loggedIn)
ShowPublish();
else
{
ShowGetStarted = true;
ShowSignup = true;
}
}
else
IsVisible = false;
}

public override void Initialize(object sender, SectionInitializeEventArgs e)
{
base.Initialize(sender, e);
RTMSetup();
Setup();
}

protected override void RepoChanged()
{
base.RepoChanged();
RTMSetup();
Setup();
}

public async void Connect()
{
loggedIn = await connectionManager.IsLoggedIn(hosts);
// we run the login on a separate UI flow because the login
// dialog is a modal dialog while the publish dialog is inlined in Team Explorer
if (loggedIn)
ShowPublish();
else
Expand Down Expand Up @@ -128,18 +113,52 @@ void StartFlow(UIControllerFlow controllerFlow)

void ShowPublish()
{
// set the loading indicator while we prep the form
IsBusy = true;

var uiProvider = ServiceProvider.GetExportedValue<IUIProvider>();
var factory = uiProvider.GetService<IExportFactoryProvider>();
var uiflow = factory.UIControllerFactory.CreateExport();
disposable = uiflow;
disposables.Add(uiflow);
var ui = uiflow.Value;
var creation = ui.SelectFlow(UIControllerFlow.Publish);
var busyTracker = new SerialDisposable();
creation.Subscribe(c =>
{
SectionContent = c;
c.DataContext = this;
((IView)c).IsBusy.Subscribe(x => IsBusy = x);

var v = (IView)c;
busyTracker.Disposable = v.IsBusy.Subscribe(x => IsBusy = x);
disposables.Add(v.Error.Subscribe(x =>
{
var vsServices = ServiceProvider.GetExportedValue<IVSServices>();
vsServices.ShowError(x as string);
}));
},
() =>
{
var vsServices = ServiceProvider.GetExportedValue<IVSServices>();
vsServices.ShowMessage("Repository published successfully.");

var v = SectionContent as IView;
// the IsPublishing flag takes way too long to fire, don't wait for it, we're done
if (IsBusy)
{
// we only want to dispose things when all the events are processed (IsPublishing is the last one)
busyTracker.Disposable = v.IsBusy.Subscribe(_ =>
{
disposables.Clear();
busyTracker.Dispose();
});
IsBusy = false;
}
else
{
busyTracker.Dispose();
disposables.Clear();
}
SectionContent = view;
});
ui.Start(null);
}
Expand All @@ -151,8 +170,7 @@ protected override void Dispose(bool disposing)
{
if (!disposed)
{
if (disposable != null)
disposable.Dispose();
disposables.Dispose();
disposed = true;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,17 @@ public RepositoryPublishControl()
d(this.OneWayBind(ViewModel, vm => vm.IsPublishing, v => v.description.IsEnabled, x => x == false));
d(this.OneWayBind(ViewModel, vm => vm.IsPublishing, v => v.accountsComboBox.IsEnabled, x => x == false));

ViewModel.PublishRepository.Subscribe(_ => NotifyDone());
d(ViewModel.PublishRepository.Subscribe(_ => NotifyDone()));
d(ViewModel.PublishRepository.ThrownExceptions.Subscribe(ex =>
{
var error = ex as UnhandledUserErrorException;
if (error == null)
NotifyError("Error publishing repository." + Environment.NewLine + ex.Message);
else
NotifyError((error.ReportedError.ErrorMessage + Environment.NewLine + error.ReportedError.ErrorCauseOrResolution).TrimEnd());
}));

d(this.WhenAny(x => x.ViewModel.IsPublishing, x => x.Value)
.Subscribe(x => NotifyIsBusy(x)));
d(this.WhenAny(x => x.ViewModel.IsPublishing, x => x.Value).Subscribe(x => NotifyIsBusy(x)));

nameText.Text = ViewModel.DefaultRepositoryName;
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -339,10 +339,10 @@ public async Task DisplaysSuccessMessageWhenCompletedWithoutError()

vm.RepositoryName = "repo-name";

var obs = Substitute.For<IObserver<Exception>>();
vm.PublishRepository.ThrownExceptions.Subscribe(obs);
await vm.PublishRepository.ExecuteAsync().Catch(Observable.Return(Unit.Default));

vsServices.Received().ShowMessage("Repository published successfully.");
vsServices.DidNotReceive().ShowError(Args.String);
obs.DidNotReceiveWithAnyArgs().OnNext(null);
}

[Fact]
Expand All @@ -358,10 +358,11 @@ public async Task DisplaysRepositoryExistsErrorWithVisualStudioNotifications()
var vm = Helpers.SetupConnectionsAndViewModel(hosts, repositoryPublishService, vsServices, cm);
vm.RepositoryName = "repo-name";

var obs = Substitute.For<IObserver<Exception>>();
vm.PublishRepository.ThrownExceptions.Subscribe(obs);
await vm.PublishRepository.ExecuteAsync().Catch(Observable.Return(Unit.Default));

vsServices.DidNotReceive().ShowMessage(Args.String);
vsServices.Received().ShowError("There is already a repository named 'repo-name' for the current account.");
obs.ReceivedWithAnyArgs().OnNext(null);
Assert.True(obs.ReceivedCalls().Any(x => ((UnhandledUserErrorException)x.GetArguments()[0]).Message == "There is already a repository named 'repo-name' for the current account."));
}

[Fact]
Expand Down Expand Up @@ -391,6 +392,7 @@ public async Task ClearsErrorsWhenSwitchingHosts()

vm.RepositoryName = "repo-name";

vm.PublishRepository.ThrownExceptions.Subscribe();
await vm.PublishRepository.ExecuteAsync().Catch(Observable.Return(Unit.Default));

vm.SelectedConnection = conns.First(x => x != vm.SelectedConnection);
Expand Down Expand Up @@ -422,6 +424,7 @@ public async Task ClearsErrorsWhenSwitchingAccounts()

vm.RepositoryName = "repo-name";

vm.PublishRepository.ThrownExceptions.Subscribe();
await vm.PublishRepository.ExecuteAsync().Catch(Observable.Return(Unit.Default));

vm.SelectedAccount = accounts[1];
Expand Down