perf: improve input responsiveness in compose input (#1413)

* perf: improve input responsiveness in compose input

* remove some unused code from autosize.js

* remove some more unused code
This commit is contained in:
Nolan Lawson 2019-08-19 21:37:11 -07:00 committed by GitHub
parent 4232da5e33
commit cccbfd70da
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 27 additions and 35 deletions

View file

@ -102,6 +102,7 @@
import { postStatus, insertHandleForReply, setReplySpoiler, setReplyVisibility } from '../../_actions/compose'
import { classname } from '../../_utils/classname'
import { POLL_EXPIRY_DEFAULT } from '../../_static/polls'
import { scheduleIdleTask } from '../../_utils/scheduleIdleTask'
export default {
oncreate () {
@ -179,6 +180,13 @@
},
methods: {
doPostStatus () {
// The reason we add a scheduleIdleTask delay here is because we also use scheduleIdleTask
// in ComposeInput.html to debounce the input events. If the user is very fast at typing
// at their keyboard and quickly presses Ctrl+Enter or the "Toot" button then there could
// be a race condition where not all of their status is posted.
scheduleIdleTask(() => this.doPostStatusAfterDelay())
},
doPostStatusAfterDelay () {
const {
text,
media,

View file

@ -59,7 +59,6 @@
import { store } from '../../_store/store'
import { autosize } from '../../_thirdparty/autosize/autosize'
import { scheduleIdleTask } from '../../_utils/scheduleIdleTask'
import debounce from 'lodash-es/debounce'
import { mark, stop } from '../../_utils/marks'
import { selectionChange } from '../../_utils/events'
import {
@ -70,6 +69,9 @@
import { get } from '../../_utils/lodash-lite'
import { on } from '../../_utils/eventBus'
import { requestPostAnimationFrame } from '../../_utils/requestPostAnimationFrame'
import { throttleTimer } from '../../_utils/throttleTimer'
const updateComposeTextInStore = throttleTimer(scheduleIdleTask)
export default {
oncreate () {
@ -106,14 +108,14 @@
})
},
setupSyncToStore () {
const saveStore = debounce(() => scheduleIdleTask(() => this.store.save()), 1000)
const { realm } = this.get()
this.observe('rawText', rawText => {
mark('observe rawText')
const { realm } = this.get()
this.store.setComposeData(realm, { text: rawText })
saveStore()
stop('observe rawText')
updateComposeTextInStore(() => {
mark('updateComposeTextInStore')
this.store.setComposeData(realm, { text: rawText })
this.store.save()
stop('updateComposeTextInStore')
})
}, { init: false })
},
setupAutosize () {

View file

@ -5,11 +5,12 @@
import { mark, stop } from '../../_utils/marks'
import debounce from 'lodash-es/debounce'
import throttle from 'lodash-es/throttle'
import { getScrollContainer } from '../../_utils/scrollContainer'
import { throttleTimer } from '../../_utils/throttleTimer'
const doUpdate = process.browser && throttleTimer(requestAnimationFrame)
const map = new Map()
const createEvent = (name) => new Event(name, { bubbles: true })
function assign (ta) {
if (!ta || !ta.nodeName || ta.nodeName !== 'TEXTAREA' || map.has(ta)) {
@ -19,7 +20,6 @@ function assign (ta) {
// TODO: hack - grab our scroll container so we can maintain the scrollTop
const container = getScrollContainer()
let heightOffset = null
let cachedHeight = null
function init () {
const style = window.getComputedStyle(ta, null)
@ -35,9 +35,8 @@ function assign (ta) {
function resize () {
mark('autosize:resize()')
const res = _resize()
_resize()
stop('autosize:resize()')
return res
}
function _resize () {
@ -51,15 +50,13 @@ function assign (ta) {
if (ta.scrollHeight === 0) {
// If the scrollHeight is 0, then the element probably has display:none or is detached from the DOM.
ta.style.height = originalHeight
return
} else {
ta.style.height = `${endHeight}px`
container.scrollTop = scrollTop // Firefox jiggles if we don't reset the scrollTop of the container
}
ta.style.height = endHeight + 'px'
container.scrollTop = scrollTop // Firefox jiggles if we don't reset the scrollTop of the container
return endHeight
}
const deferredUpdate = throttle(() => requestAnimationFrame(update), 100)
const deferredUpdate = () => doUpdate(update)
function update () {
mark('autosize:update()')
@ -68,17 +65,7 @@ function assign (ta) {
}
function _update () {
const newHeight = resize()
if (cachedHeight !== newHeight) {
cachedHeight = newHeight
const evt = createEvent('autosize:resized')
try {
ta.dispatchEvent(evt)
} catch (err) {
// Firefox will throw an error on dispatchEvent for a detached element
// https://bugzilla.mozilla.org/show_bug.cgi?id=889376
}
}
resize()
}
const pageResize = debounce(() => requestAnimationFrame(update), 1000)
@ -86,17 +73,12 @@ function assign (ta) {
const destroy = () => {
window.removeEventListener('resize', pageResize, false)
ta.removeEventListener('input', deferredUpdate, false)
ta.removeEventListener('autosize:destroy', destroy, false)
ta.removeEventListener('autosize:update', update, false)
map.delete(ta)
}
ta.addEventListener('autosize:destroy', destroy, false)
window.addEventListener('resize', pageResize, false)
ta.addEventListener('input', deferredUpdate, false)
ta.addEventListener('autosize:update', update, false)
map.set(ta, {
destroy,