-
Notifications
You must be signed in to change notification settings - Fork 9
fix: Start Over button now properly resets state to allow new generations #65
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 2 commits
89186f8
e56b852
7554da9
3529178
e16c34f
8e58537
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -46,6 +46,8 @@ const thumbnailFaqItems: { question: string; answer: string }[] = [ | |
| export default function Home() { | ||
| const videoRef = useRef<HTMLVideoElement | null>(null); | ||
| const canvasRef = useRef<HTMLCanvasElement | null>(null); | ||
| // AbortController for cancelling in-flight generation and suggestion requests | ||
| const abortControllerRef = useRef<AbortController | null>(null); | ||
|
|
||
| const [videoUrl, setVideoUrl] = useState<string | null>(null); | ||
| const [videoReady, setVideoReady] = useState(false); | ||
|
|
@@ -145,11 +147,17 @@ export default function Home() { | |
| // Fetch suggested refinements when results are generated | ||
| useEffect(() => { | ||
| if (results.length > 0 && !refinementState.isRefinementMode) { | ||
| // Capture current abort signal to use in async callbacks | ||
| const currentAbortSignal = abortControllerRef.current?.signal; | ||
|
|
||
| // Fetch suggestions for each result | ||
| results.forEach((thumbnailUrl, index) => { | ||
| if (thumbnailUrl && !suggestedRefinements[index] && !loadingSuggestions[index]) { | ||
| // Call the fetch function inline to avoid dependency issues | ||
| const fetchSuggestions = async () => { | ||
| // Check if aborted before starting | ||
| if (currentAbortSignal?.aborted) return; | ||
|
|
||
| setLoadingSuggestions(prev => ({ ...prev, [index]: true })); | ||
|
|
||
| try { | ||
|
|
@@ -172,20 +180,31 @@ export default function Home() { | |
| originalPrompt, | ||
| templateId: selectedIds[0] || "default", | ||
| }), | ||
| signal: currentAbortSignal, | ||
| }); | ||
|
|
||
| const data = await response.json(); | ||
|
|
||
| // Check if aborted before updating state | ||
| if (currentAbortSignal?.aborted) return; | ||
|
|
||
| if (data.success && data.suggestions) { | ||
| setSuggestedRefinements(prev => ({ | ||
| ...prev, | ||
| [index]: data.suggestions, | ||
| })); | ||
| } | ||
| } catch (error) { | ||
| // Silently ignore abort errors | ||
| if (error instanceof Error && error.name === 'AbortError') { | ||
| return; | ||
| } | ||
| console.error("Failed to fetch suggested refinements:", error); | ||
| } finally { | ||
| setLoadingSuggestions(prev => ({ ...prev, [index]: false })); | ||
| // Only update loading state if not aborted | ||
| if (!currentAbortSignal?.aborted) { | ||
| setLoadingSuggestions(prev => ({ ...prev, [index]: false })); | ||
| } | ||
| } | ||
| }; | ||
|
|
||
|
|
@@ -849,6 +868,23 @@ export default function Home() { | |
| setBlobUrls([]); | ||
| }; | ||
|
|
||
| // Start over: clear results and go back to step 1 | ||
| const handleStartOver = () => { | ||
| // Abort any in-flight generation or suggestion requests | ||
| if (abortControllerRef.current) { | ||
| abortControllerRef.current.abort(); | ||
| abortControllerRef.current = null; | ||
| } | ||
| cleanupBlobUrls(); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If “Start Over” can be clicked while generation or suggested-refinement fetches are still in flight, those async completions can still update 🤖 Was this useful? React with 👍 or 👎 |
||
| setResults([]); | ||
| setLabeledResults([]); | ||
| setSuggestedRefinements({}); | ||
| setLoadingSuggestions({}); | ||
| setLoading(false); | ||
| setError(null); | ||
| goTo(1); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
🤖 Was this useful? React with 👍 or 👎 |
||
| }; | ||
|
|
||
| const generate = async () => { | ||
| // Get all valid template IDs (custom + curated) | ||
| const allValidTemplateIds = new Set([ | ||
|
|
@@ -886,6 +922,13 @@ export default function Home() { | |
| setError(needed <= 0 ? "Please select at least one template." : `You need ${needed} credit${needed === 1 ? '' : 's'} to run this. You have ${credits}.`); | ||
| return; | ||
| } | ||
| // Abort any previous in-flight requests before starting new generation | ||
| if (abortControllerRef.current) { | ||
| abortControllerRef.current.abort(); | ||
| } | ||
| abortControllerRef.current = new AbortController(); | ||
| const abortSignal = abortControllerRef.current.signal; | ||
|
|
||
| setAuthRequired(false); | ||
| setShowAuthModal(false); | ||
| setError(null); | ||
|
|
@@ -1013,6 +1056,7 @@ export default function Home() { | |
| method: "POST", | ||
| headers: { "Content-Type": "application/json" }, | ||
| body: JSON.stringify(body), | ||
| signal: abortSignal, | ||
| }); | ||
| if (res.status === 401) { | ||
| setAuthRequired(true); | ||
|
|
@@ -1156,6 +1200,10 @@ export default function Home() { | |
| } | ||
| } | ||
| } catch (err: unknown) { | ||
| // Don't show error if request was aborted (e.g., user clicked Start Over) | ||
| if (err instanceof Error && err.name === 'AbortError') { | ||
|
||
| return; | ||
| } | ||
| setError(err instanceof Error ? err.message : "Failed to generate"); | ||
| } finally { | ||
| setLoading(false); | ||
|
||
|
|
@@ -2125,7 +2173,7 @@ export default function Home() { | |
|
|
||
| {/* Compact nav */} | ||
| <div className={styles.navRow} style={{ marginTop: 12 }}> | ||
| <button onClick={() => goTo(1)} style={{ padding: '6px 12px', fontSize: 13 }}>← Start Over</button> | ||
| <button onClick={handleStartOver} style={{ padding: '6px 12px', fontSize: 13 }}>← Start Over</button> | ||
| </div> | ||
| </> | ||
| )} | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since
abortControllerRefis now central to request lifecycle, consider aborting it in a component unmount cleanup as well, so in-flightfetchcalls can’t resolve and attempt state updates after navigation/unmount.🤖 Was this useful? React with 👍 or 👎