diff --git a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel-new/components/copilot/copilot.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel-new/components/copilot/copilot.tsx index e6e3fffdef..cfb6f009ed 100644 --- a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel-new/components/copilot/copilot.tsx +++ b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel-new/components/copilot/copilot.tsx @@ -25,7 +25,12 @@ import type { UserInputRef } from '@/app/workspace/[workspaceId]/w/[workflowId]/ import { useScrollManagement } from '@/app/workspace/[workspaceId]/w/[workflowId]/hooks' import { useCopilotStore } from '@/stores/panel-new/copilot/store' import { useWorkflowRegistry } from '@/stores/workflows/registry/store' -import { useChatHistory, useCopilotInitialization, useTodoManagement } from './hooks' +import { + useChatHistory, + useCopilotInitialization, + useLandingPrompt, + useTodoManagement, +} from './hooks' const logger = createLogger('Copilot') @@ -125,6 +130,22 @@ export const Copilot = forwardRef(({ panelWidth }, ref setPlanTodos, }) + /** + * Helper function to focus the copilot input + */ + const focusInput = useCallback(() => { + userInputRef.current?.focus() + }, []) + + // Handle landing page prompt retrieval and population + useLandingPrompt({ + isInitialized, + setInputValue, + focusInput, + isSendingMessage, + currentInputValue: inputValue, + }) + /** * Auto-scroll to bottom when chat loads in */ diff --git a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel-new/components/copilot/hooks/index.ts b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel-new/components/copilot/hooks/index.ts index 230f427005..234740fba4 100644 --- a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel-new/components/copilot/hooks/index.ts +++ b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel-new/components/copilot/hooks/index.ts @@ -1,3 +1,4 @@ export { useChatHistory } from './use-chat-history' export { useCopilotInitialization } from './use-copilot-initialization' +export { useLandingPrompt } from './use-landing-prompt' export { useTodoManagement } from './use-todo-management' diff --git a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel-new/components/copilot/hooks/use-landing-prompt.ts b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel-new/components/copilot/hooks/use-landing-prompt.ts new file mode 100644 index 0000000000..783a938aa5 --- /dev/null +++ b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel-new/components/copilot/hooks/use-landing-prompt.ts @@ -0,0 +1,77 @@ +'use client' + +import { useEffect, useRef } from 'react' +import { LandingPromptStorage } from '@/lib/browser-storage' +import { createLogger } from '@/lib/logs/console/logger' + +const logger = createLogger('useLandingPrompt') + +interface UseLandingPromptProps { + /** + * Whether the copilot is fully initialized and ready to receive input + */ + isInitialized: boolean + + /** + * Callback to set the input value in the copilot + */ + setInputValue: (value: string) => void + + /** + * Callback to focus the copilot input + */ + focusInput: () => void + + /** + * Whether a message is currently being sent (prevents overwriting during active chat) + */ + isSendingMessage: boolean + + /** + * Current input value (to avoid overwriting if user has already typed) + */ + currentInputValue: string +} + +/** + * Custom hook to handle landing page prompt retrieval and population + * + * When a user enters a prompt on the landing page and signs up/logs in, + * this hook retrieves that prompt from localStorage and populates it + * in the copilot input once the copilot is initialized. + * + * @param props - Configuration for landing prompt handling + */ +export function useLandingPrompt(props: UseLandingPromptProps) { + const { isInitialized, setInputValue, focusInput, isSendingMessage, currentInputValue } = props + + const hasCheckedRef = useRef(false) + + useEffect(() => { + // Only check once when copilot is first initialized + if (!isInitialized || hasCheckedRef.current || isSendingMessage) { + return + } + + // If user has already started typing, don't override + if (currentInputValue && currentInputValue.trim().length > 0) { + hasCheckedRef.current = true + return + } + + // Try to retrieve the stored prompt (max age: 24 hours) + const prompt = LandingPromptStorage.consume() + + if (prompt) { + logger.info('Retrieved landing page prompt, populating copilot input') + setInputValue(prompt) + + // Focus the input after a brief delay to ensure DOM is ready + setTimeout(() => { + focusInput() + }, 150) + } + + hasCheckedRef.current = true + }, [isInitialized, setInputValue, focusInput, isSendingMessage, currentInputValue]) +}