diff --git a/README.md b/README.md index aa38c0db9..c81a45db7 100644 --- a/README.md +++ b/README.md @@ -74,7 +74,7 @@ See [jest cli docs](https://facebook.github.io/jest/docs/en/cli.html#content) fo *NOTE: If you're a windows user, please run these scripts in Windows `cmd.exe` instead of Git Bash/MINGW64.* -Before running any test, make sure you have run `npm install` from this (scratch-gui) repository's top level. +Before running any tests, make sure you have run `npm install` from this (scratch-gui) repository's top level. #### Main testing command @@ -194,5 +194,60 @@ Further reading: [Stack Overflow](https://stackoverflow.com/questions/46602286/n You can publish the GUI to github.io so that others on the Internet can view it. [Read the wiki for a step-by-step guide.](https://github.com/LLK/scratch-gui/wiki/Publishing-to-GitHub-Pages) +## Understanding the project state machine + +Since so much code throughout scratch-gui depends on the state of the project, which goes through many different phases of loading, displaying and saving, we created a "finite state machine" to make it clear which state it is in at any moment. This is contained in the file src/reducers/project-state.js . + +It can be hard to understand the code in src/reducers/project-state.js . There are several types of data and functions used, which relate to each other: + +### Loading states + +These include state constant strings like: + +* `NOT_LOADED` (the default state), +* `ERROR`, +* `FETCHING_WITH_ID`, +* `LOADING_VM_WITH_ID`, +* `REMIXING`, +* `SHOWING_WITH_ID`, +* `SHOWING_WITHOUT_ID`, +* etc. + +### Transitions + +These are names for the action which causes a state change. Some examples are: + +* `START_FETCHING_NEW`, +* `DONE_FETCHING_WITH_ID`, +* `DONE_LOADING_VM_WITH_ID`, +* `SET_PROJECT_ID`, +* `START_AUTO_UPDATING`, + +### How transitions relate to loading states + +As this diagram of the project state machine shows, various transition actions can move us from one loading state to another: + +![Project state diagram](docs/project_state_diagram.svg) + +_Note: for clarity, the diagram above excludes states and transitions relating to error handling._ + +#### Example + +Here's an example of how states transition. + +Suppose a user clicks on a project, and the page starts to load with url https://scratch.mit.edu/projects/123456 . + +Here's what will happen in the project state machine: + +![Project state example](docs/project_state_example.png) + +1. When the app first mounts, the project state is `NOT_LOADED`. +2. The `SET_PROJECT_ID` redux action is dispatched (from src/lib/project-fetcher-hoc.jsx), with `projectId` set to `123456`. This transitions the state from `NOT_LOADED` to `FETCHING_WITH_ID`. +3. The `FETCHING_WITH_ID` state. In src/lib/project-fetcher-hoc.jsx, the `projectId` value `123456` is used to request the data for that project from the server. +4. When the server responds with the data, src/lib/project-fetcher-hoc.jsx dispatches the `DONE_FETCHING_WITH_ID` action, with `projectData` set. This transitions the state from `FETCHING_WITH_ID` to `LOADING_VM_WITH_ID`. +5. The `LOADING_VM_WITH_ID` state. In src/lib/vm-manager-hoc.jsx, we load the `projectData` into Scratch's virtual machine ("the vm"). +6. When loading is done, src/lib/vm-manager-hoc.jsx dispatches the `DONE_LOADING_VM_WITH_ID` action. This transitions the state from `LOADING_VM_WITH_ID` to `SHOWING_WITH_ID` +7. The `SHOWING_WITH_ID` state. Now the project appears normally and is playable and editable. + ## Donate We provide [Scratch](https://scratch.mit.edu) free of charge, and want to keep it that way! Please consider making a [donation](https://secure.donationpay.org/scratchfoundation/) to support our continued engineering, design, community, and resource development efforts. Donations of any size are appreciated. Thank you! diff --git a/docs/project_state_diagram.svg b/docs/project_state_diagram.svg new file mode 100644 index 000000000..e24382e5a --- /dev/null +++ b/docs/project_state_diagram.svg @@ -0,0 +1,3 @@ + + +
DONE_LOADING_VM_WITH_ID
DONE_LOADING_VM_WITH_ID
LOADING_VM_WITH_ID
loads projectData into vm
LOADING_VM_WITH_ID...
SET_PROJECT_ID
with projectId > 0
SET_PROJECT_ID...
SET_PROJECT_ID
with projectId == 0
SET_PROJECT_ID...
START_LOADING_VM_FILE_UPLOAD
START_LOADING_VM_FILE_UPLOAD
NOT_LOADED
NOT_LOADED
DONE_FETCHING_WITH_ID
sets projectData
DONE_FETCHING_WITH_ID...
FETCHING_WITH_ID
gets projectData from server
FETCHING_WITH_ID...
DONE_LOADING_VM_WITHOUT_ID
sets projectId = 0
[note: setting projectId here isn't necessary]
DONE_LOADING_VM_WITHOUT_ID...
LOADING_VM_NEW_DEFAULT
loads projectData into vm
LOADING_VM_NEW_DEFAULT...
DONE_FETCHING_DEFAULT
sets projectData
DONE_FETCHING_DEFAULT...
FETCHING_NEW_DEFAULT
gets default projectData
FETCHING_NEW_DEFAULT...
DONE_LOADING_VM_WITHOUT_ID
sets projectId = 0
DONE_LOADING_VM_WITHOUT_ID...
DONE_LOADING_VM_TO_SAVE
DONE_LOADING_VM_TO_SAVE
LOADING_VM_FILE_UPLOAD
loads project data into vm.
Note: projectData object is never set
LOADING_VM_FILE_UPLOAD...
SET_PROJECT_ID
with projectId == 0
or, START_FETCHING_NEW
SET_PROJECT_ID...
START_UPDATING_BEFORE_CREATING_COPY
START_UPDATING_BEFORE_CREATING_COPY
START_MANUAL_UPDATING
START_MANUAL_UPDATING
START_AUTO_UPDATING
START_AUTO_UPDATING
START_REMIXING
START_REMIXING
START_UPDATING_BEFORE_CREATING_NEW
START_UPDATING_BEFORE_CREATING_NEW
SET_PROJECT_ID
with projectId > 0
SET_PROJECT_ID...
START_LOADING_VM_FILE_UPLOAD
START_LOADING_VM_FILE_UPLOAD
SHOWING_WITH_ID
SHOWING_WITH_ID
DONE_CREATING_NEW
sets projectId
DONE_CREATING_NEW...
CREATING_NEW
sends project data to server,
gets project id

CREATING_NEW...
START_CREATING_NEW
START_CREATING_NEW
START_LOADING_VM_FILE_UPLOAD
START_LOADING_VM_FILE_UPLOAD
SET_PROJECT_ID
with projectId > 0
SET_PROJECT_ID...
START_FETCHING_NEW
START_FETCHING_NEW
SHOWING_WITHOUT_ID
SHOWING_WITHOUT_ID
DONE_REMIXING
sets projectId
DONE_REMIXING...
REMIXING
sends project data to server,
gets project id
REMIXING...
DONE_UPDATING
DONE_UPDATING
MANUAL_UPDATING
sends project data to server
MANUAL_UPDATING...
DONE_UPDATING
DONE_UPDATING
AUTO_UPDATING
sends project data to server
AUTO_UPDATING...
DONE_UPDATING_BEFORE_COPY
DONE_UPDATING_BEFORE_COPY
UPDATING_BEFORE_COPY
sends project data to server
UPDATING_BEFORE_COPY...
DONE_UPDATING_BEFORE_NEW
DONE_UPDATING_BEFORE_NEW
UPDATING_BEFORE_NEW
sends project data to server
UPDATING_BEFORE_NEW...
DONE_CREATING_COPY
sets projectId
DONE_CREATING_COPY...
CREATING_COPY
sends project data to server,
gets project id
CREATING_COPY...
\ No newline at end of file diff --git a/docs/project_state_example.png b/docs/project_state_example.png new file mode 100644 index 000000000..920c3087d Binary files /dev/null and b/docs/project_state_example.png differ