mirror of
https://github.com/Foundry376/Mailspring.git
synced 2025-02-22 23:23:54 +08:00
feat(composer): improve tab useage in composer
A `*` as well as a `-` will start a list. If you tab anywhere in plain text, it will insert a tab character. If your shift-tab anywhere in plain text, and the character just before the cursor is a "tab" character, it will delete that last tab character. Fix a bug whereby shift-tab and tab will indent/outdent from anywhere inside of a list. Fixes T3409
This commit is contained in:
parent
cb72438270
commit
16c4376812
1 changed files with 39 additions and 6 deletions
|
@ -161,17 +161,15 @@ class ContenteditableComponent extends React.Component
|
||||||
# re-enable at the end.
|
# re-enable at the end.
|
||||||
updateDOM = (command) =>
|
updateDOM = (command) =>
|
||||||
@_teardownSelectionListeners()
|
@_teardownSelectionListeners()
|
||||||
@_ignoreInputChanges = true
|
|
||||||
document.execCommand(command)
|
document.execCommand(command)
|
||||||
selection = document.getSelection()
|
selection = document.getSelection()
|
||||||
selection.anchorNode.parentElement.innerHTML = ""
|
selection.anchorNode.parentElement.innerHTML = ""
|
||||||
@_ignoreInputChanges = false
|
|
||||||
@_setupSelectionListeners()
|
@_setupSelectionListeners()
|
||||||
|
|
||||||
text = @_textContentAtCursor()
|
text = @_textContentAtCursor()
|
||||||
if (/^\d\.\s$/).test text
|
if (/^\d\.\s$/).test text
|
||||||
updateDOM("insertOrderedList")
|
updateDOM("insertOrderedList")
|
||||||
else if (/^-\s$/).test text
|
else if (/^[*-]\s$/).test text
|
||||||
updateDOM("insertUnorderedList")
|
updateDOM("insertUnorderedList")
|
||||||
|
|
||||||
_onTabDown: (event) ->
|
_onTabDown: (event) ->
|
||||||
|
@ -179,14 +177,47 @@ class ContenteditableComponent extends React.Component
|
||||||
selection = document.getSelection()
|
selection = document.getSelection()
|
||||||
if selection?.isCollapsed
|
if selection?.isCollapsed
|
||||||
# https://developer.mozilla.org/en-US/docs/Web/API/Element/closest
|
# https://developer.mozilla.org/en-US/docs/Web/API/Element/closest
|
||||||
# Some nodes anchorNodes might not have a `closest` method.
|
if selection.anchorNode instanceof HTMLElement
|
||||||
if selection.anchorNode?.closest?("li")
|
anchorElement = selection.anchorNode
|
||||||
|
else
|
||||||
|
anchorElement = selection.anchorNode.parentElement
|
||||||
|
|
||||||
|
# Only Elements (not Text nodes) have the `closest` method
|
||||||
|
if anchorElement.closest("li")
|
||||||
if event.shiftKey
|
if event.shiftKey
|
||||||
document.execCommand("outdent")
|
document.execCommand("outdent")
|
||||||
else
|
else
|
||||||
document.execCommand("indent")
|
document.execCommand("indent")
|
||||||
return
|
return
|
||||||
document.execCommand("insertText", false, "\t")
|
else if event.shiftKey
|
||||||
|
if @_atTabChar() then @_removeLastCharacter()
|
||||||
|
else
|
||||||
|
document.execCommand("insertText", false, "\t")
|
||||||
|
else
|
||||||
|
if event.shiftKey
|
||||||
|
document.execCommand("insertText", false, "")
|
||||||
|
else
|
||||||
|
document.execCommand("insertText", false, "\t")
|
||||||
|
|
||||||
|
_selectionInText: (selection) ->
|
||||||
|
return false unless selection
|
||||||
|
return selection.isCollapsed and selection.anchorNode.nodeType is Node.TEXT_NODE and selection.anchorOffset > 0
|
||||||
|
|
||||||
|
_atTabChar: ->
|
||||||
|
selection = document.getSelection()
|
||||||
|
if @_selectionInText(selection)
|
||||||
|
return selection.anchorNode.textContent[selection.anchorOffset - 1] is "\t"
|
||||||
|
else return false
|
||||||
|
|
||||||
|
_removeLastCharacter: ->
|
||||||
|
selection = document.getSelection()
|
||||||
|
if @_selectionInText(selection)
|
||||||
|
node = selection.anchorNode
|
||||||
|
offset = selection.anchorOffset
|
||||||
|
@_teardownSelectionListeners()
|
||||||
|
selection.setBaseAndExtent(node, offset - 1, node, offset)
|
||||||
|
document.execCommand("delete")
|
||||||
|
@_setupSelectionListeners()
|
||||||
|
|
||||||
_textContentAtCursor: ->
|
_textContentAtCursor: ->
|
||||||
selection = document.getSelection()
|
selection = document.getSelection()
|
||||||
|
@ -362,10 +393,12 @@ class ContenteditableComponent extends React.Component
|
||||||
|
|
||||||
# http://www.w3.org/TR/selection-api/#selectstart-event
|
# http://www.w3.org/TR/selection-api/#selectstart-event
|
||||||
_setupSelectionListeners: =>
|
_setupSelectionListeners: =>
|
||||||
|
@_ignoreInputChanges = false
|
||||||
document.addEventListener("selectionchange", @_saveSelectionState)
|
document.addEventListener("selectionchange", @_saveSelectionState)
|
||||||
|
|
||||||
_teardownSelectionListeners: =>
|
_teardownSelectionListeners: =>
|
||||||
document.removeEventListener("selectionchange", @_saveSelectionState)
|
document.removeEventListener("selectionchange", @_saveSelectionState)
|
||||||
|
@_ignoreInputChanges = true
|
||||||
|
|
||||||
getCurrentSelection: => _.clone(@_selection ? {})
|
getCurrentSelection: => _.clone(@_selection ? {})
|
||||||
getPreviousSelection: => _.clone(@_previousSelection ? {})
|
getPreviousSelection: => _.clone(@_previousSelection ? {})
|
||||||
|
|
Loading…
Reference in a new issue