2020-05-13 05:25:46 +02:00
|
|
|
import { IndexedDBEngine } from './IndexedDBEngine'
|
|
|
|
import { assertNonEmptyString } from './utils/assertNonEmptyString'
|
2020-06-01 17:22:26 +02:00
|
|
|
import { warnETag } from './utils/warnETag'
|
2020-05-17 02:51:37 +02:00
|
|
|
import { assertEmojiBaseData } from './utils/assertEmojiBaseData'
|
|
|
|
import { assertNumber } from './utils/assertNumber'
|
2020-05-17 05:36:21 +02:00
|
|
|
import { DEFAULT_DATA_SOURCE, DEFAULT_LOCALE } from './constants'
|
2020-05-17 19:56:31 +02:00
|
|
|
import { uniqEmoji } from './utils/uniqEmoji'
|
2020-06-01 17:22:26 +02:00
|
|
|
import { jsonChecksum } from '../svelte/utils/jsonChecksum'
|
|
|
|
import { warnOffline } from './utils/warnOffline'
|
2020-05-13 05:25:46 +02:00
|
|
|
|
|
|
|
export class Database {
|
2020-05-17 02:20:00 +02:00
|
|
|
constructor ({ dataSource = DEFAULT_DATA_SOURCE, locale = DEFAULT_LOCALE } = {}) {
|
2020-05-13 05:25:46 +02:00
|
|
|
this._dataSource = dataSource
|
|
|
|
this._locale = locale
|
|
|
|
this._idbEngine = undefined
|
|
|
|
this._readyPromise = this._init()
|
|
|
|
}
|
|
|
|
|
|
|
|
async _init () {
|
2020-05-17 02:20:00 +02:00
|
|
|
this._idbEngine = new IndexedDBEngine(`lite-emoji-picker-${this._locale}`)
|
|
|
|
await this._idbEngine.open()
|
2020-06-01 17:22:26 +02:00
|
|
|
const url = this._dataSource
|
|
|
|
const isEmpty = await this._idbEngine.isEmpty()
|
|
|
|
if (!isEmpty) {
|
2020-05-17 02:20:00 +02:00
|
|
|
// just do a simple HEAD request first to see if the eTags match
|
|
|
|
let headResponse
|
|
|
|
try {
|
2020-06-01 17:22:26 +02:00
|
|
|
headResponse = await fetch(url, { method: 'HEAD' })
|
|
|
|
} catch (e) { // offline fallback
|
|
|
|
warnOffline(e)
|
2020-05-17 02:20:00 +02:00
|
|
|
return
|
|
|
|
}
|
|
|
|
const eTag = headResponse.headers.get('etag')
|
2020-06-01 17:22:26 +02:00
|
|
|
warnETag(eTag)
|
|
|
|
if (eTag && await this._idbEngine.hasData(url, eTag)) {
|
|
|
|
console.log('Database already populated')
|
2020-05-17 02:20:00 +02:00
|
|
|
return // fast init, data is already loaded
|
|
|
|
}
|
|
|
|
}
|
2020-06-01 17:22:26 +02:00
|
|
|
let response
|
|
|
|
try {
|
|
|
|
response = await fetch(this._dataSource)
|
|
|
|
} catch (e) { // offline fallback
|
|
|
|
if (!isEmpty) {
|
|
|
|
warnOffline(e)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
throw e
|
|
|
|
}
|
2020-05-13 17:12:56 +02:00
|
|
|
const emojiBaseData = await response.json()
|
2020-05-17 02:51:37 +02:00
|
|
|
assertEmojiBaseData(emojiBaseData)
|
2020-06-01 17:22:26 +02:00
|
|
|
let eTag = response.headers.get('etag')
|
|
|
|
warnETag(eTag)
|
|
|
|
if (!eTag) {
|
|
|
|
// GNOME Web returns an empty eTag for cross-origin HEAD requests, even when
|
|
|
|
// Access-Control-Expose-Headers:* is set. So as a fallback, compute an ETag
|
|
|
|
// from the object itself.
|
|
|
|
eTag = await jsonChecksum(emojiBaseData)
|
|
|
|
}
|
|
|
|
if (!isEmpty && await this._idbEngine.hasData(url, eTag)) {
|
|
|
|
console.log('Database already populated')
|
|
|
|
return // data already loaded
|
|
|
|
}
|
2020-05-17 02:20:00 +02:00
|
|
|
|
2020-06-01 17:22:26 +02:00
|
|
|
await this._idbEngine.loadData(emojiBaseData, url, eTag)
|
2020-05-13 05:25:46 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
async getEmojiByGroup (group) {
|
2020-05-17 02:51:37 +02:00
|
|
|
assertNumber(group)
|
2020-05-13 05:25:46 +02:00
|
|
|
await this._readyPromise
|
2020-05-17 19:56:31 +02:00
|
|
|
const emojis = await this._idbEngine.getEmojiByGroup(group)
|
|
|
|
return uniqEmoji(emojis)
|
2020-05-13 05:25:46 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
async getEmojiBySearchPrefix (prefix) {
|
|
|
|
assertNonEmptyString(prefix)
|
|
|
|
await this._readyPromise
|
2020-05-17 19:56:31 +02:00
|
|
|
const emojis = await this._idbEngine.getEmojiBySearchPrefix(prefix)
|
|
|
|
return uniqEmoji(emojis)
|
2020-05-13 05:25:46 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
async getEmojiByShortcode (shortcode) {
|
|
|
|
assertNonEmptyString(shortcode)
|
|
|
|
await this._readyPromise
|
2020-05-17 19:56:31 +02:00
|
|
|
const emojis = await this._idbEngine.getEmojiByShortcode(shortcode)
|
|
|
|
return uniqEmoji(emojis)
|
2020-05-13 05:25:46 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
async getEmojiByUnicode (unicode) {
|
|
|
|
assertNonEmptyString(unicode)
|
|
|
|
await this._readyPromise
|
|
|
|
return this._idbEngine.getEmojiByUnicode(unicode)
|
|
|
|
}
|
|
|
|
|
|
|
|
async close () {
|
|
|
|
await this._readyPromise
|
|
|
|
if (this._idbEngine) {
|
|
|
|
await this._idbEngine.close()
|
|
|
|
this._idbEngine = undefined
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
async delete () {
|
|
|
|
await this._readyPromise
|
|
|
|
if (this._idbEngine) {
|
|
|
|
await this._idbEngine.delete()
|
|
|
|
this._idbEngine = undefined
|
|
|
|
}
|
|
|
|
}
|
2020-05-17 02:20:00 +02:00
|
|
|
}
|