feat: save preferred skin tone

This commit is contained in:
Nolan Lawson 2020-06-11 20:04:42 -07:00
parent bdb62c07e2
commit d5be361a49
8 changed files with 68 additions and 11 deletions

View File

@ -1,9 +1,9 @@
import { assertNonEmptyString } from './utils/assertNonEmptyString'
import { assertNumber } from './utils/assertNumber'
import { DEFAULT_DATA_SOURCE, DEFAULT_LOCALE } from './constants'
import { DEFAULT_DATA_SOURCE, DEFAULT_LOCALE, KEY_PREFERRED_SKINTONE, STORE_KEYVALUE } from './constants'
import { uniqEmoji } from './utils/uniqEmoji'
import { jsonChecksum } from './utils/jsonChecksum'
import { closeDatabase, deleteDatabase, openDatabase } from './databaseLifecycle'
import { closeDatabase, deleteDatabase, openDatabase, get, set } from './databaseLifecycle'
import {
isEmpty, hasData, loadData, getEmojiByGroup,
getEmojiBySearchQuery, getEmojiByShortcode, getEmojiByUnicode
@ -101,6 +101,17 @@ export default class Database {
return getEmojiByUnicode(this._db, unicode)
}
async getPreferredSkinTone () {
await this.ready()
return (await get(this._db, STORE_KEYVALUE, KEY_PREFERRED_SKINTONE)) || 0
}
async setPreferredSkinTone (skinTone) {
assertNumber(skinTone)
await this.ready()
return set(this._db, STORE_KEYVALUE, KEY_PREFERRED_SKINTONE, skinTone)
}
async _shutdown () {
await this.ready() // reopen if we've already been closed/deleted
try {

View File

@ -1,7 +1,8 @@
export const DB_VERSION_CURRENT = 1
export const DB_VERSION_INITIAL = 1
export const STORE_EMOJI = 'emoji'
export const STORE_META = 'meta'
export const STORE_KEYVALUE = 'keyvalue'
export const STORE_FAVORITES = 'favorites'
export const FIELD_TOKENS = 'tokens'
export const INDEX_TOKENS = 'tokens'
export const FIELD_UNICODE = 'unicode'
@ -10,6 +11,7 @@ export const FIELD_ORDER = 'order'
export const INDEX_GROUP_AND_ORDER = 'group-order'
export const KEY_ETAG = 'eTag'
export const KEY_URL = 'url'
export const KEY_PREFERRED_SKINTONE = 'skinTone'
export const MODE_READONLY = 'readonly'
export const MODE_READWRITE = 'readwrite'

View File

@ -1,5 +1,5 @@
import { migrations } from './migrations'
import { DB_VERSION_CURRENT, MODE_READONLY } from './constants'
import { DB_VERSION_CURRENT, MODE_READONLY, MODE_READWRITE } from './constants'
import { mark, stop } from '../shared/marks'
const openReqs = {}
@ -76,6 +76,13 @@ export function get (db, storeName, key) {
})
}
export function set (db, storeName, key, value) {
return dbPromise(db, storeName, MODE_READWRITE, (store, cb) => {
store.put(value, key)
cb()
})
}
export function closeDatabase (dbName) {
// close any open requests
const req = openReqs[dbName]

View File

@ -3,18 +3,18 @@ import {
INDEX_GROUP_AND_ORDER, INDEX_TOKENS, KEY_ETAG, KEY_URL,
MODE_READONLY, MODE_READWRITE,
STORE_EMOJI,
STORE_META
STORE_KEYVALUE
} from './constants'
import { transformEmojiBaseData } from './utils/transformEmojiBaseData'
import { mark, stop } from '../shared/marks'
import { extractTokens } from './utils/extractTokens'
export async function isEmpty (db) {
return !(await get(db, STORE_META, KEY_URL))
return !(await get(db, STORE_KEYVALUE, KEY_URL))
}
export async function hasData (db, url, eTag) {
const [oldETag, oldUrl] = await get(db, STORE_META, [KEY_ETAG, KEY_URL])
const [oldETag, oldUrl] = await get(db, STORE_KEYVALUE, [KEY_ETAG, KEY_URL])
return (oldETag === eTag && oldUrl === url)
}
@ -22,7 +22,7 @@ export async function loadData (db, emojiBaseData, url, eTag) {
mark('loadData')
try {
const transformedData = transformEmojiBaseData(emojiBaseData)
await dbPromise(db, [STORE_EMOJI, STORE_META], MODE_READWRITE, ([emojiStore, metaStore]) => {
await dbPromise(db, [STORE_EMOJI, STORE_KEYVALUE], MODE_READWRITE, ([emojiStore, metaStore]) => {
let oldETag
let oldUrl
let oldKeys

View File

@ -4,7 +4,9 @@ import {
FIELD_TOKENS,
INDEX_GROUP_AND_ORDER,
STORE_EMOJI,
STORE_META, INDEX_TOKENS
STORE_KEYVALUE,
STORE_FAVORITES,
INDEX_TOKENS
} from './constants'
function initialMigration (db, tx, done) {
@ -20,11 +22,12 @@ function initialMigration (db, tx, done) {
return store
}
createObjectStore(STORE_META)
createObjectStore(STORE_KEYVALUE)
createObjectStore(STORE_EMOJI, { keyPath: FIELD_UNICODE }, [
{ indexName: INDEX_TOKENS, keyPath: FIELD_TOKENS, multiEntry: true },
{ indexName: INDEX_GROUP_AND_ORDER, keyPath: [FIELD_GROUP, FIELD_ORDER] }
])
createObjectStore(STORE_FAVORITES, { keyPath: FIELD_UNICODE })
done()
}

View File

@ -65,6 +65,7 @@ $: {
}, TIMEOUT_BEFORE_LOADING_MESSAGE)
try {
await database.ready()
currentSkinTone = await database.getPreferredSkinTone()
} catch (err) {
console.error(err)
message = i18n.networkError
@ -336,6 +337,7 @@ function onClickSkinToneOption (event) {
skinTonePickerExpanded = false
focus('skintone-button')
fireEvent('skin-tone-change', { skinTone })
/* no await */ database.setPreferredSkinTone(skinTone)
}
// eslint-disable-next-line no-unused-vars

View File

@ -1,4 +1,4 @@
import { Emoji, DatabaseConstructorOptions } from "./shared";
import {Emoji, DatabaseConstructorOptions, SkinTone} from "./shared";
export default class Database {
@ -71,6 +71,22 @@ export default class Database {
return Promise.resolve(null)
}
/**
* Get the user's preferred skin tone. Returns 0 if not found.
*/
getPreferredSkinTone(): Promise<SkinTone> {
return Promise.resolve(1)
}
/**
* Set the user's preferred skin tone. Non-numbers throw an error.
*
* @param skinTone - preferred skin tone
*/
setPreferredSkinTone(skinTone: SkinTone): Promise<void> {
return Promise.resolve()
}
/**
* Closes the underlying IndexedDB connection. The Database is not usable after that (or any other Databases
* with the same locale).

View File

@ -0,0 +1,16 @@
import { ALL_EMOJI, basicAfterEach, basicBeforeEach } from '../shared'
import Database from '../../../src/database/Database'
describe('database tests', () => {
beforeEach(basicBeforeEach)
afterEach(basicAfterEach)
test('get and set preferred skin tone', async () => {
const db = new Database({ dataSource: ALL_EMOJI })
expect(await db.getPreferredSkinTone()).toBe(0)
await db.setPreferredSkinTone(5)
expect(await db.getPreferredSkinTone()).toBe(5)
await expect(() => db.setPreferredSkinTone()).rejects.toThrow()
await db.delete()
})
})