From e8239a92ab98b459be9fb3b6f3fe9fe2a529b4f6 Mon Sep 17 00:00:00 2001 From: Ben Gotow Date: Tue, 5 Jan 2016 14:31:55 -0800 Subject: [PATCH] fix(sig): Remove selectEnd, place cursor before sig Summary: When focusing the composer, select the end of the last text block above any signatures / quoted text (which can be visible by default in Fwd:). Test Plan: Run tests Reviewers: juan, evan Reviewed By: evan Differential Revision: https://phab.nylas.com/D2411 --- .../lib/signature-composer-extension.coffee | 6 ++- .../signature-composer-extension-spec.coffee | 4 +- .../composer/lib/composer-editor.jsx | 38 ++++++++++++++++++- .../contenteditable/contenteditable.cjsx | 2 - .../contenteditable/editor-api.coffee | 1 - .../contenteditable/extended-selection.coffee | 9 ----- 6 files changed, 44 insertions(+), 16 deletions(-) diff --git a/internal_packages/composer-signature/lib/signature-composer-extension.coffee b/internal_packages/composer-signature/lib/signature-composer-extension.coffee index 83b800d03..85bb09814 100644 --- a/internal_packages/composer-signature/lib/signature-composer-extension.coffee +++ b/internal_packages/composer-signature/lib/signature-composer-extension.coffee @@ -7,8 +7,12 @@ class SignatureComposerExtension extends ComposerExtension return unless signature insertionPoint = draft.body.indexOf('' + if insertionPoint is -1 insertionPoint = draft.body.length - draft.body = draft.body.slice(0, insertionPoint) + '
' + signature + "
" + draft.body.slice(insertionPoint) + signatureHTML = '

' + signatureHTML + + draft.body = draft.body.slice(0, insertionPoint) + signatureHTML + draft.body.slice(insertionPoint) module.exports = SignatureComposerExtension diff --git a/internal_packages/composer-signature/spec/signature-composer-extension-spec.coffee b/internal_packages/composer-signature/spec/signature-composer-extension-spec.coffee index 84ad6d2f1..3a3cd900e 100644 --- a/internal_packages/composer-signature/spec/signature-composer-extension-spec.coffee +++ b/internal_packages/composer-signature/spec/signature-composer-extension-spec.coffee @@ -19,9 +19,9 @@ describe "SignatureComposerExtension", -> body: 'This is a another test.' SignatureComposerExtension.prepareNewDraft(draft: a) - expect(a.body).toEqual('This is a test!
This is my signature.
Hello world
') + expect(a.body).toEqual('This is a test!
This is my signature.
Hello world
') SignatureComposerExtension.prepareNewDraft(draft: b) - expect(b.body).toEqual('This is a another test.
This is my signature.
') + expect(b.body).toEqual('This is a another test.

This is my signature.
') describe "when a signature is not defined", -> beforeEach -> diff --git a/internal_packages/composer/lib/composer-editor.jsx b/internal_packages/composer/lib/composer-editor.jsx index a3059cced..67c1e386f 100644 --- a/internal_packages/composer/lib/composer-editor.jsx +++ b/internal_packages/composer/lib/composer-editor.jsx @@ -121,7 +121,43 @@ class ComposerEditor extends Component { } focus() { - this.refs.contenteditable.selectEnd(); + // focus the composer and place the insertion point at the last text node of + // the body. Be sure to choose the last node /above/ the signature and any + // quoted text that is visible. (as in forwarded messages.) + // + this.refs.contenteditable.atomicEdit( ({editor})=> { + const walker = document.createTreeWalker(editor.rootNode, NodeFilter.SHOW_TEXT); + const nodesBelowUserBody = editor.rootNode.querySelectorAll('.nylas-n1-signature, .gmail_quote, blockquote'); + + let lastNode = null; + let node = walker.nextNode(); + + while (node != null) { + let belowUserBody = false; + for (let i = 0; i < nodesBelowUserBody.length; ++i) { + if (nodesBelowUserBody[i].contains(node)) { + belowUserBody = true; + break; + } + } + if (belowUserBody) { + break; + } + lastNode = node; + node = walker.nextNode(); + } + + editor.rootNode.focus(); + + if (lastNode) { + const range = document.createRange(); + range.selectNodeContents(lastNode); + range.collapse(false); + const selection = window.getSelection(); + selection.removeAllRanges(); + selection.addRange(range); + } + }); } /** diff --git a/src/components/contenteditable/contenteditable.cjsx b/src/components/contenteditable/contenteditable.cjsx index cd6900de3..401e03ce4 100644 --- a/src/components/contenteditable/contenteditable.cjsx +++ b/src/components/contenteditable/contenteditable.cjsx @@ -96,8 +96,6 @@ class Contenteditable extends React.Component focus: => @_editableNode().focus() - selectEnd: => @atomicEdit ({editor}) -> editor.selectEnd() - ######################################################################## ########################### React Lifecycle ############################ diff --git a/src/components/contenteditable/editor-api.coffee b/src/components/contenteditable/editor-api.coffee index b06fe3857..c0fc91745 100644 --- a/src/components/contenteditable/editor-api.coffee +++ b/src/components/contenteditable/editor-api.coffee @@ -48,7 +48,6 @@ class EditorAPI collapseToEnd: (args...) -> @_extendedSelection.collapseToEnd(args...); @ importSelection: (args...) -> @_extendedSelection.importSelection(args...); @ select: (args...) -> @_extendedSelection.select(args...); @ - selectEnd: (args...) -> @_extendedSelection.selectEnd(args...); @ selectAllChildren: (args...) -> @_extendedSelection.selectAllChildren(args...); @ restoreSelectionByTextIndex: (args...) -> @_extendedSelection.restoreSelectionByTextIndex(args...); @ diff --git a/src/components/contenteditable/extended-selection.coffee b/src/components/contenteditable/extended-selection.coffee index 624d6a20f..9dc5dedf3 100644 --- a/src/components/contenteditable/extended-selection.coffee +++ b/src/components/contenteditable/extended-selection.coffee @@ -55,15 +55,6 @@ class ExtendedSelection throw @_errBadUsage() @setBaseAndExtent(fromNode, fromIndex, toNode, toIndex) - selectEnd: -> - range = document.createRange() - range.selectNodeContents(@scopeNode) - range.collapse(false) - @scopeNode.focus() - selection = window.getSelection() - selection.removeAllRanges() - selection.addRange(range) - exportSelection: -> new ExportedSelection(@rawSelection, @scopeNode) # Since the last time we exported the selection, the DOM may have