+
+ );
}
AddToStudioModalPresentation.propTypes = {
diff --git a/src/redux/preview.js b/src/redux/preview.js
index 59bb2e565..94c54cf39 100644
--- a/src/redux/preview.js
+++ b/src/redux/preview.js
@@ -31,7 +31,8 @@ module.exports.getInitialState = () => ({
original: {},
parent: {},
projectStudios: [],
- curatedStudios: []
+ curatedStudios: [],
+ currentStudioIds: new Set()
});
module.exports.previewReducer = (state, action) => {
@@ -57,49 +58,23 @@ module.exports.previewReducer = (state, action) => {
parent: action.info
});
case 'SET_PROJECT_STUDIOS':
- // alter the returned object so that each studio object in the array
- // includes an additional property indicating that initially, this
- // studio includes the project. This is important because if it is a
- // studio open to the public, which the user does not curate or own,
- // and the user removes the project from that studio, we don't want
- // to forget about the studio completely!
+ // also initialize currentStudioIds, to keep track of which studios
+ // the project is currently in.
return Object.assign({}, state, {
- projectStudios: action.items.map(studio => (
- Object.assign({}, studio, {includesProject: true})
- ))
+ projectStudios: action.items,
+ currentStudioIds: new Set(action.items.map(studio => studio.id))
});
case 'SET_CURATED_STUDIOS':
+ return Object.assign({}, state, {curatedStudios: action.items});
+ case 'ADD_PROJECT_TO_STUDIO':
+ // add studio id to our studios-that-this-project-belongs-to set.
return Object.assign({}, state, {
- curatedStudios: action.items
+ currentStudioIds: new Set(state.currentStudioIds.add(action.studioId))
});
- case 'ADD_TO_PROJECT_STUDIOS':
- // add studio to our studios-that-this-project-belongs-to list.
- // Server response doesn't include full studio object, so just use a
- // minimal stub object.
+ case 'REMOVE_PROJECT_FROM_STUDIO':
+ state.currentStudioIds.delete(action.studioId);
return Object.assign({}, state, {
- projectStudios: state.projectStudios.some(studio => (
- studio.id === action.studioId
- )) ?
- state.projectStudios.map(studio => {
- if (studio.id === action.studioId) {
- studio.includesProject = true;
- }
- return Object.assign({}, studio);
- }) : state.projectStudios.concat(
- {
- id: action.studioId,
- includesProject: true
- }
- )
- });
- case 'REMOVE_FROM_PROJECT_STUDIOS':
- return Object.assign({}, state, {
- projectStudios: state.projectStudios.map(studio => {
- if (studio.id === action.studioId) {
- studio.includesProject = false;
- }
- return Object.assign({}, studio);
- })
+ currentStudioIds: new Set(state.currentStudioIds)
});
case 'SET_COMMENTS':
return Object.assign({}, state, {
@@ -174,13 +149,13 @@ module.exports.setCuratedStudios = items => ({
items: items
});
-module.exports.addToProjectStudios = studioId => ({
- type: 'ADD_TO_PROJECT_STUDIOS',
+module.exports.addProjectToStudio = studioId => ({
+ type: 'ADD_PROJECT_TO_STUDIO',
studioId: studioId
});
-module.exports.removeFromProjectStudios = studioId => ({
- type: 'REMOVE_FROM_PROJECT_STUDIOS',
+module.exports.removeProjectFromStudio = studioId => ({
+ type: 'REMOVE_PROJECT_FROM_STUDIO',
studioId: studioId
});
@@ -465,7 +440,7 @@ module.exports.addToStudio = (studioId, projectId, token) => (dispatch => {
return;
}
dispatch(module.exports.setStudioFetchStatus(studioId, module.exports.Status.FETCHED));
- dispatch(module.exports.addToProjectStudios(studioId));
+ dispatch(module.exports.addProjectToStudio(studioId));
});
});
@@ -485,7 +460,7 @@ module.exports.leaveStudio = (studioId, projectId, token) => (dispatch => {
return;
}
dispatch(module.exports.setStudioFetchStatus(studioId, module.exports.Status.FETCHED));
- dispatch(module.exports.removeFromProjectStudios(studioId));
+ dispatch(module.exports.removeProjectFromStudio(studioId));
});
});
diff --git a/src/views/preview/preview.jsx b/src/views/preview/preview.jsx
index 993de356e..673048141 100644
--- a/src/views/preview/preview.jsx
+++ b/src/views/preview/preview.jsx
@@ -395,34 +395,28 @@ Preview.defaultProps = {
};
// Build consolidated curatedStudios object from all studio info.
-// We add data to curatedStudios so it knows which of the studios the
-// project belongs to, and the status of requests to join/leave studios.
-function consolidateStudiosInfo (curatedStudios, projectStudios, studioRequests) {
- let consolidatedStudios = [];
- let projectStudiosFoundInCurated = {}; // temp, for time complexity
+// We add flags to indicate whether the project is currently in the studio,
+// and the status of requests to join/leave studios.
+function consolidateStudiosInfo (curatedStudios, projectStudios,
+ currentStudioIds, studioRequests) {
+ const consolidatedStudios = [];
- // copy curated studios, updating any that are also in other data structures
- curatedStudios.forEach(curatedStudio => {
- let studioCopy = Object.assign({}, curatedStudio, {includesProject: false});
- projectStudios.some(projectStudio => {
- if (curatedStudio.id === projectStudio.id) {
- studioCopy.includesProject = projectStudio.includesProject;
- projectStudiosFoundInCurated[projectStudio.id] = true;
- return true; // break out of the Array.some loop
- }
- });
- consolidatedStudios.push(studioCopy);
- });
- // if there are any other studios this project is in that are NOT in
- // the list of studios this user curates, like anyone-can-add-their-project
- // studios, add to front of list
projectStudios.forEach(projectStudio => {
- if (!(projectStudio.id in projectStudiosFoundInCurated)) {
- // no need to specify includesProject = true or false, because
- // that state is managed by redux actions.
- consolidatedStudios.unshift(Object.assign({}, projectStudio));
+ const includesProject = currentStudioIds.has(projectStudio.id);
+ const consolidatedStudio =
+ Object.assign({}, projectStudio, {includesProject: includesProject});
+ consolidatedStudios.push(consolidatedStudio);
+ });
+
+ // copy the curated studios that project is not in
+ curatedStudios.forEach(curatedStudio => {
+ if (!currentStudioIds.has(curatedStudio.id)) {
+ const consolidatedStudio =
+ Object.assign({}, curatedStudio, {includesProject: false});
+ consolidatedStudios.push(consolidatedStudio);
}
});
+
// set studio state to hasRequestOutstanding==true if it's being fetched,
// false if it's not
consolidatedStudios.forEach(consolidatedStudio => {
@@ -445,7 +439,8 @@ const mapStateToProps = state => ({
sessionStatus: state.session.status,
projectStudios: state.preview.projectStudios,
studios: consolidateStudiosInfo(state.preview.curatedStudios,
- state.preview.projectStudios, state.preview.status.studioRequests),
+ state.preview.projectStudios, state.preview.currentStudioIds,
+ state.preview.status.studioRequests),
user: state.session.session.user,
playerMode: state.scratchGui.mode.isPlayerOnly,
fullScreen: state.scratchGui.mode.isFullScreen