Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] start on electron file deploy #10183

Merged
merged 2 commits into from
Sep 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions localtypings/pxtarget.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -746,6 +746,7 @@ declare namespace ts.pxtc {
utf8?: boolean;
switches: CompileSwitches;
deployDrives?: string; // partial name of drives where the .hex file should be copied
fileDeployPaths?: pxt.Map<string>; // Path IDs => path for file deployments
deployFileMarker?: string;
shortPointers?: boolean; // set to true for 16 bit pointers
flashCodeAlign?: number; // defaults to 1k
Expand Down
9 changes: 9 additions & 0 deletions localtypings/pxtelectron.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ declare namespace pxt.electron {
banned?: string[];
timeStamp?: string; // In the format of (new Date()).toISOString()
isDriveDeployBanned?: boolean;
isFileDeployBanned?: boolean;
}

export const enum UpdateStatus {
Expand Down Expand Up @@ -50,18 +51,26 @@ declare namespace pxt.electron {
configData?: any[];
}

// Request to deploy files to a specified location
export interface FileDeployRequest {
location: string; // id for location to attempt to deploy to
files: pxt.Map<string>; // Files to write, key is filename in subpath, value is b64 file content
}

// The object that gets injected into the window
export interface PxtElectron {
onTelemetry: (handler: (ev: TelemetryEvent) => void) => void; // Registers a handler to invoke when the app shell requests a telemetry event to be sent to AI.
onUpdateInstalled: (handler: () => void) => void; // Registers a handler to invoke when the app shell notifies that an update was installed.
onUpdateStatus: (handler: (st: UpdateStatus) => void) => void; // Registers a handler to invoke when the app shell replies with the current update status.
onCriticalUpdateFailed: (handler: () => void) => void; // Registers a handler to invoke when the app shell notifies us that a critical update has failed.
onDriveDeployResult: (handler: (isSuccess: boolean) => void) => void; // Registers a handler to invoke when the app shell replies with the result of the last drive deploy attempt.
onFileDeployResult: (handler: (isSuccess: boolean) => void) => void; // Registers a handler to invoke when the app shell replies with the result of the last file deploy attempt.

sendUpdateStatusCheck: () => void; // Asks the app shell about the current update status. The answer will come as a separate, asynchronous message.
sendQuit: () => void; // Asks the app shell to quit.
sendOpenDevTools: () => void; // Asks the app shell to open dev tools.
sendDriveDeploy: (compileResult: CompileResult) => void; // Asks the app to deploy the program to the device via USB file copy.
sendFileDeploy: (files: FileDeployRequest) => void // Asks the app to deploy the given files to a known folder.
versions: VersionInfo; // Various versions for telemetry base properties
}
}
1 change: 1 addition & 0 deletions pxtlib/cmds.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ namespace pxt.commands {
export let showProgramTooLargeErrorAsync: (variants: string[], confirmAsync: (options: any) => Promise<number>, saveOnly?: boolean) => Promise<RecompileOptions>;
export let saveProjectAsync: (project: pxt.cpp.HexFile) => Promise<void> = undefined;
export let electronDeployAsync: (r: ts.pxtc.CompileResult) => Promise<void> = undefined; // A pointer to the Electron deploy function, so that targets can access it in their extension.ts
export let electronFileDeployAsync: (deployRequest: pxt.electron.FileDeployRequest) => Promise<void> = undefined; // A pointer to the Electron file deploy function, so that targets can access it in their extension.ts
export let webUsbPairDialogAsync: (pairAsync: () => Promise<boolean>, confirmAsync: (options: any) => Promise<WebUSBPairResult>, implicitlyCalled?: boolean) => Promise<WebUSBPairResult> = undefined;
export let onTutorialCompleted: () => void = undefined;
export let workspaceLoadedAsync: () => Promise<void> = undefined;
Expand Down
1 change: 1 addition & 0 deletions webapp/src/cmds.ts
Original file line number Diff line number Diff line change
Expand Up @@ -480,6 +480,7 @@ export async function initAsync() {
log(`deploy: electron`);
pxt.commands.deployCoreAsync = electron.driveDeployAsync;
pxt.commands.electronDeployAsync = electron.driveDeployAsync;
pxt.commands.electronFileDeployAsync = electron.deployFilesAsync;
} else if (webUSBSupported) {
log(`deploy: webusb`);
pxt.commands.deployCoreAsync = hidDeployCoreAsync;
Expand Down
33 changes: 33 additions & 0 deletions webapp/src/electron.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,22 @@ export function initElectron(projectView: IProjectView): void {
}
});

pxtElectron.onFileDeployResult((isSuccess) => {
if (!fileDeployDeferred) {
pxt.tickEvent("electron.filedeploy.unknowndeployoperation");
return;
}

if (isSuccess) {
pxt.tickEvent("electron.filedeploy.success");
fileDeployDeferred.resolve();
} else {
pxt.tickEvent("electron.filedeploy.failure");
const err = new Error("electron file deploy failed");
fileDeployDeferred.reject(err);
}
})

const criticalUpdateFailedPromise = new Promise<void>((resolve) => {
pxtElectron.onCriticalUpdateFailed(() => {
pxt.tickEvent("electron.criticalupdate.failed");
Expand Down Expand Up @@ -130,6 +146,23 @@ export function driveDeployAsync(compileResult: pxtc.CompileResult): Promise<voi
});
}

let fileDeployDeferred: pxt.Util.DeferredPromise<void> = null;
export async function deployFilesAsync(deployRequest: pxt.electron.FileDeployRequest) {
if (!fileDeployDeferred) {
fileDeployDeferred = pxt.Util.defer<void>();
pxtElectron.sendFileDeploy(deployRequest);
} // else queue? see if needed.

try {
await fileDeployDeferred.promise
} catch (e) {
pxt.tickEvent("electron.filedeploy.failed");
throw e;
} finally {
fileDeployDeferred = null;
}
}

export function openDevTools(): void {
if (pxtElectron) {
pxtElectron.sendOpenDevTools();
Expand Down