danielsaidi / RichTextKit

RichTextKit is a Swift SDK that helps you use rich text in Swift and SwiftUI.
MIT License
949 stars 126 forks source link

allows for monitoring textViewSouldChangeTextInRange #167

Open GabeRoze opened 7 months ago

GabeRoze commented 7 months ago

SwifTUI RichTextEditor now includes ability to monitor text changes from shouldChangeTextInRange delegate.

S1D1T1 commented 7 months ago

what is an appropriate use for this? I currently react to changes in RichTextEditor using .onChanged(attributedString.string) for things like syntax highlighting and matching parenthesis. I thought it might be inefficient, but there has been no noticeable lag. My code re-parses the contents on every keystroke.

GabeRoze commented 7 months ago
  1. We can get key press events as well as bigger changes
  2. We can substitute a key press for another action. For example when pressing return when the cursor is on a line that contains a bulleted list, we can replace the new line with a new bullet and a new line. This is how I am using it.

.onChanged(attributedString.string) only return the new string. We would have to computer the difference every time. While doable and will likely not incur a performance hit on smaller texts (and even likely larger ones), iOS already provides a native way to interact with a textViews new addition - shouldChangeTextInRange

In SwiftUI on iOS 17 we can also use .onKeyPress, ex:

RichTextEditor(...)
     .onKeyPress { press in
     if press.key == .return {
         if store.state.currentLineHasCheck(context: context) {
             store.send(.insertNewCheckAfterEnterTappepd(context))
                 return .handled
             }
         }
     }

While this worked on simulator, I had trouble getting it to function on a real iOS 17 device. I decided that a native solution that has worked solidly for years would be the quickest approach, thus this PR.

S1D1T1 commented 7 months ago

I'd love to use .onKeyPress. As discussed here, under MacOS, that is never called in my app

martindufort commented 7 months ago

@GabeRoze Interesting use case as I want to do the same thing but with a list of todos... So basically if the current line is a todo (starts with []) then I want the next line (after pressing return) to be a todo as well. But in my case, I also need the [] characters to be replaced with a nice NSImageAttachment of a beautiful open checkbox.

Any guidelines for that?

danielsaidi commented 7 months ago

@S1D1T1 @GabeRoze @martindufort Not currently, unfortunately. I'm also swamped with work atm, and am not really sure when I will have time to return to this project for more complex features.

danielsaidi commented 1 month ago

@GabeRoze After reviewing this, I think using SwiftUI to monitor is the way to go, rather than to inject these kinds of things.