Skip to content

Commit

Permalink
Switch Editor Modes When Changing Between Py/TS in File Explorer (#9651)
Browse files Browse the repository at this point in the history
With this change, when a user selects main.py (or any other python file) while in typescript mode, the editor will fully switch to python mode, which means any updated javascript will be translated into python before the file switch occurs, preventing code loss. The same will also happen in reverse when selecting a typescript file while in python mode. This behavior aligns with what happens when you click on main.blocks (it will switch to the blocks editor).
  • Loading branch information
thsparks authored Aug 28, 2023
1 parent 0053c5f commit 2353dc4
Showing 1 changed file with 39 additions and 7 deletions.
46 changes: 39 additions & 7 deletions webapp/src/app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -599,9 +599,10 @@ export class ProjectView
}

// switch
if (this.isBlocksActive()) {
const header = this.state.header;
if (this.isBlocksActive() || header.editor == pxt.BLOCKS_PROJECT_NAME) {
this.blocksEditor.openPython();
} else if (this.isJavaScriptActive()) {
} else if (this.isJavaScriptActive() || header.editor == pxt.JAVASCRIPT_PROJECT_NAME) {
this.openPythonAsync();
} else {
// make sure there's .py file
Expand Down Expand Up @@ -809,14 +810,15 @@ export class ProjectView
private convertTypeScriptToPythonAsync() {
const snap = this.editor.snapshotState();
const fromLanguage = this.isBlocksActive() ? "blocks" : "ts";
const fromText = this.editorFile.content;
const mainFileName = this.isBlocksActive() ? pxt.MAIN_BLOCKS : pxt.MAIN_TS;
const mainPkg = pkg.mainEditorPkg();
const fromText = mainPkg.files[mainFileName]?.content ?? "";

let convertPromise: Promise<void>;

const cached = mainPkg.getCachedTranspile(fromLanguage, fromText, "py");
if (cached) {
convertPromise = this.saveVirtualFileAsync(pxt.PYTHON_PROJECT_NAME, cached, true);
convertPromise = this.saveVirtualMainFileAsync(pxt.PYTHON_PROJECT_NAME, cached, true);
}
else {
convertPromise = this.saveTypeScriptAsync(false)
Expand All @@ -825,7 +827,7 @@ export class ProjectView
if (cres && cres.success) {
const mainpy = cres.outfiles[pxt.MAIN_PY];
mainPkg.cacheTranspile(fromLanguage, fromText, "py", mainpy);
return this.saveVirtualFileAsync(pxt.PYTHON_PROJECT_NAME, mainpy, true);
return this.saveVirtualMainFileAsync(pxt.PYTHON_PROJECT_NAME, mainpy, true);
} else {
const e = new Error("Failed to convert to Python.")
pxt.reportException(e);
Expand Down Expand Up @@ -1283,10 +1285,20 @@ export class ProjectView
setSideFile(fn: pkg.File, line?: number) {
let fileName = fn.name;
let currFile = this.state.currFile.name;

const header = this.state.header;
if (fileName != currFile && pxt.editor.isBlocks(fn)) {
// Going from ts -> blocks
// Going from ts/py -> blocks
pxt.tickEvent("sidebar.showBlocks");
this.openBlocks();
} else if (header.editor != pxt.PYTHON_PROJECT_NAME && fileName.endsWith(".py")) {
// Going from non-py -> py
pxt.tickEvent("sidebar.showPython");
this.openPython();
} else if (header.editor != pxt.JAVASCRIPT_PROJECT_NAME && fileName.endsWith(".ts")) {
// Going from non-ts -> ts
pxt.tickEvent("sidebar.showTypescript");
this.openJavaScript();
} else {
if (this.isTextEditor() || this.isPxtJsonEditor()) {
this.textEditor.giveFocusOnLoading = false
Expand Down Expand Up @@ -2985,10 +2997,19 @@ export class ProjectView
}

private saveVirtualFileAsync(prj: string, src: string, open: boolean): Promise<void> {
const fileName = this.editorFile.getVirtualFileName(prj);
return this.saveVirtualFileAsyncInternal(prj, src, open, fileName);
}

private saveVirtualMainFileAsync(prj: string, src: string, open: boolean): Promise<void> {
const fileName = this.getMainFileName(prj);
return this.saveVirtualFileAsyncInternal(prj, src, open, fileName);
}

private saveVirtualFileAsyncInternal(prj: string, src: string, open: boolean, fileName: string): Promise<void> {
// language service does not like empty file
src = src || "\n";
const mainPkg = pkg.mainEditorPkg();
const fileName = this.editorFile.getVirtualFileName(prj);
Util.assert(fileName && fileName != this.editorFile.name);
return mainPkg.setContentAsync(fileName, src).then(() => {
if (open) {
Expand All @@ -2998,6 +3019,17 @@ export class ProjectView
});
}

private getMainFileName(prj: string): string {
switch (prj) {
case pxt.PYTHON_PROJECT_NAME: return pxt.MAIN_PY;
case pxt.JAVASCRIPT_PROJECT_NAME: return pxt.MAIN_TS;
case pxt.BLOCKS_PROJECT_NAME: return pxt.MAIN_BLOCKS;
default:
Util.assert(false, `Unrecognized project type ${prj}`);
return undefined;
}
}

saveTypeScriptAsync(open = false): Promise<void> {
const mainPkg = pkg.mainEditorPkg();
if (!this.editor || !this.state.currFile || this.editorFile.epkg != mainPkg || this.reload)
Expand Down

0 comments on commit 2353dc4

Please sign in to comment.