diff --git a/App.tsx b/App.tsx index 58bbc72..48a1328 100644 --- a/App.tsx +++ b/App.tsx @@ -12,6 +12,7 @@ import { ConversationHistory } from './components/ConversationHistory'; import { ScenarioSetup } from './components/ScenarioSetup'; import { ApiKeySetup } from './components/ApiKeySetup'; import { GearIcon } from './components/icons/GearIcon'; +import { ConversationHint } from './components/ConversationHint'; const App: React.FC = () => { // SEO metadata - similar to Next.js metadata export @@ -29,6 +30,7 @@ const App: React.FC = () => { const [hasStarted, setHasStarted] = useState(false); const [messages, setMessages] = useState([]); const [autoPlayMessageId, setAutoPlayMessageId] = useState(null); + const [currentHint, setCurrentHint] = useState(null); // Scenario mode state const [scenarioMode, setScenarioMode] = useState('none'); @@ -221,7 +223,7 @@ const App: React.FC = () => { return; } - const { audioUrl, userText, modelText } = response; + const { audioUrl, userText, modelText, hint } = response; // Add messages to history (append for chronological order - newest last) const timestamp = Date.now(); @@ -229,10 +231,15 @@ const App: React.FC = () => { const newMessages: Message[] = [ ...messages, { role: 'user', text: userText, timestamp }, - { role: 'model', text: modelText, timestamp: modelTimestamp, audioUrl }, + { role: 'model', text: modelText, timestamp: modelTimestamp, audioUrl, hint }, ]; setMessages(newMessages); + // Update current hint (only in scenario mode) + if (scenarioMode === 'practice' && hint) { + setCurrentHint(hint); + } + // Set the new model message to auto-play setAutoPlayMessageId(modelTimestamp); @@ -277,9 +284,10 @@ const App: React.FC = () => { // Clear shared conversation history clearHistory(); - // Clear UI messages + // Clear UI messages and hint setMessages([]); setAutoPlayMessageId(null); + setCurrentHint(null); // Always reset Gemini session when clearing history, preserving scenario if active resetSession(activeScenario); } catch (error) { @@ -289,6 +297,7 @@ const App: React.FC = () => { // Still clear UI messages even if resetSession fails setMessages([]); setAutoPlayMessageId(null); + setCurrentHint(null); } }; @@ -476,10 +485,11 @@ const App: React.FC = () => { setScenario(null); setScenarioOpenAI(null); - // Clear conversation + // Clear conversation and hint clearHistory(); setMessages([]); setAutoPlayMessageId(null); + setCurrentHint(null); }; // Status text for the landing view @@ -616,6 +626,13 @@ const App: React.FC = () => { playbackSpeed={playbackSpeed} autoPlayMessageId={autoPlayMessageId} /> + {/* Conversation hint - shown only in scenario practice mode; flex-shrink-0 keeps it visible below the scrollable history */} +
+ +
{/* Sticky Footer - orb-mic + controls */} diff --git a/components/ConversationHint.tsx b/components/ConversationHint.tsx new file mode 100644 index 0000000..cf0295c --- /dev/null +++ b/components/ConversationHint.tsx @@ -0,0 +1,79 @@ +import React, { useState, useEffect } from 'react'; + +interface ConversationHintProps { + hint: string | null; + isVisible: boolean; +} + +export const ConversationHint: React.FC = ({ hint, isVisible }) => { + const [isExpanded, setIsExpanded] = useState(false); + const [isDismissed, setIsDismissed] = useState(false); + + // Reset dismissed state when a new hint arrives + useEffect(() => { + if (hint) { + setIsDismissed(false); + setIsExpanded(false); + } + }, [hint]); + + if (!hint || !isVisible || isDismissed) { + return null; + } + + return ( +
+
+ {/* Header row - toggle button and dismiss button as siblings */} +
+ + +
+ + {/* Expanded view - shows the actual hint */} + {isExpanded && ( +
+
+

+ {hint} +

+
+
+ )} +
+
+ ); +}; diff --git a/components/ConversationHistory.tsx b/components/ConversationHistory.tsx index 24616b5..e57af6e 100644 --- a/components/ConversationHistory.tsx +++ b/components/ConversationHistory.tsx @@ -144,7 +144,7 @@ export const ConversationHistory: React.FC = ({ // Messages are now in chronological order (oldest first, newest last) return ( -
+
{/* Clear button header */}
diff --git a/index.html b/index.html index cdd0a33..b7325fb 100644 --- a/index.html +++ b/index.html @@ -82,6 +82,33 @@ .chat-scrollbar::-webkit-scrollbar-thumb:hover { background: rgba(100, 116, 139, 0.5); } + /* Hint animations */ + @keyframes hint-fade-in { + from { + opacity: 0; + transform: translateY(8px); + } + to { + opacity: 1; + transform: translateY(0); + } + } + @keyframes hint-expand { + from { + opacity: 0; + max-height: 0; + } + to { + opacity: 1; + max-height: 200px; + } + } + .animate-hint-fade-in { + animation: hint-fade-in 0.3s ease-out; + } + .animate-hint-expand { + animation: hint-expand 0.2s ease-out; + }