Skip to content

Conversation

takaokouji
Copy link

Summary

Implement "Load from URL" functionality for Scratch projects as requested in issue #222.

This PR adds a new menu item "URLから読み込む" (Load from URL) to the File menu that allows users to input Scratch project URLs and automatically load the projects.

Implementation Details

Core Components Added:

  • src/lib/url-parser.js: Utility functions to extract Scratch project IDs from URLs
  • src/lib/url-loader-hoc.jsx: Higher-order component following the same pattern as sb-file-uploader-hoc.jsx

Integration Points:

  • File Menu: Added new menu item between "Load from your computer" and "Save to your computer"
  • HOC Composition: Integrated URLLoaderHOC into the main HOC chain in gui.jsx
  • Internationalization: Added Japanese translation in src/locales/ja.js

Technical Approach:

  • Uses prompt() for URL input (consistent with existing Scratch patterns)
  • Validates Scratch URLs with regex patterns supporting:
    • Standard URLs: https://scratch.mit.edu/projects/1209008277/
    • URLs with paths: https://scratch.mit.edu/projects/1209008277/editor/
  • Leverages existing infrastructure:
    • Smalruby API proxy for project token fetching
    • VM storage system for project loading
    • ProjectFetcherHOC patterns for consistent behavior

User Experience:

  1. User clicks "Load from URL" in File menu
  2. Prompted to enter Scratch project URL
  3. URL validation and project ID extraction
  4. Confirmation dialog for project replacement (if applicable)
  5. Loading screen during project fetch
  6. Project loads with extracted project ID as title

Test Plan

  • Lint checks pass
  • Menu item appears in File menu
  • Japanese translation displays correctly
  • URL validation works for various Scratch URL formats
  • Project loading works with valid Scratch project URLs
  • Error handling for invalid URLs and failed loads
  • Integration test with real Scratch project URLs

Breaking Changes

None. This is a purely additive feature.

Related Issues

Fixes #222

🤖 Generated with Claude Code

takaokouji and others added 15 commits September 16, 2025 13:37
Implement "Load from URL" functionality for Scratch projects:

- Add URL parsing utility to extract project IDs from Scratch URLs
- Create URL loader HOC following the same pattern as sb-file-uploader-hoc
- Add new menu item "Load from URL" in File menu between existing load/save options
- Add Japanese translation "URLから読み込む" for i18n support
- Integrate with existing project loading infrastructure via ProjectFetcherHOC
- Support URLs like https://scratch.mit.edu/projects/1209008277/

The implementation uses prompt() for URL input and validates Scratch project URLs,
extracting project IDs to load projects through the existing Smalruby API proxy.

Fixes #222

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <[email protected]>
- Add debug logs to URLLoaderHOC constructor, handler methods, and render
- Add debug logs to MenuBar handleClickLoadFromUrl method
- Add debug logs to HOC integration in gui.jsx
- Create proper click handler in MenuBar instead of direct prop reference

This will help identify why the Load from URL menu item is not working.
Fixed prop drilling issue where onStartSelectingUrlLoad was being
passed to DOM elements, causing React to show warnings and ignore
the event handler. Added proper prop filtering in URLLoaderHOC
render method.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <[email protected]>
MenuBar was not receiving the onStartSelectingUrlLoad prop because
it wasn't being passed down from GUIComponent. Added the prop to:
- Function parameter destructuring
- MenuBar component props
- PropTypes validation

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <[email protected]>
Added missing Japanese translations for URL loader functionality:
- gui.urlLoader.loadError: Error message when URL loading fails
- gui.urlLoader.invalidUrl: Error message for invalid URLs
- gui.urlLoader.urlPrompt: Prompt message for URL input

Added to both ja.js and ja-Hira.js localization files.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <[email protected]>
Fixed URL loader implementation to match project-fetcher-hoc.jsx pattern:
- Use onFetchedProjectData instead of direct VM loading
- Set projectId in Redux state before loading
- Use proper Redux action dispatching for error handling
- Remove loadingState/success parameters from onLoadingFinished
- Add missing PropTypes for new functions

This prevents RubyTab errors and Redux dispatch issues.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <[email protected]>
Fixed Redux dispatch error by using onLoadedProject instead of
onFetchedProjectData. The LOADING_VM_FILE_UPLOAD state requires
onLoadedProject action which properly handles the state transition.

Changes:
- Import onLoadedProject instead of onFetchedProjectData
- Load project directly to VM like sb-file-uploader-hoc.jsx
- Use onLoadedProject(loadingState, canSave=true, success=true)
- Updated PropTypes and mapDispatchToProps

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <[email protected]>
Fixed Redux dispatch error by ensuring onLoadedProject always
returns a valid action object. The default case now returns
RETURN_TO_SHOWING action instead of undefined.

This resolves the 'Cannot read properties of undefined (reading type)'
error that occurred when onLoadedProject was called with
SHOWING_WITH_ID state.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <[email protected]>
Removed all debug console.log statements from:
- url-loader-hoc.jsx: Constructor, handleStartSelectingUrlLoad, render
- menu-bar.jsx: handleClickLoadFromUrl method
- gui.jsx: Import and creation logs

Build successful and ready for production.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <[email protected]>
Change translate_getTranslate to return proper tuple format [code, order]
instead of just code string. This ensures consistency with other value
block generators and prevents Ruby code generation errors.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <[email protected]>
Replace prompt/confirm dialogs with proper modal UI for loading projects from URL.
The modal includes message, URL input field, and Open/Cancel buttons like the
block display modal.

Changes:
- Created URLLoaderModal component with proper styling
- Updated URLLoaderHOC to use modal instead of prompt()
- Added modal state management to Redux modals
- Integrated modal into GUI component
- Added missing internationalization messages
- Fixed CSS color variables to use motion-primary theme

The modal provides better user experience with proper input validation,
placeholder text, and consistent UI design.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <[email protected]>
Fixed "this.props.openUrlLoaderModal is not a function" error by adding
the missing openUrlLoaderModal and closeUrlLoaderModal imports and
dispatch functions to the URLLoaderHOC's mapDispatchToProps.

The HOC wasn't importing the modal action creators from the modals reducer,
so the props weren't being passed through the component chain properly.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <[email protected]>
Instead of showing browser alert() for invalid URLs, now displays
validation error messages within the modal itself:

- Added error state to URLLoaderModal component
- Error message displays below input field with red styling
- Modal stays open when validation fails, closes when valid
- Updated URLLoaderHOC to pass validation errors via callback
- Added CSS styling for error states and messages
- Fixed lint errors (arrow-parens, duplicate keys)

The modal now provides better user experience by keeping context
and allowing users to correct their input without reopening the modal.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <[email protected]>
Improved UI by removing redundant example URL from prompt messages:

1. Updated prompt messages to remove example URL since it's already
   shown in the input field placeholder:
   - URLLoaderModal component defaultMessage
   - Japanese locale (ja.js)
   - Japanese Hiragana locale (ja-Hira.js)

2. Removed unused urlPrompt message from URLLoaderHOC since the
   prompt is now only used in the modal component

This makes the UI cleaner and avoids duplication between the prompt
text and the placeholder text in the input field.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <[email protected]>
Moved the "Load from URL" menu item to appear after the download
section in the File menu for better logical grouping of load/save
operations.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <[email protected]>
@takaokouji takaokouji merged commit 6339bbc into develop Sep 18, 2025
2 checks passed
@takaokouji takaokouji deleted the feature/load-from-url-222 branch September 18, 2025 14:25
github-actions bot pushed a commit that referenced this pull request Sep 18, 2025
…from-url-222

feat: add Load from URL menu item to File menu
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.

Open the Scratch project from menu.
1 participant