mirror of
https://github.com/Foundry376/Mailspring.git
synced 2025-01-10 10:11:25 +08:00
fix(composer): undo/redo now properly restores selection on new msg
This commit is contained in:
parent
de02e17fdb
commit
99f6749488
1 changed files with 34 additions and 17 deletions
|
@ -122,7 +122,7 @@ class Contenteditable extends React.Component
|
||||||
|
|
||||||
componentWillReceiveProps: (nextProps) =>
|
componentWillReceiveProps: (nextProps) =>
|
||||||
if nextProps.initialSelectionSnapshot?
|
if nextProps.initialSelectionSnapshot?
|
||||||
@_saveSelectionState(nextProps.initialSelectionSnapshot)
|
@_saveExportedSelection(nextProps.initialSelectionSnapshot)
|
||||||
|
|
||||||
componentDidUpdate: =>
|
componentDidUpdate: =>
|
||||||
@_restoreSelection()
|
@_restoreSelection()
|
||||||
|
@ -253,7 +253,9 @@ class Contenteditable extends React.Component
|
||||||
|
|
||||||
@_runCallbackOnExtensions("onContentChanged", {mutations})
|
@_runCallbackOnExtensions("onContentChanged", {mutations})
|
||||||
|
|
||||||
@_saveSelectionState()
|
selection = new ExtendedSelection(@_editableNode())
|
||||||
|
if selection?.isInScope()
|
||||||
|
@_saveExportedSelection(selection.exportSelection())
|
||||||
|
|
||||||
@props.onChange(target: {value: @_editableNode().innerHTML})
|
@props.onChange(target: {value: @_editableNode().innerHTML})
|
||||||
|
|
||||||
|
@ -396,7 +398,22 @@ class Contenteditable extends React.Component
|
||||||
getCurrentSelection: => @innerState.exportedSelection ? {}
|
getCurrentSelection: => @innerState.exportedSelection ? {}
|
||||||
getPreviousSelection: => @innerState.previousExportedSelection ? {}
|
getPreviousSelection: => @innerState.previousExportedSelection ? {}
|
||||||
|
|
||||||
# Every time the cursor changes we need to save its location and state.
|
# We save an {ExportedSelection} to `innerState`.
|
||||||
|
#
|
||||||
|
# Whatever we set `innerState.exportedSelection` to will be implemented
|
||||||
|
# on the next `componentDidUpdate` by `_restoreSelection`
|
||||||
|
#
|
||||||
|
# We also allow props to manually set our `exportedSelection` state.
|
||||||
|
# This is useful in undo/redo situations when we want to revert the
|
||||||
|
# selection to where it was at a previous time.
|
||||||
|
#
|
||||||
|
# NOTE: The `exportedSelection` object may have `anchorNode` and
|
||||||
|
# `focusNode` references to similar, but not equal, DOMNodes than what
|
||||||
|
# we currently have rendered. Every time React re-renders the component
|
||||||
|
# we get new DOM objects. When the `exportedSelection` is re-imported
|
||||||
|
# during `_restoreSelection`, the `ExtendedSelection` class will attempt
|
||||||
|
# to find the appropriate DOM Nodes via the `DOMUtils.findSimilarNodes`
|
||||||
|
# method.
|
||||||
#
|
#
|
||||||
# When React re-renders it doesn't restore the Selection. We need to do
|
# When React re-renders it doesn't restore the Selection. We need to do
|
||||||
# this manually with `_restoreSelection`
|
# this manually with `_restoreSelection`
|
||||||
|
@ -407,29 +424,29 @@ class Contenteditable extends React.Component
|
||||||
#
|
#
|
||||||
# We also need to keep references to the previous selection state in
|
# We also need to keep references to the previous selection state in
|
||||||
# order for undo/redo to work properly.
|
# order for undo/redo to work properly.
|
||||||
_saveSelectionState: (exportedStateToSave=null) =>
|
_saveExportedSelection: (exportedSelection) =>
|
||||||
extendedSelection = new ExtendedSelection(@_editableNode())
|
return if (@innerState.exportedSelection?.isEqual(exportedSelection))
|
||||||
if exportedStateToSave
|
|
||||||
extendedSelection.importSelection(exportedStateToSave)
|
|
||||||
return unless extendedSelection?.isInScope()
|
|
||||||
return if (@innerState.exportedSelection?.isEqual(extendedSelection))
|
|
||||||
|
|
||||||
@setInnerState
|
@setInnerState
|
||||||
exportedSelection: extendedSelection.exportSelection()
|
exportedSelection: exportedSelection
|
||||||
editableFocused: true
|
editableFocused: true
|
||||||
previousExportedSelection: @innerState.exportedSelection
|
previousExportedSelection: @innerState.exportedSelection
|
||||||
|
|
||||||
@_onSelectionChanged(extendedSelection)
|
# Every time the cursor changes we need to save its location and state.
|
||||||
|
# We update our cache every time the selection changes by listening to
|
||||||
_onSelectionChange: (event) => @_saveSelectionState()
|
# the `document` `selectionchange` event.
|
||||||
|
_onSelectionChange: (event) =>
|
||||||
|
selection = new ExtendedSelection(@_editableNode())
|
||||||
|
return unless selection?.isInScope()
|
||||||
|
@_saveExportedSelection(selection.exportSelection())
|
||||||
|
|
||||||
_restoreSelection: =>
|
_restoreSelection: =>
|
||||||
return unless @_shouldRestoreSelection()
|
return unless @_shouldRestoreSelection()
|
||||||
@_teardownListeners()
|
@_teardownListeners()
|
||||||
extendedSelection = new ExtendedSelection(@_editableNode())
|
selection = new ExtendedSelection(@_editableNode())
|
||||||
extendedSelection.importSelection(@innerState.exportedSelection)
|
selection.importSelection(@innerState.exportedSelection)
|
||||||
if extendedSelection.isInScope()
|
if selection.isInScope()
|
||||||
@_onSelectionChanged(extendedSelection)
|
@_onSelectionChanged(selection)
|
||||||
@_setupListeners()
|
@_setupListeners()
|
||||||
|
|
||||||
_shouldRestoreSelection: ->
|
_shouldRestoreSelection: ->
|
||||||
|
|
Loading…
Reference in a new issue