Comments
This commit is contained in:
+1
-1
@@ -11,7 +11,7 @@ export const LOCAL_DEV_SERVICE =
|
|||||||
export const STAGING_SERVICE = 'https://staging.bsky.dev'
|
export const STAGING_SERVICE = 'https://staging.bsky.dev'
|
||||||
export const PROD_SERVICE = 'https://bsky.social'
|
export const PROD_SERVICE = 'https://bsky.social'
|
||||||
export const DEFAULT_SERVICE = PROD_SERVICE
|
export const DEFAULT_SERVICE = PROD_SERVICE
|
||||||
const ROOT_STATE_STORAGE_KEY = 'root'
|
export const ROOT_STATE_STORAGE_KEY = 'root'
|
||||||
const STATE_FETCH_INTERVAL = 15e3
|
const STATE_FETCH_INTERVAL = 15e3
|
||||||
|
|
||||||
export async function setupState(serviceUri = DEFAULT_SERVICE) {
|
export async function setupState(serviceUri = DEFAULT_SERVICE) {
|
||||||
|
|||||||
@@ -16,13 +16,14 @@ afterEach(() => {
|
|||||||
test(`gets and sets data synchronously`, async () => {
|
test(`gets and sets data synchronously`, async () => {
|
||||||
storage.set('shell', {colorMode: 'light'})
|
storage.set('shell', {colorMode: 'light'})
|
||||||
expect(AsyncStorage.setItem).toHaveBeenCalledWith(
|
expect(AsyncStorage.setItem).toHaveBeenCalledWith(
|
||||||
storage.STORAGE_ROOT_KEY,
|
storage.ROOT_STATE_STORAGE_KEY,
|
||||||
JSON.stringify({shell: {colorMode: 'light'}}),
|
JSON.stringify({shell: {colorMode: 'light'}}),
|
||||||
)
|
)
|
||||||
storage.set('shell', {colorMode: 'light'})
|
storage.set('shell', {colorMode: 'light'})
|
||||||
expect(AsyncStorage.getItem).not.toHaveBeenCalled()
|
expect(AsyncStorage.getItem).not.toHaveBeenCalled()
|
||||||
|
|
||||||
storage.set('shell', {colorMode: 'dark'})
|
storage.set('shell', {colorMode: 'dark'})
|
||||||
|
// @ts-expect-error
|
||||||
expect(storage.get('shell').colorMode).toBe('dark')
|
expect(storage.get('shell').colorMode).toBe('dark')
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -35,5 +36,6 @@ test(`set ignores error and continues in memory`, async () => {
|
|||||||
|
|
||||||
await storage.set('shell', {colorMode: 'system'})
|
await storage.set('shell', {colorMode: 'system'})
|
||||||
|
|
||||||
|
// @ts-expect-error
|
||||||
expect(storage.get('shell').colorMode).toBe('system')
|
expect(storage.get('shell').colorMode).toBe('system')
|
||||||
})
|
})
|
||||||
|
|||||||
+22
-4
@@ -3,7 +3,13 @@ import AsyncStorage from '@react-native-async-storage/async-storage'
|
|||||||
import {logger} from '#/logger'
|
import {logger} from '#/logger'
|
||||||
import {Schema, defaultData} from '#/storage/schema'
|
import {Schema, defaultData} from '#/storage/schema'
|
||||||
|
|
||||||
export const STORAGE_ROOT_KEY = 'root'
|
/**
|
||||||
|
* The key we use to store our data in local storage.
|
||||||
|
*
|
||||||
|
* This value exists in `src/state/index.ts` also, but that file loads every mobx
|
||||||
|
* store too, so it's duplicated here so that tests run faster.
|
||||||
|
*/
|
||||||
|
export const ROOT_STATE_STORAGE_KEY = 'root'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* In memory cache of local storage data. Never export or reference this
|
* In memory cache of local storage data. Never export or reference this
|
||||||
@@ -14,22 +20,34 @@ export const STORAGE_ROOT_KEY = 'root'
|
|||||||
*/
|
*/
|
||||||
let data: Schema = defaultData
|
let data: Schema = defaultData
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads data from local storage into memory for synchronous access. This
|
||||||
|
* should be called once at the root of the application.
|
||||||
|
*/
|
||||||
export async function init() {
|
export async function init() {
|
||||||
logger.debug(`storage initializing`)
|
logger.debug(`storage initializing`)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const raw = await AsyncStorage.getItem(STORAGE_ROOT_KEY)
|
const raw = await AsyncStorage.getItem(ROOT_STATE_STORAGE_KEY)
|
||||||
data = (raw ? JSON.parse(raw) : {}) as Schema
|
data = (raw ? JSON.parse(raw) : {}) as Schema
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
logger.error(`storage init() failed`)
|
logger.error(`storage init() failed`)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function get<T extends keyof Schema>(key: T): Schema[T] {
|
/**
|
||||||
|
* Get a value from local storage. Returns `unknown` type to force us to
|
||||||
|
* validate and cast to the types we expect.
|
||||||
|
*/
|
||||||
|
export function get<T extends keyof Schema>(key: T): unknown {
|
||||||
logger.debug(`storage get(${key})`)
|
logger.debug(`storage get(${key})`)
|
||||||
return data[key]
|
return data[key]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set a value on local storage. When setting objects, you need to manually
|
||||||
|
* merge in new values.
|
||||||
|
*/
|
||||||
export async function set<T extends keyof Schema>(key: T, value: Schema[T]) {
|
export async function set<T extends keyof Schema>(key: T, value: Schema[T]) {
|
||||||
logger.debug(`storage set(${key}, value)`)
|
logger.debug(`storage set(${key}, value)`)
|
||||||
|
|
||||||
@@ -37,7 +55,7 @@ export async function set<T extends keyof Schema>(key: T, value: Schema[T]) {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
// TODO maybe debounce this in the future
|
// TODO maybe debounce this in the future
|
||||||
await AsyncStorage.setItem(STORAGE_ROOT_KEY, JSON.stringify(data))
|
await AsyncStorage.setItem(ROOT_STATE_STORAGE_KEY, JSON.stringify(data))
|
||||||
return true
|
return true
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
logger.error(`storage set(${key}, value) failed`)
|
logger.error(`storage set(${key}, value) failed`)
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/**
|
/**
|
||||||
* The shape of the object we store in local storage
|
* The shape of the object we store in local storage.
|
||||||
*/
|
*/
|
||||||
export type Schema = {
|
export type Schema = {
|
||||||
shell: {
|
shell: {
|
||||||
@@ -7,6 +7,11 @@ export type Schema = {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The default values for the schema. This is used to initialize the store, and
|
||||||
|
* is used in case AsyncStorage is unavailable. This should be kept in sync
|
||||||
|
* with the Schema type above.
|
||||||
|
*/
|
||||||
export const defaultData: Schema = {
|
export const defaultData: Schema = {
|
||||||
shell: {
|
shell: {
|
||||||
colorMode: 'system',
|
colorMode: 'system',
|
||||||
|
|||||||
Reference in New Issue
Block a user