Merge branch 'main' into achalmers/kw-fn-sketches
This commit is contained in:
		@ -2,8 +2,8 @@ NODE_ENV=development
 | 
			
		||||
DEV=true
 | 
			
		||||
VITE_KC_API_WS_MODELING_URL=wss://api.dev.zoo.dev/ws/modeling/commands
 | 
			
		||||
VITE_KC_API_BASE_URL=https://api.dev.zoo.dev
 | 
			
		||||
BASE_URL=https://api.dev.zoo.dev
 | 
			
		||||
VITE_KC_SITE_BASE_URL=https://dev.zoo.dev
 | 
			
		||||
VITE_KC_SITE_APP_URL=https://app.dev.zoo.dev
 | 
			
		||||
VITE_KC_SKIP_AUTH=false
 | 
			
		||||
VITE_KC_CONNECTION_TIMEOUT_MS=5000
 | 
			
		||||
# ONLY add your token in .env.development.local if you want to skip auth, otherwise this token takes precedence!
 | 
			
		||||
 | 
			
		||||
@ -1,5 +1,8 @@
 | 
			
		||||
NODE_ENV=production
 | 
			
		||||
DEV=false
 | 
			
		||||
VITE_KC_API_WS_MODELING_URL=wss://api.zoo.dev/ws/modeling/commands
 | 
			
		||||
VITE_KC_API_BASE_URL=https://api.zoo.dev
 | 
			
		||||
VITE_KC_SITE_BASE_URL=https://zoo.dev
 | 
			
		||||
VITE_KC_SITE_APP_URL=https://app.zoo.dev
 | 
			
		||||
VITE_KC_SKIP_AUTH=false
 | 
			
		||||
VITE_KC_CONNECTION_TIMEOUT_MS=15000
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										16
									
								
								.github/workflows/build-apps.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										16
									
								
								.github/workflows/build-apps.yml
									
									
									
									
										vendored
									
									
								
							@ -134,8 +134,6 @@ jobs:
 | 
			
		||||
          max_attempts: 3
 | 
			
		||||
          command: yarn install
 | 
			
		||||
 | 
			
		||||
      - run: yarn tronb:vite
 | 
			
		||||
 | 
			
		||||
      - name: Prepare certificate and variables (Windows only)
 | 
			
		||||
        if: ${{ (env.IS_RELEASE == 'true' || env.IS_NIGHTLY == 'true') && matrix.os == 'windows-2022' }}
 | 
			
		||||
        run: |
 | 
			
		||||
@ -165,8 +163,8 @@ jobs:
 | 
			
		||||
      - name: Build the app (debug)
 | 
			
		||||
        if: ${{ env.IS_RELEASE == 'false' && env.IS_NIGHTLY == 'false' }}
 | 
			
		||||
        # electron-builder doesn't have a concept of release vs debug,
 | 
			
		||||
        # this is just not doing any codesign or release yml generation
 | 
			
		||||
        run: yarn electron-builder --config
 | 
			
		||||
        # this is just not doing any codesign or release yml generation, and points to dev infra
 | 
			
		||||
        run: yarn tronb:package:dev
 | 
			
		||||
 | 
			
		||||
      - name: Build the app (release)
 | 
			
		||||
        if: ${{ env.IS_RELEASE == 'true' || env.IS_NIGHTLY == 'true' }}
 | 
			
		||||
@ -185,7 +183,7 @@ jobs:
 | 
			
		||||
        with:
 | 
			
		||||
          timeout_minutes: 10
 | 
			
		||||
          max_attempts: 3
 | 
			
		||||
          command: yarn electron-builder --config --publish always
 | 
			
		||||
          command: yarn tronb:package:prod
 | 
			
		||||
 | 
			
		||||
      - name: List artifacts in out/
 | 
			
		||||
        run: ls -R out
 | 
			
		||||
@ -246,7 +244,7 @@ jobs:
 | 
			
		||||
        with:
 | 
			
		||||
          timeout_minutes: 10
 | 
			
		||||
          max_attempts: 3
 | 
			
		||||
          command: yarn electron-builder --config --publish always
 | 
			
		||||
          command: yarn tronb:package:prod
 | 
			
		||||
 | 
			
		||||
      - uses: actions/upload-artifact@v4
 | 
			
		||||
        if: ${{ env.IS_RELEASE == 'true' }}
 | 
			
		||||
@ -390,19 +388,19 @@ jobs:
 | 
			
		||||
 | 
			
		||||
      - name: Authenticate to Google Cloud
 | 
			
		||||
        if: ${{ env.IS_NIGHTLY == 'true' }}
 | 
			
		||||
        uses: 'google-github-actions/auth@v2.1.7'
 | 
			
		||||
        uses: 'google-github-actions/auth@v2.1.8'
 | 
			
		||||
        with:
 | 
			
		||||
          credentials_json: '${{ secrets.GOOGLE_CLOUD_DL_SA }}'
 | 
			
		||||
 | 
			
		||||
      - name: Set up Google Cloud SDK
 | 
			
		||||
        if: ${{ env.IS_NIGHTLY == 'true' }}
 | 
			
		||||
        uses: google-github-actions/setup-gcloud@v2.1.2
 | 
			
		||||
        uses: google-github-actions/setup-gcloud@v2.1.4
 | 
			
		||||
        with:
 | 
			
		||||
          project_id: ${{ env.GOOGLE_CLOUD_PROJECT_ID }}
 | 
			
		||||
 | 
			
		||||
      - name: Upload nightly files to public bucket
 | 
			
		||||
        if: ${{ env.IS_NIGHTLY == 'true' }}
 | 
			
		||||
        uses: google-github-actions/upload-cloud-storage@v2.2.1
 | 
			
		||||
        uses: google-github-actions/upload-cloud-storage@v2.2.2
 | 
			
		||||
        with:
 | 
			
		||||
          path: out
 | 
			
		||||
          glob: '*'
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										4
									
								
								.github/workflows/e2e-tests.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								.github/workflows/e2e-tests.yml
									
									
									
									
										vendored
									
									
								
							@ -123,9 +123,9 @@ jobs:
 | 
			
		||||
      if: steps.download-wasm.outcome == 'failure'
 | 
			
		||||
      shell: bash
 | 
			
		||||
      run: yarn build:wasm
 | 
			
		||||
    - name: build electron
 | 
			
		||||
    - name: build web
 | 
			
		||||
      shell: bash
 | 
			
		||||
      run: yarn tron:package
 | 
			
		||||
      run: yarn tronb:vite:dev
 | 
			
		||||
    # - name: Run ubuntu/chrome snapshots
 | 
			
		||||
    #   if: ${{ matrix.os == 'namespace-profile-ubuntu-8-cores' && matrix.shardIndex == 1 }}
 | 
			
		||||
    #   shell: bash
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										6
									
								
								.github/workflows/publish-apps-release.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										6
									
								
								.github/workflows/publish-apps-release.yml
									
									
									
									
										vendored
									
									
								
							@ -108,17 +108,17 @@ jobs:
 | 
			
		||||
        run: yarn files:set-notes
 | 
			
		||||
 | 
			
		||||
      - name: Authenticate to Google Cloud
 | 
			
		||||
        uses: 'google-github-actions/auth@v2.1.7'
 | 
			
		||||
        uses: 'google-github-actions/auth@v2.1.8'
 | 
			
		||||
        with:
 | 
			
		||||
          credentials_json: '${{ secrets.GOOGLE_CLOUD_DL_SA }}'
 | 
			
		||||
 | 
			
		||||
      - name: Set up Google Cloud SDK
 | 
			
		||||
        uses: google-github-actions/setup-gcloud@v2.1.2
 | 
			
		||||
        uses: google-github-actions/setup-gcloud@v2.1.4
 | 
			
		||||
        with:
 | 
			
		||||
          project_id: ${{ env.GOOGLE_CLOUD_PROJECT_ID }}
 | 
			
		||||
 | 
			
		||||
      - name: Upload release files to public bucket
 | 
			
		||||
        uses: google-github-actions/upload-cloud-storage@v2.2.1
 | 
			
		||||
        uses: google-github-actions/upload-cloud-storage@v2.2.2
 | 
			
		||||
        with:
 | 
			
		||||
          path: out
 | 
			
		||||
          glob: '*'
 | 
			
		||||
 | 
			
		||||
@ -101,7 +101,7 @@ 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).
 | 
			
		||||
 | 
			
		||||
To build, run `yarn tron:package`.
 | 
			
		||||
To build with electron-builder, run `yarn tronb:package:dev` (or `yarn tronb:package:prod` to point to the .env.production variables)
 | 
			
		||||
 | 
			
		||||
## Checking out commits / Bisecting
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -75,3 +75,6 @@ publish:
 | 
			
		||||
    channel: latest
 | 
			
		||||
releaseInfo:
 | 
			
		||||
  releaseNotesFile: release-notes.md
 | 
			
		||||
protocols:
 | 
			
		||||
  - name: Zoo Studio
 | 
			
		||||
    schemes: ['zoo-studio']
 | 
			
		||||
 | 
			
		||||
@ -9,23 +9,8 @@ const rootDir = process.cwd()
 | 
			
		||||
const config: ForgeConfig = {
 | 
			
		||||
  packagerConfig: {
 | 
			
		||||
    asar: true,
 | 
			
		||||
    osxSign: (process.env.BUILD_RELEASE === 'true' && {}) || undefined,
 | 
			
		||||
    osxNotarize:
 | 
			
		||||
      (process.env.BUILD_RELEASE === 'true' && {
 | 
			
		||||
        appleId: process.env.APPLE_ID || '',
 | 
			
		||||
        appleIdPassword: process.env.APPLE_PASSWORD || '',
 | 
			
		||||
        teamId: process.env.APPLE_TEAM_ID || '',
 | 
			
		||||
      }) ||
 | 
			
		||||
      undefined,
 | 
			
		||||
    executableName: 'zoo-modeling-app',
 | 
			
		||||
    icon: path.resolve(rootDir, 'assets', 'icon'),
 | 
			
		||||
    protocols: [
 | 
			
		||||
      {
 | 
			
		||||
        name: 'Zoo Studio',
 | 
			
		||||
        schemes: ['zoo-studio'],
 | 
			
		||||
      },
 | 
			
		||||
    ],
 | 
			
		||||
    extendInfo: 'Info.plist', // Information for file associations.
 | 
			
		||||
  },
 | 
			
		||||
  rebuildConfig: {},
 | 
			
		||||
  makers: [],
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										1
									
								
								interface.d.ts
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								interface.d.ts
									
									
									
									
										vendored
									
									
								
							@ -65,6 +65,7 @@ export interface IElectronAPI {
 | 
			
		||||
      VITE_KC_API_WS_MODELING_URL: string
 | 
			
		||||
      VITE_KC_API_BASE_URL: string
 | 
			
		||||
      VITE_KC_SITE_BASE_URL: string
 | 
			
		||||
      VITE_KC_SITE_APP_URL: string
 | 
			
		||||
      VITE_KC_SKIP_AUTH: string
 | 
			
		||||
      VITE_KC_CONNECTION_TIMEOUT_MS: string
 | 
			
		||||
      VITE_KC_DEV_TOKEN: string
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										16
									
								
								package.json
									
									
									
									
									
								
							
							
						
						
									
										16
									
								
								package.json
									
									
									
									
									
								
							@ -103,11 +103,11 @@
 | 
			
		||||
    "make:dev": "make dev",
 | 
			
		||||
    "generate:machine-api": "npx openapi-typescript ./openapi/machine-api.json -o src/lib/machine-api.d.ts",
 | 
			
		||||
    "tron:start": "electron-forge start",
 | 
			
		||||
    "tron:package": "electron-forge package",
 | 
			
		||||
    "chrome:test": "PLATFORM=web NODE_ENV=development yarn playwright test --config=playwright.config.ts --project='Google Chrome' --grep-invert='@snapshot'",
 | 
			
		||||
    "tron:test": "NODE_ENV=development yarn playwright test --config=playwright.electron.config.ts --grep-invert='@snapshot'",
 | 
			
		||||
    "tronb:vite": "vite build -c vite.main.config.ts && vite build -c vite.preload.config.ts && vite build -c vite.renderer.config.ts",
 | 
			
		||||
    "tronb:package": "electron-builder --config electron-builder.yml",
 | 
			
		||||
    "tronb:vite:dev": "vite build -c vite.main.config.ts -m development && vite build -c vite.preload.config.ts -m development && vite build -c vite.renderer.config.ts -m development",
 | 
			
		||||
    "tronb:vite:prod": "vite build -c vite.main.config.ts && vite build -c vite.preload.config.ts && vite build -c vite.renderer.config.ts",
 | 
			
		||||
    "tronb:package:dev": "yarn tronb:vite:dev && electron-builder --config electron-builder.yml",
 | 
			
		||||
    "tronb:package:prod": "yarn tronb:vite:prod && electron-builder --config electron-builder.yml --publish always",
 | 
			
		||||
    "test-setup": "yarn install && yarn build:wasm",
 | 
			
		||||
    "test": "vitest --mode development",
 | 
			
		||||
    "test:unit": "vitest run --mode development --exclude **/kclSamples.test.ts",
 | 
			
		||||
@ -116,10 +116,10 @@
 | 
			
		||||
    "test:playwright:electron:windows": "playwright test --config=playwright.electron.config.ts --grep-invert=\"@skipWin|@snapshot\" --quiet",
 | 
			
		||||
    "test:playwright:electron:macos": "playwright test --config=playwright.electron.config.ts --grep-invert='@skipMacos|@snapshot' --quiet",
 | 
			
		||||
    "test:playwright:electron:ubuntu": "playwright test --config=playwright.electron.config.ts --grep-invert='@skipLinux|@snapshot' --quiet",
 | 
			
		||||
    "test:playwright:electron:local": "yarn tron:package && NODE_ENV=development playwright test --config=playwright.electron.config.ts --grep-invert='@snapshot'",
 | 
			
		||||
    "test:playwright:electron:windows:local": "yarn tron:package && NODE_ENV=development playwright test --config=playwright.electron.config.ts --grep-invert=\"@skipWin|@snapshot\"",
 | 
			
		||||
    "test:playwright:electron:macos:local": "yarn tron:package && NODE_ENV=development playwright test --config=playwright.electron.config.ts --grep-invert='@skipMacos|@snapshot'",
 | 
			
		||||
    "test:playwright:electron:ubuntu:local": "yarn tron:package && NODE_ENV=development playwright test --config=playwright.electron.config.ts --grep-invert='@skipLinux|@snapshot'",
 | 
			
		||||
    "test:playwright:electron:local": "yarn tronb:package:dev && NODE_ENV=development playwright test --config=playwright.electron.config.ts --grep-invert='@snapshot'",
 | 
			
		||||
    "test:playwright:electron:windows:local": "yarn tronb:package:dev && set NODE_ENV='development' && playwright test --config=playwright.electron.config.ts --grep-invert=\"@skipWin|@snapshot\"",
 | 
			
		||||
    "test:playwright:electron:macos:local": "yarn tronb:package:dev && NODE_ENV=development playwright test --config=playwright.electron.config.ts --grep-invert='@skipMacos|@snapshot'",
 | 
			
		||||
    "test:playwright:electron:ubuntu:local": "yarn tronb:package:dev && NODE_ENV=development playwright test --config=playwright.electron.config.ts --grep-invert='@skipLinux|@snapshot'",
 | 
			
		||||
    "test:unit:local": "yarn simpleserver:bg && yarn test:unit; kill-port 3000",
 | 
			
		||||
    "test:unit:kcl-samples:local": "yarn simpleserver:bg && yarn test:unit:kcl-samples; kill-port 3000"
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
@ -29,6 +29,7 @@ import * as TWEEN from '@tweenjs/tween.js'
 | 
			
		||||
import { isQuaternionVertical } from './helpers'
 | 
			
		||||
import { reportRejection } from 'lib/trap'
 | 
			
		||||
import { CameraProjectionType } from 'wasm-lib/kcl/bindings/CameraProjectionType'
 | 
			
		||||
import { CameraDragInteractionType_type } from '@kittycad/lib/dist/types/src/models'
 | 
			
		||||
 | 
			
		||||
const ORTHOGRAPHIC_CAMERA_SIZE = 20
 | 
			
		||||
const FRAMES_TO_ANIMATE_IN = 30
 | 
			
		||||
@ -406,7 +407,7 @@ export class CameraControls {
 | 
			
		||||
        .sub(this.mouseDownPosition)
 | 
			
		||||
      this.mouseDownPosition.copy(this.mouseNewPosition)
 | 
			
		||||
 | 
			
		||||
      const interaction = this.getInteractionType(event)
 | 
			
		||||
      let interaction = this.getInteractionType(event)
 | 
			
		||||
      if (interaction === 'none') return
 | 
			
		||||
 | 
			
		||||
      // If there's a valid interaction and the mouse is moving,
 | 
			
		||||
@ -753,8 +754,6 @@ export class CameraControls {
 | 
			
		||||
      didChange = true
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    this.safeLookAtTarget(this.camera.up)
 | 
			
		||||
 | 
			
		||||
    // Update the camera's matrices
 | 
			
		||||
    this.camera.updateMatrixWorld()
 | 
			
		||||
    if (didChange || forceUpdate) {
 | 
			
		||||
@ -1189,14 +1188,24 @@ export class CameraControls {
 | 
			
		||||
    this.deferReactUpdate(this.reactCameraProperties)
 | 
			
		||||
    Object.values(this._camChangeCallbacks).forEach((cb) => cb())
 | 
			
		||||
  }
 | 
			
		||||
  getInteractionType = (event: MouseEvent) =>
 | 
			
		||||
    _getInteractionType(
 | 
			
		||||
  getInteractionType = (
 | 
			
		||||
    event: MouseEvent
 | 
			
		||||
  ): CameraDragInteractionType_type | 'none' => {
 | 
			
		||||
    const initialInteractionType = _getInteractionType(
 | 
			
		||||
      this.interactionGuards,
 | 
			
		||||
      event,
 | 
			
		||||
      this.enablePan,
 | 
			
		||||
      this.enableRotate,
 | 
			
		||||
      this.enableZoom
 | 
			
		||||
    )
 | 
			
		||||
    if (
 | 
			
		||||
      initialInteractionType === 'rotate' &&
 | 
			
		||||
      this.engineCommandManager.settings.cameraOrbit === 'trackball'
 | 
			
		||||
    ) {
 | 
			
		||||
      return 'rotatetrackball'
 | 
			
		||||
    }
 | 
			
		||||
    return initialInteractionType
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Pure function helpers
 | 
			
		||||
 | 
			
		||||
@ -119,6 +119,7 @@ export const ModelingMachineProvider = ({
 | 
			
		||||
          cameraProjection,
 | 
			
		||||
          highlightEdges,
 | 
			
		||||
          showScaleGrid,
 | 
			
		||||
          cameraOrbit,
 | 
			
		||||
        },
 | 
			
		||||
      },
 | 
			
		||||
    },
 | 
			
		||||
@ -1154,6 +1155,7 @@ export const ModelingMachineProvider = ({
 | 
			
		||||
      enableSSAO: enableSSAO.current,
 | 
			
		||||
      showScaleGrid: showScaleGrid.current,
 | 
			
		||||
      cameraProjection: cameraProjection.current,
 | 
			
		||||
      cameraOrbit: cameraOrbit.current,
 | 
			
		||||
    },
 | 
			
		||||
    token
 | 
			
		||||
  )
 | 
			
		||||
@ -1183,6 +1185,13 @@ export const ModelingMachineProvider = ({
 | 
			
		||||
    editorManager.selectionRanges = modelingState.context.selectionRanges
 | 
			
		||||
  }, [modelingState.context.selectionRanges])
 | 
			
		||||
 | 
			
		||||
  // When changing camera modes reset the camera to the default orientation to correct
 | 
			
		||||
  // the up vector otherwise the conconical orientation for the camera modes will be
 | 
			
		||||
  // wrong
 | 
			
		||||
  useEffect(() => {
 | 
			
		||||
    sceneInfra.camControls.resetCameraPosition().catch(reportRejection)
 | 
			
		||||
  }, [cameraOrbit.current])
 | 
			
		||||
 | 
			
		||||
  useEffect(() => {
 | 
			
		||||
    const onConnectionStateChanged = ({ detail }: CustomEvent) => {
 | 
			
		||||
      // If we are in sketch mode we need to exit it.
 | 
			
		||||
 | 
			
		||||
@ -33,7 +33,7 @@ export const OpenInDesktopAppHandler = (props: React.PropsWithChildren) => {
 | 
			
		||||
  function onOpenInDesktopApp() {
 | 
			
		||||
    const newSearchParams = new URLSearchParams(globalThis.location.search)
 | 
			
		||||
    newSearchParams.delete(ASK_TO_OPEN_QUERY_PARAM)
 | 
			
		||||
    const newURL = `${ZOO_STUDIO_PROTOCOL}${globalThis.location.pathname.replace(
 | 
			
		||||
    const newURL = `${ZOO_STUDIO_PROTOCOL}://${globalThis.location.pathname.replace(
 | 
			
		||||
      '/',
 | 
			
		||||
      ''
 | 
			
		||||
    )}${searchParams.size > 0 ? `?${newSearchParams.toString()}` : ''}`
 | 
			
		||||
 | 
			
		||||
@ -19,7 +19,7 @@ import { commandBarActor } from 'machines/commandBarMachine'
 | 
			
		||||
import { useSelector } from '@xstate/react'
 | 
			
		||||
import { copyFileShareLink } from 'lib/links'
 | 
			
		||||
import { useSettingsAuthContext } from 'hooks/useSettingsAuthContext'
 | 
			
		||||
import { DEV } from 'env'
 | 
			
		||||
import { IS_NIGHTLY_OR_DEBUG } from 'routes/Settings'
 | 
			
		||||
import { useToken } from 'machines/appMachine'
 | 
			
		||||
 | 
			
		||||
const ProjectSidebarMenu = ({
 | 
			
		||||
@ -112,6 +112,7 @@ function ProjectMenuPopover({
 | 
			
		||||
  const { onProjectClose } = useLspContext()
 | 
			
		||||
  const exportCommandInfo = { name: 'Export', groupId: 'modeling' }
 | 
			
		||||
  const makeCommandInfo = { name: 'Make', groupId: 'modeling' }
 | 
			
		||||
  const shareCommandInfo = { name: 'share-file-link', groupId: 'code' }
 | 
			
		||||
  const findCommand = (obj: { name: string; groupId: string }) =>
 | 
			
		||||
    Boolean(
 | 
			
		||||
      commands.find((c) => c.name === obj.name && c.groupId === obj.groupId)
 | 
			
		||||
@ -193,7 +194,7 @@ function ProjectMenuPopover({
 | 
			
		||||
          id: 'share-link',
 | 
			
		||||
          Element: 'button',
 | 
			
		||||
          children: 'Share link to file',
 | 
			
		||||
          disabled: !DEV,
 | 
			
		||||
          disabled: IS_NIGHTLY_OR_DEBUG || !findCommand(shareCommandInfo),
 | 
			
		||||
          onClick: async () => {
 | 
			
		||||
            await copyFileShareLink({
 | 
			
		||||
              token: token ?? '',
 | 
			
		||||
 | 
			
		||||
@ -10,6 +10,7 @@ export const VITE_KC_API_WS_MODELING_URL = env.VITE_KC_API_WS_MODELING_URL as
 | 
			
		||||
  | undefined
 | 
			
		||||
export const VITE_KC_API_BASE_URL = env.VITE_KC_API_BASE_URL as string
 | 
			
		||||
export const VITE_KC_SITE_BASE_URL = env.VITE_KC_SITE_BASE_URL as string
 | 
			
		||||
export const VITE_KC_SITE_APP_URL = env.VITE_KC_SITE_APP_URL as string
 | 
			
		||||
export const VITE_KC_SKIP_AUTH = env.VITE_KC_SKIP_AUTH as string | undefined
 | 
			
		||||
export const VITE_KC_CONNECTION_TIMEOUT_MS =
 | 
			
		||||
  env.VITE_KC_CONNECTION_TIMEOUT_MS as string | undefined
 | 
			
		||||
 | 
			
		||||
@ -16,14 +16,15 @@ export function useSetupEngineManager(
 | 
			
		||||
  streamRef: React.RefObject<HTMLDivElement>,
 | 
			
		||||
  modelingSend: ReturnType<typeof useModelingContext>['send'],
 | 
			
		||||
  modelingContext: ReturnType<typeof useModelingContext>['context'],
 | 
			
		||||
  settings = {
 | 
			
		||||
  settings: SettingsViaQueryString = {
 | 
			
		||||
    pool: null,
 | 
			
		||||
    theme: Themes.System,
 | 
			
		||||
    highlightEdges: true,
 | 
			
		||||
    enableSSAO: true,
 | 
			
		||||
    showScaleGrid: false,
 | 
			
		||||
    cameraProjection: 'perspective',
 | 
			
		||||
  } as SettingsViaQueryString,
 | 
			
		||||
    cameraOrbit: 'spherical',
 | 
			
		||||
  },
 | 
			
		||||
  token?: string
 | 
			
		||||
) {
 | 
			
		||||
  const networkContext = useNetworkContext()
 | 
			
		||||
 | 
			
		||||
@ -1389,6 +1389,7 @@ export class EngineCommandManager extends EventTarget {
 | 
			
		||||
          enableSSAO: true,
 | 
			
		||||
          showScaleGrid: false,
 | 
			
		||||
          cameraProjection: 'perspective',
 | 
			
		||||
          cameraOrbit: 'spherical',
 | 
			
		||||
        }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
@ -1437,6 +1438,7 @@ export class EngineCommandManager extends EventTarget {
 | 
			
		||||
      enableSSAO: true,
 | 
			
		||||
      showScaleGrid: false,
 | 
			
		||||
      cameraProjection: 'orthographic',
 | 
			
		||||
      cameraOrbit: 'spherical',
 | 
			
		||||
    },
 | 
			
		||||
    // When passed, use a completely separate connecting code path that simply
 | 
			
		||||
    // opens a websocket and this is a function that is called when connected.
 | 
			
		||||
 | 
			
		||||
@ -68,8 +68,6 @@ export const KCL_DEFAULT_DEGREE = `360`
 | 
			
		||||
/** localStorage key for the playwright test-specific app settings file */
 | 
			
		||||
export const TEST_SETTINGS_FILE_KEY = 'playwright-test-settings'
 | 
			
		||||
 | 
			
		||||
export const DEFAULT_HOST = 'https://api.zoo.dev'
 | 
			
		||||
export const PROD_APP_URL = 'https://app.zoo.dev'
 | 
			
		||||
export const SETTINGS_FILE_NAME = 'settings.toml'
 | 
			
		||||
export const TOKEN_FILE_NAME = 'token.txt'
 | 
			
		||||
export const PROJECT_SETTINGS_FILE_NAME = 'project.toml'
 | 
			
		||||
@ -145,7 +143,7 @@ export const VIEW_NAMES_SEMANTIC = {
 | 
			
		||||
export const SIDEBAR_BUTTON_SUFFIX = '-pane-button'
 | 
			
		||||
 | 
			
		||||
/** Custom URL protocol our desktop registers */
 | 
			
		||||
export const ZOO_STUDIO_PROTOCOL = 'zoo-studio:'
 | 
			
		||||
export const ZOO_STUDIO_PROTOCOL = 'zoo-studio'
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * A query parameter that triggers a modal
 | 
			
		||||
 | 
			
		||||
@ -1,11 +1,13 @@
 | 
			
		||||
import { CommandBarOverwriteWarning } from 'components/CommandBarOverwriteWarning'
 | 
			
		||||
import { Command, CommandArgumentOption } from './commandTypes'
 | 
			
		||||
import { kclManager } from './singletons'
 | 
			
		||||
import { codeManager, kclManager } from './singletons'
 | 
			
		||||
import { isDesktop } from './isDesktop'
 | 
			
		||||
import { FILE_EXT } from './constants'
 | 
			
		||||
import { UnitLength_type } from '@kittycad/lib/dist/types/src/models'
 | 
			
		||||
import { reportRejection } from './trap'
 | 
			
		||||
import { IndexLoaderData } from './types'
 | 
			
		||||
import { IS_NIGHTLY_OR_DEBUG } from 'routes/Settings'
 | 
			
		||||
import { copyFileShareLink } from './links'
 | 
			
		||||
 | 
			
		||||
interface OnSubmitProps {
 | 
			
		||||
  sampleName: string
 | 
			
		||||
@ -132,21 +134,22 @@ export function kclCommands(commandProps: KclCommandConfig): Command[] {
 | 
			
		||||
        },
 | 
			
		||||
      },
 | 
			
		||||
    },
 | 
			
		||||
    // {
 | 
			
		||||
    //   name: 'share-file-link',
 | 
			
		||||
    //   displayName: 'Share file',
 | 
			
		||||
    //   description: 'Create a link that contains a copy of the current file.',
 | 
			
		||||
    //   groupId: 'code',
 | 
			
		||||
    //   needsReview: false,
 | 
			
		||||
    //   icon: 'link',
 | 
			
		||||
    //   onSubmit: () => {
 | 
			
		||||
    //     copyFileShareLink({
 | 
			
		||||
    //       token: commandProps.authToken,
 | 
			
		||||
    //       code: codeManager.code,
 | 
			
		||||
    //       name: commandProps.projectData.project?.name || '',
 | 
			
		||||
    //       units: commandProps.settings.defaultUnit,
 | 
			
		||||
    //     }).catch(reportRejection)
 | 
			
		||||
    //   },
 | 
			
		||||
    // },
 | 
			
		||||
    {
 | 
			
		||||
      name: 'share-file-link',
 | 
			
		||||
      displayName: 'Share file',
 | 
			
		||||
      hide: IS_NIGHTLY_OR_DEBUG ? undefined : 'desktop',
 | 
			
		||||
      description: 'Create a link that contains a copy of the current file.',
 | 
			
		||||
      groupId: 'code',
 | 
			
		||||
      needsReview: false,
 | 
			
		||||
      icon: 'link',
 | 
			
		||||
      onSubmit: () => {
 | 
			
		||||
        copyFileShareLink({
 | 
			
		||||
          token: commandProps.authToken,
 | 
			
		||||
          code: codeManager.code,
 | 
			
		||||
          name: commandProps.projectData.project?.name || '',
 | 
			
		||||
          units: commandProps.settings.defaultUnit,
 | 
			
		||||
        }).catch(reportRejection)
 | 
			
		||||
      },
 | 
			
		||||
    },
 | 
			
		||||
  ]
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -1,3 +1,4 @@
 | 
			
		||||
import { VITE_KC_SITE_APP_URL } from 'env'
 | 
			
		||||
import { createCreateFileUrl } from './links'
 | 
			
		||||
 | 
			
		||||
describe(`link creation tests`, () => {
 | 
			
		||||
@ -8,7 +9,7 @@ describe(`link creation tests`, () => {
 | 
			
		||||
 | 
			
		||||
    // Converted with external online tools
 | 
			
		||||
    const expectedEncodedCode = `ZXh0cnVzaW9uRGlzdGFuY2UgPSAxMg%3D%3D`
 | 
			
		||||
    const expectedLink = `http://localhost:3000/?create-file=true&name=test&units=mm&code=${expectedEncodedCode}&ask-open-desktop=true`
 | 
			
		||||
    const expectedLink = `${VITE_KC_SITE_APP_URL}/?create-file=true&name=test&units=mm&code=${expectedEncodedCode}&ask-open-desktop=true`
 | 
			
		||||
 | 
			
		||||
    const result = createCreateFileUrl({ code, name, units })
 | 
			
		||||
    expect(result.toString()).toBe(expectedLink)
 | 
			
		||||
 | 
			
		||||
@ -1,11 +1,7 @@
 | 
			
		||||
import { UnitLength_type } from '@kittycad/lib/dist/types/src/models'
 | 
			
		||||
import {
 | 
			
		||||
  ASK_TO_OPEN_QUERY_PARAM,
 | 
			
		||||
  CREATE_FILE_URL_PARAM,
 | 
			
		||||
  PROD_APP_URL,
 | 
			
		||||
} from './constants'
 | 
			
		||||
import { ASK_TO_OPEN_QUERY_PARAM, CREATE_FILE_URL_PARAM } from './constants'
 | 
			
		||||
import { stringToBase64 } from './base64'
 | 
			
		||||
import { DEV, VITE_KC_API_BASE_URL } from 'env'
 | 
			
		||||
import { VITE_KC_API_BASE_URL, VITE_KC_SITE_APP_URL } from 'env'
 | 
			
		||||
import toast from 'react-hot-toast'
 | 
			
		||||
import { err } from './trap'
 | 
			
		||||
export interface FileLinkParams {
 | 
			
		||||
@ -51,8 +47,7 @@ export async function copyFileShareLink(
 | 
			
		||||
 * open the URL in the desktop app.
 | 
			
		||||
 */
 | 
			
		||||
export function createCreateFileUrl({ code, name, units }: FileLinkParams) {
 | 
			
		||||
  // Use the dev server if we are in development mode
 | 
			
		||||
  let origin = DEV ? 'http://localhost:3000' : PROD_APP_URL
 | 
			
		||||
  let origin = VITE_KC_SITE_APP_URL
 | 
			
		||||
  const searchParams = new URLSearchParams({
 | 
			
		||||
    [CREATE_FILE_URL_PARAM]: String(true),
 | 
			
		||||
    name,
 | 
			
		||||
 | 
			
		||||
@ -20,6 +20,7 @@ import { toSync } from 'lib/utils'
 | 
			
		||||
import { reportRejection } from 'lib/trap'
 | 
			
		||||
import { CameraProjectionType } from 'wasm-lib/kcl/bindings/CameraProjectionType'
 | 
			
		||||
import { OnboardingStatus } from 'wasm-lib/kcl/bindings/OnboardingStatus'
 | 
			
		||||
import { CameraOrbitType } from 'wasm-lib/kcl/bindings/CameraOrbitType'
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * A setting that can be set at the user or project level
 | 
			
		||||
@ -380,6 +381,30 @@ export function createSettings() {
 | 
			
		||||
            })),
 | 
			
		||||
        },
 | 
			
		||||
      }),
 | 
			
		||||
      /**
 | 
			
		||||
       * What methodology to use for orbiting the camera
 | 
			
		||||
       */
 | 
			
		||||
      cameraOrbit: new Setting<CameraOrbitType>({
 | 
			
		||||
        defaultValue: 'spherical',
 | 
			
		||||
        hideOnLevel: 'project',
 | 
			
		||||
        description: 'What methodology to use for orbiting the camera',
 | 
			
		||||
        validate: (v) => ['spherical', 'trackball'].includes(v),
 | 
			
		||||
        commandConfig: {
 | 
			
		||||
          inputType: 'options',
 | 
			
		||||
          defaultValueFromContext: (context) =>
 | 
			
		||||
            context.modeling.cameraOrbit.current,
 | 
			
		||||
          options: (cmdContext, settingsContext) =>
 | 
			
		||||
            (['spherical', 'trackball'] as const).map((v) => ({
 | 
			
		||||
              name: v.charAt(0).toUpperCase() + v.slice(1),
 | 
			
		||||
              value: v,
 | 
			
		||||
              isCurrent:
 | 
			
		||||
                settingsContext.modeling.cameraOrbit.shouldShowCurrentLabel(
 | 
			
		||||
                  cmdContext.argumentsToSubmit.level as SettingsLevel,
 | 
			
		||||
                  v
 | 
			
		||||
                ),
 | 
			
		||||
            })),
 | 
			
		||||
        },
 | 
			
		||||
      }),
 | 
			
		||||
      /**
 | 
			
		||||
       * Whether to highlight edges of 3D objects
 | 
			
		||||
       */
 | 
			
		||||
 | 
			
		||||
@ -4,6 +4,7 @@ import { AtLeast, PathValue, Paths } from 'lib/types'
 | 
			
		||||
import { CommandArgumentConfig } from 'lib/commandTypes'
 | 
			
		||||
import { Themes } from 'lib/theme'
 | 
			
		||||
import { CameraProjectionType } from 'wasm-lib/kcl/bindings/CameraProjectionType'
 | 
			
		||||
import { CameraOrbitType } from 'wasm-lib/kcl/bindings/CameraOrbitType'
 | 
			
		||||
 | 
			
		||||
export interface SettingsViaQueryString {
 | 
			
		||||
  pool: string | null
 | 
			
		||||
@ -12,6 +13,7 @@ export interface SettingsViaQueryString {
 | 
			
		||||
  enableSSAO: boolean
 | 
			
		||||
  showScaleGrid: boolean
 | 
			
		||||
  cameraProjection: CameraProjectionType
 | 
			
		||||
  cameraOrbit: CameraOrbitType
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export enum UnitSystem {
 | 
			
		||||
 | 
			
		||||
@ -49,6 +49,7 @@ export function configurationToSettingsPayload(
 | 
			
		||||
    modeling: {
 | 
			
		||||
      defaultUnit: configuration?.settings?.modeling?.base_unit,
 | 
			
		||||
      cameraProjection: configuration?.settings?.modeling?.camera_projection,
 | 
			
		||||
      cameraOrbit: configuration?.settings?.modeling?.camera_orbit,
 | 
			
		||||
      mouseControls: mouseControlsToCameraSystem(
 | 
			
		||||
        configuration?.settings?.modeling?.mouse_controls
 | 
			
		||||
      ),
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										71
									
								
								src/main.ts
									
									
									
									
									
								
							
							
						
						
									
										71
									
								
								src/main.ts
									
									
									
									
									
								
							@ -31,23 +31,27 @@ let mainWindow: BrowserWindow | null = null
 | 
			
		||||
// Check the command line arguments for a project path
 | 
			
		||||
const args = parseCLIArgs()
 | 
			
		||||
 | 
			
		||||
// If it's not set, scream.
 | 
			
		||||
const NODE_ENV = process.env.NODE_ENV || 'production'
 | 
			
		||||
if (!process.env.NODE_ENV)
 | 
			
		||||
  console.warn(
 | 
			
		||||
    '*FOX SCREAM* process.env.NODE_ENV is not explicitly set!, defaulting to production'
 | 
			
		||||
  )
 | 
			
		||||
// Default prod values
 | 
			
		||||
// @ts-ignore: TS1343
 | 
			
		||||
const viteEnv = import.meta.env
 | 
			
		||||
const NODE_ENV = process.env.NODE_ENV || viteEnv.MODE
 | 
			
		||||
 | 
			
		||||
// dotenv override when present
 | 
			
		||||
dotenv.config({ path: [`.env.${NODE_ENV}.local`, `.env.${NODE_ENV}`] })
 | 
			
		||||
 | 
			
		||||
process.env.VITE_KC_API_WS_MODELING_URL ??=
 | 
			
		||||
  'wss://api.zoo.dev/ws/modeling/commands'
 | 
			
		||||
process.env.VITE_KC_API_BASE_URL ??= 'https://api.zoo.dev'
 | 
			
		||||
process.env.VITE_KC_SITE_BASE_URL ??= 'https://zoo.dev'
 | 
			
		||||
process.env.VITE_KC_SKIP_AUTH ??= 'false'
 | 
			
		||||
process.env.VITE_KC_CONNECTION_TIMEOUT_MS ??= '15000'
 | 
			
		||||
// default vite values based on mode
 | 
			
		||||
process.env.NODE_ENV ??= viteEnv.MODE
 | 
			
		||||
process.env.DEV ??= viteEnv.DEV + ''
 | 
			
		||||
process.env.BASE_URL ??= viteEnv.VITE_KC_API_BASE_URL
 | 
			
		||||
process.env.VITE_KC_API_WS_MODELING_URL ??= viteEnv.VITE_KC_API_WS_MODELING_URL
 | 
			
		||||
process.env.VITE_KC_API_BASE_URL ??= viteEnv.VITE_KC_API_BASE_URL
 | 
			
		||||
process.env.VITE_KC_SITE_BASE_URL ??= viteEnv.VITE_KC_SITE_BASE_URL
 | 
			
		||||
process.env.VITE_KC_SITE_APP_URL ??= viteEnv.VITE_KC_SITE_APP_URL
 | 
			
		||||
process.env.VITE_KC_SKIP_AUTH ??= viteEnv.VITE_KC_SKIP_AUTH
 | 
			
		||||
process.env.VITE_KC_CONNECTION_TIMEOUT_MS ??=
 | 
			
		||||
  viteEnv.VITE_KC_CONNECTION_TIMEOUT_MS
 | 
			
		||||
 | 
			
		||||
// Likely convenient to keep for debugging
 | 
			
		||||
console.log('process.env', process.env)
 | 
			
		||||
 | 
			
		||||
/// Register our application to handle all "zoo-studio:" protocols.
 | 
			
		||||
if (process.defaultApp) {
 | 
			
		||||
@ -89,22 +93,43 @@ const createWindow = (pathToOpen?: string, reuse?: boolean): BrowserWindow => {
 | 
			
		||||
    })
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // Deep Link: Case of a cold start from Windows or Linux
 | 
			
		||||
  if (
 | 
			
		||||
    !pathToOpen &&
 | 
			
		||||
    process.argv.length > 1 &&
 | 
			
		||||
    process.argv[1].indexOf(ZOO_STUDIO_PROTOCOL + '://') > -1
 | 
			
		||||
  ) {
 | 
			
		||||
    pathToOpen = process.argv[1]
 | 
			
		||||
    console.log('Retrieved deep link from argv', pathToOpen)
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // Deep Link: Case of a second window opened for macOS
 | 
			
		||||
  // @ts-ignore
 | 
			
		||||
  if (!pathToOpen && global['openUrls'] && global['openUrls'][0]) {
 | 
			
		||||
    // @ts-ignore
 | 
			
		||||
    pathToOpen = global['openUrls'][0]
 | 
			
		||||
    console.log('Retrieved deep link from open-url', pathToOpen)
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  const pathIsCustomProtocolLink =
 | 
			
		||||
    pathToOpen?.startsWith(ZOO_STUDIO_PROTOCOL) ?? false
 | 
			
		||||
 | 
			
		||||
  // and load the index.html of the app.
 | 
			
		||||
  if (MAIN_WINDOW_VITE_DEV_SERVER_URL) {
 | 
			
		||||
    const filteredPath = pathToOpen
 | 
			
		||||
      ? decodeURI(pathToOpen.replace(ZOO_STUDIO_PROTOCOL, ''))
 | 
			
		||||
      ? decodeURI(pathToOpen.replace(ZOO_STUDIO_PROTOCOL + '://', ''))
 | 
			
		||||
      : ''
 | 
			
		||||
    const fullHashBasedUrl = `${MAIN_WINDOW_VITE_DEV_SERVER_URL}/#/${filteredPath}`
 | 
			
		||||
    newWindow.loadURL(fullHashBasedUrl).catch(reportRejection)
 | 
			
		||||
  } else {
 | 
			
		||||
    if (pathIsCustomProtocolLink && pathToOpen) {
 | 
			
		||||
      // We're trying to open a custom protocol link
 | 
			
		||||
      const filteredPath = pathToOpen
 | 
			
		||||
        ? decodeURI(pathToOpen.replace(ZOO_STUDIO_PROTOCOL, ''))
 | 
			
		||||
        : ''
 | 
			
		||||
      // TODO: fix the replace %3 thing
 | 
			
		||||
      const urlNoProtocol = pathToOpen
 | 
			
		||||
        .replace(ZOO_STUDIO_PROTOCOL + '://', '')
 | 
			
		||||
        .replaceAll('%3D', '')
 | 
			
		||||
        .replaceAll('%3', '')
 | 
			
		||||
      const filteredPath = decodeURI(urlNoProtocol)
 | 
			
		||||
      const startIndex = path.join(
 | 
			
		||||
        __dirname,
 | 
			
		||||
        `../renderer/${MAIN_WINDOW_VITE_NAME}/index.html`
 | 
			
		||||
@ -342,7 +367,7 @@ export function getAutoUpdater(): AppUpdater {
 | 
			
		||||
 | 
			
		||||
app.on('ready', () => {
 | 
			
		||||
  // Disable auto updater on non-versioned builds
 | 
			
		||||
  if (packageJSON.version === '0.0.0') {
 | 
			
		||||
  if (packageJSON.version === '0.0.0' && viteEnv.MODE !== 'production') {
 | 
			
		||||
    return
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
@ -459,6 +484,14 @@ function parseCLIArgs(): minimist.ParsedArgs {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function registerStartupListeners() {
 | 
			
		||||
  // Linux and Windows from https://www.electronjs.org/docs/latest/tutorial/launch-app-from-url-in-another-app
 | 
			
		||||
  app.on('second-instance', (event, commandLine, workingDirectory) => {
 | 
			
		||||
    // Deep Link: second instance for Windows and Linux
 | 
			
		||||
    const url = commandLine.pop()?.slice(0, -1)
 | 
			
		||||
    console.log('Retrieved deep link from commandLine', url)
 | 
			
		||||
    createWindow(url)
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * macOS: when someone drops a file to the not-yet running VSCode, the open-file event fires even before
 | 
			
		||||
   * the app-ready event. We listen very early for open-file and remember this upon startup as path to open.
 | 
			
		||||
@ -478,7 +511,7 @@ function registerStartupListeners() {
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * macOS: react to open-url requests.
 | 
			
		||||
   * macOS: react to open-url requests (including Deep Link on second instances)
 | 
			
		||||
   */
 | 
			
		||||
  const openUrls: string[] = []
 | 
			
		||||
  // @ts-ignore
 | 
			
		||||
 | 
			
		||||
@ -185,6 +185,7 @@ contextBridge.exposeInMainWorld('electron', {
 | 
			
		||||
        'VITE_KC_API_WS_MODELING_URL',
 | 
			
		||||
        'VITE_KC_API_BASE_URL',
 | 
			
		||||
        'VITE_KC_SITE_BASE_URL',
 | 
			
		||||
        'VITE_KC_SITE_APP_URL',
 | 
			
		||||
        'VITE_KC_SKIP_AUTH',
 | 
			
		||||
        'VITE_KC_CONNECTION_TIMEOUT_MS',
 | 
			
		||||
        'VITE_KC_DEV_TOKEN',
 | 
			
		||||
 | 
			
		||||
@ -259,6 +259,9 @@ pub struct ModelingSettings {
 | 
			
		||||
    /// The projection mode the camera should use while modeling.
 | 
			
		||||
    #[serde(default, alias = "cameraProjection", skip_serializing_if = "is_default")]
 | 
			
		||||
    pub camera_projection: CameraProjectionType,
 | 
			
		||||
    /// The methodology the camera should use to orbit around the model.
 | 
			
		||||
    #[serde(default, alias = "cameraOrbit", skip_serializing_if = "is_default")]
 | 
			
		||||
    pub camera_orbit: CameraOrbitType,
 | 
			
		||||
    /// The controls for how to navigate the 3D view.
 | 
			
		||||
    #[serde(default, alias = "mouseControls", skip_serializing_if = "is_default")]
 | 
			
		||||
    pub mouse_controls: MouseControlType,
 | 
			
		||||
@ -415,6 +418,21 @@ pub enum CameraProjectionType {
 | 
			
		||||
    Orthographic,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// The types of camera orbit methods.
 | 
			
		||||
#[derive(Debug, Default, Eq, PartialEq, Clone, Deserialize, Serialize, JsonSchema, ts_rs::TS, Display, FromStr)]
 | 
			
		||||
#[ts(export)]
 | 
			
		||||
#[serde(rename_all = "snake_case")]
 | 
			
		||||
#[display(style = "snake_case")]
 | 
			
		||||
pub enum CameraOrbitType {
 | 
			
		||||
    /// Orbit using a spherical camera movement.
 | 
			
		||||
    #[default]
 | 
			
		||||
    #[display("spherical")]
 | 
			
		||||
    Spherical,
 | 
			
		||||
    /// Orbit using a trackball camera movement.
 | 
			
		||||
    #[display("trackball")]
 | 
			
		||||
    Trackball,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Settings that affect the behavior of the KCL text editor.
 | 
			
		||||
#[derive(Debug, Default, Clone, Deserialize, Serialize, JsonSchema, ts_rs::TS, PartialEq, Eq, Validate)]
 | 
			
		||||
#[serde(rename_all = "snake_case")]
 | 
			
		||||
@ -543,6 +561,8 @@ mod tests {
 | 
			
		||||
    use pretty_assertions::assert_eq;
 | 
			
		||||
    use validator::Validate;
 | 
			
		||||
 | 
			
		||||
    use crate::settings::types::CameraOrbitType;
 | 
			
		||||
 | 
			
		||||
    use super::{
 | 
			
		||||
        AppColor, AppSettings, AppTheme, AppearanceSettings, CameraProjectionType, CommandBarSettings, Configuration,
 | 
			
		||||
        ModelingSettings, OnboardingStatus, ProjectSettings, Settings, TextEditorSettings, UnitLength,
 | 
			
		||||
@ -594,6 +614,7 @@ textWrapping = true
 | 
			
		||||
                    modeling: ModelingSettings {
 | 
			
		||||
                        base_unit: UnitLength::In,
 | 
			
		||||
                        camera_projection: CameraProjectionType::Orthographic,
 | 
			
		||||
                        camera_orbit: Default::default(),
 | 
			
		||||
                        mouse_controls: Default::default(),
 | 
			
		||||
                        highlight_edges: Default::default(),
 | 
			
		||||
                        show_debug_panel: true,
 | 
			
		||||
@ -656,6 +677,7 @@ includeSettings = false
 | 
			
		||||
                    modeling: ModelingSettings {
 | 
			
		||||
                        base_unit: UnitLength::Yd,
 | 
			
		||||
                        camera_projection: Default::default(),
 | 
			
		||||
                        camera_orbit: Default::default(),
 | 
			
		||||
                        mouse_controls: Default::default(),
 | 
			
		||||
                        highlight_edges: Default::default(),
 | 
			
		||||
                        show_debug_panel: true,
 | 
			
		||||
@ -723,6 +745,7 @@ defaultProjectName = "projects-$nnn"
 | 
			
		||||
                    modeling: ModelingSettings {
 | 
			
		||||
                        base_unit: UnitLength::Yd,
 | 
			
		||||
                        camera_projection: Default::default(),
 | 
			
		||||
                        camera_orbit: CameraOrbitType::Spherical,
 | 
			
		||||
                        mouse_controls: Default::default(),
 | 
			
		||||
                        highlight_edges: Default::default(),
 | 
			
		||||
                        show_debug_panel: true,
 | 
			
		||||
@ -802,6 +825,7 @@ projectDirectory = "/Users/macinatormax/Documents/kittycad-modeling-projects""#;
 | 
			
		||||
                    modeling: ModelingSettings {
 | 
			
		||||
                        base_unit: UnitLength::Mm,
 | 
			
		||||
                        camera_projection: Default::default(),
 | 
			
		||||
                        camera_orbit: Default::default(),
 | 
			
		||||
                        mouse_controls: Default::default(),
 | 
			
		||||
                        highlight_edges: true.into(),
 | 
			
		||||
                        show_debug_panel: false,
 | 
			
		||||
 | 
			
		||||
@ -129,6 +129,7 @@ includeSettings = false
 | 
			
		||||
                    modeling: ModelingSettings {
 | 
			
		||||
                        base_unit: UnitLength::Yd,
 | 
			
		||||
                        camera_projection: Default::default(),
 | 
			
		||||
                        camera_orbit: Default::default(),
 | 
			
		||||
                        mouse_controls: Default::default(),
 | 
			
		||||
                        highlight_edges: Default::default(),
 | 
			
		||||
                        show_debug_panel: true,
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user