-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Consolidate VS Command Architecture #1502
Conversation
- Moved `VsCommand` etc out of `GitHub.InlineReviews` and into a new assembly `GitHub.Services.Vssdk` which will be a home for services which have a hard VSSDK dependency. - Moved the command interfaces into `GitHub.Exports` - Made the `VsCommand` classes inherit from `OleMenuCommand` - Removed the automatic package registration stuff
And use it in the `GitHubPaneViewModel`.
And remove old menu framework-related code.
As it causes Rx to get loaded.
Thought I'd need it, turns out I didn't.
| usageTracker.IncrementCounter(x => x.NumberOfGitHubPaneHelpClicks).Forget(); | ||
| }); | ||
| var menuService = (IMenuCommandService)paneServiceProvider.GetService(typeof(IMenuCommandService)); | ||
| BindNavigatorCommand(menuService, PkgCmdIDList.pullRequestCommand, showPullRequests); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a reason you're not using the BindCommand extension method?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
BindNavigatorCommand does use BindCommand. It's just shorthand so we don't have to specify new CommandID(Guids.guidGitHubToolbarCmdSet, PkgCmdIDList.foo) for every command and can just pass the PkgCmdIDList.foo part`.
| protected override void QueryStatus() | ||
| { | ||
| Log.Assert(SelectedTextProvider != null, "Could not get an instance of ISelectedTextProvider"); | ||
| Visible = !string.IsNullOrWhiteSpace(SelectedTextProvider?.GetSelectedText()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unrelated to this PR, but just while I remember. We should default to selecting all text. I bet most people don't even know this command exists! ;-)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added an issue here: #1534
| protected CreateGistCommand(IGitHubServiceProvider serviceProvider) | ||
| : base(CommandSet, CommandId) | ||
| { | ||
| dialogService = new Lazy<IDialogService>(() => serviceProvider.TryGetService<IDialogService>()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm curious why we're not passing Lazy<IDialogService> (and others) into the importing constructor?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good question: basically this is how we were doing it before. I'll try using Lazy<>.
jcansdale
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we be loading InlineReviewsPackage on a background thread?
| [PackageRegistration(UseManagedResourcesOnly = true)] | ||
| [PackageRegistration(UseManagedResourcesOnly = true, AllowsBackgroundLoading = true)] | ||
| [Guid(Guids.InlineReviewsPackageId)] | ||
| [ProvideAutoLoad(UIContextGuids80.SolutionExists)] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This will cause the package to auto-load on the Main thread. I think we should be using this:
[ProvideAutoLoad(UIContextGuids80.SolutionExists, PackageAutoLoadFlags.BackgroundLoad)]
In future we might want to only auto-load when there is an active Git repository (see #1512)?
[ProvideAutoLoad(Guids.UIContext_Git, PackageAutoLoadFlags.BackgroundLoad)]
| { | ||
| base.Initialize(); | ||
| PackageResources.Register(this); | ||
| await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think we should be on the Main thread.
4fecb2c to
d4daa1e
Compare
No need to manually construct Lazy loading using GetService.
Avoid using SwitchToMainThreadAsync because it can hang when called before a solution is loaded.
|
I've made some auto-load related tweaks to the packages that install commands ( Rather than using I've changed There is also some merge related cleanup. |
Be explicit about which code needs the Main thread Don't auto-load in background to prevent potential SwitchToMainThreadAsync hang. SwitchToMainThreadAsync can hang so use ThreadingHelper.MainThreadDispatcher.InvokeAsync instead.
An old issue crept back in during merge.
9cd28b2 to
1baa921
Compare
|
Forget what I said above about using [PackageRegistration(UseManagedResourcesOnly = true, AllowsBackgroundLoading = true)]
[ProvideAutoLoad(Guids.UIContext_Git, PackageAutoLoadFlags.BackgroundLoad)]I'm using the same workaround as in |
Previously in Commands
We previously had two separate command architectures
GitHub.VisualStudio.Menus
These classes had some problems:
GitHub.VisualStudioso couldn't be used in lower-level assembliesserviceProvider.AddCommandHandlerextension method did some sync service requests making it non-ideal for use inAsyncPackagesGitHub.InlineReviews.Commands
These classes were written because of the problems with the prior framework (most notably point 1) but had their own problems:
GitHub.InlineReviewsso couldn't be used in lower-level assemblies (I'd done that with the intention of doing this consolidation at some point)Packagefor servicesThis PR
This PR consolidates the two frameworks and attempts to solve the problems of the two. There are the same
VsCommandandVsCommand<T>classes as in theGitHub.InlineReviews.Commandsnamespace, but:IMenuCommandServiceto register them and removed theAddCommandHandlerextension methods that used syncGetServicecallsICommandso they can be bound in the UIOleCommandrather than wrapping anOleCommandso they can be used wherever anOleCommandis acceptedIMenuCommandService.BindCommandto bind an existingICommand(such as aReactiveCommand) to a VS command. This is used in theGitHubPaneViewModelIn addition, I've added a new assembly:
GitHub.Services.Vssdkfor the implementations. We've been talking about this for a while, and it's really needed here. I originally called itGitHub.Services.VisualStudiobut decided to change it toVssdkbecause we already useVisualStudioinGitHub.VisualStudioand thought it was clearer that it means "abstractions over the VSSDK"Fixes #1489