Re-add rich-text formatting actions in Compose

This commit is contained in:
Shadowfacts 2025-02-26 11:08:56 -05:00
parent 2178621350
commit 67e362d6da
2 changed files with 46 additions and 9 deletions

View File

@ -10,6 +10,7 @@ import Combine
import UIKit
import SwiftUI
@MainActor
protocol ComposeInput: AnyObject, ObservableObject {
var toolbarElements: [ToolbarElement] { get }
var textInputMode: UITextInputMode? { get }

View File

@ -52,6 +52,7 @@ private struct NewMainTextViewRepresentable: UIViewRepresentable {
}
view.addInteraction(UIDropInteraction(delegate: context.coordinator))
view.delegate = context.coordinator
context.coordinator.textView = view
view.adjustsFontForContentSizeCategory = true
view.textContainer.lineBreakMode = .byWordWrapping
view.isScrollEnabled = false
@ -110,9 +111,9 @@ private struct NewMainTextViewRepresentable: UIViewRepresentable {
func makeCoordinator() -> WrappedTextViewCoordinator {
let coordinator = WrappedTextViewCoordinator(value: $value, handleAttachmentDrop: handleAttachmentDrop)
// DispatchQueue.main.async {
// inputBox.wrappedValue = coordinator
// }
DispatchQueue.main.async {
inputBox.wrappedValue = 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")
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 = {
let font = UIFont.systemFont(ofSize: 20)
let size = /*1.4 * */font.capHeight
@ -144,6 +145,9 @@ private final class WrappedTextViewCoordinator: NSObject {
var value: Binding<String>
var handleAttachmentDrop: ([NSItemProvider]) -> Void
weak var textView: UITextView?
@Published var autocompleteState: AutocompleteState?
init(value: Binding<String>, handleAttachmentDrop: @escaping ([NSItemProvider]) -> Void) {
self.value = value
@ -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.
// 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?) {
// TODO
(delegate as! WrappedTextViewCoordinator).applyFormat(.bold)
}
override func toggleItalics(_ sender: Any?) {
// TODO
(delegate as! WrappedTextViewCoordinator).applyFormat(.italics)
}
override func validate(_ command: UICommand) {