Compare commits

...

4 Commits

Author SHA1 Message Date
cccb71fd30 Set initial window size depending on screen size (#5845)
* set initial electron window size to be almost full screen with some space left

* refine initial window size and position

* slightly larger

* A snapshot a day keeps the bugs away! 📷🐛

* A snapshot a day keeps the bugs away! 📷🐛

* A snapshot a day keeps the bugs away! 📷🐛

* A snapshot a day keeps the bugs away! 📷🐛

* A snapshot a day keeps the bugs away! 📷🐛

* A snapshot a day keeps the bugs away! 📷🐛

* A snapshot a day keeps the bugs away! 📷🐛

* A snapshot a day keeps the bugs away! 📷🐛

---------

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2025-03-18 15:39:04 -04:00
44be072d04 Fix deep links and double clicks on second instance (#5865)
* Deep links or double clicks don't work on second instance on Windows
Fixes #5864

* A snapshot a day keeps the bugs away! 📷🐛

---------

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2025-03-18 15:17:21 -04:00
86beb6ebf1 Improve local setup instructions (#5860)
* Fix overwrite confirmation on existing wasm-pack

* Recommend using local .env for overrides
2025-03-18 14:39:02 -04:00
6d72104faa fix unused vars and imports (#5852)
* update eslintrc, and fix most of the errors

* more

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* fix last one

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* fixes

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* updates

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* A snapshot a day keeps the bugs away! 📷🐛

---------

Signed-off-by: Jess Frazelle <github@jessfraz.com>
Co-authored-by: Jess Frazelle <github@jessfraz.com>
Co-authored-by: Jess Frazelle <jessfraz@users.noreply.github.com>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2025-03-18 09:52:10 -07:00
64 changed files with 87 additions and 217 deletions

View File

@ -22,6 +22,13 @@
"rules": { "rules": {
"@typescript-eslint/no-floating-promises": "error", "@typescript-eslint/no-floating-promises": "error",
"@typescript-eslint/no-misused-promises": "error", "@typescript-eslint/no-misused-promises": "error",
"@typescript-eslint/no-unused-vars": ["error", {
"varsIgnorePattern": "^_",
"argsIgnorePattern": "^_",
"ignoreRestSiblings": true,
"vars": "all",
"args": "none"
}],
"jsx-a11y/click-events-have-key-events": "off", "jsx-a11y/click-events-have-key-events": "off",
"jsx-a11y/no-autofocus": "off", "jsx-a11y/no-autofocus": "off",
"jsx-a11y/no-noninteractive-element-interactions": "off", "jsx-a11y/no-noninteractive-element-interactions": "off",

View File

@ -105,7 +105,7 @@ Finally, to run the web app only, run:
yarn start yarn start
``` ```
If you're not a Zoo employee you won't be able to access the dev environment, you should copy everything from `.env.production` to `.env.development` to make it point to production instead, then when you navigate to `localhost:3000` the easiest way to sign in is to paste `localStorage.setItem('TOKEN_PERSIST_KEY', "your-token-from-https://zoo.dev/account/api-tokens")` replacing the with a real token from https://zoo.dev/account/api-tokens of course, then navigate to localhost:3000 again. Note that navigating to `localhost:3000/signin` removes your token so you will need to set the token again. If you're not a Zoo employee you won't be able to access the dev environment, you should copy everything from `.env.production` to `.env.development.local` to make it point to production instead, then when you navigate to `localhost:3000` the easiest way to sign in is to paste `localStorage.setItem('TOKEN_PERSIST_KEY', "your-token-from-https://zoo.dev/account/api-tokens")` replacing the with a real token from https://zoo.dev/account/api-tokens of course, then navigate to `localhost:3000` again. Note that navigating to `localhost:3000/signin` removes your token so you will need to set the token again.
### Development environment variables ### Development environment variables
@ -122,7 +122,7 @@ Third-Party Cookies".
## Desktop ## Desktop
To spin up the desktop app, `yarn install` and `yarn build:wasm` need to have been done before hand then To spin up the desktop app, `yarn install` and `yarn build:wasm` need to have been done before hand then:
``` ```
yarn tron:start yarn tron:start
@ -130,13 +130,13 @@ yarn tron:start
This will start the application and hot-reload on changes. This will start the application and hot-reload on changes.
Devtools can be opened with the usual Cmd-Opt-I (Mac) or Ctrl-Shift-I (Linux and Windows). Devtools can be opened with the usual Command-Option-I (macOS) or Ctrl-Shift-I (Linux and Windows).
To package the app for your platform with electron-builder, run `yarn tronb:package:dev` (or `yarn tronb:package:prod` to point to the .env.production variables) To package the app for your platform with electron-builder, run `yarn tronb:package:dev` (or `yarn tronb:package:prod` to point to the .env.production variables).
## Checking out commits / Bisecting ## Checking out commits / Bisecting
Which commands from setup are one off vs need to be run every time? Which commands from setup are one off vs. need to be run every time?
The following will need to be run when checking out a new commit and guarantees the build is not stale: The following will need to be run when checking out a new commit and guarantees the build is not stale:

View File

@ -100,7 +100,8 @@ test(
try { try {
const outputGltf = await fsp.readFile(firstFileFullPath) const outputGltf = await fsp.readFile(firstFileFullPath)
return outputGltf.byteLength return outputGltf.byteLength
} catch (e) { } catch (error: unknown) {
void error
return 0 return 0
} }
}, },
@ -179,7 +180,8 @@ test(
try { try {
const outputGltf = await fsp.readFile(secondFileFullPath) const outputGltf = await fsp.readFile(secondFileFullPath)
return outputGltf.byteLength return outputGltf.byteLength
} catch (e) { } catch (error: unknown) {
void error
return 0 return 0
} }
}, },

View File

@ -1197,7 +1197,7 @@ test.describe('Undo and redo do not keep history when navigating between files',
`cloned file has an incremented name and same contents`, `cloned file has an incremented name and same contents`,
{ tag: '@electron' }, { tag: '@electron' },
async ({ page, context, homePage }, testInfo) => { async ({ page, context, homePage }, testInfo) => {
const { panesOpen, createNewFile, cloneFile } = await getUtils(page, test) const { panesOpen, cloneFile } = await getUtils(page, test)
const { dir } = await context.folderSetupFn(async (dir) => { const { dir } = await context.folderSetupFn(async (dir) => {
const finalDir = join(dir, 'testDefault') const finalDir = join(dir, 'testDefault')

View File

@ -3,25 +3,15 @@
import type { import type {
BrowserContext, BrowserContext,
ElectronApplication, ElectronApplication,
Fixtures as PlaywrightFixtures,
TestInfo, TestInfo,
Page, Page,
} from '@playwright/test' } from '@playwright/test'
import { import { _electron as electron } from '@playwright/test'
_electron as electron,
PlaywrightTestArgs,
PlaywrightWorkerArgs,
} from '@playwright/test'
import * as TOML from '@iarna/toml' import * as TOML from '@iarna/toml'
import { import { TEST_SETTINGS } from '../storageStates'
TEST_SETTINGS_KEY, import { SETTINGS_FILE_NAME } from 'lib/constants'
TEST_SETTINGS_CORRUPTED,
TEST_SETTINGS,
TEST_SETTINGS_DEFAULT_THEME,
} from '../storageStates'
import { SETTINGS_FILE_NAME, PROJECT_SETTINGS_FILE_NAME } from 'lib/constants'
import { getUtils, setup } from '../test-utils' import { getUtils, setup } from '../test-utils'
import fsp from 'fs/promises' import fsp from 'fs/promises'
import fs from 'node:fs' import fs from 'node:fs'
@ -31,7 +21,6 @@ import { EditorFixture } from './editorFixture'
import { ToolbarFixture } from './toolbarFixture' import { ToolbarFixture } from './toolbarFixture'
import { SceneFixture } from './sceneFixture' import { SceneFixture } from './sceneFixture'
import { HomePageFixture } from './homePageFixture' import { HomePageFixture } from './homePageFixture'
import { unsafeTypedKeys } from 'lib/utils'
import { DeepPartial } from 'lib/types' import { DeepPartial } from 'lib/types'
import { Settings } from '@rust/kcl-lib/bindings/Settings' import { Settings } from '@rust/kcl-lib/bindings/Settings'
@ -278,13 +267,14 @@ export class ElectronZoo {
if (fs.existsSync(this.projectDirName)) { if (fs.existsSync(this.projectDirName)) {
await fsp.rm(this.projectDirName, { recursive: true }) await fsp.rm(this.projectDirName, { recursive: true })
} }
} catch (e) { } catch (_e) {
console.error(e) console.error(_e)
} }
try { try {
await fsp.mkdir(this.projectDirName) await fsp.mkdir(this.projectDirName)
} catch (e) { } catch (error: unknown) {
void error
// Not a problem if it already exists. // Not a problem if it already exists.
} }

View File

@ -1906,7 +1906,6 @@ extrude001 = extrude(sketch001, length = -12)
// Locators // Locators
const firstEdgeLocation = { x: 600, y: 193 } const firstEdgeLocation = { x: 600, y: 193 }
const secondEdgeLocation = { x: 600, y: 383 } const secondEdgeLocation = { x: 600, y: 383 }
const bodyLocation = { x: 630, y: 290 }
const [clickOnFirstEdge] = scene.makeMouseHelpers( const [clickOnFirstEdge] = scene.makeMouseHelpers(
firstEdgeLocation.x, firstEdgeLocation.x,
firstEdgeLocation.y firstEdgeLocation.y
@ -1919,7 +1918,6 @@ extrude001 = extrude(sketch001, length = -12)
// Colors // Colors
const edgeColorWhite: [number, number, number] = [248, 248, 248] const edgeColorWhite: [number, number, number] = [248, 248, 248]
const edgeColorYellow: [number, number, number] = [251, 251, 40] // Mac:B=67 Ubuntu:B=12 const edgeColorYellow: [number, number, number] = [251, 251, 40] // Mac:B=67 Ubuntu:B=12
const bodyColor: [number, number, number] = [155, 155, 155]
const chamferColor: [number, number, number] = [168, 168, 168] const chamferColor: [number, number, number] = [168, 168, 168]
const backgroundColor: [number, number, number] = [30, 30, 30] const backgroundColor: [number, number, number] = [30, 30, 30]
const lowTolerance = 20 const lowTolerance = 20

View File

@ -539,7 +539,8 @@ test.describe('Can export from electron app', () => {
try { try {
const outputGltf = await fsp.readFile(filepath) const outputGltf = await fsp.readFile(filepath)
return outputGltf.byteLength return outputGltf.byteLength
} catch (e) { } catch (error: unknown) {
void error
return 0 return 0
} }
}, },

View File

@ -14,7 +14,8 @@ try {
// prefer env vars over secrets file // prefer env vars over secrets file
secrets[key] = process.env[key] || (value as any).replaceAll('"', '') secrets[key] = process.env[key] || (value as any).replaceAll('"', '')
}) })
} catch (err) { } catch (error: unknown) {
void error
// probably running in CI // probably running in CI
console.warn( console.warn(
`Error reading ${secretsPath}; environment variables will be used` `Error reading ${secretsPath}; environment variables will be used`

View File

@ -2626,11 +2626,6 @@ extrude003 = extrude(profile011, length = 2.5)
{ x: 834, y: -680, z: 534 }, { x: 834, y: -680, z: 534 },
{ x: -54, y: -476, z: 148 } { x: -54, y: -476, z: 148 }
) )
const camPositionForSelectingSketchOnCapProfiles = () =>
scene.moveCameraTo(
{ x: 404, y: 690, z: 38 },
{ x: 16, y: -140, z: -10 }
)
const wallSelectionOptions = [ const wallSelectionOptions = [
{ {
title: 'select wall segment', title: 'select wall segment',
@ -2653,29 +2648,6 @@ extrude003 = extrude(profile011, length = 2.5)
selectClick: scene.makeMouseHelpers(836, 103)[0], selectClick: scene.makeMouseHelpers(836, 103)[0],
}, },
] as const ] as const
const capSelectionOptions = [
{
title: 'select cap segment',
selectClick: scene.makeMouseHelpers(688, 91)[0],
},
{
title: 'select cap solid 2d',
selectClick: scene.makeMouseHelpers(733, 204)[0],
},
// TODO keeps failing
// {
// title: 'select cap circle',
// selectClick: scene.makeMouseHelpers(679, 290)[0],
// },
{
title: 'select cap extrude wall',
selectClick: scene.makeMouseHelpers(649, 402)[0],
},
{
title: 'select cap extrude cap',
selectClick: scene.makeMouseHelpers(693, 408)[0],
},
] as const
const verifyWallProfilesAreDrawn = async () => const verifyWallProfilesAreDrawn = async () =>
test.step('verify wall profiles are drawn', async () => { test.step('verify wall profiles are drawn', async () => {
@ -2697,44 +2669,6 @@ extrude003 = extrude(profile011, length = 2.5)
]) ])
}) })
const verifyCapProfilesAreDrawn = async () =>
test.step('verify cap profiles are drawn', async () => {
// open polygon
await scene.expectPixelColor(
TEST_COLORS.WHITE,
// TEST_COLORS.BLUE, // When entering via the circle, it's selected and therefore blue
{ x: 620, y: 58 },
15
)
// revolved profile
await scene.expectPixelColor(
TEST_COLORS.WHITE,
{ x: 641, y: 110 },
15
)
// closed polygon
await scene.expectPixelColor(
TEST_COLORS.WHITE,
{ x: 632, y: 200 },
15
)
// extruded profile
await scene.expectPixelColor(
TEST_COLORS.WHITE,
{ x: 628, y: 410 },
15
)
// circle
await scene.expectPixelColor(
[
TEST_COLORS.WHITE,
TEST_COLORS.BLUE, // When entering via the circle, it's selected and therefore blue
],
{ x: 681, y: 303 },
15
)
})
await test.step('select wall profiles', async () => { await test.step('select wall profiles', async () => {
for (const { title, selectClick } of wallSelectionOptions) { for (const { title, selectClick } of wallSelectionOptions) {
await test.step(title, async () => { await test.step(title, async () => {

View File

@ -7,12 +7,7 @@ import { spawn } from 'child_process'
import { KCL_DEFAULT_LENGTH } from 'lib/constants' import { KCL_DEFAULT_LENGTH } from 'lib/constants'
import JSZip from 'jszip' import JSZip from 'jszip'
import path from 'path' import path from 'path'
import { import { TEST_SETTINGS, TEST_SETTINGS_KEY } from './storageStates'
IS_PLAYWRIGHT_KEY,
TEST_SETTINGS,
TEST_SETTINGS_KEY,
} from './storageStates'
import * as TOML from '@iarna/toml'
import { SceneFixture } from './fixtures/sceneFixture' import { SceneFixture } from './fixtures/sceneFixture'
import { CmdBarFixture } from './fixtures/cmdBarFixture' import { CmdBarFixture } from './fixtures/cmdBarFixture'

Binary file not shown.

Before

Width:  |  Height:  |  Size: 55 KiB

After

Width:  |  Height:  |  Size: 55 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 67 KiB

After

Width:  |  Height:  |  Size: 68 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 34 KiB

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 54 KiB

After

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 52 KiB

After

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 66 KiB

After

Width:  |  Height:  |  Size: 66 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 143 KiB

After

Width:  |  Height:  |  Size: 143 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 74 KiB

After

Width:  |  Height:  |  Size: 74 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 72 KiB

After

Width:  |  Height:  |  Size: 72 KiB

View File

@ -1,4 +1,3 @@
import { MouseControlType } from '@rust/kcl-lib/bindings/MouseControlType'
import { Settings } from '@rust/kcl-lib/bindings/Settings' import { Settings } from '@rust/kcl-lib/bindings/Settings'
import { SaveSettingsPayload } from 'lib/settings/settingsTypes' import { SaveSettingsPayload } from 'lib/settings/settingsTypes'
import { Themes } from 'lib/theme' import { Themes } from 'lib/theme'

View File

@ -2,15 +2,12 @@ import {
expect, expect,
BrowserContext, BrowserContext,
TestInfo, TestInfo,
_electron as electron,
ElectronApplication,
Locator, Locator,
Page, Page,
} from '@playwright/test' } from '@playwright/test'
import { test } from './zoo-test' import { test } from './zoo-test'
import { EngineCommand } from 'lang/std/artifactGraph' import { EngineCommand } from 'lang/std/artifactGraph'
import fsp from 'fs/promises' import fsp from 'fs/promises'
import fsSync from 'fs'
import path from 'path' import path from 'path'
import pixelMatch from 'pixelmatch' import pixelMatch from 'pixelmatch'
import { PNG } from 'pngjs' import { PNG } from 'pngjs'
@ -24,14 +21,11 @@ import {
IS_PLAYWRIGHT_KEY, IS_PLAYWRIGHT_KEY,
} from './storageStates' } from './storageStates'
import * as TOML from '@iarna/toml' import * as TOML from '@iarna/toml'
import { SaveSettingsPayload } from 'lib/settings/settingsTypes'
import { SETTINGS_FILE_NAME } from 'lib/constants'
import { isErrorWhitelisted } from './lib/console-error-whitelist' import { isErrorWhitelisted } from './lib/console-error-whitelist'
import { isArray } from 'lib/utils' import { isArray } from 'lib/utils'
import { reportRejection } from 'lib/trap' import { reportRejection } from 'lib/trap'
import { DeepPartial } from 'lib/types' import { DeepPartial } from 'lib/types'
import { Configuration } from 'lang/wasm' import { Configuration } from 'lang/wasm'
import { Settings } from '@rust/kcl-lib/bindings/Settings'
const toNormalizedCode = (text: string) => { const toNormalizedCode = (text: string) => {
return text.replace(/\s+/g, '') return text.replace(/\s+/g, '')
@ -928,10 +922,6 @@ export async function setup(
// await page.reload() // await page.reload()
} }
let electronApp: ElectronApplication | undefined = undefined
let context: BrowserContext | undefined = undefined
let page: Page | undefined = undefined
function failOnConsoleErrors(page: Page, testInfo?: TestInfo) { function failOnConsoleErrors(page: Page, testInfo?: TestInfo) {
// enabled for chrome for now // enabled for chrome for now
if (page.context().browser()?.browserType().name() === 'chromium') { if (page.context().browser()?.browserType().name() === 'chromium') {

View File

@ -4,7 +4,6 @@ import { bracket } from 'lib/exampleKcl'
import * as fsp from 'fs/promises' import * as fsp from 'fs/promises'
import { join } from 'path' import { join } from 'path'
import { FILE_EXT } from 'lib/constants' import { FILE_EXT } from 'lib/constants'
import { UnitLength_type } from '@kittycad/lib/dist/types/src/models'
test.describe('Testing in-app sample loading', () => { test.describe('Testing in-app sample loading', () => {
/** /**
@ -49,8 +48,6 @@ test.describe('Testing in-app sample loading', () => {
}) })
const warningText = page.getByText('Overwrite current file and units?') const warningText = page.getByText('Overwrite current file and units?')
const confirmButton = page.getByRole('button', { name: 'Submit command' }) const confirmButton = page.getByRole('button', { name: 'Submit command' })
const unitsToast = (unit: UnitLength_type) =>
page.getByText(`Set default unit to "${unit}" for this project`)
await test.step(`Precondition: check the initial code`, async () => { await test.step(`Precondition: check the initial code`, async () => {
await u.openKclCodePanel() await u.openKclCodePanel()
@ -125,8 +122,6 @@ test.describe('Testing in-app sample loading', () => {
page.getByRole('listitem').filter({ page.getByRole('listitem').filter({
has: page.getByRole('button', { name }), has: page.getByRole('button', { name }),
}) })
const unitsToast = (unit: UnitLength_type) =>
page.getByText(`Set default unit to "${unit}" for this project`)
await test.step(`Test setup`, async () => { await test.step(`Test setup`, async () => {
await page.setBodyDimensions({ width: 1200, height: 500 }) await page.setBodyDimensions({ width: 1200, height: 500 })

View File

@ -1386,7 +1386,8 @@ profile001 = startProfileAt([56.37, 120.33], sketch001)
page.getByRole('button', { name: 'Edit Sketch' }) page.getByRole('button', { name: 'Edit Sketch' })
).toBeVisible() ).toBeVisible()
return true return true
} catch (_) { // eslint-disable-next-line @typescript-eslint/no-unused-vars
} catch (_e) {
return false return false
} }
}) })

View File

@ -364,7 +364,6 @@ profile003 = startProfileAt([40.16, -120.48], sketch006)
await camPosition1() await camPosition1()
const revolve = { x: 635, y: 253 } const revolve = { x: 635, y: 253 }
const parentExtrude = { x: 915, y: 133 }
const solid2d = { x: 770, y: 167 } const solid2d = { x: 770, y: 167 }
const individualProfile = { x: 694, y: 432 } const individualProfile = { x: 694, y: 432 }

View File

@ -7,7 +7,7 @@ import {
createProject, createProject,
tomlToSettings, tomlToSettings,
} from './test-utils' } from './test-utils'
import { SaveSettingsPayload, SettingsLevel } from 'lib/settings/settingsTypes' import { SettingsLevel } from 'lib/settings/settingsTypes'
import { SETTINGS_FILE_NAME, PROJECT_SETTINGS_FILE_NAME } from 'lib/constants' import { SETTINGS_FILE_NAME, PROJECT_SETTINGS_FILE_NAME } from 'lib/constants'
import { import {
TEST_SETTINGS_KEY, TEST_SETTINGS_KEY,
@ -15,7 +15,6 @@ import {
TEST_SETTINGS, TEST_SETTINGS,
TEST_SETTINGS_DEFAULT_THEME, TEST_SETTINGS_DEFAULT_THEME,
} from './storageStates' } from './storageStates'
import * as TOML from '@iarna/toml'
import { DeepPartial } from 'lib/types' import { DeepPartial } from 'lib/types'
import { Settings } from '@rust/kcl-lib/bindings/Settings' import { Settings } from '@rust/kcl-lib/bindings/Settings'
@ -1006,11 +1005,6 @@ fn cube`
page.getByText( page.getByText(
`Set highlight edges to "${String(value)}" as a user default` `Set highlight edges to "${String(value)}" as a user default`
) )
const initialPath = testInfo.snapshotPath('toggle-settings-initial.png')
const initialScreenshot = await scene.streamWrapper.screenshot({
path: initialPath,
mask: [page.getByTestId('model-state-indicator')],
})
await test.step(`Toggle highlightEdges off`, async () => { await test.step(`Toggle highlightEdges off`, async () => {
await cmdBar.openCmdBar() await cmdBar.openCmdBar()

View File

@ -1,6 +1,6 @@
/* eslint-disable react-hooks/rules-of-hooks */ /* eslint-disable react-hooks/rules-of-hooks */
import { test as playwrightTestFn, ElectronApplication } from '@playwright/test' import { test as playwrightTestFn } from '@playwright/test'
import { import {
fixturesBasedOnProcessEnvPlatform, fixturesBasedOnProcessEnvPlatform,
@ -8,8 +8,6 @@ import {
ElectronZoo, ElectronZoo,
} from './fixtures/fixtureSetup' } from './fixtures/fixtureSetup'
import { Settings } from '@rust/kcl-lib/bindings/Settings'
import { DeepPartial } from 'lib/types'
export { expect } from '@playwright/test' export { expect } from '@playwright/test'
declare module '@playwright/test' { declare module '@playwright/test' {

View File

@ -71,7 +71,7 @@
"scripts": { "scripts": {
"install:rust": "curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --default-toolchain none && source \"$HOME/.cargo/env\" && (cd rust && (rustup show active-toolchain || rustup toolchain install))", "install:rust": "curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --default-toolchain none && source \"$HOME/.cargo/env\" && (cd rust && (rustup show active-toolchain || rustup toolchain install))",
"install:rust:windows": "winget install Microsoft.VisualStudio.2022.Community --silent --override \"--wait --quiet --add ProductLang En-us --add Microsoft.VisualStudio.Workload.NativeDesktop --includeRecommended\" && winget install Rustlang.Rustup", "install:rust:windows": "winget install Microsoft.VisualStudio.2022.Community --silent --override \"--wait --quiet --add ProductLang En-us --add Microsoft.VisualStudio.Workload.NativeDesktop --includeRecommended\" && winget install Rustlang.Rustup",
"install:wasm-pack:sh": ". $HOME/.cargo/env && curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh -s -- -y", "install:wasm-pack:sh": ". $HOME/.cargo/env && curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh -s -- -f",
"install:wasm-pack:cargo": "cargo install wasm-pack", "install:wasm-pack:cargo": "cargo install wasm-pack",
"install:tools:windows": "winget install jqlang.jq MikeFarah.yq GitHub.cli", "install:tools:windows": "winget install jqlang.jq MikeFarah.yq GitHub.cli",
"start": "vite --port=3000 --host=0.0.0.0", "start": "vite --port=3000 --host=0.0.0.0",

View File

@ -248,6 +248,7 @@ export class Ctx {
this.clientSubscriptions = [] this.clientSubscriptions = []
try { try {
await this._client?.dispose(2000) await this._client?.dispose(2000)
// eslint-disable-next-line @typescript-eslint/no-unused-vars
} catch (e) { } catch (e) {
// DO nothing. // DO nothing.
} }

View File

@ -1,4 +1,4 @@
import { useEffect, useMemo, useRef, useState } from 'react' import { useEffect, useMemo, useRef } from 'react'
import { useHotKeyListener } from './hooks/useHotKeyListener' import { useHotKeyListener } from './hooks/useHotKeyListener'
import { Stream } from './components/Stream' import { Stream } from './components/Stream'
import { AppHeader } from './components/AppHeader' import { AppHeader } from './components/AppHeader'
@ -60,7 +60,6 @@ export function App() {
const projectPath = project?.path || null const projectPath = project?.path || null
const [commands] = useEngineCommands() const [commands] = useEngineCommands()
const [capturedCanvas, setCapturedCanvas] = useState(false)
const loaderData = useRouteLoaderData(PATHS.FILE) as IndexLoaderData const loaderData = useRouteLoaderData(PATHS.FILE) as IndexLoaderData
const lastCommandType = commands[commands.length - 1]?.type const lastCommandType = commands[commands.length - 1]?.type
@ -109,11 +108,7 @@ export function App() {
// Generate thumbnail.png when loading the app // Generate thumbnail.png when loading the app
useEffect(() => { useEffect(() => {
if ( if (isDesktop() && lastCommandType === 'execution-done') {
isDesktop() &&
!capturedCanvas &&
lastCommandType === 'execution-done'
) {
setTimeout(() => { setTimeout(() => {
const projectDirectoryWithoutEndingSlash = loaderData?.project?.path const projectDirectoryWithoutEndingSlash = loaderData?.project?.path
if (!projectDirectoryWithoutEndingSlash) { if (!projectDirectoryWithoutEndingSlash) {

View File

@ -6,7 +6,7 @@ import { useEffect, useRef, useState } from 'react'
import { trap } from 'lib/trap' import { trap } from 'lib/trap'
import { codeToIdSelections } from 'lib/selections' import { codeToIdSelections } from 'lib/selections'
import { codeRefFromRange } from 'lang/std/artifactGraph' import { codeRefFromRange } from 'lang/std/artifactGraph'
import { defaultSourceRange, SourceRange, topLevelRange } from 'lang/wasm' import { defaultSourceRange, topLevelRange } from 'lang/wasm'
import { isArray } from 'lib/utils' import { isArray } from 'lib/utils'
export function AstExplorer() { export function AstExplorer() {

View File

@ -4,7 +4,6 @@ import {
Selections, Selections,
canSubmitSelectionArg, canSubmitSelectionArg,
getSelectionCountByType, getSelectionCountByType,
getSelectionTypeDisplayText,
} from 'lib/selections' } from 'lib/selections'
import { useSelector } from '@xstate/react' import { useSelector } from '@xstate/react'
import { commandBarActor, useCommandBarState } from 'machines/commandBarMachine' import { commandBarActor, useCommandBarState } from 'machines/commandBarMachine'

View File

@ -1,13 +1,9 @@
import { Dialog } from '@headlessui/react' import { Dialog } from '@headlessui/react'
import { ActionButton } from './ActionButton' import { ActionButton } from './ActionButton'
import { useState } from 'react' import { useState } from 'react'
import { useSearchParams } from 'react-router-dom'
import { CREATE_FILE_URL_PARAM } from 'lib/constants'
import { useSettings } from 'machines/appMachine' import { useSettings } from 'machines/appMachine'
const DownloadAppBanner = () => { const DownloadAppBanner = () => {
const [searchParams] = useSearchParams()
const hasCreateFileParam = searchParams.has(CREATE_FILE_URL_PARAM)
const settings = useSettings() const settings = useSettings()
const [isBannerDismissed, setIsBannerDismissed] = useState( const [isBannerDismissed, setIsBannerDismissed] = useState(
settings.app.dismissWebBanner.current settings.app.dismissWebBanner.current

View File

@ -111,7 +111,6 @@ import { commandBarActor } from 'machines/commandBarMachine'
import { useToken } from 'machines/appMachine' import { useToken } from 'machines/appMachine'
import { getNodePathFromSourceRange } from 'lang/queryAstNodePathUtils' import { getNodePathFromSourceRange } from 'lang/queryAstNodePathUtils'
import { useSettings } from 'machines/appMachine' import { useSettings } from 'machines/appMachine'
import { isDesktop } from 'lib/isDesktop'
type MachineContext<T extends AnyStateMachine> = { type MachineContext<T extends AnyStateMachine> = {
state: StateFrom<T> state: StateFrom<T>

View File

@ -4,12 +4,11 @@ import {
useLocation, useLocation,
useNavigate, useNavigate,
useRouteLoaderData, useRouteLoaderData,
redirect,
} from 'react-router-dom' } from 'react-router-dom'
import { PATHS } from 'lib/paths' import { PATHS } from 'lib/paths'
import { markOnce } from 'lib/performance' import { markOnce } from 'lib/performance'
import { useAuthNavigation } from 'hooks/useAuthNavigation' import { useAuthNavigation } from 'hooks/useAuthNavigation'
import { useAuthState, useSettings } from 'machines/appMachine' import { useSettings } from 'machines/appMachine'
import { IndexLoaderData } from 'lib/types' import { IndexLoaderData } from 'lib/types'
import { getAppSettingsFilePath } from 'lib/desktop' import { getAppSettingsFilePath } from 'lib/desktop'
import { isDesktop } from 'lib/isDesktop' import { isDesktop } from 'lib/isDesktop'
@ -17,9 +16,7 @@ import { trap } from 'lib/trap'
import { useFileSystemWatcher } from 'hooks/useFileSystemWatcher' import { useFileSystemWatcher } from 'hooks/useFileSystemWatcher'
import { loadAndValidateSettings } from 'lib/settings/settingsUtils' import { loadAndValidateSettings } from 'lib/settings/settingsUtils'
import { settingsActor } from 'machines/appMachine' import { settingsActor } from 'machines/appMachine'
import makeUrlPathRelative from 'lib/makeUrlPathRelative'
import { OnboardingStatus } from '@rust/kcl-lib/bindings/OnboardingStatus' import { OnboardingStatus } from '@rust/kcl-lib/bindings/OnboardingStatus'
import { SnapshotFrom } from 'xstate'
export const RouteProviderContext = createContext({}) export const RouteProviderContext = createContext({})
@ -35,7 +32,6 @@ export function RouteProvider({ children }: { children: ReactNode }) {
const location = useLocation() const location = useLocation()
const settings = useSettings() const settings = useSettings()
const authState = useAuthState()
useEffect(() => { useEffect(() => {
// On initialization, the react-router-dom does not send a 'loading' state event. // On initialization, the react-router-dom does not send a 'loading' state event.
// it sends an idle event first. // it sends an idle event first.

View File

@ -3,7 +3,6 @@ import { CustomIcon } from 'components/CustomIcon'
import decamelize from 'decamelize' import decamelize from 'decamelize'
import Fuse from 'fuse.js' import Fuse from 'fuse.js'
import { interactionMap } from 'lib/settings/initialKeybindings' import { interactionMap } from 'lib/settings/initialKeybindings'
import { Setting } from 'lib/settings/initialSettings'
import { SettingsLevel } from 'lib/settings/settingsTypes' import { SettingsLevel } from 'lib/settings/settingsTypes'
import { useSettings } from 'machines/appMachine' import { useSettings } from 'machines/appMachine'
import { useEffect, useMemo, useRef, useState } from 'react' import { useEffect, useMemo, useRef, useState } from 'react'

View File

@ -28,7 +28,7 @@ import { base64Decode } from 'lang/wasm'
import { sendTelemetry } from 'lib/textToCad' import { sendTelemetry } from 'lib/textToCad'
import { Themes } from 'lib/theme' import { Themes } from 'lib/theme'
import { ActionButton } from './ActionButton' import { ActionButton } from './ActionButton'
import { commandBarActor, commandBarMachine } from 'machines/commandBarMachine' import { commandBarActor } from 'machines/commandBarMachine'
import { EventFrom } from 'xstate' import { EventFrom } from 'xstate'
import { fileMachine } from 'machines/fileMachine' import { fileMachine } from 'machines/fileMachine'
import { reportRejection } from 'lib/trap' import { reportRejection } from 'lib/trap'

View File

@ -1,5 +1,5 @@
import { useLayoutEffect, useEffect, useRef } from 'react' import { useLayoutEffect, useEffect, useRef } from 'react'
import { engineCommandManager, kclManager } from 'lib/singletons' import { engineCommandManager } from 'lib/singletons'
import { deferExecution } from 'lib/utils' import { deferExecution } from 'lib/utils'
import { Themes } from 'lib/theme' import { Themes } from 'lib/theme'
import { useModelingContext } from './useModelingContext' import { useModelingContext } from './useModelingContext'
@ -93,10 +93,6 @@ export function useSetupEngineManager(
engineCommandManager.settings = settings engineCommandManager.settings = settings
const handleResize = deferExecution(() => { const handleResize = deferExecution(() => {
const { width, height } = getDimensions(
streamRef?.current?.offsetWidth ?? 0,
streamRef?.current?.offsetHeight ?? 0
)
engineCommandManager.handleResize(engineCommandManager.streamDimensions) engineCommandManager.handleResize(engineCommandManager.streamDimensions)
}, 500) }, 500)

View File

@ -324,6 +324,7 @@ export class KclManager {
if (this.wasmInitFailed) { if (this.wasmInitFailed) {
this.wasmInitFailed = false this.wasmInitFailed = false
} }
// eslint-disable-next-line @typescript-eslint/no-unused-vars
} catch (e) { } catch (e) {
this.wasmInitFailed = true this.wasmInitFailed = true
} }

View File

@ -7,7 +7,6 @@ import {
sketchFromKclValue, sketchFromKclValue,
defaultArtifactGraph, defaultArtifactGraph,
topLevelRange, topLevelRange,
VariableMap,
} from './wasm' } from './wasm'
import { enginelessExecutor } from '../lib/testHelpers' import { enginelessExecutor } from '../lib/testHelpers'
import { KCLError } from './errors' import { KCLError } from './errors'

View File

@ -5,7 +5,6 @@ import {
assertParse, assertParse,
initPromise, initPromise,
Parameter, Parameter,
SourceRange,
topLevelRange, topLevelRange,
} from './wasm' } from './wasm'
import { err } from 'lib/trap' import { err } from 'lib/trap'

View File

@ -38,6 +38,7 @@ afterAll(async () => {
try { try {
process.chdir('..') process.chdir('..')
await fs.rm(DIR_KCL_SAMPLES, { recursive: true }) await fs.rm(DIR_KCL_SAMPLES, { recursive: true })
// eslint-disable-next-line @typescript-eslint/no-unused-vars
} catch (e) {} } catch (e) {}
}) })

View File

@ -19,7 +19,6 @@ import {
BinaryExpression, BinaryExpression,
PathToNode, PathToNode,
SourceRange, SourceRange,
sketchFromKclValue,
isPathToNodeNumber, isPathToNodeNumber,
parse, parse,
formatNumber, formatNumber,
@ -75,7 +74,6 @@ import {
import { BodyItem } from '@rust/kcl-lib/bindings/BodyItem' import { BodyItem } from '@rust/kcl-lib/bindings/BodyItem'
import { findKwArg } from './util' import { findKwArg } from './util'
import { deleteEdgeTreatment } from './modifyAst/addEdgeTreatment' import { deleteEdgeTreatment } from './modifyAst/addEdgeTreatment'
import { codeManager } from 'lib/singletons'
export function startSketchOnDefault( export function startSketchOnDefault(
node: Node<Program>, node: Node<Program>,

View File

@ -13,8 +13,6 @@ import {
} from '../wasm' } from '../wasm'
import { import {
createCallExpressionStdLib, createCallExpressionStdLib,
createPipeSubstitution,
createObjectExpression,
createArrayExpression, createArrayExpression,
createIdentifier, createIdentifier,
createPipeExpression, createPipeExpression,

View File

@ -5,9 +5,6 @@ import {
PathToNode, PathToNode,
Identifier, Identifier,
topLevelRange, topLevelRange,
PipeExpression,
CallExpression,
VariableDeclarator,
} from './wasm' } from './wasm'
import { import {
findAllPreviousVariables, findAllPreviousVariables,

View File

@ -39,7 +39,7 @@ import {
import { err, Reason } from 'lib/trap' import { err, Reason } from 'lib/trap'
import { Node } from '@rust/kcl-lib/bindings/Node' import { Node } from '@rust/kcl-lib/bindings/Node'
import { findKwArg } from './util' import { findKwArg } from './util'
import { codeRefFromRange, getPlaneFromArtifact } from './std/artifactGraph' import { codeRefFromRange } from './std/artifactGraph'
import { FunctionExpression } from '@rust/kcl-lib/bindings/FunctionExpression' import { FunctionExpression } from '@rust/kcl-lib/bindings/FunctionExpression'
import { ImportStatement } from '@rust/kcl-lib/bindings/ImportStatement' import { ImportStatement } from '@rust/kcl-lib/bindings/ImportStatement'
import { KclSettingsAnnotation } from 'lib/settings/settingsTypes' import { KclSettingsAnnotation } from 'lib/settings/settingsTypes'
@ -595,6 +595,7 @@ export function isLinesParallelAndConstrained(
artifact: artifactGraph.get(prevSegment.__geoMeta.id), artifact: artifactGraph.get(prevSegment.__geoMeta.id),
}, },
} }
// eslint-disable-next-line @typescript-eslint/no-unused-vars
} catch (e) { } catch (e) {
return { return {
isParallelAndConstrained: false, isParallelAndConstrained: false,

View File

@ -1,5 +1,3 @@
import { isDesktop } from 'lib/isDesktop'
// Polyfill window.electron fs functions as needed when in a nodejs context // Polyfill window.electron fs functions as needed when in a nodejs context
// (INTENDED FOR VITEST SHINANGANS.) // (INTENDED FOR VITEST SHINANGANS.)
if (process.env.NODE_ENV === 'test' && process.env.VITEST) { if (process.env.NODE_ENV === 'test' && process.env.VITEST) {

View File

@ -19,7 +19,6 @@ import {
ARG_INDEX_FIELD, ARG_INDEX_FIELD,
getNodeFromPath, getNodeFromPath,
getNodeFromPathCurry, getNodeFromPathCurry,
getObjExprProperty,
LABELED_ARG_FIELD, LABELED_ARG_FIELD,
} from 'lang/queryAst' } from 'lang/queryAst'
import { getNodePathFromSourceRange } from 'lang/queryAstNodePathUtils' import { getNodePathFromSourceRange } from 'lang/queryAstNodePathUtils'
@ -629,7 +628,7 @@ export const lineTo: SketchLineHelperKw = {
}, },
updateArgs: ({ node, pathToNode, input }) => { updateArgs: ({ node, pathToNode, input }) => {
if (input.type !== 'straight-segment') return STRAIGHT_SEGMENT_ERR if (input.type !== 'straight-segment') return STRAIGHT_SEGMENT_ERR
const { to, from } = input const { to } = input
const _node = { ...node } const _node = { ...node }
const nodeMeta = getNodeFromPath<CallExpressionKw>(_node, pathToNode) const nodeMeta = getNodeFromPath<CallExpressionKw>(_node, pathToNode)
if (err(nodeMeta)) return nodeMeta if (err(nodeMeta)) return nodeMeta
@ -1675,7 +1674,7 @@ export const arcTo: SketchLineHelper = {
updateArgs: ({ node, pathToNode, input }) => { updateArgs: ({ node, pathToNode, input }) => {
if (input.type !== 'circle-three-point-segment') return ARC_SEGMENT_ERR if (input.type !== 'circle-three-point-segment') return ARC_SEGMENT_ERR
const { p1, p2, p3 } = input const { p2, p3 } = input
const _node = { ...node } const _node = { ...node }
const nodeMeta = getNodeFromPath<CallExpression>(_node, pathToNode) const nodeMeta = getNodeFromPath<CallExpression>(_node, pathToNode)
if (err(nodeMeta)) return nodeMeta if (err(nodeMeta)) return nodeMeta

View File

@ -16,7 +16,7 @@ import {
} from '../wasm' } from '../wasm'
import { err } from 'lib/trap' import { err } from 'lib/trap'
import { findKwArgAny } from 'lang/util' import { findKwArgAny } from 'lang/util'
import { ARG_END, ARG_END_ABSOLUTE, DETERMINING_ARGS } from './sketch' import { DETERMINING_ARGS } from './sketch'
export function getSketchSegmentFromPathToNode( export function getSketchSegmentFromPathToNode(
sketch: Sketch, sketch: Sketch,

View File

@ -26,7 +26,6 @@ import { Discovered } from '@rust/kcl-lib/bindings/Discovered'
import { KclValue } from '@rust/kcl-lib/bindings/KclValue' import { KclValue } from '@rust/kcl-lib/bindings/KclValue'
import type { Program } from '@rust/kcl-lib/bindings/Program' import type { Program } from '@rust/kcl-lib/bindings/Program'
import { Coords2d } from './std/sketch' import { Coords2d } from './std/sketch'
import { fileSystemManager } from 'lang/std/fileSystemManager'
import { CoreDumpInfo } from '@rust/kcl-lib/bindings/CoreDumpInfo' import { CoreDumpInfo } from '@rust/kcl-lib/bindings/CoreDumpInfo'
import { CoreDumpManager } from 'lib/coredump' import { CoreDumpManager } from 'lib/coredump'
import openWindow from 'lib/openWindow' import openWindow from 'lib/openWindow'
@ -318,7 +317,7 @@ export function execStateFromRust(
): ExecState { ): ExecState {
const artifactGraph = rustArtifactGraphToMap(execOutcome.artifactGraph) const artifactGraph = rustArtifactGraphToMap(execOutcome.artifactGraph)
// We haven't ported pathToNode logic to Rust yet, so we need to fill it in. // We haven't ported pathToNode logic to Rust yet, so we need to fill it in.
for (const [id, artifact] of artifactGraph) { for (const [_id, artifact] of artifactGraph) {
if (!artifact) continue if (!artifact) continue
if (!('codeRef' in artifact)) continue if (!('codeRef' in artifact)) continue
const pathToNode = getNodePathFromSourceRange( const pathToNode = getNodePathFromSourceRange(

View File

@ -3,11 +3,7 @@ import { angleLengthInfo } from 'components/Toolbar/setAngleLength'
import { transformAstSketchLines } from 'lang/std/sketchcombos' import { transformAstSketchLines } from 'lang/std/sketchcombos'
import { PathToNode } from 'lang/wasm' import { PathToNode } from 'lang/wasm'
import { StateMachineCommandSetConfig, KclCommandValue } from 'lib/commandTypes' import { StateMachineCommandSetConfig, KclCommandValue } from 'lib/commandTypes'
import { import { KCL_DEFAULT_LENGTH, KCL_DEFAULT_DEGREE } from 'lib/constants'
KCL_DEFAULT_LENGTH,
KCL_DEFAULT_DEGREE,
KCL_DEFAULT_COLOR,
} from 'lib/constants'
import { components } from 'lib/machine-api' import { components } from 'lib/machine-api'
import { Selections } from 'lib/selections' import { Selections } from 'lib/selections'
import { kclManager } from 'lib/singletons' import { kclManager } from 'lib/singletons'

View File

@ -8,9 +8,11 @@ import { MachineManager } from 'components/MachineManagerProvider'
import { Node } from '@rust/kcl-lib/bindings/Node' import { Node } from '@rust/kcl-lib/bindings/Node'
import { Artifact } from 'lang/std/artifactGraph' import { Artifact } from 'lang/std/artifactGraph'
import { CommandBarContext } from 'machines/commandBarMachine' import { CommandBarContext } from 'machines/commandBarMachine'
type Icon = CustomIconName type Icon = CustomIconName
const PLATFORMS = ['both', 'web', 'desktop'] as const const _PLATFORMS = ['both', 'web', 'desktop'] as const
const INPUT_TYPES = [ type PLATFORM = typeof _PLATFORMS
const _INPUT_TYPES = [
'options', 'options',
'string', 'string',
'text', 'text',
@ -19,6 +21,7 @@ const INPUT_TYPES = [
'selectionMixed', 'selectionMixed',
'boolean', 'boolean',
] as const ] as const
type INPUT_TYPE = typeof _INPUT_TYPES
export interface KclExpression { export interface KclExpression {
valueAst: Expr valueAst: Expr
valueText: string valueText: string
@ -31,7 +34,7 @@ export interface KclExpressionWithVariable extends KclExpression {
insertIndex: number insertIndex: number
} }
export type KclCommandValue = KclExpression | KclExpressionWithVariable export type KclCommandValue = KclExpression | KclExpressionWithVariable
export type CommandInputType = (typeof INPUT_TYPES)[number] export type CommandInputType = INPUT_TYPE[number]
export type StateMachineCommandSetSchema<T extends AnyStateMachine> = Partial<{ export type StateMachineCommandSetSchema<T extends AnyStateMachine> = Partial<{
[EventType in EventFrom<T>['type']]: Record<string, any> [EventType in EventFrom<T>['type']]: Record<string, any>
@ -86,7 +89,7 @@ export type Command<
displayName?: string displayName?: string
description?: string description?: string
icon?: Icon icon?: Icon
hide?: (typeof PLATFORMS)[number] hide?: PLATFORM[number]
} }
export type CommandConfig< export type CommandConfig<

View File

@ -1,4 +1,4 @@
import { ParseResult, VariableMap } from 'lang/wasm' import { ParseResult } from 'lang/wasm'
import { getCalculatedKclExpressionValue } from './kclHelpers' import { getCalculatedKclExpressionValue } from './kclHelpers'
describe('KCL expression calculations', () => { describe('KCL expression calculations', () => {

View File

@ -24,6 +24,7 @@ export class SafeRenderer extends Renderer {
prot = decodeURIComponent(unescape(href)) prot = decodeURIComponent(unescape(href))
.replace(/[^\w:]/g, '') .replace(/[^\w:]/g, '')
.toLowerCase() .toLowerCase()
// eslint-disable-next-line @typescript-eslint/no-unused-vars
} catch (e) { } catch (e) {
return text return text
} }

View File

@ -9,8 +9,7 @@ import {
import { updateCenterRectangleSketch } from './rectangleTool' import { updateCenterRectangleSketch } from './rectangleTool'
import { getNodePathFromSourceRange } from 'lang/queryAstNodePathUtils' import { getNodePathFromSourceRange } from 'lang/queryAstNodePathUtils'
import { getNodeFromPath } from 'lang/queryAst' import { getNodeFromPath } from 'lang/queryAst'
import { findUniqueName } from 'lang/modifyAst' import { trap } from './trap'
import { err, trap } from './trap'
beforeAll(async () => { beforeAll(async () => {
await initPromise await initPromise

View File

@ -10,12 +10,7 @@ import {
createTagDeclarator, createTagDeclarator,
createUnaryExpression, createUnaryExpression,
} from 'lang/modifyAst' } from 'lang/modifyAst'
import { import { ArrayExpression, CallExpression, PipeExpression } from 'lang/wasm'
ArrayExpression,
CallExpression,
PipeExpression,
recast,
} from 'lang/wasm'
import { roundOff } from 'lib/utils' import { roundOff } from 'lib/utils'
import { import {
isCallExpression, isCallExpression,

View File

@ -1,4 +1,4 @@
import { ActionFunction, LoaderFunction, redirect } from 'react-router-dom' import { LoaderFunction, redirect } from 'react-router-dom'
import { FileLoaderData, HomeLoaderData, IndexLoaderData } from './types' import { FileLoaderData, HomeLoaderData, IndexLoaderData } from './types'
import { getProjectMetaByRouteId, PATHS } from './paths' import { getProjectMetaByRouteId, PATHS } from './paths'
import { isDesktop } from './isDesktop' import { isDesktop } from './isDesktop'
@ -10,13 +10,11 @@ import {
PROJECT_ENTRYPOINT, PROJECT_ENTRYPOINT,
} from 'lib/constants' } from 'lib/constants'
import { loadAndValidateSettings } from './settings/settingsUtils' import { loadAndValidateSettings } from './settings/settingsUtils'
import makeUrlPathRelative from './makeUrlPathRelative'
import { codeManager } from 'lib/singletons' import { codeManager } from 'lib/singletons'
import { fileSystemManager } from 'lang/std/fileSystemManager' import { fileSystemManager } from 'lang/std/fileSystemManager'
import { getProjectInfo } from './desktop' import { getProjectInfo } from './desktop'
import { normalizeLineEndings } from 'lib/codeEditor' import { normalizeLineEndings } from 'lib/codeEditor'
import { OnboardingStatus } from '@rust/kcl-lib/bindings/OnboardingStatus' import { settingsActor } from 'machines/appMachine'
import { getSettings, settingsActor } from 'machines/appMachine'
import { waitFor } from 'xstate' import { waitFor } from 'xstate'
export const telemetryLoader: LoaderFunction = async ({ export const telemetryLoader: LoaderFunction = async ({

View File

@ -32,6 +32,7 @@ export default class RustContext {
if (this.wasmInitFailed) { if (this.wasmInitFailed) {
this.wasmInitFailed = false this.wasmInitFailed = false
} }
// eslint-disable-next-line @typescript-eslint/no-unused-vars
} catch (e) { } catch (e) {
this.wasmInitFailed = true this.wasmInitFailed = true
} }

View File

@ -167,6 +167,7 @@ export function readLocalStorageAppSettingsFile():
try { try {
return parseAppSettings(stored) return parseAppSettings(stored)
// eslint-disable-next-line @typescript-eslint/no-unused-vars
} catch (e) { } catch (e) {
const settings = defaultAppSettings() const settings = defaultAppSettings()
if (err(settings)) return settings if (err(settings)) return settings
@ -358,7 +359,6 @@ export function clearSettingsAtLevel(
level: SettingsLevel level: SettingsLevel
) { ) {
Object.entries(allSettings).forEach(([category, settingsCategory]) => { Object.entries(allSettings).forEach(([category, settingsCategory]) => {
const categoryKey = category as keyof typeof settings
Object.entries(settingsCategory).forEach( Object.entries(settingsCategory).forEach(
([_, settingValue]: [string, Setting]) => { ([_, settingValue]: [string, Setting]) => {
settingValue[level] = undefined settingValue[level] = undefined

View File

@ -12,7 +12,6 @@ import { NavigateFunction } from 'react-router-dom'
import crossPlatformFetch from './crossPlatformFetch' import crossPlatformFetch from './crossPlatformFetch'
import { isDesktop } from 'lib/isDesktop' import { isDesktop } from 'lib/isDesktop'
import { Themes } from './theme' import { Themes } from './theme'
import { commandBarMachine } from 'machines/commandBarMachine'
import { getNextFileName } from './desktopFS' import { getNextFileName } from './desktopFS'
import { reportRejection } from './trap' import { reportRejection } from './trap'
import { toSync } from './utils' import { toSync } from './utils'

View File

@ -1,4 +1,4 @@
import { ActorRefFrom, assign, createActor, setup, spawnChild } from 'xstate' import { ActorRefFrom, createActor, setup, spawnChild } from 'xstate'
import { authMachine } from './authMachine' import { authMachine } from './authMachine'
import { useSelector } from '@xstate/react' import { useSelector } from '@xstate/react'
import { ACTOR_IDS } from './machineConstants' import { ACTOR_IDS } from './machineConstants'
@ -11,12 +11,6 @@ const appMachineActors = {
[SETTINGS]: settingsMachine, [SETTINGS]: settingsMachine,
} as const } as const
type AppMachineActors = {
[K in keyof typeof appMachineActors]: ActorRefFrom<
(typeof appMachineActors)[K]
>
}
const appMachine = setup({ const appMachine = setup({
actors: appMachineActors, actors: appMachineActors,
}).createMachine({ }).createMachine({

View File

@ -93,9 +93,8 @@ import {
} from 'lang/modifyAst/deleteSelection' } from 'lang/modifyAst/deleteSelection'
import { getPathsFromPlaneArtifact } from 'lang/std/artifactGraph' import { getPathsFromPlaneArtifact } from 'lang/std/artifactGraph'
import { createProfileStartHandle } from 'clientSideScene/segments' import { createProfileStartHandle } from 'clientSideScene/segments'
import { DRAFT_POINT, SKETCH_LAYER } from 'clientSideScene/sceneInfra' import { DRAFT_POINT } from 'clientSideScene/sceneInfra'
import { setAppearance } from 'lang/modifyAst/setAppearance' import { setAppearance } from 'lang/modifyAst/setAppearance'
import { getThemeColorForThreeJs } from 'lib/theme'
import { DRAFT_DASHED_LINE } from 'clientSideScene/sceneEntities' import { DRAFT_DASHED_LINE } from 'clientSideScene/sceneEntities'
export const MODELING_PERSIST_KEY = 'MODELING_PERSIST_KEY' export const MODELING_PERSIST_KEY = 'MODELING_PERSIST_KEY'

View File

@ -2,7 +2,6 @@ import {
AnyActorRef, AnyActorRef,
assign, assign,
enqueueActions, enqueueActions,
EventObject,
fromCallback, fromCallback,
fromPromise, fromPromise,
sendTo, sendTo,

View File

@ -10,6 +10,7 @@ import {
nativeTheme, nativeTheme,
desktopCapturer, desktopCapturer,
systemPreferences, systemPreferences,
screen,
} from 'electron' } from 'electron'
import path from 'path' import path from 'path'
import { Issuer } from 'openid-client' import { Issuer } from 'openid-client'
@ -58,6 +59,7 @@ console.log('Environment vars', process.env)
console.log('Parsed CLI args', args) console.log('Parsed CLI args', args)
/// Register our application to handle all "zoo-studio:" protocols. /// Register our application to handle all "zoo-studio:" protocols.
const singleInstanceLock = app.requestSingleInstanceLock()
if (process.defaultApp) { if (process.defaultApp) {
if (process.argv.length >= 2) { if (process.argv.length >= 2) {
app.setAsDefaultProtocolClient(ZOO_STUDIO_PROTOCOL, process.execPath, [ app.setAsDefaultProtocolClient(ZOO_STUDIO_PROTOCOL, process.execPath, [
@ -72,11 +74,8 @@ if (process.defaultApp) {
// Must be done before ready event. // Must be done before ready event.
// Checking against this lock is needed for Windows and Linux, see // Checking against this lock is needed for Windows and Linux, see
// https://www.electronjs.org/docs/latest/tutorial/launch-app-from-url-in-another-app#windows-and-linux-code // https://www.electronjs.org/docs/latest/tutorial/launch-app-from-url-in-another-app#windows-and-linux-code
if (!IS_PLAYWRIGHT) { if (!singleInstanceLock && !IS_PLAYWRIGHT) {
const singleInstanceLock = app.requestSingleInstanceLock() app.quit()
if (!singleInstanceLock) {
app.quit()
}
} else { } else {
registerStartupListeners() registerStartupListeners()
} }
@ -88,12 +87,24 @@ const createWindow = (pathToOpen?: string, reuse?: boolean): BrowserWindow => {
newWindow = mainWindow newWindow = mainWindow
} }
if (!newWindow) { if (!newWindow) {
const primaryDisplay = screen.getPrimaryDisplay()
const { width, height } = primaryDisplay.workAreaSize
const windowWidth = Math.max(500, width - 150)
const windowHeight = Math.max(400, height - 100)
const x = primaryDisplay.workArea.x + Math.floor((width - windowWidth) / 2)
const y =
primaryDisplay.workArea.y + Math.floor((height - windowHeight) / 2)
newWindow = new BrowserWindow({ newWindow = new BrowserWindow({
autoHideMenuBar: false, autoHideMenuBar: false,
show: false, show: false,
enableLargerThanScreen: true, enableLargerThanScreen: true,
width: 1800, width: windowWidth,
height: 1200, height: windowHeight,
x,
y,
webPreferences: { webPreferences: {
nodeIntegration: false, // do not give the application implicit system access nodeIntegration: false, // do not give the application implicit system access
contextIsolation: true, // expose system functions in preload contextIsolation: true, // expose system functions in preload

View File

@ -9,8 +9,8 @@ import { SettingsSection } from 'components/Settings/SettingsSection'
import { settingsActor, useSettings } from 'machines/appMachine' import { settingsActor, useSettings } from 'machines/appMachine'
export default function Units() { export default function Units() {
const dismiss = useDismiss() useDismiss()
const next = useNextClick(onboardingPaths.STREAMING) useNextClick(onboardingPaths.STREAMING)
const { const {
modeling: { mouseControls }, modeling: { mouseControls },
} = useSettings() } = useSettings()