mirror of
https://github.com/arduino/arduino-ide.git
synced 2025-11-09 10:28:32 +00:00
Compare commits
1 Commits
remove-don
...
dependabot
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ebb2335b91 |
4
.github/workflows/build.yml
vendored
4
.github/workflows/build.yml
vendored
@@ -322,7 +322,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Install Node.js
|
- name: Install Node.js
|
||||||
if: runner.name != 'WINDOWS-SIGN-PC'
|
if: runner.name != 'WINDOWS-SIGN-PC'
|
||||||
uses: actions/setup-node@v4
|
uses: actions/setup-node@v6
|
||||||
with:
|
with:
|
||||||
node-version: ${{ env.NODE_VERSION }}
|
node-version: ${{ env.NODE_VERSION }}
|
||||||
registry-url: 'https://registry.npmjs.org'
|
registry-url: 'https://registry.npmjs.org'
|
||||||
@@ -456,7 +456,7 @@ jobs:
|
|||||||
name: ${{ env.STAGED_CHANNEL_FILE_ARTIFACT_PREFIX }}*
|
name: ${{ env.STAGED_CHANNEL_FILE_ARTIFACT_PREFIX }}*
|
||||||
|
|
||||||
- name: Install Node.js
|
- name: Install Node.js
|
||||||
uses: actions/setup-node@v4
|
uses: actions/setup-node@v6
|
||||||
with:
|
with:
|
||||||
node-version: ${{ env.NODE_VERSION }}
|
node-version: ${{ env.NODE_VERSION }}
|
||||||
registry-url: 'https://registry.npmjs.org'
|
registry-url: 'https://registry.npmjs.org'
|
||||||
|
|||||||
2
.github/workflows/check-i18n-task.yml
vendored
2
.github/workflows/check-i18n-task.yml
vendored
@@ -59,7 +59,7 @@ jobs:
|
|||||||
uses: actions/checkout@v5
|
uses: actions/checkout@v5
|
||||||
|
|
||||||
- name: Install Node.js 18.17
|
- name: Install Node.js 18.17
|
||||||
uses: actions/setup-node@v4
|
uses: actions/setup-node@v6
|
||||||
with:
|
with:
|
||||||
node-version: '18.17'
|
node-version: '18.17'
|
||||||
registry-url: 'https://registry.npmjs.org'
|
registry-url: 'https://registry.npmjs.org'
|
||||||
|
|||||||
2
.github/workflows/check-javascript.yml
vendored
2
.github/workflows/check-javascript.yml
vendored
@@ -68,7 +68,7 @@ jobs:
|
|||||||
uses: actions/checkout@v5
|
uses: actions/checkout@v5
|
||||||
|
|
||||||
- name: Setup Node.js
|
- name: Setup Node.js
|
||||||
uses: actions/setup-node@v4
|
uses: actions/setup-node@v6
|
||||||
with:
|
with:
|
||||||
cache: yarn
|
cache: yarn
|
||||||
node-version: ${{ env.NODE_VERSION }}
|
node-version: ${{ env.NODE_VERSION }}
|
||||||
|
|||||||
2
.github/workflows/check-yarn.yml
vendored
2
.github/workflows/check-yarn.yml
vendored
@@ -67,7 +67,7 @@ jobs:
|
|||||||
uses: actions/checkout@v5
|
uses: actions/checkout@v5
|
||||||
|
|
||||||
- name: Setup Node.js
|
- name: Setup Node.js
|
||||||
uses: actions/setup-node@v4
|
uses: actions/setup-node@v6
|
||||||
with:
|
with:
|
||||||
cache: yarn
|
cache: yarn
|
||||||
node-version: ${{ env.NODE_VERSION }}
|
node-version: ${{ env.NODE_VERSION }}
|
||||||
|
|||||||
2
.github/workflows/compose-full-changelog.yml
vendored
2
.github/workflows/compose-full-changelog.yml
vendored
@@ -24,7 +24,7 @@ jobs:
|
|||||||
uses: actions/checkout@v5
|
uses: actions/checkout@v5
|
||||||
|
|
||||||
- name: Install Node.js
|
- name: Install Node.js
|
||||||
uses: actions/setup-node@v4
|
uses: actions/setup-node@v6
|
||||||
with:
|
with:
|
||||||
node-version: ${{ env.NODE_VERSION }}
|
node-version: ${{ env.NODE_VERSION }}
|
||||||
registry-url: 'https://registry.npmjs.org'
|
registry-url: 'https://registry.npmjs.org'
|
||||||
|
|||||||
2
.github/workflows/i18n-nightly-push.yml
vendored
2
.github/workflows/i18n-nightly-push.yml
vendored
@@ -17,7 +17,7 @@ jobs:
|
|||||||
uses: actions/checkout@v5
|
uses: actions/checkout@v5
|
||||||
|
|
||||||
- name: Install Node.js 18.17
|
- name: Install Node.js 18.17
|
||||||
uses: actions/setup-node@v4
|
uses: actions/setup-node@v6
|
||||||
with:
|
with:
|
||||||
node-version: '18.17'
|
node-version: '18.17'
|
||||||
registry-url: 'https://registry.npmjs.org'
|
registry-url: 'https://registry.npmjs.org'
|
||||||
|
|||||||
2
.github/workflows/i18n-weekly-pull.yml
vendored
2
.github/workflows/i18n-weekly-pull.yml
vendored
@@ -17,7 +17,7 @@ jobs:
|
|||||||
uses: actions/checkout@v5
|
uses: actions/checkout@v5
|
||||||
|
|
||||||
- name: Install Node.js 18.17
|
- name: Install Node.js 18.17
|
||||||
uses: actions/setup-node@v4
|
uses: actions/setup-node@v6
|
||||||
with:
|
with:
|
||||||
node-version: '18.17'
|
node-version: '18.17'
|
||||||
registry-url: 'https://registry.npmjs.org'
|
registry-url: 'https://registry.npmjs.org'
|
||||||
|
|||||||
2
.github/workflows/test-javascript.yml
vendored
2
.github/workflows/test-javascript.yml
vendored
@@ -85,7 +85,7 @@ jobs:
|
|||||||
uses: actions/checkout@v5
|
uses: actions/checkout@v5
|
||||||
|
|
||||||
- name: Setup Node.js
|
- name: Setup Node.js
|
||||||
uses: actions/setup-node@v4
|
uses: actions/setup-node@v6
|
||||||
with:
|
with:
|
||||||
cache: yarn
|
cache: yarn
|
||||||
node-version: ${{ env.NODE_VERSION }}
|
node-version: ${{ env.NODE_VERSION }}
|
||||||
|
|||||||
2
.github/workflows/themes-weekly-pull.yml
vendored
2
.github/workflows/themes-weekly-pull.yml
vendored
@@ -19,7 +19,7 @@ jobs:
|
|||||||
uses: actions/checkout@v5
|
uses: actions/checkout@v5
|
||||||
|
|
||||||
- name: Install Node.js
|
- name: Install Node.js
|
||||||
uses: actions/setup-node@v4
|
uses: actions/setup-node@v6
|
||||||
with:
|
with:
|
||||||
node-version: ${{ env.NODE_VERSION }}
|
node-version: ${{ env.NODE_VERSION }}
|
||||||
registry-url: 'https://registry.npmjs.org'
|
registry-url: 'https://registry.npmjs.org'
|
||||||
|
|||||||
@@ -67,6 +67,7 @@
|
|||||||
"cross-fetch": "^3.1.5",
|
"cross-fetch": "^3.1.5",
|
||||||
"dateformat": "^3.0.3",
|
"dateformat": "^3.0.3",
|
||||||
"deepmerge": "^4.2.2",
|
"deepmerge": "^4.2.2",
|
||||||
|
"dompurify": "^2.4.7",
|
||||||
"drivelist": "^9.2.4",
|
"drivelist": "^9.2.4",
|
||||||
"electron-updater": "^4.6.5",
|
"electron-updater": "^4.6.5",
|
||||||
"fast-deep-equal": "^3.1.3",
|
"fast-deep-equal": "^3.1.3",
|
||||||
|
|||||||
@@ -368,6 +368,10 @@ import { DebugConfigurationWidget } from './theia/debug/debug-configuration-widg
|
|||||||
import { DebugConfigurationWidget as TheiaDebugConfigurationWidget } from '@theia/debug/lib/browser/view/debug-configuration-widget';
|
import { DebugConfigurationWidget as TheiaDebugConfigurationWidget } from '@theia/debug/lib/browser/view/debug-configuration-widget';
|
||||||
import { DebugToolBar } from '@theia/debug/lib/browser/view/debug-toolbar-widget';
|
import { DebugToolBar } from '@theia/debug/lib/browser/view/debug-toolbar-widget';
|
||||||
|
|
||||||
|
import {
|
||||||
|
VersionWelcomeDialog,
|
||||||
|
VersionWelcomeDialogProps,
|
||||||
|
} from './dialogs/version-welcome-dialog';
|
||||||
import { TestViewContribution as TheiaTestViewContribution } from '@theia/test/lib/browser/view/test-view-contribution';
|
import { TestViewContribution as TheiaTestViewContribution } from '@theia/test/lib/browser/view/test-view-contribution';
|
||||||
import { TestViewContribution } from './theia/test/test-view-contribution';
|
import { TestViewContribution } from './theia/test/test-view-contribution';
|
||||||
|
|
||||||
@@ -983,6 +987,11 @@ export default new ContainerModule((bind, unbind, isBound, rebind) => {
|
|||||||
title: 'IDEUpdater',
|
title: 'IDEUpdater',
|
||||||
});
|
});
|
||||||
|
|
||||||
|
bind(VersionWelcomeDialog).toSelf().inSingletonScope();
|
||||||
|
bind(VersionWelcomeDialogProps).toConstantValue({
|
||||||
|
title: 'VersionWelcomeDialog',
|
||||||
|
});
|
||||||
|
|
||||||
bind(UserFieldsDialog).toSelf().inSingletonScope();
|
bind(UserFieldsDialog).toSelf().inSingletonScope();
|
||||||
bind(UserFieldsDialogProps).toConstantValue({
|
bind(UserFieldsDialogProps).toConstantValue({
|
||||||
title: 'UserFields',
|
title: 'UserFields',
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import {
|
|||||||
} from '../../common/protocol/ide-updater';
|
} from '../../common/protocol/ide-updater';
|
||||||
import { IDEUpdaterDialog } from '../dialogs/ide-updater/ide-updater-dialog';
|
import { IDEUpdaterDialog } from '../dialogs/ide-updater/ide-updater-dialog';
|
||||||
import { Contribution } from './contribution';
|
import { Contribution } from './contribution';
|
||||||
|
import { VersionWelcomeDialog } from '../dialogs/version-welcome-dialog';
|
||||||
import { AppService } from '../app-service';
|
import { AppService } from '../app-service';
|
||||||
import { SemVer } from 'semver';
|
import { SemVer } from 'semver';
|
||||||
|
|
||||||
@@ -19,6 +20,9 @@ export class CheckForIDEUpdates extends Contribution {
|
|||||||
@inject(IDEUpdaterDialog)
|
@inject(IDEUpdaterDialog)
|
||||||
private readonly updaterDialog: IDEUpdaterDialog;
|
private readonly updaterDialog: IDEUpdaterDialog;
|
||||||
|
|
||||||
|
@inject(VersionWelcomeDialog)
|
||||||
|
private readonly versionWelcomeDialog: VersionWelcomeDialog;
|
||||||
|
|
||||||
@inject(LocalStorageService)
|
@inject(LocalStorageService)
|
||||||
private readonly localStorage: LocalStorageService;
|
private readonly localStorage: LocalStorageService;
|
||||||
|
|
||||||
@@ -55,8 +59,13 @@ export class CheckForIDEUpdates extends Contribution {
|
|||||||
return this.updater.checkForUpdates(true);
|
return this.updater.checkForUpdates(true);
|
||||||
})
|
})
|
||||||
.then(async (updateInfo) => {
|
.then(async (updateInfo) => {
|
||||||
if (!updateInfo) return;
|
if (!updateInfo) {
|
||||||
|
const isNewVersion = await this.isNewStableVersion();
|
||||||
|
if (isNewVersion) {
|
||||||
|
this.versionWelcomeDialog.open();
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
const versionToSkip = await this.localStorage.getData<string>(
|
const versionToSkip = await this.localStorage.getData<string>(
|
||||||
SKIP_IDE_VERSION
|
SKIP_IDE_VERSION
|
||||||
);
|
);
|
||||||
@@ -77,11 +86,6 @@ export class CheckForIDEUpdates extends Contribution {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* This value is set in localStorage but currently not used.
|
|
||||||
* We keep this logic running anyway for eventual future needs
|
|
||||||
* (eg. show a new version welcome dialog)
|
|
||||||
*/
|
|
||||||
private async setCurrentIDEVersion(): Promise<void> {
|
private async setCurrentIDEVersion(): Promise<void> {
|
||||||
try {
|
try {
|
||||||
const { appVersion } = await this.appService.info();
|
const { appVersion } = await this.appService.info();
|
||||||
@@ -91,4 +95,29 @@ export class CheckForIDEUpdates extends Contribution {
|
|||||||
// ignore invalid versions
|
// ignore invalid versions
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if user is running a new IDE version for the first time.
|
||||||
|
* @returns true if the current IDE version is greater than the last used version
|
||||||
|
* and both are non-prerelease versions.
|
||||||
|
*/
|
||||||
|
private async isNewStableVersion(): Promise<boolean> {
|
||||||
|
try {
|
||||||
|
const { appVersion } = await this.appService.info();
|
||||||
|
const prevVersion = await this.localStorage.getData<string>(
|
||||||
|
LAST_USED_IDE_VERSION
|
||||||
|
);
|
||||||
|
|
||||||
|
const prevSemVer = new SemVer(prevVersion ?? '');
|
||||||
|
const currSemVer = new SemVer(appVersion ?? '');
|
||||||
|
|
||||||
|
if (prevSemVer.prerelease.length || currSemVer.prerelease.length) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return currSemVer.compare(prevSemVer) === 1;
|
||||||
|
} catch (e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ import {
|
|||||||
} from '../../../common/protocol/ide-updater';
|
} from '../../../common/protocol/ide-updater';
|
||||||
import { LocalStorageService } from '@theia/core/lib/browser';
|
import { LocalStorageService } from '@theia/core/lib/browser';
|
||||||
import { WindowService } from '@theia/core/lib/browser/window/window-service';
|
import { WindowService } from '@theia/core/lib/browser/window/window-service';
|
||||||
|
import { sanitize } from 'dompurify';
|
||||||
|
|
||||||
@injectable()
|
@injectable()
|
||||||
export class IDEUpdaterDialogProps extends DialogProps {}
|
export class IDEUpdaterDialogProps extends DialogProps {}
|
||||||
@@ -165,6 +166,51 @@ export class IDEUpdaterDialog extends ReactDialog<UpdateInfo | undefined> {
|
|||||||
goToDownloadPageButton.focus();
|
goToDownloadPageButton.focus();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private appendDonateFooter() {
|
||||||
|
const footer = document.createElement('div');
|
||||||
|
footer.classList.add('ide-updater-dialog--footer');
|
||||||
|
const footerContent = document.createElement('div');
|
||||||
|
footerContent.classList.add('ide-updater-dialog--footer-content');
|
||||||
|
footer.appendChild(footerContent);
|
||||||
|
|
||||||
|
const footerLink = document.createElement('a');
|
||||||
|
footerLink.innerText = sanitize(
|
||||||
|
nls.localize('arduino/ide-updater/donateLinkText', 'donate to support us')
|
||||||
|
);
|
||||||
|
footerLink.classList.add('ide-updater-dialog--footer-link');
|
||||||
|
footerLink.onclick = () =>
|
||||||
|
this.openExternal('https://www.arduino.cc/en/donate');
|
||||||
|
|
||||||
|
const footerLinkIcon = document.createElement('span');
|
||||||
|
footerLinkIcon.title = nls.localize(
|
||||||
|
'arduino/ide-updater/donateLinkIconTitle',
|
||||||
|
'open donation page'
|
||||||
|
);
|
||||||
|
footerLinkIcon.classList.add('ide-updater-dialog--footer-link-icon');
|
||||||
|
footerLink.appendChild(footerLinkIcon);
|
||||||
|
|
||||||
|
const placeholderKey = '%%link%%';
|
||||||
|
const footerText = sanitize(
|
||||||
|
nls.localize(
|
||||||
|
'arduino/ide-updater/donateText',
|
||||||
|
'Open source is love, {0}',
|
||||||
|
placeholderKey
|
||||||
|
)
|
||||||
|
);
|
||||||
|
const placeholder = footerText.indexOf(placeholderKey);
|
||||||
|
if (placeholder !== -1) {
|
||||||
|
const parts = footerText.split(placeholderKey);
|
||||||
|
footerContent.appendChild(document.createTextNode(parts[0]));
|
||||||
|
footerContent.appendChild(footerLink);
|
||||||
|
footerContent.appendChild(document.createTextNode(parts[1]));
|
||||||
|
} else {
|
||||||
|
footerContent.appendChild(document.createTextNode(footerText));
|
||||||
|
footerContent.appendChild(footerLink);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.controlPanel.insertAdjacentElement('afterend', footer);
|
||||||
|
}
|
||||||
|
|
||||||
private openDownloadPage(): void {
|
private openDownloadPage(): void {
|
||||||
this.openExternal('https://www.arduino.cc/en/software');
|
this.openExternal('https://www.arduino.cc/en/software');
|
||||||
this.close();
|
this.close();
|
||||||
@@ -187,6 +233,7 @@ export class IDEUpdaterDialog extends ReactDialog<UpdateInfo | undefined> {
|
|||||||
downloadStarted: true,
|
downloadStarted: true,
|
||||||
});
|
});
|
||||||
this.clearButtons();
|
this.clearButtons();
|
||||||
|
this.appendDonateFooter();
|
||||||
this.updater.downloadUpdate();
|
this.updater.downloadUpdate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,107 @@
|
|||||||
|
import React from '@theia/core/shared/react';
|
||||||
|
import { inject, injectable } from '@theia/core/shared/inversify';
|
||||||
|
import { Message } from '@theia/core/shared/@phosphor/messaging';
|
||||||
|
import { ReactDialog } from '../theia/dialogs/dialogs';
|
||||||
|
import { nls } from '@theia/core';
|
||||||
|
import { DialogProps } from '@theia/core/lib/browser';
|
||||||
|
import { WindowService } from '@theia/core/lib/browser/window/window-service';
|
||||||
|
import { AppService } from '../app-service';
|
||||||
|
import { sanitize } from 'dompurify';
|
||||||
|
|
||||||
|
@injectable()
|
||||||
|
export class VersionWelcomeDialogProps extends DialogProps {}
|
||||||
|
|
||||||
|
@injectable()
|
||||||
|
export class VersionWelcomeDialog extends ReactDialog<void> {
|
||||||
|
@inject(AppService)
|
||||||
|
private readonly appService: AppService;
|
||||||
|
|
||||||
|
@inject(WindowService)
|
||||||
|
private readonly windowService: WindowService;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
@inject(VersionWelcomeDialogProps)
|
||||||
|
protected override readonly props: VersionWelcomeDialogProps
|
||||||
|
) {
|
||||||
|
super({
|
||||||
|
title: nls.localize(
|
||||||
|
'arduino/versionWelcome/title',
|
||||||
|
'Welcome to a new version of the Arduino IDE!'
|
||||||
|
),
|
||||||
|
});
|
||||||
|
this.node.id = 'version-welcome-dialog-container';
|
||||||
|
this.contentNode.classList.add('version-welcome-dialog');
|
||||||
|
}
|
||||||
|
|
||||||
|
protected render(): React.ReactNode {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<p>
|
||||||
|
{nls.localize(
|
||||||
|
'arduino/versionWelcome/donateMessage',
|
||||||
|
'Arduino is committed to keeping software free and open-source for everyone. Your donation helps us develop new features, improve libraries, and support millions of users worldwide.'
|
||||||
|
)}
|
||||||
|
</p>
|
||||||
|
<p className="bold">
|
||||||
|
{nls.localize(
|
||||||
|
'arduino/versionWelcome/donateMessage2',
|
||||||
|
'Please consider supporting our work on the free open source Arduino IDE.'
|
||||||
|
)}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
override get value(): void {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
private appendButtons(): void {
|
||||||
|
const cancelButton = this.createButton(
|
||||||
|
nls.localize('arduino/versionWelcome/cancelButton', 'Maybe later')
|
||||||
|
);
|
||||||
|
cancelButton.classList.add('secondary');
|
||||||
|
cancelButton.classList.add('cancel-button');
|
||||||
|
this.addAction(cancelButton, this.close.bind(this), 'click');
|
||||||
|
this.controlPanel.appendChild(cancelButton);
|
||||||
|
|
||||||
|
const donateButton = this.createButton(
|
||||||
|
nls.localize('arduino/versionWelcome/donateButton', 'Donate now')
|
||||||
|
);
|
||||||
|
this.addAction(donateButton, this.onDonateButtonClick.bind(this), 'click');
|
||||||
|
this.controlPanel.appendChild(donateButton);
|
||||||
|
donateButton.focus();
|
||||||
|
}
|
||||||
|
|
||||||
|
private onDonateButtonClick(): void {
|
||||||
|
this.openDonationPage();
|
||||||
|
this.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
private readonly openDonationPage = () => {
|
||||||
|
const url = 'https://www.arduino.cc/en/donate';
|
||||||
|
this.windowService.openNewWindow(url, { external: true });
|
||||||
|
};
|
||||||
|
|
||||||
|
private async updateTitleVersion(): Promise<void> {
|
||||||
|
const appInfo = await this.appService.info();
|
||||||
|
const { appVersion } = appInfo;
|
||||||
|
|
||||||
|
if (appVersion) {
|
||||||
|
this.titleNode.innerText = sanitize(
|
||||||
|
nls.localize(
|
||||||
|
'arduino/versionWelcome/titleWithVersion',
|
||||||
|
'Welcome to the new Arduino IDE {0}!',
|
||||||
|
appVersion
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override onAfterAttach(msg: Message): void {
|
||||||
|
this.update();
|
||||||
|
this.appendButtons();
|
||||||
|
this.updateTitleVersion();
|
||||||
|
super.onAfterAttach(msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -67,7 +67,3 @@ export function truncateLines(
|
|||||||
}
|
}
|
||||||
return [lines, charCount];
|
return [lines, charCount];
|
||||||
}
|
}
|
||||||
|
|
||||||
export function joinLines(lines: Line[]): string {
|
|
||||||
return lines.map((line: Line) => line.message).join('');
|
|
||||||
}
|
|
||||||
@@ -52,9 +52,6 @@ export namespace SerialMonitor {
|
|||||||
},
|
},
|
||||||
'vscode/output.contribution/clearOutput.label'
|
'vscode/output.contribution/clearOutput.label'
|
||||||
);
|
);
|
||||||
export const COPY_OUTPUT = {
|
|
||||||
id: 'serial-monitor-copy-output',
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -152,12 +149,6 @@ export class MonitorViewContribution
|
|||||||
'Clear Output'
|
'Clear Output'
|
||||||
),
|
),
|
||||||
});
|
});
|
||||||
registry.registerItem({
|
|
||||||
id: SerialMonitor.Commands.COPY_OUTPUT.id,
|
|
||||||
command: SerialMonitor.Commands.COPY_OUTPUT.id,
|
|
||||||
icon: codicon('copy'),
|
|
||||||
tooltip: nls.localize('arduino/serial/copyOutput', 'Copy Output'),
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override registerCommands(commands: CommandRegistry): void {
|
override registerCommands(commands: CommandRegistry): void {
|
||||||
@@ -170,15 +161,6 @@ export class MonitorViewContribution
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
commands.registerCommand(SerialMonitor.Commands.COPY_OUTPUT, {
|
|
||||||
isEnabled: (widget) => widget instanceof MonitorWidget,
|
|
||||||
isVisible: (widget) => widget instanceof MonitorWidget,
|
|
||||||
execute: (widget) => {
|
|
||||||
if (widget instanceof MonitorWidget) {
|
|
||||||
widget.copyOutput();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
});
|
|
||||||
if (this.toggleCommand) {
|
if (this.toggleCommand) {
|
||||||
commands.registerCommand(this.toggleCommand, {
|
commands.registerCommand(this.toggleCommand, {
|
||||||
execute: () => this.toggle(),
|
execute: () => this.toggle(),
|
||||||
|
|||||||
@@ -28,7 +28,6 @@ import {
|
|||||||
import { MonitorModel } from '../../monitor-model';
|
import { MonitorModel } from '../../monitor-model';
|
||||||
import { FrontendApplicationStateService } from '@theia/core/lib/browser/frontend-application-state';
|
import { FrontendApplicationStateService } from '@theia/core/lib/browser/frontend-application-state';
|
||||||
import { serialMonitorWidgetLabel } from '../../../common/nls';
|
import { serialMonitorWidgetLabel } from '../../../common/nls';
|
||||||
import { ClipboardService } from '@theia/core/lib/browser/clipboard-service';
|
|
||||||
|
|
||||||
@injectable()
|
@injectable()
|
||||||
export class MonitorWidget extends ReactWidget {
|
export class MonitorWidget extends ReactWidget {
|
||||||
@@ -48,7 +47,6 @@ export class MonitorWidget extends ReactWidget {
|
|||||||
*/
|
*/
|
||||||
protected closing = false;
|
protected closing = false;
|
||||||
protected readonly clearOutputEmitter = new Emitter<void>();
|
protected readonly clearOutputEmitter = new Emitter<void>();
|
||||||
protected readonly copyOutputEmitter = new Emitter<void>();
|
|
||||||
|
|
||||||
@inject(MonitorModel)
|
@inject(MonitorModel)
|
||||||
private readonly monitorModel: MonitorModel;
|
private readonly monitorModel: MonitorModel;
|
||||||
@@ -58,8 +56,6 @@ export class MonitorWidget extends ReactWidget {
|
|||||||
private readonly boardsServiceProvider: BoardsServiceProvider;
|
private readonly boardsServiceProvider: BoardsServiceProvider;
|
||||||
@inject(FrontendApplicationStateService)
|
@inject(FrontendApplicationStateService)
|
||||||
private readonly appStateService: FrontendApplicationStateService;
|
private readonly appStateService: FrontendApplicationStateService;
|
||||||
@inject(ClipboardService)
|
|
||||||
private readonly clipboardService: ClipboardService;
|
|
||||||
|
|
||||||
private readonly toDisposeOnReset: DisposableCollection;
|
private readonly toDisposeOnReset: DisposableCollection;
|
||||||
|
|
||||||
@@ -107,10 +103,6 @@ export class MonitorWidget extends ReactWidget {
|
|||||||
this.update();
|
this.update();
|
||||||
}
|
}
|
||||||
|
|
||||||
copyOutput(): void {
|
|
||||||
this.copyOutputEmitter.fire();
|
|
||||||
}
|
|
||||||
|
|
||||||
override dispose(): void {
|
override dispose(): void {
|
||||||
this.toDisposeOnReset.dispose();
|
this.toDisposeOnReset.dispose();
|
||||||
super.dispose();
|
super.dispose();
|
||||||
@@ -255,8 +247,6 @@ export class MonitorWidget extends ReactWidget {
|
|||||||
monitorModel={this.monitorModel}
|
monitorModel={this.monitorModel}
|
||||||
monitorManagerProxy={this.monitorManagerProxy}
|
monitorManagerProxy={this.monitorManagerProxy}
|
||||||
clearConsoleEvent={this.clearOutputEmitter.event}
|
clearConsoleEvent={this.clearOutputEmitter.event}
|
||||||
copyOutputEvent={this.copyOutputEmitter.event}
|
|
||||||
clipboardService={this.clipboardService}
|
|
||||||
height={Math.floor(this.widgetHeight - 50)}
|
height={Math.floor(this.widgetHeight - 50)}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -3,10 +3,9 @@ import { Event } from '@theia/core/lib/common/event';
|
|||||||
import { DisposableCollection } from '@theia/core/lib/common/disposable';
|
import { DisposableCollection } from '@theia/core/lib/common/disposable';
|
||||||
import { areEqual, FixedSizeList as List } from 'react-window';
|
import { areEqual, FixedSizeList as List } from 'react-window';
|
||||||
import dateFormat from 'dateformat';
|
import dateFormat from 'dateformat';
|
||||||
import { messagesToLines, truncateLines, joinLines } from './monitor-utils';
|
import { messagesToLines, truncateLines } from './monitor-utils';
|
||||||
import { MonitorManagerProxyClient } from '../../../common/protocol';
|
import { MonitorManagerProxyClient } from '../../../common/protocol';
|
||||||
import { MonitorModel } from '../../monitor-model';
|
import { MonitorModel } from '../../monitor-model';
|
||||||
import { ClipboardService } from '@theia/core/lib/browser/clipboard-service';
|
|
||||||
|
|
||||||
export type Line = { message: string; timestamp?: Date; lineLen: number };
|
export type Line = { message: string; timestamp?: Date; lineLen: number };
|
||||||
|
|
||||||
@@ -75,9 +74,6 @@ export class SerialMonitorOutput extends React.Component<
|
|||||||
this.props.clearConsoleEvent(() =>
|
this.props.clearConsoleEvent(() =>
|
||||||
this.setState({ lines: [], charCount: 0 })
|
this.setState({ lines: [], charCount: 0 })
|
||||||
),
|
),
|
||||||
this.props.copyOutputEvent(() =>
|
|
||||||
this.props.clipboardService.writeText(joinLines(this.state.lines))
|
|
||||||
),
|
|
||||||
this.props.monitorModel.onChange(({ property }) => {
|
this.props.monitorModel.onChange(({ property }) => {
|
||||||
if (property === 'timestamp') {
|
if (property === 'timestamp') {
|
||||||
const { timestamp } = this.props.monitorModel;
|
const { timestamp } = this.props.monitorModel;
|
||||||
@@ -134,8 +130,6 @@ export namespace SerialMonitorOutput {
|
|||||||
readonly monitorModel: MonitorModel;
|
readonly monitorModel: MonitorModel;
|
||||||
readonly monitorManagerProxy: MonitorManagerProxyClient;
|
readonly monitorManagerProxy: MonitorManagerProxyClient;
|
||||||
readonly clearConsoleEvent: Event<void>;
|
readonly clearConsoleEvent: Event<void>;
|
||||||
readonly copyOutputEvent: Event<void>;
|
|
||||||
readonly clipboardService: ClipboardService;
|
|
||||||
readonly height: number;
|
readonly height: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -34,6 +34,37 @@
|
|||||||
min-width: 0;
|
min-width: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.ide-updater-dialog--footer {
|
||||||
|
display: inline-block;
|
||||||
|
margin-top: -16px;
|
||||||
|
padding: 12px 0 24px 0;
|
||||||
|
border-top: 1px solid var(--theia-editorWidget-border);
|
||||||
|
}
|
||||||
|
.ide-updater-dialog--footer-content {
|
||||||
|
float: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ide-updater-dialog--footer-link {
|
||||||
|
display: inline-block;
|
||||||
|
color: var(--theia-textLink-foreground);
|
||||||
|
font-weight: 500;
|
||||||
|
line-height: 13px;
|
||||||
|
}
|
||||||
|
.ide-updater-dialog--footer-link:hover {
|
||||||
|
color: var(--theia-textLink-foreground);
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
.ide-updater-dialog--footer-link-icon {
|
||||||
|
display: inline-block;
|
||||||
|
-webkit-mask: url(../icons/link-open-icon.svg) center no-repeat;
|
||||||
|
background-color: var(--theia-textLink-foreground);
|
||||||
|
height: 12px;
|
||||||
|
width: 12px;
|
||||||
|
cursor: pointer;
|
||||||
|
transform: translateY(2px);
|
||||||
|
margin-left: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
.ide-updater-dialog .changelog {
|
.ide-updater-dialog .changelog {
|
||||||
color: var(--theia-editor-foreground);
|
color: var(--theia-editor-foreground);
|
||||||
background-color: var(--theia-editor-background);
|
background-color: var(--theia-editor-background);
|
||||||
@@ -109,6 +140,7 @@
|
|||||||
max-height: 100%;
|
max-height: 100%;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
padding-bottom: 20px !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ide-updater-dialog-container .skip-version-button {
|
#ide-updater-dialog-container .skip-version-button {
|
||||||
|
|||||||
@@ -10,6 +10,7 @@
|
|||||||
@import "./settings-dialog.css";
|
@import "./settings-dialog.css";
|
||||||
@import "./firmware-uploader-dialog.css";
|
@import "./firmware-uploader-dialog.css";
|
||||||
@import "./ide-updater-dialog.css";
|
@import "./ide-updater-dialog.css";
|
||||||
|
@import "./version-welcome-dialog.css";
|
||||||
@import "./certificate-uploader-dialog.css";
|
@import "./certificate-uploader-dialog.css";
|
||||||
@import "./user-fields-dialog.css";
|
@import "./user-fields-dialog.css";
|
||||||
@import "./debug.css";
|
@import "./debug.css";
|
||||||
|
|||||||
@@ -0,0 +1,7 @@
|
|||||||
|
#version-welcome-dialog-container > .dialogBlock {
|
||||||
|
width: 546px;
|
||||||
|
|
||||||
|
.bold {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,7 +2,6 @@ import { expect } from 'chai';
|
|||||||
import {
|
import {
|
||||||
messagesToLines,
|
messagesToLines,
|
||||||
truncateLines,
|
truncateLines,
|
||||||
joinLines,
|
|
||||||
} from '../../browser/serial/monitor/monitor-utils';
|
} from '../../browser/serial/monitor/monitor-utils';
|
||||||
import { Line } from '../../browser/serial/monitor/serial-monitor-send-output';
|
import { Line } from '../../browser/serial/monitor/serial-monitor-send-output';
|
||||||
import { set, reset } from 'mockdate';
|
import { set, reset } from 'mockdate';
|
||||||
@@ -16,7 +15,6 @@ type TestLine = {
|
|||||||
charCount: number;
|
charCount: number;
|
||||||
maxCharacters?: number;
|
maxCharacters?: number;
|
||||||
};
|
};
|
||||||
expectedJoined?: string;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const date = new Date();
|
const date = new Date();
|
||||||
@@ -24,7 +22,6 @@ const testLines: TestLine[] = [
|
|||||||
{
|
{
|
||||||
messages: ['Hello'],
|
messages: ['Hello'],
|
||||||
expected: { lines: [{ message: 'Hello', lineLen: 5 }], charCount: 5 },
|
expected: { lines: [{ message: 'Hello', lineLen: 5 }], charCount: 5 },
|
||||||
expectedJoined: 'Hello',
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
messages: ['Hello', 'Dog!'],
|
messages: ['Hello', 'Dog!'],
|
||||||
@@ -39,7 +36,6 @@ const testLines: TestLine[] = [
|
|||||||
],
|
],
|
||||||
charCount: 10,
|
charCount: 10,
|
||||||
},
|
},
|
||||||
expectedJoined: 'Hello\nDog!'
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
messages: ['Dog!'],
|
messages: ['Dog!'],
|
||||||
@@ -71,7 +67,6 @@ const testLines: TestLine[] = [
|
|||||||
{ message: "You're a good boy!", lineLen: 8 },
|
{ message: "You're a good boy!", lineLen: 8 },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
expectedJoined: "Hello Dog!\n Who's a good boy?\nYou're a good boy!",
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
messages: ['boy?\n', "You're a good boy!"],
|
messages: ['boy?\n', "You're a good boy!"],
|
||||||
@@ -121,7 +116,6 @@ const testLines: TestLine[] = [
|
|||||||
{ message: 'Yo', lineLen: 2 },
|
{ message: 'Yo', lineLen: 2 },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
expectedJoined: "Hello Dog!\nWho's a good boy?\nYo",
|
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
@@ -171,10 +165,6 @@ describe('Monitor Utils', () => {
|
|||||||
});
|
});
|
||||||
expect(totalCharCount).to.equal(charCount);
|
expect(totalCharCount).to.equal(charCount);
|
||||||
}
|
}
|
||||||
if (testLine.expectedJoined) {
|
|
||||||
const joined_str = joinLines(testLine.expected.lines);
|
|
||||||
expect(joined_str).to.equal(testLine.expectedJoined);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
12
i18n/en.json
12
i18n/en.json
@@ -275,6 +275,9 @@
|
|||||||
"checkForUpdates": "Check for Arduino IDE Updates",
|
"checkForUpdates": "Check for Arduino IDE Updates",
|
||||||
"closeAndInstallButton": "Close and Install",
|
"closeAndInstallButton": "Close and Install",
|
||||||
"closeToInstallNotice": "Close the software and install the update on your machine.",
|
"closeToInstallNotice": "Close the software and install the update on your machine.",
|
||||||
|
"donateLinkIconTitle": "open donation page",
|
||||||
|
"donateLinkText": "donate to support us",
|
||||||
|
"donateText": "Open source is love, {0}",
|
||||||
"downloadButton": "Download",
|
"downloadButton": "Download",
|
||||||
"downloadingNotice": "Downloading the latest version of the Arduino IDE.",
|
"downloadingNotice": "Downloading the latest version of the Arduino IDE.",
|
||||||
"errorCheckingForUpdates": "Error while checking for Arduino IDE updates.\n{0}",
|
"errorCheckingForUpdates": "Error while checking for Arduino IDE updates.\n{0}",
|
||||||
@@ -432,7 +435,6 @@
|
|||||||
"autoscroll": "Autoscroll",
|
"autoscroll": "Autoscroll",
|
||||||
"carriageReturn": "Carriage Return",
|
"carriageReturn": "Carriage Return",
|
||||||
"connecting": "Connecting to '{0}' on '{1}'...",
|
"connecting": "Connecting to '{0}' on '{1}'...",
|
||||||
"copyOutput": "Copy Output",
|
|
||||||
"message": "Message (Enter to send message to '{0}' on '{1}')",
|
"message": "Message (Enter to send message to '{0}' on '{1}')",
|
||||||
"newLine": "New Line",
|
"newLine": "New Line",
|
||||||
"newLineCarriageReturn": "Both NL & CR",
|
"newLineCarriageReturn": "Both NL & CR",
|
||||||
@@ -520,6 +522,14 @@
|
|||||||
"renameSketchFolderMessage": "The sketch '{0}' cannot be used. {1} To get rid of this message, rename the sketch. Do you want to rename the sketch now?",
|
"renameSketchFolderMessage": "The sketch '{0}' cannot be used. {1} To get rid of this message, rename the sketch. Do you want to rename the sketch now?",
|
||||||
"renameSketchFolderTitle": "Invalid sketch name"
|
"renameSketchFolderTitle": "Invalid sketch name"
|
||||||
},
|
},
|
||||||
|
"versionWelcome": {
|
||||||
|
"cancelButton": "Maybe later",
|
||||||
|
"donateButton": "Donate now",
|
||||||
|
"donateMessage": "Arduino is committed to keeping software free and open-source for everyone. Your donation helps us develop new features, improve libraries, and support millions of users worldwide.",
|
||||||
|
"donateMessage2": "Please consider supporting our work on the free open source Arduino IDE.",
|
||||||
|
"title": "Welcome to a new version of the Arduino IDE!",
|
||||||
|
"titleWithVersion": "Welcome to the new Arduino IDE {0}!"
|
||||||
|
},
|
||||||
"workspace": {
|
"workspace": {
|
||||||
"alreadyExists": "'{0}' already exists."
|
"alreadyExists": "'{0}' already exists."
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5912,7 +5912,7 @@ domexception@^4.0.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
webidl-conversions "^7.0.0"
|
webidl-conversions "^7.0.0"
|
||||||
|
|
||||||
dompurify@^2.2.9:
|
dompurify@^2.2.9, dompurify@^2.4.7:
|
||||||
version "2.5.8"
|
version "2.5.8"
|
||||||
resolved "https://registry.yarnpkg.com/dompurify/-/dompurify-2.5.8.tgz#2809d89d7e528dc7a071dea440d7376df676f824"
|
resolved "https://registry.yarnpkg.com/dompurify/-/dompurify-2.5.8.tgz#2809d89d7e528dc7a071dea440d7376df676f824"
|
||||||
integrity sha512-o1vSNgrmYMQObbSSvF/1brBYEQPHhV1+gsmrusO7/GXtp1T9rCS8cXFqVxK/9crT1jA6Ccv+5MTSjBNqr7Sovw==
|
integrity sha512-o1vSNgrmYMQObbSSvF/1brBYEQPHhV1+gsmrusO7/GXtp1T9rCS8cXFqVxK/9crT1jA6Ccv+5MTSjBNqr7Sovw==
|
||||||
|
|||||||
Reference in New Issue
Block a user