fix: use top level await accessing users idb (#721)

Co-authored-by: 三咲智子 <sxzz@sxzz.moe>
This commit is contained in:
Joaquín Sánchez 2023-01-03 01:18:01 +01:00 committed by GitHub
parent 029440421d
commit c6f292a68c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 69 additions and 4 deletions

65
composables/idb/index.ts Normal file
View file

@ -0,0 +1,65 @@
import type { MaybeComputedRef, RemovableRef } from '@vueuse/core'
import type { Ref } from 'vue'
import { del, get, set, update } from 'idb-keyval'
import type { UseIDBOptions } from '@vueuse/integrations/useIDBKeyval'
export async function useAsyncIDBKeyval<T>(
key: IDBValidKey,
initialValue: MaybeComputedRef<T>,
options: UseIDBOptions = {},
): Promise<RemovableRef<T>> {
const {
flush = 'pre',
deep = true,
shallow,
onError = (e: unknown) => {
console.error(e)
},
} = options
const data = (shallow ? shallowRef : ref)(initialValue) as Ref<T>
const rawInit: T = resolveUnref(initialValue)
async function read() {
try {
const rawValue = await get<T>(key)
if (rawValue === undefined) {
if (rawInit !== undefined && rawInit !== null)
await set(key, rawInit)
}
else {
data.value = rawValue
}
}
catch (e) {
onError(e)
}
}
await read()
async function write() {
try {
if (data.value == null) {
await del(key)
}
else {
// IndexedDB does not support saving proxies, convert from proxy before saving
if (Array.isArray(data.value))
await update(key, () => (JSON.parse(JSON.stringify(data.value))))
else if (typeof data.value === 'object')
await update(key, () => ({ ...data.value }))
else
await update(key, () => (data.value))
}
}
catch (e) {
onError(e)
}
}
watch(data, () => write(), { flush, deep })
return data as RemovableRef<T>
}

View file

@ -1,5 +1,4 @@
import { login as loginMasto } from 'masto'
import { useIDBKeyval } from '@vueuse/integrations/useIDBKeyval'
import type { Account, AccountCredentials, Instance, MastoClient, WsEvents } from 'masto'
import type { Ref } from 'vue'
import type { RemovableRef } from '@vueuse/core'
@ -14,10 +13,11 @@ import {
STORAGE_KEY_USERS,
} from '~/constants'
import type { PushNotificationPolicy, PushNotificationRequest } from '~/composables/push-notifications/types'
import { useAsyncIDBKeyval } from '~/composables/idb'
const mock = process.mock
const initializeUsers = (): Ref<UserLogin[]> | RemovableRef<UserLogin[]> => {
const initializeUsers = async (): Promise<Ref<UserLogin[]> | RemovableRef<UserLogin[]>> => {
let defaultUsers = mock ? [mock.user] : []
// Backward compatibility with localStorage
@ -32,7 +32,7 @@ const initializeUsers = (): Ref<UserLogin[]> | RemovableRef<UserLogin[]> => {
const users = process.server
? ref<UserLogin[]>(defaultUsers)
: useIDBKeyval<UserLogin[]>(STORAGE_KEY_USERS, defaultUsers, { deep: true })
: await useAsyncIDBKeyval<UserLogin[]>(STORAGE_KEY_USERS, defaultUsers, { deep: true })
if (removeUsersOnLocalStorage)
globalThis.localStorage.removeItem(STORAGE_KEY_USERS)
@ -40,7 +40,7 @@ const initializeUsers = (): Ref<UserLogin[]> | RemovableRef<UserLogin[]> => {
return users
}
const users = initializeUsers()
const users = await initializeUsers()
const instances = useLocalStorage<Record<string, Instance>>(STORAGE_KEY_SERVERS, mock ? mock.server : {}, { deep: true })
const currentUserId = useLocalStorage<string>(STORAGE_KEY_CURRENT_USER, mock ? mock.user.account.id : '')