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