diff --git a/Package.resolved b/Package.resolved new file mode 100644 index 0000000..472103e --- /dev/null +++ b/Package.resolved @@ -0,0 +1,33 @@ +{ + "originHash" : "cf25ad6b94f02765d03b56d831794bbda3a3babd339e9cf04bd230e98b5dad2e", + "pins" : [ + { + "identity" : "down", + "kind" : "remoteSourceControl", + "location" : "https://github.com/johnxnguyen/Down.git", + "state" : { + "branch" : "master", + "revision" : "e754ab1c80920dd51a8e08290c912ac1c2ac8b58" + } + }, + { + "identity" : "highlightswift", + "kind" : "remoteSourceControl", + "location" : "https://github.com/appstefan/highlightswift.git", + "state" : { + "revision" : "1ee708afe9473828f36d0202722c9cc065d74110", + "version" : "1.0.7" + } + }, + { + "identity" : "swift-collections", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-collections.git", + "state" : { + "revision" : "d029d9d39c87bed85b1c50adee7c41795261a192", + "version" : "1.0.6" + } + } + ], + "version" : 3 +} diff --git a/Sources/SelectableMarkdownUI/View/AttributedTextView.swift b/Sources/SelectableMarkdownUI/View/AttributedTextView.swift index 39bc6ef..dd49d25 100644 --- a/Sources/SelectableMarkdownUI/View/AttributedTextView.swift +++ b/Sources/SelectableMarkdownUI/View/AttributedTextView.swift @@ -19,14 +19,20 @@ struct AttributedTextView: UIViewControllerRepresentable { let text: NSAttributedString private let textView = ContentTextView() - + + init(text: NSAttributedString, editMenuActions: [ EditMenuAction ]? = nil, didChangeHeight: @escaping (CGFloat) -> Void) { + self.text = text + textView.editMenuActions = editMenuActions ?? [] + self.didChangeHeight = didChangeHeight + } + func makeUIViewController(context: Context) -> UIViewControllerType { let vc = UIViewController() textView.contentInset = .zero textView.isSelectable = true textView.isEditable = false - + textView.backgroundColor = .clear textView.isScrollEnabled = false textView.attributedText = text @@ -56,11 +62,38 @@ struct AttributedTextView: UIViewControllerRepresentable { /// ContentTextView /// subclass of UITextView returning contentSize as intrinsicContentSize private class ContentTextView: UITextView { - // override var canBecomeFirstResponder: Bool { false } + var editMenuActions = [ EditMenuAction ]() override var intrinsicContentSize: CGSize { let x = frame.height > 0 ? contentSize : super.intrinsicContentSize return super.intrinsicContentSize } + + override func editMenu(for textRange: UITextRange, suggestedActions: [UIMenuElement]) -> UIMenu? { + var actions = suggestedActions + + editMenuActions.reversed().forEach { actionTemplate in + let action = UIAction(title: actionTemplate.label) { (action) in + if let range = self.selectedTextRange, + let selectedText = self.text(in: range) { + actionTemplate.action(selectedText) + } + } + + actions.insert(action, at: 0) + } + + return UIMenu(children: actions) + } + } +} + +public struct EditMenuAction { + var label: String + var action: (String) -> Void + + public init(label: String, action: @escaping (String) -> Void) { + self.label = label + self.action = action } } diff --git a/Sources/SelectableMarkdownUI/View/SelectableMarkdownView.swift b/Sources/SelectableMarkdownUI/View/SelectableMarkdownView.swift index d3efdaf..d4f1a50 100644 --- a/Sources/SelectableMarkdownUI/View/SelectableMarkdownView.swift +++ b/Sources/SelectableMarkdownUI/View/SelectableMarkdownView.swift @@ -13,18 +13,23 @@ public struct SelectableMarkdownView: View { @Environment(\.colorScheme) var colorScheme: ColorScheme @State private var formattedText: NSAttributedString @State private var messageHeight: CGFloat = 0 + let text: String + let editMenuActions: [ EditMenuAction ]? + let styler: CodeStyler = CodeStyler.sharedInstance let down: Down - public init(text: String) { + public init(text: String, editMenuActions: [ EditMenuAction ]? = nil) { self.text = text + self.editMenuActions = editMenuActions + self.down = Down(markdownString: text) self.formattedText = (try? down.toAttributedString(styler: styler)) ?? NSAttributedString(string: text) } public var body: some View { - AttributedTextView(text: formattedText) { newHeight in + AttributedTextView(text: formattedText, editMenuActions: editMenuActions) { newHeight in self.messageHeight = newHeight } .frame(height: messageHeight) @@ -46,3 +51,21 @@ public struct SelectableMarkdownView: View { } } } + +#Preview("Simple") { + SelectableMarkdownView(text: "This is just a *simple* example") +} + +#Preview("With Actions") { + SelectableMarkdownView( + text: "This is just a *simple* example", + editMenuActions: [ + EditMenuAction(label: "Print Hightlight") { + print($0) + }, + EditMenuAction(label: "Second one") { + print("Second: `\($0)`") + } + ] + ) +}