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:
parent
4232da5e33
commit
cccbfd70da
|
@ -102,6 +102,7 @@
|
||||||
import { postStatus, insertHandleForReply, setReplySpoiler, setReplyVisibility } from '../../_actions/compose'
|
import { postStatus, insertHandleForReply, setReplySpoiler, setReplyVisibility } from '../../_actions/compose'
|
||||||
import { classname } from '../../_utils/classname'
|
import { classname } from '../../_utils/classname'
|
||||||
import { POLL_EXPIRY_DEFAULT } from '../../_static/polls'
|
import { POLL_EXPIRY_DEFAULT } from '../../_static/polls'
|
||||||
|
import { scheduleIdleTask } from '../../_utils/scheduleIdleTask'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
oncreate () {
|
oncreate () {
|
||||||
|
@ -179,6 +180,13 @@
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
doPostStatus () {
|
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 {
|
const {
|
||||||
text,
|
text,
|
||||||
media,
|
media,
|
||||||
|
|
|
@ -59,7 +59,6 @@
|
||||||
import { store } from '../../_store/store'
|
import { store } from '../../_store/store'
|
||||||
import { autosize } from '../../_thirdparty/autosize/autosize'
|
import { autosize } from '../../_thirdparty/autosize/autosize'
|
||||||
import { scheduleIdleTask } from '../../_utils/scheduleIdleTask'
|
import { scheduleIdleTask } from '../../_utils/scheduleIdleTask'
|
||||||
import debounce from 'lodash-es/debounce'
|
|
||||||
import { mark, stop } from '../../_utils/marks'
|
import { mark, stop } from '../../_utils/marks'
|
||||||
import { selectionChange } from '../../_utils/events'
|
import { selectionChange } from '../../_utils/events'
|
||||||
import {
|
import {
|
||||||
|
@ -70,6 +69,9 @@
|
||||||
import { get } from '../../_utils/lodash-lite'
|
import { get } from '../../_utils/lodash-lite'
|
||||||
import { on } from '../../_utils/eventBus'
|
import { on } from '../../_utils/eventBus'
|
||||||
import { requestPostAnimationFrame } from '../../_utils/requestPostAnimationFrame'
|
import { requestPostAnimationFrame } from '../../_utils/requestPostAnimationFrame'
|
||||||
|
import { throttleTimer } from '../../_utils/throttleTimer'
|
||||||
|
|
||||||
|
const updateComposeTextInStore = throttleTimer(scheduleIdleTask)
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
oncreate () {
|
oncreate () {
|
||||||
|
@ -106,14 +108,14 @@
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
setupSyncToStore () {
|
setupSyncToStore () {
|
||||||
const saveStore = debounce(() => scheduleIdleTask(() => this.store.save()), 1000)
|
const { realm } = this.get()
|
||||||
|
|
||||||
this.observe('rawText', rawText => {
|
this.observe('rawText', rawText => {
|
||||||
mark('observe rawText')
|
updateComposeTextInStore(() => {
|
||||||
const { realm } = this.get()
|
mark('updateComposeTextInStore')
|
||||||
this.store.setComposeData(realm, { text: rawText })
|
this.store.setComposeData(realm, { text: rawText })
|
||||||
saveStore()
|
this.store.save()
|
||||||
stop('observe rawText')
|
stop('updateComposeTextInStore')
|
||||||
|
})
|
||||||
}, { init: false })
|
}, { init: false })
|
||||||
},
|
},
|
||||||
setupAutosize () {
|
setupAutosize () {
|
||||||
|
|
36
src/routes/_thirdparty/autosize/autosize.js
vendored
36
src/routes/_thirdparty/autosize/autosize.js
vendored
|
@ -5,11 +5,12 @@
|
||||||
|
|
||||||
import { mark, stop } from '../../_utils/marks'
|
import { mark, stop } from '../../_utils/marks'
|
||||||
import debounce from 'lodash-es/debounce'
|
import debounce from 'lodash-es/debounce'
|
||||||
import throttle from 'lodash-es/throttle'
|
|
||||||
import { getScrollContainer } from '../../_utils/scrollContainer'
|
import { getScrollContainer } from '../../_utils/scrollContainer'
|
||||||
|
import { throttleTimer } from '../../_utils/throttleTimer'
|
||||||
|
|
||||||
|
const doUpdate = process.browser && throttleTimer(requestAnimationFrame)
|
||||||
|
|
||||||
const map = new Map()
|
const map = new Map()
|
||||||
const createEvent = (name) => new Event(name, { bubbles: true })
|
|
||||||
|
|
||||||
function assign (ta) {
|
function assign (ta) {
|
||||||
if (!ta || !ta.nodeName || ta.nodeName !== 'TEXTAREA' || map.has(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
|
// TODO: hack - grab our scroll container so we can maintain the scrollTop
|
||||||
const container = getScrollContainer()
|
const container = getScrollContainer()
|
||||||
let heightOffset = null
|
let heightOffset = null
|
||||||
let cachedHeight = null
|
|
||||||
|
|
||||||
function init () {
|
function init () {
|
||||||
const style = window.getComputedStyle(ta, null)
|
const style = window.getComputedStyle(ta, null)
|
||||||
|
@ -35,9 +35,8 @@ function assign (ta) {
|
||||||
|
|
||||||
function resize () {
|
function resize () {
|
||||||
mark('autosize:resize()')
|
mark('autosize:resize()')
|
||||||
const res = _resize()
|
_resize()
|
||||||
stop('autosize:resize()')
|
stop('autosize:resize()')
|
||||||
return res
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function _resize () {
|
function _resize () {
|
||||||
|
@ -51,15 +50,13 @@ function assign (ta) {
|
||||||
if (ta.scrollHeight === 0) {
|
if (ta.scrollHeight === 0) {
|
||||||
// If the scrollHeight is 0, then the element probably has display:none or is detached from the DOM.
|
// If the scrollHeight is 0, then the element probably has display:none or is detached from the DOM.
|
||||||
ta.style.height = originalHeight
|
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 () {
|
function update () {
|
||||||
mark('autosize:update()')
|
mark('autosize:update()')
|
||||||
|
@ -68,17 +65,7 @@ function assign (ta) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function _update () {
|
function _update () {
|
||||||
const newHeight = resize()
|
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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const pageResize = debounce(() => requestAnimationFrame(update), 1000)
|
const pageResize = debounce(() => requestAnimationFrame(update), 1000)
|
||||||
|
@ -86,17 +73,12 @@ function assign (ta) {
|
||||||
const destroy = () => {
|
const destroy = () => {
|
||||||
window.removeEventListener('resize', pageResize, false)
|
window.removeEventListener('resize', pageResize, false)
|
||||||
ta.removeEventListener('input', deferredUpdate, false)
|
ta.removeEventListener('input', deferredUpdate, false)
|
||||||
ta.removeEventListener('autosize:destroy', destroy, false)
|
|
||||||
ta.removeEventListener('autosize:update', update, false)
|
|
||||||
|
|
||||||
map.delete(ta)
|
map.delete(ta)
|
||||||
}
|
}
|
||||||
|
|
||||||
ta.addEventListener('autosize:destroy', destroy, false)
|
|
||||||
|
|
||||||
window.addEventListener('resize', pageResize, false)
|
window.addEventListener('resize', pageResize, false)
|
||||||
ta.addEventListener('input', deferredUpdate, false)
|
ta.addEventListener('input', deferredUpdate, false)
|
||||||
ta.addEventListener('autosize:update', update, false)
|
|
||||||
|
|
||||||
map.set(ta, {
|
map.set(ta, {
|
||||||
destroy,
|
destroy,
|
||||||
|
|
Loading…
Reference in a new issue