Re-add rich-text formatting actions in Compose
This commit is contained in:
parent
2178621350
commit
67e362d6da
@ -10,6 +10,7 @@ import Combine
|
|||||||
import UIKit
|
import UIKit
|
||||||
import SwiftUI
|
import SwiftUI
|
||||||
|
|
||||||
|
@MainActor
|
||||||
protocol ComposeInput: AnyObject, ObservableObject {
|
protocol ComposeInput: AnyObject, ObservableObject {
|
||||||
var toolbarElements: [ToolbarElement] { get }
|
var toolbarElements: [ToolbarElement] { get }
|
||||||
var textInputMode: UITextInputMode? { get }
|
var textInputMode: UITextInputMode? { get }
|
||||||
|
@ -52,6 +52,7 @@ private struct NewMainTextViewRepresentable: UIViewRepresentable {
|
|||||||
}
|
}
|
||||||
view.addInteraction(UIDropInteraction(delegate: context.coordinator))
|
view.addInteraction(UIDropInteraction(delegate: context.coordinator))
|
||||||
view.delegate = context.coordinator
|
view.delegate = context.coordinator
|
||||||
|
context.coordinator.textView = view
|
||||||
view.adjustsFontForContentSizeCategory = true
|
view.adjustsFontForContentSizeCategory = true
|
||||||
view.textContainer.lineBreakMode = .byWordWrapping
|
view.textContainer.lineBreakMode = .byWordWrapping
|
||||||
view.isScrollEnabled = false
|
view.isScrollEnabled = false
|
||||||
@ -110,9 +111,9 @@ private struct NewMainTextViewRepresentable: UIViewRepresentable {
|
|||||||
|
|
||||||
func makeCoordinator() -> WrappedTextViewCoordinator {
|
func makeCoordinator() -> WrappedTextViewCoordinator {
|
||||||
let coordinator = WrappedTextViewCoordinator(value: $value, handleAttachmentDrop: handleAttachmentDrop)
|
let coordinator = WrappedTextViewCoordinator(value: $value, handleAttachmentDrop: handleAttachmentDrop)
|
||||||
// DispatchQueue.main.async {
|
DispatchQueue.main.async {
|
||||||
// inputBox.wrappedValue = coordinator
|
inputBox.wrappedValue = coordinator
|
||||||
// }
|
}
|
||||||
return coordinator
|
return coordinator
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -127,7 +128,7 @@ private struct NewMainTextViewRepresentable: UIViewRepresentable {
|
|||||||
// laxer than the CharacterCounter regex, because we want to find mentions that are being typed but aren't yet complete (e.g., "@a@b")
|
// laxer than the CharacterCounter regex, because we want to find mentions that are being typed but aren't yet complete (e.g., "@a@b")
|
||||||
private let mentionRegex = try! NSRegularExpression(pattern: "(@[a-z0-9_]+)(?:@[a-z0-9\\-\\.]+)?", options: .caseInsensitive)
|
private let mentionRegex = try! NSRegularExpression(pattern: "(@[a-z0-9_]+)(?:@[a-z0-9\\-\\.]+)?", options: .caseInsensitive)
|
||||||
|
|
||||||
private final class WrappedTextViewCoordinator: NSObject {
|
private final class WrappedTextViewCoordinator: NSObject, ObservableObject {
|
||||||
private static let attachment: NSTextAttachment = {
|
private static let attachment: NSTextAttachment = {
|
||||||
let font = UIFont.systemFont(ofSize: 20)
|
let font = UIFont.systemFont(ofSize: 20)
|
||||||
let size = /*1.4 * */font.capHeight
|
let size = /*1.4 * */font.capHeight
|
||||||
@ -144,7 +145,10 @@ private final class WrappedTextViewCoordinator: NSObject {
|
|||||||
|
|
||||||
var value: Binding<String>
|
var value: Binding<String>
|
||||||
var handleAttachmentDrop: ([NSItemProvider]) -> Void
|
var handleAttachmentDrop: ([NSItemProvider]) -> Void
|
||||||
|
weak var textView: UITextView?
|
||||||
|
|
||||||
|
@Published var autocompleteState: AutocompleteState?
|
||||||
|
|
||||||
init(value: Binding<String>, handleAttachmentDrop: @escaping ([NSItemProvider]) -> Void) {
|
init(value: Binding<String>, handleAttachmentDrop: @escaping ([NSItemProvider]) -> Void) {
|
||||||
self.value = value
|
self.value = value
|
||||||
self.handleAttachmentDrop = handleAttachmentDrop
|
self.handleAttachmentDrop = handleAttachmentDrop
|
||||||
@ -293,9 +297,41 @@ extension WrappedTextViewCoordinator: UITextViewDelegate {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//extension WrappedTextViewCoordinator: ComposeInput {
|
extension WrappedTextViewCoordinator: ComposeInput {
|
||||||
//
|
var autocompleteStatePublisher: Published<AutocompleteState?>.Publisher { $autocompleteState }
|
||||||
//}
|
|
||||||
|
var toolbarElements: [ToolbarElement] {
|
||||||
|
[.emojiPicker, .formattingButtons]
|
||||||
|
}
|
||||||
|
|
||||||
|
var textInputMode: UITextInputMode? {
|
||||||
|
textView?.textInputMode
|
||||||
|
}
|
||||||
|
|
||||||
|
func applyFormat(_ format: StatusFormat) {
|
||||||
|
guard let textView,
|
||||||
|
textView.isFirstResponder,
|
||||||
|
let insertionResult = format.insertionResult(for: Preferences.shared.statusContentType) else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
let currentSelectedRange = textView.selectedRange
|
||||||
|
let utf16 = textView.text.utf16
|
||||||
|
let start = utf16.index(utf16.startIndex, offsetBy: currentSelectedRange.location)
|
||||||
|
let end = utf16.index(start, offsetBy: currentSelectedRange.length)
|
||||||
|
let selectedText = utf16[start..<end]
|
||||||
|
textView.insertText(insertionResult.prefix + String(Substring(selectedText)) + insertionResult.suffix)
|
||||||
|
textView.selectedRange = NSRange(location: currentSelectedRange.location + insertionResult.insertionPoint, length: currentSelectedRange.length)
|
||||||
|
}
|
||||||
|
|
||||||
|
func beginAutocompletingEmoji() {
|
||||||
|
textView?.insertText(":")
|
||||||
|
}
|
||||||
|
|
||||||
|
func autocomplete(with string: String) {
|
||||||
|
textView?.autocomplete(with: string, permittedModes: .all, autocompleteState: &autocompleteState)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Because of FB11790805, we can't handle drops for the entire screen.
|
// Because of FB11790805, we can't handle drops for the entire screen.
|
||||||
// The onDrop modifier also doesn't work when applied to the NewMainTextView.
|
// The onDrop modifier also doesn't work when applied to the NewMainTextView.
|
||||||
@ -327,11 +363,11 @@ private final class WrappedTextView: UITextView {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override func toggleBoldface(_ sender: Any?) {
|
override func toggleBoldface(_ sender: Any?) {
|
||||||
// TODO
|
(delegate as! WrappedTextViewCoordinator).applyFormat(.bold)
|
||||||
}
|
}
|
||||||
|
|
||||||
override func toggleItalics(_ sender: Any?) {
|
override func toggleItalics(_ sender: Any?) {
|
||||||
// TODO
|
(delegate as! WrappedTextViewCoordinator).applyFormat(.italics)
|
||||||
}
|
}
|
||||||
|
|
||||||
override func validate(_ command: UICommand) {
|
override func validate(_ command: UICommand) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user