// src/plugin/hooks/useMetadataCacheVersion.ts
import { useCallback, useSyncExternalStore } from 'react'
import type { MetadataCache } from '../../services/metadata'
/**
* React hook that subscribes to MetadataCache changes and returns the current version.
*
* Uses `useSyncExternalStore` internally to integrate MetadataCache's internal
* subscription system with React's rendering cycle. The version increments whenever
* the cache updates (on updateFile, removeFile, clear, deserialize, or vault events).
*
* This is an internal hook for built-in panels and UI components. External plugins
* should use `metadataCache.on('changed', callback)` directly.
*
* @example
* ```tsx
* function MyPanel({ metadataCache }: Props) {
* const version = useMetadataCacheVersion(metadataCache)
*
* const data = useMemo(
* () => metadataCache.getFileCache(docUrl),
* [docUrl, metadataCache, version] // version dependency triggers re-compute
* )
*
* return
{JSON.stringify(data)}
* }
* ```
*
* @internal Built-in UI uses this for React integration. External plugins should
* use `metadataCache.on('changed', callback)` (Obsidian-shape).
*/
export function useMetadataCacheVersion(metadataCache: MetadataCache): number {
// Subscribe function uses MetadataCache's internal subscriber system.
// This system notifies on ALL version bumps: updateFile, removeFile, clear,
// deserialize, and vault create/delete/rename events.
//
// The @internal subscribe() method exists specifically for useSyncExternalStore
// integration; external plugins should use on('changed', ...) instead.
const subscribe = useCallback(
(onStoreChange: () => void): (() => void) => {
return metadataCache.subscribe(onStoreChange)
},
[metadataCache],
)
// Snapshot function returns the current version for React's comparison.
// The @internal getVersion() method is coupled with subscribe() for this purpose.
const getSnapshot = useCallback(
(): number => metadataCache.getVersion(),
[metadataCache],
)
return useSyncExternalStore(subscribe, getSnapshot)
}