[1/4] Blob storage in TLStore (#4068)

Reworks the store to include information about how blob assets
(images/videos) are stored/retrieved. This replaces the old
internal-only `assetOptions` prop, and supplements the existing
`registerExternalAssetHandler` API.

Previously, `registerExternalAssetHandler` had two responsibilities:
1. Extracting asset metadata
2. Uploading the asset and returning its URL

Existing `registerExternalAssetHandler` implementation will still work,
but now uploading is the responsibility of a new `editor.uploadAsset`
method which calls the new store-based upload method. Our default asset
handlers extract metadata, then call that new API. I think this is a
pretty big improvement over what we had before: overriding uploads was a
pretty common ask, but doing so meant having to copy paste our metadata
extraction which felt pretty fragile. Just in this codebase, we had a
bunch of very slightly different metadata extraction code-paths that had
been copy-pasted around then diverged over time. Now, you can change how
uploads work without having to mess with metadata extraction and
vice-versa.

As part of this we also:
1. merge the old separate asset indexeddb store with the main one.
because this warrants some pretty big migration stuff, i refactored our
indexed-db helpers to work around an instance instead of being free
functions
2. move our existing asset stuff over to the new approach
3. add a new hook in `sync-react` to create a demo store with the new
assets

### Change type

- [x] `api`

### Release notes

Introduce a new `assets` option for the store, describing how to save
and retrieve asset blobs like images & videos from e.g. a user-content
CDN. These are accessible through `editor.uploadAsset` and
`editor.resolveAssetUrl`. This supplements the existing
`registerExternalAssetHandler` API: `registerExternalAssetHandler` is
for customising metadata extraction, and should call
`editor.uploadAsset` to save assets. Existing
`registerExternalAssetHandler` calls will still work, but if you're only
using them to configure uploads and don't want to customise metadata
extraction, consider switching to the new `assets` store prop.
This commit is contained in:
alex 2024-07-10 14:00:18 +01:00 committed by GitHub
parent 92fa5304f5
commit 965bc10997
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
41 changed files with 1091 additions and 1195 deletions

View file

@ -11,9 +11,9 @@ import { useEffect, useState } from 'react'
import {
Signal,
TAB_ID,
TLAssetStore,
TLRecord,
TLStore,
TLStoreSnapshot,
TLStoreWithStatus,
TLUserPreferences,
computed,
@ -38,9 +38,9 @@ export function useRemoteSyncClient(opts: UseSyncClientConfig): RemoteTLStoreWit
readyClient?: TLSyncClient<TLRecord, TLStore>
error?: Error
} | null>(null)
const { uri, roomId = 'default', userPreferences: prefs } = opts
const { uri, roomId = 'default', userPreferences: prefs, assets } = opts
const store = useTLStore({ schema })
const store = useTLStore({ schema, assets })
const error: NonNullable<typeof state>['error'] = state?.error ?? undefined
const track = opts.trackAnalyticsEvent
@ -138,7 +138,7 @@ export interface UseSyncClientConfig {
uri: string
roomId?: string
userPreferences?: Signal<TLUserPreferences>
snapshotForNewRoomRef?: { current: null | TLStoreSnapshot }
/* @internal */
trackAnalyticsEvent?(name: string, data: { [key: string]: any }): void
assets?: Partial<TLAssetStore>
}