tapping links in md opens safari

This commit is contained in:
Ryan Nystrom
2017-06-23 14:32:38 -04:00
parent 3228ffa718
commit 74ff765bb4
8 changed files with 93 additions and 37 deletions

View File

@@ -18,7 +18,8 @@ final class IssueCommentSectionController: ListBindingSectionController<IssueCom
IssueCommentReactionCellDelegate,
IssueCommentImageCellDelegate,
NYTPhotosViewControllerDelegate,
IssueCommentHtmlCellDelegate {
IssueCommentHtmlCellDelegate,
AttributedStringViewDelegate {
private var collapsed = true
private let client: GithubClient
@@ -63,6 +64,11 @@ IssueCommentHtmlCellDelegate {
}
}
private func open(url: URL) {
let safari = SFSafariViewController(url: url)
viewController?.present(safari, animated: true)
}
// MARK: ListBindingSectionControllerDataSource
func sectionController(
@@ -139,7 +145,7 @@ IssueCommentHtmlCellDelegate {
if let cell = cell as? CollapsibleCell {
cell.setCollapse(visible: collapsed && (viewModel as AnyObject) === object?.collapse?.model)
}
if let cell = cell as? IssueCommentDetailCell {
cell.delegate = self
} else if let cell = cell as? IssueCommentReactionCell {
@@ -148,6 +154,10 @@ IssueCommentHtmlCellDelegate {
cell.delegate = self
} else if let cell = cell as? IssueCommentHtmlCell {
cell.delegate = self
} else if let cell = cell as? IssueCommentTextCell {
cell.textView.delegate = self
} else if let cell = cell as? IssueCommentQuoteCell {
cell.textView.delegate = self
}
return cell
@@ -211,8 +221,13 @@ IssueCommentHtmlCellDelegate {
}
func webViewWantsNavigate(cell: IssueCommentHtmlCell, url: URL) {
let safari = SFSafariViewController(url: url)
viewController?.present(safari, animated: true)
open(url: url)
}
// MARK: AttributedStringViewDelegate
func didTapURL(view: AttributedStringView, url: URL) {
open(url: url)
}
}

View File

@@ -9,6 +9,8 @@
import UIKit
import MMMarkdown
let MarkdownURLName = "MarkdownURLName"
extension MMElement {
func attributes(
@@ -43,7 +45,7 @@ extension MMElement {
]
case .link: newAttributes = [
NSForegroundColorAttributeName: Styles.Colors.Blue.medium.color,
"FIXME": href ?? "",
MarkdownURLName: href ?? "",
]
case .header:
switch level {

View File

@@ -21,7 +21,7 @@ final class IssueCommentQuoteCell: UICollectionViewCell, ListBindable, Collapsib
)
}
private let textView = UIView()
let textView = AttributedStringView()
private var borders = [UIView]()
private let overlay = CreateCollapsibleOverlay()
@@ -68,7 +68,7 @@ final class IssueCommentQuoteCell: UICollectionViewCell, ListBindable, Collapsib
borders.append(border)
}
textView.configureAndLayout(viewModel.quote)
textView.configureAndSizeToFit(text: viewModel.quote)
setNeedsLayout()
}

View File

@@ -13,7 +13,7 @@ final class IssueCommentTextCell: UICollectionViewCell, ListBindable, Collapsibl
static let inset = Styles.Sizes.textCellInset
let textView = UIView()
let textView = AttributedStringView()
let overlay = CreateCollapsibleOverlay()
override init(frame: CGRect) {
@@ -38,7 +38,7 @@ final class IssueCommentTextCell: UICollectionViewCell, ListBindable, Collapsibl
func bindViewModel(_ viewModel: Any) {
guard let viewModel = viewModel as? NSAttributedStringSizing else { return }
textView.configureAndLayout(viewModel)
textView.configureAndSizeToFit(text: viewModel)
}
// MARK: CollapsibleCell

View File

@@ -109,6 +109,15 @@ final class NSAttributedStringSizing: NSObject, ListDiffable {
return contents
}
func attributes(point: CGPoint) -> [String: Any]? {
var fractionDistance: CGFloat = 1.0
let index = layoutManager.characterIndex(for: point, in: textContainer, fractionOfDistanceBetweenInsertionPoints: &fractionDistance)
if index != NSNotFound, fractionDistance < 1.0 {
return attributedText.attributes(at: index, effectiveRange: nil)
}
return nil
}
// MARK: ListDiffable
func diffIdentifier() -> NSObjectProtocol {

View File

@@ -0,0 +1,54 @@
//
// AttributedStringView.swift
// Freetime
//
// Created by Ryan Nystrom on 6/23/17.
// Copyright © 2017 Ryan Nystrom. All rights reserved.
//
import UIKit
protocol AttributedStringViewDelegate: class {
func didTapURL(view: AttributedStringView, url: URL)
}
final class AttributedStringView: UIView {
var delegate: AttributedStringViewDelegate? = nil
private var text: NSAttributedStringSizing? = nil
override init(frame: CGRect) {
super.init(frame: frame)
backgroundColor = .white
isOpaque = true
layer.contentsGravity = kCAGravityTopLeft
let tap = UITapGestureRecognizer(target: self, action: #selector(AttributedStringView.onTap(recognizer:)))
addGestureRecognizer(tap)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
// MARK: Public API
func configureAndSizeToFit(text: NSAttributedStringSizing) {
self.text = text
layer.contentsScale = text.screenScale
layer.contents = text.contents()
frame = UIEdgeInsetsInsetRect(CGRect(origin: .zero, size: text.textViewSize), text.inset)
}
// MARK: Private API
func onTap(recognizer: UITapGestureRecognizer) {
guard let urlString = text?.attributes(point: recognizer.location(in: self))?[MarkdownURLName] as? String,
let url = URL(string: urlString)
else { return }
delegate?.didTapURL(view: self, url: url)
}
}

View File

@@ -1,22 +0,0 @@
//
// UIView+NSAttributedStringSizing.swift
// Freetime
//
// Created by Ryan Nystrom on 6/9/17.
// Copyright © 2017 Ryan Nystrom. All rights reserved.
//
import UIKit
extension UIView {
func configureAndLayout(_ text: NSAttributedStringSizing) {
backgroundColor = .white
isOpaque = true
layer.contentsGravity = kCAGravityTopLeft
layer.contentsScale = text.screenScale
layer.contents = text.contents()
frame = UIEdgeInsetsInsetRect(CGRect(origin: .zero, size: text.textViewSize), text.inset)
}
}

View File

@@ -202,6 +202,7 @@
29921BCC1EF624D400C1E848 /* UIFont+MutableTraits.swift in Sources */ = {isa = PBXBuildFile; fileRef = 29921BCB1EF624D400C1E848 /* UIFont+MutableTraits.swift */; };
29921BCE1EF624F500C1E848 /* MMElement+Image.swift in Sources */ = {isa = PBXBuildFile; fileRef = 29921BCD1EF624F500C1E848 /* MMElement+Image.swift */; };
29921BD01EF6261C00C1E848 /* MMElement+CodeBlock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 29921BCF1EF6261C00C1E848 /* MMElement+CodeBlock.swift */; };
299E86431EFD8D8200E5FE70 /* AttributedStringView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 299E86421EFD8D8200E5FE70 /* AttributedStringView.swift */; };
299F2A121EC3BCF0006CE9D7 /* GithubSessionManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 299F2A111EC3BCF0006CE9D7 /* GithubSessionManager.swift */; };
29A195021EC66B8B00C3E289 /* UIColor+Hex.swift in Sources */ = {isa = PBXBuildFile; fileRef = 29A195011EC66B8B00C3E289 /* UIColor+Hex.swift */; };
29A195041EC74C4800C3E289 /* Date+Display.swift in Sources */ = {isa = PBXBuildFile; fileRef = 29A195031EC74C4800C3E289 /* Date+Display.swift */; };
@@ -244,8 +245,6 @@
29C295111EC7B83200D46CD2 /* ShowMoreDetailsLabel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 29C2950F1EC7B7FF00D46CD2 /* ShowMoreDetailsLabel.swift */; };
29C295141EC7BAFE00D46CD2 /* NotificationsRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 29C295121EC7B9D500D46CD2 /* NotificationsRequest.swift */; };
29C295171EC7BCDA00D46CD2 /* NotificationsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 29C295151EC7BCCD00D46CD2 /* NotificationsViewController.swift */; };
29C76D4C1EEB46B40048B23F /* UIView+NSAttributedStringSizing.swift in Sources */ = {isa = PBXBuildFile; fileRef = 29C76D4B1EEB46B40048B23F /* UIView+NSAttributedStringSizing.swift */; };
29C76D4D1EEB46B40048B23F /* UIView+NSAttributedStringSizing.swift in Sources */ = {isa = PBXBuildFile; fileRef = 29C76D4B1EEB46B40048B23F /* UIView+NSAttributedStringSizing.swift */; };
29C9FDCE1EC65FEE00EE3A52 /* Notification.swift in Sources */ = {isa = PBXBuildFile; fileRef = 29C9FDBA1EC65FEE00EE3A52 /* Notification.swift */; };
29C9FDCF1EC65FEE00EE3A52 /* Organization.swift in Sources */ = {isa = PBXBuildFile; fileRef = 29C9FDBB1EC65FEE00EE3A52 /* Organization.swift */; };
29C9FDD01EC65FEE00EE3A52 /* Permission.swift in Sources */ = {isa = PBXBuildFile; fileRef = 29C9FDBC1EC65FEE00EE3A52 /* Permission.swift */; };
@@ -394,6 +393,7 @@
29921BCB1EF624D400C1E848 /* UIFont+MutableTraits.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIFont+MutableTraits.swift"; sourceTree = "<group>"; };
29921BCD1EF624F500C1E848 /* MMElement+Image.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "MMElement+Image.swift"; sourceTree = "<group>"; };
29921BCF1EF6261C00C1E848 /* MMElement+CodeBlock.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "MMElement+CodeBlock.swift"; sourceTree = "<group>"; };
299E86421EFD8D8200E5FE70 /* AttributedStringView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AttributedStringView.swift; sourceTree = "<group>"; };
299F2A111EC3BCF0006CE9D7 /* GithubSessionManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GithubSessionManager.swift; sourceTree = "<group>"; };
29A195011EC66B8B00C3E289 /* UIColor+Hex.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIColor+Hex.swift"; sourceTree = "<group>"; };
29A195031EC74C4800C3E289 /* Date+Display.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Date+Display.swift"; sourceTree = "<group>"; };
@@ -418,7 +418,6 @@
29C2950F1EC7B7FF00D46CD2 /* ShowMoreDetailsLabel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ShowMoreDetailsLabel.swift; sourceTree = "<group>"; };
29C295121EC7B9D500D46CD2 /* NotificationsRequest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NotificationsRequest.swift; sourceTree = "<group>"; };
29C295151EC7BCCD00D46CD2 /* NotificationsViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NotificationsViewController.swift; sourceTree = "<group>"; };
29C76D4B1EEB46B40048B23F /* UIView+NSAttributedStringSizing.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIView+NSAttributedStringSizing.swift"; sourceTree = "<group>"; };
29C9FDBA1EC65FEE00EE3A52 /* Notification.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Notification.swift; sourceTree = "<group>"; };
29C9FDBB1EC65FEE00EE3A52 /* Organization.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Organization.swift; sourceTree = "<group>"; };
29C9FDBC1EC65FEE00EE3A52 /* Permission.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Permission.swift; sourceTree = "<group>"; };
@@ -820,7 +819,7 @@
29A195011EC66B8B00C3E289 /* UIColor+Hex.swift */,
29A4769F1ED0E6C6005D0953 /* UIColor+Overlay.swift */,
298BA08E1EC90FEE00B01946 /* UIView+BottomBorder.swift */,
29C76D4B1EEB46B40048B23F /* UIView+NSAttributedStringSizing.swift */,
299E86421EFD8D8200E5FE70 /* AttributedStringView.swift */,
);
path = Views;
sourceTree = "<group>";
@@ -1156,7 +1155,6 @@
29921BCA1EF6233200C1E848 /* MMElement+Attributes.swift in Sources */,
292FCB001EDFCC510026635E /* IssueCommentViewModelHeight.swift in Sources */,
29921BCC1EF624D400C1E848 /* UIFont+MutableTraits.swift in Sources */,
29C76D4C1EEB46B40048B23F /* UIView+NSAttributedStringSizing.swift in Sources */,
292FCB181EDFCC510026635E /* IssueTitleCell.swift in Sources */,
292FCB071EDFCC510026635E /* IssueCommentReactionCell.swift in Sources */,
29316DCD1ECD31E9007CAE3F /* StatusBar.swift in Sources */,
@@ -1164,6 +1162,7 @@
293B58531EF808DA001D067D /* IssueCommentUnsupportedModel.swift in Sources */,
294563EA1EE4EEF000DBCD35 /* IssueStatusCell.swift in Sources */,
2949674C1EF9716400B1CF1A /* IssueCommentHrModel.swift in Sources */,
299E86431EFD8D8200E5FE70 /* AttributedStringView.swift in Sources */,
2963A9391EE258C20066509C /* GithubClient+Issues.swift in Sources */,
299F2A121EC3BCF0006CE9D7 /* GithubSessionManager.swift in Sources */,
29A195021EC66B8B00C3E289 /* UIColor+Hex.swift in Sources */,
@@ -1272,7 +1271,6 @@
2958407E1EEA00E1007723C6 /* IssueCommentModel.swift in Sources */,
295840D21EEA00E1007723C6 /* UIButton+Label.swift in Sources */,
2958409B1EEA00E1007723C6 /* IssueLabelDotCell.swift in Sources */,
29C76D4D1EEB46B40048B23F /* UIView+NSAttributedStringSizing.swift in Sources */,
2958408F1EEA00E1007723C6 /* IssueCommentTextCell.swift in Sources */,
295840BC1EEA00E1007723C6 /* SettingsAddAccountSectionController.swift in Sources */,
2958407A1EEA00E1007723C6 /* IssueCommentImageCell.swift in Sources */,