Per-user search history (#7588)
* per-user search history * move to mmkv with cool new hook * revert accidental changes This reverts commit 27c89fa645eff0acb7a8fd852203ff1ea3725c69. * restore limits
This commit is contained in:
+69
-3
@@ -1,5 +1,5 @@
|
||||
import {useCallback, useEffect, useState} from 'react'
|
||||
import {MMKV} from 'react-native-mmkv'
|
||||
import {Did} from '@atproto/api'
|
||||
|
||||
import {Account, Device} from '#/storage/schema'
|
||||
|
||||
@@ -65,6 +65,72 @@ export class Storage<Scopes extends unknown[], Schema> {
|
||||
removeMany<Key extends keyof Schema>(scopes: [...Scopes], keys: Key[]) {
|
||||
keys.forEach(key => this.remove([...scopes, key]))
|
||||
}
|
||||
|
||||
/**
|
||||
* Fires a callback when the storage associated with a given key changes
|
||||
*
|
||||
* @returns Listener - call `remove()` to stop listening
|
||||
*/
|
||||
addOnValueChangedListener<Key extends keyof Schema>(
|
||||
scopes: [...Scopes, Key],
|
||||
callback: () => void,
|
||||
) {
|
||||
return this.store.addOnValueChangedListener(key => {
|
||||
if (key === scopes.join(this.sep)) {
|
||||
callback()
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
type StorageSchema<T extends Storage<any, any>> = T extends Storage<
|
||||
any,
|
||||
infer U
|
||||
>
|
||||
? U
|
||||
: never
|
||||
type StorageScopes<T extends Storage<any, any>> = T extends Storage<
|
||||
infer S,
|
||||
any
|
||||
>
|
||||
? S
|
||||
: never
|
||||
|
||||
/**
|
||||
* Hook to use a storage instance. Acts like a useState hook, but persists the
|
||||
* value in storage.
|
||||
*/
|
||||
export function useStorage<
|
||||
Store extends Storage<any, any>,
|
||||
Key extends keyof StorageSchema<Store>,
|
||||
>(
|
||||
storage: Store,
|
||||
scopes: [...StorageScopes<Store>, Key],
|
||||
): [
|
||||
StorageSchema<Store>[Key] | undefined,
|
||||
(data: StorageSchema<Store>[Key]) => void,
|
||||
] {
|
||||
type Schema = StorageSchema<Store>
|
||||
const [value, setValue] = useState<Schema[Key] | undefined>(() =>
|
||||
storage.get(scopes),
|
||||
)
|
||||
|
||||
useEffect(() => {
|
||||
const sub = storage.addOnValueChangedListener(scopes, () => {
|
||||
setValue(storage.get(scopes))
|
||||
})
|
||||
return () => sub.remove()
|
||||
}, [storage, scopes])
|
||||
|
||||
const setter = useCallback(
|
||||
(data: Schema[Key]) => {
|
||||
setValue(data)
|
||||
storage.set(scopes, data)
|
||||
},
|
||||
[storage, scopes],
|
||||
)
|
||||
|
||||
return [value, setter] as const
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -77,10 +143,10 @@ export const device = new Storage<[], Device>({id: 'bsky_device'})
|
||||
/**
|
||||
* Account data that's specific to the account on this device
|
||||
*/
|
||||
export const account = new Storage<[Did], Account>({id: 'bsky_account'})
|
||||
export const account = new Storage<[string], Account>({id: 'bsky_account'})
|
||||
|
||||
if (__DEV__ && typeof window !== 'undefined') {
|
||||
// @ts-ignore
|
||||
// @ts-expect-error - dev global
|
||||
window.bsky_storage = {
|
||||
device,
|
||||
account,
|
||||
|
||||
@@ -13,4 +13,5 @@ export type Device = {
|
||||
|
||||
export type Account = {
|
||||
searchTermHistory?: string[]
|
||||
searchAccountHistory?: string[]
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user