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

Commit a960664

Browse files
committed
Merge pull request #79 from github/shana/48-publish-sticks-around
Fix publish form not getting hidden after publishing is done
2 parents e830675 + 70a9090 commit a960664

14 files changed

+125
-39
lines changed

src/GitHub.App/SampleData/SampleViewModels.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -388,7 +388,7 @@ public long PrivateReposInPlan
388388
}
389389

390390
[ExcludeFromCodeCoverage]
391-
public class RepositoryModelDesigner : IRepositoryModel
391+
public class RepositoryModelDesigner : NotificationAwareObject, IRepositoryModel
392392
{
393393
public RepositoryModelDesigner() : this("repo")
394394
{
@@ -416,6 +416,8 @@ public void SetIcon(bool isPrivate, bool isFork)
416416
public Octicon Icon { get; set; }
417417

418418
public IAccount Owner { get; set; }
419+
420+
public void Refresh() { }
419421
}
420422

421423
public class RepositoryCloneViewModelDesigner : BaseViewModelDesigner, IRepositoryCloneViewModel

src/GitHub.Exports/Extensions/SimpleRepositoryModelExtensions.cs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,7 @@ public static ISimpleRepositoryModel ToModel(this IGitRepositoryInfo repo)
1515
{
1616
if (repo == null)
1717
return null;
18-
var uri = repo.GetUriFromRepository();
19-
var name = uri?.NameWithOwner;
20-
return name != null ? new SimpleRepositoryModel(name, uri, repo.RepositoryPath) : null;
18+
return SimpleRepositoryModel.Create(repo.RepositoryPath);
2119
}
2220

2321
public static bool HasCommits(this ISimpleRepositoryModel repository)
Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,22 @@
11
using GitHub.Primitives;
22
using GitHub.UI;
3+
using System.ComponentModel;
34

45
namespace GitHub.Models
56
{
6-
public interface ISimpleRepositoryModel
7+
public interface ISimpleRepositoryModel : INotifyPropertyChanged
78
{
89
string Name { get; }
910
UriString CloneUrl { get; }
1011
string LocalPath { get; }
1112
Octicon Icon { get; }
1213

1314
void SetIcon(bool isPrivate, bool isFork);
15+
16+
17+
/// <summary>
18+
/// Updates the url information based on the local path
19+
/// </summary>
20+
void Refresh();
1421
}
1522
}

src/GitHub.Exports/Models/SimpleRepositoryModel.cs

Lines changed: 47 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
1-
using GitHub.Primitives;
1+
using GitHub.Extensions;
2+
using GitHub.Primitives;
23
using GitHub.UI;
4+
using GitHub.VisualStudio;
35
using GitHub.VisualStudio.Helpers;
46
using System;
57
using System.Diagnostics;
68
using System.Globalization;
9+
using System.IO;
710

811
namespace GitHub.Models
912
{
@@ -18,6 +21,32 @@ public SimpleRepositoryModel(string name, UriString cloneUrl, string localPath =
1821
Icon = Octicon.repo;
1922
}
2023

24+
public SimpleRepositoryModel(string path)
25+
{
26+
if (path == null)
27+
throw new ArgumentNullException(nameof(path));
28+
var dir = new DirectoryInfo(path);
29+
if (!dir.Exists)
30+
throw new ArgumentException("Path does not exist", nameof(path));
31+
var uri = GitHelpers.GetRepoFromPath(path)?.GetUri();
32+
var name = uri?.NameWithOwner;
33+
if (name == null)
34+
name = dir.Name;
35+
Name = name;
36+
LocalPath = path;
37+
CloneUrl = uri;
38+
Icon = Octicon.repo;
39+
}
40+
41+
public static ISimpleRepositoryModel Create(string path)
42+
{
43+
if (path == null)
44+
return null;
45+
if (!Directory.Exists(path))
46+
return null;
47+
return new SimpleRepositoryModel(path);
48+
}
49+
2150
public void SetIcon(bool isPrivate, bool isFork)
2251
{
2352
Icon = isPrivate
@@ -27,15 +56,30 @@ public void SetIcon(bool isPrivate, bool isFork)
2756
: Octicon.repo;
2857
}
2958

59+
public void Refresh()
60+
{
61+
if (LocalPath == null)
62+
return;
63+
var uri = GitHelpers.GetRepoFromPath(LocalPath)?.GetUri();
64+
if (CloneUrl != uri)
65+
CloneUrl = uri;
66+
}
67+
3068
public string Name { get; private set; }
31-
public UriString CloneUrl { get; private set; }
69+
UriString cloneUrl;
70+
public UriString CloneUrl { get { return cloneUrl; } set { cloneUrl = value; this.RaisePropertyChange(); } }
3271
public string LocalPath { get; private set; }
3372
Octicon icon;
3473
public Octicon Icon { get { return icon; } set { icon = value; this.RaisePropertyChange(); } }
3574

75+
/// <summary>
76+
/// Note: We don't consider CloneUrl a part of the hash code because it can change during the lifetime
77+
/// of a repository. Equals takes care of any hash collisions because of this
78+
/// </summary>
79+
/// <returns></returns>
3680
public override int GetHashCode()
3781
{
38-
return (Name?.GetHashCode() ?? 0) ^ (CloneUrl?.GetHashCode() ?? 0) ^ (LocalPath?.TrimEnd('\\').ToUpperInvariant().GetHashCode() ?? 0);
82+
return (Name?.GetHashCode() ?? 0) ^ (LocalPath?.TrimEnd('\\').ToUpperInvariant().GetHashCode() ?? 0);
3983
}
4084

4185
public override bool Equals(object obj)

src/GitHub.Exports/Services/ITeamExplorerServiceHolder.cs

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using System;
22
using GitHub.Primitives;
33
using Microsoft.VisualStudio.TeamFoundation.Git.Extensibility;
4+
using GitHub.Models;
45

56
namespace GitHub.Services
67
{
@@ -28,25 +29,30 @@ public interface ITeamExplorerServiceHolder
2829
/// <summary>
2930
/// A IGitRepositoryInfo representing the currently active repository
3031
/// </summary>
31-
IGitRepositoryInfo ActiveRepo { get; }
32+
ISimpleRepositoryModel ActiveRepo { get; }
3233
/// <summary>
3334
/// Subscribe to be notified when the active repository is set and Notify is called.
3435
/// </summary>
3536
/// <param name="who">The instance that is interested in being called (or a unique key/object for that instance)</param>
3637
/// <param name="handler">The handler to call when ActiveRepo is set</param>
37-
void Subscribe(object who, Action<IGitRepositoryInfo> handler);
38+
void Subscribe(object who, Action<ISimpleRepositoryModel> handler);
3839
/// <summary>
3940
/// Unsubscribe from notifications
4041
/// </summary>
4142
/// <param name="who">The instance/key that previously subscribed to notifications</param>
4243
void Unsubscribe(object who);
4344

4445
IGitAwareItem HomeSection { get; }
46+
47+
/// <summary>
48+
/// Refresh the information on the active repo (in case of remote url changes or other such things)
49+
/// </summary>
50+
void Refresh();
4551
}
4652

4753
public interface IGitAwareItem
4854
{
49-
IGitRepositoryInfo ActiveRepo { get; }
55+
ISimpleRepositoryModel ActiveRepo { get; }
5056

5157
/// <summary>
5258
/// Represents the web URL of the repository on GitHub.com, even if the origin is an SSH address.

src/GitHub.VisualStudio/Base/TeamExplorerGitRepoInfo.cs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
using GitHub.Primitives;
1+
using GitHub.Models;
2+
using GitHub.Primitives;
23
using GitHub.Services;
34
using Microsoft.VisualStudio.TeamFoundation.Git.Extensibility;
45
using NullGuard;
@@ -12,9 +13,9 @@ public TeamExplorerGitRepoInfo()
1213
ActiveRepo = null;
1314
}
1415

15-
IGitRepositoryInfo activeRepo;
16+
ISimpleRepositoryModel activeRepo;
1617
[AllowNull]
17-
public IGitRepositoryInfo ActiveRepo
18+
public ISimpleRepositoryModel ActiveRepo
1819
{
1920
[return: AllowNull]
2021
get { return activeRepo; }

src/GitHub.VisualStudio/Base/TeamExplorerItemBase.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ protected virtual void RepoChanged()
5050
var repo = ActiveRepo;
5151
if (repo != null)
5252
{
53-
var uri = repo.GetUriFromRepository();
53+
var uri = repo.CloneUrl;
5454
if (uri?.RepositoryName != null)
5555
{
5656
ActiveRepoUri = uri;

src/GitHub.VisualStudio/Base/TeamExplorerNavigationItemBase.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
using Microsoft.VisualStudio.PlatformUI;
1111
using Microsoft.VisualStudio.TeamFoundation.Git.Extensibility;
1212
using NullGuard;
13+
using GitHub.Models;
1314

1415
namespace GitHub.VisualStudio.Base
1516
{
@@ -56,7 +57,7 @@ void OnThemeChanged()
5657
}
5758
}
5859

59-
void UpdateRepo(IGitRepositoryInfo repo)
60+
void UpdateRepo(ISimpleRepositoryModel repo)
6061
{
6162
ActiveRepo = repo;
6263
RepoChanged();

src/GitHub.VisualStudio/Base/TeamExplorerSectionBase.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ public virtual void SaveContext(object sender, SectionSaveContextEventArgs e)
100100

101101
void SubscribeToRepoChanges()
102102
{
103-
holder.Subscribe(this, (IGitRepositoryInfo repo) =>
103+
holder.Subscribe(this, (ISimpleRepositoryModel repo) =>
104104
{
105105
ActiveRepo = repo;
106106
RepoChanged();

src/GitHub.VisualStudio/Base/TeamExplorerServiceHolder.cs

Lines changed: 44 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,16 @@
1111
using System.Linq;
1212
using System.Threading;
1313
using System.Globalization;
14+
using GitHub.Models;
1415

1516
namespace GitHub.VisualStudio.Base
1617
{
1718
[Export(typeof(ITeamExplorerServiceHolder))]
1819
[PartCreationPolicy(CreationPolicy.Shared)]
1920
public class TeamExplorerServiceHolder : ITeamExplorerServiceHolder
2021
{
21-
readonly Dictionary<object, Action<IGitRepositoryInfo>> activeRepoHandlers = new Dictionary<object, Action<IGitRepositoryInfo>>();
22-
IGitRepositoryInfo activeRepo;
22+
readonly Dictionary<object, Action<ISimpleRepositoryModel>> activeRepoHandlers = new Dictionary<object, Action<ISimpleRepositoryModel>>();
23+
ISimpleRepositoryModel activeRepo;
2324
bool activeRepoNotified = false;
2425

2526
IServiceProvider serviceProvider;
@@ -48,35 +49,50 @@ public IServiceProvider ServiceProvider
4849
if (serviceProvider == null)
4950
return;
5051
GitUIContext = GitUIContext ?? UIContext.FromUIContextGuid(new Guid("11B8E6D7-C08B-4385-B321-321078CDD1F8"));
51-
UIContextChanged(GitUIContext?.IsActive ?? false);
52+
UIContextChanged(GitUIContext?.IsActive ?? false, false);
5253
}
5354
}
5455

5556
[AllowNull]
56-
public IGitRepositoryInfo ActiveRepo
57+
public ISimpleRepositoryModel ActiveRepo
5758
{
5859
[return: AllowNull] get { return activeRepo; }
5960
private set
6061
{
61-
if (activeRepo.Compare(value))
62+
if (activeRepo == value)
6263
return;
64+
if (activeRepo != null)
65+
activeRepo.PropertyChanged -= ActiveRepoPropertyChanged;
6366
activeRepo = value;
67+
if (activeRepo != null)
68+
activeRepo.PropertyChanged += ActiveRepoPropertyChanged;
6469
NotifyActiveRepo();
6570
}
6671
}
6772

68-
public void Subscribe(object who, Action<IGitRepositoryInfo> handler)
73+
public void Subscribe(object who, Action<ISimpleRepositoryModel> handler)
6974
{
75+
bool notificationsExist;
76+
ISimpleRepositoryModel repo;
7077
lock(activeRepoHandlers)
7178
{
72-
var repo = ActiveRepo;
79+
repo = ActiveRepo;
80+
notificationsExist = activeRepoNotified;
7381
if (!activeRepoHandlers.ContainsKey(who))
7482
activeRepoHandlers.Add(who, handler);
7583
else
7684
activeRepoHandlers[who] = handler;
77-
if (activeRepoNotified)
78-
handler(repo);
7985
}
86+
87+
// the repo url might have changed and we don't get notifications
88+
// for that, so this is a good place to refresh it in case that happened
89+
repo?.Refresh();
90+
91+
// if the active repo hasn't changed and there's notifications queued up,
92+
// notify the subscriber. If the repo has changed, the set above will trigger
93+
// notifications so we don't have to do it here.
94+
if (repo == ActiveRepo && notificationsExist)
95+
handler(repo);
8096
}
8197

8298
public void Unsubscribe(object who)
@@ -100,6 +116,12 @@ public void ClearServiceProvider(IServiceProvider provider)
100116
ServiceProvider = null;
101117
}
102118

119+
public void Refresh()
120+
{
121+
GitUIContext = GitUIContext ?? UIContext.FromUIContextGuid(new Guid("11B8E6D7-C08B-4385-B321-321078CDD1F8"));
122+
UIContextChanged(GitUIContext?.IsActive ?? false, true);
123+
}
124+
103125
void NotifyActiveRepo()
104126
{
105127
lock (activeRepoHandlers)
@@ -113,10 +135,10 @@ void NotifyActiveRepo()
113135
void UIContextChanged(object sender, UIContextChangedEventArgs e)
114136
{
115137
ActiveRepo = null;
116-
UIContextChanged(e.Activated);
138+
UIContextChanged(e.Activated, false);
117139
}
118140

119-
async void UIContextChanged(bool active)
141+
async void UIContextChanged(bool active, bool refresh)
120142
{
121143
Debug.Assert(ServiceProvider != null, "UIContextChanged called before service provider is set");
122144
if (ServiceProvider == null)
@@ -125,7 +147,7 @@ async void UIContextChanged(bool active)
125147
if (active)
126148
{
127149
GitService = GitService ?? ServiceProvider.GetService<IGitExt>();
128-
if (ActiveRepo == null)
150+
if (ActiveRepo == null || refresh)
129151
ActiveRepo = await System.Threading.Tasks.Task.Run(() =>
130152
{
131153
var repos = GitService?.ActiveRepositories;
@@ -140,7 +162,7 @@ async void UIContextChanged(bool active)
140162
if (repos == null)
141163
VsOutputLogger.WriteLine(string.Format(CultureInfo.CurrentCulture, "Error 2002: ActiveRepositories is null. GitService: '{0}'", GitService));
142164
}
143-
return repos?.FirstOrDefault();
165+
return repos?.FirstOrDefault()?.ToModel();
144166
});
145167
}
146168
else
@@ -156,11 +178,16 @@ void CheckAndUpdate(object sender, System.ComponentModel.PropertyChangedEventArg
156178
if (service == null)
157179
return;
158180

159-
var repo = service.ActiveRepositories.FirstOrDefault();
160-
// this comparison is safe, the extension method supports null instances
161-
if (!repo.Compare(ActiveRepo))
181+
var repo = service.ActiveRepositories.FirstOrDefault()?.ToModel();
182+
if (repo != ActiveRepo)
162183
// so annoying that this is on the wrong thread
163-
syncContext.Post(r => ActiveRepo = r as IGitRepositoryInfo, repo);
184+
syncContext.Post(r => ActiveRepo = r as ISimpleRepositoryModel, repo);
185+
}
186+
187+
void ActiveRepoPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
188+
{
189+
if (e.PropertyName == "CloneUrl")
190+
ActiveRepo = sender as ISimpleRepositoryModel;
164191
}
165192

166193
public IGitAwareItem HomeSection

0 commit comments

Comments
 (0)