perf: reduce code in PickerElement

This commit is contained in:
Nolan Lawson 2020-06-17 00:03:50 -07:00
parent 297d4ad9e8
commit c70df34450
3 changed files with 25 additions and 67 deletions

View File

@ -55,9 +55,9 @@ async function loadDataForFirstTime (db, dataSource) {
export default class Database {
constructor ({ dataSource = DEFAULT_DATA_SOURCE, locale = DEFAULT_LOCALE, customEmoji = [] } = {}) {
this._dataSource = dataSource
this._locale = locale
this._dbName = `emoji-picker-element-${this._locale}`
this.dataSource = dataSource
this.locale = locale
this._dbName = `emoji-picker-element-${this.locale}`
this._db = undefined
this._lazyUpdate = undefined
this._custom = customEmojiIndex(customEmoji)
@ -67,7 +67,7 @@ export default class Database {
async _init () {
const db = this._db = await openDatabase(this._dbName)
const dataSource = this._dataSource
const dataSource = this.dataSource
const empty = await isEmpty(db)
if (empty) {

View File

@ -1,63 +1,11 @@
import SveltePicker from './components/Picker/Picker.svelte'
import Database from './ImportedDatabase'
import { DEFAULT_DATA_SOURCE, DEFAULT_LOCALE } from '../database/constants'
import enI18n from './i18n/en'
import { mark } from '../shared/marks'
import { DEFAULT_SKIN_TONE_EMOJI } from './constants'
export default class Picker extends SveltePicker {
constructor ({
locale = DEFAULT_LOCALE,
dataSource = DEFAULT_DATA_SOURCE,
i18n = enI18n,
skinToneEmoji = DEFAULT_SKIN_TONE_EMOJI,
customEmoji = []
} = {}) {
constructor (props) {
mark('initialLoad')
// Make the API simpler, directly pass in the props
// Also wrap the locale/dataSource into a Database object
super({
props: {
database: new Database({ dataSource, locale }),
i18n,
skinToneEmoji,
customEmoji
}
})
this._locale = locale
this._dataSource = dataSource
this._updateScheduled = undefined
}
get locale () {
return this._locale
}
get dataSource () {
return this._dataSource
}
set locale (locale) {
this._locale = locale
this._scheduleUpdate()
}
set dataSource (dataSource) {
this._dataSource = dataSource
this._scheduleUpdate()
}
_scheduleUpdate () {
if (this._updateScheduled) {
return
}
// We want to update the Database once if dataSource/locale are both updated in one turn of the event loop, e.g.:
// picker.locale = 'fr' ; picker.dataSource = '/node_modules/emojibase-data/fr/data.json';
// ^ This should only cause one network request and one new Database to be created
this._updateScheduled = Promise.resolve().then(() => {
this.database = new Database({ dataSource: this._dataSource, locale: this._locale })
this._updateScheduled = undefined
})
super({ props })
}
}

View File

@ -9,7 +9,6 @@ import { requestIdleCallback } from '../../utils/requestIdleCallback'
import { hasZwj } from '../../utils/hasZwj'
import { emojiSupportLevelPromise, supportedZwjEmojis } from '../../utils/emojiSupport'
import { log } from '../../../shared/log'
import { stop } from '../../../shared/marks'
import { applySkinTone } from '../../utils/applySkinTone'
import { halt } from '../../utils/halt'
import { incrementOrDecrement } from '../../utils/incrementOrDecrement'
@ -26,8 +25,11 @@ import { summarizeEmojisForUI } from '../../utils/summarizeEmojisForUI'
import { calculateWidth, resizeObserverSupported } from '../../utils/calculateWidth'
import { checkZwjSupport } from '../../utils/checkZwjSupport'
import { requestPostAnimationFrame } from '../../utils/requestPostAnimationFrame'
import { stop } from '../../../shared/marks'
// public
let locale = null
let dataSource = null
let skinToneEmoji = DEFAULT_SKIN_TONE_EMOJI
let i18n = enI18n
let database = null
@ -131,10 +133,16 @@ $: {
// but are only set later. This would cause a double render or a double-fetch of
// the dataSource, which is bad. Delaying with a microtask avoids this.
Promise.resolve().then(() => {
if (!database) {
database = new Database({ dataSource: DEFAULT_DATA_SOURCE, locale: DEFAULT_LOCALE })
}
log('setting locale and dataSource to default')
locale = locale || DEFAULT_LOCALE
dataSource = dataSource || DEFAULT_DATA_SOURCE
})
$: {
if (locale && dataSource && (!database || (database.locale !== locale && database.dataSource !== dataSource))) {
log('creating database', { locale, dataSource })
database = new Database({ dataSource, locale })
}
}
//
// Global styles for the entire picker
@ -323,11 +331,11 @@ function checkZwjSupportAndUpdate (zwjEmojisToCheck) {
checkZwjSupport(zwjEmojisToCheck, baselineEmoji, emojiToDomNode)
// force update
currentEmojis = currentEmojis // eslint-disable-line no-self-assign
if (initialLoad) {
initialLoad = false
// Measure after style/layout are complete
// see https://github.com/andrewiggins/afterframe
if (process.env.NODE_ENV !== 'production' || process.env.PERF) {
if (process.env.NODE_ENV !== 'production' || process.env.PERF) {
if (initialLoad) {
initialLoad = false
// Measure after style/layout are complete
// see https://github.com/andrewiggins/afterframe
requestPostAnimationFrame(() => stop('initialLoad'))
}
}
@ -562,6 +570,8 @@ async function onSkinToneOptionsBlur () {
}
export {
locale,
dataSource,
database,
i18n,
skinToneEmoji,