@@ -26,6 +26,8 @@ namespace GitHub.VisualStudio.UI.Views
2626 [ PartCreationPolicy ( CreationPolicy . NonShared ) ]
2727 public class GitHubPaneViewModel : TeamExplorerItemBase , IGitHubPaneViewModel
2828 {
29+ const UIControllerFlow DefaultControllerFlow = UIControllerFlow . PullRequests ;
30+
2931 bool initialized ;
3032 readonly CompositeDisposable disposables = new CompositeDisposable ( ) ;
3133 IUIController uiController ;
@@ -40,6 +42,7 @@ public class GitHubPaneViewModel : TeamExplorerItemBase, IGitHubPaneViewModel
4042 bool navigatingViaArrows ;
4143 bool disabled ;
4244 Microsoft . VisualStudio . Shell . OleMenuCommand back , forward , refresh ;
45+ int latestReloadCallId ;
4346
4447 [ ImportingConstructor ]
4548 public GitHubPaneViewModel ( ISimpleApiClientFactory apiFactory , ITeamExplorerServiceHolder holder ,
@@ -51,8 +54,6 @@ public GitHubPaneViewModel(ISimpleApiClientFactory apiFactory, ITeamExplorerServ
5154 syncContext = SynchronizationContext . Current ;
5255 CancelCommand = ReactiveCommand . Create ( ) ;
5356 Title = "GitHub" ;
54-
55- hosts . WhenAnyValue ( x => x . IsLoggedInToAnyHost ) . Subscribe ( _ => Reload ( ) . Forget ( ) ) ;
5657 }
5758
5859 public override void Initialize ( IServiceProvider serviceProvider )
@@ -87,6 +88,8 @@ public override void Initialize(IServiceProvider serviceProvider)
8788 initialized = true ;
8889
8990 base . Initialize ( serviceProvider ) ;
91+
92+ hosts . WhenAnyValue ( x => x . IsLoggedInToAnyHost ) . Subscribe ( _ => Reload ( ) . Forget ( ) ) ;
9093 }
9194
9295 public void Initialize ( [ AllowNull ] ViewWithData data )
@@ -105,53 +108,103 @@ protected override void RepoChanged(bool changed)
105108 if ( ! changed )
106109 return ;
107110
111+ Stop ( ) ;
108112 IsGitHubRepo = null ;
109113 Reload ( ) . Forget ( ) ;
110114 }
111115
116+ /// <summary>
117+ /// This method is reentrant, so all await calls need to be done before
118+ /// any actions are performed on the data. More recent calls to this method
119+ /// will cause previous calls pending on await calls to exit early.
120+ /// </summary>
121+ /// <returns></returns>
112122 async Task Reload ( [ AllowNull ] ViewWithData data = null , bool navigating = false )
113123 {
124+ if ( ! initialized )
125+ return ;
126+
127+ latestReloadCallId ++ ;
128+ var reloadCallId = latestReloadCallId ;
129+
114130 navigatingViaArrows = navigating ;
115131
116132 if ( ! IsGitHubRepo . HasValue )
117- IsGitHubRepo = await IsAGitHubRepo ( ) ;
118-
119- if ( ! IsGitHubRepo . Value )
120133 {
121- if ( uiController != null )
122- {
123- Stop ( ) ;
124- //var factory = ServiceProvider.GetExportedValue<IUIFactory>();
125- //var c = factory.CreateViewAndViewModel(UIViewType.LoggedOut);
126- //Control = c.View;
127- }
128- return ;
134+ var isGitHubRepo = await IsAGitHubRepo ( ) ;
135+ if ( reloadCallId != latestReloadCallId )
136+ return ;
137+
138+ IsGitHubRepo = isGitHubRepo ;
129139 }
130140
131141 var connection = await connectionManager . LookupConnection ( ActiveRepo ) ;
132- IsLoggedIn = await connection . IsLoggedIn ( hosts ) ;
142+ if ( reloadCallId != latestReloadCallId )
143+ return ;
133144
134- if ( IsLoggedIn )
145+ if ( connection == null )
146+ IsLoggedIn = false ;
147+ else
135148 {
136- if ( uiController == null || ( data != null && data . ActiveFlow != uiController . SelectedFlow ) )
137- StartFlow ( data ? . ActiveFlow ?? UIControllerFlow . PullRequests , connection , data ) ;
138- else if ( data != null || currentNavItem >= 0 )
139- uiController . Jump ( data ?? navStack [ currentNavItem ] ) ;
149+ var isLoggedIn = await connection . IsLoggedIn ( hosts ) ;
150+ if ( reloadCallId != latestReloadCallId )
151+ return ;
152+
153+ IsLoggedIn = isLoggedIn ;
140154 }
155+
156+ if ( ! IsGitHubRepo . Value )
157+ {
158+ //LoadView(UIViewType.NotAGitHubRepo);
159+ }
160+
161+ else if ( ! IsLoggedIn )
162+ {
163+ LoadView ( UIViewType . LoggedOut ) ;
164+ }
165+
141166 else
167+ {
168+ LoadView ( data ? . ActiveFlow ?? DefaultControllerFlow , connection , data ) ;
169+ }
170+ }
171+
172+ void LoadView ( UIControllerFlow flow , IConnection connection = null , ViewWithData data = null , UIViewType type = UIViewType . None )
173+ {
174+ // if we're loading a single view or a different flow, we need to stop the current controller
175+ var restart = flow == UIControllerFlow . None || uiController ? . SelectedFlow != flow ;
176+
177+ if ( restart )
178+ Stop ( ) ;
179+
180+ // if there's no selected flow, then just load a view directly
181+ if ( flow == UIControllerFlow . None )
142182 {
143183 var factory = ServiceProvider . GetExportedValue < IUIFactory > ( ) ;
144- var c = factory . CreateViewAndViewModel ( UIViewType . LoggedOut ) ;
184+ var c = factory . CreateViewAndViewModel ( type ) ;
145185 c . View . DataContext = c . ViewModel ;
146186 Control = c . View ;
147187 }
148- return ;
188+ // it's a new flow!
189+ else if ( restart )
190+ {
191+ StartFlow ( flow , connection , data ) ;
192+ }
193+ // navigate to a requested view within the currently running uiController
194+ else
195+ {
196+ uiController . Jump ( data ?? navStack [ currentNavItem ] ) ;
197+ }
198+ }
199+
200+ void LoadView ( UIViewType type )
201+ {
202+ LoadView ( UIControllerFlow . None , type : type ) ;
149203 }
150204
151205 void StartFlow ( UIControllerFlow controllerFlow , [ AllowNull ] IConnection conn , ViewWithData data = null )
152206 {
153- if ( uiController != null )
154- Stop ( ) ;
207+ Stop ( ) ;
155208
156209 if ( conn == null )
157210 return ;
@@ -249,12 +302,17 @@ void DisableButtons()
249302
250303 void Stop ( )
251304 {
305+ if ( uiController == null )
306+ return ;
307+
308+ DisableButtons ( ) ;
252309 windowController ? . Close ( ) ;
253310 uiController . Stop ( ) ;
254311 disposables . Clear ( ) ;
255312 uiController = null ;
256313 currentNavItem = - 1 ;
257314 navStack . Clear ( ) ;
315+ UpdateToolbar ( ) ;
258316 }
259317
260318 string title ;
@@ -307,4 +365,4 @@ protected override void Dispose(bool disposing)
307365 base . Dispose ( disposing ) ;
308366 }
309367 }
310- }
368+ }
0 commit comments