Skip to content

Restore mobile lesson usability and fallback resilience#20

Merged
aiedwardyi merged 6 commits into
mainfrom
fix/mobile-interface-regressions
Apr 15, 2026
Merged

Restore mobile lesson usability and fallback resilience#20
aiedwardyi merged 6 commits into
mainfrom
fix/mobile-interface-regressions

Conversation

@aiedwardyi

Copy link
Copy Markdown
Owner

Summary

  • restore the compact mobile lesson header with the longer progress bar, persistent Pyi-thon branding, and no horizontal overflow on narrow screens
  • move hint access back to the task card, add a compact Task jump in the footer, and disable mobile auto-capitalization and text suggestions in the editor
  • fall back to local evaluation when online feedback fails, show quieter one-time session notices, and localize Korean Python syntax fallback errors consistently
  • add regression coverage for compact mobile layout, fallback behavior, Korean error wording, and mobile editor input settings

Testing

  • npm test
  • npm run lint
  • npm run build
  • npm run test:e2e

Copilot AI review requested due to automatic review settings April 15, 2026 08:38

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Comment thread src/theme/themes.js
Comment on lines 425 to 427
.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);
Comment thread src/components/OutputPanel.jsx Outdated
Comment on lines +91 to +114
<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>
Comment thread src/theme/themes.js
Comment on lines 419 to 421
.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);
Comment thread src/App.jsx
Comment on lines 678 to 680
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);
Comment on lines +197 to +198
await page.locator("textarea").fill('print("Hello, World!"');
await page.getByRole("button", { name: /Run Code/ }).click();
Comment on lines +210 to +211
await page.locator("textarea").fill('print("Hello, World!"');
await page.getByRole("button", { name: "코드 실행" }).click();
{showOfflineBadge && (
<div
className="ui-badge-pop"
data-testid="offline-badge"

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Comment thread src/components/OutputPanel.jsx Outdated
Comment on lines +91 to +114
<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>
Comment thread src/App.jsx Outdated
Comment on lines +695 to +698
showLocalFallbackNotice(aiResult.feedback || t("localFallbackNotice"));
result = await evaluateOffline(userCode, level, lang);
feedbackSource = "local";
sourceMessage = aiResult.sourceMessage || t("localFallbackInline");
Comment on lines +219 to +220
await page.locator("textarea").fill('print("Hello, World!"');
await page.getByRole("button", { name: /Run Code/ }).click();
Comment on lines +232 to +233
await page.locator("textarea").fill('print("Hello, World!"');
await page.getByRole("button", { name: "코드 실행" }).click();

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Comment thread src/theme/themes.js
Comment on lines 286 to 290
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);
}
Comment thread src/App.jsx Outdated
C,
completedCount: completedLevels.size,
isCompactHeader,
isCompactMobile,
Comment thread test/e2e/levels-ui.spec.js Outdated
await expect(page.getByRole("button", { name: "Return to editor" })).toBeVisible();

await page.getByTestId("open-settings").click();
await page.getByTestId("lang-ko").click({ force: true });
@aiedwardyi
aiedwardyi merged commit 80ca954 into main Apr 15, 2026
2 checks passed
@aiedwardyi
aiedwardyi deleted the fix/mobile-interface-regressions branch April 15, 2026 10:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants