Skip to content

Commit

Permalink
refactor chat input context in favor of zustand store
Browse files Browse the repository at this point in the history
  • Loading branch information
sejas committed Jan 13, 2025
1 parent 33b9b0b commit a7efc5d
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 29 deletions.
10 changes: 6 additions & 4 deletions src/components/content-tab-assistant.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import { usePromptUsage } from '../hooks/use-prompt-usage';
import { useWelcomeMessages } from '../hooks/use-welcome-messages';
import { cx } from '../lib/cx';
import { getIpcApi } from '../lib/get-ipc-api';
import { useChatInputStore } from '../stores/chat-input-store';
import ClearHistoryReminder from './ai-clear-history-reminder';
import { AIInput } from './ai-input';
import { MessageThinking } from './assistant-thinking';
Expand Down Expand Up @@ -368,19 +369,20 @@ export function ContentTabAssistant( { selectedSite }: ContentTabAssistantProps
const { __ } = useI18n();
const lastMessage = messages.length === 0 ? undefined : messages[ messages.length - 1 ];
const hasFailedMessage = messages.some( ( msg ) => msg.failedMessage );
const { getChatInput, saveChatInput } = useChatInputStore();

// Restore prompt input when site changes
useEffect( () => {
setCurrentInput( chatContext.getChatInput( selectedSite.id ) );
}, [ selectedSite.id, chatContext ] );
setCurrentInput( getChatInput( selectedSite.id ) );
}, [ selectedSite.id, getChatInput ] );

// Save prompt input when it changes
const setInput = useCallback(
( input: string ) => {
chatContext.saveChatInput( input, selectedSite.id );
saveChatInput( input, selectedSite.id );
setCurrentInput( input );
},
[ selectedSite.id, chatContext ]
[ selectedSite.id, saveChatInput ]
);

const submitPrompt = useCallback(
Expand Down
16 changes: 8 additions & 8 deletions src/hooks/tests/use-chat-context.test.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { renderHook, act } from '@testing-library/react';
import { getIpcApi } from '../../lib/get-ipc-api';
import { useChatInputStore } from '../../stores/chat-input-store';
import { ChatProvider, useChatContext } from '../use-chat-context';
import { useCheckInstalledApps } from '../use-check-installed-apps';
import { useGetWpVersion } from '../use-get-wp-version';
Expand Down Expand Up @@ -76,6 +77,11 @@ beforeEach( () => {
terminalWpCliEnabled: false,
} );
setupWpCliResult( { themes: [], plugins: [] } );

// Reset Zustand store
act( () => {
useChatInputStore.setState( { inputBySite: {} } );
} );
} );

afterEach( () => {
Expand All @@ -102,8 +108,6 @@ describe( 'useChatContext hook', () => {
availableEditors: [],
siteName: 'Test Site',
os: 'darwin',
getChatInput: expect.any( Function ),
saveChatInput: expect.any( Function ),
} );
} );

Expand Down Expand Up @@ -212,8 +216,6 @@ describe( 'useChatContext hook', () => {
availableEditors: [],
siteName: 'Another Test Site',
os: 'darwin',
getChatInput: expect.any( Function ),
saveChatInput: expect.any( Function ),
} );
} );

Expand Down Expand Up @@ -370,8 +372,6 @@ describe( 'useChatContext hook', () => {
availableEditors: [],
siteName: 'New Test Site',
os: 'darwin',
getChatInput: expect.any( Function ),
saveChatInput: expect.any( Function ),
} );
} );

Expand Down Expand Up @@ -511,7 +511,7 @@ describe( 'useChatContext hook', () => {

describe( 'chat input functionality', () => {
it( 'saves and retrieves chat input by site', () => {
const { result } = renderHook( () => useChatContext(), { wrapper } );
const { result } = renderHook( () => useChatInputStore(), { wrapper } );

act( () => {
result.current.saveChatInput( 'test input 1', 'site-1' );
Expand All @@ -523,7 +523,7 @@ describe( 'useChatContext hook', () => {
} );

it( 'returns empty string for non-existent site input', () => {
const { result } = renderHook( () => useChatContext(), { wrapper } );
const { result } = renderHook( () => useChatInputStore(), { wrapper } );
expect( result.current.getChatInput( 'non-existent-site' ) ).toBe( '' );
} );
} );
Expand Down
17 changes: 0 additions & 17 deletions src/hooks/use-chat-context.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,6 @@ export interface ChatContextType {
os: string;
availableEditors: string[];
siteName?: string;
getChatInput: ( siteId: string ) => string;
saveChatInput: ( input: string, siteId: string ) => void;
}
const ChatContext = createContext< ChatContextType >( {
currentURL: '',
Expand All @@ -43,10 +41,6 @@ const ChatContext = createContext< ChatContextType >( {
availableEditors: [] as string[],
os: '',
siteName: '',
getChatInput: () => '',
saveChatInput: () => {
// noop
},
} );

interface ChatProviderProps {
Expand All @@ -67,7 +61,6 @@ const parseWpCliOutput = ( stdout: string, defaultValue: string[] ): string[] =>

export const ChatProvider: React.FC< ChatProviderProps > = ( { children } ) => {
const initialLoad = useRef< Record< string, boolean > >( {} );
const inputBySite = useRef< Record< string, string > >( {} );
const installedApps = useCheckInstalledApps();
const { data: sites, loadingSites, selectedSite } = useSiteDetails();
const wpVersion = useGetWpVersion( selectedSite || ( {} as SiteDetails ) );
Expand All @@ -82,14 +75,6 @@ export const ChatProvider: React.FC< ChatProviderProps > = ( { children } ) => {
return installedApps[ app as keyof InstalledApps ];
} );

const getChatInput = useCallback( ( siteId: string ) => {
return inputBySite.current[ siteId ] ?? '';
}, [] );

const saveChatInput = useCallback( ( input: string, siteId: string ) => {
inputBySite.current[ siteId ] = input;
}, [] );

const fetchPluginList = useCallback( async ( siteId: string ) => {
const { stdout, stderr } = await getIpcApi().executeWPCLiInline( {
siteId,
Expand Down Expand Up @@ -165,13 +150,11 @@ export const ChatProvider: React.FC< ChatProviderProps > = ( { children } ) => {
value={ {
availableEditors,
currentURL: `http://localhost:${ sitePort }`,
getChatInput,
isBlockTheme: themeDetails?.isBlockTheme,
numberOfSites,
os: window.appGlobals?.platform,
phpVersion: selectedSite?.phpVersion ?? DEFAULT_PHP_VERSION,
pluginList: selectedSite?.id ? pluginsList[ selectedSite.id ] || [] : [],
saveChatInput,
siteName: selectedSite?.name,
themeList: selectedSite?.id ? themesList[ selectedSite.id ] || [] : [],
themeName: themeDetails?.name,
Expand Down
27 changes: 27 additions & 0 deletions src/stores/tests/chat-input-store.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { act, renderHook } from '@testing-library/react';
import { useChatInputStore } from '../chat-input-store';

describe( 'useChatInputStore', () => {
beforeEach( () => {
act( () => {
useChatInputStore.setState( { inputBySite: {} } );
} );
} );

it( 'saves and retrieves chat input by site', () => {
const { result } = renderHook( () => useChatInputStore() );

act( () => {
result.current.saveChatInput( 'test input 1', 'site-1' );
result.current.saveChatInput( 'test input 2', 'site-2' );
} );

expect( result.current.getChatInput( 'site-1' ) ).toBe( 'test input 1' );
expect( result.current.getChatInput( 'site-2' ) ).toBe( 'test input 2' );
} );

it( 'returns empty string for non-existent site input', () => {
const { result } = renderHook( () => useChatInputStore() );
expect( result.current.getChatInput( 'non-existent-site' ) ).toBe( '' );
} );
} );

0 comments on commit a7efc5d

Please sign in to comment.