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

RichText Trigger onChange on input #4955

Merged
merged 6 commits into from
Feb 12, 2018
Merged

Conversation

youknowriad
Copy link
Contributor

This will be necessary to achieve #4951

It also fixes some issues while the save draft link doesn't show up until we focus out of the component.
It may introduce a difference in a way undo/redo works but I believe we should handle those consistently (it's not the case right now, RichText triggers and undo state per word while PlainText it's per character). I'm thinking we could use the withHistory a Reducer enhancer to group similar changes into one undo level.

Testing instructions

  • Test several writing flow interactions

@youknowriad youknowriad added the [Feature] Rich Text Related to the Rich Text component that allows developers to render a contenteditable label Feb 8, 2018
@youknowriad youknowriad self-assigned this Feb 8, 2018
@youknowriad youknowriad requested review from mtias and ellatrix February 8, 2018 14:35
@aduth
Copy link
Member

aduth commented Feb 8, 2018

See: #2758

(Particularly bits about undo history)

@youknowriad youknowriad force-pushed the try/editable-input-onchange branch from 18e97c2 to 571d61d Compare February 8, 2018 14:40
@ellatrix
Copy link
Member

ellatrix commented Feb 8, 2018

I'm currently rebasing a WIP branch that does the undo signalling with a buffer in the history. I'm also leaving out selection now since it would make it more complex. I feel like we should fix undo together this PR.


// Saving the editor on updates avoid unecessary onChanges calls
// These calls can make the focus jump
this.editor.save();
}

setContent( content ) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I forgot to add content = '' here 🙈

@youknowriad youknowriad force-pushed the try/editable-input-onchange branch 2 times, most recently from e6af488 to 87ca673 Compare February 9, 2018 10:23
@youknowriad
Copy link
Contributor Author

youknowriad commented Feb 9, 2018

So from my testing, performance is good enough here but I'd appreciate that other people try it to confirm

Edit: Erratum: On long post it's not good at all, needs further investigation

@@ -92,6 +93,7 @@ export default class RichText extends Component {
this.getSettings = this.getSettings.bind( this );
this.onSetup = this.onSetup.bind( this );
this.onChange = this.onChange.bind( this );
this.throttledOnChange = throttle( this.onChange.bind( this ), 500 );
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we can, I'd love if we would avoid throttling. Case in point: We're not cancelling a scheduled change when the component unmounts.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, if the performance fix is enough, I'm fine dropping it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried dropping it but I think performance-wise it's slightly better if we keep it

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems like it always dispatched change when I type the first character. Should we wait until 500ms passes instead?

Copy link
Member

@ellatrix ellatrix Feb 12, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@youknowriad What can we do to get rid of this? :)

@aduth
Copy link
Member

aduth commented Feb 9, 2018

@youknowriad I created a branch off of this one which includes an iteration on rememo to improve per-key selector caching.

https://github.com/WordPress/gutenberg/tree/try/weak-map-cache

See: aduth/rememo#1

@youknowriad
Copy link
Contributor Author

@aduth Awesome, I'm not seeing any performance issues any more 👍


On the performance side, maybe instead of using getBlock selector, we could target block properties directly getBlockName, getBlockAttributes, isValidBlock etc... These granular properties are less likely to change compared to the block object which will avoid unnecessary renders in connect calls.

@youknowriad youknowriad force-pushed the try/editable-input-onchange branch from 15fa35c to efff741 Compare February 12, 2018 11:00
@youknowriad
Copy link
Contributor Author

Rebase this with the changes from #5002 it seems better now.

@gziolo
Copy link
Member

gziolo commented Feb 12, 2018

@youknowriad, see https://github.com/WordPress/gutenberg/pull/5002/files#r167532619, can we bring the polyfill as part of this PR?


content = renderToString( content );
this.editor.setContent( content );
setContent( content = '' ) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice refactoring :)

if ( this.editor.isDirty() ) {
this.fireChange();
}
this.savedContent = this.state.empty ? [] : this.getContent();
Copy link
Member

@gziolo gziolo Feb 12, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@aduth - should we extract [] to its own shared variable to ensure we have always one variable reference to compare with ===? I wanted to double check - you know better all those perf bits. It might not make any sense in this context :)

this.props.value !== this.savedContent &&
! isEqual( this.props.value, prevProps.value ) &&
! isEqual( this.props.value, this.savedContent )
this.props.value !== this.savedContent
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems like shallow compare is enough here.

@gziolo
Copy link
Member

gziolo commented Feb 12, 2018

I played with cmd + Z and noticed a bit strange behavior, the following screencast contains more details shared as I type:
on-change

@gziolo
Copy link
Member

gziolo commented Feb 12, 2018

I also recorded another screencast where you can observe how strangely undo behaves:

on-change

I'm doing cmd + Z until undo history gets emptied. What's is very unexpected here is that past items don't get removed until the text is completely removed with undo actions...

@gziolo
Copy link
Member

gziolo commented Feb 12, 2018

I'm still able to type something and close the tab without seeing the prompt to save your changes for my draft:

no-changes-detected

@youknowriad
Copy link
Contributor Author

@gziolo

  • I can't seem to reproduce these undo issues though granted that it's not perfect, it's not perfect in master and as I said let's explore those separately in Proposal: history "buffer"/overwrite, sync RichText history records #4956 and Try a generic undo handler #4959

  • About the last screenshot, this is due to the throttle timeout. I think it's fine for now, I don't expect people to close their tab less than 0.5 seconds after editing the post unless they don't want to save these changes :). I'm also hopeful we could get rid of the throttle entirely at some point when we improve rerendering performance event more.

@aduth
Copy link
Member

aduth commented Feb 12, 2018

I'd be inclined to omitting the throttle from the start to force our hand in addressing the performance issues. 😅

I'll try to take a pass at these today (non-blocking).

Copy link
Member

@gziolo gziolo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tested in enough. Let's merge it and continue in the follow-up PRs as discussed 👍

@youknowriad youknowriad merged commit b4d3132 into master Feb 12, 2018
) {
this.updateContent();
}
}

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed line break by accident?

@@ -508,8 +506,6 @@ export class RichText extends Component {
return;
}

this.fireChange();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this removed?

@youknowriad
Copy link
Contributor Author

I don't know, this was part of one of your commits, I can restore :)

@ellatrix
Copy link
Member

@youknowriad I think I removed that there assuming changes would be in sync all the time, but with the throttle that wouldn't be the case?

@aduth
Copy link
Member

aduth commented Feb 12, 2018

Noting that in the course of writing a post with a single paragraph containing only 32 words, I accumulated 71 copies of editor state via undo history (and that this will only grow over the course of writing a post in the same session).

@aduth
Copy link
Member

aduth commented Feb 12, 2018

Something revealed by this change: Should we be debouncing autosave instead of throttling? It feels as though it saves much more frequently now, since it can occur many times while typing within the same paragraph block.

Debouncing isn't great either, since just because I don't stop typing for X amount of time doesn't mean the post should never save during that time.

Or maybe the autosave should just be made less frequent than every 10 seconds?

@@ -149,6 +151,7 @@ export class RichText extends Component {
editor.on( 'BeforeExecCommand', this.maybePropagateUndo );
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did we test to see how TinyMCE's undo history interacts with our own?

  • Are we calling onChange with the correct value after TinyMCE finishes undo?
  • Should we be bypassing TinyMCE's undo altogether (also preventing it from accumulating any history)?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@aduth I'm proposing these changes in #4956. Good point about preventing TinyMCE accumulating any history at all. We just need the signals, not the store.

@ellatrix
Copy link
Member

@aduth I don't mind if we save frequently, but it is quite visually distracting ATM. Sounds like it need to be more subtle, similar to Google Docs. We also have to make sure we don't just pile these changes up as revisions, instead we should maybe reuse the last revision and only create a new revision on a user action or at least way less often (each revision is a post in the DB).

@aduth aduth deleted the try/editable-input-onchange branch February 13, 2018 13:11
@aduth
Copy link
Member

aduth commented Feb 13, 2018

We also have to make sure we don't just pile these changes up as revisions

Yeah, this is an ongoing issue unfortunately: #3656

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
[Feature] Rich Text Related to the Rich Text component that allows developers to render a contenteditable
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants