Restore mobile lesson usability and fallback resilience#20
Conversation
There was a problem hiding this comment.
Pull request overview
Restores and hardens the mobile lesson experience (compact header/layout, hint/task access, and editor input settings) while improving resilience when online AI evaluation fails by falling back to local evaluation and localizing Python fallback errors (notably in Korean).
Changes:
- Reintroduce compact mobile lesson header behavior, move hint access back into the task card on compact screens, and add a footer “Task” shortcut for quick navigation.
- Add local-evaluation fallback behavior (with quieter one-time session toasts and a persistent header badge) when online feedback fails.
- Add/expand unit + e2e regression tests for mobile layout/input attributes, fallback behaviors, and Korean error localization.
Reviewed changes
Copilot reviewed 17 out of 17 changed files in this pull request and generated 7 comments.
Show a summary per file
| File | Description |
|---|---|
| test/run-tests.js | Wires new localization unit test into the Node test runner. |
| test/python-error-localization.test.js | Adds unit coverage for Korean/English Python error localization behavior. |
| test/e2e/levels-ui.spec.js | Expands e2e coverage for compact header layout, editor input attrs, fallback toasts, and Korean fallback wording. |
| test/ai-evaluation.test.js | Verifies evaluateWithAI marks error outcomes as eligible for local fallback. |
| src/theme/themes.js | Updates global animations/transitions to use scale/translate/rotate transform properties and adjusts toggle knob styling. |
| src/lib/storage.js | Adds safe sessionStorage get/set helpers for one-time-per-session notices. |
| src/lib/pythonErrorLocalization.js | Introduces Korean localization for common Python runtime/syntax error patterns. |
| src/lib/aiEvaluation.js | Adds fallbackToLocal to error results to enable local-eval fallback on API issues. |
| src/data/appConfig.js | Adds new strings for “Local” labeling and new fallback/toast copy in EN/KO. |
| src/components/WorkspacePanel.jsx | Hides the bottom hint panel on compact mobile (hint moves to task card). |
| src/components/OutputPanel.jsx | Adds inline “checked with local feedback” messaging and adjusts result header UI. |
| src/components/LevelInfoPanel.jsx | Moves compact-mobile hint UI into the task card and adds “Editor” jump control. |
| src/components/GameHeader.jsx | Keeps branding visible, adds persistent local/offline badge, and adjusts compact header behavior. |
| src/components/EditorPanel.jsx | Disables mobile auto-capitalization/corrections/autocomplete and sets mobile-friendly input hints. |
| src/components/ActionBar.jsx | Changes compact-mobile hint shortcut to a “Task” scroll shortcut. |
| src/App.jsx | Adds session-scoped status toasts, task/editor scrolling, local fallback flow, and localized offline Python errors. |
| CHANGELOG.md | Documents the mobile flow changes and the new fallback/badge behavior. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| .ui-pop:hover .ui-toggle-knob { | ||
| --toggle-knob-scale: 1.04; | ||
| scale: 1.08; | ||
| box-shadow: 0 3px 10px rgba(0,0,0,0.25); |
| <button | ||
| type="button" | ||
| className={feedback.correct ? undefined : "ui-icon-pop"} | ||
| onClick={() => { | ||
| if (!feedback.correct) setTab("editor"); | ||
| }} | ||
| style={{ | ||
| width: 36, | ||
| height: 36, | ||
| borderRadius: 10, | ||
| display: "flex", | ||
| alignItems: "center", | ||
| justifyContent: "center", | ||
| flexShrink: 0, | ||
| background: feedback.correct ? C.green : C.red, | ||
| cursor: feedback.correct ? "default" : "pointer", | ||
| border: "none", | ||
| padding: 0, | ||
| }} | ||
| > | ||
| {feedback.correct | ||
| ? <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="#fff" strokeWidth="3" strokeLinecap="round" strokeLinejoin="round"><polyline points="20 6 9 17 4 12" /></svg> | ||
| : <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="#fff" strokeWidth="3" strokeLinecap="round"><line x1="18" y1="6" x2="6" y2="18" /><line x1="6" y1="6" x2="18" y2="18" /></svg>} | ||
| </button> |
| .ui-pop:focus-visible .ui-toggle-knob { | ||
| --toggle-knob-scale: 1.04; | ||
| scale: 1.08; | ||
| box-shadow: 0 3px 10px rgba(0,0,0,0.25); |
| if (!userCode || userCode === level.starterCode.trim()) { | ||
| const attemptCount = (failedAttemptsByLevel[level.id] || 0) + 1; | ||
| setFailedAttemptsByLevel(prev => ({ ...prev, [level.id]: attemptCount })); | ||
| setFeedback({ correct: false, message: t("writeCodeFirst"), expected, attemptCount }); | ||
| setFeedback({ correct: false, message: t("writeCodeFirst"), expected: level.expectedOutput }); | ||
| setShakeEditor(true); setTimeout(() => setShakeEditor(false), 500); |
| await page.locator("textarea").fill('print("Hello, World!"'); | ||
| await page.getByRole("button", { name: /Run Code/ }).click(); |
| await page.locator("textarea").fill('print("Hello, World!"'); | ||
| await page.getByRole("button", { name: "코드 실행" }).click(); |
| {showOfflineBadge && ( | ||
| <div | ||
| className="ui-badge-pop" | ||
| data-testid="offline-badge" |
There was a problem hiding this comment.
Pull request overview
This PR restores the intended compact mobile lesson experience while making evaluation more resilient by falling back to local (Pyodide) checks when online feedback fails, and by improving Korean localization for Python error messages.
Changes:
- Reworks mobile lesson UI (compact header behavior, hint/task access points, editor input attributes to reduce mobile keyboard interference).
- Adds online→local fallback signaling (session-scoped toast + inline “source” messaging) and localizes Korean Python error fallback wording.
- Adds unit + Playwright regression coverage for the above behaviors.
Reviewed changes
Copilot reviewed 17 out of 17 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| test/run-tests.js | Registers the new Python error localization unit test in the Node test runner. |
| test/python-error-localization.test.js | Adds unit coverage for Korean/English Python error localization behavior. |
| test/e2e/levels-ui.spec.js | Expands Playwright coverage for compact header layout, session toast behavior, fallback handling, and Korean wording. |
| test/ai-evaluation.test.js | Verifies evaluateWithAI marks certain failures as eligible for local fallback and returns source messaging. |
| src/theme/themes.js | Updates global animations/transitions to use individual transform properties (scale/translate/rotate). |
| src/lib/storage.js | Adds safe sessionStorage get/set helpers for session-scoped UI behavior. |
| src/lib/pythonErrorLocalization.js | Introduces Korean localization for common Python error patterns. |
| src/lib/aiEvaluation.js | Adds a structured “fallback-to-local” return shape for online evaluation failures. |
| src/data/appConfig.js | Adds new localized strings for local feedback badges/notices and inline source messaging. |
| src/components/WorkspacePanel.jsx | Moves hint rendering rules to support compact-mobile hint placement changes. |
| src/components/OutputPanel.jsx | Displays local-feedback source messaging inline and adjusts output panel UI interactions. |
| src/components/LevelInfoPanel.jsx | Adds compact-mobile hint controls and renders hint content inside the task card area. |
| src/components/GameHeader.jsx | Restores compact header behavior and adds a persistent local-feedback badge. |
| src/components/EditorPanel.jsx | Disables mobile auto-capitalization/correction/suggestions for the code editor textarea. |
| src/components/ActionBar.jsx | Replaces compact-mobile footer hint shortcut with a “Task” jump behavior. |
| src/App.jsx | Implements session-scoped toast notices, online→local fallback execution, and Korean error localization in offline evaluation. |
| CHANGELOG.md | Documents the UX + fallback behavior changes. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| <button | ||
| type="button" | ||
| className={feedback.correct ? undefined : "ui-icon-pop"} | ||
| onClick={() => { | ||
| if (!feedback.correct) setTab("editor"); | ||
| }} | ||
| style={{ | ||
| width: 36, | ||
| height: 36, | ||
| borderRadius: 10, | ||
| display: "flex", | ||
| alignItems: "center", | ||
| justifyContent: "center", | ||
| flexShrink: 0, | ||
| background: feedback.correct ? C.green : C.red, | ||
| cursor: feedback.correct ? "default" : "pointer", | ||
| border: "none", | ||
| padding: 0, | ||
| }} | ||
| > | ||
| {feedback.correct | ||
| ? <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="#fff" strokeWidth="3" strokeLinecap="round" strokeLinejoin="round"><polyline points="20 6 9 17 4 12" /></svg> | ||
| : <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="#fff" strokeWidth="3" strokeLinecap="round"><line x1="18" y1="6" x2="6" y2="18" /><line x1="6" y1="6" x2="18" y2="18" /></svg>} | ||
| </button> |
| showLocalFallbackNotice(aiResult.feedback || t("localFallbackNotice")); | ||
| result = await evaluateOffline(userCode, level, lang); | ||
| feedbackSource = "local"; | ||
| sourceMessage = aiResult.sourceMessage || t("localFallbackInline"); |
| await page.locator("textarea").fill('print("Hello, World!"'); | ||
| await page.getByRole("button", { name: /Run Code/ }).click(); |
| await page.locator("textarea").fill('print("Hello, World!"'); | ||
| await page.getByRole("button", { name: "코드 실행" }).click(); |
There was a problem hiding this comment.
Pull request overview
Restores mobile lesson usability (compact header/task+hint flow, improved mobile editor input behavior) while improving resilience when online AI evaluation fails by falling back to local evaluation with quieter session-level notices and consistent Korean error localization.
Changes:
- Reworked mobile UI flow: compact header behavior, hint access moved to the task card on compact screens, and added “Task” jump in the action bar.
- Added local-feedback resilience: session-scoped toast notices, persistent “Local” header badge, and AI-eval fallback to offline evaluation with an inline source message.
- Added Korean Python error localization and expanded unit/e2e regression coverage for layout + fallback scenarios.
Reviewed changes
Copilot reviewed 17 out of 17 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| test/run-tests.js | Registers the new unit test file in the unit test runner. |
| test/python-error-localization.test.js | Adds unit coverage for Korean Python error localization. |
| test/e2e/levels-ui.spec.js | Expands Playwright coverage for compact header/layout, mobile editor attributes, and fallback messaging. |
| test/ai-evaluation.test.js | Updates unit assertions for AI-eval fallback-to-local metadata. |
| src/theme/themes.js | Updates global animation/transition styling for UI elements and keyframes. |
| src/lib/storage.js | Adds safe sessionStorage get/set helpers used for session-scoped notices. |
| src/lib/pythonErrorLocalization.js | Introduces Korean localization for common Python error messages. |
| src/lib/aiEvaluation.js | Adds a structured “fallback to local” return path and source messaging for AI failures. |
| src/data/appConfig.js | Adds new localized strings for return-to-editor, local badge/label, and fallback notices/messages. |
| src/components/WorkspacePanel.jsx | Hides the workspace hint panel on compact mobile (hint moves to task card). |
| src/components/OutputPanel.jsx | Adds local-feedback source messaging, updates “return to editor” labeling, and simplifies the retry UI. |
| src/components/LevelInfoPanel.jsx | Moves hint UI into the task card on compact mobile, adds editor jump, and exposes a ref for task scrolling. |
| src/components/GameHeader.jsx | Restores/adjusts compact header behavior and adds a persistent “Local” status badge. |
| src/components/EditorPanel.jsx | Disables mobile auto-capitalization/autocorrect/autocomplete to reduce Python syntax interference. |
| src/components/ActionBar.jsx | Changes compact-mobile footer hint shortcut into a “Task” scroll shortcut. |
| src/App.jsx | Implements session-scoped status toasts, AI→local fallback flow, task/editor scrolling, and Korean offline error localization. |
| CHANGELOG.md | Documents the restored mobile flow and quieter local-feedback notice behavior. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| transform-origin: center; | ||
| transition-property: transform, filter, box-shadow, background-color, border-color, color, opacity; | ||
| transition-duration: 150ms; | ||
| transition-timing-function: ease-out; | ||
| transition-property: scale, translate, rotate, filter, box-shadow, background-color, border-color, color, opacity; | ||
| transition-duration: 220ms; | ||
| transition-timing-function: cubic-bezier(0.2, 0.9, 0.2, 1.15); | ||
| } |
| C, | ||
| completedCount: completedLevels.size, | ||
| isCompactHeader, | ||
| isCompactMobile, |
| await expect(page.getByRole("button", { name: "Return to editor" })).toBeVisible(); | ||
|
|
||
| await page.getByTestId("open-settings").click(); | ||
| await page.getByTestId("lang-ko").click({ force: true }); |
Summary
Testing