diff --git a/client/modules/IDE/components/Editor.jsx b/client/modules/IDE/components/Editor.jsx index 1f1e5a184e..d3658d5290 100644 --- a/client/modules/IDE/components/Editor.jsx +++ b/client/modules/IDE/components/Editor.jsx @@ -44,6 +44,7 @@ import '../../../utils/htmlmixed'; import '../../../utils/p5-javascript'; import Timer from '../components/Timer'; import EditorAccessibility from '../components/EditorAccessibility'; +import { selectActiveFile } from '../selectors/files'; import AssetPreview from './AssetPreview'; import { metaKey } from '../../../utils/metaKey'; import './show-hint'; @@ -605,10 +606,7 @@ Editor.propTypes = { function mapStateToProps(state) { return { files: state.files, - file: - state.files.find((file) => file.isSelectedFile) || - state.files.find((file) => file.name === 'sketch.js') || - state.files.find((file) => file.name !== 'root'), + file: selectActiveFile(state), htmlFile: getHTMLFile(state.files), ide: state.ide, preferences: state.preferences, diff --git a/client/modules/IDE/components/Header/Nav.jsx b/client/modules/IDE/components/Header/Nav.jsx index 3750033aaa..37709945c4 100644 --- a/client/modules/IDE/components/Header/Nav.jsx +++ b/client/modules/IDE/components/Header/Nav.jsx @@ -14,6 +14,7 @@ import { setLanguage } from '../../actions/preferences'; import NavBar from '../../../../components/Nav/NavBar'; import CaretLeftIcon from '../../../../images/left-arrow.svg'; import LogoIcon from '../../../../images/p5js-logo-small.svg'; +import { selectRootFile } from '../../selectors/files'; import { selectSketchPath } from '../../selectors/project'; import { metaKey, metaKeyName } from '../../../../utils/metaKey'; import { useSketchActions } from '../../hooks'; @@ -102,17 +103,14 @@ const DashboardMenu = () => { ); }; -const ProjectMenu = (props) => { +const ProjectMenu = () => { const isUserOwner = useSelector(getIsUserOwner); const project = useSelector((state) => state.project); const user = useSelector((state) => state.user); const isUnsaved = !project?.id; - // TODO: use selectRootFile selector - const rootFile = useSelector( - (state) => state.files.filter((file) => file.name === 'root')[0] - ); + const rootFile = useSelector(selectRootFile); const cmRef = useContext(CmControllerContext); diff --git a/client/modules/IDE/components/Sidebar.jsx b/client/modules/IDE/components/Sidebar.jsx index 3e92fd8436..b28a2fba4d 100644 --- a/client/modules/IDE/components/Sidebar.jsx +++ b/client/modules/IDE/components/Sidebar.jsx @@ -9,6 +9,7 @@ import { openProjectOptions, openUploadFileModal } from '../actions/ide'; +import { selectRootFile } from '../selectors/files'; import { getAuthenticated, selectCanEditSketch } from '../selectors/users'; import ConnectedFileNode from './FileNode'; @@ -23,9 +24,7 @@ export default function SideBar() { const [isFocused, setIsFocused] = useState(false); - const files = useSelector((state) => state.files); - // TODO: use `selectRootFile` defined in another PR - const rootFile = files.filter((file) => file.name === 'root')[0]; + const rootFile = useSelector(selectRootFile); const projectOptionsVisible = useSelector( (state) => state.ide.projectOptionsVisible ); diff --git a/client/modules/IDE/pages/IDEView.jsx b/client/modules/IDE/pages/IDEView.jsx index 24ff858d99..ba5aa2cab2 100644 --- a/client/modules/IDE/pages/IDEView.jsx +++ b/client/modules/IDE/pages/IDEView.jsx @@ -33,6 +33,7 @@ import About from '../components/About'; import AddToCollectionList from '../components/AddToCollectionList'; import Feedback from '../components/Feedback'; import { CollectionSearchbar } from '../components/Searchbar'; +import { selectActiveFile } from '../selectors/files'; import { getIsUserOwner } from '../selectors/users'; import RootPage from '../../../components/RootPage'; @@ -548,10 +549,7 @@ IDEView.propTypes = { function mapStateToProps(state) { return { - selectedFile: - state.files.find((file) => file.isSelectedFile) || - state.files.find((file) => file.name === 'sketch.js') || - state.files.find((file) => file.name !== 'root'), + selectedFile: selectActiveFile(state), htmlFile: getHTMLFile(state.files), ide: state.ide, preferences: state.preferences, diff --git a/client/modules/IDE/pages/MobileIDEView.jsx b/client/modules/IDE/pages/MobileIDEView.jsx index d3cbc679b8..57762b2e24 100644 --- a/client/modules/IDE/pages/MobileIDEView.jsx +++ b/client/modules/IDE/pages/MobileIDEView.jsx @@ -41,6 +41,7 @@ import { remSize } from '../../../theme'; import ActionStrip from '../../../components/mobile/ActionStrip'; import useAsModal from '../../../components/useAsModal'; import Dropdown from '../../../components/Dropdown'; +import { selectActiveFile } from '../selectors/files'; import { getIsUserOwner } from '../selectors/users'; import { @@ -475,10 +476,7 @@ MobileIDEView.propTypes = { function mapStateToProps(state) { return { - selectedFile: - state.files.find((file) => file.isSelectedFile) || - state.files.find((file) => file.name === 'sketch.js') || - state.files.find((file) => file.name !== 'root'), + selectedFile: selectActiveFile(state), ide: state.ide, files: state.files, unsavedChanges: state.ide.unsavedChanges, diff --git a/client/modules/IDE/selectors/files.js b/client/modules/IDE/selectors/files.js new file mode 100644 index 0000000000..e2044b6d89 --- /dev/null +++ b/client/modules/IDE/selectors/files.js @@ -0,0 +1,15 @@ +import { createSelector } from 'reselect'; + +const selectFiles = (state) => state.files; + +export const selectRootFile = createSelector(selectFiles, (files) => + files.find((file) => file.name === 'root') +); + +export const selectActiveFile = createSelector( + selectFiles, + (files) => + files.find((file) => file.isSelectedFile) || + files.find((file) => file.name === 'sketch.js') || + files.find((file) => file.name !== 'root') +); diff --git a/client/modules/Mobile/MobileSketchView.jsx b/client/modules/Mobile/MobileSketchView.jsx index dc69550f6f..3cbb8ebb78 100644 --- a/client/modules/Mobile/MobileSketchView.jsx +++ b/client/modules/Mobile/MobileSketchView.jsx @@ -16,6 +16,7 @@ import { getHTMLFile } from '../IDE/reducers/files'; import { ExitIcon } from '../../common/icons'; import Footer from '../../components/mobile/Footer'; +import { selectActiveFile } from '../IDE/selectors/files'; import Content from './MobileViewContent'; const MobileSketchView = () => { @@ -23,12 +24,7 @@ const MobileSketchView = () => { const htmlFile = useSelector((state) => getHTMLFile(state.files)); const projectName = useSelector((state) => state.project.name); - const selectedFile = useSelector( - (state) => - state.files.find((file) => file.isSelectedFile) || - state.files.find((file) => file.name === 'sketch.js') || - state.files.find((file) => file.name !== 'root') - ); + const selectedFile = useSelector(selectActiveFile); const { setTextOutput,