mirror of
https://github.com/zhigang1992/GitHawk.git
synced 2026-05-24 08:54:10 +08:00
tapping links in md opens safari
This commit is contained in:
@@ -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)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 {
|
||||
|
||||
54
Classes/Views/AttributedStringView.swift
Normal file
54
Classes/Views/AttributedStringView.swift
Normal 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)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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 */,
|
||||
|
||||
Reference in New Issue
Block a user