Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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')

Expand Down Expand Up @@ -125,6 +130,22 @@ export const Copilot = forwardRef<CopilotRef, CopilotProps>(({ 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
*/
Expand Down
Original file line number Diff line number Diff line change
@@ -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'
Original file line number Diff line number Diff line change
@@ -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])
}