Stop the macOS transcript jumping while scrolling

This commit is contained in:
Ian Gulliver
2026-10-17 10:14:06 -07:00
parent 1808ca8be6
commit ad458b3a8b
3 changed files with 38 additions and 16 deletions
+28 -10
View File
@@ -425,16 +425,7 @@ private struct FlowText: NSViewRepresentable {
}
func sizeThatFits(_ proposal: ProposedViewSize, nsView v: FlowTextView, context: Context) -> CGSize? {
let width = proposal.width.flatMap { $0.isFinite ? $0 : nil }
let storage = NSTextStorage(attributedString: text)
let layout = NSLayoutManager()
let container = NSTextContainer(size: CGSize(width: width ?? .greatestFiniteMagnitude, height: .greatestFiniteMagnitude))
container.lineFragmentPadding = 0
layout.addTextContainer(container)
storage.addLayoutManager(layout)
layout.ensureLayout(for: container)
let used = layout.usedRect(for: container)
return CGSize(width: width ?? ceil(used.width), height: ceil(used.height))
context.coordinator.size(text, proposal.width.flatMap { $0.isFinite ? $0 : nil })
}
func makeCoordinator() -> Coordinator {
@@ -443,6 +434,33 @@ private struct FlowText: NSViewRepresentable {
final class Coordinator: NSObject, NSTextViewDelegate {
var openURL: OpenURLAction?
private let storage = NSTextStorage()
private let layout = NSLayoutManager()
private let container = NSTextContainer()
private var measured: (text: NSAttributedString, width: CGFloat?, size: CGSize)?
override init() {
super.init()
container.lineFragmentPadding = 0
layout.addTextContainer(container)
storage.addLayoutManager(layout)
}
func size(_ text: NSAttributedString, _ width: CGFloat?) -> CGSize {
let same = measured.map { $0.text === text || $0.text.isEqual(to: text) } ?? false
if same, let m = measured, m.width == width {
return m.size
}
if !same {
storage.setAttributedString(text)
}
container.size = CGSize(width: width ?? .greatestFiniteMagnitude, height: .greatestFiniteMagnitude)
layout.ensureLayout(for: container)
let used = layout.usedRect(for: container)
let size = CGSize(width: width ?? ceil(used.width), height: ceil(used.height))
measured = (text, width, size)
return size
}
func textView(_ textView: NSTextView, clickedOnLink link: Any, at charIndex: Int) -> Bool {
guard let url = link as? URL, let openURL else {