fix(showcase): block financial data from AI Q&A, fix FAB overflow, fix presenter slide mapping
Build pitch-deck / build-push-deploy (push) Successful in 1m47s
CI / go-lint (push) Has been skipped
CI / python-lint (push) Has been skipped
CI / nodejs-lint (push) Has been skipped
CI / test-go-consent (push) Successful in 41s
CI / test-python-voice (push) Successful in 32s
CI / test-bqas (push) Successful in 32s
Build pitch-deck / build-push-deploy (push) Successful in 1m47s
CI / go-lint (push) Has been skipped
CI / python-lint (push) Has been skipped
CI / nodejs-lint (push) Has been skipped
CI / test-go-consent (push) Successful in 41s
CI / test-python-voice (push) Successful in 32s
CI / test-bqas (push) Successful in 32s
AI Q&A: fetch is_showcase from DB; showcase sessions receive no financial/funding context and have an explicit LLM guard refusing to discuss investment details. FAQ context and financial slide IDs stripped from system prompt. FAB: flex layout so Fullscreen button is always visible regardless of panel height. Presenter: pass activeSlideOrder to usePresenterMode so buildSlideAudioPlan maps slideIdx → slideId from the filtered list, not the full SLIDE_ORDER. Progress calculation also filters to active scripts only. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -5,6 +5,7 @@ import { Language } from '../types'
|
||||
import { PresenterState, SlideScript } from '../presenter/types'
|
||||
import { PRESENTER_SCRIPT } from '../presenter/presenter-script'
|
||||
import { SLIDE_ORDER } from './useSlideNavigation'
|
||||
import { SlideId } from '../types'
|
||||
|
||||
interface UsePresenterModeConfig {
|
||||
goToSlide: (index: number) => void
|
||||
@@ -12,6 +13,7 @@ interface UsePresenterModeConfig {
|
||||
totalSlides: number
|
||||
language: Language
|
||||
ttsEnabled?: boolean
|
||||
slideOrder?: SlideId[]
|
||||
}
|
||||
|
||||
interface UsePresenterModeReturn {
|
||||
@@ -57,8 +59,8 @@ interface SlideAudioPlan {
|
||||
segments: AudioSegment[]
|
||||
}
|
||||
|
||||
function buildSlideAudioPlan(slideIdx: number, lang: Language): SlideAudioPlan | null {
|
||||
const slideId = SLIDE_ORDER[slideIdx]
|
||||
function buildSlideAudioPlan(slideIdx: number, lang: Language, activeSlideOrder: SlideId[]): SlideAudioPlan | null {
|
||||
const slideId = activeSlideOrder[slideIdx]
|
||||
const script = PRESENTER_SCRIPT.find(s => s.slideId === slideId)
|
||||
if (!script || script.paragraphs.length === 0) return null
|
||||
|
||||
@@ -121,7 +123,9 @@ export function usePresenterMode({
|
||||
totalSlides,
|
||||
language,
|
||||
ttsEnabled: initialTtsEnabled = true,
|
||||
slideOrder: slideOrderProp,
|
||||
}: UsePresenterModeConfig): UsePresenterModeReturn {
|
||||
const activeSlideOrder = slideOrderProp ?? SLIDE_ORDER
|
||||
const [state, setState] = useState<PresenterState>('idle')
|
||||
const [currentParagraph, setCurrentParagraph] = useState(0)
|
||||
const [displayText, setDisplayText] = useState('')
|
||||
@@ -193,7 +197,7 @@ export function usePresenterMode({
|
||||
playSlideRef.current = async (slideIdx: number) => {
|
||||
if (stateRef.current !== 'presenting') return
|
||||
|
||||
const plan = buildSlideAudioPlan(slideIdx, language)
|
||||
const plan = buildSlideAudioPlan(slideIdx, language, activeSlideOrder)
|
||||
if (!plan) {
|
||||
// No script for this slide — skip to next
|
||||
if (slideIdx < totalSlides - 1) {
|
||||
@@ -216,7 +220,7 @@ export function usePresenterMode({
|
||||
|
||||
// Pre-fetch next slide's audio in background
|
||||
if (slideIdx < totalSlides - 1) {
|
||||
const nextPlan = buildSlideAudioPlan(slideIdx + 1, language)
|
||||
const nextPlan = buildSlideAudioPlan(slideIdx + 1, language, activeSlideOrder)
|
||||
if (nextPlan) fetchAudio(nextPlan.fullText, language).catch(() => {})
|
||||
}
|
||||
|
||||
@@ -329,7 +333,7 @@ export function usePresenterMode({
|
||||
setIsSpeaking(false)
|
||||
}
|
||||
}
|
||||
}, [language, totalSlides, goToSlide, ttsAvailable, ttsEnabled])
|
||||
}, [language, totalSlides, goToSlide, ttsAvailable, ttsEnabled, activeSlideOrder])
|
||||
|
||||
const start = useCallback(() => {
|
||||
unlockAudio()
|
||||
@@ -410,14 +414,18 @@ export function usePresenterMode({
|
||||
}
|
||||
}, [unlockAudio, start, stop])
|
||||
|
||||
// Calculate overall progress
|
||||
// Calculate overall progress against the active slide order's scripts
|
||||
const progress = (() => {
|
||||
if (state === 'idle') return 0
|
||||
const totalScripts = PRESENTER_SCRIPT.length
|
||||
const currentScriptIdx = PRESENTER_SCRIPT.findIndex(s => s.slideId === SLIDE_ORDER[currentSlide])
|
||||
const currentSlideId = activeSlideOrder[currentSlide]
|
||||
const activeScripts = activeSlideOrder
|
||||
.map(id => PRESENTER_SCRIPT.find(s => s.slideId === id))
|
||||
.filter(Boolean) as typeof PRESENTER_SCRIPT
|
||||
const totalScripts = activeScripts.length || 1
|
||||
const currentScriptIdx = activeScripts.findIndex(s => s.slideId === currentSlideId)
|
||||
if (currentScriptIdx < 0) return (currentSlide / totalSlides) * 100
|
||||
|
||||
const script = PRESENTER_SCRIPT[currentScriptIdx]
|
||||
const script = activeScripts[currentScriptIdx]
|
||||
const slideProgress = script.paragraphs.length > 0
|
||||
? currentParagraph / script.paragraphs.length
|
||||
: 0
|
||||
|
||||
Reference in New Issue
Block a user