Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bring signature of RichTextEditor more inline with normal TextFields #95

Open
ChrisTitos opened this issue Aug 15, 2023 · 5 comments
Open
Assignees
Labels
enhancement New feature or request

Comments

@ChrisTitos
Copy link

Hi,

We are looking into your library to integrate in our app, and use it in our forms. The library looks great and seems to support all our needs.

However there is one thing now that we are struggling with a bit.

Our use case is that the editor is in a form with other textfields, and the content of the form input fields is controlled somewhere else (a ViewModel)
This works great for normal Compose inputs, like the TextField where we have a value and onValueChange.

In the current setup of the library we need to use rememberRichTextState and then manually call setHTML in a LaunchedEffect, which already feels strange. And I don't see a way to continuously update the state in the view model, since I do not see an equivalent of onValueChange. I only see the method toHTML which needs to be called manually on the state object.

I see you had something like this before in the pre-v1.0 versions but you deprecated this.

Our ideal structure would be to be able to do something like this:

OurCustomizedRichTextEditor(value, onValueChange) {
  RichTextToolbar(richTextState) //to show the buttons
  val richTextState = rememberRichTextState(value, onValueChange) //somehow set HTML as input, and get it as output
  RichTextEditor( richTextState) 
}

Where the input and output would HTML (or other options depending on what the someone wants, our use case is HTML). This way it can be more or less a drop-in replacement for normal Compose TextFields

What do you suggest? Is something like this already possible?

I think this is similar to #66

@MohamedRejeb
Copy link
Owner

Hi,
You are right, I'm thinking of adding some public APIs to register a listener. There's something similar but it's internal, for now there's a possible workaround.

LaunchedEffect(state.annotatedString) {
    // This is going to be called after any change of the text
    val html = state.toHtml()
}

Give it a try and let me know if it works and I'll work on providing a better approach ASAP

@MohamedRejeb MohamedRejeb self-assigned this Aug 15, 2023
@MohamedRejeb MohamedRejeb added the enhancement New feature or request label Aug 15, 2023
@ChrisTitos
Copy link
Author

Thanks for the quick reply. We'll give the workaround a try.

@ChrisTitos
Copy link
Author

Hi,

Is this still a thing you plan to add?

We currently have the following structure with the work around mentioned above:

OurCustomizedRichTextEditor(value, onValueChange) {

  val richTextState = rememberRichTextState() 

 LaunchedEffect(value) {
      richTextState.setHtml(value ?: "")
  }

  LaunchedEffect(state.annotatedString) {
     val html = richTextState.toHtml()
     onValueChange(html) //propagate new value back up
  }
  RichTextEditor( richTextState) 
}

However this results in very buggy behavior. Things I noticed:

  • The textfield now grows indefinitely. I think because of Replace Empty Line with line break when converting to HTML #191 where an empty string is turned into a line break, which triggers onValueChange, which rerenders our component, which calls setHTML again, etc. I have add a check to only call onValueChanged if the value is not empty to prevent this behavior.
  • Lists don't work anymore, going to the next line loses the context so the next line is no longer a list element. (I assume there is something in setHtml that resets things

The above things don't happen when I don't call onValueChange.

@ChrisTitos
Copy link
Author

FYI I fixed my issues in the comment above by not always calling setHTML, only doing it when the incoming value differs from the one in the state.

OurCustomizedRichTextEditor(value, onValueChange) {

  val richTextState = rememberRichTextState() 

 LaunchedEffect(value) {
      //preventing buggy behavior in the rich text editor,
      //basically we try not to touch the richTextState
      if (richTextState.toHtml() != value) {
            richTextState.setHtml(value ?: "")
        }
  }

  LaunchedEffect(state.annotatedString) {
     val html = richTextState.toHtml()
     onValueChange(html) //propagate new value back up
  }
  RichTextEditor( richTextState) 
}

@MohamedRejeb
Copy link
Owner

Hello,
Hopefully this will be added soon. I'm still thinking of the type of data that will be passed with the onValueChange, either AnnotatedString or a tree representation of the rich text.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants