mirror of
https://github.com/arduino/arduino-ide.git
synced 2025-11-17 22:29:27 +00:00
Show 'progress' indicator during verify/upload.
Closes #575 Closes #1175 Signed-off-by: Akos Kitta <a.kitta@arduino.cc>
This commit is contained in:
@@ -1,7 +1,6 @@
|
||||
import { ApplicationError } from '@theia/core/lib/common/application-error';
|
||||
import type { Location } from '@theia/core/shared/vscode-languageserver-protocol';
|
||||
import type {
|
||||
Board,
|
||||
BoardUserField,
|
||||
Port,
|
||||
} from '../../common/protocol/boards-service';
|
||||
@@ -60,46 +59,39 @@ export namespace CoreError {
|
||||
export const CoreServicePath = '/services/core-service';
|
||||
export const CoreService = Symbol('CoreService');
|
||||
export interface CoreService {
|
||||
compile(
|
||||
options: CoreService.Compile.Options &
|
||||
Readonly<{
|
||||
exportBinaries?: boolean;
|
||||
compilerWarnings?: CompilerWarnings;
|
||||
}>
|
||||
): Promise<void>;
|
||||
upload(options: CoreService.Upload.Options): Promise<void>;
|
||||
uploadUsingProgrammer(options: CoreService.Upload.Options): Promise<void>;
|
||||
burnBootloader(options: CoreService.Bootloader.Options): Promise<void>;
|
||||
compile(options: CoreService.Options.Compile): Promise<void>;
|
||||
upload(options: CoreService.Options.Upload): Promise<void>;
|
||||
burnBootloader(options: CoreService.Options.Bootloader): Promise<void>;
|
||||
}
|
||||
|
||||
export namespace CoreService {
|
||||
export namespace Compile {
|
||||
export interface Options {
|
||||
export namespace Options {
|
||||
export interface Base {
|
||||
readonly fqbn?: string | undefined;
|
||||
readonly verbose: boolean; // TODO: (API) why not optional with a default false?
|
||||
readonly progressId?: string;
|
||||
}
|
||||
export interface SketchBased {
|
||||
readonly sketch: Sketch;
|
||||
readonly board?: Board;
|
||||
readonly optimizeForDebug: boolean;
|
||||
readonly verbose: boolean;
|
||||
readonly sourceOverride: Record<string, string>;
|
||||
}
|
||||
}
|
||||
|
||||
export namespace Upload {
|
||||
export interface Options extends Omit<Compile.Options, 'verbose'> {
|
||||
export interface BoardBased {
|
||||
readonly port?: Port;
|
||||
readonly programmer?: Programmer | undefined;
|
||||
readonly verify: boolean;
|
||||
/**
|
||||
* For the _Verify after upload_ setting.
|
||||
*/
|
||||
readonly verify: boolean; // TODO: (API) why not optional with false as the default value?
|
||||
}
|
||||
export interface Compile extends Base, SketchBased {
|
||||
readonly optimizeForDebug: boolean; // TODO: (API) make this optional
|
||||
readonly sourceOverride: Record<string, string>; // TODO: (API) make this optional
|
||||
readonly exportBinaries?: boolean;
|
||||
readonly compilerWarnings?: CompilerWarnings;
|
||||
}
|
||||
export interface Upload extends Base, SketchBased, BoardBased {
|
||||
readonly userFields: BoardUserField[];
|
||||
readonly verbose: { compile: boolean; upload: boolean };
|
||||
}
|
||||
}
|
||||
|
||||
export namespace Bootloader {
|
||||
export interface Options {
|
||||
readonly board?: Board;
|
||||
readonly port?: Port;
|
||||
readonly programmer?: Programmer | undefined;
|
||||
readonly verbose: boolean;
|
||||
readonly verify: boolean;
|
||||
readonly usingProgrammer?: boolean;
|
||||
}
|
||||
export interface Bootloader extends Base, BoardBased {}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,6 @@
|
||||
import * as semver from 'semver';
|
||||
import type { Progress } from '@theia/core/lib/common/message-service-protocol';
|
||||
import {
|
||||
CancellationToken,
|
||||
CancellationTokenSource,
|
||||
} from '@theia/core/lib/common/cancellation';
|
||||
import { naturalCompare } from './../utils';
|
||||
import { ExecuteWithProgress } from './progressible';
|
||||
import { naturalCompare } from '../utils';
|
||||
import type { ArduinoComponent } from './arduino-component';
|
||||
import type { MessageService } from '@theia/core/lib/common/message-service';
|
||||
import type { ResponseServiceClient } from './response-service';
|
||||
@@ -32,7 +28,7 @@ export namespace Installable {
|
||||
/**
|
||||
* Most recent version comes first, then the previous versions. (`1.8.1`, `1.6.3`, `1.6.2`, `1.6.1` and so on.)
|
||||
*/
|
||||
export const COMPARATOR = (left: Version, right: Version) => {
|
||||
export const COMPARATOR = (left: Version, right: Version): number => {
|
||||
if (semver.valid(left) && semver.valid(right)) {
|
||||
return semver.compare(left, right);
|
||||
}
|
||||
@@ -50,7 +46,7 @@ export namespace Installable {
|
||||
version: Installable.Version;
|
||||
}): Promise<void> {
|
||||
const { item, version } = options;
|
||||
return doWithProgress({
|
||||
return ExecuteWithProgress.doWithProgress({
|
||||
...options,
|
||||
progressText: `Processing ${item.name}:${version}`,
|
||||
run: ({ progressId }) =>
|
||||
@@ -71,7 +67,7 @@ export namespace Installable {
|
||||
item: T;
|
||||
}): Promise<void> {
|
||||
const { item } = options;
|
||||
return doWithProgress({
|
||||
return ExecuteWithProgress.doWithProgress({
|
||||
...options,
|
||||
progressText: `Processing ${item.name}${
|
||||
item.installedVersion ? `:${item.installedVersion}` : ''
|
||||
@@ -83,51 +79,4 @@ export namespace Installable {
|
||||
}),
|
||||
});
|
||||
}
|
||||
|
||||
export async function doWithProgress(options: {
|
||||
run: ({ progressId }: { progressId: string }) => Promise<void>;
|
||||
messageService: MessageService;
|
||||
responseService: ResponseServiceClient;
|
||||
progressText: string;
|
||||
}): Promise<void> {
|
||||
return withProgress(
|
||||
options.progressText,
|
||||
options.messageService,
|
||||
async (progress, _) => {
|
||||
const progressId = progress.id;
|
||||
const toDispose = options.responseService.onProgressDidChange(
|
||||
(progressMessage) => {
|
||||
if (progressId === progressMessage.progressId) {
|
||||
const { message, work } = progressMessage;
|
||||
progress.report({ message, work });
|
||||
}
|
||||
}
|
||||
);
|
||||
try {
|
||||
options.responseService.clearOutput();
|
||||
await options.run({ progressId });
|
||||
} finally {
|
||||
toDispose.dispose();
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
async function withProgress(
|
||||
text: string,
|
||||
messageService: MessageService,
|
||||
cb: (progress: Progress, token: CancellationToken) => Promise<void>
|
||||
): Promise<void> {
|
||||
const cancellationSource = new CancellationTokenSource();
|
||||
const { token } = cancellationSource;
|
||||
const progress = await messageService.showProgress(
|
||||
{ text, options: { cancelable: false } },
|
||||
() => cancellationSource.cancel()
|
||||
);
|
||||
try {
|
||||
await cb(progress, token);
|
||||
} finally {
|
||||
progress.cancel();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
60
arduino-ide-extension/src/common/protocol/progressible.ts
Normal file
60
arduino-ide-extension/src/common/protocol/progressible.ts
Normal file
@@ -0,0 +1,60 @@
|
||||
import type { CancellationToken } from '@theia/core/lib/common/cancellation';
|
||||
import { CancellationTokenSource } from '@theia/core/lib/common/cancellation';
|
||||
import type { MessageService } from '@theia/core/lib/common/message-service';
|
||||
import type { Progress } from '@theia/core/lib/common/message-service-protocol';
|
||||
import type { ResponseServiceClient } from './response-service';
|
||||
|
||||
export namespace ExecuteWithProgress {
|
||||
export async function doWithProgress<T>(options: {
|
||||
run: ({ progressId }: { progressId: string }) => Promise<T>;
|
||||
messageService: MessageService;
|
||||
responseService: ResponseServiceClient;
|
||||
progressText: string;
|
||||
keepOutput?: boolean;
|
||||
}): Promise<T> {
|
||||
return withProgress(
|
||||
options.progressText,
|
||||
options.messageService,
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
async (progress, _token) => {
|
||||
const progressId = progress.id;
|
||||
const toDispose = options.responseService.onProgressDidChange(
|
||||
(progressMessage) => {
|
||||
if (progressId === progressMessage.progressId) {
|
||||
const { message, work } = progressMessage;
|
||||
progress.report({ message, work });
|
||||
}
|
||||
}
|
||||
);
|
||||
try {
|
||||
if (!options.keepOutput) {
|
||||
options.responseService.clearOutput();
|
||||
}
|
||||
const result = await options.run({ progressId });
|
||||
return result;
|
||||
} finally {
|
||||
toDispose.dispose();
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
async function withProgress<T>(
|
||||
text: string,
|
||||
messageService: MessageService,
|
||||
cb: (progress: Progress, token: CancellationToken) => Promise<T>
|
||||
): Promise<T> {
|
||||
const cancellationSource = new CancellationTokenSource();
|
||||
const { token } = cancellationSource;
|
||||
const progress = await messageService.showProgress(
|
||||
{ text, options: { cancelable: false } },
|
||||
() => cancellationSource.cancel()
|
||||
);
|
||||
try {
|
||||
const result = await cb(progress, token);
|
||||
return result;
|
||||
} finally {
|
||||
progress.cancel();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -46,5 +46,5 @@ export interface ResponseService {
|
||||
export const ResponseServiceClient = Symbol('ResponseServiceClient');
|
||||
export interface ResponseServiceClient extends ResponseService {
|
||||
onProgressDidChange: Event<ProgressMessage>;
|
||||
clearOutput: () => void;
|
||||
clearOutput: () => void; // TODO: this should not belong here.
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user