feat: add proper step initialization and multi-step navigation to TutorialContext
- Add useEffect to initialize first step with correct startValue on mount - Add advanceMultiStep, previousMultiStep, resetMultiStep functions to context - Implement isProgrammaticChange flag to prevent feedback loops during step navigation - Auto-clear isProgrammaticChange flag after external value changes settle - Ensures abacus displays correct startValue when navigating between tutorial steps 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -147,6 +147,9 @@ interface TutorialContextType {
|
||||
goToNextStep: () => void
|
||||
goToPreviousStep: () => void
|
||||
handleValueChange: (newValue: number) => void
|
||||
advanceMultiStep: () => void
|
||||
previousMultiStep: () => void
|
||||
resetMultiStep: () => void
|
||||
handleBeadClick: (beadInfo: any) => void
|
||||
handleBeadRef: (bead: any, element: SVGElement | null) => void
|
||||
toggleDebugPanel: () => void
|
||||
@@ -207,6 +210,24 @@ export function TutorialProvider({
|
||||
}
|
||||
})
|
||||
|
||||
// Initialize the first step on mount
|
||||
React.useEffect(() => {
|
||||
if (tutorial.steps.length > 0) {
|
||||
const step = tutorial.steps[initialStepIndex]
|
||||
|
||||
// Mark as programmatic change to prevent AbacusReact feedback loop
|
||||
isProgrammaticChange.current = true
|
||||
|
||||
dispatch({
|
||||
type: 'INITIALIZE_STEP',
|
||||
stepIndex: initialStepIndex,
|
||||
startValue: step.startValue,
|
||||
stepId: step.id
|
||||
})
|
||||
onStepChange?.(initialStepIndex, step)
|
||||
}
|
||||
}, []) // Empty dependency array - only run on mount
|
||||
|
||||
// Current step and computed values
|
||||
const currentStep = tutorial.steps[state.currentStepIndex]
|
||||
|
||||
@@ -249,6 +270,10 @@ export function TutorialProvider({
|
||||
const goToStep = useCallback((stepIndex: number) => {
|
||||
if (stepIndex >= 0 && stepIndex < tutorial.steps.length) {
|
||||
const step = tutorial.steps[stepIndex]
|
||||
|
||||
// Mark as programmatic change to prevent AbacusReact feedback loop
|
||||
isProgrammaticChange.current = true
|
||||
|
||||
dispatch({
|
||||
type: 'INITIALIZE_STEP',
|
||||
stepIndex,
|
||||
@@ -259,6 +284,18 @@ export function TutorialProvider({
|
||||
}
|
||||
}, [tutorial.steps, onStepChange])
|
||||
|
||||
// Clear isProgrammaticChange flag after external value changes have settled
|
||||
React.useEffect(() => {
|
||||
// Use a small timeout to ensure the AbacusReact has processed the value change
|
||||
const timeoutId = setTimeout(() => {
|
||||
if (isProgrammaticChange.current) {
|
||||
isProgrammaticChange.current = false
|
||||
}
|
||||
}, 100)
|
||||
|
||||
return () => clearTimeout(timeoutId)
|
||||
}, [state.currentValue])
|
||||
|
||||
const goToNextStep = useCallback(() => {
|
||||
if (navigationState.canGoNext) {
|
||||
goToStep(state.currentStepIndex + 1)
|
||||
@@ -273,6 +310,7 @@ export function TutorialProvider({
|
||||
|
||||
const handleValueChange = useCallback((newValue: number) => {
|
||||
if (isProgrammaticChange.current) {
|
||||
isProgrammaticChange.current = false
|
||||
return
|
||||
}
|
||||
|
||||
@@ -336,6 +374,18 @@ export function TutorialProvider({
|
||||
})
|
||||
}, [state.uiState.autoAdvance])
|
||||
|
||||
const advanceMultiStep = useCallback(() => {
|
||||
dispatch({ type: 'ADVANCE_MULTI_STEP' })
|
||||
}, [])
|
||||
|
||||
const previousMultiStep = useCallback(() => {
|
||||
dispatch({ type: 'PREVIOUS_MULTI_STEP' })
|
||||
}, [])
|
||||
|
||||
const resetMultiStep = useCallback(() => {
|
||||
dispatch({ type: 'RESET_MULTI_STEP' })
|
||||
}, [])
|
||||
|
||||
const getCurrentStepBeads = useCallback(() => {
|
||||
if (expectedSteps.length === 0) return currentStep.stepBeadHighlights || []
|
||||
|
||||
@@ -425,6 +475,9 @@ export function TutorialProvider({
|
||||
goToNextStep,
|
||||
goToPreviousStep,
|
||||
handleValueChange,
|
||||
advanceMultiStep,
|
||||
previousMultiStep,
|
||||
resetMultiStep,
|
||||
handleBeadClick,
|
||||
handleBeadRef,
|
||||
toggleDebugPanel,
|
||||
|
||||
Reference in New Issue
Block a user