Newer
Older
import {
DefaultDOMElement,
FontAwesomeIcon as Icon,
Tool
} from 'substance'
class CommentBubble extends Tool {
render ($$) {
if (!this.canCreateComment()) return $$('div')
const title = 'Create a new comment'
const iconPlus = $$(Icon, { icon: 'fa-plus' })
.addClass('sc-comment-icon-plus')
const iconBubble = $$(Icon, { icon: 'fa-comment-o' })
.addClass('sc-comment-icon-bubble')
const bubble = $$('div')
.attr('title', title)
.addClass('sc-overlay-bubble')
.addClass('sc-overlay-bubble-hidden')
.on('click', this.createComment)
// reset bubble position on window resize
// only works on the horizontal level, as the vertical position gets
// calculated relative to the overlay container, which gets positioned
// wrong on resize (substance bug -- TODO)
didMount () {
this.context.editorSession.onUpdate('', this.position, this)
DefaultDOMElement.getBrowserWindow().on('resize', this.didUpdate, this)
}
dispose () {
DefaultDOMElement.getBrowserWindow().off(this)
}
position () {
if (this.el.getChildCount() === 0) return
this.setBubblePosition()
}
setBubblePosition () {
// without this check, the editor will break on first load
const surface = this.getSurface()
if (!surface) return
setTimeout(() => { // read comment below
let documentElement = document.querySelector('.se-content')
let overlayContainer = document.querySelector('.sc-overlay')
let fix = 15
if (parseInt(overlayContainer.offsetLeft) === 0) {
const minEditorContentPanelChildren = document.getElementById('notes-editor-content-panel').children
const temp = minEditorContentPanelChildren[0].children
documentElement = temp[0]
const children = temp[0].children
overlayContainer = children[1]
}
const documentElementWidth = documentElement.offsetWidth / 1.85
const overlayContainerLeft = overlayContainer.offsetLeft
const left = documentElementWidth - overlayContainerLeft - fix
// unhide it first, as the bubble has no height otherwise
this.el.removeClass('sc-overlay-bubble-hidden')
let wsel = window.getSelection()
let wrange = wsel.getRangeAt(0)
const hints = wrange.getBoundingClientRect()
const selectionHeight = hints.height
const bubbleHeight = this.el.getHeight()
const cheat = 3
const moveUp = (selectionHeight / 2) + (bubbleHeight / 2) + cheat
const top = '-' + moveUp + 'px'
})
/*
There is a race condition with overlayContainer's position.
If it gets rendered fast enough, this is fine.
Otherwise, the overlayContainerLeft variable won't have been updated by
substance for us to get the correct value.
There is no event letting us know that this has been updated,
and it's probably not worth creating a listener.
*/
}
getCommentState () {
const { commandManager } = this.context
const commandStates = commandManager.getCommandStates()
return commandStates.comment
getEditorSession () {
return this.context.editorSession
}
getMode () {
const commentState = this.getCommentState()
return commentState.mode
}
getProvider () {
return this.context.commentsProvider
const editorSession = this.getEditorSession()
return editorSession.getSelection()
getSurface () {
const surfaceManager = this.context.surfaceManager
return surfaceManager.getFocusedSurface()
}
isSelectionLargerThanComments () {
const provider = this.getProvider()
return provider.isSelectionLargerThanComments()
}
canCreateComment () {
const mode = this.getMode()
if (mode === 'create') return true
if (!this.isSelectionLargerThanComments()) return false
return true
}
if (!this.canCreateComment()) return
const provider = this.getProvider()
const selection = this.getSelection()
const surface = this.getSurface()
const newNode = {
selection: selection,
type: 'comment',
path: selection.path,
start: selection.start,
end: selection.end
surface.editorSession.transaction((tx, args) => {
const annotation = tx.create(newNode)
provider.focusTextArea(annotation.id)