diff --git a/e2e/playwright/fixtures/cmdBarFixture.ts b/e2e/playwright/fixtures/cmdBarFixture.ts index 8754f879b..a51562e60 100644 --- a/e2e/playwright/fixtures/cmdBarFixture.ts +++ b/e2e/playwright/fixtures/cmdBarFixture.ts @@ -3,7 +3,7 @@ import { expect } from '@playwright/test' import * as fs from 'fs' import * as path from 'path' -type CmdBarSerialised = +export type CmdBarSerialised = | { stage: 'commandBarClosed' } diff --git a/e2e/playwright/fixtures/toolbarFixture.ts b/e2e/playwright/fixtures/toolbarFixture.ts index 8b98af630..dbe5c9933 100644 --- a/e2e/playwright/fixtures/toolbarFixture.ts +++ b/e2e/playwright/fixtures/toolbarFixture.ts @@ -27,6 +27,7 @@ export class ToolbarFixture { offsetPlaneButton!: Locator helixButton!: Locator startSketchBtn!: Locator + insertButton!: Locator lineBtn!: Locator tangentialArcBtn!: Locator circleBtn!: Locator @@ -44,7 +45,7 @@ export class ToolbarFixture { featureTreePane!: Locator gizmo!: Locator gizmoDisabled!: Locator - insertButton!: Locator + loadButton!: Locator constructor(page: Page) { this.page = page @@ -59,6 +60,7 @@ export class ToolbarFixture { this.offsetPlaneButton = page.getByTestId('plane-offset') this.helixButton = page.getByTestId('helix') this.startSketchBtn = page.getByTestId('sketch') + this.insertButton = page.getByTestId('insert') this.lineBtn = page.getByTestId('line') this.tangentialArcBtn = page.getByTestId('tangential-arc') this.circleBtn = page.getByTestId('circle-center') @@ -68,6 +70,7 @@ export class ToolbarFixture { this.fileTreeBtn = page.locator('[id="files-button-holder"]') this.createFileBtn = page.getByTestId('create-file-button') this.treeInputField = page.getByTestId('tree-input-field') + this.loadButton = page.getByTestId('load-external-model-pane-button') this.filePane = page.locator('#files-pane') this.featureTreePane = page.locator('#feature-tree-pane') @@ -79,8 +82,6 @@ export class ToolbarFixture { // element or two different elements can represent these states. this.gizmo = page.getByTestId('gizmo') this.gizmoDisabled = page.getByTestId('gizmo-disabled') - - this.insertButton = page.getByTestId('insert-pane-button') } get logoLink() { diff --git a/e2e/playwright/native-file-menu.spec.ts b/e2e/playwright/native-file-menu.spec.ts index 3b753794b..f8d571ac0 100644 --- a/e2e/playwright/native-file-menu.spec.ts +++ b/e2e/playwright/native-file-menu.spec.ts @@ -534,7 +534,7 @@ test.describe('Native file menu', { tag: ['@electron'] }, () => { const expected = 'Open project' expect(actual).toBe(expected) }) - test('Modeling.File.Load a sample model', async ({ + test('Modeling.File.Load external model', async ({ tronApp, cmdBar, page, @@ -555,10 +555,10 @@ test.describe('Native file menu', { tag: ['@electron'] }, () => { throw new Error('app or app.applicationMenu is missing') } const openProject = app.applicationMenu.getMenuItemById( - 'File.Load a sample model' + 'File.Load external model' ) if (!openProject) { - throw new Error('File.Load a sample model') + throw new Error('File.Load external model') } openProject.click() }) @@ -568,44 +568,7 @@ test.describe('Native file menu', { tag: ['@electron'] }, () => { const actual = await cmdBar.cmdBarElement .getByTestId('command-name') .textContent() - const expected = 'Open sample' - expect(actual).toBe(expected) - }) - test('Modeling.File.Insert from project file', async ({ - tronApp, - cmdBar, - page, - homePage, - scene, - }) => { - if (!tronApp) { - throwTronAppMissing() - return - } - await homePage.goToModelingScene() - await scene.settled(cmdBar) - - // Run electron snippet to find the Menu! - await page.waitForTimeout(100) // wait for createModelingPageMenu() to run - await tronApp.electron.evaluate(async ({ app }) => { - if (!app || !app.applicationMenu) { - throw new Error('app or app.applicationMenu is missing') - } - const openProject = app.applicationMenu.getMenuItemById( - 'File.Insert from project file' - ) - if (!openProject) { - throw new Error('File.Insert from project file') - } - openProject.click() - }) - // Check that the command bar is opened - await expect(cmdBar.cmdBarElement).toBeVisible() - // Check the placeholder project name exists - const actual = await cmdBar.cmdBarElement - .getByTestId('command-name') - .textContent() - const expected = 'Insert' + const expected = 'Load external model' expect(actual).toBe(expected) }) test('Modeling.File.Export current part', async ({ @@ -2159,6 +2122,44 @@ test.describe('Native file menu', { tag: ['@electron'] }, () => { expect(actual).toBe(expected) }) + test('Modeling.Design.Insert from project file', async ({ + tronApp, + cmdBar, + page, + homePage, + scene, + }) => { + if (!tronApp) { + throwTronAppMissing() + return + } + await homePage.goToModelingScene() + await scene.settled(cmdBar) + + // Run electron snippet to find the Menu! + await page.waitForTimeout(100) // wait for createModelingPageMenu() to run + await tronApp.electron.evaluate(async ({ app }) => { + if (!app || !app.applicationMenu) { + throw new Error('app or app.applicationMenu is missing') + } + const openProject = app.applicationMenu.getMenuItemById( + 'Design.Insert from project file' + ) + if (!openProject) { + throw new Error('Design.Insert from project file') + } + openProject.click() + }) + // Check that the command bar is opened + await expect(cmdBar.cmdBarElement).toBeVisible() + // Check the placeholder project name exists + const actual = await cmdBar.cmdBarElement + .getByTestId('command-name') + .textContent() + const expected = 'Insert' + expect(actual).toBe(expected) + }) + test('Modeling.Design.Create with Zoo Text-To-CAD', async ({ tronApp, cmdBar, diff --git a/e2e/playwright/snapshot-tests.spec.ts-snapshots/Client-side-scene-scale-should-match-engine-scale-Inch-scale-1-Google-Chrome-linux.png b/e2e/playwright/snapshot-tests.spec.ts-snapshots/Client-side-scene-scale-should-match-engine-scale-Inch-scale-1-Google-Chrome-linux.png index 5588d0291..8bb7bf691 100644 Binary files a/e2e/playwright/snapshot-tests.spec.ts-snapshots/Client-side-scene-scale-should-match-engine-scale-Inch-scale-1-Google-Chrome-linux.png and b/e2e/playwright/snapshot-tests.spec.ts-snapshots/Client-side-scene-scale-should-match-engine-scale-Inch-scale-1-Google-Chrome-linux.png differ diff --git a/e2e/playwright/snapshot-tests.spec.ts-snapshots/Client-side-scene-scale-should-match-engine-scale-Inch-scale-2-Google-Chrome-linux.png b/e2e/playwright/snapshot-tests.spec.ts-snapshots/Client-side-scene-scale-should-match-engine-scale-Inch-scale-2-Google-Chrome-linux.png index 8caa73e91..2d7ddb690 100644 Binary files a/e2e/playwright/snapshot-tests.spec.ts-snapshots/Client-side-scene-scale-should-match-engine-scale-Inch-scale-2-Google-Chrome-linux.png and b/e2e/playwright/snapshot-tests.spec.ts-snapshots/Client-side-scene-scale-should-match-engine-scale-Inch-scale-2-Google-Chrome-linux.png differ diff --git a/e2e/playwright/snapshot-tests.spec.ts-snapshots/Client-side-scene-scale-should-match-engine-scale-Millimeter-scale-1-Google-Chrome-linux.png b/e2e/playwright/snapshot-tests.spec.ts-snapshots/Client-side-scene-scale-should-match-engine-scale-Millimeter-scale-1-Google-Chrome-linux.png index 86a220ca1..482a2f052 100644 Binary files a/e2e/playwright/snapshot-tests.spec.ts-snapshots/Client-side-scene-scale-should-match-engine-scale-Millimeter-scale-1-Google-Chrome-linux.png and b/e2e/playwright/snapshot-tests.spec.ts-snapshots/Client-side-scene-scale-should-match-engine-scale-Millimeter-scale-1-Google-Chrome-linux.png differ diff --git a/e2e/playwright/snapshot-tests.spec.ts-snapshots/Client-side-scene-scale-should-match-engine-scale-Millimeter-scale-2-Google-Chrome-linux.png b/e2e/playwright/snapshot-tests.spec.ts-snapshots/Client-side-scene-scale-should-match-engine-scale-Millimeter-scale-2-Google-Chrome-linux.png index d2912b374..7a663e105 100644 Binary files a/e2e/playwright/snapshot-tests.spec.ts-snapshots/Client-side-scene-scale-should-match-engine-scale-Millimeter-scale-2-Google-Chrome-linux.png and b/e2e/playwright/snapshot-tests.spec.ts-snapshots/Client-side-scene-scale-should-match-engine-scale-Millimeter-scale-2-Google-Chrome-linux.png differ diff --git a/e2e/playwright/snapshot-tests.spec.ts-snapshots/Draft-circle-should-look-right-1-Google-Chrome-linux.png b/e2e/playwright/snapshot-tests.spec.ts-snapshots/Draft-circle-should-look-right-1-Google-Chrome-linux.png index 1817c33ee..9e0b760c6 100644 Binary files a/e2e/playwright/snapshot-tests.spec.ts-snapshots/Draft-circle-should-look-right-1-Google-Chrome-linux.png and b/e2e/playwright/snapshot-tests.spec.ts-snapshots/Draft-circle-should-look-right-1-Google-Chrome-linux.png differ diff --git a/e2e/playwright/snapshot-tests.spec.ts-snapshots/Draft-rectangles-should-look-right-1-Google-Chrome-linux.png b/e2e/playwright/snapshot-tests.spec.ts-snapshots/Draft-rectangles-should-look-right-1-Google-Chrome-linux.png index 5d24a83cc..2f045e1a1 100644 Binary files a/e2e/playwright/snapshot-tests.spec.ts-snapshots/Draft-rectangles-should-look-right-1-Google-Chrome-linux.png and b/e2e/playwright/snapshot-tests.spec.ts-snapshots/Draft-rectangles-should-look-right-1-Google-Chrome-linux.png differ diff --git a/e2e/playwright/snapshot-tests.spec.ts-snapshots/Draft-segments-should-look-right-1-Google-Chrome-linux.png b/e2e/playwright/snapshot-tests.spec.ts-snapshots/Draft-segments-should-look-right-1-Google-Chrome-linux.png index f42dc8860..1167ae89e 100644 Binary files a/e2e/playwright/snapshot-tests.spec.ts-snapshots/Draft-segments-should-look-right-1-Google-Chrome-linux.png and b/e2e/playwright/snapshot-tests.spec.ts-snapshots/Draft-segments-should-look-right-1-Google-Chrome-linux.png differ diff --git a/e2e/playwright/snapshot-tests.spec.ts-snapshots/Draft-segments-should-look-right-2-Google-Chrome-linux.png b/e2e/playwright/snapshot-tests.spec.ts-snapshots/Draft-segments-should-look-right-2-Google-Chrome-linux.png index 2e6cc3b82..1f8f5a15e 100644 Binary files a/e2e/playwright/snapshot-tests.spec.ts-snapshots/Draft-segments-should-look-right-2-Google-Chrome-linux.png and b/e2e/playwright/snapshot-tests.spec.ts-snapshots/Draft-segments-should-look-right-2-Google-Chrome-linux.png differ diff --git a/e2e/playwright/snapshot-tests.spec.ts-snapshots/Draft-segments-should-look-right-3-Google-Chrome-linux.png b/e2e/playwright/snapshot-tests.spec.ts-snapshots/Draft-segments-should-look-right-3-Google-Chrome-linux.png index 4f7f6313b..01eccb71d 100644 Binary files a/e2e/playwright/snapshot-tests.spec.ts-snapshots/Draft-segments-should-look-right-3-Google-Chrome-linux.png and b/e2e/playwright/snapshot-tests.spec.ts-snapshots/Draft-segments-should-look-right-3-Google-Chrome-linux.png differ diff --git a/e2e/playwright/snapshot-tests.spec.ts-snapshots/Draft-segments-should-look-right-4-Google-Chrome-linux.png b/e2e/playwright/snapshot-tests.spec.ts-snapshots/Draft-segments-should-look-right-4-Google-Chrome-linux.png index 3297d65f4..74f876f31 100644 Binary files a/e2e/playwright/snapshot-tests.spec.ts-snapshots/Draft-segments-should-look-right-4-Google-Chrome-linux.png and b/e2e/playwright/snapshot-tests.spec.ts-snapshots/Draft-segments-should-look-right-4-Google-Chrome-linux.png differ diff --git a/e2e/playwright/snapshot-tests.spec.ts-snapshots/Draft-segments-should-look-right-5-Google-Chrome-linux.png b/e2e/playwright/snapshot-tests.spec.ts-snapshots/Draft-segments-should-look-right-5-Google-Chrome-linux.png index ec849f4f3..50215cecc 100644 Binary files a/e2e/playwright/snapshot-tests.spec.ts-snapshots/Draft-segments-should-look-right-5-Google-Chrome-linux.png and b/e2e/playwright/snapshot-tests.spec.ts-snapshots/Draft-segments-should-look-right-5-Google-Chrome-linux.png differ diff --git a/e2e/playwright/snapshot-tests.spec.ts-snapshots/Grid-visibility-Grid-turned-off-1-Google-Chrome-linux.png b/e2e/playwright/snapshot-tests.spec.ts-snapshots/Grid-visibility-Grid-turned-off-1-Google-Chrome-linux.png index d2a9c2f82..0f7cd8d2c 100644 Binary files a/e2e/playwright/snapshot-tests.spec.ts-snapshots/Grid-visibility-Grid-turned-off-1-Google-Chrome-linux.png and b/e2e/playwright/snapshot-tests.spec.ts-snapshots/Grid-visibility-Grid-turned-off-1-Google-Chrome-linux.png differ diff --git a/e2e/playwright/snapshot-tests.spec.ts-snapshots/Grid-visibility-Grid-turned-off-to-on-via-command-bar-1-Google-Chrome-linux.png b/e2e/playwright/snapshot-tests.spec.ts-snapshots/Grid-visibility-Grid-turned-off-to-on-via-command-bar-1-Google-Chrome-linux.png index 1335cd834..f17c6f989 100644 Binary files a/e2e/playwright/snapshot-tests.spec.ts-snapshots/Grid-visibility-Grid-turned-off-to-on-via-command-bar-1-Google-Chrome-linux.png and b/e2e/playwright/snapshot-tests.spec.ts-snapshots/Grid-visibility-Grid-turned-off-to-on-via-command-bar-1-Google-Chrome-linux.png differ diff --git a/e2e/playwright/snapshot-tests.spec.ts-snapshots/Grid-visibility-Grid-turned-on-1-Google-Chrome-linux.png b/e2e/playwright/snapshot-tests.spec.ts-snapshots/Grid-visibility-Grid-turned-on-1-Google-Chrome-linux.png index 6ea2e87f8..588b60b54 100644 Binary files a/e2e/playwright/snapshot-tests.spec.ts-snapshots/Grid-visibility-Grid-turned-on-1-Google-Chrome-linux.png and b/e2e/playwright/snapshot-tests.spec.ts-snapshots/Grid-visibility-Grid-turned-on-1-Google-Chrome-linux.png differ diff --git a/e2e/playwright/snapshot-tests.spec.ts-snapshots/Sketch-on-face-with-none-z-up-1-Google-Chrome-linux.png b/e2e/playwright/snapshot-tests.spec.ts-snapshots/Sketch-on-face-with-none-z-up-1-Google-Chrome-linux.png index d1f647232..3f0a04d1a 100644 Binary files a/e2e/playwright/snapshot-tests.spec.ts-snapshots/Sketch-on-face-with-none-z-up-1-Google-Chrome-linux.png and b/e2e/playwright/snapshot-tests.spec.ts-snapshots/Sketch-on-face-with-none-z-up-1-Google-Chrome-linux.png differ diff --git a/e2e/playwright/snapshot-tests.spec.ts-snapshots/Zoom-to-fit-on-load---solid-2d-1-Google-Chrome-linux.png b/e2e/playwright/snapshot-tests.spec.ts-snapshots/Zoom-to-fit-on-load---solid-2d-1-Google-Chrome-linux.png index 8d77007aa..f0e48e88c 100644 Binary files a/e2e/playwright/snapshot-tests.spec.ts-snapshots/Zoom-to-fit-on-load---solid-2d-1-Google-Chrome-linux.png and b/e2e/playwright/snapshot-tests.spec.ts-snapshots/Zoom-to-fit-on-load---solid-2d-1-Google-Chrome-linux.png differ diff --git a/e2e/playwright/snapshot-tests.spec.ts-snapshots/Zoom-to-fit-on-load---solid-3d-1-Google-Chrome-linux.png b/e2e/playwright/snapshot-tests.spec.ts-snapshots/Zoom-to-fit-on-load---solid-3d-1-Google-Chrome-linux.png index 99e959f14..7ba9823d4 100644 Binary files a/e2e/playwright/snapshot-tests.spec.ts-snapshots/Zoom-to-fit-on-load---solid-3d-1-Google-Chrome-linux.png and b/e2e/playwright/snapshot-tests.spec.ts-snapshots/Zoom-to-fit-on-load---solid-3d-1-Google-Chrome-linux.png differ diff --git a/e2e/playwright/snapshot-tests.spec.ts-snapshots/code-color-goober-code-color-goober-1-Google-Chrome-linux.png b/e2e/playwright/snapshot-tests.spec.ts-snapshots/code-color-goober-code-color-goober-1-Google-Chrome-linux.png index fe71b9a65..df2538741 100644 Binary files a/e2e/playwright/snapshot-tests.spec.ts-snapshots/code-color-goober-code-color-goober-1-Google-Chrome-linux.png and b/e2e/playwright/snapshot-tests.spec.ts-snapshots/code-color-goober-code-color-goober-1-Google-Chrome-linux.png differ diff --git a/e2e/playwright/snapshot-tests.spec.ts-snapshots/code-color-goober-code-color-goober-opening-window-1-Google-Chrome-linux.png b/e2e/playwright/snapshot-tests.spec.ts-snapshots/code-color-goober-code-color-goober-opening-window-1-Google-Chrome-linux.png index 0eac3e0e3..567fcf160 100644 Binary files a/e2e/playwright/snapshot-tests.spec.ts-snapshots/code-color-goober-code-color-goober-opening-window-1-Google-Chrome-linux.png and b/e2e/playwright/snapshot-tests.spec.ts-snapshots/code-color-goober-code-color-goober-opening-window-1-Google-Chrome-linux.png differ diff --git a/e2e/playwright/snapshot-tests.spec.ts-snapshots/extrude-on-default-planes-should-be-stable--XY-1-Google-Chrome-linux.png b/e2e/playwright/snapshot-tests.spec.ts-snapshots/extrude-on-default-planes-should-be-stable--XY-1-Google-Chrome-linux.png index 0e76ac3c0..18f2db487 100644 Binary files a/e2e/playwright/snapshot-tests.spec.ts-snapshots/extrude-on-default-planes-should-be-stable--XY-1-Google-Chrome-linux.png and b/e2e/playwright/snapshot-tests.spec.ts-snapshots/extrude-on-default-planes-should-be-stable--XY-1-Google-Chrome-linux.png differ diff --git a/e2e/playwright/snapshot-tests.spec.ts-snapshots/extrude-on-default-planes-should-be-stable--XZ-1-Google-Chrome-linux.png b/e2e/playwright/snapshot-tests.spec.ts-snapshots/extrude-on-default-planes-should-be-stable--XZ-1-Google-Chrome-linux.png index 3f5064454..b3e371dac 100644 Binary files a/e2e/playwright/snapshot-tests.spec.ts-snapshots/extrude-on-default-planes-should-be-stable--XZ-1-Google-Chrome-linux.png and b/e2e/playwright/snapshot-tests.spec.ts-snapshots/extrude-on-default-planes-should-be-stable--XZ-1-Google-Chrome-linux.png differ diff --git a/e2e/playwright/snapshot-tests.spec.ts-snapshots/extrude-on-default-planes-should-be-stable--YZ-1-Google-Chrome-linux.png b/e2e/playwright/snapshot-tests.spec.ts-snapshots/extrude-on-default-planes-should-be-stable--YZ-1-Google-Chrome-linux.png index 1191c202e..658af6c2c 100644 Binary files a/e2e/playwright/snapshot-tests.spec.ts-snapshots/extrude-on-default-planes-should-be-stable--YZ-1-Google-Chrome-linux.png and b/e2e/playwright/snapshot-tests.spec.ts-snapshots/extrude-on-default-planes-should-be-stable--YZ-1-Google-Chrome-linux.png differ diff --git a/e2e/playwright/snapshot-tests.spec.ts-snapshots/extrude-on-default-planes-should-be-stable-XY-1-Google-Chrome-linux.png b/e2e/playwright/snapshot-tests.spec.ts-snapshots/extrude-on-default-planes-should-be-stable-XY-1-Google-Chrome-linux.png index d1aa00dc8..a8370f56b 100644 Binary files a/e2e/playwright/snapshot-tests.spec.ts-snapshots/extrude-on-default-planes-should-be-stable-XY-1-Google-Chrome-linux.png and b/e2e/playwright/snapshot-tests.spec.ts-snapshots/extrude-on-default-planes-should-be-stable-XY-1-Google-Chrome-linux.png differ diff --git a/e2e/playwright/snapshot-tests.spec.ts-snapshots/extrude-on-default-planes-should-be-stable-XZ-1-Google-Chrome-linux.png b/e2e/playwright/snapshot-tests.spec.ts-snapshots/extrude-on-default-planes-should-be-stable-XZ-1-Google-Chrome-linux.png index 65d7e48c7..47ccb5b9e 100644 Binary files a/e2e/playwright/snapshot-tests.spec.ts-snapshots/extrude-on-default-planes-should-be-stable-XZ-1-Google-Chrome-linux.png and b/e2e/playwright/snapshot-tests.spec.ts-snapshots/extrude-on-default-planes-should-be-stable-XZ-1-Google-Chrome-linux.png differ diff --git a/e2e/playwright/snapshot-tests.spec.ts-snapshots/extrude-on-default-planes-should-be-stable-YZ-1-Google-Chrome-linux.png b/e2e/playwright/snapshot-tests.spec.ts-snapshots/extrude-on-default-planes-should-be-stable-YZ-1-Google-Chrome-linux.png index 9d7c655e5..0fdd83740 100644 Binary files a/e2e/playwright/snapshot-tests.spec.ts-snapshots/extrude-on-default-planes-should-be-stable-YZ-1-Google-Chrome-linux.png and b/e2e/playwright/snapshot-tests.spec.ts-snapshots/extrude-on-default-planes-should-be-stable-YZ-1-Google-Chrome-linux.png differ diff --git a/e2e/playwright/testing-samples-loading.spec.ts b/e2e/playwright/testing-samples-loading.spec.ts index 4b54d117c..01cce02c1 100644 --- a/e2e/playwright/testing-samples-loading.spec.ts +++ b/e2e/playwright/testing-samples-loading.spec.ts @@ -3,14 +3,18 @@ import { FILE_EXT } from '@src/lib/constants' import * as fsp from 'fs/promises' import { join } from 'path' +import type { CmdBarSerialised } from '@e2e/playwright/fixtures/cmdBarFixture' +import type { ElectronZoo } from '@e2e/playwright/fixtures/fixtureSetup' import { + executorInputPath, getUtils, orRunWhenFullSuiteEnabled, runningOnWindows, + testsInputPath, } from '@e2e/playwright/test-utils' import { expect, test } from '@e2e/playwright/zoo-test' -test.describe('Testing in-app sample loading', () => { +test.describe('Testing loading external models', () => { /** * Note this test implicitly depends on the KCL sample "parametric-bearing-pillow-block", * its title, and its units settings. https://github.com/KittyCAD/kcl-samples/blob/main/parametric-bearing-pillow-block/main.kcl @@ -39,7 +43,7 @@ test.describe('Testing in-app sample loading', () => { } const commandBarButton = page.getByRole('button', { name: 'Commands' }) const samplesCommandOption = page.getByRole('option', { - name: 'Open Sample', + name: 'Load external model', }) const commandSampleOption = page.getByRole('option', { name: newSample.title, @@ -83,7 +87,7 @@ test.describe('Testing in-app sample loading', () => { test( 'Desktop: should create new file by default, optionally overwrite', { tag: '@electron' }, - async ({ editor, context, page, scene, cmdBar }, testInfo) => { + async ({ editor, context, page, scene, cmdBar, toolbar }) => { if (runningOnWindows()) { test.fixme(orRunWhenFullSuiteEnabled()) } @@ -106,20 +110,12 @@ test.describe('Testing in-app sample loading', () => { title: '100mm Gear Rack', } const projectCard = page.getByRole('link', { name: 'bracket' }) - const commandBarButton = page.getByRole('button', { name: 'Commands' }) - const commandOption = page.getByRole('option', { name: 'Open Sample' }) - const commandSampleOption = (name: string) => - page.getByRole('option', { - name, - exact: true, - }) const commandMethodArgButton = page.getByRole('button', { name: 'Method', }) const commandMethodOption = page.getByRole('option', { name: 'Overwrite', }) - const newFileWarning = page.getByText('Create a new file from sample?') const overwriteWarning = page.getByText( 'Overwrite current file with sample?' ) @@ -129,6 +125,18 @@ test.describe('Testing in-app sample loading', () => { page.getByRole('listitem').filter({ has: page.getByRole('button', { name }), }) + const defaultLoadCmdBarState: CmdBarSerialised = { + commandName: 'Load external model', + currentArgKey: 'source', + currentArgValue: '', + headerArguments: { + Method: 'newFile', + Sample: '', + Source: '', + }, + highlightedHeaderArg: 'source', + stage: 'arguments', + } await test.step(`Test setup`, async () => { await page.setBodyDimensions({ width: 1200, height: 500 }) @@ -147,14 +155,12 @@ test.describe('Testing in-app sample loading', () => { }) await test.step(`Load a KCL sample with the command palette`, async () => { - await commandBarButton.click() - await page.waitForTimeout(1000) - await commandOption.click() - await page.waitForTimeout(1000) - await commandSampleOption(sampleOne.title).click() + await toolbar.loadButton.click() + await cmdBar.expectState(defaultLoadCmdBarState) + await cmdBar.progressCmdBar() + await cmdBar.selectOption({ name: sampleOne.title }).click() await expect(overwriteWarning).not.toBeVisible() - await expect(newFileWarning).toBeVisible() - await confirmButton.click() + await cmdBar.progressCmdBar() await page.waitForTimeout(1000) }) @@ -165,21 +171,15 @@ test.describe('Testing in-app sample loading', () => { }) await test.step(`Now overwrite the current file`, async () => { - await commandBarButton.click() - await page.waitForTimeout(1000) - await commandOption.click() - await page.waitForTimeout(1000) - await commandSampleOption(sampleTwo.title).click() - await page.waitForTimeout(1000) + await toolbar.loadButton.click() + await cmdBar.expectState(defaultLoadCmdBarState) + await cmdBar.progressCmdBar() + await cmdBar.selectOption({ name: sampleTwo.title }).click() await commandMethodArgButton.click() - await page.waitForTimeout(1000) await commandMethodOption.click() - await page.waitForTimeout(1000) await expect(commandMethodArgButton).toContainText('overwrite') - await expect(newFileWarning).not.toBeVisible() await expect(overwriteWarning).toBeVisible() await confirmButton.click() - await page.waitForTimeout(1000) }) await test.step(`Ensure we overwrote the current file without navigating`, async () => { @@ -200,4 +200,96 @@ test.describe('Testing in-app sample loading', () => { }) } ) + + const externalModelCases = [ + { + modelName: 'cylinder.kcl', + deconflictedModelName: 'cylinder-1.kcl', + modelPath: executorInputPath('cylinder.kcl'), + }, + { + modelName: 'cube.step', + deconflictedModelName: 'cube-1.step', + modelPath: testsInputPath('cube.step'), + }, + ] + externalModelCases.map(({ modelName, deconflictedModelName, modelPath }) => { + test( + `Load external models from local drive - ${modelName}`, + { tag: ['@electron'] }, + async ({ page, homePage, scene, toolbar, cmdBar, tronApp }) => { + if (!tronApp) { + fail() + } + + await page.setBodyDimensions({ width: 1000, height: 500 }) + await homePage.goToModelingScene() + await scene.settled(cmdBar) + const modelFileContent = await fsp.readFile(modelPath, 'utf-8') + const { editorTextMatches } = await getUtils(page, test) + + async function loadExternalFileThroughCommandBar(tronApp: ElectronZoo) { + await toolbar.loadButton.click() + await cmdBar.expectState({ + commandName: 'Load external model', + currentArgKey: 'source', + currentArgValue: '', + headerArguments: { + Method: 'newFile', + Sample: '', + Source: '', + }, + highlightedHeaderArg: 'source', + stage: 'arguments', + }) + await cmdBar.selectOption({ name: 'Local Drive' }).click() + + // Mock the file picker selection + const handleFile = tronApp.electron.evaluate( + async ({ dialog }, filePaths) => { + dialog.showOpenDialog = () => + Promise.resolve({ canceled: false, filePaths }) + }, + [modelPath] + ) + await page.getByTestId('cmd-bar-arg-file-button').click() + await handleFile + + await cmdBar.progressCmdBar() + await cmdBar.expectState({ + commandName: 'Load external model', + headerArguments: { + Source: 'local', + Path: modelName, + }, + stage: 'review', + }) + await cmdBar.progressCmdBar() + } + + await test.step('Load the external model from local drive', async () => { + await loadExternalFileThroughCommandBar(tronApp) + // TODO: I think the files pane should auto open? + await toolbar.openPane('files') + await toolbar.expectFileTreeState([modelName, 'main.kcl']) + if (modelName.endsWith('.kcl')) { + await editorTextMatches(modelFileContent) + } + }) + + await test.step('Load the same external model, except deconflicted name', async () => { + await loadExternalFileThroughCommandBar(tronApp) + await toolbar.openPane('files') + await toolbar.expectFileTreeState([ + deconflictedModelName, + modelName, + 'main.kcl', + ]) + if (modelName.endsWith('.kcl')) { + await editorTextMatches(modelFileContent) + } + }) + } + ) + }) }) diff --git a/src/components/CommandBar/CommandBarArgument.tsx b/src/components/CommandBar/CommandBarArgument.tsx index 0418c3c95..6f15e9630 100644 --- a/src/components/CommandBar/CommandBarArgument.tsx +++ b/src/components/CommandBar/CommandBarArgument.tsx @@ -2,6 +2,7 @@ import CommandArgOptionInput from '@src/components/CommandBar/CommandArgOptionIn import CommandBarBasicInput from '@src/components/CommandBar/CommandBarBasicInput' import CommandBarHeader from '@src/components/CommandBar/CommandBarHeader' import CommandBarKclInput from '@src/components/CommandBar/CommandBarKclInput' +import CommandBarPathInput from '@src/components/CommandBar/CommandBarPathInput' import CommandBarSelectionInput from '@src/components/CommandBar/CommandBarSelectionInput' import CommandBarSelectionMixedInput from '@src/components/CommandBar/CommandBarSelectionMixedInput' import CommandBarTextareaInput from '@src/components/CommandBar/CommandBarTextareaInput' @@ -108,6 +109,14 @@ function ArgumentInput({ onSubmit={onSubmit} /> ) + case 'path': + return ( + + ) default: return ( ) => + snapshot?.context + +function CommandBarPathInput({ + arg, + stepBack, + onSubmit, +}: { + arg: CommandArgument & { + inputType: 'path' + name: string + } + stepBack: () => void + onSubmit: (event: unknown) => void +}) { + const commandBarState = useCommandBarState() + useHotkeys('mod + k, mod + /', () => commandBarActor.send({ type: 'Close' })) + const inputRef = useRef(null) + const argMachineContext = useSelector( + arg.machineActor, + machineContextSelector + ) + const defaultValue = useMemo( + () => + arg.defaultValue + ? arg.defaultValue instanceof Function + ? arg.defaultValue(commandBarState.context, argMachineContext) + : arg.defaultValue + : '', + [arg.defaultValue, commandBarState.context, argMachineContext] + ) + + function handleSubmit(e: React.FormEvent) { + e.preventDefault() + onSubmit(inputRef.current?.value) + } + + async function pickFileThroughNativeDialog() { + // In desktop end-to-end tests we can't control the file picker, + // so we seed the new directory value in the element's dataset + const inputRefVal = inputRef.current?.dataset.testValue + if (inputRef.current && inputRefVal && !isArray(inputRefVal)) { + inputRef.current.value = inputRefVal + } else if (inputRef.current) { + const newPath = await window.electron.open({ + properties: ['openFile'], + title: 'Pick a file to load into the current project', + }) + if (newPath.canceled) return + inputRef.current.value = newPath.filePaths[0] + } else { + return new Error("Couldn't find inputRef") + } + } + + // Fire on component mount, if outside of e2e test context + useEffect(() => { + window.electron.process.env.IS_PLAYWRIGHT !== 'true' && + toSync(pickFileThroughNativeDialog, reportRejection)() + }, []) + + return ( +
+ +
+ ) +} + +export default CommandBarPathInput diff --git a/src/components/CustomIcon.tsx b/src/components/CustomIcon.tsx index b3179c9bf..49c0b3222 100644 --- a/src/components/CustomIcon.tsx +++ b/src/components/CustomIcon.tsx @@ -619,6 +619,22 @@ const CustomIconMap = { /> ), + importFile: ( + + + + ), 'intersection-offset': ( -1 + if (isTargetPathToCloneASubPath) { + const { name, path } = getNextFileName({ + entryName: input.targetPathToClone + ? window.electron.path.basename(input.targetPathToClone) + : createdName, + baseDir: input.targetPathToClone + ? window.electron.path.dirname(input.targetPathToClone) + : input.selectedDirectory.path, + }) + createdName = name + createdPath = path + } else { + const { name, path } = getNextFileName({ + entryName: input.targetPathToClone + ? window.electron.path.basename(input.targetPathToClone) + : createdName, + baseDir: input.selectedDirectory.path, + }) + createdName = name + createdPath = path + } if (input.targetPathToClone) { await window.electron.copyFile( input.targetPathToClone, @@ -437,19 +451,19 @@ export const FileMachineProvider = ({ settings.modeling.defaultUnit.current ?? DEFAULT_DEFAULT_LENGTH_UNIT, }, - specialPropsForSampleCommand: { + specialPropsForLoadCommand: { onSubmit: async (data) => { - if (data.method === 'overwrite') { - codeManager.updateCodeStateEditor(data.code) + if (data.method === 'overwrite' && data.content) { + codeManager.updateCodeStateEditor(data.content) await kclManager.executeCode() await codeManager.writeToFile() } else if (data.method === 'newFile' && isDesktop()) { send({ type: 'Create file', data: { - name: data.sampleName, - content: data.code, + ...data, makeDir: false, + shouldSetToRename: false, }, }) } @@ -480,7 +494,7 @@ export const FileMachineProvider = ({ }), }, }).filter( - (command) => kclSamples.length || command.name !== 'open-kcl-example' + (command) => kclSamples.length || command.name !== 'load-external-model' ), [codeManager, kclManager, send, kclSamples, project, file] ) diff --git a/src/components/ModelingSidebar/ModelingPanes/KclEditorMenu.tsx b/src/components/ModelingSidebar/ModelingPanes/KclEditorMenu.tsx index d713d7d3d..21f38f75c 100644 --- a/src/components/ModelingSidebar/ModelingPanes/KclEditorMenu.tsx +++ b/src/components/ModelingSidebar/ModelingPanes/KclEditorMenu.tsx @@ -90,13 +90,13 @@ export const KclEditorMenu = ({ children }: PropsWithChildren) => { type: 'Find and select command', data: { groupId: 'code', - name: 'open-kcl-example', + name: 'load-external-model', }, }) }} className={styles.button} > - Load a sample model + Load external model diff --git a/src/components/ModelingSidebar/ModelingSidebar.tsx b/src/components/ModelingSidebar/ModelingSidebar.tsx index 8b0b08998..6f09112cd 100644 --- a/src/components/ModelingSidebar/ModelingSidebar.tsx +++ b/src/components/ModelingSidebar/ModelingSidebar.tsx @@ -15,7 +15,6 @@ import type { } from '@src/components/ModelingSidebar/ModelingPanes' import { sidebarPanes } from '@src/components/ModelingSidebar/ModelingPanes' import Tooltip from '@src/components/Tooltip' -import { DEV } from '@src/env' import { useModelingContext } from '@src/hooks/useModelingContext' import { useNetworkContext } from '@src/hooks/useNetworkContext' import { NetworkHealthState } from '@src/hooks/useNetworkStatus' @@ -26,7 +25,6 @@ import { isDesktop } from '@src/lib/isDesktop' import { useSettings } from '@src/machines/appMachine' import { commandBarActor } from '@src/machines/commandBarMachine' import { onboardingPaths } from '@src/routes/Onboarding/paths' -import { IS_NIGHTLY_OR_DEBUG } from '@src/routes/utils' interface ModelingSidebarProps { paneOpacity: '' | 'opacity-20' | 'opacity-40' @@ -77,16 +75,15 @@ export function ModelingSidebar({ paneOpacity }: ModelingSidebarProps) { const sidebarActions: SidebarAction[] = [ { - id: 'insert', - title: 'Insert from project file', - sidebarName: 'Insert from project file', - icon: 'import', + id: 'load-external-model', + title: 'Load external model', + sidebarName: 'Load external model', + icon: 'importFile', keybinding: 'Ctrl + Shift + I', - hide: (a) => a.platform === 'web' || !(DEV || IS_NIGHTLY_OR_DEBUG), action: () => commandBarActor.send({ type: 'Find and select command', - data: { name: 'Insert', groupId: 'code' }, + data: { name: 'load-external-model', groupId: 'code' }, }), }, { diff --git a/src/lib/commandTypes.ts b/src/lib/commandTypes.ts index 61dd6d691..e895dde18 100644 --- a/src/lib/commandTypes.ts +++ b/src/lib/commandTypes.ts @@ -344,6 +344,15 @@ export type CommandArgument< machineContext?: ContextFrom ) => OutputType) } + | { + inputType: 'path' + defaultValue?: + | OutputType + | (( + commandBarContext: ContextFrom, + machineContext?: ContextFrom + ) => OutputType) + } | { inputType: 'text' defaultValue?: diff --git a/src/lib/desktopFS.ts b/src/lib/desktopFS.ts index 1a4a13b54..29bb9d8ef 100644 --- a/src/lib/desktopFS.ts +++ b/src/lib/desktopFS.ts @@ -1,3 +1,4 @@ +import { relevantFileExtensions } from '@src/lang/wasmUtils' import { FILE_EXT, INDEX_IDENTIFIER, @@ -200,14 +201,20 @@ export function getNextFileName({ entryName: string baseDir: string }) { + // Preserve the extension in case of a relevant but foreign file + let extension = window.electron.path.extname(entryName) + if (!relevantFileExtensions().includes(extension.replace('.', ''))) { + extension = FILE_EXT + } + // Remove any existing index from the name before adding a new one - let createdName = entryName.replace(FILE_EXT, '') + FILE_EXT + let createdName = entryName.replace(extension, '') + extension let createdPath = window.electron.path.join(baseDir, createdName) let i = 1 while (window.electron.exists(createdPath)) { - const matchOnIndexAndExtension = new RegExp(`(-\\d+)?(${FILE_EXT})?$`) + const matchOnIndexAndExtension = new RegExp(`(-\\d+)?(${extension})?$`) createdName = - entryName.replace(matchOnIndexAndExtension, '') + `-${i}` + FILE_EXT + entryName.replace(matchOnIndexAndExtension, '') + `-${i}` + extension createdPath = window.electron.path.join(baseDir, createdName) i++ } diff --git a/src/lib/kclCommands.ts b/src/lib/kclCommands.ts index e31745ffc..0f4441f02 100644 --- a/src/lib/kclCommands.ts +++ b/src/lib/kclCommands.ts @@ -28,16 +28,17 @@ import type { CommandBarContext } from '@src/machines/commandBarMachine' import { IS_NIGHTLY_OR_DEBUG } from '@src/routes/utils' interface OnSubmitProps { - sampleName: string - code: string - sampleUnits?: UnitLength_type + name: string + content?: string + targetPathToClone?: string method: 'overwrite' | 'newFile' + source: 'kcl-samples' | 'local' } interface KclCommandConfig { // TODO: find a different approach that doesn't require // special props for a single command - specialPropsForSampleCommand: { + specialPropsForLoadCommand: { onSubmit: (p: OnSubmitProps) => Promise providedOptions: CommandArgumentOption[] } @@ -170,69 +171,108 @@ export function kclCommands(commandProps: KclCommandConfig): Command[] { }, }, { - name: 'open-kcl-example', - displayName: 'Open sample', - description: 'Imports an example KCL program into the editor.', + name: 'load-external-model', + displayName: 'Load external model', + description: + 'Loads a model from an external source into the current project.', needsReview: true, - icon: 'code', + icon: 'importFile', reviewMessage: ({ argumentsToSubmit }) => - CommandBarOverwriteWarning({ - heading: - 'method' in argumentsToSubmit && - argumentsToSubmit.method === 'newFile' - ? 'Create a new file from sample?' - : 'Overwrite current file with sample?', - message: - 'method' in argumentsToSubmit && - argumentsToSubmit.method === 'newFile' - ? 'This will create a new file in the current project and open it.' - : 'This will erase your current file and load the sample part.', - }), + argumentsToSubmit['method'] === 'overwrite' + ? CommandBarOverwriteWarning({ + heading: 'Overwrite current file with sample?', + message: + 'This will erase your current file and load the sample part.', + }) + : 'This will create a new file in the current project and open it.', groupId: 'code', onSubmit(data) { - if (!data?.sample) { - return + if (!data) { + return new Error('No input data') } - const pathParts = data.sample.split('/') - const projectPathPart = pathParts[0] - const primaryKclFile = pathParts[1] - // local only - const sampleCodeUrl = - (isDesktop() ? '.' : '') + - `/kcl-samples/${encodeURIComponent( - projectPathPart - )}/${encodeURIComponent(primaryKclFile)}` - fetch(sampleCodeUrl) - .then(async (codeResponse): Promise => { - if (!codeResponse.ok) { - console.error( - 'Failed to fetch sample code:', - codeResponse.statusText - ) - return Promise.reject(new Error('Failed to fetch sample code')) - } - const code = await codeResponse.text() - return { - sampleName: data.sample.split('/')[0] + FILE_EXT, - code, - method: data.method, - } - }) - .then((props) => { - if (props?.code) { - commandProps.specialPropsForSampleCommand - .onSubmit(props) + const { method, source, sample, path } = data + if (source === 'local' && path) { + commandProps.specialPropsForLoadCommand + .onSubmit({ + name: '', + targetPathToClone: path, + method, + source, + }) + .catch(reportError) + } else if (source === 'kcl-samples' && sample) { + const pathParts = sample.split('/') + const projectPathPart = pathParts[0] + const primaryKclFile = pathParts[1] + // local only + const sampleCodeUrl = + (isDesktop() ? '.' : '') + + `/kcl-samples/${encodeURIComponent( + projectPathPart + )}/${encodeURIComponent(primaryKclFile)}` + + fetch(sampleCodeUrl) + .then(async (codeResponse) => { + if (!codeResponse.ok) { + console.error( + 'Failed to fetch sample code:', + codeResponse.statusText + ) + return Promise.reject(new Error('Failed to fetch sample code')) + } + const code = await codeResponse.text() + commandProps.specialPropsForLoadCommand + .onSubmit({ + name: data.sample.split('/')[0] + FILE_EXT, + content: code, + source, + method, + }) .catch(reportError) - } - }) - .catch(reportError) + }) + .catch(reportError) + } else { + toast.error("The command couldn't be submitted, check the arguments.") + } }, args: { - method: { + source: { inputType: 'options', required: true, + skip: false, + defaultValue: 'local', + hidden: !isDesktop(), + options() { + return [ + { + value: 'kcl-samples', + name: 'KCL Samples', + isCurrent: true, + }, + ...(isDesktop() + ? [ + { + value: 'local', + name: 'Local Drive', + isCurrent: false, + }, + ] + : []), + ] + }, + }, + method: { + inputType: 'options', skip: true, + required: (commandContext) => + !['local'].includes( + commandContext.argumentsToSubmit.source as string + ), + hidden: (commandContext) => + ['local'].includes( + commandContext.argumentsToSubmit.source as string + ), defaultValue: isDesktop() ? 'newFile' : 'overwrite', options() { return [ @@ -255,7 +295,14 @@ export function kclCommands(commandProps: KclCommandConfig): Command[] { }, sample: { inputType: 'options', - required: true, + required: (commandContext) => + !['local'].includes( + commandContext.argumentsToSubmit.source as string + ), + hidden: (commandContext) => + ['local'].includes( + commandContext.argumentsToSubmit.source as string + ), valueSummary(value) { const MAX_LENGTH = 12 if (typeof value === 'string') { @@ -265,7 +312,15 @@ export function kclCommands(commandProps: KclCommandConfig): Command[] { } return value }, - options: commandProps.specialPropsForSampleCommand.providedOptions, + options: commandProps.specialPropsForLoadCommand.providedOptions, + }, + path: { + inputType: 'path', + valueSummary: (value) => window.electron.path.basename(value), + required: (commandContext) => + ['local'].includes( + commandContext.argumentsToSubmit.source as string + ), }, }, }, diff --git a/src/lib/toolbar.ts b/src/lib/toolbar.ts index 5c33f9199..b8826d19b 100644 --- a/src/lib/toolbar.ts +++ b/src/lib/toolbar.ts @@ -3,6 +3,7 @@ import type { EventFrom, StateFrom } from 'xstate' import type { CustomIconName } from '@src/components/CustomIcon' import { createLiteral } from '@src/lang/create' +import { isDesktop } from '@src/lib/isDesktop' import { commandBarActor } from '@src/machines/commandBarMachine' import type { modelingMachine } from '@src/machines/modelingMachine' import { @@ -337,6 +338,50 @@ export const toolbarConfig: Record = { links: [{ label: 'KCL docs', url: 'https://zoo.dev/docs/kcl/helix' }], }, 'break', + { + id: 'modules', + array: [ + { + id: 'insert', + onClick: () => + commandBarActor.send({ + type: 'Find and select command', + data: { name: 'Insert', groupId: 'code' }, + }), + hotkey: 'I', + icon: 'import', + status: DEV || IS_NIGHTLY_OR_DEBUG ? 'available' : 'kcl-only', + disabled: () => !isDesktop(), + title: 'Insert', + description: 'Insert from a file in the current project directory', + links: [ + { + label: 'API docs', + url: 'https://zoo.dev/docs/kcl/import', + }, + ], + }, + { + id: 'transform', + icon: 'angle', + status: 'kcl-only', + title: 'Transform', + description: 'Apply a translation and/or rotation to a module', + onClick: () => undefined, + links: [ + { + label: 'API docs', + url: 'https://zoo.dev/docs/kcl/translate', + }, + { + label: 'API docs', + url: 'https://zoo.dev/docs/kcl/rotate', + }, + ], + }, + ], + }, + 'break', { id: 'ai', array: [ diff --git a/src/menu/channels.ts b/src/menu/channels.ts index 27dbec6e4..4e744d8e8 100644 --- a/src/menu/channels.ts +++ b/src/menu/channels.ts @@ -24,8 +24,7 @@ export type MenuLabels = | 'File.Sign out' | 'File.Create new file' | 'File.Create new folder' - | 'File.Load a sample model' - | 'File.Insert from project file' + | 'File.Load external model' | 'File.Export current part' | 'File.Share current part (via Zoo link)' | 'File.Preferences.Project settings' @@ -40,6 +39,7 @@ export type MenuLabels = | 'Design.Apply modification feature.Fillet' | 'Design.Apply modification feature.Chamfer' | 'Design.Apply modification feature.Shell' + | 'Design.Insert from project file' | 'Design.Create with Zoo Text-To-CAD' | 'Design.Modify with Zoo Text-To-CAD' | 'View.Command Palette...' diff --git a/src/menu/designRole.ts b/src/menu/designRole.ts index c807d1bb5..74eb6ba66 100644 --- a/src/menu/designRole.ts +++ b/src/menu/designRole.ts @@ -122,6 +122,16 @@ export const modelingDesignRole = ( ], }, { type: 'separator' }, + { + label: 'Insert from project file', + id: 'Design.Insert from project file', + click: () => { + typeSafeWebContentsSend(mainWindow, 'menu-action-clicked', { + menuLabel: 'Design.Insert from project file', + }) + }, + }, + { type: 'separator' }, { label: 'Create with Zoo Text-To-CAD', id: 'Design.Create with Zoo Text-To-CAD', diff --git a/src/menu/fileRole.ts b/src/menu/fileRole.ts index eedd6e866..211b2c481 100644 --- a/src/menu/fileRole.ts +++ b/src/menu/fileRole.ts @@ -148,21 +148,11 @@ export const modelingFileRole = ( // Appears to be only Windows and Mac OS specific. Linux does not have support { type: 'separator' }, { - label: 'Load a sample model', - id: 'File.Load a sample model', + label: 'Load external model', + id: 'File.Load external model', click: () => { typeSafeWebContentsSend(mainWindow, 'menu-action-clicked', { - menuLabel: 'File.Load a sample model', - }) - }, - }, - { type: 'separator' }, - { - label: 'Insert from project file', - id: 'File.Insert from project file', - click: () => { - typeSafeWebContentsSend(mainWindow, 'menu-action-clicked', { - menuLabel: 'File.Insert from project file', + menuLabel: 'File.Load external model', }) }, }, diff --git a/src/menu/register.ts b/src/menu/register.ts index fd7a5c2c7..12bbbee3b 100644 --- a/src/menu/register.ts +++ b/src/menu/register.ts @@ -92,12 +92,12 @@ export function modelingMenuCallbackMostActions( }).catch(reportRejection) } else if (data.menuLabel === 'File.Preferences.User default units') { navigate(filePath + PATHS.SETTINGS_USER + '#defaultUnit') - } else if (data.menuLabel === 'File.Insert from project file') { + } else if (data.menuLabel === 'File.Load external model') { commandBarActor.send({ type: 'Find and select command', data: { groupId: 'code', - name: 'Insert', + name: 'load-external-model', }, }) } else if (data.menuLabel === 'File.Export current part') { @@ -108,14 +108,6 @@ export function modelingMenuCallbackMostActions( name: 'Export', }, }) - } else if (data.menuLabel === 'File.Load a sample model') { - commandBarActor.send({ - type: 'Find and select command', - data: { - groupId: 'code', - name: 'open-kcl-example', - }, - }) } else if (data.menuLabel === 'File.Create new file') { // NO OP. A safe command bar create new file is not implemented yet. } else if (data.menuLabel === 'Edit.Modify with Zoo Text-To-CAD') { @@ -256,6 +248,14 @@ export function modelingMenuCallbackMostActions( type: 'Find and select command', data: { name: 'Shell', groupId: 'modeling' }, }) + } else if (data.menuLabel === 'Design.Insert from project file') { + commandBarActor.send({ + type: 'Find and select command', + data: { + groupId: 'code', + name: 'Insert', + }, + }) } else if (data.menuLabel === 'Design.Create with Zoo Text-To-CAD') { commandBarActor.send({ type: 'Find and select command', diff --git a/src/menu/roles.ts b/src/menu/roles.ts index 513514ee1..6925427ab 100644 --- a/src/menu/roles.ts +++ b/src/menu/roles.ts @@ -21,13 +21,12 @@ type FileRoleLabel = | 'Sign out' | 'Theme' | 'Theme color' - | 'Insert from project file' | 'Export current part' | 'Create new file' | 'Create new folder' | 'Share current part (via Zoo link)' | 'Project settings' - | 'Load a sample model' + | 'Load external model' | 'User default units' type EditRoleLabel = @@ -82,6 +81,7 @@ type ViewRoleLabel = type DesignRoleLabel = | 'Design' | 'Create a parameter' + | 'Insert from project file' | 'Create with Zoo Text-To-CAD' | 'Start sketch' | 'Create an offset plane'