kyle-n / HighlightedTextEditor

A SwiftUI view for dynamically highlighting user input
MIT License
726 stars 69 forks source link

AppKit Editor Unexpected Handling of Undo #64

Closed dbarsamian closed 9 months ago

dbarsamian commented 2 years ago

Describe the bug When using a SwiftUI document-based App with HighlightedTextEditor, the editor view will handle undo actions one letter at a time instead of undoing words or phrases at a time.

To Reproduce Steps to reproduce the behavior:

  1. Create a SwiftUI document-based app targeting the Mac.
  2. In the ContentView, add only a HighlightedTextEditor and bind the text to $document.text
  3. Run the app, and type some new text into the text editor
  4. Undo typing by either using Command + Z or the menu bar item Edit > Undo

Expected behavior I expected the editor view to undo words or phrases at a time, similar to how the TextEditor view handles undo, or any other standard NSTextView.

Screenshots Please see attached video for demonstration, which compares HighlightedTextEditor's undo behavior with TextEdit's behavior.

https://user-images.githubusercontent.com/46636471/162554231-54ba6a53-aa58-44db-a02c-8fe4fe89c34d.mov

Environment

Additional context I've attached a sample project to demonstrate the issue with minimal setup.

Test.zip

9SL9 commented 2 years ago

Has anybody figured out if this is a bug in HighlightedTextEditor or is it solved by configuration of the Undo system in the app? @kyle-n ?

hstdt commented 2 years ago

Maybe updateUIView/updateNSView will make undo broken, Have a try with no code in this method?

9SL9 commented 2 years ago

I will attempt to look into this and will share my findings, if any.

kyle-n commented 1 year ago

Apologies for the very long turnaround time, but I've begun looking into this issue. Using this sample code, the AppKit editor displays correct undo behavior after #72.

import SwiftUI

@main
struct testerino_macApp: App {
    var body: some Scene {
        WindowGroup {
            ContentView()
        }
    }
}

//...

import SwiftUI
import HighlightedTextEditor

struct ContentView: View {
    @State private var text = "one"

    var body: some View {
        VStack {
            HighlightedTextEditor(text: $text, highlightRules: .markdown)
        }
    }
}

However, your test project and the latest version of HLTE still displays incorrect undo behavior (one letter at a time).

If I change your example project to use a SwiftUI @State var as the text binding instead of a FileDocument's text, the undo behavior works correctly. It may be that TextEditor has some extra magic to handle undos with FileDocument, and HLTE needs something similar.