diff --git a/src/GitHub.VisualStudio.Contrib/GitHubCommand.cs b/src/GitHub.VisualStudio.Contrib/GitHubCommand.cs index 597d1bf..4c2823e 100644 --- a/src/GitHub.VisualStudio.Contrib/GitHubCommand.cs +++ b/src/GitHub.VisualStudio.Contrib/GitHubCommand.cs @@ -36,8 +36,6 @@ internal override void MenuItemCallback(object sender, EventArgs e) async Task ShowOpenFromGitHubAsync() { var pane = await toolWindowManager.Value.ShowGitHubPane(); - await pane.ShowPullRequests(); - if (pane.Content is INavigationViewModel navigationViewModel) { var viewModel = factory.CreateViewModel(); diff --git a/src/GitHub.VisualStudio.Contrib/UI/ViewModels/HelloWorldViewModel.cs b/src/GitHub.VisualStudio.Contrib/UI/ViewModels/HelloWorldViewModel.cs index c1ca5c1..2541abf 100644 --- a/src/GitHub.VisualStudio.Contrib/UI/ViewModels/HelloWorldViewModel.cs +++ b/src/GitHub.VisualStudio.Contrib/UI/ViewModels/HelloWorldViewModel.cs @@ -1,9 +1,12 @@ using System; +using System.IO; using System.Reactive.Linq; +using System.Threading.Tasks; using System.ComponentModel.Composition; using ReactiveUI; +using GitHub.Services; +using GitHub.Primitives; using GitHub.ViewModels.GitHubPane; -using GitHub.VisualStudio.Contrib.Console; namespace GitHub.VisualStudio.Contrib.UI.ViewModels { @@ -11,27 +14,134 @@ namespace GitHub.VisualStudio.Contrib.UI.ViewModels [PartCreationPolicy(CreationPolicy.NonShared)] public class HelloWorldViewModel : PanePageViewModelBase, IHelloWorldViewModel { + readonly IGitHubContextService contextService; + readonly ITeamExplorerContext teamExplorerContext; + readonly IRepositoryCloneService repositoryCloneService; + + GitHubContext context; + string targetUrl; + string blobName; + string defaultPath; + Uri repositoryUrl; Uri webUrl; [ImportingConstructor] - public HelloWorldViewModel(IConsoleContext console) + public HelloWorldViewModel( + IGitHubContextService contextService, + ITeamExplorerContext teamExplorerContext, + IRepositoryCloneService repositoryCloneService, + IGitHubServiceProvider serviceProvider) { - SayHello = ReactiveCommand.Create(); - SayHello.Subscribe(_ => console.WriteLine("Hello, World!")); + this.contextService = contextService; + this.teamExplorerContext = teamExplorerContext; + this.repositoryCloneService = repositoryCloneService; + + Title = "GitHub URL"; + + // Is the target URL pointing at the active repository + var isActiveRepositoryObservable = + this.WhenAnyValue(x => x.RepositoryUrl).Select(r => r is Uri targetUrl && + teamExplorerContext.ActiveRepository?.CloneUrl is UriString activeUrl && + UriString.RepositoryUrlsAreEqual(activeUrl, targetUrl.ToString())); + + GoTo = ReactiveCommand.Create( + this.WhenAnyValue(x => x.BlobName).Select(b => b != null) + .CombineLatest(isActiveRepositoryObservable, (a, b) => a && b)); + GoTo.Subscribe(_ => + { + var localPath = teamExplorerContext.ActiveRepository?.LocalPath; + contextService.TryOpenFile(localPath, Context); + }); + + Clone = ReactiveCommand.CreateAsyncTask( + (this).WhenAnyValue(x => x.DefaultPath).Select(d => d is string dir && !Directory.Exists(d)) + .CombineLatest(isActiveRepositoryObservable, (a, b) => a && !b), DoCloneAsync); + + Open = ReactiveCommand.Create( + this.WhenAnyValue(x => x.DefaultPath).Select(d => d is string dir && Directory.Exists(d)) + .CombineLatest(isActiveRepositoryObservable, (a, b) => a && !b)); + Open.Subscribe(_ => + { + var dte = serviceProvider.GetService(); + dte.ExecuteCommand("File.OpenFolder", DefaultPath); + dte.ExecuteCommand("View.TfsTeamExplorer"); + contextService.TryOpenFile(DefaultPath, Context); + }); + + Context = contextService.FindContextFromClipboard(); + TargetUrl = Context?.Url; + + this.WhenAnyValue(x => x.TargetUrl).Subscribe(u => + { + Context = contextService.FindContextFromUrl(u); + }); - WebUrl = new Uri("https://github.com/editor-tools/GitHub.VisualStudio.Contrib"); + this.WhenAnyValue(x => x.Context).Subscribe(c => + { + BlobName = c?.BlobName; + RepositoryUrl = c?.Url?.ToRepositoryUrl(); + + DefaultPath = + repositoryCloneService.DefaultClonePath is string home && + context?.Owner is string owner && + context?.RepositoryName is string repositoryName ? + Path.Combine(home, owner, repositoryName) : null; + }); Done = ReactiveCommand.Create(); } - public IReactiveCommand SayHello { get; } + async Task DoCloneAsync(object args) + { + var repositoryName = Path.GetFileName(DefaultPath); + var repositoryPath = Path.GetDirectoryName(DefaultPath); + await repositoryCloneService.CloneRepository(RepositoryUrl.ToString(), repositoryName, repositoryPath); + Open.Execute(null); + return null; + } - public IObservable Done { get; } + public string TargetUrl + { + get { return targetUrl; } + set { this.RaiseAndSetIfChanged(ref targetUrl, value); } + } + + public GitHubContext Context + { + get { return context; } + private set { this.RaiseAndSetIfChanged(ref context, value); } + } + + public string BlobName + { + get { return blobName; } + private set { this.RaiseAndSetIfChanged(ref blobName, value); } + } + + public string DefaultPath + { + get { return defaultPath; } + private set { this.RaiseAndSetIfChanged(ref defaultPath, value); } + } public Uri WebUrl { get { return webUrl; } private set { this.RaiseAndSetIfChanged(ref webUrl, value); } } + + public Uri RepositoryUrl + { + get { return repositoryUrl; } + private set { this.RaiseAndSetIfChanged(ref repositoryUrl, value); } + } + + public IReactiveCommand GoTo { get; } + + public IReactiveCommand Clone { get; } + + public IReactiveCommand Open { get; } + + public IObservable Done { get; } } } \ No newline at end of file diff --git a/src/GitHub.VisualStudio.Contrib/UI/ViewModels/IHelloWorldViewModel.cs b/src/GitHub.VisualStudio.Contrib/UI/ViewModels/IHelloWorldViewModel.cs index b7e083d..2825038 100644 --- a/src/GitHub.VisualStudio.Contrib/UI/ViewModels/IHelloWorldViewModel.cs +++ b/src/GitHub.VisualStudio.Contrib/UI/ViewModels/IHelloWorldViewModel.cs @@ -1,4 +1,5 @@ -using GitHub.ViewModels; +using GitHub.Services; +using GitHub.ViewModels; using GitHub.ViewModels.Dialog; using GitHub.ViewModels.GitHubPane; using ReactiveUI; @@ -7,6 +8,18 @@ namespace GitHub.VisualStudio.Contrib.UI.ViewModels { public interface IHelloWorldViewModel : IViewModel, IDialogContentViewModel, IPanePageViewModel, IOpenInBrowser { - IReactiveCommand SayHello { get; } + IReactiveCommand GoTo { get; } + + IReactiveCommand Clone { get; } + + IReactiveCommand Open { get; } + + string TargetUrl { get; set; } + + string BlobName { get; } + + string DefaultPath { get; } + + GitHubContext Context { get; } } } \ No newline at end of file diff --git a/src/GitHub.VisualStudio.Contrib/UI/Views/HelloWorldView.xaml b/src/GitHub.VisualStudio.Contrib/UI/Views/HelloWorldView.xaml index c002927..d499371 100644 --- a/src/GitHub.VisualStudio.Contrib/UI/Views/HelloWorldView.xaml +++ b/src/GitHub.VisualStudio.Contrib/UI/Views/HelloWorldView.xaml @@ -9,38 +9,56 @@ xmlns:ui="clr-namespace:GitHub.UI;assembly=GitHub.UI" DataContext="{Binding ViewModel}" mc:Ignorable="d"> - - - - - - - - - - - - + + + + + + + + + + + - - + diff --git a/src/GitHub.VisualStudio.Contrib/UI/Views/HelloWorldView.xaml.cs b/src/GitHub.VisualStudio.Contrib/UI/Views/HelloWorldView.xaml.cs index 8338aac..34fe32f 100644 --- a/src/GitHub.VisualStudio.Contrib/UI/Views/HelloWorldView.xaml.cs +++ b/src/GitHub.VisualStudio.Contrib/UI/Views/HelloWorldView.xaml.cs @@ -16,10 +16,18 @@ public partial class HelloWorldView : GenericHelloWorldView { public HelloWorldView() { - this.InitializeComponent(); + InitializeComponent(); this.WhenActivated(d => { + this.WhenAnyObservable(x => x.ViewModel.GoTo.CanExecuteObservable) + .BindTo(this, x => x.GoToPanel.Visibility); + + this.WhenAnyObservable(x => x.ViewModel.Clone.CanExecuteObservable) + .BindTo(this, x => x.ClonePanel.Visibility); + + this.WhenAnyObservable(x => x.ViewModel.Open.CanExecuteObservable) + .BindTo(this, x => x.OpenPanel.Visibility); }); } }