Skip to content
This repository was archived by the owner on Jun 21, 2023. It is now read-only.

Commit 17db5c1

Browse files
committed
Merge master into localization
Conflicts: src/GitHub.VisualStudio/UI/Views/Controls/RepositoryPublishControl.xaml
2 parents 64d872f + 7e40aca commit 17db5c1

File tree

19 files changed

+261
-123
lines changed

19 files changed

+261
-123
lines changed

src/GitHub.App/Controllers/UIController.cs

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
using System;
22
using System.ComponentModel.Composition;
33
using System.Diagnostics;
4+
using System.Reactive.Concurrency;
45
using System.Reactive.Disposables;
56
using System.Reactive.Linq;
67
using System.Reactive.Subjects;
8+
using System.Windows;
79
using System.Windows.Controls;
810
using GitHub.Authentication;
911
using GitHub.Exports;
@@ -15,8 +17,7 @@
1517
using NullGuard;
1618
using ReactiveUI;
1719
using Stateless;
18-
using System.Windows;
19-
using System.Reactive.Concurrency;
20+
using System.Collections.Specialized;
2021

2122
namespace GitHub.Controllers
2223
{
@@ -36,6 +37,7 @@ enum Trigger { Cancel = 0, Auth = 1, Create = 2, Clone = 3, Publish = 4, Next, F
3637
readonly StateMachine<UIViewType, Trigger> machine;
3738
Subject<UserControl> transition;
3839
UIControllerFlow currentFlow;
40+
NotifyCollectionChangedEventHandler connectionAdded;
3941

4042
[ImportingConstructor]
4143
public UIController(IUIProvider uiProvider, IRepositoryHosts hosts, IExportFactoryProvider factory,
@@ -236,6 +238,15 @@ public void Start([AllowNull] IConnection connection)
236238
.IsLoggedIn(hosts)
237239
.Do(loggedin =>
238240
{
241+
if (!loggedin && currentFlow != UIControllerFlow.Authentication)
242+
{
243+
connectionAdded = (s, e) => {
244+
if (e.Action == NotifyCollectionChangedAction.Add)
245+
uiProvider.AddService(typeof(IConnection), e.NewItems[0]);
246+
};
247+
connectionManager.Connections.CollectionChanged += connectionAdded;
248+
}
249+
239250
machine.Configure(UIViewType.None)
240251
.Permit(Trigger.Auth, UIViewType.Login)
241252
.PermitIf(Trigger.Create, UIViewType.Create, () => loggedin)
@@ -257,10 +268,7 @@ public void Start([AllowNull] IConnection connection)
257268
public void Stop()
258269
{
259270
Debug.WriteLine("Stop ({0})", GetHashCode());
260-
if (machine.IsInState(UIViewType.End))
261-
Fire(Trigger.Next);
262-
else
263-
Fire(Trigger.Cancel);
271+
Fire(machine.IsInState(UIViewType.End) ? Trigger.Next : Trigger.Cancel);
264272
}
265273

266274
bool disposed; // To detect redundant calls
@@ -273,6 +281,9 @@ protected virtual void Dispose(bool disposing)
273281
Debug.WriteLine("Disposing ({0})", GetHashCode());
274282
disposables.Dispose();
275283
transition?.Dispose();
284+
if (connectionAdded != null)
285+
connectionManager.Connections.CollectionChanged -= connectionAdded;
286+
connectionAdded = null;
276287
disposed = true;
277288
}
278289
}
@@ -283,6 +294,6 @@ public void Dispose()
283294
GC.SuppressFinalize(this);
284295
}
285296

286-
public bool IsStopped { get { return machine.IsInState(UIViewType.Finished); } }
297+
public bool IsStopped => machine.IsInState(UIViewType.Finished);
287298
}
288299
}

src/GitHub.Exports/Exports/ExportMetadata.cs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22
using System.ComponentModel.Composition;
33
using GitHub.UI;
44
using GitHub.ViewModels;
5+
using System.Windows.Controls;
6+
using System.Linq;
7+
using System.Diagnostics;
8+
using System.Reflection;
59

610
namespace GitHub.Exports {
711

@@ -42,4 +46,19 @@ public interface IViewModelMetadata
4246
{
4347
UIViewType ViewType { get; }
4448
}
49+
50+
public static class ExportViewAttributeExtensions
51+
{
52+
public static bool IsViewType(this UserControl c, UIViewType type)
53+
{
54+
return c.GetType().GetCustomAttributesData().Any(attr => IsViewType(attr, type));
55+
}
56+
57+
private static bool IsViewType(CustomAttributeData attributeData, UIViewType viewType)
58+
{
59+
Debug.Assert(attributeData.NamedArguments != null);
60+
return attributeData.AttributeType == typeof(ExportViewAttribute)
61+
&& (UIViewType)attributeData.NamedArguments[0].TypedValue.Value == viewType;
62+
}
63+
}
4564
}

src/GitHub.Exports/GitHub.Exports.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@
101101
</None>
102102
<Compile Include="Helpers\INotifyPropertySource.cs" />
103103
<Compile Include="Helpers\PropertyNotifierExtensions.cs" />
104+
<Compile Include="Helpers\SimpleRepositoryModelExtensions.cs" />
104105
<Compile Include="Info\ApplicationInfo.cs" />
105106
<Compile Include="Models\IAccount.cs" />
106107
<Compile Include="Models\IConnectionManager.cs" />
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
using GitHub.Models;
2+
using System;
3+
using System.Linq;
4+
using System.IO;
5+
6+
namespace GitHub.Extensions
7+
{
8+
using VisualStudio;
9+
10+
public static class SimpleRepositoryModelExtensions
11+
{
12+
public static bool HasCommits(this ISimpleRepositoryModel repository)
13+
{
14+
var repo = Services.GetRepoFromPath(repository.LocalPath);
15+
return repo?.Commits.Any() ?? false;
16+
}
17+
public static bool MightContainSolution(this ISimpleRepositoryModel repository)
18+
{
19+
var dir = new DirectoryInfo(repository.LocalPath);
20+
return dir.EnumerateFileSystemInfos("*", SearchOption.TopDirectoryOnly)
21+
.Any(x => ((x.Attributes.HasFlag(FileAttributes.Directory) || x.Attributes.HasFlag(FileAttributes.Normal)) &&
22+
!x.Name.StartsWith(".", StringComparison.Ordinal) && !x.Name.StartsWith("readme", StringComparison.OrdinalIgnoreCase)));
23+
}
24+
}
25+
}

src/GitHub.Exports/Services/IUIProvider.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
using System.ComponentModel.Composition.Hosting;
33
using GitHub.Models;
44
using GitHub.UI;
5+
using System.Windows.Controls;
56

67
namespace GitHub.Services
78
{
@@ -20,7 +21,7 @@ public interface IUIProvider
2021
void AddService(Type t, object instance);
2122
void RemoveService(Type t);
2223

23-
IObservable<object> SetupUI(UIControllerFlow controllerFlow, IConnection connection);
24+
IObservable<UserControl> SetupUI(UIControllerFlow controllerFlow, IConnection connection);
2425
void RunUI();
2526
void RunUI(UIControllerFlow controllerFlow, IConnection connection);
2627
}

src/GitHub.Exports/Services/Services.cs

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,8 @@
88
using Microsoft.VisualStudio.ComponentModelHost;
99
using Microsoft.VisualStudio.Shell;
1010
using Microsoft.VisualStudio.Shell.Interop;
11-
using Microsoft.VisualStudio.TextManager.Interop;
1211
using Microsoft.VisualStudio.TeamFoundation.Git.Extensibility;
13-
using GitHub.Models;
1412
using GitHub.Info;
15-
using GitHub.Extensions;
1613
using GitHub.Primitives;
1714

1815
namespace GitHub.VisualStudio

src/GitHub.Exports/Services/VSServices.cs

Lines changed: 51 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,18 @@
1-
using Microsoft.TeamFoundation.Git.Controls.Extensibility;
2-
using System;
1+
using System;
2+
using System.Collections.Generic;
33
using System.ComponentModel.Composition;
44
using System.Globalization;
55
using System.Linq;
6+
using System.Windows.Input;
67
using GitHub.Extensions;
7-
using Microsoft.Win32;
8-
using Microsoft.VisualStudio.TeamFoundation.Git.Extensibility;
8+
using GitHub.Models;
99
using GitHub.VisualStudio;
1010
using Microsoft.TeamFoundation.Controls;
11+
using Microsoft.TeamFoundation.Git.Controls.Extensibility;
1112
using Microsoft.VisualStudio;
1213
using Microsoft.VisualStudio.Shell.Interop;
13-
using System.Collections.Generic;
14-
using GitHub.Models;
14+
using Microsoft.VisualStudio.TeamFoundation.Git.Extensibility;
15+
using Microsoft.Win32;
1516

1617
namespace GitHub.Services
1718
{
@@ -25,6 +26,7 @@ public interface IVSServices
2526
string SetDefaultProjectPath(string path);
2627

2728
void ShowMessage(string message);
29+
void ShowMessage(string message, ICommand command);
2830
void ShowWarning(string message);
2931
void ShowError(string message);
3032
void ClearNotifications();
@@ -139,49 +141,76 @@ static string PokeTheRegistryForLocalClonePath()
139141
}
140142
}
141143

142-
const string PathsKey = @"Software\Microsoft\VisualStudio\14.0\NewProjectDialog\MRUSettingsLocalProjectLocationEntries";
144+
const string NewProjectDialogKeyPath = @"Software\Microsoft\VisualStudio\14.0\NewProjectDialog";
145+
const string MRUKeyPath = "MRUSettingsLocalProjectLocationEntries";
143146
public string SetDefaultProjectPath(string path)
144147
{
145148
string old;
146-
using (var key = Registry.CurrentUser.OpenSubKey(PathsKey, true))
149+
using (var newProjectKey = Registry.CurrentUser.OpenSubKey(NewProjectDialogKeyPath, true))
147150
{
148-
old = (string)key?.GetValue("Value0", string.Empty, RegistryValueOptions.DoNotExpandEnvironmentNames);
149-
key?.SetValue("Value0", path, RegistryValueKind.String);
151+
using (var mruKey = newProjectKey?.OpenSubKey(MRUKeyPath, true))
152+
{
153+
if (mruKey == null)
154+
return String.Empty;
155+
156+
// is this already the default path? bail
157+
old = (string)mruKey.GetValue("Value0", string.Empty, RegistryValueOptions.DoNotExpandEnvironmentNames);
158+
if (String.Equals(path.TrimEnd('\\'), old.TrimEnd('\\'), StringComparison.CurrentCultureIgnoreCase))
159+
return old;
160+
161+
// grab the existing list of recent paths, throwing away the last one
162+
var numEntries = (int)mruKey.GetValue("MaximumEntries", 5);
163+
var entries = new List<string>(numEntries);
164+
for (int i = 0; i < numEntries - 1; i++)
165+
{
166+
var val = (string)mruKey.GetValue("Value" + i, String.Empty, RegistryValueOptions.DoNotExpandEnvironmentNames);
167+
if (!String.IsNullOrEmpty(val))
168+
entries.Add(val);
169+
}
170+
171+
newProjectKey.SetValue("LastUsedNewProjectPath", path);
172+
mruKey.SetValue("Value0", path);
173+
// bump list of recent paths one entry down
174+
for (int i = 0; i < entries.Count; i++)
175+
mruKey.SetValue("Value" + (i+1), entries[i]);
176+
}
150177
}
151178
return old;
152179
}
153180

154181
public void ShowMessage(string message)
155182
{
156183
var manager = serviceProvider.TryGetService<ITeamExplorer>() as ITeamExplorerNotificationManager;
157-
if (manager != null)
158-
manager.ShowNotification(message, NotificationType.Information, NotificationFlags.None, null, default(Guid));
184+
manager?.ShowNotification(message, NotificationType.Information, NotificationFlags.None, null, default(Guid));
185+
}
186+
187+
public void ShowMessage(string message, ICommand command)
188+
{
189+
var manager = serviceProvider.TryGetService<ITeamExplorer>() as ITeamExplorerNotificationManager;
190+
manager?.ShowNotification(message, NotificationType.Information, NotificationFlags.None, command, default(Guid));
159191
}
160192

161193
public void ShowWarning(string message)
162194
{
163195
var manager = serviceProvider.TryGetService<ITeamExplorer>() as ITeamExplorerNotificationManager;
164-
if (manager != null)
165-
manager.ShowNotification(message, NotificationType.Warning, NotificationFlags.None, null, default(Guid));
196+
manager?.ShowNotification(message, NotificationType.Warning, NotificationFlags.None, null, default(Guid));
166197
}
167198

168199
public void ShowError(string message)
169200
{
170201
var manager = serviceProvider.TryGetService<ITeamExplorer>() as ITeamExplorerNotificationManager;
171-
if (manager != null)
172-
manager.ShowNotification(message, NotificationType.Error, NotificationFlags.None, null, default(Guid));
202+
manager?.ShowNotification(message, NotificationType.Error, NotificationFlags.None, null, default(Guid));
173203
}
174204

175205
public void ClearNotifications()
176206
{
177207
var manager = serviceProvider.TryGetService<ITeamExplorer>() as ITeamExplorerNotificationManager;
178-
if (manager != null)
179-
manager.ClearNotifications();
180-
}
208+
manager?.ClearNotifications();
209+
}
181210

182211
public void ActivityLogMessage(string message)
183212
{
184-
var log = VisualStudio.Services.GetActivityLog(serviceProvider);
213+
var log = serviceProvider.GetActivityLog();
185214
if (log != null)
186215
{
187216
if (!ErrorHandler.Succeeded(log.LogEntry((UInt32)__ACTIVITYLOG_ENTRYTYPE.ALE_INFORMATION,
@@ -192,7 +221,7 @@ public void ActivityLogMessage(string message)
192221

193222
public void ActivityLogError(string message)
194223
{
195-
var log = VisualStudio.Services.GetActivityLog(serviceProvider);
224+
var log = serviceProvider.GetActivityLog();
196225
if (log != null)
197226
{
198227

@@ -204,7 +233,7 @@ public void ActivityLogError(string message)
204233

205234
public void ActivityLogWarning(string message)
206235
{
207-
var log = VisualStudio.Services.GetActivityLog(serviceProvider);
236+
var log = serviceProvider.GetActivityLog();
208237
if (log != null)
209238
{
210239
if (!ErrorHandler.Succeeded(log.LogEntry((UInt32)__ACTIVITYLOG_ENTRYTYPE.ALE_WARNING,

src/GitHub.VisualStudio/Base/TeamExplorerBase.cs

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,11 +44,15 @@ public Ret GetService<T, Ret>() where Ret : class
4444
return GetService<T>() as Ret;
4545
}
4646

47-
protected virtual void OpenInBrowser(Lazy<IVisualStudioBrowser> browser, Uri uri)
47+
protected static void OpenInBrowser(Lazy<IVisualStudioBrowser> browser, Uri uri)
4848
{
49-
var b = browser.Value;
50-
Debug.Assert(b != null, "Could not create a browser helper instance.");
51-
b?.OpenUrl(uri);
49+
OpenInBrowser(browser.Value, uri);
50+
}
51+
52+
protected static void OpenInBrowser(IVisualStudioBrowser browser, Uri uri)
53+
{
54+
Debug.Assert(browser != null, "Could not create a browser helper instance.");
55+
browser?.OpenUrl(uri);
5256
}
5357
}
5458
}

src/GitHub.VisualStudio/GitHub.VisualStudio.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
</NuGetPackageImportStamp>
99
<TargetFrameworkProfile />
1010
<BuildType Condition="Exists('..\..\script\ApiClientConfiguration.cs')">Internal</BuildType>
11-
<ApplicationVersion>1.0.14.0</ApplicationVersion>
11+
<ApplicationVersion>1.0.15.0</ApplicationVersion>
1212
</PropertyGroup>
1313
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
1414
<PropertyGroup>
Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,15 @@
11
namespace GitHub.VisualStudio.Helpers
22
{
3-
public static class Constants
3+
internal static class Constants
44
{
55
public const string NoAngleBracketsErrorMessage = "Failed to parse signature - Neither `name` nor `email` should contain angle brackets chars.";
66
public const int MaxRepositoryNameLength = 100;
77
public const int MaxDirectoryLength = 200; // Windows allows 248, but we need to allow room for subdirectories.
88
public const int MaxFilePathLength = 260;
9+
10+
public const string Notification_RepoCreated = "[{0}](u:{1}) has been successfully created.";
11+
public const string Notification_RepoCloned = "[{0}](u:{1}) has been successfully cloned.";
12+
public const string Notification_CreateNewProject = "[Create a new project or solution](c:{0}).";
13+
public const string Notification_OpenProject = "[Open an existing project or solution](o:{0}).";
914
}
1015
}

0 commit comments

Comments
 (0)