GH-421: Cleaned up the _Output_ channel UI.

- Merged the Arduino channels into one,
 - Removed the channel selector dropdown from the UI.

Closes arduino/arduino-pro-ide#421.

Signed-off-by: Akos Kitta <kittaakos@typefox.io>
This commit is contained in:
Akos Kitta 2021-02-08 17:01:17 +01:00 committed by Akos Kitta
parent 19613de1b4
commit 3e92567d52
10 changed files with 45 additions and 31 deletions

View File

@ -140,6 +140,8 @@ import { bindArduinoPreferences } from './arduino-preferences'
import { SettingsService, SettingsDialog, SettingsWidget, SettingsDialogProps } from './settings';
import { AddFile } from './contributions/add-file';
import { ArchiveSketch } from './contributions/archive-sketch';
import { OutputToolbarContribution as TheiaOutputToolbarContribution } from '@theia/output/lib/browser/output-toolbar-contribution';
import { OutputToolbarContribution } from './theia/output/output-toolbar-contribution';
const ElementQueries = require('css-element-queries/src/ElementQueries');
@ -313,6 +315,10 @@ export default new ContainerModule((bind, unbind, isBound, rebind) => {
bind(ShellLayoutRestorer).toSelf().inSingletonScope();
rebind(TheiaShellLayoutRestorer).toService(ShellLayoutRestorer);
// No dropdown for the _Output_ view.
bind(OutputToolbarContribution).toSelf().inSingletonScope();
rebind(TheiaOutputToolbarContribution).toService(OutputToolbarContribution);
bind(ArduinoDaemon).toDynamicValue(context => WebSocketConnectionProvider.createProxy(context.container, ArduinoDaemonPath)).inSingletonScope();
// File-system extension

View File

@ -53,7 +53,7 @@ export class BurnBootloader extends SketchContribution {
this.preferences.get('arduino.upload.verify'),
this.preferences.get('arduino.upload.verbose')
]);
this.outputChannelManager.getChannel('Arduino: bootloader').clear();
this.outputChannelManager.getChannel('Arduino').clear();
await this.coreService.burnBootloader({
fqbn,
programmer,

View File

@ -122,7 +122,7 @@ export class UploadSketch extends SketchContribution {
verify
};
}
this.outputChannelManager.getChannel('Arduino: upload').clear();
this.outputChannelManager.getChannel('Arduino').clear();
if (usingProgrammer) {
await this.coreService.uploadUsingProgrammer(options);
} else {

View File

@ -77,7 +77,7 @@ export class VerifySketch extends SketchContribution {
const { boardsConfig } = this.boardsServiceClientImpl;
const fqbn = await this.boardsDataStore.appendConfigToFqbn(boardsConfig.selectedBoard?.fqbn);
const verbose = this.preferences.get('arduino.compile.verbose');
this.outputChannelManager.getChannel('Arduino: compile').clear();
this.outputChannelManager.getChannel('Arduino').clear();
await this.coreService.compile({
sketchUri: uri,
fqbn,

View File

@ -13,16 +13,10 @@ export class OutputServiceImpl implements OutputService {
protected outputChannelManager: OutputChannelManager;
append(message: OutputMessage): void {
const { name, chunk } = message;
const channel = this.outputChannelManager.getChannel(`Arduino: ${name}`);
// Zen-mode: we do not reveal the output for daemon messages.
const show: Promise<any> = name === 'daemon'
// This will open and reveal the view but won't show it. You will see the toggle bottom panel on the status bar.
? this.outputContribution.openView({ activate: false, reveal: false })
// This will open, reveal but do not activate the Output view.
: Promise.resolve(channel.show({ preserveFocus: true }));
show.then(() => channel.append(chunk));
const { chunk } = message;
const channel = this.outputChannelManager.getChannel(`Arduino`);
channel.show({ preserveFocus: true });
channel.append(chunk);
}
}

View File

@ -0,0 +1,15 @@
import { injectable } from 'inversify';
import { ReactTabBarToolbarItem, TabBarToolbarItem, TabBarToolbarRegistry } from '@theia/core/lib/browser/shell/tab-bar-toolbar';
import { OutputToolbarContribution as TheiaOutputToolbarContribution } from '@theia/output/lib/browser/output-toolbar-contribution';
@injectable()
export class OutputToolbarContribution extends TheiaOutputToolbarContribution {
async registerToolbarItems(registry: TabBarToolbarRegistry): Promise<void> {
await super.registerToolbarItems(registry); // Why is it async?
// It's a hack. Currently, it's not possible to unregister a toolbar contribution via API.
((registry as any).items as Map<string, TabBarToolbarItem | ReactTabBarToolbarItem>).delete('channels');
(registry as any).fireOnDidChange();
}
}

View File

@ -1,5 +1,4 @@
export interface OutputMessage {
readonly name: string;
readonly chunk: string;
readonly severity?: 'error' | 'warning' | 'info'; // Currently not used!
}

View File

@ -271,7 +271,7 @@ export class BoardsServiceImpl implements BoardsService {
resp.on('data', (r: PlatformInstallResp) => {
const prog = r.getProgress();
if (prog && prog.getFile()) {
this.outputService.append({ name: 'board download', chunk: `downloading ${prog.getFile()}\n` });
this.outputService.append({ chunk: `downloading ${prog.getFile()}\n` });
}
});
await new Promise<void>((resolve, reject) => {
@ -302,7 +302,7 @@ export class BoardsServiceImpl implements BoardsService {
const resp = client.platformUninstall(req);
resp.on('data', (_: PlatformUninstallResp) => {
if (!logged) {
this.outputService.append({ name: 'board uninstall', chunk: `uninstalling ${item.id}\n` });
this.outputService.append({ chunk: `uninstalling ${item.id}\n` });
logged = true;
}
})

View File

@ -24,7 +24,7 @@ export class CoreServiceImpl implements CoreService {
protected readonly notificationService: NotificationServiceServer;
async compile(options: CoreService.Compile.Options & { exportBinaries: boolean }): Promise<void> {
this.outputService.append({ name: 'compile', chunk: 'Compile...\n' + JSON.stringify(options, null, 2) + '\n--------------------------\n' });
this.outputService.append({ chunk: 'Compile...\n' + JSON.stringify(options, null, 2) + '\n--------------------------\n' });
const { sketchUri, fqbn } = options;
const sketchFilePath = FileUri.fsPath(sketchUri);
const sketchpath = dirname(sketchFilePath);
@ -48,15 +48,15 @@ export class CoreServiceImpl implements CoreService {
try {
await new Promise<void>((resolve, reject) => {
result.on('data', (cr: CompileResp) => {
this.outputService.append({ name: 'compile', chunk: Buffer.from(cr.getOutStream_asU8()).toString() });
this.outputService.append({ name: 'compile', chunk: Buffer.from(cr.getErrStream_asU8()).toString() });
this.outputService.append({ chunk: Buffer.from(cr.getOutStream_asU8()).toString() });
this.outputService.append({ chunk: Buffer.from(cr.getErrStream_asU8()).toString() });
});
result.on('error', error => reject(error));
result.on('end', () => resolve());
});
this.outputService.append({ name: 'compile', chunk: '\n--------------------------\nCompilation complete.\n' });
this.outputService.append({ chunk: '\n--------------------------\nCompilation complete.\n' });
} catch (e) {
this.outputService.append({ name: 'compile', chunk: `Compilation error: ${e}\n`, severity: 'error' });
this.outputService.append({ chunk: `Compilation error: ${e}\n`, severity: 'error' });
throw e;
}
}
@ -77,7 +77,7 @@ export class CoreServiceImpl implements CoreService {
await this.compile(Object.assign(options, { exportBinaries: false }));
const chunk = firstToUpperCase(task) + '...\n';
this.outputService.append({ name: 'upload', chunk: chunk + JSON.stringify(options, null, 2) + '\n--------------------------\n' });
this.outputService.append({ chunk: chunk + JSON.stringify(options, null, 2) + '\n--------------------------\n' });
const { sketchUri, fqbn, port, programmer } = options;
const sketchFilePath = FileUri.fsPath(sketchUri);
const sketchpath = dirname(sketchFilePath);
@ -104,15 +104,15 @@ export class CoreServiceImpl implements CoreService {
try {
await new Promise<void>((resolve, reject) => {
result.on('data', (resp: UploadResp) => {
this.outputService.append({ name: task, chunk: Buffer.from(resp.getOutStream_asU8()).toString() });
this.outputService.append({ name: task, chunk: Buffer.from(resp.getErrStream_asU8()).toString() });
this.outputService.append({ chunk: Buffer.from(resp.getOutStream_asU8()).toString() });
this.outputService.append({ chunk: Buffer.from(resp.getErrStream_asU8()).toString() });
});
result.on('error', error => reject(error));
result.on('end', () => resolve());
});
this.outputService.append({ name: 'upload', chunk: '\n--------------------------\n' + firstToLowerCase(task) + ' complete.\n' });
this.outputService.append({ chunk: '\n--------------------------\n' + firstToLowerCase(task) + ' complete.\n' });
} catch (e) {
this.outputService.append({ name: 'upload', chunk: `${firstToUpperCase(task)} error: ${e}\n`, severity: 'error' });
this.outputService.append({ chunk: `${firstToUpperCase(task)} error: ${e}\n`, severity: 'error' });
throw e;
}
}
@ -138,14 +138,14 @@ export class CoreServiceImpl implements CoreService {
try {
await new Promise<void>((resolve, reject) => {
result.on('data', (resp: BurnBootloaderResp) => {
this.outputService.append({ name: 'bootloader', chunk: Buffer.from(resp.getOutStream_asU8()).toString() });
this.outputService.append({ name: 'bootloader', chunk: Buffer.from(resp.getErrStream_asU8()).toString() });
this.outputService.append({ chunk: Buffer.from(resp.getOutStream_asU8()).toString() });
this.outputService.append({ chunk: Buffer.from(resp.getErrStream_asU8()).toString() });
});
result.on('error', error => reject(error));
result.on('end', () => resolve());
});
} catch (e) {
this.outputService.append({ name: 'bootloader', chunk: `Error while burning the bootloader: ${e}\n`, severity: 'error' });
this.outputService.append({ chunk: `Error while burning the bootloader: ${e}\n`, severity: 'error' });
throw e;
}
}

View File

@ -177,7 +177,7 @@ export class LibraryServiceImpl implements LibraryService {
resp.on('data', (r: LibraryInstallResp) => {
const prog = r.getProgress();
if (prog) {
this.outputService.append({ name: 'library', chunk: `downloading ${prog.getFile()}: ${prog.getCompleted()}%\n` });
this.outputService.append({ chunk: `downloading ${prog.getFile()}: ${prog.getCompleted()}%\n` });
}
});
await new Promise<void>((resolve, reject) => {
@ -209,7 +209,7 @@ export class LibraryServiceImpl implements LibraryService {
const resp = client.libraryUninstall(req);
resp.on('data', (_: LibraryUninstallResp) => {
if (!logged) {
this.outputService.append({ name: 'library', chunk: `uninstalling ${item.name}:${item.installedVersion}%\n` });
this.outputService.append({ chunk: `uninstalling ${item.name}:${item.installedVersion}%\n` });
logged = true;
}
});