diff --git a/src/GitHub.App/ViewModels/GitHubPane/PullRequestDetailViewModel.cs b/src/GitHub.App/ViewModels/GitHubPane/PullRequestDetailViewModel.cs index 29947ba8b1..449d884f55 100644 --- a/src/GitHub.App/ViewModels/GitHubPane/PullRequestDetailViewModel.cs +++ b/src/GitHub.App/ViewModels/GitHubPane/PullRequestDetailViewModel.cs @@ -364,7 +364,8 @@ public async Task Load(PullRequestDetailModel pullRequest) Checks = (IReadOnlyList)PullRequestCheckViewModel.Build(viewViewModelFactory, pullRequest)?.ToList() ?? Array.Empty(); - await Files.InitializeAsync(Session); + // Only show unresolved comments + await Files.InitializeAsync(Session, c => !c.IsResolved); var localBranches = await pullRequestsService.GetLocalBranches(LocalRepository, pullRequest).ToList(); diff --git a/src/GitHub.App/ViewModels/PullRequestReviewCommentThreadViewModel.cs b/src/GitHub.App/ViewModels/PullRequestReviewCommentThreadViewModel.cs index 91a9f24f14..f5ddb65bb6 100644 --- a/src/GitHub.App/ViewModels/PullRequestReviewCommentThreadViewModel.cs +++ b/src/GitHub.App/ViewModels/PullRequestReviewCommentThreadViewModel.cs @@ -70,6 +70,9 @@ public IPullRequestSessionFile File /// public DiffSide Side { get; private set; } + /// + public bool IsResolved { get; private set; } + public bool IsNewThread { get => isNewThread; @@ -97,6 +100,7 @@ public async Task InitializeAsync( File = file; LineNumber = thread.LineNumber; Side = thread.DiffLineType == DiffChangeType.Delete ? DiffSide.Left : DiffSide.Right; + IsResolved = thread.IsResolved; foreach (var comment in thread.Comments) { diff --git a/src/GitHub.Exports.Reactive/Models/IInlineCommentThreadModel.cs b/src/GitHub.Exports.Reactive/Models/IInlineCommentThreadModel.cs index ed5cd93908..802971c167 100644 --- a/src/GitHub.Exports.Reactive/Models/IInlineCommentThreadModel.cs +++ b/src/GitHub.Exports.Reactive/Models/IInlineCommentThreadModel.cs @@ -49,5 +49,10 @@ public interface IInlineCommentThreadModel /// Gets the relative path to the file that the thread is on. /// string RelativePath { get; } + + /// + /// Gets a value indicating whether comment thread has been marked as resolved by a user. + /// + bool IsResolved { get; } } } diff --git a/src/GitHub.Exports.Reactive/ViewModels/IPullRequestReviewCommentThreadViewModel.cs b/src/GitHub.Exports.Reactive/ViewModels/IPullRequestReviewCommentThreadViewModel.cs index a1bae3db1b..b669927a07 100644 --- a/src/GitHub.Exports.Reactive/ViewModels/IPullRequestReviewCommentThreadViewModel.cs +++ b/src/GitHub.Exports.Reactive/ViewModels/IPullRequestReviewCommentThreadViewModel.cs @@ -36,6 +36,11 @@ public interface IPullRequestReviewCommentThreadViewModel : ICommentThreadViewMo /// DiffSide Side { get; } + /// + /// Gets a value indicating whether comment thread has been marked as resolved by a user. + /// + bool IsResolved { get; } + /// /// Gets a value indicating whether the thread is a new thread being authored, that is not /// yet present on the server. diff --git a/src/GitHub.Exports/Models/PullRequestReviewThreadModel.cs b/src/GitHub.Exports/Models/PullRequestReviewThreadModel.cs index 76e05823c5..f0eb9a2d43 100644 --- a/src/GitHub.Exports/Models/PullRequestReviewThreadModel.cs +++ b/src/GitHub.Exports/Models/PullRequestReviewThreadModel.cs @@ -33,6 +33,11 @@ public class PullRequestReviewThreadModel /// public bool IsOutdated { get; set; } + /// + /// Gets or sets a value indicating whether the thread is resolved. + /// + public bool IsResolved { get; set; } + /// /// Gets or sets the line position in the diff that the thread starts on. /// diff --git a/src/GitHub.InlineReviews/Models/InlineCommentThreadModel.cs b/src/GitHub.InlineReviews/Models/InlineCommentThreadModel.cs index 18fdf202b1..c47b0adf6f 100644 --- a/src/GitHub.InlineReviews/Models/InlineCommentThreadModel.cs +++ b/src/GitHub.InlineReviews/Models/InlineCommentThreadModel.cs @@ -28,7 +28,8 @@ public InlineCommentThreadModel( string relativePath, string commitSha, IList diffMatch, - IEnumerable comments) + IEnumerable comments, + bool isResolved) { Guard.ArgumentNotNull(relativePath, nameof(relativePath)); Guard.ArgumentNotNull(commitSha, nameof(commitSha)); @@ -39,6 +40,7 @@ public InlineCommentThreadModel( DiffLineType = diffMatch[0].Type; CommitSha = commitSha; RelativePath = relativePath; + IsResolved = isResolved; foreach (var comment in comments) { @@ -74,5 +76,8 @@ public int LineNumber /// public string RelativePath { get; } + + /// + public bool IsResolved { get; } } } diff --git a/src/GitHub.InlineReviews/Services/PullRequestSessionService.cs b/src/GitHub.InlineReviews/Services/PullRequestSessionService.cs index 44b0126e36..d4721b0cd1 100644 --- a/src/GitHub.InlineReviews/Services/PullRequestSessionService.cs +++ b/src/GitHub.InlineReviews/Services/PullRequestSessionService.cs @@ -39,7 +39,8 @@ namespace GitHub.InlineReviews.Services public class PullRequestSessionService : IPullRequestSessionService { static readonly ILogger log = LogManager.ForContext(); - static ICompiledQuery readPullRequest; + static ICompiledQuery readPullRequestWithResolved; + static ICompiledQuery readPullRequestWithoutResolved; static ICompiledQuery> readCommitStatuses; static ICompiledQuery> readCommitStatusesEnterprise; static ICompiledQuery readViewer; @@ -123,7 +124,8 @@ public IReadOnlyList BuildCommentThreads( foreach (var thread in threadsByPosition) { - var hunk = thread.First().DiffHunk; + var reviewThread = thread.First(); + var hunk = reviewThread.DiffHunk; var chunks = DiffUtilities.ParseFragment(hunk); var chunk = chunks.Last(); var diffLines = chunk.Lines.Reverse().Take(5).ToList(); @@ -142,7 +144,8 @@ public IReadOnlyList BuildCommentThreads( { Comment = c, Review = pullRequest.Reviews.FirstOrDefault(x => x.Comments.Contains(c)), - }))); + })), + reviewThread.IsResolved); threads.Add(inlineThread); } @@ -287,11 +290,210 @@ public async Task ReadFileAsync(string path) return null; } - public virtual async Task ReadPullRequestDetail(HostAddress address, string owner, string name, int number) + public virtual Task ReadPullRequestDetail(HostAddress address, string owner, string name, int number) { - if (readPullRequest == null) + // The reviewThreads/isResolved field is only guaranteed to be available on github.com + if (address.IsGitHubDotCom()) + { + return ReadPullRequestDetailWithResolved(address, owner, name, number); + } + else + { + return ReadPullRequestDetailWithoutResolved(address, owner, name, number); + } + } + + async Task ReadPullRequestDetailWithResolved( + HostAddress address, string owner, string name, int number) + { + + if (readPullRequestWithResolved == null) + { + readPullRequestWithResolved = new Query() + .Repository(owner: Var(nameof(owner)), name: Var(nameof(name))) + .PullRequest(number: Var(nameof(number))) + .Select(pr => new PullRequestDetailModel + { + Id = pr.Id.Value, + Number = pr.Number, + Author = new ActorModel + { + Login = pr.Author.Login, + AvatarUrl = pr.Author.AvatarUrl(null), + }, + Title = pr.Title, + Body = pr.Body, + BaseRefSha = pr.BaseRefOid, + BaseRefName = pr.BaseRefName, + BaseRepositoryOwner = pr.Repository.Owner.Login, + HeadRefName = pr.HeadRefName, + HeadRefSha = pr.HeadRefOid, + HeadRepositoryOwner = pr.HeadRepositoryOwner != null ? pr.HeadRepositoryOwner.Login : null, + State = pr.State.FromGraphQl(), + UpdatedAt = pr.UpdatedAt, + CommentCount = pr.Comments(0, null, null, null).TotalCount, + Comments = pr.Comments(null, null, null, null).AllPages().Select(comment => new CommentModel + { + Id = comment.Id.Value, + Author = new ActorModel + { + Login = comment.Author.Login, + AvatarUrl = comment.Author.AvatarUrl(null), + }, + Body = comment.Body, + CreatedAt = comment.CreatedAt, + DatabaseId = comment.DatabaseId.Value, + Url = comment.Url, + }).ToList(), + Threads = pr.ReviewThreads(null, null, null, null).AllPages().Select(thread => new PullRequestReviewThreadModel + { + Comments = thread.Comments(null, null, null, null).AllPages().Select(comment => new CommentAdapter + { + Id = comment.Id.Value, + PullRequestId = comment.PullRequest.Number, + DatabaseId = comment.DatabaseId.Value, + Author = new ActorModel + { + Login = comment.Author.Login, + AvatarUrl = comment.Author.AvatarUrl(null), + }, + Body = comment.Body, + Path = comment.Path, + CommitSha = comment.Commit.Oid, + DiffHunk = comment.DiffHunk, + Position = comment.Position, + OriginalPosition = comment.OriginalPosition, + OriginalCommitId = comment.OriginalCommit.Oid, + ReplyTo = comment.ReplyTo != null ? comment.ReplyTo.Id.Value : null, + PullRequestReviewId = comment.PullRequestReview != null ? comment.PullRequestReview.Id.Value : null, + CreatedAt = comment.CreatedAt, + Url = comment.Url + }).ToList(), + IsResolved = thread.IsResolved + }).ToList(), + Reviews = pr.Reviews(null, null, null, null, null, null).AllPages().Select(review => new PullRequestReviewModel + { + Id = review.Id.Value, + Body = review.Body, + CommitId = review.Commit.Oid, + State = review.State.FromGraphQl(), + SubmittedAt = review.SubmittedAt, + Author = new ActorModel + { + Login = review.Author.Login, + AvatarUrl = review.Author.AvatarUrl(null) + } + }).ToList(), + Timeline = pr.Timeline(null, null, null, null, null).AllPages().Select(item => item.Switch(when => + when.Commit(commit => new CommitModel + { + AbbreviatedOid = commit.AbbreviatedOid, + Author = new CommitActorModel + { + Name = commit.Author.Name, + Email = commit.Author.Email, + User = commit.Author.User != null ? new ActorModel + { + Login = commit.Author.User.Login, + AvatarUrl = commit.Author.User.AvatarUrl(null), + } : null + }, + MessageHeadline = commit.MessageHeadline, + Oid = commit.Oid, + }).IssueComment(comment => new CommentModel + { + Author = new ActorModel + { + Login = comment.Author.Login, + AvatarUrl = comment.Author.AvatarUrl(null), + }, + Body = comment.Body, + CreatedAt = comment.CreatedAt, + DatabaseId = comment.DatabaseId.Value, + Id = comment.Id.Value, + Url = comment.Url, + }))).ToList() + }).Compile(); + } + + var vars = new Dictionary + { + { nameof(owner), owner }, + { nameof(name), name }, + { nameof(number), number }, + }; + + var connection = await graphqlFactory.CreateConnection(address); + var result = await connection.Run(readPullRequestWithResolved, vars); + + var apiClient = await apiClientFactory.Create(address); + + var files = await log.TimeAsync(nameof(apiClient.GetPullRequestFiles), + async () => await apiClient.GetPullRequestFiles(owner, name, number).ToList()); + + var lastCommitModel = await log.TimeAsync(nameof(GetPullRequestLastCommitAdapter), + () => GetPullRequestLastCommitAdapter(address, owner, name, number)); + + result.Statuses = (IReadOnlyList)lastCommitModel.Statuses ?? Array.Empty(); + + if (lastCommitModel.CheckSuites == null) + { + result.CheckSuites = Array.Empty(); + } + else + { + result.CheckSuites = lastCommitModel.CheckSuites; + foreach (var checkSuite in result.CheckSuites) + { + checkSuite.HeadSha = lastCommitModel.HeadSha; + } + } + + result.ChangedFiles = files.Select(file => new PullRequestFileModel + { + FileName = file.FileName, + Sha = file.Sha, + Status = (PullRequestFileStatus)Enum.Parse(typeof(PullRequestFileStatus), file.Status, true), + }).ToList(); + + foreach (var thread in result.Threads) + { + if (thread.Comments.Count > 0 && thread.Comments[0] is CommentAdapter adapter) + { + thread.CommitSha = adapter.CommitSha; + thread.DiffHunk = adapter.DiffHunk; + thread.Id = adapter.Id; + thread.IsOutdated = adapter.Position == null; + thread.OriginalCommitSha = adapter.OriginalCommitId; + thread.OriginalPosition = adapter.OriginalPosition; + thread.Path = adapter.Path; + thread.Position = adapter.Position; + + foreach (var comment in thread.Comments) + { + comment.Thread = thread; + } + } + } + + foreach (var review in result.Reviews) { - readPullRequest = new Query() + review.Comments = result.Threads + .SelectMany(t => t.Comments) + .Cast() + .Where(c => c.PullRequestReviewId == review.Id) + .ToList(); + } + + return result; + } + + async Task ReadPullRequestDetailWithoutResolved( + HostAddress address, string owner, string name, int number) + { + if (readPullRequestWithoutResolved == null) + { + readPullRequestWithoutResolved = new Query() .Repository(owner: Var(nameof(owner)), name: Var(nameof(name))) .PullRequest(number: Var(nameof(number))) .Select(pr => new PullRequestDetailModel @@ -400,7 +602,7 @@ public virtual async Task ReadPullRequestDetail(HostAddr }; var connection = await graphqlFactory.CreateConnection(address); - var result = await connection.Run(readPullRequest, vars); + var result = await connection.Run(readPullRequestWithoutResolved, vars); var apiClient = await apiClientFactory.Create(address); @@ -432,7 +634,63 @@ public virtual async Task ReadPullRequestDetail(HostAddr Status = (PullRequestFileStatus)Enum.Parse(typeof(PullRequestFileStatus), file.Status, true), }).ToList(); - BuildPullRequestThreads(result); + // Build pull request threads + var commentsByReplyId = new Dictionary>(); + + // Get all comments that are not replies. + foreach (CommentAdapter comment in result.Reviews.SelectMany(x => x.Comments)) + { + if (comment.ReplyTo == null) + { + commentsByReplyId.Add(comment.Id, new List { comment }); + } + } + + // Get the comments that are replies and place them into the relevant list. + foreach (CommentAdapter comment in result.Reviews.SelectMany(x => x.Comments).OrderBy(x => x.CreatedAt)) + { + if (comment.ReplyTo != null) + { + List thread = null; + + if (commentsByReplyId.TryGetValue(comment.ReplyTo, out thread)) + { + thread.Add(comment); + } + } + } + + // Build a collection of threads for the information collected above. + var threads = new List(); + + foreach (var threadSource in commentsByReplyId) + { + var adapter = threadSource.Value[0]; + + var thread = new PullRequestReviewThreadModel + { + Comments = threadSource.Value, + CommitSha = adapter.CommitSha, + DiffHunk = adapter.DiffHunk, + Id = adapter.Id, + IsOutdated = adapter.Position == null, + OriginalCommitSha = adapter.OriginalCommitId, + OriginalPosition = adapter.OriginalPosition, + Path = adapter.Path, + Position = adapter.Position, + }; + + // Set a reference to the thread in the comment. + foreach (var comment in threadSource.Value) + { + comment.Thread = thread; + } + + threads.Add(thread); + } + + result.Threads = threads; + return result; } @@ -913,65 +1171,6 @@ async Task GetPullRequestLastCommitAdapter(HostAddress addres return result.First(); } - static void BuildPullRequestThreads(PullRequestDetailModel model) - { - var commentsByReplyId = new Dictionary>(); - - // Get all comments that are not replies. - foreach (CommentAdapter comment in model.Reviews.SelectMany(x => x.Comments)) - { - if (comment.ReplyTo == null) - { - commentsByReplyId.Add(comment.Id, new List { comment }); - } - } - - // Get the comments that are replies and place them into the relevant list. - foreach (CommentAdapter comment in model.Reviews.SelectMany(x => x.Comments).OrderBy(x => x.CreatedAt)) - { - if (comment.ReplyTo != null) - { - List thread = null; - - if (commentsByReplyId.TryGetValue(comment.ReplyTo, out thread)) - { - thread.Add(comment); - } - } - } - - // Build a collection of threads for the information collected above. - var threads = new List(); - - foreach (var threadSource in commentsByReplyId) - { - var adapter = threadSource.Value[0]; - - var thread = new PullRequestReviewThreadModel - { - Comments = threadSource.Value, - CommitSha = adapter.CommitSha, - DiffHunk = adapter.DiffHunk, - Id = adapter.Id, - IsOutdated = adapter.Position == null, - OriginalCommitSha = adapter.OriginalCommitId, - OriginalPosition = adapter.OriginalPosition, - Path = adapter.Path, - Position = adapter.Position, - }; - - // Set a reference to the thread in the comment. - foreach (var comment in threadSource.Value) - { - comment.Thread = thread; - } - - threads.Add(thread); - } - - model.Threads = threads; - } - static Octokit.GraphQL.Model.PullRequestReviewEvent ToGraphQl(Octokit.PullRequestReviewEvent e) { switch (e) @@ -996,6 +1195,7 @@ class CommentAdapter : PullRequestReviewCommentModel public int OriginalPosition { get; set; } public string OriginalCommitId { get; set; } public string ReplyTo { get; set; } + public string PullRequestReviewId { get; set; } } class LastCommitAdapter diff --git a/src/GitHub.InlineReviews/Tags/ShowInlineCommentAnnotationGlyph.xaml b/src/GitHub.InlineReviews/Tags/ShowInlineCommentAnnotationGlyph.xaml index 000ca77afe..5d18e67537 100644 --- a/src/GitHub.InlineReviews/Tags/ShowInlineCommentAnnotationGlyph.xaml +++ b/src/GitHub.InlineReviews/Tags/ShowInlineCommentAnnotationGlyph.xaml @@ -17,14 +17,27 @@ - + StrokeThickness="1"> + + + + - + StrokeThickness="1"> + + + + diff --git a/src/GitHub.InlineReviews/Views/InlineCommentPeekView.xaml b/src/GitHub.InlineReviews/Views/InlineCommentPeekView.xaml index 55cb7fb4af..06bfd3a199 100644 --- a/src/GitHub.InlineReviews/Views/InlineCommentPeekView.xaml +++ b/src/GitHub.InlineReviews/Views/InlineCommentPeekView.xaml @@ -7,6 +7,8 @@ xmlns:cache="clr-namespace:GitHub.UI.Helpers;assembly=GitHub.UI" xmlns:ui="clr-namespace:GitHub.UI;assembly=GitHub.UI" xmlns:ghfvs="https://github.com/github/VisualStudio" + xmlns:imaging="clr-namespace:Microsoft.VisualStudio.Imaging;assembly=Microsoft.VisualStudio.Imaging" + xmlns:catalog="clr-namespace:Microsoft.VisualStudio.Imaging;assembly=Microsoft.VisualStudio.ImageCatalog" mc:Ignorable="d" d:DesignHeight="200" d:DesignWidth="500"> @@ -101,6 +103,26 @@ + + + + + + + + + + diff --git a/src/GitHub.Resources/Resources.Designer.cs b/src/GitHub.Resources/Resources.Designer.cs index 8dcf5d75cc..b02170c714 100644 --- a/src/GitHub.Resources/Resources.Designer.cs +++ b/src/GitHub.Resources/Resources.Designer.cs @@ -19,7 +19,7 @@ namespace GitHub { // class via a tool like ResGen or Visual Studio. // To add or remove a member, edit your .ResX file then rerun ResGen // with the /str option, or rebuild your VS project. - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] public class Resources { @@ -2036,6 +2036,15 @@ public static string ThereArenTAnyOpenPullRequests { } } + /// + /// Looks up a localized string similar to This conversation was marked as resolved. + /// + public static string ThisConversationWasMarkedAsResolved { + get { + return ResourceManager.GetString("ThisConversationWasMarkedAsResolved", resourceCulture); + } + } + /// /// Looks up a localized string similar to Title (required). /// diff --git a/src/GitHub.Resources/Resources.cs-CZ.resx b/src/GitHub.Resources/Resources.cs-CZ.resx index 779560f78e..8549044c4e 100644 --- a/src/GitHub.Resources/Resources.cs-CZ.resx +++ b/src/GitHub.Resources/Resources.cs-CZ.resx @@ -866,4 +866,7 @@ https://git-scm.com/download/win a další + + This conversation was marked as resolved + \ No newline at end of file diff --git a/src/GitHub.Resources/Resources.de-DE.resx b/src/GitHub.Resources/Resources.de-DE.resx index f01bb000e2..f8609ec9b6 100644 --- a/src/GitHub.Resources/Resources.de-DE.resx +++ b/src/GitHub.Resources/Resources.de-DE.resx @@ -866,4 +866,7 @@ https://git-scm.com/download/win und weitere + + This conversation was marked as resolved + \ No newline at end of file diff --git a/src/GitHub.Resources/Resources.es-ES.resx b/src/GitHub.Resources/Resources.es-ES.resx index 62de3c4eee..ef54b2b539 100644 --- a/src/GitHub.Resources/Resources.es-ES.resx +++ b/src/GitHub.Resources/Resources.es-ES.resx @@ -866,4 +866,7 @@ https://git-scm.com/download/win y otros + + This conversation was marked as resolved + \ No newline at end of file diff --git a/src/GitHub.Resources/Resources.fr-FR.resx b/src/GitHub.Resources/Resources.fr-FR.resx index a5569f554a..6e036201be 100644 --- a/src/GitHub.Resources/Resources.fr-FR.resx +++ b/src/GitHub.Resources/Resources.fr-FR.resx @@ -866,4 +866,7 @@ https://git-scm.com/download/win et autres + + This conversation was marked as resolved + \ No newline at end of file diff --git a/src/GitHub.Resources/Resources.it-IT.resx b/src/GitHub.Resources/Resources.it-IT.resx index ead7145fb8..69d0828ec2 100644 --- a/src/GitHub.Resources/Resources.it-IT.resx +++ b/src/GitHub.Resources/Resources.it-IT.resx @@ -866,4 +866,7 @@ https://git-scm.com/download/win e altri + + This conversation was marked as resolved + \ No newline at end of file diff --git a/src/GitHub.Resources/Resources.ja-JP.resx b/src/GitHub.Resources/Resources.ja-JP.resx index fdfa98158c..00b87fded9 100644 --- a/src/GitHub.Resources/Resources.ja-JP.resx +++ b/src/GitHub.Resources/Resources.ja-JP.resx @@ -866,4 +866,7 @@ https://git-scm.com/download/win その他 + + This conversation was marked as resolved + \ No newline at end of file diff --git a/src/GitHub.Resources/Resources.ko-KR.resx b/src/GitHub.Resources/Resources.ko-KR.resx index 67dc764b35..f43e1cec7f 100644 --- a/src/GitHub.Resources/Resources.ko-KR.resx +++ b/src/GitHub.Resources/Resources.ko-KR.resx @@ -866,4 +866,7 @@ https://git-scm.com/download/win 및 기타 + + This conversation was marked as resolved + \ No newline at end of file diff --git a/src/GitHub.Resources/Resources.pl-PL.resx b/src/GitHub.Resources/Resources.pl-PL.resx index d91a3e7e87..79d58049f6 100644 --- a/src/GitHub.Resources/Resources.pl-PL.resx +++ b/src/GitHub.Resources/Resources.pl-PL.resx @@ -866,4 +866,7 @@ https://git-scm.com/download/win i inni + + This conversation was marked as resolved + \ No newline at end of file diff --git a/src/GitHub.Resources/Resources.pt-BR.resx b/src/GitHub.Resources/Resources.pt-BR.resx index 37b390eb2a..509f9ef871 100644 --- a/src/GitHub.Resources/Resources.pt-BR.resx +++ b/src/GitHub.Resources/Resources.pt-BR.resx @@ -866,4 +866,7 @@ https://git-scm.com/download/win e outros + + This conversation was marked as resolved + \ No newline at end of file diff --git a/src/GitHub.Resources/Resources.resx b/src/GitHub.Resources/Resources.resx index ed14bce0d9..0ef7e5f1fc 100644 --- a/src/GitHub.Resources/Resources.resx +++ b/src/GitHub.Resources/Resources.resx @@ -866,4 +866,7 @@ https://git-scm.com/download/win and others + + This conversation was marked as resolved + \ No newline at end of file diff --git a/src/GitHub.Resources/Resources.ru-RU.resx b/src/GitHub.Resources/Resources.ru-RU.resx index 47d8ebabb1..5efc7b01c6 100644 --- a/src/GitHub.Resources/Resources.ru-RU.resx +++ b/src/GitHub.Resources/Resources.ru-RU.resx @@ -866,4 +866,7 @@ https://git-scm.com/download/win и др. + + This conversation was marked as resolved + \ No newline at end of file diff --git a/src/GitHub.Resources/Resources.tr-TR.resx b/src/GitHub.Resources/Resources.tr-TR.resx index 371ab04aea..43dcdab5d1 100644 --- a/src/GitHub.Resources/Resources.tr-TR.resx +++ b/src/GitHub.Resources/Resources.tr-TR.resx @@ -866,4 +866,7 @@ https://git-scm.com/download/win ve diğer kişiler + + This conversation was marked as resolved + \ No newline at end of file diff --git a/src/GitHub.Resources/Resources.zh-CN.resx b/src/GitHub.Resources/Resources.zh-CN.resx index 35f89163ba..133508d9ff 100644 --- a/src/GitHub.Resources/Resources.zh-CN.resx +++ b/src/GitHub.Resources/Resources.zh-CN.resx @@ -866,4 +866,7 @@ https://git-scm.com/download/win 以及其他 + + This conversation was marked as resolved + \ No newline at end of file diff --git a/src/GitHub.Resources/Resources.zh-TW.resx b/src/GitHub.Resources/Resources.zh-TW.resx index 90d915cee9..5e5695c7c7 100644 --- a/src/GitHub.Resources/Resources.zh-TW.resx +++ b/src/GitHub.Resources/Resources.zh-TW.resx @@ -866,4 +866,7 @@ https://git-scm.com/download/win 及其他 + + This conversation was marked as resolved + \ No newline at end of file