import SwiftUI import UIKit import VorleserKit struct ReadingTextView: UIViewRepresentable { let text: String let highlightedRange: Range? let onTapCharacter: (CharacterOffset) -> Void func makeUIView(context: Context) -> UITextView { let textView = UITextView() textView.isEditable = false textView.isSelectable = false textView.font = .preferredFont(forTextStyle: .body) textView.textContainerInset = UIEdgeInsets(top: 16, left: 16, bottom: 16, right: 16) let tap = UITapGestureRecognizer(target: context.coordinator, action: #selector(Coordinator.handleTap(_:))) textView.addGestureRecognizer(tap) return textView } func updateUIView(_ textView: UITextView, context: Context) { let attributed = NSMutableAttributedString( string: text, attributes: [ .font: UIFont.preferredFont(forTextStyle: .body), .foregroundColor: UIColor.label, ] ) if let range = highlightedRange, range.lowerBound >= 0, range.upperBound <= text.count { let nsRange = NSRange(location: range.lowerBound, length: range.upperBound - range.lowerBound) attributed.addAttribute(.backgroundColor, value: UIColor.systemYellow.withAlphaComponent(0.3), range: nsRange) } textView.attributedText = attributed } func makeCoordinator() -> Coordinator { Coordinator(onTapCharacter: onTapCharacter) } class Coordinator: NSObject { let onTapCharacter: (CharacterOffset) -> Void init(onTapCharacter: @escaping (CharacterOffset) -> Void) { self.onTapCharacter = onTapCharacter } @objc func handleTap(_ gesture: UITapGestureRecognizer) { guard let textView = gesture.view as? UITextView else { return } let point = gesture.location(in: textView) let characterIndex = textView.offset( from: textView.beginningOfDocument, to: textView.closestPosition(to: point) ?? textView.beginningOfDocument ) if characterIndex < textView.text.count { onTapCharacter(characterIndex) } } } }