Beispiel #1
0
        async Task RepoChanged(ILocalRepositoryModel repository)
        {
            try
            {
                await ThreadingHelper.SwitchToMainThreadAsync();
                await EnsureLoggedIn(repository);

                if (repository != this.repository)
                {
                    this.repository = repository;
                    CurrentSession  = null;
                    sessions.Clear();
                }

                if (string.IsNullOrWhiteSpace(repository?.CloneUrl))
                {
                    return;
                }

                var modelService = hosts.LookupHost(HostAddress.Create(repository.CloneUrl))?.ModelService;
                var session      = CurrentSession;

                if (modelService != null)
                {
                    var pr = await service.GetPullRequestForCurrentBranch(repository).FirstOrDefaultAsync();

                    if (pr?.Item1 != (CurrentSession?.PullRequest.Base.RepositoryCloneUrl.Owner) &&
                        pr?.Item2 != (CurrentSession?.PullRequest.Number))
                    {
                        var pullRequest = await GetPullRequestForTip(modelService, repository);

                        if (pullRequest != null)
                        {
                            var newSession = await GetSessionInternal(pullRequest);

                            if (newSession != null)
                            {
                                newSession.IsCheckedOut = true;
                            }
                            session = newSession;
                        }
                    }
                }
                else
                {
                    session = null;
                }

                CurrentSession = session;
            }
            catch
            {
                // TODO: Log
            }
        }
 public static IObservable<bool> IsLoggedIn(this IConnectionManager cm, IRepositoryHosts hosts, HostAddress address)
 {
     return cm.Connections.ToObservable()
             .Where(c => c.HostAddress.Equals(address))
             .SelectMany(c => c.Login())
             .Any(c => hosts.LookupHost(c.HostAddress).IsLoggedIn);
 }
Beispiel #3
0
 public static IObservable <bool> IsLoggedIn(this IConnectionManager cm, IRepositoryHosts hosts, HostAddress address)
 {
     return(cm.Connections.ToObservable()
            .Where(c => c.HostAddress.Equals(address))
            .SelectMany(c => c.Login())
            .Any(c => hosts.LookupHost(c.HostAddress).IsLoggedIn));
 }
Beispiel #4
0
 public static IObservable <IConnection> GetLoggedInConnections(this IConnectionManager cm, IRepositoryHosts hosts)
 {
     Guard.ArgumentNotNull(hosts, nameof(hosts));
     return(cm.Connections.ToObservable()
            .SelectMany(c => c.Login())
            .Where(c => hosts.LookupHost(c.HostAddress).IsLoggedIn));
 }
 public static IObservable<IConnection> GetLoggedInConnections(this IConnectionManager cm, IRepositoryHosts hosts)
 {
     Guard.ArgumentNotNull(hosts, nameof(hosts));
     return cm.Connections.ToObservable()
             .SelectMany(c => c.Login())
             .Where(c => hosts.LookupHost(c.HostAddress).IsLoggedIn);
 }
Beispiel #6
0
        async Task RepoChanged(ILocalRepositoryModel repository)
        {
            try
            {
                await EnsureLoggedIn(repository);

                if (repository != this.repository)
                {
                    this.repository = repository;
                    CurrentSession  = null;
                    sessions.Clear();
                }

                var modelService = hosts.LookupHost(HostAddress.Create(repository.CloneUrl))?.ModelService;
                var session      = CurrentSession;

                if (modelService != null)
                {
                    var number = await service.GetPullRequestForCurrentBranch(repository).FirstOrDefaultAsync();

                    if (number != (CurrentSession?.PullRequest.Number ?? 0))
                    {
                        var pullRequest = await GetPullRequestForTip(modelService, repository);

                        if (pullRequest != null)
                        {
                            var newSession = await GetSessionInternal(pullRequest);;
                            if (newSession != null)
                            {
                                newSession.IsCheckedOut = true;
                            }
                            session = newSession;
                        }
                    }
                }
                else
                {
                    session = null;
                }

                CurrentSession = session;
            }
            catch
            {
                // TODO: Log
            }
        }
Beispiel #7
0
        public void Start([AllowNull] IConnection connection)
        {
            if (connection != null)
            {
                uiProvider.AddService(typeof(IConnection), connection);
                connection.Login()
                .Select(c => hosts.LookupHost(connection.HostAddress))
                .Do(host =>
                {
                    machine.Configure(UIViewType.None)
                    .Permit(Trigger.Auth, UIViewType.Login)
                    .PermitIf(Trigger.Create, UIViewType.Create, () => host.IsLoggedIn)
                    .PermitIf(Trigger.Create, UIViewType.Login, () => !host.IsLoggedIn)
                    .PermitIf(Trigger.Clone, UIViewType.Clone, () => host.IsLoggedIn)
                    .PermitIf(Trigger.Clone, UIViewType.Login, () => !host.IsLoggedIn)
                    .PermitIf(Trigger.Publish, UIViewType.Publish, () => host.IsLoggedIn)
                    .PermitIf(Trigger.Publish, UIViewType.Login, () => !host.IsLoggedIn);
                })
                .ObserveOn(RxApp.MainThreadScheduler)
                .Subscribe(_ => { }, () =>
                {
                    Debug.WriteLine("Start ({0})", GetHashCode());
                    Fire((Trigger)(int)currentFlow);
                });
            }
            else
            {
                connectionManager
                .IsLoggedIn(hosts)
                .Do(loggedin =>
                {
                    if (!loggedin && currentFlow != UIControllerFlow.Authentication)
                    {
                        connectionAdded = (s, e) => {
                            if (e.Action == NotifyCollectionChangedAction.Add)
                            {
                                uiProvider.AddService(typeof(IConnection), e.NewItems[0]);
                            }
                        };
                        connectionManager.Connections.CollectionChanged += connectionAdded;
                    }

                    machine.Configure(UIViewType.None)
                    .Permit(Trigger.Auth, UIViewType.Login)
                    .PermitIf(Trigger.Create, UIViewType.Create, () => loggedin)
                    .PermitIf(Trigger.Create, UIViewType.Login, () => !loggedin)
                    .PermitIf(Trigger.Clone, UIViewType.Clone, () => loggedin)
                    .PermitIf(Trigger.Clone, UIViewType.Login, () => !loggedin)
                    .PermitIf(Trigger.Publish, UIViewType.Publish, () => loggedin)
                    .PermitIf(Trigger.Publish, UIViewType.Login, () => !loggedin);
                })
                .ObserveOn(RxApp.MainThreadScheduler)
                .Subscribe(_ => { }, () =>
                {
                    Debug.WriteLine("Start ({0})", GetHashCode());
                    Fire((Trigger)(int)currentFlow);
                });
            }
        }
Beispiel #8
0
        UIControllerFlow SelectActiveFlow()
        {
            var host = connection != null?hosts.LookupHost(connection.HostAddress) : null;

            var loggedIn = host?.IsLoggedIn ?? false;

            return(loggedIn ? selectedFlow : UIControllerFlow.Authentication);
        }
Beispiel #9
0
        protected IConnection SetupConnection(IServiceProvider provider, IRepositoryHosts hosts,
                                              IRepositoryHost host)
        {
            var connection = provider.GetConnection();

            connection.Login().Returns(Observable.Return(connection));
            hosts.LookupHost(connection.HostAddress).Returns(host);
            host.IsLoggedIn.Returns(true);
            return(connection);
        }
Beispiel #10
0
        UIControllerFlow SelectActiveFlow()
        {
            var host = connection != null?hosts.LookupHost(connection.HostAddress) : null;

            var loggedIn = host?.IsLoggedIn ?? false;

            if (!loggedIn || selectedFlow != UIControllerFlow.Gist)
            {
                return(loggedIn ? selectedFlow : UIControllerFlow.Authentication);
            }

            var supportsGist = host?.SupportsGist ?? false;

            return(supportsGist ? selectedFlow : UIControllerFlow.LogoutRequired);
        }
        public static void SetupConnections(IRepositoryHosts hosts, IConnectionManager cm,
            List<HostAddress> adds, List<IConnection> conns, List<IRepositoryHost> hsts,
            string uri)
        {
            var add = HostAddress.Create(new Uri(uri));
            var host = Substitute.For<IRepositoryHost>();
            var conn = Substitute.For<IConnection>();
            host.Address.Returns(add);
            conn.HostAddress.Returns(add);
            adds.Add(add);
            hsts.Add(host);
            conns.Add(conn);

            if (add.IsGitHubDotCom())
                hosts.GitHubHost.Returns(host);
            else
                hosts.EnterpriseHost.Returns(host);
            hosts.LookupHost(Arg.Is(add)).Returns(host);
        }
        public static void SetupConnections(IRepositoryHosts hosts, IConnectionManager cm,
                                            List <HostAddress> adds, List <IConnection> conns, List <IRepositoryHost> hsts,
                                            string uri)
        {
            var add  = HostAddress.Create(new Uri(uri));
            var host = Substitute.For <IRepositoryHost>();
            var conn = Substitute.For <IConnection>();

            host.Address.Returns(add);
            conn.HostAddress.Returns(add);
            adds.Add(add);
            hsts.Add(host);
            conns.Add(conn);

            if (add.IsGitHubDotCom())
            {
                hosts.GitHubHost.Returns(host);
            }
            else
            {
                hosts.EnterpriseHost.Returns(host);
            }
            hosts.LookupHost(Arg.Is(add)).Returns(host);
        }
 public static IObservable<bool> IsLoggedIn(this IConnection connection, IRepositoryHosts hosts)
 {
     Guard.ArgumentNotNull(hosts, nameof(hosts));
     return connection?.Login().Any(c => hosts.LookupHost(c.HostAddress).IsLoggedIn) ?? Observable.Return(false);
 }
Beispiel #14
0
 public static IObservable <bool> IsLoggedIn(this IConnection connection, IRepositoryHosts hosts)
 {
     Guard.ArgumentNotNull(hosts, nameof(hosts));
     return(connection?.Login().Any(c => hosts.LookupHost(c.HostAddress).IsLoggedIn) ?? Observable.Return(false));
 }
Beispiel #15
0
 protected ConnectionRepositoryHostMap(IConnection connection, IRepositoryHosts hosts)
     : this(hosts.LookupHost(connection.HostAddress))
 {
 }
        public RepositoryPublishViewModel(
            IRepositoryHosts hosts,
            IRepositoryPublishService repositoryPublishService,
            INotificationService notificationService,
            IConnectionManager connectionManager,
            IUsageTracker usageTracker)
        {
            this.notificationService = notificationService;
            this.hosts        = hosts;
            this.usageTracker = usageTracker;

            title = this.WhenAny(
                x => x.SelectedHost,
                x => x.Value != null ?
                string.Format(CultureInfo.CurrentCulture, Resources.PublishToTitle, x.Value.Title) :
                Resources.PublishTitle
                )
                    .ToProperty(this, x => x.Title);

            Connections = connectionManager.Connections;
            this.repositoryPublishService = repositoryPublishService;

            if (Connections.Any())
            {
                SelectedConnection = Connections.FirstOrDefault(x => x.HostAddress.IsGitHubDotCom()) ?? Connections[0];
            }

            accounts = this.WhenAny(x => x.SelectedConnection, x => x.Value != null ? hosts.LookupHost(x.Value.HostAddress) : RepositoryHosts.DisconnectedRepositoryHost)
                       .Where(x => !(x is DisconnectedRepositoryHost))
                       .SelectMany(host => host.ModelService.GetAccounts())
                       .ObserveOn(RxApp.MainThreadScheduler)
                       .ToProperty(this, x => x.Accounts, initialValue: new ReadOnlyCollection <IAccount>(new IAccount[] {}));

            this.WhenAny(x => x.Accounts, x => x.Value)
            .WhereNotNull()
            .Where(accts => accts.Any())
            .Subscribe(accts => {
                var selectedAccount = accts.FirstOrDefault();
                if (selectedAccount != null)
                {
                    SelectedAccount = accts.FirstOrDefault();
                }
            });

            isHostComboBoxVisible = this.WhenAny(x => x.Connections, x => x.Value)
                                    .WhereNotNull()
                                    .Select(h => h.Count > 1)
                                    .ToProperty(this, x => x.IsHostComboBoxVisible);

            InitializeValidation();

            PublishRepository = InitializePublishRepositoryCommand();

            canKeepPrivate = CanKeepPrivateObservable.CombineLatest(PublishRepository.IsExecuting,
                                                                    (canKeep, publishing) => canKeep && !publishing)
                             .ToProperty(this, x => x.CanKeepPrivate);

            isPublishing = PublishRepository.IsExecuting
                           .ToProperty(this, x => x.IsPublishing);

            var defaultRepositoryName = repositoryPublishService.LocalRepositoryName;

            if (!string.IsNullOrEmpty(defaultRepositoryName))
            {
                RepositoryName = defaultRepositoryName;
            }

            this.WhenAny(x => x.SelectedConnection, x => x.SelectedAccount,
                         (a, b) => true)
            .Where(x => RepositoryNameValidator.ValidationResult != null && SafeRepositoryNameWarningValidator.ValidationResult != null)
            .Subscribe(async _ =>
            {
                var name       = RepositoryName;
                RepositoryName = null;
                await RepositoryNameValidator.ResetAsync();
                await SafeRepositoryNameWarningValidator.ResetAsync();
                RepositoryName = name;
            });
        }
Beispiel #17
0
        public void Start([AllowNull] IConnection connection)
        {
            if (connection != null)
            {
                if (currentFlow != UIControllerFlow.Authentication)
                {
                    uiProvider.AddService(connection);
                }
                else // sanity check: it makes zero sense to pass a connection in when calling the auth flow
                {
                    Debug.Assert(false, "Calling the auth flow with a connection makes no sense!");
                }

                connection.Login()
                .Select(c => hosts.LookupHost(connection.HostAddress))
                .Do(host =>
                {
                    machine.Configure(UIViewType.None)
                    .Permit(Trigger.Auth, UIViewType.Login)
                    .PermitIf(Trigger.Create, UIViewType.Create, () => host.IsLoggedIn)
                    .PermitIf(Trigger.Create, UIViewType.Login, () => !host.IsLoggedIn)
                    .PermitIf(Trigger.Clone, UIViewType.Clone, () => host.IsLoggedIn)
                    .PermitIf(Trigger.Clone, UIViewType.Login, () => !host.IsLoggedIn)
                    .PermitIf(Trigger.Publish, UIViewType.Publish, () => host.IsLoggedIn)
                    .PermitIf(Trigger.Publish, UIViewType.Login, () => !host.IsLoggedIn);
                })
                .ObserveOn(RxApp.MainThreadScheduler)
                .Subscribe(_ => { }, () =>
                {
                    Debug.WriteLine("Start ({0})", GetHashCode());
                    Fire((Trigger)(int)currentFlow);
                });
            }
            else
            {
                connectionManager
                .GetLoggedInConnections(hosts)
                .FirstOrDefaultAsync()
                .Select(c =>
                {
                    bool loggedin = c != null;
                    if (currentFlow != UIControllerFlow.Authentication)
                    {
                        if (loggedin)     // register the first available connection so the viewmodel can use it
                        {
                            uiProvider.AddService(c);
                        }
                        else
                        {
                            // a connection will be added to the list when auth is done, register it so the next
                            // viewmodel can use it
                            connectionAdded = (s, e) =>
                            {
                                if (e.Action == NotifyCollectionChangedAction.Add)
                                {
                                    uiProvider.AddService(typeof(IConnection), e.NewItems[0]);
                                }
                            };
                            connectionManager.Connections.CollectionChanged += connectionAdded;
                        }
                    }

                    machine.Configure(UIViewType.None)
                    .Permit(Trigger.Auth, UIViewType.Login)
                    .PermitIf(Trigger.Create, UIViewType.Create, () => loggedin)
                    .PermitIf(Trigger.Create, UIViewType.Login, () => !loggedin)
                    .PermitIf(Trigger.Clone, UIViewType.Clone, () => loggedin)
                    .PermitIf(Trigger.Clone, UIViewType.Login, () => !loggedin)
                    .PermitIf(Trigger.Publish, UIViewType.Publish, () => loggedin)
                    .PermitIf(Trigger.Publish, UIViewType.Login, () => !loggedin);

                    return(loggedin);
                })
                .ObserveOn(RxApp.MainThreadScheduler)
                .Subscribe(_ => { }, () =>
                {
                    Debug.WriteLine("Start ({0})", GetHashCode());
                    Fire((Trigger)(int)currentFlow);
                });
            }
        }
 protected ConnectionRepositoryHostMap(IConnection connection, IRepositoryHosts hosts)
     : this(hosts.LookupHost(connection.HostAddress))
 {
 }
        /// <summary>
        /// Configures the UI that gets loaded when entering a certain state and which state
        /// to go to for each trigger. Which state to go to depends on which ui flow state machine
        /// is currently active - when a trigger happens, the PermitDynamic conditions will
        /// lookup the currently active state machine from the list of available ones in `machines`,
        /// fire the requested trigger on it, and return the state that it went to, which causes
        /// `uiStateMachine` to load a new UI (or exit)
        /// There is a bit of redundant information regarding valid state transitions between this
        /// state machine and the individual state machines for each ui flow. This is unavoidable
        /// because permited transition triggers have to be explicit, so care should be taken to
        /// make sure permitted triggers per view here match the permitted triggers in the individual
        /// state machines.
        /// </summary>
        void ConfigureUIHandlingStates()
        {
            uiStateMachine.Configure(UIViewType.None)
            .OnEntry(tr => stopping = false)
            .PermitDynamic(Trigger.Next, () =>
            {
                var loggedIn = connection != null && hosts.LookupHost(connection.HostAddress).IsLoggedIn;
                activeFlow   = loggedIn ? mainFlow : UIControllerFlow.Authentication;
                return(Go(Trigger.Next));
            })
            .PermitDynamic(Trigger.Finish, () => Go(Trigger.Finish));

            uiStateMachine.Configure(UIViewType.Clone)
            .OnEntry(tr => RunView(UIViewType.Clone, CalculateDirection(tr)))
            .PermitDynamic(Trigger.Next, () => Go(Trigger.Next))
            .PermitDynamic(Trigger.Cancel, () => Go(Trigger.Cancel))
            .PermitDynamic(Trigger.Finish, () => Go(Trigger.Finish));

            uiStateMachine.Configure(UIViewType.Create)
            .OnEntry(tr => RunView(UIViewType.Create, CalculateDirection(tr)))
            .PermitDynamic(Trigger.Next, () => Go(Trigger.Next))
            .PermitDynamic(Trigger.Cancel, () => Go(Trigger.Cancel))
            .PermitDynamic(Trigger.Finish, () => Go(Trigger.Finish));

            uiStateMachine.Configure(UIViewType.Publish)
            .OnEntry(tr => RunView(UIViewType.Publish, CalculateDirection(tr)))
            .PermitDynamic(Trigger.Next, () => Go(Trigger.Next))
            .PermitDynamic(Trigger.Cancel, () => Go(Trigger.Cancel))
            .PermitDynamic(Trigger.Finish, () => Go(Trigger.Finish));

            uiStateMachine.Configure(UIViewType.PRList)
            .OnEntry(tr => RunView(UIViewType.PRList, CalculateDirection(tr)))
            .PermitDynamic(Trigger.Next, () => Go(Trigger.Next))
            .PermitDynamic(Trigger.PRDetail, () => Go(Trigger.PRDetail))
            .PermitDynamic(Trigger.PRCreation, () => Go(Trigger.PRCreation))
            .PermitDynamic(Trigger.Cancel, () => Go(Trigger.Cancel))
            .PermitDynamic(Trigger.Finish, () => Go(Trigger.Finish));

            triggers.Add(Trigger.PRDetail, uiStateMachine.SetTriggerParameters <ViewWithData>(Trigger.PRDetail));
            uiStateMachine.Configure(UIViewType.PRDetail)
            .OnEntryFrom(triggers[Trigger.PRDetail], (arg, tr) => RunView(UIViewType.PRDetail, CalculateDirection(tr), arg))
            .PermitDynamic(Trigger.Next, () => Go(Trigger.Next))
            .PermitDynamic(Trigger.Cancel, () => Go(Trigger.Cancel))
            .PermitDynamic(Trigger.Finish, () => Go(Trigger.Finish));

            uiStateMachine.Configure(UIViewType.PRCreation)
            .OnEntry(tr => RunView(UIViewType.PRCreation, CalculateDirection(tr)))
            .PermitDynamic(Trigger.Next, () => Go(Trigger.Next))
            .PermitDynamic(Trigger.Cancel, () => Go(Trigger.Cancel))
            .PermitDynamic(Trigger.Finish, () => Go(Trigger.Finish));

            uiStateMachine.Configure(UIViewType.Login)
            .OnEntry(tr => RunView(UIViewType.Login, CalculateDirection(tr)))
            .PermitDynamic(Trigger.Next, () => Go(Trigger.Next))
            .PermitDynamic(Trigger.Cancel, () => Go(Trigger.Cancel))
            .PermitDynamic(Trigger.Finish, () => Go(Trigger.Finish));

            uiStateMachine.Configure(UIViewType.TwoFactor)
            .OnEntry(tr => RunView(UIViewType.TwoFactor, CalculateDirection(tr)))
            .PermitDynamic(Trigger.Next, () => Go(Trigger.Next))
            .PermitDynamic(Trigger.Cancel, () => Go(Trigger.Cancel))
            .PermitDynamic(Trigger.Finish, () => Go(Trigger.Finish));

            uiStateMachine.Configure(UIViewType.End)
            .OnEntryFrom(Trigger.Cancel, () => End(false))
            .OnEntryFrom(Trigger.Next, () => End(true))
            .OnEntryFrom(Trigger.Finish, () => End(true))
            // clear all the views and viewmodels created by a subflow
            .OnExit(() =>
            {
                // it's important to have the stopping flag set before we do this
                if (activeFlow == mainFlow)
                {
                    completion?.OnNext(Success.Value);
                    completion?.OnCompleted();
                }

                DisposeFlow(activeFlow);

                if (activeFlow == mainFlow)
                {
                    uiProvider.RemoveService(typeof(IConnection), this);
                    transition.OnCompleted();
                    Reset();
                }
                else
                {
                    activeFlow = stopping || LoggedIn ? mainFlow : UIControllerFlow.Authentication;
                }
            })
            .PermitDynamic(Trigger.Next, () =>
            {
                // sets the state to None for the current flow
                var state = Go(Trigger.Next);

                if (activeFlow != mainFlow)
                {
                    if (stopping)
                    {
                        // triggering the End state again so that it can clear up the main flow and really end
                        state = Go(Trigger.Finish, mainFlow);
                    }
                    else
                    {
                        // sets the state to the first UI of the main flow or the auth flow, depending on whether you're logged in
                        state = Go(Trigger.Next, LoggedIn ? mainFlow : UIControllerFlow.Authentication);
                    }
                }
                return(state);
            })
            .Permit(Trigger.Finish, UIViewType.None);
        }
        public RepositoryPublishViewModel(
            IRepositoryHosts hosts,
            IRepositoryPublishService repositoryPublishService,
            INotificationService notificationService,
            IConnectionManager connectionManager,
            IUsageTracker usageTracker)
        {
            this.notificationService = notificationService;
            this.hosts = hosts;
            this.usageTracker = usageTracker;

            title = this.WhenAny(
                x => x.SelectedHost,
                x => x.Value != null ?
                    string.Format(CultureInfo.CurrentCulture, Resources.PublishToTitle, x.Value.Title) :
                    Resources.PublishTitle
            )
            .ToProperty(this, x => x.Title);

            Connections = connectionManager.Connections;
            this.repositoryPublishService = repositoryPublishService;

            if (Connections.Any())
                SelectedConnection = Connections.FirstOrDefault(x => x.HostAddress.IsGitHubDotCom()) ?? Connections[0];

            accounts = this.WhenAny(x => x.SelectedConnection, x => x.Value != null ? hosts.LookupHost(x.Value.HostAddress) : RepositoryHosts.DisconnectedRepositoryHost)
                .Where(x => !(x is DisconnectedRepositoryHost))
                .SelectMany(host => host.ModelService.GetAccounts())
                .ObserveOn(RxApp.MainThreadScheduler)
                .ToProperty(this, x => x.Accounts, initialValue: new ReadOnlyCollection<IAccount>(new IAccount[] {}));

            this.WhenAny(x => x.Accounts, x => x.Value)
                .WhereNotNull()
                .Where(accts => accts.Any())
                .Subscribe(accts => {
                    var selectedAccount = accts.FirstOrDefault();
                    if (selectedAccount != null)
                        SelectedAccount = accts.FirstOrDefault();
                });

            isHostComboBoxVisible = this.WhenAny(x => x.Connections, x => x.Value)
                .WhereNotNull()
                .Select(h => h.Count > 1)
                .ToProperty(this, x => x.IsHostComboBoxVisible);

            InitializeValidation();

            PublishRepository = InitializePublishRepositoryCommand();

            canKeepPrivate = CanKeepPrivateObservable.CombineLatest(PublishRepository.IsExecuting,
                (canKeep, publishing) => canKeep && !publishing)
                .ToProperty(this, x => x.CanKeepPrivate);

            isPublishing = PublishRepository.IsExecuting
                .ToProperty(this, x => x.IsPublishing);

            var defaultRepositoryName = repositoryPublishService.LocalRepositoryName;
            if (!string.IsNullOrEmpty(defaultRepositoryName))
                RepositoryName = defaultRepositoryName;

            this.WhenAny(x => x.SelectedConnection, x => x.SelectedAccount,
                (a,b) => true)
                .Where(x => RepositoryNameValidator.ValidationResult != null && SafeRepositoryNameWarningValidator.ValidationResult != null)
                .Subscribe(async _ =>
                {
                    var name = RepositoryName;
                    RepositoryName = null;
                    await RepositoryNameValidator.ResetAsync();
                    await SafeRepositoryNameWarningValidator.ResetAsync();
                    RepositoryName = name;
                });
        }