mirror of
https://github.com/supabase/supabase.git
synced 2026-09-07 02:20:52 +08:00
Audited all proxy()/useSnapshot() usage against the v1→v2 migration guide; no breaking changes apply (no reused proxy() inputs, no promise-valued state, all consumers already client components). <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Chores** * Updated the Valtio dependency to a newer version for improved compatibility. * **Bug Fixes** * Improved AI assistant persistence in IndexedDB so chat sessions reliably save (while keeping only the most recent 20 messages per chat). * Hardened tabs restoration from storage to fall back to fresh defaults when data is missing, invalid, or fails validation. * **Refactor** * Switched multiple studio panels to use fresh initial-state factories for initialization and reset reliability. * Updated advisor state so the derived notification filter count is no longer exposed. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
87 lines
2.7 KiB
TypeScript
87 lines
2.7 KiB
TypeScript
import { createContext, PropsWithChildren, useContext, useMemo } from 'react'
|
|
import { proxy, useSnapshot } from 'valtio'
|
|
|
|
import { StorageItemWithColumn } from '@/components/interfaces/Storage/Storage.types'
|
|
import type { Bucket } from '@/data/storage/buckets-query'
|
|
|
|
function createBucketFilePickerState({
|
|
bucket,
|
|
maxFiles,
|
|
acceptedFileExtensions,
|
|
}: {
|
|
bucket: Bucket
|
|
maxFiles: number
|
|
acceptedFileExtensions?: string[]
|
|
}) {
|
|
const state = proxy({
|
|
bucket: bucket,
|
|
maxFiles: maxFiles,
|
|
acceptedFileExtensions: acceptedFileExtensions,
|
|
|
|
columns: [] as string[],
|
|
popColumn: () => {
|
|
const lastColumnIndex = state.columns.length - 1
|
|
state.columns = state.columns.slice(0, lastColumnIndex)
|
|
},
|
|
popColumnAtIndex: (index: number) => {
|
|
state.columns = state.columns.slice(0, index)
|
|
},
|
|
pushColumnAtIndex: (column: string, index: number) => {
|
|
state.columns = state.columns.slice(0, index).concat([column])
|
|
},
|
|
|
|
selectedItems: [] as StorageItemWithColumn[],
|
|
setSelectedItems: (items: StorageItemWithColumn[]) => (state.selectedItems = items),
|
|
clearSelectedItems: (columnIndex?: number) => {
|
|
if (columnIndex !== undefined) {
|
|
state.selectedItems = state.selectedItems.filter((item) => item.columnIndex !== columnIndex)
|
|
} else {
|
|
state.selectedItems = []
|
|
}
|
|
},
|
|
|
|
itemSearchString: '',
|
|
setItemSearchString: (value: string) => (state.itemSearchString = value),
|
|
|
|
selectedFilePreview: undefined as StorageItemWithColumn | undefined,
|
|
setSelectedFilePreview: (file?: StorageItemWithColumn) => (state.selectedFilePreview = file),
|
|
})
|
|
|
|
return state
|
|
}
|
|
|
|
export type BucketFilePickerState = ReturnType<typeof createBucketFilePickerState>
|
|
|
|
const createDefaultStateConfig = () => ({
|
|
bucket: {} as Bucket,
|
|
maxFiles: 1 as const,
|
|
})
|
|
|
|
const BucketFilePickerStateContext = createContext<BucketFilePickerState>(
|
|
createBucketFilePickerState(createDefaultStateConfig())
|
|
)
|
|
|
|
export const BucketFilePickerStateContextProvider = ({
|
|
bucket,
|
|
maxFiles,
|
|
acceptedFileExtensions,
|
|
children,
|
|
}: PropsWithChildren<{ bucket: Bucket; maxFiles: number; acceptedFileExtensions?: string[] }>) => {
|
|
const state = useMemo(
|
|
() => createBucketFilePickerState({ bucket, maxFiles, acceptedFileExtensions }),
|
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
[bucket, maxFiles, acceptedFileExtensions?.join(',')]
|
|
)
|
|
|
|
return (
|
|
<BucketFilePickerStateContext.Provider value={state}>
|
|
{children}
|
|
</BucketFilePickerStateContext.Provider>
|
|
)
|
|
}
|
|
|
|
export function useBucketFilePickerStateSnapshot(options?: Parameters<typeof useSnapshot>[1]) {
|
|
const state = useContext(BucketFilePickerStateContext)
|
|
return useSnapshot(state, options) as BucketFilePickerState
|
|
}
|