Files
openchamber/packages/ui/src/contexts/RuntimeAPIProvider.tsx
T
Cursor AgentandSerhii Dziupin fc4db0c656 fix(files): keep text opens working after content-cache dispose
React Strict Mode disposed the memoized content-cache owner while the
provider kept reusing it, so validateContextFileOpen threw before any
/api/fs/read and toasted "Failed to open file" for notes.txt. Binaries
still opened because they skip the pre-read. Serve uncached reads from
disposed owners, clear cache on runtime switch without deactivating, and
own the cache lifecycle in an effect.

Co-authored-by: Serhii Dziupin <makeittech@users.noreply.github.com>
2026-07-30 09:02:14 +00:00

33 lines
1.3 KiB
TypeScript

import React, { type JSX, type ReactNode } from 'react';
import { RuntimeAPIContext } from '@/contexts/runtimeAPIContext';
import type { FilesAPI, RuntimeAPIs } from '@/lib/api/types';
import { createContentCachedFiles } from '@/contexts/content-cache-owner';
type ContentCachedFiles = ReturnType<typeof createContentCachedFiles>;
export function RuntimeAPIProvider({ apis, children }: { apis: RuntimeAPIs; children: ReactNode }): JSX.Element {
// Effect-owned lifecycle: React Strict Mode dispose+remount must create a fresh
// owner. useMemo + dispose reused a dead owner and broke text-file opens
// (binaries skipped the pre-read, so they still appeared to work).
const [cachedOwner, setCachedOwner] = React.useState<ContentCachedFiles | null>(null);
React.useEffect(() => {
const owner = createContentCachedFiles(apis.files);
setCachedOwner(owner);
return () => {
owner.dispose();
setCachedOwner((current) => (current === owner ? null : current));
};
}, [apis.files]);
const files: FilesAPI = cachedOwner?.files ?? apis.files;
const cachedApis = React.useMemo<RuntimeAPIs>(
() => ({
...apis,
files,
}),
[apis, files],
);
return <RuntimeAPIContext.Provider value={cachedApis}>{children}</RuntimeAPIContext.Provider>;
}