Skip to content

Commit

Permalink
split projectCache off from projectInfo; those are the problematic th…
Browse files Browse the repository at this point in the history
…ings that don't quite work for opening a new file after it was created
  • Loading branch information
SillyFreak committed Jun 4, 2020
1 parent ee82ed5 commit 39e3af5
Show file tree
Hide file tree
Showing 3 changed files with 84 additions and 43 deletions.
31 changes: 21 additions & 10 deletions src/components/ide/Ide/Ide.js
Expand Up @@ -57,6 +57,7 @@ import initHedgehogSdk from '../../../sdk/hedgehog';
import PluginManager from '../../../sdk/PluginManager';

import useProjectInfo from './projectInfo';
import useProjectCache from './projectCache';
import usePersistentState from './persistentState';
import useLayoutModel from './layoutModel';

Expand Down Expand Up @@ -120,10 +121,13 @@ type Props = {|
|};

function Ide({ projectName }: Props) {
const [projectInfo, refreshProject] = useProjectInfo(projectName);
const projectInfo = useProjectInfo(projectName);
const [pluginsLoaded, setPluginsLoaded] = React.useState<boolean>(false);
const [runningTask, setRunningTask] = React.useState<Task | null>(null);

const [projectCache, refreshProject] = useProjectCache(
projectInfo && projectInfo.project,
);
const [state, dispatch] = usePersistentState(
projectInfo && projectInfo.projectUid,
);
Expand All @@ -148,7 +152,13 @@ function Ide({ projectName }: Props) {
// TODO this has a potential race condition with the initialization
// of executorRef.current.
React.useEffect(() => {
if (projectInfo === null || layoutModel === null || pluginsLoaded) return;
if (
projectInfo === null ||
projectCache === null ||
layoutModel === null ||
pluginsLoaded
)
return;

(async () => {
const pluginManager = new PluginManager(
Expand All @@ -161,10 +171,10 @@ function Ide({ projectName }: Props) {
pluginManagerRef.current = pluginManager;
setPluginsLoaded(true);
})();
}, [projectInfo, layoutModel, pluginsLoaded]);
}, [projectInfo, projectCache, layoutModel, pluginsLoaded]);

// load the project's simulator schema if it or the simulator changes
const simulatorXml = projectInfo && projectInfo.simulatorXml;
const simulatorXml = projectCache && projectCache.simulatorXml;

function refreshSimulatorFromSchema(
schema: SimulationSchema.SimulatorJson | null,
Expand Down Expand Up @@ -198,7 +208,7 @@ function Ide({ projectName }: Props) {

function getFile(path: string): FileReference {
// eslint-disable-next-line no-throw-literal
if (projectInfo === null) throw 'unreachable';
if (projectCache === null) throw 'unreachable';

const [_root, ...fragments] = path.split('/');

Expand All @@ -217,7 +227,7 @@ function Ide({ projectName }: Props) {
return child;
};

const file = fragments.reduce(reducer, projectInfo.files);
const file = fragments.reduce(reducer, projectCache.files);
return { path, file };
}

Expand Down Expand Up @@ -535,9 +545,9 @@ function Ide({ projectName }: Props) {
const path = file.path.split('/').slice(1, -1);

// eslint-disable-next-line no-throw-literal
if (projectInfo === null) throw 'unreachable';
if (projectCache === null) throw 'unreachable';

const root = projectInfo.files;
const root = projectCache.files;

// the project root is always a directory. assert and cast
// eslint-disable-next-line no-throw-literal
Expand Down Expand Up @@ -775,7 +785,8 @@ function Ide({ projectName }: Props) {
useStyles(FlexLayoutTheme);
const classes = useStylesMaterial();

if (projectInfo === null || state === null) return null;
if (projectInfo === null || projectCache === null || state === null)
return null;

const { fileTreeState, showMetadataFolder } = state;

Expand Down Expand Up @@ -920,7 +931,7 @@ function Ide({ projectName }: Props) {
<hr />
</div>
<FileTree
files={projectInfo.files}
files={projectCache.files}
{...fileTreeState}
filter={filter}
onFileAction={handleFileAction}
Expand Down
57 changes: 57 additions & 0 deletions src/components/ide/Ide/projectCache.js
@@ -0,0 +1,57 @@
// @flow

import * as React from 'react';

import filer, { fs } from 'filer';

import {
type FilerRecursiveStatInfo,
Project,
} from '../../../core/store/projects';

type ProjectCache = {|
files: FilerRecursiveStatInfo,
simulatorXml: string | null,
|};

export default function useProjectCache(
project: Project | null,
): [ProjectCache | null, () => void] {
const [state, setState] = React.useState<ProjectCache | null>(null);

function refreshProject() {
if (project === null) {
setState(null);
return;
}

async function loadSimulatorXml(): Promise<string | null> {
const absolutePath = project.resolve('./.metadata/simulator');
try {
const workspaceXml = await fs.promises.readFile(absolutePath, 'utf8');
if (workspaceXml === '') return null;
return workspaceXml;
} catch (ex) {
if (!(ex instanceof filer.Errors.ENOENT)) {
throw ex;
}
return null;
}
}

(async () => {
// load project from the file system
const files = await project.getFiles();
const simulatorXml = await loadSimulatorXml();

setState({ files, simulatorXml });
})();
}

// refresh project when projectName changes
React.useEffect(() => {
refreshProject();
}, [project]);

return [state, refreshProject];
}
39 changes: 6 additions & 33 deletions src/components/ide/Ide/projectInfo.js
Expand Up @@ -2,55 +2,28 @@

import * as React from 'react';

import filer, { fs } from 'filer';

import {
type FilerRecursiveStatInfo,
Project,
} from '../../../core/store/projects';
import { Project } from '../../../core/store/projects';

type ProjectInfo = {|
project: Project,
files: FilerRecursiveStatInfo,
projectUid: string,
simulatorXml: string | null,
|};

export default function useProjectInfo(
projectName: string,
): [ProjectInfo | null, () => void] {
): ProjectInfo | null {
const [state, setState] = React.useState<ProjectInfo | null>(null);

function refreshProject() {
async function loadSimulatorXml(project: Project): Promise<string | null> {
const absolutePath = project.resolve('./.metadata/simulator');
try {
const workspaceXml = await fs.promises.readFile(absolutePath, 'utf8');
if (workspaceXml === '') return null;
return workspaceXml;
} catch (ex) {
if (!(ex instanceof filer.Errors.ENOENT)) {
throw ex;
}
return null;
}
}

// refresh project when projectName changes
React.useEffect(() => {
(async () => {
// load project from the file system
const project = await Project.getProject(projectName);
const files = await project.getFiles();
const projectUid = await project.getUid();
const simulatorXml = await loadSimulatorXml(project);

setState({ project, files, projectUid, simulatorXml });
setState({ project, projectUid });
})();
}

// refresh project when projectName changes
React.useEffect(() => {
refreshProject();
}, [projectName]);

return [state, refreshProject];
return state;
}

0 comments on commit 39e3af5

Please sign in to comment.