diff --git a/Classes/Issues/Comments/Details/IssueCommentDetailCell.swift b/Classes/Issues/Comments/Details/IssueCommentDetailCell.swift
index 54ba5cbff..81e814d0d 100644
--- a/Classes/Issues/Comments/Details/IssueCommentDetailCell.swift
+++ b/Classes/Issues/Comments/Details/IssueCommentDetailCell.swift
@@ -24,6 +24,7 @@ final class IssueCommentDetailCell: IssueCommentBaseCell, ListBindable {
private let loginLabel = UILabel()
private let dateLabel = ShowMoreDetailsLabel()
private let editedLabel = ShowMoreDetailsLabel()
+ private let badgeView = IssueDetailBadgeView()
private var login = ""
override init(frame: CGRect) {
@@ -72,6 +73,12 @@ final class IssueCommentDetailCell: IssueCommentBaseCell, ListBindable {
make.left.equalTo(loginLabel.snp.right).offset(Styles.Sizes.columnSpacing/2)
make.centerY.equalTo(loginLabel)
}
+
+ contentView.addSubview(badgeView)
+ badgeView.snp.makeConstraints { make in
+ make.centerY.equalTo(dateLabel)
+ make.right.equalTo(dateLabel.snp.left).offset(-Styles.Sizes.columnSpacing)
+ }
}
required init?(coder aDecoder: NSCoder) {
@@ -96,6 +103,7 @@ final class IssueCommentDetailCell: IssueCommentBaseCell, ListBindable {
imageView.sd_setImage(with: viewModel.avatarURL)
dateLabel.setText(date: viewModel.date, format: .short)
loginLabel.text = viewModel.login
+ badgeView.isHidden = !viewModel.sentWithGitHawk
if let editedLogin = viewModel.editedBy, let editedDate = viewModel.editedAt {
editedLabel.isHidden = false
diff --git a/Classes/Issues/Comments/Details/IssueCommentDetailsViewModel.swift b/Classes/Issues/Comments/Details/IssueCommentDetailsViewModel.swift
index 44c2dd4d5..ef444e385 100644
--- a/Classes/Issues/Comments/Details/IssueCommentDetailsViewModel.swift
+++ b/Classes/Issues/Comments/Details/IssueCommentDetailsViewModel.swift
@@ -17,6 +17,7 @@ final class IssueCommentDetailsViewModel: ListDiffable {
let didAuthor: Bool
let editedBy: String?
let editedAt: Date?
+ let sentWithGitHawk: Bool
init(
date: Date,
@@ -24,7 +25,8 @@ final class IssueCommentDetailsViewModel: ListDiffable {
avatarURL: URL,
didAuthor: Bool,
editedBy: String?,
- editedAt: Date?
+ editedAt: Date?,
+ sentWithGitHawk: Bool
) {
self.date = date
self.login = login
@@ -32,6 +34,7 @@ final class IssueCommentDetailsViewModel: ListDiffable {
self.didAuthor = didAuthor
self.editedBy = editedBy
self.editedAt = editedAt
+ self.sentWithGitHawk = sentWithGitHawk
}
func diffIdentifier() -> NSObjectProtocol {
diff --git a/Classes/Issues/Comments/Details/IssueDetailBadgeView.swift b/Classes/Issues/Comments/Details/IssueDetailBadgeView.swift
new file mode 100644
index 000000000..a4c4cdf89
--- /dev/null
+++ b/Classes/Issues/Comments/Details/IssueDetailBadgeView.swift
@@ -0,0 +1,53 @@
+//
+// IssueDetailBadgeView.swift
+// Freetime
+//
+// Created by Ryan Nystrom on 7/29/18.
+// Copyright © 2018 Ryan Nystrom. All rights reserved.
+//
+
+import UIKit
+
+final class IssueDetailBadgeView: UIImageView {
+
+ init() {
+ super.init(frame: .zero)
+ image = UIImage(named: "githawk-badge")?.withRenderingMode(.alwaysTemplate)
+ tintColor = Styles.Colors.Blue.medium.color
+
+ isUserInteractionEnabled = true
+
+ let tap = UITapGestureRecognizer(
+ target: self,
+ action: #selector(ShowMoreDetailsLabel.showMenu(recognizer:))
+ )
+ addGestureRecognizer(tap)
+ }
+
+ required init?(coder aDecoder: NSCoder) {
+ fatalError("init(coder:) has not been implemented")
+ }
+
+ override var canBecomeFirstResponder: Bool {
+ return true
+ }
+
+ // MARK: Private API
+
+ @objc func showMenu(recognizer: UITapGestureRecognizer) {
+ becomeFirstResponder()
+
+ let menu = UIMenuController.shared
+ menu.menuItems = [
+ UIMenuItem(
+ title: NSLocalizedString("Sent with GitHawk", comment: ""),
+ action: #selector(IssueDetailBadgeView.empty)
+ )
+ ]
+ menu.setTargetRect(bounds, in: self)
+ menu.setMenuVisible(true, animated: trueUnlessReduceMotionEnabled)
+ }
+
+ @objc func empty() {}
+
+}
diff --git a/Classes/Issues/Comments/Markdown/CheckIfSentWithGitHawk.swift b/Classes/Issues/Comments/Markdown/CheckIfSentWithGitHawk.swift
new file mode 100644
index 000000000..11cce0ca2
--- /dev/null
+++ b/Classes/Issues/Comments/Markdown/CheckIfSentWithGitHawk.swift
@@ -0,0 +1,18 @@
+//
+// CheckIfSentWithGitHawk.swift
+// Freetime
+//
+// Created by Ryan Nystrom on 7/29/18.
+// Copyright © 2018 Ryan Nystrom. All rights reserved.
+//
+
+import Foundation
+
+func CheckIfSentWithGitHawk(markdown: String) -> (sentWithGitHawk: Bool, markdown: String) {
+ let nsstring = markdown as NSString
+ let range = nsstring.range(of: Signature.signature, options: .backwards)
+ if range.location != NSNotFound && range.location + range.length == nsstring.length {
+ return (true, nsstring.replacingCharacters(in: range, with: ""))
+ }
+ return (false, markdown)
+}
diff --git a/Classes/Issues/IssueViewModels.swift b/Classes/Issues/IssueViewModels.swift
index 0db80266c..0d20d4bb5 100644
--- a/Classes/Issues/IssueViewModels.swift
+++ b/Classes/Issues/IssueViewModels.swift
@@ -65,17 +65,20 @@ func createCommentModel(
let avatarURL = URL(string: author.avatarUrl)
else { return nil }
+ let checkedMarkdown = CheckIfSentWithGitHawk(markdown: commentFields.body)
+
let details = IssueCommentDetailsViewModel(
date: date,
login: author.login,
avatarURL: avatarURL,
didAuthor: commentFields.viewerDidAuthor,
editedBy: commentFields.editor?.login,
- editedAt: commentFields.lastEditedAt?.githubDate
+ editedAt: commentFields.lastEditedAt?.githubDate,
+ sentWithGitHawk: checkedMarkdown.sentWithGitHawk
)
let bodies = MarkdownModels(
- commentFields.body,
+ checkedMarkdown.markdown,
owner: owner,
repo: repo,
width: width,
diff --git a/Classes/PullRequestReviews/GithubClient+PullRequestReviewComments.swift b/Classes/PullRequestReviews/GithubClient+PullRequestReviewComments.swift
index 6b2003fa1..8bd57ce67 100644
--- a/Classes/PullRequestReviews/GithubClient+PullRequestReviewComments.swift
+++ b/Classes/PullRequestReviews/GithubClient+PullRequestReviewComments.swift
@@ -177,18 +177,21 @@ private func createReviewComment(
contentSizeCategory: UIContentSizeCategory,
width: CGFloat
) -> IssueCommentModel {
+ let checkedMarkdown = CheckIfSentWithGitHawk(markdown: model.body)
+
let details = IssueCommentDetailsViewModel(
date: model.created,
login: model.author,
avatarURL: model.authorAvatarURL,
didAuthor: model.author == viewer,
editedBy: nil,
- editedAt: nil
+ editedAt: nil,
+ sentWithGitHawk: checkedMarkdown.sentWithGitHawk
)
let reactions = IssueCommentReactionViewModel(models: [])
let bodies = MarkdownModels(
- model.body,
+ checkedMarkdown.markdown,
owner: owner,
repo: repo,
width: width,
diff --git a/Classes/Systems/Signature.swift b/Classes/Systems/Signature.swift
index d96798ac3..d219432f1 100644
--- a/Classes/Systems/Signature.swift
+++ b/Classes/Systems/Signature.swift
@@ -22,11 +22,15 @@ enum Signature {
}
}
- static func signed(text: String) -> String {
- guard enabled else { return text }
+ static var signature: String {
let format = NSLocalizedString("Sent with %@", comment: "")
let signature = String(format: format, "GitHawk")
- return text + "\n\n\(signature)"
+ return "\n\n\(signature)"
+ }
+
+ static func signed(text: String) -> String {
+ guard enabled else { return text }
+ return text + signature
}
}
diff --git a/Classes/Views/ShowMoreDetailsLabel.swift b/Classes/Views/ShowMoreDetailsLabel.swift
index b594e96c4..bab4999c8 100644
--- a/Classes/Views/ShowMoreDetailsLabel.swift
+++ b/Classes/Views/ShowMoreDetailsLabel.swift
@@ -34,7 +34,7 @@ final class ShowMoreDetailsLabel: UILabel {
// MARK: Private API
- @objc func showMenu(recognizer: UITapGestureRecognizer) {
+ @objc func showMenu(recognizer: UILongPressGestureRecognizer) {
guard recognizer.state == .began,
!detailText.isEmpty else { return }
diff --git a/Freetime.xcodeproj/project.pbxproj b/Freetime.xcodeproj/project.pbxproj
index f18abe4ce..52360a9fc 100644
--- a/Freetime.xcodeproj/project.pbxproj
+++ b/Freetime.xcodeproj/project.pbxproj
@@ -206,6 +206,8 @@
2965F3702071508C003CC92F /* StyledTextBuilder+Checkbox.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2965F36F2071508C003CC92F /* StyledTextBuilder+Checkbox.swift */; };
2965F37220715161003CC92F /* StyledTextBuilder+NewBase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2965F37120715161003CC92F /* StyledTextBuilder+NewBase.swift */; };
29693EE520FAA05F00336200 /* IssueAutocomplete.swift in Sources */ = {isa = PBXBuildFile; fileRef = 29693EE420FAA05F00336200 /* IssueAutocomplete.swift */; };
+ 296A4960210E7B9A00BBBF2B /* IssueDetailBadgeView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 296A495F210E7B9A00BBBF2B /* IssueDetailBadgeView.swift */; };
+ 296A4962210E7E0E00BBBF2B /* CheckIfSentWithGitHawk.swift in Sources */ = {isa = PBXBuildFile; fileRef = 296A4961210E7E0E00BBBF2B /* CheckIfSentWithGitHawk.swift */; };
296B4E311F7C805600C16887 /* GraphQLIDDecode.swift in Sources */ = {isa = PBXBuildFile; fileRef = 296B4E301F7C805600C16887 /* GraphQLIDDecode.swift */; };
296B4E341F7C80B800C16887 /* GraphQLIDDecodeTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 296B4E331F7C80B800C16887 /* GraphQLIDDecodeTests.swift */; };
2971722B1F069E6B005E43AC /* SpinnerSectionController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2971722A1F069E6B005E43AC /* SpinnerSectionController.swift */; };
@@ -715,6 +717,8 @@
2965F36F2071508C003CC92F /* StyledTextBuilder+Checkbox.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "StyledTextBuilder+Checkbox.swift"; sourceTree = ""; };
2965F37120715161003CC92F /* StyledTextBuilder+NewBase.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "StyledTextBuilder+NewBase.swift"; sourceTree = ""; };
29693EE420FAA05F00336200 /* IssueAutocomplete.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IssueAutocomplete.swift; sourceTree = ""; };
+ 296A495F210E7B9A00BBBF2B /* IssueDetailBadgeView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = IssueDetailBadgeView.swift; sourceTree = ""; };
+ 296A4961210E7E0E00BBBF2B /* CheckIfSentWithGitHawk.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CheckIfSentWithGitHawk.swift; sourceTree = ""; };
296B4E301F7C805600C16887 /* GraphQLIDDecode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GraphQLIDDecode.swift; sourceTree = ""; };
296B4E331F7C80B800C16887 /* GraphQLIDDecodeTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GraphQLIDDecodeTests.swift; sourceTree = ""; };
2971722A1F069E6B005E43AC /* SpinnerSectionController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SpinnerSectionController.swift; sourceTree = ""; };
@@ -1239,6 +1243,7 @@
292FCACD1EDFCC510026635E /* Details */ = {
isa = PBXGroup;
children = (
+ 296A495F210E7B9A00BBBF2B /* IssueDetailBadgeView.swift */,
292FCACE1EDFCC510026635E /* IssueCommentDetailCell.swift */,
292FCACF1EDFCC510026635E /* IssueCommentDetailsViewModel.swift */,
);
@@ -1464,6 +1469,7 @@
2965F37120715161003CC92F /* StyledTextBuilder+NewBase.swift */,
29921BCB1EF624D400C1E848 /* UIFont+MutableTraits.swift */,
2977788720B0DAD500F2AFC2 /* ViewMarkdownViewController.swift */,
+ 296A4961210E7E0E00BBBF2B /* CheckIfSentWithGitHawk.swift */,
);
path = Markdown;
sourceTree = "";
@@ -2919,6 +2925,7 @@
29136BDB200A626D007317BE /* FixedRefreshControl.swift in Sources */,
2980033E1F51E93500BE90F4 /* RatingSectionController.swift in Sources */,
29FF85A51EE1EA7A007B8762 /* ReactionContent+ReactionType.swift in Sources */,
+ 296A4960210E7B9A00BBBF2B /* IssueDetailBadgeView.swift in Sources */,
292FCB1D1EDFCD3D0026635E /* ReactionViewModel.swift in Sources */,
29DAA7AF20202BEA0029277A /* PullRequestReviewReplyModel.swift in Sources */,
29B94E691FCB36A000715D7E /* File+ListDiffable.swift in Sources */,
@@ -3003,6 +3010,7 @@
DCA5ED121FAEE3AE0072F074 /* Store.swift in Sources */,
29973E561F68BFDE0004B693 /* Signature.swift in Sources */,
2971722D1F069E96005E43AC /* SpinnerCell.swift in Sources */,
+ 296A4962210E7E0E00BBBF2B /* CheckIfSentWithGitHawk.swift in Sources */,
29B94E6F1FCB743900715D7E /* RepositoryFileCell.swift in Sources */,
29459A711FE7153500034A04 /* LogEnvironmentInformation.swift in Sources */,
49AF91B4204B4B6A00DFF325 /* MergeHelper.swift in Sources */,
diff --git a/Resources/Assets.xcassets/githawk-badge.imageset/Contents.json b/Resources/Assets.xcassets/githawk-badge.imageset/Contents.json
new file mode 100644
index 000000000..07370ac7a
--- /dev/null
+++ b/Resources/Assets.xcassets/githawk-badge.imageset/Contents.json
@@ -0,0 +1,22 @@
+{
+ "images" : [
+ {
+ "idiom" : "universal",
+ "scale" : "1x"
+ },
+ {
+ "idiom" : "universal",
+ "filename" : "githawk-badge@2x.png",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "universal",
+ "filename" : "githawk-badge@3x.png",
+ "scale" : "3x"
+ }
+ ],
+ "info" : {
+ "version" : 1,
+ "author" : "xcode"
+ }
+}
\ No newline at end of file
diff --git a/Resources/Assets.xcassets/githawk-badge.imageset/githawk-badge@2x.png b/Resources/Assets.xcassets/githawk-badge.imageset/githawk-badge@2x.png
new file mode 100644
index 000000000..788c429dd
Binary files /dev/null and b/Resources/Assets.xcassets/githawk-badge.imageset/githawk-badge@2x.png differ
diff --git a/Resources/Assets.xcassets/githawk-badge.imageset/githawk-badge@3x.png b/Resources/Assets.xcassets/githawk-badge.imageset/githawk-badge@3x.png
new file mode 100644
index 000000000..28e0f6b50
Binary files /dev/null and b/Resources/Assets.xcassets/githawk-badge.imageset/githawk-badge@3x.png differ